Merge branch 'x86/asm' into x86/apic, to resolve a conflict
authorIngo Molnar <mingo@kernel.org>
Mon, 11 May 2015 14:05:09 +0000 (16:05 +0200)
committerIngo Molnar <mingo@kernel.org>
Mon, 11 May 2015 14:05:09 +0000 (16:05 +0200)
Conflicts:
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/apic/vector.c

Signed-off-by: Ingo Molnar <mingo@kernel.org>
2901 files changed:
CREDITS
Documentation/ABI/testing/sysfs-class-mtd
Documentation/ABI/testing/sysfs-driver-toshiba_acpi
Documentation/ABI/testing/sysfs-platform-dell-laptop [new file with mode: 0644]
Documentation/DocBook/media/v4l/compat.xml
Documentation/DocBook/media/v4l/media-ioc-enum-entities.xml
Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml
Documentation/DocBook/media/v4l/pixfmt-sgrbg8.xml
Documentation/DocBook/media/v4l/pixfmt-srggb10p.xml
Documentation/DocBook/media/v4l/pixfmt-yuv420m.xml
Documentation/DocBook/media/v4l/pixfmt.xml
Documentation/DocBook/media/v4l/subdev-formats.xml
Documentation/DocBook/media/v4l/v4l2.xml
Documentation/DocBook/media/v4l/vidioc-cropcap.xml
Documentation/DocBook/media/v4l/vidioc-dqevent.xml
Documentation/DocBook/media/v4l/vidioc-g-crop.xml
Documentation/DocBook/media/v4l/vidioc-g-dv-timings.xml
Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml
Documentation/DocBook/media/v4l/vidioc-g-selection.xml
Documentation/DocBook/media/v4l/vidioc-querycap.xml
Documentation/DocBook/media/v4l/vidioc-queryctrl.xml
Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-interval.xml
Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-size.xml
Documentation/DocBook/media/v4l/vidioc-subdev-enum-mbus-code.xml
Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml
Documentation/IPMI.txt
Documentation/Makefile
Documentation/acpi/enumeration.txt
Documentation/acpi/gpio-properties.txt
Documentation/arm/00-INDEX
Documentation/arm/Makefile [deleted file]
Documentation/arm/Marvell/README
Documentation/arm/SH-Mobile/Makefile [deleted file]
Documentation/arm/SH-Mobile/vrl4.c [deleted file]
Documentation/arm/SH-Mobile/zboot-rom-mmcif.txt [deleted file]
Documentation/arm/SH-Mobile/zboot-rom-sdhi.txt [deleted file]
Documentation/arm/msm/gpiomux.txt [deleted file]
Documentation/arm64/acpi_object_usage.txt [new file with mode: 0644]
Documentation/arm64/arm-acpi.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arc/pct.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arc/pmu.txt [deleted file]
Documentation/devicetree/bindings/arm/al,alpine.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/altera.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/amlogic.txt
Documentation/devicetree/bindings/arm/arch_timer.txt
Documentation/devicetree/bindings/arm/armada-39x.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/atmel-at91.txt
Documentation/devicetree/bindings/arm/cci.txt
Documentation/devicetree/bindings/arm/coresight.txt
Documentation/devicetree/bindings/arm/cpu-enable-method/al,alpine-smp [new file with mode: 0644]
Documentation/devicetree/bindings/arm/cpus.txt
Documentation/devicetree/bindings/arm/exynos/power_domain.txt
Documentation/devicetree/bindings/arm/geniatech.txt [deleted file]
Documentation/devicetree/bindings/arm/gic.txt
Documentation/devicetree/bindings/arm/marvell,kirkwood.txt
Documentation/devicetree/bindings/arm/msm/qcom,idle-state.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/msm/qcom,saw2.txt
Documentation/devicetree/bindings/arm/msm/timer.txt
Documentation/devicetree/bindings/arm/omap/ctrl.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/omap/l4.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/omap/prcm.txt
Documentation/devicetree/bindings/arm/rockchip.txt
Documentation/devicetree/bindings/arm/shmobile.txt
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra30-actmon.txt [new file with mode: 0644]
Documentation/devicetree/bindings/bus/omap-ocp2scp.txt
Documentation/devicetree/bindings/bus/renesas,bsc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/bus/simple-pm-bus.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/exynos3250-clock.txt
Documentation/devicetree/bindings/clock/exynos5433-clock.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/fujitsu,mb86s70-crg11.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/mvebu-core-clock.txt
Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt
Documentation/devicetree/bindings/clock/pwm-clock.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/qcom,gcc.txt
Documentation/devicetree/bindings/clock/renesas,r8a7778-cpg-clocks.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/sunxi.txt
Documentation/devicetree/bindings/common-properties.txt [new file with mode: 0644]
Documentation/devicetree/bindings/cris/axis.txt [new file with mode: 0644]
Documentation/devicetree/bindings/cris/boards.txt [new file with mode: 0644]
Documentation/devicetree/bindings/cris/interrupts.txt [new file with mode: 0644]
Documentation/devicetree/bindings/dma/apm-xgene-dma.txt [new file with mode: 0644]
Documentation/devicetree/bindings/dma/jz4780-dma.txt [new file with mode: 0644]
Documentation/devicetree/bindings/dma/qcom_bam_dma.txt
Documentation/devicetree/bindings/dma/rcar-audmapp.txt [deleted file]
Documentation/devicetree/bindings/dma/renesas,usb-dmac.txt [new file with mode: 0644]
Documentation/devicetree/bindings/extcon/extcon-usb-gpio.txt [new file with mode: 0644]
Documentation/devicetree/bindings/i2c/trivial-devices.txt
Documentation/devicetree/bindings/media/exynos-jpeg-codec.txt
Documentation/devicetree/bindings/media/i2c/mt9v032.txt [new file with mode: 0644]
Documentation/devicetree/bindings/media/i2c/ov2640.txt [new file with mode: 0644]
Documentation/devicetree/bindings/media/i2c/ov2659.txt [new file with mode: 0644]
Documentation/devicetree/bindings/media/ti,omap3isp.txt [new file with mode: 0644]
Documentation/devicetree/bindings/media/video-interfaces.txt
Documentation/devicetree/bindings/media/xilinx/video.txt [new file with mode: 0644]
Documentation/devicetree/bindings/media/xilinx/xlnx,v-tc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/media/xilinx/xlnx,v-tpg.txt [new file with mode: 0644]
Documentation/devicetree/bindings/media/xilinx/xlnx,video.txt [new file with mode: 0644]
Documentation/devicetree/bindings/memory-controllers/ingenic,jz4780-nemc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/qcom,tcsr.txt [new file with mode: 0644]
Documentation/devicetree/bindings/misc/lis302.txt
Documentation/devicetree/bindings/mtd/m25p80.txt
Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
Documentation/devicetree/bindings/mtd/sunxi-nand.txt
Documentation/devicetree/bindings/net/wireless/ti,wlcore.txt [new file with mode: 0644]
Documentation/devicetree/bindings/power/fsl,imx-gpc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/power/renesas,sysc-rmobile.txt
Documentation/devicetree/bindings/pwm/imx-pwm.txt
Documentation/devicetree/bindings/rtc/abracon,abx80x.txt [new file with mode: 0644]
Documentation/devicetree/bindings/serial/atmel-usart.txt
Documentation/devicetree/bindings/serial/omap_serial.txt
Documentation/devicetree/bindings/soc/mediatek/pwrap.txt [new file with mode: 0644]
Documentation/devicetree/bindings/soc/qcom/qcom,gsbi.txt
Documentation/devicetree/bindings/sound/omap-twl4030.txt
Documentation/devicetree/bindings/spmi/qcom,spmi-pmic-arb.txt
Documentation/devicetree/bindings/vendor-prefixes.txt
Documentation/devicetree/bindings/video/atmel,lcdc.txt
Documentation/dma-buf-sharing.txt
Documentation/driver-model/devres.txt
Documentation/filesystems/nfs/nfs-rdma.txt
Documentation/filesystems/xfs.txt
Documentation/input/alps.txt
Documentation/ioctl/ioctl-number.txt
Documentation/kasan.txt
Documentation/kernel-parameters.txt
Documentation/laptops/thinkpad-acpi.txt
Documentation/md-cluster.txt [new file with mode: 0644]
Documentation/module-signing.txt
Documentation/networking/mpls-sysctl.txt
Documentation/networking/scaling.txt
Documentation/powerpc/transactional_memory.txt
Documentation/target/tcm_mod_builder.py
Documentation/target/tcmu-design.txt
Documentation/trace/coresight.txt
Documentation/video4linux/v4l2-controls.txt
Documentation/video4linux/v4l2-framework.txt
Documentation/video4linux/vivid.txt
Documentation/virtual/kvm/api.txt
MAINTAINERS
Makefile
arch/arc/boot/dts/angel4.dts
arch/arc/configs/nsimosci_defconfig
arch/arc/include/asm/arcregs.h
arch/arc/include/asm/bitops.h
arch/arc/include/asm/perf_event.h
arch/arc/kernel/perf_event.c
arch/arc/kernel/process.c
arch/arc/kernel/setup.c
arch/arc/kernel/traps.c
arch/arc/mm/init.c
arch/arm/Kconfig
arch/arm/Kconfig.debug
arch/arm/Makefile
arch/arm/boot/compressed/Makefile
arch/arm/boot/compressed/head-shmobile.S
arch/arm/boot/compressed/mmcif-sh7372.c [deleted file]
arch/arm/boot/compressed/sdhi-sh7372.c [deleted file]
arch/arm/boot/compressed/sdhi-shmobile.c [deleted file]
arch/arm/boot/compressed/sdhi-shmobile.h [deleted file]
arch/arm/boot/dts/Makefile
arch/arm/boot/dts/alpine-db.dts [new file with mode: 0644]
arch/arm/boot/dts/alpine.dtsi [new file with mode: 0644]
arch/arm/boot/dts/am335x-chiliboard.dts [new file with mode: 0644]
arch/arm/boot/dts/am335x-chilisom.dtsi [new file with mode: 0644]
arch/arm/boot/dts/am335x-evmsk.dts
arch/arm/boot/dts/am335x-nano.dts
arch/arm/boot/dts/am33xx-clocks.dtsi
arch/arm/boot/dts/am33xx.dtsi
arch/arm/boot/dts/am3517.dtsi
arch/arm/boot/dts/am35xx-clocks.dtsi
arch/arm/boot/dts/am4372.dtsi
arch/arm/boot/dts/am437x-idk-evm.dts
arch/arm/boot/dts/am43x-epos-evm.dts
arch/arm/boot/dts/am43xx-clocks.dtsi
arch/arm/boot/dts/am57xx-beagle-x15.dts
arch/arm/boot/dts/armada-370-db.dts
arch/arm/boot/dts/armada-370-mirabox.dts
arch/arm/boot/dts/armada-370-netgear-rn102.dts
arch/arm/boot/dts/armada-370-netgear-rn104.dts
arch/arm/boot/dts/armada-370-rd.dts
arch/arm/boot/dts/armada-370-synology-ds213j.dts
arch/arm/boot/dts/armada-370-xp.dtsi
arch/arm/boot/dts/armada-370.dtsi
arch/arm/boot/dts/armada-375-db.dts
arch/arm/boot/dts/armada-375.dtsi
arch/arm/boot/dts/armada-385-db-ap.dts
arch/arm/boot/dts/armada-388-db.dts
arch/arm/boot/dts/armada-388-gp.dts
arch/arm/boot/dts/armada-388-rd.dts
arch/arm/boot/dts/armada-38x.dtsi
arch/arm/boot/dts/armada-390.dtsi [new file with mode: 0644]
arch/arm/boot/dts/armada-398-db.dts [new file with mode: 0644]
arch/arm/boot/dts/armada-398.dtsi [new file with mode: 0644]
arch/arm/boot/dts/armada-39x.dtsi [new file with mode: 0644]
arch/arm/boot/dts/armada-xp-axpwifiap.dts
arch/arm/boot/dts/armada-xp-db.dts
arch/arm/boot/dts/armada-xp-gp.dts
arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts
arch/arm/boot/dts/armada-xp-linksys-mamba.dts [new file with mode: 0644]
arch/arm/boot/dts/armada-xp-matrix.dts
arch/arm/boot/dts/armada-xp-mv78260.dtsi
arch/arm/boot/dts/armada-xp-mv78460.dtsi
arch/arm/boot/dts/armada-xp-netgear-rn2120.dts
arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts
arch/arm/boot/dts/armada-xp-synology-ds414.dts
arch/arm/boot/dts/armada-xp.dtsi
arch/arm/boot/dts/at91-sama5d3_xplained.dts
arch/arm/boot/dts/at91-sama5d4_xplained.dts [new file with mode: 0644]
arch/arm/boot/dts/at91-sama5d4ek.dts
arch/arm/boot/dts/at91rm9200.dtsi
arch/arm/boot/dts/at91sam9260.dtsi
arch/arm/boot/dts/at91sam9261.dtsi
arch/arm/boot/dts/at91sam9263.dtsi
arch/arm/boot/dts/at91sam9g25.dtsi
arch/arm/boot/dts/at91sam9g25ek.dts
arch/arm/boot/dts/at91sam9g45.dtsi
arch/arm/boot/dts/at91sam9n12.dtsi
arch/arm/boot/dts/at91sam9n12ek.dts
arch/arm/boot/dts/at91sam9rl.dtsi
arch/arm/boot/dts/at91sam9x5.dtsi
arch/arm/boot/dts/at91sam9x5_isi.dtsi
arch/arm/boot/dts/at91sam9x5cm.dtsi
arch/arm/boot/dts/at91sam9x5ek.dtsi
arch/arm/boot/dts/bcm-cygnus.dtsi
arch/arm/boot/dts/bcm4708-netgear-r6250.dts
arch/arm/boot/dts/bcm4709-netgear-r8000.dts [new file with mode: 0644]
arch/arm/boot/dts/bcm7445.dtsi
arch/arm/boot/dts/bcm911360_entphn.dts
arch/arm/boot/dts/bcm958300k.dts
arch/arm/boot/dts/bcm958305k.dts [new file with mode: 0644]
arch/arm/boot/dts/dm8168-evm.dts
arch/arm/boot/dts/dm816x.dtsi
arch/arm/boot/dts/dove.dtsi
arch/arm/boot/dts/dra7-evm.dts
arch/arm/boot/dts/dra7.dtsi
arch/arm/boot/dts/dra72-evm.dts
arch/arm/boot/dts/dra72x.dtsi
arch/arm/boot/dts/dra74x.dtsi
arch/arm/boot/dts/dra7xx-clocks.dtsi
arch/arm/boot/dts/emev2-kzm9d.dts
arch/arm/boot/dts/emev2.dtsi
arch/arm/boot/dts/exynos3250.dtsi
arch/arm/boot/dts/exynos4412-odroid-common.dtsi
arch/arm/boot/dts/exynos5250-snow.dts
arch/arm/boot/dts/exynos5250-spring.dts
arch/arm/boot/dts/exynos5250.dtsi
arch/arm/boot/dts/exynos5420-arndale-octa.dts
arch/arm/boot/dts/exynos5420-peach-pit.dts
arch/arm/boot/dts/exynos5420-pinctrl.dtsi
arch/arm/boot/dts/exynos5420-smdk5420.dts
arch/arm/boot/dts/exynos5420.dtsi
arch/arm/boot/dts/exynos5422-odroidxu3.dts
arch/arm/boot/dts/exynos5800-peach-pi.dts
arch/arm/boot/dts/hip04.dtsi
arch/arm/boot/dts/imx25-pdk.dts
arch/arm/boot/dts/imx25-pinfunc.h
arch/arm/boot/dts/imx27.dtsi
arch/arm/boot/dts/imx28-apf28.dts
arch/arm/boot/dts/imx28-apf28dev.dts
arch/arm/boot/dts/imx28.dtsi
arch/arm/boot/dts/imx35.dtsi
arch/arm/boot/dts/imx50.dtsi
arch/arm/boot/dts/imx51.dtsi
arch/arm/boot/dts/imx53.dtsi
arch/arm/boot/dts/imx6dl-aristainetos_4.dts
arch/arm/boot/dts/imx6dl-aristainetos_7.dts
arch/arm/boot/dts/imx6dl-cubox-i.dts
arch/arm/boot/dts/imx6dl-hummingboard.dts
arch/arm/boot/dts/imx6q-cubox-i.dts
arch/arm/boot/dts/imx6q-hummingboard.dts
arch/arm/boot/dts/imx6q.dtsi
arch/arm/boot/dts/imx6qdl-cubox-i.dtsi
arch/arm/boot/dts/imx6qdl-hummingboard.dtsi
arch/arm/boot/dts/imx6qdl-microsom-ar8035.dtsi
arch/arm/boot/dts/imx6qdl-microsom.dtsi
arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
arch/arm/boot/dts/imx6qdl.dtsi
arch/arm/boot/dts/imx6sl-warp.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6sl.dtsi
arch/arm/boot/dts/imx6sx-sdb-reva.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6sx-sdb.dts
arch/arm/boot/dts/imx6sx-sdb.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx6sx.dtsi
arch/arm/boot/dts/kirkwood-nas2big.dts [new file with mode: 0644]
arch/arm/boot/dts/kirkwood-net2big.dts
arch/arm/boot/dts/meson.dtsi
arch/arm/boot/dts/meson6-atv1200.dts
arch/arm/boot/dts/meson8-minix-neo-x8.dts [new file with mode: 0644]
arch/arm/boot/dts/meson8.dtsi
arch/arm/boot/dts/mt6589.dtsi
arch/arm/boot/dts/nspire-classic.dtsi
arch/arm/boot/dts/nspire-cx.dts
arch/arm/boot/dts/nspire.dtsi
arch/arm/boot/dts/omap2420.dtsi
arch/arm/boot/dts/omap2430-clocks.dtsi
arch/arm/boot/dts/omap2430.dtsi
arch/arm/boot/dts/omap24xx-clocks.dtsi
arch/arm/boot/dts/omap3-beagle-xm.dts
arch/arm/boot/dts/omap3-beagle.dts
arch/arm/boot/dts/omap3-cm-t3517.dts
arch/arm/boot/dts/omap3-cm-t3730.dts
arch/arm/boot/dts/omap3-cm-t3x30.dtsi
arch/arm/boot/dts/omap3-devkit8000.dts
arch/arm/boot/dts/omap3-evm-common.dtsi
arch/arm/boot/dts/omap3-gta04.dtsi
arch/arm/boot/dts/omap3-igep.dtsi
arch/arm/boot/dts/omap3-igep0020-rev-f.dts
arch/arm/boot/dts/omap3-igep0030-rev-g.dts
arch/arm/boot/dts/omap3-lilly-a83x.dtsi
arch/arm/boot/dts/omap3-n9.dts
arch/arm/boot/dts/omap3-n900.dts
arch/arm/boot/dts/omap3-n950-n9.dtsi
arch/arm/boot/dts/omap3-n950.dts
arch/arm/boot/dts/omap3-overo-base.dtsi
arch/arm/boot/dts/omap3-pandora-1ghz.dts [new file with mode: 0644]
arch/arm/boot/dts/omap3-pandora-600mhz.dts [new file with mode: 0644]
arch/arm/boot/dts/omap3-pandora-common.dtsi [new file with mode: 0644]
arch/arm/boot/dts/omap3-tao3530.dtsi
arch/arm/boot/dts/omap3-zoom3.dts
arch/arm/boot/dts/omap3.dtsi
arch/arm/boot/dts/omap34xx-hs.dtsi [deleted file]
arch/arm/boot/dts/omap34xx.dtsi
arch/arm/boot/dts/omap36xx-hs.dtsi [deleted file]
arch/arm/boot/dts/omap36xx.dtsi
arch/arm/boot/dts/omap3xxx-clocks.dtsi
arch/arm/boot/dts/omap4-cpu-thermal.dtsi
arch/arm/boot/dts/omap4-panda-common.dtsi
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/omap5.dtsi
arch/arm/boot/dts/qcom-apq8064.dtsi
arch/arm/boot/dts/qcom-apq8074-dragonboard.dts
arch/arm/boot/dts/qcom-apq8084-ifc6540.dts
arch/arm/boot/dts/qcom-apq8084-mtp.dts
arch/arm/boot/dts/qcom-apq8084.dtsi
arch/arm/boot/dts/qcom-ipq8064.dtsi
arch/arm/boot/dts/qcom-msm8660.dtsi
arch/arm/boot/dts/qcom-msm8960.dtsi
arch/arm/boot/dts/qcom-msm8974-sony-xperia-honami.dts
arch/arm/boot/dts/qcom-msm8974.dtsi
arch/arm/boot/dts/qcom-pm8841.dtsi [new file with mode: 0644]
arch/arm/boot/dts/qcom-pm8941.dtsi [new file with mode: 0644]
arch/arm/boot/dts/qcom-pma8084.dtsi [new file with mode: 0644]
arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts [deleted file]
arch/arm/boot/dts/r8a73a4-ape6evm.dts
arch/arm/boot/dts/r8a73a4.dtsi
arch/arm/boot/dts/r8a7740.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/r8a7790-lager.dts
arch/arm/boot/dts/r8a7790.dtsi
arch/arm/boot/dts/r8a7791-henninger.dts
arch/arm/boot/dts/r8a7791-koelsch.dts
arch/arm/boot/dts/r8a7791.dtsi
arch/arm/boot/dts/r8a7794-alt.dts
arch/arm/boot/dts/r8a7794.dtsi
arch/arm/boot/dts/rk3188-radxarock.dts
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-firefly.dtsi
arch/arm/boot/dts/rk3288-popmetal.dts [new file with mode: 0644]
arch/arm/boot/dts/rk3288.dtsi
arch/arm/boot/dts/sama5d3.dtsi
arch/arm/boot/dts/sama5d35ek.dts
arch/arm/boot/dts/sama5d3_can.dtsi
arch/arm/boot/dts/sama5d3_emac.dtsi
arch/arm/boot/dts/sama5d3_gmac.dtsi
arch/arm/boot/dts/sama5d3_lcd.dtsi
arch/arm/boot/dts/sama5d3_mci2.dtsi
arch/arm/boot/dts/sama5d3_tcb1.dtsi
arch/arm/boot/dts/sama5d3_uart.dtsi
arch/arm/boot/dts/sama5d4.dtsi
arch/arm/boot/dts/sh7372-mackerel.dts [deleted file]
arch/arm/boot/dts/sh7372.dtsi [deleted file]
arch/arm/boot/dts/sh73a0-kzm9g-reference.dts [deleted file]
arch/arm/boot/dts/sh73a0-kzm9g.dts
arch/arm/boot/dts/sh73a0.dtsi
arch/arm/boot/dts/tegra124-jetson-tk1-emc.dtsi [new file with mode: 0644]
arch/arm/boot/dts/tegra124-jetson-tk1.dts
arch/arm/boot/dts/tegra124-nyan-big-emc.dtsi [new file with mode: 0644]
arch/arm/boot/dts/tegra124-nyan-big.dts
arch/arm/boot/dts/tegra124-nyan-blaze-emc.dtsi [new file with mode: 0644]
arch/arm/boot/dts/tegra124-nyan-blaze.dts [new file with mode: 0644]
arch/arm/boot/dts/tegra124-nyan.dtsi [new file with mode: 0644]
arch/arm/boot/dts/tegra124.dtsi
arch/arm/boot/dts/tegra30-beaver.dts
arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
arch/arm/boot/dts/vf-colibri-eval-v3.dtsi
arch/arm/boot/dts/vf-colibri.dtsi
arch/arm/boot/dts/vf500.dtsi
arch/arm/boot/dts/vfxxx.dtsi
arch/arm/common/mcpm_entry.c
arch/arm/configs/ape6evm_defconfig [deleted file]
arch/arm/configs/at91_dt_defconfig
arch/arm/configs/exynos_defconfig
arch/arm/configs/imx_v4_v5_defconfig
arch/arm/configs/imx_v6_v7_defconfig
arch/arm/configs/mackerel_defconfig [deleted file]
arch/arm/configs/msm_defconfig [deleted file]
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/omap1_defconfig
arch/arm/configs/omap2plus_defconfig
arch/arm/configs/qcom_defconfig
arch/arm/configs/shmobile_defconfig
arch/arm/configs/sunxi_defconfig
arch/arm/include/asm/arm-cci.h [new file with mode: 0644]
arch/arm/include/asm/mcpm.h
arch/arm/include/asm/xen/page.h
arch/arm/include/debug/msm.S
arch/arm/include/uapi/asm/kvm.h
arch/arm/kernel/head-nommu.S
arch/arm/kvm/arm.c
arch/arm/mach-alpine/Kconfig [new file with mode: 0644]
arch/arm/mach-alpine/Makefile [new file with mode: 0644]
arch/arm/mach-alpine/alpine_cpu_pm.c [new file with mode: 0644]
arch/arm/mach-alpine/alpine_cpu_pm.h [new file with mode: 0644]
arch/arm/mach-alpine/alpine_cpu_resume.h [new file with mode: 0644]
arch/arm/mach-alpine/alpine_machine.c [new file with mode: 0644]
arch/arm/mach-alpine/platsmp.c [new file with mode: 0644]
arch/arm/mach-at91/Kconfig
arch/arm/mach-at91/Makefile
arch/arm/mach-at91/at91rm9200.c
arch/arm/mach-at91/at91rm9200_time.c [deleted file]
arch/arm/mach-at91/at91sam9.c
arch/arm/mach-at91/generic.h
arch/arm/mach-at91/include/mach/at91_dbgu.h [deleted file]
arch/arm/mach-at91/include/mach/at91_matrix.h [deleted file]
arch/arm/mach-at91/include/mach/at91_ramc.h
arch/arm/mach-at91/include/mach/at91_st.h [deleted file]
arch/arm/mach-at91/include/mach/at91rm9200.h [deleted file]
arch/arm/mach-at91/include/mach/at91sam9260.h [deleted file]
arch/arm/mach-at91/include/mach/at91sam9260_matrix.h [deleted file]
arch/arm/mach-at91/include/mach/at91sam9261.h [deleted file]
arch/arm/mach-at91/include/mach/at91sam9261_matrix.h [deleted file]
arch/arm/mach-at91/include/mach/at91sam9263.h [deleted file]
arch/arm/mach-at91/include/mach/at91sam9263_matrix.h [deleted file]
arch/arm/mach-at91/include/mach/at91sam9_smc.h
arch/arm/mach-at91/include/mach/at91sam9g45.h [deleted file]
arch/arm/mach-at91/include/mach/at91sam9g45_matrix.h [deleted file]
arch/arm/mach-at91/include/mach/at91sam9n12.h [deleted file]
arch/arm/mach-at91/include/mach/at91sam9n12_matrix.h [deleted file]
arch/arm/mach-at91/include/mach/at91sam9rl.h [deleted file]
arch/arm/mach-at91/include/mach/at91sam9rl_matrix.h [deleted file]
arch/arm/mach-at91/include/mach/at91sam9x5.h [deleted file]
arch/arm/mach-at91/include/mach/at91sam9x5_matrix.h [deleted file]
arch/arm/mach-at91/include/mach/cpu.h [deleted file]
arch/arm/mach-at91/include/mach/hardware.h [deleted file]
arch/arm/mach-at91/include/mach/io.h [deleted file]
arch/arm/mach-at91/include/mach/sama5d3.h [deleted file]
arch/arm/mach-at91/include/mach/sama5d4.h [deleted file]
arch/arm/mach-at91/include/mach/uncompress.h [deleted file]
arch/arm/mach-at91/pm.c
arch/arm/mach-at91/pm.h
arch/arm/mach-at91/pm_slowclock.S [deleted file]
arch/arm/mach-at91/pm_suspend.S [new file with mode: 0644]
arch/arm/mach-at91/sama5.c
arch/arm/mach-at91/setup.c [deleted file]
arch/arm/mach-at91/soc.c [new file with mode: 0644]
arch/arm/mach-at91/soc.h [new file with mode: 0644]
arch/arm/mach-bcm/bcm_cygnus.c
arch/arm/mach-cns3xxx/pm.c
arch/arm/mach-davinci/Kconfig
arch/arm/mach-davinci/asp.h
arch/arm/mach-davinci/board-da850-evm.c
arch/arm/mach-davinci/devices-da8xx.c
arch/arm/mach-davinci/dm646x.c
arch/arm/mach-davinci/include/mach/irqs.h
arch/arm/mach-exynos/Kconfig
arch/arm/mach-exynos/common.h
arch/arm/mach-exynos/exynos.c
arch/arm/mach-exynos/firmware.c
arch/arm/mach-exynos/mcpm-exynos.c
arch/arm/mach-exynos/platsmp.c
arch/arm/mach-exynos/pm.c
arch/arm/mach-exynos/pm_domains.c
arch/arm/mach-exynos/regs-pmu.h
arch/arm/mach-exynos/smc.h
arch/arm/mach-exynos/suspend.c
arch/arm/mach-imx/Kconfig
arch/arm/mach-imx/Makefile
arch/arm/mach-imx/clk-imx25.c
arch/arm/mach-imx/clk-imx6q.c
arch/arm/mach-imx/common.h
arch/arm/mach-imx/cpu-imx25.c
arch/arm/mach-imx/devices-imx25.h [deleted file]
arch/arm/mach-imx/devices/Kconfig
arch/arm/mach-imx/devices/Makefile
arch/arm/mach-imx/devices/platform-fec.c
arch/arm/mach-imx/devices/platform-fsl-usb2-udc.c
arch/arm/mach-imx/devices/platform-imx-fb.c
arch/arm/mach-imx/devices/platform-imx-i2c.c
arch/arm/mach-imx/devices/platform-imx-keypad.c
arch/arm/mach-imx/devices/platform-imx-ssi.c
arch/arm/mach-imx/devices/platform-imx-uart.c
arch/arm/mach-imx/devices/platform-imx2-wdt.c
arch/arm/mach-imx/devices/platform-imxdi_rtc.c [deleted file]
arch/arm/mach-imx/devices/platform-mx2-camera.c
arch/arm/mach-imx/devices/platform-mxc-ehci.c
arch/arm/mach-imx/devices/platform-mxc_nand.c
arch/arm/mach-imx/devices/platform-spi_imx.c
arch/arm/mach-imx/ehci-imx25.c [deleted file]
arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c [deleted file]
arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
arch/arm/mach-imx/gpc.c
arch/arm/mach-imx/hardware.h
arch/arm/mach-imx/imx25-dt.c [deleted file]
arch/arm/mach-imx/iomux-mx25.h [deleted file]
arch/arm/mach-imx/iomux-mx3.h
arch/arm/mach-imx/iomux-v3.c
arch/arm/mach-imx/iomux-v3.h
arch/arm/mach-imx/mach-cpuimx35.c
arch/arm/mach-imx/mach-eukrea_cpuimx25.c [deleted file]
arch/arm/mach-imx/mach-imx25.c [new file with mode: 0644]
arch/arm/mach-imx/mach-imx6q.c
arch/arm/mach-imx/mach-imx6sl.c
arch/arm/mach-imx/mach-imx6sx.c
arch/arm/mach-imx/mach-mx25_3ds.c [deleted file]
arch/arm/mach-imx/mach-mx35_3ds.c
arch/arm/mach-imx/mach-pcm043.c
arch/arm/mach-imx/mach-vpr200.c
arch/arm/mach-imx/mm-imx25.c [deleted file]
arch/arm/mach-imx/mx25.h [deleted file]
arch/arm/mach-imx/pm-imx6.c
arch/arm/mach-mediatek/Kconfig
arch/arm/mach-meson/Kconfig
arch/arm/mach-msm/Kconfig [deleted file]
arch/arm/mach-msm/Makefile [deleted file]
arch/arm/mach-msm/Makefile.boot [deleted file]
arch/arm/mach-msm/board-halibut.c [deleted file]
arch/arm/mach-msm/board-msm7x30.c [deleted file]
arch/arm/mach-msm/board-qsd8x50.c [deleted file]
arch/arm/mach-msm/board-sapphire.c [deleted file]
arch/arm/mach-msm/board-trout-gpio.c [deleted file]
arch/arm/mach-msm/board-trout-mmc.c [deleted file]
arch/arm/mach-msm/board-trout-panel.c [deleted file]
arch/arm/mach-msm/board-trout.c [deleted file]
arch/arm/mach-msm/board-trout.h [deleted file]
arch/arm/mach-msm/clock-pcom.c [deleted file]
arch/arm/mach-msm/clock-pcom.h [deleted file]
arch/arm/mach-msm/clock.c [deleted file]
arch/arm/mach-msm/clock.h [deleted file]
arch/arm/mach-msm/common.h [deleted file]
arch/arm/mach-msm/devices-msm7x00.c [deleted file]
arch/arm/mach-msm/devices-msm7x30.c [deleted file]
arch/arm/mach-msm/devices-qsd8x50.c [deleted file]
arch/arm/mach-msm/devices.h [deleted file]
arch/arm/mach-msm/dma.c [deleted file]
arch/arm/mach-msm/gpiomux-8x50.c [deleted file]
arch/arm/mach-msm/gpiomux-v1.h [deleted file]
arch/arm/mach-msm/gpiomux.c [deleted file]
arch/arm/mach-msm/gpiomux.h [deleted file]
arch/arm/mach-msm/include/mach/clk.h [deleted file]
arch/arm/mach-msm/include/mach/dma.h [deleted file]
arch/arm/mach-msm/include/mach/entry-macro.S [deleted file]
arch/arm/mach-msm/include/mach/hardware.h [deleted file]
arch/arm/mach-msm/include/mach/irqs-7x00.h [deleted file]
arch/arm/mach-msm/include/mach/irqs-7x30.h [deleted file]
arch/arm/mach-msm/include/mach/irqs-8x50.h [deleted file]
arch/arm/mach-msm/include/mach/irqs.h [deleted file]
arch/arm/mach-msm/include/mach/msm_gpiomux.h [deleted file]
arch/arm/mach-msm/include/mach/msm_iomap-7x00.h [deleted file]
arch/arm/mach-msm/include/mach/msm_iomap-7x30.h [deleted file]
arch/arm/mach-msm/include/mach/msm_iomap-8x50.h [deleted file]
arch/arm/mach-msm/include/mach/msm_iomap.h [deleted file]
arch/arm/mach-msm/include/mach/msm_smd.h [deleted file]
arch/arm/mach-msm/include/mach/sirc.h [deleted file]
arch/arm/mach-msm/include/mach/vreg.h [deleted file]
arch/arm/mach-msm/io.c [deleted file]
arch/arm/mach-msm/irq-vic.c [deleted file]
arch/arm/mach-msm/irq.c [deleted file]
arch/arm/mach-msm/last_radio_log.c [deleted file]
arch/arm/mach-msm/proc_comm.c [deleted file]
arch/arm/mach-msm/proc_comm.h [deleted file]
arch/arm/mach-msm/sirc.c [deleted file]
arch/arm/mach-msm/smd.c [deleted file]
arch/arm/mach-msm/smd_debug.c [deleted file]
arch/arm/mach-msm/smd_private.h [deleted file]
arch/arm/mach-msm/vreg.c [deleted file]
arch/arm/mach-mvebu/Kconfig
arch/arm/mach-mvebu/board-v7.c
arch/arm/mach-mvebu/dove.c
arch/arm/mach-mvebu/kirkwood.c
arch/arm/mach-mvebu/platsmp-a9.c
arch/arm/mach-mvebu/pmsu.c
arch/arm/mach-omap1/pm.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/board-cm-t35.c
arch/arm/mach-omap2/board-devkit8000.c [deleted file]
arch/arm/mach-omap2/board-omap3stalker.c [deleted file]
arch/arm/mach-omap2/board-omap3touchbook.c [deleted file]
arch/arm/mach-omap2/clock.c
arch/arm/mach-omap2/clock.h
arch/arm/mach-omap2/cm.h
arch/arm/mach-omap2/cm2xxx.c
arch/arm/mach-omap2/cm2xxx.h
arch/arm/mach-omap2/cm33xx.c
arch/arm/mach-omap2/cm33xx.h
arch/arm/mach-omap2/cm3xxx.c
arch/arm/mach-omap2/cm3xxx.h
arch/arm/mach-omap2/cm44xx.h
arch/arm/mach-omap2/cm_common.c
arch/arm/mach-omap2/cminst44xx.c
arch/arm/mach-omap2/common.c
arch/arm/mach-omap2/common.h
arch/arm/mach-omap2/control.c
arch/arm/mach-omap2/control.h
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/display.c
arch/arm/mach-omap2/gpmc-nand.c
arch/arm/mach-omap2/gpmc-onenand.c
arch/arm/mach-omap2/id.c
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/mux.c
arch/arm/mach-omap2/omap-secure.h
arch/arm/mach-omap2/omap34xx.h
arch/arm/mach-omap2/omap4-common.c
arch/arm/mach-omap2/omap_device.c
arch/arm/mach-omap2/omap_hwmod_43xx_data.c
arch/arm/mach-omap2/omap_hwmod_7xx_data.c
arch/arm/mach-omap2/pdata-quirks.c
arch/arm/mach-omap2/pm24xx.c
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/prcm-common.h
arch/arm/mach-omap2/prcm43xx.h
arch/arm/mach-omap2/prm.h
arch/arm/mach-omap2/prm2xxx.c
arch/arm/mach-omap2/prm2xxx.h
arch/arm/mach-omap2/prm33xx.c
arch/arm/mach-omap2/prm33xx.h
arch/arm/mach-omap2/prm3xxx.c
arch/arm/mach-omap2/prm3xxx.h
arch/arm/mach-omap2/prm44xx.c
arch/arm/mach-omap2/prm44xx.h
arch/arm/mach-omap2/prm44xx_54xx.h
arch/arm/mach-omap2/prm54xx.h
arch/arm/mach-omap2/prm7xx.h
arch/arm/mach-omap2/prm_common.c
arch/arm/mach-omap2/prminst44xx.c
arch/arm/mach-omap2/prminst44xx.h
arch/arm/mach-omap2/sleep44xx.S
arch/arm/mach-omap2/usb-tusb6010.c
arch/arm/mach-omap2/vp.h
arch/arm/mach-omap2/vp3xxx_data.c
arch/arm/mach-omap2/vp44xx_data.c
arch/arm/mach-qcom/Kconfig
arch/arm/mach-qcom/Makefile
arch/arm/mach-qcom/platsmp.c
arch/arm/mach-qcom/scm-boot.c [deleted file]
arch/arm/mach-qcom/scm-boot.h [deleted file]
arch/arm/mach-qcom/scm.c [deleted file]
arch/arm/mach-qcom/scm.h [deleted file]
arch/arm/mach-rockchip/platsmp.c
arch/arm/mach-rockchip/pm.c
arch/arm/mach-rockchip/pm.h
arch/arm/mach-s3c24xx/Kconfig
arch/arm/mach-s3c24xx/Makefile
arch/arm/mach-s3c24xx/include/mach/pm-core.h
arch/arm/mach-s3c24xx/pm-s3c2416.c
arch/arm/mach-s3c24xx/pm.c
arch/arm/mach-s3c24xx/s3c2410.c
arch/arm/mach-s3c24xx/s3c2412.c
arch/arm/mach-s3c24xx/s3c2416.c
arch/arm/mach-s3c24xx/s3c2440.c
arch/arm/mach-s3c24xx/s3c2442.c
arch/arm/mach-s3c24xx/s3c244x.c
arch/arm/mach-s3c64xx/Kconfig
arch/arm/mach-s3c64xx/Makefile
arch/arm/mach-s3c64xx/crag6410.h
arch/arm/mach-s3c64xx/mach-crag6410.c
arch/arm/mach-s3c64xx/mach-smdk6410.c
arch/arm/mach-s3c64xx/pm.c
arch/arm/mach-shmobile/Kconfig
arch/arm/mach-shmobile/Makefile
arch/arm/mach-shmobile/Makefile.boot
arch/arm/mach-shmobile/board-ape6evm-reference.c [deleted file]
arch/arm/mach-shmobile/board-ape6evm.c [deleted file]
arch/arm/mach-shmobile/board-armadillo800eva.c
arch/arm/mach-shmobile/board-bockw-reference.c
arch/arm/mach-shmobile/board-bockw.c
arch/arm/mach-shmobile/board-kzm9g-reference.c [deleted file]
arch/arm/mach-shmobile/board-kzm9g.c
arch/arm/mach-shmobile/board-mackerel.c [deleted file]
arch/arm/mach-shmobile/board-marzen.c
arch/arm/mach-shmobile/clock-r8a73a4.c [deleted file]
arch/arm/mach-shmobile/clock-sh7372.c [deleted file]
arch/arm/mach-shmobile/clock.c
arch/arm/mach-shmobile/common.h
arch/arm/mach-shmobile/cpuidle.c [deleted file]
arch/arm/mach-shmobile/entry-intc.S [deleted file]
arch/arm/mach-shmobile/include/mach/clkdev.h [deleted file]
arch/arm/mach-shmobile/include/mach/head-mackerel.txt [deleted file]
arch/arm/mach-shmobile/include/mach/mmc-mackerel.h [deleted file]
arch/arm/mach-shmobile/include/mach/mmc.h [deleted file]
arch/arm/mach-shmobile/include/mach/sdhi-sh7372.h [deleted file]
arch/arm/mach-shmobile/include/mach/sdhi.h [deleted file]
arch/arm/mach-shmobile/include/mach/system.h [deleted file]
arch/arm/mach-shmobile/include/mach/uncompress.h [deleted file]
arch/arm/mach-shmobile/include/mach/zboot.h
arch/arm/mach-shmobile/intc-sh7372.c [deleted file]
arch/arm/mach-shmobile/pm-r8a7790.c [deleted file]
arch/arm/mach-shmobile/pm-r8a7791.c [deleted file]
arch/arm/mach-shmobile/pm-rcar-gen2.c [new file with mode: 0644]
arch/arm/mach-shmobile/pm-sh7372.c [deleted file]
arch/arm/mach-shmobile/r8a73a4.h [deleted file]
arch/arm/mach-shmobile/r8a7790.h
arch/arm/mach-shmobile/r8a7791.h
arch/arm/mach-shmobile/rcar-gen2.h
arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c [new file with mode: 0644]
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-rcar-gen2.c
arch/arm/mach-shmobile/setup-sh7372.c [deleted file]
arch/arm/mach-shmobile/setup-sh73a0.c
arch/arm/mach-shmobile/sh7372.h [deleted file]
arch/arm/mach-shmobile/sh73a0.h
arch/arm/mach-shmobile/sleep-sh7372.S [deleted file]
arch/arm/mach-shmobile/smp-r8a7779.c
arch/arm/mach-shmobile/smp-r8a7790.c
arch/arm/mach-shmobile/smp-r8a7791.c
arch/arm/mach-shmobile/smp-sh73a0.c
arch/arm/mach-vexpress/Kconfig
arch/arm/mach-vexpress/dcscb.c
arch/arm/mach-vexpress/tc2_pm.c
arch/arm/mm/Kconfig
arch/arm/plat-samsung/include/plat/pm.h
arch/arm/plat-samsung/pm-debug.c
arch/arm/plat-samsung/pm.c
arch/arm/tools/mach-types
arch/arm/vdso/.gitignore
arch/arm/vdso/Makefile
arch/arm/xen/mm.c
arch/arm64/Kconfig
arch/arm64/Kconfig.debug
arch/arm64/boot/dts/Makefile
arch/arm64/boot/dts/apm/apm-storm.dtsi
arch/arm64/boot/dts/arm/juno.dts
arch/arm64/boot/dts/mediatek/mt8173-pinfunc.h [new file with mode: 0644]
arch/arm64/boot/dts/mediatek/mt8173.dtsi
arch/arm64/boot/dts/qcom/Makefile [new file with mode: 0644]
arch/arm64/boot/dts/qcom/apq8016-sbc.dts [new file with mode: 0644]
arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/qcom/msm8916-mtp.dts [new file with mode: 0644]
arch/arm64/boot/dts/qcom/msm8916-mtp.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/qcom/msm8916.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/sprd/Makefile [new file with mode: 0644]
arch/arm64/boot/dts/sprd/sc9836-openphone.dts [new file with mode: 0644]
arch/arm64/boot/dts/sprd/sc9836.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/sprd/sharkl64.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/xilinx/Makefile [new file with mode: 0644]
arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts [new file with mode: 0644]
arch/arm64/boot/dts/xilinx/zynqmp.dtsi [new file with mode: 0644]
arch/arm64/configs/defconfig
arch/arm64/include/asm/acenv.h [new file with mode: 0644]
arch/arm64/include/asm/acpi.h [new file with mode: 0644]
arch/arm64/include/asm/arm-cci.h [new file with mode: 0644]
arch/arm64/include/asm/barrier.h
arch/arm64/include/asm/cpu_ops.h
arch/arm64/include/asm/fixmap.h
arch/arm64/include/asm/irq.h
arch/arm64/include/asm/pci.h
arch/arm64/include/asm/psci.h
arch/arm64/include/asm/smp.h
arch/arm64/include/uapi/asm/kvm.h
arch/arm64/kernel/Makefile
arch/arm64/kernel/acpi.c [new file with mode: 0644]
arch/arm64/kernel/cpu_ops.c
arch/arm64/kernel/pci.c
arch/arm64/kernel/perf_event.c
arch/arm64/kernel/psci.c
arch/arm64/kernel/setup.c
arch/arm64/kernel/smp.c
arch/arm64/kernel/time.c
arch/arm64/mm/dma-mapping.c
arch/blackfin/configs/BF518F-EZBRD_defconfig
arch/blackfin/configs/BF527-TLL6527M_defconfig
arch/blackfin/configs/BF533-EZKIT_defconfig
arch/blackfin/configs/BF533-STAMP_defconfig
arch/blackfin/configs/BF537-STAMP_defconfig
arch/blackfin/configs/BF538-EZKIT_defconfig
arch/blackfin/configs/BF561-ACVILON_defconfig
arch/blackfin/configs/BF561-EZKIT-SMP_defconfig
arch/blackfin/configs/BF561-EZKIT_defconfig
arch/blackfin/configs/BF609-EZKIT_defconfig
arch/blackfin/configs/CM-BF527_defconfig
arch/blackfin/configs/CM-BF533_defconfig
arch/blackfin/configs/CM-BF537E_defconfig
arch/blackfin/configs/CM-BF537U_defconfig
arch/blackfin/configs/CM-BF548_defconfig
arch/blackfin/configs/CM-BF561_defconfig
arch/blackfin/configs/DNP5370_defconfig
arch/blackfin/configs/IP0X_defconfig
arch/blackfin/configs/PNAV-10_defconfig
arch/blackfin/configs/SRV1_defconfig
arch/blackfin/configs/TCM-BF518_defconfig
arch/blackfin/configs/TCM-BF537_defconfig
arch/blackfin/include/asm/io.h
arch/blackfin/include/uapi/asm/unistd.h
arch/blackfin/kernel/debug-mmrs.c
arch/blackfin/kernel/kgdb.c
arch/blackfin/kernel/setup.c
arch/blackfin/mach-bf527/include/mach/cdefBF525.h
arch/blackfin/mach-bf527/include/mach/defBF525.h
arch/blackfin/mach-bf548/include/mach/cdefBF542.h
arch/blackfin/mach-bf548/include/mach/cdefBF547.h
arch/blackfin/mach-bf548/include/mach/defBF542.h
arch/blackfin/mach-bf548/include/mach/defBF547.h
arch/blackfin/mach-bf609/boards/ezkit.c
arch/blackfin/mach-bf609/clock.c
arch/blackfin/mach-common/entry.S
arch/blackfin/mach-common/pm.c
arch/cris/Kconfig
arch/cris/Makefile
arch/cris/arch-v32/kernel/Makefile
arch/cris/arch-v32/kernel/entry.S
arch/cris/arch-v32/kernel/head.S
arch/cris/arch-v32/kernel/irq.c
arch/cris/arch-v32/kernel/setup.c
arch/cris/arch-v32/kernel/signal.c
arch/cris/arch-v32/kernel/smp.c [deleted file]
arch/cris/arch-v32/kernel/time.c
arch/cris/arch-v32/lib/Makefile
arch/cris/arch-v32/lib/spinlock.S [deleted file]
arch/cris/arch-v32/mm/init.c
arch/cris/arch-v32/mm/mmu.S
arch/cris/boot/dts/Makefile [new file with mode: 0644]
arch/cris/boot/dts/dev88.dts [new file with mode: 0644]
arch/cris/boot/dts/etraxfs.dtsi [new file with mode: 0644]
arch/cris/include/arch-v10/arch/atomic.h [deleted file]
arch/cris/include/arch-v10/arch/system.h
arch/cris/include/arch-v32/arch/atomic.h [deleted file]
arch/cris/include/arch-v32/arch/processor.h
arch/cris/include/arch-v32/arch/spinlock.h [deleted file]
arch/cris/include/asm/Kbuild
arch/cris/include/asm/atomic.h [deleted file]
arch/cris/include/asm/bitops.h
arch/cris/include/asm/cmpxchg.h [deleted file]
arch/cris/include/asm/device.h [deleted file]
arch/cris/include/asm/div64.h [deleted file]
arch/cris/include/asm/elf.h
arch/cris/include/asm/emergency-restart.h [deleted file]
arch/cris/include/asm/futex.h [deleted file]
arch/cris/include/asm/hardirq.h [deleted file]
arch/cris/include/asm/irq_regs.h [deleted file]
arch/cris/include/asm/kdebug.h [deleted file]
arch/cris/include/asm/kmap_types.h [deleted file]
arch/cris/include/asm/local.h [deleted file]
arch/cris/include/asm/local64.h [deleted file]
arch/cris/include/asm/percpu.h [deleted file]
arch/cris/include/asm/smp.h [deleted file]
arch/cris/include/asm/spinlock.h [deleted file]
arch/cris/include/asm/tlbflush.h
arch/cris/include/asm/topology.h [deleted file]
arch/cris/kernel/Makefile
arch/cris/kernel/devicetree.c [new file with mode: 0644]
arch/cris/kernel/ptrace.c
arch/cris/kernel/setup.c
arch/cris/kernel/time.c
arch/frv/include/asm/io.h
arch/ia64/Kconfig
arch/ia64/kernel/acpi.c
arch/ia64/kernel/perfmon.c
arch/ia64/pci/pci.c
arch/m32r/include/asm/io.h
arch/metag/kernel/process.c
arch/mips/mti-malta/malta-init.c
arch/mn10300/include/asm/io.h
arch/nios2/include/asm/Kbuild
arch/nios2/include/asm/shmparam.h [new file with mode: 0644]
arch/nios2/include/uapi/asm/ptrace.h
arch/nios2/kernel/entry.S
arch/nios2/kernel/traps.c
arch/nios2/mm/cacheflush.c
arch/parisc/include/asm/Kbuild
arch/parisc/include/asm/pgalloc.h
arch/parisc/include/asm/scatterlist.h [deleted file]
arch/parisc/kernel/pci-dma.c
arch/powerpc/include/asm/archrandom.h
arch/powerpc/include/asm/kvm_book3s.h
arch/powerpc/include/asm/kvm_book3s_64.h
arch/powerpc/include/asm/kvm_host.h
arch/powerpc/include/asm/kvm_ppc.h
arch/powerpc/include/asm/pgtable.h
arch/powerpc/include/asm/time.h
arch/powerpc/include/uapi/asm/tm.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/eeh.c
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/idle_power7.S
arch/powerpc/kernel/io-workarounds.c
arch/powerpc/kernel/time.c
arch/powerpc/kvm/Kconfig
arch/powerpc/kvm/book3s.c
arch/powerpc/kvm/book3s_64_mmu_hv.c
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_hv_builtin.c
arch/powerpc/kvm/book3s_hv_rm_mmu.c
arch/powerpc/kvm/book3s_hv_rm_xics.c
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/powerpc/kvm/book3s_pr_papr.c
arch/powerpc/kvm/book3s_xics.c
arch/powerpc/kvm/book3s_xics.h
arch/powerpc/kvm/e500_mmu_host.c
arch/powerpc/kvm/powerpc.c
arch/powerpc/mm/hash_utils_64.c
arch/powerpc/mm/hugetlbpage.c
arch/powerpc/perf/callchain.c
arch/powerpc/platforms/cell/spufs/inode.c
arch/powerpc/platforms/powernv/pci-ioda.c
arch/powerpc/platforms/powernv/rng.c
arch/powerpc/platforms/pseries/dlpar.c
arch/s390/Kconfig
arch/s390/crypto/crypt_s390.h
arch/s390/crypto/prng.c
arch/s390/hypfs/inode.c
arch/s390/include/asm/kexec.h
arch/s390/include/asm/mmu.h
arch/s390/include/asm/mmu_context.h
arch/s390/include/asm/pgalloc.h
arch/s390/include/asm/pgtable.h
arch/s390/kvm/kvm-s390.c
arch/s390/mm/hugetlbpage.c
arch/s390/mm/pgtable.c
arch/sh/boards/board-sh7757lcr.c
arch/sh/boards/mach-ap325rxa/setup.c
arch/sh/boards/mach-ecovec24/setup.c
arch/sh/boards/mach-kfr2r09/setup.c
arch/sh/boards/mach-migor/setup.c
arch/sh/boards/mach-se/7724/setup.c
arch/sparc/kernel/ldc.c
arch/sparc/kernel/perf_event.c
arch/tile/kernel/setup.c
arch/x86/Kconfig
arch/x86/Kconfig.debug
arch/x86/Makefile
arch/x86/boot/compressed/eboot.c
arch/x86/crypto/sha512-avx2-asm.S
arch/x86/ia32/ia32entry.S
arch/x86/include/asm/alternative-asm.h
arch/x86/include/asm/atomic.h
arch/x86/include/asm/atomic64_64.h
arch/x86/include/asm/cpufeature.h
arch/x86/include/asm/hw_irq.h
arch/x86/include/asm/hypervisor.h
arch/x86/include/asm/intel-mid.h
arch/x86/include/asm/irq_vectors.h
arch/x86/include/asm/lguest.h
arch/x86/include/asm/paravirt_types.h
arch/x86/include/asm/pvclock.h
arch/x86/include/asm/serial.h
arch/x86/include/asm/spinlock.h
arch/x86/include/asm/thread_info.h
arch/x86/include/asm/uaccess_32.h
arch/x86/include/asm/xen/page.h
arch/x86/include/uapi/asm/hyperv.h
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/acpi/wakeup_64.S
arch/x86/kernel/alternative.c
arch/x86/kernel/apic/vector.c
arch/x86/kernel/asm-offsets.c
arch/x86/kernel/asm-offsets_32.c
arch/x86/kernel/asm-offsets_64.c
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/hypervisor.c
arch/x86/kernel/cpu/perf_event_intel.c
arch/x86/kernel/cpu/perf_event_intel_uncore_snb.c
arch/x86/kernel/early_printk.c
arch/x86/kernel/entry_64.S
arch/x86/kernel/i8259.c
arch/x86/kernel/irq.c
arch/x86/kernel/irq_32.c
arch/x86/kernel/irq_64.c
arch/x86/kernel/irqinit.c
arch/x86/kernel/paravirt.c
arch/x86/kernel/paravirt_patch_64.c
arch/x86/kernel/process.c
arch/x86/kernel/process_32.c
arch/x86/kernel/process_64.c
arch/x86/kernel/pvclock.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/traps.c
arch/x86/kvm/assigned-dev.c
arch/x86/kvm/lapic.c
arch/x86/kvm/mmu.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/lguest/boot.c
arch/x86/lguest/head_32.S
arch/x86/lib/usercopy_64.c
arch/x86/mm/ioremap.c
arch/x86/pci/acpi.c
arch/x86/platform/intel-mid/Makefile
arch/x86/platform/intel-mid/early_printk_intel_mid.c [deleted file]
arch/x86/power/hibernate_asm_64.S
arch/x86/vdso/vclock_gettime.c
arch/x86/xen/enlighten.c
arch/x86/xen/suspend.c
arch/x86/xen/xen-asm_64.S
arch/x86/xen/xen-ops.h
crypto/async_tx/async_pq.c
drivers/Makefile
drivers/acpi/Kconfig
drivers/acpi/Makefile
drivers/acpi/acpi_pnp.c
drivers/acpi/acpi_processor.c
drivers/acpi/bus.c
drivers/acpi/ec.c
drivers/acpi/gsi.c [new file with mode: 0644]
drivers/acpi/internal.h
drivers/acpi/osl.c
drivers/acpi/processor_core.c
drivers/acpi/resource.c
drivers/acpi/sbs.c
drivers/acpi/sbshc.c
drivers/acpi/scan.c
drivers/acpi/tables.c
drivers/base/devtmpfs.c
drivers/block/drbd/drbd_debugfs.c
drivers/block/rbd.c
drivers/block/xen-blkback/blkback.c
drivers/block/zram/zram_drv.c
drivers/bus/Kconfig
drivers/bus/Makefile
drivers/bus/arm-cci.c
drivers/bus/imx-weim.c
drivers/bus/omap-ocp2scp.c
drivers/bus/simple-pm-bus.c [new file with mode: 0644]
drivers/char/hw_random/bcm63xx-rng.c
drivers/char/hw_random/core.c
drivers/char/hw_random/pasemi-rng.c
drivers/char/hw_random/powernv-rng.c
drivers/char/hw_random/ppc4xx-rng.c
drivers/char/i8k.c
drivers/char/ipmi/ipmi_msghandler.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/ipmi/ipmi_ssif.c
drivers/char/misc.c
drivers/char/virtio_console.c
drivers/char/xillybus/xillybus_core.c
drivers/char/xillybus/xillybus_of.c
drivers/clk/Kconfig
drivers/clk/Makefile
drivers/clk/at91/clk-usb.c
drivers/clk/clk-cdce706.c
drivers/clk/clk-conf.c
drivers/clk/clk-fractional-divider.c
drivers/clk/clk-gpio-gate.c
drivers/clk/clk-mb86s7x.c [new file with mode: 0644]
drivers/clk/clk-palmas.c
drivers/clk/clk-pwm.c [new file with mode: 0644]
drivers/clk/clk-si5351.c
drivers/clk/clk-si570.c
drivers/clk/clk.c
drivers/clk/clk.h
drivers/clk/clkdev.c
drivers/clk/hisilicon/clk-hi3620.c
drivers/clk/hisilicon/clk-hix5hd2.c
drivers/clk/mvebu/Kconfig
drivers/clk/mvebu/Makefile
drivers/clk/mvebu/armada-39x.c [new file with mode: 0644]
drivers/clk/mvebu/common.c
drivers/clk/mvebu/common.h
drivers/clk/mxs/clk-imx23.c
drivers/clk/mxs/clk-imx28.c
drivers/clk/pxa/clk-pxa.h
drivers/clk/pxa/clk-pxa3xx.c
drivers/clk/qcom/Kconfig
drivers/clk/qcom/Makefile
drivers/clk/qcom/clk-pll.c
drivers/clk/qcom/clk-rcg.c
drivers/clk/qcom/clk-rcg.h
drivers/clk/qcom/clk-rcg2.c
drivers/clk/qcom/common.c
drivers/clk/qcom/common.h
drivers/clk/qcom/gcc-apq8084.c
drivers/clk/qcom/gcc-ipq806x.c
drivers/clk/qcom/gcc-msm8660.c
drivers/clk/qcom/gcc-msm8916.c [new file with mode: 0644]
drivers/clk/qcom/gcc-msm8960.c
drivers/clk/qcom/gcc-msm8974.c
drivers/clk/qcom/lcc-ipq806x.c
drivers/clk/qcom/lcc-msm8960.c
drivers/clk/qcom/mmcc-apq8084.c
drivers/clk/qcom/mmcc-msm8960.c
drivers/clk/qcom/mmcc-msm8974.c
drivers/clk/rockchip/clk-rk3188.c
drivers/clk/rockchip/clk-rk3288.c
drivers/clk/rockchip/clk.c
drivers/clk/rockchip/clk.h
drivers/clk/samsung/Makefile
drivers/clk/samsung/clk-exynos-clkout.c
drivers/clk/samsung/clk-exynos3250.c
drivers/clk/samsung/clk-exynos4.c
drivers/clk/samsung/clk-exynos5433.c [new file with mode: 0644]
drivers/clk/samsung/clk-s5pv210.c
drivers/clk/shmobile/Makefile
drivers/clk/shmobile/clk-r8a7778.c [new file with mode: 0644]
drivers/clk/st/clkgen-fsyn.c
drivers/clk/st/clkgen-mux.c
drivers/clk/st/clkgen-pll.c
drivers/clk/sunxi/Makefile
drivers/clk/sunxi/clk-sunxi.c
drivers/clk/sunxi/clk-usb.c [new file with mode: 0644]
drivers/clk/tegra/clk-pll.c
drivers/clk/tegra/clk-tegra-fixed.c
drivers/clk/tegra/clk-tegra-periph.c
drivers/clk/tegra/clk-tegra114.c
drivers/clk/tegra/clk-tegra124.c
drivers/clk/tegra/clk-tegra30.c
drivers/clk/tegra/clk.c
drivers/clk/tegra/clk.h
drivers/clk/ti/apll.c
drivers/clk/ti/autoidle.c
drivers/clk/ti/clk-3xxx-legacy.c
drivers/clk/ti/clk-3xxx.c
drivers/clk/ti/clk-44xx.c
drivers/clk/ti/clk-54xx.c
drivers/clk/ti/clk-7xx.c
drivers/clk/ti/clk-dra7-atl.c
drivers/clk/ti/clk.c
drivers/clk/ti/clockdomain.c
drivers/clk/ti/composite.c
drivers/clk/ti/divider.c
drivers/clk/ti/dpll.c
drivers/clk/ti/fapll.c
drivers/clk/ti/gate.c
drivers/clk/ti/interface.c
drivers/clk/ti/mux.c
drivers/clk/versatile/clk-versatile.c
drivers/clk/versatile/clk-vexpress-osc.c
drivers/clk/zynq/clkc.c
drivers/clocksource/Kconfig
drivers/clocksource/Makefile
drivers/clocksource/arm_arch_timer.c
drivers/clocksource/timer-atmel-st.c [new file with mode: 0644]
drivers/coresight/Makefile [deleted file]
drivers/coresight/coresight-etb10.c [deleted file]
drivers/coresight/coresight-etm-cp14.c [deleted file]
drivers/coresight/coresight-etm.h [deleted file]
drivers/coresight/coresight-etm3x.c [deleted file]
drivers/coresight/coresight-funnel.c [deleted file]
drivers/coresight/coresight-priv.h [deleted file]
drivers/coresight/coresight-replicator.c [deleted file]
drivers/coresight/coresight-tmc.c [deleted file]
drivers/coresight/coresight-tpiu.c [deleted file]
drivers/coresight/coresight.c [deleted file]
drivers/coresight/of_coresight.c [deleted file]
drivers/cpufreq/intel_pstate.c
drivers/cpuidle/cpuidle-exynos.c
drivers/cpuidle/cpuidle.c
drivers/crypto/Kconfig
drivers/dma-buf/dma-buf.c
drivers/dma/Kconfig
drivers/dma/Makefile
drivers/dma/amba-pl08x.c
drivers/dma/at_hdmac.c
drivers/dma/at_xdmac.c
drivers/dma/bestcomm/bestcomm.c
drivers/dma/dma-jz4740.c
drivers/dma/dma-jz4780.c [new file with mode: 0644]
drivers/dma/dmaengine.c
drivers/dma/dw/Kconfig
drivers/dma/dw/core.c
drivers/dma/edma.c
drivers/dma/fsl_raid.c [new file with mode: 0644]
drivers/dma/fsl_raid.h [new file with mode: 0644]
drivers/dma/hsu/Kconfig [new file with mode: 0644]
drivers/dma/hsu/Makefile [new file with mode: 0644]
drivers/dma/hsu/hsu.c [new file with mode: 0644]
drivers/dma/hsu/hsu.h [new file with mode: 0644]
drivers/dma/hsu/pci.c [new file with mode: 0644]
drivers/dma/img-mdc-dma.c
drivers/dma/imx-sdma.c
drivers/dma/ioat/dca.c
drivers/dma/ioat/dma.c
drivers/dma/ioat/dma.h
drivers/dma/ioat/dma_v2.c
drivers/dma/ioat/dma_v2.h
drivers/dma/ioat/dma_v3.c
drivers/dma/ioat/hw.h
drivers/dma/ioat/pci.c
drivers/dma/ioat/registers.h
drivers/dma/iop-adma.c
drivers/dma/k3dma.c
drivers/dma/mmp_pdma.c
drivers/dma/mmp_tdma.c
drivers/dma/mpc512x_dma.c
drivers/dma/mv_xor.c
drivers/dma/mv_xor.h
drivers/dma/pch_dma.c
drivers/dma/pl330.c
drivers/dma/ppc4xx/adma.c
drivers/dma/qcom_bam_dma.c
drivers/dma/s3c24xx-dma.c
drivers/dma/sa11x0-dma.c
drivers/dma/sh/Kconfig
drivers/dma/sh/Makefile
drivers/dma/sh/rcar-audmapp.c [deleted file]
drivers/dma/sh/shdma-base.c
drivers/dma/sh/shdmac.c
drivers/dma/sh/usb-dmac.c [new file with mode: 0644]
drivers/dma/sirf-dma.c
drivers/dma/ste_dma40.c
drivers/dma/sun6i-dma.c
drivers/dma/xgene-dma.c [new file with mode: 0755]
drivers/dma/xilinx/xilinx_vdma.c
drivers/extcon/Kconfig
drivers/extcon/Makefile
drivers/extcon/extcon-arizona.c
drivers/extcon/extcon-class.c [deleted file]
drivers/extcon/extcon-max14577.c
drivers/extcon/extcon-max77693.c
drivers/extcon/extcon-max77843.c [new file with mode: 0644]
drivers/extcon/extcon-max8997.c
drivers/extcon/extcon-rt8973a.c
drivers/extcon/extcon-sm5502.c
drivers/extcon/extcon-usb-gpio.c [new file with mode: 0644]
drivers/extcon/extcon.c [new file with mode: 0644]
drivers/firmware/Kconfig
drivers/firmware/Makefile
drivers/firmware/efi/runtime-map.c
drivers/firmware/pcdp.c
drivers/firmware/qcom_scm.c [new file with mode: 0644]
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/gpio-msm-v1.c [deleted file]
drivers/gpu/drm/armada/armada_gem.c
drivers/gpu/drm/drm_prime.c
drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_dmabuf.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_i2c.c
drivers/gpu/drm/i915/intel_lrc.c
drivers/gpu/drm/i915/intel_uncore.c
drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/atombios_encoders.c
drivers/gpu/drm/radeon/dce6_afmt.c
drivers/gpu/drm/radeon/evergreen_hdmi.c
drivers/gpu/drm/radeon/r600_hdmi.c
drivers/gpu/drm/radeon/radeon_audio.c
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_cs.c
drivers/gpu/drm/radeon/radeon_mn.c
drivers/gpu/drm/radeon/radeon_vm.c
drivers/gpu/drm/radeon/si_dpm.c
drivers/gpu/drm/rockchip/rockchip_drm_vop.c
drivers/gpu/drm/tegra/gem.c
drivers/gpu/drm/ttm/ttm_object.c
drivers/gpu/drm/udl/udl_dmabuf.c
drivers/hv/channel.c
drivers/hv/channel_mgmt.c
drivers/hv/connection.c
drivers/hv/hv.c
drivers/hv/hv_balloon.c
drivers/hv/hv_util.c
drivers/hv/hyperv_vmbus.h
drivers/hv/vmbus_drv.c
drivers/hwtracing/coresight/Kconfig [new file with mode: 0644]
drivers/hwtracing/coresight/Makefile [new file with mode: 0644]
drivers/hwtracing/coresight/coresight-etb10.c [new file with mode: 0644]
drivers/hwtracing/coresight/coresight-etm-cp14.c [new file with mode: 0644]
drivers/hwtracing/coresight/coresight-etm.h [new file with mode: 0644]
drivers/hwtracing/coresight/coresight-etm3x.c [new file with mode: 0644]
drivers/hwtracing/coresight/coresight-funnel.c [new file with mode: 0644]
drivers/hwtracing/coresight/coresight-priv.h [new file with mode: 0644]
drivers/hwtracing/coresight/coresight-replicator.c [new file with mode: 0644]
drivers/hwtracing/coresight/coresight-tmc.c [new file with mode: 0644]
drivers/hwtracing/coresight/coresight-tpiu.c [new file with mode: 0644]
drivers/hwtracing/coresight/coresight.c [new file with mode: 0644]
drivers/hwtracing/coresight/of_coresight.c [new file with mode: 0644]
drivers/i2c/busses/i2c-cros-ec-tunnel.c
drivers/i2c/busses/i2c-digicolor.c
drivers/i2c/busses/i2c-mxs.c
drivers/i2c/busses/i2c-pca-platform.c
drivers/i2c/busses/i2c-rk3x.c
drivers/i2c/busses/i2c-st.c
drivers/i2c/i2c-core.c
drivers/i2c/i2c-mux.c
drivers/infiniband/core/addr.c
drivers/infiniband/core/cm.c
drivers/infiniband/core/cm_msgs.h
drivers/infiniband/core/cma.c
drivers/infiniband/core/iwpm_msg.c
drivers/infiniband/core/iwpm_util.c
drivers/infiniband/core/iwpm_util.h
drivers/infiniband/core/umem.c
drivers/infiniband/core/umem_odp.c
drivers/infiniband/core/uverbs_main.c
drivers/infiniband/hw/cxgb4/cm.c
drivers/infiniband/hw/cxgb4/cq.c
drivers/infiniband/hw/cxgb4/device.c
drivers/infiniband/hw/cxgb4/iw_cxgb4.h
drivers/infiniband/hw/cxgb4/mem.c
drivers/infiniband/hw/cxgb4/qp.c
drivers/infiniband/hw/cxgb4/t4.h
drivers/infiniband/hw/cxgb4/t4fw_ri_api.h
drivers/infiniband/hw/ipath/ipath_fs.c
drivers/infiniband/hw/mlx4/alias_GUID.c
drivers/infiniband/hw/mlx4/mad.c
drivers/infiniband/hw/mlx4/main.c
drivers/infiniband/hw/mlx4/mlx4_ib.h
drivers/infiniband/hw/mlx4/qp.c
drivers/infiniband/hw/mlx4/sysfs.c
drivers/infiniband/hw/nes/nes.c
drivers/infiniband/hw/nes/nes_cm.c
drivers/infiniband/hw/qib/qib.h
drivers/infiniband/hw/qib/qib_file_ops.c
drivers/infiniband/hw/qib/qib_fs.c
drivers/infiniband/hw/qib/qib_iba6120.c
drivers/infiniband/hw/qib/qib_iba7220.c
drivers/infiniband/hw/qib/qib_iba7322.c
drivers/infiniband/hw/qib/qib_init.c
drivers/infiniband/hw/qib/qib_wc_x86_64.c
drivers/infiniband/ulp/ipoib/ipoib.h
drivers/infiniband/ulp/ipoib/ipoib_cm.c
drivers/infiniband/ulp/ipoib/ipoib_ib.c
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/ipoib/ipoib_multicast.c
drivers/infiniband/ulp/ipoib/ipoib_verbs.c
drivers/infiniband/ulp/iser/iscsi_iser.h
drivers/infiniband/ulp/iser/iser_initiator.c
drivers/infiniband/ulp/iser/iser_memory.c
drivers/infiniband/ulp/iser/iser_verbs.c
drivers/infiniband/ulp/isert/ib_isert.c
drivers/infiniband/ulp/isert/ib_isert.h
drivers/infiniband/ulp/srp/ib_srp.c
drivers/infiniband/ulp/srpt/ib_srpt.c
drivers/input/ff-core.c
drivers/input/ff-memless.c
drivers/input/joystick/xpad.c
drivers/input/keyboard/cros_ec_keyb.c
drivers/input/keyboard/lm8333.c
drivers/input/mouse/Kconfig
drivers/input/mouse/Makefile
drivers/input/mouse/cyapa.c
drivers/input/mouse/elan_i2c.h
drivers/input/mouse/elan_i2c_core.c
drivers/input/mouse/elan_i2c_i2c.c
drivers/input/mouse/elan_i2c_smbus.c
drivers/input/mouse/psmouse-base.c
drivers/input/mouse/psmouse.h
drivers/input/mouse/vmmouse.c [new file with mode: 0644]
drivers/input/mouse/vmmouse.h [new file with mode: 0644]
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/atmel_mxt_ts.c
drivers/input/touchscreen/elants_i2c.c
drivers/input/touchscreen/sur40.c
drivers/iommu/intel-iommu.c
drivers/iommu/intel_irq_remapping.c
drivers/irqchip/irq-gic.c
drivers/irqchip/irqchip.c
drivers/lguest/hypercalls.c
drivers/lguest/interrupts_and_traps.c
drivers/lguest/lg.h
drivers/lguest/lguest_user.c
drivers/mcb/mcb-pci.c
drivers/md/Kconfig
drivers/md/Makefile
drivers/md/bitmap.c
drivers/md/bitmap.h
drivers/md/dm-ioctl.c
drivers/md/dm.c
drivers/md/md-cluster.c [new file with mode: 0644]
drivers/md/md-cluster.h [new file with mode: 0644]
drivers/md/md.c
drivers/md/md.h
drivers/md/raid0.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5.c
drivers/md/raid5.h
drivers/media/Kconfig
drivers/media/common/saa7146/saa7146_fops.c
drivers/media/common/saa7146/saa7146_vbi.c
drivers/media/common/siano/sms-cards.c
drivers/media/common/siano/sms-cards.h
drivers/media/common/siano/smscoreapi.c
drivers/media/common/siano/smscoreapi.h
drivers/media/common/siano/smsdvb-debugfs.c
drivers/media/common/siano/smsdvb-main.c
drivers/media/common/siano/smsir.c
drivers/media/dvb-core/dmxdev.c
drivers/media/dvb-core/dvb-usb-ids.h
drivers/media/dvb-core/dvb_ca_en50221.c
drivers/media/dvb-core/dvb_frontend.c
drivers/media/dvb-core/dvb_net.c
drivers/media/dvb-core/dvbdev.c
drivers/media/dvb-core/dvbdev.h
drivers/media/dvb-frontends/Kconfig
drivers/media/dvb-frontends/Makefile
drivers/media/dvb-frontends/a8293.h
drivers/media/dvb-frontends/af9013.h
drivers/media/dvb-frontends/atbm8830.h
drivers/media/dvb-frontends/au8522.h
drivers/media/dvb-frontends/bcm3510.h
drivers/media/dvb-frontends/cx22700.h
drivers/media/dvb-frontends/cx22702.h
drivers/media/dvb-frontends/cx24110.h
drivers/media/dvb-frontends/cx24113.h
drivers/media/dvb-frontends/cx24116.h
drivers/media/dvb-frontends/cx24117.h
drivers/media/dvb-frontends/cx24123.h
drivers/media/dvb-frontends/cxd2820r.h
drivers/media/dvb-frontends/dib0070.h
drivers/media/dvb-frontends/dib0090.h
drivers/media/dvb-frontends/dib3000.h
drivers/media/dvb-frontends/dib3000mc.h
drivers/media/dvb-frontends/dib7000m.h
drivers/media/dvb-frontends/dib7000p.h
drivers/media/dvb-frontends/dib8000.h
drivers/media/dvb-frontends/dib9000.h
drivers/media/dvb-frontends/drx39xyj/drx39xxj.h
drivers/media/dvb-frontends/drxd.h
drivers/media/dvb-frontends/drxk.h
drivers/media/dvb-frontends/ds3000.h
drivers/media/dvb-frontends/dvb-pll.h
drivers/media/dvb-frontends/dvb_dummy_fe.h
drivers/media/dvb-frontends/ec100.h
drivers/media/dvb-frontends/hd29l2.h
drivers/media/dvb-frontends/isl6405.h
drivers/media/dvb-frontends/isl6421.h
drivers/media/dvb-frontends/isl6423.h
drivers/media/dvb-frontends/itd1000.h
drivers/media/dvb-frontends/ix2505v.h
drivers/media/dvb-frontends/l64781.h
drivers/media/dvb-frontends/lg2160.h
drivers/media/dvb-frontends/lgdt3305.h
drivers/media/dvb-frontends/lgdt3306a.c [new file with mode: 0644]
drivers/media/dvb-frontends/lgdt3306a.h [new file with mode: 0644]
drivers/media/dvb-frontends/lgdt330x.h
drivers/media/dvb-frontends/lgs8gl5.h
drivers/media/dvb-frontends/lgs8gxx.h
drivers/media/dvb-frontends/lnbh24.h
drivers/media/dvb-frontends/lnbp21.h
drivers/media/dvb-frontends/lnbp22.h
drivers/media/dvb-frontends/m88rs2000.h
drivers/media/dvb-frontends/mb86a16.h
drivers/media/dvb-frontends/mb86a20s.h
drivers/media/dvb-frontends/mn88472.h
drivers/media/dvb-frontends/mn88473.h
drivers/media/dvb-frontends/mt312.h
drivers/media/dvb-frontends/mt352.h
drivers/media/dvb-frontends/nxt200x.h
drivers/media/dvb-frontends/nxt6000.h
drivers/media/dvb-frontends/or51132.h
drivers/media/dvb-frontends/or51211.h
drivers/media/dvb-frontends/rtl2832.c
drivers/media/dvb-frontends/s5h1409.h
drivers/media/dvb-frontends/s5h1411.h
drivers/media/dvb-frontends/s5h1420.h
drivers/media/dvb-frontends/s5h1432.h
drivers/media/dvb-frontends/s921.h
drivers/media/dvb-frontends/si2165.c
drivers/media/dvb-frontends/si2165.h
drivers/media/dvb-frontends/si21xx.h
drivers/media/dvb-frontends/sp2.c
drivers/media/dvb-frontends/sp8870.h
drivers/media/dvb-frontends/sp887x.h
drivers/media/dvb-frontends/stb0899_drv.h
drivers/media/dvb-frontends/stb6000.h
drivers/media/dvb-frontends/stb6100.h
drivers/media/dvb-frontends/stv0288.h
drivers/media/dvb-frontends/stv0297.h
drivers/media/dvb-frontends/stv0299.h
drivers/media/dvb-frontends/stv0367.h
drivers/media/dvb-frontends/stv0900.h
drivers/media/dvb-frontends/stv090x.h
drivers/media/dvb-frontends/stv6110.h
drivers/media/dvb-frontends/stv6110x.h
drivers/media/dvb-frontends/tda1002x.h
drivers/media/dvb-frontends/tda10048.h
drivers/media/dvb-frontends/tda1004x.h
drivers/media/dvb-frontends/tda10071.h
drivers/media/dvb-frontends/tda10086.h
drivers/media/dvb-frontends/tda18271c2dd.h
drivers/media/dvb-frontends/tda665x.h
drivers/media/dvb-frontends/tda8083.h
drivers/media/dvb-frontends/tda8261.h
drivers/media/dvb-frontends/tda826x.h
drivers/media/dvb-frontends/ts2020.c
drivers/media/dvb-frontends/ts2020.h
drivers/media/dvb-frontends/tua6100.h
drivers/media/dvb-frontends/ves1820.h
drivers/media/dvb-frontends/ves1x93.h
drivers/media/dvb-frontends/zl10036.h
drivers/media/dvb-frontends/zl10039.h
drivers/media/dvb-frontends/zl10353.h
drivers/media/i2c/Kconfig
drivers/media/i2c/Makefile
drivers/media/i2c/ad9389b.c
drivers/media/i2c/adv7180.c
drivers/media/i2c/adv7343.c
drivers/media/i2c/adv7511.c
drivers/media/i2c/adv7604.c
drivers/media/i2c/adv7842.c
drivers/media/i2c/cx25840/cx25840-core.c
drivers/media/i2c/cx25840/cx25840-core.h
drivers/media/i2c/m5mols/m5mols_core.c
drivers/media/i2c/mt9m032.c
drivers/media/i2c/mt9p031.c
drivers/media/i2c/mt9t001.c
drivers/media/i2c/mt9v032.c
drivers/media/i2c/noon010pc30.c
drivers/media/i2c/ov2659.c [new file with mode: 0644]
drivers/media/i2c/ov7670.c
drivers/media/i2c/ov9650.c
drivers/media/i2c/s5c73m3/s5c73m3-core.c
drivers/media/i2c/s5c73m3/s5c73m3-spi.c
drivers/media/i2c/s5k4ecgx.c
drivers/media/i2c/s5k5baf.c
drivers/media/i2c/s5k6a3.c
drivers/media/i2c/s5k6aa.c
drivers/media/i2c/smiapp/smiapp-core.c
drivers/media/i2c/soc_camera/mt9m111.c
drivers/media/i2c/soc_camera/ov2640.c
drivers/media/i2c/ths7303.c
drivers/media/i2c/ths8200.c
drivers/media/i2c/tvp514x.c
drivers/media/i2c/tvp7002.c
drivers/media/mmc/siano/smssdio.c
drivers/media/pci/bt8xx/bttv-driver.c
drivers/media/pci/bt8xx/bttvp.h
drivers/media/pci/cx18/cx18-alsa-main.c
drivers/media/pci/cx18/cx18-driver.h
drivers/media/pci/cx18/cx18-fileops.c
drivers/media/pci/cx18/cx18-ioctl.c
drivers/media/pci/cx18/cx18-streams.c
drivers/media/pci/cx18/cx18-streams.h
drivers/media/pci/cx23885/Kconfig
drivers/media/pci/cx23885/altera-ci.c
drivers/media/pci/cx23885/altera-ci.h
drivers/media/pci/cx23885/cx23885-core.c
drivers/media/pci/cx23885/cx23885-dvb.c
drivers/media/pci/cx23885/cx23885-video.c
drivers/media/pci/cx88/cx88-blackbird.c
drivers/media/pci/cx88/cx88-core.c
drivers/media/pci/cx88/cx88-mpeg.c
drivers/media/pci/cx88/cx88-video.c
drivers/media/pci/cx88/cx88.h
drivers/media/pci/ivtv/ivtv-alsa-main.c
drivers/media/pci/ivtv/ivtv-alsa-pcm.c
drivers/media/pci/ivtv/ivtv-driver.c
drivers/media/pci/ivtv/ivtv-driver.h
drivers/media/pci/ivtv/ivtv-fileops.c
drivers/media/pci/ivtv/ivtv-ioctl.c
drivers/media/pci/ivtv/ivtv-irq.c
drivers/media/pci/ivtv/ivtv-streams.c
drivers/media/pci/ivtv/ivtv-streams.h
drivers/media/pci/meye/meye.c
drivers/media/pci/meye/meye.h
drivers/media/pci/saa7146/hexium_gemini.c
drivers/media/pci/saa7146/hexium_orion.c
drivers/media/pci/saa7146/mxb.c
drivers/media/pci/saa7164/saa7164-core.c
drivers/media/pci/smipcie/Kconfig
drivers/media/pci/smipcie/smipcie.c
drivers/media/pci/sta2x11/sta2x11_vip.c
drivers/media/pci/ttpci/av7110.h
drivers/media/pci/ttpci/budget-av.c
drivers/media/platform/Kconfig
drivers/media/platform/Makefile
drivers/media/platform/am437x/Kconfig
drivers/media/platform/am437x/am437x-vpfe.c
drivers/media/platform/am437x/am437x-vpfe.h
drivers/media/platform/blackfin/bfin_capture.c
drivers/media/platform/coda/Makefile
drivers/media/platform/coda/coda-bit.c
drivers/media/platform/coda/coda-common.c
drivers/media/platform/coda/coda-jpeg.c
drivers/media/platform/coda/coda.h
drivers/media/platform/coda/trace.h [new file with mode: 0644]
drivers/media/platform/davinci/vpfe_capture.c
drivers/media/platform/davinci/vpif_capture.c
drivers/media/platform/davinci/vpif_capture.h
drivers/media/platform/davinci/vpif_display.c
drivers/media/platform/davinci/vpif_display.h
drivers/media/platform/exynos4-is/fimc-capture.c
drivers/media/platform/exynos4-is/fimc-isp.c
drivers/media/platform/exynos4-is/fimc-lite.c
drivers/media/platform/exynos4-is/mipi-csis.c
drivers/media/platform/m2m-deinterlace.c
drivers/media/platform/marvell-ccic/mcam-core.c
drivers/media/platform/marvell-ccic/mcam-core.h
drivers/media/platform/omap/omap_vout.c
drivers/media/platform/omap/omap_vout_vrfb.c
drivers/media/platform/omap/omap_vout_vrfb.h
drivers/media/platform/omap3isp/isp.c
drivers/media/platform/omap3isp/isp.h
drivers/media/platform/omap3isp/ispccdc.c
drivers/media/platform/omap3isp/ispccp2.c
drivers/media/platform/omap3isp/ispcsi2.c
drivers/media/platform/omap3isp/ispcsiphy.c
drivers/media/platform/omap3isp/isph3a_aewb.c
drivers/media/platform/omap3isp/isph3a_af.c
drivers/media/platform/omap3isp/isphist.c
drivers/media/platform/omap3isp/isppreview.c
drivers/media/platform/omap3isp/ispresizer.c
drivers/media/platform/omap3isp/ispstat.c
drivers/media/platform/omap3isp/ispstat.h
drivers/media/platform/omap3isp/ispvideo.c
drivers/media/platform/s3c-camif/camif-capture.c
drivers/media/platform/s5p-jpeg/jpeg-core.c
drivers/media/platform/s5p-jpeg/jpeg-core.h
drivers/media/platform/s5p-jpeg/jpeg-hw-s5p.c
drivers/media/platform/s5p-jpeg/jpeg-hw-s5p.h
drivers/media/platform/s5p-mfc/s5p_mfc.c
drivers/media/platform/s5p-tv/mixer_video.c
drivers/media/platform/sh_vou.c
drivers/media/platform/soc_camera/rcar_vin.c
drivers/media/platform/soc_camera/sh_mobile_csi2.c
drivers/media/platform/soc_camera/soc_camera.c
drivers/media/platform/via-camera.c
drivers/media/platform/vim2m.c
drivers/media/platform/vivid/vivid-core.c
drivers/media/platform/vivid/vivid-core.h
drivers/media/platform/vivid/vivid-ctrls.c
drivers/media/platform/vivid/vivid-kthread-cap.c
drivers/media/platform/vivid/vivid-sdr-cap.c
drivers/media/platform/vivid/vivid-tpg.c
drivers/media/platform/vivid/vivid-tpg.h
drivers/media/platform/vivid/vivid-vid-cap.c
drivers/media/platform/vivid/vivid-vid-common.c
drivers/media/platform/vivid/vivid-vid-out.c
drivers/media/platform/vsp1/vsp1_bru.c
drivers/media/platform/vsp1/vsp1_entity.c
drivers/media/platform/vsp1/vsp1_entity.h
drivers/media/platform/vsp1/vsp1_hsit.c
drivers/media/platform/vsp1/vsp1_lif.c
drivers/media/platform/vsp1/vsp1_lut.c
drivers/media/platform/vsp1/vsp1_rwpf.c
drivers/media/platform/vsp1/vsp1_rwpf.h
drivers/media/platform/vsp1/vsp1_sru.c
drivers/media/platform/vsp1/vsp1_uds.c
drivers/media/platform/xilinx/Kconfig [new file with mode: 0644]
drivers/media/platform/xilinx/Makefile [new file with mode: 0644]
drivers/media/platform/xilinx/xilinx-dma.c [new file with mode: 0644]
drivers/media/platform/xilinx/xilinx-dma.h [new file with mode: 0644]
drivers/media/platform/xilinx/xilinx-tpg.c [new file with mode: 0644]
drivers/media/platform/xilinx/xilinx-vip.c [new file with mode: 0644]
drivers/media/platform/xilinx/xilinx-vip.h [new file with mode: 0644]
drivers/media/platform/xilinx/xilinx-vipp.c [new file with mode: 0644]
drivers/media/platform/xilinx/xilinx-vipp.h [new file with mode: 0644]
drivers/media/platform/xilinx/xilinx-vtc.c [new file with mode: 0644]
drivers/media/platform/xilinx/xilinx-vtc.h [new file with mode: 0644]
drivers/media/radio/radio-wl1273.c
drivers/media/radio/si470x/radio-si470x-common.c
drivers/media/radio/si4713/si4713.c
drivers/media/radio/wl128x/Kconfig
drivers/media/radio/wl128x/fmdrv_v4l2.c
drivers/media/rc/img-ir/img-ir-core.c
drivers/media/rc/img-ir/img-ir.h
drivers/media/rc/ir-hix5hd2.c
drivers/media/tuners/Kconfig
drivers/media/tuners/Makefile
drivers/media/tuners/fc0011.h
drivers/media/tuners/fc0012.h
drivers/media/tuners/fc0013.h
drivers/media/tuners/fc2580.h
drivers/media/tuners/m88ts2022.c [deleted file]
drivers/media/tuners/m88ts2022.h [deleted file]
drivers/media/tuners/m88ts2022_priv.h [deleted file]
drivers/media/tuners/max2165.h
drivers/media/tuners/mc44s803.h
drivers/media/tuners/mt2060.h
drivers/media/tuners/mt2063.h
drivers/media/tuners/mt20xx.h
drivers/media/tuners/mt2131.h
drivers/media/tuners/mt2266.h
drivers/media/tuners/mxl5005s.h
drivers/media/tuners/mxl5007t.h
drivers/media/tuners/qt1010.h
drivers/media/tuners/r820t.c
drivers/media/tuners/r820t.h
drivers/media/tuners/si2157.c
drivers/media/tuners/si2157_priv.h
drivers/media/tuners/tda18218.h
drivers/media/tuners/tda18271.h
drivers/media/tuners/tda827x.h
drivers/media/tuners/tda8290.h
drivers/media/tuners/tda9887.h
drivers/media/tuners/tea5761.h
drivers/media/tuners/tea5767.h
drivers/media/tuners/tua9001.h
drivers/media/tuners/tuner-simple.h
drivers/media/tuners/tuner-xc2028.h
drivers/media/tuners/xc4000.h
drivers/media/tuners/xc5000.c
drivers/media/tuners/xc5000.h
drivers/media/usb/au0828/au0828-video.c
drivers/media/usb/au0828/au0828.h
drivers/media/usb/cx231xx/Kconfig
drivers/media/usb/cx231xx/cx231xx-417.c
drivers/media/usb/cx231xx/cx231xx-cards.c
drivers/media/usb/cx231xx/cx231xx-core.c
drivers/media/usb/cx231xx/cx231xx-dvb.c
drivers/media/usb/cx231xx/cx231xx-video.c
drivers/media/usb/cx231xx/cx231xx.h
drivers/media/usb/dvb-usb-v2/Kconfig
drivers/media/usb/dvb-usb-v2/dvb_usb.h
drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
drivers/media/usb/dvb-usb-v2/dvbsky.c
drivers/media/usb/dvb-usb-v2/rtl28xxu.c
drivers/media/usb/dvb-usb/Kconfig
drivers/media/usb/dvb-usb/cxusb.c
drivers/media/usb/dvb-usb/dib0700_core.c
drivers/media/usb/dvb-usb/dib0700_devices.c
drivers/media/usb/dvb-usb/dvb-usb-dvb.c
drivers/media/usb/dvb-usb/dw2102.c
drivers/media/usb/em28xx/Kconfig
drivers/media/usb/em28xx/em28xx-camera.c
drivers/media/usb/em28xx/em28xx-cards.c
drivers/media/usb/em28xx/em28xx-dvb.c
drivers/media/usb/em28xx/em28xx-video.c
drivers/media/usb/em28xx/em28xx.h
drivers/media/usb/gspca/ov534.c
drivers/media/usb/gspca/topro.c
drivers/media/usb/hdpvr/hdpvr-core.c
drivers/media/usb/hdpvr/hdpvr-video.c
drivers/media/usb/hdpvr/hdpvr.h
drivers/media/usb/pvrusb2/pvrusb2-v4l2.c
drivers/media/usb/siano/smsusb.c
drivers/media/usb/stk1160/stk1160-v4l.c
drivers/media/usb/stkwebcam/stk-webcam.c
drivers/media/usb/tm6000/tm6000-video.c
drivers/media/usb/tm6000/tm6000.h
drivers/media/usb/usbvision/usbvision-video.c
drivers/media/usb/usbvision/usbvision.h
drivers/media/usb/uvc/uvc_driver.c
drivers/media/usb/uvc/uvc_queue.c
drivers/media/usb/uvc/uvc_v4l2.c
drivers/media/usb/uvc/uvcvideo.h
drivers/media/v4l2-core/tuner-core.c
drivers/media/v4l2-core/v4l2-clk.c
drivers/media/v4l2-core/v4l2-ctrls.c
drivers/media/v4l2-core/v4l2-dev.c
drivers/media/v4l2-core/v4l2-device.c
drivers/media/v4l2-core/v4l2-dv-timings.c
drivers/media/v4l2-core/v4l2-ioctl.c
drivers/media/v4l2-core/v4l2-mem2mem.c
drivers/media/v4l2-core/v4l2-of.c
drivers/media/v4l2-core/v4l2-subdev.c
drivers/media/v4l2-core/videobuf2-core.c
drivers/media/v4l2-core/videobuf2-dma-contig.c
drivers/media/v4l2-core/videobuf2-dma-sg.c
drivers/media/v4l2-core/videobuf2-vmalloc.c
drivers/memory/Kconfig
drivers/memory/Makefile
drivers/memory/jz4780-nemc.c [new file with mode: 0644]
drivers/memory/omap-gpmc.c
drivers/mfd/cros_ec.c
drivers/misc/bh1780gli.c
drivers/misc/carma/carma-fpga-program.c
drivers/misc/carma/carma-fpga.c
drivers/misc/lis3lv02d/lis3lv02d.c
drivers/misc/lis3lv02d/lis3lv02d_i2c.c
drivers/misc/lis3lv02d/lis3lv02d_spi.c
drivers/misc/mei/Makefile
drivers/misc/mei/amthif.c
drivers/misc/mei/bus.c
drivers/misc/mei/client.c
drivers/misc/mei/client.h
drivers/misc/mei/debugfs.c
drivers/misc/mei/hbm.c
drivers/misc/mei/hw-me.c
drivers/misc/mei/hw-me.h
drivers/misc/mei/hw-txe.c
drivers/misc/mei/init.c
drivers/misc/mei/interrupt.c
drivers/misc/mei/main.c
drivers/misc/mei/mei-trace.c [new file with mode: 0644]
drivers/misc/mei/mei-trace.h [new file with mode: 0644]
drivers/misc/mei/mei_dev.h
drivers/misc/mei/nfc.c
drivers/misc/mei/pci-me.c
drivers/misc/mei/pci-txe.c
drivers/misc/mei/wd.c
drivers/misc/mic/host/mic_boot.c
drivers/misc/mic/host/mic_intr.c
drivers/misc/sram.c
drivers/misc/tifm_7xx1.c
drivers/misc/vmw_vmci/vmci_driver.c
drivers/misc/vmw_vmci/vmci_host.c
drivers/misc/vmw_vmci/vmci_queue_pair.c
drivers/mmc/card/block.c
drivers/mmc/card/mmc_test.c
drivers/mmc/core/bus.c
drivers/mmc/core/pwrseq.c
drivers/mmc/host/Kconfig
drivers/mmc/host/Makefile
drivers/mmc/host/msm_sdcc.c [deleted file]
drivers/mmc/host/msm_sdcc.h [deleted file]
drivers/mmc/host/sh_mmcif.c
drivers/mmc/host/sh_mobile_sdhi.c
drivers/mmc/host/tmio_mmc.h
drivers/mmc/host/tmio_mmc_dma.c
drivers/mtd/Kconfig
drivers/mtd/chips/cfi_cmdset_0020.c
drivers/mtd/devices/block2mtd.c
drivers/mtd/devices/docg3.c
drivers/mtd/devices/m25p80.c
drivers/mtd/maps/Kconfig
drivers/mtd/maps/sa1100-flash.c
drivers/mtd/maps/ts5500_flash.c
drivers/mtd/mtd_blkdevs.c
drivers/mtd/mtdcore.c
drivers/mtd/mtdpart.c
drivers/mtd/nand/atmel_nand.c
drivers/mtd/nand/atmel_nand_ecc.h
drivers/mtd/nand/atmel_nand_nfc.h
drivers/mtd/nand/denali.c
drivers/mtd/nand/fsl_ifc_nand.c
drivers/mtd/nand/fsmc_nand.c
drivers/mtd/nand/gpmi-nand/gpmi-nand.c
drivers/mtd/nand/mxc_nand.c
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/pxa3xx_nand.c
drivers/mtd/nand/s3c2410.c
drivers/mtd/nand/sh_flctl.c
drivers/mtd/onenand/onenand_base.c
drivers/mtd/spi-nor/fsl-quadspi.c
drivers/mtd/spi-nor/spi-nor.c
drivers/mtd/tests/mtd_nandecctest.c
drivers/mtd/tests/mtd_test.h
drivers/mtd/tests/nandbiterrs.c
drivers/mtd/tests/oobtest.c
drivers/mtd/tests/pagetest.c
drivers/mtd/tests/readtest.c
drivers/mtd/tests/speedtest.c
drivers/mtd/tests/stresstest.c
drivers/mtd/tests/subpagetest.c
drivers/mtd/tests/torturetest.c
drivers/mtd/ubi/build.c
drivers/mtd/ubi/kapi.c
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_procfs.c
drivers/net/bonding/bonding_priv.h [new file with mode: 0644]
drivers/net/can/Kconfig
drivers/net/can/usb/kvaser_usb.c
drivers/net/dsa/mv88e6xxx.c
drivers/net/ethernet/8390/etherh.c
drivers/net/ethernet/altera/altera_msgdmahw.h
drivers/net/ethernet/altera/altera_tse_main.c
drivers/net/ethernet/amd/Kconfig
drivers/net/ethernet/arc/Kconfig
drivers/net/ethernet/atheros/atl1e/atl1e_hw.h
drivers/net/ethernet/broadcom/bcmsysport.h
drivers/net/ethernet/broadcom/bgmac.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/cadence/macb.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.h
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/ibm/ehea/ehea_main.c
drivers/net/ethernet/ibm/ibmveth.c
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/marvell/pxa168_eth.c
drivers/net/ethernet/mellanox/mlx4/cmd.c
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
drivers/net/ethernet/mellanox/mlx4/en_rx.c
drivers/net/ethernet/mellanox/mlx4/en_tx.c
drivers/net/ethernet/mellanox/mlx4/eq.c
drivers/net/ethernet/mellanox/mlx4/fw.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx4/mlx4.h
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
drivers/net/ethernet/myricom/myri10ge/myri10ge.c
drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
drivers/net/ethernet/rocker/rocker.c
drivers/net/ethernet/ti/netcp_ethss.c
drivers/net/hyperv/hyperv_net.h
drivers/net/hyperv/netvsc.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/hyperv/rndis_filter.c
drivers/net/phy/mdio-gpio.c
drivers/net/phy/mdio-mux-gpio.c
drivers/net/ppp/ppp_generic.c
drivers/net/ppp/ppp_mppe.c
drivers/net/ppp/pppoe.c
drivers/net/vxlan.c
drivers/net/wireless/ti/wilink_platform_data.c
drivers/net/wireless/ti/wl12xx/main.c
drivers/net/wireless/ti/wl12xx/wl12xx.h
drivers/net/wireless/ti/wlcore/boot.c
drivers/net/wireless/ti/wlcore/debugfs.c
drivers/net/wireless/ti/wlcore/main.c
drivers/net/wireless/ti/wlcore/sdio.c
drivers/net/wireless/ti/wlcore/spi.c
drivers/net/wireless/ti/wlcore/wlcore.h
drivers/net/wireless/ti/wlcore/wlcore_i.h
drivers/of/Kconfig
drivers/of/base.c
drivers/of/fdt.c
drivers/of/unittest.c
drivers/oprofile/oprofilefs.c
drivers/parisc/ccio-dma.c
drivers/parisc/iommu-helpers.h
drivers/parisc/sba_iommu.c
drivers/pcmcia/Kconfig
drivers/pcmcia/at91_cf.c
drivers/pcmcia/omap_cf.c
drivers/pcmcia/pd6729.c
drivers/pcmcia/soc_common.c
drivers/pcmcia/yenta_socket.c
drivers/pinctrl/Kconfig
drivers/pinctrl/core.c
drivers/pinctrl/core.h
drivers/pinctrl/devicetree.c
drivers/pinctrl/mediatek/Kconfig
drivers/pinctrl/mediatek/pinctrl-mtk-common.c
drivers/pinctrl/mvebu/pinctrl-armada-370.c
drivers/pinctrl/nomadik/Kconfig
drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
drivers/pinctrl/qcom/pinctrl-spmi-mpp.c
drivers/platform/chrome/Kconfig
drivers/platform/chrome/Makefile
drivers/platform/chrome/chromeos_laptop.c
drivers/platform/chrome/cros_ec_dev.c [new file with mode: 0644]
drivers/platform/chrome/cros_ec_dev.h [new file with mode: 0644]
drivers/platform/chrome/cros_ec_lightbar.c [new file with mode: 0644]
drivers/platform/chrome/cros_ec_lpc.c [new file with mode: 0644]
drivers/platform/chrome/cros_ec_sysfs.c [new file with mode: 0644]
drivers/platform/x86/Kconfig
drivers/platform/x86/apple-gmux.c
drivers/platform/x86/dell-laptop.c
drivers/platform/x86/ideapad-laptop.c
drivers/platform/x86/intel_oaktrail.c
drivers/platform/x86/thinkpad_acpi.c
drivers/platform/x86/toshiba_acpi.c
drivers/platform/x86/toshiba_bluetooth.c
drivers/platform/x86/wmi.c
drivers/powercap/intel_rapl.c
drivers/pwm/core.c
drivers/pwm/pwm-atmel-hlcdc.c
drivers/pwm/pwm-mxs.c
drivers/pwm/pwm-pca9685.c
drivers/pwm/pwm-samsung.c
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/rtc-abx80x.c [new file with mode: 0644]
drivers/rtc/rtc-armada38x.c
drivers/s390/char/con3215.c
drivers/s390/kvm/virtio_ccw.c
drivers/scsi/3w-9xxx.c
drivers/scsi/3w-9xxx.h
drivers/scsi/3w-sas.c
drivers/scsi/3w-sas.h
drivers/scsi/3w-xxxx.c
drivers/scsi/3w-xxxx.h
drivers/scsi/aha1542.c
drivers/scsi/qla2xxx/qla_target.c
drivers/scsi/qla2xxx/tcm_qla2xxx.c
drivers/scsi/qla2xxx/tcm_qla2xxx.h
drivers/scsi/scsi_devinfo.c
drivers/scsi/scsi_scan.c
drivers/sh/pm_runtime.c
drivers/soc/Kconfig
drivers/soc/Makefile
drivers/soc/mediatek/Kconfig [new file with mode: 0644]
drivers/soc/mediatek/Makefile [new file with mode: 0644]
drivers/soc/mediatek/mtk-pmic-wrap.c [new file with mode: 0644]
drivers/soc/qcom/Kconfig
drivers/soc/qcom/qcom_gsbi.c
drivers/spi/spi-rspi.c
drivers/spi/spi-sh-msiof.c
drivers/spmi/Kconfig
drivers/spmi/spmi-pmic-arb.c
drivers/spmi/spmi.c
drivers/staging/android/ion/ion.c
drivers/staging/lustre/lustre/llite/dcache.c
drivers/staging/lustre/lustre/llite/file.c
drivers/staging/lustre/lustre/llite/llite_internal.h
drivers/staging/lustre/lustre/llite/llite_lib.c
drivers/staging/lustre/lustre/llite/llite_nfs.c
drivers/staging/lustre/lustre/llite/namei.c
drivers/staging/lustre/lustre/llite/statahead.c
drivers/staging/lustre/lustre/llite/symlink.c
drivers/staging/lustre/lustre/llite/xattr.c
drivers/staging/media/bcm2048/radio-bcm2048.c
drivers/staging/media/davinci_vpfe/dm365_ipipe.c
drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
drivers/staging/media/davinci_vpfe/dm365_isif.c
drivers/staging/media/davinci_vpfe/dm365_resizer.c
drivers/staging/media/dt3155v4l/dt3155v4l.c
drivers/staging/media/dt3155v4l/dt3155v4l.h
drivers/staging/media/mn88472/mn88472.c
drivers/staging/media/mn88472/mn88472_priv.h
drivers/staging/media/mn88473/mn88473.c
drivers/staging/media/mn88473/mn88473_priv.h
drivers/staging/media/omap4iss/Kconfig
drivers/staging/media/omap4iss/iss.c
drivers/staging/media/omap4iss/iss.h
drivers/staging/media/omap4iss/iss_csi2.c
drivers/staging/media/omap4iss/iss_csiphy.c
drivers/staging/media/omap4iss/iss_ipipe.c
drivers/staging/media/omap4iss/iss_ipipeif.c
drivers/staging/media/omap4iss/iss_resizer.c
drivers/staging/media/omap4iss/iss_video.c
drivers/target/Kconfig
drivers/target/Makefile
drivers/target/iscsi/Makefile
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target.h
drivers/target/iscsi/iscsi_target_configfs.c
drivers/target/iscsi/iscsi_target_configfs.h [deleted file]
drivers/target/iscsi/iscsi_target_erl0.c
drivers/target/iscsi/iscsi_target_login.c
drivers/target/iscsi/iscsi_target_tpg.c
drivers/target/iscsi/iscsi_target_tpg.h
drivers/target/iscsi/iscsi_target_tq.c [deleted file]
drivers/target/iscsi/iscsi_target_tq.h [deleted file]
drivers/target/iscsi/iscsi_target_util.c
drivers/target/loopback/tcm_loop.c
drivers/target/loopback/tcm_loop.h
drivers/target/sbp/sbp_target.c
drivers/target/target_core_configfs.c
drivers/target/target_core_fabric_configfs.c
drivers/target/target_core_file.c
drivers/target/target_core_iblock.c
drivers/target/target_core_internal.h
drivers/target/target_core_pr.c
drivers/target/target_core_rd.c
drivers/target/target_core_sbc.c
drivers/target/target_core_spc.c
drivers/target/target_core_tmr.c
drivers/target/target_core_tpg.c
drivers/target/target_core_transport.c
drivers/target/target_core_user.c
drivers/target/target_core_xcopy.c
drivers/target/tcm_fc/tcm_fc.h
drivers/target/tcm_fc/tfc_conf.c
drivers/tty/hvc/hvc_opal.c
drivers/tty/hvc/hvc_xen.c
drivers/tty/n_gsm.c
drivers/tty/serial/8250/8250.h
drivers/tty/serial/8250/8250_core.c
drivers/tty/serial/8250/8250_dw.c
drivers/tty/serial/8250/8250_early.c
drivers/tty/serial/8250/8250_em.c
drivers/tty/serial/8250/8250_hp300.c
drivers/tty/serial/8250/8250_omap.c
drivers/tty/serial/8250/8250_pci.c
drivers/tty/serial/8250/Kconfig
drivers/tty/serial/Kconfig
drivers/tty/serial/Makefile
drivers/tty/serial/amba-pl011.c
drivers/tty/serial/apbuart.c
drivers/tty/serial/ar933x_uart.c
drivers/tty/serial/atmel_serial.c
drivers/tty/serial/bcm63xx_uart.c
drivers/tty/serial/bfin_uart.c
drivers/tty/serial/clps711x.c
drivers/tty/serial/cpm_uart/Makefile
drivers/tty/serial/cpm_uart/cpm_uart.h
drivers/tty/serial/cpm_uart/cpm_uart_core.c
drivers/tty/serial/earlycon.c
drivers/tty/serial/fsl_lpuart.c
drivers/tty/serial/imx.c
drivers/tty/serial/jsm/jsm_cls.c
drivers/tty/serial/jsm/jsm_neo.c
drivers/tty/serial/max3100.c
drivers/tty/serial/mfd.c [deleted file]
drivers/tty/serial/mpc52xx_uart.c
drivers/tty/serial/msm_serial.h
drivers/tty/serial/msm_serial_hs.c [deleted file]
drivers/tty/serial/mxs-auart.c
drivers/tty/serial/of_serial.c
drivers/tty/serial/omap-serial.c
drivers/tty/serial/pmac_zilog.c
drivers/tty/serial/pxa.c
drivers/tty/serial/samsung.c
drivers/tty/serial/sc16is7xx.c
drivers/tty/serial/serial-tegra.c
drivers/tty/serial/serial_core.c
drivers/tty/serial/serial_mctrl_gpio.c
drivers/tty/serial/sh-sci.c
drivers/tty/serial/sirfsoc_uart.c
drivers/tty/serial/sprd_serial.c
drivers/tty/serial/st-asc.c
drivers/tty/serial/uartlite.c
drivers/tty/serial/ucc_uart.c
drivers/tty/serial/xilinx_uartps.c
drivers/tty/tty_io.c
drivers/tty/tty_ioctl.c
drivers/tty/vt/vt.c
drivers/tty/vt/vt_ioctl.c
drivers/uio/uio.c
drivers/usb/chipidea/otg_fsm.c
drivers/usb/class/cdc-acm.c
drivers/usb/gadget/function/f_uvc.c
drivers/usb/gadget/function/uvc.h
drivers/usb/gadget/function/uvc_queue.c
drivers/usb/gadget/function/uvc_queue.h
drivers/usb/gadget/function/uvc_v4l2.c
drivers/usb/gadget/function/uvc_video.c
drivers/usb/gadget/legacy/inode.c
drivers/usb/gadget/legacy/tcm_usb_gadget.c
drivers/usb/host/ehci-msm.c
drivers/usb/storage/uas-detect.h
drivers/usb/storage/uas.c
drivers/usb/storage/usb.c
drivers/vfio/pci/vfio_pci.c
drivers/vfio/vfio.c
drivers/vhost/scsi.c
drivers/virtio/Kconfig
drivers/virtio/Makefile
drivers/virtio/virtio.c
drivers/virtio/virtio_balloon.c
drivers/virtio/virtio_input.c [new file with mode: 0644]
drivers/virtio/virtio_mmio.c
drivers/virtio/virtio_pci_modern.c
drivers/w1/masters/mxc_w1.c
drivers/w1/masters/omap_hdq.c
drivers/w1/masters/w1-gpio.c
drivers/watchdog/Kconfig
drivers/watchdog/at91rm9200_wdt.c
drivers/watchdog/bcm_kona_wdt.c
drivers/watchdog/octeon-wdt-main.c
drivers/watchdog/pnx4008_wdt.c
drivers/watchdog/qcom-wdt.c
drivers/watchdog/stmp3xxx_rtc_wdt.c
drivers/xen/Kconfig
drivers/xen/Makefile
drivers/xen/events/events_2l.c
drivers/xen/events/events_base.c
drivers/xen/gntdev.c
drivers/xen/grant-table.c
drivers/xen/manage.c
drivers/xen/swiotlb-xen.c
drivers/xen/xen-pciback/conf_space.c
drivers/xen/xen-pciback/conf_space.h
drivers/xen/xen-pciback/conf_space_header.c
drivers/xen/xen-scsiback.c
drivers/xen/xenbus/xenbus_probe.c
fs/9p/acl.c
fs/9p/vfs_dentry.c
fs/9p/vfs_dir.c
fs/9p/vfs_inode.c
fs/9p/vfs_inode_dotl.c
fs/9p/vfs_super.c
fs/adfs/inode.c
fs/affs/amigaffs.c
fs/affs/inode.c
fs/affs/namei.c
fs/afs/dir.c
fs/afs/inode.c
fs/afs/mntpt.c
fs/afs/super.c
fs/autofs4/autofs_i.h
fs/autofs4/expire.c
fs/autofs4/inode.c
fs/autofs4/root.c
fs/autofs4/symlink.c
fs/autofs4/waitq.c
fs/befs/linuxvfs.c
fs/bfs/dir.c
fs/binfmt_misc.c
fs/block_dev.c
fs/btrfs/async-thread.c
fs/btrfs/async-thread.h
fs/btrfs/backref.c
fs/btrfs/btrfs_inode.h
fs/btrfs/check-integrity.c
fs/btrfs/compression.c
fs/btrfs/compression.h
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/delayed-inode.c
fs/btrfs/delayed-ref.c
fs/btrfs/delayed-ref.h
fs/btrfs/dev-replace.c
fs/btrfs/disk-io.c
fs/btrfs/disk-io.h
fs/btrfs/export.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/extent_io.h
fs/btrfs/file-item.c
fs/btrfs/file.c
fs/btrfs/free-space-cache.c
fs/btrfs/free-space-cache.h
fs/btrfs/inode-map.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/lzo.c
fs/btrfs/math.h
fs/btrfs/props.c
fs/btrfs/qgroup.c
fs/btrfs/qgroup.h
fs/btrfs/raid56.c
fs/btrfs/relocation.c
fs/btrfs/scrub.c
fs/btrfs/send.c
fs/btrfs/super.c
fs/btrfs/sysfs.c
fs/btrfs/sysfs.h
fs/btrfs/tests/qgroup-tests.c
fs/btrfs/transaction.c
fs/btrfs/transaction.h
fs/btrfs/tree-log.c
fs/btrfs/tree-log.h
fs/btrfs/volumes.c
fs/btrfs/volumes.h
fs/btrfs/xattr.c
fs/btrfs/zlib.c
fs/cachefiles/bind.c
fs/cachefiles/interface.c
fs/cachefiles/namei.c
fs/cachefiles/rdwr.c
fs/cachefiles/security.c
fs/cachefiles/xattr.c
fs/ceph/addr.c
fs/ceph/caps.c
fs/ceph/debugfs.c
fs/ceph/dir.c
fs/ceph/export.c
fs/ceph/file.c
fs/ceph/inode.c
fs/ceph/mds_client.c
fs/ceph/strings.c
fs/ceph/super.c
fs/ceph/super.h
fs/ceph/xattr.c
fs/cifs/cifs_dfs_ref.c
fs/cifs/cifsfs.c
fs/cifs/cifssmb.c
fs/cifs/dir.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/link.c
fs/cifs/misc.c
fs/cifs/readdir.c
fs/cifs/smb1ops.c
fs/cifs/smb2file.c
fs/cifs/smb2misc.c
fs/cifs/smb2ops.c
fs/cifs/xattr.c
fs/coda/cache.c
fs/coda/dir.c
fs/coda/inode.c
fs/coda/pioctl.c
fs/coda/upcall.c
fs/configfs/dir.c
fs/configfs/file.c
fs/configfs/inode.c
fs/configfs/mount.c
fs/dax.c
fs/debugfs/file.c
fs/debugfs/inode.c
fs/devpts/inode.c
fs/direct-io.c
fs/ecryptfs/crypto.c
fs/ecryptfs/dentry.c
fs/ecryptfs/file.c
fs/ecryptfs/inode.c
fs/ecryptfs/kthread.c
fs/ecryptfs/main.c
fs/ecryptfs/mmap.c
fs/efivarfs/inode.c
fs/efivarfs/super.c
fs/efs/namei.c
fs/exofs/dir.c
fs/exofs/inode.c
fs/exofs/namei.c
fs/exofs/super.c
fs/exofs/symlink.c
fs/ext2/dir.c
fs/ext2/ialloc.c
fs/ext2/inode.c
fs/ext2/namei.c
fs/ext2/symlink.c
fs/ext2/xattr.c
fs/ext2/xattr_security.c
fs/ext2/xattr_trusted.c
fs/ext2/xattr_user.c
fs/ext3/ialloc.c
fs/ext3/inode.c
fs/ext3/namei.c
fs/ext3/super.c
fs/ext3/symlink.c
fs/ext3/xattr.c
fs/ext3/xattr_security.c
fs/ext3/xattr_trusted.c
fs/ext3/xattr_user.c
fs/ext4/Kconfig
fs/ext4/crypto_fname.c
fs/ext4/crypto_key.c
fs/ext4/crypto_policy.c
fs/ext4/dir.c
fs/ext4/ext4.h
fs/ext4/ext4_crypto.h
fs/ext4/extents.c
fs/ext4/extents_status.c
fs/ext4/fsync.c
fs/ext4/ialloc.c
fs/ext4/indirect.c
fs/ext4/inline.c
fs/ext4/inode.c
fs/ext4/migrate.c
fs/ext4/namei.c
fs/ext4/resize.c
fs/ext4/super.c
fs/ext4/symlink.c
fs/ext4/xattr.c
fs/ext4/xattr_security.c
fs/ext4/xattr_trusted.c
fs/ext4/xattr_user.c
fs/f2fs/data.c
fs/f2fs/f2fs.h
fs/f2fs/file.c
fs/f2fs/namei.c
fs/f2fs/super.c
fs/f2fs/xattr.c
fs/fat/file.c
fs/fat/namei_msdos.c
fs/fat/namei_vfat.c
fs/fat/nfs.c
fs/freevxfs/vxfs_immed.c
fs/fuse/control.c
fs/fuse/dir.c
fs/fuse/inode.c
fs/gfs2/dentry.c
fs/gfs2/export.c
fs/gfs2/inode.c
fs/gfs2/ops_fstype.c
fs/gfs2/super.c
fs/gfs2/xattr.c
fs/hfs/attr.c
fs/hfs/dir.c
fs/hfs/inode.c
fs/hfs/sysdep.c
fs/hfsplus/dir.c
fs/hfsplus/inode.c
fs/hfsplus/ioctl.c
fs/hfsplus/xattr.c
fs/hostfs/hostfs_kern.c
fs/hpfs/inode.c
fs/hpfs/namei.c
fs/hppfs/hppfs.c
fs/hugetlbfs/inode.c
fs/inode.c
fs/isofs/export.c
fs/jffs2/dir.c
fs/jffs2/fs.c
fs/jffs2/security.c
fs/jffs2/super.c
fs/jffs2/symlink.c
fs/jffs2/xattr.c
fs/jffs2/xattr_trusted.c
fs/jffs2/xattr_user.c
fs/jfs/file.c
fs/jfs/namei.c
fs/jfs/symlink.c
fs/jfs/xattr.c
fs/kernfs/dir.c
fs/kernfs/inode.c
fs/libfs.c
fs/lockd/svcsubs.c
fs/logfs/dir.c
fs/logfs/file.c
fs/minix/dir.c
fs/minix/file.c
fs/minix/inode.c
fs/minix/namei.c
fs/namei.c
fs/ncpfs/dir.c
fs/ncpfs/inode.c
fs/ncpfs/ioctl.c
fs/ncpfs/ncplib_kernel.c
fs/ncpfs/symlink.c
fs/nfs/Makefile
fs/nfs/blocklayout/blocklayout.c
fs/nfs/blocklayout/dev.c
fs/nfs/callback.c
fs/nfs/client.c
fs/nfs/delegation.c
fs/nfs/dir.c
fs/nfs/direct.c
fs/nfs/file.c
fs/nfs/filelayout/filelayout.c
fs/nfs/filelayout/filelayoutdev.c
fs/nfs/flexfilelayout/flexfilelayout.c
fs/nfs/flexfilelayout/flexfilelayoutdev.c
fs/nfs/getroot.c
fs/nfs/idmap.c [deleted file]
fs/nfs/inode.c
fs/nfs/namespace.c
fs/nfs/nfs3acl.c
fs/nfs/nfs3proc.c
fs/nfs/nfs42proc.c
fs/nfs/nfs42xdr.c
fs/nfs/nfs4client.c
fs/nfs/nfs4file.c
fs/nfs/nfs4idmap.c [new file with mode: 0644]
fs/nfs/nfs4idmap.h [new file with mode: 0644]
fs/nfs/nfs4namespace.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/nfs4super.c
fs/nfs/nfs4sysctl.c
fs/nfs/nfs4trace.h
fs/nfs/nfs4xdr.c
fs/nfs/nfstrace.c
fs/nfs/objlayout/objio_osd.c
fs/nfs/pagelist.c
fs/nfs/pnfs.c
fs/nfs/pnfs.h
fs/nfs/pnfs_dev.c
fs/nfs/pnfs_nfs.c
fs/nfs/proc.c
fs/nfs/read.c
fs/nfs/super.c
fs/nfs/symlink.c
fs/nfs/unlink.c
fs/nfs/write.c
fs/nfsd/Kconfig
fs/nfsd/export.c
fs/nfsd/nfs2acl.c
fs/nfsd/nfs3acl.c
fs/nfsd/nfs3proc.c
fs/nfsd/nfs3xdr.c
fs/nfsd/nfs4acl.c
fs/nfsd/nfs4proc.c
fs/nfsd/nfs4recover.c
fs/nfsd/nfs4state.c
fs/nfsd/nfs4xdr.c
fs/nfsd/nfsctl.c
fs/nfsd/nfsd.h
fs/nfsd/nfsfh.c
fs/nfsd/nfsfh.h
fs/nfsd/nfsproc.c
fs/nfsd/nfsxdr.c
fs/nfsd/vfs.c
fs/nfsd/xdr4.h
fs/nilfs2/btree.c
fs/nilfs2/dir.c
fs/nilfs2/inode.c
fs/nilfs2/namei.c
fs/nilfs2/super.c
fs/nsfs.c
fs/ntfs/inode.c
fs/ntfs/namei.c
fs/ocfs2/cluster/heartbeat.c
fs/ocfs2/dcache.c
fs/ocfs2/dir.h
fs/ocfs2/dlm/dlmmaster.c
fs/ocfs2/dlmfs/dlmfs.c
fs/ocfs2/dlmglue.c
fs/ocfs2/export.c
fs/ocfs2/file.c
fs/ocfs2/inode.c
fs/ocfs2/namei.c
fs/ocfs2/refcounttree.c
fs/ocfs2/super.c
fs/ocfs2/xattr.c
fs/omfs/dir.c
fs/omfs/file.c
fs/open.c
fs/pipe.c
fs/posix_acl.c
fs/proc/base.c
fs/proc/fd.c
fs/proc/generic.c
fs/proc/inode.c
fs/proc/namespaces.c
fs/proc/proc_net.c
fs/proc/proc_sysctl.c
fs/proc/root.c
fs/proc/self.c
fs/proc/thread_self.c
fs/pstore/inode.c
fs/qnx6/inode.c
fs/quota/dquot.c
fs/ramfs/file-nommu.c
fs/reiserfs/dir.c
fs/reiserfs/inode.c
fs/reiserfs/namei.c
fs/reiserfs/super.c
fs/reiserfs/xattr.c
fs/reiserfs/xattr.h
fs/reiserfs/xattr_security.c
fs/reiserfs/xattr_trusted.c
fs/reiserfs/xattr_user.c
fs/squashfs/export.c
fs/squashfs/xattr.c
fs/stat.c
fs/sysv/dir.c
fs/sysv/file.c
fs/sysv/itree.c
fs/sysv/namei.c
fs/sysv/symlink.c
fs/ubifs/dir.c
fs/ubifs/file.c
fs/ubifs/journal.c
fs/ubifs/xattr.c
fs/udf/file.c
fs/udf/namei.c
fs/ufs/dir.c
fs/ufs/namei.c
fs/ufs/super.c
fs/ufs/symlink.c
fs/ufs/truncate.c
fs/xfs/libxfs/xfs_alloc.c
fs/xfs/libxfs/xfs_attr_leaf.c
fs/xfs/libxfs/xfs_attr_leaf.h
fs/xfs/libxfs/xfs_bmap.c
fs/xfs/libxfs/xfs_bmap.h
fs/xfs/libxfs/xfs_btree.c
fs/xfs/libxfs/xfs_da_btree.c
fs/xfs/libxfs/xfs_da_format.h
fs/xfs/libxfs/xfs_dir2_data.c
fs/xfs/libxfs/xfs_format.h
fs/xfs/libxfs/xfs_ialloc.c
fs/xfs/libxfs/xfs_sb.c
fs/xfs/xfs_aops.c
fs/xfs/xfs_attr_inactive.c
fs/xfs/xfs_attr_list.c
fs/xfs/xfs_bmap_util.c
fs/xfs/xfs_bmap_util.h
fs/xfs/xfs_buf_item.c
fs/xfs/xfs_discard.c
fs/xfs/xfs_error.c
fs/xfs/xfs_error.h
fs/xfs/xfs_export.c
fs/xfs/xfs_file.c
fs/xfs/xfs_filestream.c
fs/xfs/xfs_fsops.c
fs/xfs/xfs_icache.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_inode.h
fs/xfs/xfs_ioctl.c
fs/xfs/xfs_ioctl32.c
fs/xfs/xfs_iomap.c
fs/xfs/xfs_iops.c
fs/xfs/xfs_iops.h
fs/xfs/xfs_itable.c
fs/xfs/xfs_linux.h
fs/xfs/xfs_log_recover.c
fs/xfs/xfs_mount.c
fs/xfs/xfs_mount.h
fs/xfs/xfs_mru_cache.c
fs/xfs/xfs_pnfs.c
fs/xfs/xfs_pnfs.h
fs/xfs/xfs_qm.c
fs/xfs/xfs_super.c
fs/xfs/xfs_super.h
fs/xfs/xfs_symlink.c
fs/xfs/xfs_trace.h
fs/xfs/xfs_trans.c
fs/xfs/xfs_xattr.c
include/acpi/acpi_io.h
include/acpi/actypes.h
include/acpi/processor.h
include/asm-generic/vmlinux.lds.h
include/dt-bindings/clock/exynos3250.h
include/dt-bindings/clock/exynos5433.h [new file with mode: 0644]
include/dt-bindings/clock/imx6qdl-clock.h
include/dt-bindings/clock/qcom,gcc-ipq806x.h
include/dt-bindings/clock/qcom,gcc-msm8916.h [new file with mode: 0644]
include/dt-bindings/clock/r8a73a4-clock.h [new file with mode: 0644]
include/dt-bindings/clock/r8a7778-clock.h [new file with mode: 0644]
include/dt-bindings/clock/r8a7790-clock.h
include/dt-bindings/clock/r8a7791-clock.h
include/dt-bindings/clock/sh73a0-clock.h
include/dt-bindings/clock/tegra124-car-common.h
include/dt-bindings/dma/jz4780-dma.h [new file with mode: 0644]
include/dt-bindings/media/omap3-isp.h [new file with mode: 0644]
include/dt-bindings/media/xilinx-vip.h [new file with mode: 0644]
include/dt-bindings/reset/qcom,gcc-msm8916.h [new file with mode: 0644]
include/linux/acpi.h
include/linux/acpi_irq.h [new file with mode: 0644]
include/linux/amba/xilinx_dma.h [deleted file]
include/linux/arm-cci.h
include/linux/async_tx.h
include/linux/ceph/ceph_features.h
include/linux/ceph/ceph_fs.h
include/linux/ceph/debugfs.h
include/linux/ceph/libceph.h
include/linux/ceph/osdmap.h
include/linux/clk-provider.h
include/linux/clk/at91_pmc.h
include/linux/clk/shmobile.h
include/linux/clk/ti.h
include/linux/clocksource.h
include/linux/compiler-gcc.h
include/linux/compiler-intel.h
include/linux/compiler.h
include/linux/console.h
include/linux/crush/crush.h
include/linux/dma-buf.h
include/linux/dma/hsu.h [new file with mode: 0644]
include/linux/dma/xilinx_dma.h [new file with mode: 0644]
include/linux/dmaengine.h
include/linux/falloc.h
include/linux/fixp-arith.h
include/linux/fs.h
include/linux/hyperv.h
include/linux/intel-iommu.h
include/linux/io.h
include/linux/irqchip/arm-gic-acpi.h [new file with mode: 0644]
include/linux/jz4780-nemc.h [new file with mode: 0644]
include/linux/kconfig.h
include/linux/kexec.h
include/linux/lguest.h
include/linux/mfd/arizona/core.h
include/linux/mfd/cros_ec.h
include/linux/mfd/syscon/atmel-st.h [new file with mode: 0644]
include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
include/linux/mfd/tmio.h
include/linux/miscdevice.h
include/linux/mlx4/device.h
include/linux/mm.h
include/linux/mmc/card.h
include/linux/mmc/sh_mobile_sdhi.h
include/linux/mtd/map.h
include/linux/mtd/spi-nor.h
include/linux/netdevice.h
include/linux/netfilter_bridge.h
include/linux/nfs4.h
include/linux/nfs_fs.h
include/linux/nfs_idmap.h [deleted file]
include/linux/nfs_xdr.h
include/linux/nilfs2_fs.h
include/linux/of.h
include/linux/of_fdt.h
include/linux/of_irq.h
include/linux/omap-gpmc.h
include/linux/pci_ids.h
include/linux/platform_data/dma-hsu.h [new file with mode: 0644]
include/linux/platform_data/dma-imx-sdma.h
include/linux/platform_data/mmc-msm_sdcc.h [deleted file]
include/linux/platform_data/msm_serial_hs.h [deleted file]
include/linux/platform_data/serial-imx.h
include/linux/qcom_scm.h [new file with mode: 0644]
include/linux/raid/pq.h
include/linux/rhashtable.h
include/linux/rtnetlink.h
include/linux/sched.h
include/linux/serial_8250.h
include/linux/serial_core.h
include/linux/serial_mfd.h [deleted file]
include/linux/shdma-base.h
include/linux/skbuff.h
include/linux/sunrpc/msg_prot.h
include/linux/sunrpc/xprtrdma.h
include/linux/tty.h
include/linux/usb_usual.h
include/linux/util_macros.h
include/linux/virtio.h
include/linux/virtio_config.h
include/linux/virtio_ring.h
include/linux/wl12xx.h
include/media/adv7604.h
include/media/davinci/vpfe_capture.h
include/media/media-entity.h
include/media/mt9p031.h
include/media/omap3isp.h
include/media/ov2659.h [new file with mode: 0644]
include/media/saa7146_vv.h
include/media/v4l2-clk.h
include/media/v4l2-dev.h
include/media/v4l2-device.h
include/media/v4l2-ioctl.h
include/media/v4l2-of.h
include/media/v4l2-subdev.h
include/media/videobuf2-core.h
include/net/bonding.h
include/net/inet_connection_sock.h
include/net/request_sock.h
include/rdma/ib_addr.h
include/rdma/ib_cm.h
include/rdma/iw_portmap.h
include/scsi/scsi_devinfo.h
include/sound/designware_i2s.h
include/sound/emu10k1.h
include/sound/soc-dapm.h
include/sound/soc.h
include/sound/spear_dma.h
include/target/iscsi/iscsi_target_core.h
include/target/target_core_base.h
include/target/target_core_configfs.h
include/target/target_core_fabric.h
include/target/target_core_fabric_configfs.h
include/trace/events/btrfs.h
include/trace/events/clk.h [new file with mode: 0644]
include/trace/events/ext3.h
include/trace/events/ext4.h
include/uapi/linux/Kbuild
include/uapi/linux/am437x-vpfe.h
include/uapi/linux/falloc.h
include/uapi/linux/kvm.h
include/uapi/linux/media-bus-format.h
include/uapi/linux/media.h
include/uapi/linux/nfs4.h
include/uapi/linux/nfs_idmap.h
include/uapi/linux/nfsd/debug.h
include/uapi/linux/nfsd/export.h
include/uapi/linux/raid/md_p.h
include/uapi/linux/raid/md_u.h
include/uapi/linux/serial_reg.h
include/uapi/linux/target_core_user.h
include/uapi/linux/v4l2-dv-timings.h
include/uapi/linux/v4l2-subdev.h
include/uapi/linux/videodev2.h
include/uapi/linux/virtio_balloon.h
include/uapi/linux/virtio_ids.h
include/uapi/linux/virtio_input.h [new file with mode: 0644]
include/uapi/linux/virtio_ring.h
include/uapi/linux/xilinx-v4l2-controls.h [new file with mode: 0644]
include/uapi/rdma/rdma_netlink.h
include/uapi/sound/asound.h
include/xen/grant_table.h
include/xen/xen-ops.h
ipc/mqueue.c
ipc/shm.c
kernel/Makefile
kernel/audit.c
kernel/audit.h
kernel/audit_tree.c
kernel/audit_watch.c
kernel/auditsc.c
kernel/bpf/core.c
kernel/kexec.c
kernel/module.c
kernel/params.c
kernel/printk/printk.c
kernel/rcu/tree.c
kernel/relay.c
kernel/sched/core.c
kernel/sched/idle.c
kernel/time/clockevents.c
kernel/trace/trace.c
kernel/trace/trace_events.c
kernel/trace/trace_functions_graph.c
kernel/trace/trace_uprobe.c
lib/Kconfig.debug
lib/Kconfig.kasan
lib/devres.c
lib/find_last_bit.c [deleted file]
lib/iommu-common.c
lib/raid6/algos.c
lib/raid6/altivec.uc
lib/raid6/avx2.c
lib/raid6/int.uc
lib/raid6/mmx.c
lib/raid6/neon.c
lib/raid6/sse1.c
lib/raid6/sse2.c
lib/raid6/test/test.c
lib/raid6/tilegx.uc
lib/rhashtable.c
lib/string.c
mm/hwpoison-inject.c
mm/memory-failure.c
mm/shmem.c
net/bridge/br_mdb.c
net/bridge/br_netlink.c
net/bridge/br_private.h
net/ceph/ceph_common.c
net/ceph/crush/crush.c
net/ceph/crush/crush_ln_table.h [new file with mode: 0644]
net/ceph/crush/mapper.c
net/ceph/debugfs.c
net/ceph/messenger.c
net/ceph/osdmap.c
net/core/dev.c
net/core/rtnetlink.c
net/core/skbuff.c
net/dccp/ipv4.c
net/dccp/ipv6.c
net/dccp/minisocks.c
net/dsa/dsa.c
net/ipv4/inet_connection_sock.c
net/ipv4/ip_forward.c
net/ipv4/ping.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_minisocks.c
net/ipv4/tcp_output.c
net/ipv6/ip6_gre.c
net/ipv6/tcp_ipv6.c
net/mpls/af_mpls.c
net/mpls/internal.h
net/netfilter/nf_tables_api.c
net/netfilter/nft_reject.c
net/netfilter/nft_reject_inet.c
net/netlink/af_netlink.c
net/sched/act_connmark.c
net/socket.c
net/sunrpc/rpc_pipe.c
net/sunrpc/sched.c
net/sunrpc/xprt.c
net/sunrpc/xprtrdma/Makefile
net/sunrpc/xprtrdma/fmr_ops.c [new file with mode: 0644]
net/sunrpc/xprtrdma/frwr_ops.c [new file with mode: 0644]
net/sunrpc/xprtrdma/physical_ops.c [new file with mode: 0644]
net/sunrpc/xprtrdma/rpc_rdma.c
net/sunrpc/xprtrdma/transport.c
net/sunrpc/xprtrdma/verbs.c
net/sunrpc/xprtrdma/xprt_rdma.h
net/tipc/bearer.c
net/tipc/link.c
net/tipc/server.c
net/tipc/socket.c
net/unix/af_unix.c
net/unix/diag.c
net/unix/garbage.c
scripts/Makefile.lib
scripts/check_extable.sh [new file with mode: 0755]
scripts/checkkconfigsymbols.py [changed mode: 0644->0755]
scripts/mod/modpost.c
security/apparmor/apparmorfs.c
security/apparmor/file.c
security/apparmor/lsm.c
security/commoncap.c
security/inode.c
security/integrity/evm/evm_crypto.c
security/integrity/evm/evm_main.c
security/integrity/ima/ima_appraise.c
security/lsm_audit.c
security/security.c
security/selinux/hooks.c
security/selinux/selinuxfs.c
security/smack/smack_lsm.c
security/smack/smackfs.c
security/tomoyo/condition.c
security/tomoyo/realpath.c
sound/oss/sequencer.c
sound/pci/emu10k1/emu10k1.c
sound/pci/emu10k1/emu10k1_callback.c
sound/pci/emu10k1/emu10k1_main.c
sound/pci/emu10k1/emupcm.c
sound/pci/emu10k1/memory.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_controller.h
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_i915.c
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_proc.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/thinkpad_helper.c
sound/pci/intel8x0.c
sound/soc/codecs/arizona.c
sound/soc/codecs/rt5645.c
sound/soc/codecs/rt5677.c
sound/soc/codecs/tfa9879.c
sound/soc/fsl/fsl_ssi.c
sound/soc/intel/Makefile
sound/soc/intel/baytrail/sst-baytrail-ipc.c
sound/soc/intel/haswell/sst-haswell-ipc.c
sound/soc/qcom/lpass-cpu.c
sound/soc/samsung/s3c24xx-i2s.c
sound/soc/sh/fsi.c
sound/soc/sh/rcar/dma.c
sound/synth/emux/emux_oss.c
sound/synth/emux/emux_seq.c
sound/usb/format.c
sound/usb/quirks-table.h
tools/hv/Makefile
tools/hv/hv_vss_daemon.c
tools/lib/api/Makefile
tools/lib/traceevent/event-parse.c
tools/perf/bench/futex-requeue.c
tools/perf/bench/numa.c
tools/perf/builtin-kmem.c
tools/perf/builtin-report.c
tools/perf/builtin-top.c
tools/perf/builtin-trace.c
tools/perf/util/probe-event.c
tools/perf/util/probe-finder.c
tools/power/cpupower/utils/helpers/pci.c
tools/testing/selftests/powerpc/pmu/Makefile
tools/testing/selftests/powerpc/tm/Makefile
tools/testing/selftests/x86/Makefile
tools/testing/selftests/x86/run_x86_tests.sh
tools/testing/selftests/x86/sysret_ss_attrs.c [new file with mode: 0644]
tools/testing/selftests/x86/thunks.S [new file with mode: 0644]
virt/kvm/arm/vgic.c
virt/kvm/kvm_main.c

diff --git a/CREDITS b/CREDITS
index 2ef5dceef32455ae6afac5d74db1000912fd0b9f..40cc4bfb34dbec35f2a03f4946e7868fd829c8d1 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -2049,6 +2049,10 @@ D: pirq addr, CS5535 alsa audio driver
 S: Gurgaon, India
 S: Kuala Lumpur, Malaysia
 
+N: Mohit Kumar
+D: ST Microelectronics SPEAr13xx PCI host bridge driver
+D: Synopsys Designware PCI host bridge driver
+
 N: Gabor Kuti
 M: seasons@falcon.sch.bme.hu
 M: seasons@makosteszta.sote.hu
index 76ee192f80a080b12f319d2e6624f38606f4efa7..3b5c3bca9186d13e8cf5f1911b2fc88424c6970f 100644 (file)
@@ -222,3 +222,13 @@ Description:
                The number of blocks that are marked as reserved, if any, in
                this partition. These are typically used to store the in-flash
                bad block table (BBT).
+
+What:          /sys/class/mtd/mtdX/offset
+Date:          March 2015
+KernelVersion: 4.1
+Contact:       linux-mtd@lists.infradead.org
+Description:
+               For a partition, the offset of that partition from the start
+               of the master device in bytes. This attribute is absent on
+               main devices, so it can be used to distinguish between
+               partitions and devices that aren't partitions.
index ca9c71a531c5f86c1ca281f6e9ca5d2129da0c8a..eed922ef42e533ae9bf16da6d224a50d2b46e16b 100644 (file)
@@ -8,9 +8,11 @@ Description:   This file controls the keyboard backlight operation mode, valid
                        * 0x2  -> AUTO (also called TIMER)
                        * 0x8  -> ON
                        * 0x10 -> OFF
-               Note that the kernel 3.16 onwards this file accepts all listed
+               Note that from kernel 3.16 onwards this file accepts all listed
                parameters, kernel 3.15 only accepts the first two (FN-Z and
                AUTO).
+               Also note that toggling this value on type 1 devices, requires
+               a reboot for changes to take effect.
 Users:         KToshiba
 
 What:          /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/kbd_backlight_timeout
@@ -67,15 +69,72 @@ Description:        This file shows the current keyboard backlight type,
                        * 2 -> Type 2, supporting modes TIMER, ON and OFF
 Users:         KToshiba
 
+What:          /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/usb_sleep_charge
+Date:          January 23, 2015
+KernelVersion: 4.0
+Contact:       Azael Avalos <coproscefalo@gmail.com>
+Description:   This file controls the USB Sleep & Charge charging mode, which
+               can be:
+                       * 0 -> Disabled         (0x00)
+                       * 1 -> Alternate        (0x09)
+                       * 2 -> Auto             (0x21)
+                       * 3 -> Typical          (0x11)
+               Note that from kernel 4.1 onwards this file accepts all listed
+               values, kernel 4.0 only supports the first three.
+               Note that this feature only works when connected to power, if
+               you want to use it under battery, see the entry named
+               "sleep_functions_on_battery"
+Users:         KToshiba
+
+What:          /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/sleep_functions_on_battery
+Date:          January 23, 2015
+KernelVersion: 4.0
+Contact:       Azael Avalos <coproscefalo@gmail.com>
+Description:   This file controls the USB Sleep Functions under battery, and
+               set the level at which point they will be disabled, accepted
+               values can be:
+                       * 0     -> Disabled
+                       * 1-100 -> Battery level to disable sleep functions
+               Currently it prints two values, the first one indicates if the
+               feature is enabled or disabled, while the second one shows the
+               current battery level set.
+               Note that when the value is set to disabled, the sleep function
+               will only work when connected to power.
+Users:         KToshiba
+
+What:          /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/usb_rapid_charge
+Date:          January 23, 2015
+KernelVersion: 4.0
+Contact:       Azael Avalos <coproscefalo@gmail.com>
+Description:   This file controls the USB Rapid Charge state, which can be:
+                       * 0 -> Disabled
+                       * 1 -> Enabled
+               Note that toggling this value requires a reboot for changes to
+               take effect.
+Users:         KToshiba
+
+What:          /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/usb_sleep_music
+Date:          January 23, 2015
+KernelVersion: 4.0
+Contact:       Azael Avalos <coproscefalo@gmail.com>
+Description:   This file controls the Sleep & Music state, which values can be:
+                       * 0 -> Disabled
+                       * 1 -> Enabled
+               Note that this feature only works when connected to power, if
+               you want to use it under battery, see the entry named
+               "sleep_functions_on_battery"
+Users:         KToshiba
+
 What:          /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/version
-Date:          February, 2015
-KernelVersion: 3.20
+Date:          February 12, 2015
+KernelVersion: 4.0
 Contact:       Azael Avalos <coproscefalo@gmail.com>
 Description:   This file shows the current version of the driver
+Users:         KToshiba
 
 What:          /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/fan
-Date:          February, 2015
-KernelVersion: 3.20
+Date:          February 12, 2015
+KernelVersion: 4.0
 Contact:       Azael Avalos <coproscefalo@gmail.com>
 Description:   This file controls the state of the internal fan, valid
                values are:
@@ -83,8 +142,8 @@ Description: This file controls the state of the internal fan, valid
                        * 1 -> ON
 
 What:          /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/kbd_function_keys
-Date:          February, 2015
-KernelVersion: 3.20
+Date:          February 12, 2015
+KernelVersion: 4.0
 Contact:       Azael Avalos <coproscefalo@gmail.com>
 Description:   This file controls the Special Functions (hotkeys) operation
                mode, valid values are:
@@ -94,21 +153,29 @@ Description:       This file controls the Special Functions (hotkeys) operation
                and the hotkeys are accessed via FN-F{1-12}.
                In the "Special Functions" mode, the F{1-12} keys trigger the
                hotkey and the F{1-12} keys are accessed via FN-F{1-12}.
+               Note that toggling this value requires a reboot for changes to
+               take effect.
+Users:         KToshiba
 
 What:          /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/panel_power_on
-Date:          February, 2015
-KernelVersion: 3.20
+Date:          February 12, 2015
+KernelVersion: 4.0
 Contact:       Azael Avalos <coproscefalo@gmail.com>
 Description:   This file controls whether the laptop should turn ON whenever
                the LID is opened, valid values are:
                        * 0 -> Disabled
                        * 1 -> Enabled
+               Note that toggling this value requires a reboot for changes to
+               take effect.
+Users:         KToshiba
 
 What:          /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/usb_three
-Date:          February, 2015
-KernelVersion: 3.20
+Date:          February 12, 2015
+KernelVersion: 4.0
 Contact:       Azael Avalos <coproscefalo@gmail.com>
-Description:   This file controls whether the USB 3 functionality, valid
-               values are:
+Description:   This file controls the USB 3 functionality, valid values are:
                        * 0 -> Disabled (Acts as a regular USB 2)
                        * 1 -> Enabled (Full USB 3 functionality)
+               Note that toggling this value requires a reboot for changes to
+               take effect.
+Users:         KToshiba
diff --git a/Documentation/ABI/testing/sysfs-platform-dell-laptop b/Documentation/ABI/testing/sysfs-platform-dell-laptop
new file mode 100644 (file)
index 0000000..8c6a0b8
--- /dev/null
@@ -0,0 +1,69 @@
+What:          /sys/class/leds/dell::kbd_backlight/als_enabled
+Date:          December 2014
+KernelVersion: 3.19
+Contact:       Gabriele Mazzotta <gabriele.mzt@gmail.com>,
+               Pali Rohár <pali.rohar@gmail.com>
+Description:
+               This file allows to control the automatic keyboard
+               illumination mode on some systems that have an ambient
+               light sensor. Write 1 to this file to enable the auto
+               mode, 0 to disable it.
+
+What:          /sys/class/leds/dell::kbd_backlight/als_setting
+Date:          December 2014
+KernelVersion: 3.19
+Contact:       Gabriele Mazzotta <gabriele.mzt@gmail.com>,
+               Pali Rohár <pali.rohar@gmail.com>
+Description:
+               This file allows to specifiy the on/off threshold value,
+               as reported by the ambient light sensor.
+
+What:          /sys/class/leds/dell::kbd_backlight/start_triggers
+Date:          December 2014
+KernelVersion: 3.19
+Contact:       Gabriele Mazzotta <gabriele.mzt@gmail.com>,
+               Pali Rohár <pali.rohar@gmail.com>
+Description:
+               This file allows to control the input triggers that
+               turn on the keyboard backlight illumination that is
+               disabled because of inactivity.
+               Read the file to see the triggers available. The ones
+               enabled are preceded by '+', those disabled by '-'.
+
+               To enable a trigger, write its name preceded by '+' to
+               this file. To disable a trigger, write its name preceded
+               by '-' instead.
+
+               For example, to enable the keyboard as trigger run:
+                   echo +keyboard > /sys/class/leds/dell::kbd_backlight/start_triggers
+               To disable it:
+                   echo -keyboard > /sys/class/leds/dell::kbd_backlight/start_triggers
+
+               Note that not all the available triggers can be configured.
+
+What:          /sys/class/leds/dell::kbd_backlight/stop_timeout
+Date:          December 2014
+KernelVersion: 3.19
+Contact:       Gabriele Mazzotta <gabriele.mzt@gmail.com>,
+               Pali Rohár <pali.rohar@gmail.com>
+Description:
+               This file allows to specify the interval after which the
+               keyboard illumination is disabled because of inactivity.
+               The timeouts are expressed in seconds, minutes, hours and
+               days, for which the symbols are 's', 'm', 'h' and 'd'
+               respectively.
+
+               To configure the timeout, write to this file a value along
+               with any the above units. If no unit is specified, the value
+               is assumed to be expressed in seconds.
+
+               For example, to set the timeout to 10 minutes run:
+                   echo 10m > /sys/class/leds/dell::kbd_backlight/stop_timeout
+
+               Note that when this file is read, the returned value might be
+               expressed in a different unit than the one used when the timeout
+               was set.
+
+               Also note that only some timeouts are supported and that
+               some systems might fall back to a specific timeout in case
+               an invalid timeout is written to this file.
index 350dfb3d71ea736aeeb379dcb69256b561c8a734..a0aef85d33c1f94041d46bd7f48db037385522cc 100644 (file)
@@ -2491,7 +2491,7 @@ that used it. It was originally scheduled for removal in 2.6.35.
         </listitem>
         <listitem>
          <para>Added <constant>V4L2_EVENT_CTRL_CH_RANGE</constant> control event
-         changes flag. See <xref linkend="changes-flags"/>.</para>
+         changes flag. See <xref linkend="ctrl-changes-flags"/>.</para>
         </listitem>
       </orderedlist>
     </section>
index 116c301656e0bde1732c2e0dbe124cc68285ad8d..5872f8bbf7747efb848daf103b3d70271b18e1c6 100644 (file)
          <row>
            <entry></entry>
            <entry>struct</entry>
-           <entry><structfield>v4l</structfield></entry>
+           <entry><structfield>dev</structfield></entry>
            <entry></entry>
-           <entry>Valid for V4L sub-devices and nodes only.</entry>
+           <entry>Valid for (sub-)devices that create a single device node.</entry>
          </row>
          <row>
            <entry></entry>
            <entry></entry>
            <entry>__u32</entry>
            <entry><structfield>major</structfield></entry>
-           <entry>V4L device node major number. For V4L sub-devices with no
-           device node, set by the driver to 0.</entry>
+           <entry>Device node major number.</entry>
          </row>
          <row>
            <entry></entry>
            <entry></entry>
            <entry>__u32</entry>
            <entry><structfield>minor</structfield></entry>
-           <entry>V4L device node minor number. For V4L sub-devices with no
-           device node, set by the driver to 0.</entry>
-         </row>
-         <row>
-           <entry></entry>
-           <entry>struct</entry>
-           <entry><structfield>fb</structfield></entry>
-           <entry></entry>
-           <entry>Valid for frame buffer nodes only.</entry>
-         </row>
-         <row>
-           <entry></entry>
-           <entry></entry>
-           <entry>__u32</entry>
-           <entry><structfield>major</structfield></entry>
-           <entry>Frame buffer device node major number.</entry>
-         </row>
-         <row>
-           <entry></entry>
-           <entry></entry>
-           <entry>__u32</entry>
-           <entry><structfield>minor</structfield></entry>
-           <entry>Frame buffer device node minor number.</entry>
-         </row>
-         <row>
-           <entry></entry>
-           <entry>struct</entry>
-           <entry><structfield>alsa</structfield></entry>
-           <entry></entry>
-           <entry>Valid for ALSA devices only.</entry>
-         </row>
-         <row>
-           <entry></entry>
-           <entry></entry>
-           <entry>__u32</entry>
-           <entry><structfield>card</structfield></entry>
-           <entry>ALSA card number</entry>
-         </row>
-         <row>
-           <entry></entry>
-           <entry></entry>
-           <entry>__u32</entry>
-           <entry><structfield>device</structfield></entry>
-           <entry>ALSA device number</entry>
-         </row>
-         <row>
-           <entry></entry>
-           <entry></entry>
-           <entry>__u32</entry>
-           <entry><structfield>subdevice</structfield></entry>
-           <entry>ALSA sub-device number</entry>
-         </row>
-         <row>
-           <entry></entry>
-           <entry>int</entry>
-           <entry><structfield>dvb</structfield></entry>
-           <entry></entry>
-           <entry>DVB card number</entry>
+           <entry>Device node minor number.</entry>
          </row>
          <row>
            <entry></entry>
            <entry>__u8</entry>
-           <entry><structfield>raw</structfield>[180]</entry>
+           <entry><structfield>raw</structfield>[184]</entry>
            <entry></entry>
            <entry></entry>
          </row>
            <entry>ALSA card</entry>
          </row>
          <row>
-           <entry><constant>MEDIA_ENT_T_DEVNODE_DVB</constant></entry>
-           <entry>DVB card</entry>
+           <entry><constant>MEDIA_ENT_T_DEVNODE_DVB_FE</constant></entry>
+           <entry>DVB frontend devnode</entry>
+         </row>
+         <row>
+           <entry><constant>MEDIA_ENT_T_DEVNODE_DVB_DEMUX</constant></entry>
+           <entry>DVB demux devnode</entry>
+         </row>
+         <row>
+           <entry><constant>MEDIA_ENT_T_DEVNODE_DVB_DVR</constant></entry>
+           <entry>DVB DVR devnode</entry>
+         </row>
+         <row>
+           <entry><constant>MEDIA_ENT_T_DEVNODE_DVB_CA</constant></entry>
+           <entry>DVB CAM devnode</entry>
+         </row>
+         <row>
+           <entry><constant>MEDIA_ENT_T_DEVNODE_DVB_NET</constant></entry>
+           <entry>DVB network devnode</entry>
          </row>
          <row>
            <entry><constant>MEDIA_ENT_T_V4L2_SUBDEV</constant></entry>
            it in some digital video standard, with appropriate embedded timing
            signals.</entry>
          </row>
+         <row>
+           <entry><constant>MEDIA_ENT_T_V4L2_SUBDEV_TUNER</constant></entry>
+           <entry>TV and/or radio tuner</entry>
+         </row>
        </tbody>
       </tgroup>
     </table>
index 6ab4f0f3db64abdc9de76ff3ccf458881f9b49e2..b60fb935b91b8b9282344fd5b17a3650ce150800 100644 (file)
@@ -303,45 +303,6 @@ for a pixel lie next to each other in memory.</para>
            <entry>b<subscript>1</subscript></entry>
            <entry>b<subscript>0</subscript></entry>
          </row>
-         <row id="V4L2-PIX-FMT-BGR666">
-           <entry><constant>V4L2_PIX_FMT_BGR666</constant></entry>
-           <entry>'BGRH'</entry>
-           <entry></entry>
-           <entry>b<subscript>5</subscript></entry>
-           <entry>b<subscript>4</subscript></entry>
-           <entry>b<subscript>3</subscript></entry>
-           <entry>b<subscript>2</subscript></entry>
-           <entry>b<subscript>1</subscript></entry>
-           <entry>b<subscript>0</subscript></entry>
-           <entry>g<subscript>5</subscript></entry>
-           <entry>g<subscript>4</subscript></entry>
-           <entry></entry>
-           <entry>g<subscript>3</subscript></entry>
-           <entry>g<subscript>2</subscript></entry>
-           <entry>g<subscript>1</subscript></entry>
-           <entry>g<subscript>0</subscript></entry>
-           <entry>r<subscript>5</subscript></entry>
-           <entry>r<subscript>4</subscript></entry>
-           <entry>r<subscript>3</subscript></entry>
-           <entry>r<subscript>2</subscript></entry>
-           <entry></entry>
-           <entry>r<subscript>1</subscript></entry>
-           <entry>r<subscript>0</subscript></entry>
-           <entry></entry>
-           <entry></entry>
-           <entry></entry>
-           <entry></entry>
-           <entry></entry>
-           <entry></entry>
-           <entry></entry>
-           <entry></entry>
-           <entry></entry>
-           <entry></entry>
-           <entry></entry>
-           <entry></entry>
-           <entry></entry>
-           <entry></entry>
-         </row>
          <row id="V4L2-PIX-FMT-BGR24">
            <entry><constant>V4L2_PIX_FMT_BGR24</constant></entry>
            <entry>'BGR3'</entry>
@@ -404,6 +365,46 @@ for a pixel lie next to each other in memory.</para>
            <entry>b<subscript>1</subscript></entry>
            <entry>b<subscript>0</subscript></entry>
          </row>
+         <row id="V4L2-PIX-FMT-BGR666">
+           <entry><constant>V4L2_PIX_FMT_BGR666</constant></entry>
+           <entry>'BGRH'</entry>
+           <entry></entry>
+           <entry>b<subscript>5</subscript></entry>
+           <entry>b<subscript>4</subscript></entry>
+           <entry>b<subscript>3</subscript></entry>
+           <entry>b<subscript>2</subscript></entry>
+           <entry>b<subscript>1</subscript></entry>
+           <entry>b<subscript>0</subscript></entry>
+           <entry>g<subscript>5</subscript></entry>
+           <entry>g<subscript>4</subscript></entry>
+           <entry></entry>
+           <entry>g<subscript>3</subscript></entry>
+           <entry>g<subscript>2</subscript></entry>
+           <entry>g<subscript>1</subscript></entry>
+           <entry>g<subscript>0</subscript></entry>
+           <entry>r<subscript>5</subscript></entry>
+           <entry>r<subscript>4</subscript></entry>
+           <entry>r<subscript>3</subscript></entry>
+           <entry>r<subscript>2</subscript></entry>
+           <entry></entry>
+           <entry>r<subscript>1</subscript></entry>
+           <entry>r<subscript>0</subscript></entry>
+           <entry>-</entry>
+           <entry>-</entry>
+           <entry>-</entry>
+           <entry>-</entry>
+           <entry>-</entry>
+           <entry>-</entry>
+           <entry></entry>
+           <entry>-</entry>
+           <entry>-</entry>
+           <entry>-</entry>
+           <entry>-</entry>
+           <entry>-</entry>
+           <entry>-</entry>
+           <entry>-</entry>
+           <entry>-</entry>
+         </row>
          <row id="V4L2-PIX-FMT-ABGR32">
            <entry><constant>V4L2_PIX_FMT_ABGR32</constant></entry>
            <entry>'AR24'</entry>
index 19727ab4c75752035bc59c89b693a0a3242c95cf..7803b8c41b45d2ffd2000d91abf8152886dd2654 100644 (file)
@@ -38,10 +38,10 @@ columns and rows.</para>
                    </row>
                    <row>
                      <entry>start&nbsp;+&nbsp;4:</entry>
-                     <entry>R<subscript>10</subscript></entry>
-                     <entry>B<subscript>11</subscript></entry>
-                     <entry>R<subscript>12</subscript></entry>
-                     <entry>B<subscript>13</subscript></entry>
+                     <entry>B<subscript>10</subscript></entry>
+                     <entry>G<subscript>11</subscript></entry>
+                     <entry>B<subscript>12</subscript></entry>
+                     <entry>G<subscript>13</subscript></entry>
                    </row>
                    <row>
                      <entry>start&nbsp;+&nbsp;8:</entry>
@@ -52,10 +52,10 @@ columns and rows.</para>
                    </row>
                    <row>
                      <entry>start&nbsp;+&nbsp;12:</entry>
-                     <entry>R<subscript>30</subscript></entry>
-                     <entry>B<subscript>31</subscript></entry>
-                     <entry>R<subscript>32</subscript></entry>
-                     <entry>B<subscript>33</subscript></entry>
+                     <entry>B<subscript>30</subscript></entry>
+                     <entry>G<subscript>31</subscript></entry>
+                     <entry>B<subscript>32</subscript></entry>
+                     <entry>G<subscript>33</subscript></entry>
                    </row>
                  </tbody>
                </tgroup>
index 30aa63581fe33d224f060acab75f9faef3b10c3e..a8cc102cde4fc3e5b446822cfb66f5493523ef38 100644 (file)
@@ -38,7 +38,7 @@
        <title>Byte Order.</title>
        <para>Each cell is one byte.
          <informaltable frame="topbot" colsep="1" rowsep="1">
-           <tgroup cols="5" align="center" border="1">
+           <tgroup cols="5" align="center">
              <colspec align="left" colwidth="2*" />
              <tbody valign="top">
                <row>
index 60308f1eefdfea59a33d83f30d32747c8f5c1aa4..e781cc61786c52b93f3f2973110f6040c56dac0e 100644 (file)
@@ -29,12 +29,12 @@ and Cr planes have half as many pad bytes after their rows. In other
 words, two Cx rows (including padding) is exactly as long as one Y row
 (including padding).</para>
 
-       <para><constant>V4L2_PIX_FMT_NV12M</constant> is intended to be
+       <para><constant>V4L2_PIX_FMT_YUV420M</constant> is intended to be
 used only in drivers and applications that support the multi-planar API,
 described in <xref linkend="planar-apis"/>. </para>
 
        <example>
-         <title><constant>V4L2_PIX_FMT_YVU420M</constant> 4 &times; 4
+         <title><constant>V4L2_PIX_FMT_YUV420M</constant> 4 &times; 4
 pixel image</title>
 
          <formalpara>
index 5e0352c5032414bf7e89ed34ed4c1b875998798d..fcde4e20205e18885419176491f0fec863e87dfd 100644 (file)
@@ -80,9 +80,9 @@ padding bytes after the last line of an image cross a system page
 boundary. Input devices may write padding bytes, the value is
 undefined. Output devices ignore the contents of padding
 bytes.</para><para>When the image format is planar the
-<structfield>bytesperline</structfield> value applies to the largest
+<structfield>bytesperline</structfield> value applies to the first
 plane and is divided by the same factor as the
-<structfield>width</structfield> field for any smaller planes. For
+<structfield>width</structfield> field for the other planes. For
 example the Cb and Cr planes of a YUV 4:2:0 image have half as many
 padding bytes following each line as the Y plane. To avoid ambiguities
 drivers must return a <structfield>bytesperline</structfield> value
@@ -182,14 +182,14 @@ see <xref linkend="colorspaces" />.</entry>
           </entry>
         </row>
         <row>
-          <entry>__u16</entry>
+          <entry>__u32</entry>
           <entry><structfield>bytesperline</structfield></entry>
           <entry>Distance in bytes between the leftmost pixels in two adjacent
             lines. See &v4l2-pix-format;.</entry>
         </row>
         <row>
           <entry>__u16</entry>
-          <entry><structfield>reserved[7]</structfield></entry>
+          <entry><structfield>reserved[6]</structfield></entry>
           <entry>Reserved for future extensions. Should be zeroed by the
            application.</entry>
         </row>
@@ -483,8 +483,8 @@ is the Y'CbCr encoding identifier (&v4l2-ycbcr-encoding;) to specify non-standar
 Y'CbCr encodings and the third is the quantization identifier (&v4l2-quantization;)
 to specify non-standard quantization methods. Most of the time only the colorspace
 field of &v4l2-pix-format; or &v4l2-pix-format-mplane; needs to be filled in. Note
-that the default R'G'B' quantization is always full range for all colorspaces,
-so this won't be mentioned explicitly for each colorspace description.</para>
+that the default R'G'B' quantization is full range for all colorspaces except for
+BT.2020 which uses limited range R'G'B' quantization.</para>
 
     <table pgwide="1" frame="none" id="v4l2-colorspace">
       <title>V4L2 Colorspaces</title>
@@ -598,7 +598,8 @@ so this won't be mentioned explicitly for each colorspace description.</para>
          <row>
            <entry><constant>V4L2_QUANTIZATION_DEFAULT</constant></entry>
            <entry>Use the default quantization encoding as defined by the colorspace.
-This is always full range for R'G'B' and usually limited range for Y'CbCr.</entry>
+This is always full range for R'G'B' (except for the BT.2020 colorspace) and usually
+limited range for Y'CbCr.</entry>
          </row>
          <row>
            <entry><constant>V4L2_QUANTIZATION_FULL_RANGE</constant></entry>
@@ -620,8 +621,8 @@ is mapped to [16&hellip;235]. Cb and Cr are mapped from [-0.5&hellip;0.5] to [16
 
   <section>
     <title>Detailed Colorspace Descriptions</title>
-    <section>
-      <title id="col-smpte-170m">Colorspace SMPTE 170M (<constant>V4L2_COLORSPACE_SMPTE170M</constant>)</title>
+    <section id="col-smpte-170m">
+      <title>Colorspace SMPTE 170M (<constant>V4L2_COLORSPACE_SMPTE170M</constant>)</title>
       <para>The <xref linkend="smpte170m" /> standard defines the colorspace used by NTSC and PAL and by SDTV
 in general. The default Y'CbCr encoding is <constant>V4L2_YCBCR_ENC_601</constant>.
 The default Y'CbCr quantization is limited range. The chromaticities of the primary colors and
@@ -666,8 +667,7 @@ as the SMPTE C set, so this colorspace is sometimes called SMPTE C as well.</par
       <variablelist>
        <varlistentry>
           <term>The transfer function defined for SMPTE 170M is the same as the
-one defined in Rec. 709. Normally L is in the range [0&hellip;1], but for the extended
-gamut xvYCC encoding values outside that range are allowed.</term>
+one defined in Rec. 709.</term>
          <listitem>
             <para>L' = -1.099(-L)<superscript>0.45</superscript>&nbsp;+&nbsp;0.099&nbsp;for&nbsp;L&nbsp;&le;&nbsp;-0.018</para>
             <para>L' = 4.5L&nbsp;for&nbsp;-0.018&nbsp;&lt;&nbsp;L&nbsp;&lt;&nbsp;0.018</para>
@@ -702,29 +702,10 @@ defined in the <xref linkend="itu601" /> standard and this colorspace is sometim
 though BT.601 does not mention any color primaries.</para>
       <para>The default quantization is limited range, but full range is possible although
 rarely seen.</para>
-      <para>The <constant>V4L2_YCBCR_ENC_601</constant> encoding as described above is the
-default for this colorspace, but it can be overridden with <constant>V4L2_YCBCR_ENC_709</constant>,
-in which case the Rec. 709 Y'CbCr encoding is used.</para>
-      <variablelist>
-       <varlistentry>
-         <term>The xvYCC 601 encoding (<constant>V4L2_YCBCR_ENC_XV601</constant>, <xref linkend="xvycc" />) is similar
-to the BT.601 encoding, but it allows for R', G' and B' values that are outside the range
-[0&hellip;1]. The resulting Y', Cb and Cr values are scaled and offset:</term>
-         <listitem>
-            <para>Y'&nbsp;=&nbsp;(219&nbsp;/&nbsp;255)&nbsp;*&nbsp;(0.299R'&nbsp;+&nbsp;0.587G'&nbsp;+&nbsp;0.114B')&nbsp;+&nbsp;(16&nbsp;/&nbsp;255)</para>
-            <para>Cb&nbsp;=&nbsp;(224&nbsp;/&nbsp;255)&nbsp;*&nbsp;(-0.169R'&nbsp;-&nbsp;0.331G'&nbsp;+&nbsp;0.5B')</para>
-            <para>Cr&nbsp;=&nbsp;(224&nbsp;/&nbsp;255)&nbsp;*&nbsp;(0.5R'&nbsp;-&nbsp;0.419G'&nbsp;-&nbsp;0.081B')</para>
-         </listitem>
-       </varlistentry>
-      </variablelist>
-      <para>Y' is clamped to the range [0&hellip;1] and Cb and Cr are clamped
-to the range [-0.5&hellip;0.5]. The non-standard xvYCC 709 encoding can also be used by selecting
-<constant>V4L2_YCBCR_ENC_XV709</constant>. The xvYCC encodings always use full range
-quantization.</para>
     </section>
 
-    <section>
-      <title id="col-rec709">Colorspace Rec. 709 (<constant>V4L2_COLORSPACE_REC709</constant>)</title>
+    <section id="col-rec709">
+      <title>Colorspace Rec. 709 (<constant>V4L2_COLORSPACE_REC709</constant>)</title>
       <para>The <xref linkend="itu709" /> standard defines the colorspace used by HDTV in general. The default
 Y'CbCr encoding is <constant>V4L2_YCBCR_ENC_709</constant>. The default Y'CbCr quantization is
 limited range. The chromaticities of the primary colors and the white reference are:</para>
@@ -803,26 +784,39 @@ rarely seen.</para>
       <para>The <constant>V4L2_YCBCR_ENC_709</constant> encoding described above is the default
 for this colorspace, but it can be overridden with <constant>V4L2_YCBCR_ENC_601</constant>, in which
 case the BT.601 Y'CbCr encoding is used.</para>
+      <para>Two additional extended gamut Y'CbCr encodings are also possible with this colorspace:</para>
       <variablelist>
        <varlistentry>
          <term>The xvYCC 709 encoding (<constant>V4L2_YCBCR_ENC_XV709</constant>, <xref linkend="xvycc" />)
 is similar to the Rec. 709 encoding, but it allows for R', G' and B' values that are outside the range
 [0&hellip;1]. The resulting Y', Cb and Cr values are scaled and offset:</term>
          <listitem>
-            <para>Y'&nbsp;=&nbsp;(219&nbsp;/&nbsp;255)&nbsp;*&nbsp;(0.2126R'&nbsp;+&nbsp;0.7152G'&nbsp;+&nbsp;0.0722B')&nbsp;+&nbsp;(16&nbsp;/&nbsp;255)</para>
-            <para>Cb&nbsp;=&nbsp;(224&nbsp;/&nbsp;255)&nbsp;*&nbsp;(-0.1146R'&nbsp;-&nbsp;0.3854G'&nbsp;+&nbsp;0.5B')</para>
-            <para>Cr&nbsp;=&nbsp;(224&nbsp;/&nbsp;255)&nbsp;*&nbsp;(0.5R'&nbsp;-&nbsp;0.4542G'&nbsp;-&nbsp;0.0458B')</para>
+            <para>Y'&nbsp;=&nbsp;(219&nbsp;/&nbsp;256)&nbsp;*&nbsp;(0.2126R'&nbsp;+&nbsp;0.7152G'&nbsp;+&nbsp;0.0722B')&nbsp;+&nbsp;(16&nbsp;/&nbsp;256)</para>
+            <para>Cb&nbsp;=&nbsp;(224&nbsp;/&nbsp;256)&nbsp;*&nbsp;(-0.1146R'&nbsp;-&nbsp;0.3854G'&nbsp;+&nbsp;0.5B')</para>
+            <para>Cr&nbsp;=&nbsp;(224&nbsp;/&nbsp;256)&nbsp;*&nbsp;(0.5R'&nbsp;-&nbsp;0.4542G'&nbsp;-&nbsp;0.0458B')</para>
+         </listitem>
+       </varlistentry>
+      </variablelist>
+      <variablelist>
+       <varlistentry>
+         <term>The xvYCC 601 encoding (<constant>V4L2_YCBCR_ENC_XV601</constant>, <xref linkend="xvycc" />) is similar
+to the BT.601 encoding, but it allows for R', G' and B' values that are outside the range
+[0&hellip;1]. The resulting Y', Cb and Cr values are scaled and offset:</term>
+         <listitem>
+            <para>Y'&nbsp;=&nbsp;(219&nbsp;/&nbsp;256)&nbsp;*&nbsp;(0.299R'&nbsp;+&nbsp;0.587G'&nbsp;+&nbsp;0.114B')&nbsp;+&nbsp;(16&nbsp;/&nbsp;256)</para>
+            <para>Cb&nbsp;=&nbsp;(224&nbsp;/&nbsp;256)&nbsp;*&nbsp;(-0.169R'&nbsp;-&nbsp;0.331G'&nbsp;+&nbsp;0.5B')</para>
+            <para>Cr&nbsp;=&nbsp;(224&nbsp;/&nbsp;256)&nbsp;*&nbsp;(0.5R'&nbsp;-&nbsp;0.419G'&nbsp;-&nbsp;0.081B')</para>
          </listitem>
        </varlistentry>
       </variablelist>
       <para>Y' is clamped to the range [0&hellip;1] and Cb and Cr are clamped
-to the range [-0.5&hellip;0.5]. The non-standard xvYCC 601 encoding can also be used by
-selecting <constant>V4L2_YCBCR_ENC_XV601</constant>. The xvYCC encodings always use full
-range quantization.</para>
+to the range [-0.5&hellip;0.5]. The non-standard xvYCC 709 or xvYCC 601 encodings can be used by
+selecting <constant>V4L2_YCBCR_ENC_XV709</constant> or <constant>V4L2_YCBCR_ENC_XV601</constant>.
+The xvYCC encodings always use full range quantization.</para>
     </section>
 
-    <section>
-      <title id="col-srgb">Colorspace sRGB (<constant>V4L2_COLORSPACE_SRGB</constant>)</title>
+    <section id="col-srgb">
+      <title>Colorspace sRGB (<constant>V4L2_COLORSPACE_SRGB</constant>)</title>
       <para>The <xref linkend="srgb" /> standard defines the colorspace used by most webcams and computer graphics. The
 default Y'CbCr encoding is <constant>V4L2_YCBCR_ENC_SYCC</constant>. The default Y'CbCr quantization
 is full range. The chromaticities of the primary colors and the white reference are:</para>
@@ -898,8 +892,8 @@ encoding, it is not. The <constant>V4L2_YCBCR_ENC_XV601</constant> scales and of
 values before quantization, but this encoding does not do that.</para>
     </section>
 
-    <section>
-      <title id="col-adobergb">Colorspace Adobe RGB (<constant>V4L2_COLORSPACE_ADOBERGB</constant>)</title>
+    <section id="col-adobergb">
+      <title>Colorspace Adobe RGB (<constant>V4L2_COLORSPACE_ADOBERGB</constant>)</title>
       <para>The <xref linkend="adobergb" /> standard defines the colorspace used by computer graphics
 that use the AdobeRGB colorspace. This is also known as the <xref linkend="oprgb" /> standard.
 The default Y'CbCr encoding is <constant>V4L2_YCBCR_ENC_601</constant>. The default Y'CbCr
@@ -970,12 +964,12 @@ clamped to the range [-0.5&hellip;0.5]. This transform is identical to one defin
 SMPTE 170M/BT.601. The Y'CbCr quantization is limited range.</para>
     </section>
 
-    <section>
-      <title id="col-bt2020">Colorspace BT.2020 (<constant>V4L2_COLORSPACE_BT2020</constant>)</title>
+    <section id="col-bt2020">
+      <title>Colorspace BT.2020 (<constant>V4L2_COLORSPACE_BT2020</constant>)</title>
       <para>The <xref linkend="itu2020" /> standard defines the colorspace used by Ultra-high definition
 television (UHDTV). The default Y'CbCr encoding is <constant>V4L2_YCBCR_ENC_BT2020</constant>.
-The default Y'CbCr quantization is limited range. The chromaticities of the primary colors and
-the white reference are:</para>
+The default R'G'B' quantization is limited range (!), and so is the default Y'CbCr quantization.
+The chromaticities of the primary colors and the white reference are:</para>
       <table frame="none">
         <title>BT.2020 Chromaticities</title>
         <tgroup cols="3" align="left">
@@ -1032,7 +1026,7 @@ the white reference are:</para>
          <term>The luminance (Y') and color difference (Cb and Cr) are obtained with the
 following <constant>V4L2_YCBCR_ENC_BT2020</constant> encoding:</term>
          <listitem>
-            <para>Y'&nbsp;=&nbsp;0.2627R'&nbsp;+&nbsp;0.6789G'&nbsp;+&nbsp;0.0593B'</para>
+            <para>Y'&nbsp;=&nbsp;0.2627R'&nbsp;+&nbsp;0.6780G'&nbsp;+&nbsp;0.0593B'</para>
             <para>Cb&nbsp;=&nbsp;-0.1396R'&nbsp;-&nbsp;0.3604G'&nbsp;+&nbsp;0.5B'</para>
             <para>Cr&nbsp;=&nbsp;0.5R'&nbsp;-&nbsp;0.4598G'&nbsp;-&nbsp;0.0402B'</para>
          </listitem>
@@ -1046,7 +1040,7 @@ clamped to the range [-0.5&hellip;0.5]. The Y'CbCr quantization is limited range
        <varlistentry>
          <term>Luma:</term>
          <listitem>
-            <para>Yc'&nbsp;=&nbsp;(0.2627R&nbsp;+&nbsp;0.6789G&nbsp;+&nbsp;0.0593B)'</para>
+            <para>Yc'&nbsp;=&nbsp;(0.2627R&nbsp;+&nbsp;0.6780G&nbsp;+&nbsp;0.0593B)'</para>
          </listitem>
        </varlistentry>
       </variablelist>
@@ -1054,7 +1048,7 @@ clamped to the range [-0.5&hellip;0.5]. The Y'CbCr quantization is limited range
        <varlistentry>
          <term>B'&nbsp;-&nbsp;Yc'&nbsp;&le;&nbsp;0:</term>
          <listitem>
-            <para>Cbc&nbsp;=&nbsp;(B'&nbsp;-&nbsp;Y')&nbsp;/&nbsp;1.9404</para>
+            <para>Cbc&nbsp;=&nbsp;(B'&nbsp;-&nbsp;Yc')&nbsp;/&nbsp;1.9404</para>
          </listitem>
        </varlistentry>
       </variablelist>
@@ -1062,7 +1056,7 @@ clamped to the range [-0.5&hellip;0.5]. The Y'CbCr quantization is limited range
        <varlistentry>
          <term>B'&nbsp;-&nbsp;Yc'&nbsp;&gt;&nbsp;0:</term>
          <listitem>
-            <para>Cbc&nbsp;=&nbsp;(B'&nbsp;-&nbsp;Y')&nbsp;/&nbsp;1.5816</para>
+            <para>Cbc&nbsp;=&nbsp;(B'&nbsp;-&nbsp;Yc')&nbsp;/&nbsp;1.5816</para>
          </listitem>
        </varlistentry>
       </variablelist>
@@ -1086,8 +1080,8 @@ clamped to the range [-0.5&hellip;0.5]. The Y'CbCr quantization is limited range
 clamped to the range [-0.5&hellip;0.5]. The Yc'CbcCrc quantization is limited range.</para>
     </section>
 
-    <section>
-      <title id="col-smpte-240m">Colorspace SMPTE 240M (<constant>V4L2_COLORSPACE_SMPTE240M</constant>)</title>
+    <section id="col-smpte-240m">
+      <title>Colorspace SMPTE 240M (<constant>V4L2_COLORSPACE_SMPTE240M</constant>)</title>
       <para>The <xref linkend="smpte240m" /> standard was an interim standard used during the early days of HDTV (1988-1998).
 It has been superseded by Rec. 709. The default Y'CbCr encoding is <constant>V4L2_YCBCR_ENC_SMPTE240M</constant>.
 The default Y'CbCr quantization is limited range. The chromaticities of the primary colors and the
@@ -1159,8 +1153,8 @@ following <constant>V4L2_YCBCR_ENC_SMPTE240M</constant> encoding:</term>
 clamped to the range [-0.5&hellip;0.5]. The Y'CbCr quantization is limited range.</para>
     </section>
 
-    <section>
-      <title id="col-sysm">Colorspace NTSC 1953 (<constant>V4L2_COLORSPACE_470_SYSTEM_M</constant>)</title>
+    <section id="col-sysm">
+      <title>Colorspace NTSC 1953 (<constant>V4L2_COLORSPACE_470_SYSTEM_M</constant>)</title>
       <para>This standard defines the colorspace used by NTSC in 1953. In practice this
 colorspace is obsolete and SMPTE 170M should be used instead. The default Y'CbCr encoding
 is <constant>V4L2_YCBCR_ENC_601</constant>. The default Y'CbCr quantization is limited range.
@@ -1237,8 +1231,8 @@ clamped to the range [-0.5&hellip;0.5]. The Y'CbCr quantization is limited range
 This transform is identical to one defined in SMPTE 170M/BT.601.</para>
     </section>
 
-    <section>
-      <title id="col-sysbg">Colorspace EBU Tech. 3213 (<constant>V4L2_COLORSPACE_470_SYSTEM_BG</constant>)</title>
+    <section id="col-sysbg">
+      <title>Colorspace EBU Tech. 3213 (<constant>V4L2_COLORSPACE_470_SYSTEM_BG</constant>)</title>
       <para>The <xref linkend="tech3213" /> standard defines the colorspace used by PAL/SECAM in 1975. In practice this
 colorspace is obsolete and SMPTE 170M should be used instead. The default Y'CbCr encoding
 is <constant>V4L2_YCBCR_ENC_601</constant>. The default Y'CbCr quantization is limited range.
@@ -1311,8 +1305,8 @@ clamped to the range [-0.5&hellip;0.5]. The Y'CbCr quantization is limited range
 This transform is identical to one defined in SMPTE 170M/BT.601.</para>
     </section>
 
-    <section>
-      <title id="col-jpeg">Colorspace JPEG (<constant>V4L2_COLORSPACE_JPEG</constant>)</title>
+    <section id="col-jpeg">
+      <title>Colorspace JPEG (<constant>V4L2_COLORSPACE_JPEG</constant>)</title>
       <para>This colorspace defines the colorspace used by most (Motion-)JPEG formats. The chromaticities
 of the primary colors and the white reference are identical to sRGB. The Y'CbCr encoding is
 <constant>V4L2_YCBCR_ENC_601</constant> with full range quantization where
index 553a38024745b13e85a628a8534af13f4607225b..2588ad781242e2d3f655fa1fcc2d35fe09257293 100644 (file)
@@ -482,6 +482,36 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>b<subscript>1</subscript></entry>
              <entry>b<subscript>0</subscript></entry>
            </row>
+           <row id="MEDIA-BUS-FMT-RBG888-1X24">
+             <entry>MEDIA_BUS_FMT_RBG888_1X24</entry>
+             <entry>0x100e</entry>
+             <entry></entry>
+             &dash-ent-8;
+             <entry>r<subscript>7</subscript></entry>
+             <entry>r<subscript>6</subscript></entry>
+             <entry>r<subscript>5</subscript></entry>
+             <entry>r<subscript>4</subscript></entry>
+             <entry>r<subscript>3</subscript></entry>
+             <entry>r<subscript>2</subscript></entry>
+             <entry>r<subscript>1</subscript></entry>
+             <entry>r<subscript>0</subscript></entry>
+             <entry>b<subscript>7</subscript></entry>
+             <entry>b<subscript>6</subscript></entry>
+             <entry>b<subscript>5</subscript></entry>
+             <entry>b<subscript>4</subscript></entry>
+             <entry>b<subscript>3</subscript></entry>
+             <entry>b<subscript>2</subscript></entry>
+             <entry>b<subscript>1</subscript></entry>
+             <entry>b<subscript>0</subscript></entry>
+             <entry>g<subscript>7</subscript></entry>
+             <entry>g<subscript>6</subscript></entry>
+             <entry>g<subscript>5</subscript></entry>
+             <entry>g<subscript>4</subscript></entry>
+             <entry>g<subscript>3</subscript></entry>
+             <entry>g<subscript>2</subscript></entry>
+             <entry>g<subscript>1</subscript></entry>
+             <entry>g<subscript>0</subscript></entry>
+           </row>
            <row id="MEDIA-BUS-FMT-RGB666-1X24_CPADHI">
              <entry>MEDIA_BUS_FMT_RGB666_1X24_CPADHI</entry>
              <entry>0x1015</entry>
@@ -711,6 +741,43 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>b<subscript>1</subscript></entry>
              <entry>b<subscript>0</subscript></entry>
            </row>
+           <row id="MEDIA-BUS-FMT-RGB888-1X32-PADHI">
+             <entry>MEDIA_BUS_FMT_RGB888_1X32_PADHI</entry>
+             <entry>0x100f</entry>
+             <entry></entry>
+             <entry>0</entry>
+             <entry>0</entry>
+             <entry>0</entry>
+             <entry>0</entry>
+             <entry>0</entry>
+             <entry>0</entry>
+             <entry>0</entry>
+             <entry>0</entry>
+             <entry>r<subscript>7</subscript></entry>
+             <entry>r<subscript>6</subscript></entry>
+             <entry>r<subscript>5</subscript></entry>
+             <entry>r<subscript>4</subscript></entry>
+             <entry>r<subscript>3</subscript></entry>
+             <entry>r<subscript>2</subscript></entry>
+             <entry>r<subscript>1</subscript></entry>
+             <entry>r<subscript>0</subscript></entry>
+             <entry>g<subscript>7</subscript></entry>
+             <entry>g<subscript>6</subscript></entry>
+             <entry>g<subscript>5</subscript></entry>
+             <entry>g<subscript>4</subscript></entry>
+             <entry>g<subscript>3</subscript></entry>
+             <entry>g<subscript>2</subscript></entry>
+             <entry>g<subscript>1</subscript></entry>
+             <entry>g<subscript>0</subscript></entry>
+             <entry>b<subscript>7</subscript></entry>
+             <entry>b<subscript>6</subscript></entry>
+             <entry>b<subscript>5</subscript></entry>
+             <entry>b<subscript>4</subscript></entry>
+             <entry>b<subscript>3</subscript></entry>
+             <entry>b<subscript>2</subscript></entry>
+             <entry>b<subscript>1</subscript></entry>
+             <entry>b<subscript>0</subscript></entry>
+           </row>
          </tbody>
        </tgroup>
       </table>
@@ -2575,11 +2642,15 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>y<subscript>1</subscript></entry>
              <entry>y<subscript>0</subscript></entry>
            </row>
-           <row id="MEDIA-BUS-FMT-UYVY8-1X16">
-             <entry>MEDIA_BUS_FMT_UYVY8_1X16</entry>
-             <entry>0x200f</entry>
+           <row id="MEDIA-BUS-FMT-UYVY12-2X12">
+             <entry>MEDIA_BUS_FMT_UYVY12_2X12</entry>
+             <entry>0x201c</entry>
              <entry></entry>
-             &dash-ent-16;
+             &dash-ent-20;
+             <entry>u<subscript>11</subscript></entry>
+             <entry>u<subscript>10</subscript></entry>
+             <entry>u<subscript>9</subscript></entry>
+             <entry>u<subscript>8</subscript></entry>
              <entry>u<subscript>7</subscript></entry>
              <entry>u<subscript>6</subscript></entry>
              <entry>u<subscript>5</subscript></entry>
@@ -2588,6 +2659,16 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>u<subscript>2</subscript></entry>
              <entry>u<subscript>1</subscript></entry>
              <entry>u<subscript>0</subscript></entry>
+           </row>
+           <row>
+             <entry></entry>
+             <entry></entry>
+             <entry></entry>
+             &dash-ent-20;
+             <entry>y<subscript>11</subscript></entry>
+             <entry>y<subscript>10</subscript></entry>
+             <entry>y<subscript>9</subscript></entry>
+             <entry>y<subscript>8</subscript></entry>
              <entry>y<subscript>7</subscript></entry>
              <entry>y<subscript>6</subscript></entry>
              <entry>y<subscript>5</subscript></entry>
@@ -2601,7 +2682,11 @@ see <xref linkend="colorspaces" />.</entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             &dash-ent-16;
+             &dash-ent-20;
+             <entry>v<subscript>11</subscript></entry>
+             <entry>v<subscript>10</subscript></entry>
+             <entry>v<subscript>9</subscript></entry>
+             <entry>v<subscript>8</subscript></entry>
              <entry>v<subscript>7</subscript></entry>
              <entry>v<subscript>6</subscript></entry>
              <entry>v<subscript>5</subscript></entry>
@@ -2610,6 +2695,16 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>v<subscript>2</subscript></entry>
              <entry>v<subscript>1</subscript></entry>
              <entry>v<subscript>0</subscript></entry>
+           </row>
+           <row>
+             <entry></entry>
+             <entry></entry>
+             <entry></entry>
+             &dash-ent-20;
+             <entry>y<subscript>11</subscript></entry>
+             <entry>y<subscript>10</subscript></entry>
+             <entry>y<subscript>9</subscript></entry>
+             <entry>y<subscript>8</subscript></entry>
              <entry>y<subscript>7</subscript></entry>
              <entry>y<subscript>6</subscript></entry>
              <entry>y<subscript>5</subscript></entry>
@@ -2619,11 +2714,15 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>y<subscript>1</subscript></entry>
              <entry>y<subscript>0</subscript></entry>
            </row>
-           <row id="MEDIA-BUS-FMT-VYUY8-1X16">
-             <entry>MEDIA_BUS_FMT_VYUY8_1X16</entry>
-             <entry>0x2010</entry>
+           <row id="MEDIA-BUS-FMT-VYUY12-2X12">
+             <entry>MEDIA_BUS_FMT_VYUY12_2X12</entry>
+             <entry>0x201d</entry>
              <entry></entry>
-             &dash-ent-16;
+             &dash-ent-20;
+             <entry>v<subscript>11</subscript></entry>
+             <entry>v<subscript>10</subscript></entry>
+             <entry>v<subscript>9</subscript></entry>
+             <entry>v<subscript>8</subscript></entry>
              <entry>v<subscript>7</subscript></entry>
              <entry>v<subscript>6</subscript></entry>
              <entry>v<subscript>5</subscript></entry>
@@ -2632,6 +2731,16 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>v<subscript>2</subscript></entry>
              <entry>v<subscript>1</subscript></entry>
              <entry>v<subscript>0</subscript></entry>
+           </row>
+           <row>
+             <entry></entry>
+             <entry></entry>
+             <entry></entry>
+             &dash-ent-20;
+             <entry>y<subscript>11</subscript></entry>
+             <entry>y<subscript>10</subscript></entry>
+             <entry>y<subscript>9</subscript></entry>
+             <entry>y<subscript>8</subscript></entry>
              <entry>y<subscript>7</subscript></entry>
              <entry>y<subscript>6</subscript></entry>
              <entry>y<subscript>5</subscript></entry>
@@ -2645,7 +2754,11 @@ see <xref linkend="colorspaces" />.</entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             &dash-ent-16;
+             &dash-ent-20;
+             <entry>u<subscript>11</subscript></entry>
+             <entry>u<subscript>10</subscript></entry>
+             <entry>u<subscript>9</subscript></entry>
+             <entry>u<subscript>8</subscript></entry>
              <entry>u<subscript>7</subscript></entry>
              <entry>u<subscript>6</subscript></entry>
              <entry>u<subscript>5</subscript></entry>
@@ -2654,6 +2767,16 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>u<subscript>2</subscript></entry>
              <entry>u<subscript>1</subscript></entry>
              <entry>u<subscript>0</subscript></entry>
+           </row>
+           <row>
+             <entry></entry>
+             <entry></entry>
+             <entry></entry>
+             &dash-ent-20;
+             <entry>y<subscript>11</subscript></entry>
+             <entry>y<subscript>10</subscript></entry>
+             <entry>y<subscript>9</subscript></entry>
+             <entry>y<subscript>8</subscript></entry>
              <entry>y<subscript>7</subscript></entry>
              <entry>y<subscript>6</subscript></entry>
              <entry>y<subscript>5</subscript></entry>
@@ -2663,11 +2786,15 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>y<subscript>1</subscript></entry>
              <entry>y<subscript>0</subscript></entry>
            </row>
-           <row id="MEDIA-BUS-FMT-YUYV8-1X16">
-             <entry>MEDIA_BUS_FMT_YUYV8_1X16</entry>
-             <entry>0x2011</entry>
+           <row id="MEDIA-BUS-FMT-YUYV12-2X12">
+             <entry>MEDIA_BUS_FMT_YUYV12_2X12</entry>
+             <entry>0x201e</entry>
              <entry></entry>
-             &dash-ent-16;
+             &dash-ent-20;
+             <entry>y<subscript>11</subscript></entry>
+             <entry>y<subscript>10</subscript></entry>
+             <entry>y<subscript>9</subscript></entry>
+             <entry>y<subscript>8</subscript></entry>
              <entry>y<subscript>7</subscript></entry>
              <entry>y<subscript>6</subscript></entry>
              <entry>y<subscript>5</subscript></entry>
@@ -2676,6 +2803,16 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>y<subscript>2</subscript></entry>
              <entry>y<subscript>1</subscript></entry>
              <entry>y<subscript>0</subscript></entry>
+           </row>
+           <row>
+             <entry></entry>
+             <entry></entry>
+             <entry></entry>
+             &dash-ent-20;
+             <entry>u<subscript>11</subscript></entry>
+             <entry>u<subscript>10</subscript></entry>
+             <entry>u<subscript>9</subscript></entry>
+             <entry>u<subscript>8</subscript></entry>
              <entry>u<subscript>7</subscript></entry>
              <entry>u<subscript>6</subscript></entry>
              <entry>u<subscript>5</subscript></entry>
@@ -2689,7 +2826,11 @@ see <xref linkend="colorspaces" />.</entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             &dash-ent-16;
+             &dash-ent-20;
+             <entry>y<subscript>11</subscript></entry>
+             <entry>y<subscript>10</subscript></entry>
+             <entry>y<subscript>9</subscript></entry>
+             <entry>y<subscript>8</subscript></entry>
              <entry>y<subscript>7</subscript></entry>
              <entry>y<subscript>6</subscript></entry>
              <entry>y<subscript>5</subscript></entry>
@@ -2698,6 +2839,16 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>y<subscript>2</subscript></entry>
              <entry>y<subscript>1</subscript></entry>
              <entry>y<subscript>0</subscript></entry>
+           </row>
+           <row>
+             <entry></entry>
+             <entry></entry>
+             <entry></entry>
+             &dash-ent-20;
+             <entry>v<subscript>11</subscript></entry>
+             <entry>v<subscript>10</subscript></entry>
+             <entry>v<subscript>9</subscript></entry>
+             <entry>v<subscript>8</subscript></entry>
              <entry>v<subscript>7</subscript></entry>
              <entry>v<subscript>6</subscript></entry>
              <entry>v<subscript>5</subscript></entry>
@@ -2707,11 +2858,15 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>v<subscript>1</subscript></entry>
              <entry>v<subscript>0</subscript></entry>
            </row>
-           <row id="MEDIA-BUS-FMT-YVYU8-1X16">
-             <entry>MEDIA_BUS_FMT_YVYU8_1X16</entry>
-             <entry>0x2012</entry>
+           <row id="MEDIA-BUS-FMT-YVYU12-2X12">
+             <entry>MEDIA_BUS_FMT_YVYU12_2X12</entry>
+             <entry>0x201f</entry>
              <entry></entry>
-             &dash-ent-16;
+             &dash-ent-20;
+             <entry>y<subscript>11</subscript></entry>
+             <entry>y<subscript>10</subscript></entry>
+             <entry>y<subscript>9</subscript></entry>
+             <entry>y<subscript>8</subscript></entry>
              <entry>y<subscript>7</subscript></entry>
              <entry>y<subscript>6</subscript></entry>
              <entry>y<subscript>5</subscript></entry>
@@ -2720,6 +2875,16 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>y<subscript>2</subscript></entry>
              <entry>y<subscript>1</subscript></entry>
              <entry>y<subscript>0</subscript></entry>
+           </row>
+           <row>
+             <entry></entry>
+             <entry></entry>
+             <entry></entry>
+             &dash-ent-20;
+             <entry>v<subscript>11</subscript></entry>
+             <entry>v<subscript>10</subscript></entry>
+             <entry>v<subscript>9</subscript></entry>
+             <entry>v<subscript>8</subscript></entry>
              <entry>v<subscript>7</subscript></entry>
              <entry>v<subscript>6</subscript></entry>
              <entry>v<subscript>5</subscript></entry>
@@ -2733,7 +2898,11 @@ see <xref linkend="colorspaces" />.</entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             &dash-ent-16;
+             &dash-ent-20;
+             <entry>y<subscript>11</subscript></entry>
+             <entry>y<subscript>10</subscript></entry>
+             <entry>y<subscript>9</subscript></entry>
+             <entry>y<subscript>8</subscript></entry>
              <entry>y<subscript>7</subscript></entry>
              <entry>y<subscript>6</subscript></entry>
              <entry>y<subscript>5</subscript></entry>
@@ -2742,6 +2911,16 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>y<subscript>2</subscript></entry>
              <entry>y<subscript>1</subscript></entry>
              <entry>y<subscript>0</subscript></entry>
+           </row>
+           <row>
+             <entry></entry>
+             <entry></entry>
+             <entry></entry>
+             &dash-ent-20;
+             <entry>u<subscript>11</subscript></entry>
+             <entry>u<subscript>10</subscript></entry>
+             <entry>u<subscript>9</subscript></entry>
+             <entry>u<subscript>8</subscript></entry>
              <entry>u<subscript>7</subscript></entry>
              <entry>u<subscript>6</subscript></entry>
              <entry>u<subscript>5</subscript></entry>
@@ -2751,11 +2930,19 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>u<subscript>1</subscript></entry>
              <entry>u<subscript>0</subscript></entry>
            </row>
-           <row id="MEDIA-BUS-FMT-YDYUYDYV8-1X16">
-             <entry>MEDIA_BUS_FMT_YDYUYDYV8_1X16</entry>
-             <entry>0x2014</entry>
+           <row id="MEDIA-BUS-FMT-UYVY8-1X16">
+             <entry>MEDIA_BUS_FMT_UYVY8_1X16</entry>
+             <entry>0x200f</entry>
              <entry></entry>
              &dash-ent-16;
+             <entry>u<subscript>7</subscript></entry>
+             <entry>u<subscript>6</subscript></entry>
+             <entry>u<subscript>5</subscript></entry>
+             <entry>u<subscript>4</subscript></entry>
+             <entry>u<subscript>3</subscript></entry>
+             <entry>u<subscript>2</subscript></entry>
+             <entry>u<subscript>1</subscript></entry>
+             <entry>u<subscript>0</subscript></entry>
              <entry>y<subscript>7</subscript></entry>
              <entry>y<subscript>6</subscript></entry>
              <entry>y<subscript>5</subscript></entry>
@@ -2764,20 +2951,20 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>y<subscript>2</subscript></entry>
              <entry>y<subscript>1</subscript></entry>
              <entry>y<subscript>0</subscript></entry>
-             <entry>d</entry>
-             <entry>d</entry>
-             <entry>d</entry>
-             <entry>d</entry>
-             <entry>d</entry>
-             <entry>d</entry>
-             <entry>d</entry>
-             <entry>d</entry>
            </row>
            <row>
              <entry></entry>
              <entry></entry>
              <entry></entry>
              &dash-ent-16;
+             <entry>v<subscript>7</subscript></entry>
+             <entry>v<subscript>6</subscript></entry>
+             <entry>v<subscript>5</subscript></entry>
+             <entry>v<subscript>4</subscript></entry>
+             <entry>v<subscript>3</subscript></entry>
+             <entry>v<subscript>2</subscript></entry>
+             <entry>v<subscript>1</subscript></entry>
+             <entry>v<subscript>0</subscript></entry>
              <entry>y<subscript>7</subscript></entry>
              <entry>y<subscript>6</subscript></entry>
              <entry>y<subscript>5</subscript></entry>
@@ -2786,50 +2973,12 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>y<subscript>2</subscript></entry>
              <entry>y<subscript>1</subscript></entry>
              <entry>y<subscript>0</subscript></entry>
-             <entry>u<subscript>7</subscript></entry>
-             <entry>u<subscript>6</subscript></entry>
-             <entry>u<subscript>5</subscript></entry>
-             <entry>u<subscript>4</subscript></entry>
-             <entry>u<subscript>3</subscript></entry>
-             <entry>u<subscript>2</subscript></entry>
-             <entry>u<subscript>1</subscript></entry>
-             <entry>u<subscript>0</subscript></entry>
            </row>
-           <row>
-             <entry></entry>
-             <entry></entry>
-             <entry></entry>
-             &dash-ent-16;
-             <entry>y<subscript>7</subscript></entry>
-             <entry>y<subscript>6</subscript></entry>
-             <entry>y<subscript>5</subscript></entry>
-             <entry>y<subscript>4</subscript></entry>
-             <entry>y<subscript>3</subscript></entry>
-             <entry>y<subscript>2</subscript></entry>
-             <entry>y<subscript>1</subscript></entry>
-             <entry>y<subscript>0</subscript></entry>
-             <entry>d</entry>
-             <entry>d</entry>
-             <entry>d</entry>
-             <entry>d</entry>
-             <entry>d</entry>
-             <entry>d</entry>
-             <entry>d</entry>
-             <entry>d</entry>
-           </row>
-           <row>
-             <entry></entry>
-             <entry></entry>
+           <row id="MEDIA-BUS-FMT-VYUY8-1X16">
+             <entry>MEDIA_BUS_FMT_VYUY8_1X16</entry>
+             <entry>0x2010</entry>
              <entry></entry>
              &dash-ent-16;
-             <entry>y<subscript>7</subscript></entry>
-             <entry>y<subscript>6</subscript></entry>
-             <entry>y<subscript>5</subscript></entry>
-             <entry>y<subscript>4</subscript></entry>
-             <entry>y<subscript>3</subscript></entry>
-             <entry>y<subscript>2</subscript></entry>
-             <entry>y<subscript>1</subscript></entry>
-             <entry>y<subscript>0</subscript></entry>
              <entry>v<subscript>7</subscript></entry>
              <entry>v<subscript>6</subscript></entry>
              <entry>v<subscript>5</subscript></entry>
@@ -2838,24 +2987,6 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>v<subscript>2</subscript></entry>
              <entry>v<subscript>1</subscript></entry>
              <entry>v<subscript>0</subscript></entry>
-           </row>
-           <row id="MEDIA-BUS-FMT-UYVY10-1X20">
-             <entry>MEDIA_BUS_FMT_UYVY10_1X20</entry>
-             <entry>0x201a</entry>
-             <entry></entry>
-             &dash-ent-12;
-             <entry>u<subscript>9</subscript></entry>
-             <entry>u<subscript>8</subscript></entry>
-             <entry>u<subscript>7</subscript></entry>
-             <entry>u<subscript>6</subscript></entry>
-             <entry>u<subscript>5</subscript></entry>
-             <entry>u<subscript>4</subscript></entry>
-             <entry>u<subscript>3</subscript></entry>
-             <entry>u<subscript>2</subscript></entry>
-             <entry>u<subscript>1</subscript></entry>
-             <entry>u<subscript>0</subscript></entry>
-             <entry>y<subscript>9</subscript></entry>
-             <entry>y<subscript>8</subscript></entry>
              <entry>y<subscript>7</subscript></entry>
              <entry>y<subscript>6</subscript></entry>
              <entry>y<subscript>5</subscript></entry>
@@ -2869,61 +3000,7 @@ see <xref linkend="colorspaces" />.</entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             &dash-ent-12;
-             <entry>v<subscript>9</subscript></entry>
-             <entry>v<subscript>8</subscript></entry>
-             <entry>v<subscript>7</subscript></entry>
-             <entry>v<subscript>6</subscript></entry>
-             <entry>v<subscript>5</subscript></entry>
-             <entry>v<subscript>4</subscript></entry>
-             <entry>v<subscript>3</subscript></entry>
-             <entry>v<subscript>2</subscript></entry>
-             <entry>v<subscript>1</subscript></entry>
-             <entry>v<subscript>0</subscript></entry>
-             <entry>y<subscript>9</subscript></entry>
-             <entry>y<subscript>8</subscript></entry>
-             <entry>y<subscript>7</subscript></entry>
-             <entry>y<subscript>6</subscript></entry>
-             <entry>y<subscript>5</subscript></entry>
-             <entry>y<subscript>4</subscript></entry>
-             <entry>y<subscript>3</subscript></entry>
-             <entry>y<subscript>2</subscript></entry>
-             <entry>y<subscript>1</subscript></entry>
-             <entry>y<subscript>0</subscript></entry>
-           </row>
-           <row id="MEDIA-BUS-FMT-VYUY10-1X20">
-             <entry>MEDIA_BUS_FMT_VYUY10_1X20</entry>
-             <entry>0x201b</entry>
-             <entry></entry>
-             &dash-ent-12;
-             <entry>v<subscript>9</subscript></entry>
-             <entry>v<subscript>8</subscript></entry>
-             <entry>v<subscript>7</subscript></entry>
-             <entry>v<subscript>6</subscript></entry>
-             <entry>v<subscript>5</subscript></entry>
-             <entry>v<subscript>4</subscript></entry>
-             <entry>v<subscript>3</subscript></entry>
-             <entry>v<subscript>2</subscript></entry>
-             <entry>v<subscript>1</subscript></entry>
-             <entry>v<subscript>0</subscript></entry>
-             <entry>y<subscript>9</subscript></entry>
-             <entry>y<subscript>8</subscript></entry>
-             <entry>y<subscript>7</subscript></entry>
-             <entry>y<subscript>6</subscript></entry>
-             <entry>y<subscript>5</subscript></entry>
-             <entry>y<subscript>4</subscript></entry>
-             <entry>y<subscript>3</subscript></entry>
-             <entry>y<subscript>2</subscript></entry>
-             <entry>y<subscript>1</subscript></entry>
-             <entry>y<subscript>0</subscript></entry>
-           </row>
-           <row>
-             <entry></entry>
-             <entry></entry>
-             <entry></entry>
-             &dash-ent-12;
-             <entry>u<subscript>9</subscript></entry>
-             <entry>u<subscript>8</subscript></entry>
+             &dash-ent-16;
              <entry>u<subscript>7</subscript></entry>
              <entry>u<subscript>6</subscript></entry>
              <entry>u<subscript>5</subscript></entry>
@@ -2932,8 +3009,6 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>u<subscript>2</subscript></entry>
              <entry>u<subscript>1</subscript></entry>
              <entry>u<subscript>0</subscript></entry>
-             <entry>y<subscript>9</subscript></entry>
-             <entry>y<subscript>8</subscript></entry>
              <entry>y<subscript>7</subscript></entry>
              <entry>y<subscript>6</subscript></entry>
              <entry>y<subscript>5</subscript></entry>
@@ -2943,13 +3018,11 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>y<subscript>1</subscript></entry>
              <entry>y<subscript>0</subscript></entry>
            </row>
-           <row id="MEDIA-BUS-FMT-YUYV10-1X20">
-             <entry>MEDIA_BUS_FMT_YUYV10_1X20</entry>
-             <entry>0x200d</entry>
+           <row id="MEDIA-BUS-FMT-YUYV8-1X16">
+             <entry>MEDIA_BUS_FMT_YUYV8_1X16</entry>
+             <entry>0x2011</entry>
              <entry></entry>
-             &dash-ent-12;
-             <entry>y<subscript>9</subscript></entry>
-             <entry>y<subscript>8</subscript></entry>
+             &dash-ent-16;
              <entry>y<subscript>7</subscript></entry>
              <entry>y<subscript>6</subscript></entry>
              <entry>y<subscript>5</subscript></entry>
@@ -2958,8 +3031,6 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>y<subscript>2</subscript></entry>
              <entry>y<subscript>1</subscript></entry>
              <entry>y<subscript>0</subscript></entry>
-             <entry>u<subscript>9</subscript></entry>
-             <entry>u<subscript>8</subscript></entry>
              <entry>u<subscript>7</subscript></entry>
              <entry>u<subscript>6</subscript></entry>
              <entry>u<subscript>5</subscript></entry>
@@ -2973,9 +3044,7 @@ see <xref linkend="colorspaces" />.</entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             &dash-ent-12;
-             <entry>y<subscript>9</subscript></entry>
-             <entry>y<subscript>8</subscript></entry>
+             &dash-ent-16;
              <entry>y<subscript>7</subscript></entry>
              <entry>y<subscript>6</subscript></entry>
              <entry>y<subscript>5</subscript></entry>
@@ -2984,8 +3053,6 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>y<subscript>2</subscript></entry>
              <entry>y<subscript>1</subscript></entry>
              <entry>y<subscript>0</subscript></entry>
-             <entry>v<subscript>9</subscript></entry>
-             <entry>v<subscript>8</subscript></entry>
              <entry>v<subscript>7</subscript></entry>
              <entry>v<subscript>6</subscript></entry>
              <entry>v<subscript>5</subscript></entry>
@@ -2995,13 +3062,11 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>v<subscript>1</subscript></entry>
              <entry>v<subscript>0</subscript></entry>
            </row>
-           <row id="MEDIA-BUS-FMT-YVYU10-1X20">
-             <entry>MEDIA_BUS_FMT_YVYU10_1X20</entry>
-             <entry>0x200e</entry>
+           <row id="MEDIA-BUS-FMT-YVYU8-1X16">
+             <entry>MEDIA_BUS_FMT_YVYU8_1X16</entry>
+             <entry>0x2012</entry>
              <entry></entry>
-             &dash-ent-12;
-             <entry>y<subscript>9</subscript></entry>
-             <entry>y<subscript>8</subscript></entry>
+             &dash-ent-16;
              <entry>y<subscript>7</subscript></entry>
              <entry>y<subscript>6</subscript></entry>
              <entry>y<subscript>5</subscript></entry>
@@ -3010,8 +3075,6 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>y<subscript>2</subscript></entry>
              <entry>y<subscript>1</subscript></entry>
              <entry>y<subscript>0</subscript></entry>
-             <entry>v<subscript>9</subscript></entry>
-             <entry>v<subscript>8</subscript></entry>
              <entry>v<subscript>7</subscript></entry>
              <entry>v<subscript>6</subscript></entry>
              <entry>v<subscript>5</subscript></entry>
@@ -3025,9 +3088,7 @@ see <xref linkend="colorspaces" />.</entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             &dash-ent-12;
-             <entry>y<subscript>9</subscript></entry>
-             <entry>y<subscript>8</subscript></entry>
+             &dash-ent-16;
              <entry>y<subscript>7</subscript></entry>
              <entry>y<subscript>6</subscript></entry>
              <entry>y<subscript>5</subscript></entry>
@@ -3036,8 +3097,6 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>y<subscript>2</subscript></entry>
              <entry>y<subscript>1</subscript></entry>
              <entry>y<subscript>0</subscript></entry>
-             <entry>u<subscript>9</subscript></entry>
-             <entry>u<subscript>8</subscript></entry>
              <entry>u<subscript>7</subscript></entry>
              <entry>u<subscript>6</subscript></entry>
              <entry>u<subscript>5</subscript></entry>
@@ -3047,18 +3106,11 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>u<subscript>1</subscript></entry>
              <entry>u<subscript>0</subscript></entry>
            </row>
-           <row id="MEDIA-BUS-FMT-YUV8-1X24">
-             <entry>MEDIA_BUS_FMT_YUV8_1X24</entry>
-             <entry>0x2025</entry>
+           <row id="MEDIA-BUS-FMT-YDYUYDYV8-1X16">
+             <entry>MEDIA_BUS_FMT_YDYUYDYV8_1X16</entry>
+             <entry>0x2014</entry>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>-</entry>
+             &dash-ent-16;
              <entry>y<subscript>7</subscript></entry>
              <entry>y<subscript>6</subscript></entry>
              <entry>y<subscript>5</subscript></entry>
@@ -3067,31 +3119,20 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>y<subscript>2</subscript></entry>
              <entry>y<subscript>1</subscript></entry>
              <entry>y<subscript>0</subscript></entry>
-             <entry>u<subscript>7</subscript></entry>
-             <entry>u<subscript>6</subscript></entry>
-             <entry>u<subscript>5</subscript></entry>
-             <entry>u<subscript>4</subscript></entry>
-             <entry>u<subscript>3</subscript></entry>
-             <entry>u<subscript>2</subscript></entry>
-             <entry>u<subscript>1</subscript></entry>
-             <entry>u<subscript>0</subscript></entry>
-             <entry>v<subscript>7</subscript></entry>
-             <entry>v<subscript>6</subscript></entry>
-             <entry>v<subscript>5</subscript></entry>
-             <entry>v<subscript>4</subscript></entry>
-             <entry>v<subscript>3</subscript></entry>
-             <entry>v<subscript>2</subscript></entry>
-             <entry>v<subscript>1</subscript></entry>
-             <entry>v<subscript>0</subscript></entry>
+             <entry>d</entry>
+             <entry>d</entry>
+             <entry>d</entry>
+             <entry>d</entry>
+             <entry>d</entry>
+             <entry>d</entry>
+             <entry>d</entry>
+             <entry>d</entry>
            </row>
-           <row id="MEDIA-BUS-FMT-YUV10-1X30">
-             <entry>MEDIA_BUS_FMT_YUV10_1X30</entry>
-             <entry>0x2016</entry>
+           <row>
              <entry></entry>
-             <entry>-</entry>
-             <entry>-</entry>
-             <entry>y<subscript>9</subscript></entry>
-             <entry>y<subscript>8</subscript></entry>
+             <entry></entry>
+             <entry></entry>
+             &dash-ent-16;
              <entry>y<subscript>7</subscript></entry>
              <entry>y<subscript>6</subscript></entry>
              <entry>y<subscript>5</subscript></entry>
@@ -3100,8 +3141,6 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>y<subscript>2</subscript></entry>
              <entry>y<subscript>1</subscript></entry>
              <entry>y<subscript>0</subscript></entry>
-             <entry>u<subscript>9</subscript></entry>
-             <entry>u<subscript>8</subscript></entry>
              <entry>u<subscript>7</subscript></entry>
              <entry>u<subscript>6</subscript></entry>
              <entry>u<subscript>5</subscript></entry>
@@ -3110,29 +3149,34 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>u<subscript>2</subscript></entry>
              <entry>u<subscript>1</subscript></entry>
              <entry>u<subscript>0</subscript></entry>
-             <entry>v<subscript>9</subscript></entry>
-             <entry>v<subscript>8</subscript></entry>
-             <entry>v<subscript>7</subscript></entry>
-             <entry>v<subscript>6</subscript></entry>
-             <entry>v<subscript>5</subscript></entry>
-             <entry>v<subscript>4</subscript></entry>
-             <entry>v<subscript>3</subscript></entry>
-             <entry>v<subscript>2</subscript></entry>
-             <entry>v<subscript>1</subscript></entry>
-             <entry>v<subscript>0</subscript></entry>
            </row>
-           <row id="MEDIA-BUS-FMT-AYUV8-1X32">
-             <entry>MEDIA_BUS_FMT_AYUV8_1X32</entry>
-             <entry>0x2017</entry>
+           <row>
              <entry></entry>
-             <entry>a<subscript>7</subscript></entry>
-             <entry>a<subscript>6</subscript></entry>
-             <entry>a<subscript>5</subscript></entry>
-             <entry>a<subscript>4</subscript></entry>
-             <entry>a<subscript>3</subscript></entry>
-             <entry>a<subscript>2</subscript></entry>
-             <entry>a<subscript>1</subscript></entry>
-             <entry>a<subscript>0</subscript></entry>
+             <entry></entry>
+             <entry></entry>
+             &dash-ent-16;
+             <entry>y<subscript>7</subscript></entry>
+             <entry>y<subscript>6</subscript></entry>
+             <entry>y<subscript>5</subscript></entry>
+             <entry>y<subscript>4</subscript></entry>
+             <entry>y<subscript>3</subscript></entry>
+             <entry>y<subscript>2</subscript></entry>
+             <entry>y<subscript>1</subscript></entry>
+             <entry>y<subscript>0</subscript></entry>
+             <entry>d</entry>
+             <entry>d</entry>
+             <entry>d</entry>
+             <entry>d</entry>
+             <entry>d</entry>
+             <entry>d</entry>
+             <entry>d</entry>
+             <entry>d</entry>
+           </row>
+           <row>
+             <entry></entry>
+             <entry></entry>
+             <entry></entry>
+             &dash-ent-16;
              <entry>y<subscript>7</subscript></entry>
              <entry>y<subscript>6</subscript></entry>
              <entry>y<subscript>5</subscript></entry>
@@ -3141,14 +3185,6 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>y<subscript>2</subscript></entry>
              <entry>y<subscript>1</subscript></entry>
              <entry>y<subscript>0</subscript></entry>
-             <entry>u<subscript>7</subscript></entry>
-             <entry>u<subscript>6</subscript></entry>
-             <entry>u<subscript>5</subscript></entry>
-             <entry>u<subscript>4</subscript></entry>
-             <entry>u<subscript>3</subscript></entry>
-             <entry>u<subscript>2</subscript></entry>
-             <entry>u<subscript>1</subscript></entry>
-             <entry>u<subscript>0</subscript></entry>
              <entry>v<subscript>7</subscript></entry>
              <entry>v<subscript>6</subscript></entry>
              <entry>v<subscript>5</subscript></entry>
@@ -3158,13 +3194,11 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>v<subscript>1</subscript></entry>
              <entry>v<subscript>0</subscript></entry>
            </row>
-           <row id="MEDIA-BUS-FMT-UYVY12-2X12">
-             <entry>MEDIA_BUS_FMT_UYVY12_2X12</entry>
-             <entry>0x201c</entry>
+           <row id="MEDIA-BUS-FMT-UYVY10-1X20">
+             <entry>MEDIA_BUS_FMT_UYVY10_1X20</entry>
+             <entry>0x201a</entry>
              <entry></entry>
-             &dash-ent-20;
-             <entry>u<subscript>11</subscript></entry>
-             <entry>u<subscript>10</subscript></entry>
+             &dash-ent-12;
              <entry>u<subscript>9</subscript></entry>
              <entry>u<subscript>8</subscript></entry>
              <entry>u<subscript>7</subscript></entry>
@@ -3175,14 +3209,6 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>u<subscript>2</subscript></entry>
              <entry>u<subscript>1</subscript></entry>
              <entry>u<subscript>0</subscript></entry>
-           </row>
-           <row>
-             <entry></entry>
-             <entry></entry>
-             <entry></entry>
-             &dash-ent-20;
-             <entry>y<subscript>11</subscript></entry>
-             <entry>y<subscript>10</subscript></entry>
              <entry>y<subscript>9</subscript></entry>
              <entry>y<subscript>8</subscript></entry>
              <entry>y<subscript>7</subscript></entry>
@@ -3198,9 +3224,7 @@ see <xref linkend="colorspaces" />.</entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             &dash-ent-20;
-             <entry>v<subscript>11</subscript></entry>
-             <entry>v<subscript>10</subscript></entry>
+             &dash-ent-12;
              <entry>v<subscript>9</subscript></entry>
              <entry>v<subscript>8</subscript></entry>
              <entry>v<subscript>7</subscript></entry>
@@ -3211,14 +3235,6 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>v<subscript>2</subscript></entry>
              <entry>v<subscript>1</subscript></entry>
              <entry>v<subscript>0</subscript></entry>
-           </row>
-           <row>
-             <entry></entry>
-             <entry></entry>
-             <entry></entry>
-             &dash-ent-20;
-             <entry>y<subscript>11</subscript></entry>
-             <entry>y<subscript>10</subscript></entry>
              <entry>y<subscript>9</subscript></entry>
              <entry>y<subscript>8</subscript></entry>
              <entry>y<subscript>7</subscript></entry>
@@ -3230,13 +3246,11 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>y<subscript>1</subscript></entry>
              <entry>y<subscript>0</subscript></entry>
            </row>
-           <row id="MEDIA-BUS-FMT-VYUY12-2X12">
-             <entry>MEDIA_BUS_FMT_VYUY12_2X12</entry>
-             <entry>0x201d</entry>
+           <row id="MEDIA-BUS-FMT-VYUY10-1X20">
+             <entry>MEDIA_BUS_FMT_VYUY10_1X20</entry>
+             <entry>0x201b</entry>
              <entry></entry>
-             &dash-ent-20;
-             <entry>v<subscript>11</subscript></entry>
-             <entry>v<subscript>10</subscript></entry>
+             &dash-ent-12;
              <entry>v<subscript>9</subscript></entry>
              <entry>v<subscript>8</subscript></entry>
              <entry>v<subscript>7</subscript></entry>
@@ -3247,14 +3261,6 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>v<subscript>2</subscript></entry>
              <entry>v<subscript>1</subscript></entry>
              <entry>v<subscript>0</subscript></entry>
-           </row>
-           <row>
-             <entry></entry>
-             <entry></entry>
-             <entry></entry>
-             &dash-ent-20;
-             <entry>y<subscript>11</subscript></entry>
-             <entry>y<subscript>10</subscript></entry>
              <entry>y<subscript>9</subscript></entry>
              <entry>y<subscript>8</subscript></entry>
              <entry>y<subscript>7</subscript></entry>
@@ -3270,9 +3276,7 @@ see <xref linkend="colorspaces" />.</entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             &dash-ent-20;
-             <entry>u<subscript>11</subscript></entry>
-             <entry>u<subscript>10</subscript></entry>
+             &dash-ent-12;
              <entry>u<subscript>9</subscript></entry>
              <entry>u<subscript>8</subscript></entry>
              <entry>u<subscript>7</subscript></entry>
@@ -3283,14 +3287,6 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>u<subscript>2</subscript></entry>
              <entry>u<subscript>1</subscript></entry>
              <entry>u<subscript>0</subscript></entry>
-           </row>
-           <row>
-             <entry></entry>
-             <entry></entry>
-             <entry></entry>
-             &dash-ent-20;
-             <entry>y<subscript>11</subscript></entry>
-             <entry>y<subscript>10</subscript></entry>
              <entry>y<subscript>9</subscript></entry>
              <entry>y<subscript>8</subscript></entry>
              <entry>y<subscript>7</subscript></entry>
@@ -3302,13 +3298,11 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>y<subscript>1</subscript></entry>
              <entry>y<subscript>0</subscript></entry>
            </row>
-           <row id="MEDIA-BUS-FMT-YUYV12-2X12">
-             <entry>MEDIA_BUS_FMT_YUYV12_2X12</entry>
-             <entry>0x201e</entry>
+           <row id="MEDIA-BUS-FMT-YUYV10-1X20">
+             <entry>MEDIA_BUS_FMT_YUYV10_1X20</entry>
+             <entry>0x200d</entry>
              <entry></entry>
-             &dash-ent-20;
-             <entry>y<subscript>11</subscript></entry>
-             <entry>y<subscript>10</subscript></entry>
+             &dash-ent-12;
              <entry>y<subscript>9</subscript></entry>
              <entry>y<subscript>8</subscript></entry>
              <entry>y<subscript>7</subscript></entry>
@@ -3319,14 +3313,6 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>y<subscript>2</subscript></entry>
              <entry>y<subscript>1</subscript></entry>
              <entry>y<subscript>0</subscript></entry>
-           </row>
-           <row>
-             <entry></entry>
-             <entry></entry>
-             <entry></entry>
-             &dash-ent-20;
-             <entry>u<subscript>11</subscript></entry>
-             <entry>u<subscript>10</subscript></entry>
              <entry>u<subscript>9</subscript></entry>
              <entry>u<subscript>8</subscript></entry>
              <entry>u<subscript>7</subscript></entry>
@@ -3342,9 +3328,7 @@ see <xref linkend="colorspaces" />.</entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             &dash-ent-20;
-             <entry>y<subscript>11</subscript></entry>
-             <entry>y<subscript>10</subscript></entry>
+             &dash-ent-12;
              <entry>y<subscript>9</subscript></entry>
              <entry>y<subscript>8</subscript></entry>
              <entry>y<subscript>7</subscript></entry>
@@ -3355,14 +3339,6 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>y<subscript>2</subscript></entry>
              <entry>y<subscript>1</subscript></entry>
              <entry>y<subscript>0</subscript></entry>
-           </row>
-           <row>
-             <entry></entry>
-             <entry></entry>
-             <entry></entry>
-             &dash-ent-20;
-             <entry>v<subscript>11</subscript></entry>
-             <entry>v<subscript>10</subscript></entry>
              <entry>v<subscript>9</subscript></entry>
              <entry>v<subscript>8</subscript></entry>
              <entry>v<subscript>7</subscript></entry>
@@ -3374,13 +3350,11 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>v<subscript>1</subscript></entry>
              <entry>v<subscript>0</subscript></entry>
            </row>
-           <row id="MEDIA-BUS-FMT-YVYU12-2X12">
-             <entry>MEDIA_BUS_FMT_YVYU12_2X12</entry>
-             <entry>0x201f</entry>
+           <row id="MEDIA-BUS-FMT-YVYU10-1X20">
+             <entry>MEDIA_BUS_FMT_YVYU10_1X20</entry>
+             <entry>0x200e</entry>
              <entry></entry>
-             &dash-ent-20;
-             <entry>y<subscript>11</subscript></entry>
-             <entry>y<subscript>10</subscript></entry>
+             &dash-ent-12;
              <entry>y<subscript>9</subscript></entry>
              <entry>y<subscript>8</subscript></entry>
              <entry>y<subscript>7</subscript></entry>
@@ -3391,14 +3365,6 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>y<subscript>2</subscript></entry>
              <entry>y<subscript>1</subscript></entry>
              <entry>y<subscript>0</subscript></entry>
-           </row>
-           <row>
-             <entry></entry>
-             <entry></entry>
-             <entry></entry>
-             &dash-ent-20;
-             <entry>v<subscript>11</subscript></entry>
-             <entry>v<subscript>10</subscript></entry>
              <entry>v<subscript>9</subscript></entry>
              <entry>v<subscript>8</subscript></entry>
              <entry>v<subscript>7</subscript></entry>
@@ -3414,9 +3380,7 @@ see <xref linkend="colorspaces" />.</entry>
              <entry></entry>
              <entry></entry>
              <entry></entry>
-             &dash-ent-20;
-             <entry>y<subscript>11</subscript></entry>
-             <entry>y<subscript>10</subscript></entry>
+             &dash-ent-12;
              <entry>y<subscript>9</subscript></entry>
              <entry>y<subscript>8</subscript></entry>
              <entry>y<subscript>7</subscript></entry>
@@ -3427,16 +3391,67 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>y<subscript>2</subscript></entry>
              <entry>y<subscript>1</subscript></entry>
              <entry>y<subscript>0</subscript></entry>
+             <entry>u<subscript>9</subscript></entry>
+             <entry>u<subscript>8</subscript></entry>
+             <entry>u<subscript>7</subscript></entry>
+             <entry>u<subscript>6</subscript></entry>
+             <entry>u<subscript>5</subscript></entry>
+             <entry>u<subscript>4</subscript></entry>
+             <entry>u<subscript>3</subscript></entry>
+             <entry>u<subscript>2</subscript></entry>
+             <entry>u<subscript>1</subscript></entry>
+             <entry>u<subscript>0</subscript></entry>
            </row>
-           <row>
-             <entry></entry>
+           <row id="MEDIA-BUS-FMT-VUY8-1X24">
+             <entry>MEDIA_BUS_FMT_VUY8_1X24</entry>
+             <entry>0x201a</entry>
              <entry></entry>
+             &dash-ent-8;
+             <entry>v<subscript>7</subscript></entry>
+             <entry>v<subscript>6</subscript></entry>
+             <entry>v<subscript>5</subscript></entry>
+             <entry>v<subscript>4</subscript></entry>
+             <entry>v<subscript>3</subscript></entry>
+             <entry>v<subscript>2</subscript></entry>
+             <entry>v<subscript>1</subscript></entry>
+             <entry>v<subscript>0</subscript></entry>
+             <entry>u<subscript>7</subscript></entry>
+             <entry>u<subscript>6</subscript></entry>
+             <entry>u<subscript>5</subscript></entry>
+             <entry>u<subscript>4</subscript></entry>
+             <entry>u<subscript>3</subscript></entry>
+             <entry>u<subscript>2</subscript></entry>
+             <entry>u<subscript>1</subscript></entry>
+             <entry>u<subscript>0</subscript></entry>
+             <entry>y<subscript>7</subscript></entry>
+             <entry>y<subscript>6</subscript></entry>
+             <entry>y<subscript>5</subscript></entry>
+             <entry>y<subscript>4</subscript></entry>
+             <entry>y<subscript>3</subscript></entry>
+             <entry>y<subscript>2</subscript></entry>
+             <entry>y<subscript>1</subscript></entry>
+             <entry>y<subscript>0</subscript></entry>
+           </row>
+           <row id="MEDIA-BUS-FMT-YUV8-1X24">
+             <entry>MEDIA_BUS_FMT_YUV8_1X24</entry>
+             <entry>0x2025</entry>
              <entry></entry>
-             &dash-ent-20;
-             <entry>u<subscript>11</subscript></entry>
-             <entry>u<subscript>10</subscript></entry>
-             <entry>u<subscript>9</subscript></entry>
-             <entry>u<subscript>8</subscript></entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>y<subscript>7</subscript></entry>
+             <entry>y<subscript>6</subscript></entry>
+             <entry>y<subscript>5</subscript></entry>
+             <entry>y<subscript>4</subscript></entry>
+             <entry>y<subscript>3</subscript></entry>
+             <entry>y<subscript>2</subscript></entry>
+             <entry>y<subscript>1</subscript></entry>
+             <entry>y<subscript>0</subscript></entry>
              <entry>u<subscript>7</subscript></entry>
              <entry>u<subscript>6</subscript></entry>
              <entry>u<subscript>5</subscript></entry>
@@ -3445,6 +3460,14 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>u<subscript>2</subscript></entry>
              <entry>u<subscript>1</subscript></entry>
              <entry>u<subscript>0</subscript></entry>
+             <entry>v<subscript>7</subscript></entry>
+             <entry>v<subscript>6</subscript></entry>
+             <entry>v<subscript>5</subscript></entry>
+             <entry>v<subscript>4</subscript></entry>
+             <entry>v<subscript>3</subscript></entry>
+             <entry>v<subscript>2</subscript></entry>
+             <entry>v<subscript>1</subscript></entry>
+             <entry>v<subscript>0</subscript></entry>
            </row>
            <row id="MEDIA-BUS-FMT-UYVY12-1X24">
              <entry>MEDIA_BUS_FMT_UYVY12_1X24</entry>
@@ -3686,6 +3709,80 @@ see <xref linkend="colorspaces" />.</entry>
              <entry>u<subscript>1</subscript></entry>
              <entry>u<subscript>0</subscript></entry>
            </row>
+           <row id="MEDIA-BUS-FMT-YUV10-1X30">
+             <entry>MEDIA_BUS_FMT_YUV10_1X30</entry>
+             <entry>0x2016</entry>
+             <entry></entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>y<subscript>9</subscript></entry>
+             <entry>y<subscript>8</subscript></entry>
+             <entry>y<subscript>7</subscript></entry>
+             <entry>y<subscript>6</subscript></entry>
+             <entry>y<subscript>5</subscript></entry>
+             <entry>y<subscript>4</subscript></entry>
+             <entry>y<subscript>3</subscript></entry>
+             <entry>y<subscript>2</subscript></entry>
+             <entry>y<subscript>1</subscript></entry>
+             <entry>y<subscript>0</subscript></entry>
+             <entry>u<subscript>9</subscript></entry>
+             <entry>u<subscript>8</subscript></entry>
+             <entry>u<subscript>7</subscript></entry>
+             <entry>u<subscript>6</subscript></entry>
+             <entry>u<subscript>5</subscript></entry>
+             <entry>u<subscript>4</subscript></entry>
+             <entry>u<subscript>3</subscript></entry>
+             <entry>u<subscript>2</subscript></entry>
+             <entry>u<subscript>1</subscript></entry>
+             <entry>u<subscript>0</subscript></entry>
+             <entry>v<subscript>9</subscript></entry>
+             <entry>v<subscript>8</subscript></entry>
+             <entry>v<subscript>7</subscript></entry>
+             <entry>v<subscript>6</subscript></entry>
+             <entry>v<subscript>5</subscript></entry>
+             <entry>v<subscript>4</subscript></entry>
+             <entry>v<subscript>3</subscript></entry>
+             <entry>v<subscript>2</subscript></entry>
+             <entry>v<subscript>1</subscript></entry>
+             <entry>v<subscript>0</subscript></entry>
+           </row>
+           <row id="MEDIA-BUS-FMT-AYUV8-1X32">
+             <entry>MEDIA_BUS_FMT_AYUV8_1X32</entry>
+             <entry>0x2017</entry>
+             <entry></entry>
+             <entry>a<subscript>7</subscript></entry>
+             <entry>a<subscript>6</subscript></entry>
+             <entry>a<subscript>5</subscript></entry>
+             <entry>a<subscript>4</subscript></entry>
+             <entry>a<subscript>3</subscript></entry>
+             <entry>a<subscript>2</subscript></entry>
+             <entry>a<subscript>1</subscript></entry>
+             <entry>a<subscript>0</subscript></entry>
+             <entry>y<subscript>7</subscript></entry>
+             <entry>y<subscript>6</subscript></entry>
+             <entry>y<subscript>5</subscript></entry>
+             <entry>y<subscript>4</subscript></entry>
+             <entry>y<subscript>3</subscript></entry>
+             <entry>y<subscript>2</subscript></entry>
+             <entry>y<subscript>1</subscript></entry>
+             <entry>y<subscript>0</subscript></entry>
+             <entry>u<subscript>7</subscript></entry>
+             <entry>u<subscript>6</subscript></entry>
+             <entry>u<subscript>5</subscript></entry>
+             <entry>u<subscript>4</subscript></entry>
+             <entry>u<subscript>3</subscript></entry>
+             <entry>u<subscript>2</subscript></entry>
+             <entry>u<subscript>1</subscript></entry>
+             <entry>u<subscript>0</subscript></entry>
+             <entry>v<subscript>7</subscript></entry>
+             <entry>v<subscript>6</subscript></entry>
+             <entry>v<subscript>5</subscript></entry>
+             <entry>v<subscript>4</subscript></entry>
+             <entry>v<subscript>3</subscript></entry>
+             <entry>v<subscript>2</subscript></entry>
+             <entry>v<subscript>1</subscript></entry>
+             <entry>v<subscript>0</subscript></entry>
+           </row>
          </tbody>
        </tgroup>
       </table>
index ac0f8d9d2a4976a59f6c02b44de1b6859e768134..e98caa1c39bd21ed89ca24e47a85f1733bf38be9 100644 (file)
@@ -136,6 +136,7 @@ Remote Controller chapter.</contrib>
       <year>2012</year>
       <year>2013</year>
       <year>2014</year>
+      <year>2015</year>
       <holder>Bill Dirks, Michael H. Schimek, Hans Verkuil, Martin
 Rubli, Andy Walls, Muralidharan Karicheri, Mauro Carvalho Chehab,
        Pawel Osciak</holder>
@@ -151,6 +152,14 @@ structs, ioctls) must be noted in more detail in the history chapter
 (compat.xml), along with the possible impact on existing drivers and
 applications. -->
 
+      <revision>
+       <revnumber>3.21</revnumber>
+       <date>2015-02-13</date>
+       <authorinitials>mcc</authorinitials>
+       <revremark>Fix documentation for media controller device nodes and add support for DVB device nodes.
+Add support for Tuner sub-device.
+       </revremark>
+      </revision>
       <revision>
        <revnumber>3.19</revnumber>
        <date>2014-12-05</date>
index 1f5ed64cd75a0e5c2aeb3cc0ea4c7ff670aceeea..50cb940cbe5ca97eb915e2044eb7ab2a7780a4f9 100644 (file)
@@ -59,6 +59,11 @@ constant except when switching the video standard. Remember this
 switch can occur implicit when switching the video input or
 output.</para>
 
+<para>Do not use the multiplanar buffer types.  Use <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>
+instead of <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant>
+and use <constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> instead of
+<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant>.</para>
+
     <para>This ioctl must be implemented for video capture or output devices that
 support cropping and/or scaling and/or have non-square pixels, and for overlay devices.</para>
 
@@ -73,9 +78,7 @@ support cropping and/or scaling and/or have non-square pixels, and for overlay d
            <entry>Type of the data stream, set by the application.
 Only these types are valid here:
 <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>,
-<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant>,
-<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant>,
-<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant> and
+<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> and
 <constant>V4L2_BUF_TYPE_VIDEO_OVERLAY</constant>. See <xref linkend="v4l2-buf-type" />.</entry>
          </row>
          <row>
index b036f8963353a2a2f88c336855da9282e7d68fb6..50ccd33948c1cbee6fb8bbd28864681780c1b833 100644 (file)
@@ -64,7 +64,7 @@
            <entry>__u32</entry>
            <entry><structfield>type</structfield></entry>
             <entry></entry>
-           <entry>Type of the event.</entry>
+           <entry>Type of the event, see <xref linkend="event-type" />.</entry>
          </row>
          <row>
            <entry>union</entry>
       </tgroup>
     </table>
 
+    <table frame="none" pgwide="1" id="event-type">
+      <title>Event Types</title>
+      <tgroup cols="3">
+       &cs-def;
+       <tbody valign="top">
+         <row>
+           <entry><constant>V4L2_EVENT_ALL</constant></entry>
+           <entry>0</entry>
+           <entry>All events. V4L2_EVENT_ALL is valid only for
+           VIDIOC_UNSUBSCRIBE_EVENT for unsubscribing all events at once.
+           </entry>
+         </row>
+         <row>
+           <entry><constant>V4L2_EVENT_VSYNC</constant></entry>
+           <entry>1</entry>
+           <entry>This event is triggered on the vertical sync.
+           This event has a &v4l2-event-vsync; associated with it.
+           </entry>
+         </row>
+         <row>
+           <entry><constant>V4L2_EVENT_EOS</constant></entry>
+           <entry>2</entry>
+           <entry>This event is triggered when the end of a stream is reached.
+           This is typically used with MPEG decoders to report to the application
+           when the last of the MPEG stream has been decoded.
+           </entry>
+         </row>
+         <row>
+           <entry><constant>V4L2_EVENT_CTRL</constant></entry>
+           <entry>3</entry>
+           <entry><para>This event requires that the <structfield>id</structfield>
+               matches the control ID from which you want to receive events.
+               This event is triggered if the control's value changes, if a
+               button control is pressed or if the control's flags change.
+               This event has a &v4l2-event-ctrl; associated with it. This struct
+               contains much of the same information as &v4l2-queryctrl; and
+               &v4l2-control;.</para>
+
+               <para>If the event is generated due to a call to &VIDIOC-S-CTRL; or
+               &VIDIOC-S-EXT-CTRLS;, then the event will <emphasis>not</emphasis> be sent to
+               the file handle that called the ioctl function. This prevents
+               nasty feedback loops. If you <emphasis>do</emphasis> want to get the
+               event, then set the <constant>V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK</constant>
+               flag.
+               </para>
+
+               <para>This event type will ensure that no information is lost when
+               more events are raised than there is room internally. In that
+               case the &v4l2-event-ctrl; of the second-oldest event is kept,
+               but the <structfield>changes</structfield> field of the
+               second-oldest event is ORed with the <structfield>changes</structfield>
+               field of the oldest event.</para>
+           </entry>
+         </row>
+         <row>
+           <entry><constant>V4L2_EVENT_FRAME_SYNC</constant></entry>
+           <entry>4</entry>
+           <entry>
+             <para>Triggered immediately when the reception of a
+             frame has begun. This event has a
+             &v4l2-event-frame-sync; associated with it.</para>
+
+             <para>If the hardware needs to be stopped in the case of a
+             buffer underrun it might not be able to generate this event.
+             In such cases the <structfield>frame_sequence</structfield>
+             field in &v4l2-event-frame-sync; will not be incremented. This
+             causes two consecutive frame sequence numbers to have n times
+             frame interval in between them.</para>
+           </entry>
+         </row>
+         <row>
+           <entry><constant>V4L2_EVENT_SOURCE_CHANGE</constant></entry>
+           <entry>5</entry>
+           <entry>
+             <para>This event is triggered when a source parameter change is
+              detected during runtime by the video device. It can be a
+              runtime resolution change triggered by a video decoder or the
+              format change happening on an input connector.
+              This event requires that the <structfield>id</structfield>
+              matches the input index (when used with a video device node)
+              or the pad index (when used with a subdevice node) from which
+              you want to receive events.</para>
+
+              <para>This event has a &v4l2-event-src-change; associated
+             with it. The <structfield>changes</structfield> bitfield denotes
+             what has changed for the subscribed pad. If multiple events
+             occurred before application could dequeue them, then the changes
+             will have the ORed value of all the events generated.</para>
+           </entry>
+         </row>
+         <row>
+           <entry><constant>V4L2_EVENT_MOTION_DET</constant></entry>
+           <entry>6</entry>
+           <entry>
+             <para>Triggered whenever the motion detection state for one or more of the regions
+             changes. This event has a &v4l2-event-motion-det; associated with it.</para>
+           </entry>
+         </row>
+         <row>
+           <entry><constant>V4L2_EVENT_PRIVATE_START</constant></entry>
+           <entry>0x08000000</entry>
+           <entry>Base event number for driver-private events.</entry>
+         </row>
+       </tbody>
+      </tgroup>
+    </table>
+
     <table frame="none" pgwide="1" id="v4l2-event-vsync">
       <title>struct <structname>v4l2_event_vsync</structname></title>
       <tgroup cols="3">
            <entry>__u32</entry>
            <entry><structfield>changes</structfield></entry>
            <entry></entry>
-           <entry>A bitmask that tells what has changed. See <xref linkend="changes-flags" />.</entry>
+           <entry>A bitmask that tells what has changed. See <xref linkend="ctrl-changes-flags" />.</entry>
          </row>
          <row>
            <entry>__u32</entry>
       </tgroup>
     </table>
 
-    <table pgwide="1" frame="none" id="changes-flags">
-      <title>Changes</title>
+    <table pgwide="1" frame="none" id="ctrl-changes-flags">
+      <title>Control Changes</title>
       <tgroup cols="3">
        &cs-def;
        <tbody valign="top">
            <entry><constant>V4L2_EVENT_CTRL_CH_VALUE</constant></entry>
            <entry>0x0001</entry>
            <entry>This control event was triggered because the value of the control
-               changed. Special case: if a button control is pressed, then this
-               event is sent as well, even though there is not explicit value
-               associated with a button control.</entry>
+               changed. Special cases: Volatile controls do no generate this event;
+               If a control has the <constant>V4L2_CTRL_FLAG_EXECUTE_ON_WRITE</constant>
+               flag set, then this event is sent as well, regardless its value.</entry>
          </row>
          <row>
            <entry><constant>V4L2_EVENT_CTRL_CH_FLAGS</constant></entry>
index 75c6a93de3c173246aff4763da48cfdc4b3ce81f..e6c4efb9e8b412517b7b71f2566d0ada66550bf2 100644 (file)
@@ -70,6 +70,11 @@ structure or returns the &EINVAL; if cropping is not supported.</para>
 <constant>VIDIOC_S_CROP</constant> ioctl with a pointer to this
 structure.</para>
 
+<para>Do not use the multiplanar buffer types.  Use <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>
+instead of <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant>
+and use <constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> instead of
+<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant>.</para>
+
     <para>The driver first adjusts the requested dimensions against
 hardware limits, &ie; the bounds given by the capture/output window,
 and it rounds to the closest possible values of horizontal and
index c4336577ff066a34ba7149ffde35e5e93ed2ef2c..764b635ed4cf7102e04eb3ae0de2a24f0a7f1238 100644 (file)
@@ -318,10 +318,20 @@ can't generate such frequencies, then the flag will also be cleared.
          </row>
          <row>
            <entry>V4L2_DV_FL_HALF_LINE</entry>
-           <entry>Specific to interlaced formats: if set, then field 1 (aka the odd field)
-is really one half-line longer and field 2 (aka the even field) is really one half-line
-shorter, so each field has exactly the same number of half-lines. Whether half-lines can be
-detected or used depends on the hardware.
+           <entry>Specific to interlaced formats: if set, then the vertical frontporch
+of field 1 (aka the odd field) is really one half-line longer and the vertical backporch
+of field 2 (aka the even field) is really one half-line shorter, so each field has exactly
+the same number of half-lines. Whether half-lines can be detected or used depends on
+the hardware.
+           </entry>
+         </row>
+         <row>
+           <entry>V4L2_DV_FL_IS_CE_VIDEO</entry>
+           <entry>If set, then this is a Consumer Electronics (CE) video format.
+Such formats differ from other formats (commonly called IT formats) in that if
+R'G'B' encoding is used then by default the R'G'B' values use limited range
+(i.e. 16-235) as opposed to full range (i.e. 0-255). All formats defined in CEA-861
+except for the 640x480p59.94 format are CE formats.
            </entry>
          </row>
        </tbody>
index 20460730b02ca242e0ba5d096761ac00ea8239af..77607cc196889b6fc14e412d72fc229fdf3210d0 100644 (file)
@@ -240,9 +240,9 @@ where padding bytes after the last line of an image cross a system
 page boundary. Capture devices may write padding bytes, the value is
 undefined. Output devices ignore the contents of padding
 bytes.</para><para>When the image format is planar the
-<structfield>bytesperline</structfield> value applies to the largest
+<structfield>bytesperline</structfield> value applies to the first
 plane and is divided by the same factor as the
-<structfield>width</structfield> field for any smaller planes. For
+<structfield>width</structfield> field for the other planes. For
 example the Cb and Cr planes of a YUV 4:2:0 image have half as many
 padding bytes following each line as the Y plane. To avoid ambiguities
 drivers must return a <structfield>bytesperline</structfield> value
index 9c04ac8661b10eed113e74fb57d7a14b2fb792b1..0bb5c060db27847a7a93e2f22ae51743fe413d11 100644 (file)
@@ -60,8 +60,8 @@
 
 <para>To query the cropping (composing) rectangle set &v4l2-selection;
 <structfield> type </structfield> field to the respective buffer type.
-Do not use multiplanar buffers.  Use <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>
-instead of <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant>.  Use
+Do not use the multiplanar buffer types.  Use <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>
+instead of <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant> and use
 <constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> instead of
 <constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant>.  The next step is
 setting the value of &v4l2-selection; <structfield>target</structfield> field
index d0c5e604f014f3080966510d39cf7877e018d2be..20fda75a012dc130e8a94b1935d5efe574a5dae3 100644 (file)
@@ -102,10 +102,10 @@ The bus_info must start with "PCI:" for PCI boards, "PCIe:" for PCI Express boar
            <entry>__u32</entry>
            <entry><structfield>version</structfield></entry>
            <entry><para>Version number of the driver.</para>
-<para>Starting on kernel 3.1, the version reported is provided per
-V4L2 subsystem, following the same Kernel numberation scheme. However, it
-should not always return the same version as the kernel, if, for example,
-an stable or distribution-modified kernel uses the V4L2 stack from a
+<para>Starting with kernel 3.1, the version reported is provided by the
+V4L2 subsystem following the kernel numbering scheme. However, it
+may not always return the same version as the kernel if, for example,
+a stable or distribution-modified kernel uses the V4L2 stack from a
 newer kernel.</para>
 <para>The version number is formatted using the
 <constant>KERNEL_VERSION()</constant> macro:</para></entry>
index 2bd98fd7a4e51ac542d423ab74e335b8de0a9e7a..dc83ad70f8dc8ff30c1b31c4cb833df169de80b2 100644 (file)
@@ -600,7 +600,9 @@ writing a value will cause the device to carry out a given action
 changes continuously. A typical example would be the current gain value if the device
 is in auto-gain mode. In such a case the hardware calculates the gain value based on
 the lighting conditions which can change over time. Note that setting a new value for
-a volatile control will have no effect. The new value will just be ignored.</entry>
+a volatile control will have no effect and no <constant>V4L2_EVENT_CTRL_CH_VALUE</constant>
+will be sent, unless the <constant>V4L2_CTRL_FLAG_EXECUTE_ON_WRITE</constant> flag
+(see below) is also set. Otherwise the new value will just be ignored.</entry>
          </row>
          <row>
            <entry><constant>V4L2_CTRL_FLAG_HAS_PAYLOAD</constant></entry>
@@ -610,6 +612,14 @@ using one of the pointer fields of &v4l2-ext-control;. This flag is set for cont
 that are an array, string, or have a compound type. In all cases you have to set a
 pointer to memory containing the payload of the control.</entry>
          </row>
+         <row>
+           <entry><constant>V4L2_CTRL_FLAG_EXECUTE_ON_WRITE</constant></entry>
+           <entry>0x0200</entry>
+           <entry>The value provided to the control will be propagated to the driver
+even if remains constant. This is required when the control represents an action
+on the hardware. For example: clearing an error flag or triggering the flash. All the
+controls of the type <constant>V4L2_CTRL_TYPE_BUTTON</constant> have this flag set.</entry>
+         </row>
        </tbody>
       </tgroup>
     </table>
index 2f8f4f0a023596c5b75d0ec22e8ce3d1be9ae350..cff59f5cbf044ce1c2545be614afb4fd74b25762 100644 (file)
@@ -67,9 +67,9 @@
 
     <para>To enumerate frame intervals applications initialize the
     <structfield>index</structfield>, <structfield>pad</structfield>,
-    <structfield>code</structfield>, <structfield>width</structfield> and
-    <structfield>height</structfield> fields of
-    &v4l2-subdev-frame-interval-enum; and call the
+    <structfield>which</structfield>, <structfield>code</structfield>,
+    <structfield>width</structfield> and <structfield>height</structfield>
+    fields of &v4l2-subdev-frame-interval-enum; and call the
     <constant>VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL</constant> ioctl with a pointer
     to this structure. Drivers fill the rest of the structure or return
     an &EINVAL; if one of the input fields is invalid. All frame intervals are
          </row>
          <row>
            <entry>__u32</entry>
-           <entry><structfield>reserved</structfield>[9]</entry>
+           <entry><structfield>which</structfield></entry>
+           <entry>Frame intervals to be enumerated, from &v4l2-subdev-format-whence;.</entry>
+         </row>
+         <row>
+           <entry>__u32</entry>
+           <entry><structfield>reserved</structfield>[8]</entry>
            <entry>Reserved for future extensions. Applications and drivers must
            set the array to zero.</entry>
          </row>
index 79ce42b7c60cf87b363fa5bc02ad1281358b83d8..abd545ede67ae1dd357af54b45b896c59163d3c8 100644 (file)
@@ -61,9 +61,9 @@
     ioctl.</para>
 
     <para>To enumerate frame sizes applications initialize the
-    <structfield>pad</structfield>, <structfield>code</structfield> and
-    <structfield>index</structfield> fields of the
-    &v4l2-subdev-mbus-code-enum; and call the
+    <structfield>pad</structfield>, <structfield>which</structfield> ,
+    <structfield>code</structfield> and <structfield>index</structfield>
+    fields of the &v4l2-subdev-mbus-code-enum; and call the
     <constant>VIDIOC_SUBDEV_ENUM_FRAME_SIZE</constant> ioctl with a pointer to
     the structure. Drivers fill the minimum and maximum frame sizes or return
     an &EINVAL; if one of the input parameters is invalid.</para>
          </row>
          <row>
            <entry>__u32</entry>
-           <entry><structfield>reserved</structfield>[9]</entry>
+           <entry><structfield>which</structfield></entry>
+           <entry>Frame sizes to be enumerated, from &v4l2-subdev-format-whence;.</entry>
+         </row>
+         <row>
+           <entry>__u32</entry>
+           <entry><structfield>reserved</structfield>[8]</entry>
            <entry>Reserved for future extensions. Applications and drivers must
            set the array to zero.</entry>
          </row>
index a6b3432449f64a8cab4fe9b5c5c84a7b8aa0412a..0bcb278fd062604f66a902b8a41c6ba166fd205c 100644 (file)
@@ -56,8 +56,8 @@
     </note>
 
     <para>To enumerate media bus formats available at a given sub-device pad
-    applications initialize the <structfield>pad</structfield> and
-    <structfield>index</structfield> fields of &v4l2-subdev-mbus-code-enum; and
+    applications initialize the <structfield>pad</structfield>, <structfield>which</structfield>
+    and <structfield>index</structfield> fields of &v4l2-subdev-mbus-code-enum; and
     call the <constant>VIDIOC_SUBDEV_ENUM_MBUS_CODE</constant> ioctl with a
     pointer to this structure. Drivers fill the rest of the structure or return
     an &EINVAL; if either the <structfield>pad</structfield> or
          </row>
          <row>
            <entry>__u32</entry>
-           <entry><structfield>reserved</structfield>[9]</entry>
+           <entry><structfield>which</structfield></entry>
+           <entry>Media bus format codes to be enumerated, from &v4l2-subdev-format-whence;.</entry>
+         </row>
+         <row>
+           <entry>__u32</entry>
+           <entry><structfield>reserved</structfield>[8]</entry>
            <entry>Reserved for future extensions. Applications and drivers must
            set the array to zero.</entry>
          </row>
index d7c9365ecdbe245e05aee3875ee09ab5b8fa0199..d0332f6109296e1eccd530ee6e85da157b3855e3 100644 (file)
@@ -60,7 +60,9 @@
          <row>
            <entry>__u32</entry>
            <entry><structfield>type</structfield></entry>
-           <entry>Type of the event.</entry>
+           <entry>Type of the event, see <xref linkend="event-type" />. Note that
+<constant>V4L2_EVENT_ALL</constant> can be used with VIDIOC_UNSUBSCRIBE_EVENT
+for unsubscribing all events at once.</entry>
          </row>
          <row>
            <entry>__u32</entry>
       </tgroup>
     </table>
 
-    <table frame="none" pgwide="1" id="event-type">
-      <title>Event Types</title>
-      <tgroup cols="3">
-       &cs-def;
-       <tbody valign="top">
-         <row>
-           <entry><constant>V4L2_EVENT_ALL</constant></entry>
-           <entry>0</entry>
-           <entry>All events. V4L2_EVENT_ALL is valid only for
-           VIDIOC_UNSUBSCRIBE_EVENT for unsubscribing all events at once.
-           </entry>
-         </row>
-         <row>
-           <entry><constant>V4L2_EVENT_VSYNC</constant></entry>
-           <entry>1</entry>
-           <entry>This event is triggered on the vertical sync.
-           This event has a &v4l2-event-vsync; associated with it.
-           </entry>
-         </row>
-         <row>
-           <entry><constant>V4L2_EVENT_EOS</constant></entry>
-           <entry>2</entry>
-           <entry>This event is triggered when the end of a stream is reached.
-           This is typically used with MPEG decoders to report to the application
-           when the last of the MPEG stream has been decoded.
-           </entry>
-         </row>
-         <row>
-           <entry><constant>V4L2_EVENT_CTRL</constant></entry>
-           <entry>3</entry>
-           <entry><para>This event requires that the <structfield>id</structfield>
-               matches the control ID from which you want to receive events.
-               This event is triggered if the control's value changes, if a
-               button control is pressed or if the control's flags change.
-               This event has a &v4l2-event-ctrl; associated with it. This struct
-               contains much of the same information as &v4l2-queryctrl; and
-               &v4l2-control;.</para>
-
-               <para>If the event is generated due to a call to &VIDIOC-S-CTRL; or
-               &VIDIOC-S-EXT-CTRLS;, then the event will <emphasis>not</emphasis> be sent to
-               the file handle that called the ioctl function. This prevents
-               nasty feedback loops. If you <emphasis>do</emphasis> want to get the
-               event, then set the <constant>V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK</constant>
-               flag.
-               </para>
-
-               <para>This event type will ensure that no information is lost when
-               more events are raised than there is room internally. In that
-               case the &v4l2-event-ctrl; of the second-oldest event is kept,
-               but the <structfield>changes</structfield> field of the
-               second-oldest event is ORed with the <structfield>changes</structfield>
-               field of the oldest event.</para>
-           </entry>
-         </row>
-         <row>
-           <entry><constant>V4L2_EVENT_FRAME_SYNC</constant></entry>
-           <entry>4</entry>
-           <entry>
-             <para>Triggered immediately when the reception of a
-             frame has begun. This event has a
-             &v4l2-event-frame-sync; associated with it.</para>
-
-             <para>If the hardware needs to be stopped in the case of a
-             buffer underrun it might not be able to generate this event.
-             In such cases the <structfield>frame_sequence</structfield>
-             field in &v4l2-event-frame-sync; will not be incremented. This
-             causes two consecutive frame sequence numbers to have n times
-             frame interval in between them.</para>
-           </entry>
-         </row>
-         <row>
-           <entry><constant>V4L2_EVENT_SOURCE_CHANGE</constant></entry>
-           <entry>5</entry>
-           <entry>
-             <para>This event is triggered when a source parameter change is
-              detected during runtime by the video device. It can be a
-              runtime resolution change triggered by a video decoder or the
-              format change happening on an input connector.
-              This event requires that the <structfield>id</structfield>
-              matches the input index (when used with a video device node)
-              or the pad index (when used with a subdevice node) from which
-              you want to receive events.</para>
-
-              <para>This event has a &v4l2-event-src-change; associated
-             with it. The <structfield>changes</structfield> bitfield denotes
-             what has changed for the subscribed pad. If multiple events
-             occurred before application could dequeue them, then the changes
-             will have the ORed value of all the events generated.</para>
-           </entry>
-         </row>
-         <row>
-           <entry><constant>V4L2_EVENT_MOTION_DET</constant></entry>
-           <entry>6</entry>
-           <entry>
-             <para>Triggered whenever the motion detection state for one or more of the regions
-             changes. This event has a &v4l2-event-motion-det; associated with it.</para>
-           </entry>
-         </row>
-         <row>
-           <entry><constant>V4L2_EVENT_PRIVATE_START</constant></entry>
-           <entry>0x08000000</entry>
-           <entry>Base event number for driver-private events.</entry>
-         </row>
-       </tbody>
-      </tgroup>
-    </table>
-
     <table pgwide="1" frame="none" id="event-flags">
       <title>Event Flags</title>
       <tgroup cols="3">
index 653d5d739d7ff5b55dbcd8d606b5d7e1da51a99f..31d1d658827f082f66c88c3147e99be3321635cf 100644 (file)
@@ -505,7 +505,10 @@ at module load time (for a module) with:
 
 The addresses are normal I2C addresses.  The adapter is the string
 name of the adapter, as shown in /sys/class/i2c-adapter/i2c-<n>/name.
-It is *NOT* i2c-<n> itself.
+It is *NOT* i2c-<n> itself.  Also, the comparison is done ignoring
+spaces, so if the name is "This is an I2C chip" you can say
+adapter_name=ThisisanI2cchip.  This is because it's hard to pass in
+spaces in kernel parameters.
 
 The debug flags are bit flags for each BMC found, they are:
 IPMI messages: 1, driver state: 2, timing: 4, I2C probe: 8
index 6883a1b9b351d9942112a7c450d53f3152453a4a..bc0548201755e1a8d29614bccbd78fcbbe5a34ae 100644 (file)
@@ -1,4 +1,4 @@
-subdir-y := accounting arm auxdisplay blackfin connector \
+subdir-y := accounting auxdisplay blackfin connector \
        filesystems filesystems ia64 laptops mic misc-devices \
        networking pcmcia prctl ptp spi timers vDSO video4linux \
        watchdog
index 750401f9134190a210c8c24089a08ca9cb16559c..15dfce708ebf6ec3263ac0d66ff2b6f3a57471d4 100644 (file)
@@ -253,7 +253,7 @@ input driver:
 GPIO support
 ~~~~~~~~~~~~
 ACPI 5 introduced two new resources to describe GPIO connections: GpioIo
-and GpioInt. These resources are used be used to pass GPIO numbers used by
+and GpioInt. These resources can be used to pass GPIO numbers used by
 the device to the driver. ACPI 5.1 extended this with _DSD (Device
 Specific Data) which made it possible to name the GPIOs among other things.
 
index ae36fcf86dc7213c8b1a72bb0e698f89e51c878f..f35dad11f0de78955a2e4661f8ef5c9d51eb27d9 100644 (file)
@@ -1,9 +1,9 @@
 _DSD Device Properties Related to GPIO
 --------------------------------------
 
-With the release of ACPI 5.1 and the _DSD configuration objecte names
-can finally be given to GPIOs (and other things as well) returned by
-_CRS.  Previously, we were only able to use an integer index to find
+With the release of ACPI 5.1, the _DSD configuration object finally
+allows names to be given to GPIOs (and other things as well) returned
+by _CRS.  Previously, we were only able to use an integer index to find
 the corresponding GPIO, which is pretty error prone (it depends on
 the _CRS output ordering, for example).
 
index 8edb9007844e1b6c6f49655b4e71df4da845eff1..dea011c8d7c718a8ff7a37dea7d35a81d0f67271 100644 (file)
@@ -10,8 +10,6 @@ IXP4xx
        - Intel IXP4xx Network processor.
 Makefile
        - Build sourcefiles as part of the Documentation-build for arm
-msm/
-       - MSM specific documentation
 Netwinder
        - Netwinder specific documentation
 Porting
diff --git a/Documentation/arm/Makefile b/Documentation/arm/Makefile
deleted file mode 100644 (file)
index 732c770..0000000
+++ /dev/null
@@ -1 +0,0 @@
-subdir-y := SH-Mobile
index 17453794fca5d518be980b1350784a9e3a11ecd2..18a775d101723be46320bbf475f04c066b4c3ea2 100644 (file)
@@ -96,6 +96,11 @@ EBU Armada family
        88F6820
        88F6828
 
+  Armada 390/398 Flavors:
+       88F6920
+       88F6928
+    Product infos: http://www.marvell.com/embedded-processors/armada-39x/
+
   Armada XP Flavors:
         MV78230
         MV78260
diff --git a/Documentation/arm/SH-Mobile/Makefile b/Documentation/arm/SH-Mobile/Makefile
deleted file mode 100644 (file)
index bca8a7e..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-# List of programs to build
-hostprogs-y := vrl4
-
-# Tell kbuild to always build the programs
-always := $(hostprogs-y)
-
-HOSTCFLAGS_vrl4.o += -I$(objtree)/usr/include -I$(srctree)/tools/include
diff --git a/Documentation/arm/SH-Mobile/vrl4.c b/Documentation/arm/SH-Mobile/vrl4.c
deleted file mode 100644 (file)
index f4cd8ad..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * vrl4 format generator
- *
- * Copyright (C) 2010 Simon Horman
- *
- * 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.
- */
-
-/*
- * usage: vrl4 < zImage > out
- *       dd if=out of=/dev/sdx bs=512 seek=1 # Write the image to sector 1
- *
- * Reads a zImage from stdin and writes a vrl4 image to stdout.
- * In practice this means writing a padded vrl4 header to stdout followed
- * by the zImage.
- *
- * The padding places the zImage at ALIGN bytes into the output.
- * The vrl4 uses ALIGN + START_BASE as the start_address.
- * This is where the mask ROM will jump to after verifying the header.
- *
- * The header sets copy_size to min(sizeof(zImage), MAX_BOOT_PROG_LEN) + ALIGN.
- * That is, the mask ROM will load the padded header (ALIGN bytes)
- * And then MAX_BOOT_PROG_LEN bytes of the image, or the entire image,
- * whichever is smaller.
- *
- * The zImage is not modified in any way.
- */
-
-#define _BSD_SOURCE
-#include <endian.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <errno.h>
-#include <tools/endian.h>
-
-struct hdr {
-       uint32_t magic1;
-       uint32_t reserved1;
-       uint32_t magic2;
-       uint32_t reserved2;
-       uint16_t copy_size;
-       uint16_t boot_options;
-       uint32_t reserved3;
-       uint32_t start_address;
-       uint32_t reserved4;
-       uint32_t reserved5;
-       char     reserved6[308];
-};
-
-#define DECLARE_HDR(h)                                 \
-       struct hdr (h) = {                              \
-               .magic1 =       htole32(0xea000000),    \
-               .reserved1 =    htole32(0x56),          \
-               .magic2 =       htole32(0xe59ff008),    \
-               .reserved3 =    htole16(0x1) }
-
-/* Align to 512 bytes, the MMCIF sector size */
-#define ALIGN_BITS     9
-#define ALIGN          (1 << ALIGN_BITS)
-
-#define START_BASE     0xe55b0000
-
-/*
- * With an alignment of 512 the header uses the first sector.
- * There is a 128 sector (64kbyte) limit on the data loaded by the mask ROM.
- * So there are 127 sectors left for the boot programme. But in practice
- * Only a small portion of a zImage is needed, 16 sectors should be more
- * than enough.
- *
- * Note that this sets how much of the zImage is copied by the mask ROM.
- * The entire zImage is present after the header and is loaded
- * by the code in the boot program (which is the first portion of the zImage).
- */
-#define        MAX_BOOT_PROG_LEN (16 * 512)
-
-#define ROUND_UP(x)    ((x + ALIGN - 1) & ~(ALIGN - 1))
-
-static ssize_t do_read(int fd, void *buf, size_t count)
-{
-       size_t offset = 0;
-       ssize_t l;
-
-       while (offset < count) {
-               l = read(fd, buf + offset, count - offset);
-               if (!l)
-                       break;
-               if (l < 0) {
-                       if (errno == EAGAIN || errno == EWOULDBLOCK)
-                               continue;
-                       perror("read");
-                       return -1;
-               }
-               offset += l;
-       }
-
-       return offset;
-}
-
-static ssize_t do_write(int fd, const void *buf, size_t count)
-{
-       size_t offset = 0;
-       ssize_t l;
-
-       while (offset < count) {
-               l = write(fd, buf + offset, count - offset);
-               if (l < 0) {
-                       if (errno == EAGAIN || errno == EWOULDBLOCK)
-                               continue;
-                       perror("write");
-                       return -1;
-               }
-               offset += l;
-       }
-
-       return offset;
-}
-
-static ssize_t write_zero(int fd, size_t len)
-{
-       size_t i = len;
-
-       while (i--) {
-               const char x = 0;
-               if (do_write(fd, &x, 1) < 0)
-                       return -1;
-       }
-
-       return len;
-}
-
-int main(void)
-{
-       DECLARE_HDR(hdr);
-       char boot_program[MAX_BOOT_PROG_LEN];
-       size_t aligned_hdr_len, alligned_prog_len;
-       ssize_t prog_len;
-
-       prog_len = do_read(0, boot_program, sizeof(boot_program));
-       if (prog_len <= 0)
-               return -1;
-
-       aligned_hdr_len = ROUND_UP(sizeof(hdr));
-       hdr.start_address = htole32(START_BASE + aligned_hdr_len);
-       alligned_prog_len = ROUND_UP(prog_len);
-       hdr.copy_size = htole16(aligned_hdr_len + alligned_prog_len);
-
-       if (do_write(1, &hdr, sizeof(hdr)) < 0)
-               return -1;
-       if (write_zero(1, aligned_hdr_len - sizeof(hdr)) < 0)
-               return -1;
-
-       if (do_write(1, boot_program, prog_len) < 0)
-               return 1;
-
-       /* Write out the rest of the kernel */
-       while (1) {
-               prog_len = do_read(0, boot_program, sizeof(boot_program));
-               if (prog_len < 0)
-                       return 1;
-               if (prog_len == 0)
-                       break;
-               if (do_write(1, boot_program, prog_len) < 0)
-                       return 1;
-       }
-
-       return 0;
-}
diff --git a/Documentation/arm/SH-Mobile/zboot-rom-mmcif.txt b/Documentation/arm/SH-Mobile/zboot-rom-mmcif.txt
deleted file mode 100644 (file)
index efff8ae..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-ROM-able zImage boot from MMC
------------------------------
-
-An ROM-able zImage compiled with ZBOOT_ROM_MMCIF may be written to MMC and
-SuperH Mobile ARM will to boot directly from the MMCIF hardware block.
-
-This is achieved by the mask ROM loading the first portion of the image into
-MERAM and then jumping to it. This portion contains loader code which
-copies the entire image to SDRAM and jumps to it. From there the zImage
-boot code proceeds as normal, uncompressing the image into its final
-location and then jumping to it.
-
-This code has been tested on an AP4EB board using the developer 1A eMMC
-boot mode which is configured using the following jumper settings.
-The board used for testing required a patched mask ROM in order for
-this mode to function.
-
-   8 7 6 5 4 3 2 1
-   x|x|x|x|x| |x|
-S4 -+-+-+-+-+-+-+-
-    | | | | |x| |x on
-
-The zImage must be written to the MMC card at sector 1 (512 bytes) in
-vrl4 format. A utility vrl4 is supplied to accomplish this.
-
-e.g.
-       vrl4 < zImage | dd of=/dev/sdX bs=512 seek=1
-
-A dual-voltage MMC 4.0 card was used for testing.
diff --git a/Documentation/arm/SH-Mobile/zboot-rom-sdhi.txt b/Documentation/arm/SH-Mobile/zboot-rom-sdhi.txt
deleted file mode 100644 (file)
index 4419598..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-ROM-able zImage boot from eSD
------------------------------
-
-An ROM-able zImage compiled with ZBOOT_ROM_SDHI may be written to eSD and
-SuperH Mobile ARM will to boot directly from the SDHI hardware block.
-
-This is achieved by the mask ROM loading the first portion of the image into
-MERAM and then jumping to it. This portion contains loader code which
-copies the entire image to SDRAM and jumps to it. From there the zImage
-boot code proceeds as normal, uncompressing the image into its final
-location and then jumping to it.
-
-This code has been tested on an mackerel board using the developer 1A eSD
-boot mode which is configured using the following jumper settings.
-
-   8 7 6 5 4 3 2 1
-   x|x|x|x| |x|x|
-S4 -+-+-+-+-+-+-+-
-    | | | |x| | |x on
-
-The eSD card needs to be present in SDHI slot 1 (CN7).
-As such S1 and S33 also need to be configured as per
-the notes in arch/arm/mach-shmobile/board-mackerel.c.
-
-A partial zImage must be written to physical partition #1 (boot)
-of the eSD at sector 0 in vrl4 format. A utility vrl4 is supplied to
-accomplish this.
-
-e.g.
-       vrl4 < zImage | dd of=/dev/sdX bs=512 count=17
-
-A full copy of _the same_ zImage should be written to physical partition #1
-(boot) of the eSD at sector 0. This should _not_ be in vrl4 format.
-
-       vrl4 < zImage | dd of=/dev/sdX bs=512
-
-Note: The commands above assume that the physical partition has been
-switched. No such facility currently exists in the Linux Kernel.
-
-Physical partitions are described in the eSD specification.  At the time of
-writing they are not the same as partitions that are typically configured
-using fdisk and visible through /proc/partitions
diff --git a/Documentation/arm/msm/gpiomux.txt b/Documentation/arm/msm/gpiomux.txt
deleted file mode 100644 (file)
index 67a8162..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-This document provides an overview of the msm_gpiomux interface, which
-is used to provide gpio pin multiplexing and configuration on mach-msm
-targets.
-
-History
-=======
-
-The first-generation API for gpio configuration & multiplexing on msm
-is the function gpio_tlmm_config().  This function has a few notable
-shortcomings, which led to its deprecation and replacement by gpiomux:
-
-The 'disable' parameter:  Setting the second parameter to
-gpio_tlmm_config to GPIO_CFG_DISABLE tells the peripheral
-processor in charge of the subsystem to perform a look-up into a
-low-power table and apply the low-power/sleep setting for the pin.
-As the msm family evolved this became problematic. Not all pins
-have sleep settings, not all peripheral processors will accept requests
-to apply said sleep settings, and not all msm targets have their gpio
-subsystems managed by a peripheral processor. In order to get consistent
-behavior on all targets, drivers are forced to ignore this parameter,
-rendering it useless.
-
-The 'direction' flag: for all mux-settings other than raw-gpio (0),
-the output-enable bit of a gpio is hard-wired to a known
-input (usually VDD or ground).  For those settings, the direction flag
-is meaningless at best, and deceptive at worst.  In addition, using the
-direction flag to change output-enable (OE) directly can cause trouble in
-gpiolib, which has no visibility into gpio direction changes made
-in this way.  Direction control in gpio mode should be made through gpiolib.
-
-Key Features of gpiomux
-=======================
-
-- A consistent interface across all generations of msm.  Drivers can expect
-the same results on every target.
-- gpiomux plays nicely with gpiolib.  Functions that should belong to gpiolib
-are left to gpiolib and not duplicated here.  gpiomux is written with the
-intent that gpio_chips will call gpiomux reference-counting methods
-from their request() and free() hooks, providing full integration.
-- Tabular configuration.  Instead of having to call gpio_tlmm_config
-hundreds of times, gpio configuration is placed in a single table.
-- Per-gpio sleep.  Each gpio is individually reference counted, allowing only
-those lines which are in use to be put in high-power states.
-- 0 means 'do nothing': all flags are designed so that the default memset-zero
-equates to a sensible default of 'no configuration', preventing users
-from having to provide hundreds of 'no-op' configs for unused or
-unwanted lines.
-
-Usage
-=====
-
-To use gpiomux, provide configuration information for relevant gpio lines
-in the msm_gpiomux_configs table.  Since a 0 equates to "unconfigured",
-only those lines to be managed by gpiomux need to be specified.  Here
-is a completely fictional example:
-
-struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {
-       [12] = {
-               .active = GPIOMUX_VALID | GPIOMUX_DRV_8MA | GPIOMUX_FUNC_1,
-               .suspended = GPIOMUX_VALID | GPIOMUX_PULL_DOWN,
-       },
-       [34] = {
-               .suspended = GPIOMUX_VALID | GPIOMUX_PULL_DOWN,
-       },
-};
-
-To indicate that a gpio is in use, call msm_gpiomux_get() to increase
-its reference count.  To decrease the reference count, call msm_gpiomux_put().
-
-The effect of this configuration is as follows:
-
-When the system boots, gpios 12 and 34 will be initialized with their
-'suspended' configurations.  All other gpios, which were left unconfigured,
-will not be touched.
-
-When msm_gpiomux_get() is called on gpio 12 to raise its reference count
-above 0, its active configuration will be applied.  Since no other gpio
-line has a valid active configuration, msm_gpiomux_get() will have no
-effect on any other line.
-
-When msm_gpiomux_put() is called on gpio 12 or 34 to drop their reference
-count to 0, their suspended configurations will be applied.
-Since no other gpio line has a valid suspended configuration, no other
-gpio line will be effected by msm_gpiomux_put().  Since gpio 34 has no valid
-active configuration, this is effectively a no-op for gpio 34 as well,
-with one small caveat, see the section "About Output-Enable Settings".
-
-All of the GPIOMUX_VALID flags may seem like unnecessary overhead, but
-they address some important issues.  As unused entries (all those
-except 12 and 34) are zero-filled, gpiomux needs a way to distinguish
-the used fields from the unused.  In addition, the all-zero pattern
-is a valid configuration!  Therefore, gpiomux defines an additional bit
-which is used to indicate when a field is used.  This has the pleasant
-side-effect of allowing calls to msm_gpiomux_write to use '0' to indicate
-that a value should not be changed:
-
-  msm_gpiomux_write(0, GPIOMUX_VALID, 0);
-
-replaces the active configuration of gpio 0 with an all-zero configuration,
-but leaves the suspended configuration as it was.
-
-Static Configurations
-=====================
-
-To install a static configuration, which is applied at boot and does
-not change after that, install a configuration with a suspended component
-but no active component, as in the previous example:
-
-       [34] = {
-               .suspended = GPIOMUX_VALID | GPIOMUX_PULL_DOWN,
-       },
-
-The suspended setting is applied during boot, and the lack of any valid
-active setting prevents any other setting from being applied at runtime.
-If other subsystems attempting to access the line is a concern, one could
-*really* anchor the configuration down by calling msm_gpiomux_get on the
-line at initialization to move the line into active mode.  With the line
-held, it will never be re-suspended, and with no valid active configuration,
-no new configurations will be applied.
-
-But then, if having other subsystems grabbing for the line is truly a concern,
-it should be reserved with gpio_request instead, which carries an implicit
-msm_gpiomux_get.
-
-gpiomux and gpiolib
-===================
-
-It is expected that msm gpio_chips will call msm_gpiomux_get() and
-msm_gpiomux_put() from their request and free hooks, like this fictional
-example:
-
-static int request(struct gpio_chip *chip, unsigned offset)
-{
-        return msm_gpiomux_get(chip->base + offset);
-}
-
-static void free(struct gpio_chip *chip, unsigned offset)
-{
-        msm_gpiomux_put(chip->base + offset);
-}
-
-       ...somewhere in a gpio_chip declaration...
-       .request = request,
-       .free    = free,
-
-This provides important functionality:
-- It guarantees that a gpio line will have its 'active' config applied
-  when the line is requested, and will not be suspended while the line
-  remains requested; and
-- It guarantees that gpio-direction settings from gpiolib behave sensibly.
-  See "About Output-Enable Settings."
-
-This mechanism allows for "auto-request" of gpiomux lines via gpiolib
-when it is suitable.  Drivers wishing more exact control are, of course,
-free to also use msm_gpiomux_set and msm_gpiomux_get.
-
-About Output-Enable Settings
-============================
-
-Some msm targets do not have the ability to query the current gpio
-configuration setting.  This means that changes made to the output-enable
-(OE) bit by gpiolib cannot be consistently detected and preserved by gpiomux.
-Therefore, when gpiomux applies a configuration setting, any direction
-settings which may have been applied by gpiolib are lost and the default
-input settings are re-applied.
-
-For this reason, drivers should not assume that gpio direction settings
-continue to hold if they free and then re-request a gpio.  This seems like
-common sense - after all, anybody could have obtained the line in the
-meantime - but it needs saying.
-
-This also means that calls to msm_gpiomux_write will reset the OE bit,
-which means that if the gpio line is held by a client of gpiolib and
-msm_gpiomux_write is called, the direction setting has been lost and
-gpiolib's internal state has been broken.
-Release gpio lines before reconfiguring them.
diff --git a/Documentation/arm64/acpi_object_usage.txt b/Documentation/arm64/acpi_object_usage.txt
new file mode 100644 (file)
index 0000000..a6e1a18
--- /dev/null
@@ -0,0 +1,593 @@
+ACPI Tables
+-----------
+The expectations of individual ACPI tables are discussed in the list that
+follows.
+
+If a section number is used, it refers to a section number in the ACPI
+specification where the object is defined.  If "Signature Reserved" is used,
+the table signature (the first four bytes of the table) is the only portion
+of the table recognized by the specification, and the actual table is defined
+outside of the UEFI Forum (see Section 5.2.6 of the specification).
+
+For ACPI on arm64, tables also fall into the following categories:
+
+       -- Required: DSDT, FADT, GTDT, MADT, MCFG, RSDP, SPCR, XSDT
+
+       -- Recommended: BERT, EINJ, ERST, HEST, SSDT
+
+       -- Optional: BGRT, CPEP, CSRT, DRTM, ECDT, FACS, FPDT, MCHI, MPST,
+          MSCT, RASF, SBST, SLIT, SPMI, SRAT, TCPA, TPM2, UEFI
+
+       -- Not supported: BOOT, DBG2, DBGP, DMAR, ETDT, HPET, IBFT, IVRS,
+          LPIT, MSDM, RSDT, SLIC, WAET, WDAT, WDRT, WPBT
+
+
+Table  Usage for ARMv8 Linux
+-----  ----------------------------------------------------------------
+BERT   Section 18.3 (signature == "BERT")
+       == Boot Error Record Table ==
+       Must be supplied if RAS support is provided by the platform.  It
+       is recommended this table be supplied.
+
+BOOT   Signature Reserved (signature == "BOOT")
+       == simple BOOT flag table ==
+       Microsoft only table, will not be supported.
+
+BGRT   Section 5.2.22 (signature == "BGRT")
+       == Boot Graphics Resource Table ==
+       Optional, not currently supported, with no real use-case for an
+       ARM server.
+
+CPEP   Section 5.2.18 (signature == "CPEP")
+       == Corrected Platform Error Polling table ==
+       Optional, not currently supported, and not recommended until such
+       time as ARM-compatible hardware is available, and the specification
+       suitably modified.
+
+CSRT   Signature Reserved (signature == "CSRT")
+       == Core System Resources Table ==
+       Optional, not currently supported.
+
+DBG2   Signature Reserved (signature == "DBG2")
+       == DeBuG port table 2 ==
+       Microsoft only table, will not be supported.
+
+DBGP   Signature Reserved (signature == "DBGP")
+       == DeBuG Port table ==
+       Microsoft only table, will not be supported.
+
+DSDT   Section 5.2.11.1 (signature == "DSDT")
+       == Differentiated System Description Table ==
+       A DSDT is required; see also SSDT.
+
+       ACPI tables contain only one DSDT but can contain one or more SSDTs,
+       which are optional.  Each SSDT can only add to the ACPI namespace,
+       but cannot modify or replace anything in the DSDT.
+
+DMAR   Signature Reserved (signature == "DMAR")
+       == DMA Remapping table ==
+       x86 only table, will not be supported.
+
+DRTM   Signature Reserved (signature == "DRTM")
+       == Dynamic Root of Trust for Measurement table ==
+       Optional, not currently supported.
+
+ECDT   Section 5.2.16 (signature == "ECDT")
+       == Embedded Controller Description Table ==
+       Optional, not currently supported, but could be used on ARM if and
+       only if one uses the GPE_BIT field to represent an IRQ number, since
+       there are no GPE blocks defined in hardware reduced mode.  This would
+       need to be modified in the ACPI specification.
+
+EINJ   Section 18.6 (signature == "EINJ")
+       == Error Injection table ==
+       This table is very useful for testing platform response to error
+       conditions; it allows one to inject an error into the system as
+       if it had actually occurred.  However, this table should not be
+       shipped with a production system; it should be dynamically loaded
+       and executed with the ACPICA tools only during testing.
+
+ERST   Section 18.5 (signature == "ERST")
+       == Error Record Serialization Table ==
+       On a platform supports RAS, this table must be supplied if it is not
+       UEFI-based; if it is UEFI-based, this table may be supplied. When this
+       table is not present, UEFI run time service will be utilized to save
+       and retrieve hardware error information to and from a persistent store.
+
+ETDT   Signature Reserved (signature == "ETDT")
+       == Event Timer Description Table ==
+       Obsolete table, will not be supported.
+
+FACS   Section 5.2.10 (signature == "FACS")
+       == Firmware ACPI Control Structure ==
+       It is unlikely that this table will be terribly useful.  If it is
+       provided, the Global Lock will NOT be used since it is not part of
+       the hardware reduced profile, and only 64-bit address fields will
+       be considered valid.
+
+FADT   Section 5.2.9 (signature == "FACP")
+       == Fixed ACPI Description Table ==
+       Required for arm64.
+
+       The HW_REDUCED_ACPI flag must be set.  All of the fields that are
+       to be ignored when HW_REDUCED_ACPI is set are expected to be set to
+       zero.
+
+       If an FACS table is provided, the X_FIRMWARE_CTRL field is to be
+       used, not FIRMWARE_CTRL.
+
+       If PSCI is used (as is recommended), make sure that ARM_BOOT_ARCH is
+       filled in properly -- that the PSCI_COMPLIANT flag is set and that
+       PSCI_USE_HVC is set or unset as needed (see table 5-37).
+
+       For the DSDT that is also required, the X_DSDT field is to be used,
+       not the DSDT field.
+
+FPDT   Section 5.2.23 (signature == "FPDT")
+       == Firmware Performance Data Table ==
+       Optional, not currently supported.
+
+GTDT   Section 5.2.24 (signature == "GTDT")
+       == Generic Timer Description Table ==
+       Required for arm64.
+
+HEST   Section 18.3.2 (signature == "HEST")
+       == Hardware Error Source Table ==
+       Until further error source types are defined, use only types 6 (AER
+       Root Port), 7 (AER Endpoint), 8 (AER Bridge), or 9 (Generic Hardware
+       Error Source).  Firmware first error handling is possible if and only
+       if Trusted Firmware is being used on arm64.
+
+       Must be supplied if RAS support is provided by the platform.  It
+       is recommended this table be supplied.
+
+HPET   Signature Reserved (signature == "HPET")
+       == High Precision Event timer Table ==
+       x86 only table, will not be supported.
+
+IBFT   Signature Reserved (signature == "IBFT")
+       == iSCSI Boot Firmware Table ==
+       Microsoft defined table, support TBD.
+
+IVRS   Signature Reserved (signature == "IVRS")
+       == I/O Virtualization Reporting Structure ==
+       x86_64 (AMD) only table, will not be supported.
+
+LPIT   Signature Reserved (signature == "LPIT")
+       == Low Power Idle Table ==
+       x86 only table as of ACPI 5.1; future versions have been adapted for
+       use with ARM and will be recommended in order to support ACPI power
+       management.
+
+MADT   Section 5.2.12 (signature == "APIC")
+       == Multiple APIC Description Table ==
+       Required for arm64.  Only the GIC interrupt controller structures
+       should be used (types 0xA - 0xE).
+
+MCFG   Signature Reserved (signature == "MCFG")
+       == Memory-mapped ConFiGuration space ==
+       If the platform supports PCI/PCIe, an MCFG table is required.
+
+MCHI   Signature Reserved (signature == "MCHI")
+       == Management Controller Host Interface table ==
+       Optional, not currently supported.
+
+MPST   Section 5.2.21 (signature == "MPST")
+       == Memory Power State Table ==
+       Optional, not currently supported.
+
+MSDM   Signature Reserved (signature == "MSDM")
+       == Microsoft Data Management table ==
+       Microsoft only table, will not be supported.
+
+MSCT   Section 5.2.19 (signature == "MSCT")
+       == Maximum System Characteristic Table ==
+       Optional, not currently supported.
+
+RASF   Section 5.2.20 (signature == "RASF")
+       == RAS Feature table ==
+       Optional, not currently supported.
+
+RSDP   Section 5.2.5 (signature == "RSD PTR")
+       == Root System Description PoinTeR ==
+       Required for arm64.
+
+RSDT   Section 5.2.7 (signature == "RSDT")
+       == Root System Description Table ==
+       Since this table can only provide 32-bit addresses, it is deprecated
+       on arm64, and will not be used.
+
+SBST   Section 5.2.14 (signature == "SBST")
+       == Smart Battery Subsystem Table ==
+       Optional, not currently supported.
+
+SLIC   Signature Reserved (signature == "SLIC")
+       == Software LIcensing table ==
+       Microsoft only table, will not be supported.
+
+SLIT   Section 5.2.17 (signature == "SLIT")
+       == System Locality distance Information Table ==
+       Optional in general, but required for NUMA systems.
+
+SPCR   Signature Reserved (signature == "SPCR")
+       == Serial Port Console Redirection table ==
+       Required for arm64.
+
+SPMI   Signature Reserved (signature == "SPMI")
+       == Server Platform Management Interface table ==
+       Optional, not currently supported.
+
+SRAT   Section 5.2.16 (signature == "SRAT")
+       == System Resource Affinity Table ==
+       Optional, but if used, only the GICC Affinity structures are read.
+       To support NUMA, this table is required.
+
+SSDT   Section 5.2.11.2 (signature == "SSDT")
+       == Secondary System Description Table ==
+       These tables are a continuation of the DSDT; these are recommended
+       for use with devices that can be added to a running system, but can
+       also serve the purpose of dividing up device descriptions into more
+       manageable pieces.
+
+       An SSDT can only ADD to the ACPI namespace.  It cannot modify or
+       replace existing device descriptions already in the namespace.
+
+       These tables are optional, however.  ACPI tables should contain only
+       one DSDT but can contain many SSDTs.
+
+TCPA   Signature Reserved (signature == "TCPA")
+       == Trusted Computing Platform Alliance table ==
+       Optional, not currently supported, and may need changes to fully
+       interoperate with arm64.
+
+TPM2   Signature Reserved (signature == "TPM2")
+       == Trusted Platform Module 2 table ==
+       Optional, not currently supported, and may need changes to fully
+       interoperate with arm64.
+
+UEFI   Signature Reserved (signature == "UEFI")
+       == UEFI ACPI data table ==
+       Optional, not currently supported.  No known use case for arm64,
+       at present.
+
+WAET   Signature Reserved (signature == "WAET")
+       == Windows ACPI Emulated devices Table ==
+       Microsoft only table, will not be supported.
+
+WDAT   Signature Reserved (signature == "WDAT")
+       == Watch Dog Action Table ==
+       Microsoft only table, will not be supported.
+
+WDRT   Signature Reserved (signature == "WDRT")
+       == Watch Dog Resource Table ==
+       Microsoft only table, will not be supported.
+
+WPBT   Signature Reserved (signature == "WPBT")
+       == Windows Platform Binary Table ==
+       Microsoft only table, will not be supported.
+
+XSDT   Section 5.2.8 (signature == "XSDT")
+       == eXtended System Description Table ==
+       Required for arm64.
+
+
+ACPI Objects
+------------
+The expectations on individual ACPI objects are discussed in the list that
+follows:
+
+Name   Section         Usage for ARMv8 Linux
+----   ------------    -------------------------------------------------
+_ADR   6.1.1           Use as needed.
+
+_BBN   6.5.5           Use as needed; PCI-specific.
+
+_BDN   6.5.3           Optional; not likely to be used on arm64.
+
+_CCA   6.2.17          This method should be defined for all bus masters
+                       on arm64.  While cache coherency is assumed, making
+                       it explicit ensures the kernel will set up DMA as
+                       it should.
+
+_CDM   6.2.1           Optional, to be used only for processor devices.
+
+_CID   6.1.2           Use as needed.
+
+_CLS   6.1.3           Use as needed.
+
+_CRS   6.2.2           Required on arm64.
+
+_DCK   6.5.2           Optional; not likely to be used on arm64.
+
+_DDN   6.1.4           This field can be used for a device name.  However,
+                       it is meant for DOS device names (e.g., COM1), so be
+                       careful of its use across OSes.
+
+_DEP   6.5.8           Use as needed.
+
+_DIS   6.2.3           Optional, for power management use.
+
+_DLM   5.7.5           Optional.
+
+_DMA   6.2.4           Optional.
+
+_DSD   6.2.5           To be used with caution.  If this object is used, try
+                       to use it within the constraints already defined by the
+                       Device Properties UUID.  Only in rare circumstances
+                       should it be necessary to create a new _DSD UUID.
+
+                       In either case, submit the _DSD definition along with
+                       any driver patches for discussion, especially when
+                       device properties are used.  A driver will not be
+                       considered complete without a corresponding _DSD
+                       description.  Once approved by kernel maintainers,
+                       the UUID or device properties must then be registered
+                       with the UEFI Forum; this may cause some iteration as
+                       more than one OS will be registering entries.
+
+_DSM                   Do not use this method.  It is not standardized, the
+                       return values are not well documented, and it is
+                       currently a frequent source of error.
+
+_DSW   7.2.1           Use as needed; power management specific.
+
+_EDL   6.3.1           Optional.
+
+_EJD   6.3.2           Optional.
+
+_EJx   6.3.3           Optional.
+
+_FIX   6.2.7           x86 specific, not used on arm64.
+
+\_GL   5.7.1           This object is not to be used in hardware reduced
+                       mode, and therefore should not be used on arm64.
+
+_GLK   6.5.7           This object requires a global lock be defined; there
+                       is no global lock on arm64 since it runs in hardware
+                       reduced mode.  Hence, do not use this object on arm64.
+
+\_GPE  5.3.1           This namespace is for x86 use only.  Do not use it
+                       on arm64.
+
+_GSB   6.2.7           Optional.
+
+_HID   6.1.5           Use as needed.  This is the primary object to use in
+                       device probing, though _CID and _CLS may also be used.
+
+_HPP   6.2.8           Optional, PCI specific.
+
+_HPX   6.2.9           Optional, PCI specific.
+
+_HRV   6.1.6           Optional, use as needed to clarify device behavior; in
+                       some cases, this may be easier to use than _DSD.
+
+_INI   6.5.1           Not required, but can be useful in setting up devices
+                       when UEFI leaves them in a state that may not be what
+                       the driver expects before it starts probing.
+
+_IRC   7.2.15          Use as needed; power management specific.
+
+_LCK   6.3.4           Optional.
+
+_MAT   6.2.10          Optional; see also the MADT.
+
+_MLS   6.1.7           Optional, but highly recommended for use in
+                       internationalization.
+
+_OFF   7.1.2           It is recommended to define this method for any device
+                       that can be turned on or off.
+
+_ON    7.1.3           It is recommended to define this method for any device
+                       that can be turned on or off.
+
+\_OS   5.7.3           This method will return "Linux" by default (this is
+                       the value of the macro ACPI_OS_NAME on Linux).  The
+                       command line parameter acpi_os=<string> can be used
+                       to set it to some other value.
+
+_OSC   6.2.11          This method can be a global method in ACPI (i.e.,
+                       \_SB._OSC), or it may be associated with a specific
+                       device (e.g., \_SB.DEV0._OSC), or both.  When used
+                       as a global method, only capabilities published in
+                       the ACPI specification are allowed.  When used as
+                       a device-specific method, the process described for
+                       using _DSD MUST be used to create an _OSC definition;
+                       out-of-process use of _OSC is not allowed.  That is,
+                       submit the device-specific _OSC usage description as
+                       part of the kernel driver submission, get it approved
+                       by the kernel community, then register it with the
+                       UEFI Forum.
+
+\_OSI  5.7.2           Deprecated on ARM64.  Any invocation of this method
+                       will print a warning on the console and return false.
+                       That is, as far as ACPI firmware is concerned, _OSI
+                       cannot be used to determine what sort of system is
+                       being used or what functionality is provided.  The
+                       _OSC method is to be used instead.
+
+_OST   6.3.5           Optional.
+
+_PDC   8.4.1           Deprecated, do not use on arm64.
+
+\_PIC  5.8.1           The method should not be used.  On arm64, the only
+                       interrupt model available is GIC.
+
+_PLD   6.1.8           Optional.
+
+\_PR   5.3.1           This namespace is for x86 use only on legacy systems.
+                       Do not use it on arm64.
+
+_PRS   6.2.12          Optional.
+
+_PRT   6.2.13          Required as part of the definition of all PCI root
+                       devices.
+
+_PRW   7.2.13          Use as needed; power management specific.
+
+_PRx   7.2.8-11        Use as needed; power management specific.  If _PR0 is
+                       defined, _PR3 must also be defined.
+
+_PSC   7.2.6           Use as needed; power management specific.
+
+_PSE   7.2.7           Use as needed; power management specific.
+
+_PSW   7.2.14          Use as needed; power management specific.
+
+_PSx   7.2.2-5         Use as needed; power management specific.  If _PS0 is
+                       defined, _PS3 must also be defined.  If clocks or
+                       regulators need adjusting to be consistent with power
+                       usage, change them in these methods.
+
+\_PTS  7.3.1           Use as needed; power management specific.
+
+_PXM   6.2.14          Optional.
+
+_REG   6.5.4           Use as needed.
+
+\_REV  5.7.4           Always returns the latest version of ACPI supported.
+
+_RMV   6.3.6           Optional.
+
+\_SB   5.3.1           Required on arm64; all devices must be defined in this
+                       namespace.
+
+_SEG   6.5.6           Use as needed; PCI-specific.
+
+\_SI   5.3.1,          Optional.
+       9.1
+
+_SLI   6.2.15          Optional; recommended when SLIT table is in use.
+
+_STA   6.3.7,          It is recommended to define this method for any device
+       7.1.4           that can be turned on or off.
+
+_SRS   6.2.16          Optional; see also _PRS.
+
+_STR   6.1.10          Recommended for conveying device names to end users;
+                       this is preferred over using _DDN.
+
+_SUB   6.1.9           Use as needed; _HID or _CID are preferred.
+
+_SUN   6.1.11          Optional.
+
+\_Sx   7.3.2           Use as needed; power management specific.
+
+_SxD   7.2.16-19       Use as needed; power management specific.
+
+_SxW   7.2.20-24       Use as needed; power management specific.
+
+_SWS   7.3.3           Use as needed; power management specific; this may
+                       require specification changes for use on arm64.
+
+\_TTS  7.3.4           Use as needed; power management specific.
+
+\_TZ   5.3.1           Optional.
+
+_UID   6.1.12          Recommended for distinguishing devices of the same
+                       class; define it if at all possible.
+
+\_WAK  7.3.5           Use as needed; power management specific.
+
+
+ACPI Event Model
+----------------
+Do not use GPE block devices; these are not supported in the hardware reduced
+profile used by arm64.  Since there are no GPE blocks defined for use on ARM
+platforms, GPIO-signaled interrupts should be used for creating system events.
+
+
+ACPI Processor Control
+----------------------
+Section 8 of the ACPI specification is currently undergoing change that
+should be completed in the 6.0 version of the specification.  Processor
+performance control will be handled differently for arm64 at that point
+in time.  Processor aggregator devices (section 8.5) will not be used,
+for example, but another similar mechanism instead.
+
+While UEFI constrains what we can say until the release of 6.0, it is
+recommended that CPPC (8.4.5) be used as the primary model.  This will
+still be useful into the future.  C-states and P-states will still be
+provided, but most of the current design work appears to favor CPPC.
+
+Further, it is essential that the ARMv8 SoC provide a fully functional
+implementation of PSCI; this will be the only mechanism supported by ACPI
+to control CPU power state (including secondary CPU booting).
+
+More details will be provided on the release of the ACPI 6.0 specification.
+
+
+ACPI System Address Map Interfaces
+----------------------------------
+In Section 15 of the ACPI specification, several methods are mentioned as
+possible mechanisms for conveying memory resource information to the kernel.
+For arm64, we will only support UEFI for booting with ACPI, hence the UEFI
+GetMemoryMap() boot service is the only mechanism that will be used.
+
+
+ACPI Platform Error Interfaces (APEI)
+-------------------------------------
+The APEI tables supported are described above.
+
+APEI requires the equivalent of an SCI and an NMI on ARMv8.  The SCI is used
+to notify the OSPM of errors that have occurred but can be corrected and the
+system can continue correct operation, even if possibly degraded.  The NMI is
+used to indicate fatal errors that cannot be corrected, and require immediate
+attention.
+
+Since there is no direct equivalent of the x86 SCI or NMI, arm64 handles
+these slightly differently.  The SCI is handled as a normal GPIO-signaled
+interrupt; given that these are corrected (or correctable) errors being
+reported, this is sufficient.  The NMI is emulated as the highest priority
+GPIO-signaled interrupt possible.  This implies some caution must be used
+since there could be interrupts at higher privilege levels or even interrupts
+at the same priority as the emulated NMI.  In Linux, this should not be the
+case but one should be aware it could happen.
+
+
+ACPI Objects Not Supported on ARM64
+-----------------------------------
+While this may change in the future, there are several classes of objects
+that can be defined, but are not currently of general interest to ARM servers.
+
+These are not supported:
+
+       -- Section 9.2: ambient light sensor devices
+
+       -- Section 9.3: battery devices
+
+       -- Section 9.4: lids (e.g., laptop lids)
+
+       -- Section 9.8.2: IDE controllers
+
+       -- Section 9.9: floppy controllers
+
+       -- Section 9.10: GPE block devices
+
+       -- Section 9.15: PC/AT RTC/CMOS devices
+
+       -- Section 9.16: user presence detection devices
+
+       -- Section 9.17: I/O APIC devices; all GICs must be enumerable via MADT
+
+       -- Section 9.18: time and alarm devices (see 9.15)
+
+
+ACPI Objects Not Yet Implemented
+--------------------------------
+While these objects have x86 equivalents, and they do make some sense in ARM
+servers, there is either no hardware available at present, or in some cases
+there may not yet be a non-ARM implementation.  Hence, they are currently not
+implemented though that may change in the future.
+
+Not yet implemented are:
+
+       -- Section 10: power source and power meter devices
+
+       -- Section 11: thermal management
+
+       -- Section 12: embedded controllers interface
+
+       -- Section 13: SMBus interfaces
+
+       -- Section 17: NUMA support (prototypes have been submitted for
+          review)
diff --git a/Documentation/arm64/arm-acpi.txt b/Documentation/arm64/arm-acpi.txt
new file mode 100644 (file)
index 0000000..570a4f8
--- /dev/null
@@ -0,0 +1,505 @@
+ACPI on ARMv8 Servers
+---------------------
+ACPI can be used for ARMv8 general purpose servers designed to follow
+the ARM SBSA (Server Base System Architecture) [0] and SBBR (Server
+Base Boot Requirements) [1] specifications.  Please note that the SBBR
+can be retrieved simply by visiting [1], but the SBSA is currently only
+available to those with an ARM login due to ARM IP licensing concerns.
+
+The ARMv8 kernel implements the reduced hardware model of ACPI version
+5.1 or later.  Links to the specification and all external documents
+it refers to are managed by the UEFI Forum.  The specification is
+available at http://www.uefi.org/specifications and documents referenced
+by the specification can be found via http://www.uefi.org/acpi.
+
+If an ARMv8 system does not meet the requirements of the SBSA and SBBR,
+or cannot be described using the mechanisms defined in the required ACPI
+specifications, then ACPI may not be a good fit for the hardware.
+
+While the documents mentioned above set out the requirements for building
+industry-standard ARMv8 servers, they also apply to more than one operating
+system.  The purpose of this document is to describe the interaction between
+ACPI and Linux only, on an ARMv8 system -- that is, what Linux expects of
+ACPI and what ACPI can expect of Linux.
+
+
+Why ACPI on ARM?
+----------------
+Before examining the details of the interface between ACPI and Linux, it is
+useful to understand why ACPI is being used.  Several technologies already
+exist in Linux for describing non-enumerable hardware, after all.  In this
+section we summarize a blog post [2] from Grant Likely that outlines the
+reasoning behind ACPI on ARMv8 servers.  Actually, we snitch a good portion
+of the summary text almost directly, to be honest.
+
+The short form of the rationale for ACPI on ARM is:
+
+-- ACPI’s bytecode (AML) allows the platform to encode hardware behavior,
+   while DT explicitly does not support this.  For hardware vendors, being
+   able to encode behavior is a key tool used in supporting operating
+   system releases on new hardware.
+
+-- ACPI’s OSPM defines a power management model that constrains what the
+   platform is allowed to do into a specific model, while still providing
+   flexibility in hardware design.
+
+-- In the enterprise server environment, ACPI has established bindings (such
+   as for RAS) which are currently used in production systems.  DT does not.
+   Such bindings could be defined in DT at some point, but doing so means ARM
+   and x86 would end up using completely different code paths in both firmware
+   and the kernel.
+
+-- Choosing a single interface to describe the abstraction between a platform
+   and an OS is important.  Hardware vendors would not be required to implement
+   both DT and ACPI if they want to support multiple operating systems.  And,
+   agreeing on a single interface instead of being fragmented into per OS
+   interfaces makes for better interoperability overall.
+
+-- The new ACPI governance process works well and Linux is now at the same
+   table as hardware vendors and other OS vendors.  In fact, there is no
+   longer any reason to feel that ACPI is only belongs to Windows or that
+   Linux is in any way secondary to Microsoft in this arena.  The move of
+   ACPI governance into the UEFI forum has significantly opened up the
+   specification development process, and currently, a large portion of the
+   changes being made to ACPI is being driven by Linux.
+
+Key to the use of ACPI is the support model.  For servers in general, the
+responsibility for hardware behaviour cannot solely be the domain of the
+kernel, but rather must be split between the platform and the kernel, in
+order to allow for orderly change over time.  ACPI frees the OS from needing
+to understand all the minute details of the hardware so that the OS doesn’t
+need to be ported to each and every device individually.  It allows the
+hardware vendors to take responsibility for power management behaviour without
+depending on an OS release cycle which is not under their control.
+
+ACPI is also important because hardware and OS vendors have already worked
+out the mechanisms for supporting a general purpose computing ecosystem.  The
+infrastructure is in place, the bindings are in place, and the processes are
+in place.  DT does exactly what Linux needs it to when working with vertically
+integrated devices, but there are no good processes for supporting what the
+server vendors need.  Linux could potentially get there with DT, but doing so
+really just duplicates something that already works.  ACPI already does what
+the hardware vendors need, Microsoft won’t collaborate on DT, and hardware
+vendors would still end up providing two completely separate firmware
+interfaces -- one for Linux and one for Windows.
+
+
+Kernel Compatibility
+--------------------
+One of the primary motivations for ACPI is standardization, and using that
+to provide backward compatibility for Linux kernels.  In the server market,
+software and hardware are often used for long periods.  ACPI allows the
+kernel and firmware to agree on a consistent abstraction that can be
+maintained over time, even as hardware or software change.  As long as the
+abstraction is supported, systems can be updated without necessarily having
+to replace the kernel.
+
+When a Linux driver or subsystem is first implemented using ACPI, it by
+definition ends up requiring a specific version of the ACPI specification
+-- it's baseline.  ACPI firmware must continue to work, even though it may
+not be optimal, with the earliest kernel version that first provides support
+for that baseline version of ACPI.  There may be a need for additional drivers,
+but adding new functionality (e.g., CPU power management) should not break
+older kernel versions.  Further, ACPI firmware must also work with the most
+recent version of the kernel.
+
+
+Relationship with Device Tree
+-----------------------------
+ACPI support in drivers and subsystems for ARMv8 should never be mutually
+exclusive with DT support at compile time.
+
+At boot time the kernel will only use one description method depending on
+parameters passed from the bootloader (including kernel bootargs).
+
+Regardless of whether DT or ACPI is used, the kernel must always be capable
+of booting with either scheme (in kernels with both schemes enabled at compile
+time).
+
+
+Booting using ACPI tables
+-------------------------
+The only defined method for passing ACPI tables to the kernel on ARMv8
+is via the UEFI system configuration table.  Just so it is explicit, this
+means that ACPI is only supported on platforms that boot via UEFI.
+
+When an ARMv8 system boots, it can either have DT information, ACPI tables,
+or in some very unusual cases, both.  If no command line parameters are used,
+the kernel will try to use DT for device enumeration; if there is no DT
+present, the kernel will try to use ACPI tables, but only if they are present.
+In neither is available, the kernel will not boot.  If acpi=force is used
+on the command line, the kernel will attempt to use ACPI tables first, but
+fall back to DT if there are no ACPI tables present.  The basic idea is that
+the kernel will not fail to boot unless it absolutely has no other choice.
+
+Processing of ACPI tables may be disabled by passing acpi=off on the kernel
+command line; this is the default behavior.
+
+In order for the kernel to load and use ACPI tables, the UEFI implementation
+MUST set the ACPI_20_TABLE_GUID to point to the RSDP table (the table with
+the ACPI signature "RSD PTR ").  If this pointer is incorrect and acpi=force
+is used, the kernel will disable ACPI and try to use DT to boot instead; the
+kernel has, in effect, determined that ACPI tables are not present at that
+point.
+
+If the pointer to the RSDP table is correct, the table will be mapped into
+the kernel by the ACPI core, using the address provided by UEFI.
+
+The ACPI core will then locate and map in all other ACPI tables provided by
+using the addresses in the RSDP table to find the XSDT (eXtended System
+Description Table).  The XSDT in turn provides the addresses to all other
+ACPI tables provided by the system firmware; the ACPI core will then traverse
+this table and map in the tables listed.
+
+The ACPI core will ignore any provided RSDT (Root System Description Table).
+RSDTs have been deprecated and are ignored on arm64 since they only allow
+for 32-bit addresses.
+
+Further, the ACPI core will only use the 64-bit address fields in the FADT
+(Fixed ACPI Description Table).  Any 32-bit address fields in the FADT will
+be ignored on arm64.
+
+Hardware reduced mode (see Section 4.1 of the ACPI 5.1 specification) will
+be enforced by the ACPI core on arm64.  Doing so allows the ACPI core to
+run less complex code since it no longer has to provide support for legacy
+hardware from other architectures.  Any fields that are not to be used for
+hardware reduced mode must be set to zero.
+
+For the ACPI core to operate properly, and in turn provide the information
+the kernel needs to configure devices, it expects to find the following
+tables (all section numbers refer to the ACPI 5.1 specfication):
+
+    -- RSDP (Root System Description Pointer), section 5.2.5
+
+    -- XSDT (eXtended System Description Table), section 5.2.8
+
+    -- FADT (Fixed ACPI Description Table), section 5.2.9
+
+    -- DSDT (Differentiated System Description Table), section
+       5.2.11.1
+
+    -- MADT (Multiple APIC Description Table), section 5.2.12
+
+    -- GTDT (Generic Timer Description Table), section 5.2.24
+
+    -- If PCI is supported, the MCFG (Memory mapped ConFiGuration
+       Table), section 5.2.6, specifically Table 5-31.
+
+If the above tables are not all present, the kernel may or may not be
+able to boot properly since it may not be able to configure all of the
+devices available.
+
+
+ACPI Detection
+--------------
+Drivers should determine their probe() type by checking for a null
+value for ACPI_HANDLE, or checking .of_node, or other information in
+the device structure.  This is detailed further in the "Driver
+Recommendations" section.
+
+In non-driver code, if the presence of ACPI needs to be detected at
+runtime, then check the value of acpi_disabled. If CONFIG_ACPI is not
+set, acpi_disabled will always be 1.
+
+
+Device Enumeration
+------------------
+Device descriptions in ACPI should use standard recognized ACPI interfaces.
+These may contain less information than is typically provided via a Device
+Tree description for the same device.  This is also one of the reasons that
+ACPI can be useful -- the driver takes into account that it may have less
+detailed information about the device and uses sensible defaults instead.
+If done properly in the driver, the hardware can change and improve over
+time without the driver having to change at all.
+
+Clocks provide an excellent example.  In DT, clocks need to be specified
+and the drivers need to take them into account.  In ACPI, the assumption
+is that UEFI will leave the device in a reasonable default state, including
+any clock settings.  If for some reason the driver needs to change a clock
+value, this can be done in an ACPI method; all the driver needs to do is
+invoke the method and not concern itself with what the method needs to do
+to change the clock.  Changing the hardware can then take place over time
+by changing what the ACPI method does, and not the driver.
+
+In DT, the parameters needed by the driver to set up clocks as in the example
+above are known as "bindings"; in ACPI, these are known as "Device Properties"
+and provided to a driver via the _DSD object.
+
+ACPI tables are described with a formal language called ASL, the ACPI
+Source Language (section 19 of the specification).  This means that there
+are always multiple ways to describe the same thing -- including device
+properties.  For example, device properties could use an ASL construct
+that looks like this: Name(KEY0, "value0").  An ACPI device driver would
+then retrieve the value of the property by evaluating the KEY0 object.
+However, using Name() this way has multiple problems: (1) ACPI limits
+names ("KEY0") to four characters unlike DT; (2) there is no industry
+wide registry that maintains a list of names, minimzing re-use; (3)
+there is also no registry for the definition of property values ("value0"),
+again making re-use difficult; and (4) how does one maintain backward
+compatibility as new hardware comes out?  The _DSD method was created
+to solve precisely these sorts of problems; Linux drivers should ALWAYS
+use the _DSD method for device properties and nothing else.
+
+The _DSM object (ACPI Section 9.14.1) could also be used for conveying
+device properties to a driver.  Linux drivers should only expect it to
+be used if _DSD cannot represent the data required, and there is no way
+to create a new UUID for the _DSD object.  Note that there is even less
+regulation of the use of _DSM than there is of _DSD.  Drivers that depend
+on the contents of _DSM objects will be more difficult to maintain over
+time because of this; as of this writing, the use of _DSM is the cause
+of quite a few firmware problems and is not recommended.
+
+Drivers should look for device properties in the _DSD object ONLY; the _DSD
+object is described in the ACPI specification section 6.2.5, but this only
+describes how to define the structure of an object returned via _DSD, and
+how specific data structures are defined by specific UUIDs.  Linux should
+only use the _DSD Device Properties UUID [5]:
+
+   -- UUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301
+
+   -- http://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf
+
+The UEFI Forum provides a mechanism for registering device properties [4]
+so that they may be used across all operating systems supporting ACPI.
+Device properties that have not been registered with the UEFI Forum should
+not be used.
+
+Before creating new device properties, check to be sure that they have not
+been defined before and either registered in the Linux kernel documentation
+as DT bindings, or the UEFI Forum as device properties.  While we do not want
+to simply move all DT bindings into ACPI device properties, we can learn from
+what has been previously defined.
+
+If it is necessary to define a new device property, or if it makes sense to
+synthesize the definition of a binding so it can be used in any firmware,
+both DT bindings and ACPI device properties for device drivers have review
+processes.  Use them both.  When the driver itself is submitted for review
+to the Linux mailing lists, the device property definitions needed must be
+submitted at the same time.  A driver that supports ACPI and uses device
+properties will not be considered complete without their definitions.  Once
+the device property has been accepted by the Linux community, it must be
+registered with the UEFI Forum [4], which will review it again for consistency
+within the registry.  This may require iteration.  The UEFI Forum, though,
+will always be the canonical site for device property definitions.
+
+It may make sense to provide notice to the UEFI Forum that there is the
+intent to register a previously unused device property name as a means of
+reserving the name for later use.  Other operating system vendors will
+also be submitting registration requests and this may help smooth the
+process.
+
+Once registration and review have been completed, the kernel provides an
+interface for looking up device properties in a manner independent of
+whether DT or ACPI is being used.  This API should be used [6]; it can
+eliminate some duplication of code paths in driver probing functions and
+discourage divergence between DT bindings and ACPI device properties.
+
+
+Programmable Power Control Resources
+------------------------------------
+Programmable power control resources include such resources as voltage/current
+providers (regulators) and clock sources.
+
+With ACPI, the kernel clock and regulator framework is not expected to be used
+at all.
+
+The kernel assumes that power control of these resources is represented with
+Power Resource Objects (ACPI section 7.1).  The ACPI core will then handle
+correctly enabling and disabling resources as they are needed.  In order to
+get that to work, ACPI assumes each device has defined D-states and that these
+can be controlled through the optional ACPI methods _PS0, _PS1, _PS2, and _PS3;
+in ACPI, _PS0 is the method to invoke to turn a device full on, and _PS3 is for
+turning a device full off.
+
+There are two options for using those Power Resources.  They can:
+
+   -- be managed in a _PSx method which gets called on entry to power
+      state Dx.
+
+   -- be declared separately as power resources with their own _ON and _OFF
+      methods.  They are then tied back to D-states for a particular device
+      via _PRx which specifies which power resources a device needs to be on
+      while in Dx.  Kernel then tracks number of devices using a power resource
+      and calls _ON/_OFF as needed.
+
+The kernel ACPI code will also assume that the _PSx methods follow the normal
+ACPI rules for such methods:
+
+   -- If either _PS0 or _PS3 is implemented, then the other method must also
+      be implemented.
+
+   -- If a device requires usage or setup of a power resource when on, the ASL
+      should organize that it is allocated/enabled using the _PS0 method.
+
+   -- Resources allocated or enabled in the _PS0 method should be disabled
+      or de-allocated in the _PS3 method.
+
+   -- Firmware will leave the resources in a reasonable state before handing
+      over control to the kernel.
+
+Such code in _PSx methods will of course be very platform specific.  But,
+this allows the driver to abstract out the interface for operating the device
+and avoid having to read special non-standard values from ACPI tables. Further,
+abstracting the use of these resources allows the hardware to change over time
+without requiring updates to the driver.
+
+
+Clocks
+------
+ACPI makes the assumption that clocks are initialized by the firmware --
+UEFI, in this case -- to some working value before control is handed over
+to the kernel.  This has implications for devices such as UARTs, or SoC-driven
+LCD displays, for example.
+
+When the kernel boots, the clocks are assumed to be set to reasonable
+working values.  If for some reason the frequency needs to change -- e.g.,
+throttling for power management -- the device driver should expect that
+process to be abstracted out into some ACPI method that can be invoked
+(please see the ACPI specification for further recommendations on standard
+methods to be expected).  The only exceptions to this are CPU clocks where
+CPPC provides a much richer interface than ACPI methods.  If the clocks
+are not set, there is no direct way for Linux to control them.
+
+If an SoC vendor wants to provide fine-grained control of the system clocks,
+they could do so by providing ACPI methods that could be invoked by Linux
+drivers.  However, this is NOT recommended and Linux drivers should NOT use
+such methods, even if they are provided.  Such methods are not currently
+standardized in the ACPI specification, and using them could tie a kernel
+to a very specific SoC, or tie an SoC to a very specific version of the
+kernel, both of which we are trying to avoid.
+
+
+Driver Recommendations
+----------------------
+DO NOT remove any DT handling when adding ACPI support for a driver.  The
+same device may be used on many different systems.
+
+DO try to structure the driver so that it is data-driven.  That is, set up
+a struct containing internal per-device state based on defaults and whatever
+else must be discovered by the driver probe function.  Then, have the rest
+of the driver operate off of the contents of that struct.  Doing so should
+allow most divergence between ACPI and DT functionality to be kept local to
+the probe function instead of being scattered throughout the driver.  For
+example:
+
+static int device_probe_dt(struct platform_device *pdev)
+{
+       /* DT specific functionality */
+       ...
+}
+
+static int device_probe_acpi(struct platform_device *pdev)
+{
+       /* ACPI specific functionality */
+       ...
+}
+
+static int device_probe(struct platform_device *pdev)
+{
+       ...
+       struct device_node node = pdev->dev.of_node;
+       ...
+
+       if (node)
+               ret = device_probe_dt(pdev);
+       else if (ACPI_HANDLE(&pdev->dev))
+               ret = device_probe_acpi(pdev);
+       else
+               /* other initialization */
+               ...
+       /* Continue with any generic probe operations */
+       ...
+}
+
+DO keep the MODULE_DEVICE_TABLE entries together in the driver to make it
+clear the different names the driver is probed for, both from DT and from
+ACPI:
+
+static struct of_device_id virtio_mmio_match[] = {
+        { .compatible = "virtio,mmio", },
+        { }
+};
+MODULE_DEVICE_TABLE(of, virtio_mmio_match);
+
+static const struct acpi_device_id virtio_mmio_acpi_match[] = {
+        { "LNRO0005", },
+        { }
+};
+MODULE_DEVICE_TABLE(acpi, virtio_mmio_acpi_match);
+
+
+ASWG
+----
+The ACPI specification changes regularly.  During the year 2014, for instance,
+version 5.1 was released and version 6.0 substantially completed, with most of
+the changes being driven by ARM-specific requirements.  Proposed changes are
+presented and discussed in the ASWG (ACPI Specification Working Group) which
+is a part of the UEFI Forum.
+
+Participation in this group is open to all UEFI members.  Please see
+http://www.uefi.org/workinggroup for details on group membership.
+
+It is the intent of the ARMv8 ACPI kernel code to follow the ACPI specification
+as closely as possible, and to only implement functionality that complies with
+the released standards from UEFI ASWG.  As a practical matter, there will be
+vendors that provide bad ACPI tables or violate the standards in some way.
+If this is because of errors, quirks and fixups may be necessary, but will
+be avoided if possible.  If there are features missing from ACPI that preclude
+it from being used on a platform, ECRs (Engineering Change Requests) should be
+submitted to ASWG and go through the normal approval process; for those that
+are not UEFI members, many other members of the Linux community are and would
+likely be willing to assist in submitting ECRs.
+
+
+Linux Code
+----------
+Individual items specific to Linux on ARM, contained in the the Linux
+source code, are in the list that follows:
+
+ACPI_OS_NAME           This macro defines the string to be returned when
+                       an ACPI method invokes the _OS method.  On ARM64
+                       systems, this macro will be "Linux" by default.
+                       The command line parameter acpi_os=<string>
+                       can be used to set it to some other value.  The
+                       default value for other architectures is "Microsoft
+                       Windows NT", for example.
+
+ACPI Objects
+------------
+Detailed expectations for ACPI tables and object are listed in the file
+Documentation/arm64/acpi_object_usage.txt.
+
+
+References
+----------
+[0] http://silver.arm.com -- document ARM-DEN-0029, or newer
+    "Server Base System Architecture", version 2.3, dated 27 Mar 2014
+
+[1] http://infocenter.arm.com/help/topic/com.arm.doc.den0044a/Server_Base_Boot_Requirements.pdf
+    Document ARM-DEN-0044A, or newer: "Server Base Boot Requirements, System
+    Software on ARM Platforms", dated 16 Aug 2014
+
+[2] http://www.secretlab.ca/archives/151, 10 Jan 2015, Copyright (c) 2015,
+    Linaro Ltd., written by Grant Likely.  A copy of the verbatim text (apart
+    from formatting) is also in Documentation/arm64/why_use_acpi.txt.
+
+[3] AMD ACPI for Seattle platform documentation:
+    http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2012/10/Seattle_ACPI_Guide.pdf
+
+[4] http://www.uefi.org/acpi -- please see the link for the "ACPI _DSD Device
+    Property Registry Instructions"
+
+[5] http://www.uefi.org/acpi -- please see the link for the "_DSD (Device
+    Specific Data) Implementation Guide"
+
+[6] Kernel code for the unified device property interface can be found in
+    include/linux/property.h and drivers/base/property.c.
+
+
+Authors
+-------
+Al Stone <al.stone@linaro.org>
+Graeme Gregory <graeme.gregory@linaro.org>
+Hanjun Guo <hanjun.guo@linaro.org>
+
+Grant Likely <grant.likely@linaro.org>, for the "Why ACPI on ARM?" section
diff --git a/Documentation/devicetree/bindings/arc/pct.txt b/Documentation/devicetree/bindings/arc/pct.txt
new file mode 100644 (file)
index 0000000..7b95884
--- /dev/null
@@ -0,0 +1,20 @@
+* ARC Performance Counters
+
+The ARC700 can be configured with a pipeline performance monitor for counting
+CPU and cache events like cache misses and hits. Like conventional PCT there
+are 100+ hardware conditions dynamically mapped to upto 32 counters
+
+Note that:
+ * The ARC 700 PCT does not support interrupts; although HW events may be
+   counted, the HW events themselves cannot serve as a trigger for a sample.
+
+Required properties:
+
+- compatible : should contain
+       "snps,arc700-pct"
+
+Example:
+
+pmu {
+        compatible = "snps,arc700-pct";
+};
diff --git a/Documentation/devicetree/bindings/arc/pmu.txt b/Documentation/devicetree/bindings/arc/pmu.txt
deleted file mode 100644 (file)
index 49d5173..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-* ARC Performance Monitor Unit
-
-The ARC 700 can be configured with a pipeline performance monitor for counting
-CPU and cache events like cache misses and hits.
-
-Note that:
- * ARC 700 refers to a family of ARC processor cores;
-   - There is only one type of PMU available for the whole family;
-   - The PMU may support different sets of events; supported events are probed
-     at boot time, as required by the reference manual.
-
- * The ARC 700 PMU does not support interrupts; although HW events may be
-   counted, the HW events themselves cannot serve as a trigger for a sample.
-
-Required properties:
-
-- compatible : should contain
-       "snps,arc700-pmu"
-
-Example:
-
-pmu {
-        compatible = "snps,arc700-pmu";
-};
diff --git a/Documentation/devicetree/bindings/arm/al,alpine.txt b/Documentation/devicetree/bindings/arm/al,alpine.txt
new file mode 100644 (file)
index 0000000..f404a4f
--- /dev/null
@@ -0,0 +1,88 @@
+Annapurna Labs Alpine Platform Device Tree Bindings
+---------------------------------------------------------------
+
+Boards in the Alpine family shall have the following properties:
+
+* Required root node properties:
+compatible: must contain "al,alpine"
+
+* Example:
+
+/ {
+       model = "Annapurna Labs Alpine Dev Board";
+       compatible = "al,alpine";
+
+       ...
+}
+
+* CPU node:
+
+The Alpine platform includes cortex-a15 cores.
+enable-method: must be "al,alpine-smp" to allow smp  [1]
+
+Example:
+
+cpus {
+       #address-cells = <1>;
+       #size-cells = <0>;
+       enable-method = "al,alpine-smp";
+
+       cpu@0 {
+               compatible = "arm,cortex-a15";
+               device_type = "cpu";
+               reg = <0>;
+       };
+
+       cpu@1 {
+               compatible = "arm,cortex-a15";
+               device_type = "cpu";
+               reg = <1>;
+       };
+
+       cpu@2 {
+               compatible = "arm,cortex-a15";
+               device_type = "cpu";
+               reg = <2>;
+       };
+
+       cpu@3 {
+               compatible = "arm,cortex-a15";
+               device_type = "cpu";
+               reg = <3>;
+       };
+};
+
+
+* Alpine CPU resume registers
+
+The CPU resume register are used to define required resume address after
+reset.
+
+Properties:
+- compatible : Should contain "al,alpine-cpu-resume".
+- reg : Offset and length of the register set for the device
+
+Example:
+
+cpu_resume {
+       compatible = "al,alpine-cpu-resume";
+       reg = <0xfbff5ed0 0x30>;
+};
+
+* Alpine System-Fabric Service Registers
+
+The System-Fabric Service Registers allow various operation on CPU and
+system fabric, like powering CPUs off.
+
+Properties:
+- compatible : Should contain "al,alpine-sysfabric-service" and "syscon".
+- reg : Offset and length of the register set for the device
+
+Example:
+
+nb_service {
+        compatible = "al,alpine-sysfabric-service", "syscon";
+        reg = <0xfb070000 0x10000>;
+};
+
+[1] arm/cpu-enable-method/al,alpine-smp
diff --git a/Documentation/devicetree/bindings/arm/altera.txt b/Documentation/devicetree/bindings/arm/altera.txt
new file mode 100644 (file)
index 0000000..558735a
--- /dev/null
@@ -0,0 +1,14 @@
+Altera's SoCFPGA platform device tree bindings
+---------------------------------------------
+
+Boards with Cyclone 5 SoC:
+Required root node properties:
+compatible = "altr,socfpga-cyclone5", "altr,socfpga";
+
+Boards with Arria 5 SoC:
+Required root node properties:
+compatible = "altr,socfpga-arria5", "altr,socfpga";
+
+Boards with Arria 10 SoC:
+Required root node properties:
+compatible = "altr,socfpga-arria10", "altr,socfpga";
index 8fe815046140becdbc594545d6677b8800b6a541..973884a1bacff8b9619b07f708367bf664fe7673 100644 (file)
@@ -8,3 +8,7 @@ Boards with the Amlogic Meson6 SoC shall have the following properties:
 Boards with the Amlogic Meson8 SoC shall have the following properties:
   Required root node property:
     compatible: "amlogic,meson8";
+
+Board compatible values:
+  - "geniatech,atv1200"
+  - "minix,neo-x8"
index 256b4d8bab7b93d49330c7db5334eb05e8979904..e774128935d5c37ec88b8130ed667c5b4ff133df 100644 (file)
@@ -17,7 +17,10 @@ to deliver its interrupts via SPIs.
 - interrupts : Interrupt list for secure, non-secure, virtual and
   hypervisor timers, in that order.
 
-- clock-frequency : The frequency of the main counter, in Hz. Optional.
+- clock-frequency : The frequency of the main counter, in Hz. Should be present
+  only where necessary to work around broken firmware which does not configure
+  CNTFRQ on all CPUs to a uniform correct value. Use of this property is
+  strongly discouraged; fix your firmware unless absolutely impossible.
 
 - always-on : a boolean property. If present, the timer is powered through an
   always-on power domain, therefore it never loses context.
@@ -46,7 +49,8 @@ Example:
 
 - compatible : Should at least contain "arm,armv7-timer-mem".
 
-- clock-frequency : The frequency of the main counter, in Hz. Optional.
+- clock-frequency : The frequency of the main counter, in Hz. Should be present
+  only when firmware has not configured the MMIO CNTFRQ registers.
 
 - reg : The control frame base address.
 
diff --git a/Documentation/devicetree/bindings/arm/armada-39x.txt b/Documentation/devicetree/bindings/arm/armada-39x.txt
new file mode 100644 (file)
index 0000000..53d4ff9
--- /dev/null
@@ -0,0 +1,20 @@
+Marvell Armada 39x Platforms Device Tree Bindings
+-------------------------------------------------
+
+Boards with a SoC of the Marvell Armada 39x family shall have the
+following property:
+
+Required root node property:
+
+ - compatible: must contain "marvell,armada390"
+
+In addition, boards using the Marvell Armada 398 SoC shall have the
+following property before the previous one:
+
+Required root node property:
+
+compatible: must contain "marvell,armada398"
+
+Example:
+
+compatible = "marvell,a398-db", "marvell,armada398", "marvell,armada390";
index ad319f84f56018ba1297676c2a69586864a6b4e0..2e99b5b57350d06a43f4fbed97cde970116b595f 100644 (file)
@@ -46,10 +46,12 @@ PIT Timer required properties:
   shared across all System Controller members.
 
 System Timer (ST) required properties:
-- compatible: Should be "atmel,at91rm9200-st"
+- compatible: Should be "atmel,at91rm9200-st", "syscon", "simple-mfd"
 - reg: Should contain registers location and length
 - interrupts: Should contain interrupt for the ST which is the IRQ line
   shared across all System Controller members.
+Its subnodes can be:
+- watchdog: compatible should be "atmel,at91rm9200-wdt"
 
 TC/TCLIB Timer required properties:
 - compatible: Should be "atmel,<chip>-tcb".
index f28d82bbbc56b3f3dff7716ede2f200f315d8e70..3c5c631328d3b6cbb4d7c9edefddf936347a545e 100644 (file)
@@ -94,8 +94,11 @@ specific to ARM.
                - compatible
                        Usage: required
                        Value type: <string>
-                       Definition: must be "arm,cci-400-pmu"
-
+                       Definition: Must contain one of:
+                                "arm,cci-400-pmu,r0"
+                                "arm,cci-400-pmu,r1"
+                                "arm,cci-400-pmu"  - DEPRECATED, permitted only where OS has
+                                                     secure acces to CCI registers
                - reg:
                        Usage: required
                        Value type: Integer cells. A register entry, expressed
index a3089359aaa6e58dfdf9588995d72b53ff2d1938..88602b75418e841a66d568d59652707eeb41bb4a 100644 (file)
@@ -61,7 +61,6 @@ Example:
                compatible = "arm,coresight-etb10", "arm,primecell";
                reg = <0 0x20010000 0 0x1000>;
 
-               coresight-default-sink;
                clocks = <&oscclk6a>;
                clock-names = "apb_pclk";
                port {
diff --git a/Documentation/devicetree/bindings/arm/cpu-enable-method/al,alpine-smp b/Documentation/devicetree/bindings/arm/cpu-enable-method/al,alpine-smp
new file mode 100644 (file)
index 0000000..c2e0cc5
--- /dev/null
@@ -0,0 +1,52 @@
+========================================================
+Secondary CPU enable-method "al,alpine-smp" binding
+========================================================
+
+This document describes the "al,alpine-smp" method for
+enabling secondary CPUs. To apply to all CPUs, a single
+"al,alpine-smp" enable method should be defined in the
+"cpus" node.
+
+Enable method name:    "al,alpine-smp"
+Compatible machines:   "al,alpine"
+Compatible CPUs:       "arm,cortex-a15"
+Related properties:    (none)
+
+Note:
+This enable method requires valid nodes compatible with
+"al,alpine-cpu-resume" and "al,alpine-nb-service"[1].
+
+Example:
+
+cpus {
+       #address-cells = <1>;
+       #size-cells = <0>;
+       enable-method = "al,alpine-smp";
+
+       cpu@0 {
+               compatible = "arm,cortex-a15";
+               device_type = "cpu";
+               reg = <0>;
+       };
+
+       cpu@1 {
+               compatible = "arm,cortex-a15";
+               device_type = "cpu";
+               reg = <1>;
+       };
+
+       cpu@2 {
+               compatible = "arm,cortex-a15";
+               device_type = "cpu";
+               reg = <2>;
+       };
+
+       cpu@3 {
+               compatible = "arm,cortex-a15";
+               device_type = "cpu";
+               reg = <3>;
+       };
+};
+
+--
+[1] arm/al,alpine.txt
index 8b9e0a95de317e5369932d612ac131be8ac0a641..6aa331d11c5e3e042ff2e0ec495d39e26fe0681c 100644 (file)
@@ -192,6 +192,7 @@ nodes to be present and contain the properties described below.
                            "brcm,brahma-b15"
                            "marvell,armada-375-smp"
                            "marvell,armada-380-smp"
+                           "marvell,armada-390-smp"
                            "marvell,armada-xp-smp"
                            "qcom,gcc-msm8660"
                            "qcom,kpss-acc-v1"
index 1e097037349c326a22e3f07abb3e3aca9d78d0ce..5da38c5ed476ee2248432314c0bf886305f6cc13 100644 (file)
@@ -22,6 +22,9 @@ Optional Properties:
        - pclkN, clkN: Pairs of parent of input clock and input clock to the
                devices in this power domain. Maximum of 4 pairs (N = 0 to 3)
                are supported currently.
+       - asbN: Clocks required by asynchronous bridges (ASB) present in
+               the power domain. These clock should be enabled during power
+               domain on/off operations.
 - power-domains: phandle pointing to the parent power domain, for more details
                 see Documentation/devicetree/bindings/power/power_domain.txt
 
diff --git a/Documentation/devicetree/bindings/arm/geniatech.txt b/Documentation/devicetree/bindings/arm/geniatech.txt
deleted file mode 100644 (file)
index 74ccba4..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-Geniatech platforms device tree bindings
--------------------------------------------
-
-Geniatech ATV1200
-    - compatible = "geniatech,atv1200"
index 1e0d21201d3aa7a02390fac92013bc3905d88b12..2da059a4790cb3c62365bedae458c5565589b225 100644 (file)
@@ -18,6 +18,8 @@ Main node required properties:
        "arm,arm11mp-gic"
        "brcm,brahma-b15-gic"
        "arm,arm1176jzf-devchip-gic"
+       "qcom,msm-8660-qgic"
+       "qcom,msm-qgic2"
 - interrupt-controller : Identifies the node as an interrupt controller
 - #interrupt-cells : Specifies the number of cells needed to encode an
   interrupt source.  The type shall be a <u32> and the value shall be 3.
index 925ecbf6e7b7af23681aca4a413553265b41fb0e..4f40ff3fee4b102aa6b4ec460a2b7e0e4bc1a09f 100644 (file)
@@ -42,6 +42,7 @@ board. Currently known boards are:
 "lacie,cloudbox"
 "lacie,inetspace_v2"
 "lacie,laplug"
+"lacie,nas2big"
 "lacie,netspace_lite_v2"
 "lacie,netspace_max_v2"
 "lacie,netspace_mini_v2"
diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,idle-state.txt b/Documentation/devicetree/bindings/arm/msm/qcom,idle-state.txt
new file mode 100644 (file)
index 0000000..06df04c
--- /dev/null
@@ -0,0 +1,84 @@
+QCOM Idle States for cpuidle driver
+
+ARM provides idle-state node to define the cpuidle states, as defined in [1].
+cpuidle-qcom is the cpuidle driver for Qualcomm SoCs and uses these idle
+states. Idle states have different enter/exit latency and residency values.
+The idle states supported by the QCOM SoC are defined as -
+
+    * Standby
+    * Retention
+    * Standalone Power Collapse (Standalone PC or SPC)
+    * Power Collapse (PC)
+
+Standby: Standby does a little more in addition to architectural clock gating.
+When the WFI instruction is executed the ARM core would gate its internal
+clocks. In addition to gating the clocks, QCOM cpus use this instruction as a
+trigger to execute the SPM state machine. The SPM state machine waits for the
+interrupt to trigger the core back in to active. This triggers the cache
+hierarchy to enter standby states, when all cpus are idle. An interrupt brings
+the SPM state machine out of its wait, the next step is to ensure that the
+cache hierarchy is also out of standby, and then the cpu is allowed to resume
+execution. This state is defined as a generic ARM WFI state by the ARM cpuidle
+driver and is not defined in the DT. The SPM state machine should be
+configured to execute this state by default and after executing every other
+state below.
+
+Retention: Retention is a low power state where the core is clock gated and
+the memory and the registers associated with the core are retained. The
+voltage may be reduced to the minimum value needed to keep the processor
+registers active. The SPM should be configured to execute the retention
+sequence and would wait for interrupt, before restoring the cpu to execution
+state. Retention may have a slightly higher latency than Standby.
+
+Standalone PC: A cpu can power down and warmboot if there is a sufficient time
+between the time it enters idle and the next known wake up. SPC mode is used
+to indicate a core entering a power down state without consulting any other
+cpu or the system resources. This helps save power only on that core.  The SPM
+sequence for this idle state is programmed to power down the supply to the
+core, wait for the interrupt, restore power to the core, and ensure the
+system state including cache hierarchy is ready before allowing core to
+resume. Applying power and resetting the core causes the core to warmboot
+back into Elevation Level (EL) which trampolines the control back to the
+kernel. Entering a power down state for the cpu, needs to be done by trapping
+into a EL. Failing to do so, would result in a crash enforced by the warm boot
+code in the EL for the SoC. On SoCs with write-back L1 cache, the cache has to
+be flushed in s/w, before powering down the core.
+
+Power Collapse: This state is similar to the SPC mode, but distinguishes
+itself in that the cpu acknowledges and permits the SoC to enter deeper sleep
+modes. In a hierarchical power domain SoC, this means L2 and other caches can
+be flushed, system bus, clocks - lowered, and SoC main XO clock gated and
+voltages reduced, provided all cpus enter this state.  Since the span of low
+power modes possible at this state is vast, the exit latency and the residency
+of this low power mode would be considered high even though at a cpu level,
+this essentially is cpu power down. The SPM in this state also may handshake
+with the Resource power manager (RPM) processor in the SoC to indicate a
+complete application processor subsystem shut down.
+
+The idle-state for QCOM SoCs are distinguished by the compatible property of
+the idle-states device node.
+
+The devicetree representation of the idle state should be -
+
+Required properties:
+
+- compatible: Must be one of -
+                       "qcom,idle-state-ret",
+                       "qcom,idle-state-spc",
+                       "qcom,idle-state-pc",
+               and "arm,idle-state".
+
+Other required and optional properties are specified in [1].
+
+Example:
+
+       idle-states {
+               CPU_SPC: spc {
+                       compatible = "qcom,idle-state-spc", "arm,idle-state";
+                       entry-latency-us = <150>;
+                       exit-latency-us = <200>;
+                       min-residency-us = <2000>;
+               };
+       };
+
+[1]. Documentation/devicetree/bindings/arm/idle-states.txt
index 1505fb8e131a889e4a62111c808cad57466f34bb..ae4afc6dcfe0a851a6264f50d633584f4f3a6cca 100644 (file)
@@ -2,22 +2,31 @@ SPM AVS Wrapper 2 (SAW2)
 
 The SAW2 is a wrapper around the Subsystem Power Manager (SPM) and the
 Adaptive Voltage Scaling (AVS) hardware. The SPM is a programmable
-micro-controller that transitions a piece of hardware (like a processor or
+power-controller that transitions a piece of hardware (like a processor or
 subsystem) into and out of low power modes via a direct connection to
 the PMIC. It can also be wired up to interact with other processors in the
 system, notifying them when a low power state is entered or exited.
 
+Multiple revisions of the SAW hardware are supported using these Device Nodes.
+SAW2 revisions differ in the register offset and configuration data. Also, the
+same revision of the SAW in different SoCs may have different configuration
+data due the the differences in hardware capabilities. Hence the SoC name, the
+version of the SAW hardware in that SoC and the distinction between cpu (big
+or Little) or cache, may be needed to uniquely identify the SAW register
+configuration and initialization data. The compatible string is used to
+indicate this parameter.
+
 PROPERTIES
 
 - compatible:
        Usage: required
        Value type: <string>
-       Definition: shall contain "qcom,saw2". A more specific value should be
-                   one of:
-                        "qcom,saw2-v1"
-                        "qcom,saw2-v1.1"
-                        "qcom,saw2-v2"
-                        "qcom,saw2-v2.1"
+       Definition: Must have
+                       "qcom,saw2"
+                   A more specific value could be one of:
+                       "qcom,apq8064-saw2-v1.1-cpu"
+                       "qcom,msm8974-saw2-v2.1-cpu"
+                       "qcom,apq8084-saw2-v2.1-cpu"
 
 - reg:
        Usage: required
@@ -26,10 +35,23 @@ PROPERTIES
                    the register region. An optional second element specifies
                    the base address and size of the alias register region.
 
+- regulator:
+       Usage: optional
+       Value type: boolean
+       Definition: Indicates that this SPM device acts as a regulator device
+                       device for the core (CPU or Cache) the SPM is attached
+                       to.
 
-Example:
+Example 1:
 
-       regulator@2099000 {
+       power-controller@2099000 {
                compatible = "qcom,saw2";
                reg = <0x02099000 0x1000>, <0x02009000 0x1000>;
+               regulator;
+       };
+
+Example 2:
+       saw0: power-controller@f9089000 {
+               compatible = "qcom,apq8084-saw2-v2.1-cpu", "qcom,saw2";
+               reg = <0xf9089000 0x1000>, <0xf9009000 0x1000>;
        };
index 74607b6c111763cd4e3174da9bb62817f59fe79f..5e10c345548f56b18422c9995b6fe0bdaa33d7b0 100644 (file)
@@ -9,11 +9,17 @@ Properties:
                "qcom,scss-timer" - scorpion subsystem
 
 - interrupts : Interrupts for the debug timer, the first general purpose
-               timer, and optionally a second general purpose timer in that
-               order.
+               timer, and optionally a second general purpose timer, and
+               optionally as well, 2 watchdog interrupts, in that order.
 
 - reg : Specifies the base address of the timer registers.
 
+- clocks: Reference to the parent clocks, one per output clock. The parents
+          must appear in the same order as the clock names.
+
+- clock-names: The name of the clocks as free-form strings. They should be in
+               the same order as the clocks.
+
 - clock-frequency : The frequency of the debug timer and the general purpose
                     timer(s) in Hz in that order.
 
@@ -29,9 +35,13 @@ Example:
                compatible = "qcom,scss-timer", "qcom,msm-timer";
                interrupts = <1 1 0x301>,
                             <1 2 0x301>,
-                            <1 3 0x301>;
+                            <1 3 0x301>,
+                            <1 4 0x301>,
+                            <1 5 0x301>;
                reg = <0x0200a000 0x100>;
                clock-frequency = <19200000>,
                                  <32768>;
+               clocks = <&sleep_clk>;
+               clock-names = "sleep";
                cpu-offset = <0x40000>;
        };
diff --git a/Documentation/devicetree/bindings/arm/omap/ctrl.txt b/Documentation/devicetree/bindings/arm/omap/ctrl.txt
new file mode 100644 (file)
index 0000000..3a4e590
--- /dev/null
@@ -0,0 +1,79 @@
+OMAP Control Module bindings
+
+Control Module contains miscellaneous features under it based on SoC type.
+Pincontrol is one common feature, and it has a specialized support
+described in [1]. Typically some clock nodes are also under control module.
+Syscon is used to share register level access to drivers external to
+control module driver itself.
+
+See [2] for documentation about clock/clockdomain nodes.
+
+[1] Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
+[2] Documentation/devicetree/bindings/clock/ti/*
+
+Required properties:
+- compatible:  Must be one of:
+               "ti,am3-scm"
+               "ti,am4-scm"
+               "ti,dm814-scrm"
+               "ti,dm816-scrm"
+               "ti,omap2-scm"
+               "ti,omap3-scm"
+               "ti,omap4-scm-core"
+               "ti,omap4-scm-padconf-core"
+               "ti,omap5-scm-core"
+               "ti,omap5-scm-padconf-core"
+               "ti,dra7-scm-core"
+- reg:         Contains Control Module register address range
+               (base address and length)
+
+Optional properties:
+- clocks:      clocks for this module
+- clockdomains:        clockdomains for this module
+
+Examples:
+
+scm: scm@2000 {
+       compatible = "ti,omap3-scm", "simple-bus";
+       reg = <0x2000 0x2000>;
+       #address-cells = <1>;
+       #size-cells = <1>;
+       ranges = <0 0x2000 0x2000>;
+
+       omap3_pmx_core: pinmux@30 {
+               compatible = "ti,omap3-padconf",
+                            "pinctrl-single";
+               reg = <0x30 0x230>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               #interrupt-cells = <1>;
+               interrupt-controller;
+               pinctrl-single,register-width = <16>;
+               pinctrl-single,function-mask = <0xff1f>;
+       };
+
+       scm_conf: scm_conf@270 {
+               compatible = "syscon";
+               reg = <0x270 0x330>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               scm_clocks: clocks {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+       };
+
+       scm_clockdomains: clockdomains {
+       };
+}
+
+&scm_clocks {
+       mcbsp5_mux_fck: mcbsp5_mux_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-mux-clock";
+               clocks = <&core_96m_fck>, <&mcbsp_clks>;
+               ti,bit-shift = <4>;
+               reg = <0x02d8>;
+       };
+};
diff --git a/Documentation/devicetree/bindings/arm/omap/l4.txt b/Documentation/devicetree/bindings/arm/omap/l4.txt
new file mode 100644 (file)
index 0000000..b4f8a16
--- /dev/null
@@ -0,0 +1,26 @@
+L4 interconnect bindings
+
+These bindings describe the OMAP SoCs L4 interconnect bus.
+
+Required properties:
+- compatible : Should be "ti,omap2-l4" for OMAP2 family l4 core bus
+              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-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
+              Should be "ti,dra7-l4-cfg" for DRA7 family l4 cfg bus
+              Should be "ti,dra7-l4-wkup" for DRA7 family l4 wkup bus
+              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
+
+Examples:
+
+l4: l4@48000000 {
+       compatible "ti,omap2-l4", "simple-bus";
+       #address-cells = <1>;
+       #size-cells = <1>;
+       ranges = <0 0x48000000 0x100000>;
+};
index 79074dac684abfd6eec2239ef2a128955cd1641f..3eb6d7afff14395229b36e349f13c52e87a96be8 100644 (file)
@@ -10,14 +10,10 @@ documentation about the individual clock/clockdomain nodes.
 Required properties:
 - compatible:  Must be one of:
                "ti,am3-prcm"
-               "ti,am3-scrm"
                "ti,am4-prcm"
-               "ti,am4-scrm"
                "ti,omap2-prcm"
-               "ti,omap2-scrm"
                "ti,omap3-prm"
                "ti,omap3-cm"
-               "ti,omap3-scrm"
                "ti,omap4-cm1"
                "ti,omap4-prm"
                "ti,omap4-cm2"
@@ -29,6 +25,8 @@ Required properties:
                "ti,dra7-prm"
                "ti,dra7-cm-core-aon"
                "ti,dra7-cm-core"
+               "ti,dm814-prcm"
+               "ti,dm816-prcm"
 - reg:         Contains PRCM module register address range
                (base address and length)
 - clocks:      clocks for this module
index 6809e4e51ed29bc6eda1a772b91d576aeb0cfeb0..60d4a1e0a9b589011b956ad674bb7955dbf2f19b 100644 (file)
@@ -22,3 +22,7 @@ Rockchip platforms device tree bindings
       - compatible = "firefly,firefly-rk3288", "rockchip,rk3288";
     or
       - compatible = "firefly,firefly-rk3288-beta", "rockchip,rk3288";
+
+- ChipSPARK PopMetal-RK3288 board:
+    Required root node properties:
+      - compatible = "chipspark,popmetal-rk3288", "rockchip,rk3288";
index 51147cb5c036599a0741a5cc2172f0f21d07ad39..c4f19b2e7dd95c1022a43ebe2b764a6c58f26062 100644 (file)
@@ -7,8 +7,6 @@ SoCs:
     compatible = "renesas,emev2"
   - RZ/A1H (R7S72100)
     compatible = "renesas,r7s72100"
-  - SH-Mobile AP4 (R8A73720/SH7372)
-    compatible = "renesas,sh7372"
   - SH-Mobile AG5 (R8A73A00/SH73A0)
     compatible = "renesas,sh73a0"
   - R-Mobile APE6 (R8A73A40)
@@ -37,8 +35,6 @@ Boards:
     compatible = "renesas,alt", "renesas,r8a7794"
   - APE6-EVM
     compatible = "renesas,ape6evm", "renesas,r8a73a4"
-  - APE6-EVM - Reference Device Tree Implementation
-    compatible = "renesas,ape6evm-reference", "renesas,r8a73a4"
   - Atmark Techno Armadillo-800 EVA
     compatible = "renesas,armadillo800eva"
   - BOCK-W
@@ -57,12 +53,8 @@ Boards:
     compatible = "renesas,kzm9d", "renesas,emev2"
   - Kyoto Microcomputer Co. KZM-A9-GT
     compatible = "renesas,kzm9g", "renesas,sh73a0"
-  - Kyoto Microcomputer Co. KZM-A9-GT - Reference Device Tree Implementation
-    compatible = "renesas,kzm9g-reference", "renesas,sh73a0"
   - Lager (RTP0RC7790SEB00010S)
     compatible = "renesas,lager", "renesas,r8a7790"
-  - Mackerel (R0P7372LC0016RL, AP4 EVM 2nd)
-    compatible = "renesas,mackerel"
   - Marzen
     compatible = "renesas,marzen", "renesas,r8a7779"
 
diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra30-actmon.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra30-actmon.txt
new file mode 100644 (file)
index 0000000..ea670a5
--- /dev/null
@@ -0,0 +1,32 @@
+NVIDIA Tegra Activity Monitor
+
+The activity monitor block collects statistics about the behaviour of other
+components in the system. This information can be used to derive the rate at
+which the external memory needs to be clocked in order to serve all requests
+from the monitored clients.
+
+Required properties:
+- compatible: should be "nvidia,tegra<chip>-actmon"
+- reg: offset and length of the register set for the device
+- interrupts: standard interrupt property
+- clocks: Must contain a phandle and clock specifier pair for each entry in
+clock-names. See ../../clock/clock-bindings.txt for details.
+- clock-names: Must include the following entries:
+  - actmon
+  - emc
+- resets: Must contain an entry for each entry in reset-names. See
+../../reset/reset.txt for details.
+- reset-names: Must include the following entries:
+  - actmon
+
+Example:
+       actmon@6000c800 {
+               compatible = "nvidia,tegra124-actmon";
+               reg = <0x0 0x6000c800 0x0 0x400>;
+               interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&tegra_car TEGRA124_CLK_ACTMON>,
+                        <&tegra_car TEGRA124_CLK_EMC>;
+               clock-names = "actmon", "emc";
+               resets = <&tegra_car 119>;
+               reset-names = "actmon";
+       };
index 63dd8051521c32d3674db1044ab75d01535ee074..18729f6fe1e5fbc5dea3e36c98715b4c22e4315f 100644 (file)
@@ -1,7 +1,8 @@
 * OMAP OCP2SCP - ocp interface to scp interface
 
 properties:
-- compatible : Should be "ti,omap-ocp2scp"
+- compatible : Should be "ti,am437x-ocp2scp" for AM437x processor
+              Should be "ti,omap-ocp2scp" for all others
 - reg : Address and length of the register set for the device
 - #address-cells, #size-cells : Must be present if the device has sub-nodes
 - ranges : the child address space are mapped 1:1 onto the parent address space
diff --git a/Documentation/devicetree/bindings/bus/renesas,bsc.txt b/Documentation/devicetree/bindings/bus/renesas,bsc.txt
new file mode 100644 (file)
index 0000000..90e9472
--- /dev/null
@@ -0,0 +1,46 @@
+Renesas Bus State Controller (BSC)
+==================================
+
+The Renesas Bus State Controller (BSC, sometimes called "LBSC within Bus
+Bridge", or "External Bus Interface") can be found in several Renesas ARM SoCs.
+It provides an external bus for connecting multiple external devices to the
+SoC, driving several chip select lines, for e.g. NOR FLASH, Ethernet and USB.
+
+While the BSC is a fairly simple memory-mapped bus, it may be part of a PM
+domain, and may have a gateable functional clock.
+Before a device connected to the BSC can be accessed, the PM domain
+containing the BSC must be powered on, and the functional clock
+driving the BSC must be enabled.
+
+The bindings for the BSC extend the bindings for "simple-pm-bus".
+
+
+Required properties
+  - compatible: Must contain an SoC-specific value, and "renesas,bsc" and
+               "simple-pm-bus" as fallbacks.
+                SoC-specific values can be:
+               "renesas,bsc-r8a73a4" for R-Mobile APE6 (r8a73a4)
+               "renesas,bsc-sh73a0" for SH-Mobile AG5 (sh73a0)
+  - #address-cells, #size-cells, ranges: Must describe the mapping between
+               parent address and child address spaces.
+  - reg: Must contain the base address and length to access the bus controller.
+
+Optional properties:
+  - interrupts: Must contain a reference to the BSC interrupt, if available.
+  - clocks: Must contain a reference to the functional clock, if available.
+  - power-domains: Must contain a reference to the PM domain, if available.
+
+
+Example:
+
+       bsc: bus@fec10000 {
+               compatible = "renesas,bsc-sh73a0", "renesas,bsc",
+                            "simple-pm-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0 0 0x20000000>;
+               reg = <0xfec10000 0x400>;
+               interrupts = <0 39 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&zb_clk>;
+               power-domains = <&pd_a4s>;
+       };
diff --git a/Documentation/devicetree/bindings/bus/simple-pm-bus.txt b/Documentation/devicetree/bindings/bus/simple-pm-bus.txt
new file mode 100644 (file)
index 0000000..d032237
--- /dev/null
@@ -0,0 +1,44 @@
+Simple Power-Managed Bus
+========================
+
+A Simple Power-Managed Bus is a transparent bus that doesn't need a real
+driver, as it's typically initialized by the boot loader.
+
+However, its bus controller is part of a PM domain, or under the control of a
+functional clock.  Hence, the bus controller's PM domain and/or clock must be
+enabled for child devices connected to the bus (either on-SoC or externally)
+to function.
+
+While "simple-pm-bus" follows the "simple-bus" set of properties, as specified
+in ePAPR, it is not an extension of "simple-bus".
+
+
+Required properties:
+  - compatible: Must contain at least "simple-pm-bus".
+               Must not contain "simple-bus".
+               It's recommended to let this be preceded by one or more
+               vendor-specific compatible values.
+  - #address-cells, #size-cells, ranges: Must describe the mapping between
+               parent address and child address spaces.
+
+Optional platform-specific properties for clock or PM domain control (at least
+one of them is required):
+  - clocks: Must contain a reference to the functional clock(s),
+  - power-domains: Must contain a reference to the PM domain.
+Please refer to the binding documentation for the clock and/or PM domain
+providers for more details.
+
+
+Example:
+
+       bsc: bus@fec10000 {
+               compatible = "renesas,bsc-sh73a0", "renesas,bsc",
+                            "simple-pm-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0 0 0x20000000>;
+               reg = <0xfec10000 0x400>;
+               interrupts = <0 39 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&zb_clk>;
+               power-domains = <&pd_a4s>;
+       };
index f57d9dd9ea8530ae9c8d02723b1bc15d38002497..f1738b88c22596afe1a49edb114bcdc31e3f9475 100644 (file)
@@ -9,6 +9,8 @@ Required Properties:
   - "samsung,exynos3250-cmu" - controller compatible with Exynos3250 SoC.
   - "samsung,exynos3250-cmu-dmc" - controller compatible with
     Exynos3250 SoC for Dynamic Memory Controller domain.
+  - "samsung,exynos3250-cmu-isp" - ISP block clock controller compatible
+     with Exynos3250 SOC
 
 - reg: physical base address of the controller and length of memory mapped
   region.
@@ -36,6 +38,12 @@ Example 1: Examples of clock controller nodes are listed below.
                #clock-cells = <1>;
        };
 
+       cmu_isp: clock-controller@10048000 {
+               compatible = "samsung,exynos3250-cmu-isp";
+               reg = <0x10048000 0x1000>;
+               #clock-cells = <1>;
+       };
+
 Example 2: UART controller node that consumes the clock generated by the clock
           controller. Refer to the standard clock bindings for information
           about 'clocks' and 'clock-names' property.
diff --git a/Documentation/devicetree/bindings/clock/exynos5433-clock.txt b/Documentation/devicetree/bindings/clock/exynos5433-clock.txt
new file mode 100644 (file)
index 0000000..63379b0
--- /dev/null
@@ -0,0 +1,462 @@
+* Samsung Exynos5433 CMU (Clock Management Units)
+
+The Exynos5433 clock controller generates and supplies clock to various
+controllers within the Exynos5433 SoC.
+
+Required Properties:
+
+- compatible: should be one of the following.
+  - "samsung,exynos5433-cmu-top"   - clock controller compatible for CMU_TOP
+    which generates clocks for IMEM/FSYS/G3D/GSCL/HEVC/MSCL/G2D/MFC/PERIC/PERIS
+    domains and bus clocks.
+  - "samsung,exynos5433-cmu-cpif"  - clock controller compatible for CMU_CPIF
+    which generates clocks for LLI (Low Latency Interface) IP.
+  - "samsung,exynos5433-cmu-mif"   - clock controller compatible for CMU_MIF
+    which generates clocks for DRAM Memory Controller domain.
+  - "samsung,exynos5433-cmu-peric" - clock controller compatible for CMU_PERIC
+    which generates clocks for UART/I2C/SPI/I2S/PCM/SPDIF/PWM/SLIMBUS IPs.
+  - "samsung,exynos5433-cmu-peris" - clock controller compatible for CMU_PERIS
+    which generates clocks for PMU/TMU/MCT/WDT/RTC/SECKEY/TZPC IPs.
+  - "samsung,exynos5433-cmu-fsys"  - clock controller compatible for CMU_FSYS
+    which generates clocks for USB/UFS/SDMMC/TSI/PDMA IPs.
+  - "samsung,exynos5433-cmu-g2d"   - clock controller compatible for CMU_G2D
+    which generates clocks for G2D/MDMA IPs.
+  - "samsung,exynos5433-cmu-disp"  - clock controller compatible for CMU_DISP
+    which generates clocks for Display (DECON/HDMI/DSIM/MIXER) IPs.
+  - "samsung,exynos5433-cmu-aud"   - clock controller compatible for CMU_AUD
+    which generates clocks for Cortex-A5/BUS/AUDIO clocks.
+  - "samsung,exynos5433-cmu-bus0", "samsung,exynos5433-cmu-bus1"
+    and "samsung,exynos5433-cmu-bus2" - clock controller compatible for CMU_BUS
+    which generates global data buses clock and global peripheral buses clock.
+  - "samsung,exynos5433-cmu-g3d"  - clock controller compatible for CMU_G3D
+    which generates clocks for 3D Graphics Engine IP.
+  - "samsung,exynos5433-cmu-gscl"  - clock controller compatible for CMU_GSCL
+    which generates clocks for GSCALER IPs.
+  - "samsung,exynos5433-cmu-apollo"- clock controller compatible for CMU_APOLLO
+    which generates clocks for Cortex-A53 Quad-core processor.
+  - "samsung,exynos5433-cmu-atlas" - clock controller compatible for CMU_ATLAS
+    which generates clocks for Cortex-A57 Quad-core processor, CoreSight and
+    L2 cache controller.
+  - "samsung,exynos5433-cmu-mscl" - clock controller compatible for CMU_MSCL
+    which generates clocks for M2M (Memory to Memory) scaler and JPEG IPs.
+  - "samsung,exynos5433-cmu-mfc"  - clock controller compatible for CMU_MFC
+    which generates clocks for MFC(Multi-Format Codec) IP.
+  - "samsung,exynos5433-cmu-hevc" - clock controller compatible for CMU_HEVC
+    which generates clocks for HEVC(High Efficiency Video Codec) decoder IP.
+  - "samsung,exynos5433-cmu-isp" - clock controller compatible for CMU_ISP
+    which generates clocks for FIMC-ISP/DRC/SCLC/DIS/3DNR IPs.
+  - "samsung,exynos5433-cmu-cam0" - clock controller compatible for CMU_CAM0
+    which generates clocks for MIPI_CSIS{0|1}/FIMC_LITE_{A|B|D}/FIMC_3AA{0|1}
+    IPs.
+  - "samsung,exynos5433-cmu-cam1" - clock controller compatible for CMU_CAM1
+    which generates clocks for Cortex-A5/MIPI_CSIS2/FIMC-LITE_C/FIMC-FD IPs.
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- #clock-cells: should be 1.
+
+- clocks: list of the clock controller input clock identifiers,
+       from common clock bindings. Please refer the next section
+       to find the input clocks for a given controller.
+
+- clock-names: list of the clock controller input clock names,
+       as described in clock-bindings.txt.
+
+       Input clocks for top clock controller:
+               - oscclk
+               - sclk_mphy_pll
+               - sclk_mfc_pll
+               - sclk_bus_pll
+
+       Input clocks for cpif clock controller:
+               - oscclk
+
+       Input clocks for mif clock controller:
+               - oscclk
+               - sclk_mphy_pll
+
+       Input clocks for fsys clock controller:
+               - oscclk
+               - sclk_ufs_mphy
+               - div_aclk_fsys_200
+               - sclk_pcie_100_fsys
+               - sclk_ufsunipro_fsys
+               - sclk_mmc2_fsys
+               - sclk_mmc1_fsys
+               - sclk_mmc0_fsys
+               - sclk_usbhost30_fsys
+               - sclk_usbdrd30_fsys
+
+       Input clocks for g2d clock controller:
+               - oscclk
+               - aclk_g2d_266
+               - aclk_g2d_400
+
+       Input clocks for disp clock controller:
+               - oscclk
+               - sclk_dsim1_disp
+               - sclk_dsim0_disp
+               - sclk_dsd_disp
+               - sclk_decon_tv_eclk_disp
+               - sclk_decon_vclk_disp
+               - sclk_decon_eclk_disp
+               - sclk_decon_tv_vclk_disp
+               - aclk_disp_333
+
+       Input clocks for bus0 clock controller:
+               - aclk_bus0_400
+
+       Input clocks for bus1 clock controller:
+               - aclk_bus1_400
+
+       Input clocks for bus2 clock controller:
+               - oscclk
+               - aclk_bus2_400
+
+       Input clocks for g3d clock controller:
+               - oscclk
+               - aclk_g3d_400
+
+       Input clocks for gscl clock controller:
+               - oscclk
+               - aclk_gscl_111
+               - aclk_gscl_333
+
+       Input clocks for apollo clock controller:
+               - oscclk
+               - sclk_bus_pll_apollo
+
+       Input clocks for atlas clock controller:
+               - oscclk
+               - sclk_bus_pll_atlas
+
+       Input clocks for mscl clock controller:
+               - oscclk
+               - sclk_jpeg_mscl
+               - aclk_mscl_400
+
+       Input clocks for mfc clock controller:
+               - oscclk
+               - aclk_mfc_400
+
+       Input clocks for hevc clock controller:
+               - oscclk
+               - aclk_hevc_400
+
+       Input clocks for isp clock controller:
+               - oscclk
+               - aclk_isp_dis_400
+               - aclk_isp_400
+
+       Input clocks for cam0 clock controller:
+               - oscclk
+               - aclk_cam0_333
+               - aclk_cam0_400
+               - aclk_cam0_552
+
+       Input clocks for cam1 clock controller:
+               - oscclk
+               - sclk_isp_uart_cam1
+               - sclk_isp_spi1_cam1
+               - sclk_isp_spi0_cam1
+               - aclk_cam1_333
+               - aclk_cam1_400
+               - aclk_cam1_552
+
+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/exynos5433.h header and can be used in device
+tree sources.
+
+Example 1: Examples of 'oscclk' source clock node are listed below.
+
+       xxti: xxti {
+               compatible = "fixed-clock";
+               clock-output-names = "oscclk";
+               #clock-cells = <0>;
+       };
+
+Example 2: Examples of clock controller nodes are listed below.
+
+       cmu_top: clock-controller@10030000 {
+               compatible = "samsung,exynos5433-cmu-top";
+               reg = <0x10030000 0x0c04>;
+               #clock-cells = <1>;
+
+               clock-names = "oscclk",
+                       "sclk_mphy_pll",
+                       "sclk_mfc_pll",
+                       "sclk_bus_pll";
+               clocks = <&xxti>,
+                      <&cmu_cpif CLK_SCLK_MPHY_PLL>,
+                      <&cmu_mif CLK_SCLK_MFC_PLL>,
+                      <&cmu_mif CLK_SCLK_BUS_PLL>;
+       };
+
+       cmu_cpif: clock-controller@10fc0000 {
+               compatible = "samsung,exynos5433-cmu-cpif";
+               reg = <0x10fc0000 0x0c04>;
+               #clock-cells = <1>;
+
+               clock-names = "oscclk";
+               clocks = <&xxti>;
+       };
+
+       cmu_mif: clock-controller@105b0000 {
+               compatible = "samsung,exynos5433-cmu-mif";
+               reg = <0x105b0000 0x100c>;
+               #clock-cells = <1>;
+
+               clock-names = "oscclk",
+                       "sclk_mphy_pll";
+               clocks = <&xxti>,
+                      <&cmu_cpif CLK_SCLK_MPHY_PLL>;
+       };
+
+       cmu_peric: clock-controller@14c80000 {
+               compatible = "samsung,exynos5433-cmu-peric";
+               reg = <0x14c80000 0x0b08>;
+               #clock-cells = <1>;
+       };
+
+       cmu_peris: clock-controller@10040000 {
+               compatible = "samsung,exynos5433-cmu-peris";
+               reg = <0x10040000 0x0b20>;
+               #clock-cells = <1>;
+       };
+
+       cmu_fsys: clock-controller@156e0000 {
+               compatible = "samsung,exynos5433-cmu-fsys";
+               reg = <0x156e0000 0x0b04>;
+               #clock-cells = <1>;
+
+               clock-names = "oscclk",
+                       "sclk_ufs_mphy",
+                       "div_aclk_fsys_200",
+                       "sclk_pcie_100_fsys",
+                       "sclk_ufsunipro_fsys",
+                       "sclk_mmc2_fsys",
+                       "sclk_mmc1_fsys",
+                       "sclk_mmc0_fsys",
+                       "sclk_usbhost30_fsys",
+                       "sclk_usbdrd30_fsys";
+               clocks = <&xxti>,
+                      <&cmu_cpif CLK_SCLK_UFS_MPHY>,
+                      <&cmu_top CLK_DIV_ACLK_FSYS_200>,
+                      <&cmu_top CLK_SCLK_PCIE_100_FSYS>,
+                      <&cmu_top CLK_SCLK_UFSUNIPRO_FSYS>,
+                      <&cmu_top CLK_SCLK_MMC2_FSYS>,
+                      <&cmu_top CLK_SCLK_MMC1_FSYS>,
+                      <&cmu_top CLK_SCLK_MMC0_FSYS>,
+                      <&cmu_top CLK_SCLK_USBHOST30_FSYS>,
+                      <&cmu_top CLK_SCLK_USBDRD30_FSYS>;
+       };
+
+       cmu_g2d: clock-controller@12460000 {
+               compatible = "samsung,exynos5433-cmu-g2d";
+               reg = <0x12460000 0x0b08>;
+               #clock-cells = <1>;
+
+               clock-names = "oscclk",
+                       "aclk_g2d_266",
+                       "aclk_g2d_400";
+               clocks = <&xxti>,
+                      <&cmu_top CLK_ACLK_G2D_266>,
+                      <&cmu_top CLK_ACLK_G2D_400>;
+       };
+
+       cmu_disp: clock-controller@13b90000 {
+               compatible = "samsung,exynos5433-cmu-disp";
+               reg = <0x13b90000 0x0c04>;
+               #clock-cells = <1>;
+
+               clock-names = "oscclk",
+                       "sclk_dsim1_disp",
+                       "sclk_dsim0_disp",
+                       "sclk_dsd_disp",
+                       "sclk_decon_tv_eclk_disp",
+                       "sclk_decon_vclk_disp",
+                       "sclk_decon_eclk_disp",
+                       "sclk_decon_tv_vclk_disp",
+                       "aclk_disp_333";
+               clocks = <&xxti>,
+                      <&cmu_mif CLK_SCLK_DSIM1_DISP>,
+                      <&cmu_mif CLK_SCLK_DSIM0_DISP>,
+                      <&cmu_mif CLK_SCLK_DSD_DISP>,
+                      <&cmu_mif CLK_SCLK_DECON_TV_ECLK_DISP>,
+                      <&cmu_mif CLK_SCLK_DECON_VCLK_DISP>,
+                      <&cmu_mif CLK_SCLK_DECON_ECLK_DISP>,
+                      <&cmu_mif CLK_SCLK_DECON_TV_VCLK_DISP>,
+                      <&cmu_mif CLK_ACLK_DISP_333>;
+       };
+
+       cmu_aud: clock-controller@114c0000 {
+               compatible = "samsung,exynos5433-cmu-aud";
+               reg = <0x114c0000 0x0b04>;
+               #clock-cells = <1>;
+       };
+
+       cmu_bus0: clock-controller@13600000 {
+               compatible = "samsung,exynos5433-cmu-bus0";
+               reg = <0x13600000 0x0b04>;
+               #clock-cells = <1>;
+
+               clock-names = "aclk_bus0_400";
+               clocks = <&cmu_top CLK_ACLK_BUS0_400>;
+       };
+
+       cmu_bus1: clock-controller@14800000 {
+               compatible = "samsung,exynos5433-cmu-bus1";
+               reg = <0x14800000 0x0b04>;
+               #clock-cells = <1>;
+
+               clock-names = "aclk_bus1_400";
+               clocks = <&cmu_top CLK_ACLK_BUS1_400>;
+       };
+
+       cmu_bus2: clock-controller@13400000 {
+               compatible = "samsung,exynos5433-cmu-bus2";
+               reg = <0x13400000 0x0b04>;
+               #clock-cells = <1>;
+
+               clock-names = "oscclk", "aclk_bus2_400";
+               clocks = <&xxti>, <&cmu_mif CLK_ACLK_BUS2_400>;
+       };
+
+       cmu_g3d: clock-controller@14aa0000 {
+               compatible = "samsung,exynos5433-cmu-g3d";
+               reg = <0x14aa0000 0x1000>;
+               #clock-cells = <1>;
+
+               clock-names = "oscclk", "aclk_g3d_400";
+               clocks = <&xxti>, <&cmu_top CLK_ACLK_G3D_400>;
+       };
+
+       cmu_gscl: clock-controller@13cf0000 {
+               compatible = "samsung,exynos5433-cmu-gscl";
+               reg = <0x13cf0000 0x0b10>;
+               #clock-cells = <1>;
+
+               clock-names = "oscclk",
+                       "aclk_gscl_111",
+                       "aclk_gscl_333";
+               clocks = <&xxti>,
+                       <&cmu_top CLK_ACLK_GSCL_111>,
+                       <&cmu_top CLK_ACLK_GSCL_333>;
+       };
+
+       cmu_apollo: clock-controller@11900000 {
+               compatible = "samsung,exynos5433-cmu-apollo";
+               reg = <0x11900000 0x1088>;
+               #clock-cells = <1>;
+
+               clock-names = "oscclk", "sclk_bus_pll_apollo";
+               clocks = <&xxti>, <&cmu_mif CLK_SCLK_BUS_PLL_APOLLO>;
+       };
+
+       cmu_atlas: clock-controller@11800000 {
+               compatible = "samsung,exynos5433-cmu-atlas";
+               reg = <0x11800000 0x1088>;
+               #clock-cells = <1>;
+
+               clock-names = "oscclk", "sclk_bus_pll_atlas";
+               clocks = <&xxti>, <&cmu_mif CLK_SCLK_BUS_PLL_ATLAS>;
+       };
+
+       cmu_mscl: clock-controller@105d0000 {
+               compatible = "samsung,exynos5433-cmu-mscl";
+               reg = <0x105d0000 0x0b10>;
+               #clock-cells = <1>;
+
+               clock-names = "oscclk",
+                       "sclk_jpeg_mscl",
+                       "aclk_mscl_400";
+               clocks = <&xxti>,
+                      <&cmu_top CLK_SCLK_JPEG_MSCL>,
+                      <&cmu_top CLK_ACLK_MSCL_400>;
+       };
+
+       cmu_mfc: clock-controller@15280000 {
+               compatible = "samsung,exynos5433-cmu-mfc";
+               reg = <0x15280000 0x0b08>;
+               #clock-cells = <1>;
+
+               clock-names = "oscclk", "aclk_mfc_400";
+               clocks = <&xxti>, <&cmu_top CLK_ACLK_MFC_400>;
+       };
+
+       cmu_hevc: clock-controller@14f80000 {
+               compatible = "samsung,exynos5433-cmu-hevc";
+               reg = <0x14f80000 0x0b08>;
+               #clock-cells = <1>;
+
+               clock-names = "oscclk", "aclk_hevc_400";
+               clocks = <&xxti>, <&cmu_top CLK_ACLK_HEVC_400>;
+       };
+
+       cmu_isp: clock-controller@146d0000 {
+               compatible = "samsung,exynos5433-cmu-isp";
+               reg = <0x146d0000 0x0b0c>;
+               #clock-cells = <1>;
+
+               clock-names = "oscclk",
+                       "aclk_isp_dis_400",
+                       "aclk_isp_400";
+               clocks = <&xxti>,
+                      <&cmu_top CLK_ACLK_ISP_DIS_400>,
+                      <&cmu_top CLK_ACLK_ISP_400>;
+       };
+
+       cmu_cam0: clock-controller@120d0000 {
+               compatible = "samsung,exynos5433-cmu-cam0";
+               reg = <0x120d0000 0x0b0c>;
+               #clock-cells = <1>;
+
+               clock-names = "oscclk",
+                       "aclk_cam0_333",
+                       "aclk_cam0_400",
+                       "aclk_cam0_552";
+               clocks = <&xxti>,
+                      <&cmu_top CLK_ACLK_CAM0_333>,
+                      <&cmu_top CLK_ACLK_CAM0_400>,
+                      <&cmu_top CLK_ACLK_CAM0_552>;
+       };
+
+       cmu_cam1: clock-controller@145d0000 {
+               compatible = "samsung,exynos5433-cmu-cam1";
+               reg = <0x145d0000 0x0b08>;
+               #clock-cells = <1>;
+
+               clock-names = "oscclk",
+                       "sclk_isp_uart_cam1",
+                       "sclk_isp_spi1_cam1",
+                       "sclk_isp_spi0_cam1",
+                       "aclk_cam1_333",
+                       "aclk_cam1_400",
+                       "aclk_cam1_552";
+               clocks = <&xxti>,
+                      <&cmu_top CLK_SCLK_ISP_UART_CAM1>,
+                      <&cmu_top CLK_SCLK_ISP_SPI1_CAM1>,
+                      <&cmu_top CLK_SCLK_ISP_SPI0_CAM1>,
+                      <&cmu_top CLK_ACLK_CAM1_333>,
+                      <&cmu_top CLK_ACLK_CAM1_400>,
+                      <&cmu_top CLK_ACLK_CAM1_552>;
+       };
+
+Example 3: UART controller node that consumes the clock generated by the clock
+          controller.
+
+       serial_0: serial@14C10000 {
+               compatible = "samsung,exynos5433-uart";
+               reg = <0x14C10000 0x100>;
+               interrupts = <0 421 0>;
+               clocks = <&cmu_peric CLK_PCLK_UART0>,
+                        <&cmu_peric CLK_SCLK_UART0>;
+               clock-names = "uart", "clk_uart_baud0";
+               pinctrl-names = "default";
+               pinctrl-0 = <&uart0_bus>;
+               status = "disabled";
+       };
diff --git a/Documentation/devicetree/bindings/clock/fujitsu,mb86s70-crg11.txt b/Documentation/devicetree/bindings/clock/fujitsu,mb86s70-crg11.txt
new file mode 100644 (file)
index 0000000..3323962
--- /dev/null
@@ -0,0 +1,26 @@
+Fujitsu CRG11 clock driver bindings
+-----------------------------------
+
+Required properties :
+- compatible : Shall contain "fujitsu,mb86s70-crg11"
+- #clock-cells : Shall be 3 {cntrlr domain port}
+
+The consumer specifies the desired clock pointing to its phandle.
+
+Example:
+
+       clock: crg11 {
+               compatible = "fujitsu,mb86s70-crg11";
+               #clock-cells = <3>;
+       };
+
+       mhu: mhu0@2b1f0000 {
+               #mbox-cells = <1>;
+               compatible = "arm,mhu";
+               reg = <0 0x2B1F0000 0x1000>;
+               interrupts = <0 36 4>, /* LP Non-Sec */
+                            <0 35 4>, /* HP Non-Sec */
+                            <0 37 4>; /* Secure */
+               clocks = <&clock 0 2 1>; /* Cntrlr:0 Domain:2 Port:1 */
+               clock-names = "clk";
+       };
index dc5ea5b22da90dbf43f0d5e15b28141d3c7e0e4d..670c2af3e931a779adbe3bbdd06674181e82cf8d 100644 (file)
@@ -23,6 +23,14 @@ The following is a list of provided IDs and clock names on Armada 380/385:
  2 = l2clk   (L2 Cache clock)
  3 = ddrclk  (DDR clock)
 
+The following is a list of provided IDs and clock names on Armada 39x:
+ 0 = tclk    (Internal Bus clock)
+ 1 = cpuclk  (CPU clock)
+ 2 = nbclk   (Coherent Fabric clock)
+ 3 = hclk    (SDRAM Controller Internal Clock)
+ 4 = dclk    (SDRAM Interface Clock)
+ 5 = refclk  (Reference Clock)
+
 The following is a list of provided IDs and clock names on Kirkwood and Dove:
  0 = tclk   (Internal Bus clock)
  1 = cpuclk (CPU0 clock)
@@ -39,6 +47,7 @@ Required properties:
        "marvell,armada-370-core-clock" - For Armada 370 SoC core clocks
        "marvell,armada-375-core-clock" - For Armada 375 SoC core clocks
        "marvell,armada-380-core-clock" - For Armada 380/385 SoC core clocks
+       "marvell,armada-390-core-clock" - For Armada 39x SoC core clocks
        "marvell,armada-xp-core-clock" - For Armada XP SoC core clocks
        "marvell,dove-core-clock" - for Dove SoC core clocks
        "marvell,kirkwood-core-clock" - for Kirkwood SoC (except mv88f6180)
index 76477be742b21c016e06d59f2a67c28b9ffdabf0..31c7c0c1ce8f6b47a625f8b6f41eafc6a35d402a 100644 (file)
@@ -1,6 +1,6 @@
 * Gated Clock bindings for Marvell EBU SoCs
 
-Marvell Armada 370/375/380/385/XP, Dove and Kirkwood allow some
+Marvell Armada 370/375/380/385/39x/XP, Dove and Kirkwood allow some
 peripheral clocks to be gated to save some power. The clock consumer
 should specify the desired clock by having the clock ID in its
 "clocks" phandle cell. The clock ID is directly mapped to the
@@ -77,6 +77,18 @@ ID   Clock           Peripheral
 28     xor1            XOR 1
 30     sata1           SATA 1
 
+The following is a list of provided IDs for Armada 39x:
+ID     Clock           Peripheral
+-----------------------------------
+5      pex1            PCIe 1
+6      pex2            PCIe 2
+7      pex3            PCIe 3
+8      pex0            PCIe 0
+9      usb3h0          USB3 Host 0
+17     sdio            SDIO
+22     xor0            XOR 0
+28     xor1            XOR 1
+
 The following is a list of provided IDs for Armada XP:
 ID     Clock   Peripheral
 -----------------------------------
@@ -152,6 +164,7 @@ Required properties:
        "marvell,armada-370-gating-clock" - for Armada 370 SoC clock gating
        "marvell,armada-375-gating-clock" - for Armada 375 SoC clock gating
        "marvell,armada-380-gating-clock" - for Armada 380/385 SoC clock gating
+       "marvell,armada-390-gating-clock" - for Armada 39x SoC clock gating
        "marvell,armada-xp-gating-clock" - for Armada XP SoC clock gating
        "marvell,dove-gating-clock" - for Dove SoC clock gating
        "marvell,kirkwood-gating-clock" - for Kirkwood SoC clock gating
diff --git a/Documentation/devicetree/bindings/clock/pwm-clock.txt b/Documentation/devicetree/bindings/clock/pwm-clock.txt
new file mode 100644 (file)
index 0000000..83db876
--- /dev/null
@@ -0,0 +1,26 @@
+Binding for an external clock signal driven by a PWM pin.
+
+This binding uses the common clock binding[1] and the common PWM binding[2].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Documentation/devicetree/bindings/pwm/pwm.txt
+
+Required properties:
+- compatible : shall be "pwm-clock".
+- #clock-cells : from common clock binding; shall be set to 0.
+- pwms : from common PWM binding; this determines the clock frequency
+  via the period given in the PWM specifier.
+
+Optional properties:
+- clock-output-names : From common clock binding.
+- clock-frequency : Exact output frequency, in case the PWM period
+  is not exact but was rounded to nanoseconds.
+
+Example:
+       clock {
+               compatible = "pwm-clock";
+               #clock-cells = <0>;
+               clock-frequency = <25000000>;
+               clock-output-names = "mipi_mclk";
+               pwms = <&pwm2 0 40>; /* 1 / 40 ns = 25 MHz */
+       };
index aba3d254e037902b540e0801c2294656a08d22b6..54c23f34f194608c34c01f1ecb6ae9be58e11704 100644 (file)
@@ -8,6 +8,7 @@ Required properties :
                        "qcom,gcc-apq8084"
                        "qcom,gcc-ipq8064"
                        "qcom,gcc-msm8660"
+                       "qcom,gcc-msm8916"
                        "qcom,gcc-msm8960"
                        "qcom,gcc-msm8974"
                        "qcom,gcc-msm8974pro"
diff --git a/Documentation/devicetree/bindings/clock/renesas,r8a7778-cpg-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,r8a7778-cpg-clocks.txt
new file mode 100644 (file)
index 0000000..2f3747f
--- /dev/null
@@ -0,0 +1,25 @@
+* Renesas R8A7778 Clock Pulse Generator (CPG)
+
+The CPG generates core clocks for the R8A7778. It includes two PLLs and
+several fixed ratio dividers
+
+Required Properties:
+
+  - compatible: Must be "renesas,r8a7778-cpg-clocks"
+  - reg: Base address and length of the memory resource used by the CPG
+  - #clock-cells: Must be 1
+  - clock-output-names: The names of the clocks. Supported clocks are
+    "plla", "pllb", "b", "out", "p", "s", and "s1".
+
+
+Example
+-------
+
+       cpg_clocks: cpg_clocks@ffc80000 {
+               compatible = "renesas,r8a7778-cpg-clocks";
+               reg = <0xffc80000 0x80>;
+               #clock-cells = <1>;
+               clocks = <&extal_clk>;
+               clock-output-names = "plla", "pllb", "b",
+                                    "out", "p", "s", "s1";
+       };
index 60b44285250d3b3e9e580f9d71e51239df3b1c76..4fa11af3d378ef281e43717490c012263b901122 100644 (file)
@@ -20,6 +20,7 @@ Required properties:
        "allwinner,sun8i-a23-axi-clk" - for the AXI clock on A23
        "allwinner,sun4i-a10-axi-gates-clk" - for the AXI gates
        "allwinner,sun4i-a10-ahb-clk" - for the AHB clock
+       "allwinner,sun5i-a13-ahb-clk" - for the AHB clock on A13
        "allwinner,sun9i-a80-ahb-clk" - for the AHB bus clocks on A80
        "allwinner,sun4i-a10-ahb-gates-clk" - for the AHB gates on A10
        "allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13
@@ -66,6 +67,8 @@ Required properties:
        "allwinner,sun4i-a10-usb-clk" - for usb gates + resets on A10 / A20
        "allwinner,sun5i-a13-usb-clk" - for usb gates + resets on A13
        "allwinner,sun6i-a31-usb-clk" - for usb gates + resets on A31
+       "allwinner,sun9i-a80-usb-mod-clk" - for usb gates + resets on A80
+       "allwinner,sun9i-a80-usb-phy-clk" - for usb phy gates + resets on A80
 
 Required properties for all clocks:
 - reg : shall be the control register address for the clock.
diff --git a/Documentation/devicetree/bindings/common-properties.txt b/Documentation/devicetree/bindings/common-properties.txt
new file mode 100644 (file)
index 0000000..3193979
--- /dev/null
@@ -0,0 +1,60 @@
+Common properties
+
+The ePAPR specification does not define any properties related to hardware
+byteswapping, but endianness issues show up frequently in porting Linux to
+different machine types.  This document attempts to provide a consistent
+way of handling byteswapping across drivers.
+
+Optional properties:
+ - big-endian: Boolean; force big endian register accesses
+   unconditionally (e.g. ioread32be/iowrite32be).  Use this if you
+   know the peripheral always needs to be accessed in BE mode.
+ - little-endian: Boolean; force little endian register accesses
+   unconditionally (e.g. readl/writel).  Use this if you know the
+   peripheral always needs to be accessed in LE mode.
+ - native-endian: Boolean; always use register accesses matched to the
+   endianness of the kernel binary (e.g. LE vmlinux -> readl/writel,
+   BE vmlinux -> ioread32be/iowrite32be).  In this case no byteswaps
+   will ever be performed.  Use this if the hardware "self-adjusts"
+   register endianness based on the CPU's configured endianness.
+
+If a binding supports these properties, then the binding should also
+specify the default behavior if none of these properties are present.
+In such cases, little-endian is the preferred default, but it is not
+a requirement.  The of_device_is_big_endian() and of_fdt_is_big_endian()
+helper functions do assume that little-endian is the default, because
+most existing (PCI-based) drivers implicitly default to LE by using
+readl/writel for MMIO accesses.
+
+Examples:
+Scenario 1 : CPU in LE mode & device in LE mode.
+dev: dev@40031000 {
+             compatible = "name";
+             reg = <0x40031000 0x1000>;
+             ...
+             native-endian;
+};
+
+Scenario 2 : CPU in LE mode & device in BE mode.
+dev: dev@40031000 {
+             compatible = "name";
+             reg = <0x40031000 0x1000>;
+             ...
+             big-endian;
+};
+
+Scenario 3 : CPU in BE mode & device in BE mode.
+dev: dev@40031000 {
+             compatible = "name";
+             reg = <0x40031000 0x1000>;
+             ...
+             native-endian;
+};
+
+Scenario 4 : CPU in BE mode & device in LE mode.
+dev: dev@40031000 {
+             compatible = "name";
+             reg = <0x40031000 0x1000>;
+             ...
+             little-endian;
+};
diff --git a/Documentation/devicetree/bindings/cris/axis.txt b/Documentation/devicetree/bindings/cris/axis.txt
new file mode 100644 (file)
index 0000000..d209ca2
--- /dev/null
@@ -0,0 +1,9 @@
+Axis Communications AB
+ARTPEC series SoC Device Tree Bindings
+
+
+CRISv32 based SoCs are ETRAX FS and ARTPEC-3:
+
+    - compatible = "axis,crisv32";
+
+
diff --git a/Documentation/devicetree/bindings/cris/boards.txt b/Documentation/devicetree/bindings/cris/boards.txt
new file mode 100644 (file)
index 0000000..533dd27
--- /dev/null
@@ -0,0 +1,8 @@
+Boards based on the CRIS SoCs:
+
+Required root node properties:
+    - compatible = should be one or more of the following:
+       - "axis,dev88"  - for Axis devboard 88 with ETRAX FS
+
+Optional:
+
diff --git a/Documentation/devicetree/bindings/cris/interrupts.txt b/Documentation/devicetree/bindings/cris/interrupts.txt
new file mode 100644 (file)
index 0000000..e8b123b
--- /dev/null
@@ -0,0 +1,23 @@
+* CRISv32 Interrupt Controller
+
+Interrupt controller for the CRISv32 SoCs.
+
+Main node required properties:
+
+- compatible : should be:
+       "axis,crisv32-intc"
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source. The type shall be a <u32> and the value shall be 1.
+- reg: physical base address and size of the intc registers map.
+
+Example:
+
+       intc: interrupt-controller {
+               compatible = "axis,crisv32-intc";
+               reg = <0xb001c000 0x1000>;
+               interrupt-controller;
+               #interrupt-cells = <1>;
+       };
+
+
diff --git a/Documentation/devicetree/bindings/dma/apm-xgene-dma.txt b/Documentation/devicetree/bindings/dma/apm-xgene-dma.txt
new file mode 100644 (file)
index 0000000..d305876
--- /dev/null
@@ -0,0 +1,47 @@
+Applied Micro X-Gene SoC DMA nodes
+
+DMA nodes are defined to describe on-chip DMA interfaces in
+APM X-Gene SoC.
+
+Required properties for DMA interfaces:
+- compatible: Should be "apm,xgene-dma".
+- device_type: set to "dma".
+- reg: Address and length of the register set for the device.
+  It contains the information of registers in the following order:
+  1st - DMA control and status register address space.
+  2nd - Descriptor ring control and status register address space.
+  3rd - Descriptor ring command register address space.
+  4th - Soc efuse register address space.
+- interrupts: DMA has 5 interrupts sources. 1st interrupt is
+  DMA error reporting interrupt. 2nd, 3rd, 4th and 5th interrupts
+  are completion interrupts for each DMA channels.
+- clocks: Reference to the clock entry.
+
+Optional properties:
+- dma-coherent : Present if dma operations are coherent
+
+Example:
+       dmaclk: dmaclk@1f27c000 {
+               compatible = "apm,xgene-device-clock";
+               #clock-cells = <1>;
+               clocks = <&socplldiv2 0>;
+               reg = <0x0 0x1f27c000 0x0 0x1000>;
+               reg-names = "csr-reg";
+               clock-output-names = "dmaclk";
+       };
+
+       dma: dma@1f270000 {
+                       compatible = "apm,xgene-storm-dma";
+                       device_type = "dma";
+                       reg = <0x0 0x1f270000 0x0 0x10000>,
+                             <0x0 0x1f200000 0x0 0x10000>,
+                             <0x0 0x1b008000 0x0 0x2000>,
+                             <0x0 0x1054a000 0x0 0x100>;
+                       interrupts = <0x0 0x82 0x4>,
+                                    <0x0 0xb8 0x4>,
+                                    <0x0 0xb9 0x4>,
+                                    <0x0 0xba 0x4>,
+                                    <0x0 0xbb 0x4>;
+                       dma-coherent;
+                       clocks = <&dmaclk 0>;
+       };
diff --git a/Documentation/devicetree/bindings/dma/jz4780-dma.txt b/Documentation/devicetree/bindings/dma/jz4780-dma.txt
new file mode 100644 (file)
index 0000000..f25feee
--- /dev/null
@@ -0,0 +1,56 @@
+* Ingenic JZ4780 DMA Controller
+
+Required properties:
+
+- compatible: Should be "ingenic,jz4780-dma"
+- reg: Should contain the DMA controller registers location and length.
+- interrupts: Should contain the interrupt specifier of the DMA controller.
+- interrupt-parent: Should be the phandle of the interrupt controller that
+- clocks: Should contain a clock specifier for the JZ4780 PDMA clock.
+- #dma-cells: Must be <2>. Number of integer cells in the dmas property of
+  DMA clients (see below).
+
+Optional properties:
+
+- ingenic,reserved-channels: Bitmask of channels to reserve for devices that
+  need a specific channel. These channels will only be assigned when explicitly
+  requested by a client. The primary use for this is channels 0 and 1, which
+  can be configured to have special behaviour for NAND/BCH when using
+  programmable firmware.
+
+Example:
+
+dma: dma@13420000 {
+       compatible = "ingenic,jz4780-dma";
+       reg = <0x13420000 0x10000>;
+
+       interrupt-parent = <&intc>;
+       interrupts = <10>;
+
+       clocks = <&cgu JZ4780_CLK_PDMA>;
+
+       #dma-cells = <2>;
+
+       ingenic,reserved-channels = <0x3>;
+};
+
+DMA clients must use the format described in dma.txt, giving a phandle to the
+DMA controller plus the following 2 integer cells:
+
+1. Request type: The DMA request type for transfers to/from the device on
+   the allocated channel, as defined in the SoC documentation.
+
+2. Channel: If set to 0xffffffff, any available channel will be allocated for
+   the client. Otherwise, the exact channel specified will be used. The channel
+   should be reserved on the DMA controller using the ingenic,reserved-channels
+   property.
+
+Example:
+
+uart0: serial@10030000 {
+       ...
+       dmas = <&dma 0x14 0xffffffff
+               &dma 0x15 0xffffffff>;
+       dma-names = "tx", "rx";
+       ...
+};
index f8c3311b7153e76619e8e5e47434b07898705ec6..1c9d48ea49148c20d8f3eae564e45a06d6c9c2f2 100644 (file)
@@ -4,6 +4,7 @@ Required properties:
 - compatible: must be one of the following:
  * "qcom,bam-v1.4.0" for MSM8974, APQ8074 and APQ8084
  * "qcom,bam-v1.3.0" for APQ8064, IPQ8064 and MSM8960
+ * "qcom,bam-v1.7.0" for MSM8916
 - reg: Address range for DMA registers
 - interrupts: Should contain the one interrupt shared by all channels
 - #dma-cells: must be <1>, the cell in the dmas property of the client device
diff --git a/Documentation/devicetree/bindings/dma/rcar-audmapp.txt b/Documentation/devicetree/bindings/dma/rcar-audmapp.txt
deleted file mode 100644 (file)
index 61bca50..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-* R-Car Audio DMAC peri peri Device Tree bindings
-
-Required properties:
-- compatible:  should be "renesas,rcar-audmapp"
-- #dma-cells:  should be <1>, see "dmas" property below
-
-Example:
-       audmapp: audio-dma-pp@0xec740000 {
-               compatible = "renesas,rcar-audmapp";
-               #dma-cells = <1>;
-
-               reg = <0 0xec740000 0 0x200>;
-       };
-
-
-* DMA client
-
-Required properties:
-- dmas:                a list of <[DMA multiplexer phandle] [SRS << 8 | DRS]> pairs.
-               where SRS/DRS are specified in the SoC manual.
-               It will be written into PDMACHCR as high 16-bit parts.
-- dma-names:   a list of DMA channel names, one per "dmas" entry
-
-Example:
-
-       dmas = <&audmapp 0x2d00
-               &audmapp 0x3700>;
-       dma-names =  "src0_ssiu0",
-                    "dvc0_ssiu0";
diff --git a/Documentation/devicetree/bindings/dma/renesas,usb-dmac.txt b/Documentation/devicetree/bindings/dma/renesas,usb-dmac.txt
new file mode 100644 (file)
index 0000000..040f365
--- /dev/null
@@ -0,0 +1,37 @@
+* Renesas USB DMA Controller Device Tree bindings
+
+Required Properties:
+- compatible: must contain "renesas,usb-dmac"
+- reg: base address and length of the registers block for the DMAC
+- interrupts: interrupt specifiers for the DMAC, one for each entry in
+  interrupt-names.
+- interrupt-names: one entry per channel, named "ch%u", where %u is the
+  channel number ranging from zero to the number of channels minus one.
+- clocks: a list of phandle + clock-specifier pairs.
+- #dma-cells: must be <1>, the cell specifies the channel number of the DMAC
+  port connected to the DMA client.
+- dma-channels: number of DMA channels
+
+Example: R8A7790 (R-Car H2) USB-DMACs
+
+       usb_dmac0: dma-controller@e65a0000 {
+               compatible = "renesas,usb-dmac";
+               reg = <0 0xe65a0000 0 0x100>;
+               interrupts = <0 109 IRQ_TYPE_LEVEL_HIGH
+                             0 109 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "ch0", "ch1";
+               clocks = <&mstp3_clks R8A7790_CLK_USBDMAC0>;
+               #dma-cells = <1>;
+               dma-channels = <2>;
+       };
+
+       usb_dmac1: dma-controller@e65b0000 {
+               compatible = "renesas,usb-dmac";
+               reg = <0 0xe65b0000 0 0x100>;
+               interrupts = <0 110 IRQ_TYPE_LEVEL_HIGH
+                             0 110 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "ch0", "ch1";
+               clocks = <&mstp3_clks R8A7790_CLK_USBDMAC1>;
+               #dma-cells = <1>;
+               dma-channels = <2>;
+       };
diff --git a/Documentation/devicetree/bindings/extcon/extcon-usb-gpio.txt b/Documentation/devicetree/bindings/extcon/extcon-usb-gpio.txt
new file mode 100644 (file)
index 0000000..af0b903
--- /dev/null
@@ -0,0 +1,18 @@
+USB GPIO Extcon device
+
+This is a virtual device used to generate USB cable states from the USB ID pin
+connected to a GPIO pin.
+
+Required properties:
+- compatible: Should be "linux,extcon-usb-gpio"
+- id-gpio: gpio for USB ID pin. See gpio binding.
+
+Example: Examples of extcon-usb-gpio node in dra7-evm.dts as listed below:
+       extcon_usb1 {
+               compatible = "linux,extcon-usb-gpio";
+               id-gpio = <&gpio6 1 GPIO_ACTIVE_HIGH>;
+       }
+
+       &omap_dwc3_1 {
+               extcon = <&extcon_usb1>;
+       };
index 003bd77b4595f515bd35a5ad6f9419f50abf8579..ad0c4ac916dd75ed0b7eb07e28b3c62e60f3d725 100644 (file)
@@ -77,6 +77,7 @@ nxp,pca9556           Octal SMBus and I2C registered interface
 nxp,pca9557            8-bit I2C-bus and SMBus I/O port with reset
 nxp,pcf8563            Real-time clock/calendar
 nxp,pcf85063           Tiny Real-Time Clock
+oki,ml86v7667          OKI ML86V7667 video decoder
 ovti,ov5642            OV5642: Color CMOS QSXGA (5-megapixel) Image Sensor with OmniBSI and Embedded TrueFocus
 pericom,pt7c4338       Real-time Clock Module
 plx,pex8648            48-Lane, 12-Port PCI Express Gen 2 (5.0 GT/s) Switch
index bf52ed4a5067de5c9d825f77865321112ec5a651..4ef45636ebdedd538bef484a94705b720aceda66 100644 (file)
@@ -4,7 +4,7 @@ Required properties:
 
 - compatible   : should be one of:
                  "samsung,s5pv210-jpeg", "samsung,exynos4210-jpeg",
-                 "samsung,exynos3250-jpeg";
+                 "samsung,exynos3250-jpeg", "samsung,exynos5420-jpeg";
 - reg          : address and length of the JPEG codec IP register set;
 - interrupts   : specifies the JPEG codec IP interrupt;
 - clock-names   : should contain:
diff --git a/Documentation/devicetree/bindings/media/i2c/mt9v032.txt b/Documentation/devicetree/bindings/media/i2c/mt9v032.txt
new file mode 100644 (file)
index 0000000..2025653
--- /dev/null
@@ -0,0 +1,39 @@
+* Aptina 1/3-Inch WVGA CMOS Digital Image Sensor
+
+The Aptina MT9V032 is a 1/3-inch CMOS active pixel digital image sensor with
+an active array size of 752H x 480V. It is programmable through a simple
+two-wire serial interface.
+
+Required Properties:
+
+- compatible: value should be either one among the following
+       (a) "aptina,mt9v022" for MT9V022 color sensor
+       (b) "aptina,mt9v022m" for MT9V022 monochrome sensor
+       (c) "aptina,mt9v024" for MT9V024 color sensor
+       (d) "aptina,mt9v024m" for MT9V024 monochrome sensor
+       (e) "aptina,mt9v032" for MT9V032 color sensor
+       (f) "aptina,mt9v032m" for MT9V032 monochrome sensor
+       (g) "aptina,mt9v034" for MT9V034 color sensor
+       (h) "aptina,mt9v034m" for MT9V034 monochrome sensor
+
+Optional Properties:
+
+- link-frequencies: List of allowed link frequencies in Hz. Each frequency is
+       expressed as a 64-bit big-endian integer.
+
+For further reading on port node refer to
+Documentation/devicetree/bindings/media/video-interfaces.txt.
+
+Example:
+
+       mt9v032@5c {
+               compatible = "aptina,mt9v032";
+               reg = <0x5c>;
+
+               port {
+                       mt9v032_out: endpoint {
+                               link-frequencies = /bits/ 64
+                                       <13000000 26600000 27000000>;
+                       };
+               };
+       };
diff --git a/Documentation/devicetree/bindings/media/i2c/ov2640.txt b/Documentation/devicetree/bindings/media/i2c/ov2640.txt
new file mode 100644 (file)
index 0000000..c429b5b
--- /dev/null
@@ -0,0 +1,46 @@
+* Omnivision OV2640 CMOS sensor
+
+The Omnivision OV2640 sensor support multiple resolutions output, such as
+CIF, SVGA, UXGA. It also can support YUV422/420, RGB565/555 or raw RGB
+output format.
+
+Required Properties:
+- compatible: should be "ovti,ov2640"
+- clocks: reference to the xvclk input clock.
+- clock-names: should be "xvclk".
+
+Optional Properties:
+- resetb-gpios: reference to the GPIO connected to the resetb pin, if any.
+- pwdn-gpios: reference to the GPIO connected to the pwdn pin, if any.
+
+The device node must contain one 'port' child node for its digital output
+video port, in accordance with the video interface bindings defined in
+Documentation/devicetree/bindings/media/video-interfaces.txt.
+
+Example:
+
+       i2c1: i2c@f0018000 {
+               ov2640: camera@0x30 {
+                       compatible = "ovti,ov2640";
+                       reg = <0x30>;
+
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_pck1 &pinctrl_ov2640_pwdn &pinctrl_ov2640_resetb>;
+
+                       resetb-gpios = <&pioE 24 GPIO_ACTIVE_LOW>;
+                       pwdn-gpios = <&pioE 29 GPIO_ACTIVE_HIGH>;
+
+                       clocks = <&pck1>;
+                       clock-names = "xvclk";
+
+                       assigned-clocks = <&pck1>;
+                       assigned-clock-rates = <25000000>;
+
+                       port {
+                               ov2640_0: endpoint {
+                                       remote-endpoint = <&isi_0>;
+                                       bus-width = <8>;
+                               };
+                       };
+               };
+       };
diff --git a/Documentation/devicetree/bindings/media/i2c/ov2659.txt b/Documentation/devicetree/bindings/media/i2c/ov2659.txt
new file mode 100644 (file)
index 0000000..cabc7d8
--- /dev/null
@@ -0,0 +1,38 @@
+* OV2659 1/5-Inch 2Mp SOC Camera
+
+The Omnivision OV2659 is a 1/5-inch SOC camera, with an active array size of
+1632H x 1212V. It is programmable through a SCCB. The OV2659 sensor supports
+multiple resolutions output, such as UXGA, SVGA, 720p. It also can support
+YUV422, RGB565/555 or raw RGB output formats.
+
+Required Properties:
+- compatible: Must be "ovti,ov2659"
+- reg: I2C slave address
+- clocks: reference to the xvclk input clock.
+- clock-names: should be "xvclk".
+- link-frequencies: target pixel clock frequency.
+
+For further reading on port node refer to
+Documentation/devicetree/bindings/media/video-interfaces.txt.
+
+Example:
+
+       i2c0@1c22000 {
+               ...
+               ...
+                ov2659@30 {
+                       compatible = "ovti,ov2659";
+                       reg = <0x30>;
+
+                       clocks = <&clk_ov2659 0>;
+                       clock-names = "xvclk";
+
+                       port {
+                               ov2659_0: endpoint {
+                                       remote-endpoint = <&vpfe_ep>;
+                                       link-frequencies = /bits/ 64 <70000000>;
+                               };
+                       };
+               };
+               ...
+       };
diff --git a/Documentation/devicetree/bindings/media/ti,omap3isp.txt b/Documentation/devicetree/bindings/media/ti,omap3isp.txt
new file mode 100644 (file)
index 0000000..ac23de8
--- /dev/null
@@ -0,0 +1,71 @@
+OMAP 3 ISP Device Tree bindings
+===============================
+
+The DT definitions can be found in include/dt-bindings/media/omap3-isp.h.
+
+Required properties
+===================
+
+compatible     : must contain "ti,omap3-isp"
+
+reg            : the two registers sets (physical address and length) for the
+                 ISP. The first set contains the core ISP registers up to
+                 the end of the SBL block. The second set contains the
+                 CSI PHYs and receivers registers.
+interrupts     : the ISP interrupt specifier
+iommus         : phandle and IOMMU specifier for the IOMMU that serves the ISP
+syscon         : the phandle and register offset to the Complex I/O or CSI-PHY
+                 register
+ti,phy-type    : 0 -- OMAP3ISP_PHY_TYPE_COMPLEX_IO (e.g. 3430)
+                 1 -- OMAP3ISP_PHY_TYPE_CSIPHY (e.g. 3630)
+#clock-cells   : Must be 1 --- the ISP provides two external clocks,
+                 cam_xclka and cam_xclkb, at indices 0 and 1,
+                 respectively. Please find more information on common
+                 clock bindings in ../clock/clock-bindings.txt.
+
+Port nodes (optional)
+---------------------
+
+More documentation on these bindings is available in
+video-interfaces.txt in the same directory.
+
+reg            : The interface:
+                 0 - parallel (CCDC)
+                 1 - CSIPHY1 -- CSI2C / CCP2B on 3630;
+                     CSI1 -- CSIb on 3430
+                 2 - CSIPHY2 -- CSI2A / CCP2B on 3630;
+                     CSI2 -- CSIa on 3430
+
+Optional properties
+===================
+
+vdd-csiphy1-supply : voltage supply of the CSI-2 PHY 1
+vdd-csiphy2-supply : voltage supply of the CSI-2 PHY 2
+
+Endpoint nodes
+--------------
+
+lane-polarities        : lane polarity (required on CSI-2)
+                 0 -- not inverted; 1 -- inverted
+data-lanes     : an array of data lanes from 1 to 3. The length can
+                 be either 1 or 2. (required on CSI-2)
+clock-lanes    : the clock lane (from 1 to 3). (required on CSI-2)
+
+
+Example
+=======
+
+               isp@480bc000 {
+                       compatible = "ti,omap3-isp";
+                       reg = <0x480bc000 0x12fc
+                              0x480bd800 0x0600>;
+                       interrupts = <24>;
+                       iommus = <&mmu_isp>;
+                       syscon = <&scm_conf 0x2f0>;
+                       ti,phy-type = <OMAP3ISP_PHY_TYPE_CSIPHY>;
+                       #clock-cells = <1>;
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+               };
index 571b4c60665f72939aa7ef956e301ee49c13facc..9cd2a369125d440cb393582c1b7d0f253ef25d06 100644 (file)
@@ -106,6 +106,12 @@ Optional endpoint properties
 - link-frequencies: Allowed data bus frequencies. For MIPI CSI-2, for
   instance, this is the actual frequency of the bus, not bits per clock per
   lane value. An array of 64-bit unsigned integers.
+- lane-polarities: an array of polarities of the lanes starting from the clock
+  lane and followed by the data lanes in the same order as in data-lanes.
+  Valid values are 0 (normal) and 1 (inverted). The length of the array
+  should be the combined length of data-lanes and clock-lanes properties.
+  If the lane-polarities property is omitted, the value must be interpreted
+  as 0 (normal). This property is valid for serial busses only.
 
 
 Example
diff --git a/Documentation/devicetree/bindings/media/xilinx/video.txt b/Documentation/devicetree/bindings/media/xilinx/video.txt
new file mode 100644 (file)
index 0000000..cbd46fa
--- /dev/null
@@ -0,0 +1,35 @@
+DT bindings for Xilinx video IP cores
+-------------------------------------
+
+Xilinx video IP cores process video streams by acting as video sinks and/or
+sources. They are connected by links through their input and output ports,
+creating a video pipeline.
+
+Each video IP core is represented by an AMBA bus child node in the device
+tree using bindings documented in this directory. Connections between the IP
+cores are represented as defined in ../video-interfaces.txt.
+
+The whole  pipeline is represented by an AMBA bus child node in the device
+tree using bindings documented in ./xlnx,video.txt.
+
+Common properties
+-----------------
+
+The following properties are common to all Xilinx video IP cores.
+
+- xlnx,video-format: This property represents a video format transmitted on an
+  AXI bus between video IP cores, using its VF code as defined in "AXI4-Stream
+  Video IP and System Design Guide" [UG934]. How the format relates to the IP
+  core is decribed in the IP core bindings documentation.
+
+- xlnx,video-width: This property qualifies the video format with the sample
+  width expressed as a number of bits per pixel component. All components must
+  use the same width.
+
+- xlnx,cfa-pattern: When the video format is set to Mono/Sensor, this property
+  describes the sensor's color filter array pattern. Supported values are
+  "bggr", "gbrg", "grbg", "rggb" and "mono". If not specified, the pattern
+  defaults to "mono".
+
+
+[UG934] http://www.xilinx.com/support/documentation/ip_documentation/axi_videoip/v1_0/ug934_axi_videoIP.pdf
diff --git a/Documentation/devicetree/bindings/media/xilinx/xlnx,v-tc.txt b/Documentation/devicetree/bindings/media/xilinx/xlnx,v-tc.txt
new file mode 100644 (file)
index 0000000..2aed3b4
--- /dev/null
@@ -0,0 +1,33 @@
+Xilinx Video Timing Controller (VTC)
+------------------------------------
+
+The Video Timing Controller is a general purpose video timing generator and
+detector.
+
+Required properties:
+
+  - compatible: Must be "xlnx,v-tc-6.1".
+
+  - reg: Physical base address and length of the registers set for the device.
+
+  - clocks: Must contain a clock specifier for the VTC core and timing
+    interfaces clock.
+
+Optional properties:
+
+  - xlnx,detector: The VTC has a timing detector
+  - xlnx,generator: The VTC has a timing generator
+
+  At least one of the xlnx,detector and xlnx,generator properties must be
+  specified.
+
+
+Example:
+
+       vtc: vtc@43c40000 {
+               compatible = "xlnx,v-tc-6.1";
+               reg = <0x43c40000 0x10000>;
+
+               clocks = <&clkc 15>;
+               xlnx,generator;
+       };
diff --git a/Documentation/devicetree/bindings/media/xilinx/xlnx,v-tpg.txt b/Documentation/devicetree/bindings/media/xilinx/xlnx,v-tpg.txt
new file mode 100644 (file)
index 0000000..9dd86b3
--- /dev/null
@@ -0,0 +1,71 @@
+Xilinx Video Test Pattern Generator (TPG)
+-----------------------------------------
+
+Required properties:
+
+- compatible: Must contain at least one of
+
+    "xlnx,v-tpg-5.0" (TPG version 5.0)
+    "xlnx,v-tpg-6.0" (TPG version 6.0)
+
+  TPG versions backward-compatible with previous versions should list all
+  compatible versions in the newer to older order.
+
+- reg: Physical base address and length of the registers set for the device.
+
+- clocks: Reference to the video core clock.
+
+- xlnx,video-format, xlnx,video-width: Video format and width, as defined in
+  video.txt.
+
+- port: Video port, using the DT bindings defined in ../video-interfaces.txt.
+  The TPG has a single output port numbered 0.
+
+Optional properties:
+
+- xlnx,vtc: A phandle referencing the Video Timing Controller that generates
+  video timings for the TPG test patterns.
+
+- timing-gpios: Specifier for a GPIO that controls the timing mux at the TPG
+  input. The GPIO active level corresponds to the selection of VTC-generated
+  video timings.
+
+The xlnx,vtc and timing-gpios properties are mandatory when the TPG is
+synthesized with two ports and forbidden when synthesized with one port.
+
+Example:
+
+       tpg_0: tpg@40050000 {
+               compatible = "xlnx,v-tpg-6.0", "xlnx,v-tpg-5.0";
+               reg = <0x40050000 0x10000>;
+               clocks = <&clkc 15>;
+
+               xlnx,vtc = <&vtc_3>;
+               timing-gpios = <&ps7_gpio_0 55 GPIO_ACTIVE_LOW>;
+
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@0 {
+                               reg = <0>;
+
+                               xlnx,video-format = <XVIP_VF_YUV_422>;
+                               xlnx,video-width = <8>;
+
+                               tpg_in: endpoint {
+                                       remote-endpoint = <&adv7611_out>;
+                               };
+                       };
+                       port@1 {
+                               reg = <1>;
+
+                               xlnx,video-format = <XVIP_VF_YUV_422>;
+                               xlnx,video-width = <8>;
+
+                               tpg1_out: endpoint {
+                                       remote-endpoint = <&switch_in0>;
+                               };
+                       }:
+               };
+       };
diff --git a/Documentation/devicetree/bindings/media/xilinx/xlnx,video.txt b/Documentation/devicetree/bindings/media/xilinx/xlnx,video.txt
new file mode 100644 (file)
index 0000000..5a02270
--- /dev/null
@@ -0,0 +1,55 @@
+Xilinx Video IP Pipeline (VIPP)
+-------------------------------
+
+General concept
+---------------
+
+Xilinx video IP pipeline processes video streams through one or more Xilinx
+video IP cores. Each video IP core is represented as documented in video.txt
+and IP core specific documentation, xlnx,v-*.txt, in this directory. The DT
+node of the VIPP represents as a top level node of the pipeline and defines
+mappings between DMAs and the video IP cores.
+
+Required properties:
+
+- compatible: Must be "xlnx,video".
+
+- dmas, dma-names: List of one DMA specifier and identifier string (as defined
+  in Documentation/devicetree/bindings/dma/dma.txt) per port. Each port
+  requires a DMA channel with the identifier string set to "port" followed by
+  the port index.
+
+- ports: Video port, using the DT bindings defined in ../video-interfaces.txt.
+
+Required port properties:
+
+- direction: should be either "input" or "output" depending on the direction
+  of stream.
+
+Example:
+
+       video_cap {
+               compatible = "xlnx,video";
+               dmas = <&vdma_1 1>, <&vdma_3 1>;
+               dma-names = "port0", "port1";
+
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@0 {
+                               reg = <0>;
+                               direction = "input";
+                               vcap0_in0: endpoint {
+                                       remote-endpoint = <&scaler0_out>;
+                               };
+                       };
+                       port@1 {
+                               reg = <1>;
+                               direction = "input";
+                               vcap0_in1: endpoint {
+                                       remote-endpoint = <&switch_out1>;
+                               };
+                       };
+               };
+       };
diff --git a/Documentation/devicetree/bindings/memory-controllers/ingenic,jz4780-nemc.txt b/Documentation/devicetree/bindings/memory-controllers/ingenic,jz4780-nemc.txt
new file mode 100644 (file)
index 0000000..f936b55
--- /dev/null
@@ -0,0 +1,75 @@
+* Ingenic JZ4780 NAND/external memory controller (NEMC)
+
+This file documents the device tree bindings for the NEMC external memory
+controller in Ingenic JZ4780
+
+Required properties:
+- compatible: Should be set to one of:
+    "ingenic,jz4780-nemc" (JZ4780)
+- reg: Should specify the NEMC controller registers location and length.
+- clocks: Clock for the NEMC controller.
+- #address-cells: Must be set to 2.
+- #size-cells: Must be set to 1.
+- ranges: A set of ranges for each bank describing the physical memory layout.
+  Each should specify the following 4 integer values:
+
+    <cs number> 0 <physical address of mapping> <size of mapping>
+
+Each child of the NEMC node describes a device connected to the NEMC.
+
+Required child node properties:
+- reg: Should contain at least one register specifier, given in the following
+  format:
+
+    <cs number> <offset> <size>
+
+  Multiple registers can be specified across multiple banks. This is needed,
+  for example, for packaged NAND devices with multiple dies. Such devices
+  should be grouped into a single node.
+
+Optional child node properties:
+- ingenic,nemc-bus-width: Specifies the bus width in bits. Defaults to 8 bits.
+- ingenic,nemc-tAS: Address setup time in nanoseconds.
+- ingenic,nemc-tAH: Address hold time in nanoseconds.
+- ingenic,nemc-tBP: Burst pitch time in nanoseconds.
+- ingenic,nemc-tAW: Access wait time in nanoseconds.
+- ingenic,nemc-tSTRV: Static memory recovery time in nanoseconds.
+
+If a child node references multiple banks in its "reg" property, the same value
+for all optional parameters will be configured for all banks. If any optional
+parameters are omitted, they will be left unchanged from whatever they are
+configured to when the NEMC device is probed (which may be the reset value as
+given in the hardware reference manual, or a value configured by the boot
+loader).
+
+Example (NEMC node with a NAND child device attached at CS1):
+
+nemc: nemc@13410000 {
+       compatible = "ingenic,jz4780-nemc";
+       reg = <0x13410000 0x10000>;
+
+       #address-cells = <2>;
+       #size-cells = <1>;
+
+       ranges = <1 0 0x1b000000 0x1000000
+                 2 0 0x1a000000 0x1000000
+                 3 0 0x19000000 0x1000000
+                 4 0 0x18000000 0x1000000
+                 5 0 0x17000000 0x1000000
+                 6 0 0x16000000 0x1000000>;
+
+       clocks = <&cgu JZ4780_CLK_NEMC>;
+
+       nand: nand@1 {
+               compatible = "ingenic,jz4780-nand";
+               reg = <1 0 0x1000000>;
+
+               ingenic,nemc-tAS = <10>;
+               ingenic,nemc-tAH = <5>;
+               ingenic,nemc-tBP = <10>;
+               ingenic,nemc-tAW = <15>;
+               ingenic,nemc-tSTRV = <100>;
+
+               ...
+       };
+};
diff --git a/Documentation/devicetree/bindings/mfd/qcom,tcsr.txt b/Documentation/devicetree/bindings/mfd/qcom,tcsr.txt
new file mode 100644 (file)
index 0000000..e90519d
--- /dev/null
@@ -0,0 +1,22 @@
+QCOM Top Control and Status Register
+
+Qualcomm devices have a set of registers that provide various control and status
+functions for their peripherals.  This node is intended to allow access to these
+registers via syscon.
+
+Required properties:
+- compatible:  Should contain:
+               "qcom,tcsr-ipq8064", "syscon" for IPQ8064
+               "qcom,tcsr-apq8064", "syscon" for APQ8064
+               "qcom,tcsr-msm8660", "syscon" for MSM8660
+               "qcom,tcsr-msm8960", "syscon" for MSM8960
+               "qcom,tcsr-msm8974", "syscon" for MSM8974
+               "qcom,tcsr-apq8084", "syscon" for APQ8084
+               "qcom,tcsr-msm8916", "syscon" for MSM8916
+- reg: Address range for TCSR registers
+
+Example:
+       tcsr: syscon@1a400000 {
+               compatible = "qcom,tcsr-msm8960", "syscon";
+               reg = <0x1a400000 0x100>;
+       };
index 6def86f6b053bea992004509bd812c4e56627aed..2a19bff9693fc55a7b61bb45dcf32963bc7f224a 100644 (file)
@@ -46,11 +46,18 @@ Optional properties for all bus drivers:
                                interrupt 2
  - st,wakeup-{x,y,z}-{lo,hi}:  set wakeup condition on x/y/z axis for
                                upper/lower limit
+ - st,wakeup-threshold:                set wakeup threshold
+ - st,wakeup2-{x,y,z}-{lo,hi}: set wakeup condition on x/y/z axis for
+                               upper/lower limit for second wakeup
+                               engine.
+ - st,wakeup2-threshold:       set wakeup threshold for second wakeup
+                               engine.
  - st,highpass-cutoff-hz=:     1, 2, 4 or 8 for 1Hz, 2Hz, 4Hz or 8Hz of
                                highpass cut-off frequency
  - st,hipass{1,2}-disable:     disable highpass 1/2.
  - st,default-rate=:           set the default rate
- - st,axis-{x,y,z}=:           set the axis to map to the three coordinates
+ - st,axis-{x,y,z}=:           set the axis to map to the three coordinates.
+                               Negative values can be used for inverted axis.
  - st,{min,max}-limit-{x,y,z}  set the min/max limits for x/y/z axis
                                (used by self-test)
 
index 4611aa83531b9f6834797baec0dfa7c961c74d0e..f20b111b502a7cfd29e45765bfb25ba3c8bd8f95 100644 (file)
@@ -3,10 +3,13 @@
 Required properties:
 - #address-cells, #size-cells : Must be present if the device has sub-nodes
   representing partitions.
-- compatible : Should be the manufacturer and the name of the chip. Bear in mind
-               the DT binding is not Linux-only, but in case of Linux, see the
-               "spi_nor_ids" table in drivers/mtd/spi-nor/spi-nor.c for the list
-               of supported chips.
+- compatible : May include a device-specific string consisting of the
+               manufacturer and name of the chip. Bear in mind the DT binding
+               is not Linux-only, but in case of Linux, see the "m25p_ids"
+               table in drivers/mtd/devices/m25p80.c for the list of supported
+               chips.
+               Must also include "nor-jedec" for any SPI NOR flash that can be
+               identified by the JEDEC READ ID opcode (0x9F).
 - reg : Chip-Select number
 - spi-max-frequency : Maximum frequency of the SPI bus the chip can operate at
 
@@ -22,7 +25,7 @@ Example:
        flash: m25p80@0 {
                #address-cells = <1>;
                #size-cells = <1>;
-               compatible = "spansion,m25p80";
+               compatible = "spansion,m25p80", "nor-jedec";
                reg = <0>;
                spi-max-frequency = <40000000>;
                m25p,fast-read;
index de8b517a5521914c6c37df4dc6d250abf2ffb742..4f833e3c4f516e90747865fefb7de633e240f6c3 100644 (file)
@@ -14,7 +14,7 @@ Optional properties:
  - marvell,nand-enable-arbiter:        Set to enable the bus arbiter
  - marvell,nand-keep-config:   Set to keep the NAND controller config as set
                                by the bootloader
- - num-cs:                     Number of chipselect lines to usw
+ - num-cs:                     Number of chipselect lines to use
  - nand-on-flash-bbt:          boolean to enable on flash bbt option if
                                not present false
  - nand-ecc-strength:           number of bits to correct per ECC step
index 0273adb8638ca507af4261b922a42ff5344fbc40..086d6f44c4b976b73b364d491fc290a97b00bf61 100644 (file)
@@ -21,7 +21,7 @@ Optional properties:
 - nand-ecc-mode : one of the supported ECC modes ("hw", "hw_syndrome", "soft",
   "soft_bch" or "none")
 
-see Documentation/devicetree/mtd/nand.txt for generic bindings.
+see Documentation/devicetree/bindings/mtd/nand.txt for generic bindings.
 
 
 Examples:
diff --git a/Documentation/devicetree/bindings/net/wireless/ti,wlcore.txt b/Documentation/devicetree/bindings/net/wireless/ti,wlcore.txt
new file mode 100644 (file)
index 0000000..2a3d90d
--- /dev/null
@@ -0,0 +1,47 @@
+TI Wilink 6/7/8 (wl12xx/wl18xx) SDIO devices
+
+This node provides properties for controlling the wilink wireless device. The
+node is expected to be specified as a child node to the SDIO controller that
+connects the device to the system.
+
+Required properties:
+ - compatible: should be one of the following:
+    * "ti,wl1271"
+    * "ti,wl1273"
+    * "ti,wl1281"
+    * "ti,wl1283"
+    * "ti,wl1801"
+    * "ti,wl1805"
+    * "ti,wl1807"
+    * "ti,wl1831"
+    * "ti,wl1835"
+    * "ti,wl1837"
+ - interrupts : specifies attributes for the out-of-band interrupt.
+
+Optional properties:
+ - interrupt-parent : the phandle for the interrupt controller to which the
+       device interrupts are connected.
+ - ref-clock-frequency : ref clock frequency in Hz
+ - tcxo-clock-frequency : tcxo clock frequency in Hz
+
+Note: the *-clock-frequency properties assume internal clocks. In case of external
+clock, new bindings (for parsing the clock nodes) have to be added.
+
+Example:
+
+&mmc3 {
+       status = "okay";
+       vmmc-supply = <&wlan_en_reg>;
+       bus-width = <4>;
+       cap-power-off-card;
+       keep-power-in-suspend;
+
+       #address-cells = <1>;
+       #size-cells = <0>;
+       wlcore: wlcore@2 {
+               compatible = "ti,wl1835";
+               reg = <2>;
+               interrupt-parent = <&gpio0>;
+               interrupts = <19 IRQ_TYPE_LEVEL_HIGH>;
+       };
+};
diff --git a/Documentation/devicetree/bindings/power/fsl,imx-gpc.txt b/Documentation/devicetree/bindings/power/fsl,imx-gpc.txt
new file mode 100644 (file)
index 0000000..65cc034
--- /dev/null
@@ -0,0 +1,59 @@
+Freescale i.MX General Power Controller
+=======================================
+
+The i.MX6Q General Power Control (GPC) block contains DVFS load tracking
+counters and Power Gating Control (PGC) for the CPU and PU (GPU/VPU) power
+domains.
+
+Required properties:
+- compatible: Should be "fsl,imx6q-gpc" or "fsl,imx6sl-gpc"
+- reg: should be register base and length as documented in the
+  datasheet
+- interrupts: Should contain GPC interrupt request 1
+- pu-supply: Link to the LDO regulator powering the PU power domain
+- clocks: Clock phandles to devices in the PU power domain that need
+         to be enabled during domain power-up for reset propagation.
+- #power-domain-cells: Should be 1, see below:
+
+The gpc node is a power-controller as documented by the generic power domain
+bindings in Documentation/devicetree/bindings/power/power_domain.txt.
+
+Example:
+
+       gpc: gpc@020dc000 {
+               compatible = "fsl,imx6q-gpc";
+               reg = <0x020dc000 0x4000>;
+               interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 90 IRQ_TYPE_LEVEL_HIGH>;
+               pu-supply = <&reg_pu>;
+               clocks = <&clks IMX6QDL_CLK_GPU3D_CORE>,
+                        <&clks IMX6QDL_CLK_GPU3D_SHADER>,
+                        <&clks IMX6QDL_CLK_GPU2D_CORE>,
+                        <&clks IMX6QDL_CLK_GPU2D_AXI>,
+                        <&clks IMX6QDL_CLK_OPENVG_AXI>,
+                        <&clks IMX6QDL_CLK_VPU_AXI>;
+               #power-domain-cells = <1>;
+       };
+
+
+Specifying power domain for IP modules
+======================================
+
+IP cores belonging to a power domain should contain a 'power-domains' property
+that is a phandle pointing to the gpc device node and a DOMAIN_INDEX specifying
+the power domain the device belongs to.
+
+Example of a device that is part of the PU power domain:
+
+       vpu: vpu@02040000 {
+               reg = <0x02040000 0x3c000>;
+               /* ... */
+               power-domains = <&gpc 1>;
+               /* ... */
+       };
+
+The following DOMAIN_INDEX values are valid for i.MX6Q:
+ARM_DOMAIN     0
+PU_DOMAIN      1
+The following additional DOMAIN_INDEX value is valid for i.MX6SL:
+DISPLAY_DOMAIN 2
index cc3b1f0a9b1a2b75125a2f98af131ff107f0258b..beda7d2efc304350aa7dc48f2cc6212bfc6ee795 100644 (file)
@@ -11,6 +11,7 @@ Required properties:
 - compatible: Should be "renesas,sysc-<soctype>", "renesas,sysc-rmobile" as
              fallback.
              Examples with soctypes are:
+               - "renesas,sysc-r8a73a4" (R-Mobile APE6)
                - "renesas,sysc-r8a7740" (R-Mobile A1)
                - "renesas,sysc-sh73a0" (SH-Mobile AG5)
 - reg: Two address start and address range blocks for the device:
index b50d7a6d9d7f88ca00524533981c44726e860d3f..e00c2e9f484dceea28c71df05461f0e61336f6ec 100644 (file)
@@ -1,10 +1,17 @@
 Freescale i.MX PWM controller
 
 Required properties:
-- compatible: should be "fsl,<soc>-pwm"
+- compatible : should be "fsl,<soc>-pwm" and one of the following
+   compatible strings:
+  - "fsl,imx1-pwm" for PWM compatible with the one integrated on i.MX1
+  - "fsl,imx27-pwm" for PWM compatible with the one integrated on i.MX27
 - reg: physical base address and length of the controller's registers
 - #pwm-cells: should be 2. See pwm.txt in this directory for a description of
   the cells format.
+- clocks : Clock specifiers for both ipg and per clocks.
+- clock-names : Clock names should include both "ipg" and "per"
+See the clock consumer binding,
+       Documentation/devicetree/bindings/clock/clock-bindings.txt
 - interrupts: The interrupt for the pwm controller
 
 Example:
@@ -13,5 +20,8 @@ pwm1: pwm@53fb4000 {
        #pwm-cells = <2>;
        compatible = "fsl,imx53-pwm", "fsl,imx27-pwm";
        reg = <0x53fb4000 0x4000>;
+       clocks = <&clks IMX5_CLK_PWM1_IPG_GATE>,
+                <&clks IMX5_CLK_PWM1_HF_GATE>;
+       clock-names = "ipg", "per";
        interrupts = <61>;
 };
diff --git a/Documentation/devicetree/bindings/rtc/abracon,abx80x.txt b/Documentation/devicetree/bindings/rtc/abracon,abx80x.txt
new file mode 100644 (file)
index 0000000..be78968
--- /dev/null
@@ -0,0 +1,30 @@
+Abracon ABX80X I2C ultra low power RTC/Alarm chip
+
+The Abracon ABX80X family consist of the ab0801, ab0803, ab0804, ab0805, ab1801,
+ab1803, ab1804 and ab1805. The ab0805 is the superset of ab080x and the ab1805
+is the superset of ab180x.
+
+Required properties:
+
+ - "compatible": should one of:
+        "abracon,abx80x"
+        "abracon,ab0801"
+        "abracon,ab0803"
+        "abracon,ab0804"
+        "abracon,ab0805"
+        "abracon,ab1801"
+        "abracon,ab1803"
+        "abracon,ab1804"
+        "abracon,ab1805"
+       Using "abracon,abx80x" will enable chip autodetection.
+ - "reg": I2C bus address of the device
+
+Optional properties:
+
+The abx804 and abx805 have a trickle charger that is able to charge the
+connected battery or supercap. Both the following properties have to be defined
+and valid to enable charging:
+
+ - "abracon,tc-diode": should be "standard" (0.6V) or "schottky" (0.3V)
+ - "abracon,tc-resistor": should be <0>, <3>, <6> or <11>. 0 disables the output
+                          resistor, the other values are in ohm.
index a6391e70a8fd84086b8982a6e3844f59dfb20949..90787aa2e648c55a91df5a71b9b10d7f4f7ae7c7 100644 (file)
@@ -1,9 +1,10 @@
 * Atmel Universal Synchronous Asynchronous Receiver/Transmitter (USART)
 
 Required properties:
-- compatible: Should be "atmel,<chip>-usart"
+- compatible: Should be "atmel,<chip>-usart" or "atmel,<chip>-dbgu"
   The compatible <chip> indicated will be the first SoC to support an
   additional mode or an USART new feature.
+  For the dbgu UART, use "atmel,<chip>-dbgu", "atmel,<chip>-usart"
 - reg: Should contain registers location and length
 - interrupts: Should contain interrupt
 - clock-names: tuple listing input clock names.
index 342eedd1005021f28c34696e1f80b96a4c620d5e..54c2a155c78323a70f9dc66eb62457eba1143232 100644 (file)
@@ -4,7 +4,27 @@ Required properties:
 - compatible : should be "ti,omap2-uart" for OMAP2 controllers
 - compatible : should be "ti,omap3-uart" for OMAP3 controllers
 - compatible : should be "ti,omap4-uart" for OMAP4 controllers
+- reg : address and length of the register space
+- interrupts or interrupts-extended : Should contain the uart interrupt
+                                      specifier or both the interrupt
+                                      controller phandle and interrupt
+                                      specifier.
 - ti,hwmods : Must be "uart<n>", n being the instance number (1-based)
 
 Optional properties:
 - clock-frequency : frequency of the clock input to the UART
+- dmas : DMA specifier, consisting of a phandle to the DMA controller
+         node and a DMA channel number.
+- dma-names : "rx" for receive channel, "tx" for transmit channel.
+
+Example:
+
+                uart4: serial@49042000 {
+                        compatible = "ti,omap3-uart";
+                        reg = <0x49042000 0x400>;
+                        interrupts = <80>;
+                        dmas = <&sdma 81 &sdma 82>;
+                        dma-names = "tx", "rx";
+                        ti,hwmods = "uart4";
+                        clock-frequency = <48000000>;
+                };
diff --git a/Documentation/devicetree/bindings/soc/mediatek/pwrap.txt b/Documentation/devicetree/bindings/soc/mediatek/pwrap.txt
new file mode 100644 (file)
index 0000000..ddeb5b6
--- /dev/null
@@ -0,0 +1,58 @@
+MediaTek PMIC Wrapper Driver
+
+This document describes the binding for the MediaTek PMIC wrapper.
+
+On MediaTek SoCs the PMIC is connected via SPI. The SPI master interface
+is not directly visible to the CPU, but only through the PMIC wrapper
+inside the SoC. The communication between the SoC and the PMIC can
+optionally be encrypted. Also a non standard Dual IO SPI mode can be
+used to increase speed.
+
+IP Pairing
+
+on MT8135 the pins of some SoC internal peripherals can be on the PMIC.
+The signals of these pins are routed over the SPI bus using the pwrap
+bridge. In the binding description below the properties needed for bridging
+are marked with "IP Pairing". These are optional on SoCs which do not support
+IP Pairing
+
+Required properties in pwrap device node.
+- compatible:
+       "mediatek,mt8135-pwrap" for MT8135 SoCs
+       "mediatek,mt8173-pwrap" for MT8173 SoCs
+- interrupts: IRQ for pwrap in SOC
+- reg-names: Must include the following entries:
+  "pwrap": Main registers base
+  "pwrap-bridge": bridge base (IP Pairing)
+- reg: Must contain an entry for each entry in reg-names.
+- reset-names: Must include the following entries:
+  "pwrap"
+  "pwrap-bridge" (IP Pairing)
+- resets: Must contain an entry for each entry in reset-names.
+- clock-names: Must include the following entries:
+  "spi": SPI bus clock
+  "wrap": Main module clock
+- clocks: Must contain an entry for each entry in clock-names.
+
+Optional properities:
+- pmic: Mediatek PMIC MFD is the child device of pwrap
+  See the following for child node definitions:
+  Documentation/devicetree/bindings/mfd/mt6397.txt
+
+Example:
+       pwrap: pwrap@1000f000 {
+               compatible = "mediatek,mt8135-pwrap";
+               reg = <0 0x1000f000 0 0x1000>,
+                       <0 0x11017000 0 0x1000>;
+               reg-names = "pwrap", "pwrap-bridge";
+               interrupts = <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>;
+               resets = <&infracfg MT8135_INFRA_PMIC_WRAP_RST>,
+                               <&pericfg MT8135_PERI_PWRAP_BRIDGE_SW_RST>;
+               reset-names = "pwrap", "pwrap-bridge";
+               clocks = <&clk26m>, <&clk26m>;
+               clock-names = "spi", "wrap";
+
+               pmic {
+                       compatible = "mediatek,mt6397";
+               };
+       };
index 4ce24d425bf18a42daa14d529165f506e4e3f224..2f5ede39bea2d1d3cffacbcbe0ed103a7d2c708a 100644 (file)
@@ -6,7 +6,8 @@ configuration settings.  The mode setting will govern the input/output mode of
 the 4 GSBI IOs.
 
 Required properties:
-- compatible: must contain "qcom,gsbi-v1.0.0" for APQ8064/IPQ8064
+- compatible:  Should contain "qcom,gsbi-v1.0.0"
+- cell-index:  Should contain the GSBI index
 - reg: Address range for GSBI registers
 - clocks: required clock
 - clock-names: must contain "iface" entry
@@ -16,6 +17,8 @@ Required properties:
 Optional properties:
 - qcom,crci : indicates CRCI MUX value for QUP CRCI ports.  Please reference
   dt-bindings/soc/qcom,gsbi.h for valid CRCI mux values.
+- syscon-tcsr: indicates phandle of TCSR syscon node.  Required if child uses
+  dma.
 
 Required properties if child node exists:
 - #address-cells: Must be 1
@@ -39,6 +42,7 @@ Example for APQ8064:
 
        gsbi4@16300000 {
                compatible = "qcom,gsbi-v1.0.0";
+               cell-index = <4>;
                reg = <0x16300000 0x100>;
                clocks = <&gcc GSBI4_H_CLK>;
                clock-names = "iface";
@@ -48,22 +52,24 @@ Example for APQ8064:
                qcom,mode = <GSBI_PROT_I2C_UART>;
                qcom,crci = <GSBI_CRCI_QUP>;
 
+               syscon-tcsr = <&tcsr>;
+
                /* child nodes go under here */
 
                i2c_qup4: i2c@16380000 {
-                       compatible = "qcom,i2c-qup-v1.1.1";
-                       reg = <0x16380000 0x1000>;
-                       interrupts = <0 153 0>;
+                       compatible = "qcom,i2c-qup-v1.1.1";
+                       reg = <0x16380000 0x1000>;
+                       interrupts = <0 153 0>;
 
-                       clocks = <&gcc GSBI4_QUP_CLK>, <&gcc GSBI4_H_CLK>;
-                       clock-names = "core", "iface";
+                       clocks = <&gcc GSBI4_QUP_CLK>, <&gcc GSBI4_H_CLK>;
+                       clock-names = "core", "iface";
 
-                       clock-frequency = <200000>;
+                       clock-frequency = <200000>;
 
-                       #address-cells = <1>;
-                       #size-cells = <0>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
 
-                };
+               };
 
                uart4:  serial@16340000 {
                        compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
@@ -76,3 +82,7 @@ Example for APQ8064:
                };
        };
 
+       tcsr: syscon@1a400000 {
+               compatible = "qcom,apq8064-tcsr", "syscon";
+               reg = <0x1a400000 0x100>;
+       };
index 1ab6bc8404d5bc850dea1fc1533f451b03787e5f..f6a715e4ef43c1e0d7b5402188dbf310795e9caa 100644 (file)
@@ -4,9 +4,9 @@ Required properties:
 - compatible: "ti,omap-twl4030"
 - ti,model: Name of the sound card (for example "omap3beagle")
 - ti,mcbsp: phandle for the McBSP node
-- ti,codec: phandle for the twl4030 audio node
 
 Optional properties:
+- ti,codec: phandle for the twl4030 audio node
 - ti,mcbsp-voice: phandle for the McBSP node connected to the voice port of twl
 - ti, jack-det-gpio: Jack detect GPIO
 - ti,audio-routing: List of connections between audio components.
@@ -59,5 +59,4 @@ sound {
        ti,model = "omap3beagle";
 
        ti,mcbsp = <&mcbsp2>;
-       ti,codec = <&twl_audio>;
 };
index 715d0998af8e2fbce29e16ea7cbc96e391aa6bf2..e16b9b5afc70a139087dea1ca3a64e9989525112 100644 (file)
@@ -1,6 +1,6 @@
 Qualcomm SPMI Controller (PMIC Arbiter)
 
-The SPMI PMIC Arbiter is found on the Snapdragon 800 Series.  It is an SPMI
+The SPMI PMIC Arbiter is found on Snapdragon chipsets.  It is an SPMI
 controller with wrapping arbitration logic to allow for multiple on-chip
 devices to control a single SPMI master.
 
@@ -19,6 +19,10 @@ Required properties:
      "core" - core registers
      "intr" - interrupt controller registers
      "cnfg" - configuration registers
+   Registers used only for V2 PMIC Arbiter:
+     "chnls"  - tx-channel per virtual slave registers.
+     "obsrvr" - rx-channel (called observer) per virtual slave registers.
+
 - reg : address + size pairs describing the PMIC arb register sets; order must
         correspond with the order of entries in reg-names
 - #address-cells : must be set to 2
index 4f8edb205e130a6b53375b23df03a07f45bd2363..80339192c93e2626f81eed30fe97ff147c86d746 100644 (file)
@@ -11,6 +11,7 @@ adapteva      Adapteva, Inc.
 adh    AD Holdings Plc.
 adi    Analog Devices, Inc.
 aeroflexgaisler        Aeroflex Gaisler AB
+al     Annapurna Labs
 allwinner      Allwinner Technology Co., Ltd.
 alphascale     AlphaScale Integrated Circuits Systems, Inc.
 altr   Altera Corp.
@@ -21,9 +22,11 @@ ampire       Ampire Co., Ltd.
 ams    AMS AG
 amstaos        AMS-Taos Inc.
 apm    Applied Micro Circuits Corporation (APM)
+aptina Aptina Imaging
 arasan Arasan Chip Systems
 arm    ARM Ltd.
 armadeus       ARMadeus Systems SARL
+artesyn        Artesyn Embedded Technologies Inc.
 asahi-kasei    Asahi Kasei Corp.
 atmel  Atmel Corporation
 auo    AU Optronics Corporation
@@ -82,6 +85,7 @@ globalscale   Globalscale Technologies, Inc.
 gmt    Global Mixed-mode Technology, Inc.
 goodix Shenzhen Huiding Technology Co., Ltd.
 google Google, Inc.
+grinn  Grinn
 gumstix        Gumstix, Inc.
 gw     Gateworks Corporation
 hannstar       HannStar Display Corporation
@@ -117,6 +121,7 @@ merrii      Merrii Technology Co., Ltd.
 micrel Micrel Inc.
 microchip      Microchip Technology Inc.
 micron Micron Technology Inc.
+minix  MINIX Technology Ltd.
 mitsubishi     Mitsubishi Electric Corporation
 mosaixtech     Mosaix Technologies, Inc.
 moxa   Moxa
index f059dd0b3d286c3adc1e2b42571a2d48de4b641b..ecb8da063d07b82350060ff3ce8f3af9df35a549 100644 (file)
@@ -10,7 +10,9 @@ Required properties:
        "atmel,at91sam9g45es-lcdc" ,
        "atmel,at91sam9rl-lcdc" ,
        "atmel,at32ap-lcdc"
-- reg : Should contain 1 register ranges(address and length)
+- reg : Should contain 1 register ranges(address and length).
+       Can contain an additional register range(address and length)
+       for fixed framebuffer memory. Useful for dedicated memories.
 - interrupts : framebuffer controller interrupt
 - display: a phandle pointing to the display node
 
@@ -38,6 +40,14 @@ Example:
 
        };
 
+Example for fixed framebuffer memory:
+
+       fb0: fb@0x00500000 {
+               compatible = "atmel,at91sam9263-lcdc";
+               reg = <0x00700000 0x1000 0x70000000 0x200000>;
+               [...]
+       };
+
 Atmel LCDC Display
 -----------------------------------------------------
 Required properties (as per of_videomode_helper):
index bb9753b635a3a5e8d8f794814a83584878b550e5..480c8de3c2c44786174e112795f61b2381d3b09f 100644 (file)
@@ -49,25 +49,26 @@ The dma_buf buffer sharing API usage contains the following steps:
    The buffer exporter announces its wish to export a buffer. In this, it
    connects its own private buffer data, provides implementation for operations
    that can be performed on the exported dma_buf, and flags for the file
-   associated with this buffer.
+   associated with this buffer. All these fields are filled in struct
+   dma_buf_export_info, defined via the DEFINE_DMA_BUF_EXPORT_INFO macro.
 
    Interface:
-      struct dma_buf *dma_buf_export_named(void *priv, struct dma_buf_ops *ops,
-                                    size_t size, int flags,
-                                    const char *exp_name)
+      DEFINE_DMA_BUF_EXPORT_INFO(exp_info)
+      struct dma_buf *dma_buf_export(struct dma_buf_export_info *exp_info)
 
-   If this succeeds, dma_buf_export_named allocates a dma_buf structure, and
+   If this succeeds, dma_buf_export allocates a dma_buf structure, and
    returns a pointer to the same. It also associates an anonymous file with this
    buffer, so it can be exported. On failure to allocate the dma_buf object,
    it returns NULL.
 
-   'exp_name' is the name of exporter - to facilitate information while
-   debugging.
+   'exp_name' in struct dma_buf_export_info is the name of exporter - to
+   facilitate information while debugging. It is set to KBUILD_MODNAME by
+   default, so exporters don't have to provide a specific name, if they don't
+   wish to.
+
+   DEFINE_DMA_BUF_EXPORT_INFO macro defines the struct dma_buf_export_info,
+   zeroes it out and pre-populates exp_name in it.
 
-   Exporting modules which do not wish to provide any specific name may use the
-   helper define 'dma_buf_export()', with the same arguments as above, but
-   without the last argument; a KBUILD_MODNAME pre-processor directive will be
-   inserted in place of 'exp_name' instead.
 
 2. Userspace gets a handle to pass around to potential buffer-users
 
index e1e2bbd7a40404344adb1c46697cfb47dd47f9ee..831a5363f6be37756b0016c1c30fc0f46055aff8 100644 (file)
@@ -276,6 +276,7 @@ IOMAP
   devm_ioport_unmap()
   devm_ioremap()
   devm_ioremap_nocache()
+  devm_ioremap_wc()
   devm_ioremap_resource() : checks resource, requests memory region, ioremaps
   devm_iounmap()
   pcim_iomap()
index 724043858b0834f874aff57df4155f1da3dffad8..95c13aa575ff32eebeb4938f435376ca0595a439 100644 (file)
@@ -187,8 +187,10 @@ Check RDMA and NFS Setup
     To further test the InfiniBand software stack, use IPoIB (this
     assumes you have two IB hosts named host1 and host2):
 
-    host1$ ifconfig ib0 a.b.c.x
-    host2$ ifconfig ib0 a.b.c.y
+    host1$ ip link set dev ib0 up
+    host1$ ip address add dev ib0 a.b.c.x
+    host2$ ip link set dev ib0 up
+    host2$ ip address add dev ib0 a.b.c.y
     host1$ ping a.b.c.y
     host2$ ping a.b.c.x
 
@@ -229,7 +231,8 @@ NFS/RDMA Setup
 
     $ modprobe ib_mthca
     $ modprobe ib_ipoib
-    $ ifconfig ib0 a.b.c.d
+    $ ip li set dev ib0 up
+    $ ip addr add dev ib0 a.b.c.d
 
     NOTE: use unique addresses for the client and server
 
index 0bfafe10835772be298d5a3859a1ee31de861f83..5a5a05582b583c42468764fc5a80bf8c126072e6 100644 (file)
@@ -228,30 +228,19 @@ default behaviour.
 Deprecated Mount Options
 ========================
 
-  delaylog/nodelaylog
-       Delayed logging is the only logging method that XFS supports
-       now, so these mount options are now ignored.
-
-       Due for removal in 3.12.
-
-  ihashsize=value
-       In memory inode hashes have been removed, so this option has
-       no function as of August 2007. Option is deprecated.
-
-       Due for removal in 3.12.
+None at present.
 
-  irixsgid
-       This behaviour is now controlled by a sysctl, so the mount
-       option is ignored.
 
-       Due for removal in 3.12.
+Removed Mount Options
+=====================
 
-  osyncisdsync
-  osyncisosync
-       O_SYNC and O_DSYNC are fully supported, so there is no need
-       for these options any more.
+  Name                         Removed
+  ----                         -------
+  delaylog/nodelaylog          v3.20
+  ihashsize                    v3.20
+  irixsgid                     v3.20
+  osyncisdsync/osyncisosync    v3.20
 
-       Due for removal in 3.12.
 
 sysctls
 =======
index b9d229fee6b95b7d4836b9781c6b5650cb013435..c86f2f1ae4f6aa2d9af3e3987e8be06fd237dbef 100644 (file)
@@ -94,6 +94,10 @@ PS/2 packet format
 
 Note that the device never signals overflow condition.
 
+For protocol version 2 devices when the trackpoint is used, and no fingers
+are on the touchpad, the M R L bits signal the combined status of both the
+pointingstick and touchpad buttons.
+
 ALPS Absolute Mode - Protocol Version 1
 --------------------------------------
 
@@ -107,7 +111,7 @@ ALPS Absolute Mode - Protocol Version 1
 ALPS Absolute Mode - Protocol Version 2
 ---------------------------------------
 
- byte 0:  1    ?    ?    ?    1    ?    ?    ?
+ byte 0:  1    ?    ?    ?    1  PSM  PSR  PSL
  byte 1:  0   x6   x5   x4   x3   x2   x1   x0
  byte 2:  0  x10   x9   x8   x7    ?  fin  ges
  byte 3:  0   y9   y8   y7    1    M    R    L
@@ -115,7 +119,8 @@ ALPS Absolute Mode - Protocol Version 2
  byte 5:  0   z6   z5   z4   z3   z2   z1   z0
 
 Protocol Version 2 DualPoint devices send standard PS/2 mouse packets for
-the DualPoint Stick.
+the DualPoint Stick. For non interleaved dualpoint devices the pointingstick
+buttons get reported separately in the PSM, PSR and PSL bits.
 
 Dualpoint device -- interleaved packet format
 ---------------------------------------------
index 8136e1fd30fdede7141d70bc00f5c6b8097ed981..51f4221657bff5b03c9a8ef44116d6e27ef27423 100644 (file)
@@ -321,6 +321,7 @@ Code  Seq#(hex)     Include File            Comments
 0xDB   00-0F   drivers/char/mwave/mwavepub.h
 0xDD   00-3F   ZFCP device driver      see drivers/s390/scsi/
                                        <mailto:aherrman@de.ibm.com>
+0xEC   00-01   drivers/platform/chrome/cros_ec_dev.h   ChromeOS EC driver
 0xF3   00-3F   drivers/usb/misc/sisusbvga/sisusb.h     sisfb (in development)
                                        <mailto:thomas@winischhofer.net>
 0xF4   00-1F   video/mbxfb.h           mbxfb
index 092fc10961fede482be1f7983e72db0e6c8ec3a8..4692241789b1f608ebc2535ddef1a07722a3fb19 100644 (file)
@@ -9,7 +9,9 @@ a fast and comprehensive solution for finding use-after-free and out-of-bounds
 bugs.
 
 KASan uses compile-time instrumentation for checking every memory access,
-therefore you will need a certain version of GCC > 4.9.2
+therefore you will need a gcc version of 4.9.2 or later. KASan could detect out
+of bounds accesses to stack or global variables, but only if gcc 5.0 or later was
+used to built the kernel.
 
 Currently KASan is supported only for x86_64 architecture and requires that the
 kernel be built with the SLUB allocator.
@@ -23,8 +25,8 @@ To enable KASAN configure kernel with:
 
 and choose between CONFIG_KASAN_OUTLINE and CONFIG_KASAN_INLINE. Outline/inline
 is compiler instrumentation types. The former produces smaller binary the
-latter is 1.1 - 2 times faster. Inline instrumentation requires GCC 5.0 or
-latter.
+latter is 1.1 - 2 times faster. Inline instrumentation requires a gcc version
+of 5.0 or later.
 
 Currently KASAN works only with the SLUB memory allocator.
 For better bug detection and nicer report, enable CONFIG_STACKTRACE and put
index 274252f205b7073ad909d19e2628e466b6b76c0e..61ab1628a057cc2c4d8b11d892d834f7e5f7773a 100644 (file)
@@ -165,7 +165,7 @@ multipliers 'Kilo', 'Mega', and 'Giga', equalling 2^10, 2^20, and 2^30
 bytes respectively. Such letter suffixes can also be entirely omitted.
 
 
-       acpi=           [HW,ACPI,X86]
+       acpi=           [HW,ACPI,X86,ARM64]
                        Advanced Configuration and Power Interface
                        Format: { force | off | strict | noirq | rsdt }
                        force -- enable ACPI if default was off
@@ -175,6 +175,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                                strictly ACPI specification compliant.
                        rsdt -- prefer RSDT over (default) XSDT
                        copy_dsdt -- copy DSDT to memory
+                       For ARM64, ONLY "acpi=off" or "acpi=force" are available
 
                        See also Documentation/power/runtime_pm.txt, pci=noacpi
 
@@ -713,10 +714,18 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 
                uart[8250],io,<addr>[,options]
                uart[8250],mmio,<addr>[,options]
+               uart[8250],mmio32,<addr>[,options]
+               uart[8250],0x<addr>[,options]
                        Start an early, polled-mode console on the 8250/16550
                        UART at the specified I/O port or MMIO address,
-                       switching to the matching ttyS device later.  The
-                       options are the same as for ttyS, above.
+                       switching to the matching ttyS device later.
+                       MMIO inter-register address stride is either 8-bit
+                       (mmio) or 32-bit (mmio32).
+                       If none of [io|mmio|mmio32], <addr> is assumed to be
+                       equivalent to 'mmio'. 'options' are specified in the
+                       same format described for ttyS above; if unspecified,
+                       the h/w is not re-initialized.
+
                hvc<n>  Use the hypervisor console device <n>. This is for
                        both Xen and PowerPC hypervisors.
 
@@ -950,11 +959,15 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                uart[8250],io,<addr>[,options]
                uart[8250],mmio,<addr>[,options]
                uart[8250],mmio32,<addr>[,options]
+               uart[8250],0x<addr>[,options]
                        Start an early, polled-mode console on the 8250/16550
                        UART at the specified I/O port or MMIO address.
                        MMIO inter-register address stride is either 8-bit
                        (mmio) or 32-bit (mmio32).
-                       The options are the same as for ttyS, above.
+                       If none of [io|mmio|mmio32], <addr> is assumed to be
+                       equivalent to 'mmio'. 'options' are specified in the
+                       same format described for "console=ttyS<n>"; if
+                       unspecified, the h/w is not initialized.
 
                pl011,<addr>
                        Start an early, polled-mode console on a pl011 serial
@@ -3774,6 +3787,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                                        READ_CAPACITY_16 command);
                                f = NO_REPORT_OPCODES (don't use report opcodes
                                        command, uas only);
+                               g = MAX_SECTORS_240 (don't transfer more than
+                                       240 sectors at a time, uas only);
                                h = CAPACITY_HEURISTICS (decrease the
                                        reported device capacity by one
                                        sector if the number is odd);
index fc04c14de4bbc3705e14eddb97a214ca8a7f6331..72a150d8f3dfa58975a7ed05d0371e475e059e5b 100644 (file)
@@ -1355,6 +1355,24 @@ Sysfs notes:
        rfkill controller switch "tpacpi_uwb_sw": refer to
        Documentation/rfkill.txt for details.
 
+Adaptive keyboard
+-----------------
+
+sysfs device attribute: adaptive_kbd_mode
+
+This sysfs attribute controls the keyboard "face" that will be shown on the
+Lenovo X1 Carbon 2nd gen (2014)'s adaptive keyboard. The value can be read
+and set.
+
+1 = Home mode
+2 = Web-browser mode
+3 = Web-conference mode
+4 = Function mode
+5 = Layflat mode
+
+For more details about which buttons will appear depending on the mode, please
+review the laptop's user guide:
+http://www.lenovo.com/shop/americas/content/user_guides/x1carbon_2_ug_en.pdf
 
 Multiple Commands, Module Parameters
 ------------------------------------
diff --git a/Documentation/md-cluster.txt b/Documentation/md-cluster.txt
new file mode 100644 (file)
index 0000000..de1af7d
--- /dev/null
@@ -0,0 +1,176 @@
+The cluster MD is a shared-device RAID for a cluster.
+
+
+1. On-disk format
+
+Separate write-intent-bitmap are used for each cluster node.
+The bitmaps record all writes that may have been started on that node,
+and may not yet have finished. The on-disk layout is:
+
+0                    4k                     8k                    12k
+-------------------------------------------------------------------
+| idle                | md super            | bm super [0] + bits |
+| bm bits[0, contd]   | bm super[1] + bits  | bm bits[1, contd]   |
+| bm super[2] + bits  | bm bits [2, contd]  | bm super[3] + bits  |
+| bm bits [3, contd]  |                     |                     |
+
+During "normal" functioning we assume the filesystem ensures that only one
+node writes to any given block at a time, so a write
+request will
+ - set the appropriate bit (if not already set)
+ - commit the write to all mirrors
+ - schedule the bit to be cleared after a timeout.
+
+Reads are just handled normally.  It is up to the filesystem to
+ensure one node doesn't read from a location where another node (or the same
+node) is writing.
+
+
+2. DLM Locks for management
+
+There are two locks for managing the device:
+
+2.1 Bitmap lock resource (bm_lockres)
+
+ The bm_lockres protects individual node bitmaps. They are named in the
+ form bitmap001 for node 1, bitmap002 for node and so on. When a node
+ joins the cluster, it acquires the lock in PW mode and it stays so
+ during the lifetime the node is part of the cluster. The lock resource
+ number is based on the slot number returned by the DLM subsystem. Since
+ DLM starts node count from one and bitmap slots start from zero, one is
+ subtracted from the DLM slot number to arrive at the bitmap slot number.
+
+3. Communication
+
+Each node has to communicate with other nodes when starting or ending
+resync, and metadata superblock updates.
+
+3.1 Message Types
+
+ There are 3 types, of messages which are passed
+
+ 3.1.1 METADATA_UPDATED: informs other nodes that the metadata has been
+   updated, and the node must re-read the md superblock. This is performed
+   synchronously.
+
+ 3.1.2 RESYNC: informs other nodes that a resync is initiated or ended
+   so that each node may suspend or resume the region.
+
+3.2 Communication mechanism
+
+ The DLM LVB is used to communicate within nodes of the cluster. There
+ are three resources used for the purpose:
+
+  3.2.1 Token: The resource which protects the entire communication
+   system. The node having the token resource is allowed to
+   communicate.
+
+  3.2.2 Message: The lock resource which carries the data to
+   communicate.
+
+  3.2.3 Ack: The resource, acquiring which means the message has been
+   acknowledged by all nodes in the cluster. The BAST of the resource
+   is used to inform the receive node that a node wants to communicate.
+
+The algorithm is:
+
+ 1. receive status
+
+   sender                         receiver                   receiver
+   ACK:CR                          ACK:CR                     ACK:CR
+
+ 2. sender get EX of TOKEN
+    sender get EX of MESSAGE
+    sender                        receiver                 receiver
+    TOKEN:EX                       ACK:CR                   ACK:CR
+    MESSAGE:EX
+    ACK:CR
+
+    Sender checks that it still needs to send a message. Messages received
+    or other events that happened while waiting for the TOKEN may have made
+    this message inappropriate or redundant.
+
+ 3. sender write LVB.
+    sender down-convert MESSAGE from EX to CR
+    sender try to get EX of ACK
+    [ wait until all receiver has *processed* the MESSAGE ]
+
+                                     [ triggered by bast of ACK ]
+                                     receiver get CR of MESSAGE
+                                     receiver read LVB
+                                     receiver processes the message
+                                     [ wait finish ]
+                                     receiver release ACK
+
+   sender                         receiver                   receiver
+   TOKEN:EX                       MESSAGE:CR                 MESSAGE:CR
+   MESSAGE:CR
+   ACK:EX
+
+ 4. triggered by grant of EX on ACK (indicating all receivers have processed
+    message)
+    sender down-convert ACK from EX to CR
+    sender release MESSAGE
+    sender release TOKEN
+                               receiver upconvert to EX of MESSAGE
+                               receiver get CR of ACK
+                               receiver release MESSAGE
+
+   sender                      receiver                   receiver
+   ACK:CR                       ACK:CR                     ACK:CR
+
+
+4. Handling Failures
+
+4.1 Node Failure
+ When a node fails, the DLM informs the cluster with the slot. The node
+ starts a cluster recovery thread. The cluster recovery thread:
+       - acquires the bitmap<number> lock of the failed node
+       - opens the bitmap
+       - reads the bitmap of the failed node
+       - copies the set bitmap to local node
+       - cleans the bitmap of the failed node
+       - releases bitmap<number> lock of the failed node
+       - initiates resync of the bitmap on the current node
+
+ The resync process, is the regular md resync. However, in a clustered
+ environment when a resync is performed, it needs to tell other nodes
+ of the areas which are suspended. Before a resync starts, the node
+ send out RESYNC_START with the (lo,hi) range of the area which needs
+ to be suspended. Each node maintains a suspend_list, which contains
+ the list  of ranges which are currently suspended. On receiving
+ RESYNC_START, the node adds the range to the suspend_list. Similarly,
+ when the node performing resync finishes, it send RESYNC_FINISHED
+ to other nodes and other nodes remove the corresponding entry from
+ the suspend_list.
+
+ A helper function, should_suspend() can be used to check if a particular
+ I/O range should be suspended or not.
+
+4.2 Device Failure
+ Device failures are handled and communicated with the metadata update
+ routine.
+
+5. Adding a new Device
+For adding a new device, it is necessary that all nodes "see" the new device
+to be added. For this, the following algorithm is used:
+
+    1. Node 1 issues mdadm --manage /dev/mdX --add /dev/sdYY which issues
+       ioctl(ADD_NEW_DISC with disc.state set to MD_DISK_CLUSTER_ADD)
+    2. Node 1 sends NEWDISK with uuid and slot number
+    3. Other nodes issue kobject_uevent_env with uuid and slot number
+       (Steps 4,5 could be a udev rule)
+    4. In userspace, the node searches for the disk, perhaps
+       using blkid -t SUB_UUID=""
+    5. Other nodes issue either of the following depending on whether the disk
+       was found:
+       ioctl(ADD_NEW_DISK with disc.state set to MD_DISK_CANDIDATE and
+                disc.number set to slot number)
+       ioctl(CLUSTERED_DISK_NACK)
+    6. Other nodes drop lock on no-new-devs (CR) if device is found
+    7. Node 1 attempts EX lock on no-new-devs
+    8. If node 1 gets the lock, it sends METADATA_UPDATED after unmarking the disk
+       as SpareLocal
+    9. If not (get no-new-dev lock), it fails the operation and sends METADATA_UPDATED
+    10. Other nodes get the information whether a disk is added or not
+       by the following METADATA_UPDATED.
index 09c2382ad0556b196a3b4bb941b9e86597e8ebc5..c72702ec1ded8b0b5d728e6cd0519a5862d2d3c7 100644 (file)
@@ -119,9 +119,9 @@ Most notably, in the x509.genkey file, the req_distinguished_name section
 should be altered from the default:
 
        [ req_distinguished_name ]
-       O = Magrathea
-       CN = Glacier signing key
-       emailAddress = slartibartfast@magrathea.h2g2
+       #O = Unspecified company
+       CN = Build time autogenerated kernel key
+       #emailAddress = unspecified.user@unspecified.company
 
 The generated RSA key size can also be set with:
 
index 639ddf0ece9b5fdd20bcc858c3067d4e20407163..9ed15f86c17c86ffa69fa3527e932b62f4b9ee20 100644 (file)
@@ -18,3 +18,12 @@ platform_labels - INTEGER
 
        Possible values: 0 - 1048575
        Default: 0
+
+conf/<interface>/input - BOOL
+       Control whether packets can be input on this interface.
+
+       If disabled, packets will be discarded without further
+       processing.
+
+       0 - disabled (default)
+       not 0 - enabled
index cbfac0949635c1d109930b051e6c4d96dc4c74d1..59f4db2a0c85c02df4f6cee3176ceb173333cac1 100644 (file)
@@ -282,7 +282,7 @@ following is true:
 
 - The current CPU's queue head counter >= the recorded tail counter
   value in rps_dev_flow[i]
-- The current CPU is unset (equal to RPS_NO_CPU)
+- The current CPU is unset (>= nr_cpu_ids)
 - The current CPU is offline
 
 After this check, the packet is sent to the (possibly updated) current
index ba0a2a4a54ba1ffcb484786381b91f5113a62ad6..ded69794a5c09da762db7c4c61cc3d23e619d0fa 100644 (file)
@@ -74,23 +74,22 @@ Causes of transaction aborts
 Syscalls
 ========
 
-Syscalls made from within an active transaction will not be performed and the
-transaction will be doomed by the kernel with the failure code TM_CAUSE_SYSCALL
-| TM_CAUSE_PERSISTENT.
+Performing syscalls from within transaction is not recommended, and can lead
+to unpredictable results.
 
-Syscalls made from within a suspended transaction are performed as normal and
-the transaction is not explicitly doomed by the kernel.  However, what the
-kernel does to perform the syscall may result in the transaction being doomed
-by the hardware.  The syscall is performed in suspended mode so any side
-effects will be persistent, independent of transaction success or failure.  No
-guarantees are provided by the kernel about which syscalls will affect
-transaction success.
+Syscalls do not by design abort transactions, but beware: The kernel code will
+not be running in transactional state.  The effect of syscalls will always
+remain visible, but depending on the call they may abort your transaction as a
+side-effect, read soon-to-be-aborted transactional data that should not remain
+invisible, etc.  If you constantly retry a transaction that constantly aborts
+itself by calling a syscall, you'll have a livelock & make no progress.
 
-Care must be taken when relying on syscalls to abort during active transactions
-if the calls are made via a library.  Libraries may cache values (which may
-give the appearance of success) or perform operations that cause transaction
-failure before entering the kernel (which may produce different failure codes).
-Examples are glibc's getpid() and lazy symbol resolution.
+Simple syscalls (e.g. sigprocmask()) "could" be OK.  Even things like write()
+from, say, printf() should be OK as long as the kernel does not access any
+memory that was accessed transactionally.
+
+Consider any syscalls that happen to work as debug-only -- not recommended for
+production use.  Best to queue them up till after the transaction is over.
 
 
 Signals
@@ -177,7 +176,8 @@ kernel aborted a transaction:
  TM_CAUSE_RESCHED       Thread was rescheduled.
  TM_CAUSE_TLBI          Software TLB invalid.
  TM_CAUSE_FAC_UNAV      FP/VEC/VSX unavailable trap.
- TM_CAUSE_SYSCALL       Syscall from active transaction.
+ TM_CAUSE_SYSCALL       Currently unused; future syscalls that must abort
+                        transactions for consistency will use this.
  TM_CAUSE_SIGNAL        Signal delivered.
  TM_CAUSE_MISC          Currently unused.
  TM_CAUSE_ALIGNMENT     Alignment fault.
index 2b47704f75cb3bfedf836cf02c75afd82c91e405..2ba71cea01723cf3216ef4e95708789b6e0cc9f2 100755 (executable)
@@ -237,8 +237,7 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
        buf += "#include \"" + fabric_mod_name + "_base.h\"\n"
        buf += "#include \"" + fabric_mod_name + "_fabric.h\"\n\n"
 
-       buf += "/* Local pointer to allocated TCM configfs fabric module */\n"
-       buf += "struct target_fabric_configfs *" + fabric_mod_name + "_fabric_configfs;\n\n"
+       buf += "static const struct target_core_fabric_ops " + fabric_mod_name + "_ops;\n\n"
 
        buf += "static struct se_node_acl *" + fabric_mod_name + "_make_nodeacl(\n"
        buf += "        struct se_portal_group *se_tpg,\n"
@@ -309,8 +308,8 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
        buf += "        }\n"
        buf += "        tpg->" + fabric_mod_port + " = " + fabric_mod_port + ";\n"
        buf += "        tpg->" + fabric_mod_port + "_tpgt = tpgt;\n\n"
-       buf += "        ret = core_tpg_register(&" + fabric_mod_name + "_fabric_configfs->tf_ops, wwn,\n"
-       buf += "                                &tpg->se_tpg, (void *)tpg,\n"
+       buf += "        ret = core_tpg_register(&" + fabric_mod_name + "_ops, wwn,\n"
+       buf += "                                &tpg->se_tpg, tpg,\n"
        buf += "                                TRANSPORT_TPG_TYPE_NORMAL);\n"
        buf += "        if (ret < 0) {\n"
        buf += "                kfree(tpg);\n"
@@ -370,7 +369,10 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
        buf += "        NULL,\n"
        buf += "};\n\n"
 
-       buf += "static struct target_core_fabric_ops " + fabric_mod_name + "_ops = {\n"
+       buf += "static const struct target_core_fabric_ops " + fabric_mod_name + "_ops = {\n"
+       buf += "        .module                         = THIS_MODULE,\n"
+       buf += "        .name                           = " + fabric_mod_name + ",\n"
+       buf += "        .get_fabric_proto_ident         = " + fabric_mod_name + "_get_fabric_proto_ident,\n"
        buf += "        .get_fabric_name                = " + fabric_mod_name + "_get_fabric_name,\n"
        buf += "        .get_fabric_proto_ident         = " + fabric_mod_name + "_get_fabric_proto_ident,\n"
        buf += "        .tpg_get_wwn                    = " + fabric_mod_name + "_get_fabric_wwn,\n"
@@ -413,75 +415,18 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
        buf += "        .fabric_drop_np                 = NULL,\n"
        buf += "        .fabric_make_nodeacl            = " + fabric_mod_name + "_make_nodeacl,\n"
        buf += "        .fabric_drop_nodeacl            = " + fabric_mod_name + "_drop_nodeacl,\n"
-       buf += "};\n\n"
-
-       buf += "static int " + fabric_mod_name + "_register_configfs(void)\n"
-       buf += "{\n"
-       buf += "        struct target_fabric_configfs *fabric;\n"
-       buf += "        int ret;\n\n"
-       buf += "        printk(KERN_INFO \"" + fabric_mod_name.upper() + " fabric module %s on %s/%s\"\n"
-       buf += "                \" on \"UTS_RELEASE\"\\n\"," + fabric_mod_name.upper() + "_VERSION, utsname()->sysname,\n"
-       buf += "                utsname()->machine);\n"
-       buf += "        /*\n"
-       buf += "         * Register the top level struct config_item_type with TCM core\n"
-       buf += "         */\n"
-       buf += "        fabric = target_fabric_configfs_init(THIS_MODULE, \"" + fabric_mod_name + "\");\n"
-       buf += "        if (IS_ERR(fabric)) {\n"
-       buf += "                printk(KERN_ERR \"target_fabric_configfs_init() failed\\n\");\n"
-       buf += "                return PTR_ERR(fabric);\n"
-       buf += "        }\n"
-       buf += "        /*\n"
-       buf += "         * Setup fabric->tf_ops from our local " + fabric_mod_name + "_ops\n"
-       buf += "         */\n"
-       buf += "        fabric->tf_ops = " + fabric_mod_name + "_ops;\n"
-       buf += "        /*\n"
-       buf += "         * Setup default attribute lists for various fabric->tf_cit_tmpl\n"
-       buf += "         */\n"
-       buf += "        fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = " + fabric_mod_name + "_wwn_attrs;\n"
-       buf += "        fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = NULL;\n"
-       buf += "        fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = NULL;\n"
-       buf += "        fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL;\n"
-       buf += "        fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;\n"
-       buf += "        fabric->tf_cit_tmpl.tfc_tpg_nacl_base_cit.ct_attrs = NULL;\n"
-       buf += "        fabric->tf_cit_tmpl.tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;\n"
-       buf += "        fabric->tf_cit_tmpl.tfc_tpg_nacl_auth_cit.ct_attrs = NULL;\n"
-       buf += "        fabric->tf_cit_tmpl.tfc_tpg_nacl_param_cit.ct_attrs = NULL;\n"
-       buf += "        /*\n"
-       buf += "         * Register the fabric for use within TCM\n"
-       buf += "         */\n"
-       buf += "        ret = target_fabric_configfs_register(fabric);\n"
-       buf += "        if (ret < 0) {\n"
-       buf += "                printk(KERN_ERR \"target_fabric_configfs_register() failed\"\n"
-       buf += "                                \" for " + fabric_mod_name.upper() + "\\n\");\n"
-       buf += "                return ret;\n"
-       buf += "        }\n"
-       buf += "        /*\n"
-       buf += "         * Setup our local pointer to *fabric\n"
-       buf += "         */\n"
-       buf += "        " + fabric_mod_name + "_fabric_configfs = fabric;\n"
-       buf += "        printk(KERN_INFO \"" +  fabric_mod_name.upper() + "[0] - Set fabric -> " + fabric_mod_name + "_fabric_configfs\\n\");\n"
-       buf += "        return 0;\n"
-       buf += "};\n\n"
-       buf += "static void __exit " + fabric_mod_name + "_deregister_configfs(void)\n"
-       buf += "{\n"
-       buf += "        if (!" + fabric_mod_name + "_fabric_configfs)\n"
-       buf += "                return;\n\n"
-       buf += "        target_fabric_configfs_deregister(" + fabric_mod_name + "_fabric_configfs);\n"
-       buf += "        " + fabric_mod_name + "_fabric_configfs = NULL;\n"
-       buf += "        printk(KERN_INFO \"" +  fabric_mod_name.upper() + "[0] - Cleared " + fabric_mod_name + "_fabric_configfs\\n\");\n"
+       buf += "\n"
+       buf += "        .tfc_wwn_attrs                  = " + fabric_mod_name + "_wwn_attrs;\n"
        buf += "};\n\n"
 
        buf += "static int __init " + fabric_mod_name + "_init(void)\n"
        buf += "{\n"
-       buf += "        int ret;\n\n"
-       buf += "        ret = " + fabric_mod_name + "_register_configfs();\n"
-       buf += "        if (ret < 0)\n"
-       buf += "                return ret;\n\n"
-       buf += "        return 0;\n"
+       buf += "        return target_register_template(" + fabric_mod_name + "_ops);\n"
        buf += "};\n\n"
+
        buf += "static void __exit " + fabric_mod_name + "_exit(void)\n"
        buf += "{\n"
-       buf += "        " + fabric_mod_name + "_deregister_configfs();\n"
+       buf += "        target_unregister_template(" + fabric_mod_name + "_ops);\n"
        buf += "};\n\n"
 
        buf += "MODULE_DESCRIPTION(\"" + fabric_mod_name.upper() + " series fabric driver\");\n"
index 5518465290bf5d64b3ae9b94dd5440ed0a2b97c3..43e94ea6d2cad8d0e17715a7ecf4d1e31b9b9e0e 100644 (file)
@@ -138,27 +138,40 @@ signals the kernel via a 4-byte write(). When cmd_head equals
 cmd_tail, the ring is empty -- no commands are currently waiting to be
 processed by userspace.
 
-TCMU commands start with a common header containing "len_op", a 32-bit
-value that stores the length, as well as the opcode in the lowest
-unused bits. Currently only two opcodes are defined, TCMU_OP_PAD and
-TCMU_OP_CMD. When userspace encounters a command with PAD opcode, it
-should skip ahead by the bytes in "length". (The kernel inserts PAD
-entries to ensure each CMD entry fits contigously into the circular
-buffer.)
-
-When userspace handles a CMD, it finds the SCSI CDB (Command Data
-Block) via tcmu_cmd_entry.req.cdb_off. This is an offset from the
-start of the overall shared memory region, not the entry. The data
-in/out buffers are accessible via tht req.iov[] array. Note that
-each iov.iov_base is also an offset from the start of the region.
-
-TCMU currently does not support BIDI operations.
+TCMU commands are 8-byte aligned. They start with a common header
+containing "len_op", a 32-bit value that stores the length, as well as
+the opcode in the lowest unused bits. It also contains cmd_id and
+flags fields for setting by the kernel (kflags) and userspace
+(uflags).
+
+Currently only two opcodes are defined, TCMU_OP_CMD and TCMU_OP_PAD.
+
+When the opcode is CMD, the entry in the command ring is a struct
+tcmu_cmd_entry. Userspace finds the SCSI CDB (Command Data Block) via
+tcmu_cmd_entry.req.cdb_off. This is an offset from the start of the
+overall shared memory region, not the entry. The data in/out buffers
+are accessible via tht req.iov[] array. iov_cnt contains the number of
+entries in iov[] needed to describe either the Data-In or Data-Out
+buffers. For bidirectional commands, iov_cnt specifies how many iovec
+entries cover the Data-Out area, and iov_bidi_count specifies how many
+iovec entries immediately after that in iov[] cover the Data-In
+area. Just like other fields, iov.iov_base is an offset from the start
+of the region.
 
 When completing a command, userspace sets rsp.scsi_status, and
 rsp.sense_buffer if necessary. Userspace then increments
 mailbox.cmd_tail by entry.hdr.length (mod cmdr_size) and signals the
 kernel via the UIO method, a 4-byte write to the file descriptor.
 
+When the opcode is PAD, userspace only updates cmd_tail as above --
+it's a no-op. (The kernel inserts PAD entries to ensure each CMD entry
+is contiguous within the command ring.)
+
+More opcodes may be added in the future. If userspace encounters an
+opcode it does not handle, it must set UNKNOWN_OP bit (bit 0) in
+hdr.uflags, update cmd_tail, and proceed with processing additional
+commands, if any.
+
 The Data Area:
 
 This is shared-memory space after the command ring. The organization
index 02361552a3eac314a68338c5638f4239ed0d28d7..77d14d51a670a523a14ec9b4581f66d720ba3e76 100644 (file)
@@ -14,7 +14,7 @@ document is concerned with the latter.
 HW assisted tracing is becoming increasingly useful when dealing with systems
 that have many SoCs and other components like GPU and DMA engines.  ARM has
 developed a HW assisted tracing solution by means of different components, each
-being added to a design at systhesis time to cater to specific tracing needs.
+being added to a design at synthesis time to cater to specific tracing needs.
 Compoments are generally categorised as source, link and sinks and are
 (usually) discovered using the AMBA bus.
 
index 0f84ce8c9a7b1389c4c9b34fd9b5f427bdb22c40..5517db602f37b0d3f9a0939832a2494103c422de 100644 (file)
@@ -344,7 +344,9 @@ implement g_volatile_ctrl like this:
        }
 
 Note that you use the 'new value' union as well in g_volatile_ctrl. In general
-controls that need to implement g_volatile_ctrl are read-only controls.
+controls that need to implement g_volatile_ctrl are read-only controls. If they
+are not, a V4L2_EVENT_CTRL_CH_VALUE will not be generated when the control
+changes.
 
 To mark a control as volatile you have to set V4L2_CTRL_FLAG_VOLATILE:
 
index f586e29ce22110cfbe8bfcee63a20cd7ab108547..59e619f9bbf54558f69a97405100d036b09d20d6 100644 (file)
@@ -793,8 +793,8 @@ video_register_device_no_warn() instead.
 
 Whenever a device node is created some attributes are also created for you.
 If you look in /sys/class/video4linux you see the devices. Go into e.g.
-video0 and you will see 'name', 'debug' and 'index' attributes. The 'name'
-attribute is the 'name' field of the video_device struct. The 'debug' attribute
+video0 and you will see 'name', 'dev_debug' and 'index' attributes. The 'name'
+attribute is the 'name' field of the video_device struct. The 'dev_debug' attribute
 can be used to enable core debugging. See the next section for more detailed
 information on this.
 
@@ -821,7 +821,7 @@ unregister the device if the registration failed.
 video device debugging
 ----------------------
 
-The 'debug' attribute that is created for each video, vbi, radio or swradio
+The 'dev_debug' attribute that is created for each video, vbi, radio or swradio
 device in /sys/class/video4linux/<devX>/ allows you to enable logging of
 file operations.
 
index 6cfc8541a362ccb4871259f01c91bdaadb3a8aba..cd4b5a1ac529695964940701b7627396394ac4de 100644 (file)
@@ -912,6 +912,11 @@ looped to the video input provided that:
   sequence and field counting in struct v4l2_buffer on the capture side may not
   be 100% accurate.
 
+- field settings V4L2_FIELD_SEQ_TB/BT are not supported. While it is possible to
+  implement this, it would mean a lot of work to get this right. Since these
+  field values are rarely used the decision was made not to implement this for
+  now.
+
 - on the input side the "Standard Signal Mode" for the S-Video input or the
   "DV Timings Signal Mode" for the HDMI input should be configured so that a
   valid signal is passed to the video input.
index bc9f6fe44e27614c2f26f155385fe0d5d13d2e3b..9fa2bf8c3f6f13282c92c33671b5ad9a3eaa1d0a 100644 (file)
@@ -3573,3 +3573,20 @@ struct {
 @ar   - access register number
 
 KVM handlers should exit to userspace with rc = -EREMOTE.
+
+
+8. Other capabilities.
+----------------------
+
+This section lists capabilities that give information about other
+features of the KVM implementation.
+
+8.1 KVM_CAP_PPC_HWRNG
+
+Architectures: ppc
+
+This capability, if KVM_CHECK_EXTENSION indicates that it is
+available, means that that the kernel has an implementation of the
+H_RANDOM hypercall backed by a hardware random-number generator.
+If present, the kernel H_RANDOM handler can be enabled for guest use
+with the KVM_CAP_PPC_ENABLE_HCALL capability.
index ce3eb0faffe62f9c9ba86663e0ae2b952144d6c4..19395134063dc3eca72e3d0a137d4b96cd61ab91 100644 (file)
@@ -886,6 +886,11 @@ S: Maintained
 F:     drivers/media/rc/meson-ir.c
 N:     meson[x68]
 
+ARM/Annapurna Labs ALPINE ARCHITECTURE
+M:     Tsahee Zidenberg <tsahee@annapurnalabs.com>
+S:     Maintained
+F:     arch/arm/mach-alpine/
+
 ARM/ATMEL AT91RM9200 AND AT91SAM ARM ARCHITECTURES
 M:     Andrew Victor <linux@maxim.org.za>
 M:     Nicolas Ferre <nicolas.ferre@atmel.com>
@@ -958,7 +963,7 @@ ARM/CORESIGHT FRAMEWORK AND DRIVERS
 M:     Mathieu Poirier <mathieu.poirier@linaro.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
-F:     drivers/coresight/*
+F:     drivers/hwtracing/coresight/*
 F:     Documentation/trace/coresight.txt
 F:     Documentation/devicetree/bindings/arm/coresight.txt
 F:     Documentation/ABI/testing/sysfs-bus-coresight-devices-*
@@ -1261,22 +1266,6 @@ L:       openmoko-kernel@lists.openmoko.org (subscribers-only)
 W:     http://wiki.openmoko.org/wiki/Neo_FreeRunner
 S:     Supported
 
-ARM/QUALCOMM MSM MACHINE SUPPORT
-M:     David Brown <davidb@codeaurora.org>
-M:     Daniel Walker <dwalker@fifo99.com>
-M:     Bryan Huntsman <bryanh@codeaurora.org>
-L:     linux-arm-msm@vger.kernel.org
-F:     arch/arm/mach-msm/
-F:     drivers/video/fbdev/msm/
-F:     drivers/mmc/host/msm_sdcc.c
-F:     drivers/mmc/host/msm_sdcc.h
-F:     drivers/tty/serial/msm_serial.h
-F:     drivers/tty/serial/msm_serial.c
-F:     drivers/*/pm8???-*
-F:     drivers/mfd/ssbi.c
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davidb/linux-msm.git
-S:     Maintained
-
 ARM/TOSA MACHINE SUPPORT
 M:     Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
 M:     Dirk Opfer <dirk@opfer-online.de>
@@ -1334,6 +1323,11 @@ L:       linux-soc@vger.kernel.org
 S:     Maintained
 F:     arch/arm/mach-qcom/
 F:     drivers/soc/qcom/
+F:     drivers/tty/serial/msm_serial.h
+F:     drivers/tty/serial/msm_serial.c
+F:     drivers/*/pm8???-*
+F:     drivers/mfd/ssbi.c
+F:     drivers/firmware/qcom_scm.c
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/galak/linux-qcom.git
 
 ARM/RADISYS ENP2611 MACHINE SUPPORT
@@ -1432,11 +1426,9 @@ F:       arch/arm/boot/dts/emev2*
 F:     arch/arm/boot/dts/r7s*
 F:     arch/arm/boot/dts/r8a*
 F:     arch/arm/boot/dts/sh*
-F:     arch/arm/configs/ape6evm_defconfig
 F:     arch/arm/configs/armadillo800eva_defconfig
 F:     arch/arm/configs/bockw_defconfig
 F:     arch/arm/configs/kzm9g_defconfig
-F:     arch/arm/configs/mackerel_defconfig
 F:     arch/arm/configs/marzen_defconfig
 F:     arch/arm/configs/shmobile_defconfig
 F:     arch/arm/include/debug/renesas-scif.S
@@ -1828,7 +1820,7 @@ S:        Supported
 F:     drivers/spi/spi-atmel.*
 
 ATMEL SSC DRIVER
-M:     Bo Shen <voice.shen@atmel.com>
+M:     Nicolas Ferre <nicolas.ferre@atmel.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Supported
 F:     drivers/misc/atmel-ssc.c
@@ -2577,6 +2569,7 @@ F:        include/linux/cleancache.h
 
 CLK API
 M:     Russell King <linux@arm.linux.org.uk>
+L:     linux-clk@vger.kernel.org
 S:     Maintained
 F:     include/linux/clk.h
 
@@ -2637,7 +2630,7 @@ F:        drivers/media/platform/coda/
 COMMON CLK FRAMEWORK
 M:     Mike Turquette <mturquette@linaro.org>
 M:     Stephen Boyd <sboyd@codeaurora.org>
-L:     linux-kernel@vger.kernel.org
+L:     linux-clk@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git
 S:     Maintained
 F:     drivers/clk/
@@ -3073,10 +3066,16 @@ F:      drivers/net/fddi/defxx.*
 
 DELL LAPTOP DRIVER
 M:     Matthew Garrett <mjg59@srcf.ucam.org>
+M:     Pali Rohár <pali.rohar@gmail.com>
 L:     platform-driver-x86@vger.kernel.org
 S:     Maintained
 F:     drivers/platform/x86/dell-laptop.c
 
+DELL LAPTOP FREEFALL DRIVER
+M:     Pali Rohár <pali.rohar@gmail.com>
+S:     Maintained
+F:     drivers/platform/x86/dell-smo8800.c
+
 DELL LAPTOP SMM DRIVER
 M:     Guenter Roeck <linux@roeck-us.net>
 S:     Maintained
@@ -3091,6 +3090,7 @@ F:        drivers/firmware/dcdbas.*
 
 DELL WMI EXTRAS DRIVER
 M:     Matthew Garrett <mjg59@srcf.ucam.org>
+M:     Pali Rohár <pali.rohar@gmail.com>
 S:     Maintained
 F:     drivers/platform/x86/dell-wmi.c
 
@@ -3278,12 +3278,6 @@ F:       drivers/firmware/dmi-id.c
 F:     drivers/firmware/dmi_scan.c
 F:     include/linux/dmi.h
 
-DOCKING STATION DRIVER
-M:     Shaohua Li <shaohua.li@intel.com>
-L:     linux-acpi@vger.kernel.org
-S:     Supported
-F:     drivers/acpi/dock.c
-
 DOCUMENTATION
 M:     Jonathan Corbet <corbet@lwn.net>
 L:     linux-doc@vger.kernel.org
@@ -3419,6 +3413,13 @@ F:       drivers/gpu/drm/rcar-du/
 F:     drivers/gpu/drm/shmobile/
 F:     include/linux/platform_data/shmob_drm.h
 
+DRM DRIVERS FOR ROCKCHIP
+M:     Mark Yao <mark.yao@rock-chips.com>
+L:     dri-devel@lists.freedesktop.org
+S:     Maintained
+F:     drivers/gpu/drm/rockchip/
+F:     Documentation/devicetree/bindings/video/rockchip*
+
 DSBR100 USB FM RADIO DRIVER
 M:     Alexey Klimov <klimov.linux@gmail.com>
 L:     linux-media@vger.kernel.org
@@ -4473,7 +4474,7 @@ S:        Maintained
 F:     block/partitions/efi.*
 
 STK1160 USB VIDEO CAPTURE DRIVER
-M:     Ezequiel Garcia <elezegarcia@gmail.com>
+M:     Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
 L:     linux-media@vger.kernel.org
 T:     git git://linuxtv.org/media_tree.git
 S:     Maintained
@@ -5016,6 +5017,11 @@ W:       http://industrypack.sourceforge.net
 S:     Maintained
 F:     drivers/ipack/
 
+INGENIC JZ4780 DMA Driver
+M:     Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
+S:     Maintained
+F:     drivers/dma/dma-jz4780.c
+
 INTEGRITY MEASUREMENT ARCHITECTURE (IMA)
 M:     Mimi Zohar <zohar@linux.vnet.ibm.com>
 M:     Dmitry Kasatkin <dmitry.kasatkin@gmail.com>
@@ -5036,17 +5042,19 @@ S:      Orphan
 F:     drivers/video/fbdev/imsttfb.c
 
 INFINIBAND SUBSYSTEM
-M:     Roland Dreier <roland@kernel.org>
+M:     Doug Ledford <dledford@redhat.com>
 M:     Sean Hefty <sean.hefty@intel.com>
 M:     Hal Rosenstock <hal.rosenstock@gmail.com>
 L:     linux-rdma@vger.kernel.org
 W:     http://www.openfabrics.org/
 Q:     http://patchwork.kernel.org/project/linux-rdma/list/
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband.git
+T:     git git://github.com/dledford/linux.git
 S:     Supported
 F:     Documentation/infiniband/
 F:     drivers/infiniband/
 F:     include/uapi/linux/if_infiniband.h
+F:     include/uapi/rdma/
+F:     include/rdma/
 
 INOTIFY
 M:     John McCutchan <john@johnmccutchan.com>
@@ -5799,6 +5807,7 @@ F:        drivers/scsi/53c700*
 LED SUBSYSTEM
 M:     Bryan Wu <cooloney@gmail.com>
 M:     Richard Purdie <rpurdie@rpsys.net>
+M:     Jacek Anaszewski <j.anaszewski@samsung.com>
 L:     linux-leds@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds.git
 S:     Maintained
@@ -6165,16 +6174,6 @@ Q:       http://patchwork.linuxtv.org/project/linux-media/list/
 S:     Maintained
 F:     drivers/media/dvb-frontends/m88rs2000*
 
-M88TS2022 MEDIA DRIVER
-M:     Antti Palosaari <crope@iki.fi>
-L:     linux-media@vger.kernel.org
-W:     http://linuxtv.org/
-W:     http://palosaari.fi/linux/
-Q:     http://patchwork.linuxtv.org/project/linux-media/list/
-T:     git git://linuxtv.org/anttip/media_tree.git
-S:     Maintained
-F:     drivers/media/tuners/m88ts2022*
-
 MA901 MASTERKIT USB FM RADIO DRIVER
 M:     Alexey Klimov <klimov.linux@gmail.com>
 L:     linux-media@vger.kernel.org
@@ -6598,6 +6597,7 @@ M:        Laurent Pinchart <laurent.pinchart@ideasonboard.com>
 L:     linux-media@vger.kernel.org
 T:     git git://linuxtv.org/media_tree.git
 S:     Maintained
+F:     Documentation/devicetree/bindings/media/i2c/mt9v032.txt
 F:     drivers/media/i2c/mt9v032.c
 F:     include/media/mt9v032.h
 
@@ -7015,6 +7015,8 @@ Q:        http://patchwork.kernel.org/project/linux-omap/list/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git
 S:     Maintained
 F:     arch/arm/*omap*/
+F:     arch/arm/configs/omap1_defconfig
+F:     arch/arm/configs/omap2plus_defconfig
 F:     drivers/i2c/busses/i2c-omap.c
 F:     drivers/irqchip/irq-omap-intc.c
 F:     drivers/mfd/*omap*.c
@@ -7145,6 +7147,7 @@ OMAP IMAGING SUBSYSTEM (OMAP3 ISP and OMAP4 ISS)
 M:     Laurent Pinchart <laurent.pinchart@ideasonboard.com>
 L:     linux-media@vger.kernel.org
 S:     Maintained
+F:     Documentation/devicetree/bindings/media/ti,omap3isp.txt
 F:     drivers/media/platform/omap3isp/
 F:     drivers/staging/media/omap4iss/
 
@@ -7546,7 +7549,6 @@ S:        Maintained
 F:     drivers/pci/host/pci-exynos.c
 
 PCI DRIVER FOR SYNOPSIS DESIGNWARE
-M:     Mohit Kumar <mohit.kumar@st.com>
 M:     Jingoo Han <jg1.han@samsung.com>
 L:     linux-pci@vger.kernel.org
 S:     Maintained
@@ -7561,9 +7563,8 @@ F:        Documentation/devicetree/bindings/pci/host-generic-pci.txt
 F:     drivers/pci/host/pci-host-generic.c
 
 PCIE DRIVER FOR ST SPEAR13XX
-M:     Mohit Kumar <mohit.kumar@st.com>
 L:     linux-pci@vger.kernel.org
-S:     Maintained
+S:     Orphan
 F:     drivers/pci/host/*spear*
 
 PCMCIA SUBSYSTEM
@@ -8818,6 +8819,15 @@ W:       http://www.emulex.com
 S:     Supported
 F:     drivers/net/ethernet/emulex/benet/
 
+EMULEX ONECONNECT ROCE DRIVER
+M:     Selvin Xavier <selvin.xavier@emulex.com>
+M:     Devesh Sharma <devesh.sharma@emulex.com>
+M:     Mitesh Ahuja <mitesh.ahuja@emulex.com>
+L:     linux-rdma@vger.kernel.org
+W:     http://www.emulex.com
+S:     Supported
+F:     drivers/infiniband/hw/ocrdma/
+
 SFC NETWORK DRIVER
 M:     Solarflare linux maintainers <linux-net-drivers@solarflare.com>
 M:     Shradha Shah <sshah@solarflare.com>
@@ -8991,6 +9001,16 @@ T:       git git://linuxtv.org/mhadli/v4l-dvb-davinci_devices.git
 S:     Maintained
 F:     drivers/media/platform/am437x/
 
+OV2659 OMNIVISION SENSOR DRIVER
+M:     Lad, Prabhakar <prabhakar.csengg@gmail.com>
+L:     linux-media@vger.kernel.org
+W:     http://linuxtv.org/
+Q:     http://patchwork.linuxtv.org/project/linux-media/list/
+T:     git git://linuxtv.org/mhadli/v4l-dvb-davinci_devices.git
+S:     Maintained
+F:     drivers/media/i2c/ov2659.c
+F:     include/media/ov2659.h
+
 SIS 190 ETHERNET DRIVER
 M:     Francois Romieu <romieu@fr.zoreil.com>
 L:     netdev@vger.kernel.org
@@ -9940,10 +9960,23 @@ S:      Maintained
 F:     drivers/platform/x86/topstar-laptop.c
 
 TOSHIBA ACPI EXTRAS DRIVER
+M:     Azael Avalos <coproscefalo@gmail.com>
 L:     platform-driver-x86@vger.kernel.org
-S:     Orphan
+S:     Maintained
 F:     drivers/platform/x86/toshiba_acpi.c
 
+TOSHIBA BLUETOOTH DRIVER
+M:     Azael Avalos <coproscefalo@gmail.com>
+L:     platform-driver-x86@vger.kernel.org
+S:     Maintained
+F:     drivers/platform/x86/toshiba_bluetooth.c
+
+TOSHIBA HDD ACTIVE PROTECTION SENSOR DRIVER
+M:     Azael Avalos <coproscefalo@gmail.com>
+L:     platform-driver-x86@vger.kernel.org
+S:     Maintained
+F:     drivers/platform/x86/toshiba_haps.c
+
 TOSHIBA SMM DRIVER
 M:     Jonathan Buzzard <jonathan@buzzard.org.uk>
 L:     tlinux-users@tce.toshiba-dme.co.jp
@@ -10500,7 +10533,6 @@ F:      include/linux/virtio_console.h
 F:     include/uapi/linux/virtio_console.h
 
 VIRTIO CORE, NET AND BLOCK DRIVERS
-M:     Rusty Russell <rusty@rustcorp.com.au>
 M:     "Michael S. Tsirkin" <mst@redhat.com>
 L:     virtualization@lists.linux-foundation.org
 S:     Maintained
@@ -10520,6 +10552,12 @@ S:     Maintained
 F:     drivers/vhost/
 F:     include/uapi/linux/vhost.h
 
+VIRTIO INPUT DRIVER
+M:     Gerd Hoffmann <kraxel@redhat.com>
+S:     Maintained
+F:     drivers/virtio/virtio_input.c
+F:     include/uapi/linux/virtio_input.h
+
 VIA RHINE NETWORK DRIVER
 M:     Roger Luethi <rl@hellgate.ch>
 S:     Maintained
@@ -10595,6 +10633,14 @@ L:     linux-kernel@vger.kernel.org
 S:     Maintained
 F:     drivers/misc/vmw_balloon.c
 
+VMWARE VMMOUSE SUBDRIVER
+M:     "VMware Graphics" <linux-graphics-maintainer@vmware.com>
+M:     "VMware, Inc." <pv-drivers@vmware.com>
+L:     linux-input@vger.kernel.org
+S:     Maintained
+F:     drivers/input/mouse/vmmouse.c
+F:     drivers/input/mouse/vmmouse.h
+
 VMWARE VMXNET3 ETHERNET DRIVER
 M:     Shreyas Bhatewara <sbhatewara@vmware.com>
 M:     "VMware, Inc." <pv-drivers@vmware.com>
@@ -10920,6 +10966,16 @@ L:     linux-serial@vger.kernel.org
 S:     Maintained
 F:     drivers/tty/serial/uartlite.c
 
+XILINX VIDEO IP CORES
+M:     Hyun Kwon <hyun.kwon@xilinx.com>
+M:     Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+L:     linux-media@vger.kernel.org
+T:     git git://linuxtv.org/media_tree.git
+S:     Supported
+F:     Documentation/devicetree/bindings/media/xilinx/
+F:     drivers/media/platform/xilinx/
+F:     include/uapi/linux/xilinx-v4l2-controls.h
+
 XILLYBUS DRIVER
 M:     Eli Billauer <eli.billauer@gmail.com>
 L:     linux-kernel@vger.kernel.org
@@ -10984,6 +11040,7 @@ F:      drivers/media/pci/zoran/
 ZRAM COMPRESSED RAM BLOCK DEVICE DRVIER
 M:     Minchan Kim <minchan@kernel.org>
 M:     Nitin Gupta <ngupta@vflare.org>
+R:     Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com>
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
 F:     drivers/block/zram/
index 6cc5b243422459cb3ec4317274ebc26c69e0e595..2da553fd7fc36146a36458612a21343277261495 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 4
-PATCHLEVEL = 0
+PATCHLEVEL = 1
 SUBLEVEL = 0
-EXTRAVERSION =
+EXTRAVERSION = -rc2
 NAME = Hurr durr I'ma sheep
 
 # *DOCUMENTATION*
index 757e0c62c4f98c18139d3ce71c008467549b87ef..3b076fbd83661c1c1889ce178465fb881d24f111 100644 (file)
@@ -64,7 +64,7 @@
                };
 
                arcpmu0: pmu {
-                       compatible = "snps,arc700-pmu";
+                       compatible = "snps,arc700-pct";
                };
        };
 };
index 278dacf2a3f94c66830815572a28d2f754e6abc8..d2ac4e56ba1dd6955c43044aa0ec8da7e062c785 100644 (file)
@@ -2,6 +2,9 @@ CONFIG_CROSS_COMPILE="arc-linux-uclibc-"
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_DEFAULT_HOSTNAME="ARCLinux"
 # CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
@@ -9,7 +12,7 @@ CONFIG_NAMESPACES=y
 # CONFIG_UTS_NS is not set
 # CONFIG_PID_NS is not set
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE="../arc_initramfs"
+CONFIG_INITRAMFS_SOURCE="../arc_initramfs/"
 CONFIG_KALLSYMS_ALL=y
 CONFIG_EMBEDDED=y
 # CONFIG_SLUB_DEBUG is not set
@@ -21,12 +24,9 @@ CONFIG_MODULES=y
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
 CONFIG_ARC_PLAT_FPGA_LEGACY=y
-# CONFIG_ARC_IDE is not set
-# CONFIG_ARCTANGENT_EMAC is not set
 # CONFIG_ARC_HAS_RTSC is not set
 CONFIG_ARC_BUILTIN_DTB_NAME="nsimosci"
 # CONFIG_COMPACTION is not set
-# CONFIG_CROSS_MEMORY_ATTACH is not set
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -39,23 +39,23 @@ CONFIG_INET=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 # CONFIG_BLK_DEV is not set
 CONFIG_NETDEVICES=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
 # CONFIG_MOUSE_PS2_ALPS is not set
 # CONFIG_MOUSE_PS2_LOGIPS2PP is not set
 # CONFIG_MOUSE_PS2_SYNAPTICS is not set
+# CONFIG_MOUSE_PS2_CYPRESS is not set
 # CONFIG_MOUSE_PS2_TRACKPOINT is not set
 CONFIG_MOUSE_PS2_TOUCHKIT=y
-# CONFIG_SERIO_I8042 is not set
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_SERIO_ARC_PS2=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_DW=y
+CONFIG_SERIAL_8250_NR_UARTS=1
+CONFIG_SERIAL_8250_RUNTIME_UARTS=1
 CONFIG_SERIAL_OF_PLATFORM=y
-CONFIG_SERIAL_ARC=y
-CONFIG_SERIAL_ARC_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
 CONFIG_FB=y
@@ -72,4 +72,3 @@ CONFIG_TMPFS=y
 CONFIG_NFS_FS=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
 # CONFIG_ENABLE_MUST_CHECK is not set
-CONFIG_XZ_DEC=y
index be33db8a2ee3c3af4ea3d2c9670d4388933a1969..e2b1b1211b0d4ddbb527ed7239eaf05759dfae27 100644 (file)
@@ -30,6 +30,7 @@
 #define ARC_REG_D_UNCACH_BCR   0x6A
 #define ARC_REG_BPU_BCR                0xc0
 #define ARC_REG_ISA_CFG_BCR    0xc1
+#define ARC_REG_RTT_BCR                0xF2
 #define ARC_REG_SMART_BCR      0xFF
 
 /* status32 Bits Positions */
  * [15: 8] = Exception Cause Code
  * [ 7: 0] = Exception Parameters (for certain types only)
  */
-#define ECR_VEC_MASK                   0xff0000
-#define ECR_CODE_MASK                  0x00ff00
-#define ECR_PARAM_MASK                 0x0000ff
-
-/* Exception Cause Vector Values */
+#define ECR_V_MEM_ERR                  0x01
 #define ECR_V_INSN_ERR                 0x02
 #define ECR_V_MACH_CHK                 0x20
 #define ECR_V_ITLB_MISS                        0x21
@@ -62,7 +59,8 @@
 #define ECR_V_PROTV                    0x23
 #define ECR_V_TRAP                     0x25
 
-/* Protection Violation Exception Cause Code Values */
+/* DTLB Miss and Protection Violation Cause Codes */
+
 #define ECR_C_PROTV_INST_FETCH         0x00
 #define ECR_C_PROTV_LOAD               0x01
 #define ECR_C_PROTV_STORE              0x02
        }                                               \
 }
 
-#define WRITE_BCR(reg, into)                           \
+#define WRITE_AUX(reg, into)                           \
 {                                                      \
        unsigned int tmp;                               \
        if (sizeof(tmp) == sizeof(into)) {              \
-               tmp = (*(unsigned int *)(into));        \
+               tmp = (*(unsigned int *)&(into));       \
                write_aux_reg(reg, tmp);                \
        } else  {                                       \
                extern void bogus_undefined(void);      \
index 1a5bf07eefe2d445861ecafd2ac03b0b36e9c458..4051e9525939fd9050b06b048bec8e1a47307d7b 100644 (file)
@@ -32,6 +32,20 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *m)
 
        m += nr >> 5;
 
+       /*
+        * ARC ISA micro-optimization:
+        *
+        * Instructions dealing with bitpos only consider lower 5 bits (0-31)
+        * e.g (x << 33) is handled like (x << 1) by ASL instruction
+        *  (mem pointer still needs adjustment to point to next word)
+        *
+        * Hence the masking to clamp @nr arg can be elided in general.
+        *
+        * However if @nr is a constant (above assumed it in a register),
+        * and greater than 31, gcc can optimize away (x << 33) to 0,
+        * as overflow, given the 32-bit ISA. Thus masking needs to be done
+        * for constant @nr, but no code is generated due to const prop.
+        */
        if (__builtin_constant_p(nr))
                nr &= 0x1f;
 
@@ -374,29 +388,20 @@ __test_and_change_bit(unsigned long nr, volatile unsigned long *m)
  * This routine doesn't need to be atomic.
  */
 static inline int
-__constant_test_bit(unsigned int nr, const volatile unsigned long *addr)
-{
-       return ((1UL << (nr & 31)) &
-               (((const volatile unsigned int *)addr)[nr >> 5])) != 0;
-}
-
-static inline int
-__test_bit(unsigned int nr, const volatile unsigned long *addr)
+test_bit(unsigned int nr, const volatile unsigned long *addr)
 {
        unsigned long mask;
 
        addr += nr >> 5;
 
-       /* ARC700 only considers 5 bits in bit-fiddling insn */
+       if (__builtin_constant_p(nr))
+               nr &= 0x1f;
+
        mask = 1 << nr;
 
        return ((mask & *addr) != 0);
 }
 
-#define test_bit(nr, addr)     (__builtin_constant_p(nr) ? \
-                                       __constant_test_bit((nr), (addr)) : \
-                                       __test_bit((nr), (addr)))
-
 /*
  * Count the number of zeros, starting from MSB
  * Helper for fls( ) friends
index cbf755e32a03f3c19296b552e3f767865fbacc86..2b8880e953a294f4dc4abf7fbe7ae04580dd82ce 100644 (file)
@@ -54,29 +54,13 @@ struct arc_reg_cc_build {
 #define PERF_COUNT_ARC_BPOK    (PERF_COUNT_HW_MAX + 3)
 #define PERF_COUNT_ARC_EDTLB   (PERF_COUNT_HW_MAX + 4)
 #define PERF_COUNT_ARC_EITLB   (PERF_COUNT_HW_MAX + 5)
-#define PERF_COUNT_ARC_HW_MAX  (PERF_COUNT_HW_MAX + 6)
+#define PERF_COUNT_ARC_LDC     (PERF_COUNT_HW_MAX + 6)
+#define PERF_COUNT_ARC_STC     (PERF_COUNT_HW_MAX + 7)
+
+#define PERF_COUNT_ARC_HW_MAX  (PERF_COUNT_HW_MAX + 8)
 
 /*
- * The "generalized" performance events seem to really be a copy
- * of the available events on x86 processors; the mapping to ARC
- * events is not always possible 1-to-1. Fortunately, there doesn't
- * seem to be an exact definition for these events, so we can cheat
- * a bit where necessary.
- *
- * In particular, the following PERF events may behave a bit differently
- * compared to other architectures:
- *
- * PERF_COUNT_HW_CPU_CYCLES
- *     Cycles not in halted state
- *
- * PERF_COUNT_HW_REF_CPU_CYCLES
- *     Reference cycles not in halted state, same as PERF_COUNT_HW_CPU_CYCLES
- *     for now as we don't do Dynamic Voltage/Frequency Scaling (yet)
- *
- * PERF_COUNT_HW_BUS_CYCLES
- *     Unclear what this means, Intel uses 0x013c, which according to
- *     their datasheet means "unhalted reference cycles". It sounds similar
- *     to PERF_COUNT_HW_REF_CPU_CYCLES, and we use the same counter for it.
+ * Some ARC pct quirks:
  *
  * PERF_COUNT_HW_STALLED_CYCLES_BACKEND
  * PERF_COUNT_HW_STALLED_CYCLES_FRONTEND
@@ -91,21 +75,38 @@ struct arc_reg_cc_build {
  *     Note that I$ cache misses aren't counted by either of the two!
  */
 
+/*
+ * ARC PCT has hardware conditions with fixed "names" but variable "indexes"
+ * (based on a specific RTL build)
+ * Below is the static map between perf generic/arc specific event_id and
+ * h/w condition names.
+ * At the time of probe, we loop thru each index and find it's name to
+ * complete the mapping of perf event_id to h/w index as latter is needed
+ * to program the counter really
+ */
 static const char * const arc_pmu_ev_hw_map[] = {
+       /* count cycles */
        [PERF_COUNT_HW_CPU_CYCLES] = "crun",
        [PERF_COUNT_HW_REF_CPU_CYCLES] = "crun",
        [PERF_COUNT_HW_BUS_CYCLES] = "crun",
-       [PERF_COUNT_HW_INSTRUCTIONS] = "iall",
-       [PERF_COUNT_HW_BRANCH_MISSES] = "bpfail",
-       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = "ijmp",
+
        [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = "bflush",
        [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = "bstall",
-       [PERF_COUNT_ARC_DCLM] = "dclm",
-       [PERF_COUNT_ARC_DCSM] = "dcsm",
-       [PERF_COUNT_ARC_ICM] = "icm",
-       [PERF_COUNT_ARC_BPOK] = "bpok",
-       [PERF_COUNT_ARC_EDTLB] = "edtlb",
-       [PERF_COUNT_ARC_EITLB] = "eitlb",
+
+       /* counts condition */
+       [PERF_COUNT_HW_INSTRUCTIONS] = "iall",
+       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = "ijmp",
+       [PERF_COUNT_ARC_BPOK]         = "bpok",   /* NP-NT, PT-T, PNT-NT */
+       [PERF_COUNT_HW_BRANCH_MISSES] = "bpfail", /* NP-T, PT-NT, PNT-T */
+
+       [PERF_COUNT_ARC_LDC] = "imemrdc",       /* Instr: mem read cached */
+       [PERF_COUNT_ARC_STC] = "imemwrc",       /* Instr: mem write cached */
+
+       [PERF_COUNT_ARC_DCLM] = "dclm",         /* D-cache Load Miss */
+       [PERF_COUNT_ARC_DCSM] = "dcsm",         /* D-cache Store Miss */
+       [PERF_COUNT_ARC_ICM] = "icm",           /* I-cache Miss */
+       [PERF_COUNT_ARC_EDTLB] = "edtlb",       /* D-TLB Miss */
+       [PERF_COUNT_ARC_EITLB] = "eitlb",       /* I-TLB Miss */
 };
 
 #define C(_x)                  PERF_COUNT_HW_CACHE_##_x
@@ -114,11 +115,11 @@ static const char * const arc_pmu_ev_hw_map[] = {
 static const unsigned arc_pmu_cache_map[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
        [C(L1D)] = {
                [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_ACCESS)]      = PERF_COUNT_ARC_LDC,
                        [C(RESULT_MISS)]        = PERF_COUNT_ARC_DCLM,
                },
                [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_ACCESS)]      = PERF_COUNT_ARC_STC,
                        [C(RESULT_MISS)]        = PERF_COUNT_ARC_DCSM,
                },
                [C(OP_PREFETCH)] = {
@@ -128,7 +129,7 @@ static const unsigned arc_pmu_cache_map[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
        },
        [C(L1I)] = {
                [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_ACCESS)]      = PERF_COUNT_HW_INSTRUCTIONS,
                        [C(RESULT_MISS)]        = PERF_COUNT_ARC_ICM,
                },
                [C(OP_WRITE)] = {
@@ -156,9 +157,10 @@ static const unsigned arc_pmu_cache_map[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
        },
        [C(DTLB)] = {
                [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_ACCESS)]      = PERF_COUNT_ARC_LDC,
                        [C(RESULT_MISS)]        = PERF_COUNT_ARC_EDTLB,
                },
+                       /* DTLB LD/ST Miss not segregated by h/w*/
                [C(OP_WRITE)] = {
                        [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
                        [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
index ae1c485cbc68ea116d84a0625050c0ab80fea89c..fd2ec50102f201254b1e5e51b4bbc7fa93fba95a 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/perf_event.h>
 #include <linux/platform_device.h>
 #include <asm/arcregs.h>
+#include <asm/stacktrace.h>
 
 struct arc_pmu {
        struct pmu      pmu;
@@ -25,6 +26,46 @@ struct arc_pmu {
        int             ev_hw_idx[PERF_COUNT_ARC_HW_MAX];
 };
 
+struct arc_callchain_trace {
+       int depth;
+       void *perf_stuff;
+};
+
+static int callchain_trace(unsigned int addr, void *data)
+{
+       struct arc_callchain_trace *ctrl = data;
+       struct perf_callchain_entry *entry = ctrl->perf_stuff;
+       perf_callchain_store(entry, addr);
+
+       if (ctrl->depth++ < 3)
+               return 0;
+
+       return -1;
+}
+
+void
+perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
+{
+       struct arc_callchain_trace ctrl = {
+               .depth = 0,
+               .perf_stuff = entry,
+       };
+
+       arc_unwind_core(NULL, regs, callchain_trace, &ctrl);
+}
+
+void
+perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
+{
+       /*
+        * User stack can't be unwound trivially with kernel dwarf unwinder
+        * So for now just record the user PC
+        */
+       perf_callchain_store(entry, instruction_pointer(regs));
+}
+
+static struct arc_pmu *arc_pmu;
+
 /* read counter #idx; note that counter# != event# on ARC! */
 static uint64_t arc_pmu_read_counter(int idx)
 {
@@ -47,7 +88,6 @@ static uint64_t arc_pmu_read_counter(int idx)
 static void arc_perf_event_update(struct perf_event *event,
                                  struct hw_perf_event *hwc, int idx)
 {
-       struct arc_pmu *arc_pmu = container_of(event->pmu, struct arc_pmu, pmu);
        uint64_t prev_raw_count, new_raw_count;
        int64_t delta;
 
@@ -89,13 +129,16 @@ static int arc_pmu_cache_event(u64 config)
        if (ret == CACHE_OP_UNSUPPORTED)
                return -ENOENT;
 
+       pr_debug("init cache event: type/op/result %d/%d/%d with h/w %d \'%s\'\n",
+                cache_type, cache_op, cache_result, ret,
+                arc_pmu_ev_hw_map[ret]);
+
        return ret;
 }
 
 /* initializes hw_perf_event structure if event is supported */
 static int arc_pmu_event_init(struct perf_event *event)
 {
-       struct arc_pmu *arc_pmu = container_of(event->pmu, struct arc_pmu, pmu);
        struct hw_perf_event *hwc = &event->hw;
        int ret;
 
@@ -106,8 +149,9 @@ static int arc_pmu_event_init(struct perf_event *event)
                if (arc_pmu->ev_hw_idx[event->attr.config] < 0)
                        return -ENOENT;
                hwc->config = arc_pmu->ev_hw_idx[event->attr.config];
-               pr_debug("initializing event %d with cfg %d\n",
-                        (int) event->attr.config, (int) hwc->config);
+               pr_debug("init event %d with h/w %d \'%s\'\n",
+                        (int) event->attr.config, (int) hwc->config,
+                        arc_pmu_ev_hw_map[event->attr.config]);
                return 0;
        case PERF_TYPE_HW_CACHE:
                ret = arc_pmu_cache_event(event->attr.config);
@@ -183,8 +227,6 @@ static void arc_pmu_stop(struct perf_event *event, int flags)
 
 static void arc_pmu_del(struct perf_event *event, int flags)
 {
-       struct arc_pmu *arc_pmu = container_of(event->pmu, struct arc_pmu, pmu);
-
        arc_pmu_stop(event, PERF_EF_UPDATE);
        __clear_bit(event->hw.idx, arc_pmu->used_mask);
 
@@ -194,7 +236,6 @@ static void arc_pmu_del(struct perf_event *event, int flags)
 /* allocate hardware counter and optionally start counting */
 static int arc_pmu_add(struct perf_event *event, int flags)
 {
-       struct arc_pmu *arc_pmu = container_of(event->pmu, struct arc_pmu, pmu);
        struct hw_perf_event *hwc = &event->hw;
        int idx = hwc->idx;
 
@@ -247,10 +288,7 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
        BUG_ON(pct_bcr.c > ARC_PMU_MAX_HWEVENTS);
 
        READ_BCR(ARC_REG_CC_BUILD, cc_bcr);
-       if (!cc_bcr.v) {
-               pr_err("Performance counters exist, but no countable conditions?\n");
-               return -ENODEV;
-       }
+       BUG_ON(!cc_bcr.v); /* Counters exist but No countable conditions ? */
 
        arc_pmu = devm_kzalloc(&pdev->dev, sizeof(struct arc_pmu), GFP_KERNEL);
        if (!arc_pmu)
@@ -263,19 +301,22 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
                arc_pmu->n_counters, arc_pmu->counter_size, cc_bcr.c);
 
        cc_name.str[8] = 0;
-       for (i = 0; i < PERF_COUNT_HW_MAX; i++)
+       for (i = 0; i < PERF_COUNT_ARC_HW_MAX; i++)
                arc_pmu->ev_hw_idx[i] = -1;
 
+       /* loop thru all available h/w condition indexes */
        for (j = 0; j < cc_bcr.c; j++) {
                write_aux_reg(ARC_REG_CC_INDEX, j);
                cc_name.indiv.word0 = read_aux_reg(ARC_REG_CC_NAME0);
                cc_name.indiv.word1 = read_aux_reg(ARC_REG_CC_NAME1);
+
+               /* See if it has been mapped to a perf event_id */
                for (i = 0; i < ARRAY_SIZE(arc_pmu_ev_hw_map); i++) {
                        if (arc_pmu_ev_hw_map[i] &&
                            !strcmp(arc_pmu_ev_hw_map[i], cc_name.str) &&
                            strlen(arc_pmu_ev_hw_map[i])) {
-                               pr_debug("mapping %d to idx %d with name %s\n",
-                                        i, j, cc_name.str);
+                               pr_debug("mapping perf event %2d to h/w event \'%8s\' (idx %d)\n",
+                                        i, cc_name.str, j);
                                arc_pmu->ev_hw_idx[i] = j;
                        }
                }
@@ -302,7 +343,7 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
 
 #ifdef CONFIG_OF
 static const struct of_device_id arc_pmu_match[] = {
-       { .compatible = "snps,arc700-pmu" },
+       { .compatible = "snps,arc700-pct" },
        {},
 };
 MODULE_DEVICE_TABLE(of, arc_pmu_match);
@@ -310,7 +351,7 @@ MODULE_DEVICE_TABLE(of, arc_pmu_match);
 
 static struct platform_driver arc_pmu_driver = {
        .driver = {
-               .name           = "arc700-pmu",
+               .name           = "arc700-pct",
                .of_match_table = of_match_ptr(arc_pmu_match),
        },
        .probe          = arc_pmu_device_probe,
index f46efd14059d302712df70442604c19f1a8f2fe6..e095c557afdddc3aefce744c97d5d7bb20a6f2e6 100644 (file)
@@ -49,7 +49,10 @@ void arch_cpu_idle(void)
 
 asmlinkage void ret_from_fork(void);
 
-/* Layout of Child kernel mode stack as setup at the end of this function is
+/*
+ * Copy architecture-specific thread state
+ *
+ * Layout of Child kernel mode stack as setup at the end of this function is
  *
  * |     ...        |
  * |     ...        |
@@ -81,7 +84,7 @@ asmlinkage void ret_from_fork(void);
  * ------------------  <===== END of PAGE
  */
 int copy_thread(unsigned long clone_flags,
-               unsigned long usp, unsigned long arg,
+               unsigned long usp, unsigned long kthread_arg,
                struct task_struct *p)
 {
        struct pt_regs *c_regs;        /* child's pt_regs */
@@ -112,7 +115,7 @@ int copy_thread(unsigned long clone_flags,
        if (unlikely(p->flags & PF_KTHREAD)) {
                memset(c_regs, 0, sizeof(struct pt_regs));
 
-               c_callee->r13 = arg; /* argument to kernel thread */
+               c_callee->r13 = kthread_arg;
                c_callee->r14 = usp;  /* function */
 
                return 0;
index 900f68a7008832017296f3dc641e70203358c5d6..1d167c6df8caae8a48d59b2aa08539e9f20b51d6 100644 (file)
@@ -120,7 +120,10 @@ static void read_arc_build_cfg_regs(void)
        READ_BCR(ARC_REG_SMART_BCR, bcr);
        cpu->extn.smart = bcr.ver ? 1 : 0;
 
-       cpu->extn.debug = cpu->extn.ap | cpu->extn.smart;
+       READ_BCR(ARC_REG_RTT_BCR, bcr);
+       cpu->extn.rtt = bcr.ver ? 1 : 0;
+
+       cpu->extn.debug = cpu->extn.ap | cpu->extn.smart | cpu->extn.rtt;
 }
 
 static const struct cpuinfo_data arc_cpu_tbl[] = {
index 3eadfdabc32295008aa899d74dab4057173ea19e..c927aa84e652e0ac80d37a632c60e1c0201b6d0d 100644 (file)
@@ -42,7 +42,7 @@ void die(const char *str, struct pt_regs *regs, unsigned long address)
  *  -for kernel, chk if due to copy_(to|from)_user, otherwise die()
  */
 static noinline int
-handle_exception(const char *str, struct pt_regs *regs, siginfo_t *info)
+unhandled_exception(const char *str, struct pt_regs *regs, siginfo_t *info)
 {
        if (user_mode(regs)) {
                struct task_struct *tsk = current;
@@ -71,7 +71,7 @@ int name(unsigned long address, struct pt_regs *regs) \
                .si_code  = sicode,             \
                .si_addr = (void __user *)address,      \
        };                                      \
-       return handle_exception(str, regs, &info);\
+       return unhandled_exception(str, regs, &info);\
 }
 
 /*
index 523412369f70a813e0d250013639cae6cb4c1447..d44eedd8c3220e6923b26ea8d10fc6f0f84005f3 100644 (file)
@@ -71,7 +71,7 @@ early_param("initrd", early_initrd);
  */
 void __init setup_arch_memory(void)
 {
-       unsigned long zones_size[MAX_NR_ZONES] = { 0, 0 };
+       unsigned long zones_size[MAX_NR_ZONES];
        unsigned long end_mem = CONFIG_LINUX_LINK_BASE + arc_mem_sz;
 
        init_mm.start_code = (unsigned long)_text;
@@ -90,7 +90,7 @@ void __init setup_arch_memory(void)
        /*------------- externs in mm need setting up ---------------*/
 
        /* first page of system - kernel .vector starts here */
-       min_low_pfn = PFN_DOWN(CONFIG_LINUX_LINK_BASE);
+       min_low_pfn = ARCH_PFN_OFFSET;
 
        /* Last usable page of low mem (no HIGHMEM yet for ARC port) */
        max_low_pfn = max_pfn = PFN_DOWN(end_mem);
@@ -111,7 +111,7 @@ void __init setup_arch_memory(void)
 
        /*-------------- node setup --------------------------------*/
        memset(zones_size, 0, sizeof(zones_size));
-       zones_size[ZONE_NORMAL] = max_low_pfn - min_low_pfn;
+       zones_size[ZONE_NORMAL] = max_mapnr;
 
        /*
         * We can't use the helper free_area_init(zones[]) because it uses
@@ -123,6 +123,8 @@ void __init setup_arch_memory(void)
                            zones_size,         /* num pages per zone */
                            min_low_pfn,        /* first pfn of node */
                            NULL);              /* NO holes */
+
+       high_memory = (void *)end_mem;
 }
 
 /*
@@ -133,7 +135,6 @@ void __init setup_arch_memory(void)
  */
 void __init mem_init(void)
 {
-       high_memory = (void *)(CONFIG_LINUX_LINK_BASE + arc_mem_sz);
        free_all_bootmem();
        mem_init_print_info(NULL);
 }
index 392e7ae69452e26b97ed8e8d265b7958e0ae75c2..45df48ba0b128dd408e2275687b1757c87e0ca74 100644 (file)
@@ -362,19 +362,6 @@ config ARCH_VERSATILE
        help
          This enables support for ARM Ltd Versatile board.
 
-config ARCH_AT91
-       bool "Atmel AT91"
-       select ARCH_REQUIRE_GPIOLIB
-       select CLKDEV_LOOKUP
-       select IRQ_DOMAIN
-       select NEED_MACH_IO_H if PCCARD
-       select PINCTRL
-       select PINCTRL_AT91
-       select USE_OF
-       help
-         This enables support for systems based on Atmel
-         AT91RM9200, AT91SAM9 and SAMA5 processors.
-
 config ARCH_CLPS711X
        bool "Cirrus Logic CLPS711x/EP721x/EP731x-based"
        select ARCH_REQUIRE_GPIOLIB
@@ -632,18 +619,6 @@ config ARCH_PXA
        help
          Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
 
-config ARCH_MSM
-       bool "Qualcomm MSM (non-multiplatform)"
-       select ARCH_REQUIRE_GPIOLIB
-       select COMMON_CLK
-       select GENERIC_CLOCKEVENTS
-       help
-         Support for Qualcomm MSM/QSD based systems.  This runs on the
-         apps processor of the MSM/QSD and depends on a shared memory
-         interface to the modem processor which runs the baseband
-         stack and controls some vital subsystems
-         (clock and power control, etc).
-
 config ARCH_SHMOBILE_LEGACY
        bool "Renesas ARM SoCs (non-multiplatform)"
        select ARCH_SHMOBILE
@@ -653,7 +628,6 @@ config ARCH_SHMOBILE_LEGACY
        select GENERIC_CLOCKEVENTS
        select HAVE_ARM_SCU if SMP
        select HAVE_ARM_TWD if SMP
-       select HAVE_MACH_CLKDEV
        select HAVE_SMP
        select MIGHT_HAVE_CACHE_L2X0
        select MULTI_IRQ_HANDLER
@@ -851,6 +825,8 @@ config ARCH_VIRT
 #
 source "arch/arm/mach-mvebu/Kconfig"
 
+source "arch/arm/mach-alpine/Kconfig"
+
 source "arch/arm/mach-asm9260/Kconfig"
 
 source "arch/arm/mach-at91/Kconfig"
@@ -897,8 +873,6 @@ source "arch/arm/mach-ks8695/Kconfig"
 
 source "arch/arm/mach-meson/Kconfig"
 
-source "arch/arm/mach-msm/Kconfig"
-
 source "arch/arm/mach-moxart/Kconfig"
 
 source "arch/arm/mach-mv78xx0/Kconfig"
@@ -1523,7 +1497,7 @@ config HZ_FIXED
        int
        default 200 if ARCH_EBSA110 || ARCH_S3C24XX || \
                ARCH_S5PV210 || ARCH_EXYNOS4
-       default AT91_TIMER_HZ if ARCH_AT91
+       default 128 if SOC_AT91RM9200
        default SHMOBILE_TIMER_HZ if ARCH_SHMOBILE_LEGACY
        default 0
 
@@ -1856,35 +1830,6 @@ config ZBOOT_ROM
          Say Y here if you intend to execute your compressed kernel image
          (zImage) directly from ROM or flash.  If unsure, say N.
 
-choice
-       prompt "Include SD/MMC loader in zImage (EXPERIMENTAL)"
-       depends on ZBOOT_ROM && ARCH_SH7372
-       default ZBOOT_ROM_NONE
-       help
-         Include experimental SD/MMC loading code in the ROM-able zImage.
-         With this enabled it is possible to write the ROM-able zImage
-         kernel image to an MMC or SD card and boot the kernel straight
-         from the reset vector. At reset the processor Mask ROM will load
-         the first part of the ROM-able zImage which in turn loads the
-         rest the kernel image to RAM.
-
-config ZBOOT_ROM_NONE
-       bool "No SD/MMC loader in zImage (EXPERIMENTAL)"
-       help
-         Do not load image from SD or MMC
-
-config ZBOOT_ROM_MMCIF
-       bool "Include MMCIF loader in zImage (EXPERIMENTAL)"
-       help
-         Load image from MMCIF hardware block.
-
-config ZBOOT_ROM_SH_MOBILE_SDHI
-       bool "Include SuperH Mobile SDHI loader in zImage (EXPERIMENTAL)"
-       help
-         Load image from SDHI hardware block
-
-endchoice
-
 config ARM_APPENDED_DTB
        bool "Use appended device tree blob to zImage (EXPERIMENTAL)"
        depends on OF
@@ -2158,6 +2103,8 @@ source "net/Kconfig"
 
 source "drivers/Kconfig"
 
+source "drivers/firmware/Kconfig"
+
 source "fs/Kconfig"
 
 source "arch/arm/Kconfig.debug"
index 970de7518341d2382ee86a8c9a0cefde2bca2739..0c12ffb155a23c604c9bbb9b849a913d359e34ae 100644 (file)
@@ -93,6 +93,14 @@ choice
        prompt "Kernel low-level debugging port"
        depends on DEBUG_LL
 
+       config DEBUG_ALPINE_UART0
+               bool "Kernel low-level debugging messages via Alpine UART0"
+               depends on ARCH_ALPINE
+               select DEBUG_UART_8250
+               help
+                 Say Y here if you want kernel low-level debugging support
+                 on Alpine based platforms.
+
        config DEBUG_ASM9260_UART
                bool "Kernel low-level debugging via asm9260 UART"
                depends on MACH_ASM9260
@@ -448,25 +456,6 @@ choice
                  Say Y here if you want kernel low-level debugging support
                  on MMP UART3.
 
-       config DEBUG_MSM_UART
-               bool "Kernel low-level debugging messages via MSM UART"
-               depends on ARCH_MSM
-               help
-                 Say Y here if you want the debug print routines to direct
-                 their output to the serial port on MSM devices.
-
-                 ARCH                DEBUG_UART_PHYS   DEBUG_UART_VIRT   #
-                 MSM7X00A, QSD8X50   0xa9a00000        0xe1000000        UART1
-                 MSM7X00A, QSD8X50   0xa9b00000        0xe1000000        UART2
-                 MSM7X00A, QSD8X50   0xa9c00000        0xe1000000        UART3
-
-                 MSM7X30             0xaca00000        0xe1000000        UART1
-                 MSM7X30             0xacb00000        0xe1000000        UART2
-                 MSM7X30             0xacc00000        0xe1000000        UART3
-
-                 Please adjust DEBUG_UART_PHYS and DEBUG_UART_BASE configuration
-                 options based on your needs.
-
        config DEBUG_QCOM_UARTDM
                bool "Kernel low-level debugging messages via QCOM UARTDM"
                depends on ARCH_QCOM
@@ -806,7 +795,7 @@ choice
                  via SCIF2 on Renesas R-Car H1 (R8A7779).
 
        config DEBUG_RCAR_GEN2_SCIF0
-               bool "Kernel low-level debugging messages via SCIF0 on R8A7790/R8A7791/R8A7793)"
+               bool "Kernel low-level debugging messages via SCIF0 on R8A7790/R8A7791/R8A7793"
                depends on ARCH_R8A7790 || ARCH_R8A7791 || ARCH_R8A7793
                help
                  Say Y here if you want kernel low-level debugging support
@@ -821,12 +810,11 @@ choice
                  via SCIF2 on Renesas R-Car E2 (R8A7794).
 
        config DEBUG_RMOBILE_SCIFA0
-               bool "Kernel low-level debugging messages via SCIFA0 on R8A73A4/SH7372"
-               depends on ARCH_R8A73A4 || ARCH_SH7372
+               bool "Kernel low-level debugging messages via SCIFA0 on R8A73A4"
+               depends on ARCH_R8A73A4
                help
                  Say Y here if you want kernel low-level debugging support
-                 via SCIFA0 on Renesas R-Mobile APE6 (R8A73A4) or SH-Mobile
-                 AP4 (SH7372).
+                 via SCIFA0 on Renesas R-Mobile APE6 (R8A73A4).
 
        config DEBUG_RMOBILE_SCIFA1
                bool "Kernel low-level debugging messages via SCIFA1 on R8A7740"
@@ -1295,7 +1283,7 @@ config DEBUG_LL_INCLUDE
                                 DEBUG_IMX6SL_UART || \
                                 DEBUG_IMX6SX_UART
        default "debug/ks8695.S" if DEBUG_KS8695_UART
-       default "debug/msm.S" if DEBUG_MSM_UART || DEBUG_QCOM_UARTDM
+       default "debug/msm.S" if DEBUG_QCOM_UARTDM
        default "debug/netx.S" if DEBUG_NETX_UART
        default "debug/omap2plus.S" if DEBUG_OMAP2PLUS_UART
        default "debug/renesas-scif.S" if DEBUG_R7S72100_SCIF2
@@ -1388,7 +1376,6 @@ config DEBUG_UART_PHYS
        default 0x80230000 if DEBUG_PICOXCELL_UART
        default 0x808c0000 if ARCH_EP93XX
        default 0x90020000 if DEBUG_NSPIRE_CLASSIC_UART || DEBUG_NSPIRE_CX_UART
-       default 0xa9a00000 if DEBUG_MSM_UART
        default 0xb0060000 if DEBUG_SIRFPRIMA2_UART1
        default 0xb0090000 if DEBUG_VEXPRESS_UART0_CRX
        default 0xc0013000 if DEBUG_U300_UART
@@ -1417,6 +1404,7 @@ config DEBUG_UART_PHYS
        default 0xf8b00000 if DEBUG_HIX5HD2_UART
        default 0xf991e000 if DEBUG_QCOM_UARTDM
        default 0xfcb00000 if DEBUG_HI3620_UART
+       default 0xfd883000 if DEBUG_ALPINE_UART0
        default 0xfe800000 if ARCH_IOP32X
        default 0xff690000 if DEBUG_RK32_UART2
        default 0xffc02000 if DEBUG_SOCFPGA_UART
@@ -1433,7 +1421,7 @@ config DEBUG_UART_PHYS
                DEBUG_LL_UART_8250 || DEBUG_LL_UART_PL01X || \
                DEBUG_LL_UART_EFM32 || \
                DEBUG_UART_8250 || DEBUG_UART_PL01X || DEBUG_MESON_UARTAO || \
-               DEBUG_MSM_UART || DEBUG_NETX_UART || \
+               DEBUG_NETX_UART || \
                DEBUG_QCOM_UARTDM || DEBUG_R7S72100_SCIF2 || \
                DEBUG_RCAR_GEN1_SCIF0 || DEBUG_RCAR_GEN1_SCIF2 || \
                DEBUG_RCAR_GEN2_SCIF0 || DEBUG_RCAR_GEN2_SCIF2 || \
@@ -1446,7 +1434,6 @@ config DEBUG_UART_VIRT
        hex "Virtual base address of debug UART"
        default 0xe0000a00 if DEBUG_NETX_UART
        default 0xe0010fe0 if ARCH_RPC
-       default 0xe1000000 if DEBUG_MSM_UART
        default 0xf0000be0 if ARCH_EBSA110
        default 0xf0010000 if DEBUG_ASM9260_UART
        default 0xf01fb000 if DEBUG_NOMADIK_UART
@@ -1483,6 +1470,7 @@ config DEBUG_UART_VIRT
        default 0xfd000000 if ARCH_SPEAR3XX || ARCH_SPEAR6XX
        default 0xfd000000 if ARCH_SPEAR13XX
        default 0xfd012000 if ARCH_MV78XX0
+       default 0xfd883000 if DEBUG_ALPINE_UART0
        default 0xfde12000 if ARCH_DOVE
        default 0xfe012000 if ARCH_ORION5X
        default 0xf31004c0 if DEBUG_MESON_UARTAO
@@ -1526,7 +1514,7 @@ config DEBUG_UART_VIRT
        default DEBUG_UART_PHYS if !MMU
        depends on DEBUG_LL_UART_8250 || DEBUG_LL_UART_PL01X || \
                DEBUG_UART_8250 || DEBUG_UART_PL01X || DEBUG_MESON_UARTAO || \
-               DEBUG_MSM_UART || DEBUG_NETX_UART || \
+               DEBUG_NETX_UART || \
                DEBUG_QCOM_UARTDM || DEBUG_S3C24XX_UART || \
                DEBUG_UART_BCM63XX || DEBUG_ASM9260_UART || \
                DEBUG_SIRFSOC_UART || DEBUG_DIGICOLOR_UA0
@@ -1543,7 +1531,7 @@ config DEBUG_UART_8250_WORD
        depends on DEBUG_LL_UART_8250 || DEBUG_UART_8250
        depends on DEBUG_UART_8250_SHIFT >= 2
        default y if DEBUG_PICOXCELL_UART || DEBUG_SOCFPGA_UART || \
-               ARCH_KEYSTONE || \
+               ARCH_KEYSTONE || DEBUG_ALPINE_UART0 || \
                DEBUG_DAVINCI_DMx_UART0 || DEBUG_DAVINCI_DA8XX_UART1 || \
                DEBUG_DAVINCI_DA8XX_UART2 || \
                DEBUG_BCM_KONA_UART || DEBUG_RK32_UART2 || \
@@ -1556,7 +1544,7 @@ config DEBUG_UART_8250_FLOW_CONTROL
 
 config DEBUG_UNCOMPRESS
        bool
-       depends on ARCH_MULTIPLATFORM || ARCH_MSM || PLAT_SAMSUNG
+       depends on ARCH_MULTIPLATFORM || PLAT_SAMSUNG
        default y if DEBUG_LL && !DEBUG_OMAP2PLUS_UART && \
                     (!DEBUG_TEGRA_UART || !ZBOOT_ROM)
        help
@@ -1573,7 +1561,8 @@ config DEBUG_UNCOMPRESS
 config UNCOMPRESS_INCLUDE
        string
        default "debug/uncompress.h" if ARCH_MULTIPLATFORM || ARCH_MSM || \
-                                       PLAT_SAMSUNG || ARCH_EFM32
+                                       PLAT_SAMSUNG || ARCH_EFM32 || \
+                                       ARCH_SHMOBILE_LEGACY
        default "mach/uncompress.h"
 
 config EARLY_PRINTK
@@ -1610,59 +1599,6 @@ config DEBUG_SET_MODULE_RONX
          against certain classes of kernel exploits.
          If in doubt, say "N".
 
-menuconfig CORESIGHT
-       bool "CoreSight Tracing Support"
-       select ARM_AMBA
-       help
-         This framework provides a kernel interface for the CoreSight debug
-         and trace drivers to register themselves with. It's intended to build
-         a topological view of the CoreSight components based on a DT
-         specification and configure the right serie of components when a
-         trace source gets enabled.
-
-if CORESIGHT
-config CORESIGHT_LINKS_AND_SINKS
-       bool "CoreSight Link and Sink drivers"
-       help
-         This enables support for CoreSight link and sink drivers that are
-         responsible for transporting and collecting the trace data
-         respectively.  Link and sinks are dynamically aggregated with a trace
-         entity at run time to form a complete trace path.
-
-config CORESIGHT_LINK_AND_SINK_TMC
-       bool "Coresight generic TMC driver"
-       depends on CORESIGHT_LINKS_AND_SINKS
-       help
-         This enables support for the Trace Memory Controller driver.  Depending
-         on its configuration the device can act as a link (embedded trace router
-         - ETR) or sink (embedded trace FIFO).  The driver complies with the
-         generic implementation of the component without special enhancement or
-         added features.
-
-config CORESIGHT_SINK_TPIU
-       bool "Coresight generic TPIU driver"
-       depends on CORESIGHT_LINKS_AND_SINKS
-       help
-         This enables support for the Trace Port Interface Unit driver, responsible
-         for bridging the gap between the on-chip coresight components and a trace
-         port collection engine, typically connected to an external host for use
-         case capturing more traces than the on-board coresight memory can handle.
-
-config CORESIGHT_SINK_ETBV10
-       bool "Coresight ETBv1.0 driver"
-       depends on CORESIGHT_LINKS_AND_SINKS
-       help
-         This enables support for the Embedded Trace Buffer version 1.0 driver
-         that complies with the generic implementation of the component without
-         special enhancement or added features.
+source "drivers/hwtracing/coresight/Kconfig"
 
-config CORESIGHT_SOURCE_ETM3X
-       bool "CoreSight Embedded Trace Macrocell 3.x driver"
-       select CORESIGHT_LINKS_AND_SINKS
-       help
-         This driver provides support for processor ETM3.x and PTM1.x modules,
-         which allows tracing the instructions that a processor is executing
-         This is primarily useful for instruction level tracing.  Depending
-         the ETM version data tracing may also be available.
-endif
 endmenu
index 5575d9fa8806cd5f74409242a7041f2e96b16453..985227cbbd1bd797546c36099dcd7cc17c0efc4f 100644 (file)
@@ -136,13 +136,13 @@ textofs-$(CONFIG_PM_H1940)      := 0x00108000
 ifeq ($(CONFIG_ARCH_SA1100),y)
 textofs-$(CONFIG_SA1111) := 0x00208000
 endif
-textofs-$(CONFIG_ARCH_MSM7X30) := 0x00208000
 textofs-$(CONFIG_ARCH_MSM8X60) := 0x00208000
 textofs-$(CONFIG_ARCH_MSM8960) := 0x00208000
 textofs-$(CONFIG_ARCH_AXXIA) := 0x00308000
 
 # Machine directory name.  This list is sorted alphanumerically
 # by CONFIG_* macro name.
+machine-$(CONFIG_ARCH_ALPINE)          += alpine
 machine-$(CONFIG_ARCH_AT91)            += at91
 machine-$(CONFIG_ARCH_AXXIA)           += axxia
 machine-$(CONFIG_ARCH_BCM)             += bcm
@@ -171,7 +171,6 @@ machine-$(CONFIG_ARCH_LPC32XX)              += lpc32xx
 machine-$(CONFIG_ARCH_MESON)           += meson
 machine-$(CONFIG_ARCH_MMP)             += mmp
 machine-$(CONFIG_ARCH_MOXART)          += moxart
-machine-$(CONFIG_ARCH_MSM)             += msm
 machine-$(CONFIG_ARCH_MV78XX0)         += mv78xx0
 machine-$(CONFIG_ARCH_MVEBU)           += mvebu
 machine-$(CONFIG_ARCH_MXC)             += imx
index 3ea230aa94b7e061f53b2b4cea9f867bb6c6aa17..6e1fb2b2ecc750ee4898240d1421d985888cc096 100644 (file)
@@ -6,21 +6,6 @@
 
 OBJS           =
 
-# Ensure that MMCIF loader code appears early in the image
-# to minimise that number of bocks that have to be read in
-# order to load it.
-ifeq ($(CONFIG_ZBOOT_ROM_MMCIF),y)
-OBJS           += mmcif-sh7372.o
-endif
-
-# Ensure that SDHI loader code appears early in the image
-# to minimise that number of bocks that have to be read in
-# order to load it.
-ifeq ($(CONFIG_ZBOOT_ROM_SH_MOBILE_SDHI),y)
-OBJS           += sdhi-shmobile.o
-OBJS           += sdhi-sh7372.o
-endif
-
 AFLAGS_head.o += -DTEXT_OFFSET=$(TEXT_OFFSET)
 HEAD   = head.o
 OBJS   += misc.o decompress.o
index e7f80928949c8da53a13b2bca5ace2928c1ba4c2..22a75259faa32996dffa65843c8b85f29c7d7357 100644 (file)
        /* load board-specific initialization code */
 #include <mach/zboot.h>
 
-#if defined(CONFIG_ZBOOT_ROM_MMCIF) || defined(CONFIG_ZBOOT_ROM_SH_MOBILE_SDHI)
-       /* Load image from MMC/SD */
-       adr     sp, __tmp_stack + 256
-       ldr     r0, __image_start
-       ldr     r1, __image_end
-       subs    r1, r1, r0
-       ldr     r0, __load_base
-       bl      mmc_loader
-
-       /* Jump to loaded code */
-       ldr     r0, __loaded
-       ldr     r1, __image_start
-       sub     r0, r0, r1
-       ldr     r1, __load_base
-       add     pc, r0, r1
-
-__image_start:
-       .long   _start
-__image_end:
-       .long   _got_end
-__load_base:
-       .long   MEMORY_START + 0x02000000 @ Load at 32Mb into SDRAM
-__loaded:
-       .long   __continue
-       .align
-__tmp_stack:
-       .space  256
-__continue:
-#endif /* CONFIG_ZBOOT_ROM_MMC || CONFIG_ZBOOT_ROM_SH_MOBILE_SDHI */
-
        adr     r0, dtb_info
        ldmia   r0, {r1, r3, r4, r5, r7}
 
diff --git a/arch/arm/boot/compressed/mmcif-sh7372.c b/arch/arm/boot/compressed/mmcif-sh7372.c
deleted file mode 100644 (file)
index 672ae95..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * sh7372 MMCIF loader
- *
- * Copyright (C) 2010 Magnus Damm
- * Copyright (C) 2010 Simon Horman
- *
- * 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/mmc/sh_mmcif.h>
-#include <linux/mmc/boot.h>
-#include <mach/mmc.h>
-
-#define MMCIF_BASE      (void __iomem *)0xe6bd0000
-
-#define PORT84CR       (void __iomem *)0xe6050054
-#define PORT85CR       (void __iomem *)0xe6050055
-#define PORT86CR       (void __iomem *)0xe6050056
-#define PORT87CR       (void __iomem *)0xe6050057
-#define PORT88CR       (void __iomem *)0xe6050058
-#define PORT89CR       (void __iomem *)0xe6050059
-#define PORT90CR       (void __iomem *)0xe605005a
-#define PORT91CR       (void __iomem *)0xe605005b
-#define PORT92CR       (void __iomem *)0xe605005c
-#define PORT99CR       (void __iomem *)0xe6050063
-
-#define SMSTPCR3       (void __iomem *)0xe615013c
-
-/* SH7372 specific MMCIF loader
- *
- * loads the zImage from an MMC card starting from block 1.
- *
- * The image must be start with a vrl4 header and
- * the zImage must start at offset 512 of the image. That is,
- * at block 2 (=byte 1024) on the media
- *
- * Use the following line to write the vrl4 formated zImage
- * to an MMC card
- * # dd if=vrl4.out of=/dev/sdx bs=512 seek=1
- */
-asmlinkage void mmc_loader(unsigned char *buf, unsigned long len)
-{
-       mmc_init_progress();
-       mmc_update_progress(MMC_PROGRESS_ENTER);
-
-       /* Initialise MMC
-        * registers: PORT84CR-PORT92CR
-        *            (MMCD0_0-MMCD0_7,MMCCMD0 Control)
-        * value: 0x04 - select function 4
-        */
-        __raw_writeb(0x04, PORT84CR);
-        __raw_writeb(0x04, PORT85CR);
-        __raw_writeb(0x04, PORT86CR);
-        __raw_writeb(0x04, PORT87CR);
-        __raw_writeb(0x04, PORT88CR);
-        __raw_writeb(0x04, PORT89CR);
-        __raw_writeb(0x04, PORT90CR);
-        __raw_writeb(0x04, PORT91CR);
-        __raw_writeb(0x04, PORT92CR);
-
-       /* Initialise MMC
-        * registers: PORT99CR (MMCCLK0 Control)
-        * value: 0x10 | 0x04 - enable output | select function 4
-        */
-       __raw_writeb(0x14, PORT99CR);
-
-       /* Enable clock to MMC hardware block */
-       __raw_writel(__raw_readl(SMSTPCR3) & ~(1 << 12), SMSTPCR3);
-
-       mmc_update_progress(MMC_PROGRESS_INIT);
-
-       /* setup MMCIF hardware */
-       sh_mmcif_boot_init(MMCIF_BASE);
-
-       mmc_update_progress(MMC_PROGRESS_LOAD);
-
-       /* load kernel via MMCIF interface */
-       sh_mmcif_boot_do_read(MMCIF_BASE, 2, /* Kernel is at block 2 */
-                             (len + SH_MMCIF_BBS - 1) / SH_MMCIF_BBS, buf);
-
-
-       /* Disable clock to MMC hardware block */
-       __raw_writel(__raw_readl(SMSTPCR3) | (1 << 12), SMSTPCR3);
-
-       mmc_update_progress(MMC_PROGRESS_DONE);
-}
diff --git a/arch/arm/boot/compressed/sdhi-sh7372.c b/arch/arm/boot/compressed/sdhi-sh7372.c
deleted file mode 100644 (file)
index d279294..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * SuperH Mobile SDHI
- *
- * Copyright (C) 2010 Magnus Damm
- * Copyright (C) 2010 Kuninori Morimoto
- * Copyright (C) 2010 Simon Horman
- *
- * 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.
- *
- * Parts inspired by u-boot
- */
-
-#include <linux/io.h>
-#include <mach/mmc.h>
-#include <linux/mmc/boot.h>
-#include <linux/mmc/tmio.h>
-
-#include "sdhi-shmobile.h"
-
-#define PORT179CR       0xe60520b3
-#define PORT180CR       0xe60520b4
-#define PORT181CR       0xe60520b5
-#define PORT182CR       0xe60520b6
-#define PORT183CR       0xe60520b7
-#define PORT184CR       0xe60520b8
-
-#define SMSTPCR3        0xe615013c
-
-#define CR_INPUT_ENABLE 0x10
-#define CR_FUNCTION1    0x01
-
-#define SDHI1_BASE     (void __iomem *)0xe6860000
-#define SDHI_BASE      SDHI1_BASE
-
-/*  SuperH Mobile SDHI loader
- *
- * loads the zImage from an SD card starting from block 0
- * on physical partition 1
- *
- * The image must be start with a vrl4 header and
- * the zImage must start at offset 512 of the image. That is,
- * at block 1 (=byte 512) of physical partition 1
- *
- * Use the following line to write the vrl4 formated zImage
- * to an SD card
- * # dd if=vrl4.out of=/dev/sdx bs=512
- */
-asmlinkage void mmc_loader(unsigned short *buf, unsigned long len)
-{
-       int high_capacity;
-
-       mmc_init_progress();
-
-       mmc_update_progress(MMC_PROGRESS_ENTER);
-        /* Initialise SDHI1 */
-        /* PORT184CR: GPIO_FN_SDHICMD1 Control */
-        __raw_writeb(CR_FUNCTION1, PORT184CR);
-        /* PORT179CR: GPIO_FN_SDHICLK1 Control */
-        __raw_writeb(CR_INPUT_ENABLE|CR_FUNCTION1, PORT179CR);
-        /* PORT181CR: GPIO_FN_SDHID1_3 Control */
-        __raw_writeb(CR_FUNCTION1, PORT183CR);
-        /* PORT182CR: GPIO_FN_SDHID1_2 Control */
-        __raw_writeb(CR_FUNCTION1, PORT182CR);
-        /* PORT183CR: GPIO_FN_SDHID1_1 Control */
-        __raw_writeb(CR_FUNCTION1, PORT181CR);
-        /* PORT180CR: GPIO_FN_SDHID1_0 Control */
-        __raw_writeb(CR_FUNCTION1, PORT180CR);
-
-        /* Enable clock to SDHI1 hardware block */
-        __raw_writel(__raw_readl(SMSTPCR3) & ~(1 << 13), SMSTPCR3);
-
-       /* setup SDHI hardware */
-       mmc_update_progress(MMC_PROGRESS_INIT);
-       high_capacity = sdhi_boot_init(SDHI_BASE);
-       if (high_capacity < 0)
-               goto err;
-
-       mmc_update_progress(MMC_PROGRESS_LOAD);
-       /* load kernel */
-       if (sdhi_boot_do_read(SDHI_BASE, high_capacity,
-                             0, /* Kernel is at block 1 */
-                             (len + TMIO_BBS - 1) / TMIO_BBS, buf))
-               goto err;
-
-        /* Disable clock to SDHI1 hardware block */
-        __raw_writel(__raw_readl(SMSTPCR3) | (1 << 13), SMSTPCR3);
-
-       mmc_update_progress(MMC_PROGRESS_DONE);
-
-       return;
-err:
-       for(;;);
-}
diff --git a/arch/arm/boot/compressed/sdhi-shmobile.c b/arch/arm/boot/compressed/sdhi-shmobile.c
deleted file mode 100644 (file)
index bd3d469..0000000
+++ /dev/null
@@ -1,449 +0,0 @@
-/*
- * SuperH Mobile SDHI
- *
- * Copyright (C) 2010 Magnus Damm
- * Copyright (C) 2010 Kuninori Morimoto
- * Copyright (C) 2010 Simon Horman
- *
- * 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.
- *
- * Parts inspired by u-boot
- */
-
-#include <linux/io.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/core.h>
-#include <linux/mmc/mmc.h>
-#include <linux/mmc/sd.h>
-#include <linux/mmc/tmio.h>
-#include <mach/sdhi.h>
-
-#define OCR_FASTBOOT           (1<<29)
-#define OCR_HCS                        (1<<30)
-#define OCR_BUSY               (1<<31)
-
-#define RESP_CMD12             0x00000030
-
-static inline u16 sd_ctrl_read16(void __iomem *base, int addr)
-{
-        return __raw_readw(base + addr);
-}
-
-static inline u32 sd_ctrl_read32(void __iomem *base, int addr)
-{
-       return __raw_readw(base + addr) |
-              __raw_readw(base + addr + 2) << 16;
-}
-
-static inline void sd_ctrl_write16(void __iomem *base, int addr, u16 val)
-{
-       __raw_writew(val, base + addr);
-}
-
-static inline void sd_ctrl_write32(void __iomem *base, int addr, u32 val)
-{
-       __raw_writew(val, base + addr);
-       __raw_writew(val >> 16, base + addr + 2);
-}
-
-#define ALL_ERROR (TMIO_STAT_CMD_IDX_ERR | TMIO_STAT_CRCFAIL |         \
-                  TMIO_STAT_STOPBIT_ERR | TMIO_STAT_DATATIMEOUT |      \
-                  TMIO_STAT_RXOVERFLOW | TMIO_STAT_TXUNDERRUN |        \
-                  TMIO_STAT_CMDTIMEOUT | TMIO_STAT_ILL_ACCESS |        \
-                  TMIO_STAT_ILL_FUNC)
-
-static int sdhi_intr(void __iomem *base)
-{
-       unsigned long state = sd_ctrl_read32(base, CTL_STATUS);
-
-       if (state & ALL_ERROR) {
-               sd_ctrl_write32(base, CTL_STATUS, ~ALL_ERROR);
-               sd_ctrl_write32(base, CTL_IRQ_MASK,
-                               ALL_ERROR |
-                               sd_ctrl_read32(base, CTL_IRQ_MASK));
-               return -EINVAL;
-       }
-       if (state & TMIO_STAT_CMDRESPEND) {
-               sd_ctrl_write32(base, CTL_STATUS, ~TMIO_STAT_CMDRESPEND);
-               sd_ctrl_write32(base, CTL_IRQ_MASK,
-                               TMIO_STAT_CMDRESPEND |
-                               sd_ctrl_read32(base, CTL_IRQ_MASK));
-               return 0;
-       }
-       if (state & TMIO_STAT_RXRDY) {
-               sd_ctrl_write32(base, CTL_STATUS, ~TMIO_STAT_RXRDY);
-               sd_ctrl_write32(base, CTL_IRQ_MASK,
-                               TMIO_STAT_RXRDY | TMIO_STAT_TXUNDERRUN |
-                               sd_ctrl_read32(base, CTL_IRQ_MASK));
-               return 0;
-       }
-       if (state & TMIO_STAT_DATAEND) {
-               sd_ctrl_write32(base, CTL_STATUS, ~TMIO_STAT_DATAEND);
-               sd_ctrl_write32(base, CTL_IRQ_MASK,
-                               TMIO_STAT_DATAEND |
-                               sd_ctrl_read32(base, CTL_IRQ_MASK));
-               return 0;
-       }
-
-       return -EAGAIN;
-}
-
-static int sdhi_boot_wait_resp_end(void __iomem *base)
-{
-       int err = -EAGAIN, timeout = 10000000;
-
-       while (timeout--) {
-               err = sdhi_intr(base);
-               if (err != -EAGAIN)
-                       break;
-               udelay(1);
-       }
-
-       return err;
-}
-
-/* SDHI_CLK_CTRL */
-#define CLK_MMC_ENABLE                 (1 << 8)
-#define CLK_MMC_INIT                   (1 << 6)        /* clk / 256 */
-
-static void sdhi_boot_mmc_clk_stop(void __iomem *base)
-{
-       sd_ctrl_write16(base, CTL_CLK_AND_WAIT_CTL, 0x0000);
-       msleep(10);
-       sd_ctrl_write16(base, CTL_SD_CARD_CLK_CTL, ~CLK_MMC_ENABLE &
-               sd_ctrl_read16(base, CTL_SD_CARD_CLK_CTL));
-       msleep(10);
-}
-
-static void sdhi_boot_mmc_clk_start(void __iomem *base)
-{
-       sd_ctrl_write16(base, CTL_SD_CARD_CLK_CTL, CLK_MMC_ENABLE |
-               sd_ctrl_read16(base, CTL_SD_CARD_CLK_CTL));
-       msleep(10);
-       sd_ctrl_write16(base, CTL_CLK_AND_WAIT_CTL, CLK_MMC_ENABLE);
-       msleep(10);
-}
-
-static void sdhi_boot_reset(void __iomem *base)
-{
-       sd_ctrl_write16(base, CTL_RESET_SD, 0x0000);
-       msleep(10);
-       sd_ctrl_write16(base, CTL_RESET_SD, 0x0001);
-       msleep(10);
-}
-
-/* Set MMC clock / power.
- * Note: This controller uses a simple divider scheme therefore it cannot
- * run a MMC card at full speed (20MHz). The max clock is 24MHz on SD, but as
- * MMC wont run that fast, it has to be clocked at 12MHz which is the next
- * slowest setting.
- */
-static int sdhi_boot_mmc_set_ios(void __iomem *base, struct mmc_ios *ios)
-{
-       if (sd_ctrl_read32(base, CTL_STATUS) & TMIO_STAT_CMD_BUSY)
-               return -EBUSY;
-
-       if (ios->clock)
-               sd_ctrl_write16(base, CTL_SD_CARD_CLK_CTL,
-                               ios->clock | CLK_MMC_ENABLE);
-
-       /* Power sequence - OFF -> ON -> UP */
-       switch (ios->power_mode) {
-       case MMC_POWER_OFF: /* power down SD bus */
-               sdhi_boot_mmc_clk_stop(base);
-               break;
-       case MMC_POWER_ON: /* power up SD bus */
-               break;
-       case MMC_POWER_UP: /* start bus clock */
-               sdhi_boot_mmc_clk_start(base);
-               break;
-       }
-
-       switch (ios->bus_width) {
-       case MMC_BUS_WIDTH_1:
-               sd_ctrl_write16(base, CTL_SD_MEM_CARD_OPT, 0x80e0);
-       break;
-       case MMC_BUS_WIDTH_4:
-               sd_ctrl_write16(base, CTL_SD_MEM_CARD_OPT, 0x00e0);
-       break;
-       }
-
-       /* Let things settle. delay taken from winCE driver */
-       udelay(140);
-
-       return 0;
-}
-
-/* These are the bitmasks the tmio chip requires to implement the MMC response
- * types. Note that R1 and R6 are the same in this scheme. */
-#define RESP_NONE      0x0300
-#define RESP_R1        0x0400
-#define RESP_R1B       0x0500
-#define RESP_R2        0x0600
-#define RESP_R3        0x0700
-#define DATA_PRESENT   0x0800
-#define TRANSFER_READ  0x1000
-
-static int sdhi_boot_request(void __iomem *base, struct mmc_command *cmd)
-{
-       int err, c = cmd->opcode;
-
-       switch (mmc_resp_type(cmd)) {
-       case MMC_RSP_NONE: c |= RESP_NONE; break;
-       case MMC_RSP_R1:   c |= RESP_R1;   break;
-       case MMC_RSP_R1B:  c |= RESP_R1B;  break;
-       case MMC_RSP_R2:   c |= RESP_R2;   break;
-       case MMC_RSP_R3:   c |= RESP_R3;   break;
-       default:
-               return -EINVAL;
-       }
-
-       /* No interrupts so this may not be cleared */
-       sd_ctrl_write32(base, CTL_STATUS, ~TMIO_STAT_CMDRESPEND);
-
-       sd_ctrl_write32(base, CTL_IRQ_MASK, TMIO_STAT_CMDRESPEND |
-                       sd_ctrl_read32(base, CTL_IRQ_MASK));
-       sd_ctrl_write32(base, CTL_ARG_REG, cmd->arg);
-       sd_ctrl_write16(base, CTL_SD_CMD, c);
-
-
-       sd_ctrl_write32(base, CTL_IRQ_MASK,
-                       ~(TMIO_STAT_CMDRESPEND | ALL_ERROR) &
-                       sd_ctrl_read32(base, CTL_IRQ_MASK));
-
-       err = sdhi_boot_wait_resp_end(base);
-       if (err)
-               return err;
-
-       cmd->resp[0] = sd_ctrl_read32(base, CTL_RESPONSE);
-
-       return 0;
-}
-
-static int sdhi_boot_do_read_single(void __iomem *base, int high_capacity,
-                                   unsigned long block, unsigned short *buf)
-{
-       int err, i;
-
-       /* CMD17 - Read */
-       {
-               struct mmc_command cmd;
-
-               cmd.opcode = MMC_READ_SINGLE_BLOCK | \
-                            TRANSFER_READ | DATA_PRESENT;
-               if (high_capacity)
-                       cmd.arg = block;
-               else
-                       cmd.arg = block * TMIO_BBS;
-               cmd.flags = MMC_RSP_R1;
-               err = sdhi_boot_request(base, &cmd);
-               if (err)
-                       return err;
-       }
-
-       sd_ctrl_write32(base, CTL_IRQ_MASK,
-                       ~(TMIO_STAT_DATAEND | TMIO_STAT_RXRDY |
-                         TMIO_STAT_TXUNDERRUN) &
-                       sd_ctrl_read32(base, CTL_IRQ_MASK));
-       err = sdhi_boot_wait_resp_end(base);
-       if (err)
-               return err;
-
-       sd_ctrl_write16(base, CTL_SD_XFER_LEN, TMIO_BBS);
-       for (i = 0; i < TMIO_BBS / sizeof(*buf); i++)
-               *buf++ = sd_ctrl_read16(base, RESP_CMD12);
-
-       err = sdhi_boot_wait_resp_end(base);
-       if (err)
-               return err;
-
-       return 0;
-}
-
-int sdhi_boot_do_read(void __iomem *base, int high_capacity,
-                     unsigned long offset, unsigned short count,
-                     unsigned short *buf)
-{
-       unsigned long i;
-       int err = 0;
-
-       for (i = 0; i < count; i++) {
-               err = sdhi_boot_do_read_single(base, high_capacity, offset + i,
-                                              buf + (i * TMIO_BBS /
-                                                     sizeof(*buf)));
-               if (err)
-                       return err;
-       }
-
-       return 0;
-}
-
-#define VOLTAGES (MMC_VDD_32_33 | MMC_VDD_33_34)
-
-int sdhi_boot_init(void __iomem *base)
-{
-       bool sd_v2 = false, sd_v1_0 = false;
-       unsigned short cid;
-       int err, high_capacity = 0;
-
-       sdhi_boot_mmc_clk_stop(base);
-       sdhi_boot_reset(base);
-
-       /* mmc0: clock 400000Hz busmode 1 powermode 2 cs 0 Vdd 21 width 0 timing 0 */
-       {
-               struct mmc_ios ios;
-               ios.power_mode = MMC_POWER_ON;
-               ios.bus_width = MMC_BUS_WIDTH_1;
-               ios.clock = CLK_MMC_INIT;
-               err = sdhi_boot_mmc_set_ios(base, &ios);
-               if (err)
-                       return err;
-       }
-
-       /* CMD0 */
-       {
-               struct mmc_command cmd;
-               msleep(1);
-               cmd.opcode = MMC_GO_IDLE_STATE;
-               cmd.arg = 0;
-               cmd.flags = MMC_RSP_NONE;
-               err = sdhi_boot_request(base, &cmd);
-               if (err)
-                       return err;
-               msleep(2);
-       }
-
-       /* CMD8 - Test for SD version 2 */
-       {
-               struct mmc_command cmd;
-               cmd.opcode = SD_SEND_IF_COND;
-               cmd.arg = (VOLTAGES != 0) << 8 | 0xaa;
-               cmd.flags = MMC_RSP_R1;
-               err = sdhi_boot_request(base, &cmd); /* Ignore error */
-               if ((cmd.resp[0] & 0xff) == 0xaa)
-                       sd_v2 = true;
-       }
-
-       /* CMD55 - Get OCR (SD) */
-       {
-               int timeout = 1000;
-               struct mmc_command cmd;
-
-               cmd.arg = 0;
-
-               do {
-                       cmd.opcode = MMC_APP_CMD;
-                       cmd.flags = MMC_RSP_R1;
-                       cmd.arg = 0;
-                       err = sdhi_boot_request(base, &cmd);
-                       if (err)
-                               break;
-
-                       cmd.opcode = SD_APP_OP_COND;
-                       cmd.flags = MMC_RSP_R3;
-                       cmd.arg = (VOLTAGES & 0xff8000);
-                       if (sd_v2)
-                               cmd.arg |= OCR_HCS;
-                       cmd.arg |= OCR_FASTBOOT;
-                       err = sdhi_boot_request(base, &cmd);
-                       if (err)
-                               break;
-
-                       msleep(1);
-               } while((!(cmd.resp[0] & OCR_BUSY)) && --timeout);
-
-               if (!err && timeout) {
-                       if (!sd_v2)
-                               sd_v1_0 = true;
-                       high_capacity = (cmd.resp[0] & OCR_HCS) == OCR_HCS;
-               }
-       }
-
-       /* CMD1 - Get OCR (MMC) */
-       if (!sd_v2 && !sd_v1_0) {
-               int timeout = 1000;
-               struct mmc_command cmd;
-
-               do {
-                       cmd.opcode = MMC_SEND_OP_COND;
-                       cmd.arg = VOLTAGES | OCR_HCS;
-                       cmd.flags = MMC_RSP_R3;
-                       err = sdhi_boot_request(base, &cmd);
-                       if (err)
-                               return err;
-
-                       msleep(1);
-               } while((!(cmd.resp[0] & OCR_BUSY)) && --timeout);
-
-               if (!timeout)
-                       return -EAGAIN;
-
-               high_capacity = (cmd.resp[0] & OCR_HCS) == OCR_HCS;
-       }
-
-       /* CMD2 - Get CID */
-       {
-               struct mmc_command cmd;
-               cmd.opcode = MMC_ALL_SEND_CID;
-               cmd.arg = 0;
-               cmd.flags = MMC_RSP_R2;
-               err = sdhi_boot_request(base, &cmd);
-               if (err)
-                       return err;
-       }
-
-       /* CMD3
-        * MMC: Set the relative address
-        * SD:  Get the relative address
-        * Also puts the card into the standby state
-        */
-       {
-               struct mmc_command cmd;
-               cmd.opcode = MMC_SET_RELATIVE_ADDR;
-               cmd.arg = 0;
-               cmd.flags = MMC_RSP_R1;
-               err = sdhi_boot_request(base, &cmd);
-               if (err)
-                       return err;
-               cid = cmd.resp[0] >> 16;
-       }
-
-       /* CMD9 - Get CSD */
-       {
-               struct mmc_command cmd;
-               cmd.opcode = MMC_SEND_CSD;
-               cmd.arg = cid << 16;
-               cmd.flags = MMC_RSP_R2;
-               err = sdhi_boot_request(base, &cmd);
-               if (err)
-                       return err;
-       }
-
-       /* CMD7 - Select the card */
-       {
-               struct mmc_command cmd;
-               cmd.opcode = MMC_SELECT_CARD;
-               //cmd.arg = rca << 16;
-               cmd.arg = cid << 16;
-               //cmd.flags = MMC_RSP_R1B;
-               cmd.flags = MMC_RSP_R1;
-               err = sdhi_boot_request(base, &cmd);
-               if (err)
-                       return err;
-       }
-
-       /* CMD16 - Set the block size */
-       {
-               struct mmc_command cmd;
-               cmd.opcode = MMC_SET_BLOCKLEN;
-               cmd.arg = TMIO_BBS;
-               cmd.flags = MMC_RSP_R1;
-               err = sdhi_boot_request(base, &cmd);
-               if (err)
-                       return err;
-       }
-
-       return high_capacity;
-}
diff --git a/arch/arm/boot/compressed/sdhi-shmobile.h b/arch/arm/boot/compressed/sdhi-shmobile.h
deleted file mode 100644 (file)
index 92eaa09..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef SDHI_MOBILE_H
-#define SDHI_MOBILE_H
-
-#include <linux/compiler.h>
-
-int sdhi_boot_do_read(void __iomem *base, int high_capacity,
-                     unsigned long offset, unsigned short count,
-                     unsigned short *buf);
-int sdhi_boot_init(void __iomem *base);
-
-#endif
index a1c776b8dcec51554879d1e001f7f96bd653efd8..86217db2937ab331666b710c1bd639c68caad516 100644 (file)
@@ -1,5 +1,7 @@
 ifeq ($(CONFIG_OF),y)
 
+dtb-$(CONFIG_ARCH_ALPINE) += \
+       alpine-db.dtb
 dtb-$(CONFIG_MACH_ASM9260) += \
        alphascale-asm9260-devkit.dtb
 # Keep at91 dtb files sorted alphabetically for each SoC
@@ -42,6 +44,7 @@ dtb-$(CONFIG_SOC_SAM_V7) += \
        sama5d34ek.dtb \
        sama5d35ek.dtb \
        sama5d36ek.dtb \
+       at91-sama5d4_xplained.dtb \
        at91-sama5d4ek.dtb
 dtb-$(CONFIG_ARCH_ATLAS6) += \
        atlas6-evb.dtb
@@ -59,13 +62,15 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \
        bcm4708-netgear-r6300-v2.dtb \
        bcm47081-asus-rt-n18u.dtb \
        bcm47081-buffalo-wzr-600dhp2.dtb \
-       bcm47081-buffalo-wzr-900dhp.dtb
+       bcm47081-buffalo-wzr-900dhp.dtb \
+       bcm4709-netgear-r8000.dtb
 dtb-$(CONFIG_ARCH_BCM_63XX) += \
        bcm963138dvt.dtb
 dtb-$(CONFIG_ARCH_BCM_CYGNUS) += \
        bcm911360_entphn.dtb \
        bcm911360k.dtb \
-       bcm958300k.dtb
+       bcm958300k.dtb \
+       bcm958305k.dtb
 dtb-$(CONFIG_ARCH_BCM_MOBILE) += \
        bcm28155-ap.dtb \
        bcm21664-garnet.dtb
@@ -165,6 +170,7 @@ dtb-$(CONFIG_MACH_KIRKWOOD) += \
        kirkwood-lsxhl.dtb \
        kirkwood-mplcec4.dtb \
        kirkwood-mv88f6281gtw-ge.dtb \
+       kirkwood-nas2big.dtb \
        kirkwood-net2big.dtb \
        kirkwood-net5big.dtb \
        kirkwood-netgear_readynas_duo_v2.dtb \
@@ -199,6 +205,8 @@ dtb-$(CONFIG_ARCH_LPC32XX) += \
        ea3250.dtb phy3250.dtb
 dtb-$(CONFIG_MACH_MESON6) += \
        meson6-atv1200.dtb
+dtb-$(CONFIG_MACH_MESON8) += \
+       meson8-minix-neo-x8.dtb
 dtb-$(CONFIG_ARCH_MMP) += \
        pxa168-aspenite.dtb \
        pxa910-dkb.dtb \
@@ -299,9 +307,11 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
        imx6q-wandboard.dtb \
        imx6q-wandboard-revb1.dtb
 dtb-$(CONFIG_SOC_IMX6SL) += \
-       imx6sl-evk.dtb
+       imx6sl-evk.dtb \
+       imx6sl-warp.dtb
 dtb-$(CONFIG_SOC_IMX6SX) += \
        imx6sx-sabreauto.dtb \
+       imx6sx-sdb-reva.dtb \
        imx6sx-sdb.dtb
 dtb-$(CONFIG_SOC_LS1021A) += \
        ls1021a-qds.dtb \
@@ -386,6 +396,8 @@ dtb-$(CONFIG_ARCH_OMAP3) += \
        omap3-overo-storm-tobi.dtb \
        omap3-overo-summit.dtb \
        omap3-overo-tobi.dtb \
+       omap3-pandora-600mhz.dtb \
+       omap3-pandora-1ghz.dtb \
        omap3-sbc-t3517.dtb \
        omap3-sbc-t3530.dtb \
        omap3-sbc-t3730.dtb \
@@ -401,7 +413,8 @@ dtb-$(CONFIG_SOC_AM33XX) += \
        am335x-evmsk.dtb \
        am335x-nano.dtb \
        am335x-pepper.dtb \
-       am335x-lxm.dtb
+       am335x-lxm.dtb \
+       am335x-chiliboard.dtb
 dtb-$(CONFIG_ARCH_OMAP4) += \
        omap4-duovero-parlor.dtb \
        omap4-panda.dtb \
@@ -464,25 +477,23 @@ dtb-$(CONFIG_ARCH_S5PV210) += \
        s5pv210-smdkv210.dtb \
        s5pv210-torbreck.dtb
 dtb-$(CONFIG_ARCH_SHMOBILE_LEGACY) += \
-       r8a73a4-ape6evm.dtb \
-       r8a73a4-ape6evm-reference.dtb \
        r8a7740-armadillo800eva.dtb \
        r8a7778-bockw.dtb \
        r8a7778-bockw-reference.dtb \
        r8a7779-marzen.dtb \
-       sh7372-mackerel.dtb \
-       sh73a0-kzm9g.dtb \
-       sh73a0-kzm9g-reference.dtb
+       sh73a0-kzm9g.dtb
 dtb-$(CONFIG_ARCH_SHMOBILE_MULTI) += \
        emev2-kzm9d.dtb \
        r7s72100-genmai.dtb \
        r8a73a4-ape6evm.dtb \
        r8a7740-armadillo800eva.dtb \
+       r8a7778-bockw.dtb \
        r8a7779-marzen.dtb \
        r8a7790-lager.dtb \
        r8a7791-henninger.dtb \
        r8a7791-koelsch.dtb \
-       r8a7794-alt.dtb
+       r8a7794-alt.dtb \
+       sh73a0-kzm9g.dtb
 dtb-$(CONFIG_ARCH_SOCFPGA) += \
        socfpga_arria5_socdk.dtb \
        socfpga_arria10_socdk.dtb \
@@ -577,6 +588,7 @@ dtb-$(CONFIG_ARCH_TEGRA_114_SOC) += \
 dtb-$(CONFIG_ARCH_TEGRA_124_SOC) += \
        tegra124-jetson-tk1.dtb \
        tegra124-nyan-big.dtb \
+       tegra124-nyan-blaze.dtb \
        tegra124-venice2.dtb
 dtb-$(CONFIG_ARCH_U300) += \
        ste-u300.dtb
@@ -624,11 +636,14 @@ dtb-$(CONFIG_MACH_ARMADA_38X) += \
        armada-388-db.dtb \
        armada-388-gp.dtb \
        armada-388-rd.dtb
+dtb-$(CONFIG_MACH_ARMADA_39X) += \
+       armada-398-db.dtb
 dtb-$(CONFIG_MACH_ARMADA_XP) += \
        armada-xp-axpwifiap.dtb \
        armada-xp-db.dtb \
        armada-xp-gp.dtb \
        armada-xp-lenovo-ix4-300d.dtb \
+       armada-xp-linksys-mamba.dtb \
        armada-xp-matrix.dtb \
        armada-xp-netgear-rn2120.dtb \
        armada-xp-openblocks-ax3-4.dtb \
diff --git a/arch/arm/boot/dts/alpine-db.dts b/arch/arm/boot/dts/alpine-db.dts
new file mode 100644 (file)
index 0000000..dfb5a08
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2015 Annapurna Labs 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.
+ *
+ * Alternatively, redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   *   Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *
+ *   *   Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *
+ * 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.
+ *
+ */
+
+/dts-v1/;
+
+#include "alpine.dtsi"
+
+/ {
+       model = "Annapurna Labs Alpine Dev Board";
+       /* no need for anything outside SOC */
+};
+
diff --git a/arch/arm/boot/dts/alpine.dtsi b/arch/arm/boot/dts/alpine.dtsi
new file mode 100644 (file)
index 0000000..9af2d60
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2015 Annapurna Labs 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.
+ *
+ * Alternatively, redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *   *   Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *
+ *   *   Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *
+ * 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 <dt-bindings/interrupt-controller/arm-gic.h>
+#include "skeleton64.dtsi"
+
+/ {
+       /* SOC compatibility */
+       compatible = "al,alpine";
+
+       /* CPU Configuration */
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               enable-method = "al,alpine-smp";
+
+               cpu@0 {
+                       compatible = "arm,cortex-a15";
+                       device_type = "cpu";
+                       reg = <0>;
+                       clock-frequency = <0>; /* Filled by loader */
+               };
+
+               cpu@1 {
+                       compatible = "arm,cortex-a15";
+                       device_type = "cpu";
+                       reg = <1>;
+                       clock-frequency = <0>; /* Filled by loader */
+               };
+
+               cpu@2 {
+                       compatible = "arm,cortex-a15";
+                       device_type = "cpu";
+                       reg = <2>;
+                       clock-frequency = <0>; /* Filled by loader */
+               };
+
+               cpu@3 {
+                       compatible = "arm,cortex-a15";
+                       device_type = "cpu";
+                       reg = <3>;
+                       clock-frequency = <0>; /* Filled by loader */
+               };
+       };
+
+       soc {
+               #address-cells = <2>;
+               #size-cells = <2>;
+               compatible = "simple-bus";
+               interrupt-parent = <&gic>;
+               ranges;
+
+               arch-timer {
+                       compatible = "arm,cortex-a15-timer",
+                                    "arm,armv7-timer";
+                       interrupts =
+                               <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+                               <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+                               <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+                               <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+                       clock-frequency = <0>; /* Filled by loader */
+               };
+
+               /* Interrupt Controller */
+               gic: gic@fb001000 {
+                       compatible = "arm,cortex-a15-gic";
+                       #interrupt-cells = <3>;
+                       #size-cells = <0>;
+                       #address-cells = <0>;
+                       interrupt-controller;
+                       reg = <0x0 0xfb001000 0x0 0x1000>,
+                             <0x0 0xfb002000 0x0 0x2000>,
+                             <0x0 0xfb004000 0x0 0x1000>,
+                             <0x0 0xfb006000 0x0 0x2000>;
+                       interrupts =
+                               <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+               };
+
+               /* CPU Resume registers */
+               cpu-resume@fbff5ec0 {
+                       compatible = "al,alpine-cpu-resume";
+                       reg = <0x0 0xfbff5ec0 0x0 0x30>;
+               };
+
+               /* North Bridge Service Registers */
+               sysfabric-service@fb070000 {
+                       compatible = "al,alpine-sysfabric-service", "syscon";
+                       reg = <0x0 0xfb070000 0x0 0x10000>;
+               };
+
+               /* Performance Monitor Unit */
+               pmu {
+                       compatible = "arm,cortex-a15-pmu";
+                       interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+               };
+
+               uart0:uart@fd883000 {
+                       compatible = "ns16550a";
+                       reg = <0x0 0xfd883000 0x0 0x1000>;
+                       clock-frequency = <0>; /* Filled by loader */
+                       interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+               };
+
+               uart1:uart@0xfd884000 {
+                       compatible = "ns16550a";
+                       reg = <0x0 0xfd884000 0x0 0x1000>;
+                       clock-frequency = <0>; /* Filled by loader */
+                       interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+               };
+
+               /* Internal PCIe Controller */
+               pcie-internal@0xfbc00000 {
+                       compatible = "pci-host-ecam-generic";
+                       device_type = "pci";
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       #interrupt-cells = <1>;
+                       reg = <0x0 0xfbc00000 0x0 0x100000>;
+                       interrupt-map-mask = <0xf800 0 0 7>;
+                       /* Add legacy interrupts for SATA devices only */
+                       interrupt-map = <0x4000 0 0 1 &gic 0 43 4>,
+                                       <0x4800 0 0 1 &gic 0 44 4>;
+
+                       /* 32 bit non prefetchable memory space */
+                       ranges = <0x02000000 0x0 0xfe000000 0x0 0xfe000000 0x0 0x1000000>;
+
+                       bus-range = <0x00 0x00>;
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/am335x-chiliboard.dts b/arch/arm/boot/dts/am335x-chiliboard.dts
new file mode 100644 (file)
index 0000000..310da20
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2015 Jablotron s.r.o. -- http://www.jablotron.com/
+ * Author: Rostislav Lisovy <lisovy@jablotron.cz>
+ *
+ * This program is free software; you can 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 "am335x-chilisom.dtsi"
+
+/ {
+       model = "AM335x Chiliboard";
+       compatible = "grinn,am335x-chiliboard", "grinn,am335x-chilisom",
+                    "ti,am33xx";
+
+       leds {
+               compatible = "gpio-leds";
+               pinctrl-names = "default";
+               pinctrl-0 = <&led_gpio_pins>;
+
+               led0 {
+                       label = "led0";
+                       gpios = <&gpio3 7 GPIO_ACTIVE_LOW>;
+                       default-state = "keep";
+                       linux,default-trigger = "heartbeat";
+               };
+
+               led1 {
+                       label = "led1";
+                       gpios = <&gpio3 8 GPIO_ACTIVE_LOW>;
+                       default-state = "keep";
+               };
+       };
+};
+
+&am33xx_pinmux {
+       usb1_drvvbus: usb1_drvvbus {
+               pinctrl-single,pins = <
+                       0x234 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* usb1_drvvbus.usb1_drvvbus */
+               >;
+       };
+
+       sd_pins: pinmux_sd_card {
+               pinctrl-single,pins = <
+                       0xf0 (PIN_INPUT | MUX_MODE0) /* mmc0_dat0.mmc0_dat0 */
+                       0xf4 (PIN_INPUT | MUX_MODE0) /* mmc0_dat1.mmc0_dat1 */
+                       0xf8 (PIN_INPUT | MUX_MODE0) /* mmc0_dat2.mmc0_dat2 */
+                       0xfc (PIN_INPUT | MUX_MODE0) /* mmc0_dat3.mmc0_dat3 */
+                       0x100 (PIN_INPUT | MUX_MODE0) /* mmc0_clk.mmc0_clk */
+                       0x104 (PIN_INPUT | MUX_MODE0) /* mmc0_cmd.mmc0_cmd */
+                       0x160 (PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */
+               >;
+       };
+
+       led_gpio_pins: led_gpio_pins {
+               pinctrl-single,pins = <
+                       0x1e4 (PIN_OUTPUT | MUX_MODE7) /* emu0.gpio3_7 */
+                       0x1e8 (PIN_OUTPUT | MUX_MODE7) /* emu1.gpio3_8 */
+               >;
+       };
+};
+
+&ldo4_reg {
+       regulator-min-microvolt = <3300000>;
+       regulator-max-microvolt = <3300000>;
+};
+
+/* Ethernet */
+&cpsw_emac0 {
+       phy_id = <&davinci_mdio>, <0>;
+       phy-mode = "rmii";
+};
+
+&phy_sel {
+       rmii-clock-ext;
+};
+
+/* USB */
+&usb {
+       status = "okay";
+};
+
+&usb_ctrl_mod {
+       status = "okay";
+};
+
+&usb1_phy {
+       status = "okay";
+};
+
+&usb1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&usb1_drvvbus>;
+
+       status = "okay";
+       dr_mode = "host";
+};
+
+&cppi41dma  {
+       status = "okay";
+};
+
+/* microSD */
+&mmc1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&sd_pins>;
+       vmmc-supply = <&ldo4_reg>;
+       bus-width = <0x4>;
+       cd-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/am335x-chilisom.dtsi b/arch/arm/boot/dts/am335x-chilisom.dtsi
new file mode 100644 (file)
index 0000000..7e9a34d
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2015 Jablotron s.r.o. -- http://www.jablotron.com/
+ * Author: Rostislav Lisovy <lisovy@jablotron.cz>
+ *
+ * This program is free software; you can 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 "am33xx.dtsi"
+
+/ {
+       model = "Grinn AM335x ChiliSOM";
+       compatible = "grinn,am335x-chilisom", "ti,am33xx";
+
+       cpus {
+               cpu@0 {
+                       cpu0-supply = <&dcdc2_reg>;
+               };
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x80000000 0x20000000>; /* 512 MB */
+       };
+};
+
+&am33xx_pinmux {
+       pinctrl-names = "default";
+
+       i2c0_pins: pinmux_i2c0_pins {
+               pinctrl-single,pins = <
+                       0x188 (PIN_INPUT_PULLUP | MUX_MODE0)    /* i2c0_sda.i2c0_sda */
+                       0x18c (PIN_INPUT_PULLUP | MUX_MODE0)    /* i2c0_scl.i2c0_scl */
+               >;
+       };
+
+       uart0_pins: pinmux_uart0_pins {
+               pinctrl-single,pins = <
+                       0x170 (PIN_INPUT_PULLUP | MUX_MODE0)    /* uart0_rxd.uart0_rxd */
+                       0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */
+               >;
+       };
+
+       cpsw_default: cpsw_default {
+               pinctrl-single,pins = <
+                       /* Slave 1 */
+                       0x10c (PIN_INPUT_PULLDOWN | MUX_MODE1)  /* mii1_crs.rmii1_crs */
+                       0x110 (PIN_INPUT_PULLUP | MUX_MODE1)    /* mii1_rxerr.rmii1_rxerr */
+                       0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txen.rmii1_txen */
+                       0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txd1.rmii1_txd1 */
+                       0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txd0.rmii1_txd0 */
+                       0x13c (PIN_INPUT_PULLUP | MUX_MODE1)    /* mii1_rxd1.rmii1_rxd1 */
+                       0x140 (PIN_INPUT_PULLUP | MUX_MODE1)    /* mii1_rxd0.rmii1_rxd0 */
+                       0x144 (PIN_INPUT_PULLDOWN | MUX_MODE0)  /* rmii1_ref_clk.rmii_ref_clk */
+               >;
+       };
+
+       cpsw_sleep: cpsw_sleep {
+               pinctrl-single,pins = <
+                       /* Slave 1 reset value */
+                       0x10c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       0x110 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       0x144 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+               >;
+       };
+
+       davinci_mdio_default: davinci_mdio_default {
+               pinctrl-single,pins = <
+                       /* mdio_data.mdio_data */
+                       0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)
+                       /* mdio_clk.mdio_clk */
+                       0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0)
+               >;
+       };
+
+       davinci_mdio_sleep: davinci_mdio_sleep {
+               pinctrl-single,pins = <
+                       /* MDIO reset value */
+                       0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+               >;
+       };
+
+       nandflash_pins: nandflash_pins {
+               pinctrl-single,pins = <
+                       0x00 (PIN_INPUT_PULLDOWN | MUX_MODE0)   /* gpmc_ad0.gpmc_ad0 */
+                       0x04 (PIN_INPUT_PULLDOWN | MUX_MODE0)   /* gpmc_ad1.gpmc_ad1 */
+                       0x08 (PIN_INPUT_PULLDOWN | MUX_MODE0)   /* gpmc_ad2.gpmc_ad2 */
+                       0x0c (PIN_INPUT_PULLDOWN | MUX_MODE0)   /* gpmc_ad3.gpmc_ad3 */
+                       0x10 (PIN_INPUT_PULLDOWN | MUX_MODE0)   /* gpmc_ad4.gpmc_ad4 */
+                       0x14 (PIN_INPUT_PULLDOWN | MUX_MODE0)   /* gpmc_ad5.gpmc_ad5 */
+                       0x18 (PIN_INPUT_PULLDOWN | MUX_MODE0)   /* gpmc_ad6.gpmc_ad6 */
+                       0x1c (PIN_INPUT_PULLDOWN | MUX_MODE0)   /* gpmc_ad7.gpmc_ad7 */
+
+                       0x70 (PIN_INPUT_PULLUP | MUX_MODE0)     /* gpmc_wait0.gpmc_wait0 */
+                       0x7c (PIN_OUTPUT_PULLUP | MUX_MODE0)    /* gpmc_csn0.gpmc_csn0 */
+                       0x90 (PIN_OUTPUT_PULLUP | MUX_MODE0)    /* gpmc_advn_ale.gpmc_advn_ale */
+                       0x94 (PIN_OUTPUT_PULLUP | MUX_MODE0)    /* gpmc_oen_ren.gpmc_oen_ren */
+                       0x98 (PIN_OUTPUT_PULLUP | MUX_MODE0)    /* gpmc_wen.gpmc_wen */
+                       0x9c (PIN_OUTPUT_PULLUP | MUX_MODE0)    /* gpmc_be0n_cle.gpmc_be0n_cle */
+               >;
+       };
+};
+
+&uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_pins>;
+
+       status = "okay";
+};
+
+&i2c0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c0_pins>;
+
+       status = "okay";
+       clock-frequency = <400000>;
+
+       tps: tps@24 {
+               reg = <0x24>;
+       };
+
+};
+
+/include/ "tps65217.dtsi"
+
+&tps {
+       regulators {
+               dcdc1_reg: regulator@0 {
+                       regulator-name = "vdds_dpr";
+                       regulator-always-on;
+               };
+
+               dcdc2_reg: regulator@1 {
+                       /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
+                       regulator-name = "vdd_mpu";
+                       regulator-min-microvolt = <925000>;
+                       regulator-max-microvolt = <1325000>;
+                       regulator-boot-on;
+                       regulator-always-on;
+               };
+
+               dcdc3_reg: regulator@2 {
+                       /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
+                       regulator-name = "vdd_core";
+                       regulator-min-microvolt = <925000>;
+                       regulator-max-microvolt = <1150000>;
+                       regulator-boot-on;
+                       regulator-always-on;
+               };
+
+               ldo1_reg: regulator@3 {
+                       regulator-name = "vio,vrtc,vdds";
+                       regulator-boot-on;
+                       regulator-always-on;
+               };
+
+               ldo2_reg: regulator@4 {
+                       regulator-name = "vdd_3v3aux";
+                       regulator-boot-on;
+                       regulator-always-on;
+               };
+
+               ldo3_reg: regulator@5 {
+                       regulator-name = "vdd_1v8";
+                       regulator-boot-on;
+                       regulator-always-on;
+               };
+
+               ldo4_reg: regulator@6 {
+                       regulator-name = "vdd_3v3d";
+                       regulator-boot-on;
+                       regulator-always-on;
+               };
+       };
+};
+
+/* Ethernet MAC */
+&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";
+};
+
+/* NAND Flash */
+&elm {
+       status = "okay";
+};
+
+&gpmc {
+       status = "okay";
+       pinctrl-names = "default";
+       pinctrl-0 = <&nandflash_pins>;
+       ranges = <0 0 0x08000000 0x01000000>; /* CS0 0 @addr 0x08000000, size 0x01000000 */
+       nand@0,0 {
+               reg = <0 0 4>;  /* CS0, offset 0, IO size 4 */
+               ti,nand-ecc-opt = "bch8";
+               ti,elm-id = <&elm>;
+               nand-bus-width = <8>;
+               gpmc,device-width = <1>;
+               gpmc,sync-clk-ps = <0>;
+               gpmc,cs-on-ns = <0>;
+               gpmc,cs-rd-off-ns = <44>;
+               gpmc,cs-wr-off-ns = <44>;
+               gpmc,adv-on-ns = <6>;
+               gpmc,adv-rd-off-ns = <34>;
+               gpmc,adv-wr-off-ns = <44>;
+               gpmc,we-on-ns = <0>;
+               gpmc,we-off-ns = <40>;
+               gpmc,oe-on-ns = <0>;
+               gpmc,oe-off-ns = <54>;
+               gpmc,access-ns = <64>;
+               gpmc,rd-cycle-ns = <82>;
+               gpmc,wr-cycle-ns = <82>;
+               gpmc,wait-on-read = "true";
+               gpmc,wait-on-write = "true";
+               gpmc,bus-turnaround-ns = <0>;
+               gpmc,cycle2cycle-delay-ns = <0>;
+               gpmc,clk-activation-ns = <0>;
+               gpmc,wait-monitoring-ns = <0>;
+               gpmc,wr-access-ns = <40>;
+               gpmc,wr-data-mux-bus-ns = <0>;
+       };
+};
index df5fee6b6b4bcf7ac58d33fc1d25b58cb07890a8..87fc7a35e80261cad03261fd9cf8b047606fc286 100644 (file)
@@ -15,6 +15,7 @@
 
 #include "am33xx.dtsi"
 #include <dt-bindings/pwm/pwm.h>
+#include <dt-bindings/interrupt-controller/irq.h>
 
 / {
        model = "TI AM335x EVM-SK";
        cap-power-off-card;
        pinctrl-names = "default";
        pinctrl-0 = <&mmc2_pins>;
+
+       #address-cells = <1>;
+       #size-cells = <0>;
+       wlcore: wlcore@2 {
+               compatible = "ti,wl1271";
+               reg = <2>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <31 IRQ_TYPE_LEVEL_HIGH>; /* gpio 31 */
+               ref-clock-frequency = <38400000>;
+       };
 };
 
 &mcasp1 {
index a3466455b17188eaafec7eab8b613550a264d3da..5ed4ca6eaf55b6ea0adeae9f0ea635fce453a6ef 100644 (file)
        pinctrl-0 = <&i2c0_pins>;
 
        gpio@20 {
-               compatible = "mcp,mcp23017";
+               compatible = "microchip,mcp23017";
+               gpio-controller;
+               #gpio-cells = <2>;
                reg = <0x20>;
        };
 
        };
 
        eeprom@53 {
-               compatible = "mcp,24c02";
+               compatible = "microchip,24c02";
                reg = <0x53>;
                pagesize = <8>;
        };
                |            |-->0x004FFFFF-> Kernel end
                |            |-->0x00500000-> File system start
                |            |
-               |            |-->0x014FFFFF-> File system end
-               |            |-->0x01500000-> User data start
+               |            |-->0x01FFFFFF-> File system end
+               |            |-->0x02000000-> User data start
                |            |
                |            |-->0x03FFFFFF-> User data end
                |            |-->0x04000000-> Data storage start
 
                partition@4 {
                        label = "rootfs";
-                       reg = <0x00500000 0x01000000>; /* 16MB */
+                       reg = <0x00500000 0x01b00000>; /* 27MB */
                };
 
                partition@5 {
                        label = "user";
-                       reg = <0x01500000 0x02b00000>; /* 43MB */
+                       reg = <0x02000000 0x02000000>; /* 32MB */
                };
 
                partition@6 {
 };
 
 &mac {
-       dual_emac = <1>;
+       dual_emac;
        status = "okay";
 };
 
 
 &cpsw_emac0 {
        phy_id = <&davinci_mdio>, <0>;
+       phy-mode = "mii";
        dual_emac_res_vlan = <1>;
 };
 
 &cpsw_emac1 {
        phy_id = <&davinci_mdio>, <1>;
+       phy-mode = "mii";
        dual_emac_res_vlan = <2>;
 };
 
index 071b56aa0c7e05fd18201b25ba75836edb9aed5e..afb4b3a7bab47b5e426e4e9a25f1a6dd4ec4f360 100644 (file)
@@ -7,7 +7,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-&scrm_clocks {
+&scm_clocks {
        sys_clkin_ck: sys_clkin_ck {
                #clock-cells = <0>;
                compatible = "ti,mux-clock";
index acd37057bca94377e5f092a754ee9cece5dede8a..21fcc440fc1a9d886d408701a705ad4daabd2325 100644 (file)
                };
        };
 
-       am33xx_control_module: control_module@4a002000 {
-               compatible = "syscon";
-               reg = <0x44e10000 0x7fc>;
-       };
-
-       am33xx_pinmux: pinmux@44e10800 {
-               compatible = "pinctrl-single";
-               reg = <0x44e10800 0x0238>;
-               #address-cells = <1>;
-               #size-cells = <0>;
-               pinctrl-single,register-width = <32>;
-               pinctrl-single,function-mask = <0x7f>;
-       };
-
        /*
         * XXX: Use a flat representation of the AM33XX interconnect.
         * The real AM33XX interconnect network is quite complex. Since
                ranges;
                ti,hwmods = "l3_main";
 
-               prcm: prcm@44e00000 {
-                       compatible = "ti,am3-prcm";
-                       reg = <0x44e00000 0x4000>;
-
-                       prcm_clocks: clocks {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                       };
+               l4_wkup: l4_wkup@44c00000 {
+                       compatible = "ti,am3-l4-wkup", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0 0x44c00000 0x280000>;
 
-                       prcm_clockdomains: clockdomains {
-                       };
-               };
+                       prcm: prcm@200000 {
+                               compatible = "ti,am3-prcm";
+                               reg = <0x200000 0x4000>;
 
-               scrm: scrm@44e10000 {
-                       compatible = "ti,am3-scrm";
-                       reg = <0x44e10000 0x2000>;
+                               prcm_clocks: clocks {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                               };
 
-                       scrm_clocks: clocks {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
+                               prcm_clockdomains: clockdomains {
+                               };
                        };
 
-                       scrm_clockdomains: clockdomains {
+                       scm: scm@210000 {
+                               compatible = "ti,am3-scm", "simple-bus";
+                               reg = <0x210000 0x2000>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges = <0 0x210000 0x2000>;
+
+                               am33xx_pinmux: pinmux@800 {
+                                       compatible = "pinctrl-single";
+                                       reg = <0x800 0x238>;
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       pinctrl-single,register-width = <32>;
+                                       pinctrl-single,function-mask = <0x7f>;
+                               };
+
+                               scm_conf: scm_conf@0 {
+                                       compatible = "syscon";
+                                       reg = <0x0 0x800>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       scm_clocks: clocks {
+                                               #address-cells = <1>;
+                                               #size-cells = <0>;
+                                       };
+                               };
+
+                               scm_clockdomains: clockdomains {
+                               };
                        };
                };
 
-               cm: syscon@44e10000 {
-                       compatible = "ti,am33xx-controlmodule", "syscon";
-                       reg = <0x44e10000 0x800>;
-               };
-
                intc: interrupt-controller@48200000 {
                        compatible = "ti,am33xx-intc";
                        interrupt-controller;
                        reg = <0x481cc000 0x2000>;
                        clocks = <&dcan0_fck>;
                        clock-names = "fck";
-                       syscon-raminit = <&am33xx_control_module 0x644 0>;
+                       syscon-raminit = <&scm_conf 0x644 0>;
                        interrupts = <52>;
                        status = "disabled";
                };
                        reg = <0x481d0000 0x2000>;
                        clocks = <&dcan1_fck>;
                        clock-names = "fck";
-                       syscon-raminit = <&am33xx_control_module 0x644 1>;
+                       syscon-raminit = <&scm_conf 0x644 1>;
                        interrupts = <55>;
                        status = "disabled";
                };
                         */
                        interrupts = <40 41 42 43>;
                        ranges;
-                       syscon = <&cm>;
+                       syscon = <&scm_conf>;
                        status = "disabled";
 
                        davinci_mdio: mdio@4a101000 {
index c90724bded1081b7ea6e22461451e39d48828cec..f164dce08755cc5866b79133050db9f808cafce9 100644 (file)
@@ -31,7 +31,7 @@
                        status = "disabled";
                        reg = <0x5c000000 0x30000>;
                        interrupts = <67 68 69 70>;
-                       syscon = <&omap3_scm_general>;
+                       syscon = <&scm_conf>;
                        ti,davinci-ctrl-reg-offset = <0x10000>;
                        ti,davinci-ctrl-mod-reg-offset = <0>;
                        ti,davinci-ctrl-ram-offset = <0x20000>;
index df489d310b50aa0ad01f7750cb6fb17ea36da540..518b8fde88b0c87005fe68e413cfee769befac07 100644 (file)
@@ -7,7 +7,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-&scrm_clocks {
+&scm_clocks {
        emac_ick: emac_ick {
                #clock-cells = <0>;
                compatible = "ti,am35xx-gate-clock";
index 8a099bc10c1e4579e765819d2f87bd92bec8e4a5..c80a3e23379213f67fa92fa7a5ba62f3b44c01c2 100644 (file)
                cache-level = <2>;
        };
 
-       am43xx_control_module: control_module@4a002000 {
-               compatible = "syscon";
-               reg = <0x44e10000 0x7f4>;
-       };
-
-       am43xx_pinmux: pinmux@44e10800 {
-               compatible = "ti,am437-padconf", "pinctrl-single";
-               reg = <0x44e10800 0x31c>;
-               #address-cells = <1>;
-               #size-cells = <0>;
-               #interrupt-cells = <1>;
-               interrupt-controller;
-               pinctrl-single,register-width = <32>;
-               pinctrl-single,function-mask = <0xffffffff>;
-       };
-
        ocp {
                compatible = "ti,am4372-l3-noc", "simple-bus";
                #address-cells = <1>;
                interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
                             <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
 
-               prcm: prcm@44df0000 {
-                       compatible = "ti,am4-prcm";
-                       reg = <0x44df0000 0x11000>;
-
-                       prcm_clocks: clocks {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                       };
+               l4_wkup: l4_wkup@44c00000 {
+                       compatible = "ti,am4-l4-wkup", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0 0x44c00000 0x287000>;
 
-                       prcm_clockdomains: clockdomains {
-                       };
-               };
+                       prcm: prcm@1f0000 {
+                               compatible = "ti,am4-prcm";
+                               reg = <0x1f0000 0x11000>;
 
-               scrm: scrm@44e10000 {
-                       compatible = "ti,am4-scrm";
-                       reg = <0x44e10000 0x2000>;
+                               prcm_clocks: clocks {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                               };
 
-                       scrm_clocks: clocks {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
+                               prcm_clockdomains: clockdomains {
+                               };
                        };
 
-                       scrm_clockdomains: clockdomains {
+                       scm: scm@210000 {
+                               compatible = "ti,am4-scm", "simple-bus";
+                               reg = <0x210000 0x4000>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges = <0 0x210000 0x4000>;
+
+                               am43xx_pinmux: pinmux@800 {
+                                       compatible = "ti,am437-padconf",
+                                                    "pinctrl-single";
+                                       reg = <0x800 0x31c>;
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       #interrupt-cells = <1>;
+                                       interrupt-controller;
+                                       pinctrl-single,register-width = <32>;
+                                       pinctrl-single,function-mask = <0xffffffff>;
+                               };
+
+                               scm_conf: scm_conf@0 {
+                                       compatible = "syscon";
+                                       reg = <0x0 0x800>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       scm_clocks: clocks {
+                                               #address-cells = <1>;
+                                               #size-cells = <0>;
+                                       };
+                               };
+
+                               scm_clockdomains: clockdomains {
+                               };
                        };
                };
 
                };
 
                ocp2scp0: ocp2scp@483a8000 {
-                       compatible = "ti,omap-ocp2scp";
+                       compatible = "ti,am437x-ocp2scp", "ti,omap-ocp2scp";
                        #address-cells = <1>;
                        #size-cells = <1>;
                        ranges;
                };
 
                ocp2scp1: ocp2scp@483e8000 {
-                       compatible = "ti,omap-ocp2scp";
+                       compatible = "ti,am437x-ocp2scp", "ti,omap-ocp2scp";
                        #address-cells = <1>;
                        #size-cells = <1>;
                        ranges;
                };
 
                hdq: hdq@48347000 {
-                       compatible = "ti,am43xx-hdq";
+                       compatible = "ti,am4372-hdq";
                        reg = <0x48347000 0x1000>;
                        interrupts = <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&func_12m_clk>;
                        clocks = <&dcan0_fck>;
                        clock-names = "fck";
                        reg = <0x481cc000 0x2000>;
-                       syscon-raminit = <&am43xx_control_module 0x644 0>;
+                       syscon-raminit = <&scm_conf 0x644 0>;
                        interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
                        status = "disabled";
                };
                        clocks = <&dcan1_fck>;
                        clock-names = "fck";
                        reg = <0x481d0000 0x2000>;
-                       syscon-raminit = <&am43xx_control_module 0x644 1>;
+                       syscon-raminit = <&scm_conf 0x644 1>;
                        interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
                        status = "disabled";
                };
index 0198f5a62b96cd8b8569d4ae5d6dfd2938fcd580..378344271746f20446cc8654c52fd2ef46c5cda2 100644 (file)
                >;
        };
 
+       i2c2_pins_default: i2c2_pins_default {
+               pinctrl-single,pins = <
+                       0x1e8 (PIN_INPUT | SLEWCTRL_FAST | MUX_MODE3) /* cam1_data1.i2c2_scl */
+                       0x1ec (PIN_INPUT | SLEWCTRL_FAST | MUX_MODE3) /* cam1_data0.i2c2_sda */
+               >;
+       };
+
+       i2c2_pins_sleep: i2c2_pins_sleep {
+               pinctrl-single,pins = <
+                       0x1e8 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+                       0x1ec (PIN_INPUT_PULLDOWN | MUX_MODE7)
+               >;
+       };
+
        mmc1_pins_default: pinmux_mmc1_pins_default {
                pinctrl-single,pins = <
                        0x100 (PIN_INPUT | MUX_MODE0) /* mmc0_clk.mmc0_clk */
        };
 };
 
+&i2c2 {
+       status = "okay";
+       pinctrl-names = "default", "sleep";
+       pinctrl-0 = <&i2c2_pins_default>;
+       pinctrl-1 = <&i2c2_pins_sleep>;
+       clock-frequency = <100000>;
+};
+
 &epwmss0 {
        status = "okay";
 };
index 1d7109196872299464ccfb5f3a1938b76e4f68ef..795d68af6df9dbcf9b09b71350e7816606f7994a 100644 (file)
                };
        };
 
-       am43xx_pinmux: pinmux@44e10800 {
+       matrix_keypad: matrix_keypad@0 {
+               compatible = "gpio-matrix-keypad";
+               debounce-delay-ms = <5>;
+               col-scan-delay-us = <2>;
+
+               row-gpios = <&gpio0 12 GPIO_ACTIVE_HIGH         /* Bank0, pin12 */
+                            &gpio0 13 GPIO_ACTIVE_HIGH         /* Bank0, pin13 */
+                            &gpio0 14 GPIO_ACTIVE_HIGH         /* Bank0, pin14 */
+                            &gpio0 15 GPIO_ACTIVE_HIGH>;       /* Bank0, pin15 */
+
+               col-gpios = <&gpio3 9 GPIO_ACTIVE_HIGH          /* Bank3, pin9 */
+                            &gpio3 10 GPIO_ACTIVE_HIGH         /* Bank3, pin10 */
+                            &gpio2 18 GPIO_ACTIVE_HIGH         /* Bank2, pin18 */
+                            &gpio2 19 GPIO_ACTIVE_HIGH>;       /* Bank2, pin19 */
+
+               linux,keymap = <0x00000201      /* P1 */
+                       0x01000204      /* P4 */
+                       0x02000207      /* P7 */
+                       0x0300020a      /* NUMERIC_STAR */
+                       0x00010202      /* P2 */
+                       0x01010205      /* P5 */
+                       0x02010208      /* P8 */
+                       0x03010200      /* P0 */
+                       0x00020203      /* P3 */
+                       0x01020206      /* P6 */
+                       0x02020209      /* P9 */
+                       0x0302020b      /* NUMERIC_POUND */
+                       0x00030067      /* UP */
+                       0x0103006a      /* RIGHT */
+                       0x0203006c      /* DOWN */
+                       0x03030069>;    /* LEFT */
+       };
+
+       backlight {
+               compatible = "pwm-backlight";
+               pwms = <&ecap0 0 50000 PWM_POLARITY_INVERTED>;
+               brightness-levels = <0 51 53 56 62 75 101 152 255>;
+               default-brightness-level = <8>;
+       };
+};
+
+&am43xx_pinmux {
                cpsw_default: cpsw_default {
                        pinctrl-single,pins = <
                                /* Slave 1 */
                                0x204 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7)
                        >;
                };
-       };
-
-       matrix_keypad: matrix_keypad@0 {
-                       compatible = "gpio-matrix-keypad";
-                       debounce-delay-ms = <5>;
-                       col-scan-delay-us = <2>;
-
-                       row-gpios = <&gpio0 12 GPIO_ACTIVE_HIGH         /* Bank0, pin12 */
-                                    &gpio0 13 GPIO_ACTIVE_HIGH         /* Bank0, pin13 */
-                                    &gpio0 14 GPIO_ACTIVE_HIGH         /* Bank0, pin14 */
-                                    &gpio0 15 GPIO_ACTIVE_HIGH>;       /* Bank0, pin15 */
-
-                       col-gpios = <&gpio3 9 GPIO_ACTIVE_HIGH          /* Bank3, pin9 */
-                                    &gpio3 10 GPIO_ACTIVE_HIGH         /* Bank3, pin10 */
-                                    &gpio2 18 GPIO_ACTIVE_HIGH         /* Bank2, pin18 */
-                                    &gpio2 19 GPIO_ACTIVE_HIGH>;       /* Bank2, pin19 */
-
-                       linux,keymap = <0x00000201      /* P1 */
-                               0x01000204      /* P4 */
-                               0x02000207      /* P7 */
-                               0x0300020a      /* NUMERIC_STAR */
-                               0x00010202      /* P2 */
-                               0x01010205      /* P5 */
-                               0x02010208      /* P8 */
-                               0x03010200      /* P0 */
-                               0x00020203      /* P3 */
-                               0x01020206      /* P6 */
-                               0x02020209      /* P9 */
-                               0x0302020b      /* NUMERIC_POUND */
-                               0x00030067      /* UP */
-                               0x0103006a      /* RIGHT */
-                               0x0203006c      /* DOWN */
-                               0x03030069>;    /* LEFT */
-               };
-
-       backlight {
-               compatible = "pwm-backlight";
-               pwms = <&ecap0 0 50000 PWM_POLARITY_INVERTED>;
-               brightness-levels = <0 51 53 56 62 75 101 152 255>;
-               default-brightness-level = <8>;
-       };
 };
 
 &mmc1 {
index cfb49686ab6af02ba7086e344869ee9ad457a2aa..d0c0dfa4ec486e5927abda3d9f4189435a51d23e 100644 (file)
@@ -7,7 +7,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-&scrm_clocks {
+&scm_clocks {
        sys_clkin_ck: sys_clkin_ck {
                #clock-cells = <0>;
                compatible = "ti,mux-clock";
index bd48dba1674865878049e7786e28c7b720feb0cf..15f198e4864d308196640f9ce5a8a190efe8ab9a 100644 (file)
@@ -8,7 +8,6 @@
 /dts-v1/;
 
 #include "dra74x.dtsi"
-#include <dt-bindings/clk/ti-dra7-atl.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 
@@ -87,6 +86,7 @@
                gpios =  <&tps659038_gpio 1 GPIO_ACTIVE_HIGH>;
                gpio-fan,speed-map = <0     0>,
                                     <13000 1>;
+               #cooling-cells = <2>;
        };
 
        extcon_usb1: extcon_usb1 {
                pinctrl-0 = <&tmp102_pins_default>;
                interrupt-parent = <&gpio7>;
                interrupts = <16 IRQ_TYPE_LEVEL_LOW>;
+               #thermal-sensor-cells = <1>;
        };
 };
 
        pinctrl-0 = <&usb1_pins>;
 };
 
+&omap_dwc3_1 {
+       extcon = <&extcon_usb1>;
+};
+
+&omap_dwc3_2 {
+       extcon = <&extcon_usb2>;
+};
+
 &usb2 {
        dr_mode = "peripheral";
 };
+
+&cpu_trips {
+       cpu_alert1: cpu_alert1 {
+               temperature = <50000>; /* millicelsius */
+               hysteresis = <2000>; /* millicelsius */
+               type = "active";
+       };
+};
+
+&cpu_cooling_maps {
+       map1 {
+               trip = <&cpu_alert1>;
+               cooling-device = <&gpio_fan THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+       };
+};
+
+&thermal_zones {
+       board_thermal: board_thermal {
+               polling-delay-passive = <1250>; /* milliseconds */
+               polling-delay = <1500>; /* milliseconds */
+
+                               /* sensor       ID */
+               thermal-sensors = <&tmp102     0>;
+
+               board_trips: trips {
+                       board_alert0: board_alert {
+                               temperature = <40000>; /* millicelsius */
+                               hysteresis = <2000>; /* millicelsius */
+                               type = "active";
+                       };
+
+                       board_crit: board_crit {
+                               temperature = <105000>; /* millicelsius */
+                               hysteresis = <0>; /* millicelsius */
+                               type = "critical";
+                       };
+               };
+
+               board_cooling_maps: cooling-maps {
+                       map0 {
+                               trip = <&board_alert0>;
+                               cooling-device =
+                                 <&gpio_fan THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+                       };
+               };
+       };
+};
index e993c46bd47273b247d80f49c0521c08e06767d5..19f3bf271915fc1dd843a7d10d50df353b4b52d2 100644 (file)
  *     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.
+ *
+ * Note: this Device Tree assumes that the bootloader has remapped the
+ * internal registers to 0xf1000000 (instead of the default
+ * 0xd0000000). The 0xf1000000 is the default used by the recent,
+ * DT-capable, U-Boot bootloaders provided by Marvell. Some earlier
+ * boards were delivered with an older version of the bootloader that
+ * left internal registers mapped at 0xd0000000. If you are in this
+ * situation, you should either update your bootloader (preferred
+ * solution) or the below Device Tree should be adjusted.
  */
 
 /dts-v1/;
@@ -55,7 +64,7 @@
        compatible = "marvell,a370-db", "marvell,armada370", "marvell,armada-370-xp";
 
        chosen {
-               bootargs = "console=ttyS0,115200 earlyprintk";
+               stdout-path = "serial0:115200n8";
        };
 
        memory {
@@ -64,7 +73,7 @@
        };
 
        soc {
-               ranges = <MBUS_ID(0xf0, 0x01) 0 0xd0000000 0x100000
+               ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000
                          MBUS_ID(0x01, 0xe0) 0 0xfff00000 0x100000>;
 
                internal-regs {
index b10ceb488efe5d5aec3b8e91241ae6172e206564..0f40d5da28c3c30ec83a27bacbf9332d9ad23c41 100644 (file)
@@ -51,7 +51,7 @@
        compatible = "globalscale,mirabox", "marvell,armada370", "marvell,armada-370-xp";
 
        chosen {
-               bootargs = "console=ttyS0,115200 earlyprintk";
+               stdout-path = "serial0:115200n8";
        };
 
        memory {
index 3f8cc3845a5e9423f0536ee3c201af4a1b8c5e51..a31207860f34ea385cee3d241c1c902a48d7d6a2 100644 (file)
@@ -53,7 +53,7 @@
        compatible = "netgear,readynas-102", "marvell,armada370", "marvell,armada-370-xp";
 
        chosen {
-               bootargs = "console=ttyS0,115200 earlyprintk";
+               stdout-path = "serial0:115200n8";
        };
 
        memory {
index 99eb8a014ac631df0a26b992f571be829c467411..00540f292979c57e4107ca4b4b9ef51c89e28009 100644 (file)
@@ -53,7 +53,7 @@
        compatible = "netgear,readynas-104", "marvell,armada370", "marvell,armada-370-xp";
 
        chosen {
-               bootargs = "console=ttyS0,115200 earlyprintk";
+               stdout-path = "serial0:115200n8";
        };
 
        memory {
index 6ae36a38beb25b8b1f9930f74dcb250173c627e7..19475e68b8e9246ef5220e0ec3857e5bee4b2192 100644 (file)
@@ -64,7 +64,7 @@
        compatible = "marvell,a370-rd", "marvell,armada370", "marvell,armada-370-xp";
 
        chosen {
-               bootargs = "console=ttyS0,115200 earlyprintk";
+               stdout-path = "serial0:115200n8";
        };
 
        memory {
index 59f74e66963f164b7949f41dc6a520077e2d7fd8..b42b767763aaa41c5a96420e4415efc7683adb16 100644 (file)
@@ -67,8 +67,7 @@
                     "marvell,armada-370-xp";
 
        chosen {
-               bootargs = "console=ttyS0,115200 earlyprintk";
-               stdout-path = &uart0;
+               stdout-path = "serial0:115200n8";
        };
 
        memory {
index 8a322ad57e5fbb0bd0ef15ca19f4387169abeb03..ec96f0b3634653a5976739688eca9fd791eaba0b 100644 (file)
@@ -59,8 +59,8 @@
        compatible = "marvell,armada-370-xp";
 
        aliases {
-               eth0 = &eth0;
-               eth1 = &eth1;
+               serial0 = &uart0;
+               serial1 = &uart1;
        };
 
        cpus {
                };
        };
 
+       pmu {
+               compatible = "arm,cortex-a9-pmu";
+               interrupts-extended = <&mpic 3>;
+       };
+
        soc {
                #address-cells = <2>;
                #size-cells = <1>;
                                      <0x20250 0x8>;
                        };
 
-                       mpic: interrupt-controller@20000 {
+                       mpic: interrupt-controller@20a00 {
                                compatible = "marvell,mpic";
                                #interrupt-cells = <1>;
                                #size-cells = <1>;
index 27397f151def76d9560a6855c87f2ea7afc052bd..00b50db57c9c0f7ab4111bbdba06d3fd0bdc93ad 100644 (file)
                                compatible = "marvell,aurora-outer-cache";
                                reg = <0x08000 0x1000>;
                                cache-id-part = <0x100>;
+                               cache-level = <2>;
                                cache-unified;
                                wt-override;
                        };
                                reg = <0x18330 0x4>;
                        };
 
-                       interrupt-controller@20000 {
+                       interrupt-controller@20a00 {
                                reg = <0x20a00 0x1d0>, <0x21870 0x58>;
                        };
 
index 0440891425c0408723c6ea75db1518105328f2db..4eabc9c21f8dc1e84f399edb6e56a2bdf992a7ed 100644 (file)
@@ -55,7 +55,7 @@
        compatible = "marvell,a375-db", "marvell,armada375";
 
        chosen {
-               bootargs = "console=ttyS0,115200 earlyprintk";
+               stdout-path = "serial0:115200n8";
        };
 
        memory {
index ba3c57e0af72ac577d2e82fa3d9536569dd98e24..c675257f2377f8797565871e38e77ba50fe7678b 100644 (file)
@@ -60,8 +60,8 @@
                gpio0 = &gpio0;
                gpio1 = &gpio1;
                gpio2 = &gpio2;
-               ethernet0 = &eth0;
-               ethernet1 = &eth1;
+               serial0 = &uart0;
+               serial1 = &uart1;
        };
 
        clocks {
                };
        };
 
+       pmu {
+               compatible = "arm,cortex-a9-pmu";
+               interrupts-extended = <&mpic 3>;
+       };
+
        soc {
                compatible = "marvell,armada375-mbus", "simple-bus";
                #address-cells = <2>;
                                status = "disabled";
                        };
 
-                       serial@12000 {
+                       uart0: serial@12000 {
                                compatible = "snps,dw-apb-uart";
                                reg = <0x12000 0x100>;
                                reg-shift = <2>;
                                status = "disabled";
                        };
 
-                       serial@12100 {
+                       uart1: serial@12100 {
                                compatible = "snps,dw-apb-uart";
                                reg = <0x12100 0x100>;
                                reg-shift = <2>;
                                reg = <0x20000 0x100>, <0x20180 0x20>;
                        };
 
-                       mpic: interrupt-controller@20000 {
+                       mpic: interrupt-controller@20a00 {
                                compatible = "marvell,mpic";
                                reg = <0x20a00 0x2d0>, <0x21070 0x58>;
                                #interrupt-cells = <1>;
index 57b9119fb3e05e974ee8931286d2635ab57110fe..7219ac3a3d900743114fd7d9001748118695515e 100644 (file)
@@ -49,8 +49,7 @@
        compatible = "marvell,a385-db-ap", "marvell,armada385", "marvell,armada38x";
 
        chosen {
-               bootargs = "console=ttyS0,115200";
-               stdout-path = &uart1;
+               stdout-path = "serial1:115200n8";
        };
 
        memory {
                                status = "okay";
                        };
 
+                       pinctrl@18000 {
+                               xhci0_vbus_pins: xhci0-vbus-pins {
+                                       marvell,pins = "mpp44";
+                                       marvell,function = "gpio";
+                               };
+                       };
+
                        ethernet@30000 {
                                status = "okay";
                                phy = <&phy2>;
                                phy = <&phy0>;
                                phy-mode = "rgmii-id";
                        };
+
+                       nfc: flash@d0000 {
+                               status = "okay";
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+
+                               num-cs = <1>;
+                               nand-ecc-strength = <4>;
+                               nand-ecc-step-size = <512>;
+                               marvell,nand-keep-config;
+                               marvell,nand-enable-arbiter;
+                               nand-on-flash-bbt;
+                       };
+
+                       usb3@f0000 {
+                               status = "okay";
+                               usb-phy = <&usb3_phy>;
+                       };
                };
 
                pcie-controller {
                        };
                };
        };
+
+       usb3_phy: usb3_phy {
+               compatible = "usb-nop-xceiv";
+               vcc-supply = <&reg_xhci0_vbus>;
+       };
+
+       reg_xhci0_vbus: xhci0-vbus {
+               compatible = "regulator-fixed";
+               pinctrl-names = "default";
+               pinctrl-0 = <&xhci0_vbus_pins>;
+               regulator-name = "xhci0-vbus";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               enable-active-high;
+               gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>;
+       };
 };
index 16512efcd32c091702a9a99c6ea93139598b8a5f..51d1623de53e6967750b6c602ccaeef40359a535 100644 (file)
@@ -54,7 +54,7 @@
                "marvell,armada385", "marvell,armada380";
 
        chosen {
-               bootargs = "console=ttyS0,115200 earlyprintk";
+               stdout-path = "serial0:115200n8";
        };
 
        memory {
@@ -99,7 +99,7 @@
                                phy-mode = "rgmii-id";
                        };
 
-                       usb@50000 {
+                       usb@58000 {
                                status = "ok";
                        };
 
index 590b383db323a75a1041080951d32dbf27e3e9fa..78514ab0b47ace058f49b0da052d131374a8f5d2 100644 (file)
@@ -48,8 +48,7 @@
        compatible = "marvell,a385-gp", "marvell,armada388", "marvell,armada380";
 
        chosen {
-               bootargs = "console=ttyS0,115200";
-               stdout-path = &uart0;
+               stdout-path = "serial0:115200n8";
        };
 
        memory {
                        };
 
                        /* CON4 */
-                       usb@50000 {
+                       usb@58000 {
                                vcc-supply = <&reg_usb2_0_vbus>;
                                status = "okay";
                        };
index d99baac72081b6873532bec2d2587c769a581040..1dc6e2341cc2853829abb077441b27f2cfe4456e 100644 (file)
@@ -55,7 +55,7 @@
                "marvell,armada385","marvell,armada380";
 
        chosen {
-               bootargs = "console=ttyS0,115200 earlyprintk";
+               stdout-path = "serial0:115200n8";
        };
 
        memory {
                                clock-frequency = <100000>;
                        };
 
+                       sdhci@d8000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&sdhci_pins>;
+                               broken-cd;
+                               no-1-8-v;
+                               wp-inverted;
+                               bus-width = <8>;
+                               status = "okay";
+                       };
+
                        serial@12000 {
                                status = "okay";
                        };
index 1dff30a81e247a12ecd88f1c37b2b8dd6a55d2c1..ed2dd8ba4080df7a7f85db89068de44cd693446b 100644 (file)
        aliases {
                gpio0 = &gpio0;
                gpio1 = &gpio1;
-               ethernet0 = &eth0;
-               ethernet1 = &eth1;
-               ethernet2 = &eth2;
+               serial0 = &uart0;
+               serial1 = &uart1;
+       };
+
+       pmu {
+               compatible = "arm,cortex-a9-pmu";
+               interrupts-extended = <&mpic 3>;
        };
 
        soc {
                                status = "disabled";
                        };
 
-                       serial@12100 {
+                       uart1: serial@12100 {
                                compatible = "snps,dw-apb-uart";
                                reg = <0x12100 0x100>;
                                reg-shift = <2>;
                                reg = <0x20000 0x100>, <0x20180 0x20>;
                        };
 
-                       mpic: interrupt-controller@20000 {
+                       mpic: interrupt-controller@20a00 {
                                compatible = "marvell,mpic";
                                reg = <0x20a00 0x2d0>, <0x21070 0x58>;
                                #interrupt-cells = <1>;
                                status = "disabled";
                        };
 
-                       usb@50000 {
+                       usb@58000 {
                                compatible = "marvell,orion-ehci";
                                reg = <0x58000 0x500>;
                                interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
 
                        sdhci@d8000 {
                                compatible = "marvell,armada-380-sdhci";
-                               reg = <0xd8000 0x1000>, <0xdc000 0x100>;
-                               interrupts = <0 25 0x4>;
+                               reg-names = "sdhci", "mbus", "conf-sdio3";
+                               reg = <0xd8000 0x1000>,
+                                       <0xdc000 0x100>,
+                                       <0x18454 0x4>;
+                               interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&gateclk 17>;
                                mrvl,clk-delay-cycles = <0x1F>;
                                status = "disabled";
diff --git a/arch/arm/boot/dts/armada-390.dtsi b/arch/arm/boot/dts/armada-390.dtsi
new file mode 100644 (file)
index 0000000..094e39c
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Device Tree Include file for Marvell Armada 390 SoC.
+ *
+ * Copyright (C) 2015 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , 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 "armada-39x.dtsi"
+
+/ {
+       soc {
+               internal-regs {
+                       pinctrl@18000 {
+                               compatible = "marvell,mv88f6920-pinctrl";
+                               reg = <0x18000 0x20>;
+                       };
+               };
+};
diff --git a/arch/arm/boot/dts/armada-398-db.dts b/arch/arm/boot/dts/armada-398-db.dts
new file mode 100644 (file)
index 0000000..bbf8375
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Device Tree Include file for Marvell Armada 398 Development Board
+ *
+ * Copyright (C) 2015 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , 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 "armada-398.dtsi"
+
+/ {
+       model = "Marvell Armada 398 Development Board";
+       compatible = "marvell,a398-db", "marvell,armada398", "marvell,armada390";
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x00000000 0x80000000>; /* 2 GB */
+       };
+
+       soc {
+               ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000
+                         MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000>;
+
+               internal-regs {
+                       spi@10680 {
+                               status = "okay";
+                               pinctrl-0 = <&spi1_pins>;
+                               pinctrl-names = "default";
+
+                               spi-flash@0 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       compatible = "n25q128a13";
+                                       reg = <0>;
+                                       spi-max-frequency = <108000000>;
+
+                                       partition@0 {
+                                               label = "U-Boot";
+                                               reg = <0 0x400000>;
+                                       };
+
+                                       partition@400000 {
+                                               label = "Filesystem";
+                                               reg = <0x400000 0x1000000>;
+                                       };
+                               };
+                       };
+
+                       i2c@11000 {
+                               pinctrl-0 = <&i2c0_pins>;
+                               pinctrl-names = "default";
+                               status = "okay";
+                               clock-frequency = <100000>;
+                       };
+
+                       serial@12000 {
+                               pinctrl-0 = <&uart0_pins>;
+                               pinctrl-names = "default";
+                               status = "okay";
+                       };
+
+                       serial@12100 {
+                               pinctrl-0 = <&uart1_pins>;
+                               pinctrl-names = "default";
+                               status = "okay";
+                       };
+
+                       flash@d0000 {
+                               status = "okay";
+                               pinctrl-0 = <&nand_pins>;
+                               pinctrl-names = "default";
+                               num-cs = <1>;
+                               marvell,nand-keep-config;
+                               marvell,nand-enable-arbiter;
+                               nand-on-flash-bbt;
+                               nand-ecc-strength = <8>;
+                               nand-ecc-step-size = <512>;
+
+                               partition@0 {
+                                       label = "U-Boot";
+                                       reg = <0 0x800000>;
+                               };
+                               partition@800000 {
+                                       label = "Linux";
+                                       reg = <0x800000 0x800000>;
+                               };
+                               partition@1000000 {
+                                       label = "Filesystem";
+                                       reg = <0x1000000 0x3f000000>;
+                               };
+                       };
+               };
+
+               pcie-controller {
+                       status = "okay";
+
+                       pcie@1,0 {
+                               status = "okay";
+                       };
+
+                       pcie@2,0 {
+                               status = "okay";
+                       };
+
+                       pcie@3,0 {
+                               status = "okay";
+                       };
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/armada-398.dtsi b/arch/arm/boot/dts/armada-398.dtsi
new file mode 100644 (file)
index 0000000..fdc2591
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Device Tree Include file for Marvell Armada 398 SoC.
+ *
+ * Copyright (C) 2015 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , 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 "armada-39x.dtsi"
+
+/ {
+       compatible = "marvell,armada398", "marvell,armada390";
+
+       soc {
+               internal-regs {
+                       pinctrl@18000 {
+                               compatible = "marvell,mv88f6928-pinctrl";
+                               reg = <0x18000 0x20>;
+                       };
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/armada-39x.dtsi b/arch/arm/boot/dts/armada-39x.dtsi
new file mode 100644 (file)
index 0000000..0e85fc1
--- /dev/null
@@ -0,0 +1,508 @@
+/*
+ * Device Tree Include file for Marvell Armada 39x family of SoCs.
+ *
+ * Copyright (C) 2015 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , 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 "skeleton.dtsi"
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+#define MBUS_ID(target,attributes) (((target) << 24) | ((attributes) << 16))
+
+/ {
+       model = "Marvell Armada 39x family SoC";
+       compatible = "marvell,armada390";
+
+       aliases {
+               serial0 = &uart0;
+               serial1 = &uart1;
+               serial2 = &uart2;
+               serial3 = &uart3;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               enable-method = "marvell,armada-390-smp";
+
+               cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       reg = <0>;
+               };
+               cpu@1 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       reg = <1>;
+               };
+       };
+
+       soc {
+               compatible = "marvell,armada390-mbus", "marvell,armadaxp-mbus",
+                            "simple-bus";
+               #address-cells = <2>;
+               #size-cells = <1>;
+               controller = <&mbusc>;
+               interrupt-parent = <&gic>;
+               pcie-mem-aperture = <0xe0000000 0x8000000>;
+               pcie-io-aperture  = <0xe8000000 0x100000>;
+
+               bootrom {
+                       compatible = "marvell,bootrom";
+                       reg = <MBUS_ID(0x01, 0x1d) 0 0x200000>;
+               };
+
+               internal-regs {
+                       compatible = "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>;
+
+                       L2: cache-controller@8000 {
+                               compatible = "arm,pl310-cache";
+                               reg = <0x8000 0x1000>;
+                               cache-unified;
+                               cache-level = <2>;
+                       };
+
+                       scu@c000 {
+                               compatible = "arm,cortex-a9-scu";
+                               reg = <0xc000 0x100>;
+                       };
+
+                       timer@c600 {
+                               compatible = "arm,cortex-a9-twd-timer";
+                               reg = <0xc600 0x20>;
+                               interrupts = <GIC_PPI 13 (IRQ_TYPE_EDGE_RISING | GIC_CPU_MASK_SIMPLE(2))>;
+                               clocks = <&coreclk 2>;
+                       };
+
+                       gic: interrupt-controller@d000 {
+                               compatible = "arm,cortex-a9-gic";
+                               #interrupt-cells = <3>;
+                               #size-cells = <0>;
+                               interrupt-controller;
+                               reg = <0xd000 0x1000>,
+                                     <0xc100 0x100>;
+                       };
+
+                       spi0: spi@10600 {
+                               compatible = "marvell,orion-spi";
+                               reg = <0x10600 0x50>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               cell-index = <0>;
+                               interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&coreclk 0>;
+                               status = "disabled";
+                       };
+
+                       spi1: spi@10680 {
+                               compatible = "marvell,orion-spi";
+                               reg = <0x10680 0x50>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               cell-index = <1>;
+                               interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&coreclk 0>;
+                               status = "disabled";
+                       };
+
+                       i2c0: i2c@11000 {
+                               compatible = "marvell,mv64xxx-i2c";
+                               reg = <0x11000 0x20>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+                               timeout-ms = <1000>;
+                               clocks = <&coreclk 0>;
+                               status = "disabled";
+                       };
+
+                       i2c1: i2c@11100 {
+                               compatible = "marvell,mv64xxx-i2c";
+                               reg = <0x11100 0x20>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+                               timeout-ms = <1000>;
+                               clocks = <&coreclk 0>;
+                               status = "disabled";
+                       };
+
+                       i2c2: i2c@11200 {
+                               compatible = "marvell,mv64xxx-i2c";
+                               reg = <0x11200 0x20>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+                               timeout-ms = <1000>;
+                               clocks = <&coreclk 0>;
+                               status = "disabled";
+                       };
+
+                       i2c3: i2c@11300 {
+                               compatible = "marvell,mv64xxx-i2c";
+                               reg = <0x11300 0x20>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+                               timeout-ms = <1000>;
+                               clocks = <&coreclk 0>;
+                               status = "disabled";
+                       };
+
+                       uart0: serial@12000 {
+                               compatible = "snps,dw-apb-uart";
+                               reg = <0x12000 0x100>;
+                               reg-shift = <2>;
+                               interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+                               reg-io-width = <1>;
+                               clocks = <&coreclk 0>;
+                               status = "disabled";
+                       };
+
+                       uart1: serial@12100 {
+                               compatible = "snps,dw-apb-uart";
+                               reg = <0x12100 0x100>;
+                               reg-shift = <2>;
+                               interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+                               reg-io-width = <1>;
+                               clocks = <&coreclk 0>;
+                               status = "disabled";
+                       };
+
+                       uart2: serial@12200 {
+                               compatible = "snps,dw-apb-uart";
+                               reg = <0x12200 0x100>;
+                               reg-shift = <2>;
+                               interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+                               reg-io-width = <1>;
+                               clocks = <&coreclk 0>;
+                               status = "disabled";
+                       };
+
+                       uart3: serial@12300 {
+                               compatible = "snps,dw-apb-uart";
+                               reg = <0x12300 0x100>;
+                               reg-shift = <2>;
+                               interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+                               reg-io-width = <1>;
+                               clocks = <&coreclk 0>;
+                               status = "disabled";
+                       };
+
+                       pinctrl@18000 {
+                               i2c0_pins: i2c0-pins {
+                                       marvell,pins = "mpp2", "mpp3";
+                                       marvell,function = "i2c0";
+                               };
+
+                               uart0_pins: uart0-pins {
+                                       marvell,pins = "mpp0", "mpp1";
+                                       marvell,function = "ua0";
+                               };
+
+                               uart1_pins: uart1-pins {
+                                       marvell,pins = "mpp19", "mpp20";
+                                       marvell,function = "ua1";
+                               };
+
+                               spi1_pins: spi1-pins {
+                                       marvell,pins = "mpp56", "mpp57", "mpp58", "mpp59";
+                                       marvell,function = "spi1";
+                               };
+
+                               nand_pins: nand-pins {
+                                       marvell,pins = "mpp22", "mpp34", "mpp23", "mpp33",
+                                                      "mpp38", "mpp28", "mpp40", "mpp42",
+                                                      "mpp35", "mpp36", "mpp25", "mpp30",
+                                                      "mpp32";
+                                       marvell,function = "dev";
+                               };
+                       };
+
+                       system-controller@18200 {
+                               compatible = "marvell,armada-390-system-controller",
+                                            "marvell,armada-370-xp-system-controller";
+                               reg = <0x18200 0x100>;
+                       };
+
+                       gateclk: clock-gating-control@18220 {
+                               compatible = "marvell,armada-390-gating-clock";
+                               reg = <0x18220 0x4>;
+                               clocks = <&coreclk 0>;
+                               #clock-cells = <1>;
+                       };
+
+                       coreclk: mvebu-sar@18600 {
+                               compatible = "marvell,armada-390-core-clock";
+                               reg = <0x18600 0x04>;
+                               #clock-cells = <1>;
+                       };
+
+                       mbusc: mbus-controller@20000 {
+                               compatible = "marvell,mbus-controller";
+                               reg = <0x20000 0x100>, <0x20180 0x20>, <0x20250 0x8>;
+                       };
+
+                       mpic: interrupt-controller@20a00 {
+                               compatible = "marvell,mpic";
+                               reg = <0x20a00 0x2d0>, <0x21070 0x58>;
+                               #interrupt-cells = <1>;
+                               #size-cells = <1>;
+                               interrupt-controller;
+                               msi-controller;
+                               interrupts = <GIC_PPI 15 IRQ_TYPE_LEVEL_HIGH>;
+                       };
+
+                       timer@20300 {
+                               compatible = "marvell,armada-380-timer",
+                                            "marvell,armada-xp-timer";
+                               reg = <0x20300 0x30>, <0x21040 0x30>;
+                               interrupts-extended = <&gic  GIC_SPI  8 IRQ_TYPE_LEVEL_HIGH>,
+                                                     <&gic  GIC_SPI  9 IRQ_TYPE_LEVEL_HIGH>,
+                                                     <&gic  GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>,
+                                                     <&gic  GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
+                                                     <&mpic 5>,
+                                                     <&mpic 6>;
+                               clocks = <&coreclk 2>, <&coreclk 5>;
+                               clock-names = "nbclk", "fixed";
+                       };
+
+                       cpurst@20800 {
+                               compatible = "marvell,armada-370-cpu-reset";
+                               reg = <0x20800 0x10>;
+                       };
+
+                       pmsu@22000 {
+                               compatible = "marvell,armada-390-pmsu",
+                                            "marvell,armada-380-pmsu";
+                               reg = <0x22000 0x1000>;
+                       };
+
+                       xor@60800 {
+                               compatible = "marvell,orion-xor";
+                               reg = <0x60800 0x100
+                                      0x60a00 0x100>;
+                               clocks = <&gateclk 22>;
+                               status = "okay";
+
+                               xor00 {
+                                       interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+                                       dmacap,memcpy;
+                                       dmacap,xor;
+                               };
+                               xor01 {
+                                       interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+                                       dmacap,memcpy;
+                                       dmacap,xor;
+                                       dmacap,memset;
+                               };
+                       };
+
+                       xor@60900 {
+                               compatible = "marvell,orion-xor";
+                               reg = <0x60900 0x100
+                                      0x60b00 0x100>;
+                               clocks = <&gateclk 28>;
+                               status = "okay";
+
+                               xor10 {
+                                       interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+                                       dmacap,memcpy;
+                                       dmacap,xor;
+                               };
+                               xor11 {
+                                       interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+                                       dmacap,memcpy;
+                                       dmacap,xor;
+                                       dmacap,memset;
+                               };
+                       };
+
+                       flash@d0000 {
+                               compatible = "marvell,armada370-nand";
+                               reg = <0xd0000 0x54>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&coredivclk 0>;
+                               status = "disabled";
+                       };
+
+                       sdhci@d8000 {
+                               compatible = "marvell,armada-380-sdhci";
+                               reg = <0xd8000 0x1000>, <0xdc000 0x100>;
+                               interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&gateclk 17>;
+                               mrvl,clk-delay-cycles = <0x1F>;
+                               status = "disabled";
+                       };
+
+                       coredivclk: clock@e4250 {
+                               compatible = "marvell,armada-390-corediv-clock",
+                                            "marvell,armada-380-corediv-clock";
+                               reg = <0xe4250 0xc>;
+                               #clock-cells = <1>;
+                               clocks = <&mainpll>;
+                               clock-output-names = "nand";
+                       };
+               };
+
+               pcie-controller {
+                       compatible = "marvell,armada-370-pcie";
+                       status = "disabled";
+                       device_type = "pci";
+
+                       #address-cells = <3>;
+                       #size-cells = <2>;
+
+                       msi-parent = <&mpic>;
+                       bus-range = <0x00 0xff>;
+
+                       ranges =
+                              <0x82000000 0 0x80000 MBUS_ID(0xf0, 0x01) 0x80000 0 0x00002000
+                               0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000
+                               0x82000000 0 0x44000 MBUS_ID(0xf0, 0x01) 0x44000 0 0x00002000
+                               0x82000000 0 0x48000 MBUS_ID(0xf0, 0x01) 0x48000 0 0x00002000
+                               0x82000000 0x1 0     MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 0 MEM */
+                               0x81000000 0x1 0     MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 0 IO  */
+                               0x82000000 0x2 0     MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 1 MEM */
+                               0x81000000 0x2 0     MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 1 IO  */
+                               0x82000000 0x3 0     MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 2 MEM */
+                               0x81000000 0x3 0     MBUS_ID(0x04, 0xd0) 0 1 0 /* Port 2 IO  */
+                               0x82000000 0x4 0     MBUS_ID(0x04, 0xb8) 0 1 0 /* Port 3 MEM */
+                               0x81000000 0x4 0     MBUS_ID(0x04, 0xb0) 0 1 0 /* Port 3 IO  */>;
+
+                       /*
+                        * This port can be either x4 or x1. When
+                        * configured in x4 by the bootloader, then
+                        * pcie@4,0 is not available.
+                        */
+                       pcie@1,0 {
+                               device_type = "pci";
+                               assigned-addresses = <0x82000800 0 0x80000 0 0x2000>;
+                               reg = <0x0800 0 0 0 0>;
+                               #address-cells = <3>;
+                               #size-cells = <2>;
+                               #interrupt-cells = <1>;
+                               ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
+                                         0x81000000 0 0 0x81000000 0x1 0 1 0>;
+                               interrupt-map-mask = <0 0 0 0>;
+                               interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+                               marvell,pcie-port = <0>;
+                               marvell,pcie-lane = <0>;
+                               clocks = <&gateclk 8>;
+                               status = "disabled";
+                       };
+
+                       /* x1 port */
+                       pcie@2,0 {
+                               device_type = "pci";
+                               assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
+                               reg = <0x1000 0 0 0 0>;
+                               #address-cells = <3>;
+                               #size-cells = <2>;
+                               #interrupt-cells = <1>;
+                               ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
+                                         0x81000000 0 0 0x81000000 0x2 0 1 0>;
+                               interrupt-map-mask = <0 0 0 0>;
+                               interrupt-map = <0 0 0 0 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+                               marvell,pcie-port = <1>;
+                               marvell,pcie-lane = <0>;
+                               clocks = <&gateclk 5>;
+                               status = "disabled";
+                       };
+
+                       /* x1 port */
+                       pcie@3,0 {
+                               device_type = "pci";
+                               assigned-addresses = <0x82000800 0 0x44000 0 0x2000>;
+                               reg = <0x1800 0 0 0 0>;
+                               #address-cells = <3>;
+                               #size-cells = <2>;
+                               #interrupt-cells = <1>;
+                               ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0
+                                         0x81000000 0 0 0x81000000 0x3 0 1 0>;
+                               interrupt-map-mask = <0 0 0 0>;
+                               interrupt-map = <0 0 0 0 &gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+                               marvell,pcie-port = <2>;
+                               marvell,pcie-lane = <0>;
+                               clocks = <&gateclk 6>;
+                               status = "disabled";
+                       };
+
+                       /*
+                        * x1 port only available when pcie@1,0 is
+                        * configured as a x1 port
+                        */
+                       pcie@4,0 {
+                               device_type = "pci";
+                               assigned-addresses = <0x82000800 0 0x48000 0 0x2000>;
+                               reg = <0x2000 0 0 0 0>;
+                               #address-cells = <3>;
+                               #size-cells = <2>;
+                               #interrupt-cells = <1>;
+                               ranges = <0x82000000 0 0 0x82000000 0x4 0 1 0
+                                         0x81000000 0 0 0x81000000 0x4 0 1 0>;
+                               interrupt-map-mask = <0 0 0 0>;
+                               interrupt-map = <0 0 0 0 &gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+                               marvell,pcie-port = <3>;
+                               marvell,pcie-lane = <0>;
+                               clocks = <&gateclk 7>;
+                               status = "disabled";
+                       };
+               };
+       };
+
+       clocks {
+               /* 2 GHz fixed main PLL */
+               mainpll: mainpll {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <2000000000>;
+               };
+       };
+};
index c1fbab2436095e28a72542abbe3111e1609e573d..dfd782b44e506b6fd34a8efbade76b9f94c001c6 100644 (file)
@@ -59,7 +59,7 @@
        compatible = "marvell,rd-axpwifiap", "marvell,armadaxp-mv78230", "marvell,armadaxp", "marvell,armada-370-xp";
 
        chosen {
-               bootargs = "console=ttyS0,115200 earlyprintk";
+               stdout-path = "serial0:115200n8";
        };
 
        memory {
index 48bdafe17526ab7fa6960281cc2a7cdfdf2ee82e..1037824076189db621c58809ba539693be09e3e0 100644 (file)
@@ -64,7 +64,7 @@
        compatible = "marvell,axp-db", "marvell,armadaxp-mv78460", "marvell,armadaxp", "marvell,armada-370-xp";
 
        chosen {
-               bootargs = "console=ttyS0,115200 earlyprintk";
+               stdout-path = "serial0:115200n8";
        };
 
        memory {
index 206aebba01beea82a820163778bd4dc793cea05d..565227eacf06092d518d87cc2255a6e65093abaf 100644 (file)
@@ -65,7 +65,7 @@
        compatible = "marvell,axp-gp", "marvell,armadaxp-mv78460", "marvell,armadaxp", "marvell,armada-370-xp";
 
        chosen {
-               bootargs = "console=ttyS0,115200 earlyprintk";
+               stdout-path = "serial0:115200n8";
        };
 
        memory {
index 5fb3c8b687cfad7100f7a1827197cb7811dca39e..06a6a6c1fdf709446ed713fd189a1471e6509fd3 100644 (file)
@@ -54,8 +54,7 @@
                     "marvell,armadaxp", "marvell,armada-370-xp";
 
        chosen {
-               bootargs = "console=ttyS0,115200 earlyprintk";
-               stdout-path = &uart0;
+               stdout-path = "serial0:115200n8";
        };
 
        memory {
diff --git a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts
new file mode 100644 (file)
index 0000000..a2cf215
--- /dev/null
@@ -0,0 +1,393 @@
+/*
+ * Device Tree file for the Linksys WRT1900AC (Mamba).
+ *
+ * Note: this board is shipped with a new generation boot loader that
+ * remaps internal registers at 0xf1000000. Therefore, if earlyprintk
+ * is used, the CONFIG_DEBUG_MVEBU_UART0_ALTERNATE option should be
+ * used.
+ *
+ * Copyright (C) 2014 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * Based on armada-xp-axpwifiap.dts:
+ *
+ *     Copyright (C) 2013 Marvell
+ *
+ *     Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is 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.
+ *
+ * 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/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include "armada-xp-mv78230.dtsi"
+
+/ {
+       model = "Linksys WRT1900AC";
+       compatible = "linksys,mamba", "marvell,armadaxp-mv78230",
+                    "marvell,armadaxp", "marvell,armada-370-xp";
+
+       chosen {
+               bootargs = "console=ttyS0,115200";
+               stdout-path = &uart0;
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x00000000 0x00000000 0x00000000 0x10000000>; /* 256MB */
+       };
+
+       soc {
+               ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000
+                         MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000>;
+
+               pcie-controller {
+                       status = "okay";
+
+                       /* Etron EJ168 USB 3.0 controller */
+                       pcie@1,0 {
+                               /* Port 0, Lane 0 */
+                               status = "okay";
+                       };
+
+                       /* First mini-PCIe port */
+                       pcie@2,0 {
+                               /* Port 0, Lane 1 */
+                               status = "okay";
+                       };
+
+                       /* Second mini-PCIe port */
+                       pcie@3,0 {
+                               /* Port 0, Lane 3 */
+                               status = "okay";
+                       };
+               };
+
+               internal-regs {
+
+                       /* J10: VCC, NC, RX, NC, TX, GND  */
+                       serial@12000 {
+                               status = "okay";
+                       };
+
+                       sata@a0000 {
+                               nr-ports = <1>;
+                               status = "okay";
+                       };
+
+                       ethernet@70000 {
+                               pinctrl-0 = <&ge0_rgmii_pins>;
+                               pinctrl-names = "default";
+                               status = "okay";
+                               phy-mode = "rgmii-id";
+                               fixed-link {
+                                       speed = <1000>;
+                                       full-duplex;
+                               };
+                       };
+
+                       ethernet@74000 {
+                               pinctrl-0 = <&ge1_rgmii_pins>;
+                               pinctrl-names = "default";
+                               status = "okay";
+                               phy-mode = "rgmii-id";
+                               fixed-link {
+                                       speed = <1000>;
+                                       full-duplex;
+                               };
+                       };
+
+                       /* USB part of the eSATA/USB 2.0 port */
+                       usb@50000 {
+                               status = "okay";
+                       };
+
+                       i2c@11000 {
+                               status = "okay";
+                               clock-frequency = <100000>;
+
+                               tmp421@4c {
+                                       compatible = "ti,tmp421";
+                                       reg = <0x4c>;
+                               };
+
+                               tlc59116@68 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       #gpio-cells = <2>;
+                                       compatible = "ti,tlc59116";
+                                       reg = <0x68>;
+
+                                       wan_amber@0 {
+                                               label = "mamba:amber:wan";
+                                               reg = <0x0>;
+                                       };
+
+                                       wan_white@1 {
+                                               label = "mamba:white:wan";
+                                               reg = <0x1>;
+                                       };
+
+                                       wlan_2g@2 {
+                                               label = "mamba:white:wlan_2g";
+                                               reg = <0x2>;
+                                       };
+
+                                       wlan_5g@3 {
+                                               label = "mamba:white:wlan_5g";
+                                               reg = <0x3>;
+                                       };
+
+                                       esata@4 {
+                                               label = "mamba:white:esata";
+                                               reg = <0x4>;
+                                       };
+
+                                       usb2@5 {
+                                               label = "mamba:white:usb2";
+                                               reg = <0x5>;
+                                       };
+
+                                       usb3_1@6 {
+                                               label = "mamba:white:usb3_1";
+                                               reg = <0x6>;
+                                       };
+
+                                       usb3_2@7 {
+                                               label = "mamba:white:usb3_2";
+                                               reg = <0x7>;
+                                       };
+
+                                       wps_white@8 {
+                                               label = "mamba:white:wps";
+                                               reg = <0x8>;
+                                       };
+
+                                       wps_amber@9 {
+                                               label = "mamba:amber:wps";
+                                               reg = <0x9>;
+                                       };
+                               };
+                       };
+
+                       nand@d0000 {
+                               status = "okay";
+                               num-cs = <1>;
+                               marvell,nand-keep-config;
+                               marvell,nand-enable-arbiter;
+                               nand-on-flash-bbt;
+                               nand-ecc-strength = <4>;
+                               nand-ecc-step-size = <512>;
+
+                               partition@0 {
+                                       label = "u-boot";
+                                       reg = <0x0000000 0x100000>;  /* 1MB */
+                                       read-only;
+                               };
+
+                               partition@100000 {
+                                       label = "u_env";
+                                       reg = <0x100000 0x40000>;    /* 256KB */
+                               };
+
+                               partition@140000 {
+                                       label = "s_env";
+                                       reg = <0x140000 0x40000>;    /* 256KB */
+                               };
+
+                               partition@900000 {
+                                       label = "devinfo";
+                                       reg = <0x900000 0x100000>;   /* 1MB */
+                                       read-only;
+                               };
+
+                               /* kernel1 overlaps with rootfs1 by design */
+                               partition@a00000 {
+                                       label = "kernel1";
+                                       reg = <0xa00000 0x2800000>;  /* 40MB */
+                               };
+
+                               partition@d00000 {
+                                       label = "rootfs1";
+                                       reg = <0xd00000 0x2500000>;  /* 37MB */
+                               };
+
+                               /* kernel2 overlaps with rootfs2 by design */
+                               partition@3200000 {
+                                       label = "kernel2";
+                                       reg = <0x3200000 0x2800000>; /* 40MB */
+                               };
+
+                               partition@3500000 {
+                                       label = "rootfs2";
+                                       reg = <0x3500000 0x2500000>; /* 37MB */
+                               };
+
+                               /*
+                                * 38MB, last MB is for the BBT, not writable
+                                */
+                               partition@5a00000 {
+                                       label = "syscfg";
+                                       reg = <0x5a00000 0x2600000>;
+                               };
+
+                               /*
+                                * Unused area between "s_env" and "devinfo".
+                                * Moved here because otherwise the renumbered
+                                * partitions would break the bootloader
+                                * supplied bootargs
+                                */
+                               partition@180000 {
+                                       label = "unused_area";
+                                       reg = <0x180000 0x780000>;   /* 7.5MB */
+                               };
+                       };
+
+                       spi0: spi@10600 {
+                               status = "okay";
+
+                               spi-flash@0 {
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+                                       compatible = "everspin,mr25h256";
+                                       reg = <0>; /* Chip select 0 */
+                                       spi-max-frequency = <40000000>;
+                               };
+                       };
+               };
+       };
+
+       gpio_keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               pinctrl-0 = <&keys_pin>;
+               pinctrl-names = "default";
+
+               button@1 {
+                       label = "WPS";
+                       linux,code = <KEY_WPS_BUTTON>;
+                       gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>;
+               };
+
+               button@2 {
+                       label = "Factory Reset Button";
+                       linux,code = <KEY_RESTART>;
+                       gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>;
+               };
+       };
+
+       gpio-leds {
+               compatible = "gpio-leds";
+               pinctrl-0 = <&power_led_pin>;
+               pinctrl-names = "default";
+
+               power {
+                       label = "mamba:white:power";
+                       gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
+                       default-state = "on";
+               };
+       };
+
+       gpio_fan {
+               /* SUNON HA4010V4-0000-C99 */
+               compatible = "gpio-fan";
+               gpios = <&gpio0 24 0>;
+
+               gpio-fan,speed-map = <0    0
+                                     4500 1>;
+       };
+
+       dsa@0 {
+               compatible = "marvell,dsa";
+               #address-cells = <2>;
+               #size-cells = <0>;
+
+               dsa,ethernet = <&eth0>;
+               dsa,mii-bus = <&mdio>;
+
+               switch@0 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x0 0>;  /* MDIO address 0, switch 0 in tree */
+
+                       port@0 {
+                               reg = <0>;
+                               label = "lan4";
+                       };
+
+                       port@1 {
+                               reg = <1>;
+                               label = "lan3";
+                       };
+
+                       port@2 {
+                               reg = <2>;
+                               label = "lan2";
+                       };
+
+                       port@3 {
+                               reg = <3>;
+                               label = "lan1";
+                       };
+
+                       port@4 {
+                               reg = <4>;
+                               label = "internet";
+                       };
+
+                       port@5 {
+                               reg = <5>;
+                               label = "cpu";
+                       };
+               };
+       };
+};
+
+&pinctrl {
+
+       keys_pin: keys-pin {
+               marvell,pins = "mpp32", "mpp33";
+               marvell,function = "gpio";
+       };
+
+       power_led_pin: power-led-pin {
+               marvell,pins = "mpp40";
+               marvell,function = "gpio";
+       };
+
+       gpio_fan_pin: gpio-fan-pin {
+               marvell,pins = "mpp24";
+               marvell,function = "gpio";
+       };
+};
index 56f958eb1ede07fb379f051ef12385ed5d1164d9..f894bc83e957554a55a8a155cc0cdb0c1d1d0d0e 100644 (file)
@@ -52,7 +52,7 @@
        compatible = "marvell,axp-matrix", "marvell,armadaxp-mv78460", "marvell,armadaxp", "marvell,armada-370-xp";
 
        chosen {
-               bootargs = "console=ttyS0,115200 earlyprintk";
+               stdout-path = "serial0:115200n8";
        };
 
        memory {
index 4a7cbed79b0736f9c42670a6316bb4fadb37d398..8479fdc9e9c2468e072c3592528a263610c2acc1 100644 (file)
@@ -57,7 +57,6 @@
                gpio0 = &gpio0;
                gpio1 = &gpio1;
                gpio2 = &gpio2;
-               eth3 = &eth3;
        };
 
        cpus {
index 36ce63a96cc9007bf18de678d117bbd99a78b739..661d54c815802d1bb1d2e1fa31cb255d90caf12e 100644 (file)
@@ -57,7 +57,6 @@
                gpio0 = &gpio0;
                gpio1 = &gpio1;
                gpio2 = &gpio2;
-               eth3 = &eth3;
        };
 
 
index 99cb9a8401b40737287ae15dbe7e67c0ffb2619d..1516fc2627f99f0d068fbc2d96c897c9112dc0e7 100644 (file)
@@ -53,7 +53,7 @@
        compatible = "netgear,readynas-2120", "marvell,armadaxp-mv78230", "marvell,armadaxp", "marvell,armada-370-xp";
 
        chosen {
-               bootargs = "console=ttyS0,115200 earlyprintk";
+               stdout-path = "serial0:115200n8";
        };
 
        memory {
index 0c76d9f05fd0c2e006df84f3fe7671a8ed29b52b..e3b08fb959e5f8ffc27977fa85d05c70a4d60792 100644 (file)
@@ -54,7 +54,7 @@
        compatible = "plathome,openblocks-ax3-4", "marvell,armadaxp-mv78260", "marvell,armadaxp", "marvell,armada-370-xp";
 
        chosen {
-               bootargs = "console=ttyS0,115200 earlyprintk";
+               stdout-path = "serial0:115200n8";
        };
 
        memory {
index e9fb225169aaa7338e532006b7986779537da7ef..6063428fa6a0a8ca378d1a9f00b5689544947758 100644 (file)
@@ -67,8 +67,7 @@
                     "marvell,armadaxp", "marvell,armada-370-xp";
 
        chosen {
-               bootargs = "console=ttyS0,115200 earlyprintk";
-               stdout-path = &uart0;
+               stdout-path = "serial0:115200n8";
        };
 
        memory {
index 82917236a2fbfe99426b5a70127255848a917d6a..013d63f69e361e60bbe96466bec1883388155889 100644 (file)
@@ -57,7 +57,8 @@
        compatible = "marvell,armadaxp", "marvell,armada-370-xp";
 
        aliases {
-               eth2 = &eth2;
+               serial2 = &uart2;
+               serial3 = &uart3;
        };
 
        soc {
@@ -78,6 +79,7 @@
                                compatible = "marvell,aurora-system-cache";
                                reg = <0x08000 0x1000>;
                                cache-id-part = <0x100>;
+                               cache-level = <2>;
                                cache-unified;
                                wt-override;
                        };
                        cpuclk: clock-complex@18700 {
                                #clock-cells = <1>;
                                compatible = "marvell,armada-xp-cpu-clock";
-                               reg = <0x18700 0xA0>, <0x1c054 0x10>;
+                               reg = <0x18700 0x24>, <0x1c054 0x10>;
                                clocks = <&coreclk 1>;
                        };
 
-                       interrupt-controller@20000 {
+                       interrupt-controller@20a00 {
                              reg = <0x20a00 0x2d0>, <0x21070 0x58>;
                        };
 
index fec1fca2ad66c80ad3ce949d82741b235790c1ed..9991240b7438663d184b6fa31eb04efb36fc3bdc 100644 (file)
 
                        macb1: ethernet@f802c000 {
                                phy-mode = "rmii";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
                                status = "okay";
+
+                               ethernet-phy@1 {
+                                       reg = <0x1>;
+                               };
                        };
 
                        dbgu: serial@ffffee00 {
                                                        <AT91_PIOA 19 AT91_PERIPH_B AT91_PINCTRL_PULL_UP>;
                                        };
 
+                                       pinctrl_key_gpio: key_gpio_0 {
+                                               atmel,pins =
+                                                       <AT91_PIOE 29 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>;
+                                       };
+
                                        pinctrl_mmc0_cd: mmc0_cd {
                                                atmel,pins =
                                                        <AT91_PIOE 0 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>;
        gpio_keys {
                compatible = "gpio-keys";
 
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_key_gpio>;
+
                bp3 {
                        label = "PB_USER";
                        gpios = <&pioE 29 GPIO_ACTIVE_LOW>;
diff --git a/arch/arm/boot/dts/at91-sama5d4_xplained.dts b/arch/arm/boot/dts/at91-sama5d4_xplained.dts
new file mode 100644 (file)
index 0000000..c740e1a
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * at91-sama5d4_xplained.dts - Device Tree file for SAMA5D4 Xplained board
+ *
+ *  Copyright (C) 2015 Atmel,
+ *                2015 Josh Wu <josh.wu@atmel.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+/dts-v1/;
+#include "sama5d4.dtsi"
+
+/ {
+       model = "Atmel SAMA5D4 Xplained";
+       compatible = "atmel,sama5d4-xplained", "atmel,sama5d4", "atmel,sama5";
+
+       chosen {
+               bootargs = "console=ttyS0,115200 ignore_loglevel earlyprintk";
+       };
+
+       memory {
+               reg = <0x20000000 0x20000000>;
+       };
+
+       clocks {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               main_clock: clock@0 {
+                       compatible = "atmel,osc", "fixed-clock";
+                       clock-frequency = <12000000>;
+               };
+
+               slow_xtal {
+                       clock-frequency = <32768>;
+               };
+
+               main_xtal {
+                       clock-frequency = <12000000>;
+               };
+       };
+
+       ahb {
+               apb {
+                       spi0: spi@f8010000 {
+                               cs-gpios = <&pioC 3 0>, <0>, <0>, <0>;
+                               status = "okay";
+                               m25p80@0 {
+                                       compatible = "atmel,at25df321a";
+                                       spi-max-frequency = <50000000>;
+                                       reg = <0>;
+                               };
+                       };
+
+                       i2c0: i2c@f8014000 {
+                               status = "okay";
+                       };
+
+                       macb0: ethernet@f8020000 {
+                               phy-mode = "rmii";
+                               status = "okay";
+
+                               phy0: ethernet-phy@1 {
+                                       interrupt-parent = <&pioE>;
+                                       interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
+                                       reg = <1>;
+                               };
+                       };
+
+                       mmc1: mmc@fc000000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_mmc1_clk_cmd_dat0 &pinctrl_mmc1_dat1_3 &pinctrl_mmc1_cd>;
+                               status = "okay";
+                               slot@0 {
+                                       reg = <0>;
+                                       bus-width = <4>;
+                                       cd-gpios = <&pioE 3 0>;
+                               };
+                       };
+
+                       usart3: serial@fc00c000 {
+                               status = "okay";
+                       };
+
+                       usart4: serial@fc010000 {
+                               status = "okay";
+                       };
+
+                       adc0: adc@fc034000 {
+                               atmel,adc-vref = <3300>;
+                               status = "okay";
+                       };
+
+                       watchdog@fc068640 {
+                               status = "okay";
+                       };
+
+                       pinctrl@fc06a000 {
+                               board {
+                                       pinctrl_mmc1_cd: mmc1_cd {
+                                               atmel,pins =
+                                                       <AT91_PIOE 3 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>;
+                                       };
+                                       pinctrl_usba_vbus: usba_vbus {
+                                               atmel,pins =
+                                                       <AT91_PIOE 31 AT91_PERIPH_GPIO AT91_PINCTRL_DEGLITCH>;
+                                       };
+                                       pinctrl_key_gpio: key_gpio_0 {
+                                               atmel,pins =
+                                                       <AT91_PIOE 8 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>;
+                                       };
+                               };
+                       };
+               };
+
+               usb0: gadget@00400000 {
+                       atmel,vbus-gpio = <&pioE 31 GPIO_ACTIVE_HIGH>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_usba_vbus>;
+                       status = "okay";
+               };
+
+               usb1: ohci@00500000 {
+                       num-ports = <3>;
+                       atmel,vbus-gpio = <0
+                                          &pioE 11 GPIO_ACTIVE_HIGH
+                                          &pioE 14 GPIO_ACTIVE_HIGH
+                                         >;
+                       status = "okay";
+               };
+
+               usb2: ehci@00600000 {
+                       status = "okay";
+               };
+
+               nand0: nand@80000000 {
+                       nand-bus-width = <8>;
+                       nand-ecc-mode = "hw";
+                       nand-on-flash-bbt;
+                       atmel,has-pmecc;
+                       status = "okay";
+
+                       at91bootstrap@0 {
+                               label = "at91bootstrap";
+                               reg = <0x0 0x40000>;
+                       };
+
+                       bootloader@40000 {
+                               label = "bootloader";
+                               reg = <0x40000 0x80000>;
+                       };
+
+                       bootloaderenv@c0000 {
+                               label = "bootloader env";
+                               reg = <0xc0000 0xc0000>;
+                       };
+
+                       dtb@180000 {
+                               label = "device tree";
+                               reg = <0x180000 0x80000>;
+                       };
+
+                       kernel@200000 {
+                               label = "kernel";
+                               reg = <0x200000 0x600000>;
+                       };
+
+                       rootfs@800000 {
+                               label = "rootfs";
+                               reg = <0x800000 0x0f800000>;
+                       };
+               };
+       };
+
+       gpio_keys {
+               compatible = "gpio-keys";
+
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_key_gpio>;
+
+               pb_user1 {
+                       label = "pb_user1";
+                       gpios = <&pioE 8 GPIO_ACTIVE_HIGH>;
+                       linux,code = <0x100>;
+                       gpio-key,wakeup;
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               status = "okay";
+
+               d8 {
+                       label = "d8";
+                       gpios = <&pioD 30 GPIO_ACTIVE_HIGH>;
+                       status = "disabled";
+               };
+
+               d10 {
+                       label = "d10";
+                       gpios = <&pioE 15 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "heartbeat";
+               };
+       };
+};
index 9198b719d0ef24d0ab4bef18ca7fd67a61dfd1df..89ef4a540db583015c2825d453e867afd9195852 100644 (file)
                                };
                        };
 
+                       ssc0: ssc@f8008000 {
+                               status = "okay";
+                       };
+
                        spi0: spi@f8010000 {
                                cs-gpios = <&pioC 3 0>, <0>, <0>, <0>;
                                status = "okay";
 
                        i2c0: i2c@f8014000 {
                                status = "okay";
+
+                               wm8904: codec@1a {
+                                       compatible = "wlf,wm8904";
+                                       reg = <0x1a>;
+                                       clocks = <&pck2>;
+                                       clock-names = "mclk";
+                               };
                        };
 
                        macb0: ethernet@f8020000 {
                                                atmel,pins =
                                                        <AT91_PIOE 6 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>;
                                        };
+                                       pinctrl_pck2_as_audio_mck: pck2_as_audio_mck {
+                                               atmel,pins =
+                                                       <AT91_PIOB 10 AT91_PERIPH_B AT91_PINCTRL_NONE>;
+                                       };
                                        pinctrl_usba_vbus: usba_vbus {
                                                atmel,pins =
                                                        <AT91_PIOE 31 AT91_PERIPH_GPIO AT91_PINCTRL_DEGLITCH>;
 
        gpio_keys {
                compatible = "gpio-keys";
-               #address-cells = <1>;
-               #size-cells = <0>;
 
                pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_key_gpio>;
                        gpio-key,wakeup;
                };
        };
+
+       leds {
+               compatible = "gpio-leds";
+               status = "okay";
+
+               d8 {
+                       label = "d8";
+                       /* PE28, conflicts with usart4 rts pin */
+                       gpios = <&pioE 28 GPIO_ACTIVE_LOW>;
+               };
+
+               d9 {
+                       label = "d9";
+                       gpios = <&pioE 9 GPIO_ACTIVE_HIGH>;
+               };
+
+               d10 {
+                       label = "d10";
+                       gpios = <&pioE 8 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "heartbeat";
+               };
+       };
+
+       sound {
+               compatible = "atmel,asoc-wm8904";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_pck2_as_audio_mck>;
+
+               atmel,model = "wm8904 @ SAMA5D4EK";
+               atmel,audio-routing =
+                       "Headphone Jack", "HPOUTL",
+                       "Headphone Jack", "HPOUTR",
+                       "IN1L", "Line In Jack",
+                       "IN1R", "Line In Jack";
+
+               atmel,ssc-controller = <&ssc0>;
+               atmel,audio-codec = <&wm8904>;
+       };
 };
index 21c2b504f977d16088ce290386ba73ddb4333b6b..4fb333bd1f85f10dcce81e953cf232f1ab14c74f 100644 (file)
                        };
 
                        st: timer@fffffd00 {
-                               compatible = "atmel,at91rm9200-st";
+                               compatible = "atmel,at91rm9200-st", "syscon", "simple-mfd";
                                reg = <0xfffffd00 0x100>;
                                interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
+
+                               watchdog {
+                                       compatible = "atmel,at91rm9200-wdt";
+                               };
                        };
 
                        rtc: rtc@fffffe00 {
                        };
 
                        dbgu: serial@fffff200 {
-                               compatible = "atmel,at91rm9200-usart";
+                               compatible = "atmel,at91rm9200-dbgu", "atmel,at91rm9200-usart";
                                reg = <0xfffff200 0x200>;
                                interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
                                pinctrl-names = "default";
index 62d25b14deb8a6916ddbeb6116b25ba71a7e31ba..d88fe62a2b2e12e41aaeb8058d028b7fa89cd788 100644 (file)
                        };
 
                        dbgu: serial@fffff200 {
-                               compatible = "atmel,at91sam9260-usart";
+                               compatible = "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
                                reg = <0xfffff200 0x200>;
                                interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
                                pinctrl-names = "default";
index d55fdf2487ef53f7a3c68cded4e78fe42039f538..bf8d1856a55a55a3668bd69879df1ef2c8d1dd26 100644 (file)
                        };
 
                        dbgu: serial@fffff200 {
-                               compatible = "atmel,at91sam9260-usart";
+                               compatible = "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
                                reg = <0xfffff200 0x200>;
                                interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
                                pinctrl-names = "default";
index e4f61a979a5700a067c9795d370dc841450d713b..111889b556cf1e2f52ce002995c20a0e00db8914 100644 (file)
                        };
 
                        dbgu: serial@ffffee00 {
-                               compatible = "atmel,at91sam9260-usart";
+                               compatible = "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
                                reg = <0xffffee00 0x200>;
                                interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
                                pinctrl-names = "default";
index 17b879990914c8643bfc63cb98b634c112f4f454..a7da0dd0c98fa0af8d05ad545660aba426962c30 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include "at91sam9x5.dtsi"
+#include "at91sam9x5_isi.dtsi"
 #include "at91sam9x5_usart3.dtsi"
 #include "at91sam9x5_macb0.dtsi"
 
index 1e4c49c584d38a5115b817efc57f3934681e011e..707fd4ea58f5d425bce8df2f2097f31ca0c2ae20 100644 (file)
 
        ahb {
                apb {
+                       spi0: spi@f0000000 {
+                               status = "disabled";
+                       };
+
+                       mmc1: mmc@f000c000 {
+                               status = "disabled";
+                       };
+
+                       i2c0: i2c@f8010000 {
+                               ov2640: camera@0x30 {
+                                       status = "okay";
+                               };
+                       };
+
                        macb0: ethernet@f802c000 {
                                phy-mode = "rmii";
                                status = "okay";
                        };
+
+                       isi: isi@f8048000 {
+                               status = "okay";
+                       };
                };
        };
 };
index 8ec05b11298a536b07c2c48586d6badcdcfaf9cd..70e59c5ceb2f7a56c5bd7e35d0cc9b34cf6a06a4 100644 (file)
                        };
 
                        dbgu: serial@ffffee00 {
-                               compatible = "atmel,at91sam9260-usart";
+                               compatible = "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
                                reg = <0xffffee00 0x200>;
                                interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
                                pinctrl-names = "default";
index 0c53a375ba99d214c1c0b5eabd85e77ec0cc72e6..a9e35dfc12d9d5a763e4484f8a331806da13ad63 100644 (file)
                        };
 
                        dbgu: serial@fffff200 {
-                               compatible = "atmel,at91sam9260-usart";
+                               compatible = "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
                                reg = <0xfffff200 0x200>;
                                interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
                                pinctrl-names = "default";
                                clocks = <&pwm_clk>;
                                status = "disabled";
                        };
+
+                       usb1: gadget@f803c000 {
+                               compatible = "atmel,at91sam9260-udc";
+                               reg = <0xf803c000 0x4000>;
+                               interrupts = <23 IRQ_TYPE_LEVEL_HIGH 2>;
+                               clocks = <&udphs_clk>, <&udpck>;
+                               clock-names = "pclk", "hclk";
+                               status = "disabled";
+                       };
                };
 
                nand0: nand@40000000 {
index 9575c0d895c919e0da00288192981ea299713f3e..6e067c8a350252de0d2cd66fd580d94aba0bda59 100644 (file)
                                                        <AT91_PIOB 10 AT91_PERIPH_B AT91_PINCTRL_NONE>;
                                        };
                                };
+
+                               usb1 {
+                                       pinctrl_usb1_vbus_sense: usb1_vbus_sense {
+                                               atmel,pins =
+                                                       <AT91_PIOB 16 AT91_PERIPH_GPIO AT91_PINCTRL_DEGLITCH>;  /* PB16 gpio usb vbus sense, no pull up and deglitch */
+                                       };
+                               };
                        };
 
                        spi0: spi@f0000000 {
                                };
                        };
 
+                       usb1: gadget@f803c000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_usb1_vbus_sense>;
+                               atmel,vbus-gpio = <&pioB 16 GPIO_ACTIVE_HIGH>;
+                               status = "okay";
+                       };
+
                        watchdog@fffffe40 {
                                status = "okay";
                        };
+
+                       rtc@fffffeb0 {
+                               status = "okay";
+                       };
                };
 
                nand0: nand@40000000 {
index 40f645b8fe25699d51904e5bdcaba8251375686a..ebfd5ce9cb3867d52c821ca075906b57be86abe8 100644 (file)
                        };
 
                        dbgu: serial@fffff200 {
-                               compatible = "atmel,at91sam9260-usart";
+                               compatible = "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
                                reg = <0xfffff200 0x200>;
                                interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
                                pinctrl-names = "default";
index d221179d0f1aad8aaccde552f74962a3009c6274..3aa56ae3410a5f96692df4d0f9f04238e2c06469 100644 (file)
                        };
 
                        dbgu: serial@fffff200 {
-                               compatible = "atmel,at91sam9260-usart";
+                               compatible = "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
                                reg = <0xfffff200 0x200>;
                                interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
                                pinctrl-names = "default";
index 98bc877a68ef0d697f46f3e43fe83fef6c1d7d0a..8fc45ca4dcb58a0d8d2e7a086e7437df330b6259 100644 (file)
 / {
        ahb {
                apb {
+                       pinctrl@fffff400 {
+                               isi {
+                                       pinctrl_isi_data_0_7: isi-0-data-0-7 {
+                                               atmel,pins =
+                                                       <AT91_PIOC 0 AT91_PERIPH_B AT91_PINCTRL_NONE    /* ISI_D0, conflicts with LCDDAT0 */
+                                                       AT91_PIOC 1 AT91_PERIPH_B AT91_PINCTRL_NONE     /* ISI_D1, conflicts with LCDDAT1 */
+                                                       AT91_PIOC 2 AT91_PERIPH_B AT91_PINCTRL_NONE     /* ISI_D2, conflicts with LCDDAT2 */
+                                                       AT91_PIOC 3 AT91_PERIPH_B AT91_PINCTRL_NONE     /* ISI_D3, conflicts with LCDDAT3 */
+                                                       AT91_PIOC 4 AT91_PERIPH_B AT91_PINCTRL_NONE     /* ISI_D4, conflicts with LCDDAT4 */
+                                                       AT91_PIOC 5 AT91_PERIPH_B AT91_PINCTRL_NONE     /* ISI_D5, conflicts with LCDDAT5 */
+                                                       AT91_PIOC 6 AT91_PERIPH_B AT91_PINCTRL_NONE     /* ISI_D6, conflicts with LCDDAT6 */
+                                                       AT91_PIOC 7 AT91_PERIPH_B AT91_PINCTRL_NONE     /* ISI_D7, conflicts with LCDDAT7 */
+                                                       AT91_PIOC 12 AT91_PERIPH_B AT91_PINCTRL_NONE    /* ISI_PCK, conflicts with LCDDAT12 */
+                                                       AT91_PIOC 14 AT91_PERIPH_B AT91_PINCTRL_NONE    /* ISI_HSYNC, conflicts with LCDDAT14 */
+                                                       AT91_PIOC 13 AT91_PERIPH_B AT91_PINCTRL_NONE>;  /* ISI_VSYNC, conflicts with LCDDAT13 */
+                                       };
+
+                                       pinctrl_isi_data_8_9: isi-0-data-8-9 {
+                                               atmel,pins =
+                                                       <AT91_PIOC 8 AT91_PERIPH_B AT91_PINCTRL_NONE    /* ISI_D8, conflicts with LCDDAT8 */
+                                                       AT91_PIOC 9 AT91_PERIPH_B AT91_PINCTRL_NONE>;   /* ISI_D9, conflicts with LCDDAT9 */
+                                       };
+
+                                       pinctrl_isi_data_10_11: isi-0-data-10-11 {
+                                               atmel,pins =
+                                                       <AT91_PIOC 10 AT91_PERIPH_B AT91_PINCTRL_NONE   /* ISI_D10, conflicts with LCDDAT10 */
+                                                       AT91_PIOC 11 AT91_PERIPH_B AT91_PINCTRL_NONE>;  /* ISI_D11, conflicts with LCDDAT11 */
+                                       };
+                               };
+                       };
+
                        pmc: pmc@fffffc00 {
                                periphck {
                                        isi_clk: isi_clk {
                                        };
                                };
                        };
+
+                       isi: isi@f8048000 {
+                               compatible = "atmel,at91sam9g45-isi";
+                               reg = <0xf8048000 0x4000>;
+                               interrupts = <25 IRQ_TYPE_LEVEL_HIGH 5>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_isi_data_0_7>;
+                               clocks = <&isi_clk>;
+                               clock-names = "isi_clk";
+                               status = "disabled";
+                               port {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                               };
+                       };
                };
        };
 };
index 229d6c24a9c408c37d5dcb46b279d457768b173d..26112ebd15fc4e896d576932b330b846fc4cc397 100644 (file)
                                        };
                                };
                        };
+
+                       rtc@fffffeb0 {
+                               status = "okay";
+                       };
                };
 
                nand0: nand@40000000 {
index bd16bd360272ae212cc0a86c10dde6b697c3c31b..cc83a37a7311ba55e2e717ad789d040f65fe98f1 100644 (file)
                                status = "okay";
                        };
 
+                       isi: isi@f8048000 {
+                               status = "disabled";
+                               port {
+                                       isi_0: endpoint@0 {
+                                               remote-endpoint = <&ov2640_0>;
+                                               bus-width = <8>;
+                                       };
+                               };
+                       };
+
                        i2c0: i2c@f8010000 {
                                status = "okay";
 
                                        compatible = "wm8731";
                                        reg = <0x1a>;
                                };
+
+                               ov2640: camera@0x30 {
+                                       compatible = "ovti,ov2640";
+                                       reg = <0x30>;
+                                       pinctrl-names = "default";
+                                       pinctrl-0 = <&pinctrl_pck0_as_isi_mck &pinctrl_sensor_power &pinctrl_sensor_reset>;
+                                       resetb-gpios = <&pioA 7 GPIO_ACTIVE_LOW>;
+                                       pwdn-gpios = <&pioA 13 GPIO_ACTIVE_HIGH>;
+                                       clocks = <&pck0>;
+                                       clock-names = "xvclk";
+                                       assigned-clocks = <&pck0>;
+                                       assigned-clock-rates = <25000000>;
+                                       status = "disabled";
+
+                                       port {
+                                               ov2640_0: endpoint {
+                                                       remote-endpoint = <&isi_0>;
+                                                       bus-width = <8>;
+                                               };
+                                       };
+                               };
                        };
 
                        pinctrl@fffff400 {
+                               camera_sensor {
+                                       pinctrl_pck0_as_isi_mck: pck0_as_isi_mck-0 {
+                                               atmel,pins =
+                                                       <AT91_PIOC 15 AT91_PERIPH_C AT91_PINCTRL_NONE>; /* ISI_MCK */
+                                       };
+
+                                       pinctrl_sensor_power: sensor_power-0 {
+                                               atmel,pins =
+                                                       <AT91_PIOA 13 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>;
+                                       };
+
+                                       pinctrl_sensor_reset: sensor_reset-0 {
+                                               atmel,pins =
+                                                       <AT91_PIOA 7 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>;
+                                       };
+                               };
+
                                mmc0 {
                                        pinctrl_board_mmc0: mmc0-board {
                                                atmel,pins =
index ff5fb6ab0b9748dbecd27fd7432c4f8306f5221d..7b52c33ea69aedefa667a9a96460a6d5cb4fefc4 100644 (file)
 
        /include/ "bcm-cygnus-clock.dtsi"
 
+       pinctrl: pinctrl@0x0301d0c8 {
+               compatible = "brcm,cygnus-pinmux";
+               reg = <0x0301d0c8 0x30>,
+                     <0x0301d24c 0x2c>;
+       };
+
+       gpio_crmu: gpio@03024800 {
+               compatible = "brcm,cygnus-crmu-gpio";
+               reg = <0x03024800 0x50>,
+                     <0x03024008 0x18>;
+               #gpio-cells = <2>;
+               gpio-controller;
+       };
+
+       gpio_ccm: gpio@1800a000 {
+               compatible = "brcm,cygnus-ccm-gpio";
+               reg = <0x1800a000 0x50>,
+                     <0x0301d164 0x20>;
+               #gpio-cells = <2>;
+               gpio-controller;
+               interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-controller;
+       };
+
+       gpio_asiu: gpio@180a5000 {
+               compatible = "brcm,cygnus-asiu-gpio";
+               reg = <0x180a5000 0x668>;
+               #gpio-cells = <2>;
+               gpio-controller;
+
+               pinmux = <&pinctrl>;
+
+               interrupt-controller;
+               interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
+       };
+
        amba {
                #address-cells = <1>;
                #size-cells = <1>;
                status = "disabled";
        };
 
+       pcie0: pcie@18012000 {
+               compatible = "brcm,iproc-pcie";
+               reg = <0x18012000 0x1000>;
+
+               #interrupt-cells = <1>;
+               interrupt-map-mask = <0 0 0 0>;
+               interrupt-map = <0 0 0 0 &gic GIC_SPI 100 IRQ_TYPE_NONE>;
+
+               linux,pci-domain = <0>;
+
+               bus-range = <0x00 0xff>;
+
+               #address-cells = <3>;
+               #size-cells = <2>;
+               device_type = "pci";
+               ranges = <0x81000000 0 0          0x28000000 0 0x00010000
+                         0x82000000 0 0x20000000 0x20000000 0 0x04000000>;
+
+               status = "disabled";
+       };
+
+       pcie1: pcie@18013000 {
+               compatible = "brcm,iproc-pcie";
+               reg = <0x18013000 0x1000>;
+
+               #interrupt-cells = <1>;
+               interrupt-map-mask = <0 0 0 0>;
+               interrupt-map = <0 0 0 0 &gic GIC_SPI 106 IRQ_TYPE_NONE>;
+
+               linux,pci-domain = <1>;
+
+               bus-range = <0x00 0xff>;
+
+               #address-cells = <3>;
+               #size-cells = <2>;
+               device_type = "pci";
+               ranges = <0x81000000 0 0          0x48000000 0 0x00010000
+                         0x82000000 0 0x40000000 0x40000000 0 0x04000000>;
+
+               status = "disabled";
+       };
+
        uart0: serial@18020000 {
                compatible = "snps,dw-apb-uart";
                reg = <0x18020000 0x100>;
index f18c9d9b2f2c78c616e859574626fa62489e7aa1..2ed9e5794785fb9a8f3e08228fb999e245c4d8de 100644 (file)
                power0 {
                        label = "bcm53xx:green:power";
                        gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
+                       linux,default-trigger = "default-on";
                };
 
                power1 {
                        label = "bcm53xx:amber:power";
                        gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-on";
+                       linux,default-trigger = "default-off";
                };
 
                usb {
diff --git a/arch/arm/boot/dts/bcm4709-netgear-r8000.dts b/arch/arm/boot/dts/bcm4709-netgear-r8000.dts
new file mode 100644 (file)
index 0000000..ea26dd3
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Broadcom BCM470X / BCM5301X ARM platform code.
+ * DTS for Netgear R8000
+ *
+ * Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+/dts-v1/;
+
+#include "bcm4708.dtsi"
+
+/ {
+       compatible = "netgear,r8000", "brcm,bcm4709", "brcm,bcm4708";
+       model = "Netgear R8000 (BCM4709)";
+
+       chosen {
+               bootargs = "console=ttyS0,115200";
+       };
+
+       memory {
+               reg = <0x00000000 0x08000000>;
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               power0 {
+                       label = "bcm53xx:white:power";
+                       gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "default-on";
+               };
+
+               power1 {
+                       label = "bcm53xx:amber:power";
+                       gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "default-off";
+               };
+
+               5ghz-1 {
+                       label = "bcm53xx:white:5ghz-1";
+                       gpios = <&chipcommon 12 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "default-off";
+               };
+
+               2ghz {
+                       label = "bcm53xx:white:2ghz";
+                       gpios = <&chipcommon 13 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "default-off";
+               };
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               rfkill {
+                       label = "WiFi";
+                       linux,code = <KEY_RFKILL>;
+                       gpios = <&chipcommon 4 GPIO_ACTIVE_LOW>;
+               };
+
+               wps {
+                       label = "WPS";
+                       linux,code = <KEY_WPS_BUTTON>;
+                       gpios = <&chipcommon 5 GPIO_ACTIVE_LOW>;
+               };
+
+               restart {
+                       label = "Reset";
+                       linux,code = <KEY_RESTART>;
+                       gpios = <&chipcommon 6 GPIO_ACTIVE_LOW>;
+               };
+       };
+};
index 0ca0f4e523d0adf4d6d2eac08482544f60dcbd67..39ac7840d7eebfafd5be58dc2b3fa5c5b9d6c63b 100644 (file)
@@ -76,7 +76,7 @@
                        reg-shift = <2>;
                        reg-io-width = <4>;
                        interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
-                       clock-frequency = <0x4d3f640>;
+                       clock-frequency = <81000000>;
                };
 
                sun_top_ctrl: syscon@404000 {
                                     "syscon";
                        reg = <0x452000 0x100>;
                };
+
+               irq0_intc: interrupt-controller@40a780 {
+                       compatible = "brcm,bcm7120-l2-intc";
+                       interrupt-parent = <&gic>;
+                       #interrupt-cells = <1>;
+                       reg = <0x40a780 0x8>;
+                       interrupt-controller;
+                       interrupts = <GIC_SPI 0x45 0x0>,
+                                    <GIC_SPI 0x43 0x0>;
+                       brcm,int-map-mask = <0x25c>, <0x7000000>;
+                       brcm,int-fwd-mask = <0x70000>;
+               };
        };
 
        smpboot {
index d2ee952805488df5c410fad41ccbf2d66d4d45e7..7db484323fd62dc7ed9a988e6a3008597f59467f 100644 (file)
@@ -33,6 +33,7 @@
 /dts-v1/;
 
 #include "bcm-cygnus.dtsi"
+#include "dt-bindings/input/input.h"
 
 / {
        model = "Cygnus Enterprise Phone (BCM911360_ENTPHN)";
        uart3: serial@18023000 {
                status = "okay";
        };
+
+       gpio_keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               hook {
+                       label = "HOOK";
+                       linux,code = <KEY_O>;
+                       gpios = <&gpio_asiu 48 0>;
+               };
+       };
 };
index f1bb36f3975ca3c356639d3c58424a613eab5257..c9eb8565eac5be2b3d0299218919b4a8a918bd94 100644 (file)
                bootargs = "console=ttyS0,115200";
        };
 
+       pcie0: pcie@18012000 {
+               status = "okay";
+       };
+
+       pcie1: pcie@18013000 {
+               status = "okay";
+       };
+
        uart3: serial@18023000 {
                status = "okay";
        };
diff --git a/arch/arm/boot/dts/bcm958305k.dts b/arch/arm/boot/dts/bcm958305k.dts
new file mode 100644 (file)
index 0000000..56b429a
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ *  BSD LICENSE
+ *
+ *  Copyright(c) 2015 Broadcom Corporation.  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in
+ *      the documentation and/or other materials provided with the
+ *      distribution.
+ *    * Neither the name of Broadcom Corporation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/dts-v1/;
+
+#include "bcm-cygnus.dtsi"
+
+/ {
+       model = "Cygnus Wireless Audio (BCM958305K)";
+       compatible = "brcm,bcm58305", "brcm,cygnus";
+
+       aliases {
+               serial0 = &uart3;
+       };
+
+       chosen {
+               stdout-path = &uart3;
+               bootargs = "console=ttyS0,115200";
+       };
+
+       uart3: serial@18023000 {
+               status = "okay";
+       };
+};
index afe678f6d2e950308b74e403d26a3cc326c2b760..169a85578fc93e31927c10ce381b9407a484fe38 100644 (file)
 &dm816x_pinmux {
        mcspi1_pins: pinmux_mcspi1_pins {
                pinctrl-single,pins = <
-                       DM816X_IOPAD(0x0a94, PIN_INPUT | MUX_MODE0)     /* SPI_SCLK */
-                       DM816X_IOPAD(0x0a98, PIN_OUTPUT | MUX_MODE0)    /* SPI_SCS0 */
-                       DM816X_IOPAD(0x0aa8, PIN_INPUT | MUX_MODE0)     /* SPI_D0 */
-                       DM816X_IOPAD(0x0aac, PIN_INPUT | MUX_MODE0)     /* SPI_D1 */
+                       DM816X_IOPAD(0x0a94, MUX_MODE0)                 /* SPI_SCLK */
+                       DM816X_IOPAD(0x0a98, MUX_MODE0)                 /* SPI_SCS0 */
+                       DM816X_IOPAD(0x0aa8, MUX_MODE0)                 /* SPI_D0 */
+                       DM816X_IOPAD(0x0aac, MUX_MODE0)                 /* SPI_D1 */
                >;
        };
 
 
        usb0_pins: pinmux_usb0_pins {
                pinctrl-single,pins = <
-                       DM816X_IOPAD(0x0d00, MUX_MODE0)                 /* USB0_DRVVBUS */
+                       DM816X_IOPAD(0x0d04, MUX_MODE0)                 /* USB0_DRVVBUS */
                >;
        };
 
-       usb1_pins: pinmux_usb0_pins {
+       usb1_pins: pinmux_usb1_pins {
                pinctrl-single,pins = <
-                       DM816X_IOPAD(0x0d04, MUX_MODE0)                 /* USB1_DRVVBUS */
+                       DM816X_IOPAD(0x0d08, MUX_MODE0)                 /* USB1_DRVVBUS */
                >;
        };
 };
index f35715bc69922591577299730ecf1a105c6642de..de8427be830a32e24a01ace97f11303435528b7b 100644 (file)
                                mentor,num-eps = <16>;
                                mentor,ram-bits = <12>;
                                mentor,power = <500>;
+
+                               dmas = <&cppi41dma  0 0 &cppi41dma  1 0
+                                       &cppi41dma  2 0 &cppi41dma  3 0
+                                       &cppi41dma  4 0 &cppi41dma  5 0
+                                       &cppi41dma  6 0 &cppi41dma  7 0
+                                       &cppi41dma  8 0 &cppi41dma  9 0
+                                       &cppi41dma 10 0 &cppi41dma 11 0
+                                       &cppi41dma 12 0 &cppi41dma 13 0
+                                       &cppi41dma 14 0 &cppi41dma  0 1
+                                       &cppi41dma  1 1 &cppi41dma  2 1
+                                       &cppi41dma  3 1 &cppi41dma  4 1
+                                       &cppi41dma  5 1 &cppi41dma  6 1
+                                       &cppi41dma  7 1 &cppi41dma  8 1
+                                       &cppi41dma  9 1 &cppi41dma 10 1
+                                       &cppi41dma 11 1 &cppi41dma 12 1
+                                       &cppi41dma 13 1 &cppi41dma 14 1>;
+                               dma-names =
+                                       "rx1", "rx2", "rx3", "rx4", "rx5", "rx6", "rx7",
+                                       "rx8", "rx9", "rx10", "rx11", "rx12", "rx13",
+                                       "rx14", "rx15",
+                                       "tx1", "tx2", "tx3", "tx4", "tx5", "tx6", "tx7",
+                                       "tx8", "tx9", "tx10", "tx11", "tx12", "tx13",
+                                       "tx14", "tx15";
                        };
 
                        usb1: usb@47401800 {
                                mentor,num-eps = <16>;
                                mentor,ram-bits = <12>;
                                mentor,power = <500>;
+
+                               dmas = <&cppi41dma 15 0 &cppi41dma 16 0
+                                       &cppi41dma 17 0 &cppi41dma 18 0
+                                       &cppi41dma 19 0 &cppi41dma 20 0
+                                       &cppi41dma 21 0 &cppi41dma 22 0
+                                       &cppi41dma 23 0 &cppi41dma 24 0
+                                       &cppi41dma 25 0 &cppi41dma 26 0
+                                       &cppi41dma 27 0 &cppi41dma 28 0
+                                       &cppi41dma 29 0 &cppi41dma 15 1
+                                       &cppi41dma 16 1 &cppi41dma 17 1
+                                       &cppi41dma 18 1 &cppi41dma 19 1
+                                       &cppi41dma 20 1 &cppi41dma 21 1
+                                       &cppi41dma 22 1 &cppi41dma 23 1
+                                       &cppi41dma 24 1 &cppi41dma 25 1
+                                       &cppi41dma 26 1 &cppi41dma 27 1
+                                       &cppi41dma 28 1 &cppi41dma 29 1>;
+                               dma-names =
+                                       "rx1", "rx2", "rx3", "rx4", "rx5", "rx6", "rx7",
+                                       "rx8", "rx9", "rx10", "rx11", "rx12", "rx13",
+                                       "rx14", "rx15",
+                                       "tx1", "tx2", "tx3", "tx4", "tx5", "tx6", "tx7",
+                                       "tx8", "tx9", "tx10", "tx11", "tx12", "tx13",
+                                       "tx14", "tx15";
+                       };
+
+                       cppi41dma: dma-controller@47402000 {
+                               compatible = "ti,am3359-cppi41";
+                               reg =  <0x47400000 0x1000
+                                       0x47402000 0x1000
+                                       0x47403000 0x1000
+                                       0x47404000 0x4000>;
+                               reg-names = "glue", "controller", "scheduler", "queuemgr";
+                               interrupts = <17>;
+                               interrupt-names = "glue";
+                               #dma-cells = <2>;
+                               #dma-channels = <30>;
+                               #dma-requests = <256>;
                        };
                };
 
index a5441d5482a63a0a9203f3333b96c87ec1912b11..9ad829523a1350d59bcc795286459d8dfc6c133e 100644 (file)
@@ -1,5 +1,8 @@
 /include/ "skeleton.dtsi"
 
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
 #define MBUS_ID(target,attributes) (((target) << 24) | ((attributes) << 16))
 
 / {
@@ -61,7 +64,7 @@
                                  0x82000000 0x2 0x0 MBUS_ID(0x08, 0xe8) 0 1 0   /* Port 1.0 Mem */
                                  0x81000000 0x2 0x0 MBUS_ID(0x08, 0xe0) 0 1 0>; /* Port 1.0 I/O */
 
-                       pcie-port@0 {
+                       pcie0: pcie-port@0 {
                                device_type = "pci";
                                status = "disabled";
                                assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
@@ -79,7 +82,7 @@
                                interrupt-map = <0 0 0 0 &intc 16>;
                        };
 
-                       pcie-port@1 {
+                       pcie1: pcie-port@1 {
                                device_type = "pci";
                                status = "disabled";
                                assigned-addresses = <0x82002800 0 0x80000 0 0x2000>;
 
                        uart2: serial@12200 {
                                compatible = "ns16550a";
-                               reg = <0x12000 0x100>;
+                               reg = <0x12200 0x100>;
                                reg-shift = <2>;
                                interrupts = <9>;
                                clocks = <&core_clk 0>;
 
                        uart3: serial@12300 {
                                compatible = "ns16550a";
-                               reg = <0x12100 0x100>;
+                               reg = <0x12300 0x100>;
                                reg-shift = <2>;
                                interrupts = <10>;
                                clocks = <&core_clk 0>;
                                        marvell,function = "gpio";
                                };
 
+                               pmx_pcie1_clkreq: pmx-pcie1-clkreq {
+                                       marvell,pins = "mpp9";
+                                       marvell,function = "pex1";
+                               };
+
                                pmx_gpio_10: pmx-gpio-10 {
                                        marvell,pins = "mpp10";
                                        marvell,function = "gpio";
                                        marvell,function = "gpio";
                                };
 
+                               pmx_pcie0_clkreq: pmx-pcie0-clkreq {
+                                       marvell,pins = "mpp11";
+                                       marvell,function = "pex0";
+                               };
+
                                pmx_gpio_12: pmx-gpio-12 {
                                        marvell,pins = "mpp12";
                                        marvell,function = "gpio";
                                        marvell,function = "gpio";
                                };
 
+                               pmx_spi1_4_7: pmx-spi1-4-7 {
+                                       marvell,pins = "mpp4", "mpp5",
+                                               "mpp6", "mpp7";
+                                       marvell,function = "spi1";
+                               };
+
+                               pmx_spi1_20_23: pmx-spi1-20-23 {
+                                       marvell,pins = "mpp20", "mpp21",
+                                               "mpp22", "mpp23";
+                                       marvell,function = "spi1";
+                               };
+
                                pmx_uart1: pmx-uart1 {
                                        marvell,pins = "mpp_uart1";
                                        marvell,function = "uart1";
                                        marvell,pins = "mpp_nand";
                                        marvell,function = "gpo";
                                };
+
+                               pmx_i2c1: pmx-i2c1 {
+                                       marvell,pins = "mpp17", "mpp19";
+                                       marvell,function = "twsi";
+                               };
+
+                               pmx_i2c2: pmx-i2c2 {
+                                       marvell,pins = "mpp_audio1";
+                                       marvell,function = "twsi";
+                               };
+
+                               pmx_ssp_i2c2: pmx-ssp-i2c2 {
+                                       marvell,pins = "mpp_audio1";
+                                       marvell,function = "ssp/twsi";
+                               };
+
+                               pmx_i2cmux_0: pmx-i2cmux-0 {
+                                       marvell,pins = "twsi";
+                                       marvell,function = "twsi-opt1";
+                               };
+
+                               pmx_i2cmux_1: pmx-i2cmux-1 {
+                                       marvell,pins = "twsi";
+                                       marvell,function = "twsi-opt2";
+                               };
+
+                               pmx_i2cmux_2: pmx-i2cmux-2 {
+                                       marvell,pins = "twsi";
+                                       marvell,function = "twsi-opt3";
+                               };
                        };
 
                        core_clk: core-clocks@d0214 {
index b1bd06c6c2a801ee9c647cb63483430b8be60c44..aa465904f6cc420ecad93f006bc5e622d8e70b36 100644 (file)
        };
 };
 
+&omap_dwc3_1 {
+       extcon = <&extcon_usb1>;
+};
+
+&omap_dwc3_2 {
+       extcon = <&extcon_usb2>;
+};
+
 &usb1 {
        dr_mode = "peripheral";
        pinctrl-names = "default";
index a0afce7ad482cab69ce4c3935ef59536dd41c9d2..5332b57b4950dbd61fac6ef7cb112c4cd44cffa7 100644 (file)
                interrupts-extended = <&crossbar_mpu GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
                                      <&wakeupgen GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
 
-               prm: prm@4ae06000 {
-                       compatible = "ti,dra7-prm";
-                       reg = <0x4ae06000 0x3000>;
-                       interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+               l4_cfg: l4@4a000000 {
+                       compatible = "ti,dra7-l4-cfg", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0 0x4a000000 0x22c000>;
 
-                       prm_clocks: clocks {
+                       scm: scm@2000 {
+                               compatible = "ti,dra7-scm-core", "simple-bus";
+                               reg = <0x2000 0x2000>;
                                #address-cells = <1>;
-                               #size-cells = <0>;
+                               #size-cells = <1>;
+                               ranges = <0 0x2000 0x2000>;
+
+                               scm_conf: scm_conf@0 {
+                                       compatible = "syscon";
+                                       reg = <0x0 0x1400>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       pbias_regulator: pbias_regulator {
+                                               compatible = "ti,pbias-omap";
+                                               reg = <0xe00 0x4>;
+                                               syscon = <&scm_conf>;
+                                               pbias_mmc_reg: pbias_mmc_omap5 {
+                                                       regulator-name = "pbias_mmc_omap5";
+                                                       regulator-min-microvolt = <1800000>;
+                                                       regulator-max-microvolt = <3000000>;
+                                               };
+                                       };
+                               };
+
+                               dra7_pmx_core: pinmux@1400 {
+                                       compatible = "ti,dra7-padconf",
+                                                    "pinctrl-single";
+                                       reg = <0x1400 0x0464>;
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       #interrupt-cells = <1>;
+                                       interrupt-controller;
+                                       pinctrl-single,register-width = <32>;
+                                       pinctrl-single,function-mask = <0x3fffffff>;
+                               };
+                       };
+
+                       cm_core_aon: cm_core_aon@5000 {
+                               compatible = "ti,dra7-cm-core-aon";
+                               reg = <0x5000 0x2000>;
+
+                               cm_core_aon_clocks: clocks {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                               };
+
+                               cm_core_aon_clockdomains: clockdomains {
+                               };
+                       };
+
+                       cm_core: cm_core@8000 {
+                               compatible = "ti,dra7-cm-core";
+                               reg = <0x8000 0x3000>;
+
+                               cm_core_clocks: clocks {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                               };
+
+                               cm_core_clockdomains: clockdomains {
+                               };
                        };
+               };
 
-                       prm_clockdomains: clockdomains {
+               l4_wkup: l4@4ae00000 {
+                       compatible = "ti,dra7-l4-wkup", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0 0x4ae00000 0x3f000>;
+
+                       counter32k: counter@4000 {
+                               compatible = "ti,omap-counter32k";
+                               reg = <0x4000 0x40>;
+                               ti,hwmods = "counter_32k";
+                       };
+
+                       prm: prm@6000 {
+                               compatible = "ti,dra7-prm";
+                               reg = <0x6000 0x3000>;
+                               interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+
+                               prm_clocks: clocks {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                               };
+
+                               prm_clockdomains: clockdomains {
+                               };
                        };
                };
 
                        };
                };
 
-               cm_core_aon: cm_core_aon@4a005000 {
-                       compatible = "ti,dra7-cm-core-aon";
-                       reg = <0x4a005000 0x2000>;
-
-                       cm_core_aon_clocks: clocks {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                       };
-
-                       cm_core_aon_clockdomains: clockdomains {
-                       };
-               };
-
-               cm_core: cm_core@4a008000 {
-                       compatible = "ti,dra7-cm-core";
-                       reg = <0x4a008000 0x3000>;
-
-                       cm_core_clocks: clocks {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                       };
-
-                       cm_core_clockdomains: clockdomains {
-                       };
-               };
-
-               counter32k: counter@4ae04000 {
-                       compatible = "ti,omap-counter32k";
-                       reg = <0x4ae04000 0x40>;
-                       ti,hwmods = "counter_32k";
+               bandgap: bandgap@4a0021e0 {
+                       reg = <0x4a0021e0 0xc
+                               0x4a00232c 0xc
+                               0x4a002380 0x2c
+                               0x4a0023C0 0x3c
+                               0x4a002564 0x8
+                               0x4a002574 0x50>;
+                               compatible = "ti,dra752-bandgap";
+                               interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
+                               #thermal-sensor-cells = <1>;
                };
 
                dra7_ctrl_core: ctrl_core@4a002000 {
                        reg = <0x4a002e00 0x7c>;
                };
 
-               pbias_regulator: pbias_regulator {
-                       compatible = "ti,pbias-omap";
-                       reg = <0 0x4>;
-                       syscon = <&dra7_ctrl_general>;
-                       pbias_mmc_reg: pbias_mmc_omap5 {
-                               regulator-name = "pbias_mmc_omap5";
-                               regulator-min-microvolt = <1800000>;
-                               regulator-max-microvolt = <3000000>;
-                       };
-               };
-
-               dra7_pmx_core: pinmux@4a003400 {
-                       compatible = "ti,dra7-padconf", "pinctrl-single";
-                       reg = <0x4a003400 0x0464>;
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       #interrupt-cells = <1>;
-                       interrupt-controller;
-                       pinctrl-single,register-width = <32>;
-                       pinctrl-single,function-mask = <0x3fffffff>;
-               };
-
                sdma: dma-controller@4a056000 {
                        compatible = "ti,omap4430-sdma";
                        reg = <0x4a056000 0x1000>;
                        reg = <0x48820000 0x80>;
                        interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "timer5";
-                       ti,timer-dsp;
                };
 
                timer6: timer@48822000 {
                        reg = <0x48822000 0x80>;
                        interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "timer6";
-                       ti,timer-dsp;
-                       ti,timer-pwm;
                };
 
                timer7: timer@48824000 {
                        reg = <0x48824000 0x80>;
                        interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "timer7";
-                       ti,timer-dsp;
                };
 
                timer8: timer@48826000 {
                        reg = <0x48826000 0x80>;
                        interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "timer8";
-                       ti,timer-dsp;
-                       ti,timer-pwm;
                };
 
                timer9: timer@4803e000 {
                        reg = <0x48088000 0x80>;
                        interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "timer11";
-                       ti,timer-pwm;
                };
 
                timer13: timer@48828000 {
                        compatible = "ti,dra7-d_can";
                        ti,hwmods = "dcan1";
                        reg = <0x4ae3c000 0x2000>;
-                       syscon-raminit = <&dra7_ctrl_core 0x558 0>;
+                       syscon-raminit = <&scm_conf 0x558 0>;
                        interrupts = <GIC_SPI 222 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&dcan1_sys_clk_mux>;
                        status = "disabled";
                        compatible = "ti,dra7-d_can";
                        ti,hwmods = "dcan2";
                        reg = <0x48480000 0x2000>;
-                       syscon-raminit = <&dra7_ctrl_core 0x558 1>;
+                       syscon-raminit = <&scm_conf 0x558 1>;
                        interrupts = <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&sys_clkin1>;
                        status = "disabled";
                };
        };
+
+       thermal_zones: thermal-zones {
+               #include "omap4-cpu-thermal.dtsi"
+               #include "omap5-gpu-thermal.dtsi"
+               #include "omap5-core-thermal.dtsi"
+       };
+
+};
+
+&cpu_thermal {
+       polling-delay = <500>; /* milliseconds */
 };
 
 /include/ "dra7xx-clocks.dtsi"
index daf28110d4872224be02ef57de5c61de06a7f55a..ce0390f081d92ff6966657a5a45713fa7c32c309 100644 (file)
        phy-supply = <&ldo4_reg>;
 };
 
+&omap_dwc3_1 {
+       extcon = <&extcon_usb1>;
+};
+
+&omap_dwc3_2 {
+       extcon = <&extcon_usb2>;
+};
+
 &usb1 {
        dr_mode = "peripheral";
        pinctrl-names = "default";
index f7fb0d0ef25a5400b5738ba8b8afad955cded5f5..03d742f8d572f10a42e426055f28e550ca8bd7a5 100644 (file)
                        device_type = "cpu";
                        compatible = "arm,cortex-a15";
                        reg = <0>;
+
+                       /* cooling options */
+                       cooling-min-level = <0>;
+                       cooling-max-level = <2>;
+                       #cooling-cells = <2>; /* min followed by max */
                };
        };
 
index 00eeed789b4b74a306137f82d6fb70ebea831fe7..cc560a70926f003155474d9956652c6fe09718e7 100644 (file)
                        clock-names = "cpu";
 
                        clock-latency = <300000>; /* From omap-cpufreq driver */
+
+                       /* cooling options */
+                       cooling-min-level = <0>;
+                       cooling-max-level = <2>;
+                       #cooling-cells = <2>; /* min followed by max */
                };
                cpu@1 {
                        device_type = "cpu";
index 99b09a44e2694129ece5426f8df2227719255a37..3b933f74d000cd039b3ecf441928c114dca0e124 100644 (file)
                ti,dividers = <1>, <8>;
        };
 
+       clkout2_clk: clkout2_clk {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&clkoutmux2_clk_mux>;
+               ti,bit-shift = <8>;
+               reg = <0x06b0>;
+       };
+
        l3init_960m_gfclk: l3init_960m_gfclk {
                #clock-cells = <0>;
                compatible = "ti,gate-clock";
index 667d323e80a3e17616aec13cd0faab9f5a638a89..19446273e4a7f83242bf8ead39735462d2b649e7 100644 (file)
                vdd33a-supply = <&reg_3p3v>;
        };
 };
+
+&pfc {
+       uart1_pins: uart@e1030000 {
+               renesas,groups = "uart1_ctrl", "uart1_data";
+               renesas,function = "uart1";
+       };
+};
+
+&uart1 {
+       pinctrl-0 = <&uart1_pins>;
+       pinctrl-names = "default";
+       status = "okay";
+};
index cc7bfe0ba40af9a90ac8756c74e45865e0c68b0a..bb45694d91bc1e6c4557085287235613b52f16d3 100644 (file)
                clock-names = "sclk";
        };
 
+       pfc: pfc@e0140200 {
+               compatible = "renesas,pfc-emev2";
+               reg = <0xe0140200 0x100>;
+       };
+
        gpio0: gpio@e0050000 {
                compatible = "renesas,em-gio";
                reg = <0xe0050000 0x2c>, <0xe0050040 0x20>;
                interrupts = <0 67 IRQ_TYPE_LEVEL_HIGH>,
                             <0 68 IRQ_TYPE_LEVEL_HIGH>;
                gpio-controller;
+               gpio-ranges = <&pfc 0 0 32>;
                #gpio-cells = <2>;
                ngpios = <32>;
                interrupt-controller;
                interrupts = <0 69 IRQ_TYPE_LEVEL_HIGH>,
                             <0 70 IRQ_TYPE_LEVEL_HIGH>;
                gpio-controller;
+               gpio-ranges = <&pfc 0 32 32>;
                #gpio-cells = <2>;
                ngpios = <32>;
                interrupt-controller;
                interrupts = <0 71 IRQ_TYPE_LEVEL_HIGH>,
                             <0 72 IRQ_TYPE_LEVEL_HIGH>;
                gpio-controller;
+               gpio-ranges = <&pfc 0 64 32>;
                #gpio-cells = <2>;
                ngpios = <32>;
                interrupt-controller;
                interrupts = <0 73 IRQ_TYPE_LEVEL_HIGH>,
                             <0 74 IRQ_TYPE_LEVEL_HIGH>;
                gpio-controller;
+               gpio-ranges = <&pfc 0 96 32>;
                #gpio-cells = <2>;
                ngpios = <32>;
                interrupt-controller;
                interrupts = <0 75 IRQ_TYPE_LEVEL_HIGH>,
                             <0 76 IRQ_TYPE_LEVEL_HIGH>;
                gpio-controller;
+               gpio-ranges = <&pfc 0 128 31>;
                #gpio-cells = <2>;
                ngpios = <31>;
                interrupt-controller;
index 14ab515aa83cd1a1f02918563b769657fe8c472c..e3bfb11c6ef82c3194c22f449e5d1c31ac642631 100644 (file)
                        compatible = "samsung,exynos3250-cmu";
                        reg = <0x10030000 0x20000>;
                        #clock-cells = <1>;
+                       assigned-clocks = <&cmu CLK_MOUT_ACLK_400_MCUISP_SUB>,
+                                         <&cmu CLK_MOUT_ACLK_266_SUB>;
+                       assigned-clock-parents = <&cmu CLK_FIN_PLL>,
+                                                <&cmu CLK_FIN_PLL>;
                };
 
                cmu_dmc: clock-controller@105C0000 {
index adb4f6a97a1d5b19d67d486e7d36dd386884d1fd..8de12af7c276f427c7a8901b5411326b5fd8f20e 100644 (file)
                };
        };
 
+       emmc_pwrseq: pwrseq {
+               pinctrl-0 = <&sd1_cd>;
+               pinctrl-names = "default";
+               compatible = "mmc-pwrseq-emmc";
+               reset-gpios = <&gpk1 2 1>;
+       };
+
        mmc@12550000 {
                pinctrl-0 = <&sd4_clk &sd4_cmd &sd4_bus4 &sd4_bus8>;
                pinctrl-names = "default";
                vmmc-supply = <&ldo20_reg &buck8_reg>;
+               mmc-pwrseq = <&emmc_pwrseq>;
                status = "okay";
 
                num-slots = <1>;
        };
 };
 
+/* RSTN signal for eMMC */
+&sd1_cd {
+       samsung,pin-pud = <0>;
+       samsung,pin-drv = <0>;
+};
+
 &pinctrl_1 {
        gpio_power_key: power_key {
                samsung,pins = "gpx1-3";
index b9aeec430527e3afd5aeb2c2b1af8f3a1b102682..2657e842e5a5b68f6d840c70d5953e046608344f 100644 (file)
@@ -29,6 +29,7 @@
 
        chosen {
                bootargs = "console=tty1";
+               stdout-path = "serial3:115200n8";
        };
 
        gpio-keys {
                        powerdown-gpios = <&gpy2 5 GPIO_ACTIVE_HIGH>;
                        reset-gpios = <&gpx1 5 GPIO_ACTIVE_HIGH>;
                        edid-emulation = <5>;
-                       panel = <&panel>;
+
+                       ports {
+                               port@0 {
+                                       bridge_out: endpoint {
+                                               remote-endpoint = <&panel_in>;
+                                       };
+                               };
+
+                               port@1 {
+                                       bridge_in: endpoint {
+                                               remote-endpoint = <&dp_out>;
+                                       };
+                               };
+                       };
                };
        };
 
                compatible = "auo,b116xw03";
                power-supply = <&fet6>;
                backlight = <&backlight>;
+
+               port {
+                       panel_in: endpoint {
+                               remote-endpoint = <&bridge_out>;
+                       };
+               };
+       };
+
+       mmc3_pwrseq: mmc3_pwrseq {
+               compatible = "mmc-pwrseq-simple";
+               reset-gpios = <&gpx0 2 GPIO_ACTIVE_LOW>, /* WIFI_RSTn */
+                             <&gpx0 1 GPIO_ACTIVE_LOW>; /* WIFI_EN */
+               clocks = <&max77686 MAX77686_CLK_PMIC>;
+               clock-names = "ext_clock";
        };
 };
 
        samsung,link-rate = <0x0a>;
        samsung,lane-count = <2>;
        samsung,hpd-gpio = <&gpx0 7 GPIO_ACTIVE_HIGH>;
-       bridge = <&ptn3460>;
+
+       ports {
+               port@0 {
+                       dp_out: endpoint {
+                               remote-endpoint = <&bridge_in>;
+                       };
+               };
+       };
 };
 
 &ehci {
        status = "okay";
        num-slots = <1>;
        broken-cd;
+       cap-sdio-irq;
        card-detect-delay = <200>;
        samsung,dw-mshc-ciu-div = <3>;
        samsung,dw-mshc-sdr-timing = <2 3>;
        samsung,dw-mshc-ddr-timing = <1 2>;
        pinctrl-names = "default";
-       pinctrl-0 = <&sd3_clk &sd3_cmd &sd3_bus4>;
+       pinctrl-0 = <&sd3_clk &sd3_cmd &sd3_bus4 &wifi_en &wifi_rst>;
        bus-width = <4>;
        cap-sd-highspeed;
+       mmc-pwrseq = <&mmc3_pwrseq>;
 };
 
 &pinctrl_0 {
+       wifi_en: wifi-en {
+               samsung,pins = "gpx0-1";
+               samsung,pin-function = <1>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+
+       wifi_rst: wifi-rst {
+               samsung,pins = "gpx0-2";
+               samsung,pin-function = <1>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+
        power_key_irq: power-key-irq {
                samsung,pins = "gpx1-3";
                samsung,pin-function = <0xf>;
index f02775487cd4d3d20925afb84da693f92ad13e1e..d03f9b8d376d082308fa9e06c515f69ae83386c2 100644 (file)
@@ -25,6 +25,7 @@
 
        chosen {
                bootargs = "console=tty1";
+               stdout-path = "serial3:115200n8";
        };
 
        gpio-keys {
 &mmc_0 {
        status = "okay";
        num-slots = <1>;
-       supports-highspeed;
        broken-cd;
        card-detect-delay = <200>;
        samsung,dw-mshc-ciu-div = <3>;
        samsung,dw-mshc-ddr-timing = <1 2>;
        pinctrl-names = "default";
        pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_cd &sd0_bus4 &sd0_bus8>;
-
-       slot@0 {
-               reg = <0>;
-               bus-width = <8>;
-       };
+       bus-width = <8>;
+       cap-mmc-highspeed;
 };
 
 /*
 &mmc_1 {
        status = "okay";
        num-slots = <1>;
-       supports-highspeed;
        broken-cd;
        card-detect-delay = <200>;
        samsung,dw-mshc-ciu-div = <3>;
        samsung,dw-mshc-ddr-timing = <1 2>;
        pinctrl-names = "default";
        pinctrl-0 = <&sd1_clk &sd1_cmd &sd1_cd &sd1_bus4>;
-
-       slot@0 {
-               reg = <0>;
-               bus-width = <4>;
-       };
+       bus-width = <4>;
+       cap-sd-highspeed;
 };
 
 &pinctrl_0 {
 
        power_key_irq: power-key-irq {
                samsung,pins = "gpx1-3";
-               samsung,pin-function = <0>;
+               samsung,pin-function = <0xf>;
                samsung,pin-pud = <0>;
                samsung,pin-drv = <0>;
        };
 
        lid_irq: lid-irq {
                samsung,pins = "gpx3-5";
-               samsung,pin-function = <0>;
+               samsung,pin-function = <0xf>;
                samsung,pin-pud = <0>;
                samsung,pin-drv = <0>;
        };
index 77f656eb8e6b87fe19182b72e66c2ae9160f4e59..257e2f10525de14fb8eee4ca5b4ecd630da18cf7 100644 (file)
                compatible = "samsung,exynos4210-mct";
                reg = <0x101C0000 0x800>;
                interrupt-controller;
-               #interrups-cells = <2>;
+               #interrupt-cells = <2>;
                interrupt-parent = <&mct_map>;
                interrupts = <0 0>, <1 0>, <2 0>, <3 0>,
                             <4 0>, <5 0>;
index db2c1c4cd90076b5c7bb47d12737e46bf4938264..b82b6fa15f4861d21087dbe82b578a3c66ff3f4e 100644 (file)
@@ -55,7 +55,7 @@
                samsung,dw-mshc-sdr-timing = <0 4>;
                samsung,dw-mshc-ddr-timing = <0 2>;
                pinctrl-names = "default";
-               pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
+               pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus1 &sd0_bus4 &sd0_bus8>;
                vmmc-supply = <&ldo10_reg>;
                bus-width = <8>;
                cap-mmc-highspeed;
@@ -68,7 +68,7 @@
                samsung,dw-mshc-sdr-timing = <2 3>;
                samsung,dw-mshc-ddr-timing = <1 2>;
                pinctrl-names = "default";
-               pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>;
+               pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus1 &sd2_bus4>;
                vmmc-supply = <&ldo19_reg>;
                vqmmc-supply = <&ldo13_reg>;
                bus-width = <4>;
index c47bb70665c1652c6b907e8d3d05cea077781079..0788d08fb43edd00b65f64864ab4a4476f7aaff6 100644 (file)
                pinctrl-names = "default";
        };
 
+       chosen {
+               stdout-path = "serial3:115200n8";
+       };
+
        fixed-rate-clocks {
                oscclk {
                        compatible = "samsung,exynos5420-oscclk";
                compatible = "auo,b116xw03";
                power-supply = <&tps65090_fet6>;
                backlight = <&backlight>;
+
+               port {
+                       panel_in: endpoint {
+                               remote-endpoint = <&bridge_out>;
+                       };
+               };
+       };
+
+       mmc1_pwrseq: mmc1_pwrseq {
+               compatible = "mmc-pwrseq-simple";
+               reset-gpios = <&gpx0 0 GPIO_ACTIVE_LOW>; /* WIFI_EN */
+               clocks = <&max77802 MAX77802_CLK_32K_CP>;
+               clock-names = "ext_clock";
        };
 };
 
        samsung,link-rate = <0x06>;
        samsung,lane-count = <2>;
        samsung,hpd-gpio = <&gpx2 6 0>;
-       bridge = <&ps8625>;
+
+       ports {
+               port@0 {
+                       dp_out: endpoint {
+                               remote-endpoint = <&bridge_in>;
+                       };
+               };
+       };
 };
 
 &fimd {
                interrupt-parent = <&gpx0>;
                pinctrl-names = "default";
                pinctrl-0 = <&max98090_irq>;
+               clocks = <&pmu_system_controller 0>;
+               clock-names = "mclk";
        };
 
        light-sensor@44 {
                sleep-gpios = <&gpx3 5 GPIO_ACTIVE_HIGH>;
                reset-gpios = <&gpy7 7 GPIO_ACTIVE_HIGH>;
                lane-count = <2>;
-               panel = <&panel>;
                use-external-pwm;
+
+               ports {
+                       port@0 {
+                               bridge_out: endpoint {
+                                       remote-endpoint = <&panel_in>;
+                               };
+                       };
+
+                       port@1 {
+                               bridge_in: endpoint {
+                                       remote-endpoint = <&dp_out>;
+                               };
+                       };
+               };
+
        };
 };
 
        samsung,dw-mshc-ciu-div = <3>;
        samsung,dw-mshc-sdr-timing = <0 4>;
        samsung,dw-mshc-ddr-timing = <0 2>;
+       samsung,dw-mshc-hs400-timing = <0 2>;
+       samsung,read-strobe-delay = <90>;
        pinctrl-names = "default";
-       pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
+       pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus1 &sd0_bus4 &sd0_bus8 &sd0_rclk>;
        bus-width = <8>;
 };
 
+&mmc_1 {
+       status = "okay";
+       num-slots = <1>;
+       broken-cd;
+       cap-sdio-irq;
+       card-detect-delay = <200>;
+       clock-frequency = <400000000>;
+       samsung,dw-mshc-ciu-div = <1>;
+       samsung,dw-mshc-sdr-timing = <0 1>;
+       samsung,dw-mshc-ddr-timing = <0 2>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&sd1_clk>, <&sd1_cmd>, <&sd1_int>, <&sd1_bus1>,
+                   <&sd1_bus4>, <&sd1_bus8>, <&wifi_en>;
+       bus-width = <4>;
+       cap-sd-highspeed;
+       mmc-pwrseq = <&mmc1_pwrseq>;
+       vqmmc-supply = <&buck10_reg>;
+};
+
 &mmc_2 {
        status = "okay";
        num-slots = <1>;
        samsung,dw-mshc-sdr-timing = <2 3>;
        samsung,dw-mshc-ddr-timing = <1 2>;
        pinctrl-names = "default";
-       pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>;
+       pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus1 &sd2_bus4>;
        bus-width = <4>;
 };
 
        pinctrl-names = "default";
        pinctrl-0 = <&mask_tpm_reset>;
 
+       wifi_en: wifi-en {
+               samsung,pins = "gpx0-0";
+               samsung,pin-function = <1>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+
        max98090_irq: max98090-irq {
                samsung,pins = "gpx0-2";
                samsung,pin-function = <0>;
        };
 };
 
+&pinctrl_1 {
+       /* Adjust WiFi drive strengths lower for EMI */
+       sd1_clk: sd1-clk {
+               samsung,pin-drv = <2>;
+       };
+
+       sd1_cmd: sd1-cmd {
+               samsung,pin-drv = <2>;
+       };
+
+       sd1_bus1: sd1-bus-width1 {
+               samsung,pin-drv = <2>;
+       };
+
+       sd1_bus4: sd1-bus-width4 {
+               samsung,pin-drv = <2>;
+       };
+
+       sd1_bus8: sd1-bus-width8 {
+               samsung,pin-drv = <2>;
+       };
+};
+
 &pinctrl_2 {
        pmic_dvs_2: pmic-dvs-2 {
                samsung,pins = "gpj4-2";
index ba686e40eac7965942555a1f5eca9a81bb57ef39..8b153166ebdb430e6c827ab1a80d5bd9da316e47 100644 (file)
                        samsung,pin-drv = <3>;
                };
 
+               sd0_rclk: sd0-rclk {
+                       samsung,pins = "gpc0-7";
+                       samsung,pin-function = <2>;
+                       samsung,pin-pud = <1>;
+                       samsung,pin-drv = <3>;
+               };
+
                sd1_cmd: sd1-cmd {
                        samsung,pins = "gpc1-1";
                        samsung,pin-function = <2>;
index 8be3d7b489ff3585dad03e38f8177a300cbef00f..9103f2381a6d7ccefd22a429758fd7e3a4755820 100644 (file)
                samsung,dw-mshc-ciu-div = <3>;
                samsung,dw-mshc-sdr-timing = <0 4>;
                samsung,dw-mshc-ddr-timing = <0 2>;
+               samsung,dw-mshc-hs400-timing = <0 2>;
+               samsung,read-strobe-delay = <90>;
                pinctrl-names = "default";
-               pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
+               pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus1 &sd0_bus4 &sd0_bus8
+                            &sd0_rclk>;
                bus-width = <8>;
                cap-mmc-highspeed;
        };
@@ -93,7 +96,7 @@
                samsung,dw-mshc-sdr-timing = <2 3>;
                samsung,dw-mshc-ddr-timing = <1 2>;
                pinctrl-names = "default";
-               pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>;
+               pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus1 &sd2_bus4>;
                bus-width = <4>;
                cap-sd-highspeed;
        };
index b3d2d53820e3d57005b6fb89d0f9e7dae72c3fa4..f67b23f303c3904bfbf834e790a4bfd01f127ecd 100644 (file)
                compatible = "samsung,exynos4210-mct";
                reg = <0x101C0000 0x800>;
                interrupt-controller;
-               #interrups-cells = <1>;
+               #interrupt-cells = <1>;
                interrupt-parent = <&mct_map>;
                interrupts = <0>, <1>, <2>, <3>, <4>, <5>, <6>, <7>,
                                <8>, <9>, <10>, <11>;
                compatible = "samsung,exynos4210-pd";
                reg = <0x10044000 0x20>;
                #power-domain-cells = <0>;
+               clocks = <&clock CLK_GSCL0>, <&clock CLK_GSCL1>;
+               clock-names = "asb0", "asb1";
        };
 
        isp_pd: power-domain@10044020 {
                         <&clock CLK_MOUT_SW_ACLK300>,
                         <&clock CLK_MOUT_USER_ACLK300_DISP1>,
                         <&clock CLK_MOUT_SW_ACLK400>,
-                        <&clock CLK_MOUT_USER_ACLK400_DISP1>;
+                        <&clock CLK_MOUT_USER_ACLK400_DISP1>,
+                        <&clock CLK_FIMD1>, <&clock CLK_MIXER>;
                clock-names = "oscclk", "pclk0", "clk0",
-                             "pclk1", "clk1", "pclk2", "clk2";
+                             "pclk1", "clk1", "pclk2", "clk2",
+                             "asb0", "asb1";
        };
 
        pinctrl_0: pinctrl@13400000 {
index a519c863248d85f79a24d4fa918c53827819ca90..edc25cf1d71754d230912f16393333e51574e1a1 100644 (file)
                };
        };
 
+       emmc_pwrseq: pwrseq {
+               pinctrl-0 = <&emmc_nrst_pin>;
+               pinctrl-names = "default";
+               compatible = "mmc-pwrseq-emmc";
+               reset-gpios = <&gpd1 0 1>;
+       };
+
        i2c_2: i2c@12C80000 {
                samsung,i2c-sda-delay = <100>;
                samsung,i2c-max-bus-freq = <66000>;
 
 &mmc_0 {
        status = "okay";
+       mmc-pwrseq = <&emmc_pwrseq>;
        broken-cd;
        card-detect-delay = <200>;
        samsung,dw-mshc-ciu-div = <3>;
        samsung,dw-mshc-sdr-timing = <0 4>;
        samsung,dw-mshc-ddr-timing = <0 2>;
        pinctrl-names = "default";
-       pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
+       pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus1 &sd0_bus4 &sd0_bus8>;
        bus-width = <8>;
        cap-mmc-highspeed;
 };
        samsung,dw-mshc-sdr-timing = <0 4>;
        samsung,dw-mshc-ddr-timing = <0 2>;
        pinctrl-names = "default";
-       pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>;
+       pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus1 &sd2_bus4>;
        bus-width = <4>;
        cap-sd-highspeed;
 };
        };
 };
 
+&pinctrl_1 {
+       emmc_nrst_pin: emmc-nrst {
+               samsung,pins = "gpd1-0";
+               samsung,pin-function = <0>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+};
+
 &usbdrd_dwc3_0 {
        dr_mode = "host";
 };
index 06737c60d33366b78eb74f16df8e0c113091a2bd..412f41d62686f3ae966df4640d98988dc489c65f 100644 (file)
                pinctrl-names = "default";
        };
 
+       chosen {
+               stdout-path = "serial3:115200n8";
+       };
+
        fixed-rate-clocks {
                oscclk {
                        compatible = "samsung,exynos5420-oscclk";
                power-supply = <&tps65090_fet6>;
                backlight = <&backlight>;
        };
+
+       mmc1_pwrseq: mmc1_pwrseq {
+               compatible = "mmc-pwrseq-simple";
+               reset-gpios = <&gpx0 0 GPIO_ACTIVE_LOW>; /* WIFI_EN */
+               clocks = <&max77802 MAX77802_CLK_32K_CP>;
+               clock-names = "ext_clock";
+       };
 };
 
 &adc {
                interrupt-parent = <&gpx0>;
                pinctrl-names = "default";
                pinctrl-0 = <&max98091_irq>;
+               clocks = <&pmu_system_controller 0>;
+               clock-names = "mclk";
        };
 
        light-sensor@44 {
        num-slots = <1>;
        broken-cd;
        mmc-hs200-1_8v;
+       mmc-hs400-1_8v;
        cap-mmc-highspeed;
        non-removable;
        card-detect-delay = <200>;
-       clock-frequency = <400000000>;
+       clock-frequency = <800000000>;
        samsung,dw-mshc-ciu-div = <3>;
        samsung,dw-mshc-sdr-timing = <0 4>;
        samsung,dw-mshc-ddr-timing = <0 2>;
+       samsung,dw-mshc-hs400-timing = <0 2>;
+       samsung,read-strobe-delay = <90>;
        pinctrl-names = "default";
-       pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>;
+       pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus1 &sd0_bus4 &sd0_bus8 &sd0_rclk>;
        bus-width = <8>;
 };
 
+&mmc_1 {
+       status = "okay";
+       num-slots = <1>;
+       broken-cd;
+       cap-sdio-irq;
+       card-detect-delay = <200>;
+       clock-frequency = <400000000>;
+       samsung,dw-mshc-ciu-div = <1>;
+       samsung,dw-mshc-sdr-timing = <0 1>;
+       samsung,dw-mshc-ddr-timing = <0 2>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&sd1_clk>, <&sd1_cmd>, <&sd1_int>, <&sd1_bus1>,
+                   <&sd1_bus4>, <&sd1_bus8>, <&wifi_en>;
+       bus-width = <4>;
+       cap-sd-highspeed;
+       mmc-pwrseq = <&mmc1_pwrseq>;
+       vqmmc-supply = <&buck10_reg>;
+};
+
 &mmc_2 {
        status = "okay";
        num-slots = <1>;
        samsung,dw-mshc-sdr-timing = <2 3>;
        samsung,dw-mshc-ddr-timing = <1 2>;
        pinctrl-names = "default";
-       pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>;
+       pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus1 &sd2_bus4>;
        bus-width = <4>;
 };
 
        pinctrl-names = "default";
        pinctrl-0 = <&mask_tpm_reset>;
 
+       wifi_en: wifi-en {
+               samsung,pins = "gpx0-0";
+               samsung,pin-function = <1>;
+               samsung,pin-pud = <0>;
+               samsung,pin-drv = <0>;
+       };
+
        max98091_irq: max98091-irq {
                samsung,pins = "gpx0-2";
                samsung,pin-function = <0>;
        };
 };
 
+&pinctrl_1 {
+       /* Adjust WiFi drive strengths lower for EMI */
+       sd1_clk: sd1-clk {
+               samsung,pin-drv = <2>;
+       };
+
+       sd1_cmd: sd1-cmd {
+               samsung,pin-drv = <2>;
+       };
+
+       sd1_bus1: sd1-bus-width1 {
+               samsung,pin-drv = <2>;
+       };
+
+       sd1_bus4: sd1-bus-width4 {
+               samsung,pin-drv = <2>;
+       };
+
+       sd1_bus8: sd1-bus-width8 {
+               samsung,pin-drv = <2>;
+       };
+};
+
 &pinctrl_2 {
        pmic_dvs_2: pmic-dvs-2 {
                samsung,pins = "gpj4-2";
index 238814596a8787b5135df02f592306a823a1319e..44044f2751151c6a244036de3d665da9da4bd32f 100644 (file)
                compatible = "arm,coresight-etb10", "arm,primecell";
                reg = <0 0xe3c42000 0 0x1000>;
 
-               coresight-default-sink;
                clocks = <&clk_375m>;
                clock-names = "apb_pclk";
                port {
index 9c21b15837627fcf2a98032183d77e2a8be153db..dd45e6971bc35061a3b9d5b4579c6e6697ca9eca 100644 (file)
                mux-int-port = <1>;
                mux-ext-port = <4>;
        };
+
+       wvga: display {
+               model = "CLAA057VC01CW";
+               bits-per-pixel = <16>;
+               fsl,pcr = <0xfa208b80>;
+               bus-width = <18>;
+               native-mode = <&wvga_timings>;
+               display-timings {
+                       wvga_timings: 640x480 {
+                               hactive = <640>;
+                               vactive = <480>;
+                               hback-porch = <45>;
+                               hfront-porch = <114>;
+                               hsync-len = <1>;
+                               vback-porch = <33>;
+                               vfront-porch = <11>;
+                               vsync-len = <1>;
+                               clock-frequency = <25200000>;
+                       };
+               };
+       };
 };
 
 &audmux {
                        >;
                };
 
+               pinctrl_lcd: lcdgrp {
+                       fsl,pins = <
+                               MX25_PAD_LD0__LD0               0xe0
+                               MX25_PAD_LD1__LD1               0xe0
+                               MX25_PAD_LD2__LD2               0xe0
+                               MX25_PAD_LD3__LD3               0xe0
+                               MX25_PAD_LD4__LD4               0xe0
+                               MX25_PAD_LD5__LD5               0xe0
+                               MX25_PAD_LD6__LD6               0xe0
+                               MX25_PAD_LD7__LD7               0xe0
+                               MX25_PAD_LD8__LD8               0xe0
+                               MX25_PAD_LD9__LD9               0xe0
+                               MX25_PAD_LD10__LD10             0xe0
+                               MX25_PAD_LD11__LD11             0xe0
+                               MX25_PAD_LD12__LD12             0xe0
+                               MX25_PAD_LD13__LD13             0xe0
+                               MX25_PAD_LD14__LD14             0xe0
+                               MX25_PAD_LD15__LD15             0xe0
+                               MX25_PAD_GPIO_E__LD16           0xe0
+                               MX25_PAD_GPIO_F__LD17           0xe0
+                               MX25_PAD_HSYNC__HSYNC           0xe0
+                               MX25_PAD_VSYNC__VSYNC           0xe0
+                               MX25_PAD_LSCLK__LSCLK           0xe0
+                               MX25_PAD_OE_ACD__OE_ACD         0xe0
+                               MX25_PAD_CONTRAST__CONTRAST     0xe0
+                       >;
+               };
 
                pinctrl_uart1: uart1grp {
                        fsl,pins = <
        };
 };
 
+&lcdc {
+       display = <&wvga>;
+       fsl,lpccr = <0x00a903ff>;
+       fsl,lscr1 = <0x00120300>;
+       fsl,dmacr = <0x00020010>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_lcd>;
+       status = "okay";
+};
+
 &nfc {
        nand-on-flash-bbt;
        status = "okay";
index 88eebb15da6a9ed45586e2ddfba37e9e28d85336..7c4b9f2f9aad8a31214ba2627be1fcb180884220 100644 (file)
  * <mux_reg conf_reg input_reg mux_mode input_val>
  */
 
+#define MX25_PAD_TDO__TDO                      0x000 0x3e8 0x000 0x00 0x000
+
 #define MX25_PAD_A10__A10                      0x008 0x000 0x000 0x00 0x000
 #define MX25_PAD_A10__GPIO_4_0                 0x008 0x000 0x000 0x05 0x000
 
 #define MX25_PAD_A13__A13                      0x00c 0x22C 0x000 0x00 0x000
 #define MX25_PAD_A13__GPIO_4_1                 0x00c 0x22C 0x000 0x05 0x000
+#define MX25_PAD_A13__LCDC_CLS                 0x00c 0x22C 0x000 0x07 0x000
 
 #define MX25_PAD_A14__A14                      0x010 0x230 0x000 0x10 0x000
 #define MX25_PAD_A14__GPIO_2_0                 0x010 0x230 0x000 0x15 0x000
+#define MX25_PAD_A14__SIM1_CLK1                        0x010 0x230 0x000 0x16 0x000
+#define MX25_PAD_A14__LCDC_SPL                 0x010 0x230 0x000 0x17 0x000
 
 #define MX25_PAD_A15__A15                      0x014 0x234 0x000 0x10 0x000
 #define MX25_PAD_A15__GPIO_2_1                 0x014 0x234 0x000 0x15 0x000
+#define MX25_PAD_A15__SIM1_RST1                        0x014 0x234 0x000 0x16 0x000
+#define MX25_PAD_A15__LCDC_PS                  0x014 0x234 0x000 0x17 0x000
 
 #define MX25_PAD_A16__A16                      0x018 0x000 0x000 0x10 0x000
 #define MX25_PAD_A16__GPIO_2_2                 0x018 0x000 0x000 0x15 0x000
+#define MX25_PAD_A16__SIM1_VEN1                        0x018 0x000 0x000 0x16 0x000
+#define MX25_PAD_A16__LCDC_REV                 0x018 0x000 0x000 0x17 0x000
 
 #define MX25_PAD_A17__A17                      0x01c 0x238 0x000 0x10 0x000
 #define MX25_PAD_A17__GPIO_2_3                 0x01c 0x238 0x000 0x15 0x000
+#define MX25_PAD_A17__SIM1_TX                  0x01c 0x238 0x554 0x16 0x000
+#define MX25_PAD_A17__FEC_TX_ERR               0x01c 0x238 0x000 0x17 0x000
 
 #define MX25_PAD_A18__A18                      0x020 0x23c 0x000 0x10 0x000
 #define MX25_PAD_A18__GPIO_2_4                 0x020 0x23c 0x000 0x15 0x000
+#define MX25_PAD_A18__SIM1_PD1                 0x020 0x23c 0x550 0x16 0x000
 #define MX25_PAD_A18__FEC_COL                  0x020 0x23c 0x504 0x17 0x000
 
 #define MX25_PAD_A19__A19                      0x024 0x240 0x000 0x10 0x000
-#define MX25_PAD_A19__FEC_RX_ER                        0x024 0x240 0x518 0x17 0x000
 #define MX25_PAD_A19__GPIO_2_5                 0x024 0x240 0x000 0x15 0x000
+#define MX25_PAD_A19__SIM1_RX1                 0x024 0x240 0x54c 0x16 0x000
+#define MX25_PAD_A19__FEC_RX_ERR               0x024 0x240 0x518 0x17 0x000
 
 #define MX25_PAD_A20__A20                      0x028 0x244 0x000 0x10 0x000
 #define MX25_PAD_A20__GPIO_2_6                 0x028 0x244 0x000 0x15 0x000
+#define MX25_PAD_A20__SIM2_CLK1                        0x028 0x244 0x000 0x16 0x000
 #define MX25_PAD_A20__FEC_RDATA2               0x028 0x244 0x50c 0x17 0x000
 
 #define MX25_PAD_A21__A21                      0x02c 0x248 0x000 0x10 0x000
 #define MX25_PAD_A21__GPIO_2_7                 0x02c 0x248 0x000 0x15 0x000
+#define MX25_PAD_A21__SIM2_RST1                        0x02c 0x248 0x000 0x16 0x000
 #define MX25_PAD_A21__FEC_RDATA3               0x02c 0x248 0x510 0x17 0x000
 
 #define MX25_PAD_A22__A22                      0x030 0x000 0x000 0x10 0x000
 #define MX25_PAD_A22__GPIO_2_8                 0x030 0x000 0x000 0x15 0x000
+#define MX25_PAD_A22__FEC_TDATA2               0x030 0x000 0x000 0x17 0x000
+#define MX25_PAD_A22__SIM2_VEN1                        0x030 0x000 0x000 0x16 0x000
+#define MX25_PAD_A22__FEC_TDATA2               0x030 0x000 0x000 0x17 0x000
 
 #define MX25_PAD_A23__A23                      0x034 0x24c 0x000 0x10 0x000
 #define MX25_PAD_A23__GPIO_2_9                 0x034 0x24c 0x000 0x15 0x000
+#define MX25_PAD_A23__SIM2_TX1                 0x034 0x24c 0x560 0x16 0x000
+#define MX25_PAD_A23__FEC_TDATA3               0x034 0x24c 0x000 0x17 0x000
 
 #define MX25_PAD_A24__A24                      0x038 0x250 0x000 0x10 0x000
 #define MX25_PAD_A24__GPIO_2_10                        0x038 0x250 0x000 0x15 0x000
+#define MX25_PAD_A24__SIM2_PD1                 0x038 0x250 0x55c 0x16 0x000
 #define MX25_PAD_A24__FEC_RX_CLK               0x038 0x250 0x514 0x17 0x000
 
 #define MX25_PAD_A25__A25                      0x03c 0x254 0x000 0x10 0x000
 #define MX25_PAD_D15__D15                      0x088 0x280 0x000 0x00 0x000
 #define MX25_PAD_D15__LD16                     0x088 0x280 0x000 0x01 0x000
 #define MX25_PAD_D15__GPIO_4_5                 0x088 0x280 0x000 0x05 0x000
+#define MX25_PAD_D15__SDHC1_DAT7               0x088 0x280 0x4d8 0x06 0x000
 
 #define MX25_PAD_D14__D14                      0x08c 0x284 0x000 0x00 0x000
 #define MX25_PAD_D14__LD17                     0x08c 0x284 0x000 0x01 0x000
 #define MX25_PAD_D14__GPIO_4_6                 0x08c 0x284 0x000 0x05 0x000
+#define MX25_PAD_D14__SDHC1_DAT6               0x08c 0x284 0x4d4 0x06 0x000
 
 #define MX25_PAD_D13__D13                      0x090 0x288 0x000 0x00 0x000
 #define MX25_PAD_D13__LD18                     0x090 0x288 0x000 0x01 0x000
 #define MX25_PAD_D13__GPIO_4_7                 0x090 0x288 0x000 0x05 0x000
+#define MX25_PAD_D13__SDHC1_DAT5               0x090 0x288 0x4d0 0x06 0x000
 
 #define MX25_PAD_D12__D12                      0x094 0x28c 0x000 0x00 0x000
 #define MX25_PAD_D12__GPIO_4_8                 0x094 0x28c 0x000 0x05 0x000
+#define MX25_PAD_D12__SDHC1_DAT4               0x094 0x28c 0x4cc 0x06 0x000
 
 #define MX25_PAD_D11__D11                      0x098 0x290 0x000 0x00 0x000
 #define MX25_PAD_D11__GPIO_4_9                 0x098 0x290 0x000 0x05 0x000
+#define MX25_PAD_D11__USBOTG_PWR               0x098 0x290 0x000 0x06 0x000
 
 #define MX25_PAD_D10__D10                      0x09c 0x294 0x000 0x00 0x000
 #define MX25_PAD_D10__GPIO_4_10                        0x09c 0x294 0x000 0x05 0x000
 
 #define MX25_PAD_LD8__LD8                      0x0e8 0x2e0 0x000 0x10 0x000
 #define MX25_PAD_LD8__FEC_TX_ERR               0x0e8 0x2e0 0x000 0x15 0x000
+#define MX25_PAD_LD8__SDHC2_CMD                        0x0e8 0x2e0 0x4e0 0x06 0x000
 
 #define MX25_PAD_LD9__LD9                      0x0ec 0x2e4 0x000 0x10 0x000
 #define MX25_PAD_LD9__FEC_COL                  0x0ec 0x2e4 0x504 0x15 0x001
+#define MX25_PAD_LD9__SDHC2_CLK                        0x0ec 0x2e4 0x4dc 0x06 0x000
 
 #define MX25_PAD_LD10__LD10                    0x0f0 0x2e8 0x000 0x10 0x000
-#define MX25_PAD_LD10__FEC_RX_ER               0x0f0 0x2e8 0x518 0x15 0x001
+#define MX25_PAD_LD10__FEC_RX_ERR              0x0f0 0x2e8 0x518 0x15 0x001
 
 #define MX25_PAD_LD11__LD11                    0x0f4 0x2ec 0x000 0x10 0x000
 #define MX25_PAD_LD11__FEC_RDATA2              0x0f4 0x2ec 0x50c 0x15 0x001
+#define MX25_PAD_LD11__SDHC2_DAT1              0x0f4 0x2ec 0x4e8 0x06 0x000
 
 #define MX25_PAD_LD12__LD12                    0x0f8 0x2f0 0x000 0x10 0x000
+#define MX25_PAD_LD12__CSPI2_MOSI              0x0f8 0x2f0 0x4a0 0x02 0x000
 #define MX25_PAD_LD12__FEC_RDATA3              0x0f8 0x2f0 0x510 0x15 0x001
 
 #define MX25_PAD_LD13__LD13                    0x0fc 0x2f4 0x000 0x10 0x000
+#define MX25_PAD_LD13__CSPI2_MISO              0x0fc 0x2f4 0x49c 0x02 0x000
 #define MX25_PAD_LD13__FEC_TDATA2              0x0fc 0x2f4 0x000 0x15 0x000
 
 #define MX25_PAD_LD14__LD14                    0x100 0x2f8 0x000 0x10 0x000
+#define MX25_PAD_LD14__CSPI2_SCLK              0x100 0x2f8 0x494 0x02 0x000
 #define MX25_PAD_LD14__FEC_TDATA3              0x100 0x2f8 0x000 0x15 0x000
 
 #define MX25_PAD_LD15__LD15                    0x104 0x2fc 0x000 0x10 0x000
+#define MX25_PAD_LD15__CSPI2_RDY               0x104 0x2fc 0x498 0x02 0x000
 #define MX25_PAD_LD15__FEC_RX_CLK              0x104 0x2fc 0x514 0x15 0x001
 
 #define MX25_PAD_HSYNC__HSYNC                  0x108 0x300 0x000 0x10 0x000
 #define MX25_PAD_LSCLK__GPIO_1_24              0x110 0x308 0x000 0x15 0x000
 
 #define MX25_PAD_OE_ACD__OE_ACD                        0x114 0x30c 0x000 0x10 0x000
+#define MX25_PAD_OE_ACD__CSPI2_SS0             0x114 0x30c 0x4a4 0x02 0x000
 #define MX25_PAD_OE_ACD__GPIO_1_25             0x114 0x30c 0x000 0x15 0x000
 
 #define MX25_PAD_CONTRAST__CONTRAST            0x118 0x310 0x000 0x10 0x000
 
 #define MX25_PAD_CSI_D2__CSI_D2                        0x120 0x318 0x000 0x10 0x000
 #define MX25_PAD_CSI_D2__UART5_RXD_MUX         0x120 0x318 0x578 0x11 0x001
+#define MX25_PAD_CSI_D2__SIM1_CLK0             0x120 0x318 0x000 0x04 0x000
 #define MX25_PAD_CSI_D2__GPIO_1_27             0x120 0x318 0x000 0x15 0x000
 #define MX25_PAD_CSI_D2__CSPI3_MOSI            0x120 0x318 0x000 0x17 0x000
 
 #define MX25_PAD_CSI_D3__CSI_D3                        0x124 0x31c 0x000 0x10 0x000
 #define MX25_PAD_CSI_D3__UART5_TXD_MUX         0x124 0x31c 0x000 0x11 0x000
+#define MX25_PAD_CSI_D3__SIM1_RST0             0x124 0x31c 0x000 0x04 0x000
 #define MX25_PAD_CSI_D3__GPIO_1_28             0x124 0x31c 0x000 0x15 0x000
 #define MX25_PAD_CSI_D3__CSPI3_MISO            0x124 0x31c 0x4b4 0x17 0x001
 
 #define MX25_PAD_CSI_D4__CSI_D4                        0x128 0x320 0x000 0x10 0x000
 #define MX25_PAD_CSI_D4__UART5_RTS             0x128 0x320 0x574 0x11 0x001
+#define MX25_PAD_CSI_D4__SIM1_VEN0             0x128 0x320 0x000 0x04 0x000
 #define MX25_PAD_CSI_D4__GPIO_1_29             0x128 0x320 0x000 0x15 0x000
 #define MX25_PAD_CSI_D4__CSPI3_SCLK            0x128 0x320 0x000 0x17 0x000
 
 #define MX25_PAD_CSI_D5__CSI_D5                        0x12c 0x324 0x000 0x10 0x000
-#define MX25_PAD_CSI_D5__UART5_CTS             0x12c 0x324 0x000 0x11 0x001
+#define MX25_PAD_CSI_D5__UART5_CTS             0x12c 0x324 0x000 0x11 0x000
+#define MX25_PAD_CSI_D5__SIM1_TX0              0x12c 0x324 0x000 0x04 0x000
 #define MX25_PAD_CSI_D5__GPIO_1_30             0x12c 0x324 0x000 0x15 0x000
 #define MX25_PAD_CSI_D5__CSPI3_RDY             0x12c 0x324 0x000 0x17 0x000
 
 #define MX25_PAD_CSI_D6__CSI_D6                        0x130 0x328 0x000 0x10 0x000
 #define MX25_PAD_CSI_D6__SDHC2_CMD             0x130 0x328 0x4e0 0x12 0x001
+#define MX25_PAD_CSI_D6__SIM1_PD0              0x130 0x328 0x000 0x04 0x000
 #define MX25_PAD_CSI_D6__GPIO_1_31             0x130 0x328 0x000 0x15 0x000
 
 #define MX25_PAD_CSI_D7__CSI_D7                        0x134 0x32c 0x000 0x10 0x000
 #define MX25_PAD_CSI_D7__GPIO_1_6              0x134 0x32c 0x000 0x15 0x000
 
 #define MX25_PAD_CSI_D8__CSI_D8                        0x138 0x330 0x000 0x10 0x000
-#define MX25_PAD_CSI_D8__AUD6_RXC              0x138 0x330 0x000 0x12 0x001
+#define MX25_PAD_CSI_D8__AUD6_RXC              0x138 0x330 0x000 0x12 0x000
 #define MX25_PAD_CSI_D8__GPIO_1_7              0x138 0x330 0x000 0x15 0x000
 #define MX25_PAD_CSI_D8__CSPI3_SS2             0x138 0x330 0x4c4 0x17 0x000
 
 #define MX25_PAD_CSI_D9__CSI_D9                        0x13c 0x334 0x000 0x10 0x000
-#define MX25_PAD_CSI_D9__AUD6_RXFS             0x13c 0x334 0x000 0x12 0x001
+#define MX25_PAD_CSI_D9__AUD6_RXFS             0x13c 0x334 0x000 0x12 0x000
 #define MX25_PAD_CSI_D9__GPIO_4_21             0x13c 0x334 0x000 0x15 0x000
 #define MX25_PAD_CSI_D9__CSPI3_SS3             0x13c 0x334 0x4c8 0x17 0x000
 
 #define MX25_PAD_CSI_MCLK__CSI_MCLK            0x140 0x338 0x000 0x10 0x000
-#define MX25_PAD_CSI_MCLK__AUD6_TXD            0x140 0x338 0x000 0x11 0x001
+#define MX25_PAD_CSI_MCLK__AUD6_TXD            0x140 0x338 0x000 0x11 0x000
 #define MX25_PAD_CSI_MCLK__SDHC2_DAT0          0x140 0x338 0x4e4 0x12 0x001
 #define MX25_PAD_CSI_MCLK__GPIO_1_8            0x140 0x338 0x000 0x15 0x000
 
 #define MX25_PAD_CSI_VSYNC__CSI_VSYNC          0x144 0x33c 0x000 0x10 0x000
-#define MX25_PAD_CSI_VSYNC__AUD6_RXD           0x144 0x33c 0x000 0x11 0x001
+#define MX25_PAD_CSI_VSYNC__AUD6_RXD           0x144 0x33c 0x000 0x11 0x000
 #define MX25_PAD_CSI_VSYNC__SDHC2_DAT1         0x144 0x33c 0x4e8 0x12 0x001
 #define MX25_PAD_CSI_VSYNC__GPIO_1_9           0x144 0x33c 0x000 0x15 0x000
 
 #define MX25_PAD_CSI_HSYNC__CSI_HSYNC          0x148 0x340 0x000 0x10 0x000
-#define MX25_PAD_CSI_HSYNC__AUD6_TXC           0x148 0x340 0x000 0x11 0x001
+#define MX25_PAD_CSI_HSYNC__AUD6_TXC           0x148 0x340 0x000 0x11 0x000
 #define MX25_PAD_CSI_HSYNC__SDHC2_DAT2         0x148 0x340 0x4ec 0x12 0x001
 #define MX25_PAD_CSI_HSYNC__GPIO_1_10          0x148 0x340 0x000 0x15 0x000
 
 #define MX25_PAD_CSI_PIXCLK__CSI_PIXCLK                0x14c 0x344 0x000 0x10 0x000
-#define MX25_PAD_CSI_PIXCLK__AUD6_TXFS         0x14c 0x344 0x000 0x11 0x001
+#define MX25_PAD_CSI_PIXCLK__AUD6_TXFS         0x14c 0x344 0x000 0x11 0x000
 #define MX25_PAD_CSI_PIXCLK__SDHC2_DAT3                0x14c 0x344 0x4f0 0x12 0x001
 #define MX25_PAD_CSI_PIXCLK__GPIO_1_11         0x14c 0x344 0x000 0x15 0x000
 
 #define MX25_PAD_UART2_RTS__CC1                        0x188 0x380 0x000 0x13 0x000
 #define MX25_PAD_UART2_RTS__GPIO_4_28          0x188 0x380 0x000 0x15 0x000
 
-#define MX25_PAD_UART2_CTS__FEC_RX_ER          0x18c 0x384 0x518 0x12 0x002
 #define MX25_PAD_UART2_CTS__UART2_CTS          0x18c 0x384 0x000 0x10 0x000
+#define MX25_PAD_UART2_CTS__FEC_RX_ERR         0x18c 0x384 0x518 0x12 0x002
 #define MX25_PAD_UART2_CTS__GPIO_4_29          0x18c 0x384 0x000 0x15 0x000
 
 #define MX25_PAD_SD1_CMD__SD1_CMD              0x190 0x388 0x000 0x10 0x000
 #define MX25_PAD_SD1_DATA1__GPIO_2_26          0x19c 0x394 0x000 0x15 0x000
 
 #define MX25_PAD_SD1_DATA2__SD1_DATA2          0x1a0 0x398 0x000 0x10 0x000
-#define MX25_PAD_SD1_DATA2__FEC_RX_CLK         0x1a0 0x398 0x514 0x15 0x002
+#define MX25_PAD_SD1_DATA2__FEC_RX_CLK         0x1a0 0x398 0x514 0x12 0x002
 #define MX25_PAD_SD1_DATA2__GPIO_2_27          0x1a0 0x398 0x000 0x15 0x000
 
 #define MX25_PAD_SD1_DATA3__SD1_DATA3          0x1a4 0x39c 0x000 0x10 0x000
-#define MX25_PAD_SD1_DATA3__FEC_CRS            0x1a4 0x39c 0x508 0x10 0x002
+#define MX25_PAD_SD1_DATA3__FEC_CRS            0x1a4 0x39c 0x508 0x12 0x002
 #define MX25_PAD_SD1_DATA3__GPIO_2_28          0x1a4 0x39c 0x000 0x15 0x000
 
 #define MX25_PAD_KPP_ROW0__KPP_ROW0            0x1a8 0x3a0 0x000 0x10 0x000
 #define MX25_PAD_KPP_ROW2__GPIO_2_31           0x1b0 0x3a8 0x000 0x15 0x000
 
 #define MX25_PAD_KPP_ROW3__KPP_ROW3            0x1b4 0x3ac 0x000 0x10 0x000
-#define MX25_PAD_KPP_ROW3__CSI_LD1             0x1b4 0x3ac 0x48c 0x13 0x002
+#define MX25_PAD_KPP_ROW3__CSI_D1              0x1b4 0x3ac 0x48c 0x13 0x002
 #define MX25_PAD_KPP_ROW3__GPIO_3_0            0x1b4 0x3ac 0x000 0x15 0x000
 
 #define MX25_PAD_KPP_COL0__KPP_COL0            0x1b8 0x3b0 0x000 0x10 0x000
 #define MX25_PAD_FEC_RDATA0__GPIO_3_10         0x1dc 0x3d4 0x000 0x15 0x000
 
 #define MX25_PAD_FEC_RDATA1__FEC_RDATA1                0x1e0 0x3d8 0x000 0x10 0x000
+/*
+ * According to the i.MX25 Reference manual (IMX25RM, Rev. 2,
+ * 01/2011) this is CAN1_TX but that's wrong.
+ */
+#define MX25_PAD_FEC_RDATA1__CAN2_TX           0x1e0 0x3d8 0x000 0x14 0x000
 #define MX25_PAD_FEC_RDATA1__GPIO_3_11         0x1e0 0x3d8 0x000 0x15 0x000
 
 #define MX25_PAD_FEC_RX_DV__FEC_RX_DV          0x1e4 0x3dc 0x000 0x10 0x000
+/*
+ * According to the i.MX25 Reference manual (IMX25RM, Rev. 2,
+ * 01/2011) this is CAN1_RX but that's wrong.
+ */
 #define MX25_PAD_FEC_RX_DV__CAN2_RX            0x1e4 0x3dc 0x484 0x14 0x000
 #define MX25_PAD_FEC_RX_DV__GPIO_3_12          0x1e4 0x3dc 0x000 0x15 0x000
 
 #define MX25_PAD_DE_B__DE_B                    0x1f0 0x3ec 0x000 0x10 0x000
 #define MX25_PAD_DE_B__GPIO_2_20               0x1f0 0x3ec 0x000 0x15 0x000
 
-#define MX25_PAD_TDO__TDO                      0x000 0x3e8 0x000 0x00 0x000
-
 #define MX25_PAD_GPIO_A__GPIO_A                        0x1f4 0x3f0 0x000 0x10 0x000
 #define MX25_PAD_GPIO_A__CAN1_TX               0x1f4 0x3f0 0x000 0x16 0x000
 #define MX25_PAD_GPIO_A__USBOTG_PWR            0x1f4 0x3f0 0x000 0x12 0x000
 
 #define MX25_PAD_GPIO_B__GPIO_B                        0x1f8 0x3f4 0x000 0x10 0x000
-#define MX25_PAD_GPIO_B__CAN1_RX               0x1f8 0x3f4 0x480 0x16 0x001
 #define MX25_PAD_GPIO_B__USBOTG_OC             0x1f8 0x3f4 0x57c 0x12 0x001
+#define MX25_PAD_GPIO_B__CAN1_RX               0x1f8 0x3f4 0x480 0x16 0x001
 
 #define MX25_PAD_GPIO_C__GPIO_C                        0x1fc 0x3f8 0x000 0x10 0x000
+#define MX25_PAD_GPIO_C__PWM4_PWMO             0x1fc 0x3f8 0x000 0x11 0x000
+#define MX25_PAD_GPIO_C__I2C2_SCL              0x1fc 0x3f8 0x51c 0x12 0x001
+#define MX25_PAD_GPIO_C__KPP_COL4              0x1fc 0x3f8 0x52c 0x13 0x001
 #define MX25_PAD_GPIO_C__CAN2_TX               0x1fc 0x3f8 0x000 0x16 0x000
 
 #define MX25_PAD_GPIO_D__GPIO_D                        0x200 0x3fc 0x000 0x10 0x000
+#define MX25_PAD_GPIO_D__I2C2_SDA              0x200 0x3fc 0x520 0x12 0x001
 #define MX25_PAD_GPIO_D__CAN2_RX               0x200 0x3fc 0x484 0x16 0x001
 
 #define MX25_PAD_GPIO_E__GPIO_E                        0x204 0x400 0x000 0x10 0x000
 #define MX25_PAD_GPIO_E__I2C3_CLK              0x204 0x400 0x524 0x11 0x002
 #define MX25_PAD_GPIO_E__LD16                  0x204 0x400 0x000 0x12 0x000
 #define MX25_PAD_GPIO_E__AUD7_TXD              0x204 0x400 0x000 0x14 0x000
+#define MX25_PAD_GPIO_E__UART4_RXD             0x204 0x400 0x570 0x16 0x002
 
 #define MX25_PAD_GPIO_F__GPIO_F                        0x208 0x404 0x000 0x10 0x000
 #define MX25_PAD_GPIO_F__LD17                  0x208 0x404 0x000 0x12 0x000
 #define MX25_PAD_GPIO_F__AUD7_TXC              0x208 0x404 0x000 0x14 0x000
+#define MX25_PAD_GPIO_F__UART4_TXD             0x208 0x404 0x000 0x16 0x000
 
 #define MX25_PAD_EXT_ARMCLK__EXT_ARMCLK                0x20c 0x000 0x000 0x10 0x000
 #define MX25_PAD_EXT_ARMCLK__GPIO_3_15         0x20c 0x000 0x000 0x15 0x000
 #define MX25_PAD_VSTBY_REQ__VSTBY_REQ          0x214 0x408 0x000 0x10 0x000
 #define MX25_PAD_VSTBY_REQ__AUD7_TXFS          0x214 0x408 0x000 0x14 0x000
 #define MX25_PAD_VSTBY_REQ__GPIO_3_17          0x214 0x408 0x000 0x15 0x000
+
 #define MX25_PAD_VSTBY_ACK__VSTBY_ACK          0x218 0x40c 0x000 0x10 0x000
 #define MX25_PAD_VSTBY_ACK__GPIO_3_18          0x218 0x40c 0x000 0x15 0x000
 
 
 #define MX25_PAD_BOOT_MODE0__BOOT_MODE0                0x224 0x000 0x000 0x00 0x000
 #define MX25_PAD_BOOT_MODE0__GPIO_4_30         0x224 0x000 0x000 0x05 0x000
+
 #define MX25_PAD_BOOT_MODE1__BOOT_MODE1                0x228 0x000 0x000 0x00 0x000
 #define MX25_PAD_BOOT_MODE1__GPIO_4_31         0x228 0x000 0x000 0x05 0x000
 
index 4b063b68db44cbd1f99c3b63bcdb5463a0236baa..6951b66d1ab7b4cbe37dcf8944a7626213979827 100644 (file)
                                interrupts = <54>;
                                clocks = <&clks IMX27_CLK_USB_IPG_GATE>;
                                fsl,usbmisc = <&usbmisc 1>;
+                               dr_mode = "host";
                                status = "disabled";
                        };
 
                                interrupts = <55>;
                                clocks = <&clks IMX27_CLK_USB_IPG_GATE>;
                                fsl,usbmisc = <&usbmisc 2>;
+                               dr_mode = "host";
                                status = "disabled";
                        };
 
index 7198fe3798c62b52c2c86f5d2f895cc5179571fe..070e59cbdd8b76659506cf45a078a1e302bbe942 100644 (file)
@@ -78,7 +78,7 @@
                        phy-mode = "rmii";
                        pinctrl-names = "default";
                        pinctrl-0 = <&mac0_pins_a>;
-                       phy-reset-gpios = <&gpio4 13 0>;
+                       phy-reset-gpios = <&gpio4 13 GPIO_ACTIVE_LOW>;
                        status = "okay";
                };
        };
index 1f38a052ad4b0d8767b712994d3c97ca110ca8ff..7ac4f1af16ac856d243674c630b9207da71d8335 100644 (file)
                                        };
                                };
                        };
+
+                       can0: can@80032000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&can0_pins_a>;
+                               xceiver-supply = <&reg_can0_vcc>;
+                               status = "okay";
+                       };
                };
 
                apbx@80040000 {
                                status = "okay";
                        };
 
+                       auart0: serial@8006a000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&auart0_pins_a>;
+                               fsl,uart-has-rtscts;
+                               status = "okay";
+                       };
+
                        usbphy0: usbphy@8007c000 {
                                status = "okay";
                        };
        ahb@80080000 {
                usb0: usb@80080000 {
                        pinctrl-names = "default";
-                       pinctrl-0 = <&usb0_otg_apf28dev>;
+                       pinctrl-0 = <&usb0_otg_apf28dev
+                                       &usb0_id_pins_b>;
                        vbus-supply = <&reg_usb0_vbus>;
                        status = "okay";
                };
                        phy-mode = "rmii";
                        pinctrl-names = "default";
                        pinctrl-0 = <&mac1_pins_a>;
-                       phy-reset-gpios = <&gpio0 23 0>;
+                       phy-reset-gpios = <&gpio1 29 GPIO_ACTIVE_LOW>;
                        status = "okay";
                };
        };
                        gpio = <&gpio1 23 1>;
                        enable-active-high;
                };
+
+               reg_can0_vcc: regulator@1 {
+                       compatible = "regulator-fixed";
+                       reg = <1>;
+                       regulator-name = "can0_vcc";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+               };
        };
 
        leds {
 
                user-button {
                        label = "User button";
-                       gpios = <&gpio0 17 0>;
+                       gpios = <&gpio0 17 GPIO_ACTIVE_LOW>;
                        linux,code = <0x100>;
+                       gpio-key,wakeup;
                };
        };
 };
index 47f68ac868d4b6ab20751d5d2d457a31f10a7ef6..25e25f82fbaea4d9cc5bafa62ec93d1e0ba3f1c4 100644 (file)
                                        fsl,pull-up = <MXS_PULL_DISABLE>;
                                };
 
+                               spi3_pins_b: spi3@1 {
+                                       reg = <1>;
+                                       fsl,pinmux-ids = <
+                                               MX28_PAD_SSP3_SCK__SSP3_SCK
+                                               MX28_PAD_SSP3_MOSI__SSP3_CMD
+                                               MX28_PAD_SSP3_MISO__SSP3_D0
+                                               MX28_PAD_SSP3_SS0__SSP3_D3
+                                       >;
+                                       fsl,drive-strength = <MXS_DRIVE_8mA>;
+                                       fsl,voltage = <MXS_VOLTAGE_HIGH>;
+                                       fsl,pull-up = <MXS_PULL_ENABLE>;
+                               };
+
                                usb0_pins_a: usb0@0 {
                                        reg = <0>;
                                        fsl,pinmux-ids = <
                        interrupts = <92>;
                        clocks = <&clks 61>;
                        fsl,usbphy = <&usbphy1>;
+                       dr_mode = "host";
                        status = "disabled";
                };
 
index 6932928f3b45c99cc4d807edacf9475e55650056..b6478e97d6a7eb8cbb6478470d4a5e10794afaff 100644 (file)
                                clocks = <&clks 73>;
                                fsl,usbmisc = <&usbmisc 1>;
                                fsl,usbphy = <&usbphy1>;
+                               dr_mode = "host";
                                status = "disabled";
                        };
 
index 620b0f030591209f26dc0ad19af226b9a8310ed8..e2457138311f8661fd063da8be351a84cef49ced 100644 (file)
                                reg = <0x53f80200 0x0200>;
                                interrupts = <14>;
                                clocks = <&clks IMX5_CLK_USB_PHY2_GATE>;
+                               dr_mode = "host";
                                status = "disabled";
                        };
 
                                reg = <0x53f80400 0x0200>;
                                interrupts = <16>;
                                clocks = <&clks IMX5_CLK_USBOH3_GATE>;
+                               dr_mode = "host";
                                status = "disabled";
                        };
 
                                reg = <0x53f80600 0x0200>;
                                interrupts = <17>;
                                clocks = <&clks IMX5_CLK_USBOH3_GATE>;
+                               dr_mode = "host";
                                status = "disabled";
                        };
 
index c0116cffc513436d54584ee9d1c9d8ad933ebb83..f46fe9bf0bcb37a903d7ee05d67cc3289516acac 100644 (file)
                                interrupts = <14>;
                                clocks = <&clks IMX5_CLK_USBOH3_GATE>;
                                fsl,usbmisc = <&usbmisc 1>;
+                               dr_mode = "host";
                                status = "disabled";
                        };
 
                                interrupts = <16>;
                                clocks = <&clks IMX5_CLK_USBOH3_GATE>;
                                fsl,usbmisc = <&usbmisc 2>;
+                               dr_mode = "host";
                                status = "disabled";
                        };
 
                                interrupts = <17>;
                                clocks = <&clks IMX5_CLK_USBOH3_GATE>;
                                fsl,usbmisc = <&usbmisc 3>;
+                               dr_mode = "host";
                                status = "disabled";
                        };
 
index ff4fa7ecacd86ef1ddc7f4a63f23e32af5d2808c..c3e3ca9362fbb78b6b2ecb8ec0125b83abdb7352 100644 (file)
                                clocks = <&clks IMX5_CLK_USBOH3_GATE>;
                                fsl,usbmisc = <&usbmisc 1>;
                                fsl,usbphy = <&usbphy1>;
+                               dr_mode = "host";
                                status = "disabled";
                        };
 
                                interrupts = <16>;
                                clocks = <&clks IMX5_CLK_USBOH3_GATE>;
                                fsl,usbmisc = <&usbmisc 2>;
+                               dr_mode = "host";
                                status = "disabled";
                        };
 
                                interrupts = <17>;
                                clocks = <&clks IMX5_CLK_USBOH3_GATE>;
                                fsl,usbmisc = <&usbmisc 3>;
+                               dr_mode = "host";
                                status = "disabled";
                        };
 
index 9cd06e5e59f00e35b579c07118eed164872330b9..d4c4a22db4888269c26a2294add2421dd4349c7e 100644 (file)
@@ -83,3 +83,7 @@
 &ipu1_di0_disp0 {
        remote-endpoint = <&display0_in>;
 };
+
+&pwm1 {
+       status = "okay";
+};
index b413e24288dcb08b5ba5b73d461eaf67c3e2b175..15203f0e9725cb775dac06399ab212d12479e536 100644 (file)
@@ -72,3 +72,7 @@
 &ipu1_di0_disp0 {
        remote-endpoint = <&display0_in>;
 };
+
+&pwm3 {
+       status = "okay";
+};
index 58aa8f2b0f260f7613da2890cfce01a0fac25096..e0b7fe8e18f886608e7dd302409f0d045e1ebb29 100644 (file)
@@ -1,5 +1,43 @@
 /*
  * Copyright (C) 2014 Russell King
+ *
+ * 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.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
  */
 /dts-v1/;
 
index 44a0e6736bb1217369b3c45e32ad4dbb007cea03..7369d2d7da3e545904d84175f353e220d267fef0 100644 (file)
@@ -1,6 +1,44 @@
 /*
  * Copyright (C) 2014 Rabeeh Khoury (rabeeh@solid-run.com)
  * Based on dt work by Russell King
+ *
+ * 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.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
  */
 /dts-v1/;
 
index 9efd8b0c8011fea501c0033e3da5dd5cfed3e849..670bd8c4c847514f11bc3118f2b561b86fc8099d 100644 (file)
@@ -1,5 +1,43 @@
 /*
  * Copyright (C) 2014 Russell King
+ *
+ * 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.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
  */
 /dts-v1/;
 
index c2bf8476ce45f8c496ea18e389bebc7839cb0d85..0f6044553a2490106c413b86bba4c5bbf515f6c9 100644 (file)
@@ -1,6 +1,44 @@
 /*
  * Copyright (C) 2014 Rabeeh Khoury (rabeeh@solid-run.com)
  * Based on dt work by Russell King
+ *
+ * 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.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
  */
 /dts-v1/;
 
index 93ec79bb6b35c54b451ff8ccb9775387f8574aa4..399103b8e2c948110154fa0b109e917a192061b0 100644 (file)
 };
 
 &mipi_dsi {
-       port@2 {
-               reg = <2>;
+       ports {
+               port@2 {
+                       reg = <2>;
 
-               mipi_mux_2: endpoint {
-                       remote-endpoint = <&ipu2_di0_mipi>;
+                       mipi_mux_2: endpoint {
+                               remote-endpoint = <&ipu2_di0_mipi>;
+                       };
                };
-       };
 
-       port@3 {
-               reg = <3>;
+               port@3 {
+                       reg = <3>;
 
-               mipi_mux_3: endpoint {
-                       remote-endpoint = <&ipu2_di1_mipi>;
+                       mipi_mux_3: endpoint {
+                               remote-endpoint = <&ipu2_di1_mipi>;
+                       };
                };
        };
 };
index 6a524ca011e70df048939fbc5ef0659c88a660e9..d033bb1820602773c9c0beaf661f779381344221 100644 (file)
@@ -1,8 +1,48 @@
 /*
  * Copyright (C) 2014 Russell King
+ *
+ * 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.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
  */
 #include "imx6qdl-microsom.dtsi"
 #include "imx6qdl-microsom-ar8035.dtsi"
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
 
 / {
        ir_recv: ir-receiver {
                spdif-controller = <&spdif>;
                spdif-out;
        };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+               pinctrl-0 = <&pinctrl_gpio_key>;
+               pinctrl-names = "default";
+
+               button_0 {
+                       label = "Button 0";
+                       gpios = <&gpio3 8 GPIO_ACTIVE_LOW>;
+                       linux,code = <BTN_0>;
+               };
+       };
 };
 
 &hdmi {
                                MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x13059
                        >;
                };
+
+               pinctrl_gpio_key: gpio-key {
+                       fsl,pins = <
+                               MX6QDL_PAD_EIM_DA8__GPIO3_IO08  0x17059
+                       >;
+               };
        };
 };
 
+&pwm1 {
+       status = "okay";
+};
+
 &spdif {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_cubox_i_spdif>;
index 62841e85a91e45d38e71c6e7a65d2d8f8b024154..151a3db2aea957f39d4437812e06a46455e117cb 100644 (file)
@@ -1,5 +1,43 @@
 /*
  * Copyright (C) 2013,2014 Russell King
+ *
+ * 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.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
  */
 #include "imx6qdl-microsom.dtsi"
 #include "imx6qdl-microsom-ar8035.dtsi"
                };
        };
 
+       sound-sgtl5000 {
+               audio-codec = <&sgtl5000>;
+               audio-routing =
+                       "MIC_IN", "Mic Jack",
+                       "Mic Jack", "Mic Bias",
+                       "Headphone Jack", "HP_OUT";
+               compatible = "fsl,imx-audio-sgtl5000";
+               model = "On-board Codec";
+               mux-ext-port = <5>;
+               mux-int-port = <1>;
+               ssi-controller = <&ssi1>;
+       };
+
        sound-spdif {
                compatible = "fsl,imx-audio-spdif";
                model = "On-board SPDIF";
        };
 };
 
+&audmux {
+       status = "okay";
+};
+
 &can1 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_hummingboard_flexcan1>;
 &i2c1 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_hummingboard_i2c1>;
-
-       /*
-        * Not fitted on Carrier-1 board... yet
        status = "okay";
 
+       /* Pro baseboard model */
        rtc: pcf8523@68 {
                compatible = "nxp,pcf8523";
                reg = <0x68>;
        };
-        */
+
+       /* Pro baseboard model */
+       sgtl5000: sgtl5000@0a {
+               clocks = <&clks IMX6QDL_CLK_CKO>;
+               compatible = "fsl,sgtl5000";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_hummingboard_sgtl5000>;
+               reg = <0x0a>;
+               VDDA-supply = <&reg_3p3v>;
+               VDDIO-supply = <&reg_3p3v>;
+       };
 };
 
 &i2c2 {
                        >;
                };
 
+               pinctrl_hummingboard_pwm1: pwm1grp {
+                       fsl,pins = <MX6QDL_PAD_DISP0_DAT8__PWM1_OUT 0x1b0b1>;
+               };
+
+               pinctrl_hummingboard_sgtl5000: hummingboard-sgtl5000 {
+                       fsl,pins = <
+                               MX6QDL_PAD_DISP0_DAT19__AUD5_RXD 0x130b0
+                               MX6QDL_PAD_KEY_COL0__AUD5_TXC 0x130b0
+                               MX6QDL_PAD_KEY_ROW0__AUD5_TXD 0x110b0
+                               MX6QDL_PAD_KEY_COL1__AUD5_TXFS 0x130b0
+                               MX6QDL_PAD_GPIO_5__CCM_CLKO1 0x130b0
+                       >;
+               };
+
                pinctrl_hummingboard_spdif: hummingboard-spdif {
                        fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x13091>;
                };
        };
 };
 
+&pwm1 {
+        pinctrl-names = "default";
+        pinctrl-0 = <&pinctrl_hummingboard_pwm1>;
+        status = "okay";
+};
+
+&pwm2 {
+        pinctrl-names = "default";
+        status = "okay";
+};
+
 &spdif {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_hummingboard_spdif>;
        status = "okay";
 };
 
+&ssi1 {
+       fsl,mode = "i2s-slave";
+       status = "okay";
+};
+
 &usbh1 {
        disable-over-current;
        vbus-supply = <&reg_usbh1_vbus>;
index db9f45b2c57304603a78db4c20ca50a0f133c247..4a1820309cdb82e1ac0c9dcdb8fd5b11aa306a02 100644 (file)
@@ -3,6 +3,44 @@
  *
  * This describes the hookup for an AR8035 to the iMX6 on the SolidRun
  * MicroSOM.
+ *
+ * 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.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
  */
 &fec {
        pinctrl-names = "default";
index 79eac6849d4c9d8964882d1e64435d868c2c7c01..349f82be816eb77c0119cdeeba4eb424711b9bb0 100644 (file)
@@ -1,5 +1,43 @@
 /*
  * Copyright (C) 2013,2014 Russell King
+ *
+ * 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.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
 &iomuxc {
index 009abd69385d854c15c4b35bc98aca87a1ef8d84..46b2fed7c319c891dde01d415521b7207702b45b 100644 (file)
        };
 };
 
+&i2c3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c3>;
+       pinctrl-assert-gpios = <&gpio5 4 GPIO_ACTIVE_HIGH>;
+       status = "okay";
+
+       max7310_a: gpio@30 {
+               compatible = "maxim,max7310";
+               reg = <0x30>;
+               gpio-controller;
+               #gpio-cells = <2>;
+       };
+
+       max7310_b: gpio@32 {
+               compatible = "maxim,max7310";
+               reg = <0x32>;
+               gpio-controller;
+               #gpio-cells = <2>;
+       };
+
+       max7310_c: gpio@34 {
+               compatible = "maxim,max7310";
+               reg = <0x34>;
+               gpio-controller;
+               #gpio-cells = <2>;
+       };
+};
+
 &iomuxc {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_hog>;
                        >;
                };
 
+               pinctrl_i2c3: i2c3grp {
+                       fsl,pins = <
+                               MX6QDL_PAD_GPIO_3__I2C3_SCL  0x4001b8b1
+                               MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
+                       >;
+               };
+
                pinctrl_pwm3: pwm1grp {
                        fsl,pins = <
                                MX6QDL_PAD_SD4_DAT1__PWM3_OUT           0x1b0b1
index d6c69ec443149da28012034ceea65ac2ba522539..f74a8ded515f22b9985b8d48b370a45c34e9d88e 100644 (file)
@@ -53,6 +53,7 @@
                interrupt-controller;
                reg = <0x00a01000 0x1000>,
                      <0x00a00100 0x100>;
+               interrupt-parent = <&intc>;
        };
 
        clocks {
@@ -82,7 +83,7 @@
                #address-cells = <1>;
                #size-cells = <1>;
                compatible = "simple-bus";
-               interrupt-parent = <&intc>;
+               interrupt-parent = <&gpc>;
                ranges;
 
                dma_apbh: dma-apbh@00110000 {
                        compatible = "arm,cortex-a9-twd-timer";
                        reg = <0x00a00600 0x20>;
                        interrupts = <1 13 0xf01>;
+                       interrupt-parent = <&intc>;
                        clocks = <&clks IMX6QDL_CLK_TWD>;
                };
 
                                clocks = <&clks IMX6QDL_CLK_IPG>,
                                         <&clks IMX6QDL_CLK_PWM1>;
                                clock-names = "ipg", "per";
+                               status = "disabled";
                        };
 
                        pwm2: pwm@02084000 {
                                clocks = <&clks IMX6QDL_CLK_IPG>,
                                         <&clks IMX6QDL_CLK_PWM2>;
                                clock-names = "ipg", "per";
+                               status = "disabled";
                        };
 
                        pwm3: pwm@02088000 {
                                clocks = <&clks IMX6QDL_CLK_IPG>,
                                         <&clks IMX6QDL_CLK_PWM3>;
                                clock-names = "ipg", "per";
+                               status = "disabled";
                        };
 
                        pwm4: pwm@0208c000 {
                                clocks = <&clks IMX6QDL_CLK_IPG>,
                                         <&clks IMX6QDL_CLK_PWM4>;
                                clock-names = "ipg", "per";
+                               status = "disabled";
                        };
 
                        can1: flexcan@02090000 {
                                        regulator-name = "vddpu";
                                        regulator-min-microvolt = <725000>;
                                        regulator-max-microvolt = <1450000>;
-                                       regulator-always-on;
+                                       regulator-enable-ramp-delay = <150>;
                                        anatop-reg-offset = <0x140>;
                                        anatop-vol-bit-shift = <9>;
                                        anatop-vol-bit-width = <5>;
                                #size-cells = <1>;
                                ranges = <0 0x020cc000 0x4000>;
 
-                               snvs-rtc-lp@34 {
+                               snvs_rtc: snvs-rtc-lp@34 {
                                        compatible = "fsl,sec-v4.0-mon-rtc-lp";
                                        reg = <0x34 0x58>;
                                        interrupts = <0 19 IRQ_TYPE_LEVEL_HIGH>,
                        gpc: gpc@020dc000 {
                                compatible = "fsl,imx6q-gpc";
                                reg = <0x020dc000 0x4000>;
+                               interrupt-controller;
+                               #interrupt-cells = <3>;
                                interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>,
                                             <0 90 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-parent = <&intc>;
+                               pu-supply = <&reg_pu>;
+                               clocks = <&clks IMX6QDL_CLK_GPU3D_CORE>,
+                                        <&clks IMX6QDL_CLK_GPU3D_SHADER>,
+                                        <&clks IMX6QDL_CLK_GPU2D_CORE>,
+                                        <&clks IMX6QDL_CLK_GPU2D_AXI>,
+                                        <&clks IMX6QDL_CLK_OPENVG_AXI>,
+                                        <&clks IMX6QDL_CLK_VPU_AXI>;
+                               #power-domain-cells = <1>;
                        };
 
                        gpr: iomuxc-gpr@020e0000 {
                                clocks = <&clks IMX6QDL_CLK_USBOH3>;
                                fsl,usbphy = <&usbphy2>;
                                fsl,usbmisc = <&usbmisc 1>;
+                               dr_mode = "host";
                                status = "disabled";
                        };
 
                                interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6QDL_CLK_USBOH3>;
                                fsl,usbmisc = <&usbmisc 2>;
+                               dr_mode = "host";
                                status = "disabled";
                        };
 
                                interrupts = <0 42 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6QDL_CLK_USBOH3>;
                                fsl,usbmisc = <&usbmisc 3>;
+                               dr_mode = "host";
                                status = "disabled";
                        };
 
                                reg = <0x021e0000 0x4000>;
                                status = "disabled";
 
-                               port@0 {
-                                       reg = <0>;
+                               ports {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+
+                                       port@0 {
+                                               reg = <0>;
 
-                                       mipi_mux_0: endpoint {
-                                               remote-endpoint = <&ipu1_di0_mipi>;
+                                               mipi_mux_0: endpoint {
+                                                       remote-endpoint = <&ipu1_di0_mipi>;
+                                               };
                                        };
-                               };
 
-                               port@1 {
-                                       reg = <1>;
+                                       port@1 {
+                                               reg = <1>;
 
-                                       mipi_mux_1: endpoint {
-                                               remote-endpoint = <&ipu1_di1_mipi>;
+                                               mipi_mux_1: endpoint {
+                                                       remote-endpoint = <&ipu1_di1_mipi>;
+                                               };
                                        };
                                };
                        };
diff --git a/arch/arm/boot/dts/imx6sl-warp.dts b/arch/arm/boot/dts/imx6sl-warp.dts
new file mode 100644 (file)
index 0000000..64f7dec
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * Copyright 2014, 2015 O.S. Systems Software LTDA.
+ *
+ * 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.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this file; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * 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/gpio/gpio.h>
+#include "imx6sl.dtsi"
+
+/ {
+       model = "WaRP Board";
+       compatible = "warp,imx6sl-warp", "fsl,imx6sl";
+
+       memory {
+               reg = <0x80000000 0x20000000>;
+       };
+
+       regulators {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               reg_usb_otg1_vbus: regulator@0 {
+                       compatible = "regulator-fixed";
+                       reg = <0>;
+                       regulator-name = "usb_otg1_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&gpio4 0 0>;
+                       enable-active-high;
+               };
+
+               reg_usb_otg2_vbus: regulator@1 {
+                       compatible = "regulator-fixed";
+                       reg = <1>;
+                       regulator-name = "usb_otg2_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&gpio4 2 0>;
+                       enable-active-high;
+               };
+
+               reg_1p8v: regulator@2 {
+                       compatible = "regulator-fixed";
+                       reg = <2>;
+                       regulator-name = "1P8V";
+                       regulator-min-microvolt = <1800000>;
+                       regulator-max-microvolt = <1800000>;
+               };
+       };
+
+       usdhc3_pwrseq: usdhc3_pwrseq {
+               compatible = "mmc-pwrseq-simple";
+               reset-gpios = <&gpio4 5 GPIO_ACTIVE_LOW>,       /* WL_REG_ON */
+                             <&gpio3 25 GPIO_ACTIVE_LOW>,      /* BT_REG_ON */
+                             <&gpio4 4 GPIO_ACTIVE_LOW>,       /* BT_WAKE */
+                             <&gpio4 6 GPIO_ACTIVE_LOW>;       /* BT_RST_N */
+       };
+};
+
+&uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart1>;
+       status = "okay";
+};
+
+&uart2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart2>;
+       fsl,uart-has-rtscts;
+       status = "okay";
+};
+
+&uart3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart3>;
+       status = "okay";
+};
+
+&usbotg1 {
+       vbus-supply = <&reg_usb_otg1_vbus>;
+       dr_mode = "host";
+       disable-over-current;
+       status = "okay";
+};
+
+&usbotg2 {
+       vbus-supply = <&reg_usb_otg2_vbus>;
+       disable-over-current;
+       status = "okay";
+};
+
+&usdhc2 {
+       pinctrl-names = "default", "state_100mhz", "state_200mhz";
+       pinctrl-0 = <&pinctrl_usdhc2>;
+       pinctrl-1 = <&pinctrl_usdhc2_100mhz>;
+       pinctrl-2 = <&pinctrl_usdhc2_200mhz>;
+       bus-width = <8>;
+       non-removable;
+       status = "okay";
+};
+
+&usdhc3 {
+       pinctrl-names = "default", "state_100mhz", "state_200mhz";
+       pinctrl-0 = <&pinctrl_usdhc3>;
+       pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+       pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
+       bus-width = <4>;
+       non-removable;
+       keep-power-in-suspend;
+       enable-sdio-wakeup;
+       mmc-pwrseq = <&usdhc3_pwrseq>;
+       status = "okay";
+};
+
+&iomuxc {
+       imx6sl-warp {
+               pinctrl_uart1: uart1grp {
+                       fsl,pins = <
+                               MX6SL_PAD_UART1_RXD__UART1_RX_DATA      0x41b0b1
+                               MX6SL_PAD_UART1_TXD__UART1_TX_DATA      0x41b0b1
+                       >;
+               };
+
+               pinctrl_uart2: uart2grp {
+                       fsl,pins = <
+                               MX6SL_PAD_EPDC_D12__UART2_RX_DATA       0x41b0b1
+                               MX6SL_PAD_EPDC_D13__UART2_TX_DATA       0x41b0b1
+                               MX6SL_PAD_EPDC_D14__UART2_RTS_B         0x4130B1
+                               MX6SL_PAD_EPDC_D15__UART2_CTS_B         0x4130B1
+                       >;
+               };
+
+               pinctrl_uart3: uart3grp {
+                       fsl,pins = <
+                               MX6SL_PAD_AUD_RXC__UART3_RX_DATA        0x41b0b1
+                               MX6SL_PAD_AUD_RXC__UART3_TX_DATA        0x41b0b1
+                       >;
+               };
+
+               pinctrl_usdhc2: usdhc2grp {
+                       fsl,pins = <
+                               MX6SL_PAD_SD2_CMD__SD2_CMD              0x417059
+                               MX6SL_PAD_SD2_CLK__SD2_CLK              0x410059
+                               MX6SL_PAD_SD2_DAT0__SD2_DATA0           0x417059
+                               MX6SL_PAD_SD2_DAT1__SD2_DATA1           0x417059
+                               MX6SL_PAD_SD2_DAT2__SD2_DATA2           0x417059
+                               MX6SL_PAD_SD2_DAT3__SD2_DATA3           0x417059
+                               MX6SL_PAD_SD2_DAT4__SD2_DATA4           0x417059
+                               MX6SL_PAD_SD2_DAT5__SD2_DATA5           0x417059
+                               MX6SL_PAD_SD2_DAT6__SD2_DATA6           0x417059
+                               MX6SL_PAD_SD2_DAT7__SD2_DATA7           0x417059
+                       >;
+               };
+
+               pinctrl_usdhc2_100mhz: usdhc2grp100mhz {
+                       fsl,pins = <
+                               MX6SL_PAD_SD2_CMD__SD2_CMD              0x4170b9
+                               MX6SL_PAD_SD2_CLK__SD2_CLK              0x4100b9
+                               MX6SL_PAD_SD2_DAT0__SD2_DATA0           0x4170b9
+                               MX6SL_PAD_SD2_DAT1__SD2_DATA1           0x4170b9
+                               MX6SL_PAD_SD2_DAT2__SD2_DATA2           0x4170b9
+                               MX6SL_PAD_SD2_DAT3__SD2_DATA3           0x4170b9
+                               MX6SL_PAD_SD2_DAT4__SD2_DATA4           0x4170b9
+                               MX6SL_PAD_SD2_DAT5__SD2_DATA5           0x4170b9
+                               MX6SL_PAD_SD2_DAT6__SD2_DATA6           0x4170b9
+                               MX6SL_PAD_SD2_DAT7__SD2_DATA7           0x4170b9
+                       >;
+               };
+
+               pinctrl_usdhc2_200mhz: usdhc2grp200mhz {
+                       fsl,pins = <
+                               MX6SL_PAD_SD2_CMD__SD2_CMD              0x4170f9
+                               MX6SL_PAD_SD2_CLK__SD2_CLK              0x4100f9
+                               MX6SL_PAD_SD2_DAT0__SD2_DATA0           0x4170f9
+                               MX6SL_PAD_SD2_DAT1__SD2_DATA1           0x4170f9
+                               MX6SL_PAD_SD2_DAT2__SD2_DATA2           0x4170f9
+                               MX6SL_PAD_SD2_DAT3__SD2_DATA3           0x4170f9
+                               MX6SL_PAD_SD2_DAT4__SD2_DATA4           0x4170f9
+                               MX6SL_PAD_SD2_DAT5__SD2_DATA5           0x4170f9
+                               MX6SL_PAD_SD2_DAT6__SD2_DATA6           0x4170f9
+                               MX6SL_PAD_SD2_DAT7__SD2_DATA7           0x4170f9
+                       >;
+               };
+
+               pinctrl_usdhc3: usdhc3grp {
+                       fsl,pins = <
+                               MX6SL_PAD_SD3_CMD__SD3_CMD              0x417059
+                               MX6SL_PAD_SD3_CLK__SD3_CLK              0x410059
+                               MX6SL_PAD_SD3_DAT0__SD3_DATA0           0x417059
+                               MX6SL_PAD_SD3_DAT1__SD3_DATA1           0x417059
+                               MX6SL_PAD_SD3_DAT2__SD3_DATA2           0x417059
+                               MX6SL_PAD_SD3_DAT3__SD3_DATA3           0x417059
+                       >;
+               };
+
+               pinctrl_usdhc3_100mhz: usdhc3grp100mhz {
+                       fsl,pins = <
+                               MX6SL_PAD_SD3_CMD__SD3_CMD              0x4170b9
+                               MX6SL_PAD_SD3_CLK__SD3_CLK              0x4100b9
+                               MX6SL_PAD_SD3_DAT0__SD3_DATA0           0x4170b9
+                               MX6SL_PAD_SD3_DAT1__SD3_DATA1           0x4170b9
+                               MX6SL_PAD_SD3_DAT2__SD3_DATA2           0x4170b9
+                               MX6SL_PAD_SD3_DAT3__SD3_DATA3           0x4170b9
+                       >;
+               };
+
+               pinctrl_usdhc3_200mhz: usdhc3grp200mhz {
+                       fsl,pins = <
+                               MX6SL_PAD_SD3_CMD__SD3_CMD              0x4170f9
+                               MX6SL_PAD_SD3_CLK__SD3_CLK              0x4100f9
+                               MX6SL_PAD_SD3_DAT0__SD3_DATA0           0x4170f9
+                               MX6SL_PAD_SD3_DAT1__SD3_DATA1           0x4170f9
+                               MX6SL_PAD_SD3_DAT2__SD3_DATA2           0x4170f9
+                               MX6SL_PAD_SD3_DAT3__SD3_DATA3           0x4170f9
+                       >;
+               };
+       };
+};
index 36ab8e054cee0a8ff5fcc1fb6938dc1d62a1e09f..a78e715e3982f7f821d01f386cc592e046e172f5 100644 (file)
@@ -72,6 +72,7 @@
                interrupt-controller;
                reg = <0x00a01000 0x1000>,
                      <0x00a00100 0x100>;
+               interrupt-parent = <&intc>;
        };
 
        clocks {
@@ -95,7 +96,7 @@
                #address-cells = <1>;
                #size-cells = <1>;
                compatible = "simple-bus";
-               interrupt-parent = <&intc>;
+               interrupt-parent = <&gpc>;
                ranges;
 
                ocram: sram@00900000 {
                                #size-cells = <1>;
                                ranges = <0 0x020cc000 0x4000>;
 
-                               snvs-rtc-lp@34 {
+                               snvs_rtc: snvs-rtc-lp@34 {
                                        compatible = "fsl,sec-v4.0-mon-rtc-lp";
                                        reg = <0x34 0x58>;
                                        interrupts = <0 19 IRQ_TYPE_LEVEL_HIGH>,
                        gpc: gpc@020dc000 {
                                compatible = "fsl,imx6sl-gpc", "fsl,imx6q-gpc";
                                reg = <0x020dc000 0x4000>;
+                               interrupt-controller;
+                               #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>;
                        };
 
                        gpr: iomuxc-gpr@020e0000 {
                                interrupts = <0 40 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SL_CLK_USBOH3>;
                                fsl,usbmisc = <&usbmisc 2>;
+                               dr_mode = "host";
                                status = "disabled";
                        };
 
diff --git a/arch/arm/boot/dts/imx6sx-sdb-reva.dts b/arch/arm/boot/dts/imx6sx-sdb-reva.dts
new file mode 100644 (file)
index 0000000..c76b87c
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "imx6sx-sdb.dtsi"
+
+/ {
+       model = "Freescale i.MX6 SoloX SDB RevA Board";
+};
+
+&i2c1 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c1>;
+       status = "okay";
+
+       pmic: pfuze100@08 {
+               compatible = "fsl,pfuze100";
+               reg = <0x08>;
+
+               regulators {
+                       sw1a_reg: sw1ab {
+                               regulator-min-microvolt = <300000>;
+                               regulator-max-microvolt = <1875000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                               regulator-ramp-delay = <6250>;
+                       };
+
+                       sw1c_reg: sw1c {
+                               regulator-min-microvolt = <300000>;
+                               regulator-max-microvolt = <1875000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                               regulator-ramp-delay = <6250>;
+                       };
+
+                       sw2_reg: sw2 {
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       sw3a_reg: sw3a {
+                               regulator-min-microvolt = <400000>;
+                               regulator-max-microvolt = <1975000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       sw3b_reg: sw3b {
+                               regulator-min-microvolt = <400000>;
+                               regulator-max-microvolt = <1975000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       sw4_reg: sw4 {
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <3300000>;
+                       };
+
+                       swbst_reg: swbst {
+                               regulator-min-microvolt = <5000000>;
+                               regulator-max-microvolt = <5150000>;
+                       };
+
+                       snvs_reg: vsnvs {
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <3000000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       vref_reg: vrefddr {
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       vgen1_reg: vgen1 {
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <1550000>;
+                               regulator-always-on;
+                       };
+
+                       vgen2_reg: vgen2 {
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <1550000>;
+                       };
+
+                       vgen3_reg: vgen3 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+                       };
+
+                       vgen4_reg: vgen4 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+                       };
+
+                       vgen5_reg: vgen5 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+                       };
+
+                       vgen6_reg: vgen6 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+                       };
+               };
+       };
+};
+
+&qspi2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_qspi2>;
+       status = "okay";
+
+       flash0: s25fl128s@0 {
+               reg = <0>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "spansion,s25fl128s";
+               spi-max-frequency = <66000000>;
+       };
+
+       flash1: s25fl128s@1 {
+               reg = <1>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "spansion,s25fl128s";
+               spi-max-frequency = <66000000>;
+       };
+};
index 32f07d6b404239afd3c58c43ae2cb032478a37b5..0bfc4e7865b2995fcd009fe6abc9f83f5129cb5d 100644 (file)
 /*
- * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
 
-/dts-v1/;
-
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/input/input.h>
-#include "imx6sx.dtsi"
+#include "imx6sx-sdb.dtsi"
 
 / {
-       model = "Freescale i.MX6 SoloX SDB Board";
-       compatible = "fsl,imx6sx-sdb", "fsl,imx6sx";
-
-       chosen {
-               stdout-path = &uart1;
-       };
-
-       memory {
-               reg = <0x80000000 0x40000000>;
-       };
-
-       backlight {
-               compatible = "pwm-backlight";
-               pwms = <&pwm3 0 5000000>;
-               brightness-levels = <0 4 8 16 32 64 128 255>;
-               default-brightness-level = <6>;
-       };
-
-       gpio-keys {
-               compatible = "gpio-keys";
-               pinctrl-names = "default";
-               pinctrl-0 = <&pinctrl_gpio_keys>;
-
-               volume-up {
-                       label = "Volume Up";
-                       gpios = <&gpio1 18 GPIO_ACTIVE_LOW>;
-                       linux,code = <KEY_VOLUMEUP>;
-               };
-
-               volume-down {
-                       label = "Volume Down";
-                       gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
-                       linux,code = <KEY_VOLUMEDOWN>;
-               };
-       };
-
-       regulators {
-               compatible = "simple-bus";
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               vcc_sd3: regulator@0 {
-                       compatible = "regulator-fixed";
-                       reg = <0>;
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&pinctrl_vcc_sd3>;
-                       regulator-name = "VCC_SD3";
-                       regulator-min-microvolt = <3000000>;
-                       regulator-max-microvolt = <3000000>;
-                       gpio = <&gpio2 11 GPIO_ACTIVE_HIGH>;
-                       enable-active-high;
-               };
-
-               reg_usb_otg1_vbus: regulator@1 {
-                       compatible = "regulator-fixed";
-                       reg = <1>;
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&pinctrl_usb_otg1>;
-                       regulator-name = "usb_otg1_vbus";
-                       regulator-min-microvolt = <5000000>;
-                       regulator-max-microvolt = <5000000>;
-                       gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
-                       enable-active-high;
-               };
-
-               reg_usb_otg2_vbus: regulator@2 {
-                       compatible = "regulator-fixed";
-                       reg = <2>;
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&pinctrl_usb_otg2>;
-                       regulator-name = "usb_otg2_vbus";
-                       regulator-min-microvolt = <5000000>;
-                       regulator-max-microvolt = <5000000>;
-                       gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>;
-                       enable-active-high;
-               };
-
-               reg_psu_5v: regulator@3 {
-                       compatible = "regulator-fixed";
-                       reg = <3>;
-                       regulator-name = "PSU-5V0";
-                       regulator-min-microvolt = <5000000>;
-                       regulator-max-microvolt = <5000000>;
-               };
-
-               reg_lcd_3v3: regulator@4 {
-                       compatible = "regulator-fixed";
-                       reg = <4>;
-                       regulator-name = "lcd-3v3";
-                       gpio = <&gpio3 27 0>;
-                       enable-active-high;
-               };
-
-               reg_peri_3v3: regulator@5 {
-                       compatible = "regulator-fixed";
-                       reg = <5>;
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&pinctrl_peri_3v3>;
-                       regulator-name = "peri_3v3";
-                       regulator-min-microvolt = <3300000>;
-                       regulator-max-microvolt = <3300000>;
-                       gpios = <&gpio4 16 GPIO_ACTIVE_HIGH>;
-                       enable-active-high;
-                       regulator-always-on;
-               };
-
-               reg_enet_3v3: regulator@6 {
-                       compatible = "regulator-fixed";
-                       reg = <6>;
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&pinctrl_enet_3v3>;
-                       regulator-name = "enet_3v3";
-                       regulator-min-microvolt = <3300000>;
-                       regulator-max-microvolt = <3300000>;
-                       gpios = <&gpio2 6 GPIO_ACTIVE_LOW>;
-               };
-       };
-
-       sound {
-               compatible = "fsl,imx6sx-sdb-wm8962", "fsl,imx-audio-wm8962";
-               model = "wm8962-audio";
-               ssi-controller = <&ssi2>;
-               audio-codec = <&codec>;
-               audio-routing =
-                       "Headphone Jack", "HPOUTL",
-                       "Headphone Jack", "HPOUTR",
-                       "Ext Spk", "SPKOUTL",
-                       "Ext Spk", "SPKOUTR",
-                       "AMIC", "MICBIAS",
-                       "IN3R", "AMIC";
-               mux-int-port = <2>;
-               mux-ext-port = <6>;
-       };
-};
-
-&audmux {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_audmux>;
-       status = "okay";
+       model = "Freescale i.MX6 SoloX SDB RevB Board";
 };
 
-&fec1 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_enet1>;
-       phy-supply = <&reg_enet_3v3>;
-       phy-mode = "rgmii";
-       phy-handle = <&ethphy1>;
-       status = "okay";
-
-       mdio {
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               ethphy1: ethernet-phy@1 {
-                       reg = <1>;
-               };
-
-               ethphy2: ethernet-phy@2 {
-                       reg = <2>;
-               };
-       };
+&cpu0 {
+       operating-points = <
+               /* kHz    uV */
+               996000  1250000
+               792000  1175000
+               396000  1175000
+               >;
+       fsl,soc-operating-points = <
+               /* ARM kHz      SOC uV */
+               996000  1250000
+               792000  1175000
+               396000  1175000
+       >;
 };
 
-&fec2 {
+&i2c1 {
+       clock-frequency = <100000>;
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_enet2>;
-       phy-mode = "rgmii";
-       phy-handle = <&ethphy2>;
+       pinctrl-0 = <&pinctrl_i2c1>;
        status = "okay";
-};
-
-&i2c1 {
-        clock-frequency = <100000>;
-        pinctrl-names = "default";
-        pinctrl-0 = <&pinctrl_i2c1>;
-        status = "okay";
 
        pmic: pfuze100@08 {
-               compatible = "fsl,pfuze100";
+               compatible = "fsl,pfuze200";
                reg = <0x08>;
 
                regulators {
                                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-always-on;
                        };
 
-                       sw4_reg: sw4 {
-                               regulator-min-microvolt = <800000>;
-                               regulator-max-microvolt = <3300000>;
-                       };
-
                        swbst_reg: swbst {
                                regulator-min-microvolt = <5000000>;
                                regulator-max-microvolt = <5150000>;
        };
 };
 
-&i2c4 {
-        clock-frequency = <100000>;
-        pinctrl-names = "default";
-        pinctrl-0 = <&pinctrl_i2c4>;
-        status = "okay";
-
-       codec: wm8962@1a {
-               compatible = "wlf,wm8962";
-               reg = <0x1a>;
-               clocks = <&clks IMX6SX_CLK_AUDIO>;
-               DCVDD-supply = <&vgen4_reg>;
-               DBVDD-supply = <&vgen4_reg>;
-               AVDD-supply = <&vgen4_reg>;
-               CPVDD-supply = <&vgen4_reg>;
-               MICVDD-supply = <&vgen3_reg>;
-               PLLVDD-supply = <&vgen4_reg>;
-               SPKVDD1-supply = <&reg_psu_5v>;
-               SPKVDD2-supply = <&reg_psu_5v>;
-       };
-};
-
-&lcdif1 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_lcd>;
-       lcd-supply = <&reg_lcd_3v3>;
-       display = <&display0>;
-       status = "okay";
-
-       display0: display0 {
-               bits-per-pixel = <16>;
-               bus-width = <24>;
-
-               display-timings {
-                       native-mode = <&timing0>;
-                       timing0: timing0 {
-                               clock-frequency = <33500000>;
-                               hactive = <800>;
-                               vactive = <480>;
-                               hback-porch = <89>;
-                               hfront-porch = <164>;
-                               vback-porch = <23>;
-                               vfront-porch = <10>;
-                               hsync-len = <10>;
-                               vsync-len = <10>;
-                               hsync-active = <0>;
-                               vsync-active = <0>;
-                               de-active = <1>;
-                               pixelclk-active = <0>;
-                       };
-               };
-       };
-};
-
-&pwm3 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_pwm3>;
-       status = "okay";
-};
-
-&snvs_poweroff {
-       status = "okay";
-};
-
 &qspi2 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_qspi2>;
        status = "okay";
 
-       flash0: s25fl128s@0 {
-               reg = <0>;
+       flash0: n25q256a@0 {
                #address-cells = <1>;
                #size-cells = <1>;
-               compatible = "spansion,s25fl128s";
-               spi-max-frequency = <66000000>;
+               compatible = "micron,n25q256a";
+               spi-max-frequency = <29000000>;
+               reg = <0>;
        };
 
-       flash1: s25fl128s@1 {
-               reg = <1>;
+       flash1: n25q256a@1 {
                #address-cells = <1>;
                #size-cells = <1>;
-               compatible = "spansion,s25fl128s";
-               spi-max-frequency = <66000000>;
-       };
-};
-
-&ssi2 {
-       status = "okay";
-};
-
-&uart1 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart1>;
-       status = "okay";
-};
-
-&uart5 { /* for bluetooth */
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_uart5>;
-       fsl,uart-has-rtscts;
-       status = "okay";
-};
-
-&usbotg1 {
-       vbus-supply = <&reg_usb_otg1_vbus>;
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_usb_otg1_id>;
-       status = "okay";
-};
-
-&usbotg2 {
-       vbus-supply = <&reg_usb_otg2_vbus>;
-       dr_mode = "host";
-       status = "okay";
-};
-
-&usdhc2 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_usdhc2>;
-       non-removable;
-       no-1-8-v;
-       keep-power-in-suspend;
-       enable-sdio-wakeup;
-       status = "okay";
-};
-
-&usdhc3 {
-       pinctrl-names = "default", "state_100mhz", "state_200mhz";
-       pinctrl-0 = <&pinctrl_usdhc3>;
-       pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
-       pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
-       bus-width = <8>;
-       cd-gpios = <&gpio2 10 GPIO_ACTIVE_HIGH>;
-       wp-gpios = <&gpio2 15 GPIO_ACTIVE_HIGH>;
-       keep-power-in-suspend;
-       enable-sdio-wakeup;
-       vmmc-supply = <&vcc_sd3>;
-       status = "okay";
-};
-
-&usdhc4 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_usdhc4>;
-       cd-gpios = <&gpio6 21 GPIO_ACTIVE_HIGH>;
-       wp-gpios = <&gpio6 20 GPIO_ACTIVE_HIGH>;
-       status = "okay";
-};
-
-&iomuxc {
-       imx6x-sdb {
-               pinctrl_audmux: audmuxgrp {
-                       fsl,pins = <
-                               MX6SX_PAD_CSI_DATA00__AUDMUX_AUD6_TXC   0x130b0
-                               MX6SX_PAD_CSI_DATA01__AUDMUX_AUD6_TXFS  0x130b0
-                               MX6SX_PAD_CSI_HSYNC__AUDMUX_AUD6_TXD    0x120b0
-                               MX6SX_PAD_CSI_VSYNC__AUDMUX_AUD6_RXD    0x130b0
-                               MX6SX_PAD_CSI_PIXCLK__AUDMUX_MCLK       0x130b0
-                       >;
-               };
-
-               pinctrl_enet1: enet1grp {
-                       fsl,pins = <
-                               MX6SX_PAD_ENET1_MDIO__ENET1_MDIO        0xa0b1
-                               MX6SX_PAD_ENET1_MDC__ENET1_MDC          0xa0b1
-                               MX6SX_PAD_RGMII1_TXC__ENET1_RGMII_TXC   0xa0b1
-                               MX6SX_PAD_RGMII1_TD0__ENET1_TX_DATA_0   0xa0b1
-                               MX6SX_PAD_RGMII1_TD1__ENET1_TX_DATA_1   0xa0b1
-                               MX6SX_PAD_RGMII1_TD2__ENET1_TX_DATA_2   0xa0b1
-                               MX6SX_PAD_RGMII1_TD3__ENET1_TX_DATA_3   0xa0b1
-                               MX6SX_PAD_RGMII1_TX_CTL__ENET1_TX_EN    0xa0b1
-                               MX6SX_PAD_RGMII1_RXC__ENET1_RX_CLK      0x3081
-                               MX6SX_PAD_RGMII1_RD0__ENET1_RX_DATA_0   0x3081
-                               MX6SX_PAD_RGMII1_RD1__ENET1_RX_DATA_1   0x3081
-                               MX6SX_PAD_RGMII1_RD2__ENET1_RX_DATA_2   0x3081
-                               MX6SX_PAD_RGMII1_RD3__ENET1_RX_DATA_3   0x3081
-                               MX6SX_PAD_RGMII1_RX_CTL__ENET1_RX_EN    0x3081
-                               MX6SX_PAD_ENET2_RX_CLK__ENET2_REF_CLK_25M       0x91
-                       >;
-               };
-
-               pinctrl_enet_3v3: enet3v3grp {
-                       fsl,pins = <
-                               MX6SX_PAD_ENET2_COL__GPIO2_IO_6         0x80000000
-                       >;
-               };
-
-               pinctrl_enet2: enet2grp {
-                       fsl,pins = <
-                               MX6SX_PAD_RGMII2_TXC__ENET2_RGMII_TXC   0xa0b9
-                               MX6SX_PAD_RGMII2_TD0__ENET2_TX_DATA_0   0xa0b1
-                               MX6SX_PAD_RGMII2_TD1__ENET2_TX_DATA_1   0xa0b1
-                               MX6SX_PAD_RGMII2_TD2__ENET2_TX_DATA_2   0xa0b1
-                               MX6SX_PAD_RGMII2_TD3__ENET2_TX_DATA_3   0xa0b1
-                               MX6SX_PAD_RGMII2_TX_CTL__ENET2_TX_EN    0xa0b1
-                               MX6SX_PAD_RGMII2_RXC__ENET2_RX_CLK      0x3081
-                               MX6SX_PAD_RGMII2_RD0__ENET2_RX_DATA_0   0x3081
-                               MX6SX_PAD_RGMII2_RD1__ENET2_RX_DATA_1   0x3081
-                               MX6SX_PAD_RGMII2_RD2__ENET2_RX_DATA_2   0x3081
-                               MX6SX_PAD_RGMII2_RD3__ENET2_RX_DATA_3   0x3081
-                               MX6SX_PAD_RGMII2_RX_CTL__ENET2_RX_EN    0x3081
-                       >;
-               };
-
-               pinctrl_gpio_keys: gpio_keysgrp {
-                       fsl,pins = <
-                               MX6SX_PAD_CSI_DATA04__GPIO1_IO_18 0x17059
-                               MX6SX_PAD_CSI_DATA05__GPIO1_IO_19 0x17059
-                       >;
-               };
-
-               pinctrl_i2c1: i2c1grp {
-                       fsl,pins = <
-                               MX6SX_PAD_GPIO1_IO01__I2C1_SDA          0x4001b8b1
-                               MX6SX_PAD_GPIO1_IO00__I2C1_SCL          0x4001b8b1
-                       >;
-               };
-
-               pinctrl_i2c4: i2c4grp {
-                       fsl,pins = <
-                               MX6SX_PAD_CSI_DATA07__I2C4_SDA          0x4001b8b1
-                               MX6SX_PAD_CSI_DATA06__I2C4_SCL          0x4001b8b1
-                       >;
-               };
-
-               pinctrl_lcd: lcdgrp {
-                       fsl,pins = <
-                               MX6SX_PAD_LCD1_DATA00__LCDIF1_DATA_0 0x4001b0b0
-                               MX6SX_PAD_LCD1_DATA01__LCDIF1_DATA_1 0x4001b0b0
-                               MX6SX_PAD_LCD1_DATA02__LCDIF1_DATA_2 0x4001b0b0
-                               MX6SX_PAD_LCD1_DATA03__LCDIF1_DATA_3 0x4001b0b0
-                               MX6SX_PAD_LCD1_DATA04__LCDIF1_DATA_4 0x4001b0b0
-                               MX6SX_PAD_LCD1_DATA05__LCDIF1_DATA_5 0x4001b0b0
-                               MX6SX_PAD_LCD1_DATA06__LCDIF1_DATA_6 0x4001b0b0
-                               MX6SX_PAD_LCD1_DATA07__LCDIF1_DATA_7 0x4001b0b0
-                               MX6SX_PAD_LCD1_DATA08__LCDIF1_DATA_8 0x4001b0b0
-                               MX6SX_PAD_LCD1_DATA09__LCDIF1_DATA_9 0x4001b0b0
-                               MX6SX_PAD_LCD1_DATA10__LCDIF1_DATA_10 0x4001b0b0
-                               MX6SX_PAD_LCD1_DATA11__LCDIF1_DATA_11 0x4001b0b0
-                               MX6SX_PAD_LCD1_DATA12__LCDIF1_DATA_12 0x4001b0b0
-                               MX6SX_PAD_LCD1_DATA13__LCDIF1_DATA_13 0x4001b0b0
-                               MX6SX_PAD_LCD1_DATA14__LCDIF1_DATA_14 0x4001b0b0
-                               MX6SX_PAD_LCD1_DATA15__LCDIF1_DATA_15 0x4001b0b0
-                               MX6SX_PAD_LCD1_DATA16__LCDIF1_DATA_16 0x4001b0b0
-                               MX6SX_PAD_LCD1_DATA17__LCDIF1_DATA_17 0x4001b0b0
-                               MX6SX_PAD_LCD1_DATA18__LCDIF1_DATA_18 0x4001b0b0
-                               MX6SX_PAD_LCD1_DATA19__LCDIF1_DATA_19 0x4001b0b0
-                               MX6SX_PAD_LCD1_DATA20__LCDIF1_DATA_20 0x4001b0b0
-                               MX6SX_PAD_LCD1_DATA21__LCDIF1_DATA_21 0x4001b0b0
-                               MX6SX_PAD_LCD1_DATA22__LCDIF1_DATA_22 0x4001b0b0
-                               MX6SX_PAD_LCD1_DATA23__LCDIF1_DATA_23 0x4001b0b0
-                               MX6SX_PAD_LCD1_CLK__LCDIF1_CLK  0x4001b0b0
-                               MX6SX_PAD_LCD1_ENABLE__LCDIF1_ENABLE 0x4001b0b0
-                               MX6SX_PAD_LCD1_VSYNC__LCDIF1_VSYNC 0x4001b0b0
-                               MX6SX_PAD_LCD1_HSYNC__LCDIF1_HSYNC 0x4001b0b0
-                               MX6SX_PAD_LCD1_RESET__GPIO3_IO_27 0x4001b0b0
-                       >;
-               };
-
-               pinctrl_peri_3v3: peri3v3grp {
-                       fsl,pins = <
-                               MX6SX_PAD_QSPI1A_DATA0__GPIO4_IO_16     0x80000000
-                       >;
-               };
-
-               pinctrl_pwm3: pwm3grp-1 {
-                       fsl,pins = <
-                               MX6SX_PAD_SD1_DATA2__PWM3_OUT 0x110b0
-                       >;
-               };
-
-               pinctrl_qspi2: qspi2grp {
-                       fsl,pins = <
-                               MX6SX_PAD_NAND_WP_B__QSPI2_A_DATA_0     0x70f1
-                               MX6SX_PAD_NAND_READY_B__QSPI2_A_DATA_1  0x70f1
-                               MX6SX_PAD_NAND_CE0_B__QSPI2_A_DATA_2    0x70f1
-                               MX6SX_PAD_NAND_CE1_B__QSPI2_A_DATA_3    0x70f1
-                               MX6SX_PAD_NAND_CLE__QSPI2_A_SCLK        0x70f1
-                               MX6SX_PAD_NAND_ALE__QSPI2_A_SS0_B       0x70f1
-                               MX6SX_PAD_NAND_DATA01__QSPI2_B_DATA_0   0x70f1
-                               MX6SX_PAD_NAND_DATA00__QSPI2_B_DATA_1   0x70f1
-                               MX6SX_PAD_NAND_WE_B__QSPI2_B_DATA_2     0x70f1
-                               MX6SX_PAD_NAND_RE_B__QSPI2_B_DATA_3     0x70f1
-                               MX6SX_PAD_NAND_DATA02__QSPI2_B_SCLK     0x70f1
-                               MX6SX_PAD_NAND_DATA03__QSPI2_B_SS0_B    0x70f1
-                       >;
-               };
-
-               pinctrl_vcc_sd3: vccsd3grp {
-                       fsl,pins = <
-                               MX6SX_PAD_KEY_COL1__GPIO2_IO_11         0x17059
-                       >;
-               };
-
-               pinctrl_uart1: uart1grp {
-                       fsl,pins = <
-                               MX6SX_PAD_GPIO1_IO04__UART1_TX          0x1b0b1
-                               MX6SX_PAD_GPIO1_IO05__UART1_RX          0x1b0b1
-                       >;
-               };
-
-               pinctrl_uart5: uart5grp {
-                       fsl,pins = <
-                               MX6SX_PAD_KEY_ROW3__UART5_RX            0x1b0b1
-                               MX6SX_PAD_KEY_COL3__UART5_TX            0x1b0b1
-                               MX6SX_PAD_KEY_ROW2__UART5_CTS_B         0x1b0b1
-                               MX6SX_PAD_KEY_COL2__UART5_RTS_B         0x1b0b1
-                       >;
-               };
-
-               pinctrl_usb_otg1: usbotg1grp {
-                       fsl,pins = <
-                               MX6SX_PAD_GPIO1_IO09__GPIO1_IO_9        0x10b0
-                       >;
-               };
-
-               pinctrl_usb_otg1_id: usbotg1idgrp {
-                       fsl,pins = <
-                               MX6SX_PAD_GPIO1_IO10__ANATOP_OTG1_ID    0x17059
-                       >;
-               };
-
-               pinctrl_usb_otg2: usbot2ggrp {
-                       fsl,pins = <
-                               MX6SX_PAD_GPIO1_IO12__GPIO1_IO_12       0x10b0
-                       >;
-               };
-
-               pinctrl_usdhc2: usdhc2grp {
-                       fsl,pins = <
-                               MX6SX_PAD_SD2_CMD__USDHC2_CMD           0x17059
-                               MX6SX_PAD_SD2_CLK__USDHC2_CLK           0x10059
-                               MX6SX_PAD_SD2_DATA0__USDHC2_DATA0       0x17059
-                               MX6SX_PAD_SD2_DATA1__USDHC2_DATA1       0x17059
-                               MX6SX_PAD_SD2_DATA2__USDHC2_DATA2       0x17059
-                               MX6SX_PAD_SD2_DATA3__USDHC2_DATA3       0x17059
-                       >;
-               };
-
-               pinctrl_usdhc3: usdhc3grp {
-                       fsl,pins = <
-                               MX6SX_PAD_SD3_CMD__USDHC3_CMD           0x17059
-                               MX6SX_PAD_SD3_CLK__USDHC3_CLK           0x10059
-                               MX6SX_PAD_SD3_DATA0__USDHC3_DATA0       0x17059
-                               MX6SX_PAD_SD3_DATA1__USDHC3_DATA1       0x17059
-                               MX6SX_PAD_SD3_DATA2__USDHC3_DATA2       0x17059
-                               MX6SX_PAD_SD3_DATA3__USDHC3_DATA3       0x17059
-                               MX6SX_PAD_SD3_DATA4__USDHC3_DATA4       0x17059
-                               MX6SX_PAD_SD3_DATA5__USDHC3_DATA5       0x17059
-                               MX6SX_PAD_SD3_DATA6__USDHC3_DATA6       0x17059
-                               MX6SX_PAD_SD3_DATA7__USDHC3_DATA7       0x17059
-                               MX6SX_PAD_KEY_COL0__GPIO2_IO_10         0x17059 /* CD */
-                               MX6SX_PAD_KEY_ROW0__GPIO2_IO_15         0x17059 /* WP */
-                       >;
-               };
-
-               pinctrl_usdhc3_100mhz: usdhc3grp-100mhz {
-                       fsl,pins = <
-                               MX6SX_PAD_SD3_CMD__USDHC3_CMD           0x170b9
-                               MX6SX_PAD_SD3_CLK__USDHC3_CLK           0x100b9
-                               MX6SX_PAD_SD3_DATA0__USDHC3_DATA0       0x170b9
-                               MX6SX_PAD_SD3_DATA1__USDHC3_DATA1       0x170b9
-                               MX6SX_PAD_SD3_DATA2__USDHC3_DATA2       0x170b9
-                               MX6SX_PAD_SD3_DATA3__USDHC3_DATA3       0x170b9
-                               MX6SX_PAD_SD3_DATA4__USDHC3_DATA4       0x170b9
-                               MX6SX_PAD_SD3_DATA5__USDHC3_DATA5       0x170b9
-                               MX6SX_PAD_SD3_DATA6__USDHC3_DATA6       0x170b9
-                               MX6SX_PAD_SD3_DATA7__USDHC3_DATA7       0x170b9
-                       >;
-               };
-
-               pinctrl_usdhc3_200mhz: usdhc3grp-200mhz {
-                       fsl,pins = <
-                               MX6SX_PAD_SD3_CMD__USDHC3_CMD           0x170f9
-                               MX6SX_PAD_SD3_CLK__USDHC3_CLK           0x100f9
-                               MX6SX_PAD_SD3_DATA0__USDHC3_DATA0       0x170f9
-                               MX6SX_PAD_SD3_DATA1__USDHC3_DATA1       0x170f9
-                               MX6SX_PAD_SD3_DATA2__USDHC3_DATA2       0x170f9
-                               MX6SX_PAD_SD3_DATA3__USDHC3_DATA3       0x170f9
-                               MX6SX_PAD_SD3_DATA4__USDHC3_DATA4       0x170f9
-                               MX6SX_PAD_SD3_DATA5__USDHC3_DATA5       0x170f9
-                               MX6SX_PAD_SD3_DATA6__USDHC3_DATA6       0x170f9
-                               MX6SX_PAD_SD3_DATA7__USDHC3_DATA7       0x170f9
-                       >;
-               };
-
-               pinctrl_usdhc4: usdhc4grp {
-                       fsl,pins = <
-                               MX6SX_PAD_SD4_CMD__USDHC4_CMD           0x17059
-                               MX6SX_PAD_SD4_CLK__USDHC4_CLK           0x10059
-                               MX6SX_PAD_SD4_DATA0__USDHC4_DATA0       0x17059
-                               MX6SX_PAD_SD4_DATA1__USDHC4_DATA1       0x17059
-                               MX6SX_PAD_SD4_DATA2__USDHC4_DATA2       0x17059
-                               MX6SX_PAD_SD4_DATA3__USDHC4_DATA3       0x17059
-                               MX6SX_PAD_SD4_DATA7__GPIO6_IO_21        0x17059 /* CD */
-                               MX6SX_PAD_SD4_DATA6__GPIO6_IO_20        0x17059 /* WP */
-                       >;
-               };
+               compatible = "micron,n25q256a";
+               spi-max-frequency = <29000000>;
+               reg = <1>;
        };
 };
diff --git a/arch/arm/boot/dts/imx6sx-sdb.dtsi b/arch/arm/boot/dts/imx6sx-sdb.dtsi
new file mode 100644 (file)
index 0000000..cef04ce
--- /dev/null
@@ -0,0 +1,562 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include "imx6sx.dtsi"
+
+/ {
+       model = "Freescale i.MX6 SoloX SDB Board";
+       compatible = "fsl,imx6sx-sdb", "fsl,imx6sx";
+
+       chosen {
+               stdout-path = &uart1;
+       };
+
+       memory {
+               reg = <0x80000000 0x40000000>;
+       };
+
+       backlight {
+               compatible = "pwm-backlight";
+               pwms = <&pwm3 0 5000000>;
+               brightness-levels = <0 4 8 16 32 64 128 255>;
+               default-brightness-level = <6>;
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_gpio_keys>;
+
+               volume-up {
+                       label = "Volume Up";
+                       gpios = <&gpio1 18 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_VOLUMEUP>;
+               };
+
+               volume-down {
+                       label = "Volume Down";
+                       gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_VOLUMEDOWN>;
+               };
+       };
+
+       regulators {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               vcc_sd3: regulator@0 {
+                       compatible = "regulator-fixed";
+                       reg = <0>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_vcc_sd3>;
+                       regulator-name = "VCC_SD3";
+                       regulator-min-microvolt = <3000000>;
+                       regulator-max-microvolt = <3000000>;
+                       gpio = <&gpio2 11 GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+               };
+
+               reg_usb_otg1_vbus: regulator@1 {
+                       compatible = "regulator-fixed";
+                       reg = <1>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_usb_otg1>;
+                       regulator-name = "usb_otg1_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+               };
+
+               reg_usb_otg2_vbus: regulator@2 {
+                       compatible = "regulator-fixed";
+                       reg = <2>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_usb_otg2>;
+                       regulator-name = "usb_otg2_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+               };
+
+               reg_psu_5v: regulator@3 {
+                       compatible = "regulator-fixed";
+                       reg = <3>;
+                       regulator-name = "PSU-5V0";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+               };
+
+               reg_lcd_3v3: regulator@4 {
+                       compatible = "regulator-fixed";
+                       reg = <4>;
+                       regulator-name = "lcd-3v3";
+                       gpio = <&gpio3 27 0>;
+                       enable-active-high;
+               };
+
+               reg_peri_3v3: regulator@5 {
+                       compatible = "regulator-fixed";
+                       reg = <5>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_peri_3v3>;
+                       regulator-name = "peri_3v3";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       gpios = <&gpio4 16 GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+                       regulator-always-on;
+               };
+
+               reg_enet_3v3: regulator@6 {
+                       compatible = "regulator-fixed";
+                       reg = <6>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_enet_3v3>;
+                       regulator-name = "enet_3v3";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       gpios = <&gpio2 6 GPIO_ACTIVE_LOW>;
+               };
+       };
+
+       sound {
+               compatible = "fsl,imx6sx-sdb-wm8962", "fsl,imx-audio-wm8962";
+               model = "wm8962-audio";
+               ssi-controller = <&ssi2>;
+               audio-codec = <&codec>;
+               audio-routing =
+                       "Headphone Jack", "HPOUTL",
+                       "Headphone Jack", "HPOUTR",
+                       "Ext Spk", "SPKOUTL",
+                       "Ext Spk", "SPKOUTR",
+                       "AMIC", "MICBIAS",
+                       "IN3R", "AMIC";
+               mux-int-port = <2>;
+               mux-ext-port = <6>;
+       };
+};
+
+&audmux {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_audmux>;
+       status = "okay";
+};
+
+&fec1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_enet1>;
+       phy-supply = <&reg_enet_3v3>;
+       phy-mode = "rgmii";
+       phy-handle = <&ethphy1>;
+       status = "okay";
+
+       mdio {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               ethphy1: ethernet-phy@1 {
+                       reg = <1>;
+               };
+
+               ethphy2: ethernet-phy@2 {
+                       reg = <2>;
+               };
+       };
+};
+
+&fec2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_enet2>;
+       phy-mode = "rgmii";
+       phy-handle = <&ethphy2>;
+       status = "okay";
+};
+
+&i2c4 {
+        clock-frequency = <100000>;
+        pinctrl-names = "default";
+        pinctrl-0 = <&pinctrl_i2c4>;
+        status = "okay";
+
+       codec: wm8962@1a {
+               compatible = "wlf,wm8962";
+               reg = <0x1a>;
+               clocks = <&clks IMX6SX_CLK_AUDIO>;
+               DCVDD-supply = <&vgen4_reg>;
+               DBVDD-supply = <&vgen4_reg>;
+               AVDD-supply = <&vgen4_reg>;
+               CPVDD-supply = <&vgen4_reg>;
+               MICVDD-supply = <&vgen3_reg>;
+               PLLVDD-supply = <&vgen4_reg>;
+               SPKVDD1-supply = <&reg_psu_5v>;
+               SPKVDD2-supply = <&reg_psu_5v>;
+       };
+};
+
+&lcdif1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_lcd>;
+       lcd-supply = <&reg_lcd_3v3>;
+       display = <&display0>;
+       status = "okay";
+
+       display0: display0 {
+               bits-per-pixel = <16>;
+               bus-width = <24>;
+
+               display-timings {
+                       native-mode = <&timing0>;
+                       timing0: timing0 {
+                               clock-frequency = <33500000>;
+                               hactive = <800>;
+                               vactive = <480>;
+                               hback-porch = <89>;
+                               hfront-porch = <164>;
+                               vback-porch = <23>;
+                               vfront-porch = <10>;
+                               hsync-len = <10>;
+                               vsync-len = <10>;
+                               hsync-active = <0>;
+                               vsync-active = <0>;
+                               de-active = <1>;
+                               pixelclk-active = <0>;
+                       };
+               };
+       };
+};
+
+&pwm3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_pwm3>;
+       status = "okay";
+};
+
+&snvs_poweroff {
+       status = "okay";
+};
+
+&ssi2 {
+       status = "okay";
+};
+
+&uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart1>;
+       status = "okay";
+};
+
+&uart5 { /* for bluetooth */
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart5>;
+       fsl,uart-has-rtscts;
+       status = "okay";
+};
+
+&usbotg1 {
+       vbus-supply = <&reg_usb_otg1_vbus>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usb_otg1_id>;
+       status = "okay";
+};
+
+&usbotg2 {
+       vbus-supply = <&reg_usb_otg2_vbus>;
+       dr_mode = "host";
+       status = "okay";
+};
+
+&usdhc2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usdhc2>;
+       non-removable;
+       no-1-8-v;
+       keep-power-in-suspend;
+       enable-sdio-wakeup;
+       status = "okay";
+};
+
+&usdhc3 {
+       pinctrl-names = "default", "state_100mhz", "state_200mhz";
+       pinctrl-0 = <&pinctrl_usdhc3>;
+       pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+       pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
+       bus-width = <8>;
+       cd-gpios = <&gpio2 10 GPIO_ACTIVE_HIGH>;
+       wp-gpios = <&gpio2 15 GPIO_ACTIVE_HIGH>;
+       keep-power-in-suspend;
+       enable-sdio-wakeup;
+       vmmc-supply = <&vcc_sd3>;
+       status = "okay";
+};
+
+&usdhc4 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usdhc4>;
+       cd-gpios = <&gpio6 21 GPIO_ACTIVE_HIGH>;
+       wp-gpios = <&gpio6 20 GPIO_ACTIVE_HIGH>;
+       status = "okay";
+};
+
+&iomuxc {
+       imx6x-sdb {
+               pinctrl_audmux: audmuxgrp {
+                       fsl,pins = <
+                               MX6SX_PAD_CSI_DATA00__AUDMUX_AUD6_TXC   0x130b0
+                               MX6SX_PAD_CSI_DATA01__AUDMUX_AUD6_TXFS  0x130b0
+                               MX6SX_PAD_CSI_HSYNC__AUDMUX_AUD6_TXD    0x120b0
+                               MX6SX_PAD_CSI_VSYNC__AUDMUX_AUD6_RXD    0x130b0
+                               MX6SX_PAD_CSI_PIXCLK__AUDMUX_MCLK       0x130b0
+                       >;
+               };
+
+               pinctrl_enet1: enet1grp {
+                       fsl,pins = <
+                               MX6SX_PAD_ENET1_MDIO__ENET1_MDIO        0xa0b1
+                               MX6SX_PAD_ENET1_MDC__ENET1_MDC          0xa0b1
+                               MX6SX_PAD_RGMII1_TXC__ENET1_RGMII_TXC   0xa0b1
+                               MX6SX_PAD_RGMII1_TD0__ENET1_TX_DATA_0   0xa0b1
+                               MX6SX_PAD_RGMII1_TD1__ENET1_TX_DATA_1   0xa0b1
+                               MX6SX_PAD_RGMII1_TD2__ENET1_TX_DATA_2   0xa0b1
+                               MX6SX_PAD_RGMII1_TD3__ENET1_TX_DATA_3   0xa0b1
+                               MX6SX_PAD_RGMII1_TX_CTL__ENET1_TX_EN    0xa0b1
+                               MX6SX_PAD_RGMII1_RXC__ENET1_RX_CLK      0x3081
+                               MX6SX_PAD_RGMII1_RD0__ENET1_RX_DATA_0   0x3081
+                               MX6SX_PAD_RGMII1_RD1__ENET1_RX_DATA_1   0x3081
+                               MX6SX_PAD_RGMII1_RD2__ENET1_RX_DATA_2   0x3081
+                               MX6SX_PAD_RGMII1_RD3__ENET1_RX_DATA_3   0x3081
+                               MX6SX_PAD_RGMII1_RX_CTL__ENET1_RX_EN    0x3081
+                               MX6SX_PAD_ENET2_RX_CLK__ENET2_REF_CLK_25M       0x91
+                       >;
+               };
+
+               pinctrl_enet_3v3: enet3v3grp {
+                       fsl,pins = <
+                               MX6SX_PAD_ENET2_COL__GPIO2_IO_6         0x80000000
+                       >;
+               };
+
+               pinctrl_enet2: enet2grp {
+                       fsl,pins = <
+                               MX6SX_PAD_RGMII2_TXC__ENET2_RGMII_TXC   0xa0b9
+                               MX6SX_PAD_RGMII2_TD0__ENET2_TX_DATA_0   0xa0b1
+                               MX6SX_PAD_RGMII2_TD1__ENET2_TX_DATA_1   0xa0b1
+                               MX6SX_PAD_RGMII2_TD2__ENET2_TX_DATA_2   0xa0b1
+                               MX6SX_PAD_RGMII2_TD3__ENET2_TX_DATA_3   0xa0b1
+                               MX6SX_PAD_RGMII2_TX_CTL__ENET2_TX_EN    0xa0b1
+                               MX6SX_PAD_RGMII2_RXC__ENET2_RX_CLK      0x3081
+                               MX6SX_PAD_RGMII2_RD0__ENET2_RX_DATA_0   0x3081
+                               MX6SX_PAD_RGMII2_RD1__ENET2_RX_DATA_1   0x3081
+                               MX6SX_PAD_RGMII2_RD2__ENET2_RX_DATA_2   0x3081
+                               MX6SX_PAD_RGMII2_RD3__ENET2_RX_DATA_3   0x3081
+                               MX6SX_PAD_RGMII2_RX_CTL__ENET2_RX_EN    0x3081
+                       >;
+               };
+
+               pinctrl_gpio_keys: gpio_keysgrp {
+                       fsl,pins = <
+                               MX6SX_PAD_CSI_DATA04__GPIO1_IO_18 0x17059
+                               MX6SX_PAD_CSI_DATA05__GPIO1_IO_19 0x17059
+                       >;
+               };
+
+               pinctrl_i2c1: i2c1grp {
+                       fsl,pins = <
+                               MX6SX_PAD_GPIO1_IO01__I2C1_SDA          0x4001b8b1
+                               MX6SX_PAD_GPIO1_IO00__I2C1_SCL          0x4001b8b1
+                       >;
+               };
+
+               pinctrl_i2c4: i2c4grp {
+                       fsl,pins = <
+                               MX6SX_PAD_CSI_DATA07__I2C4_SDA          0x4001b8b1
+                               MX6SX_PAD_CSI_DATA06__I2C4_SCL          0x4001b8b1
+                       >;
+               };
+
+               pinctrl_lcd: lcdgrp {
+                       fsl,pins = <
+                               MX6SX_PAD_LCD1_DATA00__LCDIF1_DATA_0 0x4001b0b0
+                               MX6SX_PAD_LCD1_DATA01__LCDIF1_DATA_1 0x4001b0b0
+                               MX6SX_PAD_LCD1_DATA02__LCDIF1_DATA_2 0x4001b0b0
+                               MX6SX_PAD_LCD1_DATA03__LCDIF1_DATA_3 0x4001b0b0
+                               MX6SX_PAD_LCD1_DATA04__LCDIF1_DATA_4 0x4001b0b0
+                               MX6SX_PAD_LCD1_DATA05__LCDIF1_DATA_5 0x4001b0b0
+                               MX6SX_PAD_LCD1_DATA06__LCDIF1_DATA_6 0x4001b0b0
+                               MX6SX_PAD_LCD1_DATA07__LCDIF1_DATA_7 0x4001b0b0
+                               MX6SX_PAD_LCD1_DATA08__LCDIF1_DATA_8 0x4001b0b0
+                               MX6SX_PAD_LCD1_DATA09__LCDIF1_DATA_9 0x4001b0b0
+                               MX6SX_PAD_LCD1_DATA10__LCDIF1_DATA_10 0x4001b0b0
+                               MX6SX_PAD_LCD1_DATA11__LCDIF1_DATA_11 0x4001b0b0
+                               MX6SX_PAD_LCD1_DATA12__LCDIF1_DATA_12 0x4001b0b0
+                               MX6SX_PAD_LCD1_DATA13__LCDIF1_DATA_13 0x4001b0b0
+                               MX6SX_PAD_LCD1_DATA14__LCDIF1_DATA_14 0x4001b0b0
+                               MX6SX_PAD_LCD1_DATA15__LCDIF1_DATA_15 0x4001b0b0
+                               MX6SX_PAD_LCD1_DATA16__LCDIF1_DATA_16 0x4001b0b0
+                               MX6SX_PAD_LCD1_DATA17__LCDIF1_DATA_17 0x4001b0b0
+                               MX6SX_PAD_LCD1_DATA18__LCDIF1_DATA_18 0x4001b0b0
+                               MX6SX_PAD_LCD1_DATA19__LCDIF1_DATA_19 0x4001b0b0
+                               MX6SX_PAD_LCD1_DATA20__LCDIF1_DATA_20 0x4001b0b0
+                               MX6SX_PAD_LCD1_DATA21__LCDIF1_DATA_21 0x4001b0b0
+                               MX6SX_PAD_LCD1_DATA22__LCDIF1_DATA_22 0x4001b0b0
+                               MX6SX_PAD_LCD1_DATA23__LCDIF1_DATA_23 0x4001b0b0
+                               MX6SX_PAD_LCD1_CLK__LCDIF1_CLK  0x4001b0b0
+                               MX6SX_PAD_LCD1_ENABLE__LCDIF1_ENABLE 0x4001b0b0
+                               MX6SX_PAD_LCD1_VSYNC__LCDIF1_VSYNC 0x4001b0b0
+                               MX6SX_PAD_LCD1_HSYNC__LCDIF1_HSYNC 0x4001b0b0
+                               MX6SX_PAD_LCD1_RESET__GPIO3_IO_27 0x4001b0b0
+                       >;
+               };
+
+               pinctrl_peri_3v3: peri3v3grp {
+                       fsl,pins = <
+                               MX6SX_PAD_QSPI1A_DATA0__GPIO4_IO_16     0x80000000
+                       >;
+               };
+
+               pinctrl_pwm3: pwm3grp-1 {
+                       fsl,pins = <
+                               MX6SX_PAD_SD1_DATA2__PWM3_OUT 0x110b0
+                       >;
+               };
+
+               pinctrl_qspi2: qspi2grp {
+                       fsl,pins = <
+                               MX6SX_PAD_NAND_WP_B__QSPI2_A_DATA_0     0x70f1
+                               MX6SX_PAD_NAND_READY_B__QSPI2_A_DATA_1  0x70f1
+                               MX6SX_PAD_NAND_CE0_B__QSPI2_A_DATA_2    0x70f1
+                               MX6SX_PAD_NAND_CE1_B__QSPI2_A_DATA_3    0x70f1
+                               MX6SX_PAD_NAND_CLE__QSPI2_A_SCLK        0x70f1
+                               MX6SX_PAD_NAND_ALE__QSPI2_A_SS0_B       0x70f1
+                               MX6SX_PAD_NAND_DATA01__QSPI2_B_DATA_0   0x70f1
+                               MX6SX_PAD_NAND_DATA00__QSPI2_B_DATA_1   0x70f1
+                               MX6SX_PAD_NAND_WE_B__QSPI2_B_DATA_2     0x70f1
+                               MX6SX_PAD_NAND_RE_B__QSPI2_B_DATA_3     0x70f1
+                               MX6SX_PAD_NAND_DATA02__QSPI2_B_SCLK     0x70f1
+                               MX6SX_PAD_NAND_DATA03__QSPI2_B_SS0_B    0x70f1
+                       >;
+               };
+
+               pinctrl_vcc_sd3: vccsd3grp {
+                       fsl,pins = <
+                               MX6SX_PAD_KEY_COL1__GPIO2_IO_11         0x17059
+                       >;
+               };
+
+               pinctrl_uart1: uart1grp {
+                       fsl,pins = <
+                               MX6SX_PAD_GPIO1_IO04__UART1_TX          0x1b0b1
+                               MX6SX_PAD_GPIO1_IO05__UART1_RX          0x1b0b1
+                       >;
+               };
+
+               pinctrl_uart5: uart5grp {
+                       fsl,pins = <
+                               MX6SX_PAD_KEY_ROW3__UART5_RX            0x1b0b1
+                               MX6SX_PAD_KEY_COL3__UART5_TX            0x1b0b1
+                               MX6SX_PAD_KEY_ROW2__UART5_CTS_B         0x1b0b1
+                               MX6SX_PAD_KEY_COL2__UART5_RTS_B         0x1b0b1
+                       >;
+               };
+
+               pinctrl_usb_otg1: usbotg1grp {
+                       fsl,pins = <
+                               MX6SX_PAD_GPIO1_IO09__GPIO1_IO_9        0x10b0
+                       >;
+               };
+
+               pinctrl_usb_otg1_id: usbotg1idgrp {
+                       fsl,pins = <
+                               MX6SX_PAD_GPIO1_IO10__ANATOP_OTG1_ID    0x17059
+                       >;
+               };
+
+               pinctrl_usb_otg2: usbot2ggrp {
+                       fsl,pins = <
+                               MX6SX_PAD_GPIO1_IO12__GPIO1_IO_12       0x10b0
+                       >;
+               };
+
+               pinctrl_usdhc2: usdhc2grp {
+                       fsl,pins = <
+                               MX6SX_PAD_SD2_CMD__USDHC2_CMD           0x17059
+                               MX6SX_PAD_SD2_CLK__USDHC2_CLK           0x10059
+                               MX6SX_PAD_SD2_DATA0__USDHC2_DATA0       0x17059
+                               MX6SX_PAD_SD2_DATA1__USDHC2_DATA1       0x17059
+                               MX6SX_PAD_SD2_DATA2__USDHC2_DATA2       0x17059
+                               MX6SX_PAD_SD2_DATA3__USDHC2_DATA3       0x17059
+                       >;
+               };
+
+               pinctrl_usdhc3: usdhc3grp {
+                       fsl,pins = <
+                               MX6SX_PAD_SD3_CMD__USDHC3_CMD           0x17059
+                               MX6SX_PAD_SD3_CLK__USDHC3_CLK           0x10059
+                               MX6SX_PAD_SD3_DATA0__USDHC3_DATA0       0x17059
+                               MX6SX_PAD_SD3_DATA1__USDHC3_DATA1       0x17059
+                               MX6SX_PAD_SD3_DATA2__USDHC3_DATA2       0x17059
+                               MX6SX_PAD_SD3_DATA3__USDHC3_DATA3       0x17059
+                               MX6SX_PAD_SD3_DATA4__USDHC3_DATA4       0x17059
+                               MX6SX_PAD_SD3_DATA5__USDHC3_DATA5       0x17059
+                               MX6SX_PAD_SD3_DATA6__USDHC3_DATA6       0x17059
+                               MX6SX_PAD_SD3_DATA7__USDHC3_DATA7       0x17059
+                               MX6SX_PAD_KEY_COL0__GPIO2_IO_10         0x17059 /* CD */
+                               MX6SX_PAD_KEY_ROW0__GPIO2_IO_15         0x17059 /* WP */
+                       >;
+               };
+
+               pinctrl_usdhc3_100mhz: usdhc3grp-100mhz {
+                       fsl,pins = <
+                               MX6SX_PAD_SD3_CMD__USDHC3_CMD           0x170b9
+                               MX6SX_PAD_SD3_CLK__USDHC3_CLK           0x100b9
+                               MX6SX_PAD_SD3_DATA0__USDHC3_DATA0       0x170b9
+                               MX6SX_PAD_SD3_DATA1__USDHC3_DATA1       0x170b9
+                               MX6SX_PAD_SD3_DATA2__USDHC3_DATA2       0x170b9
+                               MX6SX_PAD_SD3_DATA3__USDHC3_DATA3       0x170b9
+                               MX6SX_PAD_SD3_DATA4__USDHC3_DATA4       0x170b9
+                               MX6SX_PAD_SD3_DATA5__USDHC3_DATA5       0x170b9
+                               MX6SX_PAD_SD3_DATA6__USDHC3_DATA6       0x170b9
+                               MX6SX_PAD_SD3_DATA7__USDHC3_DATA7       0x170b9
+                       >;
+               };
+
+               pinctrl_usdhc3_200mhz: usdhc3grp-200mhz {
+                       fsl,pins = <
+                               MX6SX_PAD_SD3_CMD__USDHC3_CMD           0x170f9
+                               MX6SX_PAD_SD3_CLK__USDHC3_CLK           0x100f9
+                               MX6SX_PAD_SD3_DATA0__USDHC3_DATA0       0x170f9
+                               MX6SX_PAD_SD3_DATA1__USDHC3_DATA1       0x170f9
+                               MX6SX_PAD_SD3_DATA2__USDHC3_DATA2       0x170f9
+                               MX6SX_PAD_SD3_DATA3__USDHC3_DATA3       0x170f9
+                               MX6SX_PAD_SD3_DATA4__USDHC3_DATA4       0x170f9
+                               MX6SX_PAD_SD3_DATA5__USDHC3_DATA5       0x170f9
+                               MX6SX_PAD_SD3_DATA6__USDHC3_DATA6       0x170f9
+                               MX6SX_PAD_SD3_DATA7__USDHC3_DATA7       0x170f9
+                       >;
+               };
+
+               pinctrl_usdhc4: usdhc4grp {
+                       fsl,pins = <
+                               MX6SX_PAD_SD4_CMD__USDHC4_CMD           0x17059
+                               MX6SX_PAD_SD4_CLK__USDHC4_CLK           0x10059
+                               MX6SX_PAD_SD4_DATA0__USDHC4_DATA0       0x17059
+                               MX6SX_PAD_SD4_DATA1__USDHC4_DATA1       0x17059
+                               MX6SX_PAD_SD4_DATA2__USDHC4_DATA2       0x17059
+                               MX6SX_PAD_SD4_DATA3__USDHC4_DATA3       0x17059
+                               MX6SX_PAD_SD4_DATA7__GPIO6_IO_21        0x17059 /* CD */
+                               MX6SX_PAD_SD4_DATA6__GPIO6_IO_20        0x17059 /* WP */
+                       >;
+               };
+       };
+};
index 7a24fee1e7aecf7bc16df8c241e42a5ba5e5e561..708175d59b9c31085877da68ad378765fe701369 100644 (file)
@@ -88,6 +88,7 @@
                interrupt-controller;
                reg = <0x00a01000 0x1000>,
                      <0x00a00100 0x100>;
+               interrupt-parent = <&intc>;
        };
 
        clocks {
                #address-cells = <1>;
                #size-cells = <1>;
                compatible = "simple-bus";
-               interrupt-parent = <&intc>;
+               interrupt-parent = <&gpc>;
                ranges;
 
                pmu {
                                #size-cells = <1>;
                                ranges = <0 0x020cc000 0x4000>;
 
-                               snvs-rtc-lp@34 {
+                               snvs_rtc: snvs-rtc-lp@34 {
                                        compatible = "fsl,sec-v4.0-mon-rtc-lp";
                                        reg = <0x34 0x58>;
                                        interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
                        gpc: gpc@020dc000 {
                                compatible = "fsl,imx6sx-gpc", "fsl,imx6q-gpc";
                                reg = <0x020dc000 0x4000>;
+                               interrupt-controller;
+                               #interrupt-cells = <3>;
                                interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-parent = <&intc>;
                        };
 
                        iomuxc: iomuxc@020e0000 {
                                fsl,usbmisc = <&usbmisc 2>;
                                phy_type = "hsic";
                                fsl,anatop = <&anatop>;
+                               dr_mode = "host";
                                status = "disabled";
                        };
 
diff --git a/arch/arm/boot/dts/kirkwood-nas2big.dts b/arch/arm/boot/dts/kirkwood-nas2big.dts
new file mode 100644 (file)
index 0000000..7427ec5
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Device Tree file for LaCie 2Big NAS
+ *
+ * Copyright (C) 2015 Seagate
+ *
+ * Author: Simon Guinot <simon.guinot@sequanux.org>
+ *
+ * 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/;
+
+#include "kirkwood-netxbig.dtsi"
+
+/ {
+       model = "LaCie 2Big NAS";
+       compatible = "lacie,nas2big", "lacie,netxbig", "marvell,kirkwood-88f6282", "marvell,kirkwood";
+
+       memory {
+               device_type = "memory";
+               reg = <0x00000000 0x10000000>;
+       };
+
+       chosen {
+               bootargs = "console=ttyS0,115200n8";
+               stdout-path = &uart0;
+       };
+
+       mbus {
+               pcie-controller {
+                       status = "okay";
+
+                       pcie@1,0 {
+                               status = "okay";
+                       };
+               };
+       };
+
+       ocp@f1000000 {
+               rtc@10300 {
+                       /* The on-chip RTC is not powered (no supercap). */
+                       status = "disabled";
+               };
+               spi@10600 {
+                       /*
+                        * A NAND flash is used instead of an SPI flash for
+                        * the other netxbig-compatible boards.
+                        */
+                       status = "disabled";
+               };
+       };
+
+       fan {
+               /*
+                * An I2C fan controller (GMT G762) is used but alarm is
+                * wired to a separate GPIO.
+                */
+               compatible = "gpio-fan";
+               alarm-gpios = <&gpio0 25 GPIO_ACTIVE_LOW>;
+       };
+
+       regulators: regulators {
+               status = "okay";
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               pinctrl-names = "default";
+
+               regulator@2 {
+                       compatible = "regulator-fixed";
+                       reg = <2>;
+                       regulator-name = "hdd1power";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       enable-active-high;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       gpio = <&gpio0 17 GPIO_ACTIVE_HIGH>;
+               };
+               clocks {
+                       g762_clk: g762-oscillator {
+                               compatible = "fixed-clock";
+                               #clock-cells = <0>;
+                               clock-frequency = <32768>;
+                       };
+               };
+       };
+};
+
+&mdio {
+       status = "okay";
+
+       ethphy0: ethernet-phy@0 {
+               reg = <0>;
+       };
+};
+
+&i2c0 {
+       status = "okay";
+
+       /*
+        * An external I2C RTC (Dallas DS1337S+) is used. This allows
+        * to power-up the board on an RTC alarm. The external RTC can
+        * be kept powered, even when the SoC is off.
+        */
+       rtc@68 {
+               compatible = "dallas,ds1307";
+               reg = <0x68>;
+               interrupts = <43>;
+       };
+       g762@3e {
+               compatible = "gmt,g762";
+               reg = <0x3e>;
+               clocks = <&g762_clk>;
+       };
+};
+
+&nand {
+       chip-delay = <50>;
+       status = "okay";
+
+       partition@0 {
+               label = "U-Boot";
+               reg = <0x0 0x100000>;
+       };
+
+       partition@100000 {
+               label = "uImage";
+               reg = <0x100000 0x1000000>;
+       };
+
+       partition@1100000 {
+               label = "root";
+               reg = <0x1100000 0x8000000>;
+       };
+
+       partition@9100000 {
+               label = "unused";
+               reg = <0x9100000 0x6f00000>;
+       };
+};
index 53dc37a3b6875dd10fcbe9babee959de4f5a95bd..13a44773b6dfa39fe02d4ce86f3344808e498d1b 100644 (file)
                device_type = "memory";
                reg = <0x00000000 0x10000000>;
        };
+
+       fan {
+               compatible = "gpio-fan";
+               alarm-gpios = <&gpio0 25 GPIO_ACTIVE_LOW>;
+       };
 };
 
 &regulators {
index b67ede515bcdeb9decd615aac0a7b30b0951a30d..548441384d2a39488d7daffef79ed6c707576a86 100644 (file)
                        interrupts = <0 15 1>;
                        status = "disabled";
                };
+
+               spifc: spi@c1108c80 {
+                       compatible = "amlogic,meson6-spifc";
+                       reg = <0xc1108c80 0x80>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       clocks = <&clk81>;
+                       status = "disabled";
+               };
+
+               ethmac: ethernet@c9410000 {
+                       compatible = "amlogic,meson6-dwmac", "snps,dwmac";
+                       reg = <0xc9410000 0x10000
+                              0xc1108108 0x4>;
+                       interrupts = <0 8 1>;
+                       interrupt-names = "macirq";
+                       clocks = <&clk81>;
+                       clock-names = "stmmaceth";
+                       status = "disabled";
+               };
        };
 }; /* end of / */
index d7d351a689447ea6449951200c632e19febf3b3b..1237faa63ce636d5c8c85d65b4cc9e32d9a5eab7 100644 (file)
@@ -64,3 +64,7 @@
 &uart_AO {
        status = "okay";
 };
+
+&ethmac {
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/meson8-minix-neo-x8.dts b/arch/arm/boot/dts/meson8-minix-neo-x8.dts
new file mode 100644 (file)
index 0000000..4f536bb
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2014 Beniamino Galvani <b.galvani@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 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/;
+#include <dt-bindings/gpio/gpio.h>
+#include "meson8.dtsi"
+
+/ {
+       model = "MINIX NEO-X8";
+       compatible = "minix,neo-x8", "amlogic,meson8";
+
+       aliases {
+               serial0 = &uart_AO;
+       };
+
+       memory {
+               reg = <0x40000000 0x80000000>;
+       };
+
+       gpio-leds {
+               compatible = "gpio-leds";
+
+               blue {
+                       label = "x8:blue:power";
+                       gpios = <&gpio_ao GPIO_TEST_N GPIO_ACTIVE_HIGH>;
+               };
+       };
+};
+
+&uart_AO {
+       status = "okay";
+       pinctrl-0 = <&uart_ao_a_pins>;
+       pinctrl-names = "default";
+};
+
+&i2c_AO {
+       status = "okay";
+       pinctrl-0 = <&i2c_ao_pins>;
+       pinctrl-names = "default";
+
+       pmic@32 {
+               compatible = "ricoh,rn5t618";
+               reg = <0x32>;
+
+               regulators {
+               };
+       };
+
+       rtc@51 {
+               compatible = "nxp,pcf8563";
+               reg = <0x51>;
+       };
+};
+
+&spifc {
+       status = "okay";
+       pinctrl-0 = <&spi_nor_pins>;
+       pinctrl-names = "default";
+
+       spi-flash@0 {
+               compatible = "mxicy,mx25l1606e";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               reg = <0>;
+               spi-max-frequency = <30000000>;
+
+               partition@0 {
+                       label = "boot";
+                       reg = <0x0 0x100000>;
+               };
+
+               partition@100000 {
+                       label = "env";
+                       reg = <0x100000 0x10000>;
+               };
+       };
+};
+
+&ir_receiver {
+       status = "okay";
+       pinctrl-0 = <&ir_recv_pins>;
+       pinctrl-names = "default";
+};
+
+&ethmac {
+       status = "okay";
+       pinctrl-0 = <&eth_pins>;
+       pnictrl-names = "default";
+};
index 1f442a7fe03b758905205630ce3409105a88625a..a2ddcb8c545a01ebdcc86d3c011e348f5295619b 100644 (file)
@@ -43,6 +43,7 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#include <dt-bindings/gpio/meson8-gpio.h>
 /include/ "meson.dtsi"
 
 / {
                compatible = "fixed-clock";
                clock-frequency = <141666666>;
        };
+
+       pinctrl: pinctrl@c1109880 {
+               compatible = "amlogic,meson8-pinctrl";
+               reg = <0xc1109880 0x10>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               gpio: banks@c11080b0 {
+                       reg = <0xc11080b0 0x28>,
+                             <0xc11080e8 0x18>,
+                             <0xc1108120 0x18>,
+                             <0xc1108030 0x30>;
+                       reg-names = "mux", "pull", "pull-enable", "gpio";
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               gpio_ao: ao-bank@c1108030 {
+                       reg = <0xc8100014 0x4>,
+                             <0xc810002c 0x4>,
+                             <0xc8100024 0x8>;
+                       reg-names = "mux", "pull", "gpio";
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               uart_ao_a_pins: uart_ao_a {
+                       mux {
+                               groups = "uart_tx_ao_a", "uart_rx_ao_a";
+                               function = "uart_ao";
+                       };
+               };
+
+               i2c_ao_pins: i2c_mst_ao {
+                       mux {
+                               groups = "i2c_mst_sck_ao", "i2c_mst_sda_ao";
+                               function = "i2c_mst_ao";
+                       };
+               };
+
+               spi_nor_pins: nor {
+                       mux {
+                               groups = "nor_d", "nor_q", "nor_c", "nor_cs";
+                               function = "nor";
+                       };
+               };
+
+               ir_recv_pins: remote {
+                       mux {
+                               groups = "remote_input";
+                               function = "remote";
+                       };
+               };
+
+               eth_pins: ethernet {
+                       mux {
+                               groups = "eth_tx_clk_50m", "eth_tx_en",
+                                        "eth_txd1", "eth_txd0",
+                                        "eth_rx_clk_in", "eth_rx_dv",
+                                        "eth_rxd1", "eth_rxd0", "eth_mdio",
+                                        "eth_mdc";
+                               function = "ethernet";
+                       };
+               };
+       };
+
 }; /* end of / */
index 106b61b1003032e88ca8a679ed1d2d56da561f10..88b3cb128698fb9d2e0abf9cfc46134b4538477e 100644 (file)
                        clocks = <&uart_clk>;
                        status = "disabled";
                };
+
+               wdt: watchdog@010000000 {
+                       compatible = "mediatek,mt6589-wdt";
+                       reg = <0x10000000 0x44>;
+               };
        };
 };
index 9565199bce7a0986e3641d0c5e421a6cfefef12c..4907c5085d4bd3c4947b4be2ae7d65611e0d79f9 100644 (file)
        compatible = "lsi,nspire-classic-ahb-divider";
 };
 
+
+&vbus_reg {
+       gpio = <&gpio 5 0>;
+};
+
 / {
        memory {
                device_type = "memory";
index 375b924f60d80326833c13e7fbfa5f54c87d37aa..08e0b81b338527463623244d91798364e20905f7 100644 (file)
        0x0709001d      0x070a0033      >;
 };
 
+&vbus_reg {
+       gpio = <&gpio 2 0>;
+};
+
 / {
        model = "TI-NSPIRE CX";
        compatible = "ti,nspire-cx";
index a22ffe633b49b36a3f0d49a243ef7e04841f1af2..390c91aea16d479e1b7cc10b6a82a278d2732c8f 100644 (file)
                clocks = <&ahb_clk>;
        };
 
+       usb_phy: usb_phy {
+               compatible = "usb-nop-xceiv";
+       };
+
+       vbus_reg: vbus_reg {
+               compatible = "regulator-fixed";
+
+               regulator-name = "USB VBUS output";
+               regulator-type = "voltage";
+
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+       };
+
        ahb {
                compatible = "simple-bus";
                #address-cells = <1>;
                };
 
                usb0: usb@B0000000 {
+                       compatible = "lsi,zevio-usb";
                        reg = <0xB0000000 0x1000>;
                        interrupts = <8>;
+
+                       usb-phy = <&usb_phy>;
+                       vbus-supply = <&vbus_reg>;
                };
 
                usb1: usb@B4000000 {
                        ranges;
 
                        gpio: gpio@90000000 {
+                               compatible = "lsi,zevio-gpio";
                                reg = <0x90000000 0x1000>;
                                interrupts = <7>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
                        };
 
                        fast_timer: timer@90010000 {
index e2b2e93d7b6160f364bcb4832cc593c09f9627ac..5b9a376cc31eee01e38a0cbd8a5cb16b8bf6c04f 100644 (file)
        compatible = "ti,omap2420", "ti,omap2";
 
        ocp {
-               prcm: prcm@48008000 {
-                       compatible = "ti,omap2-prcm";
-                       reg = <0x48008000 0x1000>;
+               l4: l4@48000000 {
+                       compatible = "ti,omap2-l4", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0 0x48000000 0x100000>;
 
-                       prcm_clocks: clocks {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                       };
+                       prcm: prcm@8000 {
+                               compatible = "ti,omap2-prcm";
+                               reg = <0x8000 0x1000>;
 
-                       prcm_clockdomains: clockdomains {
-                       };
-               };
+                               prcm_clocks: clocks {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                               };
 
-               scrm: scrm@48000000 {
-                       compatible = "ti,omap2-scrm";
-                       reg = <0x48000000 0x1000>;
+                               prcm_clockdomains: clockdomains {
+                               };
+                       };
 
-                       scrm_clocks: clocks {
+                       scm: scm@0 {
+                               compatible = "ti,omap2-scm", "simple-bus";
+                               reg = <0x0 0x1000>;
                                #address-cells = <1>;
-                               #size-cells = <0>;
+                               #size-cells = <1>;
+                               ranges = <0 0x0 0x1000>;
+
+                               omap2420_pmx: pinmux@30 {
+                                       compatible = "ti,omap2420-padconf",
+                                                    "pinctrl-single";
+                                       reg = <0x30 0x0113>;
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       pinctrl-single,register-width = <8>;
+                                       pinctrl-single,function-mask = <0x3f>;
+                               };
+
+                               scm_conf: scm_conf@270 {
+                                       compatible = "syscon";
+                                       reg = <0x270 0x100>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       scm_clocks: clocks {
+                                               #address-cells = <1>;
+                                               #size-cells = <0>;
+                                       };
+                               };
+
+                               scm_clockdomains: clockdomains {
+                               };
                        };
 
-                       scrm_clockdomains: clockdomains {
+                       counter32k: counter@4000 {
+                               compatible = "ti,omap-counter32k";
+                               reg = <0x4000 0x20>;
+                               ti,hwmods = "counter_32k";
                        };
                };
 
-               counter32k: counter@48004000 {
-                       compatible = "ti,omap-counter32k";
-                       reg = <0x48004000 0x20>;
-                       ti,hwmods = "counter_32k";
-               };
-
-               omap2420_pmx: pinmux@48000030 {
-                       compatible = "ti,omap2420-padconf", "pinctrl-single";
-                       reg = <0x48000030 0x0113>;
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       pinctrl-single,register-width = <8>;
-                       pinctrl-single,function-mask = <0x3f>;
-               };
-
                gpio1: gpio@48018000 {
                        compatible = "ti,omap2-gpio";
                        reg = <0x48018000 0x200>;
index 805f75df1cf2011474a8fa119c95523acaffb163..93fed68839b9f66f8112713b28c92e7df86ea14a 100644 (file)
@@ -8,12 +8,12 @@
  * published by the Free Software Foundation.
  */
 
-&scrm_clocks {
+&scm_clocks {
        mcbsp3_mux_fck: mcbsp3_mux_fck {
                #clock-cells = <0>;
                compatible = "ti,composite-mux-clock";
                clocks = <&func_96m_ck>, <&mcbsp_clks>;
-               reg = <0x02e8>;
+               reg = <0x78>;
        };
 
        mcbsp3_fck: mcbsp3_fck {
@@ -27,7 +27,7 @@
                compatible = "ti,composite-mux-clock";
                clocks = <&func_96m_ck>, <&mcbsp_clks>;
                ti,bit-shift = <2>;
-               reg = <0x02e8>;
+               reg = <0x78>;
        };
 
        mcbsp4_fck: mcbsp4_fck {
@@ -41,7 +41,7 @@
                compatible = "ti,composite-mux-clock";
                clocks = <&func_96m_ck>, <&mcbsp_clks>;
                ti,bit-shift = <4>;
-               reg = <0x02e8>;
+               reg = <0x78>;
        };
 
        mcbsp5_fck: mcbsp5_fck {
index 0dc8de2782b1871772150b3a62ab7a92685da56a..11a7963be0035a002fa77c2bec6809b34444e584 100644 (file)
        compatible = "ti,omap2430", "ti,omap2";
 
        ocp {
-               prcm: prcm@49006000 {
-                       compatible = "ti,omap2-prcm";
-                       reg = <0x49006000 0x1000>;
+               l4_wkup: l4_wkup@49000000 {
+                       compatible = "ti,omap2-l4-wkup", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0 0x49000000 0x31000>;
 
-                       prcm_clocks: clocks {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                       };
+                       prcm: prcm@6000 {
+                               compatible = "ti,omap2-prcm";
+                               reg = <0x6000 0x1000>;
 
-                       prcm_clockdomains: clockdomains {
-                       };
-               };
-
-               scrm: scrm@49002000 {
-                       compatible = "ti,omap2-scrm";
-                       reg = <0x49002000 0x1000>;
+                               prcm_clocks: clocks {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                               };
 
-                       scrm_clocks: clocks {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
+                               prcm_clockdomains: clockdomains {
+                               };
                        };
 
-                       scrm_clockdomains: clockdomains {
+                       scm: scm@2000 {
+                               compatible = "ti,omap2-scm", "simple-bus";
+                               reg = <0x2000 0x1000>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges = <0 0x2000 0x1000>;
+
+                               omap2430_pmx: pinmux@30 {
+                                       compatible = "ti,omap2430-padconf",
+                                                    "pinctrl-single";
+                                       reg = <0x30 0x0154>;
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       pinctrl-single,register-width = <8>;
+                                       pinctrl-single,function-mask = <0x3f>;
+                               };
+
+                               scm_conf: scm_conf@270 {
+                                       compatible = "syscon";
+                                       reg = <0x270 0x240>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       scm_clocks: clocks {
+                                               #address-cells = <1>;
+                                               #size-cells = <0>;
+                                       };
+
+                                       pbias_regulator: pbias_regulator {
+                                               compatible = "ti,pbias-omap";
+                                               reg = <0x230 0x4>;
+                                               syscon = <&scm_conf>;
+                                               pbias_mmc_reg: pbias_mmc_omap2430 {
+                                                       regulator-name = "pbias_mmc_omap2430";
+                                                       regulator-min-microvolt = <1800000>;
+                                                       regulator-max-microvolt = <3000000>;
+                                               };
+                                       };
+                               };
+
+                               scm_clockdomains: clockdomains {
+                               };
                        };
-               };
-
-               counter32k: counter@49020000 {
-                       compatible = "ti,omap-counter32k";
-                       reg = <0x49020000 0x20>;
-                       ti,hwmods = "counter_32k";
-               };
-
-               omap2430_pmx: pinmux@49002030 {
-                       compatible = "ti,omap2430-padconf", "pinctrl-single";
-                       reg = <0x49002030 0x0154>;
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       pinctrl-single,register-width = <8>;
-                       pinctrl-single,function-mask = <0x3f>;
-               };
-
-               omap2_scm_general: tisyscon@49002270 {
-                       compatible = "syscon";
-                       reg = <0x49002270 0x240>;
-               };
 
-               pbias_regulator: pbias_regulator {
-                       compatible = "ti,pbias-omap";
-                       reg = <0x230 0x4>;
-                       syscon = <&omap2_scm_general>;
-                       pbias_mmc_reg: pbias_mmc_omap2430 {
-                               regulator-name = "pbias_mmc_omap2430";
-                               regulator-min-microvolt = <1800000>;
-                               regulator-max-microvolt = <3000000>;
+                       counter32k: counter@20000 {
+                               compatible = "ti,omap-counter32k";
+                               reg = <0x20000 0x20>;
+                               ti,hwmods = "counter_32k";
                        };
                };
 
index a1365ca926eb6a4bcd52f1099e7c1e5c882f8664..63965b8769732f7e2e30708c30b50ad3f9ee6968 100644 (file)
@@ -7,13 +7,13 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-&scrm_clocks {
+&scm_clocks {
        mcbsp1_mux_fck: mcbsp1_mux_fck {
                #clock-cells = <0>;
                compatible = "ti,composite-mux-clock";
                clocks = <&func_96m_ck>, <&mcbsp_clks>;
                ti,bit-shift = <2>;
-               reg = <0x0274>;
+               reg = <0x4>;
        };
 
        mcbsp1_fck: mcbsp1_fck {
@@ -27,7 +27,7 @@
                compatible = "ti,composite-mux-clock";
                clocks = <&func_96m_ck>, <&mcbsp_clks>;
                ti,bit-shift = <6>;
-               reg = <0x0274>;
+               reg = <0x4>;
        };
 
        mcbsp2_fck: mcbsp2_fck {
index 25f7b0a22114ee6928e58e27ceeb61cf07b04c79..7c4dca122a91d99a9848a691ce96a917294f59eb 100644 (file)
@@ -60,7 +60,6 @@
                ti,model = "omap3beagle";
 
                ti,mcbsp = <&mcbsp2>;
-               ti,codec = <&twl_audio>;
        };
 
        gpio_keys {
                compatible = "arm,coresight-etb10", "arm,primecell";
                reg = <0x5401b000 0x1000>;
 
-               coresight-default-sink;
                clocks = <&emu_src_ck>;
                clock-names = "apb_pclk";
                port {
index c792391ef090f11a77add8041f6c9e63ec3340e3..a5474113cd50647f4b945b8db7ea3ff3a7643c83 100644 (file)
@@ -71,7 +71,6 @@
                ti,model = "omap3beagle";
 
                ti,mcbsp = <&mcbsp2>;
-               ti,codec = <&twl_audio>;
        };
 
        gpio_keys {
                compatible = "arm,coresight-etb10", "arm,primecell";
                reg = <0x5401b000 0x1000>;
 
-               coresight-default-sink;
                clocks = <&emu_src_ck>;
                clock-names = "apb_pclk";
                port {
                };
        };
 };
+
+&gpmc {
+       status = "ok";
+       ranges = <0 0 0x30000000 0x1000000>;    /* CS0 space, 16MB */
+
+       /* Chip select 0 */
+       nand@0,0 {
+               reg = <0 0 4>;          /* NAND I/O window, 4 bytes */
+               interrupts = <20>;
+               ti,nand-ecc-opt = "ham1";
+               nand-bus-width = <16>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               gpmc,device-width = <2>;
+               gpmc,cs-on-ns = <0>;
+               gpmc,cs-rd-off-ns = <36>;
+               gpmc,cs-wr-off-ns = <36>;
+               gpmc,adv-on-ns = <6>;
+               gpmc,adv-rd-off-ns = <24>;
+               gpmc,adv-wr-off-ns = <36>;
+               gpmc,oe-on-ns = <6>;
+               gpmc,oe-off-ns = <48>;
+               gpmc,we-on-ns = <6>;
+               gpmc,we-off-ns = <30>;
+               gpmc,rd-cycle-ns = <72>;
+               gpmc,wr-cycle-ns = <72>;
+               gpmc,access-ns = <54>;
+               gpmc,wr-access-ns = <30>;
+
+               partition@0 {
+                       label = "X-Loader";
+                       reg = <0 0x80000>;
+               };
+               partition@80000 {
+                       label = "U-Boot";
+                       reg = <0x80000 0x1e0000>;
+               };
+               partition@1c0000 {
+                       label = "U-Boot Env";
+                       reg = <0x260000 0x20000>;
+               };
+               partition@280000 {
+                       label = "Kernel";
+                       reg = <0x280000 0x400000>;
+               };
+               partition@780000 {
+                       label = "Filesystem";
+                       reg = <0x680000 0xf980000>;
+               };
+       };
+};
index 0ab748cf7749f18d90ad225a5d0aabac564fc53f..f5b5a1d96cd740920ab215f2a7b3fc2fdaa9136e 100644 (file)
        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 = <&gpio5>;
+               interrupts = <17 IRQ_TYPE_LEVEL_HIGH>; /* gpio 145 */
+               ref-clock-frequency = <38400000>;
+       };
 };
 
 &dss {
index 46eadb21b5ef5e97882e581f6e29f33bda2cd209..2294f5b0aa102d9195aa93b33a9e298ac91cba26 100644 (file)
        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 = <&gpio5>;
+               interrupts = <8 IRQ_TYPE_LEVEL_HIGH>; /* gpio 136 */
+               ref-clock-frequency = <38400000>;
+       };
 };
 
 &dss {
index d9e92b654f851e879fe8fb4d74bfdf66c4cd7af9..046cd7733c4f9afac93d5f5382b61fd228759b8c 100644 (file)
@@ -16,7 +16,6 @@
                ti,model = "cm-t35";
 
                ti,mcbsp = <&mcbsp2>;
-               ti,codec = <&twl_audio>;
        };
 };
 
index 169037e5ff53cd83da50cfb16e70edfcc2c7d6ed..134d3f27a8ec5ae1f4f68982da4047dfcff13e13 100644 (file)
@@ -48,7 +48,6 @@
                ti,model = "devkit8000";
 
                ti,mcbsp = <&mcbsp2>;
-               ti,codec = <&twl_audio>;
                ti,audio-routing =
                        "Ext Spk", "PREDRIVEL",
                        "Ext Spk", "PREDRIVER",
index 127f3e7c10c4fcade6d95a201ffeccf4b66d9297..346552b94d9f7705a80642dc8ce86ea6bad800d6 100644 (file)
        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 = <&gpio5>;
+               interrupts = <21 IRQ_TYPE_LEVEL_HIGH>; /* gpio 149 */
+               ref-clock-frequency = <38400000>;
+       };
 };
 
 &twl_gpio {
index fb3a69604ed5ccebff4f90257c76ddfaad58a555..b9f68817bd6e636d5f1e657a3916de26c3aafcba 100644 (file)
@@ -46,7 +46,6 @@
                ti,model = "gta04";
 
                ti,mcbsp = <&mcbsp2>;
-               ti,codec = <&twl_audio>;
        };
 
        spi_lcd {
index 8a63ad2286aa26eaadf6162a12a98e24437acf28..d5e5cd449b16757d269836609b16b35d34ecc039 100644 (file)
@@ -22,7 +22,6 @@
                compatible = "ti,omap-twl4030";
                ti,model = "igep2";
                ti,mcbsp = <&mcbsp2>;
-               ti,codec = <&twl_audio>;
        };
 
        vdd33: regulator-vdd33 {
index cc8bd0cd8cf83d47deaa18ea29cbe3a08675e19b..72f7cdc091fba03ca51b223ec4f49cc810be88f4 100644 (file)
        vmmc-supply = <&lbep5clwmc_wlen>;
        bus-width = <4>;
        non-removable;
+
+       #address-cells = <1>;
+       #size-cells = <0>;
+       wlcore: wlcore@2 {
+               compatible = "ti,wl1835";
+               reg = <2>;
+               interrupt-parent = <&gpio6>;
+               interrupts = <17 IRQ_TYPE_LEVEL_HIGH>; /* gpio 177 */
+       };
 };
index 9326b282c94ab92aadc681cf362cddf8a575e98f..b899e341874a3dc84e9e898748fea314be0b84e4 100644 (file)
        vmmc-supply = <&lbep5clwmc_wlen>;
        bus-width = <4>;
        non-removable;
+
+       #address-cells = <1>;
+       #size-cells = <0>;
+       wlcore: wlcore@2 {
+               compatible = "ti,wl1835";
+               reg = <2>;
+               interrupt-parent = <&gpio5>;
+               interrupts = <8 IRQ_TYPE_LEVEL_HIGH>; /* gpio 136 */
+       };
 };
index e81fb651d5d0f04a6a90a6abca434cd64dc5d21e..e63133304a341a3d7b2d3401003b351b2c821b32 100644 (file)
@@ -38,7 +38,6 @@
                ti,model = "lilly-a83x";
 
                ti,mcbsp = <&mcbsp2>;
-               ti,codec = <&twl_audio>;
        };
 
        reg_vcc3: vcc3 {
index 9938b5dc1909c00f01e587f15a4a1c1d2a6bc665..f2e213931e09a21ed24f7e50b28a74d50eeca735 100644 (file)
        model = "Nokia N9";
        compatible = "nokia,omap3-n9", "ti,omap36xx", "ti,omap3";
 };
+
+&i2c2 {
+       smia_1: camera@10 {
+               compatible = "nokia,smia";
+               reg = <0x10>;
+               /* No reset gpio */
+               vana-supply = <&vaux3>;
+               clocks = <&isp 0>;
+               clock-frequency = <9600000>;
+               nokia,nvm-size = <(16 * 64)>;
+               port {
+                       smia_1_1: endpoint {
+                               link-frequencies = /bits/ 64 <199200000 210000000 499200000>;
+                               clock-lanes = <0>;
+                               data-lanes = <1 2>;
+                               remote-endpoint = <&csi2a_ep>;
+                       };
+               };
+       };
+};
+
+&isp {
+       vdd-csiphy1-supply = <&vaux2>;
+       vdd-csiphy2-supply = <&vaux2>;
+       ports {
+               port@2 {
+                       reg = <2>;
+                       csi2a_ep: endpoint {
+                               remote-endpoint = <&smia_1_1>;
+                               clock-lanes = <2>;
+                               data-lanes = <1 3>;
+                               crc = <1>;
+                               lane-polarities = <1 1 1>;
+                       };
+               };
+       };
+};
index db80f9d376fadf569655fc9660526b16b0c10739..a29315833ecd3bfc1f1a7f86f7f3c5734453a00f 100644 (file)
@@ -9,9 +9,23 @@
 
 /dts-v1/;
 
-#include "omap34xx-hs.dtsi"
+#include "omap34xx.dtsi"
 #include <dt-bindings/input/input.h>
 
+/*
+ * Default secure signed bootloader (Nokia X-Loader) does not enable L3 firewall
+ * for omap AES HW crypto support. When linux kernel try to access memory of AES
+ * blocks then kernel receive "Unhandled fault: external abort on non-linefetch"
+ * and crash. Until somebody fix omap-aes.c and omap_hwmod_3xxx_data.c code (no
+ * crash anymore) omap AES support will be disabled for all Nokia N900 devices.
+ * There is "unofficial" version of bootloader which enables AES in L3 firewall
+ * but it is not widely used and to prevent kernel crash rather AES is disabled.
+ * There is also no runtime detection code if AES is disabled in L3 firewall...
+ */
+&aes {
+       status = "disabled";
+};
+
 / {
        model = "Nokia N900";
        compatible = "nokia,omap3-n900", "ti,omap3430", "ti,omap3";
        pinctrl-0 = <&i2c3_pins>;
 
        clock-frequency = <400000>;
+
+       lis302dl: lis3lv02d@1d {
+               compatible = "st,lis3lv02d";
+               reg = <0x1d>;
+
+               Vdd-supply = <&vaux1>;
+               Vdd_IO-supply = <&vio>;
+
+               interrupt-parent = <&gpio6>;
+               interrupts = <21 20>; /* 181 and 180 */
+
+               /* click flags */
+               st,click-single-x;
+               st,click-single-y;
+               st,click-single-z;
+
+               /* Limits are 0.5g * value */
+               st,click-threshold-x = <8>;
+               st,click-threshold-y = <8>;
+               st,click-threshold-z = <10>;
+
+               /* Click must be longer than time limit */
+               st,click-time-limit = <9>;
+
+               /* Kind of debounce filter */
+               st,click-latency = <50>;
+
+               /* Interrupt line 2 for click detection */
+               st,irq2-click;
+
+               st,wakeup-x-hi;
+               st,wakeup-y-hi;
+               st,wakeup-threshold = <(800/18)>; /* millig-value / 18 to get HW values */
+
+               st,wakeup2-z-hi;
+               st,wakeup2-threshold = <(900/18)>; /* millig-value / 18 to get HW values */
+
+               st,hipass1-disable;
+               st,hipass2-disable;
+
+               st,axis-x = <1>;    /* LIS3_DEV_X */
+               st,axis-y = <(-2)>; /* LIS3_INV_DEV_Y */
+               st,axis-z = <(-3)>; /* LIS3_INV_DEV_Z */
+
+               st,min-limit-x = <(-32)>;
+               st,min-limit-y = <3>;
+               st,min-limit-z = <3>;
+
+               st,max-limit-x = <(-3)>;
+               st,max-limit-y = <32>;
+               st,max-limit-z = <32>;
+       };
 };
 
 &mmc1 {
index c41db94ee9c2749c34a99df9915f7da03ed7a020..800b379d368d54ca901fa25c1ab789287d6a30a0 100644 (file)
@@ -8,7 +8,7 @@
  * published by the Free Software Foundation.
  */
 
-#include "omap36xx-hs.dtsi"
+#include "omap36xx.dtsi"
 
 / {
        cpus {
index 261c5589bfa3170e76cc8f469ac1d6ca07a02765..0885b34d5d7da252953c3aaef287a1e20b9dda63 100644 (file)
        model = "Nokia N950";
        compatible = "nokia,omap3-n950", "ti,omap36xx", "ti,omap3";
 };
+
+&i2c2 {
+       smia_1: camera@10 {
+               compatible = "nokia,smia";
+               reg = <0x10>;
+               /* No reset gpio */
+               vana-supply = <&vaux3>;
+               clocks = <&isp 0>;
+               clock-frequency = <9600000>;
+               nokia,nvm-size = <(16 * 64)>;
+               port {
+                       smia_1_1: endpoint {
+                               link-frequencies = /bits/ 64 <210000000 333600000 398400000>;
+                               clock-lanes = <0>;
+                               data-lanes = <1 2>;
+                               remote-endpoint = <&csi2a_ep>;
+                       };
+               };
+       };
+};
+
+&isp {
+       vdd-csiphy1-supply = <&vaux2>;
+       vdd-csiphy2-supply = <&vaux2>;
+       ports {
+               port@2 {
+                       reg = <2>;
+                       csi2a_ep: endpoint {
+                               remote-endpoint = <&smia_1_1>;
+                               clock-lanes = <2>;
+                               data-lanes = <3 1>;
+                               crc = <1>;
+                               lane-polarities = <1 1 1>;
+                       };
+               };
+       };
+};
index d36bf0250a055427b595ee090b0cf56b6f03311b..18e1649681c1cdada8faf1673a8ac73c50bff288 100644 (file)
@@ -27,7 +27,6 @@
                ti,model = "overo";
 
                ti,mcbsp = <&mcbsp2>;
-               ti,codec = <&twl_audio>;
        };
 
        /* HS USB Port 2 Power */
diff --git a/arch/arm/boot/dts/omap3-pandora-1ghz.dts b/arch/arm/boot/dts/omap3-pandora-1ghz.dts
new file mode 100644 (file)
index 0000000..9619a28
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2015
+ *   Nikolaus Schaller <hns@goldelico.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 for OpenPandora 1GHz with DM3730
+ */
+
+/dts-v1/;
+
+#include "omap36xx.dtsi"
+#include "omap3-pandora-common.dtsi"
+
+/ {
+       model = "Pandora Handheld Console 1GHz";
+
+       compatible = "ti,omap36xx", "ti,omap3";
+};
+
+&omap3_pmx_core2 {
+
+       pinctrl-names = "default";
+       pinctrl-0 = <
+               &hsusb2_2_pins
+               &control_pins
+       >;
+
+       hsusb2_2_pins: pinmux_hsusb2_2_pins {
+               pinctrl-single,pins = <
+                       OMAP3630_CORE2_IOPAD(0x25f0, PIN_OUTPUT | MUX_MODE3)            /* etk_d10.hsusb2_clk */
+                       OMAP3630_CORE2_IOPAD(0x25f2, PIN_OUTPUT | MUX_MODE3)            /* etk_d11.hsusb2_stp */
+                       OMAP3630_CORE2_IOPAD(0x25f4, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d12.hsusb2_dir */
+                       OMAP3630_CORE2_IOPAD(0x25f6, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d13.hsusb2_nxt */
+                       OMAP3630_CORE2_IOPAD(0x25f8, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d14.hsusb2_data0 */
+                       OMAP3630_CORE2_IOPAD(0x25fa, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d15.hsusb2_data1 */
+               >;
+       };
+
+       mmc3_pins: pinmux_mmc3_pins {
+               pinctrl-single,pins = <
+                       OMAP3630_CORE2_IOPAD(0x25d8, PIN_INPUT_PULLUP | MUX_MODE2)      /* etk_clk.sdmmc3_clk */
+                       OMAP3630_CORE2_IOPAD(0x25da, PIN_INPUT_PULLUP | MUX_MODE2)      /* etk_ctl.sdmmc3_cmd */
+                       OMAP3630_CORE2_IOPAD(0x25e2, PIN_INPUT_PULLUP | MUX_MODE2)      /* etk_d3.sdmmc3_dat3 */
+                       OMAP3630_CORE2_IOPAD(0x25e4, PIN_INPUT_PULLUP | MUX_MODE2)      /* etk_d4.sdmmc3_dat0 */
+                       OMAP3630_CORE2_IOPAD(0x25e6, PIN_INPUT_PULLUP | MUX_MODE2)      /* etk_d5.sdmmc3_dat1 */
+                       OMAP3630_CORE2_IOPAD(0x25e8, PIN_INPUT_PULLUP | MUX_MODE2)      /* etk_d6.sdmmc3_dat2 */
+               >;
+       };
+
+       control_pins: pinmux_control_pins {
+               pinctrl-single,pins = <
+                       OMAP3630_CORE2_IOPAD(0x25dc, PIN_INPUT_PULLDOWN | MUX_MODE4)    /* etk_d0.gpio_14 =  HP_SHUTDOWN */
+                       OMAP3630_CORE2_IOPAD(0x25de, PIN_OUTPUT | MUX_MODE4)            /* etk_d1.gpio_15 =  BT_SHUTDOWN */
+                       OMAP3630_CORE2_IOPAD(0x25e0, PIN_OUTPUT | MUX_MODE4)            /* etk_d2.gpio_16 =  RESET_USB_HOST */
+                       OMAP3630_CORE2_IOPAD(0x25ea, PIN_INPUT | MUX_MODE4)             /* etk_d7.gpio_21 =  WIFI IRQ */
+                       OMAP3630_CORE2_IOPAD(0x25ec, PIN_OUTPUT | MUX_MODE4)            /* etk_d8.gpio_22 =  MSECURE */
+                       OMAP3630_CORE2_IOPAD(0x25ee, PIN_OUTPUT | MUX_MODE4)            /* etk_d9.gpio_23 =  WIFI_POWER */
+                       OMAP3_WKUP_IOPAD(0x2a54, PIN_INPUT | MUX_MODE4)                 /* reserved.gpio_127 = MMC2_WP */
+                       OMAP3_WKUP_IOPAD(0x2a56, PIN_INPUT | MUX_MODE4)                 /* reserved.gpio_126 = MMC1_WP */
+                       OMAP3_WKUP_IOPAD(0x2a58, PIN_OUTPUT | MUX_MODE4)                /* reserved.gpio_128 = LED_MMC1 */
+                       OMAP3_WKUP_IOPAD(0x2a5a, PIN_OUTPUT | MUX_MODE4)                /* reserved.gpio_129 = LED_MMC2 */
+
+               >;
+       };
+};
diff --git a/arch/arm/boot/dts/omap3-pandora-600mhz.dts b/arch/arm/boot/dts/omap3-pandora-600mhz.dts
new file mode 100644 (file)
index 0000000..fb803a7
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2015
+ *   Nikolaus Schaller <hns@goldelico.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 for OpenPandora with OMAP3530
+ */
+
+/dts-v1/;
+
+#include "omap34xx.dtsi"
+#include "omap3-pandora-common.dtsi"
+
+/ {
+       model = "Pandora Handheld Console";
+
+       compatible = "ti,omap3";
+};
+
+&omap3_pmx_core2 {
+
+       pinctrl-names = "default";
+       pinctrl-0 = <
+               &hsusb2_2_pins
+               &control_pins
+       >;
+
+       hsusb2_2_pins: pinmux_hsusb2_2_pins {
+               pinctrl-single,pins = <
+                       OMAP3430_CORE2_IOPAD(0x25f0, PIN_OUTPUT | MUX_MODE3)            /* etk_d10.hsusb2_clk */
+                       OMAP3430_CORE2_IOPAD(0x25f2, PIN_OUTPUT | MUX_MODE3)            /* etk_d11.hsusb2_stp */
+                       OMAP3430_CORE2_IOPAD(0x25f4, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d12.hsusb2_dir */
+                       OMAP3430_CORE2_IOPAD(0x25f6, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d13.hsusb2_nxt */
+                       OMAP3430_CORE2_IOPAD(0x25f8, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d14.hsusb2_data0 */
+                       OMAP3430_CORE2_IOPAD(0x25fa, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d15.hsusb2_data1 */
+               >;
+       };
+
+       mmc3_pins: pinmux_mmc3_pins {
+               pinctrl-single,pins = <
+                       OMAP3430_CORE2_IOPAD(0x25d8, PIN_INPUT_PULLUP | MUX_MODE2)      /* etk_clk.sdmmc3_clk */
+                       OMAP3430_CORE2_IOPAD(0x25da, PIN_INPUT_PULLUP | MUX_MODE2)      /* etk_ctl.sdmmc3_cmd */
+                       OMAP3430_CORE2_IOPAD(0x25e2, PIN_INPUT_PULLUP | MUX_MODE2)      /* etk_d3.sdmmc3_dat3 */
+                       OMAP3430_CORE2_IOPAD(0x25e4, PIN_INPUT_PULLUP | MUX_MODE2)      /* etk_d4.sdmmc3_dat0 */
+                       OMAP3430_CORE2_IOPAD(0x25e6, PIN_INPUT_PULLUP | MUX_MODE2)      /* etk_d5.sdmmc3_dat1 */
+                       OMAP3430_CORE2_IOPAD(0x25e8, PIN_INPUT_PULLUP | MUX_MODE2)      /* etk_d6.sdmmc3_dat2 */
+               >;
+       };
+
+       control_pins: pinmux_control_pins {
+               pinctrl-single,pins = <
+                       OMAP3430_CORE2_IOPAD(0x25dc, PIN_INPUT_PULLDOWN | MUX_MODE4)    /* etk_d0.gpio_14 =  HP_SHUTDOWN */
+                       OMAP3430_CORE2_IOPAD(0x25de, PIN_OUTPUT | MUX_MODE4)            /* etk_d1.gpio_15 =  BT_SHUTDOWN */
+                       OMAP3430_CORE2_IOPAD(0x25e0, PIN_OUTPUT | MUX_MODE4)            /* etk_d2.gpio_16 =  RESET_USB_HOST */
+                       OMAP3430_CORE2_IOPAD(0x25ea, PIN_INPUT | MUX_MODE4)             /* etk_d7.gpio_21 =  WIFI IRQ */
+                       OMAP3430_CORE2_IOPAD(0x25ec, PIN_OUTPUT | MUX_MODE4)            /* etk_d8.gpio_22 =  MSECURE */
+                       OMAP3430_CORE2_IOPAD(0x25ee, PIN_OUTPUT | MUX_MODE4)            /* etk_d9.gpio_23 =  WIFI_POWER */
+               >;
+       };
+};
diff --git a/arch/arm/boot/dts/omap3-pandora-common.dtsi b/arch/arm/boot/dts/omap3-pandora-common.dtsi
new file mode 100644 (file)
index 0000000..782ab1f
--- /dev/null
@@ -0,0 +1,640 @@
+/*
+ * Copyright (C) 2015
+ *   Nikolaus Schaller <hns@goldelico.com>
+ *
+ * Common device tree include for OpenPandora devices.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <dt-bindings/input/input.h>
+
+/ {
+       cpus {
+               cpu@0 {
+                       cpu0-supply = <&vcc>;
+               };
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x80000000 0x20000000>; /* 512 MB */
+       };
+
+       aliases {
+               display0 = &lcd;
+       };
+
+       tv: connector@1 {
+               compatible = "connector-analog-tv";
+               label = "tv";
+
+               port {
+                       tv_connector_in: endpoint {
+                               remote-endpoint = <&venc_out>;
+                       };
+               };
+       };
+
+       gpio-leds {
+
+               compatible = "gpio-leds";
+
+               pinctrl-names = "default";
+               pinctrl-0 = <&led_pins>;
+
+               led@1 {
+                       label = "pandora::sd1";
+                       gpios = <&gpio5 0 GPIO_ACTIVE_HIGH>;    /* GPIO_128 */
+                       linux,default-trigger = "mmc0";
+                       default-state = "off";
+               };
+
+               led@2 {
+                       label = "pandora::sd2";
+                       gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>;    /* GPIO_129 */
+                       linux,default-trigger = "mmc1";
+                       default-state = "off";
+               };
+
+               led@3 {
+                       label = "pandora::bluetooth";
+                       gpios = <&gpio5 30 GPIO_ACTIVE_HIGH>;   /* GPIO_158 */
+                       linux,default-trigger = "heartbeat";
+                       default-state = "off";
+               };
+
+               led@4 {
+                       label = "pandora::wifi";
+                       gpios = <&gpio5 31 GPIO_ACTIVE_HIGH>;   /* GPIO_159 */
+                       linux,default-trigger = "mmc2";
+                       default-state = "off";
+               };
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+
+               pinctrl-names = "default";
+               pinctrl-0 = <&button_pins>;
+
+               up-button {
+                       label = "up";
+                       linux,code = <KEY_UP>;
+                       gpios = <&gpio4 14 GPIO_ACTIVE_LOW>;    /* GPIO_110 */
+                       gpio-key,wakeup;
+               };
+
+               down-button {
+                       label = "down";
+                       linux,code = <KEY_DOWN>;
+                       gpios = <&gpio4 7 GPIO_ACTIVE_LOW>;     /* GPIO_103 */
+                       gpio-key,wakeup;
+               };
+
+               left-button {
+                       label = "left";
+                       linux,code = <KEY_LEFT>;
+                       gpios = <&gpio4 0 GPIO_ACTIVE_LOW>;     /* GPIO_96 */
+                       gpio-key,wakeup;
+               };
+
+               right-button {
+                       label = "right";
+                       linux,code = <KEY_RIGHT>;
+                       gpios = <&gpio4 2 GPIO_ACTIVE_LOW>;     /* GPIO_98 */
+                       gpio-key,wakeup;
+               };
+
+               pageup-button {
+                       label = "game 1";
+                       linux,code = <KEY_PAGEUP>;
+                       gpios = <&gpio4 13 GPIO_ACTIVE_LOW>;    /* GPIO_109 */
+                       gpio-key,wakeup;
+               };
+
+               pagedown-button {
+                       label = "game 3";
+                       linux,code = <KEY_PAGEDOWN>;
+                       gpios = <&gpio4 10 GPIO_ACTIVE_LOW>;    /* GPIO_106 */
+                       gpio-key,wakeup;
+               };
+
+               home-button {
+                       label = "game 4";
+                       linux,code = <KEY_HOME>;
+                       gpios = <&gpio4 5 GPIO_ACTIVE_LOW>;     /* GPIO_101 */
+                       gpio-key,wakeup;
+               };
+
+               end-button {
+                       label = "game 2";
+                       linux,code = <KEY_END>;
+                       gpios = <&gpio4 15 GPIO_ACTIVE_LOW>;    /* GPIO_111 */
+                       gpio-key,wakeup;
+               };
+
+               right-shift {
+                       label = "l";
+                       linux,code = <KEY_RIGHTSHIFT>;
+                       gpios = <&gpio4 6 GPIO_ACTIVE_LOW>;     /* GPIO_102 */
+                       gpio-key,wakeup;
+               };
+
+               kp-plus {
+                       label = "l2";
+                       linux,code = <KEY_KPPLUS>;
+                       gpios = <&gpio4 1 GPIO_ACTIVE_LOW>;     /* GPIO_97 */
+                       gpio-key,wakeup;
+               };
+
+               right-ctrl {
+                       label = "r";
+                       linux,code = <KEY_RIGHTCTRL>;
+                       gpios = <&gpio4 9 GPIO_ACTIVE_LOW>;     /* GPIO_105 */
+                       gpio-key,wakeup;
+               };
+
+               kp-minus {
+                       label = "r2";
+                       linux,code = <KEY_KPMINUS>;
+                       gpios = <&gpio4 11 GPIO_ACTIVE_LOW>;    /* GPIO_107 */
+                       gpio-key,wakeup;
+               };
+
+               left-ctrl {
+                       label = "ctrl";
+                       linux,code = <KEY_LEFTCTRL>;
+                       gpios = <&gpio4 8 GPIO_ACTIVE_LOW>;     /* GPIO_104 */
+                       gpio-key,wakeup;
+               };
+
+               menu {
+                       label = "menu";
+                       linux,code = <KEY_MENU>;
+                       gpios = <&gpio4 3 GPIO_ACTIVE_LOW>;     /* GPIO_99 */
+                       gpio-key,wakeup;
+               };
+
+               hold {
+                       label = "hold";
+                       linux,code = <KEY_COFFEE>;
+                       gpios = <&gpio6 16 GPIO_ACTIVE_LOW>;    /* GPIO_176 */
+                       gpio-key,wakeup;
+               };
+
+               left-alt {
+                       label = "alt";
+                       linux,code = <KEY_LEFTALT>;
+                       gpios = <&gpio4 4 GPIO_ACTIVE_HIGH>;    /* GPIO_100 */
+                       gpio-key,wakeup;
+               };
+
+               lid {
+                       label = "lid";
+                       linux,code = <0x00>;    /* SW_LID lid shut */
+                       linux,input-type = <0x05>;    /* EV_SW */
+                       gpios = <&gpio4 12 GPIO_ACTIVE_HIGH>;   /* GPIO_108 */
+               };
+       };
+};
+
+&omap3_pmx_core {
+
+       mmc1_pins: pinmux_mmc1_pins {
+               pinctrl-single,pins = <
+                       OMAP3_CORE1_IOPAD(0x2144, PIN_INPUT_PULLUP | MUX_MODE0)         /* sdmmc1_clk.sdmmc1_clk */
+                       OMAP3_CORE1_IOPAD(0x2146, PIN_INPUT_PULLUP | MUX_MODE0)         /* sdmmc1_cmd.sdmmc1_cmd */
+                       OMAP3_CORE1_IOPAD(0x2148, PIN_INPUT_PULLUP | MUX_MODE0)         /* sdmmc1_dat0.sdmmc1_dat0 */
+                       OMAP3_CORE1_IOPAD(0x214a, PIN_INPUT_PULLUP | MUX_MODE0)         /* sdmmc1_dat1.sdmmc1_dat1 */
+                       OMAP3_CORE1_IOPAD(0x214c, PIN_INPUT_PULLUP | MUX_MODE0)         /* sdmmc1_dat2.sdmmc1_dat2 */
+                       OMAP3_CORE1_IOPAD(0x214e, PIN_INPUT_PULLUP | MUX_MODE0)         /* sdmmc1_dat3.sdmmc1_dat3 */
+               >;
+       };
+
+       mmc2_pins: pinmux_mmc2_pins {
+               pinctrl-single,pins = <
+                       OMAP3_CORE1_IOPAD(0x2158, PIN_INPUT_PULLUP | MUX_MODE0)         /* sdmmc2_clk.sdmmc2_clk */
+                       OMAP3_CORE1_IOPAD(0x215a, PIN_INPUT_PULLUP | MUX_MODE0)         /* sdmmc2_cmd.sdmmc2_cmd */
+                       OMAP3_CORE1_IOPAD(0x215c, PIN_INPUT_PULLUP | MUX_MODE0)         /* sdmmc2_dat0.sdmmc2_dat0 */
+                       OMAP3_CORE1_IOPAD(0x215e, PIN_INPUT_PULLUP | MUX_MODE0)         /* sdmmc2_dat1.sdmmc2_dat1 */
+                       OMAP3_CORE1_IOPAD(0x2160, PIN_INPUT_PULLUP | MUX_MODE0)         /* sdmmc2_dat2.sdmmc2_dat2 */
+                       OMAP3_CORE1_IOPAD(0x2162, PIN_INPUT_PULLUP | MUX_MODE0)         /* sdmmc2_dat3.sdmmc2_dat3 */
+                       OMAP3_CORE1_IOPAD(0x2164, PIN_OUTPUT_PULLUP | MUX_MODE1)        /* sdmmc2_dat4.sdmmc2_dirdat0 */
+                       OMAP3_CORE1_IOPAD(0x2166, PIN_OUTPUT_PULLUP | MUX_MODE1)        /* sdmmc2_dat5.sdmmc2_dirdat1 */
+                       OMAP3_CORE1_IOPAD(0x2168, PIN_OUTPUT_PULLUP | MUX_MODE1)        /* sdmmc2_dat6.sdmmc2_dircmd */
+                       OMAP3_CORE1_IOPAD(0x216a, PIN_INPUT_PULLUP | MUX_MODE1)         /* sdmmc2_dat7.sdmmc2_clkin */
+               >;
+       };
+
+       dss_dpi_pins: pinmux_dss_dpi_pins {
+               pinctrl-single,pins = <
+                       OMAP3_CORE1_IOPAD(0x20d4, PIN_OUTPUT | MUX_MODE0)       /* dss_pclk.dss_pclk */
+                       OMAP3_CORE1_IOPAD(0x20d6, PIN_OUTPUT | MUX_MODE0)       /* dss_hsync.dss_hsync */
+                       OMAP3_CORE1_IOPAD(0x20d8, PIN_OUTPUT | MUX_MODE0)       /* dss_vsync.dss_vsync */
+                       OMAP3_CORE1_IOPAD(0x20da, PIN_OUTPUT | MUX_MODE0)       /* dss_acbias.dss_acbias */
+                       OMAP3_CORE1_IOPAD(0x20dc, PIN_OUTPUT | MUX_MODE0)       /* dss_data0.dss_data0 */
+                       OMAP3_CORE1_IOPAD(0x20de, PIN_OUTPUT | MUX_MODE0)       /* dss_data1.dss_data1 */
+                       OMAP3_CORE1_IOPAD(0x20e0, PIN_OUTPUT | MUX_MODE0)       /* dss_data2.dss_data2 */
+                       OMAP3_CORE1_IOPAD(0x20e2, PIN_OUTPUT | MUX_MODE0)       /* dss_data3.dss_data3 */
+                       OMAP3_CORE1_IOPAD(0x20e4, PIN_OUTPUT | MUX_MODE0)       /* dss_data4.dss_data4 */
+                       OMAP3_CORE1_IOPAD(0x20e6, PIN_OUTPUT | MUX_MODE0)       /* dss_data5.dss_data5 */
+                       OMAP3_CORE1_IOPAD(0x20e8, PIN_OUTPUT | MUX_MODE0)       /* dss_data6.dss_data6 */
+                       OMAP3_CORE1_IOPAD(0x20ea, PIN_OUTPUT | MUX_MODE0)       /* dss_data7.dss_data7 */
+                       OMAP3_CORE1_IOPAD(0x20ec, PIN_OUTPUT | MUX_MODE0)       /* dss_data8.dss_data8 */
+                       OMAP3_CORE1_IOPAD(0x20ee, PIN_OUTPUT | MUX_MODE0)       /* dss_data9.dss_data9 */
+                       OMAP3_CORE1_IOPAD(0x20f0, PIN_OUTPUT | MUX_MODE0)       /* dss_data10.dss_data10 */
+                       OMAP3_CORE1_IOPAD(0x20f2, PIN_OUTPUT | MUX_MODE0)       /* dss_data11.dss_data11 */
+                       OMAP3_CORE1_IOPAD(0x20f4, PIN_OUTPUT | MUX_MODE0)       /* dss_data12.dss_data12 */
+                       OMAP3_CORE1_IOPAD(0x20f6, PIN_OUTPUT | MUX_MODE0)       /* dss_data13.dss_data13 */
+                       OMAP3_CORE1_IOPAD(0x20f8, PIN_OUTPUT | MUX_MODE0)       /* dss_data14.dss_data14 */
+                       OMAP3_CORE1_IOPAD(0x20fa, PIN_OUTPUT | MUX_MODE0)       /* dss_data15.dss_data15 */
+                       OMAP3_CORE1_IOPAD(0x20fc, PIN_OUTPUT | MUX_MODE0)       /* dss_data16.dss_data16 */
+                       OMAP3_CORE1_IOPAD(0x20fe, PIN_OUTPUT | MUX_MODE0)       /* dss_data17.dss_data17 */
+                       OMAP3_CORE1_IOPAD(0x2100, PIN_OUTPUT | MUX_MODE0)       /* dss_data18.dss_data18 */
+                       OMAP3_CORE1_IOPAD(0x2102, PIN_OUTPUT | MUX_MODE0)       /* dss_data19.dss_data19 */
+                       OMAP3_CORE1_IOPAD(0x2104, PIN_OUTPUT | MUX_MODE0)       /* dss_data20.dss_data20 */
+                       OMAP3_CORE1_IOPAD(0x2106, PIN_OUTPUT | MUX_MODE0)       /* dss_data21.dss_data21 */
+                       OMAP3_CORE1_IOPAD(0x2108, PIN_OUTPUT | MUX_MODE0)       /* dss_data22.dss_data22 */
+                       OMAP3_CORE1_IOPAD(0x210a, PIN_OUTPUT | MUX_MODE0)       /* dss_data23.dss_data23 */
+                       OMAP3_CORE1_IOPAD(0x218e, PIN_OUTPUT | MUX_MODE4)       /* GPIO_157 = lcd reset */
+               >;
+       };
+
+       uart3_pins: pinmux_uart3_pins {
+               pinctrl-single,pins = <
+                       OMAP3_CORE1_IOPAD(0x219e, PIN_INPUT | PIN_OFF_WAKEUPENABLE | MUX_MODE0) /* uart3_rx_irrx.uart3_rx_irrx */
+                       OMAP3_CORE1_IOPAD(0x21a0, PIN_OUTPUT | MUX_MODE0) /* uart3_tx_irtx.uart3_tx_irtx */
+               >;
+       };
+
+       led_pins: pinmux_leds_pins {
+               pinctrl-single,pins = <
+                       OMAP3_CORE1_IOPAD(0x2154, PIN_OUTPUT | MUX_MODE4)       /* GPIO_128 */
+                       OMAP3_CORE1_IOPAD(0x2156, PIN_OUTPUT | MUX_MODE4)       /* GPIO_129 */
+                       OMAP3_CORE1_IOPAD(0x2190, PIN_OUTPUT | MUX_MODE4)       /* GPIO_158 */
+                       OMAP3_CORE1_IOPAD(0x2192, PIN_OUTPUT | MUX_MODE4)       /* GPIO_159 */
+               >;
+       };
+
+       button_pins: pinmux_button_pins {
+               pinctrl-single,pins = <
+                       OMAP3_CORE1_IOPAD(0x2110, PIN_INPUT | MUX_MODE4)        /* GPIO_96 */
+                       OMAP3_CORE1_IOPAD(0x2112, PIN_INPUT | MUX_MODE4)        /* GPIO_97 */
+                       OMAP3_CORE1_IOPAD(0x2114, PIN_INPUT | MUX_MODE4)        /* GPIO_98 */
+                       OMAP3_CORE1_IOPAD(0x2116, PIN_INPUT | MUX_MODE4)        /* GPIO_99 */
+                       OMAP3_CORE1_IOPAD(0x2118, PIN_INPUT | MUX_MODE4)        /* GPIO_100 */
+                       OMAP3_CORE1_IOPAD(0x211a, PIN_INPUT | MUX_MODE4)        /* GPIO_101 */
+                       OMAP3_CORE1_IOPAD(0x211c, PIN_INPUT | MUX_MODE4)        /* GPIO_102 */
+                       OMAP3_CORE1_IOPAD(0x211e, PIN_INPUT | MUX_MODE4)        /* GPIO_103 */
+                       OMAP3_CORE1_IOPAD(0x2120, PIN_INPUT | MUX_MODE4)        /* GPIO_104 */
+                       OMAP3_CORE1_IOPAD(0x2122, PIN_INPUT | MUX_MODE4)        /* GPIO_105 */
+                       OMAP3_CORE1_IOPAD(0x2124, PIN_INPUT | MUX_MODE4)        /* GPIO_106 */
+                       OMAP3_CORE1_IOPAD(0x2126, PIN_INPUT | MUX_MODE4)        /* GPIO_107 */
+                       OMAP3_CORE1_IOPAD(0x2128, PIN_INPUT | MUX_MODE4)        /* GPIO_108 */
+                       OMAP3_CORE1_IOPAD(0x212a, PIN_INPUT | MUX_MODE4)        /* GPIO_109 */
+                       OMAP3_CORE1_IOPAD(0x212c, PIN_INPUT | MUX_MODE4)        /* GPIO_110 */
+                       OMAP3_CORE1_IOPAD(0x212e, PIN_INPUT | MUX_MODE4)        /* GPIO_111 */
+                       OMAP3_CORE1_IOPAD(0x21d2, PIN_INPUT | MUX_MODE4)        /* GPIO_176 */
+               >;
+       };
+
+       penirq_pins: pinmux_penirq_pins {
+               pinctrl-single,pins = <
+                       /* here we could enable to wakeup the cpu from suspend by a pen touch */
+                       OMAP3_CORE1_IOPAD(0x210c, PIN_INPUT | MUX_MODE4)        /* GPIO_94 */
+               >;
+       };
+
+};
+
+&omap3_pmx_core2 {
+       /* define in CPU specific file that includes this one
+        * use either OMAP3430_CORE2_IOPAD() or OMAP3630_CORE2_IOPAD()
+        */
+};
+
+&i2c1 {
+       clock-frequency = <2600000>;
+
+       twl: twl@48 {
+               reg = <0x48>;
+               interrupts = <7>; /* SYS_NIRQ cascaded to intc */
+               interrupt-parent = <&intc>;
+
+               twl_power: power {
+                       compatible = "ti,twl4030-power-reset";
+                       ti,use_poweroff;
+               };
+
+               twl_audio: audio {
+                       compatible = "ti,twl4030-audio";
+
+                       codec {
+                               ti,ramp_delay_value = <3>;
+                       };
+               };
+       };
+};
+
+#include "twl4030.dtsi"
+#include "twl4030_omap3.dtsi"
+
+&twl_keypad {
+       keypad,num-rows = <8>;
+       keypad,num-columns = <6>;
+       linux,keymap = <
+               MATRIX_KEY(0, 0, KEY_9)
+               MATRIX_KEY(0, 1, KEY_8)
+               MATRIX_KEY(0, 2, KEY_I)
+               MATRIX_KEY(0, 3, KEY_J)
+               MATRIX_KEY(0, 4, KEY_N)
+               MATRIX_KEY(0, 5, KEY_M)
+               MATRIX_KEY(1, 0, KEY_0)
+               MATRIX_KEY(1, 1, KEY_7)
+               MATRIX_KEY(1, 2, KEY_U)
+               MATRIX_KEY(1, 3, KEY_H)
+               MATRIX_KEY(1, 4, KEY_B)
+               MATRIX_KEY(1, 5, KEY_SPACE)
+               MATRIX_KEY(2, 0, KEY_BACKSPACE)
+               MATRIX_KEY(2, 1, KEY_6)
+               MATRIX_KEY(2, 2, KEY_Y)
+               MATRIX_KEY(2, 3, KEY_G)
+               MATRIX_KEY(2, 4, KEY_V)
+               MATRIX_KEY(2, 5, KEY_FN)
+               MATRIX_KEY(3, 0, KEY_O)
+               MATRIX_KEY(3, 1, KEY_5)
+               MATRIX_KEY(3, 2, KEY_T)
+               MATRIX_KEY(3, 3, KEY_F)
+               MATRIX_KEY(3, 4, KEY_C)
+               MATRIX_KEY(4, 0, KEY_P)
+               MATRIX_KEY(4, 1, KEY_4)
+               MATRIX_KEY(4, 2, KEY_R)
+               MATRIX_KEY(4, 3, KEY_D)
+               MATRIX_KEY(4, 4, KEY_X)
+               MATRIX_KEY(5, 0, KEY_K)
+               MATRIX_KEY(5, 1, KEY_3)
+               MATRIX_KEY(5, 2, KEY_E)
+               MATRIX_KEY(5, 3, KEY_S)
+               MATRIX_KEY(5, 4, KEY_Z)
+               MATRIX_KEY(6, 0, KEY_L)
+               MATRIX_KEY(6, 1, KEY_2)
+               MATRIX_KEY(6, 2, KEY_W)
+               MATRIX_KEY(6, 3, KEY_A)
+               MATRIX_KEY(6, 4, KEY_RIGHTBRACE)
+               MATRIX_KEY(7, 0, KEY_ENTER)
+               MATRIX_KEY(7, 1, KEY_1)
+               MATRIX_KEY(7, 2, KEY_Q)
+               MATRIX_KEY(7, 3, KEY_LEFTSHIFT)
+               MATRIX_KEY(7, 4, KEY_LEFTBRACE )
+        >;
+};
+
+/* backup battery charger */
+&charger {
+       ti,bb-uvolt = <3200000>;
+       ti,bb-uamp = <150>;
+};
+
+/* MMC2 */
+&vmmc2 {
+       regulator-min-microvolt = <1850000>;
+       regulator-max-microvolt = <3150000>;
+};
+
+/* LCD */
+&vaux1 {
+       regulator-min-microvolt = <3000000>;
+       regulator-max-microvolt = <3000000>;
+};
+
+/* USB Host PHY */
+&vaux2 {
+       regulator-min-microvolt = <1800000>;
+       regulator-max-microvolt = <1800000>;
+};
+
+/* available on expansion connector */
+&vaux3 {
+       regulator-min-microvolt = <2800000>;
+       regulator-max-microvolt = <2800000>;
+};
+
+/* ADS7846 and nubs */
+&vaux4 {
+       regulator-min-microvolt = <2800000>;
+       regulator-max-microvolt = <2800000>;
+};
+
+/* power audio DAC and LID sensor */
+&vsim {
+       regulator-min-microvolt = <2800000>;
+       regulator-max-microvolt = <2800000>;
+       regulator-always-on;
+};
+
+&i2c2 {
+       clock-frequency = <100000>;
+       /* no clients so we should disable clock */
+};
+
+&i2c3 {
+       clock-frequency = <100000>;
+
+       bq27500@55 {
+               compatible = "ti,bq27500";
+               reg = <0x55>;
+       };
+
+};
+
+&usb_otg_hs {
+       interface-type = <0>;
+       usb-phy = <&usb2_phy>;
+       phys = <&usb2_phy>;
+       phy-names = "usb2-phy";
+       mode = <3>;
+       power = <50>;
+};
+
+&mmc1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc1_pins>;
+       vmmc-supply = <&vmmc1>;
+       bus-width = <4>;
+       cd-gpios = <&twl_gpio 0 GPIO_ACTIVE_LOW>;
+       wp-gpios = <&gpio4 30 GPIO_ACTIVE_LOW>; /* GPIO_126 */
+};
+
+&mmc2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc2_pins>;
+       vmmc-supply = <&vmmc2>;
+       bus-width = <4>;
+       cd-gpios = <&twl_gpio 1 GPIO_ACTIVE_HIGH>;
+       wp-gpios = <&gpio4 31 GPIO_ACTIVE_LOW>; /* GPIO_127 */
+};
+
+/* bluetooth*/
+&uart1 {
+};
+
+/* spare (expansion connector) */
+&uart2 {
+};
+
+/* console (expansion connector) */
+&uart3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart3_pins>;
+       interrupts-extended = <&intc 74 &omap3_pmx_core OMAP3_UART3_RX>;
+};
+
+&usbhshost {
+       port2-mode = "ehci-phy";
+};
+
+&gpmc {
+       ranges = <0 0 0x30000000 0x1000000>; /* CS0: 16MB for NAND */
+
+       nand@0,0 {
+               reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
+               nand-bus-width = <16>;
+               ti,nand-ecc-opt = "sw";
+
+               gpmc,sync-clk-ps = <0>;
+               gpmc,cs-on-ns = <0>;
+               gpmc,cs-rd-off-ns = <44>;
+               gpmc,cs-wr-off-ns = <44>;
+               gpmc,adv-on-ns = <6>;
+               gpmc,adv-rd-off-ns = <34>;
+               gpmc,adv-wr-off-ns = <44>;
+               gpmc,we-off-ns = <40>;
+               gpmc,oe-off-ns = <54>;
+               gpmc,access-ns = <64>;
+               gpmc,rd-cycle-ns = <82>;
+               gpmc,wr-cycle-ns = <82>;
+               gpmc,wr-access-ns = <40>;
+               gpmc,wr-data-mux-bus-ns = <0>;
+               gpmc,device-width = <2>;
+
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               /* u-boot uses mtdparts=nand:512k(xloader),1920k(uboot),128k(uboot-env),10m(boot),-(rootfs) */
+
+               x-loader@0 {
+                       label = "xloader";
+                       reg = <0 0x80000>;
+               };
+
+               bootloaders@80000 {
+                       label = "uboot";
+                       reg = <0x80000 0x1e0000>;
+               };
+
+               bootloaders_env@260000 {
+                       label = "uboot-env";
+                       reg = <0x260000 0x20000>;
+               };
+
+               kernel@280000 {
+                       label = "boot";
+                       reg = <0x280000 0xa00000>;
+               };
+
+               filesystem@680000 {
+                       label = "rootfs";
+                       reg = <0xc80000 0>;     /* 0 = MTDPART_SIZ_FULL */
+               };
+       };
+};
+
+&mcspi1 {
+       tsc2046@0 {
+               reg = <0>;      /* CS0 */
+               compatible = "ti,tsc2046";
+               spi-max-frequency = <1000000>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&penirq_pins>;
+               interrupt-parent = <&gpio3>;
+               interrupts = <30 0>;    /* GPIO_94 */
+               pendown-gpio = <&gpio3 30 0>;
+               vcc-supply = <&vaux4>;
+
+               ti,x-min = /bits/ 16 <0>;
+               ti,x-max = /bits/ 16 <8000>;
+               ti,y-min = /bits/ 16 <0>;
+               ti,y-max = /bits/ 16 <4800>;
+               ti,x-plate-ohms = /bits/ 16 <40>;
+               ti,pressure-max = /bits/ 16 <255>;
+
+               linux,wakeup;
+       };
+
+       lcd: lcd@1 {
+               reg = <1>;      /* CS1 */
+               compatible =    "omapdss,tpo,td043mtea1";
+               spi-max-frequency = <100000>;
+               spi-cpol;
+               spi-cpha;
+
+               label = "lcd";
+               reset-gpios = <&gpio5 29 GPIO_ACTIVE_LOW>;      /* GPIO_157 */
+               vcc-supply = <&vaux1>;
+
+               port {
+                       lcd_in: endpoint {
+                               remote-endpoint = <&dpi_out>;
+                       };
+               };
+       };
+
+
+};
+
+/* n/a - used as GPIOs */
+&mcbsp1 {
+};
+
+/* audio DAC */
+&mcbsp2 {
+};
+
+/* bluetooth */
+&mcbsp3 {
+};
+
+/* to twl4030*/
+&mcbsp4 {
+};
+
+&venc {
+       status = "ok";
+
+       vdda-supply = <&vdac>;
+
+       port {
+               venc_out: endpoint {
+                       remote-endpoint = <&tv_connector_in>;
+                       ti,channels = <2>;
+               };
+       };
+};
+
+&dss {
+       pinctrl-names = "default";
+       pinctrl-0 = < &dss_dpi_pins >;
+
+       status = "ok";
+       vdds_dsi-supply = <&vpll2>;
+
+       port {
+               dpi_out: endpoint {
+                       remote-endpoint = <&lcd_in>;
+                       data-lines = <24>;
+               };
+       };
+};
index e89820a6776ef2d5628e85e681e1b998aadbfdce..7bd8d9a4f67fbaece7239df36f5c141126c62a50 100644 (file)
@@ -8,7 +8,16 @@
  */
 /dts-v1/;
 
-#include "omap34xx-hs.dtsi"
+#include "omap34xx.dtsi"
+
+/* Secure omaps have some devices inaccessible depending on the firmware */
+&aes {
+       status = "disabled";
+};
+
+&sham {
+       status = "disabled";
+};
 
 / {
        cpus {
@@ -45,7 +54,6 @@
 
                /* McBSP2 is used for onboard sound, same as on beagle */
                ti,mcbsp = <&mcbsp2>;
-               ti,codec = <&twl_audio>;
        };
 
        /* Regulator to enable/switch the vcc of the Wifi module */
index 6644f516a42bd9de5f5fb52a707051ad502e18a8..131448d86e67bdd4bff337529d01a35e232c6326 100644 (file)
        cap-power-off-card;
        pinctrl-names = "default";
        pinctrl-0 = <&mmc3_pins &mmc3_2_pins>;
+
+       #address-cells = <1>;
+       #size-cells = <0>;
+       wlcore: wlcore@2 {
+               compatible = "ti,wl1271";
+               reg = <2>;
+               interrupt-parent = <&gpio6>;
+               interrupts = <2 IRQ_TYPE_LEVEL_HIGH>; /* gpio 162 */
+               ref-clock-frequency = <26000000>;
+       };
 };
 
 &uart1 {
index 3fdc84fddb70d06a2ae26db02fc2c9c9f6d8ee63..d18a90f5eca3145e527926a5d2bbbb44c2d8b1c0 100644 (file)
                ranges;
                ti,hwmods = "l3_main";
 
+               l4_core: l4@48000000 {
+                       compatible = "ti,omap3-l4-core", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0 0x48000000 0x1000000>;
+
+                       scm: scm@2000 {
+                               compatible = "ti,omap3-scm", "simple-bus";
+                               reg = <0x2000 0x2000>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges = <0 0x2000 0x2000>;
+
+                               omap3_pmx_core: pinmux@30 {
+                                       compatible = "ti,omap3-padconf",
+                                                    "pinctrl-single";
+                                       reg = <0x30 0x238>;
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       #interrupt-cells = <1>;
+                                       interrupt-controller;
+                                       pinctrl-single,register-width = <16>;
+                                       pinctrl-single,function-mask = <0xff1f>;
+                               };
+
+                               scm_conf: scm_conf@270 {
+                                       compatible = "syscon";
+                                       reg = <0x270 0x330>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       scm_clocks: clocks {
+                                               #address-cells = <1>;
+                                               #size-cells = <0>;
+                                       };
+                               };
+
+                               scm_clockdomains: clockdomains {
+                               };
+
+                               omap3_pmx_wkup: pinmux@a00 {
+                                       compatible = "ti,omap3-padconf",
+                                                    "pinctrl-single";
+                                       reg = <0xa00 0x5c>;
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       #interrupt-cells = <1>;
+                                       interrupt-controller;
+                                       pinctrl-single,register-width = <16>;
+                                       pinctrl-single,function-mask = <0xff1f>;
+                               };
+                       };
+               };
+
                aes: aes@480c5000 {
                        compatible = "ti,omap3-aes";
                        ti,hwmods = "aes";
                        };
                };
 
-               scrm: scrm@48002000 {
-                       compatible = "ti,omap3-scrm";
-                       reg = <0x48002000 0x2000>;
-
-                       scrm_clocks: clocks {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                       };
-
-                       scrm_clockdomains: clockdomains {
-                       };
-               };
-
                counter32k: counter@48320000 {
                        compatible = "ti,omap-counter32k";
                        reg = <0x48320000 0x20>;
                        dma-requests = <96>;
                };
 
-               omap3_pmx_core: pinmux@48002030 {
-                       compatible = "ti,omap3-padconf", "pinctrl-single";
-                       reg = <0x48002030 0x0238>;
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       #interrupt-cells = <1>;
-                       interrupt-controller;
-                       pinctrl-single,register-width = <16>;
-                       pinctrl-single,function-mask = <0xff1f>;
-               };
-
-               omap3_pmx_wkup: pinmux@48002a00 {
-                       compatible = "ti,omap3-padconf", "pinctrl-single";
-                       reg = <0x48002a00 0x5c>;
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       #interrupt-cells = <1>;
-                       interrupt-controller;
-                       pinctrl-single,register-width = <16>;
-                       pinctrl-single,function-mask = <0xff1f>;
-               };
-
-               omap3_scm_general: tisyscon@48002270 {
-                       compatible = "syscon";
-                       reg = <0x48002270 0x2f0>;
-               };
-
                pbias_regulator: pbias_regulator {
                        compatible = "ti,pbias-omap";
                        reg = <0x2b0 0x4>;
-                       syscon = <&omap3_scm_general>;
+                       syscon = <&scm_conf>;
                        pbias_mmc_reg: pbias_mmc_omap2430 {
                                regulator-name = "pbias_mmc_omap2430";
                                regulator-min-microvolt = <1800000>;
diff --git a/arch/arm/boot/dts/omap34xx-hs.dtsi b/arch/arm/boot/dts/omap34xx-hs.dtsi
deleted file mode 100644 (file)
index 1ff6264..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/* Disabled modules for secure omaps */
-
-#include "omap34xx.dtsi"
-
-/* Secure omaps have some devices inaccessible depending on the firmware */
-&aes {
-       status = "disabled";
-};
-
-&sham {
-       status = "disabled";
-};
-
-&timer12 {
-       status = "disabled";
-};
index 3819c1e915915b2ad79395ce97323fbaa52ae439..4f6b2d5b1902e96114f12b1f8bd7d15ba0b9819e 100644 (file)
@@ -8,6 +8,8 @@
  * kind, whether express or implied.
  */
 
+#include <dt-bindings/media/omap3-isp.h>
+
 #include "omap3.dtsi"
 
 / {
                        pinctrl-single,register-width = <16>;
                        pinctrl-single,function-mask = <0xff1f>;
                };
+
+               isp: isp@480bc000 {
+                       compatible = "ti,omap3-isp";
+                       reg = <0x480bc000 0x12fc
+                              0x480bd800 0x017c>;
+                       interrupts = <24>;
+                       iommus = <&mmu_isp>;
+                       syscon = <&scm_conf 0xdc>;
+                       ti,phy-type = <OMAP3ISP_PHY_TYPE_COMPLEX_IO>;
+                       #clock-cells = <1>;
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+               };
        };
 };
 
diff --git a/arch/arm/boot/dts/omap36xx-hs.dtsi b/arch/arm/boot/dts/omap36xx-hs.dtsi
deleted file mode 100644 (file)
index 2c7febb..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/* Disabled modules for secure omaps */
-
-#include "omap36xx.dtsi"
-
-/* Secure omaps have some devices inaccessible depending on the firmware */
-&aes {
-       status = "disabled";
-};
-
-&sham {
-       status = "disabled";
-};
-
-&timer12 {
-       status = "disabled";
-};
index 541704a59a5adcac655c7a23ea49123c6a4fe9de..86253de5a97a99ddb12ea5f41c72f3c59279fced 100644 (file)
@@ -8,6 +8,8 @@
  * kind, whether express or implied.
  */
 
+#include <dt-bindings/media/omap3-isp.h>
+
 #include "omap3.dtsi"
 
 / {
                        pinctrl-single,register-width = <16>;
                        pinctrl-single,function-mask = <0xff1f>;
                };
+
+               isp: isp@480bc000 {
+                       compatible = "ti,omap3-isp";
+                       reg = <0x480bc000 0x12fc
+                              0x480bd800 0x0600>;
+                       interrupts = <24>;
+                       iommus = <&mmu_isp>;
+                       syscon = <&scm_conf 0x2f0>;
+                       ti,phy-type = <OMAP3ISP_PHY_TYPE_CSIPHY>;
+                       #clock-cells = <1>;
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+               };
        };
 };
 
index 5c375003bad106216109b5626264300433dabd1d..bbba5bdc4bc946d5cb9b179283c65f27ecdef1d9 100644 (file)
                clock-div = <1>;
        };
 };
-&scrm_clocks {
+
+&scm_clocks {
        mcbsp5_mux_fck: mcbsp5_mux_fck {
                #clock-cells = <0>;
                compatible = "ti,composite-mux-clock";
                clocks = <&core_96m_fck>, <&mcbsp_clks>;
                ti,bit-shift = <4>;
-               reg = <0x02d8>;
+               reg = <0x68>;
        };
 
        mcbsp5_fck: mcbsp5_fck {
                compatible = "ti,composite-mux-clock";
                clocks = <&core_96m_fck>, <&mcbsp_clks>;
                ti,bit-shift = <2>;
-               reg = <0x0274>;
+               reg = <0x04>;
        };
 
        mcbsp1_fck: mcbsp1_fck {
                compatible = "ti,composite-mux-clock";
                clocks = <&per_96m_fck>, <&mcbsp_clks>;
                ti,bit-shift = <6>;
-               reg = <0x0274>;
+               reg = <0x04>;
        };
 
        mcbsp2_fck: mcbsp2_fck {
                #clock-cells = <0>;
                compatible = "ti,composite-mux-clock";
                clocks = <&per_96m_fck>, <&mcbsp_clks>;
-               reg = <0x02d8>;
+               reg = <0x68>;
        };
 
        mcbsp3_fck: mcbsp3_fck {
                compatible = "ti,composite-mux-clock";
                clocks = <&per_96m_fck>, <&mcbsp_clks>;
                ti,bit-shift = <2>;
-               reg = <0x02d8>;
+               reg = <0x68>;
        };
 
        mcbsp4_fck: mcbsp4_fck {
index cb9458feb2e36fe3c2ff95b1e857bd6ea5e52dbb..ab7f87ae96f099e5fbb53ee786602ea5492ba698 100644 (file)
@@ -18,7 +18,7 @@ cpu_thermal: cpu_thermal {
                        /* sensor       ID */
         thermal-sensors = <&bandgap     0>;
 
-        trips {
+       cpu_trips: trips {
                 cpu_alert0: cpu_alert {
                         temperature = <100000>; /* millicelsius */
                         hysteresis = <2000>; /* millicelsius */
@@ -31,7 +31,7 @@ cpu_thermal: cpu_thermal {
                 };
         };
 
-       cooling-maps {
+       cpu_cooling_maps: cooling-maps {
                map0 {
                        trip = <&cpu_alert0>;
                        cooling-device =
index 7c15fb2e2fe4098a7393bb7fa1239e37a4ebab3d..f1507bc8737ee61031d0166b915317c3bf16b238 100644 (file)
        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 = <&gpio2>;
+               interrupts = <21 IRQ_TYPE_LEVEL_HIGH>; /* gpio 53 */
+               ref-clock-frequency = <38400000>;
+       };
 };
 
 &emif1 {
index 8aca8dae968ad276f193a3b3c969082a23dcc7e7..dac86ed7481f477ba315f67aef7dd7de17a67408 100644 (file)
        non-removable;
        bus-width = <4>;
        cap-power-off-card;
+
+       #address-cells = <1>;
+       #size-cells = <0>;
+       wlcore: wlcore@2 {
+               compatible = "ti,wl1281";
+               reg = <2>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <21 IRQ_TYPE_LEVEL_HIGH>; /* gpio 53 */
+               ref-clock-frequency = <26000000>;
+               tcxo-clock-frequency = <26000000>;
+       };
 };
 
 &emif1 {
index cc66af4192366fda0a1110a1770b3722b7579b2f..9bceeb7e1f0315d91d7aa8fe77bed9fdf5652064 100644 (file)
        bus-width = <4>;
        cap-power-off-card;
        status = "okay";
+
+       #address-cells = <1>;
+       #size-cells = <0>;
+       wlcore: wlcore@2 {
+               compatible = "ti,wl1271";
+               reg = <2>;
+               interrupt-parent = <&gpio2>;
+               interrupts = <9 IRQ_TYPE_LEVEL_HIGH>; /* gpio 41 */
+               ref-clock-frequency = <38400000>;
+       };
 };
index f2091d1c9c36c2995e08a4d63929df6c2679d243..f884d6adb71e8ed28371afd54c04528403ad29ba 100644 (file)
                interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
                             <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
 
-               cm1: cm1@4a004000 {
-                       compatible = "ti,omap4-cm1";
-                       reg = <0x4a004000 0x2000>;
-
-                       cm1_clocks: clocks {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                       };
+               l4_cfg: l4@4a000000 {
+                       compatible = "ti,omap4-l4-cfg", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0 0x4a000000 0x1000000>;
 
-                       cm1_clockdomains: clockdomains {
-                       };
-               };
+                       cm1: cm1@4000 {
+                               compatible = "ti,omap4-cm1";
+                               reg = <0x4000 0x2000>;
 
-               prm: prm@4a306000 {
-                       compatible = "ti,omap4-prm";
-                       reg = <0x4a306000 0x3000>;
-                       interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+                               cm1_clocks: clocks {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                               };
 
-                       prm_clocks: clocks {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
+                               cm1_clockdomains: clockdomains {
+                               };
                        };
 
-                       prm_clockdomains: clockdomains {
-                       };
-               };
+                       cm2: cm2@8000 {
+                               compatible = "ti,omap4-cm2";
+                               reg = <0x8000 0x3000>;
 
-               cm2: cm2@4a008000 {
-                       compatible = "ti,omap4-cm2";
-                       reg = <0x4a008000 0x3000>;
+                               cm2_clocks: clocks {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                               };
 
-                       cm2_clocks: clocks {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
+                               cm2_clockdomains: clockdomains {
+                               };
                        };
 
-                       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>;
+
+                               scm_conf: scm_conf@0 {
+                                       compatible = "syscon";
+                                       reg = <0x0 0x800>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+                               };
                        };
-               };
-
-               scrm: scrm@4a30a000 {
-                       compatible = "ti,omap4-scrm";
-                       reg = <0x4a30a000 0x2000>;
 
-                       scrm_clocks: clocks {
+                       omap4_padconf_core: scm@100000 {
+                               compatible = "ti,omap4-scm-padconf-core",
+                                            "simple-bus";
                                #address-cells = <1>;
-                               #size-cells = <0>;
+                               #size-cells = <1>;
+                               ranges = <0 0x100000 0x1000>;
+
+                               omap4_pmx_core: pinmux@40 {
+                                       compatible = "ti,omap4-padconf",
+                                                    "pinctrl-single";
+                                       reg = <0x40 0x0196>;
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       #interrupt-cells = <1>;
+                                       interrupt-controller;
+                                       pinctrl-single,register-width = <16>;
+                                       pinctrl-single,function-mask = <0x7fff>;
+                               };
+
+                               omap4_padconf_global: omap4_padconf_global@5a0 {
+                                       compatible = "syscon";
+                                       reg = <0x5a0 0x170>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       pbias_regulator: pbias_regulator {
+                                               compatible = "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>;
+                                               };
+                                       };
+                               };
                        };
 
-                       scrm_clockdomains: clockdomains {
-                       };
-               };
-
-               counter32k: counter@4a304000 {
-                       compatible = "ti,omap-counter32k";
-                       reg = <0x4a304000 0x20>;
-                       ti,hwmods = "counter_32k";
-               };
-
-               omap4_pmx_core: pinmux@4a100040 {
-                       compatible = "ti,omap4-padconf", "pinctrl-single";
-                       reg = <0x4a100040 0x0196>;
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       #interrupt-cells = <1>;
-                       interrupt-controller;
-                       pinctrl-single,register-width = <16>;
-                       pinctrl-single,function-mask = <0x7fff>;
-               };
-               omap4_pmx_wkup: pinmux@4a31e040 {
-                       compatible = "ti,omap4-padconf", "pinctrl-single";
-                       reg = <0x4a31e040 0x0038>;
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       #interrupt-cells = <1>;
-                       interrupt-controller;
-                       pinctrl-single,register-width = <16>;
-                       pinctrl-single,function-mask = <0x7fff>;
-               };
-
-               omap4_padconf_global: tisyscon@4a1005a0 {
-                       compatible = "syscon";
-                       reg = <0x4a1005a0 0x170>;
-               };
-
-               pbias_regulator: pbias_regulator {
-                       compatible = "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 0x3000>;
+                                       interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+
+                                       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_pmx_wkup: pinmux@1e040 {
+                                       compatible = "ti,omap4-padconf",
+                                                    "pinctrl-single";
+                                       reg = <0x1e040 0x0038>;
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       #interrupt-cells = <1>;
+                                       interrupt-controller;
+                                       pinctrl-single,register-width = <16>;
+                                       pinctrl-single,function-mask = <0x7fff>;
+                               };
                        };
                };
 
index 77b5f70d0ebcc8279b1e8e3e45afbc92be2abc6a..efe5f737f39b42b7f01710abdd4e72d90bd53514 100644 (file)
                interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
                             <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
 
-               prm: prm@4ae06000 {
-                       compatible = "ti,omap5-prm";
-                       reg = <0x4ae06000 0x3000>;
-                       interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+               l4_cfg: l4@4a000000 {
+                       compatible = "ti,omap5-l4-cfg", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0 0x4a000000 0x22a000>;
 
-                       prm_clocks: clocks {
+                       scm_core: scm@2000 {
+                               compatible = "ti,omap5-scm-core", "simple-bus";
+                               reg = <0x2000 0x1000>;
                                #address-cells = <1>;
-                               #size-cells = <0>;
+                               #size-cells = <1>;
+                               ranges = <0 0x2000 0x800>;
+
+                               scm_conf: scm_conf@0 {
+                                       compatible = "syscon";
+                                       reg = <0x0 0x800>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+                               };
                        };
 
-                       prm_clockdomains: clockdomains {
+                       scm_padconf_core: scm@2800 {
+                               compatible = "ti,omap5-scm-padconf-core",
+                                            "simple-bus";
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges = <0 0x2800 0x800>;
+
+                               omap5_pmx_core: pinmux@40 {
+                                       compatible = "ti,omap5-padconf",
+                                                    "pinctrl-single";
+                                       reg = <0x40 0x01b6>;
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       #interrupt-cells = <1>;
+                                       interrupt-controller;
+                                       pinctrl-single,register-width = <16>;
+                                       pinctrl-single,function-mask = <0x7fff>;
+                               };
+
+                               omap5_padconf_global: omap5_padconf_global@5a0 {
+                                       compatible = "syscon";
+                                       reg = <0x5a0 0xec>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       pbias_regulator: pbias_regulator {
+                                               compatible = "ti,pbias-omap";
+                                               reg = <0x60 0x4>;
+                                               syscon = <&omap5_padconf_global>;
+                                               pbias_mmc_reg: pbias_mmc_omap5 {
+                                                       regulator-name = "pbias_mmc_omap5";
+                                                       regulator-min-microvolt = <1800000>;
+                                                       regulator-max-microvolt = <3000000>;
+                                               };
+                                       };
+                               };
                        };
-               };
 
-               cm_core_aon: cm_core_aon@4a004000 {
-                       compatible = "ti,omap5-cm-core-aon";
-                       reg = <0x4a004000 0x2000>;
+                       cm_core_aon: cm_core_aon@4000 {
+                               compatible = "ti,omap5-cm-core-aon";
+                               reg = <0x4000 0x2000>;
 
-                       cm_core_aon_clocks: clocks {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                       };
+                               cm_core_aon_clocks: clocks {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                               };
 
-                       cm_core_aon_clockdomains: clockdomains {
+                               cm_core_aon_clockdomains: clockdomains {
+                               };
                        };
-               };
 
-               scrm: scrm@4ae0a000 {
-                       compatible = "ti,omap5-scrm";
-                       reg = <0x4ae0a000 0x2000>;
+                       cm_core: cm_core@8000 {
+                               compatible = "ti,omap5-cm-core";
+                               reg = <0x8000 0x3000>;
 
-                       scrm_clocks: clocks {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                       };
+                               cm_core_clocks: clocks {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                               };
 
-                       scrm_clockdomains: clockdomains {
+                               cm_core_clockdomains: clockdomains {
+                               };
                        };
                };
 
-               cm_core: cm_core@4a008000 {
-                       compatible = "ti,omap5-cm-core";
-                       reg = <0x4a008000 0x3000>;
+               l4_wkup: l4@4ae00000 {
+                       compatible = "ti,omap5-l4-wkup", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0 0x4ae00000 0x2b000>;
 
-                       cm_core_clocks: clocks {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
+                       counter32k: counter@4000 {
+                               compatible = "ti,omap-counter32k";
+                               reg = <0x4000 0x40>;
+                               ti,hwmods = "counter_32k";
                        };
 
-                       cm_core_clockdomains: clockdomains {
+                       prm: prm@6000 {
+                               compatible = "ti,omap5-prm";
+                               reg = <0x6000 0x3000>;
+                               interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+
+                               prm_clocks: clocks {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                               };
+
+                               prm_clockdomains: clockdomains {
+                               };
                        };
-               };
 
-               counter32k: counter@4ae04000 {
-                       compatible = "ti,omap-counter32k";
-                       reg = <0x4ae04000 0x40>;
-                       ti,hwmods = "counter_32k";
-               };
+                       scrm: scrm@a000 {
+                               compatible = "ti,omap5-scrm";
+                               reg = <0xa000 0x2000>;
 
-               omap5_pmx_core: pinmux@4a002840 {
-                       compatible = "ti,omap5-padconf", "pinctrl-single";
-                       reg = <0x4a002840 0x01b6>;
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       #interrupt-cells = <1>;
-                       interrupt-controller;
-                       pinctrl-single,register-width = <16>;
-                       pinctrl-single,function-mask = <0x7fff>;
-               };
-               omap5_pmx_wkup: pinmux@4ae0c840 {
-                       compatible = "ti,omap5-padconf", "pinctrl-single";
-                       reg = <0x4ae0c840 0x0038>;
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       #interrupt-cells = <1>;
-                       interrupt-controller;
-                       pinctrl-single,register-width = <16>;
-                       pinctrl-single,function-mask = <0x7fff>;
-               };
+                               scrm_clocks: clocks {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                               };
 
-               omap5_padconf_global: tisyscon@4a002da0 {
-                       compatible = "syscon";
-                       reg = <0x4A002da0 0xec>;
-               };
+                               scrm_clockdomains: clockdomains {
+                               };
+                       };
 
-               pbias_regulator: pbias_regulator {
-                       compatible = "ti,pbias-omap";
-                       reg = <0x60 0x4>;
-                       syscon = <&omap5_padconf_global>;
-                       pbias_mmc_reg: pbias_mmc_omap5 {
-                               regulator-name = "pbias_mmc_omap5";
-                               regulator-min-microvolt = <1800000>;
-                               regulator-max-microvolt = <3000000>;
+                       omap5_pmx_wkup: pinmux@c840 {
+                               compatible = "ti,omap5-padconf",
+                                            "pinctrl-single";
+                               reg = <0xc840 0x0038>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               #interrupt-cells = <1>;
+                               interrupt-controller;
+                               pinctrl-single,register-width = <16>;
+                               pinctrl-single,function-mask = <0x7fff>;
                        };
                };
 
index b3154c0716525a77f41c602d219f2360bb0ab1f5..6c1511263a55deacd582b96bd4c57edad59300a8 100644 (file)
@@ -23,6 +23,7 @@
                        next-level-cache = <&L2>;
                        qcom,acc = <&acc0>;
                        qcom,saw = <&saw0>;
+                       cpu-idle-states = <&CPU_SPC>;
                };
 
                cpu@1 {
@@ -33,6 +34,7 @@
                        next-level-cache = <&L2>;
                        qcom,acc = <&acc1>;
                        qcom,saw = <&saw1>;
+                       cpu-idle-states = <&CPU_SPC>;
                };
 
                cpu@2 {
@@ -43,6 +45,7 @@
                        next-level-cache = <&L2>;
                        qcom,acc = <&acc2>;
                        qcom,saw = <&saw2>;
+                       cpu-idle-states = <&CPU_SPC>;
                };
 
                cpu@3 {
                        next-level-cache = <&L2>;
                        qcom,acc = <&acc3>;
                        qcom,saw = <&saw3>;
+                       cpu-idle-states = <&CPU_SPC>;
                };
 
                L2: l2-cache {
                        compatible = "cache";
                        cache-level = <2>;
                };
+
+               idle-states {
+                       CPU_SPC: spc {
+                               compatible = "qcom,idle-state-spc",
+                                               "arm,idle-state";
+                               entry-latency-us = <400>;
+                               exit-latency-us = <900>;
+                               min-residency-us = <3000>;
+                       };
+               };
        };
 
        cpu-pmu {
                        reg = <0x020b8000 0x1000>, <0x02008000 0x1000>;
                };
 
-               saw0: regulator@2089000 {
-                       compatible = "qcom,saw2";
+               saw0: power-controller@2089000 {
+                       compatible = "qcom,apq8064-saw2-v1.1-cpu", "qcom,saw2";
                        reg = <0x02089000 0x1000>, <0x02009000 0x1000>;
                        regulator;
                };
 
-               saw1: regulator@2099000 {
-                       compatible = "qcom,saw2";
+               saw1: power-controller@2099000 {
+                       compatible = "qcom,apq8064-saw2-v1.1-cpu", "qcom,saw2";
                        reg = <0x02099000 0x1000>, <0x02009000 0x1000>;
                        regulator;
                };
 
-               saw2: regulator@20a9000 {
-                       compatible = "qcom,saw2";
+               saw2: power-controller@20a9000 {
+                       compatible = "qcom,apq8064-saw2-v1.1-cpu", "qcom,saw2";
                        reg = <0x020a9000 0x1000>, <0x02009000 0x1000>;
                        regulator;
                };
 
-               saw3: regulator@20b9000 {
-                       compatible = "qcom,saw2";
+               saw3: power-controller@20b9000 {
+                       compatible = "qcom,apq8064-saw2-v1.1-cpu", "qcom,saw2";
                        reg = <0x020b9000 0x1000>, <0x02009000 0x1000>;
                        regulator;
                };
                gsbi1: gsbi@12440000 {
                        status = "disabled";
                        compatible = "qcom,gsbi-v1.0.0";
+                       cell-index = <1>;
                        reg = <0x12440000 0x100>;
                        clocks = <&gcc GSBI1_H_CLK>;
                        clock-names = "iface";
                        #size-cells = <1>;
                        ranges;
 
+                       syscon-tcsr = <&tcsr>;
+
                        i2c1: i2c@12460000 {
                                compatible = "qcom,i2c-qup-v1.1.1";
                                reg = <0x12460000 0x1000>;
                gsbi2: gsbi@12480000 {
                        status = "disabled";
                        compatible = "qcom,gsbi-v1.0.0";
+                       cell-index = <2>;
                        reg = <0x12480000 0x100>;
                        clocks = <&gcc GSBI2_H_CLK>;
                        clock-names = "iface";
                        #size-cells = <1>;
                        ranges;
 
+                       syscon-tcsr = <&tcsr>;
+
                        i2c2: i2c@124a0000 {
                                compatible = "qcom,i2c-qup-v1.1.1";
                                reg = <0x124a0000 0x1000>;
                gsbi7: gsbi@16600000 {
                        status = "disabled";
                        compatible = "qcom,gsbi-v1.0.0";
+                       cell-index = <7>;
                        reg = <0x16600000 0x100>;
                        clocks = <&gcc GSBI7_H_CLK>;
                        clock-names = "iface";
                        #size-cells = <1>;
                        ranges;
 
+                       syscon-tcsr = <&tcsr>;
+
                        serial@16640000 {
                                compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
                                reg = <0x16640000 0x1000>,
                        #reset-cells = <1>;
                };
 
+               lcc: clock-controller@28000000 {
+                       compatible = "qcom,lcc-apq8064";
+                       reg = <0x28000000 0x1000>;
+                       #clock-cells = <1>;
+                       #reset-cells = <1>;
+               };
+
                mmcc: clock-controller@4000000 {
                        compatible = "qcom,mmcc-apq8064";
                        reg = <0x4000000 0x1000>;
                                pinctrl-0 = <&sdc4_gpios>;
                        };
                };
+
+               tcsr: syscon@1a400000 {
+                       compatible = "qcom,tcsr-apq8064", "syscon";
+                       reg = <0x1a400000 0x100>;
+               };
        };
 };
index 47370494d0f84ecf2cec66f4cd9ca22beb4f1269..d484d08163e9415557e17d05e34c567c7e2d9de1 100644 (file)
@@ -1,4 +1,6 @@
 #include "qcom-msm8974.dtsi"
+#include "qcom-pm8841.dtsi"
+#include "qcom-pm8941.dtsi"
 
 / {
        model = "Qualcomm APQ8074 Dragonboard";
index c9ff10821ad992b6f4df866fb9974f11e4a68993..f7725b96612c65475fec7f67445f4afb54c19e81 100644 (file)
@@ -1,4 +1,5 @@
 #include "qcom-apq8084.dtsi"
+#include "qcom-pma8084.dtsi"
 
 / {
        model = "Qualcomm APQ8084/IFC6540";
index 8ecec58a9ff6bcc62139f17a99239925c5dbb924..cb43acfc5d1d9d0773243d42874d5bd1f5243e4f 100644 (file)
@@ -1,4 +1,5 @@
 #include "qcom-apq8084.dtsi"
+#include "qcom-pma8084.dtsi"
 
 / {
        model = "Qualcomm APQ 8084-MTP";
index 1f130bc16858d4d1b2bbfbbca031cb49755b067a..7084010ee61ba463024a9e4ba5d48caf327e3c05 100644 (file)
@@ -21,6 +21,8 @@
                        enable-method = "qcom,kpss-acc-v2";
                        next-level-cache = <&L2>;
                        qcom,acc = <&acc0>;
+                       qcom,saw = <&saw0>;
+                       cpu-idle-states = <&CPU_SPC>;
                };
 
                cpu@1 {
@@ -30,6 +32,8 @@
                        enable-method = "qcom,kpss-acc-v2";
                        next-level-cache = <&L2>;
                        qcom,acc = <&acc1>;
+                       qcom,saw = <&saw1>;
+                       cpu-idle-states = <&CPU_SPC>;
                };
 
                cpu@2 {
@@ -39,6 +43,8 @@
                        enable-method = "qcom,kpss-acc-v2";
                        next-level-cache = <&L2>;
                        qcom,acc = <&acc2>;
+                       qcom,saw = <&saw2>;
+                       cpu-idle-states = <&CPU_SPC>;
                };
 
                cpu@3 {
@@ -48,6 +54,8 @@
                        enable-method = "qcom,kpss-acc-v2";
                        next-level-cache = <&L2>;
                        qcom,acc = <&acc3>;
+                       qcom,saw = <&saw3>;
+                       cpu-idle-states = <&CPU_SPC>;
                };
 
                L2: l2-cache {
                        cache-level = <2>;
                        qcom,saw = <&saw_l2>;
                };
+
+               idle-states {
+                       CPU_SPC: spc {
+                               compatible = "qcom,idle-state-spc",
+                                               "arm,idle-state";
+                               entry-latency-us = <150>;
+                               exit-latency-us = <200>;
+                               min-residency-us = <2000>;
+                       };
+               };
        };
 
        cpu-pmu {
                        };
                };
 
-               saw_l2: regulator@f9012000 {
+               saw0: power-controller@f9089000 {
+                       compatible = "qcom,apq8084-saw2-v2.1-cpu", "qcom,saw2";
+                       reg = <0xf9089000 0x1000>, <0xf9009000 0x1000>;
+               };
+
+               saw1: power-controller@f9099000 {
+                       compatible = "qcom,apq8084-saw2-v2.1-cpu", "qcom,saw2";
+                       reg = <0xf9099000 0x1000>, <0xf9009000 0x1000>;
+               };
+
+               saw2: power-controller@f90a9000 {
+                       compatible = "qcom,apq8084-saw2-v2.1-cpu", "qcom,saw2";
+                       reg = <0xf90a9000 0x1000>, <0xf9009000 0x1000>;
+               };
+
+               saw3: power-controller@f90b9000 {
+                       compatible = "qcom,apq8084-saw2-v2.1-cpu", "qcom,saw2";
+                       reg = <0xf90b9000 0x1000>, <0xf9009000 0x1000>;
+               };
+
+               saw_l2: power-controller@f9012000 {
                        compatible = "qcom,saw2";
                        reg = <0xf9012000 0x1000>;
                        regulator;
                        clock-names = "core", "iface";
                        status = "disabled";
                };
+
+               spmi_bus: spmi@fc4cf000 {
+                       compatible = "qcom,spmi-pmic-arb";
+                       reg-names = "core", "intr", "cnfg";
+                       reg = <0xfc4cf000 0x1000>,
+                             <0xfc4cb000 0x1000>,
+                             <0xfc4ca000 0x1000>;
+                       interrupt-names = "periph_irq";
+                       interrupts = <0 190 0>;
+                       qcom,ee = <0>;
+                       qcom,channel = <0>;
+                       #address-cells = <2>;
+                       #size-cells = <0>;
+                       interrupt-controller;
+                       #interrupt-cells = <4>;
+               };
        };
 };
index cb225dafe97cd83c9ae4cc19482ed55d4a71b8b3..9f727d8eadf6998561e748e0400e46299417f9b3 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "skeleton.dtsi"
 #include <dt-bindings/clock/qcom,gcc-ipq806x.h>
+#include <dt-bindings/clock/qcom,lcc-ipq806x.h>
 #include <dt-bindings/soc/qcom,gsbi.h>
 
 / {
                };
        };
 
+       clocks {
+               sleep_clk: sleep_clk {
+                       compatible = "fixed-clock";
+                       clock-frequency = <32768>;
+                       #clock-cells = <0>;
+               };
+       };
+
        soc: soc {
                #address-cells = <1>;
                #size-cells = <1>;
                ranges;
                compatible = "simple-bus";
 
+               lpass@28100000 {
+                       compatible = "qcom,lpass-cpu";
+                       status = "disabled";
+                       clocks = <&lcc AHBIX_CLK>,
+                                       <&lcc MI2S_OSR_CLK>,
+                                       <&lcc MI2S_BIT_CLK>;
+                       clock-names = "ahbix-clk",
+                                       "mi2s-osr-clk",
+                                       "mi2s-bit-clk";
+                       interrupts = <0 85 1>;
+                       interrupt-names = "lpass-irq-lpaif";
+                       reg = <0x28100000 0x10000>;
+                       reg-names = "lpass-lpaif";
+               };
+
                qcom_pinmux: pinmux@800000 {
                        compatible = "qcom,ipq8064-pinctrl";
                        reg = <0x800000 0x4000>;
                        compatible = "qcom,kpss-timer", "qcom,msm-timer";
                        interrupts = <1 1 0x301>,
                                     <1 2 0x301>,
-                                    <1 3 0x301>;
+                                    <1 3 0x301>,
+                                    <1 4 0x301>,
+                                    <1 5 0x301>;
                        reg = <0x0200a000 0x100>;
                        clock-frequency = <25000000>,
                                          <32768>;
+                       clocks = <&sleep_clk>;
+                       clock-names = "sleep";
                        cpu-offset = <0x80000>;
                };
 
 
                gsbi2: gsbi@12480000 {
                        compatible = "qcom,gsbi-v1.0.0";
+                       cell-index = <2>;
                        reg = <0x12480000 0x100>;
                        clocks = <&gcc GSBI2_H_CLK>;
                        clock-names = "iface";
                        ranges;
                        status = "disabled";
 
+                       syscon-tcsr = <&tcsr>;
+
                        serial@12490000 {
                                compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
                                reg = <0x12490000 0x1000>,
 
                gsbi4: gsbi@16300000 {
                        compatible = "qcom,gsbi-v1.0.0";
+                       cell-index = <4>;
                        reg = <0x16300000 0x100>;
                        clocks = <&gcc GSBI4_H_CLK>;
                        clock-names = "iface";
                        ranges;
                        status = "disabled";
 
+                       syscon-tcsr = <&tcsr>;
+
                        serial@16340000 {
                                compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
                                reg = <0x16340000 0x1000>,
 
                gsbi5: gsbi@1a200000 {
                        compatible = "qcom,gsbi-v1.0.0";
+                       cell-index = <5>;
                        reg = <0x1a200000 0x100>;
                        clocks = <&gcc GSBI5_H_CLK>;
                        clock-names = "iface";
                        ranges;
                        status = "disabled";
 
+                       syscon-tcsr = <&tcsr>;
+
                        serial@1a240000 {
                                compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
                                reg = <0x1a240000 0x1000>,
                        #clock-cells = <1>;
                        #reset-cells = <1>;
                };
+
+               tcsr: syscon@1a400000 {
+                       compatible = "qcom,tcsr-ipq8064", "syscon";
+                       reg = <0x1a400000 0x100>;
+               };
+
+               lcc: clock-controller@28000000 {
+                       compatible = "qcom,lcc-ipq8064";
+                       reg = <0x28000000 0x1000>;
+                       #clock-cells = <1>;
+                       #reset-cells = <1>;
+               };
+
        };
 };
index 0affd6193f56c987c5a2806f40705fbddb92cab2..20bbd19b996ecfc4b883e770f0800dbb4f288215 100644 (file)
@@ -82,6 +82,7 @@
 
                gsbi12: gsbi@19c00000 {
                        compatible = "qcom,gsbi-v1.0.0";
+                       cell-index = <12>;
                        reg = <0x19c00000 0x100>;
                        clocks = <&gcc GSBI12_H_CLK>;
                        clock-names = "iface";
@@ -89,6 +90,8 @@
                        #size-cells = <1>;
                        ranges;
 
+                       syscon-tcsr = <&tcsr>;
+
                        serial@19c40000 {
                                compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
                                reg = <0x19c40000 0x1000>,
                                vmmc-supply = <&vsdcc_fixed>;
                        };
                };
+
+               tcsr: syscon@1a400000 {
+                       compatible = "qcom,tcsr-msm8660", "syscon";
+                       reg = <0x1a400000 0x100>;
+               };
        };
 
 };
index e1b0d5cd9e3cb7860363169a4f58efc158d05ced..a02b984cc68d8e2704abcb175e54c061ed54f629 100644 (file)
                        reg = <0x900000 0x4000>;
                };
 
+               lcc: clock-controller@28000000 {
+                       compatible = "qcom,lcc-msm8960";
+                       reg = <0x28000000 0x1000>;
+                       #clock-cells = <1>;
+                       #reset-cells = <1>;
+               };
+
                clock-controller@4000000 {
                        compatible = "qcom,mmcc-msm8960";
                        reg = <0x4000000 0x1000>;
 
                gsbi5: gsbi@16400000 {
                        compatible = "qcom,gsbi-v1.0.0";
+                       cell-index = <5>;
                        reg = <0x16400000 0x100>;
                        clocks = <&gcc GSBI5_H_CLK>;
                        clock-names = "iface";
                        #size-cells = <1>;
                        ranges;
 
+                       syscon-tcsr = <&tcsr>;
+
                        serial@16440000 {
                                compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
                                reg = <0x16440000 0x1000>,
                                vmmc-supply = <&vsdcc_fixed>;
                        };
                };
+
+               tcsr: syscon@1a400000 {
+                       compatible = "qcom,tcsr-msm8960", "syscon";
+                       reg = <0x1a400000 0x100>;
+               };
        };
 };
index cccc21b7c8fde929c3c118dde9c46be740179609..bd35b0674ff6894cd6518046d049b385e038a624 100644 (file)
@@ -1,4 +1,6 @@
 #include "qcom-msm8974.dtsi"
+#include "qcom-pm8841.dtsi"
+#include "qcom-pm8941.dtsi"
 
 / {
        model = "Sony Xperia Z1";
index e265ec16a7879b013639821e2a7b2db56aa57989..37b47b5538b816bb51c251c521d58d18b7bbd806 100644 (file)
@@ -21,6 +21,8 @@
                        reg = <0>;
                        next-level-cache = <&L2>;
                        qcom,acc = <&acc0>;
+                       qcom,saw = <&saw0>;
+                       cpu-idle-states = <&CPU_SPC>;
                };
 
                cpu@1 {
@@ -30,6 +32,8 @@
                        reg = <1>;
                        next-level-cache = <&L2>;
                        qcom,acc = <&acc1>;
+                       qcom,saw = <&saw1>;
+                       cpu-idle-states = <&CPU_SPC>;
                };
 
                cpu@2 {
@@ -39,6 +43,8 @@
                        reg = <2>;
                        next-level-cache = <&L2>;
                        qcom,acc = <&acc2>;
+                       qcom,saw = <&saw2>;
+                       cpu-idle-states = <&CPU_SPC>;
                };
 
                cpu@3 {
@@ -48,6 +54,8 @@
                        reg = <3>;
                        next-level-cache = <&L2>;
                        qcom,acc = <&acc3>;
+                       qcom,saw = <&saw3>;
+                       cpu-idle-states = <&CPU_SPC>;
                };
 
                L2: l2-cache {
                        cache-level = <2>;
                        qcom,saw = <&saw_l2>;
                };
+
+               idle-states {
+                       CPU_SPC: spc {
+                               compatible = "qcom,idle-state-spc",
+                                               "arm,idle-state";
+                               entry-latency-us = <150>;
+                               exit-latency-us = <200>;
+                               min-residency-us = <2000>;
+                       };
+               };
        };
 
        cpu-pmu {
                        };
                };
 
-               saw_l2: regulator@f9012000 {
+               saw0: power-controller@f9089000 {
+                       compatible = "qcom,msm8974-saw2-v2.1-cpu", "qcom,saw2";
+                       reg = <0xf9089000 0x1000>, <0xf9009000 0x1000>;
+               };
+
+               saw1: power-controller@f9099000 {
+                       compatible = "qcom,msm8974-saw2-v2.1-cpu", "qcom,saw2";
+                       reg = <0xf9099000 0x1000>, <0xf9009000 0x1000>;
+               };
+
+               saw2: power-controller@f90a9000 {
+                       compatible = "qcom,msm8974-saw2-v2.1-cpu", "qcom,saw2";
+                       reg = <0xf90a9000 0x1000>, <0xf9009000 0x1000>;
+               };
+
+               saw3: power-controller@f90b9000 {
+                       compatible = "qcom,msm8974-saw2-v2.1-cpu", "qcom,saw2";
+                       reg = <0xf90b9000 0x1000>, <0xf9009000 0x1000>;
+               };
+
+               saw_l2: power-controller@f9012000 {
                        compatible = "qcom,saw2";
                        reg = <0xf9012000 0x1000>;
                        regulator;
                        #address-cells = <1>;
                        #size-cells = <0>;
                };
+
+               spmi_bus: spmi@fc4cf000 {
+                       compatible = "qcom,spmi-pmic-arb";
+                       reg-names = "core", "intr", "cnfg";
+                       reg = <0xfc4cf000 0x1000>,
+                             <0xfc4cb000 0x1000>,
+                             <0xfc4ca000 0x1000>;
+                       interrupt-names = "periph_irq";
+                       interrupts = <0 190 0>;
+                       qcom,ee = <0>;
+                       qcom,channel = <0>;
+                       #address-cells = <2>;
+                       #size-cells = <0>;
+                       interrupt-controller;
+                       #interrupt-cells = <4>;
+               };
        };
 };
diff --git a/arch/arm/boot/dts/qcom-pm8841.dtsi b/arch/arm/boot/dts/qcom-pm8841.dtsi
new file mode 100644 (file)
index 0000000..73813cc
--- /dev/null
@@ -0,0 +1,18 @@
+#include <dt-bindings/spmi/spmi.h>
+
+&spmi_bus {
+
+       usid4: pm8841@4 {
+               compatible = "qcom,spmi-pmic";
+               reg = <0x4 SPMI_USID>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+
+       usid5: pm8841@5 {
+               compatible = "qcom,spmi-pmic";
+               reg = <0x5 SPMI_USID>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+};
diff --git a/arch/arm/boot/dts/qcom-pm8941.dtsi b/arch/arm/boot/dts/qcom-pm8941.dtsi
new file mode 100644 (file)
index 0000000..24c5088
--- /dev/null
@@ -0,0 +1,18 @@
+#include <dt-bindings/spmi/spmi.h>
+
+&spmi_bus {
+
+       usid0: pm8941@0 {
+               compatible ="qcom,spmi-pmic";
+               reg = <0x0 SPMI_USID>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+
+       usid1: pm8941@1 {
+               compatible ="qcom,spmi-pmic";
+               reg = <0x1 SPMI_USID>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+};
diff --git a/arch/arm/boot/dts/qcom-pma8084.dtsi b/arch/arm/boot/dts/qcom-pma8084.dtsi
new file mode 100644 (file)
index 0000000..a5a4fe6
--- /dev/null
@@ -0,0 +1,18 @@
+#include <dt-bindings/spmi/spmi.h>
+
+&spmi_bus {
+
+       usid0: pma8084@0 {
+               compatible = "qcom,spmi-pmic";
+               reg = <0x0 SPMI_USID>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+
+       usid1: pma8084@1 {
+               compatible = "qcom,spmi-pmic";
+               reg = <0x1 SPMI_USID>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+};
diff --git a/arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts b/arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts
deleted file mode 100644 (file)
index b3d8f84..0000000
+++ /dev/null
@@ -1,156 +0,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/;
-#include "r8a73a4.dtsi"
-#include <dt-bindings/gpio/gpio.h>
-
-/ {
-       model = "APE6EVM";
-       compatible = "renesas,ape6evm-reference", "renesas,r8a73a4";
-
-       aliases {
-               serial0 = &scifa0;
-       };
-
-       chosen {
-               bootargs = "ignore_loglevel rw";
-               stdout-path = &scifa0;
-       };
-
-       memory@40000000 {
-               device_type = "memory";
-               reg = <0 0x40000000 0 0x40000000>;
-       };
-
-       memory@200000000 {
-               device_type = "memory";
-               reg = <2 0x00000000 0 0x40000000>;
-       };
-
-       vcc_mmc0: regulator@0 {
-               compatible = "regulator-fixed";
-               regulator-name = "MMC0 Vcc";
-               regulator-min-microvolt = <2800000>;
-               regulator-max-microvolt = <2800000>;
-               regulator-always-on;
-       };
-
-       vcc_sdhi0: regulator@1 {
-               compatible = "regulator-fixed";
-
-               regulator-name = "SDHI0 Vcc";
-               regulator-min-microvolt = <3300000>;
-               regulator-max-microvolt = <3300000>;
-
-               gpio = <&pfc 76 GPIO_ACTIVE_HIGH>;
-               enable-active-high;
-       };
-
-       /* Common 3.3V rail, used by several devices on APE6EVM */
-       ape6evm_fixed_3v3: regulator@2 {
-               compatible = "regulator-fixed";
-               regulator-name = "3V3";
-               regulator-min-microvolt = <3300000>;
-               regulator-max-microvolt = <3300000>;
-               regulator-always-on;
-       };
-
-       lbsc {
-               compatible = "simple-bus";
-               #address-cells = <1>;
-               #size-cells = <1>;
-               ranges = <0 0 0 0x20000000>;
-       };
-};
-
-&i2c5 {
-       status = "okay";
-       vdd_dvfs: max8973@1b {
-               compatible = "maxim,max8973";
-               reg = <0x1b>;
-
-               regulator-min-microvolt = <935000>;
-               regulator-max-microvolt = <1200000>;
-               regulator-boot-on;
-               regulator-always-on;
-       };
-};
-
-&cpu0 {
-       cpu0-supply = <&vdd_dvfs>;
-       operating-points = <
-               /* kHz  uV */
-               1950000 1115000
-               1462500  995000
-       >;
-       voltage-tolerance = <1>; /* 1% */
-};
-
-&cmt1 {
-       status = "okay";
-};
-
-&pfc {
-       scifa0_pins: serial0 {
-               renesas,groups = "scifa0_data";
-               renesas,function = "scifa0";
-       };
-
-       mmc0_pins: mmc {
-               renesas,groups = "mmc0_data8", "mmc0_ctrl";
-               renesas,function = "mmc0";
-       };
-
-       sdhi0_pins: sd0 {
-               renesas,groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_cd";
-               renesas,function = "sdhi0";
-       };
-
-       sdhi1_pins: sd1 {
-               renesas,groups = "sdhi1_data4", "sdhi1_ctrl";
-               renesas,function = "sdhi1";
-       };
-};
-
-&mmcif0 {
-       vmmc-supply = <&vcc_mmc0>;
-       bus-width = <8>;
-       non-removable;
-       pinctrl-names = "default";
-       pinctrl-0 = <&mmc0_pins>;
-       status = "okay";
-};
-
-&scifa0 {
-       pinctrl-0 = <&scifa0_pins>;
-       pinctrl-names = "default";
-
-       status = "okay";
-};
-
-&sdhi0 {
-       vmmc-supply = <&vcc_sdhi0>;
-       bus-width = <4>;
-       toshiba,mmc-wrprotect-disable;
-       pinctrl-names = "default";
-       pinctrl-0 = <&sdhi0_pins>;
-       status = "okay";
-};
-
-&sdhi1 {
-       vmmc-supply = <&ape6evm_fixed_3v3>;
-       bus-width = <4>;
-       broken-cd;
-       toshiba,mmc-wrprotect-disable;
-       pinctrl-names = "default";
-       pinctrl-0 = <&sdhi1_pins>;
-       status = "okay";
-};
index 0d50bef0123449f5763a3fbd0f38956ae8508d74..81a38ceee098087ecd05ab13fa5e700783648e29 100644 (file)
@@ -22,7 +22,7 @@
        };
 
        chosen {
-               bootargs = "console=ttySC0,115200 ignore_loglevel root=/dev/nfs ip=dhcp rw";
+               bootargs = "ignore_loglevel root=/dev/nfs ip=dhcp rw";
                stdout-path = &scifa0;
        };
 
                regulator-always-on;
        };
 
-       lbsc {
-               compatible = "simple-bus";
-               #address-cells = <1>;
-               #size-cells = <1>;
-               ranges = <0 0 0 0x20000000>;
-
-               ethernet@8000000 {
-                       compatible = "smsc,lan9220", "smsc,lan9115";
-                       reg = <0x08000000 0x1000>;
-                       interrupt-parent = <&irqc1>;
-                       interrupts = <8 IRQ_TYPE_LEVEL_HIGH>;
-                       phy-mode = "mii";
-                       reg-io-width = <4>;
-                       smsc,irq-active-high;
-                       smsc,irq-push-pull;
-                       vdd33a-supply = <&ape6evm_fixed_3v3>;
-                       vddvario-supply = <&ape6evm_fixed_1v8>;
-               };
-       };
-
        leds {
                compatible = "gpio-leds";
                led1 {
-                       gpios = <&pfc 28 GPIO_ACTIVE_LOW>;
+                       gpios = <&pfc 28 GPIO_ACTIVE_HIGH>;
                        label = "GNSS_EN";
                };
                led2 {
-                       gpios = <&pfc 126 GPIO_ACTIVE_LOW>;
+                       gpios = <&pfc 126 GPIO_ACTIVE_HIGH>;
                        label = "NFC_NRST";
                };
                led3 {
-                       gpios = <&pfc 132 GPIO_ACTIVE_LOW>;
+                       gpios = <&pfc 132 GPIO_ACTIVE_HIGH>;
                        label = "GNSS_NRST";
                };
                led4 {
-                       gpios = <&pfc 232 GPIO_ACTIVE_LOW>;
+                       gpios = <&pfc 232 GPIO_ACTIVE_HIGH>;
                        label = "BT_WAKEUP";
                };
                led5 {
-                       gpios = <&pfc 250 GPIO_ACTIVE_LOW>;
+                       gpios = <&pfc 250 GPIO_ACTIVE_HIGH>;
                        label = "STROBE";
                };
                led6 {
-                       gpios = <&pfc 288 GPIO_ACTIVE_LOW>;
+                       gpios = <&pfc 288 GPIO_ACTIVE_HIGH>;
                        label = "BBRESETOUT";
                };
        };
        keyboard {
                compatible = "gpio-keys";
 
+               pinctrl-names = "default";
+               pinctrl-0 = <&keyboard_pins>;
+
                zero-key {
                        gpios = <&pfc 324 GPIO_ACTIVE_LOW>;
                        linux,code = <KEY_0>;
                        label = "S16";
+                       gpio-key,wakeup;
                };
 
                menu-key {
        voltage-tolerance = <1>; /* 1% */
 };
 
+&bsc {
+       ethernet@8000000 {
+               compatible = "smsc,lan9220", "smsc,lan9115";
+               reg = <0x08000000 0x1000>;
+               interrupt-parent = <&irqc1>;
+               interrupts = <8 IRQ_TYPE_LEVEL_HIGH>;
+               phy-mode = "mii";
+               reg-io-width = <4>;
+               smsc,irq-active-high;
+               smsc,irq-push-pull;
+               vdd33a-supply = <&ape6evm_fixed_3v3>;
+               vddvario-supply = <&ape6evm_fixed_1v8>;
+       };
+};
+
 &cmt1 {
        status = "okay";
 };
                renesas,groups = "sdhi1_data4", "sdhi1_ctrl";
                renesas,function = "sdhi1";
        };
+
+       keyboard_pins: keyboard {
+               renesas,pins = "PORT324", "PORT325", "PORT326", "PORT327",
+                              "PORT328", "PORT329";
+               bias-pull-up;
+       };
 };
 
 &mmcif0 {
index 38136d9f6d95a16ea0bb08f846ba4522a4d469aa..0fd889f88109de173c8760d7a7412ec0bc758b1d 100644 (file)
@@ -9,6 +9,7 @@
  * kind, whether express or implied.
  */
 
+#include <dt-bindings/clock/r8a73a4-clock.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 
                        compatible = "arm,cortex-a15";
                        reg = <0>;
                        clock-frequency = <1500000000>;
+                       power-domains = <&pd_a2sl>;
                };
        };
 
+       ptm {
+               compatible = "arm,coresight-etm3x";
+               power-domains = <&pd_d4>;
+       };
+
        timer {
                compatible = "arm,armv7-timer";
                interrupts = <1 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
        dbsc1: memory-controller@e6790000 {
                compatible = "renesas,dbsc-r8a73a4";
                reg = <0 0xe6790000 0 0x10000>;
+               power-domains = <&pd_a3bc>;
        };
 
        dbsc2: memory-controller@e67a0000 {
                compatible = "renesas,dbsc-r8a73a4";
                reg = <0 0xe67a0000 0 0x10000>;
+               power-domains = <&pd_a3bc>;
        };
 
        dmac: dma-multiplexer {
                                        "ch8", "ch9", "ch10", "ch11",
                                        "ch12", "ch13", "ch14", "ch15",
                                        "ch16", "ch17", "ch18", "ch19";
+                       clocks = <&mstp2_clks R8A73A4_CLK_DMAC>;
+                       power-domains = <&pd_a3sp>;
                };
        };
 
-       pfc: pfc@e6050000 {
-               compatible = "renesas,pfc-r8a73a4";
-               reg = <0 0xe6050000 0 0x9000>;
-               gpio-controller;
-               #gpio-cells = <2>;
-               interrupts-extended =
-                       <&irqc0  0 0>, <&irqc0  1 0>, <&irqc0  2 0>, <&irqc0  3 0>,
-                       <&irqc0  4 0>, <&irqc0  5 0>, <&irqc0  6 0>, <&irqc0  7 0>,
-                       <&irqc0  8 0>, <&irqc0  9 0>, <&irqc0 10 0>, <&irqc0 11 0>,
-                       <&irqc0 12 0>, <&irqc0 13 0>, <&irqc0 14 0>, <&irqc0 15 0>,
-                       <&irqc0 16 0>, <&irqc0 17 0>, <&irqc0 18 0>, <&irqc0 19 0>,
-                       <&irqc0 20 0>, <&irqc0 21 0>, <&irqc0 22 0>, <&irqc0 23 0>,
-                       <&irqc0 24 0>, <&irqc0 25 0>, <&irqc0 26 0>, <&irqc0 27 0>,
-                       <&irqc0 28 0>, <&irqc0 29 0>, <&irqc0 30 0>, <&irqc0 31 0>,
-                       <&irqc1  0 0>, <&irqc1  1 0>, <&irqc1  2 0>, <&irqc1  3 0>,
-                       <&irqc1  4 0>, <&irqc1  5 0>, <&irqc1  6 0>, <&irqc1  7 0>,
-                       <&irqc1  8 0>, <&irqc1  9 0>, <&irqc1 10 0>, <&irqc1 11 0>,
-                       <&irqc1 12 0>, <&irqc1 13 0>, <&irqc1 14 0>, <&irqc1 15 0>,
-                       <&irqc1 16 0>, <&irqc1 17 0>, <&irqc1 18 0>, <&irqc1 19 0>,
-                       <&irqc1 20 0>, <&irqc1 21 0>, <&irqc1 22 0>, <&irqc1 23 0>,
-                       <&irqc1 24 0>, <&irqc1 25 0>;
-       };
-
        i2c5: i2c@e60b0000 {
                #address-cells = <1>;
                #size-cells = <0>;
                compatible = "renesas,iic-r8a73a4", "renesas,rmobile-iic";
                reg = <0 0xe60b0000 0 0x428>;
                interrupts = <0 179 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp4_clks R8A73A4_CLK_IIC5>;
+               power-domains = <&pd_a3sp>;
 
                status = "disabled";
        };
                compatible = "renesas,cmt-48-r8a73a4", "renesas,cmt-48-gen2";
                reg = <0 0xe6130000 0 0x1004>;
                interrupts = <0 120 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp3_clks R8A73A4_CLK_CMT1>;
+               clock-names = "fck";
+               power-domains = <&pd_c5>;
 
                renesas,channels-mask = <0xff>;
 
                             <0 29 IRQ_TYPE_LEVEL_HIGH>,
                             <0 30 IRQ_TYPE_LEVEL_HIGH>,
                             <0 31 IRQ_TYPE_LEVEL_HIGH>;
+               power-domains = <&pd_c4>;
        };
 
        irqc1: interrupt-controller@e61c0200 {
                             <0 55 IRQ_TYPE_LEVEL_HIGH>,
                             <0 56 IRQ_TYPE_LEVEL_HIGH>,
                             <0 57 IRQ_TYPE_LEVEL_HIGH>;
+               power-domains = <&pd_c4>;
+       };
+
+       pfc: pfc@e6050000 {
+               compatible = "renesas,pfc-r8a73a4";
+               reg = <0 0xe6050000 0 0x9000>;
+               gpio-controller;
+               #gpio-cells = <2>;
+               interrupts-extended =
+                       <&irqc0  0 0>, <&irqc0  1 0>, <&irqc0  2 0>, <&irqc0  3 0>,
+                       <&irqc0  4 0>, <&irqc0  5 0>, <&irqc0  6 0>, <&irqc0  7 0>,
+                       <&irqc0  8 0>, <&irqc0  9 0>, <&irqc0 10 0>, <&irqc0 11 0>,
+                       <&irqc0 12 0>, <&irqc0 13 0>, <&irqc0 14 0>, <&irqc0 15 0>,
+                       <&irqc0 16 0>, <&irqc0 17 0>, <&irqc0 18 0>, <&irqc0 19 0>,
+                       <&irqc0 20 0>, <&irqc0 21 0>, <&irqc0 22 0>, <&irqc0 23 0>,
+                       <&irqc0 24 0>, <&irqc0 25 0>, <&irqc0 26 0>, <&irqc0 27 0>,
+                       <&irqc0 28 0>, <&irqc0 29 0>, <&irqc0 30 0>, <&irqc0 31 0>,
+                       <&irqc1  0 0>, <&irqc1  1 0>, <&irqc1  2 0>, <&irqc1  3 0>,
+                       <&irqc1  4 0>, <&irqc1  5 0>, <&irqc1  6 0>, <&irqc1  7 0>,
+                       <&irqc1  8 0>, <&irqc1  9 0>, <&irqc1 10 0>, <&irqc1 11 0>,
+                       <&irqc1 12 0>, <&irqc1 13 0>, <&irqc1 14 0>, <&irqc1 15 0>,
+                       <&irqc1 16 0>, <&irqc1 17 0>, <&irqc1 18 0>, <&irqc1 19 0>,
+                       <&irqc1 20 0>, <&irqc1 21 0>, <&irqc1 22 0>, <&irqc1 23 0>,
+                       <&irqc1 24 0>, <&irqc1 25 0>;
+               power-domains = <&pd_c5>;
        };
 
        thermal@e61f0000 {
                reg = <0 0xe61f0000 0 0x14>, <0 0xe61f0100 0 0x38>,
                         <0 0xe61f0200 0 0x38>, <0 0xe61f0300 0 0x38>;
                interrupts = <0 69 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp5_clks R8A73A4_CLK_THERMAL>;
+               power-domains = <&pd_c5>;
        };
 
        i2c0: i2c@e6500000 {
                compatible = "renesas,iic-r8a73a4", "renesas,rmobile-iic";
                reg = <0 0xe6500000 0 0x428>;
                interrupts = <0 174 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp3_clks R8A73A4_CLK_IIC0>;
+               power-domains = <&pd_a3sp>;
                status = "disabled";
        };
 
                compatible = "renesas,iic-r8a73a4", "renesas,rmobile-iic";
                reg = <0 0xe6510000 0 0x428>;
                interrupts = <0 175 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp3_clks R8A73A4_CLK_IIC1>;
+               power-domains = <&pd_a3sp>;
                status = "disabled";
        };
 
                compatible = "renesas,iic-r8a73a4", "renesas,rmobile-iic";
                reg = <0 0xe6520000 0 0x428>;
                interrupts = <0 176 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp3_clks R8A73A4_CLK_IIC2>;
+               power-domains = <&pd_a3sp>;
                status = "disabled";
        };
 
                compatible = "renesas,iic-r8a73a4", "renesas,rmobile-iic";
                reg = <0 0xe6530000 0 0x428>;
                interrupts = <0 177 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp4_clks R8A73A4_CLK_IIC3>;
+               power-domains = <&pd_a3sp>;
                status = "disabled";
        };
 
                compatible = "renesas,iic-r8a73a4", "renesas,rmobile-iic";
                reg = <0 0xe6540000 0 0x428>;
                interrupts = <0 178 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp4_clks R8A73A4_CLK_IIC4>;
+               power-domains = <&pd_a3sp>;
                status = "disabled";
        };
 
                compatible = "renesas,iic-r8a73a4", "renesas,rmobile-iic";
                reg = <0 0xe6550000 0 0x428>;
                interrupts = <0 184 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp3_clks R8A73A4_CLK_IIC6>;
+               power-domains = <&pd_a3sp>;
                status = "disabled";
        };
 
                compatible = "renesas,iic-r8a73a4", "renesas,rmobile-iic";
                reg = <0 0xe6560000 0 0x428>;
                interrupts = <0 185 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp3_clks R8A73A4_CLK_IIC7>;
+               power-domains = <&pd_a3sp>;
                status = "disabled";
        };
 
                compatible = "renesas,iic-r8a73a4", "renesas,rmobile-iic";
                reg = <0 0xe6570000 0 0x428>;
                interrupts = <0 173 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp5_clks R8A73A4_CLK_IIC8>;
+               power-domains = <&pd_a3sp>;
                status = "disabled";
        };
 
                compatible = "renesas,scifb-r8a73a4", "renesas,scifb";
                reg = <0 0xe6c20000 0 0x100>;
                interrupts = <0 148 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp2_clks R8A73A4_CLK_SCIFB0>;
+               clock-names = "sci_ick";
+               power-domains = <&pd_a3sp>;
                status = "disabled";
        };
 
                compatible = "renesas,scifb-r8a73a4", "renesas,scifb";
                reg = <0 0xe6c30000 0 0x100>;
                interrupts = <0 149 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp2_clks R8A73A4_CLK_SCIFB1>;
+               clock-names = "sci_ick";
+               power-domains = <&pd_a3sp>;
                status = "disabled";
        };
 
                compatible = "renesas,scifa-r8a73a4", "renesas,scifa";
                reg = <0 0xe6c40000 0 0x100>;
                interrupts = <0 144 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp2_clks R8A73A4_CLK_SCIFA0>;
+               clock-names = "sci_ick";
+               power-domains = <&pd_a3sp>;
                status = "disabled";
        };
 
                compatible = "renesas,scifa-r8a73a4", "renesas,scifa";
                reg = <0 0xe6c50000 0 0x100>;
                interrupts = <0 145 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp2_clks R8A73A4_CLK_SCIFA1>;
+               clock-names = "sci_ick";
+               power-domains = <&pd_a3sp>;
                status = "disabled";
        };
 
                compatible = "renesas,scifb-r8a73a4", "renesas,scifb";
                reg = <0 0xe6ce0000 0 0x100>;
                interrupts = <0 150 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp2_clks R8A73A4_CLK_SCIFB2>;
+               clock-names = "sci_ick";
+               power-domains = <&pd_a3sp>;
                status = "disabled";
        };
 
                compatible = "renesas,scifb-r8a73a4", "renesas,scifb";
                reg = <0 0xe6cf0000 0 0x100>;
                interrupts = <0 151 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp2_clks R8A73A4_CLK_SCIFB3>;
+               clock-names = "sci_ick";
+               power-domains = <&pd_c4>;
                status = "disabled";
        };
 
                compatible = "renesas,sdhi-r8a73a4";
                reg = <0 0xee100000 0 0x100>;
                interrupts = <0 165 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp3_clks R8A73A4_CLK_SDHI0>;
+               power-domains = <&pd_a3sp>;
                cap-sd-highspeed;
                status = "disabled";
        };
                compatible = "renesas,sdhi-r8a73a4";
                reg = <0 0xee120000 0 0x100>;
                interrupts = <0 166 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp3_clks R8A73A4_CLK_SDHI1>;
+               power-domains = <&pd_a3sp>;
                cap-sd-highspeed;
                status = "disabled";
        };
                compatible = "renesas,sdhi-r8a73a4";
                reg = <0 0xee140000 0 0x100>;
                interrupts = <0 167 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp3_clks R8A73A4_CLK_SDHI2>;
+               power-domains = <&pd_a3sp>;
                cap-sd-highspeed;
                status = "disabled";
        };
                compatible = "renesas,sh-mmcif";
                reg = <0 0xee200000 0 0x80>;
                interrupts = <0 169 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp3_clks R8A73A4_CLK_MMCIF0>;
+               power-domains = <&pd_a3sp>;
                reg-io-width = <4>;
                status = "disabled";
        };
                compatible = "renesas,sh-mmcif";
                reg = <0 0xee220000 0 0x80>;
                interrupts = <0 170 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp3_clks R8A73A4_CLK_MMCIF1>;
+               power-domains = <&pd_a3sp>;
                reg-io-width = <4>;
                status = "disabled";
        };
                        <0 0xf1006000 0 0x2000>;
                interrupts = <1 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
        };
+
+       bsc: bus@fec10000 {
+               compatible = "renesas,bsc-r8a73a4", "renesas,bsc",
+                            "simple-pm-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0 0 0 0x20000000>;
+               reg = <0 0xfec10000 0 0x400>;
+               clocks = <&zb_clk>;
+               power-domains = <&pd_c4>;
+       };
+
+       clocks {
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges;
+
+               /* External root clocks */
+               extalr_clk: extalr_clk {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <32768>;
+                       clock-output-names = "extalr";
+               };
+               extal1_clk: extal1_clk {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <25000000>;
+                       clock-output-names = "extal1";
+               };
+               extal2_clk: extal2_clk {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <48000000>;
+                       clock-output-names = "extal2";
+               };
+               fsiack_clk: fsiack_clk {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       /* This value must be overridden by the board. */
+                       clock-frequency = <0>;
+                       clock-output-names = "fsiack";
+               };
+               fsibck_clk: fsibck_clk {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       /* This value must be overridden by the board. */
+                       clock-frequency = <0>;
+                       clock-output-names = "fsibck";
+               };
+
+               /* Special CPG clocks */
+               cpg_clocks: cpg_clocks@e6150000 {
+                       compatible = "renesas,r8a73a4-cpg-clocks";
+                       reg = <0 0xe6150000 0 0x10000>;
+                       clocks = <&extal1_clk>, <&extal2_clk>;
+                       #clock-cells = <1>;
+                       clock-output-names = "main", "pll0", "pll1", "pll2",
+                                            "pll2s", "pll2h", "z", "z2",
+                                            "i", "m3", "b", "m1", "m2",
+                                            "zx", "zs", "hp";
+               };
+
+               /* Variable factor clocks (DIV6) */
+               zb_clk: zb_clk@e6150010 {
+                       compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
+                       reg = <0 0xe6150010 0 4>;
+                       clocks = <&pll1_div2_clk>, <0>,
+                                <&cpg_clocks R8A73A4_CLK_PLL2S>, <0>;
+                       #clock-cells = <0>;
+                       clock-output-names = "zb";
+               };
+               sdhi0_clk: sdhi0_clk@e6150074 {
+                       compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
+                       reg = <0 0xe6150074 0 4>;
+                       clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>,
+                                <0>, <&extal2_clk>;
+                       #clock-cells = <0>;
+                       clock-output-names = "sdhi0ck";
+               };
+               sdhi1_clk: sdhi1_clk@e6150078 {
+                       compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
+                       reg = <0 0xe6150078 0 4>;
+                       clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>,
+                                <0>, <&extal2_clk>;
+                       #clock-cells = <0>;
+                       clock-output-names = "sdhi1ck";
+               };
+               sdhi2_clk: sdhi2_clk@e615007c {
+                       compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
+                       reg = <0 0xe615007c 0 4>;
+                       clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>,
+                                <0>, <&extal2_clk>;
+                       #clock-cells = <0>;
+                       clock-output-names = "sdhi2ck";
+               };
+               mmc0_clk: mmc0_clk@e6150240 {
+                       compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
+                       reg = <0 0xe6150240 0 4>;
+                       clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>,
+                                <0>, <&extal2_clk>;
+                       #clock-cells = <0>;
+                       clock-output-names = "mmc0";
+               };
+               mmc1_clk: mmc1_clk@e6150244 {
+                       compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
+                       reg = <0 0xe6150244 0 4>;
+                       clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>,
+                                <0>, <&extal2_clk>;
+                       #clock-cells = <0>;
+                       clock-output-names = "mmc1";
+               };
+               vclk1_clk: vclk1_clk@e6150008 {
+                       compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
+                       reg = <0 0xe6150008 0 4>;
+                       clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>,
+                                <0>, <&extal2_clk>, <&main_div2_clk>,
+                                <&extalr_clk>, <0>, <0>;
+                       #clock-cells = <0>;
+                       clock-output-names = "vclk1";
+               };
+               vclk2_clk: vclk2_clk@e615000c {
+                       compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
+                       reg = <0 0xe615000c 0 4>;
+                       clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>,
+                                <0>, <&extal2_clk>, <&main_div2_clk>,
+                                <&extalr_clk>, <0>, <0>;
+                       #clock-cells = <0>;
+                       clock-output-names = "vclk2";
+               };
+               vclk3_clk: vclk3_clk@e615001c {
+                       compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
+                       reg = <0 0xe615001c 0 4>;
+                       clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>,
+                                <0>, <&extal2_clk>, <&main_div2_clk>,
+                                <&extalr_clk>, <0>, <0>;
+                       #clock-cells = <0>;
+                       clock-output-names = "vclk3";
+               };
+               vclk4_clk: vclk4_clk@e6150014 {
+                       compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
+                       reg = <0 0xe6150014 0 4>;
+                       clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>,
+                                <0>, <&extal2_clk>, <&main_div2_clk>,
+                                <&extalr_clk>, <0>, <0>;
+                       #clock-cells = <0>;
+                       clock-output-names = "vclk4";
+               };
+               vclk5_clk: vclk5_clk@e6150034 {
+                       compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
+                       reg = <0 0xe6150034 0 4>;
+                       clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>,
+                                <0>, <&extal2_clk>, <&main_div2_clk>,
+                                <&extalr_clk>, <0>, <0>;
+                       #clock-cells = <0>;
+                       clock-output-names = "vclk5";
+               };
+               fsia_clk: fsia_clk@e6150018 {
+                       compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
+                       reg = <0 0xe6150018 0 4>;
+                       clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>,
+                                <&fsiack_clk>, <0>;
+                       #clock-cells = <0>;
+                       clock-output-names = "fsia";
+               };
+               fsib_clk: fsib_clk@e6150090 {
+                       compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
+                       reg = <0 0xe6150090 0 4>;
+                       clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>,
+                                <&fsibck_clk>, <0>;
+                       #clock-cells = <0>;
+                       clock-output-names = "fsib";
+               };
+               mp_clk: mp_clk@e6150080 {
+                       compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
+                       reg = <0 0xe6150080 0 4>;
+                       clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>,
+                                <&extal2_clk>, <&extal2_clk>;
+                       #clock-cells = <0>;
+                       clock-output-names = "mp";
+               };
+               m4_clk: m4_clk@e6150098 {
+                       compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
+                       reg = <0 0xe6150098 0 4>;
+                       clocks = <&cpg_clocks R8A73A4_CLK_PLL2S>;
+                       #clock-cells = <0>;
+                       clock-output-names = "m4";
+               };
+               hsi_clk: hsi_clk@e615026c {
+                       compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
+                       reg = <0 0xe615026c 0 4>;
+                       clocks = <&cpg_clocks R8A73A4_CLK_PLL2H>, <&pll1_div2_clk>,
+                                <&cpg_clocks R8A73A4_CLK_PLL2S>, <0>;
+                       #clock-cells = <0>;
+                       clock-output-names = "hsi";
+               };
+               spuv_clk: spuv_clk@e6150094 {
+                       compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
+                       reg = <0 0xe6150094 0 4>;
+                       clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>,
+                                <&extal2_clk>, <&extal2_clk>;
+                       #clock-cells = <0>;
+                       clock-output-names = "spuv";
+               };
+
+               /* Fixed factor clocks */
+               main_div2_clk: main_div2_clk {
+                       compatible = "fixed-factor-clock";
+                       clocks = <&cpg_clocks R8A73A4_CLK_MAIN>;
+                       #clock-cells = <0>;
+                       clock-div = <2>;
+                       clock-mult = <1>;
+                       clock-output-names = "main_div2";
+               };
+               pll0_div2_clk: pll0_div2_clk {
+                       compatible = "fixed-factor-clock";
+                       clocks = <&cpg_clocks R8A73A4_CLK_PLL0>;
+                       #clock-cells = <0>;
+                       clock-div = <2>;
+                       clock-mult = <1>;
+                       clock-output-names = "pll0_div2";
+               };
+               pll1_div2_clk: pll1_div2_clk {
+                       compatible = "fixed-factor-clock";
+                       clocks = <&cpg_clocks R8A73A4_CLK_PLL1>;
+                       #clock-cells = <0>;
+                       clock-div = <2>;
+                       clock-mult = <1>;
+                       clock-output-names = "pll1_div2";
+               };
+               extal1_div2_clk: extal1_div2_clk {
+                       compatible = "fixed-factor-clock";
+                       clocks = <&extal1_clk>;
+                       #clock-cells = <0>;
+                       clock-div = <2>;
+                       clock-mult = <1>;
+                       clock-output-names = "extal1_div2";
+               };
+
+               /* Gate clocks */
+               mstp2_clks: mstp2_clks@e6150138 {
+                       compatible = "renesas,r8a73a4-mstp-clocks", "renesas,cpg-mstp-clocks";
+                       reg = <0 0xe6150138 0 4>, <0 0xe6150040 0 4>;
+                       clocks = <&mp_clk>, <&mp_clk>, <&mp_clk>, <&mp_clk>,
+                                <&mp_clk>, <&mp_clk>, <&cpg_clocks R8A73A4_CLK_HP>;
+                       #clock-cells = <1>;
+                       clock-indices = <
+                               R8A73A4_CLK_SCIFA0 R8A73A4_CLK_SCIFA1
+                               R8A73A4_CLK_SCIFB0 R8A73A4_CLK_SCIFB1
+                               R8A73A4_CLK_SCIFB2 R8A73A4_CLK_SCIFB3
+                               R8A73A4_CLK_DMAC
+                       >;
+                       clock-output-names =
+                               "scifa0", "scifa1", "scifb0", "scifb1",
+                               "scifb2", "scifb3", "dmac";
+               };
+               mstp3_clks: mstp3_clks@e615013c {
+                       compatible = "renesas,r8a73a4-mstp-clocks", "renesas,cpg-mstp-clocks";
+                       reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>;
+                       clocks = <&cpg_clocks R8A73A4_CLK_HP>, <&mmc1_clk>,
+                                <&sdhi2_clk>, <&sdhi1_clk>, <&sdhi0_clk>,
+                                <&mmc0_clk>, <&cpg_clocks R8A73A4_CLK_HP>,
+                                <&cpg_clocks R8A73A4_CLK_HP>, <&cpg_clocks
+                                R8A73A4_CLK_HP>, <&cpg_clocks
+                                R8A73A4_CLK_HP>, <&extalr_clk>;
+                       #clock-cells = <1>;
+                       clock-indices = <
+                               R8A73A4_CLK_IIC2 R8A73A4_CLK_MMCIF1
+                               R8A73A4_CLK_SDHI2 R8A73A4_CLK_SDHI1
+                               R8A73A4_CLK_SDHI0 R8A73A4_CLK_MMCIF0
+                               R8A73A4_CLK_IIC6 R8A73A4_CLK_IIC7
+                               R8A73A4_CLK_IIC0 R8A73A4_CLK_IIC1
+                               R8A73A4_CLK_CMT1
+                       >;
+                       clock-output-names =
+                               "iic2", "mmcif1", "sdhi2", "sdhi1", "sdhi0",
+                               "mmcif0", "iic6", "iic7", "iic0", "iic1",
+                               "cmt1";
+               };
+               mstp4_clks: mstp4_clks@e6150140 {
+                       compatible = "renesas,r8a73a4-mstp-clocks", "renesas,cpg-mstp-clocks";
+                       reg = <0 0xe6150140 0 4>, <0 0xe615004c 0 4>;
+                       clocks = <&main_div2_clk>, <&cpg_clocks R8A73A4_CLK_HP>,
+                                <&cpg_clocks R8A73A4_CLK_HP>;
+                       #clock-cells = <1>;
+                       clock-indices = <
+                               R8A73A4_CLK_IIC5 R8A73A4_CLK_IIC4
+                               R8A73A4_CLK_IIC3
+                       >;
+                       clock-output-names =
+                               "iic5", "iic4", "iic3";
+               };
+               mstp5_clks: mstp5_clks@e6150144 {
+                       compatible = "renesas,r8a73a4-mstp-clocks", "renesas,cpg-mstp-clocks";
+                       reg = <0 0xe6150144 0 4>, <0 0xe615003c 0 4>;
+                       clocks = <&extal2_clk>, <&cpg_clocks R8A73A4_CLK_HP>;
+                       #clock-cells = <1>;
+                       clock-indices = <
+                               R8A73A4_CLK_THERMAL R8A73A4_CLK_IIC8
+                       >;
+                       clock-output-names =
+                               "thermal", "iic8";
+               };
+       };
+
+       sysc: system-controller@e6180000 {
+               compatible = "renesas,sysc-r8a73a4", "renesas,sysc-rmobile";
+               reg = <0 0xe6180000 0 0x8000>, <0 0xe6188000 0 0x8000>;
+
+               pm-domains {
+                       pd_c5: c5 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               #power-domain-cells = <0>;
+
+                               pd_c4: c4@0 {
+                                       reg = <0>;
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       #power-domain-cells = <0>;
+
+                                       pd_a3sg: a3sg@16 {
+                                               reg = <16>;
+                                               #power-domain-cells = <0>;
+                                       };
+
+                                       pd_a3ex: a3ex@17 {
+                                               reg = <17>;
+                                               #power-domain-cells = <0>;
+                                       };
+
+                                       pd_a3sp: a3sp@18 {
+                                               reg = <18>;
+                                               #address-cells = <1>;
+                                               #size-cells = <0>;
+                                               #power-domain-cells = <0>;
+
+                                               pd_a2us: a2us@19 {
+                                                       reg = <19>;
+                                                       #power-domain-cells = <0>;
+                                               };
+                                       };
+
+                                       pd_a3sm: a3sm@20 {
+                                               reg = <20>;
+                                               #address-cells = <1>;
+                                               #size-cells = <0>;
+                                               #power-domain-cells = <0>;
+
+                                               pd_a2sl: a2sl@21 {
+                                                       reg = <21>;
+                                                       #power-domain-cells = <0>;
+                                               };
+                                       };
+
+                                       pd_a3km: a3km@22 {
+                                               reg = <22>;
+                                               #address-cells = <1>;
+                                               #size-cells = <0>;
+                                               #power-domain-cells = <0>;
+
+                                               pd_a2kl: a2kl@23 {
+                                                       reg = <23>;
+                                                       #power-domain-cells = <0>;
+                                               };
+                                       };
+                               };
+
+                               pd_c4ma: c4ma@1 {
+                                       reg = <1>;
+                                       #power-domain-cells = <0>;
+                               };
+
+                               pd_c4cl: c4cl@2 {
+                                       reg = <2>;
+                                       #power-domain-cells = <0>;
+                               };
+
+                               pd_d4: d4@3 {
+                                       reg = <3>;
+                                       #power-domain-cells = <0>;
+                               };
+
+                               pd_a4bc: a4bc@4 {
+                                       reg = <4>;
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       #power-domain-cells = <0>;
+
+                                       pd_a3bc: a3bc@5 {
+                                               reg = <5>;
+                                               #power-domain-cells = <0>;
+                                       };
+                               };
+
+                               pd_a4l: a4l@6 {
+                                       reg = <6>;
+                                       #power-domain-cells = <0>;
+                               };
+
+                               pd_a4lc: a4lc@7 {
+                                       reg = <7>;
+                                       #power-domain-cells = <0>;
+                               };
+
+                               pd_a4mp: a4mp@8 {
+                                       reg = <8>;
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       #power-domain-cells = <0>;
+
+                                       pd_a3mp: a3mp@9 {
+                                               reg = <9>;
+                                               #power-domain-cells = <0>;
+                                       };
+
+                                       pd_a3vc: a3vc@10 {
+                                               reg = <10>;
+                                               #power-domain-cells = <0>;
+                                       };
+                               };
+
+                               pd_a4sf: a4sf@11 {
+                                       reg = <11>;
+                                       #power-domain-cells = <0>;
+                               };
+
+                               pd_a3r: a3r@12 {
+                                       reg = <12>;
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       #power-domain-cells = <0>;
+
+                                       pd_a2rv: a2rv@13 {
+                                               reg = <13>;
+                                               #power-domain-cells = <0>;
+                                       };
+
+                                       pd_a2is: a2is@14 {
+                                               reg = <14>;
+                                               #power-domain-cells = <0>;
+                                       };
+                               };
+                       };
+               };
+       };
 };
index 8a092605d641f7d40827104404baed8c8e819281..83c1c3ca1b8f1400010bb28fba1d8af706633e0a 100644 (file)
                        clock-frequency = <27000000>;
                        clock-output-names = "dv";
                };
+               fmsick_clk: fmsick_clk {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <0>;
+                       clock-output-names = "fmsick";
+               };
+               fmsock_clk: fmsock_clk {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <0>;
+                       clock-output-names = "fmsock";
+               };
                fsiack_clk: fsiack_clk {
                        compatible = "fixed-clock";
                        #clock-cells = <0>;
                };
 
                /* Variable factor clocks (DIV6) */
+               vclk1_clk: vclk1_clk@e6150008 {
+                       compatible = "renesas,r8a7740-div6-clock", "renesas,cpg-div6-clock";
+                       reg = <0xe6150008 4>;
+                       clocks = <&pllc1_div2_clk>, <0>, <&dv_clk>,
+                                <&cpg_clocks R8A7740_CLK_USB24S>,
+                                <&extal1_div2_clk>, <&extalr_clk>, <0>,
+                                <0>;
+                       #clock-cells = <0>;
+                       clock-output-names = "vclk1";
+               };
+               vclk2_clk: vclk2_clk@e615000c {
+                       compatible = "renesas,r8a7740-div6-clock", "renesas,cpg-div6-clock";
+                       reg = <0xe615000c 4>;
+                       clocks = <&pllc1_div2_clk>, <0>, <&dv_clk>,
+                                <&cpg_clocks R8A7740_CLK_USB24S>,
+                                <&extal1_div2_clk>, <&extalr_clk>, <0>,
+                                <0>;
+                       #clock-cells = <0>;
+                       clock-output-names = "vclk2";
+               };
+               fmsi_clk: fmsi_clk@e6150010 {
+                       compatible = "renesas,r8a7740-div6-clock", "renesas,cpg-div6-clock";
+                       reg = <0xe6150010 4>;
+                       clocks = <&pllc1_div2_clk>, <&fmsick_clk>, <0>, <0>;
+                       #clock-cells = <0>;
+                       clock-output-names = "fmsi";
+               };
+               fmso_clk: fmso_clk@e6150014 {
+                       compatible = "renesas,r8a7740-div6-clock", "renesas,cpg-div6-clock";
+                       reg = <0xe6150014 4>;
+                       clocks = <&pllc1_div2_clk>, <&fmsock_clk>, <0>, <0>;
+                       #clock-cells = <0>;
+                       clock-output-names = "fmso";
+               };
+               fsia_clk: fsia_clk@e6150018 {
+                       compatible = "renesas,r8a7740-div6-clock", "renesas,cpg-div6-clock";
+                       reg = <0xe6150018 4>;
+                       clocks = <&pllc1_div2_clk>, <&fsiack_clk>, <0>, <0>;
+                       #clock-cells = <0>;
+                       clock-output-names = "fsia";
+               };
                sub_clk: sub_clk@e6150080 {
                        compatible = "renesas,r8a7740-div6-clock", "renesas,cpg-div6-clock";
                        reg = <0xe6150080 4>;
-                       clocks = <&pllc1_div2_clk>;
+                       clocks = <&pllc1_div2_clk>,
+                                <&cpg_clocks R8A7740_CLK_USB24S>, <0>, <0>;
                        #clock-cells = <0>;
                        clock-output-names = "sub";
                };
+               spu_clk: spu_clk@e6150084 {
+                       compatible = "renesas,r8a7740-div6-clock", "renesas,cpg-div6-clock";
+                       reg = <0xe6150084 4>;
+                       clocks = <&pllc1_div2_clk>,
+                                <&cpg_clocks R8A7740_CLK_USB24S>, <0>, <0>;
+                       #clock-cells = <0>;
+                       clock-output-names = "spu";
+               };
+               vou_clk: vou_clk@e6150088 {
+                       compatible = "renesas,r8a7740-div6-clock", "renesas,cpg-div6-clock";
+                       reg = <0xe6150088 4>;
+                       clocks = <&pllc1_div2_clk>, <&extal1_clk>, <&dv_clk>,
+                                <0>;
+                       #clock-cells = <0>;
+                       clock-output-names = "vou";
+               };
+               stpro_clk: stpro_clk@e615009c {
+                       compatible = "renesas,r8a7740-div6-clock", "renesas,cpg-div6-clock";
+                       reg = <0xe615009c 4>;
+                       clocks = <&cpg_clocks R8A7740_CLK_PLLC0>;
+                       #clock-cells = <0>;
+                       clock-output-names = "stpro";
+               };
 
                /* Fixed factor clocks */
                pllc1_div2_clk: pllc1_div2_clk {
index 46a884d4517566959992b98901d6a13b94064798..787fa6f9f46ddf4d2bd0d0db9abb82e4223c2413 100644 (file)
 
 /dts-v1/;
 #include "r8a7778.dtsi"
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/gpio/gpio.h>
 
 / {
        model = "bockw";
        compatible = "renesas,bockw", "renesas,r8a7778";
 
+       aliases {
+               serial0 = &scif0;
+       };
+
        chosen {
                bootargs = "console=ttySC0,115200 ignore_loglevel ip=dhcp root=/dev/nfs rw";
+               stdout-path = &scif0;
        };
 
        memory {
                device_type = "memory";
                reg = <0x60000000 0x10000000>;
        };
+
+       fixedregulator3v3: fixedregulator@0 {
+               compatible = "regulator-fixed";
+               regulator-name = "fixed-3.3V";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-boot-on;
+               regulator-always-on;
+       };
+
+       sound {
+               compatible = "simple-audio-card";
+
+               simple-audio-card,format = "left_j";
+               simple-audio-card,bitclock-master = <&sndcodec>;
+               simple-audio-card,frame-master = <&sndcodec>;
+
+               sndcpu: simple-audio-card,cpu {
+                       sound-dai = <&rcar_sound>;
+               };
+
+               sndcodec: simple-audio-card,codec {
+                       sound-dai = <&ak4643>;
+                       system-clock-frequency = <11289600>;
+               };
+       };
+};
+
+&bsc {
+       ethernet@18300000 {
+               compatible = "smsc,lan9220", "smsc,lan9115";
+               reg = <0x18300000 0x1000>;
+
+               phy-mode = "mii";
+               interrupt-parent = <&irqpin>;
+               interrupts = <0 IRQ_TYPE_EDGE_FALLING>;
+               reg-io-width = <4>;
+               vddvario-supply = <&fixedregulator3v3>;
+               vdd33a-supply = <&fixedregulator3v3>;
+       };
+};
+
+&extal_clk {
+       clock-frequency = <33333333>;
+};
+
+&i2c0 {
+       status = "okay";
+
+       ak4643: sound-codec@12 {
+               compatible = "asahi-kasei,ak4643";
+               #sound-dai-cells = <0>;
+               reg = <0x12>;
+       };
+
+       camera@41 {
+               compatible = "oki,ml86v7667";
+               reg = <0x41>;
+       };
+
+       camera@43 {
+               compatible = "oki,ml86v7667";
+               reg = <0x43>;
+       };
+
+       rx8581: rtc@51 {
+               compatible = "epson,rx8581";
+               reg = <0x51>;
+       };
+};
+
+&mmcif {
+       pinctrl-0 = <&mmc_pins>;
+       pinctrl-names = "default";
+
+       vmmc-supply = <&fixedregulator3v3>;
+       bus-width = <8>;
+       broken-cd;
+       status = "okay";
+};
+
+&irqpin {
+       status = "okay";
+};
+
+&tmu0 {
+       status = "okay";
+};
+
+&pfc {
+       scif0_pins: serial0 {
+               renesas,groups = "scif0_data_a", "scif0_ctrl";
+               renesas,function = "scif0";
+       };
+
+       mmc_pins: mmc {
+               renesas,groups = "mmc_data8", "mmc_ctrl";
+               renesas,function = "mmc";
+       };
+
+       sdhi0_pins: sd0 {
+               renesas,groups = "sdhi0_data4", "sdhi0_ctrl",
+                                 "sdhi0_cd";
+               renesas,function = "sdhi0";
+       };
+
+       hspi0_pins: hspi0 {
+               renesas,groups = "hspi0_a";
+               renesas,function = "hspi0";
+       };
+
+       usb0_pins: usb0 {
+               renesas,groups = "usb0";
+               renesas,function = "usb0";
+       };
+
+       usb1_pins: usb1 {
+               renesas,groups = "usb1";
+               renesas,function = "usb1";
+       };
+
+       vin0_pins: vin0 {
+               renesas,groups = "vin0_data8", "vin0_clk";
+               renesas,function = "vin0";
+       };
+
+       vin1_pins: vin1 {
+               renesas,groups = "vin1_data8", "vin1_clk";
+               renesas,function = "vin1";
+       };
+};
+
+&sdhi0 {
+       pinctrl-0 = <&sdhi0_pins>;
+       pinctrl-names = "default";
+
+       vmmc-supply = <&fixedregulator3v3>;
+       bus-width = <4>;
+       status = "okay";
+       wp-gpios = <&gpio3 18 GPIO_ACTIVE_HIGH>;
+};
+
+&hspi0 {
+       pinctrl-0 = <&hspi0_pins>;
+       pinctrl-names = "default";
+       status = "okay";
+
+       flash: flash@0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "spansion,s25fl008k";
+               reg = <0>;
+               spi-max-frequency = <104000000>;
+               m25p,fast-read;
+
+               partition@0 {
+                       label = "data(spi)";
+                       reg = <0x00000000 0x00100000>;
+               };
+       };
+};
+
+&scif0 {
+       pinctrl-0 = <&scif0_pins>;
+       pinctrl-names = "default";
+
+       status = "okay";
 };
index ef8533910029620e5cb974bdafece1c2f90a3e1d..868f9730953350e9bb8b368b7b71efb5a85e7144 100644 (file)
@@ -16,6 +16,7 @@
 
 /include/ "skeleton.dtsi"
 
+#include <dt-bindings/clock/r8a7778-clock.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 
 / {
                spi2 = &hspi2;
        };
 
+       bsc: bus@1c000000 {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0 0 0x1c000000>;
+       };
+
+       ether: ethernet@fde00000 {
+               compatible = "renesas,ether-r8a7778";
+               reg = <0xfde00000 0x400>;
+               interrupts = <0 105 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp1_clks R8A7778_CLK_ETHER>;
+               phy-mode = "rmii";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               status = "disabled";
+       };
+
        gic: interrupt-controller@fe438000 {
                compatible = "arm,cortex-a9-gic";
                #interrupt-cells = <3>;
                compatible = "renesas,i2c-r8a7778";
                reg = <0xffc70000 0x1000>;
                interrupts = <0 67 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp0_clks R8A7778_CLK_I2C0>;
                status = "disabled";
        };
 
                compatible = "renesas,i2c-r8a7778";
                reg = <0xffc71000 0x1000>;
                interrupts = <0 78 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp0_clks R8A7778_CLK_I2C1>;
                status = "disabled";
        };
 
                compatible = "renesas,i2c-r8a7778";
                reg = <0xffc72000 0x1000>;
                interrupts = <0 76 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp0_clks R8A7778_CLK_I2C2>;
                status = "disabled";
        };
 
                compatible = "renesas,i2c-r8a7778";
                reg = <0xffc73000 0x1000>;
                interrupts = <0 77 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp0_clks R8A7778_CLK_I2C3>;
                status = "disabled";
        };
 
                interrupts = <0 32 IRQ_TYPE_LEVEL_HIGH>,
                             <0 33 IRQ_TYPE_LEVEL_HIGH>,
                             <0 34 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp0_clks R8A7778_CLK_TMU0>;
+               clock-names = "fck";
 
                #renesas,channels = <3>;
 
                interrupts = <0 36 IRQ_TYPE_LEVEL_HIGH>,
                             <0 37 IRQ_TYPE_LEVEL_HIGH>,
                             <0 38 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp0_clks R8A7778_CLK_TMU1>;
+               clock-names = "fck";
 
                #renesas,channels = <3>;
 
                interrupts = <0 40 IRQ_TYPE_LEVEL_HIGH>,
                             <0 41 IRQ_TYPE_LEVEL_HIGH>,
                             <0 42 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp0_clks R8A7778_CLK_TMU2>;
+               clock-names = "fck";
 
                #renesas,channels = <3>;
 
                status = "disabled";
        };
 
+       rcar_sound: sound@ffd90000 {
+               #sound-dai-cells = <1>;
+               compatible = "renesas,rcar_sound-r8a7778", "renesas,rcar_sound-gen1";
+               reg =   <0xffd90000 0x1000>,    /* SRU */
+                       <0xffd91000 0x1240>,    /* SSI */
+                       <0xfffe0000 0x24>;      /* ADG */
+               clocks = <&mstp3_clks R8A7778_CLK_SSI8>,
+                       <&mstp3_clks R8A7778_CLK_SSI7>,
+                       <&mstp3_clks R8A7778_CLK_SSI6>,
+                       <&mstp3_clks R8A7778_CLK_SSI5>,
+                       <&mstp3_clks R8A7778_CLK_SSI4>,
+                       <&mstp0_clks R8A7778_CLK_SSI3>,
+                       <&mstp0_clks R8A7778_CLK_SSI2>,
+                       <&mstp0_clks R8A7778_CLK_SSI1>,
+                       <&mstp0_clks R8A7778_CLK_SSI0>,
+                       <&mstp5_clks R8A7778_CLK_SRU_SRC8>,
+                       <&mstp5_clks R8A7778_CLK_SRU_SRC7>,
+                       <&mstp5_clks R8A7778_CLK_SRU_SRC6>,
+                       <&mstp5_clks R8A7778_CLK_SRU_SRC5>,
+                       <&mstp5_clks R8A7778_CLK_SRU_SRC4>,
+                       <&mstp5_clks R8A7778_CLK_SRU_SRC3>,
+                       <&mstp5_clks R8A7778_CLK_SRU_SRC2>,
+                       <&mstp5_clks R8A7778_CLK_SRU_SRC1>,
+                       <&mstp5_clks R8A7778_CLK_SRU_SRC0>,
+                       <&audio_clk_a>, <&audio_clk_b>, <&audio_clk_c>,
+                       <&cpg_clocks R8A7778_CLK_S1>;
+               clock-names = "ssi.8", "ssi.7", "ssi.6", "ssi.5", "ssi.4",
+                       "ssi.3", "ssi.2", "ssi.1", "ssi.0",
+                       "src.8", "src.7", "src.6", "src.5", "src.4",
+                       "src.3", "src.2", "src.1", "src.0",
+                       "clk_a", "clk_b", "clk_c", "clk_i";
+
+               status = "disabled";
+
+               rcar_sound,src {
+                       src3: src@3 { };
+                       src4: src@4 { };
+                       src5: src@5 { };
+                       src6: src@6 { };
+                       src7: src@7 { };
+                       src8: src@8 { };
+                       src9: src@9 { };
+               };
+
+               rcar_sound,ssi {
+                       ssi3: ssi@3 { interrupts = <0 0x85 IRQ_TYPE_LEVEL_HIGH>; };
+                       ssi4: ssi@4 { interrupts = <0 0x85 IRQ_TYPE_LEVEL_HIGH>; };
+                       ssi5: ssi@5 { interrupts = <0 0x86 IRQ_TYPE_LEVEL_HIGH>; };
+                       ssi6: ssi@6 { interrupts = <0 0x86 IRQ_TYPE_LEVEL_HIGH>; };
+                       ssi7: ssi@7 { interrupts = <0 0x86 IRQ_TYPE_LEVEL_HIGH>; };
+                       ssi8: ssi@8 { interrupts = <0 0x86 IRQ_TYPE_LEVEL_HIGH>; };
+                       ssi9: ssi@9 { interrupts = <0 0x86 IRQ_TYPE_LEVEL_HIGH>; };
+               };
+       };
+
        scif0: serial@ffe40000 {
                compatible = "renesas,scif-r8a7778", "renesas,scif";
                reg = <0xffe40000 0x100>;
                interrupts = <0 70 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp0_clks R8A7778_CLK_SCIF0>;
+               clock-names = "sci_ick";
                status = "disabled";
        };
 
                compatible = "renesas,scif-r8a7778", "renesas,scif";
                reg = <0xffe41000 0x100>;
                interrupts = <0 71 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp0_clks R8A7778_CLK_SCIF1>;
+               clock-names = "sci_ick";
                status = "disabled";
        };
 
                compatible = "renesas,scif-r8a7778", "renesas,scif";
                reg = <0xffe42000 0x100>;
                interrupts = <0 72 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp0_clks R8A7778_CLK_SCIF2>;
+               clock-names = "sci_ick";
                status = "disabled";
        };
 
                compatible = "renesas,scif-r8a7778", "renesas,scif";
                reg = <0xffe43000 0x100>;
                interrupts = <0 73 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp0_clks R8A7778_CLK_SCIF3>;
+               clock-names = "sci_ick";
                status = "disabled";
        };
 
                compatible = "renesas,scif-r8a7778", "renesas,scif";
                reg = <0xffe44000 0x100>;
                interrupts = <0 74 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp0_clks R8A7778_CLK_SCIF4>;
+               clock-names = "sci_ick";
                status = "disabled";
        };
 
                compatible = "renesas,scif-r8a7778", "renesas,scif";
                reg = <0xffe45000 0x100>;
                interrupts = <0 75 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp0_clks R8A7778_CLK_SCIF5>;
+               clock-names = "sci_ick";
                status = "disabled";
        };
 
                compatible = "renesas,sh-mmcif";
                reg = <0xffe4e000 0x100>;
                interrupts = <0 61 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp3_clks R8A7778_CLK_MMC>;
                status = "disabled";
        };
 
                compatible = "renesas,sdhi-r8a7778";
                reg = <0xffe4c000 0x100>;
                interrupts = <0 87 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp3_clks R8A7778_CLK_SDHI0>;
                status = "disabled";
        };
 
                compatible = "renesas,sdhi-r8a7778";
                reg = <0xffe4d000 0x100>;
                interrupts = <0 88 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp3_clks R8A7778_CLK_SDHI1>;
                status = "disabled";
        };
 
                compatible = "renesas,sdhi-r8a7778";
                reg = <0xffe4f000 0x100>;
                interrupts = <0 86 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp3_clks R8A7778_CLK_SDHI2>;
                status = "disabled";
        };
 
                compatible = "renesas,hspi-r8a7778", "renesas,hspi";
                reg = <0xfffc7000 0x18>;
                interrupts = <0 63 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp0_clks R8A7778_CLK_HSPI>;
                #address-cells = <1>;
                #size-cells = <0>;
                status = "disabled";
                compatible = "renesas,hspi-r8a7778", "renesas,hspi";
                reg = <0xfffc8000 0x18>;
                interrupts = <0 84 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp0_clks R8A7778_CLK_HSPI>;
                #address-cells = <1>;
                #size-cells = <0>;
                status = "disabled";
                compatible = "renesas,hspi-r8a7778", "renesas,hspi";
                reg = <0xfffc6000 0x18>;
                interrupts = <0 85 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp0_clks R8A7778_CLK_HSPI>;
                #address-cells = <1>;
                #size-cells = <0>;
                status = "disabled";
        };
+
+       clocks {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               /* External input clock */
+               extal_clk: extal_clk {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <0>;
+                       clock-output-names = "extal";
+               };
+
+               /* Special CPG clocks */
+               cpg_clocks: cpg_clocks@ffc80000 {
+                       compatible = "renesas,r8a7778-cpg-clocks";
+                       reg = <0xffc80000 0x80>;
+                       #clock-cells = <1>;
+                       clocks = <&extal_clk>;
+                       clock-output-names = "plla", "pllb", "b",
+                                            "out", "p", "s", "s1";
+               };
+
+               /* Audio clocks; frequencies are set by boards if applicable. */
+               audio_clk_a: audio_clk_a {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-output-names = "audio_clk_a";
+               };
+               audio_clk_b: audio_clk_b {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-output-names = "audio_clk_b";
+               };
+               audio_clk_c: audio_clk_c {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-output-names = "audio_clk_c";
+               };
+
+               /* Fixed ratio clocks */
+               g_clk: g_clk {
+                       compatible = "fixed-factor-clock";
+                       clocks = <&cpg_clocks R8A7778_CLK_PLLA>;
+                       #clock-cells = <0>;
+                       clock-div = <12>;
+                       clock-mult = <1>;
+                       clock-output-names = "g";
+               };
+               i_clk: i_clk {
+                       compatible = "fixed-factor-clock";
+                       clocks = <&cpg_clocks R8A7778_CLK_PLLA>;
+                       #clock-cells = <0>;
+                       clock-div = <1>;
+                       clock-mult = <1>;
+                       clock-output-names = "i";
+               };
+               s3_clk: s3_clk {
+                       compatible = "fixed-factor-clock";
+                       clocks = <&cpg_clocks R8A7778_CLK_PLLA>;
+                       #clock-cells = <0>;
+                       clock-div = <4>;
+                       clock-mult = <1>;
+                       clock-output-names = "s3";
+               };
+               s4_clk: s4_clk {
+                       compatible = "fixed-factor-clock";
+                       clocks = <&cpg_clocks R8A7778_CLK_PLLA>;
+                       #clock-cells = <0>;
+                       clock-div = <8>;
+                       clock-mult = <1>;
+                       clock-output-names = "s4";
+               };
+               z_clk: z_clk {
+                       compatible = "fixed-factor-clock";
+                       clocks = <&cpg_clocks R8A7778_CLK_PLLB>;
+                       #clock-cells = <0>;
+                       clock-div = <1>;
+                       clock-mult = <1>;
+                       clock-output-names = "z";
+               };
+
+               /* Gate clocks */
+               mstp0_clks: mstp0_clks@ffc80030 {
+                       compatible = "renesas,r8a7778-mstp-clocks", "renesas,cpg-mstp-clocks";
+                       reg = <0xffc80030 4>;
+                       clocks = <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_S>;
+                       #clock-cells = <1>;
+                       clock-indices = <
+                               R8A7778_CLK_I2C0 R8A7778_CLK_I2C1
+                               R8A7778_CLK_I2C2 R8A7778_CLK_I2C3
+                               R8A7778_CLK_SCIF0 R8A7778_CLK_SCIF1
+                               R8A7778_CLK_SCIF2 R8A7778_CLK_SCIF3
+                               R8A7778_CLK_SCIF4 R8A7778_CLK_SCIF5
+                               R8A7778_CLK_TMU0 R8A7778_CLK_TMU1
+                               R8A7778_CLK_TMU2 R8A7778_CLK_SSI0
+                               R8A7778_CLK_SSI1 R8A7778_CLK_SSI2
+                               R8A7778_CLK_SSI3 R8A7778_CLK_SRU
+                               R8A7778_CLK_HSPI
+                       >;
+                       clock-output-names =
+                               "i2c0", "i2c1", "i2c2", "i2c3", "scif0",
+                               "scif1", "scif2", "scif3", "scif4", "scif5",
+                               "tmu0", "tmu1", "tmu2", "ssi0", "ssi1",
+                               "ssi2", "ssi3", "sru", "hspi";
+               };
+               mstp1_clks: mstp1_clks@ffc80034 {
+                       compatible = "renesas,r8a7778-mstp-clocks", "renesas,cpg-mstp-clocks";
+                       reg = <0xffc80034 4>, <0xffc80044 4>;
+                       clocks = <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_S>,
+                                <&cpg_clocks R8A7778_CLK_S>,
+                                <&cpg_clocks R8A7778_CLK_P>;
+                       #clock-cells = <1>;
+                       clock-indices = <
+                               R8A7778_CLK_ETHER R8A7778_CLK_VIN0
+                               R8A7778_CLK_VIN1 R8A7778_CLK_USB
+                       >;
+                       clock-output-names =
+                               "ether", "vin0", "vin1", "usb";
+               };
+               mstp3_clks: mstp3_clks@ffc8003c {
+                       compatible = "renesas,r8a7778-mstp-clocks", "renesas,cpg-mstp-clocks";
+                       reg = <0xffc8003c 4>;
+                       clocks = <&s4_clk>,
+                                <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>;
+                       #clock-cells = <1>;
+                       clock-indices = <
+                               R8A7778_CLK_MMC R8A7778_CLK_SDHI0
+                               R8A7778_CLK_SDHI1 R8A7778_CLK_SDHI2
+                               R8A7778_CLK_SSI4 R8A7778_CLK_SSI5
+                               R8A7778_CLK_SSI6 R8A7778_CLK_SSI7
+                               R8A7778_CLK_SSI8
+                       >;
+                       clock-output-names =
+                               "mmc", "sdhi0", "sdhi1", "sdhi2", "ssi4",
+                               "ssi5", "ssi6", "ssi7", "ssi8";
+               };
+               mstp5_clks: mstp5_clks@ffc80054 {
+                       compatible = "renesas,r8a7778-mstp-clocks", "renesas,cpg-mstp-clocks";
+                       reg = <0xffc80054 4>;
+                       clocks = <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>,
+                                <&cpg_clocks R8A7778_CLK_P>;
+                       #clock-cells = <1>;
+                       clock-indices = <
+                               R8A7778_CLK_SRU_SRC0 R8A7778_CLK_SRU_SRC1
+                               R8A7778_CLK_SRU_SRC2 R8A7778_CLK_SRU_SRC3
+                               R8A7778_CLK_SRU_SRC4 R8A7778_CLK_SRU_SRC5
+                               R8A7778_CLK_SRU_SRC6 R8A7778_CLK_SRU_SRC7
+                               R8A7778_CLK_SRU_SRC8
+                       >;
+                       clock-output-names =
+                               "sru-src0", "sru-src1", "sru-src2",
+                               "sru-src3", "sru-src4", "sru-src5",
+                               "sru-src6", "sru-src7", "sru-src8";
+               };
+       };
 };
index e83d40e24bcd48113d6bd1051f44413710af8b59..540756cdf3914a2af398d08734a48aa5b93ea21b 100644 (file)
                        };
                };
        };
+
+       x3_clk: x3-clock {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <65000000>;
+       };
 };
 
 &du {
        pinctrl-names = "default";
        status = "okay";
 
+       clocks = <&mstp1_clks R8A7779_CLK_DU>, <&x3_clk>;
+       clock-names = "du", "dclkin.0";
+
        ports {
                port@0 {
                        endpoint {
index 0c3b6783b72add5d05001c35f39d1da6e55f141b..aaa4f258e279ccfac92ff1142faf4fe83ce3195d 100644 (file)
                        };
                };
        };
+
+       hdmi-out {
+               compatible = "hdmi-connector";
+               type = "a";
+
+               port {
+                       hdmi_con: endpoint {
+                               remote-endpoint = <&adv7511_out>;
+                       };
+               };
+       };
+
+       x2_clk: x2-clock {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <148500000>;
+       };
+
+       x13_clk: x13-clock {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <148500000>;
+       };
 };
 
 &du {
        pinctrl-names = "default";
        status = "okay";
 
+       clocks = <&mstp7_clks R8A7790_CLK_DU0>,
+                <&mstp7_clks R8A7790_CLK_DU1>,
+                <&mstp7_clks R8A7790_CLK_DU2>,
+                <&mstp7_clks R8A7790_CLK_LVDS0>,
+                <&mstp7_clks R8A7790_CLK_LVDS1>,
+                <&x13_clk>, <&x2_clk>;
+       clock-names = "du.0", "du.1", "du.2", "lvds.0", "lvds.1",
+                     "dclkin.0", "dclkin.1";
+
        ports {
                port@0 {
                        endpoint {
                                remote-endpoint = <&adv7123_in>;
                        };
                };
+               port@1 {
+                       endpoint {
+                               remote-endpoint = <&adv7511_in>;
+                       };
+               };
                port@2 {
                        lvds_connector: endpoint {
                        };
                        };
                };
        };
+
+       hdmi@39 {
+               compatible = "adi,adv7511w";
+               reg = <0x39>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <15 IRQ_TYPE_EDGE_FALLING>;
+
+               adi,input-depth = <8>;
+               adi,input-colorspace = "rgb";
+               adi,input-clock = "1x";
+               adi,input-style = <1>;
+               adi,input-justification = "evenly";
+
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@0 {
+                               reg = <0>;
+                               adv7511_in: endpoint {
+                                       remote-endpoint = <&du_out_lvds0>;
+                               };
+                       };
+
+                       port@1 {
+                               reg = <1>;
+                               adv7511_out: endpoint {
+                                       remote-endpoint = <&hdmi_con>;
+                               };
+                       };
+               };
+       };
 };
 
 &iic3 {
        pinctrl-0 = <&iic3_pins>;
        status = "okay";
 
+       pmic@58 {
+               compatible = "dlg,da9063";
+               reg = <0x58>;
+               interrupt-parent = <&irqc0>;
+               interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+               interrupt-controller;
+
+               rtc {
+                       compatible = "dlg,da9063-rtc";
+               };
+
+               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>;
index 4b38fc92011472e0684107cce5283eb7b1b3a937..4bb2f4c17321bd55f97050cb59c1690e45f24cf5 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * 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.
  *
                dma-channels = <13>;
        };
 
-       audmapp: dma-controller@ec740000 {
-               compatible = "renesas,rcar-audmapp";
-               #dma-cells = <1>;
-
-               reg = <0 0xec740000 0 0x200>;
-       };
-
        i2c0: i2c@e6508000 {
                #address-cells = <1>;
                #size-cells = <0>;
 
        sdhi0: sd@ee100000 {
                compatible = "renesas,sdhi-r8a7790";
-               reg = <0 0xee100000 0 0x200>;
+               reg = <0 0xee100000 0 0x328>;
                interrupts = <0 165 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp3_clks R8A7790_CLK_SDHI0>;
+               dmas = <&dmac1 0xcd>, <&dmac1 0xce>;
+               dma-names = "tx", "rx";
                status = "disabled";
        };
 
        sdhi1: sd@ee120000 {
                compatible = "renesas,sdhi-r8a7790";
-               reg = <0 0xee120000 0 0x200>;
+               reg = <0 0xee120000 0 0x328>;
                interrupts = <0 166 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp3_clks R8A7790_CLK_SDHI1>;
+               dmas = <&dmac1 0xc9>, <&dmac1 0xca>;
+               dma-names = "tx", "rx";
                status = "disabled";
        };
 
                reg = <0 0xee140000 0 0x100>;
                interrupts = <0 167 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp3_clks R8A7790_CLK_SDHI2>;
+               dmas = <&dmac1 0xc1>, <&dmac1 0xc2>;
+               dma-names = "tx", "rx";
                status = "disabled";
        };
 
                reg = <0 0xee160000 0 0x100>;
                interrupts = <0 168 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp3_clks R8A7790_CLK_SDHI3>;
+               dmas = <&dmac1 0xd3>, <&dmac1 0xd4>;
+               dma-names = "tx", "rx";
                status = "disabled";
        };
 
                };
        };
 
+       can0: can@e6e80000 {
+               compatible = "renesas,can-r8a7790";
+               reg = <0 0xe6e80000 0 0x1000>;
+               interrupts = <0 186 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp9_clks R8A7790_CLK_RCAN0>,
+                        <&cpg_clocks R8A7790_CLK_RCAN>, <&can_clk>;
+               clock-names = "clkp1", "clkp2", "can_clk";
+               status = "disabled";
+       };
+
+       can1: can@e6e88000 {
+               compatible = "renesas,can-r8a7790";
+               reg = <0 0xe6e88000 0 0x1000>;
+               interrupts = <0 187 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp9_clks R8A7790_CLK_RCAN1>,
+                        <&cpg_clocks R8A7790_CLK_RCAN>, <&can_clk>;
+               clock-names = "clkp1", "clkp2", "can_clk";
+               status = "disabled";
+       };
+
        clocks {
                #address-cells = <2>;
                #size-cells = <2>;
                        clock-output-names = "audio_clk_c";
                };
 
+               /* External USB clock - can be overridden by the board */
+               usb_extal_clk: usb_extal_clk {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <48000000>;
+                       clock-output-names = "usb_extal";
+               };
+
+               /* External CAN clock */
+               can_clk: can_clk {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       /* This value must be overridden by the board. */
+                       clock-frequency = <0>;
+                       clock-output-names = "can_clk";
+                       status = "disabled";
+               };
+
                /* Special CPG clocks */
                cpg_clocks: cpg_clocks@e6150000 {
                        compatible = "renesas,r8a7790-cpg-clocks",
                                     "renesas,rcar-gen2-cpg-clocks";
                        reg = <0 0xe6150000 0 0x1000>;
-                       clocks = <&extal_clk>;
+                       clocks = <&extal_clk &usb_extal_clk>;
                        #clock-cells = <1>;
                        clock-output-names = "main", "pll0", "pll1", "pll3",
                                             "lb", "qspi", "sdh", "sd0", "sd1",
-                                            "z";
+                                            "z", "rcan", "adsp";
                };
 
                /* Variable factor clocks */
                mstp5_clks: mstp5_clks@e6150144 {
                        compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks";
                        reg = <0 0xe6150144 0 4>, <0 0xe615003c 0 4>;
-                       clocks = <&hp_clk>, <&hp_clk>, <&extal_clk>, <&p_clk>;
+                       clocks = <&hp_clk>, <&hp_clk>, <&cpg_clocks R8A7790_CLK_ADSP>,
+                                <&extal_clk>, <&p_clk>;
                        #clock-cells = <1>;
                        clock-indices = <
                                R8A7790_CLK_AUDIO_DMAC0 R8A7790_CLK_AUDIO_DMAC1
-                               R8A7790_CLK_THERMAL R8A7790_CLK_PWM
+                               R8A7790_CLK_ADSP_MOD R8A7790_CLK_THERMAL
+                               R8A7790_CLK_PWM
                        >;
-                       clock-output-names = "audmac0", "audmac1", "thermal", "pwm";
+                       clock-output-names = "audmac0", "audmac1", "adsp_mod",
+                                            "thermal", "pwm";
                };
                mstp7_clks: mstp7_clks@e615014c {
                        compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks";
                        reg = <0 0xe615014c 0 4>, <0 0xe61501c4 0 4>;
-                       clocks = <&mp_clk>, <&mp_clk>, <&zs_clk>, <&zs_clk>, <&p_clk>,
+                       clocks = <&mp_clk>, <&hp_clk>, <&zs_clk>, <&zs_clk>, <&p_clk>,
                                 <&p_clk>, <&zx_clk>, <&zx_clk>, <&zx_clk>, <&zx_clk>,
                                 <&zx_clk>;
                        #clock-cells = <1>;
                reg =   <0 0xec500000 0 0x1000>, /* SCU */
                        <0 0xec5a0000 0 0x100>,  /* ADG */
                        <0 0xec540000 0 0x1000>, /* SSIU */
-                       <0 0xec541000 0 0x1280>; /* SSI */
+                       <0 0xec541000 0 0x1280>, /* SSI */
+                       <0 0xec740000 0 0x200>;  /* Audio DMAC peri peri*/
+               reg-names = "scu", "adg", "ssiu", "ssi", "audmapp";
+
                clocks = <&mstp10_clks R8A7790_CLK_SSI_ALL>,
                        <&mstp10_clks R8A7790_CLK_SSI9>, <&mstp10_clks R8A7790_CLK_SSI8>,
                        <&mstp10_clks R8A7790_CLK_SSI7>, <&mstp10_clks R8A7790_CLK_SSI6>,
                status = "disabled";
 
                rcar_sound,dvc {
-                       dvc0: dvc@0 { };
-                       dvc1: dvc@1 { };
+                       dvc0: dvc@0 {
+                               dmas = <&audma0 0xbc>;
+                               dma-names = "tx";
+                       };
+                       dvc1: dvc@1 {
+                               dmas = <&audma0 0xbe>;
+                               dma-names = "tx";
+                       };
                };
 
                rcar_sound,src {
-                       src0: src@0 { interrupts = <0 352 IRQ_TYPE_LEVEL_HIGH>; };
-                       src1: src@1 { interrupts = <0 353 IRQ_TYPE_LEVEL_HIGH>; };
-                       src2: src@2 { interrupts = <0 354 IRQ_TYPE_LEVEL_HIGH>; };
-                       src3: src@3 { interrupts = <0 355 IRQ_TYPE_LEVEL_HIGH>; };
-                       src4: src@4 { interrupts = <0 356 IRQ_TYPE_LEVEL_HIGH>; };
-                       src5: src@5 { interrupts = <0 357 IRQ_TYPE_LEVEL_HIGH>; };
-                       src6: src@6 { interrupts = <0 358 IRQ_TYPE_LEVEL_HIGH>; };
-                       src7: src@7 { interrupts = <0 359 IRQ_TYPE_LEVEL_HIGH>; };
-                       src8: src@8 { interrupts = <0 360 IRQ_TYPE_LEVEL_HIGH>; };
-                       src9: src@9 { interrupts = <0 361 IRQ_TYPE_LEVEL_HIGH>; };
+                       src0: src@0 {
+                               interrupts = <0 352 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x85>, <&audma1 0x9a>;
+                               dma-names = "rx", "tx";
+                       };
+                       src1: src@1 {
+                               interrupts = <0 353 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x87>, <&audma1 0x9c>;
+                               dma-names = "rx", "tx";
+                       };
+                       src2: src@2 {
+                               interrupts = <0 354 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x89>, <&audma1 0x9e>;
+                               dma-names = "rx", "tx";
+                       };
+                       src3: src@3 {
+                               interrupts = <0 355 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x8b>, <&audma1 0xa0>;
+                               dma-names = "rx", "tx";
+                       };
+                       src4: src@4 {
+                               interrupts = <0 356 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x8d>, <&audma1 0xb0>;
+                               dma-names = "rx", "tx";
+                       };
+                       src5: src@5 {
+                               interrupts = <0 357 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x8f>, <&audma1 0xb2>;
+                               dma-names = "rx", "tx";
+                       };
+                       src6: src@6 {
+                               interrupts = <0 358 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x91>, <&audma1 0xb4>;
+                               dma-names = "rx", "tx";
+                       };
+                       src7: src@7 {
+                               interrupts = <0 359 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x93>, <&audma1 0xb6>;
+                               dma-names = "rx", "tx";
+                       };
+                       src8: src@8 {
+                               interrupts = <0 360 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x95>, <&audma1 0xb8>;
+                               dma-names = "rx", "tx";
+                       };
+                       src9: src@9 {
+                               interrupts = <0 361 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x97>, <&audma1 0xba>;
+                               dma-names = "rx", "tx";
+                       };
                };
 
                rcar_sound,ssi {
-                       ssi0: ssi@0 { interrupts = <0 370 IRQ_TYPE_LEVEL_HIGH>; };
-                       ssi1: ssi@1 { interrupts = <0 371 IRQ_TYPE_LEVEL_HIGH>; };
-                       ssi2: ssi@2 { interrupts = <0 372 IRQ_TYPE_LEVEL_HIGH>; };
-                       ssi3: ssi@3 { interrupts = <0 373 IRQ_TYPE_LEVEL_HIGH>; };
-                       ssi4: ssi@4 { interrupts = <0 374 IRQ_TYPE_LEVEL_HIGH>; };
-                       ssi5: ssi@5 { interrupts = <0 375 IRQ_TYPE_LEVEL_HIGH>; };
-                       ssi6: ssi@6 { interrupts = <0 376 IRQ_TYPE_LEVEL_HIGH>; };
-                       ssi7: ssi@7 { interrupts = <0 377 IRQ_TYPE_LEVEL_HIGH>; };
-                       ssi8: ssi@8 { interrupts = <0 378 IRQ_TYPE_LEVEL_HIGH>; };
-                       ssi9: ssi@9 { interrupts = <0 379 IRQ_TYPE_LEVEL_HIGH>; };
+                       ssi0: ssi@0 {
+                               interrupts = <0 370 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x01>, <&audma1 0x02>, <&audma0 0x15>, <&audma1 0x16>;
+                               dma-names = "rx", "tx", "rxu", "txu";
+                       };
+                       ssi1: ssi@1 {
+                                interrupts = <0 371 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x03>, <&audma1 0x04>, <&audma0 0x49>, <&audma1 0x4a>;
+                               dma-names = "rx", "tx", "rxu", "txu";
+                       };
+                       ssi2: ssi@2 {
+                               interrupts = <0 372 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x05>, <&audma1 0x06>, <&audma0 0x63>, <&audma1 0x64>;
+                               dma-names = "rx", "tx", "rxu", "txu";
+                       };
+                       ssi3: ssi@3 {
+                               interrupts = <0 373 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x07>, <&audma1 0x08>, <&audma0 0x6f>, <&audma1 0x70>;
+                               dma-names = "rx", "tx", "rxu", "txu";
+                       };
+                       ssi4: ssi@4 {
+                               interrupts = <0 374 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x09>, <&audma1 0x0a>, <&audma0 0x71>, <&audma1 0x72>;
+                               dma-names = "rx", "tx", "rxu", "txu";
+                       };
+                       ssi5: ssi@5 {
+                               interrupts = <0 375 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x0b>, <&audma1 0x0c>, <&audma0 0x73>, <&audma1 0x74>;
+                               dma-names = "rx", "tx", "rxu", "txu";
+                       };
+                       ssi6: ssi@6 {
+                               interrupts = <0 376 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x0d>, <&audma1 0x0e>, <&audma0 0x75>, <&audma1 0x76>;
+                               dma-names = "rx", "tx", "rxu", "txu";
+                       };
+                       ssi7: ssi@7 {
+                               interrupts = <0 377 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x0f>, <&audma1 0x10>, <&audma0 0x79>, <&audma1 0x7a>;
+                               dma-names = "rx", "tx", "rxu", "txu";
+                       };
+                       ssi8: ssi@8 {
+                               interrupts = <0 378 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x11>, <&audma1 0x12>, <&audma0 0x7b>, <&audma1 0x7c>;
+                               dma-names = "rx", "tx", "rxu", "txu";
+                       };
+                       ssi9: ssi@9 {
+                               interrupts = <0 379 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x13>, <&audma1 0x14>, <&audma0 0x7d>, <&audma1 0x7e>;
+                               dma-names = "rx", "tx", "rxu", "txu";
+                       };
                };
        };
+
+       ipmmu_sy0: mmu@e6280000 {
+               compatible = "renesas,ipmmu-vmsa";
+               reg = <0 0xe6280000 0 0x1000>;
+               interrupts = <0 223 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 224 IRQ_TYPE_LEVEL_HIGH>;
+               #iommu-cells = <1>;
+               status = "disabled";
+       };
+
+       ipmmu_sy1: mmu@e6290000 {
+               compatible = "renesas,ipmmu-vmsa";
+               reg = <0 0xe6290000 0 0x1000>;
+               interrupts = <0 225 IRQ_TYPE_LEVEL_HIGH>;
+               #iommu-cells = <1>;
+               status = "disabled";
+       };
+
+       ipmmu_ds: mmu@e6740000 {
+               compatible = "renesas,ipmmu-vmsa";
+               reg = <0 0xe6740000 0 0x1000>;
+               interrupts = <0 198 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 199 IRQ_TYPE_LEVEL_HIGH>;
+               #iommu-cells = <1>;
+               status = "disabled";
+       };
+
+       ipmmu_mp: mmu@ec680000 {
+               compatible = "renesas,ipmmu-vmsa";
+               reg = <0 0xec680000 0 0x1000>;
+               interrupts = <0 226 IRQ_TYPE_LEVEL_HIGH>;
+               #iommu-cells = <1>;
+               status = "disabled";
+       };
+
+       ipmmu_mx: mmu@fe951000 {
+               compatible = "renesas,ipmmu-vmsa";
+               reg = <0 0xfe951000 0 0x1000>;
+               interrupts = <0 222 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 221 IRQ_TYPE_LEVEL_HIGH>;
+               #iommu-cells = <1>;
+               status = "disabled";
+       };
+
+       ipmmu_rt: mmu@ffc80000 {
+               compatible = "renesas,ipmmu-vmsa";
+               reg = <0 0xffc80000 0 0x1000>;
+               interrupts = <0 307 IRQ_TYPE_LEVEL_HIGH>;
+               #iommu-cells = <1>;
+               status = "disabled";
+       };
 };
index d2ebf11f98814ab59c7d0a6d8987bd7c21e360a0..e33e4047b0b0c9207494e8cb3e30e4f2ac7bc6ee 100644 (file)
                renesas,groups = "vin0_data8", "vin0_clk";
                renesas,function = "vin0";
        };
+
+       can0_pins: can0 {
+               renesas,groups = "can0_data";
+               renesas,function = "can0";
+       };
 };
 
 &scif0 {
                };
        };
 };
+
+&can0 {
+       pinctrl-0 = <&can0_pins>;
+       pinctrl-names = "default";
+       status = "okay";
+};
index a3c27807f6c516e8c28b75642cb2df3c1a259e5e..74c3212f1f11e47e8319ab67a252853400b2c910 100644 (file)
                        system-clock-frequency = <11289600>;
                };
        };
+
+       hdmi-out {
+               compatible = "hdmi-connector";
+               type = "a";
+
+               port {
+                       hdmi_con: endpoint {
+                               remote-endpoint = <&adv7511_out>;
+                       };
+               };
+       };
+
+       x2_clk: x2-clock {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <148500000>;
+       };
+
+       x13_clk: x13-clock {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <148500000>;
+       };
 };
 
 &du {
        pinctrl-names = "default";
        status = "okay";
 
+       clocks = <&mstp7_clks R8A7791_CLK_DU0>,
+                <&mstp7_clks R8A7791_CLK_DU1>,
+                <&mstp7_clks R8A7791_CLK_LVDS0>,
+                <&x13_clk>, <&x2_clk>;
+       clock-names = "du.0", "du.1", "lvds.0",
+                     "dclkin.0", "dclkin.1";
+
        ports {
+               port@0 {
+                       endpoint {
+                               remote-endpoint = <&adv7511_in>;
+                       };
+               };
                port@1 {
                        lvds_connector: endpoint {
                        };
        };
 
        du_pins: du {
-               renesas,groups = "du_rgb666", "du_sync", "du_clk_out_0";
+               renesas,groups = "du_rgb666", "du_sync", "du_disp", "du_clk_out_0";
                renesas,function = "du";
        };
 
                };
        };
 
+       hdmi@39 {
+               compatible = "adi,adv7511w";
+               reg = <0x39>;
+               interrupt-parent = <&gpio3>;
+               interrupts = <29 IRQ_TYPE_EDGE_FALLING>;
+
+               adi,input-depth = <8>;
+               adi,input-colorspace = "rgb";
+               adi,input-clock = "1x";
+               adi,input-style = <1>;
+               adi,input-justification = "evenly";
+
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@0 {
+                               reg = <0>;
+                               adv7511_in: endpoint {
+                                       remote-endpoint = <&du_out_rgb>;
+                               };
+                       };
+
+                       port@1 {
+                               reg = <1>;
+                               adv7511_out: endpoint {
+                                       remote-endpoint = <&hdmi_con>;
+                               };
+                       };
+               };
+       };
+
        eeprom@50 {
                compatible = "renesas,24c02";
                reg = <0x50>;
        status = "okay";
        clock-frequency = <100000>;
 
+       pmic@58 {
+               compatible = "dlg,da9063";
+               reg = <0x58>;
+               interrupt-parent = <&irqc0>;
+               interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+               interrupt-controller;
+
+               rtc {
+                       compatible = "dlg,da9063-rtc";
+               };
+
+               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>;
index e35812a0d8d40e8c986c58ea71f529b54c1f5cc6..4696062f6ddeaaeb27a4260bd8932238ec461a2a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Device Tree Source for the r8a7791 SoC
  *
- * Copyright (C) 2013-2014 Renesas Electronics Corporation
+ * Copyright (C) 2013-2015 Renesas Electronics Corporation
  * Copyright (C) 2013-2014 Renesas Solutions Corp.
  * Copyright (C) 2014 Cogent Embedded Inc.
  *
                dma-channels = <13>;
        };
 
-       audmapp: dma-controller@ec740000 {
-               compatible = "renesas,rcar-audmapp";
-               #dma-cells = <1>;
-
-               reg = <0 0xec740000 0 0x200>;
-       };
-
        /* The memory map in the User's Manual maps the cores to bus numbers */
        i2c0: i2c@e6508000 {
                #address-cells = <1>;
 
        sdhi0: sd@ee100000 {
                compatible = "renesas,sdhi-r8a7791";
-               reg = <0 0xee100000 0 0x200>;
+               reg = <0 0xee100000 0 0x328>;
                interrupts = <0 165 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp3_clks R8A7791_CLK_SDHI0>;
+               dmas = <&dmac1 0xcd>, <&dmac1 0xce>;
+               dma-names = "tx", "rx";
                status = "disabled";
        };
 
                reg = <0 0xee140000 0 0x100>;
                interrupts = <0 167 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp3_clks R8A7791_CLK_SDHI1>;
+               dmas = <&dmac1 0xc1>, <&dmac1 0xc2>;
+               dma-names = "tx", "rx";
                status = "disabled";
        };
 
                reg = <0 0xee160000 0 0x100>;
                interrupts = <0 168 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp3_clks R8A7791_CLK_SDHI2>;
+               dmas = <&dmac1 0xd3>, <&dmac1 0xd4>;
+               dma-names = "tx", "rx";
                status = "disabled";
        };
 
                };
        };
 
+       can0: can@e6e80000 {
+               compatible = "renesas,can-r8a7791";
+               reg = <0 0xe6e80000 0 0x1000>;
+               interrupts = <0 186 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp9_clks R8A7791_CLK_RCAN0>,
+                        <&cpg_clocks R8A7791_CLK_RCAN>, <&can_clk>;
+               clock-names = "clkp1", "clkp2", "can_clk";
+               status = "disabled";
+       };
+
+       can1: can@e6e88000 {
+               compatible = "renesas,can-r8a7791";
+               reg = <0 0xe6e88000 0 0x1000>;
+               interrupts = <0 187 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp9_clks R8A7791_CLK_RCAN1>,
+                        <&cpg_clocks R8A7791_CLK_RCAN>, <&can_clk>;
+               clock-names = "clkp1", "clkp2", "can_clk";
+               status = "disabled";
+       };
+
        clocks {
                #address-cells = <2>;
                #size-cells = <2>;
                        status = "disabled";
                };
 
+               /* External USB clock - can be overridden by the board */
+               usb_extal_clk: usb_extal_clk {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <48000000>;
+                       clock-output-names = "usb_extal";
+               };
+
+               /* External CAN clock */
+               can_clk: can_clk {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       /* This value must be overridden by the board. */
+                       clock-frequency = <0>;
+                       clock-output-names = "can_clk";
+                       status = "disabled";
+               };
+
                /* Special CPG clocks */
                cpg_clocks: cpg_clocks@e6150000 {
                        compatible = "renesas,r8a7791-cpg-clocks",
                                     "renesas,rcar-gen2-cpg-clocks";
                        reg = <0 0xe6150000 0 0x1000>;
-                       clocks = <&extal_clk>;
+                       clocks = <&extal_clk &usb_extal_clk>;
                        #clock-cells = <1>;
                        clock-output-names = "main", "pll0", "pll1", "pll3",
-                                            "lb", "qspi", "sdh", "sd0", "z";
+                                            "lb", "qspi", "sdh", "sd0", "z",
+                                            "rcan", "adsp";
                };
 
                /* Variable factor clocks */
-               sd1_clk: sd2_clk@e6150078 {
+               sd2_clk: sd2_clk@e6150078 {
                        compatible = "renesas,r8a7791-div6-clock", "renesas,cpg-div6-clock";
                        reg = <0 0xe6150078 0 4>;
                        clocks = <&pll1_div2_clk>;
                        #clock-cells = <0>;
-                       clock-output-names = "sd1";
+                       clock-output-names = "sd2";
                };
-               sd2_clk: sd3_clk@e615026c {
+               sd3_clk: sd3_clk@e615026c {
                        compatible = "renesas,r8a7791-div6-clock", "renesas,cpg-div6-clock";
                        reg = <0 0xe615026c 0 4>;
                        clocks = <&pll1_div2_clk>;
                        #clock-cells = <0>;
-                       clock-output-names = "sd2";
+                       clock-output-names = "sd3";
                };
                mmc0_clk: mmc0_clk@e6150240 {
                        compatible = "renesas,r8a7791-div6-clock", "renesas,cpg-div6-clock";
                mstp3_clks: mstp3_clks@e615013c {
                        compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
                        reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>;
-                       clocks = <&cp_clk>, <&sd2_clk>, <&sd1_clk>, <&cpg_clocks R8A7791_CLK_SD0>,
+                       clocks = <&cp_clk>, <&sd3_clk>, <&sd2_clk>, <&cpg_clocks R8A7791_CLK_SD0>,
                                 <&mmc0_clk>, <&hp_clk>, <&mp_clk>, <&hp_clk>, <&mp_clk>, <&rclk_clk>,
                                 <&hp_clk>, <&hp_clk>;
                        #clock-cells = <1>;
                mstp5_clks: mstp5_clks@e6150144 {
                        compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
                        reg = <0 0xe6150144 0 4>, <0 0xe615003c 0 4>;
-                       clocks = <&hp_clk>, <&hp_clk>, <&extal_clk>, <&p_clk>;
+                       clocks = <&hp_clk>, <&hp_clk>, <&cpg_clocks R8A7791_CLK_ADSP>,
+                                <&extal_clk>, <&p_clk>;
                        #clock-cells = <1>;
                        clock-indices = <
                                R8A7791_CLK_AUDIO_DMAC0 R8A7791_CLK_AUDIO_DMAC1
-                               R8A7791_CLK_THERMAL R8A7791_CLK_PWM
+                               R8A7791_CLK_ADSP_MOD R8A7791_CLK_THERMAL
+                               R8A7791_CLK_PWM
                        >;
-                       clock-output-names = "audmac0", "audmac1", "thermal", "pwm";
+                       clock-output-names = "audmac0", "audmac1", "adsp_mod",
+                                            "thermal", "pwm";
                };
                mstp7_clks: mstp7_clks@e615014c {
                        compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
                        reg = <0 0xe615014c 0 4>, <0 0xe61501c4 0 4>;
-                       clocks = <&mp_clk>,  <&mp_clk>, <&zs_clk>, <&p_clk>, <&p_clk>, <&zs_clk>,
+                       clocks = <&mp_clk>,  <&hp_clk>, <&zs_clk>, <&p_clk>, <&p_clk>, <&zs_clk>,
                                 <&zs_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
                                 <&zx_clk>, <&zx_clk>, <&zx_clk>;
                        #clock-cells = <1>;
                mstp8_clks: mstp8_clks@e6150990 {
                        compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
                        reg = <0 0xe6150990 0 4>, <0 0xe61509a0 0 4>;
-                       clocks = <&zg_clk>, <&hp_clk>, <&zg_clk>, <&zg_clk>,
+                       clocks = <&zx_clk>, <&hp_clk>, <&zg_clk>, <&zg_clk>,
                                 <&zg_clk>, <&p_clk>, <&zs_clk>, <&zs_clk>;
                        #clock-cells = <1>;
                        clock-indices = <
                status = "disabled";
        };
 
+       ipmmu_sy0: mmu@e6280000 {
+               compatible = "renesas,ipmmu-vmsa";
+               reg = <0 0xe6280000 0 0x1000>;
+               interrupts = <0 223 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 224 IRQ_TYPE_LEVEL_HIGH>;
+               #iommu-cells = <1>;
+               status = "disabled";
+       };
+
+       ipmmu_sy1: mmu@e6290000 {
+               compatible = "renesas,ipmmu-vmsa";
+               reg = <0 0xe6290000 0 0x1000>;
+               interrupts = <0 225 IRQ_TYPE_LEVEL_HIGH>;
+               #iommu-cells = <1>;
+               status = "disabled";
+       };
+
+       ipmmu_ds: mmu@e6740000 {
+               compatible = "renesas,ipmmu-vmsa";
+               reg = <0 0xe6740000 0 0x1000>;
+               interrupts = <0 198 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 199 IRQ_TYPE_LEVEL_HIGH>;
+               #iommu-cells = <1>;
+               status = "disabled";
+       };
+
+       ipmmu_mp: mmu@ec680000 {
+               compatible = "renesas,ipmmu-vmsa";
+               reg = <0 0xec680000 0 0x1000>;
+               interrupts = <0 226 IRQ_TYPE_LEVEL_HIGH>;
+               #iommu-cells = <1>;
+               status = "disabled";
+       };
+
+       ipmmu_mx: mmu@fe951000 {
+               compatible = "renesas,ipmmu-vmsa";
+               reg = <0 0xfe951000 0 0x1000>;
+               interrupts = <0 222 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 221 IRQ_TYPE_LEVEL_HIGH>;
+               #iommu-cells = <1>;
+               status = "disabled";
+       };
+
+       ipmmu_rt: mmu@ffc80000 {
+               compatible = "renesas,ipmmu-vmsa";
+               reg = <0 0xffc80000 0 0x1000>;
+               interrupts = <0 307 IRQ_TYPE_LEVEL_HIGH>;
+               #iommu-cells = <1>;
+               status = "disabled";
+       };
+
+       ipmmu_gp: mmu@e62a0000 {
+               compatible = "renesas,ipmmu-vmsa";
+               reg = <0 0xe62a0000 0 0x1000>;
+               interrupts = <0 260 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 261 IRQ_TYPE_LEVEL_HIGH>;
+               #iommu-cells = <1>;
+               status = "disabled";
+       };
+
        rcar_sound: rcar_sound@ec500000 {
                /*
                 * #sound-dai-cells is required
                reg =   <0 0xec500000 0 0x1000>, /* SCU */
                        <0 0xec5a0000 0 0x100>,  /* ADG */
                        <0 0xec540000 0 0x1000>, /* SSIU */
-                       <0 0xec541000 0 0x1280>; /* SSI */
+                       <0 0xec541000 0 0x1280>, /* SSI */
+                       <0 0xec740000 0 0x200>;  /* Audio DMAC peri peri*/
+               reg-names = "scu", "adg", "ssiu", "ssi", "audmapp";
+
                clocks = <&mstp10_clks R8A7791_CLK_SSI_ALL>,
                        <&mstp10_clks R8A7791_CLK_SSI9>, <&mstp10_clks R8A7791_CLK_SSI8>,
                        <&mstp10_clks R8A7791_CLK_SSI7>, <&mstp10_clks R8A7791_CLK_SSI6>,
                status = "disabled";
 
                rcar_sound,dvc {
-                       dvc0: dvc@0 { };
-                       dvc1: dvc@1 { };
+                       dvc0: dvc@0 {
+                               dmas = <&audma0 0xbc>;
+                               dma-names = "tx";
+                       };
+                       dvc1: dvc@1 {
+                               dmas = <&audma0 0xbe>;
+                               dma-names = "tx";
+                       };
                };
 
                rcar_sound,src {
-                       src0: src@0 { interrupts = <0 352 IRQ_TYPE_LEVEL_HIGH>; };
-                       src1: src@1 { interrupts = <0 353 IRQ_TYPE_LEVEL_HIGH>; };
-                       src2: src@2 { interrupts = <0 354 IRQ_TYPE_LEVEL_HIGH>; };
-                       src3: src@3 { interrupts = <0 355 IRQ_TYPE_LEVEL_HIGH>; };
-                       src4: src@4 { interrupts = <0 356 IRQ_TYPE_LEVEL_HIGH>; };
-                       src5: src@5 { interrupts = <0 357 IRQ_TYPE_LEVEL_HIGH>; };
-                       src6: src@6 { interrupts = <0 358 IRQ_TYPE_LEVEL_HIGH>; };
-                       src7: src@7 { interrupts = <0 359 IRQ_TYPE_LEVEL_HIGH>; };
-                       src8: src@8 { interrupts = <0 360 IRQ_TYPE_LEVEL_HIGH>; };
-                       src9: src@9 { interrupts = <0 361 IRQ_TYPE_LEVEL_HIGH>; };
+                       src0: src@0 {
+                               interrupts = <0 352 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x85>, <&audma1 0x9a>;
+                               dma-names = "rx", "tx";
+                       };
+                       src1: src@1 {
+                               interrupts = <0 353 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x87>, <&audma1 0x9c>;
+                               dma-names = "rx", "tx";
+                       };
+                       src2: src@2 {
+                               interrupts = <0 354 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x89>, <&audma1 0x9e>;
+                               dma-names = "rx", "tx";
+                       };
+                       src3: src@3 {
+                               interrupts = <0 355 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x8b>, <&audma1 0xa0>;
+                               dma-names = "rx", "tx";
+                       };
+                       src4: src@4 {
+                               interrupts = <0 356 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x8d>, <&audma1 0xb0>;
+                               dma-names = "rx", "tx";
+                       };
+                       src5: src@5 {
+                               interrupts = <0 357 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x8f>, <&audma1 0xb2>;
+                               dma-names = "rx", "tx";
+                       };
+                       src6: src@6 {
+                               interrupts = <0 358 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x91>, <&audma1 0xb4>;
+                               dma-names = "rx", "tx";
+                       };
+                       src7: src@7 {
+                               interrupts = <0 359 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x93>, <&audma1 0xb6>;
+                               dma-names = "rx", "tx";
+                       };
+                       src8: src@8 {
+                               interrupts = <0 360 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x95>, <&audma1 0xb8>;
+                               dma-names = "rx", "tx";
+                       };
+                       src9: src@9 {
+                               interrupts = <0 361 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x97>, <&audma1 0xba>;
+                               dma-names = "rx", "tx";
+                       };
                };
 
                rcar_sound,ssi {
-                       ssi0: ssi@0 { interrupts = <0 370 IRQ_TYPE_LEVEL_HIGH>; };
-                       ssi1: ssi@1 { interrupts = <0 371 IRQ_TYPE_LEVEL_HIGH>; };
-                       ssi2: ssi@2 { interrupts = <0 372 IRQ_TYPE_LEVEL_HIGH>; };
-                       ssi3: ssi@3 { interrupts = <0 373 IRQ_TYPE_LEVEL_HIGH>; };
-                       ssi4: ssi@4 { interrupts = <0 374 IRQ_TYPE_LEVEL_HIGH>; };
-                       ssi5: ssi@5 { interrupts = <0 375 IRQ_TYPE_LEVEL_HIGH>; };
-                       ssi6: ssi@6 { interrupts = <0 376 IRQ_TYPE_LEVEL_HIGH>; };
-                       ssi7: ssi@7 { interrupts = <0 377 IRQ_TYPE_LEVEL_HIGH>; };
-                       ssi8: ssi@8 { interrupts = <0 378 IRQ_TYPE_LEVEL_HIGH>; };
-                       ssi9: ssi@9 { interrupts = <0 379 IRQ_TYPE_LEVEL_HIGH>; };
+                       ssi0: ssi@0 {
+                               interrupts = <0 370 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x01>, <&audma1 0x02>, <&audma0 0x15>, <&audma1 0x16>;
+                               dma-names = "rx", "tx", "rxu", "txu";
+                       };
+                       ssi1: ssi@1 {
+                                interrupts = <0 371 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x03>, <&audma1 0x04>, <&audma0 0x49>, <&audma1 0x4a>;
+                               dma-names = "rx", "tx", "rxu", "txu";
+                       };
+                       ssi2: ssi@2 {
+                               interrupts = <0 372 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x05>, <&audma1 0x06>, <&audma0 0x63>, <&audma1 0x64>;
+                               dma-names = "rx", "tx", "rxu", "txu";
+                       };
+                       ssi3: ssi@3 {
+                               interrupts = <0 373 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x07>, <&audma1 0x08>, <&audma0 0x6f>, <&audma1 0x70>;
+                               dma-names = "rx", "tx", "rxu", "txu";
+                       };
+                       ssi4: ssi@4 {
+                               interrupts = <0 374 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x09>, <&audma1 0x0a>, <&audma0 0x71>, <&audma1 0x72>;
+                               dma-names = "rx", "tx", "rxu", "txu";
+                       };
+                       ssi5: ssi@5 {
+                               interrupts = <0 375 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x0b>, <&audma1 0x0c>, <&audma0 0x73>, <&audma1 0x74>;
+                               dma-names = "rx", "tx", "rxu", "txu";
+                       };
+                       ssi6: ssi@6 {
+                               interrupts = <0 376 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x0d>, <&audma1 0x0e>, <&audma0 0x75>, <&audma1 0x76>;
+                               dma-names = "rx", "tx", "rxu", "txu";
+                       };
+                       ssi7: ssi@7 {
+                               interrupts = <0 377 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x0f>, <&audma1 0x10>, <&audma0 0x79>, <&audma1 0x7a>;
+                               dma-names = "rx", "tx", "rxu", "txu";
+                       };
+                       ssi8: ssi@8 {
+                               interrupts = <0 378 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x11>, <&audma1 0x12>, <&audma0 0x7b>, <&audma1 0x7c>;
+                               dma-names = "rx", "tx", "rxu", "txu";
+                       };
+                       ssi9: ssi@9 {
+                               interrupts = <0 379 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&audma0 0x13>, <&audma1 0x14>, <&audma0 0x7d>, <&audma1 0x7e>;
+                               dma-names = "rx", "tx", "rxu", "txu";
+                       };
                };
        };
 };
index 0d848e60507172ef8f0a7872e6b2cde4f61a7fda..928cfa641475e4f96a44232c60aacea9f7744159 100644 (file)
        status = "okay";
 };
 
+&ether {
+       phy-handle = <&phy1>;
+       renesas,ether-link-active-low;
+       status = "okay";
+
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+               interrupt-parent = <&irqc0>;
+               interrupts = <8 IRQ_TYPE_LEVEL_LOW>;
+               micrel,led-mode = <1>;
+       };
+};
+
 &scif2 {
        status = "okay";
 };
index 8f78da5ef10b603bc8324b0834e2632fec28e1e7..7a3ffa51a8bf2c8be0a5a1c990867a2a138bb06f 100644 (file)
                             <0 17 IRQ_TYPE_LEVEL_HIGH>;
        };
 
+       dmac0: dma-controller@e6700000 {
+               compatible = "renesas,rcar-dmac";
+               reg = <0 0xe6700000 0 0x20000>;
+               interrupts = <0 197 IRQ_TYPE_LEVEL_HIGH
+                             0 200 IRQ_TYPE_LEVEL_HIGH
+                             0 201 IRQ_TYPE_LEVEL_HIGH
+                             0 202 IRQ_TYPE_LEVEL_HIGH
+                             0 203 IRQ_TYPE_LEVEL_HIGH
+                             0 204 IRQ_TYPE_LEVEL_HIGH
+                             0 205 IRQ_TYPE_LEVEL_HIGH
+                             0 206 IRQ_TYPE_LEVEL_HIGH
+                             0 207 IRQ_TYPE_LEVEL_HIGH
+                             0 208 IRQ_TYPE_LEVEL_HIGH
+                             0 209 IRQ_TYPE_LEVEL_HIGH
+                             0 210 IRQ_TYPE_LEVEL_HIGH
+                             0 211 IRQ_TYPE_LEVEL_HIGH
+                             0 212 IRQ_TYPE_LEVEL_HIGH
+                             0 213 IRQ_TYPE_LEVEL_HIGH
+                             0 214 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "error",
+                               "ch0", "ch1", "ch2", "ch3",
+                               "ch4", "ch5", "ch6", "ch7",
+                               "ch8", "ch9", "ch10", "ch11",
+                               "ch12", "ch13", "ch14";
+               clocks = <&mstp2_clks R8A7794_CLK_SYS_DMAC0>;
+               clock-names = "fck";
+               #dma-cells = <1>;
+               dma-channels = <15>;
+       };
+
+       dmac1: dma-controller@e6720000 {
+               compatible = "renesas,rcar-dmac";
+               reg = <0 0xe6720000 0 0x20000>;
+               interrupts = <0 220 IRQ_TYPE_LEVEL_HIGH
+                             0 216 IRQ_TYPE_LEVEL_HIGH
+                             0 217 IRQ_TYPE_LEVEL_HIGH
+                             0 218 IRQ_TYPE_LEVEL_HIGH
+                             0 219 IRQ_TYPE_LEVEL_HIGH
+                             0 308 IRQ_TYPE_LEVEL_HIGH
+                             0 309 IRQ_TYPE_LEVEL_HIGH
+                             0 310 IRQ_TYPE_LEVEL_HIGH
+                             0 311 IRQ_TYPE_LEVEL_HIGH
+                             0 312 IRQ_TYPE_LEVEL_HIGH
+                             0 313 IRQ_TYPE_LEVEL_HIGH
+                             0 314 IRQ_TYPE_LEVEL_HIGH
+                             0 315 IRQ_TYPE_LEVEL_HIGH
+                             0 316 IRQ_TYPE_LEVEL_HIGH
+                             0 317 IRQ_TYPE_LEVEL_HIGH
+                             0 318 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "error",
+                               "ch0", "ch1", "ch2", "ch3",
+                               "ch4", "ch5", "ch6", "ch7",
+                               "ch8", "ch9", "ch10", "ch11",
+                               "ch12", "ch13", "ch14";
+               clocks = <&mstp2_clks R8A7794_CLK_SYS_DMAC1>;
+               clock-names = "fck";
+               #dma-cells = <1>;
+               dma-channels = <15>;
+       };
+
        scifa0: serial@e6c40000 {
                compatible = "renesas,scifa-r8a7794", "renesas,scifa";
                reg = <0 0xe6c40000 0 64>;
                status = "disabled";
        };
 
+       ether: ethernet@ee700000 {
+               compatible = "renesas,ether-r8a7794";
+               reg = <0 0xee700000 0 0x400>;
+               interrupts = <0 162 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp8_clks R8A7794_CLK_ETHER>;
+               phy-mode = "rmii";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               status = "disabled";
+       };
+
+       sdhi0: sd@ee100000 {
+               compatible = "renesas,sdhi-r8a7794";
+               reg = <0 0xee100000 0 0x200>;
+               interrupts = <0 165 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp3_clks R8A7794_CLK_SDHI0>;
+               status = "disabled";
+       };
+
+       sdhi1: sd@ee140000 {
+               compatible = "renesas,sdhi-r8a7794";
+               reg = <0 0xee140000 0 0x100>;
+               interrupts = <0 167 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp3_clks R8A7794_CLK_SDHI1>;
+               status = "disabled";
+       };
+
+       sdhi2: sd@ee160000 {
+               compatible = "renesas,sdhi-r8a7794";
+               reg = <0 0xee160000 0 0x100>;
+               interrupts = <0 168 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp3_clks R8A7794_CLK_SDHI2>;
+               status = "disabled";
+       };
+
        clocks {
                #address-cells = <2>;
                #size-cells = <2>;
                                             "lb", "qspi", "sdh", "sd0", "z";
                };
                /* Variable factor clocks */
-               sd1_clk: sd2_clk@e6150078 {
+               sd2_clk: sd2_clk@e6150078 {
                        compatible = "renesas,r8a7794-div6-clock", "renesas,cpg-div6-clock";
                        reg = <0 0xe6150078 0 4>;
                        clocks = <&pll1_div2_clk>;
                        #clock-cells = <0>;
-                       clock-output-names = "sd1";
+                       clock-output-names = "sd2";
                };
-               sd2_clk: sd3_clk@e615007c {
+               sd3_clk: sd3_clk@e615026c {
                        compatible = "renesas,r8a7794-div6-clock", "renesas,cpg-div6-clock";
-                       reg = <0 0xe615007c 0 4>;
+                       reg = <0 0xe615026c 0 4>;
                        clocks = <&pll1_div2_clk>;
                        #clock-cells = <0>;
-                       clock-output-names = "sd2";
+                       clock-output-names = "sd3";
                };
                mmc0_clk: mmc0_clk@e6150240 {
                        compatible = "renesas,r8a7794-div6-clock", "renesas,cpg-div6-clock";
                mstp3_clks: mstp3_clks@e615013c {
                        compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks";
                        reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>;
-                       clocks = <&sd2_clk>, <&sd1_clk>, <&cpg_clocks R8A7794_CLK_SD0>,
+                       clocks = <&sd3_clk>, <&sd2_clk>, <&cpg_clocks R8A7794_CLK_SD0>,
                                 <&mmc0_clk>, <&rclk_clk>, <&hp_clk>, <&hp_clk>;
                        #clock-cells = <1>;
                        clock-indices = <
                        clock-output-names = "scifa3", "scifa4", "scifa5";
                };
        };
+
+       ipmmu_sy0: mmu@e6280000 {
+               compatible = "renesas,ipmmu-vmsa";
+               reg = <0 0xe6280000 0 0x1000>;
+               interrupts = <0 223 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 224 IRQ_TYPE_LEVEL_HIGH>;
+               #iommu-cells = <1>;
+               status = "disabled";
+       };
+
+       ipmmu_sy1: mmu@e6290000 {
+               compatible = "renesas,ipmmu-vmsa";
+               reg = <0 0xe6290000 0 0x1000>;
+               interrupts = <0 225 IRQ_TYPE_LEVEL_HIGH>;
+               #iommu-cells = <1>;
+               status = "disabled";
+       };
+
+       ipmmu_ds: mmu@e6740000 {
+               compatible = "renesas,ipmmu-vmsa";
+               reg = <0 0xe6740000 0 0x1000>;
+               interrupts = <0 198 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 199 IRQ_TYPE_LEVEL_HIGH>;
+               #iommu-cells = <1>;
+       };
+
+       ipmmu_mp: mmu@ec680000 {
+               compatible = "renesas,ipmmu-vmsa";
+               reg = <0 0xec680000 0 0x1000>;
+               interrupts = <0 226 IRQ_TYPE_LEVEL_HIGH>;
+               #iommu-cells = <1>;
+               status = "disabled";
+       };
+
+       ipmmu_mx: mmu@fe951000 {
+               compatible = "renesas,ipmmu-vmsa";
+               reg = <0 0xfe951000 0 0x1000>;
+               interrupts = <0 222 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 221 IRQ_TYPE_LEVEL_HIGH>;
+               #iommu-cells = <1>;
+       };
+
+       ipmmu_gp: mmu@e62a0000 {
+               compatible = "renesas,ipmmu-vmsa";
+               reg = <0 0xe62a0000 0 0x1000>;
+               interrupts = <0 260 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 261 IRQ_TYPE_LEVEL_HIGH>;
+               #iommu-cells = <1>;
+               status = "disabled";
+       };
 };
index 9a09579b8309c39fbb767c7798adee8f56062cea..bdf85701987d7d355746b26a9b68e323864c4f2b 100644 (file)
                regulator-always-on;
                regulator-boot-on;
        };
+
+       vsys: vsys-regulator {
+               compatible = "regulator-fixed";
+               regulator-name = "vsys";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-boot-on;
+       };
 };
 
 &emac {
                pinctrl-names = "default";
                pinctrl-0 = <&act8846_dvs0_ctl>;
 
+               vp1-supply = <&vsys>;
+               vp2-supply = <&vsys>;
+               vp3-supply = <&vsys>;
+               vp4-supply = <&vsys>;
+               inl1-supply = <&vcc_io>;
+               inl2-supply = <&vsys>;
+               inl3-supply = <&vsys>;
+
                regulators {
                        vcc_ddr: REG1 {
                                regulator-name = "VCC_DDR";
index d7b8bbc0c25fa00c8ccf59ee0b1ad03485136622..1687e8336994fc4bb87b5d4edfd7d66250be9626 100644 (file)
@@ -33,6 +33,7 @@
                regulator-max-microvolt = <1350000>;
                regulator-always-on;
                regulator-boot-on;
+               vin-supply = <&vcc_sys>;
        };
 
        vdd_gpu: syr828@41 {
@@ -43,6 +44,7 @@
                regulator-min-microvolt = <850000>;
                regulator-max-microvolt = <1350000>;
                regulator-always-on;
+               vin-supply = <&vcc_sys>;
        };
 
        hym8563@51 {
                reg = <0x5a>;
                status = "okay";
 
+               vp1-supply = <&vcc_sys>;
+               vp2-supply = <&vcc_sys>;
+               vp3-supply = <&vcc_sys>;
+               vp4-supply = <&vcc_sys>;
+               inl1-supply = <&vcc_io>;
+               inl2-supply = <&vcc_sys>;
+               inl3-supply = <&vcc_20>;
+
                regulators {
                        vcc_ddr: REG1 {
                                regulator-name = "VCC_DDR";
index a1c294bf7fed0e51a29bd9205a408819d7aeadeb..f62ea78754a956d2f562a8900e3bfcf3cdba4871 100644 (file)
                #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 = <&vcc_18>;
                vcc9-supply = <&vcc_io>;
                vcc10-supply = <&vcc_io>;
+               vcc11-supply = <&vcc_sys>;
                vcc12-supply = <&vcc_io>;
                vddio-supply = <&vccio_pmu>;
 
index 5e895a514a0b82afef27ae7c7e849ed1ab8d226f..4a457518d8616044b26fbfa34bea17ebbd421f84 100644 (file)
                regulator-always-on;
                regulator-boot-on;
        };
+
+       vcc_sys: vsys-regulator {
+               compatible = "regulator-fixed";
+               regulator-name = "vcc_sys";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-always-on;
+               regulator-boot-on;
+       };
 };
 
 &emmc {
        };
 };
 
+&usbphy {
+       status = "okay";
+};
+
 &usb_host0_ehci {
        status = "okay";
 };
index e6f873abbe0dd991fcdcf5a81dbe33c09aec1e1d..b54dd78580c1c77a01035b62d8181d0cd995b18f 100644 (file)
        status = "okay";
 };
 
+&gmac {
+       assigned-clocks = <&cru SCLK_MAC>;
+       assigned-clock-parents = <&ext_gmac>;
+       clock_in_out = "input";
+       pinctrl-names = "default";
+       pinctrl-0 = <&rgmii_pins>, <&phy_rst>, <&phy_pmeb>, <&phy_int>;
+       phy-supply = <&vcc_lan>;
+       phy-mode = "rgmii";
+       snps,reset-active-low;
+       snps,reset-delays-us = <0 10000 1000000>;
+       snps,reset-gpio = <&gpio4 8 GPIO_ACTIVE_LOW>;
+       tx_delay = <0x30>;
+       rx_delay = <0x10>;
+       status = "ok";
+};
+
 &hdmi {
        ddc-i2c-bus = <&i2c5>;
        status = "okay";
        status = "okay";
 };
 
+&usbphy {
+       status = "okay";
+};
+
 &usb_host1 {
        pinctrl-names = "default";
        pinctrl-0 = <&usbhub_rst>;
diff --git a/arch/arm/boot/dts/rk3288-popmetal.dts b/arch/arm/boot/dts/rk3288-popmetal.dts
new file mode 100644 (file)
index 0000000..d081f0e
--- /dev/null
@@ -0,0 +1,447 @@
+/*
+ * 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/;
+
+#include "rk3288.dtsi"
+
+/ {
+       model = "PopMetal-RK3288";
+       compatible = "chipspark,popmetal-rk3288", "rockchip,rk3288";
+
+       memory{
+               reg = <0 0x80000000>;
+       };
+
+       ext_gmac: external-gmac-clock {
+               compatible = "fixed-clock";
+               clock-frequency = <125000000>;
+               clock-output-names = "ext_gmac";
+               #clock-cells = <0>;
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               autorepeat;
+
+               pinctrl-names = "default";
+               pinctrl-0 = <&pwrbtn>;
+
+               button@0 {
+                       gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
+                       linux,code = <116>;
+                       label = "GPIO Key Power";
+                       linux,input-type = <1>;
+                       gpio-key,wakeup = <1>;
+                       debounce-interval = <100>;
+               };
+       };
+
+       ir: ir-receiver {
+               compatible = "gpio-ir-receiver";
+               gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&ir_int>;
+       };
+
+       vcc_sys: vsys-regulator {
+               compatible = "regulator-fixed";
+               regulator-name = "vcc_sys";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-always-on;
+               regulator-boot-on;
+       };
+};
+
+&cpu0 {
+       cpu0-supply = <&vdd_cpu>;
+};
+
+&emmc {
+       broken-cd;
+       bus-width = <8>;
+       cap-mmc-highspeed;
+       disable-wp;
+       non-removable;
+       num-slots = <1>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_pwr &emmc_bus8>;
+       status = "okay";
+};
+
+&sdmmc {
+       bus-width = <4>;
+       cap-mmc-highspeed;
+       cap-sd-highspeed;
+       card-detect-delay = <200>;
+       disable-wp;                     /* wp not hooked up */
+       num-slots = <1>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>;
+       status = "okay";
+};
+
+&gmac {
+       phy-supply = <&vcc_lan>;
+       phy-mode = "rgmii";
+       clock_in_out = "input";
+       snps,reset-gpio = <&gpio4 7 0>;
+       snps,reset-active-low;
+       snps,reset-delays-us = <0 10000 1000000>;
+       assigned-clocks = <&cru SCLK_MAC>;
+       assigned-clock-parents = <&ext_gmac>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&rgmii_pins>;
+       tx_delay = <0x30>;
+       rx_delay = <0x10>;
+       status = "ok";
+};
+
+&hdmi {
+       ddc-i2c-bus = <&i2c5>;
+       status = "okay";
+};
+
+&i2c0 {
+       status = "okay";
+       clock-frequency = <400000>;
+
+       rk808: pmic@1b {
+               compatible = "rockchip,rk808";
+               reg = <0x1b>;
+               interrupt-parent = <&gpio0>;
+               interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pmic_int &global_pwroff>;
+               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 = <&vcc_18>;
+               vcc9-supply = <&vcc_io>;
+               vcc10-supply = <&vcc_io>;
+               vcc11-supply = <&vcc_sys>;
+               vcc12-supply = <&vcc_io>;
+               vddio-supply = <&vcc_io>;
+
+               regulators {
+                       vdd_cpu: DCDC_REG1 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <750000>;
+                               regulator-max-microvolt = <1350000>;
+                               regulator-name = "vdd_arm";
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       vdd_gpu: DCDC_REG2 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <850000>;
+                               regulator-max-microvolt = <1250000>;
+                               regulator-name = "vdd_gpu";
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1000000>;
+                               };
+                       };
+
+                       vcc_ddr: DCDC_REG3 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-name = "vcc_ddr";
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                               };
+                       };
+
+                       vcc_io: DCDC_REG4 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc_io";
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <3300000>;
+                               };
+                       };
+
+                       vcc_lan: LDO_REG1 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc_lan";
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <3300000>;
+                               };
+                       };
+
+                       vccio_sd: LDO_REG2 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vccio_sd";
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       vdd_10: LDO_REG3 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-name = "vdd_10";
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1000000>;
+                               };
+                       };
+
+                       vcc18_lcd: LDO_REG4 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-name = "vcc18_lcd";
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1800000>;
+                               };
+                       };
+
+                       ldo5: LDO_REG5 {
+                               regulator-always-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "ldo5";
+                       };
+
+                       vdd10_lcd: LDO_REG6 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-name = "vdd10_lcd";
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1000000>;
+                               };
+                       };
+
+                       vcc_18: LDO_REG7 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-name = "vcc_18";
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1800000>;
+                               };
+                       };
+
+                       vcca_codec: LDO_REG8 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcca_codec";
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <3300000>;
+                               };
+                       };
+
+                       vcc_wl: SWITCH_REG1 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-name = "vcc_wl";
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                               };
+                       };
+
+                       vcc_lcd: SWITCH_REG2 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-name = "vcc_lcd";
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                               };
+                       };
+               };
+       };
+};
+
+&i2c1 {
+       status = "okay";
+       clock-frequency = <400000>;
+
+       ak8963: ak8963@0d {
+               compatible = "asahi-kasei,ak8975";
+               reg = <0x0d>;
+               interrupt-parent = <&gpio8>;
+               interrupts = <1 IRQ_TYPE_EDGE_RISING>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&comp_int>;
+       };
+
+       l3g4200d: l3g4200d@68 {
+               compatible = "st,l3g4200d-gyro";
+               st,drdy-int-pin = <2>;
+               reg = <0x6b>;
+       };
+
+       mma8452: mma8452@1d {
+               compatible = "fsl,mma8452";
+               reg = <0x1d>;
+               interrupt-parent = <&gpio8>;
+               interrupts = <0 IRQ_TYPE_EDGE_RISING>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&gsensor_int>;
+       };
+};
+
+&i2c2 {
+       status = "okay";
+};
+
+&i2c3 {
+       status = "okay";
+};
+
+&i2c4 {
+       status = "okay";
+};
+
+&i2c5 {
+       status = "okay";
+};
+
+&pinctrl {
+       ak8963 {
+               comp_int: comp-int {
+                       rockchip,pins = <8 1 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+
+       buttons {
+               pwrbtn: pwrbtn {
+                       rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+
+       ir {
+               ir_int: ir-int {
+                       rockchip,pins = <0 6 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+
+       mma8452 {
+               gsensor_int: gsensor-int {
+                       rockchip,pins = <8 0 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+
+       pmic {
+               pmic_int: pmic-int {
+                       rockchip,pins = <RK_GPIO0 4 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+};
+
+&vopb {
+       status = "okay";
+};
+
+&vopb_mmu {
+       status = "okay";
+};
+
+&vopl {
+       status = "okay";
+};
+
+&vopl_mmu {
+       status = "okay";
+};
+
+&uart0 {
+       status = "okay";
+};
+
+&uart1 {
+       status = "okay";
+};
+
+&uart2 {
+       status = "okay";
+};
+
+&uart3 {
+       status = "okay";
+};
+
+&uart4 {
+       status = "okay";
+};
+
+&usbphy {
+       status = "okay";
+};
index eccc78d3220ba2e59e2994dfb4f5f20d3d3f7a91..165968d51d8fd7370ca596833c0e2126fc616970 100644 (file)
                interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&cru HCLK_USBHOST0>;
                clock-names = "usbhost";
+               phys = <&usbphy1>;
+               phy-names = "usb";
                status = "disabled";
        };
 
                interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&cru HCLK_USBHOST1>;
                clock-names = "otg";
+               phys = <&usbphy2>;
+               phy-names = "usb2-phy";
                status = "disabled";
        };
 
                interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&cru HCLK_OTG0>;
                clock-names = "otg";
+               phys = <&usbphy0>;
+               phy-names = "usb2-phy";
                status = "disabled";
        };
 
                interrupts = <GIC_PPI 9 0xf04>;
        };
 
+       usbphy: phy {
+               compatible = "rockchip,rk3288-usb-phy";
+               rockchip,grf = <&grf>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               status = "disabled";
+
+               usbphy0: usb-phy0 {
+                       #phy-cells = <0>;
+                       reg = <0x320>;
+                       clocks = <&cru SCLK_OTGPHY0>;
+                       clock-names = "phyclk";
+               };
+
+               usbphy1: usb-phy1 {
+                       #phy-cells = <0>;
+                       reg = <0x334>;
+                       clocks = <&cru SCLK_OTGPHY1>;
+                       clock-names = "phyclk";
+               };
+
+               usbphy2: usb-phy2 {
+                       #phy-cells = <0>;
+                       reg = <0x348>;
+                       clocks = <&cru SCLK_OTGPHY2>;
+                       clock-names = "phyclk";
+               };
+       };
+
        pinctrl: pinctrl {
                compatible = "rockchip,rk3288-pinctrl";
                rockchip,grf = <&grf>;
index 367af53c1b8437d30059b32abff7dd3ed7a0c992..57ab8587f7b977d4274dfdf2380d9f363f5a06ff 100644 (file)
@@ -26,6 +26,7 @@
                serial2 = &usart1;
                serial3 = &usart2;
                serial4 = &usart3;
+               serial5 = &uart0;
                gpio0 = &pioA;
                gpio1 = &pioB;
                gpio2 = &pioC;
                                status = "disabled";
                        };
 
+                       uart0: serial@f0024000 {
+                               compatible = "atmel,at91sam9260-usart";
+                               reg = <0xf0024000 0x100>;
+                               interrupts = <16 IRQ_TYPE_LEVEL_HIGH 5>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_uart0>;
+                               clocks = <&uart0_clk>;
+                               clock-names = "usart";
+                               status = "disabled";
+                       };
+
                        pwm0: pwm@f002c000 {
                                compatible = "atmel,sama5d3-pwm";
                                reg = <0xf002c000 0x300>;
                        };
 
                        dbgu: serial@ffffee00 {
-                               compatible = "atmel,at91sam9260-usart";
+                               compatible = "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
                                reg = <0xffffee00 0x200>;
                                interrupts = <2 IRQ_TYPE_LEVEL_HIGH 7>;
                                dmas = <&dma1 2 AT91_DMA_CFG_PER_ID(13)>,
                                        };
                                };
 
+                               uart0 {
+                                       pinctrl_uart0: uart0-0 {
+                                               atmel,pins =
+                                                       <AT91_PIOC 29 AT91_PERIPH_A AT91_PINCTRL_NONE   /* conflicts with PWMFI2, ISI_D8 */
+                                                        AT91_PIOC 30 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;      /* conflicts with ISI_PCK */
+                                       };
+                               };
+
+                               uart1 {
+                                       pinctrl_uart1: uart1-0 {
+                                               atmel,pins =
+                                                       <AT91_PIOA 30 AT91_PERIPH_B AT91_PINCTRL_NONE   /* conflicts with TWD0, ISI_VSYNC */
+                                                        AT91_PIOA 31 AT91_PERIPH_B AT91_PINCTRL_PULL_UP>;      /* conflicts with TWCK0, ISI_HSYNC */
+                                       };
+                               };
+
                                usart0 {
                                        pinctrl_usart0: usart0-0 {
                                                atmel,pins =
                                                atmel,clk-output-range = <0 66000000>;
                                        };
 
+                                       uart0_clk: uart0_clk {
+                                               #clock-cells = <0>;
+                                               reg = <16>;
+                                               atmel,clk-output-range = <0 66000000>;
+                                       };
+
                                        twi0_clk: twi0_clk {
                                                reg = <18>;
                                                #clock-cells = <0>;
index 9089c7c6cea863e547a26d7c8d2233c138827334..d9a9aca1ccfdf6d5514b535241d7c5f2ae379e92 100644 (file)
@@ -44,8 +44,6 @@
 
        gpio_keys {
                compatible = "gpio-keys";
-               #address-cells = <1>;
-               #size-cells = <0>;
 
                pb_user1 {
                        label = "pb_user1";
index eaf41451ad0cf5afec07ab94a03ae9e9a4bdee42..c5a3772741bf610b300a10147e76bcc882b973fb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * at91sama5d3_can.dtsi - Device Tree Include file for AT91SAM9x5 SoC with
+ * sama5d3_can.dtsi - Device Tree Include file for SAMA5D3 SoC with
  * CAN support
  *
  * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
index b4544cf11bad1b08e5825dcf6690bb57acc558db..7cb235ef0fb6dba30e77d6c91a0b9eafda6359a3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * at91sama5d3_emac.dtsi - Device Tree Include file for AT91SAM9x5 SoC with
+ * sama5d3_emac.dtsi - Device Tree Include file for SAMA5D3 SoC with
  * Ethernet.
  *
  * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
index de5ed59fb446d5c7cefc8ddc02d2bbe24032b9bc..23f225fbb7563e3efb4c896464b27bd3b8bf11de 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * at91sama5d3_gmac.dtsi - Device Tree Include file for AT91SAM9x5 SoC with
+ * sama5d3_gmac.dtsi - Device Tree Include file for SAMA5D3 SoC with
  * Gigabit Ethernet.
  *
  * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
index 85d30270156561c3e8b44cc189482ec469c6e1af..be7cfefc6c312351a138244dbe0db7a3cc195ee0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * at91sama5d3_lcd.dtsi - Device Tree Include file for AT91SAM9x5 SoC with
+ * sama5d3_lcd.dtsi - Device Tree Include file for SAMA5D3 SoC with
  * LCD support
  *
  * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
 / {
        ahb {
                apb {
+                       hlcdc: hlcdc@f0030000 {
+                               compatible = "atmel,sama5d3-hlcdc";
+                               reg = <0xf0030000 0x2000>;
+                               interrupts = <36 IRQ_TYPE_LEVEL_HIGH 0>;
+                               clocks = <&lcdc_clk>, <&lcdck>, <&clk32k>;
+                               clock-names = "periph_clk","sys_clk", "slow_clk";
+                               status = "disabled";
+
+                               hlcdc-display-controller {
+                                       compatible = "atmel,hlcdc-display-controller";
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+
+                                       port@0 {
+                                               #address-cells = <1>;
+                                               #size-cells = <0>;
+                                               reg = <0>;
+                                       };
+                               };
+
+                               hlcdc_pwm: hlcdc-pwm {
+                                       compatible = "atmel,hlcdc-pwm";
+                                       pinctrl-names = "default";
+                                       pinctrl-0 = <&pinctrl_lcd_pwm>;
+                                       #pwm-cells = <3>;
+                               };
+                       };
+
                        pinctrl@fffff200 {
                                lcd {
-                                       pinctrl_lcd: lcd-0 {
+                                       pinctrl_lcd_base: lcd-base-0 {
+                                               atmel,pins =
+                                                       <AT91_PIOA 26 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDVSYNC */
+                                                        AT91_PIOA 27 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDHSYNC */
+                                                        AT91_PIOA 25 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDDISP */
+                                                        AT91_PIOA 29 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDDEN */
+                                                        AT91_PIOA 28 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* LCDPCK */
+                                       };
+
+                                       pinctrl_lcd_pwm: lcd-pwm-0 {
+                                               atmel,pins = <AT91_PIOA 24 AT91_PERIPH_A AT91_PINCTRL_NONE>;    /* LCDPWM */
+                                       };
+
+                                       pinctrl_lcd_rgb444: lcd-rgb-0 {
+                                               atmel,pins =
+                                                       <AT91_PIOA 0 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD0 pin */
+                                                        AT91_PIOA 1 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD1 pin */
+                                                        AT91_PIOA 2 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD2 pin */
+                                                        AT91_PIOA 3 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD3 pin */
+                                                        AT91_PIOA 4 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD4 pin */
+                                                        AT91_PIOA 5 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD5 pin */
+                                                        AT91_PIOA 6 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD6 pin */
+                                                        AT91_PIOA 7 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD7 pin */
+                                                        AT91_PIOA 8 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD8 pin */
+                                                        AT91_PIOA 9 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD9 pin */
+                                                        AT91_PIOA 10 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD10 pin */
+                                                        AT91_PIOA 11 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* LCDD11 pin */
+                                       };
+
+                                       pinctrl_lcd_rgb565: lcd-rgb-1 {
+                                               atmel,pins =
+                                                       <AT91_PIOA 0 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD0 pin */
+                                                        AT91_PIOA 1 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD1 pin */
+                                                        AT91_PIOA 2 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD2 pin */
+                                                        AT91_PIOA 3 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD3 pin */
+                                                        AT91_PIOA 4 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD4 pin */
+                                                        AT91_PIOA 5 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD5 pin */
+                                                        AT91_PIOA 6 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD6 pin */
+                                                        AT91_PIOA 7 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD7 pin */
+                                                        AT91_PIOA 8 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD8 pin */
+                                                        AT91_PIOA 9 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD9 pin */
+                                                        AT91_PIOA 10 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD10 pin */
+                                                        AT91_PIOA 11 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD11 pin */
+                                                        AT91_PIOA 12 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD12 pin */
+                                                        AT91_PIOA 13 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD13 pin */
+                                                        AT91_PIOA 14 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD14 pin */
+                                                        AT91_PIOA 15 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* LCDD15 pin */
+                                       };
+
+                                       pinctrl_lcd_rgb666: lcd-rgb-2 {
+                                               atmel,pins =
+                                                       <AT91_PIOA 0 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD0 pin */
+                                                        AT91_PIOA 1 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD1 pin */
+                                                        AT91_PIOA 2 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD2 pin */
+                                                        AT91_PIOA 3 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD3 pin */
+                                                        AT91_PIOA 4 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD4 pin */
+                                                        AT91_PIOA 5 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD5 pin */
+                                                        AT91_PIOA 6 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD6 pin */
+                                                        AT91_PIOA 7 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD7 pin */
+                                                        AT91_PIOA 8 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD8 pin */
+                                                        AT91_PIOA 9 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD9 pin */
+                                                        AT91_PIOA 10 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD10 pin */
+                                                        AT91_PIOA 11 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD11 pin */
+                                                        AT91_PIOA 12 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD12 pin */
+                                                        AT91_PIOA 13 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD13 pin */
+                                                        AT91_PIOA 14 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD14 pin */
+                                                        AT91_PIOA 15 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD15 pin */
+                                                        AT91_PIOA 16 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD16 pin */
+                                                        AT91_PIOA 17 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* LCDD17 pin */
+                                       };
+
+                                       pinctrl_lcd_rgb666_alt: lcd-rgb-2-alt {
+                                               atmel,pins =
+                                                       <AT91_PIOA 0 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD0 pin */
+                                                        AT91_PIOA 1 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD1 pin */
+                                                        AT91_PIOA 2 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD2 pin */
+                                                        AT91_PIOA 3 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD3 pin */
+                                                        AT91_PIOA 4 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD4 pin */
+                                                        AT91_PIOA 5 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD5 pin */
+                                                        AT91_PIOA 6 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD6 pin */
+                                                        AT91_PIOA 7 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD7 pin */
+                                                        AT91_PIOA 8 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD8 pin */
+                                                        AT91_PIOA 9 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD9 pin */
+                                                        AT91_PIOA 10 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD10 pin */
+                                                        AT91_PIOA 11 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD11 pin */
+                                                        AT91_PIOA 12 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD12 pin */
+                                                        AT91_PIOA 13 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD13 pin */
+                                                        AT91_PIOA 14 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD14 pin */
+                                                        AT91_PIOA 15 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD15 pin */
+                                                        AT91_PIOC 14 AT91_PERIPH_C AT91_PINCTRL_NONE   /* LCDD16 pin */
+                                                        AT91_PIOC 13 AT91_PERIPH_C AT91_PINCTRL_NONE>; /* LCDD17 pin */
+                                       };
+
+                                       pinctrl_lcd_rgb888: lcd-rgb-3 {
+                                               atmel,pins =
+                                                       <AT91_PIOA 0 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD0 pin */
+                                                        AT91_PIOA 1 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD1 pin */
+                                                        AT91_PIOA 2 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD2 pin */
+                                                        AT91_PIOA 3 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD3 pin */
+                                                        AT91_PIOA 4 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD4 pin */
+                                                        AT91_PIOA 5 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD5 pin */
+                                                        AT91_PIOA 6 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD6 pin */
+                                                        AT91_PIOA 7 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD7 pin */
+                                                        AT91_PIOA 8 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD8 pin */
+                                                        AT91_PIOA 9 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD9 pin */
+                                                        AT91_PIOA 10 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD10 pin */
+                                                        AT91_PIOA 11 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD11 pin */
+                                                        AT91_PIOA 12 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD12 pin */
+                                                        AT91_PIOA 13 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD13 pin */
+                                                        AT91_PIOA 14 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD14 pin */
+                                                        AT91_PIOA 15 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD15 pin */
+                                                        AT91_PIOA 16 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD16 pin */
+                                                        AT91_PIOA 17 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD17 pin */
+                                                        AT91_PIOA 18 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD18 pin */
+                                                        AT91_PIOA 19 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD19 pin */
+                                                        AT91_PIOA 20 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD20 pin */
+                                                        AT91_PIOA 21 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD21 pin */
+                                                        AT91_PIOA 22 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD22 pin */
+                                                        AT91_PIOA 23 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* LCDD23 pin */
+                                       };
+
+                                       pinctrl_lcd_rgb888_alt: lcd-rgb-3-alt {
                                                atmel,pins =
-                                                       <AT91_PIOA 24 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PA24 periph A LCDPWM */
-                                                        AT91_PIOA 26 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PA26 periph A LCDVSYNC */
-                                                        AT91_PIOA 27 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PA27 periph A LCDHSYNC */
-                                                        AT91_PIOA 25 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PA25 periph A LCDDISP */
-                                                        AT91_PIOA 29 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PA29 periph A LCDDEN */
-                                                        AT91_PIOA 28 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PA28 periph A LCDPCK */
-                                                        AT91_PIOA 0 AT91_PERIPH_A AT91_PINCTRL_NONE    /* PA0 periph A LCDD0 pin */
-                                                        AT91_PIOA 1 AT91_PERIPH_A AT91_PINCTRL_NONE    /* PA1 periph A LCDD1 pin */
-                                                        AT91_PIOA 2 AT91_PERIPH_A AT91_PINCTRL_NONE    /* PA2 periph A LCDD2 pin */
-                                                        AT91_PIOA 3 AT91_PERIPH_A AT91_PINCTRL_NONE    /* PA3 periph A LCDD3 pin */
-                                                        AT91_PIOA 4 AT91_PERIPH_A AT91_PINCTRL_NONE    /* PA4 periph A LCDD4 pin */
-                                                        AT91_PIOA 5 AT91_PERIPH_A AT91_PINCTRL_NONE    /* PA5 periph A LCDD5 pin */
-                                                        AT91_PIOA 6 AT91_PERIPH_A AT91_PINCTRL_NONE    /* PA6 periph A LCDD6 pin */
-                                                        AT91_PIOA 7 AT91_PERIPH_A AT91_PINCTRL_NONE    /* PA7 periph A LCDD7 pin */
-                                                        AT91_PIOA 8 AT91_PERIPH_A AT91_PINCTRL_NONE    /* PA8 periph A LCDD8 pin */
-                                                        AT91_PIOA 9 AT91_PERIPH_A AT91_PINCTRL_NONE    /* PA9 periph A LCDD9 pin */
-                                                        AT91_PIOA 10 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PA10 periph A LCDD10 pin */
-                                                        AT91_PIOA 11 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PA11 periph A LCDD11 pin */
-                                                        AT91_PIOA 12 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PA12 periph A LCDD12 pin */
-                                                        AT91_PIOA 13 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PA13 periph A LCDD13 pin */
-                                                        AT91_PIOA 14 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PA14 periph A LCDD14 pin */
-                                                        AT91_PIOA 15 AT91_PERIPH_A AT91_PINCTRL_NONE   /* PA15 periph A LCDD15 pin */
-                                                        AT91_PIOC 14 AT91_PERIPH_C AT91_PINCTRL_NONE   /* PC14 periph C LCDD16 pin */
-                                                        AT91_PIOC 13 AT91_PERIPH_C AT91_PINCTRL_NONE   /* PC13 periph C LCDD17 pin */
-                                                        AT91_PIOC 12 AT91_PERIPH_C AT91_PINCTRL_NONE   /* PC12 periph C LCDD18 pin */
-                                                        AT91_PIOC 11 AT91_PERIPH_C AT91_PINCTRL_NONE   /* PC11 periph C LCDD19 pin */
-                                                        AT91_PIOC 10 AT91_PERIPH_C AT91_PINCTRL_NONE   /* PC10 periph C LCDD20 pin */
-                                                        AT91_PIOC 15 AT91_PERIPH_C AT91_PINCTRL_NONE   /* PC15 periph C LCDD21 pin */
-                                                        AT91_PIOE 27 AT91_PERIPH_C AT91_PINCTRL_NONE   /* PE27 periph C LCDD22 pin */
-                                                        AT91_PIOE 28 AT91_PERIPH_C AT91_PINCTRL_NONE>; /* PE28 periph C LCDD23 pin */
+                                                       <AT91_PIOA 0 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD0 pin */
+                                                        AT91_PIOA 1 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD1 pin */
+                                                        AT91_PIOA 2 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD2 pin */
+                                                        AT91_PIOA 3 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD3 pin */
+                                                        AT91_PIOA 4 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD4 pin */
+                                                        AT91_PIOA 5 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD5 pin */
+                                                        AT91_PIOA 6 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD6 pin */
+                                                        AT91_PIOA 7 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD7 pin */
+                                                        AT91_PIOA 8 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD8 pin */
+                                                        AT91_PIOA 9 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD9 pin */
+                                                        AT91_PIOA 10 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD10 pin */
+                                                        AT91_PIOA 11 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD11 pin */
+                                                        AT91_PIOA 12 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD12 pin */
+                                                        AT91_PIOA 13 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD13 pin */
+                                                        AT91_PIOA 14 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD14 pin */
+                                                        AT91_PIOA 15 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD15 pin */
+                                                        AT91_PIOC 14 AT91_PERIPH_C AT91_PINCTRL_NONE   /* LCDD16 pin */
+                                                        AT91_PIOC 13 AT91_PERIPH_C AT91_PINCTRL_NONE   /* LCDD17 pin */
+                                                        AT91_PIOC 12 AT91_PERIPH_C AT91_PINCTRL_NONE   /* LCDD18 pin */
+                                                        AT91_PIOC 11 AT91_PERIPH_C AT91_PINCTRL_NONE   /* LCDD19 pin */
+                                                        AT91_PIOC 10 AT91_PERIPH_C AT91_PINCTRL_NONE   /* LCDD20 pin */
+                                                        AT91_PIOC 15 AT91_PERIPH_C AT91_PINCTRL_NONE   /* LCDD21 pin */
+                                                        AT91_PIOE 27 AT91_PERIPH_C AT91_PINCTRL_NONE   /* LCDD22 pin */
+                                                        AT91_PIOE 28 AT91_PERIPH_C AT91_PINCTRL_NONE>; /* LCDD23 pin */
                                        };
                                };
                        };
index 1b02208ea6ff2b70aab43ddd416b37ef0b9a2a1f..026b252f09b3e6b2db4b6310fe19969f3332798e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * at91sama5d3_mci2.dtsi - Device Tree Include file for AT91SAM9x5 SoC with
+ * sama5d3_mci2.dtsi - Device Tree Include file for SAMA5D3 SoC with
  * 3 MMC ports
  *
  * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
index 02848453ca0cf5447de27aaca6b233611173da4e..f7fa58fe09f1553eff94f61b2d3f38113ad95c7b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * at91sama5d3_tcb1.dtsi - Device Tree Include file for AT91SAM9x5 SoC with
+ * sama5d3_tcb1.dtsi - Device Tree Include file for SAMA5D3 SoC with
  * 2 TC blocks.
  *
  * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
index 7a8d4c6115f72fdab533980a0f0d96eb6cb1469a..2511d748867bdd17fc3e08140b69ba5f61b594d7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * at91sama5d3_uart.dtsi - Device Tree Include file for AT91SAM9x5 SoC with
+ * sama5d3_uart.dtsi - Device Tree Include file for SAMA5D3 SoC with
  * UART support
  *
  * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
index 4303874889c69954fa894ff458bb9bfb492f33d4..6b1bb58f9c0b609fdb3622a02c89d2d394750c81 100644 (file)
                gpio2 = &pioC;
                gpio3 = &pioD;
                gpio4 = &pioE;
+               pwm0 = &pwm0;
+               ssc0 = &ssc0;
+               ssc1 = &ssc1;
                tcb0 = &tcb0;
                tcb1 = &tcb1;
                i2c0 = &i2c0;
+               i2c1 = &i2c1;
                i2c2 = &i2c2;
        };
        cpus {
                        #size-cells = <1>;
                        ranges;
 
+                       hlcdc: hlcdc@f0000000 {
+                               compatible = "atmel,sama5d4-hlcdc";
+                               reg = <0xf0000000 0x4000>;
+                               interrupts = <51 IRQ_TYPE_LEVEL_HIGH 0>;
+                               clocks = <&lcdc_clk>, <&lcdck>, <&clk32k>;
+                               clock-names = "periph_clk","sys_clk", "slow_clk";
+                               status = "disabled";
+
+                               hlcdc-display-controller {
+                                       compatible = "atmel,hlcdc-display-controller";
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+
+                                       port@0 {
+                                               #address-cells = <1>;
+                                               #size-cells = <0>;
+                                               reg = <0>;
+                                       };
+                               };
+
+                               hlcdc_pwm: hlcdc-pwm {
+                                       compatible = "atmel,hlcdc-pwm";
+                                       pinctrl-names = "default";
+                                       pinctrl-0 = <&pinctrl_lcd_pwm>;
+                                       #pwm-cells = <3>;
+                               };
+                       };
+
                        dma1: dma-controller@f0004000 {
                                compatible = "atmel,sama5d4-dma";
                                reg = <0xf0004000 0x200>;
                                clock-names = "dma_clk";
                        };
 
+                       isi: isi@f0008000 {
+                               compatible = "atmel,at91sam9g45-isi";
+                               reg = <0xf0008000 0x4000>;
+                               interrupts = <52 IRQ_TYPE_LEVEL_HIGH 5>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_isi_data_0_7>;
+                               clocks = <&isi_clk>;
+                               clock-names = "isi_clk";
+                               status = "disabled";
+                               port {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                               };
+                       };
+
                        ramc0: ramc@f0010000 {
                                compatible = "atmel,sama5d3-ddramc";
                                reg = <0xf0010000 0x200>;
                                clock-names = "mci_clk";
                        };
 
+                       ssc0: ssc@f8008000 {
+                               compatible = "atmel,at91sam9g45-ssc";
+                               reg = <0xf8008000 0x4000>;
+                               interrupts = <48 IRQ_TYPE_LEVEL_HIGH 0>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>;
+                               dmas = <&dma1
+                                       (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1)
+                                       | AT91_XDMAC_DT_PERID(26))>,
+                                      <&dma1
+                                       (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1)
+                                       | AT91_XDMAC_DT_PERID(27))>;
+                               dma-names = "tx", "rx";
+                               clocks = <&ssc0_clk>;
+                               clock-names = "pclk";
+                               status = "disabled";
+                       };
+
+                       pwm0: pwm@f800c000 {
+                               compatible = "atmel,sama5d3-pwm";
+                               reg = <0xf800c000 0x300>;
+                               interrupts = <43 IRQ_TYPE_LEVEL_HIGH 4>;
+                               #pwm-cells = <3>;
+                               clocks = <&pwm_clk>;
+                               status = "disabled";
+                       };
+
                        spi0: spi@f8010000 {
                                #address-cells = <1>;
                                #size-cells = <0>;
                                status = "disabled";
                        };
 
+                       i2c1: i2c@f8018000 {
+                               compatible = "atmel,at91sam9x5-i2c";
+                               reg = <0xf8018000 0x4000>;
+                               interrupts = <33 IRQ_TYPE_LEVEL_HIGH 6>;
+                               dmas = <&dma1
+                                       (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1))
+                                       AT91_XDMAC_DT_PERID(4)>,
+                                      <&dma1
+                                       (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1))
+                                       AT91_XDMAC_DT_PERID(5)>;
+                               dma-names = "tx", "rx";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_i2c1>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               clocks = <&twi1_clk>;
+                               status = "disabled";
+                       };
+
                        tcb0: timer@f801c000 {
                                compatible = "atmel,at91sam9x5-tcb";
                                reg = <0xf801c000 0x100>;
                                interrupts = <54 IRQ_TYPE_LEVEL_HIGH 3>;
                                pinctrl-names = "default";
                                pinctrl-0 = <&pinctrl_macb0_rmii>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
                                clocks = <&macb0_clk>, <&macb0_clk>;
                                clock-names = "hclk", "pclk";
                                status = "disabled";
                                status = "disabled";
                        };
 
+                       ssc1: ssc@fc014000 {
+                               compatible = "atmel,at91sam9g45-ssc";
+                               reg = <0xfc014000 0x4000>;
+                               interrupts = <49 IRQ_TYPE_LEVEL_HIGH 0>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_ssc1_tx &pinctrl_ssc1_rx>;
+                               dmas = <&dma1
+                                       (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1)
+                                       | AT91_XDMAC_DT_PERID(28))>,
+                                      <&dma1
+                                       (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1)
+                                       | AT91_XDMAC_DT_PERID(29))>;
+                               dma-names = "tx", "rx";
+                               clocks = <&ssc1_clk>;
+                               clock-names = "pclk";
+                               status = "disabled";
+                       };
+
                        tcb1: timer@fc020000 {
                                compatible = "atmel,at91sam9x5-tcb";
                                reg = <0xfc020000 0x100>;
                                };
                        };
 
+                       aes@fc044000 {
+                               compatible = "atmel,at91sam9g46-aes";
+                               reg = <0xfc044000 0x100>;
+                               interrupts = <12 IRQ_TYPE_LEVEL_HIGH 0>;
+                               dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1))
+                                       AT91_XDMAC_DT_PERID(41)>,
+                                      <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1))
+                                       AT91_XDMAC_DT_PERID(40)>;
+                               dma-names = "tx", "rx";
+                               clocks = <&aes_clk>;
+                               clock-names = "aes_clk";
+                               status = "disabled";
+                       };
+
+                       tdes@fc04c000 {
+                               compatible = "atmel,at91sam9g46-tdes";
+                               reg = <0xfc04c000 0x100>;
+                               interrupts = <14 IRQ_TYPE_LEVEL_HIGH 0>;
+                               dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1))
+                                       AT91_XDMAC_DT_PERID(42)>,
+                                      <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1))
+                                       AT91_XDMAC_DT_PERID(43)>;
+                               dma-names = "tx", "rx";
+                               clocks = <&tdes_clk>;
+                               clock-names = "tdes_clk";
+                               status = "disabled";
+                       };
+
+                       sha@fc050000 {
+                               compatible = "atmel,at91sam9g46-sha";
+                               reg = <0xfc050000 0x100>;
+                               interrupts = <15 IRQ_TYPE_LEVEL_HIGH 0>;
+                               dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1))
+                                       AT91_XDMAC_DT_PERID(44)>;
+                               dma-names = "tx";
+                               clocks = <&sha_clk>;
+                               clock-names = "sha_clk";
+                               status = "disabled";
+                       };
+
                        rstc@fc068600 {
                                compatible = "atmel,at91sam9g45-rstc";
                                reg = <0xfc068600 0x10>;
                        };
 
                        dbgu: serial@fc069000 {
-                               compatible = "atmel,at91sam9260-usart";
+                               compatible = "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
                                reg = <0xfc069000 0x200>;
                                interrupts = <2 IRQ_TYPE_LEVEL_HIGH 7>;
                                pinctrl-names = "default";
                                        };
                                };
 
+                               i2c1 {
+                                       pinctrl_i2c1: i2c1-0 {
+                                               atmel,pins =
+                                                       <AT91_PIOE 29 AT91_PERIPH_C AT91_PINCTRL_NONE   /* TWD1, conflicts with UART0 RX and DIBP */
+                                                        AT91_PIOE 30 AT91_PERIPH_C AT91_PINCTRL_NONE>; /* TWCK1, conflicts with UART0 TX and DIBN */
+                                       };
+                               };
+
                                i2c2 {
                                        pinctrl_i2c2: i2c2-0 {
                                                atmel,pins =
                                        };
                                };
 
+                               isi {
+                                       pinctrl_isi_data_0_7: isi-0-data-0-7 {
+                                               atmel,pins =
+                                                       <AT91_PIOC 19 AT91_PERIPH_A AT91_PINCTRL_NONE   /* ISI_D0 */
+                                                        AT91_PIOC 20 AT91_PERIPH_A AT91_PINCTRL_NONE   /* ISI_D1 */
+                                                        AT91_PIOC 21 AT91_PERIPH_A AT91_PINCTRL_NONE   /* ISI_D2 */
+                                                        AT91_PIOC 22 AT91_PERIPH_A AT91_PINCTRL_NONE   /* ISI_D3 */
+                                                        AT91_PIOC 23 AT91_PERIPH_A AT91_PINCTRL_NONE   /* ISI_D4 */
+                                                        AT91_PIOC 24 AT91_PERIPH_A AT91_PINCTRL_NONE   /* ISI_D5 */
+                                                        AT91_PIOC 25 AT91_PERIPH_A AT91_PINCTRL_NONE   /* ISI_D6 */
+                                                        AT91_PIOC 26 AT91_PERIPH_A AT91_PINCTRL_NONE   /* ISI_D7 */
+                                                        AT91_PIOB  1 AT91_PERIPH_C AT91_PINCTRL_NONE   /* ISI_PCK, conflict with G0_RXCK */
+                                                        AT91_PIOB  3 AT91_PERIPH_C AT91_PINCTRL_NONE   /* ISI_VSYNC */
+                                                        AT91_PIOB  4 AT91_PERIPH_C AT91_PINCTRL_NONE>; /* ISI_HSYNC */
+                                       };
+                                       pinctrl_isi_data_8_9: isi-0-data-8-9 {
+                                               atmel,pins =
+                                                       <AT91_PIOC 0 AT91_PERIPH_C AT91_PINCTRL_NONE    /* ISI_D8, conflicts with SPI0_MISO, PWMH2 */
+                                                        AT91_PIOC 1 AT91_PERIPH_C AT91_PINCTRL_NONE>;  /* ISI_D9, conflicts with SPI0_MOSI, PWML2 */
+                                       };
+                                       pinctrl_isi_data_10_11: isi-0-data-10-11 {
+                                               atmel,pins =
+                                                       <AT91_PIOC 2 AT91_PERIPH_C AT91_PINCTRL_NONE    /* ISI_D10, conflicts with SPI0_SPCK, PWMH3 */
+                                                        AT91_PIOC 3 AT91_PERIPH_C AT91_PINCTRL_NONE>;  /* ISI_D11, conflicts with SPI0_NPCS0, PWML3 */
+                                       };
+                               };
+
+                               lcd {
+                                       pinctrl_lcd_base: lcd-base-0 {
+                                               atmel,pins =
+                                                       <AT91_PIOA 26 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDVSYNC */
+                                                        AT91_PIOA 27 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDHSYNC */
+                                                        AT91_PIOA 29 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDDEN */
+                                                        AT91_PIOA 28 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* LCDPCK */
+                                       };
+                                       pinctrl_lcd_pwm: lcd-pwm-0 {
+                                               atmel,pins = <AT91_PIOA 24 AT91_PERIPH_A AT91_PINCTRL_NONE>;    /* LCDPWM */
+                                       };
+                                       pinctrl_lcd_rgb444: lcd-rgb-0 {
+                                               atmel,pins =
+                                                       <AT91_PIOA 0 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD0 pin */
+                                                        AT91_PIOA 1 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD1 pin */
+                                                        AT91_PIOA 2 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD2 pin */
+                                                        AT91_PIOA 3 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD3 pin */
+                                                        AT91_PIOA 4 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD4 pin */
+                                                        AT91_PIOA 5 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD5 pin */
+                                                        AT91_PIOA 6 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD6 pin */
+                                                        AT91_PIOA 7 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD7 pin */
+                                                        AT91_PIOA 8 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD8 pin */
+                                                        AT91_PIOA 9 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD9 pin */
+                                                        AT91_PIOA 10 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD10 pin */
+                                                        AT91_PIOA 11 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* LCDD11 pin */
+                                       };
+                                       pinctrl_lcd_rgb565: lcd-rgb-1 {
+                                               atmel,pins =
+                                                       <AT91_PIOA 0 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD0 pin */
+                                                        AT91_PIOA 1 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD1 pin */
+                                                        AT91_PIOA 2 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD2 pin */
+                                                        AT91_PIOA 3 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD3 pin */
+                                                        AT91_PIOA 4 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD4 pin */
+                                                        AT91_PIOA 5 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD5 pin */
+                                                        AT91_PIOA 6 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD6 pin */
+                                                        AT91_PIOA 7 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD7 pin */
+                                                        AT91_PIOA 8 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD8 pin */
+                                                        AT91_PIOA 9 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD9 pin */
+                                                        AT91_PIOA 10 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD10 pin */
+                                                        AT91_PIOA 11 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD11 pin */
+                                                        AT91_PIOA 12 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD12 pin */
+                                                        AT91_PIOA 13 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD13 pin */
+                                                        AT91_PIOA 14 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD14 pin */
+                                                        AT91_PIOA 15 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* LCDD15 pin */
+                                       };
+                                       pinctrl_lcd_rgb666: lcd-rgb-2 {
+                                               atmel,pins =
+                                                       <AT91_PIOA 2 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD2 pin */
+                                                        AT91_PIOA 3 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD3 pin */
+                                                        AT91_PIOA 4 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD4 pin */
+                                                        AT91_PIOA 5 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD5 pin */
+                                                        AT91_PIOA 6 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD6 pin */
+                                                        AT91_PIOA 7 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD7 pin */
+                                                        AT91_PIOA 10 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD10 pin */
+                                                        AT91_PIOA 11 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD11 pin */
+                                                        AT91_PIOA 12 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD12 pin */
+                                                        AT91_PIOA 13 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD13 pin */
+                                                        AT91_PIOA 14 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD14 pin */
+                                                        AT91_PIOA 15 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD15 pin */
+                                                        AT91_PIOA 18 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD18 pin */
+                                                        AT91_PIOA 19 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD19 pin */
+                                                        AT91_PIOA 20 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD20 pin */
+                                                        AT91_PIOA 21 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD21 pin */
+                                                        AT91_PIOA 22 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD22 pin */
+                                                        AT91_PIOA 23 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* LCDD23 pin */
+                                       };
+                                       pinctrl_lcd_rgb777: lcd-rgb-3 {
+                                               atmel,pins =
+                                                        /* LCDDAT0 conflicts with TMS */
+                                                       <AT91_PIOA 1 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD1 pin */
+                                                        AT91_PIOA 2 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD2 pin */
+                                                        AT91_PIOA 3 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD3 pin */
+                                                        AT91_PIOA 4 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD4 pin */
+                                                        AT91_PIOA 5 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD5 pin */
+                                                        AT91_PIOA 6 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD6 pin */
+                                                        AT91_PIOA 7 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD7 pin */
+                                                        /* LCDDAT8 conflicts with TCK */
+                                                        AT91_PIOA 9 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD9 pin */
+                                                        AT91_PIOA 10 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD10 pin */
+                                                        AT91_PIOA 11 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD11 pin */
+                                                        AT91_PIOA 12 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD12 pin */
+                                                        AT91_PIOA 13 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD13 pin */
+                                                        AT91_PIOA 14 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD14 pin */
+                                                        AT91_PIOA 15 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD15 pin */
+                                                        /* LCDDAT16 conflicts with NTRST */
+                                                        AT91_PIOA 17 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD17 pin */
+                                                        AT91_PIOA 18 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD18 pin */
+                                                        AT91_PIOA 19 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD19 pin */
+                                                        AT91_PIOA 20 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD20 pin */
+                                                        AT91_PIOA 21 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD21 pin */
+                                                        AT91_PIOA 22 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD22 pin */
+                                                        AT91_PIOA 23 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* LCDD23 pin */
+                                       };
+                                       pinctrl_lcd_rgb888: lcd-rgb-4 {
+                                               atmel,pins =
+                                                       <AT91_PIOA 0 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD0 pin */
+                                                        AT91_PIOA 1 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD1 pin */
+                                                        AT91_PIOA 2 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD2 pin */
+                                                        AT91_PIOA 3 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD3 pin */
+                                                        AT91_PIOA 4 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD4 pin */
+                                                        AT91_PIOA 5 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD5 pin */
+                                                        AT91_PIOA 6 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD6 pin */
+                                                        AT91_PIOA 7 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD7 pin */
+                                                        AT91_PIOA 8 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD8 pin */
+                                                        AT91_PIOA 9 AT91_PERIPH_A AT91_PINCTRL_NONE    /* LCDD9 pin */
+                                                        AT91_PIOA 10 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD10 pin */
+                                                        AT91_PIOA 11 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD11 pin */
+                                                        AT91_PIOA 12 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD12 pin */
+                                                        AT91_PIOA 13 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD13 pin */
+                                                        AT91_PIOA 14 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD14 pin */
+                                                        AT91_PIOA 15 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD15 pin */
+                                                        AT91_PIOA 16 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD16 pin */
+                                                        AT91_PIOA 17 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD17 pin */
+                                                        AT91_PIOA 18 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD18 pin */
+                                                        AT91_PIOA 19 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD19 pin */
+                                                        AT91_PIOA 20 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD20 pin */
+                                                        AT91_PIOA 21 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD21 pin */
+                                                        AT91_PIOA 22 AT91_PERIPH_A AT91_PINCTRL_NONE   /* LCDD22 pin */
+                                                        AT91_PIOA 23 AT91_PERIPH_A AT91_PINCTRL_NONE>; /* LCDD23 pin */
+                                       };
+                               };
+
                                macb0 {
                                        pinctrl_macb0_rmii: macb0_rmii-0 {
                                                atmel,pins =
                                        };
                                };
 
+                               ssc0 {
+                                       pinctrl_ssc0_tx: ssc0_tx {
+                                               atmel,pins =
+                                                       <AT91_PIOB 27 AT91_PERIPH_B AT91_PINCTRL_NONE   /* TK0 */
+                                                        AT91_PIOB 31 AT91_PERIPH_B AT91_PINCTRL_NONE   /* TF0 */
+                                                        AT91_PIOB 28 AT91_PERIPH_B AT91_PINCTRL_NONE>; /* TD0 */
+                                       };
+
+                                       pinctrl_ssc0_rx: ssc0_rx {
+                                               atmel,pins =
+                                                       <AT91_PIOB 26 AT91_PERIPH_B AT91_PINCTRL_NONE   /* RK0 */
+                                                        AT91_PIOB 30 AT91_PERIPH_B AT91_PINCTRL_NONE   /* RF0 */
+                                                        AT91_PIOB 29 AT91_PERIPH_B AT91_PINCTRL_NONE>; /* RD0 */
+                                       };
+                               };
+
+                               ssc1 {
+                                       pinctrl_ssc1_tx: ssc1_tx {
+                                               atmel,pins =
+                                                       <AT91_PIOC 19 AT91_PERIPH_B AT91_PINCTRL_NONE   /* TK1 */
+                                                        AT91_PIOC 20 AT91_PERIPH_B AT91_PINCTRL_NONE   /* TF1 */
+                                                        AT91_PIOC 21 AT91_PERIPH_B AT91_PINCTRL_NONE>; /* TD1 */
+                                       };
+
+                                       pinctrl_ssc1_rx: ssc1_rx {
+                                               atmel,pins =
+                                                       <AT91_PIOC 24 AT91_PERIPH_B AT91_PINCTRL_NONE   /* RK1 */
+                                                        AT91_PIOC 22 AT91_PERIPH_B AT91_PINCTRL_NONE   /* RF1 */
+                                                        AT91_PIOC 23 AT91_PERIPH_B AT91_PINCTRL_NONE>; /* RD1 */
+                                       };
+                               };
+
                                usart2 {
                                        pinctrl_usart2: usart2-0 {
                                                atmel,pins =
diff --git a/arch/arm/boot/dts/sh7372-mackerel.dts b/arch/arm/boot/dts/sh7372-mackerel.dts
deleted file mode 100644 (file)
index a759a27..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Device Tree Source for the mackerel 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/;
-#include "sh7372.dtsi"
-
-/ {
-       model = "Mackerel (AP4 EVM 2nd)";
-       compatible = "renesas,mackerel";
-
-       chosen {
-               bootargs = "console=tty0, console=ttySC0,115200 earlyprintk=sh-sci.0,115200 root=/dev/nfs nfsroot=,tcp,v3 ip=dhcp mem=240m rw";
-       };
-
-       memory {
-               device_type = "memory";
-               reg = <0x40000000 0x10000000>;
-       };
-};
diff --git a/arch/arm/boot/dts/sh7372.dtsi b/arch/arm/boot/dts/sh7372.dtsi
deleted file mode 100644 (file)
index f863a10..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Device Tree Source for the sh7372 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/ "skeleton.dtsi"
-
-/ {
-       compatible = "renesas,sh7372";
-
-       cpus {
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               cpu@0 {
-                       compatible = "arm,cortex-a8";
-                       device_type = "cpu";
-                       reg = <0x0>;
-                       clock-frequency = <800000000>;
-               };
-       };
-
-       pfc: pfc@e6050000 {
-               compatible = "renesas,pfc-sh7372";
-               reg = <0xe6050000 0x8000>,
-                     <0xe605801c 0x1c>;
-               gpio-controller;
-               #gpio-cells = <2>;
-       };
-};
diff --git a/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts b/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts
deleted file mode 100644 (file)
index 6d32c87..0000000
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- * Device Tree Source for the KZM-A9-GT board
- *
- * Copyright (C) 2012 Horms Solutions Ltd.
- *
- * 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/;
-#include "sh73a0.dtsi"
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/input/input.h>
-#include <dt-bindings/interrupt-controller/irq.h>
-
-/ {
-       model = "KZM-A9-GT";
-       compatible = "renesas,kzm9g-reference", "renesas,sh73a0";
-
-       aliases {
-               serial4 = &scifa4;
-       };
-
-       cpus {
-               cpu@0 {
-                       cpu0-supply = <&vdd_dvfs>;
-                       operating-points = <
-                               /* kHz  uV */
-                               1196000 1315000
-                                598000 1175000
-                                398667 1065000
-                       >;
-                       voltage-tolerance = <1>; /* 1% */
-               };
-       };
-
-       chosen {
-               bootargs = "console=tty0 console=ttySC4,115200 root=/dev/nfs ip=dhcp ignore_loglevel rw";
-               stdout-path = &scifa4;
-       };
-
-       memory {
-               device_type = "memory";
-               reg = <0x41000000 0x1e800000>;
-       };
-
-       reg_1p8v: regulator@0 {
-               compatible = "regulator-fixed";
-               regulator-name = "fixed-1.8V";
-               regulator-min-microvolt = <1800000>;
-               regulator-max-microvolt = <1800000>;
-               regulator-always-on;
-               regulator-boot-on;
-       };
-
-       reg_3p3v: regulator@1 {
-               compatible = "regulator-fixed";
-               regulator-name = "fixed-3.3V";
-               regulator-min-microvolt = <3300000>;
-               regulator-max-microvolt = <3300000>;
-               regulator-always-on;
-               regulator-boot-on;
-       };
-
-       vmmc_sdhi0: regulator@2 {
-               compatible = "regulator-fixed";
-               regulator-name = "SDHI0 Vcc";
-               regulator-min-microvolt = <3300000>;
-               regulator-max-microvolt = <3300000>;
-               gpio = <&pfc 15 GPIO_ACTIVE_HIGH>;
-               enable-active-high;
-       };
-
-       vmmc_sdhi2: regulator@3 {
-               compatible = "regulator-fixed";
-               regulator-name = "SDHI2 Vcc";
-               regulator-min-microvolt = <3300000>;
-               regulator-max-microvolt = <3300000>;
-               gpio = <&pfc 14 GPIO_ACTIVE_HIGH>;
-               enable-active-high;
-       };
-
-       lan9220@10000000 {
-               compatible = "smsc,lan9220", "smsc,lan9115";
-               reg = <0x10000000 0x100>;
-               phy-mode = "mii";
-               interrupt-parent = <&irqpin0>;
-               interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
-               reg-io-width = <4>;
-               smsc,irq-push-pull;
-               smsc,save-mac-address;
-               vddvario-supply = <&reg_1p8v>;
-               vdd33a-supply = <&reg_3p3v>;
-       };
-
-       leds {
-               compatible = "gpio-leds";
-               led1 {
-                       gpios = <&pfc 20 GPIO_ACTIVE_LOW>;
-                       label = "LED1";
-               };
-               led2 {
-                       gpios = <&pfc 21 GPIO_ACTIVE_LOW>;
-                       label = "LED2";
-               };
-               led3 {
-                       gpios = <&pfc 22 GPIO_ACTIVE_LOW>;
-                       label = "LED3";
-               };
-               led4 {
-                       gpios = <&pfc 23 GPIO_ACTIVE_LOW>;
-                       label = "LED4";
-               };
-       };
-
-       keyboard {
-               compatible = "gpio-keys";
-
-               back-key {
-                       gpios = <&pcf8575 8 GPIO_ACTIVE_LOW>;
-                       linux,code = <KEY_BACK>;
-                       label = "SW3";
-               };
-
-               right-key {
-                       gpios = <&pcf8575 9 GPIO_ACTIVE_LOW>;
-                       linux,code = <KEY_RIGHT>;
-                       label = "SW2-R";
-               };
-
-               left-key {
-                       gpios = <&pcf8575 10 GPIO_ACTIVE_LOW>;
-                       linux,code = <KEY_LEFT>;
-                       label = "SW2-L";
-               };
-
-               enter-key {
-                       gpios = <&pcf8575 11 GPIO_ACTIVE_LOW>;
-                       linux,code = <KEY_ENTER>;
-                       label = "SW2-P";
-               };
-
-               up-key {
-                       gpios = <&pcf8575 12 GPIO_ACTIVE_LOW>;
-                       linux,code = <KEY_UP>;
-                       label = "SW2-U";
-               };
-
-               down-key {
-                       gpios = <&pcf8575 13 GPIO_ACTIVE_LOW>;
-                       linux,code = <KEY_DOWN>;
-                       label = "SW2-D";
-               };
-
-               home-key {
-                       gpios = <&pcf8575 14 GPIO_ACTIVE_LOW>;
-                       linux,code = <KEY_HOME>;
-                       label = "SW1";
-               };
-       };
-
-       sound {
-               compatible = "simple-audio-card";
-               simple-audio-card,format = "left_j";
-               simple-audio-card,cpu {
-                       sound-dai = <&sh_fsi2 0>;
-               };
-               simple-audio-card,codec {
-                       sound-dai = <&ak4648>;
-                       bitclock-master;
-                       frame-master;
-                       system-clock-frequency = <11289600>;
-               };
-       };
-};
-
-&cmt1 {
-       status = "okay";
-};
-
-&extal2_clk {
-       clock-frequency = <48000000>;
-};
-
-&i2c0 {
-       status = "okay";
-       as3711@40 {
-               compatible = "ams,as3711";
-               reg = <0x40>;
-
-               regulators {
-                       vdd_dvfs: sd1 {
-                               regulator-name = "1.315V CPU";
-                               regulator-min-microvolt = <1050000>;
-                               regulator-max-microvolt = <1350000>;
-                               regulator-always-on;
-                               regulator-boot-on;
-                       };
-                       sd2 {
-                               regulator-name = "1.8V";
-                               regulator-min-microvolt = <1800000>;
-                               regulator-max-microvolt = <1800000>;
-                               regulator-always-on;
-                               regulator-boot-on;
-                       };
-                       sd4 {
-                               regulator-name = "1.215V";
-                               regulator-min-microvolt = <1215000>;
-                               regulator-max-microvolt = <1235000>;
-                               regulator-always-on;
-                               regulator-boot-on;
-                       };
-                       ldo2 {
-                               regulator-name = "2.8V CPU";
-                               regulator-min-microvolt = <2800000>;
-                               regulator-max-microvolt = <2800000>;
-                               regulator-always-on;
-                               regulator-boot-on;
-                       };
-                       ldo3 {
-                               regulator-name = "3.0V CPU";
-                               regulator-min-microvolt = <3000000>;
-                               regulator-max-microvolt = <3000000>;
-                               regulator-always-on;
-                               regulator-boot-on;
-                       };
-                       ldo4 {
-                               regulator-name = "2.8V";
-                               regulator-min-microvolt = <2800000>;
-                               regulator-max-microvolt = <2800000>;
-                               regulator-always-on;
-                               regulator-boot-on;
-                       };
-                       ldo5 {
-                               regulator-name = "2.8V #2";
-                               regulator-min-microvolt = <2800000>;
-                               regulator-max-microvolt = <2800000>;
-                               regulator-always-on;
-                               regulator-boot-on;
-                       };
-                       ldo7 {
-                               regulator-name = "1.15V CPU";
-                               regulator-min-microvolt = <1150000>;
-                               regulator-max-microvolt = <1150000>;
-                               regulator-always-on;
-                               regulator-boot-on;
-                       };
-                       ldo8 {
-                               regulator-name = "1.15V CPU #2";
-                               regulator-min-microvolt = <1150000>;
-                               regulator-max-microvolt = <1150000>;
-                               regulator-always-on;
-                               regulator-boot-on;
-                       };
-               };
-       };
-
-       ak4648: ak4648@12 {
-               #sound-dai-cells = <0>;
-               compatible = "asahi-kasei,ak4648";
-               reg = <0x12>;
-       };
-};
-
-&i2c3 {
-       pinctrl-0 = <&i2c3_pins>;
-       pinctrl-names = "default";
-       status = "okay";
-
-       pcf8575: gpio@20 {
-               compatible = "nxp,pcf8575";
-               reg = <0x20>;
-               interrupt-parent = <&irqpin2>;
-               interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
-               gpio-controller;
-               #gpio-cells = <2>;
-               interrupt-controller;
-               #interrupt-cells = <2>;
-       };
-};
-
-&mmcif {
-       pinctrl-0 = <&mmcif_pins>;
-       pinctrl-names = "default";
-
-       bus-width = <8>;
-       vmmc-supply = <&reg_1p8v>;
-       status = "okay";
-};
-
-&pfc {
-       i2c3_pins: i2c3 {
-               renesas,groups = "i2c3_1";
-               renesas,function = "i2c3";
-       };
-
-       mmcif_pins: mmc {
-               mux {
-                       renesas,groups = "mmc0_data8_0", "mmc0_ctrl_0";
-                       renesas,function = "mmc0";
-               };
-               cfg {
-                       renesas,groups = "mmc0_data8_0";
-                       renesas,pins = "PORT279";
-                       bias-pull-up;
-               };
-       };
-
-       scifa4_pins: serial4 {
-               renesas,groups = "scifa4_data", "scifa4_ctrl";
-               renesas,function = "scifa4";
-       };
-
-       sdhi0_pins: sd0 {
-               renesas,groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_cd", "sdhi0_wp";
-               renesas,function = "sdhi0";
-       };
-
-       sdhi2_pins: sd2 {
-               renesas,groups = "sdhi2_data4", "sdhi2_ctrl";
-               renesas,function = "sdhi2";
-       };
-
-       fsia_pins: sounda {
-               renesas,groups = "fsia_mclk_in", "fsia_sclk_in",
-                                "fsia_data_in", "fsia_data_out";
-               renesas,function = "fsia";
-       };
-};
-
-&scifa4 {
-       pinctrl-0 = <&scifa4_pins>;
-       pinctrl-names = "default";
-
-       status = "okay";
-};
-
-&sdhi0 {
-       pinctrl-0 = <&sdhi0_pins>;
-       pinctrl-names = "default";
-
-       vmmc-supply = <&vmmc_sdhi0>;
-       bus-width = <4>;
-       status = "okay";
-};
-
-&sdhi2 {
-       pinctrl-0 = <&sdhi2_pins>;
-       pinctrl-names = "default";
-
-       vmmc-supply = <&vmmc_sdhi2>;
-       bus-width = <4>;
-       broken-cd;
-       status = "okay";
-};
-
-&sh_fsi2 {
-       pinctrl-0 = <&fsia_pins>;
-       pinctrl-names = "default";
-
-       status = "okay";
-};
index 27c5f426d172f03d53801875ec5a5293c4f45b88..022ba505f57339a959d8208732eeb75e585911d4 100644 (file)
@@ -1,6 +1,9 @@
 /*
  * Device Tree Source for the KZM-A9-GT board
  *
+ * Copyright (C) 2012 Horms Solutions Ltd.
+ *
+ * Based on sh73a0-kzm9g.dts
  * Copyright (C) 2012 Renesas Solutions Corp.
  *
  * This file is licensed under the terms of the GNU General Public License
 
 /dts-v1/;
 #include "sh73a0.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
 
 / {
        model = "KZM-A9-GT";
        compatible = "renesas,kzm9g", "renesas,sh73a0";
 
+       aliases {
+               serial4 = &scifa4;
+       };
+
+       cpus {
+               cpu@0 {
+                       cpu0-supply = <&vdd_dvfs>;
+                       operating-points = <
+                               /* kHz  uV */
+                               1196000 1315000
+                                598000 1175000
+                                398667 1065000
+                       >;
+                       voltage-tolerance = <1>; /* 1% */
+               };
+       };
+
        chosen {
-               bootargs = "console=tty0 console=ttySC4,115200 root=/dev/nfs ip=dhcp ignore_loglevel earlyprintk=sh-sci.4,115200 rw";
+               bootargs = "console=tty0 console=ttySC4,115200 root=/dev/nfs ip=dhcp ignore_loglevel rw";
+               stdout-path = &scifa4;
        };
 
        memory {
                device_type = "memory";
-               reg = <0x41000000 0x1e800000>;
+               reg = <0x40000000 0x20000000>;
+       };
+
+       reg_1p8v: regulator@0 {
+               compatible = "regulator-fixed";
+               regulator-name = "fixed-1.8V";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               regulator-always-on;
+               regulator-boot-on;
+       };
+
+       reg_3p3v: regulator@1 {
+               compatible = "regulator-fixed";
+               regulator-name = "fixed-3.3V";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
+               regulator-boot-on;
+       };
+
+       vmmc_sdhi0: regulator@2 {
+               compatible = "regulator-fixed";
+               regulator-name = "SDHI0 Vcc";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&pfc 15 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+       };
+
+       vmmc_sdhi2: regulator@3 {
+               compatible = "regulator-fixed";
+               regulator-name = "SDHI2 Vcc";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&pfc 14 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               led1 {
+                       gpios = <&pfc 20 GPIO_ACTIVE_LOW>;
+                       label = "LED1";
+               };
+               led2 {
+                       gpios = <&pfc 21 GPIO_ACTIVE_LOW>;
+                       label = "LED2";
+               };
+               led3 {
+                       gpios = <&pfc 22 GPIO_ACTIVE_LOW>;
+                       label = "LED3";
+               };
+               led4 {
+                       gpios = <&pfc 23 GPIO_ACTIVE_LOW>;
+                       label = "LED4";
+               };
+       };
+
+       keyboard {
+               compatible = "gpio-keys";
+
+               back-key {
+                       gpios = <&pcf8575 8 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_BACK>;
+                       label = "SW3";
+               };
+
+               right-key {
+                       gpios = <&pcf8575 9 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_RIGHT>;
+                       label = "SW2-R";
+               };
+
+               left-key {
+                       gpios = <&pcf8575 10 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_LEFT>;
+                       label = "SW2-L";
+               };
+
+               enter-key {
+                       gpios = <&pcf8575 11 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_ENTER>;
+                       label = "SW2-P";
+               };
+
+               up-key {
+                       gpios = <&pcf8575 12 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_UP>;
+                       label = "SW2-U";
+               };
+
+               down-key {
+                       gpios = <&pcf8575 13 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_DOWN>;
+                       label = "SW2-D";
+               };
+
+               home-key {
+                       gpios = <&pcf8575 14 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_HOME>;
+                       label = "SW1";
+               };
+       };
+
+       sound {
+               compatible = "simple-audio-card";
+               simple-audio-card,format = "left_j";
+               simple-audio-card,cpu {
+                       sound-dai = <&sh_fsi2 0>;
+               };
+               simple-audio-card,codec {
+                       sound-dai = <&ak4648>;
+                       bitclock-master;
+                       frame-master;
+                       system-clock-frequency = <11289600>;
+               };
+       };
+};
+
+&bsc {
+       ethernet@10000000 {
+               compatible = "smsc,lan9220", "smsc,lan9115";
+               reg = <0x10000000 0x100>;
+               phy-mode = "mii";
+               interrupt-parent = <&irqpin0>;
+               interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+               reg-io-width = <4>;
+               smsc,irq-push-pull;
+               smsc,save-mac-address;
+               vddvario-supply = <&reg_1p8v>;
+               vdd33a-supply = <&reg_3p3v>;
+       };
+};
+
+&cmt1 {
+       status = "okay";
+};
+
+&extal2_clk {
+       clock-frequency = <48000000>;
+};
+
+&i2c0 {
+       status = "okay";
+
+       compass@c {
+               compatible = "asahi-kasei,ak8975";
+               reg = <0x0c>;
+               interrupt-parent = <&irqpin3>;
+               interrupts = <4 IRQ_TYPE_EDGE_FALLING>;
+       };
+
+       ak4648: codec@12 {
+               compatible = "asahi-kasei,ak4648";
+               reg = <0x12>;
+               #sound-dai-cells = <0>;
+       };
+
+       accelerometer@1d {
+               compatible = "adi,adxl34x";
+               reg = <0x1d>;
+               interrupt-parent = <&irqpin3>;
+               interrupts = <2 IRQ_TYPE_LEVEL_HIGH>,
+                            <3 IRQ_TYPE_LEVEL_HIGH>;
        };
+
+       rtc@32 {
+               compatible = "ricoh,r2025sd";
+               reg = <0x32>;
+       };
+
+       as3711@40 {
+               compatible = "ams,as3711";
+               reg = <0x40>;
+
+               regulators {
+                       vdd_dvfs: sd1 {
+                               regulator-name = "1.315V CPU";
+                               regulator-min-microvolt = <1050000>;
+                               regulator-max-microvolt = <1350000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+                       sd2 {
+                               regulator-name = "1.8V";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+                       sd4 {
+                               regulator-name = "1.215V";
+                               regulator-min-microvolt = <1215000>;
+                               regulator-max-microvolt = <1235000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+                       ldo2 {
+                               regulator-name = "2.8V CPU";
+                               regulator-min-microvolt = <2800000>;
+                               regulator-max-microvolt = <2800000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+                       ldo3 {
+                               regulator-name = "3.0V CPU";
+                               regulator-min-microvolt = <3000000>;
+                               regulator-max-microvolt = <3000000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+                       ldo4 {
+                               regulator-name = "2.8V";
+                               regulator-min-microvolt = <2800000>;
+                               regulator-max-microvolt = <2800000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+                       ldo5 {
+                               regulator-name = "2.8V #2";
+                               regulator-min-microvolt = <2800000>;
+                               regulator-max-microvolt = <2800000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+                       ldo7 {
+                               regulator-name = "1.15V CPU";
+                               regulator-min-microvolt = <1150000>;
+                               regulator-max-microvolt = <1150000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+                       ldo8 {
+                               regulator-name = "1.15V CPU #2";
+                               regulator-min-microvolt = <1150000>;
+                               regulator-max-microvolt = <1150000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+               };
+       };
+};
+
+&i2c1 {
+       status = "okay";
+
+       touchscreen@55 {
+               compatible = "sitronix,st1232";
+               reg = <0x55>;
+               interrupt-parent = <&irqpin1>;
+               interrupts = <0 IRQ_TYPE_EDGE_FALLING>;
+       };
+};
+
+&i2c3 {
+       pinctrl-0 = <&i2c3_pins>;
+       pinctrl-names = "default";
+       status = "okay";
+
+       pcf8575: gpio@20 {
+               compatible = "nxp,pcf8575";
+               reg = <0x20>;
+               interrupt-parent = <&irqpin2>;
+               interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+               gpio-controller;
+               #gpio-cells = <2>;
+               interrupt-controller;
+               #interrupt-cells = <2>;
+       };
+};
+
+&mmcif {
+       pinctrl-0 = <&mmcif_pins>;
+       pinctrl-names = "default";
+
+       bus-width = <8>;
+       vmmc-supply = <&reg_1p8v>;
+       status = "okay";
+};
+
+&pfc {
+       i2c3_pins: i2c3 {
+               renesas,groups = "i2c3_1";
+               renesas,function = "i2c3";
+       };
+
+       mmcif_pins: mmc {
+               mux {
+                       renesas,groups = "mmc0_data8_0", "mmc0_ctrl_0";
+                       renesas,function = "mmc0";
+               };
+               cfg {
+                       renesas,groups = "mmc0_data8_0";
+                       renesas,pins = "PORT279";
+                       bias-pull-up;
+               };
+       };
+
+       scifa4_pins: serial4 {
+               renesas,groups = "scifa4_data", "scifa4_ctrl";
+               renesas,function = "scifa4";
+       };
+
+       sdhi0_pins: sd0 {
+               renesas,groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_cd", "sdhi0_wp";
+               renesas,function = "sdhi0";
+       };
+
+       sdhi2_pins: sd2 {
+               renesas,groups = "sdhi2_data4", "sdhi2_ctrl";
+               renesas,function = "sdhi2";
+       };
+
+       fsia_pins: sounda {
+               renesas,groups = "fsia_mclk_in", "fsia_sclk_in",
+                                "fsia_data_in", "fsia_data_out";
+               renesas,function = "fsia";
+       };
+};
+
+&scifa4 {
+       pinctrl-0 = <&scifa4_pins>;
+       pinctrl-names = "default";
+
+       status = "okay";
+};
+
+&sdhi0 {
+       pinctrl-0 = <&sdhi0_pins>;
+       pinctrl-names = "default";
+
+       vmmc-supply = <&vmmc_sdhi0>;
+       bus-width = <4>;
+       status = "okay";
+};
+
+&sdhi2 {
+       pinctrl-0 = <&sdhi2_pins>;
+       pinctrl-names = "default";
+
+       vmmc-supply = <&vmmc_sdhi2>;
+       bus-width = <4>;
+       broken-cd;
+       status = "okay";
+};
+
+&sh_fsi2 {
+       pinctrl-0 = <&fsia_pins>;
+       pinctrl-names = "default";
+
+       status = "okay";
 };
index 2dfd5b44255de147e11f2c36c2b9cc5f7e9f3793..45b539ce4d3520356d45470f3bdfeb5f8020ce30 100644 (file)
@@ -11,6 +11,7 @@
 /include/ "skeleton.dtsi"
 
 #include <dt-bindings/clock/sh73a0-clock.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 
 / {
                        compatible = "arm,cortex-a9";
                        reg = <0>;
                        clock-frequency = <1196000000>;
+                       power-domains = <&pd_a2sl>;
                };
                cpu@1 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a9";
                        reg = <1>;
                        clock-frequency = <1196000000>;
+                       power-domains = <&pd_a2sl>;
                };
        };
 
+       timer@f0000600 {
+               compatible = "arm,cortex-a9-twd-timer";
+               reg = <0xf0000600 0x20>;
+               interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
+               clocks = <&twd_clk>;
+       };
+
        gic: interrupt-controller@f0001000 {
                compatible = "arm,cortex-a9-gic";
                #interrupt-cells = <3>;
@@ -49,6 +59,7 @@
                interrupts = <0 37 IRQ_TYPE_LEVEL_HIGH>,
                             <0 38 IRQ_TYPE_LEVEL_HIGH>;
                interrupt-names = "sec", "temp";
+               power-domains = <&pd_a4bc1>;
        };
 
        sbsc1: memory-controller@fe400000 {
@@ -57,6 +68,7 @@
                interrupts = <0 35 IRQ_TYPE_LEVEL_HIGH>,
                             <0 36 IRQ_TYPE_LEVEL_HIGH>;
                interrupt-names = "sec", "temp";
+               power-domains = <&pd_a4bc0>;
        };
 
        pmu {
                compatible = "renesas,cmt-48-sh73a0", "renesas,cmt-48";
                reg = <0xe6138000 0x200>;
                interrupts = <0 65 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp3_clks SH73A0_CLK_CMT1>;
+               clock-names = "fck";
+               power-domains = <&pd_c5>;
 
                renesas,channels-mask = <0x3f>;
 
-               clocks = <&mstp3_clks SH73A0_CLK_CMT1>;
-               clock-names = "fck";
                status = "disabled";
        };
 
                              0 6 IRQ_TYPE_LEVEL_HIGH
                              0 7 IRQ_TYPE_LEVEL_HIGH
                              0 8 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp5_clks SH73A0_CLK_INTCA0>;
+               power-domains = <&pd_a4s>;
+               control-parent;
        };
 
        irqpin1: irqpin@e6900004 {
                              0 14 IRQ_TYPE_LEVEL_HIGH
                              0 15 IRQ_TYPE_LEVEL_HIGH
                              0 16 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp5_clks SH73A0_CLK_INTCA0>;
+               power-domains = <&pd_a4s>;
                control-parent;
        };
 
                              0 22 IRQ_TYPE_LEVEL_HIGH
                              0 23 IRQ_TYPE_LEVEL_HIGH
                              0 24 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp5_clks SH73A0_CLK_INTCA0>;
+               power-domains = <&pd_a4s>;
+               control-parent;
        };
 
        irqpin3: irqpin@e690000c {
                              0 30 IRQ_TYPE_LEVEL_HIGH
                              0 31 IRQ_TYPE_LEVEL_HIGH
                              0 32 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&mstp5_clks SH73A0_CLK_INTCA0>;
+               power-domains = <&pd_a4s>;
+               control-parent;
        };
 
        i2c0: i2c@e6820000 {
                              0 169 IRQ_TYPE_LEVEL_HIGH
                              0 170 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp1_clks SH73A0_CLK_IIC0>;
+               power-domains = <&pd_a3sp>;
                status = "disabled";
        };
 
                              0 53 IRQ_TYPE_LEVEL_HIGH
                              0 54 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp3_clks SH73A0_CLK_IIC1>;
+               power-domains = <&pd_a3sp>;
                status = "disabled";
        };
 
                              0 173 IRQ_TYPE_LEVEL_HIGH
                              0 174 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp0_clks SH73A0_CLK_IIC2>;
+               power-domains = <&pd_a3sp>;
                status = "disabled";
        };
 
                              0 185 IRQ_TYPE_LEVEL_HIGH
                              0 186 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp4_clks SH73A0_CLK_IIC3>;
+               power-domains = <&pd_a3sp>;
                status = "disabled";
        };
 
                              0 189 IRQ_TYPE_LEVEL_HIGH
                              0 190 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp4_clks SH73A0_CLK_IIC4>;
+               power-domains = <&pd_c5>;
                status = "disabled";
        };
 
                interrupts = <0 140 IRQ_TYPE_LEVEL_HIGH
                              0 141 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp3_clks SH73A0_CLK_MMCIF0>;
+               power-domains = <&pd_a3sp>;
                reg-io-width = <4>;
                status = "disabled";
        };
                              0 84 IRQ_TYPE_LEVEL_HIGH
                              0 85 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp3_clks SH73A0_CLK_SDHI0>;
+               power-domains = <&pd_a3sp>;
                cap-sd-highspeed;
                status = "disabled";
        };
                interrupts = <0 88 IRQ_TYPE_LEVEL_HIGH
                              0 89 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp3_clks SH73A0_CLK_SDHI1>;
+               power-domains = <&pd_a3sp>;
                toshiba,mmc-wrprotect-disable;
                cap-sd-highspeed;
                status = "disabled";
                interrupts = <0 104 IRQ_TYPE_LEVEL_HIGH
                              0 105 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp3_clks SH73A0_CLK_SDHI2>;
+               power-domains = <&pd_a3sp>;
                toshiba,mmc-wrprotect-disable;
                cap-sd-highspeed;
                status = "disabled";
                interrupts = <0 72 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp2_clks SH73A0_CLK_SCIFA0>;
                clock-names = "sci_ick";
+               power-domains = <&pd_a3sp>;
                status = "disabled";
        };
 
                interrupts = <0 73 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp2_clks SH73A0_CLK_SCIFA1>;
                clock-names = "sci_ick";
+               power-domains = <&pd_a3sp>;
                status = "disabled";
        };
 
                interrupts = <0 74 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp2_clks SH73A0_CLK_SCIFA2>;
                clock-names = "sci_ick";
+               power-domains = <&pd_a3sp>;
                status = "disabled";
        };
 
                interrupts = <0 75 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp2_clks SH73A0_CLK_SCIFA3>;
                clock-names = "sci_ick";
+               power-domains = <&pd_a3sp>;
                status = "disabled";
        };
 
                interrupts = <0 78 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp2_clks SH73A0_CLK_SCIFA4>;
                clock-names = "sci_ick";
+               power-domains = <&pd_a3sp>;
                status = "disabled";
        };
 
                interrupts = <0 79 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp2_clks SH73A0_CLK_SCIFA5>;
                clock-names = "sci_ick";
+               power-domains = <&pd_a3sp>;
                status = "disabled";
        };
 
                interrupts = <0 156 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp3_clks SH73A0_CLK_SCIFA6>;
                clock-names = "sci_ick";
+               power-domains = <&pd_a3sp>;
                status = "disabled";
        };
 
                interrupts = <0 143 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp2_clks SH73A0_CLK_SCIFA7>;
                clock-names = "sci_ick";
+               power-domains = <&pd_a3sp>;
                status = "disabled";
        };
 
                interrupts = <0 80 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp2_clks SH73A0_CLK_SCIFB>;
                clock-names = "sci_ick";
+               power-domains = <&pd_a3sp>;
                status = "disabled";
        };
 
                        <&irqpin2 4 0>, <&irqpin2 5 0>, <&irqpin2 6 0>, <&irqpin2 7 0>,
                        <&irqpin3 0 0>, <&irqpin3 1 0>, <&irqpin3 2 0>, <&irqpin3 3 0>,
                        <&irqpin3 4 0>, <&irqpin3 5 0>, <&irqpin3 6 0>, <&irqpin3 7 0>;
+               power-domains = <&pd_c5>;
+       };
+
+       sysc: system-controller@e6180000 {
+               compatible = "renesas,sysc-sh73a0", "renesas,sysc-rmobile";
+               reg = <0xe6180000 0x8000>, <0xe6188000 0x8000>;
+
+               pm-domains {
+                       pd_c5: c5 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               #power-domain-cells = <0>;
+
+                               pd_c4: c4@0 {
+                                       reg = <0>;
+                                       #power-domain-cells = <0>;
+                               };
+
+                               pd_d4: d4@1 {
+                                       reg = <1>;
+                                       #power-domain-cells = <0>;
+                               };
+
+                               pd_a4bc0: a4bc0@4 {
+                                       reg = <4>;
+                                       #power-domain-cells = <0>;
+                               };
+
+                               pd_a4bc1: a4bc1@5 {
+                                       reg = <5>;
+                                       #power-domain-cells = <0>;
+                               };
+
+                               pd_a4lc0: a4lc0@6 {
+                                       reg = <6>;
+                                       #power-domain-cells = <0>;
+                               };
+
+                               pd_a4lc1: a4lc1@7 {
+                                       reg = <7>;
+                                       #power-domain-cells = <0>;
+                               };
+
+                               pd_a4mp: a4mp@8 {
+                                       reg = <8>;
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       #power-domain-cells = <0>;
+
+                                       pd_a3mp: a3mp@9 {
+                                               reg = <9>;
+                                               #power-domain-cells = <0>;
+                                       };
+
+                                       pd_a3vc: a3vc@10 {
+                                               reg = <10>;
+                                               #power-domain-cells = <0>;
+                                       };
+                               };
+
+                               pd_a4rm: a4rm@12 {
+                                       reg = <12>;
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       #power-domain-cells = <0>;
+
+                                       pd_a3r: a3r@13 {
+                                               reg = <13>;
+                                               #address-cells = <1>;
+                                               #size-cells = <0>;
+                                               #power-domain-cells = <0>;
+
+                                               pd_a2rv: a2rv@14 {
+                                                       reg = <14>;
+                                                       #address-cells = <1>;
+                                                       #size-cells = <0>;
+                                                       #power-domain-cells = <0>;
+                                               };
+                                       };
+                               };
+
+                               pd_a4s: a4s@16 {
+                                       reg = <16>;
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       #power-domain-cells = <0>;
+
+                                       pd_a3sp: a3sp@17 {
+                                               reg = <17>;
+                                               #power-domain-cells = <0>;
+                                       };
+
+                                       pd_a3sg: a3sg@18 {
+                                               reg = <18>;
+                                               #power-domain-cells = <0>;
+                                       };
+
+                                       pd_a3sm: a3sm@19 {
+                                               reg = <19>;
+                                               #address-cells = <1>;
+                                               #size-cells = <0>;
+                                               #power-domain-cells = <0>;
+
+                                               pd_a2sl: a2sl@20 {
+                                                       reg = <20>;
+                                                       #power-domain-cells = <0>;
+                                               };
+                                       };
+                               };
+                       };
+               };
        };
 
        sh_fsi2: sound@ec230000 {
                compatible = "renesas,fsi2-sh73a0", "renesas,sh_fsi2";
                reg = <0xec230000 0x400>;
                interrupts = <0 146 0x4>;
+               power-domains = <&pd_a4mp>;
                status = "disabled";
        };
 
+       bsc: bus@fec10000 {
+               compatible = "renesas,bsc-sh73a0", "renesas,bsc",
+                            "simple-pm-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0 0 0x20000000>;
+               reg = <0xfec10000 0x400>;
+               interrupts = <0 39 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&zb_clk>;
+               power-domains = <&pd_a4s>;
+       };
+
        clocks {
                #address-cells = <1>;
                #size-cells = <1>;
                vclk1_clk: vclk1_clk@e6150008 {
                        compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
                        reg = <0xe6150008 4>;
-                       clocks = <&pll1_div2_clk>;
+                       clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>,
+                                <&extcki_clk>, <&extal2_clk>, <&main_div2_clk>,
+                                <&extalr_clk>, <&cpg_clocks SH73A0_CLK_MAIN>,
+                                <0>;
                        #clock-cells = <0>;
                        clock-output-names = "vclk1";
                };
                vclk2_clk: vclk2_clk@e615000c {
                        compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
                        reg = <0xe615000c 4>;
-                       clocks = <&pll1_div2_clk>;
+                       clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>,
+                                <&extcki_clk>, <&extal2_clk>, <&main_div2_clk>,
+                                <&extalr_clk>, <&cpg_clocks SH73A0_CLK_MAIN>,
+                                <0>;
                        #clock-cells = <0>;
                        clock-output-names = "vclk2";
                };
                vclk3_clk: vclk3_clk@e615001c {
                        compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
                        reg = <0xe615001c 4>;
-                       clocks = <&pll1_div2_clk>;
+                       clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>,
+                                <&extcki_clk>, <&extal2_clk>, <&main_div2_clk>,
+                                <&extalr_clk>, <&cpg_clocks SH73A0_CLK_MAIN>,
+                                <0>;
                        #clock-cells = <0>;
                        clock-output-names = "vclk3";
                };
                zb_clk: zb_clk@e6150010 {
                        compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
                        reg = <0xe6150010 4>;
-                       clocks = <&pll1_div2_clk>;
+                       clocks = <&pll1_div2_clk>, <0>,
+                                <&cpg_clocks SH73A0_CLK_PLL2>, <0>;
                        #clock-cells = <0>;
                        clock-output-names = "zb";
                };
                flctl_clk: flctl_clk@e6150014 {
                        compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
                        reg = <0xe6150014 4>;
-                       clocks = <&pll1_div2_clk>;
+                       clocks = <&pll1_div2_clk>, <0>,
+                                <&cpg_clocks SH73A0_CLK_PLL2>, <0>;
                        #clock-cells = <0>;
                        clock-output-names = "flctlck";
                };
                sdhi0_clk: sdhi0_clk@e6150074 {
                        compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
                        reg = <0xe6150074 4>;
-                       clocks = <&pll1_div2_clk>;
+                       clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>,
+                                <&pll1_div13_clk>, <0>;
                        #clock-cells = <0>;
                        clock-output-names = "sdhi0ck";
                };
                sdhi1_clk: sdhi1_clk@e6150078 {
                        compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
                        reg = <0xe6150078 4>;
-                       clocks = <&pll1_div2_clk>;
+                       clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>,
+                                <&pll1_div13_clk>, <0>;
                        #clock-cells = <0>;
                        clock-output-names = "sdhi1ck";
                };
                sdhi2_clk: sdhi2_clk@e615007c {
                        compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
                        reg = <0xe615007c 4>;
-                       clocks = <&pll1_div2_clk>;
+                       clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>,
+                                <&pll1_div13_clk>, <0>;
                        #clock-cells = <0>;
                        clock-output-names = "sdhi2ck";
                };
                fsia_clk: fsia_clk@e6150018 {
                        compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
                        reg = <0xe6150018 4>;
-                       clocks = <&pll1_div2_clk>;
+                       clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>,
+                                <&fsiack_clk>, <&fsiack_clk>;
                        #clock-cells = <0>;
                        clock-output-names = "fsia";
                };
                fsib_clk: fsib_clk@e6150090 {
                        compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
                        reg = <0xe6150090 4>;
-                       clocks = <&pll1_div2_clk>;
+                       clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>,
+                                <&fsibck_clk>, <&fsibck_clk>;
                        #clock-cells = <0>;
                        clock-output-names = "fsib";
                };
                sub_clk: sub_clk@e6150080 {
                        compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
                        reg = <0xe6150080 4>;
-                       clocks = <&extal2_clk>;
+                       clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>,
+                                <&extal2_clk>, <&extal2_clk>;
                        #clock-cells = <0>;
                        clock-output-names = "sub";
                };
                spua_clk: spua_clk@e6150084 {
                        compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
                        reg = <0xe6150084 4>;
-                       clocks = <&pll1_div2_clk>;
+                       clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>,
+                                <&extal2_clk>, <&extal2_clk>;
                        #clock-cells = <0>;
                        clock-output-names = "spua";
                };
                spuv_clk: spuv_clk@e6150094 {
                        compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
                        reg = <0xe6150094 4>;
-                       clocks = <&pll1_div2_clk>;
+                       clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>,
+                                <&extal2_clk>, <&extal2_clk>;
                        #clock-cells = <0>;
                        clock-output-names = "spuv";
                };
                msu_clk: msu_clk@e6150088 {
                        compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
                        reg = <0xe6150088 4>;
-                       clocks = <&pll1_div2_clk>;
+                       clocks = <&pll1_div2_clk>, <0>,
+                                <&cpg_clocks SH73A0_CLK_PLL2>, <0>;
                        #clock-cells = <0>;
                        clock-output-names = "msu";
                };
                hsi_clk: hsi_clk@e615008c {
                        compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
                        reg = <0xe615008c 4>;
-                       clocks = <&pll1_div2_clk>;
+                       clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>,
+                                <&pll1_div7_clk>, <0>;
                        #clock-cells = <0>;
                        clock-output-names = "hsi";
                };
                mfg1_clk: mfg1_clk@e6150098 {
                        compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
                        reg = <0xe6150098 4>;
-                       clocks = <&pll1_div2_clk>;
+                       clocks = <&pll1_div2_clk>, <0>,
+                                <&cpg_clocks SH73A0_CLK_PLL2>, <0>;
                        #clock-cells = <0>;
                        clock-output-names = "mfg1";
                };
                mfg2_clk: mfg2_clk@e615009c {
                        compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
                        reg = <0xe615009c 4>;
-                       clocks = <&pll1_div2_clk>;
+                       clocks = <&pll1_div2_clk>, <0>,
+                                <&cpg_clocks SH73A0_CLK_PLL2>, <0>;
                        #clock-cells = <0>;
                        clock-output-names = "mfg2";
                };
                dsit_clk: dsit_clk@e6150060 {
                        compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
                        reg = <0xe6150060 4>;
-                       clocks = <&pll1_div2_clk>;
+                       clocks = <&pll1_div2_clk>, <0>,
+                                <&cpg_clocks SH73A0_CLK_PLL2>, <0>;
                        #clock-cells = <0>;
                        clock-output-names = "dsit";
                };
                dsi0p_clk: dsi0p_clk@e6150064 {
                        compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
                        reg = <0xe6150064 4>;
-                       clocks = <&pll1_div2_clk>;
+                       clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>,
+                                <&cpg_clocks SH73A0_CLK_MAIN>, <&extal2_clk>,
+                                <&extcki_clk>, <0>, <0>, <0>;
                        #clock-cells = <0>;
                        clock-output-names = "dsi0pck";
                };
                        clock-output-names =
                                "iic3", "iic4", "keysc";
                };
+               mstp5_clks: mstp5_clks@e6150144 {
+                       compatible = "renesas,sh73a0-mstp-clocks", "renesas,cpg-mstp-clocks";
+                       reg = <0xe6150144 4>, <0xe615003c 4>;
+                       clocks = <&cpg_clocks SH73A0_CLK_HP>;
+                       #clock-cells = <1>;
+                       clock-indices = <
+                               SH73A0_CLK_INTCA0
+                       >;
+                       clock-output-names =
+                               "intca0";
+               };
        };
 };
diff --git a/arch/arm/boot/dts/tegra124-jetson-tk1-emc.dtsi b/arch/arm/boot/dts/tegra124-jetson-tk1-emc.dtsi
new file mode 100644 (file)
index 0000000..2c5cede
--- /dev/null
@@ -0,0 +1,2421 @@
+/ {
+       clock@0,60006000 {
+               emc-timings-3 {
+                       nvidia,ram-code = <3>;
+
+                       timing-12750000 {
+                               clock-frequency = <12750000>;
+                               nvidia,parent-clock-frequency = <408000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_P>;
+                               clock-names = "emc-parent";
+                       };
+                       timing-20400000 {
+                               clock-frequency = <20400000>;
+                               nvidia,parent-clock-frequency = <408000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_P>;
+                               clock-names = "emc-parent";
+                       };
+                       timing-40800000 {
+                               clock-frequency = <40800000>;
+                               nvidia,parent-clock-frequency = <408000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_P>;
+                               clock-names = "emc-parent";
+                       };
+                       timing-68000000 {
+                               clock-frequency = <68000000>;
+                               nvidia,parent-clock-frequency = <408000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_P>;
+                               clock-names = "emc-parent";
+                       };
+                       timing-102000000 {
+                               clock-frequency = <102000000>;
+                               nvidia,parent-clock-frequency = <408000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_P>;
+                               clock-names = "emc-parent";
+                       };
+                       timing-204000000 {
+                               clock-frequency = <204000000>;
+                               nvidia,parent-clock-frequency = <408000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_P>;
+                               clock-names = "emc-parent";
+                       };
+                       timing-300000000 {
+                               clock-frequency = <300000000>;
+                               nvidia,parent-clock-frequency = <600000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_C>;
+                               clock-names = "emc-parent";
+                       };
+                       timing-396000000 {
+                               clock-frequency = <396000000>;
+                               nvidia,parent-clock-frequency = <792000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_M>;
+                               clock-names = "emc-parent";
+                       };
+                       timing-528000000 {
+                               clock-frequency = <528000000>;
+                               nvidia,parent-clock-frequency = <528000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_M_UD>;
+                               clock-names = "emc-parent";
+                       };
+                       timing-600000000 {
+                               clock-frequency = <600000000>;
+                               nvidia,parent-clock-frequency = <600000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_C_UD>;
+                               clock-names = "emc-parent";
+                       };
+                       timing-792000000 {
+                               clock-frequency = <792000000>;
+                               nvidia,parent-clock-frequency = <792000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_M_UD>;
+                               clock-names = "emc-parent";
+                       };
+                       timing-924000000 {
+                               clock-frequency = <924000000>;
+                               nvidia,parent-clock-frequency = <924000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_M_UD>;
+                               clock-names = "emc-parent";
+                       };
+               };
+       };
+
+       emc@0,7001b000 {
+               emc-timings-3 {
+                       nvidia,ram-code = <3>;
+
+                       timing-12750000 {
+                               clock-frequency = <12750000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430000>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000008>;
+                               nvidia,emc-cfg = <0x73240000>;
+                               nvidia,emc-cfg-2 = <0x000008c5>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100003>;
+                               nvidia,emc-mode-2 = <0x80200008>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80001221>;
+                               nvidia,emc-mrs-wait-cnt = <0x000e000e>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040128>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x0130b118>;
+                               nvidia,emc-zcal-cnt-long = <0x00000042>;
+                               nvidia,emc-zcal-interval = <0x00000000>;
+
+                               nvidia,emc-configuration = <
+                                       0x00000000
+                                       0x00000003
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000004
+                                       0x0000000a
+                                       0x00000005
+                                       0x0000000b
+                                       0x00000000
+                                       0x00000000
+                                       0x00000003
+                                       0x00000003
+                                       0x00000000
+                                       0x00000006
+                                       0x00000006
+                                       0x00000006
+                                       0x00000002
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00010000
+                                       0x00000003
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000004
+                                       0x0000000c
+                                       0x0000000d
+                                       0x0000000f
+                                       0x00000060
+                                       0x00000000
+                                       0x00000018
+                                       0x00000002
+                                       0x00000002
+                                       0x00000001
+                                       0x00000000
+                                       0x00000007
+                                       0x0000000f
+                                       0x00000005
+                                       0x00000005
+                                       0x00000004
+                                       0x00000005
+                                       0x00000004
+                                       0x00000000
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00000064
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x106aa298
+                                       0x002c00a0
+                                       0x00008000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x10000280
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc081
+                                       0x00000e0e
+                                       0x81f1f108
+                                       0x07070004
+                                       0x0000003f
+                                       0x016eeeee
+                                       0x51451400
+                                       0x00514514
+                                       0x00514514
+                                       0x51451400
+                                       0x0000003f
+                                       0x00000007
+                                       0x00000000
+                                       0x00000042
+                                       0x000e000e
+                                       0x00000000
+                                       0x00000003
+                                       0x0000f2f3
+                                       0x800001c5
+                                       0x0000000a
+                               >;
+                       };
+
+                       timing-20400000 {
+                               clock-frequency = <20400000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430000>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000008>;
+                               nvidia,emc-cfg = <0x73240000>;
+                               nvidia,emc-cfg-2 = <0x000008c5>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100003>;
+                               nvidia,emc-mode-2 = <0x80200008>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80001221>;
+                               nvidia,emc-mrs-wait-cnt = <0x000e000e>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040128>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x0130b118>;
+                               nvidia,emc-zcal-cnt-long = <0x00000042>;
+                               nvidia,emc-zcal-interval = <0x00000000>;
+
+                               nvidia,emc-configuration = <
+                                       0x00000000
+                                       0x00000005
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000004
+                                       0x0000000a
+                                       0x00000005
+                                       0x0000000b
+                                       0x00000000
+                                       0x00000000
+                                       0x00000003
+                                       0x00000003
+                                       0x00000000
+                                       0x00000006
+                                       0x00000006
+                                       0x00000006
+                                       0x00000002
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00010000
+                                       0x00000003
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000004
+                                       0x0000000c
+                                       0x0000000d
+                                       0x0000000f
+                                       0x0000009a
+                                       0x00000000
+                                       0x00000026
+                                       0x00000002
+                                       0x00000002
+                                       0x00000001
+                                       0x00000000
+                                       0x00000007
+                                       0x0000000f
+                                       0x00000006
+                                       0x00000006
+                                       0x00000004
+                                       0x00000005
+                                       0x00000004
+                                       0x00000000
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x000000a0
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x106aa298
+                                       0x002c00a0
+                                       0x00008000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x10000280
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc081
+                                       0x00000e0e
+                                       0x81f1f108
+                                       0x07070004
+                                       0x0000003f
+                                       0x016eeeee
+                                       0x51451400
+                                       0x00514514
+                                       0x00514514
+                                       0x51451400
+                                       0x0000003f
+                                       0x0000000b
+                                       0x00000000
+                                       0x00000042
+                                       0x000e000e
+                                       0x00000000
+                                       0x00000003
+                                       0x0000f2f3
+                                       0x8000023a
+                                       0x0000000a
+                               >;
+                       };
+
+                       timing-40800000 {
+                               clock-frequency = <40800000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430000>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000008>;
+                               nvidia,emc-cfg = <0x73240000>;
+                               nvidia,emc-cfg-2 = <0x000008c5>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100003>;
+                               nvidia,emc-mode-2 = <0x80200008>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80001221>;
+                               nvidia,emc-mrs-wait-cnt = <0x000e000e>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040128>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x0130b118>;
+                               nvidia,emc-zcal-cnt-long = <0x00000042>;
+                               nvidia,emc-zcal-interval = <0x00000000>;
+
+                               nvidia,emc-configuration = <
+                                       0x00000001
+                                       0x0000000a
+                                       0x00000000
+                                       0x00000001
+                                       0x00000000
+                                       0x00000004
+                                       0x0000000a
+                                       0x00000005
+                                       0x0000000b
+                                       0x00000000
+                                       0x00000000
+                                       0x00000003
+                                       0x00000003
+                                       0x00000000
+                                       0x00000006
+                                       0x00000006
+                                       0x00000006
+                                       0x00000002
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00010000
+                                       0x00000003
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000004
+                                       0x0000000c
+                                       0x0000000d
+                                       0x0000000f
+                                       0x00000134
+                                       0x00000000
+                                       0x0000004d
+                                       0x00000002
+                                       0x00000002
+                                       0x00000001
+                                       0x00000000
+                                       0x00000008
+                                       0x0000000f
+                                       0x0000000c
+                                       0x0000000c
+                                       0x00000004
+                                       0x00000005
+                                       0x00000004
+                                       0x00000000
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x0000013f
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x106aa298
+                                       0x002c00a0
+                                       0x00008000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x10000280
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc081
+                                       0x00000e0e
+                                       0x81f1f108
+                                       0x07070004
+                                       0x0000003f
+                                       0x016eeeee
+                                       0x51451400
+                                       0x00514514
+                                       0x00514514
+                                       0x51451400
+                                       0x0000003f
+                                       0x00000015
+                                       0x00000000
+                                       0x00000042
+                                       0x000e000e
+                                       0x00000000
+                                       0x00000003
+                                       0x0000f2f3
+                                       0x80000370
+                                       0x0000000a
+                               >;
+                       };
+
+                       timing-68000000 {
+                               clock-frequency = <68000000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430000>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000008>;
+                               nvidia,emc-cfg = <0x73240000>;
+                               nvidia,emc-cfg-2 = <0x000008c5>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100003>;
+                               nvidia,emc-mode-2 = <0x80200008>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80001221>;
+                               nvidia,emc-mrs-wait-cnt = <0x000e000e>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040128>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x0130b118>;
+                               nvidia,emc-zcal-cnt-long = <0x00000042>;
+                               nvidia,emc-zcal-interval = <0x00000000>;
+
+                               nvidia,emc-configuration = <
+                                       0x00000003
+                                       0x00000011
+                                       0x00000000
+                                       0x00000002
+                                       0x00000000
+                                       0x00000004
+                                       0x0000000a
+                                       0x00000005
+                                       0x0000000b
+                                       0x00000000
+                                       0x00000000
+                                       0x00000003
+                                       0x00000003
+                                       0x00000000
+                                       0x00000006
+                                       0x00000006
+                                       0x00000006
+                                       0x00000002
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00010000
+                                       0x00000003
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000004
+                                       0x0000000c
+                                       0x0000000d
+                                       0x0000000f
+                                       0x00000202
+                                       0x00000000
+                                       0x00000080
+                                       0x00000002
+                                       0x00000002
+                                       0x00000001
+                                       0x00000000
+                                       0x0000000f
+                                       0x0000000f
+                                       0x00000013
+                                       0x00000013
+                                       0x00000004
+                                       0x00000005
+                                       0x00000004
+                                       0x00000001
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00000213
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x106aa298
+                                       0x002c00a0
+                                       0x00008000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x10000280
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc081
+                                       0x00000e0e
+                                       0x81f1f108
+                                       0x07070004
+                                       0x0000003f
+                                       0x016eeeee
+                                       0x51451400
+                                       0x00514514
+                                       0x00514514
+                                       0x51451400
+                                       0x0000003f
+                                       0x00000022
+                                       0x00000000
+                                       0x00000042
+                                       0x000e000e
+                                       0x00000000
+                                       0x00000003
+                                       0x0000f2f3
+                                       0x8000050e
+                                       0x0000000a
+                               >;
+                       };
+
+                       timing-102000000 {
+                               clock-frequency = <102000000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430000>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000008>;
+                               nvidia,emc-cfg = <0x73240000>;
+                               nvidia,emc-cfg-2 = <0x000008c5>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100003>;
+                               nvidia,emc-mode-2 = <0x80200008>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80001221>;
+                               nvidia,emc-mrs-wait-cnt = <0x000e000e>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040128>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x0130b118>;
+                               nvidia,emc-zcal-cnt-long = <0x00000042>;
+                               nvidia,emc-zcal-interval = <0x00000000>;
+
+                               nvidia,emc-configuration = <
+                                       0x00000004
+                                       0x0000001a
+                                       0x00000000
+                                       0x00000003
+                                       0x00000001
+                                       0x00000004
+                                       0x0000000a
+                                       0x00000005
+                                       0x0000000b
+                                       0x00000001
+                                       0x00000001
+                                       0x00000003
+                                       0x00000003
+                                       0x00000000
+                                       0x00000006
+                                       0x00000006
+                                       0x00000006
+                                       0x00000002
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00010000
+                                       0x00000003
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000004
+                                       0x0000000c
+                                       0x0000000d
+                                       0x0000000f
+                                       0x00000304
+                                       0x00000000
+                                       0x000000c1
+                                       0x00000002
+                                       0x00000002
+                                       0x00000001
+                                       0x00000000
+                                       0x00000018
+                                       0x0000000f
+                                       0x0000001c
+                                       0x0000001c
+                                       0x00000004
+                                       0x00000005
+                                       0x00000004
+                                       0x00000002
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x0000031c
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x106aa298
+                                       0x002c00a0
+                                       0x00008000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x10000280
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc081
+                                       0x00000e0e
+                                       0x81f1f108
+                                       0x07070004
+                                       0x0000003f
+                                       0x016eeeee
+                                       0x51451400
+                                       0x00514514
+                                       0x00514514
+                                       0x51451400
+                                       0x0000003f
+                                       0x00000033
+                                       0x00000000
+                                       0x00000042
+                                       0x000e000e
+                                       0x00000000
+                                       0x00000003
+                                       0x0000f2f3
+                                       0x80000713
+                                       0x0000000a
+                               >;
+                       };
+
+                       timing-204000000 {
+                               clock-frequency = <204000000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430000>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000008>;
+                               nvidia,emc-cfg = <0x73240000>;
+                               nvidia,emc-cfg-2 = <0x000008cd>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100003>;
+                               nvidia,emc-mode-2 = <0x80200008>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80001221>;
+                               nvidia,emc-mrs-wait-cnt = <0x000e000e>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040128>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x0130b118>;
+                               nvidia,emc-zcal-cnt-long = <0x00000042>;
+                               nvidia,emc-zcal-interval = <0x00020000>;
+
+                               nvidia,emc-configuration = <
+                                       0x00000009
+                                       0x00000035
+                                       0x00000000
+                                       0x00000006
+                                       0x00000002
+                                       0x00000005
+                                       0x0000000a
+                                       0x00000005
+                                       0x0000000b
+                                       0x00000002
+                                       0x00000002
+                                       0x00000003
+                                       0x00000003
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00000006
+                                       0x00000002
+                                       0x00000000
+                                       0x00000004
+                                       0x00000006
+                                       0x00010000
+                                       0x00000003
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000003
+                                       0x0000000d
+                                       0x0000000f
+                                       0x00000011
+                                       0x00000607
+                                       0x00000000
+                                       0x00000181
+                                       0x00000002
+                                       0x00000002
+                                       0x00000001
+                                       0x00000000
+                                       0x00000032
+                                       0x0000000f
+                                       0x00000038
+                                       0x00000038
+                                       0x00000004
+                                       0x00000005
+                                       0x00000004
+                                       0x00000006
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00000638
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x106aa298
+                                       0x002c00a0
+                                       0x00008000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00080000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00008000
+                                       0x00000000
+                                       0x00000000
+                                       0x00008000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00090000
+                                       0x00090000
+                                       0x00090000
+                                       0x00090000
+                                       0x00009000
+                                       0x00009000
+                                       0x00009000
+                                       0x00009000
+                                       0x10000280
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc081
+                                       0x00000707
+                                       0x81f1f108
+                                       0x07070004
+                                       0x0000003f
+                                       0x016eeeee
+                                       0x51451400
+                                       0x00514514
+                                       0x00514514
+                                       0x51451400
+                                       0x0000003f
+                                       0x00000066
+                                       0x00000000
+                                       0x00000100
+                                       0x000e000e
+                                       0x00000000
+                                       0x00000003
+                                       0x0000d2b3
+                                       0x80000d22
+                                       0x0000000a
+                               >;
+                       };
+
+                       timing-300000000 {
+                               clock-frequency = <300000000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430000>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000000>;
+                               nvidia,emc-cfg = <0x73340000>;
+                               nvidia,emc-cfg-2 = <0x000008d5>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100002>;
+                               nvidia,emc-mode-2 = <0x80200000>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80000321>;
+                               nvidia,emc-mrs-wait-cnt = <0x0173000e>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040128>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x01231339>;
+                               nvidia,emc-zcal-cnt-long = <0x00000042>;
+                               nvidia,emc-zcal-interval = <0x00020000>;
+
+                               nvidia,emc-configuration = <
+                                       0x0000000d
+                                       0x0000004d
+                                       0x00000000
+                                       0x00000009
+                                       0x00000003
+                                       0x00000004
+                                       0x00000008
+                                       0x00000002
+                                       0x00000009
+                                       0x00000003
+                                       0x00000003
+                                       0x00000002
+                                       0x00000002
+                                       0x00000000
+                                       0x00000003
+                                       0x00000003
+                                       0x00000005
+                                       0x00000002
+                                       0x00000000
+                                       0x00000002
+                                       0x00000007
+                                       0x00020000
+                                       0x00000003
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000001
+                                       0x0000000e
+                                       0x00000010
+                                       0x00000012
+                                       0x000008e4
+                                       0x00000000
+                                       0x00000239
+                                       0x00000001
+                                       0x00000008
+                                       0x00000001
+                                       0x00000000
+                                       0x0000004b
+                                       0x0000000e
+                                       0x00000052
+                                       0x00000200
+                                       0x00000004
+                                       0x00000005
+                                       0x00000004
+                                       0x00000008
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00000924
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x104ab098
+                                       0x002c00a0
+                                       0x00008000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00098000
+                                       0x00098000
+                                       0x00000000
+                                       0x00098000
+                                       0x00098000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00050000
+                                       0x00050000
+                                       0x00050000
+                                       0x00050000
+                                       0x00005000
+                                       0x00005000
+                                       0x00005000
+                                       0x00005000
+                                       0x10000280
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc081
+                                       0x00000505
+                                       0x81f1f108
+                                       0x07070004
+                                       0x00000000
+                                       0x016eeeee
+                                       0x51451420
+                                       0x00514514
+                                       0x00514514
+                                       0x51451400
+                                       0x0000003f
+                                       0x00000096
+                                       0x00000000
+                                       0x00000100
+                                       0x0173000e
+                                       0x00000000
+                                       0x00000003
+                                       0x000052a3
+                                       0x800012d7
+                                       0x00000009
+                               >;
+                       };
+
+                       timing-396000000 {
+                               clock-frequency = <396000000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430000>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000000>;
+                               nvidia,emc-cfg = <0x73340000>;
+                               nvidia,emc-cfg-2 = <0x00000895>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100002>;
+                               nvidia,emc-mode-2 = <0x80200000>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80000521>;
+                               nvidia,emc-mrs-wait-cnt = <0x015b000e>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040008>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x01231339>;
+                               nvidia,emc-zcal-cnt-long = <0x00000042>;
+                               nvidia,emc-zcal-interval = <0x00020000>;
+
+                               nvidia,emc-configuration = <
+                                       0x00000011
+                                       0x00000066
+                                       0x00000000
+                                       0x0000000c
+                                       0x00000004
+                                       0x00000004
+                                       0x00000008
+                                       0x00000002
+                                       0x0000000a
+                                       0x00000004
+                                       0x00000004
+                                       0x00000002
+                                       0x00000002
+                                       0x00000000
+                                       0x00000003
+                                       0x00000003
+                                       0x00000005
+                                       0x00000002
+                                       0x00000000
+                                       0x00000001
+                                       0x00000008
+                                       0x00020000
+                                       0x00000003
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x0000000f
+                                       0x00000010
+                                       0x00000012
+                                       0x00000bd1
+                                       0x00000000
+                                       0x000002f4
+                                       0x00000001
+                                       0x00000008
+                                       0x00000001
+                                       0x00000000
+                                       0x00000063
+                                       0x0000000f
+                                       0x0000006c
+                                       0x00000200
+                                       0x00000004
+                                       0x00000005
+                                       0x00000004
+                                       0x0000000b
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00000c11
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x104ab098
+                                       0x002c00a0
+                                       0x00008000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00070000
+                                       0x00070000
+                                       0x00000000
+                                       0x00070000
+                                       0x00070000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00038000
+                                       0x00038000
+                                       0x00038000
+                                       0x00038000
+                                       0x00003800
+                                       0x00003800
+                                       0x00003800
+                                       0x00003800
+                                       0x10000280
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc081
+                                       0x00000505
+                                       0x81f1f108
+                                       0x07070004
+                                       0x00000000
+                                       0x016eeeee
+                                       0x51451420
+                                       0x00514514
+                                       0x00514514
+                                       0x51451400
+                                       0x0000003f
+                                       0x000000c6
+                                       0x00000000
+                                       0x00000100
+                                       0x015b000e
+                                       0x00000000
+                                       0x00000003
+                                       0x000052a3
+                                       0x8000188b
+                                       0x00000009
+                               >;
+                       };
+
+                       timing-528000000 {
+                               clock-frequency = <528000000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430000>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000000>;
+                               nvidia,emc-cfg = <0x73300000>;
+                               nvidia,emc-cfg-2 = <0x0000089d>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100002>;
+                               nvidia,emc-mode-2 = <0x80200008>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80000941>;
+                               nvidia,emc-mrs-wait-cnt = <0x0139000e>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040008>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x0123133d>;
+                               nvidia,emc-zcal-cnt-long = <0x00000042>;
+                               nvidia,emc-zcal-interval = <0x00020000>;
+
+                               nvidia,emc-configuration = <
+                                       0x00000018
+                                       0x00000088
+                                       0x00000000
+                                       0x00000010
+                                       0x00000006
+                                       0x00000006
+                                       0x00000009
+                                       0x00000002
+                                       0x0000000d
+                                       0x00000006
+                                       0x00000006
+                                       0x00000002
+                                       0x00000002
+                                       0x00000000
+                                       0x00000003
+                                       0x00000003
+                                       0x00000006
+                                       0x00000002
+                                       0x00000000
+                                       0x00000001
+                                       0x00000009
+                                       0x00030000
+                                       0x00000003
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000010
+                                       0x00000012
+                                       0x00000014
+                                       0x00000fd6
+                                       0x00000000
+                                       0x000003f5
+                                       0x00000002
+                                       0x0000000b
+                                       0x00000001
+                                       0x00000000
+                                       0x00000085
+                                       0x00000012
+                                       0x00000090
+                                       0x00000200
+                                       0x00000004
+                                       0x00000005
+                                       0x00000004
+                                       0x00000010
+                                       0x00000000
+                                       0x00000006
+                                       0x00000006
+                                       0x00001017
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x104ab098
+                                       0xe01200b1
+                                       0x00008000
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00054000
+                                       0x00054000
+                                       0x00000000
+                                       0x00054000
+                                       0x00054000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x0000000c
+                                       0x0000000c
+                                       0x0000000c
+                                       0x0000000c
+                                       0x0000000c
+                                       0x0000000c
+                                       0x0000000c
+                                       0x0000000c
+                                       0x100002a0
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc085
+                                       0x00000505
+                                       0x81f1f108
+                                       0x07070004
+                                       0x00000000
+                                       0x016eeeee
+                                       0x51451420
+                                       0x00514514
+                                       0x00514514
+                                       0x51451400
+                                       0x0606003f
+                                       0x00000000
+                                       0x00000000
+                                       0x00000100
+                                       0x0139000e
+                                       0x00000000
+                                       0x00000003
+                                       0x000042a0
+                                       0x80002062
+                                       0x0000000a
+                               >;
+                       };
+
+                       timing-600000000 {
+                               clock-frequency = <600000000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430000>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000000>;
+                               nvidia,emc-cfg = <0x73300000>;
+                               nvidia,emc-cfg-2 = <0x0000089d>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100002>;
+                               nvidia,emc-mode-2 = <0x80200010>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80000b61>;
+                               nvidia,emc-mrs-wait-cnt = <0x0127000e>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040008>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x0121113d>;
+                               nvidia,emc-zcal-cnt-long = <0x00000042>;
+                               nvidia,emc-zcal-interval = <0x00020000>;
+
+                               nvidia,emc-configuration = <
+                                       0x0000001b
+                                       0x0000009b
+                                       0x00000000
+                                       0x00000013
+                                       0x00000007
+                                       0x00000007
+                                       0x0000000b
+                                       0x00000003
+                                       0x00000010
+                                       0x00000007
+                                       0x00000007
+                                       0x00000002
+                                       0x00000002
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x0000000a
+                                       0x00000002
+                                       0x00000000
+                                       0x00000003
+                                       0x0000000b
+                                       0x00070000
+                                       0x00000003
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000002
+                                       0x00000012
+                                       0x00000016
+                                       0x00000018
+                                       0x00001208
+                                       0x00000000
+                                       0x00000482
+                                       0x00000002
+                                       0x0000000d
+                                       0x00000001
+                                       0x00000000
+                                       0x00000097
+                                       0x00000015
+                                       0x000000a3
+                                       0x00000200
+                                       0x00000004
+                                       0x00000005
+                                       0x00000004
+                                       0x00000013
+                                       0x00000000
+                                       0x00000006
+                                       0x00000006
+                                       0x00001248
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x104ab098
+                                       0xe00e00b1
+                                       0x00008000
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00048000
+                                       0x00048000
+                                       0x00000000
+                                       0x00048000
+                                       0x00048000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x0000000d
+                                       0x0000000d
+                                       0x0000000d
+                                       0x0000000d
+                                       0x0000000d
+                                       0x0000000d
+                                       0x0000000d
+                                       0x0000000d
+                                       0x100002a0
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc085
+                                       0x00000505
+                                       0x81f1f108
+                                       0x07070004
+                                       0x00000000
+                                       0x016eeeee
+                                       0x51451420
+                                       0x00514514
+                                       0x00514514
+                                       0x51451400
+                                       0x0606003f
+                                       0x00000000
+                                       0x00000000
+                                       0x00000100
+                                       0x0127000e
+                                       0x00000000
+                                       0x00000003
+                                       0x000040a0
+                                       0x800024aa
+                                       0x0000000e
+                               >;
+                       };
+
+                       timing-792000000 {
+                               clock-frequency = <792000000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430000>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000000>;
+                               nvidia,emc-cfg = <0x73300000>;
+                               nvidia,emc-cfg-2 = <0x0000089d>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100002>;
+                               nvidia,emc-mode-2 = <0x80200018>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80000d71>;
+                               nvidia,emc-mrs-wait-cnt = <0x00f7000e>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040000>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x0120113d>;
+                               nvidia,emc-zcal-cnt-long = <0x00000042>;
+                               nvidia,emc-zcal-interval = <0x00020000>;
+
+                               nvidia,emc-configuration = <
+                                       0x00000024
+                                       0x000000cd
+                                       0x00000000
+                                       0x00000019
+                                       0x0000000a
+                                       0x00000008
+                                       0x0000000d
+                                       0x00000004
+                                       0x00000013
+                                       0x0000000a
+                                       0x0000000a
+                                       0x00000004
+                                       0x00000002
+                                       0x00000000
+                                       0x00000006
+                                       0x00000006
+                                       0x0000000b
+                                       0x00000002
+                                       0x00000000
+                                       0x00000002
+                                       0x0000000d
+                                       0x00080000
+                                       0x00000004
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000001
+                                       0x00000014
+                                       0x00000018
+                                       0x0000001a
+                                       0x000017e2
+                                       0x00000000
+                                       0x000005f8
+                                       0x00000003
+                                       0x00000011
+                                       0x00000001
+                                       0x00000000
+                                       0x000000c7
+                                       0x00000018
+                                       0x000000d7
+                                       0x00000200
+                                       0x00000005
+                                       0x00000006
+                                       0x00000005
+                                       0x00000019
+                                       0x00000000
+                                       0x00000008
+                                       0x00000008
+                                       0x00001822
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x104ab098
+                                       0xe00700b1
+                                       0x00008000
+                                       0x007fc008
+                                       0x007fc008
+                                       0x007fc008
+                                       0x007fc008
+                                       0x007fc008
+                                       0x007fc008
+                                       0x007fc008
+                                       0x007fc008
+                                       0x007fc008
+                                       0x007fc008
+                                       0x007fc008
+                                       0x007fc008
+                                       0x007fc008
+                                       0x007fc008
+                                       0x007fc008
+                                       0x007fc008
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00034000
+                                       0x00034000
+                                       0x00000000
+                                       0x00034000
+                                       0x00034000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00000005
+                                       0x00000005
+                                       0x00000005
+                                       0x00000005
+                                       0x00000005
+                                       0x00000005
+                                       0x00000005
+                                       0x00000005
+                                       0x00000005
+                                       0x00000005
+                                       0x00000005
+                                       0x00000005
+                                       0x00000005
+                                       0x00000005
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x100002a0
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc085
+                                       0x00000000
+                                       0x81f1f108
+                                       0x07070004
+                                       0x00000000
+                                       0x016eeeee
+                                       0x61861820
+                                       0x00514514
+                                       0x00514514
+                                       0x61861800
+                                       0x0606003f
+                                       0x00000000
+                                       0x00000000
+                                       0x00000100
+                                       0x00f7000e
+                                       0x00000000
+                                       0x00000004
+                                       0x00004080
+                                       0x80003012
+                                       0x0000000f
+                               >;
+                       };
+
+                       timing-924000000 {
+                               clock-frequency = <924000000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430303>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000000>;
+                               nvidia,emc-cfg = <0x73300000>;
+                               nvidia,emc-cfg-2 = <0x0000089d>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100002>;
+                               nvidia,emc-mode-2 = <0x80200020>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80000f15>;
+                               nvidia,emc-mrs-wait-cnt = <0x00cd000e>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040000>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x0120113d>;
+                               nvidia,emc-zcal-cnt-long = <0x0000004c>;
+                               nvidia,emc-zcal-interval = <0x00020000>;
+
+                               nvidia,emc-configuration = <
+                                       0x0000002b
+                                       0x000000f0
+                                       0x00000000
+                                       0x0000001e
+                                       0x0000000b
+                                       0x00000009
+                                       0x0000000f
+                                       0x00000005
+                                       0x00000016
+                                       0x0000000b
+                                       0x0000000b
+                                       0x00000004
+                                       0x00000002
+                                       0x00000000
+                                       0x00000007
+                                       0x00000007
+                                       0x0000000d
+                                       0x00000002
+                                       0x00000000
+                                       0x00000002
+                                       0x0000000f
+                                       0x000a0000
+                                       0x00000004
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000001
+                                       0x00000016
+                                       0x0000001a
+                                       0x0000001c
+                                       0x00001be7
+                                       0x00000000
+                                       0x000006f9
+                                       0x00000004
+                                       0x00000015
+                                       0x00000001
+                                       0x00000000
+                                       0x000000e7
+                                       0x0000001b
+                                       0x000000fb
+                                       0x00000200
+                                       0x00000006
+                                       0x00000007
+                                       0x00000006
+                                       0x0000001e
+                                       0x00000000
+                                       0x0000000a
+                                       0x0000000a
+                                       0x00001c28
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x104ab898
+                                       0xe00400b1
+                                       0x00008000
+                                       0x007f800a
+                                       0x007f800a
+                                       0x007f800a
+                                       0x007f800a
+                                       0x007f800a
+                                       0x007f800a
+                                       0x007f800a
+                                       0x007f800a
+                                       0x007f800a
+                                       0x007f800a
+                                       0x007f800a
+                                       0x007f800a
+                                       0x007f800a
+                                       0x007f800a
+                                       0x007f800a
+                                       0x007f800a
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x0002c000
+                                       0x0002c000
+                                       0x00000000
+                                       0x0002c000
+                                       0x0002c000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000004
+                                       0x00000004
+                                       0x00000004
+                                       0x00000004
+                                       0x00000004
+                                       0x00000004
+                                       0x00000004
+                                       0x00000004
+                                       0x00000004
+                                       0x00000004
+                                       0x00000004
+                                       0x00000004
+                                       0x00000004
+                                       0x00000004
+                                       0x00000004
+                                       0x00000004
+                                       0x00000008
+                                       0x00000008
+                                       0x00000008
+                                       0x00000008
+                                       0x00000008
+                                       0x00000008
+                                       0x00000008
+                                       0x00000008
+                                       0x100002a0
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc085
+                                       0x00000000
+                                       0x81f1f108
+                                       0x07070004
+                                       0x00000000
+                                       0x016eeeee
+                                       0x5d75d720
+                                       0x00514514
+                                       0x00514514
+                                       0x5d75d700
+                                       0x0606003f
+                                       0x00000000
+                                       0x00000000
+                                       0x00000128
+                                       0x00cd000e
+                                       0x00000000
+                                       0x00000004
+                                       0x00004080
+                                       0x800037ea
+                                       0x00000011
+                               >;
+                       };
+
+               };
+       };
+
+       memory-controller@0,70019000 {
+               emc-timings-3 {
+                       nvidia,ram-code = <3>;
+
+                       timing-12750000 {
+                               clock-frequency = <12750000>;
+
+                               nvidia,emem-configuration = <
+                                       0x40040001
+                                       0x8000000a
+                                       0x00000001
+                                       0x00000001
+                                       0x00000002
+                                       0x00000000
+                                       0x00000002
+                                       0x00000001
+                                       0x00000003
+                                       0x00000008
+                                       0x00000003
+                                       0x00000002
+                                       0x00000003
+                                       0x00000006
+                                       0x06030203
+                                       0x000a0502
+                                       0x77e30303
+                                       0x70000f03
+                                       0x001f0000
+                               >;
+                       };
+
+                       timing-20400000 {
+                               clock-frequency = <20400000>;
+
+                               nvidia,emem-configuration = <
+                                       0x40020001
+                                       0x80000012
+                                       0x00000001
+                                       0x00000001
+                                       0x00000002
+                                       0x00000000
+                                       0x00000002
+                                       0x00000001
+                                       0x00000003
+                                       0x00000008
+                                       0x00000003
+                                       0x00000002
+                                       0x00000003
+                                       0x00000006
+                                       0x06030203
+                                       0x000a0502
+                                       0x76230303
+                                       0x70000f03
+                                       0x001f0000
+                               >;
+                       };
+
+                       timing-40800000 {
+                               clock-frequency = <40800000>;
+
+                               nvidia,emem-configuration = <
+                                       0xa0000001
+                                       0x80000017
+                                       0x00000001
+                                       0x00000001
+                                       0x00000002
+                                       0x00000000
+                                       0x00000002
+                                       0x00000001
+                                       0x00000003
+                                       0x00000008
+                                       0x00000003
+                                       0x00000002
+                                       0x00000003
+                                       0x00000006
+                                       0x06030203
+                                       0x000a0502
+                                       0x74a30303
+                                       0x70000f03
+                                       0x001f0000
+                               >;
+                       };
+
+                       timing-68000000 {
+                               clock-frequency = <68000000>;
+
+                               nvidia,emem-configuration = <
+                                       0x00000001
+                                       0x8000001e
+                                       0x00000001
+                                       0x00000001
+                                       0x00000002
+                                       0x00000000
+                                       0x00000002
+                                       0x00000001
+                                       0x00000003
+                                       0x00000008
+                                       0x00000003
+                                       0x00000002
+                                       0x00000003
+                                       0x00000006
+                                       0x06030203
+                                       0x000a0502
+                                       0x74230403
+                                       0x70000f03
+                                       0x001f0000
+                               >;
+                       };
+
+                       timing-102000000 {
+                               clock-frequency = <102000000>;
+
+                               nvidia,emem-configuration = <
+                                       0x08000001
+                                       0x80000026
+                                       0x00000001
+                                       0x00000001
+                                       0x00000003
+                                       0x00000000
+                                       0x00000002
+                                       0x00000001
+                                       0x00000003
+                                       0x00000008
+                                       0x00000003
+                                       0x00000002
+                                       0x00000003
+                                       0x00000006
+                                       0x06030203
+                                       0x000a0503
+                                       0x73c30504
+                                       0x70000f03
+                                       0x001f0000
+                               >;
+                       };
+
+                       timing-204000000 {
+                               clock-frequency = <204000000>;
+
+                               nvidia,emem-configuration = <
+                                       0x01000003
+                                       0x80000040
+                                       0x00000001
+                                       0x00000001
+                                       0x00000004
+                                       0x00000002
+                                       0x00000003
+                                       0x00000001
+                                       0x00000003
+                                       0x00000008
+                                       0x00000003
+                                       0x00000002
+                                       0x00000004
+                                       0x00000006
+                                       0x06040203
+                                       0x000a0504
+                                       0x73840a05
+                                       0x70000f03
+                                       0x001f0000
+                               >;
+                       };
+
+                       timing-300000000 {
+                               clock-frequency = <300000000>;
+
+                               nvidia,emem-configuration = <
+                                       0x08000004
+                                       0x80000040
+                                       0x00000001
+                                       0x00000002
+                                       0x00000007
+                                       0x00000004
+                                       0x00000004
+                                       0x00000001
+                                       0x00000002
+                                       0x00000007
+                                       0x00000002
+                                       0x00000002
+                                       0x00000004
+                                       0x00000006
+                                       0x06040202
+                                       0x000b0607
+                                       0x77450e08
+                                       0x70000f03
+                                       0x001f0000
+                               >;
+                       };
+
+                       timing-396000000 {
+                               clock-frequency = <396000000>;
+
+                               nvidia,emem-configuration = <
+                                       0x0f000005
+                                       0x80000040
+                                       0x00000001
+                                       0x00000002
+                                       0x00000009
+                                       0x00000005
+                                       0x00000006
+                                       0x00000001
+                                       0x00000002
+                                       0x00000008
+                                       0x00000002
+                                       0x00000002
+                                       0x00000004
+                                       0x00000006
+                                       0x06040202
+                                       0x000d0709
+                                       0x7586120a
+                                       0x70000f03
+                                       0x001f0000
+                               >;
+                       };
+
+                       timing-528000000 {
+                               clock-frequency = <528000000>;
+
+                               nvidia,emem-configuration = <
+                                       0x0f000007
+                                       0x80000040
+                                       0x00000002
+                                       0x00000003
+                                       0x0000000c
+                                       0x00000007
+                                       0x00000008
+                                       0x00000001
+                                       0x00000002
+                                       0x00000009
+                                       0x00000002
+                                       0x00000002
+                                       0x00000005
+                                       0x00000006
+                                       0x06050202
+                                       0x0010090c
+                                       0x7428180d
+                                       0x70000f03
+                                       0x001f0000
+                               >;
+                       };
+
+                       timing-600000000 {
+                               clock-frequency = <600000000>;
+
+                               nvidia,emem-configuration = <
+                                       0x00000009
+                                       0x80000040
+                                       0x00000003
+                                       0x00000004
+                                       0x0000000e
+                                       0x00000009
+                                       0x0000000a
+                                       0x00000001
+                                       0x00000003
+                                       0x0000000b
+                                       0x00000002
+                                       0x00000002
+                                       0x00000005
+                                       0x00000007
+                                       0x07050202
+                                       0x00130b0e
+                                       0x73a91b0f
+                                       0x70000f03
+                                       0x001f0000
+                               >;
+                       };
+
+                       timing-792000000 {
+                               clock-frequency = <792000000>;
+
+                               nvidia,emem-configuration = <
+                                       0x0e00000b
+                                       0x80000040
+                                       0x00000004
+                                       0x00000005
+                                       0x00000013
+                                       0x0000000c
+                                       0x0000000d
+                                       0x00000002
+                                       0x00000003
+                                       0x0000000c
+                                       0x00000002
+                                       0x00000002
+                                       0x00000006
+                                       0x00000008
+                                       0x08060202
+                                       0x00170e13
+                                       0x736c2414
+                                       0x70000f02
+                                       0x001f0000
+                               >;
+                       };
+
+                       timing-924000000 {
+                               clock-frequency = <924000000>;
+
+                               nvidia,emem-configuration = <
+                                       0x0e00000d
+                                       0x80000040
+                                       0x00000005
+                                       0x00000006
+                                       0x00000016
+                                       0x0000000e
+                                       0x0000000f
+                                       0x00000002
+                                       0x00000004
+                                       0x0000000e
+                                       0x00000002
+                                       0x00000002
+                                       0x00000006
+                                       0x00000009
+                                       0x09060202
+                                       0x001a1016
+                                       0x734e2a17
+                                       0x70000f02
+                                       0x001f0000
+                               >;
+                       };
+               };
+       };
+};
index dbfaba09703a62f0b88aa043286d14f9b2a8e883..ed8a8acd3d34b44d9e63afedf6f6a88e541e96d5 100644 (file)
@@ -3,6 +3,8 @@
 #include <dt-bindings/input/input.h>
 #include "tegra124.dtsi"
 
+#include "tegra124-jetson-tk1-emc.dtsi"
+
 / {
        model = "NVIDIA Tegra124 Jetson TK1";
        compatible = "nvidia,jetson-tk1", "nvidia,tegra124";
                                nvidia,pins = "clk_32k_out_pa0";
                                nvidia,function = "soc";
                                nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        uart3_cts_n_pa1 {
                                nvidia,pins = "uart3_cts_n_pa1";
-                               nvidia,function = "uartc";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,function = "gmi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        dap2_fs_pa2 {
                                nvidia,pins = "dap2_fs_pa2";
                                nvidia,function = "i2s1";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        dap2_sclk_pa3 {
                                nvidia,pins = "dap2_sclk_pa3";
                                nvidia,function = "i2s1";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        dap2_din_pa4 {
                                nvidia,pins = "dap2_din_pa4";
                                nvidia,function = "i2s1";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        dap2_dout_pa5 {
                                nvidia,function = "i2s1";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        sdmmc3_clk_pa6 {
                                nvidia,pins = "sdmmc3_clk_pa6";
                                nvidia,function = "sdmmc3";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        sdmmc3_cmd_pa7 {
                                nvidia,pins = "sdmmc3_cmd_pa7";
                                nvidia,pins = "pb0";
                                nvidia,function = "uartd";
                                nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        pb1 {
                                nvidia,pins = "pb1";
                                nvidia,function = "uartd";
                                nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        sdmmc3_dat3_pb4 {
                        };
                        uart3_rts_n_pc0 {
                                nvidia,pins = "uart3_rts_n_pc0";
-                               nvidia,function = "uartc";
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,function = "gmi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        uart2_txd_pc2 {
                                nvidia,pins = "uart2_rxd_pc3";
                                nvidia,function = "irda";
                                nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        gen1_i2c_scl_pc4 {
                        pc7 {
                                nvidia,pins = "pc7";
                                nvidia,function = "rsvd1";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        pg0 {
                                nvidia,pins = "pg0";
-                               nvidia,function = "rsvd1";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        pg1 {
                                nvidia,pins = "pg1";
-                               nvidia,function = "rsvd1";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        pg2 {
                                nvidia,pins = "pg2";
-                               nvidia,function = "rsvd1";
-                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        pg3 {
                                nvidia,pins = "pg3";
-                               nvidia,function = "rsvd1";
-                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        pg4 {
                                nvidia,pins = "pg4";
-                               nvidia,function = "spi4";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        pg5 {
                                nvidia,pins = "pg5";
                                nvidia,pins = "pg7";
                                nvidia,function = "spi4";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        ph0 {
                        };
                        ph2 {
                                nvidia,pins = "ph2";
-                               nvidia,function = "gmi";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        ph3 {
                                nvidia,pins = "ph3";
                                nvidia,function = "gmi";
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        ph4 {
                                nvidia,pins = "ph4";
-                               nvidia,function = "rsvd2";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        ph5 {
                                nvidia,pins = "ph5";
                                nvidia,function = "rsvd2";
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        ph6 {
                                nvidia,pins = "ph6";
                                nvidia,function = "gmi";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        ph7 {
                                nvidia,pins = "ph7";
-                               nvidia,function = "gmi";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        pi0 {
                                nvidia,pins = "pi0";
-                               nvidia,function = "rsvd1";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        pi1 {
                                nvidia,pins = "pi1";
-                               nvidia,function = "rsvd1";
-                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_ENABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        pi2 {
                                nvidia,pins = "pi2";
                                nvidia,function = "rsvd4";
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        pi3 {
                        pi4 {
                                nvidia,pins = "pi4";
                                nvidia,function = "gmi";
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        pi5 {
                                nvidia,pins = "pi5";
                                nvidia,function = "rsvd2";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        pi6 {
                                nvidia,pins = "pi6";
-                               nvidia,function = "rsvd1";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        pi7 {
                        };
                        pj0 {
                                nvidia,pins = "pj0";
-                               nvidia,function = "rsvd1";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        pj2 {
                                nvidia,pins = "pj2";
                                nvidia,function = "rsvd1";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        uart2_cts_n_pj5 {
                                nvidia,pins = "uart2_cts_n_pj5";
                                nvidia,function = "uartb";
                                nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        uart2_rts_n_pj6 {
                        };
                        pk0 {
                                nvidia,pins = "pk0";
-                               nvidia,function = "soc";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        pk1 {
                                nvidia,pins = "pk1";
-                               nvidia,function = "rsvd4";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        pk2 {
                                nvidia,pins = "pk2";
-                               nvidia,function = "rsvd1";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        pk3 {
                                nvidia,pins = "pk3";
                                nvidia,function = "gmi";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        pk4 {
                                nvidia,pins = "pk4";
-                               nvidia,function = "rsvd2";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        spdif_out_pk5 {
                                nvidia,pins = "spdif_out_pk5";
                                nvidia,function = "rsvd2";
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        spdif_in_pk6 {
                                nvidia,pins = "spdif_in_pk6";
-                               nvidia,function = "rsvd2";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        dap1_fs_pn0 {
                                nvidia,pins = "dap1_fs_pn0";
-                               nvidia,function = "i2s0";
+                               nvidia,function = "rsvd4";
                                nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        dap1_din_pn1 {
                                nvidia,pins = "dap1_din_pn1";
-                               nvidia,function = "i2s0";
+                               nvidia,function = "rsvd4";
                                nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        dap1_dout_pn2 {
                                nvidia,pins = "dap1_dout_pn2";
                        };
                        dap1_sclk_pn3 {
                                nvidia,pins = "dap1_sclk_pn3";
-                               nvidia,function = "i2s0";
+                               nvidia,function = "rsvd4";
                                nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        usb_vbus_en0_pn4 {
                                nvidia,pins = "usb_vbus_en0_pn4";
                                nvidia,function = "usb";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
-                               nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_DISABLE>;
                        };
                        usb_vbus_en1_pn5 {
                                nvidia,pins = "usb_vbus_en1_pn5";
                                nvidia,function = "usb";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
-                               nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_DISABLE>;
                        };
                        hdmi_int_pn7 {
                                nvidia,pins = "hdmi_int_pn7";
-                               nvidia,function = "rsvd1";
                                nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                                nvidia,rcv-sel = <TEGRA_PIN_DISABLE>;
                        };
                        ulpi_data7_po0 {
                                nvidia,pins = "ulpi_data7_po0";
                                nvidia,function = "ulpi";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        ulpi_data0_po1 {
                                nvidia,pins = "ulpi_data0_po1";
-                               nvidia,function = "ulpi";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        ulpi_data1_po2 {
                                nvidia,pins = "ulpi_data1_po2";
                                nvidia,function = "ulpi";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        ulpi_data2_po3 {
                                nvidia,pins = "ulpi_data2_po3";
                                nvidia,function = "ulpi";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        ulpi_data3_po4 {
                                nvidia,pins = "ulpi_data3_po4";
-                               nvidia,function = "ulpi";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        ulpi_data4_po5 {
                                nvidia,pins = "ulpi_data4_po5";
                                nvidia,function = "ulpi";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        ulpi_data5_po6 {
                                nvidia,pins = "ulpi_data5_po6";
                                nvidia,function = "ulpi";
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        ulpi_data6_po7 {
                                nvidia,pins = "ulpi_data6_po7";
                                nvidia,function = "ulpi";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        dap3_fs_pp0 {
                                nvidia,pins = "dap3_fs_pp0";
                                nvidia,function = "i2s2";
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        dap3_din_pp1 {
                                nvidia,pins = "dap3_din_pp1";
                                nvidia,function = "i2s2";
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        dap3_dout_pp2 {
                                nvidia,pins = "dap3_dout_pp2";
-                               nvidia,function = "rsvd4";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        dap4_fs_pp4 {
                                nvidia,pins = "dap4_fs_pp4";
-                               nvidia,function = "i2s3";
+                               nvidia,function = "rsvd4";
                                nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        dap4_din_pp5 {
                                nvidia,pins = "dap4_din_pp5";
-                               nvidia,function = "i2s3";
+                               nvidia,function = "rsvd3";
                                nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        dap4_dout_pp6 {
                                nvidia,pins = "dap4_dout_pp6";
-                               nvidia,function = "i2s3";
+                               nvidia,function = "rsvd4";
                                nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        dap4_sclk_pp7 {
                                nvidia,pins = "dap4_sclk_pp7";
-                               nvidia,function = "i2s3";
+                               nvidia,function = "rsvd3";
                                nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        kb_col0_pq0 {
                                nvidia,pins = "kb_col0_pq0";
-                               nvidia,function = "rsvd2";
                                nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        kb_col1_pq1 {
                                nvidia,pins = "kb_col1_pq1";
                                nvidia,function = "rsvd2";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        kb_col2_pq2 {
                                nvidia,pins = "kb_col2_pq2";
                                nvidia,function = "rsvd2";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        kb_col3_pq3 {
                                nvidia,pins = "kb_col3_pq3";
-                               nvidia,function = "kbc";
-                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_ENABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        kb_col4_pq4 {
                                nvidia,pins = "kb_col4_pq4";
                                nvidia,function = "sdmmc3";
                                nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        kb_col5_pq5 {
                                nvidia,pins = "kb_col5_pq5";
-                               nvidia,function = "rsvd2";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        kb_col6_pq6 {
                                nvidia,pins = "kb_col6_pq6";
                                nvidia,function = "rsvd2";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        kb_col7_pq7 {
                                nvidia,pins = "kb_col7_pq7";
-                               nvidia,function = "rsvd2";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        kb_row0_pr0 {
                                nvidia,pins = "kb_row0_pr0";
-                               nvidia,function = "rsvd2";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        kb_row1_pr1 {
                                nvidia,pins = "kb_row1_pr1";
                                nvidia,function = "rsvd2";
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        kb_row2_pr2 {
                                nvidia,pins = "kb_row2_pr2";
-                               nvidia,function = "rsvd2";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        kb_row3_pr3 {
                                nvidia,pins = "kb_row3_pr3";
-                               nvidia,function = "sys";
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,function = "kbc";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        kb_row4_pr4 {
                                nvidia,pins = "kb_row4_pr4";
-                               nvidia,function = "rsvd3";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        kb_row5_pr5 {
                                nvidia,pins = "kb_row5_pr5";
                                nvidia,function = "rsvd3";
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        kb_row6_pr6 {
                                nvidia,pins = "kb_row6_pr6";
                                nvidia,function = "displaya_alt";
-                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        kb_row7_pr7 {
                                nvidia,pins = "kb_row7_pr7";
-                               nvidia,function = "rsvd2";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        kb_row8_ps0 {
                                nvidia,pins = "kb_row8_ps0";
                                nvidia,function = "rsvd2";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        kb_row9_ps1 {
                                nvidia,pins = "kb_row9_ps1";
-                               nvidia,function = "rsvd2";
+                               nvidia,function = "uarta";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        kb_row10_ps2 {
                                nvidia,pins = "kb_row10_ps2";
-                               nvidia,function = "rsvd2";
+                               nvidia,function = "uarta";
                                nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        kb_row11_ps3 {
                                nvidia,pins = "kb_row11_ps3";
                                nvidia,function = "rsvd2";
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        kb_row12_ps4 {
                                nvidia,pins = "kb_row12_ps4";
                                nvidia,function = "rsvd2";
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        kb_row13_ps5 {
                                nvidia,pins = "kb_row13_ps5";
                                nvidia,function = "rsvd2";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        kb_row14_ps6 {
                                nvidia,pins = "kb_row14_ps6";
                                nvidia,function = "rsvd2";
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        kb_row15_ps7 {
                                nvidia,pins = "kb_row15_ps7";
-                               nvidia,function = "soc";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        kb_row16_pt0 {
                                nvidia,pins = "kb_row16_pt0";
-                               nvidia,function = "rsvd2";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        kb_row17_pt1 {
                                nvidia,pins = "kb_row17_pt1";
-                               nvidia,function = "rsvd2";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        gen2_i2c_scl_pt5 {
                                nvidia,pins = "gen2_i2c_scl_pt5";
                        };
                        pu0 {
                                nvidia,pins = "pu0";
-                               nvidia,function = "rsvd4";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        pu1 {
                                nvidia,pins = "pu1";
-                               nvidia,function = "rsvd1";
-                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        pu2 {
                                nvidia,pins = "pu2";
-                               nvidia,function = "rsvd1";
-                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        pu3 {
                                nvidia,pins = "pu3";
-                               nvidia,function = "gmi";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        pu4 {
                                nvidia,pins = "pu4";
-                               nvidia,function = "gmi";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        pu5 {
                                nvidia,pins = "pu5";
-                               nvidia,function = "gmi";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        pu6 {
                                nvidia,pins = "pu6";
-                               nvidia,function = "rsvd3";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        pv0 {
                                nvidia,pins = "pv0";
-                               nvidia,function = "rsvd1";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        pv1 {
                                nvidia,pins = "pv1";
-                               nvidia,function = "rsvd1";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        sdmmc3_cd_n_pv2 {
                                nvidia,pins = "sdmmc3_cd_n_pv2";
                                nvidia,function = "sdmmc3";
                                nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        sdmmc1_wp_n_pv3 {
                        gpio_w2_aud_pw2 {
                                nvidia,pins = "gpio_w2_aud_pw2";
                                nvidia,function = "rsvd2";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        gpio_w3_aud_pw3 {
                                nvidia,pins = "gpio_w3_aud_pw3";
                                nvidia,function = "spi6";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        dap_mclk1_pw4 {
                                nvidia,pins = "dap_mclk1_pw4";
                        };
                        uart3_txd_pw6 {
                                nvidia,pins = "uart3_txd_pw6";
-                               nvidia,function = "uartc";
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        uart3_rxd_pw7 {
                                nvidia,pins = "uart3_rxd_pw7";
-                               nvidia,function = "uartc";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        dvfs_pwm_px0 {
                                nvidia,pins = "dvfs_pwm_px0";
                        };
                        gpio_x1_aud_px1 {
                                nvidia,pins = "gpio_x1_aud_px1";
-                               nvidia,function = "rsvd2";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        dvfs_clk_px2 {
                                nvidia,pins = "dvfs_clk_px2";
                        gpio_x3_aud_px3 {
                                nvidia,pins = "gpio_x3_aud_px3";
                                nvidia,function = "rsvd4";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        gpio_x4_aud_px4 {
                                nvidia,pins = "gpio_x4_aud_px4";
-                               nvidia,function = "gmi";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        gpio_x5_aud_px5 {
                                nvidia,pins = "gpio_x5_aud_px5";
                                nvidia,function = "rsvd4";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        gpio_x6_aud_px6 {
                                nvidia,pins = "gpio_x6_aud_px6";
                                nvidia,function = "gmi";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        gpio_x7_aud_px7 {
                                nvidia,pins = "gpio_x7_aud_px7";
-                               nvidia,function = "rsvd1";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        ulpi_dir_py1 {
                                nvidia,pins = "ulpi_dir_py1";
                                nvidia,function = "spi1";
-                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        ulpi_nxt_py2 {
                        sdmmc1_dat3_py4 {
                                nvidia,pins = "sdmmc1_dat3_py4";
                                nvidia,function = "sdmmc1";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        sdmmc1_dat2_py5 {
                                nvidia,pins = "sdmmc1_dat2_py5";
                                nvidia,function = "sdmmc1";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        sdmmc1_dat1_py6 {
                                nvidia,pins = "sdmmc1_dat1_py6";
                                nvidia,function = "sdmmc1";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        sdmmc1_dat0_py7 {
                                nvidia,pins = "sdmmc1_dat0_py7";
-                               nvidia,function = "sdmmc1";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        sdmmc1_clk_pz0 {
                                nvidia,pins = "sdmmc1_clk_pz0";
-                               nvidia,function = "sdmmc1";
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,function = "rsvd3";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        sdmmc1_cmd_pz1 {
                                nvidia,pins = "sdmmc1_cmd_pz1";
                                nvidia,function = "sdmmc1";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        pwr_i2c_scl_pz6 {
                                nvidia,pins = "pwr_i2c_scl_pz6";
                        };
                        pbb3 {
                                nvidia,pins = "pbb3";
-                               nvidia,function = "vgp3";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        pbb5 {
                                nvidia,pins = "pbb5";
-                               nvidia,function = "rsvd3";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        pbb6 {
                                nvidia,pins = "pbb6";
-                               nvidia,function = "rsvd2";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        pbb7 {
                                nvidia,pins = "pbb7";
-                               nvidia,function = "rsvd2";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        pcc1 {
                                nvidia,pins = "pcc1";
-                               nvidia,function = "rsvd2";
-                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        pcc2 {
                                nvidia,pins = "pcc2";
-                               nvidia,function = "rsvd2";
-                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        clk2_req_pcc5 {
                                nvidia,pins = "clk2_req_pcc5";
                                nvidia,function = "rsvd2";
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        pex_l0_rst_n_pdd1 {
                        pex_l0_clkreq_n_pdd2 {
                                nvidia,pins = "pex_l0_clkreq_n_pdd2";
                                nvidia,function = "pe0";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        pex_wake_n_pdd3 {
                                nvidia,pins = "pex_wake_n_pdd3";
                                nvidia,function = "pe";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        pex_l1_rst_n_pdd5 {
                        pex_l1_clkreq_n_pdd6 {
                                nvidia,pins = "pex_l1_clkreq_n_pdd6";
                                nvidia,function = "pe1";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        clk3_out_pee0 {
                        clk3_req_pee1 {
                                nvidia,pins = "clk3_req_pee1";
                                nvidia,function = "rsvd2";
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                        dap_mclk1_req_pee2 {
                                nvidia,pins = "dap_mclk1_req_pee2";
-                               nvidia,function = "sata";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
-                               nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_DISABLE>;
                        };
                        sdmmc3_clk_lb_out_pee4 {
                                nvidia,pins = "sdmmc3_clk_lb_out_pee4";
                        dp_hpd_pff0 {
                                nvidia,pins = "dp_hpd_pff0";
                                nvidia,function = "dp";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        usb_vbus_en2_pff1 {
                                nvidia,pins = "usb_vbus_en2_pff1";
                                nvidia,function = "rsvd2";
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                                nvidia,open-drain = <TEGRA_PIN_DISABLE>;
                        };
                        pff2 {
                                nvidia,pins = "pff2";
                                nvidia,function = "rsvd2";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                                nvidia,open-drain = <TEGRA_PIN_DISABLE>;
                        };
                        core_pwr_req {
                        };
                        cpu_pwr_req {
                                nvidia,pins = "cpu_pwr_req";
-                               nvidia,function = "rsvd2";
+                               nvidia,function = "cpu";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                                nvidia,pins = "pwr_int_n";
                                nvidia,function = "pmi";
                                nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        reset_out_n {
                                nvidia,function = "reset_out_n";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        owr {
                                nvidia,pins = "owr";
                        };
                        clk_32k_in {
                                nvidia,pins = "clk_32k_in";
-                               nvidia,function = "rsvd2";
+                               nvidia,function = "clk";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        jtag_rtck {
diff --git a/arch/arm/boot/dts/tegra124-nyan-big-emc.dtsi b/arch/arm/boot/dts/tegra124-nyan-big-emc.dtsi
new file mode 100644 (file)
index 0000000..1a5748d
--- /dev/null
@@ -0,0 +1,2023 @@
+/ {
+       clock@0,60006000 {
+               emc-timings-1 {
+                       nvidia,ram-code = <1>;
+
+                       timing-12750000 {
+                               clock-frequency = <12750000>;
+                               nvidia,parent-clock-frequency = <408000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_P>;
+                               clock-names = "emc-parent";
+                       };
+                       timing-20400000 {
+                               clock-frequency = <20400000>;
+                               nvidia,parent-clock-frequency = <408000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_P>;
+                               clock-names = "emc-parent";
+                       };
+                       timing-40800000 {
+                               clock-frequency = <40800000>;
+                               nvidia,parent-clock-frequency = <408000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_P>;
+                               clock-names = "emc-parent";
+                       };
+                       timing-68000000 {
+                               clock-frequency = <68000000>;
+                               nvidia,parent-clock-frequency = <408000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_P>;
+                               clock-names = "emc-parent";
+                       };
+                       timing-102000000 {
+                               clock-frequency = <102000000>;
+                               nvidia,parent-clock-frequency = <408000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_P>;
+                               clock-names = "emc-parent";
+                       };
+                       timing-204000000 {
+                               clock-frequency = <204000000>;
+                               nvidia,parent-clock-frequency = <408000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_P>;
+                               clock-names = "emc-parent";
+                       };
+                       timing-300000000 {
+                               clock-frequency = <300000000>;
+                               nvidia,parent-clock-frequency = <600000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_C>;
+                               clock-names = "emc-parent";
+                       };
+                       timing-396000000 {
+                               clock-frequency = <396000000>;
+                               nvidia,parent-clock-frequency = <792000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_M>;
+                               clock-names = "emc-parent";
+                       };
+                       /* TODO: Add 528MHz frequency */
+                       timing-600000000 {
+                               clock-frequency = <600000000>;
+                               nvidia,parent-clock-frequency = <600000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_C_UD>;
+                               clock-names = "emc-parent";
+                       };
+                       timing-792000000 {
+                               clock-frequency = <792000000>;
+                               nvidia,parent-clock-frequency = <792000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_M_UD>;
+                               clock-names = "emc-parent";
+                       };
+               };
+       };
+
+       emc@0,7001b000 {
+               emc-timings-1 {
+                       nvidia,ram-code = <1>;
+
+                       timing-12750000 {
+                               clock-frequency = <12750000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430000>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000008>;
+                               nvidia,emc-cfg = <0x73240000>;
+                               nvidia,emc-cfg-2 = <0x000008c5>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100003>;
+                               nvidia,emc-mode-2 = <0x80200008>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80001221>;
+                               nvidia,emc-mrs-wait-cnt = <0x000c000c>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040128>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x0130b118>;
+                               nvidia,emc-zcal-cnt-long = <0x00000042>;
+                               nvidia,emc-zcal-interval = <0x00000000>;
+
+                               nvidia,emc-configuration = <
+                                       0x00000000
+                                       0x00000003
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000004
+                                       0x0000000a
+                                       0x00000003
+                                       0x0000000b
+                                       0x00000000
+                                       0x00000000
+                                       0x00000003
+                                       0x00000003
+                                       0x00000000
+                                       0x00000006
+                                       0x00000006
+                                       0x00000006
+                                       0x00000002
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00010000
+                                       0x00000003
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000004
+                                       0x0000000c
+                                       0x0000000d
+                                       0x0000000f
+                                       0x00000060
+                                       0x00000000
+                                       0x00000018
+                                       0x00000002
+                                       0x00000002
+                                       0x00000001
+                                       0x00000000
+                                       0x00000007
+                                       0x0000000f
+                                       0x00000005
+                                       0x00000005
+                                       0x00000004
+                                       0x00000005
+                                       0x00000004
+                                       0x00000000
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00000064
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x106aa298
+                                       0x002c00a0
+                                       0x00008000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00004000
+                                       0x00000000
+                                       0x00000000
+                                       0x00004000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x10000280
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc081
+                                       0x00000303
+                                       0x81f1f108
+                                       0x07070004
+                                       0x0000003f
+                                       0x016eeeee
+                                       0x51451400
+                                       0x00514514
+                                       0x00514514
+                                       0x51451400
+                                       0x0000003f
+                                       0x00000007
+                                       0x00000000
+                                       0x00000042
+                                       0x000c000c
+                                       0x00000000
+                                       0x00000003
+                                       0x0000f2f3
+                                       0x800001c5
+                                       0x0000000a
+                               >;
+                       };
+
+                       timing-20400000 {
+                               clock-frequency = <20400000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430000>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000008>;
+                               nvidia,emc-cfg = <0x73240000>;
+                               nvidia,emc-cfg-2 = <0x000008c5>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100003>;
+                               nvidia,emc-mode-2 = <0x80200008>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80001221>;
+                               nvidia,emc-mrs-wait-cnt = <0x000c000c>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040128>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x0130b118>;
+                               nvidia,emc-zcal-cnt-long = <0x00000042>;
+                               nvidia,emc-zcal-interval = <0x00000000>;
+
+                               nvidia,emc-configuration = <
+                                       0x00000000
+                                       0x00000005
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000004
+                                       0x0000000a
+                                       0x00000003
+                                       0x0000000b
+                                       0x00000000
+                                       0x00000000
+                                       0x00000003
+                                       0x00000003
+                                       0x00000000
+                                       0x00000006
+                                       0x00000006
+                                       0x00000006
+                                       0x00000002
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00010000
+                                       0x00000003
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000004
+                                       0x0000000c
+                                       0x0000000d
+                                       0x0000000f
+                                       0x0000009a
+                                       0x00000000
+                                       0x00000026
+                                       0x00000002
+                                       0x00000002
+                                       0x00000001
+                                       0x00000000
+                                       0x00000007
+                                       0x0000000f
+                                       0x00000006
+                                       0x00000006
+                                       0x00000004
+                                       0x00000005
+                                       0x00000004
+                                       0x00000000
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x000000a0
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x106aa298
+                                       0x002c00a0
+                                       0x00008000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00004000
+                                       0x00000000
+                                       0x00000000
+                                       0x00004000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x10000280
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc081
+                                       0x00000303
+                                       0x81f1f108
+                                       0x07070004
+                                       0x0000003f
+                                       0x016eeeee
+                                       0x51451400
+                                       0x00514514
+                                       0x00514514
+                                       0x51451400
+                                       0x0000003f
+                                       0x0000000b
+                                       0x00000000
+                                       0x00000042
+                                       0x000c000c
+                                       0x00000000
+                                       0x00000003
+                                       0x0000f2f3
+                                       0x8000023a
+                                       0x0000000a
+                               >;
+                       };
+
+                       timing-40800000 {
+                               clock-frequency = <40800000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430000>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000008>;
+                               nvidia,emc-cfg = <0x73240000>;
+                               nvidia,emc-cfg-2 = <0x000008c5>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100003>;
+                               nvidia,emc-mode-2 = <0x80200008>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80001221>;
+                               nvidia,emc-mrs-wait-cnt = <0x000c000c>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040128>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x0130b118>;
+                               nvidia,emc-zcal-cnt-long = <0x00000042>;
+                               nvidia,emc-zcal-interval = <0x00000000>;
+
+                               nvidia,emc-configuration = <
+                                       0x00000001
+                                       0x0000000a
+                                       0x00000000
+                                       0x00000001
+                                       0x00000000
+                                       0x00000004
+                                       0x0000000a
+                                       0x00000003
+                                       0x0000000b
+                                       0x00000000
+                                       0x00000000
+                                       0x00000003
+                                       0x00000003
+                                       0x00000000
+                                       0x00000006
+                                       0x00000006
+                                       0x00000006
+                                       0x00000002
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00010000
+                                       0x00000003
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000004
+                                       0x0000000c
+                                       0x0000000d
+                                       0x0000000f
+                                       0x00000134
+                                       0x00000000
+                                       0x0000004d
+                                       0x00000002
+                                       0x00000002
+                                       0x00000001
+                                       0x00000000
+                                       0x00000008
+                                       0x0000000f
+                                       0x0000000c
+                                       0x0000000c
+                                       0x00000004
+                                       0x00000005
+                                       0x00000004
+                                       0x00000000
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x0000013f
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x106aa298
+                                       0x002c00a0
+                                       0x00008000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00004000
+                                       0x00000000
+                                       0x00000000
+                                       0x00004000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x10000280
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc081
+                                       0x00000303
+                                       0x81f1f108
+                                       0x07070004
+                                       0x0000003f
+                                       0x016eeeee
+                                       0x51451400
+                                       0x00514514
+                                       0x00514514
+                                       0x51451400
+                                       0x0000003f
+                                       0x00000015
+                                       0x00000000
+                                       0x00000042
+                                       0x000c000c
+                                       0x00000000
+                                       0x00000003
+                                       0x0000f2f3
+                                       0x80000370
+                                       0x0000000a
+                               >;
+                       };
+
+                       timing-68000000 {
+                               clock-frequency = <68000000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430000>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000008>;
+                               nvidia,emc-cfg = <0x73240000>;
+                               nvidia,emc-cfg-2 = <0x000008c5>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100003>;
+                               nvidia,emc-mode-2 = <0x80200008>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80001221>;
+                               nvidia,emc-mrs-wait-cnt = <0x000c000c>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040128>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x0130b118>;
+                               nvidia,emc-zcal-cnt-long = <0x00000042>;
+                               nvidia,emc-zcal-interval = <0x00000000>;
+
+                               nvidia,emc-configuration = <
+                                       0x00000003
+                                       0x00000011
+                                       0x00000000
+                                       0x00000002
+                                       0x00000000
+                                       0x00000004
+                                       0x0000000a
+                                       0x00000003
+                                       0x0000000b
+                                       0x00000000
+                                       0x00000000
+                                       0x00000003
+                                       0x00000003
+                                       0x00000000
+                                       0x00000006
+                                       0x00000006
+                                       0x00000006
+                                       0x00000002
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00010000
+                                       0x00000003
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000004
+                                       0x0000000c
+                                       0x0000000d
+                                       0x0000000f
+                                       0x00000202
+                                       0x00000000
+                                       0x00000080
+                                       0x00000002
+                                       0x00000002
+                                       0x00000001
+                                       0x00000000
+                                       0x0000000f
+                                       0x0000000f
+                                       0x00000013
+                                       0x00000013
+                                       0x00000004
+                                       0x00000005
+                                       0x00000004
+                                       0x00000001
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00000213
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x106aa298
+                                       0x002c00a0
+                                       0x00008000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00004000
+                                       0x00000000
+                                       0x00000000
+                                       0x00004000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x10000280
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc081
+                                       0x00000303
+                                       0x81f1f108
+                                       0x07070004
+                                       0x0000003f
+                                       0x016eeeee
+                                       0x51451400
+                                       0x00514514
+                                       0x00514514
+                                       0x51451400
+                                       0x0000003f
+                                       0x00000022
+                                       0x00000000
+                                       0x00000042
+                                       0x000c000c
+                                       0x00000000
+                                       0x00000003
+                                       0x0000f2f3
+                                       0x8000050e
+                                       0x0000000a
+                               >;
+                       };
+
+                       timing-102000000 {
+                               clock-frequency = <102000000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430000>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000008>;
+                               nvidia,emc-cfg = <0x73240000>;
+                               nvidia,emc-cfg-2 = <0x000008c5>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100003>;
+                               nvidia,emc-mode-2 = <0x80200008>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80001221>;
+                               nvidia,emc-mrs-wait-cnt = <0x000c000c>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040128>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x0130b118>;
+                               nvidia,emc-zcal-cnt-long = <0x00000042>;
+                               nvidia,emc-zcal-interval = <0x00000000>;
+
+                               nvidia,emc-configuration = <
+                                       0x00000004
+                                       0x0000001a
+                                       0x00000000
+                                       0x00000003
+                                       0x00000001
+                                       0x00000004
+                                       0x0000000a
+                                       0x00000003
+                                       0x0000000b
+                                       0x00000001
+                                       0x00000001
+                                       0x00000003
+                                       0x00000003
+                                       0x00000000
+                                       0x00000006
+                                       0x00000006
+                                       0x00000006
+                                       0x00000002
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00010000
+                                       0x00000003
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000004
+                                       0x0000000c
+                                       0x0000000d
+                                       0x0000000f
+                                       0x00000304
+                                       0x00000000
+                                       0x000000c1
+                                       0x00000002
+                                       0x00000002
+                                       0x00000001
+                                       0x00000000
+                                       0x00000018
+                                       0x0000000f
+                                       0x0000001c
+                                       0x0000001c
+                                       0x00000004
+                                       0x00000005
+                                       0x00000004
+                                       0x00000003
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x0000031c
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x106aa298
+                                       0x002c00a0
+                                       0x00008000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00004000
+                                       0x00000000
+                                       0x00000000
+                                       0x00004000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x10000280
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc081
+                                       0x00000303
+                                       0x81f1f108
+                                       0x07070004
+                                       0x0000003f
+                                       0x016eeeee
+                                       0x51451400
+                                       0x00514514
+                                       0x00514514
+                                       0x51451400
+                                       0x0000003f
+                                       0x00000033
+                                       0x00000000
+                                       0x00000042
+                                       0x000c000c
+                                       0x00000000
+                                       0x00000003
+                                       0x0000f2f3
+                                       0x80000713
+                                       0x0000000a
+                               >;
+                       };
+
+                       timing-204000000 {
+                               clock-frequency = <204000000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430000>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000008>;
+                               nvidia,emc-cfg = <0x73240000>;
+                               nvidia,emc-cfg-2 = <0x0000088d>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100003>;
+                               nvidia,emc-mode-2 = <0x80200008>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80001221>;
+                               nvidia,emc-mrs-wait-cnt = <0x000c000c>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040008>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x0130b118>;
+                               nvidia,emc-zcal-cnt-long = <0x00000042>;
+                               nvidia,emc-zcal-interval = <0x00020000>;
+
+                               nvidia,emc-configuration = <
+                                       0x00000009
+                                       0x00000035
+                                       0x00000000
+                                       0x00000007
+                                       0x00000002
+                                       0x00000005
+                                       0x0000000a
+                                       0x00000003
+                                       0x0000000b
+                                       0x00000002
+                                       0x00000002
+                                       0x00000003
+                                       0x00000003
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00000006
+                                       0x00000002
+                                       0x00000000
+                                       0x00000004
+                                       0x00000006
+                                       0x00010000
+                                       0x00000003
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000003
+                                       0x0000000d
+                                       0x0000000f
+                                       0x00000011
+                                       0x00000607
+                                       0x00000000
+                                       0x00000181
+                                       0x00000002
+                                       0x00000002
+                                       0x00000001
+                                       0x00000000
+                                       0x00000032
+                                       0x0000000f
+                                       0x00000038
+                                       0x00000038
+                                       0x00000004
+                                       0x00000005
+                                       0x00000004
+                                       0x00000007
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00000638
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x106aa298
+                                       0x002c00a0
+                                       0x00008000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00004000
+                                       0x00000000
+                                       0x00000000
+                                       0x00004000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00090000
+                                       0x00090000
+                                       0x00094000
+                                       0x00094000
+                                       0x00009400
+                                       0x00009000
+                                       0x00009000
+                                       0x00009000
+                                       0x10000280
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc081
+                                       0x00000303
+                                       0x81f1f108
+                                       0x07070004
+                                       0x0000003f
+                                       0x016eeeee
+                                       0x51451400
+                                       0x00514514
+                                       0x00514514
+                                       0x51451400
+                                       0x0000003f
+                                       0x00000066
+                                       0x00000000
+                                       0x00000100
+                                       0x000c000c
+                                       0x00000000
+                                       0x00000003
+                                       0x0000d2b3
+                                       0x80000d22
+                                       0x0000000a
+                               >;
+                       };
+
+                       timing-300000000 {
+                               clock-frequency = <300000000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430000>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000000>;
+                               nvidia,emc-cfg = <0x73340000>;
+                               nvidia,emc-cfg-2 = <0x000008d5>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100002>;
+                               nvidia,emc-mode-2 = <0x80200000>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80000321>;
+                               nvidia,emc-mrs-wait-cnt = <0x0174000c>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040128>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x01231339>;
+                               nvidia,emc-zcal-cnt-long = <0x00000042>;
+                               nvidia,emc-zcal-interval = <0x00020000>;
+
+                               nvidia,emc-configuration = <
+                                       0x0000000d
+                                       0x0000004c
+                                       0x00000000
+                                       0x00000009
+                                       0x00000003
+                                       0x00000004
+                                       0x00000008
+                                       0x00000002
+                                       0x00000009
+                                       0x00000003
+                                       0x00000003
+                                       0x00000002
+                                       0x00000002
+                                       0x00000000
+                                       0x00000003
+                                       0x00000003
+                                       0x00000005
+                                       0x00000002
+                                       0x00000000
+                                       0x00000002
+                                       0x00000007
+                                       0x00020000
+                                       0x00000003
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000001
+                                       0x0000000e
+                                       0x00000010
+                                       0x00000012
+                                       0x000008e4
+                                       0x00000000
+                                       0x00000239
+                                       0x00000001
+                                       0x00000008
+                                       0x00000001
+                                       0x00000000
+                                       0x0000004a
+                                       0x0000000e
+                                       0x00000051
+                                       0x00000200
+                                       0x00000004
+                                       0x00000005
+                                       0x00000004
+                                       0x00000009
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00000924
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x104ab098
+                                       0x002c00a0
+                                       0x00008000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00098000
+                                       0x00098000
+                                       0x00000000
+                                       0x00098000
+                                       0x00098000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00060000
+                                       0x00060000
+                                       0x00060000
+                                       0x00060000
+                                       0x00006000
+                                       0x00006000
+                                       0x00006000
+                                       0x00006000
+                                       0x10000280
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc081
+                                       0x00000101
+                                       0x81f1f108
+                                       0x07070004
+                                       0x00000000
+                                       0x016eeeee
+                                       0x51451420
+                                       0x00514514
+                                       0x00514514
+                                       0x51451400
+                                       0x0000003f
+                                       0x00000096
+                                       0x00000000
+                                       0x00000100
+                                       0x0174000c
+                                       0x00000000
+                                       0x00000003
+                                       0x000052a3
+                                       0x800012d7
+                                       0x00000009
+                               >;
+                       };
+
+                       timing-396000000 {
+                               clock-frequency = <396000000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430000>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000000>;
+                               nvidia,emc-cfg = <0x73340000>;
+                               nvidia,emc-cfg-2 = <0x00000895>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100002>;
+                               nvidia,emc-mode-2 = <0x80200000>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80000521>;
+                               nvidia,emc-mrs-wait-cnt = <0x015b000c>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040008>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x01231339>;
+                               nvidia,emc-zcal-cnt-long = <0x00000042>;
+                               nvidia,emc-zcal-interval = <0x00020000>;
+
+                               nvidia,emc-configuration = <
+                                       0x00000012
+                                       0x00000065
+                                       0x00000000
+                                       0x0000000c
+                                       0x00000004
+                                       0x00000005
+                                       0x00000008
+                                       0x00000002
+                                       0x0000000a
+                                       0x00000004
+                                       0x00000004
+                                       0x00000002
+                                       0x00000002
+                                       0x00000000
+                                       0x00000003
+                                       0x00000003
+                                       0x00000005
+                                       0x00000002
+                                       0x00000000
+                                       0x00000001
+                                       0x00000008
+                                       0x00020000
+                                       0x00000003
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x0000000f
+                                       0x00000010
+                                       0x00000012
+                                       0x00000bd1
+                                       0x00000000
+                                       0x000002f4
+                                       0x00000001
+                                       0x00000008
+                                       0x00000001
+                                       0x00000000
+                                       0x00000063
+                                       0x0000000f
+                                       0x0000006b
+                                       0x00000200
+                                       0x00000004
+                                       0x00000005
+                                       0x00000004
+                                       0x0000000d
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00000c11
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x104ab098
+                                       0x002c00a0
+                                       0x00008000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00070000
+                                       0x00070000
+                                       0x00000000
+                                       0x00070000
+                                       0x00070000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00048000
+                                       0x00048000
+                                       0x00048000
+                                       0x00048000
+                                       0x00004800
+                                       0x00004800
+                                       0x00004800
+                                       0x00004800
+                                       0x10000280
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc081
+                                       0x00000101
+                                       0x81f1f108
+                                       0x07070004
+                                       0x00000000
+                                       0x016eeeee
+                                       0x51451420
+                                       0x00514514
+                                       0x00514514
+                                       0x51451400
+                                       0x0000003f
+                                       0x000000c6
+                                       0x00000000
+                                       0x00000100
+                                       0x015b000c
+                                       0x00000000
+                                       0x00000003
+                                       0x000052a3
+                                       0x8000188b
+                                       0x00000009
+                               >;
+                       };
+
+                       timing-600000000 {
+                               clock-frequency = <600000000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430000>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000000>;
+                               nvidia,emc-cfg = <0x73300000>;
+                               nvidia,emc-cfg-2 = <0x0000089d>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100002>;
+                               nvidia,emc-mode-2 = <0x80200010>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80000b61>;
+                               nvidia,emc-mrs-wait-cnt = <0x0128000c>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040008>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x0121113d>;
+                               nvidia,emc-zcal-cnt-long = <0x00000042>;
+                               nvidia,emc-zcal-interval = <0x00020000>;
+
+                               nvidia,emc-configuration = <
+                                       0x0000001c
+                                       0x0000009a
+                                       0x00000000
+                                       0x00000013
+                                       0x00000007
+                                       0x00000007
+                                       0x0000000b
+                                       0x00000003
+                                       0x00000010
+                                       0x00000007
+                                       0x00000007
+                                       0x00000002
+                                       0x00000002
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x0000000a
+                                       0x00000002
+                                       0x00000000
+                                       0x00000003
+                                       0x0000000b
+                                       0x00070000
+                                       0x00000003
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000002
+                                       0x00000012
+                                       0x00000016
+                                       0x00000018
+                                       0x00001208
+                                       0x00000000
+                                       0x00000482
+                                       0x00000002
+                                       0x0000000d
+                                       0x00000001
+                                       0x00000000
+                                       0x00000096
+                                       0x00000015
+                                       0x000000a2
+                                       0x00000200
+                                       0x00000004
+                                       0x00000005
+                                       0x00000004
+                                       0x00000015
+                                       0x00000000
+                                       0x00000006
+                                       0x00000006
+                                       0x00001249
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x104ab098
+                                       0xe00e00b1
+                                       0x00008000
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00048000
+                                       0x00048000
+                                       0x00000000
+                                       0x00048000
+                                       0x00048000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000004
+                                       0x00000004
+                                       0x00000002
+                                       0x00000005
+                                       0x00000006
+                                       0x00000003
+                                       0x00000006
+                                       0x00000005
+                                       0x00000004
+                                       0x00000004
+                                       0x00000002
+                                       0x00000005
+                                       0x00000006
+                                       0x00000003
+                                       0x00000006
+                                       0x00000005
+                                       0x0000000e
+                                       0x0000000e
+                                       0x0000000e
+                                       0x0000000e
+                                       0x0000000e
+                                       0x0000000e
+                                       0x0000000e
+                                       0x0000000e
+                                       0x100002a0
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc085
+                                       0x00000101
+                                       0x81f1f108
+                                       0x07070004
+                                       0x00000000
+                                       0x016eeeee
+                                       0x51451420
+                                       0x00514514
+                                       0x00514514
+                                       0x51451400
+                                       0x0606003f
+                                       0x00000000
+                                       0x00000000
+                                       0x00000100
+                                       0x0128000c
+                                       0x00000000
+                                       0x00000003
+                                       0x000040a0
+                                       0x800024aa
+                                       0x0000000e
+                               >;
+                       };
+
+                       timing-792000000 {
+                               clock-frequency = <792000000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430000>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000000>;
+                               nvidia,emc-cfg = <0x73300000>;
+                               nvidia,emc-cfg-2 = <0x0080089d>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100002>;
+                               nvidia,emc-mode-2 = <0x80200418>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80000d71>;
+                               nvidia,emc-mrs-wait-cnt = <0x00f8000c>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040000>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x0120113d>;
+                               nvidia,emc-zcal-cnt-long = <0x00000042>;
+                               nvidia,emc-zcal-interval = <0x00020000>;
+
+                               nvidia,emc-configuration = <
+                                       0x00000025
+                                       0x000000cc
+                                       0x00000000
+                                       0x0000001a
+                                       0x00000009
+                                       0x00000008
+                                       0x0000000d
+                                       0x00000004
+                                       0x00000013
+                                       0x00000009
+                                       0x00000009
+                                       0x00000003
+                                       0x00000002
+                                       0x00000000
+                                       0x00000006
+                                       0x00000006
+                                       0x0000000b
+                                       0x00000002
+                                       0x00000000
+                                       0x00000002
+                                       0x0000000d
+                                       0x00080000
+                                       0x00000004
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000001
+                                       0x00000014
+                                       0x00000018
+                                       0x0000001a
+                                       0x000017e2
+                                       0x00000000
+                                       0x000005f8
+                                       0x00000003
+                                       0x00000011
+                                       0x00000001
+                                       0x00000000
+                                       0x000000c6
+                                       0x00000018
+                                       0x000000d6
+                                       0x00000200
+                                       0x00000005
+                                       0x00000006
+                                       0x00000005
+                                       0x0000001d
+                                       0x00000000
+                                       0x00000008
+                                       0x00000008
+                                       0x00001822
+                                       0x00000000
+                                       0x80000005
+                                       0x00000000
+                                       0x104ab198
+                                       0xe00700b1
+                                       0x00008000
+                                       0x00000005
+                                       0x00000005
+                                       0x00000005
+                                       0x00000005
+                                       0x00000005
+                                       0x00000005
+                                       0x00000005
+                                       0x00000005
+                                       0x00000005
+                                       0x00000005
+                                       0x00000005
+                                       0x00000005
+                                       0x00000005
+                                       0x00000005
+                                       0x00000005
+                                       0x00000005
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00034000
+                                       0x00034000
+                                       0x00000000
+                                       0x00034000
+                                       0x00034000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000008
+                                       0x00000008
+                                       0x00000005
+                                       0x00000009
+                                       0x00000009
+                                       0x00000007
+                                       0x00000009
+                                       0x00000008
+                                       0x00000008
+                                       0x00000008
+                                       0x00000005
+                                       0x00000009
+                                       0x00000009
+                                       0x00000007
+                                       0x00000009
+                                       0x00000008
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x100002a0
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc085
+                                       0x00000101
+                                       0x81f1f108
+                                       0x07070004
+                                       0x00000000
+                                       0x016eeeee
+                                       0x61861820
+                                       0x00514514
+                                       0x00514514
+                                       0x61861800
+                                       0x0606003f
+                                       0x00000000
+                                       0x00000000
+                                       0x00000100
+                                       0x00f8000c
+                                       0x00000007
+                                       0x00000004
+                                       0x00004080
+                                       0x80003012
+                                       0x0000000f
+                               >;
+                       };
+
+               };
+       };
+
+       memory-controller@0,70019000 {
+               emc-timings-1 {
+                       nvidia,ram-code = <1>;
+
+
+                       timing-12750000 {
+                               clock-frequency = <12750000>;
+
+                               nvidia,emem-configuration = <
+                                       0x40040001
+                                       0x8000000a
+                                       0x00000001
+                                       0x00000001
+                                       0x00000002
+                                       0x00000000
+                                       0x00000002
+                                       0x00000001
+                                       0x00000002
+                                       0x00000008
+                                       0x00000003
+                                       0x00000002
+                                       0x00000003
+                                       0x00000006
+                                       0x06030203
+                                       0x000a0402
+                                       0x77e30303
+                                       0x70000f03
+                                       0x001f0000
+                               >;
+                       };
+
+                       timing-20400000 {
+                               clock-frequency = <20400000>;
+
+                               nvidia,emem-configuration = <
+                                       0x40020001
+                                       0x80000012
+                                       0x00000001
+                                       0x00000001
+                                       0x00000002
+                                       0x00000000
+                                       0x00000002
+                                       0x00000001
+                                       0x00000002
+                                       0x00000008
+                                       0x00000003
+                                       0x00000002
+                                       0x00000003
+                                       0x00000006
+                                       0x06030203
+                                       0x000a0402
+                                       0x76230303
+                                       0x70000f03
+                                       0x001f0000
+                               >;
+                       };
+
+                       timing-40800000 {
+                               clock-frequency = <40800000>;
+
+                               nvidia,emem-configuration = <
+                                       0xa0000001
+                                       0x80000017
+                                       0x00000001
+                                       0x00000001
+                                       0x00000002
+                                       0x00000000
+                                       0x00000002
+                                       0x00000001
+                                       0x00000002
+                                       0x00000008
+                                       0x00000003
+                                       0x00000002
+                                       0x00000003
+                                       0x00000006
+                                       0x06030203
+                                       0x000a0402
+                                       0x74a30303
+                                       0x70000f03
+                                       0x001f0000
+                               >;
+                       };
+
+                       timing-68000000 {
+                               clock-frequency = <68000000>;
+
+                               nvidia,emem-configuration = <
+                                       0x00000001
+                                       0x8000001e
+                                       0x00000001
+                                       0x00000001
+                                       0x00000002
+                                       0x00000000
+                                       0x00000002
+                                       0x00000001
+                                       0x00000002
+                                       0x00000008
+                                       0x00000003
+                                       0x00000002
+                                       0x00000003
+                                       0x00000006
+                                       0x06030203
+                                       0x000a0402
+                                       0x74230403
+                                       0x70000f03
+                                       0x001f0000
+                               >;
+                       };
+
+                       timing-102000000 {
+                               clock-frequency = <102000000>;
+
+                               nvidia,emem-configuration = <
+                                       0x08000001
+                                       0x80000026
+                                       0x00000001
+                                       0x00000001
+                                       0x00000003
+                                       0x00000000
+                                       0x00000002
+                                       0x00000001
+                                       0x00000002
+                                       0x00000008
+                                       0x00000003
+                                       0x00000002
+                                       0x00000003
+                                       0x00000006
+                                       0x06030203
+                                       0x000a0403
+                                       0x73c30504
+                                       0x70000f03
+                                       0x001f0000
+                               >;
+                       };
+
+                       timing-204000000 {
+                               clock-frequency = <204000000>;
+
+                               nvidia,emem-configuration = <
+                                       0x01000003
+                                       0x80000040
+                                       0x00000001
+                                       0x00000001
+                                       0x00000005
+                                       0x00000002
+                                       0x00000004
+                                       0x00000001
+                                       0x00000002
+                                       0x00000008
+                                       0x00000003
+                                       0x00000002
+                                       0x00000004
+                                       0x00000006
+                                       0x06040203
+                                       0x000a0405
+                                       0x73840a06
+                                       0x70000f03
+                                       0x001f0000
+                               >;
+                       };
+
+                       timing-300000000 {
+                               clock-frequency = <300000000>;
+
+                               nvidia,emem-configuration = <
+                                       0x08000004
+                                       0x80000040
+                                       0x00000001
+                                       0x00000002
+                                       0x00000007
+                                       0x00000004
+                                       0x00000005
+                                       0x00000001
+                                       0x00000002
+                                       0x00000007
+                                       0x00000002
+                                       0x00000002
+                                       0x00000004
+                                       0x00000006
+                                       0x06040202
+                                       0x000b0607
+                                       0x77450e08
+                                       0x70000f03
+                                       0x001f0000
+                               >;
+                       };
+
+                       timing-396000000 {
+                               clock-frequency = <396000000>;
+
+                               nvidia,emem-configuration = <
+                                       0x0f000005
+                                       0x80000040
+                                       0x00000001
+                                       0x00000002
+                                       0x00000009
+                                       0x00000005
+                                       0x00000007
+                                       0x00000001
+                                       0x00000002
+                                       0x00000008
+                                       0x00000002
+                                       0x00000002
+                                       0x00000004
+                                       0x00000006
+                                       0x06040202
+                                       0x000d0709
+                                       0x7586120a
+                                       0x70000f03
+                                       0x001f0000
+                               >;
+                       };
+
+                       timing-600000000 {
+                               clock-frequency = <600000000>;
+
+                               nvidia,emem-configuration = <
+                                       0x00000009
+                                       0x80000040
+                                       0x00000003
+                                       0x00000004
+                                       0x0000000e
+                                       0x00000009
+                                       0x0000000b
+                                       0x00000001
+                                       0x00000003
+                                       0x0000000b
+                                       0x00000002
+                                       0x00000002
+                                       0x00000005
+                                       0x00000007
+                                       0x07050202
+                                       0x00130b0e
+                                       0x73a91b0f
+                                       0x70000f03
+                                       0x001f0000
+                               >;
+                       };
+
+                       timing-792000000 {
+                               clock-frequency = <792000000>;
+
+                               nvidia,emem-configuration = <
+                                       0x0e00000b
+                                       0x80000040
+                                       0x00000004
+                                       0x00000005
+                                       0x00000013
+                                       0x0000000c
+                                       0x0000000f
+                                       0x00000002
+                                       0x00000003
+                                       0x0000000c
+                                       0x00000002
+                                       0x00000002
+                                       0x00000006
+                                       0x00000008
+                                       0x08060202
+                                       0x00160d13
+                                       0x734c2414
+                                       0x70000f02
+                                       0x001f0000
+                               >;
+                       };
+               };
+       };
+};
index 004e8e4e1c04f08a9b23a10c22c864c8e1011cf2..2d21253ea4e3c059665d693f8ae2ffa648cd32bf 100644 (file)
@@ -1,46 +1,29 @@
 /dts-v1/;
 
-#include <dt-bindings/input/input.h>
-#include "tegra124.dtsi"
+#include "tegra124-nyan.dtsi"
+
+#include "tegra124-nyan-big-emc.dtsi"
 
 / {
        model = "Acer Chromebook 13 CB5-311";
        compatible = "google,nyan-big", "nvidia,tegra124";
 
-       aliases {
-               rtc0 = "/i2c@0,7000d000/pmic@40";
-               rtc1 = "/rtc@0,7000e000";
-               serial0 = &uarta;
-       };
+       panel: panel {
+               compatible = "auo,b133xtn01";
 
-       memory {
-               reg = <0x0 0x80000000 0x0 0x80000000>;
+               backlight = <&backlight>;
+               ddc-i2c-bus = <&dpaux>;
        };
 
-       host1x@0,50000000 {
-               hdmi@0,54280000 {
-                       status = "okay";
-
-                       vdd-supply = <&vdd_3v3_hdmi>;
-                       pll-supply = <&vdd_hdmi_pll>;
-                       hdmi-supply = <&vdd_5v0_hdmi>;
-
-                       nvidia,ddc-i2c-bus = <&hdmi_ddc>;
-                       nvidia,hpd-gpio =
-                               <&gpio TEGRA_GPIO(N, 7) GPIO_ACTIVE_HIGH>;
-               };
-
-               sor@0,54540000 {
-                       status = "okay";
-
-                       nvidia,dpaux = <&dpaux>;
-                       nvidia,panel = <&panel>;
-               };
+       sdhci@0,700b0400 { /* SD Card on this bus */
+               wp-gpios = <&gpio TEGRA_GPIO(Q, 4) GPIO_ACTIVE_LOW>;
+       };
 
-               dpaux@0,545c0000 {
-                       vdd-supply = <&vdd_3v3_panel>;
-                       status = "okay";
-               };
+       sound {
+               compatible = "nvidia,tegra-audio-max98090-nyan-big",
+                            "nvidia,tegra-audio-max98090-nyan",
+                            "nvidia,tegra-audio-max98090";
+               nvidia,model = "GoogleNyanBig";
        };
 
        pinmux@0,70000868 {
                pinctrl-0 = <&pinmux_default>;
 
                pinmux_default: common {
-                       dap_mclk1_pw4 {
-                               nvidia,pins = "dap_mclk1_pw4";
-                               nvidia,function = "extperiph1";
-                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       clk_32k_out_pa0 {
+                               nvidia,pins = "clk_32k_out_pa0";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                       };
-                       dap2_din_pa4 {
-                               nvidia,pins = "dap2_din_pa4";
-                               nvidia,function = "i2s1";
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
                        };
-                       dap2_dout_pa5 {
-                               nvidia,pins = "dap2_dout_pa5",
-                                             "dap2_fs_pa2",
-                                             "dap2_sclk_pa3";
-                               nvidia,function = "i2s1";
+                       uart3_cts_n_pa1 {
+                               nvidia,pins = "uart3_cts_n_pa1";
+                               nvidia,function = "gmi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
                        };
-                       dvfs_pwm_px0 {
-                               nvidia,pins = "dvfs_pwm_px0",
-                                             "dvfs_clk_px2";
-                               nvidia,function = "cldvfs";
-                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       dap2_fs_pa2 {
+                               nvidia,pins = "dap2_fs_pa2";
+                               nvidia,function = "i2s1";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
-                       ulpi_clk_py0 {
-                               nvidia,pins = "ulpi_clk_py0",
-                                             "ulpi_nxt_py2",
-                                             "ulpi_stp_py3";
-                               nvidia,function = "spi1";
-                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       dap2_sclk_pa3 {
+                               nvidia,pins = "dap2_sclk_pa3";
+                               nvidia,function = "i2s1";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                       };
-                       ulpi_dir_py1 {
-                               nvidia,pins = "ulpi_dir_py1";
-                               nvidia,function = "spi1";
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
                        };
-                       cam_i2c_scl_pbb1 {
-                               nvidia,pins = "cam_i2c_scl_pbb1",
-                                             "cam_i2c_sda_pbb2";
-                               nvidia,function = "i2c3";
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       dap2_din_pa4 {
+                               nvidia,pins = "dap2_din_pa4";
+                               nvidia,function = "i2s1";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,lock = <TEGRA_PIN_DISABLE>;
-                               nvidia,open-drain = <TEGRA_PIN_ENABLE>;
-                       };
-                       gen2_i2c_scl_pt5 {
-                               nvidia,pins = "gen2_i2c_scl_pt5",
-                                             "gen2_i2c_sda_pt6";
-                               nvidia,function = "i2c2";
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,lock = <TEGRA_PIN_DISABLE>;
-                               nvidia,open-drain = <TEGRA_PIN_ENABLE>;
                        };
-                       pg4 {
-                               nvidia,pins = "pg4",
-                                             "pg5",
-                                             "pg6",
-                                             "pi3";
-                               nvidia,function = "spi4";
-                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       dap2_dout_pa5 {
+                               nvidia,pins = "dap2_dout_pa5";
+                               nvidia,function = "i2s1";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                       };
-                       pg7 {
-                               nvidia,pins = "pg7";
-                               nvidia,function = "spi4";
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
                        };
-                       ph1 {
-                               nvidia,pins = "ph1";
-                               nvidia,function = "pwm1";
-                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       sdmmc3_clk_pa6 {
+                               nvidia,pins = "sdmmc3_clk_pa6";
+                               nvidia,function = "sdmmc3";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
-                       pk0 {
-                               nvidia,pins = "pk0",
-                                             "kb_row15_ps7",
-                                             "clk_32k_out_pa0";
-                               nvidia,function = "soc";
+                       sdmmc3_cmd_pa7 {
+                               nvidia,pins = "sdmmc3_cmd_pa7";
+                               nvidia,function = "sdmmc3";
                                nvidia,pull = <TEGRA_PIN_PULL_UP>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
-                       sdmmc1_clk_pz0 {
-                               nvidia,pins = "sdmmc1_clk_pz0";
-                               nvidia,function = "sdmmc1";
+                       pb0 {
+                               nvidia,pins = "pb0";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
                        };
-                       sdmmc1_cmd_pz1 {
-                               nvidia,pins = "sdmmc1_cmd_pz1",
-                                             "sdmmc1_dat0_py7",
-                                             "sdmmc1_dat1_py6",
-                                             "sdmmc1_dat2_py5",
-                                             "sdmmc1_dat3_py4";
-                               nvidia,function = "sdmmc1";
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                       pb1 {
+                               nvidia,pins = "pb1";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
-                       sdmmc3_clk_pa6 {
-                               nvidia,pins = "sdmmc3_clk_pa6";
+                       sdmmc3_dat3_pb4 {
+                               nvidia,pins = "sdmmc3_dat3_pb4";
                                nvidia,function = "sdmmc3";
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
-                       sdmmc3_cmd_pa7 {
-                               nvidia,pins = "sdmmc3_cmd_pa7",
-                                             "sdmmc3_dat0_pb7",
-                                             "sdmmc3_dat1_pb6",
-                                             "sdmmc3_dat2_pb5",
-                                             "sdmmc3_dat3_pb4",
-                                             "kb_col4_pq4",
-                                             "sdmmc3_clk_lb_out_pee4",
-                                             "sdmmc3_clk_lb_in_pee5",
-                                             "sdmmc3_cd_n_pv2";
+                       sdmmc3_dat2_pb5 {
+                               nvidia,pins = "sdmmc3_dat2_pb5";
                                nvidia,function = "sdmmc3";
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                                nvidia,pull = <TEGRA_PIN_PULL_UP>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                       };
-                       sdmmc4_clk_pcc4 {
-                               nvidia,pins = "sdmmc4_clk_pcc4";
-                               nvidia,function = "sdmmc4";
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
                        };
-                       sdmmc4_cmd_pt7 {
-                               nvidia,pins = "sdmmc4_cmd_pt7",
-                                             "sdmmc4_dat0_paa0",
-                                             "sdmmc4_dat1_paa1",
-                                             "sdmmc4_dat2_paa2",
-                                             "sdmmc4_dat3_paa3",
-                                             "sdmmc4_dat4_paa4",
-                                             "sdmmc4_dat5_paa5",
-                                             "sdmmc4_dat6_paa6",
-                                             "sdmmc4_dat7_paa7";
-                               nvidia,function = "sdmmc4";
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       sdmmc3_dat1_pb6 {
+                               nvidia,pins = "sdmmc3_dat1_pb6";
+                               nvidia,function = "sdmmc3";
                                nvidia,pull = <TEGRA_PIN_PULL_UP>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                       };
-                       pwr_i2c_scl_pz6 {
-                               nvidia,pins = "pwr_i2c_scl_pz6",
-                                             "pwr_i2c_sda_pz7";
-                               nvidia,function = "i2cpwr";
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,lock = <TEGRA_PIN_DISABLE>;
-                               nvidia,open-drain = <TEGRA_PIN_ENABLE>;
                        };
-                       jtag_rtck {
-                               nvidia,pins = "jtag_rtck";
-                               nvidia,function = "rtck";
-                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       sdmmc3_dat0_pb7 {
+                               nvidia,pins = "sdmmc3_dat0_pb7";
+                               nvidia,function = "sdmmc3";
                                nvidia,pull = <TEGRA_PIN_PULL_UP>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                       };
-                       clk_32k_in {
-                               nvidia,pins = "clk_32k_in";
-                               nvidia,function = "clk";
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
                        };
-                       core_pwr_req {
-                               nvidia,pins = "core_pwr_req";
-                               nvidia,function = "pwron";
+                       uart3_rts_n_pc0 {
+                               nvidia,pins = "uart3_rts_n_pc0";
+                               nvidia,function = "gmi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
                        };
-                       cpu_pwr_req {
-                               nvidia,pins = "cpu_pwr_req";
-                               nvidia,function = "cpu";
+                       uart2_txd_pc2 {
+                               nvidia,pins = "uart2_txd_pc2";
+                               nvidia,function = "irda";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                       };
-                       pwr_int_n {
-                               nvidia,pins = "pwr_int_n";
-                               nvidia,function = "pmi";
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
                        };
-                       reset_out_n {
-                               nvidia,pins = "reset_out_n";
-                               nvidia,function = "reset_out_n";
+                       uart2_rxd_pc3 {
+                               nvidia,pins = "uart2_rxd_pc3";
+                               nvidia,function = "irda";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
                        };
-                       clk3_out_pee0 {
-                               nvidia,pins = "clk3_out_pee0";
-                               nvidia,function = "extperiph3";
-                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       gen1_i2c_scl_pc4 {
+                               nvidia,pins = "gen1_i2c_scl_pc4";
+                               nvidia,function = "i2c1";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_ENABLE>;
                        };
                        gen1_i2c_sda_pc5 {
-                               nvidia,pins = "gen1_i2c_sda_pc5",
-                                             "gen1_i2c_scl_pc4";
+                               nvidia,pins = "gen1_i2c_sda_pc5";
                                nvidia,function = "i2c1";
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,lock = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                                nvidia,open-drain = <TEGRA_PIN_ENABLE>;
                        };
-                       hdmi_cec_pee3 {
-                               nvidia,pins = "hdmi_cec_pee3";
-                               nvidia,function = "cec";
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       pc7 {
+                               nvidia,pins = "pc7";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,lock = <TEGRA_PIN_DISABLE>;
-                               nvidia,open-drain = <TEGRA_PIN_DISABLE>;
-                       };
-                       hdmi_int_pn7 {
-                               nvidia,pins = "hdmi_int_pn7";
-                               nvidia,function = "rsvd1";
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
-                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                       };
+                       pg0 {
+                               nvidia,pins = "pg0";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
-                       ddc_scl_pv4 {
-                               nvidia,pins = "ddc_scl_pv4",
-                                             "ddc_sda_pv5";
-                               nvidia,function = "i2c4";
+                       pg1 {
+                               nvidia,pins = "pg1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pg2 {
+                               nvidia,pins = "pg2";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,lock = <TEGRA_PIN_DISABLE>;
-                               nvidia,rcv-sel = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
-                       kb_row10_ps2 {
-                               nvidia,pins = "kb_row10_ps2";
-                               nvidia,function = "uarta";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                       pg3 {
+                               nvidia,pins = "pg3";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
-                       kb_row9_ps1 {
-                               nvidia,pins = "kb_row9_ps1";
-                               nvidia,function = "uarta";
+                       pg4 {
+                               nvidia,pins = "pg4";
+                               nvidia,function = "spi4";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
-                       usb_vbus_en0_pn4 {
-                               nvidia,pins = "usb_vbus_en0_pn4",
-                                             "usb_vbus_en1_pn5";
-                               nvidia,function = "usb";
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       pg5 {
+                               nvidia,pins = "pg5";
+                               nvidia,function = "spi4";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,lock = <TEGRA_PIN_DISABLE>;
-                               nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
-                       drive_sdio1 {
-                               nvidia,pins = "drive_sdio1";
-                               nvidia,high-speed-mode = <TEGRA_PIN_ENABLE>;
-                               nvidia,schmitt = <TEGRA_PIN_DISABLE>;
-                               nvidia,pull-down-strength = <36>;
-                               nvidia,pull-up-strength = <20>;
-                               nvidia,slew-rate-rising = <TEGRA_PIN_SLEW_RATE_SLOW>;
-                               nvidia,slew-rate-falling = <TEGRA_PIN_SLEW_RATE_SLOW>;
-                       };
-                       drive_sdio3 {
-                               nvidia,pins = "drive_sdio3";
-                               nvidia,high-speed-mode = <TEGRA_PIN_ENABLE>;
-                               nvidia,schmitt = <TEGRA_PIN_DISABLE>;
-                               nvidia,pull-down-strength = <22>;
-                               nvidia,pull-up-strength = <36>;
-                               nvidia,slew-rate-rising = <TEGRA_PIN_SLEW_RATE_FASTEST>;
-                               nvidia,slew-rate-falling = <TEGRA_PIN_SLEW_RATE_FASTEST>;
-                       };
-                       drive_gma {
-                               nvidia,pins = "drive_gma";
-                               nvidia,high-speed-mode = <TEGRA_PIN_ENABLE>;
-                               nvidia,schmitt = <TEGRA_PIN_DISABLE>;
-                               nvidia,pull-down-strength = <2>;
-                               nvidia,pull-up-strength = <1>;
-                               nvidia,slew-rate-rising = <TEGRA_PIN_SLEW_RATE_FASTEST>;
-                               nvidia,slew-rate-falling = <TEGRA_PIN_SLEW_RATE_FASTEST>;
-                               nvidia,drive-type = <1>;
-                       };
-                       codec_irq_l {
-                               nvidia,pins = "ph4";
-                               nvidia,function = "gmi";
+                       pg6 {
+                               nvidia,pins = "pg6";
+                               nvidia,function = "spi4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pg7 {
+                               nvidia,pins = "pg7";
+                               nvidia,function = "spi4";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
-                       lcd_bl_en {
-                               nvidia,pins = "ph2";
+                       ph0 {
+                               nvidia,pins = "ph0";
                                nvidia,function = "gmi";
                                nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
-                       touch_irq_l {
-                               nvidia,pins = "gpio_w3_aud_pw3";
-                               nvidia,function = "spi6";
+                       ph1 {
+                               nvidia,pins = "ph1";
+                               nvidia,function = "pwm1";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
-                       tpm_davint_l {
-                               nvidia,pins = "ph6";
-                               nvidia,function = "gmi";
+                       ph2 {
+                               nvidia,pins = "ph2";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
-                       ts_irq_l {
-                               nvidia,pins = "pk2";
+                       ph3 {
+                               nvidia,pins = "ph3";
                                nvidia,function = "gmi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       ph4 {
+                               nvidia,pins = "ph4";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
-                       ts_reset_l {
-                               nvidia,pins = "pk4";
-                               nvidia,function = "gmi";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                       ph5 {
+                               nvidia,pins = "ph5";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
-                       ts_shdn_l {
-                               nvidia,pins = "pk1";
-                               nvidia,function = "gmi";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                       ph6 {
+                               nvidia,pins = "ph6";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        ph7 {
                                nvidia,pins = "ph7";
-                               nvidia,function = "gmi";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
-                       kb_col0_ap {
-                               nvidia,pins = "kb_col0_pq0";
-                               nvidia,function = "rsvd4";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                       pi0 {
+                               nvidia,pins = "pi0";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
-                       lid_open {
-                               nvidia,pins = "kb_row4_pr4";
-                               nvidia,function = "rsvd3";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                       pi1 {
+                               nvidia,pins = "pi1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
-                       en_vdd_sd {
-                               nvidia,pins = "kb_row0_pr0";
+                       pi2 {
+                               nvidia,pins = "pi2";
                                nvidia,function = "rsvd4";
-                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
-                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
-                       ac_ok {
-                               nvidia,pins = "pj0";
+                       pi3 {
+                               nvidia,pins = "pi3";
+                               nvidia,function = "spi4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pi4 {
+                               nvidia,pins = "pi4";
                                nvidia,function = "gmi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pi5 {
+                               nvidia,pins = "pi5";
                                nvidia,pull = <TEGRA_PIN_PULL_UP>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
-                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
-                       sensor_irq_l {
+                       pi6 {
                                nvidia,pins = "pi6";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pi7 {
+                               nvidia,pins = "pi7";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pj0 {
+                               nvidia,pins = "pj0";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pj2 {
+                               nvidia,pins = "pj2";
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       uart2_cts_n_pj5 {
+                               nvidia,pins = "uart2_cts_n_pj5";
+                               nvidia,function = "gmi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       uart2_rts_n_pj6 {
+                               nvidia,pins = "uart2_rts_n_pj6";
                                nvidia,function = "gmi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pj7 {
+                               nvidia,pins = "pj7";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
-                       wifi_en {
-                               nvidia,pins = "gpio_x7_aud_px7";
-                               nvidia,function = "rsvd4";
+                       pk0 {
+                               nvidia,pins = "pk0";
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pk1 {
+                               nvidia,pins = "pk1";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
-                       en_vdd_bl {
-                               nvidia,pins = "dap3_dout_pp2";
-                               nvidia,function = "i2s2";
+                       pk2 {
+                               nvidia,pins = "pk2";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pk3 {
+                               nvidia,pins = "pk3";
+                               nvidia,function = "gmi";
                                nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pk4 {
+                               nvidia,pins = "pk4";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
-                       en_vdd_hdmi {
+                       spdif_out_pk5 {
+                               nvidia,pins = "spdif_out_pk5";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       spdif_in_pk6 {
                                nvidia,pins = "spdif_in_pk6";
-                               nvidia,function = "spdif";
                                nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
-                       soc_warm_reset_l {
-                               nvidia,pins = "pi5";
-                               nvidia,function = "gmi";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                       pk7 {
+                               nvidia,pins = "pk7";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       dap1_fs_pn0 {
+                               nvidia,pins = "dap1_fs_pn0";
+                               nvidia,function = "rsvd4";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
                                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
-                       hp_det_l {
-                               nvidia,pins = "pi7";
-                               nvidia,function = "rsvd1";
+                       dap1_din_pn1 {
+                               nvidia,pins = "dap1_din_pn1";
+                               nvidia,function = "rsvd4";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       dap1_dout_pn2 {
+                               nvidia,pins = "dap1_dout_pn2";
+                               nvidia,function = "i2s0";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       dap1_sclk_pn3 {
+                               nvidia,pins = "dap1_sclk_pn3";
+                               nvidia,function = "rsvd4";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       usb_vbus_en0_pn4 {
+                               nvidia,pins = "usb_vbus_en0_pn4";
+                               nvidia,function = "usb";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_ENABLE>;
                        };
-                       mic_det_l {
-                               nvidia,pins = "kb_row7_pr7";
+                       usb_vbus_en1_pn5 {
+                               nvidia,pins = "usb_vbus_en1_pn5";
+                               nvidia,function = "usb";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+                       };
+                       hdmi_int_pn7 {
+                               nvidia,pins = "hdmi_int_pn7";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,rcv-sel = <TEGRA_PIN_DISABLE>;
+                       };
+                       ulpi_data7_po0 {
+                               nvidia,pins = "ulpi_data7_po0";
+                               nvidia,function = "ulpi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       ulpi_data0_po1 {
+                               nvidia,pins = "ulpi_data0_po1";
+                               nvidia,function = "ulpi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       ulpi_data1_po2 {
+                               nvidia,pins = "ulpi_data1_po2";
+                               nvidia,function = "ulpi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       ulpi_data2_po3 {
+                               nvidia,pins = "ulpi_data2_po3";
+                               nvidia,function = "ulpi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       ulpi_data3_po4 {
+                               nvidia,pins = "ulpi_data3_po4";
+                               nvidia,function = "ulpi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       ulpi_data4_po5 {
+                               nvidia,pins = "ulpi_data4_po5";
+                               nvidia,function = "ulpi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       ulpi_data5_po6 {
+                               nvidia,pins = "ulpi_data5_po6";
+                               nvidia,function = "ulpi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       ulpi_data6_po7 {
+                               nvidia,pins = "ulpi_data6_po7";
+                               nvidia,function = "ulpi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       dap3_fs_pp0 {
+                               nvidia,pins = "dap3_fs_pp0";
+                               nvidia,function = "i2s2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       dap3_din_pp1 {
+                               nvidia,pins = "dap3_din_pp1";
+                               nvidia,function = "i2s2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       dap3_dout_pp2 {
+                               nvidia,pins = "dap3_dout_pp2";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       dap3_sclk_pp3 {
+                               nvidia,pins = "dap3_sclk_pp3";
+                               nvidia,function = "rsvd3";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       dap4_fs_pp4 {
+                               nvidia,pins = "dap4_fs_pp4";
+                               nvidia,function = "rsvd4";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       dap4_din_pp5 {
+                               nvidia,pins = "dap4_din_pp5";
+                               nvidia,function = "rsvd3";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       dap4_dout_pp6 {
+                               nvidia,pins = "dap4_dout_pp6";
+                               nvidia,function = "rsvd4";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       dap4_sclk_pp7 {
+                               nvidia,pins = "dap4_sclk_pp7";
+                               nvidia,function = "rsvd3";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       kb_col0_pq0 {
+                               nvidia,pins = "kb_col0_pq0";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_col1_pq1 {
+                               nvidia,pins = "kb_col1_pq1";
                                nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       kb_col2_pq2 {
+                               nvidia,pins = "kb_col2_pq2";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_col3_pq3 {
+                               nvidia,pins = "kb_col3_pq3";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_col4_pq4 {
+                               nvidia,pins = "kb_col4_pq4";
+                               nvidia,function = "sdmmc3";
                                nvidia,pull = <TEGRA_PIN_PULL_UP>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                                nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
-               };
-       };
-
-       serial@0,70006000 {
-               /* Debug connector on the bottom of the board near SD card. */
-               status = "okay";
-       };
-
-       pwm@0,7000a000 {
-               status = "okay";
-       };
-
-       i2c@0,7000c000 {
-               status = "okay";
-               clock-frequency = <100000>;
-
-               acodec: audio-codec@10 {
-                       compatible = "maxim,max98090";
-                       reg = <0x10>;
-                       interrupt-parent = <&gpio>;
-                       interrupts = <TEGRA_GPIO(H, 4) GPIO_ACTIVE_HIGH>;
-               };
-
-               temperature-sensor@4c {
-                       compatible = "ti,tmp451";
-                       reg = <0x4c>;
-                       interrupt-parent = <&gpio>;
-                       interrupts = <TEGRA_GPIO(I, 6) IRQ_TYPE_LEVEL_LOW>;
-
-                       #thermal-sensor-cells = <1>;
-               };
-       };
-
-       i2c@0,7000c400 {
-               status = "okay";
-               clock-frequency = <100000>;
-       };
-
-       i2c@0,7000c500 {
-               status = "okay";
-               clock-frequency = <400000>;
-
-               tpm@20 {
-                       compatible = "infineon,slb9645tt";
-                       reg = <0x20>;
-               };
-       };
-
-       hdmi_ddc: i2c@0,7000c700 {
-               status = "okay";
-               clock-frequency = <100000>;
-       };
-
-       i2c@0,7000d000 {
-               status = "okay";
-               clock-frequency = <400000>;
-
-               pmic: pmic@40 {
-                       compatible = "ams,as3722";
-                       reg = <0x40>;
-                       interrupts = <0 86 IRQ_TYPE_LEVEL_HIGH>;
-
-                       ams,system-power-controller;
-
-                       #interrupt-cells = <2>;
-                       interrupt-controller;
-
-                       gpio-controller;
-                       #gpio-cells = <2>;
-
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&as3722_default>;
-
-                       as3722_default: pinmux {
-                               gpio0 {
-                                       pins = "gpio0";
-                                       function = "gpio";
-                                       bias-pull-down;
-                               };
-
-                               gpio1 {
-                                       pins = "gpio1";
-                                       function = "gpio";
-                                       bias-pull-up;
-                               };
-
-                               gpio2_4_7 {
-                                       pins = "gpio2", "gpio4", "gpio7";
-                                       function = "gpio";
-                                       bias-pull-up;
-                               };
-
-                               gpio3_6 {
-                                       pins = "gpio3", "gpio6";
-                                       bias-high-impedance;
-                               };
-
-                               gpio5 {
-                                       pins = "gpio5";
-                                       function = "clk32k-out";
-                                       bias-pull-down;
-                               };
+                       kb_col5_pq5 {
+                               nvidia,pins = "kb_col5_pq5";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
-
-                       regulators {
-                               vsup-sd2-supply = <&vdd_5v0_sys>;
-                               vsup-sd3-supply = <&vdd_5v0_sys>;
-                               vsup-sd4-supply = <&vdd_5v0_sys>;
-                               vsup-sd5-supply = <&vdd_5v0_sys>;
-                               vin-ldo0-supply = <&vdd_1v35_lp0>;
-                               vin-ldo1-6-supply = <&vdd_3v3_run>;
-                               vin-ldo2-5-7-supply = <&vddio_1v8>;
-                               vin-ldo3-4-supply = <&vdd_3v3_sys>;
-                               vin-ldo9-10-supply = <&vdd_5v0_sys>;
-                               vin-ldo11-supply = <&vdd_3v3_run>;
-
-                               sd0 {
-                                       regulator-name = "+VDD_CPU_AP";
-                                       regulator-min-microvolt = <700000>;
-                                       regulator-max-microvolt = <1350000>;
-                                       regulator-min-microamp = <3500000>;
-                                       regulator-max-microamp = <3500000>;
-                                       regulator-always-on;
-                                       regulator-boot-on;
-                                       ams,ext-control = <2>;
-                               };
-
-                               sd1 {
-                                       regulator-name = "+VDD_CORE";
-                                       regulator-min-microvolt = <700000>;
-                                       regulator-max-microvolt = <1350000>;
-                                       regulator-min-microamp = <2500000>;
-                                       regulator-max-microamp = <4000000>;
-                                       regulator-always-on;
-                                       regulator-boot-on;
-                                       ams,ext-control = <1>;
-                               };
-
-                               vdd_1v35_lp0: sd2 {
-                                       regulator-name = "+1.35V_LP0(sd2)";
-                                       regulator-min-microvolt = <1350000>;
-                                       regulator-max-microvolt = <1350000>;
-                                       regulator-always-on;
-                                       regulator-boot-on;
-                               };
-
-                               sd3 {
-                                       regulator-name = "+1.35V_LP0(sd3)";
-                                       regulator-min-microvolt = <1350000>;
-                                       regulator-max-microvolt = <1350000>;
-                                       regulator-always-on;
-                                       regulator-boot-on;
-                               };
-
-                               vdd_1v05_run: sd4 {
-                                       regulator-name = "+1.05V_RUN";
-                                       regulator-min-microvolt = <1050000>;
-                                       regulator-max-microvolt = <1050000>;
-                               };
-
-                               vddio_1v8: sd5 {
-                                       regulator-name = "+1.8V_VDDIO";
-                                       regulator-min-microvolt = <1800000>;
-                                       regulator-max-microvolt = <1800000>;
-                                       regulator-boot-on;
-                                       regulator-always-on;
-                               };
-
-                               sd6 {
-                                       regulator-name = "+VDD_GPU_AP";
-                                       regulator-min-microvolt = <650000>;
-                                       regulator-max-microvolt = <1200000>;
-                                       regulator-min-microamp = <3500000>;
-                                       regulator-max-microamp = <3500000>;
-                                       regulator-boot-on;
-                                       regulator-always-on;
-                               };
-
-                               ldo0 {
-                                       regulator-name = "+1.05V_RUN_AVDD";
-                                       regulator-min-microvolt = <1050000>;
-                                       regulator-max-microvolt = <1050000>;
-                                       regulator-boot-on;
-                                       regulator-always-on;
-                                       ams,ext-control = <1>;
-                               };
-
-                               ldo1 {
-                                       regulator-name = "+1.8V_RUN_CAM";
-                                       regulator-min-microvolt = <1800000>;
-                                       regulator-max-microvolt = <1800000>;
-                               };
-
-                               ldo2 {
-                                       regulator-name = "+1.2V_GEN_AVDD";
-                                       regulator-min-microvolt = <1200000>;
-                                       regulator-max-microvolt = <1200000>;
-                                       regulator-boot-on;
-                                       regulator-always-on;
-                               };
-
-                               ldo3 {
-                                       regulator-name = "+1.00V_LP0_VDD_RTC";
-                                       regulator-min-microvolt = <1000000>;
-                                       regulator-max-microvolt = <1000000>;
-                                       regulator-boot-on;
-                                       regulator-always-on;
-                                       ams,enable-tracking;
-                               };
-
-                               vdd_run_cam: ldo4 {
-                                       regulator-name = "+3.3V_RUN_CAM";
-                                       regulator-min-microvolt = <2800000>;
-                                       regulator-max-microvolt = <2800000>;
-                               };
-
-                               ldo5 {
-                                       regulator-name = "+1.2V_RUN_CAM_FRONT";
-                                       regulator-min-microvolt = <1200000>;
-                                       regulator-max-microvolt = <1200000>;
-                               };
-
-                               vddio_sdmmc3: ldo6 {
-                                       regulator-name = "+VDDIO_SDMMC3";
-                                       regulator-min-microvolt = <1800000>;
-                                       regulator-max-microvolt = <3300000>;
-                               };
-
-                               ldo7 {
-                                       regulator-name = "+1.05V_RUN_CAM_REAR";
-                                       regulator-min-microvolt = <1050000>;
-                                       regulator-max-microvolt = <1050000>;
-                               };
-
-                               ldo9 {
-                                       regulator-name = "+2.8V_RUN_TOUCH";
-                                       regulator-min-microvolt = <2800000>;
-                                       regulator-max-microvolt = <2800000>;
-                               };
-
-                               ldo10 {
-                                       regulator-name = "+2.8V_RUN_CAM_AF";
-                                       regulator-min-microvolt = <2800000>;
-                                       regulator-max-microvolt = <2800000>;
-                               };
-
-                               ldo11 {
-                                       regulator-name = "+1.8V_RUN_VPP_FUSE";
-                                       regulator-min-microvolt = <1800000>;
-                                       regulator-max-microvolt = <1800000>;
-                               };
+                       kb_col6_pq6 {
+                               nvidia,pins = "kb_col6_pq6";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
-               };
-       };
-
-       spi@0,7000d400 {
-               status = "okay";
-
-               cros_ec: cros-ec@0 {
-                       compatible = "google,cros-ec-spi";
-                       spi-max-frequency = <3000000>;
-                       interrupt-parent = <&gpio>;
-                       interrupts = <TEGRA_GPIO(C, 7) IRQ_TYPE_LEVEL_LOW>;
-                       reg = <0>;
-
-                       google,cros-ec-spi-msg-delay = <2000>;
-
-                       i2c-tunnel {
-                               compatible = "google,cros-ec-i2c-tunnel";
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-
-                               google,remote-bus = <0>;
-
-                               charger: bq24735@9 {
-                                       compatible = "ti,bq24735";
-                                       reg = <0x9>;
-                                       interrupt-parent = <&gpio>;
-                                       interrupts = <TEGRA_GPIO(J, 0)
-                                                       GPIO_ACTIVE_HIGH>;
-                                       ti,ac-detect-gpios = <&gpio
-                                                       TEGRA_GPIO(J, 0)
-                                                       GPIO_ACTIVE_HIGH>;
-                               };
-
-                               battery: sbs-battery@b {
-                                       compatible = "sbs,sbs-battery";
-                                       reg = <0xb>;
-                                       sbs,i2c-retry-count = <2>;
-                                       sbs,poll-retry-count = <10>;
-                                       power-supplies = <&charger>;
-                               };
+                       kb_col7_pq7 {
+                               nvidia,pins = "kb_col7_pq7";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_row0_pr0 {
+                               nvidia,pins = "kb_row0_pr0";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       kb_row1_pr1 {
+                               nvidia,pins = "kb_row1_pr1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_row2_pr2 {
+                               nvidia,pins = "kb_row2_pr2";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       kb_row3_pr3 {
+                               nvidia,pins = "kb_row3_pr3";
+                               nvidia,function = "kbc";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       kb_row4_pr4 {
+                               nvidia,pins = "kb_row4_pr4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_row5_pr5 {
+                               nvidia,pins = "kb_row5_pr5";
+                               nvidia,function = "rsvd3";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       kb_row6_pr6 {
+                               nvidia,pins = "kb_row6_pr6";
+                               nvidia,function = "kbc";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       kb_row7_pr7 {
+                               nvidia,pins = "kb_row7_pr7";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_row8_ps0 {
+                               nvidia,pins = "kb_row8_ps0";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       kb_row9_ps1 {
+                               nvidia,pins = "kb_row9_ps1";
+                               nvidia,function = "uarta";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       kb_row10_ps2 {
+                               nvidia,pins = "kb_row10_ps2";
+                               nvidia,function = "uarta";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_row11_ps3 {
+                               nvidia,pins = "kb_row11_ps3";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       kb_row12_ps4 {
+                               nvidia,pins = "kb_row12_ps4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       kb_row13_ps5 {
+                               nvidia,pins = "kb_row13_ps5";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       kb_row14_ps6 {
+                               nvidia,pins = "kb_row14_ps6";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       kb_row15_ps7 {
+                               nvidia,pins = "kb_row15_ps7";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_row16_pt0 {
+                               nvidia,pins = "kb_row16_pt0";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       kb_row17_pt1 {
+                               nvidia,pins = "kb_row17_pt1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       gen2_i2c_scl_pt5 {
+                               nvidia,pins = "gen2_i2c_scl_pt5";
+                               nvidia,function = "i2c2";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+                       };
+                       gen2_i2c_sda_pt6 {
+                               nvidia,pins = "gen2_i2c_sda_pt6";
+                               nvidia,function = "i2c2";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc4_cmd_pt7 {
+                               nvidia,pins = "sdmmc4_cmd_pt7";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pu0 {
+                               nvidia,pins = "pu0";
+                               nvidia,function = "rsvd4";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pu1 {
+                               nvidia,pins = "pu1";
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pu2 {
+                               nvidia,pins = "pu2";
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pu3 {
+                               nvidia,pins = "pu3";
+                               nvidia,function = "gmi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pu4 {
+                               nvidia,pins = "pu4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pu5 {
+                               nvidia,pins = "pu5";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pu6 {
+                               nvidia,pins = "pu6";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pv0 {
+                               nvidia,pins = "pv0";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pv1 {
+                               nvidia,pins = "pv1";
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       sdmmc3_cd_n_pv2 {
+                               nvidia,pins = "sdmmc3_cd_n_pv2";
+                               nvidia,function = "sdmmc3";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc1_wp_n_pv3 {
+                               nvidia,pins = "sdmmc1_wp_n_pv3";
+                               nvidia,function = "sdmmc1";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       ddc_scl_pv4 {
+                               nvidia,pins = "ddc_scl_pv4";
+                               nvidia,function = "i2c4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,rcv-sel = <TEGRA_PIN_DISABLE>;
+                       };
+                       ddc_sda_pv5 {
+                               nvidia,pins = "ddc_sda_pv5";
+                               nvidia,function = "i2c4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,rcv-sel = <TEGRA_PIN_DISABLE>;
+                       };
+                       gpio_w2_aud_pw2 {
+                               nvidia,pins = "gpio_w2_aud_pw2";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gpio_w3_aud_pw3 {
+                               nvidia,pins = "gpio_w3_aud_pw3";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       dap_mclk1_pw4 {
+                               nvidia,pins = "dap_mclk1_pw4";
+                               nvidia,function = "extperiph1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       clk2_out_pw5 {
+                               nvidia,pins = "clk2_out_pw5";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       uart3_txd_pw6 {
+                               nvidia,pins = "uart3_txd_pw6";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       uart3_rxd_pw7 {
+                               nvidia,pins = "uart3_rxd_pw7";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       dvfs_pwm_px0 {
+                               nvidia,pins = "dvfs_pwm_px0";
+                               nvidia,function = "cldvfs";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gpio_x1_aud_px1 {
+                               nvidia,pins = "gpio_x1_aud_px1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       dvfs_clk_px2 {
+                               nvidia,pins = "dvfs_clk_px2";
+                               nvidia,function = "cldvfs";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gpio_x3_aud_px3 {
+                               nvidia,pins = "gpio_x3_aud_px3";
+                               nvidia,function = "rsvd4";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gpio_x4_aud_px4 {
+                               nvidia,pins = "gpio_x4_aud_px4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       gpio_x5_aud_px5 {
+                               nvidia,pins = "gpio_x5_aud_px5";
+                               nvidia,function = "rsvd4";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gpio_x6_aud_px6 {
+                               nvidia,pins = "gpio_x6_aud_px6";
+                               nvidia,function = "gmi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gpio_x7_aud_px7 {
+                               nvidia,pins = "gpio_x7_aud_px7";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       ulpi_clk_py0 {
+                               nvidia,pins = "ulpi_clk_py0";
+                               nvidia,function = "spi1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       ulpi_dir_py1 {
+                               nvidia,pins = "ulpi_dir_py1";
+                               nvidia,function = "spi1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       ulpi_nxt_py2 {
+                               nvidia,pins = "ulpi_nxt_py2";
+                               nvidia,function = "spi1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       ulpi_stp_py3 {
+                               nvidia,pins = "ulpi_stp_py3";
+                               nvidia,function = "spi1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       sdmmc1_dat3_py4 {
+                               nvidia,pins = "sdmmc1_dat3_py4";
+                               nvidia,function = "sdmmc1";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc1_dat2_py5 {
+                               nvidia,pins = "sdmmc1_dat2_py5";
+                               nvidia,function = "sdmmc1";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc1_dat1_py6 {
+                               nvidia,pins = "sdmmc1_dat1_py6";
+                               nvidia,function = "sdmmc1";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc1_dat0_py7 {
+                               nvidia,pins = "sdmmc1_dat0_py7";
+                               nvidia,function = "sdmmc1";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc1_clk_pz0 {
+                               nvidia,pins = "sdmmc1_clk_pz0";
+                               nvidia,function = "sdmmc1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc1_cmd_pz1 {
+                               nvidia,pins = "sdmmc1_cmd_pz1";
+                               nvidia,function = "sdmmc1";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pwr_i2c_scl_pz6 {
+                               nvidia,pins = "pwr_i2c_scl_pz6";
+                               nvidia,function = "i2cpwr";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+                       };
+                       pwr_i2c_sda_pz7 {
+                               nvidia,pins = "pwr_i2c_sda_pz7";
+                               nvidia,function = "i2cpwr";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc4_dat0_paa0 {
+                               nvidia,pins = "sdmmc4_dat0_paa0";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc4_dat1_paa1 {
+                               nvidia,pins = "sdmmc4_dat1_paa1";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc4_dat2_paa2 {
+                               nvidia,pins = "sdmmc4_dat2_paa2";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc4_dat3_paa3 {
+                               nvidia,pins = "sdmmc4_dat3_paa3";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc4_dat4_paa4 {
+                               nvidia,pins = "sdmmc4_dat4_paa4";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc4_dat5_paa5 {
+                               nvidia,pins = "sdmmc4_dat5_paa5";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc4_dat6_paa6 {
+                               nvidia,pins = "sdmmc4_dat6_paa6";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc4_dat7_paa7 {
+                               nvidia,pins = "sdmmc4_dat7_paa7";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pbb0 {
+                               nvidia,pins = "pbb0";
+                               nvidia,function = "vgp6";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       cam_i2c_scl_pbb1 {
+                               nvidia,pins = "cam_i2c_scl_pbb1";
+                               nvidia,function = "rsvd3";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+                       };
+                       cam_i2c_sda_pbb2 {
+                               nvidia,pins = "cam_i2c_sda_pbb2";
+                               nvidia,function = "rsvd3";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+                       };
+                       pbb3 {
+                               nvidia,pins = "pbb3";
+                               nvidia,function = "vgp3";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pbb4 {
+                               nvidia,pins = "pbb4";
+                               nvidia,function = "vgp4";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pbb5 {
+                               nvidia,pins = "pbb5";
+                               nvidia,function = "rsvd3";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pbb6 {
+                               nvidia,pins = "pbb6";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pbb7 {
+                               nvidia,pins = "pbb7";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       cam_mclk_pcc0 {
+                               nvidia,pins = "cam_mclk_pcc0";
+                               nvidia,function = "vi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pcc1 {
+                               nvidia,pins = "pcc1";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pcc2 {
+                               nvidia,pins = "pcc2";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       sdmmc4_clk_pcc4 {
+                               nvidia,pins = "sdmmc4_clk_pcc4";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       clk2_req_pcc5 {
+                               nvidia,pins = "clk2_req_pcc5";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pex_l0_rst_n_pdd1 {
+                               nvidia,pins = "pex_l0_rst_n_pdd1";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pex_l0_clkreq_n_pdd2 {
+                               nvidia,pins = "pex_l0_clkreq_n_pdd2";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pex_wake_n_pdd3 {
+                               nvidia,pins = "pex_wake_n_pdd3";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pex_l1_rst_n_pdd5 {
+                               nvidia,pins = "pex_l1_rst_n_pdd5";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pex_l1_clkreq_n_pdd6 {
+                               nvidia,pins = "pex_l1_clkreq_n_pdd6";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       clk3_out_pee0 {
+                               nvidia,pins = "clk3_out_pee0";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       clk3_req_pee1 {
+                               nvidia,pins = "clk3_req_pee1";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       dap_mclk1_req_pee2 {
+                               nvidia,pins = "dap_mclk1_req_pee2";
+                               nvidia,function = "rsvd4";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       hdmi_cec_pee3 {
+                               nvidia,pins = "hdmi_cec_pee3";
+                               nvidia,function = "cec";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc3_clk_lb_out_pee4 {
+                               nvidia,pins = "sdmmc3_clk_lb_out_pee4";
+                               nvidia,function = "sdmmc3";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       sdmmc3_clk_lb_in_pee5 {
+                               nvidia,pins = "sdmmc3_clk_lb_in_pee5";
+                               nvidia,function = "sdmmc3";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       dp_hpd_pff0 {
+                               nvidia,pins = "dp_hpd_pff0";
+                               nvidia,function = "dp";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       usb_vbus_en2_pff1 {
+                               nvidia,pins = "usb_vbus_en2_pff1";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+                       };
+                       pff2 {
+                               nvidia,pins = "pff2";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+                       };
+                       core_pwr_req {
+                               nvidia,pins = "core_pwr_req";
+                               nvidia,function = "pwron";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       cpu_pwr_req {
+                               nvidia,pins = "cpu_pwr_req";
+                               nvidia,function = "cpu";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pwr_int_n {
+                               nvidia,pins = "pwr_int_n";
+                               nvidia,function = "pmi";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       reset_out_n {
+                               nvidia,pins = "reset_out_n";
+                               nvidia,function = "reset_out_n";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       owr {
+                               nvidia,pins = "owr";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                               nvidia,rcv-sel = <TEGRA_PIN_DISABLE>;
+                       };
+                       clk_32k_in {
+                               nvidia,pins = "clk_32k_in";
+                               nvidia,function = "clk";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       jtag_rtck {
+                               nvidia,pins = "jtag_rtck";
+                               nvidia,function = "rtck";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
                        };
                };
        };
-
-       spi@0,7000da00 {
-               status = "okay";
-               spi-max-frequency = <25000000>;
-
-               flash@0 {
-                       compatible = "winbond,w25q32dw";
-                       reg = <0>;
-               };
-       };
-
-       pmc@0,7000e400 {
-               nvidia,invert-interrupt;
-               nvidia,suspend-mode = <0>;
-               nvidia,cpu-pwr-good-time = <500>;
-               nvidia,cpu-pwr-off-time = <300>;
-               nvidia,core-pwr-good-time = <641 3845>;
-               nvidia,core-pwr-off-time = <61036>;
-               nvidia,core-power-req-active-high;
-               nvidia,sys-clock-req-active-high;
-       };
-
-       hda@0,70030000 {
-               status = "okay";
-       };
-
-       sdhci@0,700b0000 { /* WiFi/BT on this bus */
-               status = "okay";
-               power-gpios = <&gpio TEGRA_GPIO(X, 7) GPIO_ACTIVE_HIGH>;
-               bus-width = <4>;
-               no-1-8-v;
-               non-removable;
-       };
-
-       sdhci@0,700b0400 { /* SD Card on this bus */
-               status = "okay";
-               cd-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_LOW>;
-               power-gpios = <&gpio TEGRA_GPIO(R, 0) GPIO_ACTIVE_HIGH>;
-               wp-gpios = <&gpio TEGRA_GPIO(Q, 4) GPIO_ACTIVE_LOW>;
-               bus-width = <4>;
-               no-1-8-v;
-               vqmmc-supply = <&vddio_sdmmc3>;
-       };
-
-       sdhci@0,700b0600 { /* eMMC on this bus */
-               status = "okay";
-               bus-width = <8>;
-               no-1-8-v;
-               non-removable;
-       };
-
-       ahub@0,70300000 {
-               i2s@0,70301100 {
-                       status = "okay";
-               };
-       };
-
-       usb@0,7d000000 { /* Rear external USB port. */
-               status = "okay";
-       };
-
-       usb-phy@0,7d000000 {
-               status = "okay";
-               vbus-supply = <&vdd_usb1_vbus>;
-       };
-
-       usb@0,7d004000 { /* Internal webcam. */
-               status = "okay";
-       };
-
-       usb-phy@0,7d004000 {
-               status = "okay";
-               vbus-supply = <&vdd_run_cam>;
-       };
-
-       usb@0,7d008000 { /* Left external USB port. */
-               status = "okay";
-       };
-
-       usb-phy@0,7d008000 {
-               status = "okay";
-               vbus-supply = <&vdd_usb3_vbus>;
-       };
-
-       backlight: backlight {
-               compatible = "pwm-backlight";
-
-               enable-gpios = <&gpio TEGRA_GPIO(H, 2) GPIO_ACTIVE_HIGH>;
-               power-supply = <&vdd_led>;
-               pwms = <&pwm 1 1000000>;
-
-               default-brightness-level = <224>;
-               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 101 102 103
-                        104 105 106 107 108 109 110 111
-                        112 113 114 115 116 117 118 119
-                        120 121 122 123 124 125 126 127
-                        128 129 130 131 132 133 134 135
-                        136 137 138 139 140 141 142 143
-                        144 145 146 147 148 149 150 151
-                        152 153 154 155 156 157 158 159
-                        160 161 162 163 164 165 166 167
-                        168 169 170 171 172 173 174 175
-                        176 177 178 179 180 181 182 183
-                        184 185 186 187 188 189 190 191
-                        192 193 194 195 196 197 198 199
-                        200 201 202 203 204 205 206 207
-                        208 209 210 211 212 213 214 215
-                        216 217 218 219 220 221 222 223
-                        224 225 226 227 228 229 230 231
-                        232 233 234 235 236 237 238 239
-                        240 241 242 243 244 245 246 247
-                        248 249 250 251 252 253 254 255
-                        256>;
-       };
-
-       clocks {
-               compatible = "simple-bus";
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               clk32k_in: clock@0 {
-                       compatible = "fixed-clock";
-                       reg = <0>;
-                       #clock-cells = <0>;
-                       clock-frequency = <32768>;
-               };
-       };
-
-       gpio-keys {
-               compatible = "gpio-keys";
-
-               lid {
-                       label = "Lid";
-                       gpios = <&gpio TEGRA_GPIO(R, 4) GPIO_ACTIVE_LOW>;
-                       linux,input-type = <5>;
-                       linux,code = <KEY_RESERVED>;
-                       debounce-interval = <1>;
-                       gpio-key,wakeup;
-               };
-
-               power {
-                       label = "Power";
-                       gpios = <&gpio TEGRA_GPIO(Q, 0) GPIO_ACTIVE_LOW>;
-                       linux,code = <KEY_POWER>;
-                       debounce-interval = <30>;
-                       gpio-key,wakeup;
-               };
-       };
-
-       panel: panel {
-               compatible = "auo,b133xtn01";
-
-               backlight = <&backlight>;
-               ddc-i2c-bus = <&dpaux>;
-       };
-
-       regulators {
-               compatible = "simple-bus";
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               vdd_mux: regulator@0 {
-                       compatible = "regulator-fixed";
-                       reg = <0>;
-                       regulator-name = "+VDD_MUX";
-                       regulator-min-microvolt = <12000000>;
-                       regulator-max-microvolt = <12000000>;
-                       regulator-always-on;
-                       regulator-boot-on;
-               };
-
-               vdd_5v0_sys: regulator@1 {
-                       compatible = "regulator-fixed";
-                       reg = <1>;
-                       regulator-name = "+5V_SYS";
-                       regulator-min-microvolt = <5000000>;
-                       regulator-max-microvolt = <5000000>;
-                       regulator-always-on;
-                       regulator-boot-on;
-                       vin-supply = <&vdd_mux>;
-               };
-
-               vdd_3v3_sys: regulator@2 {
-                       compatible = "regulator-fixed";
-                       reg = <2>;
-                       regulator-name = "+3.3V_SYS";
-                       regulator-min-microvolt = <3300000>;
-                       regulator-max-microvolt = <3300000>;
-                       regulator-always-on;
-                       regulator-boot-on;
-                       vin-supply = <&vdd_mux>;
-               };
-
-               vdd_3v3_run: regulator@3 {
-                       compatible = "regulator-fixed";
-                       reg = <3>;
-                       regulator-name = "+3.3V_RUN";
-                       regulator-min-microvolt = <3300000>;
-                       regulator-max-microvolt = <3300000>;
-                       regulator-always-on;
-                       regulator-boot-on;
-                       gpio = <&pmic 1 GPIO_ACTIVE_HIGH>;
-                       enable-active-high;
-                       vin-supply = <&vdd_3v3_sys>;
-               };
-
-               vdd_3v3_hdmi: regulator@4 {
-                       compatible = "regulator-fixed";
-                       reg = <4>;
-                       regulator-name = "+3.3V_AVDD_HDMI_AP_GATED";
-                       regulator-min-microvolt = <3300000>;
-                       regulator-max-microvolt = <3300000>;
-                       vin-supply = <&vdd_3v3_run>;
-               };
-
-               vdd_led: regulator@5 {
-                       compatible = "regulator-fixed";
-                       reg = <5>;
-                       regulator-name = "+VDD_LED";
-                       gpio = <&gpio TEGRA_GPIO(P, 2) GPIO_ACTIVE_HIGH>;
-                       enable-active-high;
-                       vin-supply = <&vdd_mux>;
-               };
-
-               vdd_5v0_ts: regulator@6 {
-                       compatible = "regulator-fixed";
-                       reg = <6>;
-                       regulator-name = "+5V_VDD_TS_SW";
-                       regulator-min-microvolt = <5000000>;
-                       regulator-max-microvolt = <5000000>;
-                       regulator-boot-on;
-                       gpio = <&gpio TEGRA_GPIO(K, 1) GPIO_ACTIVE_HIGH>;
-                       enable-active-high;
-                       vin-supply = <&vdd_5v0_sys>;
-               };
-
-               vdd_usb1_vbus: regulator@7 {
-                       compatible = "regulator-fixed";
-                       reg = <7>;
-                       regulator-name = "+5V_USB_HS";
-                       regulator-min-microvolt = <5000000>;
-                       regulator-max-microvolt = <5000000>;
-                       gpio = <&gpio TEGRA_GPIO(N, 4) GPIO_ACTIVE_HIGH>;
-                       enable-active-high;
-                       gpio-open-drain;
-                       vin-supply = <&vdd_5v0_sys>;
-               };
-
-               vdd_usb3_vbus: regulator@8 {
-                       compatible = "regulator-fixed";
-                       reg = <8>;
-                       regulator-name = "+5V_USB_SS";
-                       regulator-min-microvolt = <5000000>;
-                       regulator-max-microvolt = <5000000>;
-                       gpio = <&gpio TEGRA_GPIO(N, 5) GPIO_ACTIVE_HIGH>;
-                       enable-active-high;
-                       gpio-open-drain;
-                       vin-supply = <&vdd_5v0_sys>;
-               };
-
-               vdd_3v3_panel: regulator@9 {
-                       compatible = "regulator-fixed";
-                       reg = <9>;
-                       regulator-name = "+3.3V_PANEL";
-                       regulator-min-microvolt = <3300000>;
-                       regulator-max-microvolt = <3300000>;
-                       gpio = <&pmic 4 GPIO_ACTIVE_HIGH>;
-                       enable-active-high;
-                       vin-supply = <&vdd_3v3_run>;
-               };
-
-               vdd_3v3_lp0: regulator@10 {
-                       compatible = "regulator-fixed";
-                       reg = <10>;
-                       regulator-name = "+3.3V_LP0";
-                       regulator-min-microvolt = <3300000>;
-                       regulator-max-microvolt = <3300000>;
-                       /*
-                        * TODO: find a way to wire this up with the USB EHCI
-                        * controllers so that it can be enabled on demand.
-                        */
-                       regulator-always-on;
-                       gpio = <&pmic 2 GPIO_ACTIVE_HIGH>;
-                       enable-active-high;
-                       vin-supply = <&vdd_3v3_sys>;
-               };
-
-               vdd_hdmi_pll: regulator@11 {
-                       compatible = "regulator-fixed";
-                       reg = <11>;
-                       regulator-name = "+1.05V_RUN_AVDD_HDMI_PLL";
-                       regulator-min-microvolt = <1050000>;
-                       regulator-max-microvolt = <1050000>;
-                       gpio = <&gpio TEGRA_GPIO(H, 7) GPIO_ACTIVE_LOW>;
-                       vin-supply = <&vdd_1v05_run>;
-               };
-
-               vdd_5v0_hdmi: regulator@12 {
-                       compatible = "regulator-fixed";
-                       reg = <12>;
-                       regulator-name = "+5V_HDMI_CON";
-                       regulator-min-microvolt = <5000000>;
-                       regulator-max-microvolt = <5000000>;
-                       gpio = <&gpio TEGRA_GPIO(K, 6) GPIO_ACTIVE_HIGH>;
-                       enable-active-high;
-                       vin-supply = <&vdd_5v0_sys>;
-               };
-       };
-
-       sound {
-               compatible = "nvidia,tegra-audio-max98090-nyan-big",
-                            "nvidia,tegra-audio-max98090";
-               nvidia,model = "Acer Chromebook 13";
-
-               nvidia,audio-routing =
-                       "Headphones", "HPR",
-                       "Headphones", "HPL",
-                       "Speakers", "SPKR",
-                       "Speakers", "SPKL",
-                       "Mic Jack", "MICBIAS",
-                       "DMICL", "Int Mic",
-                       "DMICR", "Int Mic",
-                       "IN34", "Mic Jack";
-
-               nvidia,i2s-controller = <&tegra_i2s1>;
-               nvidia,audio-codec = <&acodec>;
-
-               clocks = <&tegra_car TEGRA124_CLK_PLL_A>,
-                        <&tegra_car TEGRA124_CLK_PLL_A_OUT0>,
-                        <&tegra_car TEGRA124_CLK_EXTERN1>;
-               clock-names = "pll_a", "pll_a_out0", "mclk";
-
-               nvidia,hp-det-gpios = <&gpio TEGRA_GPIO(I, 7) GPIO_ACTIVE_HIGH>;
-               nvidia,mic-det-gpios =
-                               <&gpio TEGRA_GPIO(R, 7) GPIO_ACTIVE_HIGH>;
-       };
 };
-
-#include "cros-ec-keyboard.dtsi"
diff --git a/arch/arm/boot/dts/tegra124-nyan-blaze-emc.dtsi b/arch/arm/boot/dts/tegra124-nyan-blaze-emc.dtsi
new file mode 100644 (file)
index 0000000..9ecd108
--- /dev/null
@@ -0,0 +1,2049 @@
+/ {
+       clock@0,60006000 {
+               emc-timings-1 {
+                       nvidia,ram-code = <1>;
+
+                       timing-12750000 {
+                               clock-frequency = <12750000>;
+                               nvidia,parent-clock-frequency = <408000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_P>;
+                               clock-names = "emc-parent";
+                       };
+                       timing-20400000 {
+                               clock-frequency = <20400000>;
+                               nvidia,parent-clock-frequency = <408000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_P>;
+                               clock-names = "emc-parent";
+                       };
+                       timing-40800000 {
+                               clock-frequency = <40800000>;
+                               nvidia,parent-clock-frequency = <408000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_P>;
+                               clock-names = "emc-parent";
+                       };
+                       timing-68000000 {
+                               clock-frequency = <68000000>;
+                               nvidia,parent-clock-frequency = <408000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_P>;
+                               clock-names = "emc-parent";
+                       };
+                       timing-102000000 {
+                               clock-frequency = <102000000>;
+                               nvidia,parent-clock-frequency = <408000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_P>;
+                               clock-names = "emc-parent";
+                       };
+                       timing-204000000 {
+                               clock-frequency = <204000000>;
+                               nvidia,parent-clock-frequency = <408000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_P>;
+                               clock-names = "emc-parent";
+                       };
+                       timing-300000000 {
+                               clock-frequency = <300000000>;
+                               nvidia,parent-clock-frequency = <600000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_C>;
+                               clock-names = "emc-parent";
+                       };
+                       timing-396000000 {
+                               clock-frequency = <396000000>;
+                               nvidia,parent-clock-frequency = <792000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_M>;
+                               clock-names = "emc-parent";
+                       };
+                       /* TODO: Add 528MHz frequency */
+                       timing-600000000 {
+                               clock-frequency = <600000000>;
+                               nvidia,parent-clock-frequency = <600000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_C_UD>;
+                               clock-names = "emc-parent";
+                       };
+                       timing-792000000 {
+                               clock-frequency = <792000000>;
+                               nvidia,parent-clock-frequency = <792000000>;
+                               clocks = <&tegra_car TEGRA124_CLK_PLL_M_UD>;
+                               clock-names = "emc-parent";
+                       };
+               };
+       };
+
+       emc@0,7001b000 {
+               emc-timings-1 {
+                       nvidia,ram-code = <1>;
+
+                       timing-12750000 {
+                               clock-frequency = <12750000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430000>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000008>;
+                               nvidia,emc-cfg = <0x73240000>;
+                               nvidia,emc-cfg-2 = <0x000008c5>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100003>;
+                               nvidia,emc-mode-2 = <0x80200008>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80001221>;
+                               nvidia,emc-mrs-wait-cnt = <0x000c000c>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040128>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x0130b118>;
+                               nvidia,emc-zcal-cnt-long = <0x00000042>;
+                               nvidia,emc-zcal-interval = <0x00000000>;
+
+                               nvidia,emc-configuration = <
+                                       0x00000000
+                                       0x00000003
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000004
+                                       0x0000000a
+                                       0x00000003
+                                       0x0000000b
+                                       0x00000000
+                                       0x00000000
+                                       0x00000003
+                                       0x00000003
+                                       0x00000000
+                                       0x00000006
+                                       0x00000006
+                                       0x00000006
+                                       0x00000002
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00010000
+                                       0x00000003
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000004
+                                       0x0000000c
+                                       0x0000000d
+                                       0x0000000f
+                                       0x00000060
+                                       0x00000000
+                                       0x00000018
+                                       0x00000002
+                                       0x00000002
+                                       0x00000001
+                                       0x00000000
+                                       0x00000007
+                                       0x0000000f
+                                       0x00000005
+                                       0x00000005
+                                       0x00000004
+                                       0x00000005
+                                       0x00000004
+                                       0x00000000
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00000064
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x106aa298
+                                       0x002c00a0
+                                       0x00008000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x0000c000
+                                       0x00000000
+                                       0x00000000
+                                       0x0000c000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x10000280
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc081
+                                       0x00000505
+                                       0x81f1f108
+                                       0x07070004
+                                       0x0000003f
+                                       0x016eeeee
+                                       0x51451400
+                                       0x00514514
+                                       0x00514514
+                                       0x51451400
+                                       0x0000003f
+                                       0x00000007
+                                       0x00000000
+                                       0x00000042
+                                       0x000c000c
+                                       0x00000000
+                                       0x00000003
+                                       0x0000f2f3
+                                       0x800001c5
+                                       0x0000000a
+                               >;
+                       };
+
+                       timing-20400000 {
+                               clock-frequency = <20400000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430000>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000008>;
+                               nvidia,emc-cfg = <0x73240000>;
+                               nvidia,emc-cfg-2 = <0x000008c5>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100003>;
+                               nvidia,emc-mode-2 = <0x80200008>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80001221>;
+                               nvidia,emc-mrs-wait-cnt = <0x000c000c>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040128>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x0130b118>;
+                               nvidia,emc-zcal-cnt-long = <0x00000042>;
+                               nvidia,emc-zcal-interval = <0x00000000>;
+
+                               nvidia,emc-configuration = <
+                                       0x00000000
+                                       0x00000005
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000004
+                                       0x0000000a
+                                       0x00000003
+                                       0x0000000b
+                                       0x00000000
+                                       0x00000000
+                                       0x00000003
+                                       0x00000003
+                                       0x00000000
+                                       0x00000006
+                                       0x00000006
+                                       0x00000006
+                                       0x00000002
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00010000
+                                       0x00000003
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000004
+                                       0x0000000c
+                                       0x0000000d
+                                       0x0000000f
+                                       0x0000009a
+                                       0x00000000
+                                       0x00000026
+                                       0x00000002
+                                       0x00000002
+                                       0x00000001
+                                       0x00000000
+                                       0x00000007
+                                       0x0000000f
+                                       0x00000006
+                                       0x00000006
+                                       0x00000004
+                                       0x00000005
+                                       0x00000004
+                                       0x00000000
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x000000a0
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x106aa298
+                                       0x002c00a0
+                                       0x00008000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x0000c000
+                                       0x00000000
+                                       0x00000000
+                                       0x0000c000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x10000280
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc081
+                                       0x00000505
+                                       0x81f1f108
+                                       0x07070004
+                                       0x0000003f
+                                       0x016eeeee
+                                       0x51451400
+                                       0x00514514
+                                       0x00514514
+                                       0x51451400
+                                       0x0000003f
+                                       0x0000000b
+                                       0x00000000
+                                       0x00000042
+                                       0x000c000c
+                                       0x00000000
+                                       0x00000003
+                                       0x0000f2f3
+                                       0x8000023a
+                                       0x0000000a
+                               >;
+                       };
+
+                       timing-40800000 {
+                               clock-frequency = <40800000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430000>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000008>;
+                               nvidia,emc-cfg = <0x73240000>;
+                               nvidia,emc-cfg-2 = <0x000008c5>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100003>;
+                               nvidia,emc-mode-2 = <0x80200008>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80001221>;
+                               nvidia,emc-mrs-wait-cnt = <0x000c000c>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040128>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x0130b118>;
+                               nvidia,emc-zcal-cnt-long = <0x00000042>;
+                               nvidia,emc-zcal-interval = <0x00000000>;
+
+                               nvidia,emc-configuration = <
+                                       0x00000001
+                                       0x0000000a
+                                       0x00000000
+                                       0x00000001
+                                       0x00000000
+                                       0x00000004
+                                       0x0000000a
+                                       0x00000003
+                                       0x0000000b
+                                       0x00000000
+                                       0x00000000
+                                       0x00000003
+                                       0x00000003
+                                       0x00000000
+                                       0x00000006
+                                       0x00000006
+                                       0x00000006
+                                       0x00000002
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00010000
+                                       0x00000003
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000004
+                                       0x0000000c
+                                       0x0000000d
+                                       0x0000000f
+                                       0x00000134
+                                       0x00000000
+                                       0x0000004d
+                                       0x00000002
+                                       0x00000002
+                                       0x00000001
+                                       0x00000000
+                                       0x00000008
+                                       0x0000000f
+                                       0x0000000c
+                                       0x0000000c
+                                       0x00000004
+                                       0x00000005
+                                       0x00000004
+                                       0x00000000
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x0000013f
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x106aa298
+                                       0x002c00a0
+                                       0x00008000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x0000c000
+                                       0x00000000
+                                       0x00000000
+                                       0x0000c000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x10000280
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc081
+                                       0x00000505
+                                       0x81f1f108
+                                       0x07070004
+                                       0x0000003f
+                                       0x016eeeee
+                                       0x51451400
+                                       0x00514514
+                                       0x00514514
+                                       0x51451400
+                                       0x0000003f
+                                       0x00000015
+                                       0x00000000
+                                       0x00000042
+                                       0x000c000c
+                                       0x00000000
+                                       0x00000003
+                                       0x0000f2f3
+                                       0x80000370
+                                       0x0000000a
+                               >;
+                       };
+
+                       timing-68000000 {
+                               clock-frequency = <68000000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430000>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000008>;
+                               nvidia,emc-cfg = <0x73240000>;
+                               nvidia,emc-cfg-2 = <0x000008c5>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100003>;
+                               nvidia,emc-mode-2 = <0x80200008>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80001221>;
+                               nvidia,emc-mrs-wait-cnt = <0x000c000c>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040128>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x0130b118>;
+                               nvidia,emc-zcal-cnt-long = <0x00000042>;
+                               nvidia,emc-zcal-interval = <0x00000000>;
+
+                               nvidia,emc-configuration = <
+                                       0x00000003
+                                       0x00000011
+                                       0x00000000
+                                       0x00000002
+                                       0x00000000
+                                       0x00000004
+                                       0x0000000a
+                                       0x00000003
+                                       0x0000000b
+                                       0x00000000
+                                       0x00000000
+                                       0x00000003
+                                       0x00000003
+                                       0x00000000
+                                       0x00000006
+                                       0x00000006
+                                       0x00000006
+                                       0x00000002
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00010000
+                                       0x00000003
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000004
+                                       0x0000000c
+                                       0x0000000d
+                                       0x0000000f
+                                       0x00000202
+                                       0x00000000
+                                       0x00000080
+                                       0x00000002
+                                       0x00000002
+                                       0x00000001
+                                       0x00000000
+                                       0x0000000f
+                                       0x0000000f
+                                       0x00000013
+                                       0x00000013
+                                       0x00000004
+                                       0x00000005
+                                       0x00000004
+                                       0x00000001
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00000213
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x106aa298
+                                       0x002c00a0
+                                       0x00008000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x0000c000
+                                       0x00000000
+                                       0x00000000
+                                       0x0000c000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x10000280
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc081
+                                       0x00000505
+                                       0x81f1f108
+                                       0x07070004
+                                       0x0000003f
+                                       0x016eeeee
+                                       0x51451400
+                                       0x00514514
+                                       0x00514514
+                                       0x51451400
+                                       0x0000003f
+                                       0x00000022
+                                       0x00000000
+                                       0x00000042
+                                       0x000c000c
+                                       0x00000000
+                                       0x00000003
+                                       0x0000f2f3
+                                       0x8000050e
+                                       0x0000000a
+                               >;
+                       };
+
+                       timing-102000000 {
+                               clock-frequency = <102000000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430000>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000008>;
+                               nvidia,emc-cfg = <0x73240000>;
+                               nvidia,emc-cfg-2 = <0x000008c5>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100003>;
+                               nvidia,emc-mode-2 = <0x80200008>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80001221>;
+                               nvidia,emc-mrs-wait-cnt = <0x000c000c>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040128>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x0130b118>;
+                               nvidia,emc-zcal-cnt-long = <0x00000042>;
+                               nvidia,emc-zcal-interval = <0x00000000>;
+
+                               nvidia,emc-configuration = <
+                                       0x00000004
+                                       0x0000001a
+                                       0x00000000
+                                       0x00000003
+                                       0x00000001
+                                       0x00000004
+                                       0x0000000a
+                                       0x00000003
+                                       0x0000000b
+                                       0x00000001
+                                       0x00000001
+                                       0x00000003
+                                       0x00000003
+                                       0x00000000
+                                       0x00000006
+                                       0x00000006
+                                       0x00000006
+                                       0x00000002
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00010000
+                                       0x00000003
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000004
+                                       0x0000000c
+                                       0x0000000d
+                                       0x0000000f
+                                       0x00000304
+                                       0x00000000
+                                       0x000000c1
+                                       0x00000002
+                                       0x00000002
+                                       0x00000001
+                                       0x00000000
+                                       0x00000018
+                                       0x0000000f
+                                       0x0000001c
+                                       0x0000001c
+                                       0x00000004
+                                       0x00000005
+                                       0x00000004
+                                       0x00000003
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x0000031c
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x106aa298
+                                       0x002c00a0
+                                       0x00008000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x0000c000
+                                       0x00000000
+                                       0x00000000
+                                       0x0000c000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x000fc000
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x0000fc00
+                                       0x10000280
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc081
+                                       0x00000505
+                                       0x81f1f108
+                                       0x07070004
+                                       0x0000003f
+                                       0x016eeeee
+                                       0x51451400
+                                       0x00514514
+                                       0x00514514
+                                       0x51451400
+                                       0x0000003f
+                                       0x00000033
+                                       0x00000000
+                                       0x00000042
+                                       0x000c000c
+                                       0x00000000
+                                       0x00000003
+                                       0x0000f2f3
+                                       0x80000713
+                                       0x0000000a
+                               >;
+                       };
+
+                       timing-204000000 {
+                               clock-frequency = <204000000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430000>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000008>;
+                               nvidia,emc-cfg = <0x73240000>;
+                               nvidia,emc-cfg-2 = <0x0000088d>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100003>;
+                               nvidia,emc-mode-2 = <0x80200008>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80001221>;
+                               nvidia,emc-mrs-wait-cnt = <0x000c000c>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040008>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x0130b118>;
+                               nvidia,emc-zcal-cnt-long = <0x00000042>;
+                               nvidia,emc-zcal-interval = <0x00020000>;
+
+                               nvidia,emc-configuration = <
+                                       0x00000009
+                                       0x00000035
+                                       0x00000000
+                                       0x00000007
+                                       0x00000002
+                                       0x00000005
+                                       0x0000000a
+                                       0x00000003
+                                       0x0000000b
+                                       0x00000002
+                                       0x00000002
+                                       0x00000003
+                                       0x00000003
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00000006
+                                       0x00000002
+                                       0x00000000
+                                       0x00000004
+                                       0x00000006
+                                       0x00010000
+                                       0x00000003
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000003
+                                       0x0000000d
+                                       0x0000000f
+                                       0x00000011
+                                       0x00000607
+                                       0x00000000
+                                       0x00000181
+                                       0x00000002
+                                       0x00000002
+                                       0x00000001
+                                       0x00000000
+                                       0x00000032
+                                       0x0000000f
+                                       0x00000038
+                                       0x00000038
+                                       0x00000004
+                                       0x00000005
+                                       0x00000004
+                                       0x00000007
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00000638
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x106aa298
+                                       0x002c00a0
+                                       0x00008000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00064000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x0000c000
+                                       0x00000000
+                                       0x00000000
+                                       0x0000c000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00090000
+                                       0x00090000
+                                       0x00090000
+                                       0x00090000
+                                       0x00009000
+                                       0x00009000
+                                       0x00009000
+                                       0x00009000
+                                       0x10000280
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc081
+                                       0x00000505
+                                       0x81f1f108
+                                       0x07070004
+                                       0x0000003f
+                                       0x016eeeee
+                                       0x51451400
+                                       0x00514514
+                                       0x00514514
+                                       0x51451400
+                                       0x0000003f
+                                       0x00000066
+                                       0x00000000
+                                       0x00000100
+                                       0x000c000c
+                                       0x00000000
+                                       0x00000003
+                                       0x0000d2b3
+                                       0x80000d22
+                                       0x0000000a
+                               >;
+                       };
+
+                       timing-300000000 {
+                               clock-frequency = <300000000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430000>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000000>;
+                               nvidia,emc-cfg = <0x73340000>;
+                               nvidia,emc-cfg-2 = <0x000008d5>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100002>;
+                               nvidia,emc-mode-2 = <0x80200000>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80000321>;
+                               nvidia,emc-mrs-wait-cnt = <0x0174000c>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040128>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x01231339>;
+                               nvidia,emc-zcal-cnt-long = <0x00000042>;
+                               nvidia,emc-zcal-interval = <0x00020000>;
+
+                               nvidia,emc-configuration = <
+                                       0x0000000d
+                                       0x0000004c
+                                       0x00000000
+                                       0x00000009
+                                       0x00000003
+                                       0x00000004
+                                       0x00000008
+                                       0x00000002
+                                       0x00000009
+                                       0x00000003
+                                       0x00000003
+                                       0x00000002
+                                       0x00000002
+                                       0x00000000
+                                       0x00000003
+                                       0x00000003
+                                       0x00000005
+                                       0x00000002
+                                       0x00000000
+                                       0x00000002
+                                       0x00000007
+                                       0x00020000
+                                       0x00000003
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000001
+                                       0x0000000e
+                                       0x00000010
+                                       0x00000012
+                                       0x000008e4
+                                       0x00000000
+                                       0x00000239
+                                       0x00000001
+                                       0x00000008
+                                       0x00000001
+                                       0x00000000
+                                       0x0000004a
+                                       0x0000000e
+                                       0x00000051
+                                       0x00000200
+                                       0x00000004
+                                       0x00000005
+                                       0x00000004
+                                       0x00000009
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00000924
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x104ab098
+                                       0x002c00a0
+                                       0x00008000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00090000
+                                       0x00090000
+                                       0x00000000
+                                       0x00090000
+                                       0x00090000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00060000
+                                       0x00060000
+                                       0x00060000
+                                       0x00060000
+                                       0x00006000
+                                       0x00006000
+                                       0x00006000
+                                       0x00006000
+                                       0x10000280
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc081
+                                       0x00000202
+                                       0x81f1f108
+                                       0x07070004
+                                       0x00000000
+                                       0x016eeeee
+                                       0x51451420
+                                       0x00514514
+                                       0x00514514
+                                       0x51451400
+                                       0x0000003f
+                                       0x00000096
+                                       0x00000000
+                                       0x00000100
+                                       0x0174000c
+                                       0x00000000
+                                       0x00000003
+                                       0x000052a3
+                                       0x800012d7
+                                       0x00000009
+                               >;
+                       };
+
+                       timing-396000000 {
+                               clock-frequency = <396000000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430000>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000000>;
+                               nvidia,emc-cfg = <0x73340000>;
+                               nvidia,emc-cfg-2 = <0x00000895>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100002>;
+                               nvidia,emc-mode-2 = <0x80200000>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80000521>;
+                               nvidia,emc-mrs-wait-cnt = <0x015b000c>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040008>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x01231339>;
+                               nvidia,emc-zcal-cnt-long = <0x00000042>;
+                               nvidia,emc-zcal-interval = <0x00020000>;
+
+                               nvidia,emc-configuration = <
+                                       0x00000012
+                                       0x00000065
+                                       0x00000000
+                                       0x0000000c
+                                       0x00000004
+                                       0x00000005
+                                       0x00000008
+                                       0x00000002
+                                       0x0000000a
+                                       0x00000004
+                                       0x00000004
+                                       0x00000002
+                                       0x00000002
+                                       0x00000000
+                                       0x00000003
+                                       0x00000003
+                                       0x00000005
+                                       0x00000002
+                                       0x00000000
+                                       0x00000001
+                                       0x00000008
+                                       0x00020000
+                                       0x00000003
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x0000000f
+                                       0x00000010
+                                       0x00000012
+                                       0x00000bd1
+                                       0x00000000
+                                       0x000002f4
+                                       0x00000001
+                                       0x00000008
+                                       0x00000001
+                                       0x00000000
+                                       0x00000063
+                                       0x0000000f
+                                       0x0000006b
+                                       0x00000200
+                                       0x00000004
+                                       0x00000005
+                                       0x00000004
+                                       0x0000000d
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x00000c11
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x104ab098
+                                       0x002c00a0
+                                       0x00008000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00030000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00068000
+                                       0x00068000
+                                       0x00000000
+                                       0x00068000
+                                       0x00068000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00058000
+                                       0x00058000
+                                       0x00058000
+                                       0x00058000
+                                       0x00005800
+                                       0x00005800
+                                       0x00005800
+                                       0x00005800
+                                       0x10000280
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc081
+                                       0x00000202
+                                       0x81f1f108
+                                       0x07070004
+                                       0x00000000
+                                       0x016eeeee
+                                       0x51451420
+                                       0x00514514
+                                       0x00514514
+                                       0x51451400
+                                       0x0000003f
+                                       0x000000c6
+                                       0x00000000
+                                       0x00000100
+                                       0x015b000c
+                                       0x00000000
+                                       0x00000003
+                                       0x000052a3
+                                       0x8000188b
+                                       0x00000009
+                               >;
+                       };
+
+                       timing-600000000 {
+                               clock-frequency = <600000000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430000>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000000>;
+                               nvidia,emc-cfg = <0x73300000>;
+                               nvidia,emc-cfg-2 = <0x0000089d>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100002>;
+                               nvidia,emc-mode-2 = <0x80200010>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80000b61>;
+                               nvidia,emc-mrs-wait-cnt = <0x0128000c>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040008>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x0121113d>;
+                               nvidia,emc-zcal-cnt-long = <0x00000042>;
+                               nvidia,emc-zcal-interval = <0x00020000>;
+
+                               nvidia,emc-configuration = <
+                                       0x0000001c
+                                       0x0000009a
+                                       0x00000000
+                                       0x00000013
+                                       0x00000007
+                                       0x00000007
+                                       0x0000000b
+                                       0x00000003
+                                       0x00000010
+                                       0x00000007
+                                       0x00000007
+                                       0x00000002
+                                       0x00000002
+                                       0x00000000
+                                       0x00000005
+                                       0x00000005
+                                       0x0000000a
+                                       0x00000002
+                                       0x00000000
+                                       0x00000003
+                                       0x0000000b
+                                       0x00070000
+                                       0x00000003
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000002
+                                       0x00000012
+                                       0x00000016
+                                       0x00000018
+                                       0x00001208
+                                       0x00000000
+                                       0x00000482
+                                       0x00000002
+                                       0x0000000d
+                                       0x00000001
+                                       0x00000000
+                                       0x00000096
+                                       0x00000015
+                                       0x000000a2
+                                       0x00000200
+                                       0x00000004
+                                       0x00000005
+                                       0x00000004
+                                       0x00000015
+                                       0x00000000
+                                       0x00000006
+                                       0x00000006
+                                       0x00001248
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x104ab098
+                                       0xe00e00b1
+                                       0x00008000
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000a
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00040000
+                                       0x00040000
+                                       0x00000000
+                                       0x00040000
+                                       0x00040000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000004
+                                       0x00000004
+                                       0x00000001
+                                       0x00000005
+                                       0x00000007
+                                       0x00000004
+                                       0x00000006
+                                       0x00000007
+                                       0x00000004
+                                       0x00000004
+                                       0x00000001
+                                       0x00000005
+                                       0x00000007
+                                       0x00000004
+                                       0x00000006
+                                       0x00000007
+                                       0x0000000e
+                                       0x0000000e
+                                       0x0000000e
+                                       0x0000000e
+                                       0x0000000e
+                                       0x0000000e
+                                       0x0000000e
+                                       0x0000000e
+                                       0x100002a0
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc085
+                                       0x00000202
+                                       0x81f1f108
+                                       0x07070004
+                                       0x00000000
+                                       0x016eeeee
+                                       0x51451420
+                                       0x00514514
+                                       0x00514514
+                                       0x51451400
+                                       0x0606003f
+                                       0x00000000
+                                       0x00000000
+                                       0x00000100
+                                       0x0128000c
+                                       0x00000000
+                                       0x00000003
+                                       0x000040a0
+                                       0x800024a9
+                                       0x0000000e
+                               >;
+                       };
+
+                       timing-792000000 {
+                               clock-frequency = <792000000>;
+
+                               nvidia,emc-auto-cal-config = <0xa1430000>;
+                               nvidia,emc-auto-cal-config2 = <0x00000000>;
+                               nvidia,emc-auto-cal-config3 = <0x00000000>;
+                               nvidia,emc-auto-cal-interval = <0x001fffff>;
+                               nvidia,emc-bgbias-ctl0 = <0x00000000>;
+                               nvidia,emc-cfg = <0x73300000>;
+                               nvidia,emc-cfg-2 = <0x0000089d>;
+                               nvidia,emc-ctt-term-ctrl = <0x00000802>;
+                               nvidia,emc-mode-1 = <0x80100002>;
+                               nvidia,emc-mode-2 = <0x80200018>;
+                               nvidia,emc-mode-4 = <0x00000000>;
+                               nvidia,emc-mode-reset = <0x80000d71>;
+                               nvidia,emc-mrs-wait-cnt = <0x00f8000c>;
+                               nvidia,emc-sel-dpd-ctrl = <0x00040000>;
+                               nvidia,emc-xm2dqspadctrl2 = <0x0120113d>;
+                               nvidia,emc-zcal-cnt-long = <0x00000042>;
+                               nvidia,emc-zcal-interval = <0x00020000>;
+
+                               nvidia,emc-configuration = <
+                                       0x00000025
+                                       0x000000cc
+                                       0x00000000
+                                       0x0000001a
+                                       0x00000009
+                                       0x00000008
+                                       0x0000000d
+                                       0x00000004
+                                       0x00000013
+                                       0x00000009
+                                       0x00000009
+                                       0x00000003
+                                       0x00000002
+                                       0x00000000
+                                       0x00000006
+                                       0x00000006
+                                       0x0000000b
+                                       0x00000002
+                                       0x00000000
+                                       0x00000002
+                                       0x0000000d
+                                       0x00080000
+                                       0x00000004
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000001
+                                       0x00000014
+                                       0x00000018
+                                       0x0000001a
+                                       0x000017e2
+                                       0x00000000
+                                       0x000005f8
+                                       0x00000003
+                                       0x00000011
+                                       0x00000001
+                                       0x00000000
+                                       0x000000c6
+                                       0x00000018
+                                       0x000000d6
+                                       0x00000200
+                                       0x00000005
+                                       0x00000006
+                                       0x00000005
+                                       0x0000001d
+                                       0x00000000
+                                       0x00000008
+                                       0x00000008
+                                       0x00001822
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x104ab098
+                                       0xe00700b1
+                                       0x00008000
+                                       0x00000008
+                                       0x00000008
+                                       0x00000008
+                                       0x00000008
+                                       0x00000008
+                                       0x00000008
+                                       0x00000008
+                                       0x00000008
+                                       0x00000008
+                                       0x00000008
+                                       0x00000008
+                                       0x00000008
+                                       0x00000008
+                                       0x00000008
+                                       0x00000008
+                                       0x00000008
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x0002c000
+                                       0x0002c000
+                                       0x00000000
+                                       0x0002c000
+                                       0x0002c000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000000
+                                       0x00000008
+                                       0x00000008
+                                       0x00000005
+                                       0x00000008
+                                       0x0000000a
+                                       0x00000008
+                                       0x0000000a
+                                       0x0000000a
+                                       0x00000008
+                                       0x00000008
+                                       0x00000005
+                                       0x00000008
+                                       0x0000000a
+                                       0x00000008
+                                       0x0000000a
+                                       0x0000000a
+                                       0x0000000e
+                                       0x0000000e
+                                       0x0000000e
+                                       0x0000000e
+                                       0x0000000e
+                                       0x0000000e
+                                       0x0000000e
+                                       0x0000000e
+                                       0x100002a0
+                                       0x00000000
+                                       0x00111111
+                                       0x00000000
+                                       0x00000000
+                                       0x77ffc085
+                                       0x00000202
+                                       0x81f1f108
+                                       0x07070004
+                                       0x00000000
+                                       0x016eeeee
+                                       0x61861820
+                                       0x00492492
+                                       0x00492492
+                                       0x61861800
+                                       0x0606003f
+                                       0x00000000
+                                       0x00000000
+                                       0x00000100
+                                       0x00f8000c
+                                       0x00000000
+                                       0x00000004
+                                       0x00004080
+                                       0x80003012
+                                       0x0000000f
+                               >;
+                       };
+
+               };
+       };
+
+       memory-controller@0,70019000 {
+               emc-timings-1 {
+                       nvidia,ram-code = <1>;
+
+
+                       timing-12750000 {
+                               clock-frequency = <12750000>;
+
+                               nvidia,emem-configuration = <
+                                       0x40040001
+                                       0x8000000a
+                                       0x00000001
+                                       0x00000001
+                                       0x00000002
+                                       0x00000000
+                                       0x00000002
+                                       0x00000001
+                                       0x00000002
+                                       0x00000008
+                                       0x00000003
+                                       0x00000002
+                                       0x00000003
+                                       0x00000006
+                                       0x06030203
+                                       0x000a0402
+                                       0x77e30303
+                                       0x70000f03
+                                       0x001f0000
+                               >;
+                       };
+
+                       timing-20400000 {
+                               clock-frequency = <20400000>;
+
+                               nvidia,emem-configuration = <
+                                       0x40020001
+                                       0x80000012
+                                       0x00000001
+                                       0x00000001
+                                       0x00000002
+                                       0x00000000
+                                       0x00000002
+                                       0x00000001
+                                       0x00000002
+                                       0x00000008
+                                       0x00000003
+                                       0x00000002
+                                       0x00000003
+                                       0x00000006
+                                       0x06030203
+                                       0x000a0402
+                                       0x76230303
+                                       0x70000f03
+                                       0x001f0000
+                               >;
+                       };
+
+                       timing-40800000 {
+                               clock-frequency = <40800000>;
+
+                               nvidia,emem-configuration = <
+                                       0xa0000001
+                                       0x80000017
+                                       0x00000001
+                                       0x00000001
+                                       0x00000002
+                                       0x00000000
+                                       0x00000002
+                                       0x00000001
+                                       0x00000002
+                                       0x00000008
+                                       0x00000003
+                                       0x00000002
+                                       0x00000003
+                                       0x00000006
+                                       0x06030203
+                                       0x000a0402
+                                       0x74a30303
+                                       0x70000f03
+                                       0x001f0000
+                               >;
+                       };
+
+                       timing-68000000 {
+                               clock-frequency = <68000000>;
+
+                               nvidia,emem-configuration = <
+                                       0x00000001
+                                       0x8000001e
+                                       0x00000001
+                                       0x00000001
+                                       0x00000002
+                                       0x00000000
+                                       0x00000002
+                                       0x00000001
+                                       0x00000002
+                                       0x00000008
+                                       0x00000003
+                                       0x00000002
+                                       0x00000003
+                                       0x00000006
+                                       0x06030203
+                                       0x000a0402
+                                       0x74230403
+                                       0x70000f03
+                                       0x001f0000
+                               >;
+                       };
+
+                       timing-102000000 {
+                               clock-frequency = <102000000>;
+
+                               nvidia,emem-configuration = <
+                                       0x08000001
+                                       0x80000026
+                                       0x00000001
+                                       0x00000001
+                                       0x00000003
+                                       0x00000000
+                                       0x00000002
+                                       0x00000001
+                                       0x00000002
+                                       0x00000008
+                                       0x00000003
+                                       0x00000002
+                                       0x00000003
+                                       0x00000006
+                                       0x06030203
+                                       0x000a0403
+                                       0x73c30504
+                                       0x70000f03
+                                       0x001f0000
+                               >;
+                       };
+
+                       timing-204000000 {
+                               clock-frequency = <204000000>;
+
+                               nvidia,emem-configuration = <
+                                       0x01000003
+                                       0x80000040
+                                       0x00000001
+                                       0x00000001
+                                       0x00000005
+                                       0x00000002
+                                       0x00000004
+                                       0x00000001
+                                       0x00000002
+                                       0x00000008
+                                       0x00000003
+                                       0x00000002
+                                       0x00000004
+                                       0x00000006
+                                       0x06040203
+                                       0x000a0405
+                                       0x73840a06
+                                       0x70000f03
+                                       0x001f0000
+                               >;
+                       };
+
+                       timing-300000000 {
+                               clock-frequency = <300000000>;
+
+                               nvidia,emem-configuration = <
+                                       0x08000004
+                                       0x80000040
+                                       0x00000001
+                                       0x00000002
+                                       0x00000007
+                                       0x00000004
+                                       0x00000005
+                                       0x00000001
+                                       0x00000002
+                                       0x00000007
+                                       0x00000002
+                                       0x00000002
+                                       0x00000004
+                                       0x00000006
+                                       0x06040202
+                                       0x000b0607
+                                       0x77450e08
+                                       0x70000f03
+                                       0x001f0000
+                               >;
+                       };
+
+                       timing-396000000 {
+                               clock-frequency = <396000000>;
+
+                               nvidia,emem-configuration = <
+                                       0x0f000005
+                                       0x80000040
+                                       0x00000001
+                                       0x00000002
+                                       0x00000009
+                                       0x00000005
+                                       0x00000007
+                                       0x00000001
+                                       0x00000002
+                                       0x00000008
+                                       0x00000002
+                                       0x00000002
+                                       0x00000004
+                                       0x00000006
+                                       0x06040202
+                                       0x000d0709
+                                       0x7586120a
+                                       0x70000f03
+                                       0x001f0000
+                               >;
+                       };
+
+                       timing-528000000 {
+                               clock-frequency = <528000000>;
+
+                               nvidia,emem-configuration = <
+                                       0x0f000007
+                                       0x80000040
+                                       0x00000002
+                                       0x00000003
+                                       0x0000000d
+                                       0x00000008
+                                       0x0000000a
+                                       0x00000001
+                                       0x00000002
+                                       0x00000009
+                                       0x00000002
+                                       0x00000002
+                                       0x00000005
+                                       0x00000006
+                                       0x06050202
+                                       0x0010090d
+                                       0x7428180e
+                                       0x70000f03
+                                       0x001f0000
+                               >;
+                       };
+
+                       timing-600000000 {
+                               clock-frequency = <600000000>;
+
+                               nvidia,emem-configuration = <
+                                       0x00000009
+                                       0x80000040
+                                       0x00000003
+                                       0x00000004
+                                       0x0000000e
+                                       0x00000009
+                                       0x0000000b
+                                       0x00000001
+                                       0x00000003
+                                       0x0000000b
+                                       0x00000002
+                                       0x00000002
+                                       0x00000005
+                                       0x00000007
+                                       0x07050202
+                                       0x00130b0e
+                                       0x73a91b0f
+                                       0x70000f03
+                                       0x001f0000
+                               >;
+                       };
+
+                       timing-792000000 {
+                               clock-frequency = <792000000>;
+
+                               nvidia,emem-configuration = <
+                                       0x0e00000b
+                                       0x80000040
+                                       0x00000004
+                                       0x00000005
+                                       0x00000013
+                                       0x0000000c
+                                       0x0000000f
+                                       0x00000002
+                                       0x00000003
+                                       0x0000000c
+                                       0x00000002
+                                       0x00000002
+                                       0x00000006
+                                       0x00000008
+                                       0x08060202
+                                       0x00160d13
+                                       0x734c2414
+                                       0x70000f02
+                                       0x001f0000
+                               >;
+                       };
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/tegra124-nyan-blaze.dts b/arch/arm/boot/dts/tegra124-nyan-blaze.dts
new file mode 100644 (file)
index 0000000..0d30c51
--- /dev/null
@@ -0,0 +1,1334 @@
+/dts-v1/;
+
+#include "tegra124-nyan.dtsi"
+
+#include "tegra124-nyan-blaze-emc.dtsi"
+
+/ {
+       model = "HP Chromebook 14";
+       compatible = "google,nyan-blaze", "google,nyan", "nvidia,tegra124";
+
+       panel: panel {
+               compatible = "samsung,ltn140at29-301";
+
+               backlight = <&backlight>;
+               ddc-i2c-bus = <&dpaux>;
+       };
+
+       sound {
+               compatible = "nvidia,tegra-audio-max98090-nyan-blaze",
+                            "nvidia,tegra-audio-max98090-nyan",
+                            "nvidia,tegra-audio-max98090";
+               nvidia,model = "GoogleNyanBlaze";
+       };
+
+       pinmux@0,70000868 {
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinmux_default>;
+
+               pinmux_default: common {
+                       clk_32k_out_pa0 {
+                               nvidia,pins = "clk_32k_out_pa0";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       uart3_cts_n_pa1 {
+                               nvidia,pins = "uart3_cts_n_pa1";
+                               nvidia,function = "gmi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       dap2_fs_pa2 {
+                               nvidia,pins = "dap2_fs_pa2";
+                               nvidia,function = "i2s1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       dap2_sclk_pa3 {
+                               nvidia,pins = "dap2_sclk_pa3";
+                               nvidia,function = "i2s1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       dap2_din_pa4 {
+                               nvidia,pins = "dap2_din_pa4";
+                               nvidia,function = "i2s1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       dap2_dout_pa5 {
+                               nvidia,pins = "dap2_dout_pa5";
+                               nvidia,function = "i2s1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc3_clk_pa6 {
+                               nvidia,pins = "sdmmc3_clk_pa6";
+                               nvidia,function = "sdmmc3";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       sdmmc3_cmd_pa7 {
+                               nvidia,pins = "sdmmc3_cmd_pa7";
+                               nvidia,function = "sdmmc3";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pb0 {
+                               nvidia,pins = "pb0";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pb1 {
+                               nvidia,pins = "pb1";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       sdmmc3_dat3_pb4 {
+                               nvidia,pins = "sdmmc3_dat3_pb4";
+                               nvidia,function = "sdmmc3";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc3_dat2_pb5 {
+                               nvidia,pins = "sdmmc3_dat2_pb5";
+                               nvidia,function = "sdmmc3";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc3_dat1_pb6 {
+                               nvidia,pins = "sdmmc3_dat1_pb6";
+                               nvidia,function = "sdmmc3";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc3_dat0_pb7 {
+                               nvidia,pins = "sdmmc3_dat0_pb7";
+                               nvidia,function = "sdmmc3";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       uart3_rts_n_pc0 {
+                               nvidia,pins = "uart3_rts_n_pc0";
+                               nvidia,function = "gmi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       uart2_txd_pc2 {
+                               nvidia,pins = "uart2_txd_pc2";
+                               nvidia,function = "irda";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       uart2_rxd_pc3 {
+                               nvidia,pins = "uart2_rxd_pc3";
+                               nvidia,function = "irda";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gen1_i2c_scl_pc4 {
+                               nvidia,pins = "gen1_i2c_scl_pc4";
+                               nvidia,function = "i2c1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+                       };
+                       gen1_i2c_sda_pc5 {
+                               nvidia,pins = "gen1_i2c_sda_pc5";
+                               nvidia,function = "i2c1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+                       };
+                       pc7 {
+                               nvidia,pins = "pc7";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pg0 {
+                               nvidia,pins = "pg0";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pg1 {
+                               nvidia,pins = "pg1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pg2 {
+                               nvidia,pins = "pg2";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pg3 {
+                               nvidia,pins = "pg3";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pg4 {
+                               nvidia,pins = "pg4";
+                               nvidia,function = "spi4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pg5 {
+                               nvidia,pins = "pg5";
+                               nvidia,function = "spi4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pg6 {
+                               nvidia,pins = "pg6";
+                               nvidia,function = "spi4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pg7 {
+                               nvidia,pins = "pg7";
+                               nvidia,function = "spi4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       ph0 {
+                               nvidia,pins = "ph0";
+                               nvidia,function = "gmi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       ph1 {
+                               nvidia,pins = "ph1";
+                               nvidia,function = "pwm1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       ph2 {
+                               nvidia,pins = "ph2";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       ph3 {
+                               nvidia,pins = "ph3";
+                               nvidia,function = "gmi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       ph4 {
+                               nvidia,pins = "ph4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       ph5 {
+                               nvidia,pins = "ph5";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       ph6 {
+                               nvidia,pins = "ph6";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       ph7 {
+                               nvidia,pins = "ph7";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pi0 {
+                               nvidia,pins = "pi0";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pi1 {
+                               nvidia,pins = "pi1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pi2 {
+                               nvidia,pins = "pi2";
+                               nvidia,function = "rsvd4";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pi3 {
+                               nvidia,pins = "pi3";
+                               nvidia,function = "spi4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pi4 {
+                               nvidia,pins = "pi4";
+                               nvidia,function = "gmi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pi5 {
+                               nvidia,pins = "pi5";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pi6 {
+                               nvidia,pins = "pi6";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pi7 {
+                               nvidia,pins = "pi7";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pj0 {
+                               nvidia,pins = "pj0";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pj2 {
+                               nvidia,pins = "pj2";
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       uart2_cts_n_pj5 {
+                               nvidia,pins = "uart2_cts_n_pj5";
+                               nvidia,function = "gmi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       uart2_rts_n_pj6 {
+                               nvidia,pins = "uart2_rts_n_pj6";
+                               nvidia,function = "gmi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pj7 {
+                               nvidia,pins = "pj7";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pk0 {
+                               nvidia,pins = "pk0";
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pk1 {
+                               nvidia,pins = "pk1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pk2 {
+                               nvidia,pins = "pk2";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pk3 {
+                               nvidia,pins = "pk3";
+                               nvidia,function = "gmi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pk4 {
+                               nvidia,pins = "pk4";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       spdif_out_pk5 {
+                               nvidia,pins = "spdif_out_pk5";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       spdif_in_pk6 {
+                               nvidia,pins = "spdif_in_pk6";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pk7 {
+                               nvidia,pins = "pk7";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       dap1_fs_pn0 {
+                               nvidia,pins = "dap1_fs_pn0";
+                               nvidia,function = "rsvd4";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       dap1_din_pn1 {
+                               nvidia,pins = "dap1_din_pn1";
+                               nvidia,function = "rsvd4";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       dap1_dout_pn2 {
+                               nvidia,pins = "dap1_dout_pn2";
+                               nvidia,function = "i2s0";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       dap1_sclk_pn3 {
+                               nvidia,pins = "dap1_sclk_pn3";
+                               nvidia,function = "rsvd4";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       usb_vbus_en0_pn4 {
+                               nvidia,pins = "usb_vbus_en0_pn4";
+                               nvidia,function = "usb";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+                       };
+                       usb_vbus_en1_pn5 {
+                               nvidia,pins = "usb_vbus_en1_pn5";
+                               nvidia,function = "usb";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+                       };
+                       hdmi_int_pn7 {
+                               nvidia,pins = "hdmi_int_pn7";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,rcv-sel = <TEGRA_PIN_DISABLE>;
+                       };
+                       ulpi_data7_po0 {
+                               nvidia,pins = "ulpi_data7_po0";
+                               nvidia,function = "ulpi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       ulpi_data0_po1 {
+                               nvidia,pins = "ulpi_data0_po1";
+                               nvidia,function = "ulpi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       ulpi_data1_po2 {
+                               nvidia,pins = "ulpi_data1_po2";
+                               nvidia,function = "ulpi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       ulpi_data2_po3 {
+                               nvidia,pins = "ulpi_data2_po3";
+                               nvidia,function = "ulpi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       ulpi_data3_po4 {
+                               nvidia,pins = "ulpi_data3_po4";
+                               nvidia,function = "ulpi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       ulpi_data4_po5 {
+                               nvidia,pins = "ulpi_data4_po5";
+                               nvidia,function = "ulpi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       ulpi_data5_po6 {
+                               nvidia,pins = "ulpi_data5_po6";
+                               nvidia,function = "ulpi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       ulpi_data6_po7 {
+                               nvidia,pins = "ulpi_data6_po7";
+                               nvidia,function = "ulpi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       dap3_fs_pp0 {
+                               nvidia,pins = "dap3_fs_pp0";
+                               nvidia,function = "i2s2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       dap3_din_pp1 {
+                               nvidia,pins = "dap3_din_pp1";
+                               nvidia,function = "i2s2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       dap3_dout_pp2 {
+                               nvidia,pins = "dap3_dout_pp2";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       dap3_sclk_pp3 {
+                               nvidia,pins = "dap3_sclk_pp3";
+                               nvidia,function = "rsvd3";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       dap4_fs_pp4 {
+                               nvidia,pins = "dap4_fs_pp4";
+                               nvidia,function = "rsvd4";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       dap4_din_pp5 {
+                               nvidia,pins = "dap4_din_pp5";
+                               nvidia,function = "rsvd3";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       dap4_dout_pp6 {
+                               nvidia,pins = "dap4_dout_pp6";
+                               nvidia,function = "rsvd4";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       dap4_sclk_pp7 {
+                               nvidia,pins = "dap4_sclk_pp7";
+                               nvidia,function = "rsvd3";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       kb_col0_pq0 {
+                               nvidia,pins = "kb_col0_pq0";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_col1_pq1 {
+                               nvidia,pins = "kb_col1_pq1";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       kb_col2_pq2 {
+                               nvidia,pins = "kb_col2_pq2";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_col3_pq3 {
+                               nvidia,pins = "kb_col3_pq3";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_col4_pq4 {
+                               nvidia,pins = "kb_col4_pq4";
+                               nvidia,function = "sdmmc3";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_col5_pq5 {
+                               nvidia,pins = "kb_col5_pq5";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       kb_col6_pq6 {
+                               nvidia,pins = "kb_col6_pq6";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_col7_pq7 {
+                               nvidia,pins = "kb_col7_pq7";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_row0_pr0 {
+                               nvidia,pins = "kb_row0_pr0";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       kb_row1_pr1 {
+                               nvidia,pins = "kb_row1_pr1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_row2_pr2 {
+                               nvidia,pins = "kb_row2_pr2";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       kb_row3_pr3 {
+                               nvidia,pins = "kb_row3_pr3";
+                               nvidia,function = "kbc";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       kb_row4_pr4 {
+                               nvidia,pins = "kb_row4_pr4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_row5_pr5 {
+                               nvidia,pins = "kb_row5_pr5";
+                               nvidia,function = "rsvd3";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       kb_row6_pr6 {
+                               nvidia,pins = "kb_row6_pr6";
+                               nvidia,function = "kbc";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       kb_row7_pr7 {
+                               nvidia,pins = "kb_row7_pr7";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_row8_ps0 {
+                               nvidia,pins = "kb_row8_ps0";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       kb_row9_ps1 {
+                               nvidia,pins = "kb_row9_ps1";
+                               nvidia,function = "uarta";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       kb_row10_ps2 {
+                               nvidia,pins = "kb_row10_ps2";
+                               nvidia,function = "uarta";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_row11_ps3 {
+                               nvidia,pins = "kb_row11_ps3";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       kb_row12_ps4 {
+                               nvidia,pins = "kb_row12_ps4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       kb_row13_ps5 {
+                               nvidia,pins = "kb_row13_ps5";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       kb_row14_ps6 {
+                               nvidia,pins = "kb_row14_ps6";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       kb_row15_ps7 {
+                               nvidia,pins = "kb_row15_ps7";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_row16_pt0 {
+                               nvidia,pins = "kb_row16_pt0";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       kb_row17_pt1 {
+                               nvidia,pins = "kb_row17_pt1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       gen2_i2c_scl_pt5 {
+                               nvidia,pins = "gen2_i2c_scl_pt5";
+                               nvidia,function = "i2c2";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+                       };
+                       gen2_i2c_sda_pt6 {
+                               nvidia,pins = "gen2_i2c_sda_pt6";
+                               nvidia,function = "i2c2";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc4_cmd_pt7 {
+                               nvidia,pins = "sdmmc4_cmd_pt7";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pu0 {
+                               nvidia,pins = "pu0";
+                               nvidia,function = "rsvd4";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pu1 {
+                               nvidia,pins = "pu1";
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pu2 {
+                               nvidia,pins = "pu2";
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pu3 {
+                               nvidia,pins = "pu3";
+                               nvidia,function = "gmi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pu4 {
+                               nvidia,pins = "pu4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pu5 {
+                               nvidia,pins = "pu5";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pu6 {
+                               nvidia,pins = "pu6";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pv0 {
+                               nvidia,pins = "pv0";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pv1 {
+                               nvidia,pins = "pv1";
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       sdmmc3_cd_n_pv2 {
+                               nvidia,pins = "sdmmc3_cd_n_pv2";
+                               nvidia,function = "sdmmc3";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc1_wp_n_pv3 {
+                               nvidia,pins = "sdmmc1_wp_n_pv3";
+                               nvidia,function = "sdmmc1";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       ddc_scl_pv4 {
+                               nvidia,pins = "ddc_scl_pv4";
+                               nvidia,function = "i2c4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,rcv-sel = <TEGRA_PIN_DISABLE>;
+                       };
+                       ddc_sda_pv5 {
+                               nvidia,pins = "ddc_sda_pv5";
+                               nvidia,function = "i2c4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,rcv-sel = <TEGRA_PIN_DISABLE>;
+                       };
+                       gpio_w2_aud_pw2 {
+                               nvidia,pins = "gpio_w2_aud_pw2";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gpio_w3_aud_pw3 {
+                               nvidia,pins = "gpio_w3_aud_pw3";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       dap_mclk1_pw4 {
+                               nvidia,pins = "dap_mclk1_pw4";
+                               nvidia,function = "extperiph1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       clk2_out_pw5 {
+                               nvidia,pins = "clk2_out_pw5";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       uart3_txd_pw6 {
+                               nvidia,pins = "uart3_txd_pw6";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       uart3_rxd_pw7 {
+                               nvidia,pins = "uart3_rxd_pw7";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       dvfs_pwm_px0 {
+                               nvidia,pins = "dvfs_pwm_px0";
+                               nvidia,function = "cldvfs";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gpio_x1_aud_px1 {
+                               nvidia,pins = "gpio_x1_aud_px1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       dvfs_clk_px2 {
+                               nvidia,pins = "dvfs_clk_px2";
+                               nvidia,function = "cldvfs";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gpio_x3_aud_px3 {
+                               nvidia,pins = "gpio_x3_aud_px3";
+                               nvidia,function = "rsvd4";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gpio_x4_aud_px4 {
+                               nvidia,pins = "gpio_x4_aud_px4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       gpio_x5_aud_px5 {
+                               nvidia,pins = "gpio_x5_aud_px5";
+                               nvidia,function = "rsvd4";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gpio_x6_aud_px6 {
+                               nvidia,pins = "gpio_x6_aud_px6";
+                               nvidia,function = "gmi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gpio_x7_aud_px7 {
+                               nvidia,pins = "gpio_x7_aud_px7";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       ulpi_clk_py0 {
+                               nvidia,pins = "ulpi_clk_py0";
+                               nvidia,function = "spi1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       ulpi_dir_py1 {
+                               nvidia,pins = "ulpi_dir_py1";
+                               nvidia,function = "spi1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       ulpi_nxt_py2 {
+                               nvidia,pins = "ulpi_nxt_py2";
+                               nvidia,function = "spi1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       ulpi_stp_py3 {
+                               nvidia,pins = "ulpi_stp_py3";
+                               nvidia,function = "spi1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       sdmmc1_dat3_py4 {
+                               nvidia,pins = "sdmmc1_dat3_py4";
+                               nvidia,function = "sdmmc1";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc1_dat2_py5 {
+                               nvidia,pins = "sdmmc1_dat2_py5";
+                               nvidia,function = "sdmmc1";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc1_dat1_py6 {
+                               nvidia,pins = "sdmmc1_dat1_py6";
+                               nvidia,function = "sdmmc1";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc1_dat0_py7 {
+                               nvidia,pins = "sdmmc1_dat0_py7";
+                               nvidia,function = "sdmmc1";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc1_clk_pz0 {
+                               nvidia,pins = "sdmmc1_clk_pz0";
+                               nvidia,function = "sdmmc1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc1_cmd_pz1 {
+                               nvidia,pins = "sdmmc1_cmd_pz1";
+                               nvidia,function = "sdmmc1";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pwr_i2c_scl_pz6 {
+                               nvidia,pins = "pwr_i2c_scl_pz6";
+                               nvidia,function = "i2cpwr";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+                       };
+                       pwr_i2c_sda_pz7 {
+                               nvidia,pins = "pwr_i2c_sda_pz7";
+                               nvidia,function = "i2cpwr";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc4_dat0_paa0 {
+                               nvidia,pins = "sdmmc4_dat0_paa0";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc4_dat1_paa1 {
+                               nvidia,pins = "sdmmc4_dat1_paa1";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc4_dat2_paa2 {
+                               nvidia,pins = "sdmmc4_dat2_paa2";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc4_dat3_paa3 {
+                               nvidia,pins = "sdmmc4_dat3_paa3";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc4_dat4_paa4 {
+                               nvidia,pins = "sdmmc4_dat4_paa4";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc4_dat5_paa5 {
+                               nvidia,pins = "sdmmc4_dat5_paa5";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc4_dat6_paa6 {
+                               nvidia,pins = "sdmmc4_dat6_paa6";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc4_dat7_paa7 {
+                               nvidia,pins = "sdmmc4_dat7_paa7";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pbb0 {
+                               nvidia,pins = "pbb0";
+                               nvidia,function = "vgp6";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       cam_i2c_scl_pbb1 {
+                               nvidia,pins = "cam_i2c_scl_pbb1";
+                               nvidia,function = "rsvd3";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+                       };
+                       cam_i2c_sda_pbb2 {
+                               nvidia,pins = "cam_i2c_sda_pbb2";
+                               nvidia,function = "rsvd3";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+                       };
+                       pbb3 {
+                               nvidia,pins = "pbb3";
+                               nvidia,function = "vgp3";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pbb4 {
+                               nvidia,pins = "pbb4";
+                               nvidia,function = "vgp4";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pbb5 {
+                               nvidia,pins = "pbb5";
+                               nvidia,function = "rsvd3";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pbb6 {
+                               nvidia,pins = "pbb6";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pbb7 {
+                               nvidia,pins = "pbb7";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       cam_mclk_pcc0 {
+                               nvidia,pins = "cam_mclk_pcc0";
+                               nvidia,function = "vi";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pcc1 {
+                               nvidia,pins = "pcc1";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pcc2 {
+                               nvidia,pins = "pcc2";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       sdmmc4_clk_pcc4 {
+                               nvidia,pins = "sdmmc4_clk_pcc4";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       clk2_req_pcc5 {
+                               nvidia,pins = "clk2_req_pcc5";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pex_l0_rst_n_pdd1 {
+                               nvidia,pins = "pex_l0_rst_n_pdd1";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pex_l0_clkreq_n_pdd2 {
+                               nvidia,pins = "pex_l0_clkreq_n_pdd2";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pex_wake_n_pdd3 {
+                               nvidia,pins = "pex_wake_n_pdd3";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pex_l1_rst_n_pdd5 {
+                               nvidia,pins = "pex_l1_rst_n_pdd5";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pex_l1_clkreq_n_pdd6 {
+                               nvidia,pins = "pex_l1_clkreq_n_pdd6";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       clk3_out_pee0 {
+                               nvidia,pins = "clk3_out_pee0";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       clk3_req_pee1 {
+                               nvidia,pins = "clk3_req_pee1";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       dap_mclk1_req_pee2 {
+                               nvidia,pins = "dap_mclk1_req_pee2";
+                               nvidia,function = "rsvd4";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       hdmi_cec_pee3 {
+                               nvidia,pins = "hdmi_cec_pee3";
+                               nvidia,function = "cec";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc3_clk_lb_out_pee4 {
+                               nvidia,pins = "sdmmc3_clk_lb_out_pee4";
+                               nvidia,function = "sdmmc3";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       sdmmc3_clk_lb_in_pee5 {
+                               nvidia,pins = "sdmmc3_clk_lb_in_pee5";
+                               nvidia,function = "sdmmc3";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       dp_hpd_pff0 {
+                               nvidia,pins = "dp_hpd_pff0";
+                               nvidia,function = "dp";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       usb_vbus_en2_pff1 {
+                               nvidia,pins = "usb_vbus_en2_pff1";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+                       };
+                       pff2 {
+                               nvidia,pins = "pff2";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+                       };
+                       core_pwr_req {
+                               nvidia,pins = "core_pwr_req";
+                               nvidia,function = "pwron";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       cpu_pwr_req {
+                               nvidia,pins = "cpu_pwr_req";
+                               nvidia,function = "cpu";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pwr_int_n {
+                               nvidia,pins = "pwr_int_n";
+                               nvidia,function = "pmi";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       reset_out_n {
+                               nvidia,pins = "reset_out_n";
+                               nvidia,function = "reset_out_n";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       owr {
+                               nvidia,pins = "owr";
+                               nvidia,function = "rsvd2";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                               nvidia,rcv-sel = <TEGRA_PIN_DISABLE>;
+                       };
+                       clk_32k_in {
+                               nvidia,pins = "clk_32k_in";
+                               nvidia,function = "clk";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       jtag_rtck {
+                               nvidia,pins = "jtag_rtck";
+                               nvidia,function = "rtck";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/tegra124-nyan.dtsi b/arch/arm/boot/dts/tegra124-nyan.dtsi
new file mode 100644 (file)
index 0000000..a9aec23
--- /dev/null
@@ -0,0 +1,695 @@
+#include <dt-bindings/input/input.h>
+#include "tegra124.dtsi"
+
+/ {
+       aliases {
+               rtc0 = "/i2c@0,7000d000/pmic@40";
+               rtc1 = "/rtc@0,7000e000";
+               serial0 = &uarta;
+       };
+
+       memory {
+               reg = <0x0 0x80000000 0x0 0x80000000>;
+       };
+
+       host1x@0,50000000 {
+               hdmi@0,54280000 {
+                       status = "okay";
+
+                       vdd-supply = <&vdd_3v3_hdmi>;
+                       pll-supply = <&vdd_hdmi_pll>;
+                       hdmi-supply = <&vdd_5v0_hdmi>;
+
+                       nvidia,ddc-i2c-bus = <&hdmi_ddc>;
+                       nvidia,hpd-gpio =
+                               <&gpio TEGRA_GPIO(N, 7) GPIO_ACTIVE_HIGH>;
+               };
+
+               sor@0,54540000 {
+                       status = "okay";
+
+                       nvidia,dpaux = <&dpaux>;
+                       nvidia,panel = <&panel>;
+               };
+
+               dpaux@0,545c0000 {
+                       vdd-supply = <&vdd_3v3_panel>;
+                       status = "okay";
+               };
+       };
+
+       serial@0,70006000 {
+               /* Debug connector on the bottom of the board near SD card. */
+               status = "okay";
+       };
+
+       pwm@0,7000a000 {
+               status = "okay";
+       };
+
+       i2c@0,7000c000 {
+               status = "okay";
+               clock-frequency = <100000>;
+
+               acodec: audio-codec@10 {
+                       compatible = "maxim,max98090";
+                       reg = <0x10>;
+                       interrupt-parent = <&gpio>;
+                       interrupts = <TEGRA_GPIO(H, 4) GPIO_ACTIVE_HIGH>;
+               };
+
+               temperature-sensor@4c {
+                       compatible = "ti,tmp451";
+                       reg = <0x4c>;
+                       interrupt-parent = <&gpio>;
+                       interrupts = <TEGRA_GPIO(I, 6) IRQ_TYPE_LEVEL_LOW>;
+
+                       #thermal-sensor-cells = <1>;
+               };
+       };
+
+       i2c@0,7000c400 {
+               status = "okay";
+               clock-frequency = <100000>;
+
+               trackpad@15 {
+                       compatible = "elan,ekth3000";
+                       reg = <0x15>;
+                       interrupt-parent = <&gpio>;
+                       interrupts = <TEGRA_GPIO(W, 3) IRQ_TYPE_EDGE_FALLING>;
+                       wakeup-source;
+               };
+       };
+
+       i2c@0,7000c500 {
+               status = "okay";
+               clock-frequency = <400000>;
+
+               tpm@20 {
+                       compatible = "infineon,slb9645tt";
+                       reg = <0x20>;
+               };
+       };
+
+       hdmi_ddc: i2c@0,7000c700 {
+               status = "okay";
+               clock-frequency = <100000>;
+       };
+
+       i2c@0,7000d000 {
+               status = "okay";
+               clock-frequency = <400000>;
+
+               pmic: pmic@40 {
+                       compatible = "ams,as3722";
+                       reg = <0x40>;
+                       interrupts = <0 86 IRQ_TYPE_LEVEL_HIGH>;
+
+                       ams,system-power-controller;
+
+                       #interrupt-cells = <2>;
+                       interrupt-controller;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&as3722_default>;
+
+                       as3722_default: pinmux {
+                               gpio0 {
+                                       pins = "gpio0";
+                                       function = "gpio";
+                                       bias-pull-down;
+                               };
+
+                               gpio1 {
+                                       pins = "gpio1";
+                                       function = "gpio";
+                                       bias-pull-up;
+                               };
+
+                               gpio2_4_7 {
+                                       pins = "gpio2", "gpio4", "gpio7";
+                                       function = "gpio";
+                                       bias-pull-up;
+                               };
+
+                               gpio3_6 {
+                                       pins = "gpio3", "gpio6";
+                                       bias-high-impedance;
+                               };
+
+                               gpio5 {
+                                       pins = "gpio5";
+                                       function = "clk32k-out";
+                                       bias-pull-down;
+                               };
+                       };
+
+                       regulators {
+                               vsup-sd2-supply = <&vdd_5v0_sys>;
+                               vsup-sd3-supply = <&vdd_5v0_sys>;
+                               vsup-sd4-supply = <&vdd_5v0_sys>;
+                               vsup-sd5-supply = <&vdd_5v0_sys>;
+                               vin-ldo0-supply = <&vdd_1v35_lp0>;
+                               vin-ldo1-6-supply = <&vdd_3v3_run>;
+                               vin-ldo2-5-7-supply = <&vddio_1v8>;
+                               vin-ldo3-4-supply = <&vdd_3v3_sys>;
+                               vin-ldo9-10-supply = <&vdd_5v0_sys>;
+                               vin-ldo11-supply = <&vdd_3v3_run>;
+
+                               sd0 {
+                                       regulator-name = "+VDD_CPU_AP";
+                                       regulator-min-microvolt = <700000>;
+                                       regulator-max-microvolt = <1350000>;
+                                       regulator-min-microamp = <3500000>;
+                                       regulator-max-microamp = <3500000>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+                                       ams,ext-control = <2>;
+                               };
+
+                               sd1 {
+                                       regulator-name = "+VDD_CORE";
+                                       regulator-min-microvolt = <700000>;
+                                       regulator-max-microvolt = <1350000>;
+                                       regulator-min-microamp = <2500000>;
+                                       regulator-max-microamp = <4000000>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+                                       ams,ext-control = <1>;
+                               };
+
+                               vdd_1v35_lp0: sd2 {
+                                       regulator-name = "+1.35V_LP0(sd2)";
+                                       regulator-min-microvolt = <1350000>;
+                                       regulator-max-microvolt = <1350000>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+                               };
+
+                               sd3 {
+                                       regulator-name = "+1.35V_LP0(sd3)";
+                                       regulator-min-microvolt = <1350000>;
+                                       regulator-max-microvolt = <1350000>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+                               };
+
+                               vdd_1v05_run: sd4 {
+                                       regulator-name = "+1.05V_RUN";
+                                       regulator-min-microvolt = <1050000>;
+                                       regulator-max-microvolt = <1050000>;
+                               };
+
+                               vddio_1v8: sd5 {
+                                       regulator-name = "+1.8V_VDDIO";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                                       regulator-always-on;
+                               };
+
+                               sd6 {
+                                       regulator-name = "+VDD_GPU_AP";
+                                       regulator-min-microvolt = <650000>;
+                                       regulator-max-microvolt = <1200000>;
+                                       regulator-min-microamp = <3500000>;
+                                       regulator-max-microamp = <3500000>;
+                                       regulator-boot-on;
+                                       regulator-always-on;
+                               };
+
+                               ldo0 {
+                                       regulator-name = "+1.05V_RUN_AVDD";
+                                       regulator-min-microvolt = <1050000>;
+                                       regulator-max-microvolt = <1050000>;
+                                       regulator-boot-on;
+                                       regulator-always-on;
+                                       ams,ext-control = <1>;
+                               };
+
+                               ldo1 {
+                                       regulator-name = "+1.8V_RUN_CAM";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                               };
+
+                               ldo2 {
+                                       regulator-name = "+1.2V_GEN_AVDD";
+                                       regulator-min-microvolt = <1200000>;
+                                       regulator-max-microvolt = <1200000>;
+                                       regulator-boot-on;
+                                       regulator-always-on;
+                               };
+
+                               ldo3 {
+                                       regulator-name = "+1.00V_LP0_VDD_RTC";
+                                       regulator-min-microvolt = <1000000>;
+                                       regulator-max-microvolt = <1000000>;
+                                       regulator-boot-on;
+                                       regulator-always-on;
+                                       ams,enable-tracking;
+                               };
+
+                               vdd_run_cam: ldo4 {
+                                       regulator-name = "+3.3V_RUN_CAM";
+                                       regulator-min-microvolt = <2800000>;
+                                       regulator-max-microvolt = <2800000>;
+                               };
+
+                               ldo5 {
+                                       regulator-name = "+1.2V_RUN_CAM_FRONT";
+                                       regulator-min-microvolt = <1200000>;
+                                       regulator-max-microvolt = <1200000>;
+                               };
+
+                               vddio_sdmmc3: ldo6 {
+                                       regulator-name = "+VDDIO_SDMMC3";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <3300000>;
+                               };
+
+                               ldo7 {
+                                       regulator-name = "+1.05V_RUN_CAM_REAR";
+                                       regulator-min-microvolt = <1050000>;
+                                       regulator-max-microvolt = <1050000>;
+                               };
+
+                               ldo9 {
+                                       regulator-name = "+2.8V_RUN_TOUCH";
+                                       regulator-min-microvolt = <2800000>;
+                                       regulator-max-microvolt = <2800000>;
+                               };
+
+                               ldo10 {
+                                       regulator-name = "+2.8V_RUN_CAM_AF";
+                                       regulator-min-microvolt = <2800000>;
+                                       regulator-max-microvolt = <2800000>;
+                               };
+
+                               ldo11 {
+                                       regulator-name = "+1.8V_RUN_VPP_FUSE";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                               };
+                       };
+               };
+       };
+
+       spi@0,7000d400 {
+               status = "okay";
+
+               cros_ec: cros-ec@0 {
+                       compatible = "google,cros-ec-spi";
+                       spi-max-frequency = <3000000>;
+                       interrupt-parent = <&gpio>;
+                       interrupts = <TEGRA_GPIO(C, 7) IRQ_TYPE_LEVEL_LOW>;
+                       reg = <0>;
+
+                       google,cros-ec-spi-msg-delay = <2000>;
+
+                       i2c-tunnel {
+                               compatible = "google,cros-ec-i2c-tunnel";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               google,remote-bus = <0>;
+
+                               charger: bq24735@9 {
+                                       compatible = "ti,bq24735";
+                                       reg = <0x9>;
+                                       interrupt-parent = <&gpio>;
+                                       interrupts = <TEGRA_GPIO(J, 0)
+                                                       GPIO_ACTIVE_HIGH>;
+                                       ti,ac-detect-gpios = <&gpio
+                                                       TEGRA_GPIO(J, 0)
+                                                       GPIO_ACTIVE_HIGH>;
+                               };
+
+                               battery: sbs-battery@b {
+                                       compatible = "sbs,sbs-battery";
+                                       reg = <0xb>;
+                                       sbs,i2c-retry-count = <2>;
+                                       sbs,poll-retry-count = <10>;
+                                       power-supplies = <&charger>;
+                               };
+                       };
+               };
+       };
+
+       spi@0,7000da00 {
+               status = "okay";
+               spi-max-frequency = <25000000>;
+
+               flash@0 {
+                       compatible = "winbond,w25q32dw";
+                       spi-max-frequency = <25000000>;
+                       reg = <0>;
+               };
+       };
+
+       pmc@0,7000e400 {
+               nvidia,invert-interrupt;
+               nvidia,suspend-mode = <0>;
+               nvidia,cpu-pwr-good-time = <500>;
+               nvidia,cpu-pwr-off-time = <300>;
+               nvidia,core-pwr-good-time = <641 3845>;
+               nvidia,core-pwr-off-time = <61036>;
+               nvidia,core-power-req-active-high;
+               nvidia,sys-clock-req-active-high;
+       };
+
+       hda@0,70030000 {
+               status = "okay";
+       };
+
+       sdhci0_pwrseq: sdhci0_pwrseq {
+               compatible = "mmc-pwrseq-simple";
+
+               reset-gpios = <&gpio TEGRA_GPIO(X, 7) GPIO_ACTIVE_LOW>;
+       };
+
+       sdhci@0,700b0000 { /* WiFi/BT on this bus */
+               status = "okay";
+               bus-width = <4>;
+               no-1-8-v;
+               non-removable;
+               mmc-pwrseq = <&sdhci0_pwrseq>;
+               vmmc-supply = <&vdd_3v3_lp0>;
+               vqmmc-supply = <&vddio_1v8>;
+               keep-power-in-suspend;
+       };
+
+       sdhci@0,700b0400 { /* SD Card on this bus */
+               status = "okay";
+               cd-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_LOW>;
+               power-gpios = <&gpio TEGRA_GPIO(R, 0) GPIO_ACTIVE_HIGH>;
+               bus-width = <4>;
+               no-1-8-v;
+               vqmmc-supply = <&vddio_sdmmc3>;
+       };
+
+       sdhci@0,700b0600 { /* eMMC on this bus */
+               status = "okay";
+               bus-width = <8>;
+               no-1-8-v;
+               non-removable;
+       };
+
+       ahub@0,70300000 {
+               i2s@0,70301100 {
+                       status = "okay";
+               };
+       };
+
+       usb@0,7d000000 { /* Rear external USB port. */
+               status = "okay";
+       };
+
+       usb-phy@0,7d000000 {
+               status = "okay";
+               vbus-supply = <&vdd_usb1_vbus>;
+       };
+
+       usb@0,7d004000 { /* Internal webcam. */
+               status = "okay";
+       };
+
+       usb-phy@0,7d004000 {
+               status = "okay";
+               vbus-supply = <&vdd_run_cam>;
+       };
+
+       usb@0,7d008000 { /* Left external USB port. */
+               status = "okay";
+       };
+
+       usb-phy@0,7d008000 {
+               status = "okay";
+               vbus-supply = <&vdd_usb3_vbus>;
+       };
+
+       backlight: backlight {
+               compatible = "pwm-backlight";
+
+               enable-gpios = <&gpio TEGRA_GPIO(H, 2) GPIO_ACTIVE_HIGH>;
+               power-supply = <&vdd_led>;
+               pwms = <&pwm 1 1000000>;
+
+               default-brightness-level = <224>;
+               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 101 102 103
+                        104 105 106 107 108 109 110 111
+                        112 113 114 115 116 117 118 119
+                        120 121 122 123 124 125 126 127
+                        128 129 130 131 132 133 134 135
+                        136 137 138 139 140 141 142 143
+                        144 145 146 147 148 149 150 151
+                        152 153 154 155 156 157 158 159
+                        160 161 162 163 164 165 166 167
+                        168 169 170 171 172 173 174 175
+                        176 177 178 179 180 181 182 183
+                        184 185 186 187 188 189 190 191
+                        192 193 194 195 196 197 198 199
+                        200 201 202 203 204 205 206 207
+                        208 209 210 211 212 213 214 215
+                        216 217 218 219 220 221 222 223
+                        224 225 226 227 228 229 230 231
+                        232 233 234 235 236 237 238 239
+                        240 241 242 243 244 245 246 247
+                        248 249 250 251 252 253 254 255
+                        256>;
+       };
+
+       clocks {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               clk32k_in: clock@0 {
+                       compatible = "fixed-clock";
+                       reg = <0>;
+                       #clock-cells = <0>;
+                       clock-frequency = <32768>;
+               };
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+
+               lid {
+                       label = "Lid";
+                       gpios = <&gpio TEGRA_GPIO(R, 4) GPIO_ACTIVE_LOW>;
+                       linux,input-type = <5>;
+                       linux,code = <KEY_RESERVED>;
+                       debounce-interval = <1>;
+                       gpio-key,wakeup;
+               };
+
+               power {
+                       label = "Power";
+                       gpios = <&gpio TEGRA_GPIO(Q, 0) GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_POWER>;
+                       debounce-interval = <30>;
+                       gpio-key,wakeup;
+               };
+       };
+
+       regulators {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               vdd_mux: regulator@0 {
+                       compatible = "regulator-fixed";
+                       reg = <0>;
+                       regulator-name = "+VDD_MUX";
+                       regulator-min-microvolt = <12000000>;
+                       regulator-max-microvolt = <12000000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+               };
+
+               vdd_5v0_sys: regulator@1 {
+                       compatible = "regulator-fixed";
+                       reg = <1>;
+                       regulator-name = "+5V_SYS";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       vin-supply = <&vdd_mux>;
+               };
+
+               vdd_3v3_sys: regulator@2 {
+                       compatible = "regulator-fixed";
+                       reg = <2>;
+                       regulator-name = "+3.3V_SYS";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       vin-supply = <&vdd_mux>;
+               };
+
+               vdd_3v3_run: regulator@3 {
+                       compatible = "regulator-fixed";
+                       reg = <3>;
+                       regulator-name = "+3.3V_RUN";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       gpio = <&pmic 1 GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+                       vin-supply = <&vdd_3v3_sys>;
+               };
+
+               vdd_3v3_hdmi: regulator@4 {
+                       compatible = "regulator-fixed";
+                       reg = <4>;
+                       regulator-name = "+3.3V_AVDD_HDMI_AP_GATED";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       vin-supply = <&vdd_3v3_run>;
+               };
+
+               vdd_led: regulator@5 {
+                       compatible = "regulator-fixed";
+                       reg = <5>;
+                       regulator-name = "+VDD_LED";
+                       gpio = <&gpio TEGRA_GPIO(P, 2) GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+                       vin-supply = <&vdd_mux>;
+               };
+
+               vdd_5v0_ts: regulator@6 {
+                       compatible = "regulator-fixed";
+                       reg = <6>;
+                       regulator-name = "+5V_VDD_TS_SW";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       regulator-boot-on;
+                       gpio = <&gpio TEGRA_GPIO(K, 1) GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+                       vin-supply = <&vdd_5v0_sys>;
+               };
+
+               vdd_usb1_vbus: regulator@7 {
+                       compatible = "regulator-fixed";
+                       reg = <7>;
+                       regulator-name = "+5V_USB_HS";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&gpio TEGRA_GPIO(N, 4) GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+                       gpio-open-drain;
+                       vin-supply = <&vdd_5v0_sys>;
+               };
+
+               vdd_usb3_vbus: regulator@8 {
+                       compatible = "regulator-fixed";
+                       reg = <8>;
+                       regulator-name = "+5V_USB_SS";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&gpio TEGRA_GPIO(N, 5) GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+                       gpio-open-drain;
+                       vin-supply = <&vdd_5v0_sys>;
+               };
+
+               vdd_3v3_panel: regulator@9 {
+                       compatible = "regulator-fixed";
+                       reg = <9>;
+                       regulator-name = "+3.3V_PANEL";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       gpio = <&pmic 4 GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+                       vin-supply = <&vdd_3v3_run>;
+               };
+
+               vdd_3v3_lp0: regulator@10 {
+                       compatible = "regulator-fixed";
+                       reg = <10>;
+                       regulator-name = "+3.3V_LP0";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       /*
+                        * TODO: find a way to wire this up with the USB EHCI
+                        * controllers so that it can be enabled on demand.
+                        */
+                       regulator-always-on;
+                       gpio = <&pmic 2 GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+                       vin-supply = <&vdd_3v3_sys>;
+               };
+
+               vdd_hdmi_pll: regulator@11 {
+                       compatible = "regulator-fixed";
+                       reg = <11>;
+                       regulator-name = "+1.05V_RUN_AVDD_HDMI_PLL";
+                       regulator-min-microvolt = <1050000>;
+                       regulator-max-microvolt = <1050000>;
+                       gpio = <&gpio TEGRA_GPIO(H, 7) GPIO_ACTIVE_LOW>;
+                       vin-supply = <&vdd_1v05_run>;
+               };
+
+               vdd_5v0_hdmi: regulator@12 {
+                       compatible = "regulator-fixed";
+                       reg = <12>;
+                       regulator-name = "+5V_HDMI_CON";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&gpio TEGRA_GPIO(K, 6) GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+                       vin-supply = <&vdd_5v0_sys>;
+               };
+       };
+
+       sound {
+               nvidia,audio-routing =
+                       "Headphones", "HPR",
+                       "Headphones", "HPL",
+                       "Speakers", "SPKR",
+                       "Speakers", "SPKL",
+                       "Mic Jack", "MICBIAS",
+                       "DMICL", "Int Mic",
+                       "DMICR", "Int Mic",
+                       "IN34", "Mic Jack";
+
+               nvidia,i2s-controller = <&tegra_i2s1>;
+               nvidia,audio-codec = <&acodec>;
+
+               clocks = <&tegra_car TEGRA124_CLK_PLL_A>,
+                        <&tegra_car TEGRA124_CLK_PLL_A_OUT0>,
+                        <&tegra_car TEGRA124_CLK_EXTERN1>;
+               clock-names = "pll_a", "pll_a_out0", "mclk";
+
+               nvidia,hp-det-gpios = <&gpio TEGRA_GPIO(I, 7) GPIO_ACTIVE_HIGH>;
+               nvidia,mic-det-gpios =
+                               <&gpio TEGRA_GPIO(R, 7) GPIO_ACTIVE_HIGH>;
+       };
+
+       gpio-restart {
+               compatible = "gpio-restart";
+               gpios = <&gpio TEGRA_GPIO(I, 5) GPIO_ACTIVE_LOW>;
+               priority = <200>;
+       };
+};
+
+#include "cros-ec-keyboard.dtsi"
index db85695aa7aa715713e0fa387e92de887565e233..cf01c818b8ea41999f231f07211aec46a86e505c 100644 (file)
                reg = <0x0 0x60006000 0x0 0x1000>;
                #clock-cells = <1>;
                #reset-cells = <1>;
+               nvidia,external-memory-controller = <&emc>;
        };
 
        flow-controller@0,60007000 {
                reg = <0x0 0x60007000 0x0 0x1000>;
        };
 
+       actmon@0,6000c800 {
+               compatible = "nvidia,tegra124-actmon";
+               reg = <0x0 0x6000c800 0x0 0x400>;
+               interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&tegra_car TEGRA124_CLK_ACTMON>,
+                        <&tegra_car TEGRA124_CLK_EMC>;
+               clock-names = "actmon", "emc";
+               resets = <&tegra_car 119>;
+               reset-names = "actmon";
+       };
+
        gpio: gpio@0,6000d000 {
                compatible = "nvidia,tegra124-gpio", "nvidia,tegra30-gpio";
                reg = <0x0 0x6000d000 0x0 0x1000>;
                #iommu-cells = <1>;
        };
 
+       emc: emc@0,7001b000 {
+               compatible = "nvidia,tegra124-emc";
+               reg = <0x0 0x7001b000 0x0 0x1000>;
+
+               nvidia,memory-controller = <&mc>;
+       };
+
        sata@0,70020000 {
                compatible = "nvidia,tegra124-ahci";
 
index 6b157eeabcc5c9b07009c4d91a291122b3732887..3dede39344461a26043a93c12914c32d962e4f64 100644 (file)
                pinctrl-0 = <&state_default>;
 
                state_default: pinmux {
+                       clk_32k_out_pa0 {
+                               nvidia,pins = "clk_32k_out_pa0";
+                               nvidia,function = "blink";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       uart3_cts_n_pa1 {
+                               nvidia,pins = "uart3_cts_n_pa1";
+                               nvidia,function = "uartc";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       dap2_fs_pa2 {
+                               nvidia,pins = "dap2_fs_pa2";
+                               nvidia,function = "i2s1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       dap2_sclk_pa3 {
+                               nvidia,pins = "dap2_sclk_pa3";
+                               nvidia,function = "i2s1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       dap2_din_pa4 {
+                               nvidia,pins = "dap2_din_pa4";
+                               nvidia,function = "i2s1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       dap2_dout_pa5 {
+                               nvidia,pins = "dap2_dout_pa5";
+                               nvidia,function = "i2s1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc3_clk_pa6 {
+                               nvidia,pins = "sdmmc3_clk_pa6";
+                               nvidia,function = "sdmmc3";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc3_cmd_pa7 {
+                               nvidia,pins = "sdmmc3_cmd_pa7";
+                               nvidia,function = "sdmmc3";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       gmi_a17_pb0 {
+                               nvidia,pins = "gmi_a17_pb0";
+                               nvidia,function = "spi4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       gmi_a18_pb1 {
+                               nvidia,pins = "gmi_a18_pb1";
+                               nvidia,function = "spi4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_pwr0_pb2 {
+                               nvidia,pins = "lcd_pwr0_pb2";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_pclk_pb3 {
+                               nvidia,pins = "lcd_pclk_pb3";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc3_dat3_pb4 {
+                               nvidia,pins = "sdmmc3_dat3_pb4";
+                               nvidia,function = "sdmmc3";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc3_dat2_pb5 {
+                               nvidia,pins = "sdmmc3_dat2_pb5";
+                               nvidia,function = "sdmmc3";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc3_dat1_pb6 {
+                               nvidia,pins = "sdmmc3_dat1_pb6";
+                               nvidia,function = "sdmmc3";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc3_dat0_pb7 {
+                               nvidia,pins = "sdmmc3_dat0_pb7";
+                               nvidia,function = "sdmmc3";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       uart3_rts_n_pc0 {
+                               nvidia,pins = "uart3_rts_n_pc0";
+                               nvidia,function = "uartc";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       lcd_pwr1_pc1 {
+                               nvidia,pins = "lcd_pwr1_pc1";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       uart2_txd_pc2 {
+                               nvidia,pins = "uart2_txd_pc2";
+                               nvidia,function = "uartb";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       uart2_rxd_pc3 {
+                               nvidia,pins = "uart2_rxd_pc3";
+                               nvidia,function = "uartb";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       gen1_i2c_scl_pc4 {
+                               nvidia,pins = "gen1_i2c_scl_pc4";
+                               nvidia,function = "i2c1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+                       };
+                       gen1_i2c_sda_pc5 {
+                               nvidia,pins = "gen1_i2c_sda_pc5";
+                               nvidia,function = "i2c1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_pwr2_pc6 {
+                               nvidia,pins = "lcd_pwr2_pc6";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       gmi_wp_n_pc7 {
+                               nvidia,pins = "gmi_wp_n_pc7";
+                               nvidia,function = "gmi";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc3_dat5_pd0 {
+                               nvidia,pins = "sdmmc3_dat5_pd0";
+                               nvidia,function = "sdmmc3";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc3_dat4_pd1 {
+                               nvidia,pins = "sdmmc3_dat4_pd1";
+                               nvidia,function = "sdmmc3";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_dc1_pd2 {
+                               nvidia,pins = "lcd_dc1_pd2";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc3_dat6_pd3 {
+                               nvidia,pins = "sdmmc3_dat6_pd3";
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc3_dat7_pd4 {
+                               nvidia,pins = "sdmmc3_dat7_pd4";
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       vi_d1_pd5 {
+                               nvidia,pins = "vi_d1_pd5";
+                               nvidia,function = "sdmmc2";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       vi_vsync_pd6 {
+                               nvidia,pins = "vi_vsync_pd6";
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       vi_hsync_pd7 {
+                               nvidia,pins = "vi_hsync_pd7";
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_d0_pe0 {
+                               nvidia,pins = "lcd_d0_pe0";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_d1_pe1 {
+                               nvidia,pins = "lcd_d1_pe1";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_d2_pe2 {
+                               nvidia,pins = "lcd_d2_pe2";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_d3_pe3 {
+                               nvidia,pins = "lcd_d3_pe3";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_d4_pe4 {
+                               nvidia,pins = "lcd_d4_pe4";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_d5_pe5 {
+                               nvidia,pins = "lcd_d5_pe5";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_d6_pe6 {
+                               nvidia,pins = "lcd_d6_pe6";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_d7_pe7 {
+                               nvidia,pins = "lcd_d7_pe7";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_d8_pf0 {
+                               nvidia,pins = "lcd_d8_pf0";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_d9_pf1 {
+                               nvidia,pins = "lcd_d9_pf1";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_d10_pf2 {
+                               nvidia,pins = "lcd_d10_pf2";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_d11_pf3 {
+                               nvidia,pins = "lcd_d11_pf3";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_d12_pf4 {
+                               nvidia,pins = "lcd_d12_pf4";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_d13_pf5 {
+                               nvidia,pins = "lcd_d13_pf5";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_d14_pf6 {
+                               nvidia,pins = "lcd_d14_pf6";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_d15_pf7 {
+                               nvidia,pins = "lcd_d15_pf7";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       gmi_ad0_pg0 {
+                               nvidia,pins = "gmi_ad0_pg0";
+                               nvidia,function = "nand";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gmi_ad1_pg1 {
+                               nvidia,pins = "gmi_ad1_pg1";
+                               nvidia,function = "nand";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gmi_ad2_pg2 {
+                               nvidia,pins = "gmi_ad2_pg2";
+                               nvidia,function = "nand";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gmi_ad3_pg3 {
+                               nvidia,pins = "gmi_ad3_pg3";
+                               nvidia,function = "nand";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gmi_ad4_pg4 {
+                               nvidia,pins = "gmi_ad4_pg4";
+                               nvidia,function = "nand";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gmi_ad5_pg5 {
+                               nvidia,pins = "gmi_ad5_pg5";
+                               nvidia,function = "nand";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gmi_ad6_pg6 {
+                               nvidia,pins = "gmi_ad6_pg6";
+                               nvidia,function = "nand";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gmi_ad7_pg7 {
+                               nvidia,pins = "gmi_ad7_pg7";
+                               nvidia,function = "nand";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gmi_ad8_ph0 {
+                               nvidia,pins = "gmi_ad8_ph0";
+                               nvidia,function = "pwm0";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gmi_ad9_ph1 {
+                               nvidia,pins = "gmi_ad9_ph1";
+                               nvidia,function = "pwm1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gmi_ad10_ph2 {
+                               nvidia,pins = "gmi_ad10_ph2";
+                               nvidia,function = "nand";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gmi_ad11_ph3 {
+                               nvidia,pins = "gmi_ad11_ph3";
+                               nvidia,function = "nand";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gmi_ad12_ph4 {
+                               nvidia,pins = "gmi_ad12_ph4";
+                               nvidia,function = "nand";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       gmi_ad13_ph5 {
+                               nvidia,pins = "gmi_ad13_ph5";
+                               nvidia,function = "nand";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       gmi_ad14_ph6 {
+                               nvidia,pins = "gmi_ad14_ph6";
+                               nvidia,function = "nand";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gmi_wr_n_pi0 {
+                               nvidia,pins = "gmi_wr_n_pi0";
+                               nvidia,function = "nand";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gmi_oe_n_pi1 {
+                               nvidia,pins = "gmi_oe_n_pi1";
+                               nvidia,function = "nand";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gmi_dqs_pi2 {
+                               nvidia,pins = "gmi_dqs_pi2";
+                               nvidia,function = "nand";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gmi_iordy_pi5 {
+                               nvidia,pins = "gmi_iordy_pi5";
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       gmi_cs7_n_pi6 {
+                               nvidia,pins = "gmi_cs7_n_pi6";
+                               nvidia,function = "nand";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       gmi_wait_pi7 {
+                               nvidia,pins = "gmi_wait_pi7";
+                               nvidia,function = "nand";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       lcd_de_pj1 {
+                               nvidia,pins = "lcd_de_pj1";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_hsync_pj3 {
+                               nvidia,pins = "lcd_hsync_pj3";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_vsync_pj4 {
+                               nvidia,pins = "lcd_vsync_pj4";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       uart2_cts_n_pj5 {
+                               nvidia,pins = "uart2_cts_n_pj5";
+                               nvidia,function = "uartb";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       uart2_rts_n_pj6 {
+                               nvidia,pins = "uart2_rts_n_pj6";
+                               nvidia,function = "uartb";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gmi_a16_pj7 {
+                               nvidia,pins = "gmi_a16_pj7";
+                               nvidia,function = "spi4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       gmi_adv_n_pk0 {
+                               nvidia,pins = "gmi_adv_n_pk0";
+                               nvidia,function = "nand";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gmi_clk_pk1 {
+                               nvidia,pins = "gmi_clk_pk1";
+                               nvidia,function = "nand";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       gmi_cs2_n_pk3 {
+                               nvidia,pins = "gmi_cs2_n_pk3";
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       gmi_cs3_n_pk4 {
+                               nvidia,pins = "gmi_cs3_n_pk4";
+                               nvidia,function = "nand";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       spdif_out_pk5 {
+                               nvidia,pins = "spdif_out_pk5";
+                               nvidia,function = "spdif";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       spdif_in_pk6 {
+                               nvidia,pins = "spdif_in_pk6";
+                               nvidia,function = "spdif";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       gmi_a19_pk7 {
+                               nvidia,pins = "gmi_a19_pk7";
+                               nvidia,function = "spi4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       vi_d2_pl0 {
+                               nvidia,pins = "vi_d2_pl0";
+                               nvidia,function = "sdmmc2";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       vi_d3_pl1 {
+                               nvidia,pins = "vi_d3_pl1";
+                               nvidia,function = "sdmmc2";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       vi_d4_pl2 {
+                               nvidia,pins = "vi_d4_pl2";
+                               nvidia,function = "vi";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       vi_d5_pl3 {
+                               nvidia,pins = "vi_d5_pl3";
+                               nvidia,function = "sdmmc2";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       vi_d6_pl4 {
+                               nvidia,pins = "vi_d6_pl4";
+                               nvidia,function = "vi";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       vi_d7_pl5 {
+                               nvidia,pins = "vi_d7_pl5";
+                               nvidia,function = "sdmmc2";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       vi_d8_pl6 {
+                               nvidia,pins = "vi_d8_pl6";
+                               nvidia,function = "sdmmc2";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       vi_d9_pl7 {
+                               nvidia,pins = "vi_d9_pl7";
+                               nvidia,function = "sdmmc2";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_d16_pm0 {
+                               nvidia,pins = "lcd_d16_pm0";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_d17_pm1 {
+                               nvidia,pins = "lcd_d17_pm1";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_d18_pm2 {
+                               nvidia,pins = "lcd_d18_pm2";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_d19_pm3 {
+                               nvidia,pins = "lcd_d19_pm3";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_d20_pm4 {
+                               nvidia,pins = "lcd_d20_pm4";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_d21_pm5 {
+                               nvidia,pins = "lcd_d21_pm5";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_d22_pm6 {
+                               nvidia,pins = "lcd_d22_pm6";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_d23_pm7 {
+                               nvidia,pins = "lcd_d23_pm7";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       dap1_fs_pn0 {
+                               nvidia,pins = "dap1_fs_pn0";
+                               nvidia,function = "i2s0";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       dap1_din_pn1 {
+                               nvidia,pins = "dap1_din_pn1";
+                               nvidia,function = "i2s0";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       dap1_dout_pn2 {
+                               nvidia,pins = "dap1_dout_pn2";
+                               nvidia,function = "i2s0";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       dap1_sclk_pn3 {
+                               nvidia,pins = "dap1_sclk_pn3";
+                               nvidia,function = "i2s0";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_cs0_n_pn4 {
+                               nvidia,pins = "lcd_cs0_n_pn4";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_sdout_pn5 {
+                               nvidia,pins = "lcd_sdout_pn5";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_dc0_pn6 {
+                               nvidia,pins = "lcd_dc0_pn6";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       hdmi_int_pn7 {
+                               nvidia,pins = "hdmi_int_pn7";
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       ulpi_data7_po0 {
+                               nvidia,pins = "ulpi_data7_po0";
+                               nvidia,function = "uarta";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       ulpi_data0_po1 {
+                               nvidia,pins = "ulpi_data0_po1";
+                               nvidia,function = "uarta";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       ulpi_data1_po2 {
+                               nvidia,pins = "ulpi_data1_po2";
+                               nvidia,function = "uarta";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       ulpi_data2_po3 {
+                               nvidia,pins = "ulpi_data2_po3";
+                               nvidia,function = "uarta";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       ulpi_data3_po4 {
+                               nvidia,pins = "ulpi_data3_po4";
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       ulpi_data4_po5 {
+                               nvidia,pins = "ulpi_data4_po5";
+                               nvidia,function = "uarta";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       ulpi_data5_po6 {
+                               nvidia,pins = "ulpi_data5_po6";
+                               nvidia,function = "uarta";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       ulpi_data6_po7 {
+                               nvidia,pins = "ulpi_data6_po7";
+                               nvidia,function = "uarta";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       dap3_fs_pp0 {
+                               nvidia,pins = "dap3_fs_pp0";
+                               nvidia,function = "i2s2";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       dap3_din_pp1 {
+                               nvidia,pins = "dap3_din_pp1";
+                               nvidia,function = "i2s2";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       dap3_dout_pp2 {
+                               nvidia,pins = "dap3_dout_pp2";
+                               nvidia,function = "i2s2";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       dap3_sclk_pp3 {
+                               nvidia,pins = "dap3_sclk_pp3";
+                               nvidia,function = "i2s2";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       dap4_fs_pp4 {
+                               nvidia,pins = "dap4_fs_pp4";
+                               nvidia,function = "i2s3";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       dap4_din_pp5 {
+                               nvidia,pins = "dap4_din_pp5";
+                               nvidia,function = "i2s3";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       dap4_dout_pp6 {
+                               nvidia,pins = "dap4_dout_pp6";
+                               nvidia,function = "i2s3";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       dap4_sclk_pp7 {
+                               nvidia,pins = "dap4_sclk_pp7";
+                               nvidia,function = "i2s3";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_col0_pq0 {
+                               nvidia,pins = "kb_col0_pq0";
+                               nvidia,function = "kbc";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_col1_pq1 {
+                               nvidia,pins = "kb_col1_pq1";
+                               nvidia,function = "kbc";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_col2_pq2 {
+                               nvidia,pins = "kb_col2_pq2";
+                               nvidia,function = "kbc";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_col3_pq3 {
+                               nvidia,pins = "kb_col3_pq3";
+                               nvidia,function = "kbc";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_col4_pq4 {
+                               nvidia,pins = "kb_col4_pq4";
+                               nvidia,function = "kbc";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_col5_pq5 {
+                               nvidia,pins = "kb_col5_pq5";
+                               nvidia,function = "kbc";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_col6_pq6 {
+                               nvidia,pins = "kb_col6_pq6";
+                               nvidia,function = "kbc";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_col7_pq7 {
+                               nvidia,pins = "kb_col7_pq7";
+                               nvidia,function = "kbc";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_row0_pr0 {
+                               nvidia,pins = "kb_row0_pr0";
+                               nvidia,function = "kbc";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_row1_pr1 {
+                               nvidia,pins = "kb_row1_pr1";
+                               nvidia,function = "kbc";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_row2_pr2 {
+                               nvidia,pins = "kb_row2_pr2";
+                               nvidia,function = "kbc";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_row3_pr3 {
+                               nvidia,pins = "kb_row3_pr3";
+                               nvidia,function = "kbc";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_row4_pr4 {
+                               nvidia,pins = "kb_row4_pr4";
+                               nvidia,function = "kbc";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_row5_pr5 {
+                               nvidia,pins = "kb_row5_pr5";
+                               nvidia,function = "kbc";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_row6_pr6 {
+                               nvidia,pins = "kb_row6_pr6";
+                               nvidia,function = "kbc";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_row7_pr7 {
+                               nvidia,pins = "kb_row7_pr7";
+                               nvidia,function = "kbc";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_row8_ps0 {
+                               nvidia,pins = "kb_row8_ps0";
+                               nvidia,function = "kbc";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_row9_ps1 {
+                               nvidia,pins = "kb_row9_ps1";
+                               nvidia,function = "kbc";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_row10_ps2 {
+                               nvidia,pins = "kb_row10_ps2";
+                               nvidia,function = "kbc";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_row11_ps3 {
+                               nvidia,pins = "kb_row11_ps3";
+                               nvidia,function = "kbc";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_row12_ps4 {
+                               nvidia,pins = "kb_row12_ps4";
+                               nvidia,function = "kbc";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_row13_ps5 {
+                               nvidia,pins = "kb_row13_ps5";
+                               nvidia,function = "kbc";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_row14_ps6 {
+                               nvidia,pins = "kb_row14_ps6";
+                               nvidia,function = "kbc";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       kb_row15_ps7 {
+                               nvidia,pins = "kb_row15_ps7";
+                               nvidia,function = "kbc";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       vi_pclk_pt0 {
+                               nvidia,pins = "vi_pclk_pt0";
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       vi_mclk_pt1 {
+                               nvidia,pins = "vi_mclk_pt1";
+                               nvidia,function = "vi";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       vi_d10_pt2 {
+                               nvidia,pins = "vi_d10_pt2";
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       vi_d11_pt3 {
+                               nvidia,pins = "vi_d11_pt3";
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       vi_d0_pt4 {
+                               nvidia,pins = "vi_d0_pt4";
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       gen2_i2c_scl_pt5 {
+                               nvidia,pins = "gen2_i2c_scl_pt5";
+                               nvidia,function = "i2c2";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+                       };
+                       gen2_i2c_sda_pt6 {
+                               nvidia,pins = "gen2_i2c_sda_pt6";
+                               nvidia,function = "i2c2";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc4_cmd_pt7 {
+                               nvidia,pins = "sdmmc4_cmd_pt7";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pu0 {
+                               nvidia,pins = "pu0";
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pu1 {
+                               nvidia,pins = "pu1";
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pu2 {
+                               nvidia,pins = "pu2";
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pu3 {
+                               nvidia,pins = "pu3";
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pu4 {
+                               nvidia,pins = "pu4";
+                               nvidia,function = "pwm1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pu5 {
+                               nvidia,pins = "pu5";
+                               nvidia,function = "pwm2";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pu6 {
+                               nvidia,pins = "pu6";
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       jtag_rtck_pu7 {
+                               nvidia,pins = "jtag_rtck_pu7";
+                               nvidia,function = "rtck";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pv0 {
+                               nvidia,pins = "pv0";
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pv2 {
+                               nvidia,pins = "pv2";
+                               nvidia,function = "owr";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pv3 {
+                               nvidia,pins = "pv3";
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       ddc_scl_pv4 {
+                               nvidia,pins = "ddc_scl_pv4";
+                               nvidia,function = "i2c4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       ddc_sda_pv5 {
+                               nvidia,pins = "ddc_sda_pv5";
+                               nvidia,function = "i2c4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       crt_hsync_pv6 {
+                               nvidia,pins = "crt_hsync_pv6";
+                               nvidia,function = "crt";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       crt_vsync_pv7 {
+                               nvidia,pins = "crt_vsync_pv7";
+                               nvidia,function = "crt";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       lcd_cs1_n_pw0 {
+                               nvidia,pins = "lcd_cs1_n_pw0";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       lcd_m1_pw1 {
+                               nvidia,pins = "lcd_m1_pw1";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       spi2_cs1_n_pw2 {
+                               nvidia,pins = "spi2_cs1_n_pw2";
+                               nvidia,function = "spi2";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       clk1_out_pw4 {
+                               nvidia,pins = "clk1_out_pw4";
+                               nvidia,function = "extperiph1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       clk2_out_pw5 {
+                               nvidia,pins = "clk2_out_pw5";
+                               nvidia,function = "extperiph2";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       uart3_txd_pw6 {
+                               nvidia,pins = "uart3_txd_pw6";
+                               nvidia,function = "uartc";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       uart3_rxd_pw7 {
+                               nvidia,pins = "uart3_rxd_pw7";
+                               nvidia,function = "uartc";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       spi2_sck_px2 {
+                               nvidia,pins = "spi2_sck_px2";
+                               nvidia,function = "gmi";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       spi1_mosi_px4 {
+                               nvidia,pins = "spi1_mosi_px4";
+                               nvidia,function = "spi1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       spi1_sck_px5 {
+                               nvidia,pins = "spi1_sck_px5";
+                               nvidia,function = "spi1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       spi1_cs0_n_px6 {
+                               nvidia,pins = "spi1_cs0_n_px6";
+                               nvidia,function = "spi1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       spi1_miso_px7 {
+                               nvidia,pins = "spi1_miso_px7";
+                               nvidia,function = "spi1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       ulpi_clk_py0 {
+                               nvidia,pins = "ulpi_clk_py0";
+                               nvidia,function = "uartd";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       ulpi_dir_py1 {
+                               nvidia,pins = "ulpi_dir_py1";
+                               nvidia,function = "uartd";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       ulpi_nxt_py2 {
+                               nvidia,pins = "ulpi_nxt_py2";
+                               nvidia,function = "uartd";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       ulpi_stp_py3 {
+                               nvidia,pins = "ulpi_stp_py3";
+                               nvidia,function = "uartd";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       sdmmc1_dat3_py4 {
+                               nvidia,pins = "sdmmc1_dat3_py4";
+                               nvidia,function = "sdmmc1";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc1_dat2_py5 {
+                               nvidia,pins = "sdmmc1_dat2_py5";
+                               nvidia,function = "sdmmc1";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc1_dat1_py6 {
+                               nvidia,pins = "sdmmc1_dat1_py6";
+                               nvidia,function = "sdmmc1";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc1_dat0_py7 {
+                               nvidia,pins = "sdmmc1_dat0_py7";
+                               nvidia,function = "sdmmc1";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
                        sdmmc1_clk_pz0 {
                                nvidia,pins = "sdmmc1_clk_pz0";
                                nvidia,function = "sdmmc1";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        sdmmc1_cmd_pz1 {
-                               nvidia,pins =   "sdmmc1_cmd_pz1",
-                                               "sdmmc1_dat0_py7",
-                                               "sdmmc1_dat1_py6",
-                                               "sdmmc1_dat2_py5",
-                                               "sdmmc1_dat3_py4";
+                               nvidia,pins = "sdmmc1_cmd_pz1";
                                nvidia,function = "sdmmc1";
                                nvidia,pull = <TEGRA_PIN_PULL_UP>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
-                       sdmmc3_clk_pa6 {
-                               nvidia,pins = "sdmmc3_clk_pa6";
-                               nvidia,function = "sdmmc3";
+                       lcd_sdin_pz2 {
+                               nvidia,pins = "lcd_sdin_pz2";
+                               nvidia,function = "displaya";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
-                       sdmmc3_cmd_pa7 {
-                               nvidia,pins =   "sdmmc3_cmd_pa7",
-                                               "sdmmc3_dat0_pb7",
-                                               "sdmmc3_dat1_pb6",
-                                               "sdmmc3_dat2_pb5",
-                                               "sdmmc3_dat3_pb4";
-                               nvidia,function = "sdmmc3";
-                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                       lcd_wr_n_pz3 {
+                               nvidia,pins = "lcd_wr_n_pz3";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
-                       sdmmc4_clk_pcc4 {
-                               nvidia,pins =   "sdmmc4_clk_pcc4",
-                                               "sdmmc4_rst_n_pcc3";
-                               nvidia,function = "sdmmc4";
+                       lcd_sck_pz4 {
+                               nvidia,pins = "lcd_sck_pz4";
+                               nvidia,function = "displaya";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sys_clk_req_pz5 {
+                               nvidia,pins = "sys_clk_req_pz5";
+                               nvidia,function = "sysclk";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pwr_i2c_scl_pz6 {
+                               nvidia,pins = "pwr_i2c_scl_pz6";
+                               nvidia,function = "i2cpwr";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+                       };
+                       pwr_i2c_sda_pz7 {
+                               nvidia,pins = "pwr_i2c_sda_pz7";
+                               nvidia,function = "i2cpwr";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_ENABLE>;
                        };
                        sdmmc4_dat0_paa0 {
-                               nvidia,pins =   "sdmmc4_dat0_paa0",
-                                               "sdmmc4_dat1_paa1",
-                                               "sdmmc4_dat2_paa2",
-                                               "sdmmc4_dat3_paa3",
-                                               "sdmmc4_dat4_paa4",
-                                               "sdmmc4_dat5_paa5",
-                                               "sdmmc4_dat6_paa6",
-                                               "sdmmc4_dat7_paa7";
+                               nvidia,pins = "sdmmc4_dat0_paa0";
                                nvidia,function = "sdmmc4";
                                nvidia,pull = <TEGRA_PIN_PULL_UP>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
-                       dap2_fs_pa2 {
-                               nvidia,pins =   "dap2_fs_pa2",
-                                               "dap2_sclk_pa3",
-                                               "dap2_din_pa4",
-                                               "dap2_dout_pa5";
-                               nvidia,function = "i2s1";
+                       sdmmc4_dat1_paa1 {
+                               nvidia,pins = "sdmmc4_dat1_paa1";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc4_dat2_paa2 {
+                               nvidia,pins = "sdmmc4_dat2_paa2";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc4_dat3_paa3 {
+                               nvidia,pins = "sdmmc4_dat3_paa3";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc4_dat4_paa4 {
+                               nvidia,pins = "sdmmc4_dat4_paa4";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc4_dat5_paa5 {
+                               nvidia,pins = "sdmmc4_dat5_paa5";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc4_dat6_paa6 {
+                               nvidia,pins = "sdmmc4_dat6_paa6";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc4_dat7_paa7 {
+                               nvidia,pins = "sdmmc4_dat7_paa7";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pbb0 {
+                               nvidia,pins = "pbb0";
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       cam_i2c_scl_pbb1 {
+                               nvidia,pins = "cam_i2c_scl_pbb1";
+                               nvidia,function = "i2c3";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+                       };
+                       cam_i2c_sda_pbb2 {
+                               nvidia,pins = "cam_i2c_sda_pbb2";
+                               nvidia,function = "i2c3";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+                       };
+                       pbb3 {
+                               nvidia,pins = "pbb3";
+                               nvidia,function = "vgp3";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pbb4 {
+                               nvidia,pins = "pbb4";
+                               nvidia,function = "vgp4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pbb5 {
+                               nvidia,pins = "pbb5";
+                               nvidia,function = "vgp5";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pbb6 {
+                               nvidia,pins = "pbb6";
+                               nvidia,function = "vgp6";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pbb7 {
+                               nvidia,pins = "pbb7";
+                               nvidia,function = "i2s4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       cam_mclk_pcc0 {
+                               nvidia,pins = "cam_mclk_pcc0";
+                               nvidia,function = "vi_alt3";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pcc1 {
+                               nvidia,pins = "pcc1";
+                               nvidia,function = "rsvd1";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pcc2 {
+                               nvidia,pins = "pcc2";
+                               nvidia,function = "i2s4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc4_rst_n_pcc3 {
+                               nvidia,pins = "sdmmc4_rst_n_pcc3";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       sdmmc4_clk_pcc4 {
+                               nvidia,pins = "sdmmc4_clk_pcc4";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       clk2_req_pcc5 {
+                               nvidia,pins = "clk2_req_pcc5";
+                               nvidia,function = "dap";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pex_l2_rst_n_pcc6 {
+                               nvidia,pins = "pex_l2_rst_n_pcc6";
+                               nvidia,function = "pcie";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pex_l2_clkreq_n_pcc7 {
+                               nvidia,pins = "pex_l2_clkreq_n_pcc7";
+                               nvidia,function = "pcie";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pex_l0_prsnt_n_pdd0 {
+                               nvidia,pins = "pex_l0_prsnt_n_pdd0";
+                               nvidia,function = "pcie";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pex_l0_rst_n_pdd1 {
+                               nvidia,pins = "pex_l0_rst_n_pdd1";
+                               nvidia,function = "pcie";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pex_l0_clkreq_n_pdd2 {
+                               nvidia,pins = "pex_l0_clkreq_n_pdd2";
+                               nvidia,function = "pcie";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pex_wake_n_pdd3 {
+                               nvidia,pins = "pex_wake_n_pdd3";
+                               nvidia,function = "pcie";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        pex_l1_prsnt_n_pdd4 {
-                               nvidia,pins =   "pex_l1_prsnt_n_pdd4",
-                                               "pex_l1_clkreq_n_pdd6";
+                               nvidia,pins = "pex_l1_prsnt_n_pdd4";
+                               nvidia,function = "pcie";
+                               nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pex_l1_rst_n_pdd5 {
+                               nvidia,pins = "pex_l1_rst_n_pdd5";
+                               nvidia,function = "pcie";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       pex_l1_clkreq_n_pdd6 {
+                               nvidia,pins = "pex_l1_clkreq_n_pdd6";
+                               nvidia,function = "pcie";
                                nvidia,pull = <TEGRA_PIN_PULL_UP>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       pex_l2_prsnt_n_pdd7 {
+                               nvidia,pins = "pex_l2_prsnt_n_pdd7";
+                               nvidia,function = "pcie";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       clk3_out_pee0 {
+                               nvidia,pins = "clk3_out_pee0";
+                               nvidia,function = "extperiph3";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+                       };
+                       clk3_req_pee1 {
+                               nvidia,pins = "clk3_req_pee1";
+                               nvidia,function = "dev3";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       clk1_req_pee2 {
+                               nvidia,pins = "clk1_req_pee2";
+                               nvidia,function = "dap";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                       };
+                       hdmi_cec_pee3 {
+                               nvidia,pins = "hdmi_cec_pee3";
+                               nvidia,function = "cec";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+                               nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+                       };
+                       owr {
+                               nvidia,pins = "owr";
+                               nvidia,function = "owr";
+                               nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+                               nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        sdio3 {
                                nvidia,pins = "drive_sdio3";
index 33920df036401a76c2a821089b3d093c4967a67e..7a2aeacd62c0c2cb23b1247ce3b5ca6c55225d24 100644 (file)
                compatible = "arm,coresight-etb10", "arm,primecell";
                reg = <0 0x20010000 0 0x1000>;
 
-               coresight-default-sink;
                clocks = <&oscclk6a>;
                clock-names = "apb_pclk";
                port {
index 36cafbfa1bfacd58bd9e6ebbfeaf8a18c23ff018..606753eb72c8f67d9551b19bfed61137b2ab07c2 100644 (file)
                bootargs = "console=ttyLP0,115200";
        };
 
+       clk16m: clk16m {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <16000000>;
+       };
+
        regulators {
                compatible = "simple-bus";
                #address-cells = <1>;
        status  = "okay";
 };
 
+&dspi1 {
+       status = "okay";
+
+       mcp2515can: can@0 {
+               compatible = "microchip,mcp2515";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_can_int>;
+               reg = <0>;
+               clocks = <&clk16m>;
+               spi-max-frequency = <10000000>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <11 GPIO_ACTIVE_LOW>;
+       };
+};
+
 &esdhc1 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_esdhc1>;
 &usbh1 {
        vbus-supply = <&usbh_vbus_reg>;
 };
+
+&iomuxc {
+       vf610-colibri {
+               pinctrl_can_int: can_int {
+                       fsl,pins = <
+                               VF610_PAD_PTB21__GPIO_43        0x22ed
+                       >;
+               };
+       };
+};
index 5c2b7320856dc0efc49c12cf7ff5575bf94a05dc..fbef0828e9303ca54d3a2304b0d4b2cf26bea417 100644 (file)
        status = "okay";
 };
 
+&dspi1 {
+       bus-num = <1>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_dspi1>;
+};
+
 &edma0 {
        status = "okay";
 };
                        >;
                };
 
+               pinctrl_dspi1: dspi1grp {
+                       fsl,pins = <
+                               VF610_PAD_PTD5__DSPI1_CS0               0x33e2
+                               VF610_PAD_PTD6__DSPI1_SIN               0x33e1
+                               VF610_PAD_PTD7__DSPI1_SOUT              0x33e2
+                               VF610_PAD_PTD8__DSPI1_SCK               0x33e2
+                       >;
+               };
+
                pinctrl_esdhc1: esdhc1grp {
                        fsl,pins = <
                                VF610_PAD_PTA24__ESDHC1_CLK     0x31ef
index 1dbf8d2d1ddf50e034b337a64b6f74b4f868fd55..e976d2fa15274239b9ed2b0568cb9bd9ba9b2aa6 100644 (file)
        };
 
        soc {
-               interrupt-parent = <&intc>;
-
                aips-bus@40000000 {
 
                        intc: interrupt-controller@40002000 {
                                compatible = "arm,cortex-a9-gic";
                                #interrupt-cells = <3>;
                                interrupt-controller;
+                               interrupt-parent = <&intc>;
                                reg = <0x40003000 0x1000>,
                                      <0x40002100 0x100>;
                        };
                                compatible = "arm,cortex-a9-global-timer";
                                reg = <0x40002200 0x20>;
                                interrupts = <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-parent = <&intc>;
                                clocks = <&clks VF610_CLK_PLATFORM_BUS>;
                        };
                };
        };
 };
 
-&adc0 {
-       interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
-};
-
-&adc1 {
-       interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
-};
-
-&can0 {
-       interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
-};
-
-&can1 {
-       interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
-};
-
-&dspi0 {
-       interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
-};
-
-&edma0 {
-       interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
-                       <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
-       interrupt-names = "edma-tx", "edma-err";
-};
-
-&edma1 {
-       interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>,
-                       <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
-       interrupt-names = "edma-tx", "edma-err";
-};
-
-&esdhc1 {
-       interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
-};
-
-&fec0 {
-       interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
-};
-
-&fec1 {
-       interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
-};
-
-&ftm {
-       interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
-};
-
-&gpio0 {
-       interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
-};
-
-&gpio1 {
-       interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
-};
-
-&gpio2 {
-       interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
-};
-
-&gpio3 {
-       interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
-};
-
-&gpio4 {
-       interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
-};
-
-&i2c0 {
-       interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
-};
-
-&pit {
-       interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
-};
-
-&qspi0 {
-       interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
-};
-
-&sai2 {
-       interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
-};
-
-&snvsrtc {
-       interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
-};
-
-&src {
-       interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
-};
-
-&uart0 {
-       interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
-};
-
-&uart1 {
-       interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
-};
-
-&uart2 {
-       interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
-};
-
-&uart3 {
-       interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
-};
-
-&uart4 {
-       interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
-};
-
-&uart5 {
-       interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
-};
-
-&usbdev0 {
-       interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
-};
-
-&usbh1 {
-       interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
-};
-
-&usbphy0 {
-       interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
-};
-
-&usbphy1 {
-       interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
+&mscm_ir {
+       interrupt-parent = <&intc>;
 };
 
 &wdoga5 {
-       interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
        status = "okay";
 };
index a29c7ce15eafb2b8bbeffb05f173c752d319d230..4aa335166be76ae7296cbaf455a03af2e872e127 100644 (file)
@@ -54,6 +54,7 @@
                #address-cells = <1>;
                #size-cells = <1>;
                compatible = "simple-bus";
+               interrupt-parent = <&mscm_ir>;
                ranges;
 
                aips0: aips-bus@40000000 {
                        #size-cells = <1>;
                        ranges;
 
+                       mscm_cpucfg: cpucfg@40001000 {
+                               compatible = "fsl,vf610-mscm-cpucfg", "syscon";
+                               reg = <0x40001000 0x800>;
+                       };
+
+                       mscm_ir: interrupt-controller@40001800 {
+                               compatible = "fsl,vf610-mscm-ir";
+                               reg = <0x40001800 0x400>;
+                               fsl,cpucfg = <&mscm_cpucfg>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                       };
+
                        edma0: dma-controller@40018000 {
                                #dma-cells = <2>;
                                compatible = "fsl,vf610-edma";
@@ -69,6 +83,9 @@
                                        <0x40024000 0x1000>,
                                        <0x40025000 0x1000>;
                                dma-channels = <32>;
+                               interrupts = <8 IRQ_TYPE_LEVEL_HIGH>,
+                                               <9 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-names = "edma-tx", "edma-err";
                                clock-names = "dmamux0", "dmamux1";
                                clocks = <&clks VF610_CLK_DMAMUX0>,
                                        <&clks VF610_CLK_DMAMUX1>;
@@ -78,6 +95,7 @@
                        can0: flexcan@40020000 {
                                compatible = "fsl,vf610-flexcan";
                                reg = <0x40020000 0x4000>;
+                               interrupts = <58 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks VF610_CLK_FLEXCAN0>,
                                         <&clks VF610_CLK_FLEXCAN0>;
                                clock-names = "ipg", "per";
                        uart0: serial@40027000 {
                                compatible = "fsl,vf610-lpuart";
                                reg = <0x40027000 0x1000>;
+                               interrupts = <61 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks VF610_CLK_UART0>;
                                clock-names = "ipg";
                                dmas = <&edma0 0 2>,
                        uart1: serial@40028000 {
                                compatible = "fsl,vf610-lpuart";
                                reg = <0x40028000 0x1000>;
+                               interrupts = <62 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks VF610_CLK_UART1>;
                                clock-names = "ipg";
                                dmas = <&edma0 0 4>,
                        uart2: serial@40029000 {
                                compatible = "fsl,vf610-lpuart";
                                reg = <0x40029000 0x1000>;
+                               interrupts = <63 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks VF610_CLK_UART2>;
                                clock-names = "ipg";
                                dmas = <&edma0 0 6>,
                        uart3: serial@4002a000 {
                                compatible = "fsl,vf610-lpuart";
                                reg = <0x4002a000 0x1000>;
+                               interrupts = <64 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks VF610_CLK_UART3>;
                                clock-names = "ipg";
                                dmas = <&edma0 0 8>,
                                #size-cells = <0>;
                                compatible = "fsl,vf610-dspi";
                                reg = <0x4002c000 0x1000>;
+                               interrupts = <67 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks VF610_CLK_DSPI0>;
                                clock-names = "dspi";
                                spi-num-chipselects = <5>;
                                status = "disabled";
                        };
 
+                       dspi1: dspi1@4002d000 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               compatible = "fsl,vf610-dspi";
+                               reg = <0x4002d000 0x1000>;
+                               interrupts = <68 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clks VF610_CLK_DSPI1>;
+                               clock-names = "dspi";
+                               spi-num-chipselects = <5>;
+                               status = "disabled";
+                       };
+
                        sai2: sai@40031000 {
                                compatible = "fsl,vf610-sai";
                                reg = <0x40031000 0x1000>;
+                               interrupts = <86 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks VF610_CLK_SAI2>;
                                clock-names = "sai";
                                dma-names = "tx", "rx";
                        pit: pit@40037000 {
                                compatible = "fsl,vf610-pit";
                                reg = <0x40037000 0x1000>;
+                               interrupts = <39 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks VF610_CLK_PIT>;
                                clock-names = "pit";
                        };
                        adc0: adc@4003b000 {
                                compatible = "fsl,vf610-adc";
                                reg = <0x4003b000 0x1000>;
+                               interrupts = <53 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks VF610_CLK_ADC0>;
                                clock-names = "adc";
                                status = "disabled";
                        wdoga5: wdog@4003e000 {
                                compatible = "fsl,vf610-wdt", "fsl,imx21-wdt";
                                reg = <0x4003e000 0x1000>;
+                               interrupts = <20 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks VF610_CLK_WDT>;
                                clock-names = "wdog";
                                status = "disabled";
                                #size-cells = <0>;
                                compatible = "fsl,vf610-qspi";
                                reg = <0x40044000 0x1000>;
+                               interrupts = <24 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks VF610_CLK_QSPI0_EN>,
                                        <&clks VF610_CLK_QSPI0>;
                                clock-names = "qspi_en", "qspi";
                        iomuxc: iomuxc@40048000 {
                                compatible = "fsl,vf610-iomuxc";
                                reg = <0x40048000 0x1000>;
-                               #gpio-range-cells = <3>;
                        };
 
                        gpio0: gpio@40049000 {
                                reg = <0x40049000 0x1000 0x400ff000 0x40>;
                                gpio-controller;
                                #gpio-cells = <2>;
+                               interrupts = <107 IRQ_TYPE_LEVEL_HIGH>;
                                interrupt-controller;
                                #interrupt-cells = <2>;
                                gpio-ranges = <&iomuxc 0 0 32>;
                                reg = <0x4004a000 0x1000 0x400ff040 0x40>;
                                gpio-controller;
                                #gpio-cells = <2>;
+                               interrupts = <108 IRQ_TYPE_LEVEL_HIGH>;
                                interrupt-controller;
                                #interrupt-cells = <2>;
                                gpio-ranges = <&iomuxc 0 32 32>;
                                reg = <0x4004b000 0x1000 0x400ff080 0x40>;
                                gpio-controller;
                                #gpio-cells = <2>;
+                               interrupts = <109 IRQ_TYPE_LEVEL_HIGH>;
                                interrupt-controller;
                                #interrupt-cells = <2>;
                                gpio-ranges = <&iomuxc 0 64 32>;
                                reg = <0x4004c000 0x1000 0x400ff0c0 0x40>;
                                gpio-controller;
                                #gpio-cells = <2>;
+                               interrupts = <110 IRQ_TYPE_LEVEL_HIGH>;
                                interrupt-controller;
                                #interrupt-cells = <2>;
                                gpio-ranges = <&iomuxc 0 96 32>;
                                reg = <0x4004d000 0x1000 0x400ff100 0x40>;
                                gpio-controller;
                                #gpio-cells = <2>;
+                               interrupts = <111 IRQ_TYPE_LEVEL_HIGH>;
                                interrupt-controller;
                                #interrupt-cells = <2>;
                                gpio-ranges = <&iomuxc 0 128 7>;
                        usbphy0: usbphy@40050800 {
                                compatible = "fsl,vf610-usbphy";
                                reg = <0x40050800 0x400>;
+                               interrupts = <50 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks VF610_CLK_USBPHY0>;
                                fsl,anatop = <&anatop>;
                                status = "disabled";
                        usbphy1: usbphy@40050c00 {
                                compatible = "fsl,vf610-usbphy";
                                reg = <0x40050c00 0x400>;
+                               interrupts = <51 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks VF610_CLK_USBPHY1>;
                                fsl,anatop = <&anatop>;
                                status = "disabled";
                                #size-cells = <0>;
                                compatible = "fsl,vf610-i2c";
                                reg = <0x40066000 0x1000>;
+                               interrupts = <71 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks VF610_CLK_I2C0>;
                                clock-names = "ipg";
                                dmas = <&edma0 0 50>,
                        usbdev0: usb@40034000 {
                                compatible = "fsl,vf610-usb", "fsl,imx27-usb";
                                reg = <0x40034000 0x800>;
+                               interrupts = <75 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks VF610_CLK_USBC0>;
                                fsl,usbphy = <&usbphy0>;
                                fsl,usbmisc = <&usbmisc0 0>;
                        src: src@4006e000 {
                                compatible = "fsl,vf610-src", "syscon";
                                reg = <0x4006e000 0x1000>;
+                               interrupts = <96 IRQ_TYPE_LEVEL_HIGH>;
                        };
                };
 
                                        <0x400a1000 0x1000>,
                                        <0x400a2000 0x1000>;
                                dma-channels = <32>;
+                               interrupts = <10 IRQ_TYPE_LEVEL_HIGH>,
+                                               <11 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-names = "edma-tx", "edma-err";
                                clock-names = "dmamux0", "dmamux1";
                                clocks = <&clks VF610_CLK_DMAMUX2>,
                                        <&clks VF610_CLK_DMAMUX3>;
                                snvsrtc: snvs-rtc-lp@34 {
                                        compatible = "fsl,sec-v4.0-mon-rtc-lp";
                                        reg = <0x34 0x58>;
+                                       interrupts = <100 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clks VF610_CLK_SNVS>;
                                        clock-names = "snvs-rtc";
                                };
                        uart4: serial@400a9000 {
                                compatible = "fsl,vf610-lpuart";
                                reg = <0x400a9000 0x1000>;
+                               interrupts = <65 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks VF610_CLK_UART4>;
                                clock-names = "ipg";
                                status = "disabled";
                        uart5: serial@400aa000 {
                                compatible = "fsl,vf610-lpuart";
                                reg = <0x400aa000 0x1000>;
+                               interrupts = <66 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks VF610_CLK_UART5>;
                                clock-names = "ipg";
                                status = "disabled";
                        adc1: adc@400bb000 {
                                compatible = "fsl,vf610-adc";
                                reg = <0x400bb000 0x1000>;
+                               interrupts = <54 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks VF610_CLK_ADC1>;
                                clock-names = "adc";
                                status = "disabled";
                        esdhc1: esdhc@400b2000 {
                                compatible = "fsl,imx53-esdhc";
                                reg = <0x400b2000 0x1000>;
+                               interrupts = <28 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks VF610_CLK_IPG_BUS>,
                                        <&clks VF610_CLK_PLATFORM_BUS>,
                                        <&clks VF610_CLK_ESDHC1>;
                        usbh1: usb@400b4000 {
                                compatible = "fsl,vf610-usb", "fsl,imx27-usb";
                                reg = <0x400b4000 0x800>;
+                               interrupts = <76 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks VF610_CLK_USBC1>;
                                fsl,usbphy = <&usbphy1>;
                                fsl,usbmisc = <&usbmisc1 0>;
                        ftm: ftm@400b8000 {
                                compatible = "fsl,ftm-timer";
                                reg = <0x400b8000 0x1000 0x400b9000 0x1000>;
+                               interrupts = <44 IRQ_TYPE_LEVEL_HIGH>;
                                clock-names = "ftm-evt", "ftm-src",
                                        "ftm-evt-counter-en", "ftm-src-counter-en";
                                clocks = <&clks VF610_CLK_FTM2>,
                        fec0: ethernet@400d0000 {
                                compatible = "fsl,mvf600-fec";
                                reg = <0x400d0000 0x1000>;
+                               interrupts = <78 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks VF610_CLK_ENET0>,
                                        <&clks VF610_CLK_ENET0>,
                                        <&clks VF610_CLK_ENET>;
                        fec1: ethernet@400d1000 {
                                compatible = "fsl,mvf600-fec";
                                reg = <0x400d1000 0x1000>;
+                               interrupts = <79 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks VF610_CLK_ENET1>,
                                        <&clks VF610_CLK_ENET1>,
                                        <&clks VF610_CLK_ENET>;
                        can1: flexcan@400d4000 {
                                compatible = "fsl,vf610-flexcan";
                                reg = <0x400d4000 0x4000>;
+                               interrupts = <59 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks VF610_CLK_FLEXCAN1>,
                                         <&clks VF610_CLK_FLEXCAN1>;
                                clock-names = "ipg", "per";
index 3c165fc2dce284593de47902637e1f7068e8798b..5f8a52ac7edf2c74ba6ba2547df969a6acfdbd87 100644 (file)
@@ -55,22 +55,81 @@ bool mcpm_is_available(void)
        return (platform_ops) ? true : false;
 }
 
+/*
+ * We can't use regular spinlocks. In the switcher case, it is possible
+ * for an outbound CPU to call power_down() after its inbound counterpart
+ * is already live using the same logical CPU number which trips lockdep
+ * debugging.
+ */
+static arch_spinlock_t mcpm_lock = __ARCH_SPIN_LOCK_UNLOCKED;
+
+static int mcpm_cpu_use_count[MAX_NR_CLUSTERS][MAX_CPUS_PER_CLUSTER];
+
+static inline bool mcpm_cluster_unused(unsigned int cluster)
+{
+       int i, cnt;
+       for (i = 0, cnt = 0; i < MAX_CPUS_PER_CLUSTER; i++)
+               cnt |= mcpm_cpu_use_count[cluster][i];
+       return !cnt;
+}
+
 int mcpm_cpu_power_up(unsigned int cpu, unsigned int cluster)
 {
+       bool cpu_is_down, cluster_is_down;
+       int ret = 0;
+
        if (!platform_ops)
                return -EUNATCH; /* try not to shadow power_up errors */
        might_sleep();
-       return platform_ops->power_up(cpu, cluster);
+
+       /* backward compatibility callback */
+       if (platform_ops->power_up)
+               return platform_ops->power_up(cpu, cluster);
+
+       pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
+
+       /*
+        * Since this is called with IRQs enabled, and no arch_spin_lock_irq
+        * variant exists, we need to disable IRQs manually here.
+        */
+       local_irq_disable();
+       arch_spin_lock(&mcpm_lock);
+
+       cpu_is_down = !mcpm_cpu_use_count[cluster][cpu];
+       cluster_is_down = mcpm_cluster_unused(cluster);
+
+       mcpm_cpu_use_count[cluster][cpu]++;
+       /*
+        * The only possible values are:
+        * 0 = CPU down
+        * 1 = CPU (still) up
+        * 2 = CPU requested to be up before it had a chance
+        *     to actually make itself down.
+        * Any other value is a bug.
+        */
+       BUG_ON(mcpm_cpu_use_count[cluster][cpu] != 1 &&
+              mcpm_cpu_use_count[cluster][cpu] != 2);
+
+       if (cluster_is_down)
+               ret = platform_ops->cluster_powerup(cluster);
+       if (cpu_is_down && !ret)
+               ret = platform_ops->cpu_powerup(cpu, cluster);
+
+       arch_spin_unlock(&mcpm_lock);
+       local_irq_enable();
+       return ret;
 }
 
 typedef void (*phys_reset_t)(unsigned long);
 
 void mcpm_cpu_power_down(void)
 {
+       unsigned int mpidr, cpu, cluster;
+       bool cpu_going_down, last_man;
        phys_reset_t phys_reset;
 
-       if (WARN_ON_ONCE(!platform_ops || !platform_ops->power_down))
-               return;
+       if (WARN_ON_ONCE(!platform_ops))
+              return;
        BUG_ON(!irqs_disabled());
 
        /*
@@ -79,28 +138,65 @@ void mcpm_cpu_power_down(void)
         */
        setup_mm_for_reboot();
 
-       platform_ops->power_down();
+       /* backward compatibility callback */
+       if (platform_ops->power_down) {
+               platform_ops->power_down();
+               goto not_dead;
+       }
+
+       mpidr = read_cpuid_mpidr();
+       cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+       cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+       pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
+
+       __mcpm_cpu_going_down(cpu, cluster);
 
+       arch_spin_lock(&mcpm_lock);
+       BUG_ON(__mcpm_cluster_state(cluster) != CLUSTER_UP);
+
+       mcpm_cpu_use_count[cluster][cpu]--;
+       BUG_ON(mcpm_cpu_use_count[cluster][cpu] != 0 &&
+              mcpm_cpu_use_count[cluster][cpu] != 1);
+       cpu_going_down = !mcpm_cpu_use_count[cluster][cpu];
+       last_man = mcpm_cluster_unused(cluster);
+
+       if (last_man && __mcpm_outbound_enter_critical(cpu, cluster)) {
+               platform_ops->cpu_powerdown_prepare(cpu, cluster);
+               platform_ops->cluster_powerdown_prepare(cluster);
+               arch_spin_unlock(&mcpm_lock);
+               platform_ops->cluster_cache_disable();
+               __mcpm_outbound_leave_critical(cluster, CLUSTER_DOWN);
+       } else {
+               if (cpu_going_down)
+                       platform_ops->cpu_powerdown_prepare(cpu, cluster);
+               arch_spin_unlock(&mcpm_lock);
+               /*
+                * If cpu_going_down is false here, that means a power_up
+                * request raced ahead of us.  Even if we do not want to
+                * shut this CPU down, the caller still expects execution
+                * to return through the system resume entry path, like
+                * when the WFI is aborted due to a new IRQ or the like..
+                * So let's continue with cache cleaning in all cases.
+                */
+               platform_ops->cpu_cache_disable();
+       }
+
+       __mcpm_cpu_down(cpu, cluster);
+
+       /* Now we are prepared for power-down, do it: */
+       if (cpu_going_down)
+               wfi();
+
+not_dead:
        /*
         * It is possible for a power_up request to happen concurrently
         * with a power_down request for the same CPU. In this case the
-        * power_down method might not be able to actually enter a
-        * powered down state with the WFI instruction if the power_up
-        * method has removed the required reset condition.  The
-        * power_down method is then allowed to return. We must perform
-        * a re-entry in the kernel as if the power_up method just had
-        * deasserted reset on the CPU.
-        *
-        * To simplify race issues, the platform specific implementation
-        * must accommodate for the possibility of unordered calls to
-        * power_down and power_up with a usage count. Therefore, if a
-        * call to power_up is issued for a CPU that is not down, then
-        * the next call to power_down must not attempt a full shutdown
-        * but only do the minimum (normally disabling L1 cache and CPU
-        * coherency) and return just as if a concurrent power_up request
-        * had happened as described above.
+        * CPU might not be able to actually enter a powered down state
+        * with the WFI instruction if the power_up request has removed
+        * the required reset condition.  We must perform a re-entry in
+        * the kernel as if the power_up method just had deasserted reset
+        * on the CPU.
         */
-
        phys_reset = (phys_reset_t)(unsigned long)virt_to_phys(cpu_reset);
        phys_reset(virt_to_phys(mcpm_entry_point));
 
@@ -125,26 +221,66 @@ int mcpm_wait_for_cpu_powerdown(unsigned int cpu, unsigned int cluster)
 
 void mcpm_cpu_suspend(u64 expected_residency)
 {
-       phys_reset_t phys_reset;
-
-       if (WARN_ON_ONCE(!platform_ops || !platform_ops->suspend))
+       if (WARN_ON_ONCE(!platform_ops))
                return;
-       BUG_ON(!irqs_disabled());
 
-       /* Very similar to mcpm_cpu_power_down() */
-       setup_mm_for_reboot();
-       platform_ops->suspend(expected_residency);
-       phys_reset = (phys_reset_t)(unsigned long)virt_to_phys(cpu_reset);
-       phys_reset(virt_to_phys(mcpm_entry_point));
-       BUG();
+       /* backward compatibility callback */
+       if (platform_ops->suspend) {
+               phys_reset_t phys_reset;
+               BUG_ON(!irqs_disabled());
+               setup_mm_for_reboot();
+               platform_ops->suspend(expected_residency);
+               phys_reset = (phys_reset_t)(unsigned long)virt_to_phys(cpu_reset);
+               phys_reset(virt_to_phys(mcpm_entry_point));
+               BUG();
+       }
+
+       /* Some platforms might have to enable special resume modes, etc. */
+       if (platform_ops->cpu_suspend_prepare) {
+               unsigned int mpidr = read_cpuid_mpidr();
+               unsigned int cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+               unsigned int cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1); 
+               arch_spin_lock(&mcpm_lock);
+               platform_ops->cpu_suspend_prepare(cpu, cluster);
+               arch_spin_unlock(&mcpm_lock);
+       }
+       mcpm_cpu_power_down();
 }
 
 int mcpm_cpu_powered_up(void)
 {
+       unsigned int mpidr, cpu, cluster;
+       bool cpu_was_down, first_man;
+       unsigned long flags;
+
        if (!platform_ops)
                return -EUNATCH;
-       if (platform_ops->powered_up)
+
+       /* backward compatibility callback */
+       if (platform_ops->powered_up) {
                platform_ops->powered_up();
+               return 0;
+       }
+
+       mpidr = read_cpuid_mpidr();
+       cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+       cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+       local_irq_save(flags);
+       arch_spin_lock(&mcpm_lock);
+
+       cpu_was_down = !mcpm_cpu_use_count[cluster][cpu];
+       first_man = mcpm_cluster_unused(cluster);
+
+       if (first_man && platform_ops->cluster_is_up)
+               platform_ops->cluster_is_up(cluster);
+       if (cpu_was_down)
+               mcpm_cpu_use_count[cluster][cpu] = 1;
+       if (platform_ops->cpu_is_up)
+               platform_ops->cpu_is_up(cpu, cluster);
+
+       arch_spin_unlock(&mcpm_lock);
+       local_irq_restore(flags);
+
        return 0;
 }
 
@@ -334,8 +470,10 @@ int __init mcpm_sync_init(
        }
        mpidr = read_cpuid_mpidr();
        this_cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
-       for_each_online_cpu(i)
+       for_each_online_cpu(i) {
+               mcpm_cpu_use_count[this_cluster][i] = 1;
                mcpm_sync.clusters[this_cluster].cpus[i].cpu = CPU_UP;
+       }
        mcpm_sync.clusters[this_cluster].cluster = CLUSTER_UP;
        sync_cache_w(&mcpm_sync);
 
diff --git a/arch/arm/configs/ape6evm_defconfig b/arch/arm/configs/ape6evm_defconfig
deleted file mode 100644 (file)
index 9e9a72e..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=16
-CONFIG_CGROUPS=y
-CONFIG_CGROUP_SCHED=y
-CONFIG_KALLSYMS_ALL=y
-CONFIG_EMBEDDED=y
-CONFIG_PERF_EVENTS=y
-CONFIG_SLAB=y
-CONFIG_ARCH_SHMOBILE_LEGACY=y
-CONFIG_ARCH_R8A73A4=y
-CONFIG_MACH_APE6EVM=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_CPU_BPREDICT_DISABLE=y
-CONFIG_PL310_ERRATA_588369=y
-CONFIG_ARM_ERRATA_754322=y
-CONFIG_SMP=y
-CONFIG_SCHED_MC=y
-CONFIG_HAVE_ARM_ARCH_TIMER=y
-CONFIG_NR_CPUS=8
-CONFIG_AEABI=y
-CONFIG_HIGHMEM=y
-CONFIG_HIGHPTE=y
-# CONFIG_HW_PERF_EVENTS is not set
-# CONFIG_COMPACTION is not set
-# CONFIG_CROSS_MEMORY_ATTACH is not set
-CONFIG_ARM_APPENDED_DTB=y
-CONFIG_VFP=y
-CONFIG_NEON=y
-CONFIG_BINFMT_MISC=y
-CONFIG_PM=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_XFRM_USER=y
-CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_INET_LRO is not set
-# CONFIG_IPV6_SIT is not set
-CONFIG_NETFILTER=y
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_DEVTMPFS=y
-CONFIG_DEVTMPFS_MOUNT=y
-# CONFIG_FW_LOADER_USER_HELPER is not set
-CONFIG_NETDEVICES=y
-# CONFIG_NET_CADENCE is not set
-CONFIG_SMC91X=y
-CONFIG_SMSC911X=y
-# CONFIG_INPUT_MOUSEDEV is not set
-CONFIG_INPUT_EVDEV=y
-CONFIG_KEYBOARD_GPIO=y
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_NONSTANDARD=y
-CONFIG_SERIAL_SH_SCI=y
-CONFIG_SERIAL_SH_SCI_NR_UARTS=12
-CONFIG_SERIAL_SH_SCI_CONSOLE=y
-CONFIG_I2C=y
-CONFIG_I2C_SH_MOBILE=y
-CONFIG_GPIO_SH_PFC=y
-CONFIG_GPIOLIB=y
-# CONFIG_HWMON is not set
-CONFIG_THERMAL=y
-CONFIG_RCAR_THERMAL=y
-CONFIG_REGULATOR=y
-CONFIG_REGULATOR_FIXED_VOLTAGE=y
-CONFIG_REGULATOR_GPIO=y
-CONFIG_REGULATOR_MAX8973=y
-# CONFIG_HID is not set
-# CONFIG_USB_SUPPORT is not set
-CONFIG_MMC=y
-CONFIG_MMC_SDHI=y
-CONFIG_MMC_SH_MMCIF=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_GPIO=y
-CONFIG_DMADEVICES=y
-CONFIG_SH_DMAE=y
-# CONFIG_IOMMU_SUPPORT is not set
-# CONFIG_DNOTIFY is not set
-CONFIG_TMPFS=y
-# CONFIG_MISC_FILESYSTEMS is not set
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3_ACL=y
-CONFIG_NFS_V4=y
-CONFIG_NFS_V4_1=y
-CONFIG_ROOT_NFS=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_ENABLE_DEFAULT_TRACERS=y
-CONFIG_CRYPTO_CBC=y
-CONFIG_CRYPTO_ECB=y
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
-CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRC_CCITT=y
-CONFIG_CRC16=y
-CONFIG_CRC_T10DIF=y
-CONFIG_CRC_ITU_T=y
-CONFIG_CRC7=y
-CONFIG_LIBCRC32C=y
index 811e72bbe6429b6e6a18ac5c31c267c178d17714..bcef49a21801436dc7f4251c3fa788e17f769a3e 100644 (file)
@@ -13,10 +13,13 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_MULTI_V4T=y
+CONFIG_ARCH_MULTI_V5=y
+# CONFIG_ARCH_MULTI_V7 is not set
 CONFIG_ARCH_AT91=y
+CONFIG_SOC_SAM_V4_V5=y
 CONFIG_SOC_AT91RM9200=y
 CONFIG_SOC_AT91SAM9=y
-CONFIG_AT91_TIMER_HZ=128
 CONFIG_AEABI=y
 CONFIG_UACCESS_WITH_MEMCPY=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
index 1d8935359fd0600ba56485a42969acbe3c4a301a..d034c96c039bd054c98eb28f4dc868e2212e53e9 100644 (file)
@@ -26,6 +26,8 @@ CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_ARM_APPENDED_DTB=y
 CONFIG_ARM_ATAG_DTB_COMPAT=y
 CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC1,115200 init=/linuxrc mem=256M"
+CONFIG_CPU_IDLE=y
+CONFIG_ARM_EXYNOS_CPUIDLE=y
 CONFIG_VFP=y
 CONFIG_NEON=y
 CONFIG_PM=y
@@ -34,6 +36,14 @@ CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_NET_KEY=y
 CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=y
+CONFIG_MWIFIEX=y
+CONFIG_MWIFIEX_SDIO=y
 CONFIG_RFKILL_REGULATOR=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
@@ -91,9 +101,11 @@ CONFIG_CHARGER_MAX77693=y
 CONFIG_CHARGER_TPS65090=y
 CONFIG_HWMON=y
 CONFIG_SENSORS_LM90=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_THERMAL=y
 CONFIG_THERMAL=y
 CONFIG_EXYNOS_THERMAL=y
-CONFIG_EXYNOS_THERMAL_CORE=y
+CONFIG_THERMAL_EMULATION=y
 CONFIG_WATCHDOG=y
 CONFIG_S3C2410_WATCHDOG=y
 CONFIG_MFD_CROS_EC=y
@@ -118,6 +130,7 @@ CONFIG_REGULATOR_S2MPS11=y
 CONFIG_REGULATOR_S5M8767=y
 CONFIG_REGULATOR_TPS65090=y
 CONFIG_DRM=y
+CONFIG_DRM_EXYNOS_HDMI=y
 CONFIG_DRM_BRIDGE=y
 CONFIG_DRM_PTN3460=y
 CONFIG_DRM_PS8622=y
@@ -171,10 +184,11 @@ CONFIG_RTC_DRV_S5M=y
 CONFIG_RTC_DRV_S3C=y
 CONFIG_DMADEVICES=y
 CONFIG_PL330_DMA=y
+CONFIG_CHROME_PLATFORMS=y
+CONFIG_CROS_EC_CHARDEV=y
 CONFIG_COMMON_CLK_MAX77686=y
 CONFIG_COMMON_CLK_MAX77802=y
 CONFIG_COMMON_CLK_S2MPS11=y
-CONFIG_EXYNOS_IOMMU=y
 CONFIG_EXTCON=y
 CONFIG_EXTCON_MAX14577=y
 CONFIG_EXTCON_MAX77693=y
@@ -197,6 +211,8 @@ CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
 CONFIG_CRAMFS=y
 CONFIG_ROMFS_FS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ASCII=y
 CONFIG_NLS_ISO8859_1=y
index e6b0007355f883eaca70e4ce4df5b6fcc9818ae4..d3a8018639de22d20e71e5de73a35bb1ab30309a 100644 (file)
@@ -24,9 +24,8 @@ CONFIG_ARCH_MXC=y
 CONFIG_MACH_SCB9328=y
 CONFIG_MACH_APF9328=y
 CONFIG_MACH_MX21ADS=y
-CONFIG_MACH_MX25_3DS=y
 CONFIG_MACH_EUKREA_CPUIMX25SD=y
-CONFIG_MACH_IMX25_DT=y
+CONFIG_SOC_IMX25=y
 CONFIG_MACH_MX27ADS=y
 CONFIG_MACH_MX27_3DS=y
 CONFIG_MACH_IMX27_VISSTRIM_M10=y
@@ -177,6 +176,7 @@ CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 CONFIG_EXT4_FS=y
 # CONFIG_DNOTIFY is not set
+CONFIG_VFAT_FS=y
 # CONFIG_PROC_PAGE_MONITOR is not set
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
index cf1e71e2f60abedc7bb8cb8c3ce5b268deaffa7e..fdeb1c83dcb57c1f2fd61c4a967df8e9248e4172 100644 (file)
@@ -71,6 +71,9 @@ CONFIG_IPV6=y
 CONFIG_NETFILTER=y
 CONFIG_CAN=y
 CONFIG_CAN_FLEXCAN=y
+CONFIG_BT=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_3WIRE=y
 CONFIG_CFG80211=y
 CONFIG_MAC80211=y
 CONFIG_RFKILL=y
@@ -168,6 +171,7 @@ CONFIG_SPI=y
 CONFIG_SPI_IMX=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_MC9S08DZ60=y
+CONFIG_GPIO_PCA953X=y
 CONFIG_GPIO_STMPE=y
 CONFIG_POWER_SUPPLY=y
 CONFIG_POWER_RESET=y
diff --git a/arch/arm/configs/mackerel_defconfig b/arch/arm/configs/mackerel_defconfig
deleted file mode 100644 (file)
index 05a5293..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=16
-# CONFIG_UTS_NS is not set
-# CONFIG_IPC_NS is not set
-# CONFIG_USER_NS is not set
-# CONFIG_PID_NS is not set
-# CONFIG_NET_NS is not set
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_SHMOBILE_LEGACY=y
-CONFIG_ARCH_SH7372=y
-CONFIG_MACH_MACKEREL=y
-CONFIG_MEMORY_SIZE=0x10000000
-CONFIG_AEABI=y
-# CONFIG_OABI_COMPAT is not set
-CONFIG_FORCE_MAX_ZONEORDER=15
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_ARM_APPENDED_DTB=y
-CONFIG_KEXEC=y
-CONFIG_VFP=y
-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_PM=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_IPV6 is not set
-# CONFIG_WIRELESS is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_DEVTMPFS=y
-CONFIG_DEVTMPFS_MOUNT=y
-# CONFIG_FIRMWARE_IN_KERNEL is not set
-CONFIG_MTD=y
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_ARM_INTEGRATOR=y
-CONFIG_MTD_BLOCK2MTD=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-# CONFIG_SCSI_LOWLEVEL is not set
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_SMSC911X=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_WLAN is not set
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_SERIAL_SH_SCI=y
-CONFIG_SERIAL_SH_SCI_NR_UARTS=8
-CONFIG_SERIAL_SH_SCI_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_SH_MOBILE=y
-# CONFIG_HWMON is not set
-# CONFIG_MFD_SUPPORT is not set
-CONFIG_REGULATOR=y
-CONFIG_FB=y
-CONFIG_FB_MODE_HELPERS=y
-CONFIG_FB_SH_MOBILE_LCDC=y
-CONFIG_FB_SH_MOBILE_HDMI=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_LOGO=y
-# CONFIG_LOGO_LINUX_MONO is not set
-# CONFIG_LOGO_LINUX_CLUT224 is not set
-# CONFIG_SND_SUPPORT_OLD_API is not set
-# CONFIG_SND_VERBOSE_PROCFS is not set
-# CONFIG_SND_DRIVERS is not set
-# CONFIG_SND_ARM is not set
-CONFIG_SND_SOC_SH4_FSI=y
-CONFIG_USB=y
-CONFIG_USB_RENESAS_USBHS_HCD=y
-CONFIG_USB_RENESAS_USBHS=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_RENESAS_USBHS_UDC=y
-CONFIG_MMC=y
-CONFIG_MMC_SDHI=y
-CONFIG_MMC_SH_MMCIF=y
-CONFIG_DMADEVICES=y
-CONFIG_SH_DMAE=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT2_FS_SECURITY=y
-CONFIG_EXT2_FS_XIP=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_EXT3_FS_SECURITY=y
-# CONFIG_DNOTIFY is not set
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-# CONFIG_MISC_FILESYSTEMS is not set
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V3_ACL=y
-CONFIG_NFS_V4=y
-CONFIG_NFS_V4_1=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_737=y
-CONFIG_NLS_CODEPAGE_775=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_CODEPAGE_852=y
-CONFIG_NLS_CODEPAGE_855=y
-CONFIG_NLS_CODEPAGE_857=y
-CONFIG_NLS_CODEPAGE_860=y
-CONFIG_NLS_CODEPAGE_861=y
-CONFIG_NLS_CODEPAGE_862=y
-CONFIG_NLS_CODEPAGE_863=y
-CONFIG_NLS_CODEPAGE_864=y
-CONFIG_NLS_CODEPAGE_865=y
-CONFIG_NLS_CODEPAGE_866=y
-CONFIG_NLS_CODEPAGE_869=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_2=y
-CONFIG_NLS_ISO8859_3=y
-CONFIG_NLS_ISO8859_4=y
-CONFIG_NLS_ISO8859_5=y
-CONFIG_NLS_ISO8859_6=y
-CONFIG_NLS_ISO8859_7=y
-CONFIG_NLS_ISO8859_9=y
-CONFIG_NLS_ISO8859_13=y
-CONFIG_NLS_ISO8859_14=y
-CONFIG_NLS_ISO8859_15=y
-CONFIG_NLS_KOI8_R=y
-CONFIG_NLS_KOI8_U=y
-CONFIG_NLS_UTF8=y
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
-# CONFIG_ENABLE_MUST_CHECK is not set
-# CONFIG_ARM_UNWIND is not set
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ANSI_CPRNG=y
diff --git a/arch/arm/configs/msm_defconfig b/arch/arm/configs/msm_defconfig
deleted file mode 100644 (file)
index dd18c9e..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-CONFIG_SYSVIPC=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_KALLSYMS_ALL=y
-CONFIG_EMBEDDED=y
-# CONFIG_SLUB_DEBUG is not set
-# CONFIG_COMPAT_BRK is not set
-CONFIG_PROFILING=y
-CONFIG_OPROFILE=y
-CONFIG_KPROBES=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_ARCH_MSM=y
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-CONFIG_HIGHMEM=y
-CONFIG_HIGHPTE=y
-CONFIG_CLEANCACHE=y
-CONFIG_AUTO_ZRELADDR=y
-CONFIG_VFP=y
-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_IPV6 is not set
-CONFIG_CFG80211=y
-CONFIG_RFKILL=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_CHR_DEV_SCH=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_SCSI_SCAN_ASYNC=y
-CONFIG_NETDEVICES=y
-CONFIG_DUMMY=y
-CONFIG_SLIP=y
-CONFIG_SLIP_COMPRESSED=y
-CONFIG_SLIP_MODE_SLIP6=y
-CONFIG_USB_USBNET=y
-# CONFIG_USB_NET_AX8817X is not set
-# CONFIG_USB_NET_ZAURUS is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_KEYBOARD_ATKBD is not set
-# CONFIG_MOUSE_PS2 is not set
-CONFIG_INPUT_JOYSTICK=y
-CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_INPUT_MISC=y
-CONFIG_INPUT_UINPUT=y
-CONFIG_SERIO_LIBPS2=y
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_MSM=y
-CONFIG_SERIAL_MSM_CONSOLE=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_SPI=y
-CONFIG_DEBUG_GPIO=y
-CONFIG_GPIO_SYSFS=y
-CONFIG_THERMAL=y
-CONFIG_REGULATOR=y
-CONFIG_MEDIA_SUPPORT=y
-CONFIG_FB=y
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_DYNAMIC_MINORS=y
-# CONFIG_SND_ARM is not set
-# CONFIG_SND_SPI is not set
-# CONFIG_SND_USB is not set
-CONFIG_SND_SOC=y
-CONFIG_USB=y
-CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_MON=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_ACM=y
-CONFIG_USB_SERIAL=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DEBUG_FILES=y
-CONFIG_USB_GADGET_VBUS_DRAW=500
-CONFIG_RTC_CLASS=y
-CONFIG_STAGING=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_EXT4_FS=y
-CONFIG_FUSE_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3_ACL=y
-CONFIG_NFS_V4=y
-CONFIG_CIFS=y
-CONFIG_PRINTK_TIME=y
-CONFIG_DYNAMIC_DEBUG=y
-CONFIG_DEBUG_INFO=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_LOCKUP_DETECTOR=y
-# CONFIG_DETECT_HUNG_TASK is not set
-# CONFIG_SCHED_DEBUG is not set
-CONFIG_TIMER_STATS=y
index 9d56781a8f80171e65922a44786d8bb10cbd3d4a..f69a459f4f92db0016857df6c710eb3b281c500e 100644 (file)
@@ -13,7 +13,7 @@ CONFIG_ARCH_MVEBU=y
 CONFIG_MACH_KIRKWOOD=y
 CONFIG_MACH_NETXBIG=y
 CONFIG_ARCH_MXC=y
-CONFIG_MACH_IMX25_DT=y
+CONFIG_SOC_IMX25=y
 CONFIG_MACH_IMX27_DT=y
 CONFIG_ARCH_U300=y
 CONFIG_PCI_MVEBU=y
index 06075b6d246364db1c57b1e8860e6f675d1857c5..ab86655c1f4be22869742d274b157e5470a2bb0c 100644 (file)
@@ -12,10 +12,12 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_CMDLINE_PARTITION=y
 CONFIG_ARCH_VIRT=y
+CONFIG_ARCH_ALPINE=y
 CONFIG_ARCH_MVEBU=y
 CONFIG_MACH_ARMADA_370=y
 CONFIG_MACH_ARMADA_375=y
 CONFIG_MACH_ARMADA_38X=y
+CONFIG_MACH_ARMADA_39X=y
 CONFIG_MACH_ARMADA_XP=y
 CONFIG_MACH_DOVE=y
 CONFIG_ARCH_BCM=y
@@ -91,6 +93,7 @@ CONFIG_ARCH_WM8850=y
 CONFIG_ARCH_ZYNQ=y
 CONFIG_TRUSTED_FOUNDATIONS=y
 CONFIG_PCI=y
+CONFIG_PCI_HOST_GENERIC=y
 CONFIG_PCI_KEYSTONE=y
 CONFIG_PCI_MSI=y
 CONFIG_PCI_MVEBU=y
@@ -133,6 +136,9 @@ CONFIG_CAN_BCM=y
 CONFIG_CAN_DEV=y
 CONFIG_CAN_XILINXCAN=y
 CONFIG_CAN_MCP251X=y
+CONFIG_BT=m
+CONFIG_BT_MRVL=m
+CONFIG_BT_MRVL_SDIO=m
 CONFIG_CFG80211=m
 CONFIG_MAC80211=m
 CONFIG_RFKILL=y
@@ -200,6 +206,8 @@ CONFIG_USB_NET_SMSC95XX=y
 CONFIG_BRCMFMAC=m
 CONFIG_RT2X00=m
 CONFIG_RT2800USB=m
+CONFIG_MWIFIEX=m
+CONFIG_MWIFIEX_SDIO=m
 CONFIG_INPUT_JOYDEV=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_KEYBOARD_GPIO=y
@@ -208,6 +216,7 @@ CONFIG_KEYBOARD_SPEAR=y
 CONFIG_KEYBOARD_ST_KEYSCAN=y
 CONFIG_KEYBOARD_CROS_EC=y
 CONFIG_MOUSE_PS2_ELANTECH=y
+CONFIG_MOUSE_ELAN_I2C=y
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_ATMEL_MXT=y
 CONFIG_TOUCHSCREEN_ST1232=m
@@ -308,6 +317,7 @@ CONFIG_BATTERY_SBS=y
 CONFIG_CHARGER_TPS65090=y
 CONFIG_POWER_RESET_AS3722=y
 CONFIG_POWER_RESET_GPIO=y
+CONFIG_POWER_RESET_GPIO_RESTART=y
 CONFIG_POWER_RESET_KEYSTONE=y
 CONFIG_POWER_RESET_SUN6I=y
 CONFIG_POWER_RESET_RMOBILE=y
@@ -505,7 +515,6 @@ CONFIG_DW_DMAC=y
 CONFIG_MV_XOR=y
 CONFIG_TEGRA20_APB_DMA=y
 CONFIG_SH_DMAE=y
-CONFIG_RCAR_AUDMAC_PP=m
 CONFIG_RCAR_DMAC=y
 CONFIG_STE_DMA40=y
 CONFIG_SIRF_DMA=y
@@ -533,6 +542,8 @@ CONFIG_MSM_MMCC_8960=y
 CONFIG_MSM_MMCC_8974=y
 CONFIG_TEGRA_IOMMU_GART=y
 CONFIG_TEGRA_IOMMU_SMMU=y
+CONFIG_PM_DEVFREQ=y
+CONFIG_ARM_TEGRA_DEVFREQ=m
 CONFIG_MEMORY=y
 CONFIG_TI_AEMIF=y
 CONFIG_IIO=y
@@ -550,6 +561,7 @@ CONFIG_PHY_MIPHY365X=y
 CONFIG_PHY_STIH41X_USB=y
 CONFIG_PHY_STIH407_USB=y
 CONFIG_PHY_SUN4I_USB=y
+CONFIG_PHY_SUN9I_USB=y
 CONFIG_EXT4_FS=y
 CONFIG_AUTOFS4_FS=y
 CONFIG_MSDOS_FS=y
index 73673e95f23c6351982ec081533f92acd72fd52f..cacc9f4055a72945aab6dba3909b0409c6cf9abc 100644 (file)
@@ -5,6 +5,7 @@ CONFIG_HIGH_RES_TIMERS=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_EXPERT=y
+CONFIG_PERF_EVENTS=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
@@ -12,6 +13,7 @@ CONFIG_ARCH_MVEBU=y
 CONFIG_MACH_ARMADA_370=y
 CONFIG_MACH_ARMADA_375=y
 CONFIG_MACH_ARMADA_38X=y
+CONFIG_MACH_ARMADA_39X=y
 CONFIG_MACH_ARMADA_XP=y
 CONFIG_MACH_DOVE=y
 CONFIG_PCI=y
index c7906c2fd645de229aeb12cde6c15cee7e0bb429..b47e7c6628c9f8883322cffba9e97c12f6963098 100644 (file)
@@ -149,6 +149,7 @@ CONFIG_EXT4_FS=y
 CONFIG_FSCACHE=m
 CONFIG_FSCACHE_STATS=y
 CONFIG_CACHEFILES=m
+CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
 CONFIG_JFFS2_FS=y
index a7dce674f1be073558dd062d5d29b32e331dba9d..0c8a787345368794950b28d529686a1554b4b1a0 100644 (file)
@@ -1,4 +1,3 @@
-CONFIG_EXPERIMENTAL=y
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
@@ -34,7 +33,6 @@ CONFIG_ARCH_OMAP16XX=y
 CONFIG_MACH_OMAP_INNOVATOR=y
 CONFIG_MACH_OMAP_H2=y
 CONFIG_MACH_OMAP_H3=y
-CONFIG_MACH_OMAP_HTCWIZARD=y
 CONFIG_MACH_HERALD=y
 CONFIG_MACH_OMAP_OSK=y
 CONFIG_MACH_OMAP_PERSEUS2=y
@@ -55,7 +53,6 @@ CONFIG_HIGH_RES_TIMERS=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_LEDS=y
-CONFIG_LEDS_CPU=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_CMDLINE="root=1f03 rootfstype=jffs2"
@@ -80,8 +77,6 @@ CONFIG_IP_PNP_BOOTP=y
 CONFIG_IPV6=y
 CONFIG_NETFILTER=y
 CONFIG_BT=y
-CONFIG_BT_L2CAP=y
-CONFIG_BT_SCO=y
 CONFIG_BT_RFCOMM=y
 CONFIG_BT_RFCOMM_TTY=y
 CONFIG_BT_BNEP=y
@@ -92,11 +87,7 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_CONNECTOR=y
 # CONFIG_PROC_EVENTS is not set
 CONFIG_MTD=y
-CONFIG_MTD_DEBUG=y
-CONFIG_MTD_DEBUG_VERBOSE=3
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_INTELEXT=y
@@ -113,11 +104,9 @@ CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
 CONFIG_BLK_DEV_SR=y
 CONFIG_CHR_DEV_SG=y
-CONFIG_SCSI_MULTI_LUN=y
 CONFIG_NETDEVICES=y
 CONFIG_TUN=y
 CONFIG_PHYLIB=y
-CONFIG_NET_ETHERNET=y
 CONFIG_SMC91X=y
 CONFIG_USB_CATC=y
 CONFIG_USB_KAWETH=y
@@ -158,7 +147,6 @@ CONFIG_SPI_OMAP_UWIRE=y
 CONFIG_WATCHDOG=y
 CONFIG_WATCHDOG_NOWAYOUT=y
 CONFIG_OMAP_WATCHDOG=y
-CONFIG_VIDEO_OUTPUT_CONTROL=y
 CONFIG_FB=y
 CONFIG_FIRMWARE_EDID=y
 CONFIG_FB_MODE_HELPERS=y
@@ -168,7 +156,6 @@ CONFIG_FB_OMAP_LCDC_EXTERNAL=y
 CONFIG_FB_OMAP_LCDC_HWA742=y
 CONFIG_FB_OMAP_MANUAL_UPDATE=y
 CONFIG_FB_OMAP_LCD_MIPID=y
-CONFIG_FB_OMAP_BOOTLOADER_INIT=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_LCD_CLASS_DEVICE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
@@ -194,7 +181,6 @@ CONFIG_SND_OMAP_SOC=y
 # CONFIG_USB_HID is not set
 CONFIG_USB=y
 CONFIG_USB_PHY=y
-# CONFIG_USB_DEVICE_CLASS is not set
 CONFIG_USB_MON=y
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_STORAGE=y
@@ -261,9 +247,7 @@ CONFIG_DEBUG_SPINLOCK=y
 CONFIG_DEBUG_MUTEXES=y
 # CONFIG_DEBUG_BUGVERBOSE is not set
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
 CONFIG_SECURITY=y
 CONFIG_CRYPTO_ECB=y
 CONFIG_CRYPTO_PCBC=y
index 8e108599e1af401451aeeb01a9e6b7a1752c7c0d..9ff7b54b2a837aa509b46d71b38741b7ded2c25d 100644 (file)
@@ -1,3 +1,4 @@
+CONFIG_KERNEL_LZMA=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_FHANDLE=y
@@ -86,17 +87,33 @@ CONFIG_IP_PNP_BOOTP=y
 CONFIG_IP_PNP_RARP=y
 # CONFIG_INET_LRO is not set
 CONFIG_NETFILTER=y
+CONFIG_PHONET=m
 CONFIG_CAN=m
 CONFIG_CAN_C_CAN=m
 CONFIG_CAN_C_CAN_PLATFORM=m
 CONFIG_BT=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+CONFIG_BT_HCIBTUSB=m
+CONFIG_BT_HCIBTSDIO=m
 CONFIG_BT_HCIUART=m
 CONFIG_BT_HCIUART_H4=y
 CONFIG_BT_HCIUART_BCSP=y
 CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIUART_3WIRE=y
 CONFIG_BT_HCIBCM203X=m
 CONFIG_BT_HCIBPA10X=m
 CONFIG_CFG80211=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_BT_MRVL=m
+CONFIG_BT_MRVL_SDIO=m
+CONFIG_AF_RXRPC=m
+CONFIG_RXKAD=m
 CONFIG_MAC80211=m
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
@@ -163,6 +180,7 @@ CONFIG_USB_EPSON2888=y
 CONFIG_USB_EHCI_HCD=m
 CONFIG_USB_OHCI_HCD=m
 CONFIG_USB_KC2190=y
+CONFIG_USB_CDC_PHONET=m
 CONFIG_LIBERTAS=m
 CONFIG_LIBERTAS_USB=m
 CONFIG_LIBERTAS_SDIO=m
@@ -209,6 +227,10 @@ CONFIG_I2C_CHARDEV=y
 CONFIG_SPI=y
 CONFIG_SPI_OMAP24XX=y
 CONFIG_SPI_TI_QSPI=m
+CONFIG_HSI=m
+CONFIG_OMAP_SSI=m
+CONFIG_NOKIA_MODEM=m
+CONFIG_SSI_PROTOCOL=m
 CONFIG_PINCTRL_SINGLE=y
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
@@ -334,6 +356,7 @@ CONFIG_USB_CONFIGFS_ECM=y
 CONFIG_USB_CONFIGFS_ECM_SUBSET=y
 CONFIG_USB_CONFIGFS_RNDIS=y
 CONFIG_USB_CONFIGFS_EEM=y
+CONFIG_USB_CONFIGFS_PHONET=y
 CONFIG_USB_CONFIGFS_MASS_STORAGE=y
 CONFIG_USB_CONFIGFS_F_LB_SS=y
 CONFIG_USB_CONFIGFS_F_FS=y
@@ -342,6 +365,7 @@ CONFIG_USB_CONFIGFS_F_UAC2=y
 CONFIG_USB_CONFIGFS_F_MIDI=y
 CONFIG_USB_CONFIGFS_F_HID=y
 CONFIG_USB_ZERO=m
+CONFIG_USB_G_NOKIA=m
 CONFIG_MMC=y
 CONFIG_SDIO_UART=y
 CONFIG_MMC_OMAP=y
@@ -349,6 +373,7 @@ CONFIG_MMC_OMAP_HS=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=m
 CONFIG_LEDS_GPIO=m
+CONFIG_LEDS_PWM=m
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=m
 CONFIG_LEDS_TRIGGER_ONESHOT=m
@@ -368,6 +393,7 @@ CONFIG_TI_EDMA=y
 CONFIG_DMA_OMAP=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXTCON=m
+CONFIG_EXTCON_GPIO=m
 CONFIG_EXTCON_PALMAS=m
 CONFIG_TI_EMIF=m
 CONFIG_PWM=y
@@ -390,6 +416,7 @@ CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_CONFIGFS_FS=y
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_SUMMARY=y
 CONFIG_JFFS2_FS_XATTR=y
index 8c7da3319d82b050cb964e3bd841c333481d61b8..d2f2babfd47a0985adda898f6de949cffb2010eb 100644 (file)
@@ -97,9 +97,9 @@ CONFIG_PINCTRL_APQ8084=y
 CONFIG_PINCTRL_IPQ8064=y
 CONFIG_PINCTRL_MSM8960=y
 CONFIG_PINCTRL_MSM8X74=y
+CONFIG_GPIOLIB=y
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
-CONFIG_POWER_SUPPLY=y
 CONFIG_POWER_RESET=y
 CONFIG_POWER_RESET_MSM=y
 CONFIG_THERMAL=y
@@ -125,7 +125,7 @@ CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DEBUG_FILES=y
 CONFIG_USB_GADGET_VBUS_DRAW=500
 CONFIG_MMC=y
-CONFIG_MMC_BLOCK_MINORS=16
+CONFIG_MMC_BLOCK_MINORS=32
 CONFIG_MMC_ARMMMCI=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
@@ -134,14 +134,15 @@ CONFIG_RTC_CLASS=y
 CONFIG_DMADEVICES=y
 CONFIG_QCOM_BAM_DMA=y
 CONFIG_STAGING=y
-CONFIG_QCOM_GSBI=y
 CONFIG_COMMON_CLK_QCOM=y
 CONFIG_APQ_MMCC_8084=y
-CONFIG_IPQ_GCC_806X=y
+CONFIG_IPQ_LCC_806X=y
 CONFIG_MSM_GCC_8660=y
+CONFIG_MSM_LCC_8960=y
 CONFIG_MSM_MMCC_8960=y
 CONFIG_MSM_MMCC_8974=y
 CONFIG_MSM_IOMMU=y
+CONFIG_QCOM_GSBI=y
 CONFIG_PHY_QCOM_APQ8064_SATA=y
 CONFIG_PHY_QCOM_IPQ806X_SATA=y
 CONFIG_EXT2_FS=y
index b17036088726eb2b135473fbd41a82d587c48f3f..b58618e2d13c51c869c3d4fa2b1c43aa7f61fd41 100644 (file)
@@ -12,7 +12,9 @@ CONFIG_SLAB=y
 CONFIG_ARCH_SHMOBILE_MULTI=y
 CONFIG_ARCH_EMEV2=y
 CONFIG_ARCH_R7S72100=y
+CONFIG_ARCH_R8A73A4=y
 CONFIG_ARCH_R8A7740=y
+CONFIG_ARCH_R8A7778=y
 CONFIG_ARCH_R8A7779=y
 CONFIG_ARCH_R8A7790=y
 CONFIG_ARCH_R8A7791=y
@@ -92,7 +94,6 @@ CONFIG_INPUT_ADXL34X=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_EM=y
 CONFIG_SERIAL_SH_SCI=y
 CONFIG_SERIAL_SH_SCI_NR_UARTS=20
@@ -109,6 +110,9 @@ CONFIG_SPI_SH_HSPI=y
 CONFIG_GPIO_EM=y
 CONFIG_GPIO_RCAR=y
 CONFIG_GPIO_PCF857X=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_RMOBILE=y
 # CONFIG_HWMON is not set
 CONFIG_THERMAL=y
 CONFIG_CPU_THERMAL=y
@@ -121,6 +125,7 @@ CONFIG_REGULATOR=y
 CONFIG_REGULATOR_AS3711=y
 CONFIG_REGULATOR_DA9210=y
 CONFIG_REGULATOR_GPIO=y
+CONFIG_REGULATOR_MAX8973=y
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_MEDIA_CAMERA_SUPPORT=y
 CONFIG_MEDIA_CONTROLLER=y
@@ -133,6 +138,7 @@ CONFIG_V4L_MEM2MEM_DRIVERS=y
 CONFIG_VIDEO_RENESAS_VSP1=y
 # CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
 CONFIG_VIDEO_ADV7180=y
+CONFIG_VIDEO_ML86V7667=y
 CONFIG_DRM=y
 CONFIG_DRM_RCAR_DU=y
 CONFIG_FB_SH_MOBILE_LCDC=y
@@ -167,6 +173,7 @@ CONFIG_LEDS_GPIO=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_RS5C372=y
 CONFIG_RTC_DRV_S35390A=y
+CONFIG_RTC_DRV_RX8581=y
 CONFIG_DMADEVICES=y
 CONFIG_SH_DMAE=y
 CONFIG_RCAR_DMAC=y
index 8f6a5702b69619eb6d332db0dbf45853b527faa4..8ecba00dcd83def3a2ef3abc86d71e1aec942b0f 100644 (file)
@@ -107,6 +107,7 @@ CONFIG_RTC_DRV_SUN6I=y
 CONFIG_RTC_DRV_SUNXI=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_PHY_SUN4I_USB=y
+CONFIG_PHY_SUN9I_USB=y
 CONFIG_EXT4_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
diff --git a/arch/arm/include/asm/arm-cci.h b/arch/arm/include/asm/arm-cci.h
new file mode 100644 (file)
index 0000000..fe77f7a
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * arch/arm/include/asm/arm-cci.h
+ *
+ * Copyright (C) 2015 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_ARM_CCI_H
+#define __ASM_ARM_CCI_H
+
+#ifdef CONFIG_MCPM
+#include <asm/mcpm.h>
+
+/*
+ * We don't have a reliable way of detecting whether,
+ * if we have access to secure-only registers, unless
+ * mcpm is registered.
+ */
+static inline bool platform_has_secure_cci_access(void)
+{
+       return mcpm_is_available();
+}
+
+#else
+static inline bool platform_has_secure_cci_access(void)
+{
+       return false;
+}
+#endif
+
+#endif
index 3446f6a1d9fa6c982dbfc511aa34da8c8803da9e..50b378f59e086c45331a594060b1bafc3d627d48 100644 (file)
@@ -171,12 +171,73 @@ void mcpm_cpu_suspend(u64 expected_residency);
 int mcpm_cpu_powered_up(void);
 
 /*
- * Platform specific methods used in the implementation of the above API.
+ * Platform specific callbacks used in the implementation of the above API.
+ *
+ * cpu_powerup:
+ * Make given CPU runable. Called with MCPM lock held and IRQs disabled.
+ * The given cluster is assumed to be set up (cluster_powerup would have
+ * been called beforehand). Must return 0 for success or negative error code.
+ *
+ * cluster_powerup:
+ * Set up power for given cluster. Called with MCPM lock held and IRQs
+ * disabled. Called before first cpu_powerup when cluster is down. Must
+ * return 0 for success or negative error code.
+ *
+ * cpu_suspend_prepare:
+ * Special suspend configuration. Called on target CPU with MCPM lock held
+ * and IRQs disabled. This callback is optional. If provided, it is called
+ * before cpu_powerdown_prepare.
+ *
+ * cpu_powerdown_prepare:
+ * Configure given CPU for power down. Called on target CPU with MCPM lock
+ * held and IRQs disabled. Power down must be effective only at the next WFI instruction.
+ *
+ * cluster_powerdown_prepare:
+ * Configure given cluster for power down. Called on one CPU from target
+ * cluster with MCPM lock held and IRQs disabled. A cpu_powerdown_prepare
+ * for each CPU in the cluster has happened when this occurs.
+ *
+ * cpu_cache_disable:
+ * Clean and disable CPU level cache for the calling CPU. Called on with IRQs
+ * disabled only. The CPU is no longer cache coherent with the rest of the
+ * system when this returns.
+ *
+ * cluster_cache_disable:
+ * Clean and disable the cluster wide cache as well as the CPU level cache
+ * for the calling CPU. No call to cpu_cache_disable will happen for this
+ * CPU. Called with IRQs disabled and only when all the other CPUs are done
+ * with their own cpu_cache_disable. The cluster is no longer cache coherent
+ * with the rest of the system when this returns.
+ *
+ * cpu_is_up:
+ * Called on given CPU after it has been powered up or resumed. The MCPM lock
+ * is held and IRQs disabled. This callback is optional.
+ *
+ * cluster_is_up:
+ * Called by the first CPU to be powered up or resumed in given cluster.
+ * The MCPM lock is held and IRQs disabled. This callback is optional. If
+ * provided, it is called before cpu_is_up for that CPU.
+ *
+ * wait_for_powerdown:
+ * Wait until given CPU is powered down. This is called in sleeping context.
+ * Some reasonable timeout must be considered. Must return 0 for success or
+ * negative error code.
  */
 struct mcpm_platform_ops {
+       int (*cpu_powerup)(unsigned int cpu, unsigned int cluster);
+       int (*cluster_powerup)(unsigned int cluster);
+       void (*cpu_suspend_prepare)(unsigned int cpu, unsigned int cluster);
+       void (*cpu_powerdown_prepare)(unsigned int cpu, unsigned int cluster);
+       void (*cluster_powerdown_prepare)(unsigned int cluster);
+       void (*cpu_cache_disable)(void);
+       void (*cluster_cache_disable)(void);
+       void (*cpu_is_up)(unsigned int cpu, unsigned int cluster);
+       void (*cluster_is_up)(unsigned int cluster);
+       int (*wait_for_powerdown)(unsigned int cpu, unsigned int cluster);
+
+       /* deprecated callbacks */
        int (*power_up)(unsigned int cpu, unsigned int cluster);
        void (*power_down)(void);
-       int (*wait_for_powerdown)(unsigned int cpu, unsigned int cluster);
        void (*suspend)(u64);
        void (*powered_up)(void);
 };
index 2f7e6ff67d51556218dbc4e9858442da6601df81..0b579b2f4e0e6490bb396c301cd2adf433e3b1ad 100644 (file)
@@ -110,5 +110,6 @@ static inline bool set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 bool xen_arch_need_swiotlb(struct device *dev,
                           unsigned long pfn,
                           unsigned long mfn);
+unsigned long xen_get_swiotlb_free_pages(unsigned int order);
 
 #endif /* _ASM_ARM_XEN_PAGE_H */
index e55a9426b49676f838663c2b6164266da7fef5e9..b03024fa671f41cebc5a0bf728b1a30fe1ad571d 100644 (file)
  */
 
        .macro  addruart, rp, rv, tmp
-#ifdef CONFIG_DEBUG_UART_PHYS
        ldr     \rp, =CONFIG_DEBUG_UART_PHYS
        ldr     \rv, =CONFIG_DEBUG_UART_VIRT
-#endif
        .endm
 
        .macro  senduart, rd, rx
 ARM_BE8(rev    \rd, \rd )
-#ifdef CONFIG_DEBUG_QCOM_UARTDM
        @ Write the 1 character to UARTDM_TF
        str     \rd, [\rx, #0x70]
-#else
-       str     \rd, [\rx, #0x0C]
-#endif
        .endm
 
        .macro  waituart, rd, rx
-#ifdef CONFIG_DEBUG_QCOM_UARTDM
        @ check for TX_EMT in UARTDM_SR
        ldr     \rd, [\rx, #0x08]
 ARM_BE8(rev     \rd, \rd )
@@ -55,13 +48,6 @@ ARM_BE8(rev     \rd, \rd )
        str     \rd, [\rx, #0x40]
        @ UARTDM reg. Read to induce delay
        ldr     \rd, [\rx, #0x08]
-#else
-       @ wait for TX_READY
-1001:  ldr     \rd, [\rx, #0x08]
-ARM_BE8(rev     \rd, \rd )
-       tst     \rd, #0x04
-       beq     1001b
-#endif
        .endm
 
        .macro  busyuart, rd, rx
index 2499867dd0d86d79477e85ac0933228b9bbcf6a2..df3f60cb1168aff33ed9c2df530439ccfedb1a72 100644 (file)
@@ -195,8 +195,14 @@ struct kvm_arch_memory_slot {
 #define KVM_ARM_IRQ_CPU_IRQ            0
 #define KVM_ARM_IRQ_CPU_FIQ            1
 
-/* Highest supported SPI, from VGIC_NR_IRQS */
+/*
+ * This used to hold the highest supported SPI, but it is now obsolete
+ * and only here to provide source code level compatibility with older
+ * userland. The highest SPI number can be set via KVM_DEV_ARM_VGIC_GRP_NR_IRQS.
+ */
+#ifndef __KERNEL__
 #define KVM_ARM_IRQ_GIC_MAX            127
+#endif
 
 /* One single KVM irqchip, ie. the VGIC */
 #define KVM_NR_IRQCHIPS          1
index cc176b67c13487b080bf7d1dc430314496a8b9b1..aebfbf79a1a3f5f2a98981e5abca8657634cb7c6 100644 (file)
@@ -80,9 +80,9 @@ ENTRY(stext)
        ldr     r13, =__mmap_switched           @ address to jump to after
                                                @ initialising sctlr
        adr     lr, BSYM(1f)                    @ return (PIC) address
- ARM(  add     pc, r10, #PROCINFO_INITFUNC     )
- THUMB(        add     r12, r10, #PROCINFO_INITFUNC    )
- THUMB(        ret     r12                             )
+       ldr     r12, [r10, #PROCINFO_INITFUNC]
+       add     r12, r12, r10
+       ret     r12
  1:    b       __after_proc_init
 ENDPROC(stext)
 
@@ -117,9 +117,9 @@ ENTRY(secondary_startup)
 
        adr     lr, BSYM(__after_proc_init)     @ return address
        mov     r13, r12                        @ __secondary_switched address
- ARM(  add     pc, r10, #PROCINFO_INITFUNC     )
- THUMB(        add     r12, r10, #PROCINFO_INITFUNC    )
- THUMB(        ret     r12                             )
+       ldr     r12, [r10, #PROCINFO_INITFUNC]
+       add     r12, r12, r10
+       ret     r12
 ENDPROC(secondary_startup)
 
 ENTRY(__secondary_switched)
index 6f536451ab784e99966a308c0892e8614214591f..d9631ecddd56ea09a9b9f922520e2e05576c974a 100644 (file)
@@ -671,8 +671,7 @@ int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level,
                if (!irqchip_in_kernel(kvm))
                        return -ENXIO;
 
-               if (irq_num < VGIC_NR_PRIVATE_IRQS ||
-                   irq_num > KVM_ARM_IRQ_GIC_MAX)
+               if (irq_num < VGIC_NR_PRIVATE_IRQS)
                        return -EINVAL;
 
                return kvm_vgic_inject_irq(kvm, 0, irq_num, level);
diff --git a/arch/arm/mach-alpine/Kconfig b/arch/arm/mach-alpine/Kconfig
new file mode 100644 (file)
index 0000000..2c44b93
--- /dev/null
@@ -0,0 +1,12 @@
+config ARCH_ALPINE
+       bool "Annapurna Labs Alpine platform" if ARCH_MULTI_V7
+       select ARM_AMBA
+       select ARM_GIC
+       select GENERIC_IRQ_CHIP
+       select HAVE_ARM_ARCH_TIMER
+       select HAVE_SMP
+       select MFD_SYSCON
+       select PCI
+       select PCI_HOST_GENERIC
+       help
+         This enables support for the Annapurna Labs Alpine V1 boards.
diff --git a/arch/arm/mach-alpine/Makefile b/arch/arm/mach-alpine/Makefile
new file mode 100644 (file)
index 0000000..b667489
--- /dev/null
@@ -0,0 +1,2 @@
+obj-y                          += alpine_machine.o
+obj-$(CONFIG_SMP)              += platsmp.o alpine_cpu_pm.o
diff --git a/arch/arm/mach-alpine/alpine_cpu_pm.c b/arch/arm/mach-alpine/alpine_cpu_pm.c
new file mode 100644 (file)
index 0000000..121c77c
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Low-level power-management support for Alpine platform.
+ *
+ * Copyright (C) 2015 Annapurna Labs 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/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+#include "alpine_cpu_pm.h"
+#include "alpine_cpu_resume.h"
+
+/* NB registers */
+#define AL_SYSFAB_POWER_CONTROL(cpu)   (0x2000 + (cpu)*0x100 + 0x20)
+
+static struct regmap *al_sysfabric;
+static struct al_cpu_resume_regs __iomem *al_cpu_resume_regs;
+static int wakeup_supported;
+
+int alpine_cpu_wakeup(unsigned int phys_cpu, uint32_t phys_resume_addr)
+{
+       if (!wakeup_supported)
+               return -ENOSYS;
+
+       /*
+        * Set CPU resume address -
+        * secure firmware running on boot will jump to this address
+        * after setting proper CPU mode, and initialiing e.g. secure
+        * regs (the same mode all CPUs are booted to - usually HYP)
+        */
+       writel(phys_resume_addr,
+              &al_cpu_resume_regs->per_cpu[phys_cpu].resume_addr);
+
+       /* Power-up the CPU */
+       regmap_write(al_sysfabric, AL_SYSFAB_POWER_CONTROL(phys_cpu), 0);
+
+       return 0;
+}
+
+void __init alpine_cpu_pm_init(void)
+{
+       struct device_node *np;
+       uint32_t watermark;
+
+       al_sysfabric = syscon_regmap_lookup_by_compatible("al,alpine-sysfabric-service");
+
+       np = of_find_compatible_node(NULL, NULL, "al,alpine-cpu-resume");
+       al_cpu_resume_regs = of_iomap(np, 0);
+
+       wakeup_supported = !IS_ERR(al_sysfabric) && al_cpu_resume_regs;
+
+       if (wakeup_supported) {
+               watermark = readl(&al_cpu_resume_regs->watermark);
+               wakeup_supported = (watermark & AL_CPU_RESUME_MAGIC_NUM_MASK)
+                                   == AL_CPU_RESUME_MAGIC_NUM;
+       }
+}
diff --git a/arch/arm/mach-alpine/alpine_cpu_pm.h b/arch/arm/mach-alpine/alpine_cpu_pm.h
new file mode 100644 (file)
index 0000000..5179e69
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Low-level power-management support for Alpine platform.
+ *
+ * Copyright (C) 2015 Annapurna Labs 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.
+ */
+
+#ifndef __ALPINE_CPU_PM_H__
+#define __ALPINE_CPU_PM_H__
+
+/* Alpine CPU Power Management Services Initialization */
+void alpine_cpu_pm_init(void);
+
+/* Wake-up a CPU */
+int alpine_cpu_wakeup(unsigned int phys_cpu, uint32_t phys_resume_addr);
+
+#endif /* __ALPINE_CPU_PM_H__ */
diff --git a/arch/arm/mach-alpine/alpine_cpu_resume.h b/arch/arm/mach-alpine/alpine_cpu_resume.h
new file mode 100644 (file)
index 0000000..c80150c
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Annapurna labs cpu-resume register structure.
+ *
+ * Copyright (C) 2015 Annapurna Labs 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.
+ */
+
+#ifndef ALPINE_CPU_RESUME_H_
+#define ALPINE_CPU_RESUME_H_
+
+/* Per-cpu regs */
+struct al_cpu_resume_regs_per_cpu {
+       uint32_t        flags;
+       uint32_t        resume_addr;
+};
+
+/* general regs */
+struct al_cpu_resume_regs {
+       /* Watermark for validating the CPU resume struct */
+       uint32_t watermark;
+       uint32_t flags;
+       struct al_cpu_resume_regs_per_cpu per_cpu[];
+};
+
+/* The expected magic number for validating the resume addresses */
+#define AL_CPU_RESUME_MAGIC_NUM                0xf0e1d200
+#define AL_CPU_RESUME_MAGIC_NUM_MASK   0xffffff00
+
+#endif /* ALPINE_CPU_RESUME_H_ */
diff --git a/arch/arm/mach-alpine/alpine_machine.c b/arch/arm/mach-alpine/alpine_machine.c
new file mode 100644 (file)
index 0000000..b8e2145
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Machine declaration for Alpine platforms.
+ *
+ * Copyright (C) 2015 Annapurna Labs 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/of_platform.h>
+
+#include <asm/mach/arch.h>
+
+static const char * const al_match[] __initconst = {
+       "al,alpine",
+       NULL,
+};
+
+DT_MACHINE_START(AL_DT, "Annapurna Labs Alpine")
+       .dt_compat      = al_match,
+MACHINE_END
diff --git a/arch/arm/mach-alpine/platsmp.c b/arch/arm/mach-alpine/platsmp.c
new file mode 100644 (file)
index 0000000..f78429f
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * SMP operations for Alpine platform.
+ *
+ * Copyright (C) 2015 Annapurna Labs 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/init.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/of.h>
+
+#include <asm/smp_plat.h>
+
+#include "alpine_cpu_pm.h"
+
+static int alpine_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+       phys_addr_t addr;
+
+       addr = virt_to_phys(secondary_startup);
+
+       if (addr > (phys_addr_t)(uint32_t)(-1)) {
+               pr_err("FAIL: resume address over 32bit (%pa)", &addr);
+               return -EINVAL;
+       }
+
+       return alpine_cpu_wakeup(cpu_logical_map(cpu), (uint32_t)addr);
+}
+
+static void __init alpine_smp_prepare_cpus(unsigned int max_cpus)
+{
+       alpine_cpu_pm_init();
+}
+
+static struct smp_operations alpine_smp_ops __initdata = {
+       .smp_prepare_cpus       = alpine_smp_prepare_cpus,
+       .smp_boot_secondary     = alpine_boot_secondary,
+};
+CPU_METHOD_OF_DECLARE(alpine_smp, "al,alpine-smp", &alpine_smp_ops);
index c74a44324e5bc3dc7cb4b5e0f31e64ca8c167f5f..fd95f34945f4826610ac810180456687abbb71bf 100644 (file)
@@ -1,55 +1,15 @@
-if ARCH_AT91
-
-config HAVE_AT91_UTMI
-       bool
-
-config HAVE_AT91_USB_CLK
-       bool
-
-config COMMON_CLK_AT91
-       bool
-       select COMMON_CLK
-
-config HAVE_AT91_SMD
-       bool
-
-config HAVE_AT91_H32MX
-       bool
-
-config SOC_SAMA5
-       bool
-       select ATMEL_AIC5_IRQ
+menuconfig ARCH_AT91
+       bool "Atmel SoCs"
+       depends on ARCH_MULTI_V4T || ARCH_MULTI_V5 || ARCH_MULTI_V7
+       select ARCH_REQUIRE_GPIOLIB
        select COMMON_CLK_AT91
-       select CPU_V7
-       select GENERIC_CLOCKEVENTS
-       select MEMORY
-       select ATMEL_SDRAMC
-       select PHYLIB if NETDEVICES
-
-menu "Atmel AT91 System-on-Chip"
-
-choice
-
-       prompt "Core type"
-
-config SOC_SAM_V4_V5
-       bool "ARM9 AT91SAM9/AT91RM9200"
-       help
-         Select this if you are using one of Atmel's AT91SAM9 or
-         AT91RM9200 SoC.
-
-config SOC_SAM_V7
-       bool "Cortex A5"
-       help
-         Select this if you are using one of Atmel's SAMA5D3 SoC.
-
-endchoice
+       select PINCTRL
+       select PINCTRL_AT91
+       select SOC_BUS
 
-comment "Atmel AT91 Processor"
-
-if SOC_SAM_V7
+if ARCH_AT91
 config SOC_SAMA5D3
-       bool "SAMA5D3 family"
+       bool "SAMA5D3 family" if ARCH_MULTI_V7
        select SOC_SAMA5
        select HAVE_FB_ATMEL
        select HAVE_AT91_UTMI
@@ -60,9 +20,8 @@ config SOC_SAMA5D3
          This support covers SAMA5D31, SAMA5D33, SAMA5D34, SAMA5D35, SAMA5D36.
 
 config SOC_SAMA5D4
-       bool "SAMA5D4 family"
+       bool "SAMA5D4 family" if ARCH_MULTI_V7
        select SOC_SAMA5
-       select CLKSRC_MMIO
        select CACHE_L2X0
        select HAVE_FB_ATMEL
        select HAVE_AT91_UTMI
@@ -71,29 +30,31 @@ config SOC_SAMA5D4
        select HAVE_AT91_H32MX
        help
          Select this if you are using one of Atmel's SAMA5D4 family SoC.
-endif
 
-if SOC_SAM_V4_V5
 config SOC_AT91RM9200
-       bool "AT91RM9200"
+       bool "AT91RM9200" if ARCH_MULTI_V4T
        select ATMEL_AIC_IRQ
-       select COMMON_CLK_AT91
+       select ATMEL_ST
        select CPU_ARM920T
-       select GENERIC_CLOCKEVENTS
        select HAVE_AT91_USB_CLK
+       select MIGHT_HAVE_PCI
+       select SOC_SAM_V4_V5
+       select SRAM if PM
+       help
+         Select this if you are using Atmel's AT91RM9200 SoC.
 
 config SOC_AT91SAM9
-       bool "AT91SAM9"
+       bool "AT91SAM9" if ARCH_MULTI_V5
        select ATMEL_AIC_IRQ
        select ATMEL_SDRAMC
-       select COMMON_CLK_AT91
        select CPU_ARM926T
-       select GENERIC_CLOCKEVENTS
        select HAVE_AT91_SMD
        select HAVE_AT91_USB_CLK
        select HAVE_AT91_UTMI
        select HAVE_FB_ATMEL
        select MEMORY
+       select SOC_SAM_V4_V5
+       select SRAM if PM
        help
          Select this if you are using one of those Atmel SoC:
            AT91SAM9260
@@ -112,40 +73,35 @@ config SOC_AT91SAM9
            AT91SAM9X25
            AT91SAM9X35
            AT91SAM9XE
-endif # SOC_SAM_V4_V5
 
-comment "AT91 Feature Selections"
+config HAVE_AT91_UTMI
+       bool
 
-config AT91_SLOW_CLOCK
-       bool "Suspend-to-RAM disables main oscillator"
-       select SRAM
-       depends on SUSPEND
-       help
-         Select this if you want Suspend-to-RAM to save the most power
-         possible (without powering off the CPU) by disabling the PLLs
-         and main oscillator so that only the 32 KiHz clock is available.
+config HAVE_AT91_USB_CLK
+       bool
 
-         When only that slow-clock is available, some peripherals lose
-         functionality.  Many can't issue wakeup events unless faster
-         clocks are available.  Some lose their operating state and
-         need to be completely re-initialized.
+config COMMON_CLK_AT91
+       bool
+       select COMMON_CLK
 
-config AT91_TIMER_HZ
-       int "Kernel HZ (jiffies per second)"
-       range 32 1024
-       depends on ARCH_AT91
-       default "128" if SOC_AT91RM9200
-       default "100"
-       help
-         On AT91rm9200 chips where you're using a system clock derived
-         from the 32768 Hz hardware clock, this tick rate should divide
-         it exactly: use a power-of-two value, such as 128 or 256, to
-         reduce timing errors caused by rounding.
+config HAVE_AT91_SMD
+       bool
+
+config HAVE_AT91_H32MX
+       bool
 
-         On AT91sam926x chips, or otherwise when using a higher precision
-         system clock (of at least several MHz), rounding is less of a
-         problem so it can be safer to use a decimal values like 100.
+config SOC_SAM_V4_V5
+       bool
 
-endmenu
+config SOC_SAM_V7
+       bool
+
+config SOC_SAMA5
+       bool
+       select ATMEL_AIC5_IRQ
+       select ATMEL_SDRAMC
+       select MEMORY
+       select SOC_SAM_V7
+       select SRAM if PM
 
 endif
index 827fdbcce1c7a69c1a8372db97c99e90e3019452..4fa8b4541e64fa06836c29863a574233a97227c8 100644 (file)
@@ -1,20 +1,25 @@
 #
 # Makefile for the linux kernel.
 #
+ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include
+asflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include
 
-obj-y          := setup.o
+obj-y          := soc.o
 
 obj-$(CONFIG_SOC_AT91SAM9)     += sam9_smc.o
 
 # CPU-specific support
-obj-$(CONFIG_SOC_AT91RM9200)   += at91rm9200.o at91rm9200_time.o
+obj-$(CONFIG_SOC_AT91RM9200)   += at91rm9200.o
 obj-$(CONFIG_SOC_AT91SAM9)     += at91sam9.o
 obj-$(CONFIG_SOC_SAMA5)                += sama5.o
 
 # Power Management
 obj-$(CONFIG_PM)               += pm.o
-obj-$(CONFIG_AT91_SLOW_CLOCK)  += pm_slowclock.o
+obj-$(CONFIG_PM)               += pm_suspend.o
 
+ifeq ($(CONFIG_CPU_V7),y)
+AFLAGS_pm_suspend.o := -march=armv7-a
+endif
 ifeq ($(CONFIG_PM_DEBUG),y)
 CFLAGS_pm.o += -DDEBUG
 endif
index 8fcfb70f712456e66a26e871dc6f524546980913..eaf58f88ef5dcd262a862e96b0656b03a31cf8b3 100644 (file)
@@ -8,60 +8,42 @@
  * Licensed under GPLv2 or later.
  */
 
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/gpio.h>
+#include <linux/clk-provider.h>
 #include <linux/of.h>
-#include <linux/of_irq.h>
 #include <linux/of_platform.h>
-#include <linux/clk-provider.h>
 
-#include <asm/setup.h>
-#include <asm/irq.h>
 #include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
 #include <asm/system_misc.h>
 
-#include <mach/at91_st.h>
-
 #include "generic.h"
+#include "soc.h"
 
-static void at91rm9200_restart(enum reboot_mode reboot_mode, const char *cmd)
-{
-       /*
-        * Perform a hardware reset with the use of the Watchdog timer.
-        */
-       at91_st_write(AT91_ST_WDMR, AT91_ST_RSTEN | AT91_ST_EXTEN | 1);
-       at91_st_write(AT91_ST_CR, AT91_ST_WDRST);
-}
-
-static void __init at91rm9200_dt_timer_init(void)
-{
-       of_clk_init(NULL);
-       at91rm9200_timer_init();
-}
+static const struct at91_soc rm9200_socs[] = {
+       AT91_SOC(AT91RM9200_CIDR_MATCH, 0, "at91rm9200 BGA", "at91rm9200"),
+       { /* sentinel */ },
+};
 
 static void __init at91rm9200_dt_device_init(void)
 {
-       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+       struct soc_device *soc;
+       struct device *soc_dev = NULL;
+
+       soc = at91_soc_init(rm9200_socs);
+       if (soc != NULL)
+               soc_dev = soc_device_to_device(soc);
+
+       of_platform_populate(NULL, of_default_bus_match_table, NULL, soc_dev);
 
        arm_pm_idle = at91rm9200_idle;
-       arm_pm_restart = at91rm9200_restart;
        at91rm9200_pm_init();
 }
 
-
-
 static const char *at91rm9200_dt_board_compat[] __initconst = {
        "atmel,at91rm9200",
        NULL
 };
 
 DT_MACHINE_START(at91rm9200_dt, "Atmel AT91RM9200")
-       .init_time      = at91rm9200_dt_timer_init,
-       .map_io         = at91_map_io,
        .init_machine   = at91rm9200_dt_device_init,
        .dt_compat      = at91rm9200_dt_board_compat,
 MACHINE_END
diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c
deleted file mode 100644 (file)
index b00d095..0000000
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * linux/arch/arm/mach-at91/at91rm9200_time.c
- *
- *  Copyright (C) 2003 SAN People
- *  Copyright (C) 2003 ATMEL
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/clockchips.h>
-#include <linux/export.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-
-#include <asm/mach/time.h>
-
-#include <mach/at91_st.h>
-#include <mach/hardware.h>
-
-static unsigned long last_crtr;
-static u32 irqmask;
-static struct clock_event_device clkevt;
-
-#define RM9200_TIMER_LATCH     ((AT91_SLOW_CLOCK + HZ/2) / HZ)
-
-/*
- * The ST_CRTR is updated asynchronously to the master clock ... but
- * the updates as seen by the CPU don't seem to be strictly monotonic.
- * Waiting until we read the same value twice avoids glitching.
- */
-static inline unsigned long read_CRTR(void)
-{
-       unsigned long x1, x2;
-
-       x1 = at91_st_read(AT91_ST_CRTR);
-       do {
-               x2 = at91_st_read(AT91_ST_CRTR);
-               if (x1 == x2)
-                       break;
-               x1 = x2;
-       } while (1);
-       return x1;
-}
-
-/*
- * IRQ handler for the timer.
- */
-static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id)
-{
-       u32     sr = at91_st_read(AT91_ST_SR) & irqmask;
-
-       /*
-        * irqs should be disabled here, but as the irq is shared they are only
-        * guaranteed to be off if the timer irq is registered first.
-        */
-       WARN_ON_ONCE(!irqs_disabled());
-
-       /* simulate "oneshot" timer with alarm */
-       if (sr & AT91_ST_ALMS) {
-               clkevt.event_handler(&clkevt);
-               return IRQ_HANDLED;
-       }
-
-       /* periodic mode should handle delayed ticks */
-       if (sr & AT91_ST_PITS) {
-               u32     crtr = read_CRTR();
-
-               while (((crtr - last_crtr) & AT91_ST_CRTV) >= RM9200_TIMER_LATCH) {
-                       last_crtr += RM9200_TIMER_LATCH;
-                       clkevt.event_handler(&clkevt);
-               }
-               return IRQ_HANDLED;
-       }
-
-       /* this irq is shared ... */
-       return IRQ_NONE;
-}
-
-static struct irqaction at91rm9200_timer_irq = {
-       .name           = "at91_tick",
-       .flags          = IRQF_SHARED | IRQF_TIMER | IRQF_IRQPOLL,
-       .handler        = at91rm9200_timer_interrupt,
-       .irq            = NR_IRQS_LEGACY + AT91_ID_SYS,
-};
-
-static cycle_t read_clk32k(struct clocksource *cs)
-{
-       return read_CRTR();
-}
-
-static struct clocksource clk32k = {
-       .name           = "32k_counter",
-       .rating         = 150,
-       .read           = read_clk32k,
-       .mask           = CLOCKSOURCE_MASK(20),
-       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-static void
-clkevt32k_mode(enum clock_event_mode mode, struct clock_event_device *dev)
-{
-       /* Disable and flush pending timer interrupts */
-       at91_st_write(AT91_ST_IDR, AT91_ST_PITS | AT91_ST_ALMS);
-       at91_st_read(AT91_ST_SR);
-
-       last_crtr = read_CRTR();
-       switch (mode) {
-       case CLOCK_EVT_MODE_PERIODIC:
-               /* PIT for periodic irqs; fixed rate of 1/HZ */
-               irqmask = AT91_ST_PITS;
-               at91_st_write(AT91_ST_PIMR, RM9200_TIMER_LATCH);
-               break;
-       case CLOCK_EVT_MODE_ONESHOT:
-               /* ALM for oneshot irqs, set by next_event()
-                * before 32 seconds have passed
-                */
-               irqmask = AT91_ST_ALMS;
-               at91_st_write(AT91_ST_RTAR, last_crtr);
-               break;
-       case CLOCK_EVT_MODE_SHUTDOWN:
-       case CLOCK_EVT_MODE_UNUSED:
-       case CLOCK_EVT_MODE_RESUME:
-               irqmask = 0;
-               break;
-       }
-       at91_st_write(AT91_ST_IER, irqmask);
-}
-
-static int
-clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev)
-{
-       u32             alm;
-       int             status = 0;
-
-       BUG_ON(delta < 2);
-
-       /* The alarm IRQ uses absolute time (now+delta), not the relative
-        * time (delta) in our calling convention.  Like all clockevents
-        * using such "match" hardware, we have a race to defend against.
-        *
-        * Our defense here is to have set up the clockevent device so the
-        * delta is at least two.  That way we never end up writing RTAR
-        * with the value then held in CRTR ... which would mean the match
-        * wouldn't trigger until 32 seconds later, after CRTR wraps.
-        */
-       alm = read_CRTR();
-
-       /* Cancel any pending alarm; flush any pending IRQ */
-       at91_st_write(AT91_ST_RTAR, alm);
-       at91_st_read(AT91_ST_SR);
-
-       /* Schedule alarm by writing RTAR. */
-       alm += delta;
-       at91_st_write(AT91_ST_RTAR, alm);
-
-       return status;
-}
-
-static struct clock_event_device clkevt = {
-       .name           = "at91_tick",
-       .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-       .rating         = 150,
-       .set_next_event = clkevt32k_next_event,
-       .set_mode       = clkevt32k_mode,
-};
-
-void __iomem *at91_st_base;
-EXPORT_SYMBOL_GPL(at91_st_base);
-
-static const struct of_device_id at91rm9200_st_timer_ids[] = {
-       { .compatible = "atmel,at91rm9200-st" },
-       { /* sentinel */ }
-};
-
-static int __init of_at91rm9200_st_init(void)
-{
-       struct device_node *np;
-       int ret;
-
-       np = of_find_matching_node(NULL, at91rm9200_st_timer_ids);
-       if (!np)
-               goto err;
-
-       at91_st_base = of_iomap(np, 0);
-       if (!at91_st_base)
-               goto node_err;
-
-       /* Get the interrupts property */
-       ret = irq_of_parse_and_map(np, 0);
-       if (!ret)
-               goto ioremap_err;
-       at91rm9200_timer_irq.irq = ret;
-
-       of_node_put(np);
-
-       return 0;
-
-ioremap_err:
-       iounmap(at91_st_base);
-node_err:
-       of_node_put(np);
-err:
-       return -EINVAL;
-}
-
-/*
- * ST (system timer) module supports both clockevents and clocksource.
- */
-void __init at91rm9200_timer_init(void)
-{
-       /* For device tree enabled device: initialize here */
-       of_at91rm9200_st_init();
-
-       /* Disable all timer interrupts, and clear any pending ones */
-       at91_st_write(AT91_ST_IDR,
-               AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS);
-       at91_st_read(AT91_ST_SR);
-
-       /* Make IRQs happen for the system timer */
-       setup_irq(at91rm9200_timer_irq.irq, &at91rm9200_timer_irq);
-
-       /* The 32KiHz "Slow Clock" (tick every 30517.58 nanoseconds) is used
-        * directly for the clocksource and all clockevents, after adjusting
-        * its prescaler from the 1 Hz default.
-        */
-       at91_st_write(AT91_ST_RTMR, 1);
-
-       /* Setup timer clockevent, with minimum of two ticks (important!!) */
-       clkevt.cpumask = cpumask_of(0);
-       clockevents_config_and_register(&clkevt, AT91_SLOW_CLOCK,
-                                       2, AT91_ST_ALMV);
-
-       /* register clocksource */
-       clocksource_register_hz(&clk32k, AT91_SLOW_CLOCK);
-}
index 56e3ba73ec407727eb0c2746b2f88c9edbe4b39a..e47a2093a0e723a1ef477dfc9954798f130b00f7 100644 (file)
@@ -7,29 +7,68 @@
  * Licensed under GPLv2 or later.
  */
 
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/gpio.h>
 #include <linux/of.h>
-#include <linux/of_irq.h>
 #include <linux/of_platform.h>
-#include <linux/clk-provider.h>
 
-#include <asm/system_misc.h>
-#include <asm/setup.h>
-#include <asm/irq.h>
 #include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
+#include <asm/system_misc.h>
 
 #include "generic.h"
+#include "soc.h"
 
-static void __init at91sam9_dt_device_init(void)
+static const struct at91_soc at91sam9_socs[] = {
+       AT91_SOC(AT91SAM9260_CIDR_MATCH, 0, "at91sam9260", NULL),
+       AT91_SOC(AT91SAM9261_CIDR_MATCH, 0, "at91sam9261", NULL),
+       AT91_SOC(AT91SAM9263_CIDR_MATCH, 0, "at91sam9263", NULL),
+       AT91_SOC(AT91SAM9G20_CIDR_MATCH, 0, "at91sam9g20", NULL),
+       AT91_SOC(AT91SAM9RL64_CIDR_MATCH, 0, "at91sam9rl64", NULL),
+       AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9M11_EXID_MATCH,
+                "at91sam9m11", "at91sam9g45"),
+       AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9M10_EXID_MATCH,
+                "at91sam9m10", "at91sam9g45"),
+       AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9G46_EXID_MATCH,
+                "at91sam9g46", "at91sam9g45"),
+       AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9G45_EXID_MATCH,
+                "at91sam9g45", "at91sam9g45"),
+       AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G15_EXID_MATCH,
+                "at91sam9g15", "at91sam9x5"),
+       AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G35_EXID_MATCH,
+                "at91sam9g35", "at91sam9x5"),
+       AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9X35_EXID_MATCH,
+                "at91sam9x35", "at91sam9x5"),
+       AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G25_EXID_MATCH,
+                "at91sam9g25", "at91sam9x5"),
+       AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9X25_EXID_MATCH,
+                "at91sam9x25", "at91sam9x5"),
+       AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9CN12_EXID_MATCH,
+                "at91sam9cn12", "at91sam9n12"),
+       AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9N12_EXID_MATCH,
+                "at91sam9n12", "at91sam9n12"),
+       AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9CN11_EXID_MATCH,
+                "at91sam9cn11", "at91sam9n12"),
+       AT91_SOC(AT91SAM9XE128_CIDR_MATCH, 0, "at91sam9xe128", "at91sam9xe128"),
+       AT91_SOC(AT91SAM9XE256_CIDR_MATCH, 0, "at91sam9xe256", "at91sam9xe256"),
+       AT91_SOC(AT91SAM9XE512_CIDR_MATCH, 0, "at91sam9xe512", "at91sam9xe512"),
+       { /* sentinel */ },
+};
+
+static void __init at91sam9_common_init(void)
 {
-       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+       struct soc_device *soc;
+       struct device *soc_dev = NULL;
+
+       soc = at91_soc_init(at91sam9_socs);
+       if (soc != NULL)
+               soc_dev = soc_device_to_device(soc);
+
+       of_platform_populate(NULL, of_default_bus_match_table, NULL, soc_dev);
 
        arm_pm_idle = at91sam9_idle;
+}
+
+static void __init at91sam9_dt_device_init(void)
+{
+       at91sam9_common_init();
        at91sam9260_pm_init();
 }
 
@@ -40,16 +79,13 @@ static const char *at91_dt_board_compat[] __initconst = {
 
 DT_MACHINE_START(at91sam_dt, "Atmel AT91SAM9")
        /* Maintainer: Atmel */
-       .map_io         = at91_map_io,
        .init_machine   = at91sam9_dt_device_init,
        .dt_compat      = at91_dt_board_compat,
 MACHINE_END
 
 static void __init at91sam9g45_dt_device_init(void)
 {
-       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-
-       arm_pm_idle = at91sam9_idle;
+       at91sam9_common_init();
        at91sam9g45_pm_init();
 }
 
@@ -60,16 +96,13 @@ static const char *at91sam9g45_board_compat[] __initconst = {
 
 DT_MACHINE_START(at91sam9g45_dt, "Atmel AT91SAM9G45")
        /* Maintainer: Atmel */
-       .map_io         = at91_map_io,
        .init_machine   = at91sam9g45_dt_device_init,
        .dt_compat      = at91sam9g45_board_compat,
 MACHINE_END
 
 static void __init at91sam9x5_dt_device_init(void)
 {
-       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-
-       arm_pm_idle = at91sam9_idle;
+       at91sam9_common_init();
        at91sam9x5_pm_init();
 }
 
@@ -81,7 +114,6 @@ static const char *at91sam9x5_board_compat[] __initconst = {
 
 DT_MACHINE_START(at91sam9x5_dt, "Atmel AT91SAM9")
        /* Maintainer: Atmel */
-       .map_io         = at91_map_io,
        .init_machine   = at91sam9x5_dt_device_init,
        .dt_compat      = at91sam9x5_board_compat,
 MACHINE_END
index 583369ffc284d5588b4c7f4c742cedbefb7614f3..b0fa7dc7286d9dc120a79c77be70fe0adb365910 100644 (file)
 extern void __init at91_map_io(void);
 extern void __init at91_alt_map_io(void);
 
- /* Timer */
-extern void at91rm9200_timer_init(void);
-
 /* idle */
 extern void at91rm9200_idle(void);
 extern void at91sam9_idle(void);
 
-/* Matrix */
-extern void at91_ioremap_matrix(u32 base_addr);
-
-
 #ifdef CONFIG_PM
 extern void __init at91rm9200_pm_init(void);
 extern void __init at91sam9260_pm_init(void);
diff --git a/arch/arm/mach-at91/include/mach/at91_dbgu.h b/arch/arm/mach-at91/include/mach/at91_dbgu.h
deleted file mode 100644 (file)
index 42925e8..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91_dbgu.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * Debug Unit (DBGU) - System peripherals registers.
- * Based on AT91RM9200 datasheet revision E.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef AT91_DBGU_H
-#define AT91_DBGU_H
-
-#define AT91_DBGU_CR           (0x00)  /* Control Register */
-#define AT91_DBGU_MR           (0x04)  /* Mode Register */
-#define AT91_DBGU_IER          (0x08)  /* Interrupt Enable Register */
-#define                AT91_DBGU_TXRDY         (1 << 1)                /* Transmitter Ready */
-#define                AT91_DBGU_TXEMPTY       (1 << 9)                /* Transmitter Empty */
-#define AT91_DBGU_IDR          (0x0c)  /* Interrupt Disable Register */
-#define AT91_DBGU_IMR          (0x10)  /* Interrupt Mask Register */
-#define AT91_DBGU_SR           (0x14)  /* Status Register */
-#define AT91_DBGU_RHR          (0x18)  /* Receiver Holding Register */
-#define AT91_DBGU_THR          (0x1c)  /* Transmitter Holding Register */
-#define AT91_DBGU_BRGR         (0x20)  /* Baud Rate Generator Register */
-
-#define AT91_DBGU_CIDR         (0x40)  /* Chip ID Register */
-#define AT91_DBGU_EXID         (0x44)  /* Chip ID Extension Register */
-#define AT91_DBGU_FNR          (0x48)  /* Force NTRST Register [SAM9 only] */
-#define                AT91_DBGU_FNTRST        (1 << 0)                /* Force NTRST */
-
-/*
- * Some AT91 parts that don't have full DEBUG units still support the ID
- * and extensions register.
- */
-#define                AT91_CIDR_VERSION       (0x1f << 0)             /* Version of the Device */
-#define                AT91_CIDR_EPROC         (7    << 5)             /* Embedded Processor */
-#define                AT91_CIDR_NVPSIZ        (0xf  << 8)             /* Nonvolatile Program Memory Size */
-#define                AT91_CIDR_NVPSIZ2       (0xf  << 12)            /* Second Nonvolatile Program Memory Size */
-#define                AT91_CIDR_SRAMSIZ       (0xf  << 16)            /* Internal SRAM Size */
-#define                        AT91_CIDR_SRAMSIZ_1K    (1 << 16)
-#define                        AT91_CIDR_SRAMSIZ_2K    (2 << 16)
-#define                        AT91_CIDR_SRAMSIZ_112K  (4 << 16)
-#define                        AT91_CIDR_SRAMSIZ_4K    (5 << 16)
-#define                        AT91_CIDR_SRAMSIZ_80K   (6 << 16)
-#define                        AT91_CIDR_SRAMSIZ_160K  (7 << 16)
-#define                        AT91_CIDR_SRAMSIZ_8K    (8 << 16)
-#define                        AT91_CIDR_SRAMSIZ_16K   (9 << 16)
-#define                        AT91_CIDR_SRAMSIZ_32K   (10 << 16)
-#define                        AT91_CIDR_SRAMSIZ_64K   (11 << 16)
-#define                        AT91_CIDR_SRAMSIZ_128K  (12 << 16)
-#define                        AT91_CIDR_SRAMSIZ_256K  (13 << 16)
-#define                        AT91_CIDR_SRAMSIZ_96K   (14 << 16)
-#define                        AT91_CIDR_SRAMSIZ_512K  (15 << 16)
-#define                AT91_CIDR_ARCH          (0xff << 20)            /* Architecture Identifier */
-#define                AT91_CIDR_NVPTYP        (7    << 28)            /* Nonvolatile Program Memory Type */
-#define                AT91_CIDR_EXT           (1    << 31)            /* Extension Flag */
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/at91_matrix.h b/arch/arm/mach-at91/include/mach/at91_matrix.h
deleted file mode 100644 (file)
index f8996c9..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
- *
- * Under GPLv2
- */
-
-#ifndef __MACH_AT91_MATRIX_H__
-#define __MACH_AT91_MATRIX_H__
-
-#ifndef __ASSEMBLY__
-extern void __iomem *at91_matrix_base;
-
-#define at91_matrix_read(field) \
-       __raw_readl(at91_matrix_base + field)
-
-#define at91_matrix_write(field, value) \
-       __raw_writel(value, at91_matrix_base + field)
-
-#else
-.extern at91_matrix_base
-#endif
-
-#endif /* __MACH_AT91_MATRIX_H__ */
index e4492b151fee6b80b5bd9ec238d796e80437577a..493bc486e85834c0f6c37e82b772b833f95ffbb3 100644 (file)
@@ -21,10 +21,6 @@ extern void __iomem *at91_ramc_base[];
 .extern at91_ramc_base
 #endif
 
-#define AT91_MEMCTRL_MC                0
-#define AT91_MEMCTRL_SDRAMC    1
-#define AT91_MEMCTRL_DDRSDR    2
-
 #include <soc/at91/at91rm9200_sdramc.h>
 #include <soc/at91/at91sam9_ddrsdr.h>
 #include <soc/at91/at91sam9_sdramc.h>
diff --git a/arch/arm/mach-at91/include/mach/at91_st.h b/arch/arm/mach-at91/include/mach/at91_st.h
deleted file mode 100644 (file)
index 67fdbd1..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91_st.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * System Timer (ST) - System peripherals registers.
- * Based on AT91RM9200 datasheet revision E.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef AT91_ST_H
-#define AT91_ST_H
-
-#ifndef __ASSEMBLY__
-extern void __iomem *at91_st_base;
-
-#define at91_st_read(field) \
-       __raw_readl(at91_st_base + field)
-
-#define at91_st_write(field, value) \
-       __raw_writel(value, at91_st_base + field)
-#else
-.extern at91_st_base
-#endif
-
-#define        AT91_ST_CR              0x00                    /* Control Register */
-#define        AT91_ST_WDRST           (1 << 0)                /* Watchdog Timer Restart */
-
-#define        AT91_ST_PIMR            0x04                    /* Period Interval Mode Register */
-#define                AT91_ST_PIV             (0xffff <<  0)          /* Period Interval Value */
-
-#define        AT91_ST_WDMR            0x08                    /* Watchdog Mode Register */
-#define                AT91_ST_WDV             (0xffff <<  0)          /* Watchdog Counter Value */
-#define                AT91_ST_RSTEN           (1      << 16)          /* Reset Enable */
-#define                AT91_ST_EXTEN           (1      << 17)          /* External Signal Assertion Enable */
-
-#define        AT91_ST_RTMR            0x0c                    /* Real-time Mode Register */
-#define                AT91_ST_RTPRES          (0xffff <<  0)          /* Real-time Prescalar Value */
-
-#define        AT91_ST_SR              0x10                    /* Status Register */
-#define                AT91_ST_PITS            (1 << 0)                /* Period Interval Timer Status */
-#define                AT91_ST_WDOVF           (1 << 1)                /* Watchdog Overflow */
-#define                AT91_ST_RTTINC          (1 << 2)                /* Real-time Timer Increment */
-#define                AT91_ST_ALMS            (1 << 3)                /* Alarm Status */
-
-#define        AT91_ST_IER             0x14                    /* Interrupt Enable Register */
-#define        AT91_ST_IDR             0x18                    /* Interrupt Disable Register */
-#define        AT91_ST_IMR             0x1c                    /* Interrupt Mask Register */
-
-#define        AT91_ST_RTAR            0x20                    /* Real-time Alarm Register */
-#define                AT91_ST_ALMV            (0xfffff << 0)          /* Alarm Value */
-
-#define        AT91_ST_CRTR            0x24                    /* Current Real-time Register */
-#define                AT91_ST_CRTV            (0xfffff << 0)          /* Current Real-Time Value */
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/at91rm9200.h b/arch/arm/mach-at91/include/mach/at91rm9200.h
deleted file mode 100644 (file)
index e67317c..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91rm9200.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * Common definitions.
- * Based on AT91RM9200 datasheet revision E.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef AT91RM9200_H
-#define AT91RM9200_H
-
-/*
- * Peripheral identifiers/interrupts.
- */
-#define AT91RM9200_ID_PIOA     2       /* Parallel IO Controller A */
-#define AT91RM9200_ID_PIOB     3       /* Parallel IO Controller B */
-#define AT91RM9200_ID_PIOC     4       /* Parallel IO Controller C */
-#define AT91RM9200_ID_PIOD     5       /* Parallel IO Controller D */
-#define AT91RM9200_ID_US0      6       /* USART 0 */
-#define AT91RM9200_ID_US1      7       /* USART 1 */
-#define AT91RM9200_ID_US2      8       /* USART 2 */
-#define AT91RM9200_ID_US3      9       /* USART 3 */
-#define AT91RM9200_ID_MCI      10      /* Multimedia Card Interface */
-#define AT91RM9200_ID_UDP      11      /* USB Device Port */
-#define AT91RM9200_ID_TWI      12      /* Two-Wire Interface */
-#define AT91RM9200_ID_SPI      13      /* Serial Peripheral Interface */
-#define AT91RM9200_ID_SSC0     14      /* Serial Synchronous Controller 0 */
-#define AT91RM9200_ID_SSC1     15      /* Serial Synchronous Controller 1 */
-#define AT91RM9200_ID_SSC2     16      /* Serial Synchronous Controller 2 */
-#define AT91RM9200_ID_TC0      17      /* Timer Counter 0 */
-#define AT91RM9200_ID_TC1      18      /* Timer Counter 1 */
-#define AT91RM9200_ID_TC2      19      /* Timer Counter 2 */
-#define AT91RM9200_ID_TC3      20      /* Timer Counter 3 */
-#define AT91RM9200_ID_TC4      21      /* Timer Counter 4 */
-#define AT91RM9200_ID_TC5      22      /* Timer Counter 5 */
-#define AT91RM9200_ID_UHP      23      /* USB Host port */
-#define AT91RM9200_ID_EMAC     24      /* Ethernet MAC */
-#define AT91RM9200_ID_IRQ0     25      /* Advanced Interrupt Controller (IRQ0) */
-#define AT91RM9200_ID_IRQ1     26      /* Advanced Interrupt Controller (IRQ1) */
-#define AT91RM9200_ID_IRQ2     27      /* Advanced Interrupt Controller (IRQ2) */
-#define AT91RM9200_ID_IRQ3     28      /* Advanced Interrupt Controller (IRQ3) */
-#define AT91RM9200_ID_IRQ4     29      /* Advanced Interrupt Controller (IRQ4) */
-#define AT91RM9200_ID_IRQ5     30      /* Advanced Interrupt Controller (IRQ5) */
-#define AT91RM9200_ID_IRQ6     31      /* Advanced Interrupt Controller (IRQ6) */
-
-
-/*
- * Peripheral physical base addresses.
- */
-#define AT91RM9200_BASE_TCB0   0xfffa0000
-#define AT91RM9200_BASE_TC0    0xfffa0000
-#define AT91RM9200_BASE_TC1    0xfffa0040
-#define AT91RM9200_BASE_TC2    0xfffa0080
-#define AT91RM9200_BASE_TCB1   0xfffa4000
-#define AT91RM9200_BASE_TC3    0xfffa4000
-#define AT91RM9200_BASE_TC4    0xfffa4040
-#define AT91RM9200_BASE_TC5    0xfffa4080
-#define AT91RM9200_BASE_UDP    0xfffb0000
-#define AT91RM9200_BASE_MCI    0xfffb4000
-#define AT91RM9200_BASE_TWI    0xfffb8000
-#define AT91RM9200_BASE_EMAC   0xfffbc000
-#define AT91RM9200_BASE_US0    0xfffc0000
-#define AT91RM9200_BASE_US1    0xfffc4000
-#define AT91RM9200_BASE_US2    0xfffc8000
-#define AT91RM9200_BASE_US3    0xfffcc000
-#define AT91RM9200_BASE_SSC0   0xfffd0000
-#define AT91RM9200_BASE_SSC1   0xfffd4000
-#define AT91RM9200_BASE_SSC2   0xfffd8000
-#define AT91RM9200_BASE_SPI    0xfffe0000
-
-
-/*
- * System Peripherals
- */
-#define AT91RM9200_BASE_DBGU   AT91_BASE_DBGU0 /* Debug Unit */
-#define AT91RM9200_BASE_PIOA   0xfffff400      /* PIO Controller A */
-#define AT91RM9200_BASE_PIOB   0xfffff600      /* PIO Controller B */
-#define AT91RM9200_BASE_PIOC   0xfffff800      /* PIO Controller C */
-#define AT91RM9200_BASE_PIOD   0xfffffa00      /* PIO Controller D */
-#define AT91RM9200_BASE_ST     0xfffffd00      /* System Timer */
-#define AT91RM9200_BASE_RTC    0xfffffe00      /* Real-Time Clock */
-#define AT91RM9200_BASE_MC     0xffffff00      /* Memory Controllers */
-
-/*
- * Internal Memory.
- */
-#define AT91RM9200_ROM_BASE    0x00100000      /* Internal ROM base address */
-#define AT91RM9200_ROM_SIZE    SZ_128K         /* Internal ROM size (128Kb) */
-
-#define AT91RM9200_SRAM_BASE   0x00200000      /* Internal SRAM base address */
-#define AT91RM9200_SRAM_SIZE   SZ_16K          /* Internal SRAM size (16Kb) */
-
-#define AT91RM9200_UHP_BASE    0x00300000      /* USB Host controller */
-
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/at91sam9260.h b/arch/arm/mach-at91/include/mach/at91sam9260.h
deleted file mode 100644 (file)
index 416c7b6..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91sam9260.h
- *
- * (C) 2006 Andrew Victor
- *
- * Common definitions.
- * Based on AT91SAM9260 datasheet revision A (Preliminary).
- *
- * Includes also definitions for AT91SAM9XE and AT91SAM9G families
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 AT91SAM9260_H
-#define AT91SAM9260_H
-
-/*
- * Peripheral identifiers/interrupts.
- */
-#define AT91SAM9260_ID_PIOA    2       /* Parallel IO Controller A */
-#define AT91SAM9260_ID_PIOB    3       /* Parallel IO Controller B */
-#define AT91SAM9260_ID_PIOC    4       /* Parallel IO Controller C */
-#define AT91SAM9260_ID_ADC     5       /* Analog-to-Digital Converter */
-#define AT91SAM9260_ID_US0     6       /* USART 0 */
-#define AT91SAM9260_ID_US1     7       /* USART 1 */
-#define AT91SAM9260_ID_US2     8       /* USART 2 */
-#define AT91SAM9260_ID_MCI     9       /* Multimedia Card Interface */
-#define AT91SAM9260_ID_UDP     10      /* USB Device Port */
-#define AT91SAM9260_ID_TWI     11      /* Two-Wire Interface */
-#define AT91SAM9260_ID_SPI0    12      /* Serial Peripheral Interface 0 */
-#define AT91SAM9260_ID_SPI1    13      /* Serial Peripheral Interface 1 */
-#define AT91SAM9260_ID_SSC     14      /* Serial Synchronous Controller */
-#define AT91SAM9260_ID_TC0     17      /* Timer Counter 0 */
-#define AT91SAM9260_ID_TC1     18      /* Timer Counter 1 */
-#define AT91SAM9260_ID_TC2     19      /* Timer Counter 2 */
-#define AT91SAM9260_ID_UHP     20      /* USB Host port */
-#define AT91SAM9260_ID_EMAC    21      /* Ethernet */
-#define AT91SAM9260_ID_ISI     22      /* Image Sensor Interface */
-#define AT91SAM9260_ID_US3     23      /* USART 3 */
-#define AT91SAM9260_ID_US4     24      /* USART 4 */
-#define AT91SAM9260_ID_US5     25      /* USART 5 */
-#define AT91SAM9260_ID_TC3     26      /* Timer Counter 3 */
-#define AT91SAM9260_ID_TC4     27      /* Timer Counter 4 */
-#define AT91SAM9260_ID_TC5     28      /* Timer Counter 5 */
-#define AT91SAM9260_ID_IRQ0    29      /* Advanced Interrupt Controller (IRQ0) */
-#define AT91SAM9260_ID_IRQ1    30      /* Advanced Interrupt Controller (IRQ1) */
-#define AT91SAM9260_ID_IRQ2    31      /* Advanced Interrupt Controller (IRQ2) */
-
-
-/*
- * User Peripheral physical base addresses.
- */
-#define AT91SAM9260_BASE_TCB0          0xfffa0000
-#define AT91SAM9260_BASE_TC0           0xfffa0000
-#define AT91SAM9260_BASE_TC1           0xfffa0040
-#define AT91SAM9260_BASE_TC2           0xfffa0080
-#define AT91SAM9260_BASE_UDP           0xfffa4000
-#define AT91SAM9260_BASE_MCI           0xfffa8000
-#define AT91SAM9260_BASE_TWI           0xfffac000
-#define AT91SAM9260_BASE_US0           0xfffb0000
-#define AT91SAM9260_BASE_US1           0xfffb4000
-#define AT91SAM9260_BASE_US2           0xfffb8000
-#define AT91SAM9260_BASE_SSC           0xfffbc000
-#define AT91SAM9260_BASE_ISI           0xfffc0000
-#define AT91SAM9260_BASE_EMAC          0xfffc4000
-#define AT91SAM9260_BASE_SPI0          0xfffc8000
-#define AT91SAM9260_BASE_SPI1          0xfffcc000
-#define AT91SAM9260_BASE_US3           0xfffd0000
-#define AT91SAM9260_BASE_US4           0xfffd4000
-#define AT91SAM9260_BASE_US5           0xfffd8000
-#define AT91SAM9260_BASE_TCB1          0xfffdc000
-#define AT91SAM9260_BASE_TC3           0xfffdc000
-#define AT91SAM9260_BASE_TC4           0xfffdc040
-#define AT91SAM9260_BASE_TC5           0xfffdc080
-#define AT91SAM9260_BASE_ADC           0xfffe0000
-
-/*
- * System Peripherals
- */
-#define AT91SAM9260_BASE_ECC   0xffffe800
-#define AT91SAM9260_BASE_SDRAMC        0xffffea00
-#define AT91SAM9260_BASE_SMC   0xffffec00
-#define AT91SAM9260_BASE_MATRIX        0xffffee00
-#define AT91SAM9260_BASE_DBGU  AT91_BASE_DBGU0
-#define AT91SAM9260_BASE_PIOA  0xfffff400
-#define AT91SAM9260_BASE_PIOB  0xfffff600
-#define AT91SAM9260_BASE_PIOC  0xfffff800
-#define AT91SAM9260_BASE_RSTC  0xfffffd00
-#define AT91SAM9260_BASE_SHDWC 0xfffffd10
-#define AT91SAM9260_BASE_RTT   0xfffffd20
-#define AT91SAM9260_BASE_PIT   0xfffffd30
-#define AT91SAM9260_BASE_WDT   0xfffffd40
-#define AT91SAM9260_BASE_GPBR  0xfffffd50
-
-
-/*
- * Internal Memory.
- */
-#define AT91SAM9260_ROM_BASE   0x00100000      /* Internal ROM base address */
-#define AT91SAM9260_ROM_SIZE   SZ_32K          /* Internal ROM size (32Kb) */
-
-#define AT91SAM9260_SRAM0_BASE 0x00200000      /* Internal SRAM 0 base address */
-#define AT91SAM9260_SRAM0_SIZE SZ_4K           /* Internal SRAM 0 size (4Kb) */
-#define AT91SAM9260_SRAM1_BASE 0x00300000      /* Internal SRAM 1 base address */
-#define AT91SAM9260_SRAM1_SIZE SZ_4K           /* Internal SRAM 1 size (4Kb) */
-#define AT91SAM9260_SRAM_BASE  0x002FF000      /* Internal SRAM base address */
-#define AT91SAM9260_SRAM_SIZE  SZ_8K           /* Internal SRAM size (8Kb) */
-
-#define AT91SAM9260_UHP_BASE   0x00500000      /* USB Host controller */
-
-#define AT91SAM9XE_FLASH_BASE  0x00200000      /* Internal FLASH base address */
-#define AT91SAM9XE_SRAM_BASE   0x00300000      /* Internal SRAM base address */
-
-#define AT91SAM9G20_ROM_BASE   0x00100000      /* Internal ROM base address */
-#define AT91SAM9G20_ROM_SIZE   SZ_32K          /* Internal ROM size (32Kb) */
-
-#define AT91SAM9G20_SRAM0_BASE 0x00200000      /* Internal SRAM 0 base address */
-#define AT91SAM9G20_SRAM0_SIZE SZ_16K          /* Internal SRAM 0 size (16Kb) */
-#define AT91SAM9G20_SRAM1_BASE 0x00300000      /* Internal SRAM 1 base address */
-#define AT91SAM9G20_SRAM1_SIZE SZ_16K          /* Internal SRAM 1 size (16Kb) */
-#define AT91SAM9G20_SRAM_BASE  0x002FC000      /* Internal SRAM base address */
-#define AT91SAM9G20_SRAM_SIZE  SZ_32K          /* Internal SRAM size (32Kb) */
-
-#define AT91SAM9G20_UHP_BASE   0x00500000      /* USB Host controller */
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/at91sam9260_matrix.h b/arch/arm/mach-at91/include/mach/at91sam9260_matrix.h
deleted file mode 100644 (file)
index f459df4..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91sam9260_matrix.h
- *
- *  Copyright (C) 2007 Atmel Corporation.
- *
- * Memory Controllers (MATRIX, EBI) - System peripherals registers.
- * Based on AT91SAM9260 datasheet revision B.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 AT91SAM9260_MATRIX_H
-#define AT91SAM9260_MATRIX_H
-
-#define AT91_MATRIX_MCFG0      0x00                    /* Master Configuration Register 0 */
-#define AT91_MATRIX_MCFG1      0x04                    /* Master Configuration Register 1 */
-#define AT91_MATRIX_MCFG2      0x08                    /* Master Configuration Register 2 */
-#define AT91_MATRIX_MCFG3      0x0C                    /* Master Configuration Register 3 */
-#define AT91_MATRIX_MCFG4      0x10                    /* Master Configuration Register 4 */
-#define AT91_MATRIX_MCFG5      0x14                    /* Master Configuration Register 5 */
-#define                AT91_MATRIX_ULBT                (7 << 0)        /* Undefined Length Burst Type */
-#define                        AT91_MATRIX_ULBT_INFINITE       (0 << 0)
-#define                        AT91_MATRIX_ULBT_SINGLE         (1 << 0)
-#define                        AT91_MATRIX_ULBT_FOUR           (2 << 0)
-#define                        AT91_MATRIX_ULBT_EIGHT          (3 << 0)
-#define                        AT91_MATRIX_ULBT_SIXTEEN        (4 << 0)
-
-#define AT91_MATRIX_SCFG0      0x40                    /* Slave Configuration Register 0 */
-#define AT91_MATRIX_SCFG1      0x44                    /* Slave Configuration Register 1 */
-#define AT91_MATRIX_SCFG2      0x48                    /* Slave Configuration Register 2 */
-#define AT91_MATRIX_SCFG3      0x4C                    /* Slave Configuration Register 3 */
-#define AT91_MATRIX_SCFG4      0x50                    /* Slave Configuration Register 4 */
-#define                AT91_MATRIX_SLOT_CYCLE          (0xff <<  0)    /* Maximum Number of Allowed Cycles for a Burst */
-#define                AT91_MATRIX_DEFMSTR_TYPE        (3    << 16)    /* Default Master Type */
-#define                        AT91_MATRIX_DEFMSTR_TYPE_NONE   (0 << 16)
-#define                        AT91_MATRIX_DEFMSTR_TYPE_LAST   (1 << 16)
-#define                        AT91_MATRIX_DEFMSTR_TYPE_FIXED  (2 << 16)
-#define                AT91_MATRIX_FIXED_DEFMSTR       (7    << 18)    /* Fixed Index of Default Master */
-#define                AT91_MATRIX_ARBT                (3    << 24)    /* Arbitration Type */
-#define                        AT91_MATRIX_ARBT_ROUND_ROBIN    (0 << 24)
-#define                        AT91_MATRIX_ARBT_FIXED_PRIORITY (1 << 24)
-
-#define AT91_MATRIX_PRAS0      0x80                    /* Priority Register A for Slave 0 */
-#define AT91_MATRIX_PRAS1      0x88                    /* Priority Register A for Slave 1 */
-#define AT91_MATRIX_PRAS2      0x90                    /* Priority Register A for Slave 2 */
-#define AT91_MATRIX_PRAS3      0x98                    /* Priority Register A for Slave 3 */
-#define AT91_MATRIX_PRAS4      0xA0                    /* Priority Register A for Slave 4 */
-#define                AT91_MATRIX_M0PR                (3 << 0)        /* Master 0 Priority */
-#define                AT91_MATRIX_M1PR                (3 << 4)        /* Master 1 Priority */
-#define                AT91_MATRIX_M2PR                (3 << 8)        /* Master 2 Priority */
-#define                AT91_MATRIX_M3PR                (3 << 12)       /* Master 3 Priority */
-#define                AT91_MATRIX_M4PR                (3 << 16)       /* Master 4 Priority */
-#define                AT91_MATRIX_M5PR                (3 << 20)       /* Master 5 Priority */
-
-#define AT91_MATRIX_MRCR       0x100                   /* Master Remap Control Register */
-#define                AT91_MATRIX_RCB0                (1 << 0)        /* Remap Command for AHB Master 0 (ARM926EJ-S Instruction Master) */
-#define                AT91_MATRIX_RCB1                (1 << 1)        /* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */
-
-#define AT91_MATRIX_EBICSA     0x11C                   /* EBI Chip Select Assignment Register */
-#define                AT91_MATRIX_CS1A                (1 << 1)        /* Chip Select 1 Assignment */
-#define                        AT91_MATRIX_CS1A_SMC            (0 << 1)
-#define                        AT91_MATRIX_CS1A_SDRAMC         (1 << 1)
-#define                AT91_MATRIX_CS3A                (1 << 3)        /* Chip Select 3 Assignment */
-#define                        AT91_MATRIX_CS3A_SMC            (0 << 3)
-#define                        AT91_MATRIX_CS3A_SMC_SMARTMEDIA (1 << 3)
-#define                AT91_MATRIX_CS4A                (1 << 4)        /* Chip Select 4 Assignment */
-#define                        AT91_MATRIX_CS4A_SMC            (0 << 4)
-#define                        AT91_MATRIX_CS4A_SMC_CF1        (1 << 4)
-#define                AT91_MATRIX_CS5A                (1 << 5)        /* Chip Select 5 Assignment */
-#define                        AT91_MATRIX_CS5A_SMC            (0 << 5)
-#define                        AT91_MATRIX_CS5A_SMC_CF2        (1 << 5)
-#define                AT91_MATRIX_DBPUC               (1 << 8)        /* Data Bus Pull-up Configuration */
-#define                AT91_MATRIX_VDDIOMSEL           (1 << 16)       /* Memory voltage selection */
-#define                        AT91_MATRIX_VDDIOMSEL_1_8V      (0 << 16)
-#define                        AT91_MATRIX_VDDIOMSEL_3_3V      (1 << 16)
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/at91sam9261.h b/arch/arm/mach-at91/include/mach/at91sam9261.h
deleted file mode 100644 (file)
index a041406..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91sam9261.h
- *
- * Copyright (C) SAN People
- *
- * Common definitions.
- * Based on AT91SAM9261 datasheet revision E. (Preliminary)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 AT91SAM9261_H
-#define AT91SAM9261_H
-
-/*
- * Peripheral identifiers/interrupts.
- */
-#define AT91SAM9261_ID_PIOA    2       /* Parallel IO Controller A */
-#define AT91SAM9261_ID_PIOB    3       /* Parallel IO Controller B */
-#define AT91SAM9261_ID_PIOC    4       /* Parallel IO Controller C */
-#define AT91SAM9261_ID_US0     6       /* USART 0 */
-#define AT91SAM9261_ID_US1     7       /* USART 1 */
-#define AT91SAM9261_ID_US2     8       /* USART 2 */
-#define AT91SAM9261_ID_MCI     9       /* Multimedia Card Interface */
-#define AT91SAM9261_ID_UDP     10      /* USB Device Port */
-#define AT91SAM9261_ID_TWI     11      /* Two-Wire Interface */
-#define AT91SAM9261_ID_SPI0    12      /* Serial Peripheral Interface 0 */
-#define AT91SAM9261_ID_SPI1    13      /* Serial Peripheral Interface 1 */
-#define AT91SAM9261_ID_SSC0    14      /* Serial Synchronous Controller 0 */
-#define AT91SAM9261_ID_SSC1    15      /* Serial Synchronous Controller 1 */
-#define AT91SAM9261_ID_SSC2    16      /* Serial Synchronous Controller 2 */
-#define AT91SAM9261_ID_TC0     17      /* Timer Counter 0 */
-#define AT91SAM9261_ID_TC1     18      /* Timer Counter 1 */
-#define AT91SAM9261_ID_TC2     19      /* Timer Counter 2 */
-#define AT91SAM9261_ID_UHP     20      /* USB Host port */
-#define AT91SAM9261_ID_LCDC    21      /* LDC Controller */
-#define AT91SAM9261_ID_IRQ0    29      /* Advanced Interrupt Controller (IRQ0) */
-#define AT91SAM9261_ID_IRQ1    30      /* Advanced Interrupt Controller (IRQ1) */
-#define AT91SAM9261_ID_IRQ2    31      /* Advanced Interrupt Controller (IRQ2) */
-
-
-/*
- * User Peripheral physical base addresses.
- */
-#define AT91SAM9261_BASE_TCB0          0xfffa0000
-#define AT91SAM9261_BASE_TC0           0xfffa0000
-#define AT91SAM9261_BASE_TC1           0xfffa0040
-#define AT91SAM9261_BASE_TC2           0xfffa0080
-#define AT91SAM9261_BASE_UDP           0xfffa4000
-#define AT91SAM9261_BASE_MCI           0xfffa8000
-#define AT91SAM9261_BASE_TWI           0xfffac000
-#define AT91SAM9261_BASE_US0           0xfffb0000
-#define AT91SAM9261_BASE_US1           0xfffb4000
-#define AT91SAM9261_BASE_US2           0xfffb8000
-#define AT91SAM9261_BASE_SSC0          0xfffbc000
-#define AT91SAM9261_BASE_SSC1          0xfffc0000
-#define AT91SAM9261_BASE_SSC2          0xfffc4000
-#define AT91SAM9261_BASE_SPI0          0xfffc8000
-#define AT91SAM9261_BASE_SPI1          0xfffcc000
-
-
-/*
- * System Peripherals
- */
-#define AT91SAM9261_BASE_SMC   0xffffec00
-#define AT91SAM9261_BASE_MATRIX        0xffffee00
-#define AT91SAM9261_BASE_SDRAMC        0xffffea00
-#define AT91SAM9261_BASE_DBGU  AT91_BASE_DBGU0
-#define AT91SAM9261_BASE_PIOA  0xfffff400
-#define AT91SAM9261_BASE_PIOB  0xfffff600
-#define AT91SAM9261_BASE_PIOC  0xfffff800
-#define AT91SAM9261_BASE_RSTC  0xfffffd00
-#define AT91SAM9261_BASE_SHDWC 0xfffffd10
-#define AT91SAM9261_BASE_RTT   0xfffffd20
-#define AT91SAM9261_BASE_PIT   0xfffffd30
-#define AT91SAM9261_BASE_WDT   0xfffffd40
-#define AT91SAM9261_BASE_GPBR  0xfffffd50
-
-
-/*
- * Internal Memory.
- */
-#define AT91SAM9261_SRAM_BASE  0x00300000      /* Internal SRAM base address */
-#define AT91SAM9261_SRAM_SIZE  0x00028000      /* Internal SRAM size (160Kb) */
-
-#define AT91SAM9G10_SRAM_BASE  AT91SAM9261_SRAM_BASE   /* Internal SRAM base address */
-#define AT91SAM9G10_SRAM_SIZE  0x00004000      /* Internal SRAM size (16Kb) */
-
-#define AT91SAM9261_ROM_BASE   0x00400000      /* Internal ROM base address */
-#define AT91SAM9261_ROM_SIZE   SZ_32K          /* Internal ROM size (32Kb) */
-
-#define AT91SAM9261_UHP_BASE   0x00500000      /* USB Host controller */
-#define AT91SAM9261_LCDC_BASE  0x00600000      /* LDC controller */
-
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/at91sam9261_matrix.h b/arch/arm/mach-at91/include/mach/at91sam9261_matrix.h
deleted file mode 100644 (file)
index a50cdf8..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91sam9261_matrix.h
- *
- *  Copyright (C) 2007 Atmel Corporation.
- *
- * Memory Controllers (MATRIX, EBI) - System peripherals registers.
- * Based on AT91SAM9261 datasheet revision D.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 AT91SAM9261_MATRIX_H
-#define AT91SAM9261_MATRIX_H
-
-#define AT91_MATRIX_MCFG       0x00                    /* Master Configuration Register */
-#define                AT91_MATRIX_RCB0        (1 << 0)                /* Remap Command for AHB Master 0 (ARM926EJ-S Instruction Master) */
-#define                AT91_MATRIX_RCB1        (1 << 1)                /* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */
-
-#define AT91_MATRIX_SCFG0      0x04                    /* Slave Configuration Register 0 */
-#define AT91_MATRIX_SCFG1      0x08                    /* Slave Configuration Register 1 */
-#define AT91_MATRIX_SCFG2      0x0C                    /* Slave Configuration Register 2 */
-#define AT91_MATRIX_SCFG3      0x10                    /* Slave Configuration Register 3 */
-#define AT91_MATRIX_SCFG4      0x14                    /* Slave Configuration Register 4 */
-#define                AT91_MATRIX_SLOT_CYCLE          (0xff << 0)     /* Maximum Number of Allowed Cycles for a Burst */
-#define                AT91_MATRIX_DEFMSTR_TYPE        (3    << 16)    /* Default Master Type */
-#define                        AT91_MATRIX_DEFMSTR_TYPE_NONE   (0 << 16)
-#define                        AT91_MATRIX_DEFMSTR_TYPE_LAST   (1 << 16)
-#define                        AT91_MATRIX_DEFMSTR_TYPE_FIXED  (2 << 16)
-#define                AT91_MATRIX_FIXED_DEFMSTR       (7    << 18)    /* Fixed Index of Default Master */
-
-#define AT91_MATRIX_TCR                0x24                    /* TCM Configuration Register */
-#define                AT91_MATRIX_ITCM_SIZE           (0xf << 0)      /* Size of ITCM enabled memory block */
-#define                        AT91_MATRIX_ITCM_0              (0 << 0)
-#define                        AT91_MATRIX_ITCM_16             (5 << 0)
-#define                        AT91_MATRIX_ITCM_32             (6 << 0)
-#define                        AT91_MATRIX_ITCM_64             (7 << 0)
-#define                AT91_MATRIX_DTCM_SIZE           (0xf << 4)      /* Size of DTCM enabled memory block */
-#define                        AT91_MATRIX_DTCM_0              (0 << 4)
-#define                        AT91_MATRIX_DTCM_16             (5 << 4)
-#define                        AT91_MATRIX_DTCM_32             (6 << 4)
-#define                        AT91_MATRIX_DTCM_64             (7 << 4)
-
-#define AT91_MATRIX_EBICSA     0x30                    /* EBI Chip Select Assignment Register */
-#define                AT91_MATRIX_CS1A                (1 << 1)        /* Chip Select 1 Assignment */
-#define                        AT91_MATRIX_CS1A_SMC            (0 << 1)
-#define                        AT91_MATRIX_CS1A_SDRAMC         (1 << 1)
-#define                AT91_MATRIX_CS3A                (1 << 3)        /* Chip Select 3 Assignment */
-#define                        AT91_MATRIX_CS3A_SMC            (0 << 3)
-#define                        AT91_MATRIX_CS3A_SMC_SMARTMEDIA (1 << 3)
-#define                AT91_MATRIX_CS4A                (1 << 4)        /* Chip Select 4 Assignment */
-#define                        AT91_MATRIX_CS4A_SMC            (0 << 4)
-#define                        AT91_MATRIX_CS4A_SMC_CF1        (1 << 4)
-#define                AT91_MATRIX_CS5A                (1 << 5)        /* Chip Select 5 Assignment */
-#define                        AT91_MATRIX_CS5A_SMC            (0 << 5)
-#define                        AT91_MATRIX_CS5A_SMC_CF2        (1 << 5)
-#define                AT91_MATRIX_DBPUC               (1 << 8)        /* Data Bus Pull-up Configuration */
-
-#define AT91_MATRIX_USBPUCR    0x34                    /* USB Pad Pull-Up Control Register */
-#define                AT91_MATRIX_USBPUCR_PUON        (1 << 30)       /* USB Device PAD Pull-up Enable */
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/at91sam9263.h b/arch/arm/mach-at91/include/mach/at91sam9263.h
deleted file mode 100644 (file)
index d201029..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91sam9263.h
- *
- * (C) 2007 Atmel Corporation.
- *
- * Common definitions.
- * Based on AT91SAM9263 datasheet revision B (Preliminary).
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 AT91SAM9263_H
-#define AT91SAM9263_H
-
-/*
- * Peripheral identifiers/interrupts.
- */
-#define AT91SAM9263_ID_PIOA    2       /* Parallel IO Controller A */
-#define AT91SAM9263_ID_PIOB    3       /* Parallel IO Controller B */
-#define AT91SAM9263_ID_PIOCDE  4       /* Parallel IO Controller C, D and E */
-#define AT91SAM9263_ID_US0     7       /* USART 0 */
-#define AT91SAM9263_ID_US1     8       /* USART 1 */
-#define AT91SAM9263_ID_US2     9       /* USART 2 */
-#define AT91SAM9263_ID_MCI0    10      /* Multimedia Card Interface 0 */
-#define AT91SAM9263_ID_MCI1    11      /* Multimedia Card Interface 1 */
-#define AT91SAM9263_ID_CAN     12      /* CAN */
-#define AT91SAM9263_ID_TWI     13      /* Two-Wire Interface */
-#define AT91SAM9263_ID_SPI0    14      /* Serial Peripheral Interface 0 */
-#define AT91SAM9263_ID_SPI1    15      /* Serial Peripheral Interface 1 */
-#define AT91SAM9263_ID_SSC0    16      /* Serial Synchronous Controller 0 */
-#define AT91SAM9263_ID_SSC1    17      /* Serial Synchronous Controller 1 */
-#define AT91SAM9263_ID_AC97C   18      /* AC97 Controller */
-#define AT91SAM9263_ID_TCB     19      /* Timer Counter 0, 1 and 2 */
-#define AT91SAM9263_ID_PWMC    20      /* Pulse Width Modulation Controller */
-#define AT91SAM9263_ID_EMAC    21      /* Ethernet */
-#define AT91SAM9263_ID_2DGE    23      /* 2D Graphic Engine */
-#define AT91SAM9263_ID_UDP     24      /* USB Device Port */
-#define AT91SAM9263_ID_ISI     25      /* Image Sensor Interface */
-#define AT91SAM9263_ID_LCDC    26      /* LCD Controller */
-#define AT91SAM9263_ID_DMA     27      /* DMA Controller */
-#define AT91SAM9263_ID_UHP     29      /* USB Host port */
-#define AT91SAM9263_ID_IRQ0    30      /* Advanced Interrupt Controller (IRQ0) */
-#define AT91SAM9263_ID_IRQ1    31      /* Advanced Interrupt Controller (IRQ1) */
-
-
-/*
- * User Peripheral physical base addresses.
- */
-#define AT91SAM9263_BASE_UDP           0xfff78000
-#define AT91SAM9263_BASE_TCB0          0xfff7c000
-#define AT91SAM9263_BASE_TC0           0xfff7c000
-#define AT91SAM9263_BASE_TC1           0xfff7c040
-#define AT91SAM9263_BASE_TC2           0xfff7c080
-#define AT91SAM9263_BASE_MCI0          0xfff80000
-#define AT91SAM9263_BASE_MCI1          0xfff84000
-#define AT91SAM9263_BASE_TWI           0xfff88000
-#define AT91SAM9263_BASE_US0           0xfff8c000
-#define AT91SAM9263_BASE_US1           0xfff90000
-#define AT91SAM9263_BASE_US2           0xfff94000
-#define AT91SAM9263_BASE_SSC0          0xfff98000
-#define AT91SAM9263_BASE_SSC1          0xfff9c000
-#define AT91SAM9263_BASE_AC97C         0xfffa0000
-#define AT91SAM9263_BASE_SPI0          0xfffa4000
-#define AT91SAM9263_BASE_SPI1          0xfffa8000
-#define AT91SAM9263_BASE_CAN           0xfffac000
-#define AT91SAM9263_BASE_PWMC          0xfffb8000
-#define AT91SAM9263_BASE_EMAC          0xfffbc000
-#define AT91SAM9263_BASE_ISI           0xfffc4000
-#define AT91SAM9263_BASE_2DGE          0xfffc8000
-
-/*
- * System Peripherals
- */
-#define AT91SAM9263_BASE_ECC0  0xffffe000
-#define AT91SAM9263_BASE_SDRAMC0 0xffffe200
-#define AT91SAM9263_BASE_SMC0  0xffffe400
-#define AT91SAM9263_BASE_ECC1  0xffffe600
-#define AT91SAM9263_BASE_SDRAMC1 0xffffe800
-#define AT91SAM9263_BASE_SMC1  0xffffea00
-#define AT91SAM9263_BASE_MATRIX        0xffffec00
-#define AT91SAM9263_BASE_DBGU  AT91_BASE_DBGU1
-#define AT91SAM9263_BASE_PIOA  0xfffff200
-#define AT91SAM9263_BASE_PIOB  0xfffff400
-#define AT91SAM9263_BASE_PIOC  0xfffff600
-#define AT91SAM9263_BASE_PIOD  0xfffff800
-#define AT91SAM9263_BASE_PIOE  0xfffffa00
-#define AT91SAM9263_BASE_RSTC  0xfffffd00
-#define AT91SAM9263_BASE_SHDWC 0xfffffd10
-#define AT91SAM9263_BASE_RTT0  0xfffffd20
-#define AT91SAM9263_BASE_PIT   0xfffffd30
-#define AT91SAM9263_BASE_WDT   0xfffffd40
-#define AT91SAM9263_BASE_RTT1  0xfffffd50
-#define AT91SAM9263_BASE_GPBR  0xfffffd60
-
-#define AT91_SMC       AT91_SMC0
-
-/*
- * Internal Memory.
- */
-#define AT91SAM9263_SRAM0_BASE 0x00300000      /* Internal SRAM 0 base address */
-#define AT91SAM9263_SRAM0_SIZE (80 * SZ_1K)    /* Internal SRAM 0 size (80Kb) */
-
-#define AT91SAM9263_ROM_BASE   0x00400000      /* Internal ROM base address */
-#define AT91SAM9263_ROM_SIZE   SZ_128K         /* Internal ROM size (128Kb) */
-
-#define AT91SAM9263_SRAM1_BASE 0x00500000      /* Internal SRAM 1 base address */
-#define AT91SAM9263_SRAM1_SIZE SZ_16K          /* Internal SRAM 1 size (16Kb) */
-
-#define AT91SAM9263_LCDC_BASE  0x00700000      /* LCD Controller */
-#define AT91SAM9263_DMAC_BASE  0x00800000      /* DMA Controller */
-#define AT91SAM9263_UHP_BASE   0x00a00000      /* USB Host controller */
-
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/at91sam9263_matrix.h b/arch/arm/mach-at91/include/mach/at91sam9263_matrix.h
deleted file mode 100644 (file)
index ebb5fdb..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91sam9263_matrix.h
- *
- *  Copyright (C) 2006 Atmel Corporation.
- *
- * Memory Controllers (MATRIX, EBI) - System peripherals registers.
- * Based on AT91SAM9263 datasheet revision B (Preliminary).
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 AT91SAM9263_MATRIX_H
-#define AT91SAM9263_MATRIX_H
-
-#define AT91_MATRIX_MCFG0      0x00                    /* Master Configuration Register 0 */
-#define AT91_MATRIX_MCFG1      0x04                    /* Master Configuration Register 1 */
-#define AT91_MATRIX_MCFG2      0x08                    /* Master Configuration Register 2 */
-#define AT91_MATRIX_MCFG3      0x0C                    /* Master Configuration Register 3 */
-#define AT91_MATRIX_MCFG4      0x10                    /* Master Configuration Register 4 */
-#define AT91_MATRIX_MCFG5      0x14                    /* Master Configuration Register 5 */
-#define AT91_MATRIX_MCFG6      0x18                    /* Master Configuration Register 6 */
-#define AT91_MATRIX_MCFG7      0x1C                    /* Master Configuration Register 7 */
-#define AT91_MATRIX_MCFG8      0x20                    /* Master Configuration Register 8 */
-#define                AT91_MATRIX_ULBT        (7 << 0)        /* Undefined Length Burst Type */
-#define                        AT91_MATRIX_ULBT_INFINITE       (0 << 0)
-#define                        AT91_MATRIX_ULBT_SINGLE         (1 << 0)
-#define                        AT91_MATRIX_ULBT_FOUR           (2 << 0)
-#define                        AT91_MATRIX_ULBT_EIGHT          (3 << 0)
-#define                        AT91_MATRIX_ULBT_SIXTEEN        (4 << 0)
-
-#define AT91_MATRIX_SCFG0      0x40                    /* Slave Configuration Register 0 */
-#define AT91_MATRIX_SCFG1      0x44                    /* Slave Configuration Register 1 */
-#define AT91_MATRIX_SCFG2      0x48                    /* Slave Configuration Register 2 */
-#define AT91_MATRIX_SCFG3      0x4C                    /* Slave Configuration Register 3 */
-#define AT91_MATRIX_SCFG4      0x50                    /* Slave Configuration Register 4 */
-#define AT91_MATRIX_SCFG5      0x54                    /* Slave Configuration Register 5 */
-#define AT91_MATRIX_SCFG6      0x58                    /* Slave Configuration Register 6 */
-#define AT91_MATRIX_SCFG7      0x5C                    /* Slave Configuration Register 7 */
-#define                AT91_MATRIX_SLOT_CYCLE          (0xff << 0)     /* Maximum Number of Allowed Cycles for a Burst */
-#define                AT91_MATRIX_DEFMSTR_TYPE        (3    << 16)    /* Default Master Type */
-#define                        AT91_MATRIX_DEFMSTR_TYPE_NONE   (0 << 16)
-#define                        AT91_MATRIX_DEFMSTR_TYPE_LAST   (1 << 16)
-#define                        AT91_MATRIX_DEFMSTR_TYPE_FIXED  (2 << 16)
-#define                AT91_MATRIX_FIXED_DEFMSTR       (0xf  << 18)    /* Fixed Index of Default Master */
-#define                AT91_MATRIX_ARBT                (3    << 24)    /* Arbitration Type */
-#define                        AT91_MATRIX_ARBT_ROUND_ROBIN    (0 << 24)
-#define                        AT91_MATRIX_ARBT_FIXED_PRIORITY (1 << 24)
-
-#define AT91_MATRIX_PRAS0      0x80                    /* Priority Register A for Slave 0 */
-#define AT91_MATRIX_PRBS0      0x84                    /* Priority Register B for Slave 0 */
-#define AT91_MATRIX_PRAS1      0x88                    /* Priority Register A for Slave 1 */
-#define AT91_MATRIX_PRBS1      0x8C                    /* Priority Register B for Slave 1 */
-#define AT91_MATRIX_PRAS2      0x90                    /* Priority Register A for Slave 2 */
-#define AT91_MATRIX_PRBS2      0x94                    /* Priority Register B for Slave 2 */
-#define AT91_MATRIX_PRAS3      0x98                    /* Priority Register A for Slave 3 */
-#define AT91_MATRIX_PRBS3      0x9C                    /* Priority Register B for Slave 3 */
-#define AT91_MATRIX_PRAS4      0xA0                    /* Priority Register A for Slave 4 */
-#define AT91_MATRIX_PRBS4      0xA4                    /* Priority Register B for Slave 4 */
-#define AT91_MATRIX_PRAS5      0xA8                    /* Priority Register A for Slave 5 */
-#define AT91_MATRIX_PRBS5      0xAC                    /* Priority Register B for Slave 5 */
-#define AT91_MATRIX_PRAS6      0xB0                    /* Priority Register A for Slave 6 */
-#define AT91_MATRIX_PRBS6      0xB4                    /* Priority Register B for Slave 6 */
-#define AT91_MATRIX_PRAS7      0xB8                    /* Priority Register A for Slave 7 */
-#define AT91_MATRIX_PRBS7      0xBC                    /* Priority Register B for Slave 7 */
-#define                AT91_MATRIX_M0PR                (3 << 0)        /* Master 0 Priority */
-#define                AT91_MATRIX_M1PR                (3 << 4)        /* Master 1 Priority */
-#define                AT91_MATRIX_M2PR                (3 << 8)        /* Master 2 Priority */
-#define                AT91_MATRIX_M3PR                (3 << 12)       /* Master 3 Priority */
-#define                AT91_MATRIX_M4PR                (3 << 16)       /* Master 4 Priority */
-#define                AT91_MATRIX_M5PR                (3 << 20)       /* Master 5 Priority */
-#define                AT91_MATRIX_M6PR                (3 << 24)       /* Master 6 Priority */
-#define                AT91_MATRIX_M7PR                (3 << 28)       /* Master 7 Priority */
-#define                AT91_MATRIX_M8PR                (3 << 0)        /* Master 8 Priority (in Register B) */
-
-#define AT91_MATRIX_MRCR       0x100                   /* Master Remap Control Register */
-#define                AT91_MATRIX_RCB0                (1 << 0)        /* Remap Command for AHB Master 0 (ARM926EJ-S Instruction Master) */
-#define                AT91_MATRIX_RCB1                (1 << 1)        /* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */
-#define                AT91_MATRIX_RCB2                (1 << 2)
-#define                AT91_MATRIX_RCB3                (1 << 3)
-#define                AT91_MATRIX_RCB4                (1 << 4)
-#define                AT91_MATRIX_RCB5                (1 << 5)
-#define                AT91_MATRIX_RCB6                (1 << 6)
-#define                AT91_MATRIX_RCB7                (1 << 7)
-#define                AT91_MATRIX_RCB8                (1 << 8)
-
-#define AT91_MATRIX_TCMR       0x114                   /* TCM Configuration Register */
-#define                AT91_MATRIX_ITCM_SIZE           (0xf << 0)      /* Size of ITCM enabled memory block */
-#define                        AT91_MATRIX_ITCM_0              (0 << 0)
-#define                        AT91_MATRIX_ITCM_16             (5 << 0)
-#define                        AT91_MATRIX_ITCM_32             (6 << 0)
-#define                AT91_MATRIX_DTCM_SIZE           (0xf << 4)      /* Size of DTCM enabled memory block */
-#define                        AT91_MATRIX_DTCM_0              (0 << 4)
-#define                        AT91_MATRIX_DTCM_16             (5 << 4)
-#define                        AT91_MATRIX_DTCM_32             (6 << 4)
-
-#define AT91_MATRIX_EBI0CSA    0x120                   /* EBI0 Chip Select Assignment Register */
-#define                AT91_MATRIX_EBI0_CS1A           (1 << 1)        /* Chip Select 1 Assignment */
-#define                        AT91_MATRIX_EBI0_CS1A_SMC               (0 << 1)
-#define                        AT91_MATRIX_EBI0_CS1A_SDRAMC            (1 << 1)
-#define                AT91_MATRIX_EBI0_CS3A           (1 << 3)        /* Chip Select 3 Assignment */
-#define                        AT91_MATRIX_EBI0_CS3A_SMC               (0 << 3)
-#define                        AT91_MATRIX_EBI0_CS3A_SMC_SMARTMEDIA    (1 << 3)
-#define                AT91_MATRIX_EBI0_CS4A           (1 << 4)        /* Chip Select 4 Assignment */
-#define                        AT91_MATRIX_EBI0_CS4A_SMC               (0 << 4)
-#define                        AT91_MATRIX_EBI0_CS4A_SMC_CF1           (1 << 4)
-#define                AT91_MATRIX_EBI0_CS5A           (1 << 5)        /* Chip Select 5 Assignment */
-#define                        AT91_MATRIX_EBI0_CS5A_SMC               (0 << 5)
-#define                        AT91_MATRIX_EBI0_CS5A_SMC_CF2           (1 << 5)
-#define                AT91_MATRIX_EBI0_DBPUC          (1 << 8)        /* Data Bus Pull-up Configuration */
-#define                AT91_MATRIX_EBI0_VDDIOMSEL      (1 << 16)       /* Memory voltage selection */
-#define                        AT91_MATRIX_EBI0_VDDIOMSEL_1_8V         (0 << 16)
-#define                        AT91_MATRIX_EBI0_VDDIOMSEL_3_3V         (1 << 16)
-
-#define AT91_MATRIX_EBI1CSA    0x124                   /* EBI1 Chip Select Assignment Register */
-#define                AT91_MATRIX_EBI1_CS1A           (1 << 1)        /* Chip Select 1 Assignment */
-#define                        AT91_MATRIX_EBI1_CS1A_SMC               (0 << 1)
-#define                        AT91_MATRIX_EBI1_CS1A_SDRAMC            (1 << 1)
-#define                AT91_MATRIX_EBI1_CS2A           (1 << 3)        /* Chip Select 3 Assignment */
-#define                        AT91_MATRIX_EBI1_CS2A_SMC               (0 << 3)
-#define                        AT91_MATRIX_EBI1_CS2A_SMC_SMARTMEDIA    (1 << 3)
-#define                AT91_MATRIX_EBI1_DBPUC          (1 << 8)        /* Data Bus Pull-up Configuration */
-#define                AT91_MATRIX_EBI1_VDDIOMSEL      (1 << 16)       /* Memory voltage selection */
-#define                        AT91_MATRIX_EBI1_VDDIOMSEL_1_8V         (0 << 16)
-#define                        AT91_MATRIX_EBI1_VDDIOMSEL_3_3V         (1 << 16)
-
-#endif
index 175e1fdd9fe8ade33846f2ff42441d61053bc928..ff54a0ce90e39d7c494c421068008260e862ebb7 100644 (file)
@@ -16,8 +16,6 @@
 #ifndef AT91SAM9_SMC_H
 #define AT91SAM9_SMC_H
 
-#include <mach/cpu.h>
-
 #ifndef __ASSEMBLY__
 struct sam9_smc_config {
        /* Setup register */
diff --git a/arch/arm/mach-at91/include/mach/at91sam9g45.h b/arch/arm/mach-at91/include/mach/at91sam9g45.h
deleted file mode 100644 (file)
index 8eba102..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Chip-specific header file for the AT91SAM9G45 family
- *
- *  Copyright (C) 2008-2009 Atmel Corporation.
- *
- * Common definitions.
- * Based on AT91SAM9G45 preliminary datasheet.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 AT91SAM9G45_H
-#define AT91SAM9G45_H
-
-/*
- * Peripheral identifiers/interrupts.
- */
-#define AT91SAM9G45_ID_PIOA    2       /* Parallel I/O Controller A */
-#define AT91SAM9G45_ID_PIOB    3       /* Parallel I/O Controller B */
-#define AT91SAM9G45_ID_PIOC    4       /* Parallel I/O Controller C */
-#define AT91SAM9G45_ID_PIODE   5       /* Parallel I/O Controller D and E */
-#define AT91SAM9G45_ID_TRNG    6       /* True Random Number Generator */
-#define AT91SAM9G45_ID_US0     7       /* USART 0 */
-#define AT91SAM9G45_ID_US1     8       /* USART 1 */
-#define AT91SAM9G45_ID_US2     9       /* USART 2 */
-#define AT91SAM9G45_ID_US3     10      /* USART 3 */
-#define AT91SAM9G45_ID_MCI0    11      /* High Speed Multimedia Card Interface 0 */
-#define AT91SAM9G45_ID_TWI0    12      /* Two-Wire Interface 0 */
-#define AT91SAM9G45_ID_TWI1    13      /* Two-Wire Interface 1 */
-#define AT91SAM9G45_ID_SPI0    14      /* Serial Peripheral Interface 0 */
-#define AT91SAM9G45_ID_SPI1    15      /* Serial Peripheral Interface 1 */
-#define AT91SAM9G45_ID_SSC0    16      /* Synchronous Serial Controller 0 */
-#define AT91SAM9G45_ID_SSC1    17      /* Synchronous Serial Controller 1 */
-#define AT91SAM9G45_ID_TCB     18      /* Timer Counter 0, 1, 2, 3, 4 and 5 */
-#define AT91SAM9G45_ID_PWMC    19      /* Pulse Width Modulation Controller */
-#define AT91SAM9G45_ID_TSC     20      /* Touch Screen ADC Controller */
-#define AT91SAM9G45_ID_DMA     21      /* DMA Controller */
-#define AT91SAM9G45_ID_UHPHS   22      /* USB Host High Speed */
-#define AT91SAM9G45_ID_LCDC    23      /* LCD Controller */
-#define AT91SAM9G45_ID_AC97C   24      /* AC97 Controller */
-#define AT91SAM9G45_ID_EMAC    25      /* Ethernet MAC */
-#define AT91SAM9G45_ID_ISI     26      /* Image Sensor Interface */
-#define AT91SAM9G45_ID_UDPHS   27      /* USB Device High Speed */
-#define AT91SAM9G45_ID_AESTDESSHA 28   /* AES + T-DES + SHA */
-#define AT91SAM9G45_ID_MCI1    29      /* High Speed Multimedia Card Interface 1 */
-#define AT91SAM9G45_ID_VDEC    30      /* Video Decoder */
-#define AT91SAM9G45_ID_IRQ0    31      /* Advanced Interrupt Controller */
-
-/*
- * User Peripheral physical base addresses.
- */
-#define AT91SAM9G45_BASE_UDPHS         0xfff78000
-#define AT91SAM9G45_BASE_TCB0          0xfff7c000
-#define AT91SAM9G45_BASE_TC0           0xfff7c000
-#define AT91SAM9G45_BASE_TC1           0xfff7c040
-#define AT91SAM9G45_BASE_TC2           0xfff7c080
-#define AT91SAM9G45_BASE_MCI0          0xfff80000
-#define AT91SAM9G45_BASE_TWI0          0xfff84000
-#define AT91SAM9G45_BASE_TWI1          0xfff88000
-#define AT91SAM9G45_BASE_US0           0xfff8c000
-#define AT91SAM9G45_BASE_US1           0xfff90000
-#define AT91SAM9G45_BASE_US2           0xfff94000
-#define AT91SAM9G45_BASE_US3           0xfff98000
-#define AT91SAM9G45_BASE_SSC0          0xfff9c000
-#define AT91SAM9G45_BASE_SSC1          0xfffa0000
-#define AT91SAM9G45_BASE_SPI0          0xfffa4000
-#define AT91SAM9G45_BASE_SPI1          0xfffa8000
-#define AT91SAM9G45_BASE_AC97C         0xfffac000
-#define AT91SAM9G45_BASE_TSC           0xfffb0000
-#define AT91SAM9G45_BASE_ISI           0xfffb4000
-#define AT91SAM9G45_BASE_PWMC          0xfffb8000
-#define AT91SAM9G45_BASE_EMAC          0xfffbc000
-#define AT91SAM9G45_BASE_AES           0xfffc0000
-#define AT91SAM9G45_BASE_TDES          0xfffc4000
-#define AT91SAM9G45_BASE_SHA           0xfffc8000
-#define AT91SAM9G45_BASE_TRNG          0xfffcc000
-#define AT91SAM9G45_BASE_MCI1          0xfffd0000
-#define AT91SAM9G45_BASE_TCB1          0xfffd4000
-#define AT91SAM9G45_BASE_TC3           0xfffd4000
-#define AT91SAM9G45_BASE_TC4           0xfffd4040
-#define AT91SAM9G45_BASE_TC5           0xfffd4080
-
-/*
- * System Peripherals
- */
-#define AT91SAM9G45_BASE_ECC   0xffffe200
-#define AT91SAM9G45_BASE_DDRSDRC1 0xffffe400
-#define AT91SAM9G45_BASE_DDRSDRC0 0xffffe600
-#define AT91SAM9G45_BASE_DMA   0xffffec00
-#define AT91SAM9G45_BASE_SMC   0xffffe800
-#define AT91SAM9G45_BASE_MATRIX        0xffffea00
-#define AT91SAM9G45_BASE_DBGU  AT91_BASE_DBGU1
-#define AT91SAM9G45_BASE_PIOA  0xfffff200
-#define AT91SAM9G45_BASE_PIOB  0xfffff400
-#define AT91SAM9G45_BASE_PIOC  0xfffff600
-#define AT91SAM9G45_BASE_PIOD  0xfffff800
-#define AT91SAM9G45_BASE_PIOE  0xfffffa00
-#define AT91SAM9G45_BASE_RSTC  0xfffffd00
-#define AT91SAM9G45_BASE_SHDWC 0xfffffd10
-#define AT91SAM9G45_BASE_RTT   0xfffffd20
-#define AT91SAM9G45_BASE_PIT   0xfffffd30
-#define AT91SAM9G45_BASE_WDT   0xfffffd40
-#define AT91SAM9G45_BASE_RTC   0xfffffdb0
-#define AT91SAM9G45_BASE_GPBR  0xfffffd60
-
-/*
- * Internal Memory.
- */
-#define AT91SAM9G45_SRAM_BASE  0x00300000      /* Internal SRAM base address */
-#define AT91SAM9G45_SRAM_SIZE  SZ_64K          /* Internal SRAM size (64Kb) */
-
-#define AT91SAM9G45_ROM_BASE   0x00400000      /* Internal ROM base address */
-#define AT91SAM9G45_ROM_SIZE   SZ_64K          /* Internal ROM size (64Kb) */
-
-#define AT91SAM9G45_LCDC_BASE  0x00500000      /* LCD Controller */
-#define AT91SAM9G45_UDPHS_FIFO 0x00600000      /* USB Device HS controller */
-#define AT91SAM9G45_OHCI_BASE  0x00700000      /* USB Host controller (OHCI) */
-#define AT91SAM9G45_EHCI_BASE  0x00800000      /* USB Host controller (EHCI) */
-#define AT91SAM9G45_VDEC_BASE  0x00900000      /* Video Decoder Controller */
-
-/*
- * DMA peripheral identifiers
- * for hardware handshaking interface
- */
-#define AT_DMA_ID_MCI0          0
-#define AT_DMA_ID_SPI0_TX       1
-#define AT_DMA_ID_SPI0_RX       2
-#define AT_DMA_ID_SPI1_TX       3
-#define AT_DMA_ID_SPI1_RX       4
-#define AT_DMA_ID_SSC0_TX       5
-#define AT_DMA_ID_SSC0_RX       6
-#define AT_DMA_ID_SSC1_TX       7
-#define AT_DMA_ID_SSC1_RX       8
-#define AT_DMA_ID_AC97_TX       9
-#define AT_DMA_ID_AC97_RX      10
-#define AT_DMA_ID_AES_TX       11
-#define AT_DMA_ID_AES_RX       12
-#define AT_DMA_ID_MCI1         13
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/at91sam9g45_matrix.h b/arch/arm/mach-at91/include/mach/at91sam9g45_matrix.h
deleted file mode 100644 (file)
index b76e2ed..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Matrix-centric header file for the AT91SAM9G45 family
- *
- *  Copyright (C) 2008-2009 Atmel Corporation.
- *
- * Memory Controllers (MATRIX, EBI) - System peripherals registers.
- * Based on AT91SAM9G45 preliminary datasheet.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 AT91SAM9G45_MATRIX_H
-#define AT91SAM9G45_MATRIX_H
-
-#define AT91_MATRIX_MCFG0      0x00                    /* Master Configuration Register 0 */
-#define AT91_MATRIX_MCFG1      0x04                    /* Master Configuration Register 1 */
-#define AT91_MATRIX_MCFG2      0x08                    /* Master Configuration Register 2 */
-#define AT91_MATRIX_MCFG3      0x0C                    /* Master Configuration Register 3 */
-#define AT91_MATRIX_MCFG4      0x10                    /* Master Configuration Register 4 */
-#define AT91_MATRIX_MCFG5      0x14                    /* Master Configuration Register 5 */
-#define AT91_MATRIX_MCFG6      0x18                    /* Master Configuration Register 6 */
-#define AT91_MATRIX_MCFG7      0x1C                    /* Master Configuration Register 7 */
-#define AT91_MATRIX_MCFG8      0x20                    /* Master Configuration Register 8 */
-#define AT91_MATRIX_MCFG9      0x24                    /* Master Configuration Register 9 */
-#define AT91_MATRIX_MCFG10     0x28                    /* Master Configuration Register 10 */
-#define AT91_MATRIX_MCFG11     0x2C                    /* Master Configuration Register 11 */
-#define                AT91_MATRIX_ULBT        (7 << 0)        /* Undefined Length Burst Type */
-#define                        AT91_MATRIX_ULBT_INFINITE       (0 << 0)
-#define                        AT91_MATRIX_ULBT_SINGLE         (1 << 0)
-#define                        AT91_MATRIX_ULBT_FOUR           (2 << 0)
-#define                        AT91_MATRIX_ULBT_EIGHT          (3 << 0)
-#define                        AT91_MATRIX_ULBT_SIXTEEN        (4 << 0)
-#define                        AT91_MATRIX_ULBT_THIRTYTWO      (5 << 0)
-#define                        AT91_MATRIX_ULBT_SIXTYFOUR      (6 << 0)
-#define                        AT91_MATRIX_ULBT_128            (7 << 0)
-
-#define AT91_MATRIX_SCFG0      0x40                    /* Slave Configuration Register 0 */
-#define AT91_MATRIX_SCFG1      0x44                    /* Slave Configuration Register 1 */
-#define AT91_MATRIX_SCFG2      0x48                    /* Slave Configuration Register 2 */
-#define AT91_MATRIX_SCFG3      0x4C                    /* Slave Configuration Register 3 */
-#define AT91_MATRIX_SCFG4      0x50                    /* Slave Configuration Register 4 */
-#define AT91_MATRIX_SCFG5      0x54                    /* Slave Configuration Register 5 */
-#define AT91_MATRIX_SCFG6      0x58                    /* Slave Configuration Register 6 */
-#define AT91_MATRIX_SCFG7      0x5C                    /* Slave Configuration Register 7 */
-#define                AT91_MATRIX_SLOT_CYCLE          (0x1ff << 0)    /* Maximum Number of Allowed Cycles for a Burst */
-#define                AT91_MATRIX_DEFMSTR_TYPE        (3    << 16)    /* Default Master Type */
-#define                        AT91_MATRIX_DEFMSTR_TYPE_NONE   (0 << 16)
-#define                        AT91_MATRIX_DEFMSTR_TYPE_LAST   (1 << 16)
-#define                        AT91_MATRIX_DEFMSTR_TYPE_FIXED  (2 << 16)
-#define                AT91_MATRIX_FIXED_DEFMSTR       (0xf  << 18)    /* Fixed Index of Default Master */
-
-#define AT91_MATRIX_PRAS0      0x80                    /* Priority Register A for Slave 0 */
-#define AT91_MATRIX_PRBS0      0x84                    /* Priority Register B for Slave 0 */
-#define AT91_MATRIX_PRAS1      0x88                    /* Priority Register A for Slave 1 */
-#define AT91_MATRIX_PRBS1      0x8C                    /* Priority Register B for Slave 1 */
-#define AT91_MATRIX_PRAS2      0x90                    /* Priority Register A for Slave 2 */
-#define AT91_MATRIX_PRBS2      0x94                    /* Priority Register B for Slave 2 */
-#define AT91_MATRIX_PRAS3      0x98                    /* Priority Register A for Slave 3 */
-#define AT91_MATRIX_PRBS3      0x9C                    /* Priority Register B for Slave 3 */
-#define AT91_MATRIX_PRAS4      0xA0                    /* Priority Register A for Slave 4 */
-#define AT91_MATRIX_PRBS4      0xA4                    /* Priority Register B for Slave 4 */
-#define AT91_MATRIX_PRAS5      0xA8                    /* Priority Register A for Slave 5 */
-#define AT91_MATRIX_PRBS5      0xAC                    /* Priority Register B for Slave 5 */
-#define AT91_MATRIX_PRAS6      0xB0                    /* Priority Register A for Slave 6 */
-#define AT91_MATRIX_PRBS6      0xB4                    /* Priority Register B for Slave 6 */
-#define AT91_MATRIX_PRAS7      0xB8                    /* Priority Register A for Slave 7 */
-#define AT91_MATRIX_PRBS7      0xBC                    /* Priority Register B for Slave 7 */
-#define                AT91_MATRIX_M0PR                (3 << 0)        /* Master 0 Priority */
-#define                AT91_MATRIX_M1PR                (3 << 4)        /* Master 1 Priority */
-#define                AT91_MATRIX_M2PR                (3 << 8)        /* Master 2 Priority */
-#define                AT91_MATRIX_M3PR                (3 << 12)       /* Master 3 Priority */
-#define                AT91_MATRIX_M4PR                (3 << 16)       /* Master 4 Priority */
-#define                AT91_MATRIX_M5PR                (3 << 20)       /* Master 5 Priority */
-#define                AT91_MATRIX_M6PR                (3 << 24)       /* Master 6 Priority */
-#define                AT91_MATRIX_M7PR                (3 << 28)       /* Master 7 Priority */
-#define                AT91_MATRIX_M8PR                (3 << 0)        /* Master 8 Priority (in Register B) */
-#define                AT91_MATRIX_M9PR                (3 << 4)        /* Master 9 Priority (in Register B) */
-#define                AT91_MATRIX_M10PR               (3 << 8)        /* Master 10 Priority (in Register B) */
-#define                AT91_MATRIX_M11PR               (3 << 12)       /* Master 11 Priority (in Register B) */
-
-#define AT91_MATRIX_MRCR       0x100                   /* Master Remap Control Register */
-#define                AT91_MATRIX_RCB0                (1 << 0)        /* Remap Command for AHB Master 0 (ARM926EJ-S Instruction Master) */
-#define                AT91_MATRIX_RCB1                (1 << 1)        /* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */
-#define                AT91_MATRIX_RCB2                (1 << 2)
-#define                AT91_MATRIX_RCB3                (1 << 3)
-#define                AT91_MATRIX_RCB4                (1 << 4)
-#define                AT91_MATRIX_RCB5                (1 << 5)
-#define                AT91_MATRIX_RCB6                (1 << 6)
-#define                AT91_MATRIX_RCB7                (1 << 7)
-#define                AT91_MATRIX_RCB8                (1 << 8)
-#define                AT91_MATRIX_RCB9                (1 << 9)
-#define                AT91_MATRIX_RCB10               (1 << 10)
-#define                AT91_MATRIX_RCB11               (1 << 11)
-
-#define AT91_MATRIX_TCMR       0x110                   /* TCM Configuration Register */
-#define                AT91_MATRIX_ITCM_SIZE           (0xf << 0)      /* Size of ITCM enabled memory block */
-#define                        AT91_MATRIX_ITCM_0              (0 << 0)
-#define                        AT91_MATRIX_ITCM_32             (6 << 0)
-#define                AT91_MATRIX_DTCM_SIZE           (0xf << 4)      /* Size of DTCM enabled memory block */
-#define                        AT91_MATRIX_DTCM_0              (0 << 4)
-#define                        AT91_MATRIX_DTCM_32             (6 << 4)
-#define                        AT91_MATRIX_DTCM_64             (7 << 4)
-#define                AT91_MATRIX_TCM_NWS             (0x1 << 11)     /* Wait state TCM register */
-#define                        AT91_MATRIX_TCM_NO_WS           (0x0 << 11)
-#define                        AT91_MATRIX_TCM_ONE_WS          (0x1 << 11)
-
-#define AT91_MATRIX_VIDEO      0x118                   /* Video Mode Configuration Register */
-#define                AT91C_VDEC_SEL                  (0x1 <<  0) /* Video Mode Selection */
-#define                        AT91C_VDEC_SEL_OFF              (0 << 0)
-#define                        AT91C_VDEC_SEL_ON               (1 << 0)
-
-#define AT91_MATRIX_EBICSA     0x128                   /* EBI Chip Select Assignment Register */
-#define                AT91_MATRIX_EBI_CS1A            (1 << 1)        /* Chip Select 1 Assignment */
-#define                        AT91_MATRIX_EBI_CS1A_SMC                (0 << 1)
-#define                        AT91_MATRIX_EBI_CS1A_SDRAMC             (1 << 1)
-#define                AT91_MATRIX_EBI_CS3A            (1 << 3)        /* Chip Select 3 Assignment */
-#define                        AT91_MATRIX_EBI_CS3A_SMC                (0 << 3)
-#define                        AT91_MATRIX_EBI_CS3A_SMC_SMARTMEDIA     (1 << 3)
-#define                AT91_MATRIX_EBI_CS4A            (1 << 4)        /* Chip Select 4 Assignment */
-#define                        AT91_MATRIX_EBI_CS4A_SMC                (0 << 4)
-#define                        AT91_MATRIX_EBI_CS4A_SMC_CF0            (1 << 4)
-#define                AT91_MATRIX_EBI_CS5A            (1 << 5)        /* Chip Select 5 Assignment */
-#define                        AT91_MATRIX_EBI_CS5A_SMC                (0 << 5)
-#define                        AT91_MATRIX_EBI_CS5A_SMC_CF1            (1 << 5)
-#define                AT91_MATRIX_EBI_DBPUC           (1 << 8)        /* Data Bus Pull-up Configuration */
-#define                        AT91_MATRIX_EBI_DBPU_ON                 (0 << 8)
-#define                        AT91_MATRIX_EBI_DBPU_OFF                (1 << 8)
-#define                AT91_MATRIX_EBI_VDDIOMSEL       (1 << 16)       /* Memory voltage selection */
-#define                        AT91_MATRIX_EBI_VDDIOMSEL_1_8V          (0 << 16)
-#define                        AT91_MATRIX_EBI_VDDIOMSEL_3_3V          (1 << 16)
-#define                AT91_MATRIX_EBI_EBI_IOSR        (1 << 17)       /* EBI I/O slew rate selection */
-#define                        AT91_MATRIX_EBI_EBI_IOSR_REDUCED        (0 << 17)
-#define                        AT91_MATRIX_EBI_EBI_IOSR_NORMAL         (1 << 17)
-#define                AT91_MATRIX_EBI_DDR_IOSR        (1 << 18)       /* DDR2 dedicated port I/O slew rate selection */
-#define                        AT91_MATRIX_EBI_DDR_IOSR_REDUCED        (0 << 18)
-#define                        AT91_MATRIX_EBI_DDR_IOSR_NORMAL         (1 << 18)
-
-#define AT91_MATRIX_WPMR       0x1E4                   /* Write Protect Mode Register */
-#define                AT91_MATRIX_WPMR_WPEN           (1 << 0)        /* Write Protect ENable */
-#define                        AT91_MATRIX_WPMR_WP_WPDIS               (0 << 0)
-#define                        AT91_MATRIX_WPMR_WP_WPEN                (1 << 0)
-#define                AT91_MATRIX_WPMR_WPKEY          (0xFFFFFF << 8) /* Write Protect KEY */
-
-#define AT91_MATRIX_WPSR       0x1E8                   /* Write Protect Status Register */
-#define                AT91_MATRIX_WPSR_WPVS           (1 << 0)        /* Write Protect Violation Status */
-#define                        AT91_MATRIX_WPSR_NO_WPV         (0 << 0)
-#define                        AT91_MATRIX_WPSR_WPV            (1 << 0)
-#define                AT91_MATRIX_WPSR_WPVSRC         (0xFFFF << 8)   /* Write Protect Violation Source */
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/at91sam9n12.h b/arch/arm/mach-at91/include/mach/at91sam9n12.h
deleted file mode 100644 (file)
index 0151bcf..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * SoC specific header file for the AT91SAM9N12
- *
- * Copyright (C) 2012 Atmel Corporation
- *
- * Common definitions, based on AT91SAM9N12 SoC datasheet
- *
- * Licensed under GPLv2 or later
- */
-
-#ifndef _AT91SAM9N12_H_
-#define _AT91SAM9N12_H_
-
-/*
- * Peripheral identifiers/interrupts.
- */
-#define AT91SAM9N12_ID_PIOAB   2       /* Parallel I/O Controller A and B */
-#define AT91SAM9N12_ID_PIOCD   3       /* Parallel I/O Controller C and D */
-#define AT91SAM9N12_ID_FUSE    4       /* FUSE Controller */
-#define AT91SAM9N12_ID_USART0  5       /* USART 0 */
-#define AT91SAM9N12_ID_USART1  6       /* USART 1 */
-#define AT91SAM9N12_ID_USART2  7       /* USART 2 */
-#define AT91SAM9N12_ID_USART3  8       /* USART 3 */
-#define AT91SAM9N12_ID_TWI0    9       /* Two-Wire Interface 0 */
-#define AT91SAM9N12_ID_TWI1    10      /* Two-Wire Interface 1 */
-#define AT91SAM9N12_ID_MCI     12      /* High Speed Multimedia Card Interface */
-#define AT91SAM9N12_ID_SPI0    13      /* Serial Peripheral Interface 0 */
-#define AT91SAM9N12_ID_SPI1    14      /* Serial Peripheral Interface 1 */
-#define AT91SAM9N12_ID_UART0   15      /* UART 0 */
-#define AT91SAM9N12_ID_UART1   16      /* UART 1 */
-#define AT91SAM9N12_ID_TCB     17      /* Timer Counter 0, 1, 2, 3, 4 and 5 */
-#define AT91SAM9N12_ID_PWM     18      /* Pulse Width Modulation Controller */
-#define AT91SAM9N12_ID_ADC     19      /* ADC Controller */
-#define AT91SAM9N12_ID_DMA     20      /* DMA Controller */
-#define AT91SAM9N12_ID_UHP     22      /* USB Host High Speed */
-#define AT91SAM9N12_ID_UDP     23      /* USB Device High Speed */
-#define AT91SAM9N12_ID_LCDC    25      /* LCD Controller */
-#define AT91SAM9N12_ID_ISI     25      /* Image Sensor Interface */
-#define AT91SAM9N12_ID_SSC     28      /* Synchronous Serial Controller */
-#define AT91SAM9N12_ID_TRNG    30      /* TRNG */
-#define AT91SAM9N12_ID_IRQ0    31      /* Advanced Interrupt Controller */
-
-/*
- * User Peripheral physical base addresses.
- */
-#define AT91SAM9N12_BASE_USART0        0xf801c000
-#define AT91SAM9N12_BASE_USART1        0xf8020000
-#define AT91SAM9N12_BASE_USART2        0xf8024000
-#define AT91SAM9N12_BASE_USART3        0xf8028000
-
-/*
- * System Peripherals
- */
-#define AT91SAM9N12_BASE_RTC   0xfffffeb0
-
-/*
- * Internal Memory.
- */
-#define AT91SAM9N12_SRAM_BASE  0x00300000      /* Internal SRAM base address */
-#define AT91SAM9N12_SRAM_SIZE  SZ_32K          /* Internal SRAM size (32Kb) */
-
-#define AT91SAM9N12_ROM_BASE   0x00100000      /* Internal ROM base address */
-#define AT91SAM9N12_ROM_SIZE   SZ_128K         /* Internal ROM size (128Kb) */
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/at91sam9n12_matrix.h b/arch/arm/mach-at91/include/mach/at91sam9n12_matrix.h
deleted file mode 100644 (file)
index 40060cd..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Matrix-centric header file for the AT91SAM9N12
- *
- * Copyright (C) 2012 Atmel Corporation.
- *
- * Only EBI related registers.
- * Write Protect register definitions may be useful.
- *
- * Licensed under GPLv2 or later.
- */
-
-#ifndef _AT91SAM9N12_MATRIX_H_
-#define _AT91SAM9N12_MATRIX_H_
-
-#define AT91_MATRIX_EBICSA     (AT91_MATRIX + 0x118)   /* EBI Chip Select Assignment Register */
-#define                AT91_MATRIX_EBI_CS1A            (1 << 1)        /* Chip Select 1 Assignment */
-#define                        AT91_MATRIX_EBI_CS1A_SMC                (0 << 1)
-#define                        AT91_MATRIX_EBI_CS1A_SDRAMC             (1 << 1)
-#define                AT91_MATRIX_EBI_CS3A            (1 << 3)        /* Chip Select 3 Assignment */
-#define                        AT91_MATRIX_EBI_CS3A_SMC                (0 << 3)
-#define                        AT91_MATRIX_EBI_CS3A_SMC_NANDFLASH      (1 << 3)
-#define                AT91_MATRIX_EBI_DBPUC           (1 << 8)        /* Data Bus Pull-up Configuration */
-#define                        AT91_MATRIX_EBI_DBPU_ON                 (0 << 8)
-#define                        AT91_MATRIX_EBI_DBPU_OFF                (1 << 8)
-#define                AT91_MATRIX_EBI_VDDIOMSEL       (1 << 16)       /* Memory voltage selection */
-#define                        AT91_MATRIX_EBI_VDDIOMSEL_1_8V          (0 << 16)
-#define                        AT91_MATRIX_EBI_VDDIOMSEL_3_3V          (1 << 16)
-#define                AT91_MATRIX_EBI_EBI_IOSR        (1 << 17)       /* EBI I/O slew rate selection */
-#define                        AT91_MATRIX_EBI_EBI_IOSR_REDUCED        (0 << 17)
-#define                        AT91_MATRIX_EBI_EBI_IOSR_NORMAL         (1 << 17)
-#define                AT91_MATRIX_EBI_DDR_IOSR        (1 << 18)       /* DDR2 dedicated port I/O slew rate selection */
-#define                        AT91_MATRIX_EBI_DDR_IOSR_REDUCED        (0 << 18)
-#define                        AT91_MATRIX_EBI_DDR_IOSR_NORMAL         (1 << 18)
-#define                AT91_MATRIX_NFD0_SELECT         (1 << 24)       /* NAND Flash Data Bus Selection */
-#define                        AT91_MATRIX_NFD0_ON_D0                  (0 << 24)
-#define                        AT91_MATRIX_NFD0_ON_D16                 (1 << 24)
-#define                AT91_MATRIX_DDR_MP_EN           (1 << 25)       /* DDR Multi-port Enable */
-#define                        AT91_MATRIX_MP_OFF                      (0 << 25)
-#define                        AT91_MATRIX_MP_ON                       (1 << 25)
-
-#define AT91_MATRIX_WPMR       (AT91_MATRIX + 0x1E4)   /* Write Protect Mode Register */
-#define                AT91_MATRIX_WPMR_WPEN           (1 << 0)        /* Write Protect ENable */
-#define                        AT91_MATRIX_WPMR_WP_WPDIS               (0 << 0)
-#define                        AT91_MATRIX_WPMR_WP_WPEN                (1 << 0)
-#define                AT91_MATRIX_WPMR_WPKEY          (0xFFFFFF << 8) /* Write Protect KEY */
-
-#define AT91_MATRIX_WPSR       (AT91_MATRIX + 0x1E8)   /* Write Protect Status Register */
-#define                AT91_MATRIX_WPSR_WPVS           (1 << 0)        /* Write Protect Violation Status */
-#define                        AT91_MATRIX_WPSR_NO_WPV         (0 << 0)
-#define                        AT91_MATRIX_WPSR_WPV            (1 << 0)
-#define                AT91_MATRIX_WPSR_WPVSRC         (0xFFFF << 8)   /* Write Protect Violation Source */
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/at91sam9rl.h b/arch/arm/mach-at91/include/mach/at91sam9rl.h
deleted file mode 100644 (file)
index a15db56..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91sam9260.h
- *
- *  Copyright (C) 2007 Atmel Corporation
- *
- * Common definitions.
- * Based on AT91SAM9RL datasheet revision A. (Preliminary)
- *
- * 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.
- */
-
-#ifndef AT91SAM9RL_H
-#define AT91SAM9RL_H
-
-/*
- * Peripheral identifiers/interrupts.
- */
-#define AT91SAM9RL_ID_PIOA     2       /* Parallel IO Controller A */
-#define AT91SAM9RL_ID_PIOB     3       /* Parallel IO Controller B */
-#define AT91SAM9RL_ID_PIOC     4       /* Parallel IO Controller C */
-#define AT91SAM9RL_ID_PIOD     5       /* Parallel IO Controller D */
-#define AT91SAM9RL_ID_US0      6       /* USART 0 */
-#define AT91SAM9RL_ID_US1      7       /* USART 1 */
-#define AT91SAM9RL_ID_US2      8       /* USART 2 */
-#define AT91SAM9RL_ID_US3      9       /* USART 3 */
-#define AT91SAM9RL_ID_MCI      10      /* Multimedia Card Interface */
-#define AT91SAM9RL_ID_TWI0     11      /* TWI 0 */
-#define AT91SAM9RL_ID_TWI1     12      /* TWI 1 */
-#define AT91SAM9RL_ID_SPI      13      /* Serial Peripheral Interface */
-#define AT91SAM9RL_ID_SSC0     14      /* Serial Synchronous Controller 0 */
-#define AT91SAM9RL_ID_SSC1     15      /* Serial Synchronous Controller 1 */
-#define AT91SAM9RL_ID_TC0      16      /* Timer Counter 0 */
-#define AT91SAM9RL_ID_TC1      17      /* Timer Counter 1 */
-#define AT91SAM9RL_ID_TC2      18      /* Timer Counter 2 */
-#define AT91SAM9RL_ID_PWMC     19      /* Pulse Width Modulation Controller */
-#define AT91SAM9RL_ID_TSC      20      /* Touch Screen Controller */
-#define AT91SAM9RL_ID_DMA      21      /* DMA Controller */
-#define AT91SAM9RL_ID_UDPHS    22      /* USB Device HS */
-#define AT91SAM9RL_ID_LCDC     23      /* LCD Controller */
-#define AT91SAM9RL_ID_AC97C    24      /* AC97 Controller */
-#define AT91SAM9RL_ID_IRQ0     31      /* Advanced Interrupt Controller (IRQ0) */
-
-
-/*
- * User Peripheral physical base addresses.
- */
-#define AT91SAM9RL_BASE_TCB0   0xfffa0000
-#define AT91SAM9RL_BASE_TC0    0xfffa0000
-#define AT91SAM9RL_BASE_TC1    0xfffa0040
-#define AT91SAM9RL_BASE_TC2    0xfffa0080
-#define AT91SAM9RL_BASE_MCI    0xfffa4000
-#define AT91SAM9RL_BASE_TWI0   0xfffa8000
-#define AT91SAM9RL_BASE_TWI1   0xfffac000
-#define AT91SAM9RL_BASE_US0    0xfffb0000
-#define AT91SAM9RL_BASE_US1    0xfffb4000
-#define AT91SAM9RL_BASE_US2    0xfffb8000
-#define AT91SAM9RL_BASE_US3    0xfffbc000
-#define AT91SAM9RL_BASE_SSC0   0xfffc0000
-#define AT91SAM9RL_BASE_SSC1   0xfffc4000
-#define AT91SAM9RL_BASE_PWMC   0xfffc8000
-#define AT91SAM9RL_BASE_SPI    0xfffcc000
-#define AT91SAM9RL_BASE_TSC    0xfffd0000
-#define AT91SAM9RL_BASE_UDPHS  0xfffd4000
-#define AT91SAM9RL_BASE_AC97C  0xfffd8000
-
-
-/*
- * System Peripherals (offset from AT91_BASE_SYS)
- */
-#define AT91_SCKCR     (0xfffffd50 - AT91_BASE_SYS)
-
-#define AT91SAM9RL_BASE_DMA    0xffffe600
-#define AT91SAM9RL_BASE_ECC    0xffffe800
-#define AT91SAM9RL_BASE_SDRAMC 0xffffea00
-#define AT91SAM9RL_BASE_SMC    0xffffec00
-#define AT91SAM9RL_BASE_MATRIX 0xffffee00
-#define AT91SAM9RL_BASE_DBGU   AT91_BASE_DBGU0
-#define AT91SAM9RL_BASE_PIOA   0xfffff400
-#define AT91SAM9RL_BASE_PIOB   0xfffff600
-#define AT91SAM9RL_BASE_PIOC   0xfffff800
-#define AT91SAM9RL_BASE_PIOD   0xfffffa00
-#define AT91SAM9RL_BASE_RSTC   0xfffffd00
-#define AT91SAM9RL_BASE_SHDWC  0xfffffd10
-#define AT91SAM9RL_BASE_RTT    0xfffffd20
-#define AT91SAM9RL_BASE_PIT    0xfffffd30
-#define AT91SAM9RL_BASE_WDT    0xfffffd40
-#define AT91SAM9RL_BASE_GPBR   0xfffffd60
-#define AT91SAM9RL_BASE_RTC    0xfffffe00
-
-
-/*
- * Internal Memory.
- */
-#define AT91SAM9RL_SRAM_BASE   0x00300000      /* Internal SRAM base address */
-#define AT91SAM9RL_SRAM_SIZE   SZ_16K          /* Internal SRAM size (16Kb) */
-
-#define AT91SAM9RL_ROM_BASE    0x00400000      /* Internal ROM base address */
-#define AT91SAM9RL_ROM_SIZE    (2 * SZ_16K)    /* Internal ROM size (32Kb) */
-
-#define AT91SAM9RL_LCDC_BASE   0x00500000      /* LCD Controller */
-#define AT91SAM9RL_UDPHS_FIFO  0x00600000      /* USB Device HS controller */
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/at91sam9rl_matrix.h b/arch/arm/mach-at91/include/mach/at91sam9rl_matrix.h
deleted file mode 100644 (file)
index 6d160ad..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91sam9rl_matrix.h
- *
- *  Copyright (C) 2007 Atmel Corporation
- *
- * Memory Controllers (MATRIX, EBI) - System peripherals registers.
- * Based on AT91SAM9RL datasheet revision A. (Preliminary)
- *
- * 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.
- */
-
-#ifndef AT91SAM9RL_MATRIX_H
-#define AT91SAM9RL_MATRIX_H
-
-#define AT91_MATRIX_MCFG0      0x00                    /* Master Configuration Register 0 */
-#define AT91_MATRIX_MCFG1      0x04                    /* Master Configuration Register 1 */
-#define AT91_MATRIX_MCFG2      0x08                    /* Master Configuration Register 2 */
-#define AT91_MATRIX_MCFG3      0x0C                    /* Master Configuration Register 3 */
-#define AT91_MATRIX_MCFG4      0x10                    /* Master Configuration Register 4 */
-#define AT91_MATRIX_MCFG5      0x14                    /* Master Configuration Register 5 */
-#define                AT91_MATRIX_ULBT        (7 << 0)        /* Undefined Length Burst Type */
-#define                        AT91_MATRIX_ULBT_INFINITE       (0 << 0)
-#define                        AT91_MATRIX_ULBT_SINGLE         (1 << 0)
-#define                        AT91_MATRIX_ULBT_FOUR           (2 << 0)
-#define                        AT91_MATRIX_ULBT_EIGHT          (3 << 0)
-#define                        AT91_MATRIX_ULBT_SIXTEEN        (4 << 0)
-
-#define AT91_MATRIX_SCFG0      0x40                    /* Slave Configuration Register 0 */
-#define AT91_MATRIX_SCFG1      0x44                    /* Slave Configuration Register 1 */
-#define AT91_MATRIX_SCFG2      0x48                    /* Slave Configuration Register 2 */
-#define AT91_MATRIX_SCFG3      0x4C                    /* Slave Configuration Register 3 */
-#define AT91_MATRIX_SCFG4      0x50                    /* Slave Configuration Register 4 */
-#define AT91_MATRIX_SCFG5      0x54                    /* Slave Configuration Register 5 */
-#define                AT91_MATRIX_SLOT_CYCLE          (0xff << 0)     /* Maximum Number of Allowed Cycles for a Burst */
-#define                AT91_MATRIX_DEFMSTR_TYPE        (3    << 16)    /* Default Master Type */
-#define                        AT91_MATRIX_DEFMSTR_TYPE_NONE   (0 << 16)
-#define                        AT91_MATRIX_DEFMSTR_TYPE_LAST   (1 << 16)
-#define                        AT91_MATRIX_DEFMSTR_TYPE_FIXED  (2 << 16)
-#define                AT91_MATRIX_FIXED_DEFMSTR       (0xf  << 18)    /* Fixed Index of Default Master */
-#define                AT91_MATRIX_ARBT                (3    << 24)    /* Arbitration Type */
-#define                        AT91_MATRIX_ARBT_ROUND_ROBIN    (0 << 24)
-#define                        AT91_MATRIX_ARBT_FIXED_PRIORITY (1 << 24)
-
-#define AT91_MATRIX_PRAS0      0x80                    /* Priority Register A for Slave 0 */
-#define AT91_MATRIX_PRAS1      0x88                    /* Priority Register A for Slave 1 */
-#define AT91_MATRIX_PRAS2      0x90                    /* Priority Register A for Slave 2 */
-#define AT91_MATRIX_PRAS3      0x98                    /* Priority Register A for Slave 3 */
-#define AT91_MATRIX_PRAS4      0xA0                    /* Priority Register A for Slave 4 */
-#define AT91_MATRIX_PRAS5      0xA8                    /* Priority Register A for Slave 5 */
-#define                AT91_MATRIX_M0PR                (3 << 0)        /* Master 0 Priority */
-#define                AT91_MATRIX_M1PR                (3 << 4)        /* Master 1 Priority */
-#define                AT91_MATRIX_M2PR                (3 << 8)        /* Master 2 Priority */
-#define                AT91_MATRIX_M3PR                (3 << 12)       /* Master 3 Priority */
-#define                AT91_MATRIX_M4PR                (3 << 16)       /* Master 4 Priority */
-#define                AT91_MATRIX_M5PR                (3 << 20)       /* Master 5 Priority */
-
-#define AT91_MATRIX_MRCR       0x100                   /* Master Remap Control Register */
-#define                AT91_MATRIX_RCB0                (1 << 0)        /* Remap Command for AHB Master 0 (ARM926EJ-S Instruction Master) */
-#define                AT91_MATRIX_RCB1                (1 << 1)        /* Remap Command for AHB Master 1 (ARM926EJ-S Data Master) */
-#define                AT91_MATRIX_RCB2                (1 << 2)
-#define                AT91_MATRIX_RCB3                (1 << 3)
-#define                AT91_MATRIX_RCB4                (1 << 4)
-#define                AT91_MATRIX_RCB5                (1 << 5)
-
-#define AT91_MATRIX_TCMR       0x114                   /* TCM Configuration Register */
-#define                AT91_MATRIX_ITCM_SIZE           (0xf << 0)      /* Size of ITCM enabled memory block */
-#define                        AT91_MATRIX_ITCM_0              (0 << 0)
-#define                        AT91_MATRIX_ITCM_16             (5 << 0)
-#define                        AT91_MATRIX_ITCM_32             (6 << 0)
-#define                AT91_MATRIX_DTCM_SIZE           (0xf << 4)      /* Size of DTCM enabled memory block */
-#define                        AT91_MATRIX_DTCM_0              (0 << 4)
-#define                        AT91_MATRIX_DTCM_16             (5 << 4)
-#define                        AT91_MATRIX_DTCM_32             (6 << 4)
-
-#define AT91_MATRIX_EBICSA     0x120                   /* EBI0 Chip Select Assignment Register */
-#define                AT91_MATRIX_CS1A                (1 << 1)        /* Chip Select 1 Assignment */
-#define                        AT91_MATRIX_CS1A_SMC            (0 << 1)
-#define                        AT91_MATRIX_CS1A_SDRAMC         (1 << 1)
-#define                AT91_MATRIX_CS3A                (1 << 3)        /* Chip Select 3 Assignment */
-#define                        AT91_MATRIX_CS3A_SMC            (0 << 3)
-#define                        AT91_MATRIX_CS3A_SMC_SMARTMEDIA (1 << 3)
-#define                AT91_MATRIX_CS4A                (1 << 4)        /* Chip Select 4 Assignment */
-#define                        AT91_MATRIX_CS4A_SMC            (0 << 4)
-#define                        AT91_MATRIX_CS4A_SMC_CF1        (1 << 4)
-#define                AT91_MATRIX_CS5A                (1 << 5)        /* Chip Select 5 Assignment */
-#define                        AT91_MATRIX_CS5A_SMC            (0 << 5)
-#define                        AT91_MATRIX_CS5A_SMC_CF2        (1 << 5)
-#define                AT91_MATRIX_DBPUC               (1 << 8)        /* Data Bus Pull-up Configuration */
-#define                AT91_MATRIX_VDDIOMSEL           (1 << 16)       /* Memory voltage selection */
-#define                        AT91_MATRIX_VDDIOMSEL_1_8V      (0 << 16)
-#define                        AT91_MATRIX_VDDIOMSEL_3_3V      (1 << 16)
-
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/at91sam9x5.h b/arch/arm/mach-at91/include/mach/at91sam9x5.h
deleted file mode 100644 (file)
index 2fc76c4..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Chip-specific header file for the AT91SAM9x5 family
- *
- *  Copyright (C) 2009-2012 Atmel Corporation.
- *
- * Common definitions.
- * Based on AT91SAM9x5 datasheet.
- *
- * Licensed under GPLv2 or later.
- */
-
-#ifndef AT91SAM9X5_H
-#define AT91SAM9X5_H
-
-/*
- * Peripheral identifiers/interrupts.
- */
-#define AT91SAM9X5_ID_PIOAB    2       /* Parallel I/O Controller A and B */
-#define AT91SAM9X5_ID_PIOCD    3       /* Parallel I/O Controller C and D */
-#define AT91SAM9X5_ID_SMD      4       /* SMD Soft Modem (SMD) */
-#define AT91SAM9X5_ID_USART0   5       /* USART 0 */
-#define AT91SAM9X5_ID_USART1   6       /* USART 1 */
-#define AT91SAM9X5_ID_USART2   7       /* USART 2 */
-#define AT91SAM9X5_ID_USART3   8       /* USART 3 */
-#define AT91SAM9X5_ID_TWI0     9       /* Two-Wire Interface 0 */
-#define AT91SAM9X5_ID_TWI1     10      /* Two-Wire Interface 1 */
-#define AT91SAM9X5_ID_TWI2     11      /* Two-Wire Interface 2 */
-#define AT91SAM9X5_ID_MCI0     12      /* High Speed Multimedia Card Interface 0 */
-#define AT91SAM9X5_ID_SPI0     13      /* Serial Peripheral Interface 0 */
-#define AT91SAM9X5_ID_SPI1     14      /* Serial Peripheral Interface 1 */
-#define AT91SAM9X5_ID_UART0    15      /* UART 0 */
-#define AT91SAM9X5_ID_UART1    16      /* UART 1 */
-#define AT91SAM9X5_ID_TCB      17      /* Timer Counter 0, 1, 2, 3, 4 and 5 */
-#define AT91SAM9X5_ID_PWM      18      /* Pulse Width Modulation Controller */
-#define AT91SAM9X5_ID_ADC      19      /* ADC Controller */
-#define AT91SAM9X5_ID_DMA0     20      /* DMA Controller 0 */
-#define AT91SAM9X5_ID_DMA1     21      /* DMA Controller 1 */
-#define AT91SAM9X5_ID_UHPHS    22      /* USB Host High Speed */
-#define AT91SAM9X5_ID_UDPHS    23      /* USB Device High Speed */
-#define AT91SAM9X5_ID_EMAC0    24      /* Ethernet MAC0 */
-#define AT91SAM9X5_ID_LCDC     25      /* LCD Controller */
-#define AT91SAM9X5_ID_ISI      25      /* Image Sensor Interface */
-#define AT91SAM9X5_ID_MCI1     26      /* High Speed Multimedia Card Interface 1 */
-#define AT91SAM9X5_ID_EMAC1    27      /* Ethernet MAC1 */
-#define AT91SAM9X5_ID_SSC      28      /* Synchronous Serial Controller */
-#define AT91SAM9X5_ID_CAN0     29      /* CAN Controller 0 */
-#define AT91SAM9X5_ID_CAN1     30      /* CAN Controller 1 */
-#define AT91SAM9X5_ID_IRQ0     31      /* Advanced Interrupt Controller */
-
-/*
- * User Peripheral physical base addresses.
- */
-#define AT91SAM9X5_BASE_USART0 0xf801c000
-#define AT91SAM9X5_BASE_USART1 0xf8020000
-#define AT91SAM9X5_BASE_USART2 0xf8024000
-
-/*
- * System Peripherals
- */
-#define AT91SAM9X5_BASE_RTC    0xfffffeb0
-
-/*
- * Internal Memory.
- */
-#define AT91SAM9X5_SRAM_BASE   0x00300000      /* Internal SRAM base address */
-#define AT91SAM9X5_SRAM_SIZE   SZ_32K          /* Internal SRAM size (32Kb) */
-
-#define AT91SAM9X5_ROM_BASE    0x00400000      /* Internal ROM base address */
-#define AT91SAM9X5_ROM_SIZE    SZ_64K          /* Internal ROM size (64Kb) */
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/at91sam9x5_matrix.h b/arch/arm/mach-at91/include/mach/at91sam9x5_matrix.h
deleted file mode 100644 (file)
index a606d39..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Matrix-centric header file for the AT91SAM9x5 family
- *
- *  Copyright (C) 2009-2012 Atmel Corporation.
- *
- * Only EBI related registers.
- * Write Protect register definitions may be useful.
- *
- * Licensed under GPLv2 or later.
- */
-
-#ifndef AT91SAM9X5_MATRIX_H
-#define AT91SAM9X5_MATRIX_H
-
-#define AT91_MATRIX_EBICSA     (AT91_MATRIX + 0x120)   /* EBI Chip Select Assignment Register */
-#define                AT91_MATRIX_EBI_CS1A            (1 << 1)        /* Chip Select 1 Assignment */
-#define                        AT91_MATRIX_EBI_CS1A_SMC                (0 << 1)
-#define                        AT91_MATRIX_EBI_CS1A_SDRAMC             (1 << 1)
-#define                AT91_MATRIX_EBI_CS3A            (1 << 3)        /* Chip Select 3 Assignment */
-#define                        AT91_MATRIX_EBI_CS3A_SMC                (0 << 3)
-#define                        AT91_MATRIX_EBI_CS3A_SMC_NANDFLASH      (1 << 3)
-#define                AT91_MATRIX_EBI_DBPUC           (1 << 8)        /* Data Bus Pull-up Configuration */
-#define                        AT91_MATRIX_EBI_DBPU_ON                 (0 << 8)
-#define                        AT91_MATRIX_EBI_DBPU_OFF                (1 << 8)
-#define                AT91_MATRIX_EBI_VDDIOMSEL       (1 << 16)       /* Memory voltage selection */
-#define                        AT91_MATRIX_EBI_VDDIOMSEL_1_8V          (0 << 16)
-#define                        AT91_MATRIX_EBI_VDDIOMSEL_3_3V          (1 << 16)
-#define                AT91_MATRIX_EBI_EBI_IOSR        (1 << 17)       /* EBI I/O slew rate selection */
-#define                        AT91_MATRIX_EBI_EBI_IOSR_REDUCED        (0 << 17)
-#define                        AT91_MATRIX_EBI_EBI_IOSR_NORMAL         (1 << 17)
-#define                AT91_MATRIX_EBI_DDR_IOSR        (1 << 18)       /* DDR2 dedicated port I/O slew rate selection */
-#define                        AT91_MATRIX_EBI_DDR_IOSR_REDUCED        (0 << 18)
-#define                        AT91_MATRIX_EBI_DDR_IOSR_NORMAL         (1 << 18)
-#define                AT91_MATRIX_NFD0_SELECT         (1 << 24)       /* NAND Flash Data Bus Selection */
-#define                        AT91_MATRIX_NFD0_ON_D0                  (0 << 24)
-#define                        AT91_MATRIX_NFD0_ON_D16                 (1 << 24)
-#define                AT91_MATRIX_DDR_MP_EN           (1 << 25)       /* DDR Multi-port Enable */
-#define                        AT91_MATRIX_MP_OFF                      (0 << 25)
-#define                        AT91_MATRIX_MP_ON                       (1 << 25)
-
-#define AT91_MATRIX_WPMR       (AT91_MATRIX + 0x1E4)   /* Write Protect Mode Register */
-#define                AT91_MATRIX_WPMR_WPEN           (1 << 0)        /* Write Protect ENable */
-#define                        AT91_MATRIX_WPMR_WP_WPDIS               (0 << 0)
-#define                        AT91_MATRIX_WPMR_WP_WPEN                (1 << 0)
-#define                AT91_MATRIX_WPMR_WPKEY          (0xFFFFFF << 8) /* Write Protect KEY */
-
-#define AT91_MATRIX_WPSR       (AT91_MATRIX + 0x1E8)   /* Write Protect Status Register */
-#define                AT91_MATRIX_WPSR_WPVS           (1 << 0)        /* Write Protect Violation Status */
-#define                        AT91_MATRIX_WPSR_NO_WPV         (0 << 0)
-#define                        AT91_MATRIX_WPSR_WPV            (1 << 0)
-#define                AT91_MATRIX_WPSR_WPVSRC         (0xFFFF << 8)   /* Write Protect Violation Source */
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/cpu.h b/arch/arm/mach-at91/include/mach/cpu.h
deleted file mode 100644 (file)
index ce7c80a..0000000
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/cpu.h
- *
- * Copyright (C) 2006 SAN People
- * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.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.
- *
- */
-
-#ifndef __MACH_CPU_H__
-#define __MACH_CPU_H__
-
-#define ARCH_ID_AT91RM9200     0x09290780
-#define ARCH_ID_AT91SAM9260    0x019803a0
-#define ARCH_ID_AT91SAM9261    0x019703a0
-#define ARCH_ID_AT91SAM9263    0x019607a0
-#define ARCH_ID_AT91SAM9G10    0x019903a0
-#define ARCH_ID_AT91SAM9G20    0x019905a0
-#define ARCH_ID_AT91SAM9RL64   0x019b03a0
-#define ARCH_ID_AT91SAM9G45    0x819b05a0
-#define ARCH_ID_AT91SAM9G45MRL 0x819b05a2      /* aka 9G45-ES2 & non ES lots */
-#define ARCH_ID_AT91SAM9G45ES  0x819b05a1      /* 9G45-ES (Engineering Sample) */
-#define ARCH_ID_AT91SAM9X5     0x819a05a0
-#define ARCH_ID_AT91SAM9N12    0x819a07a0
-
-#define ARCH_ID_AT91SAM9XE128  0x329973a0
-#define ARCH_ID_AT91SAM9XE256  0x329a93a0
-#define ARCH_ID_AT91SAM9XE512  0x329aa3a0
-
-#define ARCH_ID_AT91M40800     0x14080044
-#define ARCH_ID_AT91R40807     0x44080746
-#define ARCH_ID_AT91M40807     0x14080745
-#define ARCH_ID_AT91R40008     0x44000840
-
-#define ARCH_ID_SAMA5          0x8A5C07C0
-
-#define ARCH_EXID_AT91SAM9M11  0x00000001
-#define ARCH_EXID_AT91SAM9M10  0x00000002
-#define ARCH_EXID_AT91SAM9G46  0x00000003
-#define ARCH_EXID_AT91SAM9G45  0x00000004
-
-#define ARCH_EXID_AT91SAM9G15  0x00000000
-#define ARCH_EXID_AT91SAM9G35  0x00000001
-#define ARCH_EXID_AT91SAM9X35  0x00000002
-#define ARCH_EXID_AT91SAM9G25  0x00000003
-#define ARCH_EXID_AT91SAM9X25  0x00000004
-
-#define ARCH_EXID_SAMA5D3      0x00004300
-#define ARCH_EXID_SAMA5D31     0x00444300
-#define ARCH_EXID_SAMA5D33     0x00414300
-#define ARCH_EXID_SAMA5D34     0x00414301
-#define ARCH_EXID_SAMA5D35     0x00584300
-#define ARCH_EXID_SAMA5D36     0x00004301
-
-#define ARCH_EXID_SAMA5D4      0x00000007
-#define ARCH_EXID_SAMA5D41     0x00000001
-#define ARCH_EXID_SAMA5D42     0x00000002
-#define ARCH_EXID_SAMA5D43     0x00000003
-#define ARCH_EXID_SAMA5D44     0x00000004
-
-#define ARCH_FAMILY_AT91SAM9   0x01900000
-#define ARCH_FAMILY_AT91SAM9XE 0x02900000
-
-/* RM9200 type */
-#define ARCH_REVISON_9200_BGA  (0 << 0)
-#define ARCH_REVISON_9200_PQFP (1 << 0)
-
-#ifndef __ASSEMBLY__
-enum at91_soc_type {
-       /* 920T */
-       AT91_SOC_RM9200,
-
-       /* SAM92xx */
-       AT91_SOC_SAM9260, AT91_SOC_SAM9261, AT91_SOC_SAM9263,
-
-       /* SAM9Gxx */
-       AT91_SOC_SAM9G10, AT91_SOC_SAM9G20, AT91_SOC_SAM9G45,
-
-       /* SAM9RL */
-       AT91_SOC_SAM9RL,
-
-       /* SAM9X5 */
-       AT91_SOC_SAM9X5,
-
-       /* SAM9N12 */
-       AT91_SOC_SAM9N12,
-
-       /* SAMA5D3 */
-       AT91_SOC_SAMA5D3,
-
-       /* SAMA5D4 */
-       AT91_SOC_SAMA5D4,
-
-       /* Unknown type */
-       AT91_SOC_UNKNOWN,
-};
-
-enum at91_soc_subtype {
-       /* RM9200 */
-       AT91_SOC_RM9200_BGA, AT91_SOC_RM9200_PQFP,
-
-       /* SAM9260 */
-       AT91_SOC_SAM9XE,
-
-       /* SAM9G45 */
-       AT91_SOC_SAM9G45ES, AT91_SOC_SAM9M10, AT91_SOC_SAM9G46, AT91_SOC_SAM9M11,
-
-       /* SAM9X5 */
-       AT91_SOC_SAM9G15, AT91_SOC_SAM9G35, AT91_SOC_SAM9X35,
-       AT91_SOC_SAM9G25, AT91_SOC_SAM9X25,
-
-       /* SAMA5D3 */
-       AT91_SOC_SAMA5D31, AT91_SOC_SAMA5D33, AT91_SOC_SAMA5D34,
-       AT91_SOC_SAMA5D35, AT91_SOC_SAMA5D36,
-
-       /* SAMA5D4 */
-       AT91_SOC_SAMA5D41, AT91_SOC_SAMA5D42, AT91_SOC_SAMA5D43,
-       AT91_SOC_SAMA5D44,
-
-       /* No subtype for this SoC */
-       AT91_SOC_SUBTYPE_NONE,
-
-       /* Unknown subtype */
-       AT91_SOC_SUBTYPE_UNKNOWN,
-};
-
-struct at91_socinfo {
-       unsigned int type, subtype;
-       unsigned int cidr, exid;
-};
-
-extern struct at91_socinfo at91_soc_initdata;
-const char *at91_get_soc_type(struct at91_socinfo *c);
-const char *at91_get_soc_subtype(struct at91_socinfo *c);
-
-static inline int at91_soc_is_detected(void)
-{
-       return at91_soc_initdata.type != AT91_SOC_UNKNOWN;
-}
-
-#ifdef CONFIG_SOC_AT91RM9200
-#define cpu_is_at91rm9200()    (at91_soc_initdata.type == AT91_SOC_RM9200)
-#define cpu_is_at91rm9200_bga()        (at91_soc_initdata.subtype == AT91_SOC_RM9200_BGA)
-#define cpu_is_at91rm9200_pqfp() (at91_soc_initdata.subtype == AT91_SOC_RM9200_PQFP)
-#else
-#define cpu_is_at91rm9200()    (0)
-#define cpu_is_at91rm9200_bga()        (0)
-#define cpu_is_at91rm9200_pqfp() (0)
-#endif
-
-#ifdef CONFIG_SOC_AT91SAM9
-#define cpu_is_at91sam9xe()    (at91_soc_initdata.subtype == AT91_SOC_SAM9XE)
-#define cpu_is_at91sam9260()   (at91_soc_initdata.type == AT91_SOC_SAM9260)
-#define cpu_is_at91sam9g20()   (at91_soc_initdata.type == AT91_SOC_SAM9G20)
-#define cpu_is_at91sam9261()   (at91_soc_initdata.type == AT91_SOC_SAM9261)
-#define cpu_is_at91sam9g10()   (at91_soc_initdata.type == AT91_SOC_SAM9G10)
-#define cpu_is_at91sam9263()   (at91_soc_initdata.type == AT91_SOC_SAM9263)
-#define cpu_is_at91sam9rl()    (at91_soc_initdata.type == AT91_SOC_SAM9RL)
-#define cpu_is_at91sam9g45()   (at91_soc_initdata.type == AT91_SOC_SAM9G45)
-#define cpu_is_at91sam9g45es() (at91_soc_initdata.subtype == AT91_SOC_SAM9G45ES)
-#define cpu_is_at91sam9m10()   (at91_soc_initdata.subtype == AT91_SOC_SAM9M10)
-#define cpu_is_at91sam9g46()   (at91_soc_initdata.subtype == AT91_SOC_SAM9G46)
-#define cpu_is_at91sam9m11()   (at91_soc_initdata.subtype == AT91_SOC_SAM9M11)
-#define cpu_is_at91sam9x5()    (at91_soc_initdata.type == AT91_SOC_SAM9X5)
-#define cpu_is_at91sam9g15()   (at91_soc_initdata.subtype == AT91_SOC_SAM9G15)
-#define cpu_is_at91sam9g35()   (at91_soc_initdata.subtype == AT91_SOC_SAM9G35)
-#define cpu_is_at91sam9x35()   (at91_soc_initdata.subtype == AT91_SOC_SAM9X35)
-#define cpu_is_at91sam9g25()   (at91_soc_initdata.subtype == AT91_SOC_SAM9G25)
-#define cpu_is_at91sam9x25()   (at91_soc_initdata.subtype == AT91_SOC_SAM9X25)
-#define cpu_is_at91sam9n12()   (at91_soc_initdata.type == AT91_SOC_SAM9N12)
-#else
-#define cpu_is_at91sam9xe()    (0)
-#define cpu_is_at91sam9260()   (0)
-#define cpu_is_at91sam9g20()   (0)
-#define cpu_is_at91sam9261()   (0)
-#define cpu_is_at91sam9g10()   (0)
-#define cpu_is_at91sam9263()   (0)
-#define cpu_is_at91sam9rl()    (0)
-#define cpu_is_at91sam9g45()   (0)
-#define cpu_is_at91sam9g45es() (0)
-#define cpu_is_at91sam9m10()   (0)
-#define cpu_is_at91sam9g46()   (0)
-#define cpu_is_at91sam9m11()   (0)
-#define cpu_is_at91sam9x5()    (0)
-#define cpu_is_at91sam9g15()   (0)
-#define cpu_is_at91sam9g35()   (0)
-#define cpu_is_at91sam9x35()   (0)
-#define cpu_is_at91sam9g25()   (0)
-#define cpu_is_at91sam9x25()   (0)
-#define cpu_is_at91sam9n12()   (0)
-#endif
-
-#ifdef CONFIG_SOC_SAMA5D3
-#define cpu_is_sama5d3()       (at91_soc_initdata.type == AT91_SOC_SAMA5D3)
-#else
-#define cpu_is_sama5d3()       (0)
-#endif
-
-#ifdef CONFIG_SOC_SAMA5D4
-#define cpu_is_sama5d4()       (at91_soc_initdata.type == AT91_SOC_SAMA5D4)
-#else
-#define cpu_is_sama5d4()       (0)
-#endif
-
-/*
- * Since this is ARM, we will never run on any AVR32 CPU. But these
- * definitions may reduce clutter in common drivers.
- */
-#define cpu_is_at32ap7000()    (0)
-#endif /* __ASSEMBLY__ */
-
-#endif /* __MACH_CPU_H__ */
diff --git a/arch/arm/mach-at91/include/mach/hardware.h b/arch/arm/mach-at91/include/mach/hardware.h
deleted file mode 100644 (file)
index cacbaa5..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/hardware.h
- *
- *  Copyright (C) 2003 SAN People
- *  Copyright (C) 2003 ATMEL
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-#include <asm/sizes.h>
-
-/* DBGU base */
-/* rm9200, 9260/9g20, 9261/9g10, 9rl */
-#define AT91_BASE_DBGU0        0xfffff200
-/* 9263, 9g45, sama5d3 */
-#define AT91_BASE_DBGU1        0xffffee00
-/* sama5d4 */
-#define AT91_BASE_DBGU2        0xfc069000
-
-#include <mach/at91rm9200.h>
-#include <mach/at91sam9260.h>
-#include <mach/at91sam9261.h>
-#include <mach/at91sam9263.h>
-#include <mach/at91sam9rl.h>
-#include <mach/at91sam9g45.h>
-#include <mach/at91sam9x5.h>
-#include <mach/at91sam9n12.h>
-#include <mach/sama5d3.h>
-#include <mach/sama5d4.h>
-
-/*
- * On all at91 except rm9200 and x40 have the System Controller starts
- * at address 0xffffc000 and has a size of 16KiB.
- *
- * On rm9200 it's start at 0xfffe4000 of 111KiB with non reserved data starting
- * at 0xfffff000
- *
- * Removes the individual definitions of AT91_BASE_SYS and
- * replaces them with a common version at base 0xfffffc000 and size 16KiB
- * and map the same memory space
- */
-#define AT91_BASE_SYS  0xffffc000
-
-/*
- * On sama5d4 there is no system controller, we map some needed peripherals
- */
-#define AT91_ALT_BASE_SYS      0xfc069000
-
-/*
- * On all at91 have the Advanced Interrupt Controller starts at address
- * 0xfffff000 and the Power Management Controller starts at 0xfffffc00
- */
-#define AT91_AIC       0xfffff000
-#define AT91_PMC       0xfffffc00
-
-/*
- * Peripheral identifiers/interrupts.
- */
-#define AT91_ID_FIQ            0       /* Advanced Interrupt Controller (FIQ) */
-#define AT91_ID_SYS            1       /* System Peripherals */
-
-#ifdef CONFIG_MMU
-/*
- * Remap the peripherals from address 0xFFF78000 .. 0xFFFFFFFF
- * to 0xFEF78000 .. 0xFF000000.  (544Kb)
- */
-#define AT91_IO_PHYS_BASE      0xFFF78000
-#define AT91_IO_VIRT_BASE      IOMEM(0xFF000000 - AT91_IO_SIZE)
-
-/*
- * On sama5d4, remap the peripherals from address 0xFC069000 .. 0xFC06F000
- * to 0xFB069000 .. 0xFB06F000.  (24Kb)
- */
-#define AT91_ALT_IO_PHYS_BASE  AT91_ALT_BASE_SYS
-#define AT91_ALT_IO_VIRT_BASE  IOMEM(0xFB069000)
-#else
-/*
- * Identity mapping for the non MMU case.
- */
-#define AT91_IO_PHYS_BASE      AT91_BASE_SYS
-#define AT91_IO_VIRT_BASE      IOMEM(AT91_IO_PHYS_BASE)
-
-#define AT91_ALT_IO_PHYS_BASE  AT91_ALT_BASE_SYS
-#define AT91_ALT_IO_VIRT_BASE  IOMEM(AT91_ALT_BASE_SYS)
-#endif
-
-#define AT91_IO_SIZE           (0xFFFFFFFF - AT91_IO_PHYS_BASE + 1)
-
- /* Convert a physical IO address to virtual IO address */
-#define AT91_IO_P2V(x)         ((x) - AT91_IO_PHYS_BASE + AT91_IO_VIRT_BASE)
-#define AT91_ALT_IO_P2V(x)     ((x) - AT91_ALT_IO_PHYS_BASE + AT91_ALT_IO_VIRT_BASE)
-
-/*
- * Virtual to Physical Address mapping for IO devices.
- */
-#define AT91_VA_BASE_SYS       AT91_IO_P2V(AT91_BASE_SYS)
-#define AT91_ALT_VA_BASE_SYS   AT91_ALT_IO_P2V(AT91_ALT_BASE_SYS)
-
- /* Internal SRAM is mapped below the IO devices */
-#define AT91_SRAM_MAX          SZ_1M
-#define AT91_VIRT_BASE         (AT91_IO_VIRT_BASE - AT91_SRAM_MAX)
-
-/* External Memory Map */
-#define AT91_CHIPSELECT_0      0x10000000
-#define AT91_CHIPSELECT_1      0x20000000
-#define AT91_CHIPSELECT_2      0x30000000
-#define AT91_CHIPSELECT_3      0x40000000
-#define AT91_CHIPSELECT_4      0x50000000
-#define AT91_CHIPSELECT_5      0x60000000
-#define AT91_CHIPSELECT_6      0x70000000
-#define AT91_CHIPSELECT_7      0x80000000
-
-/* Clocks */
-#define AT91_SLOW_CLOCK                32768           /* slow clock */
-
-/*
- * FIXME: this is needed to communicate between the pinctrl driver and
- * the PM implementation in the machine. Possibly part of the PM
- * implementation should be moved down into the pinctrl driver and get
- * called as part of the generic suspend/resume path.
- */
-#ifndef __ASSEMBLY__
-extern void at91_pinctrl_gpio_suspend(void);
-extern void at91_pinctrl_gpio_resume(void);
-#endif
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/io.h b/arch/arm/mach-at91/include/mach/io.h
deleted file mode 100644 (file)
index 2d9ca04..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/io.h
- *
- *  Copyright (C) 2003 SAN People
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef __ASM_ARCH_IO_H
-#define __ASM_ARCH_IO_H
-
-#define IO_SPACE_LIMIT         0xFFFFFFFF
-#define __io(a)                        __typesafe_io(a)
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/sama5d3.h b/arch/arm/mach-at91/include/mach/sama5d3.h
deleted file mode 100644 (file)
index 25613d8..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Chip-specific header file for the SAMA5D3 family
- *
- *  Copyright (C) 2013 Atmel,
- *                2013 Ludovic Desroches <ludovic.desroches@atmel.com>
- *
- * Common definitions.
- * Based on SAMA5D3 datasheet.
- *
- * Licensed under GPLv2 or later.
- */
-
-#ifndef SAMA5D3_H
-#define SAMA5D3_H
-
-/*
- * Peripheral identifiers/interrupts.
- */
-#define AT91_ID_FIQ             0      /* Advanced Interrupt Controller (FIQ) */
-#define AT91_ID_SYS             1      /* System Peripherals */
-#define SAMA5D3_ID_DBGU                 2      /* debug Unit (usually no special interrupt line) */
-#define AT91_ID_PIT             3      /* PIT */
-#define SAMA5D3_ID_WDT          4      /* Watchdog Timer Interrupt */
-#define SAMA5D3_ID_HSMC                 5      /* Static Memory Controller */
-#define SAMA5D3_ID_PIOA                 6      /* PIOA */
-#define SAMA5D3_ID_PIOB                 7      /* PIOB */
-#define SAMA5D3_ID_PIOC                 8      /* PIOC */
-#define SAMA5D3_ID_PIOD                 9      /* PIOD */
-#define SAMA5D3_ID_PIOE                10      /* PIOE */
-#define SAMA5D3_ID_SMD         11      /* SMD Soft Modem */
-#define SAMA5D3_ID_USART0      12      /* USART0 */
-#define SAMA5D3_ID_USART1      13      /* USART1 */
-#define SAMA5D3_ID_USART2      14      /* USART2 */
-#define SAMA5D3_ID_USART3      15      /* USART3 */
-#define SAMA5D3_ID_UART0       16      /* UART 0 */
-#define SAMA5D3_ID_UART1       17      /* UART 1 */
-#define SAMA5D3_ID_TWI0                18      /* Two-Wire Interface 0 */
-#define SAMA5D3_ID_TWI1                19      /* Two-Wire Interface 1 */
-#define SAMA5D3_ID_TWI2                20      /* Two-Wire Interface 2 */
-#define SAMA5D3_ID_HSMCI0      21      /* MCI */
-#define SAMA5D3_ID_HSMCI1      22      /* MCI */
-#define SAMA5D3_ID_HSMCI2      23      /* MCI */
-#define SAMA5D3_ID_SPI0                24      /* Serial Peripheral Interface 0 */
-#define SAMA5D3_ID_SPI1                25      /* Serial Peripheral Interface 1 */
-#define SAMA5D3_ID_TC0         26      /* Timer Counter 0 */
-#define SAMA5D3_ID_TC1         27      /* Timer Counter 2 */
-#define SAMA5D3_ID_PWM         28      /* Pulse Width Modulation Controller */
-#define SAMA5D3_ID_ADC         29      /* Touch Screen ADC Controller */
-#define SAMA5D3_ID_DMA0                30      /* DMA Controller 0 */
-#define SAMA5D3_ID_DMA1                31      /* DMA Controller 1 */
-#define SAMA5D3_ID_UHPHS       32      /* USB Host High Speed */
-#define SAMA5D3_ID_UDPHS       33      /* USB Device High Speed */
-#define SAMA5D3_ID_GMAC                34      /* Gigabit Ethernet MAC */
-#define SAMA5D3_ID_EMAC                35      /* Ethernet MAC */
-#define SAMA5D3_ID_LCDC                36      /* LCD Controller */
-#define SAMA5D3_ID_ISI         37      /* Image Sensor Interface */
-#define SAMA5D3_ID_SSC0                38      /* Synchronous Serial Controller 0 */
-#define SAMA5D3_ID_SSC1                39      /* Synchronous Serial Controller 1 */
-#define SAMA5D3_ID_CAN0                40      /* CAN Controller 0 */
-#define SAMA5D3_ID_CAN1                41      /* CAN Controller 1 */
-#define SAMA5D3_ID_SHA         42      /* Secure Hash Algorithm */
-#define SAMA5D3_ID_AES         43      /* Advanced Encryption Standard */
-#define SAMA5D3_ID_TDES                44      /* Triple Data Encryption Standard */
-#define SAMA5D3_ID_TRNG                45      /* True Random Generator Number */
-#define SAMA5D3_ID_IRQ0                47      /* Advanced Interrupt Controller (IRQ0) */
-
-/*
- * User Peripheral physical base addresses.
- */
-#define SAMA5D3_BASE_USART0    0xf001c000
-#define SAMA5D3_BASE_USART1    0xf0020000
-#define SAMA5D3_BASE_USART2    0xf8020000
-#define SAMA5D3_BASE_USART3    0xf8024000
-
-/*
- * System Peripherals
- */
-#define SAMA5D3_BASE_RTC       0xfffffeb0
-
-/*
- * Internal Memory
- */
-#define SAMA5D3_SRAM_BASE      0x00300000      /* Internal SRAM base address */
-#define SAMA5D3_SRAM_SIZE      (128 * SZ_1K)   /* Internal SRAM size (128Kb) */
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/sama5d4.h b/arch/arm/mach-at91/include/mach/sama5d4.h
deleted file mode 100644 (file)
index f256a45..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Chip-specific header file for the SAMA5D4 family
- *
- *  Copyright (C) 2013 Atmel Corporation,
- *                     Nicolas Ferre <nicolas.ferre@atmel.com>
- *
- * Common definitions.
- * Based on SAMA5D4 datasheet.
- *
- * Licensed under GPLv2 or later.
- */
-
-#ifndef SAMA5D4_H
-#define SAMA5D4_H
-
-/*
- * User Peripheral physical base addresses.
- */
-#define SAMA5D4_BASE_USART3    0xfc00c000 /* (USART3 non-secure) Base Address */
-#define SAMA5D4_BASE_PMC       0xf0018000 /* (PMC) Base Address */
-#define SAMA5D4_BASE_MPDDRC    0xf0010000 /* (MPDDRC) Base Address */
-#define SAMA5D4_BASE_PIOD      0xfc068000 /* (PIOD) Base Address */
-
-/* Some other peripherals */
-#define SAMA5D4_BASE_SYS2      SAMA5D4_BASE_PIOD
-
-/*
- * Internal Memory.
- */
-#define SAMA5D4_NS_SRAM_BASE     0x00210000      /* Internal SRAM base address Non-Secure */
-#define SAMA5D4_NS_SRAM_SIZE     (64 * SZ_1K)   /* Internal SRAM size Non-Secure part (64Kb) */
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/uncompress.h b/arch/arm/mach-at91/include/mach/uncompress.h
deleted file mode 100644 (file)
index 4ebb609..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/uncompress.h
- *
- * Copyright (C) 2003 SAN People
- * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef __ASM_ARCH_UNCOMPRESS_H
-#define __ASM_ARCH_UNCOMPRESS_H
-
-#include <linux/io.h>
-#include <linux/atmel_serial.h>
-#include <mach/hardware.h>
-
-#include <mach/at91_dbgu.h>
-#include <mach/cpu.h>
-
-void __iomem *at91_uart;
-
-static const u32 uarts_rm9200[] = {
-       AT91_BASE_DBGU0,
-       AT91RM9200_BASE_US0,
-       AT91RM9200_BASE_US1,
-       AT91RM9200_BASE_US2,
-       AT91RM9200_BASE_US3,
-       0,
-};
-
-static const u32 uarts_sam9260[] = {
-       AT91_BASE_DBGU0,
-       AT91SAM9260_BASE_US0,
-       AT91SAM9260_BASE_US1,
-       AT91SAM9260_BASE_US2,
-       AT91SAM9260_BASE_US3,
-       AT91SAM9260_BASE_US4,
-       AT91SAM9260_BASE_US5,
-       0,
-};
-
-static const u32 uarts_sam9261[] = {
-       AT91_BASE_DBGU0,
-       AT91SAM9261_BASE_US0,
-       AT91SAM9261_BASE_US1,
-       AT91SAM9261_BASE_US2,
-       0,
-};
-
-static const u32 uarts_sam9263[] = {
-       AT91_BASE_DBGU1,
-       AT91SAM9263_BASE_US0,
-       AT91SAM9263_BASE_US1,
-       AT91SAM9263_BASE_US2,
-       0,
-};
-
-static const u32 uarts_sam9g45[] = {
-       AT91_BASE_DBGU1,
-       AT91SAM9G45_BASE_US0,
-       AT91SAM9G45_BASE_US1,
-       AT91SAM9G45_BASE_US2,
-       AT91SAM9G45_BASE_US3,
-       0,
-};
-
-static const u32 uarts_sam9rl[] = {
-       AT91_BASE_DBGU0,
-       AT91SAM9RL_BASE_US0,
-       AT91SAM9RL_BASE_US1,
-       AT91SAM9RL_BASE_US2,
-       AT91SAM9RL_BASE_US3,
-       0,
-};
-
-static const u32 uarts_sam9x5[] = {
-       AT91_BASE_DBGU0,
-       AT91SAM9X5_BASE_USART0,
-       AT91SAM9X5_BASE_USART1,
-       AT91SAM9X5_BASE_USART2,
-       0,
-};
-
-static const u32 uarts_sama5d3[] = {
-       AT91_BASE_DBGU1,
-       SAMA5D3_BASE_USART0,
-       SAMA5D3_BASE_USART1,
-       SAMA5D3_BASE_USART2,
-       SAMA5D3_BASE_USART3,
-       0,
-};
-
-static const u32 uarts_sama5d4[] = {
-       AT91_BASE_DBGU2,
-       SAMA5D4_BASE_USART3,
-       0,
-};
-
-static inline const u32* decomp_soc_detect(void __iomem *dbgu_base)
-{
-       u32 cidr, socid;
-
-       cidr = __raw_readl(dbgu_base + AT91_DBGU_CIDR);
-       socid = cidr & ~AT91_CIDR_VERSION;
-
-       switch (socid) {
-       case ARCH_ID_AT91RM9200:
-               return uarts_rm9200;
-
-       case ARCH_ID_AT91SAM9G20:
-       case ARCH_ID_AT91SAM9260:
-               return uarts_sam9260;
-
-       case ARCH_ID_AT91SAM9261:
-               return uarts_sam9261;
-
-       case ARCH_ID_AT91SAM9263:
-               return uarts_sam9263;
-
-       case ARCH_ID_AT91SAM9G45:
-               return uarts_sam9g45;
-
-       case ARCH_ID_AT91SAM9RL64:
-               return uarts_sam9rl;
-
-       case ARCH_ID_AT91SAM9N12:
-       case ARCH_ID_AT91SAM9X5:
-               return uarts_sam9x5;
-
-       case ARCH_ID_SAMA5:
-               cidr = __raw_readl(dbgu_base + AT91_DBGU_EXID);
-               if (cidr & ARCH_EXID_SAMA5D3)
-                       return uarts_sama5d3;
-               else if (cidr & ARCH_EXID_SAMA5D4)
-                       return uarts_sama5d4;
-
-               break;
-       }
-
-       /* at91sam9g10 */
-       if ((cidr & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) {
-               return uarts_sam9261;
-       }
-       /* at91sam9xe */
-       else if ((cidr & AT91_CIDR_ARCH) == ARCH_FAMILY_AT91SAM9XE) {
-               return uarts_sam9260;
-       }
-
-       return NULL;
-}
-
-static inline void arch_decomp_setup(void)
-{
-       int i = 0;
-       const u32* usarts;
-
-       usarts = decomp_soc_detect((void __iomem *)AT91_BASE_DBGU0);
-       if (!usarts)
-               usarts = decomp_soc_detect((void __iomem *)AT91_BASE_DBGU1);
-       if (!usarts)
-               usarts = decomp_soc_detect((void __iomem *)AT91_BASE_DBGU2);
-       if (!usarts) {
-               at91_uart = NULL;
-               return;
-       }
-
-       do {
-               /* physical address */
-               at91_uart = (void __iomem *)usarts[i];
-
-               if (__raw_readl(at91_uart + ATMEL_US_BRGR))
-                       return;
-               i++;
-       } while (usarts[i]);
-
-       at91_uart = NULL;
-}
-
-/*
- * The following code assumes the serial port has already been
- * initialized by the bootloader.  If you didn't setup a port in
- * your bootloader then nothing will appear (which might be desired).
- *
- * This does not append a newline
- */
-static void putc(int c)
-{
-       if (!at91_uart)
-               return;
-
-       while (!(__raw_readl(at91_uart + ATMEL_US_CSR) & ATMEL_US_TXRDY))
-               barrier();
-       __raw_writel(c, at91_uart + ATMEL_US_THR);
-}
-
-static inline void flush(void)
-{
-       if (!at91_uart)
-               return;
-
-       /* wait for transmission to complete */
-       while (!(__raw_readl(at91_uart + ATMEL_US_CSR) & ATMEL_US_TXEMPTY))
-               barrier();
-}
-
-#endif
index aa4116e9452f725e0f63241cfc083576c665be19..5062699cbb1258697c8f95046f30a125e4e14cae 100644 (file)
 #include <linux/atomic.h>
 #include <asm/mach/time.h>
 #include <asm/mach/irq.h>
-
-#include <mach/cpu.h>
-#include <mach/hardware.h>
+#include <asm/fncpy.h>
+#include <asm/cacheflush.h>
 
 #include "generic.h"
 #include "pm.h"
 
+/*
+ * FIXME: this is needed to communicate between the pinctrl driver and
+ * the PM implementation in the machine. Possibly part of the PM
+ * implementation should be moved down into the pinctrl driver and get
+ * called as part of the generic suspend/resume path.
+ */
+extern void at91_pinctrl_gpio_suspend(void);
+extern void at91_pinctrl_gpio_resume(void);
+
 static struct {
        unsigned long uhp_udp_mask;
        int memctrl;
 } at91_pm_data;
 
-static void (*at91_pm_standby)(void);
 void __iomem *at91_ramc_base[2];
 
 static int at91_pm_valid_state(suspend_state_t state)
@@ -119,76 +126,67 @@ int at91_suspend_entering_slow_clock(void)
 }
 EXPORT_SYMBOL(at91_suspend_entering_slow_clock);
 
-
-static void (*slow_clock)(void __iomem *pmc, void __iomem *ramc0,
+static void (*at91_suspend_sram_fn)(void __iomem *pmc, void __iomem *ramc0,
                          void __iomem *ramc1, int memctrl);
 
-#ifdef CONFIG_AT91_SLOW_CLOCK
-extern void at91_slow_clock(void __iomem *pmc, void __iomem *ramc0,
+extern void at91_pm_suspend_in_sram(void __iomem *pmc, void __iomem *ramc0,
                            void __iomem *ramc1, int memctrl);
-extern u32 at91_slow_clock_sz;
-#endif
+extern u32 at91_pm_suspend_in_sram_sz;
+
+static void at91_pm_suspend(suspend_state_t state)
+{
+       unsigned int pm_data = at91_pm_data.memctrl;
+
+       pm_data |= (state == PM_SUSPEND_MEM) ?
+                               AT91_PM_MODE(AT91_PM_SLOW_CLOCK) : 0;
+
+       flush_cache_all();
+       outer_disable();
+
+       at91_suspend_sram_fn(at91_pmc_base, at91_ramc_base[0],
+                               at91_ramc_base[1], pm_data);
+
+       outer_resume();
+}
 
 static int at91_pm_enter(suspend_state_t state)
 {
        at91_pinctrl_gpio_suspend();
 
        switch (state) {
+       /*
+        * Suspend-to-RAM 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
+        */
+       case PM_SUSPEND_MEM:
                /*
-                * Suspend-to-RAM is like STANDBY plus slow clock mode, so
-                * drivers must suspend more deeply:  only the master clock
-                * controller may be using the main oscillator.
+                * Ensure that clocks are in a valid state.
                 */
-               case PM_SUSPEND_MEM:
-                       /*
-                        * Ensure that clocks are in a valid state.
-                        */
-                       if (!at91_pm_verify_clocks())
-                               goto error;
-
-                       /*
-                        * Enter slow clock mode by switching over to clk32k and
-                        * turning off the main oscillator; reverse on wakeup.
-                        */
-                       if (slow_clock) {
-#ifdef CONFIG_AT91_SLOW_CLOCK
-                               /* copy slow_clock handler to SRAM, and call it */
-                               memcpy(slow_clock, at91_slow_clock, at91_slow_clock_sz);
-#endif
-                               slow_clock(at91_pmc_base, at91_ramc_base[0],
-                                          at91_ramc_base[1],
-                                          at91_pm_data.memctrl);
-                               break;
-                       } else {
-                               pr_info("AT91: PM - no slow clock mode enabled ...\n");
-                               /* FALLTHROUGH leaving master clock alone */
-                       }
+               if (!at91_pm_verify_clocks())
+                       goto error;
 
-               /*
-                * STANDBY mode has *all* drivers suspended; ignores irqs not
-                * marked as 'wakeup' 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.
-                */
-               case PM_SUSPEND_STANDBY:
-                       /*
-                        * NOTE: the Wait-for-Interrupt instruction needs to be
-                        * in icache so no SDRAM accesses are needed until the
-                        * wakeup IRQ occurs and self-refresh is terminated.
-                        * For ARM 926 based chips, this requirement is weaker
-                        * as at91sam9 can access a RAM in self-refresh mode.
-                        */
-                       if (at91_pm_standby)
-                               at91_pm_standby();
-                       break;
+               at91_pm_suspend(state);
 
-               case PM_SUSPEND_ON:
-                       cpu_do_idle();
-                       break;
+               break;
 
-               default:
-                       pr_debug("AT91: PM - bogus suspend state %d\n", state);
-                       goto error;
+       /*
+        * STANDBY mode has *all* drivers suspended; ignores irqs not
+        * marked as 'wakeup' 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.
+        */
+       case PM_SUSPEND_STANDBY:
+               at91_pm_suspend(state);
+               break;
+
+       case PM_SUSPEND_ON:
+               cpu_do_idle();
+               break;
+
+       default:
+               pr_debug("AT91: PM - bogus suspend state %d\n", state);
+               goto error;
        }
 
 error:
@@ -218,12 +216,99 @@ static struct platform_device at91_cpuidle_device = {
        .name = "cpuidle-at91",
 };
 
-void at91_pm_set_standby(void (*at91_standby)(void))
+static void at91_pm_set_standby(void (*at91_standby)(void))
 {
-       if (at91_standby) {
+       if (at91_standby)
                at91_cpuidle_device.dev.platform_data = at91_standby;
-               at91_pm_standby = at91_standby;
+}
+
+/*
+ * The AT91RM9200 goes into self-refresh mode with this command, and will
+ * terminate self-refresh automatically on the next SDRAM access.
+ *
+ * Self-refresh mode is exited as soon as a memory access is made, but we don't
+ * know for sure when that happens. However, we need to restore the low-power
+ * mode if it was enabled before going idle. Restoring low-power mode while
+ * still in self-refresh is "not recommended", but seems to work.
+ */
+static void at91rm9200_standby(void)
+{
+       u32 lpr = at91_ramc_read(0, AT91RM9200_SDRAMC_LPR);
+
+       asm volatile(
+               "b    1f\n\t"
+               ".align    5\n\t"
+               "1:  mcr    p15, 0, %0, c7, c10, 4\n\t"
+               "    str    %0, [%1, %2]\n\t"
+               "    str    %3, [%1, %4]\n\t"
+               "    mcr    p15, 0, %0, c7, c0, 4\n\t"
+               "    str    %5, [%1, %2]"
+               :
+               : "r" (0), "r" (at91_ramc_base[0]), "r" (AT91RM9200_SDRAMC_LPR),
+                 "r" (1), "r" (AT91RM9200_SDRAMC_SRR),
+                 "r" (lpr));
+}
+
+/* We manage both DDRAM/SDRAM controllers, we need more than one value to
+ * remember.
+ */
+static void at91_ddr_standby(void)
+{
+       /* Those two values allow us to delay self-refresh activation
+        * to the maximum. */
+       u32 lpr0, lpr1 = 0;
+       u32 saved_lpr0, saved_lpr1 = 0;
+
+       if (at91_ramc_base[1]) {
+               saved_lpr1 = at91_ramc_read(1, AT91_DDRSDRC_LPR);
+               lpr1 = saved_lpr1 & ~AT91_DDRSDRC_LPCB;
+               lpr1 |= AT91_DDRSDRC_LPCB_SELF_REFRESH;
+       }
+
+       saved_lpr0 = at91_ramc_read(0, AT91_DDRSDRC_LPR);
+       lpr0 = saved_lpr0 & ~AT91_DDRSDRC_LPCB;
+       lpr0 |= AT91_DDRSDRC_LPCB_SELF_REFRESH;
+
+       /* self-refresh mode now */
+       at91_ramc_write(0, AT91_DDRSDRC_LPR, lpr0);
+       if (at91_ramc_base[1])
+               at91_ramc_write(1, AT91_DDRSDRC_LPR, lpr1);
+
+       cpu_do_idle();
+
+       at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr0);
+       if (at91_ramc_base[1])
+               at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1);
+}
+
+/* We manage both DDRAM/SDRAM controllers, we need more than one value to
+ * remember.
+ */
+static void at91sam9_sdram_standby(void)
+{
+       u32 lpr0, lpr1 = 0;
+       u32 saved_lpr0, saved_lpr1 = 0;
+
+       if (at91_ramc_base[1]) {
+               saved_lpr1 = at91_ramc_read(1, AT91_SDRAMC_LPR);
+               lpr1 = saved_lpr1 & ~AT91_SDRAMC_LPCB;
+               lpr1 |= AT91_SDRAMC_LPCB_SELF_REFRESH;
        }
+
+       saved_lpr0 = at91_ramc_read(0, AT91_SDRAMC_LPR);
+       lpr0 = saved_lpr0 & ~AT91_SDRAMC_LPCB;
+       lpr0 |= AT91_SDRAMC_LPCB_SELF_REFRESH;
+
+       /* self-refresh mode now */
+       at91_ramc_write(0, AT91_SDRAMC_LPR, lpr0);
+       if (at91_ramc_base[1])
+               at91_ramc_write(1, AT91_SDRAMC_LPR, lpr1);
+
+       cpu_do_idle();
+
+       at91_ramc_write(0, AT91_SDRAMC_LPR, saved_lpr0);
+       if (at91_ramc_base[1])
+               at91_ramc_write(1, AT91_SDRAMC_LPR, saved_lpr1);
 }
 
 static const struct of_device_id ramc_ids[] __initconst = {
@@ -263,7 +348,6 @@ static __init void at91_dt_ramc(void)
        at91_pm_set_standby(standby);
 }
 
-#ifdef CONFIG_AT91_SLOW_CLOCK
 static void __init at91_pm_sram_init(void)
 {
        struct gen_pool *sram_pool;
@@ -291,30 +375,36 @@ static void __init at91_pm_sram_init(void)
                return;
        }
 
-       sram_base = gen_pool_alloc(sram_pool, at91_slow_clock_sz);
+       sram_base = gen_pool_alloc(sram_pool, at91_pm_suspend_in_sram_sz);
        if (!sram_base) {
-               pr_warn("%s: unable to alloc ocram!\n", __func__);
+               pr_warn("%s: unable to alloc sram!\n", __func__);
                return;
        }
 
        sram_pbase = gen_pool_virt_to_phys(sram_pool, sram_base);
-       slow_clock = __arm_ioremap_exec(sram_pbase, at91_slow_clock_sz, false);
-}
-#endif
+       at91_suspend_sram_fn = __arm_ioremap_exec(sram_pbase,
+                                       at91_pm_suspend_in_sram_sz, false);
+       if (!at91_suspend_sram_fn) {
+               pr_warn("SRAM: Could not map\n");
+               return;
+       }
 
+       /* Copy the pm suspend handler to SRAM */
+       at91_suspend_sram_fn = fncpy(at91_suspend_sram_fn,
+                       &at91_pm_suspend_in_sram, at91_pm_suspend_in_sram_sz);
+}
 
 static void __init at91_pm_init(void)
 {
-#ifdef CONFIG_AT91_SLOW_CLOCK
        at91_pm_sram_init();
-#endif
-
-       pr_info("AT91: Power Management%s\n", (slow_clock ? " (with slow clock mode)" : ""));
 
        if (at91_cpuidle_device.dev.platform_data)
                platform_device_register(&at91_cpuidle_device);
 
-       suspend_set_ops(&at91_pm_ops);
+       if (at91_suspend_sram_fn)
+               suspend_set_ops(&at91_pm_ops);
+       else
+               pr_info("AT91: PM not supported, due to no SRAM allocated\n");
 }
 
 void __init at91rm9200_pm_init(void)
index 86c0aa819d2590aae5af7146e5e3a4ebeb086e35..ecd875a91d5218281049b6b4b36924ddcc62b1d3 100644 (file)
 
 #include <mach/at91_ramc.h>
 
-#ifdef CONFIG_PM
-extern void at91_pm_set_standby(void (*at91_standby)(void));
-#else
-static inline void at91_pm_set_standby(void (*at91_standby)(void)) { }
-#endif
-
-/*
- * The AT91RM9200 goes into self-refresh mode with this command, and will
- * terminate self-refresh automatically on the next SDRAM access.
- *
- * Self-refresh mode is exited as soon as a memory access is made, but we don't
- * know for sure when that happens. However, we need to restore the low-power
- * mode if it was enabled before going idle. Restoring low-power mode while
- * still in self-refresh is "not recommended", but seems to work.
- */
-
-static inline void at91rm9200_standby(void)
-{
-       u32 lpr = at91_ramc_read(0, AT91RM9200_SDRAMC_LPR);
-
-       asm volatile(
-               "b    1f\n\t"
-               ".align    5\n\t"
-               "1:  mcr    p15, 0, %0, c7, c10, 4\n\t"
-               "    str    %0, [%1, %2]\n\t"
-               "    str    %3, [%1, %4]\n\t"
-               "    mcr    p15, 0, %0, c7, c0, 4\n\t"
-               "    str    %5, [%1, %2]"
-               :
-               : "r" (0), "r" (at91_ramc_base[0]), "r" (AT91RM9200_SDRAMC_LPR),
-                 "r" (1), "r" (AT91RM9200_SDRAMC_SRR),
-                 "r" (lpr));
-}
-
-/* We manage both DDRAM/SDRAM controllers, we need more than one value to
- * remember.
- */
-static inline void at91_ddr_standby(void)
-{
-       /* Those two values allow us to delay self-refresh activation
-        * to the maximum. */
-       u32 lpr0, lpr1 = 0;
-       u32 saved_lpr0, saved_lpr1 = 0;
-
-       if (at91_ramc_base[1]) {
-               saved_lpr1 = at91_ramc_read(1, AT91_DDRSDRC_LPR);
-               lpr1 = saved_lpr1 & ~AT91_DDRSDRC_LPCB;
-               lpr1 |= AT91_DDRSDRC_LPCB_SELF_REFRESH;
-       }
-
-       saved_lpr0 = at91_ramc_read(0, AT91_DDRSDRC_LPR);
-       lpr0 = saved_lpr0 & ~AT91_DDRSDRC_LPCB;
-       lpr0 |= AT91_DDRSDRC_LPCB_SELF_REFRESH;
-
-       /* self-refresh mode now */
-       at91_ramc_write(0, AT91_DDRSDRC_LPR, lpr0);
-       if (at91_ramc_base[1])
-               at91_ramc_write(1, AT91_DDRSDRC_LPR, lpr1);
-
-       cpu_do_idle();
-
-       at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr0);
-       if (at91_ramc_base[1])
-               at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1);
-}
-
-/* We manage both DDRAM/SDRAM controllers, we need more than one value to
- * remember.
- */
-static inline void at91sam9_sdram_standby(void)
-{
-       u32 lpr0, lpr1 = 0;
-       u32 saved_lpr0, saved_lpr1 = 0;
-
-       if (at91_ramc_base[1]) {
-               saved_lpr1 = at91_ramc_read(1, AT91_SDRAMC_LPR);
-               lpr1 = saved_lpr1 & ~AT91_SDRAMC_LPCB;
-               lpr1 |= AT91_SDRAMC_LPCB_SELF_REFRESH;
-       }
-
-       saved_lpr0 = at91_ramc_read(0, AT91_SDRAMC_LPR);
-       lpr0 = saved_lpr0 & ~AT91_SDRAMC_LPCB;
-       lpr0 |= AT91_SDRAMC_LPCB_SELF_REFRESH;
+#define AT91_MEMCTRL_MC                0
+#define AT91_MEMCTRL_SDRAMC    1
+#define AT91_MEMCTRL_DDRSDR    2
 
-       /* self-refresh mode now */
-       at91_ramc_write(0, AT91_SDRAMC_LPR, lpr0);
-       if (at91_ramc_base[1])
-               at91_ramc_write(1, AT91_SDRAMC_LPR, lpr1);
+#define        AT91_PM_MEMTYPE_MASK    0x0f
 
-       cpu_do_idle();
+#define        AT91_PM_MODE_OFFSET     4
+#define        AT91_PM_MODE_MASK       0x01
+#define        AT91_PM_MODE(x)         (((x) & AT91_PM_MODE_MASK) << AT91_PM_MODE_OFFSET)
 
-       at91_ramc_write(0, AT91_SDRAMC_LPR, saved_lpr0);
-       if (at91_ramc_base[1])
-               at91_ramc_write(1, AT91_SDRAMC_LPR, saved_lpr1);
-}
+#define        AT91_PM_SLOW_CLOCK      0x01
 
 #endif
diff --git a/arch/arm/mach-at91/pm_slowclock.S b/arch/arm/mach-at91/pm_slowclock.S
deleted file mode 100644 (file)
index 931f0e3..0000000
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * arch/arm/mach-at91/pm_slow_clock.S
- *
- *  Copyright (C) 2006 Savin Zlobec
- *
- * AT91SAM9 support:
- *  Copyright (C) 2007 Anti Sullin <anti.sullin@artecdesign.ee
- *
- * This program is free software; you can 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 <linux/clk/at91_pmc.h>
-#include <mach/hardware.h>
-#include <mach/at91_ramc.h>
-
-/*
- * When SLOWDOWN_MASTER_CLOCK is defined we will also slow down the Master
- * clock during suspend by adjusting its prescalar and divisor.
- * NOTE: This hasn't been shown to be stable on SAM9s; and on the RM9200 there
- *       are errata regarding adjusting the prescalar and divisor.
- */
-#undef SLOWDOWN_MASTER_CLOCK
-
-pmc    .req    r0
-sdramc .req    r1
-ramc1  .req    r2
-memctrl        .req    r3
-tmp1   .req    r4
-tmp2   .req    r5
-
-/*
- * Wait until master clock is ready (after switching master clock source)
- */
-       .macro wait_mckrdy
-1:     ldr     tmp1, [pmc, #AT91_PMC_SR]
-       tst     tmp1, #AT91_PMC_MCKRDY
-       beq     1b
-       .endm
-
-/*
- * Wait until master oscillator has stabilized.
- */
-       .macro wait_moscrdy
-1:     ldr     tmp1, [pmc, #AT91_PMC_SR]
-       tst     tmp1, #AT91_PMC_MOSCS
-       beq     1b
-       .endm
-
-/*
- * Wait until PLLA has locked.
- */
-       .macro wait_pllalock
-1:     ldr     tmp1, [pmc, #AT91_PMC_SR]
-       tst     tmp1, #AT91_PMC_LOCKA
-       beq     1b
-       .endm
-
-/*
- * Wait until PLLB has locked.
- */
-       .macro wait_pllblock
-1:     ldr     tmp1, [pmc, #AT91_PMC_SR]
-       tst     tmp1, #AT91_PMC_LOCKB
-       beq     1b
-       .endm
-
-       .text
-
-       .arm
-
-/* void at91_slow_clock(void __iomem *pmc, void __iomem *sdramc,
- *                     void __iomem *ramc1, int memctrl)
- */
-ENTRY(at91_slow_clock)
-       /* Save registers on stack */
-       stmfd   sp!, {r4 - r12, lr}
-
-       /*
-        * Register usage:
-        *  R0 = Base address of AT91_PMC
-        *  R1 = Base address of RAM Controller (SDRAM, DDRSDR, or AT91_SYS)
-        *  R2 = Base address of second RAM Controller or 0 if not present
-        *  R3 = Memory controller
-        *  R4 = temporary register
-        *  R5 = temporary register
-        */
-
-       /* Drain write buffer */
-       mov     tmp1, #0
-       mcr     p15, 0, tmp1, c7, c10, 4
-
-       cmp     memctrl, #AT91_MEMCTRL_MC
-       bne     ddr_sr_enable
-
-       /*
-        * at91rm9200 Memory controller
-        */
-       /* Put SDRAM in self-refresh mode */
-       mov     tmp1, #1
-       str     tmp1, [sdramc, #AT91RM9200_SDRAMC_SRR]
-       b       sdr_sr_done
-
-       /*
-        * DDRSDR Memory controller
-        */
-ddr_sr_enable:
-       cmp     memctrl, #AT91_MEMCTRL_DDRSDR
-       bne     sdr_sr_enable
-
-       /* LPDDR1 --> force DDR2 mode during self-refresh */
-       ldr     tmp1, [sdramc, #AT91_DDRSDRC_MDR]
-       str     tmp1, .saved_sam9_mdr
-       bic     tmp1, tmp1, #~AT91_DDRSDRC_MD
-       cmp     tmp1, #AT91_DDRSDRC_MD_LOW_POWER_DDR
-       ldreq   tmp1, [sdramc, #AT91_DDRSDRC_MDR]
-       biceq   tmp1, tmp1, #AT91_DDRSDRC_MD
-       orreq   tmp1, tmp1, #AT91_DDRSDRC_MD_DDR2
-       streq   tmp1, [sdramc, #AT91_DDRSDRC_MDR]
-
-       /* prepare for DDRAM self-refresh mode */
-       ldr     tmp1, [sdramc, #AT91_DDRSDRC_LPR]
-       str     tmp1, .saved_sam9_lpr
-       bic     tmp1, #AT91_DDRSDRC_LPCB
-       orr     tmp1, #AT91_DDRSDRC_LPCB_SELF_REFRESH
-
-       /* figure out if we use the second ram controller */
-       cmp     ramc1, #0
-       beq     ddr_no_2nd_ctrl
-
-       ldr     tmp2, [ramc1, #AT91_DDRSDRC_MDR]
-       str     tmp2, .saved_sam9_mdr1
-       bic     tmp2, tmp2, #~AT91_DDRSDRC_MD
-       cmp     tmp2, #AT91_DDRSDRC_MD_LOW_POWER_DDR
-       ldreq   tmp2, [ramc1, #AT91_DDRSDRC_MDR]
-       biceq   tmp2, tmp2, #AT91_DDRSDRC_MD
-       orreq   tmp2, tmp2, #AT91_DDRSDRC_MD_DDR2
-       streq   tmp2, [ramc1, #AT91_DDRSDRC_MDR]
-
-       ldr     tmp2, [ramc1, #AT91_DDRSDRC_LPR]
-       str     tmp2, .saved_sam9_lpr1
-       bic     tmp2, #AT91_DDRSDRC_LPCB
-       orr     tmp2, #AT91_DDRSDRC_LPCB_SELF_REFRESH
-
-       /* Enable DDRAM self-refresh mode */
-       str     tmp2, [ramc1, #AT91_DDRSDRC_LPR]
-ddr_no_2nd_ctrl:
-       str     tmp1, [sdramc, #AT91_DDRSDRC_LPR]
-
-       b       sdr_sr_done
-
-       /*
-        * SDRAMC Memory controller
-        */
-sdr_sr_enable:
-       /* Enable SDRAM self-refresh mode */
-       ldr     tmp1, [sdramc, #AT91_SDRAMC_LPR]
-       str     tmp1, .saved_sam9_lpr
-
-       bic     tmp1, #AT91_SDRAMC_LPCB
-       orr     tmp1, #AT91_SDRAMC_LPCB_SELF_REFRESH
-       str     tmp1, [sdramc, #AT91_SDRAMC_LPR]
-
-sdr_sr_done:
-       /* Save Master clock setting */
-       ldr     tmp1, [pmc, #AT91_PMC_MCKR]
-       str     tmp1, .saved_mckr
-
-       /*
-        * Set the Master clock source to slow clock
-        */
-       bic     tmp1, tmp1, #AT91_PMC_CSS
-       str     tmp1, [pmc, #AT91_PMC_MCKR]
-
-       wait_mckrdy
-
-#ifdef SLOWDOWN_MASTER_CLOCK
-       /*
-        * Set the Master Clock PRES and MDIV fields.
-        *
-        * See AT91RM9200 errata #27 and #28 for details.
-        */
-       mov     tmp1, #0
-       str     tmp1, [pmc, #AT91_PMC_MCKR]
-
-       wait_mckrdy
-#endif
-
-       /* Save PLLA setting and disable it */
-       ldr     tmp1, [pmc, #AT91_CKGR_PLLAR]
-       str     tmp1, .saved_pllar
-
-       mov     tmp1, #AT91_PMC_PLLCOUNT
-       orr     tmp1, tmp1, #(1 << 29)          /* bit 29 always set */
-       str     tmp1, [pmc, #AT91_CKGR_PLLAR]
-
-       /* Save PLLB setting and disable it */
-       ldr     tmp1, [pmc, #AT91_CKGR_PLLBR]
-       str     tmp1, .saved_pllbr
-
-       mov     tmp1, #AT91_PMC_PLLCOUNT
-       str     tmp1, [pmc, #AT91_CKGR_PLLBR]
-
-       /* 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]
-
-       /* Wait for interrupt */
-       mcr     p15, 0, tmp1, c7, c0, 4
-
-       /* 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]
-
-       wait_moscrdy
-
-       /* Restore PLLB setting */
-       ldr     tmp1, .saved_pllbr
-       str     tmp1, [pmc, #AT91_CKGR_PLLBR]
-
-       tst     tmp1, #(AT91_PMC_MUL &  0xff0000)
-       bne     1f
-       tst     tmp1, #(AT91_PMC_MUL & ~0xff0000)
-       beq     2f
-1:
-       wait_pllblock
-2:
-
-       /* Restore PLLA setting */
-       ldr     tmp1, .saved_pllar
-       str     tmp1, [pmc, #AT91_CKGR_PLLAR]
-
-       tst     tmp1, #(AT91_PMC_MUL &  0xff0000)
-       bne     3f
-       tst     tmp1, #(AT91_PMC_MUL & ~0xff0000)
-       beq     4f
-3:
-       wait_pllalock
-4:
-
-#ifdef SLOWDOWN_MASTER_CLOCK
-       /*
-        * First set PRES if it was not 0,
-        * than set CSS and MDIV fields.
-        *
-        * See AT91RM9200 errata #27 and #28 for details.
-        */
-       ldr     tmp1, .saved_mckr
-       tst     tmp1, #AT91_PMC_PRES
-       beq     2f
-       and     tmp1, tmp1, #AT91_PMC_PRES
-       str     tmp1, [pmc, #AT91_PMC_MCKR]
-
-       wait_mckrdy
-#endif
-
-       /*
-        * Restore master clock setting
-        */
-2:     ldr     tmp1, .saved_mckr
-       str     tmp1, [pmc, #AT91_PMC_MCKR]
-
-       wait_mckrdy
-
-       /*
-        * at91rm9200 Memory controller
-        * Do nothing - self-refresh is automatically disabled.
-        */
-       cmp     memctrl, #AT91_MEMCTRL_MC
-       beq     ram_restored
-
-       /*
-        * DDRSDR Memory controller
-        */
-       cmp     memctrl, #AT91_MEMCTRL_DDRSDR
-       bne     sdr_en_restore
-       /* Restore MDR in case of LPDDR1 */
-       ldr     tmp1, .saved_sam9_mdr
-       str     tmp1, [sdramc, #AT91_DDRSDRC_MDR]
-       /* Restore LPR on AT91 with DDRAM */
-       ldr     tmp1, .saved_sam9_lpr
-       str     tmp1, [sdramc, #AT91_DDRSDRC_LPR]
-
-       /* if we use the second ram controller */
-       cmp     ramc1, #0
-       ldrne   tmp2, .saved_sam9_mdr1
-       strne   tmp2, [ramc1, #AT91_DDRSDRC_MDR]
-       ldrne   tmp2, .saved_sam9_lpr1
-       strne   tmp2, [ramc1, #AT91_DDRSDRC_LPR]
-
-       b       ram_restored
-
-       /*
-        * SDRAMC Memory controller
-        */
-sdr_en_restore:
-       /* Restore LPR on AT91 with SDRAM */
-       ldr     tmp1, .saved_sam9_lpr
-       str     tmp1, [sdramc, #AT91_SDRAMC_LPR]
-
-ram_restored:
-       /* Restore registers, and return */
-       ldmfd   sp!, {r4 - r12, pc}
-
-
-.saved_mckr:
-       .word 0
-
-.saved_pllar:
-       .word 0
-
-.saved_pllbr:
-       .word 0
-
-.saved_sam9_lpr:
-       .word 0
-
-.saved_sam9_lpr1:
-       .word 0
-
-.saved_sam9_mdr:
-       .word 0
-
-.saved_sam9_mdr1:
-       .word 0
-
-ENTRY(at91_slow_clock_sz)
-       .word .-at91_slow_clock
diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
new file mode 100644 (file)
index 0000000..bd22b2c
--- /dev/null
@@ -0,0 +1,337 @@
+/*
+ * arch/arm/mach-at91/pm_slow_clock.S
+ *
+ *  Copyright (C) 2006 Savin Zlobec
+ *
+ * AT91SAM9 support:
+ *  Copyright (C) 2007 Anti Sullin <anti.sullin@artecdesign.ee
+ *
+ * This program is free software; you can 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 <linux/clk/at91_pmc.h>
+#include <mach/at91_ramc.h>
+#include "pm.h"
+
+#define        SRAMC_SELF_FRESH_ACTIVE         0x01
+#define        SRAMC_SELF_FRESH_EXIT           0x00
+
+pmc    .req    r0
+tmp1   .req    r4
+tmp2   .req    r5
+
+/*
+ * Wait until master clock is ready (after switching master clock source)
+ */
+       .macro wait_mckrdy
+1:     ldr     tmp1, [pmc, #AT91_PMC_SR]
+       tst     tmp1, #AT91_PMC_MCKRDY
+       beq     1b
+       .endm
+
+/*
+ * Wait until master oscillator has stabilized.
+ */
+       .macro wait_moscrdy
+1:     ldr     tmp1, [pmc, #AT91_PMC_SR]
+       tst     tmp1, #AT91_PMC_MOSCS
+       beq     1b
+       .endm
+
+/*
+ * Wait until PLLA has locked.
+ */
+       .macro wait_pllalock
+1:     ldr     tmp1, [pmc, #AT91_PMC_SR]
+       tst     tmp1, #AT91_PMC_LOCKA
+       beq     1b
+       .endm
+
+/*
+ * Put the processor to enter the idle state
+ */
+       .macro at91_cpu_idle
+
+#if defined(CONFIG_CPU_V7)
+       mov     tmp1, #AT91_PMC_PCK
+       str     tmp1, [pmc, #AT91_PMC_SCDR]
+
+       dsb
+
+       wfi             @ Wait For Interrupt
+#else
+       mcr     p15, 0, tmp1, c7, c0, 4
+#endif
+
+       .endm
+
+       .text
+
+       .arm
+
+/*
+ * void at91_pm_suspend_in_sram(void __iomem *pmc, void __iomem *sdramc,
+ *                     void __iomem *ramc1, int memctrl)
+ * @input param:
+ *     @r0: base address of AT91_PMC
+ *     @r1: base address of SDRAM Controller (SDRAM, DDRSDR, or AT91_SYS)
+ *     @r2: base address of second SDRAM Controller or 0 if not present
+ *     @r3: pm information
+ */
+ENTRY(at91_pm_suspend_in_sram)
+       /* Save registers on stack */
+       stmfd   sp!, {r4 - r12, lr}
+
+       /* Drain write buffer */
+       mov     tmp1, #0
+       mcr     p15, 0, tmp1, c7, c10, 4
+
+       str     r0, .pmc_base
+       str     r1, .sramc_base
+       str     r2, .sramc1_base
+
+       and     r0, r3, #AT91_PM_MEMTYPE_MASK
+       str     r0, .memtype
+
+       lsr     r0, r3, #AT91_PM_MODE_OFFSET
+       and     r0, r0, #AT91_PM_MODE_MASK
+       str     r0, .pm_mode
+
+       /* Active the self-refresh mode */
+       mov     r0, #SRAMC_SELF_FRESH_ACTIVE
+       bl      at91_sramc_self_refresh
+
+       ldr     r0, .pm_mode
+       tst     r0, #AT91_PM_SLOW_CLOCK
+       beq     skip_disable_main_clock
+
+       ldr     pmc, .pmc_base
+
+       /* Save Master clock setting */
+       ldr     tmp1, [pmc, #AT91_PMC_MCKR]
+       str     tmp1, .saved_mckr
+
+       /*
+        * Set the Master clock source to slow clock
+        */
+       bic     tmp1, tmp1, #AT91_PMC_CSS
+       str     tmp1, [pmc, #AT91_PMC_MCKR]
+
+       wait_mckrdy
+
+       /* Save PLLA setting and disable it */
+       ldr     tmp1, [pmc, #AT91_CKGR_PLLAR]
+       str     tmp1, .saved_pllar
+
+       mov     tmp1, #AT91_PMC_PLLCOUNT
+       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]
+
+skip_disable_main_clock:
+       ldr     pmc, .pmc_base
+
+       /* Wait for interrupt */
+       at91_cpu_idle
+
+       ldr     r0, .pm_mode
+       tst     r0, #AT91_PM_SLOW_CLOCK
+       beq     skip_enable_main_clock
+
+       ldr     pmc, .pmc_base
+
+       /* 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]
+
+       wait_moscrdy
+
+       /* Restore PLLA setting */
+       ldr     tmp1, .saved_pllar
+       str     tmp1, [pmc, #AT91_CKGR_PLLAR]
+
+       tst     tmp1, #(AT91_PMC_MUL &  0xff0000)
+       bne     3f
+       tst     tmp1, #(AT91_PMC_MUL & ~0xff0000)
+       beq     4f
+3:
+       wait_pllalock
+4:
+
+       /*
+        * Restore master clock setting
+        */
+       ldr     tmp1, .saved_mckr
+       str     tmp1, [pmc, #AT91_PMC_MCKR]
+
+       wait_mckrdy
+
+skip_enable_main_clock:
+       /* Exit the self-refresh mode */
+       mov     r0, #SRAMC_SELF_FRESH_EXIT
+       bl      at91_sramc_self_refresh
+
+       /* Restore registers, and return */
+       ldmfd   sp!, {r4 - r12, pc}
+ENDPROC(at91_pm_suspend_in_sram)
+
+/*
+ * void at91_sramc_self_refresh(unsigned int is_active)
+ *
+ * @input param:
+ *     @r0: 1 - active self-refresh mode
+ *          0 - exit self-refresh mode
+ * register usage:
+ *     @r1: memory type
+ *     @r2: base address of the sram controller
+ */
+
+ENTRY(at91_sramc_self_refresh)
+       ldr     r1, .memtype
+       ldr     r2, .sramc_base
+
+       cmp     r1, #AT91_MEMCTRL_MC
+       bne     ddrc_sf
+
+       /*
+        * at91rm9200 Memory controller
+        */
+
+        /*
+         * For exiting the self-refresh mode, do nothing,
+         * automatically exit the self-refresh mode.
+         */
+       tst     r0, #SRAMC_SELF_FRESH_ACTIVE
+       beq     exit_sramc_sf
+
+       /* Active SDRAM self-refresh mode */
+       mov     r3, #1
+       str     r3, [r2, #AT91RM9200_SDRAMC_SRR]
+       b       exit_sramc_sf
+
+ddrc_sf:
+       cmp     r1, #AT91_MEMCTRL_DDRSDR
+       bne     sdramc_sf
+
+       /*
+        * DDR Memory controller
+        */
+       tst     r0, #SRAMC_SELF_FRESH_ACTIVE
+       beq     ddrc_exit_sf
+
+       /* LPDDR1 --> force DDR2 mode during self-refresh */
+       ldr     r3, [r2, #AT91_DDRSDRC_MDR]
+       str     r3, .saved_sam9_mdr
+       bic     r3, r3, #~AT91_DDRSDRC_MD
+       cmp     r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
+       ldreq   r3, [r2, #AT91_DDRSDRC_MDR]
+       biceq   r3, r3, #AT91_DDRSDRC_MD
+       orreq   r3, r3, #AT91_DDRSDRC_MD_DDR2
+       streq   r3, [r2, #AT91_DDRSDRC_MDR]
+
+       /* Active DDRC self-refresh mode */
+       ldr     r3, [r2, #AT91_DDRSDRC_LPR]
+       str     r3, .saved_sam9_lpr
+       bic     r3, r3, #AT91_DDRSDRC_LPCB
+       orr     r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
+       str     r3, [r2, #AT91_DDRSDRC_LPR]
+
+       /* If using the 2nd ddr controller */
+       ldr     r2, .sramc1_base
+       cmp     r2, #0
+       beq     no_2nd_ddrc
+
+       ldr     r3, [r2, #AT91_DDRSDRC_MDR]
+       str     r3, .saved_sam9_mdr1
+       bic     r3, r3, #~AT91_DDRSDRC_MD
+       cmp     r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
+       ldreq   r3, [r2, #AT91_DDRSDRC_MDR]
+       biceq   r3, r3, #AT91_DDRSDRC_MD
+       orreq   r3, r3, #AT91_DDRSDRC_MD_DDR2
+       streq   r3, [r2, #AT91_DDRSDRC_MDR]
+
+       /* Active DDRC self-refresh mode */
+       ldr     r3, [r2, #AT91_DDRSDRC_LPR]
+       str     r3, .saved_sam9_lpr1
+       bic     r3, r3, #AT91_DDRSDRC_LPCB
+       orr     r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
+       str     r3, [r2, #AT91_DDRSDRC_LPR]
+
+no_2nd_ddrc:
+       b       exit_sramc_sf
+
+ddrc_exit_sf:
+       /* Restore MDR in case of LPDDR1 */
+       ldr     r3, .saved_sam9_mdr
+       str     r3, [r2, #AT91_DDRSDRC_MDR]
+       /* Restore LPR on AT91 with DDRAM */
+       ldr     r3, .saved_sam9_lpr
+       str     r3, [r2, #AT91_DDRSDRC_LPR]
+
+       /* If using the 2nd ddr controller */
+       ldr     r2, .sramc1_base
+       cmp     r2, #0
+       ldrne   r3, .saved_sam9_mdr1
+       strne   r3, [r2, #AT91_DDRSDRC_MDR]
+       ldrne   r3, .saved_sam9_lpr1
+       strne   r3, [r2, #AT91_DDRSDRC_LPR]
+
+       b       exit_sramc_sf
+
+       /*
+        * SDRAMC Memory controller
+        */
+sdramc_sf:
+       tst     r0, #SRAMC_SELF_FRESH_ACTIVE
+       beq     sdramc_exit_sf
+
+       /* Active SDRAMC self-refresh mode */
+       ldr     r3, [r2, #AT91_SDRAMC_LPR]
+       str     r3, .saved_sam9_lpr
+       bic     r3, r3, #AT91_SDRAMC_LPCB
+       orr     r3, r3, #AT91_SDRAMC_LPCB_SELF_REFRESH
+       str     r3, [r2, #AT91_SDRAMC_LPR]
+
+sdramc_exit_sf:
+       ldr     r3, .saved_sam9_lpr
+       str     r3, [r2, #AT91_SDRAMC_LPR]
+
+exit_sramc_sf:
+       mov     pc, lr
+ENDPROC(at91_sramc_self_refresh)
+
+.pmc_base:
+       .word 0
+.sramc_base:
+       .word 0
+.sramc1_base:
+       .word 0
+.memtype:
+       .word 0
+.pm_mode:
+       .word 0
+.saved_mckr:
+       .word 0
+.saved_pllar:
+       .word 0
+.saved_sam9_lpr:
+       .word 0
+.saved_sam9_lpr1:
+       .word 0
+.saved_sam9_mdr:
+       .word 0
+.saved_sam9_mdr1:
+       .word 0
+
+ENTRY(at91_pm_suspend_in_sram_sz)
+       .word .-at91_pm_suspend_in_sram
index 03dcb441f3d24662c3e7b00b8eea136426723a86..41d829d8e7d51045cc2fc38758302e13fd55b554 100644 (file)
@@ -7,48 +7,48 @@
  * Licensed under GPLv2 or later.
  */
 
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/gpio.h>
-#include <linux/micrel_phy.h>
 #include <linux/of.h>
-#include <linux/of_irq.h>
 #include <linux/of_platform.h>
-#include <linux/phy.h>
-#include <linux/clk-provider.h>
-#include <linux/phy.h>
 
-#include <mach/hardware.h>
-
-#include <asm/setup.h>
-#include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
-#include <asm/mach/irq.h>
+#include <asm/system_misc.h>
 
 #include "generic.h"
+#include "soc.h"
 
-static int ksz8081_phy_fixup(struct phy_device *phy)
-{
-       int value;
-
-       value = phy_read(phy, 0x16);
-       value &= ~0x20;
-       phy_write(phy, 0x16, value);
-
-       return 0;
-}
+static const struct at91_soc sama5_socs[] = {
+       AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D31_EXID_MATCH,
+                "sama5d31", "sama5d3"),
+       AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D33_EXID_MATCH,
+                "sama5d33", "sama5d3"),
+       AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D34_EXID_MATCH,
+                "sama5d34", "sama5d3"),
+       AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D35_EXID_MATCH,
+                "sama5d35", "sama5d3"),
+       AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D36_EXID_MATCH,
+                "sama5d36", "sama5d3"),
+       AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D41_EXID_MATCH,
+                "sama5d41", "sama5d4"),
+       AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D42_EXID_MATCH,
+                "sama5d42", "sama5d4"),
+       AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D43_EXID_MATCH,
+                "sama5d43", "sama5d4"),
+       AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D44_EXID_MATCH,
+                "sama5d44", "sama5d4"),
+       { /* sentinel */ },
+};
 
 static void __init sama5_dt_device_init(void)
 {
-       if (of_machine_is_compatible("atmel,sama5d4ek") &&
-          IS_ENABLED(CONFIG_PHYLIB)) {
-               phy_register_fixup_for_id("fc028000.etherne:00",
-                                               ksz8081_phy_fixup);
-       }
+       struct soc_device *soc;
+       struct device *soc_dev = NULL;
 
-       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+       soc = at91_soc_init(sama5_socs);
+       if (soc != NULL)
+               soc_dev = soc_device_to_device(soc);
+
+       of_platform_populate(NULL, of_default_bus_match_table, NULL, soc_dev);
        at91sam9x5_pm_init();
 }
 
@@ -59,44 +59,10 @@ static const char *sama5_dt_board_compat[] __initconst = {
 
 DT_MACHINE_START(sama5_dt, "Atmel SAMA5")
        /* Maintainer: Atmel */
-       .map_io         = at91_map_io,
        .init_machine   = sama5_dt_device_init,
        .dt_compat      = sama5_dt_board_compat,
 MACHINE_END
 
-static struct map_desc at91_io_desc[] __initdata = {
-       {
-       .virtual        = (unsigned long)AT91_ALT_IO_P2V(SAMA5D4_BASE_MPDDRC),
-       .pfn            = __phys_to_pfn(SAMA5D4_BASE_MPDDRC),
-       .length         = SZ_512,
-       .type           = MT_DEVICE,
-       },
-       {
-       .virtual        = (unsigned long)AT91_ALT_IO_P2V(SAMA5D4_BASE_PMC),
-       .pfn            = __phys_to_pfn(SAMA5D4_BASE_PMC),
-       .length         = SZ_512,
-       .type           = MT_DEVICE,
-       },
-       { /* On sama5d4, we use USART3 as serial console */
-       .virtual        = (unsigned long)AT91_ALT_IO_P2V(SAMA5D4_BASE_USART3),
-       .pfn            = __phys_to_pfn(SAMA5D4_BASE_USART3),
-       .length         = SZ_256,
-       .type           = MT_DEVICE,
-       },
-       { /* A bunch of peripheral with fine grained IO space */
-       .virtual        = (unsigned long)AT91_ALT_IO_P2V(SAMA5D4_BASE_SYS2),
-       .pfn            = __phys_to_pfn(SAMA5D4_BASE_SYS2),
-       .length         = SZ_2K,
-       .type           = MT_DEVICE,
-       },
-};
-
-static void __init sama5_alt_map_io(void)
-{
-       at91_alt_map_io();
-       iotable_init(at91_io_desc, ARRAY_SIZE(at91_io_desc));
-}
-
 static const char *sama5_alt_dt_board_compat[] __initconst = {
        "atmel,sama5d4",
        NULL
@@ -104,7 +70,6 @@ static const char *sama5_alt_dt_board_compat[] __initconst = {
 
 DT_MACHINE_START(sama5_alt_dt, "Atmel SAMA5")
        /* Maintainer: Atmel */
-       .map_io         = sama5_alt_map_io,
        .init_machine   = sama5_dt_device_init,
        .dt_compat      = sama5_alt_dt_board_compat,
        .l2c_aux_mask   = ~0UL,
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
deleted file mode 100644 (file)
index 4e58bc9..0000000
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- * Copyright (C) 2007 Atmel Corporation.
- * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
- *
- * Under GPLv2
- */
-
-#define pr_fmt(fmt)    "AT91: " fmt
-
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/mm.h>
-#include <linux/pm.h>
-#include <linux/of_address.h>
-#include <linux/pinctrl/machine.h>
-#include <linux/clk/at91_pmc.h>
-
-#include <asm/system_misc.h>
-#include <asm/mach/map.h>
-
-#include <mach/hardware.h>
-#include <mach/cpu.h>
-#include <mach/at91_dbgu.h>
-
-#include "generic.h"
-#include "pm.h"
-
-struct at91_socinfo at91_soc_initdata;
-EXPORT_SYMBOL(at91_soc_initdata);
-
-static struct map_desc at91_io_desc __initdata __maybe_unused = {
-       .virtual        = (unsigned long)AT91_VA_BASE_SYS,
-       .pfn            = __phys_to_pfn(AT91_BASE_SYS),
-       .length         = SZ_16K,
-       .type           = MT_DEVICE,
-};
-
-static struct map_desc at91_alt_io_desc __initdata __maybe_unused = {
-       .virtual        = (unsigned long)AT91_ALT_VA_BASE_SYS,
-       .pfn            = __phys_to_pfn(AT91_ALT_BASE_SYS),
-       .length         = 24 * SZ_1K,
-       .type           = MT_DEVICE,
-};
-
-static void __init soc_detect(u32 dbgu_base)
-{
-       u32 cidr, socid;
-
-       cidr = __raw_readl(AT91_IO_P2V(dbgu_base) + AT91_DBGU_CIDR);
-       socid = cidr & ~AT91_CIDR_VERSION;
-
-       switch (socid) {
-       case ARCH_ID_AT91RM9200:
-               at91_soc_initdata.type = AT91_SOC_RM9200;
-               if (at91_soc_initdata.subtype == AT91_SOC_SUBTYPE_UNKNOWN)
-                       at91_soc_initdata.subtype = AT91_SOC_RM9200_BGA;
-               break;
-
-       case ARCH_ID_AT91SAM9260:
-               at91_soc_initdata.type = AT91_SOC_SAM9260;
-               at91_soc_initdata.subtype = AT91_SOC_SUBTYPE_NONE;
-               break;
-
-       case ARCH_ID_AT91SAM9261:
-               at91_soc_initdata.type = AT91_SOC_SAM9261;
-               at91_soc_initdata.subtype = AT91_SOC_SUBTYPE_NONE;
-               break;
-
-       case ARCH_ID_AT91SAM9263:
-               at91_soc_initdata.type = AT91_SOC_SAM9263;
-               at91_soc_initdata.subtype = AT91_SOC_SUBTYPE_NONE;
-               break;
-
-       case ARCH_ID_AT91SAM9G20:
-               at91_soc_initdata.type = AT91_SOC_SAM9G20;
-               at91_soc_initdata.subtype = AT91_SOC_SUBTYPE_NONE;
-               break;
-
-       case ARCH_ID_AT91SAM9G45:
-               at91_soc_initdata.type = AT91_SOC_SAM9G45;
-               if (cidr == ARCH_ID_AT91SAM9G45ES)
-                       at91_soc_initdata.subtype = AT91_SOC_SAM9G45ES;
-               break;
-
-       case ARCH_ID_AT91SAM9RL64:
-               at91_soc_initdata.type = AT91_SOC_SAM9RL;
-               at91_soc_initdata.subtype = AT91_SOC_SUBTYPE_NONE;
-               break;
-
-       case ARCH_ID_AT91SAM9X5:
-               at91_soc_initdata.type = AT91_SOC_SAM9X5;
-               break;
-
-       case ARCH_ID_AT91SAM9N12:
-               at91_soc_initdata.type = AT91_SOC_SAM9N12;
-               break;
-
-       case ARCH_ID_SAMA5:
-               at91_soc_initdata.exid = __raw_readl(AT91_IO_P2V(dbgu_base) + AT91_DBGU_EXID);
-               if (at91_soc_initdata.exid & ARCH_EXID_SAMA5D3) {
-                       at91_soc_initdata.type = AT91_SOC_SAMA5D3;
-               }
-               break;
-       }
-
-       /* at91sam9g10 */
-       if ((socid & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) {
-               at91_soc_initdata.type = AT91_SOC_SAM9G10;
-               at91_soc_initdata.subtype = AT91_SOC_SUBTYPE_NONE;
-       }
-       /* at91sam9xe */
-       else if ((cidr & AT91_CIDR_ARCH) == ARCH_FAMILY_AT91SAM9XE) {
-               at91_soc_initdata.type = AT91_SOC_SAM9260;
-               at91_soc_initdata.subtype = AT91_SOC_SAM9XE;
-       }
-
-       if (!at91_soc_is_detected())
-               return;
-
-       at91_soc_initdata.cidr = cidr;
-
-       /* sub version of soc */
-       if (!at91_soc_initdata.exid)
-               at91_soc_initdata.exid = __raw_readl(AT91_IO_P2V(dbgu_base) + AT91_DBGU_EXID);
-
-       if (at91_soc_initdata.type == AT91_SOC_SAM9G45) {
-               switch (at91_soc_initdata.exid) {
-               case ARCH_EXID_AT91SAM9M10:
-                       at91_soc_initdata.subtype = AT91_SOC_SAM9M10;
-                       break;
-               case ARCH_EXID_AT91SAM9G46:
-                       at91_soc_initdata.subtype = AT91_SOC_SAM9G46;
-                       break;
-               case ARCH_EXID_AT91SAM9M11:
-                       at91_soc_initdata.subtype = AT91_SOC_SAM9M11;
-                       break;
-               }
-       }
-
-       if (at91_soc_initdata.type == AT91_SOC_SAM9X5) {
-               switch (at91_soc_initdata.exid) {
-               case ARCH_EXID_AT91SAM9G15:
-                       at91_soc_initdata.subtype = AT91_SOC_SAM9G15;
-                       break;
-               case ARCH_EXID_AT91SAM9G35:
-                       at91_soc_initdata.subtype = AT91_SOC_SAM9G35;
-                       break;
-               case ARCH_EXID_AT91SAM9X35:
-                       at91_soc_initdata.subtype = AT91_SOC_SAM9X35;
-                       break;
-               case ARCH_EXID_AT91SAM9G25:
-                       at91_soc_initdata.subtype = AT91_SOC_SAM9G25;
-                       break;
-               case ARCH_EXID_AT91SAM9X25:
-                       at91_soc_initdata.subtype = AT91_SOC_SAM9X25;
-                       break;
-               }
-       }
-
-       if (at91_soc_initdata.type == AT91_SOC_SAMA5D3) {
-               switch (at91_soc_initdata.exid) {
-               case ARCH_EXID_SAMA5D31:
-                       at91_soc_initdata.subtype = AT91_SOC_SAMA5D31;
-                       break;
-               case ARCH_EXID_SAMA5D33:
-                       at91_soc_initdata.subtype = AT91_SOC_SAMA5D33;
-                       break;
-               case ARCH_EXID_SAMA5D34:
-                       at91_soc_initdata.subtype = AT91_SOC_SAMA5D34;
-                       break;
-               case ARCH_EXID_SAMA5D35:
-                       at91_soc_initdata.subtype = AT91_SOC_SAMA5D35;
-                       break;
-               case ARCH_EXID_SAMA5D36:
-                       at91_soc_initdata.subtype = AT91_SOC_SAMA5D36;
-                       break;
-               }
-       }
-}
-
-static void __init alt_soc_detect(u32 dbgu_base)
-{
-       u32 cidr, socid;
-
-       /* SoC ID */
-       cidr = __raw_readl(AT91_ALT_IO_P2V(dbgu_base) + AT91_DBGU_CIDR);
-       socid = cidr & ~AT91_CIDR_VERSION;
-
-       switch (socid) {
-       case ARCH_ID_SAMA5:
-               at91_soc_initdata.exid = __raw_readl(AT91_ALT_IO_P2V(dbgu_base) + AT91_DBGU_EXID);
-               if (at91_soc_initdata.exid & ARCH_EXID_SAMA5D3) {
-                       at91_soc_initdata.type = AT91_SOC_SAMA5D3;
-               } else if (at91_soc_initdata.exid & ARCH_EXID_SAMA5D4) {
-                       at91_soc_initdata.type = AT91_SOC_SAMA5D4;
-               }
-               break;
-       }
-
-       if (!at91_soc_is_detected())
-               return;
-
-       at91_soc_initdata.cidr = cidr;
-
-       /* sub version of soc */
-       if (!at91_soc_initdata.exid)
-               at91_soc_initdata.exid = __raw_readl(AT91_ALT_IO_P2V(dbgu_base) + AT91_DBGU_EXID);
-
-       if (at91_soc_initdata.type == AT91_SOC_SAMA5D4) {
-               switch (at91_soc_initdata.exid) {
-               case ARCH_EXID_SAMA5D41:
-                       at91_soc_initdata.subtype = AT91_SOC_SAMA5D41;
-                       break;
-               case ARCH_EXID_SAMA5D42:
-                       at91_soc_initdata.subtype = AT91_SOC_SAMA5D42;
-                       break;
-               case ARCH_EXID_SAMA5D43:
-                       at91_soc_initdata.subtype = AT91_SOC_SAMA5D43;
-                       break;
-               case ARCH_EXID_SAMA5D44:
-                       at91_soc_initdata.subtype = AT91_SOC_SAMA5D44;
-                       break;
-               }
-       }
-}
-
-static const char *soc_name[] = {
-       [AT91_SOC_RM9200]       = "at91rm9200",
-       [AT91_SOC_SAM9260]      = "at91sam9260",
-       [AT91_SOC_SAM9261]      = "at91sam9261",
-       [AT91_SOC_SAM9263]      = "at91sam9263",
-       [AT91_SOC_SAM9G10]      = "at91sam9g10",
-       [AT91_SOC_SAM9G20]      = "at91sam9g20",
-       [AT91_SOC_SAM9G45]      = "at91sam9g45",
-       [AT91_SOC_SAM9RL]       = "at91sam9rl",
-       [AT91_SOC_SAM9X5]       = "at91sam9x5",
-       [AT91_SOC_SAM9N12]      = "at91sam9n12",
-       [AT91_SOC_SAMA5D3]      = "sama5d3",
-       [AT91_SOC_SAMA5D4]      = "sama5d4",
-       [AT91_SOC_UNKNOWN]      = "Unknown",
-};
-
-const char *at91_get_soc_type(struct at91_socinfo *c)
-{
-       return soc_name[c->type];
-}
-EXPORT_SYMBOL(at91_get_soc_type);
-
-static const char *soc_subtype_name[] = {
-       [AT91_SOC_RM9200_BGA]   = "at91rm9200 BGA",
-       [AT91_SOC_RM9200_PQFP]  = "at91rm9200 PQFP",
-       [AT91_SOC_SAM9XE]       = "at91sam9xe",
-       [AT91_SOC_SAM9G45ES]    = "at91sam9g45es",
-       [AT91_SOC_SAM9M10]      = "at91sam9m10",
-       [AT91_SOC_SAM9G46]      = "at91sam9g46",
-       [AT91_SOC_SAM9M11]      = "at91sam9m11",
-       [AT91_SOC_SAM9G15]      = "at91sam9g15",
-       [AT91_SOC_SAM9G35]      = "at91sam9g35",
-       [AT91_SOC_SAM9X35]      = "at91sam9x35",
-       [AT91_SOC_SAM9G25]      = "at91sam9g25",
-       [AT91_SOC_SAM9X25]      = "at91sam9x25",
-       [AT91_SOC_SAMA5D31]     = "sama5d31",
-       [AT91_SOC_SAMA5D33]     = "sama5d33",
-       [AT91_SOC_SAMA5D34]     = "sama5d34",
-       [AT91_SOC_SAMA5D35]     = "sama5d35",
-       [AT91_SOC_SAMA5D36]     = "sama5d36",
-       [AT91_SOC_SAMA5D41]     = "sama5d41",
-       [AT91_SOC_SAMA5D42]     = "sama5d42",
-       [AT91_SOC_SAMA5D43]     = "sama5d43",
-       [AT91_SOC_SAMA5D44]     = "sama5d44",
-       [AT91_SOC_SUBTYPE_NONE] = "None",
-       [AT91_SOC_SUBTYPE_UNKNOWN] = "Unknown",
-};
-
-const char *at91_get_soc_subtype(struct at91_socinfo *c)
-{
-       return soc_subtype_name[c->subtype];
-}
-EXPORT_SYMBOL(at91_get_soc_subtype);
-
-void __init at91_map_io(void)
-{
-       /* Map peripherals */
-       iotable_init(&at91_io_desc, 1);
-
-       at91_soc_initdata.type = AT91_SOC_UNKNOWN;
-       at91_soc_initdata.subtype = AT91_SOC_SUBTYPE_UNKNOWN;
-
-       soc_detect(AT91_BASE_DBGU0);
-       if (!at91_soc_is_detected())
-               soc_detect(AT91_BASE_DBGU1);
-
-       if (!at91_soc_is_detected())
-               panic(pr_fmt("Impossible to detect the SOC type"));
-
-       pr_info("Detected soc type: %s\n",
-               at91_get_soc_type(&at91_soc_initdata));
-       if (at91_soc_initdata.subtype != AT91_SOC_SUBTYPE_NONE)
-               pr_info("Detected soc subtype: %s\n",
-                       at91_get_soc_subtype(&at91_soc_initdata));
-}
-
-void __init at91_alt_map_io(void)
-{
-       /* Map peripherals */
-       iotable_init(&at91_alt_io_desc, 1);
-
-       at91_soc_initdata.type = AT91_SOC_UNKNOWN;
-       at91_soc_initdata.subtype = AT91_SOC_SUBTYPE_UNKNOWN;
-
-       alt_soc_detect(AT91_BASE_DBGU2);
-       if (!at91_soc_is_detected())
-               panic("AT91: Impossible to detect the SOC type");
-
-       pr_info("AT91: Detected soc type: %s\n",
-               at91_get_soc_type(&at91_soc_initdata));
-       if (at91_soc_initdata.subtype != AT91_SOC_SUBTYPE_NONE)
-               pr_info("AT91: Detected soc subtype: %s\n",
-                       at91_get_soc_subtype(&at91_soc_initdata));
-}
-
-void __iomem *at91_matrix_base;
-EXPORT_SYMBOL_GPL(at91_matrix_base);
-
-void __init at91_ioremap_matrix(u32 base_addr)
-{
-       at91_matrix_base = ioremap(base_addr, 512);
-       if (!at91_matrix_base)
-               panic(pr_fmt("Impossible to ioremap at91_matrix_base\n"));
-}
diff --git a/arch/arm/mach-at91/soc.c b/arch/arm/mach-at91/soc.c
new file mode 100644 (file)
index 0000000..54343ff
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2015 Atmel
+ *
+ * Alexandre Belloni <alexandre.belloni@free-electrons.com
+ * Boris Brezillon <boris.brezillon@free-electrons.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.
+ *
+ */
+
+#define pr_fmt(fmt)    "AT91: " fmt
+
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+#include <linux/sys_soc.h>
+
+#include "soc.h"
+
+#define AT91_DBGU_CIDR                 0x40
+#define AT91_DBGU_CIDR_VERSION(x)      ((x) & 0x1f)
+#define AT91_DBGU_CIDR_EXT             BIT(31)
+#define AT91_DBGU_CIDR_MATCH_MASK      0x7fffffe0
+#define AT91_DBGU_EXID                 0x44
+
+struct soc_device * __init at91_soc_init(const struct at91_soc *socs)
+{
+       struct soc_device_attribute *soc_dev_attr;
+       const struct at91_soc *soc;
+       struct soc_device *soc_dev;
+       struct device_node *np;
+       void __iomem *regs;
+       u32 cidr, exid;
+
+       np = of_find_compatible_node(NULL, NULL, "atmel,at91rm9200-dbgu");
+       if (!np)
+               np = of_find_compatible_node(NULL, NULL,
+                                            "atmel,at91sam9260-dbgu");
+
+       if (!np) {
+               pr_warn("Could not find DBGU node");
+               return NULL;
+       }
+
+       regs = of_iomap(np, 0);
+       of_node_put(np);
+
+       if (!regs) {
+               pr_warn("Could not map DBGU iomem range");
+               return NULL;
+       }
+
+       cidr = readl(regs + AT91_DBGU_CIDR);
+       exid = readl(regs + AT91_DBGU_EXID);
+
+       iounmap(regs);
+
+       for (soc = socs; soc->name; soc++) {
+               if (soc->cidr_match != (cidr & AT91_DBGU_CIDR_MATCH_MASK))
+                       continue;
+
+               if (!(cidr & AT91_DBGU_CIDR_EXT) || soc->exid_match == exid)
+                       break;
+       }
+
+       if (!soc->name) {
+               pr_warn("Could not find matching SoC description\n");
+               return NULL;
+       }
+
+       soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+       if (!soc_dev_attr)
+               return NULL;
+
+       soc_dev_attr->family = soc->family;
+       soc_dev_attr->soc_id = soc->name;
+       soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%X",
+                                          AT91_DBGU_CIDR_VERSION(cidr));
+       soc_dev = soc_device_register(soc_dev_attr);
+       if (IS_ERR(soc_dev)) {
+               kfree(soc_dev_attr->revision);
+               kfree(soc_dev_attr);
+               pr_warn("Could not register SoC device\n");
+               return NULL;
+       }
+
+       if (soc->family)
+               pr_info("Detected SoC family: %s\n", soc->family);
+       pr_info("Detected SoC: %s, revision %X\n", soc->name,
+               AT91_DBGU_CIDR_VERSION(cidr));
+
+       return soc_dev;
+}
diff --git a/arch/arm/mach-at91/soc.h b/arch/arm/mach-at91/soc.h
new file mode 100644 (file)
index 0000000..be23c40
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2015 Atmel
+ *
+ * Boris Brezillon <boris.brezillon@free-electrons.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.
+ *
+ */
+
+#ifndef __AT91_SOC_H
+#define __AT91_SOC_H
+
+#include <linux/sys_soc.h>
+
+struct at91_soc {
+       u32 cidr_match;
+       u32 exid_match;
+       const char *name;
+       const char *family;
+};
+
+#define AT91_SOC(__cidr, __exid, __name, __family)             \
+       {                                                       \
+               .cidr_match = (__cidr),                         \
+               .exid_match = (__exid),                         \
+               .name = (__name),                               \
+               .family = (__family),                           \
+       }
+
+struct soc_device * __init
+at91_soc_init(const struct at91_soc *socs);
+
+#define AT91RM9200_CIDR_MATCH          0x09290780
+
+#define AT91SAM9260_CIDR_MATCH         0x019803a0
+#define AT91SAM9261_CIDR_MATCH         0x019703a0
+#define AT91SAM9263_CIDR_MATCH         0x019607a0
+#define AT91SAM9G20_CIDR_MATCH         0x019905a0
+#define AT91SAM9RL64_CIDR_MATCH                0x019b03a0
+#define AT91SAM9G45_CIDR_MATCH         0x019b05a0
+#define AT91SAM9X5_CIDR_MATCH          0x019a05a0
+#define AT91SAM9N12_CIDR_MATCH         0x019a07a0
+
+#define AT91SAM9M11_EXID_MATCH         0x00000001
+#define AT91SAM9M10_EXID_MATCH         0x00000002
+#define AT91SAM9G46_EXID_MATCH         0x00000003
+#define AT91SAM9G45_EXID_MATCH         0x00000004
+
+#define AT91SAM9G15_EXID_MATCH         0x00000000
+#define AT91SAM9G35_EXID_MATCH         0x00000001
+#define AT91SAM9X35_EXID_MATCH         0x00000002
+#define AT91SAM9G25_EXID_MATCH         0x00000003
+#define AT91SAM9X25_EXID_MATCH         0x00000004
+
+#define AT91SAM9CN12_EXID_MATCH                0x00000005
+#define AT91SAM9N12_EXID_MATCH         0x00000006
+#define AT91SAM9CN11_EXID_MATCH                0x00000009
+
+#define AT91SAM9XE128_CIDR_MATCH       0x329973a0
+#define AT91SAM9XE256_CIDR_MATCH       0x329a93a0
+#define AT91SAM9XE512_CIDR_MATCH       0x329aa3a0
+
+#define SAMA5D3_CIDR_MATCH             0x0a5c07c0
+#define SAMA5D31_EXID_MATCH            0x00444300
+#define SAMA5D33_EXID_MATCH            0x00414300
+#define SAMA5D34_EXID_MATCH            0x00414301
+#define SAMA5D35_EXID_MATCH            0x00584300
+#define SAMA5D36_EXID_MATCH            0x00004301
+
+#define SAMA5D4_CIDR_MATCH             0x0a5c07c0
+#define SAMA5D41_EXID_MATCH            0x00000001
+#define SAMA5D42_EXID_MATCH            0x00000002
+#define SAMA5D43_EXID_MATCH            0x00000003
+#define SAMA5D44_EXID_MATCH            0x00000004
+
+#endif /* __AT91_SOC_H */
index 30dc58be51b8e70f49074ee47523e534d6676337..7ae894c7849b7cde3bc61b952868652b0fc29c22 100644 (file)
@@ -13,7 +13,7 @@
 
 #include <asm/mach/arch.h>
 
-static const char const *bcm_cygnus_dt_compat[] = {
+static const char * const bcm_cygnus_dt_compat[] __initconst = {
        "brcm,cygnus",
        NULL,
 };
index fb38c726e9877d5472608cedf237913cf0efa23f..f46b78dd613655e0b2ec2acdfea7f9ccdeee710d 100644 (file)
@@ -73,7 +73,6 @@ static void cns3xxx_pwr_soft_rst_force(unsigned int block)
 
        __raw_writel(reg, PM_SOFT_RST_REG);
 }
-EXPORT_SYMBOL(cns3xxx_pwr_soft_rst_force);
 
 void cns3xxx_pwr_soft_rst(unsigned int block)
 {
index cd30f6f5f2ff15723a2abae07b471b03f65f9b11..dd8f5312b2c0e5d15e38b42dbaaee88a4718ce61 100644 (file)
@@ -200,17 +200,6 @@ config DA850_UI_SD_VIDEO_PORT
 
 endchoice
 
-config DA850_WL12XX
-       bool "AM18x wl1271 daughter board"
-       depends on MACH_DAVINCI_DA850_EVM
-       help
-         The wl1271 daughter card for AM18x EVMs is a combo wireless
-         connectivity add-on card, based on the LS Research TiWi module with
-         Texas Instruments' wl1271 solution.
-         Say Y if you want to use a wl1271 expansion card connected to the
-         AM18x EVM.
-
-
 config MACH_MITYOMAPL138
        bool "Critical Link MityDSP-L138/MityARM-1808 SoM"
        depends on ARCH_DAVINCI_DA850
index d9b2acd12393ab0e8f4968403ce5ad901553d146..1128e1d8e4b46690f3af8909c5e5d6829d642219 100644 (file)
@@ -21,6 +21,9 @@
 /* Bases of da830 McASP1 register banks */
 #define DAVINCI_DA830_MCASP1_REG_BASE  0x01D04000
 
+/* Bases of da830 McASP2 register banks */
+#define DAVINCI_DA830_MCASP2_REG_BASE  0x01D08000
+
 /* EDMA channels of dm644x and dm355 */
 #define DAVINCI_DMA_ASP0_TX    2
 #define DAVINCI_DMA_ASP0_RX    3
 #define DAVINCI_DA830_DMA_MCASP1_AREVT 2
 #define DAVINCI_DA830_DMA_MCASP1_AXEVT 3
 
+/* EDMA channels of da830 McASP2 */
+#define DAVINCI_DA830_DMA_MCASP2_AREVT 4
+#define DAVINCI_DA830_DMA_MCASP2_AXEVT 5
+
 /* Interrupts */
 #define DAVINCI_ASP0_RX_INT    IRQ_MBRINT
 #define DAVINCI_ASP0_TX_INT    IRQ_MBXINT
index 6b5a97da9fe39da65df47b5c9bbe8fd1359666d8..1ed545cc2b83452954cc4a2217ac1be324237775 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/regulator/fixed.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
-#include <linux/wl12xx.h>
 
 #include <mach/common.h>
 #include <mach/cp_intc.h>
@@ -60,9 +59,6 @@
 #define DA850_MMCSD_CD_PIN             GPIO_TO_PIN(4, 0)
 #define DA850_MMCSD_WP_PIN             GPIO_TO_PIN(4, 1)
 
-#define DA850_WLAN_EN                  GPIO_TO_PIN(6, 9)
-#define DA850_WLAN_IRQ                 GPIO_TO_PIN(6, 10)
-
 #define DA850_MII_MDIO_CLKEN_PIN       GPIO_TO_PIN(2, 6)
 
 static struct mtd_partition da850evm_spiflash_part[] = {
@@ -1343,109 +1339,6 @@ static __init void da850_vpif_init(void)
 static __init void da850_vpif_init(void) {}
 #endif
 
-#ifdef CONFIG_DA850_WL12XX
-
-static void wl12xx_set_power(int index, bool power_on)
-{
-       static bool power_state;
-
-       pr_debug("Powering %s wl12xx", power_on ? "on" : "off");
-
-       if (power_on == power_state)
-               return;
-       power_state = power_on;
-
-       if (power_on) {
-               /* Power up sequence required for wl127x devices */
-               gpio_set_value(DA850_WLAN_EN, 1);
-               usleep_range(15000, 15000);
-               gpio_set_value(DA850_WLAN_EN, 0);
-               usleep_range(1000, 1000);
-               gpio_set_value(DA850_WLAN_EN, 1);
-               msleep(70);
-       } else {
-               gpio_set_value(DA850_WLAN_EN, 0);
-       }
-}
-
-static struct davinci_mmc_config da850_wl12xx_mmc_config = {
-       .set_power      = wl12xx_set_power,
-       .wires          = 4,
-       .max_freq       = 25000000,
-       .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_NONREMOVABLE |
-                         MMC_CAP_POWER_OFF_CARD,
-};
-
-static const short da850_wl12xx_pins[] __initconst = {
-       DA850_MMCSD1_DAT_0, DA850_MMCSD1_DAT_1, DA850_MMCSD1_DAT_2,
-       DA850_MMCSD1_DAT_3, DA850_MMCSD1_CLK, DA850_MMCSD1_CMD,
-       DA850_GPIO6_9, DA850_GPIO6_10,
-       -1
-};
-
-static struct wl12xx_platform_data da850_wl12xx_wlan_data __initdata = {
-       .irq                    = -1,
-       .board_ref_clock        = WL12XX_REFCLOCK_38,
-       .platform_quirks        = WL12XX_PLATFORM_QUIRK_EDGE_IRQ,
-};
-
-static __init int da850_wl12xx_init(void)
-{
-       int ret;
-
-       ret = davinci_cfg_reg_list(da850_wl12xx_pins);
-       if (ret) {
-               pr_err("wl12xx/mmc mux setup failed: %d\n", ret);
-               goto exit;
-       }
-
-       ret = da850_register_mmcsd1(&da850_wl12xx_mmc_config);
-       if (ret) {
-               pr_err("wl12xx/mmc registration failed: %d\n", ret);
-               goto exit;
-       }
-
-       ret = gpio_request_one(DA850_WLAN_EN, GPIOF_OUT_INIT_LOW, "wl12xx_en");
-       if (ret) {
-               pr_err("Could not request wl12xx enable gpio: %d\n", ret);
-               goto exit;
-       }
-
-       ret = gpio_request_one(DA850_WLAN_IRQ, GPIOF_IN, "wl12xx_irq");
-       if (ret) {
-               pr_err("Could not request wl12xx irq gpio: %d\n", ret);
-               goto free_wlan_en;
-       }
-
-       da850_wl12xx_wlan_data.irq = gpio_to_irq(DA850_WLAN_IRQ);
-
-       ret = wl12xx_set_platform_data(&da850_wl12xx_wlan_data);
-       if (ret) {
-               pr_err("Could not set wl12xx data: %d\n", ret);
-               goto free_wlan_irq;
-       }
-
-       return 0;
-
-free_wlan_irq:
-       gpio_free(DA850_WLAN_IRQ);
-
-free_wlan_en:
-       gpio_free(DA850_WLAN_EN);
-
-exit:
-       return ret;
-}
-
-#else /* CONFIG_DA850_WL12XX */
-
-static __init int da850_wl12xx_init(void)
-{
-       return 0;
-}
-
-#endif /* CONFIG_DA850_WL12XX */
-
 #define DA850EVM_SATA_REFCLKPN_RATE    (100 * 1000 * 1000)
 
 static __init void da850_evm_init(void)
@@ -1502,11 +1395,6 @@ static __init void da850_evm_init(void)
                if (ret)
                        pr_warn("%s: MMCSD0 registration failed: %d\n",
                                __func__, ret);
-
-               ret = da850_wl12xx_init();
-               if (ret)
-                       pr_warn("%s: WL12xx initialization failed: %d\n",
-                               __func__, ret);
        }
 
        davinci_serial_init(da8xx_serial_device);
index b85b781b05fdf7d89d7a3c256727ea9024b6d0d8..ddfdd820e6f2b99f6bfa80a51a287255794d74d5 100644 (file)
@@ -463,16 +463,23 @@ static struct resource da830_mcasp1_resources[] = {
        },
        /* TX event */
        {
+               .name   = "tx",
                .start  = DAVINCI_DA830_DMA_MCASP1_AXEVT,
                .end    = DAVINCI_DA830_DMA_MCASP1_AXEVT,
                .flags  = IORESOURCE_DMA,
        },
        /* RX event */
        {
+               .name   = "rx",
                .start  = DAVINCI_DA830_DMA_MCASP1_AREVT,
                .end    = DAVINCI_DA830_DMA_MCASP1_AREVT,
                .flags  = IORESOURCE_DMA,
        },
+       {
+               .name   = "common",
+               .start  = IRQ_DA8XX_MCASPINT,
+               .flags  = IORESOURCE_IRQ,
+       },
 };
 
 static struct platform_device da830_mcasp1_device = {
@@ -482,6 +489,41 @@ static struct platform_device da830_mcasp1_device = {
        .resource       = da830_mcasp1_resources,
 };
 
+static struct resource da830_mcasp2_resources[] = {
+       {
+               .name   = "mpu",
+               .start  = DAVINCI_DA830_MCASP2_REG_BASE,
+               .end    = DAVINCI_DA830_MCASP2_REG_BASE + (SZ_1K * 12) - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       /* TX event */
+       {
+               .name   = "tx",
+               .start  = DAVINCI_DA830_DMA_MCASP2_AXEVT,
+               .end    = DAVINCI_DA830_DMA_MCASP2_AXEVT,
+               .flags  = IORESOURCE_DMA,
+       },
+       /* RX event */
+       {
+               .name   = "rx",
+               .start  = DAVINCI_DA830_DMA_MCASP2_AREVT,
+               .end    = DAVINCI_DA830_DMA_MCASP2_AREVT,
+               .flags  = IORESOURCE_DMA,
+       },
+       {
+               .name   = "common",
+               .start  = IRQ_DA8XX_MCASPINT,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device da830_mcasp2_device = {
+       .name           = "davinci-mcasp",
+       .id             = 2,
+       .num_resources  = ARRAY_SIZE(da830_mcasp2_resources),
+       .resource       = da830_mcasp2_resources,
+};
+
 static struct resource da850_mcasp_resources[] = {
        {
                .name   = "mpu",
@@ -491,16 +533,23 @@ static struct resource da850_mcasp_resources[] = {
        },
        /* TX event */
        {
+               .name   = "tx",
                .start  = DAVINCI_DA8XX_DMA_MCASP0_AXEVT,
                .end    = DAVINCI_DA8XX_DMA_MCASP0_AXEVT,
                .flags  = IORESOURCE_DMA,
        },
        /* RX event */
        {
+               .name   = "rx",
                .start  = DAVINCI_DA8XX_DMA_MCASP0_AREVT,
                .end    = DAVINCI_DA8XX_DMA_MCASP0_AREVT,
                .flags  = IORESOURCE_DMA,
        },
+       {
+               .name   = "common",
+               .start  = IRQ_DA8XX_MCASPINT,
+               .flags  = IORESOURCE_IRQ,
+       },
 };
 
 static struct platform_device da850_mcasp_device = {
@@ -512,14 +561,31 @@ static struct platform_device da850_mcasp_device = {
 
 void __init da8xx_register_mcasp(int id, struct snd_platform_data *pdata)
 {
-       /* DA830/OMAP-L137 has 3 instances of McASP */
-       if (cpu_is_davinci_da830() && id == 1) {
-               da830_mcasp1_device.dev.platform_data = pdata;
-               platform_device_register(&da830_mcasp1_device);
-       } else if (cpu_is_davinci_da850()) {
-               da850_mcasp_device.dev.platform_data = pdata;
-               platform_device_register(&da850_mcasp_device);
+       struct platform_device *pdev;
+
+       switch (id) {
+       case 0:
+               /* Valid for DA830/OMAP-L137 or DA850/OMAP-L138 */
+               pdev = &da850_mcasp_device;
+               break;
+       case 1:
+               /* Valid for DA830/OMAP-L137 only */
+               if (!cpu_is_davinci_da830())
+                       return;
+               pdev = &da830_mcasp1_device;
+               break;
+       case 2:
+               /* Valid for DA830/OMAP-L137 only */
+               if (!cpu_is_davinci_da830())
+                       return;
+               pdev = &da830_mcasp2_device;
+               break;
+       default:
+               return;
        }
+
+       pdev->dev.platform_data = pdata;
+       platform_device_register(pdev);
 }
 
 static struct resource da8xx_pruss_resources[] = {
index 6c3bbea7d77d8f8f2432ec9321936cedf2e942f5..3f842bb266d6ebe6226209433dca0b805398afaa 100644 (file)
@@ -493,7 +493,6 @@ static u8 dm646x_default_priorities[DAVINCI_N_AINTC_IRQ] = {
        [IRQ_DM646X_EMACMISCINT]        = 7,
        [IRQ_DM646X_MCASP0TXINT]        = 7,
        [IRQ_DM646X_MCASP0RXINT]        = 7,
-       [IRQ_AEMIFINT]                  = 7,
        [IRQ_DM646X_RESERVED_3]         = 7,
        [IRQ_DM646X_MCASP1TXINT]        = 7,    /* clockevent */
        [IRQ_TINT0_TINT34]              = 7,    /* clocksource */
@@ -610,19 +609,31 @@ static struct resource dm646x_mcasp0_resources[] = {
                .end    = DAVINCI_DM646X_MCASP0_REG_BASE + (SZ_1K << 1) - 1,
                .flags  = IORESOURCE_MEM,
        },
-       /* first TX, then RX */
        {
+               .name   = "tx",
                .start  = DAVINCI_DM646X_DMA_MCASP0_AXEVT0,
                .end    = DAVINCI_DM646X_DMA_MCASP0_AXEVT0,
                .flags  = IORESOURCE_DMA,
        },
        {
+               .name   = "rx",
                .start  = DAVINCI_DM646X_DMA_MCASP0_AREVT0,
                .end    = DAVINCI_DM646X_DMA_MCASP0_AREVT0,
                .flags  = IORESOURCE_DMA,
        },
+       {
+               .name   = "tx",
+               .start  = IRQ_DM646X_MCASP0TXINT,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .name   = "rx",
+               .start  = IRQ_DM646X_MCASP0RXINT,
+               .flags  = IORESOURCE_IRQ,
+       },
 };
 
+/* DIT mode only, rx is not supported */
 static struct resource dm646x_mcasp1_resources[] = {
        {
                .name   = "mpu",
@@ -630,17 +641,16 @@ static struct resource dm646x_mcasp1_resources[] = {
                .end    = DAVINCI_DM646X_MCASP1_REG_BASE + (SZ_1K << 1) - 1,
                .flags  = IORESOURCE_MEM,
        },
-       /* DIT mode, only TX event */
        {
+               .name   = "tx",
                .start  = DAVINCI_DM646X_DMA_MCASP1_AXEVT1,
                .end    = DAVINCI_DM646X_DMA_MCASP1_AXEVT1,
                .flags  = IORESOURCE_DMA,
        },
-       /* DIT mode, dummy entry */
        {
-               .start  = -1,
-               .end    = -1,
-               .flags  = IORESOURCE_DMA,
+               .name   = "tx",
+               .start  = IRQ_DM646X_MCASP1TXINT,
+               .flags  = IORESOURCE_IRQ,
        },
 };
 
index 354af71798dcd4e09206ae6e82bfa862b4ccb0a1..edb2ca62321ae141ed6e5a9afe910e88b423bbe9 100644 (file)
 #define IRQ_DM646X_EMACMISCINT  27
 #define IRQ_DM646X_MCASP0TXINT  28
 #define IRQ_DM646X_MCASP0RXINT  29
+#define IRQ_DM646X_MCASP1TXINT  30
 #define IRQ_DM646X_RESERVED_3   31
-#define IRQ_DM646X_MCASP1TXINT  32
 #define IRQ_DM646X_VLQINT       38
 #define IRQ_DM646X_UARTINT2     42
 #define IRQ_DM646X_SPINT0       43
index 603820e5aba79bc17bab7acd56f87a69af087c45..81064cd61a0a9e72536d6dd6df56555bae352d61 100644 (file)
@@ -123,7 +123,7 @@ config SOC_EXYNOS5800
 config EXYNOS5420_MCPM
        bool "Exynos5420 Multi-Cluster PM support"
        depends on MCPM && SOC_EXYNOS5420
-       select ARM_CCI
+       select ARM_CCI400_PORT_CTRL
        select ARM_CPU_SUSPEND
        help
          This is needed to provide CPU and cluster power management
index f70eca7ee705fd26490d3ce7bbdc1988cbdf8752..acd5b560b72801c6e2e4b51baa5ca4c129f44b2d 100644 (file)
@@ -126,6 +126,12 @@ enum {
 
 void exynos_firmware_init(void);
 
+/* CPU BOOT mode flag for Exynos3250 SoC bootloader */
+#define C2_STATE       (1 << 3)
+
+void exynos_set_boot_flag(unsigned int cpu, unsigned int mode);
+void exynos_clear_boot_flag(unsigned int cpu, unsigned int mode);
+
 extern u32 exynos_get_eint_wake_mask(void);
 
 #ifdef CONFIG_PM_SLEEP
index f44c2e05c82e36ae3598ebf7ffe60e54a14235cc..bcde0dd668df950f1918a66179715a56ec9578fa 100644 (file)
@@ -206,7 +206,7 @@ static void __init exynos_dt_machine_init(void)
        if (!IS_ENABLED(CONFIG_SMP))
                exynos_sysram_init();
 
-#ifdef CONFIG_ARM_EXYNOS_CPUIDLE
+#if defined(CONFIG_SMP) && defined(CONFIG_ARM_EXYNOS_CPUIDLE)
        if (of_machine_is_compatible("samsung,exynos4210"))
                exynos_cpuidle.dev.platform_data = &cpuidle_coupled_exynos_data;
 #endif
@@ -214,6 +214,7 @@ static void __init exynos_dt_machine_init(void)
            of_machine_is_compatible("samsung,exynos4212") ||
            (of_machine_is_compatible("samsung,exynos4412") &&
             of_machine_is_compatible("samsung,trats2")) ||
+           of_machine_is_compatible("samsung,exynos3250") ||
            of_machine_is_compatible("samsung,exynos5250"))
                platform_device_register(&exynos_cpuidle);
 
index 4791a3cc00f9d40e71c474d6130c02697ebcd090..1bd35763f12ec04d712ace47f0f88bd2f9c95c89 100644 (file)
@@ -48,7 +48,13 @@ static int exynos_do_idle(unsigned long mode)
                __raw_writel(virt_to_phys(exynos_cpu_resume_ns),
                             sysram_ns_base_addr + 0x24);
                __raw_writel(EXYNOS_AFTR_MAGIC, sysram_ns_base_addr + 0x20);
-               exynos_smc(SMC_CMD_CPU0AFTR, 0, 0, 0);
+               if (soc_is_exynos3250()) {
+                       exynos_smc(SMC_CMD_SAVE, OP_TYPE_CORE,
+                                  SMC_POWERSTATE_IDLE, 0);
+                       exynos_smc(SMC_CMD_SHUTDOWN, OP_TYPE_CLUSTER,
+                                  SMC_POWERSTATE_IDLE, 0);
+               } else
+                       exynos_smc(SMC_CMD_CPU0AFTR, 0, 0, 0);
                break;
        case FW_DO_IDLE_SLEEP:
                exynos_smc(SMC_CMD_SLEEP, 0, 0, 0);
@@ -206,3 +212,28 @@ void __init exynos_firmware_init(void)
                outer_cache.configure = exynos_l2_configure;
        }
 }
+
+#define REG_CPU_STATE_ADDR     (sysram_ns_base_addr + 0x28)
+#define BOOT_MODE_MASK         0x1f
+
+void exynos_set_boot_flag(unsigned int cpu, unsigned int mode)
+{
+       unsigned int tmp;
+
+       tmp = __raw_readl(REG_CPU_STATE_ADDR + cpu * 4);
+
+       if (mode & BOOT_MODE_MASK)
+               tmp &= ~BOOT_MODE_MASK;
+
+       tmp |= mode;
+       __raw_writel(tmp, REG_CPU_STATE_ADDR + cpu * 4);
+}
+
+void exynos_clear_boot_flag(unsigned int cpu, unsigned int mode)
+{
+       unsigned int tmp;
+
+       tmp = __raw_readl(REG_CPU_STATE_ADDR + cpu * 4);
+       tmp &= ~mode;
+       __raw_writel(tmp, REG_CPU_STATE_ADDR + cpu * 4);
+}
index b0d3c2e876fbe9227d651b8c2bcc86de22fc0fc7..9bdf54795f05de26283881729a4427bd781ea2eb 100644 (file)
@@ -61,25 +61,7 @@ static void __iomem *ns_sram_base_addr;
        : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
          "r9", "r10", "lr", "memory")
 
-/*
- * We can't use regular spinlocks. In the switcher case, it is possible
- * for an outbound CPU to call power_down() after its inbound counterpart
- * is already live using the same logical CPU number which trips lockdep
- * debugging.
- */
-static arch_spinlock_t exynos_mcpm_lock = __ARCH_SPIN_LOCK_UNLOCKED;
-static int
-cpu_use_count[EXYNOS5420_CPUS_PER_CLUSTER][EXYNOS5420_NR_CLUSTERS];
-
-#define exynos_cluster_usecnt(cluster) \
-       (cpu_use_count[0][cluster] +   \
-        cpu_use_count[1][cluster] +   \
-        cpu_use_count[2][cluster] +   \
-        cpu_use_count[3][cluster])
-
-#define exynos_cluster_unused(cluster) !exynos_cluster_usecnt(cluster)
-
-static int exynos_power_up(unsigned int cpu, unsigned int cluster)
+static int exynos_cpu_powerup(unsigned int cpu, unsigned int cluster)
 {
        unsigned int cpunr = cpu + (cluster * EXYNOS5420_CPUS_PER_CLUSTER);
 
@@ -88,127 +70,65 @@ static int exynos_power_up(unsigned int cpu, unsigned int cluster)
                cluster >= EXYNOS5420_NR_CLUSTERS)
                return -EINVAL;
 
-       /*
-        * Since this is called with IRQs enabled, and no arch_spin_lock_irq
-        * variant exists, we need to disable IRQs manually here.
-        */
-       local_irq_disable();
-       arch_spin_lock(&exynos_mcpm_lock);
-
-       cpu_use_count[cpu][cluster]++;
-       if (cpu_use_count[cpu][cluster] == 1) {
-               bool was_cluster_down =
-                       (exynos_cluster_usecnt(cluster) == 1);
-
-               /*
-                * Turn on the cluster (L2/COMMON) and then power on the
-                * cores.
-                */
-               if (was_cluster_down)
-                       exynos_cluster_power_up(cluster);
-
-               exynos_cpu_power_up(cpunr);
-       } else if (cpu_use_count[cpu][cluster] != 2) {
-               /*
-                * The only possible values are:
-                * 0 = CPU down
-                * 1 = CPU (still) up
-                * 2 = CPU requested to be up before it had a chance
-                *     to actually make itself down.
-                * Any other value is a bug.
-                */
-               BUG();
-       }
+       exynos_cpu_power_up(cpunr);
+       return 0;
+}
 
-       arch_spin_unlock(&exynos_mcpm_lock);
-       local_irq_enable();
+static int exynos_cluster_powerup(unsigned int cluster)
+{
+       pr_debug("%s: cluster %u\n", __func__, cluster);
+       if (cluster >= EXYNOS5420_NR_CLUSTERS)
+               return -EINVAL;
 
+       exynos_cluster_power_up(cluster);
        return 0;
 }
 
-/*
- * NOTE: This function requires the stack data to be visible through power down
- * and can only be executed on processors like A15 and A7 that hit the cache
- * with the C bit clear in the SCTLR register.
- */
-static void exynos_power_down(void)
+static void exynos_cpu_powerdown_prepare(unsigned int cpu, unsigned int cluster)
 {
-       unsigned int mpidr, cpu, cluster;
-       bool last_man = false, skip_wfi = false;
-       unsigned int cpunr;
-
-       mpidr = read_cpuid_mpidr();
-       cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
-       cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
-       cpunr =  cpu + (cluster * EXYNOS5420_CPUS_PER_CLUSTER);
+       unsigned int cpunr = cpu + (cluster * EXYNOS5420_CPUS_PER_CLUSTER);
 
        pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
        BUG_ON(cpu >= EXYNOS5420_CPUS_PER_CLUSTER ||
                        cluster >= EXYNOS5420_NR_CLUSTERS);
+       exynos_cpu_power_down(cpunr);
+}
 
-       __mcpm_cpu_going_down(cpu, cluster);
-
-       arch_spin_lock(&exynos_mcpm_lock);
-       BUG_ON(__mcpm_cluster_state(cluster) != CLUSTER_UP);
-       cpu_use_count[cpu][cluster]--;
-       if (cpu_use_count[cpu][cluster] == 0) {
-               exynos_cpu_power_down(cpunr);
-
-               if (exynos_cluster_unused(cluster)) {
-                       exynos_cluster_power_down(cluster);
-                       last_man = true;
-               }
-       } else if (cpu_use_count[cpu][cluster] == 1) {
-               /*
-                * A power_up request went ahead of us.
-                * Even if we do not want to shut this CPU down,
-                * the caller expects a certain state as if the WFI
-                * was aborted.  So let's continue with cache cleaning.
-                */
-               skip_wfi = true;
-       } else {
-               BUG();
-       }
-
-       if (last_man && __mcpm_outbound_enter_critical(cpu, cluster)) {
-               arch_spin_unlock(&exynos_mcpm_lock);
-
-               if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A15) {
-                       /*
-                        * On the Cortex-A15 we need to disable
-                        * L2 prefetching before flushing the cache.
-                        */
-                       asm volatile(
-                       "mcr    p15, 1, %0, c15, c0, 3\n\t"
-                       "isb\n\t"
-                       "dsb"
-                       : : "r" (0x400));
-               }
+static void exynos_cluster_powerdown_prepare(unsigned int cluster)
+{
+       pr_debug("%s: cluster %u\n", __func__, cluster);
+       BUG_ON(cluster >= EXYNOS5420_NR_CLUSTERS);
+       exynos_cluster_power_down(cluster);
+}
 
-               /* Flush all cache levels for this cluster. */
-               exynos_v7_exit_coherency_flush(all);
+static void exynos_cpu_cache_disable(void)
+{
+       /* Disable and flush the local CPU cache. */
+       exynos_v7_exit_coherency_flush(louis);
+}
 
+static void exynos_cluster_cache_disable(void)
+{
+       if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A15) {
                /*
-                * Disable cluster-level coherency by masking
-                * incoming snoops and DVM messages:
+                * On the Cortex-A15 we need to disable
+                * L2 prefetching before flushing the cache.
                 */
-               cci_disable_port_by_cpu(mpidr);
-
-               __mcpm_outbound_leave_critical(cluster, CLUSTER_DOWN);
-       } else {
-               arch_spin_unlock(&exynos_mcpm_lock);
-
-               /* Disable and flush the local CPU cache. */
-               exynos_v7_exit_coherency_flush(louis);
+               asm volatile(
+               "mcr    p15, 1, %0, c15, c0, 3\n\t"
+               "isb\n\t"
+               "dsb"
+               : : "r" (0x400));
        }
 
-       __mcpm_cpu_down(cpu, cluster);
-
-       /* Now we are prepared for power-down, do it: */
-       if (!skip_wfi)
-               wfi();
+       /* Flush all cache levels for this cluster. */
+       exynos_v7_exit_coherency_flush(all);
 
-       /* Not dead at this point?  Let our caller cope. */
+       /*
+        * Disable cluster-level coherency by masking
+        * incoming snoops and DVM messages:
+        */
+       cci_disable_port_by_cpu(read_cpuid_mpidr());
 }
 
 static int exynos_wait_for_powerdown(unsigned int cpu, unsigned int cluster)
@@ -222,10 +142,8 @@ static int exynos_wait_for_powerdown(unsigned int cpu, unsigned int cluster)
 
        /* Wait for the core state to be OFF */
        while (tries--) {
-               if (ACCESS_ONCE(cpu_use_count[cpu][cluster]) == 0) {
-                       if ((exynos_cpu_power_state(cpunr) == 0))
-                               return 0; /* success: the CPU is halted */
-               }
+               if ((exynos_cpu_power_state(cpunr) == 0))
+                       return 0; /* success: the CPU is halted */
 
                /* Otherwise, wait and retry: */
                msleep(1);
@@ -234,63 +152,23 @@ static int exynos_wait_for_powerdown(unsigned int cpu, unsigned int cluster)
        return -ETIMEDOUT; /* timeout */
 }
 
-static void exynos_powered_up(void)
-{
-       unsigned int mpidr, cpu, cluster;
-
-       mpidr = read_cpuid_mpidr();
-       cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
-       cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
-
-       arch_spin_lock(&exynos_mcpm_lock);
-       if (cpu_use_count[cpu][cluster] == 0)
-               cpu_use_count[cpu][cluster] = 1;
-       arch_spin_unlock(&exynos_mcpm_lock);
-}
-
-static void exynos_suspend(u64 residency)
+static void exynos_cpu_is_up(unsigned int cpu, unsigned int cluster)
 {
-       unsigned int mpidr, cpunr;
-
-       exynos_power_down();
-
-       /*
-        * Execution reaches here only if cpu did not power down.
-        * Hence roll back the changes done in exynos_power_down function.
-        *
-        * CAUTION: "This function requires the stack data to be visible through
-        * power down and can only be executed on processors like A15 and A7
-        * that hit the cache with the C bit clear in the SCTLR register."
-       */
-       mpidr = read_cpuid_mpidr();
-       cpunr = exynos_pmu_cpunr(mpidr);
-
-       exynos_cpu_power_up(cpunr);
+       /* especially when resuming: make sure power control is set */
+       exynos_cpu_powerup(cpu, cluster);
 }
 
 static const struct mcpm_platform_ops exynos_power_ops = {
-       .power_up               = exynos_power_up,
-       .power_down             = exynos_power_down,
+       .cpu_powerup            = exynos_cpu_powerup,
+       .cluster_powerup        = exynos_cluster_powerup,
+       .cpu_powerdown_prepare  = exynos_cpu_powerdown_prepare,
+       .cluster_powerdown_prepare = exynos_cluster_powerdown_prepare,
+       .cpu_cache_disable      = exynos_cpu_cache_disable,
+       .cluster_cache_disable  = exynos_cluster_cache_disable,
        .wait_for_powerdown     = exynos_wait_for_powerdown,
-       .suspend                = exynos_suspend,
-       .powered_up             = exynos_powered_up,
+       .cpu_is_up              = exynos_cpu_is_up,
 };
 
-static void __init exynos_mcpm_usage_count_init(void)
-{
-       unsigned int mpidr, cpu, cluster;
-
-       mpidr = read_cpuid_mpidr();
-       cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
-       cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
-
-       pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
-       BUG_ON(cpu >= EXYNOS5420_CPUS_PER_CLUSTER  ||
-                       cluster >= EXYNOS5420_NR_CLUSTERS);
-
-       cpu_use_count[cpu][cluster] = 1;
-}
-
 /*
  * Enable cluster-level coherency, in preparation for turning on the MMU.
  */
@@ -302,19 +180,6 @@ static void __naked exynos_pm_power_up_setup(unsigned int affinity_level)
        "b      cci_enable_port_for_self");
 }
 
-static void __init exynos_cache_off(void)
-{
-       if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A15) {
-               /* disable L2 prefetching on the Cortex-A15 */
-               asm volatile(
-               "mcr    p15, 1, %0, c15, c0, 3\n\t"
-               "isb\n\t"
-               "dsb"
-               : : "r" (0x400));
-       }
-       exynos_v7_exit_coherency_flush(all);
-}
-
 static const struct of_device_id exynos_dt_mcpm_match[] = {
        { .compatible = "samsung,exynos5420" },
        { .compatible = "samsung,exynos5800" },
@@ -370,13 +235,11 @@ static int __init exynos_mcpm_init(void)
         */
        pmu_raw_writel(EXYNOS5420_SWRESET_KFC_SEL, S5P_PMU_SPARE3);
 
-       exynos_mcpm_usage_count_init();
-
        ret = mcpm_platform_register(&exynos_power_ops);
        if (!ret)
                ret = mcpm_sync_init(exynos_pm_power_up_setup);
        if (!ret)
-               ret = mcpm_loopback(exynos_cache_off); /* turn on the CCI */
+               ret = mcpm_loopback(exynos_cluster_cache_disable); /* turn on the CCI */
        if (ret) {
                iounmap(ns_sram_base_addr);
                return ret;
index d2e9f12d12f187e1e2c40f11748f75bbe0a283f2..ebd135bb0995611517c1bce6d3b70deeeee37de4 100644 (file)
@@ -126,6 +126,8 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
  */
 void exynos_cpu_power_down(int cpu)
 {
+       u32 core_conf;
+
        if (cpu == 0 && (soc_is_exynos5420() || soc_is_exynos5800())) {
                /*
                 * Bypass power down for CPU0 during suspend. Check for
@@ -137,7 +139,10 @@ void exynos_cpu_power_down(int cpu)
                if (!(val & S5P_CORE_LOCAL_PWR_EN))
                        return;
        }
-       pmu_raw_writel(0, EXYNOS_ARM_CORE_CONFIGURATION(cpu));
+
+       core_conf = pmu_raw_readl(EXYNOS_ARM_CORE_CONFIGURATION(cpu));
+       core_conf &= ~S5P_CORE_LOCAL_PWR_EN;
+       pmu_raw_writel(core_conf, EXYNOS_ARM_CORE_CONFIGURATION(cpu));
 }
 
 /**
@@ -148,7 +153,12 @@ void exynos_cpu_power_down(int cpu)
  */
 void exynos_cpu_power_up(int cpu)
 {
-       pmu_raw_writel(S5P_CORE_LOCAL_PWR_EN,
+       u32 core_conf = S5P_CORE_LOCAL_PWR_EN;
+
+       if (soc_is_exynos3250())
+               core_conf |= S5P_CORE_AUTOWAKEUP_EN;
+
+       pmu_raw_writel(core_conf,
                        EXYNOS_ARM_CORE_CONFIGURATION(cpu));
 }
 
@@ -226,6 +236,10 @@ static void exynos_core_restart(u32 core_id)
        if (!of_machine_is_compatible("samsung,exynos3250"))
                return;
 
+       while (!pmu_raw_readl(S5P_PMU_SPARE2))
+               udelay(10);
+       udelay(10);
+
        val = pmu_raw_readl(EXYNOS_ARM_CORE_STATUS(core_id));
        val |= S5P_CORE_WAKEUP_FROM_LOCAL_CFG;
        pmu_raw_writel(val, EXYNOS_ARM_CORE_STATUS(core_id));
@@ -346,7 +360,10 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
 
                call_firmware_op(cpu_boot, core_id);
 
-               arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+               if (soc_is_exynos3250())
+                       dsb_sev();
+               else
+                       arch_send_wakeup_ipi_mask(cpumask_of(cpu));
 
                if (pen_release == -1)
                        break;
index e6209dadc00d483c6e85b2b2870bc82828ad749d..cc75ab448be3b4ce9b3c0fc2e626da4ed3d6e6ca 100644 (file)
@@ -127,6 +127,8 @@ int exynos_pm_central_resume(void)
 static void exynos_set_wakeupmask(long mask)
 {
        pmu_raw_writel(mask, S5P_WAKEUP_MASK);
+       if (soc_is_exynos3250())
+               pmu_raw_writel(0x0, S5P_WAKEUP_MASK2);
 }
 
 static void exynos_cpu_set_boot_vector(long flags)
@@ -140,7 +142,7 @@ static int exynos_aftr_finisher(unsigned long flags)
 {
        int ret;
 
-       exynos_set_wakeupmask(0x0000ff3e);
+       exynos_set_wakeupmask(soc_is_exynos3250() ? 0x40003ffe : 0x0000ff3e);
        /* Set value of power down register for aftr mode */
        exynos_sys_powerdown_conf(SYS_AFTR);
 
@@ -157,8 +159,13 @@ static int exynos_aftr_finisher(unsigned long flags)
 
 void exynos_enter_aftr(void)
 {
+       unsigned int cpuid = smp_processor_id();
+
        cpu_pm_enter();
 
+       if (soc_is_exynos3250())
+               exynos_set_boot_flag(cpuid, C2_STATE);
+
        exynos_pm_central_suspend();
 
        if (of_machine_is_compatible("samsung,exynos4212") ||
@@ -178,9 +185,13 @@ void exynos_enter_aftr(void)
 
        exynos_pm_central_resume();
 
+       if (soc_is_exynos3250())
+               exynos_clear_boot_flag(cpuid, C2_STATE);
+
        cpu_pm_exit();
 }
 
+#if defined(CONFIG_SMP) && defined(CONFIG_ARM_EXYNOS_CPUIDLE)
 static atomic_t cpu1_wakeup = ATOMIC_INIT(0);
 
 static int exynos_cpu0_enter_aftr(void)
@@ -302,3 +313,4 @@ struct cpuidle_exynos_data cpuidle_coupled_exynos_data = {
        .pre_enter_aftr         = exynos_pre_enter_aftr,
        .post_enter_aftr                = exynos_post_enter_aftr,
 };
+#endif /* CONFIG_SMP && CONFIG_ARM_EXYNOS_CPUIDLE */
index 37266a8264372a9d8ab898aec6389476f707869f..cbe56b35aea000fe2ad5841851b5eb9a57a307d5 100644 (file)
@@ -37,6 +37,7 @@ struct exynos_pm_domain {
        struct clk *oscclk;
        struct clk *clk[MAX_CLK_PER_DOMAIN];
        struct clk *pclk[MAX_CLK_PER_DOMAIN];
+       struct clk *asb_clk[MAX_CLK_PER_DOMAIN];
 };
 
 static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
@@ -45,14 +46,19 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
        void __iomem *base;
        u32 timeout, pwr;
        char *op;
+       int i;
 
        pd = container_of(domain, struct exynos_pm_domain, pd);
        base = pd->base;
 
+       for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
+               if (IS_ERR(pd->asb_clk[i]))
+                       break;
+               clk_prepare_enable(pd->asb_clk[i]);
+       }
+
        /* Set oscclk before powering off a domain*/
        if (!power_on) {
-               int i;
-
                for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
                        if (IS_ERR(pd->clk[i]))
                                break;
@@ -81,8 +87,6 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
 
        /* Restore clocks after powering on a domain*/
        if (power_on) {
-               int i;
-
                for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
                        if (IS_ERR(pd->clk[i]))
                                break;
@@ -92,6 +96,12 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
                }
        }
 
+       for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
+               if (IS_ERR(pd->asb_clk[i]))
+                       break;
+               clk_disable_unprepare(pd->asb_clk[i]);
+       }
+
        return 0;
 }
 
@@ -125,12 +135,21 @@ static __init int exynos4_pm_init_power_domain(void)
                        return -ENOMEM;
                }
 
-               pd->pd.name = kstrdup(np->name, GFP_KERNEL);
+               pd->pd.name = kstrdup(dev_name(dev), GFP_KERNEL);
                pd->name = pd->pd.name;
                pd->base = of_iomap(np, 0);
                pd->pd.power_off = exynos_pd_power_off;
                pd->pd.power_on = exynos_pd_power_on;
 
+               for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
+                       char clk_name[8];
+
+                       snprintf(clk_name, sizeof(clk_name), "asb%d", i);
+                       pd->asb_clk[i] = clk_get(dev, clk_name);
+                       if (IS_ERR(pd->asb_clk[i]))
+                               break;
+               }
+
                pd->oscclk = clk_get(dev, "oscclk");
                if (IS_ERR(pd->oscclk))
                        goto no_clk;
index eb461e1c325ad96952495dad756af1d6b9c8a049..b7614333d2968befa767109f693bf7947528db4a 100644 (file)
 #define S5P_WAKEUP_STAT                                0x0600
 #define S5P_EINT_WAKEUP_MASK                   0x0604
 #define S5P_WAKEUP_MASK                                0x0608
+#define S5P_WAKEUP_MASK2                               0x0614
 
 #define S5P_INFORM0                            0x0800
 #define S5P_INFORM1                            0x0804
 #define S5P_INFORM5                            0x0814
 #define S5P_INFORM6                            0x0818
 #define S5P_INFORM7                            0x081C
+#define S5P_PMU_SPARE2                         0x0908
 #define S5P_PMU_SPARE3                         0x090C
 
 #define EXYNOS_IROM_DATA2                      0x0988
 
 #define S5P_CORE_LOCAL_PWR_EN                  0x3
 #define S5P_CORE_WAKEUP_FROM_LOCAL_CFG         (0x3 << 8)
+#define S5P_CORE_AUTOWAKEUP_EN                 (1 << 31)
 
 /* Only for EXYNOS4210 */
 #define S5P_CMU_CLKSTOP_LCD1_LOWPWR    0x1154
index f7b82f9c1e213053c53aaab321fb0e9f558b8b73..c2845717bc8fd9860d62ee14191556854a484d7d 100644 (file)
@@ -17,6 +17,8 @@
 #define SMC_CMD_SLEEP          (-3)
 #define SMC_CMD_CPU1BOOT       (-4)
 #define SMC_CMD_CPU0AFTR       (-5)
+#define SMC_CMD_SAVE           (-6)
+#define SMC_CMD_SHUTDOWN       (-7)
 /* For CP15 Access */
 #define SMC_CMD_C15RESUME      (-11)
 /* For L2 Cache Access */
@@ -32,4 +34,11 @@ extern void exynos_smc(u32 cmd, u32 arg1, u32 arg2, u32 arg3);
 
 #endif /* __ASSEMBLY__ */
 
+/* op type for SMC_CMD_SAVE and SMC_CMD_SHUTDOWN */
+#define OP_TYPE_CORE           0x0
+#define OP_TYPE_CLUSTER                0x1
+
+/* Power State required for SMC_CMD_SAVE and SMC_CMD_SHUTDOWN */
+#define SMC_POWERSTATE_IDLE    0x1
+
 #endif
index 2146d918aedd265623cd3a7cb1393e4437095f3b..3e6aea7f83af199d7c624372fb96549430504cc2 100644 (file)
@@ -65,8 +65,6 @@ static struct sleep_save exynos_core_save[] = {
 
 struct exynos_pm_data {
        const struct exynos_wkup_irq *wkup_irq;
-       struct sleep_save *extra_save;
-       int num_extra_save;
        unsigned int wake_disable_mask;
        unsigned int *release_ret_regs;
 
@@ -77,7 +75,7 @@ struct exynos_pm_data {
        int (*cpu_suspend)(unsigned long);
 };
 
-struct exynos_pm_data *pm_data;
+static const struct exynos_pm_data *pm_data;
 
 static int exynos5420_cpu_state;
 static unsigned int exynos_pmu_spare3;
@@ -106,7 +104,7 @@ static const struct exynos_wkup_irq exynos5250_wkup_irq[] = {
        { /* sentinel */ },
 };
 
-unsigned int exynos_release_ret_regs[] = {
+static unsigned int exynos_release_ret_regs[] = {
        S5P_PAD_RET_MAUDIO_OPTION,
        S5P_PAD_RET_GPIO_OPTION,
        S5P_PAD_RET_UART_OPTION,
@@ -117,7 +115,7 @@ unsigned int exynos_release_ret_regs[] = {
        REG_TABLE_END,
 };
 
-unsigned int exynos3250_release_ret_regs[] = {
+static unsigned int exynos3250_release_ret_regs[] = {
        S5P_PAD_RET_MAUDIO_OPTION,
        S5P_PAD_RET_GPIO_OPTION,
        S5P_PAD_RET_UART_OPTION,
@@ -130,7 +128,7 @@ unsigned int exynos3250_release_ret_regs[] = {
        REG_TABLE_END,
 };
 
-unsigned int exynos5420_release_ret_regs[] = {
+static unsigned int exynos5420_release_ret_regs[] = {
        EXYNOS_PAD_RET_DRAM_OPTION,
        EXYNOS_PAD_RET_MAUDIO_OPTION,
        EXYNOS_PAD_RET_JTAG_OPTION,
@@ -349,10 +347,6 @@ static void exynos_pm_prepare(void)
 
        s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save));
 
-        if (pm_data->extra_save)
-               s3c_pm_do_save(pm_data->extra_save,
-                               pm_data->num_extra_save);
-
        exynos_pm_enter_sleep_mode();
 
        /* ensure at least INFORM0 has the resume address */
@@ -475,10 +469,6 @@ static void exynos_pm_resume(void)
        /* For release retention */
        exynos_pm_release_retention();
 
-       if (pm_data->extra_save)
-               s3c_pm_do_restore_core(pm_data->extra_save,
-                                       pm_data->num_extra_save);
-
        s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));
 
        if (cpuid == ARM_CPU_PART_CORTEX_A9)
@@ -685,7 +675,7 @@ static const struct exynos_pm_data exynos5250_pm_data = {
        .cpu_suspend    = exynos_cpu_suspend,
 };
 
-static struct exynos_pm_data exynos5420_pm_data = {
+static const struct exynos_pm_data exynos5420_pm_data = {
        .wkup_irq       = exynos5250_wkup_irq,
        .wake_disable_mask = (0x7F << 7) | (0x1F << 1),
        .release_ret_regs = exynos5420_release_ret_regs,
@@ -736,7 +726,7 @@ void __init exynos_pm_init(void)
        if (WARN_ON(!of_find_property(np, "interrupt-controller", NULL)))
                pr_warn("Outdated DT detected, suspend/resume will NOT work\n");
 
-       pm_data = (struct exynos_pm_data *) match->data;
+       pm_data = (const struct exynos_pm_data *) match->data;
 
        /* All wakeup disable */
        tmp = pmu_raw_readl(S5P_WAKEUP_MASK);
index c8dffcee97363eec0cb898f73973088496a3b0c6..3a3d3e9d7bfd6eb7f781bfa904df5caede06a33c 100644 (file)
@@ -21,6 +21,7 @@ config MXC_AVIC
 
 config MXC_DEBUG_BOARD
        bool "Enable MXC debug board(for 3-stack)"
+       depends on MACH_MX27_3DS || MACH_MX31_3DS || MACH_MX35_3DS
        help
          The debug board is an integral part of the MXC 3-stack(PDK)
          platforms, it can be attached or removed from the peripheral
@@ -50,6 +51,7 @@ config HAVE_IMX_ANATOP
 
 config HAVE_IMX_GPC
        bool
+       select PM_GENERIC_DOMAINS if PM
 
 config HAVE_IMX_MMDC
        bool
@@ -77,13 +79,6 @@ config SOC_IMX21
        select IMX_HAVE_IOMUX_V1
        select MXC_AVIC
 
-config SOC_IMX25
-       bool
-       select ARCH_MXC_IOMUX_V3
-       select CPU_ARM926T
-       select MXC_AVIC
-       select PINCTRL_IMX25
-
 config SOC_IMX27
        bool
        select CPU_ARM926T
@@ -149,62 +144,6 @@ config MACH_MX21ADS
          Include support for MX21ADS platform. This includes specific
          configurations for the board and its peripherals.
 
-comment "MX25 platforms:"
-
-config MACH_MX25_3DS
-       bool "Support MX25PDK (3DS) Platform"
-       select IMX_HAVE_PLATFORM_FLEXCAN
-       select IMX_HAVE_PLATFORM_FSL_USB2_UDC
-       select IMX_HAVE_PLATFORM_IMX2_WDT
-       select IMX_HAVE_PLATFORM_IMXDI_RTC
-       select IMX_HAVE_PLATFORM_IMX_FB
-       select IMX_HAVE_PLATFORM_IMX_I2C
-       select IMX_HAVE_PLATFORM_IMX_KEYPAD
-       select IMX_HAVE_PLATFORM_IMX_UART
-       select IMX_HAVE_PLATFORM_MXC_EHCI
-       select IMX_HAVE_PLATFORM_MXC_NAND
-       select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
-       select SOC_IMX25
-
-config MACH_EUKREA_CPUIMX25SD
-       bool "Support Eukrea CPUIMX25 Platform"
-       select IMX_HAVE_PLATFORM_FLEXCAN
-       select IMX_HAVE_PLATFORM_FSL_USB2_UDC
-       select IMX_HAVE_PLATFORM_IMX2_WDT
-       select IMX_HAVE_PLATFORM_IMXDI_RTC
-       select IMX_HAVE_PLATFORM_IMX_FB
-       select IMX_HAVE_PLATFORM_IMX_I2C
-       select IMX_HAVE_PLATFORM_IMX_UART
-       select IMX_HAVE_PLATFORM_MXC_EHCI
-       select IMX_HAVE_PLATFORM_MXC_NAND
-       select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
-       select USB_ULPI_VIEWPORT if USB_ULPI
-       select SOC_IMX25
-
-choice
-       prompt "Baseboard"
-       depends on MACH_EUKREA_CPUIMX25SD
-       default MACH_EUKREA_MBIMXSD25_BASEBOARD
-
-config MACH_EUKREA_MBIMXSD25_BASEBOARD
-       bool "Eukrea MBIMXSD development board"
-       select IMX_HAVE_PLATFORM_GPIO_KEYS
-       select IMX_HAVE_PLATFORM_IMX_SSI
-       select IMX_HAVE_PLATFORM_SPI_IMX
-       select LEDS_GPIO_REGISTER
-       help
-         This adds board specific devices that can be found on Eukrea's
-         MBIMXSD evaluation board.
-
-endchoice
-
-config MACH_IMX25_DT
-       bool "Support i.MX25 platforms from device tree"
-       select SOC_IMX25
-       help
-         Include support for Freescale i.MX25 based platforms
-         using the device tree for discovery
-
 comment "MX27 platforms:"
 
 config MACH_MX27ADS
@@ -557,6 +496,20 @@ config MACH_VPR200
 
 endif
 
+if ARCH_MULTI_V5
+
+comment "Device tree only"
+
+config SOC_IMX25
+       bool "i.MX25 support"
+       select ARCH_MXC_IOMUX_V3
+       select CPU_ARM926T
+       select MXC_AVIC
+       select PINCTRL_IMX25
+       help
+         This enables support for Freescale i.MX25 processor
+endif
+
 if ARCH_MULTI_V7
 
 comment "Device tree only"
@@ -635,9 +588,10 @@ config SOC_VF610
        select ARM_GIC
        select PINCTRL_VF610
        select PL310_ERRATA_769419 if CACHE_L2X0
+       select SMP_ON_UP if SMP
 
        help
-         This enable support for Freescale Vybrid VF610 processor.
+         This enables support for Freescale Vybrid VF610 processor.
 
 choice
        prompt "Clocksource for scheduler clock"
@@ -667,7 +621,7 @@ config SOC_LS1021A
        select ZONE_DMA if ARM_LPAE
 
        help
-         This enable support for Freescale LS1021A processor.
+         This enables support for Freescale LS1021A processor.
 
 endif
 
index 8d1b1018090898d9d1698b6bb39825a99d540001..3244cf1d2773f1c20836b6b96e60f4d054aa67f0 100644 (file)
@@ -3,7 +3,7 @@ obj-y := time.o cpu.o system.o irq-common.o
 obj-$(CONFIG_SOC_IMX1) += clk-imx1.o mm-imx1.o
 obj-$(CONFIG_SOC_IMX21) += clk-imx21.o mm-imx21.o
 
-obj-$(CONFIG_SOC_IMX25) += clk-imx25.o mm-imx25.o ehci-imx25.o cpu-imx25.o
+obj-$(CONFIG_SOC_IMX25) += clk-imx25.o cpu-imx25.o mach-imx25.o
 
 obj-$(CONFIG_SOC_IMX27) += cpu-imx27.o pm-imx27.o
 obj-$(CONFIG_SOC_IMX27) += clk-imx27.o mm-imx27.o ehci-imx27.o
@@ -48,12 +48,6 @@ obj-$(CONFIG_MACH_IMX1_DT) += imx1-dt.o
 # i.MX21 based machines
 obj-$(CONFIG_MACH_MX21ADS) += mach-mx21ads.o
 
-# i.MX25 based machines
-obj-$(CONFIG_MACH_MX25_3DS) += mach-mx25_3ds.o
-obj-$(CONFIG_MACH_EUKREA_CPUIMX25SD) += mach-eukrea_cpuimx25.o
-obj-$(CONFIG_MACH_EUKREA_MBIMXSD25_BASEBOARD) += eukrea_mbimxsd25-baseboard.o
-obj-$(CONFIG_MACH_IMX25_DT) += imx25-dt.o
-
 # i.MX27 based machines
 obj-$(CONFIG_MACH_MX27ADS) += mach-mx27ads.o
 obj-$(CONFIG_MACH_MX27_3DS) += mach-mx27_3ds.o
index 59c0c8558c6bf5d5212c5e88083a55f859f01287..9c2633a9de9f0ec53dfdc20677eb709488b7824a 100644 (file)
@@ -30,7 +30,6 @@
 #include "clk.h"
 #include "common.h"
 #include "hardware.h"
-#include "mx25.h"
 
 #define CCM_MPCTL      0x00
 #define CCM_UPCTL      0x04
@@ -239,80 +238,6 @@ static int __init __mx25_clocks_init(unsigned long osc_rate,
        return 0;
 }
 
-int __init mx25_clocks_init(void)
-{
-       void __iomem *ccm;
-
-       ccm = ioremap(MX25_CRM_BASE_ADDR, SZ_16K);
-
-       __mx25_clocks_init(24000000, ccm);
-
-       clk_register_clkdev(clk[gpt1_ipg], "ipg", "imx-gpt.0");
-       clk_register_clkdev(clk[gpt_ipg_per], "per", "imx-gpt.0");
-       /* i.mx25 has the i.mx21 type uart */
-       clk_register_clkdev(clk[uart1_ipg], "ipg", "imx21-uart.0");
-       clk_register_clkdev(clk[uart_ipg_per], "per", "imx21-uart.0");
-       clk_register_clkdev(clk[uart2_ipg], "ipg", "imx21-uart.1");
-       clk_register_clkdev(clk[uart_ipg_per], "per", "imx21-uart.1");
-       clk_register_clkdev(clk[uart3_ipg], "ipg", "imx21-uart.2");
-       clk_register_clkdev(clk[uart_ipg_per], "per", "imx21-uart.2");
-       clk_register_clkdev(clk[uart4_ipg], "ipg", "imx21-uart.3");
-       clk_register_clkdev(clk[uart_ipg_per], "per", "imx21-uart.3");
-       clk_register_clkdev(clk[uart5_ipg], "ipg", "imx21-uart.4");
-       clk_register_clkdev(clk[uart_ipg_per], "per", "imx21-uart.4");
-       clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.0");
-       clk_register_clkdev(clk[usbotg_ahb], "ahb", "mxc-ehci.0");
-       clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.0");
-       clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.1");
-       clk_register_clkdev(clk[usbotg_ahb], "ahb", "mxc-ehci.1");
-       clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.1");
-       clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.2");
-       clk_register_clkdev(clk[usbotg_ahb], "ahb", "mxc-ehci.2");
-       clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.2");
-       clk_register_clkdev(clk[ipg], "ipg", "imx-udc-mx27");
-       clk_register_clkdev(clk[usbotg_ahb], "ahb", "imx-udc-mx27");
-       clk_register_clkdev(clk[usb_div], "per", "imx-udc-mx27");
-       clk_register_clkdev(clk[nfc_ipg_per], NULL, "imx25-nand.0");
-       /* i.mx25 has the i.mx35 type cspi */
-       clk_register_clkdev(clk[cspi1_ipg], NULL, "imx35-cspi.0");
-       clk_register_clkdev(clk[cspi2_ipg], NULL, "imx35-cspi.1");
-       clk_register_clkdev(clk[cspi3_ipg], NULL, "imx35-cspi.2");
-       clk_register_clkdev(clk[kpp_ipg], NULL, "imx-keypad");
-       clk_register_clkdev(clk[tsc_ipg], NULL, "mx25-adc");
-       clk_register_clkdev(clk[i2c_ipg_per], NULL, "imx21-i2c.0");
-       clk_register_clkdev(clk[i2c_ipg_per], NULL, "imx21-i2c.1");
-       clk_register_clkdev(clk[i2c_ipg_per], NULL, "imx21-i2c.2");
-       clk_register_clkdev(clk[fec_ipg], "ipg", "imx25-fec.0");
-       clk_register_clkdev(clk[fec_ahb], "ahb", "imx25-fec.0");
-       clk_register_clkdev(clk[dryice_ipg], NULL, "imxdi_rtc.0");
-       clk_register_clkdev(clk[lcdc_ipg_per], "per", "imx21-fb.0");
-       clk_register_clkdev(clk[lcdc_ipg], "ipg", "imx21-fb.0");
-       clk_register_clkdev(clk[lcdc_ahb], "ahb", "imx21-fb.0");
-       clk_register_clkdev(clk[wdt_ipg], NULL, "imx2-wdt.0");
-       clk_register_clkdev(clk[ssi1_ipg], NULL, "imx-ssi.0");
-       clk_register_clkdev(clk[ssi2_ipg], NULL, "imx-ssi.1");
-       clk_register_clkdev(clk[esdhc1_ipg_per], "per", "sdhci-esdhc-imx25.0");
-       clk_register_clkdev(clk[esdhc1_ipg], "ipg", "sdhci-esdhc-imx25.0");
-       clk_register_clkdev(clk[esdhc1_ahb], "ahb", "sdhci-esdhc-imx25.0");
-       clk_register_clkdev(clk[esdhc2_ipg_per], "per", "sdhci-esdhc-imx25.1");
-       clk_register_clkdev(clk[esdhc2_ipg], "ipg", "sdhci-esdhc-imx25.1");
-       clk_register_clkdev(clk[esdhc2_ahb], "ahb", "sdhci-esdhc-imx25.1");
-       clk_register_clkdev(clk[csi_ipg_per], "per", "imx25-camera.0");
-       clk_register_clkdev(clk[csi_ipg], "ipg", "imx25-camera.0");
-       clk_register_clkdev(clk[csi_ahb], "ahb", "imx25-camera.0");
-       clk_register_clkdev(clk[dummy], "audmux", NULL);
-       clk_register_clkdev(clk[can1_ipg], NULL, "flexcan.0");
-       clk_register_clkdev(clk[can2_ipg], NULL, "flexcan.1");
-       /* i.mx25 has the i.mx35 type sdma */
-       clk_register_clkdev(clk[sdma_ipg], "ipg", "imx35-sdma");
-       clk_register_clkdev(clk[sdma_ahb], "ahb", "imx35-sdma");
-       clk_register_clkdev(clk[iim_ipg], "iim", NULL);
-
-       mxc_timer_init(MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), MX25_INT_GPT1);
-
-       return 0;
-}
-
 static void __init mx25_clocks_init_dt(struct device_node *np)
 {
        struct device_node *refnp;
index d04a430607b8af66ef71ba3f01ff8e151738eeb1..469a150bf98f98cbb5521343e81d531c7fc34e91 100644 (file)
@@ -119,6 +119,7 @@ static unsigned int share_count_asrc;
 static unsigned int share_count_ssi1;
 static unsigned int share_count_ssi2;
 static unsigned int share_count_ssi3;
+static unsigned int share_count_mipi_core_cfg;
 
 static void __init imx6q_clocks_init(struct device_node *ccm_node)
 {
@@ -246,6 +247,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
        clk[IMX6QDL_CLK_PLL3_60M]  = imx_clk_fixed_factor("pll3_60m",  "pll3_usb_otg",   1, 8);
        clk[IMX6QDL_CLK_TWD]       = imx_clk_fixed_factor("twd",       "arm",            1, 2);
        clk[IMX6QDL_CLK_GPT_3M]    = imx_clk_fixed_factor("gpt_3m",    "osc",            1, 8);
+       clk[IMX6QDL_CLK_VIDEO_27M] = imx_clk_fixed_factor("video_27m", "pll3_pfd1_540m", 1, 20);
        if (cpu_is_imx6dl()) {
                clk[IMX6QDL_CLK_GPU2D_AXI] = imx_clk_fixed_factor("gpu2d_axi", "mmdc_ch0_axi_podf", 1, 1);
                clk[IMX6QDL_CLK_GPU3D_AXI] = imx_clk_fixed_factor("gpu3d_axi", "mmdc_ch0_axi_podf", 1, 1);
@@ -400,7 +402,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
                clk[IMX6QDL_CLK_GPU2D_CORE] = imx_clk_gate2("gpu2d_core", "gpu2d_core_podf", base + 0x6c, 24);
        clk[IMX6QDL_CLK_GPU3D_CORE]   = imx_clk_gate2("gpu3d_core",    "gpu3d_core_podf",   base + 0x6c, 26);
        clk[IMX6QDL_CLK_HDMI_IAHB]    = imx_clk_gate2("hdmi_iahb",     "ahb",               base + 0x70, 0);
-       clk[IMX6QDL_CLK_HDMI_ISFR]    = imx_clk_gate2("hdmi_isfr",     "pll3_pfd1_540m",    base + 0x70, 4);
+       clk[IMX6QDL_CLK_HDMI_ISFR]    = imx_clk_gate2("hdmi_isfr",     "video_27m",         base + 0x70, 4);
        clk[IMX6QDL_CLK_I2C1]         = imx_clk_gate2("i2c1",          "ipg_per",           base + 0x70, 6);
        clk[IMX6QDL_CLK_I2C2]         = imx_clk_gate2("i2c2",          "ipg_per",           base + 0x70, 8);
        clk[IMX6QDL_CLK_I2C3]         = imx_clk_gate2("i2c3",          "ipg_per",           base + 0x70, 10);
@@ -415,7 +417,9 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
        clk[IMX6QDL_CLK_LDB_DI0]      = imx_clk_gate2("ldb_di0",       "ldb_di0_podf",      base + 0x74, 12);
        clk[IMX6QDL_CLK_LDB_DI1]      = imx_clk_gate2("ldb_di1",       "ldb_di1_podf",      base + 0x74, 14);
        clk[IMX6QDL_CLK_IPU2_DI1]     = imx_clk_gate2("ipu2_di1",      "ipu2_di1_sel",      base + 0x74, 10);
-       clk[IMX6QDL_CLK_HSI_TX]       = imx_clk_gate2("hsi_tx",        "hsi_tx_podf",       base + 0x74, 16);
+       clk[IMX6QDL_CLK_HSI_TX]       = imx_clk_gate2_shared("hsi_tx", "hsi_tx_podf",       base + 0x74, 16, &share_count_mipi_core_cfg);
+       clk[IMX6QDL_CLK_MIPI_CORE_CFG] = imx_clk_gate2_shared("mipi_core_cfg", "video_27m", base + 0x74, 16, &share_count_mipi_core_cfg);
+       clk[IMX6QDL_CLK_MIPI_IPG]     = imx_clk_gate2_shared("mipi_ipg", "ipg",             base + 0x74, 16, &share_count_mipi_core_cfg);
        if (cpu_is_imx6dl())
                /*
                 * The multiplexer and divider of the imx6q clock gpu2d get
index 1028b6c505c496b315b90c65911e1cda403ac4fe..0f04e30b726d22e43ad725427bf2731295a705e7 100644 (file)
@@ -23,13 +23,11 @@ struct of_device_id;
 
 void mx1_map_io(void);
 void mx21_map_io(void);
-void mx25_map_io(void);
 void mx27_map_io(void);
 void mx31_map_io(void);
 void mx35_map_io(void);
 void imx1_init_early(void);
 void imx21_init_early(void);
-void imx25_init_early(void);
 void imx27_init_early(void);
 void imx31_init_early(void);
 void imx35_init_early(void);
@@ -37,13 +35,11 @@ void mxc_init_irq(void __iomem *);
 void tzic_init_irq(void);
 void mx1_init_irq(void);
 void mx21_init_irq(void);
-void mx25_init_irq(void);
 void mx27_init_irq(void);
 void mx31_init_irq(void);
 void mx35_init_irq(void);
 void imx1_soc_init(void);
 void imx21_soc_init(void);
-void imx25_soc_init(void);
 void imx27_soc_init(void);
 void imx31_soc_init(void);
 void imx35_soc_init(void);
@@ -51,7 +47,6 @@ void epit_timer_init(void __iomem *base, int irq);
 void mxc_timer_init(void __iomem *, int);
 int mx1_clocks_init(unsigned long fref);
 int mx21_clocks_init(unsigned long lref, unsigned long fref);
-int mx25_clocks_init(void);
 int mx27_clocks_init(unsigned long fref);
 int mx31_clocks_init(unsigned long fref);
 int mx35_clocks_init(void);
@@ -71,6 +66,7 @@ unsigned int imx_get_soc_revision(void);
 void imx_init_revision_from_anatop(void);
 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_arm_power_up_timing(u32 sw2iso, u32 sw);
 void imx_gpc_set_arm_power_down_timing(u32 sw2iso, u32 sw);
@@ -106,7 +102,6 @@ static inline void imx_scu_map_io(void) {}
 static inline void imx_smp_prepare(void) {}
 #endif
 void imx_src_init(void);
-void imx_gpc_init(void);
 void imx_gpc_pre_suspend(bool arm_power_off);
 void imx_gpc_post_resume(void);
 void imx_gpc_mask_all(void);
index 96ec64b5ff7d3e056ddfdea0f3918278732ea0c1..d0ad67e802d33962c1f10f9bfabe9e3b01c7c903 100644 (file)
@@ -11,6 +11,8 @@
  */
 #include <linux/module.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
 
 #include "iim.h"
 #include "hardware.h"
@@ -20,8 +22,15 @@ static int mx25_cpu_rev = -1;
 static int mx25_read_cpu_rev(void)
 {
        u32 rev;
+       void __iomem *iim_base;
+       struct device_node *np;
+
+       np = of_find_compatible_node(NULL, NULL, "fsl,imx25-iim");
+       iim_base = of_iomap(np, 0);
+       BUG_ON(!iim_base);
+       rev = readl(iim_base + MXC_IIMSREV);
+       iounmap(iim_base);
 
-       rev = __raw_readl(MX25_IO_ADDRESS(MX25_IIM_BASE_ADDR + MXC_IIMSREV));
        switch (rev) {
        case 0x00:
                return IMX_CHIP_REVISION_1_0;
diff --git a/arch/arm/mach-imx/devices-imx25.h b/arch/arm/mach-imx/devices-imx25.h
deleted file mode 100644 (file)
index 61a114c..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include "devices/devices-common.h"
-
-extern const struct imx_fec_data imx25_fec_data;
-#define imx25_add_fec(pdata)   \
-       imx_add_fec(&imx25_fec_data, pdata)
-
-extern const struct imx_flexcan_data imx25_flexcan_data[];
-#define imx25_add_flexcan(id)  \
-       imx_add_flexcan(&imx25_flexcan_data[id])
-#define imx25_add_flexcan0()           imx25_add_flexcan(0)
-#define imx25_add_flexcan1()           imx25_add_flexcan(1)
-
-extern const struct imx_fsl_usb2_udc_data imx25_fsl_usb2_udc_data;
-#define imx25_add_fsl_usb2_udc(pdata)  \
-       imx_add_fsl_usb2_udc(&imx25_fsl_usb2_udc_data, pdata)
-
-extern struct imx_imxdi_rtc_data imx25_imxdi_rtc_data;
-#define imx25_add_imxdi_rtc()  \
-       imx_add_imxdi_rtc(&imx25_imxdi_rtc_data)
-
-extern const struct imx_imx2_wdt_data imx25_imx2_wdt_data;
-#define imx25_add_imx2_wdt()   \
-       imx_add_imx2_wdt(&imx25_imx2_wdt_data)
-
-extern const struct imx_imx_fb_data imx25_imx_fb_data;
-#define imx25_add_imx_fb(pdata)        \
-       imx_add_imx_fb(&imx25_imx_fb_data, pdata)
-
-extern const struct imx_imx_i2c_data imx25_imx_i2c_data[];
-#define imx25_add_imx_i2c(id, pdata)   \
-       imx_add_imx_i2c(&imx25_imx_i2c_data[id], pdata)
-#define imx25_add_imx_i2c0(pdata)      imx25_add_imx_i2c(0, pdata)
-#define imx25_add_imx_i2c1(pdata)      imx25_add_imx_i2c(1, pdata)
-#define imx25_add_imx_i2c2(pdata)      imx25_add_imx_i2c(2, pdata)
-
-extern const struct imx_imx_keypad_data imx25_imx_keypad_data;
-#define imx25_add_imx_keypad(pdata)    \
-       imx_add_imx_keypad(&imx25_imx_keypad_data, pdata)
-
-extern const struct imx_imx_ssi_data imx25_imx_ssi_data[];
-#define imx25_add_imx_ssi(id, pdata)   \
-       imx_add_imx_ssi(&imx25_imx_ssi_data[id], pdata)
-
-extern const struct imx_imx_uart_1irq_data imx25_imx_uart_data[];
-#define imx25_add_imx_uart(id, pdata)  \
-       imx_add_imx_uart_1irq(&imx25_imx_uart_data[id], pdata)
-#define imx25_add_imx_uart0(pdata)     imx25_add_imx_uart(0, pdata)
-#define imx25_add_imx_uart1(pdata)     imx25_add_imx_uart(1, pdata)
-#define imx25_add_imx_uart2(pdata)     imx25_add_imx_uart(2, pdata)
-#define imx25_add_imx_uart3(pdata)     imx25_add_imx_uart(3, pdata)
-#define imx25_add_imx_uart4(pdata)     imx25_add_imx_uart(4, pdata)
-
-extern const struct imx_mx2_camera_data imx25_mx2_camera_data;
-#define imx25_add_mx2_camera(pdata)    \
-       imx_add_mx2_camera(&imx25_mx2_camera_data, pdata)
-
-extern const struct imx_mxc_ehci_data imx25_mxc_ehci_otg_data;
-#define imx25_add_mxc_ehci_otg(pdata)  \
-       imx_add_mxc_ehci(&imx25_mxc_ehci_otg_data, pdata)
-extern const struct imx_mxc_ehci_data imx25_mxc_ehci_hs_data;
-#define imx25_add_mxc_ehci_hs(pdata)   \
-       imx_add_mxc_ehci(&imx25_mxc_ehci_hs_data, pdata)
-
-extern const struct imx_mxc_nand_data imx25_mxc_nand_data;
-#define imx25_add_mxc_nand(pdata)      \
-       imx_add_mxc_nand(&imx25_mxc_nand_data, pdata)
-
-extern const struct imx_sdhci_esdhc_imx_data imx25_sdhci_esdhc_imx_data[];
-#define imx25_add_sdhci_esdhc_imx(id, pdata)   \
-       imx_add_sdhci_esdhc_imx(&imx25_sdhci_esdhc_imx_data[id], pdata)
-
-extern const struct imx_spi_imx_data imx25_cspi_data[];
-#define imx25_add_spi_imx(id, pdata)   \
-       imx_add_spi_imx(&imx25_cspi_data[id], pdata)
-#define imx25_add_spi_imx0(pdata)      imx25_add_spi_imx(0, pdata)
-#define imx25_add_spi_imx1(pdata)      imx25_add_spi_imx(1, pdata)
-#define imx25_add_spi_imx2(pdata)      imx25_add_spi_imx(2, pdata)
index 1d2cc1805f3e51d00f4f7db8d0e3f1cad318a0f0..3a552989248ed309020a0c159480f8c569f71dc9 100644 (file)
@@ -21,9 +21,6 @@ config IMX_HAVE_PLATFORM_IMX27_CODA
 config IMX_HAVE_PLATFORM_IMX2_WDT
        bool
 
-config IMX_HAVE_PLATFORM_IMXDI_RTC
-       bool
-
 config IMX_HAVE_PLATFORM_IMX_FB
        bool
 
index 8fdb12b4ca7ee12d12b9798e66d60c3dbac998fe..e5cf587bc1a0ed346ec128e3ff7cff3f990a477d 100644 (file)
@@ -8,7 +8,6 @@ obj-y += platform-gpio-mxc.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX21_HCD) += platform-imx21-hcd.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX27_CODA) += platform-imx27-coda.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX2_WDT) += platform-imx2-wdt.o
-obj-$(CONFIG_IMX_HAVE_PLATFORM_IMXDI_RTC) += platform-imxdi_rtc.o
 obj-y += platform-imx-dma.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_FB) += platform-imx-fb.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_I2C) += platform-imx-i2c.o
index d86f9250b4ee87292ce8758a4538cd64a8b4ac92..b403a4fe2892b3773f3b92ea6f8520b077269588 100644 (file)
                .irq = soc ## _INT_FEC,                                 \
        }
 
-#ifdef CONFIG_SOC_IMX25
-const struct imx_fec_data imx25_fec_data __initconst =
-       imx_fec_data_entry_single(MX25, "imx25-fec");
-#endif /* ifdef CONFIG_SOC_IMX25 */
-
 #ifdef CONFIG_SOC_IMX27
 const struct imx_fec_data imx27_fec_data __initconst =
        imx_fec_data_entry_single(MX27, "imx27-fec");
index 23b0061347cba81f5fd8c63add9d8d57b7585d82..25e1de6f3a47fd5ebca7f7c0164e7706b4bece8c 100644 (file)
                .irq = soc ## _INT_USB_OTG,                             \
        }
 
-#ifdef CONFIG_SOC_IMX25
-const struct imx_fsl_usb2_udc_data imx25_fsl_usb2_udc_data __initconst =
-       imx_fsl_usb2_udc_data_entry_single(MX25, "imx-udc-mx27");
-#endif /* ifdef CONFIG_SOC_IMX25 */
-
 #ifdef CONFIG_SOC_IMX27
 const struct imx_fsl_usb2_udc_data imx27_fsl_usb2_udc_data __initconst =
        imx_fsl_usb2_udc_data_entry_single(MX27, "imx-udc-mx27");
index 25a47c616b2d7c2b855eaf510b84b4d466b51d62..7df6328306f964dcf5c698f30c2bf4aeabb757f1 100644 (file)
@@ -29,11 +29,6 @@ const struct imx_imx_fb_data imx21_imx_fb_data __initconst =
        imx_imx_fb_data_entry_single(MX21, "imx21-fb", SZ_4K);
 #endif /* ifdef CONFIG_SOC_IMX21 */
 
-#ifdef CONFIG_SOC_IMX25
-const struct imx_imx_fb_data imx25_imx_fb_data __initconst =
-       imx_imx_fb_data_entry_single(MX25, "imx21-fb", SZ_16K);
-#endif /* ifdef CONFIG_SOC_IMX25 */
-
 #ifdef CONFIG_SOC_IMX27
 const struct imx_imx_fb_data imx27_imx_fb_data __initconst =
        imx_imx_fb_data_entry_single(MX27, "imx21-fb", SZ_4K);
index 644ac26898823ac617c5892a5c41571af254cf00..ae9791522fc80e70ac8df2dcd2791f8a3f341a6a 100644 (file)
@@ -31,16 +31,6 @@ const struct imx_imx_i2c_data imx21_imx_i2c_data __initconst =
        imx_imx_i2c_data_entry_single(MX21, "imx21-i2c", 0, , SZ_4K);
 #endif /* ifdef CONFIG_SOC_IMX21 */
 
-#ifdef CONFIG_SOC_IMX25
-const struct imx_imx_i2c_data imx25_imx_i2c_data[] __initconst = {
-#define imx25_imx_i2c_data_entry(_id, _hwid)                           \
-       imx_imx_i2c_data_entry(MX25, "imx21-i2c", _id, _hwid, SZ_16K)
-       imx25_imx_i2c_data_entry(0, 1),
-       imx25_imx_i2c_data_entry(1, 2),
-       imx25_imx_i2c_data_entry(2, 3),
-};
-#endif /* ifdef CONFIG_SOC_IMX25 */
-
 #ifdef CONFIG_SOC_IMX27
 const struct imx_imx_i2c_data imx27_imx_i2c_data[] __initconst = {
 #define imx27_imx_i2c_data_entry(_id, _hwid)                           \
index f42200b7aca96044b8d10dbedb10cfe680ab5a80..479e4d70dbf92c43812124f72add5cd6d87d21c0 100644 (file)
@@ -21,11 +21,6 @@ const struct imx_imx_keypad_data imx21_imx_keypad_data __initconst =
        imx_imx_keypad_data_entry_single(MX21, SZ_16);
 #endif /* ifdef CONFIG_SOC_IMX21 */
 
-#ifdef CONFIG_SOC_IMX25
-const struct imx_imx_keypad_data imx25_imx_keypad_data __initconst =
-       imx_imx_keypad_data_entry_single(MX25, SZ_16K);
-#endif /* ifdef CONFIG_SOC_IMX25 */
-
 #ifdef CONFIG_SOC_IMX27
 const struct imx_imx_keypad_data imx27_imx_keypad_data __initconst =
        imx_imx_keypad_data_entry_single(MX27, SZ_16);
index 1c7c721ebff1ba04ef2f73e1025aace0758769c1..6f0e94eb29eeec2c549a0110beb3234357e9c08d 100644 (file)
@@ -30,15 +30,6 @@ const struct imx_imx_ssi_data imx21_imx_ssi_data[] __initconst = {
 };
 #endif /* ifdef CONFIG_SOC_IMX21 */
 
-#ifdef CONFIG_SOC_IMX25
-const struct imx_imx_ssi_data imx25_imx_ssi_data[] __initconst = {
-#define imx25_imx_ssi_data_entry(_id, _hwid)                           \
-       imx_imx_ssi_data_entry(MX25, _id, _hwid, SZ_4K)
-       imx25_imx_ssi_data_entry(0, 1),
-       imx25_imx_ssi_data_entry(1, 2),
-};
-#endif /* ifdef CONFIG_SOC_IMX25 */
-
 #ifdef CONFIG_SOC_IMX27
 const struct imx_imx_ssi_data imx27_imx_ssi_data[] __initconst = {
 #define imx27_imx_ssi_data_entry(_id, _hwid)                           \
index 8c01836bc1d4b03c8df84a28cda9cc433d9a825c..6962cff4a9504569cc333b6e538bdbc54dfa1a36 100644 (file)
@@ -47,18 +47,6 @@ const struct imx_imx_uart_1irq_data imx21_imx_uart_data[] __initconst = {
 };
 #endif
 
-#ifdef CONFIG_SOC_IMX25
-const struct imx_imx_uart_1irq_data imx25_imx_uart_data[] __initconst = {
-#define imx25_imx_uart_data_entry(_id, _hwid)                          \
-       imx_imx_uart_1irq_data_entry(MX25, _id, _hwid, SZ_16K)
-       imx25_imx_uart_data_entry(0, 1),
-       imx25_imx_uart_data_entry(1, 2),
-       imx25_imx_uart_data_entry(2, 3),
-       imx25_imx_uart_data_entry(3, 4),
-       imx25_imx_uart_data_entry(4, 5),
-};
-#endif /* ifdef CONFIG_SOC_IMX25 */
-
 #ifdef CONFIG_SOC_IMX27
 const struct imx_imx_uart_1irq_data imx27_imx_uart_data[] __initconst = {
 #define imx27_imx_uart_data_entry(_id, _hwid)                          \
index 54f63bc25ca4d1e7974668577324ef2b61285a07..8c134c8d7500349f1040cca3fcad40ea851a1bcd 100644 (file)
@@ -25,11 +25,6 @@ const struct imx_imx2_wdt_data imx21_imx2_wdt_data __initconst =
        imx_imx2_wdt_data_entry_single(MX21, 0, , SZ_4K);
 #endif /* ifdef CONFIG_SOC_IMX21 */
 
-#ifdef CONFIG_SOC_IMX25
-const struct imx_imx2_wdt_data imx25_imx2_wdt_data __initconst =
-       imx_imx2_wdt_data_entry_single(MX25, 0, , SZ_16K);
-#endif /* ifdef CONFIG_SOC_IMX25 */
-
 #ifdef CONFIG_SOC_IMX27
 const struct imx_imx2_wdt_data imx27_imx2_wdt_data __initconst =
        imx_imx2_wdt_data_entry_single(MX27, 0, , SZ_4K);
diff --git a/arch/arm/mach-imx/devices/platform-imxdi_rtc.c b/arch/arm/mach-imx/devices/platform-imxdi_rtc.c
deleted file mode 100644 (file)
index 5bb490d..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <asm/sizes.h>
-
-#include "../hardware.h"
-#include "devices-common.h"
-
-#define imx_imxdi_rtc_data_entry_single(soc)                           \
-       {                                                               \
-               .iobase = soc ## _DRYICE_BASE_ADDR,                     \
-               .irq = soc ## _INT_DRYICE,                              \
-       }
-
-#ifdef CONFIG_SOC_IMX25
-const struct imx_imxdi_rtc_data imx25_imxdi_rtc_data __initconst =
-       imx_imxdi_rtc_data_entry_single(MX25);
-#endif /* ifdef CONFIG_SOC_IMX25 */
-
-struct platform_device *__init imx_add_imxdi_rtc(
-               const struct imx_imxdi_rtc_data *data)
-{
-       struct resource res[] = {
-               {
-                       .start = data->iobase,
-                       .end = data->iobase + SZ_16K - 1,
-                       .flags = IORESOURCE_MEM,
-               }, {
-                       .start = data->irq,
-                       .end = data->irq,
-                       .flags = IORESOURCE_IRQ,
-               },
-       };
-
-       return imx_add_platform_device("imxdi_rtc", 0,
-                       res, ARRAY_SIZE(res), NULL, 0);
-}
index b53e1f348f518f5de7ec9aa8745a7299d5c26df4..4c377c33242c75b31bfe8849a5662cb770486223 100644 (file)
                .irqemmaprp = soc ## _INT_EMMAPRP,                      \
        }
 
-#ifdef CONFIG_SOC_IMX25
-const struct imx_mx2_camera_data imx25_mx2_camera_data __initconst =
-       imx_mx2_camera_data_entry_single(MX25, "imx25-camera");
-#endif /* ifdef CONFIG_SOC_IMX25 */
-
 #ifdef CONFIG_SOC_IMX27
 const struct imx_mx2_camera_data imx27_mx2_camera_data __initconst =
        imx_mx2_camera_data_entry_single_emma(MX27, "imx27-camera");
index 296353662ff025dac519c7cffbb112f601dc007f..4537abd2a8f23df0d8323165473f65aca6258015 100644 (file)
                .irq = soc ## _INT_USB_ ## hs,                          \
        }
 
-#ifdef CONFIG_SOC_IMX25
-const struct imx_mxc_ehci_data imx25_mxc_ehci_otg_data __initconst =
-       imx_mxc_ehci_data_entry_single(MX25, 0, OTG);
-const struct imx_mxc_ehci_data imx25_mxc_ehci_hs_data __initconst =
-       imx_mxc_ehci_data_entry_single(MX25, 1, HS);
-#endif /* ifdef CONFIG_SOC_IMX25 */
-
 #ifdef CONFIG_SOC_IMX27
 const struct imx_mxc_ehci_data imx27_mxc_ehci_otg_data __initconst =
        imx_mxc_ehci_data_entry_single(MX27, 0, OTG);
index fa618a34f4625f6df8a5759116434fcd682eda18..676df4920c7b6d6e06a7e86309c5d1455a3c1648 100644 (file)
@@ -34,11 +34,6 @@ const struct imx_mxc_nand_data imx21_mxc_nand_data __initconst =
        imx_mxc_nand_data_entry_single(MX21, "imx21-nand", SZ_4K);
 #endif /* ifdef CONFIG_SOC_IMX21 */
 
-#ifdef CONFIG_SOC_IMX25
-const struct imx_mxc_nand_data imx25_mxc_nand_data __initconst =
-       imx_mxc_nand_data_entry_single(MX25, "imx25-nand", SZ_8K);
-#endif /* ifdef CONFIG_SOC_IMX25 */
-
 #ifdef CONFIG_SOC_IMX27
 const struct imx_mxc_nand_data imx27_mxc_nand_data __initconst =
        imx_mxc_nand_data_entry_single(MX27, "imx27-nand", SZ_4K);
index aca825d74c48761dabcecc6f54467520036bc698..5e9707b47f92925078200bdd363982617ece4996 100644 (file)
@@ -39,17 +39,6 @@ const struct imx_spi_imx_data imx21_cspi_data[] __initconst = {
 };
 #endif
 
-#ifdef CONFIG_SOC_IMX25
-/* i.mx25 has the i.mx35 type cspi */
-const struct imx_spi_imx_data imx25_cspi_data[] __initconst = {
-#define imx25_cspi_data_entry(_id, _hwid)                              \
-       imx_spi_imx_data_entry(MX25, CSPI, "imx35-cspi", _id, _hwid, SZ_16K)
-       imx25_cspi_data_entry(0, 1),
-       imx25_cspi_data_entry(1, 2),
-       imx25_cspi_data_entry(2, 3),
-};
-#endif /* ifdef CONFIG_SOC_IMX25 */
-
 #ifdef CONFIG_SOC_IMX27
 const struct imx_spi_imx_data imx27_cspi_data[] __initconst = {
 #define imx27_cspi_data_entry(_id, _hwid)                              \
diff --git a/arch/arm/mach-imx/ehci-imx25.c b/arch/arm/mach-imx/ehci-imx25.c
deleted file mode 100644 (file)
index 42a5a3d..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
- * Copyright (C) 2010 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/platform_data/usb-ehci-mxc.h>
-
-#include "ehci.h"
-#include "hardware.h"
-
-#define USBCTRL_OTGBASE_OFFSET 0x600
-
-#define MX25_OTG_SIC_SHIFT     29
-#define MX25_OTG_SIC_MASK      (0x3 << MX25_OTG_SIC_SHIFT)
-#define MX25_OTG_PM_BIT                (1 << 24)
-#define MX25_OTG_PP_BIT                (1 << 11)
-#define MX25_OTG_OCPOL_BIT     (1 << 3)
-
-#define MX25_H1_SIC_SHIFT      21
-#define MX25_H1_SIC_MASK       (0x3 << MX25_H1_SIC_SHIFT)
-#define MX25_H1_PP_BIT         (1 << 18)
-#define MX25_H1_PM_BIT         (1 << 16)
-#define MX25_H1_IPPUE_UP_BIT   (1 << 7)
-#define MX25_H1_IPPUE_DOWN_BIT (1 << 6)
-#define MX25_H1_TLL_BIT                (1 << 5)
-#define MX25_H1_USBTE_BIT      (1 << 4)
-#define MX25_H1_OCPOL_BIT      (1 << 2)
-
-int mx25_initialize_usb_hw(int port, unsigned int flags)
-{
-       unsigned int v;
-
-       v = readl(MX25_IO_ADDRESS(MX25_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET));
-
-       switch (port) {
-       case 0: /* OTG port */
-               v &= ~(MX25_OTG_SIC_MASK | MX25_OTG_PM_BIT | MX25_OTG_PP_BIT |
-                       MX25_OTG_OCPOL_BIT);
-               v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX25_OTG_SIC_SHIFT;
-
-               if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-                       v |= MX25_OTG_PM_BIT;
-
-               if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH)
-                       v |= MX25_OTG_PP_BIT;
-
-               if (!(flags & MXC_EHCI_OC_PIN_ACTIVE_LOW))
-                       v |= MX25_OTG_OCPOL_BIT;
-
-               break;
-       case 1: /* H1 port */
-               v &= ~(MX25_H1_SIC_MASK | MX25_H1_PM_BIT | MX25_H1_PP_BIT |
-                       MX25_H1_OCPOL_BIT | MX25_H1_TLL_BIT | MX25_H1_USBTE_BIT |
-                       MX25_H1_IPPUE_DOWN_BIT | MX25_H1_IPPUE_UP_BIT);
-               v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX25_H1_SIC_SHIFT;
-
-               if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-                       v |= MX25_H1_PM_BIT;
-
-               if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH)
-                       v |= MX25_H1_PP_BIT;
-
-               if (!(flags & MXC_EHCI_OC_PIN_ACTIVE_LOW))
-                       v |= MX25_H1_OCPOL_BIT;
-
-               if (!(flags & MXC_EHCI_TTL_ENABLED))
-                       v |= MX25_H1_TLL_BIT;
-
-               if (flags & MXC_EHCI_INTERNAL_PHY)
-                       v |= MX25_H1_USBTE_BIT;
-
-               if (flags & MXC_EHCI_IPPUE_DOWN)
-                       v |= MX25_H1_IPPUE_DOWN_BIT;
-
-               if (flags & MXC_EHCI_IPPUE_UP)
-                       v |= MX25_H1_IPPUE_UP_BIT;
-
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       writel(v, MX25_IO_ADDRESS(MX25_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET));
-
-       return 0;
-}
-
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
deleted file mode 100644 (file)
index e77cc3a..0000000
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * Copyright (C) 2010 Eric Benard - eric@eukrea.com
- *
- * Based on pcm970-baseboard.c which is :
- * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include <linux/gpio.h>
-#include <linux/leds.h>
-#include <linux/platform_device.h>
-#include <linux/input.h>
-#include <linux/spi/spi.h>
-#include <video/platform_lcd.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-#include "common.h"
-#include "devices-imx25.h"
-#include "hardware.h"
-#include "iomux-mx25.h"
-#include "mx25.h"
-
-static iomux_v3_cfg_t eukrea_mbimxsd_pads[] = {
-       /* LCD */
-       MX25_PAD_LD0__LD0,
-       MX25_PAD_LD1__LD1,
-       MX25_PAD_LD2__LD2,
-       MX25_PAD_LD3__LD3,
-       MX25_PAD_LD4__LD4,
-       MX25_PAD_LD5__LD5,
-       MX25_PAD_LD6__LD6,
-       MX25_PAD_LD7__LD7,
-       MX25_PAD_LD8__LD8,
-       MX25_PAD_LD9__LD9,
-       MX25_PAD_LD10__LD10,
-       MX25_PAD_LD11__LD11,
-       MX25_PAD_LD12__LD12,
-       MX25_PAD_LD13__LD13,
-       MX25_PAD_LD14__LD14,
-       MX25_PAD_LD15__LD15,
-       MX25_PAD_GPIO_E__LD16,
-       MX25_PAD_GPIO_F__LD17,
-       MX25_PAD_HSYNC__HSYNC,
-       MX25_PAD_VSYNC__VSYNC,
-       MX25_PAD_LSCLK__LSCLK,
-       MX25_PAD_OE_ACD__OE_ACD,
-       MX25_PAD_CONTRAST__CONTRAST,
-       /* LCD_PWR */
-       MX25_PAD_PWM__GPIO_1_26,
-       /* LED */
-       MX25_PAD_POWER_FAIL__GPIO_3_19,
-       /* SWITCH */
-       MX25_PAD_VSTBY_ACK__GPIO_3_18,
-       /* UART2 */
-       MX25_PAD_UART2_RTS__UART2_RTS,
-       MX25_PAD_UART2_CTS__UART2_CTS,
-       MX25_PAD_UART2_TXD__UART2_TXD,
-       MX25_PAD_UART2_RXD__UART2_RXD,
-       /* SD1 */
-       MX25_PAD_SD1_CMD__SD1_CMD,
-       MX25_PAD_SD1_CLK__SD1_CLK,
-       MX25_PAD_SD1_DATA0__SD1_DATA0,
-       MX25_PAD_SD1_DATA1__SD1_DATA1,
-       MX25_PAD_SD1_DATA2__SD1_DATA2,
-       MX25_PAD_SD1_DATA3__SD1_DATA3,
-       /* SD1 CD */
-       MX25_PAD_DE_B__GPIO_2_20,
-       /* I2S */
-       MX25_PAD_KPP_COL3__AUD5_TXFS,
-       MX25_PAD_KPP_COL2__AUD5_TXC,
-       MX25_PAD_KPP_COL1__AUD5_RXD,
-       MX25_PAD_KPP_COL0__AUD5_TXD,
-       /* CAN */
-       MX25_PAD_GPIO_D__CAN2_RX,
-       MX25_PAD_GPIO_C__CAN2_TX,
-       /* SPI1 */
-       MX25_PAD_CSPI1_MOSI__CSPI1_MOSI,
-       MX25_PAD_CSPI1_MISO__CSPI1_MISO,
-       MX25_PAD_CSPI1_SS0__GPIO_1_16,
-       MX25_PAD_CSPI1_SS1__GPIO_1_17,
-       MX25_PAD_CSPI1_SCLK__CSPI1_SCLK,
-       MX25_PAD_CSPI1_RDY__GPIO_2_22,
-};
-
-#define GPIO_LED1              IMX_GPIO_NR(3, 19)
-#define GPIO_SWITCH1   IMX_GPIO_NR(3, 18)
-#define GPIO_SD1CD             IMX_GPIO_NR(2, 20)
-#define GPIO_LCDPWR            IMX_GPIO_NR(1, 26)
-#define        GPIO_SPI1_SS0   IMX_GPIO_NR(1, 16)
-#define        GPIO_SPI1_SS1   IMX_GPIO_NR(1, 17)
-#define        GPIO_SPI1_IRQ   IMX_GPIO_NR(2, 22)
-
-static struct imx_fb_videomode eukrea_mximxsd_modes[] = {
-       {
-               .mode   = {
-                       .name           = "CMO-QVGA",
-                       .refresh        = 60,
-                       .xres           = 320,
-                       .yres           = 240,
-                       .pixclock       = KHZ2PICOS(6500),
-                       .left_margin    = 30,
-                       .right_margin   = 38,
-                       .upper_margin   = 20,
-                       .lower_margin   = 3,
-                       .hsync_len      = 15,
-                       .vsync_len      = 4,
-               },
-               .bpp    = 16,
-               .pcr    = 0xCAD08B80,
-       }, {
-               .mode = {
-                       .name           = "DVI-VGA",
-                       .refresh        = 60,
-                       .xres           = 640,
-                       .yres           = 480,
-                       .pixclock       = 32000,
-                       .hsync_len      = 7,
-                       .left_margin    = 100,
-                       .right_margin   = 100,
-                       .vsync_len      = 7,
-                       .upper_margin   = 7,
-                       .lower_margin   = 100,
-               },
-               .pcr            = 0xFA208B80,
-               .bpp            = 16,
-       }, {
-               .mode = {
-                       .name           = "DVI-SVGA",
-                       .refresh        = 60,
-                       .xres           = 800,
-                       .yres           = 600,
-                       .pixclock       = 25000,
-                       .hsync_len      = 7,
-                       .left_margin    = 75,
-                       .right_margin   = 75,
-                       .vsync_len      = 7,
-                       .upper_margin   = 7,
-                       .lower_margin   = 75,
-               },
-               .pcr            = 0xFA208B80,
-               .bpp            = 16,
-       },
-};
-
-static const struct imx_fb_platform_data eukrea_mximxsd_fb_pdata __initconst = {
-       .mode           = eukrea_mximxsd_modes,
-       .num_modes      = ARRAY_SIZE(eukrea_mximxsd_modes),
-       .pwmr           = 0x00A903FF,
-       .lscr1          = 0x00120300,
-       .dmacr          = 0x00040060,
-};
-
-static void eukrea_mbimxsd_lcd_power_set(struct plat_lcd_data *pd,
-                                  unsigned int power)
-{
-       if (power)
-               gpio_direction_output(GPIO_LCDPWR, 1);
-       else
-               gpio_direction_output(GPIO_LCDPWR, 0);
-}
-
-static struct plat_lcd_data eukrea_mbimxsd_lcd_power_data = {
-       .set_power              = eukrea_mbimxsd_lcd_power_set,
-};
-
-static struct platform_device eukrea_mbimxsd_lcd_powerdev = {
-       .name                   = "platform-lcd",
-       .dev.platform_data      = &eukrea_mbimxsd_lcd_power_data,
-};
-
-static const struct gpio_led eukrea_mbimxsd_leds[] __initconst = {
-       {
-               .name                   = "led1",
-               .default_trigger        = "heartbeat",
-               .active_low             = 1,
-               .gpio                   = GPIO_LED1,
-       },
-};
-
-static const struct gpio_led_platform_data
-               eukrea_mbimxsd_led_info __initconst = {
-       .leds           = eukrea_mbimxsd_leds,
-       .num_leds       = ARRAY_SIZE(eukrea_mbimxsd_leds),
-};
-
-static struct gpio_keys_button eukrea_mbimxsd_gpio_buttons[] = {
-       {
-               .gpio           = GPIO_SWITCH1,
-               .code           = BTN_0,
-               .desc           = "BP1",
-               .active_low     = 1,
-               .wakeup         = 1,
-       },
-};
-
-static const struct gpio_keys_platform_data
-               eukrea_mbimxsd_button_data __initconst = {
-       .buttons        = eukrea_mbimxsd_gpio_buttons,
-       .nbuttons       = ARRAY_SIZE(eukrea_mbimxsd_gpio_buttons),
-};
-
-static struct platform_device *platform_devices[] __initdata = {
-       &eukrea_mbimxsd_lcd_powerdev,
-};
-
-static const struct imxuart_platform_data uart_pdata __initconst = {
-       .flags = IMXUART_HAVE_RTSCTS,
-};
-
-static struct i2c_board_info eukrea_mbimxsd_i2c_devices[] = {
-       {
-               I2C_BOARD_INFO("tlv320aic23", 0x1a),
-       },
-};
-
-static const
-struct imx_ssi_platform_data eukrea_mbimxsd_ssi_pdata __initconst = {
-       .flags = IMX_SSI_SYN | IMX_SSI_NET | IMX_SSI_USE_I2S_SLAVE,
-};
-
-static struct esdhc_platform_data sd1_pdata = {
-       .cd_gpio = GPIO_SD1CD,
-       .cd_type = ESDHC_CD_GPIO,
-       .wp_type = ESDHC_WP_NONE,
-};
-
-static struct spi_board_info eukrea_mbimxsd25_spi_board_info[] __initdata = {
-       {
-               .modalias = "spidev",
-               .max_speed_hz = 20000000,
-               .bus_num = 0,
-               .chip_select = 0,
-               .mode = SPI_MODE_0,
-       },
-       {
-               .modalias = "spidev",
-               .max_speed_hz = 20000000,
-               .bus_num = 0,
-               .chip_select = 1,
-               .mode = SPI_MODE_0,
-       },
-};
-
-static int eukrea_mbimxsd25_spi_cs[] = {GPIO_SPI1_SS0, GPIO_SPI1_SS1};
-
-static const struct spi_imx_master eukrea_mbimxsd25_spi0_data __initconst = {
-       .chipselect     = eukrea_mbimxsd25_spi_cs,
-       .num_chipselect = ARRAY_SIZE(eukrea_mbimxsd25_spi_cs),
-};
-
-/*
- * system init for baseboard usage. Will be called by cpuimx25 init.
- *
- * Add platform devices present on this baseboard and init
- * them from CPU side as far as required to use them later on
- */
-void __init eukrea_mbimxsd25_baseboard_init(void)
-{
-       if (mxc_iomux_v3_setup_multiple_pads(eukrea_mbimxsd_pads,
-                       ARRAY_SIZE(eukrea_mbimxsd_pads)))
-               printk(KERN_ERR "error setting mbimxsd pads !\n");
-
-       imx25_add_imx_uart1(&uart_pdata);
-       imx25_add_imx_fb(&eukrea_mximxsd_fb_pdata);
-       imx25_add_imx_ssi(0, &eukrea_mbimxsd_ssi_pdata);
-
-       imx25_add_flexcan1();
-       imx25_add_sdhci_esdhc_imx(0, &sd1_pdata);
-
-       gpio_request(GPIO_LED1, "LED1");
-       gpio_direction_output(GPIO_LED1, 1);
-       gpio_free(GPIO_LED1);
-
-       gpio_request(GPIO_SWITCH1, "SWITCH1");
-       gpio_direction_input(GPIO_SWITCH1);
-       gpio_free(GPIO_SWITCH1);
-
-       gpio_request(GPIO_LCDPWR, "LCDPWR");
-       gpio_direction_output(GPIO_LCDPWR, 1);
-
-       i2c_register_board_info(0, eukrea_mbimxsd_i2c_devices,
-                               ARRAY_SIZE(eukrea_mbimxsd_i2c_devices));
-
-       gpio_request(GPIO_SPI1_IRQ, "SPI1_IRQ");
-       gpio_direction_input(GPIO_SPI1_IRQ);
-       gpio_free(GPIO_SPI1_IRQ);
-       imx25_add_spi_imx0(&eukrea_mbimxsd25_spi0_data);
-       spi_register_board_info(eukrea_mbimxsd25_spi_board_info,
-               ARRAY_SIZE(eukrea_mbimxsd25_spi_board_info));
-
-       platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
-       gpio_led_register_device(-1, &eukrea_mbimxsd_led_info);
-       imx_add_gpio_keys(&eukrea_mbimxsd_button_data);
-       imx_add_platform_device("eukrea_tlv320", 0, NULL, 0, NULL, 0);
-}
index 14d6c8249b76b9c5e03a5684477d84113b5daae9..6edc940e086548fd010f158a2013615f7608d062 100644 (file)
@@ -100,7 +100,7 @@ static struct mx3fb_platform_data mx3fb_pdata __initdata = {
        .num_modes      = ARRAY_SIZE(fb_modedb),
 };
 
-static iomux_v3_cfg_t eukrea_mbimxsd_pads[] = {
+static const iomux_v3_cfg_t eukrea_mbimxsd_pads[] __initconst = {
        /* LCD */
        MX35_PAD_LD0__IPU_DISPB_DAT_0,
        MX35_PAD_LD1__IPU_DISPB_DAT_1,
index 745caa18ab2c0bc0edcfa7388e1a44c1bdf6986a..4d60005e9277ce8f33307f411dd5c0baa8a6ac7a 100644 (file)
  * http://www.gnu.org/copyleft/gpl.html
  */
 
+#include <linux/clk.h>
+#include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/regulator/consumer.h>
 #include <linux/irqchip/arm-gic.h>
 #include "common.h"
+#include "hardware.h"
 
+#define GPC_CNTR               0x000
 #define GPC_IMR1               0x008
+#define GPC_PGC_GPU_PDN                0x260
+#define GPC_PGC_GPU_PUPSCR     0x264
+#define GPC_PGC_GPU_PDNSCR     0x268
 #define GPC_PGC_CPU_PDN                0x2a0
 #define GPC_PGC_CPU_PUPSCR     0x2a4
 #define GPC_PGC_CPU_PDNSCR     0x2a8
 #define GPC_PGC_SW_SHIFT       0x0
 
 #define IMR_NUM                        4
+#define GPC_MAX_IRQS           (IMR_NUM * 32)
+
+#define GPU_VPU_PUP_REQ                BIT(1)
+#define GPU_VPU_PDN_REQ                BIT(0)
+
+#define GPC_CLK_MAX            6
+
+struct pu_domain {
+       struct generic_pm_domain base;
+       struct regulator *reg;
+       struct clk *clk[GPC_CLK_MAX];
+       int num_clks;
+};
 
 static void __iomem *gpc_base;
 static u32 gpc_wake_irqs[IMR_NUM];
@@ -77,17 +100,17 @@ void imx_gpc_post_resume(void)
 
 static int imx_gpc_irq_set_wake(struct irq_data *d, unsigned int on)
 {
-       unsigned int idx = d->hwirq / 32 - 1;
+       unsigned int idx = d->hwirq / 32;
        u32 mask;
 
-       /* Sanity check for SPI irq */
-       if (d->hwirq < 32)
-               return -EINVAL;
-
        mask = 1 << d->hwirq % 32;
        gpc_wake_irqs[idx] = on ? gpc_wake_irqs[idx] | mask :
                                  gpc_wake_irqs[idx] & ~mask;
 
+       /*
+        * Do *not* call into the parent, as the GIC doesn't have any
+        * wake-up facility...
+        */
        return 0;
 }
 
@@ -117,7 +140,7 @@ void imx_gpc_hwirq_unmask(unsigned int hwirq)
        void __iomem *reg;
        u32 val;
 
-       reg = gpc_base + GPC_IMR1 + (hwirq / 32 - 1) * 4;
+       reg = gpc_base + GPC_IMR1 + hwirq / 32 * 4;
        val = readl_relaxed(reg);
        val &= ~(1 << hwirq % 32);
        writel_relaxed(val, reg);
@@ -128,7 +151,7 @@ void imx_gpc_hwirq_mask(unsigned int hwirq)
        void __iomem *reg;
        u32 val;
 
-       reg = gpc_base + GPC_IMR1 + (hwirq / 32 - 1) * 4;
+       reg = gpc_base + GPC_IMR1 + hwirq / 32 * 4;
        val = readl_relaxed(reg);
        val |= 1 << (hwirq % 32);
        writel_relaxed(val, reg);
@@ -136,37 +159,319 @@ void imx_gpc_hwirq_mask(unsigned int hwirq)
 
 static void imx_gpc_irq_unmask(struct irq_data *d)
 {
-       /* Sanity check for SPI irq */
-       if (d->hwirq < 32)
-               return;
-
        imx_gpc_hwirq_unmask(d->hwirq);
+       irq_chip_unmask_parent(d);
 }
 
 static void imx_gpc_irq_mask(struct irq_data *d)
 {
-       /* Sanity check for SPI irq */
-       if (d->hwirq < 32)
-               return;
-
        imx_gpc_hwirq_mask(d->hwirq);
+       irq_chip_mask_parent(d);
 }
 
-void __init imx_gpc_init(void)
+static struct irq_chip imx_gpc_chip = {
+       .name                   = "GPC",
+       .irq_eoi                = irq_chip_eoi_parent,
+       .irq_mask               = imx_gpc_irq_mask,
+       .irq_unmask             = imx_gpc_irq_unmask,
+       .irq_retrigger          = irq_chip_retrigger_hierarchy,
+       .irq_set_wake           = imx_gpc_irq_set_wake,
+#ifdef CONFIG_SMP
+       .irq_set_affinity       = irq_chip_set_affinity_parent,
+#endif
+};
+
+static int imx_gpc_domain_xlate(struct irq_domain *domain,
+                               struct device_node *controller,
+                               const u32 *intspec,
+                               unsigned int intsize,
+                               unsigned long *out_hwirq,
+                               unsigned int *out_type)
 {
-       struct device_node *np;
+       if (domain->of_node != controller)
+               return -EINVAL; /* Shouldn't happen, really... */
+       if (intsize != 3)
+               return -EINVAL; /* Not GIC compliant */
+       if (intspec[0] != 0)
+               return -EINVAL; /* No PPI should point to this domain */
+
+       *out_hwirq = intspec[1];
+       *out_type = intspec[2];
+       return 0;
+}
+
+static int imx_gpc_domain_alloc(struct irq_domain *domain,
+                                 unsigned int irq,
+                                 unsigned int nr_irqs, void *data)
+{
+       struct of_phandle_args *args = data;
+       struct of_phandle_args parent_args;
+       irq_hw_number_t hwirq;
        int i;
 
-       np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc");
-       gpc_base = of_iomap(np, 0);
-       WARN_ON(!gpc_base);
+       if (args->args_count != 3)
+               return -EINVAL; /* Not GIC compliant */
+       if (args->args[0] != 0)
+               return -EINVAL; /* No PPI should point to this domain */
+
+       hwirq = args->args[1];
+       if (hwirq >= GPC_MAX_IRQS)
+               return -EINVAL; /* Can't deal with this */
+
+       for (i = 0; i < nr_irqs; i++)
+               irq_domain_set_hwirq_and_chip(domain, irq + i, hwirq + i,
+                                             &imx_gpc_chip, NULL);
+
+       parent_args = *args;
+       parent_args.np = domain->parent->of_node;
+       return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs, &parent_args);
+}
+
+static struct irq_domain_ops imx_gpc_domain_ops = {
+       .xlate  = imx_gpc_domain_xlate,
+       .alloc  = imx_gpc_domain_alloc,
+       .free   = irq_domain_free_irqs_common,
+};
+
+static int __init imx_gpc_init(struct device_node *node,
+                              struct device_node *parent)
+{
+       struct irq_domain *parent_domain, *domain;
+       int i;
+
+       if (!parent) {
+               pr_err("%s: no parent, giving up\n", node->full_name);
+               return -ENODEV;
+       }
+
+       parent_domain = irq_find_host(parent);
+       if (!parent_domain) {
+               pr_err("%s: unable to obtain parent domain\n", node->full_name);
+               return -ENXIO;
+       }
+
+       gpc_base = of_iomap(node, 0);
+       if (WARN_ON(!gpc_base))
+               return -ENOMEM;
+
+       domain = irq_domain_add_hierarchy(parent_domain, 0, GPC_MAX_IRQS,
+                                         node, &imx_gpc_domain_ops,
+                                         NULL);
+       if (!domain) {
+               iounmap(gpc_base);
+               return -ENOMEM;
+       }
 
        /* Initially mask all interrupts */
        for (i = 0; i < IMR_NUM; i++)
                writel_relaxed(~0, gpc_base + GPC_IMR1 + i * 4);
 
-       /* Register GPC as the secondary interrupt controller behind GIC */
-       gic_arch_extn.irq_mask = imx_gpc_irq_mask;
-       gic_arch_extn.irq_unmask = imx_gpc_irq_unmask;
-       gic_arch_extn.irq_set_wake = imx_gpc_irq_set_wake;
+       return 0;
+}
+
+/*
+ * We cannot use the IRQCHIP_DECLARE macro that lives in
+ * drivers/irqchip, so we're forced to roll our own. Not very nice.
+ */
+OF_DECLARE_2(irqchip, imx_gpc, "fsl,imx6q-gpc", imx_gpc_init);
+
+void __init imx_gpc_check_dt(void)
+{
+       struct device_node *np;
+
+       np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc");
+       if (WARN_ON(!np ||
+                   !of_find_property(np, "interrupt-controller", NULL)))
+               pr_warn("Outdated DT detected, system is about to crash!!!\n");
+}
+
+#ifdef CONFIG_PM_GENERIC_DOMAINS
+
+static void _imx6q_pm_pu_power_off(struct generic_pm_domain *genpd)
+{
+       int iso, iso2sw;
+       u32 val;
+
+       /* Read ISO and ISO2SW power down delays */
+       val = readl_relaxed(gpc_base + GPC_PGC_GPU_PDNSCR);
+       iso = val & 0x3f;
+       iso2sw = (val >> 8) & 0x3f;
+
+       /* Gate off PU domain when GPU/VPU when powered down */
+       writel_relaxed(0x1, gpc_base + GPC_PGC_GPU_PDN);
+
+       /* Request GPC to power down GPU/VPU */
+       val = readl_relaxed(gpc_base + GPC_CNTR);
+       val |= GPU_VPU_PDN_REQ;
+       writel_relaxed(val, gpc_base + GPC_CNTR);
+
+       /* Wait ISO + ISO2SW IPG clock cycles */
+       ndelay((iso + iso2sw) * 1000 / 66);
+}
+
+static int imx6q_pm_pu_power_off(struct generic_pm_domain *genpd)
+{
+       struct pu_domain *pu = container_of(genpd, struct pu_domain, base);
+
+       _imx6q_pm_pu_power_off(genpd);
+
+       if (pu->reg)
+               regulator_disable(pu->reg);
+
+       return 0;
+}
+
+static int imx6q_pm_pu_power_on(struct generic_pm_domain *genpd)
+{
+       struct pu_domain *pu = container_of(genpd, struct pu_domain, base);
+       int i, ret, sw, sw2iso;
+       u32 val;
+
+       if (pu->reg)
+               ret = regulator_enable(pu->reg);
+       if (pu->reg && ret) {
+               pr_err("%s: failed to enable regulator: %d\n", __func__, ret);
+               return ret;
+       }
+
+       /* Enable reset clocks for all devices in the PU domain */
+       for (i = 0; i < pu->num_clks; i++)
+               clk_prepare_enable(pu->clk[i]);
+
+       /* Gate off PU domain when GPU/VPU when powered down */
+       writel_relaxed(0x1, gpc_base + GPC_PGC_GPU_PDN);
+
+       /* Read ISO and ISO2SW power down delays */
+       val = readl_relaxed(gpc_base + GPC_PGC_GPU_PUPSCR);
+       sw = val & 0x3f;
+       sw2iso = (val >> 8) & 0x3f;
+
+       /* Request GPC to power up GPU/VPU */
+       val = readl_relaxed(gpc_base + GPC_CNTR);
+       val |= GPU_VPU_PUP_REQ;
+       writel_relaxed(val, gpc_base + GPC_CNTR);
+
+       /* Wait ISO + ISO2SW IPG clock cycles */
+       ndelay((sw + sw2iso) * 1000 / 66);
+
+       /* Disable reset clocks for all devices in the PU domain */
+       for (i = 0; i < pu->num_clks; i++)
+               clk_disable_unprepare(pu->clk[i]);
+
+       return 0;
+}
+
+static struct generic_pm_domain imx6q_arm_domain = {
+       .name = "ARM",
+};
+
+static struct pu_domain imx6q_pu_domain = {
+       .base = {
+               .name = "PU",
+               .power_off = imx6q_pm_pu_power_off,
+               .power_on = imx6q_pm_pu_power_on,
+               .power_off_latency_ns = 25000,
+               .power_on_latency_ns = 2000000,
+       },
+};
+
+static struct generic_pm_domain imx6sl_display_domain = {
+       .name = "DISPLAY",
+};
+
+static struct generic_pm_domain *imx_gpc_domains[] = {
+       &imx6q_arm_domain,
+       &imx6q_pu_domain.base,
+       &imx6sl_display_domain,
+};
+
+static struct genpd_onecell_data imx_gpc_onecell_data = {
+       .domains = imx_gpc_domains,
+       .num_domains = ARRAY_SIZE(imx_gpc_domains),
+};
+
+static int imx_gpc_genpd_init(struct device *dev, struct regulator *pu_reg)
+{
+       struct clk *clk;
+       bool is_off;
+       int i;
+
+       imx6q_pu_domain.reg = pu_reg;
+
+       for (i = 0; ; i++) {
+               clk = of_clk_get(dev->of_node, i);
+               if (IS_ERR(clk))
+                       break;
+               if (i >= GPC_CLK_MAX) {
+                       dev_err(dev, "more than %d clocks\n", GPC_CLK_MAX);
+                       goto clk_err;
+               }
+               imx6q_pu_domain.clk[i] = clk;
+       }
+       imx6q_pu_domain.num_clks = i;
+
+       is_off = IS_ENABLED(CONFIG_PM);
+       if (is_off) {
+               _imx6q_pm_pu_power_off(&imx6q_pu_domain.base);
+       } else {
+               /*
+                * Enable power if compiled without CONFIG_PM in case the
+                * bootloader disabled it.
+                */
+               imx6q_pm_pu_power_on(&imx6q_pu_domain.base);
+       }
+
+       pm_genpd_init(&imx6q_pu_domain.base, NULL, is_off);
+       return of_genpd_add_provider_onecell(dev->of_node,
+                                            &imx_gpc_onecell_data);
+
+clk_err:
+       while (i--)
+               clk_put(imx6q_pu_domain.clk[i]);
+       return -EINVAL;
+}
+
+#else
+static inline int imx_gpc_genpd_init(struct device *dev, struct regulator *reg)
+{
+       return 0;
+}
+#endif /* CONFIG_PM_GENERIC_DOMAINS */
+
+static int imx_gpc_probe(struct platform_device *pdev)
+{
+       struct regulator *pu_reg;
+       int ret;
+
+       pu_reg = devm_regulator_get_optional(&pdev->dev, "pu");
+       if (PTR_ERR(pu_reg) == -ENODEV)
+               pu_reg = NULL;
+       if (IS_ERR(pu_reg)) {
+               ret = PTR_ERR(pu_reg);
+               dev_err(&pdev->dev, "failed to get pu regulator: %d\n", ret);
+               return ret;
+       }
+
+       return imx_gpc_genpd_init(&pdev->dev, pu_reg);
+}
+
+static const struct of_device_id imx_gpc_dt_ids[] = {
+       { .compatible = "fsl,imx6q-gpc" },
+       { .compatible = "fsl,imx6sl-gpc" },
+       { }
+};
+
+static struct platform_driver imx_gpc_driver = {
+       .driver = {
+               .name = "imx-gpc",
+               .owner = THIS_MODULE,
+               .of_match_table = imx_gpc_dt_ids,
+       },
+       .probe = imx_gpc_probe,
+};
+
+static int __init imx_pgc_init(void)
+{
+       return platform_driver_register(&imx_gpc_driver);
 }
+subsys_initcall(imx_pgc_init);
index 66b2b564c463ef59b27ef8145ae9f78d8c340083..76af2c03c241eff9509e6cdf6b1129763537824b 100644 (file)
 #include "mx21.h"
 #include "mx27.h"
 #include "mx1.h"
-#include "mx25.h"
 
 #define imx_map_entry(soc, name, _type)        {                               \
        .virtual = soc ## _IO_P2V(soc ## _ ## name ## _BASE_ADDR),      \
diff --git a/arch/arm/mach-imx/imx25-dt.c b/arch/arm/mach-imx/imx25-dt.c
deleted file mode 100644 (file)
index 25defbd..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2012 Sascha Hauer, Pengutronix
- *
- * 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/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 "mx25.h"
-
-static const char * const imx25_dt_board_compat[] __initconst = {
-       "fsl,imx25",
-       NULL
-};
-
-DT_MACHINE_START(IMX25_DT, "Freescale i.MX25 (Device Tree Support)")
-       .map_io         = mx25_map_io,
-       .init_early     = imx25_init_early,
-       .init_irq       = mx25_init_irq,
-       .dt_compat      = imx25_dt_board_compat,
-MACHINE_END
diff --git a/arch/arm/mach-imx/iomux-mx25.h b/arch/arm/mach-imx/iomux-mx25.h
deleted file mode 100644 (file)
index be51e83..0000000
+++ /dev/null
@@ -1,524 +0,0 @@
-/*
- * arch/arm/plat-mxc/include/mach/iomux-mx25.h
- *
- * Copyright (C) 2009 by Lothar Wassmann <LW@KARO-electronics.de>
- *
- * based on arch/arm/mach-mx25/mx25_pins.h
- *    Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
- * and
- * arch/arm/plat-mxc/include/mach/iomux-mx35.h
- *    Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH <armlinux@phytec.de>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-#ifndef __MACH_IOMUX_MX25_H__
-#define __MACH_IOMUX_MX25_H__
-
-#include "iomux-v3.h"
-
-/*
- * IOMUX/PAD Bit field definitions
- */
-
-#define MX25_PAD_A10__A10              IOMUX_PAD(0x000, 0x008, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A10__GPIO_4_0         IOMUX_PAD(0x000, 0x008, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_A13__A13              IOMUX_PAD(0x22C, 0x00c, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A13__GPIO_4_1         IOMUX_PAD(0x22C, 0x00c, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_A14__A14              IOMUX_PAD(0x230, 0x010, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A14__GPIO_2_0         IOMUX_PAD(0x230, 0x010, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_A15__A15              IOMUX_PAD(0x234, 0x014, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A15__GPIO_2_1         IOMUX_PAD(0x234, 0x014, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_A16__A16              IOMUX_PAD(0x000, 0x018, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A16__GPIO_2_2         IOMUX_PAD(0x000, 0x018, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_A17__A17              IOMUX_PAD(0x238, 0x01c, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A17__GPIO_2_3         IOMUX_PAD(0x238, 0x01c, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_A18__A18              IOMUX_PAD(0x23c, 0x020, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A18__GPIO_2_4         IOMUX_PAD(0x23c, 0x020, 0x15, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A18__FEC_COL          IOMUX_PAD(0x23c, 0x020, 0x17, 0x504, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_A19__A19              IOMUX_PAD(0x240, 0x024, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A19__FEC_RX_ER                IOMUX_PAD(0x240, 0x024, 0x17, 0x518, 0, NO_PAD_CTRL)
-#define MX25_PAD_A19__GPIO_2_5         IOMUX_PAD(0x240, 0x024, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_A20__A20              IOMUX_PAD(0x244, 0x028, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A20__GPIO_2_6         IOMUX_PAD(0x244, 0x028, 0x15, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A20__FEC_RDATA2       IOMUX_PAD(0x244, 0x028, 0x17, 0x50c, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_A21__A21              IOMUX_PAD(0x248, 0x02c, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A21__GPIO_2_7         IOMUX_PAD(0x248, 0x02c, 0x15, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A21__FEC_RDATA3       IOMUX_PAD(0x248, 0x02c, 0x17, 0x510, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_A22__A22              IOMUX_PAD(0x000, 0x030, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A22__GPIO_2_8         IOMUX_PAD(0x000, 0x030, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_A23__A23              IOMUX_PAD(0x24c, 0x034, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A23__GPIO_2_9         IOMUX_PAD(0x24c, 0x034, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_A24__A24              IOMUX_PAD(0x250, 0x038, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A24__GPIO_2_10                IOMUX_PAD(0x250, 0x038, 0x15, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A24__FEC_RX_CLK       IOMUX_PAD(0x250, 0x038, 0x17, 0x514, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_A25__A25              IOMUX_PAD(0x254, 0x03c, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A25__GPIO_2_11                IOMUX_PAD(0x254, 0x03c, 0x15, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_A25__FEC_CRS          IOMUX_PAD(0x254, 0x03c, 0x17, 0x508, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_EB0__EB0              IOMUX_PAD(0x258, 0x040, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_EB0__AUD4_TXD         IOMUX_PAD(0x258, 0x040, 0x14, 0x464, 0, NO_PAD_CTRL)
-#define MX25_PAD_EB0__GPIO_2_12                IOMUX_PAD(0x258, 0x040, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_EB1__EB1              IOMUX_PAD(0x25c, 0x044, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_EB1__AUD4_RXD         IOMUX_PAD(0x25c, 0x044, 0x14, 0x460, 0, NO_PAD_CTRL)
-#define MX25_PAD_EB1__GPIO_2_13                IOMUX_PAD(0x25c, 0x044, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_OE__OE                        IOMUX_PAD(0x260, 0x048, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_OE__AUD4_TXC          IOMUX_PAD(0x260, 0x048, 0x14, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_OE__GPIO_2_14         IOMUX_PAD(0x260, 0x048, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CS0__CS0              IOMUX_PAD(0x000, 0x04c, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CS0__GPIO_4_2         IOMUX_PAD(0x000, 0x04c, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CS1__CS1              IOMUX_PAD(0x000, 0x050, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CS1__NF_CE3           IOMUX_PAD(0x000, 0x050, 0x01, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CS1__GPIO_4_3         IOMUX_PAD(0x000, 0x050, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CS4__CS4              IOMUX_PAD(0x264, 0x054, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CS4__NF_CE1           IOMUX_PAD(0x264, 0x054, 0x01, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CS4__UART5_CTS                IOMUX_PAD(0x264, 0x054, 0x13, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CS4__GPIO_3_20                IOMUX_PAD(0x264, 0x054, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CS5__CS5              IOMUX_PAD(0x268, 0x058, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CS5__NF_CE2           IOMUX_PAD(0x268, 0x058, 0x01, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CS5__UART5_RTS                IOMUX_PAD(0x268, 0x058, 0x13, 0x574, 0, NO_PAD_CTRL)
-#define MX25_PAD_CS5__GPIO_3_21                IOMUX_PAD(0x268, 0x058, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_NF_CE0__NF_CE0                IOMUX_PAD(0x26c, 0x05c, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_NF_CE0__GPIO_3_22     IOMUX_PAD(0x26c, 0x05c, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_ECB__ECB              IOMUX_PAD(0x270, 0x060, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_ECB__UART5_TXD_MUX    IOMUX_PAD(0x270, 0x060, 0x13, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_ECB__GPIO_3_23                IOMUX_PAD(0x270, 0x060, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_LBA__LBA              IOMUX_PAD(0x274, 0x064, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_LBA__UART5_RXD_MUX    IOMUX_PAD(0x274, 0x064, 0x13, 0x578, 0, NO_PAD_CTRL)
-#define MX25_PAD_LBA__GPIO_3_24                IOMUX_PAD(0x274, 0x064, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_BCLK__BCLK            IOMUX_PAD(0x000, 0x068, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_BCLK__GPIO_4_4                IOMUX_PAD(0x000, 0x068, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_RW__RW                        IOMUX_PAD(0x278, 0x06c, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_RW__AUD4_TXFS         IOMUX_PAD(0x278, 0x06c, 0x14, 0x474, 0, NO_PAD_CTRL)
-#define MX25_PAD_RW__GPIO_3_25         IOMUX_PAD(0x278, 0x06c, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_NFWE_B__NFWE_B                IOMUX_PAD(0x000, 0x070, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_NFWE_B__GPIO_3_26     IOMUX_PAD(0x000, 0x070, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_NFRE_B__NFRE_B                IOMUX_PAD(0x000, 0x074, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_NFRE_B__GPIO_3_27     IOMUX_PAD(0x000, 0x074, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_NFALE__NFALE          IOMUX_PAD(0x000, 0x078, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_NFALE__GPIO_3_28      IOMUX_PAD(0x000, 0x078, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_NFCLE__NFCLE          IOMUX_PAD(0x000, 0x07c, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_NFCLE__GPIO_3_29      IOMUX_PAD(0x000, 0x07c, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_NFWP_B__NFWP_B                IOMUX_PAD(0x000, 0x080, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_NFWP_B__GPIO_3_30     IOMUX_PAD(0x000, 0x080, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_NFRB__NFRB            IOMUX_PAD(0x27c, 0x084, 0x10, 0, 0, PAD_CTL_PKE)
-#define MX25_PAD_NFRB__GPIO_3_31       IOMUX_PAD(0x27c, 0x084, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_D15__D15              IOMUX_PAD(0x280, 0x088, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D15__LD16             IOMUX_PAD(0x280, 0x088, 0x01, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_D15__GPIO_4_5         IOMUX_PAD(0x280, 0x088, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_D14__D14              IOMUX_PAD(0x284, 0x08c, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D14__LD17             IOMUX_PAD(0x284, 0x08c, 0x01, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_D14__GPIO_4_6         IOMUX_PAD(0x284, 0x08c, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_D13__D13              IOMUX_PAD(0x288, 0x090, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D13__LD18             IOMUX_PAD(0x288, 0x090, 0x01, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_D13__GPIO_4_7         IOMUX_PAD(0x288, 0x090, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_D12__D12              IOMUX_PAD(0x28c, 0x094, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D12__GPIO_4_8         IOMUX_PAD(0x28c, 0x094, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_D11__D11              IOMUX_PAD(0x290, 0x098, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D11__GPIO_4_9         IOMUX_PAD(0x290, 0x098, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_D10__D10              IOMUX_PAD(0x294, 0x09c, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D10__GPIO_4_10                IOMUX_PAD(0x294, 0x09c, 0x05, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D10__USBOTG_OC                IOMUX_PAD(0x294, 0x09c, 0x06, 0x57c, 0, PAD_CTL_PUS_100K_UP)
-
-#define MX25_PAD_D9__D9                        IOMUX_PAD(0x298, 0x0a0, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D9__GPIO_4_11         IOMUX_PAD(0x298, 0x0a0, 0x05, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D9__USBH2_PWR         IOMUX_PAD(0x298, 0x0a0, 0x06, 0, 0, PAD_CTL_PKE)
-
-#define MX25_PAD_D8__D8                        IOMUX_PAD(0x29c, 0x0a4, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D8__GPIO_4_12         IOMUX_PAD(0x29c, 0x0a4, 0x05, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D8__USBH2_OC          IOMUX_PAD(0x29c, 0x0a4, 0x06, 0x580, 0, PAD_CTL_PUS_100K_UP)
-
-#define MX25_PAD_D7__D7                        IOMUX_PAD(0x2a0, 0x0a8, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D7__GPIO_4_13         IOMUX_PAD(0x2a0, 0x0a8, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_D6__D6                        IOMUX_PAD(0x2a4, 0x0ac, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D6__GPIO_4_14         IOMUX_PAD(0x2a4, 0x0ac, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_D5__D5                        IOMUX_PAD(0x2a8, 0x0b0, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D5__GPIO_4_15         IOMUX_PAD(0x2a8, 0x0b0, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_D4__D4                        IOMUX_PAD(0x2ac, 0x0b4, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D4__GPIO_4_16         IOMUX_PAD(0x2ac, 0x0b4, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_D3__D3                        IOMUX_PAD(0x2b0, 0x0b8, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D3__GPIO_4_17         IOMUX_PAD(0x2b0, 0x0b8, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_D2__D2                        IOMUX_PAD(0x2b4, 0x0bc, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D2__GPIO_4_18         IOMUX_PAD(0x2b4, 0x0bc, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_D1__D1                        IOMUX_PAD(0x2b8, 0x0c0, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D1__GPIO_4_19         IOMUX_PAD(0x2b8, 0x0c0, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_D0__D0                        IOMUX_PAD(0x2bc, 0x0c4, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_D0__GPIO_4_20         IOMUX_PAD(0x2bc, 0x0c4, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_LD0__LD0              IOMUX_PAD(0x2c0, 0x0c8, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD0__CSI_D0           IOMUX_PAD(0x2c0, 0x0c8, 0x12, 0x488, 0, NO_PAD_CTRL)
-#define MX25_PAD_LD0__GPIO_2_15                IOMUX_PAD(0x2c0, 0x0c8, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_LD1__LD1              IOMUX_PAD(0x2c4, 0x0cc, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD1__CSI_D1           IOMUX_PAD(0x2c4, 0x0cc, 0x12, 0x48c, 0, NO_PAD_CTRL)
-#define MX25_PAD_LD1__GPIO_2_16                IOMUX_PAD(0x2c4, 0x0cc, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_LD2__LD2              IOMUX_PAD(0x2c8, 0x0d0, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD2__GPIO_2_17                IOMUX_PAD(0x2c8, 0x0d0, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_LD3__LD3              IOMUX_PAD(0x2cc, 0x0d4, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD3__GPIO_2_18                IOMUX_PAD(0x2cc, 0x0d4, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_LD4__LD4              IOMUX_PAD(0x2d0, 0x0d8, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD4__GPIO_2_19                IOMUX_PAD(0x2d0, 0x0d8, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_LD5__LD5              IOMUX_PAD(0x2d4, 0x0dc, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD5__GPIO_1_19                IOMUX_PAD(0x2d4, 0x0dc, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_LD6__LD6              IOMUX_PAD(0x2d8, 0x0e0, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD6__GPIO_1_20                IOMUX_PAD(0x2d8, 0x0e0, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_LD7__LD7              IOMUX_PAD(0x2dc, 0x0e4, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD7__GPIO_1_21                IOMUX_PAD(0x2dc, 0x0e4, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_LD8__LD8              IOMUX_PAD(0x2e0, 0x0e8, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD8__FEC_TX_ERR       IOMUX_PAD(0x2e0, 0x0e8, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_LD9__LD9              IOMUX_PAD(0x2e4, 0x0ec, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD9__FEC_COL          IOMUX_PAD(0x2e4, 0x0ec, 0x15, 0x504, 1, NO_PAD_CTRL)
-
-#define MX25_PAD_LD10__LD10            IOMUX_PAD(0x2e8, 0x0f0, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD10__FEC_RX_ER       IOMUX_PAD(0x2e8, 0x0f0, 0x15, 0x518, 1, NO_PAD_CTRL)
-
-#define MX25_PAD_LD11__LD11            IOMUX_PAD(0x2ec, 0x0f4, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD11__FEC_RDATA2      IOMUX_PAD(0x2ec, 0x0f4, 0x15, 0x50c, 1, NO_PAD_CTRL)
-
-#define MX25_PAD_LD12__LD12            IOMUX_PAD(0x2f0, 0x0f8, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD12__FEC_RDATA3      IOMUX_PAD(0x2f0, 0x0f8, 0x15, 0x510, 1, NO_PAD_CTRL)
-
-#define MX25_PAD_LD13__LD13            IOMUX_PAD(0x2f4, 0x0fc, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD13__FEC_TDATA2      IOMUX_PAD(0x2f4, 0x0fc, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_LD14__LD14            IOMUX_PAD(0x2f8, 0x100, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD14__FEC_TDATA3      IOMUX_PAD(0x2f8, 0x100, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_LD15__LD15            IOMUX_PAD(0x2fc, 0x104, 0x10, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_LD15__FEC_RX_CLK      IOMUX_PAD(0x2fc, 0x104, 0x15, 0x514, 1, NO_PAD_CTRL)
-
-#define MX25_PAD_HSYNC__HSYNC          IOMUX_PAD(0x300, 0x108, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_HSYNC__GPIO_1_22      IOMUX_PAD(0x300, 0x108, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_VSYNC__VSYNC          IOMUX_PAD(0x304, 0x10c, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_VSYNC__GPIO_1_23      IOMUX_PAD(0x304, 0x10c, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_LSCLK__LSCLK          IOMUX_PAD(0x308, 0x110, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_LSCLK__GPIO_1_24      IOMUX_PAD(0x308, 0x110, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_OE_ACD__OE_ACD                IOMUX_PAD(0x30c, 0x114, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_OE_ACD__GPIO_1_25     IOMUX_PAD(0x30c, 0x114, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CONTRAST__CONTRAST    IOMUX_PAD(0x310, 0x118, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CONTRAST__PWM4_PWMO   IOMUX_PAD(0x310, 0x118, 0x14, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CONTRAST__FEC_CRS     IOMUX_PAD(0x310, 0x118, 0x15, 0x508, 1, NO_PAD_CTRL)
-
-#define MX25_PAD_PWM__PWM              IOMUX_PAD(0x314, 0x11c, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_PWM__GPIO_1_26                IOMUX_PAD(0x314, 0x11c, 0x15, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_PWM__USBH2_OC         IOMUX_PAD(0x314, 0x11c, 0x16, 0x580, 1, PAD_CTL_PUS_100K_UP)
-
-#define MX25_PAD_CSI_D2__CSI_D2                IOMUX_PAD(0x318, 0x120, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_D2__UART5_RXD_MUX IOMUX_PAD(0x318, 0x120, 0x11, 0x578, 1, NO_PAD_CTRL)
-#define MX25_PAD_CSI_D2__GPIO_1_27     IOMUX_PAD(0x318, 0x120, 0x15, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_D2__CSPI3_MOSI    IOMUX_PAD(0x318, 0x120, 0x17, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSI_D3__CSI_D3                IOMUX_PAD(0x31c, 0x124, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_D3__GPIO_1_28     IOMUX_PAD(0x31c, 0x124, 0x15, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_D3__CSPI3_MISO    IOMUX_PAD(0x31c, 0x124, 0x17, 0x4b4, 1, NO_PAD_CTRL)
-
-#define MX25_PAD_CSI_D4__CSI_D4                IOMUX_PAD(0x320, 0x128, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_D4__UART5_RTS     IOMUX_PAD(0x320, 0x128, 0x11, 0x574, 1, NO_PAD_CTRL)
-#define MX25_PAD_CSI_D4__GPIO_1_29     IOMUX_PAD(0x320, 0x128, 0x15, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_D4__CSPI3_SCLK    IOMUX_PAD(0x320, 0x128, 0x17, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSI_D5__CSI_D5                IOMUX_PAD(0x324, 0x12c, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_D5__GPIO_1_30     IOMUX_PAD(0x324, 0x12c, 0x15, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_D5__CSPI3_RDY     IOMUX_PAD(0x324, 0x12c, 0x17, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSI_D6__CSI_D6                IOMUX_PAD(0x328, 0x130, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_D6__GPIO_1_31     IOMUX_PAD(0x328, 0x130, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSI_D7__CSI_D7                IOMUX_PAD(0x32c, 0x134, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_D7__GPIO_1_6      IOMUX_PAD(0x32c, 0x134, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSI_D8__CSI_D8                IOMUX_PAD(0x330, 0x138, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_D8__GPIO_1_7      IOMUX_PAD(0x330, 0x138, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSI_D9__CSI_D9                IOMUX_PAD(0x334, 0x13c, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_D9__GPIO_4_21     IOMUX_PAD(0x334, 0x13c, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSI_MCLK__CSI_MCLK    IOMUX_PAD(0x338, 0x140, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_MCLK__GPIO_1_8    IOMUX_PAD(0x338, 0x140, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSI_VSYNC__CSI_VSYNC  IOMUX_PAD(0x33c, 0x144, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_VSYNC__GPIO_1_9   IOMUX_PAD(0x33c, 0x144, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSI_HSYNC__CSI_HSYNC  IOMUX_PAD(0x340, 0x148, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_HSYNC__GPIO_1_10  IOMUX_PAD(0x340, 0x148, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSI_PIXCLK__CSI_PIXCLK        IOMUX_PAD(0x344, 0x14c, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSI_PIXCLK__GPIO_1_11 IOMUX_PAD(0x344, 0x14c, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_I2C1_CLK__I2C1_CLK    IOMUX_PAD(0x348, 0x150, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_I2C1_CLK__GPIO_1_12   IOMUX_PAD(0x348, 0x150, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_I2C1_DAT__I2C1_DAT    IOMUX_PAD(0x34c, 0x154, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_I2C1_DAT__GPIO_1_13   IOMUX_PAD(0x34c, 0x154, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSPI1_MOSI__CSPI1_MOSI        IOMUX_PAD(0x350, 0x158, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSPI1_MOSI__GPIO_1_14 IOMUX_PAD(0x350, 0x158, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSPI1_MISO__CSPI1_MISO        IOMUX_PAD(0x354, 0x15c, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSPI1_MISO__GPIO_1_15 IOMUX_PAD(0x354, 0x15c, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSPI1_SS0__CSPI1_SS0  IOMUX_PAD(0x358, 0x160, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSPI1_SS0__GPIO_1_16  IOMUX_PAD(0x358, 0x160, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSPI1_SS1__CSPI1_SS1  IOMUX_PAD(0x35c, 0x164, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSPI1_SS1__GPIO_1_17  IOMUX_PAD(0x35c, 0x164, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSPI1_SCLK__CSPI1_SCLK        IOMUX_PAD(0x360, 0x168, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CSPI1_SCLK__GPIO_1_18 IOMUX_PAD(0x360, 0x168, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CSPI1_RDY__CSPI1_RDY  IOMUX_PAD(0x364, 0x16c, 0x10, 0, 0, PAD_CTL_PKE)
-#define MX25_PAD_CSPI1_RDY__GPIO_2_22  IOMUX_PAD(0x364, 0x16c, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_UART1_RXD__UART1_RXD  IOMUX_PAD(0x368, 0x170, 0x10, 0, 0, PAD_CTL_PUS_100K_DOWN)
-#define MX25_PAD_UART1_RXD__GPIO_4_22  IOMUX_PAD(0x368, 0x170, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_UART1_TXD__UART1_TXD  IOMUX_PAD(0x36c, 0x174, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_UART1_TXD__GPIO_4_23  IOMUX_PAD(0x36c, 0x174, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_UART1_RTS__UART1_RTS  IOMUX_PAD(0x370, 0x178, 0x10, 0, 0, PAD_CTL_PUS_100K_UP)
-#define MX25_PAD_UART1_RTS__CSI_D0     IOMUX_PAD(0x370, 0x178, 0x11, 0x488, 1, NO_PAD_CTRL)
-#define MX25_PAD_UART1_RTS__GPIO_4_24  IOMUX_PAD(0x370, 0x178, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_UART1_CTS__UART1_CTS  IOMUX_PAD(0x374, 0x17c, 0x10, 0, 0, PAD_CTL_PUS_100K_UP)
-#define MX25_PAD_UART1_CTS__CSI_D1     IOMUX_PAD(0x374, 0x17c, 0x11, 0x48c, 1, NO_PAD_CTRL)
-#define MX25_PAD_UART1_CTS__GPIO_4_25  IOMUX_PAD(0x374, 0x17c, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_UART2_RXD__UART2_RXD  IOMUX_PAD(0x378, 0x180, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_UART2_RXD__GPIO_4_26  IOMUX_PAD(0x378, 0x180, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_UART2_TXD__UART2_TXD  IOMUX_PAD(0x37c, 0x184, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_UART2_TXD__GPIO_4_27  IOMUX_PAD(0x37c, 0x184, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_UART2_RTS__UART2_RTS  IOMUX_PAD(0x380, 0x188, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_UART2_RTS__FEC_COL    IOMUX_PAD(0x380, 0x188, 0x12, 0x504, 2, NO_PAD_CTRL)
-#define MX25_PAD_UART2_RTS__GPIO_4_28  IOMUX_PAD(0x380, 0x188, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_UART2_CTS__FEC_RX_ER  IOMUX_PAD(0x384, 0x18c, 0x12, 0x518, 2, NO_PAD_CTRL)
-#define MX25_PAD_UART2_CTS__UART2_CTS  IOMUX_PAD(0x384, 0x18c, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_UART2_CTS__GPIO_4_29  IOMUX_PAD(0x384, 0x18c, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_SD1_CMD__SD1_CMD      IOMUX_PAD(0x388, 0x190, 0x10, 0, 0, PAD_CTL_PUS_47K_UP)
-#define MX25_PAD_SD1_CMD__FEC_RDATA2   IOMUX_PAD(0x388, 0x190, 0x12, 0x50c, 2, NO_PAD_CTRL)
-#define MX25_PAD_SD1_CMD__GPIO_2_23    IOMUX_PAD(0x388, 0x190, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_SD1_CLK__SD1_CLK      IOMUX_PAD(0x38c, 0x194, 0x10, 0, 0, PAD_CTL_PUS_47K_UP)
-#define MX25_PAD_SD1_CLK__FEC_RDATA3   IOMUX_PAD(0x38c, 0x194, 0x12, 0x510, 2, NO_PAD_CTRL)
-#define MX25_PAD_SD1_CLK__GPIO_2_24    IOMUX_PAD(0x38c, 0x194, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_SD1_DATA0__SD1_DATA0  IOMUX_PAD(0x390, 0x198, 0x10, 0, 0, PAD_CTL_PUS_47K_UP)
-#define MX25_PAD_SD1_DATA0__GPIO_2_25  IOMUX_PAD(0x390, 0x198, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_SD1_DATA1__SD1_DATA1  IOMUX_PAD(0x394, 0x19c, 0x10, 0, 0, PAD_CTL_PUS_47K_UP)
-#define MX25_PAD_SD1_DATA1__AUD7_RXD   IOMUX_PAD(0x394, 0x19c, 0x13, 0x478, 0, NO_PAD_CTRL)
-#define MX25_PAD_SD1_DATA1__GPIO_2_26  IOMUX_PAD(0x394, 0x19c, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_SD1_DATA2__SD1_DATA2  IOMUX_PAD(0x398, 0x1a0, 0x10, 0, 0, PAD_CTL_PUS_47K_UP)
-#define MX25_PAD_SD1_DATA2__FEC_RX_CLK IOMUX_PAD(0x398, 0x1a0, 0x15, 0x514, 2, NO_PAD_CTRL)
-#define MX25_PAD_SD1_DATA2__GPIO_2_27  IOMUX_PAD(0x398, 0x1a0, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_SD1_DATA3__SD1_DATA3  IOMUX_PAD(0x39c, 0x1a4, 0x10, 0, 0, PAD_CTL_PUS_47K_UP)
-#define MX25_PAD_SD1_DATA3__FEC_CRS    IOMUX_PAD(0x39c, 0x1a4, 0x10, 0x508, 2, NO_PAD_CTRL)
-#define MX25_PAD_SD1_DATA3__GPIO_2_28  IOMUX_PAD(0x39c, 0x1a4, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define KPP_CTL_ROW    (PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_PUS_100K_UP)
-#define KPP_CTL_COL    (PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_PUS_100K_UP | PAD_CTL_ODE)
-
-#define MX25_PAD_KPP_ROW0__KPP_ROW0    IOMUX_PAD(0x3a0, 0x1a8, 0x10, 0, 0, KPP_CTL_ROW)
-#define MX25_PAD_KPP_ROW0__GPIO_2_29   IOMUX_PAD(0x3a0, 0x1a8, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_KPP_ROW1__KPP_ROW1    IOMUX_PAD(0x3a4, 0x1ac, 0x10, 0, 0, KPP_CTL_ROW)
-#define MX25_PAD_KPP_ROW1__GPIO_2_30   IOMUX_PAD(0x3a4, 0x1ac, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_KPP_ROW2__KPP_ROW2    IOMUX_PAD(0x3a8, 0x1b0, 0x10, 0, 0, KPP_CTL_ROW)
-#define MX25_PAD_KPP_ROW2__CSI_D0      IOMUX_PAD(0x3a8, 0x1b0, 0x13, 0x488, 2, NO_PAD_CTRL)
-#define MX25_PAD_KPP_ROW2__GPIO_2_31   IOMUX_PAD(0x3a8, 0x1b0, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_KPP_ROW3__KPP_ROW3    IOMUX_PAD(0x3ac, 0x1b4, 0x10, 0, 0, KPP_CTL_ROW)
-#define MX25_PAD_KPP_ROW3__CSI_LD1     IOMUX_PAD(0x3ac, 0x1b4, 0x13, 0x48c, 2, NO_PAD_CTRL)
-#define MX25_PAD_KPP_ROW3__GPIO_3_0    IOMUX_PAD(0x3ac, 0x1b4, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_KPP_COL0__KPP_COL0    IOMUX_PAD(0x3b0, 0x1b8, 0x10, 0, 0, KPP_CTL_COL)
-#define MX25_PAD_KPP_COL0__UART4_RXD_MUX IOMUX_PAD(0x3b0, 0x1b8, 0x11, 0x570, 1, NO_PAD_CTRL)
-#define MX25_PAD_KPP_COL0__AUD5_TXD    IOMUX_PAD(0x3b0, 0x1b8, 0x12, 0, 0, PAD_CTL_PKE | PAD_CTL_PUS_100K_UP)
-#define MX25_PAD_KPP_COL0__GPIO_3_1    IOMUX_PAD(0x3b0, 0x1b8, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_KPP_COL1__KPP_COL1    IOMUX_PAD(0x3b4, 0x1bc, 0x10, 0, 0, KPP_CTL_COL)
-#define MX25_PAD_KPP_COL1__UART4_TXD_MUX IOMUX_PAD(0x3b4, 0x1bc, 0x11, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_KPP_COL1__AUD5_RXD    IOMUX_PAD(0x3b4, 0x1bc, 0x12, 0, 0, PAD_CTL_PKE | PAD_CTL_PUS_100K_UP)
-#define MX25_PAD_KPP_COL1__GPIO_3_2    IOMUX_PAD(0x3b4, 0x1bc, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_KPP_COL2__KPP_COL2    IOMUX_PAD(0x3b8, 0x1c0, 0x10, 0, 0, KPP_CTL_COL)
-#define MX25_PAD_KPP_COL2__UART4_RTS   IOMUX_PAD(0x3b8, 0x1c0, 0x11, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_KPP_COL2__AUD5_TXC    IOMUX_PAD(0x3b8, 0x1c0, 0x12, 0, 0, PAD_CTL_PKE | PAD_CTL_PUS_100K_UP)
-#define MX25_PAD_KPP_COL2__GPIO_3_3    IOMUX_PAD(0x3b8, 0x1c0, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_KPP_COL3__KPP_COL3    IOMUX_PAD(0x3bc, 0x1c4, 0x10, 0, 0, KPP_CTL_COL)
-#define MX25_PAD_KPP_COL3__UART4_CTS   IOMUX_PAD(0x3bc, 0x1c4, 0x11, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_KPP_COL3__AUD5_TXFS   IOMUX_PAD(0x3bc, 0x1c4, 0x12, 0, 0, PAD_CTL_PKE | PAD_CTL_PUS_100K_UP)
-#define MX25_PAD_KPP_COL3__GPIO_3_4    IOMUX_PAD(0x3bc, 0x1c4, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_FEC_MDC__FEC_MDC      IOMUX_PAD(0x3c0, 0x1c8, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_FEC_MDC__AUD4_TXD     IOMUX_PAD(0x3c0, 0x1c8, 0x12, 0x464, 1, NO_PAD_CTRL)
-#define MX25_PAD_FEC_MDC__GPIO_3_5     IOMUX_PAD(0x3c0, 0x1c8, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_FEC_MDIO__FEC_MDIO    IOMUX_PAD(0x3c4, 0x1cc, 0x10, 0, 0, PAD_CTL_HYS | PAD_CTL_PUS_22K_UP)
-#define MX25_PAD_FEC_MDIO__AUD4_RXD    IOMUX_PAD(0x3c4, 0x1cc, 0x12, 0x460, 1, NO_PAD_CTRL)
-#define MX25_PAD_FEC_MDIO__GPIO_3_6    IOMUX_PAD(0x3c4, 0x1cc, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_FEC_TDATA0__FEC_TDATA0        IOMUX_PAD(0x3c8, 0x1d0, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_FEC_TDATA0__GPIO_3_7  IOMUX_PAD(0x3c8, 0x1d0, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_FEC_TDATA1__FEC_TDATA1        IOMUX_PAD(0x3cc, 0x1d4, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_FEC_TDATA1__AUD4_TXFS IOMUX_PAD(0x3cc, 0x1d4, 0x12, 0x474, 1, NO_PAD_CTRL)
-#define MX25_PAD_FEC_TDATA1__GPIO_3_8  IOMUX_PAD(0x3cc, 0x1d4, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_FEC_TX_EN__FEC_TX_EN  IOMUX_PAD(0x3d0, 0x1d8, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_FEC_TX_EN__GPIO_3_9           IOMUX_PAD(0x3d0, 0x1d8, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_FEC_RDATA0__FEC_RDATA0        IOMUX_PAD(0x3d4, 0x1dc, 0x10, 0, 0, PAD_CTL_PUS_100K_DOWN | NO_PAD_CTRL)
-#define MX25_PAD_FEC_RDATA0__GPIO_3_10 IOMUX_PAD(0x3d4, 0x1dc, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_FEC_RDATA1__FEC_RDATA1        IOMUX_PAD(0x3d8, 0x1e0, 0x10, 0, 0, PAD_CTL_PUS_100K_DOWN | NO_PAD_CTRL)
-#define MX25_PAD_FEC_RDATA1__GPIO_3_11 IOMUX_PAD(0x3d8, 0x1e0, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_FEC_RX_DV__FEC_RX_DV  IOMUX_PAD(0x3dc, 0x1e4, 0x10, 0, 0, PAD_CTL_PUS_100K_DOWN | NO_PAD_CTRL)
-#define MX25_PAD_FEC_RX_DV__CAN2_RX    IOMUX_PAD(0x3dc, 0x1e4, 0x14, 0x484, 0, PAD_CTL_PUS_22K_UP)
-#define MX25_PAD_FEC_RX_DV__GPIO_3_12  IOMUX_PAD(0x3dc, 0x1e4, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_FEC_TX_CLK__FEC_TX_CLK        IOMUX_PAD(0x3e0, 0x1e8, 0x10, 0, 0, PAD_CTL_HYS | PAD_CTL_PUS_100K_DOWN)
-#define MX25_PAD_FEC_TX_CLK__GPIO_3_13 IOMUX_PAD(0x3e0, 0x1e8, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_RTCK__RTCK            IOMUX_PAD(0x3e4, 0x1ec, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_RTCK__OWIRE           IOMUX_PAD(0x3e4, 0x1ec, 0x11, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_RTCK__GPIO_3_14       IOMUX_PAD(0x3e4, 0x1ec, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_DE_B__DE_B            IOMUX_PAD(0x3ec, 0x1f0, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_DE_B__GPIO_2_20       IOMUX_PAD(0x3ec, 0x1f0, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_TDO__TDO              IOMUX_PAD(0x3e8, 0x000, 0x00, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_GPIO_A__GPIO_A                IOMUX_PAD(0x3f0, 0x1f4, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_GPIO_A__CAN1_TX       IOMUX_PAD(0x3f0, 0x1f4, 0x16, 0, 0, PAD_CTL_PUS_22K_UP)
-#define MX25_PAD_GPIO_A__USBOTG_PWR    IOMUX_PAD(0x3f0, 0x1f4, 0x12, 0, 0, PAD_CTL_PKE)
-
-#define MX25_PAD_GPIO_B__GPIO_B                IOMUX_PAD(0x3f4, 0x1f8, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_GPIO_B__CAN1_RX       IOMUX_PAD(0x3f4, 0x1f8, 0x16, 0x480, 1, PAD_CTL_PUS_22K_UP)
-#define MX25_PAD_GPIO_B__USBOTG_OC     IOMUX_PAD(0x3f4, 0x1f8, 0x12, 0x57c, 1, PAD_CTL_PUS_100K_UP)
-
-#define MX25_PAD_GPIO_C__GPIO_C                IOMUX_PAD(0x3f8, 0x1fc, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_GPIO_C__CAN2_TX       IOMUX_PAD(0x3f8, 0x1fc, 0x16, 0, 0, PAD_CTL_PUS_22K_UP)
-
-#define MX25_PAD_GPIO_D__GPIO_D                IOMUX_PAD(0x3fc, 0x200, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_GPIO_E__LD16          IOMUX_PAD(0x400, 0x204, 0x02, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_GPIO_D__CAN2_RX       IOMUX_PAD(0x3fc, 0x200, 0x16, 0x484, 1, PAD_CTL_PUS_22K_UP)
-
-#define MX25_PAD_GPIO_E__GPIO_E                IOMUX_PAD(0x400, 0x204, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_GPIO_F__LD17          IOMUX_PAD(0x404, 0x208, 0x02, 0, 0, PAD_CTL_SRE_FAST)
-#define MX25_PAD_GPIO_E__AUD7_TXD      IOMUX_PAD(0x400, 0x204, 0x14, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_GPIO_F__GPIO_F                IOMUX_PAD(0x404, 0x208, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_GPIO_F__AUD7_TXC      IOMUX_PAD(0x404, 0x208, 0x14, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_EXT_ARMCLK__EXT_ARMCLK        IOMUX_PAD(0x000, 0x20c, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_EXT_ARMCLK__GPIO_3_15 IOMUX_PAD(0x000, 0x20c, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_UPLL_BYPCLK__UPLL_BYPCLK IOMUX_PAD(0x000, 0x210, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_UPLL_BYPCLK__GPIO_3_16        IOMUX_PAD(0x000, 0x210, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_VSTBY_REQ__VSTBY_REQ  IOMUX_PAD(0x408, 0x214, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_VSTBY_REQ__AUD7_TXFS  IOMUX_PAD(0x408, 0x214, 0x14, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_VSTBY_REQ__GPIO_3_17  IOMUX_PAD(0x408, 0x214, 0x15, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_VSTBY_ACK__VSTBY_ACK  IOMUX_PAD(0x40c, 0x218, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_VSTBY_ACK__GPIO_3_18  IOMUX_PAD(0x40c, 0x218, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_POWER_FAIL__POWER_FAIL        IOMUX_PAD(0x410, 0x21c, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_POWER_FAIL__AUD7_RXD  IOMUX_PAD(0x410, 0x21c, 0x14, 0x478, 1, NO_PAD_CTRL)
-#define MX25_PAD_POWER_FAIL__GPIO_3_19 IOMUX_PAD(0x410, 0x21c, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CLKO__CLKO            IOMUX_PAD(0x414, 0x220, 0x10, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CLKO__GPIO_2_21       IOMUX_PAD(0x414, 0x220, 0x15, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_BOOT_MODE0__BOOT_MODE0        IOMUX_PAD(0x000, 0x224, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_BOOT_MODE0__GPIO_4_30 IOMUX_PAD(0x000, 0x224, 0x05, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_BOOT_MODE1__BOOT_MODE1        IOMUX_PAD(0x000, 0x228, 0x00, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_BOOT_MODE1__GPIO_4_31 IOMUX_PAD(0x000, 0x228, 0x05, 0, 0, NO_PAD_CTRL)
-
-#define MX25_PAD_CTL_GRP_DVS_MISC      IOMUX_PAD(0x418, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DSE_FEC       IOMUX_PAD(0x41c, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DVS_JTAG      IOMUX_PAD(0x420, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DSE_NFC       IOMUX_PAD(0x424, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DSE_CSI       IOMUX_PAD(0x428, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DSE_WEIM      IOMUX_PAD(0x42c, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DSE_DDR       IOMUX_PAD(0x430, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DVS_CRM       IOMUX_PAD(0x434, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DSE_KPP       IOMUX_PAD(0x438, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DSE_SDHC1     IOMUX_PAD(0x43c, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DSE_LCD       IOMUX_PAD(0x440, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DSE_UART      IOMUX_PAD(0x444, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DVS_NFC       IOMUX_PAD(0x448, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DVS_CSI       IOMUX_PAD(0x44c, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DSE_CSPI1     IOMUX_PAD(0x450, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DDRTYPE       IOMUX_PAD(0x454, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DVS_SDHC1     IOMUX_PAD(0x458, 0x000, 0, 0, 0, NO_PAD_CTRL)
-#define MX25_PAD_CTL_GRP_DVS_LCD       IOMUX_PAD(0x45c, 0x000, 0, 0, 0, NO_PAD_CTRL)
-
-#endif /* __MACH_IOMUX_MX25_H__ */
index 0a5adba61e0b989e84604e95ecb2f2a9daa11113..2e4a0ddca76c29e5a98c8554f789293b394a3ad2 100644 (file)
@@ -114,7 +114,7 @@ enum iomux_gp_func {
  */
 int mxc_iomux_alloc_pin(unsigned int pin, const char *label);
 /*
- * setups mutliple pins
+ * setups multiple pins
  * convenient way to call the above function with tables
  */
 int mxc_iomux_setup_multiple_pins(const unsigned int *pin_list, unsigned count,
index d61f9606fc56e45c6cc0ecc2a93b20ff94f0e362..a53b2e64f98d547594243a67bf3581ac63250ea7 100644 (file)
@@ -56,9 +56,10 @@ int mxc_iomux_v3_setup_pad(iomux_v3_cfg_t pad)
        return 0;
 }
 
-int mxc_iomux_v3_setup_multiple_pads(iomux_v3_cfg_t *pad_list, unsigned count)
+int mxc_iomux_v3_setup_multiple_pads(const iomux_v3_cfg_t *pad_list,
+               unsigned count)
 {
-       iomux_v3_cfg_t *p = pad_list;
+       const iomux_v3_cfg_t *p = pad_list;
        int i;
        int ret;
 
index 2fa3b5430102ed862da4a52d43e8bfe559072630..f79e165a3b3c28f25920f679ef51c37be1cb10a3 100644 (file)
@@ -128,10 +128,11 @@ typedef u64 iomux_v3_cfg_t;
 int mxc_iomux_v3_setup_pad(iomux_v3_cfg_t pad);
 
 /*
- * setups mutliple pads
+ * setups multiple pads
  * convenient way to call the above function with tables
  */
-int mxc_iomux_v3_setup_multiple_pads(iomux_v3_cfg_t *pad_list, unsigned count);
+int mxc_iomux_v3_setup_multiple_pads(const iomux_v3_cfg_t *pad_list,
+               unsigned count);
 
 /*
  * Initialise the iomux controller
index 62a6e02f476318593171c38fe5c5c5b80fab1bec..922ffd6ca03936637a363ed5e34ef66f97831985 100644 (file)
@@ -75,7 +75,7 @@ static struct i2c_board_info eukrea_cpuimx35_i2c_devices[] = {
        },
 };
 
-static iomux_v3_cfg_t eukrea_cpuimx35_pads[] = {
+static const iomux_v3_cfg_t eukrea_cpuimx35_pads[] __initconst = {
        /* UART1 */
        MX35_PAD_CTS1__UART1_CTS,
        MX35_PAD_RTS1__UART1_RTS,
diff --git a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
deleted file mode 100644 (file)
index b2ee6e0..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright 2009 Sascha Hauer, <kernel@pengutronix.de>
- * Copyright 2010 Eric Bénard - Eukréa Electromatique, <eric@eukrea.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA  02110-1301, USA.
- */
-
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/irq.h>
-#include <linux/gpio.h>
-#include <linux/platform_device.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/ulpi.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <asm/memory.h>
-#include <asm/mach/map.h>
-
-#include "common.h"
-#include "devices-imx25.h"
-#include "ehci.h"
-#include "eukrea-baseboards.h"
-#include "hardware.h"
-#include "iomux-mx25.h"
-#include "mx25.h"
-
-static const struct imxuart_platform_data uart_pdata __initconst = {
-       .flags = IMXUART_HAVE_RTSCTS,
-};
-
-static iomux_v3_cfg_t eukrea_cpuimx25_pads[] = {
-       /* FEC - RMII */
-       MX25_PAD_FEC_MDC__FEC_MDC,
-       MX25_PAD_FEC_MDIO__FEC_MDIO,
-       MX25_PAD_FEC_TDATA0__FEC_TDATA0,
-       MX25_PAD_FEC_TDATA1__FEC_TDATA1,
-       MX25_PAD_FEC_TX_EN__FEC_TX_EN,
-       MX25_PAD_FEC_RDATA0__FEC_RDATA0,
-       MX25_PAD_FEC_RDATA1__FEC_RDATA1,
-       MX25_PAD_FEC_RX_DV__FEC_RX_DV,
-       MX25_PAD_FEC_TX_CLK__FEC_TX_CLK,
-       /* I2C1 */
-       MX25_PAD_I2C1_CLK__I2C1_CLK,
-       MX25_PAD_I2C1_DAT__I2C1_DAT,
-};
-
-static const struct fec_platform_data mx25_fec_pdata __initconst = {
-       .phy    = PHY_INTERFACE_MODE_RMII,
-};
-
-static const struct mxc_nand_platform_data
-eukrea_cpuimx25_nand_board_info __initconst = {
-       .width          = 1,
-       .hw_ecc         = 1,
-       .flash_bbt      = 1,
-};
-
-static const struct imxi2c_platform_data
-eukrea_cpuimx25_i2c0_data __initconst = {
-       .bitrate = 100000,
-};
-
-static struct i2c_board_info eukrea_cpuimx25_i2c_devices[] = {
-       {
-               I2C_BOARD_INFO("pcf8563", 0x51),
-       },
-};
-
-static int eukrea_cpuimx25_otg_init(struct platform_device *pdev)
-{
-       return mx25_initialize_usb_hw(pdev->id, MXC_EHCI_INTERFACE_DIFF_UNI);
-}
-
-static const struct mxc_usbh_platform_data otg_pdata __initconst = {
-       .init   = eukrea_cpuimx25_otg_init,
-       .portsc = MXC_EHCI_MODE_UTMI,
-};
-
-static int eukrea_cpuimx25_usbh2_init(struct platform_device *pdev)
-{
-       return mx25_initialize_usb_hw(pdev->id, MXC_EHCI_INTERFACE_SINGLE_UNI |
-                       MXC_EHCI_INTERNAL_PHY | MXC_EHCI_IPPUE_DOWN);
-}
-
-static const struct mxc_usbh_platform_data usbh2_pdata __initconst = {
-       .init   = eukrea_cpuimx25_usbh2_init,
-       .portsc = MXC_EHCI_MODE_SERIAL,
-};
-
-static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
-       .operating_mode = FSL_USB2_DR_DEVICE,
-       .phy_mode       = FSL_USB2_PHY_UTMI,
-       .workaround     = FLS_USB2_WORKAROUND_ENGCM09152,
-};
-
-static bool otg_mode_host __initdata;
-
-static int __init eukrea_cpuimx25_otg_mode(char *options)
-{
-       if (!strcmp(options, "host"))
-               otg_mode_host = true;
-       else if (!strcmp(options, "device"))
-               otg_mode_host = false;
-       else
-               pr_info("otg_mode neither \"host\" nor \"device\". "
-                       "Defaulting to device\n");
-       return 1;
-}
-__setup("otg_mode=", eukrea_cpuimx25_otg_mode);
-
-static void __init eukrea_cpuimx25_init(void)
-{
-       imx25_soc_init();
-
-       if (mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx25_pads,
-                       ARRAY_SIZE(eukrea_cpuimx25_pads)))
-               printk(KERN_ERR "error setting cpuimx25 pads !\n");
-
-       imx25_add_imx_uart0(&uart_pdata);
-       imx25_add_mxc_nand(&eukrea_cpuimx25_nand_board_info);
-       imx25_add_imxdi_rtc();
-       imx25_add_fec(&mx25_fec_pdata);
-       imx25_add_imx2_wdt();
-
-       i2c_register_board_info(0, eukrea_cpuimx25_i2c_devices,
-                               ARRAY_SIZE(eukrea_cpuimx25_i2c_devices));
-       imx25_add_imx_i2c0(&eukrea_cpuimx25_i2c0_data);
-
-       if (otg_mode_host)
-               imx25_add_mxc_ehci_otg(&otg_pdata);
-       else
-               imx25_add_fsl_usb2_udc(&otg_device_pdata);
-
-       imx25_add_mxc_ehci_hs(&usbh2_pdata);
-
-#ifdef CONFIG_MACH_EUKREA_MBIMXSD25_BASEBOARD
-       eukrea_mbimxsd25_baseboard_init();
-#endif
-}
-
-static void __init eukrea_cpuimx25_timer_init(void)
-{
-       mx25_clocks_init();
-}
-
-MACHINE_START(EUKREA_CPUIMX25SD, "Eukrea CPUIMX25")
-       /* Maintainer: Eukrea Electromatique */
-       .atag_offset = 0x100,
-       .map_io = mx25_map_io,
-       .init_early = imx25_init_early,
-       .init_irq = mx25_init_irq,
-       .init_time = eukrea_cpuimx25_timer_init,
-       .init_machine = eukrea_cpuimx25_init,
-       .restart        = mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-imx/mach-imx25.c b/arch/arm/mach-imx/mach-imx25.c
new file mode 100644 (file)
index 0000000..9379fd0
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2012 Sascha Hauer, Pengutronix
+ *
+ * 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/irq.h>
+#include <linux/of_address.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 "hardware.h"
+
+static void __init imx25_init_early(void)
+{
+       mxc_set_cpu_type(MXC_CPU_MX25);
+}
+
+static void __init mx25_init_irq(void)
+{
+       struct device_node *np;
+       void __iomem *avic_base;
+
+       np = of_find_compatible_node(NULL, NULL, "fsl,avic");
+       avic_base = of_iomap(np, 0);
+       BUG_ON(!avic_base);
+       mxc_init_irq(avic_base);
+}
+
+static const char * const imx25_dt_board_compat[] __initconst = {
+       "fsl,imx25",
+       NULL
+};
+
+DT_MACHINE_START(IMX25_DT, "Freescale i.MX25 (Device Tree Support)")
+       .init_early     = imx25_init_early,
+       .init_irq       = mx25_init_irq,
+       .dt_compat      = imx25_dt_board_compat,
+MACHINE_END
index 9de3412af4063ccd4ae7b8f2a176e9300020947a..3ab61549ce0fb8939c8f0a04b5a4c528fe64fbd1 100644 (file)
@@ -388,10 +388,10 @@ static void __init imx6q_map_io(void)
 
 static void __init imx6q_init_irq(void)
 {
+       imx_gpc_check_dt();
        imx_init_revision_from_anatop();
        imx_init_l2cache();
        imx_src_init();
-       imx_gpc_init();
        irqchip_init();
 }
 
index 24bfaaf944c8459f4e2947b1d855ce37cb8dd9b7..12a1b098fc6a98bd80de68161b94ae6377f04e37 100644 (file)
@@ -61,10 +61,10 @@ static void __init imx6sl_init_machine(void)
 
 static void __init imx6sl_init_irq(void)
 {
+       imx_gpc_check_dt();
        imx_init_revision_from_anatop();
        imx_init_l2cache();
        imx_src_init();
-       imx_gpc_init();
        irqchip_init();
 }
 
index 66988eb6a3a4dc5ac520bd2a19421e76eaaf28fd..f17b7004c24ba809caf27186c56cded060682586 100644 (file)
@@ -81,10 +81,10 @@ static void __init imx6sx_init_machine(void)
 
 static void __init imx6sx_init_irq(void)
 {
+       imx_gpc_check_dt();
        imx_init_revision_from_anatop();
        imx_init_l2cache();
        imx_src_init();
-       imx_gpc_init();
        irqchip_init();
 }
 
diff --git a/arch/arm/mach-imx/mach-mx25_3ds.c b/arch/arm/mach-imx/mach-mx25_3ds.c
deleted file mode 100644 (file)
index 0d01e36..0000000
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright 2009 Sascha Hauer, <kernel@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA  02110-1301, USA.
- */
-
-/*
- * This machine is known as:
- *  - i.MX25 3-Stack Development System
- *  - i.MX25 Platform Development Kit (i.MX25 PDK)
- */
-
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/irq.h>
-#include <linux/gpio.h>
-#include <linux/platform_device.h>
-#include <linux/usb/otg.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <asm/memory.h>
-#include <asm/mach/map.h>
-
-#include "common.h"
-#include "devices-imx25.h"
-#include "ehci.h"
-#include "hardware.h"
-#include "iomux-mx25.h"
-#include "mx25.h"
-
-#define MX25PDK_CAN_PWDN       IMX_GPIO_NR(4, 6)
-
-static const struct imxuart_platform_data uart_pdata __initconst = {
-       .flags = IMXUART_HAVE_RTSCTS,
-};
-
-static iomux_v3_cfg_t mx25pdk_pads[] = {
-       MX25_PAD_FEC_MDC__FEC_MDC,
-       MX25_PAD_FEC_MDIO__FEC_MDIO,
-       MX25_PAD_FEC_TDATA0__FEC_TDATA0,
-       MX25_PAD_FEC_TDATA1__FEC_TDATA1,
-       MX25_PAD_FEC_TX_EN__FEC_TX_EN,
-       MX25_PAD_FEC_RDATA0__FEC_RDATA0,
-       MX25_PAD_FEC_RDATA1__FEC_RDATA1,
-       MX25_PAD_FEC_RX_DV__FEC_RX_DV,
-       MX25_PAD_FEC_TX_CLK__FEC_TX_CLK,
-       MX25_PAD_A17__GPIO_2_3, /* FEC_EN, GPIO 35 */
-       MX25_PAD_D12__GPIO_4_8, /* FEC_RESET_B, GPIO 104 */
-
-       /* LCD */
-       MX25_PAD_LD0__LD0,
-       MX25_PAD_LD1__LD1,
-       MX25_PAD_LD2__LD2,
-       MX25_PAD_LD3__LD3,
-       MX25_PAD_LD4__LD4,
-       MX25_PAD_LD5__LD5,
-       MX25_PAD_LD6__LD6,
-       MX25_PAD_LD7__LD7,
-       MX25_PAD_LD8__LD8,
-       MX25_PAD_LD9__LD9,
-       MX25_PAD_LD10__LD10,
-       MX25_PAD_LD11__LD11,
-       MX25_PAD_LD12__LD12,
-       MX25_PAD_LD13__LD13,
-       MX25_PAD_LD14__LD14,
-       MX25_PAD_LD15__LD15,
-       MX25_PAD_GPIO_E__LD16,
-       MX25_PAD_GPIO_F__LD17,
-       MX25_PAD_HSYNC__HSYNC,
-       MX25_PAD_VSYNC__VSYNC,
-       MX25_PAD_LSCLK__LSCLK,
-       MX25_PAD_OE_ACD__OE_ACD,
-       MX25_PAD_CONTRAST__CONTRAST,
-
-       /* Keypad */
-       MX25_PAD_KPP_ROW0__KPP_ROW0,
-       MX25_PAD_KPP_ROW1__KPP_ROW1,
-       MX25_PAD_KPP_ROW2__KPP_ROW2,
-       MX25_PAD_KPP_ROW3__KPP_ROW3,
-       MX25_PAD_KPP_COL0__KPP_COL0,
-       MX25_PAD_KPP_COL1__KPP_COL1,
-       MX25_PAD_KPP_COL2__KPP_COL2,
-       MX25_PAD_KPP_COL3__KPP_COL3,
-
-       /* SD1 */
-       MX25_PAD_SD1_CMD__SD1_CMD,
-       MX25_PAD_SD1_CLK__SD1_CLK,
-       MX25_PAD_SD1_DATA0__SD1_DATA0,
-       MX25_PAD_SD1_DATA1__SD1_DATA1,
-       MX25_PAD_SD1_DATA2__SD1_DATA2,
-       MX25_PAD_SD1_DATA3__SD1_DATA3,
-       MX25_PAD_A14__GPIO_2_0, /* WriteProtect */
-       MX25_PAD_A15__GPIO_2_1, /* CardDetect */
-
-       /* I2C1 */
-       MX25_PAD_I2C1_CLK__I2C1_CLK,
-       MX25_PAD_I2C1_DAT__I2C1_DAT,
-
-       /* CAN1 */
-       MX25_PAD_GPIO_A__CAN1_TX,
-       MX25_PAD_GPIO_B__CAN1_RX,
-       MX25_PAD_D14__GPIO_4_6, /* CAN_PWDN */
-};
-
-static const struct fec_platform_data mx25_fec_pdata __initconst = {
-       .phy    = PHY_INTERFACE_MODE_RMII,
-};
-
-#define FEC_ENABLE_GPIO                IMX_GPIO_NR(2, 3)
-#define FEC_RESET_B_GPIO       IMX_GPIO_NR(4, 8)
-
-static void __init mx25pdk_fec_reset(void)
-{
-       gpio_request(FEC_ENABLE_GPIO, "FEC PHY enable");
-       gpio_request(FEC_RESET_B_GPIO, "FEC PHY reset");
-
-       gpio_direction_output(FEC_ENABLE_GPIO, 0);  /* drop PHY power */
-       gpio_direction_output(FEC_RESET_B_GPIO, 0); /* assert reset */
-       udelay(2);
-
-       /* turn on PHY power and lift reset */
-       gpio_set_value(FEC_ENABLE_GPIO, 1);
-       gpio_set_value(FEC_RESET_B_GPIO, 1);
-}
-
-static const struct mxc_nand_platform_data
-mx25pdk_nand_board_info __initconst = {
-       .width          = 1,
-       .hw_ecc         = 1,
-       .flash_bbt      = 1,
-};
-
-static struct imx_fb_videomode mx25pdk_modes[] = {
-       {
-               .mode   = {
-                       .name           = "CRT-VGA",
-                       .refresh        = 60,
-                       .xres           = 640,
-                       .yres           = 480,
-                       .pixclock       = 39683,
-                       .left_margin    = 45,
-                       .right_margin   = 114,
-                       .upper_margin   = 33,
-                       .lower_margin   = 11,
-                       .hsync_len      = 1,
-                       .vsync_len      = 1,
-               },
-               .bpp    = 16,
-               .pcr    = 0xFA208B80,
-       },
-};
-
-static const struct imx_fb_platform_data mx25pdk_fb_pdata __initconst = {
-       .mode           = mx25pdk_modes,
-       .num_modes      = ARRAY_SIZE(mx25pdk_modes),
-       .pwmr           = 0x00A903FF,
-       .lscr1          = 0x00120300,
-       .dmacr          = 0x00020010,
-};
-
-static const uint32_t mx25pdk_keymap[] = {
-       KEY(0, 0, KEY_UP),
-       KEY(0, 1, KEY_DOWN),
-       KEY(0, 2, KEY_VOLUMEDOWN),
-       KEY(0, 3, KEY_HOME),
-       KEY(1, 0, KEY_RIGHT),
-       KEY(1, 1, KEY_LEFT),
-       KEY(1, 2, KEY_ENTER),
-       KEY(1, 3, KEY_VOLUMEUP),
-       KEY(2, 0, KEY_F6),
-       KEY(2, 1, KEY_F8),
-       KEY(2, 2, KEY_F9),
-       KEY(2, 3, KEY_F10),
-       KEY(3, 0, KEY_F1),
-       KEY(3, 1, KEY_F2),
-       KEY(3, 2, KEY_F3),
-       KEY(3, 3, KEY_POWER),
-};
-
-static const struct matrix_keymap_data mx25pdk_keymap_data __initconst = {
-       .keymap         = mx25pdk_keymap,
-       .keymap_size    = ARRAY_SIZE(mx25pdk_keymap),
-};
-
-static int mx25pdk_usbh2_init(struct platform_device *pdev)
-{
-       return mx25_initialize_usb_hw(pdev->id, MXC_EHCI_INTERNAL_PHY);
-}
-
-static const struct mxc_usbh_platform_data usbh2_pdata __initconst = {
-       .init   = mx25pdk_usbh2_init,
-       .portsc = MXC_EHCI_MODE_SERIAL,
-};
-
-static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
-       .operating_mode = FSL_USB2_DR_DEVICE,
-       .phy_mode       = FSL_USB2_PHY_UTMI,
-};
-
-static const struct imxi2c_platform_data mx25_3ds_i2c0_data __initconst = {
-       .bitrate = 100000,
-};
-
-#define SD1_GPIO_WP    IMX_GPIO_NR(2, 0)
-#define SD1_GPIO_CD    IMX_GPIO_NR(2, 1)
-
-static const struct esdhc_platform_data mx25pdk_esdhc_pdata __initconst = {
-       .wp_gpio = SD1_GPIO_WP,
-       .cd_gpio = SD1_GPIO_CD,
-       .wp_type = ESDHC_WP_GPIO,
-       .cd_type = ESDHC_CD_GPIO,
-};
-
-static void __init mx25pdk_init(void)
-{
-       imx25_soc_init();
-
-       mxc_iomux_v3_setup_multiple_pads(mx25pdk_pads,
-                       ARRAY_SIZE(mx25pdk_pads));
-
-       imx25_add_imx_uart0(&uart_pdata);
-       imx25_add_fsl_usb2_udc(&otg_device_pdata);
-       imx25_add_mxc_ehci_hs(&usbh2_pdata);
-       imx25_add_mxc_nand(&mx25pdk_nand_board_info);
-       imx25_add_imxdi_rtc();
-       imx25_add_imx_fb(&mx25pdk_fb_pdata);
-       imx25_add_imx2_wdt();
-
-       mx25pdk_fec_reset();
-       imx25_add_fec(&mx25_fec_pdata);
-       imx25_add_imx_keypad(&mx25pdk_keymap_data);
-
-       imx25_add_sdhci_esdhc_imx(0, &mx25pdk_esdhc_pdata);
-       imx25_add_imx_i2c0(&mx25_3ds_i2c0_data);
-
-       gpio_request_one(MX25PDK_CAN_PWDN, GPIOF_OUT_INIT_LOW, "can-pwdn");
-       imx25_add_flexcan0();
-}
-
-static void __init mx25pdk_timer_init(void)
-{
-       mx25_clocks_init();
-}
-
-MACHINE_START(MX25_3DS, "Freescale MX25PDK (3DS)")
-       /* Maintainer: Freescale Semiconductor, Inc. */
-       .atag_offset = 0x100,
-       .map_io = mx25_map_io,
-       .init_early = imx25_init_early,
-       .init_irq = mx25_init_irq,
-       .init_time      = mx25pdk_timer_init,
-       .init_machine = mx25pdk_init,
-       .restart        = mxc_restart,
-MACHINE_END
index 72cd77d21f638c82f62736c75ab4d43e151277a9..7e315f00648d64122cee910af0466fad66c1550c 100644 (file)
@@ -166,7 +166,7 @@ static struct platform_device *devices[] __initdata = {
        &mx35pdk_flash,
 };
 
-static iomux_v3_cfg_t mx35pdk_pads[] = {
+static const iomux_v3_cfg_t mx35pdk_pads[] __initconst = {
        /* UART1 */
        MX35_PAD_CTS1__UART1_CTS,
        MX35_PAD_RTS1__UART1_RTS,
index b623bcaca76ca92624effb5fe780c3f67e0c89ae..e447e59c0604072ab02d5dd6c1834c8bb699b87d 100644 (file)
@@ -129,7 +129,7 @@ static struct platform_device *devices[] __initdata = {
        &pcm043_flash,
 };
 
-static iomux_v3_cfg_t pcm043_pads[] = {
+static const iomux_v3_cfg_t pcm043_pads[] __initconst = {
        /* UART1 */
        MX35_PAD_CTS1__UART1_CTS,
        MX35_PAD_RTS1__UART1_RTS,
index 97836e94451c471e50033aef17599bad80413585..27a8f7e3ec08016e16998e8472ba7aa1d1a9a457 100644 (file)
@@ -161,7 +161,7 @@ static struct i2c_board_info vpr200_i2c_devices[] = {
        }
 };
 
-static iomux_v3_cfg_t vpr200_pads[] = {
+static const iomux_v3_cfg_t vpr200_pads[] __initconst = {
        /* UART1 */
        MX35_PAD_TXD1__UART1_TXD_MUX,
        MX35_PAD_RXD1__UART1_RXD_MUX,
diff --git a/arch/arm/mach-imx/mm-imx25.c b/arch/arm/mach-imx/mm-imx25.c
deleted file mode 100644 (file)
index 5211f62..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- *  Copyright (C) 1999,2000 Arm Limited
- *  Copyright (C) 2000 Deep Blue Solutions Ltd
- *  Copyright (C) 2002 Shane Nay (shane@minirl.com)
- *  Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- *    - add MX31 specific definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU 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/mm.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/pinctrl/machine.h>
-
-#include <asm/pgtable.h>
-#include <asm/mach/map.h>
-
-#include "common.h"
-#include "devices/devices-common.h"
-#include "hardware.h"
-#include "iomux-v3.h"
-#include "mx25.h"
-
-/*
- * This table defines static virtual address mappings for I/O regions.
- * These are the mappings common across all MX25 boards.
- */
-static struct map_desc mx25_io_desc[] __initdata = {
-       imx_map_entry(MX25, AVIC, MT_DEVICE_NONSHARED),
-       imx_map_entry(MX25, AIPS1, MT_DEVICE_NONSHARED),
-       imx_map_entry(MX25, AIPS2, MT_DEVICE_NONSHARED),
-};
-
-/*
- * This function initializes the memory map. It is called during the
- * system startup to create static physical to virtual memory mappings
- * for the IO modules.
- */
-void __init mx25_map_io(void)
-{
-       iotable_init(mx25_io_desc, ARRAY_SIZE(mx25_io_desc));
-}
-
-void __init imx25_init_early(void)
-{
-       mxc_set_cpu_type(MXC_CPU_MX25);
-       mxc_iomux_v3_init(MX25_IO_ADDRESS(MX25_IOMUXC_BASE_ADDR));
-}
-
-void __init mx25_init_irq(void)
-{
-       mxc_init_irq(MX25_IO_ADDRESS(MX25_AVIC_BASE_ADDR));
-}
-
-static struct sdma_platform_data imx25_sdma_pdata __initdata = {
-       .fw_name = "sdma-imx25.bin",
-};
-
-static const struct resource imx25_audmux_res[] __initconst = {
-       DEFINE_RES_MEM(MX25_AUDMUX_BASE_ADDR, SZ_16K),
-};
-
-void __init imx25_soc_init(void)
-{
-       mxc_arch_reset_init(MX25_IO_ADDRESS(MX25_WDOG_BASE_ADDR));
-       mxc_device_init();
-
-       /* i.mx25 has the i.mx35 type gpio */
-       mxc_register_gpio("imx35-gpio", 0, MX25_GPIO1_BASE_ADDR, SZ_16K, MX25_INT_GPIO1, 0);
-       mxc_register_gpio("imx35-gpio", 1, MX25_GPIO2_BASE_ADDR, SZ_16K, MX25_INT_GPIO2, 0);
-       mxc_register_gpio("imx35-gpio", 2, MX25_GPIO3_BASE_ADDR, SZ_16K, MX25_INT_GPIO3, 0);
-       mxc_register_gpio("imx35-gpio", 3, MX25_GPIO4_BASE_ADDR, SZ_16K, MX25_INT_GPIO4, 0);
-
-       pinctrl_provide_dummies();
-       /* i.mx25 has the i.mx35 type sdma */
-       imx_add_imx_sdma("imx35-sdma", MX25_SDMA_BASE_ADDR, MX25_INT_SDMA, &imx25_sdma_pdata);
-       /* i.mx25 has the i.mx31 type audmux */
-       platform_device_register_simple("imx31-audmux", 0, imx25_audmux_res,
-                                       ARRAY_SIZE(imx25_audmux_res));
-}
diff --git a/arch/arm/mach-imx/mx25.h b/arch/arm/mach-imx/mx25.h
deleted file mode 100644 (file)
index ec46640..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-#ifndef __MACH_MX25_H__
-#define __MACH_MX25_H__
-
-#define MX25_AIPS1_BASE_ADDR           0x43f00000
-#define MX25_AIPS1_SIZE                        SZ_1M
-#define MX25_AIPS2_BASE_ADDR           0x53f00000
-#define MX25_AIPS2_SIZE                        SZ_1M
-#define MX25_AVIC_BASE_ADDR            0x68000000
-#define MX25_AVIC_SIZE                 SZ_1M
-
-#define MX25_I2C1_BASE_ADDR            (MX25_AIPS1_BASE_ADDR + 0x80000)
-#define MX25_I2C3_BASE_ADDR            (MX25_AIPS1_BASE_ADDR + 0x84000)
-#define MX25_CAN1_BASE_ADDR            (MX25_AIPS1_BASE_ADDR + 0x88000)
-#define MX25_CAN2_BASE_ADDR            (MX25_AIPS1_BASE_ADDR + 0x8c000)
-#define MX25_I2C2_BASE_ADDR            (MX25_AIPS1_BASE_ADDR + 0x98000)
-#define MX25_CSPI1_BASE_ADDR           (MX25_AIPS1_BASE_ADDR + 0xa4000)
-#define MX25_IOMUXC_BASE_ADDR          (MX25_AIPS1_BASE_ADDR + 0xac000)
-
-#define MX25_CRM_BASE_ADDR             (MX25_AIPS2_BASE_ADDR + 0x80000)
-#define MX25_GPT1_BASE_ADDR            (MX25_AIPS2_BASE_ADDR + 0x90000)
-#define MX25_GPIO4_BASE_ADDR           (MX25_AIPS2_BASE_ADDR + 0x9c000)
-#define MX25_PWM2_BASE_ADDR            (MX25_AIPS2_BASE_ADDR + 0xa0000)
-#define MX25_GPIO3_BASE_ADDR           (MX25_AIPS2_BASE_ADDR + 0xa4000)
-#define MX25_PWM3_BASE_ADDR            (MX25_AIPS2_BASE_ADDR + 0xa8000)
-#define MX25_PWM4_BASE_ADDR            (MX25_AIPS2_BASE_ADDR + 0xc8000)
-#define MX25_GPIO1_BASE_ADDR           (MX25_AIPS2_BASE_ADDR + 0xcc000)
-#define MX25_GPIO2_BASE_ADDR           (MX25_AIPS2_BASE_ADDR + 0xd0000)
-#define MX25_WDOG_BASE_ADDR            (MX25_AIPS2_BASE_ADDR + 0xdc000)
-#define MX25_PWM1_BASE_ADDR            (MX25_AIPS2_BASE_ADDR + 0xe0000)
-
-#define MX25_UART1_BASE_ADDR           0x43f90000
-#define MX25_UART2_BASE_ADDR           0x43f94000
-#define MX25_AUDMUX_BASE_ADDR          0x43fb0000
-#define MX25_UART3_BASE_ADDR           0x5000c000
-#define MX25_UART4_BASE_ADDR           0x50008000
-#define MX25_UART5_BASE_ADDR           0x5002c000
-
-#define MX25_CSPI3_BASE_ADDR           0x50004000
-#define MX25_CSPI2_BASE_ADDR           0x50010000
-#define MX25_FEC_BASE_ADDR             0x50038000
-#define MX25_SSI2_BASE_ADDR            0x50014000
-#define MX25_SSI1_BASE_ADDR            0x50034000
-#define MX25_NFC_BASE_ADDR             0xbb000000
-#define MX25_IIM_BASE_ADDR             0x53ff0000
-#define MX25_DRYICE_BASE_ADDR          0x53ffc000
-#define MX25_ESDHC1_BASE_ADDR          0x53fb4000
-#define MX25_ESDHC2_BASE_ADDR          0x53fb8000
-#define MX25_LCDC_BASE_ADDR            0x53fbc000
-#define MX25_KPP_BASE_ADDR             0x43fa8000
-#define MX25_SDMA_BASE_ADDR            0x53fd4000
-#define MX25_USB_BASE_ADDR             0x53ff4000
-#define MX25_USB_OTG_BASE_ADDR                 (MX25_USB_BASE_ADDR + 0x0000)
-/*
- * The reference manual (IMX25RM, Rev. 1, 06/2009) specifies an offset of 0x200
- * for the host controller.  Early documentation drafts specified 0x400 and
- * Freescale internal sources confirm only the latter value to work.
- */
-#define MX25_USB_HS_BASE_ADDR                  (MX25_USB_BASE_ADDR + 0x0400)
-#define MX25_CSI_BASE_ADDR             0x53ff8000
-
-#define MX25_IO_P2V(x)                 IMX_IO_P2V(x)
-#define MX25_IO_ADDRESS(x)             IOMEM(MX25_IO_P2V(x))
-
-/*
- * Interrupt numbers
- */
-#include <asm/irq.h>
-#define MX25_INT_CSPI3         (NR_IRQS_LEGACY + 0)
-#define MX25_INT_I2C1          (NR_IRQS_LEGACY + 3)
-#define MX25_INT_I2C2          (NR_IRQS_LEGACY + 4)
-#define MX25_INT_UART4         (NR_IRQS_LEGACY + 5)
-#define MX25_INT_ESDHC2                (NR_IRQS_LEGACY + 8)
-#define MX25_INT_ESDHC1                (NR_IRQS_LEGACY + 9)
-#define MX25_INT_I2C3          (NR_IRQS_LEGACY + 10)
-#define MX25_INT_SSI2          (NR_IRQS_LEGACY + 11)
-#define MX25_INT_SSI1          (NR_IRQS_LEGACY + 12)
-#define MX25_INT_CSPI2         (NR_IRQS_LEGACY + 13)
-#define MX25_INT_CSPI1         (NR_IRQS_LEGACY + 14)
-#define MX25_INT_GPIO3         (NR_IRQS_LEGACY + 16)
-#define MX25_INT_CSI           (NR_IRQS_LEGACY + 17)
-#define MX25_INT_UART3         (NR_IRQS_LEGACY + 18)
-#define MX25_INT_GPIO4         (NR_IRQS_LEGACY + 23)
-#define MX25_INT_KPP           (NR_IRQS_LEGACY + 24)
-#define MX25_INT_DRYICE                (NR_IRQS_LEGACY + 25)
-#define MX25_INT_PWM1          (NR_IRQS_LEGACY + 26)
-#define MX25_INT_UART2         (NR_IRQS_LEGACY + 32)
-#define MX25_INT_NFC           (NR_IRQS_LEGACY + 33)
-#define MX25_INT_SDMA          (NR_IRQS_LEGACY + 34)
-#define MX25_INT_USB_HS                (NR_IRQS_LEGACY + 35)
-#define MX25_INT_PWM2          (NR_IRQS_LEGACY + 36)
-#define MX25_INT_USB_OTG       (NR_IRQS_LEGACY + 37)
-#define MX25_INT_LCDC          (NR_IRQS_LEGACY + 39)
-#define MX25_INT_UART5         (NR_IRQS_LEGACY + 40)
-#define MX25_INT_PWM3          (NR_IRQS_LEGACY + 41)
-#define MX25_INT_PWM4          (NR_IRQS_LEGACY + 42)
-#define MX25_INT_CAN1          (NR_IRQS_LEGACY + 43)
-#define MX25_INT_CAN2          (NR_IRQS_LEGACY + 44)
-#define MX25_INT_UART1         (NR_IRQS_LEGACY + 45)
-#define MX25_INT_GPIO2         (NR_IRQS_LEGACY + 51)
-#define MX25_INT_GPIO1         (NR_IRQS_LEGACY + 52)
-#define MX25_INT_GPT1          (NR_IRQS_LEGACY + 54)
-#define MX25_INT_FEC           (NR_IRQS_LEGACY + 57)
-
-#define MX25_DMA_REQ_SSI2_RX1  22
-#define MX25_DMA_REQ_SSI2_TX1  23
-#define MX25_DMA_REQ_SSI2_RX0  24
-#define MX25_DMA_REQ_SSI2_TX0  25
-#define MX25_DMA_REQ_SSI1_RX1  26
-#define MX25_DMA_REQ_SSI1_TX1  27
-#define MX25_DMA_REQ_SSI1_RX0  28
-#define MX25_DMA_REQ_SSI1_TX0  29
-
-#ifndef __ASSEMBLY__
-extern int mx25_revision(void);
-#endif
-
-#endif /* ifndef __MACH_MX25_H__ */
index 46fd695203c70a22fdc4389b39161d1e6ef5a5b8..6a7c6fc780cce686650ea684d2965c30de3746df 100644 (file)
@@ -310,10 +310,12 @@ int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
         *    Low-Power mode.
         * 3) Software should mask IRQ #32 right after CCM Low-Power mode
         *    is set (set bits 0-1 of CCM_CLPCR).
+        *
+        * Note that IRQ #32 is GIC SPI #0.
         */
-       imx_gpc_hwirq_unmask(32);
+       imx_gpc_hwirq_unmask(0);
        writel_relaxed(val, ccm_base + CLPCR);
-       imx_gpc_hwirq_mask(32);
+       imx_gpc_hwirq_mask(0);
 
        return 0;
 }
index f7e463ca02877a77e956fa7e788f40779139896d..9f59e58da3a47717dfbe64c4813446b3945ba8c9 100644 (file)
@@ -1,6 +1,7 @@
 menuconfig ARCH_MEDIATEK
        bool "Mediatek MT65xx & MT81xx SoC" if ARCH_MULTI_V7
        select ARM_GIC
+       select PINCTRL
        select MTK_TIMER
        help
          Support for Mediatek MT65xx & MT81xx SoCs
index 18301dc9d2e7c2459344b4096a2187f5ae03305d..0743e2059645d876af692026d9dfd74713ba2608 100644 (file)
@@ -1,8 +1,11 @@
 menuconfig ARCH_MESON
        bool "Amlogic Meson SoCs" if ARCH_MULTI_V7
+       select ARCH_REQUIRE_GPIOLIB
        select GENERIC_IRQ_CHIP
        select ARM_GIC
        select CACHE_L2X0
+       select PINCTRL
+       select PINCTRL_MESON
 
 if ARCH_MESON
 
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
deleted file mode 100644 (file)
index a6b50e6..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-if ARCH_MSM
-
-choice
-       prompt "Qualcomm MSM SoC Type"
-       default ARCH_MSM7X00A
-       depends on ARCH_MSM
-
-config ARCH_MSM7X00A
-       bool "MSM7x00A / MSM7x01A"
-       select ARCH_MSM_ARM11
-       select CPU_V6
-       select GPIO_MSM_V1
-       select MACH_TROUT if !MACH_HALIBUT
-       select MSM_PROC_COMM
-       select MSM_SMD
-       select CLKSRC_QCOM
-       select MSM_SMD_PKG3
-
-config ARCH_MSM7X30
-       bool "MSM7x30"
-       select ARCH_MSM_SCORPION
-       select CPU_V7
-       select GPIO_MSM_V1
-       select MACH_MSM7X30_SURF # if !
-       select MSM_GPIOMUX
-       select MSM_PROC_COMM
-       select MSM_SMD
-       select CLKSRC_QCOM
-       select MSM_VIC
-
-config ARCH_QSD8X50
-       bool "QSD8X50"
-       select ARCH_MSM_SCORPION
-       select CPU_V7
-       select GPIO_MSM_V1
-       select MACH_QSD8X50_SURF if !MACH_QSD8X50A_ST1_5
-       select MSM_GPIOMUX
-       select MSM_PROC_COMM
-       select MSM_SMD
-       select CLKSRC_QCOM
-       select MSM_VIC
-
-endchoice
-
-config MSM_SOC_REV_A
-       bool
-
-config  ARCH_MSM_ARM11
-       bool
-
-config  ARCH_MSM_SCORPION
-       bool
-
-config  MSM_VIC
-       bool
-
-menu "Qualcomm MSM Board Type"
-       depends on ARCH_MSM
-
-config MACH_HALIBUT
-       depends on ARCH_MSM
-       depends on ARCH_MSM7X00A
-       bool "Halibut Board (QCT SURF7201A)"
-       help
-         Support for the Qualcomm SURF7201A eval board.
-
-config MACH_TROUT
-       depends on ARCH_MSM
-       depends on ARCH_MSM7X00A
-       bool "HTC Dream (aka trout)"
-       help
-         Support for the HTC Dream, T-Mobile G1, Android ADP1 devices.
-
-config MACH_MSM7X30_SURF
-       depends on ARCH_MSM7X30
-       bool "MSM7x30 SURF"
-       help
-         Support for the Qualcomm MSM7x30 SURF eval board.
-
-config MACH_QSD8X50_SURF
-       depends on ARCH_QSD8X50
-       bool "QSD8x50 SURF"
-       help
-         Support for the Qualcomm QSD8x50 SURF eval board.
-
-config MACH_QSD8X50A_ST1_5
-       depends on ARCH_QSD8X50
-       bool "QSD8x50A ST1.5"
-       select MSM_SOC_REV_A
-       help
-         Support for the Qualcomm ST1.5.
-
-endmenu
-
-config MSM_SMD_PKG3
-       bool
-
-config MSM_PROC_COMM
-       bool
-
-config MSM_SMD
-       bool
-
-config MSM_GPIOMUX
-       bool
-       help
-         Support for MSM V1 TLMM GPIOMUX architecture.
-
-endif
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
deleted file mode 100644 (file)
index 27c078a..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-obj-$(CONFIG_MSM_PROC_COMM) += clock.o
-
-obj-$(CONFIG_MSM_VIC) += irq-vic.o
-
-obj-$(CONFIG_ARCH_MSM7X00A) += irq.o
-obj-$(CONFIG_ARCH_QSD8X50) += sirc.o
-
-obj-$(CONFIG_MSM_PROC_COMM) += proc_comm.o clock-pcom.o vreg.o
-
-obj-$(CONFIG_ARCH_MSM7X00A) += dma.o io.o
-obj-$(CONFIG_ARCH_MSM7X30) += dma.o io.o
-obj-$(CONFIG_ARCH_QSD8X50) += dma.o io.o
-
-obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o
-obj-$(CONFIG_MSM_SMD) += last_radio_log.o
-
-obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o devices-msm7x00.o
-obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o board-trout-panel.o devices-msm7x00.o
-obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o devices-msm7x00.o
-obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30.o devices-msm7x30.o
-obj-$(CONFIG_ARCH_QSD8X50) += board-qsd8x50.o devices-qsd8x50.o
-obj-$(CONFIG_MSM_GPIOMUX) += gpiomux.o
-obj-$(CONFIG_ARCH_QSD8X50) += gpiomux-8x50.o
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
deleted file mode 100644 (file)
index 9b803a5..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-  zreladdr-y           += 0x10008000
-params_phys-y          := 0x10000100
-initrd_phys-y          := 0x10800000
diff --git a/arch/arm/mach-msm/board-halibut.c b/arch/arm/mach-msm/board-halibut.c
deleted file mode 100644 (file)
index fc83204..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/* linux/arch/arm/mach-msm/board-halibut.c
- *
- * Copyright (C) 2007 Google, Inc.
- * Author: Brian Swetland <swetland@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/input.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/smc91x.h>
-
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/flash.h>
-#include <asm/setup.h>
-
-#include <mach/irqs.h>
-#include <mach/msm_iomap.h>
-
-#include <linux/mtd/nand.h>
-#include <linux/mtd/partitions.h>
-
-#include "devices.h"
-#include "common.h"
-
-static struct resource smc91x_resources[] = {
-       [0] = {
-               .start  = 0x9C004300,
-               .end    = 0x9C004400,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = MSM_GPIO_TO_INT(49),
-               .end    = MSM_GPIO_TO_INT(49),
-               .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
-       },
-};
-
-static struct smc91x_platdata smc91x_platdata = {
-       .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT,
-};
-
-static struct platform_device smc91x_device = {
-       .name           = "smc91x",
-       .id             = 0,
-       .num_resources  = ARRAY_SIZE(smc91x_resources),
-       .resource       = smc91x_resources,
-       .dev.platform_data = &smc91x_platdata,
-};
-
-static struct platform_device *devices[] __initdata = {
-       &msm_clock_7x01a,
-       &msm_device_gpio_7201,
-       &msm_device_uart3,
-       &msm_device_smd,
-       &msm_device_nand,
-       &msm_device_hsusb,
-       &msm_device_i2c,
-       &smc91x_device,
-};
-
-static void __init halibut_init_early(void)
-{
-       arch_ioremap_caller = __msm_ioremap_caller;
-}
-
-static void __init halibut_init_irq(void)
-{
-       msm_init_irq();
-}
-
-static void __init halibut_init(void)
-{
-       platform_add_devices(devices, ARRAY_SIZE(devices));
-}
-
-static void __init halibut_map_io(void)
-{
-       msm_map_common_io();
-}
-
-static void __init halibut_init_late(void)
-{
-       smd_debugfs_init();
-}
-
-MACHINE_START(HALIBUT, "Halibut Board (QCT SURF7200A)")
-       .atag_offset    = 0x100,
-       .map_io         = halibut_map_io,
-       .init_early     = halibut_init_early,
-       .init_irq       = halibut_init_irq,
-       .init_machine   = halibut_init,
-       .init_late      = halibut_init_late,
-       .init_time      = msm7x01_timer_init,
-MACHINE_END
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
deleted file mode 100644 (file)
index 8f5ecdc..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only 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 Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-#include <linux/gpio.h>
-#include <linux/kernel.h>
-#include <linux/irq.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/smsc911x.h>
-#include <linux/usb/msm_hsusb.h>
-#include <linux/clkdev.h>
-#include <linux/memblock.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/memory.h>
-#include <asm/setup.h>
-
-#include <mach/clk.h>
-#include <mach/msm_iomap.h>
-#include <mach/dma.h>
-
-#include <mach/vreg.h>
-#include "devices.h"
-#include "gpiomux.h"
-#include "proc_comm.h"
-#include "common.h"
-
-static void __init msm7x30_fixup(struct tag *tag, char **cmdline)
-{
-       for (; tag->hdr.size; tag = tag_next(tag))
-               if (tag->hdr.tag == ATAG_MEM && tag->u.mem.start == 0x200000) {
-                       tag->u.mem.start = 0;
-                       tag->u.mem.size += SZ_2M;
-               }
-}
-
-static void __init msm7x30_reserve(void)
-{
-       memblock_remove(0x0, SZ_2M);
-}
-
-static int hsusb_phy_init_seq[] = {
-       0x30, 0x32,     /* Enable and set Pre-Emphasis Depth to 20% */
-       0x02, 0x36,     /* Disable CDR Auto Reset feature */
-       -1
-};
-
-static int hsusb_link_clk_reset(struct clk *link_clk, bool assert)
-{
-       int ret;
-
-       if (assert) {
-               ret = clk_reset(link_clk, CLK_RESET_ASSERT);
-               if (ret)
-                       pr_err("usb hs_clk assert failed\n");
-       } else {
-               ret = clk_reset(link_clk, CLK_RESET_DEASSERT);
-               if (ret)
-                       pr_err("usb hs_clk deassert failed\n");
-       }
-       return ret;
-}
-
-static int hsusb_phy_clk_reset(struct clk *phy_clk)
-{
-       int ret;
-
-       ret = clk_reset(phy_clk, CLK_RESET_ASSERT);
-       if (ret) {
-               pr_err("usb phy clk assert failed\n");
-               return ret;
-       }
-       usleep_range(10000, 12000);
-       ret = clk_reset(phy_clk, CLK_RESET_DEASSERT);
-       if (ret)
-               pr_err("usb phy clk deassert failed\n");
-       return ret;
-}
-
-static struct msm_otg_platform_data msm_otg_pdata = {
-       .phy_init_seq           = hsusb_phy_init_seq,
-       .mode                   = USB_DR_MODE_PERIPHERAL,
-       .otg_control            = OTG_PHY_CONTROL,
-       .link_clk_reset         = hsusb_link_clk_reset,
-       .phy_clk_reset          = hsusb_phy_clk_reset,
-};
-
-struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {
-#ifdef CONFIG_SERIAL_MSM_CONSOLE
-       [49] = { /* UART2 RFR */
-               .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
-                            GPIOMUX_FUNC_2 | GPIOMUX_VALID,
-       },
-       [50] = { /* UART2 CTS */
-               .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
-                            GPIOMUX_FUNC_2 | GPIOMUX_VALID,
-       },
-       [51] = { /* UART2 RX */
-               .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
-                            GPIOMUX_FUNC_2 | GPIOMUX_VALID,
-       },
-       [52] = { /* UART2 TX */
-               .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
-                            GPIOMUX_FUNC_2 | GPIOMUX_VALID,
-       },
-#endif
-};
-
-static struct platform_device *devices[] __initdata = {
-       &msm_clock_7x30,
-       &msm_device_gpio_7x30,
-#if defined(CONFIG_SERIAL_MSM)
-        &msm_device_uart2,
-#endif
-       &msm_device_smd,
-       &msm_device_otg,
-       &msm_device_hsusb,
-       &msm_device_hsusb_host,
-};
-
-static void __init msm7x30_init_irq(void)
-{
-       msm_init_irq();
-}
-
-static void __init msm7x30_init(void)
-{
-       msm_device_otg.dev.platform_data = &msm_otg_pdata;
-       msm_device_hsusb.dev.parent = &msm_device_otg.dev;
-       msm_device_hsusb_host.dev.parent = &msm_device_otg.dev;
-
-       platform_add_devices(devices, ARRAY_SIZE(devices));
-}
-
-static void __init msm7x30_map_io(void)
-{
-       msm_map_msm7x30_io();
-}
-
-static void __init msm7x30_init_late(void)
-{
-       smd_debugfs_init();
-}
-
-MACHINE_START(MSM7X30_SURF, "QCT MSM7X30 SURF")
-       .atag_offset = 0x100,
-       .fixup = msm7x30_fixup,
-       .reserve = msm7x30_reserve,
-       .map_io = msm7x30_map_io,
-       .init_irq = msm7x30_init_irq,
-       .init_machine = msm7x30_init,
-       .init_late = msm7x30_init_late,
-       .init_time      = msm7x30_timer_init,
-MACHINE_END
-
-MACHINE_START(MSM7X30_FFA, "QCT MSM7X30 FFA")
-       .atag_offset = 0x100,
-       .fixup = msm7x30_fixup,
-       .reserve = msm7x30_reserve,
-       .map_io = msm7x30_map_io,
-       .init_irq = msm7x30_init_irq,
-       .init_machine = msm7x30_init,
-       .init_late = msm7x30_init_late,
-       .init_time      = msm7x30_timer_init,
-MACHINE_END
-
-MACHINE_START(MSM7X30_FLUID, "QCT MSM7X30 FLUID")
-       .atag_offset = 0x100,
-       .fixup = msm7x30_fixup,
-       .reserve = msm7x30_reserve,
-       .map_io = msm7x30_map_io,
-       .init_irq = msm7x30_init_irq,
-       .init_machine = msm7x30_init,
-       .init_late = msm7x30_init_late,
-       .init_time      = msm7x30_timer_init,
-MACHINE_END
diff --git a/arch/arm/mach-msm/board-qsd8x50.c b/arch/arm/mach-msm/board-qsd8x50.c
deleted file mode 100644 (file)
index 10016a3..0000000
+++ /dev/null
@@ -1,254 +0,0 @@
-/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only 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 Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-#include <linux/gpio.h>
-#include <linux/kernel.h>
-#include <linux/irq.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/usb/msm_hsusb.h>
-#include <linux/err.h>
-#include <linux/clkdev.h>
-#include <linux/smc91x.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/io.h>
-#include <asm/setup.h>
-
-#include <mach/irqs.h>
-#include <mach/sirc.h>
-#include <mach/vreg.h>
-#include <mach/clk.h>
-#include <linux/platform_data/mmc-msm_sdcc.h>
-
-#include "devices.h"
-#include "common.h"
-
-static const resource_size_t qsd8x50_surf_smc91x_base __initconst = 0x70000300;
-static const unsigned        qsd8x50_surf_smc91x_gpio __initconst = 156;
-
-/* Leave smc91x resources empty here, as we'll fill them in
- * at run-time: they vary from board to board, and the true
- * configuration won't be known until boot.
- */
-static struct resource smc91x_resources[] = {
-       [0] = {
-               .flags = IORESOURCE_MEM,
-       },
-       [1] = {
-               .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
-       },
-};
-
-static struct smc91x_platdata smc91x_platdata = {
-       .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT,
-};
-
-static struct platform_device smc91x_device = {
-       .name           = "smc91x",
-       .id             = 0,
-       .num_resources  = ARRAY_SIZE(smc91x_resources),
-       .resource       = smc91x_resources,
-       .dev.platform_data = &smc91x_platdata,
-};
-
-static int __init msm_init_smc91x(void)
-{
-       if (machine_is_qsd8x50_surf()) {
-               smc91x_resources[0].start = qsd8x50_surf_smc91x_base;
-               smc91x_resources[0].end   = qsd8x50_surf_smc91x_base + 0xff;
-               smc91x_resources[1].start =
-                       gpio_to_irq(qsd8x50_surf_smc91x_gpio);
-               smc91x_resources[1].end   =
-                       gpio_to_irq(qsd8x50_surf_smc91x_gpio);
-               platform_device_register(&smc91x_device);
-       }
-
-       return 0;
-}
-module_init(msm_init_smc91x);
-
-static int hsusb_phy_init_seq[] = {
-       0x08, 0x31,     /* Increase HS Driver Amplitude */
-       0x20, 0x32,     /* Enable and set Pre-Emphasis Depth to 10% */
-       -1
-};
-
-static int hsusb_link_clk_reset(struct clk *link_clk, bool assert)
-{
-       int ret;
-
-       if (assert) {
-               ret = clk_reset(link_clk, CLK_RESET_ASSERT);
-               if (ret)
-                       pr_err("usb hs_clk assert failed\n");
-       } else {
-               ret = clk_reset(link_clk, CLK_RESET_DEASSERT);
-               if (ret)
-                       pr_err("usb hs_clk deassert failed\n");
-       }
-       return ret;
-}
-
-static int hsusb_phy_clk_reset(struct clk *phy_clk)
-{
-       int ret;
-
-       ret = clk_reset(phy_clk, CLK_RESET_ASSERT);
-       if (ret) {
-               pr_err("usb phy clk assert failed\n");
-               return ret;
-       }
-       usleep_range(10000, 12000);
-       ret = clk_reset(phy_clk, CLK_RESET_DEASSERT);
-       if (ret)
-               pr_err("usb phy clk deassert failed\n");
-       return ret;
-}
-
-static struct msm_otg_platform_data msm_otg_pdata = {
-       .phy_init_seq           = hsusb_phy_init_seq,
-       .mode                   = USB_DR_MODE_PERIPHERAL,
-       .otg_control            = OTG_PHY_CONTROL,
-       .link_clk_reset         = hsusb_link_clk_reset,
-       .phy_clk_reset          = hsusb_phy_clk_reset,
-};
-
-static struct platform_device *devices[] __initdata = {
-       &msm_clock_8x50,
-       &msm_device_gpio_8x50,
-       &msm_device_uart3,
-       &msm_device_smd,
-       &msm_device_otg,
-       &msm_device_hsusb,
-       &msm_device_hsusb_host,
-};
-
-static struct msm_mmc_gpio sdc1_gpio_cfg[] = {
-       {51, "sdc1_dat_3"},
-       {52, "sdc1_dat_2"},
-       {53, "sdc1_dat_1"},
-       {54, "sdc1_dat_0"},
-       {55, "sdc1_cmd"},
-       {56, "sdc1_clk"}
-};
-
-static struct vreg *vreg_mmc;
-static unsigned long vreg_sts;
-
-static uint32_t msm_sdcc_setup_power(struct device *dv, unsigned int vdd)
-{
-       int rc = 0;
-       struct platform_device *pdev;
-
-       pdev = container_of(dv, struct platform_device, dev);
-
-       if (vdd == 0) {
-               if (!vreg_sts)
-                       return 0;
-
-               clear_bit(pdev->id, &vreg_sts);
-
-               if (!vreg_sts) {
-                       rc = vreg_disable(vreg_mmc);
-                       if (rc)
-                               pr_err("vreg_mmc disable failed for slot "
-                                               "%d: %d\n", pdev->id, rc);
-               }
-               return 0;
-       }
-
-       if (!vreg_sts) {
-               rc = vreg_set_level(vreg_mmc, 2900);
-               if (rc)
-                       pr_err("vreg_mmc set level failed for slot %d: %d\n",
-                                       pdev->id, rc);
-               rc = vreg_enable(vreg_mmc);
-               if (rc)
-                       pr_err("vreg_mmc enable failed for slot %d: %d\n",
-                                       pdev->id, rc);
-       }
-       set_bit(pdev->id, &vreg_sts);
-       return 0;
-}
-
-static struct msm_mmc_gpio_data sdc1_gpio = {
-       .gpio = sdc1_gpio_cfg,
-       .size = ARRAY_SIZE(sdc1_gpio_cfg),
-};
-
-static struct msm_mmc_platform_data qsd8x50_sdc1_data = {
-       .ocr_mask       = MMC_VDD_27_28 | MMC_VDD_28_29,
-       .translate_vdd  = msm_sdcc_setup_power,
-       .gpio_data = &sdc1_gpio,
-};
-
-static void __init qsd8x50_init_mmc(void)
-{
-       vreg_mmc = vreg_get(NULL, "gp5");
-
-       if (IS_ERR(vreg_mmc)) {
-               pr_err("vreg get for vreg_mmc failed (%ld)\n",
-                               PTR_ERR(vreg_mmc));
-               return;
-       }
-
-       msm_add_sdcc(1, &qsd8x50_sdc1_data, 0, 0);
-}
-
-static void __init qsd8x50_map_io(void)
-{
-       msm_map_qsd8x50_io();
-}
-
-static void __init qsd8x50_init_irq(void)
-{
-       msm_init_irq();
-       msm_init_sirc();
-}
-
-static void __init qsd8x50_init(void)
-{
-       msm_device_otg.dev.platform_data = &msm_otg_pdata;
-       msm_device_hsusb.dev.parent = &msm_device_otg.dev;
-       msm_device_hsusb_host.dev.parent = &msm_device_otg.dev;
-       platform_add_devices(devices, ARRAY_SIZE(devices));
-       qsd8x50_init_mmc();
-}
-
-static void __init qsd8x50_init_late(void)
-{
-       smd_debugfs_init();
-}
-
-MACHINE_START(QSD8X50_SURF, "QCT QSD8X50 SURF")
-       .atag_offset = 0x100,
-       .map_io = qsd8x50_map_io,
-       .init_irq = qsd8x50_init_irq,
-       .init_machine = qsd8x50_init,
-       .init_late = qsd8x50_init_late,
-       .init_time      = qsd8x50_timer_init,
-MACHINE_END
-
-MACHINE_START(QSD8X50A_ST1_5, "QCT QSD8X50A ST1.5")
-       .atag_offset = 0x100,
-       .map_io = qsd8x50_map_io,
-       .init_irq = qsd8x50_init_irq,
-       .init_machine = qsd8x50_init,
-       .init_late = qsd8x50_init_late,
-       .init_time      = qsd8x50_timer_init,
-MACHINE_END
diff --git a/arch/arm/mach-msm/board-sapphire.c b/arch/arm/mach-msm/board-sapphire.c
deleted file mode 100644 (file)
index e509679..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-/* linux/arch/arm/mach-msm/board-sapphire.c
- * Copyright (C) 2007-2009 HTC Corporation.
- * Author: Thomas Tsai <thomas_tsai@htc.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
-*/
-#include <linux/gpio.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/input.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/device.h>
-
-#include <linux/delay.h>
-
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/flash.h>
-#include <mach/vreg.h>
-
-#include <asm/io.h>
-#include <asm/delay.h>
-#include <asm/setup.h>
-
-#include <linux/mtd/nand.h>
-#include <linux/mtd/partitions.h>
-#include <linux/memblock.h>
-
-#include "gpio_chip.h"
-#include "board-sapphire.h"
-#include "proc_comm.h"
-#include "devices.h"
-#include "common.h"
-
-void msm_init_irq(void);
-void msm_init_gpio(void);
-
-static struct platform_device *devices[] __initdata = {
-       &msm_device_smd,
-       &msm_device_dmov,
-       &msm_device_nand,
-       &msm_device_uart1,
-       &msm_device_uart3,
-};
-
-void msm_timer_init(void);
-
-static void __init sapphire_init_irq(void)
-{
-       msm_init_irq();
-}
-
-static void __init sapphire_init(void)
-{
-       platform_add_devices(devices, ARRAY_SIZE(devices));
-}
-
-static struct map_desc sapphire_io_desc[] __initdata = {
-       {
-               .virtual = SAPPHIRE_CPLD_BASE,
-               .pfn     = __phys_to_pfn(SAPPHIRE_CPLD_START),
-               .length  = SAPPHIRE_CPLD_SIZE,
-               .type    = MT_DEVICE_NONSHARED
-       }
-};
-
-static void __init sapphire_fixup(struct tag *tags, char **cmdline)
-{
-       int smi_sz = parse_tag_smi((const struct tag *)tags);
-
-       if (smi_sz == 32) {
-               memblock_add(PHYS_OFFSET, 84*SZ_1M);
-       } else if (smi_sz == 64) {
-               memblock_add(PHYS_OFFSET, 101*SZ_1M);
-       } else {
-               memblock_add(PHYS_OFFSET, 101*SZ_1M);
-               /* Give a default value when not get smi size */
-               smi_sz = 64;
-       }
-}
-
-static void __init sapphire_map_io(void)
-{
-       msm_map_common_io();
-       iotable_init(sapphire_io_desc, ARRAY_SIZE(sapphire_io_desc));
-       msm_clock_init();
-}
-
-static void __init sapphire_init_late(void)
-{
-       smd_debugfs_init();
-}
-
-MACHINE_START(SAPPHIRE, "sapphire")
-/* Maintainer: Brian Swetland <swetland@google.com> */
-       .atag_offset    = 0x100,
-       .fixup          = sapphire_fixup,
-       .map_io         = sapphire_map_io,
-       .init_irq       = sapphire_init_irq,
-       .init_machine   = sapphire_init,
-       .init_late      = sapphire_init_late,
-       .init_time      = msm_timer_init,
-MACHINE_END
diff --git a/arch/arm/mach-msm/board-trout-gpio.c b/arch/arm/mach-msm/board-trout-gpio.c
deleted file mode 100644 (file)
index 722ad63..0000000
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * linux/arch/arm/mach-msm/gpio.c
- *
- * Copyright (C) 2005 HP Labs
- * Copyright (C) 2008 Google, Inc.
- * Copyright (C) 2009 Pavel Machek <pavel@ucw.cz>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/gpio.h>
-
-#include "board-trout.h"
-
-static uint8_t trout_int_mask[2] = {
-       [0] = 0xff, /* mask all interrupts */
-       [1] = 0xff,
-};
-static uint8_t trout_sleep_int_mask[] = {
-       [0] = 0xff,
-       [1] = 0xff,
-};
-
-struct msm_gpio_chip {
-       struct gpio_chip        chip;
-       void __iomem            *reg;   /* Base of register bank */
-       u8                      shadow;
-};
-
-#define to_msm_gpio_chip(c) container_of(c, struct msm_gpio_chip, chip)
-
-static int msm_gpiolib_get(struct gpio_chip *chip, unsigned offset)
-{
-       struct msm_gpio_chip *msm_gpio = to_msm_gpio_chip(chip);
-       unsigned mask = 1 << offset;
-
-       return !!(readb(msm_gpio->reg) & mask);
-}
-
-static void msm_gpiolib_set(struct gpio_chip *chip, unsigned offset, int val)
-{
-       struct msm_gpio_chip *msm_gpio = to_msm_gpio_chip(chip);
-       unsigned mask = 1 << offset;
-
-       if (val)
-               msm_gpio->shadow |= mask;
-       else
-               msm_gpio->shadow &= ~mask;
-
-       writeb(msm_gpio->shadow, msm_gpio->reg);
-}
-
-static int msm_gpiolib_direction_input(struct gpio_chip *chip,
-                                       unsigned offset)
-{
-       msm_gpiolib_set(chip, offset, 0);
-       return 0;
-}
-
-static int msm_gpiolib_direction_output(struct gpio_chip *chip,
-                                        unsigned offset, int val)
-{
-       msm_gpiolib_set(chip, offset, val);
-       return 0;
-}
-
-static int trout_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-       return TROUT_GPIO_TO_INT(offset + chip->base);
-}
-
-#define TROUT_GPIO_BANK(name, reg_num, base_gpio, shadow_val)          \
-       {                                                               \
-               .chip = {                                               \
-                       .label            = name,                       \
-                       .direction_input  = msm_gpiolib_direction_input,\
-                       .direction_output = msm_gpiolib_direction_output, \
-                       .get              = msm_gpiolib_get,            \
-                       .set              = msm_gpiolib_set,            \
-                       .to_irq           = trout_gpio_to_irq,          \
-                       .base             = base_gpio,                  \
-                       .ngpio            = 8,                          \
-               },                                                      \
-               .reg = reg_num + TROUT_CPLD_BASE,                       \
-               .shadow = shadow_val,                                   \
-       }
-
-static struct msm_gpio_chip msm_gpio_banks[] = {
-#if defined(CONFIG_DEBUG_MSM_UART) && (CONFIG_DEBUG_UART_PHYS == 0xa9a00000)
-       /* H2W pins <-> UART1 */
-       TROUT_GPIO_BANK("MISC2", 0x00,   TROUT_GPIO_MISC2_BASE, 0x40),
-#else
-       /* H2W pins <-> UART3, Bluetooth <-> UART1 */
-       TROUT_GPIO_BANK("MISC2", 0x00,   TROUT_GPIO_MISC2_BASE, 0x80),
-#endif
-       /* I2C pull */
-       TROUT_GPIO_BANK("MISC3", 0x02,   TROUT_GPIO_MISC3_BASE, 0x04),
-       TROUT_GPIO_BANK("MISC4", 0x04,   TROUT_GPIO_MISC4_BASE, 0),
-       /* mmdi 32k en */
-       TROUT_GPIO_BANK("MISC5", 0x06,   TROUT_GPIO_MISC5_BASE, 0x04),
-       TROUT_GPIO_BANK("INT2", 0x08,    TROUT_GPIO_INT2_BASE,  0),
-       TROUT_GPIO_BANK("MISC1", 0x0a,   TROUT_GPIO_MISC1_BASE, 0),
-       TROUT_GPIO_BANK("VIRTUAL", 0x12, TROUT_GPIO_VIRTUAL_BASE, 0),
-};
-
-static void trout_gpio_irq_ack(struct irq_data *d)
-{
-       int bank = TROUT_INT_TO_BANK(d->irq);
-       uint8_t mask = TROUT_INT_TO_MASK(d->irq);
-       int reg = TROUT_BANK_TO_STAT_REG(bank);
-       /*printk(KERN_INFO "trout_gpio_irq_ack irq %d\n", d->irq);*/
-       writeb(mask, TROUT_CPLD_BASE + reg);
-}
-
-static void trout_gpio_irq_mask(struct irq_data *d)
-{
-       unsigned long flags;
-       uint8_t reg_val;
-       int bank = TROUT_INT_TO_BANK(d->irq);
-       uint8_t mask = TROUT_INT_TO_MASK(d->irq);
-       int reg = TROUT_BANK_TO_MASK_REG(bank);
-
-       local_irq_save(flags);
-       reg_val = trout_int_mask[bank] |= mask;
-       /*printk(KERN_INFO "trout_gpio_irq_mask irq %d => %d:%02x\n",
-              d->irq, bank, reg_val);*/
-       writeb(reg_val, TROUT_CPLD_BASE + reg);
-       local_irq_restore(flags);
-}
-
-static void trout_gpio_irq_unmask(struct irq_data *d)
-{
-       unsigned long flags;
-       uint8_t reg_val;
-       int bank = TROUT_INT_TO_BANK(d->irq);
-       uint8_t mask = TROUT_INT_TO_MASK(d->irq);
-       int reg = TROUT_BANK_TO_MASK_REG(bank);
-
-       local_irq_save(flags);
-       reg_val = trout_int_mask[bank] &= ~mask;
-       /*printk(KERN_INFO "trout_gpio_irq_unmask irq %d => %d:%02x\n",
-              d->irq, bank, reg_val);*/
-       writeb(reg_val, TROUT_CPLD_BASE + reg);
-       local_irq_restore(flags);
-}
-
-int trout_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
-{
-       unsigned long flags;
-       int bank = TROUT_INT_TO_BANK(d->irq);
-       uint8_t mask = TROUT_INT_TO_MASK(d->irq);
-
-       local_irq_save(flags);
-       if(on)
-               trout_sleep_int_mask[bank] &= ~mask;
-       else
-               trout_sleep_int_mask[bank] |= mask;
-       local_irq_restore(flags);
-       return 0;
-}
-
-static void trout_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
-{
-       int j, m;
-       unsigned v;
-       int bank;
-       int stat_reg;
-       int int_base = TROUT_INT_START;
-       uint8_t int_mask;
-
-       for (bank = 0; bank < 2; bank++) {
-               stat_reg = TROUT_BANK_TO_STAT_REG(bank);
-               v = readb(TROUT_CPLD_BASE + stat_reg);
-               int_mask = trout_int_mask[bank];
-               if (v & int_mask) {
-                       writeb(v & int_mask, TROUT_CPLD_BASE + stat_reg);
-                       printk(KERN_ERR "trout_gpio_irq_handler: got masked "
-                              "interrupt: %d:%02x\n", bank, v & int_mask);
-               }
-               v &= ~int_mask;
-               while (v) {
-                       m = v & -v;
-                       j = fls(m) - 1;
-                       /*printk(KERN_INFO "msm_gpio_irq_handler %d:%02x %02x b"
-                              "it %d irq %d\n", bank, v, m, j, int_base + j);*/
-                       v &= ~m;
-                       generic_handle_irq(int_base + j);
-               }
-               int_base += TROUT_INT_BANK0_COUNT;
-       }
-       desc->irq_data.chip->irq_ack(&desc->irq_data);
-}
-
-static struct irq_chip trout_gpio_irq_chip = {
-       .name          = "troutgpio",
-       .irq_ack       = trout_gpio_irq_ack,
-       .irq_mask      = trout_gpio_irq_mask,
-       .irq_unmask    = trout_gpio_irq_unmask,
-       .irq_set_wake  = trout_gpio_irq_set_wake,
-};
-
-/*
- * Called from the processor-specific init to enable GPIO pin support.
- */
-int __init trout_init_gpio(void)
-{
-       int i;
-       for(i = TROUT_INT_START; i <= TROUT_INT_END; i++) {
-               irq_set_chip_and_handler(i, &trout_gpio_irq_chip,
-                                        handle_edge_irq);
-               set_irq_flags(i, IRQF_VALID);
-       }
-
-       for (i = 0; i < ARRAY_SIZE(msm_gpio_banks); i++)
-               gpiochip_add(&msm_gpio_banks[i].chip);
-
-       irq_set_irq_type(MSM_GPIO_TO_INT(17), IRQF_TRIGGER_HIGH);
-       irq_set_chained_handler(MSM_GPIO_TO_INT(17), trout_gpio_irq_handler);
-       irq_set_irq_wake(MSM_GPIO_TO_INT(17), 1);
-
-       return 0;
-}
-
-postcore_initcall(trout_init_gpio);
-
diff --git a/arch/arm/mach-msm/board-trout-mmc.c b/arch/arm/mach-msm/board-trout-mmc.c
deleted file mode 100644 (file)
index 3723e55..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-/* linux/arch/arm/mach-msm/board-trout-mmc.c
-** Author: Brian Swetland <swetland@google.com>
-*/
-#include <linux/gpio.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/sdio_ids.h>
-#include <linux/err.h>
-#include <linux/debugfs.h>
-
-#include <asm/io.h>
-
-#include <mach/vreg.h>
-
-#include <linux/platform_data/mmc-msm_sdcc.h>
-
-#include "devices.h"
-
-#include "board-trout.h"
-
-#include "proc_comm.h"
-
-#define DEBUG_SDSLOT_VDD 1
-
-/* ---- COMMON ---- */
-static void config_gpio_table(uint32_t *table, int len)
-{
-       int n;
-       unsigned id;
-       for(n = 0; n < len; n++) {
-               id = table[n];
-               msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX, &id, 0);
-       }
-}
-
-/* ---- SDCARD ---- */
-
-static uint32_t sdcard_on_gpio_table[] = {
-       PCOM_GPIO_CFG(62, 2, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_8MA), /* CLK */
-       PCOM_GPIO_CFG(63, 2, GPIO_OUTPUT, GPIO_PULL_UP, GPIO_8MA), /* CMD */
-       PCOM_GPIO_CFG(64, 2, GPIO_OUTPUT, GPIO_PULL_UP, GPIO_8MA), /* DAT3 */
-       PCOM_GPIO_CFG(65, 2, GPIO_OUTPUT, GPIO_PULL_UP, GPIO_8MA), /* DAT2 */
-       PCOM_GPIO_CFG(66, 2, GPIO_OUTPUT, GPIO_PULL_UP, GPIO_4MA), /* DAT1 */
-       PCOM_GPIO_CFG(67, 2, GPIO_OUTPUT, GPIO_PULL_UP, GPIO_4MA), /* DAT0 */
-};
-
-static uint32_t sdcard_off_gpio_table[] = {
-       PCOM_GPIO_CFG(62, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_4MA), /* CLK */
-       PCOM_GPIO_CFG(63, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_4MA), /* CMD */
-       PCOM_GPIO_CFG(64, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_4MA), /* DAT3 */
-       PCOM_GPIO_CFG(65, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_4MA), /* DAT2 */
-       PCOM_GPIO_CFG(66, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_4MA), /* DAT1 */
-       PCOM_GPIO_CFG(67, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_4MA), /* DAT0 */
-};
-
-static uint opt_disable_sdcard;
-
-static int __init trout_disablesdcard_setup(char *str)
-{
-       int cal = simple_strtol(str, NULL, 0);
-       
-       opt_disable_sdcard = cal;
-       return 1;
-}
-
-__setup("board_trout.disable_sdcard=", trout_disablesdcard_setup);
-
-static struct vreg *vreg_sdslot;       /* SD slot power */
-
-struct mmc_vdd_xlat {
-       int mask;
-       int level;
-};
-
-static struct mmc_vdd_xlat mmc_vdd_table[] = {
-       { MMC_VDD_165_195,      1800 },
-       { MMC_VDD_20_21,        2050 },
-       { MMC_VDD_21_22,        2150 },
-       { MMC_VDD_22_23,        2250 },
-       { MMC_VDD_23_24,        2350 },
-       { MMC_VDD_24_25,        2450 },
-       { MMC_VDD_25_26,        2550 },
-       { MMC_VDD_26_27,        2650 },
-       { MMC_VDD_27_28,        2750 },
-       { MMC_VDD_28_29,        2850 },
-       { MMC_VDD_29_30,        2950 },
-};
-
-static unsigned int sdslot_vdd = 0xffffffff;
-static unsigned int sdslot_vreg_enabled;
-
-static uint32_t trout_sdslot_switchvdd(struct device *dev, unsigned int vdd)
-{
-       int i, rc;
-
-       BUG_ON(!vreg_sdslot);
-
-       if (vdd == sdslot_vdd)
-               return 0;
-
-       sdslot_vdd = vdd;
-
-       if (vdd == 0) {
-#if DEBUG_SDSLOT_VDD
-               printk("%s: Disabling SD slot power\n", __func__);
-#endif
-               config_gpio_table(sdcard_off_gpio_table,
-                                 ARRAY_SIZE(sdcard_off_gpio_table));
-               vreg_disable(vreg_sdslot);
-               sdslot_vreg_enabled = 0;
-               return 0;
-       }
-
-       if (!sdslot_vreg_enabled) {
-               rc = vreg_enable(vreg_sdslot);
-               if (rc) {
-                       printk(KERN_ERR "%s: Error enabling vreg (%d)\n",
-                              __func__, rc);
-               }
-               config_gpio_table(sdcard_on_gpio_table,
-                                 ARRAY_SIZE(sdcard_on_gpio_table));
-               sdslot_vreg_enabled = 1;
-       }
-
-       for (i = 0; i < ARRAY_SIZE(mmc_vdd_table); i++) {
-               if (mmc_vdd_table[i].mask == (1 << vdd)) {
-#if DEBUG_SDSLOT_VDD
-                       printk("%s: Setting level to %u\n",
-                               __func__, mmc_vdd_table[i].level);
-#endif
-                       rc = vreg_set_level(vreg_sdslot,
-                                           mmc_vdd_table[i].level);
-                       if (rc) {
-                               printk(KERN_ERR
-                                      "%s: Error setting vreg level (%d)\n",
-                                      __func__, rc);
-                       }
-                       return 0;
-               }
-       }
-
-       printk(KERN_ERR "%s: Invalid VDD %d specified\n", __func__, vdd);
-       return 0;
-}
-
-static unsigned int trout_sdslot_status(struct device *dev)
-{
-       unsigned int status;
-
-       status = (unsigned int) gpio_get_value(TROUT_GPIO_SDMC_CD_N);
-       return (!status);
-}
-
-#define TROUT_MMC_VDD  MMC_VDD_165_195 | MMC_VDD_20_21 | MMC_VDD_21_22 \
-                       | MMC_VDD_22_23 | MMC_VDD_23_24 | MMC_VDD_24_25 \
-                       | MMC_VDD_25_26 | MMC_VDD_26_27 | MMC_VDD_27_28 \
-                       | MMC_VDD_28_29 | MMC_VDD_29_30
-
-static struct msm_mmc_platform_data trout_sdslot_data = {
-       .ocr_mask       = TROUT_MMC_VDD,
-       .status         = trout_sdslot_status,
-       .translate_vdd  = trout_sdslot_switchvdd,
-};
-
-int __init trout_init_mmc(unsigned int sys_rev)
-{
-       sdslot_vreg_enabled = 0;
-
-       vreg_sdslot = vreg_get(0, "gp6");
-       if (IS_ERR(vreg_sdslot))
-               return PTR_ERR(vreg_sdslot);
-
-       irq_set_irq_wake(TROUT_GPIO_TO_INT(TROUT_GPIO_SDMC_CD_N), 1);
-
-       if (!opt_disable_sdcard)
-               msm_add_sdcc(2, &trout_sdslot_data,
-                            TROUT_GPIO_TO_INT(TROUT_GPIO_SDMC_CD_N), 0);
-       else
-               printk(KERN_INFO "trout: SD-Card interface disabled\n");
-       return 0;
-}
-
diff --git a/arch/arm/mach-msm/board-trout-panel.c b/arch/arm/mach-msm/board-trout-panel.c
deleted file mode 100644 (file)
index 77b0a26..0000000
+++ /dev/null
@@ -1,292 +0,0 @@
-/* linux/arch/arm/mach-msm/board-trout-mddi.c
-** Author: Brian Swetland <swetland@google.com>
-*/
-#include <linux/gpio.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/leds.h>
-#include <linux/err.h>
-
-#include <asm/io.h>
-#include <asm/mach-types.h>
-#include <asm/system_info.h>
-
-#include <linux/platform_data/video-msm_fb.h>
-#include <mach/vreg.h>
-
-#include "board-trout.h"
-#include "proc_comm.h"
-#include "clock-pcom.h"
-#include "devices.h"
-
-#define TROUT_DEFAULT_BACKLIGHT_BRIGHTNESS 255
-
-#define MDDI_CLIENT_CORE_BASE  0x108000
-#define LCD_CONTROL_BLOCK_BASE 0x110000
-#define SPI_BLOCK_BASE         0x120000
-#define I2C_BLOCK_BASE         0x130000
-#define PWM_BLOCK_BASE         0x140000
-#define GPIO_BLOCK_BASE        0x150000
-#define SYSTEM_BLOCK1_BASE     0x160000
-#define SYSTEM_BLOCK2_BASE     0x170000
-
-
-#define        DPSUS       (MDDI_CLIENT_CORE_BASE|0x24)
-#define        SYSCLKENA   (MDDI_CLIENT_CORE_BASE|0x2C)
-#define        PWM0OFF       (PWM_BLOCK_BASE|0x1C)
-
-#define V_VDDE2E_VDD2_GPIO 0
-#define MDDI_RST_N 82
-
-#define        MDDICAP0    (MDDI_CLIENT_CORE_BASE|0x00)
-#define        MDDICAP1    (MDDI_CLIENT_CORE_BASE|0x04)
-#define        MDDICAP2    (MDDI_CLIENT_CORE_BASE|0x08)
-#define        MDDICAP3    (MDDI_CLIENT_CORE_BASE|0x0C)
-#define        MDCAPCHG    (MDDI_CLIENT_CORE_BASE|0x10)
-#define        MDCRCERC    (MDDI_CLIENT_CORE_BASE|0x14)
-#define        TTBUSSEL    (MDDI_CLIENT_CORE_BASE|0x18)
-#define        DPSET0      (MDDI_CLIENT_CORE_BASE|0x1C)
-#define        DPSET1      (MDDI_CLIENT_CORE_BASE|0x20)
-#define        DPSUS       (MDDI_CLIENT_CORE_BASE|0x24)
-#define        DPRUN       (MDDI_CLIENT_CORE_BASE|0x28)
-#define        SYSCKENA    (MDDI_CLIENT_CORE_BASE|0x2C)
-#define        TESTMODE    (MDDI_CLIENT_CORE_BASE|0x30)
-#define        FIFOMONI    (MDDI_CLIENT_CORE_BASE|0x34)
-#define        INTMONI     (MDDI_CLIENT_CORE_BASE|0x38)
-#define        MDIOBIST    (MDDI_CLIENT_CORE_BASE|0x3C)
-#define        MDIOPSET    (MDDI_CLIENT_CORE_BASE|0x40)
-#define        BITMAP0     (MDDI_CLIENT_CORE_BASE|0x44)
-#define        BITMAP1     (MDDI_CLIENT_CORE_BASE|0x48)
-#define        BITMAP2     (MDDI_CLIENT_CORE_BASE|0x4C)
-#define        BITMAP3     (MDDI_CLIENT_CORE_BASE|0x50)
-#define        BITMAP4     (MDDI_CLIENT_CORE_BASE|0x54)
-
-#define        SRST        (LCD_CONTROL_BLOCK_BASE|0x00)
-#define        PORT_ENB    (LCD_CONTROL_BLOCK_BASE|0x04)
-#define        START       (LCD_CONTROL_BLOCK_BASE|0x08)
-#define        PORT        (LCD_CONTROL_BLOCK_BASE|0x0C)
-#define        CMN         (LCD_CONTROL_BLOCK_BASE|0x10)
-#define        GAMMA       (LCD_CONTROL_BLOCK_BASE|0x14)
-#define        INTFLG      (LCD_CONTROL_BLOCK_BASE|0x18)
-#define        INTMSK      (LCD_CONTROL_BLOCK_BASE|0x1C)
-#define        MPLFBUF     (LCD_CONTROL_BLOCK_BASE|0x20)
-#define        HDE_LEFT    (LCD_CONTROL_BLOCK_BASE|0x24)
-#define        VDE_TOP     (LCD_CONTROL_BLOCK_BASE|0x28)
-#define        PXL         (LCD_CONTROL_BLOCK_BASE|0x30)
-#define        HCYCLE      (LCD_CONTROL_BLOCK_BASE|0x34)
-#define        HSW         (LCD_CONTROL_BLOCK_BASE|0x38)
-#define        HDE_START   (LCD_CONTROL_BLOCK_BASE|0x3C)
-#define        HDE_SIZE    (LCD_CONTROL_BLOCK_BASE|0x40)
-#define        VCYCLE      (LCD_CONTROL_BLOCK_BASE|0x44)
-#define        VSW         (LCD_CONTROL_BLOCK_BASE|0x48)
-#define        VDE_START   (LCD_CONTROL_BLOCK_BASE|0x4C)
-#define        VDE_SIZE    (LCD_CONTROL_BLOCK_BASE|0x50)
-#define        WAKEUP      (LCD_CONTROL_BLOCK_BASE|0x54)
-#define        WSYN_DLY    (LCD_CONTROL_BLOCK_BASE|0x58)
-#define        REGENB      (LCD_CONTROL_BLOCK_BASE|0x5C)
-#define        VSYNIF      (LCD_CONTROL_BLOCK_BASE|0x60)
-#define        WRSTB       (LCD_CONTROL_BLOCK_BASE|0x64)
-#define        RDSTB       (LCD_CONTROL_BLOCK_BASE|0x68)
-#define        ASY_DATA    (LCD_CONTROL_BLOCK_BASE|0x6C)
-#define        ASY_DATB    (LCD_CONTROL_BLOCK_BASE|0x70)
-#define        ASY_DATC    (LCD_CONTROL_BLOCK_BASE|0x74)
-#define        ASY_DATD    (LCD_CONTROL_BLOCK_BASE|0x78)
-#define        ASY_DATE    (LCD_CONTROL_BLOCK_BASE|0x7C)
-#define        ASY_DATF    (LCD_CONTROL_BLOCK_BASE|0x80)
-#define        ASY_DATG    (LCD_CONTROL_BLOCK_BASE|0x84)
-#define        ASY_DATH    (LCD_CONTROL_BLOCK_BASE|0x88)
-#define        ASY_CMDSET  (LCD_CONTROL_BLOCK_BASE|0x8C)
-
-#define        SSICTL      (SPI_BLOCK_BASE|0x00)
-#define        SSITIME     (SPI_BLOCK_BASE|0x04)
-#define        SSITX       (SPI_BLOCK_BASE|0x08)
-#define        SSIRX       (SPI_BLOCK_BASE|0x0C)
-#define        SSIINTC     (SPI_BLOCK_BASE|0x10)
-#define        SSIINTS     (SPI_BLOCK_BASE|0x14)
-#define        SSIDBG1     (SPI_BLOCK_BASE|0x18)
-#define        SSIDBG2     (SPI_BLOCK_BASE|0x1C)
-#define        SSIID       (SPI_BLOCK_BASE|0x20)
-
-#define        WKREQ       (SYSTEM_BLOCK1_BASE|0x00)
-#define        CLKENB      (SYSTEM_BLOCK1_BASE|0x04)
-#define        DRAMPWR     (SYSTEM_BLOCK1_BASE|0x08)
-#define        INTMASK     (SYSTEM_BLOCK1_BASE|0x0C)
-#define        GPIOSEL     (SYSTEM_BLOCK2_BASE|0x00)
-
-#define        GPIODATA    (GPIO_BLOCK_BASE|0x00)
-#define        GPIODIR     (GPIO_BLOCK_BASE|0x04)
-#define        GPIOIS      (GPIO_BLOCK_BASE|0x08)
-#define        GPIOIBE     (GPIO_BLOCK_BASE|0x0C)
-#define        GPIOIEV     (GPIO_BLOCK_BASE|0x10)
-#define        GPIOIE      (GPIO_BLOCK_BASE|0x14)
-#define        GPIORIS     (GPIO_BLOCK_BASE|0x18)
-#define        GPIOMIS     (GPIO_BLOCK_BASE|0x1C)
-#define        GPIOIC      (GPIO_BLOCK_BASE|0x20)
-#define        GPIOOMS     (GPIO_BLOCK_BASE|0x24)
-#define        GPIOPC      (GPIO_BLOCK_BASE|0x28)
-#define        GPIOID      (GPIO_BLOCK_BASE|0x30)
-
-#define SPI_WRITE(reg, val) \
-       { SSITX,        0x00010000 | (((reg) & 0xff) << 8) | ((val) & 0xff) }, \
-       { 0, 5 },
-
-#define SPI_WRITE1(reg) \
-       { SSITX,        (reg) & 0xff }, \
-       { 0, 5 },
-
-struct mddi_table {
-       uint32_t reg;
-       uint32_t value;
-};
-static struct mddi_table mddi_toshiba_init_table[] = {
-       { DPSET0,       0x09e90046 },
-       { DPSET1,       0x00000118 },
-       { DPSUS,        0x00000000 },
-       { DPRUN,        0x00000001 },
-       { 1,            14         }, /* msleep 14 */
-       { SYSCKENA,     0x00000001 },
-       { CLKENB,       0x0000A1EF },  /*    # SYS.CLKENB  # Enable clocks for each module (without DCLK , i2cCLK) */
-
-       { GPIODATA,     0x02000200 },  /*   # GPI .GPIODATA  # GPIO2(RESET_LCD_N) set to 0 , GPIO3(eDRAM_Power) set to 0 */
-       { GPIODIR,      0x000030D  },  /* 24D   # GPI .GPIODIR  # Select direction of GPIO port (0,2,3,6,9 output) */
-       { GPIOSEL,      0/*0x00000173*/},  /*   # SYS.GPIOSEL  # GPIO port multiplexing control */
-       { GPIOPC,       0x03C300C0 },  /*   # GPI .GPIOPC  # GPIO2,3 PD cut */
-       { WKREQ,        0x00000000 },  /*   # SYS.WKREQ  # Wake-up request event is VSYNC alignment */
-
-       { GPIOIBE,      0x000003FF },
-       { GPIOIS,       0x00000000 },
-       { GPIOIC,       0x000003FF },
-       { GPIOIE,       0x00000000 },
-
-       { GPIODATA,     0x00040004 },  /*   # GPI .GPIODATA  # eDRAM VD supply */
-       { 1,            1          }, /* msleep 1 */
-       { GPIODATA,     0x02040004 },  /*   # GPI .GPIODATA  # eDRAM VD supply */
-       { DRAMPWR,      0x00000001 }, /* eDRAM power */
-};
-
-#define GPIOSEL_VWAKEINT (1U << 0)
-#define INTMASK_VWAKEOUT (1U << 0)
-
-
-static int trout_new_backlight = 1;
-static struct vreg *vreg_mddi_1v5;
-static struct vreg *vreg_lcm_2v85;
-
-static void trout_process_mddi_table(struct msm_mddi_client_data *client_data,
-                                    struct mddi_table *table, size_t count)
-{
-       int i;
-       for (i = 0; i < count; i++) {
-               uint32_t reg = table[i].reg;
-               uint32_t value = table[i].value;
-
-               if (reg == 0)
-                       udelay(value);
-               else if (reg == 1)
-                       msleep(value);
-               else
-                       client_data->remote_write(client_data, value, reg);
-       }
-}
-
-static int trout_mddi_toshiba_client_init(
-       struct msm_mddi_bridge_platform_data *bridge_data,
-       struct msm_mddi_client_data *client_data)
-{
-       int panel_id;
-
-       client_data->auto_hibernate(client_data, 0);
-       trout_process_mddi_table(client_data, mddi_toshiba_init_table,
-                                ARRAY_SIZE(mddi_toshiba_init_table));
-       client_data->auto_hibernate(client_data, 1);
-       panel_id = (client_data->remote_read(client_data, GPIODATA) >> 4) & 3;
-       if (panel_id > 1) {
-               printk(KERN_WARNING "unknown panel id at mddi_enable\n");
-               return -1;
-       }
-       return 0;
-}
-
-static int trout_mddi_toshiba_client_uninit(
-       struct msm_mddi_bridge_platform_data *bridge_data,
-       struct msm_mddi_client_data *client_data)
-{
-       return 0;
-}
-
-static struct resource resources_msm_fb[] = {
-       {
-               .start = MSM_FB_BASE,
-               .end = MSM_FB_BASE + MSM_FB_SIZE,
-               .flags = IORESOURCE_MEM,
-       },
-};
-
-struct msm_mddi_bridge_platform_data toshiba_client_data = {
-       .init = trout_mddi_toshiba_client_init,
-       .uninit = trout_mddi_toshiba_client_uninit,
-       .fb_data = {
-               .xres = 320,
-               .yres = 480,
-               .width = 45,
-               .height = 67,
-               .output_format = 0,
-       },
-};
-
-static struct msm_mddi_platform_data mddi_pdata = {
-       .clk_rate = 122880000,
-       .fb_resource = resources_msm_fb,
-       .num_clients = 1,
-       .client_platform_data = {
-               {
-                       .product_id = (0xd263 << 16 | 0),
-                       .name = "mddi_c_d263_0000",
-                       .id = 0,
-                       .client_data = &toshiba_client_data,
-                       .clk_rate = 0,
-               },
-       },
-};
-
-int __init trout_init_panel(void)
-{
-       int rc;
-
-       if (!machine_is_trout())
-               return 0;
-       vreg_mddi_1v5 = vreg_get(0, "gp2");
-       if (IS_ERR(vreg_mddi_1v5))
-               return PTR_ERR(vreg_mddi_1v5);
-       vreg_lcm_2v85 = vreg_get(0, "gp4");
-       if (IS_ERR(vreg_lcm_2v85))
-               return PTR_ERR(vreg_lcm_2v85);
-
-       trout_new_backlight = system_rev >= 5;
-       if (trout_new_backlight) {
-               uint32_t config = PCOM_GPIO_CFG(27, 0, GPIO_OUTPUT,
-                                               GPIO_NO_PULL, GPIO_8MA);
-               msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX, &config, 0);
-       } else {
-               uint32_t config = PCOM_GPIO_CFG(27, 1, GPIO_OUTPUT,
-                                               GPIO_NO_PULL, GPIO_8MA);
-               uint32_t id = P_GP_CLK;
-               uint32_t rate = 19200000;
-
-               msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX, &config, 0);
-
-               msm_proc_comm(PCOM_CLKCTL_RPC_SET_RATE, &id, &rate);
-               if (id < 0)
-                       pr_err("trout_init_panel: set clock rate failed\n");
-       }
-
-       rc = platform_device_register(&msm_device_mdp);
-       if (rc)
-               return rc;
-       msm_device_mddi0.dev.platform_data = &mddi_pdata;
-       return platform_device_register(&msm_device_mddi0);
-}
-
-device_initcall(trout_init_panel);
diff --git a/arch/arm/mach-msm/board-trout.c b/arch/arm/mach-msm/board-trout.c
deleted file mode 100644 (file)
index ba3edd3..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/* linux/arch/arm/mach-msm/board-trout.c
- *
- * Copyright (C) 2009 Google, Inc.
- * Author: Brian Swetland <swetland@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-#define pr_fmt(fmt) "%s: " fmt, __func__
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/clkdev.h>
-#include <linux/memblock.h>
-
-#include <asm/system_info.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/setup.h>
-
-#include <mach/hardware.h>
-#include <mach/msm_iomap.h>
-
-#include "devices.h"
-#include "board-trout.h"
-#include "common.h"
-
-extern int trout_init_mmc(unsigned int);
-
-static struct platform_device *devices[] __initdata = {
-       &msm_clock_7x01a,
-       &msm_device_gpio_7201,
-       &msm_device_uart3,
-       &msm_device_smd,
-       &msm_device_nand,
-       &msm_device_hsusb,
-       &msm_device_i2c,
-};
-
-static void __init trout_init_early(void)
-{
-       arch_ioremap_caller = __msm_ioremap_caller;
-}
-
-static void __init trout_init_irq(void)
-{
-       msm_init_irq();
-}
-
-static void __init trout_fixup(struct tag *tags, char **cmdline)
-{
-       memblock_add(PHYS_OFFSET, 101*SZ_1M);
-}
-
-static void __init trout_init(void)
-{
-       int rc;
-
-       platform_add_devices(devices, ARRAY_SIZE(devices));
-
-       if (IS_ENABLED(CONFIG_MMC)) {
-               rc = trout_init_mmc(system_rev);
-               if (rc)
-                       pr_crit("MMC init failure (%d)\n", rc);
-       }
-}
-
-static struct map_desc trout_io_desc[] __initdata = {
-       {
-               .virtual = (unsigned long)TROUT_CPLD_BASE,
-               .pfn     = __phys_to_pfn(TROUT_CPLD_START),
-               .length  = TROUT_CPLD_SIZE,
-               .type    = MT_DEVICE_NONSHARED
-       }
-};
-
-static void __init trout_map_io(void)
-{
-       msm_map_common_io();
-       iotable_init(trout_io_desc, ARRAY_SIZE(trout_io_desc));
-
-#if defined(CONFIG_DEBUG_MSM_UART) && (CONFIG_DEBUG_UART_PHYS == 0xa9c00000)
-       /* route UART3 to the "H2W" extended usb connector */
-       writeb(0x80, TROUT_CPLD_BASE + 0x00);
-#endif
-}
-
-static void __init trout_init_late(void)
-{
-       smd_debugfs_init();
-}
-
-MACHINE_START(TROUT, "HTC Dream")
-       .atag_offset    = 0x100,
-       .fixup          = trout_fixup,
-       .map_io         = trout_map_io,
-       .init_early     = trout_init_early,
-       .init_irq       = trout_init_irq,
-       .init_machine   = trout_init,
-       .init_late      = trout_init_late,
-       .init_time      = msm7x01_timer_init,
-MACHINE_END
diff --git a/arch/arm/mach-msm/board-trout.h b/arch/arm/mach-msm/board-trout.h
deleted file mode 100644 (file)
index adb757a..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-/* linux/arch/arm/mach-msm/board-trout.h
-** Author: Brian Swetland <swetland@google.com>
-*/
-#ifndef __ARCH_ARM_MACH_MSM_BOARD_TROUT_H
-#define __ARCH_ARM_MACH_MSM_BOARD_TROUT_H
-
-#include "common.h"
-
-#define MSM_SMI_BASE           0x00000000
-#define MSM_SMI_SIZE           0x00800000
-
-#define MSM_EBI_BASE           0x10000000
-#define MSM_EBI_SIZE           0x06e00000
-
-#define MSM_PMEM_GPU0_BASE     0x00000000
-#define MSM_PMEM_GPU0_SIZE     0x00700000
-
-#define MSM_PMEM_MDP_BASE      0x02000000
-#define MSM_PMEM_MDP_SIZE      0x00800000
-
-#define MSM_PMEM_ADSP_BASE      0x02800000
-#define MSM_PMEM_ADSP_SIZE     0x00800000
-
-#define MSM_PMEM_CAMERA_BASE   0x03000000
-#define MSM_PMEM_CAMERA_SIZE   0x00800000
-
-#define MSM_FB_BASE            0x03800000
-#define MSM_FB_SIZE            0x00100000
-
-#define MSM_LINUX_BASE         MSM_EBI_BASE
-#define MSM_LINUX_SIZE         0x06500000
-
-#define MSM_PMEM_GPU1_SIZE     0x800000
-#define MSM_PMEM_GPU1_BASE     (MSM_RAM_CONSOLE_BASE - MSM_PMEM_GPU1_SIZE)
-
-#define MSM_RAM_CONSOLE_BASE   (MSM_EBI_BASE + 0x6d00000)
-#define MSM_RAM_CONSOLE_SIZE   (128 * SZ_1K)
-
-#if (MSM_FB_BASE + MSM_FB_SIZE) >= (MSM_PMEM_GPU1_BASE)
-#error invalid memory map
-#endif
-
-#define DECLARE_MSM_IOMAP
-#include <mach/msm_iomap.h>
-
-#define TROUT_4_BALL_UP_0     1
-#define TROUT_4_BALL_LEFT_0   18
-#define TROUT_4_BALL_DOWN_0   57
-#define TROUT_4_BALL_RIGHT_0  91
-
-#define TROUT_5_BALL_UP_0     94
-#define TROUT_5_BALL_LEFT_0   18
-#define TROUT_5_BALL_DOWN_0   90
-#define TROUT_5_BALL_RIGHT_0  19
-
-#define TROUT_POWER_KEY     20
-
-#define TROUT_4_TP_LS_EN    19
-#define TROUT_5_TP_LS_EN    1
-
-#define TROUT_CPLD_BASE   IOMEM(0xE8100000)
-#define TROUT_CPLD_START  0x98000000
-#define TROUT_CPLD_SIZE   SZ_4K
-
-#define TROUT_GPIO_CABLE_IN1           (83)
-#define TROUT_GPIO_CABLE_IN2           (49)
-
-#define TROUT_GPIO_START (128)
-
-#define TROUT_GPIO_INT_MASK0_REG            (0x0c)
-#define TROUT_GPIO_INT_STAT0_REG            (0x0e)
-#define TROUT_GPIO_INT_MASK1_REG            (0x14)
-#define TROUT_GPIO_INT_STAT1_REG            (0x10)
-
-#define TROUT_GPIO_HAPTIC_PWM               (28)
-#define TROUT_GPIO_PS_HOLD                  (25)
-
-#define TROUT_GPIO_MISC2_BASE               (TROUT_GPIO_START + 0x00)
-#define TROUT_GPIO_MISC3_BASE               (TROUT_GPIO_START + 0x08)
-#define TROUT_GPIO_MISC4_BASE               (TROUT_GPIO_START + 0x10)
-#define TROUT_GPIO_MISC5_BASE               (TROUT_GPIO_START + 0x18)
-#define TROUT_GPIO_INT2_BASE                (TROUT_GPIO_START + 0x20)
-#define TROUT_GPIO_MISC1_BASE               (TROUT_GPIO_START + 0x28)
-#define TROUT_GPIO_VIRTUAL_BASE             (TROUT_GPIO_START + 0x30)
-#define TROUT_GPIO_INT5_BASE                (TROUT_GPIO_START + 0x48)
-
-#define TROUT_GPIO_CHARGER_EN               (TROUT_GPIO_MISC2_BASE + 0)
-#define TROUT_GPIO_ISET                     (TROUT_GPIO_MISC2_BASE + 1)
-#define TROUT_GPIO_H2W_DAT_DIR              (TROUT_GPIO_MISC2_BASE + 2)
-#define TROUT_GPIO_H2W_CLK_DIR              (TROUT_GPIO_MISC2_BASE + 3)
-#define TROUT_GPIO_H2W_DAT_GPO              (TROUT_GPIO_MISC2_BASE + 4)
-#define TROUT_GPIO_H2W_CLK_GPO              (TROUT_GPIO_MISC2_BASE + 5)
-#define TROUT_GPIO_H2W_SEL0                 (TROUT_GPIO_MISC2_BASE + 6)
-#define TROUT_GPIO_H2W_SEL1                 (TROUT_GPIO_MISC2_BASE + 7)
-
-#define TROUT_GPIO_SPOTLIGHT_EN             (TROUT_GPIO_MISC3_BASE + 0)
-#define TROUT_GPIO_FLASH_EN                 (TROUT_GPIO_MISC3_BASE + 1)
-#define TROUT_GPIO_I2C_PULL                 (TROUT_GPIO_MISC3_BASE + 2)
-#define TROUT_GPIO_TP_I2C_PULL              (TROUT_GPIO_MISC3_BASE + 3)
-#define TROUT_GPIO_TP_EN                    (TROUT_GPIO_MISC3_BASE + 4)
-#define TROUT_GPIO_JOG_EN                   (TROUT_GPIO_MISC3_BASE + 5)
-#define TROUT_GPIO_UI_LED_EN                (TROUT_GPIO_MISC3_BASE + 6)
-#define TROUT_GPIO_QTKEY_LED_EN             (TROUT_GPIO_MISC3_BASE + 7)
-
-#define TROUT_GPIO_VCM_PWDN                 (TROUT_GPIO_MISC4_BASE + 0)
-#define TROUT_GPIO_USB_H2W_SW               (TROUT_GPIO_MISC4_BASE + 1)
-#define TROUT_GPIO_COMPASS_RST_N            (TROUT_GPIO_MISC4_BASE + 2)
-#define TROUT_GPIO_HAPTIC_EN_UP             (TROUT_GPIO_MISC4_BASE + 3)
-#define TROUT_GPIO_HAPTIC_EN_MAIN           (TROUT_GPIO_MISC4_BASE + 4)
-#define TROUT_GPIO_USB_PHY_RST_N            (TROUT_GPIO_MISC4_BASE + 5)
-#define TROUT_GPIO_WIFI_PA_RESETX           (TROUT_GPIO_MISC4_BASE + 6)
-#define TROUT_GPIO_WIFI_EN                  (TROUT_GPIO_MISC4_BASE + 7)
-
-#define TROUT_GPIO_BT_32K_EN                (TROUT_GPIO_MISC5_BASE + 0)
-#define TROUT_GPIO_MAC_32K_EN               (TROUT_GPIO_MISC5_BASE + 1)
-#define TROUT_GPIO_MDDI_32K_EN              (TROUT_GPIO_MISC5_BASE + 2)
-#define TROUT_GPIO_COMPASS_32K_EN           (TROUT_GPIO_MISC5_BASE + 3)
-
-#define TROUT_GPIO_NAVI_ACT_N               (TROUT_GPIO_INT2_BASE + 0)
-#define TROUT_GPIO_COMPASS_IRQ              (TROUT_GPIO_INT2_BASE + 1)
-#define TROUT_GPIO_SLIDING_DET              (TROUT_GPIO_INT2_BASE + 2)
-#define TROUT_GPIO_AUD_HSMIC_DET_N          (TROUT_GPIO_INT2_BASE + 3)
-#define TROUT_GPIO_SD_DOOR_N                (TROUT_GPIO_INT2_BASE + 4)
-#define TROUT_GPIO_CAM_BTN_STEP1_N          (TROUT_GPIO_INT2_BASE + 5)
-#define TROUT_GPIO_CAM_BTN_STEP2_N          (TROUT_GPIO_INT2_BASE + 6)
-#define TROUT_GPIO_TP_ATT_N                 (TROUT_GPIO_INT2_BASE + 7)
-#define TROUT_GPIO_BANK0_FIRST_INT_SOURCE   (TROUT_GPIO_NAVI_ACT_N)
-#define TROUT_GPIO_BANK0_LAST_INT_SOURCE    (TROUT_GPIO_TP_ATT_N)
-
-#define TROUT_GPIO_H2W_DAT_GPI              (TROUT_GPIO_MISC1_BASE + 0)
-#define TROUT_GPIO_H2W_CLK_GPI              (TROUT_GPIO_MISC1_BASE + 1)
-#define TROUT_GPIO_CPLD128_VER_0            (TROUT_GPIO_MISC1_BASE + 4)
-#define TROUT_GPIO_CPLD128_VER_1            (TROUT_GPIO_MISC1_BASE + 5)
-#define TROUT_GPIO_CPLD128_VER_2            (TROUT_GPIO_MISC1_BASE + 6)
-#define TROUT_GPIO_CPLD128_VER_3            (TROUT_GPIO_MISC1_BASE + 7)
-
-#define TROUT_GPIO_SDMC_CD_N                (TROUT_GPIO_VIRTUAL_BASE + 0)
-#define TROUT_GPIO_END                      (TROUT_GPIO_SDMC_CD_N)
-#define TROUT_GPIO_BANK1_FIRST_INT_SOURCE   (TROUT_GPIO_SDMC_CD_N)
-#define TROUT_GPIO_BANK1_LAST_INT_SOURCE    (TROUT_GPIO_SDMC_CD_N)
-
-#define TROUT_GPIO_VIRTUAL_TO_REAL_OFFSET \
-       (TROUT_GPIO_INT5_BASE - TROUT_GPIO_VIRTUAL_BASE)
-
-#define TROUT_INT_START (NR_MSM_IRQS + NR_GPIO_IRQS)
-#define TROUT_INT_BANK0_COUNT (8)
-#define TROUT_INT_BANK1_START (TROUT_INT_START + TROUT_INT_BANK0_COUNT)
-#define TROUT_INT_BANK1_COUNT (1)
-#define TROUT_INT_END (TROUT_INT_START + TROUT_INT_BANK0_COUNT + \
-                       TROUT_INT_BANK1_COUNT - 1)
-#define TROUT_GPIO_TO_INT(n) (((n) <= TROUT_GPIO_BANK0_LAST_INT_SOURCE) ? \
-       (TROUT_INT_START - TROUT_GPIO_BANK0_FIRST_INT_SOURCE + (n)) : \
-       (TROUT_INT_BANK1_START - TROUT_GPIO_BANK1_FIRST_INT_SOURCE + (n)))
-
-#define TROUT_INT_TO_BANK(n) ((n - TROUT_INT_START) / TROUT_INT_BANK0_COUNT)
-#define TROUT_INT_TO_MASK(n) (1U << ((n - TROUT_INT_START) & 7))
-#define TROUT_BANK_TO_MASK_REG(bank) \
-       (bank ? TROUT_GPIO_INT_MASK1_REG : TROUT_GPIO_INT_MASK0_REG)
-#define TROUT_BANK_TO_STAT_REG(bank) \
-       (bank ? TROUT_GPIO_INT_STAT1_REG : TROUT_GPIO_INT_STAT0_REG)
-
-#endif /* GUARD */
diff --git a/arch/arm/mach-msm/clock-pcom.c b/arch/arm/mach-msm/clock-pcom.c
deleted file mode 100644 (file)
index f5b69d7..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2007-2012, The Linux Foundation. All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <linux/clk-provider.h>
-#include <linux/clkdev.h>
-
-#include <mach/clk.h>
-
-#include "proc_comm.h"
-#include "clock.h"
-#include "clock-pcom.h"
-
-struct clk_pcom {
-       unsigned id;
-       unsigned long flags;
-       struct msm_clk msm_clk;
-};
-
-static inline struct clk_pcom *to_clk_pcom(struct clk_hw *hw)
-{
-       return container_of(to_msm_clk(hw), struct clk_pcom, msm_clk);
-}
-
-static int pc_clk_enable(struct clk_hw *hw)
-{
-       unsigned id = to_clk_pcom(hw)->id;
-       int rc = msm_proc_comm(PCOM_CLKCTL_RPC_ENABLE, &id, NULL);
-       if (rc < 0)
-               return rc;
-       else
-               return (int)id < 0 ? -EINVAL : 0;
-}
-
-static void pc_clk_disable(struct clk_hw *hw)
-{
-       unsigned id = to_clk_pcom(hw)->id;
-       msm_proc_comm(PCOM_CLKCTL_RPC_DISABLE, &id, NULL);
-}
-
-static int pc_clk_reset(struct clk_hw *hw, enum clk_reset_action action)
-{
-       int rc;
-       unsigned id = to_clk_pcom(hw)->id;
-
-       if (action == CLK_RESET_ASSERT)
-               rc = msm_proc_comm(PCOM_CLKCTL_RPC_RESET_ASSERT, &id, NULL);
-       else
-               rc = msm_proc_comm(PCOM_CLKCTL_RPC_RESET_DEASSERT, &id, NULL);
-
-       if (rc < 0)
-               return rc;
-       else
-               return (int)id < 0 ? -EINVAL : 0;
-}
-
-static int pc_clk_set_rate(struct clk_hw *hw, unsigned long new_rate,
-                          unsigned long p_rate)
-{
-       struct clk_pcom *p = to_clk_pcom(hw);
-       unsigned id = p->id, rate = new_rate;
-       int rc;
-
-       /*
-        * The rate _might_ be rounded off to the nearest KHz value by the
-        * remote function. So a return value of 0 doesn't necessarily mean
-        * that the exact rate was set successfully.
-        */
-       if (p->flags & CLKFLAG_MIN)
-               rc = msm_proc_comm(PCOM_CLKCTL_RPC_MIN_RATE, &id, &rate);
-       else
-               rc = msm_proc_comm(PCOM_CLKCTL_RPC_SET_RATE, &id, &rate);
-       if (rc < 0)
-               return rc;
-       else
-               return (int)id < 0 ? -EINVAL : 0;
-}
-
-static unsigned long pc_clk_recalc_rate(struct clk_hw *hw, unsigned long p_rate)
-{
-       unsigned id = to_clk_pcom(hw)->id;
-       if (msm_proc_comm(PCOM_CLKCTL_RPC_RATE, &id, NULL))
-               return 0;
-       else
-               return id;
-}
-
-static int pc_clk_is_enabled(struct clk_hw *hw)
-{
-       unsigned id = to_clk_pcom(hw)->id;
-       if (msm_proc_comm(PCOM_CLKCTL_RPC_ENABLED, &id, NULL))
-               return 0;
-       else
-               return id;
-}
-
-static long pc_clk_round_rate(struct clk_hw *hw, unsigned long rate,
-                             unsigned long *p_rate)
-{
-       /* Not really supported; pc_clk_set_rate() does rounding on it's own. */
-       return rate;
-}
-
-static struct clk_ops clk_ops_pcom = {
-       .enable = pc_clk_enable,
-       .disable = pc_clk_disable,
-       .set_rate = pc_clk_set_rate,
-       .recalc_rate = pc_clk_recalc_rate,
-       .is_enabled = pc_clk_is_enabled,
-       .round_rate = pc_clk_round_rate,
-};
-
-static int msm_clock_pcom_probe(struct platform_device *pdev)
-{
-       const struct pcom_clk_pdata *pdata = pdev->dev.platform_data;
-       int i, ret;
-
-       for (i = 0; i < pdata->num_lookups; i++) {
-               const struct clk_pcom_desc *desc = &pdata->lookup[i];
-               struct clk *c;
-               struct clk_pcom *p;
-               struct clk_hw *hw;
-               struct clk_init_data init;
-
-               p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
-               if (!p)
-                       return -ENOMEM;
-
-               p->id = desc->id;
-               p->flags = desc->flags;
-               p->msm_clk.reset = pc_clk_reset;
-
-               hw = &p->msm_clk.hw;
-               hw->init = &init;
-
-               init.name = desc->name;
-               init.ops = &clk_ops_pcom;
-               init.num_parents = 0;
-               init.flags = CLK_IS_ROOT;
-
-               if (!(p->flags & CLKFLAG_AUTO_OFF))
-                       init.flags |= CLK_IGNORE_UNUSED;
-
-               c = devm_clk_register(&pdev->dev, hw);
-               ret = clk_register_clkdev(c, desc->con, desc->dev);
-               if (ret)
-                       return ret;
-       }
-
-       return 0;
-}
-
-static struct platform_driver msm_clock_pcom_driver = {
-       .probe          = msm_clock_pcom_probe,
-       .driver         = {
-               .name   = "msm-clock-pcom",
-       },
-};
-module_platform_driver(msm_clock_pcom_driver);
-
-MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/clock-pcom.h b/arch/arm/mach-msm/clock-pcom.h
deleted file mode 100644 (file)
index 5bb164f..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __ARCH_ARM_MACH_MSM_CLOCK_PCOM_H
-#define __ARCH_ARM_MACH_MSM_CLOCK_PCOM_H
-
-/* clock IDs used by the modem processor */
-
-#define P_ACPU_CLK     0   /* Applications processor clock */
-#define P_ADM_CLK      1   /* Applications data mover clock */
-#define P_ADSP_CLK     2   /* ADSP clock */
-#define P_EBI1_CLK     3   /* External bus interface 1 clock */
-#define P_EBI2_CLK     4   /* External bus interface 2 clock */
-#define P_ECODEC_CLK   5   /* External CODEC clock */
-#define P_EMDH_CLK     6   /* External MDDI host clock */
-#define P_GP_CLK       7   /* General purpose clock */
-#define P_GRP_3D_CLK   8   /* Graphics clock */
-#define P_I2C_CLK      9   /* I2C clock */
-#define P_ICODEC_RX_CLK        10  /* Internal CODEX RX clock */
-#define P_ICODEC_TX_CLK        11  /* Internal CODEX TX clock */
-#define P_IMEM_CLK     12  /* Internal graphics memory clock */
-#define P_MDC_CLK      13  /* MDDI client clock */
-#define P_MDP_CLK      14  /* Mobile display processor clock */
-#define P_PBUS_CLK     15  /* Peripheral bus clock */
-#define P_PCM_CLK      16  /* PCM clock */
-#define P_PMDH_CLK     17  /* Primary MDDI host clock */
-#define P_SDAC_CLK     18  /* Stereo DAC clock */
-#define P_SDC1_CLK     19  /* Secure Digital Card clocks */
-#define P_SDC1_P_CLK   20
-#define P_SDC2_CLK     21
-#define P_SDC2_P_CLK   22
-#define P_SDC3_CLK     23
-#define P_SDC3_P_CLK   24
-#define P_SDC4_CLK     25
-#define P_SDC4_P_CLK   26
-#define P_TSIF_CLK     27  /* Transport Stream Interface clocks */
-#define P_TSIF_REF_CLK 28
-#define P_TV_DAC_CLK   29  /* TV clocks */
-#define P_TV_ENC_CLK   30
-#define P_UART1_CLK    31  /* UART clocks */
-#define P_UART2_CLK    32
-#define P_UART3_CLK    33
-#define P_UART1DM_CLK  34
-#define P_UART2DM_CLK  35
-#define P_USB_HS_CLK   36  /* High speed USB core clock */
-#define P_USB_HS_P_CLK 37  /* High speed USB pbus clock */
-#define P_USB_OTG_CLK  38  /* Full speed USB clock */
-#define P_VDC_CLK      39  /* Video controller clock */
-#define P_VFE_MDC_CLK  40  /* Camera / Video Front End clock */
-#define P_VFE_CLK      41  /* VFE MDDI client clock */
-#define P_MDP_LCDC_PCLK_CLK    42
-#define P_MDP_LCDC_PAD_PCLK_CLK 43
-#define P_MDP_VSYNC_CLK        44
-#define P_SPI_CLK      45
-#define P_VFE_AXI_CLK  46
-#define P_USB_HS2_CLK  47  /* High speed USB 2 core clock */
-#define P_USB_HS2_P_CLK        48  /* High speed USB 2 pbus clock */
-#define P_USB_HS3_CLK  49  /* High speed USB 3 core clock */
-#define P_USB_HS3_P_CLK        50  /* High speed USB 3 pbus clock */
-#define P_GRP_3D_P_CLK 51  /* Graphics pbus clock */
-#define P_USB_PHY_CLK  52  /* USB PHY clock */
-#define P_USB_HS_CORE_CLK      53  /* High speed USB 1 core clock */
-#define P_USB_HS2_CORE_CLK     54  /* High speed USB 2 core clock */
-#define P_USB_HS3_CORE_CLK     55  /* High speed USB 3 core clock */
-#define P_CAM_M_CLK            56
-#define P_CAMIF_PAD_P_CLK      57
-#define P_GRP_2D_CLK           58
-#define P_GRP_2D_P_CLK         59
-#define P_I2S_CLK              60
-#define P_JPEG_CLK             61
-#define P_JPEG_P_CLK           62
-#define P_LPA_CODEC_CLK                63
-#define P_LPA_CORE_CLK         64
-#define P_LPA_P_CLK            65
-#define P_MDC_IO_CLK           66
-#define P_MDC_P_CLK            67
-#define P_MFC_CLK              68
-#define P_MFC_DIV2_CLK         69
-#define P_MFC_P_CLK            70
-#define P_QUP_I2C_CLK          71
-#define P_ROTATOR_IMEM_CLK     72
-#define P_ROTATOR_P_CLK                73
-#define P_VFE_CAMIF_CLK                74
-#define P_VFE_P_CLK            75
-#define P_VPE_CLK              76
-#define P_I2C_2_CLK            77
-#define P_MI2S_CODEC_RX_S_CLK  78
-#define P_MI2S_CODEC_RX_M_CLK  79
-#define P_MI2S_CODEC_TX_S_CLK  80
-#define P_MI2S_CODEC_TX_M_CLK  81
-#define P_PMDH_P_CLK           82
-#define P_EMDH_P_CLK           83
-#define P_SPI_P_CLK            84
-#define P_TSIF_P_CLK           85
-#define P_MDP_P_CLK            86
-#define P_SDAC_M_CLK           87
-#define P_MI2S_S_CLK           88
-#define P_MI2S_M_CLK           89
-#define P_AXI_ROTATOR_CLK      90
-#define P_HDMI_CLK             91
-#define P_CSI0_CLK             92
-#define P_CSI0_VFE_CLK         93
-#define P_CSI0_P_CLK           94
-#define P_CSI1_CLK             95
-#define P_CSI1_VFE_CLK         96
-#define P_CSI1_P_CLK           97
-#define P_GSBI_CLK             98
-#define P_GSBI_P_CLK           99
-#define P_CE_CLK               100 /* Crypto engine */
-#define P_CODEC_SSBI_CLK       101
-
-#define P_NR_CLKS              102
-
-struct clk_pcom_desc {
-       unsigned id;
-       const char *name;
-       const char *con;
-       const char *dev;
-       unsigned long flags;
-};
-
-struct pcom_clk_pdata {
-       struct clk_pcom_desc *lookup;
-       u32 num_lookups;
-};
-
-#define CLK_PCOM(clk_name, clk_id, clk_dev, clk_flags) {       \
-       .id = P_##clk_id,                                       \
-       .name = #clk_id,                                        \
-       .con = clk_name,                                        \
-       .dev = clk_dev,                                         \
-       .flags = clk_flags,                                     \
-       }
-
-#endif
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
deleted file mode 100644 (file)
index 35ea02b..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/* arch/arm/mach-msm/clock.c
- *
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2007-2012, The Linux Foundation. All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/clk-provider.h>
-#include <linux/module.h>
-
-#include "clock.h"
-
-int clk_reset(struct clk *clk, enum clk_reset_action action)
-{
-       struct clk_hw *hw = __clk_get_hw(clk);
-       struct msm_clk *m = to_msm_clk(hw);
-       return m->reset(hw, action);
-}
-EXPORT_SYMBOL(clk_reset);
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
deleted file mode 100644 (file)
index 42d29dd..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/* arch/arm/mach-msm/clock.h
- *
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2007-2012, The Linux Foundation. All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __ARCH_ARM_MACH_MSM_CLOCK_H
-#define __ARCH_ARM_MACH_MSM_CLOCK_H
-
-#include <linux/clk-provider.h>
-#include <mach/clk.h>
-
-#define CLK_FIRST_AVAILABLE_FLAG       0x00000100
-#define CLKFLAG_AUTO_OFF               0x00000200
-#define CLKFLAG_MIN                    0x00000400
-#define CLKFLAG_MAX                    0x00000800
-
-#define OFF CLKFLAG_AUTO_OFF
-#define CLK_MIN CLKFLAG_MIN
-#define CLK_MAX CLKFLAG_MAX
-#define CLK_MINMAX (CLK_MIN | CLK_MAX)
-
-struct msm_clk {
-       int (*reset)(struct clk_hw *hw, enum clk_reset_action action);
-       struct clk_hw hw;
-};
-
-static inline struct msm_clk *to_msm_clk(struct clk_hw *hw)
-{
-       return container_of(hw, struct msm_clk, hw);
-}
-
-#endif
diff --git a/arch/arm/mach-msm/common.h b/arch/arm/mach-msm/common.h
deleted file mode 100644 (file)
index 572479a..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-#ifndef __MACH_COMMON_H
-#define __MACH_COMMON_H
-
-extern void msm7x01_timer_init(void);
-extern void msm7x30_timer_init(void);
-extern void qsd8x50_timer_init(void);
-
-extern void msm_map_common_io(void);
-extern void msm_map_msm7x30_io(void);
-extern void msm_map_qsd8x50_io(void);
-
-extern void __iomem *__msm_ioremap_caller(phys_addr_t phys_addr, size_t size,
-                                         unsigned int mtype, void *caller);
-
-struct msm_mmc_platform_data;
-
-extern void msm_add_devices(void);
-extern void msm_init_irq(void);
-extern void msm_init_gpio(void);
-extern int msm_add_sdcc(unsigned int controller,
-                       struct msm_mmc_platform_data *plat,
-                       unsigned int stat_irq, unsigned long stat_irq_flags);
-
-#if defined(CONFIG_MSM_SMD) && defined(CONFIG_DEBUG_FS)
-extern int smd_debugfs_init(void);
-#else
-static inline int smd_debugfs_init(void) { return 0; }
-#endif
-
-#endif
diff --git a/arch/arm/mach-msm/devices-msm7x00.c b/arch/arm/mach-msm/devices-msm7x00.c
deleted file mode 100644 (file)
index d83404d..0000000
+++ /dev/null
@@ -1,480 +0,0 @@
-/* linux/arch/arm/mach-msm/devices.c
- *
- * Copyright (C) 2008 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/clkdev.h>
-
-#include <mach/irqs.h>
-#include <mach/msm_iomap.h>
-#include "devices.h"
-
-#include <asm/mach/flash.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/partitions.h>
-
-#include "clock.h"
-#include "clock-pcom.h"
-#include <linux/platform_data/mmc-msm_sdcc.h>
-
-static struct resource msm_gpio_resources[] = {
-       {
-               .start  = 32 + 0,
-               .end    = 32 + 0,
-               .flags  = IORESOURCE_IRQ,
-       },
-       {
-               .start  = 32 + 1,
-               .end    = 32 + 1,
-               .flags  = IORESOURCE_IRQ,
-       },
-       {
-               .start  = 0xa9200800,
-               .end    = 0xa9200800 + SZ_4K - 1,
-               .flags  = IORESOURCE_MEM,
-               .name  = "gpio1"
-       },
-       {
-               .start  = 0xa9300C00,
-               .end    = 0xa9300C00 + SZ_4K - 1,
-               .flags  = IORESOURCE_MEM,
-               .name  = "gpio2"
-       },
-};
-
-struct platform_device msm_device_gpio_7201 = {
-       .name   = "gpio-msm-7201",
-       .num_resources  = ARRAY_SIZE(msm_gpio_resources),
-       .resource       = msm_gpio_resources,
-};
-
-static struct resource resources_uart1[] = {
-       {
-               .start  = INT_UART1,
-               .end    = INT_UART1,
-               .flags  = IORESOURCE_IRQ,
-       },
-       {
-               .start  = MSM_UART1_PHYS,
-               .end    = MSM_UART1_PHYS + MSM_UART1_SIZE - 1,
-               .flags  = IORESOURCE_MEM,
-               .name  = "uart_resource"
-       },
-};
-
-static struct resource resources_uart2[] = {
-       {
-               .start  = INT_UART2,
-               .end    = INT_UART2,
-               .flags  = IORESOURCE_IRQ,
-       },
-       {
-               .start  = MSM_UART2_PHYS,
-               .end    = MSM_UART2_PHYS + MSM_UART2_SIZE - 1,
-               .flags  = IORESOURCE_MEM,
-               .name  = "uart_resource"
-       },
-};
-
-static struct resource resources_uart3[] = {
-       {
-               .start  = INT_UART3,
-               .end    = INT_UART3,
-               .flags  = IORESOURCE_IRQ,
-       },
-       {
-               .start  = MSM_UART3_PHYS,
-               .end    = MSM_UART3_PHYS + MSM_UART3_SIZE - 1,
-               .flags  = IORESOURCE_MEM,
-               .name  = "uart_resource"
-       },
-};
-
-struct platform_device msm_device_uart1 = {
-       .name   = "msm_serial",
-       .id     = 0,
-       .num_resources  = ARRAY_SIZE(resources_uart1),
-       .resource       = resources_uart1,
-};
-
-struct platform_device msm_device_uart2 = {
-       .name   = "msm_serial",
-       .id     = 1,
-       .num_resources  = ARRAY_SIZE(resources_uart2),
-       .resource       = resources_uart2,
-};
-
-struct platform_device msm_device_uart3 = {
-       .name   = "msm_serial",
-       .id     = 2,
-       .num_resources  = ARRAY_SIZE(resources_uart3),
-       .resource       = resources_uart3,
-};
-
-static struct resource resources_i2c[] = {
-       {
-               .start  = MSM_I2C_PHYS,
-               .end    = MSM_I2C_PHYS + MSM_I2C_SIZE - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               .start  = INT_PWB_I2C,
-               .end    = INT_PWB_I2C,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device msm_device_i2c = {
-       .name           = "msm_i2c",
-       .id             = 0,
-       .num_resources  = ARRAY_SIZE(resources_i2c),
-       .resource       = resources_i2c,
-};
-
-static struct resource resources_hsusb[] = {
-       {
-               .start  = MSM_HSUSB_PHYS,
-               .end    = MSM_HSUSB_PHYS + MSM_HSUSB_SIZE,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               .start  = INT_USB_HS,
-               .end    = INT_USB_HS,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device msm_device_hsusb = {
-       .name           = "msm_hsusb",
-       .id             = -1,
-       .num_resources  = ARRAY_SIZE(resources_hsusb),
-       .resource       = resources_hsusb,
-       .dev            = {
-               .coherent_dma_mask      = 0xffffffff,
-       },
-};
-
-struct flash_platform_data msm_nand_data = {
-       .parts          = NULL,
-       .nr_parts       = 0,
-};
-
-static struct resource resources_nand[] = {
-       [0] = {
-               .start  = 7,
-               .end    = 7,
-               .flags  = IORESOURCE_DMA,
-       },
-};
-
-struct platform_device msm_device_nand = {
-       .name           = "msm_nand",
-       .id             = -1,
-       .num_resources  = ARRAY_SIZE(resources_nand),
-       .resource       = resources_nand,
-       .dev            = {
-               .platform_data  = &msm_nand_data,
-       },
-};
-
-struct platform_device msm_device_smd = {
-       .name   = "msm_smd",
-       .id     = -1,
-};
-
-static struct resource resources_sdc1[] = {
-       {
-               .start  = MSM_SDC1_PHYS,
-               .end    = MSM_SDC1_PHYS + MSM_SDC1_SIZE - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               .start  = INT_SDC1_0,
-               .end    = INT_SDC1_0,
-               .flags  = IORESOURCE_IRQ,
-               .name   = "cmd_irq",
-       },
-       {
-               .flags  = IORESOURCE_IRQ | IORESOURCE_DISABLED,
-               .name   = "status_irq"
-       },
-       {
-               .start  = 8,
-               .end    = 8,
-               .flags  = IORESOURCE_DMA,
-       },
-};
-
-static struct resource resources_sdc2[] = {
-       {
-               .start  = MSM_SDC2_PHYS,
-               .end    = MSM_SDC2_PHYS + MSM_SDC2_SIZE - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               .start  = INT_SDC2_0,
-               .end    = INT_SDC2_0,
-               .flags  = IORESOURCE_IRQ,
-               .name   = "cmd_irq",
-       },
-       {
-               .flags  = IORESOURCE_IRQ | IORESOURCE_DISABLED,
-               .name   = "status_irq"
-       },
-       {
-               .start  = 8,
-               .end    = 8,
-               .flags  = IORESOURCE_DMA,
-       },
-};
-
-static struct resource resources_sdc3[] = {
-       {
-               .start  = MSM_SDC3_PHYS,
-               .end    = MSM_SDC3_PHYS + MSM_SDC3_SIZE - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               .start  = INT_SDC3_0,
-               .end    = INT_SDC3_0,
-               .flags  = IORESOURCE_IRQ,
-               .name   = "cmd_irq",
-       },
-       {
-               .flags  = IORESOURCE_IRQ | IORESOURCE_DISABLED,
-               .name   = "status_irq"
-       },
-       {
-               .start  = 8,
-               .end    = 8,
-               .flags  = IORESOURCE_DMA,
-       },
-};
-
-static struct resource resources_sdc4[] = {
-       {
-               .start  = MSM_SDC4_PHYS,
-               .end    = MSM_SDC4_PHYS + MSM_SDC4_SIZE - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               .start  = INT_SDC4_0,
-               .end    = INT_SDC4_0,
-               .flags  = IORESOURCE_IRQ,
-               .name   = "cmd_irq",
-       },
-       {
-               .flags  = IORESOURCE_IRQ | IORESOURCE_DISABLED,
-               .name   = "status_irq"
-       },
-       {
-               .start  = 8,
-               .end    = 8,
-               .flags  = IORESOURCE_DMA,
-       },
-};
-
-struct platform_device msm_device_sdc1 = {
-       .name           = "msm_sdcc",
-       .id             = 1,
-       .num_resources  = ARRAY_SIZE(resources_sdc1),
-       .resource       = resources_sdc1,
-       .dev            = {
-               .coherent_dma_mask      = 0xffffffff,
-       },
-};
-
-struct platform_device msm_device_sdc2 = {
-       .name           = "msm_sdcc",
-       .id             = 2,
-       .num_resources  = ARRAY_SIZE(resources_sdc2),
-       .resource       = resources_sdc2,
-       .dev            = {
-               .coherent_dma_mask      = 0xffffffff,
-       },
-};
-
-struct platform_device msm_device_sdc3 = {
-       .name           = "msm_sdcc",
-       .id             = 3,
-       .num_resources  = ARRAY_SIZE(resources_sdc3),
-       .resource       = resources_sdc3,
-       .dev            = {
-               .coherent_dma_mask      = 0xffffffff,
-       },
-};
-
-struct platform_device msm_device_sdc4 = {
-       .name           = "msm_sdcc",
-       .id             = 4,
-       .num_resources  = ARRAY_SIZE(resources_sdc4),
-       .resource       = resources_sdc4,
-       .dev            = {
-               .coherent_dma_mask      = 0xffffffff,
-       },
-};
-
-static struct platform_device *msm_sdcc_devices[] __initdata = {
-       &msm_device_sdc1,
-       &msm_device_sdc2,
-       &msm_device_sdc3,
-       &msm_device_sdc4,
-};
-
-int __init msm_add_sdcc(unsigned int controller,
-                       struct msm_mmc_platform_data *plat,
-                       unsigned int stat_irq, unsigned long stat_irq_flags)
-{
-       struct platform_device  *pdev;
-       struct resource *res;
-
-       if (controller < 1 || controller > 4)
-               return -EINVAL;
-
-       pdev = msm_sdcc_devices[controller-1];
-       pdev->dev.platform_data = plat;
-
-       res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "status_irq");
-       if (!res)
-               return -EINVAL;
-       else if (stat_irq) {
-               res->start = res->end = stat_irq;
-               res->flags &= ~IORESOURCE_DISABLED;
-               res->flags |= stat_irq_flags;
-       }
-
-       return platform_device_register(pdev);
-}
-
-static struct resource resources_mddi0[] = {
-       {
-               .start  = MSM_PMDH_PHYS,
-               .end    = MSM_PMDH_PHYS + MSM_PMDH_SIZE - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               .start  = INT_MDDI_PRI,
-               .end    = INT_MDDI_PRI,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct resource resources_mddi1[] = {
-       {
-               .start  = MSM_EMDH_PHYS,
-               .end    = MSM_EMDH_PHYS + MSM_EMDH_SIZE - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               .start  = INT_MDDI_EXT,
-               .end    = INT_MDDI_EXT,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device msm_device_mddi0 = {
-       .name = "msm_mddi",
-       .id = 0,
-       .num_resources = ARRAY_SIZE(resources_mddi0),
-       .resource = resources_mddi0,
-       .dev = {
-               .coherent_dma_mask      = 0xffffffff,
-       },
-};
-
-struct platform_device msm_device_mddi1 = {
-       .name = "msm_mddi",
-       .id = 1,
-       .num_resources = ARRAY_SIZE(resources_mddi1),
-       .resource = resources_mddi1,
-       .dev = {
-               .coherent_dma_mask      = 0xffffffff,
-       },
-};
-
-static struct resource resources_mdp[] = {
-       {
-               .start  = MSM_MDP_PHYS,
-               .end    = MSM_MDP_PHYS + MSM_MDP_SIZE - 1,
-               .name   = "mdp",
-               .flags  = IORESOURCE_MEM
-       },
-       {
-               .start  = INT_MDP,
-               .end    = INT_MDP,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device msm_device_mdp = {
-       .name = "msm_mdp",
-       .id = 0,
-       .num_resources = ARRAY_SIZE(resources_mdp),
-       .resource = resources_mdp,
-};
-
-static struct clk_pcom_desc msm_clocks_7x01a[] = {
-       CLK_PCOM("adm_clk",     ADM_CLK,        NULL, 0),
-       CLK_PCOM("adsp_clk",    ADSP_CLK,       NULL, 0),
-       CLK_PCOM("ebi1_clk",    EBI1_CLK,       NULL, 0),
-       CLK_PCOM("ebi2_clk",    EBI2_CLK,       NULL, 0),
-       CLK_PCOM("ecodec_clk",  ECODEC_CLK,     NULL, 0),
-       CLK_PCOM("emdh_clk",    EMDH_CLK,       NULL, OFF),
-       CLK_PCOM("gp_clk",              GP_CLK,         NULL, 0),
-       CLK_PCOM("grp_clk",     GRP_3D_CLK,     NULL, OFF),
-       CLK_PCOM("i2c_clk",     I2C_CLK,        "msm_i2c.0", 0),
-       CLK_PCOM("icodec_rx_clk",       ICODEC_RX_CLK,  NULL, 0),
-       CLK_PCOM("icodec_tx_clk",       ICODEC_TX_CLK,  NULL, 0),
-       CLK_PCOM("imem_clk",    IMEM_CLK,       NULL, OFF),
-       CLK_PCOM("mdc_clk",     MDC_CLK,        NULL, 0),
-       CLK_PCOM("mdp_clk",     MDP_CLK,        NULL, OFF),
-       CLK_PCOM("pbus_clk",    PBUS_CLK,       NULL, 0),
-       CLK_PCOM("pcm_clk",     PCM_CLK,        NULL, 0),
-       CLK_PCOM("mddi_clk",    PMDH_CLK,       NULL, OFF | CLK_MINMAX),
-       CLK_PCOM("sdac_clk",    SDAC_CLK,       NULL, OFF),
-       CLK_PCOM("sdc_clk",     SDC1_CLK,       "msm_sdcc.1", OFF),
-       CLK_PCOM("sdc_pclk",    SDC1_P_CLK,     "msm_sdcc.1", OFF),
-       CLK_PCOM("sdc_clk",     SDC2_CLK,       "msm_sdcc.2", OFF),
-       CLK_PCOM("sdc_pclk",    SDC2_P_CLK,     "msm_sdcc.2", OFF),
-       CLK_PCOM("sdc_clk",     SDC3_CLK,       "msm_sdcc.3", OFF),
-       CLK_PCOM("sdc_pclk",    SDC3_P_CLK,     "msm_sdcc.3", OFF),
-       CLK_PCOM("sdc_clk",     SDC4_CLK,       "msm_sdcc.4", OFF),
-       CLK_PCOM("sdc_pclk",    SDC4_P_CLK,     "msm_sdcc.4", OFF),
-       CLK_PCOM("tsif_clk",    TSIF_CLK,       NULL, 0),
-       CLK_PCOM("tsif_ref_clk",        TSIF_REF_CLK,   NULL, 0),
-       CLK_PCOM("tv_dac_clk",  TV_DAC_CLK,     NULL, 0),
-       CLK_PCOM("tv_enc_clk",  TV_ENC_CLK,     NULL, 0),
-       CLK_PCOM("core",        UART1_CLK,      "msm_serial.0", OFF),
-       CLK_PCOM("core",        UART2_CLK,      "msm_serial.1", 0),
-       CLK_PCOM("core",        UART3_CLK,      "msm_serial.2", OFF),
-       CLK_PCOM("uart1dm_clk", UART1DM_CLK,    NULL, OFF),
-       CLK_PCOM("uart2dm_clk", UART2DM_CLK,    NULL, 0),
-       CLK_PCOM("usb_hs_clk",  USB_HS_CLK,     "msm_hsusb", OFF),
-       CLK_PCOM("usb_hs_pclk", USB_HS_P_CLK,   "msm_hsusb", OFF),
-       CLK_PCOM("usb_otg_clk", USB_OTG_CLK,    NULL, 0),
-       CLK_PCOM("vdc_clk",     VDC_CLK,        NULL, OFF ),
-       CLK_PCOM("vfe_clk",     VFE_CLK,        NULL, OFF),
-       CLK_PCOM("vfe_mdc_clk", VFE_MDC_CLK,    NULL, OFF),
-};
-
-static struct pcom_clk_pdata msm_clock_7x01a_pdata = {
-       .lookup = msm_clocks_7x01a,
-       .num_lookups = ARRAY_SIZE(msm_clocks_7x01a),
-};
-
-struct platform_device msm_clock_7x01a = {
-       .name = "msm-clock-pcom",
-       .dev.platform_data = &msm_clock_7x01a_pdata,
-};
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
deleted file mode 100644 (file)
index c15ea8a..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-
-#include <linux/dma-mapping.h>
-#include <linux/clkdev.h>
-#include <mach/irqs.h>
-#include <mach/msm_iomap.h>
-#include <mach/dma.h>
-
-#include "devices.h"
-#include "smd_private.h"
-#include "common.h"
-
-#include <asm/mach/flash.h>
-
-#include "clock.h"
-#include "clock-pcom.h"
-
-#include <linux/platform_data/mmc-msm_sdcc.h>
-
-static struct resource msm_gpio_resources[] = {
-       {
-               .start  = 32 + 18,
-               .end    = 32 + 18,
-               .flags  = IORESOURCE_IRQ,
-       },
-       {
-               .start  = 32 + 19,
-               .end    = 32 + 19,
-               .flags  = IORESOURCE_IRQ,
-       },
-       {
-               .start  = 0xac001000,
-               .end    = 0xac001000 + SZ_4K - 1,
-               .flags  = IORESOURCE_MEM,
-               .name  = "gpio1"
-       },
-       {
-               .start  = 0xac101400,
-               .end    = 0xac101400 + SZ_4K - 1,
-               .flags  = IORESOURCE_MEM,
-               .name  = "gpio2"
-       },
-};
-
-struct platform_device msm_device_gpio_7x30 = {
-       .name   = "gpio-msm-7x30",
-       .num_resources  = ARRAY_SIZE(msm_gpio_resources),
-       .resource       = msm_gpio_resources,
-};
-
-static struct resource resources_uart2[] = {
-       {
-               .start  = INT_UART2,
-               .end    = INT_UART2,
-               .flags  = IORESOURCE_IRQ,
-       },
-       {
-               .start  = MSM_UART2_PHYS,
-               .end    = MSM_UART2_PHYS + MSM_UART2_SIZE - 1,
-               .flags  = IORESOURCE_MEM,
-               .name  = "uart_resource"
-       },
-};
-
-struct platform_device msm_device_uart2 = {
-       .name   = "msm_serial",
-       .id     = 1,
-       .num_resources  = ARRAY_SIZE(resources_uart2),
-       .resource       = resources_uart2,
-};
-
-struct platform_device msm_device_smd = {
-       .name   = "msm_smd",
-       .id     = -1,
-};
-
-static struct resource resources_otg[] = {
-       {
-               .start  = MSM_HSUSB_PHYS,
-               .end    = MSM_HSUSB_PHYS + MSM_HSUSB_SIZE,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               .start  = INT_USB_HS,
-               .end    = INT_USB_HS,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device msm_device_otg = {
-       .name           = "msm_otg",
-       .id             = -1,
-       .num_resources  = ARRAY_SIZE(resources_otg),
-       .resource       = resources_otg,
-       .dev            = {
-               .coherent_dma_mask      = 0xffffffff,
-       },
-};
-
-static struct resource resources_hsusb[] = {
-       {
-               .start  = MSM_HSUSB_PHYS,
-               .end    = MSM_HSUSB_PHYS + MSM_HSUSB_SIZE,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               .start  = INT_USB_HS,
-               .end    = INT_USB_HS,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device msm_device_hsusb = {
-       .name           = "msm_hsusb",
-       .id             = -1,
-       .num_resources  = ARRAY_SIZE(resources_hsusb),
-       .resource       = resources_hsusb,
-       .dev            = {
-               .coherent_dma_mask      = 0xffffffff,
-       },
-};
-
-static u64 dma_mask = 0xffffffffULL;
-static struct resource resources_hsusb_host[] = {
-       {
-               .start  = MSM_HSUSB_PHYS,
-               .end    = MSM_HSUSB_PHYS + MSM_HSUSB_SIZE,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               .start  = INT_USB_HS,
-               .end    = INT_USB_HS,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device msm_device_hsusb_host = {
-       .name           = "msm_hsusb_host",
-       .id             = -1,
-       .num_resources  = ARRAY_SIZE(resources_hsusb_host),
-       .resource       = resources_hsusb_host,
-       .dev            = {
-               .dma_mask               = &dma_mask,
-               .coherent_dma_mask      = 0xffffffffULL,
-       },
-};
-
-static struct clk_pcom_desc msm_clocks_7x30[] = {
-       CLK_PCOM("adm_clk",     ADM_CLK,        NULL, 0),
-       CLK_PCOM("adsp_clk",    ADSP_CLK,       NULL, 0),
-       CLK_PCOM("cam_m_clk",   CAM_M_CLK,      NULL, 0),
-       CLK_PCOM("camif_pad_pclk",      CAMIF_PAD_P_CLK,        NULL, OFF),
-       CLK_PCOM("ce_clk",      CE_CLK, NULL, 0),
-       CLK_PCOM("codec_ssbi_clk",      CODEC_SSBI_CLK, NULL, 0),
-       CLK_PCOM("ebi1_clk",    EBI1_CLK,       NULL, CLK_MIN),
-       CLK_PCOM("ecodec_clk",  ECODEC_CLK,     NULL, 0),
-       CLK_PCOM("emdh_clk",    EMDH_CLK,       NULL, OFF | CLK_MINMAX),
-       CLK_PCOM("emdh_pclk",   EMDH_P_CLK,     NULL, OFF),
-       CLK_PCOM("gp_clk",      GP_CLK,         NULL, 0),
-       CLK_PCOM("grp_2d_clk",  GRP_2D_CLK,     NULL, 0),
-       CLK_PCOM("grp_2d_pclk", GRP_2D_P_CLK,   NULL, 0),
-       CLK_PCOM("grp_clk",     GRP_3D_CLK,     NULL, 0),
-       CLK_PCOM("grp_pclk",    GRP_3D_P_CLK,   NULL, 0),
-       CLK_PCOM("hdmi_clk",    HDMI_CLK,       NULL, 0),
-       CLK_PCOM("imem_clk",    IMEM_CLK,       NULL, OFF),
-       CLK_PCOM("jpeg_clk",    JPEG_CLK,       NULL, OFF),
-       CLK_PCOM("jpeg_pclk",   JPEG_P_CLK,     NULL, OFF),
-       CLK_PCOM("lpa_codec_clk",       LPA_CODEC_CLK,          NULL, 0),
-       CLK_PCOM("lpa_core_clk",        LPA_CORE_CLK,           NULL, 0),
-       CLK_PCOM("lpa_pclk",            LPA_P_CLK,              NULL, 0),
-       CLK_PCOM("mdc_clk",     MDC_CLK,        NULL, 0),
-       CLK_PCOM("mddi_clk",    PMDH_CLK,       NULL, OFF | CLK_MINMAX),
-       CLK_PCOM("mddi_pclk",   PMDH_P_CLK,     NULL, 0),
-       CLK_PCOM("mdp_clk",     MDP_CLK,        NULL, OFF),
-       CLK_PCOM("mdp_pclk",    MDP_P_CLK,      NULL, 0),
-       CLK_PCOM("mdp_lcdc_pclk_clk", MDP_LCDC_PCLK_CLK, NULL, 0),
-       CLK_PCOM("mdp_lcdc_pad_pclk_clk", MDP_LCDC_PAD_PCLK_CLK, NULL, 0),
-       CLK_PCOM("mdp_vsync_clk",       MDP_VSYNC_CLK,  NULL, 0),
-       CLK_PCOM("mfc_clk",             MFC_CLK,                NULL, 0),
-       CLK_PCOM("mfc_div2_clk",        MFC_DIV2_CLK,           NULL, 0),
-       CLK_PCOM("mfc_pclk",            MFC_P_CLK,              NULL, 0),
-       CLK_PCOM("mi2s_m_clk",          MI2S_M_CLK,             NULL, 0),
-       CLK_PCOM("mi2s_s_clk",          MI2S_S_CLK,             NULL, 0),
-       CLK_PCOM("mi2s_codec_rx_m_clk", MI2S_CODEC_RX_M_CLK,  NULL, 0),
-       CLK_PCOM("mi2s_codec_rx_s_clk", MI2S_CODEC_RX_S_CLK,  NULL, 0),
-       CLK_PCOM("mi2s_codec_tx_m_clk", MI2S_CODEC_TX_M_CLK,  NULL, 0),
-       CLK_PCOM("mi2s_codec_tx_s_clk", MI2S_CODEC_TX_S_CLK,  NULL, 0),
-       CLK_PCOM("pbus_clk",    PBUS_CLK,       NULL, CLK_MIN),
-       CLK_PCOM("pcm_clk",     PCM_CLK,        NULL, 0),
-       CLK_PCOM("rotator_clk", AXI_ROTATOR_CLK,                NULL, 0),
-       CLK_PCOM("rotator_imem_clk",    ROTATOR_IMEM_CLK,       NULL, OFF),
-       CLK_PCOM("rotator_pclk",        ROTATOR_P_CLK,          NULL, OFF),
-       CLK_PCOM("sdac_clk",    SDAC_CLK,       NULL, OFF),
-       CLK_PCOM("spi_clk",     SPI_CLK,        NULL, 0),
-       CLK_PCOM("spi_pclk",    SPI_P_CLK,      NULL, 0),
-       CLK_PCOM("tv_dac_clk",  TV_DAC_CLK,     NULL, 0),
-       CLK_PCOM("tv_enc_clk",  TV_ENC_CLK,     NULL, 0),
-       CLK_PCOM("core",        UART2_CLK,      "msm_serial.1", 0),
-       CLK_PCOM("usb_phy_clk", USB_PHY_CLK,    NULL, 0),
-       CLK_PCOM("usb_hs_clk",          USB_HS_CLK,             NULL, OFF),
-       CLK_PCOM("usb_hs_pclk",         USB_HS_P_CLK,           NULL, OFF),
-       CLK_PCOM("usb_hs_core_clk",     USB_HS_CORE_CLK,        NULL, OFF),
-       CLK_PCOM("usb_hs2_clk",         USB_HS2_CLK,            NULL, OFF),
-       CLK_PCOM("usb_hs2_pclk",        USB_HS2_P_CLK,          NULL, OFF),
-       CLK_PCOM("usb_hs2_core_clk",    USB_HS2_CORE_CLK,       NULL, OFF),
-       CLK_PCOM("usb_hs3_clk",         USB_HS3_CLK,            NULL, OFF),
-       CLK_PCOM("usb_hs3_pclk",        USB_HS3_P_CLK,          NULL, OFF),
-       CLK_PCOM("usb_hs3_core_clk",    USB_HS3_CORE_CLK,       NULL, OFF),
-       CLK_PCOM("vdc_clk",     VDC_CLK,        NULL, OFF | CLK_MIN),
-       CLK_PCOM("vfe_camif_clk",       VFE_CAMIF_CLK,  NULL, 0),
-       CLK_PCOM("vfe_clk",     VFE_CLK,        NULL, 0),
-       CLK_PCOM("vfe_mdc_clk", VFE_MDC_CLK,    NULL, 0),
-       CLK_PCOM("vfe_pclk",    VFE_P_CLK,      NULL, OFF),
-       CLK_PCOM("vpe_clk",     VPE_CLK,        NULL, 0),
-
-       /* 7x30 v2 hardware only. */
-       CLK_PCOM("csi_clk",     CSI0_CLK,       NULL, 0),
-       CLK_PCOM("csi_pclk",    CSI0_P_CLK,     NULL, 0),
-       CLK_PCOM("csi_vfe_clk", CSI0_VFE_CLK,   NULL, 0),
-};
-
-static struct pcom_clk_pdata msm_clock_7x30_pdata = {
-       .lookup = msm_clocks_7x30,
-       .num_lookups = ARRAY_SIZE(msm_clocks_7x30),
-};
-
-struct platform_device msm_clock_7x30 = {
-       .name = "msm-clock-pcom",
-       .dev.platform_data = &msm_clock_7x30_pdata,
-};
diff --git a/arch/arm/mach-msm/devices-qsd8x50.c b/arch/arm/mach-msm/devices-qsd8x50.c
deleted file mode 100644 (file)
index 9e1e9ce..0000000
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- * Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/clkdev.h>
-#include <linux/dma-mapping.h>
-
-#include <mach/irqs.h>
-#include <mach/msm_iomap.h>
-#include <mach/dma.h>
-
-#include "devices.h"
-#include "common.h"
-
-#include <asm/mach/flash.h>
-
-#include <linux/platform_data/mmc-msm_sdcc.h>
-#include "clock.h"
-#include "clock-pcom.h"
-
-static struct resource msm_gpio_resources[] = {
-       {
-               .start  = 64 + 165 + 9,
-               .end    = 64 + 165 + 9,
-               .flags  = IORESOURCE_IRQ,
-       },
-       {
-               .start  = 64 + 165 + 10,
-               .end    = 64 + 165 + 10,
-               .flags  = IORESOURCE_IRQ,
-       },
-       {
-               .start  = 0xa9000800,
-               .end    = 0xa9000800 + SZ_4K - 1,
-               .flags  = IORESOURCE_MEM,
-               .name  = "gpio1"
-       },
-       {
-               .start  = 0xa9100C00,
-               .end    = 0xa9100C00 + SZ_4K - 1,
-               .flags  = IORESOURCE_MEM,
-               .name  = "gpio2"
-       },
-};
-
-struct platform_device msm_device_gpio_8x50 = {
-       .name   = "gpio-msm-8x50",
-       .num_resources  = ARRAY_SIZE(msm_gpio_resources),
-       .resource       = msm_gpio_resources,
-};
-
-static struct resource resources_uart3[] = {
-       {
-               .start  = INT_UART3,
-               .end    = INT_UART3,
-               .flags  = IORESOURCE_IRQ,
-       },
-       {
-               .start  = MSM_UART3_PHYS,
-               .end    = MSM_UART3_PHYS + MSM_UART3_SIZE - 1,
-               .flags  = IORESOURCE_MEM,
-               .name  = "uart_resource"
-       },
-};
-
-struct platform_device msm_device_uart3 = {
-       .name   = "msm_serial",
-       .id     = 2,
-       .num_resources  = ARRAY_SIZE(resources_uart3),
-       .resource       = resources_uart3,
-};
-
-struct platform_device msm_device_smd = {
-       .name   = "msm_smd",
-       .id     = -1,
-};
-
-static struct resource resources_otg[] = {
-       {
-               .start  = MSM_HSUSB_PHYS,
-               .end    = MSM_HSUSB_PHYS + MSM_HSUSB_SIZE,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               .start  = INT_USB_HS,
-               .end    = INT_USB_HS,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device msm_device_otg = {
-       .name           = "msm_otg",
-       .id             = -1,
-       .num_resources  = ARRAY_SIZE(resources_otg),
-       .resource       = resources_otg,
-       .dev            = {
-               .coherent_dma_mask      = 0xffffffff,
-       },
-};
-
-static struct resource resources_hsusb[] = {
-       {
-               .start  = MSM_HSUSB_PHYS,
-               .end    = MSM_HSUSB_PHYS + MSM_HSUSB_SIZE,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               .start  = INT_USB_HS,
-               .end    = INT_USB_HS,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device msm_device_hsusb = {
-       .name           = "msm_hsusb",
-       .id             = -1,
-       .num_resources  = ARRAY_SIZE(resources_hsusb),
-       .resource       = resources_hsusb,
-       .dev            = {
-               .coherent_dma_mask      = 0xffffffff,
-       },
-};
-
-static u64 dma_mask = 0xffffffffULL;
-static struct resource resources_hsusb_host[] = {
-       {
-               .start  = MSM_HSUSB_PHYS,
-               .end    = MSM_HSUSB_PHYS + MSM_HSUSB_SIZE,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               .start  = INT_USB_HS,
-               .end    = INT_USB_HS,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device msm_device_hsusb_host = {
-       .name           = "msm_hsusb_host",
-       .id             = -1,
-       .num_resources  = ARRAY_SIZE(resources_hsusb_host),
-       .resource       = resources_hsusb_host,
-       .dev            = {
-               .dma_mask               = &dma_mask,
-               .coherent_dma_mask      = 0xffffffffULL,
-       },
-};
-
-static struct resource resources_sdc1[] = {
-       {
-               .start  = MSM_SDC1_PHYS,
-               .end    = MSM_SDC1_PHYS + MSM_SDC1_SIZE - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               .start  = INT_SDC1_0,
-               .end    = INT_SDC1_0,
-               .flags  = IORESOURCE_IRQ,
-               .name   = "cmd_irq",
-       },
-       {
-               .flags  = IORESOURCE_IRQ | IORESOURCE_DISABLED,
-               .name   = "status_irq"
-       },
-       {
-               .start  = 8,
-               .end    = 8,
-               .flags  = IORESOURCE_DMA,
-       },
-};
-
-static struct resource resources_sdc2[] = {
-       {
-               .start  = MSM_SDC2_PHYS,
-               .end    = MSM_SDC2_PHYS + MSM_SDC2_SIZE - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               .start  = INT_SDC2_0,
-               .end    = INT_SDC2_0,
-               .flags  = IORESOURCE_IRQ,
-               .name   = "cmd_irq",
-       },
-       {
-               .flags  = IORESOURCE_IRQ | IORESOURCE_DISABLED,
-               .name   = "status_irq"
-       },
-       {
-               .start  = 8,
-               .end    = 8,
-               .flags  = IORESOURCE_DMA,
-       },
-};
-
-static struct resource resources_sdc3[] = {
-       {
-               .start  = MSM_SDC3_PHYS,
-               .end    = MSM_SDC3_PHYS + MSM_SDC3_SIZE - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               .start  = INT_SDC3_0,
-               .end    = INT_SDC3_0,
-               .flags  = IORESOURCE_IRQ,
-               .name   = "cmd_irq",
-       },
-       {
-               .flags  = IORESOURCE_IRQ | IORESOURCE_DISABLED,
-               .name   = "status_irq"
-       },
-       {
-               .start  = 8,
-               .end    = 8,
-               .flags  = IORESOURCE_DMA,
-       },
-};
-
-static struct resource resources_sdc4[] = {
-       {
-               .start  = MSM_SDC4_PHYS,
-               .end    = MSM_SDC4_PHYS + MSM_SDC4_SIZE - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               .start  = INT_SDC4_0,
-               .end    = INT_SDC4_0,
-               .flags  = IORESOURCE_IRQ,
-               .name   = "cmd_irq",
-       },
-       {
-               .flags  = IORESOURCE_IRQ | IORESOURCE_DISABLED,
-               .name   = "status_irq"
-       },
-       {
-               .start  = 8,
-               .end    = 8,
-               .flags  = IORESOURCE_DMA,
-       },
-};
-
-struct platform_device msm_device_sdc1 = {
-       .name           = "msm_sdcc",
-       .id             = 1,
-       .num_resources  = ARRAY_SIZE(resources_sdc1),
-       .resource       = resources_sdc1,
-       .dev            = {
-               .coherent_dma_mask      = 0xffffffff,
-       },
-};
-
-struct platform_device msm_device_sdc2 = {
-       .name           = "msm_sdcc",
-       .id             = 2,
-       .num_resources  = ARRAY_SIZE(resources_sdc2),
-       .resource       = resources_sdc2,
-       .dev            = {
-               .coherent_dma_mask      = 0xffffffff,
-       },
-};
-
-struct platform_device msm_device_sdc3 = {
-       .name           = "msm_sdcc",
-       .id             = 3,
-       .num_resources  = ARRAY_SIZE(resources_sdc3),
-       .resource       = resources_sdc3,
-       .dev            = {
-               .coherent_dma_mask      = 0xffffffff,
-       },
-};
-
-struct platform_device msm_device_sdc4 = {
-       .name           = "msm_sdcc",
-       .id             = 4,
-       .num_resources  = ARRAY_SIZE(resources_sdc4),
-       .resource       = resources_sdc4,
-       .dev            = {
-               .coherent_dma_mask      = 0xffffffff,
-       },
-};
-
-static struct platform_device *msm_sdcc_devices[] __initdata = {
-       &msm_device_sdc1,
-       &msm_device_sdc2,
-       &msm_device_sdc3,
-       &msm_device_sdc4,
-};
-
-int __init msm_add_sdcc(unsigned int controller,
-                       struct msm_mmc_platform_data *plat,
-                       unsigned int stat_irq, unsigned long stat_irq_flags)
-{
-       struct platform_device  *pdev;
-       struct resource *res;
-
-       if (controller < 1 || controller > 4)
-               return -EINVAL;
-
-       pdev = msm_sdcc_devices[controller-1];
-       pdev->dev.platform_data = plat;
-
-       res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "status_irq");
-       if (!res)
-               return -EINVAL;
-       else if (stat_irq) {
-               res->start = res->end = stat_irq;
-               res->flags &= ~IORESOURCE_DISABLED;
-               res->flags |= stat_irq_flags;
-       }
-
-       return platform_device_register(pdev);
-}
-
-static struct clk_pcom_desc msm_clocks_8x50[] = {
-       CLK_PCOM("adm_clk",     ADM_CLK,        NULL, 0),
-       CLK_PCOM("ce_clk",      CE_CLK,         NULL, 0),
-       CLK_PCOM("ebi1_clk",    EBI1_CLK,       NULL, CLK_MIN),
-       CLK_PCOM("ebi2_clk",    EBI2_CLK,       NULL, 0),
-       CLK_PCOM("ecodec_clk",  ECODEC_CLK,     NULL, 0),
-       CLK_PCOM("emdh_clk",    EMDH_CLK,       NULL, OFF | CLK_MINMAX),
-       CLK_PCOM("gp_clk",      GP_CLK,         NULL, 0),
-       CLK_PCOM("grp_clk",     GRP_3D_CLK,     NULL, 0),
-       CLK_PCOM("i2c_clk",     I2C_CLK,        NULL, 0),
-       CLK_PCOM("icodec_rx_clk",       ICODEC_RX_CLK,  NULL, 0),
-       CLK_PCOM("icodec_tx_clk",       ICODEC_TX_CLK,  NULL, 0),
-       CLK_PCOM("imem_clk",    IMEM_CLK,       NULL, OFF),
-       CLK_PCOM("mdc_clk",     MDC_CLK,        NULL, 0),
-       CLK_PCOM("mddi_clk",    PMDH_CLK,       NULL, OFF | CLK_MINMAX),
-       CLK_PCOM("mdp_clk",     MDP_CLK,        NULL, OFF),
-       CLK_PCOM("mdp_lcdc_pclk_clk", MDP_LCDC_PCLK_CLK, NULL, 0),
-       CLK_PCOM("mdp_lcdc_pad_pclk_clk", MDP_LCDC_PAD_PCLK_CLK, NULL, 0),
-       CLK_PCOM("mdp_vsync_clk",       MDP_VSYNC_CLK,  NULL, 0),
-       CLK_PCOM("pbus_clk",    PBUS_CLK,       NULL, CLK_MIN),
-       CLK_PCOM("pcm_clk",     PCM_CLK,        NULL, 0),
-       CLK_PCOM("sdac_clk",    SDAC_CLK,       NULL, OFF),
-       CLK_PCOM("sdc_clk",     SDC1_CLK,       "msm_sdcc.1", OFF),
-       CLK_PCOM("sdc_pclk",    SDC1_P_CLK,     "msm_sdcc.1", OFF),
-       CLK_PCOM("sdc_clk",     SDC2_CLK,       "msm_sdcc.2", OFF),
-       CLK_PCOM("sdc_pclk",    SDC2_P_CLK,     "msm_sdcc.2", OFF),
-       CLK_PCOM("sdc_clk",     SDC3_CLK,       "msm_sdcc.3", OFF),
-       CLK_PCOM("sdc_pclk",    SDC3_P_CLK,     "msm_sdcc.3", OFF),
-       CLK_PCOM("sdc_clk",     SDC4_CLK,       "msm_sdcc.4", OFF),
-       CLK_PCOM("sdc_pclk",    SDC4_P_CLK,     "msm_sdcc.4", OFF),
-       CLK_PCOM("spi_clk",     SPI_CLK,        NULL, 0),
-       CLK_PCOM("tsif_clk",    TSIF_CLK,       NULL, 0),
-       CLK_PCOM("tsif_ref_clk",        TSIF_REF_CLK,   NULL, 0),
-       CLK_PCOM("tv_dac_clk",  TV_DAC_CLK,     NULL, 0),
-       CLK_PCOM("tv_enc_clk",  TV_ENC_CLK,     NULL, 0),
-       CLK_PCOM("core",        UART1_CLK,      NULL, OFF),
-       CLK_PCOM("core",        UART2_CLK,      NULL, 0),
-       CLK_PCOM("core",        UART3_CLK,      "msm_serial.2", OFF),
-       CLK_PCOM("uartdm_clk",  UART1DM_CLK,    NULL, OFF),
-       CLK_PCOM("uartdm_clk",  UART2DM_CLK,    NULL, 0),
-       CLK_PCOM("usb_hs_clk",  USB_HS_CLK,     NULL, OFF),
-       CLK_PCOM("usb_hs_pclk", USB_HS_P_CLK,   NULL, OFF),
-       CLK_PCOM("usb_otg_clk", USB_OTG_CLK,    NULL, 0),
-       CLK_PCOM("vdc_clk",     VDC_CLK,        NULL, OFF | CLK_MIN),
-       CLK_PCOM("vfe_clk",     VFE_CLK,        NULL, OFF),
-       CLK_PCOM("vfe_mdc_clk", VFE_MDC_CLK,    NULL, OFF),
-       CLK_PCOM("vfe_axi_clk", VFE_AXI_CLK,    NULL, OFF),
-       CLK_PCOM("usb_hs2_clk", USB_HS2_CLK,    NULL, OFF),
-       CLK_PCOM("usb_hs2_pclk",        USB_HS2_P_CLK,  NULL, OFF),
-       CLK_PCOM("usb_hs3_clk", USB_HS3_CLK,    NULL, OFF),
-       CLK_PCOM("usb_hs3_pclk",        USB_HS3_P_CLK,  NULL, OFF),
-       CLK_PCOM("usb_phy_clk", USB_PHY_CLK,    NULL, 0),
-};
-
-static struct pcom_clk_pdata msm_clock_8x50_pdata = {
-       .lookup = msm_clocks_8x50,
-       .num_lookups = ARRAY_SIZE(msm_clocks_8x50),
-};
-
-struct platform_device msm_clock_8x50 = {
-       .name = "msm-clock-pcom",
-       .dev.platform_data = &msm_clock_8x50_pdata,
-};
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
deleted file mode 100644 (file)
index dccefad..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/* linux/arch/arm/mach-msm/devices.h
- *
- * Copyright (C) 2008 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __ARCH_ARM_MACH_MSM_DEVICES_H
-#define __ARCH_ARM_MACH_MSM_DEVICES_H
-
-extern struct platform_device msm_device_gpio_7201;
-extern struct platform_device msm_device_gpio_7x30;
-extern struct platform_device msm_device_gpio_8x50;
-
-extern struct platform_device msm_device_uart1;
-extern struct platform_device msm_device_uart2;
-extern struct platform_device msm_device_uart3;
-
-extern struct platform_device msm8960_device_uart_gsbi2;
-extern struct platform_device msm8960_device_uart_gsbi5;
-
-extern struct platform_device msm_device_sdc1;
-extern struct platform_device msm_device_sdc2;
-extern struct platform_device msm_device_sdc3;
-extern struct platform_device msm_device_sdc4;
-
-extern struct platform_device msm_device_hsusb;
-extern struct platform_device msm_device_otg;
-extern struct platform_device msm_device_hsusb_host;
-
-extern struct platform_device msm_device_i2c;
-
-extern struct platform_device msm_device_smd;
-
-extern struct platform_device msm_device_nand;
-
-extern struct platform_device msm_device_mddi0;
-extern struct platform_device msm_device_mddi1;
-extern struct platform_device msm_device_mdp;
-
-extern struct platform_device msm_clock_7x01a;
-extern struct platform_device msm_clock_7x30;
-extern struct platform_device msm_clock_8x50;
-
-#endif
diff --git a/arch/arm/mach-msm/dma.c b/arch/arm/mach-msm/dma.c
deleted file mode 100644 (file)
index fb97624..0000000
+++ /dev/null
@@ -1,298 +0,0 @@
-/* linux/arch/arm/mach-msm/dma.c
- *
- * Copyright (C) 2007 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/completion.h>
-#include <linux/module.h>
-#include <mach/dma.h>
-#include <mach/msm_iomap.h>
-
-#define MSM_DMOV_CHANNEL_COUNT 16
-
-#define DMOV_SD0(off, ch) (MSM_DMOV_BASE + 0x0000 + (off) + ((ch) << 2))
-#define DMOV_SD1(off, ch) (MSM_DMOV_BASE + 0x0400 + (off) + ((ch) << 2))
-#define DMOV_SD2(off, ch) (MSM_DMOV_BASE + 0x0800 + (off) + ((ch) << 2))
-#define DMOV_SD3(off, ch) (MSM_DMOV_BASE + 0x0C00 + (off) + ((ch) << 2))
-
-#if defined(CONFIG_ARCH_MSM7X30)
-#define DMOV_SD_AARM DMOV_SD2
-#else
-#define DMOV_SD_AARM DMOV_SD3
-#endif
-
-#define DMOV_CMD_PTR(ch)      DMOV_SD_AARM(0x000, ch)
-#define DMOV_RSLT(ch)         DMOV_SD_AARM(0x040, ch)
-#define DMOV_FLUSH0(ch)       DMOV_SD_AARM(0x080, ch)
-#define DMOV_FLUSH1(ch)       DMOV_SD_AARM(0x0C0, ch)
-#define DMOV_FLUSH2(ch)       DMOV_SD_AARM(0x100, ch)
-#define DMOV_FLUSH3(ch)       DMOV_SD_AARM(0x140, ch)
-#define DMOV_FLUSH4(ch)       DMOV_SD_AARM(0x180, ch)
-#define DMOV_FLUSH5(ch)       DMOV_SD_AARM(0x1C0, ch)
-
-#define DMOV_STATUS(ch)       DMOV_SD_AARM(0x200, ch)
-#define DMOV_ISR              DMOV_SD_AARM(0x380, 0)
-
-#define DMOV_CONFIG(ch)       DMOV_SD_AARM(0x300, ch)
-
-enum {
-       MSM_DMOV_PRINT_ERRORS = 1,
-       MSM_DMOV_PRINT_IO = 2,
-       MSM_DMOV_PRINT_FLOW = 4
-};
-
-static DEFINE_SPINLOCK(msm_dmov_lock);
-static struct clk *msm_dmov_clk;
-static unsigned int channel_active;
-static struct list_head ready_commands[MSM_DMOV_CHANNEL_COUNT];
-static struct list_head active_commands[MSM_DMOV_CHANNEL_COUNT];
-unsigned int msm_dmov_print_mask = MSM_DMOV_PRINT_ERRORS;
-
-#define MSM_DMOV_DPRINTF(mask, format, args...) \
-       do { \
-               if ((mask) & msm_dmov_print_mask) \
-                       printk(KERN_ERR format, args); \
-       } while (0)
-#define PRINT_ERROR(format, args...) \
-       MSM_DMOV_DPRINTF(MSM_DMOV_PRINT_ERRORS, format, args);
-#define PRINT_IO(format, args...) \
-       MSM_DMOV_DPRINTF(MSM_DMOV_PRINT_IO, format, args);
-#define PRINT_FLOW(format, args...) \
-       MSM_DMOV_DPRINTF(MSM_DMOV_PRINT_FLOW, format, args);
-
-void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd, int graceful)
-{
-       writel((graceful << 31), DMOV_FLUSH0(id));
-}
-EXPORT_SYMBOL_GPL(msm_dmov_stop_cmd);
-
-void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd)
-{
-       unsigned long irq_flags;
-       unsigned int status;
-
-       spin_lock_irqsave(&msm_dmov_lock, irq_flags);
-       if (!channel_active)
-               clk_enable(msm_dmov_clk);
-       dsb();
-       status = readl(DMOV_STATUS(id));
-       if (list_empty(&ready_commands[id]) &&
-               (status & DMOV_STATUS_CMD_PTR_RDY)) {
-#if 0
-               if (list_empty(&active_commands[id])) {
-                       PRINT_FLOW("msm_dmov_enqueue_cmd(%d), enable interrupt\n", id);
-                       writel(DMOV_CONFIG_IRQ_EN, DMOV_CONFIG(id));
-               }
-#endif
-               if (cmd->execute_func)
-                       cmd->execute_func(cmd);
-               PRINT_IO("msm_dmov_enqueue_cmd(%d), start command, status %x\n", id, status);
-               list_add_tail(&cmd->list, &active_commands[id]);
-               if (!channel_active)
-                       enable_irq(INT_ADM_AARM);
-               channel_active |= 1U << id;
-               writel(cmd->cmdptr, DMOV_CMD_PTR(id));
-       } else {
-               if (!channel_active)
-                       clk_disable(msm_dmov_clk);
-               if (list_empty(&active_commands[id]))
-                       PRINT_ERROR("msm_dmov_enqueue_cmd(%d), error datamover stalled, status %x\n", id, status);
-
-               PRINT_IO("msm_dmov_enqueue_cmd(%d), enqueue command, status %x\n", id, status);
-               list_add_tail(&cmd->list, &ready_commands[id]);
-       }
-       spin_unlock_irqrestore(&msm_dmov_lock, irq_flags);
-}
-EXPORT_SYMBOL_GPL(msm_dmov_enqueue_cmd);
-
-struct msm_dmov_exec_cmdptr_cmd {
-       struct msm_dmov_cmd dmov_cmd;
-       struct completion complete;
-       unsigned id;
-       unsigned int result;
-       struct msm_dmov_errdata err;
-};
-
-static void
-dmov_exec_cmdptr_complete_func(struct msm_dmov_cmd *_cmd,
-                              unsigned int result,
-                              struct msm_dmov_errdata *err)
-{
-       struct msm_dmov_exec_cmdptr_cmd *cmd = container_of(_cmd, struct msm_dmov_exec_cmdptr_cmd, dmov_cmd);
-       cmd->result = result;
-       if (result != 0x80000002 && err)
-               memcpy(&cmd->err, err, sizeof(struct msm_dmov_errdata));
-
-       complete(&cmd->complete);
-}
-
-int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr)
-{
-       struct msm_dmov_exec_cmdptr_cmd cmd;
-
-       PRINT_FLOW("dmov_exec_cmdptr(%d, %x)\n", id, cmdptr);
-
-       cmd.dmov_cmd.cmdptr = cmdptr;
-       cmd.dmov_cmd.complete_func = dmov_exec_cmdptr_complete_func;
-       cmd.dmov_cmd.execute_func = NULL;
-       cmd.id = id;
-       init_completion(&cmd.complete);
-
-       msm_dmov_enqueue_cmd(id, &cmd.dmov_cmd);
-       wait_for_completion(&cmd.complete);
-
-       if (cmd.result != 0x80000002) {
-               PRINT_ERROR("dmov_exec_cmdptr(%d): ERROR, result: %x\n", id, cmd.result);
-               PRINT_ERROR("dmov_exec_cmdptr(%d):  flush: %x %x %x %x\n",
-                       id, cmd.err.flush[0], cmd.err.flush[1], cmd.err.flush[2], cmd.err.flush[3]);
-               return -EIO;
-       }
-       PRINT_FLOW("dmov_exec_cmdptr(%d, %x) done\n", id, cmdptr);
-       return 0;
-}
-
-
-static irqreturn_t msm_datamover_irq_handler(int irq, void *dev_id)
-{
-       unsigned int int_status, mask, id;
-       unsigned long irq_flags;
-       unsigned int ch_status;
-       unsigned int ch_result;
-       struct msm_dmov_cmd *cmd;
-
-       spin_lock_irqsave(&msm_dmov_lock, irq_flags);
-
-       int_status = readl(DMOV_ISR); /* read and clear interrupt */
-       PRINT_FLOW("msm_datamover_irq_handler: DMOV_ISR %x\n", int_status);
-
-       while (int_status) {
-               mask = int_status & -int_status;
-               id = fls(mask) - 1;
-               PRINT_FLOW("msm_datamover_irq_handler %08x %08x id %d\n", int_status, mask, id);
-               int_status &= ~mask;
-               ch_status = readl(DMOV_STATUS(id));
-               if (!(ch_status & DMOV_STATUS_RSLT_VALID)) {
-                       PRINT_FLOW("msm_datamover_irq_handler id %d, result not valid %x\n", id, ch_status);
-                       continue;
-               }
-               do {
-                       ch_result = readl(DMOV_RSLT(id));
-                       if (list_empty(&active_commands[id])) {
-                               PRINT_ERROR("msm_datamover_irq_handler id %d, got result "
-                                       "with no active command, status %x, result %x\n",
-                                       id, ch_status, ch_result);
-                               cmd = NULL;
-                       } else
-                               cmd = list_entry(active_commands[id].next, typeof(*cmd), list);
-                       PRINT_FLOW("msm_datamover_irq_handler id %d, status %x, result %x\n", id, ch_status, ch_result);
-                       if (ch_result & DMOV_RSLT_DONE) {
-                               PRINT_FLOW("msm_datamover_irq_handler id %d, status %x\n",
-                                       id, ch_status);
-                               PRINT_IO("msm_datamover_irq_handler id %d, got result "
-                                       "for %p, result %x\n", id, cmd, ch_result);
-                               if (cmd) {
-                                       list_del(&cmd->list);
-                                       dsb();
-                                       cmd->complete_func(cmd, ch_result, NULL);
-                               }
-                       }
-                       if (ch_result & DMOV_RSLT_FLUSH) {
-                               struct msm_dmov_errdata errdata;
-
-                               errdata.flush[0] = readl(DMOV_FLUSH0(id));
-                               errdata.flush[1] = readl(DMOV_FLUSH1(id));
-                               errdata.flush[2] = readl(DMOV_FLUSH2(id));
-                               errdata.flush[3] = readl(DMOV_FLUSH3(id));
-                               errdata.flush[4] = readl(DMOV_FLUSH4(id));
-                               errdata.flush[5] = readl(DMOV_FLUSH5(id));
-                               PRINT_FLOW("msm_datamover_irq_handler id %d, status %x\n", id, ch_status);
-                               PRINT_FLOW("msm_datamover_irq_handler id %d, flush, result %x, flush0 %x\n", id, ch_result, errdata.flush[0]);
-                               if (cmd) {
-                                       list_del(&cmd->list);
-                                       dsb();
-                                       cmd->complete_func(cmd, ch_result, &errdata);
-                               }
-                       }
-                       if (ch_result & DMOV_RSLT_ERROR) {
-                               struct msm_dmov_errdata errdata;
-
-                               errdata.flush[0] = readl(DMOV_FLUSH0(id));
-                               errdata.flush[1] = readl(DMOV_FLUSH1(id));
-                               errdata.flush[2] = readl(DMOV_FLUSH2(id));
-                               errdata.flush[3] = readl(DMOV_FLUSH3(id));
-                               errdata.flush[4] = readl(DMOV_FLUSH4(id));
-                               errdata.flush[5] = readl(DMOV_FLUSH5(id));
-
-                               PRINT_ERROR("msm_datamover_irq_handler id %d, status %x\n", id, ch_status);
-                               PRINT_ERROR("msm_datamover_irq_handler id %d, error, result %x, flush0 %x\n", id, ch_result, errdata.flush[0]);
-                               if (cmd) {
-                                       list_del(&cmd->list);
-                                       dsb();
-                                       cmd->complete_func(cmd, ch_result, &errdata);
-                               }
-                               /* this does not seem to work, once we get an error */
-                               /* the datamover will no longer accept commands */
-                               writel(0, DMOV_FLUSH0(id));
-                       }
-                       ch_status = readl(DMOV_STATUS(id));
-                       PRINT_FLOW("msm_datamover_irq_handler id %d, status %x\n", id, ch_status);
-                       if ((ch_status & DMOV_STATUS_CMD_PTR_RDY) && !list_empty(&ready_commands[id])) {
-                               cmd = list_entry(ready_commands[id].next, typeof(*cmd), list);
-                               list_move_tail(&cmd->list, &active_commands[id]);
-                               if (cmd->execute_func)
-                                       cmd->execute_func(cmd);
-                               PRINT_FLOW("msm_datamover_irq_handler id %d, start command\n", id);
-                               writel(cmd->cmdptr, DMOV_CMD_PTR(id));
-                       }
-               } while (ch_status & DMOV_STATUS_RSLT_VALID);
-               if (list_empty(&active_commands[id]) && list_empty(&ready_commands[id]))
-                       channel_active &= ~(1U << id);
-               PRINT_FLOW("msm_datamover_irq_handler id %d, status %x\n", id, ch_status);
-       }
-
-       if (!channel_active) {
-               disable_irq_nosync(INT_ADM_AARM);
-               clk_disable(msm_dmov_clk);
-       }
-
-       spin_unlock_irqrestore(&msm_dmov_lock, irq_flags);
-       return IRQ_HANDLED;
-}
-
-static int __init msm_init_datamover(void)
-{
-       int i;
-       int ret;
-       struct clk *clk;
-
-       for (i = 0; i < MSM_DMOV_CHANNEL_COUNT; i++) {
-               INIT_LIST_HEAD(&ready_commands[i]);
-               INIT_LIST_HEAD(&active_commands[i]);
-               writel(DMOV_CONFIG_IRQ_EN | DMOV_CONFIG_FORCE_TOP_PTR_RSLT | DMOV_CONFIG_FORCE_FLUSH_RSLT, DMOV_CONFIG(i));
-       }
-       clk = clk_get(NULL, "adm_clk");
-       if (IS_ERR(clk))
-               return PTR_ERR(clk);
-       clk_prepare(clk);
-       msm_dmov_clk = clk;
-       ret = request_irq(INT_ADM_AARM, msm_datamover_irq_handler, 0, "msmdatamover", NULL);
-       if (ret)
-               return ret;
-       disable_irq(INT_ADM_AARM);
-       return 0;
-}
-module_init(msm_init_datamover);
diff --git a/arch/arm/mach-msm/gpiomux-8x50.c b/arch/arm/mach-msm/gpiomux-8x50.c
deleted file mode 100644 (file)
index f7a4ea5..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only 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 Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-#include "gpiomux.h"
-
-#if defined(CONFIG_MMC_MSM) || defined(CONFIG_MMC_MSM_MODULE)
-       #define SDCC_DAT_0_3_CMD_ACTV_CFG (GPIOMUX_VALID | GPIOMUX_PULL_UP\
-                                       | GPIOMUX_FUNC_1 | GPIOMUX_DRV_8MA)
-       #define SDCC_CLK_ACTV_CFG (GPIOMUX_VALID | GPIOMUX_PULL_NONE\
-                                       | GPIOMUX_FUNC_1 | GPIOMUX_DRV_8MA)
-#else
-       #define SDCC_DAT_0_3_CMD_ACTV_CFG 0
-       #define SDCC_CLK_ACTV_CFG 0
-#endif
-
-#define SDC1_SUSPEND_CONFIG (GPIOMUX_VALID | GPIOMUX_PULL_DOWN\
-                               | GPIOMUX_FUNC_GPIO | GPIOMUX_DRV_2MA)
-
-struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {
-       [86] = { /* UART3 RX */
-               .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
-                            GPIOMUX_FUNC_1 | GPIOMUX_VALID,
-       },
-       [87] = { /* UART3 TX */
-               .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
-                            GPIOMUX_FUNC_1 | GPIOMUX_VALID,
-       },
-       /* SDC1 data[3:0] & CMD */
-       [51 ... 55] = {
-               .active = SDCC_DAT_0_3_CMD_ACTV_CFG,
-               .suspended = SDC1_SUSPEND_CONFIG
-       },
-       /* SDC1 CLK */
-       [56] = {
-               .active = SDCC_CLK_ACTV_CFG,
-               .suspended = SDC1_SUSPEND_CONFIG
-       },
-};
diff --git a/arch/arm/mach-msm/gpiomux-v1.h b/arch/arm/mach-msm/gpiomux-v1.h
deleted file mode 100644 (file)
index 71d86fe..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only 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 Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-#ifndef __ARCH_ARM_MACH_MSM_GPIOMUX_V1_H
-#define __ARCH_ARM_MACH_MSM_GPIOMUX_V1_H
-
-#if defined(CONFIG_ARCH_MSM7X30)
-#define GPIOMUX_NGPIOS 182
-#elif defined(CONFIG_ARCH_QSD8X50)
-#define GPIOMUX_NGPIOS 165
-#else
-#define GPIOMUX_NGPIOS 133
-#endif
-
-typedef u32 gpiomux_config_t;
-
-enum {
-       GPIOMUX_DRV_2MA  = 0UL << 17,
-       GPIOMUX_DRV_4MA  = 1UL << 17,
-       GPIOMUX_DRV_6MA  = 2UL << 17,
-       GPIOMUX_DRV_8MA  = 3UL << 17,
-       GPIOMUX_DRV_10MA = 4UL << 17,
-       GPIOMUX_DRV_12MA = 5UL << 17,
-       GPIOMUX_DRV_14MA = 6UL << 17,
-       GPIOMUX_DRV_16MA = 7UL << 17,
-};
-
-enum {
-       GPIOMUX_FUNC_GPIO = 0UL,
-       GPIOMUX_FUNC_1    = 1UL,
-       GPIOMUX_FUNC_2    = 2UL,
-       GPIOMUX_FUNC_3    = 3UL,
-       GPIOMUX_FUNC_4    = 4UL,
-       GPIOMUX_FUNC_5    = 5UL,
-       GPIOMUX_FUNC_6    = 6UL,
-       GPIOMUX_FUNC_7    = 7UL,
-       GPIOMUX_FUNC_8    = 8UL,
-       GPIOMUX_FUNC_9    = 9UL,
-       GPIOMUX_FUNC_A    = 10UL,
-       GPIOMUX_FUNC_B    = 11UL,
-       GPIOMUX_FUNC_C    = 12UL,
-       GPIOMUX_FUNC_D    = 13UL,
-       GPIOMUX_FUNC_E    = 14UL,
-       GPIOMUX_FUNC_F    = 15UL,
-};
-
-enum {
-       GPIOMUX_PULL_NONE   = 0UL << 15,
-       GPIOMUX_PULL_DOWN   = 1UL << 15,
-       GPIOMUX_PULL_KEEPER = 2UL << 15,
-       GPIOMUX_PULL_UP     = 3UL << 15,
-};
-
-#endif
diff --git a/arch/arm/mach-msm/gpiomux.c b/arch/arm/mach-msm/gpiomux.c
deleted file mode 100644 (file)
index 2b8e2d2..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only 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 Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include "gpiomux.h"
-#include "proc_comm.h"
-
-static DEFINE_SPINLOCK(gpiomux_lock);
-
-static void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val)
-{
-       unsigned tlmm_config  = (val & ~GPIOMUX_CTL_MASK) |
-                               ((gpio & 0x3ff) << 4);
-       unsigned tlmm_disable = 0;
-       int rc;
-
-       rc = msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX,
-                          &tlmm_config, &tlmm_disable);
-       if (rc)
-               pr_err("%s: unexpected proc_comm failure %d: %08x %08x\n",
-                      __func__, rc, tlmm_config, tlmm_disable);
-}
-
-int msm_gpiomux_write(unsigned gpio,
-                     gpiomux_config_t active,
-                     gpiomux_config_t suspended)
-{
-       struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio;
-       unsigned long irq_flags;
-       gpiomux_config_t setting;
-
-       if (gpio >= GPIOMUX_NGPIOS)
-               return -EINVAL;
-
-       spin_lock_irqsave(&gpiomux_lock, irq_flags);
-
-       if (active & GPIOMUX_VALID)
-               cfg->active = active;
-
-       if (suspended & GPIOMUX_VALID)
-               cfg->suspended = suspended;
-
-       setting = cfg->ref ? active : suspended;
-       if (setting & GPIOMUX_VALID)
-               __msm_gpiomux_write(gpio, setting);
-
-       spin_unlock_irqrestore(&gpiomux_lock, irq_flags);
-       return 0;
-}
-EXPORT_SYMBOL(msm_gpiomux_write);
-
-int msm_gpiomux_get(unsigned gpio)
-{
-       struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio;
-       unsigned long irq_flags;
-
-       if (gpio >= GPIOMUX_NGPIOS)
-               return -EINVAL;
-
-       spin_lock_irqsave(&gpiomux_lock, irq_flags);
-       if (cfg->ref++ == 0 && cfg->active & GPIOMUX_VALID)
-               __msm_gpiomux_write(gpio, cfg->active);
-       spin_unlock_irqrestore(&gpiomux_lock, irq_flags);
-       return 0;
-}
-EXPORT_SYMBOL(msm_gpiomux_get);
-
-int msm_gpiomux_put(unsigned gpio)
-{
-       struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio;
-       unsigned long irq_flags;
-
-       if (gpio >= GPIOMUX_NGPIOS)
-               return -EINVAL;
-
-       spin_lock_irqsave(&gpiomux_lock, irq_flags);
-       BUG_ON(cfg->ref == 0);
-       if (--cfg->ref == 0 && cfg->suspended & GPIOMUX_VALID)
-               __msm_gpiomux_write(gpio, cfg->suspended);
-       spin_unlock_irqrestore(&gpiomux_lock, irq_flags);
-       return 0;
-}
-EXPORT_SYMBOL(msm_gpiomux_put);
-
-static int __init gpiomux_init(void)
-{
-       unsigned n;
-
-       for (n = 0; n < GPIOMUX_NGPIOS; ++n) {
-               msm_gpiomux_configs[n].ref = 0;
-               if (!(msm_gpiomux_configs[n].suspended & GPIOMUX_VALID))
-                       continue;
-               __msm_gpiomux_write(n, msm_gpiomux_configs[n].suspended);
-       }
-       return 0;
-}
-postcore_initcall(gpiomux_init);
diff --git a/arch/arm/mach-msm/gpiomux.h b/arch/arm/mach-msm/gpiomux.h
deleted file mode 100644 (file)
index 4410d77..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only 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 Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-#ifndef __ARCH_ARM_MACH_MSM_GPIOMUX_H
-#define __ARCH_ARM_MACH_MSM_GPIOMUX_H
-
-#include <linux/bitops.h>
-#include <linux/errno.h>
-#include <mach/msm_gpiomux.h>
-#include "gpiomux-v1.h"
-
-/**
- * struct msm_gpiomux_config: gpiomux settings for one gpio line.
- *
- * A complete gpiomux config is the bitwise-or of a drive-strength,
- * function, and pull.  For functions other than GPIO, the OE
- * is hard-wired according to the function.  For GPIO mode,
- * OE is controlled by gpiolib.
- *
- * Available settings differ by target; see the gpiomux header
- * specific to your target arch for available configurations.
- *
- * @active: The configuration to be installed when the line is
- * active, or its reference count is > 0.
- * @suspended: The configuration to be installed when the line
- * is suspended, or its reference count is 0.
- * @ref: The reference count of the line.  For internal use of
- * the gpiomux framework only.
- */
-struct msm_gpiomux_config {
-       gpiomux_config_t active;
-       gpiomux_config_t suspended;
-       unsigned         ref;
-};
-
-/**
- * @GPIOMUX_VALID:     If set, the config field contains 'good data'.
- *                      The absence of this bit will prevent the gpiomux
- *                     system from applying the configuration under all
- *                     circumstances.
- */
-enum {
-       GPIOMUX_VALID    = BIT(sizeof(gpiomux_config_t) * BITS_PER_BYTE - 1),
-       GPIOMUX_CTL_MASK = GPIOMUX_VALID,
-};
-
-#ifdef CONFIG_MSM_GPIOMUX
-
-/* Each architecture must provide its own instance of this table.
- * To avoid having gpiomux manage any given gpio, one or both of
- * the entries can avoid setting GPIOMUX_VALID - the absence
- * of that flag will prevent the configuration from being applied
- * during state transitions.
- */
-extern struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS];
-
-/* Install a new configuration to the gpio line.  To avoid overwriting
- * a configuration, leave the VALID bit out.
- */
-int msm_gpiomux_write(unsigned gpio,
-                     gpiomux_config_t active,
-                     gpiomux_config_t suspended);
-#else
-static inline int msm_gpiomux_write(unsigned gpio,
-                                   gpiomux_config_t active,
-                                   gpiomux_config_t suspended)
-{
-       return -ENOSYS;
-}
-#endif
-#endif
diff --git a/arch/arm/mach-msm/include/mach/clk.h b/arch/arm/mach-msm/include/mach/clk.h
deleted file mode 100644 (file)
index fd4f4a7..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-#ifndef __MACH_CLK_H
-#define __MACH_CLK_H
-
-/* Magic rate value for use with PM QOS to request the board's maximum
- * supported AXI rate. PM QOS will only pass positive s32 rate values
- * through to the clock driver, so INT_MAX is used.
- */
-#define MSM_AXI_MAX_FREQ       LONG_MAX
-
-enum clk_reset_action {
-       CLK_RESET_DEASSERT      = 0,
-       CLK_RESET_ASSERT        = 1
-};
-
-struct clk;
-
-/* Assert/Deassert reset to a hardware block associated with a clock */
-int clk_reset(struct clk *clk, enum clk_reset_action action);
-
-#endif
diff --git a/arch/arm/mach-msm/include/mach/dma.h b/arch/arm/mach-msm/include/mach/dma.h
deleted file mode 100644 (file)
index a72d48d..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-/* linux/include/asm-arm/arch-msm/dma.h
- *
- * Copyright (C) 2007 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __ASM_ARCH_MSM_DMA_H
-
-#include <linux/list.h>
-
-struct msm_dmov_errdata {
-       uint32_t flush[6];
-};
-
-struct msm_dmov_cmd {
-       struct list_head list;
-       unsigned int cmdptr;
-       void (*complete_func)(struct msm_dmov_cmd *cmd,
-                             unsigned int result,
-                             struct msm_dmov_errdata *err);
-       void (*execute_func)(struct msm_dmov_cmd *cmd);
-       void *data;
-};
-
-#ifndef CONFIG_ARCH_MSM8X60
-void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd);
-void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd, int graceful);
-int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr);
-#else
-static inline
-void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd) { }
-static inline
-void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd, int graceful) { }
-static inline
-int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr) { return -EIO; }
-#endif
-
-#define DMOV_CMD_LIST         (0 << 29) /* does not work */
-#define DMOV_CMD_PTR_LIST     (1 << 29) /* works */
-#define DMOV_CMD_INPUT_CFG    (2 << 29) /* untested */
-#define DMOV_CMD_OUTPUT_CFG   (3 << 29) /* untested */
-#define DMOV_CMD_ADDR(addr)   ((addr) >> 3)
-
-#define DMOV_RSLT_VALID       (1 << 31) /* 0 == host has empties result fifo */
-#define DMOV_RSLT_ERROR       (1 << 3)
-#define DMOV_RSLT_FLUSH       (1 << 2)
-#define DMOV_RSLT_DONE        (1 << 1)  /* top pointer done */
-#define DMOV_RSLT_USER        (1 << 0)  /* command with FR force result */
-
-#define DMOV_STATUS_RSLT_COUNT(n)    (((n) >> 29))
-#define DMOV_STATUS_CMD_COUNT(n)     (((n) >> 27) & 3)
-#define DMOV_STATUS_RSLT_VALID       (1 << 1)
-#define DMOV_STATUS_CMD_PTR_RDY      (1 << 0)
-
-#define DMOV_CONFIG_FORCE_TOP_PTR_RSLT (1 << 2)
-#define DMOV_CONFIG_FORCE_FLUSH_RSLT   (1 << 1)
-#define DMOV_CONFIG_IRQ_EN             (1 << 0)
-
-/* channel assignments */
-
-#define DMOV_NAND_CHAN        7
-#define DMOV_NAND_CRCI_CMD    5
-#define DMOV_NAND_CRCI_DATA   4
-
-#define DMOV_SDC1_CHAN        8
-#define DMOV_SDC1_CRCI        6
-
-#define DMOV_SDC2_CHAN        8
-#define DMOV_SDC2_CRCI        7
-
-#define DMOV_TSIF_CHAN        10
-#define DMOV_TSIF_CRCI        10
-
-#define DMOV_USB_CHAN         11
-
-/* no client rate control ifc (eg, ram) */
-#define DMOV_NONE_CRCI        0
-
-
-/* If the CMD_PTR register has CMD_PTR_LIST selected, the data mover
- * is going to walk a list of 32bit pointers as described below.  Each
- * pointer points to a *array* of dmov_s, etc structs.  The last pointer
- * in the list is marked with CMD_PTR_LP.  The last struct in each array
- * is marked with CMD_LC (see below).
- */
-#define CMD_PTR_ADDR(addr)  ((addr) >> 3)
-#define CMD_PTR_LP          (1 << 31) /* last pointer */
-#define CMD_PTR_PT          (3 << 29) /* ? */
-
-/* Single Item Mode */
-typedef struct {
-       unsigned cmd;
-       unsigned src;
-       unsigned dst;
-       unsigned len;
-} dmov_s;
-
-/* Scatter/Gather Mode */
-typedef struct {
-       unsigned cmd;
-       unsigned src_dscr;
-       unsigned dst_dscr;
-       unsigned _reserved;
-} dmov_sg;
-
-/* Box mode */
-typedef struct {
-       uint32_t cmd;
-       uint32_t src_row_addr;
-       uint32_t dst_row_addr;
-       uint32_t src_dst_len;
-       uint32_t num_rows;
-       uint32_t row_offset;
-} dmov_box;
-
-/* bits for the cmd field of the above structures */
-
-#define CMD_LC      (1 << 31)  /* last command */
-#define CMD_FR      (1 << 22)  /* force result -- does not work? */
-#define CMD_OCU     (1 << 21)  /* other channel unblock */
-#define CMD_OCB     (1 << 20)  /* other channel block */
-#define CMD_TCB     (1 << 19)  /* ? */
-#define CMD_DAH     (1 << 18)  /* destination address hold -- does not work?*/
-#define CMD_SAH     (1 << 17)  /* source address hold -- does not work? */
-
-#define CMD_MODE_SINGLE     (0 << 0) /* dmov_s structure used */
-#define CMD_MODE_SG         (1 << 0) /* untested */
-#define CMD_MODE_IND_SG     (2 << 0) /* untested */
-#define CMD_MODE_BOX        (3 << 0) /* untested */
-
-#define CMD_DST_SWAP_BYTES  (1 << 14) /* exchange each byte n with byte n+1 */
-#define CMD_DST_SWAP_SHORTS (1 << 15) /* exchange each short n with short n+1 */
-#define CMD_DST_SWAP_WORDS  (1 << 16) /* exchange each word n with word n+1 */
-
-#define CMD_SRC_SWAP_BYTES  (1 << 11) /* exchange each byte n with byte n+1 */
-#define CMD_SRC_SWAP_SHORTS (1 << 12) /* exchange each short n with short n+1 */
-#define CMD_SRC_SWAP_WORDS  (1 << 13) /* exchange each word n with word n+1 */
-
-#define CMD_DST_CRCI(n)     (((n) & 15) << 7)
-#define CMD_SRC_CRCI(n)     (((n) & 15) << 3)
-
-#endif
diff --git a/arch/arm/mach-msm/include/mach/entry-macro.S b/arch/arm/mach-msm/include/mach/entry-macro.S
deleted file mode 100644 (file)
index f2ae908..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only 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 Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- */
-
-#if !defined(CONFIG_ARM_GIC)
-#include <mach/msm_iomap.h>
-
-       .macro  get_irqnr_preamble, base, tmp
-       @ enable imprecise aborts
-       cpsie   a
-       mov     \base, #MSM_VIC_BASE
-       .endm
-
-       .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-       @ 0xD0 has irq# or old irq# if the irq has been handled
-       @ 0xD4 has irq# or -1 if none pending *but* if you just
-       @ read 0xD4 you never get the first irq for some reason
-       ldr     \irqnr, [\base, #0xD0]
-       ldr     \irqnr, [\base, #0xD4]
-       cmp     \irqnr, #0xffffffff
-       .endm
-#endif
diff --git a/arch/arm/mach-msm/include/mach/hardware.h b/arch/arm/mach-msm/include/mach/hardware.h
deleted file mode 100644 (file)
index 2d12609..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/* arch/arm/mach-msm/include/mach/hardware.h
- *
- * Copyright (C) 2007 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __ASM_ARCH_MSM_HARDWARE_H
-
-#endif
diff --git a/arch/arm/mach-msm/include/mach/irqs-7x00.h b/arch/arm/mach-msm/include/mach/irqs-7x00.h
deleted file mode 100644 (file)
index f1fe706..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009, Code Aurora Forum. All rights reserved.
- * Author: Brian Swetland <swetland@google.com>
- */
-
-#ifndef __ASM_ARCH_MSM_IRQS_7X00_H
-#define __ASM_ARCH_MSM_IRQS_7X00_H
-
-/* MSM ARM11 Interrupt Numbers */
-/* See 80-VE113-1 A, pp219-221     */
-
-#define INT_A9_M2A_0         0
-#define INT_A9_M2A_1         1
-#define INT_A9_M2A_2         2
-#define INT_A9_M2A_3         3
-#define INT_A9_M2A_4         4
-#define INT_A9_M2A_5         5
-#define INT_A9_M2A_6         6
-#define INT_GP_TIMER_EXP     7
-#define INT_DEBUG_TIMER_EXP  8
-#define INT_UART1            9
-#define INT_UART2            10
-#define INT_UART3            11
-#define INT_UART1_RX         12
-#define INT_UART2_RX         13
-#define INT_UART3_RX         14
-#define INT_USB_OTG          15
-#define INT_MDDI_PRI         16
-#define INT_MDDI_EXT         17
-#define INT_MDDI_CLIENT      18
-#define INT_MDP              19
-#define INT_GRAPHICS         20
-#define INT_ADM_AARM         21
-#define INT_ADSP_A11         22
-#define INT_ADSP_A9_A11      23
-#define INT_SDC1_0           24
-#define INT_SDC1_1           25
-#define INT_SDC2_0           26
-#define INT_SDC2_1           27
-#define INT_KEYSENSE         28
-#define INT_TCHSCRN_SSBI     29
-#define INT_TCHSCRN1         30
-#define INT_TCHSCRN2         31
-
-#define INT_GPIO_GROUP1      (32 + 0)
-#define INT_GPIO_GROUP2      (32 + 1)
-#define INT_PWB_I2C          (32 + 2)
-#define INT_SOFTRESET        (32 + 3)
-#define INT_NAND_WR_ER_DONE  (32 + 4)
-#define INT_NAND_OP_DONE     (32 + 5)
-#define INT_PBUS_ARM11       (32 + 6)
-#define INT_AXI_MPU_SMI      (32 + 7)
-#define INT_AXI_MPU_EBI1     (32 + 8)
-#define INT_AD_HSSD          (32 + 9)
-#define INT_ARM11_PMU        (32 + 10)
-#define INT_ARM11_DMA        (32 + 11)
-#define INT_TSIF_IRQ         (32 + 12)
-#define INT_UART1DM_IRQ      (32 + 13)
-#define INT_UART1DM_RX       (32 + 14)
-#define INT_USB_HS           (32 + 15)
-#define INT_SDC3_0           (32 + 16)
-#define INT_SDC3_1           (32 + 17)
-#define INT_SDC4_0           (32 + 18)
-#define INT_SDC4_1           (32 + 19)
-#define INT_UART2DM_RX       (32 + 20)
-#define INT_UART2DM_IRQ      (32 + 21)
-
-/* 22-31 are reserved */
-
-#define NR_MSM_IRQS 64
-#define NR_GPIO_IRQS 122
-#define NR_BOARD_IRQS 64
-
-#endif
diff --git a/arch/arm/mach-msm/include/mach/irqs-7x30.h b/arch/arm/mach-msm/include/mach/irqs-7x30.h
deleted file mode 100644 (file)
index 1f15902..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __ASM_ARCH_MSM_IRQS_7X30_H
-#define __ASM_ARCH_MSM_IRQS_7X30_H
-
-/* MSM ACPU Interrupt Numbers */
-
-#define INT_DEBUG_TIMER_EXP    0
-#define INT_GPT0_TIMER_EXP     1
-#define INT_GPT1_TIMER_EXP     2
-#define INT_WDT0_ACCSCSSBARK   3
-#define INT_WDT1_ACCSCSSBARK   4
-#define INT_AVS_SVIC           5
-#define INT_AVS_SVIC_SW_DONE   6
-#define INT_SC_DBG_RX_FULL     7
-#define INT_SC_DBG_TX_EMPTY    8
-#define INT_ARM11_PM           9
-#define INT_AVS_REQ_DOWN       10
-#define INT_AVS_REQ_UP         11
-#define INT_SC_ACG             12
-/* SCSS_VICFIQSTS0[13:15] are RESERVED */
-#define INT_L2_SVICCPUIRPTREQ  16
-#define INT_L2_SVICDMANSIRPTREQ 17
-#define INT_L2_SVICDMASIRPTREQ  18
-#define INT_L2_SVICSLVIRPTREQ  19
-#define INT_AD5A_MPROC_APPS_0  20
-#define INT_AD5A_MPROC_APPS_1  21
-#define INT_A9_M2A_0           22
-#define INT_A9_M2A_1           23
-#define INT_A9_M2A_2           24
-#define INT_A9_M2A_3           25
-#define INT_A9_M2A_4           26
-#define INT_A9_M2A_5           27
-#define INT_A9_M2A_6           28
-#define INT_A9_M2A_7           29
-#define INT_A9_M2A_8           30
-#define INT_A9_M2A_9           31
-
-#define INT_AXI_EBI1_SC                (32 + 0)
-#define INT_IMEM_ERR           (32 + 1)
-#define INT_AXI_EBI0_SC                (32 + 2)
-#define INT_PBUS_SC_IRQC       (32 + 3)
-#define INT_PERPH_BUS_BPM      (32 + 4)
-#define INT_CC_TEMP_SENSE      (32 + 5)
-#define INT_UXMC_EBI0          (32 + 6)
-#define INT_UXMC_EBI1          (32 + 7)
-#define INT_EBI2_OP_DONE       (32 + 8)
-#define INT_EBI2_WR_ER_DONE    (32 + 9)
-#define INT_TCSR_SPSS_CE       (32 + 10)
-#define INT_EMDH               (32 + 11)
-#define INT_PMDH               (32 + 12)
-#define INT_MDC                        (32 + 13)
-#define INT_MIDI_TO_SUPSS      (32 + 14)
-#define INT_LPA_2              (32 + 15)
-#define INT_GPIO_GROUP1_SECURE (32 + 16)
-#define INT_GPIO_GROUP2_SECURE (32 + 17)
-#define INT_GPIO_GROUP1                (32 + 18)
-#define INT_GPIO_GROUP2                (32 + 19)
-#define INT_MPRPH_SOFTRESET    (32 + 20)
-#define INT_PWB_I2C            (32 + 21)
-#define INT_PWB_I2C_2          (32 + 22)
-#define INT_TSSC_SAMPLE                (32 + 23)
-#define INT_TSSC_PENUP         (32 + 24)
-#define INT_TCHSCRN_SSBI       (32 + 25)
-#define INT_FM_RDS             (32 + 26)
-#define INT_KEYSENSE           (32 + 27)
-#define INT_USB_OTG_HS         (32 + 28)
-#define INT_USB_OTG_HS2                (32 + 29)
-#define INT_USB_OTG_HS3                (32 + 30)
-#define INT_CSI                        (32 + 31)
-
-#define INT_SPI_OUTPUT         (64 + 0)
-#define INT_SPI_INPUT          (64 + 1)
-#define INT_SPI_ERROR          (64 + 2)
-#define INT_UART1              (64 + 3)
-#define INT_UART1_RX           (64 + 4)
-#define INT_UART2              (64 + 5)
-#define INT_UART2_RX           (64 + 6)
-#define INT_UART3              (64 + 7)
-#define INT_UART3_RX           (64 + 8)
-#define INT_UART1DM_IRQ                (64 + 9)
-#define INT_UART1DM_RX         (64 + 10)
-#define INT_UART2DM_IRQ                (64 + 11)
-#define INT_UART2DM_RX         (64 + 12)
-#define INT_TSIF               (64 + 13)
-#define INT_ADM_SC1            (64 + 14)
-#define INT_ADM_SC2            (64 + 15)
-#define INT_MDP                        (64 + 16)
-#define INT_VPE                        (64 + 17)
-#define INT_GRP_2D             (64 + 18)
-#define INT_GRP_3D             (64 + 19)
-#define INT_ROTATOR            (64 + 20)
-#define INT_MFC720             (64 + 21)
-#define INT_JPEG               (64 + 22)
-#define INT_VFE                        (64 + 23)
-#define INT_TV_ENC             (64 + 24)
-#define INT_PMIC_SSBI          (64 + 25)
-#define INT_MPM_1              (64 + 26)
-#define INT_TCSR_SPSS_SAMPLE   (64 + 27)
-#define INT_TCSR_SPSS_PENUP    (64 + 28)
-#define INT_MPM_2              (64 + 29)
-#define INT_SDC1_0             (64 + 30)
-#define INT_SDC1_1             (64 + 31)
-
-#define INT_SDC3_0             (96 + 0)
-#define INT_SDC3_1             (96 + 1)
-#define INT_SDC2_0             (96 + 2)
-#define INT_SDC2_1             (96 + 3)
-#define INT_SDC4_0             (96 + 4)
-#define INT_SDC4_1             (96 + 5)
-#define INT_PWB_QUP_IN         (96 + 6)
-#define INT_PWB_QUP_OUT                (96 + 7)
-#define INT_PWB_QUP_ERR                (96 + 8)
-#define INT_SCSS_WDT0_BITE     (96 + 9)
-/* SCSS_VICFIQSTS3[10:31] are RESERVED */
-
-/* Retrofit universal macro names */
-#define INT_ADM_AARM           INT_ADM_SC2
-#define INT_USB_HS             INT_USB_OTG_HS
-#define INT_USB_OTG            INT_USB_OTG_HS
-#define INT_TCHSCRN1           INT_TSSC_SAMPLE
-#define INT_TCHSCRN2           INT_TSSC_PENUP
-#define INT_GP_TIMER_EXP       INT_GPT0_TIMER_EXP
-#define INT_ADSP_A11           INT_AD5A_MPROC_APPS_0
-#define INT_ADSP_A9_A11        INT_AD5A_MPROC_APPS_1
-#define INT_MDDI_EXT           INT_EMDH
-#define INT_MDDI_PRI           INT_PMDH
-#define INT_MDDI_CLIENT                INT_MDC
-#define INT_NAND_WR_ER_DONE    INT_EBI2_WR_ER_DONE
-#define INT_NAND_OP_DONE       INT_EBI2_OP_DONE
-
-#define NR_MSM_IRQS            128
-#define NR_GPIO_IRQS           182
-#define PMIC8058_IRQ_BASE      (NR_MSM_IRQS + NR_GPIO_IRQS)
-#define NR_PMIC8058_GPIO_IRQS  40
-#define NR_PMIC8058_MPP_IRQS   12
-#define NR_PMIC8058_MISC_IRQS  8
-#define NR_PMIC8058_IRQS       (NR_PMIC8058_GPIO_IRQS +\
-                               NR_PMIC8058_MPP_IRQS +\
-                               NR_PMIC8058_MISC_IRQS)
-#define NR_BOARD_IRQS          NR_PMIC8058_IRQS
-
-#endif /* __ASM_ARCH_MSM_IRQS_7X30_H */
diff --git a/arch/arm/mach-msm/include/mach/irqs-8x50.h b/arch/arm/mach-msm/include/mach/irqs-8x50.h
deleted file mode 100644 (file)
index 26adbe0..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __ASM_ARCH_MSM_IRQS_8XXX_H
-#define __ASM_ARCH_MSM_IRQS_8XXX_H
-
-/* MSM ACPU Interrupt Numbers */
-
-#define INT_A9_M2A_0         0
-#define INT_A9_M2A_1         1
-#define INT_A9_M2A_2         2
-#define INT_A9_M2A_3         3
-#define INT_A9_M2A_4         4
-#define INT_A9_M2A_5         5
-#define INT_A9_M2A_6         6
-#define INT_GP_TIMER_EXP     7
-#define INT_DEBUG_TIMER_EXP  8
-#define INT_SIRC_0           9
-#define INT_SDC3_0           10
-#define INT_SDC3_1           11
-#define INT_SDC4_0           12
-#define INT_SDC4_1           13
-#define INT_AD6_EXT_VFR      14
-#define INT_USB_OTG          15
-#define INT_MDDI_PRI         16
-#define INT_MDDI_EXT         17
-#define INT_MDDI_CLIENT      18
-#define INT_MDP              19
-#define INT_GRAPHICS         20
-#define INT_ADM_AARM         21
-#define INT_ADSP_A11         22
-#define INT_ADSP_A9_A11      23
-#define INT_SDC1_0           24
-#define INT_SDC1_1           25
-#define INT_SDC2_0           26
-#define INT_SDC2_1           27
-#define INT_KEYSENSE         28
-#define INT_TCHSCRN_SSBI     29
-#define INT_TCHSCRN1         30
-#define INT_TCHSCRN2         31
-
-#define INT_TCSR_MPRPH_SC1   (32 + 0)
-#define INT_USB_FS2          (32 + 1)
-#define INT_PWB_I2C          (32 + 2)
-#define INT_SOFTRESET        (32 + 3)
-#define INT_NAND_WR_ER_DONE  (32 + 4)
-#define INT_NAND_OP_DONE     (32 + 5)
-#define INT_TCSR_MPRPH_SC2   (32 + 6)
-#define INT_OP_PEN           (32 + 7)
-#define INT_AD_HSSD          (32 + 8)
-#define INT_ARM11_PM         (32 + 9)
-#define INT_SDMA_NON_SECURE  (32 + 10)
-#define INT_TSIF_IRQ         (32 + 11)
-#define INT_UART1DM_IRQ      (32 + 12)
-#define INT_UART1DM_RX       (32 + 13)
-#define INT_SDMA_SECURE      (32 + 14)
-#define INT_SI2S_SLAVE       (32 + 15)
-#define INT_SC_I2CPU         (32 + 16)
-#define INT_SC_DBG_RDTRFULL  (32 + 17)
-#define INT_SC_DBG_WDTRFULL  (32 + 18)
-#define INT_SCPLL_CTL_DONE   (32 + 19)
-#define INT_UART2DM_IRQ      (32 + 20)
-#define INT_UART2DM_RX       (32 + 21)
-#define INT_VDC_MEC          (32 + 22)
-#define INT_VDC_DB           (32 + 23)
-#define INT_VDC_AXI          (32 + 24)
-#define INT_VFE              (32 + 25)
-#define INT_USB_HS           (32 + 26)
-#define INT_AUDIO_OUT0       (32 + 27)
-#define INT_AUDIO_OUT1       (32 + 28)
-#define INT_CRYPTO           (32 + 29)
-#define INT_AD6M_IDLE        (32 + 30)
-#define INT_SIRC_1           (32 + 31)
-
-#define NR_GPIO_IRQS 165
-#define NR_MSM_IRQS 64
-#define NR_BOARD_IRQS 64
-
-#endif
diff --git a/arch/arm/mach-msm/include/mach/irqs.h b/arch/arm/mach-msm/include/mach/irqs.h
deleted file mode 100644 (file)
index 164d355..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
- * Author: Brian Swetland <swetland@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __ASM_ARCH_MSM_IRQS_H
-#define __ASM_ARCH_MSM_IRQS_H
-
-#define MSM_IRQ_BIT(irq)     (1 << ((irq) & 31))
-
-#if defined(CONFIG_ARCH_MSM7X30)
-#include "irqs-7x30.h"
-#elif defined(CONFIG_ARCH_QSD8X50)
-#include "irqs-8x50.h"
-#include "sirc.h"
-#elif defined(CONFIG_ARCH_MSM_ARM11)
-#include "irqs-7x00.h"
-#else
-#error "Unknown architecture specification"
-#endif
-
-#define NR_IRQS (NR_MSM_IRQS + NR_GPIO_IRQS + NR_BOARD_IRQS)
-#define MSM_GPIO_TO_INT(n) (NR_MSM_IRQS + (n))
-#define MSM_INT_TO_REG(base, irq) (base + irq / 32)
-
-#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_gpiomux.h b/arch/arm/mach-msm/include/mach/msm_gpiomux.h
deleted file mode 100644 (file)
index 0c7d393..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef _LINUX_MSM_GPIOMUX_H
-#define _LINUX_MSM_GPIOMUX_H
-
-#ifdef CONFIG_MSM_GPIOMUX
-
-/* Increment a gpio's reference count, possibly activating the line. */
-int __must_check msm_gpiomux_get(unsigned gpio);
-
-/* Decrement a gpio's reference count, possibly suspending the line. */
-int msm_gpiomux_put(unsigned gpio);
-
-#else
-
-static inline int __must_check msm_gpiomux_get(unsigned gpio)
-{
-       return -ENOSYS;
-}
-
-static inline int msm_gpiomux_put(unsigned gpio)
-{
-       return -ENOSYS;
-}
-
-#endif
-
-#endif /* _LINUX_MSM_GPIOMUX_H */
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h b/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h
deleted file mode 100644 (file)
index 67dc0e9..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-/* arch/arm/mach-msm/include/mach/msm_iomap.h
- *
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
- * Author: Brian Swetland <swetland@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
- * The MSM peripherals are spread all over across 768MB of physical
- * space, which makes just having a simple IO_ADDRESS macro to slide
- * them into the right virtual location rough.  Instead, we will
- * provide a master phys->virt mapping for peripherals here.
- *
- */
-
-#ifndef __ASM_ARCH_MSM_IOMAP_7X00_H
-#define __ASM_ARCH_MSM_IOMAP_7X00_H
-
-#include <asm/sizes.h>
-
-/* Physical base address and size of peripherals.
- * Ordered by the virtual base addresses they will be mapped at.
- *
- * MSM_VIC_BASE must be an value that can be loaded via a "mov"
- * instruction, otherwise entry-macro.S will not compile.
- *
- * If you add or remove entries here, you'll want to edit the
- * msm_io_desc array in arch/arm/mach-msm/io.c to reflect your
- * changes.
- *
- */
-
-#define MSM_VIC_BASE          IOMEM(0xE0000000)
-#define MSM_VIC_PHYS          0xC0000000
-#define MSM_VIC_SIZE          SZ_4K
-
-#define MSM7X00_CSR_PHYS      0xC0100000
-#define MSM7X00_CSR_SIZE      SZ_4K
-
-#define MSM_DMOV_BASE         IOMEM(0xE0002000)
-#define MSM_DMOV_PHYS         0xA9700000
-#define MSM_DMOV_SIZE         SZ_4K
-
-#define MSM7X00_GPIO1_PHYS        0xA9200000
-#define MSM7X00_GPIO1_SIZE        SZ_4K
-
-#define MSM7X00_GPIO2_PHYS        0xA9300000
-#define MSM7X00_GPIO2_SIZE        SZ_4K
-
-#define MSM_CLK_CTL_BASE      IOMEM(0xE0005000)
-#define MSM_CLK_CTL_PHYS      0xA8600000
-#define MSM_CLK_CTL_SIZE      SZ_4K
-
-#define MSM_SHARED_RAM_BASE   IOMEM(0xE0100000)
-#define MSM_SHARED_RAM_PHYS   0x01F00000
-#define MSM_SHARED_RAM_SIZE   SZ_1M
-
-#define MSM_UART1_PHYS        0xA9A00000
-#define MSM_UART1_SIZE        SZ_4K
-
-#define MSM_UART2_PHYS        0xA9B00000
-#define MSM_UART2_SIZE        SZ_4K
-
-#define MSM_UART3_PHYS        0xA9C00000
-#define MSM_UART3_SIZE        SZ_4K
-
-#define MSM_SDC1_PHYS         0xA0400000
-#define MSM_SDC1_SIZE         SZ_4K
-
-#define MSM_SDC2_PHYS         0xA0500000
-#define MSM_SDC2_SIZE         SZ_4K
-
-#define MSM_SDC3_PHYS         0xA0600000
-#define MSM_SDC3_SIZE         SZ_4K
-
-#define MSM_SDC4_PHYS         0xA0700000
-#define MSM_SDC4_SIZE         SZ_4K
-
-#define MSM_I2C_PHYS          0xA9900000
-#define MSM_I2C_SIZE          SZ_4K
-
-#define MSM_HSUSB_PHYS        0xA0800000
-#define MSM_HSUSB_SIZE        SZ_4K
-
-#define MSM_PMDH_PHYS         0xAA600000
-#define MSM_PMDH_SIZE         SZ_4K
-
-#define MSM_EMDH_PHYS         0xAA700000
-#define MSM_EMDH_SIZE         SZ_4K
-
-#define MSM_MDP_PHYS          0xAA200000
-#define MSM_MDP_SIZE          0x000F0000
-
-#define MSM_MDC_PHYS         0xAA500000
-#define MSM_MDC_SIZE         SZ_1M
-
-#define MSM_AD5_PHYS          0xAC000000
-#define MSM_AD5_SIZE          (SZ_1M*13)
-
-#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h b/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h
deleted file mode 100644 (file)
index 198202c..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2011 Code Aurora Forum. All rights reserved.
- * Author: Brian Swetland <swetland@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
- * The MSM peripherals are spread all over across 768MB of physical
- * space, which makes just having a simple IO_ADDRESS macro to slide
- * them into the right virtual location rough.  Instead, we will
- * provide a master phys->virt mapping for peripherals here.
- *
- */
-
-#ifndef __ASM_ARCH_MSM_IOMAP_7X30_H
-#define __ASM_ARCH_MSM_IOMAP_7X30_H
-
-/* Physical base address and size of peripherals.
- * Ordered by the virtual base addresses they will be mapped at.
- *
- * MSM_VIC_BASE must be an value that can be loaded via a "mov"
- * instruction, otherwise entry-macro.S will not compile.
- *
- * If you add or remove entries here, you'll want to edit the
- * msm_io_desc array in arch/arm/mach-msm/io.c to reflect your
- * changes.
- *
- */
-
-#define MSM_VIC_BASE          IOMEM(0xE0000000)
-#define MSM_VIC_PHYS          0xC0080000
-#define MSM_VIC_SIZE          SZ_4K
-
-#define MSM7X30_CSR_PHYS      0xC0100000
-#define MSM7X30_CSR_SIZE      SZ_4K
-
-#define MSM_DMOV_BASE         IOMEM(0xE0002000)
-#define MSM_DMOV_PHYS         0xAC400000
-#define MSM_DMOV_SIZE         SZ_4K
-
-#define MSM7X30_GPIO1_PHYS        0xAC001000
-#define MSM7X30_GPIO1_SIZE        SZ_4K
-
-#define MSM7X30_GPIO2_PHYS        0xAC101000
-#define MSM7X30_GPIO2_SIZE        SZ_4K
-
-#define MSM_CLK_CTL_BASE      IOMEM(0xE0005000)
-#define MSM_CLK_CTL_PHYS      0xAB800000
-#define MSM_CLK_CTL_SIZE      SZ_4K
-
-#define MSM_CLK_CTL_SH2_BASE  IOMEM(0xE0006000)
-#define MSM_CLK_CTL_SH2_PHYS  0xABA01000
-#define MSM_CLK_CTL_SH2_SIZE  SZ_4K
-
-#define MSM_ACC_BASE          IOMEM(0xE0007000)
-#define MSM_ACC_PHYS          0xC0101000
-#define MSM_ACC_SIZE          SZ_4K
-
-#define MSM_SAW_BASE          IOMEM(0xE0008000)
-#define MSM_SAW_PHYS          0xC0102000
-#define MSM_SAW_SIZE          SZ_4K
-
-#define MSM_GCC_BASE         IOMEM(0xE0009000)
-#define MSM_GCC_PHYS         0xC0182000
-#define MSM_GCC_SIZE         SZ_4K
-
-#define MSM_TCSR_BASE        IOMEM(0xE000A000)
-#define MSM_TCSR_PHYS        0xAB600000
-#define MSM_TCSR_SIZE        SZ_4K
-
-#define MSM_SHARED_RAM_BASE   IOMEM(0xE0100000)
-#define MSM_SHARED_RAM_PHYS   0x00100000
-#define MSM_SHARED_RAM_SIZE   SZ_1M
-
-#define MSM_UART1_PHYS        0xACA00000
-#define MSM_UART1_SIZE        SZ_4K
-
-#define MSM_UART2_PHYS        0xACB00000
-#define MSM_UART2_SIZE        SZ_4K
-
-#define MSM_UART3_PHYS        0xACC00000
-#define MSM_UART3_SIZE        SZ_4K
-
-#define MSM_MDC_BASE         IOMEM(0xE0200000)
-#define MSM_MDC_PHYS         0xAA500000
-#define MSM_MDC_SIZE         SZ_1M
-
-#define MSM_AD5_BASE          IOMEM(0xE0300000)
-#define MSM_AD5_PHYS          0xA7000000
-#define MSM_AD5_SIZE          (SZ_1M*13)
-
-#define MSM_HSUSB_PHYS        0xA3600000
-#define MSM_HSUSB_SIZE        SZ_1K
-
-#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h b/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h
deleted file mode 100644 (file)
index 0faa894..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2011 Code Aurora Forum. All rights reserved.
- * Author: Brian Swetland <swetland@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
- * The MSM peripherals are spread all over across 768MB of physical
- * space, which makes just having a simple IO_ADDRESS macro to slide
- * them into the right virtual location rough.  Instead, we will
- * provide a master phys->virt mapping for peripherals here.
- *
- */
-
-#ifndef __ASM_ARCH_MSM_IOMAP_8X50_H
-#define __ASM_ARCH_MSM_IOMAP_8X50_H
-
-/* Physical base address and size of peripherals.
- * Ordered by the virtual base addresses they will be mapped at.
- *
- * MSM_VIC_BASE must be an value that can be loaded via a "mov"
- * instruction, otherwise entry-macro.S will not compile.
- *
- * If you add or remove entries here, you'll want to edit the
- * msm_io_desc array in arch/arm/mach-msm/io.c to reflect your
- * changes.
- *
- */
-
-#define MSM_VIC_BASE          IOMEM(0xE0000000)
-#define MSM_VIC_PHYS          0xAC000000
-#define MSM_VIC_SIZE          SZ_4K
-
-#define QSD8X50_CSR_PHYS      0xAC100000
-#define QSD8X50_CSR_SIZE      SZ_4K
-
-#define MSM_DMOV_BASE         IOMEM(0xE0002000)
-#define MSM_DMOV_PHYS         0xA9700000
-#define MSM_DMOV_SIZE         SZ_4K
-
-#define QSD8X50_GPIO1_PHYS        0xA9000000
-#define QSD8X50_GPIO1_SIZE        SZ_4K
-
-#define QSD8X50_GPIO2_PHYS        0xA9100000
-#define QSD8X50_GPIO2_SIZE        SZ_4K
-
-#define MSM_CLK_CTL_BASE      IOMEM(0xE0005000)
-#define MSM_CLK_CTL_PHYS      0xA8600000
-#define MSM_CLK_CTL_SIZE      SZ_4K
-
-#define MSM_SIRC_BASE         IOMEM(0xE1006000)
-#define MSM_SIRC_PHYS         0xAC200000
-#define MSM_SIRC_SIZE         SZ_4K
-
-#define MSM_SCPLL_BASE        IOMEM(0xE1007000)
-#define MSM_SCPLL_PHYS        0xA8800000
-#define MSM_SCPLL_SIZE        SZ_4K
-
-#ifdef CONFIG_MSM_SOC_REV_A
-#define MSM_SMI_BASE 0xE0000000
-#else
-#define MSM_SMI_BASE 0x00000000
-#endif
-
-#define MSM_SHARED_RAM_BASE   IOMEM(0xE0100000)
-#define MSM_SHARED_RAM_PHYS (MSM_SMI_BASE + 0x00100000)
-#define MSM_SHARED_RAM_SIZE   SZ_1M
-
-#define MSM_UART1_PHYS        0xA9A00000
-#define MSM_UART1_SIZE        SZ_4K
-
-#define MSM_UART2_PHYS        0xA9B00000
-#define MSM_UART2_SIZE        SZ_4K
-
-#define MSM_UART3_PHYS        0xA9C00000
-#define MSM_UART3_SIZE        SZ_4K
-
-#define MSM_MDC_BASE         IOMEM(0xE0200000)
-#define MSM_MDC_PHYS         0xAA500000
-#define MSM_MDC_SIZE         SZ_1M
-
-#define MSM_AD5_BASE          IOMEM(0xE0300000)
-#define MSM_AD5_PHYS          0xAC000000
-#define MSM_AD5_SIZE          (SZ_1M*13)
-
-
-#define MSM_I2C_SIZE          SZ_4K
-#define MSM_I2C_PHYS          0xA9900000
-
-#define MSM_HSUSB_PHYS        0xA0800000
-#define MSM_HSUSB_SIZE        SZ_1K
-
-#define MSM_NAND_PHYS           0xA0A00000
-
-
-#define MSM_TSIF_PHYS        (0xa0100000)
-#define MSM_TSIF_SIZE        (0x200)
-
-#define MSM_TSSC_PHYS         0xAA300000
-
-#define MSM_UART1DM_PHYS      0xA0200000
-#define MSM_UART2DM_PHYS      0xA0900000
-
-
-#define MSM_SDC1_PHYS          0xA0300000
-#define MSM_SDC1_SIZE          SZ_4K
-
-#define MSM_SDC2_PHYS          0xA0400000
-#define MSM_SDC2_SIZE          SZ_4K
-
-#define MSM_SDC3_PHYS          0xA0500000
-#define MSM_SDC3_SIZE           SZ_4K
-
-#define MSM_SDC4_PHYS          0xA0600000
-#define MSM_SDC4_SIZE          SZ_4K
-
-#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
deleted file mode 100644 (file)
index 0e4f491..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
- * Author: Brian Swetland <swetland@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
- * The MSM peripherals are spread all over across 768MB of physical
- * space, which makes just having a simple IO_ADDRESS macro to slide
- * them into the right virtual location rough.  Instead, we will
- * provide a master phys->virt mapping for peripherals here.
- *
- */
-
-#ifndef __ASM_ARCH_MSM_IOMAP_H
-#define __ASM_ARCH_MSM_IOMAP_H
-
-#include <asm/sizes.h>
-
-/* Physical base address and size of peripherals.
- * Ordered by the virtual base addresses they will be mapped at.
- *
- * MSM_VIC_BASE must be an value that can be loaded via a "mov"
- * instruction, otherwise entry-macro.S will not compile.
- *
- * If you add or remove entries here, you'll want to edit the
- * msm_io_desc array in arch/arm/mach-msm/io.c to reflect your
- * changes.
- *
- */
-
-#if defined(CONFIG_ARCH_MSM7X30)
-#include "msm_iomap-7x30.h"
-#elif defined(CONFIG_ARCH_QSD8X50)
-#include "msm_iomap-8x50.h"
-#else
-#include "msm_iomap-7x00.h"
-#endif
-
-/* Virtual addresses shared across all MSM targets. */
-#define MSM_CSR_BASE           IOMEM(0xE0001000)
-#define MSM_GPIO1_BASE         IOMEM(0xE0003000)
-#define MSM_GPIO2_BASE         IOMEM(0xE0004000)
-
-#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_smd.h b/arch/arm/mach-msm/include/mach/msm_smd.h
deleted file mode 100644 (file)
index 029463e..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-/* linux/include/asm-arm/arch-msm/msm_smd.h
- *
- * Copyright (C) 2007 Google, Inc.
- * Author: Brian Swetland <swetland@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __ASM_ARCH_MSM_SMD_H
-#define __ASM_ARCH_MSM_SMD_H
-
-typedef struct smd_channel smd_channel_t;
-
-extern int (*msm_check_for_modem_crash)(void);
-
-/* warning: notify() may be called before open returns */
-int smd_open(const char *name, smd_channel_t **ch, void *priv,
-            void (*notify)(void *priv, unsigned event));
-
-#define SMD_EVENT_DATA 1
-#define SMD_EVENT_OPEN 2
-#define SMD_EVENT_CLOSE 3
-
-int smd_close(smd_channel_t *ch);
-
-/* passing a null pointer for data reads and discards */
-int smd_read(smd_channel_t *ch, void *data, int len);
-
-/* Write to stream channels may do a partial write and return
-** the length actually written.
-** Write to packet channels will never do a partial write --
-** it will return the requested length written or an error.
-*/
-int smd_write(smd_channel_t *ch, const void *data, int len);
-int smd_write_atomic(smd_channel_t *ch, const void *data, int len);
-
-int smd_write_avail(smd_channel_t *ch);
-int smd_read_avail(smd_channel_t *ch);
-
-/* Returns the total size of the current packet being read.
-** Returns 0 if no packets available or a stream channel.
-*/
-int smd_cur_packet_size(smd_channel_t *ch);
-
-/* used for tty unthrottling and the like -- causes the notify()
-** callback to be called from the same lock context as is used
-** when it is called from channel updates
-*/
-void smd_kick(smd_channel_t *ch);
-
-
-#if 0
-/* these are interruptable waits which will block you until the specified
-** number of bytes are readable or writable.
-*/
-int smd_wait_until_readable(smd_channel_t *ch, int bytes);
-int smd_wait_until_writable(smd_channel_t *ch, int bytes);
-#endif
-
-typedef enum {
-       SMD_PORT_DS = 0,
-       SMD_PORT_DIAG,
-       SMD_PORT_RPC_CALL,
-       SMD_PORT_RPC_REPLY,
-       SMD_PORT_BT,
-       SMD_PORT_CONTROL,
-       SMD_PORT_MEMCPY_SPARE1,
-       SMD_PORT_DATA1,
-       SMD_PORT_DATA2,
-       SMD_PORT_DATA3,
-       SMD_PORT_DATA4,
-       SMD_PORT_DATA5,
-       SMD_PORT_DATA6,
-       SMD_PORT_DATA7,
-       SMD_PORT_DATA8,
-       SMD_PORT_DATA9,
-       SMD_PORT_DATA10,
-       SMD_PORT_DATA11,
-       SMD_PORT_DATA12,
-       SMD_PORT_DATA13,
-       SMD_PORT_DATA14,
-       SMD_PORT_DATA15,
-       SMD_PORT_DATA16,
-       SMD_PORT_DATA17,
-       SMD_PORT_DATA18,
-       SMD_PORT_DATA19,
-       SMD_PORT_DATA20,
-       SMD_PORT_GPS_NMEA,
-       SMD_PORT_BRIDGE_1,
-       SMD_PORT_BRIDGE_2,
-       SMD_PORT_BRIDGE_3,
-       SMD_PORT_BRIDGE_4,
-       SMD_PORT_BRIDGE_5,
-       SMD_PORT_LOOPBACK,
-       SMD_PORT_CS_APPS_MODEM,
-       SMD_PORT_CS_APPS_DSP,
-       SMD_PORT_CS_MODEM_DSP,
-       SMD_NUM_PORTS,
-} smd_port_id_type;
-
-#endif
diff --git a/arch/arm/mach-msm/include/mach/sirc.h b/arch/arm/mach-msm/include/mach/sirc.h
deleted file mode 100644 (file)
index ef55868..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __ASM_ARCH_MSM_SIRC_H
-#define __ASM_ARCH_MSM_SIRC_H
-
-struct sirc_regs_t {
-       void    *int_enable;
-       void    *int_enable_clear;
-       void    *int_enable_set;
-       void    *int_type;
-       void    *int_polarity;
-       void    *int_clear;
-};
-
-struct sirc_cascade_regs {
-       void    *int_status;
-       unsigned int    cascade_irq;
-};
-
-void msm_init_sirc(void);
-void msm_sirc_enter_sleep(void);
-void msm_sirc_exit_sleep(void);
-
-#if defined(CONFIG_ARCH_MSM_SCORPION)
-
-#include <mach/msm_iomap.h>
-
-/*
- * Secondary interrupt controller interrupts
- */
-
-#define FIRST_SIRC_IRQ (NR_MSM_IRQS + NR_GPIO_IRQS)
-
-#define INT_UART1                     (FIRST_SIRC_IRQ + 0)
-#define INT_UART2                     (FIRST_SIRC_IRQ + 1)
-#define INT_UART3                     (FIRST_SIRC_IRQ + 2)
-#define INT_UART1_RX                  (FIRST_SIRC_IRQ + 3)
-#define INT_UART2_RX                  (FIRST_SIRC_IRQ + 4)
-#define INT_UART3_RX                  (FIRST_SIRC_IRQ + 5)
-#define INT_SPI_INPUT                 (FIRST_SIRC_IRQ + 6)
-#define INT_SPI_OUTPUT                (FIRST_SIRC_IRQ + 7)
-#define INT_SPI_ERROR                 (FIRST_SIRC_IRQ + 8)
-#define INT_GPIO_GROUP1               (FIRST_SIRC_IRQ + 9)
-#define INT_GPIO_GROUP2               (FIRST_SIRC_IRQ + 10)
-#define INT_GPIO_GROUP1_SECURE        (FIRST_SIRC_IRQ + 11)
-#define INT_GPIO_GROUP2_SECURE        (FIRST_SIRC_IRQ + 12)
-#define INT_AVS_SVIC                  (FIRST_SIRC_IRQ + 13)
-#define INT_AVS_REQ_UP                (FIRST_SIRC_IRQ + 14)
-#define INT_AVS_REQ_DOWN              (FIRST_SIRC_IRQ + 15)
-#define INT_PBUS_ERR                  (FIRST_SIRC_IRQ + 16)
-#define INT_AXI_ERR                   (FIRST_SIRC_IRQ + 17)
-#define INT_SMI_ERR                   (FIRST_SIRC_IRQ + 18)
-#define INT_EBI1_ERR                  (FIRST_SIRC_IRQ + 19)
-#define INT_IMEM_ERR                  (FIRST_SIRC_IRQ + 20)
-#define INT_TEMP_SENSOR               (FIRST_SIRC_IRQ + 21)
-#define INT_TV_ENC                    (FIRST_SIRC_IRQ + 22)
-#define INT_GRP2D                     (FIRST_SIRC_IRQ + 23)
-#define INT_GSBI_QUP                  (FIRST_SIRC_IRQ + 24)
-#define INT_SC_ACG                    (FIRST_SIRC_IRQ + 25)
-#define INT_WDT0                      (FIRST_SIRC_IRQ + 26)
-#define INT_WDT1                      (FIRST_SIRC_IRQ + 27)
-
-#if defined(CONFIG_MSM_SOC_REV_A)
-#define NR_SIRC_IRQS                  28
-#define SIRC_MASK                     0x0FFFFFFF
-#else
-#define NR_SIRC_IRQS                  23
-#define SIRC_MASK                     0x007FFFFF
-#endif
-
-#define LAST_SIRC_IRQ                 (FIRST_SIRC_IRQ + NR_SIRC_IRQS - 1)
-
-#define SPSS_SIRC_INT_SELECT          (MSM_SIRC_BASE + 0x00)
-#define SPSS_SIRC_INT_ENABLE          (MSM_SIRC_BASE + 0x04)
-#define SPSS_SIRC_INT_ENABLE_CLEAR    (MSM_SIRC_BASE + 0x08)
-#define SPSS_SIRC_INT_ENABLE_SET      (MSM_SIRC_BASE + 0x0C)
-#define SPSS_SIRC_INT_TYPE            (MSM_SIRC_BASE + 0x10)
-#define SPSS_SIRC_INT_POLARITY        (MSM_SIRC_BASE + 0x14)
-#define SPSS_SIRC_SECURITY            (MSM_SIRC_BASE + 0x18)
-#define SPSS_SIRC_IRQ_STATUS          (MSM_SIRC_BASE + 0x1C)
-#define SPSS_SIRC_IRQ1_STATUS         (MSM_SIRC_BASE + 0x20)
-#define SPSS_SIRC_RAW_STATUS          (MSM_SIRC_BASE + 0x24)
-#define SPSS_SIRC_INT_CLEAR           (MSM_SIRC_BASE + 0x28)
-#define SPSS_SIRC_SOFT_INT            (MSM_SIRC_BASE + 0x2C)
-
-#endif
-
-#endif
diff --git a/arch/arm/mach-msm/include/mach/vreg.h b/arch/arm/mach-msm/include/mach/vreg.h
deleted file mode 100644 (file)
index 6626e78..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/* linux/include/asm-arm/arch-msm/vreg.h
- *
- * Copyright (C) 2008 Google, Inc.
- * Author: Brian Swetland <swetland@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __ARCH_ARM_MACH_MSM_VREG_H
-#define __ARCH_ARM_MACH_MSM_VREG_H
-
-struct vreg;
-
-struct vreg *vreg_get(struct device *dev, const char *id);
-void vreg_put(struct vreg *vreg);
-
-int vreg_enable(struct vreg *vreg);
-int vreg_disable(struct vreg *vreg);
-int vreg_set_level(struct vreg *vreg, unsigned mv);
-
-#endif
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
deleted file mode 100644 (file)
index b042dca..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-/* arch/arm/mach-msm/io.c
- *
- * MSM7K, QSD io support
- *
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
- * Author: Brian Swetland <swetland@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/bug.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/export.h>
-
-#include <mach/hardware.h>
-#include <asm/page.h>
-#include <mach/msm_iomap.h>
-#include <asm/mach/map.h>
-
-#include "common.h"
-
-#define MSM_CHIP_DEVICE_TYPE(name, chip, mem_type) {                         \
-               .virtual = (unsigned long) MSM_##name##_BASE, \
-               .pfn = __phys_to_pfn(chip##_##name##_PHYS), \
-               .length = chip##_##name##_SIZE, \
-               .type = mem_type, \
-        }
-
-#define MSM_DEVICE_TYPE(name, mem_type) \
-               MSM_CHIP_DEVICE_TYPE(name, MSM, mem_type)
-#define MSM_CHIP_DEVICE(name, chip) \
-               MSM_CHIP_DEVICE_TYPE(name, chip, MT_DEVICE)
-#define MSM_DEVICE(name) MSM_CHIP_DEVICE(name, MSM)
-
-#if defined(CONFIG_ARCH_MSM7X00A)
-static struct map_desc msm_io_desc[] __initdata = {
-       MSM_DEVICE_TYPE(VIC, MT_DEVICE_NONSHARED),
-       MSM_CHIP_DEVICE_TYPE(CSR, MSM7X00, MT_DEVICE_NONSHARED),
-       MSM_DEVICE_TYPE(DMOV, MT_DEVICE_NONSHARED),
-       MSM_CHIP_DEVICE_TYPE(GPIO1, MSM7X00, MT_DEVICE_NONSHARED),
-       MSM_CHIP_DEVICE_TYPE(GPIO2, MSM7X00, MT_DEVICE_NONSHARED),
-       MSM_DEVICE_TYPE(CLK_CTL, MT_DEVICE_NONSHARED),
-       {
-               .virtual =  (unsigned long) MSM_SHARED_RAM_BASE,
-               .pfn = __phys_to_pfn(MSM_SHARED_RAM_PHYS),
-               .length =   MSM_SHARED_RAM_SIZE,
-               .type =     MT_DEVICE,
-       },
-#if defined(CONFIG_DEBUG_MSM_UART)
-       {
-               /* Must be last: virtual and pfn filled in by debug_ll_addr() */
-               .length = SZ_4K,
-               .type = MT_DEVICE_NONSHARED,
-       }
-#endif
-};
-
-void __init msm_map_common_io(void)
-{
-       size_t size = ARRAY_SIZE(msm_io_desc);
-
-       /* Make sure the peripheral register window is closed, since
-        * we will use PTE flags (TEX[1]=1,B=0,C=1) to determine which
-        * pages are peripheral interface or not.
-        */
-       asm("mcr p15, 0, %0, c15, c2, 4" : : "r" (0));
-#if defined(CONFIG_DEBUG_MSM_UART)
-#ifdef CONFIG_MMU
-       debug_ll_addr(&msm_io_desc[size - 1].pfn,
-                     &msm_io_desc[size - 1].virtual);
-#endif
-       msm_io_desc[size - 1].pfn = __phys_to_pfn(msm_io_desc[size - 1].pfn);
-#endif
-       iotable_init(msm_io_desc, size);
-}
-#endif
-
-#ifdef CONFIG_ARCH_QSD8X50
-static struct map_desc qsd8x50_io_desc[] __initdata = {
-       MSM_DEVICE(VIC),
-       MSM_CHIP_DEVICE(CSR, QSD8X50),
-       MSM_DEVICE(DMOV),
-       MSM_CHIP_DEVICE(GPIO1, QSD8X50),
-       MSM_CHIP_DEVICE(GPIO2, QSD8X50),
-       MSM_DEVICE(CLK_CTL),
-       MSM_DEVICE(SIRC),
-       MSM_DEVICE(SCPLL),
-       MSM_DEVICE(AD5),
-       MSM_DEVICE(MDC),
-       {
-               .virtual =  (unsigned long) MSM_SHARED_RAM_BASE,
-               .pfn = __phys_to_pfn(MSM_SHARED_RAM_PHYS),
-               .length =   MSM_SHARED_RAM_SIZE,
-               .type =     MT_DEVICE,
-       },
-};
-
-void __init msm_map_qsd8x50_io(void)
-{
-       debug_ll_io_init();
-       iotable_init(qsd8x50_io_desc, ARRAY_SIZE(qsd8x50_io_desc));
-}
-#endif /* CONFIG_ARCH_QSD8X50 */
-
-#ifdef CONFIG_ARCH_MSM7X30
-static struct map_desc msm7x30_io_desc[] __initdata = {
-       MSM_DEVICE(VIC),
-       MSM_CHIP_DEVICE(CSR, MSM7X30),
-       MSM_DEVICE(DMOV),
-       MSM_CHIP_DEVICE(GPIO1, MSM7X30),
-       MSM_CHIP_DEVICE(GPIO2, MSM7X30),
-       MSM_DEVICE(CLK_CTL),
-       MSM_DEVICE(CLK_CTL_SH2),
-       MSM_DEVICE(AD5),
-       MSM_DEVICE(MDC),
-       MSM_DEVICE(ACC),
-       MSM_DEVICE(SAW),
-       MSM_DEVICE(GCC),
-       MSM_DEVICE(TCSR),
-       {
-               .virtual =  (unsigned long) MSM_SHARED_RAM_BASE,
-               .pfn = __phys_to_pfn(MSM_SHARED_RAM_PHYS),
-               .length =   MSM_SHARED_RAM_SIZE,
-               .type =     MT_DEVICE,
-       },
-};
-
-void __init msm_map_msm7x30_io(void)
-{
-       debug_ll_io_init();
-       iotable_init(msm7x30_io_desc, ARRAY_SIZE(msm7x30_io_desc));
-}
-#endif /* CONFIG_ARCH_MSM7X30 */
-
-#ifdef CONFIG_ARCH_MSM7X00A
-void __iomem *__msm_ioremap_caller(phys_addr_t phys_addr, size_t size,
-                                  unsigned int mtype, void *caller)
-{
-       if (mtype == MT_DEVICE) {
-               /* The peripherals in the 88000000 - D0000000 range
-                * are only accessible by type MT_DEVICE_NONSHARED.
-                * Adjust mtype as necessary to make this "just work."
-                */
-               if ((phys_addr >= 0x88000000) && (phys_addr < 0xD0000000))
-                       mtype = MT_DEVICE_NONSHARED;
-       }
-
-       return __arm_ioremap_caller(phys_addr, size, mtype, caller);
-}
-#endif
diff --git a/arch/arm/mach-msm/irq-vic.c b/arch/arm/mach-msm/irq-vic.c
deleted file mode 100644 (file)
index 1b54f80..0000000
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009, Code Aurora Forum. All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/ptrace.h>
-#include <linux/timer.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-
-#include <asm/cacheflush.h>
-
-#include <mach/hardware.h>
-
-#include <mach/msm_iomap.h>
-
-#include "smd_private.h"
-
-enum {
-       IRQ_DEBUG_SLEEP_INT_TRIGGER = 1U << 0,
-       IRQ_DEBUG_SLEEP_INT = 1U << 1,
-       IRQ_DEBUG_SLEEP_ABORT = 1U << 2,
-       IRQ_DEBUG_SLEEP = 1U << 3,
-       IRQ_DEBUG_SLEEP_REQUEST = 1U << 4,
-};
-static int msm_irq_debug_mask;
-module_param_named(debug_mask, msm_irq_debug_mask, int,
-                  S_IRUGO | S_IWUSR | S_IWGRP);
-
-#define VIC_REG(off) (MSM_VIC_BASE + (off))
-#define VIC_INT_TO_REG_ADDR(base, irq) (base + (irq / 32) * 4)
-#define VIC_INT_TO_REG_INDEX(irq) ((irq >> 5) & 3)
-
-#define VIC_INT_SELECT0     VIC_REG(0x0000)  /* 1: FIQ, 0: IRQ */
-#define VIC_INT_SELECT1     VIC_REG(0x0004)  /* 1: FIQ, 0: IRQ */
-#define VIC_INT_SELECT2     VIC_REG(0x0008)  /* 1: FIQ, 0: IRQ */
-#define VIC_INT_SELECT3     VIC_REG(0x000C)  /* 1: FIQ, 0: IRQ */
-#define VIC_INT_EN0         VIC_REG(0x0010)
-#define VIC_INT_EN1         VIC_REG(0x0014)
-#define VIC_INT_EN2         VIC_REG(0x0018)
-#define VIC_INT_EN3         VIC_REG(0x001C)
-#define VIC_INT_ENCLEAR0    VIC_REG(0x0020)
-#define VIC_INT_ENCLEAR1    VIC_REG(0x0024)
-#define VIC_INT_ENCLEAR2    VIC_REG(0x0028)
-#define VIC_INT_ENCLEAR3    VIC_REG(0x002C)
-#define VIC_INT_ENSET0      VIC_REG(0x0030)
-#define VIC_INT_ENSET1      VIC_REG(0x0034)
-#define VIC_INT_ENSET2      VIC_REG(0x0038)
-#define VIC_INT_ENSET3      VIC_REG(0x003C)
-#define VIC_INT_TYPE0       VIC_REG(0x0040)  /* 1: EDGE, 0: LEVEL  */
-#define VIC_INT_TYPE1       VIC_REG(0x0044)  /* 1: EDGE, 0: LEVEL  */
-#define VIC_INT_TYPE2       VIC_REG(0x0048)  /* 1: EDGE, 0: LEVEL  */
-#define VIC_INT_TYPE3       VIC_REG(0x004C)  /* 1: EDGE, 0: LEVEL  */
-#define VIC_INT_POLARITY0   VIC_REG(0x0050)  /* 1: NEG, 0: POS */
-#define VIC_INT_POLARITY1   VIC_REG(0x0054)  /* 1: NEG, 0: POS */
-#define VIC_INT_POLARITY2   VIC_REG(0x0058)  /* 1: NEG, 0: POS */
-#define VIC_INT_POLARITY3   VIC_REG(0x005C)  /* 1: NEG, 0: POS */
-#define VIC_NO_PEND_VAL     VIC_REG(0x0060)
-
-#if defined(CONFIG_ARCH_MSM_SCORPION)
-#define VIC_NO_PEND_VAL_FIQ VIC_REG(0x0064)
-#define VIC_INT_MASTEREN    VIC_REG(0x0068)  /* 1: IRQ, 2: FIQ     */
-#define VIC_CONFIG          VIC_REG(0x006C)  /* 1: USE SC VIC */
-#else
-#define VIC_INT_MASTEREN    VIC_REG(0x0064)  /* 1: IRQ, 2: FIQ     */
-#define VIC_PROTECTION      VIC_REG(0x006C)  /* 1: ENABLE          */
-#define VIC_CONFIG          VIC_REG(0x0068)  /* 1: USE ARM1136 VIC */
-#endif
-
-#define VIC_IRQ_STATUS0     VIC_REG(0x0080)
-#define VIC_IRQ_STATUS1     VIC_REG(0x0084)
-#define VIC_IRQ_STATUS2     VIC_REG(0x0088)
-#define VIC_IRQ_STATUS3     VIC_REG(0x008C)
-#define VIC_FIQ_STATUS0     VIC_REG(0x0090)
-#define VIC_FIQ_STATUS1     VIC_REG(0x0094)
-#define VIC_FIQ_STATUS2     VIC_REG(0x0098)
-#define VIC_FIQ_STATUS3     VIC_REG(0x009C)
-#define VIC_RAW_STATUS0     VIC_REG(0x00A0)
-#define VIC_RAW_STATUS1     VIC_REG(0x00A4)
-#define VIC_RAW_STATUS2     VIC_REG(0x00A8)
-#define VIC_RAW_STATUS3     VIC_REG(0x00AC)
-#define VIC_INT_CLEAR0      VIC_REG(0x00B0)
-#define VIC_INT_CLEAR1      VIC_REG(0x00B4)
-#define VIC_INT_CLEAR2      VIC_REG(0x00B8)
-#define VIC_INT_CLEAR3      VIC_REG(0x00BC)
-#define VIC_SOFTINT0        VIC_REG(0x00C0)
-#define VIC_SOFTINT1        VIC_REG(0x00C4)
-#define VIC_SOFTINT2        VIC_REG(0x00C8)
-#define VIC_SOFTINT3        VIC_REG(0x00CC)
-#define VIC_IRQ_VEC_RD      VIC_REG(0x00D0)  /* pending int # */
-#define VIC_IRQ_VEC_PEND_RD VIC_REG(0x00D4)  /* pending vector addr */
-#define VIC_IRQ_VEC_WR      VIC_REG(0x00D8)
-
-#if defined(CONFIG_ARCH_MSM_SCORPION)
-#define VIC_FIQ_VEC_RD      VIC_REG(0x00DC)
-#define VIC_FIQ_VEC_PEND_RD VIC_REG(0x00E0)
-#define VIC_FIQ_VEC_WR      VIC_REG(0x00E4)
-#define VIC_IRQ_IN_SERVICE  VIC_REG(0x00E8)
-#define VIC_IRQ_IN_STACK    VIC_REG(0x00EC)
-#define VIC_FIQ_IN_SERVICE  VIC_REG(0x00F0)
-#define VIC_FIQ_IN_STACK    VIC_REG(0x00F4)
-#define VIC_TEST_BUS_SEL    VIC_REG(0x00F8)
-#define VIC_IRQ_CTRL_CONFIG VIC_REG(0x00FC)
-#else
-#define VIC_IRQ_IN_SERVICE  VIC_REG(0x00E0)
-#define VIC_IRQ_IN_STACK    VIC_REG(0x00E4)
-#define VIC_TEST_BUS_SEL    VIC_REG(0x00E8)
-#endif
-
-#define VIC_VECTPRIORITY(n) VIC_REG(0x0200+((n) * 4))
-#define VIC_VECTADDR(n)     VIC_REG(0x0400+((n) * 4))
-
-#if defined(CONFIG_ARCH_MSM7X30)
-#define VIC_NUM_REGS       4
-#else
-#define VIC_NUM_REGS       2
-#endif
-
-#if VIC_NUM_REGS == 2
-#define DPRINT_REGS(base_reg, format, ...)                             \
-       printk(KERN_INFO format " %x %x\n", ##__VA_ARGS__,              \
-                       readl(base_reg ## 0), readl(base_reg ## 1))
-#define DPRINT_ARRAY(array, format, ...)                               \
-       printk(KERN_INFO format " %x %x\n", ##__VA_ARGS__,              \
-                       array[0], array[1])
-#elif VIC_NUM_REGS == 4
-#define DPRINT_REGS(base_reg, format, ...) \
-       printk(KERN_INFO format " %x %x %x %x\n", ##__VA_ARGS__,        \
-                       readl(base_reg ## 0), readl(base_reg ## 1),     \
-                       readl(base_reg ## 2), readl(base_reg ## 3))
-#define DPRINT_ARRAY(array, format, ...)                               \
-       printk(KERN_INFO format " %x %x %x %x\n", ##__VA_ARGS__,        \
-                       array[0], array[1],                             \
-                       array[2], array[3])
-#else
-#error "VIC_NUM_REGS set to illegal value"
-#endif
-
-static uint32_t msm_irq_smsm_wake_enable[2];
-static struct {
-       uint32_t int_en[2];
-       uint32_t int_type;
-       uint32_t int_polarity;
-       uint32_t int_select;
-} msm_irq_shadow_reg[VIC_NUM_REGS];
-static uint32_t msm_irq_idle_disable[VIC_NUM_REGS];
-
-#define SMSM_FAKE_IRQ (0xff)
-static uint8_t msm_irq_to_smsm[NR_IRQS] = {
-       [INT_MDDI_EXT] = 1,
-       [INT_MDDI_PRI] = 2,
-       [INT_MDDI_CLIENT] = 3,
-       [INT_USB_OTG] = 4,
-
-       [INT_PWB_I2C] = 5,
-       [INT_SDC1_0] = 6,
-       [INT_SDC1_1] = 7,
-       [INT_SDC2_0] = 8,
-
-       [INT_SDC2_1] = 9,
-       [INT_ADSP_A9_A11] = 10,
-       [INT_UART1] = 11,
-       [INT_UART2] = 12,
-
-       [INT_UART3] = 13,
-       [INT_UART1_RX] = 14,
-       [INT_UART2_RX] = 15,
-       [INT_UART3_RX] = 16,
-
-       [INT_UART1DM_IRQ] = 17,
-       [INT_UART1DM_RX] = 18,
-       [INT_KEYSENSE] = 19,
-#if !defined(CONFIG_ARCH_MSM7X30)
-       [INT_AD_HSSD] = 20,
-#endif
-
-       [INT_NAND_WR_ER_DONE] = 21,
-       [INT_NAND_OP_DONE] = 22,
-       [INT_TCHSCRN1] = 23,
-       [INT_TCHSCRN2] = 24,
-
-       [INT_TCHSCRN_SSBI] = 25,
-       [INT_USB_HS] = 26,
-       [INT_UART2DM_RX] = 27,
-       [INT_UART2DM_IRQ] = 28,
-
-       [INT_SDC4_1] = 29,
-       [INT_SDC4_0] = 30,
-       [INT_SDC3_1] = 31,
-       [INT_SDC3_0] = 32,
-
-       /* fake wakeup interrupts */
-       [INT_GPIO_GROUP1] = SMSM_FAKE_IRQ,
-       [INT_GPIO_GROUP2] = SMSM_FAKE_IRQ,
-       [INT_A9_M2A_0] = SMSM_FAKE_IRQ,
-       [INT_A9_M2A_1] = SMSM_FAKE_IRQ,
-       [INT_A9_M2A_5] = SMSM_FAKE_IRQ,
-       [INT_GP_TIMER_EXP] = SMSM_FAKE_IRQ,
-       [INT_DEBUG_TIMER_EXP] = SMSM_FAKE_IRQ,
-       [INT_ADSP_A11] = SMSM_FAKE_IRQ,
-#ifdef CONFIG_ARCH_QSD8X50
-       [INT_SIRC_0] = SMSM_FAKE_IRQ,
-       [INT_SIRC_1] = SMSM_FAKE_IRQ,
-#endif
-};
-
-static inline void msm_irq_write_all_regs(void __iomem *base, unsigned int val)
-{
-       int i;
-
-       for (i = 0; i < VIC_NUM_REGS; i++)
-               writel(val, base + (i * 4));
-}
-
-static void msm_irq_ack(struct irq_data *d)
-{
-       void __iomem *reg = VIC_INT_TO_REG_ADDR(VIC_INT_CLEAR0, d->irq);
-       writel(1 << (d->irq & 31), reg);
-}
-
-static void msm_irq_mask(struct irq_data *d)
-{
-       void __iomem *reg = VIC_INT_TO_REG_ADDR(VIC_INT_ENCLEAR0, d->irq);
-       unsigned index = VIC_INT_TO_REG_INDEX(d->irq);
-       uint32_t mask = 1UL << (d->irq & 31);
-       int smsm_irq = msm_irq_to_smsm[d->irq];
-
-       msm_irq_shadow_reg[index].int_en[0] &= ~mask;
-       writel(mask, reg);
-       if (smsm_irq == 0)
-               msm_irq_idle_disable[index] &= ~mask;
-       else {
-               mask = 1UL << (smsm_irq - 1);
-               msm_irq_smsm_wake_enable[0] &= ~mask;
-       }
-}
-
-static void msm_irq_unmask(struct irq_data *d)
-{
-       void __iomem *reg = VIC_INT_TO_REG_ADDR(VIC_INT_ENSET0, d->irq);
-       unsigned index = VIC_INT_TO_REG_INDEX(d->irq);
-       uint32_t mask = 1UL << (d->irq & 31);
-       int smsm_irq = msm_irq_to_smsm[d->irq];
-
-       msm_irq_shadow_reg[index].int_en[0] |= mask;
-       writel(mask, reg);
-
-       if (smsm_irq == 0)
-               msm_irq_idle_disable[index] |= mask;
-       else {
-               mask = 1UL << (smsm_irq - 1);
-               msm_irq_smsm_wake_enable[0] |= mask;
-       }
-}
-
-static int msm_irq_set_wake(struct irq_data *d, unsigned int on)
-{
-       unsigned index = VIC_INT_TO_REG_INDEX(d->irq);
-       uint32_t mask = 1UL << (d->irq & 31);
-       int smsm_irq = msm_irq_to_smsm[d->irq];
-
-       if (smsm_irq == 0) {
-               printk(KERN_ERR "msm_irq_set_wake: bad wakeup irq %d\n", d->irq);
-               return -EINVAL;
-       }
-       if (on)
-               msm_irq_shadow_reg[index].int_en[1] |= mask;
-       else
-               msm_irq_shadow_reg[index].int_en[1] &= ~mask;
-
-       if (smsm_irq == SMSM_FAKE_IRQ)
-               return 0;
-
-       mask = 1UL << (smsm_irq - 1);
-       if (on)
-               msm_irq_smsm_wake_enable[1] |= mask;
-       else
-               msm_irq_smsm_wake_enable[1] &= ~mask;
-       return 0;
-}
-
-static int msm_irq_set_type(struct irq_data *d, unsigned int flow_type)
-{
-       void __iomem *treg = VIC_INT_TO_REG_ADDR(VIC_INT_TYPE0, d->irq);
-       void __iomem *preg = VIC_INT_TO_REG_ADDR(VIC_INT_POLARITY0, d->irq);
-       unsigned index = VIC_INT_TO_REG_INDEX(d->irq);
-       int b = 1 << (d->irq & 31);
-       uint32_t polarity;
-       uint32_t type;
-
-       polarity = msm_irq_shadow_reg[index].int_polarity;
-       if (flow_type & (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW))
-               polarity |= b;
-       if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_HIGH))
-               polarity &= ~b;
-       writel(polarity, preg);
-       msm_irq_shadow_reg[index].int_polarity = polarity;
-
-       type = msm_irq_shadow_reg[index].int_type;
-       if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
-               type |= b;
-               __irq_set_handler_locked(d->irq, handle_edge_irq);
-       }
-       if (flow_type & (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW)) {
-               type &= ~b;
-               __irq_set_handler_locked(d->irq, handle_level_irq);
-       }
-       writel(type, treg);
-       msm_irq_shadow_reg[index].int_type = type;
-       return 0;
-}
-
-static struct irq_chip msm_irq_chip = {
-       .name          = "msm",
-       .irq_disable   = msm_irq_mask,
-       .irq_ack       = msm_irq_ack,
-       .irq_mask      = msm_irq_mask,
-       .irq_unmask    = msm_irq_unmask,
-       .irq_set_wake  = msm_irq_set_wake,
-       .irq_set_type  = msm_irq_set_type,
-};
-
-void __init msm_init_irq(void)
-{
-       unsigned n;
-
-       /* select level interrupts */
-       msm_irq_write_all_regs(VIC_INT_TYPE0, 0);
-
-       /* select highlevel interrupts */
-       msm_irq_write_all_regs(VIC_INT_POLARITY0, 0);
-
-       /* select IRQ for all INTs */
-       msm_irq_write_all_regs(VIC_INT_SELECT0, 0);
-
-       /* disable all INTs */
-       msm_irq_write_all_regs(VIC_INT_EN0, 0);
-
-       /* don't use vic */
-       writel(0, VIC_CONFIG);
-
-       /* enable interrupt controller */
-       writel(3, VIC_INT_MASTEREN);
-
-       for (n = 0; n < NR_MSM_IRQS; n++) {
-               irq_set_chip_and_handler(n, &msm_irq_chip, handle_level_irq);
-               set_irq_flags(n, IRQF_VALID);
-       }
-}
diff --git a/arch/arm/mach-msm/irq.c b/arch/arm/mach-msm/irq.c
deleted file mode 100644 (file)
index ea514be..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-/* linux/arch/arm/mach-msm/irq.c
- *
- * Copyright (C) 2007 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/ptrace.h>
-#include <linux/timer.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-
-#include <mach/msm_iomap.h>
-
-#define VIC_REG(off) (MSM_VIC_BASE + (off))
-
-#define VIC_INT_SELECT0     VIC_REG(0x0000)  /* 1: FIQ, 0: IRQ */
-#define VIC_INT_SELECT1     VIC_REG(0x0004)  /* 1: FIQ, 0: IRQ */
-#define VIC_INT_EN0         VIC_REG(0x0010)
-#define VIC_INT_EN1         VIC_REG(0x0014)
-#define VIC_INT_ENCLEAR0    VIC_REG(0x0020)
-#define VIC_INT_ENCLEAR1    VIC_REG(0x0024)
-#define VIC_INT_ENSET0      VIC_REG(0x0030)
-#define VIC_INT_ENSET1      VIC_REG(0x0034)
-#define VIC_INT_TYPE0       VIC_REG(0x0040)  /* 1: EDGE, 0: LEVEL  */
-#define VIC_INT_TYPE1       VIC_REG(0x0044)  /* 1: EDGE, 0: LEVEL  */
-#define VIC_INT_POLARITY0   VIC_REG(0x0050)  /* 1: NEG, 0: POS */
-#define VIC_INT_POLARITY1   VIC_REG(0x0054)  /* 1: NEG, 0: POS */
-#define VIC_NO_PEND_VAL     VIC_REG(0x0060)
-#define VIC_INT_MASTEREN    VIC_REG(0x0064)  /* 1: IRQ, 2: FIQ     */
-#define VIC_PROTECTION      VIC_REG(0x006C)  /* 1: ENABLE          */
-#define VIC_CONFIG          VIC_REG(0x0068)  /* 1: USE ARM1136 VIC */
-#define VIC_IRQ_STATUS0     VIC_REG(0x0080)
-#define VIC_IRQ_STATUS1     VIC_REG(0x0084)
-#define VIC_FIQ_STATUS0     VIC_REG(0x0090)
-#define VIC_FIQ_STATUS1     VIC_REG(0x0094)
-#define VIC_RAW_STATUS0     VIC_REG(0x00A0)
-#define VIC_RAW_STATUS1     VIC_REG(0x00A4)
-#define VIC_INT_CLEAR0      VIC_REG(0x00B0)
-#define VIC_INT_CLEAR1      VIC_REG(0x00B4)
-#define VIC_SOFTINT0        VIC_REG(0x00C0)
-#define VIC_SOFTINT1        VIC_REG(0x00C4)
-#define VIC_IRQ_VEC_RD      VIC_REG(0x00D0)  /* pending int # */
-#define VIC_IRQ_VEC_PEND_RD VIC_REG(0x00D4)  /* pending vector addr */
-#define VIC_IRQ_VEC_WR      VIC_REG(0x00D8)
-#define VIC_IRQ_IN_SERVICE  VIC_REG(0x00E0)
-#define VIC_IRQ_IN_STACK    VIC_REG(0x00E4)
-#define VIC_TEST_BUS_SEL    VIC_REG(0x00E8)
-
-#define VIC_VECTPRIORITY(n) VIC_REG(0x0200+((n) * 4))
-#define VIC_VECTADDR(n)     VIC_REG(0x0400+((n) * 4))
-
-static void msm_irq_ack(struct irq_data *d)
-{
-       void __iomem *reg = VIC_INT_CLEAR0 + ((d->irq & 32) ? 4 : 0);
-       writel(1 << (d->irq & 31), reg);
-}
-
-static void msm_irq_mask(struct irq_data *d)
-{
-       void __iomem *reg = VIC_INT_ENCLEAR0 + ((d->irq & 32) ? 4 : 0);
-       writel(1 << (d->irq & 31), reg);
-}
-
-static void msm_irq_unmask(struct irq_data *d)
-{
-       void __iomem *reg = VIC_INT_ENSET0 + ((d->irq & 32) ? 4 : 0);
-       writel(1 << (d->irq & 31), reg);
-}
-
-static int msm_irq_set_wake(struct irq_data *d, unsigned int on)
-{
-       return -EINVAL;
-}
-
-static int msm_irq_set_type(struct irq_data *d, unsigned int flow_type)
-{
-       void __iomem *treg = VIC_INT_TYPE0 + ((d->irq & 32) ? 4 : 0);
-       void __iomem *preg = VIC_INT_POLARITY0 + ((d->irq & 32) ? 4 : 0);
-       int b = 1 << (d->irq & 31);
-
-       if (flow_type & (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW))
-               writel(readl(preg) | b, preg);
-       if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_HIGH))
-               writel(readl(preg) & (~b), preg);
-
-       if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
-               writel(readl(treg) | b, treg);
-               __irq_set_handler_locked(d->irq, handle_edge_irq);
-       }
-       if (flow_type & (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW)) {
-               writel(readl(treg) & (~b), treg);
-               __irq_set_handler_locked(d->irq, handle_level_irq);
-       }
-       return 0;
-}
-
-static struct irq_chip msm_irq_chip = {
-       .name          = "msm",
-       .irq_ack       = msm_irq_ack,
-       .irq_mask      = msm_irq_mask,
-       .irq_unmask    = msm_irq_unmask,
-       .irq_set_wake  = msm_irq_set_wake,
-       .irq_set_type  = msm_irq_set_type,
-};
-
-void __init msm_init_irq(void)
-{
-       unsigned n;
-
-       /* select level interrupts */
-       writel(0, VIC_INT_TYPE0);
-       writel(0, VIC_INT_TYPE1);
-
-       /* select highlevel interrupts */
-       writel(0, VIC_INT_POLARITY0);
-       writel(0, VIC_INT_POLARITY1);
-
-       /* select IRQ for all INTs */
-       writel(0, VIC_INT_SELECT0);
-       writel(0, VIC_INT_SELECT1);
-
-       /* disable all INTs */
-       writel(0, VIC_INT_EN0);
-       writel(0, VIC_INT_EN1);
-
-       /* don't use 1136 vic */
-       writel(0, VIC_CONFIG);
-
-       /* enable interrupt controller */
-       writel(1, VIC_INT_MASTEREN);
-
-       for (n = 0; n < NR_MSM_IRQS; n++) {
-               irq_set_chip_and_handler(n, &msm_irq_chip, handle_level_irq);
-               set_irq_flags(n, IRQF_VALID);
-       }
-}
diff --git a/arch/arm/mach-msm/last_radio_log.c b/arch/arm/mach-msm/last_radio_log.c
deleted file mode 100644 (file)
index 9c392a2..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/* arch/arm/mach-msm/last_radio_log.c
- *
- * Extract the log from a modem crash though SMEM
- *
- * Copyright (C) 2007 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/proc_fs.h>
-#include <linux/uaccess.h>
-
-#include "smd_private.h"
-
-static void *radio_log_base;
-static size_t radio_log_size;
-
-extern void *smem_item(unsigned id, unsigned *size);
-
-static ssize_t last_radio_log_read(struct file *file, char __user *buf,
-                       size_t len, loff_t *offset)
-{
-       return simple_read_from_buffer(buf, len, offset,
-                               radio_log_base, radio_log_size);
-}
-
-static struct file_operations last_radio_log_fops = {
-       .read = last_radio_log_read,
-       .llseek = default_llseek,
-};
-
-void msm_init_last_radio_log(struct module *owner)
-{
-       struct proc_dir_entry *entry;
-
-       if (last_radio_log_fops.owner) {
-               pr_err("%s: already claimed\n", __func__);
-               return;
-       }
-
-       radio_log_base = smem_item(SMEM_CLKREGIM_BSP, &radio_log_size);
-       if (!radio_log_base) {
-               pr_err("%s: could not retrieve SMEM_CLKREGIM_BSP\n", __func__);
-               return;
-       }
-
-       entry = proc_create("last_radio_log", S_IRUGO, NULL,
-                               &last_radio_log_fops);
-       if (!entry) {
-               pr_err("%s: could not create proc entry for radio log\n",
-                               __func__);
-               return;
-       }
-
-       pr_err("%s: last radio log is %d bytes long\n", __func__,
-               radio_log_size);
-       last_radio_log_fops.owner = owner;
-       proc_set_size(entry, radio_log_size);
-}
-EXPORT_SYMBOL(msm_init_last_radio_log);
diff --git a/arch/arm/mach-msm/proc_comm.c b/arch/arm/mach-msm/proc_comm.c
deleted file mode 100644 (file)
index 507f5ca..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-/* arch/arm/mach-msm/proc_comm.c
- *
- * Copyright (C) 2007-2008 Google, Inc.
- * Author: Brian Swetland <swetland@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/io.h>
-#include <linux/spinlock.h>
-#include <mach/msm_iomap.h>
-
-#include "proc_comm.h"
-
-static inline void msm_a2m_int(uint32_t irq)
-{
-#if defined(CONFIG_ARCH_MSM7X30)
-       writel(1 << irq, MSM_GCC_BASE + 0x8);
-#else
-       writel(1, MSM_CSR_BASE + 0x400 + (irq * 4));
-#endif
-}
-
-static inline void notify_other_proc_comm(void)
-{
-       msm_a2m_int(6);
-}
-
-#define APP_COMMAND 0x00
-#define APP_STATUS  0x04
-#define APP_DATA1   0x08
-#define APP_DATA2   0x0C
-
-#define MDM_COMMAND 0x10
-#define MDM_STATUS  0x14
-#define MDM_DATA1   0x18
-#define MDM_DATA2   0x1C
-
-static DEFINE_SPINLOCK(proc_comm_lock);
-
-/* The higher level SMD support will install this to
- * provide a way to check for and handle modem restart.
- */
-int (*msm_check_for_modem_crash)(void);
-
-/* Poll for a state change, checking for possible
- * modem crashes along the way (so we don't wait
- * forever while the ARM9 is blowing up).
- *
- * Return an error in the event of a modem crash and
- * restart so the msm_proc_comm() routine can restart
- * the operation from the beginning.
- */
-static int proc_comm_wait_for(void __iomem *addr, unsigned value)
-{
-       for (;;) {
-               if (readl(addr) == value)
-                       return 0;
-
-               if (msm_check_for_modem_crash)
-                       if (msm_check_for_modem_crash())
-                               return -EAGAIN;
-       }
-}
-
-int msm_proc_comm(unsigned cmd, unsigned *data1, unsigned *data2)
-{
-       void __iomem *base = MSM_SHARED_RAM_BASE;
-       unsigned long flags;
-       int ret;
-
-       spin_lock_irqsave(&proc_comm_lock, flags);
-
-       for (;;) {
-               if (proc_comm_wait_for(base + MDM_STATUS, PCOM_READY))
-                       continue;
-
-               writel(cmd, base + APP_COMMAND);
-               writel(data1 ? *data1 : 0, base + APP_DATA1);
-               writel(data2 ? *data2 : 0, base + APP_DATA2);
-
-               notify_other_proc_comm();
-
-               if (proc_comm_wait_for(base + APP_COMMAND, PCOM_CMD_DONE))
-                       continue;
-
-               if (readl(base + APP_STATUS) != PCOM_CMD_FAIL) {
-                       if (data1)
-                               *data1 = readl(base + APP_DATA1);
-                       if (data2)
-                               *data2 = readl(base + APP_DATA2);
-                       ret = 0;
-               } else {
-                       ret = -EIO;
-               }
-               break;
-       }
-
-       writel(PCOM_CMD_IDLE, base + APP_COMMAND);
-
-       spin_unlock_irqrestore(&proc_comm_lock, flags);
-
-       return ret;
-}
-
-/*
- * We need to wait for the ARM9 to at least partially boot
- * up before we can continue. Since the ARM9 does resource
- * allocation, if we dont' wait we could end up crashing or in
- * and unknown state. This function should be called early to
- * wait on the ARM9.
- */
-void proc_comm_boot_wait(void)
-{
-       void __iomem *base = MSM_SHARED_RAM_BASE;
-       proc_comm_wait_for(base + MDM_STATUS, PCOM_READY);
-}
diff --git a/arch/arm/mach-msm/proc_comm.h b/arch/arm/mach-msm/proc_comm.h
deleted file mode 100644 (file)
index e8d043a..0000000
+++ /dev/null
@@ -1,258 +0,0 @@
-/* arch/arm/mach-msm/proc_comm.h
- *
- * Copyright (c) 2007 QUALCOMM Incorporated
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _ARCH_ARM_MACH_MSM_PROC_COMM_H_
-#define _ARCH_ARM_MACH_MSM_PROC_COMM_H_
-
-#include <linux/init.h>
-
-enum {
-       PCOM_CMD_IDLE = 0x0,
-       PCOM_CMD_DONE,
-       PCOM_RESET_APPS,
-       PCOM_RESET_CHIP,
-       PCOM_CONFIG_NAND_MPU,
-       PCOM_CONFIG_USB_CLKS,
-       PCOM_GET_POWER_ON_STATUS,
-       PCOM_GET_WAKE_UP_STATUS,
-       PCOM_GET_BATT_LEVEL,
-       PCOM_CHG_IS_CHARGING,
-       PCOM_POWER_DOWN,
-       PCOM_USB_PIN_CONFIG,
-       PCOM_USB_PIN_SEL,
-       PCOM_SET_RTC_ALARM,
-       PCOM_NV_READ,
-       PCOM_NV_WRITE,
-       PCOM_GET_UUID_HIGH,
-       PCOM_GET_UUID_LOW,
-       PCOM_GET_HW_ENTROPY,
-       PCOM_RPC_GPIO_TLMM_CONFIG_REMOTE,
-       PCOM_CLKCTL_RPC_ENABLE,
-       PCOM_CLKCTL_RPC_DISABLE,
-       PCOM_CLKCTL_RPC_RESET,
-       PCOM_CLKCTL_RPC_SET_FLAGS,
-       PCOM_CLKCTL_RPC_SET_RATE,
-       PCOM_CLKCTL_RPC_MIN_RATE,
-       PCOM_CLKCTL_RPC_MAX_RATE,
-       PCOM_CLKCTL_RPC_RATE,
-       PCOM_CLKCTL_RPC_PLL_REQUEST,
-       PCOM_CLKCTL_RPC_ENABLED,
-       PCOM_VREG_SWITCH,
-       PCOM_VREG_SET_LEVEL,
-       PCOM_GPIO_TLMM_CONFIG_GROUP,
-       PCOM_GPIO_TLMM_UNCONFIG_GROUP,
-       PCOM_NV_WRITE_BYTES_4_7,
-       PCOM_CONFIG_DISP,
-       PCOM_GET_FTM_BOOT_COUNT,
-       PCOM_RPC_GPIO_TLMM_CONFIG_EX,
-       PCOM_PM_MPP_CONFIG,
-       PCOM_GPIO_IN,
-       PCOM_GPIO_OUT,
-       PCOM_RESET_MODEM,
-       PCOM_RESET_CHIP_IMM,
-       PCOM_PM_VID_EN,
-       PCOM_VREG_PULLDOWN,
-       PCOM_GET_MODEM_VERSION,
-       PCOM_CLK_REGIME_SEC_RESET,
-       PCOM_CLK_REGIME_SEC_RESET_ASSERT,
-       PCOM_CLK_REGIME_SEC_RESET_DEASSERT,
-       PCOM_CLK_REGIME_SEC_PLL_REQUEST_WRP,
-       PCOM_CLK_REGIME_SEC_ENABLE,
-       PCOM_CLK_REGIME_SEC_DISABLE,
-       PCOM_CLK_REGIME_SEC_IS_ON,
-       PCOM_CLK_REGIME_SEC_SEL_CLK_INV,
-       PCOM_CLK_REGIME_SEC_SEL_CLK_SRC,
-       PCOM_CLK_REGIME_SEC_SEL_CLK_DIV,
-       PCOM_CLK_REGIME_SEC_ICODEC_CLK_ENABLE,
-       PCOM_CLK_REGIME_SEC_ICODEC_CLK_DISABLE,
-       PCOM_CLK_REGIME_SEC_SEL_SPEED,
-       PCOM_CLK_REGIME_SEC_CONFIG_GP_CLK_WRP,
-       PCOM_CLK_REGIME_SEC_CONFIG_MDH_CLK_WRP,
-       PCOM_CLK_REGIME_SEC_USB_XTAL_ON,
-       PCOM_CLK_REGIME_SEC_USB_XTAL_OFF,
-       PCOM_CLK_REGIME_SEC_SET_QDSP_DME_MODE,
-       PCOM_CLK_REGIME_SEC_SWITCH_ADSP_CLK,
-       PCOM_CLK_REGIME_SEC_GET_MAX_ADSP_CLK_KHZ,
-       PCOM_CLK_REGIME_SEC_GET_I2C_CLK_KHZ,
-       PCOM_CLK_REGIME_SEC_MSM_GET_CLK_FREQ_KHZ,
-       PCOM_CLK_REGIME_SEC_SEL_VFE_SRC,
-       PCOM_CLK_REGIME_SEC_MSM_SEL_CAMCLK,
-       PCOM_CLK_REGIME_SEC_MSM_SEL_LCDCLK,
-       PCOM_CLK_REGIME_SEC_VFE_RAIL_OFF,
-       PCOM_CLK_REGIME_SEC_VFE_RAIL_ON,
-       PCOM_CLK_REGIME_SEC_GRP_RAIL_OFF,
-       PCOM_CLK_REGIME_SEC_GRP_RAIL_ON,
-       PCOM_CLK_REGIME_SEC_VDC_RAIL_OFF,
-       PCOM_CLK_REGIME_SEC_VDC_RAIL_ON,
-       PCOM_CLK_REGIME_SEC_LCD_CTRL,
-       PCOM_CLK_REGIME_SEC_REGISTER_FOR_CPU_RESOURCE,
-       PCOM_CLK_REGIME_SEC_DEREGISTER_FOR_CPU_RESOURCE,
-       PCOM_CLK_REGIME_SEC_RESOURCE_REQUEST_WRP,
-       PCOM_CLK_REGIME_MSM_SEC_SEL_CLK_OWNER,
-       PCOM_CLK_REGIME_SEC_DEVMAN_REQUEST_WRP,
-       PCOM_GPIO_CONFIG,
-       PCOM_GPIO_CONFIGURE_GROUP,
-       PCOM_GPIO_TLMM_SET_PORT,
-       PCOM_GPIO_TLMM_CONFIG_EX,
-       PCOM_SET_FTM_BOOT_COUNT,
-       PCOM_RESERVED0,
-       PCOM_RESERVED1,
-       PCOM_CUSTOMER_CMD1,
-       PCOM_CUSTOMER_CMD2,
-       PCOM_CUSTOMER_CMD3,
-       PCOM_CLK_REGIME_ENTER_APPSBL_CHG_MODE,
-       PCOM_CLK_REGIME_EXIT_APPSBL_CHG_MODE,
-       PCOM_CLK_REGIME_SEC_RAIL_DISABLE,
-       PCOM_CLK_REGIME_SEC_RAIL_ENABLE,
-       PCOM_CLK_REGIME_SEC_RAIL_CONTROL,
-       PCOM_SET_SW_WATCHDOG_STATE,
-       PCOM_PM_MPP_CONFIG_DIGITAL_INPUT,
-       PCOM_PM_MPP_CONFIG_I_SINK,
-       PCOM_RESERVED_101,
-       PCOM_MSM_HSUSB_PHY_RESET,
-       PCOM_GET_BATT_MV_LEVEL,
-       PCOM_CHG_USB_IS_PC_CONNECTED,
-       PCOM_CHG_USB_IS_CHARGER_CONNECTED,
-       PCOM_CHG_USB_IS_DISCONNECTED,
-       PCOM_CHG_USB_IS_AVAILABLE,
-       PCOM_CLK_REGIME_SEC_MSM_SEL_FREQ,
-       PCOM_CLK_REGIME_SEC_SET_PCLK_AXI_POLICY,
-       PCOM_CLKCTL_RPC_RESET_ASSERT,
-       PCOM_CLKCTL_RPC_RESET_DEASSERT,
-       PCOM_CLKCTL_RPC_RAIL_ON,
-       PCOM_CLKCTL_RPC_RAIL_OFF,
-       PCOM_CLKCTL_RPC_RAIL_ENABLE,
-       PCOM_CLKCTL_RPC_RAIL_DISABLE,
-       PCOM_CLKCTL_RPC_RAIL_CONTROL,
-       PCOM_CLKCTL_RPC_MIN_MSMC1,
-       PCOM_NUM_CMDS,
-};
-
-enum {
-       PCOM_INVALID_STATUS = 0x0,
-       PCOM_READY,
-       PCOM_CMD_RUNNING,
-       PCOM_CMD_SUCCESS,
-       PCOM_CMD_FAIL,
-       PCOM_CMD_FAIL_FALSE_RETURNED,
-       PCOM_CMD_FAIL_CMD_OUT_OF_BOUNDS_SERVER,
-       PCOM_CMD_FAIL_CMD_OUT_OF_BOUNDS_CLIENT,
-       PCOM_CMD_FAIL_CMD_UNREGISTERED,
-       PCOM_CMD_FAIL_CMD_LOCKED,
-       PCOM_CMD_FAIL_SERVER_NOT_YET_READY,
-       PCOM_CMD_FAIL_BAD_DESTINATION,
-       PCOM_CMD_FAIL_SERVER_RESET,
-       PCOM_CMD_FAIL_SMSM_NOT_INIT,
-       PCOM_CMD_FAIL_PROC_COMM_BUSY,
-       PCOM_CMD_FAIL_PROC_COMM_NOT_INIT,
-
-};
-
-/* List of VREGs that support the Pull Down Resistor setting. */
-enum vreg_pdown_id {
-       PM_VREG_PDOWN_MSMA_ID,
-       PM_VREG_PDOWN_MSMP_ID,
-       PM_VREG_PDOWN_MSME1_ID, /* Not supported in Panoramix */
-       PM_VREG_PDOWN_MSMC1_ID, /* Not supported in PM6620 */
-       PM_VREG_PDOWN_MSMC2_ID, /* Supported in PM7500 only */
-       PM_VREG_PDOWN_GP3_ID,   /* Supported in PM7500 only */
-       PM_VREG_PDOWN_MSME2_ID, /* Supported in PM7500 and Panoramix only */
-       PM_VREG_PDOWN_GP4_ID,   /* Supported in PM7500 only */
-       PM_VREG_PDOWN_GP1_ID,   /* Supported in PM7500 only */
-       PM_VREG_PDOWN_TCXO_ID,
-       PM_VREG_PDOWN_PA_ID,
-       PM_VREG_PDOWN_RFTX_ID,
-       PM_VREG_PDOWN_RFRX1_ID,
-       PM_VREG_PDOWN_RFRX2_ID,
-       PM_VREG_PDOWN_SYNT_ID,
-       PM_VREG_PDOWN_WLAN_ID,
-       PM_VREG_PDOWN_USB_ID,
-       PM_VREG_PDOWN_MMC_ID,
-       PM_VREG_PDOWN_RUIM_ID,
-       PM_VREG_PDOWN_MSMC0_ID, /* Supported in PM6610 only */
-       PM_VREG_PDOWN_GP2_ID,   /* Supported in PM7500 only */
-       PM_VREG_PDOWN_GP5_ID,   /* Supported in PM7500 only */
-       PM_VREG_PDOWN_GP6_ID,   /* Supported in PM7500 only */
-       PM_VREG_PDOWN_RF_ID,
-       PM_VREG_PDOWN_RF_VCO_ID,
-       PM_VREG_PDOWN_MPLL_ID,
-       PM_VREG_PDOWN_S2_ID,
-       PM_VREG_PDOWN_S3_ID,
-       PM_VREG_PDOWN_RFUBM_ID,
-
-       /* new for HAN */
-       PM_VREG_PDOWN_RF1_ID,
-       PM_VREG_PDOWN_RF2_ID,
-       PM_VREG_PDOWN_RFA_ID,
-       PM_VREG_PDOWN_CDC2_ID,
-       PM_VREG_PDOWN_RFTX2_ID,
-       PM_VREG_PDOWN_USIM_ID,
-       PM_VREG_PDOWN_USB2P6_ID,
-       PM_VREG_PDOWN_USB3P3_ID,
-       PM_VREG_PDOWN_INVALID_ID,
-
-       /* backward compatible enums only */
-       PM_VREG_PDOWN_CAM_ID = PM_VREG_PDOWN_GP1_ID,
-       PM_VREG_PDOWN_MDDI_ID = PM_VREG_PDOWN_GP2_ID,
-       PM_VREG_PDOWN_RUIM2_ID = PM_VREG_PDOWN_GP3_ID,
-       PM_VREG_PDOWN_AUX_ID = PM_VREG_PDOWN_GP4_ID,
-       PM_VREG_PDOWN_AUX2_ID = PM_VREG_PDOWN_GP5_ID,
-       PM_VREG_PDOWN_BT_ID = PM_VREG_PDOWN_GP6_ID,
-
-       PM_VREG_PDOWN_MSME_ID = PM_VREG_PDOWN_MSME1_ID,
-       PM_VREG_PDOWN_MSMC_ID = PM_VREG_PDOWN_MSMC1_ID,
-       PM_VREG_PDOWN_RFA1_ID = PM_VREG_PDOWN_RFRX2_ID,
-       PM_VREG_PDOWN_RFA2_ID = PM_VREG_PDOWN_RFTX2_ID,
-       PM_VREG_PDOWN_XO_ID = PM_VREG_PDOWN_TCXO_ID
-};
-
-enum {
-       PCOM_CLKRGM_APPS_RESET_USB_PHY  = 34,
-       PCOM_CLKRGM_APPS_RESET_USBH     = 37,
-};
-
-/* gpio info for PCOM_RPC_GPIO_TLMM_CONFIG_EX */
-
-#define GPIO_ENABLE    0
-#define GPIO_DISABLE   1
-
-#define GPIO_INPUT     0
-#define GPIO_OUTPUT    1
-
-#define GPIO_NO_PULL   0
-#define GPIO_PULL_DOWN 1
-#define GPIO_KEEPER    2
-#define GPIO_PULL_UP   3
-
-#define GPIO_2MA       0
-#define GPIO_4MA       1
-#define GPIO_6MA       2
-#define GPIO_8MA       3
-#define GPIO_10MA      4
-#define GPIO_12MA      5
-#define GPIO_14MA      6
-#define GPIO_16MA      7
-
-#define PCOM_GPIO_CFG(gpio, func, dir, pull, drvstr) \
-               ((((gpio) & 0x3FF) << 4)        | \
-               ((func) & 0xf)                  | \
-               (((dir) & 0x1) << 14)           | \
-               (((pull) & 0x3) << 15)          | \
-               (((drvstr) & 0xF) << 17))
-
-int msm_proc_comm(unsigned cmd, unsigned *data1, unsigned *data2);
-void proc_comm_boot_wait(void);
-
-#endif
diff --git a/arch/arm/mach-msm/sirc.c b/arch/arm/mach-msm/sirc.c
deleted file mode 100644 (file)
index 689e78c..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only 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 Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- */
-
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <asm/irq.h>
-
-static unsigned int int_enable;
-static unsigned int wake_enable;
-
-static struct sirc_regs_t sirc_regs = {
-       .int_enable       = SPSS_SIRC_INT_ENABLE,
-       .int_enable_clear = SPSS_SIRC_INT_ENABLE_CLEAR,
-       .int_enable_set   = SPSS_SIRC_INT_ENABLE_SET,
-       .int_type         = SPSS_SIRC_INT_TYPE,
-       .int_polarity     = SPSS_SIRC_INT_POLARITY,
-       .int_clear        = SPSS_SIRC_INT_CLEAR,
-};
-
-static struct sirc_cascade_regs sirc_reg_table[] = {
-       {
-               .int_status  = SPSS_SIRC_IRQ_STATUS,
-               .cascade_irq = INT_SIRC_0,
-       }
-};
-
-/* Mask off the given interrupt. Keep the int_enable mask in sync with
-   the enable reg, so it can be restored after power collapse. */
-static void sirc_irq_mask(struct irq_data *d)
-{
-       unsigned int mask;
-
-       mask = 1 << (d->irq - FIRST_SIRC_IRQ);
-       writel(mask, sirc_regs.int_enable_clear);
-       int_enable &= ~mask;
-       return;
-}
-
-/* Unmask the given interrupt. Keep the int_enable mask in sync with
-   the enable reg, so it can be restored after power collapse. */
-static void sirc_irq_unmask(struct irq_data *d)
-{
-       unsigned int mask;
-
-       mask = 1 << (d->irq - FIRST_SIRC_IRQ);
-       writel(mask, sirc_regs.int_enable_set);
-       int_enable |= mask;
-       return;
-}
-
-static void sirc_irq_ack(struct irq_data *d)
-{
-       unsigned int mask;
-
-       mask = 1 << (d->irq - FIRST_SIRC_IRQ);
-       writel(mask, sirc_regs.int_clear);
-       return;
-}
-
-static int sirc_irq_set_wake(struct irq_data *d, unsigned int on)
-{
-       unsigned int mask;
-
-       /* Used to set the interrupt enable mask during power collapse. */
-       mask = 1 << (d->irq - FIRST_SIRC_IRQ);
-       if (on)
-               wake_enable |= mask;
-       else
-               wake_enable &= ~mask;
-
-       return 0;
-}
-
-static int sirc_irq_set_type(struct irq_data *d, unsigned int flow_type)
-{
-       unsigned int mask;
-       unsigned int val;
-
-       mask = 1 << (d->irq - FIRST_SIRC_IRQ);
-       val = readl(sirc_regs.int_polarity);
-
-       if (flow_type & (IRQF_TRIGGER_LOW | IRQF_TRIGGER_FALLING))
-               val |= mask;
-       else
-               val &= ~mask;
-
-       writel(val, sirc_regs.int_polarity);
-
-       val = readl(sirc_regs.int_type);
-       if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
-               val |= mask;
-               __irq_set_handler_locked(d->irq, handle_edge_irq);
-       } else {
-               val &= ~mask;
-               __irq_set_handler_locked(d->irq, handle_level_irq);
-       }
-
-       writel(val, sirc_regs.int_type);
-
-       return 0;
-}
-
-/* Finds the pending interrupt on the passed cascade irq and redrives it */
-static void sirc_irq_handler(unsigned int irq, struct irq_desc *desc)
-{
-       unsigned int reg = 0;
-       unsigned int sirq;
-       unsigned int status;
-
-       while ((reg < ARRAY_SIZE(sirc_reg_table)) &&
-               (sirc_reg_table[reg].cascade_irq != irq))
-               reg++;
-
-       status = readl(sirc_reg_table[reg].int_status);
-       status &= SIRC_MASK;
-       if (status == 0)
-               return;
-
-       for (sirq = 0;
-            (sirq < NR_SIRC_IRQS) && ((status & (1U << sirq)) == 0);
-            sirq++)
-               ;
-       generic_handle_irq(sirq+FIRST_SIRC_IRQ);
-
-       desc->irq_data.chip->irq_ack(&desc->irq_data);
-}
-
-static struct irq_chip sirc_irq_chip = {
-       .name          = "sirc",
-       .irq_ack       = sirc_irq_ack,
-       .irq_mask      = sirc_irq_mask,
-       .irq_unmask    = sirc_irq_unmask,
-       .irq_set_wake  = sirc_irq_set_wake,
-       .irq_set_type  = sirc_irq_set_type,
-};
-
-void __init msm_init_sirc(void)
-{
-       int i;
-
-       int_enable = 0;
-       wake_enable = 0;
-
-       for (i = FIRST_SIRC_IRQ; i < LAST_SIRC_IRQ; i++) {
-               irq_set_chip_and_handler(i, &sirc_irq_chip, handle_edge_irq);
-               set_irq_flags(i, IRQF_VALID);
-       }
-
-       for (i = 0; i < ARRAY_SIZE(sirc_reg_table); i++) {
-               irq_set_chained_handler(sirc_reg_table[i].cascade_irq,
-                                       sirc_irq_handler);
-               irq_set_irq_wake(sirc_reg_table[i].cascade_irq, 1);
-       }
-       return;
-}
-
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
deleted file mode 100644 (file)
index 7550f5a..0000000
+++ /dev/null
@@ -1,1034 +0,0 @@
-/* arch/arm/mach-msm/smd.c
- *
- * Copyright (C) 2007 Google, Inc.
- * Author: Brian Swetland <swetland@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/cdev.h>
-#include <linux/device.h>
-#include <linux/wait.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/debugfs.h>
-#include <linux/delay.h>
-
-#include <mach/msm_smd.h>
-
-#include "smd_private.h"
-#include "proc_comm.h"
-
-#if defined(CONFIG_ARCH_QSD8X50)
-#define CONFIG_QDSP6 1
-#endif
-
-#define MODULE_NAME "msm_smd"
-
-enum {
-       MSM_SMD_DEBUG = 1U << 0,
-       MSM_SMSM_DEBUG = 1U << 0,
-};
-
-static int msm_smd_debug_mask;
-
-struct shared_info {
-       int ready;
-       void __iomem *state;
-};
-
-static unsigned dummy_state[SMSM_STATE_COUNT];
-
-static struct shared_info smd_info = {
-       /* FIXME: not a real __iomem pointer */
-       .state = &dummy_state,
-};
-
-module_param_named(debug_mask, msm_smd_debug_mask,
-                  int, S_IRUGO | S_IWUSR | S_IWGRP);
-
-static unsigned last_heap_free = 0xffffffff;
-
-static inline void notify_other_smsm(void)
-{
-       msm_a2m_int(5);
-#ifdef CONFIG_QDSP6
-       msm_a2m_int(8);
-#endif
-}
-
-static inline void notify_modem_smd(void)
-{
-       msm_a2m_int(0);
-}
-
-static inline void notify_dsp_smd(void)
-{
-       msm_a2m_int(8);
-}
-
-static void smd_diag(void)
-{
-       char *x;
-
-       x = smem_find(ID_DIAG_ERR_MSG, SZ_DIAG_ERR_MSG);
-       if (x != 0) {
-               x[SZ_DIAG_ERR_MSG - 1] = 0;
-               pr_debug("DIAG '%s'\n", x);
-       }
-}
-
-/* call when SMSM_RESET flag is set in the A9's smsm_state */
-static void handle_modem_crash(void)
-{
-       pr_err("ARM9 has CRASHED\n");
-       smd_diag();
-
-       /* in this case the modem or watchdog should reboot us */
-       for (;;)
-               ;
-}
-
-uint32_t raw_smsm_get_state(enum smsm_state_item item)
-{
-       return readl(smd_info.state + item * 4);
-}
-
-static int check_for_modem_crash(void)
-{
-       if (raw_smsm_get_state(SMSM_STATE_MODEM) & SMSM_RESET) {
-               handle_modem_crash();
-               return -1;
-       }
-       return 0;
-}
-
-/* the spinlock is used to synchronize between the
- * irq handler and code that mutates the channel
- * list or fiddles with channel state
- */
-DEFINE_SPINLOCK(smd_lock);
-DEFINE_SPINLOCK(smem_lock);
-
-/* the mutex is used during open() and close()
- * operations to avoid races while creating or
- * destroying smd_channel structures
- */
-static DEFINE_MUTEX(smd_creation_mutex);
-
-static int smd_initialized;
-
-LIST_HEAD(smd_ch_closed_list);
-LIST_HEAD(smd_ch_list_modem);
-LIST_HEAD(smd_ch_list_dsp);
-
-static unsigned char smd_ch_allocated[64];
-static struct work_struct probe_work;
-
-/* how many bytes are available for reading */
-static int smd_stream_read_avail(struct smd_channel *ch)
-{
-       return (ch->recv->head - ch->recv->tail) & ch->fifo_mask;
-}
-
-/* how many bytes we are free to write */
-static int smd_stream_write_avail(struct smd_channel *ch)
-{
-       return ch->fifo_mask -
-               ((ch->send->head - ch->send->tail) & ch->fifo_mask);
-}
-
-static int smd_packet_read_avail(struct smd_channel *ch)
-{
-       if (ch->current_packet) {
-               int n = smd_stream_read_avail(ch);
-               if (n > ch->current_packet)
-                       n = ch->current_packet;
-               return n;
-       } else {
-               return 0;
-       }
-}
-
-static int smd_packet_write_avail(struct smd_channel *ch)
-{
-       int n = smd_stream_write_avail(ch);
-       return n > SMD_HEADER_SIZE ? n - SMD_HEADER_SIZE : 0;
-}
-
-static int ch_is_open(struct smd_channel *ch)
-{
-       return (ch->recv->state == SMD_SS_OPENED) &&
-               (ch->send->state == SMD_SS_OPENED);
-}
-
-/* provide a pointer and length to readable data in the fifo */
-static unsigned ch_read_buffer(struct smd_channel *ch, void **ptr)
-{
-       unsigned head = ch->recv->head;
-       unsigned tail = ch->recv->tail;
-       *ptr = (void *) (ch->recv_data + tail);
-
-       if (tail <= head)
-               return head - tail;
-       else
-               return ch->fifo_size - tail;
-}
-
-/* advance the fifo read pointer after data from ch_read_buffer is consumed */
-static void ch_read_done(struct smd_channel *ch, unsigned count)
-{
-       BUG_ON(count > smd_stream_read_avail(ch));
-       ch->recv->tail = (ch->recv->tail + count) & ch->fifo_mask;
-       ch->send->fTAIL = 1;
-}
-
-/* basic read interface to ch_read_{buffer,done} used
- * by smd_*_read() and update_packet_state()
- * will read-and-discard if the _data pointer is null
- */
-static int ch_read(struct smd_channel *ch, void *_data, int len)
-{
-       void *ptr;
-       unsigned n;
-       unsigned char *data = _data;
-       int orig_len = len;
-
-       while (len > 0) {
-               n = ch_read_buffer(ch, &ptr);
-               if (n == 0)
-                       break;
-
-               if (n > len)
-                       n = len;
-               if (_data)
-                       memcpy(data, ptr, n);
-
-               data += n;
-               len -= n;
-               ch_read_done(ch, n);
-       }
-
-       return orig_len - len;
-}
-
-static void update_stream_state(struct smd_channel *ch)
-{
-       /* streams have no special state requiring updating */
-}
-
-static void update_packet_state(struct smd_channel *ch)
-{
-       unsigned hdr[5];
-       int r;
-
-       /* can't do anything if we're in the middle of a packet */
-       if (ch->current_packet != 0)
-               return;
-
-       /* don't bother unless we can get the full header */
-       if (smd_stream_read_avail(ch) < SMD_HEADER_SIZE)
-               return;
-
-       r = ch_read(ch, hdr, SMD_HEADER_SIZE);
-       BUG_ON(r != SMD_HEADER_SIZE);
-
-       ch->current_packet = hdr[0];
-}
-
-/* provide a pointer and length to next free space in the fifo */
-static unsigned ch_write_buffer(struct smd_channel *ch, void **ptr)
-{
-       unsigned head = ch->send->head;
-       unsigned tail = ch->send->tail;
-       *ptr = (void *) (ch->send_data + head);
-
-       if (head < tail) {
-               return tail - head - 1;
-       } else {
-               if (tail == 0)
-                       return ch->fifo_size - head - 1;
-               else
-                       return ch->fifo_size - head;
-       }
-}
-
-/* advace the fifo write pointer after freespace
- * from ch_write_buffer is filled
- */
-static void ch_write_done(struct smd_channel *ch, unsigned count)
-{
-       BUG_ON(count > smd_stream_write_avail(ch));
-       ch->send->head = (ch->send->head + count) & ch->fifo_mask;
-       ch->send->fHEAD = 1;
-}
-
-static void ch_set_state(struct smd_channel *ch, unsigned n)
-{
-       if (n == SMD_SS_OPENED) {
-               ch->send->fDSR = 1;
-               ch->send->fCTS = 1;
-               ch->send->fCD = 1;
-       } else {
-               ch->send->fDSR = 0;
-               ch->send->fCTS = 0;
-               ch->send->fCD = 0;
-       }
-       ch->send->state = n;
-       ch->send->fSTATE = 1;
-       ch->notify_other_cpu();
-}
-
-static void do_smd_probe(void)
-{
-       struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE;
-       if (shared->heap_info.free_offset != last_heap_free) {
-               last_heap_free = shared->heap_info.free_offset;
-               schedule_work(&probe_work);
-       }
-}
-
-static void smd_state_change(struct smd_channel *ch,
-                            unsigned last, unsigned next)
-{
-       ch->last_state = next;
-
-       pr_debug("ch %d %d -> %d\n", ch->n, last, next);
-
-       switch (next) {
-       case SMD_SS_OPENING:
-               ch->recv->tail = 0;
-       case SMD_SS_OPENED:
-               if (ch->send->state != SMD_SS_OPENED)
-                       ch_set_state(ch, SMD_SS_OPENED);
-               ch->notify(ch->priv, SMD_EVENT_OPEN);
-               break;
-       case SMD_SS_FLUSHING:
-       case SMD_SS_RESET:
-               /* we should force them to close? */
-       default:
-               ch->notify(ch->priv, SMD_EVENT_CLOSE);
-       }
-}
-
-static void handle_smd_irq(struct list_head *list, void (*notify)(void))
-{
-       unsigned long flags;
-       struct smd_channel *ch;
-       int do_notify = 0;
-       unsigned ch_flags;
-       unsigned tmp;
-
-       spin_lock_irqsave(&smd_lock, flags);
-       list_for_each_entry(ch, list, ch_list) {
-               ch_flags = 0;
-               if (ch_is_open(ch)) {
-                       if (ch->recv->fHEAD) {
-                               ch->recv->fHEAD = 0;
-                               ch_flags |= 1;
-                               do_notify |= 1;
-                       }
-                       if (ch->recv->fTAIL) {
-                               ch->recv->fTAIL = 0;
-                               ch_flags |= 2;
-                               do_notify |= 1;
-                       }
-                       if (ch->recv->fSTATE) {
-                               ch->recv->fSTATE = 0;
-                               ch_flags |= 4;
-                               do_notify |= 1;
-                       }
-               }
-               tmp = ch->recv->state;
-               if (tmp != ch->last_state)
-                       smd_state_change(ch, ch->last_state, tmp);
-               if (ch_flags) {
-                       ch->update_state(ch);
-                       ch->notify(ch->priv, SMD_EVENT_DATA);
-               }
-       }
-       if (do_notify)
-               notify();
-       spin_unlock_irqrestore(&smd_lock, flags);
-       do_smd_probe();
-}
-
-static irqreturn_t smd_modem_irq_handler(int irq, void *data)
-{
-       handle_smd_irq(&smd_ch_list_modem, notify_modem_smd);
-       return IRQ_HANDLED;
-}
-
-#if defined(CONFIG_QDSP6)
-static irqreturn_t smd_dsp_irq_handler(int irq, void *data)
-{
-       handle_smd_irq(&smd_ch_list_dsp, notify_dsp_smd);
-       return IRQ_HANDLED;
-}
-#endif
-
-static void smd_fake_irq_handler(unsigned long arg)
-{
-       handle_smd_irq(&smd_ch_list_modem, notify_modem_smd);
-       handle_smd_irq(&smd_ch_list_dsp, notify_dsp_smd);
-}
-
-static DECLARE_TASKLET(smd_fake_irq_tasklet, smd_fake_irq_handler, 0);
-
-static inline int smd_need_int(struct smd_channel *ch)
-{
-       if (ch_is_open(ch)) {
-               if (ch->recv->fHEAD || ch->recv->fTAIL || ch->recv->fSTATE)
-                       return 1;
-               if (ch->recv->state != ch->last_state)
-                       return 1;
-       }
-       return 0;
-}
-
-void smd_sleep_exit(void)
-{
-       unsigned long flags;
-       struct smd_channel *ch;
-       int need_int = 0;
-
-       spin_lock_irqsave(&smd_lock, flags);
-       list_for_each_entry(ch, &smd_ch_list_modem, ch_list) {
-               if (smd_need_int(ch)) {
-                       need_int = 1;
-                       break;
-               }
-       }
-       list_for_each_entry(ch, &smd_ch_list_dsp, ch_list) {
-               if (smd_need_int(ch)) {
-                       need_int = 1;
-                       break;
-               }
-       }
-       spin_unlock_irqrestore(&smd_lock, flags);
-       do_smd_probe();
-
-       if (need_int) {
-               if (msm_smd_debug_mask & MSM_SMD_DEBUG)
-                       pr_info("smd_sleep_exit need interrupt\n");
-               tasklet_schedule(&smd_fake_irq_tasklet);
-       }
-}
-
-
-void smd_kick(smd_channel_t *ch)
-{
-       unsigned long flags;
-       unsigned tmp;
-
-       spin_lock_irqsave(&smd_lock, flags);
-       ch->update_state(ch);
-       tmp = ch->recv->state;
-       if (tmp != ch->last_state) {
-               ch->last_state = tmp;
-               if (tmp == SMD_SS_OPENED)
-                       ch->notify(ch->priv, SMD_EVENT_OPEN);
-               else
-                       ch->notify(ch->priv, SMD_EVENT_CLOSE);
-       }
-       ch->notify(ch->priv, SMD_EVENT_DATA);
-       ch->notify_other_cpu();
-       spin_unlock_irqrestore(&smd_lock, flags);
-}
-
-static int smd_is_packet(int chn, unsigned type)
-{
-       type &= SMD_KIND_MASK;
-       if (type == SMD_KIND_PACKET)
-               return 1;
-       if (type == SMD_KIND_STREAM)
-               return 0;
-
-       /* older AMSS reports SMD_KIND_UNKNOWN always */
-       if ((chn > 4) || (chn == 1))
-               return 1;
-       else
-               return 0;
-}
-
-static int smd_stream_write(smd_channel_t *ch, const void *_data, int len)
-{
-       void *ptr;
-       const unsigned char *buf = _data;
-       unsigned xfer;
-       int orig_len = len;
-
-       if (len < 0)
-               return -EINVAL;
-
-       while ((xfer = ch_write_buffer(ch, &ptr)) != 0) {
-               if (!ch_is_open(ch))
-                       break;
-               if (xfer > len)
-                       xfer = len;
-               memcpy(ptr, buf, xfer);
-               ch_write_done(ch, xfer);
-               len -= xfer;
-               buf += xfer;
-               if (len == 0)
-                       break;
-       }
-
-       ch->notify_other_cpu();
-
-       return orig_len - len;
-}
-
-static int smd_packet_write(smd_channel_t *ch, const void *_data, int len)
-{
-       unsigned hdr[5];
-
-       if (len < 0)
-               return -EINVAL;
-
-       if (smd_stream_write_avail(ch) < (len + SMD_HEADER_SIZE))
-               return -ENOMEM;
-
-       hdr[0] = len;
-       hdr[1] = hdr[2] = hdr[3] = hdr[4] = 0;
-
-       smd_stream_write(ch, hdr, sizeof(hdr));
-       smd_stream_write(ch, _data, len);
-
-       return len;
-}
-
-static int smd_stream_read(smd_channel_t *ch, void *data, int len)
-{
-       int r;
-
-       if (len < 0)
-               return -EINVAL;
-
-       r = ch_read(ch, data, len);
-       if (r > 0)
-               ch->notify_other_cpu();
-
-       return r;
-}
-
-static int smd_packet_read(smd_channel_t *ch, void *data, int len)
-{
-       unsigned long flags;
-       int r;
-
-       if (len < 0)
-               return -EINVAL;
-
-       if (len > ch->current_packet)
-               len = ch->current_packet;
-
-       r = ch_read(ch, data, len);
-       if (r > 0)
-               ch->notify_other_cpu();
-
-       spin_lock_irqsave(&smd_lock, flags);
-       ch->current_packet -= r;
-       update_packet_state(ch);
-       spin_unlock_irqrestore(&smd_lock, flags);
-
-       return r;
-}
-
-static int smd_alloc_channel(const char *name, uint32_t cid, uint32_t type)
-{
-       struct smd_channel *ch;
-
-       ch = kzalloc(sizeof(struct smd_channel), GFP_KERNEL);
-       if (ch == 0) {
-               pr_err("smd_alloc_channel() out of memory\n");
-               return -1;
-       }
-       ch->n = cid;
-
-       if (_smd_alloc_channel(ch)) {
-               kfree(ch);
-               return -1;
-       }
-
-       ch->fifo_mask = ch->fifo_size - 1;
-       ch->type = type;
-
-       if ((type & SMD_TYPE_MASK) == SMD_TYPE_APPS_MODEM)
-               ch->notify_other_cpu = notify_modem_smd;
-       else
-               ch->notify_other_cpu = notify_dsp_smd;
-
-       if (smd_is_packet(cid, type)) {
-               ch->read = smd_packet_read;
-               ch->write = smd_packet_write;
-               ch->read_avail = smd_packet_read_avail;
-               ch->write_avail = smd_packet_write_avail;
-               ch->update_state = update_packet_state;
-       } else {
-               ch->read = smd_stream_read;
-               ch->write = smd_stream_write;
-               ch->read_avail = smd_stream_read_avail;
-               ch->write_avail = smd_stream_write_avail;
-               ch->update_state = update_stream_state;
-       }
-
-       if ((type & 0xff) == 0)
-               memcpy(ch->name, "SMD_", 4);
-       else
-               memcpy(ch->name, "DSP_", 4);
-       memcpy(ch->name + 4, name, 20);
-       ch->name[23] = 0;
-       ch->pdev.name = ch->name;
-       ch->pdev.id = -1;
-
-       pr_debug("smd_alloc_channel() cid=%02d size=%05d '%s'\n",
-               ch->n, ch->fifo_size, ch->name);
-
-       mutex_lock(&smd_creation_mutex);
-       list_add(&ch->ch_list, &smd_ch_closed_list);
-       mutex_unlock(&smd_creation_mutex);
-
-       platform_device_register(&ch->pdev);
-       return 0;
-}
-
-static void smd_channel_probe_worker(struct work_struct *work)
-{
-       struct smd_alloc_elm *shared;
-       unsigned ctype;
-       unsigned type;
-       unsigned n;
-
-       shared = smem_find(ID_CH_ALLOC_TBL, sizeof(*shared) * 64);
-       if (!shared) {
-               pr_err("cannot find allocation table\n");
-               return;
-       }
-       for (n = 0; n < 64; n++) {
-               if (smd_ch_allocated[n])
-                       continue;
-               if (!shared[n].ref_count)
-                       continue;
-               if (!shared[n].name[0])
-                       continue;
-               ctype = shared[n].ctype;
-               type = ctype & SMD_TYPE_MASK;
-
-               /* DAL channels are stream but neither the modem,
-                * nor the DSP correctly indicate this.  Fixup manually.
-                */
-               if (!memcmp(shared[n].name, "DAL", 3))
-                       ctype = (ctype & (~SMD_KIND_MASK)) | SMD_KIND_STREAM;
-
-               type = shared[n].ctype & SMD_TYPE_MASK;
-               if ((type == SMD_TYPE_APPS_MODEM) ||
-                   (type == SMD_TYPE_APPS_DSP))
-                       if (!smd_alloc_channel(shared[n].name, shared[n].cid, ctype))
-                               smd_ch_allocated[n] = 1;
-       }
-}
-
-static void do_nothing_notify(void *priv, unsigned flags)
-{
-}
-
-struct smd_channel *smd_get_channel(const char *name)
-{
-       struct smd_channel *ch;
-
-       mutex_lock(&smd_creation_mutex);
-       list_for_each_entry(ch, &smd_ch_closed_list, ch_list) {
-               if (!strcmp(name, ch->name)) {
-                       list_del(&ch->ch_list);
-                       mutex_unlock(&smd_creation_mutex);
-                       return ch;
-               }
-       }
-       mutex_unlock(&smd_creation_mutex);
-
-       return NULL;
-}
-
-int smd_open(const char *name, smd_channel_t **_ch,
-            void *priv, void (*notify)(void *, unsigned))
-{
-       struct smd_channel *ch;
-       unsigned long flags;
-
-       if (smd_initialized == 0) {
-               pr_info("smd_open() before smd_init()\n");
-               return -ENODEV;
-       }
-
-       ch = smd_get_channel(name);
-       if (!ch)
-               return -ENODEV;
-
-       if (notify == 0)
-               notify = do_nothing_notify;
-
-       ch->notify = notify;
-       ch->current_packet = 0;
-       ch->last_state = SMD_SS_CLOSED;
-       ch->priv = priv;
-
-       *_ch = ch;
-
-       spin_lock_irqsave(&smd_lock, flags);
-
-       if ((ch->type & SMD_TYPE_MASK) == SMD_TYPE_APPS_MODEM)
-               list_add(&ch->ch_list, &smd_ch_list_modem);
-       else
-               list_add(&ch->ch_list, &smd_ch_list_dsp);
-
-       /* If the remote side is CLOSING, we need to get it to
-        * move to OPENING (which we'll do by moving from CLOSED to
-        * OPENING) and then get it to move from OPENING to
-        * OPENED (by doing the same state change ourselves).
-        *
-        * Otherwise, it should be OPENING and we can move directly
-        * to OPENED so that it will follow.
-        */
-       if (ch->recv->state == SMD_SS_CLOSING) {
-               ch->send->head = 0;
-               ch_set_state(ch, SMD_SS_OPENING);
-       } else {
-               ch_set_state(ch, SMD_SS_OPENED);
-       }
-       spin_unlock_irqrestore(&smd_lock, flags);
-       smd_kick(ch);
-
-       return 0;
-}
-
-int smd_close(smd_channel_t *ch)
-{
-       unsigned long flags;
-
-       if (ch == 0)
-               return -1;
-
-       spin_lock_irqsave(&smd_lock, flags);
-       ch->notify = do_nothing_notify;
-       list_del(&ch->ch_list);
-       ch_set_state(ch, SMD_SS_CLOSED);
-       spin_unlock_irqrestore(&smd_lock, flags);
-
-       mutex_lock(&smd_creation_mutex);
-       list_add(&ch->ch_list, &smd_ch_closed_list);
-       mutex_unlock(&smd_creation_mutex);
-
-       return 0;
-}
-
-int smd_read(smd_channel_t *ch, void *data, int len)
-{
-       return ch->read(ch, data, len);
-}
-
-int smd_write(smd_channel_t *ch, const void *data, int len)
-{
-       return ch->write(ch, data, len);
-}
-
-int smd_write_atomic(smd_channel_t *ch, const void *data, int len)
-{
-       unsigned long flags;
-       int res;
-       spin_lock_irqsave(&smd_lock, flags);
-       res = ch->write(ch, data, len);
-       spin_unlock_irqrestore(&smd_lock, flags);
-       return res;
-}
-
-int smd_read_avail(smd_channel_t *ch)
-{
-       return ch->read_avail(ch);
-}
-
-int smd_write_avail(smd_channel_t *ch)
-{
-       return ch->write_avail(ch);
-}
-
-int smd_wait_until_readable(smd_channel_t *ch, int bytes)
-{
-       return -1;
-}
-
-int smd_wait_until_writable(smd_channel_t *ch, int bytes)
-{
-       return -1;
-}
-
-int smd_cur_packet_size(smd_channel_t *ch)
-{
-       return ch->current_packet;
-}
-
-
-/* ------------------------------------------------------------------------- */
-
-void *smem_alloc(unsigned id, unsigned size)
-{
-       return smem_find(id, size);
-}
-
-void __iomem *smem_item(unsigned id, unsigned *size)
-{
-       struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE;
-       struct smem_heap_entry *toc = shared->heap_toc;
-
-       if (id >= SMEM_NUM_ITEMS)
-               return NULL;
-
-       if (toc[id].allocated) {
-               *size = toc[id].size;
-               return (MSM_SHARED_RAM_BASE + toc[id].offset);
-       } else {
-               *size = 0;
-       }
-
-       return NULL;
-}
-
-void *smem_find(unsigned id, unsigned size_in)
-{
-       unsigned size;
-       void *ptr;
-
-       ptr = smem_item(id, &size);
-       if (!ptr)
-               return 0;
-
-       size_in = ALIGN(size_in, 8);
-       if (size_in != size) {
-               pr_err("smem_find(%d, %d): wrong size %d\n",
-                      id, size_in, size);
-               return 0;
-       }
-
-       return ptr;
-}
-
-static irqreturn_t smsm_irq_handler(int irq, void *data)
-{
-       unsigned long flags;
-       unsigned apps, modm;
-
-       spin_lock_irqsave(&smem_lock, flags);
-
-       apps = raw_smsm_get_state(SMSM_STATE_APPS);
-       modm = raw_smsm_get_state(SMSM_STATE_MODEM);
-
-       if (msm_smd_debug_mask & MSM_SMSM_DEBUG)
-               pr_info("<SM %08x %08x>\n", apps, modm);
-       if (modm & SMSM_RESET)
-               handle_modem_crash();
-
-       do_smd_probe();
-
-       spin_unlock_irqrestore(&smem_lock, flags);
-       return IRQ_HANDLED;
-}
-
-int smsm_change_state(enum smsm_state_item item,
-                     uint32_t clear_mask, uint32_t set_mask)
-{
-       void __iomem *addr = smd_info.state + item * 4;
-       unsigned long flags;
-       unsigned state;
-
-       if (!smd_info.ready)
-               return -EIO;
-
-       spin_lock_irqsave(&smem_lock, flags);
-
-       if (raw_smsm_get_state(SMSM_STATE_MODEM) & SMSM_RESET)
-               handle_modem_crash();
-
-       state = (readl(addr) & ~clear_mask) | set_mask;
-       writel(state, addr);
-
-       if (msm_smd_debug_mask & MSM_SMSM_DEBUG)
-               pr_info("smsm_change_state %d %x\n", item, state);
-       notify_other_smsm();
-
-       spin_unlock_irqrestore(&smem_lock, flags);
-
-       return 0;
-}
-
-uint32_t smsm_get_state(enum smsm_state_item item)
-{
-       unsigned long flags;
-       uint32_t rv;
-
-       spin_lock_irqsave(&smem_lock, flags);
-
-       rv = readl(smd_info.state + item * 4);
-
-       if (item == SMSM_STATE_MODEM && (rv & SMSM_RESET))
-               handle_modem_crash();
-
-       spin_unlock_irqrestore(&smem_lock, flags);
-
-       return rv;
-}
-
-#ifdef CONFIG_ARCH_MSM_SCORPION
-
-int smsm_set_sleep_duration(uint32_t delay)
-{
-       struct msm_dem_slave_data *ptr;
-
-       ptr = smem_find(SMEM_APPS_DEM_SLAVE_DATA, sizeof(*ptr));
-       if (ptr == NULL) {
-               pr_err("smsm_set_sleep_duration <SM NO APPS_DEM_SLAVE_DATA>\n");
-               return -EIO;
-       }
-       if (msm_smd_debug_mask & MSM_SMSM_DEBUG)
-               pr_info("smsm_set_sleep_duration %d -> %d\n",
-                      ptr->sleep_time, delay);
-       ptr->sleep_time = delay;
-       return 0;
-}
-
-#else
-
-int smsm_set_sleep_duration(uint32_t delay)
-{
-       uint32_t *ptr;
-
-       ptr = smem_find(SMEM_SMSM_SLEEP_DELAY, sizeof(*ptr));
-       if (ptr == NULL) {
-               pr_err("smsm_set_sleep_duration <SM NO SLEEP_DELAY>\n");
-               return -EIO;
-       }
-       if (msm_smd_debug_mask & MSM_SMSM_DEBUG)
-               pr_info("smsm_set_sleep_duration %d -> %d\n",
-                      *ptr, delay);
-       *ptr = delay;
-       return 0;
-}
-
-#endif
-
-int smd_core_init(void)
-{
-       int r;
-
-       /* wait for essential items to be initialized */
-       for (;;) {
-               unsigned size;
-               void __iomem *state;
-               state = smem_item(SMEM_SMSM_SHARED_STATE, &size);
-               if (size == SMSM_V1_SIZE || size == SMSM_V2_SIZE) {
-                       smd_info.state = state;
-                       break;
-               }
-       }
-
-       smd_info.ready = 1;
-
-       r = request_irq(INT_A9_M2A_0, smd_modem_irq_handler,
-                       IRQF_TRIGGER_RISING, "smd_dev", 0);
-       if (r < 0)
-               return r;
-       r = enable_irq_wake(INT_A9_M2A_0);
-       if (r < 0)
-               pr_err("smd_core_init: enable_irq_wake failed for A9_M2A_0\n");
-
-       r = request_irq(INT_A9_M2A_5, smsm_irq_handler,
-                       IRQF_TRIGGER_RISING, "smsm_dev", 0);
-       if (r < 0) {
-               free_irq(INT_A9_M2A_0, 0);
-               return r;
-       }
-       r = enable_irq_wake(INT_A9_M2A_5);
-       if (r < 0)
-               pr_err("smd_core_init: enable_irq_wake failed for A9_M2A_5\n");
-
-#if defined(CONFIG_QDSP6)
-       r = request_irq(INT_ADSP_A11, smd_dsp_irq_handler,
-                       IRQF_TRIGGER_RISING, "smd_dsp", 0);
-       if (r < 0) {
-               free_irq(INT_A9_M2A_0, 0);
-               free_irq(INT_A9_M2A_5, 0);
-               return r;
-       }
-#endif
-
-       /* check for any SMD channels that may already exist */
-       do_smd_probe();
-
-       /* indicate that we're up and running */
-       smsm_change_state(SMSM_STATE_APPS,
-                         ~0, SMSM_INIT | SMSM_SMDINIT | SMSM_RPCINIT | SMSM_RUN);
-#ifdef CONFIG_ARCH_MSM_SCORPION
-       smsm_change_state(SMSM_STATE_APPS_DEM, ~0, 0);
-#endif
-
-       return 0;
-}
-
-static int msm_smd_probe(struct platform_device *pdev)
-{
-       /*
-        * If we haven't waited for the ARM9 to boot up till now,
-        * then we need to wait here. Otherwise this should just
-        * return immediately.
-        */
-       proc_comm_boot_wait();
-
-       INIT_WORK(&probe_work, smd_channel_probe_worker);
-
-       if (smd_core_init()) {
-               pr_err("smd_core_init() failed\n");
-               return -1;
-       }
-
-       do_smd_probe();
-
-       msm_check_for_modem_crash = check_for_modem_crash;
-
-       msm_init_last_radio_log(THIS_MODULE);
-
-       smd_initialized = 1;
-
-       return 0;
-}
-
-static struct platform_driver msm_smd_driver = {
-       .probe = msm_smd_probe,
-       .driver = {
-               .name = MODULE_NAME,
-       },
-};
-
-static int __init msm_smd_init(void)
-{
-       return platform_driver_register(&msm_smd_driver);
-}
-
-module_init(msm_smd_init);
-
-MODULE_DESCRIPTION("MSM Shared Memory Core");
-MODULE_AUTHOR("Brian Swetland <swetland@google.com>");
-MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-msm/smd_debug.c b/arch/arm/mach-msm/smd_debug.c
deleted file mode 100644 (file)
index 8056b3e..0000000
+++ /dev/null
@@ -1,311 +0,0 @@
-/* arch/arm/mach-msm/smd_debug.c
- *
- * Copyright (C) 2007 Google, Inc.
- * Author: Brian Swetland <swetland@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/debugfs.h>
-#include <linux/list.h>
-
-#include <mach/msm_iomap.h>
-
-#include "smd_private.h"
-
-#if defined(CONFIG_DEBUG_FS)
-
-static char *chstate(unsigned n)
-{
-       switch (n) {
-       case SMD_SS_CLOSED:
-               return "CLOSED";
-       case SMD_SS_OPENING:
-               return "OPENING";
-       case SMD_SS_OPENED:
-               return "OPENED";
-       case SMD_SS_FLUSHING:
-               return "FLUSHING";
-       case SMD_SS_CLOSING:
-               return "CLOSING";
-       case SMD_SS_RESET:
-               return "RESET";
-       case SMD_SS_RESET_OPENING:
-               return "ROPENING";
-       default:
-               return "UNKNOWN";
-       }
-}
-
-
-static int dump_ch(char *buf, int max, struct smd_channel *ch)
-{
-       volatile struct smd_half_channel *s = ch->send;
-       volatile struct smd_half_channel *r = ch->recv;
-
-       return scnprintf(
-               buf, max,
-               "ch%02d:"
-               " %8s(%05d/%05d) %c%c%c%c%c%c%c <->"
-               " %8s(%05d/%05d) %c%c%c%c%c%c%c '%s'\n", ch->n,
-               chstate(s->state), s->tail, s->head,
-               s->fDSR ? 'D' : 'd',
-               s->fCTS ? 'C' : 'c',
-               s->fCD ? 'C' : 'c',
-               s->fRI ? 'I' : 'i',
-               s->fHEAD ? 'W' : 'w',
-               s->fTAIL ? 'R' : 'r',
-               s->fSTATE ? 'S' : 's',
-               chstate(r->state), r->tail, r->head,
-               r->fDSR ? 'D' : 'd',
-               r->fCTS ? 'R' : 'r',
-               r->fCD ? 'C' : 'c',
-               r->fRI ? 'I' : 'i',
-               r->fHEAD ? 'W' : 'w',
-               r->fTAIL ? 'R' : 'r',
-               r->fSTATE ? 'S' : 's',
-               ch->name
-               );
-}
-
-static int debug_read_stat(char *buf, int max)
-{
-       char *msg;
-       int i = 0;
-
-       msg = smem_find(ID_DIAG_ERR_MSG, SZ_DIAG_ERR_MSG);
-
-       if (raw_smsm_get_state(SMSM_STATE_MODEM) & SMSM_RESET)
-               i += scnprintf(buf + i, max - i,
-                              "smsm: ARM9 HAS CRASHED\n");
-
-       i += scnprintf(buf + i, max - i, "smsm: a9: %08x a11: %08x\n",
-                      raw_smsm_get_state(SMSM_STATE_MODEM),
-                      raw_smsm_get_state(SMSM_STATE_APPS));
-#ifdef CONFIG_ARCH_MSM_SCORPION
-       i += scnprintf(buf + i, max - i, "smsm dem: apps: %08x modem: %08x "
-                      "qdsp6: %08x power: %08x time: %08x\n",
-                      raw_smsm_get_state(SMSM_STATE_APPS_DEM),
-                      raw_smsm_get_state(SMSM_STATE_MODEM_DEM),
-                      raw_smsm_get_state(SMSM_STATE_QDSP6_DEM),
-                      raw_smsm_get_state(SMSM_STATE_POWER_MASTER_DEM),
-                      raw_smsm_get_state(SMSM_STATE_TIME_MASTER_DEM));
-#endif
-       if (msg) {
-               msg[SZ_DIAG_ERR_MSG - 1] = 0;
-               i += scnprintf(buf + i, max - i, "diag: '%s'\n", msg);
-       }
-       return i;
-}
-
-static int debug_read_mem(char *buf, int max)
-{
-       unsigned n;
-       struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE;
-       struct smem_heap_entry *toc = shared->heap_toc;
-       int i = 0;
-
-       i += scnprintf(buf + i, max - i,
-                      "heap: init=%d free=%d remain=%d\n",
-                      shared->heap_info.initialized,
-                      shared->heap_info.free_offset,
-                      shared->heap_info.heap_remaining);
-
-       for (n = 0; n < SMEM_NUM_ITEMS; n++) {
-               if (toc[n].allocated == 0)
-                       continue;
-               i += scnprintf(buf + i, max - i,
-                              "%04d: offset %08x size %08x\n",
-                              n, toc[n].offset, toc[n].size);
-       }
-       return i;
-}
-
-static int debug_read_ch(char *buf, int max)
-{
-       struct smd_channel *ch;
-       unsigned long flags;
-       int i = 0;
-
-       spin_lock_irqsave(&smd_lock, flags);
-       list_for_each_entry(ch, &smd_ch_list_dsp, ch_list)
-               i += dump_ch(buf + i, max - i, ch);
-       list_for_each_entry(ch, &smd_ch_list_modem, ch_list)
-               i += dump_ch(buf + i, max - i, ch);
-       list_for_each_entry(ch, &smd_ch_closed_list, ch_list)
-               i += dump_ch(buf + i, max - i, ch);
-       spin_unlock_irqrestore(&smd_lock, flags);
-
-       return i;
-}
-
-static int debug_read_version(char *buf, int max)
-{
-       struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE;
-       unsigned version = shared->version[VERSION_MODEM];
-       return sprintf(buf, "%d.%d\n", version >> 16, version & 0xffff);
-}
-
-static int debug_read_build_id(char *buf, int max)
-{
-       unsigned size;
-       void *data;
-
-       data = smem_item(SMEM_HW_SW_BUILD_ID, &size);
-       if (!data)
-               return 0;
-
-       if (size >= max)
-               size = max;
-       memcpy(buf, data, size);
-
-       return size;
-}
-
-static int debug_read_alloc_tbl(char *buf, int max)
-{
-       struct smd_alloc_elm *shared;
-       int n, i = 0;
-
-       shared = smem_find(ID_CH_ALLOC_TBL, sizeof(*shared) * 64);
-
-       for (n = 0; n < 64; n++) {
-               if (shared[n].ref_count == 0)
-                       continue;
-               i += scnprintf(buf + i, max - i,
-                              "%03d: %-20s cid=%02d type=%03d "
-                              "kind=%02d ref_count=%d\n",
-                              n, shared[n].name, shared[n].cid,
-                              shared[n].ctype & 0xff,
-                              (shared[n].ctype >> 8) & 0xf,
-                              shared[n].ref_count);
-       }
-
-       return i;
-}
-
-#define DEBUG_BUFMAX 4096
-static char debug_buffer[DEBUG_BUFMAX];
-
-static ssize_t debug_read(struct file *file, char __user *buf,
-                         size_t count, loff_t *ppos)
-{
-       int (*fill)(char *buf, int max) = file->private_data;
-       int bsize = fill(debug_buffer, DEBUG_BUFMAX);
-       return simple_read_from_buffer(buf, count, ppos, debug_buffer, bsize);
-}
-
-static const struct file_operations debug_ops = {
-       .read = debug_read,
-       .open = simple_open,
-       .llseek = default_llseek,
-};
-
-static void debug_create(const char *name, umode_t mode,
-                        struct dentry *dent,
-                        int (*fill)(char *buf, int max))
-{
-       debugfs_create_file(name, mode, dent, fill, &debug_ops);
-}
-
-int __init smd_debugfs_init(void)
-{
-       struct dentry *dent;
-
-       dent = debugfs_create_dir("smd", 0);
-       if (IS_ERR(dent))
-               return 1;
-
-       debug_create("ch", 0444, dent, debug_read_ch);
-       debug_create("stat", 0444, dent, debug_read_stat);
-       debug_create("mem", 0444, dent, debug_read_mem);
-       debug_create("version", 0444, dent, debug_read_version);
-       debug_create("tbl", 0444, dent, debug_read_alloc_tbl);
-       debug_create("build", 0444, dent, debug_read_build_id);
-
-       return 0;
-}
-
-#endif
-
-
-#define MAX_NUM_SLEEP_CLIENTS          64
-#define MAX_SLEEP_NAME_LEN             8
-
-#define NUM_GPIO_INT_REGISTERS         6
-#define GPIO_SMEM_NUM_GROUPS           2
-#define GPIO_SMEM_MAX_PC_INTERRUPTS    8
-
-struct tramp_gpio_save {
-       unsigned int enable;
-       unsigned int detect;
-       unsigned int polarity;
-};
-
-struct tramp_gpio_smem {
-       uint16_t num_fired[GPIO_SMEM_NUM_GROUPS];
-       uint16_t fired[GPIO_SMEM_NUM_GROUPS][GPIO_SMEM_MAX_PC_INTERRUPTS];
-       uint32_t enabled[NUM_GPIO_INT_REGISTERS];
-       uint32_t detection[NUM_GPIO_INT_REGISTERS];
-       uint32_t polarity[NUM_GPIO_INT_REGISTERS];
-};
-
-
-void smsm_print_sleep_info(void)
-{
-       unsigned long flags;
-       uint32_t *ptr;
-#ifndef CONFIG_ARCH_MSM_SCORPION
-       struct tramp_gpio_smem *gpio;
-       struct smsm_interrupt_info *int_info;
-#endif
-
-
-       spin_lock_irqsave(&smem_lock, flags);
-
-       ptr = smem_alloc(SMEM_SMSM_SLEEP_DELAY, sizeof(*ptr));
-       if (ptr)
-               pr_info("SMEM_SMSM_SLEEP_DELAY: %x\n", *ptr);
-
-       ptr = smem_alloc(SMEM_SMSM_LIMIT_SLEEP, sizeof(*ptr));
-       if (ptr)
-               pr_info("SMEM_SMSM_LIMIT_SLEEP: %x\n", *ptr);
-
-       ptr = smem_alloc(SMEM_SLEEP_POWER_COLLAPSE_DISABLED, sizeof(*ptr));
-       if (ptr)
-               pr_info("SMEM_SLEEP_POWER_COLLAPSE_DISABLED: %x\n", *ptr);
-
-#ifndef CONFIG_ARCH_MSM_SCORPION
-       int_info = smem_alloc(SMEM_SMSM_INT_INFO, sizeof(*int_info));
-       if (int_info)
-               pr_info("SMEM_SMSM_INT_INFO %x %x %x\n",
-                       int_info->interrupt_mask,
-                       int_info->pending_interrupts,
-                       int_info->wakeup_reason);
-
-       gpio = smem_alloc(SMEM_GPIO_INT, sizeof(*gpio));
-       if (gpio) {
-               int i;
-               for (i = 0; i < NUM_GPIO_INT_REGISTERS; i++)
-                       pr_info("SMEM_GPIO_INT: %d: e %x d %x p %x\n",
-                               i, gpio->enabled[i], gpio->detection[i],
-                               gpio->polarity[i]);
-
-               for (i = 0; i < GPIO_SMEM_NUM_GROUPS; i++)
-                       pr_info("SMEM_GPIO_INT: %d: f %d: %d %d...\n",
-                               i, gpio->num_fired[i], gpio->fired[i][0],
-                               gpio->fired[i][1]);
-       }
-#else
-#endif
-       spin_unlock_irqrestore(&smem_lock, flags);
-}
-
diff --git a/arch/arm/mach-msm/smd_private.h b/arch/arm/mach-msm/smd_private.h
deleted file mode 100644 (file)
index 727bfe6..0000000
+++ /dev/null
@@ -1,403 +0,0 @@
-/* arch/arm/mach-msm/smd_private.h
- *
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2007 QUALCOMM Incorporated
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-#ifndef _ARCH_ARM_MACH_MSM_MSM_SMD_PRIVATE_H_
-#define _ARCH_ARM_MACH_MSM_MSM_SMD_PRIVATE_H_
-
-#include <linux/platform_device.h>
-#include <linux/spinlock.h>
-#include <linux/list.h>
-#include <linux/io.h>
-
-#include <mach/msm_iomap.h>
-
-struct smem_heap_info {
-       unsigned initialized;
-       unsigned free_offset;
-       unsigned heap_remaining;
-       unsigned reserved;
-};
-
-struct smem_heap_entry {
-       unsigned allocated;
-       unsigned offset;
-       unsigned size;
-       unsigned reserved;
-};
-
-struct smem_proc_comm {
-       unsigned command;
-       unsigned status;
-       unsigned data1;
-       unsigned data2;
-};
-
-#define PC_APPS  0
-#define PC_MODEM 1
-
-#define VERSION_SMD       0
-#define VERSION_QDSP6     4
-#define VERSION_APPS_SBL  6
-#define VERSION_MODEM_SBL 7
-#define VERSION_APPS      8
-#define VERSION_MODEM     9
-
-struct smem_shared {
-       struct smem_proc_comm proc_comm[4];
-       unsigned version[32];
-       struct smem_heap_info heap_info;
-       struct smem_heap_entry heap_toc[512];
-};
-
-#define SMSM_V1_SIZE           (sizeof(unsigned) * 8)
-#define SMSM_V2_SIZE           (sizeof(unsigned) * 4)
-
-#ifdef CONFIG_MSM_SMD_PKG3
-struct smsm_interrupt_info {
-       uint32_t interrupt_mask;
-       uint32_t pending_interrupts;
-       uint32_t wakeup_reason;
-};
-#else
-#define DEM_MAX_PORT_NAME_LEN (20)
-struct msm_dem_slave_data {
-       uint32_t sleep_time;
-       uint32_t interrupt_mask;
-       uint32_t resources_used;
-       uint32_t reserved1;
-
-       uint32_t wakeup_reason;
-       uint32_t pending_interrupts;
-       uint32_t rpc_prog;
-       uint32_t rpc_proc;
-       char     smd_port_name[DEM_MAX_PORT_NAME_LEN];
-       uint32_t reserved2;
-};
-#endif
-
-#define SZ_DIAG_ERR_MSG 0xC8
-#define ID_DIAG_ERR_MSG SMEM_DIAG_ERR_MESSAGE
-#define ID_SMD_CHANNELS SMEM_SMD_BASE_ID
-#define ID_SHARED_STATE SMEM_SMSM_SHARED_STATE
-#define ID_CH_ALLOC_TBL SMEM_CHANNEL_ALLOC_TBL
-
-#define SMSM_INIT              0x00000001
-#define SMSM_SMDINIT           0x00000008
-#define SMSM_RPCINIT           0x00000020
-#define SMSM_RESET             0x00000040
-#define SMSM_RSA               0x00000080
-#define SMSM_RUN               0x00000100
-#define SMSM_PWRC              0x00000200
-#define SMSM_TIMEWAIT          0x00000400
-#define SMSM_TIMEINIT          0x00000800
-#define SMSM_PWRC_EARLY_EXIT   0x00001000
-#define SMSM_WFPI              0x00002000
-#define SMSM_SLEEP             0x00004000
-#define SMSM_SLEEPEXIT         0x00008000
-#define SMSM_APPS_REBOOT       0x00020000
-#define SMSM_SYSTEM_POWER_DOWN 0x00040000
-#define SMSM_SYSTEM_REBOOT     0x00080000
-#define SMSM_SYSTEM_DOWNLOAD   0x00100000
-#define SMSM_PWRC_SUSPEND      0x00200000
-#define SMSM_APPS_SHUTDOWN     0x00400000
-#define SMSM_SMD_LOOPBACK      0x00800000
-#define SMSM_RUN_QUIET         0x01000000
-#define SMSM_MODEM_WAIT                0x02000000
-#define SMSM_MODEM_BREAK       0x04000000
-#define SMSM_MODEM_CONTINUE    0x08000000
-#define SMSM_UNKNOWN           0x80000000
-
-#define SMSM_WKUP_REASON_RPC   0x00000001
-#define SMSM_WKUP_REASON_INT   0x00000002
-#define SMSM_WKUP_REASON_GPIO  0x00000004
-#define SMSM_WKUP_REASON_TIMER 0x00000008
-#define SMSM_WKUP_REASON_ALARM 0x00000010
-#define SMSM_WKUP_REASON_RESET 0x00000020
-
-#ifdef CONFIG_ARCH_MSM7X00A
-enum smsm_state_item {
-       SMSM_STATE_APPS = 1,
-       SMSM_STATE_MODEM = 3,
-       SMSM_STATE_COUNT,
-};
-#else
-enum smsm_state_item {
-       SMSM_STATE_APPS,
-       SMSM_STATE_MODEM,
-       SMSM_STATE_HEXAGON,
-       SMSM_STATE_APPS_DEM,
-       SMSM_STATE_MODEM_DEM,
-       SMSM_STATE_QDSP6_DEM,
-       SMSM_STATE_POWER_MASTER_DEM,
-       SMSM_STATE_TIME_MASTER_DEM,
-       SMSM_STATE_COUNT,
-};
-#endif
-
-void *smem_alloc(unsigned id, unsigned size);
-int smsm_change_state(enum smsm_state_item item, uint32_t clear_mask, uint32_t set_mask);
-uint32_t smsm_get_state(enum smsm_state_item item);
-int smsm_set_sleep_duration(uint32_t delay);
-void smsm_print_sleep_info(void);
-
-#define SMEM_NUM_SMD_CHANNELS        64
-
-typedef enum {
-       /* fixed items */
-       SMEM_PROC_COMM = 0,
-       SMEM_HEAP_INFO,
-       SMEM_ALLOCATION_TABLE,
-       SMEM_VERSION_INFO,
-       SMEM_HW_RESET_DETECT,
-       SMEM_AARM_WARM_BOOT,
-       SMEM_DIAG_ERR_MESSAGE,
-       SMEM_SPINLOCK_ARRAY,
-       SMEM_MEMORY_BARRIER_LOCATION,
-
-       /* dynamic items */
-       SMEM_AARM_PARTITION_TABLE,
-       SMEM_AARM_BAD_BLOCK_TABLE,
-       SMEM_RESERVE_BAD_BLOCKS,
-       SMEM_WM_UUID,
-       SMEM_CHANNEL_ALLOC_TBL,
-       SMEM_SMD_BASE_ID,
-       SMEM_SMEM_LOG_IDX = SMEM_SMD_BASE_ID + SMEM_NUM_SMD_CHANNELS,
-       SMEM_SMEM_LOG_EVENTS,
-       SMEM_SMEM_STATIC_LOG_IDX,
-       SMEM_SMEM_STATIC_LOG_EVENTS,
-       SMEM_SMEM_SLOW_CLOCK_SYNC,
-       SMEM_SMEM_SLOW_CLOCK_VALUE,
-       SMEM_BIO_LED_BUF,
-       SMEM_SMSM_SHARED_STATE,
-       SMEM_SMSM_INT_INFO,
-       SMEM_SMSM_SLEEP_DELAY,
-       SMEM_SMSM_LIMIT_SLEEP,
-       SMEM_SLEEP_POWER_COLLAPSE_DISABLED,
-       SMEM_KEYPAD_KEYS_PRESSED,
-       SMEM_KEYPAD_STATE_UPDATED,
-       SMEM_KEYPAD_STATE_IDX,
-       SMEM_GPIO_INT,
-       SMEM_MDDI_LCD_IDX,
-       SMEM_MDDI_HOST_DRIVER_STATE,
-       SMEM_MDDI_LCD_DISP_STATE,
-       SMEM_LCD_CUR_PANEL,
-       SMEM_MARM_BOOT_SEGMENT_INFO,
-       SMEM_AARM_BOOT_SEGMENT_INFO,
-       SMEM_SLEEP_STATIC,
-       SMEM_SCORPION_FREQUENCY,
-       SMEM_SMD_PROFILES,
-       SMEM_TSSC_BUSY,
-       SMEM_HS_SUSPEND_FILTER_INFO,
-       SMEM_BATT_INFO,
-       SMEM_APPS_BOOT_MODE,
-       SMEM_VERSION_FIRST,
-       SMEM_VERSION_LAST = SMEM_VERSION_FIRST + 24,
-       SMEM_OSS_RRCASN1_BUF1,
-       SMEM_OSS_RRCASN1_BUF2,
-       SMEM_ID_VENDOR0,
-       SMEM_ID_VENDOR1,
-       SMEM_ID_VENDOR2,
-       SMEM_HW_SW_BUILD_ID,
-       SMEM_SMD_BLOCK_PORT_BASE_ID,
-       SMEM_SMD_BLOCK_PORT_PROC0_HEAP = SMEM_SMD_BLOCK_PORT_BASE_ID + SMEM_NUM_SMD_CHANNELS,
-       SMEM_SMD_BLOCK_PORT_PROC1_HEAP = SMEM_SMD_BLOCK_PORT_PROC0_HEAP + SMEM_NUM_SMD_CHANNELS,
-       SMEM_I2C_MUTEX = SMEM_SMD_BLOCK_PORT_PROC1_HEAP + SMEM_NUM_SMD_CHANNELS,
-       SMEM_SCLK_CONVERSION,
-       SMEM_SMD_SMSM_INTR_MUX,
-       SMEM_SMSM_CPU_INTR_MASK,
-       SMEM_APPS_DEM_SLAVE_DATA,
-       SMEM_QDSP6_DEM_SLAVE_DATA,
-       SMEM_CLKREGIM_BSP,
-       SMEM_CLKREGIM_SOURCES,
-       SMEM_SMD_FIFO_BASE_ID,
-       SMEM_USABLE_RAM_PARTITION_TABLE = SMEM_SMD_FIFO_BASE_ID + SMEM_NUM_SMD_CHANNELS,
-       SMEM_POWER_ON_STATUS_INFO,
-       SMEM_DAL_AREA,
-       SMEM_SMEM_LOG_POWER_IDX,
-       SMEM_SMEM_LOG_POWER_WRAP,
-       SMEM_SMEM_LOG_POWER_EVENTS,
-       SMEM_ERR_CRASH_LOG,
-       SMEM_ERR_F3_TRACE_LOG,
-       SMEM_NUM_ITEMS,
-} smem_mem_type;
-
-
-#define SMD_SS_CLOSED          0x00000000
-#define SMD_SS_OPENING         0x00000001
-#define SMD_SS_OPENED          0x00000002
-#define SMD_SS_FLUSHING                0x00000003
-#define SMD_SS_CLOSING         0x00000004
-#define SMD_SS_RESET           0x00000005
-#define SMD_SS_RESET_OPENING   0x00000006
-
-#define SMD_BUF_SIZE           8192
-#define SMD_CHANNELS           64
-
-#define SMD_HEADER_SIZE                20
-
-struct smd_alloc_elm {
-       char name[20];
-       uint32_t cid;
-       uint32_t ctype;
-       uint32_t ref_count;
-};
-
-struct smd_half_channel {
-       unsigned state;
-       unsigned char fDSR;
-       unsigned char fCTS;
-       unsigned char fCD;
-       unsigned char fRI;
-       unsigned char fHEAD;
-       unsigned char fTAIL;
-       unsigned char fSTATE;
-       unsigned char fUNUSED;
-       unsigned tail;
-       unsigned head;
-} __attribute__(( aligned(4), packed ));
-
-/* Only used on SMD package v3 on msm7201a */
-struct smd_shared_v1 {
-       struct smd_half_channel ch0;
-       unsigned char data0[SMD_BUF_SIZE];
-       struct smd_half_channel ch1;
-       unsigned char data1[SMD_BUF_SIZE];
-};
-
-/* Used on SMD package v4 */
-struct smd_shared_v2 {
-       struct smd_half_channel ch0;
-       struct smd_half_channel ch1;
-};
-
-struct smd_channel {
-       volatile struct smd_half_channel *send;
-       volatile struct smd_half_channel *recv;
-       unsigned char *send_data;
-       unsigned char *recv_data;
-
-       unsigned fifo_mask;
-       unsigned fifo_size;
-       unsigned current_packet;
-       unsigned n;
-
-       struct list_head ch_list;
-
-       void *priv;
-       void (*notify)(void *priv, unsigned flags);
-
-       int (*read)(struct smd_channel *ch, void *data, int len);
-       int (*write)(struct smd_channel *ch, const void *data, int len);
-       int (*read_avail)(struct smd_channel *ch);
-       int (*write_avail)(struct smd_channel *ch);
-
-       void (*update_state)(struct smd_channel *ch);
-       unsigned last_state;
-       void (*notify_other_cpu)(void);
-       unsigned type;
-
-       char name[32];
-       struct platform_device pdev;
-};
-
-#define SMD_TYPE_MASK          0x0FF
-#define SMD_TYPE_APPS_MODEM    0x000
-#define SMD_TYPE_APPS_DSP      0x001
-#define SMD_TYPE_MODEM_DSP     0x002
-
-#define SMD_KIND_MASK          0xF00
-#define SMD_KIND_UNKNOWN       0x000
-#define SMD_KIND_STREAM                0x100
-#define SMD_KIND_PACKET                0x200
-
-extern struct list_head smd_ch_closed_list;
-extern struct list_head smd_ch_list_modem;
-extern struct list_head smd_ch_list_dsp;
-
-extern spinlock_t smd_lock;
-extern spinlock_t smem_lock;
-
-void *smem_find(unsigned id, unsigned size);
-void *smem_item(unsigned id, unsigned *size);
-uint32_t raw_smsm_get_state(enum smsm_state_item item);
-
-extern void msm_init_last_radio_log(struct module *);
-
-#ifdef CONFIG_MSM_SMD_PKG3
-/*
- * This allocator assumes an SMD Package v3 which only exists on
- * MSM7x00 SoC's.
- */
-static inline int _smd_alloc_channel(struct smd_channel *ch)
-{
-       struct smd_shared_v1 *shared1;
-
-       shared1 = smem_alloc(ID_SMD_CHANNELS + ch->n, sizeof(*shared1));
-       if (!shared1) {
-               pr_err("smd_alloc_channel() cid %d does not exist\n", ch->n);
-               return -1;
-       }
-       ch->send = &shared1->ch0;
-       ch->recv = &shared1->ch1;
-       ch->send_data = shared1->data0;
-       ch->recv_data = shared1->data1;
-       ch->fifo_size = SMD_BUF_SIZE;
-       return 0;
-}
-#else
-/*
- * This allocator assumes an SMD Package v4, the most common
- * and the default.
- */
-static inline int _smd_alloc_channel(struct smd_channel *ch)
-{
-       struct smd_shared_v2 *shared2;
-       void *buffer;
-       unsigned buffer_sz;
-
-       shared2 = smem_alloc(SMEM_SMD_BASE_ID + ch->n, sizeof(*shared2));
-       buffer = smem_item(SMEM_SMD_FIFO_BASE_ID + ch->n, &buffer_sz);
-
-       if (!buffer)
-               return -1;
-
-       /* buffer must be a power-of-two size */
-       if (buffer_sz & (buffer_sz - 1))
-               return -1;
-
-       buffer_sz /= 2;
-       ch->send = &shared2->ch0;
-       ch->recv = &shared2->ch1;
-       ch->send_data = buffer;
-       ch->recv_data = buffer + buffer_sz;
-       ch->fifo_size = buffer_sz;
-       return 0;
-}
-#endif /* CONFIG_MSM_SMD_PKG3 */
-
-#if defined(CONFIG_ARCH_MSM7X30)
-static inline void msm_a2m_int(uint32_t irq)
-{
-       writel(1 << irq, MSM_GCC_BASE + 0x8);
-}
-#else
-static inline void msm_a2m_int(uint32_t irq)
-{
-       writel(1, MSM_CSR_BASE + 0x400 + (irq * 4));
-}
-#endif /* CONFIG_ARCH_MSM7X30 */
-
-
-#endif
diff --git a/arch/arm/mach-msm/vreg.c b/arch/arm/mach-msm/vreg.c
deleted file mode 100644 (file)
index bd66ed0..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-/* arch/arm/mach-msm/vreg.c
- *
- * Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2009, Code Aurora Forum. All rights reserved.
- * Author: Brian Swetland <swetland@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/debugfs.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <mach/vreg.h>
-
-#include "proc_comm.h"
-
-struct vreg {
-       const char *name;
-       unsigned id;
-       int status;
-       unsigned refcnt;
-};
-
-#define VREG(_name, _id, _status, _refcnt) \
-       { .name = _name, .id = _id, .status = _status, .refcnt = _refcnt }
-
-static struct vreg vregs[] = {
-       VREG("msma",    0, 0, 0),
-       VREG("msmp",    1, 0, 0),
-       VREG("msme1",   2, 0, 0),
-       VREG("msmc1",   3, 0, 0),
-       VREG("msmc2",   4, 0, 0),
-       VREG("gp3",     5, 0, 0),
-       VREG("msme2",   6, 0, 0),
-       VREG("gp4",     7, 0, 0),
-       VREG("gp1",     8, 0, 0),
-       VREG("tcxo",    9, 0, 0),
-       VREG("pa",      10, 0, 0),
-       VREG("rftx",    11, 0, 0),
-       VREG("rfrx1",   12, 0, 0),
-       VREG("rfrx2",   13, 0, 0),
-       VREG("synt",    14, 0, 0),
-       VREG("wlan",    15, 0, 0),
-       VREG("usb",     16, 0, 0),
-       VREG("boost",   17, 0, 0),
-       VREG("mmc",     18, 0, 0),
-       VREG("ruim",    19, 0, 0),
-       VREG("msmc0",   20, 0, 0),
-       VREG("gp2",     21, 0, 0),
-       VREG("gp5",     22, 0, 0),
-       VREG("gp6",     23, 0, 0),
-       VREG("rf",      24, 0, 0),
-       VREG("rf_vco",  26, 0, 0),
-       VREG("mpll",    27, 0, 0),
-       VREG("s2",      28, 0, 0),
-       VREG("s3",      29, 0, 0),
-       VREG("rfubm",   30, 0, 0),
-       VREG("ncp",     31, 0, 0),
-       VREG("gp7",     32, 0, 0),
-       VREG("gp8",     33, 0, 0),
-       VREG("gp9",     34, 0, 0),
-       VREG("gp10",    35, 0, 0),
-       VREG("gp11",    36, 0, 0),
-       VREG("gp12",    37, 0, 0),
-       VREG("gp13",    38, 0, 0),
-       VREG("gp14",    39, 0, 0),
-       VREG("gp15",    40, 0, 0),
-       VREG("gp16",    41, 0, 0),
-       VREG("gp17",    42, 0, 0),
-       VREG("s4",      43, 0, 0),
-       VREG("usb2",    44, 0, 0),
-       VREG("wlan2",   45, 0, 0),
-       VREG("xo_out",  46, 0, 0),
-       VREG("lvsw0",   47, 0, 0),
-       VREG("lvsw1",   48, 0, 0),
-};
-
-struct vreg *vreg_get(struct device *dev, const char *id)
-{
-       int n;
-       for (n = 0; n < ARRAY_SIZE(vregs); n++) {
-               if (!strcmp(vregs[n].name, id))
-                       return vregs + n;
-       }
-       return ERR_PTR(-ENOENT);
-}
-
-void vreg_put(struct vreg *vreg)
-{
-}
-
-int vreg_enable(struct vreg *vreg)
-{
-       unsigned id = vreg->id;
-       unsigned enable = 1;
-
-       if (vreg->refcnt == 0)
-               vreg->status = msm_proc_comm(PCOM_VREG_SWITCH, &id, &enable);
-
-       if ((vreg->refcnt < UINT_MAX) && (!vreg->status))
-               vreg->refcnt++;
-
-       return vreg->status;
-}
-
-int vreg_disable(struct vreg *vreg)
-{
-       unsigned id = vreg->id;
-       unsigned enable = 0;
-
-       if (!vreg->refcnt)
-               return 0;
-
-       if (vreg->refcnt == 1)
-               vreg->status = msm_proc_comm(PCOM_VREG_SWITCH, &id, &enable);
-
-       if (!vreg->status)
-               vreg->refcnt--;
-
-       return vreg->status;
-}
-
-int vreg_set_level(struct vreg *vreg, unsigned mv)
-{
-       unsigned id = vreg->id;
-
-       vreg->status = msm_proc_comm(PCOM_VREG_SET_LEVEL, &id, &mv);
-       return vreg->status;
-}
-
-#if defined(CONFIG_DEBUG_FS)
-
-static int vreg_debug_set(void *data, u64 val)
-{
-       struct vreg *vreg = data;
-       switch (val) {
-       case 0:
-               vreg_disable(vreg);
-               break;
-       case 1:
-               vreg_enable(vreg);
-               break;
-       default:
-               vreg_set_level(vreg, val);
-               break;
-       }
-       return 0;
-}
-
-static int vreg_debug_get(void *data, u64 *val)
-{
-       struct vreg *vreg = data;
-
-       if (!vreg->status)
-               *val = 0;
-       else
-               *val = 1;
-
-       return 0;
-}
-
-static int vreg_debug_count_set(void *data, u64 val)
-{
-       struct vreg *vreg = data;
-       if (val > UINT_MAX)
-               val = UINT_MAX;
-       vreg->refcnt = val;
-       return 0;
-}
-
-static int vreg_debug_count_get(void *data, u64 *val)
-{
-       struct vreg *vreg = data;
-
-       *val = vreg->refcnt;
-
-       return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(vreg_fops, vreg_debug_get, vreg_debug_set, "%llu\n");
-DEFINE_SIMPLE_ATTRIBUTE(vreg_count_fops, vreg_debug_count_get,
-                       vreg_debug_count_set, "%llu\n");
-
-static int __init vreg_debug_init(void)
-{
-       struct dentry *dent;
-       int n;
-       char name[32];
-       const char *refcnt_name = "_refcnt";
-
-       dent = debugfs_create_dir("vreg", 0);
-       if (IS_ERR(dent))
-               return 0;
-
-       for (n = 0; n < ARRAY_SIZE(vregs); n++) {
-               (void) debugfs_create_file(vregs[n].name, 0644,
-                                          dent, vregs + n, &vreg_fops);
-
-               strlcpy(name, vregs[n].name, sizeof(name));
-               strlcat(name, refcnt_name, sizeof(name));
-               (void) debugfs_create_file(name, 0644,
-                                          dent, vregs + n, &vreg_count_fops);
-       }
-
-       return 0;
-}
-
-device_initcall(vreg_debug_init);
-#endif
index c1e4567a5ab3ed8cfc10da7340beb624a7e0713c..97473168d6b65dfade5d92356a6ce73fe990c341 100644 (file)
@@ -64,6 +64,20 @@ config MACH_ARMADA_38X
          Say 'Y' here if you want your kernel to support boards based
          on the Marvell Armada 380/385 SoC with device tree.
 
+config MACH_ARMADA_39X
+       bool "Marvell Armada 39x boards" if ARCH_MULTI_V7
+       select ARM_GIC
+       select ARMADA_39X_CLK
+       select CACHE_L2X0
+       select HAVE_ARM_SCU
+       select HAVE_ARM_TWD if SMP
+       select HAVE_SMP
+       select MACH_MVEBU_V7
+       select PINCTRL_ARMADA_39X
+       help
+         Say 'Y' here if you want your kernel to support boards based
+         on the Marvell Armada 39x SoC with device tree.
+
 config MACH_ARMADA_XP
        bool "Marvell Armada XP boards" if ARCH_MULTI_V7
        select ARMADA_XP_CLK
index 89a139ed7d5bd3969f04d651d3cb29b122afb3e3..afee9083ad92bc6d16bb7b29ef5f86f811351847 100644 (file)
@@ -184,7 +184,7 @@ static void __init mvebu_dt_init(void)
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
-static const char * const armada_370_xp_dt_compat[] = {
+static const char * const armada_370_xp_dt_compat[] __initconst = {
        "marvell,armada-370-xp",
        NULL,
 };
@@ -205,7 +205,7 @@ DT_MACHINE_START(ARMADA_370_XP_DT, "Marvell Armada 370/XP (Device Tree)")
        .dt_compat      = armada_370_xp_dt_compat,
 MACHINE_END
 
-static const char * const armada_375_dt_compat[] = {
+static const char * const armada_375_dt_compat[] __initconst = {
        "marvell,armada375",
        NULL,
 };
@@ -219,7 +219,7 @@ DT_MACHINE_START(ARMADA_375_DT, "Marvell Armada 375 (Device Tree)")
        .dt_compat      = armada_375_dt_compat,
 MACHINE_END
 
-static const char * const armada_38x_dt_compat[] = {
+static const char * const armada_38x_dt_compat[] __initconst = {
        "marvell,armada380",
        "marvell,armada385",
        NULL,
@@ -232,3 +232,17 @@ DT_MACHINE_START(ARMADA_38X_DT, "Marvell Armada 380/385 (Device Tree)")
        .restart        = mvebu_restart,
        .dt_compat      = armada_38x_dt_compat,
 MACHINE_END
+
+static const char * const armada_39x_dt_compat[] __initconst = {
+       "marvell,armada390",
+       "marvell,armada398",
+       NULL,
+};
+
+DT_MACHINE_START(ARMADA_39X_DT, "Marvell Armada 39x (Device Tree)")
+       .l2c_aux_val    = 0,
+       .l2c_aux_mask   = ~0,
+       .init_irq       = mvebu_init_irq,
+       .restart        = mvebu_restart,
+       .dt_compat      = armada_39x_dt_compat,
+MACHINE_END
index b50464ec1130ff0b5961990d2684953c582d44cc..5a1741500a3000d6778fe5fb4d93cf26a2af11a2 100644 (file)
@@ -27,7 +27,7 @@ static void __init dove_init(void)
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
-static const char * const dove_dt_compat[] = {
+static const char * const dove_dt_compat[] __initconst = {
        "marvell,dove",
        NULL
 };
index 6b5310828eb2e7fa95fda207492ff0cc014803ab..925f75f54268ee5d4b5b9093ad48b6b1e290ad0a 100644 (file)
@@ -186,7 +186,7 @@ static void __init kirkwood_dt_init(void)
        of_platform_populate(NULL, of_default_bus_match_table, auxdata, NULL);
 }
 
-static const char * const kirkwood_dt_board_compat[] = {
+static const char * const kirkwood_dt_board_compat[] __initconst = {
        "marvell,kirkwood",
        NULL
 };
index 2ec1a42b432152dafadd1bedf793b17f036037d2..df0a9cc5da59ad2ce7a95e7d13dc8e2a82937069 100644 (file)
@@ -110,3 +110,5 @@ CPU_METHOD_OF_DECLARE(mvebu_armada_375_smp, "marvell,armada-375-smp",
                      &mvebu_cortex_a9_smp_ops);
 CPU_METHOD_OF_DECLARE(mvebu_armada_380_smp, "marvell,armada-380-smp",
                      &armada_38x_smp_ops);
+CPU_METHOD_OF_DECLARE(mvebu_armada_390_smp, "marvell,armada-390-smp",
+                     &armada_38x_smp_ops);
index 8b9f5e202ccf67d34681a2e1966fc424680a417f..4f4e22206ae5a913cbb5ebebb5b195f6d751028c 100644 (file)
@@ -415,6 +415,9 @@ static __init int armada_38x_cpuidle_init(void)
        void __iomem *mpsoc_base;
        u32 reg;
 
+       pr_warn("CPU idle is currently broken on Armada 38x: disabling");
+       return 0;
+
        np = of_find_compatible_node(NULL, NULL,
                                     "marvell,armada-380-coherency-fabric");
        if (!np)
@@ -476,6 +479,16 @@ static int __init mvebu_v7_cpu_pm_init(void)
                return 0;
        of_node_put(np);
 
+       /*
+        * Currently the CPU idle support for Armada 38x is broken, as
+        * the CPU hotplug uses some of the CPU idle functions it is
+        * broken too, so let's disable it
+        */
+       if (of_machine_is_compatible("marvell,armada380")) {
+               cpu_hotplug_disable();
+               pr_warn("CPU hotplug support is currently broken on Armada 38x: disabling");
+       }
+
        if (of_machine_is_compatible("marvell,armadaxp"))
                ret = armada_xp_cpuidle_init();
        else if (of_machine_is_compatible("marvell,armada370"))
@@ -489,7 +502,8 @@ static int __init mvebu_v7_cpu_pm_init(void)
                return ret;
 
        mvebu_v7_pmsu_enable_l2_powerdown_onidle();
-       platform_device_register(&mvebu_v7_cpuidle_device);
+       if (mvebu_v7_cpuidle_device.name)
+               platform_device_register(&mvebu_v7_cpuidle_device);
        cpu_pm_register_notifier(&mvebu_v7_cpu_pm_notifier);
 
        return 0;
index 34b4c0044961eefaf3dac6094a3a215152aae6bd..dd94567c36289c16303a267a86cde69cfba82e75 100644 (file)
@@ -71,13 +71,7 @@ static unsigned int mpui7xx_sleep_save[MPUI7XX_SLEEP_SAVE_SIZE];
 static unsigned int mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_SIZE];
 static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE];
 
-#ifndef CONFIG_OMAP_32K_TIMER
-
-static unsigned short enable_dyn_sleep = 0;
-
-#else
-
-static unsigned short enable_dyn_sleep = 1;
+static unsigned short enable_dyn_sleep;
 
 static ssize_t idle_show(struct kobject *kobj, struct kobj_attribute *attr,
                         char *buf)
@@ -90,8 +84,9 @@ static ssize_t idle_store(struct kobject *kobj, struct kobj_attribute *attr,
 {
        unsigned short value;
        if (sscanf(buf, "%hu", &value) != 1 ||
-           (value != 0 && value != 1)) {
-               printk(KERN_ERR "idle_sleep_store: Invalid value\n");
+           (value != 0 && value != 1) ||
+           (value != 0 && !IS_ENABLED(CONFIG_OMAP_32K_TIMER))) {
+               pr_err("idle_sleep_store: Invalid value\n");
                return -EINVAL;
        }
        enable_dyn_sleep = value;
@@ -101,7 +96,6 @@ static ssize_t idle_store(struct kobject *kobj, struct kobj_attribute *attr,
 static struct kobj_attribute sleep_while_idle_attr =
        __ATTR(sleep_while_idle, 0644, idle_show, idle_store);
 
-#endif
 
 static void (*omap_sram_suspend)(unsigned long r0, unsigned long r1) = NULL;
 
@@ -115,16 +109,11 @@ void omap1_pm_idle(void)
 {
        extern __u32 arm_idlect1_mask;
        __u32 use_idlect1 = arm_idlect1_mask;
-       int do_sleep = 0;
 
        local_fiq_disable();
 
 #if defined(CONFIG_OMAP_MPU_TIMER) && !defined(CONFIG_OMAP_DM_TIMER)
-#warning Enable 32kHz OS timer in order to allow sleep states in idle
        use_idlect1 = use_idlect1 & ~(1 << 9);
-#else
-       if (enable_dyn_sleep)
-               do_sleep = 1;
 #endif
 
 #ifdef CONFIG_OMAP_DM_TIMER
@@ -134,10 +123,12 @@ void omap1_pm_idle(void)
        if (omap_dma_running())
                use_idlect1 &= ~(1 << 6);
 
-       /* We should be able to remove the do_sleep variable and multiple
+       /*
+        * We should be able to remove the do_sleep variable and multiple
         * tests above as soon as drivers, timer and DMA code have been fixed.
-        * Even the sleep block count should become obsolete. */
-       if ((use_idlect1 != ~0) || !do_sleep) {
+        * Even the sleep block count should become obsolete.
+        */
+       if ((use_idlect1 != ~0) || !enable_dyn_sleep) {
 
                __u32 saved_idlect1 = omap_readl(ARM_IDLECT1);
                if (cpu_is_omap15xx())
@@ -635,15 +626,25 @@ static const struct platform_suspend_ops omap_pm_ops = {
 
 static int __init omap_pm_init(void)
 {
-
-#ifdef CONFIG_OMAP_32K_TIMER
-       int error;
-#endif
+       int error = 0;
 
        if (!cpu_class_is_omap1())
                return -ENODEV;
 
-       printk("Power Management for TI OMAP.\n");
+       pr_info("Power Management for TI OMAP.\n");
+
+       if (!IS_ENABLED(CONFIG_OMAP_32K_TIMER))
+               pr_info("OMAP1 PM: sleep states in idle disabled due to no 32KiHz timer\n");
+
+       if (!IS_ENABLED(CONFIG_OMAP_DM_TIMER))
+               pr_info("OMAP1 PM: sleep states in idle disabled due to no DMTIMER support\n");
+
+       if (IS_ENABLED(CONFIG_OMAP_32K_TIMER) &&
+           IS_ENABLED(CONFIG_OMAP_DM_TIMER)) {
+               /* OMAP16xx only */
+               pr_info("OMAP1 PM: sleep states in idle enabled\n");
+               enable_dyn_sleep = 1;
+       }
 
        /*
         * We copy the assembler sleep/wakeup routines to SRAM.
@@ -693,17 +694,15 @@ static int __init omap_pm_init(void)
        omap_pm_init_debugfs();
 #endif
 
-#ifdef CONFIG_OMAP_32K_TIMER
        error = sysfs_create_file(power_kobj, &sleep_while_idle_attr.attr);
        if (error)
                printk(KERN_ERR "sysfs_create_file failed: %d\n", error);
-#endif
 
        if (cpu_is_omap16xx()) {
                /* configure LOW_PWR pin */
                omap_cfg_reg(T20_1610_LOW_PWR);
        }
 
-       return 0;
+       return error;
 }
 __initcall(omap_pm_init);
index 2b8e47788062d7744bdffc6281714c07f6e0e38e..6468f15f060ca78f25b8664f5d95894b45268c03 100644 (file)
@@ -69,6 +69,7 @@ config SOC_DRA7XX
        select ARM_GIC
        select HAVE_ARM_ARCH_TIMER
        select IRQ_CROSSBAR
+       select ARM_ERRATA_798181 if SMP
 
 config ARCH_OMAP2PLUS
        bool
@@ -80,6 +81,7 @@ config ARCH_OMAP2PLUS
        select GENERIC_IRQ_CHIP
        select MACH_OMAP_GENERIC
        select MEMORY
+       select MFD_SYSCON
        select OMAP_DM_TIMER
        select OMAP_GPMC
        select PINCTRL
@@ -175,12 +177,6 @@ config MACH_OMAP3_BEAGLE
        default y
        select OMAP_PACKAGE_CBB
 
-config MACH_DEVKIT8000
-       bool "DEVKIT8000 board"
-       depends on ARCH_OMAP3
-       default y
-       select OMAP_PACKAGE_CUS
-
 config MACH_OMAP_LDP
        bool "OMAP3 LDP board"
        depends on ARCH_OMAP3
@@ -225,12 +221,6 @@ config MACH_OMAP3_PANDORA
        select OMAP_PACKAGE_CBB
        select REGULATOR_FIXED_VOLTAGE if REGULATOR
 
-config MACH_TOUCHBOOK
-       bool "OMAP3 Touch Book"
-       depends on ARCH_OMAP3
-       default y
-       select OMAP_PACKAGE_CBB
-
 config MACH_NOKIA_N810
        bool
 
@@ -260,12 +250,6 @@ config MACH_CM_T35
 config MACH_CM_T3730
        bool
 
-config MACH_SBC3530
-       bool "OMAP3 SBC STALKER board"
-       depends on ARCH_OMAP3
-       default y
-       select OMAP_PACKAGE_CUS
-
 config OMAP3_SDRC_AC_TIMING
        bool "Enable SDRC AC timing register changes"
        depends on ARCH_OMAP3
@@ -278,27 +262,6 @@ config OMAP3_SDRC_AC_TIMING
          wish to say no.  Selecting yes without understanding what is
          going on could result in system crashes;
 
-config OMAP4_ERRATA_I688
-       bool "OMAP4 errata: Async Bridge Corruption"
-       depends on (ARCH_OMAP4 || SOC_OMAP5) && !ARCH_MULTIPLATFORM
-       select ARCH_HAS_BARRIERS
-       help
-         If a data is stalled inside asynchronous bridge because of back
-         pressure, it may be accepted multiple times, creating pointer
-         misalignment that will corrupt next transfers on that data path
-         until next reset of the system (No recovery procedure once the
-         issue is hit, the path remains consistently broken). Async bridge
-         can be found on path between MPU to EMIF and MPU to L3 interconnect.
-         This situation can happen only when the idle is initiated by a
-         Master Request Disconnection (which is trigged by software when
-         executing WFI on CPU).
-         The work-around for this errata needs all the initiators connected
-         through async bridge must ensure that data path is properly drained
-         before issuing WFI. This condition will be met if one Strongly ordered
-         access is performed to the target right before executing the WFI.
-         In MPU case, L3 T2ASYNC FIFO and DDR T2ASYNC FIFO needs to be drained.
-         IO barrier ensure that there is no synchronisation loss on initiators
-         operating on both interconnect port simultaneously.
 endmenu
 
 endif
index b83f18fcec9b3c693944a6a2d0aafccf8e660a75..ec002bd4af771508e712bf7b93ec373d18323620 100644 (file)
@@ -243,7 +243,6 @@ obj-$(CONFIG_SOC_OMAP2420)          += msdi.o
 # Specific board support
 obj-$(CONFIG_MACH_OMAP_GENERIC)                += board-generic.o pdata-quirks.o
 obj-$(CONFIG_MACH_OMAP3_BEAGLE)                += board-omap3beagle.o
-obj-$(CONFIG_MACH_DEVKIT8000)          += board-devkit8000.o
 obj-$(CONFIG_MACH_OMAP_LDP)            += board-ldp.o
 obj-$(CONFIG_MACH_OMAP3530_LV_SOM)      += board-omap3logic.o
 obj-$(CONFIG_MACH_OMAP3_TORPEDO)        += board-omap3logic.o
@@ -254,9 +253,6 @@ obj-$(CONFIG_MACH_NOKIA_RX51)               += board-rx51.o sdram-nokia.o
 obj-$(CONFIG_MACH_NOKIA_RX51)          += board-rx51-peripherals.o
 obj-$(CONFIG_MACH_NOKIA_RX51)          += board-rx51-video.o
 obj-$(CONFIG_MACH_CM_T35)              += board-cm-t35.o
-obj-$(CONFIG_MACH_TOUCHBOOK)           += board-omap3touchbook.o
-
-obj-$(CONFIG_MACH_SBC3530)             += board-omap3stalker.o
 
 # Platform specific device init code
 
index 91738a14ecbe424ad31ee1140946f16f50c7c84b..b5dfbc1b1fc6f0bbcdabc713098ab1bd69bb32a4 100644 (file)
@@ -492,51 +492,36 @@ static struct twl4030_platform_data cm_t35_twldata = {
 #include <media/omap3isp.h>
 #include "devices.h"
 
-static struct i2c_board_info cm_t35_isp_i2c_boardinfo[] = {
+static struct isp_platform_subdev cm_t35_isp_subdevs[] = {
        {
-               I2C_BOARD_INFO("mt9t001", 0x5d),
-       },
-       {
-               I2C_BOARD_INFO("tvp5150", 0x5c),
-       },
-};
-
-static struct isp_subdev_i2c_board_info cm_t35_isp_primary_subdevs[] = {
-       {
-               .board_info = &cm_t35_isp_i2c_boardinfo[0],
-               .i2c_adapter_id = 3,
-       },
-       { NULL, 0, },
-};
-
-static struct isp_subdev_i2c_board_info cm_t35_isp_secondary_subdevs[] = {
-       {
-               .board_info = &cm_t35_isp_i2c_boardinfo[1],
+               .board_info = &(struct i2c_board_info){
+                       I2C_BOARD_INFO("mt9t001", 0x5d)
+               },
                .i2c_adapter_id = 3,
-       },
-       { NULL, 0, },
-};
-
-static struct isp_v4l2_subdevs_group cm_t35_isp_subdevs[] = {
-       {
-               .subdevs = cm_t35_isp_primary_subdevs,
-               .interface = ISP_INTERFACE_PARALLEL,
-               .bus = {
-                       .parallel = {
-                               .clk_pol = 1,
+               .bus = &(struct isp_bus_cfg){
+                       .interface = ISP_INTERFACE_PARALLEL,
+                       .bus = {
+                               .parallel = {
+                                       .clk_pol = 1,
+                               },
                        },
                },
        },
        {
-               .subdevs = cm_t35_isp_secondary_subdevs,
-               .interface = ISP_INTERFACE_PARALLEL,
-               .bus = {
-                       .parallel = {
-                               .clk_pol = 0,
+               .board_info = &(struct i2c_board_info){
+                       I2C_BOARD_INFO("tvp5150", 0x5c),
+               },
+               .i2c_adapter_id = 3,
+               .bus = &(struct isp_bus_cfg){
+                       .interface = ISP_INTERFACE_PARALLEL,
+                       .bus = {
+                               .parallel = {
+                                       .clk_pol = 0,
+                               },
                        },
                },
        },
-       { NULL, 0, },
+       { 0 },
 };
 
 static struct isp_platform_data cm_t35_isp_pdata = {
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
deleted file mode 100644 (file)
index d8e4f34..0000000
+++ /dev/null
@@ -1,654 +0,0 @@
-/*
- * board-devkit8000.c - TimLL Devkit8000
- *
- * Copyright (C) 2009 Kim Botherway
- * Copyright (C) 2010 Thomas Weber
- *
- * Modified from mach-omap2/board-omap3beagle.c
- *
- * Initial code: Syed Mohammed Khasim
- *
- * This program is free software; you can 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/init.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/leds.h>
-#include <linux/gpio.h>
-#include <linux/input.h>
-#include <linux/gpio_keys.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/nand.h>
-#include <linux/mmc/host.h>
-#include <linux/usb/phy.h>
-
-#include <linux/regulator/machine.h>
-#include <linux/i2c/twl.h>
-#include "id.h"
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/flash.h>
-
-#include "common.h"
-#include "gpmc.h"
-#include <linux/platform_data/mtd-nand-omap2.h>
-#include <video/omapdss.h>
-#include <video/omap-panel-data.h>
-
-#include <linux/platform_data/spi-omap2-mcspi.h>
-#include <linux/input/matrix_keypad.h>
-#include <linux/spi/spi.h>
-#include <linux/dm9000.h>
-#include <linux/interrupt.h>
-
-#include "sdram-micron-mt46h32m32lf-6.h"
-#include "mux.h"
-#include "hsmmc.h"
-#include "board-flash.h"
-#include "common-board-devices.h"
-
-#define        NAND_CS                 0
-
-#define OMAP_DM9000_GPIO_IRQ   25
-#define OMAP3_DEVKIT_TS_GPIO   27
-
-static struct mtd_partition devkit8000_nand_partitions[] = {
-       /* All the partition sizes are listed in terms of NAND block size */
-       {
-               .name           = "X-Loader",
-               .offset         = 0,
-               .size           = 4 * NAND_BLOCK_SIZE,
-               .mask_flags     = MTD_WRITEABLE,        /* force read-only */
-       },
-       {
-               .name           = "U-Boot",
-               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x80000 */
-               .size           = 15 * NAND_BLOCK_SIZE,
-               .mask_flags     = MTD_WRITEABLE,        /* force read-only */
-       },
-       {
-               .name           = "U-Boot Env",
-               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x260000 */
-               .size           = 1 * NAND_BLOCK_SIZE,
-       },
-       {
-               .name           = "Kernel",
-               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x280000 */
-               .size           = 32 * NAND_BLOCK_SIZE,
-       },
-       {
-               .name           = "File System",
-               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x680000 */
-               .size           = MTDPART_SIZ_FULL,
-       },
-};
-
-static struct omap2_hsmmc_info mmc[] = {
-       {
-               .mmc            = 1,
-               .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
-               .gpio_wp        = 29,
-               .deferred       = true,
-       },
-       {}      /* Terminator */
-};
-
-static struct regulator_consumer_supply devkit8000_vmmc1_supply[] = {
-       REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
-};
-
-/* ads7846 on SPI */
-static struct regulator_consumer_supply devkit8000_vio_supply[] = {
-       REGULATOR_SUPPLY("vcc", "spi2.0"),
-};
-
-static const struct display_timing devkit8000_lcd_videomode = {
-       .pixelclock     = { 0, 40000000, 0 },
-
-       .hactive = { 0, 800, 0 },
-       .hfront_porch = { 0, 1, 0 },
-       .hback_porch = { 0, 1, 0 },
-       .hsync_len = { 0, 48, 0 },
-
-       .vactive = { 0, 480, 0 },
-       .vfront_porch = { 0, 12, 0 },
-       .vback_porch = { 0, 25, 0 },
-       .vsync_len = { 0, 3, 0 },
-
-       .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW |
-               DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE,
-};
-
-static struct panel_dpi_platform_data devkit8000_lcd_pdata = {
-       .name                   = "lcd",
-       .source                 = "dpi.0",
-
-       .data_lines             = 24,
-
-       .display_timing         = &devkit8000_lcd_videomode,
-
-       .enable_gpio            = -1,   /* filled in code */
-       .backlight_gpio         = -1,
-};
-
-static struct platform_device devkit8000_lcd_device = {
-       .name                   = "panel-dpi",
-       .id                     = 0,
-       .dev.platform_data      = &devkit8000_lcd_pdata,
-};
-
-static struct connector_dvi_platform_data devkit8000_dvi_connector_pdata = {
-       .name                   = "dvi",
-       .source                 = "tfp410.0",
-       .i2c_bus_num            = 1,
-};
-
-static struct platform_device devkit8000_dvi_connector_device = {
-       .name                   = "connector-dvi",
-       .id                     = 0,
-       .dev.platform_data      = &devkit8000_dvi_connector_pdata,
-};
-
-static struct encoder_tfp410_platform_data devkit8000_tfp410_pdata = {
-       .name                   = "tfp410.0",
-       .source                 = "dpi.0",
-       .data_lines             = 24,
-       .power_down_gpio        = -1,   /* filled in code */
-};
-
-static struct platform_device devkit8000_tfp410_device = {
-       .name                   = "tfp410",
-       .id                     = 0,
-       .dev.platform_data      = &devkit8000_tfp410_pdata,
-};
-
-static struct connector_atv_platform_data devkit8000_tv_pdata = {
-       .name = "tv",
-       .source = "venc.0",
-       .connector_type = OMAP_DSS_VENC_TYPE_SVIDEO,
-       .invert_polarity = false,
-};
-
-static struct platform_device devkit8000_tv_connector_device = {
-       .name                   = "connector-analog-tv",
-       .id                     = 0,
-       .dev.platform_data      = &devkit8000_tv_pdata,
-};
-
-static struct omap_dss_board_info devkit8000_dss_data = {
-       .default_display_name = "lcd",
-};
-
-static uint32_t board_keymap[] = {
-       KEY(0, 0, KEY_1),
-       KEY(1, 0, KEY_2),
-       KEY(2, 0, KEY_3),
-       KEY(0, 1, KEY_4),
-       KEY(1, 1, KEY_5),
-       KEY(2, 1, KEY_6),
-       KEY(3, 1, KEY_F5),
-       KEY(0, 2, KEY_7),
-       KEY(1, 2, KEY_8),
-       KEY(2, 2, KEY_9),
-       KEY(3, 2, KEY_F6),
-       KEY(0, 3, KEY_F7),
-       KEY(1, 3, KEY_0),
-       KEY(2, 3, KEY_F8),
-       PERSISTENT_KEY(4, 5),
-       KEY(4, 4, KEY_VOLUMEUP),
-       KEY(5, 5, KEY_VOLUMEDOWN),
-       0
-};
-
-static struct matrix_keymap_data board_map_data = {
-       .keymap                 = board_keymap,
-       .keymap_size            = ARRAY_SIZE(board_keymap),
-};
-
-static struct twl4030_keypad_data devkit8000_kp_data = {
-       .keymap_data    = &board_map_data,
-       .rows           = 6,
-       .cols           = 6,
-       .rep            = 1,
-};
-
-static struct gpio_led gpio_leds[];
-
-static int devkit8000_twl_gpio_setup(struct device *dev,
-               unsigned gpio, unsigned ngpio)
-{
-       /* gpio + 0 is "mmc0_cd" (input/IRQ) */
-       mmc[0].gpio_cd = gpio + 0;
-       omap_hsmmc_late_init(mmc);
-
-       /* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
-       gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
-
-       /* TWL4030_GPIO_MAX + 0 is "LCD_PWREN" (out, active high) */
-       devkit8000_lcd_pdata.enable_gpio = gpio + TWL4030_GPIO_MAX + 0;
-
-       /* gpio + 7 is "DVI_PD" (out, active low) */
-       devkit8000_tfp410_pdata.power_down_gpio = gpio + 7;
-
-       return 0;
-}
-
-static struct twl4030_gpio_platform_data devkit8000_gpio_data = {
-       .use_leds       = true,
-       .pulldowns      = BIT(1) | BIT(2) | BIT(6) | BIT(8) | BIT(13)
-                               | BIT(15) | BIT(16) | BIT(17),
-       .setup          = devkit8000_twl_gpio_setup,
-};
-
-static struct regulator_consumer_supply devkit8000_vpll1_supplies[] = {
-       REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
-       REGULATOR_SUPPLY("vdds_dsi", "omapdss_dpi.0"),
-       REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"),
-};
-
-/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
-static struct regulator_init_data devkit8000_vmmc1 = {
-       .constraints = {
-               .min_uV                 = 1850000,
-               .max_uV                 = 3150000,
-               .valid_modes_mask       = REGULATOR_MODE_NORMAL
-                                       | REGULATOR_MODE_STANDBY,
-               .valid_ops_mask         = REGULATOR_CHANGE_VOLTAGE
-                                       | REGULATOR_CHANGE_MODE
-                                       | REGULATOR_CHANGE_STATUS,
-       },
-       .num_consumer_supplies  = ARRAY_SIZE(devkit8000_vmmc1_supply),
-       .consumer_supplies      = devkit8000_vmmc1_supply,
-};
-
-/* VPLL1 for digital video outputs */
-static struct regulator_init_data devkit8000_vpll1 = {
-       .constraints = {
-               .min_uV                 = 1800000,
-               .max_uV                 = 1800000,
-               .valid_modes_mask       = REGULATOR_MODE_NORMAL
-                                       | REGULATOR_MODE_STANDBY,
-               .valid_ops_mask         = REGULATOR_CHANGE_MODE
-                                       | REGULATOR_CHANGE_STATUS,
-       },
-       .num_consumer_supplies  = ARRAY_SIZE(devkit8000_vpll1_supplies),
-       .consumer_supplies      = devkit8000_vpll1_supplies,
-};
-
-/* VAUX4 for ads7846 and nubs */
-static struct regulator_init_data devkit8000_vio = {
-       .constraints = {
-               .min_uV                 = 1800000,
-               .max_uV                 = 1800000,
-               .apply_uV               = true,
-               .valid_modes_mask       = REGULATOR_MODE_NORMAL
-                       | REGULATOR_MODE_STANDBY,
-               .valid_ops_mask         = REGULATOR_CHANGE_MODE
-                       | REGULATOR_CHANGE_STATUS,
-       },
-       .num_consumer_supplies  = ARRAY_SIZE(devkit8000_vio_supply),
-       .consumer_supplies      = devkit8000_vio_supply,
-};
-
-static struct twl4030_platform_data devkit8000_twldata = {
-       /* platform_data for children goes here */
-       .gpio           = &devkit8000_gpio_data,
-       .vmmc1          = &devkit8000_vmmc1,
-       .vpll1          = &devkit8000_vpll1,
-       .vio            = &devkit8000_vio,
-       .keypad         = &devkit8000_kp_data,
-};
-
-static int __init devkit8000_i2c_init(void)
-{
-       omap3_pmic_get_config(&devkit8000_twldata,
-                         TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_AUDIO,
-                         TWL_COMMON_REGULATOR_VDAC);
-       omap3_pmic_init("tps65930", &devkit8000_twldata);
-       /* Bus 3 is attached to the DVI port where devices like the pico DLP
-        * projector don't work reliably with 400kHz */
-       omap_register_i2c_bus(3, 400, NULL, 0);
-       return 0;
-}
-
-static struct gpio_led gpio_leds[] = {
-       {
-               .name                   = "led1",
-               .default_trigger        = "heartbeat",
-               .gpio                   = 186,
-               .active_low             = true,
-       },
-       {
-               .name                   = "led2",
-               .default_trigger        = "mmc0",
-               .gpio                   = 163,
-               .active_low             = true,
-       },
-       {
-               .name                   = "ledB",
-               .default_trigger        = "none",
-               .gpio                   = 153,
-               .active_low             = true,
-       },
-       {
-               .name                   = "led3",
-               .default_trigger        = "none",
-               .gpio                   = 164,
-               .active_low             = true,
-       },
-};
-
-static struct gpio_led_platform_data gpio_led_info = {
-       .leds           = gpio_leds,
-       .num_leds       = ARRAY_SIZE(gpio_leds),
-};
-
-static struct platform_device leds_gpio = {
-       .name   = "leds-gpio",
-       .id     = -1,
-       .dev    = {
-               .platform_data  = &gpio_led_info,
-       },
-};
-
-static struct gpio_keys_button gpio_buttons[] = {
-       {
-               .code                   = BTN_EXTRA,
-               .gpio                   = 26,
-               .desc                   = "user",
-               .wakeup                 = 1,
-       },
-};
-
-static struct gpio_keys_platform_data gpio_key_info = {
-       .buttons        = gpio_buttons,
-       .nbuttons       = ARRAY_SIZE(gpio_buttons),
-};
-
-static struct platform_device keys_gpio = {
-       .name   = "gpio-keys",
-       .id     = -1,
-       .dev    = {
-               .platform_data  = &gpio_key_info,
-       },
-};
-
-#define OMAP_DM9000_BASE       0x2c000000
-
-static struct resource omap_dm9000_resources[] = {
-       [0] = {
-               .start          = OMAP_DM9000_BASE,
-               .end            = (OMAP_DM9000_BASE + 0x4 - 1),
-               .flags          = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start          = (OMAP_DM9000_BASE + 0x400),
-               .end            = (OMAP_DM9000_BASE + 0x400 + 0x4 - 1),
-               .flags          = IORESOURCE_MEM,
-       },
-       [2] = {
-               .flags          = IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
-       },
-};
-
-static struct dm9000_plat_data omap_dm9000_platdata = {
-       .flags = DM9000_PLATF_16BITONLY,
-};
-
-static struct platform_device omap_dm9000_dev = {
-       .name = "dm9000",
-       .id = -1,
-       .num_resources  = ARRAY_SIZE(omap_dm9000_resources),
-       .resource       = omap_dm9000_resources,
-       .dev = {
-               .platform_data = &omap_dm9000_platdata,
-       },
-};
-
-static void __init omap_dm9000_init(void)
-{
-       unsigned char *eth_addr = omap_dm9000_platdata.dev_addr;
-       struct omap_die_id odi;
-       int ret;
-
-       ret = gpio_request_one(OMAP_DM9000_GPIO_IRQ, GPIOF_IN, "dm9000 irq");
-       if (ret < 0) {
-               printk(KERN_ERR "Failed to request GPIO%d for dm9000 IRQ\n",
-                       OMAP_DM9000_GPIO_IRQ);
-               return;
-       }
-
-       /* init the mac address using DIE id */
-       omap_get_die_id(&odi);
-
-       eth_addr[0] = 0x02; /* locally administered */
-       eth_addr[1] = odi.id_1 & 0xff;
-       eth_addr[2] = (odi.id_0 & 0xff000000) >> 24;
-       eth_addr[3] = (odi.id_0 & 0x00ff0000) >> 16;
-       eth_addr[4] = (odi.id_0 & 0x0000ff00) >> 8;
-       eth_addr[5] = (odi.id_0 & 0x000000ff);
-}
-
-static struct platform_device *devkit8000_devices[] __initdata = {
-       &leds_gpio,
-       &keys_gpio,
-       &omap_dm9000_dev,
-       &devkit8000_lcd_device,
-       &devkit8000_tfp410_device,
-       &devkit8000_dvi_connector_device,
-       &devkit8000_tv_connector_device,
-};
-
-static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
-       .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
-};
-
-#ifdef CONFIG_OMAP_MUX
-static struct omap_board_mux board_mux[] __initdata = {
-       /* nCS and IRQ for Devkit8000 ethernet */
-       OMAP3_MUX(GPMC_NCS6, OMAP_MUX_MODE0),
-       OMAP3_MUX(ETK_D11, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP),
-
-       /* McSPI 2*/
-       OMAP3_MUX(MCSPI2_CLK, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(MCSPI2_SIMO, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(MCSPI2_SOMI, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(MCSPI2_CS0, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(MCSPI2_CS1, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-
-       /* PENDOWN GPIO */
-       OMAP3_MUX(ETK_D13, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
-
-       /* mUSB */
-       OMAP3_MUX(HSUSB0_CLK, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(HSUSB0_STP, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(HSUSB0_DIR, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(HSUSB0_NXT, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(HSUSB0_DATA0, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(HSUSB0_DATA1, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(HSUSB0_DATA2, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(HSUSB0_DATA3, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(HSUSB0_DATA4, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(HSUSB0_DATA5, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(HSUSB0_DATA6, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(HSUSB0_DATA7, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-
-       /* USB 1 */
-       OMAP3_MUX(ETK_CTL, OMAP_MUX_MODE3 | OMAP_PIN_INPUT),
-       OMAP3_MUX(ETK_CLK, OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(ETK_D8, OMAP_MUX_MODE3 | OMAP_PIN_INPUT),
-       OMAP3_MUX(ETK_D9, OMAP_MUX_MODE3 | OMAP_PIN_INPUT),
-       OMAP3_MUX(ETK_D0, OMAP_MUX_MODE3 | OMAP_PIN_INPUT),
-       OMAP3_MUX(ETK_D1, OMAP_MUX_MODE3 | OMAP_PIN_INPUT),
-       OMAP3_MUX(ETK_D2, OMAP_MUX_MODE3 | OMAP_PIN_INPUT),
-       OMAP3_MUX(ETK_D3, OMAP_MUX_MODE3 | OMAP_PIN_INPUT),
-       OMAP3_MUX(ETK_D4, OMAP_MUX_MODE3 | OMAP_PIN_INPUT),
-       OMAP3_MUX(ETK_D5, OMAP_MUX_MODE3 | OMAP_PIN_INPUT),
-       OMAP3_MUX(ETK_D6, OMAP_MUX_MODE3 | OMAP_PIN_INPUT),
-       OMAP3_MUX(ETK_D7, OMAP_MUX_MODE3 | OMAP_PIN_INPUT),
-
-       /* MMC 1 */
-       OMAP3_MUX(SDMMC1_CLK, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(SDMMC1_CMD, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(SDMMC1_DAT0, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(SDMMC1_DAT1, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(SDMMC1_DAT2, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(SDMMC1_DAT3, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(SDMMC1_DAT4, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(SDMMC1_DAT5, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(SDMMC1_DAT6, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(SDMMC1_DAT7, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-
-       /* McBSP 2 */
-       OMAP3_MUX(MCBSP2_FSX, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(MCBSP2_CLKX, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(MCBSP2_DR, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(MCBSP2_DX, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-
-       /* I2C 1 */
-       OMAP3_MUX(I2C1_SCL, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(I2C1_SDA, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-
-       /* I2C 2 */
-       OMAP3_MUX(I2C2_SCL, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(I2C2_SDA, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-
-       /* I2C 3 */
-       OMAP3_MUX(I2C3_SCL, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(I2C3_SDA, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-
-       /* I2C 4 */
-       OMAP3_MUX(I2C4_SCL, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(I2C4_SDA, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-
-       /* serial ports */
-       OMAP3_MUX(MCBSP3_CLKX, OMAP_MUX_MODE1 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(MCBSP3_FSX, OMAP_MUX_MODE1 | OMAP_PIN_INPUT),
-       OMAP3_MUX(UART1_TX, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(UART1_RX, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-
-       /* DSS */
-       OMAP3_MUX(DSS_PCLK, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_HSYNC, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_VSYNC, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_ACBIAS, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA0, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA1, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA2, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA3, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA4, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA5, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA6, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA7, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA8, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA9, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA10, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA11, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA12, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA13, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA14, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA15, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA16, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA17, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA18, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA19, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA20, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA21, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA22, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(DSS_DATA23, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-
-       /* expansion port */
-       /* McSPI 1 */
-       OMAP3_MUX(MCSPI1_CLK, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(MCSPI1_SIMO, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(MCSPI1_SOMI, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(MCSPI1_CS0, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN),
-       OMAP3_MUX(MCSPI1_CS3, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN),
-
-       /* HDQ */
-       OMAP3_MUX(HDQ_SIO, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-
-       /* McSPI4 */
-       OMAP3_MUX(MCBSP1_CLKR, OMAP_MUX_MODE1 | OMAP_PIN_INPUT),
-       OMAP3_MUX(MCBSP1_DX, OMAP_MUX_MODE1 | OMAP_PIN_INPUT),
-       OMAP3_MUX(MCBSP1_DR, OMAP_MUX_MODE1 | OMAP_PIN_INPUT),
-       OMAP3_MUX(MCBSP1_FSX, OMAP_MUX_MODE1 | OMAP_PIN_INPUT_PULLUP),
-
-       /* MMC 2 */
-       OMAP3_MUX(SDMMC2_DAT4, OMAP_MUX_MODE1 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(SDMMC2_DAT5, OMAP_MUX_MODE1 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(SDMMC2_DAT6, OMAP_MUX_MODE1 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(SDMMC2_DAT7, OMAP_MUX_MODE1 | OMAP_PIN_INPUT),
-
-       /* I2C3 */
-       OMAP3_MUX(I2C3_SCL, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-       OMAP3_MUX(I2C3_SDA, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
-
-       OMAP3_MUX(MCBSP1_CLKX, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(MCBSP_CLKS, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(MCBSP1_FSR, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
-
-       OMAP3_MUX(GPMC_NCS7, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
-       OMAP3_MUX(GPMC_NCS3, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
-
-       /* TPS IRQ */
-       OMAP3_MUX(SYS_NIRQ, OMAP_MUX_MODE0 | OMAP_WAKEUP_EN | \
-                       OMAP_PIN_INPUT_PULLUP),
-
-       { .reg_offset = OMAP_MUX_TERMINATOR },
-};
-#endif
-
-static void __init devkit8000_init(void)
-{
-       omap3_mux_init(board_mux, OMAP_PACKAGE_CUS);
-       omap_serial_init();
-       omap_sdrc_init(mt46h32m32lf6_sdrc_params,
-                                 mt46h32m32lf6_sdrc_params);
-
-       omap_dm9000_init();
-
-       omap_hsmmc_init(mmc);
-       devkit8000_i2c_init();
-       omap_dm9000_resources[2].start = gpio_to_irq(OMAP_DM9000_GPIO_IRQ);
-       platform_add_devices(devkit8000_devices,
-                       ARRAY_SIZE(devkit8000_devices));
-
-       omap_display_init(&devkit8000_dss_data);
-
-       omap_ads7846_init(2, OMAP3_DEVKIT_TS_GPIO, 0, NULL);
-
-       usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
-       usb_musb_init(NULL);
-       usbhs_init(&usbhs_bdata);
-       board_nand_init(devkit8000_nand_partitions,
-                       ARRAY_SIZE(devkit8000_nand_partitions), NAND_CS,
-                       NAND_BUSWIDTH_16, NULL);
-       omap_twl4030_audio_init("omap3beagle", NULL);
-
-       /* Ensure SDRC pins are mux'd for self-refresh */
-       omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
-       omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
-}
-
-MACHINE_START(DEVKIT8000, "OMAP3 Devkit8000")
-       .atag_offset    = 0x100,
-       .reserve        = omap_reserve,
-       .map_io         = omap3_map_io,
-       .init_early     = omap35xx_init_early,
-       .init_irq       = omap3_init_irq,
-       .init_machine   = devkit8000_init,
-       .init_late      = omap35xx_init_late,
-       .init_time      = omap3_secure_sync32k_timer_init,
-       .restart        = omap3xxx_restart,
-MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
deleted file mode 100644 (file)
index 6311f4b..0000000
+++ /dev/null
@@ -1,433 +0,0 @@
-/*
- * linux/arch/arm/mach-omap2/board-omap3evm.c
- *
- * Copyright (C) 2008 Guangzhou EMA-Tech
- *
- * Modified from mach-omap2/board-omap3evm.c
- *
- * Initial code: Syed Mohammed Khasim
- *
- * This program is free software; you can 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/init.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/leds.h>
-#include <linux/gpio.h>
-#include <linux/input.h>
-#include <linux/gpio_keys.h>
-
-#include <linux/regulator/fixed.h>
-#include <linux/regulator/machine.h>
-#include <linux/i2c/twl.h>
-#include <linux/mmc/host.h>
-#include <linux/input/matrix_keypad.h>
-#include <linux/spi/spi.h>
-#include <linux/interrupt.h>
-#include <linux/smsc911x.h>
-#include <linux/platform_data/at24.h>
-#include <linux/usb/phy.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/flash.h>
-
-#include "common.h"
-#include "gpmc.h"
-#include <linux/platform_data/mtd-nand-omap2.h>
-#include <video/omapdss.h>
-#include <video/omap-panel-data.h>
-
-#include <linux/platform_data/spi-omap2-mcspi.h>
-
-#include "sdram-micron-mt46h32m32lf-6.h"
-#include "mux.h"
-#include "hsmmc.h"
-#include "common-board-devices.h"
-
-#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
-#include "gpmc-smsc911x.h"
-
-#define OMAP3STALKER_ETHR_START        0x2c000000
-#define OMAP3STALKER_ETHR_SIZE 1024
-#define OMAP3STALKER_ETHR_GPIO_IRQ     19
-#define OMAP3STALKER_SMC911X_CS        5
-
-static struct omap_smsc911x_platform_data smsc911x_cfg = {
-       .cs             = OMAP3STALKER_SMC911X_CS,
-       .gpio_irq       = OMAP3STALKER_ETHR_GPIO_IRQ,
-       .gpio_reset     = -EINVAL,
-       .flags          = (SMSC911X_USE_32BIT | SMSC911X_SAVE_MAC_ADDRESS),
-};
-
-static inline void __init omap3stalker_init_eth(void)
-{
-       omap_mux_init_gpio(19, OMAP_PIN_INPUT_PULLUP);
-       gpmc_smsc911x_init(&smsc911x_cfg);
-}
-
-#else
-static inline void __init omap3stalker_init_eth(void)
-{
-       return;
-}
-#endif
-
-/*
- * OMAP3 DSS control signals
- */
-
-#define DSS_ENABLE_GPIO        199
-#define LCD_PANEL_BKLIGHT_GPIO 210
-#define ENABLE_VPLL2_DEV_GRP   0xE0
-
-static void __init omap3_stalker_display_init(void)
-{
-       return;
-}
-static struct connector_dvi_platform_data omap3stalker_dvi_connector_pdata = {
-       .name                   = "dvi",
-       .source                 = "tfp410.0",
-       .i2c_bus_num            = -1,
-};
-
-static struct platform_device omap3stalker_dvi_connector_device = {
-       .name                   = "connector-dvi",
-       .id                     = 0,
-       .dev.platform_data      = &omap3stalker_dvi_connector_pdata,
-};
-
-static struct encoder_tfp410_platform_data omap3stalker_tfp410_pdata = {
-       .name                   = "tfp410.0",
-       .source                 = "dpi.0",
-       .data_lines             = 24,
-       .power_down_gpio        = DSS_ENABLE_GPIO,
-};
-
-static struct platform_device omap3stalker_tfp410_device = {
-       .name                   = "tfp410",
-       .id                     = 0,
-       .dev.platform_data      = &omap3stalker_tfp410_pdata,
-};
-
-static struct connector_atv_platform_data omap3stalker_tv_pdata = {
-       .name = "tv",
-       .source = "venc.0",
-       .connector_type = OMAP_DSS_VENC_TYPE_COMPOSITE,
-       .invert_polarity = false,
-};
-
-static struct platform_device omap3stalker_tv_connector_device = {
-       .name                   = "connector-analog-tv",
-       .id                     = 0,
-       .dev.platform_data      = &omap3stalker_tv_pdata,
-};
-
-static struct omap_dss_board_info omap3_stalker_dss_data = {
-       .default_display_name = "dvi",
-};
-
-static struct regulator_consumer_supply omap3stalker_vmmc1_supply[] = {
-       REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
-};
-
-static struct regulator_consumer_supply omap3stalker_vsim_supply[] = {
-       REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.0"),
-};
-
-/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
-static struct regulator_init_data omap3stalker_vmmc1 = {
-       .constraints            = {
-               .min_uV                 = 1850000,
-               .max_uV                 = 3150000,
-               .valid_modes_mask       = REGULATOR_MODE_NORMAL
-               | REGULATOR_MODE_STANDBY,
-               .valid_ops_mask         = REGULATOR_CHANGE_VOLTAGE
-               | REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS,
-       },
-       .num_consumer_supplies  = ARRAY_SIZE(omap3stalker_vmmc1_supply),
-       .consumer_supplies      = omap3stalker_vmmc1_supply,
-};
-
-/* VSIM for MMC1 pins DAT4..DAT7 (2 mA, plus card == max 50 mA) */
-static struct regulator_init_data omap3stalker_vsim = {
-       .constraints            = {
-               .min_uV                 = 1800000,
-               .max_uV                 = 3000000,
-               .valid_modes_mask       = REGULATOR_MODE_NORMAL
-               | REGULATOR_MODE_STANDBY,
-               .valid_ops_mask         = REGULATOR_CHANGE_VOLTAGE
-               | REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS,
-       },
-       .num_consumer_supplies  = ARRAY_SIZE(omap3stalker_vsim_supply),
-       .consumer_supplies      = omap3stalker_vsim_supply,
-};
-
-static struct omap2_hsmmc_info mmc[] = {
-       {
-               .mmc            = 1,
-               .caps           = MMC_CAP_4_BIT_DATA,
-               .gpio_cd        = -EINVAL,
-               .gpio_wp        = 23,
-               .deferred       = true,
-        },
-       {}                      /* Terminator */
-};
-
-static struct gpio_keys_button gpio_buttons[] = {
-       {
-        .code          = BTN_EXTRA,
-        .gpio          = 18,
-        .desc          = "user",
-        .wakeup        = 1,
-        },
-};
-
-static struct gpio_keys_platform_data gpio_key_info = {
-       .buttons        = gpio_buttons,
-       .nbuttons       = ARRAY_SIZE(gpio_buttons),
-};
-
-static struct platform_device keys_gpio = {
-       .name           = "gpio-keys",
-       .id             = -1,
-       .dev            = {
-               .platform_data  = &gpio_key_info,
-       },
-};
-
-static struct gpio_led gpio_leds[] = {
-       {
-        .name                  = "stalker:D8:usr0",
-        .default_trigger       = "default-on",
-        .gpio                  = 126,
-        },
-       {
-        .name                  = "stalker:D9:usr1",
-        .default_trigger       = "default-on",
-        .gpio                  = 127,
-        },
-       {
-        .name                  = "stalker:D3:mmc0",
-        .gpio                  = -EINVAL,      /* gets replaced */
-        .active_low            = true,
-        .default_trigger       = "mmc0",
-        },
-       {
-        .name                  = "stalker:D4:heartbeat",
-        .gpio                  = -EINVAL,      /* gets replaced */
-        .active_low            = true,
-        .default_trigger       = "heartbeat",
-        },
-};
-
-static struct gpio_led_platform_data gpio_led_info = {
-       .leds           = gpio_leds,
-       .num_leds       = ARRAY_SIZE(gpio_leds),
-};
-
-static struct platform_device leds_gpio = {
-       .name   = "leds-gpio",
-       .id     = -1,
-       .dev    = {
-               .platform_data  = &gpio_led_info,
-       },
-};
-
-static int
-omap3stalker_twl_gpio_setup(struct device *dev,
-                           unsigned gpio, unsigned ngpio)
-{
-       /* gpio + 0 is "mmc0_cd" (input/IRQ) */
-       mmc[0].gpio_cd = gpio + 0;
-       omap_hsmmc_late_init(mmc);
-
-       /*
-        * Most GPIOs are for USB OTG.  Some are mostly sent to
-        * the P2 connector; notably LEDA for the LCD backlight.
-        */
-
-       /* TWL4030_GPIO_MAX + 0 == ledA, LCD Backlight control */
-       gpio_request_one(gpio + TWL4030_GPIO_MAX, GPIOF_OUT_INIT_LOW,
-                        "EN_LCD_BKL");
-
-       /* gpio + 7 == DVI Enable */
-       gpio_request_one(gpio + 7, GPIOF_OUT_INIT_LOW, "EN_DVI");
-
-       /* TWL4030_GPIO_MAX + 1 == ledB (out, mmc0) */
-       gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
-       /* GPIO + 13 == ledsync (out, heartbeat) */
-       gpio_leds[3].gpio = gpio + 13;
-
-       platform_device_register(&leds_gpio);
-       return 0;
-}
-
-static struct twl4030_gpio_platform_data omap3stalker_gpio_data = {
-       .use_leds       = true,
-       .setup          = omap3stalker_twl_gpio_setup,
-};
-
-static uint32_t board_keymap[] = {
-       KEY(0, 0, KEY_LEFT),
-       KEY(0, 1, KEY_DOWN),
-       KEY(0, 2, KEY_ENTER),
-       KEY(0, 3, KEY_M),
-
-       KEY(1, 0, KEY_RIGHT),
-       KEY(1, 1, KEY_UP),
-       KEY(1, 2, KEY_I),
-       KEY(1, 3, KEY_N),
-
-       KEY(2, 0, KEY_A),
-       KEY(2, 1, KEY_E),
-       KEY(2, 2, KEY_J),
-       KEY(2, 3, KEY_O),
-
-       KEY(3, 0, KEY_B),
-       KEY(3, 1, KEY_F),
-       KEY(3, 2, KEY_K),
-       KEY(3, 3, KEY_P)
-};
-
-static struct matrix_keymap_data board_map_data = {
-       .keymap         = board_keymap,
-       .keymap_size    = ARRAY_SIZE(board_keymap),
-};
-
-static struct twl4030_keypad_data omap3stalker_kp_data = {
-       .keymap_data    = &board_map_data,
-       .rows           = 4,
-       .cols           = 4,
-       .rep            = 1,
-};
-
-static struct twl4030_platform_data omap3stalker_twldata = {
-       /* platform_data for children goes here */
-       .keypad         = &omap3stalker_kp_data,
-       .gpio           = &omap3stalker_gpio_data,
-       .vmmc1          = &omap3stalker_vmmc1,
-       .vsim           = &omap3stalker_vsim,
-};
-
-static struct at24_platform_data fram_info = {
-       .byte_len       = (64 * 1024) / 8,
-       .page_size      = 8192,
-       .flags          = AT24_FLAG_ADDR16 | AT24_FLAG_IRUGO,
-};
-
-static struct i2c_board_info __initdata omap3stalker_i2c_boardinfo3[] = {
-       {
-        I2C_BOARD_INFO("24c64", 0x50),
-        .flags         = I2C_CLIENT_WAKE,
-        .platform_data = &fram_info,
-        },
-};
-
-static int __init omap3_stalker_i2c_init(void)
-{
-       omap3_pmic_get_config(&omap3stalker_twldata,
-                       TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_MADC |
-                       TWL_COMMON_PDATA_AUDIO,
-                       TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2);
-
-       omap3stalker_twldata.vdac->constraints.apply_uV = true;
-       omap3stalker_twldata.vpll2->constraints.apply_uV = true;
-       omap3stalker_twldata.vpll2->constraints.name = "VDVI";
-
-       omap3_pmic_init("twl4030", &omap3stalker_twldata);
-       omap_register_i2c_bus(2, 400, NULL, 0);
-       omap_register_i2c_bus(3, 400, omap3stalker_i2c_boardinfo3,
-                             ARRAY_SIZE(omap3stalker_i2c_boardinfo3));
-       return 0;
-}
-
-#define OMAP3_STALKER_TS_GPIO  175
-
-static struct usbhs_phy_data phy_data[] __initdata = {
-       {
-               .port = 2,
-               .reset_gpio = 21,
-               .vcc_gpio = -EINVAL,
-       },
-};
-
-static struct platform_device *omap3_stalker_devices[] __initdata = {
-       &keys_gpio,
-       &omap3stalker_tfp410_device,
-       &omap3stalker_dvi_connector_device,
-       &omap3stalker_tv_connector_device,
-};
-
-static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
-       .port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
-};
-
-#ifdef CONFIG_OMAP_MUX
-static struct omap_board_mux board_mux[] __initdata = {
-       OMAP3_MUX(SYS_NIRQ, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP |
-                 OMAP_PIN_OFF_INPUT_PULLUP | OMAP_PIN_OFF_WAKEUPENABLE),
-       OMAP3_MUX(MCSPI1_CS1, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP |
-                 OMAP_PIN_OFF_INPUT_PULLUP | OMAP_PIN_OFF_WAKEUPENABLE),
-       {.reg_offset = OMAP_MUX_TERMINATOR},
-};
-#endif
-
-static struct regulator_consumer_supply dummy_supplies[] = {
-       REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
-       REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
-};
-
-static void __init omap3_stalker_init(void)
-{
-       regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
-       omap3_mux_init(board_mux, OMAP_PACKAGE_CUS);
-
-       omap_mux_init_gpio(23, OMAP_PIN_INPUT);
-       omap_hsmmc_init(mmc);
-
-       omap3_stalker_i2c_init();
-
-       platform_add_devices(omap3_stalker_devices,
-                            ARRAY_SIZE(omap3_stalker_devices));
-
-       omap_display_init(&omap3_stalker_dss_data);
-
-       omap_serial_init();
-       omap_sdrc_init(mt46h32m32lf6_sdrc_params, NULL);
-       usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
-       usb_musb_init(NULL);
-
-       usbhs_init_phys(phy_data, ARRAY_SIZE(phy_data));
-       usbhs_init(&usbhs_bdata);
-       omap_ads7846_init(1, OMAP3_STALKER_TS_GPIO, 310, NULL);
-
-       omap_mux_init_gpio(21, OMAP_PIN_OUTPUT);
-       omap_mux_init_gpio(18, OMAP_PIN_INPUT_PULLUP);
-
-       omap3stalker_init_eth();
-       omap3_stalker_display_init();
-/* Ensure SDRC pins are mux'd for self-refresh */
-       omap_mux_init_signal("sdr_cke0", OMAP_PIN_OUTPUT);
-       omap_mux_init_signal("sdr_cke1", OMAP_PIN_OUTPUT);
-}
-
-MACHINE_START(SBC3530, "OMAP3 STALKER")
-       /* Maintainer: Jason Lam -lzg@ema-tech.com */
-       .atag_offset            = 0x100,
-       .map_io                 = omap3_map_io,
-       .init_early             = omap35xx_init_early,
-       .init_irq               = omap3_init_irq,
-       .init_machine           = omap3_stalker_init,
-       .init_late              = omap35xx_init_late,
-       .init_time              = omap3_secure_sync32k_timer_init,
-       .restart                = omap3xxx_restart,
-MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
deleted file mode 100644 (file)
index a01993e..0000000
+++ /dev/null
@@ -1,395 +0,0 @@
-/*
- * linux/arch/arm/mach-omap2/board-omap3touchbook.c
- *
- * Copyright (C) 2009 Always Innovating
- *
- * Modified from mach-omap2/board-omap3beagleboard.c
- *
- * Initial code: Grégoire Gentil, Tim Yamin
- *
- * This program is free software; you can 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/init.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/leds.h>
-#include <linux/gpio.h>
-#include <linux/input.h>
-#include <linux/gpio_keys.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/nand.h>
-#include <linux/mmc/host.h>
-#include <linux/usb/phy.h>
-
-#include <linux/platform_data/spi-omap2-mcspi.h>
-#include <linux/spi/spi.h>
-
-#include <linux/spi/ads7846.h>
-
-#include <linux/regulator/machine.h>
-#include <linux/i2c/twl.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/flash.h>
-#include <asm/system_info.h>
-
-#include "common.h"
-#include "gpmc.h"
-#include <linux/platform_data/mtd-nand-omap2.h>
-
-#include "mux.h"
-#include "hsmmc.h"
-#include "board-flash.h"
-#include "common-board-devices.h"
-
-#include <asm/setup.h>
-
-#define OMAP3_AC_GPIO          136
-#define OMAP3_TS_GPIO          162
-#define TB_BL_PWM_TIMER                9
-#define TB_KILL_POWER_GPIO     168
-
-#define        NAND_CS                 0
-
-static unsigned long touchbook_revision;
-
-static struct mtd_partition omap3touchbook_nand_partitions[] = {
-       /* All the partition sizes are listed in terms of NAND block size */
-       {
-               .name           = "X-Loader",
-               .offset         = 0,
-               .size           = 4 * NAND_BLOCK_SIZE,
-               .mask_flags     = MTD_WRITEABLE,        /* force read-only */
-       },
-       {
-               .name           = "U-Boot",
-               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x80000 */
-               .size           = 15 * NAND_BLOCK_SIZE,
-               .mask_flags     = MTD_WRITEABLE,        /* force read-only */
-       },
-       {
-               .name           = "U-Boot Env",
-               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x260000 */
-               .size           = 1 * NAND_BLOCK_SIZE,
-       },
-       {
-               .name           = "Kernel",
-               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x280000 */
-               .size           = 32 * NAND_BLOCK_SIZE,
-       },
-       {
-               .name           = "File System",
-               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x680000 */
-               .size           = MTDPART_SIZ_FULL,
-       },
-};
-
-#include "sdram-micron-mt46h32m32lf-6.h"
-
-static struct omap2_hsmmc_info mmc[] = {
-       {
-               .mmc            = 1,
-               .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
-               .gpio_wp        = 29,
-               .deferred       = true,
-       },
-       {}      /* Terminator */
-};
-
-static struct regulator_consumer_supply touchbook_vmmc1_supply[] = {
-       REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
-};
-
-static struct regulator_consumer_supply touchbook_vsim_supply[] = {
-       REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.0"),
-};
-
-static struct gpio_led gpio_leds[];
-
-static int touchbook_twl_gpio_setup(struct device *dev,
-               unsigned gpio, unsigned ngpio)
-{
-       /* gpio + 0 is "mmc0_cd" (input/IRQ) */
-       mmc[0].gpio_cd = gpio + 0;
-       omap_hsmmc_late_init(mmc);
-
-       /* REVISIT: need ehci-omap hooks for external VBUS
-        * power switch and overcurrent detect
-        */
-       gpio_request_one(gpio + 1, GPIOF_IN, "EHCI_nOC");
-
-       /* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, active low) */
-       gpio_request_one(gpio + TWL4030_GPIO_MAX, GPIOF_OUT_INIT_LOW,
-                        "nEN_USB_PWR");
-
-       /* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
-       gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
-
-       return 0;
-}
-
-static struct twl4030_gpio_platform_data touchbook_gpio_data = {
-       .use_leds       = true,
-       .pullups        = BIT(1),
-       .pulldowns      = BIT(2) | BIT(6) | BIT(7) | BIT(8) | BIT(13)
-                               | BIT(15) | BIT(16) | BIT(17),
-       .setup          = touchbook_twl_gpio_setup,
-};
-
-static struct regulator_consumer_supply touchbook_vdac_supply[] = {
-{
-       .supply         = "vdac",
-},
-};
-
-static struct regulator_consumer_supply touchbook_vdvi_supply[] = {
-{
-       .supply         = "vdvi",
-},
-};
-
-/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
-static struct regulator_init_data touchbook_vmmc1 = {
-       .constraints = {
-               .min_uV                 = 1850000,
-               .max_uV                 = 3150000,
-               .valid_modes_mask       = REGULATOR_MODE_NORMAL
-                                       | REGULATOR_MODE_STANDBY,
-               .valid_ops_mask         = REGULATOR_CHANGE_VOLTAGE
-                                       | REGULATOR_CHANGE_MODE
-                                       | REGULATOR_CHANGE_STATUS,
-       },
-       .num_consumer_supplies  = ARRAY_SIZE(touchbook_vmmc1_supply),
-       .consumer_supplies      = touchbook_vmmc1_supply,
-};
-
-/* VSIM for MMC1 pins DAT4..DAT7 (2 mA, plus card == max 50 mA) */
-static struct regulator_init_data touchbook_vsim = {
-       .constraints = {
-               .min_uV                 = 1800000,
-               .max_uV                 = 3000000,
-               .valid_modes_mask       = REGULATOR_MODE_NORMAL
-                                       | REGULATOR_MODE_STANDBY,
-               .valid_ops_mask         = REGULATOR_CHANGE_VOLTAGE
-                                       | REGULATOR_CHANGE_MODE
-                                       | REGULATOR_CHANGE_STATUS,
-       },
-       .num_consumer_supplies  = ARRAY_SIZE(touchbook_vsim_supply),
-       .consumer_supplies      = touchbook_vsim_supply,
-};
-
-static struct twl4030_platform_data touchbook_twldata = {
-       /* platform_data for children goes here */
-       .gpio           = &touchbook_gpio_data,
-       .vmmc1          = &touchbook_vmmc1,
-       .vsim           = &touchbook_vsim,
-};
-
-static struct i2c_board_info __initdata touchBook_i2c_boardinfo[] = {
-       {
-               I2C_BOARD_INFO("bq27200", 0x55),
-       },
-};
-
-static int __init omap3_touchbook_i2c_init(void)
-{
-       /* Standard TouchBook bus */
-       omap3_pmic_get_config(&touchbook_twldata,
-                       TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_AUDIO,
-                       TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2);
-
-       touchbook_twldata.vdac->num_consumer_supplies =
-                                       ARRAY_SIZE(touchbook_vdac_supply);
-       touchbook_twldata.vdac->consumer_supplies = touchbook_vdac_supply;
-
-       touchbook_twldata.vpll2->constraints.name = "VDVI";
-       touchbook_twldata.vpll2->num_consumer_supplies =
-                                       ARRAY_SIZE(touchbook_vdvi_supply);
-       touchbook_twldata.vpll2->consumer_supplies = touchbook_vdvi_supply;
-
-       omap3_pmic_init("twl4030", &touchbook_twldata);
-       /* Additional TouchBook bus */
-       omap_register_i2c_bus(3, 100, touchBook_i2c_boardinfo,
-                       ARRAY_SIZE(touchBook_i2c_boardinfo));
-
-       return 0;
-}
-
-static struct ads7846_platform_data ads7846_pdata = {
-       .x_min                  = 100,
-       .y_min                  = 265,
-       .x_max                  = 3950,
-       .y_max                  = 3750,
-       .x_plate_ohms           = 40,
-       .pressure_max           = 255,
-       .debounce_max           = 10,
-       .debounce_tol           = 5,
-       .debounce_rep           = 1,
-       .gpio_pendown           = OMAP3_TS_GPIO,
-       .keep_vref_on           = 1,
-};
-
-static struct gpio_led gpio_leds[] = {
-       {
-               .name                   = "touchbook::usr0",
-               .default_trigger        = "heartbeat",
-               .gpio                   = 150,
-       },
-       {
-               .name                   = "touchbook::usr1",
-               .default_trigger        = "mmc0",
-               .gpio                   = 149,
-       },
-       {
-               .name                   = "touchbook::pmu_stat",
-               .gpio                   = -EINVAL,      /* gets replaced */
-               .active_low             = true,
-       },
-};
-
-static struct gpio_led_platform_data gpio_led_info = {
-       .leds           = gpio_leds,
-       .num_leds       = ARRAY_SIZE(gpio_leds),
-};
-
-static struct platform_device leds_gpio = {
-       .name   = "leds-gpio",
-       .id     = -1,
-       .dev    = {
-               .platform_data  = &gpio_led_info,
-       },
-};
-
-static struct gpio_keys_button gpio_buttons[] = {
-       {
-               .code                   = BTN_EXTRA,
-               .gpio                   = 7,
-               .desc                   = "user",
-               .wakeup                 = 1,
-       },
-       {
-               .code                   = KEY_POWER,
-               .gpio                   = 183,
-               .desc                   = "power",
-               .wakeup                 = 1,
-       },
-};
-
-static struct gpio_keys_platform_data gpio_key_info = {
-       .buttons        = gpio_buttons,
-       .nbuttons       = ARRAY_SIZE(gpio_buttons),
-};
-
-static struct platform_device keys_gpio = {
-       .name   = "gpio-keys",
-       .id     = -1,
-       .dev    = {
-               .platform_data  = &gpio_key_info,
-       },
-};
-
-#ifdef CONFIG_OMAP_MUX
-static struct omap_board_mux board_mux[] __initdata = {
-       { .reg_offset = OMAP_MUX_TERMINATOR },
-};
-#endif
-
-static struct usbhs_phy_data phy_data[] __initdata = {
-       {
-               .port = 2,
-               .reset_gpio = 147,
-               .vcc_gpio = -EINVAL,
-       },
-};
-
-static struct platform_device *omap3_touchbook_devices[] __initdata = {
-       &leds_gpio,
-       &keys_gpio,
-};
-
-static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
-       .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
-       .port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
-};
-
-static void omap3_touchbook_poweroff(void)
-{
-       int pwr_off = TB_KILL_POWER_GPIO;
-
-       if (gpio_request_one(pwr_off, GPIOF_OUT_INIT_LOW, "DVI reset") < 0)
-               printk(KERN_ERR "Unable to get kill power GPIO\n");
-}
-
-static int __init early_touchbook_revision(char *p)
-{
-       if (!p)
-               return 0;
-
-       return kstrtoul(p, 10, &touchbook_revision);
-}
-early_param("tbr", early_touchbook_revision);
-
-static void __init omap3_touchbook_init(void)
-{
-       omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
-
-       pm_power_off = omap3_touchbook_poweroff;
-
-       if (system_rev >= 0x20 && system_rev <= 0x34301000) {
-               omap_mux_init_gpio(23, OMAP_PIN_INPUT);
-               mmc[0].gpio_wp = 23;
-       } else {
-               omap_mux_init_gpio(29, OMAP_PIN_INPUT);
-       }
-       omap_hsmmc_init(mmc);
-
-       omap3_touchbook_i2c_init();
-       platform_add_devices(omap3_touchbook_devices,
-                       ARRAY_SIZE(omap3_touchbook_devices));
-       omap_serial_init();
-       omap_sdrc_init(mt46h32m32lf6_sdrc_params,
-                                 mt46h32m32lf6_sdrc_params);
-
-       omap_mux_init_gpio(170, OMAP_PIN_INPUT);
-       /* REVISIT leave DVI powered down until it's needed ... */
-       gpio_request_one(176, GPIOF_OUT_INIT_HIGH, "DVI_nPD");
-
-       /* Touchscreen and accelerometer */
-       omap_ads7846_init(4, OMAP3_TS_GPIO, 310, &ads7846_pdata);
-       usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
-       usb_musb_init(NULL);
-
-       usbhs_init_phys(phy_data, ARRAY_SIZE(phy_data));
-       usbhs_init(&usbhs_bdata);
-       board_nand_init(omap3touchbook_nand_partitions,
-                       ARRAY_SIZE(omap3touchbook_nand_partitions), NAND_CS,
-                       NAND_BUSWIDTH_16, NULL);
-
-       /* Ensure SDRC pins are mux'd for self-refresh */
-       omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
-       omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
-}
-
-MACHINE_START(TOUCHBOOK, "OMAP3 touchbook Board")
-       /* Maintainer: Gregoire Gentil - http://www.alwaysinnovating.com */
-       .atag_offset    = 0x100,
-       .reserve        = omap_reserve,
-       .map_io         = omap3_map_io,
-       .init_early     = omap3430_init_early,
-       .init_irq       = omap3_init_irq,
-       .init_machine   = omap3_touchbook_init,
-       .init_late      = omap3430_init_late,
-       .init_time      = omap3_secure_sync32k_timer_init,
-       .restart        = omap3xxx_restart,
-MACHINE_END
index 6124db5c37aebf5d3092b66c355c326bdf6815f9..a699d716930746d4f37bd603be865b248d5986bc 100644 (file)
@@ -23,6 +23,9 @@
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/bitops.h>
+#include <linux/regmap.h>
+#include <linux/of_address.h>
+#include <linux/bootmem.h>
 #include <asm/cpu.h>
 
 #include <trace/events/power.h>
@@ -72,30 +75,110 @@ struct ti_clk_features ti_clk_features;
 static bool clkdm_control = true;
 
 static LIST_HEAD(clk_hw_omap_clocks);
-void __iomem *clk_memmaps[CLK_MAX_MEMMAPS];
+
+struct clk_iomap {
+       struct regmap *regmap;
+       void __iomem *mem;
+};
+
+static struct clk_iomap *clk_memmaps[CLK_MAX_MEMMAPS];
+
+static void clk_memmap_writel(u32 val, void __iomem *reg)
+{
+       struct clk_omap_reg *r = (struct clk_omap_reg *)&reg;
+       struct clk_iomap *io = clk_memmaps[r->index];
+
+       if (io->regmap)
+               regmap_write(io->regmap, r->offset, val);
+       else
+               writel_relaxed(val, io->mem + r->offset);
+}
+
+static u32 clk_memmap_readl(void __iomem *reg)
+{
+       u32 val;
+       struct clk_omap_reg *r = (struct clk_omap_reg *)&reg;
+       struct clk_iomap *io = clk_memmaps[r->index];
+
+       if (io->regmap)
+               regmap_read(io->regmap, r->offset, &val);
+       else
+               val = readl_relaxed(io->mem + r->offset);
+
+       return val;
+}
 
 void omap2_clk_writel(u32 val, struct clk_hw_omap *clk, void __iomem *reg)
 {
-       if (clk->flags & MEMMAP_ADDRESSING) {
-               struct clk_omap_reg *r = (struct clk_omap_reg *)&reg;
-               writel_relaxed(val, clk_memmaps[r->index] + r->offset);
-       } else {
+       if (WARN_ON_ONCE(!(clk->flags & MEMMAP_ADDRESSING)))
                writel_relaxed(val, reg);
-       }
+       else
+               clk_memmap_writel(val, reg);
 }
 
 u32 omap2_clk_readl(struct clk_hw_omap *clk, void __iomem *reg)
 {
-       u32 val;
+       if (WARN_ON_ONCE(!(clk->flags & MEMMAP_ADDRESSING)))
+               return readl_relaxed(reg);
+       else
+               return clk_memmap_readl(reg);
+}
 
-       if (clk->flags & MEMMAP_ADDRESSING) {
-               struct clk_omap_reg *r = (struct clk_omap_reg *)&reg;
-               val = readl_relaxed(clk_memmaps[r->index] + r->offset);
-       } else {
-               val = readl_relaxed(reg);
-       }
+static struct ti_clk_ll_ops omap_clk_ll_ops = {
+       .clk_readl = clk_memmap_readl,
+       .clk_writel = clk_memmap_writel,
+};
 
-       return val;
+/**
+ * omap2_clk_provider_init - initialize a clock provider
+ * @match_table: DT device table to match for devices to init
+ * @np: device node pointer for the this clock provider
+ * @index: index for the clock provider
+ + @syscon: syscon regmap pointer
+ * @mem: iomem pointer for the clock provider memory area, only used if
+ *      syscon is not provided
+ *
+ * Initializes a clock provider module (CM/PRM etc.), registering
+ * the memory mapping at specified index and initializing the
+ * low level driver infrastructure. Returns 0 in success.
+ */
+int __init omap2_clk_provider_init(struct device_node *np, int index,
+                                  struct regmap *syscon, void __iomem *mem)
+{
+       struct clk_iomap *io;
+
+       ti_clk_ll_ops = &omap_clk_ll_ops;
+
+       io = kzalloc(sizeof(*io), GFP_KERNEL);
+
+       io->regmap = syscon;
+       io->mem = mem;
+
+       clk_memmaps[index] = io;
+
+       ti_dt_clk_init_provider(np, index);
+
+       return 0;
+}
+
+/**
+ * omap2_clk_legacy_provider_init - initialize a legacy clock provider
+ * @index: index for the clock provider
+ * @mem: iomem pointer for the clock provider memory area
+ *
+ * Initializes a legacy clock provider memory mapping.
+ */
+void __init omap2_clk_legacy_provider_init(int index, void __iomem *mem)
+{
+       struct clk_iomap *io;
+
+       ti_clk_ll_ops = &omap_clk_ll_ops;
+
+       io = memblock_virt_alloc(sizeof(*io), 0);
+
+       io->mem = mem;
+
+       clk_memmaps[index] = io;
 }
 
 /*
index a56742f96000a64eb125010903304fb0d7e37414..652ed0ab86ec022cffdb55271e3c1e9fb6a78e0c 100644 (file)
@@ -271,10 +271,14 @@ extern const struct clksel_rate div_1_3_rates[];
 extern const struct clksel_rate div_1_4_rates[];
 extern const struct clksel_rate div31_1to31_rates[];
 
-extern void __iomem *clk_memmaps[];
-
 extern int omap2_clkops_enable_clkdm(struct clk_hw *hw);
 extern void omap2_clkops_disable_clkdm(struct clk_hw *hw);
 
+struct regmap;
+
+int __init omap2_clk_provider_init(struct device_node *np, int index,
+                                  struct regmap *syscon, void __iomem *mem);
+void __init omap2_clk_legacy_provider_init(int index, void __iomem *mem);
+
 void __init ti_clk_init_features(void);
 #endif
index 6222e87a79b623e7299e2c694e01246979d1accd..1fe3e6b833d255e76a8c564b68c532c1a63f0c83 100644 (file)
@@ -70,6 +70,8 @@ int omap_cm_module_enable(u8 mode, u8 part, u16 inst, u16 clkctrl_offs);
 int omap_cm_module_disable(u8 part, u16 inst, u16 clkctrl_offs);
 extern int cm_register(struct cm_ll_data *cld);
 extern int cm_unregister(struct cm_ll_data *cld);
+int omap_cm_init(void);
+int omap2_cm_base_init(void);
 
 # endif
 
index ef62ac9dcd0516452cda05309594e3b8008080b7..3e5fd3587eb1870e16daa70d2e27001cb449f01a 100644 (file)
@@ -393,7 +393,7 @@ static struct cm_ll_data omap2xxx_cm_ll_data = {
        .wait_module_ready      = &omap2xxx_cm_wait_module_ready,
 };
 
-int __init omap2xxx_cm_init(void)
+int __init omap2xxx_cm_init(const struct omap_prcm_init_data *data)
 {
        return cm_register(&omap2xxx_cm_ll_data);
 }
index 83b6c597b0e185e1d0e5d40c1768d729e23a7595..7b8c79c0ce27b11bf6b4fea313ab625d4c738779 100644 (file)
@@ -63,7 +63,7 @@ extern u32 omap2xxx_cm_get_core_pll_config(void);
 extern void omap2xxx_cm_set_mod_dividers(u32 mpu, u32 dsp, u32 gfx, u32 core,
                                         u32 mdm);
 
-extern int __init omap2xxx_cm_init(void);
+int __init omap2xxx_cm_init(const struct omap_prcm_init_data *data);
 
 #endif
 
index cc5aac784278b5e27fc8d90e080bec971a751eff..7b181f92952557b777e5e0bbbcedae0c6cb647f8 100644 (file)
@@ -352,7 +352,7 @@ static struct cm_ll_data am33xx_cm_ll_data = {
        .module_disable         = &am33xx_cm_module_disable,
 };
 
-int __init am33xx_cm_init(void)
+int __init am33xx_cm_init(const struct omap_prcm_init_data *data)
 {
        return cm_register(&am33xx_cm_ll_data);
 }
index 046b4b2bc9d93db7a584554c3dc4f93ae0342639..a91f7d2824559887f30088740f2defc551f7487b 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "cm.h"
 #include "cm-regbits-33xx.h"
+#include "prcm-common.h"
 
 /* CM base address */
 #define AM33XX_CM_BASE         0x44e00000
 
 
 #ifndef __ASSEMBLER__
-int am33xx_cm_init(void);
+int am33xx_cm_init(const struct omap_prcm_init_data *data);
 #endif /* ASSEMBLER */
 #endif
index ebead8f035f986d257e7d406bbe12d4bcf3089fa..187fa438671860c8edaa48b04769c09fe5d358ea 100644 (file)
@@ -671,8 +671,9 @@ static struct cm_ll_data omap3xxx_cm_ll_data = {
        .wait_module_ready      = &omap3xxx_cm_wait_module_ready,
 };
 
-int __init omap3xxx_cm_init(void)
+int __init omap3xxx_cm_init(const struct omap_prcm_init_data *data)
 {
+       omap2_clk_legacy_provider_init(TI_CLKM_CM, cm_base + OMAP3430_IVA2_MOD);
        return cm_register(&omap3xxx_cm_ll_data);
 }
 
index 734a8581c0c4e07d8286e7cd7725357955481384..bc444e2080a174fa49bb9da016d81fcf2f78ce05 100644 (file)
@@ -72,7 +72,7 @@ extern void omap3_cm_save_context(void);
 extern void omap3_cm_restore_context(void);
 extern void omap3_cm_save_scratchpad_contents(u32 *ptr);
 
-extern int __init omap3xxx_cm_init(void);
+int __init omap3xxx_cm_init(const struct omap_prcm_init_data *data);
 
 #endif
 
index 728d06a4af198f16cd5afab63ecccb752c68936f..309a4c91344847f41cb2074cb7060452c03474a3 100644 (file)
@@ -23,7 +23,6 @@
 #define OMAP4_CM_CLKSTCTRL                             0x0000
 #define OMAP4_CM_STATICDEP                             0x0004
 
-void omap_cm_base_init(void);
-int omap4_cm_init(void);
+int omap4_cm_init(const struct omap_prcm_init_data *data);
 
 #endif
index 8fe02fcedc48e3974bc90388753efa8a9c27aab6..23e8bcec34e33c89d7f9f196badb57136db57378 100644 (file)
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/bug.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
 
 #include "cm2xxx.h"
 #include "cm3xxx.h"
+#include "cm33xx.h"
 #include "cm44xx.h"
+#include "clock.h"
 
 /*
  * cm_ll_data: function pointers to SoC-specific implementations of
@@ -33,6 +37,9 @@ void __iomem *cm_base;
 /* cm2_base: base virtual address of the CM2 IP block (OMAP44xx only) */
 void __iomem *cm2_base;
 
+#define CM_NO_CLOCKS           0x1
+#define CM_SINGLE_INSTANCE     0x2
+
 /**
  * omap2_set_globals_cm - set the CM/CM2 base addresses (for early use)
  * @cm: CM base virtual address
@@ -212,3 +219,152 @@ int cm_unregister(struct cm_ll_data *cld)
 
        return 0;
 }
+
+#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \
+       defined(CONFIG_SOC_DRA7XX)
+static struct omap_prcm_init_data cm_data __initdata = {
+       .index = TI_CLKM_CM,
+       .init = omap4_cm_init,
+};
+
+static struct omap_prcm_init_data cm2_data __initdata = {
+       .index = TI_CLKM_CM2,
+       .init = omap4_cm_init,
+};
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2
+static struct omap_prcm_init_data omap2_prcm_data __initdata = {
+       .index = TI_CLKM_CM,
+       .init = omap2xxx_cm_init,
+       .flags = CM_NO_CLOCKS | CM_SINGLE_INSTANCE,
+};
+#endif
+
+#ifdef CONFIG_ARCH_OMAP3
+static struct omap_prcm_init_data omap3_cm_data __initdata = {
+       .index = TI_CLKM_CM,
+       .init = omap3xxx_cm_init,
+       .flags = CM_SINGLE_INSTANCE,
+
+       /*
+        * IVA2 offset is a negative value, must offset the cm_base address
+        * by this to get it to positive side on the iomap
+        */
+       .offset = -OMAP3430_IVA2_MOD,
+};
+#endif
+
+#if defined(CONFIG_SOC_AM33XX) || defined(CONFIG_SOC_TI81XX)
+static struct omap_prcm_init_data am3_prcm_data __initdata = {
+       .index = TI_CLKM_CM,
+       .flags = CM_NO_CLOCKS | CM_SINGLE_INSTANCE,
+       .init = am33xx_cm_init,
+};
+#endif
+
+#ifdef CONFIG_SOC_AM43XX
+static struct omap_prcm_init_data am4_prcm_data __initdata = {
+       .index = TI_CLKM_CM,
+       .flags = CM_NO_CLOCKS | CM_SINGLE_INSTANCE,
+       .init = omap4_cm_init,
+};
+#endif
+
+static const struct of_device_id omap_cm_dt_match_table[] __initconst = {
+#ifdef CONFIG_ARCH_OMAP2
+       { .compatible = "ti,omap2-prcm", .data = &omap2_prcm_data },
+#endif
+#ifdef CONFIG_ARCH_OMAP3
+       { .compatible = "ti,omap3-cm", .data = &omap3_cm_data },
+#endif
+#ifdef CONFIG_ARCH_OMAP4
+       { .compatible = "ti,omap4-cm1", .data = &cm_data },
+       { .compatible = "ti,omap4-cm2", .data = &cm2_data },
+#endif
+#ifdef CONFIG_SOC_OMAP5
+       { .compatible = "ti,omap5-cm-core-aon", .data = &cm_data },
+       { .compatible = "ti,omap5-cm-core", .data = &cm2_data },
+#endif
+#ifdef CONFIG_SOC_DRA7XX
+       { .compatible = "ti,dra7-cm-core-aon", .data = &cm_data },
+       { .compatible = "ti,dra7-cm-core", .data = &cm2_data },
+#endif
+#ifdef CONFIG_SOC_AM33XX
+       { .compatible = "ti,am3-prcm", .data = &am3_prcm_data },
+#endif
+#ifdef CONFIG_SOC_AM43XX
+       { .compatible = "ti,am4-prcm", .data = &am4_prcm_data },
+#endif
+#ifdef CONFIG_SOC_TI81XX
+       { .compatible = "ti,dm814-prcm", .data = &am3_prcm_data },
+       { .compatible = "ti,dm816-prcm", .data = &am3_prcm_data },
+#endif
+       { }
+};
+
+/**
+ * omap2_cm_base_init - initialize iomappings for the CM drivers
+ *
+ * Detects and initializes the iomappings for the CM driver, based
+ * on the DT data. Returns 0 in success, negative error value
+ * otherwise.
+ */
+int __init omap2_cm_base_init(void)
+{
+       struct device_node *np;
+       const struct of_device_id *match;
+       struct omap_prcm_init_data *data;
+       void __iomem *mem;
+
+       for_each_matching_node_and_match(np, omap_cm_dt_match_table, &match) {
+               data = (struct omap_prcm_init_data *)match->data;
+
+               mem = of_iomap(np, 0);
+               if (!mem)
+                       return -ENOMEM;
+
+               if (data->index == TI_CLKM_CM)
+                       cm_base = mem + data->offset;
+
+               if (data->index == TI_CLKM_CM2)
+                       cm2_base = mem + data->offset;
+
+               data->mem = mem;
+
+               data->np = np;
+
+               if (data->init && (data->flags & CM_SINGLE_INSTANCE ||
+                                  (cm_base && cm2_base)))
+                       data->init(data);
+       }
+
+       return 0;
+}
+
+/**
+ * omap_cm_init - low level init for the CM drivers
+ *
+ * Initializes the low level clock infrastructure for CM drivers.
+ * Returns 0 in success, negative error value in failure.
+ */
+int __init omap_cm_init(void)
+{
+       struct device_node *np;
+       const struct of_device_id *match;
+       const struct omap_prcm_init_data *data;
+       int ret;
+
+       for_each_matching_node_and_match(np, omap_cm_dt_match_table, &match) {
+               data = match->data;
+
+               if (data->flags & CM_NO_CLOCKS)
+                       continue;
+
+               ret = omap2_clk_provider_init(np, data->index, NULL, data->mem);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
index 95a8cff66aff5adf51320dda23c58b773adf67b6..2c0e07ed6b995b77b2c3a01aaaba457173251335 100644 (file)
@@ -63,7 +63,7 @@ static void __iomem *_cm_bases[OMAP4_MAX_PRCM_PARTITIONS];
  * Populates the base addresses of the _cm_bases
  * array used for read/write of cm module registers.
  */
-void omap_cm_base_init(void)
+static void omap_cm_base_init(void)
 {
        _cm_bases[OMAP4430_PRM_PARTITION] = prm_base;
        _cm_bases[OMAP4430_CM1_PARTITION] = cm_base;
@@ -514,8 +514,10 @@ static struct cm_ll_data omap4xxx_cm_ll_data = {
        .module_disable         = &omap4_cminst_module_disable,
 };
 
-int __init omap4_cm_init(void)
+int __init omap4_cm_init(const struct omap_prcm_init_data *data)
 {
+       omap_cm_base_init();
+
        return cm_register(&omap4xxx_cm_ll_data);
 }
 
index 484cdadfb18785ade051c29bab4d5e608dd56218..eae6a0e87c90d33649bccb350ed1f5732deae25d 100644 (file)
@@ -30,5 +30,4 @@ int __weak omap_secure_ram_reserve_memblock(void)
 void __init omap_reserve(void)
 {
        omap_secure_ram_reserve_memblock();
-       omap_barrier_reserve_memblock();
 }
index 46e24581d6245a45ff316a9c00dfe74284539238..cf3cf22ecd42696da3de4371ad11d38e46d95b33 100644 (file)
@@ -200,9 +200,6 @@ void __init omap4_map_io(void);
 void __init omap5_map_io(void);
 void __init ti81xx_map_io(void);
 
-/* omap_barriers_init() is OMAP4 only */
-void omap_barriers_init(void);
-
 /**
  * omap_test_timeout - busy-loop, testing a condition
  * @cond: condition to test until it evaluates to true
index da041b4ab29c6bb0b5ae5e67aee2271887b8b73e..af95a624fe71ea2a6d4f56f2ee11b2d2d51230c6 100644 (file)
@@ -14,6 +14,9 @@
 
 #include <linux/kernel.h>
 #include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
 
 #include "soc.h"
 #include "iomap.h"
 #include "sdrc.h"
 #include "pm.h"
 #include "control.h"
+#include "clock.h"
 
 /* Used by omap3_ctrl_save_padconf() */
 #define START_PADCONF_SAVE             0x2
 #define PADCONF_SAVE_DONE              0x1
 
 static void __iomem *omap2_ctrl_base;
-static void __iomem *omap4_ctrl_pad_base;
+static s16 omap2_ctrl_offset;
+static struct regmap *omap2_ctrl_syscon;
 
 #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
 struct omap3_scratchpad {
@@ -133,66 +138,79 @@ struct omap3_control_regs {
 static struct omap3_control_regs control_context;
 #endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */
 
-#define OMAP_CTRL_REGADDR(reg)         (omap2_ctrl_base + (reg))
-#define OMAP4_CTRL_PAD_REGADDR(reg)    (omap4_ctrl_pad_base + (reg))
-
-void __init omap2_set_globals_control(void __iomem *ctrl,
-                                     void __iomem *ctrl_pad)
+void __init omap2_set_globals_control(void __iomem *ctrl)
 {
        omap2_ctrl_base = ctrl;
-       omap4_ctrl_pad_base = ctrl_pad;
-}
-
-void __iomem *omap_ctrl_base_get(void)
-{
-       return omap2_ctrl_base;
 }
 
 u8 omap_ctrl_readb(u16 offset)
 {
-       return readb_relaxed(OMAP_CTRL_REGADDR(offset));
+       u32 val;
+       u8 byte_offset = offset & 0x3;
+
+       val = omap_ctrl_readl(offset);
+
+       return (val >> (byte_offset * 8)) & 0xff;
 }
 
 u16 omap_ctrl_readw(u16 offset)
 {
-       return readw_relaxed(OMAP_CTRL_REGADDR(offset));
+       u32 val;
+       u16 byte_offset = offset & 0x2;
+
+       val = omap_ctrl_readl(offset);
+
+       return (val >> (byte_offset * 8)) & 0xffff;
 }
 
 u32 omap_ctrl_readl(u16 offset)
 {
-       return readl_relaxed(OMAP_CTRL_REGADDR(offset));
+       u32 val;
+
+       offset &= 0xfffc;
+       if (!omap2_ctrl_syscon)
+               val = readl_relaxed(omap2_ctrl_base + offset);
+       else
+               regmap_read(omap2_ctrl_syscon, omap2_ctrl_offset + offset,
+                           &val);
+
+       return val;
 }
 
 void omap_ctrl_writeb(u8 val, u16 offset)
 {
-       writeb_relaxed(val, OMAP_CTRL_REGADDR(offset));
+       u32 tmp;
+       u8 byte_offset = offset & 0x3;
+
+       tmp = omap_ctrl_readl(offset);
+
+       tmp &= 0xffffffff ^ (0xff << (byte_offset * 8));
+       tmp |= val << (byte_offset * 8);
+
+       omap_ctrl_writel(tmp, offset);
 }
 
 void omap_ctrl_writew(u16 val, u16 offset)
 {
-       writew_relaxed(val, OMAP_CTRL_REGADDR(offset));
-}
+       u32 tmp;
+       u8 byte_offset = offset & 0x2;
 
-void omap_ctrl_writel(u32 val, u16 offset)
-{
-       writel_relaxed(val, OMAP_CTRL_REGADDR(offset));
-}
+       tmp = omap_ctrl_readl(offset);
 
-/*
- * On OMAP4 control pad are not addressable from control
- * core base. So the common omap_ctrl_read/write APIs breaks
- * Hence export separate APIs to manage the omap4 pad control
- * registers. This APIs will work only for OMAP4
- */
+       tmp &= 0xffffffff ^ (0xffff << (byte_offset * 8));
+       tmp |= val << (byte_offset * 8);
 
-u32 omap4_ctrl_pad_readl(u16 offset)
-{
-       return readl_relaxed(OMAP4_CTRL_PAD_REGADDR(offset));
+       omap_ctrl_writel(tmp, offset);
 }
 
-void omap4_ctrl_pad_writel(u32 val, u16 offset)
+void omap_ctrl_writel(u32 val, u16 offset)
 {
-       writel_relaxed(val, OMAP4_CTRL_PAD_REGADDR(offset));
+       offset &= 0xfffc;
+       if (!omap2_ctrl_syscon)
+               writel_relaxed(val, omap2_ctrl_base + offset);
+       else
+               regmap_write(omap2_ctrl_syscon, omap2_ctrl_offset + offset,
+                            val);
 }
 
 #ifdef CONFIG_ARCH_OMAP3
@@ -611,3 +629,120 @@ void __init omap3_ctrl_init(void)
        omap3_ctrl_setup_d2d_padconf();
 }
 #endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */
+
+struct control_init_data {
+       int index;
+       s16 offset;
+};
+
+static struct control_init_data ctrl_data = {
+       .index = TI_CLKM_CTRL,
+};
+
+static const struct control_init_data omap2_ctrl_data = {
+       .index = TI_CLKM_CTRL,
+       .offset = -OMAP2_CONTROL_GENERAL,
+};
+
+static const struct of_device_id omap_scrm_dt_match_table[] = {
+       { .compatible = "ti,am3-scm", .data = &ctrl_data },
+       { .compatible = "ti,am4-scm", .data = &ctrl_data },
+       { .compatible = "ti,omap2-scm", .data = &omap2_ctrl_data },
+       { .compatible = "ti,omap3-scm", .data = &omap2_ctrl_data },
+       { .compatible = "ti,dm816-scrm", .data = &ctrl_data },
+       { .compatible = "ti,omap4-scm-core", .data = &ctrl_data },
+       { .compatible = "ti,omap5-scm-core", .data = &ctrl_data },
+       { .compatible = "ti,dra7-scm-core", .data = &ctrl_data },
+       { }
+};
+
+/**
+ * omap2_control_base_init - initialize iomappings for the control driver
+ *
+ * Detects and initializes the iomappings for the control driver, based
+ * on the DT data. Returns 0 in success, negative error value
+ * otherwise.
+ */
+int __init omap2_control_base_init(void)
+{
+       struct device_node *np;
+       const struct of_device_id *match;
+       struct control_init_data *data;
+
+       for_each_matching_node_and_match(np, omap_scrm_dt_match_table, &match) {
+               data = (struct control_init_data *)match->data;
+
+               omap2_ctrl_base = of_iomap(np, 0);
+               if (!omap2_ctrl_base)
+                       return -ENOMEM;
+
+               omap2_ctrl_offset = data->offset;
+       }
+
+       return 0;
+}
+
+/**
+ * omap_control_init - low level init for the control driver
+ *
+ * Initializes the low level clock infrastructure for control driver.
+ * Returns 0 in success, negative error value in failure.
+ */
+int __init omap_control_init(void)
+{
+       struct device_node *np, *scm_conf;
+       const struct of_device_id *match;
+       const struct omap_prcm_init_data *data;
+       int ret;
+       struct regmap *syscon;
+
+       for_each_matching_node_and_match(np, omap_scrm_dt_match_table, &match) {
+               data = match->data;
+
+               /*
+                * Check if we have scm_conf node, if yes, use this to
+                * access clock registers.
+                */
+               scm_conf = of_get_child_by_name(np, "scm_conf");
+
+               if (scm_conf) {
+                       syscon = syscon_node_to_regmap(scm_conf);
+
+                       if (IS_ERR(syscon))
+                               return PTR_ERR(syscon);
+
+                       omap2_ctrl_syscon = syscon;
+
+                       if (of_get_child_by_name(scm_conf, "clocks")) {
+                               ret = omap2_clk_provider_init(scm_conf,
+                                                             data->index,
+                                                             syscon, NULL);
+                               if (ret)
+                                       return ret;
+                       }
+
+                       iounmap(omap2_ctrl_base);
+                       omap2_ctrl_base = NULL;
+               } else {
+                       /* No scm_conf found, direct access */
+                       ret = omap2_clk_provider_init(np, data->index, NULL,
+                                                     omap2_ctrl_base);
+                       if (ret)
+                               return ret;
+               }
+       }
+
+       return 0;
+}
+
+/**
+ * omap3_control_legacy_iomap_init - legacy iomap init for clock providers
+ *
+ * Legacy iomap init for clock provider. Needed only by legacy boot mode,
+ * where the base addresses are not parsed from DT, but still required
+ * by the clock driver to be setup properly.
+ */
+void __init omap3_control_legacy_iomap_init(void)
+{
+       omap2_clk_legacy_provider_init(TI_CLKM_SCRM, omap2_ctrl_base);
+}
index b8a48718121015931c1d7d90092dd1161a5c4efb..80d2b7d8e36ed56e76dfb585fb04995e5b04a18b 100644 (file)
 
 #ifndef __ASSEMBLY__
 #ifdef CONFIG_ARCH_OMAP2PLUS
-extern void __iomem *omap_ctrl_base_get(void);
 extern u8 omap_ctrl_readb(u16 offset);
 extern u16 omap_ctrl_readw(u16 offset);
 extern u32 omap_ctrl_readl(u16 offset);
-extern u32 omap4_ctrl_pad_readl(u16 offset);
 extern void omap_ctrl_writeb(u8 val, u16 offset);
 extern void omap_ctrl_writew(u16 val, u16 offset);
 extern void omap_ctrl_writel(u32 val, u16 offset);
-extern void omap4_ctrl_pad_writel(u32 val, u16 offset);
 
 extern void omap3_save_scratchpad_contents(void);
 extern void omap3_clear_scratchpad_contents(void);
@@ -464,10 +461,11 @@ extern void omap_ctrl_write_dsp_boot_mode(u8 bootmode);
 extern void omap3630_ctrl_disable_rta(void);
 extern int omap3_ctrl_save_padconf(void);
 void omap3_ctrl_init(void);
-extern void omap2_set_globals_control(void __iomem *ctrl,
-                                     void __iomem *ctrl_pad);
+int omap2_control_base_init(void);
+int omap_control_init(void);
+void omap2_set_globals_control(void __iomem *ctrl);
+void __init omap3_control_legacy_iomap_init(void);
 #else
-#define omap_ctrl_base_get()           0
 #define omap_ctrl_readb(x)             0
 #define omap_ctrl_readw(x)             0
 #define omap_ctrl_readl(x)             0
index 1afb50d6d63672887805d4ae3d29962593b14ddb..990338fbaa591274c6a5ade9bbbf055e633decac 100644 (file)
@@ -74,82 +74,12 @@ omap_postcore_initcall(omap3_l3_init);
 static struct resource omap3isp_resources[] = {
        {
                .start          = OMAP3430_ISP_BASE,
-               .end            = OMAP3430_ISP_END,
+               .end            = OMAP3430_ISP_BASE + 0x12fc,
                .flags          = IORESOURCE_MEM,
        },
        {
-               .start          = OMAP3430_ISP_CCP2_BASE,
-               .end            = OMAP3430_ISP_CCP2_END,
-               .flags          = IORESOURCE_MEM,
-       },
-       {
-               .start          = OMAP3430_ISP_CCDC_BASE,
-               .end            = OMAP3430_ISP_CCDC_END,
-               .flags          = IORESOURCE_MEM,
-       },
-       {
-               .start          = OMAP3430_ISP_HIST_BASE,
-               .end            = OMAP3430_ISP_HIST_END,
-               .flags          = IORESOURCE_MEM,
-       },
-       {
-               .start          = OMAP3430_ISP_H3A_BASE,
-               .end            = OMAP3430_ISP_H3A_END,
-               .flags          = IORESOURCE_MEM,
-       },
-       {
-               .start          = OMAP3430_ISP_PREV_BASE,
-               .end            = OMAP3430_ISP_PREV_END,
-               .flags          = IORESOURCE_MEM,
-       },
-       {
-               .start          = OMAP3430_ISP_RESZ_BASE,
-               .end            = OMAP3430_ISP_RESZ_END,
-               .flags          = IORESOURCE_MEM,
-       },
-       {
-               .start          = OMAP3430_ISP_SBL_BASE,
-               .end            = OMAP3430_ISP_SBL_END,
-               .flags          = IORESOURCE_MEM,
-       },
-       {
-               .start          = OMAP3430_ISP_CSI2A_REGS1_BASE,
-               .end            = OMAP3430_ISP_CSI2A_REGS1_END,
-               .flags          = IORESOURCE_MEM,
-       },
-       {
-               .start          = OMAP3430_ISP_CSIPHY2_BASE,
-               .end            = OMAP3430_ISP_CSIPHY2_END,
-               .flags          = IORESOURCE_MEM,
-       },
-       {
-               .start          = OMAP3630_ISP_CSI2A_REGS2_BASE,
-               .end            = OMAP3630_ISP_CSI2A_REGS2_END,
-               .flags          = IORESOURCE_MEM,
-       },
-       {
-               .start          = OMAP3630_ISP_CSI2C_REGS1_BASE,
-               .end            = OMAP3630_ISP_CSI2C_REGS1_END,
-               .flags          = IORESOURCE_MEM,
-       },
-       {
-               .start          = OMAP3630_ISP_CSIPHY1_BASE,
-               .end            = OMAP3630_ISP_CSIPHY1_END,
-               .flags          = IORESOURCE_MEM,
-       },
-       {
-               .start          = OMAP3630_ISP_CSI2C_REGS2_BASE,
-               .end            = OMAP3630_ISP_CSI2C_REGS2_END,
-               .flags          = IORESOURCE_MEM,
-       },
-       {
-               .start          = OMAP343X_CTRL_BASE + OMAP343X_CONTROL_CSIRXFE,
-               .end            = OMAP343X_CTRL_BASE + OMAP343X_CONTROL_CSIRXFE + 3,
-               .flags          = IORESOURCE_MEM,
-       },
-       {
-               .start          = OMAP343X_CTRL_BASE + OMAP3630_CONTROL_CAMERA_PHY_CTRL,
-               .end            = OMAP343X_CTRL_BASE + OMAP3630_CONTROL_CAMERA_PHY_CTRL + 3,
+               .start          = OMAP3430_ISP_BASE2,
+               .end            = OMAP3430_ISP_BASE2 + 0x0600,
                .flags          = IORESOURCE_MEM,
        },
        {
index 7a050f9c37ff2bf9bd5e8c0ccd75f8f16510b86f..f492ae147c6ac6752aaeb74b921c2861a1d8cd2a 100644 (file)
@@ -26,6 +26,8 @@
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/slab.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
 
 #include <video/omapdss.h>
 #include "omap_hwmod.h"
@@ -104,6 +106,10 @@ static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initconst = {
        { "dss_hdmi", "omapdss_hdmi", -1 },
 };
 
+#define OMAP4_DSIPHY_SYSCON_OFFSET             0x78
+
+static struct regmap *omap4_dsi_mux_syscon;
+
 static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
 {
        u32 enable_mask, enable_shift;
@@ -124,7 +130,7 @@ static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
                return -ENODEV;
        }
 
-       reg = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY);
+       regmap_read(omap4_dsi_mux_syscon, OMAP4_DSIPHY_SYSCON_OFFSET, &reg);
 
        reg &= ~enable_mask;
        reg &= ~pipd_mask;
@@ -132,7 +138,7 @@ static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
        reg |= (lanes << enable_shift) & enable_mask;
        reg |= (lanes << pipd_shift) & pipd_mask;
 
-       omap4_ctrl_pad_writel(reg, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY);
+       regmap_write(omap4_dsi_mux_syscon, OMAP4_DSIPHY_SYSCON_OFFSET, reg);
 
        return 0;
 }
@@ -665,5 +671,10 @@ int __init omapdss_init_of(void)
                return r;
        }
 
+       /* add DSI info for omap4 */
+       node = of_find_node_by_name(NULL, "omap4_padconf_global");
+       if (node)
+               omap4_dsi_mux_syscon = syscon_node_to_regmap(node);
+
        return 0;
 }
index d5951b17b7368c0713b5bddd56e03cff34b6cc17..72918c4973ea7f0cc86da080916c9f72bd327fcd 100644 (file)
@@ -96,14 +96,6 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
        gpmc_nand_res[1].start = gpmc_get_client_irq(GPMC_IRQ_FIFOEVENTENABLE);
        gpmc_nand_res[2].start = gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT);
 
-       if (gpmc_t) {
-               err = gpmc_cs_set_timings(gpmc_nand_data->cs, gpmc_t);
-               if (err < 0) {
-                       pr_err("omap2-gpmc: Unable to set gpmc timings: %d\n", err);
-                       return err;
-               }
-       }
-
        memset(&s, 0, sizeof(struct gpmc_settings));
        if (gpmc_nand_data->of_node)
                gpmc_read_settings_dt(gpmc_nand_data->of_node, &s);
@@ -111,6 +103,16 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
                gpmc_set_legacy(gpmc_nand_data, &s);
 
        s.device_nand = true;
+
+       if (gpmc_t) {
+               err = gpmc_cs_set_timings(gpmc_nand_data->cs, gpmc_t, &s);
+               if (err < 0) {
+                       pr_err("omap2-gpmc: Unable to set gpmc timings: %d\n",
+                              err);
+                       return err;
+               }
+       }
+
        err = gpmc_cs_program_settings(gpmc_nand_data->cs, &s);
        if (err < 0)
                goto out_free_cs;
index 53d197e0c1f34525b828e256bff935e41ebe7d33..f899e77ff5e6e37eca7d131533f3526a13b5d20c 100644 (file)
@@ -293,7 +293,7 @@ static int omap2_onenand_setup_async(void __iomem *onenand_base)
        if (ret < 0)
                return ret;
 
-       ret = gpmc_cs_set_timings(gpmc_onenand_data->cs, &t);
+       ret = gpmc_cs_set_timings(gpmc_onenand_data->cs, &t, &onenand_async);
        if (ret < 0)
                return ret;
 
@@ -331,7 +331,7 @@ static int omap2_onenand_setup_sync(void __iomem *onenand_base, int *freq_ptr)
        if (ret < 0)
                return ret;
 
-       ret = gpmc_cs_set_timings(gpmc_onenand_data->cs, &t);
+       ret = gpmc_cs_set_timings(gpmc_onenand_data->cs, &t, &onenand_sync);
        if (ret < 0)
                return ret;
 
index 25f1beea453e0252234b3c62d7f53de75e6ed3f3..e3f713ffb06b7f7fd2e9187668b7698286a29dad 100644 (file)
@@ -52,7 +52,10 @@ EXPORT_SYMBOL(omap_rev);
 
 int omap_type(void)
 {
-       u32 val = 0;
+       static u32 val = OMAP2_DEVICETYPE_MASK;
+
+       if (val < OMAP2_DEVICETYPE_MASK)
+               return val;
 
        if (cpu_is_omap24xx()) {
                val = omap_ctrl_readl(OMAP24XX_CONTROL_STATUS);
index c4871c55bd8b641544a86a281121cad4c9219e42..820dde8b5b0453f96a6a3c53a4db8e4c3c9abca6 100644 (file)
@@ -306,7 +306,6 @@ void __init am33xx_map_io(void)
 void __init omap4_map_io(void)
 {
        iotable_init(omap44xx_io_desc, ARRAY_SIZE(omap44xx_io_desc));
-       omap_barriers_init();
 }
 #endif
 
@@ -314,7 +313,6 @@ void __init omap4_map_io(void)
 void __init omap5_map_io(void)
 {
        iotable_init(omap54xx_io_desc, ARRAY_SIZE(omap54xx_io_desc));
-       omap_barriers_init();
 }
 #endif
 /*
@@ -384,13 +382,9 @@ void __init omap2420_init_early(void)
        omap2_set_globals_tap(OMAP242X_CLASS, OMAP2_L4_IO_ADDRESS(0x48014000));
        omap2_set_globals_sdrc(OMAP2_L3_IO_ADDRESS(OMAP2420_SDRC_BASE),
                               OMAP2_L3_IO_ADDRESS(OMAP2420_SMS_BASE));
-       omap2_set_globals_control(OMAP2_L4_IO_ADDRESS(OMAP242X_CTRL_BASE),
-                                 NULL);
-       omap2_set_globals_prm(OMAP2_L4_IO_ADDRESS(OMAP2420_PRM_BASE));
-       omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(OMAP2420_CM_BASE), NULL);
+       omap2_control_base_init();
        omap2xxx_check_revision();
-       omap2xxx_prm_init();
-       omap2xxx_cm_init();
+       omap2_prcm_base_init();
        omap2xxx_voltagedomains_init();
        omap242x_powerdomains_init();
        omap242x_clockdomains_init();
@@ -414,13 +408,9 @@ void __init omap2430_init_early(void)
        omap2_set_globals_tap(OMAP243X_CLASS, OMAP2_L4_IO_ADDRESS(0x4900a000));
        omap2_set_globals_sdrc(OMAP2_L3_IO_ADDRESS(OMAP243X_SDRC_BASE),
                               OMAP2_L3_IO_ADDRESS(OMAP243X_SMS_BASE));
-       omap2_set_globals_control(OMAP2_L4_IO_ADDRESS(OMAP243X_CTRL_BASE),
-                                 NULL);
-       omap2_set_globals_prm(OMAP2_L4_IO_ADDRESS(OMAP2430_PRM_BASE));
-       omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(OMAP2430_CM_BASE), NULL);
+       omap2_control_base_init();
        omap2xxx_check_revision();
-       omap2xxx_prm_init();
-       omap2xxx_cm_init();
+       omap2_prcm_base_init();
        omap2xxx_voltagedomains_init();
        omap243x_powerdomains_init();
        omap243x_clockdomains_init();
@@ -448,21 +438,30 @@ void __init omap3_init_early(void)
        omap2_set_globals_tap(OMAP343X_CLASS, OMAP2_L4_IO_ADDRESS(0x4830A000));
        omap2_set_globals_sdrc(OMAP2_L3_IO_ADDRESS(OMAP343X_SDRC_BASE),
                               OMAP2_L3_IO_ADDRESS(OMAP343X_SMS_BASE));
-       omap2_set_globals_control(OMAP2_L4_IO_ADDRESS(OMAP343X_CTRL_BASE),
-                                 NULL);
-       omap2_set_globals_prm(OMAP2_L4_IO_ADDRESS(OMAP3430_PRM_BASE));
-       omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(OMAP3430_CM_BASE), NULL);
+       /* XXX: remove these once OMAP3 is DT only */
+       if (!of_have_populated_dt()) {
+               omap2_set_globals_control(
+                       OMAP2_L4_IO_ADDRESS(OMAP343X_CTRL_BASE));
+               omap2_set_globals_prm(OMAP2_L4_IO_ADDRESS(OMAP3430_PRM_BASE));
+               omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(OMAP3430_CM_BASE),
+                                    NULL);
+       }
+       omap2_control_base_init();
        omap3xxx_check_revision();
        omap3xxx_check_features();
-       omap3xxx_prm_init();
-       omap3xxx_cm_init();
+       omap2_prcm_base_init();
+       /* XXX: remove these once OMAP3 is DT only */
+       if (!of_have_populated_dt()) {
+               omap3xxx_prm_init(NULL);
+               omap3xxx_cm_init(NULL);
+       }
        omap3xxx_voltagedomains_init();
        omap3xxx_powerdomains_init();
        omap3xxx_clockdomains_init();
        omap3xxx_hwmod_init();
        omap_hwmod_init_postsetup();
        if (!of_have_populated_dt()) {
-               omap3_prcm_legacy_iomaps_init();
+               omap3_control_legacy_iomap_init();
                if (soc_is_am35xx())
                        omap_clk_soc_init = am35xx_clk_legacy_init;
                else if (cpu_is_omap3630())
@@ -549,14 +548,10 @@ void __init ti814x_init_early(void)
 {
        omap2_set_globals_tap(TI814X_CLASS,
                              OMAP2_L4_IO_ADDRESS(TI81XX_TAP_BASE));
-       omap2_set_globals_control(OMAP2_L4_IO_ADDRESS(TI81XX_CTRL_BASE),
-                                 NULL);
-       omap2_set_globals_prm(OMAP2_L4_IO_ADDRESS(TI81XX_PRCM_BASE));
-       omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(TI81XX_PRCM_BASE), NULL);
+       omap2_control_base_init();
        omap3xxx_check_revision();
        ti81xx_check_features();
-       am33xx_prm_init();
-       am33xx_cm_init();
+       omap2_prcm_base_init();
        omap3xxx_voltagedomains_init();
        omap3xxx_powerdomains_init();
        ti81xx_clockdomains_init();
@@ -570,14 +565,10 @@ void __init ti816x_init_early(void)
 {
        omap2_set_globals_tap(TI816X_CLASS,
                              OMAP2_L4_IO_ADDRESS(TI81XX_TAP_BASE));
-       omap2_set_globals_control(OMAP2_L4_IO_ADDRESS(TI81XX_CTRL_BASE),
-                                 NULL);
-       omap2_set_globals_prm(OMAP2_L4_IO_ADDRESS(TI81XX_PRCM_BASE));
-       omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(TI81XX_PRCM_BASE), NULL);
+       omap2_control_base_init();
        omap3xxx_check_revision();
        ti81xx_check_features();
-       am33xx_prm_init();
-       am33xx_cm_init();
+       omap2_prcm_base_init();
        omap3xxx_voltagedomains_init();
        omap3xxx_powerdomains_init();
        ti81xx_clockdomains_init();
@@ -593,14 +584,10 @@ void __init am33xx_init_early(void)
 {
        omap2_set_globals_tap(AM335X_CLASS,
                              AM33XX_L4_WK_IO_ADDRESS(AM33XX_TAP_BASE));
-       omap2_set_globals_control(AM33XX_L4_WK_IO_ADDRESS(AM33XX_CTRL_BASE),
-                                 NULL);
-       omap2_set_globals_prm(AM33XX_L4_WK_IO_ADDRESS(AM33XX_PRCM_BASE));
-       omap2_set_globals_cm(AM33XX_L4_WK_IO_ADDRESS(AM33XX_PRCM_BASE), NULL);
+       omap2_control_base_init();
        omap3xxx_check_revision();
        am33xx_check_features();
-       am33xx_prm_init();
-       am33xx_cm_init();
+       omap2_prcm_base_init();
        am33xx_powerdomains_init();
        am33xx_clockdomains_init();
        am33xx_hwmod_init();
@@ -619,16 +606,10 @@ void __init am43xx_init_early(void)
 {
        omap2_set_globals_tap(AM335X_CLASS,
                              AM33XX_L4_WK_IO_ADDRESS(AM33XX_TAP_BASE));
-       omap2_set_globals_control(AM33XX_L4_WK_IO_ADDRESS(AM33XX_CTRL_BASE),
-                                 NULL);
-       omap2_set_globals_prm(AM33XX_L4_WK_IO_ADDRESS(AM43XX_PRCM_BASE));
-       omap2_set_globals_cm(AM33XX_L4_WK_IO_ADDRESS(AM43XX_PRCM_BASE), NULL);
-       omap_prm_base_init();
-       omap_cm_base_init();
+       omap2_control_base_init();
        omap3xxx_check_revision();
        am33xx_check_features();
-       omap44xx_prm_init();
-       omap4_cm_init();
+       omap2_prcm_base_init();
        am43xx_powerdomains_init();
        am43xx_clockdomains_init();
        am43xx_hwmod_init();
@@ -648,19 +629,12 @@ void __init omap4430_init_early(void)
 {
        omap2_set_globals_tap(OMAP443X_CLASS,
                              OMAP2_L4_IO_ADDRESS(OMAP443X_SCM_BASE));
-       omap2_set_globals_control(OMAP2_L4_IO_ADDRESS(OMAP443X_SCM_BASE),
-                                 OMAP2_L4_IO_ADDRESS(OMAP443X_CTRL_BASE));
-       omap2_set_globals_prm(OMAP2_L4_IO_ADDRESS(OMAP4430_PRM_BASE));
-       omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(OMAP4430_CM_BASE),
-                            OMAP2_L4_IO_ADDRESS(OMAP4430_CM2_BASE));
        omap2_set_globals_prcm_mpu(OMAP2_L4_IO_ADDRESS(OMAP4430_PRCM_MPU_BASE));
-       omap_prm_base_init();
-       omap_cm_base_init();
+       omap2_control_base_init();
        omap4xxx_check_revision();
        omap4xxx_check_features();
-       omap4_cm_init();
+       omap2_prcm_base_init();
        omap4_pm_init_early();
-       omap44xx_prm_init();
        omap44xx_voltagedomains_init();
        omap44xx_powerdomains_init();
        omap44xx_clockdomains_init();
@@ -683,18 +657,11 @@ void __init omap5_init_early(void)
 {
        omap2_set_globals_tap(OMAP54XX_CLASS,
                              OMAP2_L4_IO_ADDRESS(OMAP54XX_SCM_BASE));
-       omap2_set_globals_control(OMAP2_L4_IO_ADDRESS(OMAP54XX_SCM_BASE),
-                                 OMAP2_L4_IO_ADDRESS(OMAP54XX_CTRL_BASE));
-       omap2_set_globals_prm(OMAP2_L4_IO_ADDRESS(OMAP54XX_PRM_BASE));
-       omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(OMAP54XX_CM_CORE_AON_BASE),
-                            OMAP2_L4_IO_ADDRESS(OMAP54XX_CM_CORE_BASE));
        omap2_set_globals_prcm_mpu(OMAP2_L4_IO_ADDRESS(OMAP54XX_PRCM_MPU_BASE));
+       omap2_control_base_init();
        omap4_pm_init_early();
-       omap_prm_base_init();
-       omap_cm_base_init();
-       omap44xx_prm_init();
+       omap2_prcm_base_init();
        omap5xxx_check_revision();
-       omap4_cm_init();
        omap54xx_voltagedomains_init();
        omap54xx_powerdomains_init();
        omap54xx_clockdomains_init();
@@ -715,18 +682,11 @@ void __init omap5_init_late(void)
 void __init dra7xx_init_early(void)
 {
        omap2_set_globals_tap(-1, OMAP2_L4_IO_ADDRESS(DRA7XX_TAP_BASE));
-       omap2_set_globals_control(OMAP2_L4_IO_ADDRESS(OMAP54XX_SCM_BASE),
-                                 OMAP2_L4_IO_ADDRESS(DRA7XX_CTRL_BASE));
-       omap2_set_globals_prm(OMAP2_L4_IO_ADDRESS(OMAP54XX_PRM_BASE));
-       omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(DRA7XX_CM_CORE_AON_BASE),
-                            OMAP2_L4_IO_ADDRESS(OMAP54XX_CM_CORE_BASE));
        omap2_set_globals_prcm_mpu(OMAP2_L4_IO_ADDRESS(OMAP54XX_PRCM_MPU_BASE));
+       omap2_control_base_init();
        omap4_pm_init_early();
-       omap_prm_base_init();
-       omap_cm_base_init();
-       omap44xx_prm_init();
+       omap2_prcm_base_init();
        dra7xxx_check_revision();
-       omap4_cm_init();
        dra7xx_powerdomains_init();
        dra7xx_clockdomains_init();
        dra7xx_hwmod_init();
@@ -764,7 +724,11 @@ int __init omap_clk_init(void)
        ti_clk_init_features();
 
        if (of_have_populated_dt()) {
-               ret = of_prcm_init();
+               ret = omap_control_init();
+               if (ret)
+                       return ret;
+
+               ret = omap_prcm_init();
                if (ret)
                        return ret;
 
index 78064b0d4db56be1154a1262107e26801ee0eeee..176eef6ef338267f8ab67d1adf47b49ca0cdc72a 100644 (file)
@@ -1053,7 +1053,7 @@ static void __init omap_mux_init_list(struct omap_mux_partition *partition,
                struct omap_mux *entry;
 
 #ifdef CONFIG_OMAP_MUX
-               if (!superset->muxnames || !superset->muxnames[0]) {
+               if (!superset->muxnames[0]) {
                        superset++;
                        continue;
                }
index dec2b05d184bd329cf990fef3477bfe36f1bb7cb..af2851fbcdf02e224bb196dc805500b788e0a400 100644 (file)
@@ -70,13 +70,6 @@ extern u32 rx51_secure_dispatcher(u32 idx, u32 process, u32 flag, u32 nargs,
 extern u32 rx51_secure_update_aux_cr(u32 set_bits, u32 clear_bits);
 extern u32 rx51_secure_rng_call(u32 ptr, u32 count, u32 flag);
 
-#ifdef CONFIG_OMAP4_ERRATA_I688
-extern int omap_barrier_reserve_memblock(void);
-#else
-static inline void omap_barrier_reserve_memblock(void)
-{ }
-#endif
-
 #ifdef CONFIG_SOC_HAS_REALTIME_COUNTER
 void set_cntfreq(void);
 #else
index c0d1b4b1653f0d150cb7b9b3a64a9791af04c825..ed0024dda133d8856fa05169fdd00bae7045deb6 100644 (file)
 
 #define OMAP34XX_IC_BASE       0x48200000
 
-#define OMAP3430_ISP_BASE              (L4_34XX_BASE + 0xBC000)
-#define OMAP3430_ISP_CBUFF_BASE                (OMAP3430_ISP_BASE + 0x0100)
-#define OMAP3430_ISP_CCP2_BASE         (OMAP3430_ISP_BASE + 0x0400)
-#define OMAP3430_ISP_CCDC_BASE         (OMAP3430_ISP_BASE + 0x0600)
-#define OMAP3430_ISP_HIST_BASE         (OMAP3430_ISP_BASE + 0x0A00)
-#define OMAP3430_ISP_H3A_BASE          (OMAP3430_ISP_BASE + 0x0C00)
-#define OMAP3430_ISP_PREV_BASE         (OMAP3430_ISP_BASE + 0x0E00)
-#define OMAP3430_ISP_RESZ_BASE         (OMAP3430_ISP_BASE + 0x1000)
-#define OMAP3430_ISP_SBL_BASE          (OMAP3430_ISP_BASE + 0x1200)
-#define OMAP3430_ISP_MMU_BASE          (OMAP3430_ISP_BASE + 0x1400)
-#define OMAP3430_ISP_CSI2A_REGS1_BASE  (OMAP3430_ISP_BASE + 0x1800)
-#define OMAP3430_ISP_CSIPHY2_BASE      (OMAP3430_ISP_BASE + 0x1970)
-#define OMAP3630_ISP_CSI2A_REGS2_BASE  (OMAP3430_ISP_BASE + 0x19C0)
-#define OMAP3630_ISP_CSI2C_REGS1_BASE  (OMAP3430_ISP_BASE + 0x1C00)
-#define OMAP3630_ISP_CSIPHY1_BASE      (OMAP3430_ISP_BASE + 0x1D70)
-#define OMAP3630_ISP_CSI2C_REGS2_BASE  (OMAP3430_ISP_BASE + 0x1DC0)
-
-#define OMAP3430_ISP_END               (OMAP3430_ISP_BASE         + 0x06F)
-#define OMAP3430_ISP_CBUFF_END         (OMAP3430_ISP_CBUFF_BASE   + 0x077)
-#define OMAP3430_ISP_CCP2_END          (OMAP3430_ISP_CCP2_BASE    + 0x1EF)
-#define OMAP3430_ISP_CCDC_END          (OMAP3430_ISP_CCDC_BASE    + 0x0A7)
-#define OMAP3430_ISP_HIST_END          (OMAP3430_ISP_HIST_BASE    + 0x047)
-#define OMAP3430_ISP_H3A_END           (OMAP3430_ISP_H3A_BASE     + 0x05F)
-#define OMAP3430_ISP_PREV_END          (OMAP3430_ISP_PREV_BASE    + 0x09F)
-#define OMAP3430_ISP_RESZ_END          (OMAP3430_ISP_RESZ_BASE    + 0x0AB)
-#define OMAP3430_ISP_SBL_END           (OMAP3430_ISP_SBL_BASE     + 0x0FB)
-#define OMAP3430_ISP_MMU_END           (OMAP3430_ISP_MMU_BASE     + 0x06F)
-#define OMAP3430_ISP_CSI2A_REGS1_END   (OMAP3430_ISP_CSI2A_REGS1_BASE + 0x16F)
-#define OMAP3430_ISP_CSIPHY2_END       (OMAP3430_ISP_CSIPHY2_BASE + 0x00B)
-#define OMAP3630_ISP_CSI2A_REGS2_END   (OMAP3630_ISP_CSI2A_REGS2_BASE + 0x3F)
-#define OMAP3630_ISP_CSI2C_REGS1_END   (OMAP3630_ISP_CSI2C_REGS1_BASE + 0x16F)
-#define OMAP3630_ISP_CSIPHY1_END       (OMAP3630_ISP_CSIPHY1_BASE + 0x00B)
-#define OMAP3630_ISP_CSI2C_REGS2_END   (OMAP3630_ISP_CSI2C_REGS2_BASE + 0x3F)
+#define OMAP3430_ISP_BASE      (L4_34XX_BASE + 0xBC000)
+#define OMAP3430_ISP_MMU_BASE  (OMAP3430_ISP_BASE + 0x1400)
+#define OMAP3430_ISP_BASE2     (OMAP3430_ISP_BASE + 0x1800)
 
 #define OMAP34XX_HSUSB_OTG_BASE        (L4_34XX_BASE + 0xAB000)
 #define OMAP34XX_USBTLL_BASE   (L4_34XX_BASE + 0x62000)
index 7bb116a6f86f5b88c35830c2e2b78fd291b43499..16350eefa66c893c0843836aa7f595e51369fb03 100644 (file)
@@ -51,75 +51,6 @@ static void __iomem *twd_base;
 
 #define IRQ_LOCALTIMER         29
 
-#ifdef CONFIG_OMAP4_ERRATA_I688
-/* Used to implement memory barrier on DRAM path */
-#define OMAP4_DRAM_BARRIER_VA                  0xfe600000
-
-void __iomem *dram_sync, *sram_sync;
-
-static phys_addr_t paddr;
-static u32 size;
-
-void omap_bus_sync(void)
-{
-       if (dram_sync && sram_sync) {
-               writel_relaxed(readl_relaxed(dram_sync), dram_sync);
-               writel_relaxed(readl_relaxed(sram_sync), sram_sync);
-               isb();
-       }
-}
-EXPORT_SYMBOL(omap_bus_sync);
-
-static int __init omap4_sram_init(void)
-{
-       struct device_node *np;
-       struct gen_pool *sram_pool;
-
-       np = of_find_compatible_node(NULL, NULL, "ti,omap4-mpu");
-       if (!np)
-               pr_warn("%s:Unable to allocate sram needed to handle errata I688\n",
-                       __func__);
-       sram_pool = of_get_named_gen_pool(np, "sram", 0);
-       if (!sram_pool)
-               pr_warn("%s:Unable to get sram pool needed to handle errata I688\n",
-                       __func__);
-       else
-               sram_sync = (void *)gen_pool_alloc(sram_pool, PAGE_SIZE);
-
-       return 0;
-}
-omap_arch_initcall(omap4_sram_init);
-
-/* Steal one page physical memory for barrier implementation */
-int __init omap_barrier_reserve_memblock(void)
-{
-
-       size = ALIGN(PAGE_SIZE, SZ_1M);
-       paddr = arm_memblock_steal(size, SZ_1M);
-
-       return 0;
-}
-
-void __init omap_barriers_init(void)
-{
-       struct map_desc dram_io_desc[1];
-
-       dram_io_desc[0].virtual = OMAP4_DRAM_BARRIER_VA;
-       dram_io_desc[0].pfn = __phys_to_pfn(paddr);
-       dram_io_desc[0].length = size;
-       dram_io_desc[0].type = MT_MEMORY_RW_SO;
-       iotable_init(dram_io_desc, ARRAY_SIZE(dram_io_desc));
-       dram_sync = (void __iomem *) dram_io_desc[0].virtual;
-
-       pr_info("OMAP4: Map 0x%08llx to 0x%08lx for dram barrier\n",
-               (long long) paddr, dram_io_desc[0].virtual);
-
-}
-#else
-void __init omap_barriers_init(void)
-{}
-#endif
-
 void gic_dist_disable(void)
 {
        if (gic_dist_base_addr)
index be9541e1865096bb2c8b81659dfce952cbc98eeb..166b18f515a206ab3747d4eb51d4d1677c3879a2 100644 (file)
@@ -690,6 +690,9 @@ struct dev_pm_domain omap_device_pm_domain = {
                USE_PLATFORM_PM_SLEEP_OPS
                .suspend_noirq = _od_suspend_noirq,
                .resume_noirq = _od_resume_noirq,
+               .freeze_noirq = _od_suspend_noirq,
+               .thaw_noirq = _od_resume_noirq,
+               .restore_noirq = _od_resume_noirq,
        }
 };
 
index 8eb85925e44483c5840b83a79621a40f108cc752..e2223148ba4d37a0818fc65d19ddb00bdc49d56c 100644 (file)
@@ -20,6 +20,7 @@
 #include "omap_hwmod_33xx_43xx_common_data.h"
 #include "prcm43xx.h"
 #include "omap_hwmod_common_data.h"
+#include "hdq1w.h"
 
 
 /* IP blocks */
@@ -516,6 +517,33 @@ static struct omap_hwmod am43xx_dss_rfbi_hwmod = {
        .parent_hwmod   = &am43xx_dss_core_hwmod,
 };
 
+/* HDQ1W */
+static struct omap_hwmod_class_sysconfig am43xx_hdq1w_sysc = {
+       .rev_offs       = 0x0000,
+       .sysc_offs      = 0x0014,
+       .syss_offs      = 0x0018,
+       .sysc_flags     = (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class am43xx_hdq1w_hwmod_class = {
+       .name   = "hdq1w",
+       .sysc   = &am43xx_hdq1w_sysc,
+       .reset  = &omap_hdq1w_reset,
+};
+
+static struct omap_hwmod am43xx_hdq1w_hwmod = {
+       .name           = "hdq1w",
+       .class          = &am43xx_hdq1w_hwmod_class,
+       .clkdm_name     = "l4ls_clkdm",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_offs = AM43XX_CM_PER_HDQ1W_CLKCTRL_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
+               },
+       },
+};
+
 /* Interfaces */
 static struct omap_hwmod_ocp_if am43xx_l3_main__l4_hs = {
        .master         = &am33xx_l3_main_hwmod,
@@ -790,6 +818,13 @@ static struct omap_hwmod_ocp_if am43xx_l4_ls__dss_rfbi = {
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+static struct omap_hwmod_ocp_if am43xx_l4_ls__hdq1w = {
+       .master         = &am33xx_l4_ls_hwmod,
+       .slave          = &am43xx_hdq1w_hwmod,
+       .clk            = "l4ls_gclk",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 static struct omap_hwmod_ocp_if *am43xx_hwmod_ocp_ifs[] __initdata = {
        &am33xx_l4_wkup__synctimer,
        &am43xx_l4_ls__timer8,
@@ -889,6 +924,7 @@ static struct omap_hwmod_ocp_if *am43xx_hwmod_ocp_ifs[] __initdata = {
        &am43xx_l4_ls__dss,
        &am43xx_l4_ls__dss_dispc,
        &am43xx_l4_ls__dss_rfbi,
+       &am43xx_l4_ls__hdq1w,
        NULL,
 };
 
index 16fe7a1b7a3578069746371dc789e51308cc2134..0e64c2fac0b5fad2c92af76a2042a1080108fc04 100644 (file)
@@ -1726,21 +1726,6 @@ static struct omap_hwmod_class dra7xx_timer_1ms_hwmod_class = {
        .sysc   = &dra7xx_timer_1ms_sysc,
 };
 
-static struct omap_hwmod_class_sysconfig dra7xx_timer_secure_sysc = {
-       .rev_offs       = 0x0000,
-       .sysc_offs      = 0x0010,
-       .sysc_flags     = (SYSC_HAS_EMUFREE | SYSC_HAS_RESET_STATUS |
-                          SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
-       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-                          SIDLE_SMART_WKUP),
-       .sysc_fields    = &omap_hwmod_sysc_type2,
-};
-
-static struct omap_hwmod_class dra7xx_timer_secure_hwmod_class = {
-       .name   = "timer",
-       .sysc   = &dra7xx_timer_secure_sysc,
-};
-
 static struct omap_hwmod_class_sysconfig dra7xx_timer_sysc = {
        .rev_offs       = 0x0000,
        .sysc_offs      = 0x0010,
@@ -1804,7 +1789,7 @@ static struct omap_hwmod dra7xx_timer3_hwmod = {
 /* timer4 */
 static struct omap_hwmod dra7xx_timer4_hwmod = {
        .name           = "timer4",
-       .class          = &dra7xx_timer_secure_hwmod_class,
+       .class          = &dra7xx_timer_hwmod_class,
        .clkdm_name     = "l4per_clkdm",
        .main_clk       = "timer4_gfclk_mux",
        .prcm = {
@@ -1921,6 +1906,66 @@ static struct omap_hwmod dra7xx_timer11_hwmod = {
        },
 };
 
+/* timer13 */
+static struct omap_hwmod dra7xx_timer13_hwmod = {
+       .name           = "timer13",
+       .class          = &dra7xx_timer_hwmod_class,
+       .clkdm_name     = "l4per3_clkdm",
+       .main_clk       = "timer13_gfclk_mux",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_offs = DRA7XX_CM_L4PER3_TIMER13_CLKCTRL_OFFSET,
+                       .context_offs = DRA7XX_RM_L4PER3_TIMER13_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
+               },
+       },
+};
+
+/* timer14 */
+static struct omap_hwmod dra7xx_timer14_hwmod = {
+       .name           = "timer14",
+       .class          = &dra7xx_timer_hwmod_class,
+       .clkdm_name     = "l4per3_clkdm",
+       .main_clk       = "timer14_gfclk_mux",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_offs = DRA7XX_CM_L4PER3_TIMER14_CLKCTRL_OFFSET,
+                       .context_offs = DRA7XX_RM_L4PER3_TIMER14_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
+               },
+       },
+};
+
+/* timer15 */
+static struct omap_hwmod dra7xx_timer15_hwmod = {
+       .name           = "timer15",
+       .class          = &dra7xx_timer_hwmod_class,
+       .clkdm_name     = "l4per3_clkdm",
+       .main_clk       = "timer15_gfclk_mux",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_offs = DRA7XX_CM_L4PER3_TIMER15_CLKCTRL_OFFSET,
+                       .context_offs = DRA7XX_RM_L4PER3_TIMER15_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
+               },
+       },
+};
+
+/* timer16 */
+static struct omap_hwmod dra7xx_timer16_hwmod = {
+       .name           = "timer16",
+       .class          = &dra7xx_timer_hwmod_class,
+       .clkdm_name     = "l4per3_clkdm",
+       .main_clk       = "timer16_gfclk_mux",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_offs = DRA7XX_CM_L4PER3_TIMER16_CLKCTRL_OFFSET,
+                       .context_offs = DRA7XX_RM_L4PER3_TIMER16_CONTEXT_OFFSET,
+                       .modulemode   = MODULEMODE_SWCTRL,
+               },
+       },
+};
+
 /*
  * 'uart' class
  *
@@ -3059,6 +3104,38 @@ static struct omap_hwmod_ocp_if dra7xx_l4_per1__timer11 = {
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* l4_per3 -> timer13 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__timer13 = {
+       .master         = &dra7xx_l4_per3_hwmod,
+       .slave          = &dra7xx_timer13_hwmod,
+       .clk            = "l3_iclk_div",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per3 -> timer14 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__timer14 = {
+       .master         = &dra7xx_l4_per3_hwmod,
+       .slave          = &dra7xx_timer14_hwmod,
+       .clk            = "l3_iclk_div",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per3 -> timer15 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__timer15 = {
+       .master         = &dra7xx_l4_per3_hwmod,
+       .slave          = &dra7xx_timer15_hwmod,
+       .clk            = "l3_iclk_div",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per3 -> timer16 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per3__timer16 = {
+       .master         = &dra7xx_l4_per3_hwmod,
+       .slave          = &dra7xx_timer16_hwmod,
+       .clk            = "l3_iclk_div",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* l4_per1 -> uart1 */
 static struct omap_hwmod_ocp_if dra7xx_l4_per1__uart1 = {
        .master         = &dra7xx_l4_per1_hwmod,
@@ -3295,6 +3372,10 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = {
        &dra7xx_l4_per1__timer9,
        &dra7xx_l4_per1__timer10,
        &dra7xx_l4_per1__timer11,
+       &dra7xx_l4_per3__timer13,
+       &dra7xx_l4_per3__timer14,
+       &dra7xx_l4_per3__timer15,
+       &dra7xx_l4_per3__timer16,
        &dra7xx_l4_per1__uart1,
        &dra7xx_l4_per1__uart2,
        &dra7xx_l4_per1__uart3,
index e642b079e9f313ac97876e8f74a8b10612a80b83..af11511dda50bd239dbba1aa6710d15c022e2e77 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/kernel.h>
 #include <linux/of_platform.h>
 #include <linux/ti_wilink_st.h>
-#include <linux/wl12xx.h>
 
 #include <linux/platform_data/pinctrl-single.h>
 #include <linux/platform_data/iommu-omap.h>
@@ -35,34 +34,6 @@ struct pdata_init {
 struct of_dev_auxdata omap_auxdata_lookup[];
 static struct twl4030_gpio_platform_data twl_gpio_auxdata;
 
-#if IS_ENABLED(CONFIG_WL12XX)
-
-static struct wl12xx_platform_data wl12xx __initdata;
-
-static void __init __used legacy_init_wl12xx(unsigned ref_clock,
-                                            unsigned tcxo_clock,
-                                            int gpio)
-{
-       int res;
-
-       wl12xx.board_ref_clock = ref_clock;
-       wl12xx.board_tcxo_clock = tcxo_clock;
-       wl12xx.irq = gpio_to_irq(gpio);
-
-       res = wl12xx_set_platform_data(&wl12xx);
-       if (res) {
-               pr_err("error setting wl12xx data: %d\n", res);
-               return;
-       }
-}
-#else
-static inline void legacy_init_wl12xx(unsigned ref_clock,
-                                     unsigned tcxo_clock,
-                                     int gpio)
-{
-}
-#endif
-
 #ifdef CONFIG_MACH_NOKIA_N8X0
 static void __init omap2420_n8x0_legacy_init(void)
 {
@@ -129,7 +100,6 @@ static void __init omap3_sbc_t3730_twl_init(void)
 static void __init omap3_sbc_t3730_legacy_init(void)
 {
        omap3_sbc_t3x_usb_hub_init(167, "sb-t35 usb hub");
-       legacy_init_wl12xx(WL12XX_REFCLOCK_38, 0, 136);
 }
 
 static void __init omap3_sbc_t3530_legacy_init(void)
@@ -159,14 +129,12 @@ static struct platform_device btwilink_device = {
 
 static void __init omap3_igep0020_rev_f_legacy_init(void)
 {
-       legacy_init_wl12xx(0, 0, 177);
        platform_device_register(&wl18xx_device);
        platform_device_register(&btwilink_device);
 }
 
 static void __init omap3_igep0030_rev_g_legacy_init(void)
 {
-       legacy_init_wl12xx(0, 0, 136);
        platform_device_register(&wl18xx_device);
        platform_device_register(&btwilink_device);
 }
@@ -174,12 +142,6 @@ static void __init omap3_igep0030_rev_g_legacy_init(void)
 static void __init omap3_evm_legacy_init(void)
 {
        hsmmc2_internal_input_clk();
-       legacy_init_wl12xx(WL12XX_REFCLOCK_38, 0, 149);
-}
-
-static void __init omap3_zoom_legacy_init(void)
-{
-       legacy_init_wl12xx(WL12XX_REFCLOCK_26, 0, 162);
 }
 
 static void am35xx_enable_emac_int(void)
@@ -246,7 +208,6 @@ static void __init omap3_sbc_t3517_legacy_init(void)
        am35xx_emac_reset();
        hsmmc2_internal_input_clk();
        omap3_sbc_t3517_wifi_init();
-       legacy_init_wl12xx(WL12XX_REFCLOCK_38, 0, 145);
 }
 
 static void __init am3517_evm_legacy_init(void)
@@ -288,24 +249,6 @@ static void __init omap3_tao3530_legacy_init(void)
 }
 #endif /* CONFIG_ARCH_OMAP3 */
 
-#ifdef CONFIG_ARCH_OMAP4
-static void __init omap4_sdp_legacy_init(void)
-{
-       legacy_init_wl12xx(WL12XX_REFCLOCK_26,
-                          WL12XX_TCXOCLOCK_26, 53);
-}
-
-static void __init omap4_panda_legacy_init(void)
-{
-       legacy_init_wl12xx(WL12XX_REFCLOCK_38, 0, 53);
-}
-
-static void __init var_som_om44_legacy_init(void)
-{
-       legacy_init_wl12xx(WL12XX_REFCLOCK_38, 0, 41);
-}
-#endif
-
 #if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5)
 static struct iommu_platform_data omap4_iommu_pdata = {
        .reset_name = "mmu_cache",
@@ -314,13 +257,6 @@ static struct iommu_platform_data omap4_iommu_pdata = {
 };
 #endif
 
-#ifdef CONFIG_SOC_AM33XX
-static void __init am335x_evmsk_legacy_init(void)
-{
-       legacy_init_wl12xx(WL12XX_REFCLOCK_38, 0, 31);
-}
-#endif
-
 #ifdef CONFIG_SOC_OMAP5
 static void __init omap5_uevm_legacy_init(void)
 {
@@ -421,19 +357,9 @@ static struct pdata_init pdata_quirks[] __initdata = {
        { "isee,omap3-igep0020-rev-f", omap3_igep0020_rev_f_legacy_init, },
        { "isee,omap3-igep0030-rev-g", omap3_igep0030_rev_g_legacy_init, },
        { "ti,omap3-evm-37xx", omap3_evm_legacy_init, },
-       { "ti,omap3-zoom3", omap3_zoom_legacy_init, },
        { "ti,am3517-evm", am3517_evm_legacy_init, },
        { "technexion,omap3-tao3530", omap3_tao3530_legacy_init, },
 #endif
-#ifdef CONFIG_ARCH_OMAP4
-       { "ti,omap4-sdp", omap4_sdp_legacy_init, },
-       { "ti,omap4-panda", omap4_panda_legacy_init, },
-       { "variscite,var-dvk-om44", var_som_om44_legacy_init, },
-       { "variscite,var-stk-om44", var_som_om44_legacy_init, },
-#endif
-#ifdef CONFIG_SOC_AM33XX
-       { "ti,am335x-evmsk", am335x_evmsk_legacy_init, },
-#endif
 #ifdef CONFIG_SOC_OMAP5
        { "ti,omap5-uevm", omap5_uevm_legacy_init, },
 #endif
index fe01c5a03aa242ccf3abd62bdd8d65e84ae29a27..b1aad7e1426c62e9a394b72a09dfc48ab361f348 100644 (file)
@@ -75,9 +75,9 @@ static int omap2_enter_full_retention(void)
 
        /* Clear old wake-up events */
        /* REVISIT: These write to reserved bits? */
-       omap2xxx_prm_clear_mod_irqs(CORE_MOD, PM_WKST1, ~0);
-       omap2xxx_prm_clear_mod_irqs(CORE_MOD, OMAP24XX_PM_WKST2, ~0);
-       omap2xxx_prm_clear_mod_irqs(WKUP_MOD, PM_WKST, ~0);
+       omap_prm_clear_mod_irqs(CORE_MOD, PM_WKST1, ~0);
+       omap_prm_clear_mod_irqs(CORE_MOD, OMAP24XX_PM_WKST2, ~0);
+       omap_prm_clear_mod_irqs(WKUP_MOD, PM_WKST, ~0);
 
        pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_RET);
        pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
@@ -104,18 +104,16 @@ no_sleep:
        clk_enable(osc_ck);
 
        /* clear CORE wake-up events */
-       omap2xxx_prm_clear_mod_irqs(CORE_MOD, PM_WKST1, ~0);
-       omap2xxx_prm_clear_mod_irqs(CORE_MOD, OMAP24XX_PM_WKST2, ~0);
+       omap_prm_clear_mod_irqs(CORE_MOD, PM_WKST1, ~0);
+       omap_prm_clear_mod_irqs(CORE_MOD, OMAP24XX_PM_WKST2, ~0);
 
        /* wakeup domain events - bit 1: GPT1, bit5 GPIO */
-       omap2xxx_prm_clear_mod_irqs(WKUP_MOD, PM_WKST, 0x4 | 0x1);
+       omap_prm_clear_mod_irqs(WKUP_MOD, PM_WKST, 0x4 | 0x1);
 
        /* MPU domain wake events */
-       omap2xxx_prm_clear_mod_irqs(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET,
-                                   0x1);
+       omap_prm_clear_mod_irqs(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET, 0x1);
 
-       omap2xxx_prm_clear_mod_irqs(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET,
-                                   0x20);
+       omap_prm_clear_mod_irqs(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET, 0x20);
 
        pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON);
        pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_ON);
@@ -143,9 +141,9 @@ static void omap2_enter_mpu_retention(void)
         * it is in retention mode. */
        if (omap2_allow_mpu_retention()) {
                /* REVISIT: These write to reserved bits? */
-               omap2xxx_prm_clear_mod_irqs(CORE_MOD, PM_WKST1, ~0);
-               omap2xxx_prm_clear_mod_irqs(CORE_MOD, OMAP24XX_PM_WKST2, ~0);
-               omap2xxx_prm_clear_mod_irqs(WKUP_MOD, PM_WKST, ~0);
+               omap_prm_clear_mod_irqs(CORE_MOD, PM_WKST1, ~0);
+               omap_prm_clear_mod_irqs(CORE_MOD, OMAP24XX_PM_WKST2, ~0);
+               omap_prm_clear_mod_irqs(WKUP_MOD, PM_WKST, ~0);
 
                /* Try to enter MPU retention */
                pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
index 88721df6001d0ef7741aa377ef853dc89cb67bca..87b98bf92366f4f816ca4f53a32ecae305930016 100644 (file)
@@ -137,9 +137,8 @@ static irqreturn_t _prcm_int_handle_io(int irq, void *unused)
 {
        int c;
 
-       c = omap3xxx_prm_clear_mod_irqs(WKUP_MOD, 1,
-                                       ~(OMAP3430_ST_IO_MASK |
-                                         OMAP3430_ST_IO_CHAIN_MASK));
+       c = omap_prm_clear_mod_irqs(WKUP_MOD, 1, OMAP3430_ST_IO_MASK |
+                                   OMAP3430_ST_IO_CHAIN_MASK);
 
        return c ? IRQ_HANDLED : IRQ_NONE;
 }
@@ -153,14 +152,13 @@ static irqreturn_t _prcm_int_handle_wakeup(int irq, void *unused)
         * these are handled in a separate handler to avoid acking
         * IO events before parsing in mux code
         */
-       c = omap3xxx_prm_clear_mod_irqs(WKUP_MOD, 1,
-                                       OMAP3430_ST_IO_MASK |
-                                       OMAP3430_ST_IO_CHAIN_MASK);
-       c += omap3xxx_prm_clear_mod_irqs(CORE_MOD, 1, 0);
-       c += omap3xxx_prm_clear_mod_irqs(OMAP3430_PER_MOD, 1, 0);
+       c = omap_prm_clear_mod_irqs(WKUP_MOD, 1, ~(OMAP3430_ST_IO_MASK |
+                                                  OMAP3430_ST_IO_CHAIN_MASK));
+       c += omap_prm_clear_mod_irqs(CORE_MOD, 1, ~0);
+       c += omap_prm_clear_mod_irqs(OMAP3430_PER_MOD, 1, ~0);
        if (omap_rev() > OMAP3430_REV_ES1_0) {
-               c += omap3xxx_prm_clear_mod_irqs(CORE_MOD, 3, 0);
-               c += omap3xxx_prm_clear_mod_irqs(OMAP3430ES2_USBHOST_MOD, 1, 0);
+               c += omap_prm_clear_mod_irqs(CORE_MOD, 3, ~0);
+               c += omap_prm_clear_mod_irqs(OMAP3430ES2_USBHOST_MOD, 1, ~0);
        }
 
        return c ? IRQ_HANDLED : IRQ_NONE;
index 6163d66102a3561890240487a592964874cb260c..6ae0b3a1781e99deee4f2cdc8699a4f434ad7fa3 100644 (file)
@@ -518,6 +518,26 @@ struct omap_prcm_irq_setup {
        .priority = _priority                           \
        }
 
+/**
+ * struct omap_prcm_init_data - PRCM driver init data
+ * @index: clock memory mapping index to be used
+ * @mem: IO mem pointer for this module
+ * @offset: module base address offset from the IO base
+ * @flags: PRCM module init flags
+ * @device_inst_offset: device instance offset within the module address space
+ * @init: low level PRCM init function for this module
+ * @np: device node for this PRCM module
+ */
+struct omap_prcm_init_data {
+       int index;
+       void __iomem *mem;
+       s16 offset;
+       u16 flags;
+       s32 device_inst_offset;
+       int (*init)(const struct omap_prcm_init_data *data);
+       struct device_node *np;
+};
+
 extern void omap_prcm_irq_cleanup(void);
 extern int omap_prcm_register_chain_handler(
        struct omap_prcm_irq_setup *irq_setup);
index ad7b3e9977f8fa520b0281e3e9b876e98f7e98b3..48df3b55057e4d346076ada24e6e7404a13a117a 100644 (file)
 #define AM43XX_CM_PER_USB_OTG_SS1_CLKCTRL_OFFSET        0x0268
 #define AM43XX_CM_PER_USBPHYOCP2SCP1_CLKCTRL_OFFSET    0x05C0
 #define AM43XX_CM_PER_DSS_CLKCTRL_OFFSET               0x0a20
+#define AM43XX_CM_PER_HDQ1W_CLKCTRL_OFFSET             0x04a0
 
 #endif
index b9061a6a2db8998314cf83dc0aa98dab2899ce43..233bc84fbc0e4ee13248a388a76e7c0270b819a4 100644 (file)
@@ -19,8 +19,9 @@
 extern void __iomem *prm_base;
 extern u16 prm_features;
 extern void omap2_set_globals_prm(void __iomem *prm);
-int of_prcm_init(void);
-void omap3_prcm_legacy_iomaps_init(void);
+int omap_prcm_init(void);
+int omap2_prm_base_init(void);
+int omap2_prcm_base_init(void);
 # endif
 
 /*
@@ -28,9 +29,11 @@ void omap3_prcm_legacy_iomaps_init(void);
  *
  * PRM_HAS_IO_WAKEUP: has IO wakeup capability
  * PRM_HAS_VOLTAGE: has voltage domains
+ * PRM_IRQ_DEFAULT: use default irq number for PRM irq
  */
-#define PRM_HAS_IO_WAKEUP      (1 << 0)
-#define PRM_HAS_VOLTAGE                (1 << 1)
+#define PRM_HAS_IO_WAKEUP      BIT(0)
+#define PRM_HAS_VOLTAGE                BIT(1)
+#define PRM_IRQ_DEFAULT                BIT(2)
 
 /*
  * MAX_MODULE_SOFTRESET_WAIT: Maximum microseconds to wait for OMAP
@@ -146,6 +149,9 @@ struct prm_ll_data {
        int (*is_hardreset_asserted)(u8 shift, u8 part, s16 prm_mod,
                                     u16 offset);
        void (*reset_system)(void);
+       int (*clear_mod_irqs)(s16 module, u8 regs, u32 wkst_mask);
+       u32 (*vp_check_txdone)(u8 vp_id);
+       void (*vp_clear_txdone)(u8 vp_id);
 };
 
 extern int prm_register(struct prm_ll_data *pld);
@@ -161,6 +167,19 @@ extern void prm_clear_context_loss_flags_old(u8 part, s16 inst, u16 idx);
 void omap_prm_reset_system(void);
 
 void omap_prm_reconfigure_io_chain(void);
+int omap_prm_clear_mod_irqs(s16 module, u8 regs, u32 wkst_mask);
+
+/*
+ * Voltage Processor (VP) identifiers
+ */
+#define OMAP3_VP_VDD_MPU_ID    0
+#define OMAP3_VP_VDD_CORE_ID   1
+#define OMAP4_VP_VDD_CORE_ID   0
+#define OMAP4_VP_VDD_IVA_ID    1
+#define OMAP4_VP_VDD_MPU_ID    2
+
+u32 omap_prm_vp_check_txdone(u8 vp_id);
+void omap_prm_vp_clear_txdone(u8 vp_id);
 
 #endif
 
index af0f15278fc2afc2d7480da370cba6cafac9d2f6..752018ce129ca953669686445371143962e12376 100644 (file)
@@ -123,13 +123,14 @@ static void omap2xxx_prm_dpll_reset(void)
  * Clears wakeup status bits for a given module, so that the device can
  * re-enter idle.
  */
-void omap2xxx_prm_clear_mod_irqs(s16 module, u8 regs, u32 wkst_mask)
+static int omap2xxx_prm_clear_mod_irqs(s16 module, u8 regs, u32 wkst_mask)
 {
        u32 wkst;
 
        wkst = omap2_prm_read_mod_reg(module, regs);
        wkst &= wkst_mask;
        omap2_prm_write_mod_reg(wkst, module, regs);
+       return 0;
 }
 
 int omap2xxx_clkdm_sleep(struct clockdomain *clkdm)
@@ -216,9 +217,10 @@ static struct prm_ll_data omap2xxx_prm_ll_data = {
        .deassert_hardreset = &omap2_prm_deassert_hardreset,
        .is_hardreset_asserted = &omap2_prm_is_hardreset_asserted,
        .reset_system = &omap2xxx_prm_dpll_reset,
+       .clear_mod_irqs = &omap2xxx_prm_clear_mod_irqs,
 };
 
-int __init omap2xxx_prm_init(void)
+int __init omap2xxx_prm_init(const struct omap_prcm_init_data *data)
 {
        return prm_register(&omap2xxx_prm_ll_data);
 }
index 1d51643062f7957dec8b9be7a66fcbf11d3e5de9..9008a9e55a1ac750535034c0ce48b6c9f8413eaf 100644 (file)
 extern int omap2xxx_clkdm_sleep(struct clockdomain *clkdm);
 extern int omap2xxx_clkdm_wakeup(struct clockdomain *clkdm);
 
-void omap2xxx_prm_clear_mod_irqs(s16 module, u8 regs, u32 wkst_mask);
-
-extern int __init omap2xxx_prm_init(void);
+int __init omap2xxx_prm_init(const struct omap_prcm_init_data *data);
 
 #endif
 
index 02f628601b098799e2b73354215ac33a411abe3b..dcb5001d77da3d487c9bfb8674f4de6d3aab9db2 100644 (file)
@@ -378,7 +378,7 @@ static struct prm_ll_data am33xx_prm_ll_data = {
        .reset_system                   = am33xx_prm_global_warm_sw_reset,
 };
 
-int __init am33xx_prm_init(void)
+int __init am33xx_prm_init(const struct omap_prcm_init_data *data)
 {
        return prm_register(&am33xx_prm_ll_data);
 }
index 98ac41f271da3460378a11a44468504f11ed0f32..2bc4ec52ba78da3d17d33be25936db3a91cf5f1e 100644 (file)
 #define AM33XX_PM_CEFUSE_PWRSTST               AM33XX_PRM_REGADDR(AM33XX_PRM_CEFUSE_MOD, 0x0004)
 
 #ifndef __ASSEMBLER__
-int am33xx_prm_init(void);
+int am33xx_prm_init(const struct omap_prcm_init_data *data);
 
 #endif /* ASSEMBLER */
 #endif
index 5713bbdf83bc57ac7314f6e27455e3851772bc09..62680aad212666af7f07131546ff1e9bc01c2572 100644 (file)
@@ -29,6 +29,7 @@
 #include "prm-regbits-34xx.h"
 #include "cm3xxx.h"
 #include "cm-regbits-34xx.h"
+#include "clock.h"
 
 static void omap3xxx_prm_read_pending_irqs(unsigned long *events);
 static void omap3xxx_prm_ocp_barrier(void);
@@ -96,7 +97,7 @@ static struct omap3_vp omap3_vp[] = {
 
 #define MAX_VP_ID ARRAY_SIZE(omap3_vp);
 
-u32 omap3_prm_vp_check_txdone(u8 vp_id)
+static u32 omap3_prm_vp_check_txdone(u8 vp_id)
 {
        struct omap3_vp *vp = &omap3_vp[vp_id];
        u32 irqstatus;
@@ -106,7 +107,7 @@ u32 omap3_prm_vp_check_txdone(u8 vp_id)
        return irqstatus & vp->tranxdone_status;
 }
 
-void omap3_prm_vp_clear_txdone(u8 vp_id)
+static void omap3_prm_vp_clear_txdone(u8 vp_id)
 {
        struct omap3_vp *vp = &omap3_vp[vp_id];
 
@@ -217,7 +218,7 @@ static void omap3xxx_prm_restore_irqen(u32 *saved_mask)
  * omap3xxx_prm_clear_mod_irqs - clear wake-up events from PRCM interrupt
  * @module: PRM module to clear wakeups from
  * @regs: register set to clear, 1 or 3
- * @ignore_bits: wakeup status bits to ignore
+ * @wkst_mask: wkst bits to clear
  *
  * The purpose of this function is to clear any wake-up events latched
  * in the PRCM PM_WKST_x registers. It is possible that a wake-up event
@@ -226,7 +227,7 @@ static void omap3xxx_prm_restore_irqen(u32 *saved_mask)
  * that any peripheral wake-up events occurring while attempting to
  * clear the PM_WKST_x are detected and cleared.
  */
-int omap3xxx_prm_clear_mod_irqs(s16 module, u8 regs, u32 ignore_bits)
+static int omap3xxx_prm_clear_mod_irqs(s16 module, u8 regs, u32 wkst_mask)
 {
        u32 wkst, fclk, iclk, clken;
        u16 wkst_off = (regs == 3) ? OMAP3430ES2_PM_WKST3 : PM_WKST1;
@@ -238,7 +239,7 @@ int omap3xxx_prm_clear_mod_irqs(s16 module, u8 regs, u32 ignore_bits)
 
        wkst = omap2_prm_read_mod_reg(module, wkst_off);
        wkst &= omap2_prm_read_mod_reg(module, grpsel_off);
-       wkst &= ~ignore_bits;
+       wkst &= wkst_mask;
        if (wkst) {
                iclk = omap2_cm_read_mod_reg(module, iclk_off);
                fclk = omap2_cm_read_mod_reg(module, fclk_off);
@@ -254,7 +255,7 @@ int omap3xxx_prm_clear_mod_irqs(s16 module, u8 regs, u32 ignore_bits)
                        omap2_cm_set_mod_reg_bits(clken, module, fclk_off);
                        omap2_prm_write_mod_reg(wkst, module, wkst_off);
                        wkst = omap2_prm_read_mod_reg(module, wkst_off);
-                       wkst &= ~ignore_bits;
+                       wkst &= wkst_mask;
                        c++;
                }
                omap2_cm_write_mod_reg(iclk, module, iclk_off);
@@ -664,10 +665,15 @@ static struct prm_ll_data omap3xxx_prm_ll_data = {
        .deassert_hardreset = &omap2_prm_deassert_hardreset,
        .is_hardreset_asserted = &omap2_prm_is_hardreset_asserted,
        .reset_system = &omap3xxx_prm_dpll3_reset,
+       .clear_mod_irqs = &omap3xxx_prm_clear_mod_irqs,
+       .vp_check_txdone = &omap3_prm_vp_check_txdone,
+       .vp_clear_txdone = &omap3_prm_vp_clear_txdone,
 };
 
-int __init omap3xxx_prm_init(void)
+int __init omap3xxx_prm_init(const struct omap_prcm_init_data *data)
 {
+       omap2_clk_legacy_provider_init(TI_CLKM_PRM,
+                                      prm_base + OMAP3430_IVA2_MOD);
        if (omap3_has_io_wakeup())
                prm_features |= PRM_HAS_IO_WAKEUP;
 
index ed8a3d8b739a87578416775bf135fc8ce139a0de..5f095eec339c0627fc6c93faff62201d5990d4ca 100644 (file)
 
 #ifndef __ASSEMBLER__
 
-/* OMAP3-specific VP functions */
-u32 omap3_prm_vp_check_txdone(u8 vp_id);
-void omap3_prm_vp_clear_txdone(u8 vp_id);
-
 /*
  * OMAP3 access functions for voltage controller (VC) and
  * voltage proccessor (VP) in the PRM.
@@ -144,8 +140,7 @@ extern u32 omap3_prm_vcvp_read(u8 offset);
 extern void omap3_prm_vcvp_write(u32 val, u8 offset);
 extern u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset);
 
-extern int __init omap3xxx_prm_init(void);
-int omap3xxx_prm_clear_mod_irqs(s16 module, u8 regs, u32 ignore_bits);
+int __init omap3xxx_prm_init(const struct omap_prcm_init_data *data);
 void omap3xxx_prm_iva_idle(void);
 void omap3_prm_reset_modem(void);
 int omap3xxx_prm_clear_global_cold_reset(void);
index d6d6bc39e05c962d80b3b777b50c1d802764af0b..4541700f743a871fbd139512856c1de327745d8b 100644 (file)
@@ -138,7 +138,7 @@ static struct omap4_vp omap4_vp[] = {
        },
 };
 
-u32 omap4_prm_vp_check_txdone(u8 vp_id)
+static u32 omap4_prm_vp_check_txdone(u8 vp_id)
 {
        struct omap4_vp *vp = &omap4_vp[vp_id];
        u32 irqstatus;
@@ -149,7 +149,7 @@ u32 omap4_prm_vp_check_txdone(u8 vp_id)
        return irqstatus & vp->tranxdone_status;
 }
 
-void omap4_prm_vp_clear_txdone(u8 vp_id)
+static void omap4_prm_vp_clear_txdone(u8 vp_id)
 {
        struct omap4_vp *vp = &omap4_vp[vp_id];
 
@@ -699,29 +699,31 @@ static struct prm_ll_data omap44xx_prm_ll_data = {
        .deassert_hardreset     = omap4_prminst_deassert_hardreset,
        .is_hardreset_asserted  = omap4_prminst_is_hardreset_asserted,
        .reset_system           = omap4_prminst_global_warm_sw_reset,
+       .vp_check_txdone        = omap4_prm_vp_check_txdone,
+       .vp_clear_txdone        = omap4_prm_vp_clear_txdone,
 };
 
-int __init omap44xx_prm_init(void)
+static const struct omap_prcm_init_data *prm_init_data;
+
+int __init omap44xx_prm_init(const struct omap_prcm_init_data *data)
 {
-       if (cpu_is_omap44xx() || soc_is_omap54xx() || soc_is_dra7xx())
+       omap_prm_base_init();
+
+       prm_init_data = data;
+
+       if (data->flags & PRM_HAS_IO_WAKEUP)
                prm_features |= PRM_HAS_IO_WAKEUP;
 
-       if (!soc_is_dra7xx())
+       if (data->flags & PRM_HAS_VOLTAGE)
                prm_features |= PRM_HAS_VOLTAGE;
 
+       omap4_prminst_set_prm_dev_inst(data->device_inst_offset);
+
        return prm_register(&omap44xx_prm_ll_data);
 }
 
-static const struct of_device_id omap_prm_dt_match_table[] = {
-       { .compatible = "ti,omap4-prm" },
-       { .compatible = "ti,omap5-prm" },
-       { .compatible = "ti,dra7-prm" },
-       { }
-};
-
 static int omap44xx_prm_late_init(void)
 {
-       struct device_node *np;
        int irq_num;
 
        if (!(prm_features & PRM_HAS_IO_WAKEUP))
@@ -731,31 +733,23 @@ static int omap44xx_prm_late_init(void)
        if (!of_have_populated_dt())
                return 0;
 
-       np = of_find_matching_node(NULL, omap_prm_dt_match_table);
-
-       if (!np) {
-               /* Default loaded up with OMAP4 values */
-               if (!cpu_is_omap44xx())
-                       return 0;
-       } else {
-               irq_num = of_irq_get(np, 0);
-               /*
-                * Already have OMAP4 IRQ num. For all other platforms, we need
-                * IRQ numbers from DT
-                */
-               if (irq_num < 0 && !cpu_is_omap44xx()) {
-                       if (irq_num == -EPROBE_DEFER)
-                               return irq_num;
-
-                       /* Have nothing to do */
-                       return 0;
-               }
-
-               /* Once OMAP4 DT is filled as well */
-               if (irq_num >= 0) {
-                       omap4_prcm_irq_setup.irq = irq_num;
-                       omap4_prcm_irq_setup.xlate_irq = NULL;
-               }
+       irq_num = of_irq_get(prm_init_data->np, 0);
+       /*
+        * Already have OMAP4 IRQ num. For all other platforms, we need
+        * IRQ numbers from DT
+        */
+       if (irq_num < 0 && !(prm_init_data->flags & PRM_IRQ_DEFAULT)) {
+               if (irq_num == -EPROBE_DEFER)
+                       return irq_num;
+
+               /* Have nothing to do */
+               return 0;
+       }
+
+       /* Once OMAP4 DT is filled as well */
+       if (irq_num >= 0) {
+               omap4_prcm_irq_setup.irq = irq_num;
+               omap4_prcm_irq_setup.xlate_irq = NULL;
        }
 
        omap44xx_prm_enable_io_wakeup();
index 7db2422faa16e8b788901c8f1a8396226a0e1123..efd6035d0871d4fdcf211c69adabec288d20f414 100644 (file)
@@ -26,7 +26,6 @@
 #define __ARCH_ARM_MACH_OMAP2_PRM44XX_H
 
 #include "prm44xx_54xx.h"
-#include "prcm-common.h"
 #include "prm.h"
 
 #define OMAP4430_PRM_BASE              0x4a306000
index 714329565b90b70e4509a8b4ae4583c223afdc9a..3f139ebc839895137ff5488dfb07b0b0b81047cf 100644 (file)
 #ifndef __ARCH_ARM_MACH_OMAP2_PRM44XX_54XX_H
 #define __ARCH_ARM_MACH_OMAP2_PRM44XX_54XX_H
 
+#include "prcm-common.h"
+
 /* Function prototypes */
 #ifndef __ASSEMBLER__
 
-/* OMAP4/OMAP5-specific VP functions */
-u32 omap4_prm_vp_check_txdone(u8 vp_id);
-void omap4_prm_vp_clear_txdone(u8 vp_id);
-
 /*
  * OMAP4/OMAP5 access functions for voltage controller (VC) and
  * voltage proccessor (VP) in the PRM.
@@ -38,7 +36,7 @@ extern u32 omap4_prm_vcvp_read(u8 offset);
 extern void omap4_prm_vcvp_write(u32 val, u8 offset);
 extern u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset);
 
-extern int __init omap44xx_prm_init(void);
+int __init omap44xx_prm_init(const struct omap_prcm_init_data *data);
 
 #endif
 
index e4411010309c566cb708ef1a39dad9a01d29c81b..1eb22ff087dc207bc8ce4ec57e012c142415f38c 100644 (file)
@@ -22,7 +22,6 @@
 #define __ARCH_ARM_MACH_OMAP2_PRM54XX_H
 
 #include "prm44xx_54xx.h"
-#include "prcm-common.h"
 #include "prm.h"
 
 #define OMAP54XX_PRM_BASE              0x4ae06000
index 4bb50fbf29bebb5f546edf866665dcd29bb11d36..cc1e6a2b97f66af3b9ea53f0a1a57115aaac77a4 100644 (file)
@@ -22,8 +22,8 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_PRM7XX_H
 #define __ARCH_ARM_MACH_OMAP2_PRM7XX_H
 
-#include "prm44xx_54xx.h"
 #include "prcm-common.h"
+#include "prm44xx_54xx.h"
 #include "prm.h"
 
 #define DRA7XX_PRM_BASE                0x4ae06000
index bfaa7ba595cc832ec7783e759db4425c5e1e58c0..7add7994dbfcf01496eec5182500833ab26cdd5f 100644 (file)
 #include "prm2xxx_3xxx.h"
 #include "prm2xxx.h"
 #include "prm3xxx.h"
+#include "prm33xx.h"
 #include "prm44xx.h"
+#include "prm54xx.h"
+#include "prm7xx.h"
+#include "prcm43xx.h"
 #include "common.h"
 #include "clock.h"
 #include "cm.h"
@@ -533,6 +537,61 @@ void omap_prm_reset_system(void)
                cpu_relax();
 }
 
+/**
+ * omap_prm_clear_mod_irqs - clear wake-up events from PRCM interrupt
+ * @module: PRM module to clear wakeups from
+ * @regs: register to clear
+ * @wkst_mask: wkst bits to clear
+ *
+ * Clears any wakeup events for the module and register set defined.
+ * Uses SoC specific implementation to do the actual wakeup status
+ * clearing.
+ */
+int omap_prm_clear_mod_irqs(s16 module, u8 regs, u32 wkst_mask)
+{
+       if (!prm_ll_data->clear_mod_irqs) {
+               WARN_ONCE(1, "prm: %s: no mapping function defined\n",
+                         __func__);
+               return -EINVAL;
+       }
+
+       return prm_ll_data->clear_mod_irqs(module, regs, wkst_mask);
+}
+
+/**
+ * omap_prm_vp_check_txdone - check voltage processor TX done status
+ *
+ * Checks if voltage processor transmission has been completed.
+ * Returns non-zero if a transmission has completed, 0 otherwise.
+ */
+u32 omap_prm_vp_check_txdone(u8 vp_id)
+{
+       if (!prm_ll_data->vp_check_txdone) {
+               WARN_ONCE(1, "prm: %s: no mapping function defined\n",
+                         __func__);
+               return 0;
+       }
+
+       return prm_ll_data->vp_check_txdone(vp_id);
+}
+
+/**
+ * omap_prm_vp_clear_txdone - clears voltage processor TX done status
+ *
+ * Clears the status bit for completed voltage processor transmission
+ * returned by prm_vp_check_txdone.
+ */
+void omap_prm_vp_clear_txdone(u8 vp_id)
+{
+       if (!prm_ll_data->vp_clear_txdone) {
+               WARN_ONCE(1, "prm: %s: no mapping function defined\n",
+                         __func__);
+               return;
+       }
+
+       prm_ll_data->vp_clear_txdone(vp_id);
+}
+
 /**
  * prm_register - register per-SoC low-level data with the PRM
  * @pld: low-level per-SoC OMAP PRM data & function pointers to register
@@ -578,78 +637,175 @@ int prm_unregister(struct prm_ll_data *pld)
        return 0;
 }
 
-static const struct of_device_id omap_prcm_dt_match_table[] = {
-       { .compatible = "ti,am3-prcm" },
-       { .compatible = "ti,am3-scrm" },
-       { .compatible = "ti,am4-prcm" },
-       { .compatible = "ti,am4-scrm" },
-       { .compatible = "ti,dm814-prcm" },
-       { .compatible = "ti,dm814-scrm" },
-       { .compatible = "ti,dm816-prcm" },
-       { .compatible = "ti,dm816-scrm" },
-       { .compatible = "ti,omap2-prcm" },
-       { .compatible = "ti,omap2-scrm" },
-       { .compatible = "ti,omap3-prm" },
-       { .compatible = "ti,omap3-cm" },
-       { .compatible = "ti,omap3-scrm" },
-       { .compatible = "ti,omap4-cm1" },
-       { .compatible = "ti,omap4-prm" },
-       { .compatible = "ti,omap4-cm2" },
-       { .compatible = "ti,omap4-scrm" },
-       { .compatible = "ti,omap5-prm" },
-       { .compatible = "ti,omap5-cm-core-aon" },
-       { .compatible = "ti,omap5-scrm" },
-       { .compatible = "ti,omap5-cm-core" },
-       { .compatible = "ti,dra7-prm" },
-       { .compatible = "ti,dra7-cm-core-aon" },
-       { .compatible = "ti,dra7-cm-core" },
-       { }
+#ifdef CONFIG_ARCH_OMAP2
+static struct omap_prcm_init_data omap2_prm_data __initdata = {
+       .index = TI_CLKM_PRM,
+       .init = omap2xxx_prm_init,
 };
+#endif
+
+#ifdef CONFIG_ARCH_OMAP3
+static struct omap_prcm_init_data omap3_prm_data __initdata = {
+       .index = TI_CLKM_PRM,
+       .init = omap3xxx_prm_init,
 
-static struct clk_hw_omap memmap_dummy_ck = {
-       .flags = MEMMAP_ADDRESSING,
+       /*
+        * IVA2 offset is a negative value, must offset the prm_base
+        * address by this to get it to positive
+        */
+       .offset = -OMAP3430_IVA2_MOD,
 };
+#endif
 
-static u32 prm_clk_readl(void __iomem *reg)
-{
-       return omap2_clk_readl(&memmap_dummy_ck, reg);
-}
+#if defined(CONFIG_SOC_AM33XX) || defined(CONFIG_SOC_TI81XX)
+static struct omap_prcm_init_data am3_prm_data __initdata = {
+       .index = TI_CLKM_PRM,
+       .init = am33xx_prm_init,
+};
+#endif
+
+#ifdef CONFIG_ARCH_OMAP4
+static struct omap_prcm_init_data omap4_prm_data __initdata = {
+       .index = TI_CLKM_PRM,
+       .init = omap44xx_prm_init,
+       .device_inst_offset = OMAP4430_PRM_DEVICE_INST,
+       .flags = PRM_HAS_IO_WAKEUP | PRM_HAS_VOLTAGE | PRM_IRQ_DEFAULT,
+};
+#endif
+
+#ifdef CONFIG_SOC_OMAP5
+static struct omap_prcm_init_data omap5_prm_data __initdata = {
+       .index = TI_CLKM_PRM,
+       .init = omap44xx_prm_init,
+       .device_inst_offset = OMAP54XX_PRM_DEVICE_INST,
+       .flags = PRM_HAS_IO_WAKEUP | PRM_HAS_VOLTAGE,
+};
+#endif
+
+#ifdef CONFIG_SOC_DRA7XX
+static struct omap_prcm_init_data dra7_prm_data __initdata = {
+       .index = TI_CLKM_PRM,
+       .init = omap44xx_prm_init,
+       .device_inst_offset = DRA7XX_PRM_DEVICE_INST,
+       .flags = PRM_HAS_IO_WAKEUP,
+};
+#endif
 
-static void prm_clk_writel(u32 val, void __iomem *reg)
-{
-       omap2_clk_writel(val, &memmap_dummy_ck, reg);
-}
+#ifdef CONFIG_SOC_AM43XX
+static struct omap_prcm_init_data am4_prm_data __initdata = {
+       .index = TI_CLKM_PRM,
+       .init = omap44xx_prm_init,
+       .device_inst_offset = AM43XX_PRM_DEVICE_INST,
+};
+#endif
 
-static struct ti_clk_ll_ops omap_clk_ll_ops = {
-       .clk_readl = prm_clk_readl,
-       .clk_writel = prm_clk_writel,
+#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5)
+static struct omap_prcm_init_data scrm_data __initdata = {
+       .index = TI_CLKM_SCRM,
+};
+#endif
+
+static const struct of_device_id omap_prcm_dt_match_table[] __initconst = {
+#ifdef CONFIG_SOC_AM33XX
+       { .compatible = "ti,am3-prcm", .data = &am3_prm_data },
+#endif
+#ifdef CONFIG_SOC_AM43XX
+       { .compatible = "ti,am4-prcm", .data = &am4_prm_data },
+#endif
+#ifdef CONFIG_SOC_TI81XX
+       { .compatible = "ti,dm814-prcm", .data = &am3_prm_data },
+       { .compatible = "ti,dm816-prcm", .data = &am3_prm_data },
+#endif
+#ifdef CONFIG_ARCH_OMAP2
+       { .compatible = "ti,omap2-prcm", .data = &omap2_prm_data },
+#endif
+#ifdef CONFIG_ARCH_OMAP3
+       { .compatible = "ti,omap3-prm", .data = &omap3_prm_data },
+#endif
+#ifdef CONFIG_ARCH_OMAP4
+       { .compatible = "ti,omap4-prm", .data = &omap4_prm_data },
+       { .compatible = "ti,omap4-scrm", .data = &scrm_data },
+#endif
+#ifdef CONFIG_SOC_OMAP5
+       { .compatible = "ti,omap5-prm", .data = &omap5_prm_data },
+       { .compatible = "ti,omap5-scrm", .data = &scrm_data },
+#endif
+#ifdef CONFIG_SOC_DRA7XX
+       { .compatible = "ti,dra7-prm", .data = &dra7_prm_data },
+#endif
+       { }
 };
 
-int __init of_prcm_init(void)
+/**
+ * omap2_prm_base_init - initialize iomappings for the PRM driver
+ *
+ * Detects and initializes the iomappings for the PRM driver, based
+ * on the DT data. Returns 0 in success, negative error value
+ * otherwise.
+ */
+int __init omap2_prm_base_init(void)
 {
        struct device_node *np;
+       const struct of_device_id *match;
+       struct omap_prcm_init_data *data;
        void __iomem *mem;
-       int memmap_index = 0;
 
-       ti_clk_ll_ops = &omap_clk_ll_ops;
+       for_each_matching_node_and_match(np, omap_prcm_dt_match_table, &match) {
+               data = (struct omap_prcm_init_data *)match->data;
 
-       for_each_matching_node(np, omap_prcm_dt_match_table) {
                mem = of_iomap(np, 0);
-               clk_memmaps[memmap_index] = mem;
-               ti_dt_clk_init_provider(np, memmap_index);
-               memmap_index++;
+               if (!mem)
+                       return -ENOMEM;
+
+               if (data->index == TI_CLKM_PRM)
+                       prm_base = mem + data->offset;
+
+               data->mem = mem;
+
+               data->np = np;
+
+               if (data->init)
+                       data->init(data);
        }
 
        return 0;
 }
 
-void __init omap3_prcm_legacy_iomaps_init(void)
+int __init omap2_prcm_base_init(void)
 {
-       ti_clk_ll_ops = &omap_clk_ll_ops;
+       int ret;
 
-       clk_memmaps[TI_CLKM_CM] = cm_base + OMAP3430_IVA2_MOD;
-       clk_memmaps[TI_CLKM_PRM] = prm_base + OMAP3430_IVA2_MOD;
-       clk_memmaps[TI_CLKM_SCRM] = omap_ctrl_base_get();
+       ret = omap2_prm_base_init();
+       if (ret)
+               return ret;
+
+       return omap2_cm_base_init();
+}
+
+/**
+ * omap_prcm_init - low level init for the PRCM drivers
+ *
+ * Initializes the low level clock infrastructure for PRCM drivers.
+ * Returns 0 in success, negative error value in failure.
+ */
+int __init omap_prcm_init(void)
+{
+       struct device_node *np;
+       const struct of_device_id *match;
+       const struct omap_prcm_init_data *data;
+       int ret;
+
+       for_each_matching_node_and_match(np, omap_prcm_dt_match_table, &match) {
+               data = match->data;
+
+               ret = omap2_clk_provider_init(np, data->index, NULL, data->mem);
+               if (ret)
+                       return ret;
+       }
+
+       omap_cm_init();
+
+       return 0;
 }
 
 static int __init prm_late_init(void)
index 8adf7b1a1dce68cd9139854e2f4785e1511e8c43..c4859c4d364692b575199f0287b4ee4751ccdee2 100644 (file)
@@ -47,22 +47,14 @@ void omap_prm_base_init(void)
 
 s32 omap4_prmst_get_prm_dev_inst(void)
 {
-       if (prm_dev_inst != PRM_INSTANCE_UNKNOWN)
-               return prm_dev_inst;
-
-       /* This cannot be done way early at boot.. as things are not setup */
-       if (cpu_is_omap44xx())
-               prm_dev_inst = OMAP4430_PRM_DEVICE_INST;
-       else if (soc_is_omap54xx())
-               prm_dev_inst = OMAP54XX_PRM_DEVICE_INST;
-       else if (soc_is_dra7xx())
-               prm_dev_inst = DRA7XX_PRM_DEVICE_INST;
-       else if (soc_is_am43xx())
-               prm_dev_inst = AM43XX_PRM_DEVICE_INST;
-
        return prm_dev_inst;
 }
 
+void omap4_prminst_set_prm_dev_inst(s32 dev_inst)
+{
+       prm_dev_inst = dev_inst;
+}
+
 /* Read a register in a PRM instance */
 u32 omap4_prminst_read_inst_reg(u8 part, s16 inst, u16 idx)
 {
index fb1c9d7a2f9defe6b9255cbf193cae32c2eaef14..0c03d0731d7fb32b69fcb0d56e65c420b6964781 100644 (file)
@@ -14,6 +14,7 @@
 
 #define PRM_INSTANCE_UNKNOWN   -1
 extern s32 omap4_prmst_get_prm_dev_inst(void);
+void omap4_prminst_set_prm_dev_inst(s32 dev_inst);
 
 /*
  * In an ideal world, we would not export these low-level functions,
index b84a0122d823a88b8655b0a4c761a460e3cf4cbc..ad1bb9431e941c6fd084fa5d8f0867f24667b72c 100644 (file)
@@ -333,11 +333,9 @@ ENDPROC(omap4_cpu_resume)
 
 #endif /* defined(CONFIG_SMP) && defined(CONFIG_PM) */
 
-#ifndef CONFIG_OMAP4_ERRATA_I688
 ENTRY(omap_bus_sync)
        ret     lr
 ENDPROC(omap_bus_sync)
-#endif
 
 ENTRY(omap_do_wfi)
        stmfd   sp!, {lr}
index 8333400898fb0e14b175fed06731e0d76304c605..e554d9e66a1ce35af7e4db9567fb9b398a451e0f 100644 (file)
@@ -71,7 +71,7 @@ static int tusb_set_async_mode(unsigned sysclk_ps)
 
        gpmc_calc_timings(&t, &tusb_async, &dev_t);
 
-       return gpmc_cs_set_timings(async_cs, &t);
+       return gpmc_cs_set_timings(async_cs, &t, &tusb_async);
 }
 
 static int tusb_set_sync_mode(unsigned sysclk_ps)
@@ -98,7 +98,7 @@ static int tusb_set_sync_mode(unsigned sysclk_ps)
 
        gpmc_calc_timings(&t, &tusb_sync, &dev_t);
 
-       return gpmc_cs_set_timings(sync_cs, &t);
+       return gpmc_cs_set_timings(sync_cs, &t, &tusb_sync);
 }
 
 /* tusb driver calls this when it changes the chip's clocking */
index 0fdf7080e4a641002796a0f9fe34b76c363b95c3..7e0829682bd02cba1b1897d837c8cd5960eca489 100644 (file)
 
 struct voltagedomain;
 
-/*
- * Voltage Processor (VP) identifiers
- */
-#define OMAP3_VP_VDD_MPU_ID 0
-#define OMAP3_VP_VDD_CORE_ID 1
-#define OMAP4_VP_VDD_CORE_ID 0
-#define OMAP4_VP_VDD_IVA_ID 1
-#define OMAP4_VP_VDD_MPU_ID 2
-
 /* XXX document */
 #define VP_IDLE_TIMEOUT                200
 #define VP_TRANXDONE_TIMEOUT   300
index 1914e026245e0464f77d9bd49d6c4aba29fefb3a..b0590fe6ab01dc3a3f653fb8e9d22f3a333ea1cb 100644 (file)
@@ -28,8 +28,8 @@
 #include "prm2xxx_3xxx.h"
 
 static const struct omap_vp_ops omap3_vp_ops = {
-       .check_txdone = omap3_prm_vp_check_txdone,
-       .clear_txdone = omap3_prm_vp_clear_txdone,
+       .check_txdone = omap_prm_vp_check_txdone,
+       .clear_txdone = omap_prm_vp_clear_txdone,
 };
 
 /*
index e62f6b018beb2379ad5dde520cfa84fe6e39e454..2448bb9a871608e102033dd76a9796186b339ea1 100644 (file)
@@ -28,8 +28,8 @@
 #include "vp.h"
 
 static const struct omap_vp_ops omap4_vp_ops = {
-       .check_txdone = omap4_prm_vp_check_txdone,
-       .clear_txdone = omap4_prm_vp_clear_txdone,
+       .check_txdone = omap_prm_vp_check_txdone,
+       .clear_txdone = omap_prm_vp_clear_txdone,
 };
 
 /*
index 48003ea652b9f56341cce4b8d1fe7fb2bf89d8d1..2256cd1e25d156cfd7e40d6c86cd8a9a1b104997 100644 (file)
@@ -22,7 +22,4 @@ config ARCH_MSM8974
        bool "Enable support for MSM8974"
        select HAVE_ARM_ARCH_TIMER
 
-config QCOM_SCM
-       bool
-
 endif
index 8f756ae1ae31ea69780361079902af7f8c9d97fb..e324375fa9195227f951025e41fce094819184cb 100644 (file)
@@ -1,5 +1,2 @@
 obj-y                  := board.o
 obj-$(CONFIG_SMP)      += platsmp.o
-obj-$(CONFIG_QCOM_SCM) += scm.o scm-boot.o
-
-CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
index 09cffed4c0a445784371cf493a4e210b1b261c89..5cde63a64b34d9d5ff2b6c1821d4a4caa77586ae 100644 (file)
 #include <linux/of_address.h>
 #include <linux/smp.h>
 #include <linux/io.h>
+#include <linux/qcom_scm.h>
 
 #include <asm/smp_plat.h>
 
-#include "scm-boot.h"
 
 #define VDD_SC1_ARRAY_CLAMP_GFS_CTL    0x35a0
 #define SCSS_CPU1CORE_RESET            0x2d80
@@ -319,25 +319,10 @@ static int kpssv2_boot_secondary(unsigned int cpu, struct task_struct *idle)
 
 static void __init qcom_smp_prepare_cpus(unsigned int max_cpus)
 {
-       int cpu, map;
-       unsigned int flags = 0;
-       static const int cold_boot_flags[] = {
-               0,
-               SCM_FLAG_COLDBOOT_CPU1,
-               SCM_FLAG_COLDBOOT_CPU2,
-               SCM_FLAG_COLDBOOT_CPU3,
-       };
-
-       for_each_present_cpu(cpu) {
-               map = cpu_logical_map(cpu);
-               if (WARN_ON(map >= ARRAY_SIZE(cold_boot_flags))) {
-                       set_cpu_present(cpu, false);
-                       continue;
-               }
-               flags |= cold_boot_flags[map];
-       }
+       int cpu;
 
-       if (scm_set_boot_addr(virt_to_phys(secondary_startup_arm), flags)) {
+       if (qcom_scm_set_cold_boot_addr(secondary_startup_arm,
+                                       cpu_present_mask)) {
                for_each_present_cpu(cpu) {
                        if (cpu == smp_processor_id())
                                continue;
diff --git a/arch/arm/mach-qcom/scm-boot.c b/arch/arm/mach-qcom/scm-boot.c
deleted file mode 100644 (file)
index e8ff7be..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only 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 Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-
-#include "scm.h"
-#include "scm-boot.h"
-
-/*
- * Set the cold/warm boot address for one of the CPU cores.
- */
-int scm_set_boot_addr(u32 addr, int flags)
-{
-       struct {
-               __le32 flags;
-               __le32 addr;
-       } cmd;
-
-       cmd.addr = cpu_to_le32(addr);
-       cmd.flags = cpu_to_le32(flags);
-       return scm_call(SCM_SVC_BOOT, SCM_BOOT_ADDR,
-                       &cmd, sizeof(cmd), NULL, 0);
-}
-EXPORT_SYMBOL(scm_set_boot_addr);
diff --git a/arch/arm/mach-qcom/scm-boot.h b/arch/arm/mach-qcom/scm-boot.h
deleted file mode 100644 (file)
index 3e210fb..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-#ifndef __MACH_SCM_BOOT_H
-#define __MACH_SCM_BOOT_H
-
-#define SCM_BOOT_ADDR                  0x1
-#define SCM_FLAG_COLDBOOT_CPU1         0x01
-#define SCM_FLAG_COLDBOOT_CPU2         0x08
-#define SCM_FLAG_COLDBOOT_CPU3         0x20
-#define SCM_FLAG_WARMBOOT_CPU0         0x04
-#define SCM_FLAG_WARMBOOT_CPU1         0x02
-#define SCM_FLAG_WARMBOOT_CPU2         0x10
-#define SCM_FLAG_WARMBOOT_CPU3         0x40
-
-int scm_set_boot_addr(u32 addr, int flags);
-
-#endif
diff --git a/arch/arm/mach-qcom/scm.c b/arch/arm/mach-qcom/scm.c
deleted file mode 100644 (file)
index 1d9cf18..0000000
+++ /dev/null
@@ -1,326 +0,0 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only 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 Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-
-#include <asm/outercache.h>
-#include <asm/cacheflush.h>
-
-#include "scm.h"
-
-#define SCM_ENOMEM             -5
-#define SCM_EOPNOTSUPP         -4
-#define SCM_EINVAL_ADDR                -3
-#define SCM_EINVAL_ARG         -2
-#define SCM_ERROR              -1
-#define SCM_INTERRUPTED                1
-
-static DEFINE_MUTEX(scm_lock);
-
-/**
- * struct scm_command - one SCM command buffer
- * @len: total available memory for command and response
- * @buf_offset: start of command buffer
- * @resp_hdr_offset: start of response buffer
- * @id: command to be executed
- * @buf: buffer returned from scm_get_command_buffer()
- *
- * An SCM command is laid out in memory as follows:
- *
- *     ------------------- <--- struct scm_command
- *     | command header  |
- *     ------------------- <--- scm_get_command_buffer()
- *     | command buffer  |
- *     ------------------- <--- struct scm_response and
- *     | response header |      scm_command_to_response()
- *     ------------------- <--- scm_get_response_buffer()
- *     | response buffer |
- *     -------------------
- *
- * There can be arbitrary padding between the headers and buffers so
- * you should always use the appropriate scm_get_*_buffer() routines
- * to access the buffers in a safe manner.
- */
-struct scm_command {
-       __le32 len;
-       __le32 buf_offset;
-       __le32 resp_hdr_offset;
-       __le32 id;
-       __le32 buf[0];
-};
-
-/**
- * struct scm_response - one SCM response buffer
- * @len: total available memory for response
- * @buf_offset: start of response data relative to start of scm_response
- * @is_complete: indicates if the command has finished processing
- */
-struct scm_response {
-       __le32 len;
-       __le32 buf_offset;
-       __le32 is_complete;
-};
-
-/**
- * alloc_scm_command() - Allocate an SCM command
- * @cmd_size: size of the command buffer
- * @resp_size: size of the response buffer
- *
- * Allocate an SCM command, including enough room for the command
- * and response headers as well as the command and response buffers.
- *
- * Returns a valid &scm_command on success or %NULL if the allocation fails.
- */
-static struct scm_command *alloc_scm_command(size_t cmd_size, size_t resp_size)
-{
-       struct scm_command *cmd;
-       size_t len = sizeof(*cmd) + sizeof(struct scm_response) + cmd_size +
-               resp_size;
-       u32 offset;
-
-       cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL);
-       if (cmd) {
-               cmd->len = cpu_to_le32(len);
-               offset = offsetof(struct scm_command, buf);
-               cmd->buf_offset = cpu_to_le32(offset);
-               cmd->resp_hdr_offset = cpu_to_le32(offset + cmd_size);
-       }
-       return cmd;
-}
-
-/**
- * free_scm_command() - Free an SCM command
- * @cmd: command to free
- *
- * Free an SCM command.
- */
-static inline void free_scm_command(struct scm_command *cmd)
-{
-       kfree(cmd);
-}
-
-/**
- * scm_command_to_response() - Get a pointer to a scm_response
- * @cmd: command
- *
- * Returns a pointer to a response for a command.
- */
-static inline struct scm_response *scm_command_to_response(
-               const struct scm_command *cmd)
-{
-       return (void *)cmd + le32_to_cpu(cmd->resp_hdr_offset);
-}
-
-/**
- * scm_get_command_buffer() - Get a pointer to a command buffer
- * @cmd: command
- *
- * Returns a pointer to the command buffer of a command.
- */
-static inline void *scm_get_command_buffer(const struct scm_command *cmd)
-{
-       return (void *)cmd->buf;
-}
-
-/**
- * scm_get_response_buffer() - Get a pointer to a response buffer
- * @rsp: response
- *
- * Returns a pointer to a response buffer of a response.
- */
-static inline void *scm_get_response_buffer(const struct scm_response *rsp)
-{
-       return (void *)rsp + le32_to_cpu(rsp->buf_offset);
-}
-
-static int scm_remap_error(int err)
-{
-       pr_err("scm_call failed with error code %d\n", err);
-       switch (err) {
-       case SCM_ERROR:
-               return -EIO;
-       case SCM_EINVAL_ADDR:
-       case SCM_EINVAL_ARG:
-               return -EINVAL;
-       case SCM_EOPNOTSUPP:
-               return -EOPNOTSUPP;
-       case SCM_ENOMEM:
-               return -ENOMEM;
-       }
-       return -EINVAL;
-}
-
-static u32 smc(u32 cmd_addr)
-{
-       int context_id;
-       register u32 r0 asm("r0") = 1;
-       register u32 r1 asm("r1") = (u32)&context_id;
-       register u32 r2 asm("r2") = cmd_addr;
-       do {
-               asm volatile(
-                       __asmeq("%0", "r0")
-                       __asmeq("%1", "r0")
-                       __asmeq("%2", "r1")
-                       __asmeq("%3", "r2")
-#ifdef REQUIRES_SEC
-                       ".arch_extension sec\n"
-#endif
-                       "smc    #0      @ switch to secure world\n"
-                       : "=r" (r0)
-                       : "r" (r0), "r" (r1), "r" (r2)
-                       : "r3");
-       } while (r0 == SCM_INTERRUPTED);
-
-       return r0;
-}
-
-static int __scm_call(const struct scm_command *cmd)
-{
-       int ret;
-       u32 cmd_addr = virt_to_phys(cmd);
-
-       /*
-        * Flush the command buffer so that the secure world sees
-        * the correct data.
-        */
-       __cpuc_flush_dcache_area((void *)cmd, cmd->len);
-       outer_flush_range(cmd_addr, cmd_addr + cmd->len);
-
-       ret = smc(cmd_addr);
-       if (ret < 0)
-               ret = scm_remap_error(ret);
-
-       return ret;
-}
-
-static void scm_inv_range(unsigned long start, unsigned long end)
-{
-       u32 cacheline_size, ctr;
-
-       asm volatile("mrc p15, 0, %0, c0, c0, 1" : "=r" (ctr));
-       cacheline_size = 4 << ((ctr >> 16) & 0xf);
-
-       start = round_down(start, cacheline_size);
-       end = round_up(end, cacheline_size);
-       outer_inv_range(start, end);
-       while (start < end) {
-               asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start)
-                    : "memory");
-               start += cacheline_size;
-       }
-       dsb();
-       isb();
-}
-
-/**
- * scm_call() - Send an SCM command
- * @svc_id: service identifier
- * @cmd_id: command identifier
- * @cmd_buf: command buffer
- * @cmd_len: length of the command buffer
- * @resp_buf: response buffer
- * @resp_len: length of the response buffer
- *
- * Sends a command to the SCM and waits for the command to finish processing.
- *
- * A note on cache maintenance:
- * Note that any buffers that are expected to be accessed by the secure world
- * must be flushed before invoking scm_call and invalidated in the cache
- * immediately after scm_call returns. Cache maintenance on the command and
- * response buffers is taken care of by scm_call; however, callers are
- * responsible for any other cached buffers passed over to the secure world.
- */
-int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
-               void *resp_buf, size_t resp_len)
-{
-       int ret;
-       struct scm_command *cmd;
-       struct scm_response *rsp;
-       unsigned long start, end;
-
-       cmd = alloc_scm_command(cmd_len, resp_len);
-       if (!cmd)
-               return -ENOMEM;
-
-       cmd->id = cpu_to_le32((svc_id << 10) | cmd_id);
-       if (cmd_buf)
-               memcpy(scm_get_command_buffer(cmd), cmd_buf, cmd_len);
-
-       mutex_lock(&scm_lock);
-       ret = __scm_call(cmd);
-       mutex_unlock(&scm_lock);
-       if (ret)
-               goto out;
-
-       rsp = scm_command_to_response(cmd);
-       start = (unsigned long)rsp;
-
-       do {
-               scm_inv_range(start, start + sizeof(*rsp));
-       } while (!rsp->is_complete);
-
-       end = (unsigned long)scm_get_response_buffer(rsp) + resp_len;
-       scm_inv_range(start, end);
-
-       if (resp_buf)
-               memcpy(resp_buf, scm_get_response_buffer(rsp), resp_len);
-out:
-       free_scm_command(cmd);
-       return ret;
-}
-EXPORT_SYMBOL(scm_call);
-
-u32 scm_get_version(void)
-{
-       int context_id;
-       static u32 version = -1;
-       register u32 r0 asm("r0");
-       register u32 r1 asm("r1");
-
-       if (version != -1)
-               return version;
-
-       mutex_lock(&scm_lock);
-
-       r0 = 0x1 << 8;
-       r1 = (u32)&context_id;
-       do {
-               asm volatile(
-                       __asmeq("%0", "r0")
-                       __asmeq("%1", "r1")
-                       __asmeq("%2", "r0")
-                       __asmeq("%3", "r1")
-#ifdef REQUIRES_SEC
-                       ".arch_extension sec\n"
-#endif
-                       "smc    #0      @ switch to secure world\n"
-                       : "=r" (r0), "=r" (r1)
-                       : "r" (r0), "r" (r1)
-                       : "r2", "r3");
-       } while (r0 == SCM_INTERRUPTED);
-
-       version = r1;
-       mutex_unlock(&scm_lock);
-
-       return version;
-}
-EXPORT_SYMBOL(scm_get_version);
diff --git a/arch/arm/mach-qcom/scm.h b/arch/arm/mach-qcom/scm.h
deleted file mode 100644 (file)
index 00b31ea..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-#ifndef __MACH_SCM_H
-#define __MACH_SCM_H
-
-#define SCM_SVC_BOOT                   0x1
-#define SCM_SVC_PIL                    0x2
-
-extern int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
-               void *resp_buf, size_t resp_len);
-
-#define SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF))
-
-extern u32 scm_get_version(void);
-
-#endif
index f26fcdca2445e96e5cbac6731791485e9f904e7e..5b4ca3c3c8797d2560c4addaad6773b974ebb2d0 100644 (file)
@@ -55,7 +55,7 @@ static int pmu_power_domain_is_on(int pd)
        return !(val & BIT(pd));
 }
 
-struct reset_control *rockchip_get_core_reset(int cpu)
+static struct reset_control *rockchip_get_core_reset(int cpu)
 {
        struct device *dev = get_cpu_device(cpu);
        struct device_node *np;
@@ -201,7 +201,7 @@ static int __init rockchip_smp_prepare_sram(struct device_node *node)
        return 0;
 }
 
-static struct regmap_config rockchip_pmu_regmap_config = {
+static const struct regmap_config rockchip_pmu_regmap_config = {
        .reg_bits = 32,
        .val_bits = 32,
        .reg_stride = 4,
index 50cb781aaa36c97f9b2f905a0e1e3076421b5654..b07d8860207323e302a86234f9bf7cbbeac827a4 100644 (file)
@@ -75,9 +75,13 @@ static void rk3288_slp_mode_set(int level)
        regmap_read(pmu_regmap, RK3288_PMU_PWRMODE_CON,
                    &rk3288_pmu_pwr_mode_con);
 
-       /* set bit 8 so that system will resume to FAST_BOOT_ADDR */
+       /*
+        * SGRF_FAST_BOOT_EN - system to boot from FAST_BOOT_ADDR
+        * PCLK_WDT_GATE - disable WDT during suspend.
+        */
        regmap_write(sgrf_regmap, RK3288_SGRF_SOC_CON0,
-                    SGRF_FAST_BOOT_EN | SGRF_FAST_BOOT_EN_WRITE);
+                    SGRF_PCLK_WDT_GATE | SGRF_FAST_BOOT_EN
+                    | SGRF_PCLK_WDT_GATE_WRITE | SGRF_FAST_BOOT_EN_WRITE);
 
        /* booting address of resuming system is from this register value */
        regmap_write(sgrf_regmap, RK3288_SGRF_FAST_BOOT_ADDR,
@@ -122,7 +126,8 @@ static void rk3288_slp_mode_set_resume(void)
                     rk3288_pmu_pwr_mode_con);
 
        regmap_write(sgrf_regmap, RK3288_SGRF_SOC_CON0,
-                    rk3288_sgrf_soc_con0 | SGRF_FAST_BOOT_EN_WRITE);
+                    rk3288_sgrf_soc_con0 | SGRF_PCLK_WDT_GATE_WRITE
+                    | SGRF_FAST_BOOT_EN_WRITE);
 }
 
 static int rockchip_lpmode_enter(unsigned long arg)
@@ -209,6 +214,9 @@ static int rk3288_suspend_init(struct device_node *np)
        memcpy(rk3288_bootram_base, rockchip_slp_cpu_resume,
               rk3288_bootram_sz);
 
+       regmap_write(pmu_regmap, RK3288_PMU_OSC_CNT, OSC_STABL_CNT_THRESH);
+       regmap_write(pmu_regmap, RK3288_PMU_STABL_CNT, PMU_STABL_CNT_THRESH);
+
        return 0;
 }
 
index 7c889c04604b5ec0d9faaec30d0b612275c4cda4..03ff31d8282d07bd4fcd54dcde67b6ee7d7069ef 100644 (file)
@@ -50,6 +50,8 @@ static inline void rockchip_suspend_init(void)
 
 #define RK3288_SGRF_SOC_CON0           (0x0000)
 #define RK3288_SGRF_FAST_BOOT_ADDR     (0x0120)
+#define SGRF_PCLK_WDT_GATE             BIT(6)
+#define SGRF_PCLK_WDT_GATE_WRITE       BIT(22)
 #define SGRF_FAST_BOOT_EN              BIT(8)
 #define SGRF_FAST_BOOT_EN_WRITE                BIT(24)
 
@@ -63,6 +65,10 @@ static inline void rockchip_suspend_init(void)
 /* PMU_WAKEUP_CFG1 bits */
 #define PMU_ARMINT_WAKEUP_EN           BIT(0)
 
+/* wait 30ms for OSC stable and 30ms for pmic stable */
+#define OSC_STABL_CNT_THRESH   (32 * 30)
+#define PMU_STABL_CNT_THRESH   (32 * 30)
+
 enum rk3288_pwr_mode_con {
        PMU_PWR_MODE_EN = 0,
        PMU_CLK_CORE_SRC_GATE_EN,
index 79c49ff77f6ed3261498e05affea2b4ff3c60248..23bec3a85b22bb2e2231804d8c164839f5e46818 100644 (file)
@@ -39,14 +39,14 @@ config CPU_S3C2412
        bool "SAMSUNG S3C2412"
        select CPU_ARM926T
        select S3C2412_COMMON_CLK
-       select S3C2412_PM if PM
+       select S3C2412_PM if PM_SLEEP
        help
          Support for the S3C2412 and S3C2413 SoCs from the S3C24XX line
 
 config CPU_S3C2416
        bool "SAMSUNG S3C2416/S3C2450"
        select CPU_ARM926T
-       select S3C2416_PM if PM
+       select S3C2416_PM if PM_SLEEP
        select S3C2443_COMMON_CLK
        help
          Support for the S3C2416 SoC from the S3C24XX line
@@ -55,7 +55,7 @@ config CPU_S3C2440
        bool "SAMSUNG S3C2440"
        select CPU_ARM920T
        select S3C2410_COMMON_CLK
-       select S3C2410_PM if PM
+       select S3C2410_PM if PM_SLEEP
        help
          Support for S3C2440 Samsung Mobile CPU based systems.
 
@@ -63,7 +63,7 @@ config CPU_S3C2442
        bool "SAMSUNG S3C2442"
        select CPU_ARM920T
        select S3C2410_COMMON_CLK
-       select S3C2410_PM if PM
+       select S3C2410_PM if PM_SLEEP
        help
          Support for S3C2442 Samsung Mobile CPU based systems.
 
@@ -228,11 +228,6 @@ config H1940BT
          This is a simple driver that is able to control
          the state of built in bluetooth chip on h1940.
 
-config PM_H1940
-       bool
-       help
-         Internal node for H1940 and related PM
-
 config MACH_N30
        bool "Acer N30 family"
        select S3C_DEV_NAND
@@ -362,6 +357,7 @@ if CPU_S3C2416
 config S3C2416_PM
        bool
        select S3C2412_PM_SLEEP
+       select SAMSUNG_WAKEMASK
        help
          Internal config node to apply S3C2416 power management
 
@@ -584,6 +580,11 @@ config MACH_SMDK2443
 
 endif  # CPU_S3C2443
 
+config PM_H1940
+       bool
+       help
+         Internal node for H1940 and related PM
+
 endmenu        # SAMSUNG S3C24XX SoCs Support
 
 endif  # ARCH_S3C24XX
index b40a22fe082ada4efb6e33c53a7fd20ddceca4b6..05920c8a5764737b845883030be776b6b1d9c122 100644 (file)
@@ -32,7 +32,8 @@ obj-$(CONFIG_CPU_S3C2443)     += s3c2443.o
 
 # PM
 
-obj-$(CONFIG_PM)               += pm.o irq-pm.o sleep.o
+obj-$(CONFIG_PM)               += pm.o
+obj-$(CONFIG_PM_SLEEP)         += irq-pm.o sleep.o
 
 # common code
 
index 2eef7e6f76758497094c1b0fe8865b0ee34cda2a..69459dbbdcad9df7f243286d076e54b2aabf667d 100644 (file)
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include "regs-clock.h"
+#include "regs-irq.h"
 
 static inline void s3c_pm_debug_init_uart(void)
 {
@@ -42,8 +47,23 @@ static inline void s3c_pm_arch_stop_clocks(void)
        __raw_writel(0x00, S3C2410_CLKCON);  /* turn off clocks over sleep */
 }
 
-static void s3c_pm_show_resume_irqs(int start, unsigned long which,
-                                   unsigned long mask);
+/* s3c2410_pm_show_resume_irqs
+ *
+ * print any IRQs asserted at resume time (ie, we woke from)
+*/
+static inline void s3c_pm_show_resume_irqs(int start, unsigned long which,
+                                          unsigned long mask)
+{
+       int i;
+
+       which &= ~mask;
+
+       for (i = 0; i <= 31; i++) {
+               if (which & (1L<<i)) {
+                       S3C_PMDBG("IRQ %d asserted at resume\n", start+i);
+               }
+       }
+}
 
 static inline void s3c_pm_arch_show_resume_irqs(void)
 {
index 44923895f558633251adc07ce589cfbcb8d86480..c0e328e37bd63927fd48b6cc415fef6bc86bdd44 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "s3c2412-power.h"
 
+#ifdef CONFIG_PM_SLEEP
 extern void s3c2412_sleep_enter(void);
 
 static int s3c2416_cpu_suspend(unsigned long arg)
@@ -70,7 +71,7 @@ static __init int s3c2416_pm_init(void)
 }
 
 arch_initcall(s3c2416_pm_init);
-
+#endif
 
 static void s3c2416_pm_resume(void)
 {
index b19256ec8d407cc4ee7dbf995db7f8498323a7ae..5d510bca0844005ae5f38c717319da1fa3948168 100644 (file)
@@ -50,6 +50,7 @@
 
 #define PFX "s3c24xx-pm: "
 
+#ifdef CONFIG_PM_SLEEP
 static struct sleep_save core_save[] = {
        /* we restore the timings here, with the proviso that the board
         * brings the system up in an slower, or equal frequency setting
@@ -67,6 +68,7 @@ static struct sleep_save core_save[] = {
        SAVE_ITEM(S3C2410_BANKCON4),
        SAVE_ITEM(S3C2410_BANKCON5),
 };
+#endif
 
 /* s3c_pm_check_resume_pin
  *
@@ -121,7 +123,7 @@ void s3c_pm_configure_extint(void)
        }
 }
 
-
+#ifdef CONFIG_PM_SLEEP
 void s3c_pm_restore_core(void)
 {
        s3c_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
@@ -131,4 +133,4 @@ void s3c_pm_save_core(void)
 {
        s3c_pm_do_save(core_save, ARRAY_SIZE(core_save));
 }
-
+#endif
index 2a6985a4a0ff8952b32e1d144d12416432e2c4d0..5061d66ca10cb47809ae9b33c62da0be52b1bc9e 100644 (file)
@@ -121,7 +121,7 @@ int __init s3c2410_init(void)
 {
        printk("S3C2410: Initialising architecture\n");
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
        register_syscore_ops(&s3c2410_pm_syscore_ops);
        register_syscore_ops(&s3c24xx_irq_syscore_ops);
 #endif
index ecf2c77ab88b17c508417a928909af0bb0ec286d..64a13605cfc3d08b60bfb042fc7d6cba73882b34 100644 (file)
@@ -172,7 +172,7 @@ int __init s3c2412_init(void)
 {
        printk("S3C2412: Initialising architecture\n");
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
        register_syscore_ops(&s3c2412_pm_syscore_ops);
        register_syscore_ops(&s3c24xx_irq_syscore_ops);
 #endif
index bfd4da86deb8e94d20698ceef91f06fd305a1ff2..3f8ca2a3ef176953d76e995cdb6e0edea23a271a 100644 (file)
@@ -98,7 +98,7 @@ int __init s3c2416_init(void)
        s3c_adc_setname("s3c2416-adc");
        s3c_rtc_setname("s3c2416-rtc");
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
        register_syscore_ops(&s3c2416_pm_syscore_ops);
        register_syscore_ops(&s3c24xx_irq_syscore_ops);
        register_syscore_ops(&s3c2416_irq_syscore_ops);
index 03d379f1fc5255037679b070234851afaffef976..eb733555fab52d495be89fa14fba0407412ce13e 100644 (file)
@@ -57,11 +57,11 @@ int __init s3c2440_init(void)
 
        /* register suspend/resume handlers */
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
        register_syscore_ops(&s3c2410_pm_syscore_ops);
        register_syscore_ops(&s3c24xx_irq_syscore_ops);
-#endif
        register_syscore_ops(&s3c244x_pm_syscore_ops);
+#endif
 
        /* register our system device for everything else */
 
index 7b043349f1c8297c6256ac2690d924d2e59d2c81..893998ede0223baf4a7709da0aa53029deaeed08 100644 (file)
@@ -60,11 +60,11 @@ int __init s3c2442_init(void)
 {
        printk("S3C2442: Initialising architecture\n");
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
        register_syscore_ops(&s3c2410_pm_syscore_ops);
        register_syscore_ops(&s3c24xx_irq_syscore_ops);
-#endif
        register_syscore_ops(&s3c244x_pm_syscore_ops);
+#endif
 
        return device_register(&s3c2442_dev);
 }
index 177f97802745fa133f4bef1ed001541a023d850c..b14119585dc727fa99ca1a70e23fc498093525dd 100644 (file)
@@ -108,7 +108,7 @@ static int __init s3c2442_core_init(void)
 core_initcall(s3c2442_core_init);
 
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static struct sleep_save s3c244x_sleep[] = {
        SAVE_ITEM(S3C2440_DSC0),
        SAVE_ITEM(S3C2440_DSC1),
@@ -127,12 +127,9 @@ static void s3c244x_resume(void)
 {
        s3c_pm_do_restore(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
 }
-#else
-#define s3c244x_suspend NULL
-#define s3c244x_resume  NULL
-#endif
 
 struct syscore_ops s3c244x_pm_syscore_ops = {
        .suspend        = s3c244x_suspend,
        .resume         = s3c244x_resume,
 };
+#endif
index 26ca2427e53de3f8690a3eb10c02242ed4132f91..eff95e950d812afd7eb4993096176ff0264e656c 100644 (file)
@@ -189,6 +189,7 @@ endchoice
 config SMDK6410_WM1190_EV1
        bool "Support Wolfson Microelectronics 1190-EV1 PMIC card"
        depends on MACH_SMDK6410
+       depends on I2C=y
        select MFD_WM8350_I2C
        select REGULATOR
        select REGULATOR_WM8350
@@ -203,6 +204,7 @@ config SMDK6410_WM1190_EV1
 config SMDK6410_WM1192_EV1
        bool "Support Wolfson Microelectronics 1192-EV1 PMIC card"
        depends on MACH_SMDK6410
+       depends on I2C=y
        select MFD_WM831X
        select MFD_WM831X_I2C
        select REGULATOR
@@ -269,8 +271,8 @@ config MACH_SMARTQ7
 
 config MACH_WLF_CRAGG_6410
        bool "Wolfson Cragganmore 6410"
+       depends on I2C=y
        select CPU_S3C6410
-       select I2C
        select LEDS_GPIO_REGISTER
        select S3C64XX_DEV_SPI0
        select S3C64XX_SETUP_FB_24BPP
index 12f67b61ca5f7e7340821f21744530bef0ec844d..17f4b07ec763b65936664522e3bd8c230876722c 100644 (file)
@@ -16,7 +16,8 @@ obj-$(CONFIG_CPU_S3C6410)     += s3c6410.o
 
 # PM
 
-obj-$(CONFIG_PM)               += pm.o irq-pm.o sleep.o
+obj-$(CONFIG_PM)               += pm.o
+obj-$(CONFIG_PM_SLEEP)         += irq-pm.o sleep.o
 obj-$(CONFIG_CPU_IDLE)         += cpuidle.o
 
 # DMA support
index 7bc66682687efa4f240a5557618278d38c39e4b1..dcbe17f5e5f8054ee7fd1e796197eb88d78e97a8 100644 (file)
@@ -14,6 +14,7 @@
 #include <mach/gpio-samsung.h>
 
 #define GLENFARCLAS_PMIC_IRQ_BASE      IRQ_BOARD_START
+#define BANFF_PMIC_IRQ_BASE            (IRQ_BOARD_START + 64)
 
 #define PCA935X_GPIO_BASE              GPIO_BOARD_START
 #define CODEC_GPIO_BASE                        (GPIO_BOARD_START + 8)
index 10b913baab2883562acb916ecef103d96b35b761..65c426bc45f72eb530df0736493d4e4a373904cd 100644 (file)
@@ -554,6 +554,7 @@ static struct wm831x_touch_pdata touch_pdata = {
 
 static struct wm831x_pdata crag_pmic_pdata = {
        .wm831x_num = 1,
+       .irq_base = BANFF_PMIC_IRQ_BASE,
        .gpio_base = BANFF_PMIC_GPIO_BASE,
        .soft_shutdown = true,
 
index 661eb662d05159861fb9fffd9b95705b8dbac238..b7447a92276eadea2fa198a090fff761b16fa6e1 100644 (file)
@@ -209,7 +209,7 @@ static struct platform_device smdk6410_smsc911x = {
 };
 
 #ifdef CONFIG_REGULATOR
-static struct regulator_consumer_supply smdk6410_b_pwr_5v_consumers[] __initdata = {
+static struct regulator_consumer_supply smdk6410_b_pwr_5v_consumers[] = {
        REGULATOR_SUPPLY("PVDD", "0-001b"),
        REGULATOR_SUPPLY("AVDD", "0-001b"),
 };
index aaf7bea4032f4824a611f92710335aa717f70a33..75b14e756383859c76c65f5544f06676faba5e58 100644 (file)
@@ -194,6 +194,7 @@ void s3c_pm_debug_smdkled(u32 set, u32 clear)
 }
 #endif
 
+#ifdef CONFIG_PM_SLEEP
 static struct sleep_save core_save[] = {
        SAVE_ITEM(S3C64XX_MEM0DRVCON),
        SAVE_ITEM(S3C64XX_MEM1DRVCON),
@@ -238,6 +239,7 @@ void s3c_pm_save_core(void)
        s3c_pm_do_save(misc_save, ARRAY_SIZE(misc_save));
        s3c_pm_do_save(core_save, ARRAY_SIZE(core_save));
 }
+#endif
 
 /* since both s3c6400 and s3c6410 share the same sleep pm calls, we
  * put the per-cpu code in here until any new cpu comes along and changes
index 2f36c85eec4b201e4ab1016a2c9501a433758e65..0fb484221c90e0eb9c0a5aeefd5df7beac098678 100644 (file)
@@ -62,6 +62,10 @@ config ARCH_R8A7740
        select ARCH_RMOBILE
        select RENESAS_INTC_IRQPIN
 
+config ARCH_R8A7778
+       bool "R-Car M1A (R8A77781)"
+       select ARCH_RCAR_GEN1
+
 config ARCH_R8A7779
        bool "R-Car H1 (R8A77790)"
        select ARCH_RCAR_GEN1
@@ -69,15 +73,22 @@ config ARCH_R8A7779
 config ARCH_R8A7790
        bool "R-Car H2 (R8A77900)"
        select ARCH_RCAR_GEN2
+       select I2C
 
 config ARCH_R8A7791
        bool "R-Car M2-W (R8A77910)"
        select ARCH_RCAR_GEN2
+       select I2C
 
 config ARCH_R8A7794
        bool "R-Car E2 (R8A77940)"
        select ARCH_RCAR_GEN2
 
+config ARCH_SH73A0
+       bool "SH-Mobile AG5 (R8A73A00)"
+       select ARCH_RMOBILE
+       select RENESAS_INTC_IRQPIN
+
 comment "Renesas ARM SoCs Board Type"
 
 config MACH_MARZEN
@@ -92,13 +103,6 @@ if ARCH_SHMOBILE_LEGACY
 
 comment "Renesas ARM SoCs System Type"
 
-config ARCH_SH7372
-       bool "SH-Mobile AP4 (SH7372)"
-       select ARCH_RMOBILE
-       select ARCH_WANT_OPTIONAL_GPIOLIB
-       select ARM_CPU_SUSPEND if PM || CPU_IDLE
-       select SH_INTC
-
 config ARCH_SH73A0
        bool "SH-Mobile AG5 (R8A73A00)"
        select ARCH_RMOBILE
@@ -108,13 +112,6 @@ config ARCH_SH73A0
        select SH_INTC
        select RENESAS_INTC_IRQPIN
 
-config ARCH_R8A73A4
-       bool "R-Mobile APE6 (R8A73A40)"
-       select ARCH_RMOBILE
-       select ARCH_WANT_OPTIONAL_GPIOLIB
-       select ARM_GIC
-       select RENESAS_IRQC
-
 config ARCH_R8A7740
        bool "R-Mobile A1 (R8A77400)"
        select ARCH_RMOBILE
@@ -136,33 +133,6 @@ config ARCH_R8A7779
 
 comment "Renesas ARM SoCs Board Type"
 
-config MACH_APE6EVM
-       bool "APE6EVM board"
-       depends on ARCH_R8A73A4
-       select SMSC_PHY if SMSC911X
-       select USE_OF
-
-config MACH_APE6EVM_REFERENCE
-       bool "APE6EVM board - Reference Device Tree Implementation"
-       depends on ARCH_R8A73A4
-       select SMSC_PHY if SMSC911X
-       select USE_OF
-       ---help---
-          Use reference implementation of APE6EVM board support
-          which makes a greater use of device tree at the expense
-          of not supporting a number of devices.
-
-          This is intended to aid developers
-
-config MACH_MACKEREL
-       bool "mackerel board"
-       depends on ARCH_SH7372
-       select ARCH_REQUIRE_GPIOLIB
-       select REGULATOR_FIXED_VOLTAGE if REGULATOR
-       select SMSC_PHY if SMSC911X
-       select SND_SOC_AK4642 if SND_SIMPLE_CARD
-       select USE_OF
-
 config MACH_ARMADILLO800EVA
        bool "Armadillo-800 EVA board"
        depends on ARCH_R8A7740
@@ -209,20 +179,6 @@ config MACH_KZM9G
        select SND_SOC_AK4642 if SND_SIMPLE_CARD
        select USE_OF
 
-config MACH_KZM9G_REFERENCE
-       bool "KZM-A9-GT board - Reference Device Tree Implementation"
-       depends on ARCH_SH73A0
-       select ARCH_REQUIRE_GPIOLIB
-       select REGULATOR_FIXED_VOLTAGE if REGULATOR
-       select SND_SOC_AK4642 if SND_SIMPLE_CARD
-       select USE_OF
-       ---help---
-          Use reference implementation of KZM-A9-GT board support
-          which makes as greater use of device tree at the expense
-          of not supporting a number of devices.
-
-          This is intended to aid developers
-
 comment "Renesas ARM SoCs System Configuration"
 
 config CPU_HAS_INTEVT
index d53996e6da970d8d451ad1a6baab8b450c8dfaab..89e463de44798fc3cc2ff18b9d39a4a409c1b734 100644 (file)
@@ -6,14 +6,13 @@
 obj-y                          := timer.o console.o
 
 # CPU objects
-obj-$(CONFIG_ARCH_SH7372)      += setup-sh7372.o intc-sh7372.o pm-sh7372.o
-obj-$(CONFIG_ARCH_SH73A0)      += setup-sh73a0.o intc-sh73a0.o pm-sh73a0.o
+obj-$(CONFIG_ARCH_SH73A0)      += setup-sh73a0.o pm-sh73a0.o
 obj-$(CONFIG_ARCH_R8A73A4)     += setup-r8a73a4.o
 obj-$(CONFIG_ARCH_R8A7740)     += setup-r8a7740.o pm-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 pm-r8a7790.o
-obj-$(CONFIG_ARCH_R8A7791)     += setup-r8a7791.o pm-r8a7791.o
+obj-$(CONFIG_ARCH_R8A7790)     += setup-r8a7790.o
+obj-$(CONFIG_ARCH_R8A7791)     += setup-r8a7791.o
 obj-$(CONFIG_ARCH_R8A7794)     += setup-r8a7794.o
 obj-$(CONFIG_ARCH_EMEV2)       += setup-emev2.o
 obj-$(CONFIG_ARCH_R7S72100)    += setup-r7s72100.o
@@ -21,9 +20,7 @@ obj-$(CONFIG_ARCH_R7S72100)   += setup-r7s72100.o
 # Clock objects
 ifndef CONFIG_COMMON_CLK
 obj-y                          += clock.o
-obj-$(CONFIG_ARCH_SH7372)      += clock-sh7372.o
 obj-$(CONFIG_ARCH_SH73A0)      += clock-sh73a0.o
-obj-$(CONFIG_ARCH_R8A73A4)     += clock-r8a73a4.o
 obj-$(CONFIG_ARCH_R8A7740)     += clock-r8a7740.o
 obj-$(CONFIG_ARCH_R8A7778)     += clock-r8a7778.o
 obj-$(CONFIG_ARCH_R8A7779)     += clock-r8a7779.o
@@ -35,6 +32,8 @@ 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_R8A7790)     += regulator-quirk-rcar-gen2.o
+obj-$(CONFIG_ARCH_R8A7791)     += regulator-quirk-rcar-gen2.o
 
 # SMP objects
 smp-y                          := $(cpu-y)
@@ -46,27 +45,20 @@ smp-$(CONFIG_ARCH_EMEV2)    += smp-emev2.o headsmp-scu.o platsmp-scu.o
 
 # PM objects
 obj-$(CONFIG_SUSPEND)          += suspend.o
-obj-$(CONFIG_CPU_IDLE)         += cpuidle.o
 obj-$(CONFIG_CPU_FREQ)         += cpufreq.o
 obj-$(CONFIG_PM_RCAR)          += pm-rcar.o
 obj-$(CONFIG_PM_RMOBILE)       += pm-rmobile.o
-
-# special sh7372 handling for IRQ objects and low level sleep code
-obj-$(CONFIG_ARCH_SH7372)      += entry-intc.o sleep-sh7372.o
+obj-$(CONFIG_ARCH_RCAR_GEN2)   += pm-rcar-gen2.o
 
 # Board objects
 ifdef CONFIG_ARCH_SHMOBILE_MULTI
 obj-$(CONFIG_MACH_MARZEN)      += board-marzen-reference.o
 else
-obj-$(CONFIG_MACH_APE6EVM)     += board-ape6evm.o
-obj-$(CONFIG_MACH_APE6EVM_REFERENCE)   += board-ape6evm-reference.o
-obj-$(CONFIG_MACH_MACKEREL)    += board-mackerel.o
 obj-$(CONFIG_MACH_BOCKW)       += board-bockw.o
 obj-$(CONFIG_MACH_BOCKW_REFERENCE)     += board-bockw-reference.o
 obj-$(CONFIG_MACH_MARZEN)      += board-marzen.o
 obj-$(CONFIG_MACH_ARMADILLO800EVA)     += board-armadillo800eva.o
-obj-$(CONFIG_MACH_KZM9G)       += board-kzm9g.o
-obj-$(CONFIG_MACH_KZM9G_REFERENCE)     += board-kzm9g-reference.o
+obj-$(CONFIG_MACH_KZM9G)       += board-kzm9g.o intc-sh73a0.o
 endif
 
 # Framework support
index 02532bea530000cbc0b9c850517c00b07b2564d1..e1ef19cef89c7f342b59200a18f4a6b7c56dca15 100644 (file)
@@ -1,13 +1,9 @@
 # per-board load address for uImage
 loadaddr-y     :=
-loadaddr-$(CONFIG_MACH_APE6EVM) += 0x40008000
-loadaddr-$(CONFIG_MACH_APE6EVM_REFERENCE) += 0x40008000
 loadaddr-$(CONFIG_MACH_ARMADILLO800EVA) += 0x40008000
 loadaddr-$(CONFIG_MACH_BOCKW) += 0x60008000
 loadaddr-$(CONFIG_MACH_BOCKW_REFERENCE) += 0x60008000
 loadaddr-$(CONFIG_MACH_KZM9G) += 0x41008000
-loadaddr-$(CONFIG_MACH_KZM9G_REFERENCE) += 0x41008000
-loadaddr-$(CONFIG_MACH_MACKEREL) += 0x40008000
 loadaddr-$(CONFIG_MACH_MARZEN) += 0x60008000
 
 __ZRELADDR     := $(sort $(loadaddr-y))
diff --git a/arch/arm/mach-shmobile/board-ape6evm-reference.c b/arch/arm/mach-shmobile/board-ape6evm-reference.c
deleted file mode 100644 (file)
index 3b68370..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * APE6EVM board 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/gpio.h>
-#include <linux/kernel.h>
-#include <linux/of_platform.h>
-#include <linux/pinctrl/machine.h>
-#include <linux/platform_device.h>
-#include <linux/sh_clk.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-#include "common.h"
-#include "r8a73a4.h"
-
-static void __init ape6evm_add_standard_devices(void)
-{
-
-       struct clk *parent;
-       struct clk *mp;
-
-       r8a73a4_clock_init();
-
-       /* MP clock parent = extal2 */
-       parent      = clk_get(NULL, "extal2");
-       mp          = clk_get(NULL, "mp");
-       BUG_ON(IS_ERR(parent) || IS_ERR(mp));
-
-       clk_set_parent(mp, parent);
-       clk_put(parent);
-       clk_put(mp);
-
-       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
-
-static const char *ape6evm_boards_compat_dt[] __initdata = {
-       "renesas,ape6evm-reference",
-       NULL,
-};
-
-DT_MACHINE_START(APE6EVM_DT, "ape6evm")
-       .init_early     = shmobile_init_delay,
-       .init_machine   = ape6evm_add_standard_devices,
-       .init_late      = shmobile_init_late,
-       .dt_compat      = ape6evm_boards_compat_dt,
-MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-ape6evm.c b/arch/arm/mach-shmobile/board-ape6evm.c
deleted file mode 100644 (file)
index 444f22d..0000000
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * APE6EVM board 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/gpio.h>
-#include <linux/gpio_keys.h>
-#include <linux/input.h>
-#include <linux/interrupt.h>
-#include <linux/irqchip.h>
-#include <linux/irqchip/arm-gic.h>
-#include <linux/kernel.h>
-#include <linux/mfd/tmio.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/sh_mmcif.h>
-#include <linux/mmc/sh_mobile_sdhi.h>
-#include <linux/pinctrl/machine.h>
-#include <linux/platform_device.h>
-#include <linux/regulator/fixed.h>
-#include <linux/regulator/machine.h>
-#include <linux/sh_clk.h>
-#include <linux/smsc911x.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-#include "common.h"
-#include "irqs.h"
-#include "r8a73a4.h"
-
-/* LEDS */
-static struct gpio_led ape6evm_leds[] = {
-       {
-               .name           = "gnss-en",
-               .gpio           = 28,
-               .default_state  = LEDS_GPIO_DEFSTATE_OFF,
-       }, {
-               .name           = "nfc-nrst",
-               .gpio           = 126,
-               .default_state  = LEDS_GPIO_DEFSTATE_OFF,
-       }, {
-               .name           = "gnss-nrst",
-               .gpio           = 132,
-               .default_state  = LEDS_GPIO_DEFSTATE_OFF,
-       }, {
-               .name           = "bt-wakeup",
-               .gpio           = 232,
-               .default_state  = LEDS_GPIO_DEFSTATE_OFF,
-       }, {
-               .name           = "strobe",
-               .gpio           = 250,
-               .default_state  = LEDS_GPIO_DEFSTATE_OFF,
-       }, {
-               .name           = "bbresetout",
-               .gpio           = 288,
-               .default_state  = LEDS_GPIO_DEFSTATE_OFF,
-       },
-};
-
-static __initdata struct gpio_led_platform_data ape6evm_leds_pdata = {
-       .leds           = ape6evm_leds,
-       .num_leds       = ARRAY_SIZE(ape6evm_leds),
-};
-
-/* GPIO KEY */
-#define GPIO_KEY(c, g, d, ...) \
-       { .code = c, .gpio = g, .desc = d, .active_low = 1 }
-
-static struct gpio_keys_button gpio_buttons[] = {
-       GPIO_KEY(KEY_0,                 324,    "S16"),
-       GPIO_KEY(KEY_MENU,              325,    "S17"),
-       GPIO_KEY(KEY_HOME,              326,    "S18"),
-       GPIO_KEY(KEY_BACK,              327,    "S19"),
-       GPIO_KEY(KEY_VOLUMEUP,          328,    "S20"),
-       GPIO_KEY(KEY_VOLUMEDOWN,        329,    "S21"),
-};
-
-static struct gpio_keys_platform_data ape6evm_keys_pdata __initdata = {
-       .buttons        = gpio_buttons,
-       .nbuttons       = ARRAY_SIZE(gpio_buttons),
-};
-
-/* Dummy supplies, where voltage doesn't matter */
-static struct regulator_consumer_supply dummy_supplies[] = {
-       REGULATOR_SUPPLY("vddvario", "smsc911x"),
-       REGULATOR_SUPPLY("vdd33a", "smsc911x"),
-};
-
-/* SMSC LAN9220 */
-static const struct resource lan9220_res[] __initconst = {
-       DEFINE_RES_MEM(0x08000000, 0x1000),
-       {
-               .start  = irq_pin(40), /* IRQ40 */
-               .flags  = IORESOURCE_IRQ | IRQF_TRIGGER_HIGH,
-       },
-};
-
-static const struct smsc911x_platform_config lan9220_data __initconst = {
-       .flags          = SMSC911X_USE_32BIT,
-       .irq_type       = SMSC911X_IRQ_TYPE_PUSH_PULL,
-       .irq_polarity   = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
-};
-
-/*
- * MMC0 power supplies:
- * Both Vcc and VccQ to eMMC on APE6EVM are supplied by a tps80032 voltage
- * regulator. Until support for it is added to this file we simulate the
- * Vcc supply by a fixed always-on regulator
- */
-static struct regulator_consumer_supply vcc_mmc0_consumers[] =
-{
-       REGULATOR_SUPPLY("vmmc", "sh_mmcif.0"),
-};
-
-/*
- * SDHI0 power supplies:
- * Vcc to SDHI0 on APE6EVM is supplied by a GPIO-switchable regulator. VccQ is
- * provided by the same tps80032 regulator as both MMC0 voltages - see comment
- * above
- */
-static struct regulator_consumer_supply vcc_sdhi0_consumers[] =
-{
-       REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"),
-};
-
-static struct regulator_init_data vcc_sdhi0_init_data = {
-       .constraints = {
-               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
-       },
-       .num_consumer_supplies  = ARRAY_SIZE(vcc_sdhi0_consumers),
-       .consumer_supplies      = vcc_sdhi0_consumers,
-};
-
-static const struct fixed_voltage_config vcc_sdhi0_info __initconst = {
-       .supply_name = "SDHI0 Vcc",
-       .microvolts = 3300000,
-       .gpio = 76,
-       .enable_high = 1,
-       .init_data = &vcc_sdhi0_init_data,
-};
-
-/*
- * SDHI1 power supplies:
- * Vcc and VccQ to SDHI1 on APE6EVM are both fixed at 3.3V
- */
-static struct regulator_consumer_supply vcc_sdhi1_consumers[] =
-{
-       REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.1"),
-};
-
-/* MMCIF */
-static const struct sh_mmcif_plat_data mmcif0_pdata __initconst = {
-       .caps           = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE,
-       .slave_id_tx    = SHDMA_SLAVE_MMCIF0_TX,
-       .slave_id_rx    = SHDMA_SLAVE_MMCIF0_RX,
-       .ccs_unsupported = true,
-};
-
-static const struct resource mmcif0_resources[] __initconst = {
-       DEFINE_RES_MEM(0xee200000, 0x100),
-       DEFINE_RES_IRQ(gic_spi(169)),
-};
-
-/* SDHI0 */
-static const struct sh_mobile_sdhi_info sdhi0_pdata __initconst = {
-       .tmio_flags     = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE,
-       .tmio_caps      = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ,
-};
-
-static const struct resource sdhi0_resources[] __initconst = {
-       DEFINE_RES_MEM(0xee100000, 0x100),
-       DEFINE_RES_IRQ(gic_spi(165)),
-};
-
-/* SDHI1 */
-static const struct sh_mobile_sdhi_info sdhi1_pdata __initconst = {
-       .tmio_flags     = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE,
-       .tmio_caps      = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
-                         MMC_CAP_NEEDS_POLL,
-};
-
-static const struct resource sdhi1_resources[] __initconst = {
-       DEFINE_RES_MEM(0xee120000, 0x100),
-       DEFINE_RES_IRQ(gic_spi(166)),
-};
-
-static const struct pinctrl_map ape6evm_pinctrl_map[] __initconst = {
-       /* SCIFA0 console */
-       PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.0", "pfc-r8a73a4",
-                                 "scifa0_data", "scifa0"),
-       /* SMSC */
-       PIN_MAP_MUX_GROUP_DEFAULT("smsc911x", "pfc-r8a73a4",
-                                 "irqc_irq40", "irqc"),
-       /* MMCIF0 */
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-r8a73a4",
-                                 "mmc0_data8", "mmc0"),
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-r8a73a4",
-                                 "mmc0_ctrl", "mmc0"),
-       /* SDHI0: uSD: no WP */
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a73a4",
-                                 "sdhi0_data4", "sdhi0"),
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a73a4",
-                                 "sdhi0_ctrl", "sdhi0"),
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a73a4",
-                                 "sdhi0_cd", "sdhi0"),
-       /* SDHI1 */
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-r8a73a4",
-                                 "sdhi1_data4", "sdhi1"),
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-r8a73a4",
-                                 "sdhi1_ctrl", "sdhi1"),
-};
-
-static void __init ape6evm_add_standard_devices(void)
-{
-
-       struct clk *parent;
-       struct clk *mp;
-
-       r8a73a4_clock_init();
-
-       /* MP clock parent = extal2 */
-       parent      = clk_get(NULL, "extal2");
-       mp          = clk_get(NULL, "mp");
-       BUG_ON(IS_ERR(parent) || IS_ERR(mp));
-
-       clk_set_parent(mp, parent);
-       clk_put(parent);
-       clk_put(mp);
-
-       pinctrl_register_mappings(ape6evm_pinctrl_map,
-                                 ARRAY_SIZE(ape6evm_pinctrl_map));
-       r8a73a4_pinmux_init();
-       r8a73a4_add_standard_devices();
-
-       /* LAN9220 ethernet */
-       gpio_request_one(270, GPIOF_OUT_INIT_HIGH, NULL); /* smsc9220 RESET */
-
-       regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
-
-       platform_device_register_resndata(NULL, "smsc911x", -1,
-                                         lan9220_res, ARRAY_SIZE(lan9220_res),
-                                         &lan9220_data, sizeof(lan9220_data));
-
-       regulator_register_always_on(1, "MMC0 Vcc", vcc_mmc0_consumers,
-                                    ARRAY_SIZE(vcc_mmc0_consumers), 2800000);
-       platform_device_register_resndata(NULL, "sh_mmcif", 0,
-                                         mmcif0_resources, ARRAY_SIZE(mmcif0_resources),
-                                         &mmcif0_pdata, sizeof(mmcif0_pdata));
-       platform_device_register_data(NULL, "reg-fixed-voltage", 2,
-                                     &vcc_sdhi0_info, sizeof(vcc_sdhi0_info));
-       platform_device_register_resndata(NULL, "sh_mobile_sdhi", 0,
-                                         sdhi0_resources, ARRAY_SIZE(sdhi0_resources),
-                                         &sdhi0_pdata, sizeof(sdhi0_pdata));
-       regulator_register_always_on(3, "SDHI1 Vcc", vcc_sdhi1_consumers,
-                                    ARRAY_SIZE(vcc_sdhi1_consumers), 3300000);
-       platform_device_register_resndata(NULL, "sh_mobile_sdhi", 1,
-                                         sdhi1_resources, ARRAY_SIZE(sdhi1_resources),
-                                         &sdhi1_pdata, sizeof(sdhi1_pdata));
-       platform_device_register_data(NULL, "gpio-keys", -1,
-                                     &ape6evm_keys_pdata,
-                                     sizeof(ape6evm_keys_pdata));
-       platform_device_register_data(NULL, "leds-gpio", -1,
-                                     &ape6evm_leds_pdata,
-                                     sizeof(ape6evm_leds_pdata));
-}
-
-static void __init ape6evm_legacy_init_time(void)
-{
-       /* Do not invoke DT-based timers via clocksource_of_init() */
-}
-
-static void __init ape6evm_legacy_init_irq(void)
-{
-       void __iomem *gic_dist_base = ioremap_nocache(0xf1001000, 0x1000);
-       void __iomem *gic_cpu_base = ioremap_nocache(0xf1002000, 0x1000);
-
-       gic_init(0, 29, gic_dist_base, gic_cpu_base);
-
-       /* Do not invoke DT-based interrupt code via irqchip_init() */
-}
-
-
-static const char *ape6evm_boards_compat_dt[] __initdata = {
-       "renesas,ape6evm",
-       NULL,
-};
-
-DT_MACHINE_START(APE6EVM_DT, "ape6evm")
-       .init_early     = shmobile_init_delay,
-       .init_irq       = ape6evm_legacy_init_irq,
-       .init_machine   = ape6evm_add_standard_devices,
-       .init_late      = shmobile_init_late,
-       .dt_compat      = ape6evm_boards_compat_dt,
-       .init_time      = ape6evm_legacy_init_time,
-MACHINE_END
index 36aaeb12e1a558af99c7aa383adfdf2d5bcaa665..bf37e3c532f661a6b8adb5cbb3997a289cb29eb7 100644 (file)
@@ -754,12 +754,12 @@ static struct platform_device vcc_sdhi1 = {
 };
 
 /* SDHI0 */
-static struct sh_mobile_sdhi_info sdhi0_info = {
-       .dma_slave_tx   = SHDMA_SLAVE_SDHI0_TX,
-       .dma_slave_rx   = SHDMA_SLAVE_SDHI0_RX,
-       .tmio_caps      = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
+static struct tmio_mmc_data sdhi0_info = {
+       .chan_priv_tx   = (void *)SHDMA_SLAVE_SDHI0_TX,
+       .chan_priv_rx   = (void *)SHDMA_SLAVE_SDHI0_RX,
+       .capabilities   = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
                          MMC_CAP_POWER_OFF_CARD,
-       .tmio_flags     = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_USE_GPIO_CD,
+       .flags          = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_USE_GPIO_CD,
        .cd_gpio        = 167,
 };
 
@@ -796,12 +796,12 @@ static struct platform_device sdhi0_device = {
 };
 
 /* SDHI1 */
-static struct sh_mobile_sdhi_info sdhi1_info = {
-       .dma_slave_tx   = SHDMA_SLAVE_SDHI1_TX,
-       .dma_slave_rx   = SHDMA_SLAVE_SDHI1_RX,
-       .tmio_caps      = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
+static struct tmio_mmc_data sdhi1_info = {
+       .chan_priv_tx   = (void *)SHDMA_SLAVE_SDHI1_TX,
+       .chan_priv_rx   = (void *)SHDMA_SLAVE_SDHI1_RX,
+       .capabilities   = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
                          MMC_CAP_POWER_OFF_CARD,
-       .tmio_flags     = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_USE_GPIO_CD,
+       .flags          = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_USE_GPIO_CD,
        /* Port72 cannot generate IRQs, will be used in polling mode. */
        .cd_gpio        = 72,
 };
index d649ade4a202a2794abb107fd5b252047b5958c9..9a74efda3d18a8c45b0ac898205f7a5ac373917b 100644 (file)
@@ -36,7 +36,9 @@ static void __init bockw_init(void)
        void __iomem *fpga;
        void __iomem *pfc;
 
+#ifndef CONFIG_COMMON_CLK
        r8a7778_clock_init();
+#endif
        r8a7778_init_irq_extpin_dt(1);
        r8a7778_add_dt_devices();
 
index f27b5a833bf0bb966a7046ae18a64f3f306f3134..25558d1f417f6bf5fab72a9b36ecf43c2fb467d0 100644 (file)
@@ -201,12 +201,12 @@ static struct rcar_phy_platform_data usb_phy_platform_data __initdata =
 
 
 /* SDHI */
-static struct sh_mobile_sdhi_info sdhi0_info __initdata = {
-       .dma_slave_tx   = HPBDMA_SLAVE_SDHI0_TX,
-       .dma_slave_rx   = HPBDMA_SLAVE_SDHI0_RX,
-       .tmio_caps      = MMC_CAP_SD_HIGHSPEED,
-       .tmio_ocr_mask  = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
-       .tmio_flags     = TMIO_MMC_HAS_IDLE_WAIT,
+static struct tmio_mmc_data sdhi0_info __initdata = {
+       .chan_priv_tx   = (void *)HPBDMA_SLAVE_SDHI0_TX,
+       .chan_priv_rx   = (void *)HPBDMA_SLAVE_SDHI0_RX,
+       .capabilities   = MMC_CAP_SD_HIGHSPEED,
+       .ocr_mask       = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
+       .flags          = TMIO_MMC_HAS_IDLE_WAIT,
 };
 
 static struct resource sdhi0_resources[] __initdata = {
@@ -683,7 +683,7 @@ static void __init bockw_init(void)
                platform_device_register_resndata(
                        NULL, "sh_mobile_sdhi", 0,
                        sdhi0_resources, ARRAY_SIZE(sdhi0_resources),
-                       &sdhi0_info, sizeof(struct sh_mobile_sdhi_info));
+                       &sdhi0_info, sizeof(struct tmio_mmc_data));
        }
 
        /* for Audio */
diff --git a/arch/arm/mach-shmobile/board-kzm9g-reference.c b/arch/arm/mach-shmobile/board-kzm9g-reference.c
deleted file mode 100644 (file)
index 2e82e44..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * KZM-A9-GT board support - Reference Device Tree Implementation
- *
- * Copyright (C) 2012  Horms Solutions Ltd.
- *
- * Based on board-kzm9g.c
- * Copyright (C) 2012  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/delay.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/input.h>
-#include <linux/of_platform.h>
-
-#include <asm/hardware/cache-l2x0.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-#include "common.h"
-#include "sh73a0.h"
-
-static void __init kzm_init(void)
-{
-       sh73a0_add_standard_devices_dt();
-
-#ifdef CONFIG_CACHE_L2X0
-       /* Shared attribute override enable, 64K*8way */
-       l2x0_init(IOMEM(0xf0100000), 0x00400000, 0xc20f0fff);
-#endif
-}
-
-#define RESCNT2 IOMEM(0xe6188020)
-static void kzm9g_restart(enum reboot_mode mode, const char *cmd)
-{
-       /* Do soft power on reset */
-       writel((1 << 31), RESCNT2);
-}
-
-static const char *kzm9g_boards_compat_dt[] __initdata = {
-       "renesas,kzm9g-reference",
-       NULL,
-};
-
-DT_MACHINE_START(KZM9G_DT, "kzm9g-reference")
-       .smp            = smp_ops(sh73a0_smp_ops),
-       .map_io         = sh73a0_map_io,
-       .init_early     = shmobile_init_delay,
-       .init_machine   = kzm_init,
-       .init_late      = shmobile_init_late,
-       .restart        = kzm9g_restart,
-       .dt_compat      = kzm9g_boards_compat_dt,
-MACHINE_END
index 7c9b63bdde9fa458c3ddc7aa751030e0484beaf2..260d8319fd82f92773547373ecb269ea8c133e50 100644 (file)
@@ -442,11 +442,11 @@ static struct platform_device vcc_sdhi2 = {
 };
 
 /* SDHI */
-static struct sh_mobile_sdhi_info sdhi0_info = {
-       .dma_slave_tx   = SHDMA_SLAVE_SDHI0_TX,
-       .dma_slave_rx   = SHDMA_SLAVE_SDHI0_RX,
-       .tmio_flags     = TMIO_MMC_HAS_IDLE_WAIT,
-       .tmio_caps      = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
+static struct tmio_mmc_data sdhi0_info = {
+       .chan_priv_tx   = (void *)SHDMA_SLAVE_SDHI0_TX,
+       .chan_priv_rx   = (void *)SHDMA_SLAVE_SDHI0_RX,
+       .flags          = TMIO_MMC_HAS_IDLE_WAIT,
+       .capabilities   = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
                          MMC_CAP_POWER_OFF_CARD,
 };
 
@@ -484,13 +484,13 @@ static struct platform_device sdhi0_device = {
 };
 
 /* Micro SD */
-static struct sh_mobile_sdhi_info sdhi2_info = {
-       .dma_slave_tx   = SHDMA_SLAVE_SDHI2_TX,
-       .dma_slave_rx   = SHDMA_SLAVE_SDHI2_RX,
-       .tmio_flags     = TMIO_MMC_HAS_IDLE_WAIT |
+static struct tmio_mmc_data sdhi2_info = {
+       .chan_priv_tx   = (void *)SHDMA_SLAVE_SDHI2_TX,
+       .chan_priv_rx   = (void *)SHDMA_SLAVE_SDHI2_RX,
+       .flags          = TMIO_MMC_HAS_IDLE_WAIT |
                          TMIO_MMC_USE_GPIO_CD |
                          TMIO_MMC_WRPROTECT_DISABLE,
-       .tmio_caps      = MMC_CAP_SD_HIGHSPEED | MMC_CAP_POWER_OFF_CARD,
+       .capabilities   = MMC_CAP_SD_HIGHSPEED | MMC_CAP_POWER_OFF_CARD,
        .cd_gpio        = 13,
 };
 
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
deleted file mode 100644 (file)
index a1c1dfb..0000000
+++ /dev/null
@@ -1,1522 +0,0 @@
-/*
- * mackerel board support
- *
- * Copyright (C) 2010 Renesas Solutions Corp.
- * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
- *
- * based on ap4evb
- * 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/delay.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/input.h>
-#include <linux/io.h>
-#include <linux/i2c.h>
-#include <linux/leds.h>
-#include <linux/mfd/tmio.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/sh_mmcif.h>
-#include <linux/mmc/sh_mobile_sdhi.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/physmap.h>
-#include <linux/mtd/sh_flctl.h>
-#include <linux/pinctrl/machine.h>
-#include <linux/pinctrl/pinconf-generic.h>
-#include <linux/platform_data/gpio_backlight.h>
-#include <linux/pm_clock.h>
-#include <linux/regulator/fixed.h>
-#include <linux/regulator/machine.h>
-#include <linux/smsc911x.h>
-#include <linux/sh_clk.h>
-#include <linux/tca6416_keypad.h>
-#include <linux/usb/renesas_usbhs.h>
-#include <linux/dma-mapping.h>
-
-#include <video/sh_mobile_hdmi.h>
-#include <video/sh_mobile_lcdc.h>
-#include <media/sh_mobile_ceu.h>
-#include <media/soc_camera.h>
-#include <media/soc_camera_platform.h>
-#include <sound/sh_fsi.h>
-#include <sound/simple_card.h>
-#include <asm/mach/arch.h>
-#include <asm/mach-types.h>
-
-#include "common.h"
-#include "intc.h"
-#include "irqs.h"
-#include "pm-rmobile.h"
-#include "sh-gpio.h"
-#include "sh7372.h"
-
-/*
- * Address     Interface               BusWidth        note
- * ------------------------------------------------------------------
- * 0x0000_0000 NOR Flash ROM (MCP)     16bit           SW7 : bit1 = ON
- * 0x0800_0000 user area               -
- * 0x1000_0000 NOR Flash ROM (MCP)     16bit           SW7 : bit1 = OFF
- * 0x1400_0000 Ether (LAN9220)         16bit
- * 0x1600_0000 user area               -               cannot use with NAND
- * 0x1800_0000 user area               -
- * 0x1A00_0000 -
- * 0x4000_0000 LPDDR2-SDRAM (POP)      32bit
- */
-
-/*
- * CPU mode
- *
- * SW4                                     | Boot Area| Master   | Remarks
- *  1  | 2   | 3   | 4   | 5   | 6   | 8   |          | Processor|
- * ----+-----+-----+-----+-----+-----+-----+----------+----------+--------------
- * ON  | ON  | OFF | ON  | ON  | OFF | OFF | External | System   | External ROM
- * ON  | ON  | ON  | ON  | ON  | OFF | OFF | External | System   | ROM Debug
- * ON  | ON  | X   | ON  | OFF | OFF | OFF | Built-in | System   | ROM Debug
- * X   | OFF | X   | X   | X   | X   | OFF | Built-in | System   | MaskROM
- * OFF | X   | X   | X   | X   | X   | OFF | Built-in | System   | MaskROM
- * X   | X   | X   | OFF | X   | X   | OFF | Built-in | System   | MaskROM
- * OFF | ON  | OFF | X   | X   | OFF | ON  | External | System   | Standalone
- * ON  | OFF | OFF | X   | X   | OFF | ON  | External | Realtime | Standalone
-*/
-
-/*
- * NOR Flash ROM
- *
- *  SW1  |     SW2    | SW7  | NOR Flash ROM
- *  bit1 | bit1  bit2 | bit1 | Memory allocation
- * ------+------------+------+------------------
- *  OFF  | ON     OFF | ON   |    Area 0
- *  OFF  | ON     OFF | OFF  |    Area 4
- */
-
-/*
- * SMSC 9220
- *
- *  SW1                SMSC 9220
- * -----------------------
- *  ON         access disable
- *  OFF                access enable
- */
-
-/*
- * NAND Flash ROM
- *
- *  SW1  |     SW2    | SW7  | NAND Flash ROM
- *  bit1 | bit1  bit2 | bit2 | Memory allocation
- * ------+------------+------+------------------
- *  OFF  | ON     OFF | ON   |    FCE 0
- *  OFF  | ON     OFF | OFF  |    FCE 1
- */
-
-/*
- * External interrupt pin settings
- *
- * IRQX  | pin setting        | device             | level
- * ------+--------------------+--------------------+-------
- * IRQ0  | ICR1A.IRQ0SA=0010  | SDHI2 card detect  | Low
- * IRQ6  | ICR1A.IRQ6SA=0011  | Ether(LAN9220)     | High
- * IRQ7  | ICR1A.IRQ7SA=0010  | LCD Touch Panel    | Low
- * IRQ8  | ICR2A.IRQ8SA=0010  | MMC/SD card detect | Low
- * IRQ9  | ICR2A.IRQ9SA=0010  | KEY(TCA6408)       | Low
- * IRQ21 | ICR4A.IRQ21SA=0011 | Sensor(ADXL345)    | High
- * IRQ22 | ICR4A.IRQ22SA=0011 | Sensor(AK8975)     | High
- */
-
-/*
- * USB
- *
- * USB0 : CN22 : Function
- * USB1 : CN31 : Function/Host *1
- *
- * J30 (for CN31) *1
- * ----------+---------------+-------------
- * 1-2 short | VBUS 5V       | Host
- * open      | external VBUS | Function
- *
- * CAUTION
- *
- * renesas_usbhs driver can use external interrupt mode
- * (which come from USB-PHY) or autonomy mode (it use own interrupt)
- * for detecting connection/disconnection when Function.
- * USB will be power OFF while it has been disconnecting
- * if external interrupt mode, and it is always power ON if autonomy mode,
- *
- * mackerel can not use external interrupt (IRQ7-PORT167) mode on "USB0",
- * because Touchscreen is using IRQ7-PORT40.
- * It is impossible to use IRQ7 demux on this board.
- */
-
-/*
- * SDHI0 (CN12)
- *
- * SW56 : OFF
- *
- */
-
-/* MMC /SDHI1 (CN7)
- *
- * I/O voltage : 1.8v
- *
- * Power voltage : 1.8v or 3.3v
- *  J22 : select power voltage *1
- *     1-2 pin : 1.8v
- *     2-3 pin : 3.3v
- *
- * *1
- * Please change J22 depends the card to be used.
- * MMC's OCR field set to support either voltage for the card inserted.
- *
- *     SW1     |       SW33
- *             | bit1 | bit2 | bit3 | bit4
- * -------------+------+------+------+-------
- * MMC0   OFF  |  OFF |   X  |  ON  |  X       (Use MMCIF)
- * SDHI1  OFF  |  ON  |   X  |  OFF |  X       (Use MFD_SH_MOBILE_SDHI)
- *
- */
-
-/*
- * SDHI2 (CN23)
- *
- * microSD card sloct
- *
- */
-
-/*
- * FSI - AK4642
- *
- * it needs amixer settings for playing
- *
- * amixer set "Headphone Enable" on
- */
-
-/* Fixed 3.3V and 1.8V regulators to be used by multiple devices */
-static struct regulator_consumer_supply fixed1v8_power_consumers[] =
-{
-       /*
-        * J22 on mackerel switches mmcif.0 and sdhi.1 between 1.8V and 3.3V
-        * Since we cannot support both voltages, we support the default 1.8V
-        */
-       REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.1"),
-       REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.1"),
-       REGULATOR_SUPPLY("vmmc", "sh_mmcif.0"),
-       REGULATOR_SUPPLY("vqmmc", "sh_mmcif.0"),
-};
-
-static struct regulator_consumer_supply fixed3v3_power_consumers[] =
-{
-       REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"),
-       REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.0"),
-       REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.2"),
-       REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.2"),
-};
-
-/* Dummy supplies, where voltage doesn't matter */
-static struct regulator_consumer_supply dummy_supplies[] = {
-       REGULATOR_SUPPLY("vddvario", "smsc911x"),
-       REGULATOR_SUPPLY("vdd33a", "smsc911x"),
-};
-
-/* MTD */
-static struct mtd_partition nor_flash_partitions[] = {
-       {
-               .name           = "loader",
-               .offset         = 0x00000000,
-               .size           = 512 * 1024,
-               .mask_flags     = MTD_WRITEABLE,
-       },
-       {
-               .name           = "bootenv",
-               .offset         = MTDPART_OFS_APPEND,
-               .size           = 512 * 1024,
-               .mask_flags     = MTD_WRITEABLE,
-       },
-       {
-               .name           = "kernel_ro",
-               .offset         = MTDPART_OFS_APPEND,
-               .size           = 8 * 1024 * 1024,
-               .mask_flags     = MTD_WRITEABLE,
-       },
-       {
-               .name           = "kernel",
-               .offset         = MTDPART_OFS_APPEND,
-               .size           = 8 * 1024 * 1024,
-       },
-       {
-               .name           = "data",
-               .offset         = MTDPART_OFS_APPEND,
-               .size           = MTDPART_SIZ_FULL,
-       },
-};
-
-static struct physmap_flash_data nor_flash_data = {
-       .width          = 2,
-       .parts          = nor_flash_partitions,
-       .nr_parts       = ARRAY_SIZE(nor_flash_partitions),
-};
-
-static struct resource nor_flash_resources[] = {
-       [0]     = {
-               .start  = 0x20000000, /* CS0 shadow instead of regular CS0 */
-               .end    = 0x28000000 - 1, /* needed by USB MASK ROM boot */
-               .flags  = IORESOURCE_MEM,
-       }
-};
-
-static struct platform_device nor_flash_device = {
-       .name           = "physmap-flash",
-       .dev            = {
-               .platform_data  = &nor_flash_data,
-       },
-       .num_resources  = ARRAY_SIZE(nor_flash_resources),
-       .resource       = nor_flash_resources,
-};
-
-/* SMSC */
-static struct resource smc911x_resources[] = {
-       {
-               .start  = 0x14000000,
-               .end    = 0x16000000 - 1,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .start  = evt2irq(0x02c0) /* IRQ6A */,
-               .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
-       },
-};
-
-static struct smsc911x_platform_config smsc911x_info = {
-       .flags          = SMSC911X_USE_16BIT | SMSC911X_SAVE_MAC_ADDRESS,
-       .irq_polarity   = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
-       .irq_type       = SMSC911X_IRQ_TYPE_PUSH_PULL,
-};
-
-static struct platform_device smc911x_device = {
-       .name           = "smsc911x",
-       .id             = -1,
-       .num_resources  = ARRAY_SIZE(smc911x_resources),
-       .resource       = smc911x_resources,
-       .dev            = {
-               .platform_data = &smsc911x_info,
-       },
-};
-
-/* MERAM */
-static struct sh_mobile_meram_info mackerel_meram_info = {
-       .addr_mode      = SH_MOBILE_MERAM_MODE1,
-};
-
-static struct resource meram_resources[] = {
-       [0] = {
-               .name   = "regs",
-               .start  = 0xe8000000,
-               .end    = 0xe807ffff,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .name   = "meram",
-               .start  = 0xe8080000,
-               .end    = 0xe81fffff,
-               .flags  = IORESOURCE_MEM,
-       },
-};
-
-static struct platform_device meram_device = {
-       .name           = "sh_mobile_meram",
-       .id             = 0,
-       .num_resources  = ARRAY_SIZE(meram_resources),
-       .resource       = meram_resources,
-       .dev            = {
-               .platform_data = &mackerel_meram_info,
-       },
-};
-
-/* LCDC and backlight */
-static struct fb_videomode mackerel_lcdc_modes[] = {
-       {
-               .name           = "WVGA Panel",
-               .xres           = 800,
-               .yres           = 480,
-               .left_margin    = 220,
-               .right_margin   = 110,
-               .hsync_len      = 70,
-               .upper_margin   = 20,
-               .lower_margin   = 5,
-               .vsync_len      = 5,
-               .sync           = 0,
-       },
-};
-
-static const struct sh_mobile_meram_cfg lcd_meram_cfg = {
-       .icb[0] = {
-               .meram_size     = 0x40,
-       },
-       .icb[1] = {
-               .meram_size     = 0x40,
-       },
-};
-
-static struct sh_mobile_lcdc_info lcdc_info = {
-       .meram_dev = &mackerel_meram_info,
-       .clock_source = LCDC_CLK_BUS,
-       .ch[0] = {
-               .chan = LCDC_CHAN_MAINLCD,
-               .fourcc = V4L2_PIX_FMT_RGB565,
-               .lcd_modes = mackerel_lcdc_modes,
-               .num_modes = ARRAY_SIZE(mackerel_lcdc_modes),
-               .interface_type         = RGB24,
-               .clock_divider          = 3,
-               .flags                  = 0,
-               .panel_cfg = {
-                       .width          = 152,
-                       .height         = 91,
-               },
-               .meram_cfg = &lcd_meram_cfg,
-       }
-};
-
-static struct resource lcdc_resources[] = {
-       [0] = {
-               .name   = "LCDC",
-               .start  = 0xfe940000,
-               .end    = 0xfe943fff,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = intcs_evt2irq(0x580),
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device lcdc_device = {
-       .name           = "sh_mobile_lcdc_fb",
-       .num_resources  = ARRAY_SIZE(lcdc_resources),
-       .resource       = lcdc_resources,
-       .dev    = {
-               .platform_data  = &lcdc_info,
-               .coherent_dma_mask = DMA_BIT_MASK(32),
-       },
-};
-
-static struct gpio_backlight_platform_data gpio_backlight_data = {
-       .fbdev = &lcdc_device.dev,
-       .gpio = 31,
-       .def_value = 1,
-       .name = "backlight",
-};
-
-static struct platform_device gpio_backlight_device = {
-       .name = "gpio-backlight",
-       .dev = {
-               .platform_data = &gpio_backlight_data,
-       },
-};
-
-/* HDMI */
-static struct sh_mobile_hdmi_info hdmi_info = {
-       .flags          = HDMI_SND_SRC_SPDIF,
-};
-
-static struct resource hdmi_resources[] = {
-       [0] = {
-               .name   = "HDMI",
-               .start  = 0xe6be0000,
-               .end    = 0xe6be00ff,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               /* There's also an HDMI interrupt on INTCS @ 0x18e0 */
-               .start  = evt2irq(0x17e0),
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device hdmi_device = {
-       .name           = "sh-mobile-hdmi",
-       .num_resources  = ARRAY_SIZE(hdmi_resources),
-       .resource       = hdmi_resources,
-       .id             = -1,
-       .dev    = {
-               .platform_data  = &hdmi_info,
-       },
-};
-
-static const struct sh_mobile_meram_cfg hdmi_meram_cfg = {
-       .icb[0] = {
-               .meram_size     = 0x100,
-       },
-       .icb[1] = {
-               .meram_size     = 0x100,
-       },
-};
-
-static struct sh_mobile_lcdc_info hdmi_lcdc_info = {
-       .meram_dev = &mackerel_meram_info,
-       .clock_source = LCDC_CLK_EXTERNAL,
-       .ch[0] = {
-               .chan = LCDC_CHAN_MAINLCD,
-               .fourcc = V4L2_PIX_FMT_RGB565,
-               .interface_type = RGB24,
-               .clock_divider = 1,
-               .flags = LCDC_FLAGS_DWPOL,
-               .meram_cfg = &hdmi_meram_cfg,
-               .tx_dev = &hdmi_device,
-       }
-};
-
-static struct resource hdmi_lcdc_resources[] = {
-       [0] = {
-               .name   = "LCDC1",
-               .start  = 0xfe944000,
-               .end    = 0xfe947fff,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = intcs_evt2irq(0x1780),
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device hdmi_lcdc_device = {
-       .name           = "sh_mobile_lcdc_fb",
-       .num_resources  = ARRAY_SIZE(hdmi_lcdc_resources),
-       .resource       = hdmi_lcdc_resources,
-       .id             = 1,
-       .dev    = {
-               .platform_data  = &hdmi_lcdc_info,
-               .coherent_dma_mask = DMA_BIT_MASK(32),
-       },
-};
-
-static struct asoc_simple_card_info fsi2_hdmi_info = {
-       .name           = "HDMI",
-       .card           = "FSI2B-HDMI",
-       .codec          = "sh-mobile-hdmi",
-       .platform       = "sh_fsi2",
-       .daifmt         = SND_SOC_DAIFMT_CBS_CFS,
-       .cpu_dai = {
-               .name   = "fsib-dai",
-       },
-       .codec_dai = {
-               .name   = "sh_mobile_hdmi-hifi",
-       },
-};
-
-static struct platform_device fsi_hdmi_device = {
-       .name   = "asoc-simple-card",
-       .id     = 1,
-       .dev    = {
-               .platform_data  = &fsi2_hdmi_info,
-               .coherent_dma_mask = DMA_BIT_MASK(32),
-               .dma_mask = &fsi_hdmi_device.dev.coherent_dma_mask,
-       },
-};
-
-static void __init hdmi_init_pm_clock(void)
-{
-       struct clk *hdmi_ick = clk_get(&hdmi_device.dev, "ick");
-       int ret;
-       long rate;
-
-       if (IS_ERR(hdmi_ick)) {
-               ret = PTR_ERR(hdmi_ick);
-               pr_err("Cannot get HDMI ICK: %d\n", ret);
-               goto out;
-       }
-
-       ret = clk_set_parent(&sh7372_pllc2_clk, &sh7372_dv_clki_div2_clk);
-       if (ret < 0) {
-               pr_err("Cannot set PLLC2 parent: %d, %d users\n",
-                      ret, sh7372_pllc2_clk.usecount);
-               goto out;
-       }
-
-       pr_debug("PLLC2 initial frequency %lu\n",
-                clk_get_rate(&sh7372_pllc2_clk));
-
-       rate = clk_round_rate(&sh7372_pllc2_clk, 594000000);
-       if (rate <= 0) {
-               pr_err("Cannot get suitable rate: %ld\n", rate);
-               ret = -EINVAL;
-               goto out;
-       }
-
-       ret = clk_set_rate(&sh7372_pllc2_clk, rate);
-       if (ret < 0) {
-               pr_err("Cannot set rate %ld: %d\n", rate, ret);
-               goto out;
-       }
-
-       pr_debug("PLLC2 set frequency %lu\n", rate);
-
-       ret = clk_set_parent(hdmi_ick, &sh7372_pllc2_clk);
-       if (ret < 0)
-               pr_err("Cannot set HDMI parent: %d\n", ret);
-
-out:
-       if (!IS_ERR(hdmi_ick))
-               clk_put(hdmi_ick);
-}
-
-/* USBHS0 is connected to CN22 which takes a USB Mini-B plug
- *
- * The sh7372 SoC has IRQ7 set aside for USBHS0 hotplug,
- * but on this particular board IRQ7 is already used by
- * the touch screen. This leaves us with software polling.
- */
-#define USBHS0_POLL_INTERVAL (HZ * 5)
-
-struct usbhs_private {
-       void __iomem *usbphyaddr;
-       void __iomem *usbcrcaddr;
-       struct renesas_usbhs_platform_info info;
-       struct delayed_work work;
-       struct platform_device *pdev;
-};
-
-#define usbhs_get_priv(pdev)                           \
-       container_of(renesas_usbhs_get_info(pdev),      \
-                    struct usbhs_private, info)
-
-#define usbhs_is_connected(priv)                       \
-       (!((1 << 7) & __raw_readw(priv->usbcrcaddr)))
-
-static int usbhs_get_vbus(struct platform_device *pdev)
-{
-       return usbhs_is_connected(usbhs_get_priv(pdev));
-}
-
-static int usbhs_phy_reset(struct platform_device *pdev)
-{
-       struct usbhs_private *priv = usbhs_get_priv(pdev);
-
-       /* init phy */
-       __raw_writew(0x8a0a, priv->usbcrcaddr);
-
-       return 0;
-}
-
-static int usbhs0_get_id(struct platform_device *pdev)
-{
-       return USBHS_GADGET;
-}
-
-static void usbhs0_work_function(struct work_struct *work)
-{
-       struct usbhs_private *priv = container_of(work, struct usbhs_private,
-                                                 work.work);
-
-       renesas_usbhs_call_notify_hotplug(priv->pdev);
-       schedule_delayed_work(&priv->work, USBHS0_POLL_INTERVAL);
-}
-
-static int usbhs0_hardware_init(struct platform_device *pdev)
-{
-       struct usbhs_private *priv = usbhs_get_priv(pdev);
-
-       priv->pdev = pdev;
-       INIT_DELAYED_WORK(&priv->work, usbhs0_work_function);
-       schedule_delayed_work(&priv->work, USBHS0_POLL_INTERVAL);
-       return 0;
-}
-
-static int usbhs0_hardware_exit(struct platform_device *pdev)
-{
-       struct usbhs_private *priv = usbhs_get_priv(pdev);
-
-       cancel_delayed_work_sync(&priv->work);
-
-       return 0;
-}
-
-static struct usbhs_private usbhs0_private = {
-       .usbcrcaddr     = IOMEM(0xe605810c),            /* USBCR2 */
-       .info = {
-               .platform_callback = {
-                       .hardware_init  = usbhs0_hardware_init,
-                       .hardware_exit  = usbhs0_hardware_exit,
-                       .phy_reset      = usbhs_phy_reset,
-                       .get_id         = usbhs0_get_id,
-                       .get_vbus       = usbhs_get_vbus,
-               },
-               .driver_param = {
-                       .buswait_bwait  = 4,
-                       .d0_tx_id       = SHDMA_SLAVE_USB0_TX,
-                       .d1_rx_id       = SHDMA_SLAVE_USB0_RX,
-               },
-       },
-};
-
-static struct resource usbhs0_resources[] = {
-       [0] = {
-               .name   = "USBHS0",
-               .start  = 0xe6890000,
-               .end    = 0xe68900e6 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = evt2irq(0x1ca0) /* USB0_USB0I0 */,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device usbhs0_device = {
-       .name   = "renesas_usbhs",
-       .id     = 0,
-       .dev = {
-               .platform_data          = &usbhs0_private.info,
-       },
-       .num_resources  = ARRAY_SIZE(usbhs0_resources),
-       .resource       = usbhs0_resources,
-};
-
-/* USBHS1 is connected to CN31 which takes a USB Mini-AB plug
- *
- * Use J30 to select between Host and Function. This setting
- * can however not be detected by software. Hotplug of USBHS1
- * is provided via IRQ8.
- *
- * Current USB1 works as "USB Host".
- *  - set J30 "short"
- *
- * If you want to use it as "USB gadget",
- *  - J30 "open"
- *  - modify usbhs1_get_id() USBHS_HOST -> USBHS_GADGET
- *  - add .get_vbus = usbhs_get_vbus in usbhs1_private
- *  - check usbhs0_device(pio)/usbhs1_device(irq) order in mackerel_devices.
- */
-#define IRQ8 evt2irq(0x0300)
-#define USB_PHY_MODE           (1 << 4)
-#define USB_PHY_INT_EN         ((1 << 3) | (1 << 2))
-#define USB_PHY_ON             (1 << 1)
-#define USB_PHY_OFF            (1 << 0)
-#define USB_PHY_INT_CLR                (USB_PHY_ON | USB_PHY_OFF)
-
-static irqreturn_t usbhs1_interrupt(int irq, void *data)
-{
-       struct platform_device *pdev = data;
-       struct usbhs_private *priv = usbhs_get_priv(pdev);
-
-       dev_dbg(&pdev->dev, "%s\n", __func__);
-
-       renesas_usbhs_call_notify_hotplug(pdev);
-
-       /* clear status */
-       __raw_writew(__raw_readw(priv->usbphyaddr) | USB_PHY_INT_CLR,
-                    priv->usbphyaddr);
-
-       return IRQ_HANDLED;
-}
-
-static int usbhs1_hardware_init(struct platform_device *pdev)
-{
-       struct usbhs_private *priv = usbhs_get_priv(pdev);
-       int ret;
-
-       /* clear interrupt status */
-       __raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->usbphyaddr);
-
-       ret = request_irq(IRQ8, usbhs1_interrupt, IRQF_TRIGGER_HIGH,
-                         dev_name(&pdev->dev), pdev);
-       if (ret) {
-               dev_err(&pdev->dev, "request_irq err\n");
-               return ret;
-       }
-
-       /* enable USB phy interrupt */
-       __raw_writew(USB_PHY_MODE | USB_PHY_INT_EN, priv->usbphyaddr);
-
-       return 0;
-}
-
-static int usbhs1_hardware_exit(struct platform_device *pdev)
-{
-       struct usbhs_private *priv = usbhs_get_priv(pdev);
-
-       /* clear interrupt status */
-       __raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->usbphyaddr);
-
-       free_irq(IRQ8, pdev);
-
-       return 0;
-}
-
-static int usbhs1_get_id(struct platform_device *pdev)
-{
-       return USBHS_HOST;
-}
-
-static u32 usbhs1_pipe_cfg[] = {
-       USB_ENDPOINT_XFER_CONTROL,
-       USB_ENDPOINT_XFER_ISOC,
-       USB_ENDPOINT_XFER_ISOC,
-       USB_ENDPOINT_XFER_BULK,
-       USB_ENDPOINT_XFER_BULK,
-       USB_ENDPOINT_XFER_BULK,
-       USB_ENDPOINT_XFER_INT,
-       USB_ENDPOINT_XFER_INT,
-       USB_ENDPOINT_XFER_INT,
-       USB_ENDPOINT_XFER_BULK,
-       USB_ENDPOINT_XFER_BULK,
-       USB_ENDPOINT_XFER_BULK,
-       USB_ENDPOINT_XFER_BULK,
-       USB_ENDPOINT_XFER_BULK,
-       USB_ENDPOINT_XFER_BULK,
-       USB_ENDPOINT_XFER_BULK,
-};
-
-static struct usbhs_private usbhs1_private = {
-       .usbphyaddr     = IOMEM(0xe60581e2),    /* USBPHY1INTAP */
-       .usbcrcaddr     = IOMEM(0xe6058130),    /* USBCR4 */
-       .info = {
-               .platform_callback = {
-                       .hardware_init  = usbhs1_hardware_init,
-                       .hardware_exit  = usbhs1_hardware_exit,
-                       .get_id         = usbhs1_get_id,
-                       .phy_reset      = usbhs_phy_reset,
-               },
-               .driver_param = {
-                       .buswait_bwait  = 4,
-                       .has_otg        = 1,
-                       .pipe_type      = usbhs1_pipe_cfg,
-                       .pipe_size      = ARRAY_SIZE(usbhs1_pipe_cfg),
-                       .d0_tx_id       = SHDMA_SLAVE_USB1_TX,
-                       .d1_rx_id       = SHDMA_SLAVE_USB1_RX,
-               },
-       },
-};
-
-static struct resource usbhs1_resources[] = {
-       [0] = {
-               .name   = "USBHS1",
-               .start  = 0xe68b0000,
-               .end    = 0xe68b00e6 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = evt2irq(0x1ce0) /* USB1_USB1I0 */,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device usbhs1_device = {
-       .name   = "renesas_usbhs",
-       .id     = 1,
-       .dev = {
-               .platform_data          = &usbhs1_private.info,
-               .dma_mask               = &usbhs1_device.dev.coherent_dma_mask,
-               .coherent_dma_mask      = DMA_BIT_MASK(32),
-       },
-       .num_resources  = ARRAY_SIZE(usbhs1_resources),
-       .resource       = usbhs1_resources,
-};
-
-/* LED */
-static struct gpio_led mackerel_leds[] = {
-       {
-               .name           = "led0",
-               .gpio           = 0,
-               .default_state  = LEDS_GPIO_DEFSTATE_ON,
-       },
-       {
-               .name           = "led1",
-               .gpio           = 1,
-               .default_state  = LEDS_GPIO_DEFSTATE_ON,
-       },
-       {
-               .name           = "led2",
-               .gpio           = 2,
-               .default_state  = LEDS_GPIO_DEFSTATE_ON,
-       },
-       {
-               .name           = "led3",
-               .gpio           = 159,
-               .default_state  = LEDS_GPIO_DEFSTATE_ON,
-       }
-};
-
-static struct gpio_led_platform_data mackerel_leds_pdata = {
-       .leds = mackerel_leds,
-       .num_leds = ARRAY_SIZE(mackerel_leds),
-};
-
-static struct platform_device leds_device = {
-       .name = "leds-gpio",
-       .id = 0,
-       .dev = {
-               .platform_data  = &mackerel_leds_pdata,
-       },
-};
-
-/* FSI */
-#define IRQ_FSI evt2irq(0x1840)
-static struct sh_fsi_platform_info fsi_info = {
-       .port_a = {
-               .tx_id = SHDMA_SLAVE_FSIA_TX,
-               .rx_id = SHDMA_SLAVE_FSIA_RX,
-       },
-       .port_b = {
-               .flags = SH_FSI_CLK_CPG |
-                        SH_FSI_FMT_SPDIF,
-       }
-};
-
-static struct resource fsi_resources[] = {
-       [0] = {
-               /* we need 0xFE1F0000 to access DMA
-                * instead of 0xFE3C0000 */
-               .name   = "FSI",
-               .start  = 0xFE1F0000,
-               .end    = 0xFE1F0400 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_FSI,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device fsi_device = {
-       .name           = "sh_fsi2",
-       .id             = -1,
-       .num_resources  = ARRAY_SIZE(fsi_resources),
-       .resource       = fsi_resources,
-       .dev    = {
-               .platform_data  = &fsi_info,
-       },
-};
-
-static struct asoc_simple_card_info fsi2_ak4643_info = {
-       .name           = "AK4643",
-       .card           = "FSI2A-AK4643",
-       .codec          = "ak4642-codec.0-0013",
-       .platform       = "sh_fsi2",
-       .daifmt         = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM,
-       .cpu_dai = {
-               .name   = "fsia-dai",
-       },
-       .codec_dai = {
-               .name   = "ak4642-hifi",
-               .sysclk = 11289600,
-       },
-};
-
-static struct platform_device fsi_ak4643_device = {
-       .name   = "asoc-simple-card",
-       .dev    = {
-               .platform_data  = &fsi2_ak4643_info,
-               .coherent_dma_mask = DMA_BIT_MASK(32),
-               .dma_mask = &fsi_ak4643_device.dev.coherent_dma_mask,
-       },
-};
-
-/* FLCTL */
-static struct mtd_partition nand_partition_info[] = {
-       {
-               .name   = "system",
-               .offset = 0,
-               .size   = 128 * 1024 * 1024,
-       },
-       {
-               .name   = "userdata",
-               .offset = MTDPART_OFS_APPEND,
-               .size   = 256 * 1024 * 1024,
-       },
-       {
-               .name   = "cache",
-               .offset = MTDPART_OFS_APPEND,
-               .size   = 128 * 1024 * 1024,
-       },
-};
-
-static struct resource nand_flash_resources[] = {
-       [0] = {
-               .start  = 0xe6a30000,
-               .end    = 0xe6a3009b,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = evt2irq(0x0d80), /* flstei: status error irq */
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct sh_flctl_platform_data nand_flash_data = {
-       .parts          = nand_partition_info,
-       .nr_parts       = ARRAY_SIZE(nand_partition_info),
-       .flcmncr_val    = CLK_16B_12L_4H | TYPESEL_SET
-                       | SHBUSSEL | SEL_16BIT | SNAND_E,
-       .use_holden     = 1,
-};
-
-static struct platform_device nand_flash_device = {
-       .name           = "sh_flctl",
-       .resource       = nand_flash_resources,
-       .num_resources  = ARRAY_SIZE(nand_flash_resources),
-       .dev            = {
-               .platform_data = &nand_flash_data,
-       },
-};
-
-/* SDHI0 */
-static struct sh_mobile_sdhi_info sdhi0_info = {
-       .dma_slave_tx   = SHDMA_SLAVE_SDHI0_TX,
-       .dma_slave_rx   = SHDMA_SLAVE_SDHI0_RX,
-       .tmio_flags     = TMIO_MMC_USE_GPIO_CD,
-       .tmio_caps      = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ,
-       .cd_gpio        = 172,
-};
-
-static struct resource sdhi0_resources[] = {
-       {
-               .name   = "SDHI0",
-               .start  = 0xe6850000,
-               .end    = 0xe68500ff,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .name   = SH_MOBILE_SDHI_IRQ_SDCARD,
-               .start  = evt2irq(0x0e20) /* SDHI0_SDHI0I1 */,
-               .flags  = IORESOURCE_IRQ,
-       }, {
-               .name   = SH_MOBILE_SDHI_IRQ_SDIO,
-               .start  = evt2irq(0x0e40) /* SDHI0_SDHI0I2 */,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device sdhi0_device = {
-       .name           = "sh_mobile_sdhi",
-       .num_resources  = ARRAY_SIZE(sdhi0_resources),
-       .resource       = sdhi0_resources,
-       .id             = 0,
-       .dev    = {
-               .platform_data  = &sdhi0_info,
-       },
-};
-
-#if !IS_ENABLED(CONFIG_MMC_SH_MMCIF)
-/* SDHI1 */
-
-/* GPIO 41 can trigger IRQ8, but it is used by USBHS1, we have to poll */
-static struct sh_mobile_sdhi_info sdhi1_info = {
-       .dma_slave_tx   = SHDMA_SLAVE_SDHI1_TX,
-       .dma_slave_rx   = SHDMA_SLAVE_SDHI1_RX,
-       .tmio_flags     = TMIO_MMC_WRPROTECT_DISABLE | TMIO_MMC_USE_GPIO_CD,
-       .tmio_caps      = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
-                         MMC_CAP_NEEDS_POLL,
-       .cd_gpio        = 41,
-};
-
-static struct resource sdhi1_resources[] = {
-       {
-               .name   = "SDHI1",
-               .start  = 0xe6860000,
-               .end    = 0xe68600ff,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .name   = SH_MOBILE_SDHI_IRQ_SDCARD,
-               .start  = evt2irq(0x0ea0), /* SDHI1_SDHI1I1 */
-               .flags  = IORESOURCE_IRQ,
-       }, {
-               .name   = SH_MOBILE_SDHI_IRQ_SDIO,
-               .start  = evt2irq(0x0ec0), /* SDHI1_SDHI1I2 */
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device sdhi1_device = {
-       .name           = "sh_mobile_sdhi",
-       .num_resources  = ARRAY_SIZE(sdhi1_resources),
-       .resource       = sdhi1_resources,
-       .id             = 1,
-       .dev    = {
-               .platform_data  = &sdhi1_info,
-       },
-};
-#endif
-
-/* SDHI2 */
-
-/*
- * The card detect pin of the top SD/MMC slot (CN23) is active low and is
- * connected to GPIO SCIFB_SCK of SH7372 (GPIO 162).
- */
-static struct sh_mobile_sdhi_info sdhi2_info = {
-       .dma_slave_tx   = SHDMA_SLAVE_SDHI2_TX,
-       .dma_slave_rx   = SHDMA_SLAVE_SDHI2_RX,
-       .tmio_flags     = TMIO_MMC_WRPROTECT_DISABLE | TMIO_MMC_USE_GPIO_CD,
-       .tmio_caps      = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
-                         MMC_CAP_NEEDS_POLL,
-       .cd_gpio        = 162,
-};
-
-static struct resource sdhi2_resources[] = {
-       {
-               .name   = "SDHI2",
-               .start  = 0xe6870000,
-               .end    = 0xe68700ff,
-               .flags  = IORESOURCE_MEM,
-       }, {
-               .name   = SH_MOBILE_SDHI_IRQ_SDCARD,
-               .start  = evt2irq(0x1220), /* SDHI2_SDHI2I1 */
-               .flags  = IORESOURCE_IRQ,
-       }, {
-               .name   = SH_MOBILE_SDHI_IRQ_SDIO,
-               .start  = evt2irq(0x1240), /* SDHI2_SDHI2I2 */
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device sdhi2_device = {
-       .name   = "sh_mobile_sdhi",
-       .num_resources  = ARRAY_SIZE(sdhi2_resources),
-       .resource       = sdhi2_resources,
-       .id             = 2,
-       .dev    = {
-               .platform_data  = &sdhi2_info,
-       },
-};
-
-/* SH_MMCIF */
-#if IS_ENABLED(CONFIG_MMC_SH_MMCIF)
-static struct resource sh_mmcif_resources[] = {
-       [0] = {
-               .name   = "MMCIF",
-               .start  = 0xE6BD0000,
-               .end    = 0xE6BD00FF,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               /* MMC ERR */
-               .start  = evt2irq(0x1ac0),
-               .flags  = IORESOURCE_IRQ,
-       },
-       [2] = {
-               /* MMC NOR */
-               .start  = evt2irq(0x1ae0),
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct sh_mmcif_plat_data sh_mmcif_plat = {
-       .sup_pclk       = 0,
-       .caps           = MMC_CAP_4_BIT_DATA |
-                         MMC_CAP_8_BIT_DATA |
-                         MMC_CAP_NEEDS_POLL,
-       .use_cd_gpio    = true,
-       /* card detect pin for SD/MMC slot (CN7) */
-       .cd_gpio        = 41,
-       .slave_id_tx    = SHDMA_SLAVE_MMCIF_TX,
-       .slave_id_rx    = SHDMA_SLAVE_MMCIF_RX,
-};
-
-static struct platform_device sh_mmcif_device = {
-       .name           = "sh_mmcif",
-       .id             = 0,
-       .dev            = {
-               .dma_mask               = NULL,
-               .coherent_dma_mask      = 0xffffffff,
-               .platform_data          = &sh_mmcif_plat,
-       },
-       .num_resources  = ARRAY_SIZE(sh_mmcif_resources),
-       .resource       = sh_mmcif_resources,
-};
-#endif
-
-static int mackerel_camera_add(struct soc_camera_device *icd);
-static void mackerel_camera_del(struct soc_camera_device *icd);
-
-static int camera_set_capture(struct soc_camera_platform_info *info,
-                             int enable)
-{
-       return 0; /* camera sensor always enabled */
-}
-
-static struct soc_camera_platform_info camera_info = {
-       .format_name = "UYVY",
-       .format_depth = 16,
-       .format = {
-               .code = MEDIA_BUS_FMT_UYVY8_2X8,
-               .colorspace = V4L2_COLORSPACE_SMPTE170M,
-               .field = V4L2_FIELD_NONE,
-               .width = 640,
-               .height = 480,
-       },
-       .mbus_param = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER |
-       V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_HIGH |
-       V4L2_MBUS_DATA_ACTIVE_HIGH,
-       .mbus_type = V4L2_MBUS_PARALLEL,
-       .set_capture = camera_set_capture,
-};
-
-static struct soc_camera_link camera_link = {
-       .bus_id         = 0,
-       .add_device     = mackerel_camera_add,
-       .del_device     = mackerel_camera_del,
-       .module_name    = "soc_camera_platform",
-       .priv           = &camera_info,
-};
-
-static struct platform_device *camera_device;
-
-static void mackerel_camera_release(struct device *dev)
-{
-       soc_camera_platform_release(&camera_device);
-}
-
-static int mackerel_camera_add(struct soc_camera_device *icd)
-{
-       return soc_camera_platform_add(icd, &camera_device, &camera_link,
-                                      mackerel_camera_release, 0);
-}
-
-static void mackerel_camera_del(struct soc_camera_device *icd)
-{
-       soc_camera_platform_del(icd, camera_device, &camera_link);
-}
-
-static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
-       .flags = SH_CEU_FLAG_USE_8BIT_BUS,
-       .max_width = 8188,
-       .max_height = 8188,
-};
-
-static struct resource ceu_resources[] = {
-       [0] = {
-               .name   = "CEU",
-               .start  = 0xfe910000,
-               .end    = 0xfe91009f,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = intcs_evt2irq(0x880),
-               .flags  = IORESOURCE_IRQ,
-       },
-       [2] = {
-               /* place holder for contiguous memory */
-       },
-};
-
-static struct platform_device ceu_device = {
-       .name           = "sh_mobile_ceu",
-       .id             = 0, /* "ceu0" clock */
-       .num_resources  = ARRAY_SIZE(ceu_resources),
-       .resource       = ceu_resources,
-       .dev            = {
-               .platform_data          = &sh_mobile_ceu_info,
-               .coherent_dma_mask      = 0xffffffff,
-       },
-};
-
-static struct platform_device mackerel_camera = {
-       .name   = "soc-camera-pdrv",
-       .id     = 0,
-       .dev    = {
-               .platform_data = &camera_link,
-       },
-};
-
-static struct platform_device *mackerel_devices[] __initdata = {
-       &nor_flash_device,
-       &smc911x_device,
-       &lcdc_device,
-       &gpio_backlight_device,
-       &usbhs0_device,
-       &usbhs1_device,
-       &leds_device,
-       &fsi_device,
-       &fsi_ak4643_device,
-       &fsi_hdmi_device,
-       &nand_flash_device,
-       &sdhi0_device,
-#if !IS_ENABLED(CONFIG_MMC_SH_MMCIF)
-       &sdhi1_device,
-#else
-       &sh_mmcif_device,
-#endif
-       &sdhi2_device,
-       &ceu_device,
-       &mackerel_camera,
-       &hdmi_device,
-       &hdmi_lcdc_device,
-       &meram_device,
-};
-
-/* Keypad Initialization */
-#define KEYPAD_BUTTON(ev_type, ev_code, act_low) \
-{                                                              \
-       .type           = ev_type,                              \
-       .code           = ev_code,                              \
-       .active_low     = act_low,                              \
-}
-
-#define KEYPAD_BUTTON_LOW(event_code) KEYPAD_BUTTON(EV_KEY, event_code, 1)
-
-static struct tca6416_button mackerel_gpio_keys[] = {
-       KEYPAD_BUTTON_LOW(KEY_HOME),
-       KEYPAD_BUTTON_LOW(KEY_MENU),
-       KEYPAD_BUTTON_LOW(KEY_BACK),
-       KEYPAD_BUTTON_LOW(KEY_POWER),
-};
-
-static struct tca6416_keys_platform_data mackerel_tca6416_keys_info = {
-       .buttons        = mackerel_gpio_keys,
-       .nbuttons       = ARRAY_SIZE(mackerel_gpio_keys),
-       .rep            = 1,
-       .use_polling    = 0,
-       .pinmask        = 0x000F,
-};
-
-/* I2C */
-#define IRQ7 evt2irq(0x02e0)
-#define IRQ9 evt2irq(0x0320)
-
-static struct i2c_board_info i2c0_devices[] = {
-       {
-               I2C_BOARD_INFO("ak4643", 0x13),
-       },
-       /* Keypad */
-       {
-               I2C_BOARD_INFO("tca6408-keys", 0x20),
-               .platform_data = &mackerel_tca6416_keys_info,
-               .irq = IRQ9,
-       },
-       /* Touchscreen */
-       {
-               I2C_BOARD_INFO("st1232-ts", 0x55),
-               .irq = IRQ7,
-       },
-};
-
-#define IRQ21 evt2irq(0x32a0)
-
-static struct i2c_board_info i2c1_devices[] = {
-       /* Accelerometer */
-       {
-               I2C_BOARD_INFO("adxl34x", 0x53),
-               .irq = IRQ21,
-       },
-};
-
-static unsigned long pin_pulldown_conf[] = {
-       PIN_CONF_PACKED(PIN_CONFIG_BIAS_PULL_DOWN, 0),
-};
-
-static const struct pinctrl_map mackerel_pinctrl_map[] = {
-       /* ADXL34X */
-       PIN_MAP_MUX_GROUP_DEFAULT("1-0053", "pfc-sh7372",
-                                 "intc_irq21", "intc"),
-       /* CEU */
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_ceu.0", "pfc-sh7372",
-                                 "ceu_data_0_7", "ceu"),
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_ceu.0", "pfc-sh7372",
-                                 "ceu_clk_0", "ceu"),
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_ceu.0", "pfc-sh7372",
-                                 "ceu_sync", "ceu"),
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_ceu.0", "pfc-sh7372",
-                                 "ceu_field", "ceu"),
-       /* FLCTL */
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_flctl.0", "pfc-sh7372",
-                                 "flctl_data", "flctl"),
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_flctl.0", "pfc-sh7372",
-                                 "flctl_ce0", "flctl"),
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_flctl.0", "pfc-sh7372",
-                                 "flctl_ctrl", "flctl"),
-       /* FSIA (AK4643) */
-       PIN_MAP_MUX_GROUP_DEFAULT("asoc-simple-card.0", "pfc-sh7372",
-                                 "fsia_sclk_in", "fsia"),
-       PIN_MAP_MUX_GROUP_DEFAULT("asoc-simple-card.0", "pfc-sh7372",
-                                 "fsia_data_in", "fsia"),
-       PIN_MAP_MUX_GROUP_DEFAULT("asoc-simple-card.0", "pfc-sh7372",
-                                 "fsia_data_out", "fsia"),
-       /* FSIB (HDMI) */
-       PIN_MAP_MUX_GROUP_DEFAULT("asoc-simple-card.1", "pfc-sh7372",
-                                 "fsib_mclk_in", "fsib"),
-       /* HDMI */
-       PIN_MAP_MUX_GROUP_DEFAULT("sh-mobile-hdmi", "pfc-sh7372",
-                                 "hdmi", "hdmi"),
-       /* LCDC */
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_lcdc_fb.0", "pfc-sh7372",
-                                 "lcd_data24", "lcd"),
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_lcdc_fb.0", "pfc-sh7372",
-                                 "lcd_sync", "lcd"),
-       /* SCIFA0 */
-       PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.0", "pfc-sh7372",
-                                 "scifa0_data", "scifa0"),
-       /* SCIFA2 (GT-720F GPS module) */
-       PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.2", "pfc-sh7372",
-                                 "scifa2_data", "scifa2"),
-       /* SDHI0 */
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh7372",
-                                 "sdhi0_data4", "sdhi0"),
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh7372",
-                                 "sdhi0_ctrl", "sdhi0"),
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh7372",
-                                 "sdhi0_wp", "sdhi0"),
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-sh7372",
-                                 "intc_irq26_1", "intc"),
-       /* SDHI1 */
-#if !IS_ENABLED(CONFIG_MMC_SH_MMCIF)
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-sh7372",
-                                 "sdhi1_data4", "sdhi1"),
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.1", "pfc-sh7372",
-                                 "sdhi1_ctrl", "sdhi1"),
-#else
-       /* MMCIF */
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-sh7372",
-                                 "mmc0_data8_0", "mmc0"),
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.0", "pfc-sh7372",
-                                 "mmc0_ctrl_0", "mmc0"),
-#endif
-       /* SDHI2 */
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.2", "pfc-sh7372",
-                                 "sdhi2_data4", "sdhi2"),
-       PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.2", "pfc-sh7372",
-                                 "sdhi2_ctrl", "sdhi2"),
-       /* SMSC911X */
-       PIN_MAP_MUX_GROUP_DEFAULT("smsc911x", "pfc-sh7372",
-                                 "bsc_cs5a", "bsc"),
-       PIN_MAP_MUX_GROUP_DEFAULT("smsc911x", "pfc-sh7372",
-                                 "intc_irq6_0", "intc"),
-       /* ST1232 */
-       PIN_MAP_MUX_GROUP_DEFAULT("0-0055", "pfc-sh7372",
-                                 "intc_irq7_0", "intc"),
-       /* TCA6416 */
-       PIN_MAP_MUX_GROUP_DEFAULT("0-0020", "pfc-sh7372",
-                                 "intc_irq9_0", "intc"),
-       /* USBHS0 */
-       PIN_MAP_MUX_GROUP_DEFAULT("renesas_usbhs.0", "pfc-sh7372",
-                                 "usb0_vbus", "usb0"),
-       PIN_MAP_CONFIGS_GROUP_DEFAULT("renesas_usbhs.0", "pfc-sh7372",
-                                     "usb0_vbus", pin_pulldown_conf),
-       /* USBHS1 */
-       PIN_MAP_MUX_GROUP_DEFAULT("renesas_usbhs.1", "pfc-sh7372",
-                                 "usb1_vbus", "usb1"),
-       PIN_MAP_CONFIGS_GROUP_DEFAULT("renesas_usbhs.1", "pfc-sh7372",
-                                     "usb1_vbus", pin_pulldown_conf),
-       PIN_MAP_MUX_GROUP_DEFAULT("renesas_usbhs.1", "pfc-sh7372",
-                                 "usb1_otg_id_0", "usb1"),
-};
-
-#define GPIO_PORT9CR   IOMEM(0xE6051009)
-#define GPIO_PORT10CR  IOMEM(0xE605100A)
-#define SRCR4          IOMEM(0xe61580bc)
-#define USCCR1         IOMEM(0xE6058144)
-static void __init mackerel_init(void)
-{
-       static struct pm_domain_device domain_devices[] __initdata = {
-               { "A4LC", &lcdc_device, },
-               { "A4LC", &hdmi_lcdc_device, },
-               { "A4LC", &meram_device, },
-               { "A4MP", &fsi_device, },
-               { "A3SP", &usbhs0_device, },
-               { "A3SP", &usbhs1_device, },
-               { "A3SP", &nand_flash_device, },
-               { "A3SP", &sdhi0_device, },
-#if !IS_ENABLED(CONFIG_MMC_SH_MMCIF)
-               { "A3SP", &sdhi1_device, },
-#else
-               { "A3SP", &sh_mmcif_device, },
-#endif
-               { "A3SP", &sdhi2_device, },
-               { "A4R", &ceu_device, },
-       };
-       u32 srcr4;
-       struct clk *clk;
-
-       regulator_register_always_on(0, "fixed-1.8V", fixed1v8_power_consumers,
-                                    ARRAY_SIZE(fixed1v8_power_consumers), 1800000);
-       regulator_register_always_on(1, "fixed-3.3V", fixed3v3_power_consumers,
-                                    ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
-       regulator_register_fixed(2, dummy_supplies, ARRAY_SIZE(dummy_supplies));
-
-       /* External clock source */
-       clk_set_rate(&sh7372_dv_clki_clk, 27000000);
-
-       pinctrl_register_mappings(mackerel_pinctrl_map,
-                                 ARRAY_SIZE(mackerel_pinctrl_map));
-       sh7372_pinmux_init();
-
-       gpio_request_one(151, GPIOF_OUT_INIT_HIGH, NULL); /* LCDDON */
-
-       /* FSI2 port A (ak4643) */
-       gpio_request_one(161, GPIOF_OUT_INIT_LOW, NULL); /* slave */
-
-       gpio_request(9,  NULL);
-       gpio_request(10, NULL);
-       gpio_direction_none(GPIO_PORT9CR);  /* FSIAOBT needs no direction */
-       gpio_direction_none(GPIO_PORT10CR); /* FSIAOLR needs no direction */
-
-       intc_set_priority(IRQ_FSI, 3); /* irq priority FSI(3) > SMSC911X(2) */
-
-       /* FSI2 port B (HDMI) */
-       __raw_writew(__raw_readw(USCCR1) & ~(1 << 6), USCCR1); /* use SPDIF */
-
-       /* set SPU2 clock to 119.6 MHz */
-       clk = clk_get(NULL, "spu_clk");
-       if (!IS_ERR(clk)) {
-               clk_set_rate(clk, clk_round_rate(clk, 119600000));
-               clk_put(clk);
-       }
-
-       /* Keypad */
-       irq_set_irq_type(IRQ9, IRQ_TYPE_LEVEL_HIGH);
-
-       /* Touchscreen */
-       irq_set_irq_type(IRQ7, IRQ_TYPE_LEVEL_LOW);
-
-       /* Accelerometer */
-       irq_set_irq_type(IRQ21, IRQ_TYPE_LEVEL_HIGH);
-
-       /* Reset HDMI, must be held at least one EXTALR (32768Hz) period */
-       srcr4 = __raw_readl(SRCR4);
-       __raw_writel(srcr4 | (1 << 13), SRCR4);
-       udelay(50);
-       __raw_writel(srcr4 & ~(1 << 13), SRCR4);
-
-       i2c_register_board_info(0, i2c0_devices,
-                               ARRAY_SIZE(i2c0_devices));
-       i2c_register_board_info(1, i2c1_devices,
-                               ARRAY_SIZE(i2c1_devices));
-
-       sh7372_add_standard_devices();
-
-       platform_add_devices(mackerel_devices, ARRAY_SIZE(mackerel_devices));
-
-       rmobile_add_devices_to_domains(domain_devices,
-                                      ARRAY_SIZE(domain_devices));
-
-       hdmi_init_pm_clock();
-       sh7372_pm_init();
-       pm_clk_add(&fsi_device.dev, "spu2");
-       pm_clk_add(&hdmi_lcdc_device.dev, "hdmi");
-}
-
-static const char *mackerel_boards_compat_dt[] __initdata = {
-       "renesas,mackerel",
-       NULL,
-};
-
-DT_MACHINE_START(MACKEREL_DT, "mackerel")
-       .map_io         = sh7372_map_io,
-       .init_early     = sh7372_add_early_devices,
-       .init_irq       = sh7372_init_irq,
-       .handle_irq     = shmobile_handle_irq_intc,
-       .init_machine   = mackerel_init,
-       .init_late      = sh7372_pm_init_late,
-       .init_time      = sh7372_earlytimer_init,
-       .dt_compat  = mackerel_boards_compat_dt,
-MACHINE_END
index 598f704f76ae7420c96f420c9d3c9b63bbf09edc..51db288f192abf0c572011e8c7465defc704a8f5 100644 (file)
@@ -122,11 +122,11 @@ static struct resource sdhi0_resources[] = {
        },
 };
 
-static struct sh_mobile_sdhi_info sdhi0_platform_data = {
-       .dma_slave_tx = HPBDMA_SLAVE_SDHI0_TX,
-       .dma_slave_rx = HPBDMA_SLAVE_SDHI0_RX,
-       .tmio_flags = TMIO_MMC_WRPROTECT_DISABLE | TMIO_MMC_HAS_IDLE_WAIT,
-       .tmio_caps = MMC_CAP_SD_HIGHSPEED,
+static struct tmio_mmc_data sdhi0_platform_data = {
+       .chan_priv_tx = (void *)HPBDMA_SLAVE_SDHI0_TX,
+       .chan_priv_rx = (void *)HPBDMA_SLAVE_SDHI0_RX,
+       .flags        = TMIO_MMC_WRPROTECT_DISABLE | TMIO_MMC_HAS_IDLE_WAIT,
+       .capabilities = MMC_CAP_SD_HIGHSPEED,
 };
 
 static struct platform_device sdhi0_device = {
diff --git a/arch/arm/mach-shmobile/clock-r8a73a4.c b/arch/arm/mach-shmobile/clock-r8a73a4.c
deleted file mode 100644 (file)
index 1cf44dc..0000000
+++ /dev/null
@@ -1,659 +0,0 @@
-/*
- * r8a73a4 clock framework 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 <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/sh_clk.h>
-#include <linux/clkdev.h>
-#include "common.h"
-#include "clock.h"
-
-#define CPG_BASE 0xe6150000
-#define CPG_LEN 0x270
-
-#define SMSTPCR2 0xe6150138
-#define SMSTPCR3 0xe615013c
-#define SMSTPCR4 0xe6150140
-#define SMSTPCR5 0xe6150144
-
-#define FRQCRA         0xE6150000
-#define FRQCRB         0xE6150004
-#define FRQCRC         0xE61500E0
-#define VCLKCR1                0xE6150008
-#define VCLKCR2                0xE615000C
-#define VCLKCR3                0xE615001C
-#define VCLKCR4                0xE6150014
-#define VCLKCR5                0xE6150034
-#define ZBCKCR         0xE6150010
-#define SD0CKCR                0xE6150074
-#define SD1CKCR                0xE6150078
-#define SD2CKCR                0xE615007C
-#define MMC0CKCR       0xE6150240
-#define MMC1CKCR       0xE6150244
-#define FSIACKCR       0xE6150018
-#define FSIBCKCR       0xE6150090
-#define MPCKCR         0xe6150080
-#define SPUVCKCR       0xE6150094
-#define HSICKCR                0xE615026C
-#define M4CKCR         0xE6150098
-#define PLLECR         0xE61500D0
-#define PLL0CR         0xE61500D8
-#define PLL1CR         0xE6150028
-#define PLL2CR         0xE615002C
-#define PLL2SCR                0xE61501F4
-#define PLL2HCR                0xE61501E4
-#define CKSCR          0xE61500C0
-
-#define CPG_MAP(o) ((o - CPG_BASE) + cpg_mapping.base)
-
-static struct clk_mapping cpg_mapping = {
-       .phys   = CPG_BASE,
-       .len    = CPG_LEN,
-};
-
-static struct clk extalr_clk = {
-       .rate   = 32768,
-       .mapping        = &cpg_mapping,
-};
-
-static struct clk extal1_clk = {
-       .rate   = 26000000,
-       .mapping        = &cpg_mapping,
-};
-
-static struct clk extal2_clk = {
-       .rate   = 48000000,
-       .mapping        = &cpg_mapping,
-};
-
-static struct sh_clk_ops followparent_clk_ops = {
-       .recalc = followparent_recalc,
-};
-
-static struct clk main_clk = {
-       /* .parent will be set r8a73a4_clock_init */
-       .ops    = &followparent_clk_ops,
-};
-
-SH_CLK_RATIO(div2,     1, 2);
-SH_CLK_RATIO(div4,     1, 4);
-
-SH_FIXED_RATIO_CLK(main_div2_clk,      main_clk,               div2);
-SH_FIXED_RATIO_CLK(extal1_div2_clk,    extal1_clk,             div2);
-SH_FIXED_RATIO_CLK(extal2_div2_clk,    extal2_clk,             div2);
-SH_FIXED_RATIO_CLK(extal2_div4_clk,    extal2_clk,             div4);
-
-/* External FSIACK/FSIBCK clock */
-static struct clk fsiack_clk = {
-};
-
-static struct clk fsibck_clk = {
-};
-
-/*
- *             PLL clocks
- */
-static struct clk *pll_parent_main[] = {
-       [0] = &main_clk,
-       [1] = &main_div2_clk
-};
-
-static struct clk *pll_parent_main_extal[8] = {
-       [0] = &main_div2_clk,
-       [1] = &extal2_div2_clk,
-       [3] = &extal2_div4_clk,
-       [4] = &main_clk,
-       [5] = &extal2_clk,
-};
-
-static unsigned long pll_recalc(struct clk *clk)
-{
-       unsigned long mult = 1;
-
-       if (ioread32(CPG_MAP(PLLECR)) & (1 << clk->enable_bit))
-               mult = (((ioread32(clk->mapped_reg) >> 24) & 0x7f) + 1);
-
-       return clk->parent->rate * mult;
-}
-
-static int pll_set_parent(struct clk *clk, struct clk *parent)
-{
-       u32 val;
-       int i, ret;
-
-       if (!clk->parent_table || !clk->parent_num)
-               return -EINVAL;
-
-       /* Search the parent */
-       for (i = 0; i < clk->parent_num; i++)
-               if (clk->parent_table[i] == parent)
-                       break;
-
-       if (i == clk->parent_num)
-               return -ENODEV;
-
-       ret = clk_reparent(clk, parent);
-       if (ret < 0)
-               return ret;
-
-       val = ioread32(clk->mapped_reg) &
-               ~(((1 << clk->src_width) - 1) << clk->src_shift);
-
-       iowrite32(val | i << clk->src_shift, clk->mapped_reg);
-
-       return 0;
-}
-
-static struct sh_clk_ops pll_clk_ops = {
-       .recalc         = pll_recalc,
-       .set_parent     = pll_set_parent,
-};
-
-#define PLL_CLOCK(name, p, pt, w, s, reg, e)           \
-       static struct clk name = {                      \
-               .ops            = &pll_clk_ops,         \
-               .flags          = CLK_ENABLE_ON_INIT,   \
-               .parent         = p,                    \
-               .parent_table   = pt,                   \
-               .parent_num     = ARRAY_SIZE(pt),       \
-               .src_width      = w,                    \
-               .src_shift      = s,                    \
-               .enable_reg     = (void __iomem *)reg,  \
-               .enable_bit     = e,                    \
-               .mapping        = &cpg_mapping,         \
-       }
-
-PLL_CLOCK(pll0_clk,  &main_clk,      pll_parent_main,      1, 20, PLL0CR,  0);
-PLL_CLOCK(pll1_clk,  &main_clk,      pll_parent_main,       1, 7, PLL1CR,  1);
-PLL_CLOCK(pll2_clk,  &main_div2_clk, pll_parent_main_extal, 3, 5, PLL2CR,  2);
-PLL_CLOCK(pll2s_clk, &main_div2_clk, pll_parent_main_extal, 3, 5, PLL2SCR, 4);
-PLL_CLOCK(pll2h_clk, &main_div2_clk, pll_parent_main_extal, 3, 5, PLL2HCR, 5);
-
-SH_FIXED_RATIO_CLK(pll1_div2_clk,      pll1_clk,       div2);
-
-static atomic_t frqcr_lock;
-
-/* Several clocks need to access FRQCRB, have to lock */
-static bool frqcr_kick_check(struct clk *clk)
-{
-       return !(ioread32(CPG_MAP(FRQCRB)) & BIT(31));
-}
-
-static int frqcr_kick_do(struct clk *clk)
-{
-       int i;
-
-       /* set KICK bit in FRQCRB to update hardware setting, check success */
-       iowrite32(ioread32(CPG_MAP(FRQCRB)) | BIT(31), CPG_MAP(FRQCRB));
-       for (i = 1000; i; i--)
-               if (ioread32(CPG_MAP(FRQCRB)) & BIT(31))
-                       cpu_relax();
-               else
-                       return 0;
-
-       return -ETIMEDOUT;
-}
-
-static int zclk_set_rate(struct clk *clk, unsigned long rate)
-{
-       void __iomem *frqcrc;
-       int ret;
-       unsigned long step, p_rate;
-       u32 val;
-
-       if (!clk->parent || !__clk_get(clk->parent))
-               return -ENODEV;
-
-       if (!atomic_inc_and_test(&frqcr_lock) || !frqcr_kick_check(clk)) {
-               ret = -EBUSY;
-               goto done;
-       }
-
-       /*
-        * Users are supposed to first call clk_set_rate() only with
-        * clk_round_rate() results. So, we don't fix wrong rates here, but
-        * guard against them anyway
-        */
-
-       p_rate = clk_get_rate(clk->parent);
-       if (rate == p_rate) {
-               val = 0;
-       } else {
-               step = DIV_ROUND_CLOSEST(p_rate, 32);
-
-               if (rate > p_rate || rate < step) {
-                       ret = -EINVAL;
-                       goto done;
-               }
-
-               val = 32 - rate / step;
-       }
-
-       frqcrc = clk->mapped_reg + (FRQCRC - (u32)clk->enable_reg);
-
-       iowrite32((ioread32(frqcrc) & ~(clk->div_mask << clk->enable_bit)) |
-                 (val << clk->enable_bit), frqcrc);
-
-       ret = frqcr_kick_do(clk);
-
-done:
-       atomic_dec(&frqcr_lock);
-       __clk_put(clk->parent);
-       return ret;
-}
-
-static long zclk_round_rate(struct clk *clk, unsigned long rate)
-{
-       /*
-        * theoretical rate = parent rate * multiplier / 32,
-        * where 1 <= multiplier <= 32. Therefore we should do
-        * multiplier = rate * 32 / parent rate
-        * rounded rate = parent rate * multiplier / 32.
-        * However, multiplication before division won't fit in 32 bits, so
-        * we sacrifice some precision by first dividing and then multiplying.
-        * To find the nearest divisor we calculate both and pick up the best
-        * one. This avoids 64-bit arithmetics.
-        */
-       unsigned long step, mul_min, mul_max, rate_min, rate_max;
-
-       rate_max = clk_get_rate(clk->parent);
-
-       /* output freq <= parent */
-       if (rate >= rate_max)
-               return rate_max;
-
-       step = DIV_ROUND_CLOSEST(rate_max, 32);
-       /* output freq >= parent / 32 */
-       if (step >= rate)
-               return step;
-
-       mul_min = rate / step;
-       mul_max = DIV_ROUND_UP(rate, step);
-       rate_min = step * mul_min;
-       if (mul_max == mul_min)
-               return rate_min;
-
-       rate_max = step * mul_max;
-
-       if (rate_max - rate <  rate - rate_min)
-               return rate_max;
-
-       return rate_min;
-}
-
-static unsigned long zclk_recalc(struct clk *clk)
-{
-       void __iomem *frqcrc = FRQCRC - (u32)clk->enable_reg + clk->mapped_reg;
-       unsigned int max = clk->div_mask + 1;
-       unsigned long val = ((ioread32(frqcrc) >> clk->enable_bit) &
-                            clk->div_mask);
-
-       return DIV_ROUND_CLOSEST(clk_get_rate(clk->parent), max) *
-               (max - val);
-}
-
-static struct sh_clk_ops zclk_ops = {
-       .recalc = zclk_recalc,
-       .set_rate = zclk_set_rate,
-       .round_rate = zclk_round_rate,
-};
-
-static struct clk z_clk = {
-       .parent = &pll0_clk,
-       .div_mask = 0x1f,
-       .enable_bit = 8,
-       /* We'll need to access FRQCRB and FRQCRC */
-       .enable_reg = (void __iomem *)FRQCRB,
-       .ops = &zclk_ops,
-};
-
-/*
- * It seems only 1/2 divider is usable in manual mode. 1/2 / 2/3
- * switching is only available in auto-DVFS mode
- */
-SH_FIXED_RATIO_CLK(pll0_div2_clk,      pll0_clk,               div2);
-
-static struct clk z2_clk = {
-       .parent = &pll0_div2_clk,
-       .div_mask = 0x1f,
-       .enable_bit = 0,
-       /* We'll need to access FRQCRB and FRQCRC */
-       .enable_reg = (void __iomem *)FRQCRB,
-       .ops = &zclk_ops,
-};
-
-static struct clk *main_clks[] = {
-       &extalr_clk,
-       &extal1_clk,
-       &extal1_div2_clk,
-       &extal2_clk,
-       &extal2_div2_clk,
-       &extal2_div4_clk,
-       &main_clk,
-       &main_div2_clk,
-       &fsiack_clk,
-       &fsibck_clk,
-       &pll0_clk,
-       &pll1_clk,
-       &pll1_div2_clk,
-       &pll2_clk,
-       &pll2s_clk,
-       &pll2h_clk,
-       &z_clk,
-       &pll0_div2_clk,
-       &z2_clk,
-};
-
-/* DIV4 */
-static void div4_kick(struct clk *clk)
-{
-       if (!WARN(!atomic_inc_and_test(&frqcr_lock), "FRQCR* lock broken!\n"))
-               frqcr_kick_do(clk);
-       atomic_dec(&frqcr_lock);
-}
-
-static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18, 24, 0, 36, 48, 10};
-
-static struct clk_div_mult_table div4_div_mult_table = {
-       .divisors       = divisors,
-       .nr_divisors    = ARRAY_SIZE(divisors),
-};
-
-static struct clk_div4_table div4_table = {
-       .div_mult_table = &div4_div_mult_table,
-       .kick           = div4_kick,
-};
-
-enum {
-       DIV4_I, DIV4_M3, DIV4_B, DIV4_M1, DIV4_M2,
-       DIV4_ZX, DIV4_ZS, DIV4_HP,
-       DIV4_NR };
-
-static struct clk div4_clks[DIV4_NR] = {
-       [DIV4_I]        = SH_CLK_DIV4(&pll1_clk, FRQCRA, 20, 0x0dff, CLK_ENABLE_ON_INIT),
-       [DIV4_M3]       = SH_CLK_DIV4(&pll1_clk, FRQCRA, 12, 0x1dff, CLK_ENABLE_ON_INIT),
-       [DIV4_B]        = SH_CLK_DIV4(&pll1_clk, FRQCRA,  8, 0x0dff, CLK_ENABLE_ON_INIT),
-       [DIV4_M1]       = SH_CLK_DIV4(&pll1_clk, FRQCRA,  4, 0x1dff, 0),
-       [DIV4_M2]       = SH_CLK_DIV4(&pll1_clk, FRQCRA,  0, 0x1dff, 0),
-       [DIV4_ZX]       = SH_CLK_DIV4(&pll1_clk, FRQCRB, 12, 0x0dff, 0),
-       [DIV4_ZS]       = SH_CLK_DIV4(&pll1_clk, FRQCRB,  8, 0x0dff, 0),
-       [DIV4_HP]       = SH_CLK_DIV4(&pll1_clk, FRQCRB,  4, 0x0dff, 0),
-};
-
-enum {
-       DIV6_ZB,
-       DIV6_SDHI0, DIV6_SDHI1, DIV6_SDHI2,
-       DIV6_MMC0, DIV6_MMC1,
-       DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_VCK4, DIV6_VCK5,
-       DIV6_FSIA, DIV6_FSIB,
-       DIV6_MP, DIV6_M4, DIV6_HSI, DIV6_SPUV,
-       DIV6_NR };
-
-static struct clk *div6_parents[8] = {
-       [0] = &pll1_div2_clk,
-       [1] = &pll2s_clk,
-       [3] = &extal2_clk,
-       [4] = &main_div2_clk,
-       [6] = &extalr_clk,
-};
-
-static struct clk *fsia_parents[4] = {
-       [0] = &pll1_div2_clk,
-       [1] = &pll2s_clk,
-       [2] = &fsiack_clk,
-};
-
-static struct clk *fsib_parents[4] = {
-       [0] = &pll1_div2_clk,
-       [1] = &pll2s_clk,
-       [2] = &fsibck_clk,
-};
-
-static struct clk *mp_parents[4] = {
-       [0] = &pll1_div2_clk,
-       [1] = &pll2s_clk,
-       [2] = &extal2_clk,
-       [3] = &extal2_clk,
-};
-
-static struct clk *m4_parents[2] = {
-       [0] = &pll2s_clk,
-};
-
-static struct clk *hsi_parents[4] = {
-       [0] = &pll2h_clk,
-       [1] = &pll1_div2_clk,
-       [3] = &pll2s_clk,
-};
-
-/*** FIXME ***
- * SH_CLK_DIV6_EXT() macro doesn't care .mapping
- * but, it is necessary on R-Car (= ioremap() base CPG)
- * The difference between
- * SH_CLK_DIV6_EXT() <--> SH_CLK_MAP_DIV6_EXT()
- * is only .mapping
- */
-#define SH_CLK_MAP_DIV6_EXT(_reg, _flags, _parents,                    \
-                           _num_parents, _src_shift, _src_width)       \
-{                                                                      \
-       .enable_reg     = (void __iomem *)_reg,                         \
-       .enable_bit     = 0, /* unused */                               \
-       .flags          = _flags | CLK_MASK_DIV_ON_DISABLE,             \
-       .div_mask       = SH_CLK_DIV6_MSK,                              \
-       .parent_table   = _parents,                                     \
-       .parent_num     = _num_parents,                                 \
-       .src_shift      = _src_shift,                                   \
-       .src_width      = _src_width,                                   \
-       .mapping        = &cpg_mapping,                                 \
-}
-
-static struct clk div6_clks[DIV6_NR] = {
-       [DIV6_ZB] = SH_CLK_MAP_DIV6_EXT(ZBCKCR, CLK_ENABLE_ON_INIT,
-                               div6_parents, 2, 7, 1),
-       [DIV6_SDHI0] = SH_CLK_MAP_DIV6_EXT(SD0CKCR, 0,
-                               div6_parents, 2, 6, 2),
-       [DIV6_SDHI1] = SH_CLK_MAP_DIV6_EXT(SD1CKCR, 0,
-                               div6_parents, 2, 6, 2),
-       [DIV6_SDHI2] = SH_CLK_MAP_DIV6_EXT(SD2CKCR, 0,
-                               div6_parents, 2, 6, 2),
-       [DIV6_MMC0] = SH_CLK_MAP_DIV6_EXT(MMC0CKCR, 0,
-                               div6_parents, 2, 6, 2),
-       [DIV6_MMC1] = SH_CLK_MAP_DIV6_EXT(MMC1CKCR, 0,
-                               div6_parents, 2, 6, 2),
-       [DIV6_VCK1] = SH_CLK_MAP_DIV6_EXT(VCLKCR1, 0, /* didn't care bit[6-7] */
-                               div6_parents, ARRAY_SIZE(div6_parents), 12, 3),
-       [DIV6_VCK2] = SH_CLK_MAP_DIV6_EXT(VCLKCR2, 0, /* didn't care bit[6-7] */
-                               div6_parents, ARRAY_SIZE(div6_parents), 12, 3),
-       [DIV6_VCK3] = SH_CLK_MAP_DIV6_EXT(VCLKCR3, 0, /* didn't care bit[6-7] */
-                               div6_parents, ARRAY_SIZE(div6_parents), 12, 3),
-       [DIV6_VCK4] = SH_CLK_MAP_DIV6_EXT(VCLKCR4, 0, /* didn't care bit[6-7] */
-                               div6_parents, ARRAY_SIZE(div6_parents), 12, 3),
-       [DIV6_VCK5] = SH_CLK_MAP_DIV6_EXT(VCLKCR5, 0, /* didn't care bit[6-7] */
-                               div6_parents, ARRAY_SIZE(div6_parents), 12, 3),
-       [DIV6_FSIA] = SH_CLK_MAP_DIV6_EXT(FSIACKCR, 0,
-                               fsia_parents, ARRAY_SIZE(fsia_parents), 6, 2),
-       [DIV6_FSIB] = SH_CLK_MAP_DIV6_EXT(FSIBCKCR, 0,
-                               fsib_parents, ARRAY_SIZE(fsib_parents), 6, 2),
-       [DIV6_MP] = SH_CLK_MAP_DIV6_EXT(MPCKCR, 0, /* it needs bit[9-11] control */
-                               mp_parents, ARRAY_SIZE(mp_parents), 6, 2),
-       /* pll2s will be selected always for M4 */
-       [DIV6_M4] = SH_CLK_MAP_DIV6_EXT(M4CKCR, 0, /* it needs bit[9] control */
-                               m4_parents, ARRAY_SIZE(m4_parents), 6, 1),
-       [DIV6_HSI] = SH_CLK_MAP_DIV6_EXT(HSICKCR, 0, /* it needs bit[9] control */
-                               hsi_parents, ARRAY_SIZE(hsi_parents), 6, 2),
-       [DIV6_SPUV] = SH_CLK_MAP_DIV6_EXT(SPUVCKCR, 0,
-                               mp_parents, ARRAY_SIZE(mp_parents), 6, 2),
-};
-
-/* MSTP */
-enum {
-       MSTP218, MSTP217, MSTP216, MSTP207, MSTP206, MSTP204, MSTP203,
-       MSTP329, MSTP323, MSTP318, MSTP317, MSTP316,
-       MSTP315, MSTP314, MSTP313, MSTP312, MSTP305, MSTP300,
-       MSTP411, MSTP410, MSTP409,
-       MSTP522, MSTP515,
-       MSTP_NR
-};
-
-static struct clk mstp_clks[MSTP_NR] = {
-       [MSTP204] = SH_CLK_MSTP32(&div6_clks[DIV6_MP],  SMSTPCR2, 4, 0), /* SCIFA0 */
-       [MSTP203] = SH_CLK_MSTP32(&div6_clks[DIV6_MP],  SMSTPCR2, 3, 0), /* SCIFA1 */
-       [MSTP206] = SH_CLK_MSTP32(&div6_clks[DIV6_MP],  SMSTPCR2, 6, 0), /* SCIFB0 */
-       [MSTP207] = SH_CLK_MSTP32(&div6_clks[DIV6_MP],  SMSTPCR2, 7, 0), /* SCIFB1 */
-       [MSTP216] = SH_CLK_MSTP32(&div6_clks[DIV6_MP],  SMSTPCR2, 16, 0), /* SCIFB2 */
-       [MSTP217] = SH_CLK_MSTP32(&div6_clks[DIV6_MP],  SMSTPCR2, 17, 0), /* SCIFB3 */
-       [MSTP218] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR2, 18, 0), /* DMAC */
-       [MSTP300] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR3, 0, 0), /* IIC2 */
-       [MSTP305] = SH_CLK_MSTP32(&div6_clks[DIV6_MMC1],SMSTPCR3, 5, 0), /* MMCIF1 */
-       [MSTP312] = SH_CLK_MSTP32(&div6_clks[DIV6_SDHI2],SMSTPCR3, 12, 0), /* SDHI2 */
-       [MSTP313] = SH_CLK_MSTP32(&div6_clks[DIV6_SDHI1],SMSTPCR3, 13, 0), /* SDHI1 */
-       [MSTP314] = SH_CLK_MSTP32(&div6_clks[DIV6_SDHI0],SMSTPCR3, 14, 0), /* SDHI0 */
-       [MSTP315] = SH_CLK_MSTP32(&div6_clks[DIV6_MMC0],SMSTPCR3, 15, 0), /* MMCIF0 */
-       [MSTP316] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR3, 16, 0), /* IIC6 */
-       [MSTP317] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR3, 17, 0), /* IIC7 */
-       [MSTP318] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR3, 18, 0), /* IIC0 */
-       [MSTP323] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR3, 23, 0), /* IIC1 */
-       [MSTP329] = SH_CLK_MSTP32(&extalr_clk, SMSTPCR3, 29, 0), /* CMT10 */
-       [MSTP409] = SH_CLK_MSTP32(&main_div2_clk,       SMSTPCR4, 9, 0), /* IIC5 */
-       [MSTP410] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR4, 10, 0), /* IIC4 */
-       [MSTP411] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR4, 11, 0), /* IIC3 */
-       [MSTP522] = SH_CLK_MSTP32(&extal2_clk, SMSTPCR5, 22, 0), /* Thermal */
-       [MSTP515] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR5, 15, 0), /* IIC8 */
-};
-
-static struct clk_lookup lookups[] = {
-       /* main clock */
-       CLKDEV_CON_ID("extal1",                 &extal1_clk),
-       CLKDEV_CON_ID("extal1_div2",            &extal1_div2_clk),
-       CLKDEV_CON_ID("extal2",                 &extal2_clk),
-       CLKDEV_CON_ID("extal2_div2",            &extal2_div2_clk),
-       CLKDEV_CON_ID("extal2_div4",            &extal2_div4_clk),
-       CLKDEV_CON_ID("fsiack",                 &fsiack_clk),
-       CLKDEV_CON_ID("fsibck",                 &fsibck_clk),
-
-       /* pll clock */
-       CLKDEV_CON_ID("pll1",                   &pll1_clk),
-       CLKDEV_CON_ID("pll1_div2",              &pll1_div2_clk),
-       CLKDEV_CON_ID("pll2",                   &pll2_clk),
-       CLKDEV_CON_ID("pll2s",                  &pll2s_clk),
-       CLKDEV_CON_ID("pll2h",                  &pll2h_clk),
-
-       /* CPU clock */
-       CLKDEV_DEV_ID("cpu0",                   &z_clk),
-
-       /* DIV6 */
-       CLKDEV_CON_ID("zb",                     &div6_clks[DIV6_ZB]),
-       CLKDEV_CON_ID("vck1",                   &div6_clks[DIV6_VCK1]),
-       CLKDEV_CON_ID("vck2",                   &div6_clks[DIV6_VCK2]),
-       CLKDEV_CON_ID("vck3",                   &div6_clks[DIV6_VCK3]),
-       CLKDEV_CON_ID("vck4",                   &div6_clks[DIV6_VCK4]),
-       CLKDEV_CON_ID("vck5",                   &div6_clks[DIV6_VCK5]),
-       CLKDEV_CON_ID("fsia",                   &div6_clks[DIV6_FSIA]),
-       CLKDEV_CON_ID("fsib",                   &div6_clks[DIV6_FSIB]),
-       CLKDEV_CON_ID("mp",                     &div6_clks[DIV6_MP]),
-       CLKDEV_CON_ID("m4",                     &div6_clks[DIV6_M4]),
-       CLKDEV_CON_ID("hsi",                    &div6_clks[DIV6_HSI]),
-       CLKDEV_CON_ID("spuv",                   &div6_clks[DIV6_SPUV]),
-
-       /* MSTP */
-       CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]),
-       CLKDEV_DEV_ID("e6c40000.serial", &mstp_clks[MSTP204]),
-       CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]),
-       CLKDEV_DEV_ID("e6c50000.serial", &mstp_clks[MSTP203]),
-       CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP206]),
-       CLKDEV_DEV_ID("e6c20000.serial", &mstp_clks[MSTP206]),
-       CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP207]),
-       CLKDEV_DEV_ID("e6c30000.serial", &mstp_clks[MSTP207]),
-       CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP216]),
-       CLKDEV_DEV_ID("e6ce0000.serial", &mstp_clks[MSTP216]),
-       CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP217]),
-       CLKDEV_DEV_ID("e6cf0000.serial", &mstp_clks[MSTP217]),
-       CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]),
-       CLKDEV_DEV_ID("e6700020.dma-controller", &mstp_clks[MSTP218]),
-       CLKDEV_DEV_ID("rcar_thermal", &mstp_clks[MSTP522]),
-       CLKDEV_DEV_ID("e6520000.i2c", &mstp_clks[MSTP300]),
-       CLKDEV_DEV_ID("sh_mmcif.1", &mstp_clks[MSTP305]),
-       CLKDEV_DEV_ID("ee220000.mmc", &mstp_clks[MSTP305]),
-       CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP312]),
-       CLKDEV_DEV_ID("ee140000.sd", &mstp_clks[MSTP312]),
-       CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]),
-       CLKDEV_DEV_ID("ee120000.sd", &mstp_clks[MSTP313]),
-       CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]),
-       CLKDEV_DEV_ID("ee100000.sd", &mstp_clks[MSTP314]),
-       CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP315]),
-       CLKDEV_DEV_ID("ee200000.mmc", &mstp_clks[MSTP315]),
-       CLKDEV_DEV_ID("e6550000.i2c", &mstp_clks[MSTP316]),
-       CLKDEV_DEV_ID("e6560000.i2c", &mstp_clks[MSTP317]),
-       CLKDEV_DEV_ID("e6500000.i2c", &mstp_clks[MSTP318]),
-       CLKDEV_DEV_ID("e6510000.i2c", &mstp_clks[MSTP323]),
-       CLKDEV_ICK_ID("fck", "sh-cmt-48-gen2.1", &mstp_clks[MSTP329]),
-       CLKDEV_ICK_ID("fck", "e6130000.timer", &mstp_clks[MSTP329]),
-       CLKDEV_DEV_ID("e60b0000.i2c", &mstp_clks[MSTP409]),
-       CLKDEV_DEV_ID("e6540000.i2c", &mstp_clks[MSTP410]),
-       CLKDEV_DEV_ID("e6530000.i2c", &mstp_clks[MSTP411]),
-       CLKDEV_DEV_ID("e6570000.i2c", &mstp_clks[MSTP515]),
-
-       /* for DT */
-       CLKDEV_DEV_ID("e61f0000.thermal", &mstp_clks[MSTP522]),
-};
-
-void __init r8a73a4_clock_init(void)
-{
-       void __iomem *reg;
-       int k, ret = 0;
-       u32 ckscr;
-
-       atomic_set(&frqcr_lock, -1);
-
-       reg = ioremap_nocache(CKSCR, PAGE_SIZE);
-       BUG_ON(!reg);
-       ckscr = ioread32(reg);
-       iounmap(reg);
-
-       switch ((ckscr >> 28) & 0x3) {
-       case 0:
-               main_clk.parent = &extal1_clk;
-               break;
-       case 1:
-               main_clk.parent = &extal1_div2_clk;
-               break;
-       case 2:
-               main_clk.parent = &extal2_clk;
-               break;
-       case 3:
-               main_clk.parent = &extal2_div2_clk;
-               break;
-       }
-
-       for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
-               ret = clk_register(main_clks[k]);
-
-       if (!ret)
-               ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
-
-       if (!ret)
-               ret = sh_clk_div6_reparent_register(div6_clks, DIV6_NR);
-
-       if (!ret)
-               ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
-
-       clkdev_add_table(lookups, ARRAY_SIZE(lookups));
-
-       if (!ret)
-               shmobile_clk_init();
-       else
-               panic("failed to setup r8a73a4 clocks\n");
-}
diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c
deleted file mode 100644 (file)
index 3bc92f4..0000000
+++ /dev/null
@@ -1,620 +0,0 @@
-/*
- * SH7372 clock framework support
- *
- * Copyright (C) 2010 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; 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/init.h>
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/sh_clk.h>
-#include <linux/clkdev.h>
-#include "clock.h"
-#include "common.h"
-
-/* SH7372 registers */
-#define FRQCRA         IOMEM(0xe6150000)
-#define FRQCRB         IOMEM(0xe6150004)
-#define FRQCRC         IOMEM(0xe61500e0)
-#define FRQCRD         IOMEM(0xe61500e4)
-#define VCLKCR1                IOMEM(0xe6150008)
-#define VCLKCR2                IOMEM(0xe615000c)
-#define VCLKCR3                IOMEM(0xe615001c)
-#define FMSICKCR       IOMEM(0xe6150010)
-#define FMSOCKCR       IOMEM(0xe6150014)
-#define FSIACKCR       IOMEM(0xe6150018)
-#define FSIBCKCR       IOMEM(0xe6150090)
-#define SUBCKCR                IOMEM(0xe6150080)
-#define SPUCKCR                IOMEM(0xe6150084)
-#define VOUCKCR                IOMEM(0xe6150088)
-#define HDMICKCR       IOMEM(0xe6150094)
-#define DSITCKCR       IOMEM(0xe6150060)
-#define DSI0PCKCR      IOMEM(0xe6150064)
-#define DSI1PCKCR      IOMEM(0xe6150098)
-#define PLLC01CR       IOMEM(0xe6150028)
-#define PLLC2CR                IOMEM(0xe615002c)
-#define RMSTPCR0       IOMEM(0xe6150110)
-#define RMSTPCR1       IOMEM(0xe6150114)
-#define RMSTPCR2       IOMEM(0xe6150118)
-#define RMSTPCR3       IOMEM(0xe615011c)
-#define RMSTPCR4       IOMEM(0xe6150120)
-#define SMSTPCR0       IOMEM(0xe6150130)
-#define SMSTPCR1       IOMEM(0xe6150134)
-#define SMSTPCR2       IOMEM(0xe6150138)
-#define SMSTPCR3       IOMEM(0xe615013c)
-#define SMSTPCR4       IOMEM(0xe6150140)
-
-#define FSIDIVA                0xFE1F8000
-#define FSIDIVB                0xFE1F8008
-
-/* Platforms must set frequency on their DV_CLKI pin */
-struct clk sh7372_dv_clki_clk = {
-};
-
-/* Fixed 32 KHz root clock from EXTALR pin */
-static struct clk r_clk = {
-       .rate           = 32768,
-};
-
-/*
- * 26MHz default rate for the EXTAL1 root input clock.
- * If needed, reset this with clk_set_rate() from the platform code.
- */
-struct clk sh7372_extal1_clk = {
-       .rate           = 26000000,
-};
-
-/*
- * 48MHz default rate for the EXTAL2 root input clock.
- * If needed, reset this with clk_set_rate() from the platform code.
- */
-struct clk sh7372_extal2_clk = {
-       .rate           = 48000000,
-};
-
-SH_CLK_RATIO(div2, 1, 2);
-
-SH_FIXED_RATIO_CLKg(sh7372_dv_clki_div2_clk,   sh7372_dv_clki_clk,     div2);
-SH_FIXED_RATIO_CLK(extal1_div2_clk,            sh7372_extal1_clk,      div2);
-SH_FIXED_RATIO_CLK(extal2_div2_clk,            sh7372_extal2_clk,      div2);
-SH_FIXED_RATIO_CLK(extal2_div4_clk,            extal2_div2_clk,        div2);
-
-/* PLLC0 and PLLC1 */
-static unsigned long pllc01_recalc(struct clk *clk)
-{
-       unsigned long mult = 1;
-
-       if (__raw_readl(PLLC01CR) & (1 << 14))
-               mult = (((__raw_readl(clk->enable_reg) >> 24) & 0x3f) + 1) * 2;
-
-       return clk->parent->rate * mult;
-}
-
-static struct sh_clk_ops pllc01_clk_ops = {
-       .recalc         = pllc01_recalc,
-};
-
-static struct clk pllc0_clk = {
-       .ops            = &pllc01_clk_ops,
-       .flags          = CLK_ENABLE_ON_INIT,
-       .parent         = &extal1_div2_clk,
-       .enable_reg     = (void __iomem *)FRQCRC,
-};
-
-static struct clk pllc1_clk = {
-       .ops            = &pllc01_clk_ops,
-       .flags          = CLK_ENABLE_ON_INIT,
-       .parent         = &extal1_div2_clk,
-       .enable_reg     = (void __iomem *)FRQCRA,
-};
-
-/* Divide PLLC1 by two */
-SH_FIXED_RATIO_CLK(pllc1_div2_clk,     pllc1_clk,      div2);
-
-/* PLLC2 */
-
-/* Indices are important - they are the actual src selecting values */
-static struct clk *pllc2_parent[] = {
-       [0] = &extal1_div2_clk,
-       [1] = &extal2_div2_clk,
-       [2] = &sh7372_dv_clki_div2_clk,
-};
-
-/* Only multipliers 20 * 2 to 46 * 2 are valid, last entry for CPUFREQ_TABLE_END */
-static struct cpufreq_frequency_table pllc2_freq_table[29];
-
-static void pllc2_table_rebuild(struct clk *clk)
-{
-       int i;
-
-       /* Initialise PLLC2 frequency table */
-       for (i = 0; i < ARRAY_SIZE(pllc2_freq_table) - 2; i++) {
-               pllc2_freq_table[i].frequency = clk->parent->rate * (i + 20) * 2;
-               pllc2_freq_table[i].driver_data = i;
-       }
-
-       /* This is a special entry - switching PLL off makes it a repeater */
-       pllc2_freq_table[i].frequency = clk->parent->rate;
-       pllc2_freq_table[i].driver_data = i;
-
-       pllc2_freq_table[++i].frequency = CPUFREQ_TABLE_END;
-       pllc2_freq_table[i].driver_data = i;
-}
-
-static unsigned long pllc2_recalc(struct clk *clk)
-{
-       unsigned long mult = 1;
-
-       pllc2_table_rebuild(clk);
-
-       /*
-        * If the PLL is off, mult == 1, clk->rate will be updated in
-        * pllc2_enable().
-        */
-       if (__raw_readl(PLLC2CR) & (1 << 31))
-               mult = (((__raw_readl(PLLC2CR) >> 24) & 0x3f) + 1) * 2;
-
-       return clk->parent->rate * mult;
-}
-
-static long pllc2_round_rate(struct clk *clk, unsigned long rate)
-{
-       return clk_rate_table_round(clk, clk->freq_table, rate);
-}
-
-static int pllc2_enable(struct clk *clk)
-{
-       int i;
-
-       __raw_writel(__raw_readl(PLLC2CR) | 0x80000000, PLLC2CR);
-
-       for (i = 0; i < 100; i++)
-               if (__raw_readl(PLLC2CR) & 0x80000000) {
-                       clk->rate = pllc2_recalc(clk);
-                       return 0;
-               }
-
-       pr_err("%s(): timeout!\n", __func__);
-
-       return -ETIMEDOUT;
-}
-
-static void pllc2_disable(struct clk *clk)
-{
-       __raw_writel(__raw_readl(PLLC2CR) & ~0x80000000, PLLC2CR);
-}
-
-static int pllc2_set_rate(struct clk *clk, unsigned long rate)
-{
-       unsigned long value;
-       int idx;
-
-       idx = clk_rate_table_find(clk, clk->freq_table, rate);
-       if (idx < 0)
-               return idx;
-
-       if (rate == clk->parent->rate)
-               return -EINVAL;
-
-       value = __raw_readl(PLLC2CR) & ~(0x3f << 24);
-
-       __raw_writel(value | ((idx + 19) << 24), PLLC2CR);
-
-       clk->rate = clk->freq_table[idx].frequency;
-
-       return 0;
-}
-
-static int pllc2_set_parent(struct clk *clk, struct clk *parent)
-{
-       u32 value;
-       int ret, i;
-
-       if (!clk->parent_table || !clk->parent_num)
-               return -EINVAL;
-
-       /* Search the parent */
-       for (i = 0; i < clk->parent_num; i++)
-               if (clk->parent_table[i] == parent)
-                       break;
-
-       if (i == clk->parent_num)
-               return -ENODEV;
-
-       ret = clk_reparent(clk, parent);
-       if (ret < 0)
-               return ret;
-
-       value = __raw_readl(PLLC2CR) & ~(3 << 6);
-
-       __raw_writel(value | (i << 6), PLLC2CR);
-
-       /* Rebiuld the frequency table */
-       pllc2_table_rebuild(clk);
-
-       return 0;
-}
-
-static struct sh_clk_ops pllc2_clk_ops = {
-       .recalc         = pllc2_recalc,
-       .round_rate     = pllc2_round_rate,
-       .set_rate       = pllc2_set_rate,
-       .enable         = pllc2_enable,
-       .disable        = pllc2_disable,
-       .set_parent     = pllc2_set_parent,
-};
-
-struct clk sh7372_pllc2_clk = {
-       .ops            = &pllc2_clk_ops,
-       .parent         = &extal1_div2_clk,
-       .freq_table     = pllc2_freq_table,
-       .nr_freqs       = ARRAY_SIZE(pllc2_freq_table) - 1,
-       .parent_table   = pllc2_parent,
-       .parent_num     = ARRAY_SIZE(pllc2_parent),
-};
-
-/* External input clock (pin name: FSIACK/FSIBCK ) */
-static struct clk fsiack_clk = {
-};
-
-static struct clk fsibck_clk = {
-};
-
-static struct clk *main_clks[] = {
-       &sh7372_dv_clki_clk,
-       &r_clk,
-       &sh7372_extal1_clk,
-       &sh7372_extal2_clk,
-       &sh7372_dv_clki_div2_clk,
-       &extal1_div2_clk,
-       &extal2_div2_clk,
-       &extal2_div4_clk,
-       &pllc0_clk,
-       &pllc1_clk,
-       &pllc1_div2_clk,
-       &sh7372_pllc2_clk,
-       &fsiack_clk,
-       &fsibck_clk,
-};
-
-static void div4_kick(struct clk *clk)
-{
-       unsigned long value;
-
-       /* set KICK bit in FRQCRB to update hardware setting */
-       value = __raw_readl(FRQCRB);
-       value |= (1 << 31);
-       __raw_writel(value, FRQCRB);
-}
-
-static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18,
-                         24, 32, 36, 48, 0, 72, 96, 0 };
-
-static struct clk_div_mult_table div4_div_mult_table = {
-       .divisors = divisors,
-       .nr_divisors = ARRAY_SIZE(divisors),
-};
-
-static struct clk_div4_table div4_table = {
-       .div_mult_table = &div4_div_mult_table,
-       .kick = div4_kick,
-};
-
-enum { DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_CSIR,
-       DIV4_ZX, DIV4_HP,
-       DIV4_ISPB, DIV4_S, DIV4_ZB, DIV4_ZB3, DIV4_CP,
-       DIV4_DDRP, DIV4_NR };
-
-#define DIV4(_reg, _bit, _mask, _flags) \
-  SH_CLK_DIV4(&pllc1_clk, _reg, _bit, _mask, _flags)
-
-static struct clk div4_clks[DIV4_NR] = {
-       [DIV4_I] = DIV4(FRQCRA, 20, 0x6fff, CLK_ENABLE_ON_INIT),
-       [DIV4_ZG] = DIV4(FRQCRA, 16, 0x6fff, CLK_ENABLE_ON_INIT),
-       [DIV4_B] = DIV4(FRQCRA, 8, 0x6fff, CLK_ENABLE_ON_INIT),
-       [DIV4_M1] = DIV4(FRQCRA, 4, 0x6fff, CLK_ENABLE_ON_INIT),
-       [DIV4_CSIR] = DIV4(FRQCRA, 0, 0x6fff, 0),
-       [DIV4_ZX] = DIV4(FRQCRB, 12, 0x6fff, 0),
-       [DIV4_HP] = DIV4(FRQCRB, 4, 0x6fff, 0),
-       [DIV4_ISPB] = DIV4(FRQCRC, 20, 0x6fff, 0),
-       [DIV4_S] = DIV4(FRQCRC, 12, 0x6fff, 0),
-       [DIV4_ZB] = DIV4(FRQCRC, 8, 0x6fff, 0),
-       [DIV4_ZB3] = DIV4(FRQCRC, 4, 0x6fff, 0),
-       [DIV4_CP] = DIV4(FRQCRC, 0, 0x6fff, 0),
-       [DIV4_DDRP] = DIV4(FRQCRD, 0, 0x677c, 0),
-};
-
-enum { DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_FMSI, DIV6_FMSO,
-       DIV6_SUB, DIV6_SPU,
-       DIV6_VOU, DIV6_DSIT, DIV6_DSI0P, DIV6_DSI1P,
-       DIV6_NR };
-
-static struct clk div6_clks[DIV6_NR] = {
-       [DIV6_VCK1] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR1, 0),
-       [DIV6_VCK2] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR2, 0),
-       [DIV6_VCK3] = SH_CLK_DIV6(&pllc1_div2_clk, VCLKCR3, 0),
-       [DIV6_FMSI] = SH_CLK_DIV6(&pllc1_div2_clk, FMSICKCR, 0),
-       [DIV6_FMSO] = SH_CLK_DIV6(&pllc1_div2_clk, FMSOCKCR, 0),
-       [DIV6_SUB] = SH_CLK_DIV6(&sh7372_extal2_clk, SUBCKCR, 0),
-       [DIV6_SPU] = SH_CLK_DIV6(&pllc1_div2_clk, SPUCKCR, 0),
-       [DIV6_VOU] = SH_CLK_DIV6(&pllc1_div2_clk, VOUCKCR, 0),
-       [DIV6_DSIT] = SH_CLK_DIV6(&pllc1_div2_clk, DSITCKCR, 0),
-       [DIV6_DSI0P] = SH_CLK_DIV6(&pllc1_div2_clk, DSI0PCKCR, 0),
-       [DIV6_DSI1P] = SH_CLK_DIV6(&pllc1_div2_clk, DSI1PCKCR, 0),
-};
-
-enum { DIV6_HDMI, DIV6_FSIA, DIV6_FSIB, DIV6_REPARENT_NR };
-
-/* Indices are important - they are the actual src selecting values */
-static struct clk *hdmi_parent[] = {
-       [0] = &pllc1_div2_clk,
-       [1] = &sh7372_pllc2_clk,
-       [2] = &sh7372_dv_clki_clk,
-       [3] = NULL,     /* pllc2_div4 not implemented yet */
-};
-
-static struct clk *fsiackcr_parent[] = {
-       [0] = &pllc1_div2_clk,
-       [1] = &sh7372_pllc2_clk,
-       [2] = &fsiack_clk, /* external input for FSI A */
-       [3] = NULL,     /* setting prohibited */
-};
-
-static struct clk *fsibckcr_parent[] = {
-       [0] = &pllc1_div2_clk,
-       [1] = &sh7372_pllc2_clk,
-       [2] = &fsibck_clk, /* external input for FSI B */
-       [3] = NULL,     /* setting prohibited */
-};
-
-static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = {
-       [DIV6_HDMI] = SH_CLK_DIV6_EXT(HDMICKCR, 0,
-                                     hdmi_parent, ARRAY_SIZE(hdmi_parent), 6, 2),
-       [DIV6_FSIA] = SH_CLK_DIV6_EXT(FSIACKCR, 0,
-                                     fsiackcr_parent, ARRAY_SIZE(fsiackcr_parent), 6, 2),
-       [DIV6_FSIB] = SH_CLK_DIV6_EXT(FSIBCKCR, 0,
-                                     fsibckcr_parent, ARRAY_SIZE(fsibckcr_parent), 6, 2),
-};
-
-/* FSI DIV */
-enum { FSIDIV_A, FSIDIV_B, FSIDIV_REPARENT_NR };
-
-static struct clk fsidivs[] = {
-       [FSIDIV_A] = SH_CLK_FSIDIV(FSIDIVA, &div6_reparent_clks[DIV6_FSIA]),
-       [FSIDIV_B] = SH_CLK_FSIDIV(FSIDIVB, &div6_reparent_clks[DIV6_FSIB]),
-};
-
-enum { MSTP001, MSTP000,
-       MSTP131, MSTP130,
-       MSTP129, MSTP128, MSTP127, MSTP126, MSTP125,
-       MSTP118, MSTP117, MSTP116, MSTP113,
-       MSTP106, MSTP101, MSTP100,
-       MSTP223,
-       MSTP218, MSTP217, MSTP216, MSTP214, MSTP208, MSTP207,
-       MSTP206, MSTP205, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
-       MSTP328, MSTP323, MSTP322, MSTP315, MSTP314, MSTP313, MSTP312,
-       MSTP423, MSTP415, MSTP413, MSTP411, MSTP410, MSTP407, MSTP406,
-       MSTP405, MSTP404, MSTP403, MSTP400,
-       MSTP_NR };
-
-#define MSTP(_parent, _reg, _bit, _flags) \
-  SH_CLK_MSTP32(_parent, _reg, _bit, _flags)
-
-static struct clk mstp_clks[MSTP_NR] = {
-       [MSTP001] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR0, 1, 0), /* IIC2 */
-       [MSTP000] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR0, 0, 0), /* MSIOF0 */
-       [MSTP131] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 31, 0), /* VEU3 */
-       [MSTP130] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 30, 0), /* VEU2 */
-       [MSTP129] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 29, 0), /* VEU1 */
-       [MSTP128] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 28, 0), /* VEU0 */
-       [MSTP127] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 27, 0), /* CEU */
-       [MSTP126] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 26, 0), /* CSI2 */
-       [MSTP125] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR1, 25, 0), /* TMU0 */
-       [MSTP118] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 18, 0), /* DSITX */
-       [MSTP117] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 17, 0), /* LCDC1 */
-       [MSTP116] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR1, 16, 0), /* IIC0 */
-       [MSTP113] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR1, 13, 0), /* MERAM */
-       [MSTP106] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 6, 0), /* JPU */
-       [MSTP101] = MSTP(&div4_clks[DIV4_M1], SMSTPCR1, 1, 0), /* VPU */
-       [MSTP100] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 0, 0), /* LCDC0 */
-       [MSTP223] = MSTP(&div6_clks[DIV6_SPU], SMSTPCR2, 23, 0), /* SPU2 */
-       [MSTP218] = MSTP(&div4_clks[DIV4_HP], SMSTPCR2, 18, 0), /* DMAC1 */
-       [MSTP217] = MSTP(&div4_clks[DIV4_HP], SMSTPCR2, 17, 0), /* DMAC2 */
-       [MSTP216] = MSTP(&div4_clks[DIV4_HP], SMSTPCR2, 16, 0), /* DMAC3 */
-       [MSTP214] = MSTP(&div4_clks[DIV4_HP], SMSTPCR2, 14, 0), /* USBDMAC */
-       [MSTP208] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 8, 0), /* MSIOF1 */
-       [MSTP207] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 7, 0), /* SCIFA5 */
-       [MSTP206] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 6, 0), /* SCIFB */
-       [MSTP205] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 5, 0), /* MSIOF2 */
-       [MSTP204] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 4, 0), /* SCIFA0 */
-       [MSTP203] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 3, 0), /* SCIFA1 */
-       [MSTP202] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 2, 0), /* SCIFA2 */
-       [MSTP201] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 1, 0), /* SCIFA3 */
-       [MSTP200] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */
-       [MSTP328] = MSTP(&div6_clks[DIV6_SPU], SMSTPCR3, 28, 0), /* FSI2 */
-       [MSTP323] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */
-       [MSTP322] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 22, 0), /* USB0 */
-       [MSTP315] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 15, 0), /* FLCTL*/
-       [MSTP314] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 14, 0), /* SDHI0 */
-       [MSTP313] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 13, 0), /* SDHI1 */
-       [MSTP312] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMC */
-       [MSTP423] = MSTP(&div4_clks[DIV4_B], SMSTPCR4, 23, 0), /* DSITX1 */
-       [MSTP415] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 15, 0), /* SDHI2 */
-       [MSTP413] = MSTP(&pllc1_div2_clk, SMSTPCR4, 13, 0), /* HDMI */
-       [MSTP411] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR4, 11, 0), /* IIC3 */
-       [MSTP410] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR4, 10, 0), /* IIC4 */
-       [MSTP407] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 7, 0), /* USB-DMAC1 */
-       [MSTP406] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR4, 6, 0), /* USB1 */
-       [MSTP405] = MSTP(&r_clk, SMSTPCR4, 5, 0), /* CMT4 */
-       [MSTP404] = MSTP(&r_clk, SMSTPCR4, 4, 0), /* CMT3 */
-       [MSTP403] = MSTP(&r_clk, SMSTPCR4, 3, 0), /* KEYSC */
-       [MSTP400] = MSTP(&r_clk, SMSTPCR4, 0, 0), /* CMT2 */
-};
-
-static struct clk_lookup lookups[] = {
-       /* main clocks */
-       CLKDEV_CON_ID("dv_clki_div2_clk", &sh7372_dv_clki_div2_clk),
-       CLKDEV_CON_ID("r_clk", &r_clk),
-       CLKDEV_CON_ID("extal1", &sh7372_extal1_clk),
-       CLKDEV_CON_ID("extal2", &sh7372_extal2_clk),
-       CLKDEV_CON_ID("extal1_div2_clk", &extal1_div2_clk),
-       CLKDEV_CON_ID("extal2_div2_clk", &extal2_div2_clk),
-       CLKDEV_CON_ID("extal2_div4_clk", &extal2_div4_clk),
-       CLKDEV_CON_ID("pllc0_clk", &pllc0_clk),
-       CLKDEV_CON_ID("pllc1_clk", &pllc1_clk),
-       CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk),
-       CLKDEV_CON_ID("pllc2_clk", &sh7372_pllc2_clk),
-       CLKDEV_CON_ID("fsiack", &fsiack_clk),
-       CLKDEV_CON_ID("fsibck", &fsibck_clk),
-
-       /* DIV4 clocks */
-       CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]),
-       CLKDEV_CON_ID("zg_clk", &div4_clks[DIV4_ZG]),
-       CLKDEV_CON_ID("b_clk", &div4_clks[DIV4_B]),
-       CLKDEV_CON_ID("m1_clk", &div4_clks[DIV4_M1]),
-       CLKDEV_CON_ID("csir_clk", &div4_clks[DIV4_CSIR]),
-       CLKDEV_CON_ID("zx_clk", &div4_clks[DIV4_ZX]),
-       CLKDEV_CON_ID("hp_clk", &div4_clks[DIV4_HP]),
-       CLKDEV_CON_ID("ispb_clk", &div4_clks[DIV4_ISPB]),
-       CLKDEV_CON_ID("s_clk", &div4_clks[DIV4_S]),
-       CLKDEV_CON_ID("zb_clk", &div4_clks[DIV4_ZB]),
-       CLKDEV_CON_ID("zb3_clk", &div4_clks[DIV4_ZB3]),
-       CLKDEV_CON_ID("cp_clk", &div4_clks[DIV4_CP]),
-       CLKDEV_CON_ID("ddrp_clk", &div4_clks[DIV4_DDRP]),
-
-       /* DIV6 clocks */
-       CLKDEV_CON_ID("vck1_clk", &div6_clks[DIV6_VCK1]),
-       CLKDEV_CON_ID("vck2_clk", &div6_clks[DIV6_VCK2]),
-       CLKDEV_CON_ID("vck3_clk", &div6_clks[DIV6_VCK3]),
-       CLKDEV_CON_ID("fmsi_clk", &div6_clks[DIV6_FMSI]),
-       CLKDEV_CON_ID("fmso_clk", &div6_clks[DIV6_FMSO]),
-       CLKDEV_CON_ID("sub_clk", &div6_clks[DIV6_SUB]),
-       CLKDEV_CON_ID("spu_clk", &div6_clks[DIV6_SPU]),
-       CLKDEV_CON_ID("vou_clk", &div6_clks[DIV6_VOU]),
-       CLKDEV_CON_ID("hdmi_clk", &div6_reparent_clks[DIV6_HDMI]),
-
-       /* MSTP32 clocks */
-       CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* IIC2 */
-       CLKDEV_DEV_ID("fff30000.i2c", &mstp_clks[MSTP001]), /* IIC2 */
-       CLKDEV_DEV_ID("spi_sh_msiof.0", &mstp_clks[MSTP000]), /* MSIOF0 */
-       CLKDEV_DEV_ID("uio_pdrv_genirq.4", &mstp_clks[MSTP131]), /* VEU3 */
-       CLKDEV_DEV_ID("uio_pdrv_genirq.3", &mstp_clks[MSTP130]), /* VEU2 */
-       CLKDEV_DEV_ID("uio_pdrv_genirq.2", &mstp_clks[MSTP129]), /* VEU1 */
-       CLKDEV_DEV_ID("uio_pdrv_genirq.1", &mstp_clks[MSTP128]), /* VEU0 */
-       CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[MSTP127]), /* CEU */
-       CLKDEV_DEV_ID("sh-mobile-csi2.0", &mstp_clks[MSTP126]), /* CSI2 */
-       CLKDEV_DEV_ID("sh-mipi-dsi.0", &mstp_clks[MSTP118]), /* DSITX0 */
-       CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1", &mstp_clks[MSTP117]), /* LCDC1 */
-       CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* IIC0 */
-       CLKDEV_DEV_ID("fff20000.i2c", &mstp_clks[MSTP116]), /* IIC0 */
-       CLKDEV_DEV_ID("sh_mobile_meram.0", &mstp_clks[MSTP113]), /* MERAM */
-       CLKDEV_DEV_ID("uio_pdrv_genirq.5", &mstp_clks[MSTP106]), /* JPU */
-       CLKDEV_DEV_ID("uio_pdrv_genirq.0", &mstp_clks[MSTP101]), /* VPU */
-       CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[MSTP100]), /* LCDC0 */
-       CLKDEV_DEV_ID("uio_pdrv_genirq.6", &mstp_clks[MSTP223]), /* SPU2DSP0 */
-       CLKDEV_DEV_ID("uio_pdrv_genirq.7", &mstp_clks[MSTP223]), /* SPU2DSP1 */
-       CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]), /* DMAC1 */
-       CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[MSTP217]), /* DMAC2 */
-       CLKDEV_DEV_ID("sh-dma-engine.2", &mstp_clks[MSTP216]), /* DMAC3 */
-       CLKDEV_DEV_ID("sh-dma-engine.3", &mstp_clks[MSTP214]), /* USB-DMAC0 */
-       CLKDEV_DEV_ID("spi_sh_msiof.1", &mstp_clks[MSTP208]), /* MSIOF1 */
-       CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]), /* SCIFA5 */
-       CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP206]), /* SCIFB */
-       CLKDEV_DEV_ID("spi_sh_msiof.2", &mstp_clks[MSTP205]), /* MSIOF2 */
-       CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), /* SCIFA0 */
-       CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]), /* SCIFA1 */
-       CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP202]), /* SCIFA2 */
-       CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]), /* SCIFA3 */
-       CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */
-       CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI2 */
-       CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* IIC1 */
-       CLKDEV_DEV_ID("e6c20000.i2c", &mstp_clks[MSTP323]), /* IIC1 */
-       CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP322]), /* USB0 */
-       CLKDEV_DEV_ID("r8a66597_udc.0", &mstp_clks[MSTP322]), /* USB0 */
-       CLKDEV_DEV_ID("renesas_usbhs.0", &mstp_clks[MSTP322]), /* USB0 */
-       CLKDEV_DEV_ID("sh_flctl.0", &mstp_clks[MSTP315]), /* FLCTL */
-       CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */
-       CLKDEV_DEV_ID("e6850000.sdhi", &mstp_clks[MSTP314]), /* SDHI0 */
-       CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */
-       CLKDEV_DEV_ID("e6860000.sdhi", &mstp_clks[MSTP313]), /* SDHI1 */
-       CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMC */
-       CLKDEV_DEV_ID("e6bd0000.mmcif", &mstp_clks[MSTP312]), /* MMC */
-       CLKDEV_DEV_ID("sh-mipi-dsi.1", &mstp_clks[MSTP423]), /* DSITX1 */
-       CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP415]), /* SDHI2 */
-       CLKDEV_DEV_ID("e6870000.sdhi", &mstp_clks[MSTP415]), /* SDHI2 */
-       CLKDEV_DEV_ID("sh-mobile-hdmi", &mstp_clks[MSTP413]), /* HDMI */
-       CLKDEV_DEV_ID("i2c-sh_mobile.3", &mstp_clks[MSTP411]), /* IIC3 */
-       CLKDEV_DEV_ID("e6d20000.i2c", &mstp_clks[MSTP411]), /* IIC3 */
-       CLKDEV_DEV_ID("i2c-sh_mobile.4", &mstp_clks[MSTP410]), /* IIC4 */
-       CLKDEV_DEV_ID("e6d30000.i2c", &mstp_clks[MSTP410]), /* IIC4 */
-       CLKDEV_DEV_ID("sh-dma-engine.4", &mstp_clks[MSTP407]), /* USB-DMAC1 */
-       CLKDEV_DEV_ID("r8a66597_hcd.1", &mstp_clks[MSTP406]), /* USB1 */
-       CLKDEV_DEV_ID("r8a66597_udc.1", &mstp_clks[MSTP406]), /* USB1 */
-       CLKDEV_DEV_ID("renesas_usbhs.1", &mstp_clks[MSTP406]), /* USB1 */
-       CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */
-
-       /* ICK */
-       CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]),
-       CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSIT]),
-       CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]),
-       CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSI1P]),
-       CLKDEV_ICK_ID("hdmi", "sh_mobile_lcdc_fb.1",
-                     &div6_reparent_clks[DIV6_HDMI]),
-       CLKDEV_ICK_ID("ick", "sh-mobile-hdmi", &div6_reparent_clks[DIV6_HDMI]),
-       CLKDEV_ICK_ID("icka", "sh_fsi2", &div6_reparent_clks[DIV6_FSIA]),
-       CLKDEV_ICK_ID("ickb", "sh_fsi2", &div6_reparent_clks[DIV6_FSIB]),
-       CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[MSTP125]), /* TMU0 */
-       CLKDEV_ICK_ID("spu2", "sh_fsi2", &mstp_clks[MSTP223]),
-       CLKDEV_ICK_ID("fck", "sh-cmt-32-fast.4", &mstp_clks[MSTP405]), /* CMT4 */
-       CLKDEV_ICK_ID("fck", "sh-cmt-32-fast.3", &mstp_clks[MSTP404]), /* CMT3 */
-       CLKDEV_ICK_ID("fck", "sh-cmt-32-fast.2", &mstp_clks[MSTP400]), /* CMT2 */
-       CLKDEV_ICK_ID("diva", "sh_fsi2", &fsidivs[FSIDIV_A]),
-       CLKDEV_ICK_ID("divb", "sh_fsi2", &fsidivs[FSIDIV_B]),
-       CLKDEV_ICK_ID("xcka", "sh_fsi2", &fsiack_clk),
-       CLKDEV_ICK_ID("xckb", "sh_fsi2", &fsibck_clk),
-};
-
-void __init sh7372_clock_init(void)
-{
-       int k, ret = 0;
-
-       /* make sure MSTP bits on the RT/SH4AL-DSP side are off */
-       __raw_writel(0xe4ef8087, RMSTPCR0);
-       __raw_writel(0xffffffff, RMSTPCR1);
-       __raw_writel(0x37c7f7ff, RMSTPCR2);
-       __raw_writel(0xffffffff, RMSTPCR3);
-       __raw_writel(0xffe0fffd, RMSTPCR4);
-
-       for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
-               ret = clk_register(main_clks[k]);
-
-       if (!ret)
-               ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
-
-       if (!ret)
-               ret = sh_clk_div6_register(div6_clks, DIV6_NR);
-
-       if (!ret)
-               ret = sh_clk_div6_reparent_register(div6_reparent_clks, DIV6_REPARENT_NR);
-
-       if (!ret)
-               ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
-
-       if (!ret)
-               ret = sh_clk_fsidiv_register(fsidivs, FSIDIV_REPARENT_NR);
-
-       clkdev_add_table(lookups, ARRAY_SIZE(lookups));
-
-       if (!ret)
-               shmobile_clk_init();
-       else
-               panic("failed to setup sh7372 clocks\n");
-}
index 34f056fc375691c22169b4ee26fb4f049e1396e6..68c2d06d0eaaa800ce61bc074320259cf6b6f9eb 100644 (file)
@@ -45,14 +45,3 @@ int __init shmobile_clk_init(void)
 
        return 0;
 }
-
-int __clk_get(struct clk *clk)
-{
-       return 1;
-}
-EXPORT_SYMBOL(__clk_get);
-
-void __clk_put(struct clk *clk)
-{
-}
-EXPORT_SYMBOL(__clk_put);
index 309025efd4cf29df8fecee49e05ddf883e10be04..afc60bad6fd6b7d02093b6bf7d384ec4d7914cec 100644 (file)
@@ -21,10 +21,7 @@ extern void shmobile_smp_scu_cpu_die(unsigned int cpu);
 extern int shmobile_smp_scu_cpu_kill(unsigned int cpu);
 struct clk;
 extern int shmobile_clk_init(void);
-extern void shmobile_handle_irq_intc(struct pt_regs *);
 extern struct platform_suspend_ops shmobile_suspend_ops;
-struct cpuidle_driver;
-extern void shmobile_cpuidle_set_driver(struct cpuidle_driver *drv);
 
 #ifdef CONFIG_SUSPEND
 int shmobile_suspend_init(void);
@@ -34,12 +31,6 @@ static inline int shmobile_suspend_init(void) { return 0; }
 static inline void shmobile_smp_apmu_suspend_init(void) { }
 #endif
 
-#ifdef CONFIG_CPU_IDLE
-int shmobile_cpuidle_init(void);
-#else
-static inline int shmobile_cpuidle_init(void) { return 0; }
-#endif
-
 #ifdef CONFIG_CPU_FREQ
 int shmobile_cpufreq_init(void);
 #else
@@ -51,7 +42,6 @@ extern void __iomem *shmobile_scu_base;
 static inline void __init shmobile_init_late(void)
 {
        shmobile_suspend_init();
-       shmobile_cpuidle_init();
        shmobile_cpufreq_init();
 }
 
diff --git a/arch/arm/mach-shmobile/cpuidle.c b/arch/arm/mach-shmobile/cpuidle.c
deleted file mode 100644 (file)
index 0afeb5c..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * CPUIdle support code for SH-Mobile ARM
- *
- *  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/pm.h>
-#include <linux/cpuidle.h>
-#include <linux/suspend.h>
-#include <linux/module.h>
-#include <linux/err.h>
-#include <asm/cpuidle.h>
-#include <asm/io.h>
-
-static struct cpuidle_driver shmobile_cpuidle_default_driver = {
-       .name                   = "shmobile_cpuidle",
-       .owner                  = THIS_MODULE,
-       .states[0]              = ARM_CPUIDLE_WFI_STATE,
-       .safe_state_index       = 0, /* C1 */
-       .state_count            = 1,
-};
-
-static struct cpuidle_driver *cpuidle_drv = &shmobile_cpuidle_default_driver;
-
-void __init shmobile_cpuidle_set_driver(struct cpuidle_driver *drv)
-{
-       cpuidle_drv = drv;
-}
-
-int __init shmobile_cpuidle_init(void)
-{
-       return cpuidle_register(cpuidle_drv, NULL);
-}
diff --git a/arch/arm/mach-shmobile/entry-intc.S b/arch/arm/mach-shmobile/entry-intc.S
deleted file mode 100644 (file)
index 1a1c00c..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * ARM Interrupt demux handler using INTC
- *
- * Copyright (C) 2010 Magnus Damm
- * Copyright (C) 2008 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 <asm/entry-macro-multi.S>
-
-#define INTCA_BASE     0xe6980000
-#define INTFLGA_OFFS   0x00000018 /* accept pending interrupt */
-#define INTEVTA_OFFS   0x00000020 /* vector number of accepted interrupt */
-#define INTLVLA_OFFS   0x00000030 /* priority level of accepted interrupt */
-#define INTLVLB_OFFS   0x00000034 /* previous priority level */
-
-       .macro  get_irqnr_preamble, base, tmp
-       ldr     \base, =INTCA_BASE
-       .endm
-
-       .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-       /* The single INTFLGA read access below results in the following:
-        *
-        * 1. INTLVLB is updated with old priority value from INTLVLA
-        * 2. Highest priority interrupt is accepted
-        * 3. INTLVLA is updated to contain priority of accepted interrupt
-        * 4. Accepted interrupt vector is stored in INTFLGA and INTEVTA
-        */
-       ldr     \irqnr, [\base, #INTFLGA_OFFS]
-
-       /* Restore INTLVLA with the value saved in INTLVLB.
-        * This is required to support interrupt priorities properly.
-        */
-       ldrb    \tmp, [\base, #INTLVLB_OFFS]
-       strb    \tmp, [\base, #INTLVLA_OFFS]
-
-       /* Handle invalid vector number case */
-       cmp     \irqnr, #0
-       beq     1000f
-
-       /* Convert vector to irq number, same as the evt2irq() macro */
-       lsr     \irqnr, \irqnr, #0x5
-       subs    \irqnr, \irqnr, #16
-
-1000:
-       .endm
-
-       .macro  test_for_ipi, irqnr, irqstat, base, tmp
-       .endm
-
-       arch_irq_handler shmobile_handle_irq_intc
diff --git a/arch/arm/mach-shmobile/include/mach/clkdev.h b/arch/arm/mach-shmobile/include/mach/clkdev.h
deleted file mode 100644 (file)
index 36d0163..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-int __clk_get(struct clk *clk);
-void __clk_put(struct clk *clk);
-
-#endif /* __ASM_MACH_CLKDEV_H */
diff --git a/arch/arm/mach-shmobile/include/mach/head-mackerel.txt b/arch/arm/mach-shmobile/include/mach/head-mackerel.txt
deleted file mode 100644 (file)
index 9f134df..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-LIST "partner-jet-setup.txt"
-LIST "(C) Copyright 2010 Renesas Solutions Corp"
-LIST "Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"
-
-LIST "RWT Setting"
-EW 0xE6020004, 0xA500
-EW 0xE6030004, 0xA500
-
-LIST "GPIO Setting"
-EB 0xE6051013, 0xA2
-
-LIST "CPG"
-ED 0xE61500C0, 0x00000002
-
-WAIT 1, 0xFE40009C
-
-LIST "FRQCR"
-ED 0xE6150000, 0x2D1305C3
-ED 0xE61500E0, 0x9E40358E
-ED 0xE6150004, 0x80331050
-
-WAIT 1, 0xFE40009C
-
-ED 0xE61500E4, 0x00002000
-
-WAIT 1, 0xFE40009C
-
-LIST "PLL"
-ED 0xE6150028, 0x00004000
-
-WAIT 1, 0xFE40009C
-
-ED 0xE615002C, 0x93000040
-
-WAIT 1, 0xFE40009C
-
-LIST "SUB/USBClk"
-ED 0xE6150080, 0x00000180
-
-LIST "BSC"
-ED 0xFEC10000, 0x00E0001B
-
-LIST "SBSC1"
-ED 0xFE400354, 0x01AD8000
-ED 0xFE400354, 0x01AD8001
-
-WAIT 5, 0xFE40009C
-
-ED 0xFE400008, 0xBCC90151
-ED 0xFE400040, 0x41774113
-ED 0xFE400044, 0x2712E229
-ED 0xFE400048, 0x20C18505
-ED 0xFE40004C, 0x00110209
-ED 0xFE400010, 0x00000087
-
-WAIT 30, 0xFE40009C
-
-ED 0xFE400084, 0x0000003F
-EB 0xFE500000, 0x00
-
-WAIT 5, 0xFE40009C
-
-ED 0xFE400084, 0x0000FF0A
-EB 0xFE500000, 0x00
-
-WAIT 1, 0xFE40009C
-
-ED 0xFE400084, 0x00002201
-EB 0xFE500000, 0x00
-ED 0xFE400084, 0x00000302
-EB 0xFE500000, 0x00
-EB 0xFE5C0000, 0x00
-ED 0xFE400008, 0xBCC90159
-ED 0xFE40008C, 0x88800004
-ED 0xFE400094, 0x00000004
-ED 0xFE400028, 0xA55A0032
-ED 0xFE40002C, 0xA55A000C
-ED 0xFE400020, 0xA55A2048
-ED 0xFE400008, 0xBCC90959
-
-LIST "Change CPGA setting"
-ED 0xE61500E0, 0x9E40352E
-ED 0xE6150004, 0x80331050
-
-WAIT 1, 0xFE40009C
-
-ED 0xFE400354, 0x01AD8002
-
-LIST "SCIF0 - Serial port for earlyprintk"
-EB 0xE6053098, 0xe1
-EW 0xE6C40000, 0x0000
-EB 0xE6C40004, 0x19
-EW 0xE6C40008, 0x0030
diff --git a/arch/arm/mach-shmobile/include/mach/mmc-mackerel.h b/arch/arm/mach-shmobile/include/mach/mmc-mackerel.h
deleted file mode 100644 (file)
index 15d3a9e..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef MMC_MACKEREL_H
-#define MMC_MACKEREL_H
-
-#define PORT0CR      (void __iomem *)0xe6051000
-#define PORT1CR      (void __iomem *)0xe6051001
-#define PORT2CR      (void __iomem *)0xe6051002
-#define PORT159CR    (void __iomem *)0xe605009f
-
-#define PORTR031_000DR (void __iomem *)0xe6055000
-#define PORTL159_128DR (void __iomem *)0xe6054010
-
-static inline void mmc_init_progress(void)
-{
-       /* Initialise LEDS0-3
-        * registers: PORT0CR-PORT2CR,PORT159CR (LED0-LED3 Control)
-        * value:     0x10 - enable output
-        */
-       __raw_writeb(0x10, PORT0CR);
-       __raw_writeb(0x10, PORT1CR);
-       __raw_writeb(0x10, PORT2CR);
-       __raw_writeb(0x10, PORT159CR);
-}
-
-static inline void mmc_update_progress(int n)
-{
-       unsigned a = 0, b = 0;
-
-       if (n < 3)
-               a = 1 << n;
-       else
-               b = 1 << 31;
-
-       __raw_writel((__raw_readl(PORTR031_000DR) & ~0x7) | a,
-                    PORTR031_000DR);
-       __raw_writel((__raw_readl(PORTL159_128DR) & ~(1 << 31)) | b,
-                    PORTL159_128DR);
-}
-#endif /* MMC_MACKEREL_H */
diff --git a/arch/arm/mach-shmobile/include/mach/mmc.h b/arch/arm/mach-shmobile/include/mach/mmc.h
deleted file mode 100644 (file)
index e979b8f..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef MMC_H
-#define MMC_H
-
-/**************************************************
- *
- *             board specific settings
- *
- **************************************************/
-
-#ifdef CONFIG_MACH_MACKEREL
-#include "mach/mmc-mackerel.h"
-#else
-#error "unsupported board."
-#endif
-
-#endif /* MMC_H */
diff --git a/arch/arm/mach-shmobile/include/mach/sdhi-sh7372.h b/arch/arm/mach-shmobile/include/mach/sdhi-sh7372.h
deleted file mode 100644 (file)
index 4a81b01..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef SDHI_SH7372_H
-#define SDHI_SH7372_H
-
-#define SDGENCNTA       0xfe40009c
-
-/* The countdown of SDGENCNTA is controlled by
- * ZB3D2CLK which runs at 149.5MHz.
- * That is 149.5ticks/us. Approximate this as 150ticks/us.
- */
-static void udelay(int us)
-{
-       __raw_writel(us * 150, SDGENCNTA);
-       while(__raw_readl(SDGENCNTA)) ;
-}
-
-static void msleep(int ms)
-{
-       udelay(ms * 1000);
-}
-
-#endif
diff --git a/arch/arm/mach-shmobile/include/mach/sdhi.h b/arch/arm/mach-shmobile/include/mach/sdhi.h
deleted file mode 100644 (file)
index 0ec9e69..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef SDHI_H
-#define SDHI_H
-
-/**************************************************
- *
- *             CPU specific settings
- *
- **************************************************/
-
-#ifdef CONFIG_ARCH_SH7372
-#include "mach/sdhi-sh7372.h"
-#else
-#error "unsupported CPU."
-#endif
-
-#endif /* SDHI_H */
diff --git a/arch/arm/mach-shmobile/include/mach/system.h b/arch/arm/mach-shmobile/include/mach/system.h
deleted file mode 100644 (file)
index 540eaff..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef __ASM_ARCH_SYSTEM_H
-#define __ASM_ARCH_SYSTEM_H
-
-#include <asm/system_misc.h>
-
-static inline void arch_reset(char mode, const char *cmd)
-{
-       soft_restart(0);
-}
-
-#endif
diff --git a/arch/arm/mach-shmobile/include/mach/uncompress.h b/arch/arm/mach-shmobile/include/mach/uncompress.h
deleted file mode 100644 (file)
index f1aee56..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef __ASM_MACH_UNCOMPRESS_H
-#define __ASM_MACH_UNCOMPRESS_H
-
-/*
- * This does not append a newline
- */
-static void putc(int c)
-{
-}
-
-static inline void flush(void)
-{
-}
-
-static void arch_decomp_setup(void)
-{
-}
-
-#endif /* __ASM_MACH_UNCOMPRESS_H */
index 727cc78ac8ece93729603fe23188119f9fe1cdcf..175ee05465da19eb04a6f95422e451124448f772 100644 (file)
@@ -9,10 +9,7 @@
  *
  **************************************************/
 
-#ifdef CONFIG_MACH_MACKEREL
-#define MEMORY_START   0x40000000
-#include "mach/head-mackerel.txt"
-#elif defined(CONFIG_MACH_KZM9G) || defined(CONFIG_MACH_KZM9G_REFERENCE)
+#ifdef CONFIG_MACH_KZM9G
 #define MEMORY_START   0x43000000
 #include "mach/head-kzm9g.txt"
 #else
diff --git a/arch/arm/mach-shmobile/intc-sh7372.c b/arch/arm/mach-shmobile/intc-sh7372.c
deleted file mode 100644 (file)
index 1ccf49c..0000000
+++ /dev/null
@@ -1,672 +0,0 @@
-/*
- * sh7372 processor support - INTC hardware block
- *
- * Copyright (C) 2010  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/interrupt.h>
-#include <linux/module.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include "intc.h"
-#include "irqs.h"
-
-enum {
-       UNUSED_INTCA = 0,
-
-       /* interrupt sources INTCA */
-       DIRC,
-       CRYPT_STD,
-       IIC1_ALI1, IIC1_TACKI1, IIC1_WAITI1, IIC1_DTEI1,
-       AP_ARM_IRQPMU, AP_ARM_COMMTX, AP_ARM_COMMRX,
-       MFI_MFIM, MFI_MFIS,
-       BBIF1, BBIF2,
-       USBHSDMAC0_USHDMI,
-       _3DG_SGX540,
-       CMT1_CMT10, CMT1_CMT11, CMT1_CMT12, CMT1_CMT13, CMT2, CMT3,
-       KEYSC_KEY,
-       SCIFA0, SCIFA1, SCIFA2, SCIFA3,
-       MSIOF2, MSIOF1,
-       SCIFA4, SCIFA5, SCIFB,
-       FLCTL_FLSTEI, FLCTL_FLTENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I,
-       SDHI0_SDHI0I0, SDHI0_SDHI0I1, SDHI0_SDHI0I2, SDHI0_SDHI0I3,
-       SDHI1_SDHI1I0, SDHI1_SDHI1I1, SDHI1_SDHI1I2,
-       IRREM,
-       IRDA,
-       TPU0,
-       TTI20,
-       DDM,
-       SDHI2_SDHI2I0, SDHI2_SDHI2I1, SDHI2_SDHI2I2, SDHI2_SDHI2I3,
-       RWDT0,
-       DMAC1_1_DEI0, DMAC1_1_DEI1, DMAC1_1_DEI2, DMAC1_1_DEI3,
-       DMAC1_2_DEI4, DMAC1_2_DEI5, DMAC1_2_DADERR,
-       DMAC2_1_DEI0, DMAC2_1_DEI1, DMAC2_1_DEI2, DMAC2_1_DEI3,
-       DMAC2_2_DEI4, DMAC2_2_DEI5, DMAC2_2_DADERR,
-       DMAC3_1_DEI0, DMAC3_1_DEI1, DMAC3_1_DEI2, DMAC3_1_DEI3,
-       DMAC3_2_DEI4, DMAC3_2_DEI5, DMAC3_2_DADERR,
-       SHWYSTAT_RT, SHWYSTAT_HS, SHWYSTAT_COM,
-       HDMI,
-       SPU2_SPU0, SPU2_SPU1,
-       FSI, FMSI,
-       MIPI_HSI,
-       IPMMU_IPMMUD,
-       CEC_1, CEC_2,
-       AP_ARM_CTIIRQ, AP_ARM_DMAEXTERRIRQ, AP_ARM_DMAIRQ, AP_ARM_DMASIRQ,
-       MFIS2,
-       CPORTR2S,
-       CMT14, CMT15,
-       MMC_MMC_ERR, MMC_MMC_NOR,
-       IIC4_ALI4, IIC4_TACKI4, IIC4_WAITI4, IIC4_DTEI4,
-       IIC3_ALI3, IIC3_TACKI3, IIC3_WAITI3, IIC3_DTEI3,
-       USB0_USB0I1, USB0_USB0I0,
-       USB1_USB1I1, USB1_USB1I0,
-       USBHSDMAC1_USHDMI,
-
-       /* interrupt groups INTCA */
-       DMAC1_1, DMAC1_2, DMAC2_1, DMAC2_2, DMAC3_1, DMAC3_2, SHWYSTAT,
-       AP_ARM1, AP_ARM2, SPU2, FLCTL, IIC1, SDHI0, SDHI1, SDHI2
-};
-
-static struct intc_vect intca_vectors[] __initdata = {
-       INTC_VECT(DIRC, 0x0560),
-       INTC_VECT(CRYPT_STD, 0x0700),
-       INTC_VECT(IIC1_ALI1, 0x0780), INTC_VECT(IIC1_TACKI1, 0x07a0),
-       INTC_VECT(IIC1_WAITI1, 0x07c0), INTC_VECT(IIC1_DTEI1, 0x07e0),
-       INTC_VECT(AP_ARM_IRQPMU, 0x0800), INTC_VECT(AP_ARM_COMMTX, 0x0840),
-       INTC_VECT(AP_ARM_COMMRX, 0x0860),
-       INTC_VECT(MFI_MFIM, 0x0900), INTC_VECT(MFI_MFIS, 0x0920),
-       INTC_VECT(BBIF1, 0x0940), INTC_VECT(BBIF2, 0x0960),
-       INTC_VECT(USBHSDMAC0_USHDMI, 0x0a00),
-       INTC_VECT(_3DG_SGX540, 0x0a60),
-       INTC_VECT(CMT1_CMT10, 0x0b00), INTC_VECT(CMT1_CMT11, 0x0b20),
-       INTC_VECT(CMT1_CMT12, 0x0b40), INTC_VECT(CMT1_CMT13, 0x0b60),
-       INTC_VECT(CMT2, 0x0b80), INTC_VECT(CMT3, 0x0ba0),
-       INTC_VECT(KEYSC_KEY, 0x0be0),
-       INTC_VECT(SCIFA0, 0x0c00), INTC_VECT(SCIFA1, 0x0c20),
-       INTC_VECT(SCIFA2, 0x0c40), INTC_VECT(SCIFA3, 0x0c60),
-       INTC_VECT(MSIOF2, 0x0c80), INTC_VECT(MSIOF1, 0x0d00),
-       INTC_VECT(SCIFA4, 0x0d20), INTC_VECT(SCIFA5, 0x0d40),
-       INTC_VECT(SCIFB, 0x0d60),
-       INTC_VECT(FLCTL_FLSTEI, 0x0d80), INTC_VECT(FLCTL_FLTENDI, 0x0da0),
-       INTC_VECT(FLCTL_FLTREQ0I, 0x0dc0), INTC_VECT(FLCTL_FLTREQ1I, 0x0de0),
-       INTC_VECT(SDHI0_SDHI0I0, 0x0e00), INTC_VECT(SDHI0_SDHI0I1, 0x0e20),
-       INTC_VECT(SDHI0_SDHI0I2, 0x0e40), INTC_VECT(SDHI0_SDHI0I3, 0x0e60),
-       INTC_VECT(SDHI1_SDHI1I0, 0x0e80), INTC_VECT(SDHI1_SDHI1I1, 0x0ea0),
-       INTC_VECT(SDHI1_SDHI1I2, 0x0ec0),
-       INTC_VECT(IRREM, 0x0f60),
-       INTC_VECT(IRDA, 0x0480),
-       INTC_VECT(TPU0, 0x04a0),
-       INTC_VECT(TTI20, 0x1100),
-       INTC_VECT(DDM, 0x1140),
-       INTC_VECT(SDHI2_SDHI2I0, 0x1200), INTC_VECT(SDHI2_SDHI2I1, 0x1220),
-       INTC_VECT(SDHI2_SDHI2I2, 0x1240), INTC_VECT(SDHI2_SDHI2I3, 0x1260),
-       INTC_VECT(RWDT0, 0x1280),
-       INTC_VECT(DMAC1_1_DEI0, 0x2000), INTC_VECT(DMAC1_1_DEI1, 0x2020),
-       INTC_VECT(DMAC1_1_DEI2, 0x2040), INTC_VECT(DMAC1_1_DEI3, 0x2060),
-       INTC_VECT(DMAC1_2_DEI4, 0x2080), INTC_VECT(DMAC1_2_DEI5, 0x20a0),
-       INTC_VECT(DMAC1_2_DADERR, 0x20c0),
-       INTC_VECT(DMAC2_1_DEI0, 0x2100), INTC_VECT(DMAC2_1_DEI1, 0x2120),
-       INTC_VECT(DMAC2_1_DEI2, 0x2140), INTC_VECT(DMAC2_1_DEI3, 0x2160),
-       INTC_VECT(DMAC2_2_DEI4, 0x2180), INTC_VECT(DMAC2_2_DEI5, 0x21a0),
-       INTC_VECT(DMAC2_2_DADERR, 0x21c0),
-       INTC_VECT(DMAC3_1_DEI0, 0x2200), INTC_VECT(DMAC3_1_DEI1, 0x2220),
-       INTC_VECT(DMAC3_1_DEI2, 0x2240), INTC_VECT(DMAC3_1_DEI3, 0x2260),
-       INTC_VECT(DMAC3_2_DEI4, 0x2280), INTC_VECT(DMAC3_2_DEI5, 0x22a0),
-       INTC_VECT(DMAC3_2_DADERR, 0x22c0),
-       INTC_VECT(SHWYSTAT_RT, 0x1300), INTC_VECT(SHWYSTAT_HS, 0x1320),
-       INTC_VECT(SHWYSTAT_COM, 0x1340),
-       INTC_VECT(HDMI, 0x17e0),
-       INTC_VECT(SPU2_SPU0, 0x1800), INTC_VECT(SPU2_SPU1, 0x1820),
-       INTC_VECT(FSI, 0x1840),
-       INTC_VECT(FMSI, 0x1860),
-       INTC_VECT(MIPI_HSI, 0x18e0),
-       INTC_VECT(IPMMU_IPMMUD, 0x1920),
-       INTC_VECT(CEC_1, 0x1940), INTC_VECT(CEC_2, 0x1960),
-       INTC_VECT(AP_ARM_CTIIRQ, 0x1980),
-       INTC_VECT(AP_ARM_DMAEXTERRIRQ, 0x19a0),
-       INTC_VECT(AP_ARM_DMAIRQ, 0x19c0),
-       INTC_VECT(AP_ARM_DMASIRQ, 0x19e0),
-       INTC_VECT(MFIS2, 0x1a00),
-       INTC_VECT(CPORTR2S, 0x1a20),
-       INTC_VECT(CMT14, 0x1a40), INTC_VECT(CMT15, 0x1a60),
-       INTC_VECT(MMC_MMC_ERR, 0x1ac0), INTC_VECT(MMC_MMC_NOR, 0x1ae0),
-       INTC_VECT(IIC4_ALI4, 0x1b00), INTC_VECT(IIC4_TACKI4, 0x1b20),
-       INTC_VECT(IIC4_WAITI4, 0x1b40), INTC_VECT(IIC4_DTEI4, 0x1b60),
-       INTC_VECT(IIC3_ALI3, 0x1b80), INTC_VECT(IIC3_TACKI3, 0x1ba0),
-       INTC_VECT(IIC3_WAITI3, 0x1bc0), INTC_VECT(IIC3_DTEI3, 0x1be0),
-       INTC_VECT(USB0_USB0I1, 0x1c80), INTC_VECT(USB0_USB0I0, 0x1ca0),
-       INTC_VECT(USB1_USB1I1, 0x1cc0), INTC_VECT(USB1_USB1I0, 0x1ce0),
-       INTC_VECT(USBHSDMAC1_USHDMI, 0x1d00),
-};
-
-static struct intc_group intca_groups[] __initdata = {
-       INTC_GROUP(DMAC1_1, DMAC1_1_DEI0,
-                  DMAC1_1_DEI1, DMAC1_1_DEI2, DMAC1_1_DEI3),
-       INTC_GROUP(DMAC1_2, DMAC1_2_DEI4,
-                  DMAC1_2_DEI5, DMAC1_2_DADERR),
-       INTC_GROUP(DMAC2_1, DMAC2_1_DEI0,
-                  DMAC2_1_DEI1, DMAC2_1_DEI2, DMAC2_1_DEI3),
-       INTC_GROUP(DMAC2_2, DMAC2_2_DEI4,
-                  DMAC2_2_DEI5, DMAC2_2_DADERR),
-       INTC_GROUP(DMAC3_1, DMAC3_1_DEI0,
-                  DMAC3_1_DEI1, DMAC3_1_DEI2, DMAC3_1_DEI3),
-       INTC_GROUP(DMAC3_2, DMAC3_2_DEI4,
-                  DMAC3_2_DEI5, DMAC3_2_DADERR),
-       INTC_GROUP(AP_ARM1, AP_ARM_IRQPMU, AP_ARM_COMMTX, AP_ARM_COMMRX),
-       INTC_GROUP(AP_ARM2, AP_ARM_CTIIRQ, AP_ARM_DMAEXTERRIRQ,
-                  AP_ARM_DMAIRQ, AP_ARM_DMASIRQ),
-       INTC_GROUP(SPU2, SPU2_SPU0, SPU2_SPU1),
-       INTC_GROUP(FLCTL, FLCTL_FLSTEI, FLCTL_FLTENDI,
-                  FLCTL_FLTREQ0I, FLCTL_FLTREQ1I),
-       INTC_GROUP(IIC1, IIC1_ALI1, IIC1_TACKI1, IIC1_WAITI1, IIC1_DTEI1),
-       INTC_GROUP(SDHI0, SDHI0_SDHI0I0, SDHI0_SDHI0I1,
-                  SDHI0_SDHI0I2, SDHI0_SDHI0I3),
-       INTC_GROUP(SDHI1, SDHI1_SDHI1I0, SDHI1_SDHI1I1,
-                  SDHI1_SDHI1I2),
-       INTC_GROUP(SDHI2, SDHI2_SDHI2I0, SDHI2_SDHI2I1,
-                  SDHI2_SDHI2I2, SDHI2_SDHI2I3),
-       INTC_GROUP(SHWYSTAT, SHWYSTAT_RT, SHWYSTAT_HS, SHWYSTAT_COM),
-};
-
-static struct intc_mask_reg intca_mask_registers[] __initdata = {
-       { 0xe6940080, 0xe69400c0, 8, /* IMR0A / IMCR0A */
-         { DMAC2_1_DEI3, DMAC2_1_DEI2, DMAC2_1_DEI1, DMAC2_1_DEI0,
-           AP_ARM_IRQPMU, 0, AP_ARM_COMMTX, AP_ARM_COMMRX } },
-       { 0xe6940084, 0xe69400c4, 8, /* IMR1A / IMCR1A */
-         { 0, CRYPT_STD, DIRC, 0,
-           DMAC1_1_DEI3, DMAC1_1_DEI2, DMAC1_1_DEI1, DMAC1_1_DEI0 } },
-       { 0xe6940088, 0xe69400c8, 8, /* IMR2A / IMCR2A */
-         { 0, 0, 0, 0,
-           BBIF1, BBIF2, MFI_MFIS, MFI_MFIM } },
-       { 0xe694008c, 0xe69400cc, 8, /* IMR3A / IMCR3A */
-         { DMAC3_1_DEI3, DMAC3_1_DEI2, DMAC3_1_DEI1, DMAC3_1_DEI0,
-           DMAC3_2_DADERR, DMAC3_2_DEI5, DMAC3_2_DEI4, IRDA } },
-       { 0xe6940090, 0xe69400d0, 8, /* IMR4A / IMCR4A */
-         { DDM, 0, 0, 0,
-           0, 0, 0, 0 } },
-       { 0xe6940094, 0xe69400d4, 8, /* IMR5A / IMCR5A */
-         { KEYSC_KEY, DMAC1_2_DADERR, DMAC1_2_DEI5, DMAC1_2_DEI4,
-           SCIFA3, SCIFA2, SCIFA1, SCIFA0 } },
-       { 0xe6940098, 0xe69400d8, 8, /* IMR6A / IMCR6A */
-         { SCIFB, SCIFA5, SCIFA4, MSIOF1,
-           0, 0, MSIOF2, 0 } },
-       { 0xe694009c, 0xe69400dc, 8, /* IMR7A / IMCR7A */
-         { SDHI0_SDHI0I3, SDHI0_SDHI0I2, SDHI0_SDHI0I1, SDHI0_SDHI0I0,
-           FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLTENDI, FLCTL_FLSTEI } },
-       { 0xe69400a0, 0xe69400e0, 8, /* IMR8A / IMCR8A */
-         { 0, SDHI1_SDHI1I2, SDHI1_SDHI1I1, SDHI1_SDHI1I0,
-           TTI20, USBHSDMAC0_USHDMI, 0, 0 } },
-       { 0xe69400a4, 0xe69400e4, 8, /* IMR9A / IMCR9A */
-         { CMT1_CMT13, CMT1_CMT12, CMT1_CMT11, CMT1_CMT10,
-           CMT2, 0, 0, _3DG_SGX540 } },
-       { 0xe69400a8, 0xe69400e8, 8, /* IMR10A / IMCR10A */
-         { 0, DMAC2_2_DADERR, DMAC2_2_DEI5, DMAC2_2_DEI4,
-           0, 0, 0, 0 } },
-       { 0xe69400ac, 0xe69400ec, 8, /* IMR11A / IMCR11A */
-         { IIC1_DTEI1, IIC1_WAITI1, IIC1_TACKI1, IIC1_ALI1,
-           0, 0, IRREM, 0 } },
-       { 0xe69400b0, 0xe69400f0, 8, /* IMR12A / IMCR12A */
-         { 0, 0, TPU0, 0,
-           0, 0, 0, 0 } },
-       { 0xe69400b4, 0xe69400f4, 8, /* IMR13A / IMCR13A */
-         { SDHI2_SDHI2I3, SDHI2_SDHI2I2, SDHI2_SDHI2I1, SDHI2_SDHI2I0,
-           0, CMT3, 0, RWDT0 } },
-       { 0xe6950080, 0xe69500c0, 8, /* IMR0A3 / IMCR0A3 */
-         { SHWYSTAT_RT, SHWYSTAT_HS, SHWYSTAT_COM, 0,
-           0, 0, 0, 0 } },
-       { 0xe6950090, 0xe69500d0, 8, /* IMR4A3 / IMCR4A3 */
-         { 0, 0, 0, 0,
-           0, 0, 0, HDMI } },
-       { 0xe6950094, 0xe69500d4, 8, /* IMR5A3 / IMCR5A3 */
-         { SPU2_SPU0, SPU2_SPU1, FSI, FMSI,
-           0, 0, 0, MIPI_HSI } },
-       { 0xe6950098, 0xe69500d8, 8, /* IMR6A3 / IMCR6A3 */
-         { 0, IPMMU_IPMMUD, CEC_1, CEC_2,
-           AP_ARM_CTIIRQ, AP_ARM_DMAEXTERRIRQ,
-           AP_ARM_DMAIRQ, AP_ARM_DMASIRQ } },
-       { 0xe695009c, 0xe69500dc, 8, /* IMR7A3 / IMCR7A3 */
-         { MFIS2, CPORTR2S, CMT14, CMT15,
-           0, 0, MMC_MMC_ERR, MMC_MMC_NOR } },
-       { 0xe69500a0, 0xe69500e0, 8, /* IMR8A3 / IMCR8A3 */
-         { IIC4_ALI4, IIC4_TACKI4, IIC4_WAITI4, IIC4_DTEI4,
-           IIC3_ALI3, IIC3_TACKI3, IIC3_WAITI3, IIC3_DTEI3 } },
-       { 0xe69500a4, 0xe69500e4, 8, /* IMR9A3 / IMCR9A3 */
-         { 0, 0, 0, 0,
-           USB0_USB0I1, USB0_USB0I0, USB1_USB1I1, USB1_USB1I0 } },
-       { 0xe69500a8, 0xe69500e8, 8, /* IMR10A3 / IMCR10A3 */
-         { USBHSDMAC1_USHDMI, 0, 0, 0,
-           0, 0, 0, 0 } },
-};
-
-static struct intc_prio_reg intca_prio_registers[] __initdata = {
-       { 0xe6940000, 0, 16, 4, /* IPRAA */ { DMAC3_1, DMAC3_2, CMT2, 0 } },
-       { 0xe6940004, 0, 16, 4, /* IPRBA */ { IRDA, 0, BBIF1, BBIF2 } },
-       { 0xe6940008, 0, 16, 4, /* IPRCA */ { 0, CRYPT_STD,
-                                             CMT1_CMT11, AP_ARM1 } },
-       { 0xe694000c, 0, 16, 4, /* IPRDA */ { 0, 0,
-                                             CMT1_CMT12, 0 } },
-       { 0xe6940010, 0, 16, 4, /* IPREA */ { DMAC1_1, MFI_MFIS,
-                                             MFI_MFIM, 0 } },
-       { 0xe6940014, 0, 16, 4, /* IPRFA */ { KEYSC_KEY, DMAC1_2,
-                                             _3DG_SGX540, CMT1_CMT10 } },
-       { 0xe6940018, 0, 16, 4, /* IPRGA */ { SCIFA0, SCIFA1,
-                                             SCIFA2, SCIFA3 } },
-       { 0xe694001c, 0, 16, 4, /* IPRGH */ { MSIOF2, USBHSDMAC0_USHDMI,
-                                             FLCTL, SDHI0 } },
-       { 0xe6940020, 0, 16, 4, /* IPRIA */ { MSIOF1, SCIFA4,
-                                             0/* MSU */, IIC1 } },
-       { 0xe6940024, 0, 16, 4, /* IPRJA */ { DMAC2_1, DMAC2_2,
-                                             0/* MSUG */, TTI20 } },
-       { 0xe6940028, 0, 16, 4, /* IPRKA */ { 0, CMT1_CMT13, IRREM, SDHI1 } },
-       { 0xe694002c, 0, 16, 4, /* IPRLA */ { TPU0, 0, 0, 0 } },
-       { 0xe6940030, 0, 16, 4, /* IPRMA */ { 0, CMT3, 0, RWDT0 } },
-       { 0xe6940034, 0, 16, 4, /* IPRNA */ { SCIFB, SCIFA5, 0, DDM } },
-       { 0xe6940038, 0, 16, 4, /* IPROA */ { 0, 0, DIRC, SDHI2 } },
-       { 0xe6950000, 0, 16, 4, /* IPRAA3 */ { SHWYSTAT, 0, 0, 0 } },
-       { 0xe6950024, 0, 16, 4, /* IPRJA3 */ { 0, 0, 0, HDMI } },
-       { 0xe6950028, 0, 16, 4, /* IPRKA3 */ { SPU2, 0, FSI, FMSI } },
-       { 0xe695002c, 0, 16, 4, /* IPRLA3 */ { 0, 0, 0, MIPI_HSI } },
-       { 0xe6950030, 0, 16, 4, /* IPRMA3 */ { IPMMU_IPMMUD, 0,
-                                              CEC_1, CEC_2 } },
-       { 0xe6950034, 0, 16, 4, /* IPRNA3 */ { AP_ARM2, 0, 0, 0 } },
-       { 0xe6950038, 0, 16, 4, /* IPROA3 */ { MFIS2, CPORTR2S,
-                                              CMT14, CMT15 } },
-       { 0xe695003c, 0, 16, 4, /* IPRPA3 */ { 0, 0,
-                                              MMC_MMC_ERR, MMC_MMC_NOR } },
-       { 0xe6950040, 0, 16, 4, /* IPRQA3 */ { IIC4_ALI4, IIC4_TACKI4,
-                                              IIC4_WAITI4, IIC4_DTEI4 } },
-       { 0xe6950044, 0, 16, 4, /* IPRRA3 */ { IIC3_ALI3, IIC3_TACKI3,
-                                              IIC3_WAITI3, IIC3_DTEI3 } },
-       { 0xe6950048, 0, 16, 4, /* IPRSA3 */ { 0/*ERI*/, 0/*RXI*/,
-                                              0/*TXI*/, 0/*TEI*/} },
-       { 0xe695004c, 0, 16, 4, /* IPRTA3 */ { USB0_USB0I1, USB0_USB0I0,
-                                              USB1_USB1I1, USB1_USB1I0 } },
-       { 0xe6950050, 0, 16, 4, /* IPRUA3 */ { USBHSDMAC1_USHDMI, 0, 0, 0 } },
-};
-
-static DECLARE_INTC_DESC(intca_desc, "sh7372-intca",
-                        intca_vectors, intca_groups,
-                        intca_mask_registers, intca_prio_registers,
-                        NULL);
-
-INTC_IRQ_PINS_16(intca_irq_pins_lo, 0xe6900000,
-                INTC_VECT, "sh7372-intca-irq-lo");
-
-INTC_IRQ_PINS_16H(intca_irq_pins_hi, 0xe6900000,
-                INTC_VECT, "sh7372-intca-irq-hi");
-
-enum {
-       UNUSED_INTCS = 0,
-       ENABLED_INTCS,
-
-       /* interrupt sources INTCS */
-
-       /* IRQ0S - IRQ31S */
-       VEU_VEU0, VEU_VEU1, VEU_VEU2, VEU_VEU3,
-       RTDMAC_1_DEI0, RTDMAC_1_DEI1, RTDMAC_1_DEI2, RTDMAC_1_DEI3,
-       CEU, BEU_BEU0, BEU_BEU1, BEU_BEU2,
-       /* MFI */
-       /* BBIF2 */
-       VPU,
-       TSIF1,
-       /* 3DG */
-       _2DDMAC,
-       IIC2_ALI2, IIC2_TACKI2, IIC2_WAITI2, IIC2_DTEI2,
-       IPMMU_IPMMUR, IPMMU_IPMMUR2,
-       RTDMAC_2_DEI4, RTDMAC_2_DEI5, RTDMAC_2_DADERR,
-       /* KEYSC */
-       /* TTI20 */
-       MSIOF,
-       IIC0_ALI0, IIC0_TACKI0, IIC0_WAITI0, IIC0_DTEI0,
-       TMU_TUNI0, TMU_TUNI1, TMU_TUNI2,
-       CMT0,
-       TSIF0,
-       /* CMT2 */
-       LMB,
-       CTI,
-       /* RWDT0 */
-       ICB,
-       JPU_JPEG,
-       LCDC,
-       LCRC,
-       RTDMAC2_1_DEI0, RTDMAC2_1_DEI1, RTDMAC2_1_DEI2, RTDMAC2_1_DEI3,
-       RTDMAC2_2_DEI4, RTDMAC2_2_DEI5, RTDMAC2_2_DADERR,
-       ISP,
-       LCDC1,
-       CSIRX,
-       DSITX_DSITX0,
-       DSITX_DSITX1,
-       /* SPU2 */
-       /* FSI */
-       /* FMSI */
-       /* HDMI */
-       TMU1_TUNI0, TMU1_TUNI1, TMU1_TUNI2,
-       CMT4,
-       DSITX1_DSITX1_0,
-       DSITX1_DSITX1_1,
-       MFIS2_INTCS, /* Priority always enabled using ENABLED_INTCS */
-       CPORTS2R,
-       /* CEC */
-       JPU6E,
-
-       /* interrupt groups INTCS */
-       RTDMAC_1, RTDMAC_2, VEU, BEU, IIC0, IPMMU, IIC2,
-       RTDMAC2_1, RTDMAC2_2, TMU1, DSITX,
-};
-
-static struct intc_vect intcs_vectors[] = {
-       /* IRQ0S - IRQ31S */
-       INTCS_VECT(VEU_VEU0, 0x700), INTCS_VECT(VEU_VEU1, 0x720),
-       INTCS_VECT(VEU_VEU2, 0x740), INTCS_VECT(VEU_VEU3, 0x760),
-       INTCS_VECT(RTDMAC_1_DEI0, 0x800), INTCS_VECT(RTDMAC_1_DEI1, 0x820),
-       INTCS_VECT(RTDMAC_1_DEI2, 0x840), INTCS_VECT(RTDMAC_1_DEI3, 0x860),
-       INTCS_VECT(CEU, 0x880), INTCS_VECT(BEU_BEU0, 0x8a0),
-       INTCS_VECT(BEU_BEU1, 0x8c0), INTCS_VECT(BEU_BEU2, 0x8e0),
-       /* MFI */
-       /* BBIF2 */
-       INTCS_VECT(VPU, 0x980),
-       INTCS_VECT(TSIF1, 0x9a0),
-       /* 3DG */
-       INTCS_VECT(_2DDMAC, 0xa00),
-       INTCS_VECT(IIC2_ALI2, 0xa80), INTCS_VECT(IIC2_TACKI2, 0xaa0),
-       INTCS_VECT(IIC2_WAITI2, 0xac0), INTCS_VECT(IIC2_DTEI2, 0xae0),
-       INTCS_VECT(IPMMU_IPMMUR, 0xb00), INTCS_VECT(IPMMU_IPMMUR2, 0xb20),
-       INTCS_VECT(RTDMAC_2_DEI4, 0xb80), INTCS_VECT(RTDMAC_2_DEI5, 0xba0),
-       INTCS_VECT(RTDMAC_2_DADERR, 0xbc0),
-       /* KEYSC */
-       /* TTI20 */
-       INTCS_VECT(MSIOF, 0x0d20),
-       INTCS_VECT(IIC0_ALI0, 0xe00), INTCS_VECT(IIC0_TACKI0, 0xe20),
-       INTCS_VECT(IIC0_WAITI0, 0xe40), INTCS_VECT(IIC0_DTEI0, 0xe60),
-       INTCS_VECT(TMU_TUNI0, 0xe80), INTCS_VECT(TMU_TUNI1, 0xea0),
-       INTCS_VECT(TMU_TUNI2, 0xec0),
-       INTCS_VECT(CMT0, 0xf00),
-       INTCS_VECT(TSIF0, 0xf20),
-       /* CMT2 */
-       INTCS_VECT(LMB, 0xf60),
-       INTCS_VECT(CTI, 0x400),
-       /* RWDT0 */
-       INTCS_VECT(ICB, 0x480),
-       INTCS_VECT(JPU_JPEG, 0x560),
-       INTCS_VECT(LCDC, 0x580),
-       INTCS_VECT(LCRC, 0x5a0),
-       INTCS_VECT(RTDMAC2_1_DEI0, 0x1300), INTCS_VECT(RTDMAC2_1_DEI1, 0x1320),
-       INTCS_VECT(RTDMAC2_1_DEI2, 0x1340), INTCS_VECT(RTDMAC2_1_DEI3, 0x1360),
-       INTCS_VECT(RTDMAC2_2_DEI4, 0x1380), INTCS_VECT(RTDMAC2_2_DEI5, 0x13a0),
-       INTCS_VECT(RTDMAC2_2_DADERR, 0x13c0),
-       INTCS_VECT(ISP, 0x1720),
-       INTCS_VECT(LCDC1, 0x1780),
-       INTCS_VECT(CSIRX, 0x17a0),
-       INTCS_VECT(DSITX_DSITX0, 0x17c0),
-       INTCS_VECT(DSITX_DSITX1, 0x17e0),
-       /* SPU2 */
-       /* FSI */
-       /* FMSI */
-       /* HDMI */
-       INTCS_VECT(TMU1_TUNI0, 0x1900), INTCS_VECT(TMU1_TUNI1, 0x1920),
-       INTCS_VECT(TMU1_TUNI2, 0x1940),
-       INTCS_VECT(CMT4, 0x1980),
-       INTCS_VECT(DSITX1_DSITX1_0, 0x19a0),
-       INTCS_VECT(DSITX1_DSITX1_1, 0x19c0),
-       INTCS_VECT(MFIS2_INTCS, 0x1a00),
-       INTCS_VECT(CPORTS2R, 0x1a20),
-       /* CEC */
-       INTCS_VECT(JPU6E, 0x1a80),
-};
-
-static struct intc_group intcs_groups[] __initdata = {
-       INTC_GROUP(RTDMAC_1, RTDMAC_1_DEI0, RTDMAC_1_DEI1,
-                  RTDMAC_1_DEI2, RTDMAC_1_DEI3),
-       INTC_GROUP(RTDMAC_2, RTDMAC_2_DEI4, RTDMAC_2_DEI5, RTDMAC_2_DADERR),
-       INTC_GROUP(VEU, VEU_VEU0, VEU_VEU1, VEU_VEU2, VEU_VEU3),
-       INTC_GROUP(BEU, BEU_BEU0, BEU_BEU1, BEU_BEU2),
-       INTC_GROUP(IIC0, IIC0_ALI0, IIC0_TACKI0, IIC0_WAITI0, IIC0_DTEI0),
-       INTC_GROUP(IPMMU, IPMMU_IPMMUR, IPMMU_IPMMUR2),
-       INTC_GROUP(IIC2, IIC2_ALI2, IIC2_TACKI2, IIC2_WAITI2, IIC2_DTEI2),
-       INTC_GROUP(RTDMAC2_1, RTDMAC2_1_DEI0, RTDMAC2_1_DEI1,
-                  RTDMAC2_1_DEI2, RTDMAC2_1_DEI3),
-       INTC_GROUP(RTDMAC2_2, RTDMAC2_2_DEI4,
-                  RTDMAC2_2_DEI5, RTDMAC2_2_DADERR),
-       INTC_GROUP(TMU1, TMU1_TUNI2, TMU1_TUNI1, TMU1_TUNI0),
-       INTC_GROUP(DSITX, DSITX_DSITX0, DSITX_DSITX1),
-};
-
-static struct intc_mask_reg intcs_mask_registers[] = {
-       { 0xffd20184, 0xffd201c4, 8, /* IMR1SA / IMCR1SA */
-         { BEU_BEU2, BEU_BEU1, BEU_BEU0, CEU,
-           VEU_VEU3, VEU_VEU2, VEU_VEU1, VEU_VEU0 } },
-       { 0xffd20188, 0xffd201c8, 8, /* IMR2SA / IMCR2SA */
-         { 0, 0, 0, VPU,
-           0, 0, 0, 0 } },
-       { 0xffd2018c, 0xffd201cc, 8, /* IMR3SA / IMCR3SA */
-         { 0, 0, 0, _2DDMAC,
-           0, 0, 0, ICB } },
-       { 0xffd20190, 0xffd201d0, 8, /* IMR4SA / IMCR4SA */
-         { 0, 0, 0, CTI,
-           JPU_JPEG, 0, LCRC, LCDC } },
-       { 0xffd20194, 0xffd201d4, 8, /* IMR5SA / IMCR5SA */
-         { 0, RTDMAC_2_DADERR, RTDMAC_2_DEI5, RTDMAC_2_DEI4,
-           RTDMAC_1_DEI3, RTDMAC_1_DEI2, RTDMAC_1_DEI1, RTDMAC_1_DEI0 } },
-       { 0xffd20198, 0xffd201d8, 8, /* IMR6SA / IMCR6SA */
-         { 0, 0, MSIOF, 0,
-           0, 0, 0, 0 } },
-       { 0xffd2019c, 0xffd201dc, 8, /* IMR7SA / IMCR7SA */
-         { 0, TMU_TUNI2, TMU_TUNI1, TMU_TUNI0,
-           0, 0, 0, 0 } },
-       { 0xffd201a4, 0xffd201e4, 8, /* IMR9SA / IMCR9SA */
-         { 0, 0, 0, CMT0,
-           IIC2_DTEI2, IIC2_WAITI2, IIC2_TACKI2, IIC2_ALI2 } },
-       { 0xffd201a8, 0xffd201e8, 8, /* IMR10SA / IMCR10SA */
-         { 0, 0, IPMMU_IPMMUR2, IPMMU_IPMMUR,
-           0, 0, 0, 0 } },
-       { 0xffd201ac, 0xffd201ec, 8, /* IMR11SA / IMCR11SA */
-         { IIC0_DTEI0, IIC0_WAITI0, IIC0_TACKI0, IIC0_ALI0,
-           0, TSIF1, LMB, TSIF0 } },
-       { 0xffd50180, 0xffd501c0, 8, /* IMR0SA3 / IMCR0SA3 */
-         { 0, RTDMAC2_2_DADERR, RTDMAC2_2_DEI5, RTDMAC2_2_DEI4,
-           RTDMAC2_1_DEI3, RTDMAC2_1_DEI2, RTDMAC2_1_DEI1, RTDMAC2_1_DEI0 } },
-       { 0xffd50190, 0xffd501d0, 8, /* IMR4SA3 / IMCR4SA3 */
-         { 0, ISP, 0, 0,
-           LCDC1, CSIRX, DSITX_DSITX0, DSITX_DSITX1 } },
-       { 0xffd50198, 0xffd501d8, 8, /* IMR6SA3 / IMCR6SA3 */
-         { 0, TMU1_TUNI2, TMU1_TUNI1, TMU1_TUNI0,
-           CMT4, DSITX1_DSITX1_0, DSITX1_DSITX1_1, 0 } },
-       { 0xffd5019c, 0xffd501dc, 8, /* IMR7SA3 / IMCR7SA3 */
-         { MFIS2_INTCS, CPORTS2R, 0, 0,
-           JPU6E, 0, 0, 0 } },
-};
-
-/* Priority is needed for INTCA to receive the INTCS interrupt */
-static struct intc_prio_reg intcs_prio_registers[] = {
-       { 0xffd20000, 0, 16, 4, /* IPRAS */ { CTI, 0, _2DDMAC, ICB } },
-       { 0xffd20004, 0, 16, 4, /* IPRBS */ { JPU_JPEG, LCDC, 0, LCRC } },
-       { 0xffd20010, 0, 16, 4, /* IPRES */ { RTDMAC_1, CEU, 0, VPU } },
-       { 0xffd20014, 0, 16, 4, /* IPRFS */ { 0, RTDMAC_2, 0, CMT0 } },
-       { 0xffd20018, 0, 16, 4, /* IPRGS */ { TMU_TUNI0, TMU_TUNI1,
-                                             TMU_TUNI2, TSIF1 } },
-       { 0xffd2001c, 0, 16, 4, /* IPRHS */ { 0, 0, VEU, BEU } },
-       { 0xffd20020, 0, 16, 4, /* IPRIS */ { 0, MSIOF, TSIF0, IIC0 } },
-       { 0xffd20028, 0, 16, 4, /* IPRKS */ { 0, 0, LMB, 0 } },
-       { 0xffd2002c, 0, 16, 4, /* IPRLS */ { IPMMU, 0, 0, 0 } },
-       { 0xffd20030, 0, 16, 4, /* IPRMS */ { IIC2, 0, 0, 0 } },
-       { 0xffd50000, 0, 16, 4, /* IPRAS3 */ { RTDMAC2_1, 0, 0, 0 } },
-       { 0xffd50004, 0, 16, 4, /* IPRBS3 */ { RTDMAC2_2, 0, 0, 0 } },
-       { 0xffd50020, 0, 16, 4, /* IPRIS3 */ { 0, ISP, 0, 0 } },
-       { 0xffd50024, 0, 16, 4, /* IPRJS3 */ { LCDC1, CSIRX, DSITX, 0 } },
-       { 0xffd50030, 0, 16, 4, /* IPRMS3 */ { TMU1, 0, 0, 0 } },
-       { 0xffd50034, 0, 16, 4, /* IPRNS3 */ { CMT4, DSITX1_DSITX1_0,
-                                              DSITX1_DSITX1_1, 0 } },
-       { 0xffd50038, 0, 16, 4, /* IPROS3 */ { ENABLED_INTCS, CPORTS2R,
-                                              0, 0 } },
-       { 0xffd5003c, 0, 16, 4, /* IPRPS3 */ { JPU6E, 0, 0, 0 } },
-};
-
-static struct resource intcs_resources[] __initdata = {
-       [0] = {
-               .start  = 0xffd20000,
-               .end    = 0xffd201ff,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = 0xffd50000,
-               .end    = 0xffd501ff,
-               .flags  = IORESOURCE_MEM,
-       }
-};
-
-static struct intc_desc intcs_desc __initdata = {
-       .name = "sh7372-intcs",
-       .force_enable = ENABLED_INTCS,
-       .skip_syscore_suspend = true,
-       .resource = intcs_resources,
-       .num_resources = ARRAY_SIZE(intcs_resources),
-       .hw = INTC_HW_DESC(intcs_vectors, intcs_groups, intcs_mask_registers,
-                          intcs_prio_registers, NULL, NULL),
-};
-
-static void intcs_demux(unsigned int irq, struct irq_desc *desc)
-{
-       void __iomem *reg = (void *)irq_get_handler_data(irq);
-       unsigned int evtcodeas = ioread32(reg);
-
-       generic_handle_irq(intcs_evt2irq(evtcodeas));
-}
-
-static void __iomem *intcs_ffd2;
-static void __iomem *intcs_ffd5;
-
-void __init sh7372_init_irq(void)
-{
-       void __iomem *intevtsa;
-       int n;
-
-       intcs_ffd2 = ioremap_nocache(0xffd20000, PAGE_SIZE);
-       intevtsa = intcs_ffd2 + 0x100;
-       intcs_ffd5 = ioremap_nocache(0xffd50000, PAGE_SIZE);
-
-       register_intc_controller(&intca_desc);
-       register_intc_controller(&intca_irq_pins_lo_desc);
-       register_intc_controller(&intca_irq_pins_hi_desc);
-       register_intc_controller(&intcs_desc);
-
-       /* setup dummy cascade chip for INTCS */
-       n = evt2irq(0xf80);
-       irq_alloc_desc_at(n, numa_node_id());
-       irq_set_chip_and_handler_name(n, &dummy_irq_chip,
-                                     handle_level_irq, "level");
-       set_irq_flags(n, IRQF_VALID); /* yuck */
-
-       /* demux using INTEVTSA */
-       irq_set_handler_data(n, (void *)intevtsa);
-       irq_set_chained_handler(n, intcs_demux);
-
-       /* unmask INTCS in INTAMASK */
-       iowrite16(0, intcs_ffd2 + 0x104);
-}
-
-static unsigned short ffd2[0x200];
-static unsigned short ffd5[0x100];
-
-void sh7372_intcs_suspend(void)
-{
-       int k;
-
-       for (k = 0x00; k <= 0x30; k += 4)
-               ffd2[k] = __raw_readw(intcs_ffd2 + k);
-
-       for (k = 0x80; k <= 0xb0; k += 4)
-               ffd2[k] = __raw_readb(intcs_ffd2 + k);
-
-       for (k = 0x180; k <= 0x188; k += 4)
-               ffd2[k] = __raw_readb(intcs_ffd2 + k);
-
-       for (k = 0x00; k <= 0x3c; k += 4)
-               ffd5[k] = __raw_readw(intcs_ffd5 + k);
-
-       for (k = 0x80; k <= 0x9c; k += 4)
-               ffd5[k] = __raw_readb(intcs_ffd5 + k);
-}
-
-void sh7372_intcs_resume(void)
-{
-       int k;
-
-       for (k = 0x00; k <= 0x30; k += 4)
-               __raw_writew(ffd2[k], intcs_ffd2 + k);
-
-       for (k = 0x80; k <= 0xb0; k += 4)
-               __raw_writeb(ffd2[k], intcs_ffd2 + k);
-
-       for (k = 0x180; k <= 0x188; k += 4)
-               __raw_writeb(ffd2[k], intcs_ffd2 + k);
-
-       for (k = 0x00; k <= 0x3c; k += 4)
-               __raw_writew(ffd5[k], intcs_ffd5 + k);
-
-       for (k = 0x80; k <= 0x9c; k += 4)
-               __raw_writeb(ffd5[k], intcs_ffd5 + k);
-}
-
-#define E694_BASE IOMEM(0xe6940000)
-#define E695_BASE IOMEM(0xe6950000)
-
-static unsigned short e694[0x200];
-static unsigned short e695[0x200];
-
-void sh7372_intca_suspend(void)
-{
-       int k;
-
-       for (k = 0x00; k <= 0x38; k += 4)
-               e694[k] = __raw_readw(E694_BASE + k);
-
-       for (k = 0x80; k <= 0xb4; k += 4)
-               e694[k] = __raw_readb(E694_BASE + k);
-
-       for (k = 0x180; k <= 0x1b4; k += 4)
-               e694[k] = __raw_readb(E694_BASE + k);
-
-       for (k = 0x00; k <= 0x50; k += 4)
-               e695[k] = __raw_readw(E695_BASE + k);
-
-       for (k = 0x80; k <= 0xa8; k += 4)
-               e695[k] = __raw_readb(E695_BASE + k);
-
-       for (k = 0x180; k <= 0x1a8; k += 4)
-               e695[k] = __raw_readb(E695_BASE + k);
-}
-
-void sh7372_intca_resume(void)
-{
-       int k;
-
-       for (k = 0x00; k <= 0x38; k += 4)
-               __raw_writew(e694[k], E694_BASE + k);
-
-       for (k = 0x80; k <= 0xb4; k += 4)
-               __raw_writeb(e694[k], E694_BASE + k);
-
-       for (k = 0x180; k <= 0x1b4; k += 4)
-               __raw_writeb(e694[k], E694_BASE + k);
-
-       for (k = 0x00; k <= 0x50; k += 4)
-               __raw_writew(e695[k], E695_BASE + k);
-
-       for (k = 0x80; k <= 0xa8; k += 4)
-               __raw_writeb(e695[k], E695_BASE + k);
-
-       for (k = 0x180; k <= 0x1a8; k += 4)
-               __raw_writeb(e695[k], E695_BASE + k);
-}
diff --git a/arch/arm/mach-shmobile/pm-r8a7790.c b/arch/arm/mach-shmobile/pm-r8a7790.c
deleted file mode 100644 (file)
index 80e8d95..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * r8a7790 Power management support
- *
- * Copyright (C) 2013  Renesas Electronics Corporation
- * 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/kernel.h>
-#include <linux/smp.h>
-#include <asm/io.h>
-#include "common.h"
-#include "pm-rcar.h"
-#include "r8a7790.h"
-
-/* RST */
-#define RST            0xe6160000
-#define CA15BAR                0x0020
-#define CA7BAR         0x0030
-#define CA15RESCNT     0x0040
-#define CA7RESCNT      0x0044
-
-/* On-chip RAM */
-#define MERAM          0xe8080000
-
-/* SYSC */
-#define SYSCIER 0x0c
-#define SYSCIMR 0x10
-
-#if defined(CONFIG_SMP)
-
-static void __init r8a7790_sysc_init(void)
-{
-       void __iomem *base = rcar_sysc_init(0xe6180000);
-
-       /* enable all interrupt sources, but do not use interrupt handler */
-       iowrite32(0x0131000e, base + SYSCIER);
-       iowrite32(0, base + SYSCIMR);
-}
-
-#else /* CONFIG_SMP */
-
-static inline void r8a7790_sysc_init(void) {}
-
-#endif /* CONFIG_SMP */
-
-void __init r8a7790_pm_init(void)
-{
-       void __iomem *p;
-       u32 bar;
-       static int once;
-
-       if (once++)
-               return;
-
-       /* MERAM for jump stub, because BAR requires 256KB aligned address */
-       p = ioremap_nocache(MERAM, shmobile_boot_size);
-       memcpy_toio(p, shmobile_boot_vector, shmobile_boot_size);
-       iounmap(p);
-
-       /* setup reset vectors */
-       p = ioremap_nocache(RST, 0x63);
-       bar = (MERAM >> 8) & 0xfffffc00;
-       writel_relaxed(bar, p + CA15BAR);
-       writel_relaxed(bar, p + CA7BAR);
-       writel_relaxed(bar | 0x10, p + CA15BAR);
-       writel_relaxed(bar | 0x10, p + CA7BAR);
-
-       /* de-assert reset for all CPUs */
-       writel_relaxed((readl_relaxed(p + CA15RESCNT) & ~0x0f) | 0xa5a50000,
-                      p + CA15RESCNT);
-       writel_relaxed((readl_relaxed(p + CA7RESCNT) & ~0x0f) | 0x5a5a0000,
-                      p + CA7RESCNT);
-       iounmap(p);
-
-       r8a7790_sysc_init();
-       shmobile_smp_apmu_suspend_init();
-}
diff --git a/arch/arm/mach-shmobile/pm-r8a7791.c b/arch/arm/mach-shmobile/pm-r8a7791.c
deleted file mode 100644 (file)
index 25f107b..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * r8a7791 Power management support
- *
- * Copyright (C) 2014  Renesas Electronics Corporation
- * 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/kernel.h>
-#include <linux/smp.h>
-#include <asm/io.h>
-#include "common.h"
-#include "pm-rcar.h"
-#include "r8a7791.h"
-
-#define RST            0xe6160000
-#define CA15BAR                0x0020
-#define CA15RESCNT     0x0040
-#define RAM            0xe6300000
-
-/* SYSC */
-#define SYSCIER 0x0c
-#define SYSCIMR 0x10
-
-#if defined(CONFIG_SMP)
-
-static void __init r8a7791_sysc_init(void)
-{
-       void __iomem *base = rcar_sysc_init(0xe6180000);
-
-       /* enable all interrupt sources, but do not use interrupt handler */
-       iowrite32(0x0131000e, base + SYSCIER);
-       iowrite32(0, base + SYSCIMR);
-}
-
-#else /* CONFIG_SMP */
-
-static inline void r8a7791_sysc_init(void) {}
-
-#endif /* CONFIG_SMP */
-
-void __init r8a7791_pm_init(void)
-{
-       void __iomem *p;
-       u32 bar;
-       static int once;
-
-       if (once++)
-               return;
-
-       /* RAM for jump stub, because BAR requires 256KB aligned address */
-       p = ioremap_nocache(RAM, shmobile_boot_size);
-       memcpy_toio(p, shmobile_boot_vector, shmobile_boot_size);
-       iounmap(p);
-
-       /* setup reset vectors */
-       p = ioremap_nocache(RST, 0x63);
-       bar = (RAM >> 8) & 0xfffffc00;
-       writel_relaxed(bar, p + CA15BAR);
-       writel_relaxed(bar | 0x10, p + CA15BAR);
-
-       /* enable clocks to all CPUs */
-       writel_relaxed((readl_relaxed(p + CA15RESCNT) & ~0x0f) | 0xa5a50000,
-                      p + CA15RESCNT);
-       iounmap(p);
-
-       r8a7791_sysc_init();
-       shmobile_smp_apmu_suspend_init();
-}
diff --git a/arch/arm/mach-shmobile/pm-rcar-gen2.c b/arch/arm/mach-shmobile/pm-rcar-gen2.c
new file mode 100644 (file)
index 0000000..6815781
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * R-Car Generation 2 Power management support
+ *
+ * Copyright (C) 2013 - 2015  Renesas Electronics Corporation
+ * 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/kernel.h>
+#include <linux/of.h>
+#include <linux/smp.h>
+#include <asm/io.h>
+#include "common.h"
+#include "pm-rcar.h"
+#include "rcar-gen2.h"
+
+/* RST */
+#define RST            0xe6160000
+#define CA15BAR                0x0020
+#define CA7BAR         0x0030
+#define CA15RESCNT     0x0040
+#define CA7RESCNT      0x0044
+
+/* On-chip RAM */
+#define MERAM          0xe8080000
+#define RAM            0xe6300000
+
+/* SYSC */
+#define SYSCIER 0x0c
+#define SYSCIMR 0x10
+
+#if defined(CONFIG_SMP)
+
+static void __init rcar_gen2_sysc_init(u32 syscier)
+{
+       void __iomem *base = rcar_sysc_init(0xe6180000);
+
+       /* enable all interrupt sources, but do not use interrupt handler */
+       iowrite32(syscier, base + SYSCIER);
+       iowrite32(0, base + SYSCIMR);
+}
+
+#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;
+       u32 bar;
+       static int once;
+       struct device_node *np, *cpus;
+       bool has_a7 = false;
+       bool has_a15 = false;
+       phys_addr_t boot_vector_addr = 0;
+       u32 syscier = 0;
+
+       if (once++)
+               return;
+
+       cpus = of_find_node_by_path("/cpus");
+       if (!cpus)
+               return;
+
+       for_each_child_of_node(cpus, np) {
+               if (of_device_is_compatible(np, "arm,cortex-a15"))
+                       has_a15 = true;
+               else if (of_device_is_compatible(np, "arm,cortex-a7"))
+                       has_a7 = true;
+       }
+
+       if (of_machine_is_compatible("renesas,r8a7790")) {
+               boot_vector_addr = MERAM;
+               syscier = 0x013111ef;
+
+       } else if (of_machine_is_compatible("renesas,r8a7791")) {
+               boot_vector_addr = RAM;
+               syscier = 0x00111003;
+       }
+
+       /* RAM for jump stub, because BAR requires 256KB aligned address */
+       p = ioremap_nocache(boot_vector_addr, shmobile_boot_size);
+       memcpy_toio(p, shmobile_boot_vector, shmobile_boot_size);
+       iounmap(p);
+
+       /* setup reset vectors */
+       p = ioremap_nocache(RST, 0x63);
+       bar = (boot_vector_addr >> 8) & 0xfffffc00;
+       if (has_a15) {
+               writel_relaxed(bar, p + CA15BAR);
+               writel_relaxed(bar | 0x10, p + CA15BAR);
+
+               /* de-assert reset for CA15 CPUs */
+               writel_relaxed((readl_relaxed(p + CA15RESCNT) & ~0x0f) |
+                               0xa5a50000, p + CA15RESCNT);
+       }
+       if (has_a7) {
+               writel_relaxed(bar, p + CA7BAR);
+               writel_relaxed(bar | 0x10, p + CA7BAR);
+
+               /* de-assert reset for CA7 CPUs */
+               writel_relaxed((readl_relaxed(p + CA7RESCNT) & ~0x0f) |
+                               0x5a5a0000, p + CA7RESCNT);
+       }
+       iounmap(p);
+
+       rcar_gen2_sysc_init(syscier);
+       shmobile_smp_apmu_suspend_init();
+}
diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c
deleted file mode 100644 (file)
index c0293ae..0000000
+++ /dev/null
@@ -1,549 +0,0 @@
-/*
- * sh7372 Power management support
- *
- *  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/pm.h>
-#include <linux/suspend.h>
-#include <linux/cpuidle.h>
-#include <linux/module.h>
-#include <linux/list.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/pm_clock.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/irq.h>
-#include <linux/bitrev.h>
-#include <linux/console.h>
-
-#include <asm/cpuidle.h>
-#include <asm/io.h>
-#include <asm/tlbflush.h>
-#include <asm/suspend.h>
-
-#include "common.h"
-#include "pm-rmobile.h"
-#include "sh7372.h"
-
-/* DBG */
-#define DBGREG1 IOMEM(0xe6100020)
-#define DBGREG9 IOMEM(0xe6100040)
-
-/* CPGA */
-#define SYSTBCR IOMEM(0xe6150024)
-#define MSTPSR0 IOMEM(0xe6150030)
-#define MSTPSR1 IOMEM(0xe6150038)
-#define MSTPSR2 IOMEM(0xe6150040)
-#define MSTPSR3 IOMEM(0xe6150048)
-#define MSTPSR4 IOMEM(0xe615004c)
-#define PLLC01STPCR IOMEM(0xe61500c8)
-
-/* SYSC */
-#define SYSC_BASE IOMEM(0xe6180000)
-
-#define SBAR IOMEM(0xe6180020)
-#define WUPRMSK IOMEM(0xe6180028)
-#define WUPSMSK IOMEM(0xe618002c)
-#define WUPSMSK2 IOMEM(0xe6180048)
-#define WUPSFAC IOMEM(0xe6180098)
-#define IRQCR IOMEM(0xe618022c)
-#define IRQCR2 IOMEM(0xe6180238)
-#define IRQCR3 IOMEM(0xe6180244)
-#define IRQCR4 IOMEM(0xe6180248)
-#define PDNSEL IOMEM(0xe6180254)
-
-/* INTC */
-#define ICR1A IOMEM(0xe6900000)
-#define ICR2A IOMEM(0xe6900004)
-#define ICR3A IOMEM(0xe6900008)
-#define ICR4A IOMEM(0xe690000c)
-#define INTMSK00A IOMEM(0xe6900040)
-#define INTMSK10A IOMEM(0xe6900044)
-#define INTMSK20A IOMEM(0xe6900048)
-#define INTMSK30A IOMEM(0xe690004c)
-
-/* MFIS */
-/* FIXME: pointing where? */
-#define SMFRAM 0xe6a70000
-
-/* AP-System Core */
-#define APARMBAREA IOMEM(0xe6f10020)
-
-#ifdef CONFIG_PM
-
-#define PM_DOMAIN_ON_OFF_LATENCY_NS    250000
-
-static int sh7372_a4r_pd_suspend(void)
-{
-       sh7372_intcs_suspend();
-       __raw_writel(0x300fffff, WUPRMSK); /* avoid wakeup */
-       return 0;
-}
-
-static bool a4s_suspend_ready;
-
-static int sh7372_a4s_pd_suspend(void)
-{
-       /*
-        * The A4S domain contains the CPU core and therefore it should
-        * only be turned off if the CPU is not in use.  This may happen
-        * during system suspend, when SYSC is going to be used for generating
-        * resume signals and a4s_suspend_ready is set to let
-        * sh7372_enter_suspend() know that it can turn A4S off.
-        */
-       a4s_suspend_ready = true;
-       return -EBUSY;
-}
-
-static void sh7372_a4s_pd_resume(void)
-{
-       a4s_suspend_ready = false;
-}
-
-static int sh7372_a3sp_pd_suspend(void)
-{
-       /*
-        * Serial consoles make use of SCIF hardware located in A3SP,
-        * keep such power domain on if "no_console_suspend" is set.
-        */
-       return console_suspend_enabled ? 0 : -EBUSY;
-}
-
-static struct rmobile_pm_domain sh7372_pm_domains[] = {
-       {
-               .genpd.name = "A4LC",
-               .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
-               .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
-               .base = SYSC_BASE,
-               .bit_shift = 1,
-       },
-       {
-               .genpd.name = "A4MP",
-               .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
-               .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
-               .base = SYSC_BASE,
-               .bit_shift = 2,
-       },
-       {
-               .genpd.name = "D4",
-               .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
-               .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
-               .base = SYSC_BASE,
-               .bit_shift = 3,
-       },
-       {
-               .genpd.name = "A4R",
-               .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
-               .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
-               .base = SYSC_BASE,
-               .bit_shift = 5,
-               .suspend = sh7372_a4r_pd_suspend,
-               .resume = sh7372_intcs_resume,
-       },
-       {
-               .genpd.name = "A3RV",
-               .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
-               .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
-               .base = SYSC_BASE,
-               .bit_shift = 6,
-       },
-       {
-               .genpd.name = "A3RI",
-               .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
-               .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
-               .base = SYSC_BASE,
-               .bit_shift = 8,
-       },
-       {
-               .genpd.name = "A4S",
-               .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
-               .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
-               .base = SYSC_BASE,
-               .bit_shift = 10,
-               .gov = &pm_domain_always_on_gov,
-               .no_debug = true,
-               .suspend = sh7372_a4s_pd_suspend,
-               .resume = sh7372_a4s_pd_resume,
-       },
-       {
-               .genpd.name = "A3SP",
-               .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
-               .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
-               .base = SYSC_BASE,
-               .bit_shift = 11,
-               .gov = &pm_domain_always_on_gov,
-               .no_debug = true,
-               .suspend = sh7372_a3sp_pd_suspend,
-       },
-       {
-               .genpd.name = "A3SG",
-               .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
-               .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
-               .base = SYSC_BASE,
-               .bit_shift = 13,
-       },
-};
-
-void __init sh7372_init_pm_domains(void)
-{
-       rmobile_init_domains(sh7372_pm_domains, ARRAY_SIZE(sh7372_pm_domains));
-       pm_genpd_add_subdomain_names("A4LC", "A3RV");
-       pm_genpd_add_subdomain_names("A4R", "A4LC");
-       pm_genpd_add_subdomain_names("A4S", "A3SG");
-       pm_genpd_add_subdomain_names("A4S", "A3SP");
-}
-
-#endif /* CONFIG_PM */
-
-#if defined(CONFIG_SUSPEND) || defined(CONFIG_CPU_IDLE)
-static void sh7372_set_reset_vector(unsigned long address)
-{
-       /* set reset vector, translate 4k */
-       __raw_writel(address, SBAR);
-       __raw_writel(0, APARMBAREA);
-}
-
-static void sh7372_enter_sysc(int pllc0_on, unsigned long sleep_mode)
-{
-       if (pllc0_on)
-               __raw_writel(0, PLLC01STPCR);
-       else
-               __raw_writel(1 << 28, PLLC01STPCR);
-
-       __raw_readl(WUPSFAC); /* read wakeup int. factor before sleep */
-       cpu_suspend(sleep_mode, sh7372_do_idle_sysc);
-       __raw_readl(WUPSFAC); /* read wakeup int. factor after wakeup */
-
-        /* disable reset vector translation */
-       __raw_writel(0, SBAR);
-}
-
-static int sh7372_sysc_valid(unsigned long *mskp, unsigned long *msk2p)
-{
-       unsigned long mstpsr0, mstpsr1, mstpsr2, mstpsr3, mstpsr4;
-       unsigned long msk, msk2;
-
-       /* check active clocks to determine potential wakeup sources */
-
-       mstpsr0 = __raw_readl(MSTPSR0);
-       if ((mstpsr0 & 0x00000003) != 0x00000003) {
-               pr_debug("sh7372 mstpsr0 0x%08lx\n", mstpsr0);
-               return 0;
-       }
-
-       mstpsr1 = __raw_readl(MSTPSR1);
-       if ((mstpsr1 & 0xff079b7f) != 0xff079b7f) {
-               pr_debug("sh7372 mstpsr1 0x%08lx\n", mstpsr1);
-               return 0;
-       }
-
-       mstpsr2 = __raw_readl(MSTPSR2);
-       if ((mstpsr2 & 0x000741ff) != 0x000741ff) {
-               pr_debug("sh7372 mstpsr2 0x%08lx\n", mstpsr2);
-               return 0;
-       }
-
-       mstpsr3 = __raw_readl(MSTPSR3);
-       if ((mstpsr3 & 0x1a60f010) != 0x1a60f010) {
-               pr_debug("sh7372 mstpsr3 0x%08lx\n", mstpsr3);
-               return 0;
-       }
-
-       mstpsr4 = __raw_readl(MSTPSR4);
-       if ((mstpsr4 & 0x00008cf0) != 0x00008cf0) {
-               pr_debug("sh7372 mstpsr4 0x%08lx\n", mstpsr4);
-               return 0;
-       }
-
-       msk = 0;
-       msk2 = 0;
-
-       /* make bitmaps of limited number of wakeup sources */
-
-       if ((mstpsr2 & (1 << 23)) == 0) /* SPU2 */
-               msk |= 1 << 31;
-
-       if ((mstpsr2 & (1 << 12)) == 0) /* MFI_MFIM */
-               msk |= 1 << 21;
-
-       if ((mstpsr4 & (1 << 3)) == 0) /* KEYSC */
-               msk |= 1 << 2;
-
-       if ((mstpsr1 & (1 << 24)) == 0) /* CMT0 */
-               msk |= 1 << 1;
-
-       if ((mstpsr3 & (1 << 29)) == 0) /* CMT1 */
-               msk |= 1 << 1;
-
-       if ((mstpsr4 & (1 << 0)) == 0) /* CMT2 */
-               msk |= 1 << 1;
-
-       if ((mstpsr2 & (1 << 13)) == 0) /* MFI_MFIS */
-               msk2 |= 1 << 17;
-
-       *mskp = msk;
-       *msk2p = msk2;
-
-       return 1;
-}
-
-static void sh7372_icr_to_irqcr(unsigned long icr, u16 *irqcr1p, u16 *irqcr2p)
-{
-       u16 tmp, irqcr1, irqcr2;
-       int k;
-
-       irqcr1 = 0;
-       irqcr2 = 0;
-
-       /* convert INTCA ICR register layout to SYSC IRQCR+IRQCR2 */
-       for (k = 0; k <= 7; k++) {
-               tmp = (icr >> ((7 - k) * 4)) & 0xf;
-               irqcr1 |= (tmp & 0x03) << (k * 2);
-               irqcr2 |= (tmp >> 2) << (k * 2);
-       }
-
-       *irqcr1p = irqcr1;
-       *irqcr2p = irqcr2;
-}
-
-static void sh7372_setup_sysc(unsigned long msk, unsigned long msk2)
-{
-       u16 irqcrx_low, irqcrx_high, irqcry_low, irqcry_high;
-       unsigned long tmp;
-
-       /* read IRQ0A -> IRQ15A mask */
-       tmp = bitrev8(__raw_readb(INTMSK00A));
-       tmp |= bitrev8(__raw_readb(INTMSK10A)) << 8;
-
-       /* setup WUPSMSK from clocks and external IRQ mask */
-       msk = (~msk & 0xc030000f) | (tmp << 4);
-       __raw_writel(msk, WUPSMSK);
-
-       /* propage level/edge trigger for external IRQ 0->15 */
-       sh7372_icr_to_irqcr(__raw_readl(ICR1A), &irqcrx_low, &irqcry_low);
-       sh7372_icr_to_irqcr(__raw_readl(ICR2A), &irqcrx_high, &irqcry_high);
-       __raw_writel((irqcrx_high << 16) | irqcrx_low, IRQCR);
-       __raw_writel((irqcry_high << 16) | irqcry_low, IRQCR2);
-
-       /* read IRQ16A -> IRQ31A mask */
-       tmp = bitrev8(__raw_readb(INTMSK20A));
-       tmp |= bitrev8(__raw_readb(INTMSK30A)) << 8;
-
-       /* setup WUPSMSK2 from clocks and external IRQ mask */
-       msk2 = (~msk2 & 0x00030000) | tmp;
-       __raw_writel(msk2, WUPSMSK2);
-
-       /* propage level/edge trigger for external IRQ 16->31 */
-       sh7372_icr_to_irqcr(__raw_readl(ICR3A), &irqcrx_low, &irqcry_low);
-       sh7372_icr_to_irqcr(__raw_readl(ICR4A), &irqcrx_high, &irqcry_high);
-       __raw_writel((irqcrx_high << 16) | irqcrx_low, IRQCR3);
-       __raw_writel((irqcry_high << 16) | irqcry_low, IRQCR4);
-}
-
-static void sh7372_enter_a3sm_common(int pllc0_on)
-{
-       /* use INTCA together with SYSC for wakeup */
-       sh7372_setup_sysc(1 << 0, 0);
-       sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc));
-       sh7372_enter_sysc(pllc0_on, 1 << 12);
-}
-
-static void sh7372_enter_a4s_common(int pllc0_on)
-{
-       sh7372_intca_suspend();
-       sh7372_set_reset_vector(SMFRAM);
-       sh7372_enter_sysc(pllc0_on, 1 << 10);
-       sh7372_intca_resume();
-}
-
-static void sh7372_pm_setup_smfram(void)
-{
-       /* pass physical address of cpu_resume() to assembly resume code */
-       sh7372_cpu_resume = virt_to_phys(cpu_resume);
-
-       memcpy((void *)SMFRAM, sh7372_resume_core_standby_sysc, 0x100);
-}
-#else
-static inline void sh7372_pm_setup_smfram(void) {}
-#endif /* CONFIG_SUSPEND || CONFIG_CPU_IDLE */
-
-#ifdef CONFIG_CPU_IDLE
-static int sh7372_do_idle_core_standby(unsigned long unused)
-{
-       cpu_do_idle(); /* WFI when SYSTBCR == 0x10 -> Core Standby */
-       return 0;
-}
-
-static int sh7372_enter_core_standby(struct cpuidle_device *dev,
-                                    struct cpuidle_driver *drv, int index)
-{
-       sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc));
-
-       /* enter sleep mode with SYSTBCR to 0x10 */
-       __raw_writel(0x10, SYSTBCR);
-       cpu_suspend(0, sh7372_do_idle_core_standby);
-       __raw_writel(0, SYSTBCR);
-
-        /* disable reset vector translation */
-       __raw_writel(0, SBAR);
-
-       return 1;
-}
-
-static int sh7372_enter_a3sm_pll_on(struct cpuidle_device *dev,
-                                   struct cpuidle_driver *drv, int index)
-{
-       sh7372_enter_a3sm_common(1);
-       return 2;
-}
-
-static int sh7372_enter_a3sm_pll_off(struct cpuidle_device *dev,
-                                    struct cpuidle_driver *drv, int index)
-{
-       sh7372_enter_a3sm_common(0);
-       return 3;
-}
-
-static int sh7372_enter_a4s(struct cpuidle_device *dev,
-                           struct cpuidle_driver *drv, int index)
-{
-       unsigned long msk, msk2;
-
-       if (!sh7372_sysc_valid(&msk, &msk2))
-               return sh7372_enter_a3sm_pll_off(dev, drv, index);
-
-       sh7372_setup_sysc(msk, msk2);
-       sh7372_enter_a4s_common(0);
-       return 4;
-}
-
-static struct cpuidle_driver sh7372_cpuidle_driver = {
-       .name                   = "sh7372_cpuidle",
-       .owner                  = THIS_MODULE,
-       .state_count            = 5,
-       .safe_state_index       = 0, /* C1 */
-       .states[0] = ARM_CPUIDLE_WFI_STATE,
-       .states[1] = {
-               .name = "C2",
-               .desc = "Core Standby Mode",
-               .exit_latency = 10,
-               .target_residency = 20 + 10,
-               .enter = sh7372_enter_core_standby,
-       },
-       .states[2] = {
-               .name = "C3",
-               .desc = "A3SM PLL ON",
-               .exit_latency = 20,
-               .target_residency = 30 + 20,
-               .enter = sh7372_enter_a3sm_pll_on,
-       },
-       .states[3] = {
-               .name = "C4",
-               .desc = "A3SM PLL OFF",
-               .exit_latency = 120,
-               .target_residency = 30 + 120,
-               .enter = sh7372_enter_a3sm_pll_off,
-       },
-       .states[4] = {
-               .name = "C5",
-               .desc = "A4S PLL OFF",
-               .exit_latency = 240,
-               .target_residency = 30 + 240,
-               .enter = sh7372_enter_a4s,
-               .disabled = true,
-       },
-};
-
-static void __init sh7372_cpuidle_init(void)
-{
-       shmobile_cpuidle_set_driver(&sh7372_cpuidle_driver);
-}
-#else
-static void __init sh7372_cpuidle_init(void) {}
-#endif
-
-#ifdef CONFIG_SUSPEND
-static int sh7372_enter_suspend(suspend_state_t suspend_state)
-{
-       unsigned long msk, msk2;
-
-       /* check active clocks to determine potential wakeup sources */
-       if (sh7372_sysc_valid(&msk, &msk2) && a4s_suspend_ready) {
-               /* convert INTC mask/sense to SYSC mask/sense */
-               sh7372_setup_sysc(msk, msk2);
-
-               /* enter A4S sleep with PLLC0 off */
-               pr_debug("entering A4S\n");
-               sh7372_enter_a4s_common(0);
-               return 0;
-       }
-
-       /* default to enter A3SM sleep with PLLC0 off */
-       pr_debug("entering A3SM\n");
-       sh7372_enter_a3sm_common(0);
-       return 0;
-}
-
-/**
- * sh7372_pm_notifier_fn - SH7372 PM notifier routine.
- * @notifier: Unused.
- * @pm_event: Event being handled.
- * @unused: Unused.
- */
-static int sh7372_pm_notifier_fn(struct notifier_block *notifier,
-                                unsigned long pm_event, void *unused)
-{
-       switch (pm_event) {
-       case PM_SUSPEND_PREPARE:
-               /*
-                * This is necessary, because the A4R domain has to be "on"
-                * when suspend_device_irqs() and resume_device_irqs() are
-                * executed during system suspend and resume, respectively, so
-                * that those functions don't crash while accessing the INTCS.
-                */
-               pm_genpd_name_poweron("A4R");
-               break;
-       case PM_POST_SUSPEND:
-               pm_genpd_poweroff_unused();
-               break;
-       }
-
-       return NOTIFY_DONE;
-}
-
-static void sh7372_suspend_init(void)
-{
-       shmobile_suspend_ops.enter = sh7372_enter_suspend;
-       pm_notifier(sh7372_pm_notifier_fn, 0);
-}
-#else
-static void sh7372_suspend_init(void) {}
-#endif
-
-void __init sh7372_pm_init(void)
-{
-       /* enable DBG hardware block to kick SYSC */
-       __raw_writel(0x0000a500, DBGREG9);
-       __raw_writel(0x0000a501, DBGREG9);
-       __raw_writel(0x00000000, DBGREG1);
-
-       /* do not convert A3SM, A3SP, A3SG, A4R power down into A4S */
-       __raw_writel(0, PDNSEL);
-
-       sh7372_pm_setup_smfram();
-
-       sh7372_suspend_init();
-       sh7372_cpuidle_init();
-}
-
-void __init sh7372_pm_init_late(void)
-{
-       shmobile_init_late();
-       pm_genpd_name_attach_cpuidle("A4S", 4);
-}
diff --git a/arch/arm/mach-shmobile/r8a73a4.h b/arch/arm/mach-shmobile/r8a73a4.h
deleted file mode 100644 (file)
index 70dcd84..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef __ASM_R8A73A4_H__
-#define __ASM_R8A73A4_H__
-
-/* DMA slave IDs */
-enum {
-       SHDMA_SLAVE_INVALID,
-       SHDMA_SLAVE_MMCIF0_TX,
-       SHDMA_SLAVE_MMCIF0_RX,
-       SHDMA_SLAVE_MMCIF1_TX,
-       SHDMA_SLAVE_MMCIF1_RX,
-};
-
-void r8a73a4_add_standard_devices(void);
-void r8a73a4_clock_init(void);
-void r8a73a4_pinmux_init(void);
-
-#endif /* __ASM_R8A73A4_H__ */
index bf73a850aaede0152fac083e82793d1fb2aa8bf3..1a46d026052c012a4e52967a7c49bec27a64f604 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_R8A7790_H__
 #define __ASM_R8A7790_H__
 
-void r8a7790_pm_init(void);
 extern struct smp_operations r8a7790_smp_ops;
 
 #endif /* __ASM_R8A7790_H__ */
index 6cf11eb69d10a4aee5ffea9700a0592fe971b766..7ca0b7d0f59bac6595ddeb8f817aa58ea695f476 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_R8A7791_H__
 #define __ASM_R8A7791_H__
 
-void r8a7791_pm_init(void);
 extern struct smp_operations r8a7791_smp_ops;
 
 #endif /* __ASM_R8A7791_H__ */
index ce53cb5f53a12af7da12472bc5fef0a3ef355170..8a66b4aae03548ce797a946820acd736a4172601 100644 (file)
@@ -5,5 +5,6 @@ void rcar_gen2_timer_init(void);
 #define MD(nr) BIT(nr)
 u32 rcar_gen2_read_mode_pins(void);
 void rcar_gen2_reserve(void);
+void rcar_gen2_pm_init(void);
 
 #endif /* __ASM_RCAR_GEN2_H__ */
diff --git a/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c b/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c
new file mode 100644 (file)
index 0000000..384e6e9
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * R-Car Generation 2 da9063/da9210 regulator quirk
+ *
+ * The r8a7790/lager and r8a7791/koelsch development boards have da9063 and
+ * da9210 regulators.  Both regulators have their interrupt request lines tied
+ * to the same interrupt pin (IRQ2) on the SoC.
+ *
+ * After cold boot or da9063-induced restart, both the da9063 and da9210 seem
+ * to assert their interrupt request lines.  Hence as soon as one driver
+ * requests this irq, it gets stuck in an interrupt storm, as it only manages
+ * to deassert its own interrupt request line, and the other driver hasn't
+ * installed an interrupt handler yet.
+ *
+ * To handle this, install a quirk that masks the interrupts in both the
+ * da9063 and da9210.  This quirk has to run after the i2c master driver has
+ * 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>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/notifier.h>
+#include <linux/of.h>
+#include <linux/mfd/da9063/registers.h>
+
+
+#define IRQC_BASE              0xe61c0000
+#define IRQC_MONITOR           0x104   /* IRQn Signal Level Monitor Register */
+
+#define REGULATOR_IRQ_MASK     BIT(2)  /* IRQ2, active low */
+
+static void __iomem *irqc;
+
+static const u8 da9063_mask_regs[] = {
+       DA9063_REG_IRQ_MASK_A,
+       DA9063_REG_IRQ_MASK_B,
+       DA9063_REG_IRQ_MASK_C,
+       DA9063_REG_IRQ_MASK_D,
+};
+
+/* DA9210 System Control and Event Registers */
+#define DA9210_REG_MASK_A              0x54
+#define DA9210_REG_MASK_B              0x55
+
+static const u8 da9210_mask_regs[] = {
+       DA9210_REG_MASK_A,
+       DA9210_REG_MASK_B,
+};
+
+static void da9xxx_mask_irqs(struct i2c_client *client, const u8 regs[],
+                            unsigned int nregs)
+{
+       unsigned int i;
+
+       dev_info(&client->dev, "Masking %s interrupt sources\n", client->name);
+
+       for (i = 0; i < nregs; i++) {
+               int error = i2c_smbus_write_byte_data(client, regs[i], ~0);
+               if (error) {
+                       dev_err(&client->dev, "i2c error %d\n", error);
+                       return;
+               }
+       }
+}
+
+static int regulator_quirk_notify(struct notifier_block *nb,
+                                 unsigned long action, void *data)
+{
+       struct device *dev = data;
+       struct i2c_client *client;
+       u32 mon;
+
+       mon = ioread32(irqc + IRQC_MONITOR);
+       dev_dbg(dev, "%s: %ld, IRQC_MONITOR = 0x%x\n", __func__, action, mon);
+       if (mon & REGULATOR_IRQ_MASK)
+               goto remove;
+
+       if (action != BUS_NOTIFY_ADD_DEVICE || dev->type == &i2c_adapter_type)
+               return 0;
+
+       client = to_i2c_client(dev);
+       dev_dbg(dev, "Detected %s\n", client->name);
+
+       if ((client->addr == 0x58 && !strcmp(client->name, "da9063")))
+               da9xxx_mask_irqs(client, da9063_mask_regs,
+                                ARRAY_SIZE(da9063_mask_regs));
+       else if (client->addr == 0x68 && !strcmp(client->name, "da9210"))
+               da9xxx_mask_irqs(client, da9210_mask_regs,
+                                ARRAY_SIZE(da9210_mask_regs));
+
+       mon = ioread32(irqc + IRQC_MONITOR);
+       if (mon & REGULATOR_IRQ_MASK)
+               goto remove;
+
+       return 0;
+
+remove:
+       dev_info(dev, "IRQ2 is not asserted, removing quirk\n");
+
+       bus_unregister_notifier(&i2c_bus_type, nb);
+       iounmap(irqc);
+       return 0;
+}
+
+static struct notifier_block regulator_quirk_nb = {
+       .notifier_call = regulator_quirk_notify
+};
+
+static int __init rcar_gen2_regulator_quirk(void)
+{
+       u32 mon;
+
+       if (!of_machine_is_compatible("renesas,koelsch") &&
+           !of_machine_is_compatible("renesas,lager"))
+               return -ENODEV;
+
+       irqc = ioremap(IRQC_BASE, PAGE_SIZE);
+       if (!irqc)
+               return -ENOMEM;
+
+       mon = ioread32(irqc + IRQC_MONITOR);
+       if (mon & REGULATOR_IRQ_MASK) {
+               pr_debug("%s: IRQ2 is not asserted, not installing quirk\n",
+                        __func__);
+               iounmap(irqc);
+               return 0;
+       }
+
+       pr_info("IRQ2 is asserted, installing da9063/da9210 regulator quirk\n");
+
+       bus_register_notifier(&i2c_bus_type, &regulator_quirk_nb);
+       return 0;
+}
+
+arch_initcall(rcar_gen2_regulator_quirk);
index c27682291cbf032c5d02f88495af7af150575cdd..446cee6119026f209b629e705c815dae26bee534 100644 (file)
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/of_platform.h>
-#include <linux/platform_data/irq-renesas-irqc.h>
-#include <linux/serial_sci.h>
-#include <linux/sh_dma.h>
-#include <linux/sh_timer.h>
+
+#include <linux/init.h>
 
 #include <asm/mach/arch.h>
 
 #include "common.h"
-#include "dma-register.h"
-#include "irqs.h"
-#include "r8a73a4.h"
-
-static const struct resource pfc_resources[] = {
-       DEFINE_RES_MEM(0xe6050000, 0x9000),
-};
-
-void __init r8a73a4_pinmux_init(void)
-{
-       platform_device_register_simple("pfc-r8a73a4", -1, pfc_resources,
-                                       ARRAY_SIZE(pfc_resources));
-}
-
-#define R8A73A4_SCIF(scif_type, _scscr, index, baseaddr, irq)  \
-static struct plat_sci_port scif##index##_platform_data = {    \
-       .type           = scif_type,                            \
-       .flags          = UPF_BOOT_AUTOCONF | UPF_IOREMAP,      \
-       .scscr          = _scscr,                               \
-};                                                             \
-                                                               \
-static struct resource scif##index##_resources[] = {           \
-       DEFINE_RES_MEM(baseaddr, 0x100),                        \
-       DEFINE_RES_IRQ(irq),                                    \
-}
-
-#define R8A73A4_SCIFA(index, baseaddr, irq)    \
-       R8A73A4_SCIF(PORT_SCIFA, SCSCR_RE | SCSCR_TE | SCSCR_CKE0, \
-                    index, baseaddr, irq)
-
-#define R8A73A4_SCIFB(index, baseaddr, irq)    \
-       R8A73A4_SCIF(PORT_SCIFB, SCSCR_RE | SCSCR_TE, \
-                    index, baseaddr, irq)
-
-R8A73A4_SCIFA(0, 0xe6c40000, gic_spi(144)); /* SCIFA0 */
-R8A73A4_SCIFA(1, 0xe6c50000, gic_spi(145)); /* SCIFA1 */
-R8A73A4_SCIFB(2, 0xe6c20000, gic_spi(148)); /* SCIFB0 */
-R8A73A4_SCIFB(3, 0xe6c30000, gic_spi(149)); /* SCIFB1 */
-R8A73A4_SCIFB(4, 0xe6ce0000, gic_spi(150)); /* SCIFB2 */
-R8A73A4_SCIFB(5, 0xe6cf0000, gic_spi(151)); /* SCIFB3 */
-
-#define r8a73a4_register_scif(index)                                          \
-       platform_device_register_resndata(NULL, "sh-sci", index,               \
-                                         scif##index##_resources,             \
-                                         ARRAY_SIZE(scif##index##_resources), \
-                                         &scif##index##_platform_data,        \
-                                         sizeof(scif##index##_platform_data))
-
-static const struct renesas_irqc_config irqc0_data = {
-       .irq_base = irq_pin(0), /* IRQ0 -> IRQ31 */
-};
-
-static const struct resource irqc0_resources[] = {
-       DEFINE_RES_MEM(0xe61c0000, 0x200), /* IRQC Event Detector Block_0 */
-       DEFINE_RES_IRQ(gic_spi(0)), /* IRQ0 */
-       DEFINE_RES_IRQ(gic_spi(1)), /* IRQ1 */
-       DEFINE_RES_IRQ(gic_spi(2)), /* IRQ2 */
-       DEFINE_RES_IRQ(gic_spi(3)), /* IRQ3 */
-       DEFINE_RES_IRQ(gic_spi(4)), /* IRQ4 */
-       DEFINE_RES_IRQ(gic_spi(5)), /* IRQ5 */
-       DEFINE_RES_IRQ(gic_spi(6)), /* IRQ6 */
-       DEFINE_RES_IRQ(gic_spi(7)), /* IRQ7 */
-       DEFINE_RES_IRQ(gic_spi(8)), /* IRQ8 */
-       DEFINE_RES_IRQ(gic_spi(9)), /* IRQ9 */
-       DEFINE_RES_IRQ(gic_spi(10)), /* IRQ10 */
-       DEFINE_RES_IRQ(gic_spi(11)), /* IRQ11 */
-       DEFINE_RES_IRQ(gic_spi(12)), /* IRQ12 */
-       DEFINE_RES_IRQ(gic_spi(13)), /* IRQ13 */
-       DEFINE_RES_IRQ(gic_spi(14)), /* IRQ14 */
-       DEFINE_RES_IRQ(gic_spi(15)), /* IRQ15 */
-       DEFINE_RES_IRQ(gic_spi(16)), /* IRQ16 */
-       DEFINE_RES_IRQ(gic_spi(17)), /* IRQ17 */
-       DEFINE_RES_IRQ(gic_spi(18)), /* IRQ18 */
-       DEFINE_RES_IRQ(gic_spi(19)), /* IRQ19 */
-       DEFINE_RES_IRQ(gic_spi(20)), /* IRQ20 */
-       DEFINE_RES_IRQ(gic_spi(21)), /* IRQ21 */
-       DEFINE_RES_IRQ(gic_spi(22)), /* IRQ22 */
-       DEFINE_RES_IRQ(gic_spi(23)), /* IRQ23 */
-       DEFINE_RES_IRQ(gic_spi(24)), /* IRQ24 */
-       DEFINE_RES_IRQ(gic_spi(25)), /* IRQ25 */
-       DEFINE_RES_IRQ(gic_spi(26)), /* IRQ26 */
-       DEFINE_RES_IRQ(gic_spi(27)), /* IRQ27 */
-       DEFINE_RES_IRQ(gic_spi(28)), /* IRQ28 */
-       DEFINE_RES_IRQ(gic_spi(29)), /* IRQ29 */
-       DEFINE_RES_IRQ(gic_spi(30)), /* IRQ30 */
-       DEFINE_RES_IRQ(gic_spi(31)), /* IRQ31 */
-};
-
-static const struct renesas_irqc_config irqc1_data = {
-       .irq_base = irq_pin(32), /* IRQ32 -> IRQ57 */
-};
-
-static const struct resource irqc1_resources[] = {
-       DEFINE_RES_MEM(0xe61c0200, 0x200), /* IRQC Event Detector Block_1 */
-       DEFINE_RES_IRQ(gic_spi(32)), /* IRQ32 */
-       DEFINE_RES_IRQ(gic_spi(33)), /* IRQ33 */
-       DEFINE_RES_IRQ(gic_spi(34)), /* IRQ34 */
-       DEFINE_RES_IRQ(gic_spi(35)), /* IRQ35 */
-       DEFINE_RES_IRQ(gic_spi(36)), /* IRQ36 */
-       DEFINE_RES_IRQ(gic_spi(37)), /* IRQ37 */
-       DEFINE_RES_IRQ(gic_spi(38)), /* IRQ38 */
-       DEFINE_RES_IRQ(gic_spi(39)), /* IRQ39 */
-       DEFINE_RES_IRQ(gic_spi(40)), /* IRQ40 */
-       DEFINE_RES_IRQ(gic_spi(41)), /* IRQ41 */
-       DEFINE_RES_IRQ(gic_spi(42)), /* IRQ42 */
-       DEFINE_RES_IRQ(gic_spi(43)), /* IRQ43 */
-       DEFINE_RES_IRQ(gic_spi(44)), /* IRQ44 */
-       DEFINE_RES_IRQ(gic_spi(45)), /* IRQ45 */
-       DEFINE_RES_IRQ(gic_spi(46)), /* IRQ46 */
-       DEFINE_RES_IRQ(gic_spi(47)), /* IRQ47 */
-       DEFINE_RES_IRQ(gic_spi(48)), /* IRQ48 */
-       DEFINE_RES_IRQ(gic_spi(49)), /* IRQ49 */
-       DEFINE_RES_IRQ(gic_spi(50)), /* IRQ50 */
-       DEFINE_RES_IRQ(gic_spi(51)), /* IRQ51 */
-       DEFINE_RES_IRQ(gic_spi(52)), /* IRQ52 */
-       DEFINE_RES_IRQ(gic_spi(53)), /* IRQ53 */
-       DEFINE_RES_IRQ(gic_spi(54)), /* IRQ54 */
-       DEFINE_RES_IRQ(gic_spi(55)), /* IRQ55 */
-       DEFINE_RES_IRQ(gic_spi(56)), /* IRQ56 */
-       DEFINE_RES_IRQ(gic_spi(57)), /* IRQ57 */
-};
-
-#define r8a73a4_register_irqc(idx)                                     \
-       platform_device_register_resndata(NULL, "renesas_irqc",         \
-                                         idx, irqc##idx##_resources,   \
-                                         ARRAY_SIZE(irqc##idx##_resources), \
-                                         &irqc##idx##_data,            \
-                                         sizeof(struct renesas_irqc_config))
-
-/* Thermal0 -> Thermal2 */
-static const struct resource thermal0_resources[] = {
-       DEFINE_RES_MEM(0xe61f0000, 0x14),
-       DEFINE_RES_MEM(0xe61f0100, 0x38),
-       DEFINE_RES_MEM(0xe61f0200, 0x38),
-       DEFINE_RES_MEM(0xe61f0300, 0x38),
-       DEFINE_RES_IRQ(gic_spi(69)),
-};
-
-#define r8a73a4_register_thermal()                                     \
-       platform_device_register_simple("rcar_thermal", -1,             \
-                                       thermal0_resources,             \
-                                       ARRAY_SIZE(thermal0_resources))
-
-static struct sh_timer_config cmt1_platform_data = {
-       .channels_mask = 0xff,
-};
-
-static struct resource cmt1_resources[] = {
-       DEFINE_RES_MEM(0xe6130000, 0x1004),
-       DEFINE_RES_IRQ(gic_spi(120)),
-};
-
-#define r8a73a4_register_cmt(idx)                                      \
-       platform_device_register_resndata(NULL, "sh-cmt-48-gen2",       \
-                                         idx, cmt##idx##_resources,    \
-                                         ARRAY_SIZE(cmt##idx##_resources), \
-                                         &cmt##idx##_platform_data,    \
-                                         sizeof(struct sh_timer_config))
-
-/* DMA */
-static const struct sh_dmae_slave_config dma_slaves[] = {
-       {
-               .slave_id       = SHDMA_SLAVE_MMCIF0_TX,
-               .addr           = 0xee200034,
-               .chcr           = CHCR_TX(XMIT_SZ_32BIT),
-               .mid_rid        = 0xd1,
-       }, {
-               .slave_id       = SHDMA_SLAVE_MMCIF0_RX,
-               .addr           = 0xee200034,
-               .chcr           = CHCR_RX(XMIT_SZ_32BIT),
-               .mid_rid        = 0xd2,
-       }, {
-               .slave_id       = SHDMA_SLAVE_MMCIF1_TX,
-               .addr           = 0xee220034,
-               .chcr           = CHCR_TX(XMIT_SZ_32BIT),
-               .mid_rid        = 0xe1,
-       }, {
-               .slave_id       = SHDMA_SLAVE_MMCIF1_RX,
-               .addr           = 0xee220034,
-               .chcr           = CHCR_RX(XMIT_SZ_32BIT),
-               .mid_rid        = 0xe2,
-       },
-};
-
-#define DMAE_CHANNEL(a, b)                             \
-       {                                               \
-               .offset         = (a) - 0x20,           \
-               .dmars          = (a) - 0x20 + 0x40,    \
-               .chclr_bit      = (b),                  \
-               .chclr_offset   = 0x80 - 0x20,          \
-       }
-
-static const struct sh_dmae_channel dma_channels[] = {
-       DMAE_CHANNEL(0x8000, 0),
-       DMAE_CHANNEL(0x8080, 1),
-       DMAE_CHANNEL(0x8100, 2),
-       DMAE_CHANNEL(0x8180, 3),
-       DMAE_CHANNEL(0x8200, 4),
-       DMAE_CHANNEL(0x8280, 5),
-       DMAE_CHANNEL(0x8300, 6),
-       DMAE_CHANNEL(0x8380, 7),
-       DMAE_CHANNEL(0x8400, 8),
-       DMAE_CHANNEL(0x8480, 9),
-       DMAE_CHANNEL(0x8500, 10),
-       DMAE_CHANNEL(0x8580, 11),
-       DMAE_CHANNEL(0x8600, 12),
-       DMAE_CHANNEL(0x8680, 13),
-       DMAE_CHANNEL(0x8700, 14),
-       DMAE_CHANNEL(0x8780, 15),
-       DMAE_CHANNEL(0x8800, 16),
-       DMAE_CHANNEL(0x8880, 17),
-       DMAE_CHANNEL(0x8900, 18),
-       DMAE_CHANNEL(0x8980, 19),
-};
-
-static const struct sh_dmae_pdata dma_pdata = {
-       .slave          = dma_slaves,
-       .slave_num      = ARRAY_SIZE(dma_slaves),
-       .channel        = dma_channels,
-       .channel_num    = ARRAY_SIZE(dma_channels),
-       .ts_low_shift   = TS_LOW_SHIFT,
-       .ts_low_mask    = TS_LOW_BIT << TS_LOW_SHIFT,
-       .ts_high_shift  = TS_HI_SHIFT,
-       .ts_high_mask   = TS_HI_BIT << TS_HI_SHIFT,
-       .ts_shift       = dma_ts_shift,
-       .ts_shift_num   = ARRAY_SIZE(dma_ts_shift),
-       .dmaor_init     = DMAOR_DME,
-       .chclr_present  = 1,
-       .chclr_bitwise  = 1,
-};
-
-static struct resource dma_resources[] = {
-       DEFINE_RES_MEM(0xe6700020, 0x89e0),
-       DEFINE_RES_IRQ(gic_spi(220)),
-       {
-               /* IRQ for channels 0-19 */
-               .start  = gic_spi(200),
-               .end    = gic_spi(219),
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-#define r8a73a4_register_dmac()                                                        \
-       platform_device_register_resndata(NULL, "sh-dma-engine", 0,             \
-                               dma_resources, ARRAY_SIZE(dma_resources),       \
-                               &dma_pdata, sizeof(dma_pdata))
-
-void __init r8a73a4_add_standard_devices(void)
-{
-       r8a73a4_register_cmt(1);
-       r8a73a4_register_scif(0);
-       r8a73a4_register_scif(1);
-       r8a73a4_register_scif(2);
-       r8a73a4_register_scif(3);
-       r8a73a4_register_scif(4);
-       r8a73a4_register_scif(5);
-       r8a73a4_register_irqc(0);
-       r8a73a4_register_irqc(1);
-       r8a73a4_register_thermal();
-       r8a73a4_register_dmac();
-}
-
-#ifdef CONFIG_USE_OF
 
 static const char *r8a73a4_boards_compat_dt[] __initdata = {
        "renesas,r8a73a4",
@@ -298,4 +30,3 @@ DT_MACHINE_START(R8A73A4_DT, "Generic R8A73A4 (Flattened Device Tree)")
        .init_late      = shmobile_init_late,
        .dt_compat      = r8a73a4_boards_compat_dt,
 MACHINE_END
-#endif /* CONFIG_USE_OF */
index dd64caf792160198de27755e60084040e139c3ad..9832e48396a40a9241d5f7e7c6e4f79420d2a887 100644 (file)
@@ -842,13 +842,6 @@ static void __init r8a7740_generic_init(void)
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
-#define RESCNT2 IOMEM(0xe6188020)
-static void r8a7740_restart(enum reboot_mode mode, const char *cmd)
-{
-       /* Do soft power on reset */
-       writel(1 << 31, RESCNT2);
-}
-
 static const char *r8a7740_boards_compat_dt[] __initdata = {
        "renesas,r8a7740",
        NULL,
@@ -861,7 +854,6 @@ DT_MACHINE_START(R8A7740_DT, "Generic R8A7740 (Flattened Device Tree)")
        .init_machine   = r8a7740_generic_init,
        .init_late      = shmobile_init_late,
        .dt_compat      = r8a7740_boards_compat_dt,
-       .restart        = r8a7740_restart,
 MACHINE_END
 
 #endif /* CONFIG_USE_OF */
index cef8895a9b8271dcd27549b7a5f6209cc4cb9abb..c49aa094fe17acb62e186155784a688e960767b9 100644 (file)
@@ -15,6 +15,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/clk/shmobile.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/irqchip/arm-gic.h>
 #include "irqs.h"
 #include "r8a7778.h"
 
+#define MODEMR 0xffcc0020
+
+#ifdef CONFIG_COMMON_CLK
+static void __init r8a7778_timer_init(void)
+{
+       u32 mode;
+       void __iomem *modemr = ioremap_nocache(MODEMR, 4);
+
+       BUG_ON(!modemr);
+       mode = ioread32(modemr);
+       iounmap(modemr);
+       r8a7778_clocks_init(mode);
+}
+#endif
+
 /* SCIF */
 #define R8A7778_SCIF(index, baseaddr, irq)                     \
 static struct plat_sci_port scif##index##_platform_data = {    \
@@ -608,6 +624,9 @@ DT_MACHINE_START(R8A7778_DT, "Generic R8A7778 (Flattened Device Tree)")
        .init_early     = shmobile_init_delay,
        .init_irq       = r8a7778_init_irq_dt,
        .init_late      = shmobile_init_late,
+#ifdef CONFIG_COMMON_CLK
+       .init_time      = r8a7778_timer_init,
+#endif
        .dt_compat      = r8a7778_compat_dt,
 MACHINE_END
 
index d1fa625e61f5ef604ba98fb48eb89fb784879962..5d13595aa027447dc9b933f4a5132c6d9f75407c 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/dma-contiguous.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
+#include <linux/memblock.h>
 #include <linux/of.h>
 #include <linux/of_fdt.h>
 #include <asm/mach/arch.h>
@@ -50,9 +51,7 @@ u32 rcar_gen2_read_mode_pins(void)
 
 void __init rcar_gen2_timer_init(void)
 {
-#if defined(CONFIG_ARM_ARCH_TIMER) || defined(CONFIG_COMMON_CLK)
        u32 mode = rcar_gen2_read_mode_pins();
-#endif
 #ifdef CONFIG_ARM_ARCH_TIMER
        void __iomem *base;
        int extal_mhz = 0;
@@ -128,9 +127,7 @@ void __init rcar_gen2_timer_init(void)
        iounmap(base);
 #endif /* CONFIG_ARM_ARCH_TIMER */
 
-#ifdef CONFIG_COMMON_CLK
        rcar_gen2_clocks_init(mode);
-#endif
 #ifdef CONFIG_ARCH_SHMOBILE_MULTI
        clocksource_of_init();
 #endif
@@ -199,7 +196,7 @@ void __init rcar_gen2_reserve(void)
 
        of_scan_flat_dt(rcar_gen2_scan_mem, &mrc);
 #ifdef CONFIG_DMA_CMA
-       if (mrc.size)
+       if (mrc.size && memblock_is_region_memory(mrc.base, mrc.size))
                dma_contiguous_reserve_area(mrc.size, mrc.base, 0,
                                            &rcar_gen2_dma_contiguous, true);
 #endif
diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c
deleted file mode 100644 (file)
index 458a2cf..0000000
+++ /dev/null
@@ -1,1016 +0,0 @@
-/*
- * sh7372 processor support
- *
- * 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>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/platform_device.h>
-#include <linux/of_platform.h>
-#include <linux/uio_driver.h>
-#include <linux/delay.h>
-#include <linux/input.h>
-#include <linux/io.h>
-#include <linux/serial_sci.h>
-#include <linux/sh_dma.h>
-#include <linux/sh_timer.h>
-#include <linux/pm_domain.h>
-#include <linux/dma-mapping.h>
-#include <linux/platform_data/sh_ipmmu.h>
-
-#include <asm/mach/map.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "common.h"
-#include "dma-register.h"
-#include "intc.h"
-#include "irqs.h"
-#include "pm-rmobile.h"
-#include "sh7372.h"
-
-static struct map_desc sh7372_io_desc[] __initdata = {
-       /* create a 1:1 identity mapping for 0xe6xxxxxx
-        * used by CPGA, INTC and PFC.
-        */
-       {
-               .virtual        = 0xe6000000,
-               .pfn            = __phys_to_pfn(0xe6000000),
-               .length         = 256 << 20,
-               .type           = MT_DEVICE_NONSHARED
-       },
-};
-
-void __init sh7372_map_io(void)
-{
-       debug_ll_io_init();
-       iotable_init(sh7372_io_desc, ARRAY_SIZE(sh7372_io_desc));
-}
-
-/* PFC */
-static struct resource sh7372_pfc_resources[] = {
-       [0] = {
-               .start  = 0xe6050000,
-               .end    = 0xe6057fff,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = 0xe605800c,
-               .end    = 0xe6058027,
-               .flags  = IORESOURCE_MEM,
-       }
-};
-
-static struct platform_device sh7372_pfc_device = {
-       .name           = "pfc-sh7372",
-       .id             = -1,
-       .resource       = sh7372_pfc_resources,
-       .num_resources  = ARRAY_SIZE(sh7372_pfc_resources),
-};
-
-void __init sh7372_pinmux_init(void)
-{
-       platform_device_register(&sh7372_pfc_device);
-}
-
-/* SCIF */
-#define SH7372_SCIF(scif_type, index, baseaddr, irq)           \
-static struct plat_sci_port scif##index##_platform_data = {    \
-       .type           = scif_type,                            \
-       .flags          = UPF_BOOT_AUTOCONF,                    \
-       .scscr          = SCSCR_RE | SCSCR_TE,                  \
-};                                                             \
-                                                               \
-static struct resource scif##index##_resources[] = {           \
-       DEFINE_RES_MEM(baseaddr, 0x100),                        \
-       DEFINE_RES_IRQ(irq),                                    \
-};                                                             \
-                                                               \
-static struct platform_device scif##index##_device = {         \
-       .name           = "sh-sci",                             \
-       .id             = index,                                \
-       .resource       = scif##index##_resources,              \
-       .num_resources  = ARRAY_SIZE(scif##index##_resources),  \
-       .dev            = {                                     \
-               .platform_data  = &scif##index##_platform_data, \
-       },                                                      \
-}
-
-SH7372_SCIF(PORT_SCIFA, 0, 0xe6c40000, evt2irq(0x0c00));
-SH7372_SCIF(PORT_SCIFA, 1, 0xe6c50000, evt2irq(0x0c20));
-SH7372_SCIF(PORT_SCIFA, 2, 0xe6c60000, evt2irq(0x0c40));
-SH7372_SCIF(PORT_SCIFA, 3, 0xe6c70000, evt2irq(0x0c60));
-SH7372_SCIF(PORT_SCIFA, 4, 0xe6c80000, evt2irq(0x0d20));
-SH7372_SCIF(PORT_SCIFA, 5, 0xe6cb0000, evt2irq(0x0d40));
-SH7372_SCIF(PORT_SCIFB, 6, 0xe6c30000, evt2irq(0x0d60));
-
-/* CMT */
-static struct sh_timer_config cmt2_platform_data = {
-       .channels_mask = 0x20,
-};
-
-static struct resource cmt2_resources[] = {
-       DEFINE_RES_MEM(0xe6130000, 0x50),
-       DEFINE_RES_IRQ(evt2irq(0x0b80)),
-};
-
-static struct platform_device cmt2_device = {
-       .name           = "sh-cmt-32-fast",
-       .id             = 2,
-       .dev = {
-               .platform_data  = &cmt2_platform_data,
-       },
-       .resource       = cmt2_resources,
-       .num_resources  = ARRAY_SIZE(cmt2_resources),
-};
-
-/* TMU */
-static struct sh_timer_config tmu0_platform_data = {
-       .channels_mask = 7,
-};
-
-static struct resource tmu0_resources[] = {
-       DEFINE_RES_MEM(0xfff60000, 0x2c),
-       DEFINE_RES_IRQ(intcs_evt2irq(0xe80)),
-       DEFINE_RES_IRQ(intcs_evt2irq(0xea0)),
-       DEFINE_RES_IRQ(intcs_evt2irq(0xec0)),
-};
-
-static struct platform_device tmu0_device = {
-       .name           = "sh-tmu",
-       .id             = 0,
-       .dev = {
-               .platform_data  = &tmu0_platform_data,
-       },
-       .resource       = tmu0_resources,
-       .num_resources  = ARRAY_SIZE(tmu0_resources),
-};
-
-/* I2C */
-static struct resource iic0_resources[] = {
-       [0] = {
-               .name   = "IIC0",
-               .start  = 0xFFF20000,
-               .end    = 0xFFF20425 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = intcs_evt2irq(0xe00), /* IIC0_ALI0 */
-               .end    = intcs_evt2irq(0xe60), /* IIC0_DTEI0 */
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device iic0_device = {
-       .name           = "i2c-sh_mobile",
-       .id             = 0, /* "i2c0" clock */
-       .num_resources  = ARRAY_SIZE(iic0_resources),
-       .resource       = iic0_resources,
-};
-
-static struct resource iic1_resources[] = {
-       [0] = {
-               .name   = "IIC1",
-               .start  = 0xE6C20000,
-               .end    = 0xE6C20425 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = evt2irq(0x780), /* IIC1_ALI1 */
-               .end    = evt2irq(0x7e0), /* IIC1_DTEI1 */
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device iic1_device = {
-       .name           = "i2c-sh_mobile",
-       .id             = 1, /* "i2c1" clock */
-       .num_resources  = ARRAY_SIZE(iic1_resources),
-       .resource       = iic1_resources,
-};
-
-/* DMA */
-static const struct sh_dmae_slave_config sh7372_dmae_slaves[] = {
-       {
-               .slave_id       = SHDMA_SLAVE_SCIF0_TX,
-               .addr           = 0xe6c40020,
-               .chcr           = CHCR_TX(XMIT_SZ_8BIT),
-               .mid_rid        = 0x21,
-       }, {
-               .slave_id       = SHDMA_SLAVE_SCIF0_RX,
-               .addr           = 0xe6c40024,
-               .chcr           = CHCR_RX(XMIT_SZ_8BIT),
-               .mid_rid        = 0x22,
-       }, {
-               .slave_id       = SHDMA_SLAVE_SCIF1_TX,
-               .addr           = 0xe6c50020,
-               .chcr           = CHCR_TX(XMIT_SZ_8BIT),
-               .mid_rid        = 0x25,
-       }, {
-               .slave_id       = SHDMA_SLAVE_SCIF1_RX,
-               .addr           = 0xe6c50024,
-               .chcr           = CHCR_RX(XMIT_SZ_8BIT),
-               .mid_rid        = 0x26,
-       }, {
-               .slave_id       = SHDMA_SLAVE_SCIF2_TX,
-               .addr           = 0xe6c60020,
-               .chcr           = CHCR_TX(XMIT_SZ_8BIT),
-               .mid_rid        = 0x29,
-       }, {
-               .slave_id       = SHDMA_SLAVE_SCIF2_RX,
-               .addr           = 0xe6c60024,
-               .chcr           = CHCR_RX(XMIT_SZ_8BIT),
-               .mid_rid        = 0x2a,
-       }, {
-               .slave_id       = SHDMA_SLAVE_SCIF3_TX,
-               .addr           = 0xe6c70020,
-               .chcr           = CHCR_TX(XMIT_SZ_8BIT),
-               .mid_rid        = 0x2d,
-       }, {
-               .slave_id       = SHDMA_SLAVE_SCIF3_RX,
-               .addr           = 0xe6c70024,
-               .chcr           = CHCR_RX(XMIT_SZ_8BIT),
-               .mid_rid        = 0x2e,
-       }, {
-               .slave_id       = SHDMA_SLAVE_SCIF4_TX,
-               .addr           = 0xe6c80020,
-               .chcr           = CHCR_TX(XMIT_SZ_8BIT),
-               .mid_rid        = 0x39,
-       }, {
-               .slave_id       = SHDMA_SLAVE_SCIF4_RX,
-               .addr           = 0xe6c80024,
-               .chcr           = CHCR_RX(XMIT_SZ_8BIT),
-               .mid_rid        = 0x3a,
-       }, {
-               .slave_id       = SHDMA_SLAVE_SCIF5_TX,
-               .addr           = 0xe6cb0020,
-               .chcr           = CHCR_TX(XMIT_SZ_8BIT),
-               .mid_rid        = 0x35,
-       }, {
-               .slave_id       = SHDMA_SLAVE_SCIF5_RX,
-               .addr           = 0xe6cb0024,
-               .chcr           = CHCR_RX(XMIT_SZ_8BIT),
-               .mid_rid        = 0x36,
-       }, {
-               .slave_id       = SHDMA_SLAVE_SCIF6_TX,
-               .addr           = 0xe6c30040,
-               .chcr           = CHCR_TX(XMIT_SZ_8BIT),
-               .mid_rid        = 0x3d,
-       }, {
-               .slave_id       = SHDMA_SLAVE_SCIF6_RX,
-               .addr           = 0xe6c30060,
-               .chcr           = CHCR_RX(XMIT_SZ_8BIT),
-               .mid_rid        = 0x3e,
-       }, {
-               .slave_id       = SHDMA_SLAVE_FLCTL0_TX,
-               .addr           = 0xe6a30050,
-               .chcr           = CHCR_TX(XMIT_SZ_32BIT),
-               .mid_rid        = 0x83,
-       }, {
-               .slave_id       = SHDMA_SLAVE_FLCTL0_RX,
-               .addr           = 0xe6a30050,
-               .chcr           = CHCR_RX(XMIT_SZ_32BIT),
-               .mid_rid        = 0x83,
-       }, {
-               .slave_id       = SHDMA_SLAVE_FLCTL1_TX,
-               .addr           = 0xe6a30060,
-               .chcr           = CHCR_TX(XMIT_SZ_32BIT),
-               .mid_rid        = 0x87,
-       }, {
-               .slave_id       = SHDMA_SLAVE_FLCTL1_RX,
-               .addr           = 0xe6a30060,
-               .chcr           = CHCR_RX(XMIT_SZ_32BIT),
-               .mid_rid        = 0x87,
-       }, {
-               .slave_id       = SHDMA_SLAVE_SDHI0_TX,
-               .addr           = 0xe6850030,
-               .chcr           = CHCR_TX(XMIT_SZ_16BIT),
-               .mid_rid        = 0xc1,
-       }, {
-               .slave_id       = SHDMA_SLAVE_SDHI0_RX,
-               .addr           = 0xe6850030,
-               .chcr           = CHCR_RX(XMIT_SZ_16BIT),
-               .mid_rid        = 0xc2,
-       }, {
-               .slave_id       = SHDMA_SLAVE_SDHI1_TX,
-               .addr           = 0xe6860030,
-               .chcr           = CHCR_TX(XMIT_SZ_16BIT),
-               .mid_rid        = 0xc9,
-       }, {
-               .slave_id       = SHDMA_SLAVE_SDHI1_RX,
-               .addr           = 0xe6860030,
-               .chcr           = CHCR_RX(XMIT_SZ_16BIT),
-               .mid_rid        = 0xca,
-       }, {
-               .slave_id       = SHDMA_SLAVE_SDHI2_TX,
-               .addr           = 0xe6870030,
-               .chcr           = CHCR_TX(XMIT_SZ_16BIT),
-               .mid_rid        = 0xcd,
-       }, {
-               .slave_id       = SHDMA_SLAVE_SDHI2_RX,
-               .addr           = 0xe6870030,
-               .chcr           = CHCR_RX(XMIT_SZ_16BIT),
-               .mid_rid        = 0xce,
-       }, {
-               .slave_id       = SHDMA_SLAVE_FSIA_TX,
-               .addr           = 0xfe1f0024,
-               .chcr           = CHCR_TX(XMIT_SZ_32BIT),
-               .mid_rid        = 0xb1,
-       }, {
-               .slave_id       = SHDMA_SLAVE_FSIA_RX,
-               .addr           = 0xfe1f0020,
-               .chcr           = CHCR_RX(XMIT_SZ_32BIT),
-               .mid_rid        = 0xb2,
-       }, {
-               .slave_id       = SHDMA_SLAVE_MMCIF_TX,
-               .addr           = 0xe6bd0034,
-               .chcr           = CHCR_TX(XMIT_SZ_32BIT),
-               .mid_rid        = 0xd1,
-       }, {
-               .slave_id       = SHDMA_SLAVE_MMCIF_RX,
-               .addr           = 0xe6bd0034,
-               .chcr           = CHCR_RX(XMIT_SZ_32BIT),
-               .mid_rid        = 0xd2,
-       },
-};
-
-#define SH7372_CHCLR (0x220 - 0x20)
-
-static const struct sh_dmae_channel sh7372_dmae_channels[] = {
-       {
-               .offset = 0,
-               .dmars = 0,
-               .dmars_bit = 0,
-               .chclr_offset = SH7372_CHCLR + 0,
-       }, {
-               .offset = 0x10,
-               .dmars = 0,
-               .dmars_bit = 8,
-               .chclr_offset = SH7372_CHCLR + 0x10,
-       }, {
-               .offset = 0x20,
-               .dmars = 4,
-               .dmars_bit = 0,
-               .chclr_offset = SH7372_CHCLR + 0x20,
-       }, {
-               .offset = 0x30,
-               .dmars = 4,
-               .dmars_bit = 8,
-               .chclr_offset = SH7372_CHCLR + 0x30,
-       }, {
-               .offset = 0x50,
-               .dmars = 8,
-               .dmars_bit = 0,
-               .chclr_offset = SH7372_CHCLR + 0x50,
-       }, {
-               .offset = 0x60,
-               .dmars = 8,
-               .dmars_bit = 8,
-               .chclr_offset = SH7372_CHCLR + 0x60,
-       }
-};
-
-static struct sh_dmae_pdata dma_platform_data = {
-       .slave          = sh7372_dmae_slaves,
-       .slave_num      = ARRAY_SIZE(sh7372_dmae_slaves),
-       .channel        = sh7372_dmae_channels,
-       .channel_num    = ARRAY_SIZE(sh7372_dmae_channels),
-       .ts_low_shift   = TS_LOW_SHIFT,
-       .ts_low_mask    = TS_LOW_BIT << TS_LOW_SHIFT,
-       .ts_high_shift  = TS_HI_SHIFT,
-       .ts_high_mask   = TS_HI_BIT << TS_HI_SHIFT,
-       .ts_shift       = dma_ts_shift,
-       .ts_shift_num   = ARRAY_SIZE(dma_ts_shift),
-       .dmaor_init     = DMAOR_DME,
-       .chclr_present  = 1,
-};
-
-/* Resource order important! */
-static struct resource sh7372_dmae0_resources[] = {
-       {
-               /* Channel registers and DMAOR */
-               .start  = 0xfe008020,
-               .end    = 0xfe00828f,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               /* DMARSx */
-               .start  = 0xfe009000,
-               .end    = 0xfe00900b,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               .name   = "error_irq",
-               .start  = evt2irq(0x20c0),
-               .end    = evt2irq(0x20c0),
-               .flags  = IORESOURCE_IRQ,
-       },
-       {
-               /* IRQ for channels 0-5 */
-               .start  = evt2irq(0x2000),
-               .end    = evt2irq(0x20a0),
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-/* Resource order important! */
-static struct resource sh7372_dmae1_resources[] = {
-       {
-               /* Channel registers and DMAOR */
-               .start  = 0xfe018020,
-               .end    = 0xfe01828f,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               /* DMARSx */
-               .start  = 0xfe019000,
-               .end    = 0xfe01900b,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               .name   = "error_irq",
-               .start  = evt2irq(0x21c0),
-               .end    = evt2irq(0x21c0),
-               .flags  = IORESOURCE_IRQ,
-       },
-       {
-               /* IRQ for channels 0-5 */
-               .start  = evt2irq(0x2100),
-               .end    = evt2irq(0x21a0),
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-/* Resource order important! */
-static struct resource sh7372_dmae2_resources[] = {
-       {
-               /* Channel registers and DMAOR */
-               .start  = 0xfe028020,
-               .end    = 0xfe02828f,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               /* DMARSx */
-               .start  = 0xfe029000,
-               .end    = 0xfe02900b,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               .name   = "error_irq",
-               .start  = evt2irq(0x22c0),
-               .end    = evt2irq(0x22c0),
-               .flags  = IORESOURCE_IRQ,
-       },
-       {
-               /* IRQ for channels 0-5 */
-               .start  = evt2irq(0x2200),
-               .end    = evt2irq(0x22a0),
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device dma0_device = {
-       .name           = "sh-dma-engine",
-       .id             = 0,
-       .resource       = sh7372_dmae0_resources,
-       .num_resources  = ARRAY_SIZE(sh7372_dmae0_resources),
-       .dev            = {
-               .platform_data  = &dma_platform_data,
-       },
-};
-
-static struct platform_device dma1_device = {
-       .name           = "sh-dma-engine",
-       .id             = 1,
-       .resource       = sh7372_dmae1_resources,
-       .num_resources  = ARRAY_SIZE(sh7372_dmae1_resources),
-       .dev            = {
-               .platform_data  = &dma_platform_data,
-       },
-};
-
-static struct platform_device dma2_device = {
-       .name           = "sh-dma-engine",
-       .id             = 2,
-       .resource       = sh7372_dmae2_resources,
-       .num_resources  = ARRAY_SIZE(sh7372_dmae2_resources),
-       .dev            = {
-               .platform_data  = &dma_platform_data,
-       },
-};
-
-/*
- * USB-DMAC
- */
-static const struct sh_dmae_channel sh7372_usb_dmae_channels[] = {
-       {
-               .offset = 0,
-       }, {
-               .offset = 0x20,
-       },
-};
-
-/* USB DMAC0 */
-static const struct sh_dmae_slave_config sh7372_usb_dmae0_slaves[] = {
-       {
-               .slave_id       = SHDMA_SLAVE_USB0_TX,
-               .chcr           = USBTS_INDEX2VAL(USBTS_XMIT_SZ_8BYTE),
-       }, {
-               .slave_id       = SHDMA_SLAVE_USB0_RX,
-               .chcr           = USBTS_INDEX2VAL(USBTS_XMIT_SZ_8BYTE),
-       },
-};
-
-static struct sh_dmae_pdata usb_dma0_platform_data = {
-       .slave          = sh7372_usb_dmae0_slaves,
-       .slave_num      = ARRAY_SIZE(sh7372_usb_dmae0_slaves),
-       .channel        = sh7372_usb_dmae_channels,
-       .channel_num    = ARRAY_SIZE(sh7372_usb_dmae_channels),
-       .ts_low_shift   = USBTS_LOW_SHIFT,
-       .ts_low_mask    = USBTS_LOW_BIT << USBTS_LOW_SHIFT,
-       .ts_high_shift  = USBTS_HI_SHIFT,
-       .ts_high_mask   = USBTS_HI_BIT << USBTS_HI_SHIFT,
-       .ts_shift       = dma_usbts_shift,
-       .ts_shift_num   = ARRAY_SIZE(dma_usbts_shift),
-       .dmaor_init     = DMAOR_DME,
-       .chcr_offset    = 0x14,
-       .chcr_ie_bit    = 1 << 5,
-       .dmaor_is_32bit = 1,
-       .needs_tend_set = 1,
-       .no_dmars       = 1,
-       .slave_only     = 1,
-};
-
-static struct resource sh7372_usb_dmae0_resources[] = {
-       {
-               /* Channel registers and DMAOR */
-               .start  = 0xe68a0020,
-               .end    = 0xe68a0064 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               /* VCR/SWR/DMICR */
-               .start  = 0xe68a0000,
-               .end    = 0xe68a0014 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               /* IRQ for channels */
-               .start  = evt2irq(0x0a00),
-               .end    = evt2irq(0x0a00),
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device usb_dma0_device = {
-       .name           = "sh-dma-engine",
-       .id             = 3,
-       .resource       = sh7372_usb_dmae0_resources,
-       .num_resources  = ARRAY_SIZE(sh7372_usb_dmae0_resources),
-       .dev            = {
-               .platform_data  = &usb_dma0_platform_data,
-       },
-};
-
-/* USB DMAC1 */
-static const struct sh_dmae_slave_config sh7372_usb_dmae1_slaves[] = {
-       {
-               .slave_id       = SHDMA_SLAVE_USB1_TX,
-               .chcr           = USBTS_INDEX2VAL(USBTS_XMIT_SZ_8BYTE),
-       }, {
-               .slave_id       = SHDMA_SLAVE_USB1_RX,
-               .chcr           = USBTS_INDEX2VAL(USBTS_XMIT_SZ_8BYTE),
-       },
-};
-
-static struct sh_dmae_pdata usb_dma1_platform_data = {
-       .slave          = sh7372_usb_dmae1_slaves,
-       .slave_num      = ARRAY_SIZE(sh7372_usb_dmae1_slaves),
-       .channel        = sh7372_usb_dmae_channels,
-       .channel_num    = ARRAY_SIZE(sh7372_usb_dmae_channels),
-       .ts_low_shift   = USBTS_LOW_SHIFT,
-       .ts_low_mask    = USBTS_LOW_BIT << USBTS_LOW_SHIFT,
-       .ts_high_shift  = USBTS_HI_SHIFT,
-       .ts_high_mask   = USBTS_HI_BIT << USBTS_HI_SHIFT,
-       .ts_shift       = dma_usbts_shift,
-       .ts_shift_num   = ARRAY_SIZE(dma_usbts_shift),
-       .dmaor_init     = DMAOR_DME,
-       .chcr_offset    = 0x14,
-       .chcr_ie_bit    = 1 << 5,
-       .dmaor_is_32bit = 1,
-       .needs_tend_set = 1,
-       .no_dmars       = 1,
-       .slave_only     = 1,
-};
-
-static struct resource sh7372_usb_dmae1_resources[] = {
-       {
-               /* Channel registers and DMAOR */
-               .start  = 0xe68c0020,
-               .end    = 0xe68c0064 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               /* VCR/SWR/DMICR */
-               .start  = 0xe68c0000,
-               .end    = 0xe68c0014 - 1,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               /* IRQ for channels */
-               .start  = evt2irq(0x1d00),
-               .end    = evt2irq(0x1d00),
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device usb_dma1_device = {
-       .name           = "sh-dma-engine",
-       .id             = 4,
-       .resource       = sh7372_usb_dmae1_resources,
-       .num_resources  = ARRAY_SIZE(sh7372_usb_dmae1_resources),
-       .dev            = {
-               .platform_data  = &usb_dma1_platform_data,
-       },
-};
-
-/* VPU */
-static struct uio_info vpu_platform_data = {
-       .name = "VPU5HG",
-       .version = "0",
-       .irq = intcs_evt2irq(0x980),
-};
-
-static struct resource vpu_resources[] = {
-       [0] = {
-               .name   = "VPU",
-               .start  = 0xfe900000,
-               .end    = 0xfe900157,
-               .flags  = IORESOURCE_MEM,
-       },
-};
-
-static struct platform_device vpu_device = {
-       .name           = "uio_pdrv_genirq",
-       .id             = 0,
-       .dev = {
-               .platform_data  = &vpu_platform_data,
-       },
-       .resource       = vpu_resources,
-       .num_resources  = ARRAY_SIZE(vpu_resources),
-};
-
-/* VEU0 */
-static struct uio_info veu0_platform_data = {
-       .name = "VEU0",
-       .version = "0",
-       .irq = intcs_evt2irq(0x700),
-};
-
-static struct resource veu0_resources[] = {
-       [0] = {
-               .name   = "VEU0",
-               .start  = 0xfe920000,
-               .end    = 0xfe9200cb,
-               .flags  = IORESOURCE_MEM,
-       },
-};
-
-static struct platform_device veu0_device = {
-       .name           = "uio_pdrv_genirq",
-       .id             = 1,
-       .dev = {
-               .platform_data  = &veu0_platform_data,
-       },
-       .resource       = veu0_resources,
-       .num_resources  = ARRAY_SIZE(veu0_resources),
-};
-
-/* VEU1 */
-static struct uio_info veu1_platform_data = {
-       .name = "VEU1",
-       .version = "0",
-       .irq = intcs_evt2irq(0x720),
-};
-
-static struct resource veu1_resources[] = {
-       [0] = {
-               .name   = "VEU1",
-               .start  = 0xfe924000,
-               .end    = 0xfe9240cb,
-               .flags  = IORESOURCE_MEM,
-       },
-};
-
-static struct platform_device veu1_device = {
-       .name           = "uio_pdrv_genirq",
-       .id             = 2,
-       .dev = {
-               .platform_data  = &veu1_platform_data,
-       },
-       .resource       = veu1_resources,
-       .num_resources  = ARRAY_SIZE(veu1_resources),
-};
-
-/* VEU2 */
-static struct uio_info veu2_platform_data = {
-       .name = "VEU2",
-       .version = "0",
-       .irq = intcs_evt2irq(0x740),
-};
-
-static struct resource veu2_resources[] = {
-       [0] = {
-               .name   = "VEU2",
-               .start  = 0xfe928000,
-               .end    = 0xfe928307,
-               .flags  = IORESOURCE_MEM,
-       },
-};
-
-static struct platform_device veu2_device = {
-       .name           = "uio_pdrv_genirq",
-       .id             = 3,
-       .dev = {
-               .platform_data  = &veu2_platform_data,
-       },
-       .resource       = veu2_resources,
-       .num_resources  = ARRAY_SIZE(veu2_resources),
-};
-
-/* VEU3 */
-static struct uio_info veu3_platform_data = {
-       .name = "VEU3",
-       .version = "0",
-       .irq = intcs_evt2irq(0x760),
-};
-
-static struct resource veu3_resources[] = {
-       [0] = {
-               .name   = "VEU3",
-               .start  = 0xfe92c000,
-               .end    = 0xfe92c307,
-               .flags  = IORESOURCE_MEM,
-       },
-};
-
-static struct platform_device veu3_device = {
-       .name           = "uio_pdrv_genirq",
-       .id             = 4,
-       .dev = {
-               .platform_data  = &veu3_platform_data,
-       },
-       .resource       = veu3_resources,
-       .num_resources  = ARRAY_SIZE(veu3_resources),
-};
-
-/* JPU */
-static struct uio_info jpu_platform_data = {
-       .name = "JPU",
-       .version = "0",
-       .irq = intcs_evt2irq(0x560),
-};
-
-static struct resource jpu_resources[] = {
-       [0] = {
-               .name   = "JPU",
-               .start  = 0xfe980000,
-               .end    = 0xfe9902d3,
-               .flags  = IORESOURCE_MEM,
-       },
-};
-
-static struct platform_device jpu_device = {
-       .name           = "uio_pdrv_genirq",
-       .id             = 5,
-       .dev = {
-               .platform_data  = &jpu_platform_data,
-       },
-       .resource       = jpu_resources,
-       .num_resources  = ARRAY_SIZE(jpu_resources),
-};
-
-/* SPU2DSP0 */
-static struct uio_info spu0_platform_data = {
-       .name = "SPU2DSP0",
-       .version = "0",
-       .irq = evt2irq(0x1800),
-};
-
-static struct resource spu0_resources[] = {
-       [0] = {
-               .name   = "SPU2DSP0",
-               .start  = 0xfe200000,
-               .end    = 0xfe2fffff,
-               .flags  = IORESOURCE_MEM,
-       },
-};
-
-static struct platform_device spu0_device = {
-       .name           = "uio_pdrv_genirq",
-       .id             = 6,
-       .dev = {
-               .platform_data  = &spu0_platform_data,
-       },
-       .resource       = spu0_resources,
-       .num_resources  = ARRAY_SIZE(spu0_resources),
-};
-
-/* SPU2DSP1 */
-static struct uio_info spu1_platform_data = {
-       .name = "SPU2DSP1",
-       .version = "0",
-       .irq = evt2irq(0x1820),
-};
-
-static struct resource spu1_resources[] = {
-       [0] = {
-               .name   = "SPU2DSP1",
-               .start  = 0xfe300000,
-               .end    = 0xfe3fffff,
-               .flags  = IORESOURCE_MEM,
-       },
-};
-
-static struct platform_device spu1_device = {
-       .name           = "uio_pdrv_genirq",
-       .id             = 7,
-       .dev = {
-               .platform_data  = &spu1_platform_data,
-       },
-       .resource       = spu1_resources,
-       .num_resources  = ARRAY_SIZE(spu1_resources),
-};
-
-/* IPMMUI (an IPMMU module for ICB/LMB) */
-static struct resource ipmmu_resources[] = {
-       [0] = {
-               .name   = "IPMMUI",
-               .start  = 0xfe951000,
-               .end    = 0xfe9510ff,
-               .flags  = IORESOURCE_MEM,
-       },
-};
-
-static const char * const ipmmu_dev_names[] = {
-       "sh_mobile_lcdc_fb.0",
-       "sh_mobile_lcdc_fb.1",
-       "sh_mobile_ceu.0",
-       "uio_pdrv_genirq.0",
-       "uio_pdrv_genirq.1",
-       "uio_pdrv_genirq.2",
-       "uio_pdrv_genirq.3",
-       "uio_pdrv_genirq.4",
-       "uio_pdrv_genirq.5",
-};
-
-static struct shmobile_ipmmu_platform_data ipmmu_platform_data = {
-       .dev_names = ipmmu_dev_names,
-       .num_dev_names = ARRAY_SIZE(ipmmu_dev_names),
-};
-
-static struct platform_device ipmmu_device = {
-       .name           = "ipmmu",
-       .id             = -1,
-       .dev = {
-               .platform_data = &ipmmu_platform_data,
-       },
-       .resource       = ipmmu_resources,
-       .num_resources  = ARRAY_SIZE(ipmmu_resources),
-};
-
-static struct platform_device *sh7372_early_devices[] __initdata = {
-       &scif0_device,
-       &scif1_device,
-       &scif2_device,
-       &scif3_device,
-       &scif4_device,
-       &scif5_device,
-       &scif6_device,
-       &cmt2_device,
-       &tmu0_device,
-       &ipmmu_device,
-};
-
-static struct platform_device *sh7372_late_devices[] __initdata = {
-       &iic0_device,
-       &iic1_device,
-       &dma0_device,
-       &dma1_device,
-       &dma2_device,
-       &usb_dma0_device,
-       &usb_dma1_device,
-       &vpu_device,
-       &veu0_device,
-       &veu1_device,
-       &veu2_device,
-       &veu3_device,
-       &jpu_device,
-       &spu0_device,
-       &spu1_device,
-};
-
-void __init sh7372_add_standard_devices(void)
-{
-       static struct pm_domain_device domain_devices[] __initdata = {
-               { "A3RV", &vpu_device, },
-               { "A4MP", &spu0_device, },
-               { "A4MP", &spu1_device, },
-               { "A3SP", &scif0_device, },
-               { "A3SP", &scif1_device, },
-               { "A3SP", &scif2_device, },
-               { "A3SP", &scif3_device, },
-               { "A3SP", &scif4_device, },
-               { "A3SP", &scif5_device, },
-               { "A3SP", &scif6_device, },
-               { "A3SP", &iic1_device, },
-               { "A3SP", &dma0_device, },
-               { "A3SP", &dma1_device, },
-               { "A3SP", &dma2_device, },
-               { "A3SP", &usb_dma0_device, },
-               { "A3SP", &usb_dma1_device, },
-               { "A4R", &iic0_device, },
-               { "A4R", &veu0_device, },
-               { "A4R", &veu1_device, },
-               { "A4R", &veu2_device, },
-               { "A4R", &veu3_device, },
-               { "A4R", &jpu_device, },
-               { "A4R", &tmu0_device, },
-       };
-
-       sh7372_init_pm_domains();
-
-       platform_add_devices(sh7372_early_devices,
-                           ARRAY_SIZE(sh7372_early_devices));
-
-       platform_add_devices(sh7372_late_devices,
-                           ARRAY_SIZE(sh7372_late_devices));
-
-       rmobile_add_devices_to_domains(domain_devices,
-                                      ARRAY_SIZE(domain_devices));
-}
-
-void __init sh7372_earlytimer_init(void)
-{
-       sh7372_clock_init();
-       shmobile_earlytimer_init();
-}
-
-void __init sh7372_add_early_devices(void)
-{
-       early_platform_add_devices(sh7372_early_devices,
-                                  ARRAY_SIZE(sh7372_early_devices));
-
-       /* setup early console here as well */
-       shmobile_setup_console();
-}
-
-#ifdef CONFIG_USE_OF
-
-void __init sh7372_add_early_devices_dt(void)
-{
-       shmobile_init_delay();
-
-       sh7372_add_early_devices();
-}
-
-void __init sh7372_add_standard_devices_dt(void)
-{
-       /* clocks are setup late during boot in the case of DT */
-       sh7372_clock_init();
-
-       platform_add_devices(sh7372_early_devices,
-                           ARRAY_SIZE(sh7372_early_devices));
-
-       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
-
-static const char *sh7372_boards_compat_dt[] __initdata = {
-       "renesas,sh7372",
-       NULL,
-};
-
-DT_MACHINE_START(SH7372_DT, "Generic SH7372 (Flattened Device Tree)")
-       .map_io         = sh7372_map_io,
-       .init_early     = sh7372_add_early_devices_dt,
-       .init_irq       = sh7372_init_irq,
-       .handle_irq     = shmobile_handle_irq_intc,
-       .init_machine   = sh7372_add_standard_devices_dt,
-       .init_late      = shmobile_init_late,
-       .dt_compat      = sh7372_boards_compat_dt,
-MACHINE_END
-
-#endif /* CONFIG_USE_OF */
index faea74a2151b1ca6849065f27e2d356711fe8ba5..fb2ab7590af8bf9dbca323f44e95d08a5afdf6cf 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/platform_data/sh_ipmmu.h>
 #include <linux/platform_data/irq-renesas-intc-irqpin.h>
 
+#include <asm/hardware/cache-l2x0.h>
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
 #include <asm/mach/arch.h>
@@ -784,22 +785,15 @@ void __init sh73a0_add_early_devices(void)
 
 #ifdef CONFIG_USE_OF
 
-void __init sh73a0_add_standard_devices_dt(void)
+static void __init sh73a0_generic_init(void)
 {
-       /* clocks are setup late during boot in the case of DT */
-#ifndef CONFIG_COMMON_CLK
-       sh73a0_clock_init();
+#ifdef CONFIG_CACHE_L2X0
+       /* Shared attribute override enable, 64K*8way */
+       l2x0_init(IOMEM(0xf0100000), 0x00400000, 0xc20f0fff);
 #endif
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
-#define RESCNT2 IOMEM(0xe6188020)
-static void sh73a0_restart(enum reboot_mode mode, const char *cmd)
-{
-       /* Do soft power on reset */
-       writel((1 << 31), RESCNT2);
-}
-
 static const char *sh73a0_boards_compat_dt[] __initdata = {
        "renesas,sh73a0",
        NULL,
@@ -809,9 +803,8 @@ DT_MACHINE_START(SH73A0_DT, "Generic SH73A0 (Flattened Device Tree)")
        .smp            = smp_ops(sh73a0_smp_ops),
        .map_io         = sh73a0_map_io,
        .init_early     = shmobile_init_delay,
-       .init_machine   = sh73a0_add_standard_devices_dt,
+       .init_machine   = sh73a0_generic_init,
        .init_late      = shmobile_init_late,
-       .restart        = sh73a0_restart,
        .dt_compat      = sh73a0_boards_compat_dt,
 MACHINE_END
 #endif /* CONFIG_USE_OF */
diff --git a/arch/arm/mach-shmobile/sh7372.h b/arch/arm/mach-shmobile/sh7372.h
deleted file mode 100644 (file)
index 4ad960d..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2010 Renesas Solutions Corp.
- *
- * Kuninori Morimoto <morimoto.kuninori@renesas.com>
- *
- * 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.
- */
-
-#ifndef __ASM_SH7372_H__
-#define __ASM_SH7372_H__
-
-/* DMA slave IDs */
-enum {
-       SHDMA_SLAVE_INVALID,
-       SHDMA_SLAVE_SCIF0_TX,
-       SHDMA_SLAVE_SCIF0_RX,
-       SHDMA_SLAVE_SCIF1_TX,
-       SHDMA_SLAVE_SCIF1_RX,
-       SHDMA_SLAVE_SCIF2_TX,
-       SHDMA_SLAVE_SCIF2_RX,
-       SHDMA_SLAVE_SCIF3_TX,
-       SHDMA_SLAVE_SCIF3_RX,
-       SHDMA_SLAVE_SCIF4_TX,
-       SHDMA_SLAVE_SCIF4_RX,
-       SHDMA_SLAVE_SCIF5_TX,
-       SHDMA_SLAVE_SCIF5_RX,
-       SHDMA_SLAVE_SCIF6_TX,
-       SHDMA_SLAVE_SCIF6_RX,
-       SHDMA_SLAVE_FLCTL0_TX,
-       SHDMA_SLAVE_FLCTL0_RX,
-       SHDMA_SLAVE_FLCTL1_TX,
-       SHDMA_SLAVE_FLCTL1_RX,
-       SHDMA_SLAVE_SDHI0_RX,
-       SHDMA_SLAVE_SDHI0_TX,
-       SHDMA_SLAVE_SDHI1_RX,
-       SHDMA_SLAVE_SDHI1_TX,
-       SHDMA_SLAVE_SDHI2_RX,
-       SHDMA_SLAVE_SDHI2_TX,
-       SHDMA_SLAVE_FSIA_RX,
-       SHDMA_SLAVE_FSIA_TX,
-       SHDMA_SLAVE_MMCIF_RX,
-       SHDMA_SLAVE_MMCIF_TX,
-       SHDMA_SLAVE_USB0_TX,
-       SHDMA_SLAVE_USB0_RX,
-       SHDMA_SLAVE_USB1_TX,
-       SHDMA_SLAVE_USB1_RX,
-};
-
-extern struct clk sh7372_extal1_clk;
-extern struct clk sh7372_extal2_clk;
-extern struct clk sh7372_dv_clki_clk;
-extern struct clk sh7372_dv_clki_div2_clk;
-extern struct clk sh7372_pllc2_clk;
-
-extern void sh7372_init_irq(void);
-extern void sh7372_map_io(void);
-extern void sh7372_earlytimer_init(void);
-extern void sh7372_add_early_devices(void);
-extern void sh7372_add_standard_devices(void);
-extern void sh7372_add_early_devices_dt(void);
-extern void sh7372_add_standard_devices_dt(void);
-extern void sh7372_clock_init(void);
-extern void sh7372_pinmux_init(void);
-extern void sh7372_pm_init(void);
-extern void sh7372_resume_core_standby_sysc(void);
-extern int  sh7372_do_idle_sysc(unsigned long sleep_mode);
-extern void sh7372_intcs_suspend(void);
-extern void sh7372_intcs_resume(void);
-extern void sh7372_intca_suspend(void);
-extern void sh7372_intca_resume(void);
-
-extern unsigned long sh7372_cpu_resume;
-
-#ifdef CONFIG_PM
-extern void __init sh7372_init_pm_domains(void);
-#else
-static inline void sh7372_init_pm_domains(void) {}
-#endif
-
-extern void __init sh7372_pm_init_late(void);
-
-#endif /* __ASM_SH7372_H__ */
index f037c64b14fc076749933eb2cef291500e56ee0a..5a80f18b4fa0665f375430afe6dd0cacaa66de62 100644 (file)
@@ -77,7 +77,6 @@ extern void sh73a0_map_io(void);
 extern void sh73a0_earlytimer_init(void);
 extern void sh73a0_add_early_devices(void);
 extern void sh73a0_add_standard_devices(void);
-extern void sh73a0_add_standard_devices_dt(void);
 extern void sh73a0_clock_init(void);
 extern void sh73a0_pinmux_init(void);
 extern void sh73a0_pm_init(void);
diff --git a/arch/arm/mach-shmobile/sleep-sh7372.S b/arch/arm/mach-shmobile/sleep-sh7372.S
deleted file mode 100644 (file)
index 146b8de..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * sh7372 lowlevel sleep code for "Core Standby Mode"
- *
- * Copyright (C) 2011 Magnus Damm
- *
- * In "Core Standby Mode" the ARM core is off, but L2 cache is still on
- *
- * Based on mach-omap2/sleep34xx.S
- *
- * (C) Copyright 2007 Texas Instruments
- * Karthik Dasu <karthik-dp@ti.com>
- *
- * (C) Copyright 2004 Texas Instruments, <www.ti.com>
- * Richard Woodruff <r-woodruff2@ti.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/linkage.h>
-#include <linux/init.h>
-#include <asm/memory.h>
-#include <asm/assembler.h>
-
-#if defined(CONFIG_SUSPEND) || defined(CONFIG_CPU_IDLE)
-       .align  12
-       .text
-       .global sh7372_resume_core_standby_sysc
-sh7372_resume_core_standby_sysc:
-       ldr     pc, 1f
-
-       .align  2
-       .globl  sh7372_cpu_resume
-sh7372_cpu_resume:
-1:     .space  4
-
-#define SPDCR 0xe6180008
-
-       /* A3SM & A4S power down */
-       .global sh7372_do_idle_sysc
-sh7372_do_idle_sysc:
-       mov     r8, r0 /* sleep mode passed in r0 */
-
-       /*
-        * Clear the SCTLR.C bit to prevent further data cache
-        * allocation. Clearing SCTLR.C would make all the data accesses
-        * strongly ordered and would not hit the cache.
-        */
-       mrc     p15, 0, r0, c1, c0, 0
-       bic     r0, r0, #(1 << 2)       @ Disable the C bit
-       mcr     p15, 0, r0, c1, c0, 0
-       isb
-
-       /*
-        * Clean and invalidate data cache again.
-        */
-       ldr     r1, kernel_flush
-       blx     r1
-
-       /* disable L2 cache in the aux control register */
-       mrc     p15, 0, r10, c1, c0, 1
-       bic     r10, r10, #2
-       mcr     p15, 0, r10, c1, c0, 1
-       isb
-
-       /*
-        * The kernel doesn't interwork: v7_flush_dcache_all in particluar will
-        * always return in Thumb state when CONFIG_THUMB2_KERNEL is enabled.
-        * This sequence switches back to ARM.  Note that .align may insert a
-        * nop: bx pc needs to be word-aligned in order to work.
-        */
- THUMB(        .thumb          )
- THUMB(        .align          )
- THUMB(        bx      pc      )
- THUMB(        nop             )
-       .arm
-
-       /* Data memory barrier and Data sync barrier */
-       dsb
-       dmb
-
-       /* SYSC power down */
-       ldr     r0, =SPDCR
-       str     r8, [r0]
-1:
-       b      1b
-
-       .align  2
-kernel_flush:
-       .word v7_flush_dcache_all
-#endif
index 9fc280e24ef49cfa5c7892be1bcceb5ef4879d4a..01f792fcb220188aa73043abc7f7ffc1f52c6432 100644 (file)
@@ -124,19 +124,12 @@ static int r8a7779_cpu_kill(unsigned int cpu)
 
        return 0;
 }
-
-static int r8a7779_cpu_disable(unsigned int cpu)
-{
-       /* only CPU1->3 have power domains, do not allow hotplug of CPU0 */
-       return cpu == 0 ? -EPERM : 0;
-}
 #endif /* CONFIG_HOTPLUG_CPU */
 
 struct smp_operations r8a7779_smp_ops  __initdata = {
        .smp_prepare_cpus       = r8a7779_smp_prepare_cpus,
        .smp_boot_secondary     = r8a7779_boot_secondary,
 #ifdef CONFIG_HOTPLUG_CPU
-       .cpu_disable            = r8a7779_cpu_disable,
        .cpu_die                = shmobile_smp_scu_cpu_die,
        .cpu_kill               = r8a7779_cpu_kill,
 #endif
index 9c3da1345b8b7eb45b778eb77e9a81cfed7f8cb4..930f45cbc08a5bb33677bbf02b5a2eb66b98d8ea 100644 (file)
@@ -23,6 +23,7 @@
 #include "common.h"
 #include "platsmp-apmu.h"
 #include "pm-rcar.h"
+#include "rcar-gen2.h"
 #include "r8a7790.h"
 
 static struct rcar_sysc_ch r8a7790_ca15_scu = {
@@ -37,11 +38,11 @@ static struct rcar_sysc_ch r8a7790_ca7_scu = {
 
 static struct rcar_apmu_config r8a7790_apmu_config[] = {
        {
-               .iomem = DEFINE_RES_MEM(0xe6152000, 0x88),
+               .iomem = DEFINE_RES_MEM(0xe6152000, 0x188),
                .cpus = { 0, 1, 2, 3 },
        },
        {
-               .iomem = DEFINE_RES_MEM(0xe6151000, 0x88),
+               .iomem = DEFINE_RES_MEM(0xe6151000, 0x188),
                .cpus = { 0x100, 0x0101, 0x102, 0x103 },
        }
 };
@@ -54,7 +55,7 @@ static void __init r8a7790_smp_prepare_cpus(unsigned int max_cpus)
                                       ARRAY_SIZE(r8a7790_apmu_config));
 
        /* turn on power to SCU */
-       r8a7790_pm_init();
+       rcar_gen2_pm_init();
        rcar_sysc_power_up(&r8a7790_ca15_scu);
        rcar_sysc_power_up(&r8a7790_ca7_scu);
 }
index 7e49e0a52e32a168de45abd40bcb174cae04989c..5e2d1db79afa5316152d031e7bb223d1465c6e57 100644 (file)
@@ -27,7 +27,7 @@
 
 static struct rcar_apmu_config r8a7791_apmu_config[] = {
        {
-               .iomem = DEFINE_RES_MEM(0xe6152000, 0x88),
+               .iomem = DEFINE_RES_MEM(0xe6152000, 0x188),
                .cpus = { 0, 1 },
        }
 };
@@ -39,7 +39,7 @@ static void __init r8a7791_smp_prepare_cpus(unsigned int max_cpus)
                                       r8a7791_apmu_config,
                                       ARRAY_SIZE(r8a7791_apmu_config));
 
-       r8a7791_pm_init();
+       rcar_gen2_pm_init();
 }
 
 static int r8a7791_smp_boot_secondary(unsigned int cpu,
index c16dbfe9836c527de5116c5620434ffb1ced2ef6..2106d6b76a06939238ad373486e408f7df12065f 100644 (file)
@@ -33,7 +33,7 @@
 
 #define SH73A0_SCU_BASE 0xf0000000
 
-#ifdef CONFIG_HAVE_ARM_TWD
+#if defined(CONFIG_HAVE_ARM_TWD) && !defined(CONFIG_ARCH_MULTIPLATFORM)
 static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, SH73A0_SCU_BASE + 0x600, 29);
 void __init sh73a0_register_twd(void)
 {
index 4be5379770407f75f501d98020478f6cb606f774..10f9389572da2e8a6fb9fb59824f3b8d3fea4c64 100644 (file)
@@ -54,7 +54,7 @@ config ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA
 config ARCH_VEXPRESS_DCSCB
        bool "Dual Cluster System Control Block (DCSCB) support"
        depends on MCPM
-       select ARM_CCI
+       select ARM_CCI400_PORT_CTRL
        help
          Support for the Dual Cluster System Configuration Block (DCSCB).
          This is needed to provide CPU and cluster power management
@@ -72,7 +72,7 @@ config ARCH_VEXPRESS_SPC
 config ARCH_VEXPRESS_TC2_PM
        bool "Versatile Express TC2 power management"
        depends on MCPM
-       select ARM_CCI
+       select ARM_CCI400_PORT_CTRL
        select ARCH_VEXPRESS_SPC
        select ARM_CPU_SUSPEND
        help
index 30b993399ed7758062f1f458b05d3fee2c9cd7b8..5cedcf572104bcdf82b1b75ab61f89f4cdf19651 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
-#include <linux/spinlock.h>
 #include <linux/errno.h>
 #include <linux/of_address.h>
 #include <linux/vexpress.h>
 #define KFC_CFG_W      0x2c
 #define DCS_CFG_R      0x30
 
-/*
- * We can't use regular spinlocks. In the switcher case, it is possible
- * for an outbound CPU to call power_down() while its inbound counterpart
- * is already live using the same logical CPU number which trips lockdep
- * debugging.
- */
-static arch_spinlock_t dcscb_lock = __ARCH_SPIN_LOCK_UNLOCKED;
-
 static void __iomem *dcscb_base;
-static int dcscb_use_count[4][2];
 static int dcscb_allcpus_mask[2];
 
-static int dcscb_power_up(unsigned int cpu, unsigned int cluster)
+static int dcscb_cpu_powerup(unsigned int cpu, unsigned int cluster)
 {
        unsigned int rst_hold, cpumask = (1 << cpu);
-       unsigned int all_mask;
 
        pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
-       if (cpu >= 4 || cluster >= 2)
+       if (cluster >= 2 || !(cpumask & dcscb_allcpus_mask[cluster]))
                return -EINVAL;
 
-       all_mask = dcscb_allcpus_mask[cluster];
+       rst_hold = readl_relaxed(dcscb_base + RST_HOLD0 + cluster * 4);
+       rst_hold &= ~(cpumask | (cpumask << 4));
+       writel_relaxed(rst_hold, dcscb_base + RST_HOLD0 + cluster * 4);
+       return 0;
+}
 
-       /*
-        * Since this is called with IRQs enabled, and no arch_spin_lock_irq
-        * variant exists, we need to disable IRQs manually here.
-        */
-       local_irq_disable();
-       arch_spin_lock(&dcscb_lock);
-
-       dcscb_use_count[cpu][cluster]++;
-       if (dcscb_use_count[cpu][cluster] == 1) {
-               rst_hold = readl_relaxed(dcscb_base + RST_HOLD0 + cluster * 4);
-               if (rst_hold & (1 << 8)) {
-                       /* remove cluster reset and add individual CPU's reset */
-                       rst_hold &= ~(1 << 8);
-                       rst_hold |= all_mask;
-               }
-               rst_hold &= ~(cpumask | (cpumask << 4));
-               writel_relaxed(rst_hold, dcscb_base + RST_HOLD0 + cluster * 4);
-       } else if (dcscb_use_count[cpu][cluster] != 2) {
-               /*
-                * The only possible values are:
-                * 0 = CPU down
-                * 1 = CPU (still) up
-                * 2 = CPU requested to be up before it had a chance
-                *     to actually make itself down.
-                * Any other value is a bug.
-                */
-               BUG();
-       }
+static int dcscb_cluster_powerup(unsigned int cluster)
+{
+       unsigned int rst_hold;
 
-       arch_spin_unlock(&dcscb_lock);
-       local_irq_enable();
+       pr_debug("%s: cluster %u\n", __func__, cluster);
+       if (cluster >= 2)
+               return -EINVAL;
 
+       /* remove cluster reset and add individual CPU's reset */
+       rst_hold = readl_relaxed(dcscb_base + RST_HOLD0 + cluster * 4);
+       rst_hold &= ~(1 << 8);
+       rst_hold |= dcscb_allcpus_mask[cluster];
+       writel_relaxed(rst_hold, dcscb_base + RST_HOLD0 + cluster * 4);
        return 0;
 }
 
-static void dcscb_power_down(void)
+static void dcscb_cpu_powerdown_prepare(unsigned int cpu, unsigned int cluster)
 {
-       unsigned int mpidr, cpu, cluster, rst_hold, cpumask, all_mask;
-       bool last_man = false, skip_wfi = false;
-
-       mpidr = read_cpuid_mpidr();
-       cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
-       cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
-       cpumask = (1 << cpu);
+       unsigned int rst_hold;
 
        pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
-       BUG_ON(cpu >= 4 || cluster >= 2);
-
-       all_mask = dcscb_allcpus_mask[cluster];
-
-       __mcpm_cpu_going_down(cpu, cluster);
-
-       arch_spin_lock(&dcscb_lock);
-       BUG_ON(__mcpm_cluster_state(cluster) != CLUSTER_UP);
-       dcscb_use_count[cpu][cluster]--;
-       if (dcscb_use_count[cpu][cluster] == 0) {
-               rst_hold = readl_relaxed(dcscb_base + RST_HOLD0 + cluster * 4);
-               rst_hold |= cpumask;
-               if (((rst_hold | (rst_hold >> 4)) & all_mask) == all_mask) {
-                       rst_hold |= (1 << 8);
-                       last_man = true;
-               }
-               writel_relaxed(rst_hold, dcscb_base + RST_HOLD0 + cluster * 4);
-       } else if (dcscb_use_count[cpu][cluster] == 1) {
-               /*
-                * A power_up request went ahead of us.
-                * Even if we do not want to shut this CPU down,
-                * the caller expects a certain state as if the WFI
-                * was aborted.  So let's continue with cache cleaning.
-                */
-               skip_wfi = true;
-       } else
-               BUG();
-
-       if (last_man && __mcpm_outbound_enter_critical(cpu, cluster)) {
-               arch_spin_unlock(&dcscb_lock);
-
-               /* Flush all cache levels for this cluster. */
-               v7_exit_coherency_flush(all);
-
-               /*
-                * A full outer cache flush could be needed at this point
-                * on platforms with such a cache, depending on where the
-                * outer cache sits. In some cases the notion of a "last
-                * cluster standing" would need to be implemented if the
-                * outer cache is shared across clusters. In any case, when
-                * the outer cache needs flushing, there is no concurrent
-                * access to the cache controller to worry about and no
-                * special locking besides what is already provided by the
-                * MCPM state machinery is needed.
-                */
-
-               /*
-                * Disable cluster-level coherency by masking
-                * incoming snoops and DVM messages:
-                */
-               cci_disable_port_by_cpu(mpidr);
-
-               __mcpm_outbound_leave_critical(cluster, CLUSTER_DOWN);
-       } else {
-               arch_spin_unlock(&dcscb_lock);
-
-               /* Disable and flush the local CPU cache. */
-               v7_exit_coherency_flush(louis);
-       }
+       BUG_ON(cluster >= 2 || !((1 << cpu) & dcscb_allcpus_mask[cluster]));
 
-       __mcpm_cpu_down(cpu, cluster);
+       rst_hold = readl_relaxed(dcscb_base + RST_HOLD0 + cluster * 4);
+       rst_hold |= (1 << cpu);
+       writel_relaxed(rst_hold, dcscb_base + RST_HOLD0 + cluster * 4);
+}
 
-       /* Now we are prepared for power-down, do it: */
-       dsb();
-       if (!skip_wfi)
-               wfi();
+static void dcscb_cluster_powerdown_prepare(unsigned int cluster)
+{
+       unsigned int rst_hold;
 
-       /* Not dead at this point?  Let our caller cope. */
+       pr_debug("%s: cluster %u\n", __func__, cluster);
+       BUG_ON(cluster >= 2);
+
+       rst_hold = readl_relaxed(dcscb_base + RST_HOLD0 + cluster * 4);
+       rst_hold |= (1 << 8);
+       writel_relaxed(rst_hold, dcscb_base + RST_HOLD0 + cluster * 4);
 }
 
-static const struct mcpm_platform_ops dcscb_power_ops = {
-       .power_up       = dcscb_power_up,
-       .power_down     = dcscb_power_down,
-};
+static void dcscb_cpu_cache_disable(void)
+{
+       /* Disable and flush the local CPU cache. */
+       v7_exit_coherency_flush(louis);
+}
 
-static void __init dcscb_usage_count_init(void)
+static void dcscb_cluster_cache_disable(void)
 {
-       unsigned int mpidr, cpu, cluster;
+       /* Flush all cache levels for this cluster. */
+       v7_exit_coherency_flush(all);
 
-       mpidr = read_cpuid_mpidr();
-       cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
-       cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+       /*
+        * A full outer cache flush could be needed at this point
+        * on platforms with such a cache, depending on where the
+        * outer cache sits. In some cases the notion of a "last
+        * cluster standing" would need to be implemented if the
+        * outer cache is shared across clusters. In any case, when
+        * the outer cache needs flushing, there is no concurrent
+        * access to the cache controller to worry about and no
+        * special locking besides what is already provided by the
+        * MCPM state machinery is needed.
+        */
 
-       pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
-       BUG_ON(cpu >= 4 || cluster >= 2);
-       dcscb_use_count[cpu][cluster] = 1;
+       /*
+        * Disable cluster-level coherency by masking
+        * incoming snoops and DVM messages:
+        */
+       cci_disable_port_by_cpu(read_cpuid_mpidr());
 }
 
+static const struct mcpm_platform_ops dcscb_power_ops = {
+       .cpu_powerup            = dcscb_cpu_powerup,
+       .cluster_powerup        = dcscb_cluster_powerup,
+       .cpu_powerdown_prepare  = dcscb_cpu_powerdown_prepare,
+       .cluster_powerdown_prepare = dcscb_cluster_powerdown_prepare,
+       .cpu_cache_disable      = dcscb_cpu_cache_disable,
+       .cluster_cache_disable  = dcscb_cluster_cache_disable,
+};
+
 extern void dcscb_power_up_setup(unsigned int affinity_level);
 
 static int __init dcscb_init(void)
@@ -213,7 +151,6 @@ static int __init dcscb_init(void)
        cfg = readl_relaxed(dcscb_base + DCS_CFG_R);
        dcscb_allcpus_mask[0] = (1 << (((cfg >> 16) >> (0 << 2)) & 0xf)) - 1;
        dcscb_allcpus_mask[1] = (1 << (((cfg >> 16) >> (1 << 2)) & 0xf)) - 1;
-       dcscb_usage_count_init();
 
        ret = mcpm_platform_register(&dcscb_power_ops);
        if (!ret)
index 2fb78b4648cba73620516a7cd52fcf95d45e40a8..b3328cd46c332b61d3981ed008947dbe45f8a1b2 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/kernel.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
-#include <linux/spinlock.h>
 #include <linux/errno.h>
 #include <linux/irqchip/arm-gic.h>
 
 
 static void __iomem *scc;
 
-/*
- * We can't use regular spinlocks. In the switcher case, it is possible
- * for an outbound CPU to call power_down() after its inbound counterpart
- * is already live using the same logical CPU number which trips lockdep
- * debugging.
- */
-static arch_spinlock_t tc2_pm_lock = __ARCH_SPIN_LOCK_UNLOCKED;
-
 #define TC2_CLUSTERS                   2
 #define TC2_MAX_CPUS_PER_CLUSTER       3
 
 static unsigned int tc2_nr_cpus[TC2_CLUSTERS];
 
-/* Keep per-cpu usage count to cope with unordered up/down requests */
-static int tc2_pm_use_count[TC2_MAX_CPUS_PER_CLUSTER][TC2_CLUSTERS];
-
-#define tc2_cluster_unused(cluster) \
-       (!tc2_pm_use_count[0][cluster] && \
-        !tc2_pm_use_count[1][cluster] && \
-        !tc2_pm_use_count[2][cluster])
-
-static int tc2_pm_power_up(unsigned int cpu, unsigned int cluster)
+static int tc2_pm_cpu_powerup(unsigned int cpu, unsigned int cluster)
 {
        pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
        if (cluster >= TC2_CLUSTERS || cpu >= tc2_nr_cpus[cluster])
                return -EINVAL;
-
-       /*
-        * Since this is called with IRQs enabled, and no arch_spin_lock_irq
-        * variant exists, we need to disable IRQs manually here.
-        */
-       local_irq_disable();
-       arch_spin_lock(&tc2_pm_lock);
-
-       if (tc2_cluster_unused(cluster))
-               ve_spc_powerdown(cluster, false);
-
-       tc2_pm_use_count[cpu][cluster]++;
-       if (tc2_pm_use_count[cpu][cluster] == 1) {
-               ve_spc_set_resume_addr(cluster, cpu,
-                                      virt_to_phys(mcpm_entry_point));
-               ve_spc_cpu_wakeup_irq(cluster, cpu, true);
-       } else if (tc2_pm_use_count[cpu][cluster] != 2) {
-               /*
-                * The only possible values are:
-                * 0 = CPU down
-                * 1 = CPU (still) up
-                * 2 = CPU requested to be up before it had a chance
-                *     to actually make itself down.
-                * Any other value is a bug.
-                */
-               BUG();
-       }
-
-       arch_spin_unlock(&tc2_pm_lock);
-       local_irq_enable();
-
+       ve_spc_set_resume_addr(cluster, cpu,
+                              virt_to_phys(mcpm_entry_point));
+       ve_spc_cpu_wakeup_irq(cluster, cpu, true);
        return 0;
 }
 
-static void tc2_pm_down(u64 residency)
+static int tc2_pm_cluster_powerup(unsigned int cluster)
 {
-       unsigned int mpidr, cpu, cluster;
-       bool last_man = false, skip_wfi = false;
-
-       mpidr = read_cpuid_mpidr();
-       cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
-       cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+       pr_debug("%s: cluster %u\n", __func__, cluster);
+       if (cluster >= TC2_CLUSTERS)
+               return -EINVAL;
+       ve_spc_powerdown(cluster, false);
+       return 0;
+}
 
+static void tc2_pm_cpu_powerdown_prepare(unsigned int cpu, unsigned int cluster)
+{
        pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
        BUG_ON(cluster >= TC2_CLUSTERS || cpu >= TC2_MAX_CPUS_PER_CLUSTER);
-
-       __mcpm_cpu_going_down(cpu, cluster);
-
-       arch_spin_lock(&tc2_pm_lock);
-       BUG_ON(__mcpm_cluster_state(cluster) != CLUSTER_UP);
-       tc2_pm_use_count[cpu][cluster]--;
-       if (tc2_pm_use_count[cpu][cluster] == 0) {
-               ve_spc_cpu_wakeup_irq(cluster, cpu, true);
-               if (tc2_cluster_unused(cluster)) {
-                       ve_spc_powerdown(cluster, true);
-                       ve_spc_global_wakeup_irq(true);
-                       last_man = true;
-               }
-       } else if (tc2_pm_use_count[cpu][cluster] == 1) {
-               /*
-                * A power_up request went ahead of us.
-                * Even if we do not want to shut this CPU down,
-                * the caller expects a certain state as if the WFI
-                * was aborted.  So let's continue with cache cleaning.
-                */
-               skip_wfi = true;
-       } else
-               BUG();
-
+       ve_spc_cpu_wakeup_irq(cluster, cpu, true);
        /*
         * If the CPU is committed to power down, make sure
         * the power controller will be in charge of waking it
@@ -146,55 +80,38 @@ static void tc2_pm_down(u64 residency)
         * to the CPU by disabling the GIC CPU IF to prevent wfi
         * from completing execution behind power controller back
         */
-       if (!skip_wfi)
-               gic_cpu_if_down();
-
-       if (last_man && __mcpm_outbound_enter_critical(cpu, cluster)) {
-               arch_spin_unlock(&tc2_pm_lock);
-
-               if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A15) {
-                       /*
-                        * On the Cortex-A15 we need to disable
-                        * L2 prefetching before flushing the cache.
-                        */
-                       asm volatile(
-                       "mcr    p15, 1, %0, c15, c0, 3 \n\t"
-                       "isb    \n\t"
-                       "dsb    "
-                       : : "r" (0x400) );
-               }
-
-               v7_exit_coherency_flush(all);
-
-               cci_disable_port_by_cpu(mpidr);
-
-               __mcpm_outbound_leave_critical(cluster, CLUSTER_DOWN);
-       } else {
-               /*
-                * If last man then undo any setup done previously.
-                */
-               if (last_man) {
-                       ve_spc_powerdown(cluster, false);
-                       ve_spc_global_wakeup_irq(false);
-               }
-
-               arch_spin_unlock(&tc2_pm_lock);
-
-               v7_exit_coherency_flush(louis);
-       }
-
-       __mcpm_cpu_down(cpu, cluster);
+       gic_cpu_if_down();
+}
 
-       /* Now we are prepared for power-down, do it: */
-       if (!skip_wfi)
-               wfi();
+static void tc2_pm_cluster_powerdown_prepare(unsigned int cluster)
+{
+       pr_debug("%s: cluster %u\n", __func__, cluster);
+       BUG_ON(cluster >= TC2_CLUSTERS);
+       ve_spc_powerdown(cluster, true);
+       ve_spc_global_wakeup_irq(true);
+}
 
-       /* Not dead at this point?  Let our caller cope. */
+static void tc2_pm_cpu_cache_disable(void)
+{
+       v7_exit_coherency_flush(louis);
 }
 
-static void tc2_pm_power_down(void)
+static void tc2_pm_cluster_cache_disable(void)
 {
-       tc2_pm_down(0);
+       if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A15) {
+               /*
+                * On the Cortex-A15 we need to disable
+                * L2 prefetching before flushing the cache.
+                */
+               asm volatile(
+               "mcr    p15, 1, %0, c15, c0, 3 \n\t"
+               "isb    \n\t"
+               "dsb    "
+               : : "r" (0x400) );
+       }
+
+       v7_exit_coherency_flush(all);
+       cci_disable_port_by_cpu(read_cpuid_mpidr());
 }
 
 static int tc2_core_in_reset(unsigned int cpu, unsigned int cluster)
@@ -217,27 +134,21 @@ static int tc2_pm_wait_for_powerdown(unsigned int cpu, unsigned int cluster)
        BUG_ON(cluster >= TC2_CLUSTERS || cpu >= TC2_MAX_CPUS_PER_CLUSTER);
 
        for (tries = 0; tries < TIMEOUT_MSEC / POLL_MSEC; ++tries) {
+               pr_debug("%s(cpu=%u, cluster=%u): RESET_CTRL = 0x%08X\n",
+                        __func__, cpu, cluster,
+                        readl_relaxed(scc + RESET_CTRL));
+
                /*
-                * Only examine the hardware state if the target CPU has
-                * caught up at least as far as tc2_pm_down():
+                * We need the CPU to reach WFI, but the power
+                * controller may put the cluster in reset and
+                * power it off as soon as that happens, before
+                * we have a chance to see STANDBYWFI.
+                *
+                * So we need to check for both conditions:
                 */
-               if (ACCESS_ONCE(tc2_pm_use_count[cpu][cluster]) == 0) {
-                       pr_debug("%s(cpu=%u, cluster=%u): RESET_CTRL = 0x%08X\n",
-                                __func__, cpu, cluster,
-                                readl_relaxed(scc + RESET_CTRL));
-
-                       /*
-                        * We need the CPU to reach WFI, but the power
-                        * controller may put the cluster in reset and
-                        * power it off as soon as that happens, before
-                        * we have a chance to see STANDBYWFI.
-                        *
-                        * So we need to check for both conditions:
-                        */
-                       if (tc2_core_in_reset(cpu, cluster) ||
-                           ve_spc_cpu_in_wfi(cpu, cluster))
-                               return 0; /* success: the CPU is halted */
-               }
+               if (tc2_core_in_reset(cpu, cluster) ||
+                   ve_spc_cpu_in_wfi(cpu, cluster))
+                       return 0; /* success: the CPU is halted */
 
                /* Otherwise, wait and retry: */
                msleep(POLL_MSEC);
@@ -246,72 +157,40 @@ static int tc2_pm_wait_for_powerdown(unsigned int cpu, unsigned int cluster)
        return -ETIMEDOUT; /* timeout */
 }
 
-static void tc2_pm_suspend(u64 residency)
+static void tc2_pm_cpu_suspend_prepare(unsigned int cpu, unsigned int cluster)
 {
-       unsigned int mpidr, cpu, cluster;
-
-       mpidr = read_cpuid_mpidr();
-       cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
-       cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
        ve_spc_set_resume_addr(cluster, cpu, virt_to_phys(mcpm_entry_point));
-       tc2_pm_down(residency);
 }
 
-static void tc2_pm_powered_up(void)
+static void tc2_pm_cpu_is_up(unsigned int cpu, unsigned int cluster)
 {
-       unsigned int mpidr, cpu, cluster;
-       unsigned long flags;
-
-       mpidr = read_cpuid_mpidr();
-       cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
-       cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
-
        pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
        BUG_ON(cluster >= TC2_CLUSTERS || cpu >= TC2_MAX_CPUS_PER_CLUSTER);
-
-       local_irq_save(flags);
-       arch_spin_lock(&tc2_pm_lock);
-
-       if (tc2_cluster_unused(cluster)) {
-               ve_spc_powerdown(cluster, false);
-               ve_spc_global_wakeup_irq(false);
-       }
-
-       if (!tc2_pm_use_count[cpu][cluster])
-               tc2_pm_use_count[cpu][cluster] = 1;
-
        ve_spc_cpu_wakeup_irq(cluster, cpu, false);
        ve_spc_set_resume_addr(cluster, cpu, 0);
+}
 
-       arch_spin_unlock(&tc2_pm_lock);
-       local_irq_restore(flags);
+static void tc2_pm_cluster_is_up(unsigned int cluster)
+{
+       pr_debug("%s: cluster %u\n", __func__, cluster);
+       BUG_ON(cluster >= TC2_CLUSTERS);
+       ve_spc_powerdown(cluster, false);
+       ve_spc_global_wakeup_irq(false);
 }
 
 static const struct mcpm_platform_ops tc2_pm_power_ops = {
-       .power_up               = tc2_pm_power_up,
-       .power_down             = tc2_pm_power_down,
+       .cpu_powerup            = tc2_pm_cpu_powerup,
+       .cluster_powerup        = tc2_pm_cluster_powerup,
+       .cpu_suspend_prepare    = tc2_pm_cpu_suspend_prepare,
+       .cpu_powerdown_prepare  = tc2_pm_cpu_powerdown_prepare,
+       .cluster_powerdown_prepare = tc2_pm_cluster_powerdown_prepare,
+       .cpu_cache_disable      = tc2_pm_cpu_cache_disable,
+       .cluster_cache_disable  = tc2_pm_cluster_cache_disable,
        .wait_for_powerdown     = tc2_pm_wait_for_powerdown,
-       .suspend                = tc2_pm_suspend,
-       .powered_up             = tc2_pm_powered_up,
+       .cpu_is_up              = tc2_pm_cpu_is_up,
+       .cluster_is_up          = tc2_pm_cluster_is_up,
 };
 
-static bool __init tc2_pm_usage_count_init(void)
-{
-       unsigned int mpidr, cpu, cluster;
-
-       mpidr = read_cpuid_mpidr();
-       cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
-       cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
-
-       pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
-       if (cluster >= TC2_CLUSTERS || cpu >= tc2_nr_cpus[cluster]) {
-               pr_err("%s: boot CPU is out of bound!\n", __func__);
-               return false;
-       }
-       tc2_pm_use_count[cpu][cluster] = 1;
-       return true;
-}
-
 /*
  * Enable cluster-level coherency, in preparation for turning on the MMU.
  */
@@ -323,23 +202,9 @@ static void __naked tc2_pm_power_up_setup(unsigned int affinity_level)
 "      b       cci_enable_port_for_self ");
 }
 
-static void __init tc2_cache_off(void)
-{
-       pr_info("TC2: disabling cache during MCPM loopback test\n");
-       if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A15) {
-               /* disable L2 prefetching on the Cortex-A15 */
-               asm volatile(
-               "mcr    p15, 1, %0, c15, c0, 3 \n\t"
-               "isb    \n\t"
-               "dsb    "
-               : : "r" (0x400) );
-       }
-       v7_exit_coherency_flush(all);
-       cci_disable_port_by_cpu(read_cpuid_mpidr());
-}
-
 static int __init tc2_pm_init(void)
 {
+       unsigned int mpidr, cpu, cluster;
        int ret, irq;
        u32 a15_cluster_id, a7_cluster_id, sys_info;
        struct device_node *np;
@@ -379,14 +244,20 @@ static int __init tc2_pm_init(void)
        if (!cci_probed())
                return -ENODEV;
 
-       if (!tc2_pm_usage_count_init())
+       mpidr = read_cpuid_mpidr();
+       cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
+       cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
+       pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
+       if (cluster >= TC2_CLUSTERS || cpu >= tc2_nr_cpus[cluster]) {
+               pr_err("%s: boot CPU is out of bound!\n", __func__);
                return -EINVAL;
+       }
 
        ret = mcpm_platform_register(&tc2_pm_power_ops);
        if (!ret) {
                mcpm_sync_init(tc2_pm_power_up_setup);
                /* test if we can (re)enable the CCI on our own */
-               BUG_ON(mcpm_loopback(tc2_cache_off) != 0);
+               BUG_ON(mcpm_loopback(tc2_pm_cluster_cache_disable) != 0);
                pr_info("TC2 power management initialized\n");
        }
        return ret;
index b7644310236b1748c97da4196e5c473791a32a16..b4f92b9a13ac85c1c425542ff50b6df2783b3c50 100644 (file)
@@ -827,7 +827,7 @@ config KUSER_HELPERS
 
 config VDSO
        bool "Enable VDSO for acceleration of some system calls"
-       depends on AEABI && MMU
+       depends on AEABI && MMU && CPU_V7
        default y if ARM_ARCH_TIMER
        select GENERIC_TIME_VSYSCALL
        help
index e17d871b934cc36a5998312b448e8ff54ef80b7a..7f415ce74591487b3d4c3c689184b37fc7b49134 100644 (file)
@@ -43,7 +43,11 @@ extern unsigned long s3c_irqwake_eintmask;
 
 /* IRQ masks for IRQs allowed to go to sleep (see irq.c) */
 extern unsigned long s3c_irqwake_intallow;
+#ifdef CONFIG_PM_SLEEP
 extern unsigned long s3c_irqwake_eintallow;
+#else
+#define s3c_irqwake_eintallow 0
+#endif
 
 /* per-cpu sleep functions */
 
@@ -58,16 +62,20 @@ extern unsigned long s3c_pm_flags;
 
 extern int s3c2410_cpu_suspend(unsigned long);
 
-#ifdef CONFIG_SAMSUNG_PM
+#ifdef CONFIG_PM_SLEEP
 extern int s3c_irq_wake(struct irq_data *data, unsigned int state);
-extern int s3c_irqext_wake(struct irq_data *data, unsigned int state);
 extern void s3c_cpu_resume(void);
 #else
 #define s3c_irq_wake NULL
-#define s3c_irqext_wake NULL
 #define s3c_cpu_resume NULL
 #endif
 
+#ifdef CONFIG_SAMSUNG_PM
+extern int s3c_irqext_wake(struct irq_data *data, unsigned int state);
+#else
+#define s3c_irqext_wake NULL
+#endif
+
 #ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
 /**
  * s3c_pm_debug_smdkled() - Debug PM suspend/resume via SMDK Board LEDs
index 39609601f407fdc1b0f5891e23646ce45207fc6f..64e15da33b4258f332aa58261e7595802ebe47ae 100644 (file)
@@ -23,6 +23,7 @@
 #include <plat/pm-common.h>
 
 #ifdef CONFIG_SAMSUNG_ATAGS
+#include <plat/pm.h>
 #include <mach/pm-core.h>
 #else
 static inline void s3c_pm_debug_init_uart(void) {}
index f8c0f9797dcf4f0f5d041fa9c5a76895d13cf16e..82777c649774a78062aff6fe802d780059567bfc 100644 (file)
@@ -65,26 +65,6 @@ int s3c_irqext_wake(struct irq_data *data, unsigned int state)
        return 0;
 }
 
-/* s3c2410_pm_show_resume_irqs
- *
- * print any IRQs asserted at resume time (ie, we woke from)
-*/
-static void __maybe_unused s3c_pm_show_resume_irqs(int start,
-                                                  unsigned long which,
-                                                  unsigned long mask)
-{
-       int i;
-
-       which &= ~mask;
-
-       for (i = 0; i <= 31; i++) {
-               if (which & (1L<<i)) {
-                       S3C_PMDBG("IRQ %d asserted at resume\n", start+i);
-               }
-       }
-}
-
-
 void (*pm_cpu_prep)(void);
 int (*pm_cpu_sleep)(unsigned long);
 
index a10297da122b75b270432bd8a9d2fb627507687e..2ed1b8a922ed02b9e3545991873af77b4c1bf871 100644 (file)
@@ -526,7 +526,6 @@ ag5evm                      MACH_AG5EVM             AG5EVM                  3189
 ics_if_voip            MACH_ICS_IF_VOIP        ICS_IF_VOIP             3206
 wlf_cragg_6410         MACH_WLF_CRAGG_6410     WLF_CRAGG_6410          3207
 trimslice              MACH_TRIMSLICE          TRIMSLICE               3209
-mackerel               MACH_MACKEREL           MACKEREL                3211
 kaen                   MACH_KAEN               KAEN                    3217
 nokia_rm680            MACH_NOKIA_RM680        NOKIA_RM680             3220
 msm8960_sim            MACH_MSM8960_SIM        MSM8960_SIM             3230
index f8b69d84238eb4f7743c23b425e1a4900cb9cd7f..6b47f6e0b03281bf4d385a34ae7bf480059ed91b 100644 (file)
@@ -1 +1,3 @@
 vdso.lds
+vdso.so.raw
+vdsomunge
index bab0a8be79247121bf20006254d49fbc943f3ba0..8aa7910510299b0dd6e10190209c330285de2449 100644 (file)
@@ -10,8 +10,8 @@ ccflags-y := -shared -fPIC -fno-common -fno-builtin -fno-stack-protector
 ccflags-y += -nostdlib -Wl,-soname=linux-vdso.so.1 -DDISABLE_BRANCH_PROFILING
 ccflags-y += -Wl,--no-undefined $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
 
-obj-y += vdso.o
-extra-y += vdso.lds
+obj-$(CONFIG_VDSO) += vdso.o
+extra-$(CONFIG_VDSO) += vdso.lds
 CPPFLAGS_vdso.lds += -P -C -U$(ARCH)
 
 CFLAGS_REMOVE_vdso.o = -pg
index 793551d15f1dac1a1241b23971a788b4c36702b6..498325074a06fa911a5cfa9f37137c7936f8b9c4 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/gfp.h>
 #include <linux/highmem.h>
 #include <linux/export.h>
+#include <linux/memblock.h>
 #include <linux/of_address.h>
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <asm/xen/hypercall.h>
 #include <asm/xen/interface.h>
 
+unsigned long xen_get_swiotlb_free_pages(unsigned int order)
+{
+       struct memblock_region *reg;
+       gfp_t flags = __GFP_NOWARN;
+
+       for_each_memblock(memory, reg) {
+               if (reg->base < (phys_addr_t)0xffffffff) {
+                       flags |= __GFP_DMA;
+                       break;
+               }
+       }
+       return __get_free_pages(flags, order);
+}
+
 enum dma_cache_op {
        DMA_UNMAP,
        DMA_MAP,
index b8d96f1554af11aef71af0627278925f244067a9..7796af4b1d6f65f6352ed40cd6dfcaf580cfd63d 100644 (file)
@@ -1,5 +1,7 @@
 config ARM64
        def_bool y
+       select ACPI_GENERIC_GSI if ACPI
+       select ACPI_REDUCED_HARDWARE_ONLY if ACPI
        select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
        select ARCH_HAS_ELF_RANDOMIZE
        select ARCH_HAS_GCOV_PROFILE_ALL
@@ -29,6 +31,7 @@ config ARM64
        select GENERIC_EARLY_IOREMAP
        select GENERIC_IRQ_PROBE
        select GENERIC_IRQ_SHOW
+       select GENERIC_IRQ_SHOW_LEVEL
        select GENERIC_PCI_IOMAP
        select GENERIC_SCHED_CLOCK
        select GENERIC_SMP_IDLE_THREAD
@@ -181,9 +184,16 @@ config ARCH_FSL_LS2085A
 config ARCH_MEDIATEK
        bool "Mediatek MT65xx & MT81xx ARMv8 SoC"
        select ARM_GIC
+       select PINCTRL
        help
          Support for Mediatek MT65xx & MT81xx ARMv8 SoCs
 
+config ARCH_QCOM
+       bool "Qualcomm Platforms"
+       select PINCTRL
+       help
+         This enables support for the ARMv8 based Qualcomm chipsets.
+
 config ARCH_SEATTLE
        bool "AMD Seattle SoC Family"
        help
@@ -215,6 +225,11 @@ config ARCH_TEGRA_132_SOC
          but contains an NVIDIA Denver CPU complex in place of
          Tegra124's "4+1" Cortex-A15 CPU complex.
 
+config ARCH_SPRD
+       bool "Spreadtrum SoC platform"
+       help
+         Support for Spreadtrum ARM based SoCs
+
 config ARCH_THUNDER
        bool "Cavium Inc. Thunder SoC Family"
        help
@@ -235,6 +250,11 @@ config ARCH_XGENE
        help
          This enables support for AppliedMicro X-Gene SOC Family
 
+config ARCH_ZYNQMP
+       bool "Xilinx ZynqMP Family"
+       help
+         This enables support for Xilinx ZynqMP Family
+
 endmenu
 
 menu "Bus support"
@@ -741,6 +761,8 @@ source "drivers/Kconfig"
 
 source "drivers/firmware/Kconfig"
 
+source "drivers/acpi/Kconfig"
+
 source "fs/Kconfig"
 
 source "arch/arm64/kvm/Kconfig"
index 4a8741073c90c0585772cff64093b9f3f0e63aa9..d6285ef9b5f976639630606b04d7244a05ac6130 100644 (file)
@@ -89,4 +89,6 @@ config DEBUG_ALIGN_RODATA
 
          If in doubt, say N
 
+source "drivers/hwtracing/coresight/Kconfig"
+
 endmenu
index e0350caf049e72f25db374e90b198223e74fd544..ad26a752b976ad5e961255029e3638d7c173323c 100644 (file)
@@ -5,5 +5,8 @@ dts-dirs += cavium
 dts-dirs += exynos
 dts-dirs += freescale
 dts-dirs += mediatek
+dts-dirs += qcom
+dts-dirs += sprd
+dts-dirs += xilinx
 
 subdir-y       := $(dts-dirs)
index e74f6e0a208ccbf584d2b2d61c98d3d0f1d169e2..c8d3e0e866787bcbe7ac1d72b370d20927a15a5d 100644 (file)
                #address-cells = <2>;
                #size-cells = <2>;
                ranges;
+               dma-ranges = <0x0 0x0 0x0 0x0 0x400 0x0>;
 
                clocks {
                        #address-cells = <2>;
                                reg-names = "csr-reg";
                                clock-output-names = "pcie4clk";
                        };
+
+                       dmaclk: dmaclk@1f27c000 {
+                               compatible = "apm,xgene-device-clock";
+                               #clock-cells = <1>;
+                               clocks = <&socplldiv2 0>;
+                               reg = <0x0 0x1f27c000 0x0 0x1000>;
+                               reg-names = "csr-reg";
+                               clock-output-names = "dmaclk";
+                       };
                };
 
                pcie0: pcie@1f2b0000 {
                        interrupts = <0x0 0x41 0x4>;
                        clocks = <&rngpkaclk 0>;
                };
+
+               dma: dma@1f270000 {
+                       compatible = "apm,xgene-storm-dma";
+                       device_type = "dma";
+                       reg = <0x0 0x1f270000 0x0 0x10000>,
+                             <0x0 0x1f200000 0x0 0x10000>,
+                             <0x0 0x1b008000 0x0 0x2000>,
+                             <0x0 0x1054a000 0x0 0x100>;
+                       interrupts = <0x0 0x82 0x4>,
+                                    <0x0 0xb8 0x4>,
+                                    <0x0 0xb9 0x4>,
+                                    <0x0 0xba 0x4>,
+                                    <0x0 0xbb 0x4>;
+                       dma-coherent;
+                       clocks = <&dmaclk 0>;
+               };
        };
 };
index 133ee59de2d70672db3ca648952006cdfae7c7cb..5e9110a3353da48e24b3be0d77f15ceb0d3cdd6e 100644 (file)
 
        pmu {
                compatible = "arm,armv8-pmuv3";
-               interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
+               interrupts = <GIC_SPI 02 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 06 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
                             <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>,
                             <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>,
-                            <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>,
-                            <GIC_SPI 02 IRQ_TYPE_LEVEL_HIGH>,
-                            <GIC_SPI 06 IRQ_TYPE_LEVEL_HIGH>;
+                            <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-affinity = <&A57_0>,
+                                    <&A57_1>,
+                                    <&A53_0>,
+                                    <&A53_1>,
+                                    <&A53_2>,
+                                    <&A53_3>;
        };
 
        /include/ "juno-clocks.dtsi"
diff --git a/arch/arm64/boot/dts/mediatek/mt8173-pinfunc.h b/arch/arm64/boot/dts/mediatek/mt8173-pinfunc.h
new file mode 100644 (file)
index 0000000..d2f3809
--- /dev/null
@@ -0,0 +1,682 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Hongzhou.Yang <hongzhou.yang@mediatek.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.
+ */
+
+#ifndef __DTS_MT8173_PINFUNC_H
+#define __DTS_MT8173_PINFUNC_H
+
+#include <dt-bindings/pinctrl/mt65xx.h>
+
+#define MT8173_PIN_0_EINT0__FUNC_GPIO0 (MTK_PIN_NO(0) | 0)
+#define MT8173_PIN_0_EINT0__FUNC_IRDA_PDN (MTK_PIN_NO(0) | 1)
+#define MT8173_PIN_0_EINT0__FUNC_I2S1_WS (MTK_PIN_NO(0) | 2)
+#define MT8173_PIN_0_EINT0__FUNC_AUD_SPDIF (MTK_PIN_NO(0) | 3)
+#define MT8173_PIN_0_EINT0__FUNC_UTXD0 (MTK_PIN_NO(0) | 4)
+#define MT8173_PIN_0_EINT0__FUNC_DBG_MON_A_20_ (MTK_PIN_NO(0) | 7)
+
+#define MT8173_PIN_1_EINT1__FUNC_GPIO1 (MTK_PIN_NO(1) | 0)
+#define MT8173_PIN_1_EINT1__FUNC_IRDA_RXD (MTK_PIN_NO(1) | 1)
+#define MT8173_PIN_1_EINT1__FUNC_I2S1_BCK (MTK_PIN_NO(1) | 2)
+#define MT8173_PIN_1_EINT1__FUNC_SDA5 (MTK_PIN_NO(1) | 3)
+#define MT8173_PIN_1_EINT1__FUNC_URXD0 (MTK_PIN_NO(1) | 4)
+#define MT8173_PIN_1_EINT1__FUNC_DBG_MON_A_21_ (MTK_PIN_NO(1) | 7)
+
+#define MT8173_PIN_2_EINT2__FUNC_GPIO2 (MTK_PIN_NO(2) | 0)
+#define MT8173_PIN_2_EINT2__FUNC_IRDA_TXD (MTK_PIN_NO(2) | 1)
+#define MT8173_PIN_2_EINT2__FUNC_I2S1_MCK (MTK_PIN_NO(2) | 2)
+#define MT8173_PIN_2_EINT2__FUNC_SCL5 (MTK_PIN_NO(2) | 3)
+#define MT8173_PIN_2_EINT2__FUNC_UTXD3 (MTK_PIN_NO(2) | 4)
+#define MT8173_PIN_2_EINT2__FUNC_DBG_MON_A_22_ (MTK_PIN_NO(2) | 7)
+
+#define MT8173_PIN_3_EINT3__FUNC_GPIO3 (MTK_PIN_NO(3) | 0)
+#define MT8173_PIN_3_EINT3__FUNC_DSI1_TE (MTK_PIN_NO(3) | 1)
+#define MT8173_PIN_3_EINT3__FUNC_I2S1_DO_1 (MTK_PIN_NO(3) | 2)
+#define MT8173_PIN_3_EINT3__FUNC_SDA3 (MTK_PIN_NO(3) | 3)
+#define MT8173_PIN_3_EINT3__FUNC_URXD3 (MTK_PIN_NO(3) | 4)
+#define MT8173_PIN_3_EINT3__FUNC_DBG_MON_A_23_ (MTK_PIN_NO(3) | 7)
+
+#define MT8173_PIN_4_EINT4__FUNC_GPIO4 (MTK_PIN_NO(4) | 0)
+#define MT8173_PIN_4_EINT4__FUNC_DISP_PWM1 (MTK_PIN_NO(4) | 1)
+#define MT8173_PIN_4_EINT4__FUNC_I2S1_DO_2 (MTK_PIN_NO(4) | 2)
+#define MT8173_PIN_4_EINT4__FUNC_SCL3 (MTK_PIN_NO(4) | 3)
+#define MT8173_PIN_4_EINT4__FUNC_UCTS3 (MTK_PIN_NO(4) | 4)
+#define MT8173_PIN_4_EINT4__FUNC_SFWP_B (MTK_PIN_NO(4) | 6)
+
+#define MT8173_PIN_5_EINT5__FUNC_GPIO5 (MTK_PIN_NO(5) | 0)
+#define MT8173_PIN_5_EINT5__FUNC_PCM1_CLK (MTK_PIN_NO(5) | 1)
+#define MT8173_PIN_5_EINT5__FUNC_I2S2_WS (MTK_PIN_NO(5) | 2)
+#define MT8173_PIN_5_EINT5__FUNC_SPI_CK_3_ (MTK_PIN_NO(5) | 3)
+#define MT8173_PIN_5_EINT5__FUNC_URTS3 (MTK_PIN_NO(5) | 4)
+#define MT8173_PIN_5_EINT5__FUNC_AP_MD32_JTAG_TMS (MTK_PIN_NO(5) | 5)
+#define MT8173_PIN_5_EINT5__FUNC_SFOUT (MTK_PIN_NO(5) | 6)
+
+#define MT8173_PIN_6_EINT6__FUNC_GPIO6 (MTK_PIN_NO(6) | 0)
+#define MT8173_PIN_6_EINT6__FUNC_PCM1_SYNC (MTK_PIN_NO(6) | 1)
+#define MT8173_PIN_6_EINT6__FUNC_I2S2_BCK (MTK_PIN_NO(6) | 2)
+#define MT8173_PIN_6_EINT6__FUNC_SPI_MI_3_ (MTK_PIN_NO(6) | 3)
+#define MT8173_PIN_6_EINT6__FUNC_AP_MD32_JTAG_TCK (MTK_PIN_NO(6) | 5)
+#define MT8173_PIN_6_EINT6__FUNC_SFCS0 (MTK_PIN_NO(6) | 6)
+
+#define MT8173_PIN_7_EINT7__FUNC_GPIO7 (MTK_PIN_NO(7) | 0)
+#define MT8173_PIN_7_EINT7__FUNC_PCM1_DI (MTK_PIN_NO(7) | 1)
+#define MT8173_PIN_7_EINT7__FUNC_I2S2_DI_1 (MTK_PIN_NO(7) | 2)
+#define MT8173_PIN_7_EINT7__FUNC_SPI_MO_3_ (MTK_PIN_NO(7) | 3)
+#define MT8173_PIN_7_EINT7__FUNC_AP_MD32_JTAG_TDI (MTK_PIN_NO(7) | 5)
+#define MT8173_PIN_7_EINT7__FUNC_SFHOLD (MTK_PIN_NO(7) | 6)
+
+#define MT8173_PIN_8_EINT8__FUNC_GPIO8 (MTK_PIN_NO(8) | 0)
+#define MT8173_PIN_8_EINT8__FUNC_PCM1_DO (MTK_PIN_NO(8) | 1)
+#define MT8173_PIN_8_EINT8__FUNC_I2S2_DI_2 (MTK_PIN_NO(8) | 2)
+#define MT8173_PIN_8_EINT8__FUNC_SPI_CS_3_ (MTK_PIN_NO(8) | 3)
+#define MT8173_PIN_8_EINT8__FUNC_AUD_SPDIF (MTK_PIN_NO(8) | 4)
+#define MT8173_PIN_8_EINT8__FUNC_AP_MD32_JTAG_TDO (MTK_PIN_NO(8) | 5)
+#define MT8173_PIN_8_EINT8__FUNC_SFIN (MTK_PIN_NO(8) | 6)
+
+#define MT8173_PIN_9_EINT9__FUNC_GPIO9 (MTK_PIN_NO(9) | 0)
+#define MT8173_PIN_9_EINT9__FUNC_USB_DRVVBUS_P0 (MTK_PIN_NO(9) | 1)
+#define MT8173_PIN_9_EINT9__FUNC_I2S2_MCK (MTK_PIN_NO(9) | 2)
+#define MT8173_PIN_9_EINT9__FUNC_USB_DRVVBUS_P1 (MTK_PIN_NO(9) | 4)
+#define MT8173_PIN_9_EINT9__FUNC_AP_MD32_JTAG_TRST (MTK_PIN_NO(9) | 5)
+#define MT8173_PIN_9_EINT9__FUNC_SFCK (MTK_PIN_NO(9) | 6)
+
+#define MT8173_PIN_10_EINT10__FUNC_GPIO10 (MTK_PIN_NO(10) | 0)
+#define MT8173_PIN_10_EINT10__FUNC_CLKM0 (MTK_PIN_NO(10) | 1)
+#define MT8173_PIN_10_EINT10__FUNC_DSI1_TE (MTK_PIN_NO(10) | 2)
+#define MT8173_PIN_10_EINT10__FUNC_DISP_PWM1 (MTK_PIN_NO(10) | 3)
+#define MT8173_PIN_10_EINT10__FUNC_PWM4 (MTK_PIN_NO(10) | 4)
+#define MT8173_PIN_10_EINT10__FUNC_IRDA_RXD (MTK_PIN_NO(10) | 5)
+
+#define MT8173_PIN_11_EINT11__FUNC_GPIO11 (MTK_PIN_NO(11) | 0)
+#define MT8173_PIN_11_EINT11__FUNC_CLKM1 (MTK_PIN_NO(11) | 1)
+#define MT8173_PIN_11_EINT11__FUNC_I2S3_WS (MTK_PIN_NO(11) | 2)
+#define MT8173_PIN_11_EINT11__FUNC_USB_DRVVBUS_P0 (MTK_PIN_NO(11) | 3)
+#define MT8173_PIN_11_EINT11__FUNC_PWM5 (MTK_PIN_NO(11) | 4)
+#define MT8173_PIN_11_EINT11__FUNC_IRDA_TXD (MTK_PIN_NO(11) | 5)
+#define MT8173_PIN_11_EINT11__FUNC_USB_DRVVBUS_P1 (MTK_PIN_NO(11) | 6)
+#define MT8173_PIN_11_EINT11__FUNC_DBG_MON_B_30_ (MTK_PIN_NO(11) | 7)
+
+#define MT8173_PIN_12_EINT12__FUNC_GPIO12 (MTK_PIN_NO(12) | 0)
+#define MT8173_PIN_12_EINT12__FUNC_CLKM2 (MTK_PIN_NO(12) | 1)
+#define MT8173_PIN_12_EINT12__FUNC_I2S3_BCK (MTK_PIN_NO(12) | 2)
+#define MT8173_PIN_12_EINT12__FUNC_SRCLKENA0 (MTK_PIN_NO(12) | 3)
+#define MT8173_PIN_12_EINT12__FUNC_I2S2_WS (MTK_PIN_NO(12) | 5)
+#define MT8173_PIN_12_EINT12__FUNC_DBG_MON_B_32_ (MTK_PIN_NO(12) | 7)
+
+#define MT8173_PIN_13_EINT13__FUNC_GPIO13 (MTK_PIN_NO(13) | 0)
+#define MT8173_PIN_13_EINT13__FUNC_CLKM3 (MTK_PIN_NO(13) | 1)
+#define MT8173_PIN_13_EINT13__FUNC_I2S3_MCK (MTK_PIN_NO(13) | 2)
+#define MT8173_PIN_13_EINT13__FUNC_SRCLKENA0 (MTK_PIN_NO(13) | 3)
+#define MT8173_PIN_13_EINT13__FUNC_I2S2_BCK (MTK_PIN_NO(13) | 5)
+#define MT8173_PIN_13_EINT13__FUNC_DBG_MON_A_32_ (MTK_PIN_NO(13) | 7)
+
+#define MT8173_PIN_14_EINT14__FUNC_GPIO14 (MTK_PIN_NO(14) | 0)
+#define MT8173_PIN_14_EINT14__FUNC_CMDAT0 (MTK_PIN_NO(14) | 1)
+#define MT8173_PIN_14_EINT14__FUNC_CMCSD0 (MTK_PIN_NO(14) | 2)
+#define MT8173_PIN_14_EINT14__FUNC_CLKM2 (MTK_PIN_NO(14) | 4)
+#define MT8173_PIN_14_EINT14__FUNC_DBG_MON_B_6_ (MTK_PIN_NO(14) | 7)
+
+#define MT8173_PIN_15_EINT15__FUNC_GPIO15 (MTK_PIN_NO(15) | 0)
+#define MT8173_PIN_15_EINT15__FUNC_CMDAT1 (MTK_PIN_NO(15) | 1)
+#define MT8173_PIN_15_EINT15__FUNC_CMCSD1 (MTK_PIN_NO(15) | 2)
+#define MT8173_PIN_15_EINT15__FUNC_CMFLASH (MTK_PIN_NO(15) | 3)
+#define MT8173_PIN_15_EINT15__FUNC_CLKM3 (MTK_PIN_NO(15) | 4)
+#define MT8173_PIN_15_EINT15__FUNC_DBG_MON_B_29_ (MTK_PIN_NO(15) | 7)
+
+#define MT8173_PIN_16_IDDIG__FUNC_GPIO16 (MTK_PIN_NO(16) | 0)
+#define MT8173_PIN_16_IDDIG__FUNC_IDDIG (MTK_PIN_NO(16) | 1)
+#define MT8173_PIN_16_IDDIG__FUNC_CMFLASH (MTK_PIN_NO(16) | 2)
+#define MT8173_PIN_16_IDDIG__FUNC_PWM5 (MTK_PIN_NO(16) | 4)
+
+#define MT8173_PIN_17_WATCHDOG__FUNC_GPIO17 (MTK_PIN_NO(17) | 0)
+#define MT8173_PIN_17_WATCHDOG__FUNC_WATCHDOG_AO (MTK_PIN_NO(17) | 1)
+
+#define MT8173_PIN_18_CEC__FUNC_GPIO18 (MTK_PIN_NO(18) | 0)
+#define MT8173_PIN_18_CEC__FUNC_CEC (MTK_PIN_NO(18) | 1)
+
+#define MT8173_PIN_19_HDMISCK__FUNC_GPIO19 (MTK_PIN_NO(19) | 0)
+#define MT8173_PIN_19_HDMISCK__FUNC_HDMISCK (MTK_PIN_NO(19) | 1)
+#define MT8173_PIN_19_HDMISCK__FUNC_HDCP_SCL (MTK_PIN_NO(19) | 2)
+
+#define MT8173_PIN_20_HDMISD__FUNC_GPIO20 (MTK_PIN_NO(20) | 0)
+#define MT8173_PIN_20_HDMISD__FUNC_HDMISD (MTK_PIN_NO(20) | 1)
+#define MT8173_PIN_20_HDMISD__FUNC_HDCP_SDA (MTK_PIN_NO(20) | 2)
+
+#define MT8173_PIN_21_HTPLG__FUNC_GPIO21 (MTK_PIN_NO(21) | 0)
+#define MT8173_PIN_21_HTPLG__FUNC_HTPLG (MTK_PIN_NO(21) | 1)
+
+#define MT8173_PIN_22_MSDC3_DAT0__FUNC_GPIO22 (MTK_PIN_NO(22) | 0)
+#define MT8173_PIN_22_MSDC3_DAT0__FUNC_MSDC3_DAT0 (MTK_PIN_NO(22) | 1)
+
+#define MT8173_PIN_23_MSDC3_DAT1__FUNC_GPIO23 (MTK_PIN_NO(23) | 0)
+#define MT8173_PIN_23_MSDC3_DAT1__FUNC_MSDC3_DAT1 (MTK_PIN_NO(23) | 1)
+
+#define MT8173_PIN_24_MSDC3_DAT2__FUNC_GPIO24 (MTK_PIN_NO(24) | 0)
+#define MT8173_PIN_24_MSDC3_DAT2__FUNC_MSDC3_DAT2 (MTK_PIN_NO(24) | 1)
+
+#define MT8173_PIN_25_MSDC3_DAT3__FUNC_GPIO25 (MTK_PIN_NO(25) | 0)
+#define MT8173_PIN_25_MSDC3_DAT3__FUNC_MSDC3_DAT3 (MTK_PIN_NO(25) | 1)
+
+#define MT8173_PIN_26_MSDC3_CLK__FUNC_GPIO26 (MTK_PIN_NO(26) | 0)
+#define MT8173_PIN_26_MSDC3_CLK__FUNC_MSDC3_CLK (MTK_PIN_NO(26) | 1)
+
+#define MT8173_PIN_27_MSDC3_CMD__FUNC_GPIO27 (MTK_PIN_NO(27) | 0)
+#define MT8173_PIN_27_MSDC3_CMD__FUNC_MSDC3_CMD (MTK_PIN_NO(27) | 1)
+
+#define MT8173_PIN_28_MSDC3_DSL__FUNC_GPIO28 (MTK_PIN_NO(28) | 0)
+#define MT8173_PIN_28_MSDC3_DSL__FUNC_MSDC3_DSL (MTK_PIN_NO(28) | 1)
+
+#define MT8173_PIN_29_UCTS2__FUNC_GPIO29 (MTK_PIN_NO(29) | 0)
+#define MT8173_PIN_29_UCTS2__FUNC_UCTS2 (MTK_PIN_NO(29) | 1)
+
+#define MT8173_PIN_30_URTS2__FUNC_GPIO30 (MTK_PIN_NO(30) | 0)
+#define MT8173_PIN_30_URTS2__FUNC_URTS2 (MTK_PIN_NO(30) | 1)
+
+#define MT8173_PIN_31_URXD2__FUNC_GPIO31 (MTK_PIN_NO(31) | 0)
+#define MT8173_PIN_31_URXD2__FUNC_URXD2 (MTK_PIN_NO(31) | 1)
+#define MT8173_PIN_31_URXD2__FUNC_UTXD2 (MTK_PIN_NO(31) | 2)
+
+#define MT8173_PIN_32_UTXD2__FUNC_GPIO32 (MTK_PIN_NO(32) | 0)
+#define MT8173_PIN_32_UTXD2__FUNC_UTXD2 (MTK_PIN_NO(32) | 1)
+#define MT8173_PIN_32_UTXD2__FUNC_URXD2 (MTK_PIN_NO(32) | 2)
+
+#define MT8173_PIN_33_DAICLK__FUNC_GPIO33 (MTK_PIN_NO(33) | 0)
+#define MT8173_PIN_33_DAICLK__FUNC_MRG_CLK (MTK_PIN_NO(33) | 1)
+#define MT8173_PIN_33_DAICLK__FUNC_PCM0_CLK (MTK_PIN_NO(33) | 2)
+
+#define MT8173_PIN_34_DAIPCMIN__FUNC_GPIO34 (MTK_PIN_NO(34) | 0)
+#define MT8173_PIN_34_DAIPCMIN__FUNC_MRG_DI (MTK_PIN_NO(34) | 1)
+#define MT8173_PIN_34_DAIPCMIN__FUNC_PCM0_DI (MTK_PIN_NO(34) | 2)
+
+#define MT8173_PIN_35_DAIPCMOUT__FUNC_GPIO35 (MTK_PIN_NO(35) | 0)
+#define MT8173_PIN_35_DAIPCMOUT__FUNC_MRG_DO (MTK_PIN_NO(35) | 1)
+#define MT8173_PIN_35_DAIPCMOUT__FUNC_PCM0_DO (MTK_PIN_NO(35) | 2)
+
+#define MT8173_PIN_36_DAISYNC__FUNC_GPIO36 (MTK_PIN_NO(36) | 0)
+#define MT8173_PIN_36_DAISYNC__FUNC_MRG_SYNC (MTK_PIN_NO(36) | 1)
+#define MT8173_PIN_36_DAISYNC__FUNC_PCM0_SYNC (MTK_PIN_NO(36) | 2)
+
+#define MT8173_PIN_37_EINT16__FUNC_GPIO37 (MTK_PIN_NO(37) | 0)
+#define MT8173_PIN_37_EINT16__FUNC_USB_DRVVBUS_P0 (MTK_PIN_NO(37) | 1)
+#define MT8173_PIN_37_EINT16__FUNC_USB_DRVVBUS_P1 (MTK_PIN_NO(37) | 2)
+#define MT8173_PIN_37_EINT16__FUNC_PWM0 (MTK_PIN_NO(37) | 3)
+#define MT8173_PIN_37_EINT16__FUNC_PWM1 (MTK_PIN_NO(37) | 4)
+#define MT8173_PIN_37_EINT16__FUNC_PWM2 (MTK_PIN_NO(37) | 5)
+#define MT8173_PIN_37_EINT16__FUNC_CLKM0 (MTK_PIN_NO(37) | 6)
+
+#define MT8173_PIN_38_CONN_RST__FUNC_GPIO38 (MTK_PIN_NO(38) | 0)
+#define MT8173_PIN_38_CONN_RST__FUNC_USB_DRVVBUS_P0 (MTK_PIN_NO(38) | 1)
+#define MT8173_PIN_38_CONN_RST__FUNC_USB_DRVVBUS_P1 (MTK_PIN_NO(38) | 2)
+#define MT8173_PIN_38_CONN_RST__FUNC_CLKM1 (MTK_PIN_NO(38) | 6)
+
+#define MT8173_PIN_39_CM2MCLK__FUNC_GPIO39 (MTK_PIN_NO(39) | 0)
+#define MT8173_PIN_39_CM2MCLK__FUNC_CM2MCLK (MTK_PIN_NO(39) | 1)
+#define MT8173_PIN_39_CM2MCLK__FUNC_CMCSD0 (MTK_PIN_NO(39) | 2)
+#define MT8173_PIN_39_CM2MCLK__FUNC_DBG_MON_A_17_ (MTK_PIN_NO(39) | 7)
+
+#define MT8173_PIN_40_CMPCLK__FUNC_GPIO40 (MTK_PIN_NO(40) | 0)
+#define MT8173_PIN_40_CMPCLK__FUNC_CMPCLK (MTK_PIN_NO(40) | 1)
+#define MT8173_PIN_40_CMPCLK__FUNC_CMCSK (MTK_PIN_NO(40) | 2)
+#define MT8173_PIN_40_CMPCLK__FUNC_CMCSD2 (MTK_PIN_NO(40) | 3)
+#define MT8173_PIN_40_CMPCLK__FUNC_DBG_MON_A_18_ (MTK_PIN_NO(40) | 7)
+
+#define MT8173_PIN_41_CMMCLK__FUNC_GPIO41 (MTK_PIN_NO(41) | 0)
+#define MT8173_PIN_41_CMMCLK__FUNC_CMMCLK (MTK_PIN_NO(41) | 1)
+#define MT8173_PIN_41_CMMCLK__FUNC_DBG_MON_A_19_ (MTK_PIN_NO(41) | 7)
+
+#define MT8173_PIN_42_DSI_TE__FUNC_GPIO42 (MTK_PIN_NO(42) | 0)
+#define MT8173_PIN_42_DSI_TE__FUNC_DSI_TE (MTK_PIN_NO(42) | 1)
+
+#define MT8173_PIN_43_SDA2__FUNC_GPIO43 (MTK_PIN_NO(43) | 0)
+#define MT8173_PIN_43_SDA2__FUNC_SDA2 (MTK_PIN_NO(43) | 1)
+
+#define MT8173_PIN_44_SCL2__FUNC_GPIO44 (MTK_PIN_NO(44) | 0)
+#define MT8173_PIN_44_SCL2__FUNC_SCL2 (MTK_PIN_NO(44) | 1)
+
+#define MT8173_PIN_45_SDA0__FUNC_GPIO45 (MTK_PIN_NO(45) | 0)
+#define MT8173_PIN_45_SDA0__FUNC_SDA0 (MTK_PIN_NO(45) | 1)
+
+#define MT8173_PIN_46_SCL0__FUNC_GPIO46 (MTK_PIN_NO(46) | 0)
+#define MT8173_PIN_46_SCL0__FUNC_SCL0 (MTK_PIN_NO(46) | 1)
+
+#define MT8173_PIN_47_RDN0_A__FUNC_GPIO47 (MTK_PIN_NO(47) | 0)
+#define MT8173_PIN_47_RDN0_A__FUNC_CMDAT2 (MTK_PIN_NO(47) | 1)
+
+#define MT8173_PIN_48_RDP0_A__FUNC_GPIO48 (MTK_PIN_NO(48) | 0)
+#define MT8173_PIN_48_RDP0_A__FUNC_CMDAT3 (MTK_PIN_NO(48) | 1)
+
+#define MT8173_PIN_49_RDN1_A__FUNC_GPIO49 (MTK_PIN_NO(49) | 0)
+#define MT8173_PIN_49_RDN1_A__FUNC_CMDAT4 (MTK_PIN_NO(49) | 1)
+
+#define MT8173_PIN_50_RDP1_A__FUNC_GPIO50 (MTK_PIN_NO(50) | 0)
+#define MT8173_PIN_50_RDP1_A__FUNC_CMDAT5 (MTK_PIN_NO(50) | 1)
+
+#define MT8173_PIN_51_RCN_A__FUNC_GPIO51 (MTK_PIN_NO(51) | 0)
+#define MT8173_PIN_51_RCN_A__FUNC_CMDAT6 (MTK_PIN_NO(51) | 1)
+
+#define MT8173_PIN_52_RCP_A__FUNC_GPIO52 (MTK_PIN_NO(52) | 0)
+#define MT8173_PIN_52_RCP_A__FUNC_CMDAT7 (MTK_PIN_NO(52) | 1)
+
+#define MT8173_PIN_53_RDN2_A__FUNC_GPIO53 (MTK_PIN_NO(53) | 0)
+#define MT8173_PIN_53_RDN2_A__FUNC_CMDAT8 (MTK_PIN_NO(53) | 1)
+#define MT8173_PIN_53_RDN2_A__FUNC_CMCSD3 (MTK_PIN_NO(53) | 2)
+
+#define MT8173_PIN_54_RDP2_A__FUNC_GPIO54 (MTK_PIN_NO(54) | 0)
+#define MT8173_PIN_54_RDP2_A__FUNC_CMDAT9 (MTK_PIN_NO(54) | 1)
+#define MT8173_PIN_54_RDP2_A__FUNC_CMCSD2 (MTK_PIN_NO(54) | 2)
+
+#define MT8173_PIN_55_RDN3_A__FUNC_GPIO55 (MTK_PIN_NO(55) | 0)
+#define MT8173_PIN_55_RDN3_A__FUNC_CMHSYNC (MTK_PIN_NO(55) | 1)
+#define MT8173_PIN_55_RDN3_A__FUNC_CMCSD1 (MTK_PIN_NO(55) | 2)
+
+#define MT8173_PIN_56_RDP3_A__FUNC_GPIO56 (MTK_PIN_NO(56) | 0)
+#define MT8173_PIN_56_RDP3_A__FUNC_CMVSYNC (MTK_PIN_NO(56) | 1)
+#define MT8173_PIN_56_RDP3_A__FUNC_CMCSD0 (MTK_PIN_NO(56) | 2)
+
+#define MT8173_PIN_57_MSDC0_DAT0__FUNC_GPIO57 (MTK_PIN_NO(57) | 0)
+#define MT8173_PIN_57_MSDC0_DAT0__FUNC_MSDC0_DAT0 (MTK_PIN_NO(57) | 1)
+#define MT8173_PIN_57_MSDC0_DAT0__FUNC_I2S1_WS (MTK_PIN_NO(57) | 2)
+#define MT8173_PIN_57_MSDC0_DAT0__FUNC_DBG_MON_B_7_ (MTK_PIN_NO(57) | 7)
+
+#define MT8173_PIN_58_MSDC0_DAT1__FUNC_GPIO58 (MTK_PIN_NO(58) | 0)
+#define MT8173_PIN_58_MSDC0_DAT1__FUNC_MSDC0_DAT1 (MTK_PIN_NO(58) | 1)
+#define MT8173_PIN_58_MSDC0_DAT1__FUNC_I2S1_BCK (MTK_PIN_NO(58) | 2)
+#define MT8173_PIN_58_MSDC0_DAT1__FUNC_DBG_MON_B_8_ (MTK_PIN_NO(58) | 7)
+
+#define MT8173_PIN_59_MSDC0_DAT2__FUNC_GPIO59 (MTK_PIN_NO(59) | 0)
+#define MT8173_PIN_59_MSDC0_DAT2__FUNC_MSDC0_DAT2 (MTK_PIN_NO(59) | 1)
+#define MT8173_PIN_59_MSDC0_DAT2__FUNC_I2S1_MCK (MTK_PIN_NO(59) | 2)
+#define MT8173_PIN_59_MSDC0_DAT2__FUNC_DBG_MON_B_9_ (MTK_PIN_NO(59) | 7)
+
+#define MT8173_PIN_60_MSDC0_DAT3__FUNC_GPIO60 (MTK_PIN_NO(60) | 0)
+#define MT8173_PIN_60_MSDC0_DAT3__FUNC_MSDC0_DAT3 (MTK_PIN_NO(60) | 1)
+#define MT8173_PIN_60_MSDC0_DAT3__FUNC_I2S1_DO_1 (MTK_PIN_NO(60) | 2)
+#define MT8173_PIN_60_MSDC0_DAT3__FUNC_DBG_MON_B_10_ (MTK_PIN_NO(60) | 7)
+
+#define MT8173_PIN_61_MSDC0_DAT4__FUNC_GPIO61 (MTK_PIN_NO(61) | 0)
+#define MT8173_PIN_61_MSDC0_DAT4__FUNC_MSDC0_DAT4 (MTK_PIN_NO(61) | 1)
+#define MT8173_PIN_61_MSDC0_DAT4__FUNC_I2S1_DO_2 (MTK_PIN_NO(61) | 2)
+#define MT8173_PIN_61_MSDC0_DAT4__FUNC_DBG_MON_B_11_ (MTK_PIN_NO(61) | 7)
+
+#define MT8173_PIN_62_MSDC0_DAT5__FUNC_GPIO62 (MTK_PIN_NO(62) | 0)
+#define MT8173_PIN_62_MSDC0_DAT5__FUNC_MSDC0_DAT5 (MTK_PIN_NO(62) | 1)
+#define MT8173_PIN_62_MSDC0_DAT5__FUNC_I2S2_WS (MTK_PIN_NO(62) | 2)
+#define MT8173_PIN_62_MSDC0_DAT5__FUNC_DBG_MON_B_12_ (MTK_PIN_NO(62) | 7)
+
+#define MT8173_PIN_63_MSDC0_DAT6__FUNC_GPIO63 (MTK_PIN_NO(63) | 0)
+#define MT8173_PIN_63_MSDC0_DAT6__FUNC_MSDC0_DAT6 (MTK_PIN_NO(63) | 1)
+#define MT8173_PIN_63_MSDC0_DAT6__FUNC_I2S2_BCK (MTK_PIN_NO(63) | 2)
+#define MT8173_PIN_63_MSDC0_DAT6__FUNC_DBG_MON_B_13_ (MTK_PIN_NO(63) | 7)
+
+#define MT8173_PIN_64_MSDC0_DAT7__FUNC_GPIO64 (MTK_PIN_NO(64) | 0)
+#define MT8173_PIN_64_MSDC0_DAT7__FUNC_MSDC0_DAT7 (MTK_PIN_NO(64) | 1)
+#define MT8173_PIN_64_MSDC0_DAT7__FUNC_I2S2_DI_1 (MTK_PIN_NO(64) | 2)
+#define MT8173_PIN_64_MSDC0_DAT7__FUNC_DBG_MON_B_14_ (MTK_PIN_NO(64) | 7)
+
+#define MT8173_PIN_65_MSDC0_CLK__FUNC_GPIO65 (MTK_PIN_NO(65) | 0)
+#define MT8173_PIN_65_MSDC0_CLK__FUNC_MSDC0_CLK (MTK_PIN_NO(65) | 1)
+#define MT8173_PIN_65_MSDC0_CLK__FUNC_DBG_MON_B_16_ (MTK_PIN_NO(65) | 7)
+
+#define MT8173_PIN_66_MSDC0_CMD__FUNC_GPIO66 (MTK_PIN_NO(66) | 0)
+#define MT8173_PIN_66_MSDC0_CMD__FUNC_MSDC0_CMD (MTK_PIN_NO(66) | 1)
+#define MT8173_PIN_66_MSDC0_CMD__FUNC_I2S2_DI_2 (MTK_PIN_NO(66) | 2)
+#define MT8173_PIN_66_MSDC0_CMD__FUNC_DBG_MON_B_15_ (MTK_PIN_NO(66) | 7)
+
+#define MT8173_PIN_67_MSDC0_DSL__FUNC_GPIO67 (MTK_PIN_NO(67) | 0)
+#define MT8173_PIN_67_MSDC0_DSL__FUNC_MSDC0_DSL (MTK_PIN_NO(67) | 1)
+#define MT8173_PIN_67_MSDC0_DSL__FUNC_DBG_MON_B_17_ (MTK_PIN_NO(67) | 7)
+
+#define MT8173_PIN_68_MSDC0_RST___FUNC_GPIO68 (MTK_PIN_NO(68) | 0)
+#define MT8173_PIN_68_MSDC0_RST___FUNC_MSDC0_RSTB (MTK_PIN_NO(68) | 1)
+#define MT8173_PIN_68_MSDC0_RST___FUNC_I2S2_MCK (MTK_PIN_NO(68) | 2)
+#define MT8173_PIN_68_MSDC0_RST___FUNC_DBG_MON_B_18_ (MTK_PIN_NO(68) | 7)
+
+#define MT8173_PIN_69_SPI_CK__FUNC_GPIO69 (MTK_PIN_NO(69) | 0)
+#define MT8173_PIN_69_SPI_CK__FUNC_SPI_CK_0_ (MTK_PIN_NO(69) | 1)
+#define MT8173_PIN_69_SPI_CK__FUNC_I2S3_DO_1 (MTK_PIN_NO(69) | 2)
+#define MT8173_PIN_69_SPI_CK__FUNC_PWM0 (MTK_PIN_NO(69) | 3)
+#define MT8173_PIN_69_SPI_CK__FUNC_PWM5 (MTK_PIN_NO(69) | 4)
+#define MT8173_PIN_69_SPI_CK__FUNC_I2S2_MCK (MTK_PIN_NO(69) | 5)
+#define MT8173_PIN_69_SPI_CK__FUNC_DBG_MON_B_19_ (MTK_PIN_NO(69) | 7)
+
+#define MT8173_PIN_70_SPI_MI__FUNC_GPIO70 (MTK_PIN_NO(70) | 0)
+#define MT8173_PIN_70_SPI_MI__FUNC_SPI_MI_0_ (MTK_PIN_NO(70) | 1)
+#define MT8173_PIN_70_SPI_MI__FUNC_I2S3_DO_2 (MTK_PIN_NO(70) | 2)
+#define MT8173_PIN_70_SPI_MI__FUNC_PWM1 (MTK_PIN_NO(70) | 3)
+#define MT8173_PIN_70_SPI_MI__FUNC_SPI_MO_0_ (MTK_PIN_NO(70) | 4)
+#define MT8173_PIN_70_SPI_MI__FUNC_I2S2_DI_1 (MTK_PIN_NO(70) | 5)
+#define MT8173_PIN_70_SPI_MI__FUNC_DSI1_TE (MTK_PIN_NO(70) | 6)
+#define MT8173_PIN_70_SPI_MI__FUNC_DBG_MON_B_20_ (MTK_PIN_NO(70) | 7)
+
+#define MT8173_PIN_71_SPI_MO__FUNC_GPIO71 (MTK_PIN_NO(71) | 0)
+#define MT8173_PIN_71_SPI_MO__FUNC_SPI_MO_0_ (MTK_PIN_NO(71) | 1)
+#define MT8173_PIN_71_SPI_MO__FUNC_I2S3_DO_3 (MTK_PIN_NO(71) | 2)
+#define MT8173_PIN_71_SPI_MO__FUNC_PWM2 (MTK_PIN_NO(71) | 3)
+#define MT8173_PIN_71_SPI_MO__FUNC_SPI_MI_0_ (MTK_PIN_NO(71) | 4)
+#define MT8173_PIN_71_SPI_MO__FUNC_I2S2_DI_2 (MTK_PIN_NO(71) | 5)
+#define MT8173_PIN_71_SPI_MO__FUNC_DBG_MON_B_21_ (MTK_PIN_NO(71) | 7)
+
+#define MT8173_PIN_72_SPI_CS__FUNC_GPIO72 (MTK_PIN_NO(72) | 0)
+#define MT8173_PIN_72_SPI_CS__FUNC_SPI_CS_0_ (MTK_PIN_NO(72) | 1)
+#define MT8173_PIN_72_SPI_CS__FUNC_I2S3_DO_4 (MTK_PIN_NO(72) | 2)
+#define MT8173_PIN_72_SPI_CS__FUNC_PWM3 (MTK_PIN_NO(72) | 3)
+#define MT8173_PIN_72_SPI_CS__FUNC_PWM6 (MTK_PIN_NO(72) | 4)
+#define MT8173_PIN_72_SPI_CS__FUNC_DISP_PWM1 (MTK_PIN_NO(72) | 5)
+#define MT8173_PIN_72_SPI_CS__FUNC_DBG_MON_B_22_ (MTK_PIN_NO(72) | 7)
+
+#define MT8173_PIN_73_MSDC1_DAT0__FUNC_GPIO73 (MTK_PIN_NO(73) | 0)
+#define MT8173_PIN_73_MSDC1_DAT0__FUNC_MSDC1_DAT0 (MTK_PIN_NO(73) | 1)
+#define MT8173_PIN_73_MSDC1_DAT0__FUNC_DBG_MON_B_24_ (MTK_PIN_NO(73) | 7)
+
+#define MT8173_PIN_74_MSDC1_DAT1__FUNC_GPIO74 (MTK_PIN_NO(74) | 0)
+#define MT8173_PIN_74_MSDC1_DAT1__FUNC_MSDC1_DAT1 (MTK_PIN_NO(74) | 1)
+#define MT8173_PIN_74_MSDC1_DAT1__FUNC_DBG_MON_B_25_ (MTK_PIN_NO(74) | 7)
+
+#define MT8173_PIN_75_MSDC1_DAT2__FUNC_GPIO75 (MTK_PIN_NO(75) | 0)
+#define MT8173_PIN_75_MSDC1_DAT2__FUNC_MSDC1_DAT2 (MTK_PIN_NO(75) | 1)
+#define MT8173_PIN_75_MSDC1_DAT2__FUNC_DBG_MON_B_26_ (MTK_PIN_NO(75) | 7)
+
+#define MT8173_PIN_76_MSDC1_DAT3__FUNC_GPIO76 (MTK_PIN_NO(76) | 0)
+#define MT8173_PIN_76_MSDC1_DAT3__FUNC_MSDC1_DAT3 (MTK_PIN_NO(76) | 1)
+#define MT8173_PIN_76_MSDC1_DAT3__FUNC_DBG_MON_B_27_ (MTK_PIN_NO(76) | 7)
+
+#define MT8173_PIN_77_MSDC1_CLK__FUNC_GPIO77 (MTK_PIN_NO(77) | 0)
+#define MT8173_PIN_77_MSDC1_CLK__FUNC_MSDC1_CLK (MTK_PIN_NO(77) | 1)
+#define MT8173_PIN_77_MSDC1_CLK__FUNC_DBG_MON_B_28_ (MTK_PIN_NO(77) | 7)
+
+#define MT8173_PIN_78_MSDC1_CMD__FUNC_GPIO78 (MTK_PIN_NO(78) | 0)
+#define MT8173_PIN_78_MSDC1_CMD__FUNC_MSDC1_CMD (MTK_PIN_NO(78) | 1)
+#define MT8173_PIN_78_MSDC1_CMD__FUNC_DBG_MON_B_23_ (MTK_PIN_NO(78) | 7)
+
+#define MT8173_PIN_79_PWRAP_SPI0_MI__FUNC_GPIO79 (MTK_PIN_NO(79) | 0)
+#define MT8173_PIN_79_PWRAP_SPI0_MI__FUNC_PWRAP_SPIMI (MTK_PIN_NO(79) | 1)
+#define MT8173_PIN_79_PWRAP_SPI0_MI__FUNC_PWRAP_SPIMO (MTK_PIN_NO(79) | 2)
+
+#define MT8173_PIN_80_PWRAP_SPI0_MO__FUNC_GPIO80 (MTK_PIN_NO(80) | 0)
+#define MT8173_PIN_80_PWRAP_SPI0_MO__FUNC_PWRAP_SPIMO (MTK_PIN_NO(80) | 1)
+#define MT8173_PIN_80_PWRAP_SPI0_MO__FUNC_PWRAP_SPIMI (MTK_PIN_NO(80) | 2)
+
+#define MT8173_PIN_81_PWRAP_SPI0_CK__FUNC_GPIO81 (MTK_PIN_NO(81) | 0)
+#define MT8173_PIN_81_PWRAP_SPI0_CK__FUNC_PWRAP_SPICK (MTK_PIN_NO(81) | 1)
+
+#define MT8173_PIN_82_PWRAP_SPI0_CSN__FUNC_GPIO82 (MTK_PIN_NO(82) | 0)
+#define MT8173_PIN_82_PWRAP_SPI0_CSN__FUNC_PWRAP_SPICS (MTK_PIN_NO(82) | 1)
+
+#define MT8173_PIN_83_AUD_CLK_MOSI__FUNC_GPIO83 (MTK_PIN_NO(83) | 0)
+#define MT8173_PIN_83_AUD_CLK_MOSI__FUNC_AUD_CLK_MOSI (MTK_PIN_NO(83) | 1)
+
+#define MT8173_PIN_84_AUD_DAT_MISO__FUNC_GPIO84 (MTK_PIN_NO(84) | 0)
+#define MT8173_PIN_84_AUD_DAT_MISO__FUNC_AUD_DAT_MISO (MTK_PIN_NO(84) | 1)
+#define MT8173_PIN_84_AUD_DAT_MISO__FUNC_AUD_DAT_MOSI (MTK_PIN_NO(84) | 2)
+
+#define MT8173_PIN_85_AUD_DAT_MOSI__FUNC_GPIO85 (MTK_PIN_NO(85) | 0)
+#define MT8173_PIN_85_AUD_DAT_MOSI__FUNC_AUD_DAT_MOSI (MTK_PIN_NO(85) | 1)
+#define MT8173_PIN_85_AUD_DAT_MOSI__FUNC_AUD_DAT_MISO (MTK_PIN_NO(85) | 2)
+
+#define MT8173_PIN_86_RTC32K_CK__FUNC_GPIO86 (MTK_PIN_NO(86) | 0)
+#define MT8173_PIN_86_RTC32K_CK__FUNC_RTC32K_CK (MTK_PIN_NO(86) | 1)
+
+#define MT8173_PIN_87_DISP_PWM0__FUNC_GPIO87 (MTK_PIN_NO(87) | 0)
+#define MT8173_PIN_87_DISP_PWM0__FUNC_DISP_PWM0 (MTK_PIN_NO(87) | 1)
+#define MT8173_PIN_87_DISP_PWM0__FUNC_DISP_PWM1 (MTK_PIN_NO(87) | 2)
+#define MT8173_PIN_87_DISP_PWM0__FUNC_DBG_MON_B_31_ (MTK_PIN_NO(87) | 7)
+
+#define MT8173_PIN_88_SRCLKENAI__FUNC_GPIO88 (MTK_PIN_NO(88) | 0)
+#define MT8173_PIN_88_SRCLKENAI__FUNC_SRCLKENAI (MTK_PIN_NO(88) | 1)
+
+#define MT8173_PIN_89_SRCLKENAI2__FUNC_GPIO89 (MTK_PIN_NO(89) | 0)
+#define MT8173_PIN_89_SRCLKENAI2__FUNC_SRCLKENAI2 (MTK_PIN_NO(89) | 1)
+
+#define MT8173_PIN_90_SRCLKENA0__FUNC_GPIO90 (MTK_PIN_NO(90) | 0)
+#define MT8173_PIN_90_SRCLKENA0__FUNC_SRCLKENA0 (MTK_PIN_NO(90) | 1)
+
+#define MT8173_PIN_91_SRCLKENA1__FUNC_GPIO91 (MTK_PIN_NO(91) | 0)
+#define MT8173_PIN_91_SRCLKENA1__FUNC_SRCLKENA1 (MTK_PIN_NO(91) | 1)
+
+#define MT8173_PIN_92_PCM_CLK__FUNC_GPIO92 (MTK_PIN_NO(92) | 0)
+#define MT8173_PIN_92_PCM_CLK__FUNC_PCM1_CLK (MTK_PIN_NO(92) | 1)
+#define MT8173_PIN_92_PCM_CLK__FUNC_I2S0_BCK (MTK_PIN_NO(92) | 2)
+#define MT8173_PIN_92_PCM_CLK__FUNC_DBG_MON_A_24_ (MTK_PIN_NO(92) | 7)
+
+#define MT8173_PIN_93_PCM_SYNC__FUNC_GPIO93 (MTK_PIN_NO(93) | 0)
+#define MT8173_PIN_93_PCM_SYNC__FUNC_PCM1_SYNC (MTK_PIN_NO(93) | 1)
+#define MT8173_PIN_93_PCM_SYNC__FUNC_I2S0_WS (MTK_PIN_NO(93) | 2)
+#define MT8173_PIN_93_PCM_SYNC__FUNC_DBG_MON_A_25_ (MTK_PIN_NO(93) | 7)
+
+#define MT8173_PIN_94_PCM_RX__FUNC_GPIO94 (MTK_PIN_NO(94) | 0)
+#define MT8173_PIN_94_PCM_RX__FUNC_PCM1_DI (MTK_PIN_NO(94) | 1)
+#define MT8173_PIN_94_PCM_RX__FUNC_I2S0_DI (MTK_PIN_NO(94) | 2)
+#define MT8173_PIN_94_PCM_RX__FUNC_DBG_MON_A_26_ (MTK_PIN_NO(94) | 7)
+
+#define MT8173_PIN_95_PCM_TX__FUNC_GPIO95 (MTK_PIN_NO(95) | 0)
+#define MT8173_PIN_95_PCM_TX__FUNC_PCM1_DO (MTK_PIN_NO(95) | 1)
+#define MT8173_PIN_95_PCM_TX__FUNC_I2S0_DO (MTK_PIN_NO(95) | 2)
+#define MT8173_PIN_95_PCM_TX__FUNC_DBG_MON_A_27_ (MTK_PIN_NO(95) | 7)
+
+#define MT8173_PIN_96_URXD1__FUNC_GPIO96 (MTK_PIN_NO(96) | 0)
+#define MT8173_PIN_96_URXD1__FUNC_URXD1 (MTK_PIN_NO(96) | 1)
+#define MT8173_PIN_96_URXD1__FUNC_UTXD1 (MTK_PIN_NO(96) | 2)
+#define MT8173_PIN_96_URXD1__FUNC_DBG_MON_A_28_ (MTK_PIN_NO(96) | 7)
+
+#define MT8173_PIN_97_UTXD1__FUNC_GPIO97 (MTK_PIN_NO(97) | 0)
+#define MT8173_PIN_97_UTXD1__FUNC_UTXD1 (MTK_PIN_NO(97) | 1)
+#define MT8173_PIN_97_UTXD1__FUNC_URXD1 (MTK_PIN_NO(97) | 2)
+#define MT8173_PIN_97_UTXD1__FUNC_DBG_MON_A_29_ (MTK_PIN_NO(97) | 7)
+
+#define MT8173_PIN_98_URTS1__FUNC_GPIO98 (MTK_PIN_NO(98) | 0)
+#define MT8173_PIN_98_URTS1__FUNC_URTS1 (MTK_PIN_NO(98) | 1)
+#define MT8173_PIN_98_URTS1__FUNC_UCTS1 (MTK_PIN_NO(98) | 2)
+#define MT8173_PIN_98_URTS1__FUNC_DBG_MON_A_30_ (MTK_PIN_NO(98) | 7)
+
+#define MT8173_PIN_99_UCTS1__FUNC_GPIO99 (MTK_PIN_NO(99) | 0)
+#define MT8173_PIN_99_UCTS1__FUNC_UCTS1 (MTK_PIN_NO(99) | 1)
+#define MT8173_PIN_99_UCTS1__FUNC_URTS1 (MTK_PIN_NO(99) | 2)
+#define MT8173_PIN_99_UCTS1__FUNC_DBG_MON_A_31_ (MTK_PIN_NO(99) | 7)
+
+#define MT8173_PIN_100_MSDC2_DAT0__FUNC_GPIO100 (MTK_PIN_NO(100) | 0)
+#define MT8173_PIN_100_MSDC2_DAT0__FUNC_MSDC2_DAT0 (MTK_PIN_NO(100) | 1)
+#define MT8173_PIN_100_MSDC2_DAT0__FUNC_USB_DRVVBUS_P0 (MTK_PIN_NO(100) | 3)
+#define MT8173_PIN_100_MSDC2_DAT0__FUNC_SDA5 (MTK_PIN_NO(100) | 4)
+#define MT8173_PIN_100_MSDC2_DAT0__FUNC_USB_DRVVBUS_P1 (MTK_PIN_NO(100) | 5)
+#define MT8173_PIN_100_MSDC2_DAT0__FUNC_DBG_MON_B_0_ (MTK_PIN_NO(100) | 7)
+
+#define MT8173_PIN_101_MSDC2_DAT1__FUNC_GPIO101 (MTK_PIN_NO(101) | 0)
+#define MT8173_PIN_101_MSDC2_DAT1__FUNC_MSDC2_DAT1 (MTK_PIN_NO(101) | 1)
+#define MT8173_PIN_101_MSDC2_DAT1__FUNC_AUD_SPDIF (MTK_PIN_NO(101) | 3)
+#define MT8173_PIN_101_MSDC2_DAT1__FUNC_SCL5 (MTK_PIN_NO(101) | 4)
+#define MT8173_PIN_101_MSDC2_DAT1__FUNC_DBG_MON_B_1_ (MTK_PIN_NO(101) | 7)
+
+#define MT8173_PIN_102_MSDC2_DAT2__FUNC_GPIO102 (MTK_PIN_NO(102) | 0)
+#define MT8173_PIN_102_MSDC2_DAT2__FUNC_MSDC2_DAT2 (MTK_PIN_NO(102) | 1)
+#define MT8173_PIN_102_MSDC2_DAT2__FUNC_UTXD0 (MTK_PIN_NO(102) | 3)
+#define MT8173_PIN_102_MSDC2_DAT2__FUNC_PWM0 (MTK_PIN_NO(102) | 5)
+#define MT8173_PIN_102_MSDC2_DAT2__FUNC_SPI_CK_1_ (MTK_PIN_NO(102) | 6)
+#define MT8173_PIN_102_MSDC2_DAT2__FUNC_DBG_MON_B_2_ (MTK_PIN_NO(102) | 7)
+
+#define MT8173_PIN_103_MSDC2_DAT3__FUNC_GPIO103 (MTK_PIN_NO(103) | 0)
+#define MT8173_PIN_103_MSDC2_DAT3__FUNC_MSDC2_DAT3 (MTK_PIN_NO(103) | 1)
+#define MT8173_PIN_103_MSDC2_DAT3__FUNC_URXD0 (MTK_PIN_NO(103) | 3)
+#define MT8173_PIN_103_MSDC2_DAT3__FUNC_PWM1 (MTK_PIN_NO(103) | 5)
+#define MT8173_PIN_103_MSDC2_DAT3__FUNC_SPI_MI_1_ (MTK_PIN_NO(103) | 6)
+#define MT8173_PIN_103_MSDC2_DAT3__FUNC_DBG_MON_B_3_ (MTK_PIN_NO(103) | 7)
+
+#define MT8173_PIN_104_MSDC2_CLK__FUNC_GPIO104 (MTK_PIN_NO(104) | 0)
+#define MT8173_PIN_104_MSDC2_CLK__FUNC_MSDC2_CLK (MTK_PIN_NO(104) | 1)
+#define MT8173_PIN_104_MSDC2_CLK__FUNC_UTXD3 (MTK_PIN_NO(104) | 3)
+#define MT8173_PIN_104_MSDC2_CLK__FUNC_SDA3 (MTK_PIN_NO(104) | 4)
+#define MT8173_PIN_104_MSDC2_CLK__FUNC_PWM2 (MTK_PIN_NO(104) | 5)
+#define MT8173_PIN_104_MSDC2_CLK__FUNC_SPI_MO_1_ (MTK_PIN_NO(104) | 6)
+#define MT8173_PIN_104_MSDC2_CLK__FUNC_DBG_MON_B_4_ (MTK_PIN_NO(104) | 7)
+
+#define MT8173_PIN_105_MSDC2_CMD__FUNC_GPIO105 (MTK_PIN_NO(105) | 0)
+#define MT8173_PIN_105_MSDC2_CMD__FUNC_MSDC2_CMD (MTK_PIN_NO(105) | 1)
+#define MT8173_PIN_105_MSDC2_CMD__FUNC_URXD3 (MTK_PIN_NO(105) | 3)
+#define MT8173_PIN_105_MSDC2_CMD__FUNC_SCL3 (MTK_PIN_NO(105) | 4)
+#define MT8173_PIN_105_MSDC2_CMD__FUNC_PWM3 (MTK_PIN_NO(105) | 5)
+#define MT8173_PIN_105_MSDC2_CMD__FUNC_SPI_CS_1_ (MTK_PIN_NO(105) | 6)
+#define MT8173_PIN_105_MSDC2_CMD__FUNC_DBG_MON_B_5_ (MTK_PIN_NO(105) | 7)
+
+#define MT8173_PIN_106_SDA3__FUNC_GPIO106 (MTK_PIN_NO(106) | 0)
+#define MT8173_PIN_106_SDA3__FUNC_SDA3 (MTK_PIN_NO(106) | 1)
+
+#define MT8173_PIN_107_SCL3__FUNC_GPIO107 (MTK_PIN_NO(107) | 0)
+#define MT8173_PIN_107_SCL3__FUNC_SCL3 (MTK_PIN_NO(107) | 1)
+
+#define MT8173_PIN_108_JTMS__FUNC_GPIO108 (MTK_PIN_NO(108) | 0)
+#define MT8173_PIN_108_JTMS__FUNC_JTMS (MTK_PIN_NO(108) | 1)
+#define MT8173_PIN_108_JTMS__FUNC_MFG_JTAG_TMS (MTK_PIN_NO(108) | 2)
+#define MT8173_PIN_108_JTMS__FUNC_AP_MD32_JTAG_TMS (MTK_PIN_NO(108) | 5)
+#define MT8173_PIN_108_JTMS__FUNC_DFD_TMS (MTK_PIN_NO(108) | 6)
+
+#define MT8173_PIN_109_JTCK__FUNC_GPIO109 (MTK_PIN_NO(109) | 0)
+#define MT8173_PIN_109_JTCK__FUNC_JTCK (MTK_PIN_NO(109) | 1)
+#define MT8173_PIN_109_JTCK__FUNC_MFG_JTAG_TCK (MTK_PIN_NO(109) | 2)
+#define MT8173_PIN_109_JTCK__FUNC_AP_MD32_JTAG_TCK (MTK_PIN_NO(109) | 5)
+#define MT8173_PIN_109_JTCK__FUNC_DFD_TCK (MTK_PIN_NO(109) | 6)
+
+#define MT8173_PIN_110_JTDI__FUNC_GPIO110 (MTK_PIN_NO(110) | 0)
+#define MT8173_PIN_110_JTDI__FUNC_JTDI (MTK_PIN_NO(110) | 1)
+#define MT8173_PIN_110_JTDI__FUNC_MFG_JTAG_TDI (MTK_PIN_NO(110) | 2)
+#define MT8173_PIN_110_JTDI__FUNC_AP_MD32_JTAG_TDI (MTK_PIN_NO(110) | 5)
+#define MT8173_PIN_110_JTDI__FUNC_DFD_TDI (MTK_PIN_NO(110) | 6)
+
+#define MT8173_PIN_111_JTDO__FUNC_GPIO111 (MTK_PIN_NO(111) | 0)
+#define MT8173_PIN_111_JTDO__FUNC_JTDO (MTK_PIN_NO(111) | 1)
+#define MT8173_PIN_111_JTDO__FUNC_MFG_JTAG_TDO (MTK_PIN_NO(111) | 2)
+#define MT8173_PIN_111_JTDO__FUNC_AP_MD32_JTAG_TDO (MTK_PIN_NO(111) | 5)
+#define MT8173_PIN_111_JTDO__FUNC_DFD_TDO (MTK_PIN_NO(111) | 6)
+
+#define MT8173_PIN_112_JTRST_B__FUNC_GPIO112 (MTK_PIN_NO(112) | 0)
+#define MT8173_PIN_112_JTRST_B__FUNC_JTRST_B (MTK_PIN_NO(112) | 1)
+#define MT8173_PIN_112_JTRST_B__FUNC_MFG_JTAG_TRSTN (MTK_PIN_NO(112) | 2)
+#define MT8173_PIN_112_JTRST_B__FUNC_AP_MD32_JTAG_TRST (MTK_PIN_NO(112) | 5)
+#define MT8173_PIN_112_JTRST_B__FUNC_DFD_NTRST (MTK_PIN_NO(112) | 6)
+
+#define MT8173_PIN_113_URXD0__FUNC_GPIO113 (MTK_PIN_NO(113) | 0)
+#define MT8173_PIN_113_URXD0__FUNC_URXD0 (MTK_PIN_NO(113) | 1)
+#define MT8173_PIN_113_URXD0__FUNC_UTXD0 (MTK_PIN_NO(113) | 2)
+#define MT8173_PIN_113_URXD0__FUNC_I2S2_WS (MTK_PIN_NO(113) | 6)
+#define MT8173_PIN_113_URXD0__FUNC_DBG_MON_A_0_ (MTK_PIN_NO(113) | 7)
+
+#define MT8173_PIN_114_UTXD0__FUNC_GPIO114 (MTK_PIN_NO(114) | 0)
+#define MT8173_PIN_114_UTXD0__FUNC_UTXD0 (MTK_PIN_NO(114) | 1)
+#define MT8173_PIN_114_UTXD0__FUNC_URXD0 (MTK_PIN_NO(114) | 2)
+#define MT8173_PIN_114_UTXD0__FUNC_I2S2_BCK (MTK_PIN_NO(114) | 6)
+#define MT8173_PIN_114_UTXD0__FUNC_DBG_MON_A_1_ (MTK_PIN_NO(114) | 7)
+
+#define MT8173_PIN_115_URTS0__FUNC_GPIO115 (MTK_PIN_NO(115) | 0)
+#define MT8173_PIN_115_URTS0__FUNC_URTS0 (MTK_PIN_NO(115) | 1)
+#define MT8173_PIN_115_URTS0__FUNC_UCTS0 (MTK_PIN_NO(115) | 2)
+#define MT8173_PIN_115_URTS0__FUNC_I2S2_MCK (MTK_PIN_NO(115) | 6)
+#define MT8173_PIN_115_URTS0__FUNC_DBG_MON_A_2_ (MTK_PIN_NO(115) | 7)
+
+#define MT8173_PIN_116_UCTS0__FUNC_GPIO116 (MTK_PIN_NO(116) | 0)
+#define MT8173_PIN_116_UCTS0__FUNC_UCTS0 (MTK_PIN_NO(116) | 1)
+#define MT8173_PIN_116_UCTS0__FUNC_URTS0 (MTK_PIN_NO(116) | 2)
+#define MT8173_PIN_116_UCTS0__FUNC_I2S2_DI_1 (MTK_PIN_NO(116) | 6)
+#define MT8173_PIN_116_UCTS0__FUNC_DBG_MON_A_3_ (MTK_PIN_NO(116) | 7)
+
+#define MT8173_PIN_117_URXD3__FUNC_GPIO117 (MTK_PIN_NO(117) | 0)
+#define MT8173_PIN_117_URXD3__FUNC_URXD3 (MTK_PIN_NO(117) | 1)
+#define MT8173_PIN_117_URXD3__FUNC_UTXD3 (MTK_PIN_NO(117) | 2)
+#define MT8173_PIN_117_URXD3__FUNC_DBG_MON_A_9_ (MTK_PIN_NO(117) | 7)
+
+#define MT8173_PIN_118_UTXD3__FUNC_GPIO118 (MTK_PIN_NO(118) | 0)
+#define MT8173_PIN_118_UTXD3__FUNC_UTXD3 (MTK_PIN_NO(118) | 1)
+#define MT8173_PIN_118_UTXD3__FUNC_URXD3 (MTK_PIN_NO(118) | 2)
+#define MT8173_PIN_118_UTXD3__FUNC_DBG_MON_A_10_ (MTK_PIN_NO(118) | 7)
+
+#define MT8173_PIN_119_KPROW0__FUNC_GPIO119 (MTK_PIN_NO(119) | 0)
+#define MT8173_PIN_119_KPROW0__FUNC_KROW0 (MTK_PIN_NO(119) | 1)
+#define MT8173_PIN_119_KPROW0__FUNC_DBG_MON_A_11_ (MTK_PIN_NO(119) | 7)
+
+#define MT8173_PIN_120_KPROW1__FUNC_GPIO120 (MTK_PIN_NO(120) | 0)
+#define MT8173_PIN_120_KPROW1__FUNC_KROW1 (MTK_PIN_NO(120) | 1)
+#define MT8173_PIN_120_KPROW1__FUNC_PWM6 (MTK_PIN_NO(120) | 3)
+#define MT8173_PIN_120_KPROW1__FUNC_DBG_MON_A_12_ (MTK_PIN_NO(120) | 7)
+
+#define MT8173_PIN_121_KPROW2__FUNC_GPIO121 (MTK_PIN_NO(121) | 0)
+#define MT8173_PIN_121_KPROW2__FUNC_KROW2 (MTK_PIN_NO(121) | 1)
+#define MT8173_PIN_121_KPROW2__FUNC_IRDA_PDN (MTK_PIN_NO(121) | 2)
+#define MT8173_PIN_121_KPROW2__FUNC_USB_DRVVBUS_P0 (MTK_PIN_NO(121) | 3)
+#define MT8173_PIN_121_KPROW2__FUNC_PWM4 (MTK_PIN_NO(121) | 4)
+#define MT8173_PIN_121_KPROW2__FUNC_USB_DRVVBUS_P1 (MTK_PIN_NO(121) | 5)
+#define MT8173_PIN_121_KPROW2__FUNC_DBG_MON_A_13_ (MTK_PIN_NO(121) | 7)
+
+#define MT8173_PIN_122_KPCOL0__FUNC_GPIO122 (MTK_PIN_NO(122) | 0)
+#define MT8173_PIN_122_KPCOL0__FUNC_KCOL0 (MTK_PIN_NO(122) | 1)
+#define MT8173_PIN_122_KPCOL0__FUNC_DBG_MON_A_14_ (MTK_PIN_NO(122) | 7)
+
+#define MT8173_PIN_123_KPCOL1__FUNC_GPIO123 (MTK_PIN_NO(123) | 0)
+#define MT8173_PIN_123_KPCOL1__FUNC_KCOL1 (MTK_PIN_NO(123) | 1)
+#define MT8173_PIN_123_KPCOL1__FUNC_IRDA_RXD (MTK_PIN_NO(123) | 2)
+#define MT8173_PIN_123_KPCOL1__FUNC_PWM5 (MTK_PIN_NO(123) | 3)
+#define MT8173_PIN_123_KPCOL1__FUNC_DBG_MON_A_15_ (MTK_PIN_NO(123) | 7)
+
+#define MT8173_PIN_124_KPCOL2__FUNC_GPIO124 (MTK_PIN_NO(124) | 0)
+#define MT8173_PIN_124_KPCOL2__FUNC_KCOL2 (MTK_PIN_NO(124) | 1)
+#define MT8173_PIN_124_KPCOL2__FUNC_IRDA_TXD (MTK_PIN_NO(124) | 2)
+#define MT8173_PIN_124_KPCOL2__FUNC_USB_DRVVBUS_P0 (MTK_PIN_NO(124) | 3)
+#define MT8173_PIN_124_KPCOL2__FUNC_PWM3 (MTK_PIN_NO(124) | 4)
+#define MT8173_PIN_124_KPCOL2__FUNC_USB_DRVVBUS_P1 (MTK_PIN_NO(124) | 5)
+#define MT8173_PIN_124_KPCOL2__FUNC_DBG_MON_A_16_ (MTK_PIN_NO(124) | 7)
+
+#define MT8173_PIN_125_SDA1__FUNC_GPIO125 (MTK_PIN_NO(125) | 0)
+#define MT8173_PIN_125_SDA1__FUNC_SDA1 (MTK_PIN_NO(125) | 1)
+
+#define MT8173_PIN_126_SCL1__FUNC_GPIO126 (MTK_PIN_NO(126) | 0)
+#define MT8173_PIN_126_SCL1__FUNC_SCL1 (MTK_PIN_NO(126) | 1)
+
+#define MT8173_PIN_127_LCM_RST__FUNC_GPIO127 (MTK_PIN_NO(127) | 0)
+#define MT8173_PIN_127_LCM_RST__FUNC_LCM_RST (MTK_PIN_NO(127) | 1)
+
+#define MT8173_PIN_128_I2S0_LRCK__FUNC_GPIO128 (MTK_PIN_NO(128) | 0)
+#define MT8173_PIN_128_I2S0_LRCK__FUNC_I2S0_WS (MTK_PIN_NO(128) | 1)
+#define MT8173_PIN_128_I2S0_LRCK__FUNC_I2S1_WS (MTK_PIN_NO(128) | 2)
+#define MT8173_PIN_128_I2S0_LRCK__FUNC_I2S2_WS (MTK_PIN_NO(128) | 3)
+#define MT8173_PIN_128_I2S0_LRCK__FUNC_SPI_CK_2_ (MTK_PIN_NO(128) | 5)
+#define MT8173_PIN_128_I2S0_LRCK__FUNC_DBG_MON_A_4_ (MTK_PIN_NO(128) | 7)
+
+#define MT8173_PIN_129_I2S0_BCK__FUNC_GPIO129 (MTK_PIN_NO(129) | 0)
+#define MT8173_PIN_129_I2S0_BCK__FUNC_I2S0_BCK (MTK_PIN_NO(129) | 1)
+#define MT8173_PIN_129_I2S0_BCK__FUNC_I2S1_BCK (MTK_PIN_NO(129) | 2)
+#define MT8173_PIN_129_I2S0_BCK__FUNC_I2S2_BCK (MTK_PIN_NO(129) | 3)
+#define MT8173_PIN_129_I2S0_BCK__FUNC_SPI_MI_2_ (MTK_PIN_NO(129) | 5)
+#define MT8173_PIN_129_I2S0_BCK__FUNC_DBG_MON_A_5_ (MTK_PIN_NO(129) | 7)
+
+#define MT8173_PIN_130_I2S0_MCK__FUNC_GPIO130 (MTK_PIN_NO(130) | 0)
+#define MT8173_PIN_130_I2S0_MCK__FUNC_I2S0_MCK (MTK_PIN_NO(130) | 1)
+#define MT8173_PIN_130_I2S0_MCK__FUNC_I2S1_MCK (MTK_PIN_NO(130) | 2)
+#define MT8173_PIN_130_I2S0_MCK__FUNC_I2S2_MCK (MTK_PIN_NO(130) | 3)
+#define MT8173_PIN_130_I2S0_MCK__FUNC_SPI_MO_2_ (MTK_PIN_NO(130) | 5)
+#define MT8173_PIN_130_I2S0_MCK__FUNC_DBG_MON_A_6_ (MTK_PIN_NO(130) | 7)
+
+#define MT8173_PIN_131_I2S0_DATA0__FUNC_GPIO131 (MTK_PIN_NO(131) | 0)
+#define MT8173_PIN_131_I2S0_DATA0__FUNC_I2S0_DO (MTK_PIN_NO(131) | 1)
+#define MT8173_PIN_131_I2S0_DATA0__FUNC_I2S1_DO_1 (MTK_PIN_NO(131) | 2)
+#define MT8173_PIN_131_I2S0_DATA0__FUNC_I2S2_DI_1 (MTK_PIN_NO(131) | 3)
+#define MT8173_PIN_131_I2S0_DATA0__FUNC_SPI_CS_2_ (MTK_PIN_NO(131) | 5)
+#define MT8173_PIN_131_I2S0_DATA0__FUNC_DBG_MON_A_7_ (MTK_PIN_NO(131) | 7)
+
+#define MT8173_PIN_132_I2S0_DATA1__FUNC_GPIO132 (MTK_PIN_NO(132) | 0)
+#define MT8173_PIN_132_I2S0_DATA1__FUNC_I2S0_DI (MTK_PIN_NO(132) | 1)
+#define MT8173_PIN_132_I2S0_DATA1__FUNC_I2S1_DO_2 (MTK_PIN_NO(132) | 2)
+#define MT8173_PIN_132_I2S0_DATA1__FUNC_I2S2_DI_2 (MTK_PIN_NO(132) | 3)
+#define MT8173_PIN_132_I2S0_DATA1__FUNC_DBG_MON_A_8_ (MTK_PIN_NO(132) | 7)
+
+#define MT8173_PIN_133_SDA4__FUNC_GPIO133 (MTK_PIN_NO(133) | 0)
+#define MT8173_PIN_133_SDA4__FUNC_SDA4 (MTK_PIN_NO(133) | 1)
+
+#define MT8173_PIN_134_SCL4__FUNC_GPIO134 (MTK_PIN_NO(134) | 0)
+#define MT8173_PIN_134_SCL4__FUNC_SCL4 (MTK_PIN_NO(134) | 1)
+
+#endif /* __DTS_MT8173_PINFUNC_H */
index 8554ec31dd9ec823de5017d0d1ec3f00bba543e6..924fdb6673ff62a46616b59143f6785f4a3540aa 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "mt8173-pinfunc.h"
 
 / {
        compatible = "mediatek,mt8173";
                compatible = "simple-bus";
                ranges;
 
+               syscfg_pctl_a: syscfg_pctl_a@10005000 {
+                       compatible = "mediatek,mt8173-pctl-a-syscfg", "syscon";
+                       reg = <0 0x10005000 0 0x1000>;
+               };
+
+               pio: pinctrl@0x10005000 {
+                       compatible = "mediatek,mt8173-pinctrl";
+                       reg = <0 0x1000B000 0 0x1000>;
+                       mediatek,pctl-regmap = <&syscfg_pctl_a>;
+                       pins-are-numbered;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>,
+                                               <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>,
+                                               <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>;
+               };
+
                sysirq: intpol-controller@10200620 {
                        compatible = "mediatek,mt8173-sysirq",
                                        "mediatek,mt6577-sysirq";
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
new file mode 100644 (file)
index 0000000..8e94af6
--- /dev/null
@@ -0,0 +1,5 @@
+dtb-$(CONFIG_ARCH_QCOM)        += apq8016-sbc.dtb msm8916-mtp.dtb
+
+always         := $(dtb-y)
+subdir-y       := $(dts-dirs)
+clean-files    := *.dtb
diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc.dts b/arch/arm64/boot/dts/qcom/apq8016-sbc.dts
new file mode 100644 (file)
index 0000000..825f489
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ */
+
+/dts-v1/;
+
+#include "apq8016-sbc.dtsi"
+
+/ {
+       model = "Qualcomm Technologies, Inc. APQ 8016 SBC";
+       compatible = "qcom,apq8016-sbc", "qcom,apq8016", "qcom,sbc";
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi b/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
new file mode 100644 (file)
index 0000000..703a4f1
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "msm8916.dtsi"
+
+/ {
+       aliases {
+               serial0 = &blsp1_uart2;
+       };
+
+       chosen {
+               stdout-path = "serial0";
+       };
+
+       soc {
+               serial@78b0000 {
+                       status = "okay";
+                       pinctrl-names = "default", "sleep";
+                       pinctrl-0 = <&blsp1_uart2_default>;
+                       pinctrl-1 = <&blsp1_uart2_sleep>;
+               };
+       };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8916-mtp.dts b/arch/arm64/boot/dts/qcom/msm8916-mtp.dts
new file mode 100644 (file)
index 0000000..fced77f
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ */
+
+/dts-v1/;
+
+#include "msm8916-mtp.dtsi"
+
+/ {
+       model = "Qualcomm Technologies, Inc. MSM 8916 MTP";
+       compatible = "qcom,msm8916-mtp", "qcom,msm8916-mtp-smb1360",
+                       "qcom,msm8916", "qcom,mtp";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8916-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8916-mtp.dtsi
new file mode 100644 (file)
index 0000000..bea871b
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "msm8916.dtsi"
+
+/ {
+       aliases {
+               serial0 = &blsp1_uart2;
+       };
+
+       chosen {
+               stdout-path = "serial0";
+       };
+
+       soc {
+               serial@78b0000 {
+                       status = "okay";
+                       pinctrl-names = "default", "sleep";
+                       pinctrl-0 = <&blsp1_uart2_default>;
+                       pinctrl-1 = <&blsp1_uart2_sleep>;
+               };
+       };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
new file mode 100644 (file)
index 0000000..f212b83
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/qcom,gcc-msm8916.h>
+#include <dt-bindings/reset/qcom,gcc-msm8916.h>
+
+/ {
+       model = "Qualcomm Technologies, Inc. MSM8916";
+       compatible = "qcom,msm8916";
+
+       interrupt-parent = <&intc>;
+
+       #address-cells = <2>;
+       #size-cells = <2>;
+
+       aliases { };
+
+       chosen { };
+
+       memory {
+               device_type = "memory";
+               /* We expect the bootloader to fill in the reg */
+               reg = <0 0 0 0>;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               CPU0: cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <0x0>;
+               };
+
+               CPU1: cpu@1 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <0x1>;
+               };
+
+               CPU2: cpu@2 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <0x2>;
+               };
+
+               CPU3: cpu@3 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <0x3>;
+               };
+       };
+
+       timer {
+               compatible = "arm,armv8-timer";
+               interrupts = <GIC_PPI 2 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 3 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 4 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 1 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+       };
+
+       soc: soc {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0 0 0 0xffffffff>;
+               compatible = "simple-bus";
+
+               pinctrl@1000000 {
+                       compatible = "qcom,msm8916-pinctrl";
+                       reg = <0x1000000 0x300000>;
+                       interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+
+                       blsp1_uart2_default: blsp1_uart2_default {
+                               pinmux {
+                                       function = "blsp_uart2";
+                                       pins = "gpio4", "gpio5";
+                               };
+                               pinconf {
+                                       pins = "gpio4", "gpio5";
+                                       drive-strength = <16>;
+                                       bias-disable;
+                               };
+                       };
+
+                       blsp1_uart2_sleep: blsp1_uart2_sleep {
+                               pinmux {
+                                       function = "blsp_uart2";
+                                       pins = "gpio4", "gpio5";
+                               };
+                               pinconf {
+                                       pins = "gpio4", "gpio5";
+                                       drive-strength = <2>;
+                                       bias-pull-down;
+                               };
+                       };
+               };
+
+               gcc: qcom,gcc@1800000 {
+                       compatible = "qcom,gcc-msm8916";
+                       #clock-cells = <1>;
+                       #reset-cells = <1>;
+                       reg = <0x1800000 0x80000>;
+               };
+
+               blsp1_uart2: serial@78b0000 {
+                       compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
+                       reg = <0x78b0000 0x200>;
+                       interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&gcc GCC_BLSP1_UART2_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>;
+                       clock-names = "core", "iface";
+                       status = "disabled";
+               };
+
+               intc: interrupt-controller@b000000 {
+                       compatible = "qcom,msm-qgic2";
+                       interrupt-controller;
+                       #interrupt-cells = <3>;
+                       reg = <0x0b000000 0x1000>, <0x0b002000 0x1000>;
+               };
+
+               timer@b020000 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges;
+                       compatible = "arm,armv7-timer-mem";
+                       reg = <0xb020000 0x1000>;
+                       clock-frequency = <19200000>;
+
+                       frame@b021000 {
+                               frame-number = <0>;
+                               interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+                               reg = <0xb021000 0x1000>,
+                                     <0xb022000 0x1000>;
+                       };
+
+                       frame@b023000 {
+                               frame-number = <1>;
+                               interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+                               reg = <0xb023000 0x1000>;
+                               status = "disabled";
+                       };
+
+                       frame@b024000 {
+                               frame-number = <2>;
+                               interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+                               reg = <0xb024000 0x1000>;
+                               status = "disabled";
+                       };
+
+                       frame@b025000 {
+                               frame-number = <3>;
+                               interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+                               reg = <0xb025000 0x1000>;
+                               status = "disabled";
+                       };
+
+                       frame@b026000 {
+                               frame-number = <4>;
+                               interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+                               reg = <0xb026000 0x1000>;
+                               status = "disabled";
+                       };
+
+                       frame@b027000 {
+                               frame-number = <5>;
+                               interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+                               reg = <0xb027000 0x1000>;
+                               status = "disabled";
+                       };
+
+                       frame@b028000 {
+                               frame-number = <6>;
+                               interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+                               reg = <0xb028000 0x1000>;
+                               status = "disabled";
+                       };
+               };
+       };
+};
diff --git a/arch/arm64/boot/dts/sprd/Makefile b/arch/arm64/boot/dts/sprd/Makefile
new file mode 100644 (file)
index 0000000..b658c5e
--- /dev/null
@@ -0,0 +1,5 @@
+dtb-$(CONFIG_ARCH_SPRD) += sc9836-openphone.dtb
+
+always         := $(dtb-y)
+subdir-y       := $(dts-dirs)
+clean-files    := *.dtb
diff --git a/arch/arm64/boot/dts/sprd/sc9836-openphone.dts b/arch/arm64/boot/dts/sprd/sc9836-openphone.dts
new file mode 100644 (file)
index 0000000..e5657c3
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Spreadtrum SC9836 openphone board DTS file
+ *
+ * Copyright (C) 2014, Spreadtrum Communications Inc.
+ *
+ * This file is licensed under a dual GPLv2 or X11 license.
+ */
+
+/dts-v1/;
+
+#include "sc9836.dtsi"
+
+/ {
+       model = "Spreadtrum SC9836 Openphone Board";
+
+       compatible = "sprd,sc9836-openphone", "sprd,sc9836";
+
+       aliases {
+               serial0 = &uart0;
+               serial1 = &uart1;
+               serial2 = &uart2;
+               serial3 = &uart3;
+       };
+
+       memory@80000000 {
+               device_type = "memory";
+               reg = <0 0x80000000 0 0x20000000>;
+       };
+
+       chosen {
+               stdout-path = "serial1:115200n8";
+       };
+};
+
+&uart0 {
+       status = "okay";
+};
+
+&uart1 {
+       status = "okay";
+};
+
+&uart2 {
+       status = "okay";
+};
+
+&uart3 {
+       status = "okay";
+};
diff --git a/arch/arm64/boot/dts/sprd/sc9836.dtsi b/arch/arm64/boot/dts/sprd/sc9836.dtsi
new file mode 100644 (file)
index 0000000..ee34e1a
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Spreadtrum SC9836 SoC DTS file
+ *
+ * Copyright (C) 2014, Spreadtrum Communications Inc.
+ *
+ * This file is licensed under a dual GPLv2 or X11 license.
+ */
+
+#include "sharkl64.dtsi"
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+       compatible = "sprd,sc9836";
+
+       cpus {
+               #address-cells = <2>;
+               #size-cells = <0>;
+
+               cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <0x0 0x0>;
+                       enable-method = "psci";
+               };
+
+               cpu@1 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <0x0 0x1>;
+                       enable-method = "psci";
+               };
+
+               cpu@2 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <0x0 0x2>;
+                       enable-method = "psci";
+               };
+
+               cpu@3 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <0x0 0x3>;
+                       enable-method = "psci";
+               };
+       };
+
+       etf@10003000 {
+               compatible = "arm,coresight-tmc", "arm,primecell";
+               reg = <0 0x10003000 0 0x1000>;
+               clocks = <&clk26mhz>;
+               clock-names = "apb_pclk";
+               port {
+                       etf_in: endpoint {
+                               slave-mode;
+                               remote-endpoint = <&funnel_out_port0>;
+                       };
+               };
+       };
+
+       funnel@10001000 {
+               compatible = "arm,coresight-funnel", "arm,primecell";
+               reg = <0 0x10001000 0 0x1000>;
+               clocks = <&clk26mhz>;
+               clock-names = "apb_pclk";
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       /* funnel output port */
+                       port@0 {
+                               reg = <0>;
+                               funnel_out_port0: endpoint {
+                                       remote-endpoint = <&etf_in>;
+                               };
+                       };
+
+                       /* funnel input port 0~3 is reserved for ETMs */
+                       port@1 {
+                               reg = <4>;
+                               funnel_in_port4: endpoint {
+                                       slave-mode;
+                                       remote-endpoint = <&stm_out>;
+                               };
+                       };
+               };
+       };
+
+       stm@10006000 {
+               compatible = "arm,coresight-stm", "arm,primecell";
+               reg = <0 0x10006000 0 0x1000>,
+                     <0 0x01000000 0 0x180000>;
+               reg-names = "stm-base", "stm-stimulus-base";
+               clocks = <&clk26mhz>;
+               clock-names = "apb_pclk";
+               port {
+                       stm_out: endpoint {
+                               remote-endpoint = <&funnel_in_port4>;
+                       };
+               };
+       };
+
+       gic: interrupt-controller@12001000 {
+               compatible = "arm,gic-400";
+               reg = <0 0x12001000 0 0x1000>,
+                     <0 0x12002000 0 0x2000>,
+                     <0 0x12004000 0 0x2000>,
+                     <0 0x12006000 0 0x2000>;
+               #interrupt-cells = <3>;
+               interrupt-controller;
+               interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+       };
+
+       psci {
+               compatible      = "arm,psci";
+               method          = "smc";
+               cpu_on          = <0xc4000003>;
+               cpu_off         = <0x84000002>;
+               cpu_suspend     = <0xc4000001>;
+       };
+
+       timer {
+               compatible = "arm,armv8-timer";
+               interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+       };
+};
diff --git a/arch/arm64/boot/dts/sprd/sharkl64.dtsi b/arch/arm64/boot/dts/sprd/sharkl64.dtsi
new file mode 100644 (file)
index 0000000..69f64e7
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Spreadtrum Sharkl64 platform DTS file
+ *
+ * Copyright (C) 2014, Spreadtrum Communications Inc.
+ *
+ * This file is licensed under a dual GPLv2 or X11 license.
+ */
+
+/ {
+       interrupt-parent = <&gic>;
+       #address-cells = <2>;
+       #size-cells = <2>;
+
+       soc {
+               compatible = "simple-bus";
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges;
+
+               ap-apb {
+                       compatible = "simple-bus";
+                       #address-cells = <2>;
+                       #size-cells = <2>;
+                       ranges;
+
+                       uart0: serial@70000000 {
+                               compatible = "sprd,sc9836-uart";
+                               reg = <0 0x70000000 0 0x100>;
+                               interrupts = <0 2 0xf04>;
+                               clocks = <&clk26mhz>;
+                               status = "disabled";
+                       };
+
+                       uart1: serial@70100000 {
+                               compatible = "sprd,sc9836-uart";
+                               reg = <0 0x70100000 0 0x100>;
+                               interrupts = <0 3 0xf04>;
+                               clocks = <&clk26mhz>;
+                               status = "disabled";
+                       };
+
+                       uart2: serial@70200000 {
+                               compatible = "sprd,sc9836-uart";
+                               reg = <0 0x70200000 0 0x100>;
+                               interrupts = <0 4 0xf04>;
+                               clocks = <&clk26mhz>;
+                               status = "disabled";
+                       };
+
+                       uart3: serial@70300000 {
+                               compatible = "sprd,sc9836-uart";
+                               reg = <0 0x70300000 0 0x100>;
+                               interrupts = <0 5 0xf04>;
+                               clocks = <&clk26mhz>;
+                               status = "disabled";
+                       };
+               };
+       };
+
+       clk26mhz: clk26mhz {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <26000000>;
+       };
+};
diff --git a/arch/arm64/boot/dts/xilinx/Makefile b/arch/arm64/boot/dts/xilinx/Makefile
new file mode 100644 (file)
index 0000000..ae16427
--- /dev/null
@@ -0,0 +1,5 @@
+dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-ep108.dtb
+
+always         := $(dtb-y)
+subdir-y       := $(dts-dirs)
+clean-files    := *.dtb
diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts b/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts
new file mode 100644 (file)
index 0000000..0a3f40e
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * 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"
+
+/ {
+       model = "ZynqMP EP108";
+
+       aliases {
+               serial0 = &uart0;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x0 0x0 0x40000000>;
+       };
+};
+
+&gem0 {
+       status = "okay";
+       phy-handle = <&phy0>;
+       phy-mode = "rgmii-id";
+       phy0: phy@0{
+               reg = <0>;
+               max-speed = <100>;
+       };
+};
+
+&uart0 {
+       status = "okay";
+};
diff --git a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
new file mode 100644 (file)
index 0000000..11e0b00
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ * dts file for Xilinx ZynqMP
+ *
+ * (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.
+ */
+
+/ {
+       compatible = "xlnx,zynqmp";
+       #address-cells = <2>;
+       #size-cells = <1>;
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@0 {
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       device_type = "cpu";
+                       enable-method = "psci";
+                       reg = <0x0>;
+               };
+
+               cpu@1 {
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       device_type = "cpu";
+                       enable-method = "psci";
+                       reg = <0x1>;
+               };
+
+               cpu@2 {
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       device_type = "cpu";
+                       enable-method = "psci";
+                       reg = <0x2>;
+               };
+
+               cpu@3 {
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       device_type = "cpu";
+                       enable-method = "psci";
+                       reg = <0x3>;
+               };
+       };
+
+       pmu {
+               compatible = "arm,armv8-pmuv3";
+               interrupts = <0 143 4>,
+                            <0 144 4>,
+                            <0 145 4>,
+                            <0 146 4>;
+       };
+
+       psci {
+               compatible = "arm,psci-0.2";
+               method = "smc";
+       };
+
+       timer {
+               compatible = "arm,armv8-timer";
+               interrupt-parent = <&gic>;
+               interrupts = <1 13 0xf01>,
+                            <1 14 0xf01>,
+                            <1 11 0xf01>,
+                            <1 10 0xf01>;
+       };
+
+       amba_apu {
+               compatible = "simple-bus";
+               #address-cells = <2>;
+               #size-cells = <1>;
+               ranges;
+
+               gic: interrupt-controller@f9010000 {
+                       compatible = "arm,gic-400", "arm,cortex-a15-gic";
+                       #interrupt-cells = <3>;
+                       reg = <0x0 0xf9010000 0x10000>,
+                             <0x0 0xf902f000 0x2000>,
+                             <0x0 0xf9040000 0x20000>,
+                             <0x0 0xf906f000 0x2000>;
+                       interrupt-controller;
+                       interrupt-parent = <&gic>;
+                       interrupts = <1 9 0xf04>;
+               };
+       };
+
+       amba {
+               compatible = "simple-bus";
+               #address-cells = <2>;
+               #size-cells = <1>;
+               ranges;
+
+               misc_clk: misc_clk {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <25000000>;
+               };
+
+               ttc0: timer@ff110000 {
+                       compatible = "cdns,ttc";
+                       status = "disabled";
+                       interrupt-parent = <&gic>;
+                       interrupts = <0 36 4>, <0 37 4>, <0 38 4>;
+                       reg = <0x0 0xff110000 0x1000>;
+                       clocks = <&misc_clk>;
+                       timer-width = <32>;
+               };
+
+               ttc1: timer@ff120000 {
+                       compatible = "cdns,ttc";
+                       status = "disabled";
+                       interrupt-parent = <&gic>;
+                       interrupts = <0 39 4>, <0 40 4>, <0 41 4>;
+                       reg = <0x0 0xff120000 0x1000>;
+                       clocks = <&misc_clk>;
+                       timer-width = <32>;
+               };
+
+               ttc2: timer@ff130000 {
+                       compatible = "cdns,ttc";
+                       status = "disabled";
+                       interrupt-parent = <&gic>;
+                       interrupts = <0 42 4>, <0 43 4>, <0 44 4>;
+                       reg = <0x0 0xff130000 0x1000>;
+                       clocks = <&misc_clk>;
+                       timer-width = <32>;
+               };
+
+               ttc3: timer@ff140000 {
+                       compatible = "cdns,ttc";
+                       status = "disabled";
+                       interrupt-parent = <&gic>;
+                       interrupts = <0 45 4>, <0 46 4>, <0 47 4>;
+                       reg = <0x0 0xff140000 0x1000>;
+                       clocks = <&misc_clk>;
+                       timer-width = <32>;
+               };
+
+               uart0: serial@ff000000 {
+                       compatible = "cdns,uart-r1p8";
+                       status = "disabled";
+                       interrupt-parent = <&gic>;
+                       interrupts = <0 21 4>;
+                       reg = <0x0 0xff000000 0x1000>;
+                       clock-names = "uart_clk", "pclk";
+                       clocks = <&misc_clk &misc_clk>;
+               };
+
+               uart1: serial@ff010000 {
+                       compatible = "cdns,uart-r1p8";
+                       status = "disabled";
+                       interrupt-parent = <&gic>;
+                       interrupts = <0 22 4>;
+                       reg = <0x0 0xff010000 0x1000>;
+                       clock-names = "uart_clk", "pclk";
+                       clocks = <&misc_clk &misc_clk>;
+               };
+
+               gpio: gpio@ff0a0000 {
+                       compatible = "xlnx,zynq-gpio-1.0";
+                       status = "disabled";
+                       #gpio-cells = <0x2>;
+                       clocks = <&misc_clk>;
+                       interrupt-parent = <&gic>;
+                       interrupts = <0 16 4>;
+                       reg = <0x0 0xff0a0000 0x1000>;
+               };
+
+               gem0: ethernet@ff0b0000 {
+                       compatible = "cdns,gem";
+                       status = "disabled";
+                       interrupt-parent = <&gic>;
+                       interrupts = <0 57 4>, <0 57 4>;
+                       reg = <0x0 0xff0b0000 0x1000>;
+                       clock-names = "pclk", "hclk", "tx_clk";
+                       clocks = <&misc_clk>, <&misc_clk>, <&misc_clk>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               gem1: ethernet@ff0c0000 {
+                       compatible = "cdns,gem";
+                       status = "disabled";
+                       interrupt-parent = <&gic>;
+                       interrupts = <0 59 4>, <0 59 4>;
+                       reg = <0x0 0xff0c0000 0x1000>;
+                       clock-names = "pclk", "hclk", "tx_clk";
+                       clocks = <&misc_clk>, <&misc_clk>, <&misc_clk>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               gem2: ethernet@ff0d0000 {
+                       compatible = "cdns,gem";
+                       status = "disabled";
+                       interrupt-parent = <&gic>;
+                       interrupts = <0 61 4>, <0 61 4>;
+                       reg = <0x0 0xff0d0000 0x1000>;
+                       clock-names = "pclk", "hclk", "tx_clk";
+                       clocks = <&misc_clk>, <&misc_clk>, <&misc_clk>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               gem3: ethernet@ff0e0000 {
+                       compatible = "cdns,gem";
+                       status = "disabled";
+                       interrupt-parent = <&gic>;
+                       interrupts = <0 63 4>, <0 63 4>;
+                       reg = <0x0 0xff0e0000 0x1000>;
+                       clock-names = "pclk", "hclk", "tx_clk";
+                       clocks = <&misc_clk>, <&misc_clk>, <&misc_clk>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               spi0: spi@ff040000 {
+                       compatible = "cdns,spi-r1p6";
+                       status = "disabled";
+                       interrupt-parent = <&gic>;
+                       interrupts = <0 19 4>;
+                       reg = <0x0 0xff040000 0x1000>;
+                       clock-names = "ref_clk", "pclk";
+                       clocks = <&misc_clk &misc_clk>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               spi1: spi@ff050000 {
+                       compatible = "cdns,spi-r1p6";
+                       status = "disabled";
+                       interrupt-parent = <&gic>;
+                       interrupts = <0 20 4>;
+                       reg = <0x0 0xff050000 0x1000>;
+                       clock-names = "ref_clk", "pclk";
+                       clocks = <&misc_clk &misc_clk>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               i2c_clk: i2c_clk {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0x0>;
+                       clock-frequency = <111111111>;
+               };
+
+               i2c0: i2c@ff020000 {
+                       compatible = "cdns,i2c-r1p10";
+                       status = "disabled";
+                       interrupt-parent = <&gic>;
+                       interrupts = <0 17 4>;
+                       reg = <0x0 0xff020000 0x1000>;
+                       clocks = <&i2c_clk>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               i2c1: i2c@ff030000 {
+                       compatible = "cdns,i2c-r1p10";
+                       status = "disabled";
+                       interrupt-parent = <&gic>;
+                       interrupts = <0 18 4>;
+                       reg = <0x0 0xff030000 0x1000>;
+                       clocks = <&i2c_clk>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               sdhci0: sdhci@ff160000 {
+                       compatible = "arasan,sdhci-8.9a";
+                       status = "disabled";
+                       interrupt-parent = <&gic>;
+                       interrupts = <0 48 4>;
+                       reg = <0x0 0xff160000 0x1000>;
+                       clock-names = "clk_xin", "clk_ahb";
+                       clocks = <&misc_clk>, <&misc_clk>;
+               };
+
+               sdhci1: sdhci@ff170000 {
+                       compatible = "arasan,sdhci-8.9a";
+                       status = "disabled";
+                       interrupt-parent = <&gic>;
+                       interrupts = <0 49 4>;
+                       reg = <0x0 0xff170000 0x1000>;
+                       clock-names = "clk_xin", "clk_ahb";
+                       clocks = <&misc_clk>, <&misc_clk>;
+               };
+
+               watchdog0: watchdog@fd4d0000 {
+                       compatible = "cdns,wdt-r1p2";
+                       status = "disabled";
+                       clocks= <&misc_clk>;
+                       interrupt-parent = <&gic>;
+                       interrupts = <0 52 1>;
+                       reg = <0x0 0xfd4d0000 0x1000>;
+                       timeout-sec = <10>;
+               };
+       };
+};
index 4e03d8dd23f6fe7423df8971484195b071756cd5..2ed7449d9273c01b314d59c7a81b12472b4f7948 100644 (file)
@@ -37,9 +37,12 @@ CONFIG_ARCH_MEDIATEK=y
 CONFIG_ARCH_SEATTLE=y
 CONFIG_ARCH_TEGRA=y
 CONFIG_ARCH_TEGRA_132_SOC=y
+CONFIG_ARCH_QCOM=y
+CONFIG_ARCH_SPRD=y
 CONFIG_ARCH_THUNDER=y
 CONFIG_ARCH_VEXPRESS=y
 CONFIG_ARCH_XGENE=y
+CONFIG_ARCH_ZYNQMP=y
 CONFIG_PCI=y
 CONFIG_PCI_MSI=y
 CONFIG_PCI_XGENE=y
@@ -99,11 +102,16 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_MT6577=y
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_SERIAL_MSM=y
+CONFIG_SERIAL_MSM_CONSOLE=y
 CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SERIAL_XILINX_PS_UART=y
+CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y
 CONFIG_VIRTIO_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_SPI=y
 CONFIG_SPI_PL022=y
+CONFIG_PINCTRL_MSM8916=y
 CONFIG_GPIO_PL061=y
 CONFIG_GPIO_XGENE=y
 CONFIG_POWER_RESET_XGENE=y
@@ -136,6 +144,8 @@ CONFIG_RTC_DRV_XGENE=y
 CONFIG_VIRTIO_PCI=y
 CONFIG_VIRTIO_BALLOON=y
 CONFIG_VIRTIO_MMIO=y
+CONFIG_COMMON_CLK_QCOM=y
+CONFIG_MSM_GCC_8916=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_PHY_XGENE=y
 CONFIG_EXT2_FS=y
diff --git a/arch/arm64/include/asm/acenv.h b/arch/arm64/include/asm/acenv.h
new file mode 100644 (file)
index 0000000..b49166f
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * ARM64 specific ACPICA environments and implementation
+ *
+ * Copyright (C) 2014, Linaro Ltd.
+ *   Author: Hanjun Guo <hanjun.guo@linaro.org>
+ *   Author: Graeme Gregory <graeme.gregory@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _ASM_ACENV_H
+#define _ASM_ACENV_H
+
+/* It is required unconditionally by ACPI core, update it when needed. */
+
+#endif /* _ASM_ACENV_H */
diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
new file mode 100644 (file)
index 0000000..59c05d8
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ *  Copyright (C) 2013-2014, Linaro Ltd.
+ *     Author: Al Stone <al.stone@linaro.org>
+ *     Author: Graeme Gregory <graeme.gregory@linaro.org>
+ *     Author: Hanjun Guo <hanjun.guo@linaro.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation;
+ */
+
+#ifndef _ASM_ACPI_H
+#define _ASM_ACPI_H
+
+#include <linux/mm.h>
+#include <linux/irqchip/arm-gic-acpi.h>
+
+#include <asm/cputype.h>
+#include <asm/smp_plat.h>
+
+/* Basic configuration for ACPI */
+#ifdef CONFIG_ACPI
+/* ACPI table mapping after acpi_gbl_permanent_mmap is set */
+static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys,
+                                           acpi_size size)
+{
+       if (!page_is_ram(phys >> PAGE_SHIFT))
+               return ioremap(phys, size);
+
+       return ioremap_cache(phys, size);
+}
+#define acpi_os_ioremap acpi_os_ioremap
+
+typedef u64 phys_cpuid_t;
+#define PHYS_CPUID_INVALID INVALID_HWID
+
+#define acpi_strict 1  /* No out-of-spec workarounds on ARM64 */
+extern int acpi_disabled;
+extern int acpi_noirq;
+extern int acpi_pci_disabled;
+
+/* 1 to indicate PSCI 0.2+ is implemented */
+static inline bool acpi_psci_present(void)
+{
+       return acpi_gbl_FADT.arm_boot_flags & ACPI_FADT_PSCI_COMPLIANT;
+}
+
+/* 1 to indicate HVC must be used instead of SMC as the PSCI conduit */
+static inline bool acpi_psci_use_hvc(void)
+{
+       return acpi_gbl_FADT.arm_boot_flags & ACPI_FADT_PSCI_USE_HVC;
+}
+
+static inline void disable_acpi(void)
+{
+       acpi_disabled = 1;
+       acpi_pci_disabled = 1;
+       acpi_noirq = 1;
+}
+
+static inline void enable_acpi(void)
+{
+       acpi_disabled = 0;
+       acpi_pci_disabled = 0;
+       acpi_noirq = 0;
+}
+
+/*
+ * The ACPI processor driver for ACPI core code needs this macro
+ * to find out this cpu was already mapped (mapping from CPU hardware
+ * ID to CPU logical ID) or not.
+ */
+#define cpu_physical_id(cpu) cpu_logical_map(cpu)
+
+/*
+ * It's used from ACPI core in kdump to boot UP system with SMP kernel,
+ * with this check the ACPI core will not override the CPU index
+ * obtained from GICC with 0 and not print some error message as well.
+ * Since MADT must provide at least one GICC structure for GIC
+ * initialization, CPU will be always available in MADT on ARM64.
+ */
+static inline bool acpi_has_cpu_in_madt(void)
+{
+       return true;
+}
+
+static inline void arch_fix_phys_package_id(int num, u32 slot) { }
+void __init acpi_init_cpus(void);
+
+#else
+static inline bool acpi_psci_present(void) { return false; }
+static inline bool acpi_psci_use_hvc(void) { return false; }
+static inline void acpi_init_cpus(void) { }
+#endif /* CONFIG_ACPI */
+
+#endif /*_ASM_ACPI_H*/
diff --git a/arch/arm64/include/asm/arm-cci.h b/arch/arm64/include/asm/arm-cci.h
new file mode 100644 (file)
index 0000000..f0b6371
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * arch/arm64/include/asm/arm-cci.h
+ *
+ * Copyright (C) 2015 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_ARM_CCI_H
+#define __ASM_ARM_CCI_H
+
+static inline bool platform_has_secure_cci_access(void)
+{
+       return false;
+}
+
+#endif
index a5abb0062d6e943d67ca4ff5479e887194482367..71f19c4dc0dee8c8a74bbdea252f73432e0b1aa5 100644 (file)
@@ -65,6 +65,14 @@ do {                                                                 \
 do {                                                                   \
        compiletime_assert_atomic_type(*p);                             \
        switch (sizeof(*p)) {                                           \
+       case 1:                                                         \
+               asm volatile ("stlrb %w1, %0"                           \
+                               : "=Q" (*p) : "r" (v) : "memory");      \
+               break;                                                  \
+       case 2:                                                         \
+               asm volatile ("stlrh %w1, %0"                           \
+                               : "=Q" (*p) : "r" (v) : "memory");      \
+               break;                                                  \
        case 4:                                                         \
                asm volatile ("stlr %w1, %0"                            \
                                : "=Q" (*p) : "r" (v) : "memory");      \
@@ -81,6 +89,14 @@ do {                                                                 \
        typeof(*p) ___p1;                                               \
        compiletime_assert_atomic_type(*p);                             \
        switch (sizeof(*p)) {                                           \
+       case 1:                                                         \
+               asm volatile ("ldarb %w0, %1"                           \
+                       : "=r" (___p1) : "Q" (*p) : "memory");          \
+               break;                                                  \
+       case 2:                                                         \
+               asm volatile ("ldarh %w0, %1"                           \
+                       : "=r" (___p1) : "Q" (*p) : "memory");          \
+               break;                                                  \
        case 4:                                                         \
                asm volatile ("ldar %w0, %1"                            \
                        : "=r" (___p1) : "Q" (*p) : "memory");          \
index da301ee7395c85a11329d246867a008bbb3bc7c2..5a31d671691439b1a329f49d878bbc479f4b253c 100644 (file)
@@ -66,5 +66,6 @@ struct cpu_operations {
 extern const struct cpu_operations *cpu_ops[NR_CPUS];
 int __init cpu_read_ops(struct device_node *dn, int cpu);
 void __init cpu_read_bootcpu_ops(void);
+const struct cpu_operations *cpu_get_ops(const char *name);
 
 #endif /* ifndef __ASM_CPU_OPS_H */
index 92649568655474296e38f1f49697bf25ec3b0b75..95e6b6dcbe37ecdc191a3d37bb0c263265095f31 100644 (file)
@@ -62,6 +62,9 @@ void __init early_fixmap_init(void);
 
 #define __early_set_fixmap __set_fixmap
 
+#define __late_set_fixmap __set_fixmap
+#define __late_clear_fixmap(idx) __set_fixmap((idx), 0, FIXMAP_PAGE_CLEAR)
+
 extern void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot);
 
 #include <asm-generic/fixmap.h>
index 94c53674a31d24f45b6b392d90ac840c6bde7589..bbb251b14746cb7005d1be35d50fdfb453464870 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __ASM_IRQ_H
 #define __ASM_IRQ_H
 
+#include <linux/irqchip/arm-gic-acpi.h>
+
 #include <asm-generic/irq.h>
 
 struct pt_regs;
@@ -8,4 +10,15 @@ struct pt_regs;
 extern void migrate_irqs(void);
 extern void set_handle_irq(void (*handle_irq)(struct pt_regs *));
 
+static inline void acpi_irq_init(void)
+{
+       /*
+        * Hardcode ACPI IRQ chip initialization to GICv2 for now.
+        * Proper irqchip infrastructure will be implemented along with
+        * incoming  GICv2m|GICv3|ITS bits.
+        */
+       acpi_gic_init();
+}
+#define acpi_irq_init acpi_irq_init
+
 #endif
index 872ba939fcb206c287fdba69150aecc5aa4354a1..b008a72f8bc02733347c782f5b9c286cff16f7a2 100644 (file)
 extern int isa_dma_bridge_buggy;
 
 #ifdef CONFIG_PCI
+static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
+{
+       /* no legacy IRQ on arm64 */
+       return -ENODEV;
+}
+
 static inline int pci_proc_domain(struct pci_bus *bus)
 {
        return 1;
index e5312ea0ec1a59bdd92934926da81155a6ce3e12..2454bc59c916b20ce0c275d370d06e47b5cfaf85 100644 (file)
@@ -14,6 +14,7 @@
 #ifndef __ASM_PSCI_H
 #define __ASM_PSCI_H
 
-int psci_init(void);
+int psci_dt_init(void);
+int psci_acpi_init(void);
 
 #endif /* __ASM_PSCI_H */
index 780f82c827b6e733da94fab939380364c9e2b279..bf22650b1a782738275b63cdf8e59fc33450c4ca 100644 (file)
@@ -39,9 +39,10 @@ extern void show_ipi_list(struct seq_file *p, int prec);
 extern void handle_IPI(int ipinr, struct pt_regs *regs);
 
 /*
- * Setup the set of possible CPUs (via set_cpu_possible)
+ * Discover the set of possible CPUs and determine their
+ * SMP operations.
  */
-extern void smp_init_cpus(void);
+extern void of_smp_init_cpus(void);
 
 /*
  * Provide a function to raise an IPI cross call on CPUs in callmap.
index c154c0b7eb604ae09214beed276063f222af69ae..d26832022127e822d9912f19ca73fe6ea794a309 100644 (file)
@@ -188,8 +188,14 @@ struct kvm_arch_memory_slot {
 #define KVM_ARM_IRQ_CPU_IRQ            0
 #define KVM_ARM_IRQ_CPU_FIQ            1
 
-/* Highest supported SPI, from VGIC_NR_IRQS */
+/*
+ * This used to hold the highest supported SPI, but it is now obsolete
+ * and only here to provide source code level compatibility with older
+ * userland. The highest SPI number can be set via KVM_DEV_ARM_VGIC_GRP_NR_IRQS.
+ */
+#ifndef __KERNEL__
 #define KVM_ARM_IRQ_GIC_MAX            127
+#endif
 
 /* One single KVM irqchip, ie. the VGIC */
 #define KVM_NR_IRQCHIPS          1
index b12e15b80516af7862ef6c88be568498173f2b17..426d0763c81bf3ac9113314a25d367e997cf2e17 100644 (file)
@@ -35,6 +35,7 @@ arm64-obj-$(CONFIG_KGDB)              += kgdb.o
 arm64-obj-$(CONFIG_EFI)                        += efi.o efi-stub.o efi-entry.o
 arm64-obj-$(CONFIG_PCI)                        += pci.o
 arm64-obj-$(CONFIG_ARMV8_DEPRECATED)   += armv8_deprecated.o
+arm64-obj-$(CONFIG_ACPI)               += acpi.o
 
 obj-y                                  += $(arm64-obj-y) vdso/
 obj-m                                  += $(arm64-obj-m)
diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
new file mode 100644 (file)
index 0000000..8b83955
--- /dev/null
@@ -0,0 +1,345 @@
+/*
+ *  ARM64 Specific Low-Level ACPI Boot Support
+ *
+ *  Copyright (C) 2013-2014, Linaro Ltd.
+ *     Author: Al Stone <al.stone@linaro.org>
+ *     Author: Graeme Gregory <graeme.gregory@linaro.org>
+ *     Author: Hanjun Guo <hanjun.guo@linaro.org>
+ *     Author: Tomasz Nowicki <tomasz.nowicki@linaro.org>
+ *     Author: Naresh Bhat <naresh.bhat@linaro.org>
+ *
+ *  This program is free software; you can 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 pr_fmt(fmt) "ACPI: " fmt
+
+#include <linux/acpi.h>
+#include <linux/bootmem.h>
+#include <linux/cpumask.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/memblock.h>
+#include <linux/of_fdt.h>
+#include <linux/smp.h>
+
+#include <asm/cputype.h>
+#include <asm/cpu_ops.h>
+#include <asm/smp_plat.h>
+
+int acpi_noirq = 1;            /* skip ACPI IRQ initialization */
+int acpi_disabled = 1;
+EXPORT_SYMBOL(acpi_disabled);
+
+int acpi_pci_disabled = 1;     /* skip ACPI PCI scan and IRQ initialization */
+EXPORT_SYMBOL(acpi_pci_disabled);
+
+/* Processors with enabled flag and sane MPIDR */
+static int enabled_cpus;
+
+/* Boot CPU is valid or not in MADT */
+static bool bootcpu_valid  __initdata;
+
+static bool param_acpi_off __initdata;
+static bool param_acpi_force __initdata;
+
+static int __init parse_acpi(char *arg)
+{
+       if (!arg)
+               return -EINVAL;
+
+       /* "acpi=off" disables both ACPI table parsing and interpreter */
+       if (strcmp(arg, "off") == 0)
+               param_acpi_off = true;
+       else if (strcmp(arg, "force") == 0) /* force ACPI to be enabled */
+               param_acpi_force = true;
+       else
+               return -EINVAL; /* Core will print when we return error */
+
+       return 0;
+}
+early_param("acpi", parse_acpi);
+
+static int __init dt_scan_depth1_nodes(unsigned long node,
+                                      const char *uname, int depth,
+                                      void *data)
+{
+       /*
+        * Return 1 as soon as we encounter a node at depth 1 that is
+        * not the /chosen node.
+        */
+       if (depth == 1 && (strcmp(uname, "chosen") != 0))
+               return 1;
+       return 0;
+}
+
+/*
+ * __acpi_map_table() will be called before page_init(), so early_ioremap()
+ * or early_memremap() should be called here to for ACPI table mapping.
+ */
+char *__init __acpi_map_table(unsigned long phys, unsigned long size)
+{
+       if (!size)
+               return NULL;
+
+       return early_memremap(phys, size);
+}
+
+void __init __acpi_unmap_table(char *map, unsigned long size)
+{
+       if (!map || !size)
+               return;
+
+       early_memunmap(map, size);
+}
+
+/**
+ * acpi_map_gic_cpu_interface - generates a logical cpu number
+ * and map to MPIDR represented by GICC structure
+ */
+static void __init
+acpi_map_gic_cpu_interface(struct acpi_madt_generic_interrupt *processor)
+{
+       int i;
+       u64 mpidr = processor->arm_mpidr & MPIDR_HWID_BITMASK;
+       bool enabled = !!(processor->flags & ACPI_MADT_ENABLED);
+
+       if (mpidr == INVALID_HWID) {
+               pr_info("Skip MADT cpu entry with invalid MPIDR\n");
+               return;
+       }
+
+       total_cpus++;
+       if (!enabled)
+               return;
+
+       if (enabled_cpus >=  NR_CPUS) {
+               pr_warn("NR_CPUS limit of %d reached, Processor %d/0x%llx ignored.\n",
+                       NR_CPUS, total_cpus, mpidr);
+               return;
+       }
+
+       /* Check if GICC structure of boot CPU is available in the MADT */
+       if (cpu_logical_map(0) == mpidr) {
+               if (bootcpu_valid) {
+                       pr_err("Firmware bug, duplicate CPU MPIDR: 0x%llx in MADT\n",
+                              mpidr);
+                       return;
+               }
+
+               bootcpu_valid = true;
+       }
+
+       /*
+        * Duplicate MPIDRs are a recipe for disaster. Scan
+        * all initialized entries and check for
+        * duplicates. If any is found just ignore the CPU.
+        */
+       for (i = 1; i < enabled_cpus; i++) {
+               if (cpu_logical_map(i) == mpidr) {
+                       pr_err("Firmware bug, duplicate CPU MPIDR: 0x%llx in MADT\n",
+                              mpidr);
+                       return;
+               }
+       }
+
+       if (!acpi_psci_present())
+               return;
+
+       cpu_ops[enabled_cpus] = cpu_get_ops("psci");
+       /* CPU 0 was already initialized */
+       if (enabled_cpus) {
+               if (!cpu_ops[enabled_cpus])
+                       return;
+
+               if (cpu_ops[enabled_cpus]->cpu_init(NULL, enabled_cpus))
+                       return;
+
+               /* map the logical cpu id to cpu MPIDR */
+               cpu_logical_map(enabled_cpus) = mpidr;
+       }
+
+       enabled_cpus++;
+}
+
+static int __init
+acpi_parse_gic_cpu_interface(struct acpi_subtable_header *header,
+                               const unsigned long end)
+{
+       struct acpi_madt_generic_interrupt *processor;
+
+       processor = (struct acpi_madt_generic_interrupt *)header;
+
+       if (BAD_MADT_ENTRY(processor, end))
+               return -EINVAL;
+
+       acpi_table_print_madt_entry(header);
+       acpi_map_gic_cpu_interface(processor);
+       return 0;
+}
+
+/* Parse GIC cpu interface entries in MADT for SMP init */
+void __init acpi_init_cpus(void)
+{
+       int count, i;
+
+       /*
+        * do a partial walk of MADT to determine how many CPUs
+        * we have including disabled CPUs, and get information
+        * we need for SMP init
+        */
+       count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT,
+                       acpi_parse_gic_cpu_interface, 0);
+
+       if (!count) {
+               pr_err("No GIC CPU interface entries present\n");
+               return;
+       } else if (count < 0) {
+               pr_err("Error parsing GIC CPU interface entry\n");
+               return;
+       }
+
+       if (!bootcpu_valid) {
+               pr_err("MADT missing boot CPU MPIDR, not enabling secondaries\n");
+               return;
+       }
+
+       for (i = 0; i < enabled_cpus; i++)
+               set_cpu_possible(i, true);
+
+       /* Make boot-up look pretty */
+       pr_info("%d CPUs enabled, %d CPUs total\n", enabled_cpus, total_cpus);
+}
+
+/*
+ * acpi_fadt_sanity_check() - Check FADT presence and carry out sanity
+ *                           checks on it
+ *
+ * Return 0 on success,  <0 on failure
+ */
+static int __init acpi_fadt_sanity_check(void)
+{
+       struct acpi_table_header *table;
+       struct acpi_table_fadt *fadt;
+       acpi_status status;
+       acpi_size tbl_size;
+       int ret = 0;
+
+       /*
+        * FADT is required on arm64; retrieve it to check its presence
+        * and carry out revision and ACPI HW reduced compliancy tests
+        */
+       status = acpi_get_table_with_size(ACPI_SIG_FADT, 0, &table, &tbl_size);
+       if (ACPI_FAILURE(status)) {
+               const char *msg = acpi_format_exception(status);
+
+               pr_err("Failed to get FADT table, %s\n", msg);
+               return -ENODEV;
+       }
+
+       fadt = (struct acpi_table_fadt *)table;
+
+       /*
+        * Revision in table header is the FADT Major revision, and there
+        * is a minor revision of FADT which was introduced by ACPI 5.1,
+        * we only deal with ACPI 5.1 or newer revision to get GIC and SMP
+        * boot protocol configuration data.
+        */
+       if (table->revision < 5 ||
+          (table->revision == 5 && fadt->minor_revision < 1)) {
+               pr_err("Unsupported FADT revision %d.%d, should be 5.1+\n",
+                      table->revision, fadt->minor_revision);
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (!(fadt->flags & ACPI_FADT_HW_REDUCED)) {
+               pr_err("FADT not ACPI hardware reduced compliant\n");
+               ret = -EINVAL;
+       }
+
+out:
+       /*
+        * acpi_get_table_with_size() creates FADT table mapping that
+        * should be released after parsing and before resuming boot
+        */
+       early_acpi_os_unmap_memory(table, tbl_size);
+       return ret;
+}
+
+/*
+ * acpi_boot_table_init() called from setup_arch(), always.
+ *     1. find RSDP and get its address, and then find XSDT
+ *     2. extract all tables and checksums them all
+ *     3. check ACPI FADT revision
+ *     4. check ACPI FADT HW reduced flag
+ *
+ * We can parse ACPI boot-time tables such as MADT after
+ * this function is called.
+ *
+ * On return ACPI is enabled if either:
+ *
+ * - ACPI tables are initialized and sanity checks passed
+ * - acpi=force was passed in the command line and ACPI was not disabled
+ *   explicitly through acpi=off command line parameter
+ *
+ * ACPI is disabled on function return otherwise
+ */
+void __init acpi_boot_table_init(void)
+{
+       /*
+        * Enable ACPI instead of device tree unless
+        * - ACPI has been disabled explicitly (acpi=off), or
+        * - the device tree is not empty (it has more than just a /chosen node)
+        *   and ACPI has not been force enabled (acpi=force)
+        */
+       if (param_acpi_off ||
+           (!param_acpi_force && of_scan_flat_dt(dt_scan_depth1_nodes, NULL)))
+               return;
+
+       /*
+        * ACPI is disabled at this point. Enable it in order to parse
+        * the ACPI tables and carry out sanity checks
+        */
+       enable_acpi();
+
+       /*
+        * If ACPI tables are initialized and FADT sanity checks passed,
+        * leave ACPI enabled and carry on booting; otherwise disable ACPI
+        * on initialization error.
+        * If acpi=force was passed on the command line it forces ACPI
+        * to be enabled even if its initialization failed.
+        */
+       if (acpi_table_init() || acpi_fadt_sanity_check()) {
+               pr_err("Failed to init ACPI tables\n");
+               if (!param_acpi_force)
+                       disable_acpi();
+       }
+}
+
+void __init acpi_gic_init(void)
+{
+       struct acpi_table_header *table;
+       acpi_status status;
+       acpi_size tbl_size;
+       int err;
+
+       if (acpi_disabled)
+               return;
+
+       status = acpi_get_table_with_size(ACPI_SIG_MADT, 0, &table, &tbl_size);
+       if (ACPI_FAILURE(status)) {
+               const char *msg = acpi_format_exception(status);
+
+               pr_err("Failed to get MADT table, %s\n", msg);
+               return;
+       }
+
+       err = gic_v2_acpi_init(table);
+       if (err)
+               pr_err("Failed to initialize GIC IRQ controller");
+
+       early_acpi_os_unmap_memory((char *)table, tbl_size);
+}
index cce952440c64a757ed62b2ada5cfecfe58086d88..fb8ff9ba467a9701cc870a451c7172f534c37f58 100644 (file)
@@ -35,7 +35,7 @@ static const struct cpu_operations *supported_cpu_ops[] __initconst = {
        NULL,
 };
 
-static const struct cpu_operations * __init cpu_get_ops(const char *name)
+const struct cpu_operations * __init cpu_get_ops(const char *name)
 {
        const struct cpu_operations **ops = supported_cpu_ops;
 
index 6f93c24ca80122f4844801d42b1bde561bc01909..4095379dc069838d99651e91e9a33abd1466619c 100644 (file)
@@ -10,6 +10,7 @@
  *
  */
 
+#include <linux/acpi.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
@@ -46,3 +47,27 @@ int pcibios_add_device(struct pci_dev *dev)
 
        return 0;
 }
+
+/*
+ * raw_pci_read/write - Platform-specific PCI config space access.
+ */
+int raw_pci_read(unsigned int domain, unsigned int bus,
+                 unsigned int devfn, int reg, int len, u32 *val)
+{
+       return -ENXIO;
+}
+
+int raw_pci_write(unsigned int domain, unsigned int bus,
+               unsigned int devfn, int reg, int len, u32 val)
+{
+       return -ENXIO;
+}
+
+#ifdef CONFIG_ACPI
+/* Root bridge scanning */
+struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
+{
+       /* TODO: Should be revisited when implementing PCI on ACPI */
+       return NULL;
+}
+#endif
index 195991dadc3772c67a084396d28aa2a7c8b2019e..23f25acf43a9021ee9b4ad0f79e3b3e5d6ef49c4 100644 (file)
@@ -1310,7 +1310,7 @@ static const struct of_device_id armpmu_of_device_ids[] = {
 
 static int armpmu_device_probe(struct platform_device *pdev)
 {
-       int i, *irqs;
+       int i, irq, *irqs;
 
        if (!cpu_pmu)
                return -ENODEV;
@@ -1319,6 +1319,11 @@ static int armpmu_device_probe(struct platform_device *pdev)
        if (!irqs)
                return -ENOMEM;
 
+       /* Don't bother with PPIs; they're already affine */
+       irq = platform_get_irq(pdev, 0);
+       if (irq >= 0 && irq_is_percpu(irq))
+               return 0;
+
        for (i = 0; i < pdev->num_resources; ++i) {
                struct device_node *dn;
                int cpu;
@@ -1327,7 +1332,7 @@ static int armpmu_device_probe(struct platform_device *pdev)
                                      i);
                if (!dn) {
                        pr_warn("Failed to parse %s/interrupt-affinity[%d]\n",
-                               of_node_full_name(dn), i);
+                               of_node_full_name(pdev->dev.of_node), i);
                        break;
                }
 
index 9b8a70ae64a187d2647a10576a789ebba213788c..ea18cb53921e8f8ed8197c6cc7090473a5ba56af 100644 (file)
@@ -15,6 +15,7 @@
 
 #define pr_fmt(fmt) "psci: " fmt
 
+#include <linux/acpi.h>
 #include <linux/init.h>
 #include <linux/of.h>
 #include <linux/smp.h>
@@ -24,6 +25,7 @@
 #include <linux/slab.h>
 #include <uapi/linux/psci.h>
 
+#include <asm/acpi.h>
 #include <asm/compiler.h>
 #include <asm/cpu_ops.h>
 #include <asm/errno.h>
@@ -273,39 +275,8 @@ static void psci_sys_poweroff(void)
        invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);
 }
 
-/*
- * PSCI Function IDs for v0.2+ are well defined so use
- * standard values.
- */
-static int __init psci_0_2_init(struct device_node *np)
+static void __init psci_0_2_set_functions(void)
 {
-       int err, ver;
-
-       err = get_set_conduit_method(np);
-
-       if (err)
-               goto out_put_node;
-
-       ver = psci_get_version();
-
-       if (ver == PSCI_RET_NOT_SUPPORTED) {
-               /* PSCI v0.2 mandates implementation of PSCI_ID_VERSION. */
-               pr_err("PSCI firmware does not comply with the v0.2 spec.\n");
-               err = -EOPNOTSUPP;
-               goto out_put_node;
-       } else {
-               pr_info("PSCIv%d.%d detected in firmware.\n",
-                               PSCI_VERSION_MAJOR(ver),
-                               PSCI_VERSION_MINOR(ver));
-
-               if (PSCI_VERSION_MAJOR(ver) == 0 &&
-                               PSCI_VERSION_MINOR(ver) < 2) {
-                       err = -EINVAL;
-                       pr_err("Conflicting PSCI version detected.\n");
-                       goto out_put_node;
-               }
-       }
-
        pr_info("Using standard PSCI v0.2 function IDs\n");
        psci_function_id[PSCI_FN_CPU_SUSPEND] = PSCI_0_2_FN64_CPU_SUSPEND;
        psci_ops.cpu_suspend = psci_cpu_suspend;
@@ -329,6 +300,60 @@ static int __init psci_0_2_init(struct device_node *np)
        arm_pm_restart = psci_sys_reset;
 
        pm_power_off = psci_sys_poweroff;
+}
+
+/*
+ * Probe function for PSCI firmware versions >= 0.2
+ */
+static int __init psci_probe(void)
+{
+       int ver = psci_get_version();
+
+       if (ver == PSCI_RET_NOT_SUPPORTED) {
+               /*
+                * PSCI versions >=0.2 mandates implementation of
+                * PSCI_VERSION.
+                */
+               pr_err("PSCI firmware does not comply with the v0.2 spec.\n");
+               return -EOPNOTSUPP;
+       } else {
+               pr_info("PSCIv%d.%d detected in firmware.\n",
+                               PSCI_VERSION_MAJOR(ver),
+                               PSCI_VERSION_MINOR(ver));
+
+               if (PSCI_VERSION_MAJOR(ver) == 0 &&
+                               PSCI_VERSION_MINOR(ver) < 2) {
+                       pr_err("Conflicting PSCI version detected.\n");
+                       return -EINVAL;
+               }
+       }
+
+       psci_0_2_set_functions();
+
+       return 0;
+}
+
+/*
+ * PSCI init function for PSCI versions >=0.2
+ *
+ * Probe based on PSCI PSCI_VERSION function
+ */
+static int __init psci_0_2_init(struct device_node *np)
+{
+       int err;
+
+       err = get_set_conduit_method(np);
+
+       if (err)
+               goto out_put_node;
+       /*
+        * Starting with v0.2, the PSCI specification introduced a call
+        * (PSCI_VERSION) that allows probing the firmware version, so
+        * that PSCI function IDs and version specific initialization
+        * can be carried out according to the specific version reported
+        * by firmware
+        */
+       err = psci_probe();
 
 out_put_node:
        of_node_put(np);
@@ -381,7 +406,7 @@ static const struct of_device_id psci_of_match[] __initconst = {
        {},
 };
 
-int __init psci_init(void)
+int __init psci_dt_init(void)
 {
        struct device_node *np;
        const struct of_device_id *matched_np;
@@ -396,6 +421,27 @@ int __init psci_init(void)
        return init_fn(np);
 }
 
+/*
+ * We use PSCI 0.2+ when ACPI is deployed on ARM64 and it's
+ * explicitly clarified in SBBR
+ */
+int __init psci_acpi_init(void)
+{
+       if (!acpi_psci_present()) {
+               pr_info("is not implemented in ACPI.\n");
+               return -EOPNOTSUPP;
+       }
+
+       pr_info("probing for conduit method from ACPI.\n");
+
+       if (acpi_psci_use_hvc())
+               invoke_psci_fn = __invoke_psci_fn_hvc;
+       else
+               invoke_psci_fn = __invoke_psci_fn_smc;
+
+       return psci_probe();
+}
+
 #ifdef CONFIG_SMP
 
 static int __init cpu_psci_cpu_init(struct device_node *dn, unsigned int cpu)
index 51ef97274b52ac342a6c760aa60cd90665a7e705..74753132c3ac8fc9bb58d6585d3d08960faed69a 100644 (file)
@@ -17,6 +17,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/acpi.h>
 #include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/stddef.h>
@@ -46,6 +47,7 @@
 #include <linux/efi.h>
 #include <linux/personality.h>
 
+#include <asm/acpi.h>
 #include <asm/fixmap.h>
 #include <asm/cpu.h>
 #include <asm/cputype.h>
@@ -395,18 +397,27 @@ void __init setup_arch(char **cmdline_p)
        efi_init();
        arm64_memblock_init();
 
+       /* Parse the ACPI tables for possible boot-time configuration */
+       acpi_boot_table_init();
+
        paging_init();
        request_standard_resources();
 
        early_ioremap_reset();
 
-       unflatten_device_tree();
-
-       psci_init();
+       if (acpi_disabled) {
+               unflatten_device_tree();
+               psci_dt_init();
+               cpu_read_bootcpu_ops();
+#ifdef CONFIG_SMP
+               of_smp_init_cpus();
+#endif
+       } else {
+               psci_acpi_init();
+               acpi_init_cpus();
+       }
 
-       cpu_read_bootcpu_ops();
 #ifdef CONFIG_SMP
-       smp_init_cpus();
        smp_build_mpidr_hash();
 #endif
 
index 714411f623919250d7ae5da48b504151ccea447f..2cb008177252f08d876875e08e4448b5b3260dde 100644 (file)
@@ -323,7 +323,7 @@ void __init smp_prepare_boot_cpu(void)
  * cpu logical map array containing MPIDR values related to logical
  * cpus. Assumes that cpu_logical_map(0) has already been initialized.
  */
-void __init smp_init_cpus(void)
+void __init of_smp_init_cpus(void)
 {
        struct device_node *dn = NULL;
        unsigned int i, cpu = 1;
index 1a7125c3099b65cd4be91503cebaca48ad5da563..42f9195cf2f8ab5747a5f666e6cb4c66f0c5b247 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/delay.h>
 #include <linux/clocksource.h>
 #include <linux/clk-provider.h>
+#include <linux/acpi.h>
 
 #include <clocksource/arm_arch_timer.h>
 
@@ -72,6 +73,12 @@ void __init time_init(void)
 
        tick_setup_hrtimer_broadcast();
 
+       /*
+        * Since ACPI or FDT will only one be available in the system,
+        * we can use acpi_generic_timer_init() here safely
+        */
+       acpi_generic_timer_init();
+
        arch_timer_rate = arch_timer_get_rate();
        if (!arch_timer_rate)
                panic("Unable to initialise architected timer.\n");
index ef7d112f5ce0df9ca1c1a793301c2c1b3874e23f..b0bd4e5fd5cf9c2599ddbc509bccb233838638a4 100644 (file)
@@ -67,8 +67,7 @@ static void *__alloc_from_pool(size_t size, struct page **ret_page, gfp_t flags)
 
                *ret_page = phys_to_page(phys);
                ptr = (void *)val;
-               if (flags & __GFP_ZERO)
-                       memset(ptr, 0, size);
+               memset(ptr, 0, size);
        }
 
        return ptr;
@@ -105,7 +104,6 @@ static void *__dma_alloc_coherent(struct device *dev, size_t size,
                struct page *page;
                void *addr;
 
-               size = PAGE_ALIGN(size);
                page = dma_alloc_from_contiguous(dev, size >> PAGE_SHIFT,
                                                        get_order(size));
                if (!page)
@@ -113,8 +111,7 @@ static void *__dma_alloc_coherent(struct device *dev, size_t size,
 
                *dma_handle = phys_to_dma(dev, page_to_phys(page));
                addr = page_address(page);
-               if (flags & __GFP_ZERO)
-                       memset(addr, 0, size);
+               memset(addr, 0, size);
                return addr;
        } else {
                return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
@@ -195,6 +192,8 @@ static void __dma_free(struct device *dev, size_t size,
 {
        void *swiotlb_addr = phys_to_virt(dma_to_phys(dev, dma_handle));
 
+       size = PAGE_ALIGN(size);
+
        if (!is_device_dma_coherent(dev)) {
                if (__free_from_pool(vaddr, size))
                        return;
index 383007877b2b2f2e5dc8b94e53da22bc4990a00f..99c00d835f4795d2d48d5f2a327e55c264aa71e8 100644 (file)
@@ -48,7 +48,6 @@ CONFIG_IP_PNP=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_JEDECPROBE=m
 CONFIG_MTD_RAM=y
index cd0636bb24a0904d0d0ddcc3da12752f3830f8e9..cdeb51856f267a5d12577c0a9ede0e9836848e33 100644 (file)
@@ -67,7 +67,6 @@ CONFIG_BFIN_SIR0=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_INTELEXT=y
index 16273a92205626cb8c86cefd95274555739a932a..ed7d2c096739436db89c866917a43e54b6723d71 100644 (file)
@@ -50,7 +50,6 @@ CONFIG_IRTTY_SIR=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_CHAR=m
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_JEDECPROBE=y
 CONFIG_MTD_CFI_AMDSTD=y
index 0df2f921f7e5aa7caa50eb1c63d43ac6db3e143d..0c241f4d28d73508e53179b654c51328dc255b2c 100644 (file)
@@ -50,7 +50,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=m
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=m
 CONFIG_MTD_CFI_AMDSTD=m
index 91d3eda42742697665d2fadee71d2f96f4d95ff6..e5360b30e39aed23f17a294ecb536a1da94c31e7 100644 (file)
@@ -55,13 +55,14 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=m
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=m
 CONFIG_MTD_CFI_AMDSTD=m
 CONFIG_MTD_RAM=y
 CONFIG_MTD_ROM=m
 CONFIG_MTD_PHYSMAP=m
+CONFIG_MTD_M25P80=y
+CONFIG_MTD_SPI_NOR=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_NETDEVICES=y
 CONFIG_NET_BFIN=y
index be03be6ba5436eef23950abef36f4dbf294ce7cc..60f6fb86125c16ac1c473bdffd9f12b794c4220f 100644 (file)
@@ -60,7 +60,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=m
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=m
 CONFIG_MTD_CFI_AMDSTD=m
index 802f9c421621764869672bd8002b8bb893d950eb..78f6bc79f91005b5d576016a5ec39b85414339fe 100644 (file)
@@ -50,7 +50,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_PLATRAM=y
 CONFIG_MTD_PHRAM=y
index e2a2fa5935ce52ae260bc2696ab2f90ff4b81899..fac8bb5782491bb183b68e9735a7c93caa0f40a3 100644 (file)
@@ -52,7 +52,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_AMDSTD=y
index 680730eeaf236d8954fe6a08fca1f6ebb1844175..2a2e4d0cebc1c8095d374cff57cf4ee33b6a987f 100644 (file)
@@ -54,7 +54,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_AMDSTD=y
index fcec5ce71392d20712b15516c3786e43513b0d10..ba4267f658af4dd86abbd09232aa584442837a90 100644 (file)
@@ -105,6 +105,7 @@ CONFIG_SPI=y
 CONFIG_SPI_ADI_V3=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_MCP23S08=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_BFIN_WDT=y
index 05108b85ab12bf38e291e58ba2c9095a953b9198..1902bb05d0863f9952fbf3e91450fe83f3784dd8 100644 (file)
@@ -55,7 +55,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_INTELEXT=y
index 5e0db82b679ea669e72d28f1bdffb10fb5bfec19..9a5716d57ebc37c93ff0f7e39bddc612a8b8f669 100644 (file)
@@ -37,7 +37,6 @@ CONFIG_UNIX=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_INTELEXT=y
index 2e47df77490f29c3f42add408b847ada13da4370..6845928843494b4fe100ff0f531755bd3a12e62a 100644 (file)
@@ -52,7 +52,6 @@ CONFIG_IP_PNP=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_INTELEXT=y
index 6da629ffc2f10954ffdca933bacd690a08819fef..d9915e9847872edcdafada414577098ff5889fc4 100644 (file)
@@ -48,7 +48,6 @@ CONFIG_INET=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_INTELEXT=y
index 9ff79df6825c6b3fe67f108a156cbc56ed1cfee8..92d8130cdb513c2ff9ffba4b866de3965d6ed9be 100644 (file)
@@ -54,7 +54,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_INTELEXT=y
index d6dd98e671463b4d86e83e3febcc376e46581faa..fa8d91132a57ea69cf839a287e6b7b23066f7341 100644 (file)
@@ -52,7 +52,6 @@ CONFIG_INET=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_INTELEXT=y
index 2b58cb2212837f2dcafd49eda71efaef9fa8e2aa..88600593c731a30355b016c5bc55ca420a1152fc 100644 (file)
@@ -36,7 +36,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
 CONFIG_MTD_DEBUG=y
 CONFIG_MTD_DEBUG_VERBOSE=1
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_NFTL=y
 CONFIG_NFTL_RW=y
index 5adf0da58499cb3e002033bb8d39685213a44f41..9e3ae4b36d202bf7bb30d3f09e312581d088e967 100644 (file)
@@ -43,7 +43,6 @@ CONFIG_IP_NF_TARGET_REJECT=y
 CONFIG_IP_NF_MANGLE=y
 # CONFIG_WIRELESS is not set
 CONFIG_MTD=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_AMDSTD=y
index a6a7298962edcda479759327b2b2c1e8ac25656a..c7926812971c079effc55eef31fd94c627d66463 100644 (file)
@@ -46,7 +46,6 @@ CONFIG_IP_PNP=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_CHAR=m
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_RAM=y
 CONFIG_MTD_COMPLEX_MAPPINGS=y
index bc216646fe1864579ce444d6da28170147ea6523..23fdc57d657ae3aca63bedd57783e7b6bf717122 100644 (file)
@@ -38,7 +38,6 @@ CONFIG_IRTTY_SIR=m
 # CONFIG_WIRELESS is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_CHAR=m
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_JEDECPROBE=m
 CONFIG_MTD_RAM=y
index ea88158ab432c7a7f2897c8d061e41cf2c40df84..e28959479fe07357dcd06bb225f6406961f51bb4 100644 (file)
@@ -55,7 +55,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_ADV_OPTIONS=y
index c1f45f15295cdf5c9fbf47c1f945d10cfe29f15c..39e85cce95d7a190c7f8711197b430647a2531a0 100644 (file)
@@ -44,7 +44,6 @@ CONFIG_INET=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_INTELEXT=y
index dccae26805b0a38c4b09ecd836a12de422bb1a52..4e8ad0523118d631ea24f6b9f8fd1c3ffb123194 100644 (file)
 #include <linux/types.h>
 #include <asm/byteorder.h>
 
-#define DECLARE_BFIN_RAW_READX(size, type, asm, asm_sign) \
-static inline type __raw_read##size(const volatile void __iomem *addr) \
-{ \
-       unsigned int val; \
-       int tmp; \
-       __asm__ __volatile__ ( \
-               "cli %1;" \
-               "NOP; NOP; SSYNC;" \
-               "%0 = "#asm" [%2] "#asm_sign";" \
-               "sti %1;" \
-               : "=d"(val), "=d"(tmp) \
-               : "a"(addr) \
-       ); \
-       return (type) val; \
-}
-DECLARE_BFIN_RAW_READX(b, u8, b, (z))
-#define __raw_readb __raw_readb
-DECLARE_BFIN_RAW_READX(w, u16, w, (z))
-#define __raw_readw __raw_readw
-DECLARE_BFIN_RAW_READX(l, u32, , )
-#define __raw_readl __raw_readl
+#define __raw_readb bfin_read8
+#define __raw_readw bfin_read16
+#define __raw_readl bfin_read32
+#define __raw_writeb(val, addr) bfin_write8(addr, val)
+#define __raw_writew(val, addr) bfin_write16(addr, val)
+#define __raw_writel(val, addr) bfin_write32(addr, val)
 
 extern void outsb(unsigned long port, const void *addr, unsigned long count);
 extern void outsw(unsigned long port, const void *addr, unsigned long count);
@@ -50,14 +35,6 @@ extern void insl_16(unsigned long port, void *addr, unsigned long count);
 #define insw insw
 #define insl insl
 
-extern void dma_outsb(unsigned long port, const void *addr, unsigned short count);
-extern void dma_outsw(unsigned long port, const void *addr, unsigned short count);
-extern void dma_outsl(unsigned long port, const void *addr, unsigned short count);
-
-extern void dma_insb(unsigned long port, void *addr, unsigned short count);
-extern void dma_insw(unsigned long port, void *addr, unsigned short count);
-extern void dma_insl(unsigned long port, void *addr, unsigned short count);
-
 /**
  * I/O write barrier
  *
index a4511649a864e41b8d8774c396f3a2ac9ba7dad4..0cb9078ef48271b8a83165e613c1d13efd3f2e42 100644 (file)
 #define __NR_sendmmsg          380
 #define __NR_process_vm_readv  381
 #define __NR_process_vm_writev 382
+#define __NR_kcmp              383
+#define __NR_finit_module      384
+#define __NR_sched_setattr     385
+#define __NR_sched_getattr     386
+#define __NR_renameat2         387
+#define __NR_seccomp           388
+#define __NR_getrandom         389
+#define __NR_memfd_create      390
+#define __NR_bpf               391
+#define __NR_execveat          392
 
-#define __NR_syscall           383
+#define __NR_syscall           393  /* For internal using, not implemented */
 #define NR_syscalls            __NR_syscall
 
 /* Old optional stuff no one actually uses */
index 947ad083233879eb4c6bb69fcbb2641ba6582027..86b1cd3a030996d8f5a70ba2b864bb386cfb6020 100644 (file)
@@ -1620,7 +1620,6 @@ static int __init bfin_debug_mmrs_init(void)
        D16(USB_APHY_CNTRL);
        D16(USB_APHY_CALIB);
        D16(USB_APHY_CNTRL2);
-       D16(USB_PHY_TEST);
        D16(USB_PLLOSC_CTRL);
        D16(USB_SRP_CLKDIV);
        D16(USB_EP_NI0_TXMAXP);
index fa53faeeb0e93902aebe5ffa9b2495a258b0830d..cf773f0f1f3063f6d88994517ea5dd5c13be4567 100644 (file)
@@ -330,9 +330,6 @@ static void bfin_disable_hw_debug(struct pt_regs *regs)
 }
 
 #ifdef CONFIG_SMP
-extern void generic_exec_single(int cpu, struct call_single_data *data, int wait);
-static struct call_single_data kgdb_smp_ipi_data[NR_CPUS];
-
 void kgdb_passive_cpu_callback(void *info)
 {
        kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs());
@@ -343,15 +340,14 @@ void kgdb_roundup_cpus(unsigned long flags)
        unsigned int cpu;
 
        for (cpu = cpumask_first(cpu_online_mask); cpu < nr_cpu_ids;
-               cpu = cpumask_next(cpu, cpu_online_mask)) {
-               kgdb_smp_ipi_data[cpu].func = kgdb_passive_cpu_callback;
-               generic_exec_single(cpu, &kgdb_smp_ipi_data[cpu], 0);
-       }
+               cpu = cpumask_next(cpu, cpu_online_mask))
+               smp_call_function_single(cpu, kgdb_passive_cpu_callback,
+                                        NULL, 0);
 }
 
 void kgdb_roundup_cpu(int cpu, unsigned long flags)
 {
-       generic_exec_single(cpu, &kgdb_smp_ipi_data[cpu], 0);
+       smp_call_function_single(cpu, kgdb_passive_cpu_callback, NULL, 0);
 }
 #endif
 
@@ -359,19 +355,6 @@ void kgdb_roundup_cpu(int cpu, unsigned long flags)
 static unsigned long kgdb_arch_imask;
 #endif
 
-void kgdb_post_primary_code(struct pt_regs *regs, int e_vector, int err_code)
-{
-       if (kgdb_single_step)
-               preempt_enable();
-
-#ifdef CONFIG_IPIPE
-       if (kgdb_arch_imask) {
-               cpu_pda[raw_smp_processor_id()].ex_imask = kgdb_arch_imask;
-               kgdb_arch_imask = 0;
-       }
-#endif
-}
-
 int kgdb_arch_handle_exception(int vector, int signo,
                               int err_code, char *remcom_in_buffer,
                               char *remcom_out_buffer,
index 4f424ae3b36de8225e5bee3977bde03a82548bb4..ad82468bd94d0dea2dda6472a734ff1745dfe9df 100644 (file)
@@ -1464,5 +1464,5 @@ void __init cmdline_init(const char *r0)
 {
        early_shadow_stamp();
        if (r0)
-               strncpy(command_line, r0, COMMAND_LINE_SIZE);
+               strlcpy(command_line, r0, COMMAND_LINE_SIZE);
 }
index d90a85b6b6b941cee8e446b1bbde751adbd9d44c..bd045318a250eb4ca8429f4ae5fe643e861429e6 100644 (file)
 #define bfin_read_USB_APHY_CNTRL2()            bfin_read16(USB_APHY_CNTRL2)
 #define bfin_write_USB_APHY_CNTRL2(val)                bfin_write16(USB_APHY_CNTRL2, val)
 
-/* (PHY_TEST is for ADI usage only) */
-
-#define bfin_read_USB_PHY_TEST()               bfin_read16(USB_PHY_TEST)
-#define bfin_write_USB_PHY_TEST(val)           bfin_write16(USB_PHY_TEST, val)
-
 #define bfin_read_USB_PLLOSC_CTRL()            bfin_read16(USB_PLLOSC_CTRL)
 #define bfin_write_USB_PLLOSC_CTRL(val)                bfin_write16(USB_PLLOSC_CTRL, val)
 #define bfin_read_USB_SRP_CLKDIV()             bfin_read16(USB_SRP_CLKDIV)
index 71578d964d00bb87ce561df8c650f08841144e4c..591e00ff620a3ebd42f10f15294ea29f6094b8f5 100644 (file)
 
 #define                  USB_APHY_CNTRL2  0xffc039e8   /* Register used to prevent re-enumeration once Moab goes into hibernate mode */
 
-/* (PHY_TEST is for ADI usage only) */
-
-#define                     USB_PHY_TEST  0xffc039ec   /* Used for reducing simulation time and simplifies FIFO testability */
-
 #define                  USB_PLLOSC_CTRL  0xffc039f0   /* Used to program different parameters for USB PLL and Oscillator */
 #define                   USB_SRP_CLKDIV  0xffc039f4   /* Used to program clock divide value for the clock fed to the SRP detection logic */
 
index d09c19cd1b7b22fc575fd125bdecfa40e406d49b..916347901d5af8d917ceb876cc13cafd32a792b2 100644 (file)
 #define bfin_read_USB_APHY_CNTRL2()            bfin_read16(USB_APHY_CNTRL2)
 #define bfin_write_USB_APHY_CNTRL2(val)                bfin_write16(USB_APHY_CNTRL2, val)
 
-/* (PHY_TEST is for ADI usage only) */
-
-#define bfin_read_USB_PHY_TEST()               bfin_read16(USB_PHY_TEST)
-#define bfin_write_USB_PHY_TEST(val)           bfin_write16(USB_PHY_TEST, val)
 #define bfin_read_USB_PLLOSC_CTRL()            bfin_read16(USB_PLLOSC_CTRL)
 #define bfin_write_USB_PLLOSC_CTRL(val)                bfin_write16(USB_PLLOSC_CTRL, val)
 #define bfin_read_USB_SRP_CLKDIV()             bfin_read16(USB_SRP_CLKDIV)
index bcb9726dea542ca955691852c27f0f98b9abf1d6..be83f645bba861a8375fb7d4f331c4e19d329bc6 100644 (file)
 #define bfin_read_USB_APHY_CNTRL2()            bfin_read16(USB_APHY_CNTRL2)
 #define bfin_write_USB_APHY_CNTRL2(val)                bfin_write16(USB_APHY_CNTRL2, val)
 
-/* (PHY_TEST is for ADI usage only) */
-
-#define bfin_read_USB_PHY_TEST()               bfin_read16(USB_PHY_TEST)
-#define bfin_write_USB_PHY_TEST(val)           bfin_write16(USB_PHY_TEST, val)
 #define bfin_read_USB_PLLOSC_CTRL()            bfin_read16(USB_PLLOSC_CTRL)
 #define bfin_write_USB_PLLOSC_CTRL(val)                bfin_write16(USB_PLLOSC_CTRL, val)
 #define bfin_read_USB_SRP_CLKDIV()             bfin_read16(USB_SRP_CLKDIV)
index 51161575a16333b3710a342b8b5138422b0a0c71..ae4b889e36066c2dfeb4bdcdf05b6bb00c8b6b46 100644 (file)
 #define                   USB_APHY_CALIB  0xffc03de4   /* Register used to set some calibration values */
 #define                  USB_APHY_CNTRL2  0xffc03de8   /* Register used to prevent re-enumeration once Moab goes into hibernate mode */
 
-/* (PHY_TEST is for ADI usage only) */
-
-#define                     USB_PHY_TEST  0xffc03dec   /* Used for reducing simulation time and simplifies FIFO testability */
 #define                  USB_PLLOSC_CTRL  0xffc03df0   /* Used to program different parameters for USB PLL and Oscillator */
 #define                   USB_SRP_CLKDIV  0xffc03df4   /* Used to program clock divide value for the clock fed to the SRP detection logic */
 
index d55dcc0f53246c311d31dd7d9677f7a3205eb6a5..7cc7928a3c73bf7ba9cc7a2f943e12570437cb9d 100644 (file)
 #define                   USB_APHY_CALIB  0xffc03de4   /* Register used to set some calibration values */
 #define                  USB_APHY_CNTRL2  0xffc03de8   /* Register used to prevent re-enumeration once Moab goes into hibernate mode */
 
-/* (PHY_TEST is for ADI usage only) */
-
-#define                     USB_PHY_TEST  0xffc03dec   /* Used for reducing simulation time and simplifies FIFO testability */
 #define                  USB_PLLOSC_CTRL  0xffc03df0   /* Used to program different parameters for USB PLL and Oscillator */
 #define                   USB_SRP_CLKDIV  0xffc03df4   /* Used to program clock divide value for the clock fed to the SRP detection logic */
 
index 7f9fc272ec30576827ad62922afb0ff799ab89c3..2c61fc0c98f94eb9d1692f6d1508086f8e092318 100644 (file)
@@ -780,8 +780,8 @@ static struct adi_spi3_chip spidev_chip_info = {
 };
 #endif
 
-#if IS_ENABLED(CONFIG_SND_BF5XX_I2S)
-static struct platform_device bfin_i2s_pcm = {
+#if IS_ENABLED(CONFIG_SND_BF6XX_PCM)
+static struct platform_device bfin_pcm = {
        .name = "bfin-i2s-pcm-audio",
        .id = -1,
 };
@@ -1034,7 +1034,6 @@ static struct adv7842_platform_data adv7842_data = {
        .i2c_infoframe = 0x48,
        .i2c_cec = 0x49,
        .i2c_avlink = 0x4a,
-       .i2c_ex = 0x26,
 };
 
 static struct bfin_capture_config bfin_capture_data = {
@@ -1104,7 +1103,6 @@ static struct disp_route adv7511_routes[] = {
 
 static struct adv7511_platform_data adv7511_data = {
        .edid_addr = 0x7e,
-       .i2c_ex = 0x25,
 };
 
 static struct bfin_display_config bfin_display_data = {
@@ -1209,6 +1207,35 @@ static struct platform_device bfin_display_device = {
 };
 #endif
 
+#if defined(CONFIG_FB_BF609_NL8048) \
+       || defined(CONFIG_FB_BF609_NL8048_MODULE)
+static struct resource nl8048_resources[] = {
+       {
+               .start = EPPI2_STAT,
+               .end = EPPI2_STAT,
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .start = CH_EPPI2_CH0,
+               .end = CH_EPPI2_CH0,
+               .flags = IORESOURCE_DMA,
+       },
+       {
+               .start = IRQ_EPPI2_STAT,
+               .end = IRQ_EPPI2_STAT,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+static struct platform_device bfin_fb_device = {
+       .name = "bf609_nl8048",
+       .num_resources = ARRAY_SIZE(nl8048_resources),
+       .resource = nl8048_resources,
+       .dev = {
+               .platform_data = (void *)GPIO_PC15,
+       },
+};
+#endif
+
 #if defined(CONFIG_BFIN_CRC)
 #define BFIN_CRC_NAME "bfin-crc"
 
@@ -1862,6 +1889,29 @@ static struct platform_device i2c_bfin_twi1_device = {
 };
 #endif
 
+#if IS_ENABLED(CONFIG_GPIO_MCP23S08)
+#include <linux/spi/mcp23s08.h>
+static const struct mcp23s08_platform_data bfin_mcp23s08_soft_switch0 = {
+       .base = 120,
+};
+static const struct mcp23s08_platform_data bfin_mcp23s08_soft_switch1 = {
+       .base = 130,
+};
+static const struct mcp23s08_platform_data bfin_mcp23s08_soft_switch2 = {
+       .base = 140,
+};
+# if IS_ENABLED(CONFIG_VIDEO_ADV7842)
+static const struct mcp23s08_platform_data bfin_adv7842_soft_switch = {
+       .base = 150,
+};
+# endif
+# if IS_ENABLED(CONFIG_VIDEO_ADV7511) || IS_ENABLED(CONFIG_VIDEO_ADV7343)
+static const struct mcp23s08_platform_data bfin_adv7511_soft_switch = {
+       .base = 160,
+};
+# endif
+#endif
+
 static struct i2c_board_info __initdata bfin_i2c_board_info0[] = {
 #if IS_ENABLED(CONFIG_INPUT_ADXL34X_I2C)
        {
@@ -1881,6 +1931,32 @@ static struct i2c_board_info __initdata bfin_i2c_board_info0[] = {
                I2C_BOARD_INFO("ssm2602", 0x1b),
        },
 #endif
+#if IS_ENABLED(CONFIG_GPIO_MCP23S08)
+       {
+               I2C_BOARD_INFO("mcp23017", 0x21),
+               .platform_data = (void *)&bfin_mcp23s08_soft_switch0
+       },
+       {
+               I2C_BOARD_INFO("mcp23017", 0x22),
+               .platform_data = (void *)&bfin_mcp23s08_soft_switch1
+       },
+       {
+               I2C_BOARD_INFO("mcp23017", 0x23),
+               .platform_data = (void *)&bfin_mcp23s08_soft_switch2
+       },
+# if IS_ENABLED(CONFIG_VIDEO_ADV7842)
+       {
+               I2C_BOARD_INFO("mcp23017", 0x26),
+               .platform_data = (void *)&bfin_adv7842_soft_switch
+       },
+# endif
+# if IS_ENABLED(CONFIG_VIDEO_ADV7511) || IS_ENABLED(CONFIG_VIDEO_ADV7343)
+       {
+               I2C_BOARD_INFO("mcp23017", 0x25),
+               .platform_data = (void *)&bfin_adv7511_soft_switch
+       },
+# endif
+#endif
 };
 
 static struct i2c_board_info __initdata bfin_i2c_board_info1[] = {
@@ -2023,8 +2099,8 @@ static struct platform_device *ezkit_devices[] __initdata = {
 #if IS_ENABLED(CONFIG_MTD_PHYSMAP)
        &ezkit_flash_device,
 #endif
-#if IS_ENABLED(CONFIG_SND_BF5XX_I2S)
-       &bfin_i2s_pcm,
+#if IS_ENABLED(CONFIG_SND_BF6XX_PCM)
+       &bfin_pcm,
 #endif
 #if IS_ENABLED(CONFIG_SND_BF6XX_SOC_I2S)
        &bfin_i2s,
@@ -2060,7 +2136,7 @@ static struct pinctrl_map __initdata bfin_pinmux_map[] = {
        PIN_MAP_MUX_GROUP_DEFAULT("bfin-rotary",  "pinctrl-adi2.0", NULL, "rotary"),
        PIN_MAP_MUX_GROUP_DEFAULT("bfin_can.0",  "pinctrl-adi2.0", NULL, "can0"),
        PIN_MAP_MUX_GROUP_DEFAULT("physmap-flash.0",  "pinctrl-adi2.0", NULL, "smc0"),
-       PIN_MAP_MUX_GROUP_DEFAULT("bf609_nl8048.2",  "pinctrl-adi2.0", "ppi2_16bgrp", "ppi2"),
+       PIN_MAP_MUX_GROUP_DEFAULT("bf609_nl8048.0",  "pinctrl-adi2.0", "ppi2_16bgrp", "ppi2"),
        PIN_MAP_MUX_GROUP("bfin_display.0", "8bit",  "pinctrl-adi2.0", "ppi2_8bgrp", "ppi2"),
        PIN_MAP_MUX_GROUP_DEFAULT("bfin_display.0",  "pinctrl-adi2.0", "ppi2_16bgrp", "ppi2"),
        PIN_MAP_MUX_GROUP("bfin_display.0", "16bit",  "pinctrl-adi2.0", "ppi2_16bgrp", "ppi2"),
index 244fa4ab4c56b854cff2c068dc9b4860a2238596..378305844b2c9ec14d2f20197216519eb8249010 100644 (file)
@@ -363,6 +363,12 @@ static struct clk ethclk = {
        .ops        = &dummy_clk_ops,
 };
 
+static struct clk ethpclk = {
+       .name       = "pclk",
+       .parent     = &sclk0,
+       .ops        = &dummy_clk_ops,
+};
+
 static struct clk spiclk = {
        .name       = "spi",
        .parent     = &sclk1,
@@ -381,6 +387,7 @@ static struct clk_lookup bf609_clks[] = {
        CLK(dclk, NULL, "DCLK"),
        CLK(oclk, NULL, "OCLK"),
        CLK(ethclk, NULL, "stmmaceth"),
+       CLK(ethpclk, NULL, "pclk"),
        CLK(spiclk, NULL, "spi"),
 };
 
index 86b5a095c5a1c93c2ffc820993a4c6ca576728b4..8d9431e22e8c5f04b48b65f4d83802d345945b69 100644 (file)
@@ -1694,6 +1694,16 @@ ENTRY(_sys_call_table)
        .long _sys_sendmmsg             /* 380 */
        .long _sys_process_vm_readv
        .long _sys_process_vm_writev
+       .long _sys_kcmp
+       .long _sys_finit_module
+       .long _sys_sched_setattr        /* 385 */
+       .long _sys_sched_getattr
+       .long _sys_renameat2
+       .long _sys_seccomp
+       .long _sys_getrandom
+       .long _sys_memfd_create         /* 390 */
+       .long _sys_bpf
+       .long _sys_execveat
 
        .rept NR_syscalls-(.-_sys_call_table)/4
        .long _sys_ni_syscall
index 1387a94bcfd5a30e68fb00d9e293eea7db710d98..a66d979ec6512b24857f98227e01412a3ea83a75 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/slab.h>
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/delay.h>
 
 #include <asm/cplb.h>
 #include <asm/gpio.h>
@@ -180,6 +181,7 @@ int bfin_pm_suspend_mem_enter(void)
 
 #if defined(CONFIG_BFIN_EXTMEM_WRITEBACK) || defined(CONFIG_BFIN_L2_WRITEBACK)
        flushinv_all_dcache();
+       udelay(1);
 #endif
        _disable_dcplb();
        _disable_icplb();
index 4a03911053ab8df634cfa200158fb54aa4ac3aca..0314e325a669345eb8f9aea8d006a0bc66a13e1d 100644 (file)
@@ -46,12 +46,18 @@ config CRIS
        select ARCH_WANT_IPC_PARSE_VERSION
        select GENERIC_IRQ_SHOW
        select GENERIC_IOMAP
-       select GENERIC_SMP_IDLE_THREAD if ETRAX_ARCH_V32
        select GENERIC_CMOS_UPDATE
        select MODULES_USE_ELF_RELA
        select CLONE_BACKWARDS2
        select OLD_SIGSUSPEND
        select OLD_SIGACTION
+       select ARCH_REQUIRE_GPIOLIB
+       select IRQ_DOMAIN if ETRAX_ARCH_V32
+       select OF if ETRAX_ARCH_V32
+       select OF_EARLY_FLATTREE if ETRAX_ARCH_V32
+       select CLKSRC_MMIO if ETRAX_ARCH_V32
+       select GENERIC_CLOCKEVENTS if ETRAX_ARCH_V32
+       select GENERIC_SCHED_CLOCK if ETRAX_ARCH_V32
 
 config HZ
        int
@@ -61,6 +67,10 @@ config NR_CPUS
        int
        default "1"
 
+config BUILTIN_DTB
+       string "DTB to build into the kernel image"
+       depends on OF
+
 source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
index 39dc7d00083e10d393337a66bb0225052accf0cb..4a5404b3d0e45712c246b93c05ce21da5e732489 100644 (file)
@@ -40,6 +40,10 @@ else
 MACH :=
 endif
 
+ifneq ($(CONFIG_BUILTIN_DTB),"")
+core-$(CONFIG_OF) += arch/cris/boot/dts/
+endif
+
 LD = $(CROSS_COMPILE)ld -mcrislinux
 
 OBJCOPYFLAGS := -O binary -R .note -R .comment -S
index 40358355d0cbb96e8c61339605845f2ba06c4f6c..d9fc617ea25346c739cea8894f282405a933efc1 100644 (file)
@@ -9,7 +9,6 @@ obj-y   := entry.o traps.o irq.o debugport.o \
           process.o ptrace.o setup.o signal.o traps.o time.o \
           cache.o cacheflush.o
 
-obj-$(CONFIG_SMP) += smp.o
 obj-$(CONFIG_ETRAX_KGDB) += kgdb.o kgdb_asm.o
 obj-$(CONFIG_ETRAX_FAST_TIMER) += fasttimer.o
 obj-$(CONFIG_MODULES)    += crisksyms.o
index 2f19ac6217aafd2754d7f423b5441d988aacbae7..026a0b21b8f0f4018a6922386e2913c368b37b83 100644 (file)
@@ -99,6 +99,8 @@ ret_from_kernel_thread:
 
        .type   ret_from_intr,@function
 ret_from_intr:
+       moveq   0, $r9                  ; not a syscall
+
        ;; Check for resched if preemptive kernel, or if we're going back to
        ;; user-mode. This test matches the user_regs(regs) macro. Don't simply
        ;; test CCS since that doesn't necessarily reflect what mode we'll
@@ -145,7 +147,7 @@ system_call:
        ;; Stack-frame similar to the irq heads, which is reversed in
        ;; ret_from_sys_call.
 
-       sub.d   92, $sp         ; Skip EXS and EDA.
+       sub.d   92, $sp         ; Skip EDA.
        movem   $r13, [$sp]
        move.d  $sp, $r8
        addq    14*4, $r8
@@ -156,8 +158,9 @@ system_call:
        move    $ccs, $r4
        move    $srp, $r5
        move    $erp, $r6
+       move.d  $r9, $r7        ; Store syscall number in EXS
        subq    4, $sp
-       movem   $r6, [$r8]
+       movem   $r7, [$r8]
        ei                      ; Enable interrupts while processing syscalls.
        move.d  $r10, [$sp]
 
@@ -277,44 +280,15 @@ _syscall_exit_work:
 
        .type   _work_pending,@function
 _work_pending:
-       addoq   +TI_flags, $r0, $acr
-       move.d  [$acr], $r10
-       btstq   TIF_NEED_RESCHED, $r10  ; Need resched?
-       bpl     _work_notifysig         ; No, must be signal/notify.
-       nop
-       .size   _work_pending, . - _work_pending
-
-       .type   _work_resched,@function
-_work_resched:
-       move.d  $r9, $r1                ; Preserve R9.
-       jsr     schedule
-       nop
-       move.d  $r1, $r9
-       di
-
-       addoq   +TI_flags, $r0, $acr
-       move.d  [$acr], $r1
-       and.d   _TIF_WORK_MASK, $r1     ; Ignore sycall trace counter.
-       beq     _Rexit
-       nop
-       btstq   TIF_NEED_RESCHED, $r1
-       bmi     _work_resched           ; current->work.need_resched.
-       nop
-       .size   _work_resched, . - _work_resched
-
-       .type   _work_notifysig,@function
-_work_notifysig:
-       ;; Deal with pending signals and notify-resume requests.
-
        addoq   +TI_flags, $r0, $acr
        move.d  [$acr], $r12            ; The thread_info_flags parameter.
        move.d  $sp, $r11               ; The regs param.
-       jsr     do_notify_resume
-       move.d  $r9, $r10               ; do_notify_resume syscall/irq param.
+       jsr     do_work_pending
+       move.d  $r9, $r10               ; The syscall/irq param.
 
        ba _Rexit
        nop
-       .size   _work_notifysig, . - _work_notifysig
+       .size   _work_pending, . - _work_pending
 
        ;; We get here as a sidetrack when we've entered a syscall with the
        ;; trace-bit set. We need to call do_syscall_trace and then continue
index 51e34165ece7feb7d0da60d5e42af1581aa8b260..74a66e0e3777388a9a05a92ba83fbcce17a6c7f9 100644 (file)
@@ -52,11 +52,6 @@ tstart:
 
        GIO_INIT
 
-#ifdef CONFIG_SMP
-secondary_cpu_entry: /* Entry point for secondary CPUs */
-       di
-#endif
-
        ;; Setup and enable the MMU. Use same configuration for both the data
        ;; and the instruction MMU.
        ;;
@@ -164,33 +159,6 @@ secondary_cpu_entry: /* Entry point for secondary CPUs */
        nop
        nop
 
-#ifdef CONFIG_SMP
-       ;; Read CPU ID
-       move    0, $srs
-       nop
-       nop
-       nop
-       move    $s12, $r0
-       cmpq    0, $r0
-       beq     master_cpu
-       nop
-slave_cpu:
-       ; Time to boot-up. Get stack location provided by master CPU.
-       move.d  smp_init_current_idle_thread, $r1
-       move.d  [$r1], $sp
-       add.d   8192, $sp
-       move.d  ebp_start, $r0  ; Defined in linker-script.
-       move    $r0, $ebp
-       jsr     smp_callin
-       nop
-master_cpu:
-       /* Set up entry point for secondary CPUs. The boot ROM has set up
-        * EBP at start of internal memory. The CPU will get there
-        * later when we issue an IPI to them... */
-       move.d MEM_INTMEM_START + IPI_INTR_VECT * 4, $r0
-       move.d secondary_cpu_entry, $r1
-       move.d $r1, [$r0]
-#endif
        ; Check if starting from DRAM (network->RAM boot or unpacked
        ; compressed kernel), or directly from flash.
        lapcq   ., $r0
index 25437ae2812838ccf0d5e378563588e1de9096a5..6a881e0e92b43990dd14a7b7e06edeac9541dcb6 100644 (file)
@@ -10,6 +10,8 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/profile.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/threads.h>
@@ -56,9 +58,6 @@ struct cris_irq_allocation irq_allocations[NR_REAL_IRQS] =
 static unsigned long irq_regs[NR_CPUS] =
 {
   regi_irq,
-#ifdef CONFIG_SMP
-  regi_irq2,
-#endif
 };
 
 #if NR_REAL_IRQS > 32
@@ -431,6 +430,19 @@ crisv32_do_multiple(struct pt_regs* regs)
        irq_exit();
 }
 
+static int crisv32_irq_map(struct irq_domain *h, unsigned int virq,
+                          irq_hw_number_t hw_irq_num)
+{
+       irq_set_chip_and_handler(virq, &crisv32_irq_type, handle_simple_irq);
+
+       return 0;
+}
+
+static struct irq_domain_ops crisv32_irq_ops = {
+       .map    = crisv32_irq_map,
+       .xlate  = irq_domain_xlate_onecell,
+};
+
 /*
  * This is called by start_kernel. It fixes the IRQ masks and setup the
  * interrupt vector table to point to bad_interrupt pointers.
@@ -441,6 +453,8 @@ init_IRQ(void)
        int i;
        int j;
        reg_intr_vect_rw_mask vect_mask = {0};
+       struct device_node *np;
+       struct irq_domain *domain;
 
        /* Clear all interrupts masks. */
        for (i = 0; i < NBR_REGS; i++)
@@ -449,10 +463,15 @@ init_IRQ(void)
        for (i = 0; i < 256; i++)
                etrax_irv->v[i] = weird_irq;
 
-       /* Point all IRQ's to bad handlers. */
+       np = of_find_compatible_node(NULL, NULL, "axis,crisv32-intc");
+       domain = irq_domain_add_legacy(np, NR_IRQS - FIRST_IRQ,
+                                      FIRST_IRQ, FIRST_IRQ,
+                                      &crisv32_irq_ops, NULL);
+       BUG_ON(!domain);
+       irq_set_default_host(domain);
+       of_node_put(np);
+
        for (i = FIRST_IRQ, j = 0; j < NR_IRQS; i++, j++) {
-               irq_set_chip_and_handler(j, &crisv32_irq_type,
-                                        handle_simple_irq);
                set_exception_vector(i, interrupt[j]);
        }
 
index 81715c683baf08a3339c15305a457cd760d5523b..cd1865d68b2e031d55149c6e29c68bc2041de5a4 100644 (file)
@@ -63,11 +63,6 @@ int show_cpuinfo(struct seq_file *m, void *v)
 
        info = &cpinfo[ARRAY_SIZE(cpinfo) - 1];
 
-#ifdef CONFIG_SMP
-       if (!cpu_online(cpu))
-               return 0;
-#endif
-
        revision = rdvr();
 
        for (i = 0; i < ARRAY_SIZE(cpinfo); i++) {
index 0c9ce9eac6143dae6545e659b048ece37f5c8730..3a36ae6b79d5a30d2723eee234ef9e2063be0f78 100644 (file)
@@ -72,6 +72,9 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
        /* Make that the user-mode flag is set. */
        regs->ccs |= (1 << (U_CCS_BITNR + CCS_SHIFT));
 
+       /* Don't perform syscall restarting */
+       regs->exs = -1;
+
        /* Restore the old USP. */
        err |= __get_user(old_usp, &sc->usp);
        wrusp(old_usp);
@@ -425,6 +428,8 @@ do_signal(int canrestart, struct pt_regs *regs)
 {
        struct ksignal ksig;
 
+       canrestart = canrestart && ((int)regs->exs >= 0);
+
        /*
         * The common case should go fast, which is why this point is
         * reached from kernel-mode. If that's the case, just return
diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c
deleted file mode 100644 (file)
index 0698582..0000000
+++ /dev/null
@@ -1,358 +0,0 @@
-#include <linux/types.h>
-#include <asm/delay.h>
-#include <irq.h>
-#include <hwregs/intr_vect.h>
-#include <hwregs/intr_vect_defs.h>
-#include <asm/tlbflush.h>
-#include <asm/mmu_context.h>
-#include <hwregs/asm/mmu_defs_asm.h>
-#include <hwregs/supp_reg.h>
-#include <linux/atomic.h>
-
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/timex.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/cpumask.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-
-#define IPI_SCHEDULE 1
-#define IPI_CALL 2
-#define IPI_FLUSH_TLB 4
-#define IPI_BOOT 8
-
-#define FLUSH_ALL (void*)0xffffffff
-
-/* Vector of locks used for various atomic operations */
-spinlock_t cris_atomic_locks[] = {
-       [0 ... LOCK_COUNT - 1] = __SPIN_LOCK_UNLOCKED(cris_atomic_locks)
-};
-
-/* CPU masks */
-cpumask_t phys_cpu_present_map = CPU_MASK_NONE;
-EXPORT_SYMBOL(phys_cpu_present_map);
-
-/* Variables used during SMP boot */
-volatile int cpu_now_booting = 0;
-volatile struct thread_info *smp_init_current_idle_thread;
-
-/* Variables used during IPI */
-static DEFINE_SPINLOCK(call_lock);
-static DEFINE_SPINLOCK(tlbstate_lock);
-
-struct call_data_struct {
-       void (*func) (void *info);
-       void *info;
-       int wait;
-};
-
-static struct call_data_struct * call_data;
-
-static struct mm_struct* flush_mm;
-static struct vm_area_struct* flush_vma;
-static unsigned long flush_addr;
-
-/* Mode registers */
-static unsigned long irq_regs[NR_CPUS] = {
-  regi_irq,
-  regi_irq2
-};
-
-static irqreturn_t crisv32_ipi_interrupt(int irq, void *dev_id);
-static int send_ipi(int vector, int wait, cpumask_t cpu_mask);
-static struct irqaction irq_ipi  = {
-       .handler = crisv32_ipi_interrupt,
-       .flags = 0,
-       .name = "ipi",
-};
-
-extern void cris_mmu_init(void);
-extern void cris_timer_init(void);
-
-/* SMP initialization */
-void __init smp_prepare_cpus(unsigned int max_cpus)
-{
-       int i;
-
-       /* From now on we can expect IPIs so set them up */
-       setup_irq(IPI_INTR_VECT, &irq_ipi);
-
-       /* Mark all possible CPUs as present */
-       for (i = 0; i < max_cpus; i++)
-               cpumask_set_cpu(i, &phys_cpu_present_map);
-}
-
-void smp_prepare_boot_cpu(void)
-{
-       /* PGD pointer has moved after per_cpu initialization so
-        * update the MMU.
-        */
-       pgd_t **pgd;
-       pgd = (pgd_t**)&per_cpu(current_pgd, smp_processor_id());
-
-       SUPP_BANK_SEL(1);
-       SUPP_REG_WR(RW_MM_TLB_PGD, pgd);
-       SUPP_BANK_SEL(2);
-       SUPP_REG_WR(RW_MM_TLB_PGD, pgd);
-
-       set_cpu_online(0, true);
-       cpumask_set_cpu(0, &phys_cpu_present_map);
-       set_cpu_possible(0, true);
-}
-
-void __init smp_cpus_done(unsigned int max_cpus)
-{
-}
-
-/* Bring one cpu online.*/
-static int __init
-smp_boot_one_cpu(int cpuid, struct task_struct idle)
-{
-       unsigned timeout;
-       cpumask_t cpu_mask;
-
-       cpumask_clear(&cpu_mask);
-       task_thread_info(idle)->cpu = cpuid;
-
-       /* Information to the CPU that is about to boot */
-       smp_init_current_idle_thread = task_thread_info(idle);
-       cpu_now_booting = cpuid;
-
-       /* Kick it */
-       set_cpu_online(cpuid, true);
-       cpumask_set_cpu(cpuid, &cpu_mask);
-       send_ipi(IPI_BOOT, 0, cpu_mask);
-       set_cpu_online(cpuid, false);
-
-       /* Wait for CPU to come online */
-       for (timeout = 0; timeout < 10000; timeout++) {
-               if(cpu_online(cpuid)) {
-                       cpu_now_booting = 0;
-                       smp_init_current_idle_thread = NULL;
-                       return 0; /* CPU online */
-               }
-               udelay(100);
-               barrier();
-       }
-
-       printk(KERN_CRIT "SMP: CPU:%d is stuck.\n", cpuid);
-       return -1;
-}
-
-/* Secondary CPUs starts using C here. Here we need to setup CPU
- * specific stuff such as the local timer and the MMU. */
-void __init smp_callin(void)
-{
-       int cpu = cpu_now_booting;
-       reg_intr_vect_rw_mask vect_mask = {0};
-
-       /* Initialise the idle task for this CPU */
-       atomic_inc(&init_mm.mm_count);
-       current->active_mm = &init_mm;
-
-       /* Set up MMU */
-       cris_mmu_init();
-       __flush_tlb_all();
-
-       /* Setup local timer. */
-       cris_timer_init();
-
-       /* Enable IRQ and idle */
-       REG_WR(intr_vect, irq_regs[cpu], rw_mask, vect_mask);
-       crisv32_unmask_irq(IPI_INTR_VECT);
-       crisv32_unmask_irq(TIMER0_INTR_VECT);
-       preempt_disable();
-       notify_cpu_starting(cpu);
-       local_irq_enable();
-
-       set_cpu_online(cpu, true);
-       cpu_startup_entry(CPUHP_ONLINE);
-}
-
-/* Stop execution on this CPU.*/
-void stop_this_cpu(void* dummy)
-{
-       local_irq_disable();
-       asm volatile("halt");
-}
-
-/* Other calls */
-void smp_send_stop(void)
-{
-       smp_call_function(stop_this_cpu, NULL, 0);
-}
-
-int setup_profiling_timer(unsigned int multiplier)
-{
-       return -EINVAL;
-}
-
-
-/* cache_decay_ticks is used by the scheduler to decide if a process
- * is "hot" on one CPU. A higher value means a higher penalty to move
- * a process to another CPU. Our cache is rather small so we report
- * 1 tick.
- */
-unsigned long cache_decay_ticks = 1;
-
-int __cpu_up(unsigned int cpu, struct task_struct *tidle)
-{
-       smp_boot_one_cpu(cpu, tidle);
-       return cpu_online(cpu) ? 0 : -ENOSYS;
-}
-
-void smp_send_reschedule(int cpu)
-{
-       cpumask_t cpu_mask;
-       cpumask_clear(&cpu_mask);
-       cpumask_set_cpu(cpu, &cpu_mask);
-       send_ipi(IPI_SCHEDULE, 0, cpu_mask);
-}
-
-/* TLB flushing
- *
- * Flush needs to be done on the local CPU and on any other CPU that
- * may have the same mapping. The mm->cpu_vm_mask is used to keep track
- * of which CPUs that a specific process has been executed on.
- */
-void flush_tlb_common(struct mm_struct* mm, struct vm_area_struct* vma, unsigned long addr)
-{
-       unsigned long flags;
-       cpumask_t cpu_mask;
-
-       spin_lock_irqsave(&tlbstate_lock, flags);
-       cpu_mask = (mm == FLUSH_ALL ? cpu_all_mask : *mm_cpumask(mm));
-       cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
-       flush_mm = mm;
-       flush_vma = vma;
-       flush_addr = addr;
-       send_ipi(IPI_FLUSH_TLB, 1, cpu_mask);
-       spin_unlock_irqrestore(&tlbstate_lock, flags);
-}
-
-void flush_tlb_all(void)
-{
-       __flush_tlb_all();
-       flush_tlb_common(FLUSH_ALL, FLUSH_ALL, 0);
-}
-
-void flush_tlb_mm(struct mm_struct *mm)
-{
-       __flush_tlb_mm(mm);
-       flush_tlb_common(mm, FLUSH_ALL, 0);
-       /* No more mappings in other CPUs */
-       cpumask_clear(mm_cpumask(mm));
-       cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm));
-}
-
-void flush_tlb_page(struct vm_area_struct *vma,
-                          unsigned long addr)
-{
-       __flush_tlb_page(vma, addr);
-       flush_tlb_common(vma->vm_mm, vma, addr);
-}
-
-/* Inter processor interrupts
- *
- * The IPIs are used for:
- *   * Force a schedule on a CPU
- *   * FLush TLB on other CPUs
- *   * Call a function on other CPUs
- */
-
-int send_ipi(int vector, int wait, cpumask_t cpu_mask)
-{
-       int i = 0;
-       reg_intr_vect_rw_ipi ipi = REG_RD(intr_vect, irq_regs[i], rw_ipi);
-       int ret = 0;
-
-       /* Calculate CPUs to send to. */
-       cpumask_and(&cpu_mask, &cpu_mask, cpu_online_mask);
-
-       /* Send the IPI. */
-       for_each_cpu(i, &cpu_mask)
-       {
-               ipi.vector |= vector;
-               REG_WR(intr_vect, irq_regs[i], rw_ipi, ipi);
-       }
-
-       /* Wait for IPI to finish on other CPUS */
-       if (wait) {
-               for_each_cpu(i, &cpu_mask) {
-                        int j;
-                        for (j = 0 ; j < 1000; j++) {
-                               ipi = REG_RD(intr_vect, irq_regs[i], rw_ipi);
-                               if (!ipi.vector)
-                                       break;
-                               udelay(100);
-                       }
-
-                       /* Timeout? */
-                       if (ipi.vector) {
-                               printk("SMP call timeout from %d to %d\n", smp_processor_id(), i);
-                               ret = -ETIMEDOUT;
-                               dump_stack();
-                       }
-               }
-       }
-       return ret;
-}
-
-/*
- * You must not call this function with disabled interrupts or from a
- * hardware interrupt handler or from a bottom half handler.
- */
-int smp_call_function(void (*func)(void *info), void *info, int wait)
-{
-       cpumask_t cpu_mask;
-       struct call_data_struct data;
-       int ret;
-
-       cpumask_setall(&cpu_mask);
-       cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
-
-       WARN_ON(irqs_disabled());
-
-       data.func = func;
-       data.info = info;
-       data.wait = wait;
-
-       spin_lock(&call_lock);
-       call_data = &data;
-       ret = send_ipi(IPI_CALL, wait, cpu_mask);
-       spin_unlock(&call_lock);
-
-       return ret;
-}
-
-irqreturn_t crisv32_ipi_interrupt(int irq, void *dev_id)
-{
-       void (*func) (void *info) = call_data->func;
-       void *info = call_data->info;
-       reg_intr_vect_rw_ipi ipi;
-
-       ipi = REG_RD(intr_vect, irq_regs[smp_processor_id()], rw_ipi);
-
-       if (ipi.vector & IPI_SCHEDULE) {
-               scheduler_ipi();
-       }
-       if (ipi.vector & IPI_CALL) {
-               func(info);
-       }
-       if (ipi.vector & IPI_FLUSH_TLB) {
-               if (flush_mm == FLUSH_ALL)
-                       __flush_tlb_all();
-               else if (flush_vma == FLUSH_ALL)
-                       __flush_tlb_mm(flush_mm);
-               else
-                       __flush_tlb_page(flush_vma, flush_addr);
-       }
-
-       ipi.vector = 0;
-       REG_WR(intr_vect, irq_regs[smp_processor_id()], rw_ipi, ipi);
-
-       return IRQ_HANDLED;
-}
-
index c17b01abdc3b4725ddeb79f1f33a2dcbd67d5021..4fce9f1f7cc07c1e92054f64257a3f5cb2d913b4 100644 (file)
@@ -8,12 +8,14 @@
 #include <linux/timex.h>
 #include <linux/time.h>
 #include <linux/clocksource.h>
+#include <linux/clockchips.h>
 #include <linux/interrupt.h>
 #include <linux/swap.h>
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/threads.h>
 #include <linux/cpufreq.h>
+#include <linux/sched_clock.h>
 #include <linux/mm.h>
 #include <asm/types.h>
 #include <asm/signal.h>
 /* Number of 763 counts before watchdog bites */
 #define ETRAX_WD_CNT           ((2*ETRAX_WD_HZ)/HZ + 1)
 
-/* Register the continuos readonly timer available in FS and ARTPEC-3.  */
-static cycle_t read_cont_rotime(struct clocksource *cs)
-{
-       return (u32)REG_RD(timer, regi_timer0, r_time);
-}
-
-static struct clocksource cont_rotime = {
-       .name   = "crisv32_rotime",
-       .rating = 300,
-       .read   = read_cont_rotime,
-       .mask   = CLOCKSOURCE_MASK(32),
-       .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-static int __init etrax_init_cont_rotime(void)
-{
-       clocksource_register_khz(&cont_rotime, 100000);
-       return 0;
-}
-arch_initcall(etrax_init_cont_rotime);
+#define CRISV32_TIMER_FREQ     (100000000lu)
 
 unsigned long timer_regs[NR_CPUS] =
 {
        regi_timer0,
-#ifdef CONFIG_SMP
-       regi_timer2
-#endif
 };
 
 extern int set_rtc_mmss(unsigned long nowtime);
@@ -189,81 +169,104 @@ void handle_watchdog_bite(struct pt_regs *regs)
 #endif
 }
 
-/*
- * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "xtime_update()" routine every clocktick.
- */
-extern void cris_do_profile(struct pt_regs *regs);
+extern void cris_profile_sample(struct pt_regs *regs);
+static void __iomem *timer_base;
 
-static inline irqreturn_t timer_interrupt(int irq, void *dev_id)
+static void crisv32_clkevt_mode(enum clock_event_mode mode,
+                               struct clock_event_device *dev)
 {
-       struct pt_regs *regs = get_irq_regs();
-       int cpu = smp_processor_id();
-       reg_timer_r_masked_intr masked_intr;
-       reg_timer_rw_ack_intr ack_intr = { 0 };
-
-       /* Check if the timer interrupt is for us (a tmr0 int) */
-       masked_intr = REG_RD(timer, timer_regs[cpu], r_masked_intr);
-       if (!masked_intr.tmr0)
-               return IRQ_NONE;
+       reg_timer_rw_tmr0_ctrl ctrl = {
+               .op = regk_timer_hold,
+               .freq = regk_timer_f100,
+       };
 
-       /* Acknowledge the timer irq. */
-       ack_intr.tmr0 = 1;
-       REG_WR(timer, timer_regs[cpu], rw_ack_intr, ack_intr);
+       REG_WR(timer, timer_base, rw_tmr0_ctrl, ctrl);
+}
 
-       /* Reset watchdog otherwise it resets us! */
-       reset_watchdog();
+static int crisv32_clkevt_next_event(unsigned long evt,
+                                    struct clock_event_device *dev)
+{
+       reg_timer_rw_tmr0_ctrl ctrl = {
+               .op = regk_timer_ld,
+               .freq = regk_timer_f100,
+       };
+
+       REG_WR(timer, timer_base, rw_tmr0_div, evt);
+       REG_WR(timer, timer_base, rw_tmr0_ctrl, ctrl);
+
+       ctrl.op = regk_timer_run;
+       REG_WR(timer, timer_base, rw_tmr0_ctrl, ctrl);
+
+       return 0;
+}
+
+static irqreturn_t crisv32_timer_interrupt(int irq, void *dev_id)
+{
+       struct clock_event_device *evt = dev_id;
+       reg_timer_rw_tmr0_ctrl ctrl = {
+               .op = regk_timer_hold,
+               .freq = regk_timer_f100,
+       };
+       reg_timer_rw_ack_intr ack = { .tmr0 = 1 };
+       reg_timer_r_masked_intr intr;
+
+       intr = REG_RD(timer, timer_base, r_masked_intr);
+       if (!intr.tmr0)
+               return IRQ_NONE;
 
-       /* Update statistics. */
-       update_process_times(user_mode(regs));
+       REG_WR(timer, timer_base, rw_tmr0_ctrl, ctrl);
+       REG_WR(timer, timer_base, rw_ack_intr, ack);
 
-       cris_do_profile(regs); /* Save profiling information */
+       reset_watchdog();
+#ifdef CONFIG_SYSTEM_PROFILER
+       cris_profile_sample(get_irq_regs());
+#endif
 
-       /* The master CPU is responsible for the time keeping. */
-       if (cpu != 0)
-               return IRQ_HANDLED;
+       evt->event_handler(evt);
 
-       /* Call the real timer interrupt handler */
-       xtime_update(1);
        return IRQ_HANDLED;
 }
 
+static struct clock_event_device crisv32_clockevent = {
+       .name = "crisv32-timer",
+       .rating = 300,
+       .features = CLOCK_EVT_FEAT_ONESHOT,
+       .set_mode = crisv32_clkevt_mode,
+       .set_next_event = crisv32_clkevt_next_event,
+};
+
 /* Timer is IRQF_SHARED so drivers can add stuff to the timer irq chain. */
 static struct irqaction irq_timer = {
-       .handler = timer_interrupt,
-       .flags = IRQF_SHARED,
-       .name = "timer"
+       .handler = crisv32_timer_interrupt,
+       .flags = IRQF_TIMER | IRQF_SHARED,
+       .name = "crisv32-timer",
+       .dev_id = &crisv32_clockevent,
 };
 
-void __init cris_timer_init(void)
+static u64 notrace crisv32_timer_sched_clock(void)
 {
-       int cpu = smp_processor_id();
-       reg_timer_rw_tmr0_ctrl tmr0_ctrl = { 0 };
-       reg_timer_rw_tmr0_div tmr0_div = TIMER0_DIV;
-       reg_timer_rw_intr_mask timer_intr_mask;
+       return REG_RD(timer, timer_base, r_time);
+}
 
-       /* Setup the etrax timers.
-        * Base frequency is 100MHz, divider 1000000 -> 100 HZ
-        * We use timer0, so timer1 is free.
-        * The trig timer is used by the fasttimer API if enabled.
-        */
+static void __init crisv32_timer_init(void)
+{
+       reg_timer_rw_intr_mask timer_intr_mask;
+       reg_timer_rw_tmr0_ctrl ctrl = {
+               .op = regk_timer_hold,
+               .freq = regk_timer_f100,
+       };
 
-       tmr0_ctrl.op = regk_timer_ld;
-       tmr0_ctrl.freq = regk_timer_f100;
-       REG_WR(timer, timer_regs[cpu], rw_tmr0_div, tmr0_div);
-       REG_WR(timer, timer_regs[cpu], rw_tmr0_ctrl, tmr0_ctrl); /* Load */
-       tmr0_ctrl.op = regk_timer_run;
-       REG_WR(timer, timer_regs[cpu], rw_tmr0_ctrl, tmr0_ctrl); /* Start */
+       REG_WR(timer, timer_base, rw_tmr0_ctrl, ctrl);
 
-       /* Enable the timer irq. */
-       timer_intr_mask = REG_RD(timer, timer_regs[cpu], rw_intr_mask);
+       timer_intr_mask = REG_RD(timer, timer_base, rw_intr_mask);
        timer_intr_mask.tmr0 = 1;
-       REG_WR(timer, timer_regs[cpu], rw_intr_mask, timer_intr_mask);
+       REG_WR(timer, timer_base, rw_intr_mask, timer_intr_mask);
 }
 
 void __init time_init(void)
 {
-       reg_intr_vect_rw_mask intr_mask;
+       int irq;
+       int ret;
 
        /* Probe for the RTC and read it if it exists.
         * Before the RTC can be probed the loops_per_usec variable needs
@@ -273,17 +276,28 @@ void __init time_init(void)
         */
        loops_per_usec = 50;
 
-       /* Start CPU local timer. */
-       cris_timer_init();
+       irq = TIMER0_INTR_VECT;
+       timer_base = (void __iomem *) regi_timer0;
+
+       crisv32_timer_init();
+
+       sched_clock_register(crisv32_timer_sched_clock, 32,
+                            CRISV32_TIMER_FREQ);
+
+       clocksource_mmio_init(timer_base + REG_RD_ADDR_timer_r_time,
+                             "crisv32-timer", CRISV32_TIMER_FREQ,
+                             300, 32, clocksource_mmio_readl_up);
+
+       crisv32_clockevent.cpumask = cpu_possible_mask;
+       crisv32_clockevent.irq = irq;
 
-       /* Enable the timer irq in global config. */
-       intr_mask = REG_RD_VECT(intr_vect, regi_irq, rw_mask, 1);
-       intr_mask.timer0 = 1;
-       REG_WR_VECT(intr_vect, regi_irq, rw_mask, 1, intr_mask);
+       ret = setup_irq(irq, &irq_timer);
+       if (ret)
+               pr_warn("failed to setup irq %d\n", irq);
 
-       /* Now actually register the timer irq handler that calls
-        * timer_interrupt(). */
-       setup_irq(TIMER0_INTR_VECT, &irq_timer);
+       clockevents_config_and_register(&crisv32_clockevent,
+                                       CRISV32_TIMER_FREQ,
+                                       2, 0xffffffff);
 
        /* Enable watchdog if we should use one. */
 
index dd296b9db034a5e1d5791ca0069c875fbb5b18e9..e91cf02f625d1c9a57960330a1074d50fbd74dfd 100644 (file)
@@ -3,5 +3,5 @@
 #
 
 lib-y  = checksum.o checksumcopy.o string.o usercopy.o memset.o \
-       csumcpfruser.o spinlock.o delay.o strcmp.o
+       csumcpfruser.o delay.o strcmp.o
 
diff --git a/arch/cris/arch-v32/lib/spinlock.S b/arch/cris/arch-v32/lib/spinlock.S
deleted file mode 100644 (file)
index fe610b9..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-;; Core of the spinlock implementation
-;;
-;; Copyright (C) 2004 Axis Communications AB.
-;;
-;; Author: Mikael Starvik
-
-
-       .global cris_spin_lock
-       .type   cris_spin_lock,@function
-       .global cris_spin_trylock
-       .type   cris_spin_trylock,@function
-
-       .text
-
-cris_spin_lock:
-       clearf  p
-1:     test.b  [$r10]
-       beq     1b
-       clearf  p
-       ax
-       clear.b [$r10]
-       bcs     1b
-       clearf  p
-       ret
-       nop
-
-       .size   cris_spin_lock, . - cris_spin_lock
-
-cris_spin_trylock:
-       clearf  p
-1:     move.b  [$r10], $r11
-       ax
-       clear.b [$r10]
-        bcs    1b
-        clearf p
-       ret
-       movu.b  $r11,$r10
-
-       .size   cris_spin_trylock, . - cris_spin_trylock
-
index 3deca5253d91be5e448253abec875994ba7b9f9b..f5438ca8122df9cd33139dde81fad698a4f39b2c 100644 (file)
@@ -40,17 +40,6 @@ void __init cris_mmu_init(void)
         */
        per_cpu(current_pgd, smp_processor_id()) = init_mm.pgd;
 
-#ifdef CONFIG_SMP
-       {
-               pgd_t **pgd;
-               pgd = (pgd_t**)&per_cpu(current_pgd, smp_processor_id());
-               SUPP_BANK_SEL(1);
-               SUPP_REG_WR(RW_MM_TLB_PGD, pgd);
-               SUPP_BANK_SEL(2);
-               SUPP_REG_WR(RW_MM_TLB_PGD, pgd);
-       }
-#endif
-
        /* Initialise the TLB. Function found in tlb.c. */
        tlb_init();
 
index 72727c1d8e602a5ee95281ef7ee01a97da7a72e8..c0981044eccbc0a43c4aca85b2f32c0856e2907f 100644 (file)
        move.d  $r0, [$r1]      ; last_refill_cause = rw_mm_cause
 
 3:     ; Probably not in a loop, continue normal processing
-#ifdef CONFIG_SMP
-       move    $s7, $acr       ; PGD
-#else
        move.d  current_pgd, $acr ; PGD
-#endif
        ; Look up PMD in PGD
        lsrq    24, $r0 ; Get PMD index into PGD (bit 24-31)
        move.d  [$acr], $acr    ; PGD for the current process
diff --git a/arch/cris/boot/dts/Makefile b/arch/cris/boot/dts/Makefile
new file mode 100644 (file)
index 0000000..faf69fb
--- /dev/null
@@ -0,0 +1,6 @@
+BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_BUILTIN_DTB)).dtb.o
+ifneq ($(CONFIG_BUILTIN_DTB),"")
+obj-$(CONFIG_OF) += $(BUILTIN_DTB)
+endif
+
+clean-files := *.dtb.S
diff --git a/arch/cris/boot/dts/dev88.dts b/arch/cris/boot/dts/dev88.dts
new file mode 100644 (file)
index 0000000..4fa5a3f
--- /dev/null
@@ -0,0 +1,18 @@
+/dts-v1/;
+
+/include/ "etraxfs.dtsi"
+
+/ {
+       model = "Axis 88 Developer Board";
+       compatible = "axis,dev88";
+
+       aliases {
+               serial0 = &uart0;
+       };
+
+       soc {
+               uart0: serial@b00260000 {
+                       status = "okay";
+               };
+       };
+};
diff --git a/arch/cris/boot/dts/etraxfs.dtsi b/arch/cris/boot/dts/etraxfs.dtsi
new file mode 100644 (file)
index 0000000..909bced
--- /dev/null
@@ -0,0 +1,38 @@
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+       interrupt-parent = <&intc>;
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@0 {
+                       device_type = "cpu";
+                       model = "axis,crisv32";
+                       reg = <0>;
+               };
+       };
+
+       soc {
+               compatible = "simple-bus";
+               model = "etraxfs";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               intc: interrupt-controller {
+                       compatible = "axis,crisv32-intc";
+                       reg = <0xb001c000 0x1000>;
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               serial@b00260000 {
+                       compatible = "axis,etraxfs-uart";
+                       reg = <0xb0026000 0x1000>;
+                       interrupts = <68>;
+                       status = "disabled";
+               };
+       };
+};
diff --git a/arch/cris/include/arch-v10/arch/atomic.h b/arch/cris/include/arch-v10/arch/atomic.h
deleted file mode 100644 (file)
index 6ef5e7d..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_CRIS_ARCH_ATOMIC__
-#define __ASM_CRIS_ARCH_ATOMIC__
-
-#define cris_atomic_save(addr, flags) local_irq_save(flags);
-#define cris_atomic_restore(addr, flags) local_irq_restore(flags);
-
-#endif
index 935fde34aa15782db1fc2dd7c39e4b47c2a96992..9b5580f58b96cb0b7c61d8892673585111dc40e9 100644 (file)
@@ -36,12 +36,4 @@ static inline unsigned long _get_base(char * addr)
   return 0;
 }
 
-#define nop() __asm__ __volatile__ ("nop");
-
-#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-#define tas(ptr) (xchg((ptr),1))
-
-struct __xchg_dummy { unsigned long a[100]; };
-#define __xg(x) ((struct __xchg_dummy *)(x))
-
 #endif
diff --git a/arch/cris/include/arch-v32/arch/atomic.h b/arch/cris/include/arch-v32/arch/atomic.h
deleted file mode 100644 (file)
index 852ceff..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef __ASM_CRIS_ARCH_ATOMIC__
-#define __ASM_CRIS_ARCH_ATOMIC__
-
-#include <linux/spinlock_types.h>
-
-extern void cris_spin_unlock(void *l, int val);
-extern void cris_spin_lock(void *l);
-extern int cris_spin_trylock(void* l);
-
-#ifndef CONFIG_SMP
-#define cris_atomic_save(addr, flags) local_irq_save(flags);
-#define cris_atomic_restore(addr, flags) local_irq_restore(flags);
-#else
-
-extern spinlock_t cris_atomic_locks[];
-#define LOCK_COUNT 128
-#define HASH_ADDR(a) (((int)a) & 127)
-
-#define cris_atomic_save(addr, flags) \
-  local_irq_save(flags); \
-  cris_spin_lock((void *)&cris_atomic_locks[HASH_ADDR(addr)].raw_lock.slock);
-
-#define cris_atomic_restore(addr, flags) \
-  { \
-    spinlock_t *lock = (void*)&cris_atomic_locks[HASH_ADDR(addr)]; \
-    __asm__ volatile ("move.d %1,%0" \
-                       : "=m" (lock->raw_lock.slock) \
-                       : "r" (1) \
-                       : "memory"); \
-    local_irq_restore(flags); \
-  }
-
-#endif
-
-#endif
-
index a024b7d32fed9b9066cd66e11fe8ffcd222aba9b..568759271ab537a954548cab4d562cb85bd43b07 100644 (file)
@@ -25,8 +25,7 @@ struct thread_struct {
  */
 #define TASK_SIZE      (0xB0000000UL)
 
-/* CCS I=1, enable interrupts. */
-#define INIT_THREAD { 0, 0, (1 << I_CCS_BITNR) }
+#define INIT_THREAD { }
 
 #define KSTK_EIP(tsk)          \
 ({                             \
diff --git a/arch/cris/include/arch-v32/arch/spinlock.h b/arch/cris/include/arch-v32/arch/spinlock.h
deleted file mode 100644 (file)
index f132755..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-#ifndef __ASM_ARCH_SPINLOCK_H
-#define __ASM_ARCH_SPINLOCK_H
-
-#include <linux/spinlock_types.h>
-
-#define RW_LOCK_BIAS 0x01000000
-
-extern void cris_spin_unlock(void *l, int val);
-extern void cris_spin_lock(void *l);
-extern int cris_spin_trylock(void *l);
-
-static inline int arch_spin_is_locked(arch_spinlock_t *x)
-{
-       return *(volatile signed char *)(&(x)->slock) <= 0;
-}
-
-static inline void arch_spin_unlock(arch_spinlock_t *lock)
-{
-       __asm__ volatile ("move.d %1,%0" \
-                         : "=m" (lock->slock) \
-                         : "r" (1) \
-                         : "memory");
-}
-
-static inline void arch_spin_unlock_wait(arch_spinlock_t *lock)
-{
-       while (arch_spin_is_locked(lock))
-               cpu_relax();
-}
-
-static inline int arch_spin_trylock(arch_spinlock_t *lock)
-{
-       return cris_spin_trylock((void *)&lock->slock);
-}
-
-static inline void arch_spin_lock(arch_spinlock_t *lock)
-{
-       cris_spin_lock((void *)&lock->slock);
-}
-
-static inline void
-arch_spin_lock_flags(arch_spinlock_t *lock, unsigned long flags)
-{
-       arch_spin_lock(lock);
-}
-
-/*
- * Read-write spinlocks, allowing multiple readers
- * but only one writer.
- *
- * NOTE! it is quite common to have readers in interrupts
- * but no interrupt writers. For those circumstances we
- * can "mix" irq-safe locks - any writer needs to get a
- * irq-safe write-lock, but readers can get non-irqsafe
- * read-locks.
- *
- */
-
-static inline int arch_read_can_lock(arch_rwlock_t *x)
-{
-       return (int)(x)->lock > 0;
-}
-
-static inline int arch_write_can_lock(arch_rwlock_t *x)
-{
-       return (x)->lock == RW_LOCK_BIAS;
-}
-
-static  inline void arch_read_lock(arch_rwlock_t *rw)
-{
-       arch_spin_lock(&rw->slock);
-       while (rw->lock == 0);
-       rw->lock--;
-       arch_spin_unlock(&rw->slock);
-}
-
-static  inline void arch_write_lock(arch_rwlock_t *rw)
-{
-       arch_spin_lock(&rw->slock);
-       while (rw->lock != RW_LOCK_BIAS);
-       rw->lock = 0;
-       arch_spin_unlock(&rw->slock);
-}
-
-static  inline void arch_read_unlock(arch_rwlock_t *rw)
-{
-       arch_spin_lock(&rw->slock);
-       rw->lock++;
-       arch_spin_unlock(&rw->slock);
-}
-
-static  inline void arch_write_unlock(arch_rwlock_t *rw)
-{
-       arch_spin_lock(&rw->slock);
-       while (rw->lock != RW_LOCK_BIAS);
-       rw->lock = RW_LOCK_BIAS;
-       arch_spin_unlock(&rw->slock);
-}
-
-static  inline int arch_read_trylock(arch_rwlock_t *rw)
-{
-       int ret = 0;
-       arch_spin_lock(&rw->slock);
-       if (rw->lock != 0) {
-               rw->lock--;
-               ret = 1;
-       }
-       arch_spin_unlock(&rw->slock);
-       return ret;
-}
-
-static  inline int arch_write_trylock(arch_rwlock_t *rw)
-{
-       int ret = 0;
-       arch_spin_lock(&rw->slock);
-       if (rw->lock == RW_LOCK_BIAS) {
-               rw->lock = 0;
-               ret = 1;
-       }
-       arch_spin_unlock(&rw->slock);
-       return ret;
-}
-
-#define _raw_read_lock_flags(lock, flags) _raw_read_lock(lock)
-#define _raw_write_lock_flags(lock, flags) _raw_write_lock(lock)
-
-#define arch_spin_relax(lock)  cpu_relax()
-#define arch_read_relax(lock)  cpu_relax()
-#define arch_write_relax(lock) cpu_relax()
-
-#endif /* __ASM_ARCH_SPINLOCK_H */
index 889f2de050a34e80e1cbd1424e8307a1f7442566..057e51859b0a3ae3efc992bcdf413b73e2c2d7a0 100644 (file)
@@ -1,16 +1,29 @@
-
+generic-y += atomic.h
 generic-y += barrier.h
 generic-y += clkdev.h
+generic-y += cmpxchg.h
 generic-y += cputime.h
+generic-y += device.h
+generic-y += div64.h
 generic-y += exec.h
+generic-y += emergency-restart.h
+generic-y += futex.h
+generic-y += hardirq.h
+generic-y += irq_regs.h
 generic-y += irq_work.h
+generic-y += kdebug.h
+generic-y += kmap_types.h
 generic-y += kvm_para.h
 generic-y += linkage.h
+generic-y += local.h
+generic-y += local64.h
 generic-y += mcs_spinlock.h
 generic-y += module.h
+generic-y += percpu.h
 generic-y += preempt.h
 generic-y += scatterlist.h
 generic-y += sections.h
+generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += vga.h
 generic-y += xor.h
diff --git a/arch/cris/include/asm/atomic.h b/arch/cris/include/asm/atomic.h
deleted file mode 100644 (file)
index 279766a..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-/* $Id: atomic.h,v 1.3 2001/07/25 16:15:19 bjornw Exp $ */
-
-#ifndef __ASM_CRIS_ATOMIC__
-#define __ASM_CRIS_ATOMIC__
-
-#include <linux/compiler.h>
-#include <linux/types.h>
-#include <asm/cmpxchg.h>
-#include <arch/atomic.h>
-#include <arch/system.h>
-#include <asm/barrier.h>
-
-/*
- * Atomic operations that C can't guarantee us.  Useful for
- * resource counting etc..
- */
-
-#define ATOMIC_INIT(i)  { (i) }
-
-#define atomic_read(v) ACCESS_ONCE((v)->counter)
-#define atomic_set(v,i) (((v)->counter) = (i))
-
-/* These should be written in asm but we do it in C for now. */
-
-#define ATOMIC_OP(op, c_op)                                            \
-static inline void atomic_##op(int i, volatile atomic_t *v)            \
-{                                                                      \
-       unsigned long flags;                                            \
-       cris_atomic_save(v, flags);                                     \
-       v->counter c_op i;                                              \
-       cris_atomic_restore(v, flags);                                  \
-}                                                                      \
-
-#define ATOMIC_OP_RETURN(op, c_op)                                     \
-static inline int atomic_##op##_return(int i, volatile atomic_t *v)    \
-{                                                                      \
-       unsigned long flags;                                            \
-       int retval;                                                     \
-       cris_atomic_save(v, flags);                                     \
-       retval = (v->counter c_op i);                                   \
-       cris_atomic_restore(v, flags);                                  \
-       return retval;                                                  \
-}
-
-#define ATOMIC_OPS(op, c_op) ATOMIC_OP(op, c_op) ATOMIC_OP_RETURN(op, c_op)
-
-ATOMIC_OPS(add, +=)
-ATOMIC_OPS(sub, -=)
-
-#undef ATOMIC_OPS
-#undef ATOMIC_OP_RETURN
-#undef ATOMIC_OP
-
-#define atomic_add_negative(a, v)      (atomic_add_return((a), (v)) < 0)
-
-static inline int atomic_sub_and_test(int i, volatile atomic_t *v)
-{
-       int retval;
-       unsigned long flags;
-       cris_atomic_save(v, flags);
-       retval = (v->counter -= i) == 0;
-       cris_atomic_restore(v, flags);
-       return retval;
-}
-
-static inline void atomic_inc(volatile atomic_t *v)
-{
-       unsigned long flags;
-       cris_atomic_save(v, flags);
-       (v->counter)++;
-       cris_atomic_restore(v, flags);
-}
-
-static inline void atomic_dec(volatile atomic_t *v)
-{
-       unsigned long flags;
-       cris_atomic_save(v, flags);
-       (v->counter)--;
-       cris_atomic_restore(v, flags);
-}
-
-static inline int atomic_inc_return(volatile atomic_t *v)
-{
-       unsigned long flags;
-       int retval;
-       cris_atomic_save(v, flags);
-       retval = ++(v->counter);
-       cris_atomic_restore(v, flags);
-       return retval;
-}
-
-static inline int atomic_dec_return(volatile atomic_t *v)
-{
-       unsigned long flags;
-       int retval;
-       cris_atomic_save(v, flags);
-       retval = --(v->counter);
-       cris_atomic_restore(v, flags);
-       return retval;
-}
-static inline int atomic_dec_and_test(volatile atomic_t *v)
-{
-       int retval;
-       unsigned long flags;
-       cris_atomic_save(v, flags);
-       retval = --(v->counter) == 0;
-       cris_atomic_restore(v, flags);
-       return retval;
-}
-
-static inline int atomic_inc_and_test(volatile atomic_t *v)
-{
-       int retval;
-       unsigned long flags;
-       cris_atomic_save(v, flags);
-       retval = ++(v->counter) == 0;
-       cris_atomic_restore(v, flags);
-       return retval;
-}
-
-static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
-{
-       int ret;
-       unsigned long flags;
-
-       cris_atomic_save(v, flags);
-       ret = v->counter;
-       if (likely(ret == old))
-               v->counter = new;
-       cris_atomic_restore(v, flags);
-       return ret;
-}
-
-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
-
-static inline int __atomic_add_unless(atomic_t *v, int a, int u)
-{
-       int ret;
-       unsigned long flags;
-
-       cris_atomic_save(v, flags);
-       ret = v->counter;
-       if (ret != u)
-               v->counter += a;
-       cris_atomic_restore(v, flags);
-       return ret;
-}
-
-#endif
index bd49a546f4f5f6a7230920d8ef6b20b55cc398e9..8062cb52d343220eb596a49a7cc383368e17b5f6 100644 (file)
 #endif
 
 #include <arch/bitops.h>
-#include <linux/atomic.h>
 #include <linux/compiler.h>
 #include <asm/barrier.h>
 
-/*
- * set_bit - Atomically set a bit in memory
- * @nr: the bit to set
- * @addr: the address to start counting from
- *
- * This function is atomic and may not be reordered.  See __set_bit()
- * if you do not require the atomic guarantees.
- * Note that @nr may be almost arbitrarily large; this function is not
- * restricted to acting on a single-word quantity.
- */
-
-#define set_bit(nr, addr)    (void)test_and_set_bit(nr, addr)
-
-/*
- * clear_bit - Clears a bit in memory
- * @nr: Bit to clear
- * @addr: Address to start counting from
- *
- * clear_bit() is atomic and may not be reordered.  However, it does
- * not contain a memory barrier, so if it is used for locking purposes,
- * you should call smp_mb__before_atomic() and/or smp_mb__after_atomic()
- * in order to ensure changes are visible on other processors.
- */
-
-#define clear_bit(nr, addr)  (void)test_and_clear_bit(nr, addr)
-
-/*
- * change_bit - Toggle a bit in memory
- * @nr: Bit to change
- * @addr: Address to start counting from
- *
- * change_bit() is atomic and may not be reordered.
- * Note that @nr may be almost arbitrarily large; this function is not
- * restricted to acting on a single-word quantity.
- */
-
-#define change_bit(nr, addr) (void)test_and_change_bit(nr, addr)
-
-/**
- * test_and_set_bit - Set a bit and return its old value
- * @nr: Bit to set
- * @addr: Address to count from
- *
- * This operation is atomic and cannot be reordered.  
- * It also implies a memory barrier.
- */
-
-static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
-{
-       unsigned int mask, retval;
-       unsigned long flags;
-       unsigned int *adr = (unsigned int *)addr;
-       
-       adr += nr >> 5;
-       mask = 1 << (nr & 0x1f);
-       cris_atomic_save(addr, flags);
-       retval = (mask & *adr) != 0;
-       *adr |= mask;
-       cris_atomic_restore(addr, flags);
-       return retval;
-}
-
-/**
- * test_and_clear_bit - Clear a bit and return its old value
- * @nr: Bit to clear
- * @addr: Address to count from
- *
- * This operation is atomic and cannot be reordered.  
- * It also implies a memory barrier.
- */
-
-static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
-{
-       unsigned int mask, retval;
-       unsigned long flags;
-       unsigned int *adr = (unsigned int *)addr;
-       
-       adr += nr >> 5;
-       mask = 1 << (nr & 0x1f);
-       cris_atomic_save(addr, flags);
-       retval = (mask & *adr) != 0;
-       *adr &= ~mask;
-       cris_atomic_restore(addr, flags);
-       return retval;
-}
-
-/**
- * test_and_change_bit - Change a bit and return its old value
- * @nr: Bit to change
- * @addr: Address to count from
- *
- * This operation is atomic and cannot be reordered.  
- * It also implies a memory barrier.
- */
-
-static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
-{
-       unsigned int mask, retval;
-       unsigned long flags;
-       unsigned int *adr = (unsigned int *)addr;
-       adr += nr >> 5;
-       mask = 1 << (nr & 0x1f);
-       cris_atomic_save(addr, flags);
-       retval = (mask & *adr) != 0;
-       *adr ^= mask;
-       cris_atomic_restore(addr, flags);
-       return retval;
-}
-
+#include <asm-generic/bitops/atomic.h>
 #include <asm-generic/bitops/non-atomic.h>
 
 /*
diff --git a/arch/cris/include/asm/cmpxchg.h b/arch/cris/include/asm/cmpxchg.h
deleted file mode 100644 (file)
index b756dac..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-#ifndef __ASM_CRIS_CMPXCHG__
-#define __ASM_CRIS_CMPXCHG__
-
-#include <linux/irqflags.h>
-
-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
-{
-  /* since Etrax doesn't have any atomic xchg instructions, we need to disable
-     irq's (if enabled) and do it with move.d's */
-  unsigned long flags,temp;
-  local_irq_save(flags); /* save flags, including irq enable bit and shut off irqs */
-  switch (size) {
-  case 1:
-    *((unsigned char *)&temp) = x;
-    x = *(unsigned char *)ptr;
-    *(unsigned char *)ptr = *((unsigned char *)&temp);
-    break;
-  case 2:
-    *((unsigned short *)&temp) = x;
-    x = *(unsigned short *)ptr;
-    *(unsigned short *)ptr = *((unsigned short *)&temp);
-    break;
-  case 4:
-    temp = x;
-    x = *(unsigned long *)ptr;
-    *(unsigned long *)ptr = temp;
-    break;
-  }
-  local_irq_restore(flags); /* restore irq enable bit */
-  return x;
-}
-
-#define xchg(ptr,x) \
-       ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-
-#define tas(ptr) (xchg((ptr),1))
-
-#include <asm-generic/cmpxchg-local.h>
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-#define cmpxchg_local(ptr, o, n)                                              \
-       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
-                       (unsigned long)(n), sizeof(*(ptr))))
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-#ifndef CONFIG_SMP
-#include <asm-generic/cmpxchg.h>
-#endif
-
-#endif /* __ASM_CRIS_CMPXCHG__ */
diff --git a/arch/cris/include/asm/device.h b/arch/cris/include/asm/device.h
deleted file mode 100644 (file)
index d8f9872..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * Arch specific extensions to struct device
- *
- * This file is released under the GPLv2
- */
-#include <asm-generic/device.h>
-
diff --git a/arch/cris/include/asm/div64.h b/arch/cris/include/asm/div64.h
deleted file mode 100644 (file)
index 6cd978c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/div64.h>
index 30ded8fbf59297bd84294211cd5e9fa0087e959c..c2a394ff55ff39f31cfe1f96893865ee8f5d97a9 100644 (file)
@@ -71,7 +71,7 @@ typedef unsigned long elf_fpregset_t;
    the loader.  We need to make sure that it is out of the way of the program
    that it will "exec", and that there is sufficient room for the brk.  */
 
-#define ELF_ET_DYN_BASE         (2 * TASK_SIZE / 3)
+#define ELF_ET_DYN_BASE         (TASK_SIZE / 3 * 2)
 
 /* This yields a mask that user programs can use to figure out what
    instruction set this CPU supports.  This could be done in user space,
diff --git a/arch/cris/include/asm/emergency-restart.h b/arch/cris/include/asm/emergency-restart.h
deleted file mode 100644 (file)
index 108d8c4..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_EMERGENCY_RESTART_H
-#define _ASM_EMERGENCY_RESTART_H
-
-#include <asm-generic/emergency-restart.h>
-
-#endif /* _ASM_EMERGENCY_RESTART_H */
diff --git a/arch/cris/include/asm/futex.h b/arch/cris/include/asm/futex.h
deleted file mode 100644 (file)
index 6a332a9..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_FUTEX_H
-#define _ASM_FUTEX_H
-
-#include <asm-generic/futex.h>
-
-#endif
diff --git a/arch/cris/include/asm/hardirq.h b/arch/cris/include/asm/hardirq.h
deleted file mode 100644 (file)
index 04126f7..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __ASM_HARDIRQ_H
-#define __ASM_HARDIRQ_H
-
-#include <asm/irq.h>
-#include <asm-generic/hardirq.h>
-
-#endif /* __ASM_HARDIRQ_H */
diff --git a/arch/cris/include/asm/irq_regs.h b/arch/cris/include/asm/irq_regs.h
deleted file mode 100644 (file)
index 3dd9c0b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/irq_regs.h>
diff --git a/arch/cris/include/asm/kdebug.h b/arch/cris/include/asm/kdebug.h
deleted file mode 100644 (file)
index 6ece1b0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kdebug.h>
diff --git a/arch/cris/include/asm/kmap_types.h b/arch/cris/include/asm/kmap_types.h
deleted file mode 100644 (file)
index d2d643c..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _ASM_KMAP_TYPES_H
-#define _ASM_KMAP_TYPES_H
-
-/* Dummy header just to define km_type.  None of this
- * is actually used on cris. 
- */
-
-#include <asm-generic/kmap_types.h>
-
-#endif
diff --git a/arch/cris/include/asm/local.h b/arch/cris/include/asm/local.h
deleted file mode 100644 (file)
index c11c530..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/local.h>
diff --git a/arch/cris/include/asm/local64.h b/arch/cris/include/asm/local64.h
deleted file mode 100644 (file)
index 36c93b5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/local64.h>
diff --git a/arch/cris/include/asm/percpu.h b/arch/cris/include/asm/percpu.h
deleted file mode 100644 (file)
index 6db9b43..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _CRIS_PERCPU_H
-#define _CRIS_PERCPU_H
-
-#include <asm-generic/percpu.h>
-
-#endif /* _CRIS_PERCPU_H */
diff --git a/arch/cris/include/asm/smp.h b/arch/cris/include/asm/smp.h
deleted file mode 100644 (file)
index c615a06..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __ASM_SMP_H
-#define __ASM_SMP_H
-
-#include <linux/cpumask.h>
-
-extern cpumask_t phys_cpu_present_map;
-
-#define raw_smp_processor_id() (current_thread_info()->cpu)
-
-#endif
diff --git a/arch/cris/include/asm/spinlock.h b/arch/cris/include/asm/spinlock.h
deleted file mode 100644 (file)
index ed816b5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <arch/spinlock.h>
index 20697e7ef4f2091d594bb187b512cba4f4b88017..b424f43a9fd6a41e87b5bbabc16001978c5df356 100644 (file)
@@ -22,16 +22,9 @@ extern void __flush_tlb_mm(struct mm_struct *mm);
 extern void __flush_tlb_page(struct vm_area_struct *vma,
                           unsigned long addr);
 
-#ifdef CONFIG_SMP
-extern void flush_tlb_all(void);
-extern void flush_tlb_mm(struct mm_struct *mm);
-extern void flush_tlb_page(struct vm_area_struct *vma, 
-                          unsigned long addr);
-#else
 #define flush_tlb_all __flush_tlb_all
 #define flush_tlb_mm __flush_tlb_mm
 #define flush_tlb_page __flush_tlb_page
-#endif
 
 static inline void flush_tlb_range(struct vm_area_struct * vma, unsigned long start, unsigned long end)
 {
diff --git a/arch/cris/include/asm/topology.h b/arch/cris/include/asm/topology.h
deleted file mode 100644 (file)
index 2ac613d..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_CRIS_TOPOLOGY_H
-#define _ASM_CRIS_TOPOLOGY_H
-
-#include <asm-generic/topology.h>
-
-#endif /* _ASM_CRIS_TOPOLOGY_H */
index b45640b3e6006cf3b5da0c5b5330534d7520fe3a..edef71f12bb8860c147dfb1ef703d817cef33d9d 100644 (file)
@@ -7,6 +7,7 @@ CPPFLAGS_vmlinux.lds := -DDRAM_VIRTUAL_BASE=0x$(CONFIG_ETRAX_DRAM_VIRTUAL_BASE)
 extra-y        := vmlinux.lds
 
 obj-y   := process.o traps.o irq.o ptrace.o setup.o time.o sys_cris.o
+obj-y += devicetree.o
 
 obj-$(CONFIG_MODULES)    += crisksyms.o
 obj-$(CONFIG_MODULES)   += module.o
diff --git a/arch/cris/kernel/devicetree.c b/arch/cris/kernel/devicetree.c
new file mode 100644 (file)
index 0000000..53ff8d7
--- /dev/null
@@ -0,0 +1,14 @@
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/printk.h>
+
+void __init early_init_dt_add_memory_arch(u64 base, u64 size)
+{
+       pr_err("%s(%llx, %llx)\n",
+              __func__, base, size);
+}
+
+void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
+{
+       return alloc_bootmem_align(size, align);
+}
index 58d44ee1a71f70885aef328fdf6a6af32d6c7b58..fd3427e563c55b35cd440fd0619ce4a612fa5ad3 100644 (file)
@@ -42,3 +42,26 @@ void do_notify_resume(int canrestart, struct pt_regs *regs,
                tracehook_notify_resume(regs);
        }
 }
+
+void do_work_pending(int syscall, struct pt_regs *regs,
+                    unsigned int thread_flags)
+{
+       do {
+               if (likely(thread_flags & _TIF_NEED_RESCHED)) {
+                       schedule();
+               } else {
+                       if (unlikely(!user_mode(regs)))
+                               return;
+                       local_irq_enable();
+                       if (thread_flags & _TIF_SIGPENDING) {
+                               do_signal(syscall, regs);
+                               syscall = 0;
+                       } else {
+                               clear_thread_flag(TIF_NOTIFY_RESUME);
+                               tracehook_notify_resume(regs);
+                       }
+               }
+               local_irq_disable();
+               thread_flags = current_thread_info()->flags;
+       } while (thread_flags & _TIF_WORK_MASK);
+}
index 905b70ea9939dcc629da3574fc30b4441e34cb63..bb12aa93201df1b0cdd904d1a09b785705e72945 100644 (file)
@@ -19,6 +19,9 @@
 #include <linux/utsname.h>
 #include <linux/pfn.h>
 #include <linux/cpu.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/of_platform.h>
 #include <asm/setup.h>
 #include <arch/system.h>
 
@@ -64,6 +67,10 @@ void __init setup_arch(char **cmdline_p)
        unsigned long start_pfn, max_pfn;
        unsigned long memory_start;
 
+#ifdef CONFIG_OF
+       early_init_dt_scan(__dtb_start);
+#endif
+
        /* register an initial console printing routine for printk's */
 
        init_etrax_debug();
@@ -141,6 +148,8 @@ void __init setup_arch(char **cmdline_p)
 
        reserve_bootmem(PFN_PHYS(start_pfn), bootmap_size, BOOTMEM_DEFAULT);
 
+       unflatten_and_copy_device_tree();
+
        /* paging_init() sets up the MMU and marks all pages as reserved */
 
        paging_init();
@@ -204,3 +213,9 @@ static int __init topology_init(void)
 
 subsys_initcall(topology_init);
 
+static int __init cris_of_init(void)
+{
+       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+       return 0;
+}
+core_initcall(cris_of_init);
index fe6acdabbc8d755b1d8de64a2ab7a917317896f8..7780d379522f49bcebddc54ddfc57f7d1d6d1e34 100644 (file)
@@ -79,11 +79,13 @@ cris_do_profile(struct pt_regs* regs)
 #endif
 }
 
+#ifndef CONFIG_GENERIC_SCHED_CLOCK
 unsigned long long sched_clock(void)
 {
        return (unsigned long long)jiffies * (NSEC_PER_SEC / HZ) +
                get_ns_in_jiffie();
 }
+#endif
 
 static int
 __init init_udelay(void)
index 99bb7efaf9b7ec458762cd3f5016a92949a44987..0b78bc89e8402f867fcdbb31e85ff2cffa693494 100644 (file)
@@ -342,6 +342,11 @@ static inline void iowrite32(u32 val, void __iomem *p)
                __flush_PCI_writes();
 }
 
+#define ioread16be(addr)       be16_to_cpu(ioread16(addr))
+#define ioread32be(addr)       be32_to_cpu(ioread32(addr))
+#define iowrite16be(v, addr)   iowrite16(cpu_to_be16(v), (addr))
+#define iowrite32be(v, addr)   iowrite32(cpu_to_be32(v), (addr))
+
 static inline void ioread8_rep(void __iomem *p, void *dst, unsigned long count)
 {
        io_insb((unsigned long) p, dst, count);
index 4f9a6661491b4d203f568470f4a7d1c18a3efeba..76d25b2cfbbe8fd44bc1386764e9bc4279f1f74c 100644 (file)
@@ -15,6 +15,7 @@ config IA64
        select ARCH_MIGHT_HAVE_PC_SERIO
        select PCI if (!IA64_HP_SIM)
        select ACPI if (!IA64_HP_SIM)
+       select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI
        select ARCH_MIGHT_HAVE_ACPI_PDC if ACPI
        select HAVE_UNSTABLE_SCHED_CLOCK
        select HAVE_IDE
index 35bf22cc71b76358190a1a48dc4697e4947c3ad8..b1698bc042c8aacc63872d7568743fd9c5718f41 100644 (file)
@@ -887,7 +887,7 @@ static int _acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu)
 }
 
 /* wrapper to silence section mismatch warning */
-int __ref acpi_map_cpu(acpi_handle handle, int physid, int *pcpu)
+int __ref acpi_map_cpu(acpi_handle handle, phys_cpuid_t physid, int *pcpu)
 {
        return _acpi_map_lsapic(handle, physid, pcpu);
 }
index 5f4243f0acfa47be82766b2ccb9f8bbe13bcd55e..60e02f7747ff054e4edcce16daa454df8224ed84 100644 (file)
@@ -2159,7 +2159,7 @@ static const struct file_operations pfm_file_ops = {
 static char *pfmfs_dname(struct dentry *dentry, char *buffer, int buflen)
 {
        return dynamic_dname(dentry, buffer, buflen, "pfm:[%lu]",
-                            dentry->d_inode->i_ino);
+                            d_inode(dentry)->i_ino);
 }
 
 static const struct dentry_operations pfmfs_dentry_operations = {
index 48cc65705db467a5d38d1353a452de0ef8f74761..d4e162d35b3467b9d7814769129237583f8cb100 100644 (file)
@@ -240,15 +240,12 @@ static acpi_status resource_to_window(struct acpi_resource *resource,
         * We're only interested in _CRS descriptors that are
         *      - address space descriptors for memory or I/O space
         *      - non-zero size
-        *      - producers, i.e., the address space is routed downstream,
-        *        not consumed by the bridge itself
         */
        status = acpi_resource_to_address64(resource, addr);
        if (ACPI_SUCCESS(status) &&
            (addr->resource_type == ACPI_MEMORY_RANGE ||
             addr->resource_type == ACPI_IO_RANGE) &&
-           addr->address.address_length &&
-           addr->producer_consumer == ACPI_PRODUCER)
+           addr->address.address_length)
                return AE_OK;
 
        return AE_ERROR;
index 6e7787f3dac7bb52f87ec33378193b14f65bf70c..9cc00dbd59cef4096b186fd1ffe5e4b51766f430 100644 (file)
@@ -67,6 +67,7 @@ static inline void __iomem *ioremap(unsigned long offset, unsigned long size)
 
 extern void iounmap(volatile void __iomem *addr);
 #define ioremap_nocache(off,size) ioremap(off,size)
+#define ioremap_wc ioremap_nocache
 
 /*
  * IO bus memory addresses are also 1:1 with the physical address
index 483dff986a23ebdb9e4b762dbf84254e1e715041..7f546183a0f026385354abb547235d8f397255ac 100644 (file)
@@ -174,8 +174,11 @@ void show_regs(struct pt_regs *regs)
        show_trace(NULL, (unsigned long *)regs->ctx.AX[0].U0, regs);
 }
 
+/*
+ * Copy architecture-specific thread state
+ */
 int copy_thread(unsigned long clone_flags, unsigned long usp,
-               unsigned long arg, struct task_struct *tsk)
+               unsigned long kthread_arg, struct task_struct *tsk)
 {
        struct pt_regs *childregs = task_pt_regs(tsk);
        void *kernel_context = ((void *) childregs +
@@ -202,12 +205,13 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
                global_base = __core_reg_get(A1GbP);
                childregs->ctx.AX[0].U1 = (unsigned long) global_base;
                childregs->ctx.AX[0].U0 = (unsigned long) kernel_context;
-               /* Set D1Ar1=arg and D1RtP=usp (fn) */
+               /* Set D1Ar1=kthread_arg and D1RtP=usp (fn) */
                childregs->ctx.DX[4].U1 = usp;
-               childregs->ctx.DX[3].U1 = arg;
+               childregs->ctx.DX[3].U1 = kthread_arg;
                tsk->thread.int_depth = 2;
                return 0;
        }
+
        /*
         * Get a pointer to where the new child's register block should have
         * been pushed.
index 6849f533154f7cf67e4b07e272b002a166e234cd..cec3e187c48f4dcf6e176e14c7e85be1d1234b35 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
-#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
 
 #include <asm/cacheflush.h>
 #include <asm/smp-ops.h>
@@ -75,7 +75,7 @@ static void __init console_config(void)
        if ((strstr(fw_getcmdline(), "earlycon=")) == NULL) {
                sprintf(console_string, "uart8250,io,0x3f8,%d%c%c", baud,
                        parity, bits);
-               setup_early_serial8250_console(console_string);
+               setup_earlycon(console_string);
        }
 
        if ((strstr(fw_getcmdline(), "console=")) == NULL) {
index 897ba3c12b3276b9071a56e70e67e7e39d28850e..cc4a2ba9e228998c7ccbd5af24d5e5d9c5c42fb6 100644 (file)
@@ -197,6 +197,11 @@ static inline void outsl(unsigned long addr, const void *buffer, int count)
 #define iowrite16(v, addr)     writew((v), (addr))
 #define iowrite32(v, addr)     writel((v), (addr))
 
+#define ioread16be(addr)       be16_to_cpu(readw(addr))
+#define ioread32be(addr)       be32_to_cpu(readl(addr))
+#define iowrite16be(v, addr)   writew(cpu_to_be16(v), (addr))
+#define iowrite32be(v, addr)   writel(cpu_to_be32(v), (addr))
+
 #define ioread8_rep(p, dst, count) \
        insb((unsigned long) (p), (dst), (count))
 #define ioread16_rep(p, dst, count) \
index 01c75f36e8b3b7506512367aa114d0469d1a7df1..24b3d8999ac709f5030de524d262bc5ca1a1a1b1 100644 (file)
@@ -46,7 +46,6 @@ generic-y += segment.h
 generic-y += sembuf.h
 generic-y += serial.h
 generic-y += shmbuf.h
-generic-y += shmparam.h
 generic-y += siginfo.h
 generic-y += signal.h
 generic-y += socket.h
diff --git a/arch/nios2/include/asm/shmparam.h b/arch/nios2/include/asm/shmparam.h
new file mode 100644 (file)
index 0000000..6078429
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright Altera Corporation (C) <2015>. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _ASM_NIOS2_SHMPARAM_H
+#define _ASM_NIOS2_SHMPARAM_H
+
+#define        SHMLBA  CONFIG_NIOS2_DCACHE_SIZE
+
+#endif /* _ASM_NIOS2_SHMPARAM_H */
index eff00e67c0a245f5208ece2f662f9055f328f3c6..1d35de90a977b513982d9e71a907c041033a786c 100644 (file)
@@ -14,6 +14,8 @@
 
 #ifndef __ASSEMBLY__
 
+#include <linux/types.h>
+
 /*
  * Register numbers used by 'ptrace' system call interface.
  */
index 27b006c52e12e1193fd392033f5804c1c42c56da..1e515ccd698e38f4a437b43ee6a97eb8c2aed987 100644 (file)
@@ -92,35 +92,35 @@ exception_table:
 
 trap_table:
        .word   handle_system_call      /* 0  */
-       .word   instruction_trap        /* 1  */
-       .word   instruction_trap        /* 2  */
-       .word   instruction_trap        /* 3  */
-       .word   instruction_trap        /* 4  */
-       .word   instruction_trap        /* 5  */
-       .word   instruction_trap        /* 6  */
-       .word   instruction_trap        /* 7  */
-       .word   instruction_trap        /* 8  */
-       .word   instruction_trap        /* 9  */
-       .word   instruction_trap        /* 10 */
-       .word   instruction_trap        /* 11 */
-       .word   instruction_trap        /* 12 */
-       .word   instruction_trap        /* 13 */
-       .word   instruction_trap        /* 14 */
-       .word   instruction_trap        /* 15 */
-       .word   instruction_trap        /* 16 */
-       .word   instruction_trap        /* 17 */
-       .word   instruction_trap        /* 18 */
-       .word   instruction_trap        /* 19 */
-       .word   instruction_trap        /* 20 */
-       .word   instruction_trap        /* 21 */
-       .word   instruction_trap        /* 22 */
-       .word   instruction_trap        /* 23 */
-       .word   instruction_trap        /* 24 */
-       .word   instruction_trap        /* 25 */
-       .word   instruction_trap        /* 26 */
-       .word   instruction_trap        /* 27 */
-       .word   instruction_trap        /* 28 */
-       .word   instruction_trap        /* 29 */
+       .word   handle_trap_1           /* 1  */
+       .word   handle_trap_2           /* 2  */
+       .word   handle_trap_3           /* 3  */
+       .word   handle_trap_reserved    /* 4  */
+       .word   handle_trap_reserved    /* 5  */
+       .word   handle_trap_reserved    /* 6  */
+       .word   handle_trap_reserved    /* 7  */
+       .word   handle_trap_reserved    /* 8  */
+       .word   handle_trap_reserved    /* 9  */
+       .word   handle_trap_reserved    /* 10 */
+       .word   handle_trap_reserved    /* 11 */
+       .word   handle_trap_reserved    /* 12 */
+       .word   handle_trap_reserved    /* 13 */
+       .word   handle_trap_reserved    /* 14 */
+       .word   handle_trap_reserved    /* 15 */
+       .word   handle_trap_reserved    /* 16 */
+       .word   handle_trap_reserved    /* 17 */
+       .word   handle_trap_reserved    /* 18 */
+       .word   handle_trap_reserved    /* 19 */
+       .word   handle_trap_reserved    /* 20 */
+       .word   handle_trap_reserved    /* 21 */
+       .word   handle_trap_reserved    /* 22 */
+       .word   handle_trap_reserved    /* 23 */
+       .word   handle_trap_reserved    /* 24 */
+       .word   handle_trap_reserved    /* 25 */
+       .word   handle_trap_reserved    /* 26 */
+       .word   handle_trap_reserved    /* 27 */
+       .word   handle_trap_reserved    /* 28 */
+       .word   handle_trap_reserved    /* 29 */
 #ifdef CONFIG_KGDB
        .word   handle_kgdb_breakpoint  /* 30 KGDB breakpoint */
 #else
@@ -455,6 +455,19 @@ handle_kgdb_breakpoint:
        br      ret_from_exception
 #endif
 
+handle_trap_1:
+       call    handle_trap_1_c
+       br      ret_from_exception
+
+handle_trap_2:
+       call    handle_trap_2_c
+       br      ret_from_exception
+
+handle_trap_3:
+handle_trap_reserved:
+       call    handle_trap_3_c
+       br      ret_from_exception
+
 /*
  * Beware - when entering resume, prev (the current task) is
  * in r4, next (the new task) is in r5, don't change these
index b7b97641a9a66b6beef868242c61d06032144327..81f7da7b1d5590492940404bca781643fe305c1e 100644 (file)
 
 static DEFINE_SPINLOCK(die_lock);
 
+static void _send_sig(int signo, int code, unsigned long addr)
+{
+       siginfo_t info;
+
+       info.si_signo = signo;
+       info.si_errno = 0;
+       info.si_code = code;
+       info.si_addr = (void __user *) addr;
+       force_sig_info(signo, &info, current);
+}
+
 void die(const char *str, struct pt_regs *regs, long err)
 {
        console_verbose();
@@ -39,16 +50,10 @@ void die(const char *str, struct pt_regs *regs, long err)
 
 void _exception(int signo, struct pt_regs *regs, int code, unsigned long addr)
 {
-       siginfo_t info;
-
        if (!user_mode(regs))
                die("Exception in kernel mode", regs, signo);
 
-       info.si_signo = signo;
-       info.si_errno = 0;
-       info.si_code = code;
-       info.si_addr = (void __user *) addr;
-       force_sig_info(signo, &info, current);
+       _send_sig(signo, code, addr);
 }
 
 /*
@@ -183,3 +188,18 @@ asmlinkage void unhandled_exception(struct pt_regs *regs, int cause)
 
        pr_emerg("opcode: 0x%08lx\n", *(unsigned long *)(regs->ea));
 }
+
+asmlinkage void handle_trap_1_c(struct pt_regs *fp)
+{
+       _send_sig(SIGUSR1, 0, fp->ea);
+}
+
+asmlinkage void handle_trap_2_c(struct pt_regs *fp)
+{
+       _send_sig(SIGUSR2, 0, fp->ea);
+}
+
+asmlinkage void handle_trap_3_c(struct pt_regs *fp)
+{
+       _send_sig(SIGILL, ILL_ILLTRP, fp->ea);
+}
index 796642932e2ef446a9e78b72e7fecccc4ed14647..223cdcc8203f566483c15051c1ce5cfdfe608791 100644 (file)
@@ -58,9 +58,6 @@ static void __invalidate_dcache(unsigned long start, unsigned long end)
        end += (cpuinfo.dcache_line_size - 1);
        end &= ~(cpuinfo.dcache_line_size - 1);
 
-       if (end > start + cpuinfo.dcache_size)
-               end = start + cpuinfo.dcache_size;
-
        for (addr = start; addr < end; addr += cpuinfo.dcache_line_size) {
                __asm__ __volatile__ ("   initda 0(%0)\n"
                                        : /* Outputs */
@@ -131,12 +128,14 @@ void flush_cache_dup_mm(struct mm_struct *mm)
 
 void flush_icache_range(unsigned long start, unsigned long end)
 {
+       __flush_dcache(start, end);
        __flush_icache(start, end);
 }
 
 void flush_dcache_range(unsigned long start, unsigned long end)
 {
        __flush_dcache(start, end);
+       __flush_icache(start, end);
 }
 EXPORT_SYMBOL(flush_dcache_range);
 
@@ -159,6 +158,7 @@ void flush_icache_page(struct vm_area_struct *vma, struct page *page)
        unsigned long start = (unsigned long) page_address(page);
        unsigned long end = start + PAGE_SIZE;
 
+       __flush_dcache(start, end);
        __flush_icache(start, end);
 }
 
@@ -173,6 +173,18 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr,
                __flush_icache(start, end);
 }
 
+void __flush_dcache_page(struct address_space *mapping, struct page *page)
+{
+       /*
+        * Writeback any data associated with the kernel mapping of this
+        * page.  This ensures that data in the physical page is mutually
+        * coherent with the kernels mapping.
+        */
+       unsigned long start = (unsigned long)page_address(page);
+
+       __flush_dcache_all(start, start + PAGE_SIZE);
+}
+
 void flush_dcache_page(struct page *page)
 {
        struct address_space *mapping;
@@ -190,11 +202,12 @@ void flush_dcache_page(struct page *page)
        if (mapping && !mapping_mapped(mapping)) {
                clear_bit(PG_dcache_clean, &page->flags);
        } else {
-               unsigned long start = (unsigned long)page_address(page);
-
-               __flush_dcache_all(start, start + PAGE_SIZE);
-               if (mapping)
+               __flush_dcache_page(mapping, page);
+               if (mapping) {
+                       unsigned long start = (unsigned long)page_address(page);
                        flush_aliases(mapping,  page);
+                       flush_icache_range(start, start + PAGE_SIZE);
+               }
                set_bit(PG_dcache_clean, &page->flags);
        }
 }
@@ -205,6 +218,7 @@ void update_mmu_cache(struct vm_area_struct *vma,
 {
        unsigned long pfn = pte_pfn(*pte);
        struct page *page;
+       struct address_space *mapping;
 
        if (!pfn_valid(pfn))
                return;
@@ -217,16 +231,15 @@ void update_mmu_cache(struct vm_area_struct *vma,
        if (page == ZERO_PAGE(0))
                return;
 
-       if (!PageReserved(page) &&
-            !test_and_set_bit(PG_dcache_clean, &page->flags)) {
-               unsigned long start = page_to_virt(page);
-               struct address_space *mapping;
-
-               __flush_dcache(start, start + PAGE_SIZE);
-
-               mapping = page_mapping(page);
-               if (mapping)
-                       flush_aliases(mapping, page);
+       mapping = page_mapping(page);
+       if (!test_and_set_bit(PG_dcache_clean, &page->flags))
+               __flush_dcache_page(mapping, page);
+
+       if(mapping)
+       {
+               flush_aliases(mapping, page);
+               if (vma->vm_flags & VM_EXEC)
+                       flush_icache_page(vma, page);
        }
 }
 
@@ -234,15 +247,19 @@ void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
                    struct page *to)
 {
        __flush_dcache(vaddr, vaddr + PAGE_SIZE);
+       __flush_icache(vaddr, vaddr + PAGE_SIZE);
        copy_page(vto, vfrom);
        __flush_dcache((unsigned long)vto, (unsigned long)vto + PAGE_SIZE);
+       __flush_icache((unsigned long)vto, (unsigned long)vto + PAGE_SIZE);
 }
 
 void clear_user_page(void *addr, unsigned long vaddr, struct page *page)
 {
        __flush_dcache(vaddr, vaddr + PAGE_SIZE);
+       __flush_icache(vaddr, vaddr + PAGE_SIZE);
        clear_page(addr);
        __flush_dcache((unsigned long)addr, (unsigned long)addr + PAGE_SIZE);
+       __flush_icache((unsigned long)addr, (unsigned long)addr + PAGE_SIZE);
 }
 
 void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
@@ -251,7 +268,7 @@ void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
 {
        flush_cache_page(vma, user_vaddr, page_to_pfn(page));
        memcpy(dst, src, len);
-       __flush_dcache((unsigned long)src, (unsigned long)src + len);
+       __flush_dcache_all((unsigned long)src, (unsigned long)src + len);
        if (vma->vm_flags & VM_EXEC)
                __flush_icache((unsigned long)src, (unsigned long)src + len);
 }
@@ -262,7 +279,7 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
 {
        flush_cache_page(vma, user_vaddr, page_to_pfn(page));
        memcpy(dst, src, len);
-       __flush_dcache((unsigned long)dst, (unsigned long)dst + len);
+       __flush_dcache_all((unsigned long)dst, (unsigned long)dst + len);
        if (vma->vm_flags & VM_EXEC)
                __flush_icache((unsigned long)dst, (unsigned long)dst + len);
 }
index 12b341d04f88d09be325e318967f537153602d86..7a4bcc36303d08ac5831c1d344ce1039d41f3fc7 100644 (file)
@@ -20,6 +20,7 @@ generic-y += param.h
 generic-y += percpu.h
 generic-y += poll.h
 generic-y += preempt.h
+generic-y += scatterlist.h
 generic-y += seccomp.h
 generic-y += segment.h
 generic-y += topology.h
index 1ba29369257c1234585a23b8a290e9f788ab52ec..3a08eae3318fe8da341a563613ae16e82e64912b 100644 (file)
@@ -26,7 +26,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 
        if (likely(pgd != NULL)) {
                memset(pgd, 0, PAGE_SIZE<<PGD_ALLOC_ORDER);
-#if PT_NLEVELS == 3
+#if CONFIG_PGTABLE_LEVELS == 3
                actual_pgd += PTRS_PER_PGD;
                /* Populate first pmd with allocated memory.  We mark it
                 * with PxD_FLAG_ATTACHED as a signal to the system that this
@@ -45,7 +45,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 
 static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
 {
-#if PT_NLEVELS == 3
+#if CONFIG_PGTABLE_LEVELS == 3
        pgd -= PTRS_PER_PGD;
 #endif
        free_pages((unsigned long)pgd, PGD_ALLOC_ORDER);
@@ -102,7 +102,7 @@ static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
 static inline void
 pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *pte)
 {
-#if PT_NLEVELS == 3
+#if CONFIG_PGTABLE_LEVELS == 3
        /* preserve the gateway marker if this is the beginning of
         * the permanent pmd */
        if(pmd_flag(*pmd) & PxD_FLAG_ATTACHED)
diff --git a/arch/parisc/include/asm/scatterlist.h b/arch/parisc/include/asm/scatterlist.h
deleted file mode 100644 (file)
index 8bf1f0d..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _ASM_PARISC_SCATTERLIST_H
-#define _ASM_PARISC_SCATTERLIST_H
-
-#include <asm/page.h>
-#include <asm/types.h>
-#include <asm-generic/scatterlist.h>
-
-#define sg_virt_addr(sg) ((unsigned long)sg_virt(sg))
-
-#endif /* _ASM_PARISC_SCATTERLIST_H */
index d87d1c476d851c233b02580beaffbb25cc22eb1a..ff834fd67478acce421a2b6c6be35585de35aacb 100644 (file)
@@ -482,7 +482,7 @@ static int pa11_dma_map_sg(struct device *dev, struct scatterlist *sglist, int n
        BUG_ON(direction == DMA_NONE);
 
        for (i = 0; i < nents; i++, sglist++ ) {
-               unsigned long vaddr = sg_virt_addr(sglist);
+               unsigned long vaddr = (unsigned long)sg_virt(sglist);
                sg_dma_address(sglist) = (dma_addr_t) virt_to_phys(vaddr);
                sg_dma_len(sglist) = sglist->length;
                flush_kernel_dcache_range(vaddr, sglist->length);
@@ -502,7 +502,7 @@ static void pa11_dma_unmap_sg(struct device *dev, struct scatterlist *sglist, in
        /* once we do combining we'll need to use phys_to_virt(sg_dma_address(sglist)) */
 
        for (i = 0; i < nents; i++, sglist++ )
-               flush_kernel_dcache_range(sg_virt_addr(sglist), sglist->length);
+               flush_kernel_vmap_range(sg_virt(sglist), sglist->length);
        return;
 }
 
@@ -527,7 +527,7 @@ static void pa11_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sgl
        /* once we do combining we'll need to use phys_to_virt(sg_dma_address(sglist)) */
 
        for (i = 0; i < nents; i++, sglist++ )
-               flush_kernel_dcache_range(sg_virt_addr(sglist), sglist->length);
+               flush_kernel_vmap_range(sg_virt(sglist), sglist->length);
 }
 
 static void pa11_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sglist, int nents, enum dma_data_direction direction)
@@ -537,7 +537,7 @@ static void pa11_dma_sync_sg_for_device(struct device *dev, struct scatterlist *
        /* once we do combining we'll need to use phys_to_virt(sg_dma_address(sglist)) */
 
        for (i = 0; i < nents; i++, sglist++ )
-               flush_kernel_dcache_range(sg_virt_addr(sglist), sglist->length);
+               flush_kernel_vmap_range(sg_virt(sglist), sglist->length);
 }
 
 struct hppa_dma_ops pcxl_dma_ops = {
index bde5311036384c891463de556bb75e62b6d39a7c..0cc6eedc4780325fbf4241738f4694c84d5248b9 100644 (file)
@@ -30,8 +30,6 @@ static inline int arch_has_random(void)
        return !!ppc_md.get_random_long;
 }
 
-int powernv_get_random_long(unsigned long *v);
-
 static inline int arch_get_random_seed_long(unsigned long *v)
 {
        return 0;
@@ -47,4 +45,13 @@ static inline int arch_has_random_seed(void)
 
 #endif /* CONFIG_ARCH_RANDOM */
 
+#ifdef CONFIG_PPC_POWERNV
+int powernv_hwrng_present(void);
+int powernv_get_random_long(unsigned long *v);
+int powernv_get_random_real_mode(unsigned long *v);
+#else
+static inline int powernv_hwrng_present(void) { return 0; }
+static inline int powernv_get_random_real_mode(unsigned long *v) { return 0; }
+#endif
+
 #endif /* _ASM_POWERPC_ARCHRANDOM_H */
index 993090422690c748eeb9f272918724d0bc164e9f..b91e74a817d89742355e547c61b9ce36a243f11b 100644 (file)
@@ -288,6 +288,9 @@ static inline bool kvmppc_supports_magic_page(struct kvm_vcpu *vcpu)
        return !is_kvmppc_hv_enabled(vcpu->kvm);
 }
 
+extern int kvmppc_h_logical_ci_load(struct kvm_vcpu *vcpu);
+extern int kvmppc_h_logical_ci_store(struct kvm_vcpu *vcpu);
+
 /* Magic register values loaded into r3 and r4 before the 'sc' assembly
  * instruction for the OSI hypercalls */
 #define OSI_SC_MAGIC_R3                        0x113724FA
index 14619a59ec09b9ad93840803b9ff73e6b94ba53d..3536d12eb79831811670e6212a97ecb4d3e76178 100644 (file)
@@ -85,6 +85,20 @@ static inline long try_lock_hpte(__be64 *hpte, unsigned long bits)
        return old == 0;
 }
 
+static inline void unlock_hpte(__be64 *hpte, unsigned long hpte_v)
+{
+       hpte_v &= ~HPTE_V_HVLOCK;
+       asm volatile(PPC_RELEASE_BARRIER "" : : : "memory");
+       hpte[0] = cpu_to_be64(hpte_v);
+}
+
+/* Without barrier */
+static inline void __unlock_hpte(__be64 *hpte, unsigned long hpte_v)
+{
+       hpte_v &= ~HPTE_V_HVLOCK;
+       hpte[0] = cpu_to_be64(hpte_v);
+}
+
 static inline int __hpte_actual_psize(unsigned int lp, int psize)
 {
        int i, shift;
@@ -281,16 +295,17 @@ static inline int hpte_cache_flags_ok(unsigned long ptel, unsigned long io_type)
 
 /*
  * If it's present and writable, atomically set dirty and referenced bits and
- * return the PTE, otherwise return 0. If we find a transparent hugepage
- * and if it is marked splitting we return 0;
+ * return the PTE, otherwise return 0.
  */
-static inline pte_t kvmppc_read_update_linux_pte(pte_t *ptep, int writing,
-                                                unsigned int hugepage)
+static inline pte_t kvmppc_read_update_linux_pte(pte_t *ptep, int writing)
 {
        pte_t old_pte, new_pte = __pte(0);
 
        while (1) {
-               old_pte = *ptep;
+               /*
+                * Make sure we don't reload from ptep
+                */
+               old_pte = READ_ONCE(*ptep);
                /*
                 * wait until _PAGE_BUSY is clear then set it atomically
                 */
@@ -298,12 +313,6 @@ static inline pte_t kvmppc_read_update_linux_pte(pte_t *ptep, int writing,
                        cpu_relax();
                        continue;
                }
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
-               /* If hugepage and is trans splitting return None */
-               if (unlikely(hugepage &&
-                            pmd_trans_splitting(pte_pmd(old_pte))))
-                       return __pte(0);
-#endif
                /* If pte is not present return None */
                if (unlikely(!(pte_val(old_pte) & _PAGE_PRESENT)))
                        return __pte(0);
@@ -424,6 +433,10 @@ static inline struct kvm_memslots *kvm_memslots_raw(struct kvm *kvm)
        return rcu_dereference_raw_notrace(kvm->memslots);
 }
 
+extern void kvmppc_mmu_debugfs_init(struct kvm *kvm);
+
+extern void kvmhv_rm_send_ipi(int cpu);
+
 #endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */
 
 #endif /* __ASM_KVM_BOOK3S_64_H__ */
index c610961720c72aa075ee808f3f49044bb3664e5b..a193a13cf08bf1dd40a51e393aeeab4456ce42b0 100644 (file)
@@ -227,10 +227,8 @@ struct kvm_arch {
        unsigned long host_sdr1;
        int tlbie_lock;
        unsigned long lpcr;
-       unsigned long rmor;
-       struct kvm_rma_info *rma;
        unsigned long vrma_slb_v;
-       int rma_setup_done;
+       int hpte_setup_done;
        u32 hpt_order;
        atomic_t vcpus_running;
        u32 online_vcores;
@@ -239,6 +237,8 @@ struct kvm_arch {
        atomic_t hpte_mod_interest;
        cpumask_t need_tlb_flush;
        int hpt_cma_alloc;
+       struct dentry *debugfs_dir;
+       struct dentry *htab_dentry;
 #endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */
 #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
        struct mutex hpt_mutex;
@@ -263,18 +263,15 @@ struct kvm_arch {
 
 /*
  * Struct for a virtual core.
- * Note: entry_exit_count combines an entry count in the bottom 8 bits
- * and an exit count in the next 8 bits.  This is so that we can
- * atomically increment the entry count iff the exit count is 0
- * without taking the lock.
+ * Note: entry_exit_map combines a bitmap of threads that have entered
+ * in the bottom 8 bits and a bitmap of threads that have exited in the
+ * next 8 bits.  This is so that we can atomically set the entry bit
+ * iff the exit map is 0 without taking a lock.
  */
 struct kvmppc_vcore {
        int n_runnable;
-       int n_busy;
        int num_threads;
-       int entry_exit_count;
-       int n_woken;
-       int nap_count;
+       int entry_exit_map;
        int napping_threads;
        int first_vcpuid;
        u16 pcpu;
@@ -299,13 +296,14 @@ struct kvmppc_vcore {
        ulong conferring_threads;
 };
 
-#define VCORE_ENTRY_COUNT(vc)  ((vc)->entry_exit_count & 0xff)
-#define VCORE_EXIT_COUNT(vc)   ((vc)->entry_exit_count >> 8)
+#define VCORE_ENTRY_MAP(vc)    ((vc)->entry_exit_map & 0xff)
+#define VCORE_EXIT_MAP(vc)     ((vc)->entry_exit_map >> 8)
+#define VCORE_IS_EXITING(vc)   (VCORE_EXIT_MAP(vc) != 0)
 
 /* Values for vcore_state */
 #define VCORE_INACTIVE 0
 #define VCORE_SLEEPING 1
-#define VCORE_STARTING 2
+#define VCORE_PREEMPT  2
 #define VCORE_RUNNING  3
 #define VCORE_EXITING  4
 
@@ -368,6 +366,14 @@ struct kvmppc_slb {
        u8 base_page_size;      /* MMU_PAGE_xxx */
 };
 
+/* Struct used to accumulate timing information in HV real mode code */
+struct kvmhv_tb_accumulator {
+       u64     seqcount;       /* used to synchronize access, also count * 2 */
+       u64     tb_total;       /* total time in timebase ticks */
+       u64     tb_min;         /* min time */
+       u64     tb_max;         /* max time */
+};
+
 # ifdef CONFIG_PPC_FSL_BOOK3E
 #define KVMPPC_BOOKE_IAC_NUM   2
 #define KVMPPC_BOOKE_DAC_NUM   2
@@ -656,6 +662,19 @@ struct kvm_vcpu_arch {
 
        u32 emul_inst;
 #endif
+
+#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
+       struct kvmhv_tb_accumulator *cur_activity;      /* What we're timing */
+       u64     cur_tb_start;                   /* when it started */
+       struct kvmhv_tb_accumulator rm_entry;   /* real-mode entry code */
+       struct kvmhv_tb_accumulator rm_intr;    /* real-mode intr handling */
+       struct kvmhv_tb_accumulator rm_exit;    /* real-mode exit code */
+       struct kvmhv_tb_accumulator guest_time; /* guest execution */
+       struct kvmhv_tb_accumulator cede_time;  /* time napping inside guest */
+
+       struct dentry *debugfs_dir;
+       struct dentry *debugfs_timings;
+#endif /* CONFIG_KVM_BOOK3S_HV_EXIT_TIMING */
 };
 
 #define VCPU_FPR(vcpu, i)      (vcpu)->arch.fp.fpr[i][TS_FPROFFSET]
index 46bf652c91697c384e8a5323ad5ed428014f9980..b8475daad88471006369ad99c25d6c51efbe7501 100644 (file)
@@ -302,6 +302,8 @@ static inline bool is_kvmppc_hv_enabled(struct kvm *kvm)
        return kvm->arch.kvm_ops == kvmppc_hv_ops;
 }
 
+extern int kvmppc_hwrng_present(void);
+
 /*
  * Cuts out inst bits with ordering according to spec.
  * That means the leftmost bit is zero. All given bits are included.
index 9835ac4173b75c2c3db2ec14e062516a117c27bf..11a38635dd658b1e94e9dffeeda8d080b6b713d8 100644 (file)
@@ -247,28 +247,16 @@ extern int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long addr,
 #define pmd_large(pmd)         0
 #define has_transparent_hugepage() 0
 #endif
-pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea,
+pte_t *__find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea,
                                 unsigned *shift);
-
-static inline pte_t *lookup_linux_ptep(pgd_t *pgdir, unsigned long hva,
-                                    unsigned long *pte_sizep)
+static inline pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea,
+                                              unsigned *shift)
 {
-       pte_t *ptep;
-       unsigned long ps = *pte_sizep;
-       unsigned int shift;
-
-       ptep = find_linux_pte_or_hugepte(pgdir, hva, &shift);
-       if (!ptep)
-               return NULL;
-       if (shift)
-               *pte_sizep = 1ul << shift;
-       else
-               *pte_sizep = PAGE_SIZE;
-
-       if (ps > *pte_sizep)
-               return NULL;
-
-       return ptep;
+       if (!arch_irqs_disabled()) {
+               pr_info("%s called with irq enabled\n", __func__);
+               dump_stack();
+       }
+       return __find_linux_pte_or_hugepte(pgdir, ea, shift);
 }
 #endif /* __ASSEMBLY__ */
 
index 03cbada59d3afaff427ca59dab3475426ef16304..10fc784a2ad4cbf687ce28b1d2bc2d6c06fed5b4 100644 (file)
@@ -211,5 +211,8 @@ extern void secondary_cpu_time_init(void);
 
 DECLARE_PER_CPU(u64, decrementers_next_tb);
 
+/* Convert timebase ticks to nanoseconds */
+unsigned long long tb_to_ns(unsigned long long tb_ticks);
+
 #endif /* __KERNEL__ */
 #endif /* __POWERPC_TIME_H */
index 5047659815a54ffd69037b245eebd9f6c64a679d..5d836b7c1176242ae2c943c0bcc81cf6bcb031cf 100644 (file)
@@ -11,7 +11,7 @@
 #define TM_CAUSE_RESCHED       0xde
 #define TM_CAUSE_TLBI          0xdc
 #define TM_CAUSE_FAC_UNAV      0xda
-#define TM_CAUSE_SYSCALL       0xd8
+#define TM_CAUSE_SYSCALL       0xd8  /* future use */
 #define TM_CAUSE_MISC          0xd6  /* future use */
 #define TM_CAUSE_SIGNAL                0xd4
 #define TM_CAUSE_ALIGNMENT     0xd2
index 4717859fdd04401e4b17bf0c1d0b98c7390c4957..0034b6b3556a4f6b571ec60fdd55c02535c6ea97 100644 (file)
@@ -37,6 +37,7 @@
 #include <asm/thread_info.h>
 #include <asm/rtas.h>
 #include <asm/vdso_datapage.h>
+#include <asm/dbell.h>
 #ifdef CONFIG_PPC64
 #include <asm/paca.h>
 #include <asm/lppaca.h>
@@ -458,6 +459,19 @@ int main(void)
        DEFINE(VCPU_SPRG1, offsetof(struct kvm_vcpu, arch.shregs.sprg1));
        DEFINE(VCPU_SPRG2, offsetof(struct kvm_vcpu, arch.shregs.sprg2));
        DEFINE(VCPU_SPRG3, offsetof(struct kvm_vcpu, arch.shregs.sprg3));
+#endif
+#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
+       DEFINE(VCPU_TB_RMENTRY, offsetof(struct kvm_vcpu, arch.rm_entry));
+       DEFINE(VCPU_TB_RMINTR, offsetof(struct kvm_vcpu, arch.rm_intr));
+       DEFINE(VCPU_TB_RMEXIT, offsetof(struct kvm_vcpu, arch.rm_exit));
+       DEFINE(VCPU_TB_GUEST, offsetof(struct kvm_vcpu, arch.guest_time));
+       DEFINE(VCPU_TB_CEDE, offsetof(struct kvm_vcpu, arch.cede_time));
+       DEFINE(VCPU_CUR_ACTIVITY, offsetof(struct kvm_vcpu, arch.cur_activity));
+       DEFINE(VCPU_ACTIVITY_START, offsetof(struct kvm_vcpu, arch.cur_tb_start));
+       DEFINE(TAS_SEQCOUNT, offsetof(struct kvmhv_tb_accumulator, seqcount));
+       DEFINE(TAS_TOTAL, offsetof(struct kvmhv_tb_accumulator, tb_total));
+       DEFINE(TAS_MIN, offsetof(struct kvmhv_tb_accumulator, tb_min));
+       DEFINE(TAS_MAX, offsetof(struct kvmhv_tb_accumulator, tb_max));
 #endif
        DEFINE(VCPU_SHARED_SPRG3, offsetof(struct kvm_vcpu_arch_shared, sprg3));
        DEFINE(VCPU_SHARED_SPRG4, offsetof(struct kvm_vcpu_arch_shared, sprg4));
@@ -492,7 +506,6 @@ int main(void)
        DEFINE(KVM_NEED_FLUSH, offsetof(struct kvm, arch.need_tlb_flush.bits));
        DEFINE(KVM_ENABLED_HCALLS, offsetof(struct kvm, arch.enabled_hcalls));
        DEFINE(KVM_LPCR, offsetof(struct kvm, arch.lpcr));
-       DEFINE(KVM_RMOR, offsetof(struct kvm, arch.rmor));
        DEFINE(KVM_VRMA_SLB_V, offsetof(struct kvm, arch.vrma_slb_v));
        DEFINE(VCPU_DSISR, offsetof(struct kvm_vcpu, arch.shregs.dsisr));
        DEFINE(VCPU_DAR, offsetof(struct kvm_vcpu, arch.shregs.dar));
@@ -550,8 +563,7 @@ int main(void)
        DEFINE(VCPU_ACOP, offsetof(struct kvm_vcpu, arch.acop));
        DEFINE(VCPU_WORT, offsetof(struct kvm_vcpu, arch.wort));
        DEFINE(VCPU_SHADOW_SRR1, offsetof(struct kvm_vcpu, arch.shadow_srr1));
-       DEFINE(VCORE_ENTRY_EXIT, offsetof(struct kvmppc_vcore, entry_exit_count));
-       DEFINE(VCORE_NAP_COUNT, offsetof(struct kvmppc_vcore, nap_count));
+       DEFINE(VCORE_ENTRY_EXIT, offsetof(struct kvmppc_vcore, entry_exit_map));
        DEFINE(VCORE_IN_GUEST, offsetof(struct kvmppc_vcore, in_guest));
        DEFINE(VCORE_NAPPING_THREADS, offsetof(struct kvmppc_vcore, napping_threads));
        DEFINE(VCORE_KVM, offsetof(struct kvmppc_vcore, kvm));
@@ -748,5 +760,7 @@ int main(void)
                        offsetof(struct paca_struct, subcore_sibling_mask));
 #endif
 
+       DEFINE(PPC_DBELL_SERVER, PPC_DBELL_SERVER);
+
        return 0;
 }
index a4c62eb0ee48c8f5ca9c64f9c64dc780df6e1b3a..9ee61d15653d6ec46546b93ea72601072176e4b7 100644 (file)
@@ -334,9 +334,11 @@ static inline unsigned long eeh_token_to_phys(unsigned long token)
        int hugepage_shift;
 
        /*
-        * We won't find hugepages here, iomem
+        * We won't find hugepages here(this is iomem). Hence we are not
+        * worried about _PAGE_SPLITTING/collapse. Also we will not hit
+        * page table free, because of init_mm.
         */
-       ptep = find_linux_pte_or_hugepte(init_mm.pgd, token, &hugepage_shift);
+       ptep = __find_linux_pte_or_hugepte(init_mm.pgd, token, &hugepage_shift);
        if (!ptep)
                return token;
        WARN_ON(hugepage_shift);
@@ -747,21 +749,24 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state stat
                eeh_unfreeze_pe(pe, false);
                eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED);
                eeh_pe_dev_traverse(pe, eeh_restore_dev_state, dev);
+               eeh_pe_state_clear(pe, EEH_PE_ISOLATED);
                break;
        case pcie_hot_reset:
+               eeh_pe_state_mark(pe, EEH_PE_ISOLATED);
                eeh_ops->set_option(pe, EEH_OPT_FREEZE_PE);
                eeh_pe_dev_traverse(pe, eeh_disable_and_save_dev_state, dev);
                eeh_pe_state_mark(pe, EEH_PE_CFG_BLOCKED);
                eeh_ops->reset(pe, EEH_RESET_HOT);
                break;
        case pcie_warm_reset:
+               eeh_pe_state_mark(pe, EEH_PE_ISOLATED);
                eeh_ops->set_option(pe, EEH_OPT_FREEZE_PE);
                eeh_pe_dev_traverse(pe, eeh_disable_and_save_dev_state, dev);
                eeh_pe_state_mark(pe, EEH_PE_CFG_BLOCKED);
                eeh_ops->reset(pe, EEH_RESET_FUNDAMENTAL);
                break;
        default:
-               eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED);
+               eeh_pe_state_clear(pe, EEH_PE_ISOLATED | EEH_PE_CFG_BLOCKED);
                return -EINVAL;
        };
 
@@ -1056,6 +1061,9 @@ void eeh_add_device_early(struct pci_dn *pdn)
        if (!edev || !eeh_enabled())
                return;
 
+       if (!eeh_has_flag(EEH_PROBE_MODE_DEVTREE))
+               return;
+
        /* USB Bus children of PCI devices will not have BUID's */
        phb = edev->phb;
        if (NULL == phb ||
@@ -1110,6 +1118,9 @@ void eeh_add_device_late(struct pci_dev *dev)
                return;
        }
 
+       if (eeh_has_flag(EEH_PROBE_MODE_DEV))
+               eeh_ops->probe(pdn, NULL);
+
        /*
         * The EEH cache might not be removed correctly because of
         * unbalanced kref to the device during unplug time, which
index 8ca9434c40e6a705e1eccb8e8ddcca727bf68044..afbc20019c2efba2b81b7cd6298941753d9776b5 100644 (file)
@@ -34,7 +34,6 @@
 #include <asm/ftrace.h>
 #include <asm/hw_irq.h>
 #include <asm/context_tracking.h>
-#include <asm/tm.h>
 
 /*
  * System calls.
@@ -146,24 +145,6 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)
        andi.   r11,r10,_TIF_SYSCALL_DOTRACE
        bne     syscall_dotrace
 .Lsyscall_dotrace_cont:
-#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
-BEGIN_FTR_SECTION
-       b       1f
-END_FTR_SECTION_IFCLR(CPU_FTR_TM)
-       extrdi. r11, r12, 1, (63-MSR_TS_T_LG) /* transaction active? */
-       beq+    1f
-
-       /* Doom the transaction and don't perform the syscall: */
-       mfmsr   r11
-       li      r12, 1
-       rldimi  r11, r12, MSR_TM_LG, 63-MSR_TM_LG
-       mtmsrd  r11, 0
-       li      r11, (TM_CAUSE_SYSCALL|TM_CAUSE_PERSISTENT)
-       TABORT(R11)
-
-       b       .Lsyscall_exit
-1:
-#endif
        cmpldi  0,r0,NR_syscalls
        bge-    syscall_enosys
 
index eeaa0d5f69d5e60271ccca1790aaf98559ca92fa..ccde8f084ce426ab382964ec5e2eba389317be44 100644 (file)
@@ -501,9 +501,11 @@ BEGIN_FTR_SECTION
        CHECK_HMI_INTERRUPT
 END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
        ld      r1,PACAR1(r13)
+       ld      r6,_CCR(r1)
        ld      r4,_MSR(r1)
        ld      r5,_NIP(r1)
        addi    r1,r1,INT_FRAME_SIZE
+       mtcr    r6
        mtspr   SPRN_SRR1,r4
        mtspr   SPRN_SRR0,r5
        rfid
index 24b968f8e4d83fdb61349ec1067d18583953613f..63d9cc4d7366adfa674b2ff7917d698c6ff2a380 100644 (file)
@@ -71,15 +71,15 @@ struct iowa_bus *iowa_mem_find_bus(const PCI_IO_ADDR addr)
                vaddr = (unsigned long)PCI_FIX_ADDR(addr);
                if (vaddr < PHB_IO_BASE || vaddr >= PHB_IO_END)
                        return NULL;
-
-               ptep = find_linux_pte_or_hugepte(init_mm.pgd, vaddr,
+               /*
+                * We won't find huge pages here (iomem). Also can't hit
+                * a page table free due to init_mm
+                */
+               ptep = __find_linux_pte_or_hugepte(init_mm.pgd, vaddr,
                                                 &hugepage_shift);
                if (ptep == NULL)
                        paddr = 0;
                else {
-                       /*
-                        * we don't have hugepages backing iomem
-                        */
                        WARN_ON(hugepage_shift);
                        paddr = pte_pfn(*ptep) << PAGE_SHIFT;
                }
index 2d7b33fab953283cf391679b1e316e81f53852f9..56f44848b044b67c7d3b84caf82a9a9ed6fb493a 100644 (file)
@@ -608,6 +608,12 @@ void arch_suspend_enable_irqs(void)
 }
 #endif
 
+unsigned long long tb_to_ns(unsigned long long ticks)
+{
+       return mulhdu(ticks, tb_to_ns_scale) << tb_to_ns_shift;
+}
+EXPORT_SYMBOL_GPL(tb_to_ns);
+
 /*
  * Scheduler clock - returns current time in nanosec units.
  *
index 11850f310fb41fb50c639e558da1921a167af7ac..3caec2c421058b0065e9d0cfd382e23e9d7102a6 100644 (file)
@@ -75,7 +75,7 @@ config KVM_BOOK3S_64
 
 config KVM_BOOK3S_64_HV
        tristate "KVM support for POWER7 and PPC970 using hypervisor mode in host"
-       depends on KVM_BOOK3S_64
+       depends on KVM_BOOK3S_64 && PPC_POWERNV
        select KVM_BOOK3S_HV_POSSIBLE
        select MMU_NOTIFIER
        select CMA
@@ -110,6 +110,20 @@ config KVM_BOOK3S_64_PR
          processor, including emulating 32-bit processors on a 64-bit
          host.
 
+config KVM_BOOK3S_HV_EXIT_TIMING
+       bool "Detailed timing for hypervisor real-mode code"
+       depends on KVM_BOOK3S_HV_POSSIBLE && DEBUG_FS
+       ---help---
+         Calculate time taken for each vcpu in the real-mode guest entry,
+         exit, and interrupt handling code, plus time spent in the guest
+         and in nap mode due to idle (cede) while other threads are still
+         in the guest.  The total, minimum and maximum times in nanoseconds
+         together with the number of executions are reported in debugfs in
+         kvm/vm#/vcpu#/timings.  The overhead is of the order of 30 - 40
+         ns per exit on POWER8.
+
+         If unsure, say N.
+
 config KVM_BOOKE_HV
        bool
 
index cfbcdc65420195c566c9541a38d9fc8aed0b80d9..453a8a47a4676c72333643305ef0770f188a555e 100644 (file)
@@ -821,6 +821,82 @@ void kvmppc_core_destroy_vm(struct kvm *kvm)
 #endif
 }
 
+int kvmppc_h_logical_ci_load(struct kvm_vcpu *vcpu)
+{
+       unsigned long size = kvmppc_get_gpr(vcpu, 4);
+       unsigned long addr = kvmppc_get_gpr(vcpu, 5);
+       u64 buf;
+       int ret;
+
+       if (!is_power_of_2(size) || (size > sizeof(buf)))
+               return H_TOO_HARD;
+
+       ret = kvm_io_bus_read(vcpu, KVM_MMIO_BUS, addr, size, &buf);
+       if (ret != 0)
+               return H_TOO_HARD;
+
+       switch (size) {
+       case 1:
+               kvmppc_set_gpr(vcpu, 4, *(u8 *)&buf);
+               break;
+
+       case 2:
+               kvmppc_set_gpr(vcpu, 4, be16_to_cpu(*(__be16 *)&buf));
+               break;
+
+       case 4:
+               kvmppc_set_gpr(vcpu, 4, be32_to_cpu(*(__be32 *)&buf));
+               break;
+
+       case 8:
+               kvmppc_set_gpr(vcpu, 4, be64_to_cpu(*(__be64 *)&buf));
+               break;
+
+       default:
+               BUG();
+       }
+
+       return H_SUCCESS;
+}
+EXPORT_SYMBOL_GPL(kvmppc_h_logical_ci_load);
+
+int kvmppc_h_logical_ci_store(struct kvm_vcpu *vcpu)
+{
+       unsigned long size = kvmppc_get_gpr(vcpu, 4);
+       unsigned long addr = kvmppc_get_gpr(vcpu, 5);
+       unsigned long val = kvmppc_get_gpr(vcpu, 6);
+       u64 buf;
+       int ret;
+
+       switch (size) {
+       case 1:
+               *(u8 *)&buf = val;
+               break;
+
+       case 2:
+               *(__be16 *)&buf = cpu_to_be16(val);
+               break;
+
+       case 4:
+               *(__be32 *)&buf = cpu_to_be32(val);
+               break;
+
+       case 8:
+               *(__be64 *)&buf = cpu_to_be64(val);
+               break;
+
+       default:
+               return H_TOO_HARD;
+       }
+
+       ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, addr, size, &buf);
+       if (ret != 0)
+               return H_TOO_HARD;
+
+       return H_SUCCESS;
+}
+EXPORT_SYMBOL_GPL(kvmppc_h_logical_ci_store);
+
 int kvmppc_core_check_processor_compat(void)
 {
        /*
index 534acb3c6c3df87e2ff2a063fa1dfd6b795cf4a8..1a4acf8bf4f4b7a790c16dc0286c4c8bc9380edf 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/srcu.h>
 #include <linux/anon_inodes.h>
 #include <linux/file.h>
+#include <linux/debugfs.h>
 
 #include <asm/tlbflush.h>
 #include <asm/kvm_ppc.h>
@@ -116,12 +117,12 @@ long kvmppc_alloc_reset_hpt(struct kvm *kvm, u32 *htab_orderp)
        long order;
 
        mutex_lock(&kvm->lock);
-       if (kvm->arch.rma_setup_done) {
-               kvm->arch.rma_setup_done = 0;
-               /* order rma_setup_done vs. vcpus_running */
+       if (kvm->arch.hpte_setup_done) {
+               kvm->arch.hpte_setup_done = 0;
+               /* order hpte_setup_done vs. vcpus_running */
                smp_mb();
                if (atomic_read(&kvm->arch.vcpus_running)) {
-                       kvm->arch.rma_setup_done = 1;
+                       kvm->arch.hpte_setup_done = 1;
                        goto out;
                }
        }
@@ -338,9 +339,7 @@ static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
        v = be64_to_cpu(hptep[0]) & ~HPTE_V_HVLOCK;
        gr = kvm->arch.revmap[index].guest_rpte;
 
-       /* Unlock the HPTE */
-       asm volatile("lwsync" : : : "memory");
-       hptep[0] = cpu_to_be64(v);
+       unlock_hpte(hptep, v);
        preempt_enable();
 
        gpte->eaddr = eaddr;
@@ -469,8 +468,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
        hpte[0] = be64_to_cpu(hptep[0]) & ~HPTE_V_HVLOCK;
        hpte[1] = be64_to_cpu(hptep[1]);
        hpte[2] = r = rev->guest_rpte;
-       asm volatile("lwsync" : : : "memory");
-       hptep[0] = cpu_to_be64(hpte[0]);
+       unlock_hpte(hptep, hpte[0]);
        preempt_enable();
 
        if (hpte[0] != vcpu->arch.pgfault_hpte[0] ||
@@ -537,23 +535,21 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
                }
                /* if the guest wants write access, see if that is OK */
                if (!writing && hpte_is_writable(r)) {
-                       unsigned int hugepage_shift;
                        pte_t *ptep, pte;
-
+                       unsigned long flags;
                        /*
                         * We need to protect against page table destruction
-                        * while looking up and updating the pte.
+                        * hugepage split and collapse.
                         */
-                       rcu_read_lock_sched();
+                       local_irq_save(flags);
                        ptep = find_linux_pte_or_hugepte(current->mm->pgd,
-                                                        hva, &hugepage_shift);
+                                                        hva, NULL);
                        if (ptep) {
-                               pte = kvmppc_read_update_linux_pte(ptep, 1,
-                                                          hugepage_shift);
+                               pte = kvmppc_read_update_linux_pte(ptep, 1);
                                if (pte_write(pte))
                                        write_ok = 1;
                        }
-                       rcu_read_unlock_sched();
+                       local_irq_restore(flags);
                }
        }
 
@@ -621,7 +617,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
 
        hptep[1] = cpu_to_be64(r);
        eieio();
-       hptep[0] = cpu_to_be64(hpte[0]);
+       __unlock_hpte(hptep, hpte[0]);
        asm volatile("ptesync" : : : "memory");
        preempt_enable();
        if (page && hpte_is_writable(r))
@@ -642,7 +638,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
        return ret;
 
  out_unlock:
-       hptep[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
+       __unlock_hpte(hptep, be64_to_cpu(hptep[0]));
        preempt_enable();
        goto out_put;
 }
@@ -771,7 +767,7 @@ static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp,
                        }
                }
                unlock_rmap(rmapp);
-               hptep[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
+               __unlock_hpte(hptep, be64_to_cpu(hptep[0]));
        }
        return 0;
 }
@@ -857,7 +853,7 @@ static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
                        }
                        ret = 1;
                }
-               hptep[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
+               __unlock_hpte(hptep, be64_to_cpu(hptep[0]));
        } while ((i = j) != head);
 
        unlock_rmap(rmapp);
@@ -974,8 +970,7 @@ static int kvm_test_clear_dirty_npages(struct kvm *kvm, unsigned long *rmapp)
 
                /* Now check and modify the HPTE */
                if (!(hptep[0] & cpu_to_be64(HPTE_V_VALID))) {
-                       /* unlock and continue */
-                       hptep[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
+                       __unlock_hpte(hptep, be64_to_cpu(hptep[0]));
                        continue;
                }
 
@@ -996,9 +991,9 @@ static int kvm_test_clear_dirty_npages(struct kvm *kvm, unsigned long *rmapp)
                                npages_dirty = n;
                        eieio();
                }
-               v &= ~(HPTE_V_ABSENT | HPTE_V_HVLOCK);
+               v &= ~HPTE_V_ABSENT;
                v |= HPTE_V_VALID;
-               hptep[0] = cpu_to_be64(v);
+               __unlock_hpte(hptep, v);
        } while ((i = j) != head);
 
        unlock_rmap(rmapp);
@@ -1218,8 +1213,7 @@ static long record_hpte(unsigned long flags, __be64 *hptp,
                        r &= ~HPTE_GR_MODIFIED;
                        revp->guest_rpte = r;
                }
-               asm volatile(PPC_RELEASE_BARRIER "" : : : "memory");
-               hptp[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
+               unlock_hpte(hptp, be64_to_cpu(hptp[0]));
                preempt_enable();
                if (!(valid == want_valid && (first_pass || dirty)))
                        ok = 0;
@@ -1339,20 +1333,20 @@ static ssize_t kvm_htab_write(struct file *file, const char __user *buf,
        unsigned long tmp[2];
        ssize_t nb;
        long int err, ret;
-       int rma_setup;
+       int hpte_setup;
 
        if (!access_ok(VERIFY_READ, buf, count))
                return -EFAULT;
 
        /* lock out vcpus from running while we're doing this */
        mutex_lock(&kvm->lock);
-       rma_setup = kvm->arch.rma_setup_done;
-       if (rma_setup) {
-               kvm->arch.rma_setup_done = 0;   /* temporarily */
-               /* order rma_setup_done vs. vcpus_running */
+       hpte_setup = kvm->arch.hpte_setup_done;
+       if (hpte_setup) {
+               kvm->arch.hpte_setup_done = 0;  /* temporarily */
+               /* order hpte_setup_done vs. vcpus_running */
                smp_mb();
                if (atomic_read(&kvm->arch.vcpus_running)) {
-                       kvm->arch.rma_setup_done = 1;
+                       kvm->arch.hpte_setup_done = 1;
                        mutex_unlock(&kvm->lock);
                        return -EBUSY;
                }
@@ -1405,7 +1399,7 @@ static ssize_t kvm_htab_write(struct file *file, const char __user *buf,
                                       "r=%lx\n", ret, i, v, r);
                                goto out;
                        }
-                       if (!rma_setup && is_vrma_hpte(v)) {
+                       if (!hpte_setup && is_vrma_hpte(v)) {
                                unsigned long psize = hpte_base_page_size(v, r);
                                unsigned long senc = slb_pgsize_encoding(psize);
                                unsigned long lpcr;
@@ -1414,7 +1408,7 @@ static ssize_t kvm_htab_write(struct file *file, const char __user *buf,
                                        (VRMA_VSID << SLB_VSID_SHIFT_1T);
                                lpcr = senc << (LPCR_VRMASD_SH - 4);
                                kvmppc_update_lpcr(kvm, lpcr, LPCR_VRMASD);
-                               rma_setup = 1;
+                               hpte_setup = 1;
                        }
                        ++i;
                        hptp += 2;
@@ -1430,9 +1424,9 @@ static ssize_t kvm_htab_write(struct file *file, const char __user *buf,
        }
 
  out:
-       /* Order HPTE updates vs. rma_setup_done */
+       /* Order HPTE updates vs. hpte_setup_done */
        smp_wmb();
-       kvm->arch.rma_setup_done = rma_setup;
+       kvm->arch.hpte_setup_done = hpte_setup;
        mutex_unlock(&kvm->lock);
 
        if (err)
@@ -1495,6 +1489,141 @@ int kvm_vm_ioctl_get_htab_fd(struct kvm *kvm, struct kvm_get_htab_fd *ghf)
        return ret;
 }
 
+struct debugfs_htab_state {
+       struct kvm      *kvm;
+       struct mutex    mutex;
+       unsigned long   hpt_index;
+       int             chars_left;
+       int             buf_index;
+       char            buf[64];
+};
+
+static int debugfs_htab_open(struct inode *inode, struct file *file)
+{
+       struct kvm *kvm = inode->i_private;
+       struct debugfs_htab_state *p;
+
+       p = kzalloc(sizeof(*p), GFP_KERNEL);
+       if (!p)
+               return -ENOMEM;
+
+       kvm_get_kvm(kvm);
+       p->kvm = kvm;
+       mutex_init(&p->mutex);
+       file->private_data = p;
+
+       return nonseekable_open(inode, file);
+}
+
+static int debugfs_htab_release(struct inode *inode, struct file *file)
+{
+       struct debugfs_htab_state *p = file->private_data;
+
+       kvm_put_kvm(p->kvm);
+       kfree(p);
+       return 0;
+}
+
+static ssize_t debugfs_htab_read(struct file *file, char __user *buf,
+                                size_t len, loff_t *ppos)
+{
+       struct debugfs_htab_state *p = file->private_data;
+       ssize_t ret, r;
+       unsigned long i, n;
+       unsigned long v, hr, gr;
+       struct kvm *kvm;
+       __be64 *hptp;
+
+       ret = mutex_lock_interruptible(&p->mutex);
+       if (ret)
+               return ret;
+
+       if (p->chars_left) {
+               n = p->chars_left;
+               if (n > len)
+                       n = len;
+               r = copy_to_user(buf, p->buf + p->buf_index, n);
+               n -= r;
+               p->chars_left -= n;
+               p->buf_index += n;
+               buf += n;
+               len -= n;
+               ret = n;
+               if (r) {
+                       if (!n)
+                               ret = -EFAULT;
+                       goto out;
+               }
+       }
+
+       kvm = p->kvm;
+       i = p->hpt_index;
+       hptp = (__be64 *)(kvm->arch.hpt_virt + (i * HPTE_SIZE));
+       for (; len != 0 && i < kvm->arch.hpt_npte; ++i, hptp += 2) {
+               if (!(be64_to_cpu(hptp[0]) & (HPTE_V_VALID | HPTE_V_ABSENT)))
+                       continue;
+
+               /* lock the HPTE so it's stable and read it */
+               preempt_disable();
+               while (!try_lock_hpte(hptp, HPTE_V_HVLOCK))
+                       cpu_relax();
+               v = be64_to_cpu(hptp[0]) & ~HPTE_V_HVLOCK;
+               hr = be64_to_cpu(hptp[1]);
+               gr = kvm->arch.revmap[i].guest_rpte;
+               unlock_hpte(hptp, v);
+               preempt_enable();
+
+               if (!(v & (HPTE_V_VALID | HPTE_V_ABSENT)))
+                       continue;
+
+               n = scnprintf(p->buf, sizeof(p->buf),
+                             "%6lx %.16lx %.16lx %.16lx\n",
+                             i, v, hr, gr);
+               p->chars_left = n;
+               if (n > len)
+                       n = len;
+               r = copy_to_user(buf, p->buf, n);
+               n -= r;
+               p->chars_left -= n;
+               p->buf_index = n;
+               buf += n;
+               len -= n;
+               ret += n;
+               if (r) {
+                       if (!ret)
+                               ret = -EFAULT;
+                       goto out;
+               }
+       }
+       p->hpt_index = i;
+
+ out:
+       mutex_unlock(&p->mutex);
+       return ret;
+}
+
+ssize_t debugfs_htab_write(struct file *file, const char __user *buf,
+                          size_t len, loff_t *ppos)
+{
+       return -EACCES;
+}
+
+static const struct file_operations debugfs_htab_fops = {
+       .owner   = THIS_MODULE,
+       .open    = debugfs_htab_open,
+       .release = debugfs_htab_release,
+       .read    = debugfs_htab_read,
+       .write   = debugfs_htab_write,
+       .llseek  = generic_file_llseek,
+};
+
+void kvmppc_mmu_debugfs_init(struct kvm *kvm)
+{
+       kvm->arch.htab_dentry = debugfs_create_file("htab", 0400,
+                                                   kvm->arch.debugfs_dir, kvm,
+                                                   &debugfs_htab_fops);
+}
+
 void kvmppc_mmu_book3s_hv_init(struct kvm_vcpu *vcpu)
 {
        struct kvmppc_mmu *mmu = &vcpu->arch.mmu;
index de747563d29df39be580e6cd67c54769194dce42..48d3c5d2ecc9ee83aab086715b3ffd6bf904d80a 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/page-flags.h>
 #include <linux/srcu.h>
 #include <linux/miscdevice.h>
+#include <linux/debugfs.h>
 
 #include <asm/reg.h>
 #include <asm/cputable.h>
@@ -50,6 +51,7 @@
 #include <asm/hvcall.h>
 #include <asm/switch_to.h>
 #include <asm/smp.h>
+#include <asm/dbell.h>
 #include <linux/gfp.h>
 #include <linux/vmalloc.h>
 #include <linux/highmem.h>
@@ -83,9 +85,35 @@ static DECLARE_BITMAP(default_enabled_hcalls, MAX_HCALL_OPCODE/4 + 1);
 static void kvmppc_end_cede(struct kvm_vcpu *vcpu);
 static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu);
 
+static bool kvmppc_ipi_thread(int cpu)
+{
+       /* On POWER8 for IPIs to threads in the same core, use msgsnd */
+       if (cpu_has_feature(CPU_FTR_ARCH_207S)) {
+               preempt_disable();
+               if (cpu_first_thread_sibling(cpu) ==
+                   cpu_first_thread_sibling(smp_processor_id())) {
+                       unsigned long msg = PPC_DBELL_TYPE(PPC_DBELL_SERVER);
+                       msg |= cpu_thread_in_core(cpu);
+                       smp_mb();
+                       __asm__ __volatile__ (PPC_MSGSND(%0) : : "r" (msg));
+                       preempt_enable();
+                       return true;
+               }
+               preempt_enable();
+       }
+
+#if defined(CONFIG_PPC_ICP_NATIVE) && defined(CONFIG_SMP)
+       if (cpu >= 0 && cpu < nr_cpu_ids && paca[cpu].kvm_hstate.xics_phys) {
+               xics_wake_cpu(cpu);
+               return true;
+       }
+#endif
+
+       return false;
+}
+
 static void kvmppc_fast_vcpu_kick_hv(struct kvm_vcpu *vcpu)
 {
-       int me;
        int cpu = vcpu->cpu;
        wait_queue_head_t *wqp;
 
@@ -95,20 +123,12 @@ static void kvmppc_fast_vcpu_kick_hv(struct kvm_vcpu *vcpu)
                ++vcpu->stat.halt_wakeup;
        }
 
-       me = get_cpu();
+       if (kvmppc_ipi_thread(cpu + vcpu->arch.ptid))
+               return;
 
        /* CPU points to the first thread of the core */
-       if (cpu != me && cpu >= 0 && cpu < nr_cpu_ids) {
-#ifdef CONFIG_PPC_ICP_NATIVE
-               int real_cpu = cpu + vcpu->arch.ptid;
-               if (paca[real_cpu].kvm_hstate.xics_phys)
-                       xics_wake_cpu(real_cpu);
-               else
-#endif
-               if (cpu_online(cpu))
-                       smp_send_reschedule(cpu);
-       }
-       put_cpu();
+       if (cpu >= 0 && cpu < nr_cpu_ids && cpu_online(cpu))
+               smp_send_reschedule(cpu);
 }
 
 /*
@@ -706,6 +726,16 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
 
                /* Send the error out to userspace via KVM_RUN */
                return rc;
+       case H_LOGICAL_CI_LOAD:
+               ret = kvmppc_h_logical_ci_load(vcpu);
+               if (ret == H_TOO_HARD)
+                       return RESUME_HOST;
+               break;
+       case H_LOGICAL_CI_STORE:
+               ret = kvmppc_h_logical_ci_store(vcpu);
+               if (ret == H_TOO_HARD)
+                       return RESUME_HOST;
+               break;
        case H_SET_MODE:
                ret = kvmppc_h_set_mode(vcpu, kvmppc_get_gpr(vcpu, 4),
                                        kvmppc_get_gpr(vcpu, 5),
@@ -740,6 +770,8 @@ static int kvmppc_hcall_impl_hv(unsigned long cmd)
        case H_CONFER:
        case H_REGISTER_VPA:
        case H_SET_MODE:
+       case H_LOGICAL_CI_LOAD:
+       case H_LOGICAL_CI_STORE:
 #ifdef CONFIG_KVM_XICS
        case H_XIRR:
        case H_CPPR:
@@ -1410,6 +1442,154 @@ static struct kvmppc_vcore *kvmppc_vcore_create(struct kvm *kvm, int core)
        return vcore;
 }
 
+#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
+static struct debugfs_timings_element {
+       const char *name;
+       size_t offset;
+} timings[] = {
+       {"rm_entry",    offsetof(struct kvm_vcpu, arch.rm_entry)},
+       {"rm_intr",     offsetof(struct kvm_vcpu, arch.rm_intr)},
+       {"rm_exit",     offsetof(struct kvm_vcpu, arch.rm_exit)},
+       {"guest",       offsetof(struct kvm_vcpu, arch.guest_time)},
+       {"cede",        offsetof(struct kvm_vcpu, arch.cede_time)},
+};
+
+#define N_TIMINGS      (sizeof(timings) / sizeof(timings[0]))
+
+struct debugfs_timings_state {
+       struct kvm_vcpu *vcpu;
+       unsigned int    buflen;
+       char            buf[N_TIMINGS * 100];
+};
+
+static int debugfs_timings_open(struct inode *inode, struct file *file)
+{
+       struct kvm_vcpu *vcpu = inode->i_private;
+       struct debugfs_timings_state *p;
+
+       p = kzalloc(sizeof(*p), GFP_KERNEL);
+       if (!p)
+               return -ENOMEM;
+
+       kvm_get_kvm(vcpu->kvm);
+       p->vcpu = vcpu;
+       file->private_data = p;
+
+       return nonseekable_open(inode, file);
+}
+
+static int debugfs_timings_release(struct inode *inode, struct file *file)
+{
+       struct debugfs_timings_state *p = file->private_data;
+
+       kvm_put_kvm(p->vcpu->kvm);
+       kfree(p);
+       return 0;
+}
+
+static ssize_t debugfs_timings_read(struct file *file, char __user *buf,
+                                   size_t len, loff_t *ppos)
+{
+       struct debugfs_timings_state *p = file->private_data;
+       struct kvm_vcpu *vcpu = p->vcpu;
+       char *s, *buf_end;
+       struct kvmhv_tb_accumulator tb;
+       u64 count;
+       loff_t pos;
+       ssize_t n;
+       int i, loops;
+       bool ok;
+
+       if (!p->buflen) {
+               s = p->buf;
+               buf_end = s + sizeof(p->buf);
+               for (i = 0; i < N_TIMINGS; ++i) {
+                       struct kvmhv_tb_accumulator *acc;
+
+                       acc = (struct kvmhv_tb_accumulator *)
+                               ((unsigned long)vcpu + timings[i].offset);
+                       ok = false;
+                       for (loops = 0; loops < 1000; ++loops) {
+                               count = acc->seqcount;
+                               if (!(count & 1)) {
+                                       smp_rmb();
+                                       tb = *acc;
+                                       smp_rmb();
+                                       if (count == acc->seqcount) {
+                                               ok = true;
+                                               break;
+                                       }
+                               }
+                               udelay(1);
+                       }
+                       if (!ok)
+                               snprintf(s, buf_end - s, "%s: stuck\n",
+                                       timings[i].name);
+                       else
+                               snprintf(s, buf_end - s,
+                                       "%s: %llu %llu %llu %llu\n",
+                                       timings[i].name, count / 2,
+                                       tb_to_ns(tb.tb_total),
+                                       tb_to_ns(tb.tb_min),
+                                       tb_to_ns(tb.tb_max));
+                       s += strlen(s);
+               }
+               p->buflen = s - p->buf;
+       }
+
+       pos = *ppos;
+       if (pos >= p->buflen)
+               return 0;
+       if (len > p->buflen - pos)
+               len = p->buflen - pos;
+       n = copy_to_user(buf, p->buf + pos, len);
+       if (n) {
+               if (n == len)
+                       return -EFAULT;
+               len -= n;
+       }
+       *ppos = pos + len;
+       return len;
+}
+
+static ssize_t debugfs_timings_write(struct file *file, const char __user *buf,
+                                    size_t len, loff_t *ppos)
+{
+       return -EACCES;
+}
+
+static const struct file_operations debugfs_timings_ops = {
+       .owner   = THIS_MODULE,
+       .open    = debugfs_timings_open,
+       .release = debugfs_timings_release,
+       .read    = debugfs_timings_read,
+       .write   = debugfs_timings_write,
+       .llseek  = generic_file_llseek,
+};
+
+/* Create a debugfs directory for the vcpu */
+static void debugfs_vcpu_init(struct kvm_vcpu *vcpu, unsigned int id)
+{
+       char buf[16];
+       struct kvm *kvm = vcpu->kvm;
+
+       snprintf(buf, sizeof(buf), "vcpu%u", id);
+       if (IS_ERR_OR_NULL(kvm->arch.debugfs_dir))
+               return;
+       vcpu->arch.debugfs_dir = debugfs_create_dir(buf, kvm->arch.debugfs_dir);
+       if (IS_ERR_OR_NULL(vcpu->arch.debugfs_dir))
+               return;
+       vcpu->arch.debugfs_timings =
+               debugfs_create_file("timings", 0444, vcpu->arch.debugfs_dir,
+                                   vcpu, &debugfs_timings_ops);
+}
+
+#else /* CONFIG_KVM_BOOK3S_HV_EXIT_TIMING */
+static void debugfs_vcpu_init(struct kvm_vcpu *vcpu, unsigned int id)
+{
+}
+#endif /* CONFIG_KVM_BOOK3S_HV_EXIT_TIMING */
+
 static struct kvm_vcpu *kvmppc_core_vcpu_create_hv(struct kvm *kvm,
                                                   unsigned int id)
 {
@@ -1479,6 +1659,8 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_hv(struct kvm *kvm,
        vcpu->arch.cpu_type = KVM_CPU_3S_64;
        kvmppc_sanity_check(vcpu);
 
+       debugfs_vcpu_init(vcpu, id);
+
        return vcpu;
 
 free_vcpu:
@@ -1566,8 +1748,10 @@ static int kvmppc_grab_hwthread(int cpu)
        tpaca = &paca[cpu];
 
        /* Ensure the thread won't go into the kernel if it wakes */
-       tpaca->kvm_hstate.hwthread_req = 1;
        tpaca->kvm_hstate.kvm_vcpu = NULL;
+       tpaca->kvm_hstate.napping = 0;
+       smp_wmb();
+       tpaca->kvm_hstate.hwthread_req = 1;
 
        /*
         * If the thread is already executing in the kernel (e.g. handling
@@ -1610,35 +1794,41 @@ static void kvmppc_start_thread(struct kvm_vcpu *vcpu)
        }
        cpu = vc->pcpu + vcpu->arch.ptid;
        tpaca = &paca[cpu];
-       tpaca->kvm_hstate.kvm_vcpu = vcpu;
        tpaca->kvm_hstate.kvm_vcore = vc;
        tpaca->kvm_hstate.ptid = vcpu->arch.ptid;
        vcpu->cpu = vc->pcpu;
+       /* Order stores to hstate.kvm_vcore etc. before store to kvm_vcpu */
        smp_wmb();
-#if defined(CONFIG_PPC_ICP_NATIVE) && defined(CONFIG_SMP)
-       if (cpu != smp_processor_id()) {
-               xics_wake_cpu(cpu);
-               if (vcpu->arch.ptid)
-                       ++vc->n_woken;
-       }
-#endif
+       tpaca->kvm_hstate.kvm_vcpu = vcpu;
+       if (cpu != smp_processor_id())
+               kvmppc_ipi_thread(cpu);
 }
 
-static void kvmppc_wait_for_nap(struct kvmppc_vcore *vc)
+static void kvmppc_wait_for_nap(void)
 {
-       int i;
+       int cpu = smp_processor_id();
+       int i, loops;
 
-       HMT_low();
-       i = 0;
-       while (vc->nap_count < vc->n_woken) {
-               if (++i >= 1000000) {
-                       pr_err("kvmppc_wait_for_nap timeout %d %d\n",
-                              vc->nap_count, vc->n_woken);
-                       break;
+       for (loops = 0; loops < 1000000; ++loops) {
+               /*
+                * Check if all threads are finished.
+                * We set the vcpu pointer when starting a thread
+                * and the thread clears it when finished, so we look
+                * for any threads that still have a non-NULL vcpu ptr.
+                */
+               for (i = 1; i < threads_per_subcore; ++i)
+                       if (paca[cpu + i].kvm_hstate.kvm_vcpu)
+                               break;
+               if (i == threads_per_subcore) {
+                       HMT_medium();
+                       return;
                }
-               cpu_relax();
+               HMT_low();
        }
        HMT_medium();
+       for (i = 1; i < threads_per_subcore; ++i)
+               if (paca[cpu + i].kvm_hstate.kvm_vcpu)
+                       pr_err("KVM: CPU %d seems to be stuck\n", cpu + i);
 }
 
 /*
@@ -1700,54 +1890,91 @@ static void kvmppc_start_restoring_l2_cache(const struct kvmppc_vcore *vc)
        mtspr(SPRN_MPPR, mpp_addr | PPC_MPPR_FETCH_WHOLE_TABLE);
 }
 
+static void prepare_threads(struct kvmppc_vcore *vc)
+{
+       struct kvm_vcpu *vcpu, *vnext;
+
+       list_for_each_entry_safe(vcpu, vnext, &vc->runnable_threads,
+                                arch.run_list) {
+               if (signal_pending(vcpu->arch.run_task))
+                       vcpu->arch.ret = -EINTR;
+               else if (vcpu->arch.vpa.update_pending ||
+                        vcpu->arch.slb_shadow.update_pending ||
+                        vcpu->arch.dtl.update_pending)
+                       vcpu->arch.ret = RESUME_GUEST;
+               else
+                       continue;
+               kvmppc_remove_runnable(vc, vcpu);
+               wake_up(&vcpu->arch.cpu_run);
+       }
+}
+
+static void post_guest_process(struct kvmppc_vcore *vc)
+{
+       u64 now;
+       long ret;
+       struct kvm_vcpu *vcpu, *vnext;
+
+       now = get_tb();
+       list_for_each_entry_safe(vcpu, vnext, &vc->runnable_threads,
+                                arch.run_list) {
+               /* cancel pending dec exception if dec is positive */
+               if (now < vcpu->arch.dec_expires &&
+                   kvmppc_core_pending_dec(vcpu))
+                       kvmppc_core_dequeue_dec(vcpu);
+
+               trace_kvm_guest_exit(vcpu);
+
+               ret = RESUME_GUEST;
+               if (vcpu->arch.trap)
+                       ret = kvmppc_handle_exit_hv(vcpu->arch.kvm_run, vcpu,
+                                                   vcpu->arch.run_task);
+
+               vcpu->arch.ret = ret;
+               vcpu->arch.trap = 0;
+
+               if (vcpu->arch.ceded) {
+                       if (!is_kvmppc_resume_guest(ret))
+                               kvmppc_end_cede(vcpu);
+                       else
+                               kvmppc_set_timer(vcpu);
+               }
+               if (!is_kvmppc_resume_guest(vcpu->arch.ret)) {
+                       kvmppc_remove_runnable(vc, vcpu);
+                       wake_up(&vcpu->arch.cpu_run);
+               }
+       }
+}
+
 /*
  * Run a set of guest threads on a physical core.
  * Called with vc->lock held.
  */
-static void kvmppc_run_core(struct kvmppc_vcore *vc)
+static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
 {
-       struct kvm_vcpu *vcpu, *vnext;
-       long ret;
-       u64 now;
-       int i, need_vpa_update;
+       struct kvm_vcpu *vcpu;
+       int i;
        int srcu_idx;
-       struct kvm_vcpu *vcpus_to_update[threads_per_core];
 
-       /* don't start if any threads have a signal pending */
-       need_vpa_update = 0;
-       list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) {
-               if (signal_pending(vcpu->arch.run_task))
-                       return;
-               if (vcpu->arch.vpa.update_pending ||
-                   vcpu->arch.slb_shadow.update_pending ||
-                   vcpu->arch.dtl.update_pending)
-                       vcpus_to_update[need_vpa_update++] = vcpu;
-       }
+       /*
+        * Remove from the list any threads that have a signal pending
+        * or need a VPA update done
+        */
+       prepare_threads(vc);
+
+       /* if the runner is no longer runnable, let the caller pick a new one */
+       if (vc->runner->arch.state != KVMPPC_VCPU_RUNNABLE)
+               return;
 
        /*
-        * Initialize *vc, in particular vc->vcore_state, so we can
-        * drop the vcore lock if necessary.
+        * Initialize *vc.
         */
-       vc->n_woken = 0;
-       vc->nap_count = 0;
-       vc->entry_exit_count = 0;
+       vc->entry_exit_map = 0;
        vc->preempt_tb = TB_NIL;
-       vc->vcore_state = VCORE_STARTING;
        vc->in_guest = 0;
        vc->napping_threads = 0;
        vc->conferring_threads = 0;
 
-       /*
-        * Updating any of the vpas requires calling kvmppc_pin_guest_page,
-        * which can't be called with any spinlocks held.
-        */
-       if (need_vpa_update) {
-               spin_unlock(&vc->lock);
-               for (i = 0; i < need_vpa_update; ++i)
-                       kvmppc_update_vpas(vcpus_to_update[i]);
-               spin_lock(&vc->lock);
-       }
-
        /*
         * Make sure we are running on primary threads, and that secondary
         * threads are offline.  Also check if the number of threads in this
@@ -1755,8 +1982,11 @@ static void kvmppc_run_core(struct kvmppc_vcore *vc)
         */
        if ((threads_per_core > 1) &&
            ((vc->num_threads > threads_per_subcore) || !on_primary_thread())) {
-               list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
+               list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) {
                        vcpu->arch.ret = -EBUSY;
+                       kvmppc_remove_runnable(vc, vcpu);
+                       wake_up(&vcpu->arch.cpu_run);
+               }
                goto out;
        }
 
@@ -1797,8 +2027,7 @@ static void kvmppc_run_core(struct kvmppc_vcore *vc)
        list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
                vcpu->cpu = -1;
        /* wait for secondary threads to finish writing their state to memory */
-       if (vc->nap_count < vc->n_woken)
-               kvmppc_wait_for_nap(vc);
+       kvmppc_wait_for_nap();
        for (i = 0; i < threads_per_subcore; ++i)
                kvmppc_release_hwthread(vc->pcpu + i);
        /* prevent other vcpu threads from doing kvmppc_start_thread() now */
@@ -1812,44 +2041,12 @@ static void kvmppc_run_core(struct kvmppc_vcore *vc)
        kvm_guest_exit();
 
        preempt_enable();
-       cond_resched();
 
        spin_lock(&vc->lock);
-       now = get_tb();
-       list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) {
-               /* cancel pending dec exception if dec is positive */
-               if (now < vcpu->arch.dec_expires &&
-                   kvmppc_core_pending_dec(vcpu))
-                       kvmppc_core_dequeue_dec(vcpu);
-
-               trace_kvm_guest_exit(vcpu);
-
-               ret = RESUME_GUEST;
-               if (vcpu->arch.trap)
-                       ret = kvmppc_handle_exit_hv(vcpu->arch.kvm_run, vcpu,
-                                                   vcpu->arch.run_task);
-
-               vcpu->arch.ret = ret;
-               vcpu->arch.trap = 0;
-
-               if (vcpu->arch.ceded) {
-                       if (!is_kvmppc_resume_guest(ret))
-                               kvmppc_end_cede(vcpu);
-                       else
-                               kvmppc_set_timer(vcpu);
-               }
-       }
+       post_guest_process(vc);
 
  out:
        vc->vcore_state = VCORE_INACTIVE;
-       list_for_each_entry_safe(vcpu, vnext, &vc->runnable_threads,
-                                arch.run_list) {
-               if (!is_kvmppc_resume_guest(vcpu->arch.ret)) {
-                       kvmppc_remove_runnable(vc, vcpu);
-                       wake_up(&vcpu->arch.cpu_run);
-               }
-       }
-
        trace_kvmppc_run_core(vc, 1);
 }
 
@@ -1939,8 +2136,7 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
         * this thread straight away and have it join in.
         */
        if (!signal_pending(current)) {
-               if (vc->vcore_state == VCORE_RUNNING &&
-                   VCORE_EXIT_COUNT(vc) == 0) {
+               if (vc->vcore_state == VCORE_RUNNING && !VCORE_IS_EXITING(vc)) {
                        kvmppc_create_dtl_entry(vcpu, vc);
                        kvmppc_start_thread(vcpu);
                        trace_kvm_guest_enter(vcpu);
@@ -1971,7 +2167,6 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
                }
                if (!vc->n_runnable || vcpu->arch.state != KVMPPC_VCPU_RUNNABLE)
                        break;
-               vc->runner = vcpu;
                n_ceded = 0;
                list_for_each_entry(v, &vc->runnable_threads, arch.run_list) {
                        if (!v->arch.pending_exceptions)
@@ -1979,10 +2174,17 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
                        else
                                v->arch.ceded = 0;
                }
-               if (n_ceded == vc->n_runnable)
+               vc->runner = vcpu;
+               if (n_ceded == vc->n_runnable) {
                        kvmppc_vcore_blocked(vc);
-               else
+               } else if (should_resched()) {
+                       vc->vcore_state = VCORE_PREEMPT;
+                       /* Let something else run */
+                       cond_resched_lock(&vc->lock);
+                       vc->vcore_state = VCORE_INACTIVE;
+               } else {
                        kvmppc_run_core(vc);
+               }
                vc->runner = NULL;
        }
 
@@ -2032,11 +2234,11 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu)
        }
 
        atomic_inc(&vcpu->kvm->arch.vcpus_running);
-       /* Order vcpus_running vs. rma_setup_done, see kvmppc_alloc_reset_hpt */
+       /* Order vcpus_running vs. hpte_setup_done, see kvmppc_alloc_reset_hpt */
        smp_mb();
 
        /* On the first time here, set up HTAB and VRMA */
-       if (!vcpu->kvm->arch.rma_setup_done) {
+       if (!vcpu->kvm->arch.hpte_setup_done) {
                r = kvmppc_hv_setup_htab_rma(vcpu);
                if (r)
                        goto out;
@@ -2238,7 +2440,7 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
        int srcu_idx;
 
        mutex_lock(&kvm->lock);
-       if (kvm->arch.rma_setup_done)
+       if (kvm->arch.hpte_setup_done)
                goto out;       /* another vcpu beat us to it */
 
        /* Allocate hashed page table (if not done already) and reset it */
@@ -2289,9 +2491,9 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
 
        kvmppc_update_lpcr(kvm, lpcr, LPCR_VRMASD);
 
-       /* Order updates to kvm->arch.lpcr etc. vs. rma_setup_done */
+       /* Order updates to kvm->arch.lpcr etc. vs. hpte_setup_done */
        smp_wmb();
-       kvm->arch.rma_setup_done = 1;
+       kvm->arch.hpte_setup_done = 1;
        err = 0;
  out_srcu:
        srcu_read_unlock(&kvm->srcu, srcu_idx);
@@ -2307,6 +2509,7 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
 static int kvmppc_core_init_vm_hv(struct kvm *kvm)
 {
        unsigned long lpcr, lpid;
+       char buf[32];
 
        /* Allocate the guest's logical partition ID */
 
@@ -2347,6 +2550,14 @@ static int kvmppc_core_init_vm_hv(struct kvm *kvm)
         */
        kvm_hv_vm_activated();
 
+       /*
+        * Create a debugfs directory for the VM
+        */
+       snprintf(buf, sizeof(buf), "vm%d", current->pid);
+       kvm->arch.debugfs_dir = debugfs_create_dir(buf, kvm_debugfs_dir);
+       if (!IS_ERR_OR_NULL(kvm->arch.debugfs_dir))
+               kvmppc_mmu_debugfs_init(kvm);
+
        return 0;
 }
 
@@ -2367,6 +2578,8 @@ static void kvmppc_free_vcores(struct kvm *kvm)
 
 static void kvmppc_core_destroy_vm_hv(struct kvm *kvm)
 {
+       debugfs_remove_recursive(kvm->arch.debugfs_dir);
+
        kvm_hv_vm_deactivated();
 
        kvmppc_free_vcores(kvm);
index 1f083ff8a61a065cd7aa2dc2901000224e515e2e..ed2589d4593fb710085014bcc81a3d2a0e9e54ff 100644 (file)
 #include <asm/cputable.h>
 #include <asm/kvm_ppc.h>
 #include <asm/kvm_book3s.h>
+#include <asm/archrandom.h>
+#include <asm/xics.h>
+#include <asm/dbell.h>
+#include <asm/cputhreads.h>
 
 #define KVM_CMA_CHUNK_ORDER    18
 
@@ -114,11 +118,11 @@ long int kvmppc_rm_h_confer(struct kvm_vcpu *vcpu, int target,
        int rv = H_SUCCESS; /* => don't yield */
 
        set_bit(vcpu->arch.ptid, &vc->conferring_threads);
-       while ((get_tb() < stop) && (VCORE_EXIT_COUNT(vc) == 0)) {
-               threads_running = VCORE_ENTRY_COUNT(vc);
-               threads_ceded = hweight32(vc->napping_threads);
-               threads_conferring = hweight32(vc->conferring_threads);
-               if (threads_ceded + threads_conferring >= threads_running) {
+       while ((get_tb() < stop) && !VCORE_IS_EXITING(vc)) {
+               threads_running = VCORE_ENTRY_MAP(vc);
+               threads_ceded = vc->napping_threads;
+               threads_conferring = vc->conferring_threads;
+               if ((threads_ceded | threads_conferring) == threads_running) {
                        rv = H_TOO_HARD; /* => do yield */
                        break;
                }
@@ -169,3 +173,89 @@ int kvmppc_hcall_impl_hv_realmode(unsigned long cmd)
        return 0;
 }
 EXPORT_SYMBOL_GPL(kvmppc_hcall_impl_hv_realmode);
+
+int kvmppc_hwrng_present(void)
+{
+       return powernv_hwrng_present();
+}
+EXPORT_SYMBOL_GPL(kvmppc_hwrng_present);
+
+long kvmppc_h_random(struct kvm_vcpu *vcpu)
+{
+       if (powernv_get_random_real_mode(&vcpu->arch.gpr[4]))
+               return H_SUCCESS;
+
+       return H_HARDWARE;
+}
+
+static inline void rm_writeb(unsigned long paddr, u8 val)
+{
+       __asm__ __volatile__("stbcix %0,0,%1"
+               : : "r" (val), "r" (paddr) : "memory");
+}
+
+/*
+ * Send an interrupt or message to another CPU.
+ * This can only be called in real mode.
+ * The caller needs to include any barrier needed to order writes
+ * to memory vs. the IPI/message.
+ */
+void kvmhv_rm_send_ipi(int cpu)
+{
+       unsigned long xics_phys;
+
+       /* On POWER8 for IPIs to threads in the same core, use msgsnd */
+       if (cpu_has_feature(CPU_FTR_ARCH_207S) &&
+           cpu_first_thread_sibling(cpu) ==
+           cpu_first_thread_sibling(raw_smp_processor_id())) {
+               unsigned long msg = PPC_DBELL_TYPE(PPC_DBELL_SERVER);
+               msg |= cpu_thread_in_core(cpu);
+               __asm__ __volatile__ (PPC_MSGSND(%0) : : "r" (msg));
+               return;
+       }
+
+       /* Else poke the target with an IPI */
+       xics_phys = paca[cpu].kvm_hstate.xics_phys;
+       rm_writeb(xics_phys + XICS_MFRR, IPI_PRIORITY);
+}
+
+/*
+ * The following functions are called from the assembly code
+ * in book3s_hv_rmhandlers.S.
+ */
+static void kvmhv_interrupt_vcore(struct kvmppc_vcore *vc, int active)
+{
+       int cpu = vc->pcpu;
+
+       /* Order setting of exit map vs. msgsnd/IPI */
+       smp_mb();
+       for (; active; active >>= 1, ++cpu)
+               if (active & 1)
+                       kvmhv_rm_send_ipi(cpu);
+}
+
+void kvmhv_commence_exit(int trap)
+{
+       struct kvmppc_vcore *vc = local_paca->kvm_hstate.kvm_vcore;
+       int ptid = local_paca->kvm_hstate.ptid;
+       int me, ee;
+
+       /* Set our bit in the threads-exiting-guest map in the 0xff00
+          bits of vcore->entry_exit_map */
+       me = 0x100 << ptid;
+       do {
+               ee = vc->entry_exit_map;
+       } while (cmpxchg(&vc->entry_exit_map, ee, ee | me) != ee);
+
+       /* Are we the first here? */
+       if ((ee >> 8) != 0)
+               return;
+
+       /*
+        * Trigger the other threads in this vcore to exit the guest.
+        * If this is a hypervisor decrementer interrupt then they
+        * will be already on their way out of the guest.
+        */
+       if (trap != BOOK3S_INTERRUPT_HV_DECREMENTER)
+               kvmhv_interrupt_vcore(vc, ee & ~(1 << ptid));
+}
index 625407e4d3b0a77314181af9fd891448e765c8a0..b027a89737b62cee4399e63eb9d61232f156687d 100644 (file)
@@ -26,11 +26,14 @@ static void *real_vmalloc_addr(void *x)
 {
        unsigned long addr = (unsigned long) x;
        pte_t *p;
-
-       p = find_linux_pte_or_hugepte(swapper_pg_dir, addr, NULL);
+       /*
+        * assume we don't have huge pages in vmalloc space...
+        * So don't worry about THP collapse/split. Called
+        * Only in realmode, hence won't need irq_save/restore.
+        */
+       p = __find_linux_pte_or_hugepte(swapper_pg_dir, addr, NULL);
        if (!p || !pte_present(*p))
                return NULL;
-       /* assume we don't have huge pages in vmalloc space... */
        addr = (pte_pfn(*p) << PAGE_SHIFT) | (addr & ~PAGE_MASK);
        return __va(addr);
 }
@@ -131,31 +134,6 @@ static void remove_revmap_chain(struct kvm *kvm, long pte_index,
        unlock_rmap(rmap);
 }
 
-static pte_t lookup_linux_pte_and_update(pgd_t *pgdir, unsigned long hva,
-                             int writing, unsigned long *pte_sizep)
-{
-       pte_t *ptep;
-       unsigned long ps = *pte_sizep;
-       unsigned int hugepage_shift;
-
-       ptep = find_linux_pte_or_hugepte(pgdir, hva, &hugepage_shift);
-       if (!ptep)
-               return __pte(0);
-       if (hugepage_shift)
-               *pte_sizep = 1ul << hugepage_shift;
-       else
-               *pte_sizep = PAGE_SIZE;
-       if (ps > *pte_sizep)
-               return __pte(0);
-       return kvmppc_read_update_linux_pte(ptep, writing, hugepage_shift);
-}
-
-static inline void unlock_hpte(__be64 *hpte, unsigned long hpte_v)
-{
-       asm volatile(PPC_RELEASE_BARRIER "" : : : "memory");
-       hpte[0] = cpu_to_be64(hpte_v);
-}
-
 long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
                       long pte_index, unsigned long pteh, unsigned long ptel,
                       pgd_t *pgdir, bool realmode, unsigned long *pte_idx_ret)
@@ -166,13 +144,13 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
        struct revmap_entry *rev;
        unsigned long g_ptel;
        struct kvm_memory_slot *memslot;
-       unsigned long pte_size;
+       unsigned hpage_shift;
        unsigned long is_io;
        unsigned long *rmap;
-       pte_t pte;
+       pte_t *ptep;
        unsigned int writing;
        unsigned long mmu_seq;
-       unsigned long rcbits;
+       unsigned long rcbits, irq_flags = 0;
 
        psize = hpte_page_size(pteh, ptel);
        if (!psize)
@@ -208,22 +186,46 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
 
        /* Translate to host virtual address */
        hva = __gfn_to_hva_memslot(memslot, gfn);
-
-       /* Look up the Linux PTE for the backing page */
-       pte_size = psize;
-       pte = lookup_linux_pte_and_update(pgdir, hva, writing, &pte_size);
-       if (pte_present(pte) && !pte_protnone(pte)) {
-               if (writing && !pte_write(pte))
-                       /* make the actual HPTE be read-only */
-                       ptel = hpte_make_readonly(ptel);
-               is_io = hpte_cache_bits(pte_val(pte));
-               pa = pte_pfn(pte) << PAGE_SHIFT;
-               pa |= hva & (pte_size - 1);
-               pa |= gpa & ~PAGE_MASK;
+       /*
+        * If we had a page table table change after lookup, we would
+        * retry via mmu_notifier_retry.
+        */
+       if (realmode)
+               ptep = __find_linux_pte_or_hugepte(pgdir, hva, &hpage_shift);
+       else {
+               local_irq_save(irq_flags);
+               ptep = find_linux_pte_or_hugepte(pgdir, hva, &hpage_shift);
        }
+       if (ptep) {
+               pte_t pte;
+               unsigned int host_pte_size;
 
-       if (pte_size < psize)
-               return H_PARAMETER;
+               if (hpage_shift)
+                       host_pte_size = 1ul << hpage_shift;
+               else
+                       host_pte_size = PAGE_SIZE;
+               /*
+                * We should always find the guest page size
+                * to <= host page size, if host is using hugepage
+                */
+               if (host_pte_size < psize) {
+                       if (!realmode)
+                               local_irq_restore(flags);
+                       return H_PARAMETER;
+               }
+               pte = kvmppc_read_update_linux_pte(ptep, writing);
+               if (pte_present(pte) && !pte_protnone(pte)) {
+                       if (writing && !pte_write(pte))
+                               /* make the actual HPTE be read-only */
+                               ptel = hpte_make_readonly(ptel);
+                       is_io = hpte_cache_bits(pte_val(pte));
+                       pa = pte_pfn(pte) << PAGE_SHIFT;
+                       pa |= hva & (host_pte_size - 1);
+                       pa |= gpa & ~PAGE_MASK;
+               }
+       }
+       if (!realmode)
+               local_irq_restore(irq_flags);
 
        ptel &= ~(HPTE_R_PP0 - psize);
        ptel |= pa;
@@ -271,10 +273,10 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
                                u64 pte;
                                while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
                                        cpu_relax();
-                               pte = be64_to_cpu(*hpte);
+                               pte = be64_to_cpu(hpte[0]);
                                if (!(pte & (HPTE_V_VALID | HPTE_V_ABSENT)))
                                        break;
-                               *hpte &= ~cpu_to_be64(HPTE_V_HVLOCK);
+                               __unlock_hpte(hpte, pte);
                                hpte += 2;
                        }
                        if (i == 8)
@@ -290,9 +292,9 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
 
                        while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
                                cpu_relax();
-                       pte = be64_to_cpu(*hpte);
+                       pte = be64_to_cpu(hpte[0]);
                        if (pte & (HPTE_V_VALID | HPTE_V_ABSENT)) {
-                               *hpte &= ~cpu_to_be64(HPTE_V_HVLOCK);
+                               __unlock_hpte(hpte, pte);
                                return H_PTEG_FULL;
                        }
                }
@@ -331,7 +333,7 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
 
        /* Write the first HPTE dword, unlocking the HPTE and making it valid */
        eieio();
-       hpte[0] = cpu_to_be64(pteh);
+       __unlock_hpte(hpte, pteh);
        asm volatile("ptesync" : : : "memory");
 
        *pte_idx_ret = pte_index;
@@ -412,7 +414,7 @@ long kvmppc_do_h_remove(struct kvm *kvm, unsigned long flags,
        if ((pte & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 ||
            ((flags & H_AVPN) && (pte & ~0x7fUL) != avpn) ||
            ((flags & H_ANDCOND) && (pte & avpn) != 0)) {
-               hpte[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
+               __unlock_hpte(hpte, pte);
                return H_NOT_FOUND;
        }
 
@@ -548,7 +550,7 @@ long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu)
                                be64_to_cpu(hp[0]), be64_to_cpu(hp[1]));
                        rcbits = rev->guest_rpte & (HPTE_R_R|HPTE_R_C);
                        args[j] |= rcbits << (56 - 5);
-                       hp[0] = 0;
+                       __unlock_hpte(hp, 0);
                }
        }
 
@@ -574,7 +576,7 @@ long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
        pte = be64_to_cpu(hpte[0]);
        if ((pte & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 ||
            ((flags & H_AVPN) && (pte & ~0x7fUL) != avpn)) {
-               hpte[0] &= ~cpu_to_be64(HPTE_V_HVLOCK);
+               __unlock_hpte(hpte, pte);
                return H_NOT_FOUND;
        }
 
@@ -755,8 +757,7 @@ long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr, unsigned long slb_v,
                                /* Return with the HPTE still locked */
                                return (hash << 3) + (i >> 1);
 
-                       /* Unlock and move on */
-                       hpte[i] = cpu_to_be64(v);
+                       __unlock_hpte(&hpte[i], v);
                }
 
                if (val & HPTE_V_SECONDARY)
index 7c22997de906410fc71802855607b92f2d700954..00e45b6d4f2464a0bde10762f5f995ea43b2296a 100644 (file)
 
 #define DEBUG_PASSUP
 
-static inline void rm_writeb(unsigned long paddr, u8 val)
+static void icp_rm_deliver_irq(struct kvmppc_xics *xics, struct kvmppc_icp *icp,
+                           u32 new_irq);
+
+/* -- ICS routines -- */
+static void ics_rm_check_resend(struct kvmppc_xics *xics,
+                               struct kvmppc_ics *ics, struct kvmppc_icp *icp)
 {
-       __asm__ __volatile__("sync; stbcix %0,0,%1"
-               : : "r" (val), "r" (paddr) : "memory");
+       int i;
+
+       arch_spin_lock(&ics->lock);
+
+       for (i = 0; i < KVMPPC_XICS_IRQ_PER_ICS; i++) {
+               struct ics_irq_state *state = &ics->irq_state[i];
+
+               if (!state->resend)
+                       continue;
+
+               arch_spin_unlock(&ics->lock);
+               icp_rm_deliver_irq(xics, icp, state->number);
+               arch_spin_lock(&ics->lock);
+       }
+
+       arch_spin_unlock(&ics->lock);
 }
 
+/* -- ICP routines -- */
+
 static void icp_rm_set_vcpu_irq(struct kvm_vcpu *vcpu,
                                struct kvm_vcpu *this_vcpu)
 {
        struct kvmppc_icp *this_icp = this_vcpu->arch.icp;
-       unsigned long xics_phys;
        int cpu;
 
        /* Mark the target VCPU as having an interrupt pending */
@@ -56,9 +76,8 @@ static void icp_rm_set_vcpu_irq(struct kvm_vcpu *vcpu,
        /* In SMT cpu will always point to thread 0, we adjust it */
        cpu += vcpu->arch.ptid;
 
-       /* Not too hard, then poke the target */
-       xics_phys = paca[cpu].kvm_hstate.xics_phys;
-       rm_writeb(xics_phys + XICS_MFRR, IPI_PRIORITY);
+       smp_mb();
+       kvmhv_rm_send_ipi(cpu);
 }
 
 static void icp_rm_clr_vcpu_irq(struct kvm_vcpu *vcpu)
@@ -116,6 +135,180 @@ static inline int check_too_hard(struct kvmppc_xics *xics,
        return (xics->real_mode_dbg || icp->rm_action) ? H_TOO_HARD : H_SUCCESS;
 }
 
+static void icp_rm_check_resend(struct kvmppc_xics *xics,
+                            struct kvmppc_icp *icp)
+{
+       u32 icsid;
+
+       /* Order this load with the test for need_resend in the caller */
+       smp_rmb();
+       for_each_set_bit(icsid, icp->resend_map, xics->max_icsid + 1) {
+               struct kvmppc_ics *ics = xics->ics[icsid];
+
+               if (!test_and_clear_bit(icsid, icp->resend_map))
+                       continue;
+               if (!ics)
+                       continue;
+               ics_rm_check_resend(xics, ics, icp);
+       }
+}
+
+static bool icp_rm_try_to_deliver(struct kvmppc_icp *icp, u32 irq, u8 priority,
+                              u32 *reject)
+{
+       union kvmppc_icp_state old_state, new_state;
+       bool success;
+
+       do {
+               old_state = new_state = READ_ONCE(icp->state);
+
+               *reject = 0;
+
+               /* See if we can deliver */
+               success = new_state.cppr > priority &&
+                       new_state.mfrr > priority &&
+                       new_state.pending_pri > priority;
+
+               /*
+                * If we can, check for a rejection and perform the
+                * delivery
+                */
+               if (success) {
+                       *reject = new_state.xisr;
+                       new_state.xisr = irq;
+                       new_state.pending_pri = priority;
+               } else {
+                       /*
+                        * If we failed to deliver we set need_resend
+                        * so a subsequent CPPR state change causes us
+                        * to try a new delivery.
+                        */
+                       new_state.need_resend = true;
+               }
+
+       } while (!icp_rm_try_update(icp, old_state, new_state));
+
+       return success;
+}
+
+static void icp_rm_deliver_irq(struct kvmppc_xics *xics, struct kvmppc_icp *icp,
+                           u32 new_irq)
+{
+       struct ics_irq_state *state;
+       struct kvmppc_ics *ics;
+       u32 reject;
+       u16 src;
+
+       /*
+        * This is used both for initial delivery of an interrupt and
+        * for subsequent rejection.
+        *
+        * Rejection can be racy vs. resends. We have evaluated the
+        * rejection in an atomic ICP transaction which is now complete,
+        * so potentially the ICP can already accept the interrupt again.
+        *
+        * So we need to retry the delivery. Essentially the reject path
+        * boils down to a failed delivery. Always.
+        *
+        * Now the interrupt could also have moved to a different target,
+        * thus we may need to re-do the ICP lookup as well
+        */
+
+ again:
+       /* Get the ICS state and lock it */
+       ics = kvmppc_xics_find_ics(xics, new_irq, &src);
+       if (!ics) {
+               /* Unsafe increment, but this does not need to be accurate */
+               xics->err_noics++;
+               return;
+       }
+       state = &ics->irq_state[src];
+
+       /* Get a lock on the ICS */
+       arch_spin_lock(&ics->lock);
+
+       /* Get our server */
+       if (!icp || state->server != icp->server_num) {
+               icp = kvmppc_xics_find_server(xics->kvm, state->server);
+               if (!icp) {
+                       /* Unsafe increment again*/
+                       xics->err_noicp++;
+                       goto out;
+               }
+       }
+
+       /* Clear the resend bit of that interrupt */
+       state->resend = 0;
+
+       /*
+        * If masked, bail out
+        *
+        * Note: PAPR doesn't mention anything about masked pending
+        * when doing a resend, only when doing a delivery.
+        *
+        * However that would have the effect of losing a masked
+        * interrupt that was rejected and isn't consistent with
+        * the whole masked_pending business which is about not
+        * losing interrupts that occur while masked.
+        *
+        * I don't differentiate normal deliveries and resends, this
+        * implementation will differ from PAPR and not lose such
+        * interrupts.
+        */
+       if (state->priority == MASKED) {
+               state->masked_pending = 1;
+               goto out;
+       }
+
+       /*
+        * Try the delivery, this will set the need_resend flag
+        * in the ICP as part of the atomic transaction if the
+        * delivery is not possible.
+        *
+        * Note that if successful, the new delivery might have itself
+        * rejected an interrupt that was "delivered" before we took the
+        * ics spin lock.
+        *
+        * In this case we do the whole sequence all over again for the
+        * new guy. We cannot assume that the rejected interrupt is less
+        * favored than the new one, and thus doesn't need to be delivered,
+        * because by the time we exit icp_rm_try_to_deliver() the target
+        * processor may well have already consumed & completed it, and thus
+        * the rejected interrupt might actually be already acceptable.
+        */
+       if (icp_rm_try_to_deliver(icp, new_irq, state->priority, &reject)) {
+               /*
+                * Delivery was successful, did we reject somebody else ?
+                */
+               if (reject && reject != XICS_IPI) {
+                       arch_spin_unlock(&ics->lock);
+                       new_irq = reject;
+                       goto again;
+               }
+       } else {
+               /*
+                * We failed to deliver the interrupt we need to set the
+                * resend map bit and mark the ICS state as needing a resend
+                */
+               set_bit(ics->icsid, icp->resend_map);
+               state->resend = 1;
+
+               /*
+                * If the need_resend flag got cleared in the ICP some time
+                * between icp_rm_try_to_deliver() atomic update and now, then
+                * we know it might have missed the resend_map bit. So we
+                * retry
+                */
+               smp_mb();
+               if (!icp->state.need_resend) {
+                       arch_spin_unlock(&ics->lock);
+                       goto again;
+               }
+       }
+ out:
+       arch_spin_unlock(&ics->lock);
+}
+
 static void icp_rm_down_cppr(struct kvmppc_xics *xics, struct kvmppc_icp *icp,
                             u8 new_cppr)
 {
@@ -184,8 +377,8 @@ static void icp_rm_down_cppr(struct kvmppc_xics *xics, struct kvmppc_icp *icp,
         * separately here as well.
         */
        if (resend) {
-               icp->rm_action |= XICS_RM_CHECK_RESEND;
-               icp->rm_resend_icp = icp;
+               icp->n_check_resend++;
+               icp_rm_check_resend(xics, icp);
        }
 }
 
@@ -300,16 +493,16 @@ int kvmppc_rm_h_ipi(struct kvm_vcpu *vcpu, unsigned long server,
                }
        } while (!icp_rm_try_update(icp, old_state, new_state));
 
-       /* Pass rejects to virtual mode */
+       /* Handle reject in real mode */
        if (reject && reject != XICS_IPI) {
-               this_icp->rm_action |= XICS_RM_REJECT;
-               this_icp->rm_reject = reject;
+               this_icp->n_reject++;
+               icp_rm_deliver_irq(xics, icp, reject);
        }
 
-       /* Pass resends to virtual mode */
+       /* Handle resends in real mode */
        if (resend) {
-               this_icp->rm_action |= XICS_RM_CHECK_RESEND;
-               this_icp->rm_resend_icp = icp;
+               this_icp->n_check_resend++;
+               icp_rm_check_resend(xics, icp);
        }
 
        return check_too_hard(xics, this_icp);
@@ -365,10 +558,13 @@ int kvmppc_rm_h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr)
 
        } while (!icp_rm_try_update(icp, old_state, new_state));
 
-       /* Pass rejects to virtual mode */
+       /*
+        * Check for rejects. They are handled by doing a new delivery
+        * attempt (see comments in icp_rm_deliver_irq).
+        */
        if (reject && reject != XICS_IPI) {
-               icp->rm_action |= XICS_RM_REJECT;
-               icp->rm_reject = reject;
+               icp->n_reject++;
+               icp_rm_deliver_irq(xics, icp, reject);
        }
  bail:
        return check_too_hard(xics, icp);
@@ -416,10 +612,10 @@ int kvmppc_rm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr)
                goto bail;
        state = &ics->irq_state[src];
 
-       /* Still asserted, resend it, we make it look like a reject */
+       /* Still asserted, resend it */
        if (state->asserted) {
-               icp->rm_action |= XICS_RM_REJECT;
-               icp->rm_reject = irq;
+               icp->n_reject++;
+               icp_rm_deliver_irq(xics, icp, irq);
        }
 
        if (!hlist_empty(&vcpu->kvm->irq_ack_notifier_list)) {
index 6cbf1630cb70c9d8b306a7628c91a3c9acf35785..4d70df26c402c7f59f4bc8468f93afec162c1f8d 100644 (file)
@@ -172,6 +172,22 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
 
 kvmppc_primary_no_guest:
        /* We handle this much like a ceded vcpu */
+       /* put the HDEC into the DEC, since HDEC interrupts don't wake us */
+       mfspr   r3, SPRN_HDEC
+       mtspr   SPRN_DEC, r3
+       /*
+        * Make sure the primary has finished the MMU switch.
+        * We should never get here on a secondary thread, but
+        * check it for robustness' sake.
+        */
+       ld      r5, HSTATE_KVM_VCORE(r13)
+65:    lbz     r0, VCORE_IN_GUEST(r5)
+       cmpwi   r0, 0
+       beq     65b
+       /* Set LPCR. */
+       ld      r8,VCORE_LPCR(r5)
+       mtspr   SPRN_LPCR,r8
+       isync
        /* set our bit in napping_threads */
        ld      r5, HSTATE_KVM_VCORE(r13)
        lbz     r7, HSTATE_PTID(r13)
@@ -182,7 +198,7 @@ kvmppc_primary_no_guest:
        or      r3, r3, r0
        stwcx.  r3, 0, r6
        bne     1b
-       /* order napping_threads update vs testing entry_exit_count */
+       /* order napping_threads update vs testing entry_exit_map */
        isync
        li      r12, 0
        lwz     r7, VCORE_ENTRY_EXIT(r5)
@@ -191,6 +207,7 @@ kvmppc_primary_no_guest:
        li      r3, NAPPING_NOVCPU
        stb     r3, HSTATE_NAPPING(r13)
 
+       li      r3, 0           /* Don't wake on privileged (OS) doorbell */
        b       kvm_do_nap
 
 kvm_novcpu_wakeup:
@@ -202,7 +219,7 @@ kvm_novcpu_wakeup:
 
        /* check the wake reason */
        bl      kvmppc_check_wake_reason
-       
+
        /* see if any other thread is already exiting */
        lwz     r0, VCORE_ENTRY_EXIT(r5)
        cmpwi   r0, 0x100
@@ -222,13 +239,37 @@ kvm_novcpu_wakeup:
        cmpdi   r3, 0
        bge     kvm_novcpu_exit
 
+       /* See if our timeslice has expired (HDEC is negative) */
+       mfspr   r0, SPRN_HDEC
+       li      r12, BOOK3S_INTERRUPT_HV_DECREMENTER
+       cmpwi   r0, 0
+       blt     kvm_novcpu_exit
+
        /* Got an IPI but other vcpus aren't yet exiting, must be a latecomer */
        ld      r4, HSTATE_KVM_VCPU(r13)
        cmpdi   r4, 0
-       bne     kvmppc_got_guest
+       beq     kvmppc_primary_no_guest
+
+#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
+       addi    r3, r4, VCPU_TB_RMENTRY
+       bl      kvmhv_start_timing
+#endif
+       b       kvmppc_got_guest
 
 kvm_novcpu_exit:
-       b       hdec_soon
+#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
+       ld      r4, HSTATE_KVM_VCPU(r13)
+       cmpdi   r4, 0
+       beq     13f
+       addi    r3, r4, VCPU_TB_RMEXIT
+       bl      kvmhv_accumulate_time
+#endif
+13:    mr      r3, r12
+       stw     r12, 112-4(r1)
+       bl      kvmhv_commence_exit
+       nop
+       lwz     r12, 112-4(r1)
+       b       kvmhv_switch_to_host
 
 /*
  * We come in here when wakened from nap mode.
@@ -239,9 +280,9 @@ kvm_novcpu_exit:
 kvm_start_guest:
 
        /* Set runlatch bit the minute you wake up from nap */
-       mfspr   r1, SPRN_CTRLF
-       ori     r1, r1, 1
-       mtspr   SPRN_CTRLT, r1
+       mfspr   r0, SPRN_CTRLF
+       ori     r0, r0, 1
+       mtspr   SPRN_CTRLT, r0
 
        ld      r2,PACATOC(r13)
 
@@ -286,26 +327,21 @@ kvm_secondary_got_guest:
        ld      r6, PACA_DSCR(r13)
        std     r6, HSTATE_DSCR(r13)
 
+       /* Order load of vcore, ptid etc. after load of vcpu */
+       lwsync
        bl      kvmppc_hv_entry
 
        /* Back from the guest, go back to nap */
        /* Clear our vcpu pointer so we don't come back in early */
        li      r0, 0
-       std     r0, HSTATE_KVM_VCPU(r13)
        /*
-        * Make sure we clear HSTATE_KVM_VCPU(r13) before incrementing
-        * the nap_count, because once the increment to nap_count is
-        * visible we could be given another vcpu.
+        * Once we clear HSTATE_KVM_VCPU(r13), the code in
+        * kvmppc_run_core() is going to assume that all our vcpu
+        * state is visible in memory.  This lwsync makes sure
+        * that that is true.
         */
        lwsync
-
-       /* increment the nap count and then go to nap mode */
-       ld      r4, HSTATE_KVM_VCORE(r13)
-       addi    r4, r4, VCORE_NAP_COUNT
-51:    lwarx   r3, 0, r4
-       addi    r3, r3, 1
-       stwcx.  r3, 0, r4
-       bne     51b
+       std     r0, HSTATE_KVM_VCPU(r13)
 
 /*
  * At this point we have finished executing in the guest.
@@ -376,6 +412,14 @@ kvmppc_hv_entry:
        li      r6, KVM_GUEST_MODE_HOST_HV
        stb     r6, HSTATE_IN_GUEST(r13)
 
+#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
+       /* Store initial timestamp */
+       cmpdi   r4, 0
+       beq     1f
+       addi    r3, r4, VCPU_TB_RMENTRY
+       bl      kvmhv_start_timing
+1:
+#endif
        /* Clear out SLB */
        li      r6,0
        slbmte  r6,r6
@@ -387,21 +431,23 @@ kvmppc_hv_entry:
         * We don't have to lock against concurrent tlbies,
         * but we do have to coordinate across hardware threads.
         */
-       /* Increment entry count iff exit count is zero. */
-       ld      r5,HSTATE_KVM_VCORE(r13)
-       addi    r9,r5,VCORE_ENTRY_EXIT
-21:    lwarx   r3,0,r9
-       cmpwi   r3,0x100                /* any threads starting to exit? */
+       /* Set bit in entry map iff exit map is zero. */
+       ld      r5, HSTATE_KVM_VCORE(r13)
+       li      r7, 1
+       lbz     r6, HSTATE_PTID(r13)
+       sld     r7, r7, r6
+       addi    r9, r5, VCORE_ENTRY_EXIT
+21:    lwarx   r3, 0, r9
+       cmpwi   r3, 0x100               /* any threads starting to exit? */
        bge     secondary_too_late      /* if so we're too late to the party */
-       addi    r3,r3,1
-       stwcx.  r3,0,r9
+       or      r3, r3, r7
+       stwcx.  r3, 0, r9
        bne     21b
 
        /* Primary thread switches to guest partition. */
        ld      r9,VCORE_KVM(r5)        /* pointer to struct kvm */
-       lbz     r6,HSTATE_PTID(r13)
        cmpwi   r6,0
-       bne     20f
+       bne     10f
        ld      r6,KVM_SDR1(r9)
        lwz     r7,KVM_LPID(r9)
        li      r0,LPID_RSVD            /* switch to reserved LPID */
@@ -472,28 +518,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
 
        li      r0,1
        stb     r0,VCORE_IN_GUEST(r5)   /* signal secondaries to continue */
-       b       10f
-
-       /* Secondary threads wait for primary to have done partition switch */
-20:    lbz     r0,VCORE_IN_GUEST(r5)
-       cmpwi   r0,0
-       beq     20b
-
-       /* Set LPCR and RMOR. */
-10:    ld      r8,VCORE_LPCR(r5)
-       mtspr   SPRN_LPCR,r8
-       ld      r8,KVM_RMOR(r9)
-       mtspr   SPRN_RMOR,r8
-       isync
-
-       /* Check if HDEC expires soon */
-       mfspr   r3,SPRN_HDEC
-       cmpwi   r3,512          /* 1 microsecond */
-       li      r12,BOOK3S_INTERRUPT_HV_DECREMENTER
-       blt     hdec_soon
 
        /* Do we have a guest vcpu to run? */
-       cmpdi   r4, 0
+10:    cmpdi   r4, 0
        beq     kvmppc_primary_no_guest
 kvmppc_got_guest:
 
@@ -818,6 +845,30 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
        clrrdi  r6,r6,1
        mtspr   SPRN_CTRLT,r6
 4:
+       /* Secondary threads wait for primary to have done partition switch */
+       ld      r5, HSTATE_KVM_VCORE(r13)
+       lbz     r6, HSTATE_PTID(r13)
+       cmpwi   r6, 0
+       beq     21f
+       lbz     r0, VCORE_IN_GUEST(r5)
+       cmpwi   r0, 0
+       bne     21f
+       HMT_LOW
+20:    lbz     r0, VCORE_IN_GUEST(r5)
+       cmpwi   r0, 0
+       beq     20b
+       HMT_MEDIUM
+21:
+       /* Set LPCR. */
+       ld      r8,VCORE_LPCR(r5)
+       mtspr   SPRN_LPCR,r8
+       isync
+
+       /* Check if HDEC expires soon */
+       mfspr   r3, SPRN_HDEC
+       cmpwi   r3, 512         /* 1 microsecond */
+       blt     hdec_soon
+
        ld      r6, VCPU_CTR(r4)
        lwz     r7, VCPU_XER(r4)
 
@@ -880,6 +931,12 @@ fast_guest_return:
        li      r9, KVM_GUEST_MODE_GUEST_HV
        stb     r9, HSTATE_IN_GUEST(r13)
 
+#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
+       /* Accumulate timing */
+       addi    r3, r4, VCPU_TB_GUEST
+       bl      kvmhv_accumulate_time
+#endif
+
        /* Enter guest */
 
 BEGIN_FTR_SECTION
@@ -917,6 +974,27 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
        hrfid
        b       .
 
+secondary_too_late:
+       li      r12, 0
+       cmpdi   r4, 0
+       beq     11f
+       stw     r12, VCPU_TRAP(r4)
+#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
+       addi    r3, r4, VCPU_TB_RMEXIT
+       bl      kvmhv_accumulate_time
+#endif
+11:    b       kvmhv_switch_to_host
+
+hdec_soon:
+       li      r12, BOOK3S_INTERRUPT_HV_DECREMENTER
+       stw     r12, VCPU_TRAP(r4)
+       mr      r9, r4
+#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
+       addi    r3, r4, VCPU_TB_RMEXIT
+       bl      kvmhv_accumulate_time
+#endif
+       b       guest_exit_cont
+
 /******************************************************************************
  *                                                                            *
  *                               Exit code                                    *
@@ -1002,6 +1080,16 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
 
        stw     r12,VCPU_TRAP(r9)
 
+#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
+       addi    r3, r9, VCPU_TB_RMINTR
+       mr      r4, r9
+       bl      kvmhv_accumulate_time
+       ld      r5, VCPU_GPR(R5)(r9)
+       ld      r6, VCPU_GPR(R6)(r9)
+       ld      r7, VCPU_GPR(R7)(r9)
+       ld      r8, VCPU_GPR(R8)(r9)
+#endif
+
        /* Save HEIR (HV emulation assist reg) in emul_inst
           if this is an HEI (HV emulation interrupt, e40) */
        li      r3,KVM_INST_FETCH_FAILED
@@ -1028,34 +1116,37 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
        bne     2f
        mfspr   r3,SPRN_HDEC
        cmpwi   r3,0
-       bge     ignore_hdec
+       mr      r4,r9
+       bge     fast_guest_return
 2:
        /* See if this is an hcall we can handle in real mode */
        cmpwi   r12,BOOK3S_INTERRUPT_SYSCALL
        beq     hcall_try_real_mode
 
+       /* Hypervisor doorbell - exit only if host IPI flag set */
+       cmpwi   r12, BOOK3S_INTERRUPT_H_DOORBELL
+       bne     3f
+       lbz     r0, HSTATE_HOST_IPI(r13)
+       beq     4f
+       b       guest_exit_cont
+3:
        /* External interrupt ? */
        cmpwi   r12, BOOK3S_INTERRUPT_EXTERNAL
-       bne+    ext_interrupt_to_host
+       bne+    guest_exit_cont
 
        /* External interrupt, first check for host_ipi. If this is
         * set, we know the host wants us out so let's do it now
         */
        bl      kvmppc_read_intr
        cmpdi   r3, 0
-       bgt     ext_interrupt_to_host
+       bgt     guest_exit_cont
 
        /* Check if any CPU is heading out to the host, if so head out too */
-       ld      r5, HSTATE_KVM_VCORE(r13)
+4:     ld      r5, HSTATE_KVM_VCORE(r13)
        lwz     r0, VCORE_ENTRY_EXIT(r5)
        cmpwi   r0, 0x100
-       bge     ext_interrupt_to_host
-
-       /* Return to guest after delivering any pending interrupt */
        mr      r4, r9
-       b       deliver_guest_interrupt
-
-ext_interrupt_to_host:
+       blt     deliver_guest_interrupt
 
 guest_exit_cont:               /* r9 = vcpu, r12 = trap, r13 = paca */
        /* Save more register state  */
@@ -1065,7 +1156,7 @@ guest_exit_cont:          /* r9 = vcpu, r12 = trap, r13 = paca */
        stw     r7, VCPU_DSISR(r9)
        /* don't overwrite fault_dar/fault_dsisr if HDSI */
        cmpwi   r12,BOOK3S_INTERRUPT_H_DATA_STORAGE
-       beq     6f
+       beq     mc_cont
        std     r6, VCPU_FAULT_DAR(r9)
        stw     r7, VCPU_FAULT_DSISR(r9)
 
@@ -1073,9 +1164,20 @@ guest_exit_cont:         /* r9 = vcpu, r12 = trap, r13 = paca */
        cmpwi   r12, BOOK3S_INTERRUPT_MACHINE_CHECK
        beq     machine_check_realmode
 mc_cont:
+#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
+       addi    r3, r9, VCPU_TB_RMEXIT
+       mr      r4, r9
+       bl      kvmhv_accumulate_time
+#endif
+
+       /* Increment exit count, poke other threads to exit */
+       bl      kvmhv_commence_exit
+       nop
+       ld      r9, HSTATE_KVM_VCPU(r13)
+       lwz     r12, VCPU_TRAP(r9)
 
        /* Save guest CTRL register, set runlatch to 1 */
-6:     mfspr   r6,SPRN_CTRLF
+       mfspr   r6,SPRN_CTRLF
        stw     r6,VCPU_CTRL(r9)
        andi.   r0,r6,1
        bne     4f
@@ -1417,68 +1519,14 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
        slbia
        ptesync
 
-hdec_soon:                     /* r12 = trap, r13 = paca */
        /*
         * POWER7/POWER8 guest -> host partition switch code.
         * We don't have to lock against tlbies but we do
         * have to coordinate the hardware threads.
         */
-       /* Increment the threads-exiting-guest count in the 0xff00
-          bits of vcore->entry_exit_count */
-       ld      r5,HSTATE_KVM_VCORE(r13)
-       addi    r6,r5,VCORE_ENTRY_EXIT
-41:    lwarx   r3,0,r6
-       addi    r0,r3,0x100
-       stwcx.  r0,0,r6
-       bne     41b
-       isync           /* order stwcx. vs. reading napping_threads */
-
-       /*
-        * At this point we have an interrupt that we have to pass
-        * up to the kernel or qemu; we can't handle it in real mode.
-        * Thus we have to do a partition switch, so we have to
-        * collect the other threads, if we are the first thread
-        * to take an interrupt.  To do this, we set the HDEC to 0,
-        * which causes an HDEC interrupt in all threads within 2ns
-        * because the HDEC register is shared between all 4 threads.
-        * However, we don't need to bother if this is an HDEC
-        * interrupt, since the other threads will already be on their
-        * way here in that case.
-        */
-       cmpwi   r3,0x100        /* Are we the first here? */
-       bge     43f
-       cmpwi   r12,BOOK3S_INTERRUPT_HV_DECREMENTER
-       beq     40f
-       li      r0,0
-       mtspr   SPRN_HDEC,r0
-40:
-       /*
-        * Send an IPI to any napping threads, since an HDEC interrupt
-        * doesn't wake CPUs up from nap.
-        */
-       lwz     r3,VCORE_NAPPING_THREADS(r5)
-       lbz     r4,HSTATE_PTID(r13)
-       li      r0,1
-       sld     r0,r0,r4
-       andc.   r3,r3,r0                /* no sense IPI'ing ourselves */
-       beq     43f
-       /* Order entry/exit update vs. IPIs */
-       sync
-       mulli   r4,r4,PACA_SIZE         /* get paca for thread 0 */
-       subf    r6,r4,r13
-42:    andi.   r0,r3,1
-       beq     44f
-       ld      r8,HSTATE_XICS_PHYS(r6) /* get thread's XICS reg addr */
-       li      r0,IPI_PRIORITY
-       li      r7,XICS_MFRR
-       stbcix  r0,r7,r8                /* trigger the IPI */
-44:    srdi.   r3,r3,1
-       addi    r6,r6,PACA_SIZE
-       bne     42b
-
-secondary_too_late:
+kvmhv_switch_to_host:
        /* Secondary threads wait for primary to do partition switch */
-43:    ld      r5,HSTATE_KVM_VCORE(r13)
+       ld      r5,HSTATE_KVM_VCORE(r13)
        ld      r4,VCORE_KVM(r5)        /* pointer to struct kvm */
        lbz     r3,HSTATE_PTID(r13)
        cmpwi   r3,0
@@ -1562,6 +1610,15 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
 1:     addi    r8,r8,16
        .endr
 
+#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
+       /* Finish timing, if we have a vcpu */
+       ld      r4, HSTATE_KVM_VCPU(r13)
+       cmpdi   r4, 0
+       li      r3, 0
+       beq     2f
+       bl      kvmhv_accumulate_time
+2:
+#endif
        /* Unset guest mode */
        li      r0, KVM_GUEST_MODE_NONE
        stb     r0, HSTATE_IN_GUEST(r13)
@@ -1696,8 +1753,10 @@ kvmppc_hisi:
  * Returns to the guest if we handle it, or continues on up to
  * the kernel if we can't (i.e. if we don't have a handler for
  * it, or if the handler returns H_TOO_HARD).
+ *
+ * r5 - r8 contain hcall args,
+ * r9 = vcpu, r10 = pc, r11 = msr, r12 = trap, r13 = paca
  */
-       .globl  hcall_try_real_mode
 hcall_try_real_mode:
        ld      r3,VCPU_GPR(R3)(r9)
        andi.   r0,r11,MSR_PR
@@ -1839,13 +1898,124 @@ hcall_real_table:
        .long   0               /* 0x12c */
        .long   0               /* 0x130 */
        .long   DOTSYM(kvmppc_h_set_xdabr) - hcall_real_table
+       .long   0               /* 0x138 */
+       .long   0               /* 0x13c */
+       .long   0               /* 0x140 */
+       .long   0               /* 0x144 */
+       .long   0               /* 0x148 */
+       .long   0               /* 0x14c */
+       .long   0               /* 0x150 */
+       .long   0               /* 0x154 */
+       .long   0               /* 0x158 */
+       .long   0               /* 0x15c */
+       .long   0               /* 0x160 */
+       .long   0               /* 0x164 */
+       .long   0               /* 0x168 */
+       .long   0               /* 0x16c */
+       .long   0               /* 0x170 */
+       .long   0               /* 0x174 */
+       .long   0               /* 0x178 */
+       .long   0               /* 0x17c */
+       .long   0               /* 0x180 */
+       .long   0               /* 0x184 */
+       .long   0               /* 0x188 */
+       .long   0               /* 0x18c */
+       .long   0               /* 0x190 */
+       .long   0               /* 0x194 */
+       .long   0               /* 0x198 */
+       .long   0               /* 0x19c */
+       .long   0               /* 0x1a0 */
+       .long   0               /* 0x1a4 */
+       .long   0               /* 0x1a8 */
+       .long   0               /* 0x1ac */
+       .long   0               /* 0x1b0 */
+       .long   0               /* 0x1b4 */
+       .long   0               /* 0x1b8 */
+       .long   0               /* 0x1bc */
+       .long   0               /* 0x1c0 */
+       .long   0               /* 0x1c4 */
+       .long   0               /* 0x1c8 */
+       .long   0               /* 0x1cc */
+       .long   0               /* 0x1d0 */
+       .long   0               /* 0x1d4 */
+       .long   0               /* 0x1d8 */
+       .long   0               /* 0x1dc */
+       .long   0               /* 0x1e0 */
+       .long   0               /* 0x1e4 */
+       .long   0               /* 0x1e8 */
+       .long   0               /* 0x1ec */
+       .long   0               /* 0x1f0 */
+       .long   0               /* 0x1f4 */
+       .long   0               /* 0x1f8 */
+       .long   0               /* 0x1fc */
+       .long   0               /* 0x200 */
+       .long   0               /* 0x204 */
+       .long   0               /* 0x208 */
+       .long   0               /* 0x20c */
+       .long   0               /* 0x210 */
+       .long   0               /* 0x214 */
+       .long   0               /* 0x218 */
+       .long   0               /* 0x21c */
+       .long   0               /* 0x220 */
+       .long   0               /* 0x224 */
+       .long   0               /* 0x228 */
+       .long   0               /* 0x22c */
+       .long   0               /* 0x230 */
+       .long   0               /* 0x234 */
+       .long   0               /* 0x238 */
+       .long   0               /* 0x23c */
+       .long   0               /* 0x240 */
+       .long   0               /* 0x244 */
+       .long   0               /* 0x248 */
+       .long   0               /* 0x24c */
+       .long   0               /* 0x250 */
+       .long   0               /* 0x254 */
+       .long   0               /* 0x258 */
+       .long   0               /* 0x25c */
+       .long   0               /* 0x260 */
+       .long   0               /* 0x264 */
+       .long   0               /* 0x268 */
+       .long   0               /* 0x26c */
+       .long   0               /* 0x270 */
+       .long   0               /* 0x274 */
+       .long   0               /* 0x278 */
+       .long   0               /* 0x27c */
+       .long   0               /* 0x280 */
+       .long   0               /* 0x284 */
+       .long   0               /* 0x288 */
+       .long   0               /* 0x28c */
+       .long   0               /* 0x290 */
+       .long   0               /* 0x294 */
+       .long   0               /* 0x298 */
+       .long   0               /* 0x29c */
+       .long   0               /* 0x2a0 */
+       .long   0               /* 0x2a4 */
+       .long   0               /* 0x2a8 */
+       .long   0               /* 0x2ac */
+       .long   0               /* 0x2b0 */
+       .long   0               /* 0x2b4 */
+       .long   0               /* 0x2b8 */
+       .long   0               /* 0x2bc */
+       .long   0               /* 0x2c0 */
+       .long   0               /* 0x2c4 */
+       .long   0               /* 0x2c8 */
+       .long   0               /* 0x2cc */
+       .long   0               /* 0x2d0 */
+       .long   0               /* 0x2d4 */
+       .long   0               /* 0x2d8 */
+       .long   0               /* 0x2dc */
+       .long   0               /* 0x2e0 */
+       .long   0               /* 0x2e4 */
+       .long   0               /* 0x2e8 */
+       .long   0               /* 0x2ec */
+       .long   0               /* 0x2f0 */
+       .long   0               /* 0x2f4 */
+       .long   0               /* 0x2f8 */
+       .long   0               /* 0x2fc */
+       .long   DOTSYM(kvmppc_h_random) - hcall_real_table
        .globl  hcall_real_table_end
 hcall_real_table_end:
 
-ignore_hdec:
-       mr      r4,r9
-       b       fast_guest_return
-
 _GLOBAL(kvmppc_h_set_xdabr)
        andi.   r0, r5, DABRX_USER | DABRX_KERNEL
        beq     6f
@@ -1884,7 +2054,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
        li      r3, 0
        blr
 
-_GLOBAL(kvmppc_h_cede)
+_GLOBAL(kvmppc_h_cede)         /* r3 = vcpu pointer, r11 = msr, r13 = paca */
        ori     r11,r11,MSR_EE
        std     r11,VCPU_MSR(r3)
        li      r0,1
@@ -1893,8 +2063,8 @@ _GLOBAL(kvmppc_h_cede)
        lbz     r5,VCPU_PRODDED(r3)
        cmpwi   r5,0
        bne     kvm_cede_prodded
-       li      r0,0            /* set trap to 0 to say hcall is handled */
-       stw     r0,VCPU_TRAP(r3)
+       li      r12,0           /* set trap to 0 to say hcall is handled */
+       stw     r12,VCPU_TRAP(r3)
        li      r0,H_SUCCESS
        std     r0,VCPU_GPR(R3)(r3)
 
@@ -1912,12 +2082,11 @@ _GLOBAL(kvmppc_h_cede)
        addi    r6,r5,VCORE_NAPPING_THREADS
 31:    lwarx   r4,0,r6
        or      r4,r4,r0
-       PPC_POPCNTW(R7,R4)
-       cmpw    r7,r8
-       bge     kvm_cede_exit
+       cmpw    r4,r8
+       beq     kvm_cede_exit
        stwcx.  r4,0,r6
        bne     31b
-       /* order napping_threads update vs testing entry_exit_count */
+       /* order napping_threads update vs testing entry_exit_map */
        isync
        li      r0,NAPPING_CEDE
        stb     r0,HSTATE_NAPPING(r13)
@@ -1954,22 +2123,53 @@ _GLOBAL(kvmppc_h_cede)
        /* save FP state */
        bl      kvmppc_save_fp
 
+       /*
+        * Set DEC to the smaller of DEC and HDEC, so that we wake
+        * no later than the end of our timeslice (HDEC interrupts
+        * don't wake us from nap).
+        */
+       mfspr   r3, SPRN_DEC
+       mfspr   r4, SPRN_HDEC
+       mftb    r5
+       cmpw    r3, r4
+       ble     67f
+       mtspr   SPRN_DEC, r4
+67:
+       /* save expiry time of guest decrementer */
+       extsw   r3, r3
+       add     r3, r3, r5
+       ld      r4, HSTATE_KVM_VCPU(r13)
+       ld      r5, HSTATE_KVM_VCORE(r13)
+       ld      r6, VCORE_TB_OFFSET(r5)
+       subf    r3, r6, r3      /* convert to host TB value */
+       std     r3, VCPU_DEC_EXPIRES(r4)
+
+#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
+       ld      r4, HSTATE_KVM_VCPU(r13)
+       addi    r3, r4, VCPU_TB_CEDE
+       bl      kvmhv_accumulate_time
+#endif
+
+       lis     r3, LPCR_PECEDP@h       /* Do wake on privileged doorbell */
+
        /*
         * Take a nap until a decrementer or external or doobell interrupt
-        * occurs, with PECE1, PECE0 and PECEDP set in LPCR. Also clear the
-        * runlatch bit before napping.
+        * occurs, with PECE1 and PECE0 set in LPCR.
+        * On POWER8, set PECEDH, and if we are ceding, also set PECEDP.
+        * Also clear the runlatch bit before napping.
         */
 kvm_do_nap:
-       mfspr   r2, SPRN_CTRLF
-       clrrdi  r2, r2, 1
-       mtspr   SPRN_CTRLT, r2
+       mfspr   r0, SPRN_CTRLF
+       clrrdi  r0, r0, 1
+       mtspr   SPRN_CTRLT, r0
 
        li      r0,1
        stb     r0,HSTATE_HWTHREAD_REQ(r13)
        mfspr   r5,SPRN_LPCR
        ori     r5,r5,LPCR_PECE0 | LPCR_PECE1
 BEGIN_FTR_SECTION
-       oris    r5,r5,LPCR_PECEDP@h
+       ori     r5, r5, LPCR_PECEDH
+       rlwimi  r5, r3, 0, LPCR_PECEDP
 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
        mtspr   SPRN_LPCR,r5
        isync
@@ -1994,9 +2194,23 @@ kvm_end_cede:
        /* Woken by external or decrementer interrupt */
        ld      r1, HSTATE_HOST_R1(r13)
 
+#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
+       addi    r3, r4, VCPU_TB_RMINTR
+       bl      kvmhv_accumulate_time
+#endif
+
        /* load up FP state */
        bl      kvmppc_load_fp
 
+       /* Restore guest decrementer */
+       ld      r3, VCPU_DEC_EXPIRES(r4)
+       ld      r5, HSTATE_KVM_VCORE(r13)
+       ld      r6, VCORE_TB_OFFSET(r5)
+       add     r3, r3, r6      /* convert host TB to guest TB value */
+       mftb    r7
+       subf    r3, r7, r3
+       mtspr   SPRN_DEC, r3
+
        /* Load NV GPRS */
        ld      r14, VCPU_GPR(R14)(r4)
        ld      r15, VCPU_GPR(R15)(r4)
@@ -2057,7 +2271,8 @@ kvm_cede_prodded:
 
        /* we've ceded but we want to give control to the host */
 kvm_cede_exit:
-       b       hcall_real_fallback
+       ld      r9, HSTATE_KVM_VCPU(r13)
+       b       guest_exit_cont
 
        /* Try to handle a machine check in real mode */
 machine_check_realmode:
@@ -2089,13 +2304,14 @@ machine_check_realmode:
 
 /*
  * Check the reason we woke from nap, and take appropriate action.
- * Returns:
+ * Returns (in r3):
  *     0 if nothing needs to be done
  *     1 if something happened that needs to be handled by the host
- *     -1 if there was a guest wakeup (IPI)
+ *     -1 if there was a guest wakeup (IPI or msgsnd)
  *
  * Also sets r12 to the interrupt vector for any interrupt that needs
  * to be handled now by the host (0x500 for external interrupt), or zero.
+ * Modifies r0, r6, r7, r8.
  */
 kvmppc_check_wake_reason:
        mfspr   r6, SPRN_SRR1
@@ -2122,7 +2338,15 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
 
        /* hypervisor doorbell */
 3:     li      r12, BOOK3S_INTERRUPT_H_DOORBELL
+       /* see if it's a host IPI */
        li      r3, 1
+       lbz     r0, HSTATE_HOST_IPI(r13)
+       cmpwi   r0, 0
+       bnelr
+       /* if not, clear it and return -1 */
+       lis     r6, (PPC_DBELL_SERVER << (63-36))@h
+       PPC_MSGCLR(6)
+       li      r3, -1
        blr
 
 /*
@@ -2131,6 +2355,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
  *     0 if no interrupt is pending
  *     1 if an interrupt is pending that needs to be handled by the host
  *     -1 if there was a guest wakeup IPI (which has now been cleared)
+ * Modifies r0, r6, r7, r8, returns value in r3.
  */
 kvmppc_read_intr:
        /* see if a host IPI is pending */
@@ -2185,6 +2410,7 @@ kvmppc_read_intr:
        bne-    43f
 
        /* OK, it's an IPI for us */
+       li      r12, 0
        li      r3, -1
 1:     blr
 
@@ -2314,3 +2540,62 @@ kvmppc_fix_pmao:
        mtspr   SPRN_PMC6, r3
        isync
        blr
+
+#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
+/*
+ * Start timing an activity
+ * r3 = pointer to time accumulation struct, r4 = vcpu
+ */
+kvmhv_start_timing:
+       ld      r5, HSTATE_KVM_VCORE(r13)
+       lbz     r6, VCORE_IN_GUEST(r5)
+       cmpwi   r6, 0
+       beq     5f                              /* if in guest, need to */
+       ld      r6, VCORE_TB_OFFSET(r5)         /* subtract timebase offset */
+5:     mftb    r5
+       subf    r5, r6, r5
+       std     r3, VCPU_CUR_ACTIVITY(r4)
+       std     r5, VCPU_ACTIVITY_START(r4)
+       blr
+
+/*
+ * Accumulate time to one activity and start another.
+ * r3 = pointer to new time accumulation struct, r4 = vcpu
+ */
+kvmhv_accumulate_time:
+       ld      r5, HSTATE_KVM_VCORE(r13)
+       lbz     r8, VCORE_IN_GUEST(r5)
+       cmpwi   r8, 0
+       beq     4f                              /* if in guest, need to */
+       ld      r8, VCORE_TB_OFFSET(r5)         /* subtract timebase offset */
+4:     ld      r5, VCPU_CUR_ACTIVITY(r4)
+       ld      r6, VCPU_ACTIVITY_START(r4)
+       std     r3, VCPU_CUR_ACTIVITY(r4)
+       mftb    r7
+       subf    r7, r8, r7
+       std     r7, VCPU_ACTIVITY_START(r4)
+       cmpdi   r5, 0
+       beqlr
+       subf    r3, r6, r7
+       ld      r8, TAS_SEQCOUNT(r5)
+       cmpdi   r8, 0
+       addi    r8, r8, 1
+       std     r8, TAS_SEQCOUNT(r5)
+       lwsync
+       ld      r7, TAS_TOTAL(r5)
+       add     r7, r7, r3
+       std     r7, TAS_TOTAL(r5)
+       ld      r6, TAS_MIN(r5)
+       ld      r7, TAS_MAX(r5)
+       beq     3f
+       cmpd    r3, r6
+       bge     1f
+3:     std     r3, TAS_MIN(r5)
+1:     cmpd    r3, r7
+       ble     2f
+       std     r3, TAS_MAX(r5)
+2:     lwsync
+       addi    r8, r8, 1
+       std     r8, TAS_SEQCOUNT(r5)
+       blr
+#endif
index ce3c893d509b17b3611e6fe5050a50424ba5d83d..f2c75a1e0536c7b13fdb329be3067691f3f2c284 100644 (file)
@@ -258,6 +258,28 @@ static int kvmppc_h_pr_put_tce(struct kvm_vcpu *vcpu)
        return EMULATE_DONE;
 }
 
+static int kvmppc_h_pr_logical_ci_load(struct kvm_vcpu *vcpu)
+{
+       long rc;
+
+       rc = kvmppc_h_logical_ci_load(vcpu);
+       if (rc == H_TOO_HARD)
+               return EMULATE_FAIL;
+       kvmppc_set_gpr(vcpu, 3, rc);
+       return EMULATE_DONE;
+}
+
+static int kvmppc_h_pr_logical_ci_store(struct kvm_vcpu *vcpu)
+{
+       long rc;
+
+       rc = kvmppc_h_logical_ci_store(vcpu);
+       if (rc == H_TOO_HARD)
+               return EMULATE_FAIL;
+       kvmppc_set_gpr(vcpu, 3, rc);
+       return EMULATE_DONE;
+}
+
 static int kvmppc_h_pr_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd)
 {
        long rc = kvmppc_xics_hcall(vcpu, cmd);
@@ -290,6 +312,10 @@ int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd)
                clear_bit(KVM_REQ_UNHALT, &vcpu->requests);
                vcpu->stat.halt_wakeup++;
                return EMULATE_DONE;
+       case H_LOGICAL_CI_LOAD:
+               return kvmppc_h_pr_logical_ci_load(vcpu);
+       case H_LOGICAL_CI_STORE:
+               return kvmppc_h_pr_logical_ci_store(vcpu);
        case H_XIRR:
        case H_CPPR:
        case H_EOI:
@@ -323,6 +349,8 @@ int kvmppc_hcall_impl_pr(unsigned long cmd)
        case H_BULK_REMOVE:
        case H_PUT_TCE:
        case H_CEDE:
+       case H_LOGICAL_CI_LOAD:
+       case H_LOGICAL_CI_STORE:
 #ifdef CONFIG_KVM_XICS
        case H_XIRR:
        case H_CPPR:
index a4a8d9f0dcb735d6d16057aeb81fc9e4ac1bb5e1..c6ca7db646735428fb14bde6af9ed1eb68b98351 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/err.h>
 #include <linux/gfp.h>
 #include <linux/anon_inodes.h>
+#include <linux/spinlock.h>
 
 #include <asm/uaccess.h>
 #include <asm/kvm_book3s.h>
@@ -39,7 +40,7 @@
  * LOCKING
  * =======
  *
- * Each ICS has a mutex protecting the information about the IRQ
+ * Each ICS has a spin lock protecting the information about the IRQ
  * sources and avoiding simultaneous deliveries if the same interrupt.
  *
  * ICP operations are done via a single compare & swap transaction
@@ -109,7 +110,10 @@ static void ics_check_resend(struct kvmppc_xics *xics, struct kvmppc_ics *ics,
 {
        int i;
 
-       mutex_lock(&ics->lock);
+       unsigned long flags;
+
+       local_irq_save(flags);
+       arch_spin_lock(&ics->lock);
 
        for (i = 0; i < KVMPPC_XICS_IRQ_PER_ICS; i++) {
                struct ics_irq_state *state = &ics->irq_state[i];
@@ -120,12 +124,15 @@ static void ics_check_resend(struct kvmppc_xics *xics, struct kvmppc_ics *ics,
                XICS_DBG("resend %#x prio %#x\n", state->number,
                              state->priority);
 
-               mutex_unlock(&ics->lock);
+               arch_spin_unlock(&ics->lock);
+               local_irq_restore(flags);
                icp_deliver_irq(xics, icp, state->number);
-               mutex_lock(&ics->lock);
+               local_irq_save(flags);
+               arch_spin_lock(&ics->lock);
        }
 
-       mutex_unlock(&ics->lock);
+       arch_spin_unlock(&ics->lock);
+       local_irq_restore(flags);
 }
 
 static bool write_xive(struct kvmppc_xics *xics, struct kvmppc_ics *ics,
@@ -133,8 +140,10 @@ static bool write_xive(struct kvmppc_xics *xics, struct kvmppc_ics *ics,
                       u32 server, u32 priority, u32 saved_priority)
 {
        bool deliver;
+       unsigned long flags;
 
-       mutex_lock(&ics->lock);
+       local_irq_save(flags);
+       arch_spin_lock(&ics->lock);
 
        state->server = server;
        state->priority = priority;
@@ -145,7 +154,8 @@ static bool write_xive(struct kvmppc_xics *xics, struct kvmppc_ics *ics,
                deliver = true;
        }
 
-       mutex_unlock(&ics->lock);
+       arch_spin_unlock(&ics->lock);
+       local_irq_restore(flags);
 
        return deliver;
 }
@@ -186,6 +196,7 @@ int kvmppc_xics_get_xive(struct kvm *kvm, u32 irq, u32 *server, u32 *priority)
        struct kvmppc_ics *ics;
        struct ics_irq_state *state;
        u16 src;
+       unsigned long flags;
 
        if (!xics)
                return -ENODEV;
@@ -195,10 +206,12 @@ int kvmppc_xics_get_xive(struct kvm *kvm, u32 irq, u32 *server, u32 *priority)
                return -EINVAL;
        state = &ics->irq_state[src];
 
-       mutex_lock(&ics->lock);
+       local_irq_save(flags);
+       arch_spin_lock(&ics->lock);
        *server = state->server;
        *priority = state->priority;
-       mutex_unlock(&ics->lock);
+       arch_spin_unlock(&ics->lock);
+       local_irq_restore(flags);
 
        return 0;
 }
@@ -365,6 +378,7 @@ static void icp_deliver_irq(struct kvmppc_xics *xics, struct kvmppc_icp *icp,
        struct kvmppc_ics *ics;
        u32 reject;
        u16 src;
+       unsigned long flags;
 
        /*
         * This is used both for initial delivery of an interrupt and
@@ -391,7 +405,8 @@ static void icp_deliver_irq(struct kvmppc_xics *xics, struct kvmppc_icp *icp,
        state = &ics->irq_state[src];
 
        /* Get a lock on the ICS */
-       mutex_lock(&ics->lock);
+       local_irq_save(flags);
+       arch_spin_lock(&ics->lock);
 
        /* Get our server */
        if (!icp || state->server != icp->server_num) {
@@ -434,7 +449,7 @@ static void icp_deliver_irq(struct kvmppc_xics *xics, struct kvmppc_icp *icp,
         *
         * Note that if successful, the new delivery might have itself
         * rejected an interrupt that was "delivered" before we took the
-        * icp mutex.
+        * ics spin lock.
         *
         * In this case we do the whole sequence all over again for the
         * new guy. We cannot assume that the rejected interrupt is less
@@ -448,7 +463,8 @@ static void icp_deliver_irq(struct kvmppc_xics *xics, struct kvmppc_icp *icp,
                 * Delivery was successful, did we reject somebody else ?
                 */
                if (reject && reject != XICS_IPI) {
-                       mutex_unlock(&ics->lock);
+                       arch_spin_unlock(&ics->lock);
+                       local_irq_restore(flags);
                        new_irq = reject;
                        goto again;
                }
@@ -468,12 +484,14 @@ static void icp_deliver_irq(struct kvmppc_xics *xics, struct kvmppc_icp *icp,
                 */
                smp_mb();
                if (!icp->state.need_resend) {
-                       mutex_unlock(&ics->lock);
+                       arch_spin_unlock(&ics->lock);
+                       local_irq_restore(flags);
                        goto again;
                }
        }
  out:
-       mutex_unlock(&ics->lock);
+       arch_spin_unlock(&ics->lock);
+       local_irq_restore(flags);
 }
 
 static void icp_down_cppr(struct kvmppc_xics *xics, struct kvmppc_icp *icp,
@@ -802,14 +820,22 @@ static noinline int kvmppc_xics_rm_complete(struct kvm_vcpu *vcpu, u32 hcall)
        XICS_DBG("XICS_RM: H_%x completing, act: %x state: %lx tgt: %p\n",
                 hcall, icp->rm_action, icp->rm_dbgstate.raw, icp->rm_dbgtgt);
 
-       if (icp->rm_action & XICS_RM_KICK_VCPU)
+       if (icp->rm_action & XICS_RM_KICK_VCPU) {
+               icp->n_rm_kick_vcpu++;
                kvmppc_fast_vcpu_kick(icp->rm_kick_target);
-       if (icp->rm_action & XICS_RM_CHECK_RESEND)
+       }
+       if (icp->rm_action & XICS_RM_CHECK_RESEND) {
+               icp->n_rm_check_resend++;
                icp_check_resend(xics, icp->rm_resend_icp);
-       if (icp->rm_action & XICS_RM_REJECT)
+       }
+       if (icp->rm_action & XICS_RM_REJECT) {
+               icp->n_rm_reject++;
                icp_deliver_irq(xics, icp, icp->rm_reject);
-       if (icp->rm_action & XICS_RM_NOTIFY_EOI)
+       }
+       if (icp->rm_action & XICS_RM_NOTIFY_EOI) {
+               icp->n_rm_notify_eoi++;
                kvm_notify_acked_irq(vcpu->kvm, 0, icp->rm_eoied_irq);
+       }
 
        icp->rm_action = 0;
 
@@ -872,10 +898,21 @@ static int xics_debug_show(struct seq_file *m, void *private)
        struct kvm *kvm = xics->kvm;
        struct kvm_vcpu *vcpu;
        int icsid, i;
+       unsigned long flags;
+       unsigned long t_rm_kick_vcpu, t_rm_check_resend;
+       unsigned long t_rm_reject, t_rm_notify_eoi;
+       unsigned long t_reject, t_check_resend;
 
        if (!kvm)
                return 0;
 
+       t_rm_kick_vcpu = 0;
+       t_rm_notify_eoi = 0;
+       t_rm_check_resend = 0;
+       t_rm_reject = 0;
+       t_check_resend = 0;
+       t_reject = 0;
+
        seq_printf(m, "=========\nICP state\n=========\n");
 
        kvm_for_each_vcpu(i, vcpu, kvm) {
@@ -890,8 +927,19 @@ static int xics_debug_show(struct seq_file *m, void *private)
                           icp->server_num, state.xisr,
                           state.pending_pri, state.cppr, state.mfrr,
                           state.out_ee, state.need_resend);
+               t_rm_kick_vcpu += icp->n_rm_kick_vcpu;
+               t_rm_notify_eoi += icp->n_rm_notify_eoi;
+               t_rm_check_resend += icp->n_rm_check_resend;
+               t_rm_reject += icp->n_rm_reject;
+               t_check_resend += icp->n_check_resend;
+               t_reject += icp->n_reject;
        }
 
+       seq_printf(m, "ICP Guest->Host totals: kick_vcpu=%lu check_resend=%lu reject=%lu notify_eoi=%lu\n",
+                       t_rm_kick_vcpu, t_rm_check_resend,
+                       t_rm_reject, t_rm_notify_eoi);
+       seq_printf(m, "ICP Real Mode totals: check_resend=%lu resend=%lu\n",
+                       t_check_resend, t_reject);
        for (icsid = 0; icsid <= KVMPPC_XICS_MAX_ICS_ID; icsid++) {
                struct kvmppc_ics *ics = xics->ics[icsid];
 
@@ -901,7 +949,8 @@ static int xics_debug_show(struct seq_file *m, void *private)
                seq_printf(m, "=========\nICS state for ICS 0x%x\n=========\n",
                           icsid);
 
-               mutex_lock(&ics->lock);
+               local_irq_save(flags);
+               arch_spin_lock(&ics->lock);
 
                for (i = 0; i < KVMPPC_XICS_IRQ_PER_ICS; i++) {
                        struct ics_irq_state *irq = &ics->irq_state[i];
@@ -912,7 +961,8 @@ static int xics_debug_show(struct seq_file *m, void *private)
                                   irq->resend, irq->masked_pending);
 
                }
-               mutex_unlock(&ics->lock);
+               arch_spin_unlock(&ics->lock);
+               local_irq_restore(flags);
        }
        return 0;
 }
@@ -965,7 +1015,6 @@ static struct kvmppc_ics *kvmppc_xics_create_ics(struct kvm *kvm,
        if (!ics)
                goto out;
 
-       mutex_init(&ics->lock);
        ics->icsid = icsid;
 
        for (i = 0; i < KVMPPC_XICS_IRQ_PER_ICS; i++) {
@@ -1107,13 +1156,15 @@ static int xics_get_source(struct kvmppc_xics *xics, long irq, u64 addr)
        u64 __user *ubufp = (u64 __user *) addr;
        u16 idx;
        u64 val, prio;
+       unsigned long flags;
 
        ics = kvmppc_xics_find_ics(xics, irq, &idx);
        if (!ics)
                return -ENOENT;
 
        irqp = &ics->irq_state[idx];
-       mutex_lock(&ics->lock);
+       local_irq_save(flags);
+       arch_spin_lock(&ics->lock);
        ret = -ENOENT;
        if (irqp->exists) {
                val = irqp->server;
@@ -1129,7 +1180,8 @@ static int xics_get_source(struct kvmppc_xics *xics, long irq, u64 addr)
                        val |= KVM_XICS_PENDING;
                ret = 0;
        }
-       mutex_unlock(&ics->lock);
+       arch_spin_unlock(&ics->lock);
+       local_irq_restore(flags);
 
        if (!ret && put_user(val, ubufp))
                ret = -EFAULT;
@@ -1146,6 +1198,7 @@ static int xics_set_source(struct kvmppc_xics *xics, long irq, u64 addr)
        u64 val;
        u8 prio;
        u32 server;
+       unsigned long flags;
 
        if (irq < KVMPPC_XICS_FIRST_IRQ || irq >= KVMPPC_XICS_NR_IRQS)
                return -ENOENT;
@@ -1166,7 +1219,8 @@ static int xics_set_source(struct kvmppc_xics *xics, long irq, u64 addr)
            kvmppc_xics_find_server(xics->kvm, server) == NULL)
                return -EINVAL;
 
-       mutex_lock(&ics->lock);
+       local_irq_save(flags);
+       arch_spin_lock(&ics->lock);
        irqp->server = server;
        irqp->saved_priority = prio;
        if (val & KVM_XICS_MASKED)
@@ -1178,7 +1232,8 @@ static int xics_set_source(struct kvmppc_xics *xics, long irq, u64 addr)
        if ((val & KVM_XICS_PENDING) && (val & KVM_XICS_LEVEL_SENSITIVE))
                irqp->asserted = 1;
        irqp->exists = 1;
-       mutex_unlock(&ics->lock);
+       arch_spin_unlock(&ics->lock);
+       local_irq_restore(flags);
 
        if (val & KVM_XICS_PENDING)
                icp_deliver_irq(xics, NULL, irqp->number);
index 73f0f2723c074ec2aa292bc4b0f20958666a70c8..56ea44f9867fa6a59364e2c252bf57e4cbfc1da5 100644 (file)
@@ -78,13 +78,22 @@ struct kvmppc_icp {
        u32  rm_reject;
        u32  rm_eoied_irq;
 
+       /* Counters for each reason we exited real mode */
+       unsigned long n_rm_kick_vcpu;
+       unsigned long n_rm_check_resend;
+       unsigned long n_rm_reject;
+       unsigned long n_rm_notify_eoi;
+       /* Counters for handling ICP processing in real mode */
+       unsigned long n_check_resend;
+       unsigned long n_reject;
+
        /* Debug stuff for real mode */
        union kvmppc_icp_state rm_dbgstate;
        struct kvm_vcpu *rm_dbgtgt;
 };
 
 struct kvmppc_ics {
-       struct mutex lock;
+       arch_spinlock_t lock;
        u16 icsid;
        struct ics_irq_state irq_state[KVMPPC_XICS_IRQ_PER_ICS];
 };
@@ -96,6 +105,8 @@ struct kvmppc_xics {
        u32 max_icsid;
        bool real_mode;
        bool real_mode_dbg;
+       u32 err_noics;
+       u32 err_noicp;
        struct kvmppc_ics *ics[KVMPPC_XICS_MAX_ICS_ID + 1];
 };
 
index cc536d4a75eff6c19dfa44b8d20db1ebfa50b90c..4d33e199edcc6769fa94d56a7a0a690a1dd4447c 100644 (file)
@@ -338,6 +338,7 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
        pte_t *ptep;
        unsigned int wimg = 0;
        pgd_t *pgdir;
+       unsigned long flags;
 
        /* used to check for invalidations in progress */
        mmu_seq = kvm->mmu_notifier_seq;
@@ -468,15 +469,28 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
 
 
        pgdir = vcpu_e500->vcpu.arch.pgdir;
-       ptep = lookup_linux_ptep(pgdir, hva, &tsize_pages);
-       if (pte_present(*ptep))
-               wimg = (*ptep >> PTE_WIMGE_SHIFT) & MAS2_WIMGE_MASK;
-       else {
-               if (printk_ratelimit())
-                       pr_err("%s: pte not present: gfn %lx, pfn %lx\n",
-                               __func__, (long)gfn, pfn);
-               ret = -EINVAL;
-               goto out;
+       /*
+        * We are just looking at the wimg bits, so we don't
+        * care much about the trans splitting bit.
+        * We are holding kvm->mmu_lock so a notifier invalidate
+        * can't run hence pfn won't change.
+        */
+       local_irq_save(flags);
+       ptep = find_linux_pte_or_hugepte(pgdir, hva, NULL);
+       if (ptep) {
+               pte_t pte = READ_ONCE(*ptep);
+
+               if (pte_present(pte)) {
+                       wimg = (pte_val(pte) >> PTE_WIMGE_SHIFT) &
+                               MAS2_WIMGE_MASK;
+                       local_irq_restore(flags);
+               } else {
+                       local_irq_restore(flags);
+                       pr_err_ratelimited("%s: pte not present: gfn %lx,pfn %lx\n",
+                                          __func__, (long)gfn, pfn);
+                       ret = -EINVAL;
+                       goto out;
+               }
        }
        kvmppc_e500_ref_setup(ref, gtlbe, pfn, wimg);
 
index 91bbc845ac6654d994010ae847fd5ec977be0698..ac3ddf115f3d852db205c72e79f2b592c6ef9e99 100644 (file)
@@ -529,6 +529,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
        case KVM_CAP_PPC_RMA:
                r = 0;
                break;
+       case KVM_CAP_PPC_HWRNG:
+               r = kvmppc_hwrng_present();
+               break;
 #endif
        case KVM_CAP_SYNC_MMU:
 #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
index 2c2022d1605905c0bea4415e44ad2fde47c88df2..fda236f908eb3a8239d172d5e3d35b21fc67e3ac 100644 (file)
@@ -1066,7 +1066,7 @@ int hash_page_mm(struct mm_struct *mm, unsigned long ea,
 #endif /* CONFIG_PPC_64K_PAGES */
 
        /* Get PTE and page size from page tables */
-       ptep = find_linux_pte_or_hugepte(pgdir, ea, &hugeshift);
+       ptep = __find_linux_pte_or_hugepte(pgdir, ea, &hugeshift);
        if (ptep == NULL || !pte_present(*ptep)) {
                DBG_LOW(" no PTE !\n");
                rc = 1;
@@ -1394,6 +1394,7 @@ tm_abort:
                tm_abort(TM_CAUSE_TLBI);
        }
 #endif
+       return;
 }
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
 
index fa9d5c238d224f2d9a4f2f7b544d4de5cd92f75d..0ce968b00b7c665967ca3addc26d0cc04a72f729 100644 (file)
@@ -109,7 +109,7 @@ int pgd_huge(pgd_t pgd)
 pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
 {
        /* Only called for hugetlbfs pages, hence can ignore THP */
-       return find_linux_pte_or_hugepte(mm->pgd, addr, NULL);
+       return __find_linux_pte_or_hugepte(mm->pgd, addr, NULL);
 }
 
 static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
@@ -581,6 +581,7 @@ static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud,
        pmd = pmd_offset(pud, start);
        pud_clear(pud);
        pmd_free_tlb(tlb, pmd, start);
+       mm_dec_nr_pmds(tlb->mm);
 }
 
 static void hugetlb_free_pud_range(struct mmu_gather *tlb, pgd_t *pgd,
@@ -681,28 +682,35 @@ void hugetlb_free_pgd_range(struct mmu_gather *tlb,
        } while (addr = next, addr != end);
 }
 
+/*
+ * We are holding mmap_sem, so a parallel huge page collapse cannot run.
+ * To prevent hugepage split, disable irq.
+ */
 struct page *
 follow_huge_addr(struct mm_struct *mm, unsigned long address, int write)
 {
        pte_t *ptep;
        struct page *page;
        unsigned shift;
-       unsigned long mask;
+       unsigned long mask, flags;
        /*
         * Transparent hugepages are handled by generic code. We can skip them
         * here.
         */
+       local_irq_save(flags);
        ptep = find_linux_pte_or_hugepte(mm->pgd, address, &shift);
 
        /* Verify it is a huge page else bail. */
-       if (!ptep || !shift || pmd_trans_huge(*(pmd_t *)ptep))
+       if (!ptep || !shift || pmd_trans_huge(*(pmd_t *)ptep)) {
+               local_irq_restore(flags);
                return ERR_PTR(-EINVAL);
-
+       }
        mask = (1UL << shift) - 1;
        page = pte_page(*ptep);
        if (page)
                page += (address & mask) / PAGE_SIZE;
 
+       local_irq_restore(flags);
        return page;
 }
 
@@ -949,9 +957,12 @@ void flush_dcache_icache_hugepage(struct page *page)
  *
  * So long as we atomically load page table pointers we are safe against teardown,
  * we can follow the address down to the the page and take a ref on it.
+ * This function need to be called with interrupts disabled. We use this variant
+ * when we have MSR[EE] = 0 but the paca->soft_enabled = 1
  */
 
-pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, unsigned *shift)
+pte_t *__find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea,
+                                  unsigned *shift)
 {
        pgd_t pgd, *pgdp;
        pud_t pud, *pudp;
@@ -1003,12 +1014,11 @@ pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, unsigned *shift
                         * A hugepage collapse is captured by pmd_none, because
                         * it mark the pmd none and do a hpte invalidate.
                         *
-                        * A hugepage split is captured by pmd_trans_splitting
-                        * because we mark the pmd trans splitting and do a
-                        * hpte invalidate
-                        *
+                        * We don't worry about pmd_trans_splitting here, The
+                        * caller if it needs to handle the splitting case
+                        * should check for that.
                         */
-                       if (pmd_none(pmd) || pmd_trans_splitting(pmd))
+                       if (pmd_none(pmd))
                                return NULL;
 
                        if (pmd_huge(pmd) || pmd_large(pmd)) {
@@ -1030,7 +1040,7 @@ out:
                *shift = pdshift;
        return ret_pte;
 }
-EXPORT_SYMBOL_GPL(find_linux_pte_or_hugepte);
+EXPORT_SYMBOL_GPL(__find_linux_pte_or_hugepte);
 
 int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long addr,
                unsigned long end, int write, struct page **pages, int *nr)
index ead55351b2542accc663c496be8592b9c3942b08..ff09cde20cd275563f71faaee7b153ce39a3ba08 100644 (file)
@@ -111,41 +111,45 @@ perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
  * interrupt context, so if the access faults, we read the page tables
  * to find which page (if any) is mapped and access it directly.
  */
-static int read_user_stack_slow(void __user *ptr, void *ret, int nb)
+static int read_user_stack_slow(void __user *ptr, void *buf, int nb)
 {
+       int ret = -EFAULT;
        pgd_t *pgdir;
        pte_t *ptep, pte;
        unsigned shift;
        unsigned long addr = (unsigned long) ptr;
        unsigned long offset;
-       unsigned long pfn;
+       unsigned long pfn, flags;
        void *kaddr;
 
        pgdir = current->mm->pgd;
        if (!pgdir)
                return -EFAULT;
 
+       local_irq_save(flags);
        ptep = find_linux_pte_or_hugepte(pgdir, addr, &shift);
+       if (!ptep)
+               goto err_out;
        if (!shift)
                shift = PAGE_SHIFT;
 
        /* align address to page boundary */
        offset = addr & ((1UL << shift) - 1);
-       addr -= offset;
 
-       if (ptep == NULL)
-               return -EFAULT;
-       pte = *ptep;
+       pte = READ_ONCE(*ptep);
        if (!pte_present(pte) || !(pte_val(pte) & _PAGE_USER))
-               return -EFAULT;
+               goto err_out;
        pfn = pte_pfn(pte);
        if (!page_is_ram(pfn))
-               return -EFAULT;
+               goto err_out;
 
        /* no highmem to worry about here */
        kaddr = pfn_to_kaddr(pfn);
-       memcpy(ret, kaddr + offset, nb);
-       return 0;
+       memcpy(buf, kaddr + offset, nb);
+       ret = 0;
+err_out:
+       local_irq_restore(flags);
+       return ret;
 }
 
 static int read_user_stack_64(unsigned long __user *ptr, unsigned long *ret)
index 1a3429e1ccb5bb87531d79355b593310a69103c9..1ba6307be4dba78b24bbb1eff1566a796cd71fde 100644 (file)
@@ -111,7 +111,7 @@ out:
 static int
 spufs_setattr(struct dentry *dentry, struct iattr *attr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
 
        if ((attr->ia_valid & ATTR_SIZE) &&
            (attr->ia_size != inode->i_size))
@@ -163,14 +163,14 @@ static void spufs_prune_dir(struct dentry *dir)
 {
        struct dentry *dentry, *tmp;
 
-       mutex_lock(&dir->d_inode->i_mutex);
+       mutex_lock(&d_inode(dir)->i_mutex);
        list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_child) {
                spin_lock(&dentry->d_lock);
-               if (!(d_unhashed(dentry)) && dentry->d_inode) {
+               if (!(d_unhashed(dentry)) && d_really_is_positive(dentry)) {
                        dget_dlock(dentry);
                        __d_drop(dentry);
                        spin_unlock(&dentry->d_lock);
-                       simple_unlink(dir->d_inode, dentry);
+                       simple_unlink(d_inode(dir), dentry);
                        /* XXX: what was dcache_lock protecting here? Other
                         * filesystems (IB, configfs) release dcache_lock
                         * before unlink */
@@ -180,7 +180,7 @@ static void spufs_prune_dir(struct dentry *dir)
                }
        }
        shrink_dcache_parent(dir);
-       mutex_unlock(&dir->d_inode->i_mutex);
+       mutex_unlock(&d_inode(dir)->i_mutex);
 }
 
 /* Caller must hold parent->i_mutex */
@@ -192,7 +192,7 @@ static int spufs_rmdir(struct inode *parent, struct dentry *dir)
        d_drop(dir);
        res = simple_rmdir(parent, dir);
        /* We have to give up the mm_struct */
-       spu_forget(SPUFS_I(dir->d_inode)->i_ctx);
+       spu_forget(SPUFS_I(d_inode(dir))->i_ctx);
        return res;
 }
 
@@ -222,8 +222,8 @@ static int spufs_dir_close(struct inode *inode, struct file *file)
        int ret;
 
        dir = file->f_path.dentry;
-       parent = dir->d_parent->d_inode;
-       ctx = SPUFS_I(dir->d_inode)->i_ctx;
+       parent = d_inode(dir->d_parent);
+       ctx = SPUFS_I(d_inode(dir))->i_ctx;
 
        mutex_lock_nested(&parent->i_mutex, I_MUTEX_PARENT);
        ret = spufs_rmdir(parent, dir);
@@ -460,7 +460,7 @@ spufs_create_context(struct inode *inode, struct dentry *dentry,
                goto out_aff_unlock;
 
        if (affinity) {
-               spufs_set_affinity(flags, SPUFS_I(dentry->d_inode)->i_ctx,
+               spufs_set_affinity(flags, SPUFS_I(d_inode(dentry))->i_ctx,
                                                                neighbor);
                if (neighbor)
                        put_spu_context(neighbor);
@@ -504,7 +504,7 @@ spufs_mkgang(struct inode *dir, struct dentry *dentry, umode_t mode)
 
        d_instantiate(dentry, inode);
        inc_nlink(dir);
-       inc_nlink(dentry->d_inode);
+       inc_nlink(d_inode(dentry));
        return ret;
 
 out_iput:
@@ -561,7 +561,7 @@ static struct file_system_type spufs_type;
 long spufs_create(struct path *path, struct dentry *dentry,
                unsigned int flags, umode_t mode, struct file *filp)
 {
-       struct inode *dir = path->dentry->d_inode;
+       struct inode *dir = d_inode(path->dentry);
        int ret;
 
        /* check if we are on spufs */
index 920c252d1f49329616eddb2cf3ba4f2ec1f202b3..f8bc950efcae39a63f213290b65d36fec1667b60 100644 (file)
@@ -2693,7 +2693,6 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,
                hose->last_busno = 0xff;
        }
        hose->private_data = phb;
-       hose->controller_ops = pnv_pci_controller_ops;
        phb->hub_id = hub_id;
        phb->opal_id = phb_id;
        phb->type = ioda_type;
@@ -2812,6 +2811,7 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,
        pnv_pci_controller_ops.enable_device_hook = pnv_pci_enable_device_hook;
        pnv_pci_controller_ops.window_alignment = pnv_pci_window_alignment;
        pnv_pci_controller_ops.reset_secondary_bus = pnv_pci_reset_secondary_bus;
+       hose->controller_ops = pnv_pci_controller_ops;
 
 #ifdef CONFIG_PCI_IOV
        ppc_md.pcibios_fixup_sriov = pnv_pci_ioda_fixup_iov_resources;
index 80db43944afefe927cec6e09ed088bffb635f45d..6eb808ff637e712e038138488c1dad53ca926264 100644 (file)
 
 struct powernv_rng {
        void __iomem *regs;
+       void __iomem *regs_real;
        unsigned long mask;
 };
 
 static DEFINE_PER_CPU(struct powernv_rng *, powernv_rng);
 
 
+int powernv_hwrng_present(void)
+{
+       struct powernv_rng *rng;
+
+       rng = get_cpu_var(powernv_rng);
+       put_cpu_var(rng);
+       return rng != NULL;
+}
+
 static unsigned long rng_whiten(struct powernv_rng *rng, unsigned long val)
 {
        unsigned long parity;
@@ -46,6 +56,17 @@ static unsigned long rng_whiten(struct powernv_rng *rng, unsigned long val)
        return val;
 }
 
+int powernv_get_random_real_mode(unsigned long *v)
+{
+       struct powernv_rng *rng;
+
+       rng = raw_cpu_read(powernv_rng);
+
+       *v = rng_whiten(rng, in_rm64(rng->regs_real));
+
+       return 1;
+}
+
 int powernv_get_random_long(unsigned long *v)
 {
        struct powernv_rng *rng;
@@ -80,12 +101,20 @@ static __init void rng_init_per_cpu(struct powernv_rng *rng,
 static __init int rng_create(struct device_node *dn)
 {
        struct powernv_rng *rng;
+       struct resource res;
        unsigned long val;
 
        rng = kzalloc(sizeof(*rng), GFP_KERNEL);
        if (!rng)
                return -ENOMEM;
 
+       if (of_address_to_resource(dn, 0, &res)) {
+               kfree(rng);
+               return -ENXIO;
+       }
+
+       rng->regs_real = (void __iomem *)res.start;
+
        rng->regs = of_iomap(dn, 0);
        if (!rng->regs) {
                kfree(rng);
index b4b11096ea8b74c3695c46deff77c25d2409f8f4..019d34aaf054bc843d6a2d5ac531e9207e6c42ab 100644 (file)
@@ -412,6 +412,10 @@ static ssize_t dlpar_cpu_probe(const char *buf, size_t count)
        if (rc)
                return -EINVAL;
 
+       rc = dlpar_acquire_drc(drc_index);
+       if (rc)
+               return -EINVAL;
+
        parent = of_find_node_by_path("/cpus");
        if (!parent)
                return -ENODEV;
@@ -422,12 +426,6 @@ static ssize_t dlpar_cpu_probe(const char *buf, size_t count)
 
        of_node_put(parent);
 
-       rc = dlpar_acquire_drc(drc_index);
-       if (rc) {
-               dlpar_free_cc_nodes(dn);
-               return -EINVAL;
-       }
-
        rc = dlpar_attach_node(dn);
        if (rc) {
                dlpar_release_drc(drc_index);
index 8e58c614c37d7203e39f389ab33e31b8542328c2..b06dc383926846c73e85a6c635ff0fac0a3ddcab 100644 (file)
@@ -115,7 +115,7 @@ config S390
        select HAVE_ARCH_SECCOMP_FILTER
        select HAVE_ARCH_TRACEHOOK
        select HAVE_ARCH_TRANSPARENT_HUGEPAGE
-       select HAVE_BPF_JIT if PACK_STACK && HAVE_MARCH_Z9_109_FEATURES
+       select HAVE_BPF_JIT if PACK_STACK && HAVE_MARCH_Z196_FEATURES
        select HAVE_CMPXCHG_DOUBLE
        select HAVE_CMPXCHG_LOCAL
        select HAVE_DEBUG_KMEMLEAK
index ba3b2aefddf55fa6dfa5a75f947273e0196a65e0..d9c4c313fbc61d5bbf73c8a3c7f88eb74c9d6cee 100644 (file)
@@ -3,9 +3,10 @@
  *
  * Support for s390 cryptographic instructions.
  *
- *   Copyright IBM Corp. 2003, 2007
+ *   Copyright IBM Corp. 2003, 2015
  *   Author(s): Thomas Spatzier
  *             Jan Glauber (jan.glauber@de.ibm.com)
+ *             Harald Freudenberger (freude@de.ibm.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
 #define CRYPT_S390_MSA 0x1
 #define CRYPT_S390_MSA3        0x2
 #define CRYPT_S390_MSA4        0x4
+#define CRYPT_S390_MSA5        0x8
 
 /* s390 cryptographic operations */
 enum crypt_s390_operations {
-       CRYPT_S390_KM   = 0x0100,
-       CRYPT_S390_KMC  = 0x0200,
-       CRYPT_S390_KIMD = 0x0300,
-       CRYPT_S390_KLMD = 0x0400,
-       CRYPT_S390_KMAC = 0x0500,
-       CRYPT_S390_KMCTR = 0x0600
+       CRYPT_S390_KM    = 0x0100,
+       CRYPT_S390_KMC   = 0x0200,
+       CRYPT_S390_KIMD  = 0x0300,
+       CRYPT_S390_KLMD  = 0x0400,
+       CRYPT_S390_KMAC  = 0x0500,
+       CRYPT_S390_KMCTR = 0x0600,
+       CRYPT_S390_PPNO  = 0x0700
 };
 
 /*
@@ -138,6 +141,16 @@ enum crypt_s390_kmac_func {
        KMAC_TDEA_192 = CRYPT_S390_KMAC | 3
 };
 
+/*
+ * function codes for PPNO (PERFORM PSEUDORANDOM NUMBER
+ * OPERATION) instruction
+ */
+enum crypt_s390_ppno_func {
+       PPNO_QUERY            = CRYPT_S390_PPNO | 0,
+       PPNO_SHA512_DRNG_GEN  = CRYPT_S390_PPNO | 3,
+       PPNO_SHA512_DRNG_SEED = CRYPT_S390_PPNO | 0x83
+};
+
 /**
  * crypt_s390_km:
  * @func: the function code passed to KM; see crypt_s390_km_func
@@ -162,11 +175,11 @@ static inline int crypt_s390_km(long func, void *param,
        int ret;
 
        asm volatile(
-               "0:     .insn   rre,0xb92e0000,%3,%1 \n" /* KM opcode */
-               "1:     brc     1,0b \n" /* handle partial completion */
+               "0:     .insn   rre,0xb92e0000,%3,%1\n" /* KM opcode */
+               "1:     brc     1,0b\n" /* handle partial completion */
                "       la      %0,0\n"
                "2:\n"
-               EX_TABLE(0b,2b) EX_TABLE(1b,2b)
+               EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
                : "=d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest)
                : "d" (__func), "a" (__param), "0" (-1) : "cc", "memory");
        if (ret < 0)
@@ -198,11 +211,11 @@ static inline int crypt_s390_kmc(long func, void *param,
        int ret;
 
        asm volatile(
-               "0:     .insn   rre,0xb92f0000,%3,%1 \n" /* KMC opcode */
-               "1:     brc     1,0b \n" /* handle partial completion */
+               "0:     .insn   rre,0xb92f0000,%3,%1\n" /* KMC opcode */
+               "1:     brc     1,0b\n" /* handle partial completion */
                "       la      %0,0\n"
                "2:\n"
-               EX_TABLE(0b,2b) EX_TABLE(1b,2b)
+               EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
                : "=d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest)
                : "d" (__func), "a" (__param), "0" (-1) : "cc", "memory");
        if (ret < 0)
@@ -233,11 +246,11 @@ static inline int crypt_s390_kimd(long func, void *param,
        int ret;
 
        asm volatile(
-               "0:     .insn   rre,0xb93e0000,%1,%1 \n" /* KIMD opcode */
-               "1:     brc     1,0b \n" /* handle partial completion */
+               "0:     .insn   rre,0xb93e0000,%1,%1\n" /* KIMD opcode */
+               "1:     brc     1,0b\n" /* handle partial completion */
                "       la      %0,0\n"
                "2:\n"
-               EX_TABLE(0b,2b) EX_TABLE(1b,2b)
+               EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
                : "=d" (ret), "+a" (__src), "+d" (__src_len)
                : "d" (__func), "a" (__param), "0" (-1) : "cc", "memory");
        if (ret < 0)
@@ -267,11 +280,11 @@ static inline int crypt_s390_klmd(long func, void *param,
        int ret;
 
        asm volatile(
-               "0:     .insn   rre,0xb93f0000,%1,%1 \n" /* KLMD opcode */
-               "1:     brc     1,0b \n" /* handle partial completion */
+               "0:     .insn   rre,0xb93f0000,%1,%1\n" /* KLMD opcode */
+               "1:     brc     1,0b\n" /* handle partial completion */
                "       la      %0,0\n"
                "2:\n"
-               EX_TABLE(0b,2b) EX_TABLE(1b,2b)
+               EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
                : "=d" (ret), "+a" (__src), "+d" (__src_len)
                : "d" (__func), "a" (__param), "0" (-1) : "cc", "memory");
        if (ret < 0)
@@ -302,11 +315,11 @@ static inline int crypt_s390_kmac(long func, void *param,
        int ret;
 
        asm volatile(
-               "0:     .insn   rre,0xb91e0000,%1,%1 \n" /* KLAC opcode */
-               "1:     brc     1,0b \n" /* handle partial completion */
+               "0:     .insn   rre,0xb91e0000,%1,%1\n" /* KLAC opcode */
+               "1:     brc     1,0b\n" /* handle partial completion */
                "       la      %0,0\n"
                "2:\n"
-               EX_TABLE(0b,2b) EX_TABLE(1b,2b)
+               EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
                : "=d" (ret), "+a" (__src), "+d" (__src_len)
                : "d" (__func), "a" (__param), "0" (-1) : "cc", "memory");
        if (ret < 0)
@@ -340,11 +353,11 @@ static inline int crypt_s390_kmctr(long func, void *param, u8 *dest,
        int ret = -1;
 
        asm volatile(
-               "0:     .insn   rrf,0xb92d0000,%3,%1,%4,0 \n" /* KMCTR opcode */
-               "1:     brc     1,0b \n" /* handle partial completion */
+               "0:     .insn   rrf,0xb92d0000,%3,%1,%4,0\n" /* KMCTR opcode */
+               "1:     brc     1,0b\n" /* handle partial completion */
                "       la      %0,0\n"
                "2:\n"
-               EX_TABLE(0b,2b) EX_TABLE(1b,2b)
+               EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
                : "+d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest),
                  "+a" (__ctr)
                : "d" (__func), "a" (__param) : "cc", "memory");
@@ -353,6 +366,47 @@ static inline int crypt_s390_kmctr(long func, void *param, u8 *dest,
        return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
 }
 
+/**
+ * crypt_s390_ppno:
+ * @func: the function code passed to PPNO; see crypt_s390_ppno_func
+ * @param: address of parameter block; see POP for details on each func
+ * @dest: address of destination memory area
+ * @dest_len: size of destination memory area in bytes
+ * @seed: address of seed data
+ * @seed_len: size of seed data in bytes
+ *
+ * Executes the PPNO (PERFORM PSEUDORANDOM NUMBER OPERATION)
+ * operation of the CPU.
+ *
+ * Returns -1 for failure, 0 for the query func, number of random
+ * bytes stored in dest buffer for generate function
+ */
+static inline int crypt_s390_ppno(long func, void *param,
+                                 u8 *dest, long dest_len,
+                                 const u8 *seed, long seed_len)
+{
+       register long  __func     asm("0") = func & CRYPT_S390_FUNC_MASK;
+       register void *__param    asm("1") = param;    /* param block (240 bytes) */
+       register u8   *__dest     asm("2") = dest;     /* buf for recv random bytes */
+       register long  __dest_len asm("3") = dest_len; /* requested random bytes */
+       register const u8 *__seed asm("4") = seed;     /* buf with seed data */
+       register long  __seed_len asm("5") = seed_len; /* bytes in seed buf */
+       int ret = -1;
+
+       asm volatile (
+               "0:     .insn   rre,0xb93c0000,%1,%5\n" /* PPNO opcode */
+               "1:     brc     1,0b\n"   /* handle partial completion */
+               "       la      %0,0\n"
+               "2:\n"
+               EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
+               : "+d" (ret), "+a"(__dest), "+d"(__dest_len)
+               : "d"(__func), "a"(__param), "a"(__seed), "d"(__seed_len)
+               : "cc", "memory");
+       if (ret < 0)
+               return ret;
+       return (func & CRYPT_S390_FUNC_MASK) ? dest_len - __dest_len : 0;
+}
+
 /**
  * crypt_s390_func_available:
  * @func: the function code of the specific function; 0 if op in general
@@ -373,6 +427,9 @@ static inline int crypt_s390_func_available(int func,
                return 0;
        if (facility_mask & CRYPT_S390_MSA4 && !test_facility(77))
                return 0;
+       if (facility_mask & CRYPT_S390_MSA5 && !test_facility(57))
+               return 0;
+
        switch (func & CRYPT_S390_OP_MASK) {
        case CRYPT_S390_KM:
                ret = crypt_s390_km(KM_QUERY, &status, NULL, NULL, 0);
@@ -390,8 +447,12 @@ static inline int crypt_s390_func_available(int func,
                ret = crypt_s390_kmac(KMAC_QUERY, &status, NULL, 0);
                break;
        case CRYPT_S390_KMCTR:
-               ret = crypt_s390_kmctr(KMCTR_QUERY, &status, NULL, NULL, 0,
-                                      NULL);
+               ret = crypt_s390_kmctr(KMCTR_QUERY, &status,
+                                      NULL, NULL, 0, NULL);
+               break;
+       case CRYPT_S390_PPNO:
+               ret = crypt_s390_ppno(PPNO_QUERY, &status,
+                                     NULL, 0, NULL, 0);
                break;
        default:
                return 0;
@@ -419,15 +480,14 @@ static inline int crypt_s390_pcc(long func, void *param)
        int ret = -1;
 
        asm volatile(
-               "0:     .insn   rre,0xb92c0000,0,0 \n" /* PCC opcode */
-               "1:     brc     1,0b \n" /* handle partial completion */
+               "0:     .insn   rre,0xb92c0000,0,0\n" /* PCC opcode */
+               "1:     brc     1,0b\n" /* handle partial completion */
                "       la      %0,0\n"
                "2:\n"
-               EX_TABLE(0b,2b) EX_TABLE(1b,2b)
+               EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
                : "+d" (ret)
                : "d" (__func), "a" (__param) : "cc", "memory");
        return ret;
 }
 
-
 #endif /* _CRYPTO_ARCH_S390_CRYPT_S390_H */
index 94a35a4c1b486c02200f6be510ecafd8a59701c6..1f374b39a4ec9a933249b3924d393d118084112f 100644 (file)
 /*
- * Copyright IBM Corp. 2006, 2007
+ * Copyright IBM Corp. 2006, 2015
  * Author(s): Jan Glauber <jan.glauber@de.ibm.com>
+ *           Harald Freudenberger <freude@de.ibm.com>
  * Driver for the s390 pseudo random number generator
  */
+
+#define KMSG_COMPONENT "prng"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
 #include <linux/fs.h>
+#include <linux/fips.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/device.h>
 #include <linux/miscdevice.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <linux/mutex.h>
 #include <linux/random.h>
 #include <linux/slab.h>
 #include <asm/debug.h>
 #include <asm/uaccess.h>
+#include <asm/timex.h>
 
 #include "crypt_s390.h"
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jan Glauber <jan.glauber@de.ibm.com>");
+MODULE_AUTHOR("IBM Corporation");
 MODULE_DESCRIPTION("s390 PRNG interface");
 
-static int prng_chunk_size = 256;
-module_param(prng_chunk_size, int, S_IRUSR | S_IRGRP | S_IROTH);
+
+#define PRNG_MODE_AUTO   0
+#define PRNG_MODE_TDES   1
+#define PRNG_MODE_SHA512  2
+
+static unsigned int prng_mode = PRNG_MODE_AUTO;
+module_param_named(mode, prng_mode, int, 0);
+MODULE_PARM_DESC(prng_mode, "PRNG mode: 0 - auto, 1 - TDES, 2 - SHA512");
+
+
+#define PRNG_CHUNKSIZE_TDES_MIN   8
+#define PRNG_CHUNKSIZE_TDES_MAX   (64*1024)
+#define PRNG_CHUNKSIZE_SHA512_MIN 64
+#define PRNG_CHUNKSIZE_SHA512_MAX (64*1024)
+
+static unsigned int prng_chunk_size = 256;
+module_param_named(chunksize, prng_chunk_size, int, 0);
 MODULE_PARM_DESC(prng_chunk_size, "PRNG read chunk size in bytes");
 
-static int prng_entropy_limit = 4096;
-module_param(prng_entropy_limit, int, S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR);
-MODULE_PARM_DESC(prng_entropy_limit,
-       "PRNG add entropy after that much bytes were produced");
+
+#define PRNG_RESEED_LIMIT_TDES          4096
+#define PRNG_RESEED_LIMIT_TDES_LOWER    4096
+#define PRNG_RESEED_LIMIT_SHA512       100000
+#define PRNG_RESEED_LIMIT_SHA512_LOWER 10000
+
+static unsigned int prng_reseed_limit;
+module_param_named(reseed_limit, prng_reseed_limit, int, 0);
+MODULE_PARM_DESC(prng_reseed_limit, "PRNG reseed limit");
+
 
 /*
  * Any one who considers arithmetical methods of producing random digits is,
  * of course, in a state of sin. -- John von Neumann
  */
 
-struct s390_prng_data {
-       unsigned long count; /* how many bytes were produced */
-       char *buf;
+static int prng_errorflag;
+
+#define PRNG_GEN_ENTROPY_FAILED  1
+#define PRNG_SELFTEST_FAILED    2
+#define PRNG_INSTANTIATE_FAILED  3
+#define PRNG_SEED_FAILED        4
+#define PRNG_RESEED_FAILED      5
+#define PRNG_GEN_FAILED                 6
+
+struct prng_ws_s {
+       u8  parm_block[32];
+       u32 reseed_counter;
+       u64 byte_counter;
 };
 
-static struct s390_prng_data *p;
+struct ppno_ws_s {
+       u32 res;
+       u32 reseed_counter;
+       u64 stream_bytes;
+       u8  V[112];
+       u8  C[112];
+};
 
-/* copied from libica, use a non-zero initial parameter block */
-static unsigned char parm_block[32] = {
-0x0F,0x2B,0x8E,0x63,0x8C,0x8E,0xD2,0x52,0x64,0xB7,0xA0,0x7B,0x75,0x28,0xB8,0xF4,
-0x75,0x5F,0xD2,0xA6,0x8D,0x97,0x11,0xFF,0x49,0xD8,0x23,0xF3,0x7E,0x21,0xEC,0xA0,
+struct prng_data_s {
+       struct mutex mutex;
+       union {
+               struct prng_ws_s prngws;
+               struct ppno_ws_s ppnows;
+       };
+       u8 *buf;
+       u32 rest;
+       u8 *prev;
 };
 
-static int prng_open(struct inode *inode, struct file *file)
+static struct prng_data_s *prng_data;
+
+/* initial parameter block for tdes mode, copied from libica */
+static const u8 initial_parm_block[32] __initconst = {
+       0x0F, 0x2B, 0x8E, 0x63, 0x8C, 0x8E, 0xD2, 0x52,
+       0x64, 0xB7, 0xA0, 0x7B, 0x75, 0x28, 0xB8, 0xF4,
+       0x75, 0x5F, 0xD2, 0xA6, 0x8D, 0x97, 0x11, 0xFF,
+       0x49, 0xD8, 0x23, 0xF3, 0x7E, 0x21, 0xEC, 0xA0 };
+
+
+/*** helper functions ***/
+
+static int generate_entropy(u8 *ebuf, size_t nbytes)
 {
-       return nonseekable_open(inode, file);
+       int n, ret = 0;
+       u8 *pg, *h, hash[32];
+
+       pg = (u8 *) __get_free_page(GFP_KERNEL);
+       if (!pg) {
+               prng_errorflag = PRNG_GEN_ENTROPY_FAILED;
+               return -ENOMEM;
+       }
+
+       while (nbytes) {
+               /* fill page with urandom bytes */
+               get_random_bytes(pg, PAGE_SIZE);
+               /* exor page with stckf values */
+               for (n = 0; n < sizeof(PAGE_SIZE/sizeof(u64)); n++) {
+                       u64 *p = ((u64 *)pg) + n;
+                       *p ^= get_tod_clock_fast();
+               }
+               n = (nbytes < sizeof(hash)) ? nbytes : sizeof(hash);
+               if (n < sizeof(hash))
+                       h = hash;
+               else
+                       h = ebuf;
+               /* generate sha256 from this page */
+               if (crypt_s390_kimd(KIMD_SHA_256, h,
+                                   pg, PAGE_SIZE) != PAGE_SIZE) {
+                       prng_errorflag = PRNG_GEN_ENTROPY_FAILED;
+                       ret = -EIO;
+                       goto out;
+               }
+               if (n < sizeof(hash))
+                       memcpy(ebuf, hash, n);
+               ret += n;
+               ebuf += n;
+               nbytes -= n;
+       }
+
+out:
+       free_page((unsigned long)pg);
+       return ret;
 }
 
-static void prng_add_entropy(void)
+
+/*** tdes functions ***/
+
+static void prng_tdes_add_entropy(void)
 {
        __u64 entropy[4];
        unsigned int i;
        int ret;
 
        for (i = 0; i < 16; i++) {
-               ret = crypt_s390_kmc(KMC_PRNG, parm_block, (char *)entropy,
-                                    (char *)entropy, sizeof(entropy));
+               ret = crypt_s390_kmc(KMC_PRNG, prng_data->prngws.parm_block,
+                                    (char *)entropy, (char *)entropy,
+                                    sizeof(entropy));
                BUG_ON(ret < 0 || ret != sizeof(entropy));
-               memcpy(parm_block, entropy, sizeof(entropy));
+               memcpy(prng_data->prngws.parm_block, entropy, sizeof(entropy));
        }
 }
 
-static void prng_seed(int nbytes)
+
+static void prng_tdes_seed(int nbytes)
 {
        char buf[16];
        int i = 0;
 
-       BUG_ON(nbytes > 16);
+       BUG_ON(nbytes > sizeof(buf));
+
        get_random_bytes(buf, nbytes);
 
        /* Add the entropy */
        while (nbytes >= 8) {
-               *((__u64 *)parm_block) ^= *((__u64 *)(buf+i));
-               prng_add_entropy();
+               *((__u64 *)prng_data->prngws.parm_block) ^= *((__u64 *)(buf+i));
+               prng_tdes_add_entropy();
                i += 8;
                nbytes -= 8;
        }
-       prng_add_entropy();
+       prng_tdes_add_entropy();
+       prng_data->prngws.reseed_counter = 0;
+}
+
+
+static int __init prng_tdes_instantiate(void)
+{
+       int datalen;
+
+       pr_debug("prng runs in TDES mode with "
+                "chunksize=%d and reseed_limit=%u\n",
+                prng_chunk_size, prng_reseed_limit);
+
+       /* memory allocation, prng_data struct init, mutex init */
+       datalen = sizeof(struct prng_data_s) + prng_chunk_size;
+       prng_data = kzalloc(datalen, GFP_KERNEL);
+       if (!prng_data) {
+               prng_errorflag = PRNG_INSTANTIATE_FAILED;
+               return -ENOMEM;
+       }
+       mutex_init(&prng_data->mutex);
+       prng_data->buf = ((u8 *)prng_data) + sizeof(struct prng_data_s);
+       memcpy(prng_data->prngws.parm_block, initial_parm_block, 32);
+
+       /* initialize the PRNG, add 128 bits of entropy */
+       prng_tdes_seed(16);
+
+       return 0;
 }
 
-static ssize_t prng_read(struct file *file, char __user *ubuf, size_t nbytes,
-                        loff_t *ppos)
+
+static void prng_tdes_deinstantiate(void)
+{
+       pr_debug("The prng module stopped "
+                "after running in triple DES mode\n");
+       kzfree(prng_data);
+}
+
+
+/*** sha512 functions ***/
+
+static int __init prng_sha512_selftest(void)
 {
-       int chunk, n;
+       /* NIST DRBG testvector for Hash Drbg, Sha-512, Count #0 */
+       static const u8 seed[] __initconst = {
+               0x6b, 0x50, 0xa7, 0xd8, 0xf8, 0xa5, 0x5d, 0x7a,
+               0x3d, 0xf8, 0xbb, 0x40, 0xbc, 0xc3, 0xb7, 0x22,
+               0xd8, 0x70, 0x8d, 0xe6, 0x7f, 0xda, 0x01, 0x0b,
+               0x03, 0xc4, 0xc8, 0x4d, 0x72, 0x09, 0x6f, 0x8c,
+               0x3e, 0xc6, 0x49, 0xcc, 0x62, 0x56, 0xd9, 0xfa,
+               0x31, 0xdb, 0x7a, 0x29, 0x04, 0xaa, 0xf0, 0x25 };
+       static const u8 V0[] __initconst = {
+               0x00, 0xad, 0xe3, 0x6f, 0x9a, 0x01, 0xc7, 0x76,
+               0x61, 0x34, 0x35, 0xf5, 0x4e, 0x24, 0x74, 0x22,
+               0x21, 0x9a, 0x29, 0x89, 0xc7, 0x93, 0x2e, 0x60,
+               0x1e, 0xe8, 0x14, 0x24, 0x8d, 0xd5, 0x03, 0xf1,
+               0x65, 0x5d, 0x08, 0x22, 0x72, 0xd5, 0xad, 0x95,
+               0xe1, 0x23, 0x1e, 0x8a, 0xa7, 0x13, 0xd9, 0x2b,
+               0x5e, 0xbc, 0xbb, 0x80, 0xab, 0x8d, 0xe5, 0x79,
+               0xab, 0x5b, 0x47, 0x4e, 0xdd, 0xee, 0x6b, 0x03,
+               0x8f, 0x0f, 0x5c, 0x5e, 0xa9, 0x1a, 0x83, 0xdd,
+               0xd3, 0x88, 0xb2, 0x75, 0x4b, 0xce, 0x83, 0x36,
+               0x57, 0x4b, 0xf1, 0x5c, 0xca, 0x7e, 0x09, 0xc0,
+               0xd3, 0x89, 0xc6, 0xe0, 0xda, 0xc4, 0x81, 0x7e,
+               0x5b, 0xf9, 0xe1, 0x01, 0xc1, 0x92, 0x05, 0xea,
+               0xf5, 0x2f, 0xc6, 0xc6, 0xc7, 0x8f, 0xbc, 0xf4 };
+       static const u8 C0[] __initconst = {
+               0x00, 0xf4, 0xa3, 0xe5, 0xa0, 0x72, 0x63, 0x95,
+               0xc6, 0x4f, 0x48, 0xd0, 0x8b, 0x5b, 0x5f, 0x8e,
+               0x6b, 0x96, 0x1f, 0x16, 0xed, 0xbc, 0x66, 0x94,
+               0x45, 0x31, 0xd7, 0x47, 0x73, 0x22, 0xa5, 0x86,
+               0xce, 0xc0, 0x4c, 0xac, 0x63, 0xb8, 0x39, 0x50,
+               0xbf, 0xe6, 0x59, 0x6c, 0x38, 0x58, 0x99, 0x1f,
+               0x27, 0xa7, 0x9d, 0x71, 0x2a, 0xb3, 0x7b, 0xf9,
+               0xfb, 0x17, 0x86, 0xaa, 0x99, 0x81, 0xaa, 0x43,
+               0xe4, 0x37, 0xd3, 0x1e, 0x6e, 0xe5, 0xe6, 0xee,
+               0xc2, 0xed, 0x95, 0x4f, 0x53, 0x0e, 0x46, 0x8a,
+               0xcc, 0x45, 0xa5, 0xdb, 0x69, 0x0d, 0x81, 0xc9,
+               0x32, 0x92, 0xbc, 0x8f, 0x33, 0xe6, 0xf6, 0x09,
+               0x7c, 0x8e, 0x05, 0x19, 0x0d, 0xf1, 0xb6, 0xcc,
+               0xf3, 0x02, 0x21, 0x90, 0x25, 0xec, 0xed, 0x0e };
+       static const u8 random[] __initconst = {
+               0x95, 0xb7, 0xf1, 0x7e, 0x98, 0x02, 0xd3, 0x57,
+               0x73, 0x92, 0xc6, 0xa9, 0xc0, 0x80, 0x83, 0xb6,
+               0x7d, 0xd1, 0x29, 0x22, 0x65, 0xb5, 0xf4, 0x2d,
+               0x23, 0x7f, 0x1c, 0x55, 0xbb, 0x9b, 0x10, 0xbf,
+               0xcf, 0xd8, 0x2c, 0x77, 0xa3, 0x78, 0xb8, 0x26,
+               0x6a, 0x00, 0x99, 0x14, 0x3b, 0x3c, 0x2d, 0x64,
+               0x61, 0x1e, 0xee, 0xb6, 0x9a, 0xcd, 0xc0, 0x55,
+               0x95, 0x7c, 0x13, 0x9e, 0x8b, 0x19, 0x0c, 0x7a,
+               0x06, 0x95, 0x5f, 0x2c, 0x79, 0x7c, 0x27, 0x78,
+               0xde, 0x94, 0x03, 0x96, 0xa5, 0x01, 0xf4, 0x0e,
+               0x91, 0x39, 0x6a, 0xcf, 0x8d, 0x7e, 0x45, 0xeb,
+               0xdb, 0xb5, 0x3b, 0xbf, 0x8c, 0x97, 0x52, 0x30,
+               0xd2, 0xf0, 0xff, 0x91, 0x06, 0xc7, 0x61, 0x19,
+               0xae, 0x49, 0x8e, 0x7f, 0xbc, 0x03, 0xd9, 0x0f,
+               0x8e, 0x4c, 0x51, 0x62, 0x7a, 0xed, 0x5c, 0x8d,
+               0x42, 0x63, 0xd5, 0xd2, 0xb9, 0x78, 0x87, 0x3a,
+               0x0d, 0xe5, 0x96, 0xee, 0x6d, 0xc7, 0xf7, 0xc2,
+               0x9e, 0x37, 0xee, 0xe8, 0xb3, 0x4c, 0x90, 0xdd,
+               0x1c, 0xf6, 0xa9, 0xdd, 0xb2, 0x2b, 0x4c, 0xbd,
+               0x08, 0x6b, 0x14, 0xb3, 0x5d, 0xe9, 0x3d, 0xa2,
+               0xd5, 0xcb, 0x18, 0x06, 0x69, 0x8c, 0xbd, 0x7b,
+               0xbb, 0x67, 0xbf, 0xe3, 0xd3, 0x1f, 0xd2, 0xd1,
+               0xdb, 0xd2, 0xa1, 0xe0, 0x58, 0xa3, 0xeb, 0x99,
+               0xd7, 0xe5, 0x1f, 0x1a, 0x93, 0x8e, 0xed, 0x5e,
+               0x1c, 0x1d, 0xe2, 0x3a, 0x6b, 0x43, 0x45, 0xd3,
+               0x19, 0x14, 0x09, 0xf9, 0x2f, 0x39, 0xb3, 0x67,
+               0x0d, 0x8d, 0xbf, 0xb6, 0x35, 0xd8, 0xe6, 0xa3,
+               0x69, 0x32, 0xd8, 0x10, 0x33, 0xd1, 0x44, 0x8d,
+               0x63, 0xb4, 0x03, 0xdd, 0xf8, 0x8e, 0x12, 0x1b,
+               0x6e, 0x81, 0x9a, 0xc3, 0x81, 0x22, 0x6c, 0x13,
+               0x21, 0xe4, 0xb0, 0x86, 0x44, 0xf6, 0x72, 0x7c,
+               0x36, 0x8c, 0x5a, 0x9f, 0x7a, 0x4b, 0x3e, 0xe2 };
+
        int ret = 0;
-       int tmp;
+       u8 buf[sizeof(random)];
+       struct ppno_ws_s ws;
+
+       memset(&ws, 0, sizeof(ws));
+
+       /* initial seed */
+       ret = crypt_s390_ppno(PPNO_SHA512_DRNG_SEED,
+                             &ws, NULL, 0,
+                             seed, sizeof(seed));
+       if (ret < 0) {
+               pr_err("The prng self test seed operation for the "
+                      "SHA-512 mode failed with rc=%d\n", ret);
+               prng_errorflag = PRNG_SELFTEST_FAILED;
+               return -EIO;
+       }
+
+       /* check working states V and C */
+       if (memcmp(ws.V, V0, sizeof(V0)) != 0
+           || memcmp(ws.C, C0, sizeof(C0)) != 0) {
+               pr_err("The prng self test state test "
+                      "for the SHA-512 mode failed\n");
+               prng_errorflag = PRNG_SELFTEST_FAILED;
+               return -EIO;
+       }
+
+       /* generate random bytes */
+       ret = crypt_s390_ppno(PPNO_SHA512_DRNG_GEN,
+                             &ws, buf, sizeof(buf),
+                             NULL, 0);
+       if (ret < 0) {
+               pr_err("The prng self test generate operation for "
+                      "the SHA-512 mode failed with rc=%d\n", ret);
+               prng_errorflag = PRNG_SELFTEST_FAILED;
+               return -EIO;
+       }
+       ret = crypt_s390_ppno(PPNO_SHA512_DRNG_GEN,
+                             &ws, buf, sizeof(buf),
+                             NULL, 0);
+       if (ret < 0) {
+               pr_err("The prng self test generate operation for "
+                      "the SHA-512 mode failed with rc=%d\n", ret);
+               prng_errorflag = PRNG_SELFTEST_FAILED;
+               return -EIO;
+       }
+
+       /* check against expected data */
+       if (memcmp(buf, random, sizeof(random)) != 0) {
+               pr_err("The prng self test data test "
+                      "for the SHA-512 mode failed\n");
+               prng_errorflag = PRNG_SELFTEST_FAILED;
+               return -EIO;
+       }
+
+       return 0;
+}
+
+
+static int __init prng_sha512_instantiate(void)
+{
+       int ret, datalen;
+       u8 seed[64];
+
+       pr_debug("prng runs in SHA-512 mode "
+                "with chunksize=%d and reseed_limit=%u\n",
+                prng_chunk_size, prng_reseed_limit);
+
+       /* memory allocation, prng_data struct init, mutex init */
+       datalen = sizeof(struct prng_data_s) + prng_chunk_size;
+       if (fips_enabled)
+               datalen += prng_chunk_size;
+       prng_data = kzalloc(datalen, GFP_KERNEL);
+       if (!prng_data) {
+               prng_errorflag = PRNG_INSTANTIATE_FAILED;
+               return -ENOMEM;
+       }
+       mutex_init(&prng_data->mutex);
+       prng_data->buf = ((u8 *)prng_data) + sizeof(struct prng_data_s);
+
+       /* selftest */
+       ret = prng_sha512_selftest();
+       if (ret)
+               goto outfree;
+
+       /* generate initial seed bytestring, first 48 bytes of entropy */
+       ret = generate_entropy(seed, 48);
+       if (ret != 48)
+               goto outfree;
+       /* followed by 16 bytes of unique nonce */
+       get_tod_clock_ext(seed + 48);
+
+       /* initial seed of the ppno drng */
+       ret = crypt_s390_ppno(PPNO_SHA512_DRNG_SEED,
+                             &prng_data->ppnows, NULL, 0,
+                             seed, sizeof(seed));
+       if (ret < 0) {
+               prng_errorflag = PRNG_SEED_FAILED;
+               ret = -EIO;
+               goto outfree;
+       }
+
+       /* if fips mode is enabled, generate a first block of random
+          bytes for the FIPS 140-2 Conditional Self Test */
+       if (fips_enabled) {
+               prng_data->prev = prng_data->buf + prng_chunk_size;
+               ret = crypt_s390_ppno(PPNO_SHA512_DRNG_GEN,
+                                     &prng_data->ppnows,
+                                     prng_data->prev,
+                                     prng_chunk_size,
+                                     NULL, 0);
+               if (ret < 0 || ret != prng_chunk_size) {
+                       prng_errorflag = PRNG_GEN_FAILED;
+                       ret = -EIO;
+                       goto outfree;
+               }
+       }
+
+       return 0;
+
+outfree:
+       kfree(prng_data);
+       return ret;
+}
+
+
+static void prng_sha512_deinstantiate(void)
+{
+       pr_debug("The prng module stopped after running in SHA-512 mode\n");
+       kzfree(prng_data);
+}
+
+
+static int prng_sha512_reseed(void)
+{
+       int ret;
+       u8 seed[32];
+
+       /* generate 32 bytes of fresh entropy */
+       ret = generate_entropy(seed, sizeof(seed));
+       if (ret != sizeof(seed))
+               return ret;
+
+       /* do a reseed of the ppno drng with this bytestring */
+       ret = crypt_s390_ppno(PPNO_SHA512_DRNG_SEED,
+                             &prng_data->ppnows, NULL, 0,
+                             seed, sizeof(seed));
+       if (ret) {
+               prng_errorflag = PRNG_RESEED_FAILED;
+               return -EIO;
+       }
+
+       return 0;
+}
+
+
+static int prng_sha512_generate(u8 *buf, size_t nbytes)
+{
+       int ret;
+
+       /* reseed needed ? */
+       if (prng_data->ppnows.reseed_counter > prng_reseed_limit) {
+               ret = prng_sha512_reseed();
+               if (ret)
+                       return ret;
+       }
+
+       /* PPNO generate */
+       ret = crypt_s390_ppno(PPNO_SHA512_DRNG_GEN,
+                             &prng_data->ppnows, buf, nbytes,
+                             NULL, 0);
+       if (ret < 0 || ret != nbytes) {
+               prng_errorflag = PRNG_GEN_FAILED;
+               return -EIO;
+       }
+
+       /* FIPS 140-2 Conditional Self Test */
+       if (fips_enabled) {
+               if (!memcmp(prng_data->prev, buf, nbytes)) {
+                       prng_errorflag = PRNG_GEN_FAILED;
+                       return -EILSEQ;
+               }
+               memcpy(prng_data->prev, buf, nbytes);
+       }
+
+       return ret;
+}
+
+
+/*** file io functions ***/
+
+static int prng_open(struct inode *inode, struct file *file)
+{
+       return nonseekable_open(inode, file);
+}
+
+
+static ssize_t prng_tdes_read(struct file *file, char __user *ubuf,
+                             size_t nbytes, loff_t *ppos)
+{
+       int chunk, n, tmp, ret = 0;
+
+       /* lock prng_data struct */
+       if (mutex_lock_interruptible(&prng_data->mutex))
+               return -ERESTARTSYS;
 
-       /* nbytes can be arbitrary length, we split it into chunks */
        while (nbytes) {
-               /* same as in extract_entropy_user in random.c */
                if (need_resched()) {
                        if (signal_pending(current)) {
                                if (ret == 0)
                                        ret = -ERESTARTSYS;
                                break;
                        }
+                       /* give mutex free before calling schedule() */
+                       mutex_unlock(&prng_data->mutex);
                        schedule();
+                       /* occopy mutex again */
+                       if (mutex_lock_interruptible(&prng_data->mutex)) {
+                               if (ret == 0)
+                                       ret = -ERESTARTSYS;
+                               return ret;
+                       }
                }
 
                /*
@@ -112,12 +535,11 @@ static ssize_t prng_read(struct file *file, char __user *ubuf, size_t nbytes,
                /* PRNG only likes multiples of 8 bytes */
                n = (chunk + 7) & -8;
 
-               if (p->count > prng_entropy_limit)
-                       prng_seed(8);
+               if (prng_data->prngws.reseed_counter > prng_reseed_limit)
+                       prng_tdes_seed(8);
 
                /* if the CPU supports PRNG stckf is present too */
-               asm volatile(".insn     s,0xb27c0000,%0"
-                            : "=m" (*((unsigned long long *)p->buf)) : : "cc");
+               *((unsigned long long *)prng_data->buf) = get_tod_clock_fast();
 
                /*
                 * Beside the STCKF the input for the TDES-EDE is the output
@@ -132,35 +554,259 @@ static ssize_t prng_read(struct file *file, char __user *ubuf, size_t nbytes,
                 * Note: you can still get strict X9.17 conformity by setting
                 * prng_chunk_size to 8 bytes.
                */
-               tmp = crypt_s390_kmc(KMC_PRNG, parm_block, p->buf, p->buf, n);
-               BUG_ON((tmp < 0) || (tmp != n));
+               tmp = crypt_s390_kmc(KMC_PRNG, prng_data->prngws.parm_block,
+                                    prng_data->buf, prng_data->buf, n);
+               if (tmp < 0 || tmp != n) {
+                       ret = -EIO;
+                       break;
+               }
 
-               p->count += n;
+               prng_data->prngws.byte_counter += n;
+               prng_data->prngws.reseed_counter += n;
 
-               if (copy_to_user(ubuf, p->buf, chunk))
+               if (copy_to_user(ubuf, prng_data->buf, chunk))
                        return -EFAULT;
 
                nbytes -= chunk;
                ret += chunk;
                ubuf += chunk;
        }
+
+       /* unlock prng_data struct */
+       mutex_unlock(&prng_data->mutex);
+
        return ret;
 }
 
-static const struct file_operations prng_fops = {
+
+static ssize_t prng_sha512_read(struct file *file, char __user *ubuf,
+                               size_t nbytes, loff_t *ppos)
+{
+       int n, ret = 0;
+       u8 *p;
+
+       /* if errorflag is set do nothing and return 'broken pipe' */
+       if (prng_errorflag)
+               return -EPIPE;
+
+       /* lock prng_data struct */
+       if (mutex_lock_interruptible(&prng_data->mutex))
+               return -ERESTARTSYS;
+
+       while (nbytes) {
+               if (need_resched()) {
+                       if (signal_pending(current)) {
+                               if (ret == 0)
+                                       ret = -ERESTARTSYS;
+                               break;
+                       }
+                       /* give mutex free before calling schedule() */
+                       mutex_unlock(&prng_data->mutex);
+                       schedule();
+                       /* occopy mutex again */
+                       if (mutex_lock_interruptible(&prng_data->mutex)) {
+                               if (ret == 0)
+                                       ret = -ERESTARTSYS;
+                               return ret;
+                       }
+               }
+               if (prng_data->rest) {
+                       /* push left over random bytes from the previous read */
+                       p = prng_data->buf + prng_chunk_size - prng_data->rest;
+                       n = (nbytes < prng_data->rest) ?
+                               nbytes : prng_data->rest;
+                       prng_data->rest -= n;
+               } else {
+                       /* generate one chunk of random bytes into read buf */
+                       p = prng_data->buf;
+                       n = prng_sha512_generate(p, prng_chunk_size);
+                       if (n < 0) {
+                               ret = n;
+                               break;
+                       }
+                       if (nbytes < prng_chunk_size) {
+                               n = nbytes;
+                               prng_data->rest = prng_chunk_size - n;
+                       } else {
+                               n = prng_chunk_size;
+                               prng_data->rest = 0;
+                       }
+               }
+               if (copy_to_user(ubuf, p, n)) {
+                       ret = -EFAULT;
+                       break;
+               }
+               ubuf += n;
+               nbytes -= n;
+               ret += n;
+       }
+
+       /* unlock prng_data struct */
+       mutex_unlock(&prng_data->mutex);
+
+       return ret;
+}
+
+
+/*** sysfs stuff ***/
+
+static const struct file_operations prng_sha512_fops = {
+       .owner          = THIS_MODULE,
+       .open           = &prng_open,
+       .release        = NULL,
+       .read           = &prng_sha512_read,
+       .llseek         = noop_llseek,
+};
+static const struct file_operations prng_tdes_fops = {
        .owner          = THIS_MODULE,
        .open           = &prng_open,
        .release        = NULL,
-       .read           = &prng_read,
+       .read           = &prng_tdes_read,
        .llseek         = noop_llseek,
 };
 
-static struct miscdevice prng_dev = {
+static struct miscdevice prng_sha512_dev = {
+       .name   = "prandom",
+       .minor  = MISC_DYNAMIC_MINOR,
+       .fops   = &prng_sha512_fops,
+};
+static struct miscdevice prng_tdes_dev = {
        .name   = "prandom",
        .minor  = MISC_DYNAMIC_MINOR,
-       .fops   = &prng_fops,
+       .fops   = &prng_tdes_fops,
 };
 
+
+/* chunksize attribute (ro) */
+static ssize_t prng_chunksize_show(struct device *dev,
+                                  struct device_attribute *attr,
+                                  char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%u\n", prng_chunk_size);
+}
+static DEVICE_ATTR(chunksize, 0444, prng_chunksize_show, NULL);
+
+/* counter attribute (ro) */
+static ssize_t prng_counter_show(struct device *dev,
+                                struct device_attribute *attr,
+                                char *buf)
+{
+       u64 counter;
+
+       if (mutex_lock_interruptible(&prng_data->mutex))
+               return -ERESTARTSYS;
+       if (prng_mode == PRNG_MODE_SHA512)
+               counter = prng_data->ppnows.stream_bytes;
+       else
+               counter = prng_data->prngws.byte_counter;
+       mutex_unlock(&prng_data->mutex);
+
+       return snprintf(buf, PAGE_SIZE, "%llu\n", counter);
+}
+static DEVICE_ATTR(byte_counter, 0444, prng_counter_show, NULL);
+
+/* errorflag attribute (ro) */
+static ssize_t prng_errorflag_show(struct device *dev,
+                                  struct device_attribute *attr,
+                                  char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%d\n", prng_errorflag);
+}
+static DEVICE_ATTR(errorflag, 0444, prng_errorflag_show, NULL);
+
+/* mode attribute (ro) */
+static ssize_t prng_mode_show(struct device *dev,
+                             struct device_attribute *attr,
+                             char *buf)
+{
+       if (prng_mode == PRNG_MODE_TDES)
+               return snprintf(buf, PAGE_SIZE, "TDES\n");
+       else
+               return snprintf(buf, PAGE_SIZE, "SHA512\n");
+}
+static DEVICE_ATTR(mode, 0444, prng_mode_show, NULL);
+
+/* reseed attribute (w) */
+static ssize_t prng_reseed_store(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buf, size_t count)
+{
+       if (mutex_lock_interruptible(&prng_data->mutex))
+               return -ERESTARTSYS;
+       prng_sha512_reseed();
+       mutex_unlock(&prng_data->mutex);
+
+       return count;
+}
+static DEVICE_ATTR(reseed, 0200, NULL, prng_reseed_store);
+
+/* reseed limit attribute (rw) */
+static ssize_t prng_reseed_limit_show(struct device *dev,
+                                     struct device_attribute *attr,
+                                     char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%u\n", prng_reseed_limit);
+}
+static ssize_t prng_reseed_limit_store(struct device *dev,
+                                      struct device_attribute *attr,
+                                      const char *buf, size_t count)
+{
+       unsigned limit;
+
+       if (sscanf(buf, "%u\n", &limit) != 1)
+               return -EINVAL;
+
+       if (prng_mode == PRNG_MODE_SHA512) {
+               if (limit < PRNG_RESEED_LIMIT_SHA512_LOWER)
+                       return -EINVAL;
+       } else {
+               if (limit < PRNG_RESEED_LIMIT_TDES_LOWER)
+                       return -EINVAL;
+       }
+
+       prng_reseed_limit = limit;
+
+       return count;
+}
+static DEVICE_ATTR(reseed_limit, 0644,
+                  prng_reseed_limit_show, prng_reseed_limit_store);
+
+/* strength attribute (ro) */
+static ssize_t prng_strength_show(struct device *dev,
+                                 struct device_attribute *attr,
+                                 char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "256\n");
+}
+static DEVICE_ATTR(strength, 0444, prng_strength_show, NULL);
+
+static struct attribute *prng_sha512_dev_attrs[] = {
+       &dev_attr_errorflag.attr,
+       &dev_attr_chunksize.attr,
+       &dev_attr_byte_counter.attr,
+       &dev_attr_mode.attr,
+       &dev_attr_reseed.attr,
+       &dev_attr_reseed_limit.attr,
+       &dev_attr_strength.attr,
+       NULL
+};
+static struct attribute *prng_tdes_dev_attrs[] = {
+       &dev_attr_chunksize.attr,
+       &dev_attr_byte_counter.attr,
+       &dev_attr_mode.attr,
+       NULL
+};
+
+static struct attribute_group prng_sha512_dev_attr_group = {
+       .attrs = prng_sha512_dev_attrs
+};
+static struct attribute_group prng_tdes_dev_attr_group = {
+       .attrs = prng_tdes_dev_attrs
+};
+
+
+/*** module init and exit ***/
+
 static int __init prng_init(void)
 {
        int ret;
@@ -169,43 +815,105 @@ static int __init prng_init(void)
        if (!crypt_s390_func_available(KMC_PRNG, CRYPT_S390_MSA))
                return -EOPNOTSUPP;
 
-       if (prng_chunk_size < 8)
-               return -EINVAL;
+       /* choose prng mode */
+       if (prng_mode != PRNG_MODE_TDES) {
+               /* check for MSA5 support for PPNO operations */
+               if (!crypt_s390_func_available(PPNO_SHA512_DRNG_GEN,
+                                              CRYPT_S390_MSA5)) {
+                       if (prng_mode == PRNG_MODE_SHA512) {
+                               pr_err("The prng module cannot "
+                                      "start in SHA-512 mode\n");
+                               return -EOPNOTSUPP;
+                       }
+                       prng_mode = PRNG_MODE_TDES;
+               } else
+                       prng_mode = PRNG_MODE_SHA512;
+       }
 
-       p = kmalloc(sizeof(struct s390_prng_data), GFP_KERNEL);
-       if (!p)
-               return -ENOMEM;
-       p->count = 0;
+       if (prng_mode == PRNG_MODE_SHA512) {
 
-       p->buf = kmalloc(prng_chunk_size, GFP_KERNEL);
-       if (!p->buf) {
-               ret = -ENOMEM;
-               goto out_free;
-       }
+               /* SHA512 mode */
 
-       /* initialize the PRNG, add 128 bits of entropy */
-       prng_seed(16);
+               if (prng_chunk_size < PRNG_CHUNKSIZE_SHA512_MIN
+                   || prng_chunk_size > PRNG_CHUNKSIZE_SHA512_MAX)
+                       return -EINVAL;
+               prng_chunk_size = (prng_chunk_size + 0x3f) & ~0x3f;
 
-       ret = misc_register(&prng_dev);
-       if (ret)
-               goto out_buf;
-       return 0;
+               if (prng_reseed_limit == 0)
+                       prng_reseed_limit = PRNG_RESEED_LIMIT_SHA512;
+               else if (prng_reseed_limit < PRNG_RESEED_LIMIT_SHA512_LOWER)
+                       return -EINVAL;
+
+               ret = prng_sha512_instantiate();
+               if (ret)
+                       goto out;
+
+               ret = misc_register(&prng_sha512_dev);
+               if (ret) {
+                       prng_sha512_deinstantiate();
+                       goto out;
+               }
+               ret = sysfs_create_group(&prng_sha512_dev.this_device->kobj,
+                                        &prng_sha512_dev_attr_group);
+               if (ret) {
+                       misc_deregister(&prng_sha512_dev);
+                       prng_sha512_deinstantiate();
+                       goto out;
+               }
 
-out_buf:
-       kfree(p->buf);
-out_free:
-       kfree(p);
+       } else {
+
+               /* TDES mode */
+
+               if (prng_chunk_size < PRNG_CHUNKSIZE_TDES_MIN
+                   || prng_chunk_size > PRNG_CHUNKSIZE_TDES_MAX)
+                       return -EINVAL;
+               prng_chunk_size = (prng_chunk_size + 0x07) & ~0x07;
+
+               if (prng_reseed_limit == 0)
+                       prng_reseed_limit = PRNG_RESEED_LIMIT_TDES;
+               else if (prng_reseed_limit < PRNG_RESEED_LIMIT_TDES_LOWER)
+                       return -EINVAL;
+
+               ret = prng_tdes_instantiate();
+               if (ret)
+                       goto out;
+
+               ret = misc_register(&prng_tdes_dev);
+               if (ret) {
+                       prng_tdes_deinstantiate();
+                       goto out;
+               }
+               ret = sysfs_create_group(&prng_tdes_dev.this_device->kobj,
+                                        &prng_tdes_dev_attr_group);
+               if (ret) {
+                       misc_deregister(&prng_tdes_dev);
+                       prng_tdes_deinstantiate();
+                       goto out;
+               }
+
+       }
+
+out:
        return ret;
 }
 
+
 static void __exit prng_exit(void)
 {
-       /* wipe me */
-       kzfree(p->buf);
-       kfree(p);
-
-       misc_deregister(&prng_dev);
+       if (prng_mode == PRNG_MODE_SHA512) {
+               sysfs_remove_group(&prng_sha512_dev.this_device->kobj,
+                                  &prng_sha512_dev_attr_group);
+               misc_deregister(&prng_sha512_dev);
+               prng_sha512_deinstantiate();
+       } else {
+               sysfs_remove_group(&prng_tdes_dev.this_device->kobj,
+                                  &prng_tdes_dev_attr_group);
+               misc_deregister(&prng_tdes_dev);
+               prng_tdes_deinstantiate();
+       }
 }
 
+
 module_init(prng_init);
 module_exit(prng_exit);
index 3f5c799b7fb53aecc3af6cf8b877705cb0e8bd0e..d3f896a35b9813080351f1bb7be178f127114c19 100644 (file)
@@ -48,7 +48,7 @@ static struct dentry *hypfs_last_dentry;
 static void hypfs_update_update(struct super_block *sb)
 {
        struct hypfs_sb_info *sb_info = sb->s_fs_info;
-       struct inode *inode = sb_info->update_file->d_inode;
+       struct inode *inode = d_inode(sb_info->update_file);
 
        sb_info->last_update = get_seconds();
        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
@@ -64,7 +64,7 @@ static void hypfs_add_dentry(struct dentry *dentry)
 
 static inline int hypfs_positive(struct dentry *dentry)
 {
-       return dentry->d_inode && !d_unhashed(dentry);
+       return d_really_is_positive(dentry) && !d_unhashed(dentry);
 }
 
 static void hypfs_remove(struct dentry *dentry)
@@ -72,16 +72,16 @@ static void hypfs_remove(struct dentry *dentry)
        struct dentry *parent;
 
        parent = dentry->d_parent;
-       mutex_lock(&parent->d_inode->i_mutex);
+       mutex_lock(&d_inode(parent)->i_mutex);
        if (hypfs_positive(dentry)) {
                if (d_is_dir(dentry))
-                       simple_rmdir(parent->d_inode, dentry);
+                       simple_rmdir(d_inode(parent), dentry);
                else
-                       simple_unlink(parent->d_inode, dentry);
+                       simple_unlink(d_inode(parent), dentry);
        }
        d_delete(dentry);
        dput(dentry);
-       mutex_unlock(&parent->d_inode->i_mutex);
+       mutex_unlock(&d_inode(parent)->i_mutex);
 }
 
 static void hypfs_delete_tree(struct dentry *root)
@@ -336,7 +336,7 @@ static struct dentry *hypfs_create_file(struct dentry *parent, const char *name,
        struct dentry *dentry;
        struct inode *inode;
 
-       mutex_lock(&parent->d_inode->i_mutex);
+       mutex_lock(&d_inode(parent)->i_mutex);
        dentry = lookup_one_len(name, parent, strlen(name));
        if (IS_ERR(dentry)) {
                dentry = ERR_PTR(-ENOMEM);
@@ -357,14 +357,14 @@ static struct dentry *hypfs_create_file(struct dentry *parent, const char *name,
        } else if (S_ISDIR(mode)) {
                inode->i_op = &simple_dir_inode_operations;
                inode->i_fop = &simple_dir_operations;
-               inc_nlink(parent->d_inode);
+               inc_nlink(d_inode(parent));
        } else
                BUG();
        inode->i_private = data;
        d_instantiate(dentry, inode);
        dget(dentry);
 fail:
-       mutex_unlock(&parent->d_inode->i_mutex);
+       mutex_unlock(&d_inode(parent)->i_mutex);
        return dentry;
 }
 
index 694bcd6bd927bff60bf76ceede7a222877e02999..2f924bc30e358542201bdde082ab6d0289f3403c 100644 (file)
@@ -26,6 +26,9 @@
 /* Not more than 2GB */
 #define KEXEC_CONTROL_MEMORY_LIMIT (1UL<<31)
 
+/* Allocate control page with GFP_DMA */
+#define KEXEC_CONTROL_MEMORY_GFP GFP_DMA
+
 /* Maximum address we can use for the crash control pages */
 #define KEXEC_CRASH_CONTROL_MEMORY_LIMIT (-1UL)
 
index a5e656260a70183dd4f3768c3be082fed5988603..d29ad9545b4187a18c660e1ad62922b052447478 100644 (file)
@@ -14,7 +14,9 @@ typedef struct {
        unsigned long asce_bits;
        unsigned long asce_limit;
        unsigned long vdso_base;
-       /* The mmu context has extended page tables. */
+       /* The mmu context allocates 4K page tables. */
+       unsigned int alloc_pgste:1;
+       /* The mmu context uses extended page tables. */
        unsigned int has_pgste:1;
        /* The mmu context uses storage keys. */
        unsigned int use_skey:1;
index d25d9ff10ba8fe2e2d7e53fea8c2a73b16facf61..fb1b93ea3e3fead0efde9f30e819c55eecb88da9 100644 (file)
@@ -20,8 +20,11 @@ static inline int init_new_context(struct task_struct *tsk,
        mm->context.flush_mm = 0;
        mm->context.asce_bits = _ASCE_TABLE_LENGTH | _ASCE_USER_BITS;
        mm->context.asce_bits |= _ASCE_TYPE_REGION3;
+#ifdef CONFIG_PGSTE
+       mm->context.alloc_pgste = page_table_allocate_pgste;
        mm->context.has_pgste = 0;
        mm->context.use_skey = 0;
+#endif
        mm->context.asce_limit = STACK_TOP_MAX;
        crst_table_init((unsigned long *) mm->pgd, pgd_entry_type(mm));
        return 0;
index 51e7fb634ebc1e6bab2bfdac3655443096296ad3..7b7858f158b4574b549ab99648f977a3e249068c 100644 (file)
@@ -21,6 +21,7 @@ void crst_table_free(struct mm_struct *, unsigned long *);
 unsigned long *page_table_alloc(struct mm_struct *);
 void page_table_free(struct mm_struct *, unsigned long *);
 void page_table_free_rcu(struct mmu_gather *, unsigned long *, unsigned long);
+extern int page_table_allocate_pgste;
 
 int set_guest_storage_key(struct mm_struct *mm, unsigned long addr,
                          unsigned long key, bool nq);
index 989cfae9e202cf1d5adfdd894af3324997aec65a..fc642399b489d896f2b4494cc57456ab7bd2ddb9 100644 (file)
 #define _ASM_S390_PGTABLE_H
 
 /*
- * The Linux memory management assumes a three-level page table setup. For
- * s390 31 bit we "fold" the mid level into the top-level page table, so
- * that we physically have the same two-level page table as the s390 mmu
- * expects in 31 bit mode. For s390 64 bit we use three of the five levels
- * the hardware provides (region first and region second tables are not
- * used).
+ * The Linux memory management assumes a three-level page table setup.
+ * For s390 64 bit we use up to four of the five levels the hardware
+ * provides (region first tables are not used).
  *
  * The "pgd_xxx()" functions are trivial for a folded two-level
  * setup: the pgd is never bad, and a pmd always exists (as it's folded
@@ -101,8 +98,8 @@ extern unsigned long zero_page_mask;
 
 #ifndef __ASSEMBLY__
 /*
- * The vmalloc and module area will always be on the topmost area of the kernel
- * mapping. We reserve 96MB (31bit) / 128GB (64bit) for vmalloc and modules.
+ * The vmalloc and module area will always be on the topmost area of the
+ * kernel mapping. We reserve 128GB (64bit) for vmalloc and modules.
  * On 64 bit kernels we have a 2GB area at the top of the vmalloc area where
  * modules will reside. That makes sure that inter module branches always
  * happen without trampolines and in addition the placement within a 2GB frame
@@ -131,38 +128,6 @@ static inline int is_module_addr(void *addr)
 }
 
 /*
- * A 31 bit pagetable entry of S390 has following format:
- *  |   PFRA          |    |  OS  |
- * 0                   0IP0
- * 00000000001111111111222222222233
- * 01234567890123456789012345678901
- *
- * I Page-Invalid Bit:    Page is not available for address-translation
- * P Page-Protection Bit: Store access not possible for page
- *
- * A 31 bit segmenttable entry of S390 has following format:
- *  |   P-table origin      |  |PTL
- * 0                         IC
- * 00000000001111111111222222222233
- * 01234567890123456789012345678901
- *
- * I Segment-Invalid Bit:    Segment is not available for address-translation
- * C Common-Segment Bit:     Segment is not private (PoP 3-30)
- * PTL Page-Table-Length:    Page-table length (PTL+1*16 entries -> up to 256)
- *
- * The 31 bit segmenttable origin of S390 has following format:
- *
- *  |S-table origin   |     | STL |
- * X                   **GPS
- * 00000000001111111111222222222233
- * 01234567890123456789012345678901
- *
- * X Space-Switch event:
- * G Segment-Invalid Bit:     *
- * P Private-Space Bit:       Segment is not private (PoP 3-30)
- * S Storage-Alteration:
- * STL Segment-Table-Length:  Segment-table length (STL+1*16 entries -> up to 2048)
- *
  * A 64 bit pagetable entry of S390 has following format:
  * |                    PFRA                         |0IPC|  OS  |
  * 0000000000111111111122222222223333333333444444444455555555556666
@@ -220,7 +185,6 @@ static inline int is_module_addr(void *addr)
 
 /* Software bits in the page table entry */
 #define _PAGE_PRESENT  0x001           /* SW pte present bit */
-#define _PAGE_TYPE     0x002           /* SW pte type bit */
 #define _PAGE_YOUNG    0x004           /* SW pte young bit */
 #define _PAGE_DIRTY    0x008           /* SW pte dirty bit */
 #define _PAGE_READ     0x010           /* SW pte read bit */
@@ -240,31 +204,34 @@ static inline int is_module_addr(void *addr)
  * table lock held.
  *
  * The following table gives the different possible bit combinations for
- * the pte hardware and software bits in the last 12 bits of a pte:
+ * the pte hardware and software bits in the last 12 bits of a pte
+ * (. unassigned bit, x don't care, t swap type):
  *
  *                             842100000000
  *                             000084210000
  *                             000000008421
- *                             .IR...wrdytp
- * empty                       .10...000000
- * swap                                .10...xxxx10
- * file                                .11...xxxxx0
- * prot-none, clean, old       .11...000001
- * prot-none, clean, young     .11...000101
- * prot-none, dirty, old       .10...001001
- * prot-none, dirty, young     .10...001101
- * read-only, clean, old       .11...010001
- * read-only, clean, young     .01...010101
- * read-only, dirty, old       .11...011001
- * read-only, dirty, young     .01...011101
- * read-write, clean, old      .11...110001
- * read-write, clean, young    .01...110101
- * read-write, dirty, old      .10...111001
- * read-write, dirty, young    .00...111101
+ *                             .IR.uswrdy.p
+ * empty                       .10.00000000
+ * swap                                .11..ttttt.0
+ * prot-none, clean, old       .11.xx0000.1
+ * prot-none, clean, young     .11.xx0001.1
+ * prot-none, dirty, old       .10.xx0010.1
+ * prot-none, dirty, young     .10.xx0011.1
+ * read-only, clean, old       .11.xx0100.1
+ * read-only, clean, young     .01.xx0101.1
+ * read-only, dirty, old       .11.xx0110.1
+ * read-only, dirty, young     .01.xx0111.1
+ * read-write, clean, old      .11.xx1100.1
+ * read-write, clean, young    .01.xx1101.1
+ * read-write, dirty, old      .10.xx1110.1
+ * read-write, dirty, young    .00.xx1111.1
+ * HW-bits: R read-only, I invalid
+ * SW-bits: p present, y young, d dirty, r read, w write, s special,
+ *         u unused, l large
  *
- * pte_present is true for the bit pattern .xx...xxxxx1, (pte & 0x001) == 0x001
- * pte_none    is true for the bit pattern .10...xxxx00, (pte & 0x603) == 0x400
- * pte_swap    is true for the bit pattern .10...xxxx10, (pte & 0x603) == 0x402
+ * pte_none    is true for the bit pattern .10.00000000, pte == 0x400
+ * pte_swap    is true for the bit pattern .11..ooooo.0, (pte & 0x201) == 0x200
+ * pte_present is true for the bit pattern .xx.xxxxxx.1, (pte & 0x001) == 0x001
  */
 
 /* Bits in the segment/region table address-space-control-element */
@@ -335,6 +302,8 @@ static inline int is_module_addr(void *addr)
  * read-write, dirty, young    11..0...0...11
  * The segment table origin is used to distinguish empty (origin==0) from
  * read-write, old segment table entries (origin!=0)
+ * HW-bits: R read-only, I invalid
+ * SW-bits: y young, d dirty, r read, w write
  */
 
 #define _SEGMENT_ENTRY_SPLIT_BIT 11    /* THP splitting bit number */
@@ -423,6 +392,15 @@ static inline int mm_has_pgste(struct mm_struct *mm)
        return 0;
 }
 
+static inline int mm_alloc_pgste(struct mm_struct *mm)
+{
+#ifdef CONFIG_PGSTE
+       if (unlikely(mm->context.alloc_pgste))
+               return 1;
+#endif
+       return 0;
+}
+
 /*
  * In the case that a guest uses storage keys
  * faults should no longer be backed by zero pages
@@ -582,10 +560,9 @@ static inline int pte_none(pte_t pte)
 
 static inline int pte_swap(pte_t pte)
 {
-       /* Bit pattern: (pte & 0x603) == 0x402 */
-       return (pte_val(pte) & (_PAGE_INVALID | _PAGE_PROTECT |
-                               _PAGE_TYPE | _PAGE_PRESENT))
-               == (_PAGE_INVALID | _PAGE_TYPE);
+       /* Bit pattern: (pte & 0x201) == 0x200 */
+       return (pte_val(pte) & (_PAGE_PROTECT | _PAGE_PRESENT))
+               == _PAGE_PROTECT;
 }
 
 static inline int pte_special(pte_t pte)
@@ -1586,51 +1563,51 @@ static inline int has_transparent_hugepage(void)
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
 
 /*
- * 31 bit swap entry format:
- * A page-table entry has some bits we have to treat in a special way.
- * Bits 0, 20 and bit 23 have to be zero, otherwise an specification
- * exception will occur instead of a page translation exception. The
- * specifiation exception has the bad habit not to store necessary
- * information in the lowcore.
- * Bits 21, 22, 30 and 31 are used to indicate the page type.
- * A swap pte is indicated by bit pattern (pte & 0x603) == 0x402
- * This leaves the bits 1-19 and bits 24-29 to store type and offset.
- * We use the 5 bits from 25-29 for the type and the 20 bits from 1-19
- * plus 24 for the offset.
- * 0|     offset        |0110|o|type |00|
- * 0 0000000001111111111 2222 2 22222 33
- * 0 1234567890123456789 0123 4 56789 01
- *
  * 64 bit swap entry format:
  * A page-table entry has some bits we have to treat in a special way.
  * Bits 52 and bit 55 have to be zero, otherwise an specification
  * exception will occur instead of a page translation exception. The
  * specifiation exception has the bad habit not to store necessary
  * information in the lowcore.
- * Bits 53, 54, 62 and 63 are used to indicate the page type.
- * A swap pte is indicated by bit pattern (pte & 0x603) == 0x402
- * This leaves the bits 0-51 and bits 56-61 to store type and offset.
- * We use the 5 bits from 57-61 for the type and the 53 bits from 0-51
- * plus 56 for the offset.
- * |                      offset                        |0110|o|type |00|
- *  0000000000111111111122222222223333333333444444444455 5555 5 55566 66
- *  0123456789012345678901234567890123456789012345678901 2345 6 78901 23
+ * Bits 54 and 63 are used to indicate the page type.
+ * A swap pte is indicated by bit pattern (pte & 0x201) == 0x200
+ * This leaves the bits 0-51 and bits 56-62 to store type and offset.
+ * We use the 5 bits from 57-61 for the type and the 52 bits from 0-51
+ * for the offset.
+ * |                     offset                        |01100|type |00|
+ * |0000000000111111111122222222223333333333444444444455|55555|55566|66|
+ * |0123456789012345678901234567890123456789012345678901|23456|78901|23|
  */
 
-#define __SWP_OFFSET_MASK (~0UL >> 11)
+#define __SWP_OFFSET_MASK      ((1UL << 52) - 1)
+#define __SWP_OFFSET_SHIFT     12
+#define __SWP_TYPE_MASK                ((1UL << 5) - 1)
+#define __SWP_TYPE_SHIFT       2
 
 static inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
 {
        pte_t pte;
-       offset &= __SWP_OFFSET_MASK;
-       pte_val(pte) = _PAGE_INVALID | _PAGE_TYPE | ((type & 0x1f) << 2) |
-               ((offset & 1UL) << 7) | ((offset & ~1UL) << 11);
+
+       pte_val(pte) = _PAGE_INVALID | _PAGE_PROTECT;
+       pte_val(pte) |= (offset & __SWP_OFFSET_MASK) << __SWP_OFFSET_SHIFT;
+       pte_val(pte) |= (type & __SWP_TYPE_MASK) << __SWP_TYPE_SHIFT;
        return pte;
 }
 
-#define __swp_type(entry)      (((entry).val >> 2) & 0x1f)
-#define __swp_offset(entry)    (((entry).val >> 11) | (((entry).val >> 7) & 1))
-#define __swp_entry(type,offset) ((swp_entry_t) { pte_val(mk_swap_pte((type),(offset))) })
+static inline unsigned long __swp_type(swp_entry_t entry)
+{
+       return (entry.val >> __SWP_TYPE_SHIFT) & __SWP_TYPE_MASK;
+}
+
+static inline unsigned long __swp_offset(swp_entry_t entry)
+{
+       return (entry.val >> __SWP_OFFSET_SHIFT) & __SWP_OFFSET_MASK;
+}
+
+static inline swp_entry_t __swp_entry(unsigned long type, unsigned long offset)
+{
+       return (swp_entry_t) { pte_val(mk_swap_pte(type, offset)) };
+}
 
 #define __pte_to_swp_entry(pte)        ((swp_entry_t) { pte_val(pte) })
 #define __swp_entry_to_pte(x)  ((pte_t) { (x).val })
index afa2bd750ffc814d36300bc491a0a6eff516bda4..8cd8e7b288c5db84bf358785bb9aee4510c69050 100644 (file)
@@ -110,7 +110,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
 /* upper facilities limit for kvm */
 unsigned long kvm_s390_fac_list_mask[] = {
        0xffe6fffbfcfdfc40UL,
-       0x205c800000000000UL,
+       0x005c800000000000UL,
 };
 
 unsigned long kvm_s390_fac_list_mask_size(void)
index 210ffede0153130d40ce222a15c559057b114e1e..e617e74b7be22aade65168f2c103c32b18b18653 100644 (file)
@@ -14,20 +14,23 @@ static inline pmd_t __pte_to_pmd(pte_t pte)
 
        /*
         * Convert encoding               pte bits         pmd bits
-        *                              .IR...wrdytp    dy..R...I...wr
-        * empty                        .10...000000 -> 00..0...1...00
-        * prot-none, clean, old        .11...000001 -> 00..1...1...00
-        * prot-none, clean, young      .11...000101 -> 01..1...1...00
-        * prot-none, dirty, old        .10...001001 -> 10..1...1...00
-        * prot-none, dirty, young      .10...001101 -> 11..1...1...00
-        * read-only, clean, old        .11...010001 -> 00..1...1...01
-        * read-only, clean, young      .01...010101 -> 01..1...0...01
-        * read-only, dirty, old        .11...011001 -> 10..1...1...01
-        * read-only, dirty, young      .01...011101 -> 11..1...0...01
-        * read-write, clean, old       .11...110001 -> 00..0...1...11
-        * read-write, clean, young     .01...110101 -> 01..0...0...11
-        * read-write, dirty, old       .10...111001 -> 10..0...1...11
-        * read-write, dirty, young     .00...111101 -> 11..0...0...11
+        *                              lIR.uswrdy.p    dy..R...I...wr
+        * empty                        010.000000.0 -> 00..0...1...00
+        * prot-none, clean, old        111.000000.1 -> 00..1...1...00
+        * prot-none, clean, young      111.000001.1 -> 01..1...1...00
+        * prot-none, dirty, old        111.000010.1 -> 10..1...1...00
+        * prot-none, dirty, young      111.000011.1 -> 11..1...1...00
+        * read-only, clean, old        111.000100.1 -> 00..1...1...01
+        * read-only, clean, young      101.000101.1 -> 01..1...0...01
+        * read-only, dirty, old        111.000110.1 -> 10..1...1...01
+        * read-only, dirty, young      101.000111.1 -> 11..1...0...01
+        * read-write, clean, old       111.001100.1 -> 00..1...1...11
+        * read-write, clean, young     101.001101.1 -> 01..1...0...11
+        * read-write, dirty, old       110.001110.1 -> 10..0...1...11
+        * read-write, dirty, young     100.001111.1 -> 11..0...0...11
+        * HW-bits: R read-only, I invalid
+        * SW-bits: p present, y young, d dirty, r read, w write, s special,
+        *          u unused, l large
         */
        if (pte_present(pte)) {
                pmd_val(pmd) = pte_val(pte) & PAGE_MASK;
@@ -48,20 +51,23 @@ static inline pte_t __pmd_to_pte(pmd_t pmd)
 
        /*
         * Convert encoding                pmd bits         pte bits
-        *                              dy..R...I...wr    .IR...wrdytp
-        * empty                        00..0...1...00 -> .10...001100
-        * prot-none, clean, old        00..0...1...00 -> .10...000001
-        * prot-none, clean, young      01..0...1...00 -> .10...000101
-        * prot-none, dirty, old        10..0...1...00 -> .10...001001
-        * prot-none, dirty, young      11..0...1...00 -> .10...001101
-        * read-only, clean, old        00..1...1...01 -> .11...010001
-        * read-only, clean, young      01..1...1...01 -> .11...010101
-        * read-only, dirty, old        10..1...1...01 -> .11...011001
-        * read-only, dirty, young      11..1...1...01 -> .11...011101
-        * read-write, clean, old       00..0...1...11 -> .10...110001
-        * read-write, clean, young     01..0...1...11 -> .10...110101
-        * read-write, dirty, old       10..0...1...11 -> .10...111001
-        * read-write, dirty, young     11..0...1...11 -> .10...111101
+        *                              dy..R...I...wr    lIR.uswrdy.p
+        * empty                        00..0...1...00 -> 010.000000.0
+        * prot-none, clean, old        00..1...1...00 -> 111.000000.1
+        * prot-none, clean, young      01..1...1...00 -> 111.000001.1
+        * prot-none, dirty, old        10..1...1...00 -> 111.000010.1
+        * prot-none, dirty, young      11..1...1...00 -> 111.000011.1
+        * read-only, clean, old        00..1...1...01 -> 111.000100.1
+        * read-only, clean, young      01..1...0...01 -> 101.000101.1
+        * read-only, dirty, old        10..1...1...01 -> 111.000110.1
+        * read-only, dirty, young      11..1...0...01 -> 101.000111.1
+        * read-write, clean, old       00..1...1...11 -> 111.001100.1
+        * read-write, clean, young     01..1...0...11 -> 101.001101.1
+        * read-write, dirty, old       10..0...1...11 -> 110.001110.1
+        * read-write, dirty, young     11..0...0...11 -> 100.001111.1
+        * HW-bits: R read-only, I invalid
+        * SW-bits: p present, y young, d dirty, r read, w write, s special,
+        *          u unused, l large
         */
        if (pmd_present(pmd)) {
                pte_val(pte) = pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN_LARGE;
@@ -70,8 +76,8 @@ static inline pte_t __pmd_to_pte(pmd_t pmd)
                pte_val(pte) |= (pmd_val(pmd) & _SEGMENT_ENTRY_WRITE) << 4;
                pte_val(pte) |= (pmd_val(pmd) & _SEGMENT_ENTRY_INVALID) << 5;
                pte_val(pte) |= (pmd_val(pmd) & _SEGMENT_ENTRY_PROTECT);
-               pmd_val(pmd) |= (pte_val(pte) & _PAGE_DIRTY) << 10;
-               pmd_val(pmd) |= (pte_val(pte) & _PAGE_YOUNG) << 10;
+               pte_val(pte) |= (pmd_val(pmd) & _SEGMENT_ENTRY_DIRTY) >> 10;
+               pte_val(pte) |= (pmd_val(pmd) & _SEGMENT_ENTRY_YOUNG) >> 10;
        } else
                pte_val(pte) = _PAGE_INVALID;
        return pte;
index 33f5894591138ea75ec12b2e9d6cf64492b6ced3..b33f66110ca9401418f7d657b951d8bfb84d99c3 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/rcupdate.h>
 #include <linux/slab.h>
 #include <linux/swapops.h>
+#include <linux/sysctl.h>
 #include <linux/ksm.h>
 #include <linux/mman.h>
 
@@ -920,6 +921,40 @@ unsigned long get_guest_storage_key(struct mm_struct *mm, unsigned long addr)
 }
 EXPORT_SYMBOL(get_guest_storage_key);
 
+static int page_table_allocate_pgste_min = 0;
+static int page_table_allocate_pgste_max = 1;
+int page_table_allocate_pgste = 0;
+EXPORT_SYMBOL(page_table_allocate_pgste);
+
+static struct ctl_table page_table_sysctl[] = {
+       {
+               .procname       = "allocate_pgste",
+               .data           = &page_table_allocate_pgste,
+               .maxlen         = sizeof(int),
+               .mode           = S_IRUGO | S_IWUSR,
+               .proc_handler   = proc_dointvec,
+               .extra1         = &page_table_allocate_pgste_min,
+               .extra2         = &page_table_allocate_pgste_max,
+       },
+       { }
+};
+
+static struct ctl_table page_table_sysctl_dir[] = {
+       {
+               .procname       = "vm",
+               .maxlen         = 0,
+               .mode           = 0555,
+               .child          = page_table_sysctl,
+       },
+       { }
+};
+
+static int __init page_table_register_sysctl(void)
+{
+       return register_sysctl_table(page_table_sysctl_dir) ? 0 : -ENOMEM;
+}
+__initcall(page_table_register_sysctl);
+
 #else /* CONFIG_PGSTE */
 
 static inline int page_table_with_pgste(struct page *page)
@@ -963,7 +998,7 @@ unsigned long *page_table_alloc(struct mm_struct *mm)
        struct page *uninitialized_var(page);
        unsigned int mask, bit;
 
-       if (mm_has_pgste(mm))
+       if (mm_alloc_pgste(mm))
                return page_table_alloc_pgste(mm);
        /* Allocate fragments of a 4K page as 1K/2K page table */
        spin_lock_bh(&mm->context.list_lock);
@@ -1165,116 +1200,25 @@ static inline void thp_split_mm(struct mm_struct *mm)
 }
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
 
-static unsigned long page_table_realloc_pmd(struct mmu_gather *tlb,
-                               struct mm_struct *mm, pud_t *pud,
-                               unsigned long addr, unsigned long end)
-{
-       unsigned long next, *table, *new;
-       struct page *page;
-       spinlock_t *ptl;
-       pmd_t *pmd;
-
-       pmd = pmd_offset(pud, addr);
-       do {
-               next = pmd_addr_end(addr, end);
-again:
-               if (pmd_none_or_clear_bad(pmd))
-                       continue;
-               table = (unsigned long *) pmd_deref(*pmd);
-               page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
-               if (page_table_with_pgste(page))
-                       continue;
-               /* Allocate new page table with pgstes */
-               new = page_table_alloc_pgste(mm);
-               if (!new)
-                       return -ENOMEM;
-
-               ptl = pmd_lock(mm, pmd);
-               if (likely((unsigned long *) pmd_deref(*pmd) == table)) {
-                       /* Nuke pmd entry pointing to the "short" page table */
-                       pmdp_flush_lazy(mm, addr, pmd);
-                       pmd_clear(pmd);
-                       /* Copy ptes from old table to new table */
-                       memcpy(new, table, PAGE_SIZE/2);
-                       clear_table(table, _PAGE_INVALID, PAGE_SIZE/2);
-                       /* Establish new table */
-                       pmd_populate(mm, pmd, (pte_t *) new);
-                       /* Free old table with rcu, there might be a walker! */
-                       page_table_free_rcu(tlb, table, addr);
-                       new = NULL;
-               }
-               spin_unlock(ptl);
-               if (new) {
-                       page_table_free_pgste(new);
-                       goto again;
-               }
-       } while (pmd++, addr = next, addr != end);
-
-       return addr;
-}
-
-static unsigned long page_table_realloc_pud(struct mmu_gather *tlb,
-                                  struct mm_struct *mm, pgd_t *pgd,
-                                  unsigned long addr, unsigned long end)
-{
-       unsigned long next;
-       pud_t *pud;
-
-       pud = pud_offset(pgd, addr);
-       do {
-               next = pud_addr_end(addr, end);
-               if (pud_none_or_clear_bad(pud))
-                       continue;
-               next = page_table_realloc_pmd(tlb, mm, pud, addr, next);
-               if (unlikely(IS_ERR_VALUE(next)))
-                       return next;
-       } while (pud++, addr = next, addr != end);
-
-       return addr;
-}
-
-static unsigned long page_table_realloc(struct mmu_gather *tlb, struct mm_struct *mm,
-                                       unsigned long addr, unsigned long end)
-{
-       unsigned long next;
-       pgd_t *pgd;
-
-       pgd = pgd_offset(mm, addr);
-       do {
-               next = pgd_addr_end(addr, end);
-               if (pgd_none_or_clear_bad(pgd))
-                       continue;
-               next = page_table_realloc_pud(tlb, mm, pgd, addr, next);
-               if (unlikely(IS_ERR_VALUE(next)))
-                       return next;
-       } while (pgd++, addr = next, addr != end);
-
-       return 0;
-}
-
 /*
  * switch on pgstes for its userspace process (for kvm)
  */
 int s390_enable_sie(void)
 {
-       struct task_struct *tsk = current;
-       struct mm_struct *mm = tsk->mm;
-       struct mmu_gather tlb;
+       struct mm_struct *mm = current->mm;
 
        /* Do we have pgstes? if yes, we are done */
-       if (mm_has_pgste(tsk->mm))
+       if (mm_has_pgste(mm))
                return 0;
-
+       /* Fail if the page tables are 2K */
+       if (!mm_alloc_pgste(mm))
+               return -EINVAL;
        down_write(&mm->mmap_sem);
+       mm->context.has_pgste = 1;
        /* split thp mappings and disable thp for future mappings */
        thp_split_mm(mm);
-       /* Reallocate the page tables with pgstes */
-       tlb_gather_mmu(&tlb, mm, 0, TASK_SIZE);
-       if (!page_table_realloc(&tlb, mm, 0, TASK_SIZE))
-               mm->context.has_pgste = 1;
-       tlb_finish_mmu(&tlb, 0, TASK_SIZE);
        up_write(&mm->mmap_sem);
-       return mm->context.has_pgste ? 0 : -ENOMEM;
+       return 0;
 }
 EXPORT_SYMBOL_GPL(s390_enable_sie);
 
index 669df51a82e3bb7024dbdd68f6f87a79702d867e..324599bfad14204a4b9ef9a56890346d6cb2b322 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
 #include <linux/io.h>
+#include <linux/mfd/tmio.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/sh_mmcif.h>
 #include <linux/mmc/sh_mobile_sdhi.h>
@@ -243,10 +244,10 @@ static struct platform_device sh_mmcif_device = {
 };
 
 /* SDHI0 */
-static struct sh_mobile_sdhi_info sdhi_info = {
-       .dma_slave_tx   = SHDMA_SLAVE_SDHI_TX,
-       .dma_slave_rx   = SHDMA_SLAVE_SDHI_RX,
-       .tmio_caps      = MMC_CAP_SD_HIGHSPEED,
+static struct tmio_mmc_data sdhi_info = {
+       .chan_priv_tx   = (void *)SHDMA_SLAVE_SDHI_TX,
+       .chan_priv_rx   = (void *)SHDMA_SLAVE_SDHI_RX,
+       .capabilities   = MMC_CAP_SD_HIGHSPEED,
 };
 
 static struct resource sdhi_resources[] = {
index d4b01d4cc102e80b5645dcf4aaa09470868e6485..cbd2a9f02a91ff795696b23656e570d3110102af 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/sh_flctl.h>
+#include <linux/mfd/tmio.h>
 #include <linux/delay.h>
 #include <linux/i2c.h>
 #include <linux/regulator/fixed.h>
@@ -447,8 +448,8 @@ static struct resource sdhi0_cn3_resources[] = {
        },
 };
 
-static struct sh_mobile_sdhi_info sdhi0_cn3_data = {
-       .tmio_caps      = MMC_CAP_SDIO_IRQ,
+static struct tmio_mmc_data sdhi0_cn3_data = {
+       .capabilities   = MMC_CAP_SDIO_IRQ,
 };
 
 static struct platform_device sdhi0_cn3_device = {
@@ -474,8 +475,8 @@ static struct resource sdhi1_cn7_resources[] = {
        },
 };
 
-static struct sh_mobile_sdhi_info sdhi1_cn7_data = {
-       .tmio_caps      = MMC_CAP_SDIO_IRQ,
+static struct tmio_mmc_data sdhi1_cn7_data = {
+       .capabilities   = MMC_CAP_SDIO_IRQ,
 };
 
 static struct platform_device sdhi1_cn7_device = {
index 0d3049244cd3ad048a93a452ffd9583d48163531..d531791f06ffe154bed0b4bbd978709d6b5e8309 100644 (file)
@@ -601,12 +601,12 @@ static struct platform_device sdhi0_power = {
        },
 };
 
-static struct sh_mobile_sdhi_info sdhi0_info = {
-       .dma_slave_tx   = SHDMA_SLAVE_SDHI0_TX,
-       .dma_slave_rx   = SHDMA_SLAVE_SDHI0_RX,
-       .tmio_caps      = MMC_CAP_SDIO_IRQ | MMC_CAP_POWER_OFF_CARD |
+static struct tmio_mmc_data sdhi0_info = {
+       .chan_priv_tx   = (void *)SHDMA_SLAVE_SDHI0_TX,
+       .chan_priv_rx   = (void *)SHDMA_SLAVE_SDHI0_RX,
+       .capabilities   = MMC_CAP_SDIO_IRQ | MMC_CAP_POWER_OFF_CARD |
                          MMC_CAP_NEEDS_POLL,
-       .tmio_flags     = TMIO_MMC_USE_GPIO_CD,
+       .flags          = TMIO_MMC_USE_GPIO_CD,
        .cd_gpio        = GPIO_PTY7,
 };
 
@@ -635,12 +635,12 @@ static struct platform_device sdhi0_device = {
 
 #if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE)
 /* SDHI1 */
-static struct sh_mobile_sdhi_info sdhi1_info = {
-       .dma_slave_tx   = SHDMA_SLAVE_SDHI1_TX,
-       .dma_slave_rx   = SHDMA_SLAVE_SDHI1_RX,
-       .tmio_caps      = MMC_CAP_SDIO_IRQ | MMC_CAP_POWER_OFF_CARD |
+static struct tmio_mmc_data sdhi1_info = {
+       .chan_priv_tx   = (void *)SHDMA_SLAVE_SDHI1_TX,
+       .chan_priv_rx   = (void *)SHDMA_SLAVE_SDHI1_RX,
+       .capabilities   = MMC_CAP_SDIO_IRQ | MMC_CAP_POWER_OFF_CARD |
                          MMC_CAP_NEEDS_POLL,
-       .tmio_flags     = TMIO_MMC_USE_GPIO_CD,
+       .flags          = TMIO_MMC_USE_GPIO_CD,
        .cd_gpio        = GPIO_PTW7,
 };
 
index 1df4398f83757d20503688f166fd57b0831fd4f9..7d997cec09c53ef0a10fc18d6db4e6c5f796331e 100644 (file)
@@ -373,11 +373,11 @@ static struct resource kfr2r09_sh_sdhi0_resources[] = {
        },
 };
 
-static struct sh_mobile_sdhi_info sh7724_sdhi0_data = {
-       .dma_slave_tx   = SHDMA_SLAVE_SDHI0_TX,
-       .dma_slave_rx   = SHDMA_SLAVE_SDHI0_RX,
-       .tmio_flags     = TMIO_MMC_WRPROTECT_DISABLE,
-       .tmio_caps      = MMC_CAP_SDIO_IRQ,
+static struct tmio_mmc_data sh7724_sdhi0_data = {
+       .chan_priv_tx   = (void *)SHDMA_SLAVE_SDHI0_TX,
+       .chan_priv_rx   = (void *)SHDMA_SLAVE_SDHI0_RX,
+       .flags          = TMIO_MMC_WRPROTECT_DISABLE,
+       .capabilities   = MMC_CAP_SDIO_IRQ,
 };
 
 static struct platform_device kfr2r09_sh_sdhi0_device = {
index 8b73194ed2ce2ee8fe6e207d1ac614b6415e02a5..29b7c0dcfc51c6e5c200d1c3c4d377627a3b50cf 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mtd/physmap.h>
+#include <linux/mfd/tmio.h>
 #include <linux/mtd/nand.h>
 #include <linux/i2c.h>
 #include <linux/regulator/fixed.h>
@@ -408,10 +409,10 @@ static struct resource sdhi_cn9_resources[] = {
        },
 };
 
-static struct sh_mobile_sdhi_info sh7724_sdhi_data = {
-       .dma_slave_tx   = SHDMA_SLAVE_SDHI0_TX,
-       .dma_slave_rx   = SHDMA_SLAVE_SDHI0_RX,
-       .tmio_caps      = MMC_CAP_SDIO_IRQ,
+static struct tmio_mmc_data sh7724_sdhi_data = {
+       .chan_priv_tx   = (void *)SHDMA_SLAVE_SDHI0_TX,
+       .chan_priv_rx   = (void *)SHDMA_SLAVE_SDHI0_RX,
+       .capabilities   = MMC_CAP_SDIO_IRQ,
 };
 
 static struct platform_device sdhi_cn9_device = {
index 1162bc6945a38ebd19ac3f13def4cef2459b907a..4f6635a075f20429549251b77fd1cc053dbe1f0c 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/platform_device.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/sh_mobile_sdhi.h>
+#include <linux/mfd/tmio.h>
 #include <linux/mtd/physmap.h>
 #include <linux/delay.h>
 #include <linux/regulator/fixed.h>
@@ -468,10 +469,10 @@ static struct resource sdhi0_cn7_resources[] = {
        },
 };
 
-static struct sh_mobile_sdhi_info sh7724_sdhi0_data = {
-       .dma_slave_tx   = SHDMA_SLAVE_SDHI0_TX,
-       .dma_slave_rx   = SHDMA_SLAVE_SDHI0_RX,
-       .tmio_caps      = MMC_CAP_SDIO_IRQ,
+static struct tmio_mmc_data sh7724_sdhi0_data = {
+       .chan_priv_tx   = (void *)SHDMA_SLAVE_SDHI0_TX,
+       .chan_priv_rx   = (void *)SHDMA_SLAVE_SDHI0_RX,
+       .capabilities   = MMC_CAP_SDIO_IRQ,
 };
 
 static struct platform_device sdhi0_cn7_device = {
@@ -497,10 +498,10 @@ static struct resource sdhi1_cn8_resources[] = {
        },
 };
 
-static struct sh_mobile_sdhi_info sh7724_sdhi1_data = {
-       .dma_slave_tx   = SHDMA_SLAVE_SDHI1_TX,
-       .dma_slave_rx   = SHDMA_SLAVE_SDHI1_RX,
-       .tmio_caps      = MMC_CAP_SDIO_IRQ,
+static struct tmio_mmc_data sh7724_sdhi1_data = {
+       .chan_priv_tx   = (void *)SHDMA_SLAVE_SDHI1_TX,
+       .chan_priv_rx   = (void *)SHDMA_SLAVE_SDHI1_RX,
+       .capabilities   = MMC_CAP_SDIO_IRQ,
 };
 
 static struct platform_device sdhi1_cn8_device = {
index d2ae0f70059ead513bde0ff52ffa02de6615d9d8..7d3ca30fcd1506d81dfca9859ffb4cc290fae109 100644 (file)
@@ -2290,7 +2290,7 @@ void *ldc_alloc_exp_dring(struct ldc_channel *lp, unsigned int len,
        if (len & (8UL - 1))
                return ERR_PTR(-EINVAL);
 
-       buf = kzalloc(len, GFP_KERNEL);
+       buf = kzalloc(len, GFP_ATOMIC);
        if (!buf)
                return ERR_PTR(-ENOMEM);
 
index 86eebfa3b15873dfd60117389e9c80f0018a13e0..59cf917a77b5055e47d2b17c11c9788db434d4c5 100644 (file)
@@ -737,25 +737,9 @@ static void sparc_vt_write_pmc(int idx, u64 val)
 {
        u64 pcr;
 
-       /* There seems to be an internal latch on the overflow event
-        * on SPARC-T4 that prevents it from triggering unless you
-        * update the PIC exactly as we do here.  The requirement
-        * seems to be that you have to turn off event counting in the
-        * PCR around the PIC update.
-        *
-        * For example, after the following sequence:
-        *
-        * 1) set PIC to -1
-        * 2) enable event counting and overflow reporting in PCR
-        * 3) overflow triggers, softint 15 handler invoked
-        * 4) clear OV bit in PCR
-        * 5) write PIC to -1
-        *
-        * a subsequent overflow event will not trigger.  This
-        * sequence works on SPARC-T3 and previous chips.
-        */
        pcr = pcr_ops->read_pcr(idx);
-       pcr_ops->write_pcr(idx, PCR_N4_PICNPT);
+       /* ensure ov and ntc are reset */
+       pcr &= ~(PCR_N4_OV | PCR_N4_NTC);
 
        pcr_ops->write_pic(idx, val & 0xffffffff);
 
@@ -792,25 +776,12 @@ static const struct sparc_pmu niagara4_pmu = {
        .num_pic_regs   = 4,
 };
 
-static void sparc_m7_write_pmc(int idx, u64 val)
-{
-       u64 pcr;
-
-       pcr = pcr_ops->read_pcr(idx);
-       /* ensure ov and ntc are reset */
-       pcr &= ~(PCR_N4_OV | PCR_N4_NTC);
-
-       pcr_ops->write_pic(idx, val & 0xffffffff);
-
-       pcr_ops->write_pcr(idx, pcr);
-}
-
 static const struct sparc_pmu sparc_m7_pmu = {
        .event_map      = niagara4_event_map,
        .cache_map      = &niagara4_cache_map,
        .max_events     = ARRAY_SIZE(niagara4_perfmon_event_map),
        .read_pmc       = sparc_vt_read_pmc,
-       .write_pmc      = sparc_m7_write_pmc,
+       .write_pmc      = sparc_vt_write_pmc,
        .upper_shift    = 5,
        .lower_shift    = 5,
        .event_mask     = 0x7ff,
index 6873f006f7d04fb1e71f8e9be386854431acb513..d366675e4bf88ef10e18f53637abd314b69b3725 100644 (file)
@@ -774,7 +774,7 @@ static void __init zone_sizes_init(void)
                 * though, there'll be no lowmem, so we just alloc_bootmem
                 * the memmap.  There will be no percpu memory either.
                 */
-               if (i != 0 && cpumask_test_cpu(i, &isolnodes)) {
+               if (i != 0 && node_isset(i, isolnodes)) {
                        node_memmap_pfn[i] =
                                alloc_bootmem_pfn(0, memmap_size, 0);
                        BUG_ON(node_percpu[i] != 0);
index 3c17c04ce5a7ee696c31eddcb8bd739c343ae1b2..6bbb991d0f3c17396d1a89ec11ba9af5ce708fa2 100644 (file)
@@ -22,6 +22,7 @@ config X86_64
 ### Arch settings
 config X86
        def_bool y
+       select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI
        select ARCH_MIGHT_HAVE_ACPI_PDC if ACPI
        select ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS
        select ARCH_HAS_FAST_MULTIPLIER
index 20028da8ae188ce16aaabdc1ef6da2fd1eb5b8f0..72484a645f056d1d7a8aa4182b07fc908c3b4162 100644 (file)
@@ -43,10 +43,6 @@ config EARLY_PRINTK
          with klogd/syslogd or the X server. You should normally N here,
          unless you want to debug such a crash.
 
-config EARLY_PRINTK_INTEL_MID
-       bool "Early printk for Intel MID platform support"
-       depends on EARLY_PRINTK && X86_INTEL_MID
-
 config EARLY_PRINTK_DBGP
        bool "Early printk via EHCI debug port"
        depends on EARLY_PRINTK && PCI
index 2fda005bb33443c1684546dff0620f8db48e7c5c..c7c31876bb40e8774676a382c5e1f53fbe8fc6df 100644 (file)
@@ -84,6 +84,9 @@ else
        # Use -mpreferred-stack-boundary=3 if supported.
        KBUILD_CFLAGS += $(call cc-option,-mpreferred-stack-boundary=3)
 
+       # Use -mskip-rax-setup if supported.
+       KBUILD_CFLAGS += $(call cc-option,-mskip-rax-setup)
+
         # FIXME - should be integrated in Makefile.cpu (Makefile_32.cpu)
         cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8)
         cflags-$(CONFIG_MPSC) += $(call cc-option,-march=nocona)
index ef17683484e9b308e2cb89312258dfe1e62e2d72..48304b89b601fa92bbd8ee1f5e548b4c2ffcc2dc 100644 (file)
@@ -1109,6 +1109,8 @@ struct boot_params *make_boot_params(struct efi_config *c)
        if (!cmdline_ptr)
                goto fail;
        hdr->cmd_line_ptr = (unsigned long)cmdline_ptr;
+       /* Fill in upper bits of command line address, NOP on 32 bit  */
+       boot_params->ext_cmd_line_ptr = (u64)(unsigned long)cmdline_ptr >> 32;
 
        hdr->ramdisk_image = 0;
        hdr->ramdisk_size = 0;
index a4771dcd1fcf4ff6c2a778ed481174b4cfefe694..1f20b35d8573a131241505d58f292d67bc866c6d 100644 (file)
@@ -79,7 +79,7 @@ NUM_BLKS    = %rdx
 c           = %rcx
 d           = %r8
 e           = %rdx
-y3          = %rdi
+y3          = %rsi
 
 TBL   = %rbp
 
index a821b1cd4fa7a2748cce60ba986ef63d27efb131..63450a5968001ab8c3ee087cd41c78b732b9b443 100644 (file)
@@ -77,12 +77,6 @@ ENTRY(native_usergs_sysret32)
        swapgs
        sysretl
 ENDPROC(native_usergs_sysret32)
-
-ENTRY(native_irq_enable_sysexit)
-       swapgs
-       sti
-       sysexit
-ENDPROC(native_irq_enable_sysexit)
 #endif
 
 /*
@@ -119,7 +113,7 @@ ENTRY(ia32_sysenter_target)
         * it is too small to ever cause noticeable irq latency.
         */
        SWAPGS_UNSAFE_STACK
-       movq    PER_CPU_VAR(cpu_tss + TSS_sp0), %rsp
+       movq    PER_CPU_VAR(cpu_current_top_of_stack), %rsp
        ENABLE_INTERRUPTS(CLBR_NONE)
 
        /* Zero-extending 32-bit regs, do not remove */
@@ -142,7 +136,7 @@ ENTRY(ia32_sysenter_target)
        pushq_cfi_reg   rsi                     /* pt_regs->si */
        pushq_cfi_reg   rdx                     /* pt_regs->dx */
        pushq_cfi_reg   rcx                     /* pt_regs->cx */
-       pushq_cfi_reg   rax                     /* pt_regs->ax */
+       pushq_cfi       $-ENOSYS                /* pt_regs->ax */
        cld
        sub     $(10*8),%rsp /* pt_regs->r8-11,bp,bx,r12-15 not saved */
        CFI_ADJUST_CFA_OFFSET 10*8
@@ -169,8 +163,6 @@ sysenter_flags_fixed:
        testl   $_TIF_WORK_SYSCALL_ENTRY, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
        CFI_REMEMBER_STATE
        jnz  sysenter_tracesys
-       cmpq    $(IA32_NR_syscalls-1),%rax
-       ja      ia32_badsys
 sysenter_do_call:
        /* 32bit syscall -> 64bit C ABI argument conversion */
        movl    %edi,%r8d       /* arg5 */
@@ -179,8 +171,11 @@ sysenter_do_call:
        movl    %ebx,%edi       /* arg1 */
        movl    %edx,%edx       /* arg3 (zero extension) */
 sysenter_dispatch:
+       cmpq    $(IA32_NR_syscalls-1),%rax
+       ja      1f
        call    *ia32_sys_call_table(,%rax,8)
        movq    %rax,RAX(%rsp)
+1:
        DISABLE_INTERRUPTS(CLBR_NONE)
        TRACE_IRQS_OFF
        testl   $_TIF_ALLWORK_MASK, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
@@ -247,9 +242,7 @@ sysexit_from_sys_call:
        movl %ebx,%esi                  /* 2nd arg: 1st syscall arg */
        movl %eax,%edi                  /* 1st arg: syscall number */
        call __audit_syscall_entry
-       movl RAX(%rsp),%eax     /* reload syscall number */
-       cmpq $(IA32_NR_syscalls-1),%rax
-       ja ia32_badsys
+       movl ORIG_RAX(%rsp),%eax        /* reload syscall number */
        movl %ebx,%edi                  /* reload 1st syscall arg */
        movl RCX(%rsp),%esi     /* reload 2nd syscall arg */
        movl RDX(%rsp),%edx     /* reload 3rd syscall arg */
@@ -300,13 +293,10 @@ sysenter_tracesys:
 #endif
        SAVE_EXTRA_REGS
        CLEAR_RREGS
-       movq    $-ENOSYS,RAX(%rsp)/* ptrace can change this for a bad syscall */
        movq    %rsp,%rdi        /* &pt_regs -> arg1 */
        call    syscall_trace_enter
        LOAD_ARGS32  /* reload args from stack in case ptrace changed it */
        RESTORE_EXTRA_REGS
-       cmpq    $(IA32_NR_syscalls-1),%rax
-       ja      int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */
        jmp     sysenter_do_call
        CFI_ENDPROC
 ENDPROC(ia32_sysenter_target)
@@ -356,7 +346,7 @@ ENTRY(ia32_cstar_target)
        SWAPGS_UNSAFE_STACK
        movl    %esp,%r8d
        CFI_REGISTER    rsp,r8
-       movq    PER_CPU_VAR(kernel_stack),%rsp
+       movq    PER_CPU_VAR(cpu_current_top_of_stack),%rsp
        ENABLE_INTERRUPTS(CLBR_NONE)
 
        /* Zero-extending 32-bit regs, do not remove */
@@ -376,7 +366,7 @@ ENTRY(ia32_cstar_target)
        pushq_cfi_reg   rdx                     /* pt_regs->dx */
        pushq_cfi_reg   rbp                     /* pt_regs->cx */
        movl    %ebp,%ecx
-       pushq_cfi_reg   rax                     /* pt_regs->ax */
+       pushq_cfi       $-ENOSYS                /* pt_regs->ax */
        sub     $(10*8),%rsp /* pt_regs->r8-11,bp,bx,r12-15 not saved */
        CFI_ADJUST_CFA_OFFSET 10*8
 
@@ -392,8 +382,6 @@ ENTRY(ia32_cstar_target)
        testl   $_TIF_WORK_SYSCALL_ENTRY, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
        CFI_REMEMBER_STATE
        jnz   cstar_tracesys
-       cmpq $IA32_NR_syscalls-1,%rax
-       ja  ia32_badsys
 cstar_do_call:
        /* 32bit syscall -> 64bit C ABI argument conversion */
        movl    %edi,%r8d       /* arg5 */
@@ -402,8 +390,11 @@ cstar_do_call:
        movl    %ebx,%edi       /* arg1 */
        movl    %edx,%edx       /* arg3 (zero extension) */
 cstar_dispatch:
+       cmpq    $(IA32_NR_syscalls-1),%rax
+       ja      1f
        call *ia32_sys_call_table(,%rax,8)
        movq %rax,RAX(%rsp)
+1:
        DISABLE_INTERRUPTS(CLBR_NONE)
        TRACE_IRQS_OFF
        testl $_TIF_ALLWORK_MASK, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
@@ -427,6 +418,13 @@ sysretl_from_sys_call:
         * cs and ss are loaded from MSRs.
         * (Note: 32bit->32bit SYSRET is different: since r11
         * does not exist, it merely sets eflags.IF=1).
+        *
+        * NB: On AMD CPUs with the X86_BUG_SYSRET_SS_ATTRS bug, the ss
+        * descriptor is not reinitialized.  This means that we must
+        * avoid SYSRET with SS == NULL, which could happen if we schedule,
+        * exit the kernel, and re-enter using an interrupt vector.  (All
+        * interrupt entries on x86_64 set SS to NULL.)  We prevent that
+        * from happening by reloading SS in __switch_to.
         */
        USERGS_SYSRET32
 
@@ -450,14 +448,11 @@ cstar_tracesys:
        xchgl %r9d,%ebp
        SAVE_EXTRA_REGS
        CLEAR_RREGS r9
-       movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
        movq %rsp,%rdi        /* &pt_regs -> arg1 */
        call syscall_trace_enter
        LOAD_ARGS32 1   /* reload args from stack in case ptrace changed it */
        RESTORE_EXTRA_REGS
        xchgl %ebp,%r9d
-       cmpq $(IA32_NR_syscalls-1),%rax
-       ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */
        jmp cstar_do_call
 END(ia32_cstar_target)
                                
@@ -516,7 +511,7 @@ ENTRY(ia32_syscall)
        pushq_cfi_reg   rsi                     /* pt_regs->si */
        pushq_cfi_reg   rdx                     /* pt_regs->dx */
        pushq_cfi_reg   rcx                     /* pt_regs->cx */
-       pushq_cfi_reg   rax                     /* pt_regs->ax */
+       pushq_cfi       $-ENOSYS                /* pt_regs->ax */
        cld
        sub     $(10*8),%rsp /* pt_regs->r8-11,bp,bx,r12-15 not saved */
        CFI_ADJUST_CFA_OFFSET 10*8
@@ -524,8 +519,6 @@ ENTRY(ia32_syscall)
        orl $TS_COMPAT, ASM_THREAD_INFO(TI_status, %rsp, SIZEOF_PTREGS)
        testl $_TIF_WORK_SYSCALL_ENTRY, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
        jnz ia32_tracesys
-       cmpq $(IA32_NR_syscalls-1),%rax
-       ja ia32_badsys
 ia32_do_call:
        /* 32bit syscall -> 64bit C ABI argument conversion */
        movl %edi,%r8d  /* arg5 */
@@ -533,9 +526,12 @@ ia32_do_call:
        xchg %ecx,%esi  /* rsi:arg2, rcx:arg4 */
        movl %ebx,%edi  /* arg1 */
        movl %edx,%edx  /* arg3 (zero extension) */
+       cmpq    $(IA32_NR_syscalls-1),%rax
+       ja      1f
        call *ia32_sys_call_table(,%rax,8) # xxx: rip relative
 ia32_sysret:
        movq %rax,RAX(%rsp)
+1:
 ia32_ret_from_sys_call:
        CLEAR_RREGS
        jmp int_ret_from_sys_call
@@ -543,23 +539,14 @@ ia32_ret_from_sys_call:
 ia32_tracesys:
        SAVE_EXTRA_REGS
        CLEAR_RREGS
-       movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
        movq %rsp,%rdi        /* &pt_regs -> arg1 */
        call syscall_trace_enter
        LOAD_ARGS32     /* reload args from stack in case ptrace changed it */
        RESTORE_EXTRA_REGS
-       cmpq $(IA32_NR_syscalls-1),%rax
-       ja  int_ret_from_sys_call       /* ia32_tracesys has set RAX(%rsp) */
        jmp ia32_do_call
+       CFI_ENDPROC
 END(ia32_syscall)
 
-ia32_badsys:
-       movq $0,ORIG_RAX(%rsp)
-       movq $-ENOSYS,%rax
-       jmp ia32_sysret
-
-       CFI_ENDPROC
-       
        .macro PTREGSCALL label, func
        ALIGN
 GLOBAL(\label)
index bdf02eeee76519582b0fe9c35b631852b1b417d9..e7636bac7372d41d4b8077f4d7df7d81de32ee32 100644 (file)
        .endm
 #endif
 
+/*
+ * Issue one struct alt_instr descriptor entry (need to put it into
+ * the section .altinstructions, see below). This entry contains
+ * enough information for the alternatives patching code to patch an
+ * instruction. See apply_alternatives().
+ */
 .macro altinstruction_entry orig alt feature orig_len alt_len pad_len
        .long \orig - .
        .long \alt - .
        .byte \pad_len
 .endm
 
+/*
+ * Define an alternative between two instructions. If @feature is
+ * present, early code in apply_alternatives() replaces @oldinstr with
+ * @newinstr. ".skip" directive takes care of proper instruction padding
+ * in case @newinstr is longer than @oldinstr.
+ */
 .macro ALTERNATIVE oldinstr, newinstr, feature
 140:
        \oldinstr
  */
 #define alt_max_short(a, b)    ((a) ^ (((a) ^ (b)) & -(-((a) < (b)))))
 
+
+/*
+ * Same as ALTERNATIVE macro above but for two alternatives. If CPU
+ * has @feature1, it replaces @oldinstr with @newinstr1. If CPU has
+ * @feature2, it replaces @oldinstr with @feature2.
+ */
 .macro ALTERNATIVE_2 oldinstr, newinstr1, feature1, newinstr2, feature2
 140:
        \oldinstr
index 5e5cd123fdfbc2b0fe90cabc5d27948d3ded267a..e9168955c42f4ee8b18e726e28ecacf39b75a7f2 100644 (file)
@@ -22,7 +22,7 @@
  *
  * Atomically reads the value of @v.
  */
-static inline int atomic_read(const atomic_t *v)
+static __always_inline int atomic_read(const atomic_t *v)
 {
        return ACCESS_ONCE((v)->counter);
 }
@@ -34,7 +34,7 @@ static inline int atomic_read(const atomic_t *v)
  *
  * Atomically sets the value of @v to @i.
  */
-static inline void atomic_set(atomic_t *v, int i)
+static __always_inline void atomic_set(atomic_t *v, int i)
 {
        v->counter = i;
 }
@@ -46,7 +46,7 @@ static inline void atomic_set(atomic_t *v, int i)
  *
  * Atomically adds @i to @v.
  */
-static inline void atomic_add(int i, atomic_t *v)
+static __always_inline void atomic_add(int i, atomic_t *v)
 {
        asm volatile(LOCK_PREFIX "addl %1,%0"
                     : "+m" (v->counter)
@@ -60,7 +60,7 @@ static inline void atomic_add(int i, atomic_t *v)
  *
  * Atomically subtracts @i from @v.
  */
-static inline void atomic_sub(int i, atomic_t *v)
+static __always_inline void atomic_sub(int i, atomic_t *v)
 {
        asm volatile(LOCK_PREFIX "subl %1,%0"
                     : "+m" (v->counter)
@@ -76,7 +76,7 @@ static inline void atomic_sub(int i, atomic_t *v)
  * true if the result is zero, or false for all
  * other cases.
  */
-static inline int atomic_sub_and_test(int i, atomic_t *v)
+static __always_inline int atomic_sub_and_test(int i, atomic_t *v)
 {
        GEN_BINARY_RMWcc(LOCK_PREFIX "subl", v->counter, "er", i, "%0", "e");
 }
@@ -87,7 +87,7 @@ static inline int atomic_sub_and_test(int i, atomic_t *v)
  *
  * Atomically increments @v by 1.
  */
-static inline void atomic_inc(atomic_t *v)
+static __always_inline void atomic_inc(atomic_t *v)
 {
        asm volatile(LOCK_PREFIX "incl %0"
                     : "+m" (v->counter));
@@ -99,7 +99,7 @@ static inline void atomic_inc(atomic_t *v)
  *
  * Atomically decrements @v by 1.
  */
-static inline void atomic_dec(atomic_t *v)
+static __always_inline void atomic_dec(atomic_t *v)
 {
        asm volatile(LOCK_PREFIX "decl %0"
                     : "+m" (v->counter));
@@ -113,7 +113,7 @@ static inline void atomic_dec(atomic_t *v)
  * returns true if the result is 0, or false for all other
  * cases.
  */
-static inline int atomic_dec_and_test(atomic_t *v)
+static __always_inline int atomic_dec_and_test(atomic_t *v)
 {
        GEN_UNARY_RMWcc(LOCK_PREFIX "decl", v->counter, "%0", "e");
 }
@@ -126,7 +126,7 @@ static inline int atomic_dec_and_test(atomic_t *v)
  * and returns true if the result is zero, or false for all
  * other cases.
  */
-static inline int atomic_inc_and_test(atomic_t *v)
+static __always_inline int atomic_inc_and_test(atomic_t *v)
 {
        GEN_UNARY_RMWcc(LOCK_PREFIX "incl", v->counter, "%0", "e");
 }
@@ -140,7 +140,7 @@ static inline int atomic_inc_and_test(atomic_t *v)
  * if the result is negative, or false when
  * result is greater than or equal to zero.
  */
-static inline int atomic_add_negative(int i, atomic_t *v)
+static __always_inline int atomic_add_negative(int i, atomic_t *v)
 {
        GEN_BINARY_RMWcc(LOCK_PREFIX "addl", v->counter, "er", i, "%0", "s");
 }
@@ -152,7 +152,7 @@ static inline int atomic_add_negative(int i, atomic_t *v)
  *
  * Atomically adds @i to @v and returns @i + @v
  */
-static inline int atomic_add_return(int i, atomic_t *v)
+static __always_inline int atomic_add_return(int i, atomic_t *v)
 {
        return i + xadd(&v->counter, i);
 }
@@ -164,7 +164,7 @@ static inline int atomic_add_return(int i, atomic_t *v)
  *
  * Atomically subtracts @i from @v and returns @v - @i
  */
-static inline int atomic_sub_return(int i, atomic_t *v)
+static __always_inline int atomic_sub_return(int i, atomic_t *v)
 {
        return atomic_add_return(-i, v);
 }
@@ -172,7 +172,7 @@ static inline int atomic_sub_return(int i, atomic_t *v)
 #define atomic_inc_return(v)  (atomic_add_return(1, v))
 #define atomic_dec_return(v)  (atomic_sub_return(1, v))
 
-static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
+static __always_inline int atomic_cmpxchg(atomic_t *v, int old, int new)
 {
        return cmpxchg(&v->counter, old, new);
 }
@@ -191,7 +191,7 @@ static inline int atomic_xchg(atomic_t *v, int new)
  * Atomically adds @a to @v, so long as @v was not already @u.
  * Returns the old value of @v.
  */
-static inline int __atomic_add_unless(atomic_t *v, int a, int u)
+static __always_inline int __atomic_add_unless(atomic_t *v, int a, int u)
 {
        int c, old;
        c = atomic_read(v);
@@ -213,7 +213,7 @@ static inline int __atomic_add_unless(atomic_t *v, int a, int u)
  * Atomically adds 1 to @v
  * Returns the new value of @u
  */
-static inline short int atomic_inc_short(short int *v)
+static __always_inline short int atomic_inc_short(short int *v)
 {
        asm(LOCK_PREFIX "addw $1, %0" : "+m" (*v));
        return *v;
index f8d273e18516dedf885bbafb16224c189913e14f..b965f9e03f2a04b2291fc0b62d537b6d9416bdaf 100644 (file)
@@ -40,7 +40,7 @@ static inline void atomic64_set(atomic64_t *v, long i)
  *
  * Atomically adds @i to @v.
  */
-static inline void atomic64_add(long i, atomic64_t *v)
+static __always_inline void atomic64_add(long i, atomic64_t *v)
 {
        asm volatile(LOCK_PREFIX "addq %1,%0"
                     : "=m" (v->counter)
@@ -81,7 +81,7 @@ static inline int atomic64_sub_and_test(long i, atomic64_t *v)
  *
  * Atomically increments @v by 1.
  */
-static inline void atomic64_inc(atomic64_t *v)
+static __always_inline void atomic64_inc(atomic64_t *v)
 {
        asm volatile(LOCK_PREFIX "incq %0"
                     : "=m" (v->counter)
@@ -94,7 +94,7 @@ static inline void atomic64_inc(atomic64_t *v)
  *
  * Atomically decrements @v by 1.
  */
-static inline void atomic64_dec(atomic64_t *v)
+static __always_inline void atomic64_dec(atomic64_t *v)
 {
        asm volatile(LOCK_PREFIX "decq %0"
                     : "=m" (v->counter)
@@ -148,7 +148,7 @@ static inline int atomic64_add_negative(long i, atomic64_t *v)
  *
  * Atomically adds @i to @v and returns @i + @v
  */
-static inline long atomic64_add_return(long i, atomic64_t *v)
+static __always_inline long atomic64_add_return(long i, atomic64_t *v)
 {
        return i + xadd(&v->counter, i);
 }
index 7ee9b94d9921bf0a1ea7e010c76985cb6a8595ce..3d6606fb97d05496d21ea93c0030a5f7aa109516 100644 (file)
 #define X86_BUG_11AP           X86_BUG(5) /* Bad local APIC aka 11AP */
 #define X86_BUG_FXSAVE_LEAK    X86_BUG(6) /* FXSAVE leaks FOP/FIP/FOP */
 #define X86_BUG_CLFLUSH_MONITOR        X86_BUG(7) /* AAI65, CLFLUSH required before MONITOR */
+#define X86_BUG_SYSRET_SS_ATTRS        X86_BUG(8) /* SYSRET doesn't fix up SS attrs */
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 
index 1f88e719fa78c7565a0d8041d2a040f300859575..9472c9aff26de0a98ebcabdbac801b8ebcd0d8ac 100644 (file)
@@ -36,40 +36,6 @@ extern asmlinkage void spurious_interrupt(void);
 extern asmlinkage void thermal_interrupt(void);
 extern asmlinkage void reschedule_interrupt(void);
 
-extern asmlinkage void invalidate_interrupt(void);
-extern asmlinkage void invalidate_interrupt0(void);
-extern asmlinkage void invalidate_interrupt1(void);
-extern asmlinkage void invalidate_interrupt2(void);
-extern asmlinkage void invalidate_interrupt3(void);
-extern asmlinkage void invalidate_interrupt4(void);
-extern asmlinkage void invalidate_interrupt5(void);
-extern asmlinkage void invalidate_interrupt6(void);
-extern asmlinkage void invalidate_interrupt7(void);
-extern asmlinkage void invalidate_interrupt8(void);
-extern asmlinkage void invalidate_interrupt9(void);
-extern asmlinkage void invalidate_interrupt10(void);
-extern asmlinkage void invalidate_interrupt11(void);
-extern asmlinkage void invalidate_interrupt12(void);
-extern asmlinkage void invalidate_interrupt13(void);
-extern asmlinkage void invalidate_interrupt14(void);
-extern asmlinkage void invalidate_interrupt15(void);
-extern asmlinkage void invalidate_interrupt16(void);
-extern asmlinkage void invalidate_interrupt17(void);
-extern asmlinkage void invalidate_interrupt18(void);
-extern asmlinkage void invalidate_interrupt19(void);
-extern asmlinkage void invalidate_interrupt20(void);
-extern asmlinkage void invalidate_interrupt21(void);
-extern asmlinkage void invalidate_interrupt22(void);
-extern asmlinkage void invalidate_interrupt23(void);
-extern asmlinkage void invalidate_interrupt24(void);
-extern asmlinkage void invalidate_interrupt25(void);
-extern asmlinkage void invalidate_interrupt26(void);
-extern asmlinkage void invalidate_interrupt27(void);
-extern asmlinkage void invalidate_interrupt28(void);
-extern asmlinkage void invalidate_interrupt29(void);
-extern asmlinkage void invalidate_interrupt30(void);
-extern asmlinkage void invalidate_interrupt31(void);
-
 extern asmlinkage void irq_move_cleanup_interrupt(void);
 extern asmlinkage void reboot_interrupt(void);
 extern asmlinkage void threshold_interrupt(void);
@@ -206,7 +172,6 @@ extern asmlinkage void smp_irq_move_cleanup_interrupt(void);
 extern __visible void smp_reschedule_interrupt(struct pt_regs *);
 extern __visible void smp_call_function_interrupt(struct pt_regs *);
 extern __visible void smp_call_function_single_interrupt(struct pt_regs *);
-extern __visible void smp_invalidate_interrupt(struct pt_regs *);
 #endif
 
 extern char irq_entries_start[];
index e42f758a0fbd9b14b38feaae9fbb3f1a2bfcd204..055ea9941dd5f671d116306a6544adf7a4f189bc 100644 (file)
@@ -50,7 +50,7 @@ extern const struct hypervisor_x86 *x86_hyper;
 /* Recognized hypervisors */
 extern const struct hypervisor_x86 x86_hyper_vmware;
 extern const struct hypervisor_x86 x86_hyper_ms_hyperv;
-extern const struct hypervisor_x86 x86_hyper_xen_hvm;
+extern const struct hypervisor_x86 x86_hyper_xen;
 extern const struct hypervisor_x86 x86_hyper_kvm;
 
 extern void init_hypervisor(struct cpuinfo_x86 *c);
index 705d35708a508cd520d579d888719bc296e563b9..7c5af123bdbd21680744000f1a6195644a5140b3 100644 (file)
@@ -136,9 +136,6 @@ extern enum intel_mid_timer_options intel_mid_timer_options;
 #define SFI_MTMR_MAX_NUM 8
 #define SFI_MRTC_MAX   8
 
-extern struct console early_hsu_console;
-extern void hsu_early_console_init(const char *);
-
 extern void intel_scu_devices_create(void);
 extern void intel_scu_devices_destroy(void);
 
index b26cb124a4f1cf7bc55fe350c25a8debcee82a44..bf55235d7772522045323e33350f42ed2861ec7a 100644 (file)
 #define IRQ_MOVE_CLEANUP_VECTOR                FIRST_EXTERNAL_VECTOR
 
 #define IA32_SYSCALL_VECTOR            0x80
-#ifdef CONFIG_X86_32
-# define SYSCALL_VECTOR                        0x80
-#endif
 
 /*
  * Vectors 0x30-0x3f are used for ISA interrupts.
  *   round up to the next 16-vector boundary
  */
-#define IRQ0_VECTOR                    ((FIRST_EXTERNAL_VECTOR + 16) & ~15)
-
-#define IRQ1_VECTOR                    (IRQ0_VECTOR +  1)
-#define IRQ2_VECTOR                    (IRQ0_VECTOR +  2)
-#define IRQ3_VECTOR                    (IRQ0_VECTOR +  3)
-#define IRQ4_VECTOR                    (IRQ0_VECTOR +  4)
-#define IRQ5_VECTOR                    (IRQ0_VECTOR +  5)
-#define IRQ6_VECTOR                    (IRQ0_VECTOR +  6)
-#define IRQ7_VECTOR                    (IRQ0_VECTOR +  7)
-#define IRQ8_VECTOR                    (IRQ0_VECTOR +  8)
-#define IRQ9_VECTOR                    (IRQ0_VECTOR +  9)
-#define IRQ10_VECTOR                   (IRQ0_VECTOR + 10)
-#define IRQ11_VECTOR                   (IRQ0_VECTOR + 11)
-#define IRQ12_VECTOR                   (IRQ0_VECTOR + 12)
-#define IRQ13_VECTOR                   (IRQ0_VECTOR + 13)
-#define IRQ14_VECTOR                   (IRQ0_VECTOR + 14)
-#define IRQ15_VECTOR                   (IRQ0_VECTOR + 15)
+#define ISA_IRQ_VECTOR(irq)            (((FIRST_EXTERNAL_VECTOR + 16) & ~15) + irq)
 
 /*
  * Special IRQ vectors used by the SMP architecture, 0xf0-0xff
index e2d4a4afa8c3070374f3617fa405f5733b5624b1..3bbc07a57a31e9d68f232fd56651be6788491f95 100644 (file)
@@ -20,13 +20,10 @@ extern unsigned long switcher_addr;
 /* Found in switcher.S */
 extern unsigned long default_idt_entries[];
 
-/* Declarations for definitions in lguest_guest.S */
-extern char lguest_noirq_start[], lguest_noirq_end[];
+/* Declarations for definitions in arch/x86/lguest/head_32.S */
+extern char lguest_noirq_iret[];
 extern const char lgstart_cli[], lgend_cli[];
-extern const char lgstart_sti[], lgend_sti[];
-extern const char lgstart_popf[], lgend_popf[];
 extern const char lgstart_pushf[], lgend_pushf[];
-extern const char lgstart_iret[], lgend_iret[];
 
 extern void lguest_iret(void);
 extern void lguest_init(void);
index f7b0b5c112f28cc89c524231e9022b4560158b48..344c646e7f068979ca9e20d1d5333bd3cafb72ce 100644 (file)
@@ -160,13 +160,14 @@ struct pv_cpu_ops {
        u64 (*read_pmc)(int counter);
        unsigned long long (*read_tscp)(unsigned int *aux);
 
+#ifdef CONFIG_X86_32
        /*
         * Atomically enable interrupts and return to userspace.  This
-        * is only ever used to return to 32-bit processes; in a
-        * 64-bit kernel, it's used for 32-on-64 compat processes, but
-        * never native 64-bit processes.  (Jump, not call.)
+        * is only used in 32-bit kernels.  64-bit kernels use
+        * usergs_sysret32 instead.
         */
        void (*irq_enable_sysexit)(void);
+#endif
 
        /*
         * Switch to usermode gs and return to 64-bit usermode using
index 25b1cc07d49668c8a40306bf2ec81e4e2a11988e..d6b078e9fa28a3f4588237cb9a122f5b5ce53162 100644 (file)
@@ -95,7 +95,6 @@ unsigned __pvclock_read_cycles(const struct pvclock_vcpu_time_info *src,
 
 struct pvclock_vsyscall_time_info {
        struct pvclock_vcpu_time_info pvti;
-       u32 migrate_count;
 } __attribute__((__aligned__(SMP_CACHE_BYTES)));
 
 #define PVTI_SIZE sizeof(struct pvclock_vsyscall_time_info)
index 460b84f64556dded375c779a59d2c6a521c575c7..8378b8c9109c851c3c7d1b6669e6bf0e9be689bf 100644 (file)
 
 /* Standard COM flags (except for COM4, because of the 8514 problem) */
 #ifdef CONFIG_SERIAL_DETECT_IRQ
-# define STD_COMX_FLAGS        (ASYNC_BOOT_AUTOCONF |  ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
-# define STD_COM4_FLAGS        (ASYNC_BOOT_AUTOCONF |  0               | ASYNC_AUTO_IRQ)
+# define STD_COMX_FLAGS        (UPF_BOOT_AUTOCONF |    UPF_SKIP_TEST   | UPF_AUTO_IRQ)
+# define STD_COM4_FLAGS        (UPF_BOOT_AUTOCONF |    0               | UPF_AUTO_IRQ)
 #else
-# define STD_COMX_FLAGS        (ASYNC_BOOT_AUTOCONF |  ASYNC_SKIP_TEST | 0             )
-# define STD_COM4_FLAGS        (ASYNC_BOOT_AUTOCONF |  0               | 0             )
+# define STD_COMX_FLAGS        (UPF_BOOT_AUTOCONF |    UPF_SKIP_TEST   | 0             )
+# define STD_COM4_FLAGS        (UPF_BOOT_AUTOCONF |    0               | 0             )
 #endif
 
 #define SERIAL_PORT_DFNS                                                               \
index cf87de3fc39000eb21028ab2597d5187978bda4a..64b611782ef0856f1744611936f76d6e8de1bb57 100644 (file)
@@ -169,7 +169,7 @@ static inline int arch_spin_is_contended(arch_spinlock_t *lock)
        struct __raw_tickets tmp = READ_ONCE(lock->tickets);
 
        tmp.head &= ~TICKET_SLOWPATH_FLAG;
-       return (tmp.tail - tmp.head) > TICKET_LOCK_INC;
+       return (__ticket_t)(tmp.tail - tmp.head) > TICKET_LOCK_INC;
 }
 #define arch_spin_is_contended arch_spin_is_contended
 
index b4bdec3e9523e03b7ece3154302c8d95ce2a9ac8..225ee545e1a05e36bfa25eb6a214102b8be8c0bf 100644 (file)
@@ -177,8 +177,6 @@ struct thread_info {
  */
 #ifndef __ASSEMBLY__
 
-DECLARE_PER_CPU(unsigned long, kernel_stack);
-
 static inline struct thread_info *current_thread_info(void)
 {
        return (struct thread_info *)(current_top_of_stack() - THREAD_SIZE);
@@ -197,9 +195,13 @@ static inline unsigned long current_stack_pointer(void)
 
 #else /* !__ASSEMBLY__ */
 
+#ifdef CONFIG_X86_64
+# define cpu_current_top_of_stack (cpu_tss + TSS_sp0)
+#endif
+
 /* Load thread_info address into "reg" */
 #define GET_THREAD_INFO(reg) \
-       _ASM_MOV PER_CPU_VAR(kernel_stack),reg ; \
+       _ASM_MOV PER_CPU_VAR(cpu_current_top_of_stack),reg ; \
        _ASM_SUB $(THREAD_SIZE),reg ;
 
 /*
index 3c03a5de64d30c01c1408953bf75c4970f54bcb1..0ed5504c606081642912ae8ca31d3dc438f45200 100644 (file)
@@ -59,6 +59,10 @@ __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
                        __put_user_size(*(u32 *)from, (u32 __user *)to,
                                        4, ret, 4);
                        return ret;
+               case 8:
+                       __put_user_size(*(u64 *)from, (u64 __user *)to,
+                                       8, ret, 8);
+                       return ret;
                }
        }
        return __copy_to_user_ll(to, from, n);
index 358dcd33891582a2da1d07d0b75a11333091a1a9..c44a5d53e464733509de6d3d6347cf9b89889c06 100644 (file)
@@ -269,4 +269,9 @@ static inline bool xen_arch_need_swiotlb(struct device *dev,
        return false;
 }
 
+static inline unsigned long xen_get_swiotlb_free_pages(unsigned int order)
+{
+       return __get_free_pages(__GFP_NOWARN, order);
+}
+
 #endif /* _ASM_X86_XEN_PAGE_H */
index 90c458e66e13332b847f2a5fb1f0772d3f70e39f..ce6068dbcfbc6e84c76b43239d80f5d020d431ee 100644 (file)
 #define HV_STATUS_INVALID_HYPERCALL_CODE       2
 #define HV_STATUS_INVALID_HYPERCALL_INPUT      3
 #define HV_STATUS_INVALID_ALIGNMENT            4
+#define HV_STATUS_INSUFFICIENT_MEMORY          11
+#define HV_STATUS_INVALID_CONNECTION_ID                18
 #define HV_STATUS_INSUFFICIENT_BUFFERS         19
 
 typedef struct _HV_REFERENCE_TSC_PAGE {
index cb9f6f12246b797a870419001ae2323d69070797..271293ad89d74678dc1bc504bfe6ed5313de1c91 100644 (file)
@@ -728,7 +728,7 @@ static int _acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu)
 }
 
 /* wrapper to silence section mismatch warning */
-int __ref acpi_map_cpu(acpi_handle handle, int physid, int *pcpu)
+int __ref acpi_map_cpu(acpi_handle handle, phys_cpuid_t physid, int *pcpu)
 {
        return _acpi_map_lsapic(handle, physid, pcpu);
 }
index ae693b51ed8ed589660570a77cfb5654af924388..8c35df4681041eee92f14020de8f795a8b7d710c 100644 (file)
@@ -62,7 +62,7 @@ ENTRY(do_suspend_lowlevel)
        pushfq
        popq    pt_regs_flags(%rax)
 
-       movq    $resume_point, saved_rip(%rip)
+       movq    $.Lresume_point, saved_rip(%rip)
 
        movq    %rsp, saved_rsp
        movq    %rbp, saved_rbp
@@ -75,10 +75,10 @@ ENTRY(do_suspend_lowlevel)
        xorl    %eax, %eax
        call    x86_acpi_enter_sleep_state
        /* in case something went wrong, restore the machine status and go on */
-       jmp     resume_point
+       jmp     .Lresume_point
 
        .align 4
-resume_point:
+.Lresume_point:
        /* We don't restore %rax, it must be 0 anyway */
        movq    $saved_context, %rax
        movq    saved_context_cr4(%rax), %rbx
index aef65319316065eab845f35141682c3550f18a22..b0932c4341b3fd467ec10764d47e88b50d3d1d35 100644 (file)
@@ -227,6 +227,15 @@ void __init arch_init_ideal_nops(void)
 #endif
                }
                break;
+
+       case X86_VENDOR_AMD:
+               if (boot_cpu_data.x86 > 0xf) {
+                       ideal_nops = p6_nops;
+                       return;
+               }
+
+               /* fall through */
+
        default:
 #ifdef CONFIG_X86_64
                ideal_nops = k8_nops;
index 426496862be0765c7af89673fa37d8c3f7d0983a..2766747e1a3b316d65be99b0d3f6feb4a021a533 100644 (file)
@@ -366,16 +366,13 @@ static void init_legacy_irqs(void)
 
        /*
         * For legacy IRQ's, start with assigning irq0 to irq15 to
-        * IRQ0_VECTOR to IRQ15_VECTOR for all cpu's.
+        * ISA_IRQ_VECTOR(i) for all cpu's.
         */
        for (i = 0; i < nr_legacy_irqs(); i++) {
                data = legacy_irq_data[i] = alloc_apic_chip_data(node);
                BUG_ON(!data);
-               /*
-                * For legacy IRQ's, start with assigning irq0 to irq15 to
-                * IRQ0_VECTOR to IRQ15_VECTOR for all cpu's.
-                */
-               data->cfg.vector = IRQ0_VECTOR + i;
+
+               data->cfg.vector = ISA_IRQ_VECTOR(i);
                cpumask_setall(data->domain);
                irq_set_chip_data(i, data);
        }
@@ -452,7 +449,7 @@ void setup_vector_irq(int cpu)
         * legacy vector to irq mapping:
         */
        for (irq = 0; irq < nr_legacy_irqs(); irq++)
-               per_cpu(vector_irq, cpu)[IRQ0_VECTOR + irq] = irq;
+               per_cpu(vector_irq, cpu)[ISA_IRQ_VECTOR(irq)] = irq;
 
        __setup_vector_irq(cpu);
 }
index 9f6b9341950f7895b247b1c320cc0f9cd75cda9d..8e3d22a1af94094b749abca95187b073403d628c 100644 (file)
@@ -41,6 +41,25 @@ void common(void) {
        OFFSET(pbe_orig_address, pbe, orig_address);
        OFFSET(pbe_next, pbe, next);
 
+#if defined(CONFIG_X86_32) || defined(CONFIG_IA32_EMULATION)
+       BLANK();
+       OFFSET(IA32_SIGCONTEXT_ax, sigcontext_ia32, ax);
+       OFFSET(IA32_SIGCONTEXT_bx, sigcontext_ia32, bx);
+       OFFSET(IA32_SIGCONTEXT_cx, sigcontext_ia32, cx);
+       OFFSET(IA32_SIGCONTEXT_dx, sigcontext_ia32, dx);
+       OFFSET(IA32_SIGCONTEXT_si, sigcontext_ia32, si);
+       OFFSET(IA32_SIGCONTEXT_di, sigcontext_ia32, di);
+       OFFSET(IA32_SIGCONTEXT_bp, sigcontext_ia32, bp);
+       OFFSET(IA32_SIGCONTEXT_sp, sigcontext_ia32, sp);
+       OFFSET(IA32_SIGCONTEXT_ip, sigcontext_ia32, ip);
+
+       BLANK();
+       OFFSET(TI_sysenter_return, thread_info, sysenter_return);
+
+       BLANK();
+       OFFSET(IA32_RT_SIGFRAME_sigcontext, rt_sigframe_ia32, uc.uc_mcontext);
+#endif
+
 #ifdef CONFIG_PARAVIRT
        BLANK();
        OFFSET(PARAVIRT_enabled, pv_info, paravirt_enabled);
@@ -49,7 +68,9 @@ void common(void) {
        OFFSET(PV_IRQ_irq_disable, pv_irq_ops, irq_disable);
        OFFSET(PV_IRQ_irq_enable, pv_irq_ops, irq_enable);
        OFFSET(PV_CPU_iret, pv_cpu_ops, iret);
+#ifdef CONFIG_X86_32
        OFFSET(PV_CPU_irq_enable_sysexit, pv_cpu_ops, irq_enable_sysexit);
+#endif
        OFFSET(PV_CPU_read_cr0, pv_cpu_ops, read_cr0);
        OFFSET(PV_MMU_read_cr2, pv_mmu_ops, read_cr2);
 #endif
index 47703aed74cfb7d013b2d577488d68c7280bf8c6..6ce39025f467fb060ce68c8b8ebfaf8f87258d09 100644 (file)
@@ -17,17 +17,6 @@ void foo(void);
 
 void foo(void)
 {
-       OFFSET(IA32_SIGCONTEXT_ax, sigcontext, ax);
-       OFFSET(IA32_SIGCONTEXT_bx, sigcontext, bx);
-       OFFSET(IA32_SIGCONTEXT_cx, sigcontext, cx);
-       OFFSET(IA32_SIGCONTEXT_dx, sigcontext, dx);
-       OFFSET(IA32_SIGCONTEXT_si, sigcontext, si);
-       OFFSET(IA32_SIGCONTEXT_di, sigcontext, di);
-       OFFSET(IA32_SIGCONTEXT_bp, sigcontext, bp);
-       OFFSET(IA32_SIGCONTEXT_sp, sigcontext, sp);
-       OFFSET(IA32_SIGCONTEXT_ip, sigcontext, ip);
-       BLANK();
-
        OFFSET(CPUINFO_x86, cpuinfo_x86, x86);
        OFFSET(CPUINFO_x86_vendor, cpuinfo_x86, x86_vendor);
        OFFSET(CPUINFO_x86_model, cpuinfo_x86, x86_model);
@@ -37,10 +26,6 @@ void foo(void)
        OFFSET(CPUINFO_x86_vendor_id, cpuinfo_x86, x86_vendor_id);
        BLANK();
 
-       OFFSET(TI_sysenter_return, thread_info, sysenter_return);
-       OFFSET(TI_cpu, thread_info, cpu);
-       BLANK();
-
        OFFSET(PT_EBX, pt_regs, bx);
        OFFSET(PT_ECX, pt_regs, cx);
        OFFSET(PT_EDX, pt_regs, dx);
@@ -60,9 +45,6 @@ void foo(void)
        OFFSET(PT_OLDSS,  pt_regs, ss);
        BLANK();
 
-       OFFSET(IA32_RT_SIGFRAME_sigcontext, rt_sigframe, uc.uc_mcontext);
-       BLANK();
-
        OFFSET(saved_context_gdt_desc, saved_context, gdt_desc);
        BLANK();
 
index 5ce6f2da87639c7d373879e43120c9035ba590b9..dcaab87da6298045363f868982ad7f5f5688ab8b 100644 (file)
@@ -29,27 +29,6 @@ int main(void)
        BLANK();
 #endif
 
-#ifdef CONFIG_IA32_EMULATION
-       OFFSET(TI_sysenter_return, thread_info, sysenter_return);
-       BLANK();
-
-#define ENTRY(entry) OFFSET(IA32_SIGCONTEXT_ ## entry, sigcontext_ia32, entry)
-       ENTRY(ax);
-       ENTRY(bx);
-       ENTRY(cx);
-       ENTRY(dx);
-       ENTRY(si);
-       ENTRY(di);
-       ENTRY(bp);
-       ENTRY(sp);
-       ENTRY(ip);
-       BLANK();
-#undef ENTRY
-
-       OFFSET(IA32_RT_SIGFRAME_sigcontext, rt_sigframe_ia32, uc.uc_mcontext);
-       BLANK();
-#endif
-
 #define ENTRY(entry) OFFSET(pt_regs_ ## entry, pt_regs, entry)
        ENTRY(bx);
        ENTRY(cx);
index fd470ebf924e574e827f1942b973075d3168a9b6..e4cf63301ff439ed390e50a81a72fef9ea50e23a 100644 (file)
@@ -720,6 +720,9 @@ static void init_amd(struct cpuinfo_x86 *c)
        if (!cpu_has(c, X86_FEATURE_3DNOWPREFETCH))
                if (cpu_has(c, X86_FEATURE_3DNOW) || cpu_has(c, X86_FEATURE_LM))
                        set_cpu_cap(c, X86_FEATURE_3DNOWPREFETCH);
+
+       /* AMD CPUs don't reset SS attributes on SYSRET */
+       set_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS);
 }
 
 #ifdef CONFIG_X86_32
index a62cf04dac8ae99d1310b02b827bca528311d490..6bec0b55863e315c65ca40ff18454aaf55844d06 100644 (file)
@@ -1155,10 +1155,6 @@ static __init int setup_disablecpuid(char *arg)
 }
 __setup("clearcpuid=", setup_disablecpuid);
 
-DEFINE_PER_CPU(unsigned long, kernel_stack) =
-       (unsigned long)&init_thread_union + THREAD_SIZE;
-EXPORT_PER_CPU_SYMBOL(kernel_stack);
-
 #ifdef CONFIG_X86_64
 struct desc_ptr idt_descr = { NR_VECTORS * 16 - 1, (unsigned long) idt_table };
 struct desc_ptr debug_idt_descr = { NR_VECTORS * 16 - 1,
index 36ce402a3fa5b311014b30e3dd8cac69d5f68a88..d820d8eae96be0b3daa0ec01d9f4a22bf1ad930e 100644 (file)
@@ -27,8 +27,8 @@
 
 static const __initconst struct hypervisor_x86 * const hypervisors[] =
 {
-#ifdef CONFIG_XEN_PVHVM
-       &x86_hyper_xen_hvm,
+#ifdef CONFIG_XEN
+       &x86_hyper_xen,
 #endif
        &x86_hyper_vmware,
        &x86_hyper_ms_hyperv,
index 219d3fb423a17a1bb30e99d565ab01de552f49e7..960e85de13fbca45c317eeb8b719f05c7914ba1f 100644 (file)
@@ -2533,34 +2533,6 @@ ssize_t intel_event_sysfs_show(char *page, u64 config)
        return x86_event_sysfs_show(page, config, event);
 }
 
-static __initconst const struct x86_pmu core_pmu = {
-       .name                   = "core",
-       .handle_irq             = x86_pmu_handle_irq,
-       .disable_all            = x86_pmu_disable_all,
-       .enable_all             = core_pmu_enable_all,
-       .enable                 = core_pmu_enable_event,
-       .disable                = x86_pmu_disable_event,
-       .hw_config              = x86_pmu_hw_config,
-       .schedule_events        = x86_schedule_events,
-       .eventsel               = MSR_ARCH_PERFMON_EVENTSEL0,
-       .perfctr                = MSR_ARCH_PERFMON_PERFCTR0,
-       .event_map              = intel_pmu_event_map,
-       .max_events             = ARRAY_SIZE(intel_perfmon_event_map),
-       .apic                   = 1,
-       /*
-        * Intel PMCs cannot be accessed sanely above 32 bit width,
-        * so we install an artificial 1<<31 period regardless of
-        * the generic event period:
-        */
-       .max_period             = (1ULL << 31) - 1,
-       .get_event_constraints  = intel_get_event_constraints,
-       .put_event_constraints  = intel_put_event_constraints,
-       .event_constraints      = intel_core_event_constraints,
-       .guest_get_msrs         = core_guest_get_msrs,
-       .format_attrs           = intel_arch_formats_attr,
-       .events_sysfs_show      = intel_event_sysfs_show,
-};
-
 struct intel_shared_regs *allocate_shared_regs(int cpu)
 {
        struct intel_shared_regs *regs;
@@ -2743,6 +2715,44 @@ static struct attribute *intel_arch3_formats_attr[] = {
        NULL,
 };
 
+static __initconst const struct x86_pmu core_pmu = {
+       .name                   = "core",
+       .handle_irq             = x86_pmu_handle_irq,
+       .disable_all            = x86_pmu_disable_all,
+       .enable_all             = core_pmu_enable_all,
+       .enable                 = core_pmu_enable_event,
+       .disable                = x86_pmu_disable_event,
+       .hw_config              = x86_pmu_hw_config,
+       .schedule_events        = x86_schedule_events,
+       .eventsel               = MSR_ARCH_PERFMON_EVENTSEL0,
+       .perfctr                = MSR_ARCH_PERFMON_PERFCTR0,
+       .event_map              = intel_pmu_event_map,
+       .max_events             = ARRAY_SIZE(intel_perfmon_event_map),
+       .apic                   = 1,
+       /*
+        * Intel PMCs cannot be accessed sanely above 32-bit width,
+        * so we install an artificial 1<<31 period regardless of
+        * the generic event period:
+        */
+       .max_period             = (1ULL<<31) - 1,
+       .get_event_constraints  = intel_get_event_constraints,
+       .put_event_constraints  = intel_put_event_constraints,
+       .event_constraints      = intel_core_event_constraints,
+       .guest_get_msrs         = core_guest_get_msrs,
+       .format_attrs           = intel_arch_formats_attr,
+       .events_sysfs_show      = intel_event_sysfs_show,
+
+       /*
+        * Virtual (or funny metal) CPU can define x86_pmu.extra_regs
+        * together with PMU version 1 and thus be using core_pmu with
+        * shared_regs. We need following callbacks here to allocate
+        * it properly.
+        */
+       .cpu_prepare            = intel_pmu_cpu_prepare,
+       .cpu_starting           = intel_pmu_cpu_starting,
+       .cpu_dying              = intel_pmu_cpu_dying,
+};
+
 static __initconst const struct x86_pmu intel_pmu = {
        .name                   = "Intel",
        .handle_irq             = intel_pmu_handle_irq,
index 3001015b755c7e4dc2f540db36d3d1a88cb09bbf..4562e9e22c60600a89f706c3b8c3cfb269636060 100644 (file)
@@ -1,6 +1,13 @@
 /* Nehalem/SandBridge/Haswell uncore support */
 #include "perf_event_intel_uncore.h"
 
+/* Uncore IMC PCI IDs */
+#define PCI_DEVICE_ID_INTEL_SNB_IMC    0x0100
+#define PCI_DEVICE_ID_INTEL_IVB_IMC    0x0154
+#define PCI_DEVICE_ID_INTEL_IVB_E3_IMC 0x0150
+#define PCI_DEVICE_ID_INTEL_HSW_IMC    0x0c00
+#define PCI_DEVICE_ID_INTEL_HSW_U_IMC  0x0a04
+
 /* SNB event control */
 #define SNB_UNC_CTL_EV_SEL_MASK                        0x000000ff
 #define SNB_UNC_CTL_UMASK_MASK                 0x0000ff00
@@ -472,6 +479,10 @@ static const struct pci_device_id hsw_uncore_pci_ids[] = {
                PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HSW_IMC),
                .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
        },
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HSW_U_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
        { /* end: all zeroes */ },
 };
 
@@ -502,6 +513,7 @@ static const struct imc_uncore_pci_dev desktop_imc_pci_ids[] = {
        IMC_DEV(IVB_IMC, &ivb_uncore_pci_driver),    /* 3rd Gen Core processor */
        IMC_DEV(IVB_E3_IMC, &ivb_uncore_pci_driver), /* Xeon E3-1200 v2/3rd Gen Core processor */
        IMC_DEV(HSW_IMC, &hsw_uncore_pci_driver),    /* 4th Gen Core Processor */
+       IMC_DEV(HSW_U_IMC, &hsw_uncore_pci_driver),  /* 4th Gen Core ULT Mobile Processor */
        {  /* end marker */ }
 };
 
index 49ff55ef9b26cba11af5d9b36c694926ea3e7f6b..89427d8d4fc53addcb429b994f02de7d0bb7dfa4 100644 (file)
@@ -375,12 +375,6 @@ static int __init setup_early_printk(char *buf)
                if (!strncmp(buf, "xen", 3))
                        early_console_register(&xenboot_console, keep);
 #endif
-#ifdef CONFIG_EARLY_PRINTK_INTEL_MID
-               if (!strncmp(buf, "hsu", 3)) {
-                       hsu_early_console_init(buf + 3);
-                       early_console_register(&early_hsu_console, keep);
-               }
-#endif
 #ifdef CONFIG_EARLY_PRINTK_EFI
                if (!strncmp(buf, "efi", 3))
                        early_console_register(&early_efi_console, keep);
index c7b238494b31f267b9c4fc3f4a74d519fb7b3aa5..09c3f9e0e07e142d3254946b700b00aea9b94020 100644 (file)
@@ -216,7 +216,7 @@ ENTRY(system_call)
 GLOBAL(system_call_after_swapgs)
 
        movq    %rsp,PER_CPU_VAR(rsp_scratch)
-       movq    PER_CPU_VAR(kernel_stack),%rsp
+       movq    PER_CPU_VAR(cpu_current_top_of_stack),%rsp
 
        /* Construct struct pt_regs on stack */
        pushq_cfi $__USER_DS                    /* pt_regs->ss */
@@ -295,6 +295,15 @@ system_call_fastpath:
         * rflags from r11 (but RF and VM bits are forced to 0),
         * cs and ss are loaded from MSRs.
         * Restoration of rflags re-enables interrupts.
+        *
+        * NB: On AMD CPUs with the X86_BUG_SYSRET_SS_ATTRS bug, the ss
+        * descriptor is not reinitialized.  This means that we should
+        * avoid SYSRET with SS == NULL, which could happen if we schedule,
+        * exit the kernel, and re-enter using an interrupt vector.  (All
+        * interrupt entries on x86_64 set SS to NULL.)  We prevent that
+        * from happening by reloading SS in __switch_to.  (Actually
+        * detecting the failure in 64-bit userspace is tricky but can be
+        * done.)
         */
        USERGS_SYSRET64
 
@@ -410,26 +419,27 @@ syscall_return:
         * a completely clean 64-bit userspace context.
         */
        movq RCX(%rsp),%rcx
-       cmpq %rcx,RIP(%rsp)             /* RCX == RIP */
+       movq RIP(%rsp),%r11
+       cmpq %rcx,%r11                  /* RCX == RIP */
        jne opportunistic_sysret_failed
 
        /*
         * On Intel CPUs, SYSRET with non-canonical RCX/RIP will #GP
         * in kernel space.  This essentially lets the user take over
-        * the kernel, since userspace controls RSP.  It's not worth
-        * testing for canonicalness exactly -- this check detects any
-        * of the 17 high bits set, which is true for non-canonical
-        * or kernel addresses.  (This will pessimize vsyscall=native.
-        * Big deal.)
+        * the kernel, since userspace controls RSP.
         *
-        * If virtual addresses ever become wider, this will need
+        * If width of "canonical tail" ever becomes variable, this will need
         * to be updated to remain correct on both old and new CPUs.
         */
        .ifne __VIRTUAL_MASK_SHIFT - 47
        .error "virtual address width changed -- SYSRET checks need update"
        .endif
-       shr $__VIRTUAL_MASK_SHIFT, %rcx
-       jnz opportunistic_sysret_failed
+       /* Change top 16 bits to be the sign-extension of 47th bit */
+       shl     $(64 - (__VIRTUAL_MASK_SHIFT+1)), %rcx
+       sar     $(64 - (__VIRTUAL_MASK_SHIFT+1)), %rcx
+       /* If this changed %rcx, it was not canonical */
+       cmpq    %rcx, %r11
+       jne     opportunistic_sysret_failed
 
        cmpq $__USER_CS,CS(%rsp)        /* CS must match SYSRET */
        jne opportunistic_sysret_failed
@@ -466,8 +476,8 @@ syscall_return:
         */
 syscall_return_via_sysret:
        CFI_REMEMBER_STATE
-       /* r11 is already restored (see code above) */
-       RESTORE_C_REGS_EXCEPT_R11
+       /* rcx and r11 are already restored (see code above) */
+       RESTORE_C_REGS_EXCEPT_RCX_R11
        movq RSP(%rsp),%rsp
        USERGS_SYSRET64
        CFI_RESTORE_STATE
@@ -524,40 +534,27 @@ GLOBAL(stub_execveat)
        CFI_ENDPROC
 END(stub_execveat)
 
-#ifdef CONFIG_X86_X32_ABI
+#if defined(CONFIG_X86_X32_ABI) || defined(CONFIG_IA32_EMULATION)
        .align  8
 GLOBAL(stub_x32_execve)
+GLOBAL(stub32_execve)
        CFI_STARTPROC
        DEFAULT_FRAME 0, 8
        call    compat_sys_execve
        jmp     return_from_execve
        CFI_ENDPROC
+END(stub32_execve)
 END(stub_x32_execve)
        .align  8
 GLOBAL(stub_x32_execveat)
-       CFI_STARTPROC
-       DEFAULT_FRAME 0, 8
-       call    compat_sys_execveat
-       jmp     return_from_execve
-       CFI_ENDPROC
-END(stub_x32_execveat)
-#endif
-
-#ifdef CONFIG_IA32_EMULATION
-       .align  8
-GLOBAL(stub32_execve)
-       CFI_STARTPROC
-       call    compat_sys_execve
-       jmp     return_from_execve
-       CFI_ENDPROC
-END(stub32_execve)
-       .align  8
 GLOBAL(stub32_execveat)
        CFI_STARTPROC
+       DEFAULT_FRAME 0, 8
        call    compat_sys_execveat
        jmp     return_from_execve
        CFI_ENDPROC
 END(stub32_execveat)
+END(stub_x32_execveat)
 #endif
 
 /*
@@ -613,7 +610,7 @@ ENTRY(ret_from_fork)
 
        RESTORE_EXTRA_REGS
 
-       testl $3,CS(%rsp)                       # from kernel_thread?
+       testb   $3, CS(%rsp)                    # from kernel_thread?
 
        /*
         * By the time we get here, we have no idea whether our pt_regs,
@@ -677,8 +674,8 @@ END(irq_entries_start)
 
        leaq -RBP(%rsp),%rdi    /* arg1 for \func (pointer to pt_regs) */
 
-       testl $3, CS-RBP(%rsp)
-       je 1f
+       testb   $3, CS-RBP(%rsp)
+       jz      1f
        SWAPGS
 1:
        /*
@@ -732,8 +729,8 @@ ret_from_intr:
        CFI_DEF_CFA_REGISTER    rsp
        CFI_ADJUST_CFA_OFFSET   RBP
 
-       testl $3,CS(%rsp)
-       je retint_kernel
+       testb   $3, CS(%rsp)
+       jz      retint_kernel
        /* Interrupt came from user space */
 
        GET_THREAD_INFO(%rcx)
@@ -980,7 +977,7 @@ ENTRY(\sym)
        .if \paranoid
        .if \paranoid == 1
        CFI_REMEMBER_STATE
-       testl $3, CS(%rsp)              /* If coming from userspace, switch */
+       testb   $3, CS(%rsp)            /* If coming from userspace, switch */
        jnz 1f                          /* stacks. */
        .endif
        call paranoid_entry
@@ -1321,8 +1318,8 @@ ENTRY(error_entry)
        SAVE_C_REGS 8
        SAVE_EXTRA_REGS 8
        xorl %ebx,%ebx
-       testl $3,CS+8(%rsp)
-       je error_kernelspace
+       testb   $3, CS+8(%rsp)
+       jz      error_kernelspace
 error_swapgs:
        SWAPGS
 error_sti:
@@ -1373,7 +1370,7 @@ ENTRY(error_exit)
        TRACE_IRQS_OFF
        GET_THREAD_INFO(%rcx)
        testl %eax,%eax
-       jne retint_kernel
+       jnz retint_kernel
        LOCKDEP_SYS_EXIT_IRQ
        movl TI_flags(%rcx),%edx
        movl $_TIF_WORK_MASK,%edi
@@ -1618,7 +1615,6 @@ end_repeat_nmi:
        je 1f
        movq %r12, %cr2
 1:
-       
        testl %ebx,%ebx                         /* swapgs needed? */
        jnz nmi_restore
 nmi_swapgs:
index e7cc5370cd2fcade87dc1cecae2ab85184f62d27..16cb827a5b27745d1f571d49a5b45443babb2c8c 100644 (file)
@@ -329,8 +329,8 @@ static void init_8259A(int auto_eoi)
         */
        outb_pic(0x11, PIC_MASTER_CMD); /* ICW1: select 8259A-1 init */
 
-       /* ICW2: 8259A-1 IR0-7 mapped to 0x30-0x37 */
-       outb_pic(IRQ0_VECTOR, PIC_MASTER_IMR);
+       /* ICW2: 8259A-1 IR0-7 mapped to ISA_IRQ_VECTOR(0) */
+       outb_pic(ISA_IRQ_VECTOR(0), PIC_MASTER_IMR);
 
        /* 8259A-1 (the master) has a slave on IR2 */
        outb_pic(1U << PIC_CASCADE_IR, PIC_MASTER_IMR);
@@ -342,8 +342,8 @@ static void init_8259A(int auto_eoi)
 
        outb_pic(0x11, PIC_SLAVE_CMD);  /* ICW1: select 8259A-2 init */
 
-       /* ICW2: 8259A-2 IR0-7 mapped to IRQ8_VECTOR */
-       outb_pic(IRQ8_VECTOR, PIC_SLAVE_IMR);
+       /* ICW2: 8259A-2 IR0-7 mapped to ISA_IRQ_VECTOR(8) */
+       outb_pic(ISA_IRQ_VECTOR(8), PIC_SLAVE_IMR);
        /* 8259A-2 is a slave on master's IR2 */
        outb_pic(PIC_CASCADE_IR, PIC_SLAVE_IMR);
        /* (slave's support for AEOI in flat mode is to be investigated) */
index e5952c22553241e2ceea5d5fd6f1f7b758cc960e..fe2ed8bb507be2a20f90e4c284afd3e8a5a6977e 100644 (file)
 #define CREATE_TRACE_POINTS
 #include <asm/trace/irq_vectors.h>
 
+DEFINE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);
+EXPORT_PER_CPU_SYMBOL(irq_stat);
+
+DEFINE_PER_CPU(struct pt_regs *, irq_regs);
+EXPORT_PER_CPU_SYMBOL(irq_regs);
+
 atomic_t irq_err_count;
 
 /* Function pointer for generic interrupt vector handling */
index f9fd86a7fcc7d1bc8c2cc920fc5b5037f5859336..cd74f5978ab97a4c7d2ee072d23d764ab49ca6dd 100644 (file)
 
 #include <asm/apic.h>
 
-DEFINE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);
-EXPORT_PER_CPU_SYMBOL(irq_stat);
-
-DEFINE_PER_CPU(struct pt_regs *, irq_regs);
-EXPORT_PER_CPU_SYMBOL(irq_regs);
-
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
 
 int sysctl_panic_on_stackoverflow __read_mostly;
index 394e643d7830fc01d4da516bd79cab1dc0aa6962..bc4604e500a3284ab3b2f5903b4fc1d506c0b367 100644 (file)
 #include <asm/idle.h>
 #include <asm/apic.h>
 
-DEFINE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);
-EXPORT_PER_CPU_SYMBOL(irq_stat);
-
-DEFINE_PER_CPU(struct pt_regs *, irq_regs);
-EXPORT_PER_CPU_SYMBOL(irq_regs);
-
 int sysctl_panic_on_stackoverflow;
 
 /*
index cd10a64372647c3579ba6717db49c6cd63c6353a..dc1e08d2355251b834b0c86e480181e2d4fb1ab9 100644 (file)
@@ -86,7 +86,7 @@ void __init init_IRQ(void)
        int i;
 
        /*
-        * On cpu 0, Assign IRQ0_VECTOR..IRQ15_VECTOR's to IRQ 0..15.
+        * On cpu 0, Assign ISA_IRQ_VECTOR(irq) to IRQ 0..15.
         * If these IRQ's are handled by legacy interrupt-controllers like PIC,
         * then this configuration will likely be static after the boot. If
         * these IRQ's are handled by more mordern controllers like IO-APIC,
@@ -94,7 +94,7 @@ void __init init_IRQ(void)
         * irq's migrate etc.
         */
        for (i = 0; i < nr_legacy_irqs(); i++)
-               per_cpu(vector_irq, 0)[IRQ0_VECTOR + i] = i;
+               per_cpu(vector_irq, 0)[ISA_IRQ_VECTOR(i)] = i;
 
        x86_init.irqs.intr_init();
 }
index c614dd492f5f720058346a33883f5a67d4689b94..58bcfb67c01f1f1f9b60a6e87bf5fd11b80bd281 100644 (file)
@@ -154,7 +154,9 @@ unsigned paravirt_patch_default(u8 type, u16 clobbers, void *insnbuf,
                ret = paravirt_patch_ident_64(insnbuf, len);
 
        else if (type == PARAVIRT_PATCH(pv_cpu_ops.iret) ||
+#ifdef CONFIG_X86_32
                 type == PARAVIRT_PATCH(pv_cpu_ops.irq_enable_sysexit) ||
+#endif
                 type == PARAVIRT_PATCH(pv_cpu_ops.usergs_sysret32) ||
                 type == PARAVIRT_PATCH(pv_cpu_ops.usergs_sysret64))
                /* If operation requires a jmp, then jmp */
@@ -371,7 +373,7 @@ __visible struct pv_cpu_ops pv_cpu_ops = {
 
        .load_sp0 = native_load_sp0,
 
-#if defined(CONFIG_X86_32) || defined(CONFIG_IA32_EMULATION)
+#if defined(CONFIG_X86_32)
        .irq_enable_sysexit = native_irq_enable_sysexit,
 #endif
 #ifdef CONFIG_X86_64
index a1da6737ba5b80c4ee636204d49d4813348ef903..0de21c62c348542be70f11782b9718579dfac6f1 100644 (file)
@@ -49,7 +49,6 @@ unsigned native_patch(u8 type, u16 clobbers, void *ibuf,
                PATCH_SITE(pv_irq_ops, save_fl);
                PATCH_SITE(pv_irq_ops, irq_enable);
                PATCH_SITE(pv_irq_ops, irq_disable);
-               PATCH_SITE(pv_cpu_ops, irq_enable_sysexit);
                PATCH_SITE(pv_cpu_ops, usergs_sysret32);
                PATCH_SITE(pv_cpu_ops, usergs_sysret64);
                PATCH_SITE(pv_cpu_ops, swapgs);
index 8213da62b1b79c1c37798b598494add6802881d7..6e338e3b1dc04cc69ab41c012fe5671cc25321cd 100644 (file)
@@ -57,7 +57,7 @@ __visible DEFINE_PER_CPU_SHARED_ALIGNED(struct tss_struct, cpu_tss) = {
        .io_bitmap              = { [0 ... IO_BITMAP_LONGS] = ~0 },
 #endif
 };
-EXPORT_PER_CPU_SYMBOL_GPL(cpu_tss);
+EXPORT_PER_CPU_SYMBOL(cpu_tss);
 
 #ifdef CONFIG_X86_64
 static DEFINE_PER_CPU(unsigned char, is_idle);
@@ -156,11 +156,13 @@ void flush_thread(void)
                /* FPU state will be reallocated lazily at the first use. */
                drop_fpu(tsk);
                free_thread_xstate(tsk);
-       } else if (!used_math()) {
-               /* kthread execs. TODO: cleanup this horror. */
-               if (WARN_ON(init_fpu(tsk)))
-                       force_sig(SIGKILL, tsk);
-               user_fpu_begin();
+       } else {
+               if (!tsk_used_math(tsk)) {
+                       /* kthread execs. TODO: cleanup this horror. */
+                       if (WARN_ON(init_fpu(tsk)))
+                               force_sig(SIGKILL, tsk);
+                       user_fpu_begin();
+               }
                restore_init_xstate();
        }
 }
index 8ed2106b06da63e0a8e0dcf561aad7a1fc112e40..a99900cedc22c4fc9836a0c956ef3723c4863215 100644 (file)
@@ -302,13 +302,10 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
        arch_end_context_switch(next_p);
 
        /*
-        * Reload esp0, kernel_stack, and current_top_of_stack.  This changes
+        * Reload esp0 and cpu_current_top_of_stack.  This changes
         * current_thread_info().
         */
        load_sp0(tss, next);
-       this_cpu_write(kernel_stack,
-                      (unsigned long)task_stack_page(next_p) +
-                      THREAD_SIZE);
        this_cpu_write(cpu_current_top_of_stack,
                       (unsigned long)task_stack_page(next_p) +
                       THREAD_SIZE);
index 4baaa972f52aaed15b3dddd94b4df4f653126d81..82134506faa8ae939c9b1e216898ef66b1392e4b 100644 (file)
@@ -409,9 +409,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
        /* Reload esp0 and ss1.  This changes current_thread_info(). */
        load_sp0(tss, next);
 
-       this_cpu_write(kernel_stack,
-               (unsigned long)task_stack_page(next_p) + THREAD_SIZE);
-
        /*
         * Now maybe reload the debug registers and handle I/O bitmaps
         */
@@ -419,6 +416,34 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
                     task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV))
                __switch_to_xtra(prev_p, next_p, tss);
 
+       if (static_cpu_has_bug(X86_BUG_SYSRET_SS_ATTRS)) {
+               /*
+                * AMD CPUs have a misfeature: SYSRET sets the SS selector but
+                * does not update the cached descriptor.  As a result, if we
+                * do SYSRET while SS is NULL, we'll end up in user mode with
+                * SS apparently equal to __USER_DS but actually unusable.
+                *
+                * The straightforward workaround would be to fix it up just
+                * before SYSRET, but that would slow down the system call
+                * fast paths.  Instead, we ensure that SS is never NULL in
+                * system call context.  We do this by replacing NULL SS
+                * selectors at every context switch.  SYSCALL sets up a valid
+                * SS, so the only way to get NULL is to re-enter the kernel
+                * from CPL 3 through an interrupt.  Since that can't happen
+                * in the same task as a running syscall, we are guaranteed to
+                * context switch between every interrupt vector entry and a
+                * subsequent SYSRET.
+                *
+                * We read SS first because SS reads are much faster than
+                * writes.  Out of caution, we force SS to __KERNEL_DS even if
+                * it previously had a different non-NULL value.
+                */
+               unsigned short ss_sel;
+               savesegment(ss, ss_sel);
+               if (ss_sel != __KERNEL_DS)
+                       loadsegment(ss, __KERNEL_DS);
+       }
+
        return prev_p;
 }
 
index e5ecd20e72dd56d82447c94c17e6e85ae29eba90..2f355d229a587771680b28080d92fd06f345d7e7 100644 (file)
@@ -141,46 +141,7 @@ void pvclock_read_wallclock(struct pvclock_wall_clock *wall_clock,
        set_normalized_timespec(ts, now.tv_sec, now.tv_nsec);
 }
 
-static struct pvclock_vsyscall_time_info *pvclock_vdso_info;
-
-static struct pvclock_vsyscall_time_info *
-pvclock_get_vsyscall_user_time_info(int cpu)
-{
-       if (!pvclock_vdso_info) {
-               BUG();
-               return NULL;
-       }
-
-       return &pvclock_vdso_info[cpu];
-}
-
-struct pvclock_vcpu_time_info *pvclock_get_vsyscall_time_info(int cpu)
-{
-       return &pvclock_get_vsyscall_user_time_info(cpu)->pvti;
-}
-
 #ifdef CONFIG_X86_64
-static int pvclock_task_migrate(struct notifier_block *nb, unsigned long l,
-                               void *v)
-{
-       struct task_migration_notifier *mn = v;
-       struct pvclock_vsyscall_time_info *pvti;
-
-       pvti = pvclock_get_vsyscall_user_time_info(mn->from_cpu);
-
-       /* this is NULL when pvclock vsyscall is not initialized */
-       if (unlikely(pvti == NULL))
-               return NOTIFY_DONE;
-
-       pvti->migrate_count++;
-
-       return NOTIFY_DONE;
-}
-
-static struct notifier_block pvclock_migrate = {
-       .notifier_call = pvclock_task_migrate,
-};
-
 /*
  * Initialize the generic pvclock vsyscall state.  This will allocate
  * a/some page(s) for the per-vcpu pvclock information, set up a
@@ -194,17 +155,12 @@ int __init pvclock_init_vsyscall(struct pvclock_vsyscall_time_info *i,
 
        WARN_ON (size != PVCLOCK_VSYSCALL_NR_PAGES*PAGE_SIZE);
 
-       pvclock_vdso_info = i;
-
        for (idx = 0; idx <= (PVCLOCK_FIXMAP_END-PVCLOCK_FIXMAP_BEGIN); idx++) {
                __set_fixmap(PVCLOCK_FIXMAP_BEGIN + idx,
                             __pa(i) + (idx*PAGE_SIZE),
                             PAGE_KERNEL_VVAR);
        }
 
-
-       register_task_migration_notifier(&pvclock_migrate);
-
        return 0;
 }
 #endif
index 63b46414c80c78ab5845b58e46cd2ca0bd437e67..51203f60587f847d51eaa33638604a082a864f54 100644 (file)
@@ -807,8 +807,6 @@ void common_cpu_up(unsigned int cpu, struct task_struct *idle)
        clear_tsk_thread_flag(idle, TIF_FORK);
        initial_gs = per_cpu_offset(cpu);
 #endif
-       per_cpu(kernel_stack, cpu) =
-               (unsigned long)task_stack_page(idle) + THREAD_SIZE;
 }
 
 /*
index 324ab524768756b1987efbee11f06ce3ba24562b..5e0791f9d3dca6c74de6f72d353d08224e395514 100644 (file)
@@ -997,8 +997,8 @@ void __init trap_init(void)
 #endif
 
 #ifdef CONFIG_X86_32
-       set_system_trap_gate(SYSCALL_VECTOR, &system_call);
-       set_bit(SYSCALL_VECTOR, used_vectors);
+       set_system_trap_gate(IA32_SYSCALL_VECTOR, &system_call);
+       set_bit(IA32_SYSCALL_VECTOR, used_vectors);
 #endif
 
        /*
index 6eb5c20ee3739855a5d3fe52aa9a253b677552fd..d090ecf088097f4f845fc20d7d1bdd0a5849e712 100644 (file)
@@ -666,7 +666,7 @@ static int probe_sysfs_permissions(struct pci_dev *dev)
                if (r)
                        return r;
 
-               inode = path.dentry->d_inode;
+               inode = d_backing_inode(path.dentry);
 
                r = inode_permission(inode, MAY_READ | MAY_WRITE | MAY_ACCESS);
                path_put(&path);
index d67206a7b99a689a4d7361de8bd8fc1b9ab02c1a..629af0f1c5c4d0953010adc88233132bcdff4cb7 100644 (file)
@@ -683,8 +683,7 @@ bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src,
        unsigned long bitmap = 1;
        struct kvm_lapic **dst;
        int i;
-       bool ret = false;
-       bool x2apic_ipi = src && apic_x2apic_mode(src);
+       bool ret, x2apic_ipi;
 
        *r = -1;
 
@@ -696,16 +695,18 @@ bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src,
        if (irq->shorthand)
                return false;
 
+       x2apic_ipi = src && apic_x2apic_mode(src);
        if (irq->dest_id == (x2apic_ipi ? X2APIC_BROADCAST : APIC_BROADCAST))
                return false;
 
+       ret = true;
        rcu_read_lock();
        map = rcu_dereference(kvm->arch.apic_map);
 
-       if (!map)
+       if (!map) {
+               ret = false;
                goto out;
-
-       ret = true;
+       }
 
        if (irq->dest_mode == APIC_DEST_PHYSICAL) {
                if (irq->dest_id >= ARRAY_SIZE(map->phys_map))
index 146f295ee32214a6f4ad40a58e53b61a3d1fa06d..d43867c33bc4efee0c970e9602cd63616b4ec739 100644 (file)
@@ -4481,9 +4481,11 @@ static bool kvm_mmu_zap_collapsible_spte(struct kvm *kvm,
                pfn = spte_to_pfn(*sptep);
 
                /*
-                * Only EPT supported for now; otherwise, one would need to
-                * find out efficiently whether the guest page tables are
-                * also using huge pages.
+                * We cannot do huge page mapping for indirect shadow pages,
+                * which are found on the last rmap (level = 1) when not using
+                * tdp; such shadow pages are synced with the page table in
+                * the guest, and the guest page table is using 4K page size
+                * mapping if the indirect sp has level = 1.
                 */
                if (sp->role.direct &&
                        !kvm_is_reserved_pfn(pfn) &&
@@ -4504,19 +4506,12 @@ void kvm_mmu_zap_collapsible_sptes(struct kvm *kvm,
        bool flush = false;
        unsigned long *rmapp;
        unsigned long last_index, index;
-       gfn_t gfn_start, gfn_end;
 
        spin_lock(&kvm->mmu_lock);
 
-       gfn_start = memslot->base_gfn;
-       gfn_end = memslot->base_gfn + memslot->npages - 1;
-
-       if (gfn_start >= gfn_end)
-               goto out;
-
        rmapp = memslot->arch.rmap[0];
-       last_index = gfn_to_index(gfn_end, memslot->base_gfn,
-                                       PT_PAGE_TABLE_LEVEL);
+       last_index = gfn_to_index(memslot->base_gfn + memslot->npages - 1,
+                               memslot->base_gfn, PT_PAGE_TABLE_LEVEL);
 
        for (index = 0; index <= last_index; ++index, ++rmapp) {
                if (*rmapp)
@@ -4534,7 +4529,6 @@ void kvm_mmu_zap_collapsible_sptes(struct kvm *kvm,
        if (flush)
                kvm_flush_remote_tlbs(kvm);
 
-out:
        spin_unlock(&kvm->mmu_lock);
 }
 
index f5e8dce8046c56b5273e9aa043754f98a7dee7d7..f7b61687bd79facc3f6ed0339b68ecf3fcf43aed 100644 (file)
@@ -3622,8 +3622,16 @@ static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
 
 static int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
 {
-       unsigned long hw_cr4 = cr4 | (to_vmx(vcpu)->rmode.vm86_active ?
-                   KVM_RMODE_VM_CR4_ALWAYS_ON : KVM_PMODE_VM_CR4_ALWAYS_ON);
+       /*
+        * Pass through host's Machine Check Enable value to hw_cr4, which
+        * is in force while we are in guest mode.  Do not let guests control
+        * this bit, even if host CR4.MCE == 0.
+        */
+       unsigned long hw_cr4 =
+               (cr4_read_shadow() & X86_CR4_MCE) |
+               (cr4 & ~X86_CR4_MCE) |
+               (to_vmx(vcpu)->rmode.vm86_active ?
+                KVM_RMODE_VM_CR4_ALWAYS_ON : KVM_PMODE_VM_CR4_ALWAYS_ON);
 
        if (cr4 & X86_CR4_VMXE) {
                /*
index e1a81267f3f632e971d1fc63cfe687be2e7c60f3..c73efcd03e294a2e5bc2ef276dc7fa4a6e9d837f 100644 (file)
@@ -1669,12 +1669,28 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
                &guest_hv_clock, sizeof(guest_hv_clock))))
                return 0;
 
-       /*
-        * The interface expects us to write an even number signaling that the
-        * update is finished. Since the guest won't see the intermediate
-        * state, we just increase by 2 at the end.
+       /* This VCPU is paused, but it's legal for a guest to read another
+        * VCPU's kvmclock, so we really have to follow the specification where
+        * it says that version is odd if data is being modified, and even after
+        * it is consistent.
+        *
+        * Version field updates must be kept separate.  This is because
+        * kvm_write_guest_cached might use a "rep movs" instruction, and
+        * writes within a string instruction are weakly ordered.  So there
+        * are three writes overall.
+        *
+        * As a small optimization, only write the version field in the first
+        * and third write.  The vcpu->pv_time cache is still valid, because the
+        * version field is the first in the struct.
         */
-       vcpu->hv_clock.version = guest_hv_clock.version + 2;
+       BUILD_BUG_ON(offsetof(struct pvclock_vcpu_time_info, version) != 0);
+
+       vcpu->hv_clock.version = guest_hv_clock.version + 1;
+       kvm_write_guest_cached(v->kvm, &vcpu->pv_time,
+                               &vcpu->hv_clock,
+                               sizeof(vcpu->hv_clock.version));
+
+       smp_wmb();
 
        /* retain PVCLOCK_GUEST_STOPPED if set in guest copy */
        pvclock_flags = (guest_hv_clock.flags & PVCLOCK_GUEST_STOPPED);
@@ -1695,6 +1711,13 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
        kvm_write_guest_cached(v->kvm, &vcpu->pv_time,
                                &vcpu->hv_clock,
                                sizeof(vcpu->hv_clock));
+
+       smp_wmb();
+
+       vcpu->hv_clock.version++;
+       kvm_write_guest_cached(v->kvm, &vcpu->pv_time,
+                               &vcpu->hv_clock,
+                               sizeof(vcpu->hv_clock.version));
        return 0;
 }
 
@@ -5799,7 +5822,6 @@ int kvm_arch_init(void *opaque)
        kvm_set_mmio_spte_mask();
 
        kvm_x86_ops = ops;
-       kvm_init_msr_list();
 
        kvm_mmu_set_mask_ptes(PT_USER_MASK, PT_ACCESSED_MASK,
                        PT_DIRTY_MASK, PT64_NX_MASK, 0);
@@ -7253,7 +7275,14 @@ void kvm_arch_hardware_disable(void)
 
 int kvm_arch_hardware_setup(void)
 {
-       return kvm_x86_ops->hardware_setup();
+       int r;
+
+       r = kvm_x86_ops->hardware_setup();
+       if (r != 0)
+               return r;
+
+       kvm_init_msr_list();
+       return 0;
 }
 
 void kvm_arch_hardware_unsetup(void)
index 717908b16037d45957a0ec69b94c8c7d396bfaa6..cab9aaa7802c8e8ca729567f1a97cf9080458884 100644 (file)
 
 struct lguest_data lguest_data = {
        .hcall_status = { [0 ... LHCALL_RING_SIZE-1] = 0xFF },
-       .noirq_start = (u32)lguest_noirq_start,
-       .noirq_end = (u32)lguest_noirq_end,
+       .noirq_iret = (u32)lguest_noirq_iret,
        .kernel_address = PAGE_OFFSET,
        .blocked_interrupts = { 1 }, /* Block timer interrupts */
-       .syscall_vec = SYSCALL_VECTOR,
+       .syscall_vec = IA32_SYSCALL_VECTOR,
 };
 
 /*G:037
@@ -262,7 +261,7 @@ PV_CALLEE_SAVE_REGS_THUNK(lguest_save_fl);
 PV_CALLEE_SAVE_REGS_THUNK(lguest_irq_disable);
 /*:*/
 
-/* These are in i386_head.S */
+/* These are in head_32.S */
 extern void lg_irq_enable(void);
 extern void lg_restore_fl(unsigned long flags);
 
@@ -867,7 +866,7 @@ static void __init lguest_init_IRQ(void)
        for (i = FIRST_EXTERNAL_VECTOR; i < FIRST_SYSTEM_VECTOR; i++) {
                /* Some systems map "vectors" to interrupts weirdly.  Not us! */
                __this_cpu_write(vector_irq[i], i - FIRST_EXTERNAL_VECTOR);
-               if (i != SYSCALL_VECTOR)
+               if (i != IA32_SYSCALL_VECTOR)
                        set_intr_gate(i, irq_entries_start +
                                        8 * (i - FIRST_EXTERNAL_VECTOR));
        }
@@ -1368,7 +1367,7 @@ static void lguest_restart(char *reason)
  * fit comfortably.
  *
  * First we need assembly templates of each of the patchable Guest operations,
- * and these are in i386_head.S.
+ * and these are in head_32.S.
  */
 
 /*G:060 We construct a table from the assembler templates: */
index 6ddfe4fc23c3eefbfe4bb10f726ce27bc51a2fba..d5ae63f5ec5d8d8836a4391c29cca8ecc9742c9e 100644 (file)
@@ -84,7 +84,7 @@ ENTRY(lg_irq_enable)
         * set lguest_data.irq_pending to X86_EFLAGS_IF.  If it's not zero, we
         * jump to send_interrupts, otherwise we're done.
         */
-       testl $0, lguest_data+LGUEST_DATA_irq_pending
+       cmpl $0, lguest_data+LGUEST_DATA_irq_pending
        jnz send_interrupts
        /*
         * One cool thing about x86 is that you can do many things without using
@@ -133,9 +133,8 @@ ENTRY(lg_restore_fl)
        ret
 /*:*/
 
-/* These demark the EIP range where host should never deliver interrupts. */
-.global lguest_noirq_start
-.global lguest_noirq_end
+/* These demark the EIP where host should never deliver interrupts. */
+.global lguest_noirq_iret
 
 /*M:004
  * When the Host reflects a trap or injects an interrupt into the Guest, it
@@ -168,29 +167,26 @@ ENTRY(lg_restore_fl)
  * So we have to copy eflags from the stack to lguest_data.irq_enabled before
  * we do the "iret".
  *
- * There are two problems with this: firstly, we need to use a register to do
- * the copy and secondly, the whole thing needs to be atomic.  The first
- * problem is easy to solve: push %eax on the stack so we can use it, and then
- * restore it at the end just before the real "iret".
+ * There are two problems with this: firstly, we can't clobber any registers
+ * and secondly, the whole thing needs to be atomic.  The first problem
+ * is solved by using "push memory"/"pop memory" instruction pair for copying.
  *
  * The second is harder: copying eflags to lguest_data.irq_enabled will turn
  * interrupts on before we're finished, so we could be interrupted before we
- * return to userspace or wherever.  Our solution to this is to surround the
- * code with lguest_noirq_start: and lguest_noirq_end: labels.  We tell the
+ * return to userspace or wherever.  Our solution to this is to tell the
  * Host that it is *never* to interrupt us there, even if interrupts seem to be
- * enabled.
+ * enabled. (It's not necessary to protect pop instruction, since
+ * data gets updated only after it completes, so we only need to protect
+ * one instruction, iret).
  */
 ENTRY(lguest_iret)
-       pushl   %eax
-       movl    12(%esp), %eax
-lguest_noirq_start:
+       pushl   2*4(%esp)
        /*
         * Note the %ss: segment prefix here.  Normal data accesses use the
         * "ds" segment, but that will have already been restored for whatever
         * we're returning to (such as userspace): we can't trust it.  The %ss:
         * prefix makes sure we use the stack segment, which is still valid.
         */
-       movl    %eax,%ss:lguest_data+LGUEST_DATA_irq_enabled
-       popl    %eax
+       popl    %ss:lguest_data+LGUEST_DATA_irq_enabled
+lguest_noirq_iret:
        iret
-lguest_noirq_end:
index 1f33b3d1fd68239c9bb07840d287bcee5d2d26b8..0a42327a59d71e5e2d607623ba209a69d37c6f8d 100644 (file)
@@ -82,7 +82,7 @@ copy_user_handle_tail(char *to, char *from, unsigned len)
        clac();
 
        /* If the destination is a kernel buffer, we always clear the end */
-       if ((unsigned long)to >= TASK_SIZE_MAX)
+       if (!__addr_ok(to))
                memset(to, 0, len);
        return len;
 }
index 5ead4d6cf3a7ae4173265924246415b8fa12d520..70e7444c68351641828b834fd9a9a4fc9cea3b65 100644 (file)
@@ -351,18 +351,20 @@ int arch_ioremap_pmd_supported(void)
  */
 void *xlate_dev_mem_ptr(phys_addr_t phys)
 {
-       void *addr;
-       unsigned long start = phys & PAGE_MASK;
+       unsigned long start  = phys &  PAGE_MASK;
+       unsigned long offset = phys & ~PAGE_MASK;
+       unsigned long vaddr;
 
        /* If page is RAM, we can use __va. Otherwise ioremap and unmap. */
        if (page_is_ram(start >> PAGE_SHIFT))
                return __va(phys);
 
-       addr = (void __force *)ioremap_cache(start, PAGE_SIZE);
-       if (addr)
-               addr = (void *)((unsigned long)addr | (phys & ~PAGE_MASK));
+       vaddr = (unsigned long)ioremap_cache(start, PAGE_SIZE);
+       /* Only add the offset on success and return NULL if the ioremap() failed: */
+       if (vaddr)
+               vaddr += offset;
 
-       return addr;
+       return (void *)vaddr;
 }
 
 void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)
index e4695985f9de85778db5e084b37eda5719d3a82a..d93963340c3c0d958385ce4ec8aadcdfe225a174 100644 (file)
@@ -325,6 +325,26 @@ static void release_pci_root_info(struct pci_host_bridge *bridge)
        kfree(info);
 }
 
+/*
+ * An IO port or MMIO resource assigned to a PCI host bridge may be
+ * consumed by the host bridge itself or available to its child
+ * bus/devices. The ACPI specification defines a bit (Producer/Consumer)
+ * to tell whether the resource is consumed by the host bridge itself,
+ * but firmware hasn't used that bit consistently, so we can't rely on it.
+ *
+ * On x86 and IA64 platforms, all IO port and MMIO resources are assumed
+ * to be available to child bus/devices except one special case:
+ *     IO port [0xCF8-0xCFF] is consumed by the host bridge itself
+ *     to access PCI configuration space.
+ *
+ * So explicitly filter out PCI CFG IO ports[0xCF8-0xCFF].
+ */
+static bool resource_is_pcicfg_ioport(struct resource *res)
+{
+       return (res->flags & IORESOURCE_IO) &&
+               res->start == 0xCF8 && res->end == 0xCFF;
+}
+
 static void probe_pci_root_info(struct pci_root_info *info,
                                struct acpi_device *device,
                                int busnum, int domain,
@@ -346,8 +366,8 @@ static void probe_pci_root_info(struct pci_root_info *info,
                        "no IO and memory resources present in _CRS\n");
        else
                resource_list_for_each_entry_safe(entry, tmp, list) {
-                       if ((entry->res->flags & IORESOURCE_WINDOW) == 0 ||
-                           (entry->res->flags & IORESOURCE_DISABLED))
+                       if ((entry->res->flags & IORESOURCE_DISABLED) ||
+                           resource_is_pcicfg_ioport(entry->res))
                                resource_list_destroy_entry(entry);
                        else
                                entry->res->name = info->name;
index 0a8ee703b9fae9cbfd2205376650563bf7b9eecb..0ce1b1913673fa9ea259013471955c1f994d829c 100644 (file)
@@ -1,5 +1,4 @@
 obj-$(CONFIG_X86_INTEL_MID) += intel-mid.o intel_mid_vrtc.o mfld.o mrfl.o
-obj-$(CONFIG_EARLY_PRINTK_INTEL_MID) += early_printk_intel_mid.o
 
 # SFI specific code
 ifdef CONFIG_X86_INTEL_MID
diff --git a/arch/x86/platform/intel-mid/early_printk_intel_mid.c b/arch/x86/platform/intel-mid/early_printk_intel_mid.c
deleted file mode 100644 (file)
index 4e72082..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * early_printk_intel_mid.c - early consoles for Intel MID platforms
- *
- * Copyright (c) 2008-2010, 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; version 2
- * of the License.
- */
-
-/*
- * This file implements early console named hsu.
- * hsu is based on a High Speed UART device which only exists in the Medfield
- * platform
- */
-
-#include <linux/serial_reg.h>
-#include <linux/serial_mfd.h>
-#include <linux/console.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-
-#include <asm/fixmap.h>
-#include <asm/pgtable.h>
-#include <asm/intel-mid.h>
-
-/*
- * Following is the early console based on Medfield HSU (High
- * Speed UART) device.
- */
-#define HSU_PORT_BASE          0xffa28080
-
-static void __iomem *phsu;
-
-void hsu_early_console_init(const char *s)
-{
-       unsigned long paddr, port = 0;
-       u8 lcr;
-
-       /*
-        * Select the early HSU console port if specified by user in the
-        * kernel command line.
-        */
-       if (*s && !kstrtoul(s, 10, &port))
-               port = clamp_val(port, 0, 2);
-
-       paddr = HSU_PORT_BASE + port * 0x80;
-       phsu = (void __iomem *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE, paddr);
-
-       /* Disable FIFO */
-       writeb(0x0, phsu + UART_FCR);
-
-       /* Set to default 115200 bps, 8n1 */
-       lcr = readb(phsu + UART_LCR);
-       writeb((0x80 | lcr), phsu + UART_LCR);
-       writeb(0x18, phsu + UART_DLL);
-       writeb(lcr,  phsu + UART_LCR);
-       writel(0x3600, phsu + UART_MUL*4);
-
-       writeb(0x8, phsu + UART_MCR);
-       writeb(0x7, phsu + UART_FCR);
-       writeb(0x3, phsu + UART_LCR);
-
-       /* Clear IRQ status */
-       readb(phsu + UART_LSR);
-       readb(phsu + UART_RX);
-       readb(phsu + UART_IIR);
-       readb(phsu + UART_MSR);
-
-       /* Enable FIFO */
-       writeb(0x7, phsu + UART_FCR);
-}
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-static void early_hsu_putc(char ch)
-{
-       unsigned int timeout = 10000; /* 10ms */
-       u8 status;
-
-       while (--timeout) {
-               status = readb(phsu + UART_LSR);
-               if (status & BOTH_EMPTY)
-                       break;
-               udelay(1);
-       }
-
-       /* Only write the char when there was no timeout */
-       if (timeout)
-               writeb(ch, phsu + UART_TX);
-}
-
-static void early_hsu_write(struct console *con, const char *str, unsigned n)
-{
-       int i;
-
-       for (i = 0; i < n && *str; i++) {
-               if (*str == '\n')
-                       early_hsu_putc('\r');
-               early_hsu_putc(*str);
-               str++;
-       }
-}
-
-struct console early_hsu_console = {
-       .name =         "earlyhsu",
-       .write =        early_hsu_write,
-       .flags =        CON_PRINTBUFFER,
-       .index =        -1,
-};
index 3c4469a7a929c7fa3488707a25829cdc6fcc6411..e2386cb4e0c315f32fae03afd13045c4047eb902 100644 (file)
@@ -78,9 +78,9 @@ ENTRY(restore_image)
 
        /* code below has been relocated to a safe page */
 ENTRY(core_restore_code)
-loop:
+.Lloop:
        testq   %rdx, %rdx
-       jz      done
+       jz      .Ldone
 
        /* get addresses from the pbe and copy the page */
        movq    pbe_address(%rdx), %rsi
@@ -91,8 +91,8 @@ loop:
 
        /* progress to the next pbe */
        movq    pbe_next(%rdx), %rdx
-       jmp     loop
-done:
+       jmp     .Lloop
+.Ldone:
        /* jump to the restore_registers address from the image header */
        jmpq    *%rax
        /*
index 40d2473836c923acc5705018bf3aebf50cfb12b8..9793322751e02f63ddba0d1b8fef5f21b0a4d502 100644 (file)
@@ -82,15 +82,18 @@ static notrace cycle_t vread_pvclock(int *mode)
        cycle_t ret;
        u64 last;
        u32 version;
-       u32 migrate_count;
        u8 flags;
        unsigned cpu, cpu1;
 
 
        /*
-        * When looping to get a consistent (time-info, tsc) pair, we
-        * also need to deal with the possibility we can switch vcpus,
-        * so make sure we always re-fetch time-info for the current vcpu.
+        * Note: hypervisor must guarantee that:
+        * 1. cpu ID number maps 1:1 to per-CPU pvclock time info.
+        * 2. that per-CPU pvclock time info is updated if the
+        *    underlying CPU changes.
+        * 3. that version is increased whenever underlying CPU
+        *    changes.
+        *
         */
        do {
                cpu = __getcpu() & VGETCPU_CPU_MASK;
@@ -99,27 +102,20 @@ static notrace cycle_t vread_pvclock(int *mode)
                 * __getcpu() calls (Gleb).
                 */
 
-               /* Make sure migrate_count will change if we leave the VCPU. */
-               do {
-                       pvti = get_pvti(cpu);
-                       migrate_count = pvti->migrate_count;
-
-                       cpu1 = cpu;
-                       cpu = __getcpu() & VGETCPU_CPU_MASK;
-               } while (unlikely(cpu != cpu1));
+               pvti = get_pvti(cpu);
 
                version = __pvclock_read_cycles(&pvti->pvti, &ret, &flags);
 
                /*
                 * Test we're still on the cpu as well as the version.
-                * - We must read TSC of pvti's VCPU.
-                * - KVM doesn't follow the versioning protocol, so data could
-                *   change before version if we left the VCPU.
+                * We could have been migrated just after the first
+                * vgetcpu but before fetching the version, so we
+                * wouldn't notice a version change.
                 */
-               smp_rmb();
-       } while (unlikely((pvti->pvti.version & 1) ||
-                         pvti->pvti.version != version ||
-                         pvti->migrate_count != migrate_count));
+               cpu1 = __getcpu() & VGETCPU_CPU_MASK;
+       } while (unlikely(cpu != cpu1 ||
+                         (pvti->pvti.version & 1) ||
+                         pvti->pvti.version != version));
 
        if (unlikely(!(flags & PVCLOCK_TSC_STABLE_BIT)))
                *mode = VCLOCK_NONE;
index 94578efd3067f0a0fd86c36c5b3be07eced3d509..fe969ac1c65e771f62ee432b922bb7f6300fea0a 100644 (file)
@@ -1181,10 +1181,11 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = {
        .read_tscp = native_read_tscp,
 
        .iret = xen_iret,
-       .irq_enable_sysexit = xen_sysexit,
 #ifdef CONFIG_X86_64
        .usergs_sysret32 = xen_sysret32,
        .usergs_sysret64 = xen_sysret64,
+#else
+       .irq_enable_sysexit = xen_sysexit,
 #endif
 
        .load_tr_desc = paravirt_nop,
@@ -1760,6 +1761,9 @@ static struct notifier_block xen_hvm_cpu_notifier = {
 
 static void __init xen_hvm_guest_init(void)
 {
+       if (xen_pv_domain())
+               return;
+
        init_hvm_pv_info();
 
        xen_hvm_init_shared_info();
@@ -1775,6 +1779,7 @@ static void __init xen_hvm_guest_init(void)
        xen_hvm_init_time_ops();
        xen_hvm_init_mmu_ops();
 }
+#endif
 
 static bool xen_nopv = false;
 static __init int xen_parse_nopv(char *arg)
@@ -1784,14 +1789,11 @@ static __init int xen_parse_nopv(char *arg)
 }
 early_param("xen_nopv", xen_parse_nopv);
 
-static uint32_t __init xen_hvm_platform(void)
+static uint32_t __init xen_platform(void)
 {
        if (xen_nopv)
                return 0;
 
-       if (xen_pv_domain())
-               return 0;
-
        return xen_cpuid_base();
 }
 
@@ -1809,11 +1811,19 @@ bool xen_hvm_need_lapic(void)
 }
 EXPORT_SYMBOL_GPL(xen_hvm_need_lapic);
 
-const struct hypervisor_x86 x86_hyper_xen_hvm __refconst = {
-       .name                   = "Xen HVM",
-       .detect                 = xen_hvm_platform,
+static void xen_set_cpu_features(struct cpuinfo_x86 *c)
+{
+       if (xen_pv_domain())
+               clear_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS);
+}
+
+const struct hypervisor_x86 x86_hyper_xen = {
+       .name                   = "Xen",
+       .detect                 = xen_platform,
+#ifdef CONFIG_XEN_PVHVM
        .init_platform          = xen_hvm_guest_init,
+#endif
        .x2apic_available       = xen_x2apic_para_available,
+       .set_cpu_features       = xen_set_cpu_features,
 };
-EXPORT_SYMBOL(x86_hyper_xen_hvm);
-#endif
+EXPORT_SYMBOL(x86_hyper_xen);
index d9497698645a53b10ab4b62ddc98d12f4412a616..53b4c0811f4f64a72d286fcaa2a9cab9749bacc2 100644 (file)
@@ -88,7 +88,17 @@ static void xen_vcpu_notify_restore(void *data)
        tick_resume_local();
 }
 
+static void xen_vcpu_notify_suspend(void *data)
+{
+       tick_suspend_local();
+}
+
 void xen_arch_resume(void)
 {
        on_each_cpu(xen_vcpu_notify_restore, NULL, 1);
 }
+
+void xen_arch_suspend(void)
+{
+       on_each_cpu(xen_vcpu_notify_suspend, NULL, 1);
+}
index 985fc3ee0973c85f916c67cd9a40fc9c2c73d340..04529e620559fabdb6b4878168ded883055c17f2 100644 (file)
@@ -15,6 +15,8 @@
 #include <asm/percpu.h>
 #include <asm/processor-flags.h>
 #include <asm/segment.h>
+#include <asm/asm-offsets.h>
+#include <asm/thread_info.h>
 
 #include <xen/interface/xen.h>
 
@@ -47,29 +49,13 @@ ENTRY(xen_iret)
 ENDPATCH(xen_iret)
 RELOC(xen_iret, 1b+1)
 
-/*
- * sysexit is not used for 64-bit processes, so it's only ever used to
- * return to 32-bit compat userspace.
- */
-ENTRY(xen_sysexit)
-       pushq $__USER32_DS
-       pushq %rcx
-       pushq $X86_EFLAGS_IF
-       pushq $__USER32_CS
-       pushq %rdx
-
-       pushq $0
-1:     jmp hypercall_iret
-ENDPATCH(xen_sysexit)
-RELOC(xen_sysexit, 1b+1)
-
 ENTRY(xen_sysret64)
        /*
         * We're already on the usermode stack at this point, but
         * still with the kernel gs, so we can easily switch back
         */
        movq %rsp, PER_CPU_VAR(rsp_scratch)
-       movq PER_CPU_VAR(kernel_stack), %rsp
+       movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
 
        pushq $__USER_DS
        pushq PER_CPU_VAR(rsp_scratch)
@@ -88,7 +74,7 @@ ENTRY(xen_sysret32)
         * still with the kernel gs, so we can easily switch back
         */
        movq %rsp, PER_CPU_VAR(rsp_scratch)
-       movq PER_CPU_VAR(kernel_stack), %rsp
+       movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
 
        pushq $__USER32_DS
        pushq PER_CPU_VAR(rsp_scratch)
index 9e195c683549dc138d77e98687c34f62b40eda76..c20fe29e65f48b4706789e0ad59bb33b1a3acc18 100644 (file)
@@ -134,7 +134,9 @@ DECL_ASM(void, xen_restore_fl_direct, unsigned long);
 
 /* These are not functions, and cannot be called normally */
 __visible void xen_iret(void);
+#ifdef CONFIG_X86_32
 __visible void xen_sysexit(void);
+#endif
 __visible void xen_sysret32(void);
 __visible void xen_sysret64(void);
 __visible void xen_adjust_exception_frame(void);
index d05327caf69dbc18532478b122ea9834e67f1fd9..5d355e0c263339b5bd179ad61aad63c9b7efb3a3 100644 (file)
@@ -124,6 +124,7 @@ do_sync_gen_syndrome(struct page **blocks, unsigned int offset, int disks,
 {
        void **srcs;
        int i;
+       int start = -1, stop = disks - 3;
 
        if (submit->scribble)
                srcs = submit->scribble;
@@ -134,10 +135,21 @@ do_sync_gen_syndrome(struct page **blocks, unsigned int offset, int disks,
                if (blocks[i] == NULL) {
                        BUG_ON(i > disks - 3); /* P or Q can't be zero */
                        srcs[i] = (void*)raid6_empty_zero_page;
-               } else
+               } else {
                        srcs[i] = page_address(blocks[i]) + offset;
+                       if (i < disks - 2) {
+                               stop = i;
+                               if (start == -1)
+                                       start = i;
+                       }
+               }
        }
-       raid6_call.gen_syndrome(disks, len, srcs);
+       if (submit->flags & ASYNC_TX_PQ_XOR_DST) {
+               BUG_ON(!raid6_call.xor_syndrome);
+               if (start >= 0)
+                       raid6_call.xor_syndrome(disks, start, stop, len, srcs);
+       } else
+               raid6_call.gen_syndrome(disks, len, srcs);
        async_tx_sync_epilog(submit);
 }
 
@@ -178,7 +190,8 @@ async_gen_syndrome(struct page **blocks, unsigned int offset, int disks,
        if (device)
                unmap = dmaengine_get_unmap_data(device->dev, disks, GFP_NOIO);
 
-       if (unmap &&
+       /* XORing P/Q is only implemented in software */
+       if (unmap && !(submit->flags & ASYNC_TX_PQ_XOR_DST) &&
            (src_cnt <= dma_maxpq(device, 0) ||
             dma_maxpq(device, DMA_PREP_CONTINUE) > 0) &&
            is_dma_pq_aligned(device, offset, 0, len)) {
index 527a6da8d539ad2abb84c5397e0087c1914501af..46d2554be40459060ae8ab3e7bba1b21a453c7d0 100644 (file)
@@ -163,5 +163,5 @@ obj-$(CONFIG_POWERCAP)              += powercap/
 obj-$(CONFIG_MCB)              += mcb/
 obj-$(CONFIG_RAS)              += ras/
 obj-$(CONFIG_THUNDERBOLT)      += thunderbolt/
-obj-$(CONFIG_CORESIGHT)                += coresight/
+obj-$(CONFIG_CORESIGHT)                += hwtracing/coresight/
 obj-$(CONFIG_ANDROID)          += android/
index e6c3ddd926658cd615241328e1f51b90ce16c611..ab2cbb51c6aaccde0ec2f97af343383c6f360dff 100644 (file)
@@ -5,7 +5,7 @@
 menuconfig ACPI
        bool "ACPI (Advanced Configuration and Power Interface) Support"
        depends on !IA64_HP_SIM
-       depends on IA64 || X86
+       depends on IA64 || X86 || (ARM64 && EXPERT)
        depends on PCI
        select PNP
        default y
@@ -48,9 +48,16 @@ config ACPI_LEGACY_TABLES_LOOKUP
 config ARCH_MIGHT_HAVE_ACPI_PDC
        bool
 
+config ACPI_GENERIC_GSI
+       bool
+
+config ACPI_SYSTEM_POWER_STATES_SUPPORT
+       bool
+
 config ACPI_SLEEP
        bool
        depends on SUSPEND || HIBERNATION
+       depends on ACPI_SYSTEM_POWER_STATES_SUPPORT
        default y
 
 config ACPI_PROCFS_POWER
@@ -163,6 +170,7 @@ config ACPI_PROCESSOR
        tristate "Processor"
        select THERMAL
        select CPU_IDLE
+       depends on X86 || IA64
        default y
        help
          This driver installs ACPI as the idle handler for Linux and uses
index 623b117ad1a23ee09ac7aca1ca5d028b51ec2738..8a063e276530e244b4020a1e6a6ef6ebec60920e 100644 (file)
@@ -23,7 +23,7 @@ acpi-y                                += nvs.o
 
 # Power management related files
 acpi-y                         += wakeup.o
-acpi-y                         += sleep.o
+acpi-$(CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT) += sleep.o
 acpi-y                         += device_pm.o
 acpi-$(CONFIG_ACPI_SLEEP)      += proc.o
 
@@ -56,6 +56,7 @@ ifdef CONFIG_ACPI_VIDEO
 acpi-y                         += video_detect.o
 endif
 acpi-y                         += acpi_lpat.o
+acpi-$(CONFIG_ACPI_GENERIC_GSI) += gsi.o
 
 # These are (potentially) separate modules
 
index b193f842599902445015a219687310cdf3bfe9c9..ff6d8adc9cda69c4d0d1f9a22ff3481846020cbd 100644 (file)
@@ -304,6 +304,8 @@ static const struct acpi_device_id acpi_pnp_device_ids[] = {
        {"PNPb006"},
        /* cs423x-pnpbios */
        {"CSC0100"},
+       {"CSC0103"},
+       {"CSC0110"},
        {"CSC0000"},
        {"GIM0100"},            /* Guillemot Turtlebeach something appears to be cs4232 compatible */
        /* es18xx-pnpbios */
index 1020b1b53a174e58111056e2c3e88089d0180d83..58f335ca2e75f9cc3ca47eb7ef2140fb010ee7e4 100644 (file)
@@ -170,7 +170,7 @@ static int acpi_processor_hotadd_init(struct acpi_processor *pr)
        acpi_status status;
        int ret;
 
-       if (pr->phys_id == -1)
+       if (pr->phys_id == PHYS_CPUID_INVALID)
                return -ENODEV;
 
        status = acpi_evaluate_integer(pr->handle, "_STA", NULL, &sta);
@@ -215,7 +215,8 @@ static int acpi_processor_get_info(struct acpi_device *device)
        union acpi_object object = { 0 };
        struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
        struct acpi_processor *pr = acpi_driver_data(device);
-       int phys_id, cpu_index, device_declaration = 0;
+       phys_cpuid_t phys_id;
+       int cpu_index, device_declaration = 0;
        acpi_status status = AE_OK;
        static int cpu0_initialized;
        unsigned long long value;
@@ -263,7 +264,7 @@ static int acpi_processor_get_info(struct acpi_device *device)
        }
 
        phys_id = acpi_get_phys_id(pr->handle, device_declaration, pr->acpi_id);
-       if (phys_id < 0)
+       if (phys_id == PHYS_CPUID_INVALID)
                acpi_handle_debug(pr->handle, "failed to get CPU physical ID.\n");
        pr->phys_id = phys_id;
 
index 8b67bd0f6bb5e629d77de4b18490c0f64e329ad6..c412fdb28d34430913fa2080af6e68619050c107 100644 (file)
@@ -448,6 +448,9 @@ static int __init acpi_bus_init_irq(void)
        case ACPI_IRQ_MODEL_IOSAPIC:
                message = "IOSAPIC";
                break;
+       case ACPI_IRQ_MODEL_GIC:
+               message = "GIC";
+               break;
        case ACPI_IRQ_MODEL_PLATFORM:
                message = "platform specific model";
                break;
index 220d6406c9e93cbd7ed269fca5adbd94e3303152..5e8fed448850fc1c8f50448f6b344066d2e730ef 100644 (file)
@@ -861,7 +861,7 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
                }
        }
        mutex_unlock(&ec->mutex);
-       list_for_each_entry(handler, &free_list, node)
+       list_for_each_entry_safe(handler, tmp, &free_list, node)
                acpi_ec_put_query_handler(handler);
 }
 EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
diff --git a/drivers/acpi/gsi.c b/drivers/acpi/gsi.c
new file mode 100644 (file)
index 0000000..38208f2
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * ACPI GSI IRQ layer
+ *
+ * Copyright (C) 2015 ARM Ltd.
+ * Author: Lorenzo Pieralisi <lorenzo.pieralisi@arm.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/acpi.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+
+enum acpi_irq_model_id acpi_irq_model;
+
+static unsigned int acpi_gsi_get_irq_type(int trigger, int polarity)
+{
+       switch (polarity) {
+       case ACPI_ACTIVE_LOW:
+               return trigger == ACPI_EDGE_SENSITIVE ?
+                      IRQ_TYPE_EDGE_FALLING :
+                      IRQ_TYPE_LEVEL_LOW;
+       case ACPI_ACTIVE_HIGH:
+               return trigger == ACPI_EDGE_SENSITIVE ?
+                      IRQ_TYPE_EDGE_RISING :
+                      IRQ_TYPE_LEVEL_HIGH;
+       case ACPI_ACTIVE_BOTH:
+               if (trigger == ACPI_EDGE_SENSITIVE)
+                       return IRQ_TYPE_EDGE_BOTH;
+       default:
+               return IRQ_TYPE_NONE;
+       }
+}
+
+/**
+ * acpi_gsi_to_irq() - Retrieve the linux irq number for a given GSI
+ * @gsi: GSI IRQ number to map
+ * @irq: pointer where linux IRQ number is stored
+ *
+ * irq location updated with irq value [>0 on success, 0 on failure]
+ *
+ * Returns: linux IRQ number on success (>0)
+ *          -EINVAL on failure
+ */
+int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
+{
+       /*
+        * Only default domain is supported at present, always find
+        * the mapping corresponding to default domain by passing NULL
+        * as irq_domain parameter
+        */
+       *irq = irq_find_mapping(NULL, gsi);
+       /*
+        * *irq == 0 means no mapping, that should
+        * be reported as a failure
+        */
+       return (*irq > 0) ? *irq : -EINVAL;
+}
+EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
+
+/**
+ * acpi_register_gsi() - Map a GSI to a linux IRQ number
+ * @dev: device for which IRQ has to be mapped
+ * @gsi: GSI IRQ number
+ * @trigger: trigger type of the GSI number to be mapped
+ * @polarity: polarity of the GSI to be mapped
+ *
+ * Returns: a valid linux IRQ number on success
+ *          -EINVAL on failure
+ */
+int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
+                     int polarity)
+{
+       unsigned int irq;
+       unsigned int irq_type = acpi_gsi_get_irq_type(trigger, polarity);
+
+       /*
+        * There is no way at present to look-up the IRQ domain on ACPI,
+        * hence always create mapping referring to the default domain
+        * by passing NULL as irq_domain parameter
+        */
+       irq = irq_create_mapping(NULL, gsi);
+       if (!irq)
+               return -EINVAL;
+
+       /* Set irq type if specified and different than the current one */
+       if (irq_type != IRQ_TYPE_NONE &&
+               irq_type != irq_get_trigger_type(irq))
+               irq_set_irq_type(irq, irq_type);
+       return irq;
+}
+EXPORT_SYMBOL_GPL(acpi_register_gsi);
+
+/**
+ * acpi_unregister_gsi() - Free a GSI<->linux IRQ number mapping
+ * @gsi: GSI IRQ number
+ */
+void acpi_unregister_gsi(u32 gsi)
+{
+       int irq = irq_find_mapping(NULL, gsi);
+
+       irq_dispose_mapping(irq);
+}
+EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
index 56b321aa2b1c8a3b4395623ead294bc967702cf8..ba4a61e964be4d1d2abdb59bfab85a25aa3048c4 100644 (file)
@@ -161,7 +161,11 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit);
 /*--------------------------------------------------------------------------
                                   Suspend/Resume
   -------------------------------------------------------------------------- */
+#ifdef CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT
 extern int acpi_sleep_init(void);
+#else
+static inline int acpi_sleep_init(void) { return -ENXIO; }
+#endif
 
 #ifdef CONFIG_ACPI_SLEEP
 int acpi_sleep_proc_init(void);
index f9eeae87159338d41c22235f274499db3750d66b..39748bb3a5430111b8cf4723462eb837137b0213 100644 (file)
@@ -336,11 +336,11 @@ acpi_map_lookup_virt(void __iomem *virt, acpi_size size)
        return NULL;
 }
 
-#ifndef CONFIG_IA64
-#define should_use_kmap(pfn)   page_is_ram(pfn)
-#else
+#if defined(CONFIG_IA64) || defined(CONFIG_ARM64)
 /* ioremap will take care of cache attributes */
 #define should_use_kmap(pfn)   0
+#else
+#define should_use_kmap(pfn)   page_is_ram(pfn)
 #endif
 
 static void __iomem *acpi_map(acpi_physical_address pg_off, unsigned long pg_sz)
index 7962651cdbd43a6a7b7e22e75263f90c9567dc80..b1ec78b8a6455c68f08af8123a529e5513475b03 100644 (file)
@@ -32,7 +32,7 @@ static struct acpi_table_madt *get_madt_table(void)
 }
 
 static int map_lapic_id(struct acpi_subtable_header *entry,
-                u32 acpi_id, int *apic_id)
+                u32 acpi_id, phys_cpuid_t *apic_id)
 {
        struct acpi_madt_local_apic *lapic =
                container_of(entry, struct acpi_madt_local_apic, header);
@@ -48,7 +48,7 @@ static int map_lapic_id(struct acpi_subtable_header *entry,
 }
 
 static int map_x2apic_id(struct acpi_subtable_header *entry,
-                        int device_declaration, u32 acpi_id, int *apic_id)
+               int device_declaration, u32 acpi_id, phys_cpuid_t *apic_id)
 {
        struct acpi_madt_local_x2apic *apic =
                container_of(entry, struct acpi_madt_local_x2apic, header);
@@ -65,7 +65,7 @@ static int map_x2apic_id(struct acpi_subtable_header *entry,
 }
 
 static int map_lsapic_id(struct acpi_subtable_header *entry,
-               int device_declaration, u32 acpi_id, int *apic_id)
+               int device_declaration, u32 acpi_id, phys_cpuid_t *apic_id)
 {
        struct acpi_madt_local_sapic *lsapic =
                container_of(entry, struct acpi_madt_local_sapic, header);
@@ -83,10 +83,35 @@ static int map_lsapic_id(struct acpi_subtable_header *entry,
        return 0;
 }
 
-static int map_madt_entry(int type, u32 acpi_id)
+/*
+ * Retrieve the ARM CPU physical identifier (MPIDR)
+ */
+static int map_gicc_mpidr(struct acpi_subtable_header *entry,
+               int device_declaration, u32 acpi_id, phys_cpuid_t *mpidr)
+{
+       struct acpi_madt_generic_interrupt *gicc =
+           container_of(entry, struct acpi_madt_generic_interrupt, header);
+
+       if (!(gicc->flags & ACPI_MADT_ENABLED))
+               return -ENODEV;
+
+       /* device_declaration means Device object in DSDT, in the
+        * GIC interrupt model, logical processors are required to
+        * have a Processor Device object in the DSDT, so we should
+        * check device_declaration here
+        */
+       if (device_declaration && (gicc->uid == acpi_id)) {
+               *mpidr = gicc->arm_mpidr;
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static phys_cpuid_t map_madt_entry(int type, u32 acpi_id)
 {
        unsigned long madt_end, entry;
-       int phys_id = -1;       /* CPU hardware ID */
+       phys_cpuid_t phys_id = PHYS_CPUID_INVALID;      /* CPU hardware ID */
        struct acpi_table_madt *madt;
 
        madt = get_madt_table();
@@ -111,18 +136,21 @@ static int map_madt_entry(int type, u32 acpi_id)
                } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
                        if (!map_lsapic_id(header, type, acpi_id, &phys_id))
                                break;
+               } else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) {
+                       if (!map_gicc_mpidr(header, type, acpi_id, &phys_id))
+                               break;
                }
                entry += header->length;
        }
        return phys_id;
 }
 
-static int map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
+static phys_cpuid_t map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
 {
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
        union acpi_object *obj;
        struct acpi_subtable_header *header;
-       int phys_id = -1;
+       phys_cpuid_t phys_id = PHYS_CPUID_INVALID;
 
        if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
                goto exit;
@@ -143,33 +171,35 @@ static int map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
                map_lsapic_id(header, type, acpi_id, &phys_id);
        else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC)
                map_x2apic_id(header, type, acpi_id, &phys_id);
+       else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT)
+               map_gicc_mpidr(header, type, acpi_id, &phys_id);
 
 exit:
        kfree(buffer.pointer);
        return phys_id;
 }
 
-int acpi_get_phys_id(acpi_handle handle, int type, u32 acpi_id)
+phys_cpuid_t acpi_get_phys_id(acpi_handle handle, int type, u32 acpi_id)
 {
-       int phys_id;
+       phys_cpuid_t phys_id;
 
        phys_id = map_mat_entry(handle, type, acpi_id);
-       if (phys_id == -1)
+       if (phys_id == PHYS_CPUID_INVALID)
                phys_id = map_madt_entry(type, acpi_id);
 
        return phys_id;
 }
 
-int acpi_map_cpuid(int phys_id, u32 acpi_id)
+int acpi_map_cpuid(phys_cpuid_t phys_id, u32 acpi_id)
 {
 #ifdef CONFIG_SMP
        int i;
 #endif
 
-       if (phys_id == -1) {
+       if (phys_id == PHYS_CPUID_INVALID) {
                /*
                 * On UP processor, there is no _MAT or MADT table.
-                * So above phys_id is always set to -1.
+                * So above phys_id is always set to PHYS_CPUID_INVALID.
                 *
                 * BIOS may define multiple CPU handles even for UP processor.
                 * For example,
@@ -190,7 +220,7 @@ int acpi_map_cpuid(int phys_id, u32 acpi_id)
                if (nr_cpu_ids <= 1 && acpi_id == 0)
                        return acpi_id;
                else
-                       return phys_id;
+                       return -1;
        }
 
 #ifdef CONFIG_SMP
@@ -208,7 +238,7 @@ int acpi_map_cpuid(int phys_id, u32 acpi_id)
 
 int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
 {
-       int phys_id;
+       phys_cpuid_t phys_id;
 
        phys_id = acpi_get_phys_id(handle, type, acpi_id);
 
index 5589a6e2a02346e3b2ce48656b3facea1abfc621..8244f013f21095a9508e80ef01621e0ffbaab106 100644 (file)
@@ -573,7 +573,7 @@ EXPORT_SYMBOL_GPL(acpi_dev_get_resources);
  * @ares: Input ACPI resource object.
  * @types: Valid resource types of IORESOURCE_XXX
  *
- * This is a hepler function to support acpi_dev_get_resources(), which filters
+ * This is a helper function to support acpi_dev_get_resources(), which filters
  * ACPI resource objects according to resource types.
  */
 int acpi_dev_filter_resource_type(struct acpi_resource *ares,
index cd827625cf079207f36a2e2f2b86e00ae649faa4..01504c819e8f6692382a2b8138fb72a40bb50780 100644 (file)
@@ -684,7 +684,7 @@ static int acpi_sbs_add(struct acpi_device *device)
        if (!sbs_manager_broken) {
                result = acpi_manager_get_info(sbs);
                if (!result) {
-                       sbs->manager_present = 0;
+                       sbs->manager_present = 1;
                        for (id = 0; id < MAX_SBS_BAT; ++id)
                                if ((sbs->batteries_supported & (1 << id)))
                                        acpi_battery_add(sbs, id);
index 26e5b50605230e2e34a46d8118486fb1ba2eb939..bf034f8b7c1acde77f90ded7f39f70dbd636b7db 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
+#include <linux/dmi.h>
 #include "sbshc.h"
 
 #define PREFIX "ACPI: "
@@ -87,6 +88,8 @@ enum acpi_smb_offset {
        ACPI_SMB_ALARM_DATA = 0x26,     /* 2 bytes alarm data */
 };
 
+static bool macbook;
+
 static inline int smb_hc_read(struct acpi_smb_hc *hc, u8 address, u8 *data)
 {
        return ec_read(hc->offset + address, data);
@@ -132,6 +135,8 @@ static int acpi_smbus_transaction(struct acpi_smb_hc *hc, u8 protocol,
        }
 
        mutex_lock(&hc->lock);
+       if (macbook)
+               udelay(5);
        if (smb_hc_read(hc, ACPI_SMB_PROTOCOL, &temp))
                goto end;
        if (temp) {
@@ -257,12 +262,29 @@ extern int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
                              acpi_handle handle, acpi_ec_query_func func,
                              void *data);
 
+static int macbook_dmi_match(const struct dmi_system_id *d)
+{
+       pr_debug("Detected MacBook, enabling workaround\n");
+       macbook = true;
+       return 0;
+}
+
+static struct dmi_system_id acpi_smbus_dmi_table[] = {
+       { macbook_dmi_match, "Apple MacBook", {
+         DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
+         DMI_MATCH(DMI_PRODUCT_NAME, "MacBook") },
+       },
+       { },
+};
+
 static int acpi_smbus_hc_add(struct acpi_device *device)
 {
        int status;
        unsigned long long val;
        struct acpi_smb_hc *hc;
 
+       dmi_check_system(acpi_smbus_dmi_table);
+
        if (!device)
                return -EINVAL;
 
index 69bc0d888c012523d03f15267c3ca75a1d4a10e3..03141aa4ea9500bce3a973605ecbf203af96a060 100644 (file)
@@ -375,7 +375,11 @@ bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent)
        struct acpi_device_physical_node *pn;
        bool offline = true;
 
-       mutex_lock(&adev->physical_node_lock);
+       /*
+        * acpi_container_offline() calls this for all of the container's
+        * children under the container's physical_node_lock lock.
+        */
+       mutex_lock_nested(&adev->physical_node_lock, SINGLE_DEPTH_NESTING);
 
        list_for_each_entry(pn, &adev->physical_node_list, node)
                if (device_supports_offline(pn->dev) && !pn->dev->offline) {
@@ -2388,9 +2392,6 @@ static void acpi_default_enumeration(struct acpi_device *device)
        struct list_head resource_list;
        bool is_spi_i2c_slave = false;
 
-       if (!device->pnp.type.platform_id || device->handler)
-               return;
-
        /*
         * Do not enemerate SPI/I2C slaves as they will be enuerated by their
         * respective parents.
@@ -2403,6 +2404,29 @@ static void acpi_default_enumeration(struct acpi_device *device)
                acpi_create_platform_device(device);
 }
 
+static const struct acpi_device_id generic_device_ids[] = {
+       {"PRP0001", },
+       {"", },
+};
+
+static int acpi_generic_device_attach(struct acpi_device *adev,
+                                     const struct acpi_device_id *not_used)
+{
+       /*
+        * Since PRP0001 is the only ID handled here, the test below can be
+        * unconditional.
+        */
+       if (adev->data.of_compatible)
+               acpi_default_enumeration(adev);
+
+       return 1;
+}
+
+static struct acpi_scan_handler generic_device_handler = {
+       .ids = generic_device_ids,
+       .attach = acpi_generic_device_attach,
+};
+
 static int acpi_scan_attach_handler(struct acpi_device *device)
 {
        struct acpi_hardware_id *hwid;
@@ -2428,8 +2452,6 @@ static int acpi_scan_attach_handler(struct acpi_device *device)
                                break;
                }
        }
-       if (!ret)
-               acpi_default_enumeration(device);
 
        return ret;
 }
@@ -2471,6 +2493,9 @@ static void acpi_bus_attach(struct acpi_device *device)
                ret = device_attach(&device->dev);
                if (ret < 0)
                        return;
+
+               if (!ret && device->pnp.type.platform_id)
+                       acpi_default_enumeration(device);
        }
        device->flags.visited = true;
 
@@ -2629,6 +2654,8 @@ int __init acpi_scan_init(void)
        acpi_pnp_init();
        acpi_int340x_thermal_init();
 
+       acpi_scan_add_handler(&generic_device_handler);
+
        mutex_lock(&acpi_scan_lock);
        /*
         * Enumerate devices in the ACPI namespace.
index 93b81523a2fef769bb2892b9586b7ecbd70b3031..2e19189da0ee4f770f98931143dfde1b3bafa4a1 100644 (file)
@@ -23,6 +23,8 @@
  *
  */
 
+/* Uncomment next line to get verbose printout */
+/* #define DEBUG */
 #define pr_fmt(fmt) "ACPI: " fmt
 
 #include <linux/init.h>
@@ -61,9 +63,9 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
                {
                        struct acpi_madt_local_apic *p =
                            (struct acpi_madt_local_apic *)header;
-                       pr_info("LAPIC (acpi_id[0x%02x] lapic_id[0x%02x] %s)\n",
-                               p->processor_id, p->id,
-                               (p->lapic_flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled");
+                       pr_debug("LAPIC (acpi_id[0x%02x] lapic_id[0x%02x] %s)\n",
+                                p->processor_id, p->id,
+                                (p->lapic_flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled");
                }
                break;
 
@@ -71,9 +73,9 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
                {
                        struct acpi_madt_local_x2apic *p =
                            (struct acpi_madt_local_x2apic *)header;
-                       pr_info("X2APIC (apic_id[0x%02x] uid[0x%02x] %s)\n",
-                               p->local_apic_id, p->uid,
-                               (p->lapic_flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled");
+                       pr_debug("X2APIC (apic_id[0x%02x] uid[0x%02x] %s)\n",
+                                p->local_apic_id, p->uid,
+                                (p->lapic_flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled");
                }
                break;
 
@@ -81,8 +83,8 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
                {
                        struct acpi_madt_io_apic *p =
                            (struct acpi_madt_io_apic *)header;
-                       pr_info("IOAPIC (id[0x%02x] address[0x%08x] gsi_base[%d])\n",
-                               p->id, p->address, p->global_irq_base);
+                       pr_debug("IOAPIC (id[0x%02x] address[0x%08x] gsi_base[%d])\n",
+                                p->id, p->address, p->global_irq_base);
                }
                break;
 
@@ -155,9 +157,9 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
                {
                        struct acpi_madt_io_sapic *p =
                            (struct acpi_madt_io_sapic *)header;
-                       pr_info("IOSAPIC (id[0x%x] address[%p] gsi_base[%d])\n",
-                               p->id, (void *)(unsigned long)p->address,
-                               p->global_irq_base);
+                       pr_debug("IOSAPIC (id[0x%x] address[%p] gsi_base[%d])\n",
+                                p->id, (void *)(unsigned long)p->address,
+                                p->global_irq_base);
                }
                break;
 
@@ -165,9 +167,9 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
                {
                        struct acpi_madt_local_sapic *p =
                            (struct acpi_madt_local_sapic *)header;
-                       pr_info("LSAPIC (acpi_id[0x%02x] lsapic_id[0x%02x] lsapic_eid[0x%02x] %s)\n",
-                               p->processor_id, p->id, p->eid,
-                               (p->lapic_flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled");
+                       pr_debug("LSAPIC (acpi_id[0x%02x] lsapic_id[0x%02x] lsapic_eid[0x%02x] %s)\n",
+                                p->processor_id, p->id, p->eid,
+                                (p->lapic_flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled");
                }
                break;
 
@@ -183,6 +185,28 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
                }
                break;
 
+       case ACPI_MADT_TYPE_GENERIC_INTERRUPT:
+               {
+                       struct acpi_madt_generic_interrupt *p =
+                               (struct acpi_madt_generic_interrupt *)header;
+                       pr_debug("GICC (acpi_id[0x%04x] address[%llx] MPIDR[0x%llx] %s)\n",
+                                p->uid, p->base_address,
+                                p->arm_mpidr,
+                                (p->flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled");
+
+               }
+               break;
+
+       case ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR:
+               {
+                       struct acpi_madt_generic_distributor *p =
+                               (struct acpi_madt_generic_distributor *)header;
+                       pr_debug("GIC Distributor (gic_id[0x%04x] address[%llx] gsi_base[%d])\n",
+                                p->gic_id, p->base_address,
+                                p->global_irq_base);
+               }
+               break;
+
        default:
                pr_warn("Found unsupported MADT entry (type = 0x%x)\n",
                        header->type);
index 25798db14553265e899257d8e13e53fc356e81bb..68f03141e432a2c5a03358d59ed541ac9ae79529 100644 (file)
@@ -157,10 +157,10 @@ static int dev_mkdir(const char *name, umode_t mode)
        if (IS_ERR(dentry))
                return PTR_ERR(dentry);
 
-       err = vfs_mkdir(path.dentry->d_inode, dentry, mode);
+       err = vfs_mkdir(d_inode(path.dentry), dentry, mode);
        if (!err)
                /* mark as kernel-created inode */
-               dentry->d_inode->i_private = &thread;
+               d_inode(dentry)->i_private = &thread;
        done_path_create(&path, dentry);
        return err;
 }
@@ -207,7 +207,7 @@ static int handle_create(const char *nodename, umode_t mode, kuid_t uid,
        if (IS_ERR(dentry))
                return PTR_ERR(dentry);
 
-       err = vfs_mknod(path.dentry->d_inode, dentry, mode, dev->devt);
+       err = vfs_mknod(d_inode(path.dentry), dentry, mode, dev->devt);
        if (!err) {
                struct iattr newattrs;
 
@@ -215,12 +215,12 @@ static int handle_create(const char *nodename, umode_t mode, kuid_t uid,
                newattrs.ia_uid = uid;
                newattrs.ia_gid = gid;
                newattrs.ia_valid = ATTR_MODE|ATTR_UID|ATTR_GID;
-               mutex_lock(&dentry->d_inode->i_mutex);
+               mutex_lock(&d_inode(dentry)->i_mutex);
                notify_change(dentry, &newattrs, NULL);
-               mutex_unlock(&dentry->d_inode->i_mutex);
+               mutex_unlock(&d_inode(dentry)->i_mutex);
 
                /* mark as kernel-created inode */
-               dentry->d_inode->i_private = &thread;
+               d_inode(dentry)->i_private = &thread;
        }
        done_path_create(&path, dentry);
        return err;
@@ -235,16 +235,16 @@ static int dev_rmdir(const char *name)
        dentry = kern_path_locked(name, &parent);
        if (IS_ERR(dentry))
                return PTR_ERR(dentry);
-       if (dentry->d_inode) {
-               if (dentry->d_inode->i_private == &thread)
-                       err = vfs_rmdir(parent.dentry->d_inode, dentry);
+       if (d_really_is_positive(dentry)) {
+               if (d_inode(dentry)->i_private == &thread)
+                       err = vfs_rmdir(d_inode(parent.dentry), dentry);
                else
                        err = -EPERM;
        } else {
                err = -ENOENT;
        }
        dput(dentry);
-       mutex_unlock(&parent.dentry->d_inode->i_mutex);
+       mutex_unlock(&d_inode(parent.dentry)->i_mutex);
        path_put(&parent);
        return err;
 }
@@ -306,11 +306,11 @@ static int handle_remove(const char *nodename, struct device *dev)
        if (IS_ERR(dentry))
                return PTR_ERR(dentry);
 
-       if (dentry->d_inode) {
+       if (d_really_is_positive(dentry)) {
                struct kstat stat;
                struct path p = {.mnt = parent.mnt, .dentry = dentry};
                err = vfs_getattr(&p, &stat);
-               if (!err && dev_mynode(dev, dentry->d_inode, &stat)) {
+               if (!err && dev_mynode(dev, d_inode(dentry), &stat)) {
                        struct iattr newattrs;
                        /*
                         * before unlinking this node, reset permissions
@@ -321,10 +321,10 @@ static int handle_remove(const char *nodename, struct device *dev)
                        newattrs.ia_mode = stat.mode & ~0777;
                        newattrs.ia_valid =
                                ATTR_UID|ATTR_GID|ATTR_MODE;
-                       mutex_lock(&dentry->d_inode->i_mutex);
+                       mutex_lock(&d_inode(dentry)->i_mutex);
                        notify_change(dentry, &newattrs, NULL);
-                       mutex_unlock(&dentry->d_inode->i_mutex);
-                       err = vfs_unlink(parent.dentry->d_inode, dentry, NULL);
+                       mutex_unlock(&d_inode(dentry)->i_mutex);
+                       err = vfs_unlink(d_inode(parent.dentry), dentry, NULL);
                        if (!err || err == -ENOENT)
                                deleted = 1;
                }
@@ -332,7 +332,7 @@ static int handle_remove(const char *nodename, struct device *dev)
                err = -ENOENT;
        }
        dput(dentry);
-       mutex_unlock(&parent.dentry->d_inode->i_mutex);
+       mutex_unlock(&d_inode(parent.dentry)->i_mutex);
 
        path_put(&parent);
        if (deleted && strchr(nodename, '/'))
index 9a950022ff885d40ba539438f0ff529c34152a47..a6ee3d750c302b435a41533d83c9fa83efd90d06 100644 (file)
@@ -424,7 +424,7 @@ static int in_flight_summary_show(struct seq_file *m, void *pos)
  * So we have our own inline version of it above.  :-( */
 static inline int debugfs_positive(struct dentry *dentry)
 {
-        return dentry->d_inode && !d_unhashed(dentry);
+        return d_really_is_positive(dentry) && !d_unhashed(dentry);
 }
 
 /* make sure at *open* time that the respective object won't go away. */
@@ -439,15 +439,15 @@ static int drbd_single_open(struct file *file, int (*show)(struct seq_file *, vo
         * or has debugfs_remove() already been called? */
        parent = file->f_path.dentry->d_parent;
        /* not sure if this can happen: */
-       if (!parent || !parent->d_inode)
+       if (!parent || d_really_is_negative(parent))
                goto out;
        /* serialize with d_delete() */
-       mutex_lock(&parent->d_inode->i_mutex);
+       mutex_lock(&d_inode(parent)->i_mutex);
        /* Make sure the object is still alive */
        if (debugfs_positive(file->f_path.dentry)
        && kref_get_unless_zero(kref))
                ret = 0;
-       mutex_unlock(&parent->d_inode->i_mutex);
+       mutex_unlock(&d_inode(parent)->i_mutex);
        if (!ret) {
                ret = single_open(file, show, data);
                if (ret)
index b40af3203089c846db053dfac879567230509299..ec6c5c6e1ac94b2bcbe0619a7fe62b9e7d0ce4a5 100644 (file)
@@ -2264,6 +2264,11 @@ static bool rbd_img_obj_end_request(struct rbd_obj_request *obj_request)
                        result, xferred);
                if (!img_request->result)
                        img_request->result = result;
+               /*
+                * Need to end I/O on the entire obj_request worth of
+                * bytes in case of error.
+                */
+               xferred = obj_request->length;
        }
 
        /* Image object requests don't own their page array */
@@ -3762,8 +3767,8 @@ static int rbd_init_disk(struct rbd_device *rbd_dev)
                goto out_tag_set;
        }
 
-       /* We use the default size, but let's be explicit about it. */
-       blk_queue_physical_block_size(q, SECTOR_SIZE);
+       queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q);
+       /* QUEUE_FLAG_ADD_RANDOM is off by default for blk-mq */
 
        /* set io sizes to object size */
        segment_size = rbd_obj_bytes(&rbd_dev->header);
@@ -5301,8 +5306,13 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping)
 
        if (mapping) {
                ret = rbd_dev_header_watch_sync(rbd_dev);
-               if (ret)
+               if (ret) {
+                       if (ret == -ENOENT)
+                               pr_info("image %s/%s does not exist\n",
+                                       rbd_dev->spec->pool_name,
+                                       rbd_dev->spec->image_name);
                        goto out_header_name;
+               }
        }
 
        ret = rbd_dev_header_info(rbd_dev);
@@ -5319,8 +5329,14 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping)
                ret = rbd_spec_fill_snap_id(rbd_dev);
        else
                ret = rbd_spec_fill_names(rbd_dev);
-       if (ret)
+       if (ret) {
+               if (ret == -ENOENT)
+                       pr_info("snap %s/%s@%s does not exist\n",
+                               rbd_dev->spec->pool_name,
+                               rbd_dev->spec->image_name,
+                               rbd_dev->spec->snap_name);
                goto err_out_probe;
+       }
 
        if (rbd_dev->header.features & RBD_FEATURE_LAYERING) {
                ret = rbd_dev_v2_parent_info(rbd_dev);
@@ -5390,8 +5406,11 @@ static ssize_t do_rbd_add(struct bus_type *bus,
 
        /* pick the pool */
        rc = rbd_add_get_pool_id(rbdc, spec->pool_name);
-       if (rc < 0)
+       if (rc < 0) {
+               if (rc == -ENOENT)
+                       pr_info("pool %s does not exist\n", spec->pool_name);
                goto err_out_client;
+       }
        spec->pool_id = (u64)rc;
 
        /* The ceph file layout needs to fit pool id in 32 bits */
@@ -5673,7 +5692,7 @@ static int __init rbd_init(void)
 
        /*
         * The number of active work items is limited by the number of
-        * rbd devices, so leave @max_active at default.
+        * rbd devices * queue depth, so leave @max_active at default.
         */
        rbd_wq = alloc_workqueue(RBD_DRV_NAME, WQ_MEM_RECLAIM, 0);
        if (!rbd_wq) {
index bd2b3bbbb22cf6fb1157845eafc3b2230375a4e3..713fc9ff11492766efcb7a4795b4a1750ceb9707 100644 (file)
@@ -265,17 +265,6 @@ static void put_persistent_gnt(struct xen_blkif *blkif,
        atomic_dec(&blkif->persistent_gnt_in_use);
 }
 
-static void free_persistent_gnts_unmap_callback(int result,
-                                               struct gntab_unmap_queue_data *data)
-{
-       struct completion *c = data->data;
-
-       /* BUG_ON used to reproduce existing behaviour,
-          but is this the best way to deal with this? */
-       BUG_ON(result);
-       complete(c);
-}
-
 static void free_persistent_gnts(struct xen_blkif *blkif, struct rb_root *root,
                                  unsigned int num)
 {
@@ -285,12 +274,7 @@ static void free_persistent_gnts(struct xen_blkif *blkif, struct rb_root *root,
        struct rb_node *n;
        int segs_to_unmap = 0;
        struct gntab_unmap_queue_data unmap_data;
-       struct completion unmap_completion;
 
-       init_completion(&unmap_completion);
-
-       unmap_data.data = &unmap_completion;
-       unmap_data.done = &free_persistent_gnts_unmap_callback;
        unmap_data.pages = pages;
        unmap_data.unmap_ops = unmap;
        unmap_data.kunmap_ops = NULL;
@@ -310,8 +294,7 @@ static void free_persistent_gnts(struct xen_blkif *blkif, struct rb_root *root,
                        !rb_next(&persistent_gnt->node)) {
 
                        unmap_data.count = segs_to_unmap;
-                       gnttab_unmap_refs_async(&unmap_data);
-                       wait_for_completion(&unmap_completion);
+                       BUG_ON(gnttab_unmap_refs_sync(&unmap_data));
 
                        put_free_pages(blkif, pages, segs_to_unmap);
                        segs_to_unmap = 0;
@@ -329,8 +312,13 @@ void xen_blkbk_unmap_purged_grants(struct work_struct *work)
        struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST];
        struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST];
        struct persistent_gnt *persistent_gnt;
-       int ret, segs_to_unmap = 0;
+       int segs_to_unmap = 0;
        struct xen_blkif *blkif = container_of(work, typeof(*blkif), persistent_purge_work);
+       struct gntab_unmap_queue_data unmap_data;
+
+       unmap_data.pages = pages;
+       unmap_data.unmap_ops = unmap;
+       unmap_data.kunmap_ops = NULL;
 
        while(!list_empty(&blkif->persistent_purge_list)) {
                persistent_gnt = list_first_entry(&blkif->persistent_purge_list,
@@ -346,17 +334,16 @@ void xen_blkbk_unmap_purged_grants(struct work_struct *work)
                pages[segs_to_unmap] = persistent_gnt->page;
 
                if (++segs_to_unmap == BLKIF_MAX_SEGMENTS_PER_REQUEST) {
-                       ret = gnttab_unmap_refs(unmap, NULL, pages,
-                               segs_to_unmap);
-                       BUG_ON(ret);
+                       unmap_data.count = segs_to_unmap;
+                       BUG_ON(gnttab_unmap_refs_sync(&unmap_data));
                        put_free_pages(blkif, pages, segs_to_unmap);
                        segs_to_unmap = 0;
                }
                kfree(persistent_gnt);
        }
        if (segs_to_unmap > 0) {
-               ret = gnttab_unmap_refs(unmap, NULL, pages, segs_to_unmap);
-               BUG_ON(ret);
+               unmap_data.count = segs_to_unmap;
+               BUG_ON(gnttab_unmap_refs_sync(&unmap_data));
                put_free_pages(blkif, pages, segs_to_unmap);
        }
 }
index c94386aa563d618abf2d59a046b50b1607c3a20f..8dcbced0eafd5f8dc0a53dc8d8e9d4b37bad9bab 100644 (file)
@@ -74,6 +74,27 @@ static inline struct zram *dev_to_zram(struct device *dev)
        return (struct zram *)dev_to_disk(dev)->private_data;
 }
 
+static ssize_t compact_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t len)
+{
+       unsigned long nr_migrated;
+       struct zram *zram = dev_to_zram(dev);
+       struct zram_meta *meta;
+
+       down_read(&zram->init_lock);
+       if (!init_done(zram)) {
+               up_read(&zram->init_lock);
+               return -EINVAL;
+       }
+
+       meta = zram->meta;
+       nr_migrated = zs_compact(meta->mem_pool);
+       atomic64_add(nr_migrated, &zram->stats.num_migrated);
+       up_read(&zram->init_lock);
+
+       return len;
+}
+
 static ssize_t disksize_show(struct device *dev,
                struct device_attribute *attr, char *buf)
 {
@@ -1038,6 +1059,7 @@ static const struct block_device_operations zram_devops = {
        .owner = THIS_MODULE
 };
 
+static DEVICE_ATTR_WO(compact);
 static DEVICE_ATTR_RW(disksize);
 static DEVICE_ATTR_RO(initstate);
 static DEVICE_ATTR_WO(reset);
@@ -1114,6 +1136,7 @@ static struct attribute *zram_disk_attrs[] = {
        &dev_attr_num_writes.attr,
        &dev_attr_failed_reads.attr,
        &dev_attr_failed_writes.attr,
+       &dev_attr_compact.attr,
        &dev_attr_invalid_io.attr,
        &dev_attr_notify_free.attr,
        &dev_attr_zero_pages.attr,
index cbddbaddb34780dd1295f8ea22ceaaef16bd2f0f..a1d4af6df3f57a5e7de71bbdaa79bb5f271d0fef 100644 (file)
@@ -4,6 +4,41 @@
 
 menu "Bus devices"
 
+config ARM_CCI
+       bool
+
+config ARM_CCI400_COMMON
+       bool
+       select ARM_CCI
+
+config ARM_CCI400_PMU
+       bool "ARM CCI400 PMU support"
+       default y
+       depends on ARM || ARM64
+       depends on HW_PERF_EVENTS
+       select ARM_CCI400_COMMON
+       help
+         Support for PMU events monitoring on the ARM CCI cache coherent
+         interconnect.
+
+         If unsure, say Y
+
+config ARM_CCI400_PORT_CTRL
+       bool
+       depends on ARM && OF && CPU_V7
+       select ARM_CCI400_COMMON
+       help
+         Low level power management driver for CCI400 cache coherent
+         interconnect for ARM platforms.
+
+config ARM_CCN
+       bool "ARM CCN driver support"
+       depends on ARM || ARM64
+       depends on PERF_EVENTS
+       help
+         PMU (perf) driver supporting the ARM CCN (Cache Coherent Network)
+         interconnect.
+
 config BRCMSTB_GISB_ARB
        bool "Broadcom STB GISB bus arbiter"
        depends on ARM || MIPS
@@ -40,15 +75,6 @@ config MVEBU_MBUS
          Driver needed for the MBus configuration on Marvell EBU SoCs
          (Kirkwood, Dove, Orion5x, MV78XX0 and Armada 370/XP).
 
-config OMAP_OCP2SCP
-       tristate "OMAP OCP2SCP DRIVER"
-       depends on ARCH_OMAP2PLUS
-       help
-         Driver to enable ocp2scp module which transforms ocp interface
-         protocol to scp protocol. In OMAP4, USB PHY is connected via
-         OCP2SCP and in OMAP5, both USB PHY and SATA PHY is connected via
-         OCP2SCP.
-
 config OMAP_INTERCONNECT
        tristate "OMAP INTERCONNECT DRIVER"
        depends on ARCH_OMAP2PLUS
@@ -56,20 +82,27 @@ config OMAP_INTERCONNECT
        help
          Driver to enable OMAP interconnect error handling driver.
 
-config ARM_CCI
-       bool "ARM CCI driver support"
-       depends on ARM && OF && CPU_V7
+config OMAP_OCP2SCP
+       tristate "OMAP OCP2SCP DRIVER"
+       depends on ARCH_OMAP2PLUS
        help
-         Driver supporting the CCI cache coherent interconnect for ARM
-         platforms.
+         Driver to enable ocp2scp module which transforms ocp interface
+         protocol to scp protocol. In OMAP4, USB PHY is connected via
+         OCP2SCP and in OMAP5, both USB PHY and SATA PHY is connected via
+         OCP2SCP.
 
-config ARM_CCN
-       bool "ARM CCN driver support"
-       depends on ARM || ARM64
-       depends on PERF_EVENTS
+config SIMPLE_PM_BUS
+       bool "Simple Power-Managed Bus Driver"
+       depends on OF && PM
+       depends on ARCH_SHMOBILE || COMPILE_TEST
        help
-         PMU (perf) driver supporting the ARM CCN (Cache Coherent Network)
-         interconnect.
+         Driver for transparent busses that don't need a real driver, but
+         where the bus controller is part of a PM domain, or under the control
+         of a functional clock, and thus relies on runtime PM for managing
+         this PM domain and/or clock.
+         An example of such a bus controller is the Renesas Bus State
+         Controller (BSC, sometimes called "LBSC within Bus Bridge", or
+         "External Bus Interface") as found on several Renesas ARM SoCs.
 
 config VEXPRESS_CONFIG
        bool "Versatile Express configuration bus"
index 807dd17ef2f822ee98cc2e96916ffe55177f03ad..790e7b933fb2f9b2a266d43ecfec16620605fe2f 100644 (file)
@@ -2,17 +2,18 @@
 # Makefile for the bus drivers.
 #
 
+# Interconnect bus drivers for ARM platforms
+obj-$(CONFIG_ARM_CCI)          += arm-cci.o
+obj-$(CONFIG_ARM_CCN)          += arm-ccn.o
+
 obj-$(CONFIG_BRCMSTB_GISB_ARB) += brcmstb_gisb.o
-obj-$(CONFIG_IMX_WEIM) += imx-weim.o
-obj-$(CONFIG_MIPS_CDMM) += mips_cdmm.o
-obj-$(CONFIG_MVEBU_MBUS) += mvebu-mbus.o
-obj-$(CONFIG_OMAP_OCP2SCP)     += omap-ocp2scp.o
+obj-$(CONFIG_IMX_WEIM)         += imx-weim.o
+obj-$(CONFIG_MIPS_CDMM)                += mips_cdmm.o
+obj-$(CONFIG_MVEBU_MBUS)       += mvebu-mbus.o
 
 # Interconnect bus driver for OMAP SoCs.
 obj-$(CONFIG_OMAP_INTERCONNECT)        += omap_l3_smx.o omap_l3_noc.o
 
-# Interconnect bus drivers for ARM platforms
-obj-$(CONFIG_ARM_CCI)          += arm-cci.o
-obj-$(CONFIG_ARM_CCN)          += arm-ccn.o
-
+obj-$(CONFIG_OMAP_OCP2SCP)     += omap-ocp2scp.o
+obj-$(CONFIG_SIMPLE_PM_BUS)    += simple-pm-bus.o
 obj-$(CONFIG_VEXPRESS_CONFIG)  += vexpress-config.o
index 84fd66057dadf9e60b6c9ad04e535334265cda01..b854125e48311aa1e101c8ea9ab6ff0ec909753c 100644 (file)
 #include <asm/cacheflush.h>
 #include <asm/smp_plat.h>
 
-#define DRIVER_NAME            "CCI-400"
-#define DRIVER_NAME_PMU                DRIVER_NAME " PMU"
-
-#define CCI_PORT_CTRL          0x0
-#define CCI_CTRL_STATUS                0xc
-
-#define CCI_ENABLE_SNOOP_REQ   0x1
-#define CCI_ENABLE_DVM_REQ     0x2
-#define CCI_ENABLE_REQ         (CCI_ENABLE_SNOOP_REQ | CCI_ENABLE_DVM_REQ)
+static void __iomem *cci_ctrl_base;
+static unsigned long cci_ctrl_phys;
 
+#ifdef CONFIG_ARM_CCI400_PORT_CTRL
 struct cci_nb_ports {
        unsigned int nb_ace;
        unsigned int nb_ace_lite;
 };
 
-enum cci_ace_port_type {
-       ACE_INVALID_PORT = 0x0,
-       ACE_PORT,
-       ACE_LITE_PORT,
+static const struct cci_nb_ports cci400_ports = {
+       .nb_ace = 2,
+       .nb_ace_lite = 3
 };
 
-struct cci_ace_port {
-       void __iomem *base;
-       unsigned long phys;
-       enum cci_ace_port_type type;
-       struct device_node *dn;
-};
+#define CCI400_PORTS_DATA      (&cci400_ports)
+#else
+#define CCI400_PORTS_DATA      (NULL)
+#endif
 
-static struct cci_ace_port *ports;
-static unsigned int nb_cci_ports;
+static const struct of_device_id arm_cci_matches[] = {
+#ifdef CONFIG_ARM_CCI400_COMMON
+       {.compatible = "arm,cci-400", .data = CCI400_PORTS_DATA },
+#endif
+       {},
+};
 
-static void __iomem *cci_ctrl_base;
-static unsigned long cci_ctrl_phys;
+#ifdef CONFIG_ARM_CCI400_PMU
 
-#ifdef CONFIG_HW_PERF_EVENTS
+#define DRIVER_NAME            "CCI-400"
+#define DRIVER_NAME_PMU                DRIVER_NAME " PMU"
 
 #define CCI_PMCR               0x0100
 #define CCI_PID2               0x0fe8
@@ -75,20 +70,6 @@ static unsigned long cci_ctrl_phys;
 #define CCI_PID2_REV_MASK      0xf0
 #define CCI_PID2_REV_SHIFT     4
 
-/* Port ids */
-#define CCI_PORT_S0    0
-#define CCI_PORT_S1    1
-#define CCI_PORT_S2    2
-#define CCI_PORT_S3    3
-#define CCI_PORT_S4    4
-#define CCI_PORT_M0    5
-#define CCI_PORT_M1    6
-#define CCI_PORT_M2    7
-
-#define CCI_REV_R0             0
-#define CCI_REV_R1             1
-#define CCI_REV_R1_PX          5
-
 #define CCI_PMU_EVT_SEL                0x000
 #define CCI_PMU_CNTR           0x004
 #define CCI_PMU_CNTR_CTRL      0x008
@@ -100,76 +81,22 @@ static unsigned long cci_ctrl_phys;
 
 #define CCI_PMU_CNTR_MASK      ((1ULL << 32) -1)
 
-/*
- * Instead of an event id to monitor CCI cycles, a dedicated counter is
- * provided. Use 0xff to represent CCI cycles and hope that no future revisions
- * make use of this event in hardware.
- */
-enum cci400_perf_events {
-       CCI_PMU_CYCLES = 0xff
-};
-
-#define CCI_PMU_EVENT_MASK             0xff
+#define CCI_PMU_EVENT_MASK             0xffUL
 #define CCI_PMU_EVENT_SOURCE(event)    ((event >> 5) & 0x7)
 #define CCI_PMU_EVENT_CODE(event)      (event & 0x1f)
 
 #define CCI_PMU_MAX_HW_EVENTS 5   /* CCI PMU has 4 counters + 1 cycle counter */
 
-#define CCI_PMU_CYCLE_CNTR_IDX         0
-#define CCI_PMU_CNTR0_IDX              1
-#define CCI_PMU_CNTR_LAST(cci_pmu)     (CCI_PMU_CYCLE_CNTR_IDX + cci_pmu->num_events - 1)
-
-/*
- * CCI PMU event id is an 8-bit value made of two parts - bits 7:5 for one of 8
- * ports and bits 4:0 are event codes. There are different event codes
- * associated with each port type.
- *
- * Additionally, the range of events associated with the port types changed
- * between Rev0 and Rev1.
- *
- * The constants below define the range of valid codes for each port type for
- * the different revisions and are used to validate the event to be monitored.
- */
-
-#define CCI_REV_R0_SLAVE_PORT_MIN_EV   0x00
-#define CCI_REV_R0_SLAVE_PORT_MAX_EV   0x13
-#define CCI_REV_R0_MASTER_PORT_MIN_EV  0x14
-#define CCI_REV_R0_MASTER_PORT_MAX_EV  0x1a
-
-#define CCI_REV_R1_SLAVE_PORT_MIN_EV   0x00
-#define CCI_REV_R1_SLAVE_PORT_MAX_EV   0x14
-#define CCI_REV_R1_MASTER_PORT_MIN_EV  0x00
-#define CCI_REV_R1_MASTER_PORT_MAX_EV  0x11
-
-struct pmu_port_event_ranges {
-       u8 slave_min;
-       u8 slave_max;
-       u8 master_min;
-       u8 master_max;
-};
-
-static struct pmu_port_event_ranges port_event_range[] = {
-       [CCI_REV_R0] = {
-               .slave_min = CCI_REV_R0_SLAVE_PORT_MIN_EV,
-               .slave_max = CCI_REV_R0_SLAVE_PORT_MAX_EV,
-               .master_min = CCI_REV_R0_MASTER_PORT_MIN_EV,
-               .master_max = CCI_REV_R0_MASTER_PORT_MAX_EV,
-       },
-       [CCI_REV_R1] = {
-               .slave_min = CCI_REV_R1_SLAVE_PORT_MIN_EV,
-               .slave_max = CCI_REV_R1_SLAVE_PORT_MAX_EV,
-               .master_min = CCI_REV_R1_MASTER_PORT_MIN_EV,
-               .master_max = CCI_REV_R1_MASTER_PORT_MAX_EV,
-       },
+/* Types of interfaces that can generate events */
+enum {
+       CCI_IF_SLAVE,
+       CCI_IF_MASTER,
+       CCI_IF_MAX,
 };
 
-/*
- * Export different PMU names for the different revisions so userspace knows
- * because the event ids are different
- */
-static char *const pmu_names[] = {
-       [CCI_REV_R0] = "CCI_400",
-       [CCI_REV_R1] = "CCI_400_r1",
+struct event_range {
+       u32 min;
+       u32 max;
 };
 
 struct cci_pmu_hw_events {
@@ -178,13 +105,20 @@ struct cci_pmu_hw_events {
        raw_spinlock_t pmu_lock;
 };
 
+struct cci_pmu_model {
+       char *name;
+       struct event_range event_ranges[CCI_IF_MAX];
+};
+
+static struct cci_pmu_model cci_pmu_models[];
+
 struct cci_pmu {
        void __iomem *base;
        struct pmu pmu;
        int nr_irqs;
        int irqs[CCI_PMU_MAX_HW_EVENTS];
        unsigned long active_irqs;
-       struct pmu_port_event_ranges *port_ranges;
+       const struct cci_pmu_model *model;
        struct cci_pmu_hw_events hw_events;
        struct platform_device *plat_device;
        int num_events;
@@ -196,52 +130,63 @@ static struct cci_pmu *pmu;
 
 #define to_cci_pmu(c)  (container_of(c, struct cci_pmu, pmu))
 
-static bool is_duplicate_irq(int irq, int *irqs, int nr_irqs)
-{
-       int i;
-
-       for (i = 0; i < nr_irqs; i++)
-               if (irq == irqs[i])
-                       return true;
-
-       return false;
-}
+/* Port ids */
+#define CCI_PORT_S0    0
+#define CCI_PORT_S1    1
+#define CCI_PORT_S2    2
+#define CCI_PORT_S3    3
+#define CCI_PORT_S4    4
+#define CCI_PORT_M0    5
+#define CCI_PORT_M1    6
+#define CCI_PORT_M2    7
 
-static int probe_cci_revision(void)
-{
-       int rev;
-       rev = readl_relaxed(cci_ctrl_base + CCI_PID2) & CCI_PID2_REV_MASK;
-       rev >>= CCI_PID2_REV_SHIFT;
+#define CCI_REV_R0             0
+#define CCI_REV_R1             1
+#define CCI_REV_R1_PX          5
 
-       if (rev < CCI_REV_R1_PX)
-               return CCI_REV_R0;
-       else
-               return CCI_REV_R1;
-}
+/*
+ * Instead of an event id to monitor CCI cycles, a dedicated counter is
+ * provided. Use 0xff to represent CCI cycles and hope that no future revisions
+ * make use of this event in hardware.
+ */
+enum cci400_perf_events {
+       CCI_PMU_CYCLES = 0xff
+};
 
-static struct pmu_port_event_ranges *port_range_by_rev(void)
-{
-       int rev = probe_cci_revision();
+#define CCI_PMU_CYCLE_CNTR_IDX         0
+#define CCI_PMU_CNTR0_IDX              1
+#define CCI_PMU_CNTR_LAST(cci_pmu)     (CCI_PMU_CYCLE_CNTR_IDX + cci_pmu->num_events - 1)
 
-       return &port_event_range[rev];
-}
+/*
+ * CCI PMU event id is an 8-bit value made of two parts - bits 7:5 for one of 8
+ * ports and bits 4:0 are event codes. There are different event codes
+ * associated with each port type.
+ *
+ * Additionally, the range of events associated with the port types changed
+ * between Rev0 and Rev1.
+ *
+ * The constants below define the range of valid codes for each port type for
+ * the different revisions and are used to validate the event to be monitored.
+ */
 
-static int pmu_is_valid_slave_event(u8 ev_code)
-{
-       return pmu->port_ranges->slave_min <= ev_code &&
-               ev_code <= pmu->port_ranges->slave_max;
-}
+#define CCI_REV_R0_SLAVE_PORT_MIN_EV   0x00
+#define CCI_REV_R0_SLAVE_PORT_MAX_EV   0x13
+#define CCI_REV_R0_MASTER_PORT_MIN_EV  0x14
+#define CCI_REV_R0_MASTER_PORT_MAX_EV  0x1a
 
-static int pmu_is_valid_master_event(u8 ev_code)
-{
-       return pmu->port_ranges->master_min <= ev_code &&
-               ev_code <= pmu->port_ranges->master_max;
-}
+#define CCI_REV_R1_SLAVE_PORT_MIN_EV   0x00
+#define CCI_REV_R1_SLAVE_PORT_MAX_EV   0x14
+#define CCI_REV_R1_MASTER_PORT_MIN_EV  0x00
+#define CCI_REV_R1_MASTER_PORT_MAX_EV  0x11
 
-static int pmu_validate_hw_event(u8 hw_event)
+static int pmu_validate_hw_event(unsigned long hw_event)
 {
        u8 ev_source = CCI_PMU_EVENT_SOURCE(hw_event);
        u8 ev_code = CCI_PMU_EVENT_CODE(hw_event);
+       int if_type;
+
+       if (hw_event & ~CCI_PMU_EVENT_MASK)
+               return -ENOENT;
 
        switch (ev_source) {
        case CCI_PORT_S0:
@@ -250,21 +195,44 @@ static int pmu_validate_hw_event(u8 hw_event)
        case CCI_PORT_S3:
        case CCI_PORT_S4:
                /* Slave Interface */
-               if (pmu_is_valid_slave_event(ev_code))
-                       return hw_event;
+               if_type = CCI_IF_SLAVE;
                break;
        case CCI_PORT_M0:
        case CCI_PORT_M1:
        case CCI_PORT_M2:
                /* Master Interface */
-               if (pmu_is_valid_master_event(ev_code))
-                       return hw_event;
+               if_type = CCI_IF_MASTER;
                break;
+       default:
+               return -ENOENT;
        }
 
+       if (ev_code >= pmu->model->event_ranges[if_type].min &&
+               ev_code <= pmu->model->event_ranges[if_type].max)
+               return hw_event;
+
        return -ENOENT;
 }
 
+static int probe_cci_revision(void)
+{
+       int rev;
+       rev = readl_relaxed(cci_ctrl_base + CCI_PID2) & CCI_PID2_REV_MASK;
+       rev >>= CCI_PID2_REV_SHIFT;
+
+       if (rev < CCI_REV_R1_PX)
+               return CCI_REV_R0;
+       else
+               return CCI_REV_R1;
+}
+
+static const struct cci_pmu_model *probe_cci_model(struct platform_device *pdev)
+{
+       if (platform_has_secure_cci_access())
+               return &cci_pmu_models[probe_cci_revision()];
+       return NULL;
+}
+
 static int pmu_is_valid_counter(struct cci_pmu *cci_pmu, int idx)
 {
        return CCI_PMU_CYCLE_CNTR_IDX <= idx &&
@@ -293,7 +261,6 @@ static void pmu_enable_counter(int idx)
 
 static void pmu_set_event(int idx, unsigned long event)
 {
-       event &= CCI_PMU_EVENT_MASK;
        pmu_write_register(event, idx, CCI_PMU_EVT_SEL);
 }
 
@@ -310,7 +277,7 @@ static int pmu_get_event_idx(struct cci_pmu_hw_events *hw, struct perf_event *ev
 {
        struct cci_pmu *cci_pmu = to_cci_pmu(event->pmu);
        struct hw_perf_event *hw_event = &event->hw;
-       unsigned long cci_event = hw_event->config_base & CCI_PMU_EVENT_MASK;
+       unsigned long cci_event = hw_event->config_base;
        int idx;
 
        if (cci_event == CCI_PMU_CYCLES) {
@@ -331,7 +298,7 @@ static int pmu_get_event_idx(struct cci_pmu_hw_events *hw, struct perf_event *ev
 static int pmu_map_event(struct perf_event *event)
 {
        int mapping;
-       u8 config = event->attr.config & CCI_PMU_EVENT_MASK;
+       unsigned long config = event->attr.config;
 
        if (event->attr.type < PERF_TYPE_MAX)
                return -ENOENT;
@@ -660,12 +627,21 @@ static void cci_pmu_del(struct perf_event *event, int flags)
 }
 
 static int
-validate_event(struct cci_pmu_hw_events *hw_events,
-              struct perf_event *event)
+validate_event(struct pmu *cci_pmu,
+               struct cci_pmu_hw_events *hw_events,
+               struct perf_event *event)
 {
        if (is_software_event(event))
                return 1;
 
+       /*
+        * Reject groups spanning multiple HW PMUs (e.g. CPU + CCI). The
+        * core perf code won't check that the pmu->ctx == leader->ctx
+        * until after pmu->event_init(event).
+        */
+       if (event->pmu != cci_pmu)
+               return 0;
+
        if (event->state < PERF_EVENT_STATE_OFF)
                return 1;
 
@@ -687,15 +663,15 @@ validate_group(struct perf_event *event)
                .used_mask = CPU_BITS_NONE,
        };
 
-       if (!validate_event(&fake_pmu, leader))
+       if (!validate_event(event->pmu, &fake_pmu, leader))
                return -EINVAL;
 
        list_for_each_entry(sibling, &leader->sibling_list, group_entry) {
-               if (!validate_event(&fake_pmu, sibling))
+               if (!validate_event(event->pmu, &fake_pmu, sibling))
                        return -EINVAL;
        }
 
-       if (!validate_event(&fake_pmu, event))
+       if (!validate_event(event->pmu, &fake_pmu, event))
                return -EINVAL;
 
        return 0;
@@ -831,9 +807,9 @@ static const struct attribute_group *pmu_attr_groups[] = {
 
 static int cci_pmu_init(struct cci_pmu *cci_pmu, struct platform_device *pdev)
 {
-       char *name = pmu_names[probe_cci_revision()];
+       char *name = cci_pmu->model->name;
        cci_pmu->pmu = (struct pmu) {
-               .name           = pmu_names[probe_cci_revision()],
+               .name           = cci_pmu->model->name,
                .task_ctx_nr    = perf_invalid_context,
                .pmu_enable     = cci_pmu_enable,
                .pmu_disable    = cci_pmu_disable,
@@ -886,22 +862,93 @@ static struct notifier_block cci_pmu_cpu_nb = {
        .priority       = CPU_PRI_PERF + 1,
 };
 
+static struct cci_pmu_model cci_pmu_models[] = {
+       [CCI_REV_R0] = {
+               .name = "CCI_400",
+               .event_ranges = {
+                       [CCI_IF_SLAVE] = {
+                               CCI_REV_R0_SLAVE_PORT_MIN_EV,
+                               CCI_REV_R0_SLAVE_PORT_MAX_EV,
+                       },
+                       [CCI_IF_MASTER] = {
+                               CCI_REV_R0_MASTER_PORT_MIN_EV,
+                               CCI_REV_R0_MASTER_PORT_MAX_EV,
+                       },
+               },
+       },
+       [CCI_REV_R1] = {
+               .name = "CCI_400_r1",
+               .event_ranges = {
+                       [CCI_IF_SLAVE] = {
+                               CCI_REV_R1_SLAVE_PORT_MIN_EV,
+                               CCI_REV_R1_SLAVE_PORT_MAX_EV,
+                       },
+                       [CCI_IF_MASTER] = {
+                               CCI_REV_R1_MASTER_PORT_MIN_EV,
+                               CCI_REV_R1_MASTER_PORT_MAX_EV,
+                       },
+               },
+       },
+};
+
 static const struct of_device_id arm_cci_pmu_matches[] = {
        {
                .compatible = "arm,cci-400-pmu",
+               .data   = NULL,
+       },
+       {
+               .compatible = "arm,cci-400-pmu,r0",
+               .data   = &cci_pmu_models[CCI_REV_R0],
+       },
+       {
+               .compatible = "arm,cci-400-pmu,r1",
+               .data   = &cci_pmu_models[CCI_REV_R1],
        },
        {},
 };
 
+static inline const struct cci_pmu_model *get_cci_model(struct platform_device *pdev)
+{
+       const struct of_device_id *match = of_match_node(arm_cci_pmu_matches,
+                                                       pdev->dev.of_node);
+       if (!match)
+               return NULL;
+       if (match->data)
+               return match->data;
+
+       dev_warn(&pdev->dev, "DEPRECATED compatible property,"
+                        "requires secure access to CCI registers");
+       return probe_cci_model(pdev);
+}
+
+static bool is_duplicate_irq(int irq, int *irqs, int nr_irqs)
+{
+       int i;
+
+       for (i = 0; i < nr_irqs; i++)
+               if (irq == irqs[i])
+                       return true;
+
+       return false;
+}
+
 static int cci_pmu_probe(struct platform_device *pdev)
 {
        struct resource *res;
        int i, ret, irq;
+       const struct cci_pmu_model *model;
+
+       model = get_cci_model(pdev);
+       if (!model) {
+               dev_warn(&pdev->dev, "CCI PMU version not supported\n");
+               return -ENODEV;
+       }
 
        pmu = devm_kzalloc(&pdev->dev, sizeof(*pmu), GFP_KERNEL);
        if (!pmu)
                return -ENOMEM;
 
+       pmu->model = model;
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        pmu->base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(pmu->base))
@@ -933,12 +980,6 @@ static int cci_pmu_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       pmu->port_ranges = port_range_by_rev();
-       if (!pmu->port_ranges) {
-               dev_warn(&pdev->dev, "CCI PMU version not supported\n");
-               return -EINVAL;
-       }
-
        raw_spin_lock_init(&pmu->hw_events.pmu_lock);
        mutex_init(&pmu->reserve_mutex);
        atomic_set(&pmu->active_events, 0);
@@ -952,6 +993,7 @@ static int cci_pmu_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
+       pr_info("ARM %s PMU driver probed", pmu->model->name);
        return 0;
 }
 
@@ -963,7 +1005,66 @@ static int cci_platform_probe(struct platform_device *pdev)
        return of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
 }
 
-#endif /* CONFIG_HW_PERF_EVENTS */
+static struct platform_driver cci_pmu_driver = {
+       .driver = {
+                  .name = DRIVER_NAME_PMU,
+                  .of_match_table = arm_cci_pmu_matches,
+                 },
+       .probe = cci_pmu_probe,
+};
+
+static struct platform_driver cci_platform_driver = {
+       .driver = {
+                  .name = DRIVER_NAME,
+                  .of_match_table = arm_cci_matches,
+                 },
+       .probe = cci_platform_probe,
+};
+
+static int __init cci_platform_init(void)
+{
+       int ret;
+
+       ret = platform_driver_register(&cci_pmu_driver);
+       if (ret)
+               return ret;
+
+       return platform_driver_register(&cci_platform_driver);
+}
+
+#else /* !CONFIG_ARM_CCI400_PMU */
+
+static int __init cci_platform_init(void)
+{
+       return 0;
+}
+
+#endif /* CONFIG_ARM_CCI400_PMU */
+
+#ifdef CONFIG_ARM_CCI400_PORT_CTRL
+
+#define CCI_PORT_CTRL          0x0
+#define CCI_CTRL_STATUS                0xc
+
+#define CCI_ENABLE_SNOOP_REQ   0x1
+#define CCI_ENABLE_DVM_REQ     0x2
+#define CCI_ENABLE_REQ         (CCI_ENABLE_SNOOP_REQ | CCI_ENABLE_DVM_REQ)
+
+enum cci_ace_port_type {
+       ACE_INVALID_PORT = 0x0,
+       ACE_PORT,
+       ACE_LITE_PORT,
+};
+
+struct cci_ace_port {
+       void __iomem *base;
+       unsigned long phys;
+       enum cci_ace_port_type type;
+       struct device_node *dn;
+};
+
+static struct cci_ace_port *ports;
+static unsigned int nb_cci_ports;
 
 struct cpu_port {
        u64 mpidr;
@@ -1284,36 +1385,20 @@ int notrace __cci_control_port_by_index(u32 port, bool enable)
 }
 EXPORT_SYMBOL_GPL(__cci_control_port_by_index);
 
-static const struct cci_nb_ports cci400_ports = {
-       .nb_ace = 2,
-       .nb_ace_lite = 3
-};
-
-static const struct of_device_id arm_cci_matches[] = {
-       {.compatible = "arm,cci-400", .data = &cci400_ports },
-       {},
-};
-
 static const struct of_device_id arm_cci_ctrl_if_matches[] = {
        {.compatible = "arm,cci-400-ctrl-if", },
        {},
 };
 
-static int cci_probe(void)
+static int cci_probe_ports(struct device_node *np)
 {
        struct cci_nb_ports const *cci_config;
        int ret, i, nb_ace = 0, nb_ace_lite = 0;
-       struct device_node *np, *cp;
+       struct device_node *cp;
        struct resource res;
        const char *match_str;
        bool is_ace;
 
-       np = of_find_matching_node(NULL, arm_cci_matches);
-       if (!np)
-               return -ENODEV;
-
-       if (!of_device_is_available(np))
-               return -ENODEV;
 
        cci_config = of_match_node(arm_cci_matches, np)->data;
        if (!cci_config)
@@ -1325,17 +1410,6 @@ static int cci_probe(void)
        if (!ports)
                return -ENOMEM;
 
-       ret = of_address_to_resource(np, 0, &res);
-       if (!ret) {
-               cci_ctrl_base = ioremap(res.start, resource_size(&res));
-               cci_ctrl_phys = res.start;
-       }
-       if (ret || !cci_ctrl_base) {
-               WARN(1, "unable to ioremap CCI ctrl\n");
-               ret = -ENXIO;
-               goto memalloc_err;
-       }
-
        for_each_child_of_node(np, cp) {
                if (!of_match_node(arm_cci_ctrl_if_matches, cp))
                        continue;
@@ -1395,12 +1469,37 @@ static int cci_probe(void)
        sync_cache_w(&cpu_port);
        __sync_cache_range_w(ports, sizeof(*ports) * nb_cci_ports);
        pr_info("ARM CCI driver probed\n");
+
        return 0;
+}
+#else /* !CONFIG_ARM_CCI400_PORT_CTRL */
+static inline int cci_probe_ports(struct device_node *np)
+{
+       return 0;
+}
+#endif /* CONFIG_ARM_CCI400_PORT_CTRL */
 
-memalloc_err:
+static int cci_probe(void)
+{
+       int ret;
+       struct device_node *np;
+       struct resource res;
+
+       np = of_find_matching_node(NULL, arm_cci_matches);
+       if(!np || !of_device_is_available(np))
+               return -ENODEV;
 
-       kfree(ports);
-       return ret;
+       ret = of_address_to_resource(np, 0, &res);
+       if (!ret) {
+               cci_ctrl_base = ioremap(res.start, resource_size(&res));
+               cci_ctrl_phys = res.start;
+       }
+       if (ret || !cci_ctrl_base) {
+               WARN(1, "unable to ioremap CCI ctrl\n");
+               return -ENXIO;
+       }
+
+       return cci_probe_ports(np);
 }
 
 static int cci_init_status = -EAGAIN;
@@ -1418,42 +1517,6 @@ static int cci_init(void)
        return cci_init_status;
 }
 
-#ifdef CONFIG_HW_PERF_EVENTS
-static struct platform_driver cci_pmu_driver = {
-       .driver = {
-                  .name = DRIVER_NAME_PMU,
-                  .of_match_table = arm_cci_pmu_matches,
-                 },
-       .probe = cci_pmu_probe,
-};
-
-static struct platform_driver cci_platform_driver = {
-       .driver = {
-                  .name = DRIVER_NAME,
-                  .of_match_table = arm_cci_matches,
-                 },
-       .probe = cci_platform_probe,
-};
-
-static int __init cci_platform_init(void)
-{
-       int ret;
-
-       ret = platform_driver_register(&cci_pmu_driver);
-       if (ret)
-               return ret;
-
-       return platform_driver_register(&cci_platform_driver);
-}
-
-#else
-
-static int __init cci_platform_init(void)
-{
-       return 0;
-}
-
-#endif
 /*
  * To sort out early init calls ordering a helper function is provided to
  * check if the CCI driver has beed initialized. Function check if the driver
index 0958b6981773c19527973916c65b3e703c5633f8..e98d15eaa7994c7349d1db8df4dd19f684b85ba6 100644 (file)
@@ -142,7 +142,7 @@ static int __init weim_parse_dt(struct platform_device *pdev,
                                                           &pdev->dev);
        const struct imx_weim_devtype *devtype = of_id->data;
        struct device_node *child;
-       int ret;
+       int ret, have_child = 0;
 
        if (devtype == &imx50_weim_devtype) {
                ret = imx_weim_gpr_setup(pdev);
@@ -155,14 +155,15 @@ static int __init weim_parse_dt(struct platform_device *pdev,
                        continue;
 
                ret = weim_timing_setup(child, base, devtype);
-               if (ret) {
-                       dev_err(&pdev->dev, "%s set timing failed.\n",
+               if (ret)
+                       dev_warn(&pdev->dev, "%s set timing failed.\n",
                                child->full_name);
-                       return ret;
-               }
+               else
+                       have_child = 1;
        }
 
-       ret = of_platform_populate(pdev->dev.of_node,
+       if (have_child)
+               ret = of_platform_populate(pdev->dev.of_node,
                                   of_default_bus_match_table,
                                   NULL, &pdev->dev);
        if (ret)
index 723ec06ad2c8209d211fa58e6377625882d74754..9f185694875850427e9613aaf725859c7efbfc63 100644 (file)
@@ -16,6 +16,7 @@
  *
  */
 
+#include <linux/io.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/err.h>
@@ -23,6 +24,9 @@
 #include <linux/of.h>
 #include <linux/of_platform.h>
 
+#define OCP2SCP_TIMING 0x18
+#define SYNC2_MASK 0xf
+
 static int ocp2scp_remove_devices(struct device *dev, void *c)
 {
        struct platform_device *pdev = to_platform_device(dev);
@@ -35,6 +39,9 @@ static int ocp2scp_remove_devices(struct device *dev, void *c)
 static int omap_ocp2scp_probe(struct platform_device *pdev)
 {
        int ret;
+       u32 reg;
+       void __iomem *regs;
+       struct resource *res;
        struct device_node *np = pdev->dev.of_node;
 
        if (np) {
@@ -47,6 +54,32 @@ static int omap_ocp2scp_probe(struct platform_device *pdev)
        }
 
        pm_runtime_enable(&pdev->dev);
+       /*
+        * As per AM572x TRM: http://www.ti.com/lit/ug/spruhz6/spruhz6.pdf
+        * under section 26.3.2.2, table 26-26 OCP2SCP TIMING Caution;
+        * As per OMAP4430 TRM: http://www.ti.com/lit/ug/swpu231ap/swpu231ap.pdf
+        * under section 23.12.6.2.2 , Table 23-1213 OCP2SCP TIMING Caution;
+        * As per OMAP4460 TRM: http://www.ti.com/lit/ug/swpu235ab/swpu235ab.pdf
+        * under section 23.12.6.2.2, Table 23-1213 OCP2SCP TIMING Caution;
+        * As per OMAP543x TRM http://www.ti.com/lit/pdf/swpu249
+        * under section 27.3.2.2, Table 27-27 OCP2SCP TIMING Caution;
+        *
+        * Read path of OCP2SCP is not working properly due to low reset value
+        * of SYNC2 parameter in OCP2SCP. Suggested reset value is 0x6 or more.
+        */
+       if (!of_device_is_compatible(np, "ti,am437x-ocp2scp")) {
+               res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+               regs = devm_ioremap_resource(&pdev->dev, res);
+               if (IS_ERR(regs))
+                       goto err0;
+
+               pm_runtime_get_sync(&pdev->dev);
+               reg = readl_relaxed(regs + OCP2SCP_TIMING);
+               reg &= ~(SYNC2_MASK);
+               reg |= 0x6;
+               writel_relaxed(reg, regs + OCP2SCP_TIMING);
+               pm_runtime_put_sync(&pdev->dev);
+       }
 
        return 0;
 
@@ -67,6 +100,7 @@ static int omap_ocp2scp_remove(struct platform_device *pdev)
 #ifdef CONFIG_OF
 static const struct of_device_id omap_ocp2scp_id_table[] = {
        { .compatible = "ti,omap-ocp2scp" },
+       { .compatible = "ti,am437x-ocp2scp" },
        {}
 };
 MODULE_DEVICE_TABLE(of, omap_ocp2scp_id_table);
diff --git a/drivers/bus/simple-pm-bus.c b/drivers/bus/simple-pm-bus.c
new file mode 100644 (file)
index 0000000..c5eb46c
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Simple Power-Managed Bus Driver
+ *
+ * Copyright (C) 2014-2015 Glider bvba
+ *
+ * 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/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+
+
+static int simple_pm_bus_probe(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+
+       dev_dbg(&pdev->dev, "%s\n", __func__);
+
+       pm_runtime_enable(&pdev->dev);
+
+       if (np)
+               of_platform_populate(np, NULL, NULL, &pdev->dev);
+
+       return 0;
+}
+
+static int simple_pm_bus_remove(struct platform_device *pdev)
+{
+       dev_dbg(&pdev->dev, "%s\n", __func__);
+
+       pm_runtime_disable(&pdev->dev);
+       return 0;
+}
+
+static const struct of_device_id simple_pm_bus_of_match[] = {
+       { .compatible = "simple-pm-bus", },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, simple_pm_bus_of_match);
+
+static struct platform_driver simple_pm_bus_driver = {
+       .probe = simple_pm_bus_probe,
+       .remove = simple_pm_bus_remove,
+       .driver = {
+               .name = "simple-pm-bus",
+               .of_match_table = simple_pm_bus_of_match,
+       },
+};
+
+module_platform_driver(simple_pm_bus_driver);
+
+MODULE_DESCRIPTION("Simple Power-Managed Bus Driver");
+MODULE_AUTHOR("Geert Uytterhoeven <geert+renesas@glider.be>");
+MODULE_LICENSE("GPL v2");
index d1494ecd9e116490dd5c5875387be7e6a2a92fde..4b31f1387f37fa9cbe8f09afc682df62aedab384 100644 (file)
@@ -57,7 +57,7 @@ static void bcm63xx_rng_cleanup(struct hwrng *rng)
        val &= ~RNG_EN;
        __raw_writel(val, priv->regs + RNG_CTRL);
 
-       clk_didsable_unprepare(prov->clk);
+       clk_disable_unprepare(priv->clk);
 }
 
 static int bcm63xx_rng_data_present(struct hwrng *rng, int wait)
@@ -97,14 +97,14 @@ static int bcm63xx_rng_probe(struct platform_device *pdev)
        priv->rng.name = pdev->name;
        priv->rng.init = bcm63xx_rng_init;
        priv->rng.cleanup = bcm63xx_rng_cleanup;
-       prov->rng.data_present = bcm63xx_rng_data_present;
+       priv->rng.data_present = bcm63xx_rng_data_present;
        priv->rng.data_read = bcm63xx_rng_data_read;
 
        priv->clk = devm_clk_get(&pdev->dev, "ipsec");
        if (IS_ERR(priv->clk)) {
-               error = PTR_ERR(priv->clk);
-               dev_err(&pdev->dev, "no clock for device: %d\n", error);
-               return error;
+               ret = PTR_ERR(priv->clk);
+               dev_err(&pdev->dev, "no clock for device: %d\n", ret);
+               return ret;
        }
 
        if (!devm_request_mem_region(&pdev->dev, r->start,
@@ -120,11 +120,11 @@ static int bcm63xx_rng_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
 
-       error = devm_hwrng_register(&pdev->dev, &priv->rng);
-       if (error) {
+       ret = devm_hwrng_register(&pdev->dev, &priv->rng);
+       if (ret) {
                dev_err(&pdev->dev, "failed to register rng device: %d\n",
-                       error);
-               return error;
+                       ret);
+               return ret;
        }
 
        dev_info(&pdev->dev, "registered RNG driver\n");
index 571ef61f8ea94eb36bd34b4ab459b4c3435f5247..da8faf78536a3ae01827a2ee9480c486a04297a5 100644 (file)
@@ -300,11 +300,14 @@ static const struct file_operations rng_chrdev_ops = {
        .llseek         = noop_llseek,
 };
 
+static const struct attribute_group *rng_dev_groups[];
+
 static struct miscdevice rng_miscdev = {
        .minor          = RNG_MISCDEV_MINOR,
        .name           = RNG_MODULE_NAME,
        .nodename       = "hwrng",
        .fops           = &rng_chrdev_ops,
+       .groups         = rng_dev_groups,
 };
 
 
@@ -377,37 +380,22 @@ static DEVICE_ATTR(rng_available, S_IRUGO,
                   hwrng_attr_available_show,
                   NULL);
 
+static struct attribute *rng_dev_attrs[] = {
+       &dev_attr_rng_current.attr,
+       &dev_attr_rng_available.attr,
+       NULL
+};
+
+ATTRIBUTE_GROUPS(rng_dev);
 
 static void __exit unregister_miscdev(void)
 {
-       device_remove_file(rng_miscdev.this_device, &dev_attr_rng_available);
-       device_remove_file(rng_miscdev.this_device, &dev_attr_rng_current);
        misc_deregister(&rng_miscdev);
 }
 
 static int __init register_miscdev(void)
 {
-       int err;
-
-       err = misc_register(&rng_miscdev);
-       if (err)
-               goto out;
-       err = device_create_file(rng_miscdev.this_device,
-                                &dev_attr_rng_current);
-       if (err)
-               goto err_misc_dereg;
-       err = device_create_file(rng_miscdev.this_device,
-                                &dev_attr_rng_available);
-       if (err)
-               goto err_remove_current;
-out:
-       return err;
-
-err_remove_current:
-       device_remove_file(rng_miscdev.this_device, &dev_attr_rng_current);
-err_misc_dereg:
-       misc_deregister(&rng_miscdev);
-       goto out;
+       return misc_register(&rng_miscdev);
 }
 
 static int hwrng_fillfn(void *unused)
index 3eb7bdd7f93bc31f39e70e7416b8ae85a46c7590..51cb1d5cc489773072edcaf637091172c55ef1fe 100644 (file)
@@ -133,7 +133,7 @@ static int rng_remove(struct platform_device *dev)
        return 0;
 }
 
-static struct of_device_id rng_match[] = {
+static const struct of_device_id rng_match[] = {
        { .compatible      = "1682m-rng", },
        { .compatible      = "pasemi,pwrficient-rng", },
        { },
index 3f4f63204560f932a5160b8d403baa51dac9b4bf..263a5bb8e605a729a7e68fa056f43d377fd69d41 100644 (file)
@@ -61,7 +61,7 @@ static int powernv_rng_probe(struct platform_device *pdev)
        return 0;
 }
 
-static struct of_device_id powernv_rng_match[] = {
+static const struct of_device_id powernv_rng_match[] = {
        { .compatible   = "ibm,power-rng",},
        {},
 };
index c85d31a5f9e3f57acff8ca95338e15a2f6ab5419..b2cfda0fa93e28535772cd67237ee681885d274f 100644 (file)
@@ -123,7 +123,7 @@ static int ppc4xx_rng_remove(struct platform_device *dev)
        return 0;
 }
 
-static struct of_device_id ppc4xx_rng_match[] = {
+static const struct of_device_id ppc4xx_rng_match[] = {
        { .compatible = "ppc4xx-rng", },
        { .compatible = "amcc,ppc460ex-rng", },
        { .compatible = "amcc,ppc440epx-rng", },
index 24cc4ed9a78014509371815cbe0dfda3ef5ca679..a43048b5b05fde621b836a8ef444c381313ce3c8 100644 (file)
@@ -510,13 +510,15 @@ static int i8k_proc_show(struct seq_file *seq, void *offset)
         * 9)  AC power
         * 10) Fn Key status
         */
-       return seq_printf(seq, "%s %s %s %d %d %d %d %d %d %d\n",
-                         I8K_PROC_FMT,
-                         bios_version,
-                         i8k_get_dmi_data(DMI_PRODUCT_SERIAL),
-                         cpu_temp,
-                         left_fan, right_fan, left_speed, right_speed,
-                         ac_power, fn_key);
+       seq_printf(seq, "%s %s %s %d %d %d %d %d %d %d\n",
+                  I8K_PROC_FMT,
+                  bios_version,
+                  i8k_get_dmi_data(DMI_PRODUCT_SERIAL),
+                  cpu_temp,
+                  left_fan, right_fan, left_speed, right_speed,
+                  ac_power, fn_key);
+
+       return 0;
 }
 
 static int i8k_open_fs(struct inode *inode, struct file *file)
index 9bb592872532b1853efb00930c001e54df5fa7ed..bf75f63617731595d958765b7c1582f79452f3cb 100644 (file)
@@ -2000,7 +2000,7 @@ static int smi_ipmb_proc_show(struct seq_file *m, void *v)
                seq_printf(m, " %x", intf->channels[i].address);
        seq_putc(m, '\n');
 
-       return seq_has_overflowed(m);
+       return 0;
 }
 
 static int smi_ipmb_proc_open(struct inode *inode, struct file *file)
@@ -2023,7 +2023,7 @@ static int smi_version_proc_show(struct seq_file *m, void *v)
                   ipmi_version_major(&intf->bmc->id),
                   ipmi_version_minor(&intf->bmc->id));
 
-       return seq_has_overflowed(m);
+       return 0;
 }
 
 static int smi_version_proc_open(struct inode *inode, struct file *file)
index 518585c1ce94626b1142f83bd0697afef9c05438..8a45e92ff60c7483349cf1819b9d0ebc576ebd44 100644 (file)
@@ -942,8 +942,7 @@ static void sender(void                *send_info,
                 * If we are running to completion, start it and run
                 * transactions until everything is clear.
                 */
-               smi_info->curr_msg = msg;
-               smi_info->waiting_msg = NULL;
+               smi_info->waiting_msg = msg;
 
                /*
                 * Run to completion means we are single-threaded, no
@@ -2244,7 +2243,7 @@ static int ipmi_pnp_probe(struct pnp_dev *dev,
        acpi_handle handle;
        acpi_status status;
        unsigned long long tmp;
-       int rv;
+       int rv = -EINVAL;
 
        acpi_dev = pnp_acpi_device(dev);
        if (!acpi_dev)
@@ -2262,8 +2261,10 @@ static int ipmi_pnp_probe(struct pnp_dev *dev,
 
        /* _IFT tells us the interface type: KCS, BT, etc */
        status = acpi_evaluate_integer(handle, "_IFT", NULL, &tmp);
-       if (ACPI_FAILURE(status))
+       if (ACPI_FAILURE(status)) {
+               dev_err(&dev->dev, "Could not find ACPI IPMI interface type\n");
                goto err_free;
+       }
 
        switch (tmp) {
        case 1:
@@ -2276,6 +2277,7 @@ static int ipmi_pnp_probe(struct pnp_dev *dev,
                info->si_type = SI_BT;
                break;
        case 4: /* SSIF, just ignore */
+               rv = -ENODEV;
                goto err_free;
        default:
                dev_info(&dev->dev, "unknown IPMI type %lld\n", tmp);
@@ -2336,7 +2338,7 @@ static int ipmi_pnp_probe(struct pnp_dev *dev,
 
 err_free:
        kfree(info);
-       return -EINVAL;
+       return rv;
 }
 
 static void ipmi_pnp_remove(struct pnp_dev *dev)
@@ -2667,7 +2669,7 @@ static struct pci_driver ipmi_pci_driver = {
 };
 #endif /* CONFIG_PCI */
 
-static struct of_device_id ipmi_match[];
+static const struct of_device_id ipmi_match[];
 static int ipmi_probe(struct platform_device *dev)
 {
 #ifdef CONFIG_OF
@@ -2764,7 +2766,7 @@ static int ipmi_remove(struct platform_device *dev)
        return 0;
 }
 
-static struct of_device_id ipmi_match[] =
+static const struct of_device_id ipmi_match[] =
 {
        { .type = "ipmi", .compatible = "ipmi-kcs",
          .data = (void *)(unsigned long) SI_KCS },
@@ -3080,7 +3082,7 @@ static int smi_type_proc_show(struct seq_file *m, void *v)
 
        seq_printf(m, "%s\n", si_to_str[smi->si_type]);
 
-       return seq_has_overflowed(m);
+       return 0;
 }
 
 static int smi_type_proc_open(struct inode *inode, struct file *file)
@@ -3153,7 +3155,7 @@ static int smi_params_proc_show(struct seq_file *m, void *v)
                   smi->irq,
                   smi->slave_addr);
 
-       return seq_has_overflowed(m);
+       return 0;
 }
 
 static int smi_params_proc_open(struct inode *inode, struct file *file)
index f40e3bd2c69c265400f1241900be8dddd26b51e8..207689c444a8155540b72280b9c402c027ac361b 100644 (file)
@@ -31,7 +31,6 @@
  * interface into the I2C driver, I believe.
  */
 
-#include <linux/version.h>
 #if defined(MODVERSIONS)
 #include <linux/modversions.h>
 #endif
@@ -166,6 +165,9 @@ enum ssif_stat_indexes {
        /* Number of watchdog pretimeouts. */
        SSIF_STAT_watchdog_pretimeouts,
 
+       /* Number of alers received. */
+       SSIF_STAT_alerts,
+
        /* Always add statistics before this value, it must be last. */
        SSIF_NUM_STATS
 };
@@ -214,7 +216,16 @@ struct ssif_info {
 #define WDT_PRE_TIMEOUT_INT    0x08
        unsigned char       msg_flags;
 
+       u8                  global_enables;
        bool                has_event_buffer;
+       bool                supports_alert;
+
+       /*
+        * Used to tell what we should do with alerts.  If we are
+        * waiting on a response, read the data immediately.
+        */
+       bool                got_alert;
+       bool                waiting_alert;
 
        /*
         * If set to true, this will request events the next time the
@@ -478,13 +489,13 @@ static int ipmi_ssif_thread(void *data)
 
                if (ssif_info->i2c_read_write == I2C_SMBUS_WRITE) {
                        result = i2c_smbus_write_block_data(
-                               ssif_info->client, SSIF_IPMI_REQUEST,
+                               ssif_info->client, ssif_info->i2c_command,
                                ssif_info->i2c_data[0],
                                ssif_info->i2c_data + 1);
                        ssif_info->done_handler(ssif_info, result, NULL, 0);
                } else {
                        result = i2c_smbus_read_block_data(
-                               ssif_info->client, SSIF_IPMI_RESPONSE,
+                               ssif_info->client, ssif_info->i2c_command,
                                ssif_info->i2c_data);
                        if (result < 0)
                                ssif_info->done_handler(ssif_info, result,
@@ -518,15 +529,12 @@ static int ssif_i2c_send(struct ssif_info *ssif_info,
 static void msg_done_handler(struct ssif_info *ssif_info, int result,
                             unsigned char *data, unsigned int len);
 
-static void retry_timeout(unsigned long data)
+static void start_get(struct ssif_info *ssif_info)
 {
-       struct ssif_info *ssif_info = (void *) data;
        int rv;
 
-       if (ssif_info->stopping)
-               return;
-
        ssif_info->rtc_us_timer = 0;
+       ssif_info->multi_pos = 0;
 
        rv = ssif_i2c_send(ssif_info, msg_done_handler, I2C_SMBUS_READ,
                          SSIF_IPMI_RESPONSE,
@@ -540,6 +548,46 @@ static void retry_timeout(unsigned long data)
        }
 }
 
+static void retry_timeout(unsigned long data)
+{
+       struct ssif_info *ssif_info = (void *) data;
+       unsigned long oflags, *flags;
+       bool waiting;
+
+       if (ssif_info->stopping)
+               return;
+
+       flags = ipmi_ssif_lock_cond(ssif_info, &oflags);
+       waiting = ssif_info->waiting_alert;
+       ssif_info->waiting_alert = false;
+       ipmi_ssif_unlock_cond(ssif_info, flags);
+
+       if (waiting)
+               start_get(ssif_info);
+}
+
+
+static void ssif_alert(struct i2c_client *client, unsigned int data)
+{
+       struct ssif_info *ssif_info = i2c_get_clientdata(client);
+       unsigned long oflags, *flags;
+       bool do_get = false;
+
+       ssif_inc_stat(ssif_info, alerts);
+
+       flags = ipmi_ssif_lock_cond(ssif_info, &oflags);
+       if (ssif_info->waiting_alert) {
+               ssif_info->waiting_alert = false;
+               del_timer(&ssif_info->retry_timer);
+               do_get = true;
+       } else if (ssif_info->curr_msg) {
+               ssif_info->got_alert = true;
+       }
+       ipmi_ssif_unlock_cond(ssif_info, flags);
+       if (do_get)
+               start_get(ssif_info);
+}
+
 static int start_resend(struct ssif_info *ssif_info);
 
 static void msg_done_handler(struct ssif_info *ssif_info, int result,
@@ -559,9 +607,12 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
                if (ssif_info->retries_left > 0) {
                        ssif_inc_stat(ssif_info, receive_retries);
 
+                       flags = ipmi_ssif_lock_cond(ssif_info, &oflags);
+                       ssif_info->waiting_alert = true;
+                       ssif_info->rtc_us_timer = SSIF_MSG_USEC;
                        mod_timer(&ssif_info->retry_timer,
                                  jiffies + SSIF_MSG_JIFFIES);
-                       ssif_info->rtc_us_timer = SSIF_MSG_USEC;
+                       ipmi_ssif_unlock_cond(ssif_info, flags);
                        return;
                }
 
@@ -581,9 +632,9 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
                ssif_inc_stat(ssif_info, received_message_parts);
 
                /* Remove the multi-part read marker. */
-               for (i = 0; i < (len-2); i++)
-                       ssif_info->data[i] = data[i+2];
                len -= 2;
+               for (i = 0; i < len; i++)
+                       ssif_info->data[i] = data[i+2];
                ssif_info->multi_len = len;
                ssif_info->multi_pos = 1;
 
@@ -610,9 +661,9 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
                        goto continue_op;
                }
 
-               blocknum = data[ssif_info->multi_len];
+               blocknum = data[0];
 
-               if (ssif_info->multi_len+len-1 > IPMI_MAX_MSG_LENGTH) {
+               if (ssif_info->multi_len + len - 1 > IPMI_MAX_MSG_LENGTH) {
                        /* Received message too big, abort the operation. */
                        result = -E2BIG;
                        if (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
@@ -622,15 +673,15 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
                }
 
                /* Remove the blocknum from the data. */
-               for (i = 0; i < (len-1); i++)
-                       ssif_info->data[i+ssif_info->multi_len] = data[i+1];
                len--;
+               for (i = 0; i < len; i++)
+                       ssif_info->data[i + ssif_info->multi_len] = data[i + 1];
                ssif_info->multi_len += len;
                if (blocknum == 0xff) {
                        /* End of read */
                        len = ssif_info->multi_len;
                        data = ssif_info->data;
-               } else if ((blocknum+1) != ssif_info->multi_pos) {
+               } else if (blocknum + 1 != ssif_info->multi_pos) {
                        /*
                         * Out of sequence block, just abort.  Block
                         * numbers start at zero for the second block,
@@ -650,7 +701,7 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
                        if (rv < 0) {
                                if (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
                                        pr_info(PFX
-                                               "Error from i2c_non_blocking_op(2)\n");
+                                               "Error from ssif_i2c_send\n");
 
                                result = -EIO;
                        } else
@@ -830,7 +881,11 @@ static void msg_written_handler(struct ssif_info *ssif_info, int result,
        }
 
        if (ssif_info->multi_data) {
-               /* In the middle of a multi-data write. */
+               /*
+                * In the middle of a multi-data write.  See the comment
+                * in the SSIF_MULTI_n_PART case in the probe function
+                * for details on the intricacies of this.
+                */
                int left;
 
                ssif_inc_stat(ssif_info, sent_messages_parts);
@@ -864,15 +919,32 @@ static void msg_written_handler(struct ssif_info *ssif_info, int result,
                        msg_done_handler(ssif_info, -EIO, NULL, 0);
                }
        } else {
+               unsigned long oflags, *flags;
+               bool got_alert;
+
                ssif_inc_stat(ssif_info, sent_messages);
                ssif_inc_stat(ssif_info, sent_messages_parts);
 
-               /* Wait a jiffie then request the next message */
-               ssif_info->retries_left = SSIF_RECV_RETRIES;
-               ssif_info->rtc_us_timer = SSIF_MSG_PART_USEC;
-               mod_timer(&ssif_info->retry_timer,
-                         jiffies + SSIF_MSG_PART_JIFFIES);
-               return;
+               flags = ipmi_ssif_lock_cond(ssif_info, &oflags);
+               got_alert = ssif_info->got_alert;
+               if (got_alert) {
+                       ssif_info->got_alert = false;
+                       ssif_info->waiting_alert = false;
+               }
+
+               if (got_alert) {
+                       ipmi_ssif_unlock_cond(ssif_info, flags);
+                       /* The alert already happened, try now. */
+                       retry_timeout((unsigned long) ssif_info);
+               } else {
+                       /* Wait a jiffie then request the next message */
+                       ssif_info->waiting_alert = true;
+                       ssif_info->retries_left = SSIF_RECV_RETRIES;
+                       ssif_info->rtc_us_timer = SSIF_MSG_PART_USEC;
+                       mod_timer(&ssif_info->retry_timer,
+                                 jiffies + SSIF_MSG_PART_JIFFIES);
+                       ipmi_ssif_unlock_cond(ssif_info, flags);
+               }
        }
 }
 
@@ -881,6 +953,8 @@ static int start_resend(struct ssif_info *ssif_info)
        int rv;
        int command;
 
+       ssif_info->got_alert = false;
+
        if (ssif_info->data_len > 32) {
                command = SSIF_IPMI_MULTI_PART_REQUEST_START;
                ssif_info->multi_data = ssif_info->data;
@@ -915,7 +989,7 @@ static int start_send(struct ssif_info *ssif_info,
                return -E2BIG;
 
        ssif_info->retries_left = SSIF_SEND_RETRIES;
-       memcpy(ssif_info->data+1, data, len);
+       memcpy(ssif_info->data + 1, data, len);
        ssif_info->data_len = len;
        return start_resend(ssif_info);
 }
@@ -1200,7 +1274,7 @@ static int smi_type_proc_show(struct seq_file *m, void *v)
 {
        seq_puts(m, "ssif\n");
 
-       return seq_has_overflowed(m);
+       return 0;
 }
 
 static int smi_type_proc_open(struct inode *inode, struct file *file)
@@ -1243,6 +1317,8 @@ static int smi_stats_proc_show(struct seq_file *m, void *v)
                   ssif_get_stat(ssif_info, events));
        seq_printf(m, "watchdog_pretimeouts:   %u\n",
                   ssif_get_stat(ssif_info, watchdog_pretimeouts));
+       seq_printf(m, "alerts:                 %u\n",
+                  ssif_get_stat(ssif_info, alerts));
        return 0;
 }
 
@@ -1258,6 +1334,23 @@ static const struct file_operations smi_stats_proc_ops = {
        .release        = single_release,
 };
 
+static int strcmp_nospace(char *s1, char *s2)
+{
+       while (*s1 && *s2) {
+               while (isspace(*s1))
+                       s1++;
+               while (isspace(*s2))
+                       s2++;
+               if (*s1 > *s2)
+                       return 1;
+               if (*s1 < *s2)
+                       return -1;
+               s1++;
+               s2++;
+       }
+       return 0;
+}
+
 static struct ssif_addr_info *ssif_info_find(unsigned short addr,
                                             char *adapter_name,
                                             bool match_null_name)
@@ -1272,8 +1365,10 @@ restart:
                                        /* One is NULL and one is not */
                                        continue;
                                }
-                               if (strcmp(info->adapter_name, adapter_name))
-                                       /* Names to not match */
+                               if (adapter_name &&
+                                   strcmp_nospace(info->adapter_name,
+                                                  adapter_name))
+                                       /* Names do not match */
                                        continue;
                        }
                        found = info;
@@ -1306,6 +1401,12 @@ static bool check_acpi(struct ssif_info *ssif_info, struct device *dev)
        return false;
 }
 
+/*
+ * Global enables we care about.
+ */
+#define GLOBAL_ENABLES_MASK (IPMI_BMC_EVT_MSG_BUFF | IPMI_BMC_RCV_MSG_INTR | \
+                            IPMI_BMC_EVT_MSG_INTR)
+
 static int ssif_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
        unsigned char     msg[3];
@@ -1391,13 +1492,33 @@ static int ssif_probe(struct i2c_client *client, const struct i2c_device_id *id)
                        break;
 
                case SSIF_MULTI_2_PART:
-                       if (ssif_info->max_xmit_msg_size > 64)
-                               ssif_info->max_xmit_msg_size = 64;
+                       if (ssif_info->max_xmit_msg_size > 63)
+                               ssif_info->max_xmit_msg_size = 63;
                        if (ssif_info->max_recv_msg_size > 62)
                                ssif_info->max_recv_msg_size = 62;
                        break;
 
                case SSIF_MULTI_n_PART:
+                       /*
+                        * The specification is rather confusing at
+                        * this point, but I think I understand what
+                        * is meant.  At least I have a workable
+                        * solution.  With multi-part messages, you
+                        * cannot send a message that is a multiple of
+                        * 32-bytes in length, because the start and
+                        * middle messages are 32-bytes and the end
+                        * message must be at least one byte.  You
+                        * can't fudge on an extra byte, that would
+                        * screw up things like fru data writes.  So
+                        * we limit the length to 63 bytes.  That way
+                        * a 32-byte message gets sent as a single
+                        * part.  A larger message will be a 32-byte
+                        * start and the next message is always going
+                        * to be 1-31 bytes in length.  Not ideal, but
+                        * it should work.
+                        */
+                       if (ssif_info->max_xmit_msg_size > 63)
+                               ssif_info->max_xmit_msg_size = 63;
                        break;
 
                default:
@@ -1407,7 +1528,7 @@ static int ssif_probe(struct i2c_client *client, const struct i2c_device_id *id)
        } else {
  no_support:
                /* Assume no multi-part or PEC support */
-               pr_info(PFX "Error fetching SSIF: %d %d %2.2x, your system probably doesn't support this command so  using defaults\n",
+               pr_info(PFX "Error fetching SSIF: %d %d %2.2x, your system probably doesn't support this command so using defaults\n",
                       rv, len, resp[2]);
 
                ssif_info->max_xmit_msg_size = 32;
@@ -1436,6 +1557,8 @@ static int ssif_probe(struct i2c_client *client, const struct i2c_device_id *id)
                goto found;
        }
 
+       ssif_info->global_enables = resp[3];
+
        if (resp[3] & IPMI_BMC_EVT_MSG_BUFF) {
                ssif_info->has_event_buffer = true;
                /* buffer is already enabled, nothing to do. */
@@ -1444,18 +1567,37 @@ static int ssif_probe(struct i2c_client *client, const struct i2c_device_id *id)
 
        msg[0] = IPMI_NETFN_APP_REQUEST << 2;
        msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD;
-       msg[2] = resp[3] | IPMI_BMC_EVT_MSG_BUFF;
+       msg[2] = ssif_info->global_enables | IPMI_BMC_EVT_MSG_BUFF;
        rv = do_cmd(client, 3, msg, &len, resp);
        if (rv || (len < 2)) {
-               pr_warn(PFX "Error getting global enables: %d %d %2.2x\n",
+               pr_warn(PFX "Error setting global enables: %d %d %2.2x\n",
                        rv, len, resp[2]);
                rv = 0; /* Not fatal */
                goto found;
        }
 
-       if (resp[2] == 0)
+       if (resp[2] == 0) {
                /* A successful return means the event buffer is supported. */
                ssif_info->has_event_buffer = true;
+               ssif_info->global_enables |= IPMI_BMC_EVT_MSG_BUFF;
+       }
+
+       msg[0] = IPMI_NETFN_APP_REQUEST << 2;
+       msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD;
+       msg[2] = ssif_info->global_enables | IPMI_BMC_RCV_MSG_INTR;
+       rv = do_cmd(client, 3, msg, &len, resp);
+       if (rv || (len < 2)) {
+               pr_warn(PFX "Error setting global enables: %d %d %2.2x\n",
+                       rv, len, resp[2]);
+               rv = 0; /* Not fatal */
+               goto found;
+       }
+
+       if (resp[2] == 0) {
+               /* A successful return means the alert is supported. */
+               ssif_info->supports_alert = true;
+               ssif_info->global_enables |= IPMI_BMC_RCV_MSG_INTR;
+       }
 
  found:
        ssif_info->intf_num = atomic_inc_return(&next_intf);
@@ -1813,6 +1955,7 @@ static struct i2c_driver ssif_i2c_driver = {
        },
        .probe          = ssif_probe,
        .remove         = ssif_remove,
+       .alert          = ssif_alert,
        .id_table       = ssif_id,
        .detect         = ssif_detect
 };
@@ -1832,7 +1975,7 @@ static int init_ipmi_ssif(void)
                rv = new_ssif_client(addr[i], adapter_name[i],
                                     dbg[i], slave_addrs[i],
                                     SI_HARDCODED);
-               if (!rv)
+               if (rv)
                        pr_err(PFX
                               "Couldn't add hardcoded device at addr 0x%x\n",
                               addr[i]);
index ffa97d261cf3322615bc403931d99c71d1896a50..9fd5a91e0d81e4f5f2ec2abe714ca0d0ef88972c 100644 (file)
@@ -140,12 +140,17 @@ static int misc_open(struct inode * inode, struct file * file)
                        goto fail;
        }
 
+       /*
+        * Place the miscdevice in the file's
+        * private_data so it can be used by the
+        * file operations, including f_op->open below
+        */
+       file->private_data = c;
+
        err = 0;
        replace_fops(file, new_fops);
-       if (file->f_op->open) {
-               file->private_data = c;
+       if (file->f_op->open)
                err = file->f_op->open(inode,file);
-       }
 fail:
        mutex_unlock(&misc_mtx);
        return err;
@@ -169,7 +174,9 @@ static const struct file_operations misc_fops = {
  *     the minor number requested is used.
  *
  *     The structure passed is linked into the kernel and may not be
- *     destroyed until it has been unregistered.
+ *     destroyed until it has been unregistered. By default, an open()
+ *     syscall to the device sets file->private_data to point to the
+ *     structure. Drivers don't need open in fops for this.
  *
  *     A zero is returned on success and a negative errno code for
  *     failure.
@@ -205,8 +212,9 @@ int misc_register(struct miscdevice * misc)
 
        dev = MKDEV(MISC_MAJOR, misc->minor);
 
-       misc->this_device = device_create(misc_class, misc->parent, dev,
-                                         misc, "%s", misc->name);
+       misc->this_device =
+               device_create_with_groups(misc_class, misc->parent, dev,
+                                         misc, misc->groups, "%s", misc->name);
        if (IS_ERR(misc->this_device)) {
                int i = DYNAMIC_MINORS - misc->minor - 1;
                if (i < DYNAMIC_MINORS && i >= 0)
index 72d7028f779b55801795ef0fe49d9dda8cde7970..50754d2033100851b87f78d06401a3c5c137262d 100644 (file)
@@ -355,7 +355,7 @@ static inline bool use_multiport(struct ports_device *portdev)
         * early_init
         */
        if (!portdev->vdev)
-               return 0;
+               return false;
        return __virtio_test_bit(portdev->vdev, VIRTIO_CONSOLE_F_MULTIPORT);
 }
 
index b827fa095f1b324231e3916bc2e22f2315ec8bbf..77d6c127e691a4a8a6417bd4cd0760fed0d513e8 100644 (file)
@@ -1237,6 +1237,8 @@ static ssize_t xillybus_write(struct file *filp, const char __user *userbuf,
                                        unsigned char *tail;
                                        int i;
 
+                                       howmany = 0;
+
                                        end_offset_plus1 = bufpos >>
                                                channel->log2_element_size;
 
index 2002a3a28146985f911b449fb7da72a4cbbec9fd..781865084dc17444d74d39fb87d5aa5c9099988d 100644 (file)
@@ -31,7 +31,7 @@ MODULE_LICENSE("GPL v2");
 static const char xillyname[] = "xillybus_of";
 
 /* Match table for of_platform binding */
-static struct of_device_id xillybus_of_match[] = {
+static const struct of_device_id xillybus_of_match[] = {
        { .compatible = "xillybus,xillybus-1.00.a", },
        { .compatible = "xlnx,xillybus-1.00.a", }, /* Deprecated */
        {}
index 0b474a04730fe4d2c588cb1a3a1818dbff61f995..9897f353bf1a63f24a0192aeff7ea9785a7c32bf 100644 (file)
@@ -130,6 +130,13 @@ config COMMON_CLK_PALMAS
          This driver supports TI Palmas devices 32KHz output KG and KG_AUDIO
          using common clock framework.
 
+config COMMON_CLK_PWM
+       tristate "Clock driver for PWMs used as clock outputs"
+       depends on PWM
+       ---help---
+         Adapter driver so that any PWM output can be (mis)used as clock signal
+         at 50% duty cycle.
+
 config COMMON_CLK_PXA
        def_bool COMMON_CLK && ARCH_PXA
        ---help---
index e43ff53f85a664802d3dd62d364b72ae569d9549..3d00c25382c53b02e9d461437aa38c5eea77b090 100644 (file)
@@ -28,6 +28,7 @@ obj-$(CONFIG_MACH_LOONGSON1)          += clk-ls1x.o
 obj-$(CONFIG_COMMON_CLK_MAX_GEN)       += clk-max-gen.o
 obj-$(CONFIG_COMMON_CLK_MAX77686)      += clk-max77686.o
 obj-$(CONFIG_COMMON_CLK_MAX77802)      += clk-max77802.o
+obj-$(CONFIG_ARCH_MB86S7X)             += clk-mb86s7x.o
 obj-$(CONFIG_ARCH_MOXART)              += clk-moxart.o
 obj-$(CONFIG_ARCH_NOMADIK)             += clk-nomadik.o
 obj-$(CONFIG_ARCH_NSPIRE)              += clk-nspire.o
@@ -42,6 +43,7 @@ obj-$(CONFIG_ARCH_U300)                       += clk-u300.o
 obj-$(CONFIG_ARCH_VT8500)              += clk-vt8500.o
 obj-$(CONFIG_COMMON_CLK_WM831X)                += clk-wm831x.o
 obj-$(CONFIG_COMMON_CLK_XGENE)         += clk-xgene.o
+obj-$(CONFIG_COMMON_CLK_PWM)           += clk-pwm.o
 obj-$(CONFIG_COMMON_CLK_AT91)          += at91/
 obj-$(CONFIG_ARCH_BCM_MOBILE)          += bcm/
 obj-$(CONFIG_ARCH_BERLIN)              += berlin/
index a23ac0c724f014643e66bc2485f7c79cef523920..0b7c3e8840bae0ebf2c97cf276e44e8ab7116f6e 100644 (file)
@@ -56,22 +56,55 @@ static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk_hw *hw,
        return DIV_ROUND_CLOSEST(parent_rate, (usbdiv + 1));
 }
 
-static long at91sam9x5_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate,
-                                         unsigned long *parent_rate)
+static long at91sam9x5_clk_usb_determine_rate(struct clk_hw *hw,
+                                             unsigned long rate,
+                                             unsigned long min_rate,
+                                             unsigned long max_rate,
+                                             unsigned long *best_parent_rate,
+                                             struct clk_hw **best_parent_hw)
 {
-       unsigned long div;
+       struct clk *parent = NULL;
+       long best_rate = -EINVAL;
+       unsigned long tmp_rate;
+       int best_diff = -1;
+       int tmp_diff;
+       int i;
 
-       if (!rate)
-               return -EINVAL;
+       for (i = 0; i < __clk_get_num_parents(hw->clk); i++) {
+               int div;
 
-       if (rate >= *parent_rate)
-               return *parent_rate;
+               parent = clk_get_parent_by_index(hw->clk, i);
+               if (!parent)
+                       continue;
+
+               for (div = 1; div < SAM9X5_USB_MAX_DIV + 2; div++) {
+                       unsigned long tmp_parent_rate;
+
+                       tmp_parent_rate = rate * div;
+                       tmp_parent_rate = __clk_round_rate(parent,
+                                                          tmp_parent_rate);
+                       tmp_rate = DIV_ROUND_CLOSEST(tmp_parent_rate, div);
+                       if (tmp_rate < rate)
+                               tmp_diff = rate - tmp_rate;
+                       else
+                               tmp_diff = tmp_rate - rate;
+
+                       if (best_diff < 0 || best_diff > tmp_diff) {
+                               best_rate = tmp_rate;
+                               best_diff = tmp_diff;
+                               *best_parent_rate = tmp_parent_rate;
+                               *best_parent_hw = __clk_get_hw(parent);
+                       }
+
+                       if (!best_diff || tmp_rate < rate)
+                               break;
+               }
 
-       div = DIV_ROUND_CLOSEST(*parent_rate, rate);
-       if (div > SAM9X5_USB_MAX_DIV + 1)
-               div = SAM9X5_USB_MAX_DIV + 1;
+               if (!best_diff)
+                       break;
+       }
 
-       return DIV_ROUND_CLOSEST(*parent_rate, div);
+       return best_rate;
 }
 
 static int at91sam9x5_clk_usb_set_parent(struct clk_hw *hw, u8 index)
@@ -121,7 +154,7 @@ static int at91sam9x5_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate,
 
 static const struct clk_ops at91sam9x5_usb_ops = {
        .recalc_rate = at91sam9x5_clk_usb_recalc_rate,
-       .round_rate = at91sam9x5_clk_usb_round_rate,
+       .determine_rate = at91sam9x5_clk_usb_determine_rate,
        .get_parent = at91sam9x5_clk_usb_get_parent,
        .set_parent = at91sam9x5_clk_usb_set_parent,
        .set_rate = at91sam9x5_clk_usb_set_rate,
@@ -159,7 +192,7 @@ static const struct clk_ops at91sam9n12_usb_ops = {
        .disable = at91sam9n12_clk_usb_disable,
        .is_enabled = at91sam9n12_clk_usb_is_enabled,
        .recalc_rate = at91sam9x5_clk_usb_recalc_rate,
-       .round_rate = at91sam9x5_clk_usb_round_rate,
+       .determine_rate = at91sam9x5_clk_usb_determine_rate,
        .set_rate = at91sam9x5_clk_usb_set_rate,
 };
 
@@ -179,7 +212,8 @@ at91sam9x5_clk_register_usb(struct at91_pmc *pmc, const char *name,
        init.ops = &at91sam9x5_usb_ops;
        init.parent_names = parent_names;
        init.num_parents = num_parents;
-       init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
+       init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
+                    CLK_SET_RATE_PARENT;
 
        usb->hw.init = &init;
        usb->pmc = pmc;
@@ -207,7 +241,7 @@ at91sam9n12_clk_register_usb(struct at91_pmc *pmc, const char *name,
        init.ops = &at91sam9n12_usb_ops;
        init.parent_names = &parent_name;
        init.num_parents = 1;
-       init.flags = CLK_SET_RATE_GATE;
+       init.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT;
 
        usb->hw.init = &init;
        usb->pmc = pmc;
index c386ad25beb4af6abbd58e769ee2f165ff28f6d5..b8e4f8a822e9f334d6db9071136903e88699a280 100644 (file)
@@ -58,7 +58,7 @@
 #define CDCE706_CLKOUT_DIVIDER_MASK    0x7
 #define CDCE706_CLKOUT_ENABLE_MASK     0x8
 
-static struct regmap_config cdce706_regmap_config = {
+static const struct regmap_config cdce706_regmap_config = {
        .reg_bits = 8,
        .val_bits = 8,
        .val_format_endian = REGMAP_ENDIAN_NATIVE,
index aad4796aa3ed7e6e10bbe8a066f1e68e70498f80..48a65b2b402785659d25120f6e18d70b478df4fe 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/device.h>
 #include <linux/of.h>
 #include <linux/printk.h>
-#include "clk.h"
 
 static int __set_clk_parents(struct device_node *node, bool clk_supplier)
 {
@@ -39,7 +38,7 @@ static int __set_clk_parents(struct device_node *node, bool clk_supplier)
                }
                if (clkspec.np == node && !clk_supplier)
                        return 0;
-               pclk = of_clk_get_by_clkspec(&clkspec);
+               pclk = of_clk_get_from_provider(&clkspec);
                if (IS_ERR(pclk)) {
                        pr_warn("clk: couldn't get parent clock %d for %s\n",
                                index, node->full_name);
@@ -54,7 +53,7 @@ static int __set_clk_parents(struct device_node *node, bool clk_supplier)
                        rc = 0;
                        goto err;
                }
-               clk = of_clk_get_by_clkspec(&clkspec);
+               clk = of_clk_get_from_provider(&clkspec);
                if (IS_ERR(clk)) {
                        pr_warn("clk: couldn't get parent clock %d for %s\n",
                                index, node->full_name);
@@ -98,7 +97,7 @@ static int __set_clk_rates(struct device_node *node, bool clk_supplier)
                        if (clkspec.np == node && !clk_supplier)
                                return 0;
 
-                       clk = of_clk_get_by_clkspec(&clkspec);
+                       clk = of_clk_get_from_provider(&clkspec);
                        if (IS_ERR(clk)) {
                                pr_warn("clk: couldn't get clock %d for %s\n",
                                        index, node->full_name);
index 82a59d0086cc79d654c4ceaf4aa42a8491467dbc..6aa72d9d79bad43d5c8f79f47fa30134d710a624 100644 (file)
@@ -36,6 +36,9 @@ static unsigned long clk_fd_recalc_rate(struct clk_hw *hw,
        m = (val & fd->mmask) >> fd->mshift;
        n = (val & fd->nmask) >> fd->nshift;
 
+       if (!n || !m)
+               return parent_rate;
+
        ret = (u64)parent_rate * m;
        do_div(ret, n);
 
index 08e43224fd522a876ed8cf736e43f2bc739c930d..a71cabedda93c88d87230c038398413bb48e9c7b 100644 (file)
@@ -65,10 +65,12 @@ EXPORT_SYMBOL_GPL(clk_gpio_gate_ops);
  * @dev: device that is registering this clock
  * @name: name of this clock
  * @parent_name: name of this clock's parent
- * @gpiod: gpio descriptor to gate this clock
+ * @gpio: gpio number to gate this clock
+ * @active_low: true if gpio should be set to 0 to enable clock
+ * @flags: clock flags
  */
 struct clk *clk_register_gpio_gate(struct device *dev, const char *name,
-               const char *parent_name, struct gpio_desc *gpiod,
+               const char *parent_name, unsigned gpio, bool active_low,
                unsigned long flags)
 {
        struct clk_gpio *clk_gpio = NULL;
@@ -77,20 +79,19 @@ struct clk *clk_register_gpio_gate(struct device *dev, const char *name,
        unsigned long gpio_flags;
        int err;
 
-       if (gpiod_is_active_low(gpiod))
-               gpio_flags = GPIOF_OUT_INIT_HIGH;
+       if (active_low)
+               gpio_flags = GPIOF_ACTIVE_LOW | GPIOF_OUT_INIT_HIGH;
        else
                gpio_flags = GPIOF_OUT_INIT_LOW;
 
        if (dev)
-               err = devm_gpio_request_one(dev, desc_to_gpio(gpiod),
-                                           gpio_flags, name);
+               err = devm_gpio_request_one(dev, gpio, gpio_flags, name);
        else
-               err = gpio_request_one(desc_to_gpio(gpiod), gpio_flags, name);
+               err = gpio_request_one(gpio, gpio_flags, name);
 
        if (err) {
                pr_err("%s: %s: Error requesting clock control gpio %u\n",
-                      __func__, name, desc_to_gpio(gpiod));
+                      __func__, name, gpio);
                return ERR_PTR(err);
        }
 
@@ -111,7 +112,7 @@ struct clk *clk_register_gpio_gate(struct device *dev, const char *name,
        init.parent_names = (parent_name ? &parent_name : NULL);
        init.num_parents = (parent_name ? 1 : 0);
 
-       clk_gpio->gpiod = gpiod;
+       clk_gpio->gpiod = gpio_to_desc(gpio);
        clk_gpio->hw.init = &init;
 
        clk = clk_register(dev, &clk_gpio->hw);
@@ -123,7 +124,8 @@ struct clk *clk_register_gpio_gate(struct device *dev, const char *name,
                kfree(clk_gpio);
 
 clk_register_gpio_gate_err:
-       gpiod_put(gpiod);
+       if (!dev)
+               gpio_free(gpio);
 
        return clk;
 }
@@ -149,8 +151,8 @@ static struct clk *of_clk_gpio_gate_delayed_register_get(
        struct clk *clk;
        const char *clk_name = data->node->name;
        const char *parent_name;
-       struct gpio_desc *gpiod;
        int gpio;
+       enum of_gpio_flags of_flags;
 
        mutex_lock(&data->lock);
 
@@ -159,7 +161,8 @@ static struct clk *of_clk_gpio_gate_delayed_register_get(
                return data->clk;
        }
 
-       gpio = of_get_named_gpio_flags(data->node, "enable-gpios", 0, NULL);
+       gpio = of_get_named_gpio_flags(data->node, "enable-gpios", 0,
+                                               &of_flags);
        if (gpio < 0) {
                mutex_unlock(&data->lock);
                if (gpio != -EPROBE_DEFER)
@@ -167,11 +170,11 @@ static struct clk *of_clk_gpio_gate_delayed_register_get(
                               __func__, clk_name);
                return ERR_PTR(gpio);
        }
-       gpiod = gpio_to_desc(gpio);
 
        parent_name = of_clk_get_parent_name(data->node, 0);
 
-       clk = clk_register_gpio_gate(NULL, clk_name, parent_name, gpiod, 0);
+       clk = clk_register_gpio_gate(NULL, clk_name, parent_name, gpio,
+                                       of_flags & OF_GPIO_ACTIVE_LOW, 0);
        if (IS_ERR(clk)) {
                mutex_unlock(&data->lock);
                return clk;
diff --git a/drivers/clk/clk-mb86s7x.c b/drivers/clk/clk-mb86s7x.c
new file mode 100644 (file)
index 0000000..f39c25a
--- /dev/null
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2013-2015 FUJITSU SEMICONDUCTOR LIMITED
+ * Copyright (C) 2015 Linaro 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, 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/clkdev.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/cpu.h>
+#include <linux/clk-provider.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/topology.h>
+#include <linux/mailbox_client.h>
+#include <linux/platform_device.h>
+
+#include <soc/mb86s7x/scb_mhu.h>
+
+#define to_crg_clk(p) container_of(p, struct crg_clk, hw)
+#define to_clc_clk(p) container_of(p, struct cl_clk, hw)
+
+struct mb86s7x_peri_clk {
+       u32 payload_size;
+       u32 cntrlr;
+       u32 domain;
+       u32 port;
+       u32 en;
+       u64 frequency;
+} __packed __aligned(4);
+
+struct hack_rate {
+       unsigned clk_id;
+       unsigned long rate;
+       int gated;
+};
+
+struct crg_clk {
+       struct clk_hw hw;
+       u8 cntrlr, domain, port;
+};
+
+static int crg_gate_control(struct clk_hw *hw, int en)
+{
+       struct crg_clk *crgclk = to_crg_clk(hw);
+       struct mb86s7x_peri_clk cmd;
+       int ret;
+
+       cmd.payload_size = sizeof(cmd);
+       cmd.cntrlr = crgclk->cntrlr;
+       cmd.domain = crgclk->domain;
+       cmd.port = crgclk->port;
+       cmd.en = en;
+
+       /* Port is UngatedCLK */
+       if (cmd.port == 8)
+               return en ? 0 : -EINVAL;
+
+       pr_debug("%s:%d CMD Cntrlr-%u Dom-%u Port-%u En-%u}\n",
+                __func__, __LINE__, cmd.cntrlr,
+                cmd.domain, cmd.port, cmd.en);
+
+       ret = mb86s7x_send_packet(CMD_PERI_CLOCK_GATE_SET_REQ,
+                                 &cmd, sizeof(cmd));
+       if (ret < 0) {
+               pr_err("%s:%d failed!\n", __func__, __LINE__);
+               return ret;
+       }
+
+       pr_debug("%s:%d REP Cntrlr-%u Dom-%u Port-%u En-%u}\n",
+                __func__, __LINE__, cmd.cntrlr,
+                cmd.domain, cmd.port, cmd.en);
+
+       /* If the request was rejected */
+       if (cmd.en != en)
+               ret = -EINVAL;
+       else
+               ret = 0;
+
+       return ret;
+}
+
+static int crg_port_prepare(struct clk_hw *hw)
+{
+       return crg_gate_control(hw, 1);
+}
+
+static void crg_port_unprepare(struct clk_hw *hw)
+{
+       crg_gate_control(hw, 0);
+}
+
+static int
+crg_rate_control(struct clk_hw *hw, int set, unsigned long *rate)
+{
+       struct crg_clk *crgclk = to_crg_clk(hw);
+       struct mb86s7x_peri_clk cmd;
+       int code, ret;
+
+       cmd.payload_size = sizeof(cmd);
+       cmd.cntrlr = crgclk->cntrlr;
+       cmd.domain = crgclk->domain;
+       cmd.port = crgclk->port;
+       cmd.frequency = *rate;
+
+       if (set) {
+               code = CMD_PERI_CLOCK_RATE_SET_REQ;
+               pr_debug("%s:%d CMD Cntrlr-%u Dom-%u Port-%u Rate-SET %lluHz}\n",
+                        __func__, __LINE__, cmd.cntrlr,
+                        cmd.domain, cmd.port, cmd.frequency);
+       } else {
+               code = CMD_PERI_CLOCK_RATE_GET_REQ;
+               pr_debug("%s:%d CMD Cntrlr-%u Dom-%u Port-%u Rate-GET}\n",
+                        __func__, __LINE__, cmd.cntrlr,
+                        cmd.domain, cmd.port);
+       }
+
+       ret = mb86s7x_send_packet(code, &cmd, sizeof(cmd));
+       if (ret < 0) {
+               pr_err("%s:%d failed!\n", __func__, __LINE__);
+               return ret;
+       }
+
+       if (set)
+               pr_debug("%s:%d REP Cntrlr-%u Dom-%u Port-%u Rate-SET %lluHz}\n",
+                        __func__, __LINE__, cmd.cntrlr,
+                        cmd.domain, cmd.port, cmd.frequency);
+       else
+               pr_debug("%s:%d REP Cntrlr-%u Dom-%u Port-%u Rate-GOT %lluHz}\n",
+                        __func__, __LINE__, cmd.cntrlr,
+                        cmd.domain, cmd.port, cmd.frequency);
+
+       *rate = cmd.frequency;
+       return 0;
+}
+
+static unsigned long
+crg_port_recalc_rate(struct clk_hw *hw,        unsigned long parent_rate)
+{
+       unsigned long rate;
+
+       crg_rate_control(hw, 0, &rate);
+
+       return rate;
+}
+
+static long
+crg_port_round_rate(struct clk_hw *hw,
+                   unsigned long rate, unsigned long *pr)
+{
+       return rate;
+}
+
+static int
+crg_port_set_rate(struct clk_hw *hw,
+                 unsigned long rate, unsigned long parent_rate)
+{
+       return crg_rate_control(hw, 1, &rate);
+}
+
+const struct clk_ops crg_port_ops = {
+       .prepare = crg_port_prepare,
+       .unprepare = crg_port_unprepare,
+       .recalc_rate = crg_port_recalc_rate,
+       .round_rate = crg_port_round_rate,
+       .set_rate = crg_port_set_rate,
+};
+
+struct mb86s70_crg11 {
+       struct mutex lock; /* protects CLK populating and searching */
+};
+
+static struct clk *crg11_get(struct of_phandle_args *clkspec, void *data)
+{
+       struct mb86s70_crg11 *crg11 = data;
+       struct clk_init_data init;
+       u32 cntrlr, domain, port;
+       struct crg_clk *crgclk;
+       struct clk *clk;
+       char clkp[20];
+
+       if (clkspec->args_count != 3)
+               return ERR_PTR(-EINVAL);
+
+       cntrlr = clkspec->args[0];
+       domain = clkspec->args[1];
+       port = clkspec->args[2];
+
+       if (port > 7)
+               snprintf(clkp, 20, "UngatedCLK%d_%X", cntrlr, domain);
+       else
+               snprintf(clkp, 20, "CLK%d_%X_%d", cntrlr, domain, port);
+
+       mutex_lock(&crg11->lock);
+
+       clk = __clk_lookup(clkp);
+       if (clk) {
+               mutex_unlock(&crg11->lock);
+               return clk;
+       }
+
+       crgclk = kzalloc(sizeof(*crgclk), GFP_KERNEL);
+       if (!crgclk) {
+               mutex_unlock(&crg11->lock);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       init.name = clkp;
+       init.num_parents = 0;
+       init.ops = &crg_port_ops;
+       init.flags = CLK_IS_ROOT;
+       crgclk->hw.init = &init;
+       crgclk->cntrlr = cntrlr;
+       crgclk->domain = domain;
+       crgclk->port = port;
+       clk = clk_register(NULL, &crgclk->hw);
+       if (IS_ERR(clk))
+               pr_err("%s:%d Error!\n", __func__, __LINE__);
+       else
+               pr_debug("Registered %s\n", clkp);
+
+       clk_register_clkdev(clk, clkp, NULL);
+       mutex_unlock(&crg11->lock);
+       return clk;
+}
+
+static void __init crg_port_init(struct device_node *node)
+{
+       struct mb86s70_crg11 *crg11;
+
+       crg11 = kzalloc(sizeof(*crg11), GFP_KERNEL);
+       if (!crg11)
+               return;
+
+       mutex_init(&crg11->lock);
+
+       of_clk_add_provider(node, crg11_get, crg11);
+}
+CLK_OF_DECLARE(crg11_gate, "fujitsu,mb86s70-crg11", crg_port_init);
+
+struct cl_clk {
+       struct clk_hw hw;
+       int cluster;
+};
+
+struct mb86s7x_cpu_freq {
+       u32 payload_size;
+       u32 cluster_class;
+       u32 cluster_id;
+       u32 cpu_id;
+       u64 frequency;
+};
+
+static void mhu_cluster_rate(struct clk_hw *hw, unsigned long *rate, int get)
+{
+       struct cl_clk *clc = to_clc_clk(hw);
+       struct mb86s7x_cpu_freq cmd;
+       int code, ret;
+
+       cmd.payload_size = sizeof(cmd);
+       cmd.cluster_class = 0;
+       cmd.cluster_id = clc->cluster;
+       cmd.cpu_id = 0;
+       cmd.frequency = *rate;
+
+       if (get)
+               code = CMD_CPU_CLOCK_RATE_GET_REQ;
+       else
+               code = CMD_CPU_CLOCK_RATE_SET_REQ;
+
+       pr_debug("%s:%d CMD Cl_Class-%u CL_ID-%u CPU_ID-%u Freq-%llu}\n",
+                __func__, __LINE__, cmd.cluster_class,
+                cmd.cluster_id, cmd.cpu_id, cmd.frequency);
+
+       ret = mb86s7x_send_packet(code, &cmd, sizeof(cmd));
+       if (ret < 0) {
+               pr_err("%s:%d failed!\n", __func__, __LINE__);
+               return;
+       }
+
+       pr_debug("%s:%d REP Cl_Class-%u CL_ID-%u CPU_ID-%u Freq-%llu}\n",
+                __func__, __LINE__, cmd.cluster_class,
+                cmd.cluster_id, cmd.cpu_id, cmd.frequency);
+
+       *rate = cmd.frequency;
+}
+
+static unsigned long
+clc_recalc_rate(struct clk_hw *hw, unsigned long unused)
+{
+       unsigned long rate;
+
+       mhu_cluster_rate(hw, &rate, 1);
+       return rate;
+}
+
+static long
+clc_round_rate(struct clk_hw *hw, unsigned long rate,
+              unsigned long *unused)
+{
+       return rate;
+}
+
+static int
+clc_set_rate(struct clk_hw *hw, unsigned long rate,
+            unsigned long unused)
+{
+       unsigned long res = rate;
+
+       mhu_cluster_rate(hw, &res, 0);
+
+       return (res == rate) ? 0 : -EINVAL;
+}
+
+static struct clk_ops clk_clc_ops = {
+       .recalc_rate = clc_recalc_rate,
+       .round_rate = clc_round_rate,
+       .set_rate = clc_set_rate,
+};
+
+struct clk *mb86s7x_clclk_register(struct device *cpu_dev)
+{
+       struct clk_init_data init;
+       struct cl_clk *clc;
+
+       clc = kzalloc(sizeof(*clc), GFP_KERNEL);
+       if (!clc)
+               return ERR_PTR(-ENOMEM);
+
+       clc->hw.init = &init;
+       clc->cluster = topology_physical_package_id(cpu_dev->id);
+
+       init.name = dev_name(cpu_dev);
+       init.ops = &clk_clc_ops;
+       init.flags = CLK_IS_ROOT | CLK_GET_RATE_NOCACHE;
+       init.num_parents = 0;
+
+       return devm_clk_register(cpu_dev, &clc->hw);
+}
+
+static int mb86s7x_clclk_of_init(void)
+{
+       int cpu, ret = -ENODEV;
+       struct device_node *np;
+       struct clk *clk;
+
+       np = of_find_compatible_node(NULL, NULL, "fujitsu,mb86s70-scb-1.0");
+       if (!np || !of_device_is_available(np))
+               goto exit;
+
+       for_each_possible_cpu(cpu) {
+               struct device *cpu_dev = get_cpu_device(cpu);
+
+               if (!cpu_dev) {
+                       pr_err("failed to get cpu%d device\n", cpu);
+                       continue;
+               }
+
+               clk = mb86s7x_clclk_register(cpu_dev);
+               if (IS_ERR(clk)) {
+                       pr_err("failed to register cpu%d clock\n", cpu);
+                       continue;
+               }
+               if (clk_register_clkdev(clk, NULL, dev_name(cpu_dev))) {
+                       pr_err("failed to register cpu%d clock lookup\n", cpu);
+                       continue;
+               }
+               pr_debug("registered clk for %s\n", dev_name(cpu_dev));
+       }
+       ret = 0;
+
+       platform_device_register_simple("arm-bL-cpufreq-dt", -1, NULL, 0);
+exit:
+       of_node_put(np);
+       return ret;
+}
+module_init(mb86s7x_clclk_of_init);
index 8d459923a15fd591c782752f79393bb20f4b4da9..45a535ab48aaa1cf443d4467f42734b7949b1b47 100644 (file)
@@ -161,7 +161,7 @@ static struct palmas_clks_of_match_data palmas_of_clk32kgaudio = {
        },
 };
 
-static struct of_device_id palmas_clks_of_match[] = {
+static const struct of_device_id palmas_clks_of_match[] = {
        {
                .compatible = "ti,palmas-clk32kg",
                .data = &palmas_of_clk32kg,
diff --git a/drivers/clk/clk-pwm.c b/drivers/clk/clk-pwm.c
new file mode 100644 (file)
index 0000000..328fcfc
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2014 Philipp Zabel, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * PWM (mis)used as clock output
+ */
+#include <linux/clk-provider.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+
+struct clk_pwm {
+       struct clk_hw hw;
+       struct pwm_device *pwm;
+       u32 fixed_rate;
+};
+
+static inline struct clk_pwm *to_clk_pwm(struct clk_hw *hw)
+{
+       return container_of(hw, struct clk_pwm, hw);
+}
+
+static int clk_pwm_prepare(struct clk_hw *hw)
+{
+       struct clk_pwm *clk_pwm = to_clk_pwm(hw);
+
+       return pwm_enable(clk_pwm->pwm);
+}
+
+static void clk_pwm_unprepare(struct clk_hw *hw)
+{
+       struct clk_pwm *clk_pwm = to_clk_pwm(hw);
+
+       pwm_disable(clk_pwm->pwm);
+}
+
+static unsigned long clk_pwm_recalc_rate(struct clk_hw *hw,
+                                        unsigned long parent_rate)
+{
+       struct clk_pwm *clk_pwm = to_clk_pwm(hw);
+
+       return clk_pwm->fixed_rate;
+}
+
+static const struct clk_ops clk_pwm_ops = {
+       .prepare = clk_pwm_prepare,
+       .unprepare = clk_pwm_unprepare,
+       .recalc_rate = clk_pwm_recalc_rate,
+};
+
+static int clk_pwm_probe(struct platform_device *pdev)
+{
+       struct device_node *node = pdev->dev.of_node;
+       struct clk_init_data init;
+       struct clk_pwm *clk_pwm;
+       struct pwm_device *pwm;
+       const char *clk_name;
+       struct clk *clk;
+       int ret;
+
+       clk_pwm = devm_kzalloc(&pdev->dev, sizeof(*clk_pwm), GFP_KERNEL);
+       if (!clk_pwm)
+               return -ENOMEM;
+
+       pwm = devm_pwm_get(&pdev->dev, NULL);
+       if (IS_ERR(pwm))
+               return PTR_ERR(pwm);
+
+       if (!pwm->period) {
+               dev_err(&pdev->dev, "invalid PWM period\n");
+               return -EINVAL;
+       }
+
+       if (of_property_read_u32(node, "clock-frequency", &clk_pwm->fixed_rate))
+               clk_pwm->fixed_rate = NSEC_PER_SEC / pwm->period;
+
+       if (pwm->period != NSEC_PER_SEC / clk_pwm->fixed_rate &&
+           pwm->period != DIV_ROUND_UP(NSEC_PER_SEC, clk_pwm->fixed_rate)) {
+               dev_err(&pdev->dev,
+                       "clock-frequency does not match PWM period\n");
+               return -EINVAL;
+       }
+
+       ret = pwm_config(pwm, (pwm->period + 1) >> 1, pwm->period);
+       if (ret < 0)
+               return ret;
+
+       clk_name = node->name;
+       of_property_read_string(node, "clock-output-names", &clk_name);
+
+       init.name = clk_name;
+       init.ops = &clk_pwm_ops;
+       init.flags = CLK_IS_BASIC | CLK_IS_ROOT;
+       init.num_parents = 0;
+
+       clk_pwm->pwm = pwm;
+       clk_pwm->hw.init = &init;
+       clk = devm_clk_register(&pdev->dev, &clk_pwm->hw);
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       return of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+
+static int clk_pwm_remove(struct platform_device *pdev)
+{
+       of_clk_del_provider(pdev->dev.of_node);
+
+       return 0;
+}
+
+static const struct of_device_id clk_pwm_dt_ids[] = {
+       { .compatible = "pwm-clock" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, clk_pwm_dt_ids);
+
+static struct platform_driver clk_pwm_driver = {
+       .probe = clk_pwm_probe,
+       .remove = clk_pwm_remove,
+       .driver = {
+               .name = "pwm-clock",
+               .of_match_table = of_match_ptr(clk_pwm_dt_ids),
+       },
+};
+
+module_platform_driver(clk_pwm_driver);
+
+MODULE_AUTHOR("Philipp Zabel <p.zabel@pengutronix.de>");
+MODULE_DESCRIPTION("PWM clock driver");
+MODULE_LICENSE("GPL");
index 3b2a66f78755113fe9afde8f9caaa4d4e801260b..44ea107cfc6729818ea8a02dfd250f7e6a557967 100644 (file)
@@ -68,16 +68,16 @@ struct si5351_driver_data {
        struct si5351_hw_data   *clkout;
 };
 
-static const char const *si5351_input_names[] = {
+static const char * const si5351_input_names[] = {
        "xtal", "clkin"
 };
-static const char const *si5351_pll_names[] = {
+static const char * const si5351_pll_names[] = {
        "plla", "pllb", "vxco"
 };
-static const char const *si5351_msynth_names[] = {
+static const char * const si5351_msynth_names[] = {
        "ms0", "ms1", "ms2", "ms3", "ms4", "ms5", "ms6", "ms7"
 };
-static const char const *si5351_clkout_names[] = {
+static const char * const si5351_clkout_names[] = {
        "clk0", "clk1", "clk2", "clk3", "clk4", "clk5", "clk6", "clk7"
 };
 
@@ -207,7 +207,7 @@ static bool si5351_regmap_is_writeable(struct device *dev, unsigned int reg)
        return true;
 }
 
-static struct regmap_config si5351_regmap_config = {
+static const struct regmap_config si5351_regmap_config = {
        .reg_bits = 8,
        .val_bits = 8,
        .cache_type = REGCACHE_RBTREE,
index fc167b3f8919677b56a71c75491201fbf4ac079f..20a5aec98b1a2ca1b88560ccd0336d75073c4bed 100644 (file)
@@ -393,7 +393,7 @@ static bool si570_regmap_is_writeable(struct device *dev, unsigned int reg)
        }
 }
 
-static struct regmap_config si570_regmap_config = {
+static const struct regmap_config si570_regmap_config = {
        .reg_bits = 8,
        .val_bits = 8,
        .cache_type = REGCACHE_RBTREE,
index 237f23f68bfce18cdfee3306487ba924906125c4..459ce9da13e0631b41e6cafc5ed9a85523e5e1b7 100644 (file)
@@ -77,13 +77,16 @@ struct clk_core {
        struct kref             ref;
 };
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/clk.h>
+
 struct clk {
        struct clk_core *core;
        const char *dev_id;
        const char *con_id;
        unsigned long min_rate;
        unsigned long max_rate;
-       struct hlist_node child_node;
+       struct hlist_node clks_node;
 };
 
 /***           locking             ***/
@@ -480,6 +483,8 @@ static void clk_unprepare_unused_subtree(struct clk_core *clk)
 {
        struct clk_core *child;
 
+       lockdep_assert_held(&prepare_lock);
+
        hlist_for_each_entry(child, &clk->children, child_node)
                clk_unprepare_unused_subtree(child);
 
@@ -490,10 +495,12 @@ static void clk_unprepare_unused_subtree(struct clk_core *clk)
                return;
 
        if (clk_core_is_prepared(clk)) {
+               trace_clk_unprepare(clk);
                if (clk->ops->unprepare_unused)
                        clk->ops->unprepare_unused(clk->hw);
                else if (clk->ops->unprepare)
                        clk->ops->unprepare(clk->hw);
+               trace_clk_unprepare_complete(clk);
        }
 }
 
@@ -503,6 +510,8 @@ static void clk_disable_unused_subtree(struct clk_core *clk)
        struct clk_core *child;
        unsigned long flags;
 
+       lockdep_assert_held(&prepare_lock);
+
        hlist_for_each_entry(child, &clk->children, child_node)
                clk_disable_unused_subtree(child);
 
@@ -520,10 +529,12 @@ static void clk_disable_unused_subtree(struct clk_core *clk)
         * back to .disable
         */
        if (clk_core_is_enabled(clk)) {
+               trace_clk_disable(clk);
                if (clk->ops->disable_unused)
                        clk->ops->disable_unused(clk->hw);
                else if (clk->ops->disable)
                        clk->ops->disable(clk->hw);
+               trace_clk_disable_complete(clk);
        }
 
 unlock_out:
@@ -851,10 +862,10 @@ static void clk_core_get_boundaries(struct clk_core *clk,
        *min_rate = 0;
        *max_rate = ULONG_MAX;
 
-       hlist_for_each_entry(clk_user, &clk->clks, child_node)
+       hlist_for_each_entry(clk_user, &clk->clks, clks_node)
                *min_rate = max(*min_rate, clk_user->min_rate);
 
-       hlist_for_each_entry(clk_user, &clk->clks, child_node)
+       hlist_for_each_entry(clk_user, &clk->clks, clks_node)
                *max_rate = min(*max_rate, clk_user->max_rate);
 }
 
@@ -903,9 +914,12 @@ static void clk_core_unprepare(struct clk_core *clk)
 
        WARN_ON(clk->enable_count > 0);
 
+       trace_clk_unprepare(clk);
+
        if (clk->ops->unprepare)
                clk->ops->unprepare(clk->hw);
 
+       trace_clk_unprepare_complete(clk);
        clk_core_unprepare(clk->parent);
 }
 
@@ -943,12 +957,16 @@ static int clk_core_prepare(struct clk_core *clk)
                if (ret)
                        return ret;
 
-               if (clk->ops->prepare) {
+               trace_clk_prepare(clk);
+
+               if (clk->ops->prepare)
                        ret = clk->ops->prepare(clk->hw);
-                       if (ret) {
-                               clk_core_unprepare(clk->parent);
-                               return ret;
-                       }
+
+               trace_clk_prepare_complete(clk);
+
+               if (ret) {
+                       clk_core_unprepare(clk->parent);
+                       return ret;
                }
        }
 
@@ -995,9 +1013,13 @@ static void clk_core_disable(struct clk_core *clk)
        if (--clk->enable_count > 0)
                return;
 
+       trace_clk_disable(clk);
+
        if (clk->ops->disable)
                clk->ops->disable(clk->hw);
 
+       trace_clk_disable_complete(clk);
+
        clk_core_disable(clk->parent);
 }
 
@@ -1050,12 +1072,16 @@ static int clk_core_enable(struct clk_core *clk)
                if (ret)
                        return ret;
 
-               if (clk->ops->enable) {
+               trace_clk_enable(clk);
+
+               if (clk->ops->enable)
                        ret = clk->ops->enable(clk->hw);
-                       if (ret) {
-                               clk_core_disable(clk->parent);
-                               return ret;
-                       }
+
+               trace_clk_enable_complete(clk);
+
+               if (ret) {
+                       clk_core_disable(clk->parent);
+                       return ret;
                }
        }
 
@@ -1106,6 +1132,8 @@ static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
        struct clk_core *parent;
        struct clk_hw *parent_hw;
 
+       lockdep_assert_held(&prepare_lock);
+
        if (!clk)
                return 0;
 
@@ -1245,6 +1273,8 @@ static void __clk_recalc_accuracies(struct clk_core *clk)
        unsigned long parent_accuracy = 0;
        struct clk_core *child;
 
+       lockdep_assert_held(&prepare_lock);
+
        if (clk->parent)
                parent_accuracy = clk->parent->accuracy;
 
@@ -1318,6 +1348,8 @@ static void __clk_recalc_rates(struct clk_core *clk, unsigned long msg)
        unsigned long parent_rate = 0;
        struct clk_core *child;
 
+       lockdep_assert_held(&prepare_lock);
+
        old_rate = clk->rate;
 
        if (clk->parent)
@@ -1479,10 +1511,14 @@ static int __clk_set_parent(struct clk_core *clk, struct clk_core *parent,
 
        old_parent = __clk_set_parent_before(clk, parent);
 
+       trace_clk_set_parent(clk, parent);
+
        /* change clock input source */
        if (parent && clk->ops->set_parent)
                ret = clk->ops->set_parent(clk->hw, p_index);
 
+       trace_clk_set_parent_complete(clk, parent);
+
        if (ret) {
                flags = clk_enable_lock();
                clk_reparent(clk, old_parent);
@@ -1524,6 +1560,8 @@ static int __clk_speculate_rates(struct clk_core *clk,
        unsigned long new_rate;
        int ret = NOTIFY_DONE;
 
+       lockdep_assert_held(&prepare_lock);
+
        new_rate = clk_recalc(clk, parent_rate);
 
        /* abort rate change if a driver returns NOTIFY_BAD or NOTIFY_STOP */
@@ -1580,6 +1618,7 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *clk,
        unsigned long min_rate;
        unsigned long max_rate;
        int p_index = 0;
+       long ret;
 
        /* sanity */
        if (IS_ERR_OR_NULL(clk))
@@ -1595,15 +1634,23 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *clk,
        /* find the closest rate and parent clk/rate */
        if (clk->ops->determine_rate) {
                parent_hw = parent ? parent->hw : NULL;
-               new_rate = clk->ops->determine_rate(clk->hw, rate,
-                                                   min_rate,
-                                                   max_rate,
-                                                   &best_parent_rate,
-                                                   &parent_hw);
+               ret = clk->ops->determine_rate(clk->hw, rate,
+                                              min_rate,
+                                              max_rate,
+                                              &best_parent_rate,
+                                              &parent_hw);
+               if (ret < 0)
+                       return NULL;
+
+               new_rate = ret;
                parent = parent_hw ? parent_hw->core : NULL;
        } else if (clk->ops->round_rate) {
-               new_rate = clk->ops->round_rate(clk->hw, rate,
-                                               &best_parent_rate);
+               ret = clk->ops->round_rate(clk->hw, rate,
+                                          &best_parent_rate);
+               if (ret < 0)
+                       return NULL;
+
+               new_rate = ret;
                if (new_rate < min_rate || new_rate > max_rate)
                        return NULL;
        } else if (!parent || !(clk->flags & CLK_SET_RATE_PARENT)) {
@@ -1706,6 +1753,7 @@ static void clk_change_rate(struct clk_core *clk)
 
        if (clk->new_parent && clk->new_parent != clk->parent) {
                old_parent = __clk_set_parent_before(clk, clk->new_parent);
+               trace_clk_set_parent(clk, clk->new_parent);
 
                if (clk->ops->set_rate_and_parent) {
                        skip_set_rate = true;
@@ -1716,12 +1764,17 @@ static void clk_change_rate(struct clk_core *clk)
                        clk->ops->set_parent(clk->hw, clk->new_parent_index);
                }
 
+               trace_clk_set_parent_complete(clk, clk->new_parent);
                __clk_set_parent_after(clk, clk->new_parent, old_parent);
        }
 
+       trace_clk_set_rate(clk, clk->new_rate);
+
        if (!skip_set_rate && clk->ops->set_rate)
                clk->ops->set_rate(clk->hw, clk->new_rate, best_parent_rate);
 
+       trace_clk_set_rate_complete(clk, clk->new_rate);
+
        clk->rate = clk_recalc(clk, best_parent_rate);
 
        if (clk->notifier_count && old_rate != clk->rate)
@@ -2010,16 +2063,18 @@ static int clk_core_set_parent(struct clk_core *clk, struct clk_core *parent)
        if (!clk)
                return 0;
 
-       /* verify ops for for multi-parent clks */
-       if ((clk->num_parents > 1) && (!clk->ops->set_parent))
-               return -ENOSYS;
-
        /* prevent racing with updates to the clock topology */
        clk_prepare_lock();
 
        if (clk->parent == parent)
                goto out;
 
+       /* verify ops for for multi-parent clks */
+       if ((clk->num_parents > 1) && (!clk->ops->set_parent)) {
+               ret = -ENOSYS;
+               goto out;
+       }
+
        /* check that we are allowed to re-parent if the clock is in use */
        if ((clk->flags & CLK_SET_PARENT_GATE) && clk->prepare_count) {
                ret = -EBUSY;
@@ -2110,10 +2165,10 @@ EXPORT_SYMBOL_GPL(clk_set_parent);
  */
 int clk_set_phase(struct clk *clk, int degrees)
 {
-       int ret = 0;
+       int ret = -EINVAL;
 
        if (!clk)
-               goto out;
+               return 0;
 
        /* sanity check degrees */
        degrees %= 360;
@@ -2122,18 +2177,18 @@ int clk_set_phase(struct clk *clk, int degrees)
 
        clk_prepare_lock();
 
-       if (!clk->core->ops->set_phase)
-               goto out_unlock;
+       trace_clk_set_phase(clk->core, degrees);
 
-       ret = clk->core->ops->set_phase(clk->core->hw, degrees);
+       if (clk->core->ops->set_phase)
+               ret = clk->core->ops->set_phase(clk->core->hw, degrees);
+
+       trace_clk_set_phase_complete(clk->core, degrees);
 
        if (!ret)
                clk->core->phase = degrees;
 
-out_unlock:
        clk_prepare_unlock();
 
-out:
        return ret;
 }
 EXPORT_SYMBOL_GPL(clk_set_phase);
@@ -2401,7 +2456,7 @@ struct clk *__clk_create_clk(struct clk_hw *hw, const char *dev_id,
        clk->max_rate = ULONG_MAX;
 
        clk_prepare_lock();
-       hlist_add_head(&clk->child_node, &hw->core->clks);
+       hlist_add_head(&clk->clks_node, &hw->core->clks);
        clk_prepare_unlock();
 
        return clk;
@@ -2410,7 +2465,7 @@ struct clk *__clk_create_clk(struct clk_hw *hw, const char *dev_id,
 void __clk_free_clk(struct clk *clk)
 {
        clk_prepare_lock();
-       hlist_del(&clk->child_node);
+       hlist_del(&clk->clks_node);
        clk_prepare_unlock();
 
        kfree(clk);
@@ -2513,6 +2568,8 @@ static void __clk_release(struct kref *ref)
        struct clk_core *clk = container_of(ref, struct clk_core, ref);
        int i = clk->num_parents;
 
+       lockdep_assert_held(&prepare_lock);
+
        kfree(clk->parents);
        while (--i >= 0)
                kfree_const(clk->parent_names[i]);
@@ -2688,7 +2745,7 @@ void __clk_put(struct clk *clk)
 
        clk_prepare_lock();
 
-       hlist_del(&clk->child_node);
+       hlist_del(&clk->clks_node);
        if (clk->min_rate > clk->core->req_rate ||
            clk->max_rate < clk->core->req_rate)
                clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
@@ -2834,17 +2891,6 @@ static const struct of_device_id __clk_of_table_sentinel
 static LIST_HEAD(of_clk_providers);
 static DEFINE_MUTEX(of_clk_mutex);
 
-/* of_clk_provider list locking helpers */
-void of_clk_lock(void)
-{
-       mutex_lock(&of_clk_mutex);
-}
-
-void of_clk_unlock(void)
-{
-       mutex_unlock(&of_clk_mutex);
-}
-
 struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec,
                                     void *data)
 {
@@ -2928,7 +2974,11 @@ struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec,
        struct of_clk_provider *provider;
        struct clk *clk = ERR_PTR(-EPROBE_DEFER);
 
+       if (!clkspec)
+               return ERR_PTR(-EINVAL);
+
        /* Check if we have such a provider in our array */
+       mutex_lock(&of_clk_mutex);
        list_for_each_entry(provider, &of_clk_providers, link) {
                if (provider->node == clkspec->np)
                        clk = provider->get(clkspec, provider->data);
@@ -2944,19 +2994,22 @@ struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec,
                        break;
                }
        }
+       mutex_unlock(&of_clk_mutex);
 
        return clk;
 }
 
+/**
+ * of_clk_get_from_provider() - Lookup a clock from a clock provider
+ * @clkspec: pointer to a clock specifier data structure
+ *
+ * This function looks up a struct clk from the registered list of clock
+ * providers, an input is a clock specifier data structure as returned
+ * from the of_parse_phandle_with_args() function call.
+ */
 struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec)
 {
-       struct clk *clk;
-
-       mutex_lock(&of_clk_mutex);
-       clk = __of_clk_get_from_provider(clkspec, NULL, __func__);
-       mutex_unlock(&of_clk_mutex);
-
-       return clk;
+       return __of_clk_get_from_provider(clkspec, NULL, __func__);
 }
 
 int of_clk_get_parent_count(struct device_node *np)
index ba845408cc3e8515ef8c9457f686727b57027185..00b35a13cdf389310afe65856fc23e3fee68d067 100644 (file)
 struct clk_hw;
 
 #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
-struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec);
 struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec,
                                       const char *dev_id, const char *con_id);
-void of_clk_lock(void);
-void of_clk_unlock(void);
 #endif
 
 #ifdef CONFIG_COMMON_CLK
index 043fd3633373982f0408de1618370c6d63d5887b..1fcb6ef2cdacd75afe77257eec3da8d769052505 100644 (file)
@@ -28,34 +28,6 @@ static LIST_HEAD(clocks);
 static DEFINE_MUTEX(clocks_mutex);
 
 #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
-
-static struct clk *__of_clk_get_by_clkspec(struct of_phandle_args *clkspec,
-                                        const char *dev_id, const char *con_id)
-{
-       struct clk *clk;
-
-       if (!clkspec)
-               return ERR_PTR(-EINVAL);
-
-       of_clk_lock();
-       clk = __of_clk_get_from_provider(clkspec, dev_id, con_id);
-       of_clk_unlock();
-       return clk;
-}
-
-/**
- * of_clk_get_by_clkspec() - Lookup a clock form a clock provider
- * @clkspec: pointer to a clock specifier data structure
- *
- * This function looks up a struct clk from the registered list of clock
- * providers, an input is a clock specifier data structure as returned
- * from the of_parse_phandle_with_args() function call.
- */
-struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec)
-{
-       return __of_clk_get_by_clkspec(clkspec, NULL, __func__);
-}
-
 static struct clk *__of_clk_get(struct device_node *np, int index,
                               const char *dev_id, const char *con_id)
 {
@@ -71,7 +43,7 @@ static struct clk *__of_clk_get(struct device_node *np, int index,
        if (rc)
                return ERR_PTR(rc);
 
-       clk = __of_clk_get_by_clkspec(&clkspec, dev_id, con_id);
+       clk = __of_clk_get_from_provider(&clkspec, dev_id, con_id);
        of_node_put(clkspec.np);
 
        return clk;
index 2e4f6d432bebeb21b6c543494764320407b9a488..472dd2cb10b3bfe71a2e811c6e82db75f2d5df66 100644 (file)
 #include "clk.h"
 
 /* clock parent list */
-static const char *timer0_mux_p[] __initconst = { "osc32k", "timerclk01", };
-static const char *timer1_mux_p[] __initconst = { "osc32k", "timerclk01", };
-static const char *timer2_mux_p[] __initconst = { "osc32k", "timerclk23", };
-static const char *timer3_mux_p[] __initconst = { "osc32k", "timerclk23", };
-static const char *timer4_mux_p[] __initconst = { "osc32k", "timerclk45", };
-static const char *timer5_mux_p[] __initconst = { "osc32k", "timerclk45", };
-static const char *timer6_mux_p[] __initconst = { "osc32k", "timerclk67", };
-static const char *timer7_mux_p[] __initconst = { "osc32k", "timerclk67", };
-static const char *timer8_mux_p[] __initconst = { "osc32k", "timerclk89", };
-static const char *timer9_mux_p[] __initconst = { "osc32k", "timerclk89", };
-static const char *uart0_mux_p[] __initconst = { "osc26m", "pclk", };
-static const char *uart1_mux_p[] __initconst = { "osc26m", "pclk", };
-static const char *uart2_mux_p[] __initconst = { "osc26m", "pclk", };
-static const char *uart3_mux_p[] __initconst = { "osc26m", "pclk", };
-static const char *uart4_mux_p[] __initconst = { "osc26m", "pclk", };
-static const char *spi0_mux_p[] __initconst = { "osc26m", "rclk_cfgaxi", };
-static const char *spi1_mux_p[] __initconst = { "osc26m", "rclk_cfgaxi", };
-static const char *spi2_mux_p[] __initconst = { "osc26m", "rclk_cfgaxi", };
+static const char *timer0_mux_p[] __initdata = { "osc32k", "timerclk01", };
+static const char *timer1_mux_p[] __initdata = { "osc32k", "timerclk01", };
+static const char *timer2_mux_p[] __initdata = { "osc32k", "timerclk23", };
+static const char *timer3_mux_p[] __initdata = { "osc32k", "timerclk23", };
+static const char *timer4_mux_p[] __initdata = { "osc32k", "timerclk45", };
+static const char *timer5_mux_p[] __initdata = { "osc32k", "timerclk45", };
+static const char *timer6_mux_p[] __initdata = { "osc32k", "timerclk67", };
+static const char *timer7_mux_p[] __initdata = { "osc32k", "timerclk67", };
+static const char *timer8_mux_p[] __initdata = { "osc32k", "timerclk89", };
+static const char *timer9_mux_p[] __initdata = { "osc32k", "timerclk89", };
+static const char *uart0_mux_p[] __initdata = { "osc26m", "pclk", };
+static const char *uart1_mux_p[] __initdata = { "osc26m", "pclk", };
+static const char *uart2_mux_p[] __initdata = { "osc26m", "pclk", };
+static const char *uart3_mux_p[] __initdata = { "osc26m", "pclk", };
+static const char *uart4_mux_p[] __initdata = { "osc26m", "pclk", };
+static const char *spi0_mux_p[] __initdata = { "osc26m", "rclk_cfgaxi", };
+static const char *spi1_mux_p[] __initdata = { "osc26m", "rclk_cfgaxi", };
+static const char *spi2_mux_p[] __initdata = { "osc26m", "rclk_cfgaxi", };
 /* share axi parent */
-static const char *saxi_mux_p[] __initconst = { "armpll3", "armpll2", };
-static const char *pwm0_mux_p[] __initconst = { "osc32k", "osc26m", };
-static const char *pwm1_mux_p[] __initconst = { "osc32k", "osc26m", };
-static const char *sd_mux_p[] __initconst = { "armpll2", "armpll3", };
-static const char *mmc1_mux_p[] __initconst = { "armpll2", "armpll3", };
-static const char *mmc1_mux2_p[] __initconst = { "osc26m", "mmc1_div", };
-static const char *g2d_mux_p[] __initconst = { "armpll2", "armpll3", };
-static const char *venc_mux_p[] __initconst = { "armpll2", "armpll3", };
-static const char *vdec_mux_p[] __initconst = { "armpll2", "armpll3", };
-static const char *vpp_mux_p[] __initconst = { "armpll2", "armpll3", };
-static const char *edc0_mux_p[] __initconst = { "armpll2", "armpll3", };
-static const char *ldi0_mux_p[] __initconst = { "armpll2", "armpll4",
+static const char *saxi_mux_p[] __initdata = { "armpll3", "armpll2", };
+static const char *pwm0_mux_p[] __initdata = { "osc32k", "osc26m", };
+static const char *pwm1_mux_p[] __initdata = { "osc32k", "osc26m", };
+static const char *sd_mux_p[] __initdata = { "armpll2", "armpll3", };
+static const char *mmc1_mux_p[] __initdata = { "armpll2", "armpll3", };
+static const char *mmc1_mux2_p[] __initdata = { "osc26m", "mmc1_div", };
+static const char *g2d_mux_p[] __initdata = { "armpll2", "armpll3", };
+static const char *venc_mux_p[] __initdata = { "armpll2", "armpll3", };
+static const char *vdec_mux_p[] __initdata = { "armpll2", "armpll3", };
+static const char *vpp_mux_p[] __initdata = { "armpll2", "armpll3", };
+static const char *edc0_mux_p[] __initdata = { "armpll2", "armpll3", };
+static const char *ldi0_mux_p[] __initdata = { "armpll2", "armpll4",
                                             "armpll3", "armpll5", };
-static const char *edc1_mux_p[] __initconst = { "armpll2", "armpll3", };
-static const char *ldi1_mux_p[] __initconst = { "armpll2", "armpll4",
+static const char *edc1_mux_p[] __initdata = { "armpll2", "armpll3", };
+static const char *ldi1_mux_p[] __initdata = { "armpll2", "armpll4",
                                             "armpll3", "armpll5", };
-static const char *rclk_hsic_p[] __initconst = { "armpll3", "armpll2", };
-static const char *mmc2_mux_p[] __initconst = { "armpll2", "armpll3", };
-static const char *mmc3_mux_p[] __initconst = { "armpll2", "armpll3", };
+static const char *rclk_hsic_p[] __initdata = { "armpll3", "armpll2", };
+static const char *mmc2_mux_p[] __initdata = { "armpll2", "armpll3", };
+static const char *mmc3_mux_p[] __initdata = { "armpll2", "armpll3", };
 
 
 /* fixed rate clocks */
index 3f369c60fe56a9f6d449ef82c51ffca141cf8aee..f1d239435826ca6e7a873d08c9dcaa0c8590e630 100644 (file)
@@ -46,15 +46,15 @@ static struct hisi_fixed_rate_clock hix5hd2_fixed_rate_clks[] __initdata = {
        { HIX5HD2_FIXED_83M, "83m", NULL, CLK_IS_ROOT, 83333333, },
 };
 
-static const char *sfc_mux_p[] __initconst = {
+static const char *sfc_mux_p[] __initdata = {
                "24m", "150m", "200m", "100m", "75m", };
 static u32 sfc_mux_table[] = {0, 4, 5, 6, 7};
 
-static const char *sdio_mux_p[] __initconst = {
+static const char *sdio_mux_p[] __initdata = {
                "75m", "100m", "50m", "15m", };
 static u32 sdio_mux_table[] = {0, 1, 2, 3};
 
-static const char *fephy_mux_p[] __initconst = { "25m", "125m"};
+static const char *fephy_mux_p[] __initdata = { "25m", "125m"};
 static u32 fephy_mux_table[] = {0, 1};
 
 
index 3b34dba9178d9c792fffa5f5afa5b2c0e00d83dd..27696255486dee6feb00e728019d4b7752128bcc 100644 (file)
@@ -21,6 +21,10 @@ config ARMADA_38X_CLK
        bool
        select MVEBU_CLK_COMMON
 
+config ARMADA_39X_CLK
+       bool
+       select MVEBU_CLK_COMMON
+
 config ARMADA_XP_CLK
        bool
        select MVEBU_CLK_COMMON
index a9a56fc01901580f36804efb6d21968cf7d749f0..645ac7ea3565a46658c1e94e05d594a02a0fcece 100644 (file)
@@ -5,6 +5,7 @@ obj-$(CONFIG_MVEBU_CLK_COREDIV) += clk-corediv.o
 obj-$(CONFIG_ARMADA_370_CLK)   += armada-370.o
 obj-$(CONFIG_ARMADA_375_CLK)   += armada-375.o
 obj-$(CONFIG_ARMADA_38X_CLK)   += armada-38x.o
+obj-$(CONFIG_ARMADA_39X_CLK)   += armada-39x.o
 obj-$(CONFIG_ARMADA_XP_CLK)    += armada-xp.o
 obj-$(CONFIG_DOVE_CLK)         += dove.o
 obj-$(CONFIG_KIRKWOOD_CLK)     += kirkwood.o
diff --git a/drivers/clk/mvebu/armada-39x.c b/drivers/clk/mvebu/armada-39x.c
new file mode 100644 (file)
index 0000000..efb974d
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Marvell Armada 39x SoC clocks
+ *
+ * Copyright (C) 2015 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ * Andrew Lunn <andrew@lunn.ch>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.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/kernel.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include "common.h"
+
+/*
+ * SARL[14:10] : Ratios between CPU, NBCLK, HCLK and DCLK.
+ *
+ * SARL[15]    : TCLK frequency
+ *              0 = 250 MHz
+ *              1 = 200 MHz
+ *
+ * SARH[0]     : Reference clock frequency
+ *               0 = 25 Mhz
+ *               1 = 40 Mhz
+ */
+
+#define SARL                                   0
+#define  SARL_A390_TCLK_FREQ_OPT               15
+#define  SARL_A390_TCLK_FREQ_OPT_MASK          0x1
+#define  SARL_A390_CPU_DDR_L2_FREQ_OPT         10
+#define  SARL_A390_CPU_DDR_L2_FREQ_OPT_MASK    0x1F
+#define SARH                                   4
+#define  SARH_A390_REFCLK_FREQ                 BIT(0)
+
+static const u32 armada_39x_tclk_frequencies[] __initconst = {
+       250000000,
+       200000000,
+};
+
+static u32 __init armada_39x_get_tclk_freq(void __iomem *sar)
+{
+       u8 tclk_freq_select;
+
+       tclk_freq_select = ((readl(sar + SARL) >> SARL_A390_TCLK_FREQ_OPT) &
+                           SARL_A390_TCLK_FREQ_OPT_MASK);
+       return armada_39x_tclk_frequencies[tclk_freq_select];
+}
+
+static const u32 armada_39x_cpu_frequencies[] __initconst = {
+       [0x0] = 666 * 1000 * 1000,
+       [0x2] = 800 * 1000 * 1000,
+       [0x3] = 800 * 1000 * 1000,
+       [0x4] = 1066 * 1000 * 1000,
+       [0x5] = 1066 * 1000 * 1000,
+       [0x6] = 1200 * 1000 * 1000,
+       [0x8] = 1332 * 1000 * 1000,
+       [0xB] = 1600 * 1000 * 1000,
+       [0xC] = 1600 * 1000 * 1000,
+       [0x12] = 1800 * 1000 * 1000,
+       [0x1E] = 1800 * 1000 * 1000,
+};
+
+static u32 __init armada_39x_get_cpu_freq(void __iomem *sar)
+{
+       u8 cpu_freq_select;
+
+       cpu_freq_select = ((readl(sar + SARL) >> SARL_A390_CPU_DDR_L2_FREQ_OPT) &
+                          SARL_A390_CPU_DDR_L2_FREQ_OPT_MASK);
+       if (cpu_freq_select >= ARRAY_SIZE(armada_39x_cpu_frequencies)) {
+               pr_err("Selected CPU frequency (%d) unsupported\n",
+                       cpu_freq_select);
+               return 0;
+       }
+
+       return armada_39x_cpu_frequencies[cpu_freq_select];
+}
+
+enum { A390_CPU_TO_NBCLK, A390_CPU_TO_HCLK, A390_CPU_TO_DCLK };
+
+static const struct coreclk_ratio armada_39x_coreclk_ratios[] __initconst = {
+       { .id = A390_CPU_TO_NBCLK, .name = "nbclk" },
+       { .id = A390_CPU_TO_HCLK, .name = "hclk" },
+       { .id = A390_CPU_TO_DCLK, .name = "dclk" },
+};
+
+static void __init armada_39x_get_clk_ratio(
+       void __iomem *sar, int id, int *mult, int *div)
+{
+       switch (id) {
+       case A390_CPU_TO_NBCLK:
+               *mult = 1;
+               *div = 2;
+               break;
+       case A390_CPU_TO_HCLK:
+               *mult = 1;
+               *div = 4;
+               break;
+       case A390_CPU_TO_DCLK:
+               *mult = 1;
+               *div = 2;
+               break;
+       }
+}
+
+static u32 __init armada_39x_refclk_ratio(void __iomem *sar)
+{
+       if (readl(sar + SARH) & SARH_A390_REFCLK_FREQ)
+               return 40 * 1000 * 1000;
+       else
+               return 25 * 1000 * 1000;
+}
+
+static const struct coreclk_soc_desc armada_39x_coreclks = {
+       .get_tclk_freq = armada_39x_get_tclk_freq,
+       .get_cpu_freq = armada_39x_get_cpu_freq,
+       .get_clk_ratio = armada_39x_get_clk_ratio,
+       .get_refclk_freq = armada_39x_refclk_ratio,
+       .ratios = armada_39x_coreclk_ratios,
+       .num_ratios = ARRAY_SIZE(armada_39x_coreclk_ratios),
+};
+
+static void __init armada_39x_coreclk_init(struct device_node *np)
+{
+       mvebu_coreclk_setup(np, &armada_39x_coreclks);
+}
+CLK_OF_DECLARE(armada_39x_core_clk, "marvell,armada-390-core-clock",
+              armada_39x_coreclk_init);
+
+/*
+ * Clock Gating Control
+ */
+static const struct clk_gating_soc_desc armada_39x_gating_desc[] __initconst = {
+       { "pex1", NULL, 5 },
+       { "pex2", NULL, 6 },
+       { "pex3", NULL, 7 },
+       { "pex0", NULL, 8 },
+       { "usb3h0", NULL, 9 },
+       { "sdio", NULL, 17 },
+       { "xor0", NULL, 22 },
+       { "xor1", NULL, 28 },
+       { }
+};
+
+static void __init armada_39x_clk_gating_init(struct device_node *np)
+{
+       mvebu_clk_gating_setup(np, armada_39x_gating_desc);
+}
+CLK_OF_DECLARE(armada_39x_clk_gating, "marvell,armada-390-gating-clock",
+              armada_39x_clk_gating_init);
index 0d4d1216f2dd25fb32f0b5417359d95957c9f086..15b370ff37481a61e4351377793d5619e14a6cd8 100644 (file)
@@ -121,6 +121,11 @@ void __init mvebu_coreclk_setup(struct device_node *np,
 
        /* Allocate struct for TCLK, cpu clk, and core ratio clocks */
        clk_data.clk_num = 2 + desc->num_ratios;
+
+       /* One more clock for the optional refclk */
+       if (desc->get_refclk_freq)
+               clk_data.clk_num += 1;
+
        clk_data.clks = kzalloc(clk_data.clk_num * sizeof(struct clk *),
                                GFP_KERNEL);
        if (WARN_ON(!clk_data.clks)) {
@@ -162,6 +167,18 @@ void __init mvebu_coreclk_setup(struct device_node *np,
                WARN_ON(IS_ERR(clk_data.clks[2+n]));
        };
 
+       /* Register optional refclk */
+       if (desc->get_refclk_freq) {
+               const char *name = "refclk";
+               of_property_read_string_index(np, "clock-output-names",
+                                             2 + desc->num_ratios, &name);
+               rate = desc->get_refclk_freq(base);
+               clk_data.clks[2 + desc->num_ratios] =
+                       clk_register_fixed_rate(NULL, name, NULL,
+                                               CLK_IS_ROOT, rate);
+               WARN_ON(IS_ERR(clk_data.clks[2 + desc->num_ratios]));
+       }
+
        /* SAR register isn't needed anymore */
        iounmap(base);
 
index 783b5631a453fe614e070a51e760e1004d2580e1..f0de6c8a494a3ca65e18d340c3918e0b4396a43c 100644 (file)
@@ -30,6 +30,7 @@ struct coreclk_soc_desc {
        u32 (*get_tclk_freq)(void __iomem *sar);
        u32 (*get_cpu_freq)(void __iomem *sar);
        void (*get_clk_ratio)(void __iomem *sar, int id, int *mult, int *div);
+       u32 (*get_refclk_freq)(void __iomem *sar);
        bool (*is_sscg_enabled)(void __iomem *sar);
        u32 (*fix_sscg_deviation)(u32 system_clk);
        const struct coreclk_ratio *ratios;
index 9fc9359f51335e60451e9073469f0a6a34ed6730..22d136aa699ff1b15a73247e183d4a81d98726c7 100644 (file)
@@ -77,12 +77,12 @@ static void __init clk_misc_init(void)
        writel_relaxed(30 << BP_FRAC_IOFRAC, FRAC + SET);
 }
 
-static const char *sel_pll[]  __initconst = { "pll", "ref_xtal", };
-static const char *sel_cpu[]  __initconst = { "ref_cpu", "ref_xtal", };
-static const char *sel_pix[]  __initconst = { "ref_pix", "ref_xtal", };
-static const char *sel_io[]   __initconst = { "ref_io", "ref_xtal", };
-static const char *cpu_sels[] __initconst = { "cpu_pll", "cpu_xtal", };
-static const char *emi_sels[] __initconst = { "emi_pll", "emi_xtal", };
+static const char *sel_pll[]  __initdata = { "pll", "ref_xtal", };
+static const char *sel_cpu[]  __initdata = { "ref_cpu", "ref_xtal", };
+static const char *sel_pix[]  __initdata = { "ref_pix", "ref_xtal", };
+static const char *sel_io[]   __initdata = { "ref_io", "ref_xtal", };
+static const char *cpu_sels[] __initdata = { "cpu_pll", "cpu_xtal", };
+static const char *emi_sels[] __initdata = { "emi_pll", "emi_xtal", };
 
 enum imx23_clk {
        ref_xtal, pll, ref_cpu, ref_emi, ref_pix, ref_io, saif_sel,
index a6c35010e4e5b1a61f8e802896bc15ad623bc74a..b1be3746ce958dad95fe396c0621b3f4ae248b29 100644 (file)
@@ -125,15 +125,15 @@ static void __init clk_misc_init(void)
        writel_relaxed(val, FRAC0);
 }
 
-static const char *sel_cpu[]  __initconst = { "ref_cpu", "ref_xtal", };
-static const char *sel_io0[]  __initconst = { "ref_io0", "ref_xtal", };
-static const char *sel_io1[]  __initconst = { "ref_io1", "ref_xtal", };
-static const char *sel_pix[]  __initconst = { "ref_pix", "ref_xtal", };
-static const char *sel_gpmi[] __initconst = { "ref_gpmi", "ref_xtal", };
-static const char *sel_pll0[] __initconst = { "pll0", "ref_xtal", };
-static const char *cpu_sels[] __initconst = { "cpu_pll", "cpu_xtal", };
-static const char *emi_sels[] __initconst = { "emi_pll", "emi_xtal", };
-static const char *ptp_sels[] __initconst = { "ref_xtal", "pll0", };
+static const char *sel_cpu[]  __initdata = { "ref_cpu", "ref_xtal", };
+static const char *sel_io0[]  __initdata = { "ref_io0", "ref_xtal", };
+static const char *sel_io1[]  __initdata = { "ref_io1", "ref_xtal", };
+static const char *sel_pix[]  __initdata = { "ref_pix", "ref_xtal", };
+static const char *sel_gpmi[] __initdata = { "ref_gpmi", "ref_xtal", };
+static const char *sel_pll0[] __initdata = { "pll0", "ref_xtal", };
+static const char *cpu_sels[] __initdata = { "cpu_pll", "cpu_xtal", };
+static const char *emi_sels[] __initdata = { "emi_pll", "emi_xtal", };
+static const char *ptp_sels[] __initdata = { "ref_xtal", "pll0", };
 
 enum imx28_clk {
        ref_xtal, pll0, pll1, pll2, ref_cpu, ref_emi, ref_io0, ref_io1,
index 323965430111943b33dad32b3e8d5a889c7dead2..b04c5b9c0ea816e4e900b83268126cecd051e3f5 100644 (file)
@@ -14,7 +14,7 @@
 #define _CLK_PXA_
 
 #define PARENTS(name) \
-       static const char *name ## _parents[] __initconst
+       static const char *name ## _parents[] __initdata
 #define MUX_RO_RATE_RO_OPS(name, clk_name)                     \
        static struct clk_hw name ## _mux_hw;                   \
        static struct clk_hw name ## _rate_hw;                  \
index 39f891bba09a99d2c70af1d882399d95ebc43fe8..4b93a1efb36d11fa7171735d29bac283e4bb6d97 100644 (file)
@@ -336,6 +336,9 @@ static void __init pxa3xx_base_clocks_init(void)
        clk_register_clk_pxa3xx_smemc();
        clk_register_gate(NULL, "CLK_POUT", "osc_13mhz", 0,
                          (void __iomem *)&OSCC, 11, 0, NULL);
+       clkdev_pxa_register(CLK_OSTIMER, "OSTIMER0", NULL,
+                           clk_register_fixed_factor(NULL, "os-timer0",
+                                                     "osc_13mhz", 0, 1, 4));
 }
 
 int __init pxa3xx_clocks_init(void)
index 0d7ab52b7ab0076fec09340410c09bca0efe3b4f..59d16668bdf5e807ab1cdbf8bc4fd12c3b6fb179 100644 (file)
@@ -1,6 +1,7 @@
 config COMMON_CLK_QCOM
        tristate "Support for Qualcomm's clock controllers"
        depends on OF
+       depends on ARCH_QCOM || COMPILE_TEST
        select REGMAP_MMIO
        select RESET_CONTROLLER
 
@@ -46,6 +47,14 @@ config MSM_GCC_8660
          Say Y if you want to use peripheral devices such as UART, SPI,
          i2c, USB, SD/eMMC, etc.
 
+config MSM_GCC_8916
+       tristate "MSM8916 Global Clock Controller"
+       depends on COMMON_CLK_QCOM
+       help
+         Support for the global clock controller on msm8916 devices.
+         Say Y if you want to use devices such as UART, SPI i2c, USB,
+         SD/eMMC, display, graphics, camera etc.
+
 config MSM_GCC_8960
        tristate "APQ8064/MSM8960 Global Clock Controller"
        depends on COMMON_CLK_QCOM
index 61782646959534bec2b19d445762abbec7fb1591..50b337a24a87a08066823342a2ca9a452f825c90 100644 (file)
@@ -15,6 +15,7 @@ obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o
 obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o
 obj-$(CONFIG_IPQ_LCC_806X) += lcc-ipq806x.o
 obj-$(CONFIG_MSM_GCC_8660) += gcc-msm8660.o
+obj-$(CONFIG_MSM_GCC_8916) += gcc-msm8916.o
 obj-$(CONFIG_MSM_GCC_8960) += gcc-msm8960.o
 obj-$(CONFIG_MSM_LCC_8960) += lcc-msm8960.o
 obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o
index b4325f65a1bf6f225811936c9a00927391c62787..245d5063a385968a5081050b7ef679f86a71b124 100644 (file)
@@ -71,12 +71,8 @@ static int clk_pll_enable(struct clk_hw *hw)
        udelay(50);
 
        /* Enable PLL output. */
-       ret = regmap_update_bits(pll->clkr.regmap, pll->mode_reg, PLL_OUTCTRL,
+       return regmap_update_bits(pll->clkr.regmap, pll->mode_reg, PLL_OUTCTRL,
                                 PLL_OUTCTRL);
-       if (ret)
-               return ret;
-
-       return 0;
 }
 
 static void clk_pll_disable(struct clk_hw *hw)
index 0039bd7d3965370108bba619abdf40009495e693..7b3d62674203e4238cba23ff2eb6530f9bdac23b 100644 (file)
@@ -47,15 +47,20 @@ static u8 clk_rcg_get_parent(struct clk_hw *hw)
        struct clk_rcg *rcg = to_clk_rcg(hw);
        int num_parents = __clk_get_num_parents(hw->clk);
        u32 ns;
-       int i;
+       int i, ret;
 
-       regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns);
+       ret = regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns);
+       if (ret)
+               goto err;
        ns = ns_to_src(&rcg->s, ns);
        for (i = 0; i < num_parents; i++)
-               if (ns == rcg->s.parent_map[i])
+               if (ns == rcg->s.parent_map[i].cfg)
                        return i;
 
-       return -EINVAL;
+err:
+       pr_debug("%s: Clock %s has invalid parent, using default.\n",
+                __func__, __clk_get_name(hw->clk));
+       return 0;
 }
 
 static int reg_to_bank(struct clk_dyn_rcg *rcg, u32 bank)
@@ -70,21 +75,28 @@ static u8 clk_dyn_rcg_get_parent(struct clk_hw *hw)
        int num_parents = __clk_get_num_parents(hw->clk);
        u32 ns, reg;
        int bank;
-       int i;
+       int i, ret;
        struct src_sel *s;
 
-       regmap_read(rcg->clkr.regmap, rcg->bank_reg, &reg);
+       ret = regmap_read(rcg->clkr.regmap, rcg->bank_reg, &reg);
+       if (ret)
+               goto err;
        bank = reg_to_bank(rcg, reg);
        s = &rcg->s[bank];
 
-       regmap_read(rcg->clkr.regmap, rcg->ns_reg[bank], &ns);
+       ret = regmap_read(rcg->clkr.regmap, rcg->ns_reg[bank], &ns);
+       if (ret)
+               goto err;
        ns = ns_to_src(s, ns);
 
        for (i = 0; i < num_parents; i++)
-               if (ns == s->parent_map[i])
+               if (ns == s->parent_map[i].cfg)
                        return i;
 
-       return -EINVAL;
+err:
+       pr_debug("%s: Clock %s has invalid parent, using default.\n",
+                __func__, __clk_get_name(hw->clk));
+       return 0;
 }
 
 static int clk_rcg_set_parent(struct clk_hw *hw, u8 index)
@@ -93,7 +105,7 @@ static int clk_rcg_set_parent(struct clk_hw *hw, u8 index)
        u32 ns;
 
        regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns);
-       ns = src_to_ns(&rcg->s, rcg->s.parent_map[index], ns);
+       ns = src_to_ns(&rcg->s, rcg->s.parent_map[index].cfg, ns);
        regmap_write(rcg->clkr.regmap, rcg->ns_reg, ns);
 
        return 0;
@@ -191,10 +203,10 @@ static u32 mn_to_reg(struct mn *mn, u32 m, u32 n, u32 val)
        return val;
 }
 
-static void configure_bank(struct clk_dyn_rcg *rcg, const struct freq_tbl *f)
+static int configure_bank(struct clk_dyn_rcg *rcg, const struct freq_tbl *f)
 {
        u32 ns, md, reg;
-       int bank, new_bank;
+       int bank, new_bank, ret, index;
        struct mn *mn;
        struct pre_div *p;
        struct src_sel *s;
@@ -206,38 +218,56 @@ static void configure_bank(struct clk_dyn_rcg *rcg, const struct freq_tbl *f)
 
        enabled = __clk_is_enabled(hw->clk);
 
-       regmap_read(rcg->clkr.regmap, rcg->bank_reg, &reg);
+       ret = regmap_read(rcg->clkr.regmap, rcg->bank_reg, &reg);
+       if (ret)
+               return ret;
        bank = reg_to_bank(rcg, reg);
        new_bank = enabled ? !bank : bank;
 
        ns_reg = rcg->ns_reg[new_bank];
-       regmap_read(rcg->clkr.regmap, ns_reg, &ns);
+       ret = regmap_read(rcg->clkr.regmap, ns_reg, &ns);
+       if (ret)
+               return ret;
 
        if (banked_mn) {
                mn = &rcg->mn[new_bank];
                md_reg = rcg->md_reg[new_bank];
 
                ns |= BIT(mn->mnctr_reset_bit);
-               regmap_write(rcg->clkr.regmap, ns_reg, ns);
+               ret = regmap_write(rcg->clkr.regmap, ns_reg, ns);
+               if (ret)
+                       return ret;
 
-               regmap_read(rcg->clkr.regmap, md_reg, &md);
+               ret = regmap_read(rcg->clkr.regmap, md_reg, &md);
+               if (ret)
+                       return ret;
                md = mn_to_md(mn, f->m, f->n, md);
-               regmap_write(rcg->clkr.regmap, md_reg, md);
-
+               ret = regmap_write(rcg->clkr.regmap, md_reg, md);
+               if (ret)
+                       return ret;
                ns = mn_to_ns(mn, f->m, f->n, ns);
-               regmap_write(rcg->clkr.regmap, ns_reg, ns);
+               ret = regmap_write(rcg->clkr.regmap, ns_reg, ns);
+               if (ret)
+                       return ret;
 
                /* Two NS registers means mode control is in NS register */
                if (rcg->ns_reg[0] != rcg->ns_reg[1]) {
                        ns = mn_to_reg(mn, f->m, f->n, ns);
-                       regmap_write(rcg->clkr.regmap, ns_reg, ns);
+                       ret = regmap_write(rcg->clkr.regmap, ns_reg, ns);
+                       if (ret)
+                               return ret;
                } else {
                        reg = mn_to_reg(mn, f->m, f->n, reg);
-                       regmap_write(rcg->clkr.regmap, rcg->bank_reg, reg);
+                       ret = regmap_write(rcg->clkr.regmap, rcg->bank_reg,
+                                          reg);
+                       if (ret)
+                               return ret;
                }
 
                ns &= ~BIT(mn->mnctr_reset_bit);
-               regmap_write(rcg->clkr.regmap, ns_reg, ns);
+               ret = regmap_write(rcg->clkr.regmap, ns_reg, ns);
+               if (ret)
+                       return ret;
        }
 
        if (banked_p) {
@@ -246,14 +276,24 @@ static void configure_bank(struct clk_dyn_rcg *rcg, const struct freq_tbl *f)
        }
 
        s = &rcg->s[new_bank];
-       ns = src_to_ns(s, s->parent_map[f->src], ns);
-       regmap_write(rcg->clkr.regmap, ns_reg, ns);
+       index = qcom_find_src_index(hw, s->parent_map, f->src);
+       if (index < 0)
+               return index;
+       ns = src_to_ns(s, s->parent_map[index].cfg, ns);
+       ret = regmap_write(rcg->clkr.regmap, ns_reg, ns);
+       if (ret)
+               return ret;
 
        if (enabled) {
-               regmap_read(rcg->clkr.regmap, rcg->bank_reg, &reg);
+               ret = regmap_read(rcg->clkr.regmap, rcg->bank_reg, &reg);
+               if (ret)
+                       return ret;
                reg ^= BIT(rcg->mux_sel_bit);
-               regmap_write(rcg->clkr.regmap, rcg->bank_reg, reg);
+               ret = regmap_write(rcg->clkr.regmap, rcg->bank_reg, reg);
+               if (ret)
+                       return ret;
        }
+       return 0;
 }
 
 static int clk_dyn_rcg_set_parent(struct clk_hw *hw, u8 index)
@@ -279,10 +319,8 @@ static int clk_dyn_rcg_set_parent(struct clk_hw *hw, u8 index)
        if (banked_p)
                f.pre_div = ns_to_pre_div(&rcg->p[bank], ns) + 1;
 
-       f.src = index;
-       configure_bank(rcg, &f);
-
-       return 0;
+       f.src = qcom_find_src_index(hw, rcg->s[bank].parent_map, index);
+       return configure_bank(rcg, &f);
 }
 
 /*
@@ -369,17 +407,23 @@ clk_dyn_rcg_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
 static long _freq_tbl_determine_rate(struct clk_hw *hw,
                const struct freq_tbl *f, unsigned long rate,
                unsigned long min_rate, unsigned long max_rate,
-               unsigned long *p_rate, struct clk_hw **p_hw)
+               unsigned long *p_rate, struct clk_hw **p_hw,
+               const struct parent_map *parent_map)
 {
        unsigned long clk_flags;
        struct clk *p;
+       int index;
 
        f = qcom_find_freq(f, rate);
        if (!f)
                return -EINVAL;
 
+       index = qcom_find_src_index(hw, parent_map, f->src);
+       if (index < 0)
+               return index;
+
        clk_flags = __clk_get_flags(hw->clk);
-       p = clk_get_parent_by_index(hw->clk, f->src);
+       p = clk_get_parent_by_index(hw->clk, index);
        if (clk_flags & CLK_SET_RATE_PARENT) {
                rate = rate * f->pre_div;
                if (f->n) {
@@ -404,7 +448,7 @@ static long clk_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
        struct clk_rcg *rcg = to_clk_rcg(hw);
 
        return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, min_rate,
-                       max_rate, p_rate, p);
+                       max_rate, p_rate, p, rcg->s.parent_map);
 }
 
 static long clk_dyn_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
@@ -412,9 +456,16 @@ static long clk_dyn_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
                unsigned long *p_rate, struct clk_hw **p)
 {
        struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw);
+       u32 reg;
+       int bank;
+       struct src_sel *s;
+
+       regmap_read(rcg->clkr.regmap, rcg->bank_reg, &reg);
+       bank = reg_to_bank(rcg, reg);
+       s = &rcg->s[bank];
 
        return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, min_rate,
-                       max_rate, p_rate, p);
+                       max_rate, p_rate, p, s->parent_map);
 }
 
 static long clk_rcg_bypass_determine_rate(struct clk_hw *hw, unsigned long rate,
@@ -424,8 +475,9 @@ static long clk_rcg_bypass_determine_rate(struct clk_hw *hw, unsigned long rate,
        struct clk_rcg *rcg = to_clk_rcg(hw);
        const struct freq_tbl *f = rcg->freq_tbl;
        struct clk *p;
+       int index = qcom_find_src_index(hw, rcg->s.parent_map, f->src);
 
-       p = clk_get_parent_by_index(hw->clk, f->src);
+       p = clk_get_parent_by_index(hw->clk, index);
        *p_hw = __clk_get_hw(p);
        *p_rate = __clk_round_rate(p, rate);
 
@@ -495,6 +547,57 @@ static int clk_rcg_bypass_set_rate(struct clk_hw *hw, unsigned long rate,
        return __clk_rcg_set_rate(rcg, rcg->freq_tbl);
 }
 
+/*
+ * This type of clock has a glitch-free mux that switches between the output of
+ * the M/N counter and an always on clock source (XO). When clk_set_rate() is
+ * called we need to make sure that we don't switch to the M/N counter if it
+ * isn't clocking because the mux will get stuck and the clock will stop
+ * outputting a clock. This can happen if the framework isn't aware that this
+ * clock is on and so clk_set_rate() doesn't turn on the new parent. To fix
+ * this we switch the mux in the enable/disable ops and reprogram the M/N
+ * counter in the set_rate op. We also make sure to switch away from the M/N
+ * counter in set_rate if software thinks the clock is off.
+ */
+static int clk_rcg_lcc_set_rate(struct clk_hw *hw, unsigned long rate,
+                               unsigned long parent_rate)
+{
+       struct clk_rcg *rcg = to_clk_rcg(hw);
+       const struct freq_tbl *f;
+       int ret;
+       u32 gfm = BIT(10);
+
+       f = qcom_find_freq(rcg->freq_tbl, rate);
+       if (!f)
+               return -EINVAL;
+
+       /* Switch to XO to avoid glitches */
+       regmap_update_bits(rcg->clkr.regmap, rcg->ns_reg, gfm, 0);
+       ret = __clk_rcg_set_rate(rcg, f);
+       /* Switch back to M/N if it's clocking */
+       if (__clk_is_enabled(hw->clk))
+               regmap_update_bits(rcg->clkr.regmap, rcg->ns_reg, gfm, gfm);
+
+       return ret;
+}
+
+static int clk_rcg_lcc_enable(struct clk_hw *hw)
+{
+       struct clk_rcg *rcg = to_clk_rcg(hw);
+       u32 gfm = BIT(10);
+
+       /* Use M/N */
+       return regmap_update_bits(rcg->clkr.regmap, rcg->ns_reg, gfm, gfm);
+}
+
+static void clk_rcg_lcc_disable(struct clk_hw *hw)
+{
+       struct clk_rcg *rcg = to_clk_rcg(hw);
+       u32 gfm = BIT(10);
+
+       /* Use XO */
+       regmap_update_bits(rcg->clkr.regmap, rcg->ns_reg, gfm, 0);
+}
+
 static int __clk_dyn_rcg_set_rate(struct clk_hw *hw, unsigned long rate)
 {
        struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw);
@@ -504,9 +607,7 @@ static int __clk_dyn_rcg_set_rate(struct clk_hw *hw, unsigned long rate)
        if (!f)
                return -EINVAL;
 
-       configure_bank(rcg, f);
-
-       return 0;
+       return configure_bank(rcg, f);
 }
 
 static int clk_dyn_rcg_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -543,6 +644,17 @@ const struct clk_ops clk_rcg_bypass_ops = {
 };
 EXPORT_SYMBOL_GPL(clk_rcg_bypass_ops);
 
+const struct clk_ops clk_rcg_lcc_ops = {
+       .enable = clk_rcg_lcc_enable,
+       .disable = clk_rcg_lcc_disable,
+       .get_parent = clk_rcg_get_parent,
+       .set_parent = clk_rcg_set_parent,
+       .recalc_rate = clk_rcg_recalc_rate,
+       .determine_rate = clk_rcg_determine_rate,
+       .set_rate = clk_rcg_lcc_set_rate,
+};
+EXPORT_SYMBOL_GPL(clk_rcg_lcc_ops);
+
 const struct clk_ops clk_dyn_rcg_ops = {
        .enable = clk_enable_regmap,
        .is_enabled = clk_is_enabled_regmap,
index 687e41f91d7c9f90d99eb80acbd98086d237e4e5..56028bb31d8713f4a627a78027191df58b504bfb 100644 (file)
@@ -25,6 +25,16 @@ struct freq_tbl {
        u16 n;
 };
 
+/**
+ * struct parent_map - map table for PLL source select configuration values
+ * @src: source PLL
+ * @cfg: configuration value
+ */
+struct parent_map {
+       u8 src;
+       u8 cfg;
+};
+
 /**
  * struct mn - M/N:D counter
  * @mnctr_en_bit: bit to enable mn counter
@@ -65,7 +75,7 @@ struct pre_div {
 struct src_sel {
        u8              src_sel_shift;
 #define SRC_SEL_MASK   0x7
-       const u8        *parent_map;
+       const struct parent_map *parent_map;
 };
 
 /**
@@ -96,6 +106,7 @@ struct clk_rcg {
 
 extern const struct clk_ops clk_rcg_ops;
 extern const struct clk_ops clk_rcg_bypass_ops;
+extern const struct clk_ops clk_rcg_lcc_ops;
 
 #define to_clk_rcg(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg, clkr)
 
@@ -150,7 +161,7 @@ struct clk_rcg2 {
        u32                     cmd_rcgr;
        u8                      mnd_width;
        u8                      hid_width;
-       const u8                *parent_map;
+       const struct parent_map *parent_map;
        const struct freq_tbl   *freq_tbl;
        struct clk_regmap       clkr;
 };
index 742acfa18d63798c19c25884ef2b50d508965858..b95d17fbb8d7edb86fa6754d21b47dc6d1e66ee6 100644 (file)
@@ -69,16 +69,19 @@ static u8 clk_rcg2_get_parent(struct clk_hw *hw)
 
        ret = regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &cfg);
        if (ret)
-               return ret;
+               goto err;
 
        cfg &= CFG_SRC_SEL_MASK;
        cfg >>= CFG_SRC_SEL_SHIFT;
 
        for (i = 0; i < num_parents; i++)
-               if (cfg == rcg->parent_map[i])
+               if (cfg == rcg->parent_map[i].cfg)
                        return i;
 
-       return -EINVAL;
+err:
+       pr_debug("%s: Clock %s has invalid parent, using default.\n",
+                __func__, __clk_get_name(hw->clk));
+       return 0;
 }
 
 static int update_config(struct clk_rcg2 *rcg)
@@ -111,10 +114,10 @@ static int clk_rcg2_set_parent(struct clk_hw *hw, u8 index)
 {
        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
        int ret;
+       u32 cfg = rcg->parent_map[index].cfg << CFG_SRC_SEL_SHIFT;
 
        ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG,
-                                CFG_SRC_SEL_MASK,
-                                rcg->parent_map[index] << CFG_SRC_SEL_SHIFT);
+                                CFG_SRC_SEL_MASK, cfg);
        if (ret)
                return ret;
 
@@ -179,13 +182,19 @@ static long _freq_tbl_determine_rate(struct clk_hw *hw,
 {
        unsigned long clk_flags;
        struct clk *p;
+       struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+       int index;
 
        f = qcom_find_freq(f, rate);
        if (!f)
                return -EINVAL;
 
+       index = qcom_find_src_index(hw, rcg->parent_map, f->src);
+       if (index < 0)
+               return index;
+
        clk_flags = __clk_get_flags(hw->clk);
-       p = clk_get_parent_by_index(hw->clk, f->src);
+       p = clk_get_parent_by_index(hw->clk, index);
        if (clk_flags & CLK_SET_RATE_PARENT) {
                if (f->pre_div) {
                        rate /= 2;
@@ -219,7 +228,11 @@ static long clk_rcg2_determine_rate(struct clk_hw *hw, unsigned long rate,
 static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f)
 {
        u32 cfg, mask;
-       int ret;
+       struct clk_hw *hw = &rcg->clkr.hw;
+       int ret, index = qcom_find_src_index(hw, rcg->parent_map, f->src);
+
+       if (index < 0)
+               return index;
 
        if (rcg->mnd_width && f->n) {
                mask = BIT(rcg->mnd_width) - 1;
@@ -242,8 +255,8 @@ static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f)
        mask = BIT(rcg->hid_width) - 1;
        mask |= CFG_SRC_SEL_MASK | CFG_MODE_MASK;
        cfg = f->pre_div << CFG_SRC_DIV_SHIFT;
-       cfg |= rcg->parent_map[f->src] << CFG_SRC_SEL_SHIFT;
-       if (rcg->mnd_width && f->n)
+       cfg |= rcg->parent_map[index].cfg << CFG_SRC_SEL_SHIFT;
+       if (rcg->mnd_width && f->n && (f->m != f->n))
                cfg |= CFG_MODE_DUAL_EDGE;
        ret = regmap_update_bits(rcg->clkr.regmap,
                        rcg->cmd_rcgr + CFG_REG, mask, cfg);
@@ -374,9 +387,10 @@ static long clk_edp_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
        s64 request;
        u32 mask = BIT(rcg->hid_width) - 1;
        u32 hid_div;
+       int index = qcom_find_src_index(hw, rcg->parent_map, f->src);
 
        /* Force the correct parent */
-       *p = __clk_get_hw(clk_get_parent_by_index(hw->clk, f->src));
+       *p = __clk_get_hw(clk_get_parent_by_index(hw->clk, index));
 
        if (src_rate == 810000000)
                frac = frac_table_810m;
@@ -420,6 +434,7 @@ static long clk_byte_determine_rate(struct clk_hw *hw, unsigned long rate,
 {
        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
        const struct freq_tbl *f = rcg->freq_tbl;
+       int index = qcom_find_src_index(hw, rcg->parent_map, f->src);
        unsigned long parent_rate, div;
        u32 mask = BIT(rcg->hid_width) - 1;
        struct clk *p;
@@ -427,7 +442,7 @@ static long clk_byte_determine_rate(struct clk_hw *hw, unsigned long rate,
        if (rate == 0)
                return -EINVAL;
 
-       p = clk_get_parent_by_index(hw->clk, f->src);
+       p = clk_get_parent_by_index(hw->clk, index);
        *p_hw = __clk_get_hw(p);
        *p_rate = parent_rate = __clk_round_rate(p, rate);
 
@@ -489,7 +504,8 @@ static long clk_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
        int delta = 100000;
        const struct freq_tbl *f = rcg->freq_tbl;
        const struct frac_entry *frac = frac_table_pixel;
-       struct clk *parent = clk_get_parent_by_index(hw->clk, f->src);
+       int index = qcom_find_src_index(hw, rcg->parent_map, f->src);
+       struct clk *parent = clk_get_parent_by_index(hw->clk, index);
 
        *p = __clk_get_hw(parent);
 
@@ -518,7 +534,8 @@ static int clk_pixel_set_rate(struct clk_hw *hw, unsigned long rate,
        int delta = 100000;
        u32 mask = BIT(rcg->hid_width) - 1;
        u32 hid_div;
-       struct clk *parent = clk_get_parent_by_index(hw->clk, f.src);
+       int index = qcom_find_src_index(hw, rcg->parent_map, f.src);
+       struct clk *parent = clk_get_parent_by_index(hw->clk, index);
 
        for (; frac->num; frac++) {
                request = (rate * frac->den) / frac->num;
index e20d947db3e50516a132f9e6cc17717da0abd23f..f7101e330b1dd5d1ef182155282275abc1b51405 100644 (file)
@@ -43,6 +43,18 @@ struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, unsigned long rate)
 }
 EXPORT_SYMBOL_GPL(qcom_find_freq);
 
+int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map, u8 src)
+{
+       int i, num_parents = __clk_get_num_parents(hw->clk);
+
+       for (i = 0; i < num_parents; i++)
+               if (src == map[i].src)
+                       return i;
+
+       return -ENOENT;
+}
+EXPORT_SYMBOL_GPL(qcom_find_src_index);
+
 struct regmap *
 qcom_cc_map(struct platform_device *pdev, const struct qcom_cc_desc *desc)
 {
index f519322acdf3be21d4ada6d014a517b459f956a6..7a0e737130630228ef2b27ed4874b5709d0ea682 100644 (file)
@@ -19,6 +19,8 @@ struct clk_regmap;
 struct qcom_reset_map;
 struct regmap;
 struct freq_tbl;
+struct clk_hw;
+struct parent_map;
 
 struct qcom_cc_desc {
        const struct regmap_config *config;
@@ -30,6 +32,8 @@ struct qcom_cc_desc {
 
 extern const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f,
                                             unsigned long rate);
+extern int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map,
+                              u8 src);
 
 extern struct regmap *qcom_cc_map(struct platform_device *pdev,
                                  const struct qcom_cc_desc *desc);
index e3ef90264214ba32d96ca00ec117595e464d7ed9..54a756b90a3742342b5babcd5f38a26dfc4df48c 100644 (file)
 #include "clk-branch.h"
 #include "reset.h"
 
-#define P_XO   0
-#define P_GPLL0        1
-#define P_GPLL1        1
-#define P_GPLL4        2
-#define P_PCIE_0_1_PIPE_CLK 1
-#define P_SATA_ASIC0_CLK 1
-#define P_SATA_RX_CLK 1
-#define P_SLEEP_CLK 1
+enum {
+       P_XO,
+       P_GPLL0,
+       P_GPLL1,
+       P_GPLL4,
+       P_PCIE_0_1_PIPE_CLK,
+       P_SATA_ASIC0_CLK,
+       P_SATA_RX_CLK,
+       P_SLEEP_CLK,
+};
 
-static const u8 gcc_xo_gpll0_map[] = {
-       [P_XO]          = 0,
-       [P_GPLL0]       = 1,
+static const struct parent_map gcc_xo_gpll0_map[] = {
+       { P_XO, 0 },
+       { P_GPLL0, 1 }
 };
 
 static const char *gcc_xo_gpll0[] = {
@@ -51,10 +53,10 @@ static const char *gcc_xo_gpll0[] = {
        "gpll0_vote",
 };
 
-static const u8 gcc_xo_gpll0_gpll4_map[] = {
-       [P_XO]          = 0,
-       [P_GPLL0]       = 1,
-       [P_GPLL4]       = 5,
+static const struct parent_map gcc_xo_gpll0_gpll4_map[] = {
+       { P_XO, 0 },
+       { P_GPLL0, 1 },
+       { P_GPLL4, 5 }
 };
 
 static const char *gcc_xo_gpll0_gpll4[] = {
@@ -63,9 +65,9 @@ static const char *gcc_xo_gpll0_gpll4[] = {
        "gpll4_vote",
 };
 
-static const u8 gcc_xo_sata_asic0_map[] = {
-       [P_XO]                  = 0,
-       [P_SATA_ASIC0_CLK]      = 2,
+static const struct parent_map gcc_xo_sata_asic0_map[] = {
+       { P_XO, 0 },
+       { P_SATA_ASIC0_CLK, 2 }
 };
 
 static const char *gcc_xo_sata_asic0[] = {
@@ -73,9 +75,9 @@ static const char *gcc_xo_sata_asic0[] = {
        "sata_asic0_clk",
 };
 
-static const u8 gcc_xo_sata_rx_map[] = {
-       [P_XO]                  = 0,
-       [P_SATA_RX_CLK]         = 2,
+static const struct parent_map gcc_xo_sata_rx_map[] = {
+       { P_XO, 0 },
+       { P_SATA_RX_CLK, 2}
 };
 
 static const char *gcc_xo_sata_rx[] = {
@@ -83,9 +85,9 @@ static const char *gcc_xo_sata_rx[] = {
        "sata_rx_clk",
 };
 
-static const u8 gcc_xo_pcie_map[] = {
-       [P_XO]                  = 0,
-       [P_PCIE_0_1_PIPE_CLK]   = 2,
+static const struct parent_map gcc_xo_pcie_map[] = {
+       { P_XO, 0 },
+       { P_PCIE_0_1_PIPE_CLK, 2 }
 };
 
 static const char *gcc_xo_pcie[] = {
@@ -93,9 +95,9 @@ static const char *gcc_xo_pcie[] = {
        "pcie_pipe",
 };
 
-static const u8 gcc_xo_pcie_sleep_map[] = {
-       [P_XO]                  = 0,
-       [P_SLEEP_CLK]           = 6,
+static const struct parent_map gcc_xo_pcie_sleep_map[] = {
+       { P_XO, 0 },
+       { P_SLEEP_CLK, 6 }
 };
 
 static const char *gcc_xo_pcie_sleep[] = {
@@ -1263,9 +1265,9 @@ static const struct freq_tbl ftbl_gcc_usb_hsic_clk[] = {
        { }
 };
 
-static u8 usb_hsic_clk_src_map[] = {
-       [P_XO]          = 0,
-       [P_GPLL1]       = 4,
+static const struct parent_map usb_hsic_clk_src_map[] = {
+       { P_XO, 0 },
+       { P_GPLL1, 4 }
 };
 
 static struct clk_rcg2 usb_hsic_clk_src = {
index cbdc31dea7f4311d091b938959179b3dd97e0fbe..a50936a17376b3654a6449c78554254aea19824a 100644 (file)
@@ -140,15 +140,17 @@ static struct clk_regmap pll14_vote = {
        },
 };
 
-#define P_PXO  0
-#define P_PLL8 1
-#define P_PLL3 1
-#define P_PLL0 2
-#define P_CXO  2
+enum {
+       P_PXO,
+       P_PLL8,
+       P_PLL3,
+       P_PLL0,
+       P_CXO,
+};
 
-static const u8 gcc_pxo_pll8_map[] = {
-       [P_PXO]         = 0,
-       [P_PLL8]        = 3,
+static const struct parent_map gcc_pxo_pll8_map[] = {
+       { P_PXO, 0 },
+       { P_PLL8, 3 }
 };
 
 static const char *gcc_pxo_pll8[] = {
@@ -156,10 +158,10 @@ static const char *gcc_pxo_pll8[] = {
        "pll8_vote",
 };
 
-static const u8 gcc_pxo_pll8_cxo_map[] = {
-       [P_PXO]         = 0,
-       [P_PLL8]        = 3,
-       [P_CXO]         = 5,
+static const struct parent_map gcc_pxo_pll8_cxo_map[] = {
+       { P_PXO, 0 },
+       { P_PLL8, 3 },
+       { P_CXO, 5 }
 };
 
 static const char *gcc_pxo_pll8_cxo[] = {
@@ -168,14 +170,14 @@ static const char *gcc_pxo_pll8_cxo[] = {
        "cxo",
 };
 
-static const u8 gcc_pxo_pll3_map[] = {
-       [P_PXO]         = 0,
-       [P_PLL3]        = 1,
+static const struct parent_map gcc_pxo_pll3_map[] = {
+       { P_PXO, 0 },
+       { P_PLL3, 1 }
 };
 
-static const u8 gcc_pxo_pll3_sata_map[] = {
-       [P_PXO]         = 0,
-       [P_PLL3]        = 6,
+static const struct parent_map gcc_pxo_pll3_sata_map[] = {
+       { P_PXO, 0 },
+       { P_PLL3, 6 }
 };
 
 static const char *gcc_pxo_pll3[] = {
@@ -183,10 +185,10 @@ static const char *gcc_pxo_pll3[] = {
        "pll3",
 };
 
-static const u8 gcc_pxo_pll8_pll0[] = {
-       [P_PXO]         = 0,
-       [P_PLL8]        = 3,
-       [P_PLL0]        = 2,
+static const struct parent_map gcc_pxo_pll8_pll0[] = {
+       { P_PXO, 0 },
+       { P_PLL8, 3 },
+       { P_PLL0, 2 }
 };
 
 static const char *gcc_pxo_pll8_pll0_map[] = {
@@ -525,8 +527,8 @@ static struct freq_tbl clk_tbl_gsbi_qup[] = {
        { 10800000, P_PXO,  1, 2,  5 },
        { 15060000, P_PLL8, 1, 2, 51 },
        { 24000000, P_PLL8, 4, 1,  4 },
+       { 25000000, P_PXO,  1, 0,  0 },
        { 25600000, P_PLL8, 1, 1, 15 },
-       { 27000000, P_PXO,  1, 0,  0 },
        { 48000000, P_PLL8, 4, 1,  2 },
        { 51200000, P_PLL8, 1, 2, 15 },
        { }
@@ -2170,6 +2172,36 @@ static struct clk_branch usb_fs1_h_clk = {
        },
 };
 
+static struct clk_branch ebi2_clk = {
+       .hwcg_reg = 0x3b00,
+       .hwcg_bit = 6,
+       .halt_reg = 0x2fcc,
+       .halt_bit = 1,
+       .clkr = {
+               .enable_reg = 0x3b00,
+               .enable_mask = BIT(4),
+               .hw.init = &(struct clk_init_data){
+                       .name = "ebi2_clk",
+                       .ops = &clk_branch_ops,
+                       .flags = CLK_IS_ROOT,
+               },
+       },
+};
+
+static struct clk_branch ebi2_aon_clk = {
+       .halt_reg = 0x2fcc,
+       .halt_bit = 0,
+       .clkr = {
+               .enable_reg = 0x3b00,
+               .enable_mask = BIT(8),
+               .hw.init = &(struct clk_init_data){
+                       .name = "ebi2_always_on_clk",
+                       .ops = &clk_branch_ops,
+                       .flags = CLK_IS_ROOT,
+               },
+       },
+};
+
 static struct clk_regmap *gcc_ipq806x_clks[] = {
        [PLL0] = &pll0.clkr,
        [PLL0_VOTE] = &pll0_vote,
@@ -2273,6 +2305,8 @@ static struct clk_regmap *gcc_ipq806x_clks[] = {
        [USB_FS1_XCVR_SRC] = &usb_fs1_xcvr_clk_src.clkr,
        [USB_FS1_XCVR_CLK] = &usb_fs1_xcvr_clk.clkr,
        [USB_FS1_SYSTEM_CLK] = &usb_fs1_sys_clk.clkr,
+       [EBI2_CLK] = &ebi2_clk.clkr,
+       [EBI2_AON_CLK] = &ebi2_aon_clk.clkr,
 };
 
 static const struct qcom_reset_map gcc_ipq806x_resets[] = {
index f366e68f73163137aa974d1cfaf8f7592f7bdaaa..fc6b12da5b306916b771583334ebaf39b9a0336c 100644 (file)
@@ -59,13 +59,15 @@ static struct clk_regmap pll8_vote = {
        },
 };
 
-#define P_PXO  0
-#define P_PLL8 1
-#define P_CXO  2
+enum {
+       P_PXO,
+       P_PLL8,
+       P_CXO,
+};
 
-static const u8 gcc_pxo_pll8_map[] = {
-       [P_PXO]         = 0,
-       [P_PLL8]        = 3,
+static const struct parent_map gcc_pxo_pll8_map[] = {
+       { P_PXO, 0 },
+       { P_PLL8, 3 }
 };
 
 static const char *gcc_pxo_pll8[] = {
@@ -73,10 +75,10 @@ static const char *gcc_pxo_pll8[] = {
        "pll8_vote",
 };
 
-static const u8 gcc_pxo_pll8_cxo_map[] = {
-       [P_PXO]         = 0,
-       [P_PLL8]        = 3,
-       [P_CXO]         = 5,
+static const struct parent_map gcc_pxo_pll8_cxo_map[] = {
+       { P_PXO, 0 },
+       { P_PLL8, 3 },
+       { P_CXO, 5 }
 };
 
 static const char *gcc_pxo_pll8_cxo[] = {
diff --git a/drivers/clk/qcom/gcc-msm8916.c b/drivers/clk/qcom/gcc-msm8916.c
new file mode 100644 (file)
index 0000000..d345847
--- /dev/null
@@ -0,0 +1,2868 @@
+/*
+ * Copyright 2015 Linaro Limited
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+
+#include <dt-bindings/clock/qcom,gcc-msm8916.h>
+#include <dt-bindings/reset/qcom,gcc-msm8916.h>
+
+#include "common.h"
+#include "clk-regmap.h"
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-branch.h"
+#include "reset.h"
+
+enum {
+       P_XO,
+       P_GPLL0,
+       P_GPLL0_AUX,
+       P_BIMC,
+       P_GPLL1,
+       P_GPLL1_AUX,
+       P_GPLL2,
+       P_GPLL2_AUX,
+       P_SLEEP_CLK,
+       P_DSI0_PHYPLL_BYTE,
+       P_DSI0_PHYPLL_DSI,
+};
+
+static const struct parent_map gcc_xo_gpll0_map[] = {
+       { P_XO, 0 },
+       { P_GPLL0, 1 },
+};
+
+static const char *gcc_xo_gpll0[] = {
+       "xo",
+       "gpll0_vote",
+};
+
+static const struct parent_map gcc_xo_gpll0_bimc_map[] = {
+       { P_XO, 0 },
+       { P_GPLL0, 1 },
+       { P_BIMC, 2 },
+};
+
+static const char *gcc_xo_gpll0_bimc[] = {
+       "xo",
+       "gpll0_vote",
+       "bimc_pll_vote",
+};
+
+static const struct parent_map gcc_xo_gpll0a_gpll1_gpll2a_map[] = {
+       { P_XO, 0 },
+       { P_GPLL0_AUX, 3 },
+       { P_GPLL2_AUX, 2 },
+       { P_GPLL1, 1 },
+};
+
+static const char *gcc_xo_gpll0a_gpll1_gpll2a[] = {
+       "xo",
+       "gpll0_vote",
+       "gpll1_vote",
+       "gpll2_vote",
+};
+
+static const struct parent_map gcc_xo_gpll0_gpll2_map[] = {
+       { P_XO, 0 },
+       { P_GPLL0, 1 },
+       { P_GPLL2, 2 },
+};
+
+static const char *gcc_xo_gpll0_gpll2[] = {
+       "xo",
+       "gpll0_vote",
+       "gpll2_vote",
+};
+
+static const struct parent_map gcc_xo_gpll0a_map[] = {
+       { P_XO, 0 },
+       { P_GPLL0_AUX, 2 },
+};
+
+static const char *gcc_xo_gpll0a[] = {
+       "xo",
+       "gpll0_vote",
+};
+
+static const struct parent_map gcc_xo_gpll0_gpll1a_sleep_map[] = {
+       { P_XO, 0 },
+       { P_GPLL0, 1 },
+       { P_GPLL1_AUX, 2 },
+       { P_SLEEP_CLK, 6 },
+};
+
+static const char *gcc_xo_gpll0_gpll1a_sleep[] = {
+       "xo",
+       "gpll0_vote",
+       "gpll1_vote",
+       "sleep_clk",
+};
+
+static const struct parent_map gcc_xo_gpll0_gpll1a_map[] = {
+       { P_XO, 0 },
+       { P_GPLL0, 1 },
+       { P_GPLL1_AUX, 2 },
+};
+
+static const char *gcc_xo_gpll0_gpll1a[] = {
+       "xo",
+       "gpll0_vote",
+       "gpll1_vote",
+};
+
+static const struct parent_map gcc_xo_dsibyte_map[] = {
+       { P_XO, 0, },
+       { P_DSI0_PHYPLL_BYTE, 2 },
+};
+
+static const char *gcc_xo_dsibyte[] = {
+       "xo",
+       "dsi0pllbyte",
+};
+
+static const struct parent_map gcc_xo_gpll0a_dsibyte_map[] = {
+       { P_XO, 0 },
+       { P_GPLL0_AUX, 2 },
+       { P_DSI0_PHYPLL_BYTE, 1 },
+};
+
+static const char *gcc_xo_gpll0a_dsibyte[] = {
+       "xo",
+       "gpll0_vote",
+       "dsi0pllbyte",
+};
+
+static const struct parent_map gcc_xo_gpll0_dsiphy_map[] = {
+       { P_XO, 0 },
+       { P_GPLL0, 1 },
+       { P_DSI0_PHYPLL_DSI, 2 },
+};
+
+static const char *gcc_xo_gpll0_dsiphy[] = {
+       "xo",
+       "gpll0_vote",
+       "dsi0pll",
+};
+
+static const struct parent_map gcc_xo_gpll0a_dsiphy_map[] = {
+       { P_XO, 0 },
+       { P_GPLL0_AUX, 2 },
+       { P_DSI0_PHYPLL_DSI, 1 },
+};
+
+static const char *gcc_xo_gpll0a_dsiphy[] = {
+       "xo",
+       "gpll0_vote",
+       "dsi0pll",
+};
+
+static const struct parent_map gcc_xo_gpll0a_gpll1_gpll2_map[] = {
+       { P_XO, 0 },
+       { P_GPLL0_AUX, 1 },
+       { P_GPLL1, 3 },
+       { P_GPLL2, 2 },
+};
+
+static const char *gcc_xo_gpll0a_gpll1_gpll2[] = {
+       "xo",
+       "gpll0_vote",
+       "gpll1_vote",
+       "gpll2_vote",
+};
+
+#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
+
+static struct clk_pll gpll0 = {
+       .l_reg = 0x21004,
+       .m_reg = 0x21008,
+       .n_reg = 0x2100c,
+       .config_reg = 0x21014,
+       .mode_reg = 0x21000,
+       .status_reg = 0x2101c,
+       .status_bit = 17,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gpll0",
+               .parent_names = (const char *[]){ "xo" },
+               .num_parents = 1,
+               .ops = &clk_pll_ops,
+       },
+};
+
+static struct clk_regmap gpll0_vote = {
+       .enable_reg = 0x45000,
+       .enable_mask = BIT(0),
+       .hw.init = &(struct clk_init_data){
+               .name = "gpll0_vote",
+               .parent_names = (const char *[]){ "gpll0" },
+               .num_parents = 1,
+               .ops = &clk_pll_vote_ops,
+       },
+};
+
+static struct clk_pll gpll1 = {
+       .l_reg = 0x20004,
+       .m_reg = 0x20008,
+       .n_reg = 0x2000c,
+       .config_reg = 0x20014,
+       .mode_reg = 0x20000,
+       .status_reg = 0x2001c,
+       .status_bit = 17,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gpll1",
+               .parent_names = (const char *[]){ "xo" },
+               .num_parents = 1,
+               .ops = &clk_pll_ops,
+       },
+};
+
+static struct clk_regmap gpll1_vote = {
+       .enable_reg = 0x45000,
+       .enable_mask = BIT(1),
+       .hw.init = &(struct clk_init_data){
+               .name = "gpll1_vote",
+               .parent_names = (const char *[]){ "gpll1" },
+               .num_parents = 1,
+               .ops = &clk_pll_vote_ops,
+       },
+};
+
+static struct clk_pll gpll2 = {
+       .l_reg = 0x4a004,
+       .m_reg = 0x4a008,
+       .n_reg = 0x4a00c,
+       .config_reg = 0x4a014,
+       .mode_reg = 0x4a000,
+       .status_reg = 0x4a01c,
+       .status_bit = 17,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gpll2",
+               .parent_names = (const char *[]){ "xo" },
+               .num_parents = 1,
+               .ops = &clk_pll_ops,
+       },
+};
+
+static struct clk_regmap gpll2_vote = {
+       .enable_reg = 0x45000,
+       .enable_mask = BIT(2),
+       .hw.init = &(struct clk_init_data){
+               .name = "gpll2_vote",
+               .parent_names = (const char *[]){ "gpll2" },
+               .num_parents = 1,
+               .ops = &clk_pll_vote_ops,
+       },
+};
+
+static struct clk_pll bimc_pll = {
+       .l_reg = 0x23004,
+       .m_reg = 0x23008,
+       .n_reg = 0x2300c,
+       .config_reg = 0x23014,
+       .mode_reg = 0x23000,
+       .status_reg = 0x2301c,
+       .status_bit = 17,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "bimc_pll",
+               .parent_names = (const char *[]){ "xo" },
+               .num_parents = 1,
+               .ops = &clk_pll_ops,
+       },
+};
+
+static struct clk_regmap bimc_pll_vote = {
+       .enable_reg = 0x45000,
+       .enable_mask = BIT(3),
+       .hw.init = &(struct clk_init_data){
+               .name = "bimc_pll_vote",
+               .parent_names = (const char *[]){ "bimc_pll" },
+               .num_parents = 1,
+               .ops = &clk_pll_vote_ops,
+       },
+};
+
+static struct clk_rcg2 pcnoc_bfdcd_clk_src = {
+       .cmd_rcgr = 0x27000,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_bimc_map,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "pcnoc_bfdcd_clk_src",
+               .parent_names = gcc_xo_gpll0_bimc,
+               .num_parents = 3,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 system_noc_bfdcd_clk_src = {
+       .cmd_rcgr = 0x26004,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_bimc_map,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "system_noc_bfdcd_clk_src",
+               .parent_names = gcc_xo_gpll0_bimc,
+               .num_parents = 3,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_camss_ahb_clk[] = {
+       F(40000000, P_GPLL0, 10, 1, 2),
+       F(80000000, P_GPLL0, 10, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 camss_ahb_clk_src = {
+       .cmd_rcgr = 0x5a000,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_gcc_camss_ahb_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "camss_ahb_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_apss_ahb_clk[] = {
+       F(19200000, P_XO, 1, 0, 0),
+       F(50000000, P_GPLL0, 16, 0, 0),
+       F(100000000, P_GPLL0, 8, 0, 0),
+       F(133330000, P_GPLL0, 6, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 apss_ahb_clk_src = {
+       .cmd_rcgr = 0x46000,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_apss_ahb_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "apss_ahb_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_camss_csi0_1_clk[] = {
+       F(100000000, P_GPLL0, 8, 0,     0),
+       F(200000000, P_GPLL0, 4, 0,     0),
+       { }
+};
+
+static struct clk_rcg2 csi0_clk_src = {
+       .cmd_rcgr = 0x4e020,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_gcc_camss_csi0_1_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "csi0_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 csi1_clk_src = {
+       .cmd_rcgr = 0x4f020,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_gcc_camss_csi0_1_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "csi1_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_oxili_gfx3d_clk[] = {
+       F(19200000, P_XO, 1, 0, 0),
+       F(50000000, P_GPLL0_AUX, 16, 0, 0),
+       F(80000000, P_GPLL0_AUX, 10, 0, 0),
+       F(100000000, P_GPLL0_AUX, 8, 0, 0),
+       F(160000000, P_GPLL0_AUX, 5, 0, 0),
+       F(177780000, P_GPLL0_AUX, 4.5, 0, 0),
+       F(200000000, P_GPLL0_AUX, 4, 0, 0),
+       F(266670000, P_GPLL0_AUX, 3, 0, 0),
+       F(294912000, P_GPLL1, 3, 0, 0),
+       F(310000000, P_GPLL2, 3, 0, 0),
+       F(400000000, P_GPLL0_AUX, 2, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 gfx3d_clk_src = {
+       .cmd_rcgr = 0x59000,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0a_gpll1_gpll2a_map,
+       .freq_tbl = ftbl_gcc_oxili_gfx3d_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gfx3d_clk_src",
+               .parent_names = gcc_xo_gpll0a_gpll1_gpll2a,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_camss_vfe0_clk[] = {
+       F(50000000, P_GPLL0, 16, 0, 0),
+       F(80000000, P_GPLL0, 10, 0, 0),
+       F(100000000, P_GPLL0, 8, 0, 0),
+       F(160000000, P_GPLL0, 5, 0, 0),
+       F(177780000, P_GPLL0, 4.5, 0, 0),
+       F(200000000, P_GPLL0, 4, 0, 0),
+       F(266670000, P_GPLL0, 3, 0, 0),
+       F(320000000, P_GPLL0, 2.5, 0, 0),
+       F(400000000, P_GPLL0, 2, 0, 0),
+       F(465000000, P_GPLL2, 2, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 vfe0_clk_src = {
+       .cmd_rcgr = 0x58000,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_gpll2_map,
+       .freq_tbl = ftbl_gcc_camss_vfe0_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "vfe0_clk_src",
+               .parent_names = gcc_xo_gpll0_gpll2,
+               .num_parents = 3,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_blsp1_qup1_6_i2c_apps_clk[] = {
+       F(19200000, P_XO, 1, 0, 0),
+       F(50000000, P_GPLL0, 16, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = {
+       .cmd_rcgr = 0x0200c,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_gcc_blsp1_qup1_6_i2c_apps_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "blsp1_qup1_i2c_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_blsp1_qup1_6_spi_apps_clk[] = {
+       F(960000, P_XO, 10, 1, 2),
+       F(4800000, P_XO, 4, 0, 0),
+       F(9600000, P_XO, 2, 0, 0),
+       F(16000000, P_GPLL0, 10, 1, 5),
+       F(19200000, P_XO, 1, 0, 0),
+       F(25000000, P_GPLL0, 16, 1, 2),
+       F(50000000, P_GPLL0, 16, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src = {
+       .cmd_rcgr = 0x02024,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "blsp1_qup1_spi_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp1_qup2_i2c_apps_clk_src = {
+       .cmd_rcgr = 0x03000,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_gcc_blsp1_qup1_6_i2c_apps_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "blsp1_qup2_i2c_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp1_qup2_spi_apps_clk_src = {
+       .cmd_rcgr = 0x03014,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "blsp1_qup2_spi_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp1_qup3_i2c_apps_clk_src = {
+       .cmd_rcgr = 0x04000,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_gcc_blsp1_qup1_6_i2c_apps_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "blsp1_qup3_i2c_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp1_qup3_spi_apps_clk_src = {
+       .cmd_rcgr = 0x04024,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "blsp1_qup3_spi_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp1_qup4_i2c_apps_clk_src = {
+       .cmd_rcgr = 0x05000,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_gcc_blsp1_qup1_6_i2c_apps_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "blsp1_qup4_i2c_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp1_qup4_spi_apps_clk_src = {
+       .cmd_rcgr = 0x05024,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "blsp1_qup4_spi_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp1_qup5_i2c_apps_clk_src = {
+       .cmd_rcgr = 0x06000,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_gcc_blsp1_qup1_6_i2c_apps_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "blsp1_qup5_i2c_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp1_qup5_spi_apps_clk_src = {
+       .cmd_rcgr = 0x06024,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "blsp1_qup5_spi_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp1_qup6_i2c_apps_clk_src = {
+       .cmd_rcgr = 0x07000,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_gcc_blsp1_qup1_6_i2c_apps_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "blsp1_qup6_i2c_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp1_qup6_spi_apps_clk_src = {
+       .cmd_rcgr = 0x07024,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "blsp1_qup6_spi_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_blsp1_uart1_6_apps_clk[] = {
+       F(3686400, P_GPLL0, 1, 72, 15625),
+       F(7372800, P_GPLL0, 1, 144, 15625),
+       F(14745600, P_GPLL0, 1, 288, 15625),
+       F(16000000, P_GPLL0, 10, 1, 5),
+       F(19200000, P_XO, 1, 0, 0),
+       F(24000000, P_GPLL0, 1, 3, 100),
+       F(25000000, P_GPLL0, 16, 1, 2),
+       F(32000000, P_GPLL0, 1, 1, 25),
+       F(40000000, P_GPLL0, 1, 1, 20),
+       F(46400000, P_GPLL0, 1, 29, 500),
+       F(48000000, P_GPLL0, 1, 3, 50),
+       F(51200000, P_GPLL0, 1, 8, 125),
+       F(56000000, P_GPLL0, 1, 7, 100),
+       F(58982400, P_GPLL0, 1, 1152, 15625),
+       F(60000000, P_GPLL0, 1, 3, 40),
+       { }
+};
+
+static struct clk_rcg2 blsp1_uart1_apps_clk_src = {
+       .cmd_rcgr = 0x02044,
+       .mnd_width = 16,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "blsp1_uart1_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 blsp1_uart2_apps_clk_src = {
+       .cmd_rcgr = 0x03034,
+       .mnd_width = 16,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "blsp1_uart2_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_camss_cci_clk[] = {
+       F(19200000,     P_XO, 1, 0,     0),
+       { }
+};
+
+static struct clk_rcg2 cci_clk_src = {
+       .cmd_rcgr = 0x51000,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0a_map,
+       .freq_tbl = ftbl_gcc_camss_cci_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "cci_clk_src",
+               .parent_names = gcc_xo_gpll0a,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_camss_gp0_1_clk[] = {
+       F(100000000, P_GPLL0, 8, 0, 0),
+       F(200000000, P_GPLL0, 4, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 camss_gp0_clk_src = {
+       .cmd_rcgr = 0x54000,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_gpll1a_sleep_map,
+       .freq_tbl = ftbl_gcc_camss_gp0_1_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "camss_gp0_clk_src",
+               .parent_names = gcc_xo_gpll0_gpll1a_sleep,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 camss_gp1_clk_src = {
+       .cmd_rcgr = 0x55000,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_gpll1a_sleep_map,
+       .freq_tbl = ftbl_gcc_camss_gp0_1_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "camss_gp1_clk_src",
+               .parent_names = gcc_xo_gpll0_gpll1a_sleep,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_camss_jpeg0_clk[] = {
+       F(133330000, P_GPLL0, 6, 0,     0),
+       F(266670000, P_GPLL0, 3, 0,     0),
+       F(320000000, P_GPLL0, 2.5, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 jpeg0_clk_src = {
+       .cmd_rcgr = 0x57000,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_gcc_camss_jpeg0_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "jpeg0_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_camss_mclk0_1_clk[] = {
+       F(9600000, P_XO, 2, 0, 0),
+       F(23880000, P_GPLL0, 1, 2, 67),
+       F(66670000, P_GPLL0, 12, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 mclk0_clk_src = {
+       .cmd_rcgr = 0x52000,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_gpll1a_sleep_map,
+       .freq_tbl = ftbl_gcc_camss_mclk0_1_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "mclk0_clk_src",
+               .parent_names = gcc_xo_gpll0_gpll1a_sleep,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 mclk1_clk_src = {
+       .cmd_rcgr = 0x53000,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_gpll1a_sleep_map,
+       .freq_tbl = ftbl_gcc_camss_mclk0_1_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "mclk1_clk_src",
+               .parent_names = gcc_xo_gpll0_gpll1a_sleep,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_camss_csi0_1phytimer_clk[] = {
+       F(100000000, P_GPLL0, 8, 0,     0),
+       F(200000000, P_GPLL0, 4, 0,     0),
+       { }
+};
+
+static struct clk_rcg2 csi0phytimer_clk_src = {
+       .cmd_rcgr = 0x4e000,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_gpll1a_map,
+       .freq_tbl = ftbl_gcc_camss_csi0_1phytimer_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "csi0phytimer_clk_src",
+               .parent_names = gcc_xo_gpll0_gpll1a,
+               .num_parents = 3,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 csi1phytimer_clk_src = {
+       .cmd_rcgr = 0x4f000,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_gpll1a_map,
+       .freq_tbl = ftbl_gcc_camss_csi0_1phytimer_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "csi1phytimer_clk_src",
+               .parent_names = gcc_xo_gpll0_gpll1a,
+               .num_parents = 3,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_camss_cpp_clk[] = {
+       F(160000000, P_GPLL0, 5, 0, 0),
+       F(320000000, P_GPLL0, 2.5, 0, 0),
+       F(465000000, P_GPLL2, 2, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 cpp_clk_src = {
+       .cmd_rcgr = 0x58018,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_gpll2_map,
+       .freq_tbl = ftbl_gcc_camss_cpp_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "cpp_clk_src",
+               .parent_names = gcc_xo_gpll0_gpll2,
+               .num_parents = 3,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_crypto_clk[] = {
+       F(50000000, P_GPLL0, 16, 0, 0),
+       F(80000000, P_GPLL0, 10, 0, 0),
+       F(100000000, P_GPLL0, 8, 0, 0),
+       F(160000000, P_GPLL0, 5, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 crypto_clk_src = {
+       .cmd_rcgr = 0x16004,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_gcc_crypto_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "crypto_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_gp1_3_clk[] = {
+       F(19200000, P_XO, 1, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 gp1_clk_src = {
+       .cmd_rcgr = 0x08004,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_gpll1a_sleep_map,
+       .freq_tbl = ftbl_gcc_gp1_3_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gp1_clk_src",
+               .parent_names = gcc_xo_gpll0_gpll1a_sleep,
+               .num_parents = 3,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 gp2_clk_src = {
+       .cmd_rcgr = 0x09004,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_gpll1a_sleep_map,
+       .freq_tbl = ftbl_gcc_gp1_3_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gp2_clk_src",
+               .parent_names = gcc_xo_gpll0_gpll1a_sleep,
+               .num_parents = 3,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_rcg2 gp3_clk_src = {
+       .cmd_rcgr = 0x0a004,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_gpll1a_sleep_map,
+       .freq_tbl = ftbl_gcc_gp1_3_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "gp3_clk_src",
+               .parent_names = gcc_xo_gpll0_gpll1a_sleep,
+               .num_parents = 3,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct freq_tbl ftbl_gcc_mdss_byte0_clk[] = {
+       { .src = P_DSI0_PHYPLL_BYTE },
+       { }
+};
+
+static struct clk_rcg2 byte0_clk_src = {
+       .cmd_rcgr = 0x4d044,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0a_dsibyte_map,
+       .freq_tbl = ftbl_gcc_mdss_byte0_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "byte0_clk_src",
+               .parent_names = gcc_xo_gpll0a_dsibyte,
+               .num_parents = 3,
+               .ops = &clk_byte_ops,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_mdss_esc0_clk[] = {
+       F(19200000, P_XO, 1, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 esc0_clk_src = {
+       .cmd_rcgr = 0x4d05c,
+       .hid_width = 5,
+       .parent_map = gcc_xo_dsibyte_map,
+       .freq_tbl = ftbl_gcc_mdss_esc0_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "esc0_clk_src",
+               .parent_names = gcc_xo_dsibyte,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_mdss_mdp_clk[] = {
+       F(50000000, P_GPLL0, 16, 0, 0),
+       F(80000000, P_GPLL0, 10, 0, 0),
+       F(100000000, P_GPLL0, 8, 0, 0),
+       F(160000000, P_GPLL0, 5, 0, 0),
+       F(177780000, P_GPLL0, 4.5, 0, 0),
+       F(200000000, P_GPLL0, 4, 0, 0),
+       F(266670000, P_GPLL0, 3, 0, 0),
+       F(320000000, P_GPLL0, 2.5, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 mdp_clk_src = {
+       .cmd_rcgr = 0x4d014,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_dsiphy_map,
+       .freq_tbl = ftbl_gcc_mdss_mdp_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "mdp_clk_src",
+               .parent_names = gcc_xo_gpll0_dsiphy,
+               .num_parents = 3,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct freq_tbl ftbl_gcc_mdss_pclk[] = {
+       { .src = P_DSI0_PHYPLL_DSI },
+       { }
+};
+
+static struct clk_rcg2 pclk0_clk_src = {
+       .cmd_rcgr = 0x4d000,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0a_dsiphy_map,
+       .freq_tbl = ftbl_gcc_mdss_pclk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "pclk0_clk_src",
+               .parent_names = gcc_xo_gpll0a_dsiphy,
+               .num_parents = 3,
+               .ops = &clk_pixel_ops,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_mdss_vsync_clk[] = {
+       F(19200000, P_XO, 1, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 vsync_clk_src = {
+       .cmd_rcgr = 0x4d02c,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0a_map,
+       .freq_tbl = ftbl_gcc_mdss_vsync_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "vsync_clk_src",
+               .parent_names = gcc_xo_gpll0a,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_pdm2_clk[] = {
+       F(64000000, P_GPLL0, 12.5, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 pdm2_clk_src = {
+       .cmd_rcgr = 0x44010,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_gcc_pdm2_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "pdm2_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk[] = {
+       F(144000, P_XO, 16, 3, 25),
+       F(400000, P_XO, 12, 1, 4),
+       F(20000000, P_GPLL0, 10, 1, 4),
+       F(25000000, P_GPLL0, 16, 1, 2),
+       F(50000000, P_GPLL0, 16, 0, 0),
+       F(100000000, P_GPLL0, 8, 0, 0),
+       F(177770000, P_GPLL0, 4.5, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 sdcc1_apps_clk_src = {
+       .cmd_rcgr = 0x42004,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_gcc_sdcc1_apps_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "sdcc1_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk[] = {
+       F(144000, P_XO, 16, 3, 25),
+       F(400000, P_XO, 12, 1, 4),
+       F(20000000, P_GPLL0, 10, 1, 4),
+       F(25000000, P_GPLL0, 16, 1, 2),
+       F(50000000, P_GPLL0, 16, 0, 0),
+       F(100000000, P_GPLL0, 8, 0, 0),
+       F(200000000, P_GPLL0, 4, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 sdcc2_apps_clk_src = {
+       .cmd_rcgr = 0x43004,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_gcc_sdcc2_apps_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "sdcc2_apps_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_apss_tcu_clk[] = {
+       F(155000000, P_GPLL2, 6, 0, 0),
+       F(310000000, P_GPLL2, 3, 0, 0),
+       F(400000000, P_GPLL0, 2, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 apss_tcu_clk_src = {
+       .cmd_rcgr = 0x1207c,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0a_gpll1_gpll2_map,
+       .freq_tbl = ftbl_gcc_apss_tcu_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "apss_tcu_clk_src",
+               .parent_names = gcc_xo_gpll0a_gpll1_gpll2,
+               .num_parents = 4,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_usb_hs_system_clk[] = {
+       F(80000000, P_GPLL0, 10, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 usb_hs_system_clk_src = {
+       .cmd_rcgr = 0x41010,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_gcc_usb_hs_system_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "usb_hs_system_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static const struct freq_tbl ftbl_gcc_venus0_vcodec0_clk[] = {
+       F(100000000, P_GPLL0, 8, 0, 0),
+       F(160000000, P_GPLL0, 5, 0, 0),
+       F(228570000, P_GPLL0, 5, 0, 0),
+       { }
+};
+
+static struct clk_rcg2 vcodec0_clk_src = {
+       .cmd_rcgr = 0x4C000,
+       .mnd_width = 8,
+       .hid_width = 5,
+       .parent_map = gcc_xo_gpll0_map,
+       .freq_tbl = ftbl_gcc_venus0_vcodec0_clk,
+       .clkr.hw.init = &(struct clk_init_data){
+               .name = "vcodec0_clk_src",
+               .parent_names = gcc_xo_gpll0,
+               .num_parents = 2,
+               .ops = &clk_rcg2_ops,
+       },
+};
+
+static struct clk_branch gcc_blsp1_ahb_clk = {
+       .halt_reg = 0x01008,
+       .halt_check = BRANCH_HALT_VOTED,
+       .clkr = {
+               .enable_reg = 0x45004,
+               .enable_mask = BIT(10),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_blsp1_ahb_clk",
+                       .parent_names = (const char *[]){
+                               "pcnoc_bfdcd_clk_src",
+                       },
+                       .num_parents = 1,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_sleep_clk = {
+       .halt_reg = 0x01004,
+       .clkr = {
+               .enable_reg = 0x01004,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_blsp1_sleep_clk",
+                       .parent_names = (const char *[]){
+                               "sleep_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup1_i2c_apps_clk = {
+       .halt_reg = 0x02008,
+       .clkr = {
+               .enable_reg = 0x02008,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_blsp1_qup1_i2c_apps_clk",
+                       .parent_names = (const char *[]){
+                               "blsp1_qup1_i2c_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup1_spi_apps_clk = {
+       .halt_reg = 0x02004,
+       .clkr = {
+               .enable_reg = 0x02004,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_blsp1_qup1_spi_apps_clk",
+                       .parent_names = (const char *[]){
+                               "blsp1_qup1_spi_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup2_i2c_apps_clk = {
+       .halt_reg = 0x03010,
+       .clkr = {
+               .enable_reg = 0x03010,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_blsp1_qup2_i2c_apps_clk",
+                       .parent_names = (const char *[]){
+                               "blsp1_qup2_i2c_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup2_spi_apps_clk = {
+       .halt_reg = 0x0300c,
+       .clkr = {
+               .enable_reg = 0x0300c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_blsp1_qup2_spi_apps_clk",
+                       .parent_names = (const char *[]){
+                               "blsp1_qup2_spi_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup3_i2c_apps_clk = {
+       .halt_reg = 0x04020,
+       .clkr = {
+               .enable_reg = 0x04020,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_blsp1_qup3_i2c_apps_clk",
+                       .parent_names = (const char *[]){
+                               "blsp1_qup3_i2c_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup3_spi_apps_clk = {
+       .halt_reg = 0x0401c,
+       .clkr = {
+               .enable_reg = 0x0401c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_blsp1_qup3_spi_apps_clk",
+                       .parent_names = (const char *[]){
+                               "blsp1_qup3_spi_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup4_i2c_apps_clk = {
+       .halt_reg = 0x05020,
+       .clkr = {
+               .enable_reg = 0x05020,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_blsp1_qup4_i2c_apps_clk",
+                       .parent_names = (const char *[]){
+                               "blsp1_qup4_i2c_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup4_spi_apps_clk = {
+       .halt_reg = 0x0501c,
+       .clkr = {
+               .enable_reg = 0x0501c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_blsp1_qup4_spi_apps_clk",
+                       .parent_names = (const char *[]){
+                               "blsp1_qup4_spi_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup5_i2c_apps_clk = {
+       .halt_reg = 0x06020,
+       .clkr = {
+               .enable_reg = 0x06020,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_blsp1_qup5_i2c_apps_clk",
+                       .parent_names = (const char *[]){
+                               "blsp1_qup5_i2c_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup5_spi_apps_clk = {
+       .halt_reg = 0x0601c,
+       .clkr = {
+               .enable_reg = 0x0601c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_blsp1_qup5_spi_apps_clk",
+                       .parent_names = (const char *[]){
+                               "blsp1_qup5_spi_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup6_i2c_apps_clk = {
+       .halt_reg = 0x07020,
+       .clkr = {
+               .enable_reg = 0x07020,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_blsp1_qup6_i2c_apps_clk",
+                       .parent_names = (const char *[]){
+                               "blsp1_qup6_i2c_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_qup6_spi_apps_clk = {
+       .halt_reg = 0x0701c,
+       .clkr = {
+               .enable_reg = 0x0701c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_blsp1_qup6_spi_apps_clk",
+                       .parent_names = (const char *[]){
+                               "blsp1_qup6_spi_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_uart1_apps_clk = {
+       .halt_reg = 0x0203c,
+       .clkr = {
+               .enable_reg = 0x0203c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_blsp1_uart1_apps_clk",
+                       .parent_names = (const char *[]){
+                               "blsp1_uart1_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_blsp1_uart2_apps_clk = {
+       .halt_reg = 0x0302c,
+       .clkr = {
+               .enable_reg = 0x0302c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_blsp1_uart2_apps_clk",
+                       .parent_names = (const char *[]){
+                               "blsp1_uart2_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_boot_rom_ahb_clk = {
+       .halt_reg = 0x1300c,
+       .halt_check = BRANCH_HALT_VOTED,
+       .clkr = {
+               .enable_reg = 0x45004,
+               .enable_mask = BIT(7),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_boot_rom_ahb_clk",
+                       .parent_names = (const char *[]){
+                               "pcnoc_bfdcd_clk_src",
+                       },
+                       .num_parents = 1,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_camss_cci_ahb_clk = {
+       .halt_reg = 0x5101c,
+       .clkr = {
+               .enable_reg = 0x5101c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_camss_cci_ahb_clk",
+                       .parent_names = (const char *[]){
+                               "camss_ahb_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_camss_cci_clk = {
+       .halt_reg = 0x51018,
+       .clkr = {
+               .enable_reg = 0x51018,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_camss_cci_clk",
+                       .parent_names = (const char *[]){
+                               "cci_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_camss_csi0_ahb_clk = {
+       .halt_reg = 0x4e040,
+       .clkr = {
+               .enable_reg = 0x4e040,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_camss_csi0_ahb_clk",
+                       .parent_names = (const char *[]){
+                               "camss_ahb_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_camss_csi0_clk = {
+       .halt_reg = 0x4e03c,
+       .clkr = {
+               .enable_reg = 0x4e03c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_camss_csi0_clk",
+                       .parent_names = (const char *[]){
+                               "csi0_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_camss_csi0phy_clk = {
+       .halt_reg = 0x4e048,
+       .clkr = {
+               .enable_reg = 0x4e048,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_camss_csi0phy_clk",
+                       .parent_names = (const char *[]){
+                               "csi0_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_camss_csi0pix_clk = {
+       .halt_reg = 0x4e058,
+       .clkr = {
+               .enable_reg = 0x4e058,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_camss_csi0pix_clk",
+                       .parent_names = (const char *[]){
+                               "csi0_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_camss_csi0rdi_clk = {
+       .halt_reg = 0x4e050,
+       .clkr = {
+               .enable_reg = 0x4e050,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_camss_csi0rdi_clk",
+                       .parent_names = (const char *[]){
+                               "csi0_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_camss_csi1_ahb_clk = {
+       .halt_reg = 0x4f040,
+       .clkr = {
+               .enable_reg = 0x4f040,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_camss_csi1_ahb_clk",
+                       .parent_names = (const char *[]){
+                               "camss_ahb_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_camss_csi1_clk = {
+       .halt_reg = 0x4f03c,
+       .clkr = {
+               .enable_reg = 0x4f03c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_camss_csi1_clk",
+                       .parent_names = (const char *[]){
+                               "csi1_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_camss_csi1phy_clk = {
+       .halt_reg = 0x4f048,
+       .clkr = {
+               .enable_reg = 0x4f048,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_camss_csi1phy_clk",
+                       .parent_names = (const char *[]){
+                               "csi1_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_camss_csi1pix_clk = {
+       .halt_reg = 0x4f058,
+       .clkr = {
+               .enable_reg = 0x4f058,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_camss_csi1pix_clk",
+                       .parent_names = (const char *[]){
+                               "csi1_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_camss_csi1rdi_clk = {
+       .halt_reg = 0x4f050,
+       .clkr = {
+               .enable_reg = 0x4f050,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_camss_csi1rdi_clk",
+                       .parent_names = (const char *[]){
+                               "csi1_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_camss_csi_vfe0_clk = {
+       .halt_reg = 0x58050,
+       .clkr = {
+               .enable_reg = 0x58050,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_camss_csi_vfe0_clk",
+                       .parent_names = (const char *[]){
+                               "vfe0_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_camss_gp0_clk = {
+       .halt_reg = 0x54018,
+       .clkr = {
+               .enable_reg = 0x54018,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_camss_gp0_clk",
+                       .parent_names = (const char *[]){
+                               "camss_gp0_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_camss_gp1_clk = {
+       .halt_reg = 0x55018,
+       .clkr = {
+               .enable_reg = 0x55018,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_camss_gp1_clk",
+                       .parent_names = (const char *[]){
+                               "camss_gp1_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_camss_ispif_ahb_clk = {
+       .halt_reg = 0x50004,
+       .clkr = {
+               .enable_reg = 0x50004,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_camss_ispif_ahb_clk",
+                       .parent_names = (const char *[]){
+                               "camss_ahb_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_camss_jpeg0_clk = {
+       .halt_reg = 0x57020,
+       .clkr = {
+               .enable_reg = 0x57020,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_camss_jpeg0_clk",
+                       .parent_names = (const char *[]){
+                               "jpeg0_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_camss_jpeg_ahb_clk = {
+       .halt_reg = 0x57024,
+       .clkr = {
+               .enable_reg = 0x57024,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_camss_jpeg_ahb_clk",
+                       .parent_names = (const char *[]){
+                               "camss_ahb_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_camss_jpeg_axi_clk = {
+       .halt_reg = 0x57028,
+       .clkr = {
+               .enable_reg = 0x57028,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_camss_jpeg_axi_clk",
+                       .parent_names = (const char *[]){
+                               "system_noc_bfdcd_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_camss_mclk0_clk = {
+       .halt_reg = 0x52018,
+       .clkr = {
+               .enable_reg = 0x52018,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_camss_mclk0_clk",
+                       .parent_names = (const char *[]){
+                               "mclk0_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_camss_mclk1_clk = {
+       .halt_reg = 0x53018,
+       .clkr = {
+               .enable_reg = 0x53018,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_camss_mclk1_clk",
+                       .parent_names = (const char *[]){
+                               "mclk1_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_camss_micro_ahb_clk = {
+       .halt_reg = 0x5600c,
+       .clkr = {
+               .enable_reg = 0x5600c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_camss_micro_ahb_clk",
+                       .parent_names = (const char *[]){
+                               "camss_ahb_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_camss_csi0phytimer_clk = {
+       .halt_reg = 0x4e01c,
+       .clkr = {
+               .enable_reg = 0x4e01c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_camss_csi0phytimer_clk",
+                       .parent_names = (const char *[]){
+                               "csi0phytimer_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_camss_csi1phytimer_clk = {
+       .halt_reg = 0x4f01c,
+       .clkr = {
+               .enable_reg = 0x4f01c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_camss_csi1phytimer_clk",
+                       .parent_names = (const char *[]){
+                               "csi1phytimer_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_camss_ahb_clk = {
+       .halt_reg = 0x5a014,
+       .clkr = {
+               .enable_reg = 0x5a014,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_camss_ahb_clk",
+                       .parent_names = (const char *[]){
+                               "camss_ahb_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_camss_top_ahb_clk = {
+       .halt_reg = 0x56004,
+       .clkr = {
+               .enable_reg = 0x56004,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_camss_top_ahb_clk",
+                       .parent_names = (const char *[]){
+                               "pcnoc_bfdcd_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_camss_cpp_ahb_clk = {
+       .halt_reg = 0x58040,
+       .clkr = {
+               .enable_reg = 0x58040,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_camss_cpp_ahb_clk",
+                       .parent_names = (const char *[]){
+                               "camss_ahb_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_camss_cpp_clk = {
+       .halt_reg = 0x5803c,
+       .clkr = {
+               .enable_reg = 0x5803c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_camss_cpp_clk",
+                       .parent_names = (const char *[]){
+                               "cpp_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_camss_vfe0_clk = {
+       .halt_reg = 0x58038,
+       .clkr = {
+               .enable_reg = 0x58038,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_camss_vfe0_clk",
+                       .parent_names = (const char *[]){
+                               "vfe0_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_camss_vfe_ahb_clk = {
+       .halt_reg = 0x58044,
+       .clkr = {
+               .enable_reg = 0x58044,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_camss_vfe_ahb_clk",
+                       .parent_names = (const char *[]){
+                               "camss_ahb_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_camss_vfe_axi_clk = {
+       .halt_reg = 0x58048,
+       .clkr = {
+               .enable_reg = 0x58048,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_camss_vfe_axi_clk",
+                       .parent_names = (const char *[]){
+                               "system_noc_bfdcd_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_crypto_ahb_clk = {
+       .halt_reg = 0x16024,
+       .halt_check = BRANCH_HALT_VOTED,
+       .clkr = {
+               .enable_reg = 0x45004,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_crypto_ahb_clk",
+                       .parent_names = (const char *[]){
+                               "pcnoc_bfdcd_clk_src",
+                       },
+                       .num_parents = 1,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_crypto_axi_clk = {
+       .halt_reg = 0x16020,
+       .halt_check = BRANCH_HALT_VOTED,
+       .clkr = {
+               .enable_reg = 0x45004,
+               .enable_mask = BIT(1),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_crypto_axi_clk",
+                       .parent_names = (const char *[]){
+                               "pcnoc_bfdcd_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_crypto_clk = {
+       .halt_reg = 0x1601c,
+       .halt_check = BRANCH_HALT_VOTED,
+       .clkr = {
+               .enable_reg = 0x45004,
+               .enable_mask = BIT(2),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_crypto_clk",
+                       .parent_names = (const char *[]){
+                               "crypto_clk_src",
+                       },
+                       .num_parents = 1,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_oxili_gmem_clk = {
+       .halt_reg = 0x59024,
+       .clkr = {
+               .enable_reg = 0x59024,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_oxili_gmem_clk",
+                       .parent_names = (const char *[]){
+                               "gfx3d_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_gp1_clk = {
+       .halt_reg = 0x08000,
+       .clkr = {
+               .enable_reg = 0x08000,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_gp1_clk",
+                       .parent_names = (const char *[]){
+                               "gp1_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_gp2_clk = {
+       .halt_reg = 0x09000,
+       .clkr = {
+               .enable_reg = 0x09000,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_gp2_clk",
+                       .parent_names = (const char *[]){
+                               "gp2_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_gp3_clk = {
+       .halt_reg = 0x0a000,
+       .clkr = {
+               .enable_reg = 0x0a000,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_gp3_clk",
+                       .parent_names = (const char *[]){
+                               "gp3_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_mdss_ahb_clk = {
+       .halt_reg = 0x4d07c,
+       .clkr = {
+               .enable_reg = 0x4d07c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_mdss_ahb_clk",
+                       .parent_names = (const char *[]){
+                               "pcnoc_bfdcd_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_mdss_axi_clk = {
+       .halt_reg = 0x4d080,
+       .clkr = {
+               .enable_reg = 0x4d080,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_mdss_axi_clk",
+                       .parent_names = (const char *[]){
+                               "system_noc_bfdcd_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_mdss_byte0_clk = {
+       .halt_reg = 0x4d094,
+       .clkr = {
+               .enable_reg = 0x4d094,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_mdss_byte0_clk",
+                       .parent_names = (const char *[]){
+                               "byte0_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_mdss_esc0_clk = {
+       .halt_reg = 0x4d098,
+       .clkr = {
+               .enable_reg = 0x4d098,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_mdss_esc0_clk",
+                       .parent_names = (const char *[]){
+                               "esc0_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_mdss_mdp_clk = {
+       .halt_reg = 0x4D088,
+       .clkr = {
+               .enable_reg = 0x4D088,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_mdss_mdp_clk",
+                       .parent_names = (const char *[]){
+                               "mdp_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_mdss_pclk0_clk = {
+       .halt_reg = 0x4d084,
+       .clkr = {
+               .enable_reg = 0x4d084,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_mdss_pclk0_clk",
+                       .parent_names = (const char *[]){
+                               "pclk0_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_mdss_vsync_clk = {
+       .halt_reg = 0x4d090,
+       .clkr = {
+               .enable_reg = 0x4d090,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_mdss_vsync_clk",
+                       .parent_names = (const char *[]){
+                               "vsync_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_mss_cfg_ahb_clk = {
+       .halt_reg = 0x49000,
+       .clkr = {
+               .enable_reg = 0x49000,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_mss_cfg_ahb_clk",
+                       .parent_names = (const char *[]){
+                               "pcnoc_bfdcd_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_oxili_ahb_clk = {
+       .halt_reg = 0x59028,
+       .clkr = {
+               .enable_reg = 0x59028,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_oxili_ahb_clk",
+                       .parent_names = (const char *[]){
+                               "pcnoc_bfdcd_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_oxili_gfx3d_clk = {
+       .halt_reg = 0x59020,
+       .clkr = {
+               .enable_reg = 0x59020,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_oxili_gfx3d_clk",
+                       .parent_names = (const char *[]){
+                               "gfx3d_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_pdm2_clk = {
+       .halt_reg = 0x4400c,
+       .clkr = {
+               .enable_reg = 0x4400c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_pdm2_clk",
+                       .parent_names = (const char *[]){
+                               "pdm2_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_pdm_ahb_clk = {
+       .halt_reg = 0x44004,
+       .clkr = {
+               .enable_reg = 0x44004,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_pdm_ahb_clk",
+                       .parent_names = (const char *[]){
+                               "pcnoc_bfdcd_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_prng_ahb_clk = {
+       .halt_reg = 0x13004,
+       .halt_check = BRANCH_HALT_VOTED,
+       .clkr = {
+               .enable_reg = 0x45004,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_prng_ahb_clk",
+                       .parent_names = (const char *[]){
+                               "pcnoc_bfdcd_clk_src",
+                       },
+                       .num_parents = 1,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_sdcc1_ahb_clk = {
+       .halt_reg = 0x4201c,
+       .clkr = {
+               .enable_reg = 0x4201c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_sdcc1_ahb_clk",
+                       .parent_names = (const char *[]){
+                               "pcnoc_bfdcd_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_sdcc1_apps_clk = {
+       .halt_reg = 0x42018,
+       .clkr = {
+               .enable_reg = 0x42018,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_sdcc1_apps_clk",
+                       .parent_names = (const char *[]){
+                               "sdcc1_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_sdcc2_ahb_clk = {
+       .halt_reg = 0x4301c,
+       .clkr = {
+               .enable_reg = 0x4301c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_sdcc2_ahb_clk",
+                       .parent_names = (const char *[]){
+                               "pcnoc_bfdcd_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_sdcc2_apps_clk = {
+       .halt_reg = 0x43018,
+       .clkr = {
+               .enable_reg = 0x43018,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_sdcc2_apps_clk",
+                       .parent_names = (const char *[]){
+                               "sdcc2_apps_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_gtcu_ahb_clk = {
+       .halt_reg = 0x12044,
+       .clkr = {
+               .enable_reg = 0x4500c,
+               .enable_mask = BIT(13),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_gtcu_ahb_clk",
+                       .parent_names = (const char *[]){
+                               "pcnoc_bfdcd_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_jpeg_tbu_clk = {
+       .halt_reg = 0x12034,
+       .clkr = {
+               .enable_reg = 0x4500c,
+               .enable_mask = BIT(10),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_jpeg_tbu_clk",
+                       .parent_names = (const char *[]){
+                               "system_noc_bfdcd_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_mdp_tbu_clk = {
+       .halt_reg = 0x1201c,
+       .clkr = {
+               .enable_reg = 0x4500c,
+               .enable_mask = BIT(4),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_mdp_tbu_clk",
+                       .parent_names = (const char *[]){
+                               "system_noc_bfdcd_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_smmu_cfg_clk = {
+       .halt_reg = 0x12038,
+       .clkr = {
+               .enable_reg = 0x4500c,
+               .enable_mask = BIT(12),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_smmu_cfg_clk",
+                       .parent_names = (const char *[]){
+                               "pcnoc_bfdcd_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_venus_tbu_clk = {
+       .halt_reg = 0x12014,
+       .clkr = {
+               .enable_reg = 0x4500c,
+               .enable_mask = BIT(5),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_venus_tbu_clk",
+                       .parent_names = (const char *[]){
+                               "system_noc_bfdcd_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_vfe_tbu_clk = {
+       .halt_reg = 0x1203c,
+       .clkr = {
+               .enable_reg = 0x4500c,
+               .enable_mask = BIT(9),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_vfe_tbu_clk",
+                       .parent_names = (const char *[]){
+                               "system_noc_bfdcd_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_usb2a_phy_sleep_clk = {
+       .halt_reg = 0x4102c,
+       .clkr = {
+               .enable_reg = 0x4102c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_usb2a_phy_sleep_clk",
+                       .parent_names = (const char *[]){
+                               "sleep_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_usb_hs_ahb_clk = {
+       .halt_reg = 0x41008,
+       .clkr = {
+               .enable_reg = 0x41008,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_usb_hs_ahb_clk",
+                       .parent_names = (const char *[]){
+                               "pcnoc_bfdcd_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_usb_hs_system_clk = {
+       .halt_reg = 0x41004,
+       .clkr = {
+               .enable_reg = 0x41004,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_usb_hs_system_clk",
+                       .parent_names = (const char *[]){
+                               "usb_hs_system_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_venus0_ahb_clk = {
+       .halt_reg = 0x4c020,
+       .clkr = {
+               .enable_reg = 0x4c020,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_venus0_ahb_clk",
+                       .parent_names = (const char *[]){
+                               "pcnoc_bfdcd_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_venus0_axi_clk = {
+       .halt_reg = 0x4c024,
+       .clkr = {
+               .enable_reg = 0x4c024,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_venus0_axi_clk",
+                       .parent_names = (const char *[]){
+                               "system_noc_bfdcd_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_branch gcc_venus0_vcodec0_clk = {
+       .halt_reg = 0x4c01c,
+       .clkr = {
+               .enable_reg = 0x4c01c,
+               .enable_mask = BIT(0),
+               .hw.init = &(struct clk_init_data){
+                       .name = "gcc_venus0_vcodec0_clk",
+                       .parent_names = (const char *[]){
+                               "vcodec0_clk_src",
+                       },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
+                       .ops = &clk_branch2_ops,
+               },
+       },
+};
+
+static struct clk_regmap *gcc_msm8916_clocks[] = {
+       [GPLL0] = &gpll0.clkr,
+       [GPLL0_VOTE] = &gpll0_vote,
+       [BIMC_PLL] = &bimc_pll.clkr,
+       [BIMC_PLL_VOTE] = &bimc_pll_vote,
+       [GPLL1] = &gpll1.clkr,
+       [GPLL1_VOTE] = &gpll1_vote,
+       [GPLL2] = &gpll2.clkr,
+       [GPLL2_VOTE] = &gpll2_vote,
+       [PCNOC_BFDCD_CLK_SRC] = &pcnoc_bfdcd_clk_src.clkr,
+       [SYSTEM_NOC_BFDCD_CLK_SRC] = &system_noc_bfdcd_clk_src.clkr,
+       [CAMSS_AHB_CLK_SRC] = &camss_ahb_clk_src.clkr,
+       [APSS_AHB_CLK_SRC] = &apss_ahb_clk_src.clkr,
+       [CSI0_CLK_SRC] = &csi0_clk_src.clkr,
+       [CSI1_CLK_SRC] = &csi1_clk_src.clkr,
+       [GFX3D_CLK_SRC] = &gfx3d_clk_src.clkr,
+       [VFE0_CLK_SRC] = &vfe0_clk_src.clkr,
+       [BLSP1_QUP1_I2C_APPS_CLK_SRC] = &blsp1_qup1_i2c_apps_clk_src.clkr,
+       [BLSP1_QUP1_SPI_APPS_CLK_SRC] = &blsp1_qup1_spi_apps_clk_src.clkr,
+       [BLSP1_QUP2_I2C_APPS_CLK_SRC] = &blsp1_qup2_i2c_apps_clk_src.clkr,
+       [BLSP1_QUP2_SPI_APPS_CLK_SRC] = &blsp1_qup2_spi_apps_clk_src.clkr,
+       [BLSP1_QUP3_I2C_APPS_CLK_SRC] = &blsp1_qup3_i2c_apps_clk_src.clkr,
+       [BLSP1_QUP3_SPI_APPS_CLK_SRC] = &blsp1_qup3_spi_apps_clk_src.clkr,
+       [BLSP1_QUP4_I2C_APPS_CLK_SRC] = &blsp1_qup4_i2c_apps_clk_src.clkr,
+       [BLSP1_QUP4_SPI_APPS_CLK_SRC] = &blsp1_qup4_spi_apps_clk_src.clkr,
+       [BLSP1_QUP5_I2C_APPS_CLK_SRC] = &blsp1_qup5_i2c_apps_clk_src.clkr,
+       [BLSP1_QUP5_SPI_APPS_CLK_SRC] = &blsp1_qup5_spi_apps_clk_src.clkr,
+       [BLSP1_QUP6_I2C_APPS_CLK_SRC] = &blsp1_qup6_i2c_apps_clk_src.clkr,
+       [BLSP1_QUP6_SPI_APPS_CLK_SRC] = &blsp1_qup6_spi_apps_clk_src.clkr,
+       [BLSP1_UART1_APPS_CLK_SRC] = &blsp1_uart1_apps_clk_src.clkr,
+       [BLSP1_UART2_APPS_CLK_SRC] = &blsp1_uart2_apps_clk_src.clkr,
+       [CCI_CLK_SRC] = &cci_clk_src.clkr,
+       [CAMSS_GP0_CLK_SRC] = &camss_gp0_clk_src.clkr,
+       [CAMSS_GP1_CLK_SRC] = &camss_gp1_clk_src.clkr,
+       [JPEG0_CLK_SRC] = &jpeg0_clk_src.clkr,
+       [MCLK0_CLK_SRC] = &mclk0_clk_src.clkr,
+       [MCLK1_CLK_SRC] = &mclk1_clk_src.clkr,
+       [CSI0PHYTIMER_CLK_SRC] = &csi0phytimer_clk_src.clkr,
+       [CSI1PHYTIMER_CLK_SRC] = &csi1phytimer_clk_src.clkr,
+       [CPP_CLK_SRC] = &cpp_clk_src.clkr,
+       [CRYPTO_CLK_SRC] = &crypto_clk_src.clkr,
+       [GP1_CLK_SRC] = &gp1_clk_src.clkr,
+       [GP2_CLK_SRC] = &gp2_clk_src.clkr,
+       [GP3_CLK_SRC] = &gp3_clk_src.clkr,
+       [BYTE0_CLK_SRC] = &byte0_clk_src.clkr,
+       [ESC0_CLK_SRC] = &esc0_clk_src.clkr,
+       [MDP_CLK_SRC] = &mdp_clk_src.clkr,
+       [PCLK0_CLK_SRC] = &pclk0_clk_src.clkr,
+       [VSYNC_CLK_SRC] = &vsync_clk_src.clkr,
+       [PDM2_CLK_SRC] = &pdm2_clk_src.clkr,
+       [SDCC1_APPS_CLK_SRC] = &sdcc1_apps_clk_src.clkr,
+       [SDCC2_APPS_CLK_SRC] = &sdcc2_apps_clk_src.clkr,
+       [APSS_TCU_CLK_SRC] = &apss_tcu_clk_src.clkr,
+       [USB_HS_SYSTEM_CLK_SRC] = &usb_hs_system_clk_src.clkr,
+       [VCODEC0_CLK_SRC] = &vcodec0_clk_src.clkr,
+       [GCC_BLSP1_AHB_CLK] = &gcc_blsp1_ahb_clk.clkr,
+       [GCC_BLSP1_SLEEP_CLK] = &gcc_blsp1_sleep_clk.clkr,
+       [GCC_BLSP1_QUP1_I2C_APPS_CLK] = &gcc_blsp1_qup1_i2c_apps_clk.clkr,
+       [GCC_BLSP1_QUP1_SPI_APPS_CLK] = &gcc_blsp1_qup1_spi_apps_clk.clkr,
+       [GCC_BLSP1_QUP2_I2C_APPS_CLK] = &gcc_blsp1_qup2_i2c_apps_clk.clkr,
+       [GCC_BLSP1_QUP2_SPI_APPS_CLK] = &gcc_blsp1_qup2_spi_apps_clk.clkr,
+       [GCC_BLSP1_QUP3_I2C_APPS_CLK] = &gcc_blsp1_qup3_i2c_apps_clk.clkr,
+       [GCC_BLSP1_QUP3_SPI_APPS_CLK] = &gcc_blsp1_qup3_spi_apps_clk.clkr,
+       [GCC_BLSP1_QUP4_I2C_APPS_CLK] = &gcc_blsp1_qup4_i2c_apps_clk.clkr,
+       [GCC_BLSP1_QUP4_SPI_APPS_CLK] = &gcc_blsp1_qup4_spi_apps_clk.clkr,
+       [GCC_BLSP1_QUP5_I2C_APPS_CLK] = &gcc_blsp1_qup5_i2c_apps_clk.clkr,
+       [GCC_BLSP1_QUP5_SPI_APPS_CLK] = &gcc_blsp1_qup5_spi_apps_clk.clkr,
+       [GCC_BLSP1_QUP6_I2C_APPS_CLK] = &gcc_blsp1_qup6_i2c_apps_clk.clkr,
+       [GCC_BLSP1_QUP6_SPI_APPS_CLK] = &gcc_blsp1_qup6_spi_apps_clk.clkr,
+       [GCC_BLSP1_UART1_APPS_CLK] = &gcc_blsp1_uart1_apps_clk.clkr,
+       [GCC_BLSP1_UART2_APPS_CLK] = &gcc_blsp1_uart2_apps_clk.clkr,
+       [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr,
+       [GCC_CAMSS_CCI_AHB_CLK] = &gcc_camss_cci_ahb_clk.clkr,
+       [GCC_CAMSS_CCI_CLK] = &gcc_camss_cci_clk.clkr,
+       [GCC_CAMSS_CSI0_AHB_CLK] = &gcc_camss_csi0_ahb_clk.clkr,
+       [GCC_CAMSS_CSI0_CLK] = &gcc_camss_csi0_clk.clkr,
+       [GCC_CAMSS_CSI0PHY_CLK] = &gcc_camss_csi0phy_clk.clkr,
+       [GCC_CAMSS_CSI0PIX_CLK] = &gcc_camss_csi0pix_clk.clkr,
+       [GCC_CAMSS_CSI0RDI_CLK] = &gcc_camss_csi0rdi_clk.clkr,
+       [GCC_CAMSS_CSI1_AHB_CLK] = &gcc_camss_csi1_ahb_clk.clkr,
+       [GCC_CAMSS_CSI1_CLK] = &gcc_camss_csi1_clk.clkr,
+       [GCC_CAMSS_CSI1PHY_CLK] = &gcc_camss_csi1phy_clk.clkr,
+       [GCC_CAMSS_CSI1PIX_CLK] = &gcc_camss_csi1pix_clk.clkr,
+       [GCC_CAMSS_CSI1RDI_CLK] = &gcc_camss_csi1rdi_clk.clkr,
+       [GCC_CAMSS_CSI_VFE0_CLK] = &gcc_camss_csi_vfe0_clk.clkr,
+       [GCC_CAMSS_GP0_CLK] = &gcc_camss_gp0_clk.clkr,
+       [GCC_CAMSS_GP1_CLK] = &gcc_camss_gp1_clk.clkr,
+       [GCC_CAMSS_ISPIF_AHB_CLK] = &gcc_camss_ispif_ahb_clk.clkr,
+       [GCC_CAMSS_JPEG0_CLK] = &gcc_camss_jpeg0_clk.clkr,
+       [GCC_CAMSS_JPEG_AHB_CLK] = &gcc_camss_jpeg_ahb_clk.clkr,
+       [GCC_CAMSS_JPEG_AXI_CLK] = &gcc_camss_jpeg_axi_clk.clkr,
+       [GCC_CAMSS_MCLK0_CLK] = &gcc_camss_mclk0_clk.clkr,
+       [GCC_CAMSS_MCLK1_CLK] = &gcc_camss_mclk1_clk.clkr,
+       [GCC_CAMSS_MICRO_AHB_CLK] = &gcc_camss_micro_ahb_clk.clkr,
+       [GCC_CAMSS_CSI0PHYTIMER_CLK] = &gcc_camss_csi0phytimer_clk.clkr,
+       [GCC_CAMSS_CSI1PHYTIMER_CLK] = &gcc_camss_csi1phytimer_clk.clkr,
+       [GCC_CAMSS_AHB_CLK] = &gcc_camss_ahb_clk.clkr,
+       [GCC_CAMSS_TOP_AHB_CLK] = &gcc_camss_top_ahb_clk.clkr,
+       [GCC_CAMSS_CPP_AHB_CLK] = &gcc_camss_cpp_ahb_clk.clkr,
+       [GCC_CAMSS_CPP_CLK] = &gcc_camss_cpp_clk.clkr,
+       [GCC_CAMSS_VFE0_CLK] = &gcc_camss_vfe0_clk.clkr,
+       [GCC_CAMSS_VFE_AHB_CLK] = &gcc_camss_vfe_ahb_clk.clkr,
+       [GCC_CAMSS_VFE_AXI_CLK] = &gcc_camss_vfe_axi_clk.clkr,
+       [GCC_CRYPTO_AHB_CLK] = &gcc_crypto_ahb_clk.clkr,
+       [GCC_CRYPTO_AXI_CLK] = &gcc_crypto_axi_clk.clkr,
+       [GCC_CRYPTO_CLK] = &gcc_crypto_clk.clkr,
+       [GCC_OXILI_GMEM_CLK] = &gcc_oxili_gmem_clk.clkr,
+       [GCC_GP1_CLK] = &gcc_gp1_clk.clkr,
+       [GCC_GP2_CLK] = &gcc_gp2_clk.clkr,
+       [GCC_GP3_CLK] = &gcc_gp3_clk.clkr,
+       [GCC_MDSS_AHB_CLK] = &gcc_mdss_ahb_clk.clkr,
+       [GCC_MDSS_AXI_CLK] = &gcc_mdss_axi_clk.clkr,
+       [GCC_MDSS_BYTE0_CLK] = &gcc_mdss_byte0_clk.clkr,
+       [GCC_MDSS_ESC0_CLK] = &gcc_mdss_esc0_clk.clkr,
+       [GCC_MDSS_MDP_CLK] = &gcc_mdss_mdp_clk.clkr,
+       [GCC_MDSS_PCLK0_CLK] = &gcc_mdss_pclk0_clk.clkr,
+       [GCC_MDSS_VSYNC_CLK] = &gcc_mdss_vsync_clk.clkr,
+       [GCC_MSS_CFG_AHB_CLK] = &gcc_mss_cfg_ahb_clk.clkr,
+       [GCC_OXILI_AHB_CLK] = &gcc_oxili_ahb_clk.clkr,
+       [GCC_OXILI_GFX3D_CLK] = &gcc_oxili_gfx3d_clk.clkr,
+       [GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr,
+       [GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.clkr,
+       [GCC_PRNG_AHB_CLK] = &gcc_prng_ahb_clk.clkr,
+       [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr,
+       [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr,
+       [GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr,
+       [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr,
+       [GCC_GTCU_AHB_CLK] = &gcc_gtcu_ahb_clk.clkr,
+       [GCC_JPEG_TBU_CLK] = &gcc_jpeg_tbu_clk.clkr,
+       [GCC_MDP_TBU_CLK] = &gcc_mdp_tbu_clk.clkr,
+       [GCC_SMMU_CFG_CLK] = &gcc_smmu_cfg_clk.clkr,
+       [GCC_VENUS_TBU_CLK] = &gcc_venus_tbu_clk.clkr,
+       [GCC_VFE_TBU_CLK] = &gcc_vfe_tbu_clk.clkr,
+       [GCC_USB2A_PHY_SLEEP_CLK] = &gcc_usb2a_phy_sleep_clk.clkr,
+       [GCC_USB_HS_AHB_CLK] = &gcc_usb_hs_ahb_clk.clkr,
+       [GCC_USB_HS_SYSTEM_CLK] = &gcc_usb_hs_system_clk.clkr,
+       [GCC_VENUS0_AHB_CLK] = &gcc_venus0_ahb_clk.clkr,
+       [GCC_VENUS0_AXI_CLK] = &gcc_venus0_axi_clk.clkr,
+       [GCC_VENUS0_VCODEC0_CLK] = &gcc_venus0_vcodec0_clk.clkr,
+};
+
+static const struct qcom_reset_map gcc_msm8916_resets[] = {
+       [GCC_BLSP1_BCR] = { 0x01000 },
+       [GCC_BLSP1_QUP1_BCR] = { 0x02000 },
+       [GCC_BLSP1_UART1_BCR] = { 0x02038 },
+       [GCC_BLSP1_QUP2_BCR] = { 0x03008 },
+       [GCC_BLSP1_UART2_BCR] = { 0x03028 },
+       [GCC_BLSP1_QUP3_BCR] = { 0x04018 },
+       [GCC_BLSP1_QUP4_BCR] = { 0x05018 },
+       [GCC_BLSP1_QUP5_BCR] = { 0x06018 },
+       [GCC_BLSP1_QUP6_BCR] = { 0x07018 },
+       [GCC_IMEM_BCR] = { 0x0e000 },
+       [GCC_SMMU_BCR] = { 0x12000 },
+       [GCC_APSS_TCU_BCR] = { 0x12050 },
+       [GCC_SMMU_XPU_BCR] = { 0x12054 },
+       [GCC_PCNOC_TBU_BCR] = { 0x12058 },
+       [GCC_PRNG_BCR] = { 0x13000 },
+       [GCC_BOOT_ROM_BCR] = { 0x13008 },
+       [GCC_CRYPTO_BCR] = { 0x16000 },
+       [GCC_SEC_CTRL_BCR] = { 0x1a000 },
+       [GCC_AUDIO_CORE_BCR] = { 0x1c008 },
+       [GCC_ULT_AUDIO_BCR] = { 0x1c0b4 },
+       [GCC_DEHR_BCR] = { 0x1f000 },
+       [GCC_SYSTEM_NOC_BCR] = { 0x26000 },
+       [GCC_PCNOC_BCR] = { 0x27018 },
+       [GCC_TCSR_BCR] = { 0x28000 },
+       [GCC_QDSS_BCR] = { 0x29000 },
+       [GCC_DCD_BCR] = { 0x2a000 },
+       [GCC_MSG_RAM_BCR] = { 0x2b000 },
+       [GCC_MPM_BCR] = { 0x2c000 },
+       [GCC_SPMI_BCR] = { 0x2e000 },
+       [GCC_SPDM_BCR] = { 0x2f000 },
+       [GCC_MM_SPDM_BCR] = { 0x2f024 },
+       [GCC_BIMC_BCR] = { 0x31000 },
+       [GCC_RBCPR_BCR] = { 0x33000 },
+       [GCC_TLMM_BCR] = { 0x34000 },
+       [GCC_USB_HS_BCR] = { 0x41000 },
+       [GCC_USB2A_PHY_BCR] = { 0x41028 },
+       [GCC_SDCC1_BCR] = { 0x42000 },
+       [GCC_SDCC2_BCR] = { 0x43000 },
+       [GCC_PDM_BCR] = { 0x44000 },
+       [GCC_SNOC_BUS_TIMEOUT0_BCR] = { 0x47000 },
+       [GCC_PCNOC_BUS_TIMEOUT0_BCR] = { 0x48000 },
+       [GCC_PCNOC_BUS_TIMEOUT1_BCR] = { 0x48008 },
+       [GCC_PCNOC_BUS_TIMEOUT2_BCR] = { 0x48010 },
+       [GCC_PCNOC_BUS_TIMEOUT3_BCR] = { 0x48018 },
+       [GCC_PCNOC_BUS_TIMEOUT4_BCR] = { 0x48020 },
+       [GCC_PCNOC_BUS_TIMEOUT5_BCR] = { 0x48028 },
+       [GCC_PCNOC_BUS_TIMEOUT6_BCR] = { 0x48030 },
+       [GCC_PCNOC_BUS_TIMEOUT7_BCR] = { 0x48038 },
+       [GCC_PCNOC_BUS_TIMEOUT8_BCR] = { 0x48040 },
+       [GCC_PCNOC_BUS_TIMEOUT9_BCR] = { 0x48048 },
+       [GCC_MMSS_BCR] = { 0x4b000 },
+       [GCC_VENUS0_BCR] = { 0x4c014 },
+       [GCC_MDSS_BCR] = { 0x4d074 },
+       [GCC_CAMSS_PHY0_BCR] = { 0x4e018 },
+       [GCC_CAMSS_CSI0_BCR] = { 0x4e038 },
+       [GCC_CAMSS_CSI0PHY_BCR] = { 0x4e044 },
+       [GCC_CAMSS_CSI0RDI_BCR] = { 0x4e04c },
+       [GCC_CAMSS_CSI0PIX_BCR] = { 0x4e054 },
+       [GCC_CAMSS_PHY1_BCR] = { 0x4f018 },
+       [GCC_CAMSS_CSI1_BCR] = { 0x4f038 },
+       [GCC_CAMSS_CSI1PHY_BCR] = { 0x4f044 },
+       [GCC_CAMSS_CSI1RDI_BCR] = { 0x4f04c },
+       [GCC_CAMSS_CSI1PIX_BCR] = { 0x4f054 },
+       [GCC_CAMSS_ISPIF_BCR] = { 0x50000 },
+       [GCC_CAMSS_CCI_BCR] = { 0x51014 },
+       [GCC_CAMSS_MCLK0_BCR] = { 0x52014 },
+       [GCC_CAMSS_MCLK1_BCR] = { 0x53014 },
+       [GCC_CAMSS_GP0_BCR] = { 0x54014 },
+       [GCC_CAMSS_GP1_BCR] = { 0x55014 },
+       [GCC_CAMSS_TOP_BCR] = { 0x56000 },
+       [GCC_CAMSS_MICRO_BCR] = { 0x56008 },
+       [GCC_CAMSS_JPEG_BCR] = { 0x57018 },
+       [GCC_CAMSS_VFE_BCR] = { 0x58030 },
+       [GCC_CAMSS_CSI_VFE0_BCR] = { 0x5804c },
+       [GCC_OXILI_BCR] = { 0x59018 },
+       [GCC_GMEM_BCR] = { 0x5902c },
+       [GCC_CAMSS_AHB_BCR] = { 0x5a018 },
+       [GCC_MDP_TBU_BCR] = { 0x62000 },
+       [GCC_GFX_TBU_BCR] = { 0x63000 },
+       [GCC_GFX_TCU_BCR] = { 0x64000 },
+       [GCC_MSS_TBU_AXI_BCR] = { 0x65000 },
+       [GCC_MSS_TBU_GSS_AXI_BCR] = { 0x66000 },
+       [GCC_MSS_TBU_Q6_AXI_BCR] = { 0x67000 },
+       [GCC_GTCU_AHB_BCR] = { 0x68000 },
+       [GCC_SMMU_CFG_BCR] = { 0x69000 },
+       [GCC_VFE_TBU_BCR] = { 0x6a000 },
+       [GCC_VENUS_TBU_BCR] = { 0x6b000 },
+       [GCC_JPEG_TBU_BCR] = { 0x6c000 },
+       [GCC_PRONTO_TBU_BCR] = { 0x6d000 },
+       [GCC_SMMU_CATS_BCR] = { 0x7c000 },
+};
+
+static const struct regmap_config gcc_msm8916_regmap_config = {
+       .reg_bits       = 32,
+       .reg_stride     = 4,
+       .val_bits       = 32,
+       .max_register   = 0x80000,
+       .fast_io        = true,
+};
+
+static const struct qcom_cc_desc gcc_msm8916_desc = {
+       .config = &gcc_msm8916_regmap_config,
+       .clks = gcc_msm8916_clocks,
+       .num_clks = ARRAY_SIZE(gcc_msm8916_clocks),
+       .resets = gcc_msm8916_resets,
+       .num_resets = ARRAY_SIZE(gcc_msm8916_resets),
+};
+
+static const struct of_device_id gcc_msm8916_match_table[] = {
+       { .compatible = "qcom,gcc-msm8916" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, gcc_msm8916_match_table);
+
+static int gcc_msm8916_probe(struct platform_device *pdev)
+{
+       struct clk *clk;
+       struct device *dev = &pdev->dev;
+
+       /* Temporary until RPM clocks supported */
+       clk = clk_register_fixed_rate(dev, "xo", NULL, CLK_IS_ROOT, 19200000);
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       clk = clk_register_fixed_rate(dev, "sleep_clk_src", NULL,
+                                     CLK_IS_ROOT, 32768);
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       return qcom_cc_probe(pdev, &gcc_msm8916_desc);
+}
+
+static int gcc_msm8916_remove(struct platform_device *pdev)
+{
+       qcom_cc_remove(pdev);
+       return 0;
+}
+
+static struct platform_driver gcc_msm8916_driver = {
+       .probe          = gcc_msm8916_probe,
+       .remove         = gcc_msm8916_remove,
+       .driver         = {
+               .name   = "gcc-msm8916",
+               .of_match_table = gcc_msm8916_match_table,
+       },
+};
+
+static int __init gcc_msm8916_init(void)
+{
+       return platform_driver_register(&gcc_msm8916_driver);
+}
+core_initcall(gcc_msm8916_init);
+
+static void __exit gcc_msm8916_exit(void)
+{
+       platform_driver_unregister(&gcc_msm8916_driver);
+}
+module_exit(gcc_msm8916_exit);
+
+MODULE_DESCRIPTION("Qualcomm GCC MSM8916 Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:gcc-msm8916");
index e60feffc10a151dd77d291c71a81e8cb73234804..eb6a4f9fa107e9af98ab1991f50e22d4c8b503c5 100644 (file)
@@ -113,14 +113,16 @@ static struct clk_regmap pll14_vote = {
        },
 };
 
-#define P_PXO  0
-#define P_PLL8 1
-#define P_PLL3 2
-#define P_CXO  2
+enum {
+       P_PXO,
+       P_PLL8,
+       P_PLL3,
+       P_CXO,
+};
 
-static const u8 gcc_pxo_pll8_map[] = {
-       [P_PXO]         = 0,
-       [P_PLL8]        = 3,
+static const struct parent_map gcc_pxo_pll8_map[] = {
+       { P_PXO, 0 },
+       { P_PLL8, 3 }
 };
 
 static const char *gcc_pxo_pll8[] = {
@@ -128,10 +130,10 @@ static const char *gcc_pxo_pll8[] = {
        "pll8_vote",
 };
 
-static const u8 gcc_pxo_pll8_cxo_map[] = {
-       [P_PXO]         = 0,
-       [P_PLL8]        = 3,
-       [P_CXO]         = 5,
+static const struct parent_map gcc_pxo_pll8_cxo_map[] = {
+       { P_PXO, 0 },
+       { P_PLL8, 3 },
+       { P_CXO, 5 }
 };
 
 static const char *gcc_pxo_pll8_cxo[] = {
@@ -140,10 +142,10 @@ static const char *gcc_pxo_pll8_cxo[] = {
        "cxo",
 };
 
-static const u8 gcc_pxo_pll8_pll3_map[] = {
-       [P_PXO]         = 0,
-       [P_PLL8]        = 3,
-       [P_PLL3]        = 6,
+static const struct parent_map gcc_pxo_pll8_pll3_map[] = {
+       { P_PXO, 0 },
+       { P_PLL8, 3 },
+       { P_PLL3, 6 }
 };
 
 static const char *gcc_pxo_pll8_pll3[] = {
index a6937fe78d8a92b802684e51fde28ba68bfee58e..c39d09874e74d5d05a7f59e437ce5bb1f0ef8199 100644 (file)
 #include "clk-branch.h"
 #include "reset.h"
 
-#define P_XO   0
-#define P_GPLL0        1
-#define P_GPLL1        1
-#define P_GPLL4        2
+enum {
+       P_XO,
+       P_GPLL0,
+       P_GPLL1,
+       P_GPLL4,
+};
 
-static const u8 gcc_xo_gpll0_map[] = {
-       [P_XO]          = 0,
-       [P_GPLL0]       = 1,
+static const struct parent_map gcc_xo_gpll0_map[] = {
+       { P_XO, 0 },
+       { P_GPLL0, 1 }
 };
 
 static const char *gcc_xo_gpll0[] = {
@@ -47,10 +49,10 @@ static const char *gcc_xo_gpll0[] = {
        "gpll0_vote",
 };
 
-static const u8 gcc_xo_gpll0_gpll4_map[] = {
-       [P_XO]          = 0,
-       [P_GPLL0]       = 1,
-       [P_GPLL4]       = 5,
+static const struct parent_map gcc_xo_gpll0_gpll4_map[] = {
+       { P_XO, 0 },
+       { P_GPLL0, 1 },
+       { P_GPLL4, 5 }
 };
 
 static const char *gcc_xo_gpll0_gpll4[] = {
@@ -984,9 +986,9 @@ static const struct freq_tbl ftbl_gcc_usb_hsic_clk[] = {
        { }
 };
 
-static u8 usb_hsic_clk_src_map[] = {
-       [P_XO]          = 0,
-       [P_GPLL1]       = 4,
+static const struct parent_map usb_hsic_clk_src_map[] = {
+       { P_XO, 0 },
+       { P_GPLL1, 4 }
 };
 
 static struct clk_rcg2 usb_hsic_clk_src = {
index c9ff27b4648b56abc37499c1c8f284fc20da05d7..47f0ac16d149c811d9f9ceca241e0d0468d09935 100644 (file)
@@ -61,12 +61,14 @@ static const struct pll_config pll4_config = {
        .main_output_mask = BIT(23),
 };
 
-#define P_PXO  0
-#define P_PLL4 1
+enum {
+       P_PXO,
+       P_PLL4,
+};
 
-static const u8 lcc_pxo_pll4_map[] = {
-       [P_PXO]         = 0,
-       [P_PLL4]        = 2,
+static const struct parent_map lcc_pxo_pll4_map[] = {
+       { P_PXO, 0 },
+       { P_PLL4, 2 }
 };
 
 static const char *lcc_pxo_pll4[] = {
@@ -294,14 +296,14 @@ static struct clk_regmap_mux pcm_clk = {
 };
 
 static struct freq_tbl clk_tbl_aif_osr[] = {
-       {  22050, P_PLL4, 1, 147, 20480 },
-       {  32000, P_PLL4, 1,   1,    96 },
-       {  44100, P_PLL4, 1, 147, 10240 },
-       {  48000, P_PLL4, 1,   1,    64 },
-       {  88200, P_PLL4, 1, 147,  5120 },
-       {  96000, P_PLL4, 1,   1,    32 },
-       { 176400, P_PLL4, 1, 147,  2560 },
-       { 192000, P_PLL4, 1,   1,    16 },
+       {  2822400, P_PLL4, 1, 147, 20480 },
+       {  4096000, P_PLL4, 1,   1,    96 },
+       {  5644800, P_PLL4, 1, 147, 10240 },
+       {  6144000, P_PLL4, 1,   1,    64 },
+       { 11289600, P_PLL4, 1, 147,  5120 },
+       { 12288000, P_PLL4, 1,   1,    32 },
+       { 22579200, P_PLL4, 1, 147,  2560 },
+       { 24576000, P_PLL4, 1,   1,    16 },
        { },
 };
 
@@ -360,7 +362,7 @@ static struct clk_branch spdif_clk = {
 };
 
 static struct freq_tbl clk_tbl_ahbix[] = {
-       { 131072, P_PLL4, 1, 1, 3 },
+       { 131072000, P_PLL4, 1, 1, 3 },
        { },
 };
 
@@ -386,13 +388,12 @@ static struct clk_rcg ahbix_clk = {
        .freq_tbl = clk_tbl_ahbix,
        .clkr = {
                .enable_reg = 0x38,
-               .enable_mask = BIT(10), /* toggle the gfmux to select mn/pxo */
+               .enable_mask = BIT(11),
                .hw.init = &(struct clk_init_data){
                        .name = "ahbix",
                        .parent_names = lcc_pxo_pll4,
                        .num_parents = 2,
-                       .ops = &clk_rcg_ops,
-                       .flags = CLK_SET_RATE_GATE,
+                       .ops = &clk_rcg_lcc_ops,
                },
        },
 };
index e2c863295f001fd5f99071dcf250ddd931967d09..d0df9d5fc3af0a8eda7349bff0a6179a841bfa09 100644 (file)
@@ -47,12 +47,14 @@ static struct clk_pll pll4 = {
        },
 };
 
-#define P_PXO  0
-#define P_PLL4 1
+enum {
+       P_PXO,
+       P_PLL4,
+};
 
-static const u8 lcc_pxo_pll4_map[] = {
-       [P_PXO]         = 0,
-       [P_PLL4]        = 2,
+static const struct parent_map lcc_pxo_pll4_map[] = {
+       { P_PXO, 0 },
+       { P_PLL4, 2 }
 };
 
 static const char *lcc_pxo_pll4[] = {
index 157139a5c1ca956d76d1be30dfb6687f82d01816..1b17df2cb0afdd9350283fddbce43f048fb8acf3 100644 (file)
 #include "clk-branch.h"
 #include "reset.h"
 
-#define P_XO           0
-#define P_MMPLL0       1
-#define P_EDPLINK      1
-#define P_MMPLL1       2
-#define P_HDMIPLL      2
-#define P_GPLL0                3
-#define P_EDPVCO       3
-#define P_MMPLL4       4
-#define P_DSI0PLL      4
-#define P_DSI0PLL_BYTE 4
-#define P_MMPLL2       4
-#define P_MMPLL3       4
-#define P_GPLL1                5
-#define P_DSI1PLL      5
-#define P_DSI1PLL_BYTE 5
-#define P_MMSLEEP      6
-
-static const u8 mmcc_xo_mmpll0_mmpll1_gpll0_map[] = {
-       [P_XO]          = 0,
-       [P_MMPLL0]      = 1,
-       [P_MMPLL1]      = 2,
-       [P_GPLL0]       = 5,
+enum {
+       P_XO,
+       P_MMPLL0,
+       P_EDPLINK,
+       P_MMPLL1,
+       P_HDMIPLL,
+       P_GPLL0,
+       P_EDPVCO,
+       P_MMPLL4,
+       P_DSI0PLL,
+       P_DSI0PLL_BYTE,
+       P_MMPLL2,
+       P_MMPLL3,
+       P_GPLL1,
+       P_DSI1PLL,
+       P_DSI1PLL_BYTE,
+       P_MMSLEEP,
+};
+
+static const struct parent_map mmcc_xo_mmpll0_mmpll1_gpll0_map[] = {
+       { P_XO, 0 },
+       { P_MMPLL0, 1 },
+       { P_MMPLL1, 2 },
+       { P_GPLL0, 5 }
 };
 
 static const char *mmcc_xo_mmpll0_mmpll1_gpll0[] = {
@@ -58,13 +60,13 @@ static const char *mmcc_xo_mmpll0_mmpll1_gpll0[] = {
        "mmss_gpll0_vote",
 };
 
-static const u8 mmcc_xo_mmpll0_dsi_hdmi_gpll0_map[] = {
-       [P_XO]          = 0,
-       [P_MMPLL0]      = 1,
-       [P_HDMIPLL]     = 4,
-       [P_GPLL0]       = 5,
-       [P_DSI0PLL]     = 2,
-       [P_DSI1PLL]     = 3,
+static const struct parent_map mmcc_xo_mmpll0_dsi_hdmi_gpll0_map[] = {
+       { P_XO, 0 },
+       { P_MMPLL0, 1 },
+       { P_HDMIPLL, 4 },
+       { P_GPLL0, 5 },
+       { P_DSI0PLL, 2 },
+       { P_DSI1PLL, 3 }
 };
 
 static const char *mmcc_xo_mmpll0_dsi_hdmi_gpll0[] = {
@@ -76,12 +78,12 @@ static const char *mmcc_xo_mmpll0_dsi_hdmi_gpll0[] = {
        "dsi1pll",
 };
 
-static const u8 mmcc_xo_mmpll0_1_2_gpll0_map[] = {
-       [P_XO]          = 0,
-       [P_MMPLL0]      = 1,
-       [P_MMPLL1]      = 2,
-       [P_GPLL0]       = 5,
-       [P_MMPLL2]      = 3,
+static const struct parent_map mmcc_xo_mmpll0_1_2_gpll0_map[] = {
+       { P_XO, 0 },
+       { P_MMPLL0, 1 },
+       { P_MMPLL1, 2 },
+       { P_GPLL0, 5 },
+       { P_MMPLL2, 3 }
 };
 
 static const char *mmcc_xo_mmpll0_1_2_gpll0[] = {
@@ -92,12 +94,12 @@ static const char *mmcc_xo_mmpll0_1_2_gpll0[] = {
        "mmpll2",
 };
 
-static const u8 mmcc_xo_mmpll0_1_3_gpll0_map[] = {
-       [P_XO]          = 0,
-       [P_MMPLL0]      = 1,
-       [P_MMPLL1]      = 2,
-       [P_GPLL0]       = 5,
-       [P_MMPLL3]      = 3,
+static const struct parent_map mmcc_xo_mmpll0_1_3_gpll0_map[] = {
+       { P_XO, 0 },
+       { P_MMPLL0, 1 },
+       { P_MMPLL1, 2 },
+       { P_GPLL0, 5 },
+       { P_MMPLL3, 3 }
 };
 
 static const char *mmcc_xo_mmpll0_1_3_gpll0[] = {
@@ -108,13 +110,13 @@ static const char *mmcc_xo_mmpll0_1_3_gpll0[] = {
        "mmpll3",
 };
 
-static const u8 mmcc_xo_dsi_hdmi_edp_map[] = {
-       [P_XO]          = 0,
-       [P_EDPLINK]     = 4,
-       [P_HDMIPLL]     = 3,
-       [P_EDPVCO]      = 5,
-       [P_DSI0PLL]     = 1,
-       [P_DSI1PLL]     = 2,
+static const struct parent_map mmcc_xo_dsi_hdmi_edp_map[] = {
+       { P_XO, 0 },
+       { P_EDPLINK, 4 },
+       { P_HDMIPLL, 3 },
+       { P_EDPVCO, 5 },
+       { P_DSI0PLL, 1 },
+       { P_DSI1PLL, 2 }
 };
 
 static const char *mmcc_xo_dsi_hdmi_edp[] = {
@@ -126,13 +128,13 @@ static const char *mmcc_xo_dsi_hdmi_edp[] = {
        "dsi1pll",
 };
 
-static const u8 mmcc_xo_dsi_hdmi_edp_gpll0_map[] = {
-       [P_XO]          = 0,
-       [P_EDPLINK]     = 4,
-       [P_HDMIPLL]     = 3,
-       [P_GPLL0]       = 5,
-       [P_DSI0PLL]     = 1,
-       [P_DSI1PLL]     = 2,
+static const struct parent_map mmcc_xo_dsi_hdmi_edp_gpll0_map[] = {
+       { P_XO, 0 },
+       { P_EDPLINK, 4 },
+       { P_HDMIPLL, 3 },
+       { P_GPLL0, 5 },
+       { P_DSI0PLL, 1 },
+       { P_DSI1PLL, 2 }
 };
 
 static const char *mmcc_xo_dsi_hdmi_edp_gpll0[] = {
@@ -144,13 +146,13 @@ static const char *mmcc_xo_dsi_hdmi_edp_gpll0[] = {
        "dsi1pll",
 };
 
-static const u8 mmcc_xo_dsibyte_hdmi_edp_gpll0_map[] = {
-       [P_XO]                  = 0,
-       [P_EDPLINK]             = 4,
-       [P_HDMIPLL]             = 3,
-       [P_GPLL0]               = 5,
-       [P_DSI0PLL_BYTE]        = 1,
-       [P_DSI1PLL_BYTE]        = 2,
+static const struct parent_map mmcc_xo_dsibyte_hdmi_edp_gpll0_map[] = {
+       { P_XO, 0 },
+       { P_EDPLINK, 4 },
+       { P_HDMIPLL, 3 },
+       { P_GPLL0, 5 },
+       { P_DSI0PLL_BYTE, 1 },
+       { P_DSI1PLL_BYTE, 2 }
 };
 
 static const char *mmcc_xo_dsibyte_hdmi_edp_gpll0[] = {
@@ -162,12 +164,12 @@ static const char *mmcc_xo_dsibyte_hdmi_edp_gpll0[] = {
        "dsi1pllbyte",
 };
 
-static const u8 mmcc_xo_mmpll0_1_4_gpll0_map[] = {
-       [P_XO]          = 0,
-       [P_MMPLL0]      = 1,
-       [P_MMPLL1]      = 2,
-       [P_GPLL0]       = 5,
-       [P_MMPLL4]      = 3,
+static const struct parent_map mmcc_xo_mmpll0_1_4_gpll0_map[] = {
+       { P_XO, 0 },
+       { P_MMPLL0, 1 },
+       { P_MMPLL1, 2 },
+       { P_GPLL0, 5 },
+       { P_MMPLL4, 3 }
 };
 
 static const char *mmcc_xo_mmpll0_1_4_gpll0[] = {
@@ -178,13 +180,13 @@ static const char *mmcc_xo_mmpll0_1_4_gpll0[] = {
        "gpll0",
 };
 
-static const u8 mmcc_xo_mmpll0_1_4_gpll1_0_map[] = {
-       [P_XO]          = 0,
-       [P_MMPLL0]      = 1,
-       [P_MMPLL1]      = 2,
-       [P_MMPLL4]      = 3,
-       [P_GPLL0]       = 5,
-       [P_GPLL1]       = 4,
+static const struct parent_map mmcc_xo_mmpll0_1_4_gpll1_0_map[] = {
+       { P_XO, 0 },
+       { P_MMPLL0, 1 },
+       { P_MMPLL1, 2 },
+       { P_MMPLL4, 3 },
+       { P_GPLL0, 5 },
+       { P_GPLL1, 4 }
 };
 
 static const char *mmcc_xo_mmpll0_1_4_gpll1_0[] = {
@@ -196,14 +198,14 @@ static const char *mmcc_xo_mmpll0_1_4_gpll1_0[] = {
        "gpll0",
 };
 
-static const u8 mmcc_xo_mmpll0_1_4_gpll1_0_sleep_map[] = {
-       [P_XO]          = 0,
-       [P_MMPLL0]      = 1,
-       [P_MMPLL1]      = 2,
-       [P_MMPLL4]      = 3,
-       [P_GPLL0]       = 5,
-       [P_GPLL1]       = 4,
-       [P_MMSLEEP]     = 6,
+static const struct parent_map mmcc_xo_mmpll0_1_4_gpll1_0_sleep_map[] = {
+       { P_XO, 0 },
+       { P_MMPLL0, 1 },
+       { P_MMPLL1, 2 },
+       { P_MMPLL4, 3 },
+       { P_GPLL0, 5 },
+       { P_GPLL1, 4 },
+       { P_MMSLEEP, 6 }
 };
 
 static const char *mmcc_xo_mmpll0_1_4_gpll1_0_sleep[] = {
index e8b33bbc362f9aa552959fbd56d231dba86ee1f0..9711bca9cc06aaf270ed2fb1c4195fa23eade8c2 100644 (file)
 #include "clk-branch.h"
 #include "reset.h"
 
-#define P_PXO  0
-#define P_PLL8 1
-#define P_PLL2 2
-#define P_PLL3 3
-#define P_PLL15        3
+enum {
+       P_PXO,
+       P_PLL8,
+       P_PLL2,
+       P_PLL3,
+       P_PLL15,
+       P_HDMI_PLL,
+};
 
 #define F_MN(f, s, _m, _n) { .freq = f, .src = s, .m = _m, .n = _n }
 
-static u8 mmcc_pxo_pll8_pll2_map[] = {
-       [P_PXO]         = 0,
-       [P_PLL8]        = 2,
-       [P_PLL2]        = 1,
+static const struct parent_map mmcc_pxo_pll8_pll2_map[] = {
+       { P_PXO, 0 },
+       { P_PLL8, 2 },
+       { P_PLL2, 1 }
 };
 
 static const char *mmcc_pxo_pll8_pll2[] = {
@@ -53,11 +56,11 @@ static const char *mmcc_pxo_pll8_pll2[] = {
        "pll2",
 };
 
-static u8 mmcc_pxo_pll8_pll2_pll3_map[] = {
-       [P_PXO]         = 0,
-       [P_PLL8]        = 2,
-       [P_PLL2]        = 1,
-       [P_PLL3]        = 3,
+static const struct parent_map mmcc_pxo_pll8_pll2_pll3_map[] = {
+       { P_PXO, 0 },
+       { P_PLL8, 2 },
+       { P_PLL2, 1 },
+       { P_PLL3, 3 }
 };
 
 static const char *mmcc_pxo_pll8_pll2_pll15[] = {
@@ -67,11 +70,11 @@ static const char *mmcc_pxo_pll8_pll2_pll15[] = {
        "pll15",
 };
 
-static u8 mmcc_pxo_pll8_pll2_pll15_map[] = {
-       [P_PXO]         = 0,
-       [P_PLL8]        = 2,
-       [P_PLL2]        = 1,
-       [P_PLL15]       = 3,
+static const struct parent_map mmcc_pxo_pll8_pll2_pll15_map[] = {
+       { P_PXO, 0 },
+       { P_PLL8, 2 },
+       { P_PLL2, 1 },
+       { P_PLL15, 3 }
 };
 
 static const char *mmcc_pxo_pll8_pll2_pll3[] = {
@@ -1377,11 +1380,9 @@ static struct clk_branch rot_clk = {
        },
 };
 
-#define P_HDMI_PLL 1
-
-static u8 mmcc_pxo_hdmi_map[] = {
-       [P_PXO]         = 0,
-       [P_HDMI_PLL]    = 3,
+static const struct parent_map mmcc_pxo_hdmi_map[] = {
+       { P_PXO, 0 },
+       { P_HDMI_PLL, 3 }
 };
 
 static const char *mmcc_pxo_hdmi[] = {
index be94c54a9a4f72db338c07f260a69da0b706b561..07f4cc159ad3103e79a955d26e085b596e34756c 100644 (file)
 #include "clk-branch.h"
 #include "reset.h"
 
-#define P_XO           0
-#define P_MMPLL0       1
-#define P_EDPLINK      1
-#define P_MMPLL1       2
-#define P_HDMIPLL      2
-#define P_GPLL0                3
-#define P_EDPVCO       3
-#define P_GPLL1                4
-#define P_DSI0PLL      4
-#define P_DSI0PLL_BYTE 4
-#define P_MMPLL2       4
-#define P_MMPLL3       4
-#define P_DSI1PLL      5
-#define P_DSI1PLL_BYTE 5
-
-static const u8 mmcc_xo_mmpll0_mmpll1_gpll0_map[] = {
-       [P_XO]          = 0,
-       [P_MMPLL0]      = 1,
-       [P_MMPLL1]      = 2,
-       [P_GPLL0]       = 5,
+enum {
+       P_XO,
+       P_MMPLL0,
+       P_EDPLINK,
+       P_MMPLL1,
+       P_HDMIPLL,
+       P_GPLL0,
+       P_EDPVCO,
+       P_GPLL1,
+       P_DSI0PLL,
+       P_DSI0PLL_BYTE,
+       P_MMPLL2,
+       P_MMPLL3,
+       P_DSI1PLL,
+       P_DSI1PLL_BYTE,
+};
+
+static const struct parent_map mmcc_xo_mmpll0_mmpll1_gpll0_map[] = {
+       { P_XO, 0 },
+       { P_MMPLL0, 1 },
+       { P_MMPLL1, 2 },
+       { P_GPLL0, 5 }
 };
 
 static const char *mmcc_xo_mmpll0_mmpll1_gpll0[] = {
@@ -61,13 +63,13 @@ static const char *mmcc_xo_mmpll0_mmpll1_gpll0[] = {
        "mmss_gpll0_vote",
 };
 
-static const u8 mmcc_xo_mmpll0_dsi_hdmi_gpll0_map[] = {
-       [P_XO]          = 0,
-       [P_MMPLL0]      = 1,
-       [P_HDMIPLL]     = 4,
-       [P_GPLL0]       = 5,
-       [P_DSI0PLL]     = 2,
-       [P_DSI1PLL]     = 3,
+static const struct parent_map mmcc_xo_mmpll0_dsi_hdmi_gpll0_map[] = {
+       { P_XO, 0 },
+       { P_MMPLL0, 1 },
+       { P_HDMIPLL, 4 },
+       { P_GPLL0, 5 },
+       { P_DSI0PLL, 2 },
+       { P_DSI1PLL, 3 }
 };
 
 static const char *mmcc_xo_mmpll0_dsi_hdmi_gpll0[] = {
@@ -79,12 +81,12 @@ static const char *mmcc_xo_mmpll0_dsi_hdmi_gpll0[] = {
        "dsi1pll",
 };
 
-static const u8 mmcc_xo_mmpll0_1_2_gpll0_map[] = {
-       [P_XO]          = 0,
-       [P_MMPLL0]      = 1,
-       [P_MMPLL1]      = 2,
-       [P_GPLL0]       = 5,
-       [P_MMPLL2]      = 3,
+static const struct parent_map mmcc_xo_mmpll0_1_2_gpll0_map[] = {
+       { P_XO, 0 },
+       { P_MMPLL0, 1 },
+       { P_MMPLL1, 2 },
+       { P_GPLL0, 5 },
+       { P_MMPLL2, 3 }
 };
 
 static const char *mmcc_xo_mmpll0_1_2_gpll0[] = {
@@ -95,12 +97,12 @@ static const char *mmcc_xo_mmpll0_1_2_gpll0[] = {
        "mmpll2",
 };
 
-static const u8 mmcc_xo_mmpll0_1_3_gpll0_map[] = {
-       [P_XO]          = 0,
-       [P_MMPLL0]      = 1,
-       [P_MMPLL1]      = 2,
-       [P_GPLL0]       = 5,
-       [P_MMPLL3]      = 3,
+static const struct parent_map mmcc_xo_mmpll0_1_3_gpll0_map[] = {
+       { P_XO, 0 },
+       { P_MMPLL0, 1 },
+       { P_MMPLL1, 2 },
+       { P_GPLL0, 5 },
+       { P_MMPLL3, 3 }
 };
 
 static const char *mmcc_xo_mmpll0_1_3_gpll0[] = {
@@ -111,12 +113,12 @@ static const char *mmcc_xo_mmpll0_1_3_gpll0[] = {
        "mmpll3",
 };
 
-static const u8 mmcc_xo_mmpll0_1_gpll1_0_map[] = {
-       [P_XO]          = 0,
-       [P_MMPLL0]      = 1,
-       [P_MMPLL1]      = 2,
-       [P_GPLL0]       = 5,
-       [P_GPLL1]       = 4,
+static const struct parent_map mmcc_xo_mmpll0_1_gpll1_0_map[] = {
+       { P_XO, 0 },
+       { P_MMPLL0, 1 },
+       { P_MMPLL1, 2 },
+       { P_GPLL0, 5 },
+       { P_GPLL1, 4 }
 };
 
 static const char *mmcc_xo_mmpll0_1_gpll1_0[] = {
@@ -127,13 +129,13 @@ static const char *mmcc_xo_mmpll0_1_gpll1_0[] = {
        "gpll1_vote",
 };
 
-static const u8 mmcc_xo_dsi_hdmi_edp_map[] = {
-       [P_XO]          = 0,
-       [P_EDPLINK]     = 4,
-       [P_HDMIPLL]     = 3,
-       [P_EDPVCO]      = 5,
-       [P_DSI0PLL]     = 1,
-       [P_DSI1PLL]     = 2,
+static const struct parent_map mmcc_xo_dsi_hdmi_edp_map[] = {
+       { P_XO, 0 },
+       { P_EDPLINK, 4 },
+       { P_HDMIPLL, 3 },
+       { P_EDPVCO, 5 },
+       { P_DSI0PLL, 1 },
+       { P_DSI1PLL, 2 }
 };
 
 static const char *mmcc_xo_dsi_hdmi_edp[] = {
@@ -145,13 +147,13 @@ static const char *mmcc_xo_dsi_hdmi_edp[] = {
        "dsi1pll",
 };
 
-static const u8 mmcc_xo_dsi_hdmi_edp_gpll0_map[] = {
-       [P_XO]          = 0,
-       [P_EDPLINK]     = 4,
-       [P_HDMIPLL]     = 3,
-       [P_GPLL0]       = 5,
-       [P_DSI0PLL]     = 1,
-       [P_DSI1PLL]     = 2,
+static const struct parent_map mmcc_xo_dsi_hdmi_edp_gpll0_map[] = {
+       { P_XO, 0 },
+       { P_EDPLINK, 4 },
+       { P_HDMIPLL, 3 },
+       { P_GPLL0, 5 },
+       { P_DSI0PLL, 1 },
+       { P_DSI1PLL, 2 }
 };
 
 static const char *mmcc_xo_dsi_hdmi_edp_gpll0[] = {
@@ -163,13 +165,13 @@ static const char *mmcc_xo_dsi_hdmi_edp_gpll0[] = {
        "dsi1pll",
 };
 
-static const u8 mmcc_xo_dsibyte_hdmi_edp_gpll0_map[] = {
-       [P_XO]                  = 0,
-       [P_EDPLINK]             = 4,
-       [P_HDMIPLL]             = 3,
-       [P_GPLL0]               = 5,
-       [P_DSI0PLL_BYTE]        = 1,
-       [P_DSI1PLL_BYTE]        = 2,
+static const struct parent_map mmcc_xo_dsibyte_hdmi_edp_gpll0_map[] = {
+       { P_XO, 0 },
+       { P_EDPLINK, 4 },
+       { P_HDMIPLL, 3 },
+       { P_GPLL0, 5 },
+       { P_DSI0PLL_BYTE, 1 },
+       { P_DSI1PLL_BYTE, 2 }
 };
 
 static const char *mmcc_xo_dsibyte_hdmi_edp_gpll0[] = {
index 7eb684c50d42ce9f0d06ffa4de1ecef4270808b7..556ce041d371478b43a9549a258f368b57f3468d 100644 (file)
@@ -704,7 +704,7 @@ static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = {
        GATE(ACLK_GPS, "aclk_gps", "aclk_peri", 0, RK2928_CLKGATE_CON(8), 13, GFLAGS),
 };
 
-static const char *rk3188_critical_clocks[] __initconst = {
+static const char *const rk3188_critical_clocks[] __initconst = {
        "aclk_cpu",
        "aclk_peri",
        "hclk_peri",
index 05d7a0bc059907872ff1719d0c401a0494082199..d17eb4528a283ee089603876ac8daa7da6b66054 100644 (file)
@@ -771,7 +771,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
        GATE(0, "pclk_isp_in", "ext_isp", 0, RK3288_CLKGATE_CON(16), 3, GFLAGS),
 };
 
-static const char *rk3288_critical_clocks[] __initconst = {
+static const char *const rk3288_critical_clocks[] __initconst = {
        "aclk_cpu",
        "aclk_peri",
        "hclk_peri",
index 20e05bbb3a6766bd8c630c9ce9cd16d16d81c6f8..edb5d489ae61859c5853d2ece634bd5d3e397f73 100644 (file)
@@ -317,7 +317,8 @@ void __init rockchip_clk_register_armclk(unsigned int lookup_id,
        rockchip_clk_add_lookup(clk, lookup_id);
 }
 
-void __init rockchip_clk_protect_critical(const char *clocks[], int nclocks)
+void __init rockchip_clk_protect_critical(const char *const clocks[],
+                                         int nclocks)
 {
        int i;
 
index 58d2e3bdf22fed499f8b4893eaf48690433d0298..e63cafe893e19f82f2d200a6c1a391aff6112a12 100644 (file)
@@ -182,7 +182,7 @@ struct clk *rockchip_clk_register_mmc(const char *name,
                                const char **parent_names, u8 num_parents,
                                void __iomem *reg, int shift);
 
-#define PNAME(x) static const char *x[] __initconst
+#define PNAME(x) static const char *x[] __initdata
 
 enum rockchip_clk_branch_type {
        branch_composite,
@@ -407,7 +407,7 @@ void rockchip_clk_register_armclk(unsigned int lookup_id, const char *name,
                        const struct rockchip_cpuclk_reg_data *reg_data,
                        const struct rockchip_cpuclk_rate_table *rates,
                        int nrates);
-void rockchip_clk_protect_critical(const char *clocks[], int nclocks);
+void rockchip_clk_protect_critical(const char *const clocks[], int nclocks);
 void rockchip_register_restart_notifier(unsigned int reg);
 
 #define ROCKCHIP_SOFTRST_HIWORD_MASK   BIT(0)
index 006c6f294310d51e804bfda91b76e3eeb211b7e7..17e9af7fe81fe0aad57ad6ec1c2a2ac05b2280dd 100644 (file)
@@ -10,6 +10,7 @@ obj-$(CONFIG_SOC_EXYNOS5250)  += clk-exynos5250.o
 obj-$(CONFIG_SOC_EXYNOS5260)   += clk-exynos5260.o
 obj-$(CONFIG_SOC_EXYNOS5410)   += clk-exynos5410.o
 obj-$(CONFIG_SOC_EXYNOS5420)   += clk-exynos5420.o
+obj-$(CONFIG_ARCH_EXYNOS5433)  += clk-exynos5433.o
 obj-$(CONFIG_SOC_EXYNOS5440)   += clk-exynos5440.o
 obj-$(CONFIG_ARCH_EXYNOS)      += clk-exynos-audss.o
 obj-$(CONFIG_ARCH_EXYNOS)      += clk-exynos-clkout.o
index 3a7cb2506731c0ab04e4f3901e789588be8211af..03a52228b6d1f1a4a280fcca7862b2aea2b79c0d 100644 (file)
@@ -142,6 +142,8 @@ CLK_OF_DECLARE(exynos4212_clkout, "samsung,exynos4212-pmu",
                exynos4_clkout_init);
 CLK_OF_DECLARE(exynos4412_clkout, "samsung,exynos4412-pmu",
                exynos4_clkout_init);
+CLK_OF_DECLARE(exynos3250_clkout, "samsung,exynos3250-pmu",
+               exynos4_clkout_init);
 
 static void __init exynos5_clkout_init(struct device_node *node)
 {
@@ -151,3 +153,5 @@ CLK_OF_DECLARE(exynos5250_clkout, "samsung,exynos5250-pmu",
                exynos5_clkout_init);
 CLK_OF_DECLARE(exynos5420_clkout, "samsung,exynos5420-pmu",
                exynos5_clkout_init);
+CLK_OF_DECLARE(exynos5433_clkout, "samsung,exynos5433-pmu",
+               exynos5_clkout_init);
index cc4c348d8a24038007375bcf53ba45a96bcd9ac9..538de66a759e12092e70b385e579bbc112133ca3 100644 (file)
@@ -894,3 +894,166 @@ static void __init exynos3250_cmu_dmc_init(struct device_node *np)
 }
 CLK_OF_DECLARE(exynos3250_cmu_dmc, "samsung,exynos3250-cmu-dmc",
                exynos3250_cmu_dmc_init);
+
+
+/*
+ * CMU ISP
+ */
+
+#define DIV_ISP0               0x300
+#define DIV_ISP1               0x304
+#define GATE_IP_ISP0           0x800
+#define GATE_IP_ISP1           0x804
+#define GATE_SCLK_ISP          0x900
+
+static struct samsung_div_clock isp_div_clks[] __initdata = {
+       /*
+        * NOTE: Following table is sorted by register address in ascending
+        * order and then bitfield shift in descending order, as it is done
+        * in the User's Manual. When adding new entries, please make sure
+        * that the order is preserved, to avoid merge conflicts and make
+        * further work with defined data easier.
+        */
+       /* DIV_ISP0 */
+       DIV(CLK_DIV_ISP1, "div_isp1", "mout_aclk_266_sub", DIV_ISP0, 4, 3),
+       DIV(CLK_DIV_ISP0, "div_isp0", "mout_aclk_266_sub", DIV_ISP0, 0, 3),
+
+       /* DIV_ISP1 */
+       DIV(CLK_DIV_MCUISP1, "div_mcuisp1", "mout_aclk_400_mcuisp_sub",
+               DIV_ISP1, 8, 3),
+       DIV(CLK_DIV_MCUISP0, "div_mcuisp0", "mout_aclk_400_mcuisp_sub",
+               DIV_ISP1, 4, 3),
+       DIV(CLK_DIV_MPWM, "div_mpwm", "div_isp1", DIV_ISP1, 0, 3),
+};
+
+static struct samsung_gate_clock isp_gate_clks[] __initdata = {
+       /*
+        * NOTE: Following table is sorted by register address in ascending
+        * order and then bitfield shift in descending order, as it is done
+        * in the User's Manual. When adding new entries, please make sure
+        * that the order is preserved, to avoid merge conflicts and make
+        * further work with defined data easier.
+        */
+
+       /* GATE_IP_ISP0 */
+       GATE(CLK_UART_ISP, "uart_isp", "uart_isp_top",
+               GATE_IP_ISP0, 31, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_WDT_ISP, "wdt_isp", "mout_aclk_266_sub",
+               GATE_IP_ISP0, 30, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PWM_ISP, "pwm_isp", "mout_aclk_266_sub",
+               GATE_IP_ISP0, 28, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_I2C1_ISP, "i2c1_isp", "mout_aclk_266_sub",
+               GATE_IP_ISP0, 26, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_I2C0_ISP, "i2c0_isp", "mout_aclk_266_sub",
+               GATE_IP_ISP0, 25, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_MPWM_ISP, "mpwm_isp", "mout_aclk_266_sub",
+               GATE_IP_ISP0, 24, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_MCUCTL_ISP, "mcuctl_isp", "mout_aclk_266_sub",
+               GATE_IP_ISP0, 23, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PPMUISPX, "ppmuispx", "mout_aclk_266_sub",
+               GATE_IP_ISP0, 21, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PPMUISPMX, "ppmuispmx", "mout_aclk_266_sub",
+               GATE_IP_ISP0, 20, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_QE_LITE1, "qe_lite1", "mout_aclk_266_sub",
+               GATE_IP_ISP0, 18, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_QE_LITE0, "qe_lite0", "mout_aclk_266_sub",
+               GATE_IP_ISP0, 17, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_QE_FD, "qe_fd", "mout_aclk_266_sub",
+               GATE_IP_ISP0, 16, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_QE_DRC, "qe_drc", "mout_aclk_266_sub",
+               GATE_IP_ISP0, 15, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_QE_ISP, "qe_isp", "mout_aclk_266_sub",
+               GATE_IP_ISP0, 14, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_CSIS1, "csis1", "mout_aclk_266_sub",
+               GATE_IP_ISP0, 13, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SMMU_LITE1, "smmu_lite1", "mout_aclk_266_sub",
+               GATE_IP_ISP0, 12, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SMMU_LITE0, "smmu_lite0", "mout_aclk_266_sub",
+               GATE_IP_ISP0, 11, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SMMU_FD, "smmu_fd", "mout_aclk_266_sub",
+               GATE_IP_ISP0, 10, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SMMU_DRC, "smmu_drc", "mout_aclk_266_sub",
+               GATE_IP_ISP0, 9, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SMMU_ISP, "smmu_isp", "mout_aclk_266_sub",
+               GATE_IP_ISP0, 8, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_GICISP, "gicisp", "mout_aclk_266_sub",
+               GATE_IP_ISP0, 7, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_CSIS0, "csis0", "mout_aclk_266_sub",
+               GATE_IP_ISP0, 6, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_MCUISP, "mcuisp", "mout_aclk_266_sub",
+               GATE_IP_ISP0, 5, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_LITE1, "lite1", "mout_aclk_266_sub",
+               GATE_IP_ISP0, 4, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_LITE0, "lite0", "mout_aclk_266_sub",
+               GATE_IP_ISP0, 3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_FD, "fd", "mout_aclk_266_sub",
+               GATE_IP_ISP0, 2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_DRC, "drc", "mout_aclk_266_sub",
+               GATE_IP_ISP0, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ISP, "isp", "mout_aclk_266_sub",
+               GATE_IP_ISP0, 0, CLK_IGNORE_UNUSED, 0),
+
+       /* GATE_IP_ISP1 */
+       GATE(CLK_QE_ISPCX, "qe_ispcx", "uart_isp_top",
+               GATE_IP_ISP0, 21, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_QE_SCALERP, "qe_scalerp", "uart_isp_top",
+               GATE_IP_ISP0, 20, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_QE_SCALERC, "qe_scalerc", "uart_isp_top",
+               GATE_IP_ISP0, 19, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SMMU_SCALERP, "smmu_scalerp", "uart_isp_top",
+               GATE_IP_ISP0, 18, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SMMU_SCALERC, "smmu_scalerc", "uart_isp_top",
+               GATE_IP_ISP0, 17, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SCALERP, "scalerp", "uart_isp_top",
+               GATE_IP_ISP0, 16, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SCALERC, "scalerc", "uart_isp_top",
+               GATE_IP_ISP0, 15, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SPI1_ISP, "spi1_isp", "uart_isp_top",
+               GATE_IP_ISP0, 13, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SPI0_ISP, "spi0_isp", "uart_isp_top",
+               GATE_IP_ISP0, 12, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SMMU_ISPCX, "smmu_ispcx", "uart_isp_top",
+               GATE_IP_ISP0, 4, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ASYNCAXIM, "asyncaxim", "uart_isp_top",
+               GATE_IP_ISP0, 0, CLK_IGNORE_UNUSED, 0),
+
+       /* GATE_SCLK_ISP */
+       GATE(CLK_SCLK_MPWM_ISP, "sclk_mpwm_isp", "div_mpwm",
+               GATE_SCLK_ISP, 0, CLK_IGNORE_UNUSED, 0),
+};
+
+static struct samsung_cmu_info isp_cmu_info __initdata = {
+       .div_clks       = isp_div_clks,
+       .nr_div_clks    = ARRAY_SIZE(isp_div_clks),
+       .gate_clks      = isp_gate_clks,
+       .nr_gate_clks   = ARRAY_SIZE(isp_gate_clks),
+       .nr_clk_ids     = NR_CLKS_ISP,
+};
+
+static int __init exynos3250_cmu_isp_probe(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+
+       samsung_cmu_register_one(np, &isp_cmu_info);
+       return 0;
+}
+
+static const struct of_device_id exynos3250_cmu_isp_of_match[] = {
+       { .compatible = "samsung,exynos3250-cmu-isp", },
+       { /* sentinel */ }
+};
+
+static struct platform_driver exynos3250_cmu_isp_driver = {
+       .driver = {
+               .name = "exynos3250-cmu-isp",
+               .of_match_table = exynos3250_cmu_isp_of_match,
+       },
+};
+
+static int __init exynos3250_cmu_platform_init(void)
+{
+       return platform_driver_probe(&exynos3250_cmu_isp_driver,
+                                       exynos3250_cmu_isp_probe);
+}
+subsys_initcall(exynos3250_cmu_platform_init);
+
index 51462e85675f7f6ed04dc6d3f38891c400aea7e4..714d6ba782c81b2420c7770db183a3b6b1ffd785 100644 (file)
@@ -1354,7 +1354,7 @@ static struct samsung_pll_clock exynos4x12_plls[nr_plls] __initdata = {
                        VPLL_LOCK, VPLL_CON0, NULL),
 };
 
-static void __init exynos4_core_down_clock(enum exynos4_soc soc)
+static void __init exynos4x12_core_down_clock(void)
 {
        unsigned int tmp;
 
@@ -1373,11 +1373,9 @@ static void __init exynos4_core_down_clock(enum exynos4_soc soc)
        __raw_writel(tmp, reg_base + PWR_CTRL1);
 
        /*
-        * Disable the clock up feature on Exynos4x12, in case it was
-        * enabled by bootloader.
+        * Disable the clock up feature in case it was enabled by bootloader.
         */
-       if (exynos4_soc == EXYNOS4X12)
-               __raw_writel(0x0, reg_base + E4X12_PWR_CTRL2);
+       __raw_writel(0x0, reg_base + E4X12_PWR_CTRL2);
 }
 
 /* register exynos4 clocks */
@@ -1474,7 +1472,8 @@ static void __init exynos4_clk_init(struct device_node *np,
        samsung_clk_register_alias(ctx, exynos4_aliases,
                        ARRAY_SIZE(exynos4_aliases));
 
-       exynos4_core_down_clock(soc);
+       if (soc == EXYNOS4X12)
+               exynos4x12_core_down_clock();
        exynos4_clk_sleep_init();
 
        samsung_clk_of_add_provider(np, ctx);
diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c
new file mode 100644 (file)
index 0000000..387e3e3
--- /dev/null
@@ -0,0 +1,5423 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Author: Chanwoo Choi <cw00.choi@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 Exynos5443 SoC.
+ */
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+
+#include <dt-bindings/clock/exynos5433.h>
+
+#include "clk.h"
+#include "clk-pll.h"
+
+/*
+ * Register offset definitions for CMU_TOP
+ */
+#define ISP_PLL_LOCK                   0x0000
+#define AUD_PLL_LOCK                   0x0004
+#define ISP_PLL_CON0                   0x0100
+#define ISP_PLL_CON1                   0x0104
+#define ISP_PLL_FREQ_DET               0x0108
+#define AUD_PLL_CON0                   0x0110
+#define AUD_PLL_CON1                   0x0114
+#define AUD_PLL_CON2                   0x0118
+#define AUD_PLL_FREQ_DET               0x011c
+#define MUX_SEL_TOP0                   0x0200
+#define MUX_SEL_TOP1                   0x0204
+#define MUX_SEL_TOP2                   0x0208
+#define MUX_SEL_TOP3                   0x020c
+#define MUX_SEL_TOP4                   0x0210
+#define MUX_SEL_TOP_MSCL               0x0220
+#define MUX_SEL_TOP_CAM1               0x0224
+#define MUX_SEL_TOP_DISP               0x0228
+#define MUX_SEL_TOP_FSYS0              0x0230
+#define MUX_SEL_TOP_FSYS1              0x0234
+#define MUX_SEL_TOP_PERIC0             0x0238
+#define MUX_SEL_TOP_PERIC1             0x023c
+#define MUX_ENABLE_TOP0                        0x0300
+#define MUX_ENABLE_TOP1                        0x0304
+#define MUX_ENABLE_TOP2                        0x0308
+#define MUX_ENABLE_TOP3                        0x030c
+#define MUX_ENABLE_TOP4                        0x0310
+#define MUX_ENABLE_TOP_MSCL            0x0320
+#define MUX_ENABLE_TOP_CAM1            0x0324
+#define MUX_ENABLE_TOP_DISP            0x0328
+#define MUX_ENABLE_TOP_FSYS0           0x0330
+#define MUX_ENABLE_TOP_FSYS1           0x0334
+#define MUX_ENABLE_TOP_PERIC0          0x0338
+#define MUX_ENABLE_TOP_PERIC1          0x033c
+#define MUX_STAT_TOP0                  0x0400
+#define MUX_STAT_TOP1                  0x0404
+#define MUX_STAT_TOP2                  0x0408
+#define MUX_STAT_TOP3                  0x040c
+#define MUX_STAT_TOP4                  0x0410
+#define MUX_STAT_TOP_MSCL              0x0420
+#define MUX_STAT_TOP_CAM1              0x0424
+#define MUX_STAT_TOP_FSYS0             0x0430
+#define MUX_STAT_TOP_FSYS1             0x0434
+#define MUX_STAT_TOP_PERIC0            0x0438
+#define MUX_STAT_TOP_PERIC1            0x043c
+#define DIV_TOP0                       0x0600
+#define DIV_TOP1                       0x0604
+#define DIV_TOP2                       0x0608
+#define DIV_TOP3                       0x060c
+#define DIV_TOP4                       0x0610
+#define DIV_TOP_MSCL                   0x0618
+#define DIV_TOP_CAM10                  0x061c
+#define DIV_TOP_CAM11                  0x0620
+#define DIV_TOP_FSYS0                  0x062c
+#define DIV_TOP_FSYS1                  0x0630
+#define DIV_TOP_FSYS2                  0x0634
+#define DIV_TOP_PERIC0                 0x0638
+#define DIV_TOP_PERIC1                 0x063c
+#define DIV_TOP_PERIC2                 0x0640
+#define DIV_TOP_PERIC3                 0x0644
+#define DIV_TOP_PERIC4                 0x0648
+#define DIV_TOP_PLL_FREQ_DET           0x064c
+#define DIV_STAT_TOP0                  0x0700
+#define DIV_STAT_TOP1                  0x0704
+#define DIV_STAT_TOP2                  0x0708
+#define DIV_STAT_TOP3                  0x070c
+#define DIV_STAT_TOP4                  0x0710
+#define DIV_STAT_TOP_MSCL              0x0718
+#define DIV_STAT_TOP_CAM10             0x071c
+#define DIV_STAT_TOP_CAM11             0x0720
+#define DIV_STAT_TOP_FSYS0             0x072c
+#define DIV_STAT_TOP_FSYS1             0x0730
+#define DIV_STAT_TOP_FSYS2             0x0734
+#define DIV_STAT_TOP_PERIC0            0x0738
+#define DIV_STAT_TOP_PERIC1            0x073c
+#define DIV_STAT_TOP_PERIC2            0x0740
+#define DIV_STAT_TOP_PERIC3            0x0744
+#define DIV_STAT_TOP_PLL_FREQ_DET      0x074c
+#define ENABLE_ACLK_TOP                        0x0800
+#define ENABLE_SCLK_TOP                        0x0a00
+#define ENABLE_SCLK_TOP_MSCL           0x0a04
+#define ENABLE_SCLK_TOP_CAM1           0x0a08
+#define ENABLE_SCLK_TOP_DISP           0x0a0c
+#define ENABLE_SCLK_TOP_FSYS           0x0a10
+#define ENABLE_SCLK_TOP_PERIC          0x0a14
+#define ENABLE_IP_TOP                  0x0b00
+#define ENABLE_CMU_TOP                 0x0c00
+#define ENABLE_CMU_TOP_DIV_STAT                0x0c04
+
+static unsigned long top_clk_regs[] __initdata = {
+       ISP_PLL_LOCK,
+       AUD_PLL_LOCK,
+       ISP_PLL_CON0,
+       ISP_PLL_CON1,
+       ISP_PLL_FREQ_DET,
+       AUD_PLL_CON0,
+       AUD_PLL_CON1,
+       AUD_PLL_CON2,
+       AUD_PLL_FREQ_DET,
+       MUX_SEL_TOP0,
+       MUX_SEL_TOP1,
+       MUX_SEL_TOP2,
+       MUX_SEL_TOP3,
+       MUX_SEL_TOP4,
+       MUX_SEL_TOP_MSCL,
+       MUX_SEL_TOP_CAM1,
+       MUX_SEL_TOP_DISP,
+       MUX_SEL_TOP_FSYS0,
+       MUX_SEL_TOP_FSYS1,
+       MUX_SEL_TOP_PERIC0,
+       MUX_SEL_TOP_PERIC1,
+       MUX_ENABLE_TOP0,
+       MUX_ENABLE_TOP1,
+       MUX_ENABLE_TOP2,
+       MUX_ENABLE_TOP3,
+       MUX_ENABLE_TOP4,
+       MUX_ENABLE_TOP_MSCL,
+       MUX_ENABLE_TOP_CAM1,
+       MUX_ENABLE_TOP_DISP,
+       MUX_ENABLE_TOP_FSYS0,
+       MUX_ENABLE_TOP_FSYS1,
+       MUX_ENABLE_TOP_PERIC0,
+       MUX_ENABLE_TOP_PERIC1,
+       MUX_STAT_TOP0,
+       MUX_STAT_TOP1,
+       MUX_STAT_TOP2,
+       MUX_STAT_TOP3,
+       MUX_STAT_TOP4,
+       MUX_STAT_TOP_MSCL,
+       MUX_STAT_TOP_CAM1,
+       MUX_STAT_TOP_FSYS0,
+       MUX_STAT_TOP_FSYS1,
+       MUX_STAT_TOP_PERIC0,
+       MUX_STAT_TOP_PERIC1,
+       DIV_TOP0,
+       DIV_TOP1,
+       DIV_TOP2,
+       DIV_TOP3,
+       DIV_TOP4,
+       DIV_TOP_MSCL,
+       DIV_TOP_CAM10,
+       DIV_TOP_CAM11,
+       DIV_TOP_FSYS0,
+       DIV_TOP_FSYS1,
+       DIV_TOP_FSYS2,
+       DIV_TOP_PERIC0,
+       DIV_TOP_PERIC1,
+       DIV_TOP_PERIC2,
+       DIV_TOP_PERIC3,
+       DIV_TOP_PERIC4,
+       DIV_TOP_PLL_FREQ_DET,
+       DIV_STAT_TOP0,
+       DIV_STAT_TOP1,
+       DIV_STAT_TOP2,
+       DIV_STAT_TOP3,
+       DIV_STAT_TOP4,
+       DIV_STAT_TOP_MSCL,
+       DIV_STAT_TOP_CAM10,
+       DIV_STAT_TOP_CAM11,
+       DIV_STAT_TOP_FSYS0,
+       DIV_STAT_TOP_FSYS1,
+       DIV_STAT_TOP_FSYS2,
+       DIV_STAT_TOP_PERIC0,
+       DIV_STAT_TOP_PERIC1,
+       DIV_STAT_TOP_PERIC2,
+       DIV_STAT_TOP_PERIC3,
+       DIV_STAT_TOP_PLL_FREQ_DET,
+       ENABLE_ACLK_TOP,
+       ENABLE_SCLK_TOP,
+       ENABLE_SCLK_TOP_MSCL,
+       ENABLE_SCLK_TOP_CAM1,
+       ENABLE_SCLK_TOP_DISP,
+       ENABLE_SCLK_TOP_FSYS,
+       ENABLE_SCLK_TOP_PERIC,
+       ENABLE_IP_TOP,
+       ENABLE_CMU_TOP,
+       ENABLE_CMU_TOP_DIV_STAT,
+};
+
+/* list of all parent clock list */
+PNAME(mout_aud_pll_p)          = { "oscclk", "fout_aud_pll", };
+PNAME(mout_isp_pll_p)          = { "oscclk", "fout_isp_pll", };
+PNAME(mout_aud_pll_user_p)     = { "oscclk", "mout_aud_pll", };
+PNAME(mout_mphy_pll_user_p)    = { "oscclk", "sclk_mphy_pll", };
+PNAME(mout_mfc_pll_user_p)     = { "oscclk", "sclk_mfc_pll", };
+PNAME(mout_bus_pll_user_p)     = { "oscclk", "sclk_bus_pll", };
+PNAME(mout_bus_pll_user_t_p)   = { "oscclk", "mout_bus_pll_user", };
+PNAME(mout_mphy_pll_user_t_p)  = { "oscclk", "mout_mphy_pll_user", };
+
+PNAME(mout_bus_mfc_pll_user_p) = { "mout_bus_pll_user", "mout_mfc_pll_user",};
+PNAME(mout_mfc_bus_pll_user_p) = { "mout_mfc_pll_user", "mout_bus_pll_user",};
+PNAME(mout_aclk_cam1_552_b_p)  = { "mout_aclk_cam1_552_a",
+                                   "mout_mfc_pll_user", };
+PNAME(mout_aclk_cam1_552_a_p)  = { "mout_isp_pll", "mout_bus_pll_user", };
+
+PNAME(mout_aclk_mfc_400_c_p)   = { "mout_aclk_mfc_400_b",
+                                   "mout_mphy_pll_user", };
+PNAME(mout_aclk_mfc_400_b_p)   = { "mout_aclk_mfc_400_a",
+                                   "mout_bus_pll_user", };
+PNAME(mout_aclk_mfc_400_a_p)   = { "mout_mfc_pll_user", "mout_isp_pll", };
+
+PNAME(mout_bus_mphy_pll_user_p)        = { "mout_bus_pll_user",
+                                   "mout_mphy_pll_user", };
+PNAME(mout_aclk_mscl_b_p)      = { "mout_aclk_mscl_400_a",
+                                   "mout_mphy_pll_user", };
+PNAME(mout_aclk_g2d_400_b_p)   = { "mout_aclk_g2d_400_a",
+                                   "mout_mphy_pll_user", };
+
+PNAME(mout_sclk_jpeg_c_p)      = { "mout_sclk_jpeg_b", "mout_mphy_pll_user",};
+PNAME(mout_sclk_jpeg_b_p)      = { "mout_sclk_jpeg_a", "mout_mfc_pll_user", };
+
+PNAME(mout_sclk_mmc2_b_p)      = { "mout_sclk_mmc2_a", "mout_mfc_pll_user",};
+PNAME(mout_sclk_mmc1_b_p)      = { "mout_sclk_mmc1_a", "mout_mfc_pll_user",};
+PNAME(mout_sclk_mmc0_d_p)      = { "mout_sclk_mmc0_c", "mout_isp_pll", };
+PNAME(mout_sclk_mmc0_c_p)      = { "mout_sclk_mmc0_b", "mout_mphy_pll_user",};
+PNAME(mout_sclk_mmc0_b_p)      = { "mout_sclk_mmc0_a", "mout_mfc_pll_user", };
+
+PNAME(mout_sclk_spdif_p)       = { "sclk_audio0", "sclk_audio1",
+                                   "oscclk", "ioclk_spdif_extclk", };
+PNAME(mout_sclk_audio1_p)      = { "ioclk_audiocdclk1", "oscclk",
+                                   "mout_aud_pll_user_t",};
+PNAME(mout_sclk_audio0_p)      = { "ioclk_audiocdclk0", "oscclk",
+                                   "mout_aud_pll_user_t",};
+
+PNAME(mout_sclk_hdmi_spdif_p)  = { "sclk_audio1", "ioclk_spdif_extclk", };
+
+static struct samsung_fixed_factor_clock top_fixed_factor_clks[] __initdata = {
+       FFACTOR(0, "oscclk_efuse_common", "oscclk", 1, 1, 0),
+};
+
+static struct samsung_fixed_rate_clock top_fixed_clks[] __initdata = {
+       /* Xi2s{0|1}CDCLK input clock for I2S/PCM */
+       FRATE(0, "ioclk_audiocdclk1", NULL, CLK_IS_ROOT, 100000000),
+       FRATE(0, "ioclk_audiocdclk0", NULL, CLK_IS_ROOT, 100000000),
+       /* Xi2s1SDI input clock for SPDIF */
+       FRATE(0, "ioclk_spdif_extclk", NULL, CLK_IS_ROOT, 100000000),
+       /* XspiCLK[4:0] input clock for SPI */
+       FRATE(0, "ioclk_spi4_clk_in", NULL, CLK_IS_ROOT, 50000000),
+       FRATE(0, "ioclk_spi3_clk_in", NULL, CLK_IS_ROOT, 50000000),
+       FRATE(0, "ioclk_spi2_clk_in", NULL, CLK_IS_ROOT, 50000000),
+       FRATE(0, "ioclk_spi1_clk_in", NULL, CLK_IS_ROOT, 50000000),
+       FRATE(0, "ioclk_spi0_clk_in", NULL, CLK_IS_ROOT, 50000000),
+       /* Xi2s1SCLK input clock for I2S1_BCLK */
+       FRATE(0, "ioclk_i2s1_bclk_in", NULL, CLK_IS_ROOT, 12288000),
+};
+
+static struct samsung_mux_clock top_mux_clks[] __initdata = {
+       /* MUX_SEL_TOP0 */
+       MUX(CLK_MOUT_AUD_PLL, "mout_aud_pll", mout_aud_pll_p, MUX_SEL_TOP0,
+                       4, 1),
+       MUX(CLK_MOUT_ISP_PLL, "mout_isp_pll", mout_isp_pll_p, MUX_SEL_TOP0,
+                       0, 1),
+
+       /* MUX_SEL_TOP1 */
+       MUX(CLK_MOUT_AUD_PLL_USER_T, "mout_aud_pll_user_t",
+                       mout_aud_pll_user_p, MUX_SEL_TOP1, 12, 1),
+       MUX(CLK_MOUT_MPHY_PLL_USER, "mout_mphy_pll_user", mout_mphy_pll_user_p,
+                       MUX_SEL_TOP1, 8, 1),
+       MUX(CLK_MOUT_MFC_PLL_USER, "mout_mfc_pll_user", mout_mfc_pll_user_p,
+                       MUX_SEL_TOP1, 4, 1),
+       MUX(CLK_MOUT_BUS_PLL_USER, "mout_bus_pll_user", mout_bus_pll_user_p,
+                       MUX_SEL_TOP1, 0, 1),
+
+       /* MUX_SEL_TOP2 */
+       MUX(CLK_MOUT_ACLK_HEVC_400, "mout_aclk_hevc_400",
+                       mout_bus_mfc_pll_user_p, MUX_SEL_TOP2, 28, 1),
+       MUX(CLK_MOUT_ACLK_CAM1_333, "mout_aclk_cam1_333",
+                       mout_mfc_bus_pll_user_p, MUX_SEL_TOP2, 16, 1),
+       MUX(CLK_MOUT_ACLK_CAM1_552_B, "mout_aclk_cam1_552_b",
+                       mout_aclk_cam1_552_b_p, MUX_SEL_TOP2, 12, 1),
+       MUX(CLK_MOUT_ACLK_CAM1_552_A, "mout_aclk_cam1_552_a",
+                       mout_aclk_cam1_552_a_p, MUX_SEL_TOP2, 8, 1),
+       MUX(CLK_MOUT_ACLK_ISP_DIS_400, "mout_aclk_isp_dis_400",
+                       mout_bus_mfc_pll_user_p, MUX_SEL_TOP2, 4, 1),
+       MUX(CLK_MOUT_ACLK_ISP_400, "mout_aclk_isp_400",
+                       mout_bus_mfc_pll_user_p, MUX_SEL_TOP2, 0, 1),
+
+       /* MUX_SEL_TOP3 */
+       MUX(CLK_MOUT_ACLK_BUS0_400, "mout_aclk_bus0_400",
+                       mout_bus_mphy_pll_user_p, MUX_SEL_TOP3, 20, 1),
+       MUX(CLK_MOUT_ACLK_MSCL_400_B, "mout_aclk_mscl_400_b",
+                       mout_aclk_mscl_b_p, MUX_SEL_TOP3, 16, 1),
+       MUX(CLK_MOUT_ACLK_MSCL_400_A, "mout_aclk_mscl_400_a",
+                       mout_bus_mfc_pll_user_p, MUX_SEL_TOP3, 12, 1),
+       MUX(CLK_MOUT_ACLK_GSCL_333, "mout_aclk_gscl_333",
+                       mout_mfc_bus_pll_user_p, MUX_SEL_TOP3, 8, 1),
+       MUX(CLK_MOUT_ACLK_G2D_400_B, "mout_aclk_g2d_400_b",
+                       mout_aclk_g2d_400_b_p, MUX_SEL_TOP3, 4, 1),
+       MUX(CLK_MOUT_ACLK_G2D_400_A, "mout_aclk_g2d_400_a",
+                       mout_bus_mfc_pll_user_p, MUX_SEL_TOP3, 0, 1),
+
+       /* MUX_SEL_TOP4 */
+       MUX(CLK_MOUT_ACLK_MFC_400_C, "mout_aclk_mfc_400_c",
+                       mout_aclk_mfc_400_c_p, MUX_SEL_TOP4, 8, 1),
+       MUX(CLK_MOUT_ACLK_MFC_400_B, "mout_aclk_mfc_400_b",
+                       mout_aclk_mfc_400_b_p, MUX_SEL_TOP4, 4, 1),
+       MUX(CLK_MOUT_ACLK_MFC_400_A, "mout_aclk_mfc_400_a",
+                       mout_aclk_mfc_400_a_p, MUX_SEL_TOP4, 0, 1),
+
+       /* MUX_SEL_TOP_MSCL */
+       MUX(CLK_MOUT_SCLK_JPEG_C, "mout_sclk_jpeg_c", mout_sclk_jpeg_c_p,
+                       MUX_SEL_TOP_MSCL, 8, 1),
+       MUX(CLK_MOUT_SCLK_JPEG_B, "mout_sclk_jpeg_b", mout_sclk_jpeg_b_p,
+                       MUX_SEL_TOP_MSCL, 4, 1),
+       MUX(CLK_MOUT_SCLK_JPEG_A, "mout_sclk_jpeg_a", mout_bus_pll_user_t_p,
+                       MUX_SEL_TOP_MSCL, 0, 1),
+
+       /* MUX_SEL_TOP_CAM1 */
+       MUX(CLK_MOUT_SCLK_ISP_SENSOR2, "mout_sclk_isp_sensor2",
+                       mout_bus_pll_user_t_p, MUX_SEL_TOP_CAM1, 24, 1),
+       MUX(CLK_MOUT_SCLK_ISP_SENSOR1, "mout_sclk_isp_sensor1",
+                       mout_bus_pll_user_t_p, MUX_SEL_TOP_CAM1, 20, 1),
+       MUX(CLK_MOUT_SCLK_ISP_SENSOR0, "mout_sclk_isp_sensor0",
+                       mout_bus_pll_user_t_p, MUX_SEL_TOP_CAM1, 16, 1),
+       MUX(CLK_MOUT_SCLK_ISP_UART, "mout_sclk_isp_uart",
+                       mout_bus_pll_user_t_p, MUX_SEL_TOP_CAM1, 8, 1),
+       MUX(CLK_MOUT_SCLK_ISP_SPI1, "mout_sclk_isp_spi1",
+                       mout_bus_pll_user_t_p, MUX_SEL_TOP_CAM1, 4, 1),
+       MUX(CLK_MOUT_SCLK_ISP_SPI0, "mout_sclk_isp_spi0",
+                       mout_bus_pll_user_t_p, MUX_SEL_TOP_CAM1, 0, 1),
+
+       /* MUX_SEL_TOP_FSYS0 */
+       MUX(CLK_MOUT_SCLK_MMC2_B, "mout_sclk_mmc2_b", mout_sclk_mmc2_b_p,
+                       MUX_SEL_TOP_FSYS0, 28, 1),
+       MUX(CLK_MOUT_SCLK_MMC2_A, "mout_sclk_mmc2_a", mout_bus_pll_user_t_p,
+                       MUX_SEL_TOP_FSYS0, 24, 1),
+       MUX(CLK_MOUT_SCLK_MMC1_B, "mout_sclk_mmc1_b", mout_sclk_mmc1_b_p,
+                       MUX_SEL_TOP_FSYS0, 20, 1),
+       MUX(CLK_MOUT_SCLK_MMC1_A, "mout_sclk_mmc1_a", mout_bus_pll_user_t_p,
+                       MUX_SEL_TOP_FSYS0, 16, 1),
+       MUX(CLK_MOUT_SCLK_MMC0_D, "mout_sclk_mmc0_d", mout_sclk_mmc0_d_p,
+                       MUX_SEL_TOP_FSYS0, 12, 1),
+       MUX(CLK_MOUT_SCLK_MMC0_C, "mout_sclk_mmc0_c", mout_sclk_mmc0_c_p,
+                       MUX_SEL_TOP_FSYS0, 8, 1),
+       MUX(CLK_MOUT_SCLK_MMC0_B, "mout_sclk_mmc0_b", mout_sclk_mmc0_b_p,
+                       MUX_SEL_TOP_FSYS0, 4, 1),
+       MUX(CLK_MOUT_SCLK_MMC0_A, "mout_sclk_mmc0_a", mout_bus_pll_user_t_p,
+                       MUX_SEL_TOP_FSYS0, 0, 1),
+
+       /* MUX_SEL_TOP_FSYS1 */
+       MUX(CLK_MOUT_SCLK_PCIE_100, "mout_sclk_pcie_100", mout_bus_pll_user_t_p,
+                       MUX_SEL_TOP_FSYS1, 12, 1),
+       MUX(CLK_MOUT_SCLK_UFSUNIPRO, "mout_sclk_ufsunipro",
+                       mout_mphy_pll_user_t_p, MUX_SEL_TOP_FSYS1, 8, 1),
+       MUX(CLK_MOUT_SCLK_USBHOST30, "mout_sclk_usbhost30",
+                       mout_bus_pll_user_t_p, MUX_SEL_TOP_FSYS1, 4, 1),
+       MUX(CLK_MOUT_SCLK_USBDRD30, "mout_sclk_usbdrd30",
+                       mout_bus_pll_user_t_p, MUX_SEL_TOP_FSYS1, 0, 1),
+
+       /* MUX_SEL_TOP_PERIC0 */
+       MUX(CLK_MOUT_SCLK_SPI4, "mout_sclk_spi4", mout_bus_pll_user_t_p,
+                       MUX_SEL_TOP_PERIC0, 28, 1),
+       MUX(CLK_MOUT_SCLK_SPI3, "mout_sclk_spi3", mout_bus_pll_user_t_p,
+                       MUX_SEL_TOP_PERIC0, 24, 1),
+       MUX(CLK_MOUT_SCLK_UART2, "mout_sclk_uart2", mout_bus_pll_user_t_p,
+                       MUX_SEL_TOP_PERIC0, 20, 1),
+       MUX(CLK_MOUT_SCLK_UART1, "mout_sclk_uart1", mout_bus_pll_user_t_p,
+                       MUX_SEL_TOP_PERIC0, 16, 1),
+       MUX(CLK_MOUT_SCLK_UART0, "mout_sclk_uart0", mout_bus_pll_user_t_p,
+                       MUX_SEL_TOP_PERIC0, 12, 1),
+       MUX(CLK_MOUT_SCLK_SPI2, "mout_sclk_spi2", mout_bus_pll_user_t_p,
+                       MUX_SEL_TOP_PERIC0, 8, 1),
+       MUX(CLK_MOUT_SCLK_SPI1, "mout_sclk_spi1", mout_bus_pll_user_t_p,
+                       MUX_SEL_TOP_PERIC0, 4, 1),
+       MUX(CLK_MOUT_SCLK_SPI0, "mout_sclk_spi0", mout_bus_pll_user_t_p,
+                       MUX_SEL_TOP_PERIC0, 0, 1),
+
+       /* MUX_SEL_TOP_PERIC1 */
+       MUX(CLK_MOUT_SCLK_SLIMBUS, "mout_sclk_slimbus", mout_aud_pll_user_p,
+                       MUX_SEL_TOP_PERIC1, 16, 1),
+       MUX(CLK_MOUT_SCLK_SPDIF, "mout_sclk_spdif", mout_sclk_spdif_p,
+                       MUX_SEL_TOP_PERIC1, 12, 2),
+       MUX(CLK_MOUT_SCLK_AUDIO1, "mout_sclk_audio1", mout_sclk_audio1_p,
+                       MUX_SEL_TOP_PERIC1, 4, 2),
+       MUX(CLK_MOUT_SCLK_AUDIO0, "mout_sclk_audio0", mout_sclk_audio0_p,
+                       MUX_SEL_TOP_PERIC1, 0, 2),
+
+       /* MUX_SEL_TOP_DISP */
+       MUX(CLK_MOUT_SCLK_HDMI_SPDIF, "mout_sclk_hdmi_spdif",
+                       mout_sclk_hdmi_spdif_p, MUX_SEL_TOP_DISP, 0, 1),
+};
+
+static struct samsung_div_clock top_div_clks[] __initdata = {
+       /* DIV_TOP0 */
+       DIV(CLK_DIV_ACLK_CAM1_333, "div_aclk_cam1_333", "mout_aclk_cam1_333",
+                       DIV_TOP0, 28, 3),
+       DIV(CLK_DIV_ACLK_CAM1_400, "div_aclk_cam1_400", "mout_bus_pll_user",
+                       DIV_TOP0, 24, 3),
+       DIV(CLK_DIV_ACLK_CAM1_552, "div_aclk_cam1_552", "mout_aclk_cam1_552_b",
+                       DIV_TOP0, 20, 3),
+       DIV(CLK_DIV_ACLK_CAM0_333, "div_aclk_cam0_333", "mout_mfc_pll_user",
+                       DIV_TOP0, 16, 3),
+       DIV(CLK_DIV_ACLK_CAM0_400, "div_aclk_cam0_400", "mout_bus_pll_user",
+                       DIV_TOP0, 12, 3),
+       DIV(CLK_DIV_ACLK_CAM0_552, "div_aclk_cam0_552", "mout_isp_pll",
+                       DIV_TOP0, 8, 3),
+       DIV(CLK_DIV_ACLK_ISP_DIS_400, "div_aclk_isp_dis_400",
+                       "mout_aclk_isp_dis_400", DIV_TOP0, 4, 4),
+       DIV(CLK_DIV_ACLK_ISP_400, "div_aclk_isp_400",
+                       "mout_aclk_isp_400", DIV_TOP0, 0, 4),
+
+       /* DIV_TOP1 */
+       DIV(CLK_DIV_ACLK_GSCL_111, "div_aclk_gscl_111", "mout_aclk_gscl_333",
+                       DIV_TOP1, 28, 3),
+       DIV(CLK_DIV_ACLK_GSCL_333, "div_aclk_gscl_333", "mout_aclk_gscl_333",
+                       DIV_TOP1, 24, 3),
+       DIV(CLK_DIV_ACLK_HEVC_400, "div_aclk_hevc_400", "mout_aclk_hevc_400",
+                       DIV_TOP1, 20, 3),
+       DIV(CLK_DIV_ACLK_MFC_400, "div_aclk_mfc_400", "mout_aclk_mfc_400_c",
+                       DIV_TOP1, 12, 3),
+       DIV(CLK_DIV_ACLK_G2D_266, "div_aclk_g2d_266", "mout_bus_pll_user",
+                       DIV_TOP1, 8, 3),
+       DIV(CLK_DIV_ACLK_G2D_400, "div_aclk_g2d_400", "mout_aclk_g2d_400_b",
+                       DIV_TOP1, 0, 3),
+
+       /* DIV_TOP2 */
+       DIV(CLK_DIV_ACLK_MSCL_400, "div_aclk_mscl_400", "mout_aclk_mscl_400_b",
+                       DIV_TOP2, 4, 3),
+       DIV(CLK_DIV_ACLK_FSYS_200, "div_aclk_fsys_200", "mout_bus_pll_user",
+                       DIV_TOP2, 0, 3),
+
+       /* DIV_TOP3 */
+       DIV(CLK_DIV_ACLK_IMEM_SSSX_266, "div_aclk_imem_sssx_266",
+                       "mout_bus_pll_user", DIV_TOP3, 24, 3),
+       DIV(CLK_DIV_ACLK_IMEM_200, "div_aclk_imem_200",
+                       "mout_bus_pll_user", DIV_TOP3, 20, 3),
+       DIV(CLK_DIV_ACLK_IMEM_266, "div_aclk_imem_266",
+                       "mout_bus_pll_user", DIV_TOP3, 16, 3),
+       DIV(CLK_DIV_ACLK_PERIC_66_B, "div_aclk_peric_66_b",
+                       "div_aclk_peric_66_a", DIV_TOP3, 12, 3),
+       DIV(CLK_DIV_ACLK_PERIC_66_A, "div_aclk_peric_66_a",
+                       "mout_bus_pll_user", DIV_TOP3, 8, 3),
+       DIV(CLK_DIV_ACLK_PERIS_66_B, "div_aclk_peris_66_b",
+                       "div_aclk_peris_66_a", DIV_TOP3, 4, 3),
+       DIV(CLK_DIV_ACLK_PERIS_66_A, "div_aclk_peris_66_a",
+                       "mout_bus_pll_user", DIV_TOP3, 0, 3),
+
+       /* DIV_TOP4 */
+       DIV(CLK_DIV_ACLK_G3D_400, "div_aclk_g3d_400", "mout_bus_pll_user",
+                       DIV_TOP4, 8, 3),
+       DIV(CLK_DIV_ACLK_BUS0_400, "div_aclk_bus0_400", "mout_aclk_bus0_400",
+                       DIV_TOP4, 4, 3),
+       DIV(CLK_DIV_ACLK_BUS1_400, "div_aclk_bus1_400", "mout_bus_pll_user",
+                       DIV_TOP4, 0, 3),
+
+       /* DIV_TOP_MSCL */
+       DIV(CLK_DIV_SCLK_JPEG, "div_sclk_jpeg", "mout_sclk_jpeg_c",
+                       DIV_TOP_MSCL, 0, 4),
+
+       /* DIV_TOP_CAM10 */
+       DIV(CLK_DIV_SCLK_ISP_UART, "div_sclk_isp_uart", "mout_sclk_isp_uart",
+                       DIV_TOP_CAM10, 24, 5),
+       DIV(CLK_DIV_SCLK_ISP_SPI1_B, "div_sclk_isp_spi1_b",
+                       "div_sclk_isp_spi1_a", DIV_TOP_CAM10, 16, 8),
+       DIV(CLK_DIV_SCLK_ISP_SPI1_A, "div_sclk_isp_spi1_a",
+                       "mout_sclk_isp_spi1", DIV_TOP_CAM10, 12, 4),
+       DIV(CLK_DIV_SCLK_ISP_SPI0_B, "div_sclk_isp_spi0_b",
+                       "div_sclk_isp_spi0_a", DIV_TOP_CAM10, 4, 8),
+       DIV(CLK_DIV_SCLK_ISP_SPI0_A, "div_sclk_isp_spi0_a",
+                       "mout_sclk_isp_spi0", DIV_TOP_CAM10, 0, 4),
+
+       /* DIV_TOP_CAM11 */
+       DIV(CLK_DIV_SCLK_ISP_SENSOR2_B, "div_sclk_isp_sensor2_b",
+                       "div_sclk_isp_sensor2_a", DIV_TOP_CAM11, 20, 4),
+       DIV(CLK_DIV_SCLK_ISP_SENSOR2_A, "div_sclk_isp_sensor2_a",
+                       "mout_sclk_isp_sensor2", DIV_TOP_CAM11, 16, 4),
+       DIV(CLK_DIV_SCLK_ISP_SENSOR1_B, "div_sclk_isp_sensor1_b",
+                       "div_sclk_isp_sensor1_a", DIV_TOP_CAM11, 12, 4),
+       DIV(CLK_DIV_SCLK_ISP_SENSOR1_A, "div_sclk_isp_sensor1_a",
+                       "mout_sclk_isp_sensor1", DIV_TOP_CAM11, 8, 4),
+       DIV(CLK_DIV_SCLK_ISP_SENSOR0_B, "div_sclk_isp_sensor0_b",
+                       "div_sclk_isp_sensor0_a", DIV_TOP_CAM11, 12, 4),
+       DIV(CLK_DIV_SCLK_ISP_SENSOR0_A, "div_sclk_isp_sensor0_a",
+                       "mout_sclk_isp_sensor0", DIV_TOP_CAM11, 8, 4),
+
+       /* DIV_TOP_FSYS0 */
+       DIV(CLK_DIV_SCLK_MMC1_B, "div_sclk_mmc1_b", "div_sclk_mmc1_a",
+                       DIV_TOP_FSYS0, 16, 8),
+       DIV(CLK_DIV_SCLK_MMC1_A, "div_sclk_mmc1_a", "mout_sclk_mmc1_b",
+                       DIV_TOP_FSYS0, 12, 4),
+       DIV_F(CLK_DIV_SCLK_MMC0_B, "div_sclk_mmc0_b", "div_sclk_mmc0_a",
+                       DIV_TOP_FSYS0, 4, 8, CLK_SET_RATE_PARENT, 0),
+       DIV_F(CLK_DIV_SCLK_MMC0_A, "div_sclk_mmc0_a", "mout_sclk_mmc0_d",
+                       DIV_TOP_FSYS0, 0, 4, CLK_SET_RATE_PARENT, 0),
+
+       /* DIV_TOP_FSYS1 */
+       DIV(CLK_DIV_SCLK_MMC2_B, "div_sclk_mmc2_b", "div_sclk_mmc2_a",
+                       DIV_TOP_FSYS1, 4, 8),
+       DIV(CLK_DIV_SCLK_MMC2_A, "div_sclk_mmc2_a", "mout_sclk_mmc2_b",
+                       DIV_TOP_FSYS1, 0, 4),
+
+       /* DIV_TOP_FSYS2 */
+       DIV(CLK_DIV_SCLK_PCIE_100, "div_sclk_pcie_100", "mout_sclk_pcie_100",
+                       DIV_TOP_FSYS2, 12, 3),
+       DIV(CLK_DIV_SCLK_USBHOST30, "div_sclk_usbhost30",
+                       "mout_sclk_usbhost30", DIV_TOP_FSYS2, 8, 4),
+       DIV(CLK_DIV_SCLK_UFSUNIPRO, "div_sclk_ufsunipro",
+                       "mout_sclk_ufsunipro", DIV_TOP_FSYS2, 4, 4),
+       DIV(CLK_DIV_SCLK_USBDRD30, "div_sclk_usbdrd30", "mout_sclk_usbdrd30",
+                       DIV_TOP_FSYS2, 0, 4),
+
+       /* DIV_TOP_PERIC0 */
+       DIV(CLK_DIV_SCLK_SPI1_B, "div_sclk_spi1_b", "div_sclk_spi1_a",
+                       DIV_TOP_PERIC0, 16, 8),
+       DIV(CLK_DIV_SCLK_SPI1_A, "div_sclk_spi1_a", "mout_sclk_spi1",
+                       DIV_TOP_PERIC0, 12, 4),
+       DIV(CLK_DIV_SCLK_SPI0_B, "div_sclk_spi0_b", "div_sclk_spi0_a",
+                       DIV_TOP_PERIC0, 4, 8),
+       DIV(CLK_DIV_SCLK_SPI0_A, "div_sclk_spi0_a", "mout_sclk_spi0",
+                       DIV_TOP_PERIC0, 0, 4),
+
+       /* DIV_TOP_PERIC1 */
+       DIV(CLK_DIV_SCLK_SPI2_B, "div_sclk_spi2_b", "div_sclk_spi2_a",
+                       DIV_TOP_PERIC1, 4, 8),
+       DIV(CLK_DIV_SCLK_SPI2_A, "div_sclk_spi2_a", "mout_sclk_spi2",
+                       DIV_TOP_PERIC1, 0, 4),
+
+       /* DIV_TOP_PERIC2 */
+       DIV(CLK_DIV_SCLK_UART2, "div_sclk_uart2", "mout_sclk_uart2",
+                       DIV_TOP_PERIC2, 8, 4),
+       DIV(CLK_DIV_SCLK_UART1, "div_sclk_uart1", "mout_sclk_uart0",
+                       DIV_TOP_PERIC2, 4, 4),
+       DIV(CLK_DIV_SCLK_UART0, "div_sclk_uart0", "mout_sclk_uart1",
+                       DIV_TOP_PERIC2, 0, 4),
+
+       /* DIV_TOP_PERIC3 */
+       DIV(CLK_DIV_SCLK_I2S1, "div_sclk_i2s1", "sclk_audio1",
+                       DIV_TOP_PERIC3, 16, 6),
+       DIV(CLK_DIV_SCLK_PCM1, "div_sclk_pcm1", "sclk_audio1",
+                       DIV_TOP_PERIC3, 8, 8),
+       DIV(CLK_DIV_SCLK_AUDIO1, "div_sclk_audio1", "mout_sclk_audio1",
+                       DIV_TOP_PERIC3, 4, 4),
+       DIV(CLK_DIV_SCLK_AUDIO0, "div_sclk_audio0", "mout_sclk_audio0",
+                       DIV_TOP_PERIC3, 0, 4),
+
+       /* DIV_TOP_PERIC4 */
+       DIV(CLK_DIV_SCLK_SPI4_B, "div_sclk_spi4_b", "div_sclk_spi4_a",
+                       DIV_TOP_PERIC4, 16, 8),
+       DIV(CLK_DIV_SCLK_SPI4_A, "div_sclk_spi4_a", "mout_sclk_spi4",
+                       DIV_TOP_PERIC4, 12, 4),
+       DIV(CLK_DIV_SCLK_SPI3_B, "div_sclk_spi3_b", "div_sclk_spi3_a",
+                       DIV_TOP_PERIC4, 4, 8),
+       DIV(CLK_DIV_SCLK_SPI3_A, "div_sclk_spi3_a", "mout_sclk_spi3",
+                       DIV_TOP_PERIC4, 0, 4),
+};
+
+static struct samsung_gate_clock top_gate_clks[] __initdata = {
+       /* ENABLE_ACLK_TOP */
+       GATE(CLK_ACLK_G3D_400, "aclk_g3d_400", "div_aclk_g3d_400",
+                       ENABLE_ACLK_TOP, 30, 0, 0),
+       GATE(CLK_ACLK_IMEM_SSX_266, "aclk_imem_ssx_266",
+                       "div_aclk_imem_sssx_266", ENABLE_ACLK_TOP,
+                       29, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_BUS0_400, "aclk_bus0_400", "div_aclk_bus0_400",
+                       ENABLE_ACLK_TOP, 26,
+                       CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_ACLK_BUS1_400, "aclk_bus1_400", "div_aclk_bus1_400",
+                       ENABLE_ACLK_TOP, 25,
+                       CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_ACLK_IMEM_200, "aclk_imem_200", "div_aclk_imem_266",
+                       ENABLE_ACLK_TOP, 24,
+                       CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_ACLK_IMEM_266, "aclk_imem_266", "div_aclk_imem_200",
+                       ENABLE_ACLK_TOP, 23,
+                       CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_ACLK_PERIC_66, "aclk_peric_66", "div_aclk_peric_66_b",
+                       ENABLE_ACLK_TOP, 22,
+                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_PERIS_66, "aclk_peris_66", "div_aclk_peris_66_b",
+                       ENABLE_ACLK_TOP, 21,
+                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_MSCL_400, "aclk_mscl_400", "div_aclk_mscl_400",
+                       ENABLE_ACLK_TOP, 19,
+                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_FSYS_200, "aclk_fsys_200", "div_aclk_fsys_200",
+                       ENABLE_ACLK_TOP, 18,
+                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_GSCL_111, "aclk_gscl_111", "div_aclk_gscl_111",
+                       ENABLE_ACLK_TOP, 15,
+                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_GSCL_333, "aclk_gscl_333", "div_aclk_gscl_333",
+                       ENABLE_ACLK_TOP, 14,
+                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_CAM1_333, "aclk_cam1_333", "div_aclk_cam1_333",
+                       ENABLE_ACLK_TOP, 13,
+                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_CAM1_400, "aclk_cam1_400", "div_aclk_cam1_400",
+                       ENABLE_ACLK_TOP, 12,
+                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_CAM1_552, "aclk_cam1_552", "div_aclk_cam1_552",
+                       ENABLE_ACLK_TOP, 11,
+                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_CAM0_333, "aclk_cam0_333", "div_aclk_cam0_333",
+                       ENABLE_ACLK_TOP, 10,
+                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_CAM0_400, "aclk_cam0_400", "div_aclk_cam0_400",
+                       ENABLE_ACLK_TOP, 9,
+                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_CAM0_552, "aclk_cam0_552", "div_aclk_cam0_552",
+                       ENABLE_ACLK_TOP, 8,
+                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ISP_DIS_400, "aclk_isp_dis_400", "div_aclk_isp_dis_400",
+                       ENABLE_ACLK_TOP, 7,
+                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ISP_400, "aclk_isp_400", "div_aclk_isp_400",
+                       ENABLE_ACLK_TOP, 6,
+                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_HEVC_400, "aclk_hevc_400", "div_aclk_hevc_400",
+                       ENABLE_ACLK_TOP, 5,
+                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_MFC_400, "aclk_mfc_400", "div_aclk_mfc_400",
+                       ENABLE_ACLK_TOP, 3,
+                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_G2D_266, "aclk_g2d_266", "div_aclk_g2d_266",
+                       ENABLE_ACLK_TOP, 2,
+                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_G2D_400, "aclk_g2d_400", "div_aclk_g2d_400",
+                       ENABLE_ACLK_TOP, 0,
+                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_SCLK_TOP_MSCL */
+       GATE(CLK_SCLK_JPEG_MSCL, "sclk_jpeg_mscl", "div_sclk_jpeg",
+                       ENABLE_SCLK_TOP_MSCL, 0, 0, 0),
+
+       /* ENABLE_SCLK_TOP_CAM1 */
+       GATE(CLK_SCLK_ISP_SENSOR2, "sclk_isp_sensor2", "div_sclk_isp_sensor2_b",
+                       ENABLE_SCLK_TOP_CAM1, 7, 0, 0),
+       GATE(CLK_SCLK_ISP_SENSOR1, "sclk_isp_sensor1", "div_sclk_isp_sensor1_b",
+                       ENABLE_SCLK_TOP_CAM1, 6, 0, 0),
+       GATE(CLK_SCLK_ISP_SENSOR0, "sclk_isp_sensor0", "div_sclk_isp_sensor0_b",
+                       ENABLE_SCLK_TOP_CAM1, 5, 0, 0),
+       GATE(CLK_SCLK_ISP_MCTADC_CAM1, "sclk_isp_mctadc_cam1", "oscclk",
+                       ENABLE_SCLK_TOP_CAM1, 4, 0, 0),
+       GATE(CLK_SCLK_ISP_UART_CAM1, "sclk_isp_uart_cam1", "div_sclk_isp_uart",
+                       ENABLE_SCLK_TOP_CAM1, 2, 0, 0),
+       GATE(CLK_SCLK_ISP_SPI1_CAM1, "sclk_isp_spi1_cam1", "div_sclk_isp_spi1_b",
+                       ENABLE_SCLK_TOP_CAM1, 1, 0, 0),
+       GATE(CLK_SCLK_ISP_SPI0_CAM1, "sclk_isp_spi0_cam1", "div_sclk_isp_spi0_b",
+                       ENABLE_SCLK_TOP_CAM1, 0, 0, 0),
+
+       /* ENABLE_SCLK_TOP_DISP */
+       GATE(CLK_SCLK_HDMI_SPDIF_DISP, "sclk_hdmi_spdif_disp",
+                       "mout_sclk_hdmi_spdif", ENABLE_SCLK_TOP_DISP, 0,
+                       CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_SCLK_TOP_FSYS */
+       GATE(CLK_SCLK_PCIE_100_FSYS, "sclk_pcie_100_fsys", "div_sclk_pcie_100",
+                       ENABLE_SCLK_TOP_FSYS, 7, 0, 0),
+       GATE(CLK_SCLK_MMC2_FSYS, "sclk_mmc2_fsys", "div_sclk_mmc2_b",
+                       ENABLE_SCLK_TOP_FSYS, 6, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_MMC1_FSYS, "sclk_mmc1_fsys", "div_sclk_mmc1_b",
+                       ENABLE_SCLK_TOP_FSYS, 5, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_MMC0_FSYS, "sclk_mmc0_fsys", "div_sclk_mmc0_b",
+                       ENABLE_SCLK_TOP_FSYS, 4, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_UFSUNIPRO_FSYS, "sclk_ufsunipro_fsys",
+                       "div_sclk_ufsunipro", ENABLE_SCLK_TOP_FSYS,
+                       3, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_USBHOST30_FSYS, "sclk_usbhost30_fsys",
+                       "div_sclk_usbhost30", ENABLE_SCLK_TOP_FSYS,
+                       1, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_USBDRD30_FSYS, "sclk_usbdrd30_fsys",
+                       "div_sclk_usbdrd30", ENABLE_SCLK_TOP_FSYS,
+                       0, CLK_SET_RATE_PARENT, 0),
+
+       /* ENABLE_SCLK_TOP_PERIC */
+       GATE(CLK_SCLK_SPI4_PERIC, "sclk_spi4_peric", "div_sclk_spi4_b",
+                       ENABLE_SCLK_TOP_PERIC, 12, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_SPI3_PERIC, "sclk_spi3_peric", "div_sclk_spi3_b",
+                       ENABLE_SCLK_TOP_PERIC, 11, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_SPDIF_PERIC, "sclk_spdif_peric", "mout_sclk_spdif",
+                       ENABLE_SCLK_TOP_PERIC, 9, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_I2S1_PERIC, "sclk_i2s1_peric", "div_sclk_i2s1",
+                       ENABLE_SCLK_TOP_PERIC, 8, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_PCM1_PERIC, "sclk_pcm1_peric", "div_sclk_pcm1",
+                       ENABLE_SCLK_TOP_PERIC, 7, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_UART2_PERIC, "sclk_uart2_peric", "div_sclk_uart2",
+                       ENABLE_SCLK_TOP_PERIC, 5, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_UART1_PERIC, "sclk_uart1_peric", "div_sclk_uart1",
+                       ENABLE_SCLK_TOP_PERIC, 4, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_UART0_PERIC, "sclk_uart0_peric", "div_sclk_uart0",
+                       ENABLE_SCLK_TOP_PERIC, 3, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_SPI2_PERIC, "sclk_spi2_peric", "div_sclk_spi2_b",
+                       ENABLE_SCLK_TOP_PERIC, 2, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_SPI1_PERIC, "sclk_spi1_peric", "div_sclk_spi1_b",
+                       ENABLE_SCLK_TOP_PERIC, 1, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_SPI0_PERIC, "sclk_spi0_peric", "div_sclk_spi0_b",
+                       ENABLE_SCLK_TOP_PERIC, 0, CLK_SET_RATE_PARENT, 0),
+
+       /* MUX_ENABLE_TOP_PERIC1 */
+       GATE(CLK_SCLK_SLIMBUS, "sclk_slimbus", "mout_sclk_slimbus",
+                       MUX_ENABLE_TOP_PERIC1, 16, 0, 0),
+       GATE(CLK_SCLK_AUDIO1, "sclk_audio1", "div_sclk_audio1",
+                       MUX_ENABLE_TOP_PERIC1, 4, 0, 0),
+       GATE(CLK_SCLK_AUDIO0, "sclk_audio0", "div_sclk_audio0",
+                       MUX_ENABLE_TOP_PERIC1, 0, 0, 0),
+};
+
+/*
+ * ATLAS_PLL & APOLLO_PLL & MEM0_PLL & MEM1_PLL & BUS_PLL & MFC_PLL
+ * & MPHY_PLL & G3D_PLL & DISP_PLL & ISP_PLL
+ */
+static struct samsung_pll_rate_table exynos5443_pll_rates[] = {
+       PLL_35XX_RATE(2500000000U, 625, 6,  0),
+       PLL_35XX_RATE(2400000000U, 500, 5,  0),
+       PLL_35XX_RATE(2300000000U, 575, 6,  0),
+       PLL_35XX_RATE(2200000000U, 550, 6,  0),
+       PLL_35XX_RATE(2100000000U, 350, 4,  0),
+       PLL_35XX_RATE(2000000000U, 500, 6,  0),
+       PLL_35XX_RATE(1900000000U, 475, 6,  0),
+       PLL_35XX_RATE(1800000000U, 375, 5,  0),
+       PLL_35XX_RATE(1700000000U, 425, 6,  0),
+       PLL_35XX_RATE(1600000000U, 400, 6,  0),
+       PLL_35XX_RATE(1500000000U, 250, 4,  0),
+       PLL_35XX_RATE(1400000000U, 350, 6,  0),
+       PLL_35XX_RATE(1332000000U, 222, 4,  0),
+       PLL_35XX_RATE(1300000000U, 325, 6,  0),
+       PLL_35XX_RATE(1200000000U, 500, 5,  1),
+       PLL_35XX_RATE(1100000000U, 550, 6,  1),
+       PLL_35XX_RATE(1086000000U, 362, 4,  1),
+       PLL_35XX_RATE(1066000000U, 533, 6,  1),
+       PLL_35XX_RATE(1000000000U, 500, 6,  1),
+       PLL_35XX_RATE(933000000U,  311, 4,  1),
+       PLL_35XX_RATE(921000000U,  307, 4,  1),
+       PLL_35XX_RATE(900000000U,  375, 5,  1),
+       PLL_35XX_RATE(825000000U,  275, 4,  1),
+       PLL_35XX_RATE(800000000U,  400, 6,  1),
+       PLL_35XX_RATE(733000000U,  733, 12, 1),
+       PLL_35XX_RATE(700000000U,  360, 6,  1),
+       PLL_35XX_RATE(667000000U,  222, 4,  1),
+       PLL_35XX_RATE(633000000U,  211, 4,  1),
+       PLL_35XX_RATE(600000000U,  500, 5,  2),
+       PLL_35XX_RATE(552000000U,  460, 5,  2),
+       PLL_35XX_RATE(550000000U,  550, 6,  2),
+       PLL_35XX_RATE(543000000U,  362, 4,  2),
+       PLL_35XX_RATE(533000000U,  533, 6,  2),
+       PLL_35XX_RATE(500000000U,  500, 6,  2),
+       PLL_35XX_RATE(444000000U,  370, 5,  2),
+       PLL_35XX_RATE(420000000U,  350, 5,  2),
+       PLL_35XX_RATE(400000000U,  400, 6,  2),
+       PLL_35XX_RATE(350000000U,  360, 6,  2),
+       PLL_35XX_RATE(333000000U,  222, 4,  2),
+       PLL_35XX_RATE(300000000U,  500, 5,  3),
+       PLL_35XX_RATE(266000000U,  532, 6,  3),
+       PLL_35XX_RATE(200000000U,  400, 6,  3),
+       PLL_35XX_RATE(166000000U,  332, 6,  3),
+       PLL_35XX_RATE(160000000U,  320, 6,  3),
+       PLL_35XX_RATE(133000000U,  552, 6,  4),
+       PLL_35XX_RATE(100000000U,  400, 6,  4),
+       { /* sentinel */ }
+};
+
+/* AUD_PLL */
+static struct samsung_pll_rate_table exynos5443_aud_pll_rates[] = {
+       PLL_36XX_RATE(400000000U, 200, 3, 2,      0),
+       PLL_36XX_RATE(393216000U, 197, 3, 2, -25690),
+       PLL_36XX_RATE(384000000U, 128, 2, 2,      0),
+       PLL_36XX_RATE(368640000U, 246, 4, 2, -15729),
+       PLL_36XX_RATE(361507200U, 181, 3, 2, -16148),
+       PLL_36XX_RATE(338688000U, 113, 2, 2,  -6816),
+       PLL_36XX_RATE(294912000U,  98, 1, 3,  19923),
+       PLL_36XX_RATE(288000000U,  96, 1, 3,      0),
+       PLL_36XX_RATE(252000000U,  84, 1, 3,      0),
+       { /* sentinel */ }
+};
+
+static struct samsung_pll_clock top_pll_clks[] __initdata = {
+       PLL(pll_35xx, CLK_FOUT_ISP_PLL, "fout_isp_pll", "oscclk",
+               ISP_PLL_LOCK, ISP_PLL_CON0, exynos5443_pll_rates),
+       PLL(pll_36xx, CLK_FOUT_AUD_PLL, "fout_aud_pll", "oscclk",
+               AUD_PLL_LOCK, AUD_PLL_CON0, exynos5443_aud_pll_rates),
+};
+
+static struct samsung_cmu_info top_cmu_info __initdata = {
+       .pll_clks               = top_pll_clks,
+       .nr_pll_clks            = ARRAY_SIZE(top_pll_clks),
+       .mux_clks               = top_mux_clks,
+       .nr_mux_clks            = ARRAY_SIZE(top_mux_clks),
+       .div_clks               = top_div_clks,
+       .nr_div_clks            = ARRAY_SIZE(top_div_clks),
+       .gate_clks              = top_gate_clks,
+       .nr_gate_clks           = ARRAY_SIZE(top_gate_clks),
+       .fixed_clks             = top_fixed_clks,
+       .nr_fixed_clks          = ARRAY_SIZE(top_fixed_clks),
+       .fixed_factor_clks      = top_fixed_factor_clks,
+       .nr_fixed_factor_clks   = ARRAY_SIZE(top_fixed_factor_clks),
+       .nr_clk_ids             = TOP_NR_CLK,
+       .clk_regs               = top_clk_regs,
+       .nr_clk_regs            = ARRAY_SIZE(top_clk_regs),
+};
+
+static void __init exynos5433_cmu_top_init(struct device_node *np)
+{
+       samsung_cmu_register_one(np, &top_cmu_info);
+}
+CLK_OF_DECLARE(exynos5433_cmu_top, "samsung,exynos5433-cmu-top",
+               exynos5433_cmu_top_init);
+
+/*
+ * Register offset definitions for CMU_CPIF
+ */
+#define MPHY_PLL_LOCK          0x0000
+#define MPHY_PLL_CON0          0x0100
+#define MPHY_PLL_CON1          0x0104
+#define MPHY_PLL_FREQ_DET      0x010c
+#define MUX_SEL_CPIF0          0x0200
+#define DIV_CPIF               0x0600
+#define ENABLE_SCLK_CPIF       0x0a00
+
+static unsigned long cpif_clk_regs[] __initdata = {
+       MPHY_PLL_LOCK,
+       MPHY_PLL_CON0,
+       MPHY_PLL_CON1,
+       MPHY_PLL_FREQ_DET,
+       MUX_SEL_CPIF0,
+       ENABLE_SCLK_CPIF,
+};
+
+/* list of all parent clock list */
+PNAME(mout_mphy_pll_p)         = { "oscclk", "fout_mphy_pll", };
+
+static struct samsung_pll_clock cpif_pll_clks[] __initdata = {
+       PLL(pll_35xx, CLK_FOUT_MPHY_PLL, "fout_mphy_pll", "oscclk",
+               MPHY_PLL_LOCK, MPHY_PLL_CON0, exynos5443_pll_rates),
+};
+
+static struct samsung_mux_clock cpif_mux_clks[] __initdata = {
+       /* MUX_SEL_CPIF0 */
+       MUX(CLK_MOUT_MPHY_PLL, "mout_mphy_pll", mout_mphy_pll_p, MUX_SEL_CPIF0,
+                       0, 1),
+};
+
+static struct samsung_div_clock cpif_div_clks[] __initdata = {
+       /* DIV_CPIF */
+       DIV(CLK_DIV_SCLK_MPHY, "div_sclk_mphy", "mout_mphy_pll", DIV_CPIF,
+                       0, 6),
+};
+
+static struct samsung_gate_clock cpif_gate_clks[] __initdata = {
+       /* ENABLE_SCLK_CPIF */
+       GATE(CLK_SCLK_MPHY_PLL, "sclk_mphy_pll", "mout_mphy_pll",
+                       ENABLE_SCLK_CPIF, 9, 0, 0),
+       GATE(CLK_SCLK_UFS_MPHY, "sclk_ufs_mphy", "div_sclk_mphy",
+                       ENABLE_SCLK_CPIF, 4, 0, 0),
+};
+
+static struct samsung_cmu_info cpif_cmu_info __initdata = {
+       .pll_clks               = cpif_pll_clks,
+       .nr_pll_clks            = ARRAY_SIZE(cpif_pll_clks),
+       .mux_clks               = cpif_mux_clks,
+       .nr_mux_clks            = ARRAY_SIZE(cpif_mux_clks),
+       .div_clks               = cpif_div_clks,
+       .nr_div_clks            = ARRAY_SIZE(cpif_div_clks),
+       .gate_clks              = cpif_gate_clks,
+       .nr_gate_clks           = ARRAY_SIZE(cpif_gate_clks),
+       .nr_clk_ids             = CPIF_NR_CLK,
+       .clk_regs               = cpif_clk_regs,
+       .nr_clk_regs            = ARRAY_SIZE(cpif_clk_regs),
+};
+
+static void __init exynos5433_cmu_cpif_init(struct device_node *np)
+{
+       samsung_cmu_register_one(np, &cpif_cmu_info);
+}
+CLK_OF_DECLARE(exynos5433_cmu_cpif, "samsung,exynos5433-cmu-cpif",
+               exynos5433_cmu_cpif_init);
+
+/*
+ * Register offset definitions for CMU_MIF
+ */
+#define MEM0_PLL_LOCK                  0x0000
+#define MEM1_PLL_LOCK                  0x0004
+#define BUS_PLL_LOCK                   0x0008
+#define MFC_PLL_LOCK                   0x000c
+#define MEM0_PLL_CON0                  0x0100
+#define MEM0_PLL_CON1                  0x0104
+#define MEM0_PLL_FREQ_DET              0x010c
+#define MEM1_PLL_CON0                  0x0110
+#define MEM1_PLL_CON1                  0x0114
+#define MEM1_PLL_FREQ_DET              0x011c
+#define BUS_PLL_CON0                   0x0120
+#define BUS_PLL_CON1                   0x0124
+#define BUS_PLL_FREQ_DET               0x012c
+#define MFC_PLL_CON0                   0x0130
+#define MFC_PLL_CON1                   0x0134
+#define MFC_PLL_FREQ_DET               0x013c
+#define MUX_SEL_MIF0                   0x0200
+#define MUX_SEL_MIF1                   0x0204
+#define MUX_SEL_MIF2                   0x0208
+#define MUX_SEL_MIF3                   0x020c
+#define MUX_SEL_MIF4                   0x0210
+#define MUX_SEL_MIF5                   0x0214
+#define MUX_SEL_MIF6                   0x0218
+#define MUX_SEL_MIF7                   0x021c
+#define MUX_ENABLE_MIF0                        0x0300
+#define MUX_ENABLE_MIF1                        0x0304
+#define MUX_ENABLE_MIF2                        0x0308
+#define MUX_ENABLE_MIF3                        0x030c
+#define MUX_ENABLE_MIF4                        0x0310
+#define MUX_ENABLE_MIF5                        0x0314
+#define MUX_ENABLE_MIF6                        0x0318
+#define MUX_ENABLE_MIF7                        0x031c
+#define MUX_STAT_MIF0                  0x0400
+#define MUX_STAT_MIF1                  0x0404
+#define MUX_STAT_MIF2                  0x0408
+#define MUX_STAT_MIF3                  0x040c
+#define MUX_STAT_MIF4                  0x0410
+#define MUX_STAT_MIF5                  0x0414
+#define MUX_STAT_MIF6                  0x0418
+#define MUX_STAT_MIF7                  0x041c
+#define DIV_MIF1                       0x0604
+#define DIV_MIF2                       0x0608
+#define DIV_MIF3                       0x060c
+#define DIV_MIF4                       0x0610
+#define DIV_MIF5                       0x0614
+#define DIV_MIF_PLL_FREQ_DET           0x0618
+#define DIV_STAT_MIF1                  0x0704
+#define DIV_STAT_MIF2                  0x0708
+#define DIV_STAT_MIF3                  0x070c
+#define DIV_STAT_MIF4                  0x0710
+#define DIV_STAT_MIF5                  0x0714
+#define DIV_STAT_MIF_PLL_FREQ_DET      0x0718
+#define ENABLE_ACLK_MIF0               0x0800
+#define ENABLE_ACLK_MIF1               0x0804
+#define ENABLE_ACLK_MIF2               0x0808
+#define ENABLE_ACLK_MIF3               0x080c
+#define ENABLE_PCLK_MIF                        0x0900
+#define ENABLE_PCLK_MIF_SECURE_DREX0_TZ        0x0904
+#define ENABLE_PCLK_MIF_SECURE_DREX1_TZ        0x0908
+#define ENABLE_PCLK_MIF_SECURE_MONOTONIC_CNT   0x090c
+#define ENABLE_PCLK_MIF_SECURE_RTC     0x0910
+#define ENABLE_SCLK_MIF                        0x0a00
+#define ENABLE_IP_MIF0                 0x0b00
+#define ENABLE_IP_MIF1                 0x0b04
+#define ENABLE_IP_MIF2                 0x0b08
+#define ENABLE_IP_MIF3                 0x0b0c
+#define ENABLE_IP_MIF_SECURE_DREX0_TZ  0x0b10
+#define ENABLE_IP_MIF_SECURE_DREX1_TZ  0x0b14
+#define ENABLE_IP_MIF_SECURE_MONOTONIC_CNT     0x0b18
+#define ENABLE_IP_MIF_SECURE_RTC       0x0b1c
+#define CLKOUT_CMU_MIF                 0x0c00
+#define CLKOUT_CMU_MIF_DIV_STAT                0x0c04
+#define DREX_FREQ_CTRL0                        0x1000
+#define DREX_FREQ_CTRL1                        0x1004
+#define PAUSE                          0x1008
+#define DDRPHY_LOCK_CTRL               0x100c
+
+static unsigned long mif_clk_regs[] __initdata = {
+       MEM0_PLL_LOCK,
+       MEM1_PLL_LOCK,
+       BUS_PLL_LOCK,
+       MFC_PLL_LOCK,
+       MEM0_PLL_CON0,
+       MEM0_PLL_CON1,
+       MEM0_PLL_FREQ_DET,
+       MEM1_PLL_CON0,
+       MEM1_PLL_CON1,
+       MEM1_PLL_FREQ_DET,
+       BUS_PLL_CON0,
+       BUS_PLL_CON1,
+       BUS_PLL_FREQ_DET,
+       MFC_PLL_CON0,
+       MFC_PLL_CON1,
+       MFC_PLL_FREQ_DET,
+       MUX_SEL_MIF0,
+       MUX_SEL_MIF1,
+       MUX_SEL_MIF2,
+       MUX_SEL_MIF3,
+       MUX_SEL_MIF4,
+       MUX_SEL_MIF5,
+       MUX_SEL_MIF6,
+       MUX_SEL_MIF7,
+       MUX_ENABLE_MIF0,
+       MUX_ENABLE_MIF1,
+       MUX_ENABLE_MIF2,
+       MUX_ENABLE_MIF3,
+       MUX_ENABLE_MIF4,
+       MUX_ENABLE_MIF5,
+       MUX_ENABLE_MIF6,
+       MUX_ENABLE_MIF7,
+       MUX_STAT_MIF0,
+       MUX_STAT_MIF1,
+       MUX_STAT_MIF2,
+       MUX_STAT_MIF3,
+       MUX_STAT_MIF4,
+       MUX_STAT_MIF5,
+       MUX_STAT_MIF6,
+       MUX_STAT_MIF7,
+       DIV_MIF1,
+       DIV_MIF2,
+       DIV_MIF3,
+       DIV_MIF4,
+       DIV_MIF5,
+       DIV_MIF_PLL_FREQ_DET,
+       DIV_STAT_MIF1,
+       DIV_STAT_MIF2,
+       DIV_STAT_MIF3,
+       DIV_STAT_MIF4,
+       DIV_STAT_MIF5,
+       DIV_STAT_MIF_PLL_FREQ_DET,
+       ENABLE_ACLK_MIF0,
+       ENABLE_ACLK_MIF1,
+       ENABLE_ACLK_MIF2,
+       ENABLE_ACLK_MIF3,
+       ENABLE_PCLK_MIF,
+       ENABLE_PCLK_MIF_SECURE_DREX0_TZ,
+       ENABLE_PCLK_MIF_SECURE_DREX1_TZ,
+       ENABLE_PCLK_MIF_SECURE_MONOTONIC_CNT,
+       ENABLE_PCLK_MIF_SECURE_RTC,
+       ENABLE_SCLK_MIF,
+       ENABLE_IP_MIF0,
+       ENABLE_IP_MIF1,
+       ENABLE_IP_MIF2,
+       ENABLE_IP_MIF3,
+       ENABLE_IP_MIF_SECURE_DREX0_TZ,
+       ENABLE_IP_MIF_SECURE_DREX1_TZ,
+       ENABLE_IP_MIF_SECURE_MONOTONIC_CNT,
+       ENABLE_IP_MIF_SECURE_RTC,
+       CLKOUT_CMU_MIF,
+       CLKOUT_CMU_MIF_DIV_STAT,
+       DREX_FREQ_CTRL0,
+       DREX_FREQ_CTRL1,
+       PAUSE,
+       DDRPHY_LOCK_CTRL,
+};
+
+static struct samsung_pll_clock mif_pll_clks[] __initdata = {
+       PLL(pll_35xx, CLK_FOUT_MEM0_PLL, "fout_mem0_pll", "oscclk",
+               MEM0_PLL_LOCK, MEM0_PLL_CON0, exynos5443_pll_rates),
+       PLL(pll_35xx, CLK_FOUT_MEM1_PLL, "fout_mem1_pll", "oscclk",
+               MEM1_PLL_LOCK, MEM1_PLL_CON0, exynos5443_pll_rates),
+       PLL(pll_35xx, CLK_FOUT_BUS_PLL, "fout_bus_pll", "oscclk",
+               BUS_PLL_LOCK, BUS_PLL_CON0, exynos5443_pll_rates),
+       PLL(pll_35xx, CLK_FOUT_MFC_PLL, "fout_mfc_pll", "oscclk",
+               MFC_PLL_LOCK, MFC_PLL_CON0, exynos5443_pll_rates),
+};
+
+/* list of all parent clock list */
+PNAME(mout_mfc_pll_div2_p)     = { "mout_mfc_pll", "dout_mfc_pll", };
+PNAME(mout_bus_pll_div2_p)     = { "mout_bus_pll", "dout_bus_pll", };
+PNAME(mout_mem1_pll_div2_p)    = { "mout_mem1_pll", "dout_mem1_pll", };
+PNAME(mout_mem0_pll_div2_p)    = { "mout_mem0_pll", "dout_mem0_pll", };
+PNAME(mout_mfc_pll_p)          = { "oscclk", "fout_mfc_pll", };
+PNAME(mout_bus_pll_p)          = { "oscclk", "fout_bus_pll", };
+PNAME(mout_mem1_pll_p)         = { "oscclk", "fout_mem1_pll", };
+PNAME(mout_mem0_pll_p)         = { "oscclk", "fout_mem0_pll", };
+
+PNAME(mout_clk2x_phy_c_p)      = { "mout_mem0_pll_div2", "mout_clkm_phy_b", };
+PNAME(mout_clk2x_phy_b_p)      = { "mout_bus_pll_div2", "mout_clkm_phy_a", };
+PNAME(mout_clk2x_phy_a_p)      = { "mout_bus_pll_div2", "mout_mfc_pll_div2", };
+PNAME(mout_clkm_phy_b_p)       = { "mout_mem1_pll_div2", "mout_clkm_phy_a", };
+
+PNAME(mout_aclk_mifnm_200_p)   = { "mout_mem0_pll_div2", "div_mif_pre", };
+PNAME(mout_aclk_mifnm_400_p)   = { "mout_mem1_pll_div2", "mout_bus_pll_div2",};
+
+PNAME(mout_aclk_disp_333_b_p)  = { "mout_aclk_disp_333_a",
+                                   "mout_bus_pll_div2", };
+PNAME(mout_aclk_disp_333_a_p)  = { "mout_mfc_pll_div2", "sclk_mphy_pll", };
+
+PNAME(mout_sclk_decon_vclk_c_p)        = { "mout_sclk_decon_vclk_b",
+                                   "sclk_mphy_pll", };
+PNAME(mout_sclk_decon_vclk_b_p)        = { "mout_sclk_decon_vclk_a",
+                                   "mout_mfc_pll_div2", };
+PNAME(mout_sclk_decon_p)       = { "oscclk", "mout_bus_pll_div2", };
+PNAME(mout_sclk_decon_eclk_c_p)        = { "mout_sclk_decon_eclk_b",
+                                   "sclk_mphy_pll", };
+PNAME(mout_sclk_decon_eclk_b_p)        = { "mout_sclk_decon_eclk_a",
+                                   "mout_mfc_pll_div2", };
+
+PNAME(mout_sclk_decon_tv_eclk_c_p) = { "mout_sclk_decon_tv_eclk_b",
+                                      "sclk_mphy_pll", };
+PNAME(mout_sclk_decon_tv_eclk_b_p) = { "mout_sclk_decon_tv_eclk_a",
+                                      "mout_mfc_pll_div2", };
+PNAME(mout_sclk_dsd_c_p)       = { "mout_sclk_dsd_b", "mout_bus_pll_div2", };
+PNAME(mout_sclk_dsd_b_p)       = { "mout_sclk_dsd_a", "sclk_mphy_pll", };
+PNAME(mout_sclk_dsd_a_p)       = { "oscclk", "mout_mfc_pll_div2", };
+
+PNAME(mout_sclk_dsim0_c_p)     = { "mout_sclk_dsim0_b", "sclk_mphy_pll", };
+PNAME(mout_sclk_dsim0_b_p)     = { "mout_sclk_dsim0_a", "mout_mfc_pll_div2" };
+
+PNAME(mout_sclk_decon_tv_vclk_c_p) = { "mout_sclk_decon_tv_vclk_b",
+                                      "sclk_mphy_pll", };
+PNAME(mout_sclk_decon_tv_vclk_b_p) = { "mout_sclk_decon_tv_vclk_a",
+                                      "mout_mfc_pll_div2", };
+PNAME(mout_sclk_dsim1_c_p)     = { "mout_sclk_dsim1_b", "sclk_mphy_pll", };
+PNAME(mout_sclk_dsim1_b_p)     = { "mout_sclk_dsim1_a", "mout_mfc_pll_div2",};
+
+static struct samsung_fixed_factor_clock mif_fixed_factor_clks[] __initdata = {
+       /* dout_{mfc|bus|mem1|mem0}_pll is half fixed rate from parent mux */
+       FFACTOR(CLK_DOUT_MFC_PLL, "dout_mfc_pll", "mout_mfc_pll", 1, 1, 0),
+       FFACTOR(CLK_DOUT_BUS_PLL, "dout_bus_pll", "mout_bus_pll", 1, 1, 0),
+       FFACTOR(CLK_DOUT_MEM1_PLL, "dout_mem1_pll", "mout_mem1_pll", 1, 1, 0),
+       FFACTOR(CLK_DOUT_MEM0_PLL, "dout_mem0_pll", "mout_mem0_pll", 1, 1, 0),
+};
+
+static struct samsung_mux_clock mif_mux_clks[] __initdata = {
+       /* MUX_SEL_MIF0 */
+       MUX(CLK_MOUT_MFC_PLL_DIV2, "mout_mfc_pll_div2", mout_mfc_pll_div2_p,
+                       MUX_SEL_MIF0, 28, 1),
+       MUX(CLK_MOUT_BUS_PLL_DIV2, "mout_bus_pll_div2", mout_bus_pll_div2_p,
+                       MUX_SEL_MIF0, 24, 1),
+       MUX(CLK_MOUT_MEM1_PLL_DIV2, "mout_mem1_pll_div2", mout_mem1_pll_div2_p,
+                       MUX_SEL_MIF0, 20, 1),
+       MUX(CLK_MOUT_MEM0_PLL_DIV2, "mout_mem0_pll_div2", mout_mem0_pll_div2_p,
+                       MUX_SEL_MIF0, 16, 1),
+       MUX(CLK_MOUT_MFC_PLL, "mout_mfc_pll", mout_mfc_pll_p, MUX_SEL_MIF0,
+                       12, 1),
+       MUX(CLK_MOUT_BUS_PLL, "mout_bus_pll", mout_bus_pll_p, MUX_SEL_MIF0,
+                       8, 1),
+       MUX(CLK_MOUT_MEM1_PLL, "mout_mem1_pll", mout_mem1_pll_p, MUX_SEL_MIF0,
+                       4, 1),
+       MUX(CLK_MOUT_MEM0_PLL, "mout_mem0_pll", mout_mem0_pll_p, MUX_SEL_MIF0,
+                       0, 1),
+
+       /* MUX_SEL_MIF1 */
+       MUX(CLK_MOUT_CLK2X_PHY_C, "mout_clk2x_phy_c", mout_clk2x_phy_c_p,
+                       MUX_SEL_MIF1, 24, 1),
+       MUX(CLK_MOUT_CLK2X_PHY_B, "mout_clk2x_phy_b", mout_clk2x_phy_b_p,
+                       MUX_SEL_MIF1, 20, 1),
+       MUX(CLK_MOUT_CLK2X_PHY_A, "mout_clk2x_phy_a", mout_clk2x_phy_a_p,
+                       MUX_SEL_MIF1, 16, 1),
+       MUX(CLK_MOUT_CLKM_PHY_C, "mout_clkm_phy_c", mout_clk2x_phy_c_p,
+                       MUX_SEL_MIF1, 12, 1),
+       MUX(CLK_MOUT_CLKM_PHY_B, "mout_clkm_phy_b", mout_clkm_phy_b_p,
+                       MUX_SEL_MIF1, 8, 1),
+       MUX(CLK_MOUT_CLKM_PHY_A, "mout_clkm_phy_a", mout_clk2x_phy_a_p,
+                       MUX_SEL_MIF1, 4, 1),
+
+       /* MUX_SEL_MIF2 */
+       MUX(CLK_MOUT_ACLK_MIFNM_200, "mout_aclk_mifnm_200",
+                       mout_aclk_mifnm_200_p, MUX_SEL_MIF2, 8, 1),
+       MUX(CLK_MOUT_ACLK_MIFNM_400, "mout_aclk_mifnm_400",
+                       mout_aclk_mifnm_400_p, MUX_SEL_MIF2, 0, 1),
+
+       /* MUX_SEL_MIF3 */
+       MUX(CLK_MOUT_ACLK_DISP_333_B, "mout_aclk_disp_333_b",
+                       mout_aclk_disp_333_b_p, MUX_SEL_MIF3, 4, 1),
+       MUX(CLK_MOUT_ACLK_DISP_333_A, "mout_aclk_disp_333_a",
+                       mout_aclk_disp_333_a_p, MUX_SEL_MIF3, 0, 1),
+
+       /* MUX_SEL_MIF4 */
+       MUX(CLK_MOUT_SCLK_DECON_VCLK_C, "mout_sclk_decon_vclk_c",
+                       mout_sclk_decon_vclk_c_p, MUX_SEL_MIF4, 24, 1),
+       MUX(CLK_MOUT_SCLK_DECON_VCLK_B, "mout_sclk_decon_vclk_b",
+                       mout_sclk_decon_vclk_b_p, MUX_SEL_MIF4, 20, 1),
+       MUX(CLK_MOUT_SCLK_DECON_VCLK_A, "mout_sclk_decon_vclk_a",
+                       mout_sclk_decon_p, MUX_SEL_MIF4, 16, 1),
+       MUX(CLK_MOUT_SCLK_DECON_ECLK_C, "mout_sclk_decon_eclk_c",
+                       mout_sclk_decon_eclk_c_p, MUX_SEL_MIF4, 8, 1),
+       MUX(CLK_MOUT_SCLK_DECON_ECLK_B, "mout_sclk_decon_eclk_b",
+                       mout_sclk_decon_eclk_b_p, MUX_SEL_MIF4, 4, 1),
+       MUX(CLK_MOUT_SCLK_DECON_ECLK_A, "mout_sclk_decon_eclk_a",
+                       mout_sclk_decon_p, MUX_SEL_MIF4, 0, 1),
+
+       /* MUX_SEL_MIF5 */
+       MUX(CLK_MOUT_SCLK_DECON_TV_ECLK_C, "mout_sclk_decon_tv_eclk_c",
+                       mout_sclk_decon_tv_eclk_c_p, MUX_SEL_MIF5, 24, 1),
+       MUX(CLK_MOUT_SCLK_DECON_TV_ECLK_B, "mout_sclk_decon_tv_eclk_b",
+                       mout_sclk_decon_tv_eclk_b_p, MUX_SEL_MIF5, 20, 1),
+       MUX(CLK_MOUT_SCLK_DECON_TV_ECLK_A, "mout_sclk_decon_tv_eclk_a",
+                       mout_sclk_decon_p, MUX_SEL_MIF5, 16, 1),
+       MUX(CLK_MOUT_SCLK_DSD_C, "mout_sclk_dsd_c", mout_sclk_dsd_c_p,
+                       MUX_SEL_MIF5, 8, 1),
+       MUX(CLK_MOUT_SCLK_DSD_B, "mout_sclk_dsd_b", mout_sclk_dsd_b_p,
+                       MUX_SEL_MIF5, 4, 1),
+       MUX(CLK_MOUT_SCLK_DSD_A, "mout_sclk_dsd_a", mout_sclk_dsd_a_p,
+                       MUX_SEL_MIF5, 0, 1),
+
+       /* MUX_SEL_MIF6 */
+       MUX(CLK_MOUT_SCLK_DSIM0_C, "mout_sclk_dsim0_c", mout_sclk_dsim0_c_p,
+                       MUX_SEL_MIF6, 8, 1),
+       MUX(CLK_MOUT_SCLK_DSIM0_B, "mout_sclk_dsim0_b", mout_sclk_dsim0_b_p,
+                       MUX_SEL_MIF6, 4, 1),
+       MUX(CLK_MOUT_SCLK_DSIM0_A, "mout_sclk_dsim0_a", mout_sclk_decon_p,
+                       MUX_SEL_MIF6, 0, 1),
+
+       /* MUX_SEL_MIF7 */
+       MUX(CLK_MOUT_SCLK_DECON_TV_VCLK_C, "mout_sclk_decon_tv_vclk_c",
+                       mout_sclk_decon_tv_vclk_c_p, MUX_SEL_MIF7, 24, 1),
+       MUX(CLK_MOUT_SCLK_DECON_TV_VCLK_B, "mout_sclk_decon_tv_vclk_b",
+                       mout_sclk_decon_tv_vclk_b_p, MUX_SEL_MIF7, 20, 1),
+       MUX(CLK_MOUT_SCLK_DECON_TV_VCLK_A, "mout_sclk_decon_tv_vclk_a",
+                       mout_sclk_decon_p, MUX_SEL_MIF7, 16, 1),
+       MUX(CLK_MOUT_SCLK_DSIM1_C, "mout_sclk_dsim1_c", mout_sclk_dsim1_c_p,
+                       MUX_SEL_MIF7, 8, 1),
+       MUX(CLK_MOUT_SCLK_DSIM1_B, "mout_sclk_dsim1_b", mout_sclk_dsim1_b_p,
+                       MUX_SEL_MIF7, 4, 1),
+       MUX(CLK_MOUT_SCLK_DSIM1_A, "mout_sclk_dsim1_a", mout_sclk_decon_p,
+                       MUX_SEL_MIF7, 0, 1),
+};
+
+static struct samsung_div_clock mif_div_clks[] __initdata = {
+       /* DIV_MIF1 */
+       DIV(CLK_DIV_SCLK_HPM_MIF, "div_sclk_hpm_mif", "div_clk2x_phy",
+                       DIV_MIF1, 16, 2),
+       DIV(CLK_DIV_ACLK_DREX1, "div_aclk_drex1", "div_clk2x_phy", DIV_MIF1,
+                       12, 2),
+       DIV(CLK_DIV_ACLK_DREX0, "div_aclk_drex0", "div_clk2x_phy", DIV_MIF1,
+                       8, 2),
+       DIV(CLK_DIV_CLK2XPHY, "div_clk2x_phy", "mout_clk2x_phy_c", DIV_MIF1,
+                       4, 4),
+
+       /* DIV_MIF2 */
+       DIV(CLK_DIV_ACLK_MIF_266, "div_aclk_mif_266", "mout_bus_pll_div2",
+                       DIV_MIF2, 20, 3),
+       DIV(CLK_DIV_ACLK_MIFND_133, "div_aclk_mifnd_133", "div_mif_pre",
+                       DIV_MIF2, 16, 4),
+       DIV(CLK_DIV_ACLK_MIF_133, "div_aclk_mif_133", "div_mif_pre",
+                       DIV_MIF2, 12, 4),
+       DIV(CLK_DIV_ACLK_MIFNM_200, "div_aclk_mifnm_200",
+                       "mout_aclk_mifnm_200", DIV_MIF2, 8, 3),
+       DIV(CLK_DIV_ACLK_MIF_200, "div_aclk_mif_200", "div_aclk_mif_400",
+                       DIV_MIF2, 4, 2),
+       DIV(CLK_DIV_ACLK_MIF_400, "div_aclk_mif_400", "mout_aclk_mifnm_400",
+                       DIV_MIF2, 0, 3),
+
+       /* DIV_MIF3 */
+       DIV(CLK_DIV_ACLK_BUS2_400, "div_aclk_bus2_400", "div_mif_pre",
+                       DIV_MIF3, 16, 4),
+       DIV(CLK_DIV_ACLK_DISP_333, "div_aclk_disp_333", "mout_aclk_disp_333_b",
+                       DIV_MIF3, 4, 3),
+       DIV(CLK_DIV_ACLK_CPIF_200, "div_aclk_cpif_200", "mout_aclk_mifnm_200",
+                       DIV_MIF3, 0, 3),
+
+       /* DIV_MIF4 */
+       DIV(CLK_DIV_SCLK_DSIM1, "div_sclk_dsim1", "mout_sclk_dsim1_c",
+                       DIV_MIF4, 24, 4),
+       DIV(CLK_DIV_SCLK_DECON_TV_VCLK, "div_sclk_decon_tv_vclk",
+                       "mout_sclk_decon_tv_vclk_c", DIV_MIF4, 20, 4),
+       DIV(CLK_DIV_SCLK_DSIM0, "div_sclk_dsim0", "mout_sclk_dsim0_c",
+                       DIV_MIF4, 16, 4),
+       DIV(CLK_DIV_SCLK_DSD, "div_sclk_dsd", "mout_sclk_dsd_c",
+                       DIV_MIF4, 12, 4),
+       DIV(CLK_DIV_SCLK_DECON_TV_ECLK, "div_sclk_decon_tv_eclk",
+                       "mout_sclk_decon_tv_eclk_c", DIV_MIF4, 8, 4),
+       DIV(CLK_DIV_SCLK_DECON_VCLK, "div_sclk_decon_vclk",
+                       "mout_sclk_decon_vclk_c", DIV_MIF4, 4, 4),
+       DIV(CLK_DIV_SCLK_DECON_ECLK, "div_sclk_decon_eclk",
+                       "mout_sclk_decon_eclk_c", DIV_MIF4, 0, 4),
+
+       /* DIV_MIF5 */
+       DIV(CLK_DIV_MIF_PRE, "div_mif_pre", "mout_bus_pll_div2", DIV_MIF5,
+                       0, 3),
+};
+
+static struct samsung_gate_clock mif_gate_clks[] __initdata = {
+       /* ENABLE_ACLK_MIF0 */
+       GATE(CLK_CLK2X_PHY1, "clk2k_phy1", "div_clk2x_phy", ENABLE_ACLK_MIF0,
+                       19, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_CLK2X_PHY0, "clk2x_phy0", "div_clk2x_phy", ENABLE_ACLK_MIF0,
+                       18, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_CLKM_PHY1, "clkm_phy1", "mout_clkm_phy_c", ENABLE_ACLK_MIF0,
+                       17, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_CLKM_PHY0, "clkm_phy0", "mout_clkm_phy_c", ENABLE_ACLK_MIF0,
+                       16, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_RCLK_DREX1, "rclk_drex1", "oscclk", ENABLE_ACLK_MIF0,
+                       15, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_RCLK_DREX0, "rclk_drex0", "oscclk", ENABLE_ACLK_MIF0,
+                       14, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_DREX1_TZ, "aclk_drex1_tz", "div_aclk_drex1",
+                       ENABLE_ACLK_MIF0, 13, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_DREX0_TZ, "aclk_drex0_tz", "div_aclk_drex0",
+                       ENABLE_ACLK_MIF0, 12, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_DREX1_PEREV, "aclk_drex1_perev", "div_aclk_drex1",
+                       ENABLE_ACLK_MIF0, 11, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_DREX0_PEREV, "aclk_drex0_perev", "div_aclk_drex0",
+                       ENABLE_ACLK_MIF0, 10, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_DREX1_MEMIF, "aclk_drex1_memif", "div_aclk_drex1",
+                       ENABLE_ACLK_MIF0, 9, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_DREX0_MEMIF, "aclk_drex0_memif", "div_aclk_drex0",
+                       ENABLE_ACLK_MIF0, 8, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_DREX1_SCH, "aclk_drex1_sch", "div_aclk_drex1",
+                       ENABLE_ACLK_MIF0, 7, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_DREX0_SCH, "aclk_drex0_sch", "div_aclk_drex0",
+                       ENABLE_ACLK_MIF0, 6, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_DREX1_BUSIF, "aclk_drex1_busif", "div_aclk_drex1",
+                       ENABLE_ACLK_MIF0, 5, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_DREX0_BUSIF, "aclk_drex0_busif", "div_aclk_drex0",
+                       ENABLE_ACLK_MIF0, 4, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_DREX1_BUSIF_RD, "aclk_drex1_busif_rd", "div_aclk_drex1",
+                       ENABLE_ACLK_MIF0, 3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_DREX0_BUSIF_RD, "aclk_drex0_busif_rd", "div_aclk_drex0",
+                       ENABLE_ACLK_MIF0, 2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_DREX1, "aclk_drex1", "div_aclk_drex1",
+                       ENABLE_ACLK_MIF0, 2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_DREX0, "aclk_drex0", "div_aclk_drex0",
+                       ENABLE_ACLK_MIF0, 1, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_ACLK_MIF1 */
+       GATE(CLK_ACLK_ASYNCAXIS_MIF_IMEM, "aclk_asyncaxis_mif_imem",
+                       "div_aclk_mif_200", ENABLE_ACLK_MIF1, 28,
+                       CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIS_NOC_P_CCI, "aclk_asyncaxis_noc_p_cci",
+                       "div_aclk_mif_200", ENABLE_ACLK_MIF1,
+                       27, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIM_NOC_P_CCI, "aclk_asyncaxim_noc_p_cci",
+                       "div_aclk_mif_133", ENABLE_ACLK_MIF1,
+                       26, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIS_CP1, "aclk_asyncaxis_cp1",
+                       "div_aclk_mifnm_200", ENABLE_ACLK_MIF1,
+                       25, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIM_CP1, "aclk_asyncaxim_cp1",
+                       "div_aclk_drex1", ENABLE_ACLK_MIF1,
+                       24, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIS_CP0, "aclk_asyncaxis_cp0",
+                       "div_aclk_mifnm_200", ENABLE_ACLK_MIF1,
+                       23, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIM_CP0, "aclk_asyncaxim_cp0",
+                       "div_aclk_drex0", ENABLE_ACLK_MIF1,
+                       22, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIS_DREX1_3, "aclk_asyncaxis_drex1_3",
+                       "div_aclk_mif_133", ENABLE_ACLK_MIF1,
+                       21, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIM_DREX1_3, "aclk_asyncaxim_drex1_3",
+                       "div_aclk_drex1", ENABLE_ACLK_MIF1,
+                       20, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIS_DREX1_1, "aclk_asyncaxis_drex1_1",
+                       "div_aclk_mif_133", ENABLE_ACLK_MIF1,
+                       19, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIM_DREX1_1, "aclk_asyncaxim_drex1_1",
+                       "div_aclk_drex1", ENABLE_ACLK_MIF1,
+                       18, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIS_DREX1_0, "aclk_asyncaxis_drex1_0",
+                       "div_aclk_mif_133", ENABLE_ACLK_MIF1,
+                       17, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIM_DREX1_0, "aclk_asyncaxim_drex1_0",
+                       "div_aclk_drex1", ENABLE_ACLK_MIF1,
+                       16, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIS_DREX0_3, "aclk_asyncaxis_drex0_3",
+                       "div_aclk_mif_133", ENABLE_ACLK_MIF1,
+                       15, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIM_DREX0_3, "aclk_asyncaxim_drex0_3",
+                       "div_aclk_drex0", ENABLE_ACLK_MIF1,
+                       14, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIS_DREX0_1, "aclk_asyncaxis_drex0_1",
+                       "div_aclk_mif_133", ENABLE_ACLK_MIF1,
+                       13, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIM_DREX0_1, "aclk_asyncaxim_drex0_1",
+                       "div_aclk_drex0", ENABLE_ACLK_MIF1,
+                       12, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIS_DREX0_0, "aclk_asyncaxis_drex0_0",
+                       "div_aclk_mif_133", ENABLE_ACLK_MIF1,
+                       11, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIM_DREX0_0, "aclk_asyncaxim_drex0_0",
+                       "div_aclk_drex0", ENABLE_ACLK_MIF1,
+                       10, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AHB2APB_MIF2P, "aclk_ahb2apb_mif2p", "div_aclk_mif_133",
+                       ENABLE_ACLK_MIF1, 9, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AHB2APB_MIF1P, "aclk_ahb2apb_mif1p", "div_aclk_mif_133",
+                       ENABLE_ACLK_MIF1, 8, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AHB2APB_MIF0P, "aclk_ahb2apb_mif0p", "div_aclk_mif_133",
+                       ENABLE_ACLK_MIF1, 7, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_IXIU_CCI, "aclk_ixiu_cci", "div_aclk_mif_400",
+                       ENABLE_ACLK_MIF1, 6, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_XIU_MIFSFRX, "aclk_xiu_mifsfrx", "div_aclk_mif_200",
+                       ENABLE_ACLK_MIF1, 5, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_MIFNP_133, "aclk_mifnp_133", "div_aclk_mif_133",
+                       ENABLE_ACLK_MIF1, 4, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_MIFNM_200, "aclk_mifnm_200", "div_aclk_mifnm_200",
+                       ENABLE_ACLK_MIF1, 3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_MIFND_133, "aclk_mifnd_133", "div_aclk_mifnd_133",
+                       ENABLE_ACLK_MIF1, 2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_MIFND_400, "aclk_mifnd_400", "div_aclk_mif_400",
+                       ENABLE_ACLK_MIF1, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_CCI, "aclk_cci", "div_aclk_mif_400", ENABLE_ACLK_MIF1,
+                       0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_ACLK_MIF2 */
+       GATE(CLK_ACLK_MIFND_266, "aclk_mifnd_266", "div_aclk_mif_266",
+                       ENABLE_ACLK_MIF2, 20, 0, 0),
+       GATE(CLK_ACLK_PPMU_DREX1S3, "aclk_ppmu_drex1s3", "div_aclk_drex1",
+                       ENABLE_ACLK_MIF2, 17, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_PPMU_DREX1S1, "aclk_ppmu_drex1s1", "div_aclk_drex1",
+                       ENABLE_ACLK_MIF2, 16, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_PPMU_DREX1S0, "aclk_ppmu_drex1s0", "div_aclk_drex1",
+                       ENABLE_ACLK_MIF2, 15, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_PPMU_DREX0S3, "aclk_ppmu_drex0s3", "div_aclk_drex0",
+                       ENABLE_ACLK_MIF2, 14, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_PPMU_DREX0S1, "aclk_ppmu_drex0s1", "div_aclk_drex0",
+                       ENABLE_ACLK_MIF2, 13, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_PPMU_DREX0S0, "aclk_ppmu_drex0s0", "div_aclk_drex0",
+                       ENABLE_ACLK_MIF2, 12, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AXIDS_CCI_MIFSFRX, "aclk_axids_cci_mifsfrx",
+                       "div_aclk_mif_200", ENABLE_ACLK_MIF2, 7,
+                       CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AXISYNCDNS_CCI, "aclk_axisyncdns_cci",
+                       "div_aclk_mif_400", ENABLE_ACLK_MIF2,
+                       5, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AXISYNCDN_CCI, "aclk_axisyncdn_cci", "div_aclk_mif_400",
+                       ENABLE_ACLK_MIF2, 4, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AXISYNCDN_NOC_D, "aclk_axisyncdn_noc_d",
+                       "div_aclk_mif_200", ENABLE_ACLK_MIF2,
+                       3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAPBS_MIF_CSSYS, "aclk_asyncapbs_mif_cssys",
+                       "div_aclk_mifnd_133", ENABLE_ACLK_MIF2, 0, 0, 0),
+
+       /* ENABLE_ACLK_MIF3 */
+       GATE(CLK_ACLK_BUS2_400, "aclk_bus2_400", "div_aclk_bus2_400",
+                       ENABLE_ACLK_MIF3, 4,
+                       CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_ACLK_DISP_333, "aclk_disp_333", "div_aclk_disp_333",
+                       ENABLE_ACLK_MIF3, 1,
+                       CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_ACLK_CPIF_200, "aclk_cpif_200", "div_aclk_cpif_200",
+                       ENABLE_ACLK_MIF3, 0,
+                       CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
+
+       /* ENABLE_PCLK_MIF */
+       GATE(CLK_PCLK_PPMU_DREX1S3, "pclk_ppmu_drex1s3", "div_aclk_drex1",
+                       ENABLE_PCLK_MIF, 29, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_PPMU_DREX1S1, "pclk_ppmu_drex1s1", "div_aclk_drex1",
+                       ENABLE_PCLK_MIF, 28, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_PPMU_DREX1S0, "pclk_ppmu_drex1s0", "div_aclk_drex1",
+                       ENABLE_PCLK_MIF, 27, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_PPMU_DREX0S3, "pclk_ppmu_drex0s3", "div_aclk_drex0",
+                       ENABLE_PCLK_MIF, 26, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_PPMU_DREX0S1, "pclk_ppmu_drex0s1", "div_aclk_drex0",
+                       ENABLE_PCLK_MIF, 25, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_PPMU_DREX0S0, "pclk_ppmu_drex0s0", "div_aclk_drex0",
+                       ENABLE_PCLK_MIF, 24, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_ASYNCAXI_NOC_P_CCI, "pclk_asyncaxi_noc_p_cci",
+                       "div_aclk_mif_133", ENABLE_PCLK_MIF, 21,
+                       CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_ASYNCAXI_CP1, "pclk_asyncaxi_cp1", "div_aclk_mif_133",
+                       ENABLE_PCLK_MIF, 19, 0, 0),
+       GATE(CLK_PCLK_ASYNCAXI_CP0, "pclk_asyncaxi_cp0", "div_aclk_mif_133",
+                       ENABLE_PCLK_MIF, 18, 0, 0),
+       GATE(CLK_PCLK_ASYNCAXI_DREX1_3, "pclk_asyncaxi_drex1_3",
+                       "div_aclk_mif_133", ENABLE_PCLK_MIF, 17, 0, 0),
+       GATE(CLK_PCLK_ASYNCAXI_DREX1_1, "pclk_asyncaxi_drex1_1",
+                       "div_aclk_mif_133", ENABLE_PCLK_MIF, 16, 0, 0),
+       GATE(CLK_PCLK_ASYNCAXI_DREX1_0, "pclk_asyncaxi_drex1_0",
+                       "div_aclk_mif_133", ENABLE_PCLK_MIF, 15, 0, 0),
+       GATE(CLK_PCLK_ASYNCAXI_DREX0_3, "pclk_asyncaxi_drex0_3",
+                       "div_aclk_mif_133", ENABLE_PCLK_MIF, 14, 0, 0),
+       GATE(CLK_PCLK_ASYNCAXI_DREX0_1, "pclk_asyncaxi_drex0_1",
+                       "div_aclk_mif_133", ENABLE_PCLK_MIF, 13, 0, 0),
+       GATE(CLK_PCLK_ASYNCAXI_DREX0_0, "pclk_asyncaxi_drex0_0",
+                       "div_aclk_mif_133", ENABLE_PCLK_MIF, 12, 0, 0),
+       GATE(CLK_PCLK_MIFSRVND_133, "pclk_mifsrvnd_133", "div_aclk_mif_133",
+                       ENABLE_PCLK_MIF, 11, 0, 0),
+       GATE(CLK_PCLK_PMU_MIF, "pclk_pmu_mif", "div_aclk_mif_133",
+                       ENABLE_PCLK_MIF, 10, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SYSREG_MIF, "pclk_sysreg_mif", "div_aclk_mif_133",
+                       ENABLE_PCLK_MIF, 9, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_GPIO_ALIVE, "pclk_gpio_alive", "div_aclk_mif_133",
+                       ENABLE_PCLK_MIF, 8, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_ABB, "pclk_abb", "div_aclk_mif_133",
+                       ENABLE_PCLK_MIF, 7, 0, 0),
+       GATE(CLK_PCLK_PMU_APBIF, "pclk_pmu_apbif", "div_aclk_mif_133",
+                       ENABLE_PCLK_MIF, 6, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_DDR_PHY1, "pclk_ddr_phy1", "div_aclk_mif_133",
+                       ENABLE_PCLK_MIF, 5, 0, 0),
+       GATE(CLK_PCLK_DREX1, "pclk_drex1", "div_aclk_mif_133",
+                       ENABLE_PCLK_MIF, 3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_DDR_PHY0, "pclk_ddr_phy0", "div_aclk_mif_133",
+                       ENABLE_PCLK_MIF, 2, 0, 0),
+       GATE(CLK_PCLK_DREX0, "pclk_drex0", "div_aclk_mif_133",
+                       ENABLE_PCLK_MIF, 0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_PCLK_MIF_SECURE_DREX0_TZ */
+       GATE(CLK_PCLK_DREX0_TZ, "pclk_drex0_tz", "div_aclk_mif_133",
+                       ENABLE_PCLK_MIF_SECURE_DREX0_TZ, 0, 0, 0),
+
+       /* ENABLE_PCLK_MIF_SECURE_DREX1_TZ */
+       GATE(CLK_PCLK_DREX1_TZ, "pclk_drex1_tz", "div_aclk_mif_133",
+                       ENABLE_PCLK_MIF_SECURE_DREX1_TZ, 0, 0, 0),
+
+       /* ENABLE_PCLK_MIF_SECURE_MONOTONIC_CNT */
+       GATE(CLK_PCLK_MONOTONIC_CNT, "pclk_monotonic_cnt", "div_aclk_mif_133",
+                       ENABLE_PCLK_MIF_SECURE_RTC, 0, 0, 0),
+
+       /* ENABLE_PCLK_MIF_SECURE_RTC */
+       GATE(CLK_PCLK_RTC, "pclk_rtc", "div_aclk_mif_133",
+                       ENABLE_PCLK_MIF_SECURE_RTC, 0, 0, 0),
+
+       /* ENABLE_SCLK_MIF */
+       GATE(CLK_SCLK_DSIM1_DISP, "sclk_dsim1_disp", "div_sclk_dsim1",
+                       ENABLE_SCLK_MIF, 15, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SCLK_DECON_TV_VCLK_DISP, "sclk_decon_tv_vclk_disp",
+                       "div_sclk_decon_tv_vclk", ENABLE_SCLK_MIF,
+                       14, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SCLK_DSIM0_DISP, "sclk_dsim0_disp", "div_sclk_dsim0",
+                       ENABLE_SCLK_MIF, 9, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SCLK_DSD_DISP, "sclk_dsd_disp", "div_sclk_dsd",
+                       ENABLE_SCLK_MIF, 8, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SCLK_DECON_TV_ECLK_DISP, "sclk_decon_tv_eclk_disp",
+                       "div_sclk_decon_tv_eclk", ENABLE_SCLK_MIF,
+                       7, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SCLK_DECON_VCLK_DISP, "sclk_decon_vclk_disp",
+                       "div_sclk_decon_vclk", ENABLE_SCLK_MIF,
+                       6, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SCLK_DECON_ECLK_DISP, "sclk_decon_eclk_disp",
+                       "div_sclk_decon_eclk", ENABLE_SCLK_MIF,
+                       5, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SCLK_HPM_MIF, "sclk_hpm_mif", "div_sclk_hpm_mif",
+                       ENABLE_SCLK_MIF, 4,
+                       CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_MFC_PLL, "sclk_mfc_pll", "mout_mfc_pll_div2",
+                       ENABLE_SCLK_MIF, 3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SCLK_BUS_PLL, "sclk_bus_pll", "mout_bus_pll_div2",
+                       ENABLE_SCLK_MIF, 2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SCLK_BUS_PLL_APOLLO, "sclk_bus_pll_apollo", "sclk_bus_pll",
+                       ENABLE_SCLK_MIF, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SCLK_BUS_PLL_ATLAS, "sclk_bus_pll_atlas", "sclk_bus_pll",
+                       ENABLE_SCLK_MIF, 0, CLK_IGNORE_UNUSED, 0),
+};
+
+static struct samsung_cmu_info mif_cmu_info __initdata = {
+       .pll_clks               = mif_pll_clks,
+       .nr_pll_clks            = ARRAY_SIZE(mif_pll_clks),
+       .mux_clks               = mif_mux_clks,
+       .nr_mux_clks            = ARRAY_SIZE(mif_mux_clks),
+       .div_clks               = mif_div_clks,
+       .nr_div_clks            = ARRAY_SIZE(mif_div_clks),
+       .gate_clks              = mif_gate_clks,
+       .nr_gate_clks           = ARRAY_SIZE(mif_gate_clks),
+       .fixed_factor_clks      = mif_fixed_factor_clks,
+       .nr_fixed_factor_clks   = ARRAY_SIZE(mif_fixed_factor_clks),
+       .nr_clk_ids             = MIF_NR_CLK,
+       .clk_regs               = mif_clk_regs,
+       .nr_clk_regs            = ARRAY_SIZE(mif_clk_regs),
+};
+
+static void __init exynos5433_cmu_mif_init(struct device_node *np)
+{
+       samsung_cmu_register_one(np, &mif_cmu_info);
+}
+CLK_OF_DECLARE(exynos5433_cmu_mif, "samsung,exynos5433-cmu-mif",
+               exynos5433_cmu_mif_init);
+
+/*
+ * Register offset definitions for CMU_PERIC
+ */
+#define DIV_PERIC                      0x0600
+#define DIV_STAT_PERIC                 0x0700
+#define ENABLE_ACLK_PERIC              0x0800
+#define ENABLE_PCLK_PERIC0             0x0900
+#define ENABLE_PCLK_PERIC1             0x0904
+#define ENABLE_SCLK_PERIC              0x0A00
+#define ENABLE_IP_PERIC0               0x0B00
+#define ENABLE_IP_PERIC1               0x0B04
+#define ENABLE_IP_PERIC2               0x0B08
+
+static unsigned long peric_clk_regs[] __initdata = {
+       DIV_PERIC,
+       DIV_STAT_PERIC,
+       ENABLE_ACLK_PERIC,
+       ENABLE_PCLK_PERIC0,
+       ENABLE_PCLK_PERIC1,
+       ENABLE_SCLK_PERIC,
+       ENABLE_IP_PERIC0,
+       ENABLE_IP_PERIC1,
+       ENABLE_IP_PERIC2,
+};
+
+static struct samsung_div_clock peric_div_clks[] __initdata = {
+       /* DIV_PERIC */
+       DIV(CLK_DIV_SCLK_SCI, "div_sclk_sci", "oscclk", DIV_PERIC, 4, 4),
+       DIV(CLK_DIV_SCLK_SC_IN, "div_sclk_sc_in", "oscclk", DIV_PERIC, 0, 4),
+};
+
+static struct samsung_gate_clock peric_gate_clks[] __initdata = {
+       /* ENABLE_ACLK_PERIC */
+       GATE(CLK_ACLK_AHB2APB_PERIC2P, "aclk_ahb2apb_peric2p", "aclk_peric_66",
+                       ENABLE_ACLK_PERIC, 3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AHB2APB_PERIC1P, "aclk_ahb2apb_peric1p", "aclk_peric_66",
+                       ENABLE_ACLK_PERIC, 2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AHB2APB_PERIC0P, "aclk_ahb2apb_peric0p", "aclk_peric_66",
+                       ENABLE_ACLK_PERIC, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_PERICNP_66, "aclk_pericnp_66", "aclk_peric_66",
+                       ENABLE_ACLK_PERIC, 0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_PCLK_PERIC0 */
+       GATE(CLK_PCLK_SCI, "pclk_sci", "aclk_peric_66", ENABLE_PCLK_PERIC0,
+                       31, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_GPIO_FINGER, "pclk_gpio_finger", "aclk_peric_66",
+                       ENABLE_PCLK_PERIC0, 30, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_GPIO_ESE, "pclk_gpio_ese", "aclk_peric_66",
+                       ENABLE_PCLK_PERIC0, 29, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_PWM, "pclk_pwm", "aclk_peric_66", ENABLE_PCLK_PERIC0,
+                       28, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_SPDIF, "pclk_spdif", "aclk_peric_66", ENABLE_PCLK_PERIC0,
+                       26, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_PCM1, "pclk_pcm1", "aclk_peric_66", ENABLE_PCLK_PERIC0,
+                       25, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_I2S1, "pclk_i2s", "aclk_peric_66", ENABLE_PCLK_PERIC0,
+                       24, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_SPI2, "pclk_spi2", "aclk_peric_66", ENABLE_PCLK_PERIC0,
+                       23, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_SPI1, "pclk_spi1", "aclk_peric_66", ENABLE_PCLK_PERIC0,
+                       22, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_SPI0, "pclk_spi0", "aclk_peric_66", ENABLE_PCLK_PERIC0,
+                       21, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_ADCIF, "pclk_adcif", "aclk_peric_66", ENABLE_PCLK_PERIC0,
+                       20, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_GPIO_TOUCH, "pclk_gpio_touch", "aclk_peric_66",
+                       ENABLE_PCLK_PERIC0, 19, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_GPIO_NFC, "pclk_gpio_nfc", "aclk_peric_66",
+                       ENABLE_PCLK_PERIC0, 18, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_GPIO_PERIC, "pclk_gpio_peric", "aclk_peric_66",
+                       ENABLE_PCLK_PERIC0, 17, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_PMU_PERIC, "pclk_pmu_peric", "aclk_peric_66",
+                       ENABLE_PCLK_PERIC0, 16, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_SYSREG_PERIC, "pclk_sysreg_peric", "aclk_peric_66",
+                       ENABLE_PCLK_PERIC0, 15,
+                       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_UART2, "pclk_uart2", "aclk_peric_66", ENABLE_PCLK_PERIC0,
+                       14, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_UART1, "pclk_uart1", "aclk_peric_66", ENABLE_PCLK_PERIC0,
+                       13, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_UART0, "pclk_uart0", "aclk_peric_66", ENABLE_PCLK_PERIC0,
+                       12, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_HSI2C3, "pclk_hsi2c3", "aclk_peric_66",
+                       ENABLE_PCLK_PERIC0, 11, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_HSI2C2, "pclk_hsi2c2", "aclk_peric_66",
+                       ENABLE_PCLK_PERIC0, 10, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_HSI2C1, "pclk_hsi2c1", "aclk_peric_66",
+                       ENABLE_PCLK_PERIC0, 9, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_HSI2C0, "pclk_hsi2c0", "aclk_peric_66",
+                       ENABLE_PCLK_PERIC0, 8, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_I2C7, "pclk_i2c7", "aclk_peric_66", ENABLE_PCLK_PERIC0,
+                       7, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_I2C6, "pclk_i2c6", "aclk_peric_66", ENABLE_PCLK_PERIC0,
+                       6, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_I2C5, "pclk_i2c5", "aclk_peric_66", ENABLE_PCLK_PERIC0,
+                       5, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_I2C4, "pclk_i2c4", "aclk_peric_66", ENABLE_PCLK_PERIC0,
+                       4, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_I2C3, "pclk_i2c3", "aclk_peric_66", ENABLE_PCLK_PERIC0,
+                       3, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_I2C2, "pclk_i2c2", "aclk_peric_66", ENABLE_PCLK_PERIC0,
+                       2, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_I2C1, "pclk_i2c1", "aclk_peric_66", ENABLE_PCLK_PERIC0,
+                       1, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_I2C0, "pclk_i2c0", "aclk_peric_66", ENABLE_PCLK_PERIC0,
+                       0, CLK_SET_RATE_PARENT, 0),
+
+       /* ENABLE_PCLK_PERIC1 */
+       GATE(CLK_PCLK_SPI4, "pclk_spi4", "aclk_peric_66", ENABLE_PCLK_PERIC1,
+                       9, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_SPI3, "pclk_spi3", "aclk_peric_66", ENABLE_PCLK_PERIC1,
+                       8, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_HSI2C11, "pclk_hsi2c11", "aclk_peric_66",
+                       ENABLE_PCLK_PERIC1, 7, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_HSI2C10, "pclk_hsi2c10", "aclk_peric_66",
+                       ENABLE_PCLK_PERIC1, 6, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_HSI2C9, "pclk_hsi2c9", "aclk_peric_66",
+                       ENABLE_PCLK_PERIC1, 5, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_HSI2C8, "pclk_hsi2c8", "aclk_peric_66",
+                       ENABLE_PCLK_PERIC1, 4, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_HSI2C7, "pclk_hsi2c7", "aclk_peric_66",
+                       ENABLE_PCLK_PERIC1, 3, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_HSI2C6, "pclk_hsi2c6", "aclk_peric_66",
+                       ENABLE_PCLK_PERIC1, 2, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_HSI2C5, "pclk_hsi2c5", "aclk_peric_66",
+                       ENABLE_PCLK_PERIC1, 1, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_PCLK_HSI2C4, "pclk_hsi2c4", "aclk_peric_66",
+                       ENABLE_PCLK_PERIC1, 0, CLK_SET_RATE_PARENT, 0),
+
+       /* ENABLE_SCLK_PERIC */
+       GATE(CLK_SCLK_IOCLK_SPI4, "sclk_ioclk_spi4", "ioclk_spi4_clk_in",
+                       ENABLE_SCLK_PERIC, 21, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_IOCLK_SPI3, "sclk_ioclk_spi3", "ioclk_spi3_clk_in",
+                       ENABLE_SCLK_PERIC, 20, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_SPI4, "sclk_spi4", "sclk_spi4_peric", ENABLE_SCLK_PERIC,
+                       19, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_SPI3, "sclk_spi3", "sclk_spi3_peric", ENABLE_SCLK_PERIC,
+                       18, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_SCI, "sclk_sci", "div_sclk_sci", ENABLE_SCLK_PERIC,
+                       17, 0, 0),
+       GATE(CLK_SCLK_SC_IN, "sclk_sc_in", "div_sclk_sc_in", ENABLE_SCLK_PERIC,
+                       16, 0, 0),
+       GATE(CLK_SCLK_PWM, "sclk_pwm", "oscclk", ENABLE_SCLK_PERIC, 15, 0, 0),
+       GATE(CLK_SCLK_IOCLK_SPI2, "sclk_ioclk_spi2", "ioclk_spi2_clk_in",
+                       ENABLE_SCLK_PERIC, 13, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_IOCLK_SPI1, "sclk_ioclk_spi1", "ioclk_spi1_clk_in",
+                       ENABLE_SCLK_PERIC, 12,
+                       CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_IOCLK_SPI0, "sclk_ioclk_spi0", "ioclk_spi0_clk_in",
+                       ENABLE_SCLK_PERIC, 11, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_IOCLK_I2S1_BCLK, "sclk_ioclk_i2s1_bclk",
+                       "ioclk_i2s1_bclk_in", ENABLE_SCLK_PERIC, 10,
+                       CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_SPDIF, "sclk_spdif", "sclk_spdif_peric",
+                       ENABLE_SCLK_PERIC, 8, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_PCM1, "sclk_pcm1", "sclk_pcm1_peric",
+                       ENABLE_SCLK_PERIC, 7, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_I2S1, "sclk_i2s1", "sclk_i2s1_peric",
+                       ENABLE_SCLK_PERIC, 6, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_SPI2, "sclk_spi2", "sclk_spi2_peric", ENABLE_SCLK_PERIC,
+                       5, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_SPI1, "sclk_spi1", "sclk_spi1_peric", ENABLE_SCLK_PERIC,
+                       4, CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_SPI0, "sclk_spi0", "sclk_spi0_peric", ENABLE_SCLK_PERIC,
+                       3, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_UART2, "sclk_uart2", "sclk_uart2_peric",
+                       ENABLE_SCLK_PERIC, 2, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_UART1, "sclk_uart1", "sclk_uart1_peric",
+                       ENABLE_SCLK_PERIC, 1, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_UART0, "sclk_uart0", "sclk_uart0_peric",
+                       ENABLE_SCLK_PERIC, 0, CLK_SET_RATE_PARENT, 0),
+};
+
+static struct samsung_cmu_info peric_cmu_info __initdata = {
+       .div_clks               = peric_div_clks,
+       .nr_div_clks            = ARRAY_SIZE(peric_div_clks),
+       .gate_clks              = peric_gate_clks,
+       .nr_gate_clks           = ARRAY_SIZE(peric_gate_clks),
+       .nr_clk_ids             = PERIC_NR_CLK,
+       .clk_regs               = peric_clk_regs,
+       .nr_clk_regs            = ARRAY_SIZE(peric_clk_regs),
+};
+
+static void __init exynos5433_cmu_peric_init(struct device_node *np)
+{
+       samsung_cmu_register_one(np, &peric_cmu_info);
+}
+
+CLK_OF_DECLARE(exynos5433_cmu_peric, "samsung,exynos5433-cmu-peric",
+               exynos5433_cmu_peric_init);
+
+/*
+ * Register offset definitions for CMU_PERIS
+ */
+#define ENABLE_ACLK_PERIS                              0x0800
+#define ENABLE_PCLK_PERIS                              0x0900
+#define ENABLE_PCLK_PERIS_SECURE_TZPC                  0x0904
+#define ENABLE_PCLK_PERIS_SECURE_SECKEY_APBIF          0x0908
+#define ENABLE_PCLK_PERIS_SECURE_CHIPID_APBIF          0x090c
+#define ENABLE_PCLK_PERIS_SECURE_TOPRTC                        0x0910
+#define ENABLE_PCLK_PERIS_SECURE_CUSTOM_EFUSE_APBIF    0x0914
+#define ENABLE_PCLK_PERIS_SECURE_ANTIRBK_CNT_APBIF     0x0918
+#define ENABLE_PCLK_PERIS_SECURE_OTP_CON_APBIF         0x091c
+#define ENABLE_SCLK_PERIS                              0x0a00
+#define ENABLE_SCLK_PERIS_SECURE_SECKEY                        0x0a04
+#define ENABLE_SCLK_PERIS_SECURE_CHIPID                        0x0a08
+#define ENABLE_SCLK_PERIS_SECURE_TOPRTC                        0x0a0c
+#define ENABLE_SCLK_PERIS_SECURE_CUSTOM_EFUSE          0x0a10
+#define ENABLE_SCLK_PERIS_SECURE_ANTIRBK_CNT           0x0a14
+#define ENABLE_SCLK_PERIS_SECURE_OTP_CON               0x0a18
+#define ENABLE_IP_PERIS0                               0x0b00
+#define ENABLE_IP_PERIS1                               0x0b04
+#define ENABLE_IP_PERIS_SECURE_TZPC                    0x0b08
+#define ENABLE_IP_PERIS_SECURE_SECKEY                  0x0b0c
+#define ENABLE_IP_PERIS_SECURE_CHIPID                  0x0b10
+#define ENABLE_IP_PERIS_SECURE_TOPRTC                  0x0b14
+#define ENABLE_IP_PERIS_SECURE_CUSTOM_EFUSE            0x0b18
+#define ENABLE_IP_PERIS_SECURE_ANTIBRK_CNT             0x0b1c
+#define ENABLE_IP_PERIS_SECURE_OTP_CON                 0x0b20
+
+static unsigned long peris_clk_regs[] __initdata = {
+       ENABLE_ACLK_PERIS,
+       ENABLE_PCLK_PERIS,
+       ENABLE_PCLK_PERIS_SECURE_TZPC,
+       ENABLE_PCLK_PERIS_SECURE_SECKEY_APBIF,
+       ENABLE_PCLK_PERIS_SECURE_CHIPID_APBIF,
+       ENABLE_PCLK_PERIS_SECURE_TOPRTC,
+       ENABLE_PCLK_PERIS_SECURE_CUSTOM_EFUSE_APBIF,
+       ENABLE_PCLK_PERIS_SECURE_ANTIRBK_CNT_APBIF,
+       ENABLE_PCLK_PERIS_SECURE_OTP_CON_APBIF,
+       ENABLE_SCLK_PERIS,
+       ENABLE_SCLK_PERIS_SECURE_SECKEY,
+       ENABLE_SCLK_PERIS_SECURE_CHIPID,
+       ENABLE_SCLK_PERIS_SECURE_TOPRTC,
+       ENABLE_SCLK_PERIS_SECURE_CUSTOM_EFUSE,
+       ENABLE_SCLK_PERIS_SECURE_ANTIRBK_CNT,
+       ENABLE_SCLK_PERIS_SECURE_OTP_CON,
+       ENABLE_IP_PERIS0,
+       ENABLE_IP_PERIS1,
+       ENABLE_IP_PERIS_SECURE_TZPC,
+       ENABLE_IP_PERIS_SECURE_SECKEY,
+       ENABLE_IP_PERIS_SECURE_CHIPID,
+       ENABLE_IP_PERIS_SECURE_TOPRTC,
+       ENABLE_IP_PERIS_SECURE_CUSTOM_EFUSE,
+       ENABLE_IP_PERIS_SECURE_ANTIBRK_CNT,
+       ENABLE_IP_PERIS_SECURE_OTP_CON,
+};
+
+static struct samsung_gate_clock peris_gate_clks[] __initdata = {
+       /* ENABLE_ACLK_PERIS */
+       GATE(CLK_ACLK_AHB2APB_PERIS1P, "aclk_ahb2apb_peris1p", "aclk_peris_66",
+                       ENABLE_ACLK_PERIS, 2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AHB2APB_PERIS0P, "aclk_ahb2apb_peris0p", "aclk_peris_66",
+                       ENABLE_ACLK_PERIS, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_PERISNP_66, "aclk_perisnp_66", "aclk_peris_66",
+                       ENABLE_ACLK_PERIS, 0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_PCLK_PERIS */
+       GATE(CLK_PCLK_HPM_APBIF, "pclk_hpm_apbif", "aclk_peris_66",
+                       ENABLE_PCLK_PERIS, 30, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_TMU1_APBIF, "pclk_tmu1_apbif", "aclk_peris_66",
+                       ENABLE_PCLK_PERIS, 24, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_TMU0_APBIF, "pclk_tmu0_apbif", "aclk_peris_66",
+                       ENABLE_PCLK_PERIS, 23, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_PMU_PERIS, "pclk_pmu_peris", "aclk_peris_66",
+                       ENABLE_PCLK_PERIS, 22, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SYSREG_PERIS, "pclk_sysreg_peris", "aclk_peris_66",
+                       ENABLE_PCLK_PERIS, 21, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_CMU_TOP_APBIF, "pclk_cmu_top_apbif", "aclk_peris_66",
+                       ENABLE_PCLK_PERIS, 20, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_WDT_APOLLO, "pclk_wdt_apollo", "aclk_peris_66",
+                       ENABLE_PCLK_PERIS, 17, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_WDT_ATLAS, "pclk_wdt_atlas", "aclk_peris_66",
+                       ENABLE_PCLK_PERIS, 16, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_MCT, "pclk_mct", "aclk_peris_66",
+                       ENABLE_PCLK_PERIS, 15, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_HDMI_CEC, "pclk_hdmi_cec", "aclk_peris_66",
+                       ENABLE_PCLK_PERIS, 14, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_PCLK_PERIS_SECURE_TZPC */
+       GATE(CLK_PCLK_TZPC12, "pclk_tzpc12", "aclk_peris_66",
+                       ENABLE_PCLK_PERIS_SECURE_TZPC, 12, 0, 0),
+       GATE(CLK_PCLK_TZPC11, "pclk_tzpc11", "aclk_peris_66",
+                       ENABLE_PCLK_PERIS_SECURE_TZPC, 11, 0, 0),
+       GATE(CLK_PCLK_TZPC10, "pclk_tzpc10", "aclk_peris_66",
+                       ENABLE_PCLK_PERIS_SECURE_TZPC, 10, 0, 0),
+       GATE(CLK_PCLK_TZPC9, "pclk_tzpc9", "aclk_peris_66",
+                       ENABLE_PCLK_PERIS_SECURE_TZPC, 9, 0, 0),
+       GATE(CLK_PCLK_TZPC8, "pclk_tzpc8", "aclk_peris_66",
+                       ENABLE_PCLK_PERIS_SECURE_TZPC, 8, 0, 0),
+       GATE(CLK_PCLK_TZPC7, "pclk_tzpc7", "aclk_peris_66",
+                       ENABLE_PCLK_PERIS_SECURE_TZPC, 7, 0, 0),
+       GATE(CLK_PCLK_TZPC6, "pclk_tzpc6", "aclk_peris_66",
+                       ENABLE_PCLK_PERIS_SECURE_TZPC, 6, 0, 0),
+       GATE(CLK_PCLK_TZPC5, "pclk_tzpc5", "aclk_peris_66",
+                       ENABLE_PCLK_PERIS_SECURE_TZPC, 5, 0, 0),
+       GATE(CLK_PCLK_TZPC4, "pclk_tzpc4", "aclk_peris_66",
+                       ENABLE_PCLK_PERIS_SECURE_TZPC, 4, 0, 0),
+       GATE(CLK_PCLK_TZPC3, "pclk_tzpc3", "aclk_peris_66",
+                       ENABLE_PCLK_PERIS_SECURE_TZPC, 3, 0, 0),
+       GATE(CLK_PCLK_TZPC2, "pclk_tzpc2", "aclk_peris_66",
+                       ENABLE_PCLK_PERIS_SECURE_TZPC, 2, 0, 0),
+       GATE(CLK_PCLK_TZPC1, "pclk_tzpc1", "aclk_peris_66",
+                       ENABLE_PCLK_PERIS_SECURE_TZPC, 1, 0, 0),
+       GATE(CLK_PCLK_TZPC0, "pclk_tzpc0", "aclk_peris_66",
+                       ENABLE_PCLK_PERIS_SECURE_TZPC, 0, 0, 0),
+
+       /* ENABLE_PCLK_PERIS_SECURE_SECKEY_APBIF */
+       GATE(CLK_PCLK_SECKEY_APBIF, "pclk_seckey_apbif", "aclk_peris_66",
+                       ENABLE_PCLK_PERIS_SECURE_SECKEY_APBIF, 0, 0, 0),
+
+       /* ENABLE_PCLK_PERIS_SECURE_CHIPID_APBIF */
+       GATE(CLK_PCLK_CHIPID_APBIF, "pclk_chipid_apbif", "aclk_peris_66",
+                       ENABLE_PCLK_PERIS_SECURE_CHIPID_APBIF, 0, 0, 0),
+
+       /* ENABLE_PCLK_PERIS_SECURE_TOPRTC */
+       GATE(CLK_PCLK_TOPRTC, "pclk_toprtc", "aclk_peris_66",
+                       ENABLE_PCLK_PERIS_SECURE_TOPRTC, 0, 0, 0),
+
+       /* ENABLE_PCLK_PERIS_SECURE_CUSTOM_EFUSE_APBIF */
+       GATE(CLK_PCLK_CUSTOM_EFUSE_APBIF, "pclk_custom_efuse_apbif",
+                       "aclk_peris_66",
+                       ENABLE_PCLK_PERIS_SECURE_CUSTOM_EFUSE_APBIF, 0, 0, 0),
+
+       /* ENABLE_PCLK_PERIS_SECURE_ANTIRBK_CNT_APBIF */
+       GATE(CLK_PCLK_ANTIRBK_CNT_APBIF, "pclk_antirbk_cnt_apbif",
+                       "aclk_peris_66",
+                       ENABLE_PCLK_PERIS_SECURE_ANTIRBK_CNT_APBIF, 0, 0, 0),
+
+       /* ENABLE_PCLK_PERIS_SECURE_OTP_CON_APBIF */
+       GATE(CLK_PCLK_OTP_CON_APBIF, "pclk_otp_con_apbif",
+                       "aclk_peris_66",
+                       ENABLE_PCLK_PERIS_SECURE_OTP_CON_APBIF, 0, 0, 0),
+
+       /* ENABLE_SCLK_PERIS */
+       GATE(CLK_SCLK_ASV_TB, "sclk_asv_tb", "oscclk_efuse_common",
+                       ENABLE_SCLK_PERIS, 10, 0, 0),
+       GATE(CLK_SCLK_TMU1, "sclk_tmu1", "oscclk_efuse_common",
+                       ENABLE_SCLK_PERIS, 4, 0, 0),
+       GATE(CLK_SCLK_TMU0, "sclk_tmu0", "oscclk_efuse_common",
+                       ENABLE_SCLK_PERIS, 3, 0, 0),
+
+       /* ENABLE_SCLK_PERIS_SECURE_SECKEY */
+       GATE(CLK_SCLK_SECKEY, "sclk_seckey", "oscclk_efuse_common",
+                       ENABLE_SCLK_PERIS_SECURE_SECKEY, 0, 0, 0),
+
+       /* ENABLE_SCLK_PERIS_SECURE_CHIPID */
+       GATE(CLK_SCLK_CHIPID, "sclk_chipid", "oscclk_efuse_common",
+                       ENABLE_SCLK_PERIS_SECURE_CHIPID, 0, 0, 0),
+
+       /* ENABLE_SCLK_PERIS_SECURE_TOPRTC */
+       GATE(CLK_SCLK_TOPRTC, "sclk_toprtc", "oscclk_efuse_common",
+                       ENABLE_SCLK_PERIS_SECURE_TOPRTC, 0, 0, 0),
+
+       /* ENABLE_SCLK_PERIS_SECURE_CUSTOM_EFUSE */
+       GATE(CLK_SCLK_CUSTOM_EFUSE, "sclk_custom_efuse", "oscclk_efuse_common",
+                       ENABLE_SCLK_PERIS_SECURE_CUSTOM_EFUSE, 0, 0, 0),
+
+       /* ENABLE_SCLK_PERIS_SECURE_ANTIRBK_CNT */
+       GATE(CLK_SCLK_ANTIRBK_CNT, "sclk_antirbk_cnt", "oscclk_efuse_common",
+                       ENABLE_SCLK_PERIS_SECURE_ANTIRBK_CNT, 0, 0, 0),
+
+       /* ENABLE_SCLK_PERIS_SECURE_OTP_CON */
+       GATE(CLK_SCLK_OTP_CON, "sclk_otp_con", "oscclk_efuse_common",
+                       ENABLE_SCLK_PERIS_SECURE_OTP_CON, 0, 0, 0),
+};
+
+static struct samsung_cmu_info peris_cmu_info __initdata = {
+       .gate_clks              = peris_gate_clks,
+       .nr_gate_clks           = ARRAY_SIZE(peris_gate_clks),
+       .nr_clk_ids             = PERIS_NR_CLK,
+       .clk_regs               = peris_clk_regs,
+       .nr_clk_regs            = ARRAY_SIZE(peris_clk_regs),
+};
+
+static void __init exynos5433_cmu_peris_init(struct device_node *np)
+{
+       samsung_cmu_register_one(np, &peris_cmu_info);
+}
+
+CLK_OF_DECLARE(exynos5433_cmu_peris, "samsung,exynos5433-cmu-peris",
+               exynos5433_cmu_peris_init);
+
+/*
+ * Register offset definitions for CMU_FSYS
+ */
+#define MUX_SEL_FSYS0                  0x0200
+#define MUX_SEL_FSYS1                  0x0204
+#define MUX_SEL_FSYS2                  0x0208
+#define MUX_SEL_FSYS3                  0x020c
+#define MUX_SEL_FSYS4                  0x0210
+#define MUX_ENABLE_FSYS0               0x0300
+#define MUX_ENABLE_FSYS1               0x0304
+#define MUX_ENABLE_FSYS2               0x0308
+#define MUX_ENABLE_FSYS3               0x030c
+#define MUX_ENABLE_FSYS4               0x0310
+#define MUX_STAT_FSYS0                 0x0400
+#define MUX_STAT_FSYS1                 0x0404
+#define MUX_STAT_FSYS2                 0x0408
+#define MUX_STAT_FSYS3                 0x040c
+#define MUX_STAT_FSYS4                 0x0410
+#define MUX_IGNORE_FSYS2               0x0508
+#define MUX_IGNORE_FSYS3               0x050c
+#define ENABLE_ACLK_FSYS0              0x0800
+#define ENABLE_ACLK_FSYS1              0x0804
+#define ENABLE_PCLK_FSYS               0x0900
+#define ENABLE_SCLK_FSYS               0x0a00
+#define ENABLE_IP_FSYS0                        0x0b00
+#define ENABLE_IP_FSYS1                        0x0b04
+
+/* list of all parent clock list */
+PNAME(mout_sclk_ufs_mphy_user_p)       = { "oscclk", "sclk_ufs_mphy", };
+PNAME(mout_aclk_fsys_200_user_p)       = { "oscclk", "div_aclk_fsys_200", };
+PNAME(mout_sclk_pcie_100_user_p)       = { "oscclk", "sclk_pcie_100_fsys",};
+PNAME(mout_sclk_ufsunipro_user_p)      = { "oscclk", "sclk_ufsunipro_fsys",};
+PNAME(mout_sclk_mmc2_user_p)           = { "oscclk", "sclk_mmc2_fsys", };
+PNAME(mout_sclk_mmc1_user_p)           = { "oscclk", "sclk_mmc1_fsys", };
+PNAME(mout_sclk_mmc0_user_p)           = { "oscclk", "sclk_mmc0_fsys", };
+PNAME(mout_sclk_usbhost30_user_p)      = { "oscclk", "sclk_usbhost30_fsys",};
+PNAME(mout_sclk_usbdrd30_user_p)       = { "oscclk", "sclk_usbdrd30_fsys", };
+
+PNAME(mout_phyclk_usbhost30_uhost30_pipe_pclk_user_p)
+               = { "oscclk", "phyclk_usbhost30_uhost30_pipe_pclk_phy", };
+PNAME(mout_phyclk_usbhost30_uhost30_phyclock_user_p)
+               = { "oscclk", "phyclk_usbhost30_uhost30_phyclock_phy", };
+PNAME(mout_phyclk_usbhost20_phy_hsic1_p)
+               = { "oscclk", "phyclk_usbhost20_phy_hsic1_phy", };
+PNAME(mout_phyclk_usbhost20_phy_clk48mohci_user_p)
+               = { "oscclk", "phyclk_usbhost20_phy_clk48mohci_phy", };
+PNAME(mout_phyclk_usbhost20_phy_phyclock_user_p)
+               = { "oscclk", "phyclk_usbhost20_phy_phyclock_phy", };
+PNAME(mout_phyclk_usbhost20_phy_freeclk_user_p)
+               = { "oscclk", "phyclk_usbhost20_phy_freeclk_phy", };
+PNAME(mout_phyclk_usbdrd30_udrd30_pipe_pclk_p)
+               = { "oscclk", "phyclk_usbdrd30_udrd30_pipe_pclk_phy", };
+PNAME(mout_phyclk_usbdrd30_udrd30_phyclock_user_p)
+               = { "oscclk", "phyclk_usbdrd30_udrd30_phyclock_phy", };
+PNAME(mout_phyclk_ufs_rx1_symbol_user_p)
+               = { "oscclk", "phyclk_ufs_rx1_symbol_phy", };
+PNAME(mout_phyclk_ufs_rx0_symbol_user_p)
+               = { "oscclk", "phyclk_ufs_rx0_symbol_phy", };
+PNAME(mout_phyclk_ufs_tx1_symbol_user_p)
+               = { "oscclk", "phyclk_ufs_tx1_symbol_phy", };
+PNAME(mout_phyclk_ufs_tx0_symbol_user_p)
+               = { "oscclk", "phyclk_ufs_tx0_symbol_phy", };
+PNAME(mout_phyclk_lli_mphy_to_ufs_user_p)
+               = { "oscclk", "phyclk_lli_mphy_to_ufs_phy", };
+PNAME(mout_sclk_mphy_p)
+               = { "mout_sclk_ufs_mphy_user",
+                           "mout_phyclk_lli_mphy_to_ufs_user", };
+
+static unsigned long fsys_clk_regs[] __initdata = {
+       MUX_SEL_FSYS0,
+       MUX_SEL_FSYS1,
+       MUX_SEL_FSYS2,
+       MUX_SEL_FSYS3,
+       MUX_SEL_FSYS4,
+       MUX_ENABLE_FSYS0,
+       MUX_ENABLE_FSYS1,
+       MUX_ENABLE_FSYS2,
+       MUX_ENABLE_FSYS3,
+       MUX_ENABLE_FSYS4,
+       MUX_STAT_FSYS0,
+       MUX_STAT_FSYS1,
+       MUX_STAT_FSYS2,
+       MUX_STAT_FSYS3,
+       MUX_STAT_FSYS4,
+       MUX_IGNORE_FSYS2,
+       MUX_IGNORE_FSYS3,
+       ENABLE_ACLK_FSYS0,
+       ENABLE_ACLK_FSYS1,
+       ENABLE_PCLK_FSYS,
+       ENABLE_SCLK_FSYS,
+       ENABLE_IP_FSYS0,
+       ENABLE_IP_FSYS1,
+};
+
+static struct samsung_fixed_rate_clock fsys_fixed_clks[] __initdata = {
+       /* PHY clocks from USBDRD30_PHY */
+       FRATE(CLK_PHYCLK_USBDRD30_UDRD30_PHYCLOCK_PHY,
+                       "phyclk_usbdrd30_udrd30_phyclock_phy", NULL,
+                       CLK_IS_ROOT, 60000000),
+       FRATE(CLK_PHYCLK_USBDRD30_UDRD30_PIPE_PCLK_PHY,
+                       "phyclk_usbdrd30_udrd30_pipe_pclk_phy", NULL,
+                       CLK_IS_ROOT, 125000000),
+       /* PHY clocks from USBHOST30_PHY */
+       FRATE(CLK_PHYCLK_USBHOST30_UHOST30_PHYCLOCK_PHY,
+                       "phyclk_usbhost30_uhost30_phyclock_phy", NULL,
+                       CLK_IS_ROOT, 60000000),
+       FRATE(CLK_PHYCLK_USBHOST30_UHOST30_PIPE_PCLK_PHY,
+                       "phyclk_usbhost30_uhost30_pipe_pclk_phy", NULL,
+                       CLK_IS_ROOT, 125000000),
+       /* PHY clocks from USBHOST20_PHY */
+       FRATE(CLK_PHYCLK_USBHOST20_PHY_FREECLK_PHY,
+                       "phyclk_usbhost20_phy_freeclk_phy", NULL, CLK_IS_ROOT,
+                       60000000),
+       FRATE(CLK_PHYCLK_USBHOST20_PHY_PHYCLOCK_PHY,
+                       "phyclk_usbhost20_phy_phyclock_phy", NULL, CLK_IS_ROOT,
+                       60000000),
+       FRATE(CLK_PHYCLK_USBHOST20_PHY_CLK48MOHCI_PHY,
+                       "phyclk_usbhost20_phy_clk48mohci_phy", NULL,
+                       CLK_IS_ROOT, 48000000),
+       FRATE(CLK_PHYCLK_USBHOST20_PHY_HSIC1_PHY,
+                       "phyclk_usbhost20_phy_hsic1_phy", NULL, CLK_IS_ROOT,
+                       60000000),
+       /* PHY clocks from UFS_PHY */
+       FRATE(CLK_PHYCLK_UFS_TX0_SYMBOL_PHY, "phyclk_ufs_tx0_symbol_phy",
+                       NULL, CLK_IS_ROOT, 300000000),
+       FRATE(CLK_PHYCLK_UFS_RX0_SYMBOL_PHY, "phyclk_ufs_rx0_symbol_phy",
+                       NULL, CLK_IS_ROOT, 300000000),
+       FRATE(CLK_PHYCLK_UFS_TX1_SYMBOL_PHY, "phyclk_ufs_tx1_symbol_phy",
+                       NULL, CLK_IS_ROOT, 300000000),
+       FRATE(CLK_PHYCLK_UFS_RX1_SYMBOL_PHY, "phyclk_ufs_rx1_symbol_phy",
+                       NULL, CLK_IS_ROOT, 300000000),
+       /* PHY clocks from LLI_PHY */
+       FRATE(CLK_PHYCLK_LLI_MPHY_TO_UFS_PHY, "phyclk_lli_mphy_to_ufs_phy",
+                       NULL, CLK_IS_ROOT, 26000000),
+};
+
+static struct samsung_mux_clock fsys_mux_clks[] __initdata = {
+       /* MUX_SEL_FSYS0 */
+       MUX(CLK_MOUT_SCLK_UFS_MPHY_USER, "mout_sclk_ufs_mphy_user",
+                       mout_sclk_ufs_mphy_user_p, MUX_SEL_FSYS0, 4, 1),
+       MUX(CLK_MOUT_ACLK_FSYS_200_USER, "mout_aclk_fsys_200_user",
+                       mout_aclk_fsys_200_user_p, MUX_SEL_FSYS0, 0, 1),
+
+       /* MUX_SEL_FSYS1 */
+       MUX(CLK_MOUT_SCLK_PCIE_100_USER, "mout_sclk_pcie_100_user",
+                       mout_sclk_pcie_100_user_p, MUX_SEL_FSYS1, 28, 1),
+       MUX(CLK_MOUT_SCLK_UFSUNIPRO_USER, "mout_sclk_ufsunipro_user",
+                       mout_sclk_ufsunipro_user_p, MUX_SEL_FSYS1, 24, 1),
+       MUX(CLK_MOUT_SCLK_MMC2_USER, "mout_sclk_mmc2_user",
+                       mout_sclk_mmc2_user_p, MUX_SEL_FSYS1, 20, 1),
+       MUX(CLK_MOUT_SCLK_MMC1_USER, "mout_sclk_mmc1_user",
+                       mout_sclk_mmc1_user_p, MUX_SEL_FSYS1, 16, 1),
+       MUX(CLK_MOUT_SCLK_MMC0_USER, "mout_sclk_mmc0_user",
+                       mout_sclk_mmc0_user_p, MUX_SEL_FSYS1, 12, 1),
+       MUX(CLK_MOUT_SCLK_USBHOST30_USER, "mout_sclk_usbhost30_user",
+                       mout_sclk_usbhost30_user_p, MUX_SEL_FSYS1, 4, 1),
+       MUX(CLK_MOUT_SCLK_USBDRD30_USER, "mout_sclk_usbdrd30_user",
+                       mout_sclk_usbdrd30_user_p, MUX_SEL_FSYS1, 0, 1),
+
+       /* MUX_SEL_FSYS2 */
+       MUX(CLK_MOUT_PHYCLK_USBHOST30_UHOST30_PIPE_PCLK_USER,
+                       "mout_phyclk_usbhost30_uhost30_pipe_pclk_user",
+                       mout_phyclk_usbhost30_uhost30_pipe_pclk_user_p,
+                       MUX_SEL_FSYS2, 28, 1),
+       MUX(CLK_MOUT_PHYCLK_USBHOST30_UHOST30_PHYCLOCK_USER,
+                       "mout_phyclk_usbhost30_uhost30_phyclock_user",
+                       mout_phyclk_usbhost30_uhost30_phyclock_user_p,
+                       MUX_SEL_FSYS2, 24, 1),
+       MUX(CLK_MOUT_PHYCLK_USBHOST20_PHY_HSIC1_USER,
+                       "mout_phyclk_usbhost20_phy_hsic1",
+                       mout_phyclk_usbhost20_phy_hsic1_p,
+                       MUX_SEL_FSYS2, 20, 1),
+       MUX(CLK_MOUT_PHYCLK_USBHOST20_PHY_CLK48MOHCI_USER,
+                       "mout_phyclk_usbhost20_phy_clk48mohci_user",
+                       mout_phyclk_usbhost20_phy_clk48mohci_user_p,
+                       MUX_SEL_FSYS2, 16, 1),
+       MUX(CLK_MOUT_PHYCLK_USBHOST20_PHY_PHYCLOCK_USER,
+                       "mout_phyclk_usbhost20_phy_phyclock_user",
+                       mout_phyclk_usbhost20_phy_phyclock_user_p,
+                       MUX_SEL_FSYS2, 12, 1),
+       MUX(CLK_MOUT_PHYCLK_USBHOST20_PHY_PHY_FREECLK_USER,
+                       "mout_phyclk_usbhost20_phy_freeclk_user",
+                       mout_phyclk_usbhost20_phy_freeclk_user_p,
+                       MUX_SEL_FSYS2, 8, 1),
+       MUX(CLK_MOUT_PHYCLK_USBDRD30_UDRD30_PIPE_PCLK_USER,
+                       "mout_phyclk_usbdrd30_udrd30_pipe_pclk_user",
+                       mout_phyclk_usbdrd30_udrd30_pipe_pclk_p,
+                       MUX_SEL_FSYS2, 4, 1),
+       MUX(CLK_MOUT_PHYCLK_USBDRD30_UDRD30_PHYCLOCK_USER,
+                       "mout_phyclk_usbdrd30_udrd30_phyclock_user",
+                       mout_phyclk_usbdrd30_udrd30_phyclock_user_p,
+                       MUX_SEL_FSYS2, 0, 1),
+
+       /* MUX_SEL_FSYS3 */
+       MUX(CLK_MOUT_PHYCLK_UFS_RX1_SYMBOL_USER,
+                       "mout_phyclk_ufs_rx1_symbol_user",
+                       mout_phyclk_ufs_rx1_symbol_user_p,
+                       MUX_SEL_FSYS3, 16, 1),
+       MUX(CLK_MOUT_PHYCLK_UFS_RX0_SYMBOL_USER,
+                       "mout_phyclk_ufs_rx0_symbol_user",
+                       mout_phyclk_ufs_rx0_symbol_user_p,
+                       MUX_SEL_FSYS3, 12, 1),
+       MUX(CLK_MOUT_PHYCLK_UFS_TX1_SYMBOL_USER,
+                       "mout_phyclk_ufs_tx1_symbol_user",
+                       mout_phyclk_ufs_tx1_symbol_user_p,
+                       MUX_SEL_FSYS3, 8, 1),
+       MUX(CLK_MOUT_PHYCLK_UFS_TX0_SYMBOL_USER,
+                       "mout_phyclk_ufs_tx0_symbol_user",
+                       mout_phyclk_ufs_tx0_symbol_user_p,
+                       MUX_SEL_FSYS3, 4, 1),
+       MUX(CLK_MOUT_PHYCLK_LLI_MPHY_TO_UFS_USER,
+                       "mout_phyclk_lli_mphy_to_ufs_user",
+                       mout_phyclk_lli_mphy_to_ufs_user_p,
+                       MUX_SEL_FSYS3, 0, 1),
+
+       /* MUX_SEL_FSYS4 */
+       MUX(CLK_MOUT_SCLK_MPHY, "mout_sclk_mphy", mout_sclk_mphy_p,
+                       MUX_SEL_FSYS4, 0, 1),
+};
+
+static struct samsung_gate_clock fsys_gate_clks[] __initdata = {
+       /* ENABLE_ACLK_FSYS0 */
+       GATE(CLK_ACLK_PCIE, "aclk_pcie", "mout_aclk_fsys_200_user",
+                       ENABLE_ACLK_FSYS0, 13, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_PDMA1, "aclk_pdma1", "mout_aclk_fsys_200_user",
+                       ENABLE_ACLK_FSYS0, 11, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_TSI, "aclk_tsi", "mout_aclk_fsys_200_user",
+                       ENABLE_ACLK_FSYS0, 10, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_MMC2, "aclk_mmc2", "mout_aclk_fsys_200_user",
+                       ENABLE_ACLK_FSYS0, 8, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_MMC1, "aclk_mmc1", "mout_aclk_fsys_200_user",
+                       ENABLE_ACLK_FSYS0, 7, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_MMC0, "aclk_mmc0", "mout_aclk_fsys_200_user",
+                       ENABLE_ACLK_FSYS0, 6, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_UFS, "aclk_ufs", "mout_aclk_fsys_200_user",
+                       ENABLE_ACLK_FSYS0, 5, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_USBHOST20, "aclk_usbhost20", "mout_aclk_fsys_200_user",
+                       ENABLE_ACLK_FSYS0, 3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_USBHOST30, "aclk_usbhost30", "mout_aclk_fsys_200_user",
+                       ENABLE_ACLK_FSYS0, 2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_USBDRD30, "aclk_usbdrd30", "mout_aclk_fsys_200_user",
+                       ENABLE_ACLK_FSYS0, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_PDMA0, "aclk_pdma0", "mout_aclk_fsys_200_user",
+                       ENABLE_ACLK_FSYS0, 0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_ACLK_FSYS1 */
+       GATE(CLK_ACLK_XIU_FSYSPX, "aclk_xiu_fsyspx", "mout_aclk_fsys_200_user",
+                       ENABLE_ACLK_FSYS1, 27, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AHB_USBLINKH1, "aclk_ahb_usblinkh1",
+                       "mout_aclk_fsys_200_user", ENABLE_ACLK_FSYS1,
+                       26, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_SMMU_PDMA1, "aclk_smmu_pdma1", "mout_aclk_fsys_200_user",
+                       ENABLE_ACLK_FSYS1, 25, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_BTS_PCIE, "aclk_bts_pcie", "mout_aclk_fsys_200_user",
+                       ENABLE_ACLK_FSYS1, 24, 0, 0),
+       GATE(CLK_ACLK_AXIUS_PDMA1, "aclk_axius_pdma1",
+                       "mout_aclk_fsys_200_user", ENABLE_ACLK_FSYS1,
+                       22, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_SMMU_PDMA0, "aclk_smmu_pdma0", "mout_aclk_fsys_200_user",
+                       ENABLE_ACLK_FSYS1, 17, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_BTS_UFS, "aclk_bts_ufs", "mout_aclk_fsys_200_user",
+                       ENABLE_ACLK_FSYS1, 14, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_BTS_USBHOST30, "aclk_bts_usbhost30",
+                       "mout_aclk_fsys_200_user", ENABLE_ACLK_FSYS1,
+                       13, 0, 0),
+       GATE(CLK_ACLK_BTS_USBDRD30, "aclk_bts_usbdrd30",
+                       "mout_aclk_fsys_200_user", ENABLE_ACLK_FSYS1,
+                       12, 0, 0),
+       GATE(CLK_ACLK_AXIUS_PDMA0, "aclk_axius_pdma0",
+                       "mout_aclk_fsys_200_user", ENABLE_ACLK_FSYS1,
+                       11, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AXIUS_USBHS, "aclk_axius_usbhs",
+                       "mout_aclk_fsys_200_user", ENABLE_ACLK_FSYS1,
+                       10, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AXIUS_FSYSSX, "aclk_axius_fsyssx",
+                       "mout_aclk_fsys_200_user", ENABLE_ACLK_FSYS1,
+                       9, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AHB2APB_FSYSP, "aclk_ahb2apb_fsysp",
+                       "mout_aclk_fsys_200_user", ENABLE_ACLK_FSYS1,
+                       8, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AHB2AXI_USBHS, "aclk_ahb2axi_usbhs",
+                       "mout_aclk_fsys_200_user", ENABLE_ACLK_FSYS1,
+                       7, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AHB_USBLINKH0, "aclk_ahb_usblinkh0",
+                       "mout_aclk_fsys_200_user", ENABLE_ACLK_FSYS1,
+                       6, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AHB_USBHS, "aclk_ahb_usbhs", "mout_aclk_fsys_200_user",
+                       ENABLE_ACLK_FSYS1, 5, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AHB_FSYSH, "aclk_ahb_fsysh", "mout_aclk_fsys_200_user",
+                       ENABLE_ACLK_FSYS1, 4, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_XIU_FSYSX, "aclk_xiu_fsysx", "mout_aclk_fsys_200_user",
+                       ENABLE_ACLK_FSYS1, 3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_XIU_FSYSSX, "aclk_xiu_fsyssx", "mout_aclk_fsys_200_user",
+                       ENABLE_ACLK_FSYS1, 2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_FSYSNP_200, "aclk_fsysnp_200", "mout_aclk_fsys_200_user",
+                       ENABLE_ACLK_FSYS1, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_FSYSND_200, "aclk_fsysnd_200", "mout_aclk_fsys_200_user",
+                       ENABLE_ACLK_FSYS1, 0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_PCLK_FSYS */
+       GATE(CLK_PCLK_PCIE_CTRL, "pclk_pcie_ctrl", "mout_aclk_fsys_200_user",
+                       ENABLE_PCLK_FSYS, 17, 0, 0),
+       GATE(CLK_PCLK_SMMU_PDMA1, "pclk_smmu_pdma1", "mout_aclk_fsys_200_user",
+                       ENABLE_PCLK_FSYS, 16, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_PCIE_PHY, "pclk_pcie_phy", "mout_aclk_fsys_200_user",
+                       ENABLE_PCLK_FSYS, 14, 0, 0),
+       GATE(CLK_PCLK_BTS_PCIE, "pclk_bts_pcie", "mout_aclk_fsys_200_user",
+                       ENABLE_PCLK_FSYS, 13, 0, 0),
+       GATE(CLK_PCLK_SMMU_PDMA0, "pclk_smmu_pdma0", "mout_aclk_fsys_200_user",
+                       ENABLE_PCLK_FSYS, 8, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_BTS_UFS, "pclk_bts_ufs", "mout_aclk_fsys_200_user",
+                       ENABLE_PCLK_FSYS, 5, 0, 0),
+       GATE(CLK_PCLK_BTS_USBHOST30, "pclk_bts_usbhost30",
+                       "mout_aclk_fsys_200_user", ENABLE_PCLK_FSYS, 4, 0, 0),
+       GATE(CLK_PCLK_BTS_USBDRD30, "pclk_bts_usbdrd30",
+                       "mout_aclk_fsys_200_user", ENABLE_PCLK_FSYS, 3, 0, 0),
+       GATE(CLK_PCLK_GPIO_FSYS, "pclk_gpio_fsys", "mout_aclk_fsys_200_user",
+                       ENABLE_PCLK_FSYS, 2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_PMU_FSYS, "pclk_pmu_fsys", "mout_aclk_fsys_200_user",
+                       ENABLE_PCLK_FSYS, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SYSREG_FSYS, "pclk_sysreg_fsys",
+                       "mout_aclk_fsys_200_user", ENABLE_PCLK_FSYS,
+                       0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_SCLK_FSYS */
+       GATE(CLK_SCLK_PCIE_100, "sclk_pcie_100", "mout_sclk_pcie_100_user",
+                       ENABLE_SCLK_FSYS, 21, 0, 0),
+       GATE(CLK_PHYCLK_USBHOST30_UHOST30_PIPE_PCLK,
+                       "phyclk_usbhost30_uhost30_pipe_pclk",
+                       "mout_phyclk_usbhost30_uhost30_pipe_pclk_user",
+                       ENABLE_SCLK_FSYS, 18, 0, 0),
+       GATE(CLK_PHYCLK_USBHOST30_UHOST30_PHYCLOCK,
+                       "phyclk_usbhost30_uhost30_phyclock",
+                       "mout_phyclk_usbhost30_uhost30_phyclock_user",
+                       ENABLE_SCLK_FSYS, 17, 0, 0),
+       GATE(CLK_PHYCLK_UFS_RX1_SYMBOL, "phyclk_ufs_rx1_symbol",
+                       "mout_phyclk_ufs_rx1_symbol_user", ENABLE_SCLK_FSYS,
+                       16, 0, 0),
+       GATE(CLK_PHYCLK_UFS_RX0_SYMBOL, "phyclk_ufs_rx0_symbol",
+                       "mout_phyclk_ufs_rx0_symbol_user", ENABLE_SCLK_FSYS,
+                       15, 0, 0),
+       GATE(CLK_PHYCLK_UFS_TX1_SYMBOL, "phyclk_ufs_tx1_symbol",
+                       "mout_phyclk_ufs_tx1_symbol_user", ENABLE_SCLK_FSYS,
+                       14, 0, 0),
+       GATE(CLK_PHYCLK_UFS_TX0_SYMBOL, "phyclk_ufs_tx0_symbol",
+                       "mout_phyclk_ufs_tx0_symbol_user", ENABLE_SCLK_FSYS,
+                       13, 0, 0),
+       GATE(CLK_PHYCLK_USBHOST20_PHY_HSIC1, "phyclk_usbhost20_phy_hsic1",
+                       "mout_phyclk_usbhost20_phy_hsic1", ENABLE_SCLK_FSYS,
+                       12, 0, 0),
+       GATE(CLK_PHYCLK_USBHOST20_PHY_CLK48MOHCI,
+                       "phyclk_usbhost20_phy_clk48mohci",
+                       "mout_phyclk_usbhost20_phy_clk48mohci_user",
+                       ENABLE_SCLK_FSYS, 11, 0, 0),
+       GATE(CLK_PHYCLK_USBHOST20_PHY_PHYCLOCK,
+                       "phyclk_usbhost20_phy_phyclock",
+                       "mout_phyclk_usbhost20_phy_phyclock_user",
+                       ENABLE_SCLK_FSYS, 10, 0, 0),
+       GATE(CLK_PHYCLK_USBHOST20_PHY_FREECLK,
+                       "phyclk_usbhost20_phy_freeclk",
+                       "mout_phyclk_usbhost20_phy_freeclk_user",
+                       ENABLE_SCLK_FSYS, 9, 0, 0),
+       GATE(CLK_PHYCLK_USBDRD30_UDRD30_PIPE_PCLK,
+                       "phyclk_usbdrd30_udrd30_pipe_pclk",
+                       "mout_phyclk_usbdrd30_udrd30_pipe_pclk_user",
+                       ENABLE_SCLK_FSYS, 8, 0, 0),
+       GATE(CLK_PHYCLK_USBDRD30_UDRD30_PHYCLOCK,
+                       "phyclk_usbdrd30_udrd30_phyclock",
+                       "mout_phyclk_usbdrd30_udrd30_phyclock_user",
+                       ENABLE_SCLK_FSYS, 7, 0, 0),
+       GATE(CLK_SCLK_MPHY, "sclk_mphy", "mout_sclk_mphy",
+                       ENABLE_SCLK_FSYS, 6, 0, 0),
+       GATE(CLK_SCLK_UFSUNIPRO, "sclk_ufsunipro", "mout_sclk_ufsunipro_user",
+                       ENABLE_SCLK_FSYS, 5, 0, 0),
+       GATE(CLK_SCLK_MMC2, "sclk_mmc2", "mout_sclk_mmc2_user",
+                       ENABLE_SCLK_FSYS, 4, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_MMC1, "sclk_mmc1", "mout_sclk_mmc1_user",
+                       ENABLE_SCLK_FSYS, 3, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_MMC0, "sclk_mmc0", "mout_sclk_mmc0_user",
+                       ENABLE_SCLK_FSYS, 2, CLK_SET_RATE_PARENT, 0),
+       GATE(CLK_SCLK_USBHOST30, "sclk_usbhost30", "mout_sclk_usbhost30_user",
+                       ENABLE_SCLK_FSYS, 1, 0, 0),
+       GATE(CLK_SCLK_USBDRD30, "sclk_usbdrd30", "mout_sclk_usbdrd30_user",
+                       ENABLE_SCLK_FSYS, 0, 0, 0),
+
+       /* ENABLE_IP_FSYS0 */
+       GATE(CLK_PDMA1, "pdma1", "aclk_pdma1", ENABLE_IP_FSYS0, 15, 0, 0),
+       GATE(CLK_PDMA0, "pdma0", "aclk_pdma0", ENABLE_IP_FSYS0, 0, 0, 0),
+};
+
+static struct samsung_cmu_info fsys_cmu_info __initdata = {
+       .mux_clks               = fsys_mux_clks,
+       .nr_mux_clks            = ARRAY_SIZE(fsys_mux_clks),
+       .gate_clks              = fsys_gate_clks,
+       .nr_gate_clks           = ARRAY_SIZE(fsys_gate_clks),
+       .fixed_clks             = fsys_fixed_clks,
+       .nr_fixed_clks          = ARRAY_SIZE(fsys_fixed_clks),
+       .nr_clk_ids             = FSYS_NR_CLK,
+       .clk_regs               = fsys_clk_regs,
+       .nr_clk_regs            = ARRAY_SIZE(fsys_clk_regs),
+};
+
+static void __init exynos5433_cmu_fsys_init(struct device_node *np)
+{
+       samsung_cmu_register_one(np, &fsys_cmu_info);
+}
+
+CLK_OF_DECLARE(exynos5433_cmu_fsys, "samsung,exynos5433-cmu-fsys",
+               exynos5433_cmu_fsys_init);
+
+/*
+ * Register offset definitions for CMU_G2D
+ */
+#define MUX_SEL_G2D0                           0x0200
+#define MUX_SEL_ENABLE_G2D0                    0x0300
+#define MUX_SEL_STAT_G2D0                      0x0400
+#define DIV_G2D                                        0x0600
+#define DIV_STAT_G2D                           0x0700
+#define DIV_ENABLE_ACLK_G2D                    0x0800
+#define DIV_ENABLE_ACLK_G2D_SECURE_SMMU_G2D    0x0804
+#define DIV_ENABLE_PCLK_G2D                    0x0900
+#define DIV_ENABLE_PCLK_G2D_SECURE_SMMU_G2D    0x0904
+#define DIV_ENABLE_IP_G2D0                     0x0b00
+#define DIV_ENABLE_IP_G2D1                     0x0b04
+#define DIV_ENABLE_IP_G2D_SECURE_SMMU_G2D      0x0b08
+
+static unsigned long g2d_clk_regs[] __initdata = {
+       MUX_SEL_G2D0,
+       MUX_SEL_ENABLE_G2D0,
+       MUX_SEL_STAT_G2D0,
+       DIV_G2D,
+       DIV_STAT_G2D,
+       DIV_ENABLE_ACLK_G2D,
+       DIV_ENABLE_ACLK_G2D_SECURE_SMMU_G2D,
+       DIV_ENABLE_PCLK_G2D,
+       DIV_ENABLE_PCLK_G2D_SECURE_SMMU_G2D,
+       DIV_ENABLE_IP_G2D0,
+       DIV_ENABLE_IP_G2D1,
+       DIV_ENABLE_IP_G2D_SECURE_SMMU_G2D,
+};
+
+/* list of all parent clock list */
+PNAME(mout_aclk_g2d_266_user_p)                = { "oscclk", "aclk_g2d_266", };
+PNAME(mout_aclk_g2d_400_user_p)                = { "oscclk", "aclk_g2d_400", };
+
+static struct samsung_mux_clock g2d_mux_clks[] __initdata = {
+       /* MUX_SEL_G2D0 */
+       MUX(CLK_MUX_ACLK_G2D_266_USER, "mout_aclk_g2d_266_user",
+                       mout_aclk_g2d_266_user_p, MUX_SEL_G2D0, 4, 1),
+       MUX(CLK_MUX_ACLK_G2D_400_USER, "mout_aclk_g2d_400_user",
+                       mout_aclk_g2d_400_user_p, MUX_SEL_G2D0, 0, 1),
+};
+
+static struct samsung_div_clock g2d_div_clks[] __initdata = {
+       /* DIV_G2D */
+       DIV(CLK_DIV_PCLK_G2D, "div_pclk_g2d", "mout_aclk_g2d_266_user",
+                       DIV_G2D, 0, 2),
+};
+
+static struct samsung_gate_clock g2d_gate_clks[] __initdata = {
+       /* DIV_ENABLE_ACLK_G2D */
+       GATE(CLK_ACLK_SMMU_MDMA1, "aclk_smmu_mdma1", "mout_aclk_g2d_266_user",
+                       DIV_ENABLE_ACLK_G2D, 12, 0, 0),
+       GATE(CLK_ACLK_BTS_MDMA1, "aclk_bts_mdam1", "mout_aclk_g2d_266_user",
+                       DIV_ENABLE_ACLK_G2D, 11, 0, 0),
+       GATE(CLK_ACLK_BTS_G2D, "aclk_bts_g2d", "mout_aclk_g2d_400_user",
+                       DIV_ENABLE_ACLK_G2D, 10, 0, 0),
+       GATE(CLK_ACLK_ALB_G2D, "aclk_alb_g2d", "mout_aclk_g2d_400_user",
+                       DIV_ENABLE_ACLK_G2D, 9, 0, 0),
+       GATE(CLK_ACLK_AXIUS_G2DX, "aclk_axius_g2dx", "mout_aclk_g2d_400_user",
+                       DIV_ENABLE_ACLK_G2D, 8, 0, 0),
+       GATE(CLK_ACLK_ASYNCAXI_SYSX, "aclk_asyncaxi_sysx",
+                       "mout_aclk_g2d_400_user", DIV_ENABLE_ACLK_G2D,
+                       7, 0, 0),
+       GATE(CLK_ACLK_AHB2APB_G2D1P, "aclk_ahb2apb_g2d1p", "div_pclk_g2d",
+                       DIV_ENABLE_ACLK_G2D, 6, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AHB2APB_G2D0P, "aclk_ahb2apb_g2d0p", "div_pclk_g2d",
+                       DIV_ENABLE_ACLK_G2D, 5, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_XIU_G2DX, "aclk_xiu_g2dx", "mout_aclk_g2d_400_user",
+                       DIV_ENABLE_ACLK_G2D, 4, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_G2DNP_133, "aclk_g2dnp_133", "div_pclk_g2d",
+                       DIV_ENABLE_ACLK_G2D, 3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_G2DND_400, "aclk_g2dnd_400", "mout_aclk_g2d_400_user",
+                       DIV_ENABLE_ACLK_G2D, 2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_MDMA1, "aclk_mdma1", "mout_aclk_g2d_266_user",
+                       DIV_ENABLE_ACLK_G2D, 1, 0, 0),
+       GATE(CLK_ACLK_G2D, "aclk_g2d", "mout_aclk_g2d_400_user",
+                       DIV_ENABLE_ACLK_G2D, 0, 0, 0),
+
+       /* DIV_ENABLE_ACLK_G2D_SECURE_SMMU_G2D */
+       GATE(CLK_ACLK_SMMU_G2D, "aclk_smmu_g2d", "mout_aclk_g2d_400_user",
+               DIV_ENABLE_ACLK_G2D_SECURE_SMMU_G2D, 0, 0, 0),
+
+       /* DIV_ENABLE_PCLK_G2D */
+       GATE(CLK_PCLK_SMMU_MDMA1, "pclk_smmu_mdma1", "div_pclk_g2d",
+                       DIV_ENABLE_PCLK_G2D, 7, 0, 0),
+       GATE(CLK_PCLK_BTS_MDMA1, "pclk_bts_mdam1", "div_pclk_g2d",
+                       DIV_ENABLE_PCLK_G2D, 6, 0, 0),
+       GATE(CLK_PCLK_BTS_G2D, "pclk_bts_g2d", "div_pclk_g2d",
+                       DIV_ENABLE_PCLK_G2D, 5, 0, 0),
+       GATE(CLK_PCLK_ALB_G2D, "pclk_alb_g2d", "div_pclk_g2d",
+                       DIV_ENABLE_PCLK_G2D, 4, 0, 0),
+       GATE(CLK_PCLK_ASYNCAXI_SYSX, "pclk_asyncaxi_sysx", "div_pclk_g2d",
+                       DIV_ENABLE_PCLK_G2D, 3, 0, 0),
+       GATE(CLK_PCLK_PMU_G2D, "pclk_pmu_g2d", "div_pclk_g2d",
+                       DIV_ENABLE_PCLK_G2D, 2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SYSREG_G2D, "pclk_sysreg_g2d", "div_pclk_g2d",
+                       DIV_ENABLE_PCLK_G2D, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_G2D, "pclk_g2d", "div_pclk_g2d", DIV_ENABLE_PCLK_G2D,
+                       0, 0, 0),
+
+       /* DIV_ENABLE_PCLK_G2D_SECURE_SMMU_G2D */
+       GATE(CLK_PCLK_SMMU_G2D, "pclk_smmu_g2d", "div_pclk_g2d",
+               DIV_ENABLE_PCLK_G2D_SECURE_SMMU_G2D, 0, 0, 0),
+};
+
+static struct samsung_cmu_info g2d_cmu_info __initdata = {
+       .mux_clks               = g2d_mux_clks,
+       .nr_mux_clks            = ARRAY_SIZE(g2d_mux_clks),
+       .div_clks               = g2d_div_clks,
+       .nr_div_clks            = ARRAY_SIZE(g2d_div_clks),
+       .gate_clks              = g2d_gate_clks,
+       .nr_gate_clks           = ARRAY_SIZE(g2d_gate_clks),
+       .nr_clk_ids             = G2D_NR_CLK,
+       .clk_regs               = g2d_clk_regs,
+       .nr_clk_regs            = ARRAY_SIZE(g2d_clk_regs),
+};
+
+static void __init exynos5433_cmu_g2d_init(struct device_node *np)
+{
+       samsung_cmu_register_one(np, &g2d_cmu_info);
+}
+
+CLK_OF_DECLARE(exynos5433_cmu_g2d, "samsung,exynos5433-cmu-g2d",
+               exynos5433_cmu_g2d_init);
+
+/*
+ * Register offset definitions for CMU_DISP
+ */
+#define DISP_PLL_LOCK                  0x0000
+#define DISP_PLL_CON0                  0x0100
+#define DISP_PLL_CON1                  0x0104
+#define DISP_PLL_FREQ_DET              0x0108
+#define MUX_SEL_DISP0                  0x0200
+#define MUX_SEL_DISP1                  0x0204
+#define MUX_SEL_DISP2                  0x0208
+#define MUX_SEL_DISP3                  0x020c
+#define MUX_SEL_DISP4                  0x0210
+#define MUX_ENABLE_DISP0               0x0300
+#define MUX_ENABLE_DISP1               0x0304
+#define MUX_ENABLE_DISP2               0x0308
+#define MUX_ENABLE_DISP3               0x030c
+#define MUX_ENABLE_DISP4               0x0310
+#define MUX_STAT_DISP0                 0x0400
+#define MUX_STAT_DISP1                 0x0404
+#define MUX_STAT_DISP2                 0x0408
+#define MUX_STAT_DISP3                 0x040c
+#define MUX_STAT_DISP4                 0x0410
+#define MUX_IGNORE_DISP2               0x0508
+#define DIV_DISP                       0x0600
+#define DIV_DISP_PLL_FREQ_DET          0x0604
+#define DIV_STAT_DISP                  0x0700
+#define DIV_STAT_DISP_PLL_FREQ_DET     0x0704
+#define ENABLE_ACLK_DISP0              0x0800
+#define ENABLE_ACLK_DISP1              0x0804
+#define ENABLE_PCLK_DISP               0x0900
+#define ENABLE_SCLK_DISP               0x0a00
+#define ENABLE_IP_DISP0                        0x0b00
+#define ENABLE_IP_DISP1                        0x0b04
+#define CLKOUT_CMU_DISP                        0x0c00
+#define CLKOUT_CMU_DISP_DIV_STAT       0x0c04
+
+static unsigned long disp_clk_regs[] __initdata = {
+       DISP_PLL_LOCK,
+       DISP_PLL_CON0,
+       DISP_PLL_CON1,
+       DISP_PLL_FREQ_DET,
+       MUX_SEL_DISP0,
+       MUX_SEL_DISP1,
+       MUX_SEL_DISP2,
+       MUX_SEL_DISP3,
+       MUX_SEL_DISP4,
+       MUX_ENABLE_DISP0,
+       MUX_ENABLE_DISP1,
+       MUX_ENABLE_DISP2,
+       MUX_ENABLE_DISP3,
+       MUX_ENABLE_DISP4,
+       MUX_STAT_DISP0,
+       MUX_STAT_DISP1,
+       MUX_STAT_DISP2,
+       MUX_STAT_DISP3,
+       MUX_STAT_DISP4,
+       MUX_IGNORE_DISP2,
+       DIV_DISP,
+       DIV_DISP_PLL_FREQ_DET,
+       DIV_STAT_DISP,
+       DIV_STAT_DISP_PLL_FREQ_DET,
+       ENABLE_ACLK_DISP0,
+       ENABLE_ACLK_DISP1,
+       ENABLE_PCLK_DISP,
+       ENABLE_SCLK_DISP,
+       ENABLE_IP_DISP0,
+       ENABLE_IP_DISP1,
+       CLKOUT_CMU_DISP,
+       CLKOUT_CMU_DISP_DIV_STAT,
+};
+
+/* list of all parent clock list */
+PNAME(mout_disp_pll_p)                 = { "oscclk", "fout_disp_pll", };
+PNAME(mout_sclk_dsim1_user_p)          = { "oscclk", "sclk_dsim1_disp", };
+PNAME(mout_sclk_dsim0_user_p)          = { "oscclk", "sclk_dsim0_disp", };
+PNAME(mout_sclk_dsd_user_p)            = { "oscclk", "sclk_dsd_disp", };
+PNAME(mout_sclk_decon_tv_eclk_user_p)  = { "oscclk",
+                                           "sclk_decon_tv_eclk_disp", };
+PNAME(mout_sclk_decon_vclk_user_p)     = { "oscclk",
+                                           "sclk_decon_vclk_disp", };
+PNAME(mout_sclk_decon_eclk_user_p)     = { "oscclk",
+                                           "sclk_decon_eclk_disp", };
+PNAME(mout_sclk_decon_tv_vlkc_user_p)  = { "oscclk",
+                                           "sclk_decon_tv_vclk_disp", };
+PNAME(mout_aclk_disp_333_user_p)       = { "oscclk", "aclk_disp_333", };
+
+PNAME(mout_phyclk_mipidphy1_bitclkdiv8_user_p) = { "oscclk",
+                                       "phyclk_mipidphy1_bitclkdiv8_phy", };
+PNAME(mout_phyclk_mipidphy1_rxclkesc0_user_p)  = { "oscclk",
+                                       "phyclk_mipidphy1_rxclkesc0_phy", };
+PNAME(mout_phyclk_mipidphy0_bitclkdiv8_user_p) = { "oscclk",
+                                       "phyclk_mipidphy0_bitclkdiv8_phy", };
+PNAME(mout_phyclk_mipidphy0_rxclkesc0_user_p)  = { "oscclk",
+                                       "phyclk_mipidphy0_rxclkesc0_phy", };
+PNAME(mout_phyclk_hdmiphy_tmds_clko_user_p)    = { "oscclk",
+                                       "phyclk_hdmiphy_tmds_clko_phy", };
+PNAME(mout_phyclk_hdmiphy_pixel_clko_user_p)   = { "oscclk",
+                                       "phyclk_hdmiphy_pixel_clko_phy", };
+
+PNAME(mout_sclk_dsim0_p)               = { "mout_disp_pll",
+                                           "mout_sclk_dsim0_user", };
+PNAME(mout_sclk_decon_tv_eclk_p)       = { "mout_disp_pll",
+                                           "mout_sclk_decon_tv_eclk_user", };
+PNAME(mout_sclk_decon_vclk_p)          = { "mout_disp_pll",
+                                           "mout_sclk_decon_vclk_user", };
+PNAME(mout_sclk_decon_eclk_p)          = { "mout_disp_pll",
+                                           "mout_sclk_decon_eclk_user", };
+
+PNAME(mout_sclk_dsim1_b_disp_p)                = { "mout_sclk_dsim1_a_disp",
+                                           "mout_sclk_dsim1_user", };
+PNAME(mout_sclk_decon_tv_vclk_c_disp_p)        = {
+                               "mout_phyclk_hdmiphy_pixel_clko_user",
+                               "mout_sclk_decon_tv_vclk_b_disp", };
+PNAME(mout_sclk_decon_tv_vclk_b_disp_p)        = { "mout_sclk_decon_tv_vclk_a_disp",
+                                           "mout_sclk_decon_tv_vclk_user", };
+
+static struct samsung_pll_clock disp_pll_clks[] __initdata = {
+       PLL(pll_35xx, CLK_FOUT_DISP_PLL, "fout_disp_pll", "oscclk",
+               DISP_PLL_LOCK, DISP_PLL_CON0, exynos5443_pll_rates),
+};
+
+static struct samsung_fixed_factor_clock disp_fixed_factor_clks[] __initdata = {
+       /*
+        * sclk_rgb_{vclk|tv_vclk} is half clock of sclk_decon_{vclk|tv_vclk}.
+        * The divider has fixed value (2) between sclk_rgb_{vclk|tv_vclk}
+        * and sclk_decon_{vclk|tv_vclk}.
+        */
+       FFACTOR(CLK_SCLK_RGB_VCLK, "sclk_rgb_vclk", "sclk_decon_vclk",
+                       1, 2, 0),
+       FFACTOR(CLK_SCLK_RGB_TV_VCLK, "sclk_rgb_tv_vclk", "sclk_decon_tv_vclk",
+                       1, 2, 0),
+};
+
+static struct samsung_fixed_rate_clock disp_fixed_clks[] __initdata = {
+       /* PHY clocks from MIPI_DPHY1 */
+       FRATE(0, "phyclk_mipidphy1_bitclkdiv8_phy", NULL, CLK_IS_ROOT,
+                       188000000),
+       FRATE(0, "phyclk_mipidphy1_rxclkesc0_phy", NULL, CLK_IS_ROOT,
+                       100000000),
+       /* PHY clocks from MIPI_DPHY0 */
+       FRATE(0, "phyclk_mipidphy0_bitclkdiv8_phy", NULL, CLK_IS_ROOT,
+                       188000000),
+       FRATE(0, "phyclk_mipidphy0_rxclkesc0_phy", NULL, CLK_IS_ROOT,
+                       100000000),
+       /* PHY clocks from HDMI_PHY */
+       FRATE(0, "phyclk_hdmiphy_tmds_clko_phy", NULL, CLK_IS_ROOT, 300000000),
+       FRATE(0, "phyclk_hdmiphy_pixel_clko_phy", NULL, CLK_IS_ROOT, 166000000),
+};
+
+static struct samsung_mux_clock disp_mux_clks[] __initdata = {
+       /* MUX_SEL_DISP0 */
+       MUX(CLK_MOUT_DISP_PLL, "mout_disp_pll", mout_disp_pll_p, MUX_SEL_DISP0,
+                       0, 1),
+
+       /* MUX_SEL_DISP1 */
+       MUX(CLK_MOUT_SCLK_DSIM1_USER, "mout_sclk_dsim1_user",
+                       mout_sclk_dsim1_user_p, MUX_SEL_DISP1, 28, 1),
+       MUX(CLK_MOUT_SCLK_DSIM0_USER, "mout_sclk_dsim0_user",
+                       mout_sclk_dsim0_user_p, MUX_SEL_DISP1, 24, 1),
+       MUX(CLK_MOUT_SCLK_DSD_USER, "mout_sclk_dsd_user", mout_sclk_dsd_user_p,
+                       MUX_SEL_DISP1, 20, 1),
+       MUX(CLK_MOUT_SCLK_DECON_TV_ECLK_USER, "mout_sclk_decon_tv_eclk_user",
+                       mout_sclk_decon_tv_eclk_user_p, MUX_SEL_DISP1, 16, 1),
+       MUX(CLK_MOUT_SCLK_DECON_VCLK_USER, "mout_sclk_decon_vclk_user",
+                       mout_sclk_decon_vclk_user_p, MUX_SEL_DISP1, 12, 1),
+       MUX(CLK_MOUT_SCLK_DECON_ECLK_USER, "mout_sclk_decon_eclk_user",
+                       mout_sclk_decon_eclk_user_p, MUX_SEL_DISP1, 8, 1),
+       MUX(CLK_MOUT_SCLK_DECON_TV_VCLK_USER, "mout_sclk_decon_tv_vclk_user",
+                       mout_sclk_decon_tv_vlkc_user_p, MUX_SEL_DISP1, 4, 1),
+       MUX(CLK_MOUT_ACLK_DISP_333_USER, "mout_aclk_disp_333_user",
+                       mout_aclk_disp_333_user_p, MUX_SEL_DISP1, 0, 1),
+
+       /* MUX_SEL_DISP2 */
+       MUX(CLK_MOUT_PHYCLK_MIPIDPHY1_BITCLKDIV8_USER,
+                       "mout_phyclk_mipidphy1_bitclkdiv8_user",
+                       mout_phyclk_mipidphy1_bitclkdiv8_user_p, MUX_SEL_DISP2,
+                       20, 1),
+       MUX(CLK_MOUT_PHYCLK_MIPIDPHY1_RXCLKESC0_USER,
+                       "mout_phyclk_mipidphy1_rxclkesc0_user",
+                       mout_phyclk_mipidphy1_rxclkesc0_user_p, MUX_SEL_DISP2,
+                       16, 1),
+       MUX(CLK_MOUT_PHYCLK_MIPIDPHY0_BITCLKDIV8_USER,
+                       "mout_phyclk_mipidphy0_bitclkdiv8_user",
+                       mout_phyclk_mipidphy0_bitclkdiv8_user_p, MUX_SEL_DISP2,
+                       12, 1),
+       MUX(CLK_MOUT_PHYCLK_MIPIDPHY0_RXCLKESC0_USER,
+                       "mout_phyclk_mipidphy0_rxclkesc0_user",
+                       mout_phyclk_mipidphy0_rxclkesc0_user_p, MUX_SEL_DISP2,
+                       8, 1),
+       MUX(CLK_MOUT_PHYCLK_HDMIPHY_TMDS_CLKO_USER,
+                       "mout_phyclk_hdmiphy_tmds_clko_user",
+                       mout_phyclk_hdmiphy_tmds_clko_user_p, MUX_SEL_DISP2,
+                       4, 1),
+       MUX(CLK_MOUT_PHYCLK_HDMIPHY_PIXEL_CLKO_USER,
+                       "mout_phyclk_hdmiphy_pixel_clko_user",
+                       mout_phyclk_hdmiphy_pixel_clko_user_p, MUX_SEL_DISP2,
+                       0, 1),
+
+       /* MUX_SEL_DISP3 */
+       MUX(CLK_MOUT_SCLK_DSIM0, "mout_sclk_dsim0", mout_sclk_dsim0_p,
+                       MUX_SEL_DISP3, 12, 1),
+       MUX(CLK_MOUT_SCLK_DECON_TV_ECLK, "mout_sclk_decon_tv_eclk",
+                       mout_sclk_decon_tv_eclk_p, MUX_SEL_DISP3, 8, 1),
+       MUX(CLK_MOUT_SCLK_DECON_VCLK, "mout_sclk_decon_vclk",
+                       mout_sclk_decon_vclk_p, MUX_SEL_DISP3, 4, 1),
+       MUX(CLK_MOUT_SCLK_DECON_ECLK, "mout_sclk_decon_eclk",
+                       mout_sclk_decon_eclk_p, MUX_SEL_DISP3, 0, 1),
+
+       /* MUX_SEL_DISP4 */
+       MUX(CLK_MOUT_SCLK_DSIM1_B_DISP, "mout_sclk_dsim1_b_disp",
+                       mout_sclk_dsim1_b_disp_p, MUX_SEL_DISP4, 16, 1),
+       MUX(CLK_MOUT_SCLK_DSIM1_A_DISP, "mout_sclk_dsim1_a_disp",
+                       mout_sclk_dsim0_p, MUX_SEL_DISP4, 12, 1),
+       MUX(CLK_MOUT_SCLK_DECON_TV_VCLK_C_DISP,
+                       "mout_sclk_decon_tv_vclk_c_disp",
+                       mout_sclk_decon_tv_vclk_c_disp_p, MUX_SEL_DISP4, 8, 1),
+       MUX(CLK_MOUT_SCLK_DECON_TV_VCLK_B_DISP,
+                       "mout_sclk_decon_tv_vclk_b_disp",
+                       mout_sclk_decon_tv_vclk_b_disp_p, MUX_SEL_DISP4, 4, 1),
+       MUX(CLK_MOUT_SCLK_DECON_TV_VCLK_A_DISP,
+                       "mout_sclk_decon_tv_vclk_a_disp",
+                       mout_sclk_decon_vclk_p, MUX_SEL_DISP4, 0, 1),
+};
+
+static struct samsung_div_clock disp_div_clks[] __initdata = {
+       /* DIV_DISP */
+       DIV(CLK_DIV_SCLK_DSIM1_DISP, "div_sclk_dsim1_disp",
+                       "mout_sclk_dsim1_b_disp", DIV_DISP, 24, 3),
+       DIV(CLK_DIV_SCLK_DECON_TV_VCLK_DISP, "div_sclk_decon_tv_vclk_disp",
+                       "mout_sclk_decon_tv_vclk_c_disp", DIV_DISP, 20, 3),
+       DIV(CLK_DIV_SCLK_DSIM0_DISP, "div_sclk_dsim0_disp", "mout_sclk_dsim0",
+                       DIV_DISP, 16, 3),
+       DIV(CLK_DIV_SCLK_DECON_TV_ECLK_DISP, "div_sclk_decon_tv_eclk_disp",
+                       "mout_sclk_decon_tv_eclk", DIV_DISP, 12, 3),
+       DIV(CLK_DIV_SCLK_DECON_VCLK_DISP, "div_sclk_decon_vclk_disp",
+                       "mout_sclk_decon_vclk", DIV_DISP, 8, 3),
+       DIV(CLK_DIV_SCLK_DECON_ECLK_DISP, "div_sclk_decon_eclk_disp",
+                       "mout_sclk_decon_eclk", DIV_DISP, 4, 3),
+       DIV(CLK_DIV_PCLK_DISP, "div_pclk_disp", "mout_aclk_disp_333_user",
+                       DIV_DISP, 0, 2),
+};
+
+static struct samsung_gate_clock disp_gate_clks[] __initdata = {
+       /* ENABLE_ACLK_DISP0 */
+       GATE(CLK_ACLK_DECON_TV, "aclk_decon_tv", "mout_aclk_disp_333_user",
+                       ENABLE_ACLK_DISP0, 2, 0, 0),
+       GATE(CLK_ACLK_DECON, "aclk_decon", "mout_aclk_disp_333_user",
+                       ENABLE_ACLK_DISP0, 0, 0, 0),
+
+       /* ENABLE_ACLK_DISP1 */
+       GATE(CLK_ACLK_SMMU_TV1X, "aclk_smmu_tv1x", "mout_aclk_disp_333_user",
+                       ENABLE_ACLK_DISP1, 25, 0, 0),
+       GATE(CLK_ACLK_SMMU_TV0X, "aclk_smmu_tv0x", "mout_aclk_disp_333_user",
+                       ENABLE_ACLK_DISP1, 24, 0, 0),
+       GATE(CLK_ACLK_SMMU_DECON1X, "aclk_smmu_decon1x",
+                       "mout_aclk_disp_333_user", ENABLE_ACLK_DISP1, 23, 0, 0),
+       GATE(CLK_ACLK_SMMU_DECON0X, "aclk_smmu_decon0x",
+                       "mout_aclk_disp_333_user", ENABLE_ACLK_DISP1, 22, 0, 0),
+       GATE(CLK_ACLK_BTS_DECON_TV_M3, "aclk_bts_decon_tv_m3",
+                       "mout_aclk_disp_333_user", ENABLE_ACLK_DISP1, 21, 0, 0),
+       GATE(CLK_ACLK_BTS_DECON_TV_M2, "aclk_bts_decon_tv_m2",
+                       "mout_aclk_disp_333_user", ENABLE_ACLK_DISP1, 20, 0, 0),
+       GATE(CLK_ACLK_BTS_DECON_TV_M1, "aclk_bts_decon_tv_m1",
+                       "mout_aclk_disp_333_user", ENABLE_ACLK_DISP1, 19, 0, 0),
+       GATE(CLK_ACLK_BTS_DECON_TV_M0, "aclk-bts_decon_tv_m0",
+                       "mout_aclk_disp_333_user", ENABLE_ACLK_DISP1, 18, 0, 0),
+       GATE(CLK_ACLK_BTS_DECON_NM4, "aclk_bts_decon_nm4",
+                       "mout_aclk_disp_333_user", ENABLE_ACLK_DISP1, 17, 0, 0),
+       GATE(CLK_ACLK_BTS_DECON_NM3, "aclk_bts_decon_nm3",
+                       "mout_aclk_disp_333_user", ENABLE_ACLK_DISP1, 16, 0, 0),
+       GATE(CLK_ACLK_BTS_DECON_NM2, "aclk_bts_decon_nm2",
+                       "mout_aclk_disp_333_user", ENABLE_ACLK_DISP1, 15, 0, 0),
+       GATE(CLK_ACLK_BTS_DECON_NM1, "aclk_bts_decon_nm1",
+                       "mout_aclk_disp_333_user", ENABLE_ACLK_DISP1, 14, 0, 0),
+       GATE(CLK_ACLK_BTS_DECON_NM0, "aclk_bts_decon_nm0",
+                       "mout_aclk_disp_333_user", ENABLE_ACLK_DISP1, 13, 0, 0),
+       GATE(CLK_ACLK_AHB2APB_DISPSFR2P, "aclk_ahb2apb_dispsfr2p",
+                       "div_pclk_disp", ENABLE_ACLK_DISP1,
+                       12, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AHB2APB_DISPSFR1P, "aclk_ahb2apb_dispsfr1p",
+                       "div_pclk_disp", ENABLE_ACLK_DISP1,
+                       11, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AHB2APB_DISPSFR0P, "aclk_ahb2apb_dispsfr0p",
+                       "div_pclk_disp", ENABLE_ACLK_DISP1,
+                       10, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AHB_DISPH, "aclk_ahb_disph", "div_pclk_disp",
+                       ENABLE_ACLK_DISP1, 8, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_XIU_TV1X, "aclk_xiu_tv1x", "mout_aclk_disp_333_user",
+                       ENABLE_ACLK_DISP1, 7, 0, 0),
+       GATE(CLK_ACLK_XIU_TV0X, "aclk_xiu_tv0x", "mout_aclk_disp_333_user",
+                       ENABLE_ACLK_DISP1, 6, 0, 0),
+       GATE(CLK_ACLK_XIU_DECON1X, "aclk_xiu_decon1x",
+                       "mout_aclk_disp_333_user", ENABLE_ACLK_DISP1, 5, 0, 0),
+       GATE(CLK_ACLK_XIU_DECON0X, "aclk_xiu_decon0x",
+                       "mout_aclk_disp_333_user", ENABLE_ACLK_DISP1, 4, 0, 0),
+       GATE(CLK_ACLK_XIU_DISP1X, "aclk_xiu_disp1x", "mout_aclk_disp_333_user",
+                       ENABLE_ACLK_DISP1, 3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_XIU_DISPNP_100, "aclk_xiu_dispnp_100", "div_pclk_disp",
+                       ENABLE_ACLK_DISP1, 2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_DISP1ND_333, "aclk_disp1nd_333",
+                       "mout_aclk_disp_333_user", ENABLE_ACLK_DISP1, 1,
+                       CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_DISP0ND_333, "aclk_disp0nd_333",
+                       "mout_aclk_disp_333_user", ENABLE_ACLK_DISP1,
+                       0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_PCLK_DISP */
+       GATE(CLK_PCLK_SMMU_TV1X, "pclk_smmu_tv1x", "div_pclk_disp",
+                       ENABLE_PCLK_DISP, 23, 0, 0),
+       GATE(CLK_PCLK_SMMU_TV0X, "pclk_smmu_tv0x", "div_pclk_disp",
+                       ENABLE_PCLK_DISP, 22, 0, 0),
+       GATE(CLK_PCLK_SMMU_DECON1X, "pclk_smmu_decon1x", "div_pclk_disp",
+                       ENABLE_PCLK_DISP, 21, 0, 0),
+       GATE(CLK_PCLK_SMMU_DECON0X, "pclk_smmu_decon0x", "div_pclk_disp",
+                       ENABLE_PCLK_DISP, 20, 0, 0),
+       GATE(CLK_PCLK_BTS_DECON_TV_M3, "pclk_bts_decon_tv_m3", "div_pclk_disp",
+                       ENABLE_PCLK_DISP, 19, 0, 0),
+       GATE(CLK_PCLK_BTS_DECON_TV_M2, "pclk_bts_decon_tv_m2", "div_pclk_disp",
+                       ENABLE_PCLK_DISP, 18, 0, 0),
+       GATE(CLK_PCLK_BTS_DECON_TV_M1, "pclk_bts_decon_tv_m1", "div_pclk_disp",
+                       ENABLE_PCLK_DISP, 17, 0, 0),
+       GATE(CLK_PCLK_BTS_DECON_TV_M0, "pclk_bts_decon_tv_m0", "div_pclk_disp",
+                       ENABLE_PCLK_DISP, 16, 0, 0),
+       GATE(CLK_PCLK_BTS_DECONM4, "pclk_bts_deconm4", "div_pclk_disp",
+                       ENABLE_PCLK_DISP, 15, 0, 0),
+       GATE(CLK_PCLK_BTS_DECONM3, "pclk_bts_deconm3", "div_pclk_disp",
+                       ENABLE_PCLK_DISP, 14, 0, 0),
+       GATE(CLK_PCLK_BTS_DECONM2, "pclk_bts_deconm2", "div_pclk_disp",
+                       ENABLE_PCLK_DISP, 13, 0, 0),
+       GATE(CLK_PCLK_BTS_DECONM1, "pclk_bts_deconm1", "div_pclk_disp",
+                       ENABLE_PCLK_DISP, 12, 0, 0),
+       GATE(CLK_PCLK_BTS_DECONM0, "pclk_bts_deconm0", "div_pclk_disp",
+                       ENABLE_PCLK_DISP, 11, 0, 0),
+       GATE(CLK_PCLK_MIC1, "pclk_mic1", "div_pclk_disp",
+                       ENABLE_PCLK_DISP, 10, 0, 0),
+       GATE(CLK_PCLK_PMU_DISP, "pclk_pmu_disp", "div_pclk_disp",
+                       ENABLE_PCLK_DISP, 9, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SYSREG_DISP, "pclk_sysreg_disp", "div_pclk_disp",
+                       ENABLE_PCLK_DISP, 8, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_HDMIPHY, "pclk_hdmiphy", "div_pclk_disp",
+                       ENABLE_PCLK_DISP, 7, 0, 0),
+       GATE(CLK_PCLK_HDMI, "pclk_hdmi", "div_pclk_disp",
+                       ENABLE_PCLK_DISP, 6, 0, 0),
+       GATE(CLK_PCLK_MIC0, "pclk_mic0", "div_pclk_disp",
+                       ENABLE_PCLK_DISP, 5, 0, 0),
+       GATE(CLK_PCLK_DSIM1, "pclk_dsim1", "div_pclk_disp",
+                       ENABLE_PCLK_DISP, 3, 0, 0),
+       GATE(CLK_PCLK_DSIM0, "pclk_dsim0", "div_pclk_disp",
+                       ENABLE_PCLK_DISP, 2, 0, 0),
+       GATE(CLK_PCLK_DECON_TV, "pclk_decon_tv", "div_pclk_disp",
+                       ENABLE_PCLK_DISP, 1, 0, 0),
+
+       /* ENABLE_SCLK_DISP */
+       GATE(CLK_PHYCLK_MIPIDPHY1_BITCLKDIV8, "phyclk_mipidphy1_bitclkdiv8",
+                       "mout_phyclk_mipidphy1_bitclkdiv8_user",
+                       ENABLE_SCLK_DISP, 26, 0, 0),
+       GATE(CLK_PHYCLK_MIPIDPHY1_RXCLKESC0, "phyclk_mipidphy1_rxclkesc0",
+                       "mout_phyclk_mipidphy1_rxclkesc0_user",
+                       ENABLE_SCLK_DISP, 25, 0, 0),
+       GATE(CLK_SCLK_RGB_TV_VCLK_TO_DSIM1, "sclk_rgb_tv_vclk_to_dsim1",
+                       "sclk_rgb_tv_vclk", ENABLE_SCLK_DISP, 24, 0, 0),
+       GATE(CLK_SCLK_RGB_TV_VCLK_TO_MIC1, "sclk_rgb_tv_vclk_to_mic1",
+                       "sclk_rgb_tv_vclk", ENABLE_SCLK_DISP, 23, 0, 0),
+       GATE(CLK_SCLK_DSIM1, "sclk_dsim1", "div_sclk_dsim1_disp",
+                       ENABLE_SCLK_DISP, 22, 0, 0),
+       GATE(CLK_SCLK_DECON_TV_VCLK, "sclk_decon_tv_vclk",
+                       "div_sclk_decon_tv_vclk_disp",
+                       ENABLE_SCLK_DISP, 21, 0, 0),
+       GATE(CLK_PHYCLK_MIPIDPHY0_BITCLKDIV8, "phyclk_mipidphy0_bitclkdiv8",
+                       "mout_phyclk_mipidphy0_bitclkdiv8_user",
+                       ENABLE_SCLK_DISP, 15, 0, 0),
+       GATE(CLK_PHYCLK_MIPIDPHY0_RXCLKESC0, "phyclk_mipidphy0_rxclkesc0",
+                       "mout_phyclk_mipidphy0_rxclkesc0_user",
+                       ENABLE_SCLK_DISP, 14, 0, 0),
+       GATE(CLK_PHYCLK_HDMIPHY_TMDS_CLKO, "phyclk_hdmiphy_tmds_clko",
+                       "mout_phyclk_hdmiphy_tmds_clko_user",
+                       ENABLE_SCLK_DISP, 13, 0, 0),
+       GATE(CLK_PHYCLK_HDMI_PIXEL, "phyclk_hdmi_pixel",
+                       "sclk_rgb_tv_vclk", ENABLE_SCLK_DISP, 12, 0, 0),
+       GATE(CLK_SCLK_RGB_VCLK_TO_SMIES, "sclk_rgb_vclk_to_smies",
+                       "sclk_rgb_vclk", ENABLE_SCLK_DISP, 11, 0, 0),
+       GATE(CLK_SCLK_RGB_VCLK_TO_DSIM0, "sclk_rgb_vclk_to_dsim0",
+                       "sclk_rgb_vclk", ENABLE_SCLK_DISP, 9, 0, 0),
+       GATE(CLK_SCLK_RGB_VCLK_TO_MIC0, "sclk_rgb_vclk_to_mic0",
+                       "sclk_rgb_vclk", ENABLE_SCLK_DISP, 8, 0, 0),
+       GATE(CLK_SCLK_DSD, "sclk_dsd", "mout_sclk_dsd_user",
+                       ENABLE_SCLK_DISP, 7, 0, 0),
+       GATE(CLK_SCLK_HDMI_SPDIF, "sclk_hdmi_spdif", "sclk_hdmi_spdif_disp",
+                       ENABLE_SCLK_DISP, 6, 0, 0),
+       GATE(CLK_SCLK_DSIM0, "sclk_dsim0", "div_sclk_dsim0_disp",
+                       ENABLE_SCLK_DISP, 5, 0, 0),
+       GATE(CLK_SCLK_DECON_TV_ECLK, "sclk_decon_tv_eclk",
+                       "div_sclk_decon_tv_eclk_disp",
+                       ENABLE_SCLK_DISP, 4, 0, 0),
+       GATE(CLK_SCLK_DECON_VCLK, "sclk_decon_vclk",
+                       "div_sclk_decon_vclk_disp", ENABLE_SCLK_DISP, 3, 0, 0),
+       GATE(CLK_SCLK_DECON_ECLK, "sclk_decon_eclk",
+                       "div_sclk_decon_eclk_disp", ENABLE_SCLK_DISP, 2, 0, 0),
+};
+
+static struct samsung_cmu_info disp_cmu_info __initdata = {
+       .pll_clks               = disp_pll_clks,
+       .nr_pll_clks            = ARRAY_SIZE(disp_pll_clks),
+       .mux_clks               = disp_mux_clks,
+       .nr_mux_clks            = ARRAY_SIZE(disp_mux_clks),
+       .div_clks               = disp_div_clks,
+       .nr_div_clks            = ARRAY_SIZE(disp_div_clks),
+       .gate_clks              = disp_gate_clks,
+       .nr_gate_clks           = ARRAY_SIZE(disp_gate_clks),
+       .fixed_clks             = disp_fixed_clks,
+       .nr_fixed_clks          = ARRAY_SIZE(disp_fixed_clks),
+       .fixed_factor_clks      = disp_fixed_factor_clks,
+       .nr_fixed_factor_clks   = ARRAY_SIZE(disp_fixed_factor_clks),
+       .nr_clk_ids             = DISP_NR_CLK,
+       .clk_regs               = disp_clk_regs,
+       .nr_clk_regs            = ARRAY_SIZE(disp_clk_regs),
+};
+
+static void __init exynos5433_cmu_disp_init(struct device_node *np)
+{
+       samsung_cmu_register_one(np, &disp_cmu_info);
+}
+
+CLK_OF_DECLARE(exynos5433_cmu_disp, "samsung,exynos5433-cmu-disp",
+               exynos5433_cmu_disp_init);
+
+/*
+ * Register offset definitions for CMU_AUD
+ */
+#define MUX_SEL_AUD0                   0x0200
+#define MUX_SEL_AUD1                   0x0204
+#define MUX_ENABLE_AUD0                        0x0300
+#define MUX_ENABLE_AUD1                        0x0304
+#define MUX_STAT_AUD0                  0x0400
+#define DIV_AUD0                       0x0600
+#define DIV_AUD1                       0x0604
+#define DIV_STAT_AUD0                  0x0700
+#define DIV_STAT_AUD1                  0x0704
+#define ENABLE_ACLK_AUD                        0x0800
+#define ENABLE_PCLK_AUD                        0x0900
+#define ENABLE_SCLK_AUD0               0x0a00
+#define ENABLE_SCLK_AUD1               0x0a04
+#define ENABLE_IP_AUD0                 0x0b00
+#define ENABLE_IP_AUD1                 0x0b04
+
+static unsigned long aud_clk_regs[] __initdata = {
+       MUX_SEL_AUD0,
+       MUX_SEL_AUD1,
+       MUX_ENABLE_AUD0,
+       MUX_ENABLE_AUD1,
+       MUX_STAT_AUD0,
+       DIV_AUD0,
+       DIV_AUD1,
+       DIV_STAT_AUD0,
+       DIV_STAT_AUD1,
+       ENABLE_ACLK_AUD,
+       ENABLE_PCLK_AUD,
+       ENABLE_SCLK_AUD0,
+       ENABLE_SCLK_AUD1,
+       ENABLE_IP_AUD0,
+       ENABLE_IP_AUD1,
+};
+
+/* list of all parent clock list */
+PNAME(mout_aud_pll_user_aud_p) = { "oscclk", "fout_aud_pll", };
+PNAME(mout_sclk_aud_pcm_p)     = { "mout_aud_pll_user", "ioclk_audiocdclk0",};
+
+static struct samsung_fixed_rate_clock aud_fixed_clks[] __initdata = {
+       FRATE(0, "ioclk_jtag_tclk", NULL, CLK_IS_ROOT, 33000000),
+       FRATE(0, "ioclk_slimbus_clk", NULL, CLK_IS_ROOT, 25000000),
+       FRATE(0, "ioclk_i2s_bclk", NULL, CLK_IS_ROOT, 50000000),
+};
+
+static struct samsung_mux_clock aud_mux_clks[] __initdata = {
+       /* MUX_SEL_AUD0 */
+       MUX(CLK_MOUT_AUD_PLL_USER, "mout_aud_pll_user",
+                       mout_aud_pll_user_aud_p, MUX_SEL_AUD0, 0, 1),
+
+       /* MUX_SEL_AUD1 */
+       MUX(CLK_MOUT_SCLK_AUD_PCM, "mout_sclk_aud_pcm", mout_sclk_aud_pcm_p,
+                       MUX_SEL_AUD1, 8, 1),
+       MUX(CLK_MOUT_SCLK_AUD_I2S, "mout_sclk_aud_i2s", mout_sclk_aud_pcm_p,
+                       MUX_SEL_AUD1, 0, 1),
+};
+
+static struct samsung_div_clock aud_div_clks[] __initdata = {
+       /* DIV_AUD0 */
+       DIV(CLK_DIV_ATCLK_AUD, "div_atclk_aud", "div_aud_ca5", DIV_AUD0,
+                       12, 4),
+       DIV(CLK_DIV_PCLK_DBG_AUD, "div_pclk_dbg_aud", "div_aud_ca5", DIV_AUD0,
+                       8, 4),
+       DIV(CLK_DIV_ACLK_AUD, "div_aclk_aud", "div_aud_ca5", DIV_AUD0,
+                       4, 4),
+       DIV(CLK_DIV_AUD_CA5, "div_aud_ca5", "mout_aud_pll_user", DIV_AUD0,
+                       0, 4),
+
+       /* DIV_AUD1 */
+       DIV(CLK_DIV_SCLK_AUD_SLIMBUS, "div_sclk_aud_slimbus",
+                       "mout_aud_pll_user", DIV_AUD1, 16, 5),
+       DIV(CLK_DIV_SCLK_AUD_UART, "div_sclk_aud_uart", "mout_aud_pll_user",
+                       DIV_AUD1, 12, 4),
+       DIV(CLK_DIV_SCLK_AUD_PCM, "div_sclk_aud_pcm", "mout_sclk_aud_pcm",
+                       DIV_AUD1, 4, 8),
+       DIV(CLK_DIV_SCLK_AUD_I2S, "div_sclk_aud_i2s",  "mout_sclk_aud_i2s",
+                       DIV_AUD1, 0, 4),
+};
+
+static struct samsung_gate_clock aud_gate_clks[] __initdata = {
+       /* ENABLE_ACLK_AUD */
+       GATE(CLK_ACLK_INTR_CTRL, "aclk_intr_ctrl", "div_aclk_aud",
+                       ENABLE_ACLK_AUD, 12, 0, 0),
+       GATE(CLK_ACLK_SMMU_LPASSX, "aclk_smmu_lpassx", "div_aclk_aud",
+                       ENABLE_ACLK_AUD, 7, 0, 0),
+       GATE(CLK_ACLK_XIU_LPASSX, "aclk_xiu_lpassx", "div_aclk_aud",
+                       ENABLE_ACLK_AUD, 0, 4, 0),
+       GATE(CLK_ACLK_AUDNP_133, "aclk_audnp_133", "div_aclk_aud",
+                       ENABLE_ACLK_AUD, 0, 3, 0),
+       GATE(CLK_ACLK_AUDND_133, "aclk_audnd_133", "div_aclk_aud",
+                       ENABLE_ACLK_AUD, 0, 2, 0),
+       GATE(CLK_ACLK_SRAMC, "aclk_sramc", "div_aclk_aud", ENABLE_ACLK_AUD,
+                       0, 1, 0),
+       GATE(CLK_ACLK_DMAC, "aclk_dmac",  "div_aclk_aud", ENABLE_ACLK_AUD,
+                       0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_PCLK_AUD */
+       GATE(CLK_PCLK_WDT1, "pclk_wdt1", "div_aclk_aud", ENABLE_PCLK_AUD,
+                       13, 0, 0),
+       GATE(CLK_PCLK_WDT0, "pclk_wdt0", "div_aclk_aud", ENABLE_PCLK_AUD,
+                       12, 0, 0),
+       GATE(CLK_PCLK_SFR1, "pclk_sfr1", "div_aclk_aud", ENABLE_PCLK_AUD,
+                       11, 0, 0),
+       GATE(CLK_PCLK_SMMU_LPASSX, "pclk_smmu_lpassx", "div_aclk_aud",
+                       ENABLE_PCLK_AUD, 10, 0, 0),
+       GATE(CLK_PCLK_GPIO_AUD, "pclk_gpio_aud", "div_aclk_aud",
+                       ENABLE_PCLK_AUD, 9, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_PMU_AUD, "pclk_pmu_aud", "div_aclk_aud",
+                       ENABLE_PCLK_AUD, 8, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SYSREG_AUD, "pclk_sysreg_aud", "div_aclk_aud",
+                       ENABLE_PCLK_AUD, 7, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_AUD_SLIMBUS, "pclk_aud_slimbus", "div_aclk_aud",
+                       ENABLE_PCLK_AUD, 6, 0, 0),
+       GATE(CLK_PCLK_AUD_UART, "pclk_aud_uart", "div_aclk_aud",
+                       ENABLE_PCLK_AUD, 5, 0, 0),
+       GATE(CLK_PCLK_AUD_PCM, "pclk_aud_pcm", "div_aclk_aud",
+                       ENABLE_PCLK_AUD, 4, 0, 0),
+       GATE(CLK_PCLK_AUD_I2S, "pclk_aud_i2s", "div_aclk_aud",
+                       ENABLE_PCLK_AUD, 3, 0, 0),
+       GATE(CLK_PCLK_TIMER, "pclk_timer", "div_aclk_aud", ENABLE_PCLK_AUD,
+                       2, 0, 0),
+       GATE(CLK_PCLK_SFR0_CTRL, "pclk_sfr0_ctrl", "div_aclk_aud",
+                       ENABLE_PCLK_AUD, 0, 0, 0),
+
+       /* ENABLE_SCLK_AUD0 */
+       GATE(CLK_ATCLK_AUD, "atclk_aud", "div_atclk_aud", ENABLE_SCLK_AUD0,
+                       2, 0, 0),
+       GATE(CLK_PCLK_DBG_AUD, "pclk_dbg_aud", "div_pclk_dbg_aud",
+                       ENABLE_SCLK_AUD0, 1, 0, 0),
+       GATE(CLK_SCLK_AUD_CA5, "sclk_aud_ca5", "div_aud_ca5", ENABLE_SCLK_AUD0,
+                       0, 0, 0),
+
+       /* ENABLE_SCLK_AUD1 */
+       GATE(CLK_SCLK_JTAG_TCK, "sclk_jtag_tck", "ioclk_jtag_tclk",
+                       ENABLE_SCLK_AUD1, 6, 0, 0),
+       GATE(CLK_SCLK_SLIMBUS_CLKIN, "sclk_slimbus_clkin", "ioclk_slimbus_clk",
+                       ENABLE_SCLK_AUD1, 5, 0, 0),
+       GATE(CLK_SCLK_AUD_SLIMBUS, "sclk_aud_slimbus", "div_sclk_aud_slimbus",
+                       ENABLE_SCLK_AUD1, 4, 0, 0),
+       GATE(CLK_SCLK_AUD_UART, "sclk_aud_uart", "div_sclk_aud_uart",
+                       ENABLE_SCLK_AUD1, 3, 0, 0),
+       GATE(CLK_SCLK_AUD_PCM, "sclk_aud_pcm", "div_sclk_aud_pcm",
+                       ENABLE_SCLK_AUD1, 2, 0, 0),
+       GATE(CLK_SCLK_I2S_BCLK, "sclk_i2s_bclk", "ioclk_i2s_bclk",
+                       ENABLE_SCLK_AUD1, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SCLK_AUD_I2S, "sclk_aud_i2s", "div_sclk_aud_i2s",
+                       ENABLE_SCLK_AUD1, 0, CLK_IGNORE_UNUSED, 0),
+};
+
+static struct samsung_cmu_info aud_cmu_info __initdata = {
+       .mux_clks               = aud_mux_clks,
+       .nr_mux_clks            = ARRAY_SIZE(aud_mux_clks),
+       .div_clks               = aud_div_clks,
+       .nr_div_clks            = ARRAY_SIZE(aud_div_clks),
+       .gate_clks              = aud_gate_clks,
+       .nr_gate_clks           = ARRAY_SIZE(aud_gate_clks),
+       .fixed_clks             = aud_fixed_clks,
+       .nr_fixed_clks          = ARRAY_SIZE(aud_fixed_clks),
+       .nr_clk_ids             = AUD_NR_CLK,
+       .clk_regs               = aud_clk_regs,
+       .nr_clk_regs            = ARRAY_SIZE(aud_clk_regs),
+};
+
+static void __init exynos5433_cmu_aud_init(struct device_node *np)
+{
+       samsung_cmu_register_one(np, &aud_cmu_info);
+}
+CLK_OF_DECLARE(exynos5433_cmu_aud, "samsung,exynos5433-cmu-aud",
+               exynos5433_cmu_aud_init);
+
+
+/*
+ * Register offset definitions for CMU_BUS{0|1|2}
+ */
+#define DIV_BUS                                0x0600
+#define DIV_STAT_BUS                   0x0700
+#define ENABLE_ACLK_BUS                        0x0800
+#define ENABLE_PCLK_BUS                        0x0900
+#define ENABLE_IP_BUS0                 0x0b00
+#define ENABLE_IP_BUS1                 0x0b04
+
+#define MUX_SEL_BUS2                   0x0200  /* Only for CMU_BUS2 */
+#define MUX_ENABLE_BUS2                        0x0300  /* Only for CMU_BUS2 */
+#define MUX_STAT_BUS2                  0x0400  /* Only for CMU_BUS2 */
+
+/* list of all parent clock list */
+PNAME(mout_aclk_bus2_400_p)    = { "oscclk", "aclk_bus2_400", };
+
+#define CMU_BUS_COMMON_CLK_REGS        \
+       DIV_BUS,                \
+       DIV_STAT_BUS,           \
+       ENABLE_ACLK_BUS,        \
+       ENABLE_PCLK_BUS,        \
+       ENABLE_IP_BUS0,         \
+       ENABLE_IP_BUS1
+
+static unsigned long bus01_clk_regs[] __initdata = {
+       CMU_BUS_COMMON_CLK_REGS,
+};
+
+static unsigned long bus2_clk_regs[] __initdata = {
+       MUX_SEL_BUS2,
+       MUX_ENABLE_BUS2,
+       MUX_STAT_BUS2,
+       CMU_BUS_COMMON_CLK_REGS,
+};
+
+static struct samsung_div_clock bus0_div_clks[] __initdata = {
+       /* DIV_BUS0 */
+       DIV(CLK_DIV_PCLK_BUS_133, "div_pclk_bus0_133", "aclk_bus0_400",
+                       DIV_BUS, 0, 3),
+};
+
+/* CMU_BUS0 clocks */
+static struct samsung_gate_clock bus0_gate_clks[] __initdata = {
+       /* ENABLE_ACLK_BUS0 */
+       GATE(CLK_ACLK_AHB2APB_BUSP, "aclk_ahb2apb_bus0p", "div_pclk_bus0_133",
+                       ENABLE_ACLK_BUS, 4, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_BUSNP_133, "aclk_bus0np_133", "div_pclk_bus0_133",
+                       ENABLE_ACLK_BUS, 2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_BUSND_400, "aclk_bus0nd_400", "aclk_bus0_400",
+                       ENABLE_ACLK_BUS, 0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_PCLK_BUS0 */
+       GATE(CLK_PCLK_BUSSRVND_133, "pclk_bus0srvnd_133", "div_pclk_bus0_133",
+                       ENABLE_PCLK_BUS, 2, 0, 0),
+       GATE(CLK_PCLK_PMU_BUS, "pclk_pmu_bus0", "div_pclk_bus0_133",
+                       ENABLE_PCLK_BUS, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SYSREG_BUS, "pclk_sysreg_bus0", "div_pclk_bus0_133",
+                       ENABLE_PCLK_BUS, 0, CLK_IGNORE_UNUSED, 0),
+};
+
+/* CMU_BUS1 clocks */
+static struct samsung_div_clock bus1_div_clks[] __initdata = {
+       /* DIV_BUS1 */
+       DIV(CLK_DIV_PCLK_BUS_133, "div_pclk_bus1_133", "aclk_bus1_400",
+                       DIV_BUS, 0, 3),
+};
+
+static struct samsung_gate_clock bus1_gate_clks[] __initdata = {
+       /* ENABLE_ACLK_BUS1 */
+       GATE(CLK_ACLK_AHB2APB_BUSP, "aclk_ahb2apb_bus1p", "div_pclk_bus1_133",
+                       ENABLE_ACLK_BUS, 4, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_BUSNP_133, "aclk_bus1np_133", "div_pclk_bus1_133",
+                       ENABLE_ACLK_BUS, 2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_BUSND_400, "aclk_bus1nd_400", "aclk_bus1_400",
+                       ENABLE_ACLK_BUS, 0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_PCLK_BUS1 */
+       GATE(CLK_PCLK_BUSSRVND_133, "pclk_bus1srvnd_133", "div_pclk_bus1_133",
+                       ENABLE_PCLK_BUS, 2, 0, 0),
+       GATE(CLK_PCLK_PMU_BUS, "pclk_pmu_bus1", "div_pclk_bus1_133",
+                       ENABLE_PCLK_BUS, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SYSREG_BUS, "pclk_sysreg_bus1", "div_pclk_bus1_133",
+                       ENABLE_PCLK_BUS, 0, CLK_IGNORE_UNUSED, 0),
+};
+
+/* CMU_BUS2 clocks */
+static struct samsung_mux_clock bus2_mux_clks[] __initdata = {
+       /* MUX_SEL_BUS2 */
+       MUX(CLK_MOUT_ACLK_BUS2_400_USER, "mout_aclk_bus2_400_user",
+                       mout_aclk_bus2_400_p, MUX_SEL_BUS2, 0, 1),
+};
+
+static struct samsung_div_clock bus2_div_clks[] __initdata = {
+       /* DIV_BUS2 */
+       DIV(CLK_DIV_PCLK_BUS_133, "div_pclk_bus2_133",
+                       "mout_aclk_bus2_400_user", DIV_BUS, 0, 3),
+};
+
+static struct samsung_gate_clock bus2_gate_clks[] __initdata = {
+       /* ENABLE_ACLK_BUS2 */
+       GATE(CLK_ACLK_AHB2APB_BUSP, "aclk_ahb2apb_bus2p", "div_pclk_bus2_133",
+                       ENABLE_ACLK_BUS, 3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_BUSNP_133, "aclk_bus2np_133", "div_pclk_bus2_133",
+                       ENABLE_ACLK_BUS, 2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_BUS2BEND_400, "aclk_bus2bend_400",
+                       "mout_aclk_bus2_400_user", ENABLE_ACLK_BUS,
+                       1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_BUS2RTND_400, "aclk_bus2rtnd_400",
+                       "mout_aclk_bus2_400_user", ENABLE_ACLK_BUS,
+                       0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_PCLK_BUS2 */
+       GATE(CLK_PCLK_BUSSRVND_133, "pclk_bus2srvnd_133", "div_pclk_bus2_133",
+                       ENABLE_PCLK_BUS, 2, 0, 0),
+       GATE(CLK_PCLK_PMU_BUS, "pclk_pmu_bus2", "div_pclk_bus2_133",
+                       ENABLE_PCLK_BUS, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SYSREG_BUS, "pclk_sysreg_bus2", "div_pclk_bus2_133",
+                       ENABLE_PCLK_BUS, 0, CLK_IGNORE_UNUSED, 0),
+};
+
+#define CMU_BUS_INFO_CLKS(id)                                          \
+       .div_clks               = bus##id##_div_clks,                   \
+       .nr_div_clks            = ARRAY_SIZE(bus##id##_div_clks),       \
+       .gate_clks              = bus##id##_gate_clks,                  \
+       .nr_gate_clks           = ARRAY_SIZE(bus##id##_gate_clks),      \
+       .nr_clk_ids             = BUSx_NR_CLK
+
+static struct samsung_cmu_info bus0_cmu_info __initdata = {
+       CMU_BUS_INFO_CLKS(0),
+       .clk_regs               = bus01_clk_regs,
+       .nr_clk_regs            = ARRAY_SIZE(bus01_clk_regs),
+};
+
+static struct samsung_cmu_info bus1_cmu_info __initdata = {
+       CMU_BUS_INFO_CLKS(1),
+       .clk_regs               = bus01_clk_regs,
+       .nr_clk_regs            = ARRAY_SIZE(bus01_clk_regs),
+};
+
+static struct samsung_cmu_info bus2_cmu_info __initdata = {
+       CMU_BUS_INFO_CLKS(2),
+       .mux_clks               = bus2_mux_clks,
+       .nr_mux_clks            = ARRAY_SIZE(bus2_mux_clks),
+       .clk_regs               = bus2_clk_regs,
+       .nr_clk_regs            = ARRAY_SIZE(bus2_clk_regs),
+};
+
+#define exynos5433_cmu_bus_init(id)                                    \
+static void __init exynos5433_cmu_bus##id##_init(struct device_node *np)\
+{                                                                      \
+       samsung_cmu_register_one(np, &bus##id##_cmu_info);              \
+}                                                                      \
+CLK_OF_DECLARE(exynos5433_cmu_bus##id,                                 \
+               "samsung,exynos5433-cmu-bus"#id,                        \
+               exynos5433_cmu_bus##id##_init)
+
+exynos5433_cmu_bus_init(0);
+exynos5433_cmu_bus_init(1);
+exynos5433_cmu_bus_init(2);
+
+/*
+ * Register offset definitions for CMU_G3D
+ */
+#define G3D_PLL_LOCK                   0x0000
+#define G3D_PLL_CON0                   0x0100
+#define G3D_PLL_CON1                   0x0104
+#define G3D_PLL_FREQ_DET               0x010c
+#define MUX_SEL_G3D                    0x0200
+#define MUX_ENABLE_G3D                 0x0300
+#define MUX_STAT_G3D                   0x0400
+#define DIV_G3D                                0x0600
+#define DIV_G3D_PLL_FREQ_DET           0x0604
+#define DIV_STAT_G3D                   0x0700
+#define DIV_STAT_G3D_PLL_FREQ_DET      0x0704
+#define ENABLE_ACLK_G3D                        0x0800
+#define ENABLE_PCLK_G3D                        0x0900
+#define ENABLE_SCLK_G3D                        0x0a00
+#define ENABLE_IP_G3D0                 0x0b00
+#define ENABLE_IP_G3D1                 0x0b04
+#define CLKOUT_CMU_G3D                 0x0c00
+#define CLKOUT_CMU_G3D_DIV_STAT                0x0c04
+#define CLK_STOPCTRL                   0x1000
+
+static unsigned long g3d_clk_regs[] __initdata = {
+       G3D_PLL_LOCK,
+       G3D_PLL_CON0,
+       G3D_PLL_CON1,
+       G3D_PLL_FREQ_DET,
+       MUX_SEL_G3D,
+       MUX_ENABLE_G3D,
+       MUX_STAT_G3D,
+       DIV_G3D,
+       DIV_G3D_PLL_FREQ_DET,
+       DIV_STAT_G3D,
+       DIV_STAT_G3D_PLL_FREQ_DET,
+       ENABLE_ACLK_G3D,
+       ENABLE_PCLK_G3D,
+       ENABLE_SCLK_G3D,
+       ENABLE_IP_G3D0,
+       ENABLE_IP_G3D1,
+       CLKOUT_CMU_G3D,
+       CLKOUT_CMU_G3D_DIV_STAT,
+       CLK_STOPCTRL,
+};
+
+/* list of all parent clock list */
+PNAME(mout_aclk_g3d_400_p)     = { "mout_g3d_pll", "aclk_g3d_400", };
+PNAME(mout_g3d_pll_p)          = { "oscclk", "fout_g3d_pll", };
+
+static struct samsung_pll_clock g3d_pll_clks[] __initdata = {
+       PLL(pll_35xx, CLK_FOUT_G3D_PLL, "fout_g3d_pll", "oscclk",
+               G3D_PLL_LOCK, G3D_PLL_CON0, exynos5443_pll_rates),
+};
+
+static struct samsung_mux_clock g3d_mux_clks[] __initdata = {
+       /* MUX_SEL_G3D */
+       MUX(CLK_MOUT_ACLK_G3D_400, "mout_aclk_g3d_400", mout_aclk_g3d_400_p,
+                       MUX_SEL_G3D, 8, 1),
+       MUX(CLK_MOUT_G3D_PLL, "mout_g3d_pll", mout_g3d_pll_p,
+                       MUX_SEL_G3D, 0, 1),
+};
+
+static struct samsung_div_clock g3d_div_clks[] __initdata = {
+       /* DIV_G3D */
+       DIV(CLK_DIV_SCLK_HPM_G3D, "div_sclk_hpm_g3d", "mout_g3d_pll", DIV_G3D,
+                       8, 2),
+       DIV(CLK_DIV_PCLK_G3D, "div_pclk_g3d", "div_aclk_g3d", DIV_G3D,
+                       4, 3),
+       DIV(CLK_DIV_ACLK_G3D, "div_aclk_g3d", "mout_aclk_g3d_400", DIV_G3D,
+                       0, 3),
+};
+
+static struct samsung_gate_clock g3d_gate_clks[] __initdata = {
+       /* ENABLE_ACLK_G3D */
+       GATE(CLK_ACLK_BTS_G3D1, "aclk_bts_g3d1", "div_aclk_g3d",
+                       ENABLE_ACLK_G3D, 7, 0, 0),
+       GATE(CLK_ACLK_BTS_G3D0, "aclk_bts_g3d0", "div_aclk_g3d",
+                       ENABLE_ACLK_G3D, 6, 0, 0),
+       GATE(CLK_ACLK_ASYNCAPBS_G3D, "aclk_asyncapbs_g3d", "div_pclk_g3d",
+                       ENABLE_ACLK_G3D, 5, 0, 0),
+       GATE(CLK_ACLK_ASYNCAPBM_G3D, "aclk_asyncapbm_g3d", "div_aclk_g3d",
+                       ENABLE_ACLK_G3D, 4, 0, 0),
+       GATE(CLK_ACLK_AHB2APB_G3DP, "aclk_ahb2apb_g3dp", "div_pclk_g3d",
+                       ENABLE_ACLK_G3D, 3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_G3DNP_150, "aclk_g3dnp_150", "div_pclk_g3d",
+                       ENABLE_ACLK_G3D, 2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_G3DND_600, "aclk_g3dnd_600", "div_aclk_g3d",
+                       ENABLE_ACLK_G3D, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_G3D, "aclk_g3d", "div_aclk_g3d",
+                       ENABLE_ACLK_G3D, 0, 0, 0),
+
+       /* ENABLE_PCLK_G3D */
+       GATE(CLK_PCLK_BTS_G3D1, "pclk_bts_g3d1", "div_pclk_g3d",
+                       ENABLE_PCLK_G3D, 3, 0, 0),
+       GATE(CLK_PCLK_BTS_G3D0, "pclk_bts_g3d0", "div_pclk_g3d",
+                       ENABLE_PCLK_G3D, 2, 0, 0),
+       GATE(CLK_PCLK_PMU_G3D, "pclk_pmu_g3d", "div_pclk_g3d",
+                       ENABLE_PCLK_G3D, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SYSREG_G3D, "pclk_sysreg_g3d", "div_pclk_g3d",
+                       ENABLE_PCLK_G3D, 0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_SCLK_G3D */
+       GATE(CLK_SCLK_HPM_G3D, "sclk_hpm_g3d", "div_sclk_hpm_g3d",
+                       ENABLE_SCLK_G3D, 0, 0, 0),
+};
+
+static struct samsung_cmu_info g3d_cmu_info __initdata = {
+       .pll_clks               = g3d_pll_clks,
+       .nr_pll_clks            = ARRAY_SIZE(g3d_pll_clks),
+       .mux_clks               = g3d_mux_clks,
+       .nr_mux_clks            = ARRAY_SIZE(g3d_mux_clks),
+       .div_clks               = g3d_div_clks,
+       .nr_div_clks            = ARRAY_SIZE(g3d_div_clks),
+       .gate_clks              = g3d_gate_clks,
+       .nr_gate_clks           = ARRAY_SIZE(g3d_gate_clks),
+       .nr_clk_ids             = G3D_NR_CLK,
+       .clk_regs               = g3d_clk_regs,
+       .nr_clk_regs            = ARRAY_SIZE(g3d_clk_regs),
+};
+
+static void __init exynos5433_cmu_g3d_init(struct device_node *np)
+{
+       samsung_cmu_register_one(np, &g3d_cmu_info);
+}
+CLK_OF_DECLARE(exynos5433_cmu_g3d, "samsung,exynos5433-cmu-g3d",
+               exynos5433_cmu_g3d_init);
+
+/*
+ * Register offset definitions for CMU_GSCL
+ */
+#define MUX_SEL_GSCL                           0x0200
+#define MUX_ENABLE_GSCL                                0x0300
+#define MUX_STAT_GSCL                          0x0400
+#define ENABLE_ACLK_GSCL                       0x0800
+#define ENABLE_ACLK_GSCL_SECURE_SMMU_GSCL0     0x0804
+#define ENABLE_ACLK_GSCL_SECURE_SMMU_GSCL1     0x0808
+#define ENABLE_ACLK_GSCL_SECURE_SMMU_GSCL2     0x080c
+#define ENABLE_PCLK_GSCL                       0x0900
+#define ENABLE_PCLK_GSCL_SECURE_SMMU_GSCL0     0x0904
+#define ENABLE_PCLK_GSCL_SECURE_SMMU_GSCL1     0x0908
+#define ENABLE_PCLK_GSCL_SECURE_SMMU_GSCL2     0x090c
+#define ENABLE_IP_GSCL0                                0x0b00
+#define ENABLE_IP_GSCL1                                0x0b04
+#define ENABLE_IP_GSCL_SECURE_SMMU_GSCL0       0x0b08
+#define ENABLE_IP_GSCL_SECURE_SMMU_GSCL1       0x0b0c
+#define ENABLE_IP_GSCL_SECURE_SMMU_GSCL2       0x0b10
+
+static unsigned long gscl_clk_regs[] __initdata = {
+       MUX_SEL_GSCL,
+       MUX_ENABLE_GSCL,
+       MUX_STAT_GSCL,
+       ENABLE_ACLK_GSCL,
+       ENABLE_ACLK_GSCL_SECURE_SMMU_GSCL0,
+       ENABLE_ACLK_GSCL_SECURE_SMMU_GSCL1,
+       ENABLE_ACLK_GSCL_SECURE_SMMU_GSCL2,
+       ENABLE_PCLK_GSCL,
+       ENABLE_PCLK_GSCL_SECURE_SMMU_GSCL0,
+       ENABLE_PCLK_GSCL_SECURE_SMMU_GSCL1,
+       ENABLE_PCLK_GSCL_SECURE_SMMU_GSCL2,
+       ENABLE_IP_GSCL0,
+       ENABLE_IP_GSCL1,
+       ENABLE_IP_GSCL_SECURE_SMMU_GSCL0,
+       ENABLE_IP_GSCL_SECURE_SMMU_GSCL1,
+       ENABLE_IP_GSCL_SECURE_SMMU_GSCL2,
+};
+
+/* list of all parent clock list */
+PNAME(aclk_gscl_111_user_p)    = { "oscclk", "aclk_gscl_111", };
+PNAME(aclk_gscl_333_user_p)    = { "oscclk", "aclk_gscl_333", };
+
+static struct samsung_mux_clock gscl_mux_clks[] __initdata = {
+       /* MUX_SEL_GSCL */
+       MUX(CLK_MOUT_ACLK_GSCL_111_USER, "mout_aclk_gscl_111_user",
+                       aclk_gscl_111_user_p, MUX_SEL_GSCL, 4, 1),
+       MUX(CLK_MOUT_ACLK_GSCL_333_USER, "mout_aclk_gscl_333_user",
+                       aclk_gscl_333_user_p, MUX_SEL_GSCL, 0, 1),
+};
+
+static struct samsung_gate_clock gscl_gate_clks[] __initdata = {
+       /* ENABLE_ACLK_GSCL */
+       GATE(CLK_ACLK_BTS_GSCL2, "aclk_bts_gscl2", "mout_aclk_gscl_333_user",
+                       ENABLE_ACLK_GSCL, 11, 0, 0),
+       GATE(CLK_ACLK_BTS_GSCL1, "aclk_bts_gscl1", "mout_aclk_gscl_333_user",
+                       ENABLE_ACLK_GSCL, 10, 0, 0),
+       GATE(CLK_ACLK_BTS_GSCL0, "aclk_bts_gscl0", "mout_aclk_gscl_333_user",
+                       ENABLE_ACLK_GSCL, 9, 0, 0),
+       GATE(CLK_ACLK_AHB2APB_GSCLP, "aclk_ahb2apb_gsclp",
+                       "mout_aclk_gscl_111_user", ENABLE_ACLK_GSCL,
+                       8, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_XIU_GSCLX, "aclk_xiu_gsclx", "mout_aclk_gscl_333_user",
+                       ENABLE_ACLK_GSCL, 7, 0, 0),
+       GATE(CLK_ACLK_GSCLNP_111, "aclk_gsclnp_111", "mout_aclk_gscl_111_user",
+                       ENABLE_ACLK_GSCL, 6, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_GSCLRTND_333, "aclk_gsclrtnd_333",
+                       "mout_aclk_gscl_333_user", ENABLE_ACLK_GSCL, 5, 0, 0),
+       GATE(CLK_ACLK_GSCLBEND_333, "aclk_gsclbend_333",
+                       "mout_aclk_gscl_333_user", ENABLE_ACLK_GSCL, 4, 0, 0),
+       GATE(CLK_ACLK_GSD, "aclk_gsd", "mout_aclk_gscl_333_user",
+                       ENABLE_ACLK_GSCL, 3, 0, 0),
+       GATE(CLK_ACLK_GSCL2, "aclk_gscl2", "mout_aclk_gscl_333_user",
+                       ENABLE_ACLK_GSCL, 2, 0, 0),
+       GATE(CLK_ACLK_GSCL1, "aclk_gscl1", "mout_aclk_gscl_333_user",
+                       ENABLE_ACLK_GSCL, 1, 0, 0),
+       GATE(CLK_ACLK_GSCL0, "aclk_gscl0", "mout_aclk_gscl_333_user",
+                       ENABLE_ACLK_GSCL, 0, 0, 0),
+
+       /* ENABLE_ACLK_GSCL_SECURE_SMMU_GSCL0 */
+       GATE(CLK_ACLK_SMMU_GSCL0, "aclk_smmu_gscl0", "mout_aclk_gscl_333_user",
+                       ENABLE_ACLK_GSCL_SECURE_SMMU_GSCL0, 0, 0, 0),
+
+       /* ENABLE_ACLK_GSCL_SECURE_SMMU_GSCL1 */
+       GATE(CLK_ACLK_SMMU_GSCL1, "aclk_smmu_gscl1", "mout_aclk_gscl_333_user",
+                       ENABLE_ACLK_GSCL_SECURE_SMMU_GSCL1, 0, 0, 0),
+
+       /* ENABLE_ACLK_GSCL_SECURE_SMMU_GSCL2 */
+       GATE(CLK_ACLK_SMMU_GSCL2, "aclk_smmu_gscl2", "mout_aclk_gscl_333_user",
+                       ENABLE_ACLK_GSCL_SECURE_SMMU_GSCL2, 0, 0, 0),
+
+       /* ENABLE_PCLK_GSCL */
+       GATE(CLK_PCLK_BTS_GSCL2, "pclk_bts_gscl2", "mout_aclk_gscl_111_user",
+                       ENABLE_PCLK_GSCL, 7, 0, 0),
+       GATE(CLK_PCLK_BTS_GSCL1, "pclk_bts_gscl1", "mout_aclk_gscl_111_user",
+                       ENABLE_PCLK_GSCL, 6, 0, 0),
+       GATE(CLK_PCLK_BTS_GSCL0, "pclk_bts_gscl0", "mout_aclk_gscl_111_user",
+                       ENABLE_PCLK_GSCL, 5, 0, 0),
+       GATE(CLK_PCLK_PMU_GSCL, "pclk_pmu_gscl", "mout_aclk_gscl_111_user",
+                       ENABLE_PCLK_GSCL, 4, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SYSREG_GSCL, "pclk_sysreg_gscl",
+                       "mout_aclk_gscl_111_user", ENABLE_PCLK_GSCL,
+                       3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_GSCL2, "pclk_gscl2", "mout_aclk_gscl_111_user",
+                       ENABLE_PCLK_GSCL, 2, 0, 0),
+       GATE(CLK_PCLK_GSCL1, "pclk_gscl1", "mout_aclk_gscl_111_user",
+                       ENABLE_PCLK_GSCL, 1, 0, 0),
+       GATE(CLK_PCLK_GSCL0, "pclk_gscl0", "mout_aclk_gscl_111_user",
+                       ENABLE_PCLK_GSCL, 0, 0, 0),
+
+       /* ENABLE_PCLK_GSCL_SECURE_SMMU_GSCL0 */
+       GATE(CLK_PCLK_SMMU_GSCL0, "pclk_smmu_gscl0", "mout_aclk_gscl_111_user",
+               ENABLE_PCLK_GSCL_SECURE_SMMU_GSCL0, 0, 0, 0),
+
+       /* ENABLE_PCLK_GSCL_SECURE_SMMU_GSCL1 */
+       GATE(CLK_PCLK_SMMU_GSCL1, "pclk_smmu_gscl1", "mout_aclk_gscl_111_user",
+               ENABLE_PCLK_GSCL_SECURE_SMMU_GSCL0, 0, 0, 0),
+
+       /* ENABLE_PCLK_GSCL_SECURE_SMMU_GSCL2 */
+       GATE(CLK_PCLK_SMMU_GSCL2, "pclk_smmu_gscl2", "mout_aclk_gscl_111_user",
+               ENABLE_PCLK_GSCL_SECURE_SMMU_GSCL0, 0, 0, 0),
+};
+
+static struct samsung_cmu_info gscl_cmu_info __initdata = {
+       .mux_clks               = gscl_mux_clks,
+       .nr_mux_clks            = ARRAY_SIZE(gscl_mux_clks),
+       .gate_clks              = gscl_gate_clks,
+       .nr_gate_clks           = ARRAY_SIZE(gscl_gate_clks),
+       .nr_clk_ids             = GSCL_NR_CLK,
+       .clk_regs               = gscl_clk_regs,
+       .nr_clk_regs            = ARRAY_SIZE(gscl_clk_regs),
+};
+
+static void __init exynos5433_cmu_gscl_init(struct device_node *np)
+{
+       samsung_cmu_register_one(np, &gscl_cmu_info);
+}
+CLK_OF_DECLARE(exynos5433_cmu_gscl, "samsung,exynos5433-cmu-gscl",
+               exynos5433_cmu_gscl_init);
+
+/*
+ * Register offset definitions for CMU_APOLLO
+ */
+#define APOLLO_PLL_LOCK                                0x0000
+#define APOLLO_PLL_CON0                                0x0100
+#define APOLLO_PLL_CON1                                0x0104
+#define APOLLO_PLL_FREQ_DET                    0x010c
+#define MUX_SEL_APOLLO0                                0x0200
+#define MUX_SEL_APOLLO1                                0x0204
+#define MUX_SEL_APOLLO2                                0x0208
+#define MUX_ENABLE_APOLLO0                     0x0300
+#define MUX_ENABLE_APOLLO1                     0x0304
+#define MUX_ENABLE_APOLLO2                     0x0308
+#define MUX_STAT_APOLLO0                       0x0400
+#define MUX_STAT_APOLLO1                       0x0404
+#define MUX_STAT_APOLLO2                       0x0408
+#define DIV_APOLLO0                            0x0600
+#define DIV_APOLLO1                            0x0604
+#define DIV_APOLLO_PLL_FREQ_DET                        0x0608
+#define DIV_STAT_APOLLO0                       0x0700
+#define DIV_STAT_APOLLO1                       0x0704
+#define DIV_STAT_APOLLO_PLL_FREQ_DET           0x0708
+#define ENABLE_ACLK_APOLLO                     0x0800
+#define ENABLE_PCLK_APOLLO                     0x0900
+#define ENABLE_SCLK_APOLLO                     0x0a00
+#define ENABLE_IP_APOLLO0                      0x0b00
+#define ENABLE_IP_APOLLO1                      0x0b04
+#define CLKOUT_CMU_APOLLO                      0x0c00
+#define CLKOUT_CMU_APOLLO_DIV_STAT             0x0c04
+#define ARMCLK_STOPCTRL                                0x1000
+#define APOLLO_PWR_CTRL                                0x1020
+#define APOLLO_PWR_CTRL2                       0x1024
+#define APOLLO_INTR_SPREAD_ENABLE              0x1080
+#define APOLLO_INTR_SPREAD_USE_STANDBYWFI      0x1084
+#define APOLLO_INTR_SPREAD_BLOCKING_DURATION   0x1088
+
+static unsigned long apollo_clk_regs[] __initdata = {
+       APOLLO_PLL_LOCK,
+       APOLLO_PLL_CON0,
+       APOLLO_PLL_CON1,
+       APOLLO_PLL_FREQ_DET,
+       MUX_SEL_APOLLO0,
+       MUX_SEL_APOLLO1,
+       MUX_SEL_APOLLO2,
+       MUX_ENABLE_APOLLO0,
+       MUX_ENABLE_APOLLO1,
+       MUX_ENABLE_APOLLO2,
+       MUX_STAT_APOLLO0,
+       MUX_STAT_APOLLO1,
+       MUX_STAT_APOLLO2,
+       DIV_APOLLO0,
+       DIV_APOLLO1,
+       DIV_APOLLO_PLL_FREQ_DET,
+       DIV_STAT_APOLLO0,
+       DIV_STAT_APOLLO1,
+       DIV_STAT_APOLLO_PLL_FREQ_DET,
+       ENABLE_ACLK_APOLLO,
+       ENABLE_PCLK_APOLLO,
+       ENABLE_SCLK_APOLLO,
+       ENABLE_IP_APOLLO0,
+       ENABLE_IP_APOLLO1,
+       CLKOUT_CMU_APOLLO,
+       CLKOUT_CMU_APOLLO_DIV_STAT,
+       ARMCLK_STOPCTRL,
+       APOLLO_PWR_CTRL,
+       APOLLO_PWR_CTRL2,
+       APOLLO_INTR_SPREAD_ENABLE,
+       APOLLO_INTR_SPREAD_USE_STANDBYWFI,
+       APOLLO_INTR_SPREAD_BLOCKING_DURATION,
+};
+
+/* list of all parent clock list */
+PNAME(mout_apollo_pll_p)               = { "oscclk", "fout_apollo_pll", };
+PNAME(mout_bus_pll_apollo_user_p)      = { "oscclk", "sclk_bus_pll_apollo", };
+PNAME(mout_apollo_p)                   = { "mout_apollo_pll",
+                                           "mout_bus_pll_apollo_user", };
+
+static struct samsung_pll_clock apollo_pll_clks[] __initdata = {
+       PLL(pll_35xx, CLK_FOUT_APOLLO_PLL, "fout_apollo_pll", "oscclk",
+               APOLLO_PLL_LOCK, APOLLO_PLL_CON0, exynos5443_pll_rates),
+};
+
+static struct samsung_mux_clock apollo_mux_clks[] __initdata = {
+       /* MUX_SEL_APOLLO0 */
+       MUX_F(CLK_MOUT_APOLLO_PLL, "mout_apollo_pll", mout_apollo_pll_p,
+                       MUX_SEL_APOLLO0, 0, 1, 0, CLK_MUX_READ_ONLY),
+
+       /* MUX_SEL_APOLLO1 */
+       MUX(CLK_MOUT_BUS_PLL_APOLLO_USER, "mout_bus_pll_apollo_user",
+                       mout_bus_pll_apollo_user_p, MUX_SEL_APOLLO1, 0, 1),
+
+       /* MUX_SEL_APOLLO2 */
+       MUX_F(CLK_MOUT_APOLLO, "mout_apollo", mout_apollo_p, MUX_SEL_APOLLO2,
+                       0, 1, 0, CLK_MUX_READ_ONLY),
+};
+
+static struct samsung_div_clock apollo_div_clks[] __initdata = {
+       /* DIV_APOLLO0 */
+       DIV_F(CLK_DIV_CNTCLK_APOLLO, "div_cntclk_apollo", "div_apollo2",
+                       DIV_APOLLO0, 24, 3, CLK_GET_RATE_NOCACHE,
+                       CLK_DIVIDER_READ_ONLY),
+       DIV_F(CLK_DIV_PCLK_DBG_APOLLO, "div_pclk_dbg_apollo", "div_apollo2",
+                       DIV_APOLLO0, 20, 3, CLK_GET_RATE_NOCACHE,
+                       CLK_DIVIDER_READ_ONLY),
+       DIV_F(CLK_DIV_ATCLK_APOLLO, "div_atclk_apollo", "div_apollo2",
+                       DIV_APOLLO0, 16, 3, CLK_GET_RATE_NOCACHE,
+                       CLK_DIVIDER_READ_ONLY),
+       DIV_F(CLK_DIV_PCLK_APOLLO, "div_pclk_apollo", "div_apollo2",
+                       DIV_APOLLO0, 12, 3, CLK_GET_RATE_NOCACHE,
+                       CLK_DIVIDER_READ_ONLY),
+       DIV_F(CLK_DIV_ACLK_APOLLO, "div_aclk_apollo", "div_apollo2",
+                       DIV_APOLLO0, 8, 3, CLK_GET_RATE_NOCACHE,
+                       CLK_DIVIDER_READ_ONLY),
+       DIV_F(CLK_DIV_APOLLO2, "div_apollo2", "div_apollo1",
+                       DIV_APOLLO0, 4, 3, CLK_GET_RATE_NOCACHE,
+                       CLK_DIVIDER_READ_ONLY),
+       DIV_F(CLK_DIV_APOLLO1, "div_apollo1", "mout_apollo",
+                       DIV_APOLLO0, 0, 3, CLK_GET_RATE_NOCACHE,
+                       CLK_DIVIDER_READ_ONLY),
+
+       /* DIV_APOLLO1 */
+       DIV_F(CLK_DIV_SCLK_HPM_APOLLO, "div_sclk_hpm_apollo", "mout_apollo",
+                       DIV_APOLLO1, 4, 3, CLK_GET_RATE_NOCACHE,
+                       CLK_DIVIDER_READ_ONLY),
+       DIV_F(CLK_DIV_APOLLO_PLL, "div_apollo_pll", "mout_apollo",
+                       DIV_APOLLO1, 0, 3, CLK_GET_RATE_NOCACHE,
+                       CLK_DIVIDER_READ_ONLY),
+};
+
+static struct samsung_gate_clock apollo_gate_clks[] __initdata = {
+       /* ENABLE_ACLK_APOLLO */
+       GATE(CLK_ACLK_ASATBSLV_APOLLO_3_CSSYS, "aclk_asatbslv_apollo_3_cssys",
+                       "div_atclk_apollo", ENABLE_ACLK_APOLLO,
+                       6, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASATBSLV_APOLLO_2_CSSYS, "aclk_asatbslv_apollo_2_cssys",
+                       "div_atclk_apollo", ENABLE_ACLK_APOLLO,
+                       5, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASATBSLV_APOLLO_1_CSSYS, "aclk_asatbslv_apollo_1_cssys",
+                       "div_atclk_apollo", ENABLE_ACLK_APOLLO,
+                       4, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASATBSLV_APOLLO_0_CSSYS, "aclk_asatbslv_apollo_0_cssys",
+                       "div_atclk_apollo", ENABLE_ACLK_APOLLO,
+                       3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCACES_APOLLO_CCI, "aclk_asyncaces_apollo_cci",
+                       "div_aclk_apollo", ENABLE_ACLK_APOLLO,
+                       2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AHB2APB_APOLLOP, "aclk_ahb2apb_apollop",
+                       "div_pclk_apollo", ENABLE_ACLK_APOLLO,
+                       1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_APOLLONP_200, "aclk_apollonp_200",
+                       "div_pclk_apollo", ENABLE_ACLK_APOLLO,
+                       0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_PCLK_APOLLO */
+       GATE(CLK_PCLK_ASAPBMST_CSSYS_APOLLO, "pclk_asapbmst_cssys_apollo",
+                       "div_pclk_dbg_apollo", ENABLE_PCLK_APOLLO,
+                       2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_PMU_APOLLO, "pclk_pmu_apollo", "div_pclk_apollo",
+                       ENABLE_PCLK_APOLLO, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SYSREG_APOLLO, "pclk_sysreg_apollo",
+                       "div_pclk_apollo", ENABLE_PCLK_APOLLO,
+                       0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_SCLK_APOLLO */
+       GATE(CLK_CNTCLK_APOLLO, "cntclk_apollo", "div_cntclk_apollo",
+                       ENABLE_SCLK_APOLLO, 3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SCLK_HPM_APOLLO, "sclk_hpm_apollo", "div_sclk_hpm_apollo",
+                       ENABLE_SCLK_APOLLO, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SCLK_APOLLO, "sclk_apollo", "div_apollo_pll",
+                       ENABLE_SCLK_APOLLO, 0, CLK_IGNORE_UNUSED, 0),
+};
+
+static struct samsung_cmu_info apollo_cmu_info __initdata = {
+       .pll_clks               = apollo_pll_clks,
+       .nr_pll_clks            = ARRAY_SIZE(apollo_pll_clks),
+       .mux_clks               = apollo_mux_clks,
+       .nr_mux_clks            = ARRAY_SIZE(apollo_mux_clks),
+       .div_clks               = apollo_div_clks,
+       .nr_div_clks            = ARRAY_SIZE(apollo_div_clks),
+       .gate_clks              = apollo_gate_clks,
+       .nr_gate_clks           = ARRAY_SIZE(apollo_gate_clks),
+       .nr_clk_ids             = APOLLO_NR_CLK,
+       .clk_regs               = apollo_clk_regs,
+       .nr_clk_regs            = ARRAY_SIZE(apollo_clk_regs),
+};
+
+static void __init exynos5433_cmu_apollo_init(struct device_node *np)
+{
+       samsung_cmu_register_one(np, &apollo_cmu_info);
+}
+CLK_OF_DECLARE(exynos5433_cmu_apollo, "samsung,exynos5433-cmu-apollo",
+               exynos5433_cmu_apollo_init);
+
+/*
+ * Register offset definitions for CMU_ATLAS
+ */
+#define ATLAS_PLL_LOCK                         0x0000
+#define ATLAS_PLL_CON0                         0x0100
+#define ATLAS_PLL_CON1                         0x0104
+#define ATLAS_PLL_FREQ_DET                     0x010c
+#define MUX_SEL_ATLAS0                         0x0200
+#define MUX_SEL_ATLAS1                         0x0204
+#define MUX_SEL_ATLAS2                         0x0208
+#define MUX_ENABLE_ATLAS0                      0x0300
+#define MUX_ENABLE_ATLAS1                      0x0304
+#define MUX_ENABLE_ATLAS2                      0x0308
+#define MUX_STAT_ATLAS0                                0x0400
+#define MUX_STAT_ATLAS1                                0x0404
+#define MUX_STAT_ATLAS2                                0x0408
+#define DIV_ATLAS0                             0x0600
+#define DIV_ATLAS1                             0x0604
+#define DIV_ATLAS_PLL_FREQ_DET                 0x0608
+#define DIV_STAT_ATLAS0                                0x0700
+#define DIV_STAT_ATLAS1                                0x0704
+#define DIV_STAT_ATLAS_PLL_FREQ_DET            0x0708
+#define ENABLE_ACLK_ATLAS                      0x0800
+#define ENABLE_PCLK_ATLAS                      0x0900
+#define ENABLE_SCLK_ATLAS                      0x0a00
+#define ENABLE_IP_ATLAS0                       0x0b00
+#define ENABLE_IP_ATLAS1                       0x0b04
+#define CLKOUT_CMU_ATLAS                       0x0c00
+#define CLKOUT_CMU_ATLAS_DIV_STAT              0x0c04
+#define ARMCLK_STOPCTRL                                0x1000
+#define ATLAS_PWR_CTRL                         0x1020
+#define ATLAS_PWR_CTRL2                                0x1024
+#define ATLAS_INTR_SPREAD_ENABLE               0x1080
+#define ATLAS_INTR_SPREAD_USE_STANDBYWFI       0x1084
+#define ATLAS_INTR_SPREAD_BLOCKING_DURATION    0x1088
+
+static unsigned long atlas_clk_regs[] __initdata = {
+       ATLAS_PLL_LOCK,
+       ATLAS_PLL_CON0,
+       ATLAS_PLL_CON1,
+       ATLAS_PLL_FREQ_DET,
+       MUX_SEL_ATLAS0,
+       MUX_SEL_ATLAS1,
+       MUX_SEL_ATLAS2,
+       MUX_ENABLE_ATLAS0,
+       MUX_ENABLE_ATLAS1,
+       MUX_ENABLE_ATLAS2,
+       MUX_STAT_ATLAS0,
+       MUX_STAT_ATLAS1,
+       MUX_STAT_ATLAS2,
+       DIV_ATLAS0,
+       DIV_ATLAS1,
+       DIV_ATLAS_PLL_FREQ_DET,
+       DIV_STAT_ATLAS0,
+       DIV_STAT_ATLAS1,
+       DIV_STAT_ATLAS_PLL_FREQ_DET,
+       ENABLE_ACLK_ATLAS,
+       ENABLE_PCLK_ATLAS,
+       ENABLE_SCLK_ATLAS,
+       ENABLE_IP_ATLAS0,
+       ENABLE_IP_ATLAS1,
+       CLKOUT_CMU_ATLAS,
+       CLKOUT_CMU_ATLAS_DIV_STAT,
+       ARMCLK_STOPCTRL,
+       ATLAS_PWR_CTRL,
+       ATLAS_PWR_CTRL2,
+       ATLAS_INTR_SPREAD_ENABLE,
+       ATLAS_INTR_SPREAD_USE_STANDBYWFI,
+       ATLAS_INTR_SPREAD_BLOCKING_DURATION,
+};
+
+/* list of all parent clock list */
+PNAME(mout_atlas_pll_p)                        = { "oscclk", "fout_atlas_pll", };
+PNAME(mout_bus_pll_atlas_user_p)       = { "oscclk", "sclk_bus_pll_atlas", };
+PNAME(mout_atlas_p)                    = { "mout_atlas_pll",
+                                           "mout_bus_pll_atlas_user", };
+
+static struct samsung_pll_clock atlas_pll_clks[] __initdata = {
+       PLL(pll_35xx, CLK_FOUT_ATLAS_PLL, "fout_atlas_pll", "oscclk",
+               ATLAS_PLL_LOCK, ATLAS_PLL_CON0, exynos5443_pll_rates),
+};
+
+static struct samsung_mux_clock atlas_mux_clks[] __initdata = {
+       /* MUX_SEL_ATLAS0 */
+       MUX_F(CLK_MOUT_ATLAS_PLL, "mout_atlas_pll", mout_atlas_pll_p,
+                       MUX_SEL_ATLAS0, 0, 1, 0, CLK_MUX_READ_ONLY),
+
+       /* MUX_SEL_ATLAS1 */
+       MUX(CLK_MOUT_BUS_PLL_ATLAS_USER, "mout_bus_pll_atlas_user",
+                       mout_bus_pll_atlas_user_p, MUX_SEL_ATLAS1, 0, 1),
+
+       /* MUX_SEL_ATLAS2 */
+       MUX_F(CLK_MOUT_ATLAS, "mout_atlas", mout_atlas_p, MUX_SEL_ATLAS2,
+                       0, 1, 0, CLK_MUX_READ_ONLY),
+};
+
+static struct samsung_div_clock atlas_div_clks[] __initdata = {
+       /* DIV_ATLAS0 */
+       DIV_F(CLK_DIV_CNTCLK_ATLAS, "div_cntclk_atlas", "div_atlas2",
+                       DIV_ATLAS0, 24, 3, CLK_GET_RATE_NOCACHE,
+                       CLK_DIVIDER_READ_ONLY),
+       DIV_F(CLK_DIV_PCLK_DBG_ATLAS, "div_pclk_dbg_atlas", "div_atclk_atlas",
+                       DIV_ATLAS0, 20, 3, CLK_GET_RATE_NOCACHE,
+                       CLK_DIVIDER_READ_ONLY),
+       DIV_F(CLK_DIV_ATCLK_ATLASO, "div_atclk_atlas", "div_atlas2",
+                       DIV_ATLAS0, 16, 3, CLK_GET_RATE_NOCACHE,
+                       CLK_DIVIDER_READ_ONLY),
+       DIV_F(CLK_DIV_PCLK_ATLAS, "div_pclk_atlas", "div_atlas2",
+                       DIV_ATLAS0, 12, 3, CLK_GET_RATE_NOCACHE,
+                       CLK_DIVIDER_READ_ONLY),
+       DIV_F(CLK_DIV_ACLK_ATLAS, "div_aclk_atlas", "div_atlas2",
+                       DIV_ATLAS0, 8, 3, CLK_GET_RATE_NOCACHE,
+                       CLK_DIVIDER_READ_ONLY),
+       DIV_F(CLK_DIV_ATLAS2, "div_atlas2", "div_atlas1",
+                       DIV_ATLAS0, 4, 3, CLK_GET_RATE_NOCACHE,
+                       CLK_DIVIDER_READ_ONLY),
+       DIV_F(CLK_DIV_ATLAS1, "div_atlas1", "mout_atlas",
+                       DIV_ATLAS0, 0, 3, CLK_GET_RATE_NOCACHE,
+                       CLK_DIVIDER_READ_ONLY),
+
+       /* DIV_ATLAS1 */
+       DIV_F(CLK_DIV_SCLK_HPM_ATLAS, "div_sclk_hpm_atlas", "mout_atlas",
+                       DIV_ATLAS1, 4, 3, CLK_GET_RATE_NOCACHE,
+                       CLK_DIVIDER_READ_ONLY),
+       DIV_F(CLK_DIV_ATLAS_PLL, "div_atlas_pll", "mout_atlas",
+                       DIV_ATLAS1, 0, 3, CLK_GET_RATE_NOCACHE,
+                       CLK_DIVIDER_READ_ONLY),
+};
+
+static struct samsung_gate_clock atlas_gate_clks[] __initdata = {
+       /* ENABLE_ACLK_ATLAS */
+       GATE(CLK_ACLK_ATB_AUD_CSSYS, "aclk_atb_aud_cssys",
+                       "div_atclk_atlas", ENABLE_ACLK_ATLAS,
+                       9, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ATB_APOLLO3_CSSYS, "aclk_atb_apollo3_cssys",
+                       "div_atclk_atlas", ENABLE_ACLK_ATLAS,
+                       8, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ATB_APOLLO2_CSSYS, "aclk_atb_apollo2_cssys",
+                       "div_atclk_atlas", ENABLE_ACLK_ATLAS,
+                       7, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ATB_APOLLO1_CSSYS, "aclk_atb_apollo1_cssys",
+                       "div_atclk_atlas", ENABLE_ACLK_ATLAS,
+                       6, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ATB_APOLLO0_CSSYS, "aclk_atb_apollo0_cssys",
+                       "div_atclk_atlas", ENABLE_ACLK_ATLAS,
+                       5, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAHBS_CSSYS_SSS, "aclk_asyncahbs_cssys_sss",
+                       "div_atclk_atlas", ENABLE_ACLK_ATLAS,
+                       4, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIS_CSSYS_CCIX, "aclk_asyncaxis_cssys_ccix",
+                       "div_pclk_dbg_atlas", ENABLE_ACLK_ATLAS,
+                       3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCACES_ATLAS_CCI, "aclk_asyncaces_atlas_cci",
+                       "div_aclk_atlas", ENABLE_ACLK_ATLAS,
+                       2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AHB2APB_ATLASP, "aclk_ahb2apb_atlasp", "div_pclk_atlas",
+                       ENABLE_ACLK_ATLAS, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ATLASNP_200, "aclk_atlasnp_200", "div_pclk_atlas",
+                       ENABLE_ACLK_ATLAS, 0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_PCLK_ATLAS */
+       GATE(CLK_PCLK_ASYNCAPB_AUD_CSSYS, "pclk_asyncapb_aud_cssys",
+                       "div_pclk_dbg_atlas", ENABLE_PCLK_ATLAS,
+                       5, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_ASYNCAPB_ISP_CSSYS, "pclk_asyncapb_isp_cssys",
+                       "div_pclk_dbg_atlas", ENABLE_PCLK_ATLAS,
+                       4, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_ASYNCAPB_APOLLO_CSSYS, "pclk_asyncapb_apollo_cssys",
+                       "div_pclk_dbg_atlas", ENABLE_PCLK_ATLAS,
+                       3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_PMU_ATLAS, "pclk_pmu_atlas", "div_pclk_atlas",
+                       ENABLE_PCLK_ATLAS, 2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SYSREG_ATLAS, "pclk_sysreg_atlas", "div_pclk_atlas",
+                       ENABLE_PCLK_ATLAS, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SECJTAG, "pclk_secjtag", "div_pclk_dbg_atlas",
+                       ENABLE_PCLK_ATLAS, 0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_SCLK_ATLAS */
+       GATE(CLK_CNTCLK_ATLAS, "cntclk_atlas", "div_cntclk_atlas",
+                       ENABLE_SCLK_ATLAS, 10, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SCLK_HPM_ATLAS, "sclk_hpm_atlas", "div_sclk_hpm_atlas",
+                       ENABLE_SCLK_ATLAS, 7, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_TRACECLK, "traceclk", "div_atclk_atlas",
+                       ENABLE_SCLK_ATLAS, 6, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_CTMCLK, "ctmclk", "div_atclk_atlas",
+                       ENABLE_SCLK_ATLAS, 5, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_HCLK_CSSYS, "hclk_cssys", "div_atclk_atlas",
+                       ENABLE_SCLK_ATLAS, 4, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_DBG_CSSYS, "pclk_dbg_cssys", "div_pclk_dbg_atlas",
+                       ENABLE_SCLK_ATLAS, 3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_DBG, "pclk_dbg", "div_pclk_dbg_atlas",
+                       ENABLE_SCLK_ATLAS, 2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ATCLK, "atclk", "div_atclk_atlas",
+                       ENABLE_SCLK_ATLAS, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SCLK_ATLAS, "sclk_atlas", "div_atlas2",
+                       ENABLE_SCLK_ATLAS, 0, CLK_IGNORE_UNUSED, 0),
+};
+
+static struct samsung_cmu_info atlas_cmu_info __initdata = {
+       .pll_clks               = atlas_pll_clks,
+       .nr_pll_clks            = ARRAY_SIZE(atlas_pll_clks),
+       .mux_clks               = atlas_mux_clks,
+       .nr_mux_clks            = ARRAY_SIZE(atlas_mux_clks),
+       .div_clks               = atlas_div_clks,
+       .nr_div_clks            = ARRAY_SIZE(atlas_div_clks),
+       .gate_clks              = atlas_gate_clks,
+       .nr_gate_clks           = ARRAY_SIZE(atlas_gate_clks),
+       .nr_clk_ids             = ATLAS_NR_CLK,
+       .clk_regs               = atlas_clk_regs,
+       .nr_clk_regs            = ARRAY_SIZE(atlas_clk_regs),
+};
+
+static void __init exynos5433_cmu_atlas_init(struct device_node *np)
+{
+       samsung_cmu_register_one(np, &atlas_cmu_info);
+}
+CLK_OF_DECLARE(exynos5433_cmu_atlas, "samsung,exynos5433-cmu-atlas",
+               exynos5433_cmu_atlas_init);
+
+/*
+ * Register offset definitions for CMU_MSCL
+ */
+#define MUX_SEL_MSCL0                                  0x0200
+#define MUX_SEL_MSCL1                                  0x0204
+#define MUX_ENABLE_MSCL0                               0x0300
+#define MUX_ENABLE_MSCL1                               0x0304
+#define MUX_STAT_MSCL0                                 0x0400
+#define MUX_STAT_MSCL1                                 0x0404
+#define DIV_MSCL                                       0x0600
+#define DIV_STAT_MSCL                                  0x0700
+#define ENABLE_ACLK_MSCL                               0x0800
+#define ENABLE_ACLK_MSCL_SECURE_SMMU_M2MSCALER0                0x0804
+#define ENABLE_ACLK_MSCL_SECURE_SMMU_M2MSCALER1                0x0808
+#define ENABLE_ACLK_MSCL_SECURE_SMMU_JPEG              0x080c
+#define ENABLE_PCLK_MSCL                               0x0900
+#define ENABLE_PCLK_MSCL_SECURE_SMMU_M2MSCALER0                0x0904
+#define ENABLE_PCLK_MSCL_SECURE_SMMU_M2MSCALER1                0x0908
+#define ENABLE_PCLK_MSCL_SECURE_SMMU_JPEG              0x000c
+#define ENABLE_SCLK_MSCL                               0x0a00
+#define ENABLE_IP_MSCL0                                        0x0b00
+#define ENABLE_IP_MSCL1                                        0x0b04
+#define ENABLE_IP_MSCL_SECURE_SMMU_M2MSCALER0          0x0b08
+#define ENABLE_IP_MSCL_SECURE_SMMU_M2MSCALER1          0x0b0c
+#define ENABLE_IP_MSCL_SECURE_SMMU_JPEG                        0x0b10
+
+static unsigned long mscl_clk_regs[] __initdata = {
+       MUX_SEL_MSCL0,
+       MUX_SEL_MSCL1,
+       MUX_ENABLE_MSCL0,
+       MUX_ENABLE_MSCL1,
+       MUX_STAT_MSCL0,
+       MUX_STAT_MSCL1,
+       DIV_MSCL,
+       DIV_STAT_MSCL,
+       ENABLE_ACLK_MSCL,
+       ENABLE_ACLK_MSCL_SECURE_SMMU_M2MSCALER0,
+       ENABLE_ACLK_MSCL_SECURE_SMMU_M2MSCALER1,
+       ENABLE_ACLK_MSCL_SECURE_SMMU_JPEG,
+       ENABLE_PCLK_MSCL,
+       ENABLE_PCLK_MSCL_SECURE_SMMU_M2MSCALER0,
+       ENABLE_PCLK_MSCL_SECURE_SMMU_M2MSCALER1,
+       ENABLE_PCLK_MSCL_SECURE_SMMU_JPEG,
+       ENABLE_SCLK_MSCL,
+       ENABLE_IP_MSCL0,
+       ENABLE_IP_MSCL1,
+       ENABLE_IP_MSCL_SECURE_SMMU_M2MSCALER0,
+       ENABLE_IP_MSCL_SECURE_SMMU_M2MSCALER1,
+       ENABLE_IP_MSCL_SECURE_SMMU_JPEG,
+};
+
+/* list of all parent clock list */
+PNAME(mout_sclk_jpeg_user_p)           = { "oscclk", "sclk_jpeg_mscl", };
+PNAME(mout_aclk_mscl_400_user_p)       = { "oscclk", "aclk_mscl_400", };
+PNAME(mout_sclk_jpeg_p)                        = { "mout_sclk_jpeg_user",
+                                       "mout_aclk_mscl_400_user", };
+
+static struct samsung_mux_clock mscl_mux_clks[] __initdata = {
+       /* MUX_SEL_MSCL0 */
+       MUX(CLK_MOUT_SCLK_JPEG_USER, "mout_sclk_jpeg_user",
+                       mout_sclk_jpeg_user_p, MUX_SEL_MSCL0, 4, 1),
+       MUX(CLK_MOUT_ACLK_MSCL_400_USER, "mout_aclk_mscl_400_user",
+                       mout_aclk_mscl_400_user_p, MUX_SEL_MSCL0, 0, 1),
+
+       /* MUX_SEL_MSCL1 */
+       MUX(CLK_MOUT_SCLK_JPEG, "mout_sclk_jpeg", mout_sclk_jpeg_p,
+                       MUX_SEL_MSCL1, 0, 1),
+};
+
+static struct samsung_div_clock mscl_div_clks[] __initdata = {
+       /* DIV_MSCL */
+       DIV(CLK_DIV_PCLK_MSCL, "div_pclk_mscl", "mout_aclk_mscl_400_user",
+                       DIV_MSCL, 0, 3),
+};
+
+static struct samsung_gate_clock mscl_gate_clks[] __initdata = {
+       /* ENABLE_ACLK_MSCL */
+       GATE(CLK_ACLK_BTS_JPEG, "aclk_bts_jpeg", "mout_aclk_mscl_400_user",
+                       ENABLE_ACLK_MSCL, 9, 0, 0),
+       GATE(CLK_ACLK_BTS_M2MSCALER1, "aclk_bts_m2mscaler1",
+                       "mout_aclk_mscl_400_user", ENABLE_ACLK_MSCL, 8, 0, 0),
+       GATE(CLK_ACLK_BTS_M2MSCALER0, "aclk_bts_m2mscaler0",
+                       "mout_aclk_mscl_400_user", ENABLE_ACLK_MSCL, 7, 0, 0),
+       GATE(CLK_ACLK_AHB2APB_MSCL0P, "aclk_abh2apb_mscl0p", "div_pclk_mscl",
+                       ENABLE_ACLK_MSCL, 6, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_XIU_MSCLX, "aclk_xiu_msclx", "mout_aclk_mscl_400_user",
+                       ENABLE_ACLK_MSCL, 5, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_MSCLNP_100, "aclk_msclnp_100", "div_pclk_mscl",
+                       ENABLE_ACLK_MSCL, 4, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_MSCLND_400, "aclk_msclnd_400", "mout_aclk_mscl_400_user",
+                       ENABLE_ACLK_MSCL, 3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_JPEG, "aclk_jpeg", "mout_aclk_mscl_400_user",
+                       ENABLE_ACLK_MSCL, 2, 0, 0),
+       GATE(CLK_ACLK_M2MSCALER1, "aclk_m2mscaler1", "mout_aclk_mscl_400_user",
+                       ENABLE_ACLK_MSCL, 1, 0, 0),
+       GATE(CLK_ACLK_M2MSCALER0, "aclk_m2mscaler0", "mout_aclk_mscl_400_user",
+                       ENABLE_ACLK_MSCL, 0, 0, 0),
+
+       /* ENABLE_ACLK_MSCL_SECURE_SMMU_M2MSCALER0 */
+       GATE(CLK_ACLK_SMMU_M2MSCALER0, "aclk_smmu_m2mscaler0",
+                       "mout_aclk_mscl_400_user",
+                       ENABLE_ACLK_MSCL_SECURE_SMMU_M2MSCALER0,
+                       0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_ACLK_MSCL_SECURE_SMMU_M2MSCALER1 */
+       GATE(CLK_ACLK_SMMU_M2MSCALER1, "aclk_smmu_m2mscaler1",
+                       "mout_aclk_mscl_400_user",
+                       ENABLE_ACLK_MSCL_SECURE_SMMU_M2MSCALER1,
+                       0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_ACLK_MSCL_SECURE_SMMU_JPEG */
+       GATE(CLK_ACLK_SMMU_JPEG, "aclk_smmu_jpeg", "mout_aclk_mscl_400_user",
+                       ENABLE_ACLK_MSCL_SECURE_SMMU_JPEG,
+                       0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_PCLK_MSCL */
+       GATE(CLK_PCLK_BTS_JPEG, "pclk_bts_jpeg", "div_pclk_mscl",
+                       ENABLE_PCLK_MSCL, 7, 0, 0),
+       GATE(CLK_PCLK_BTS_M2MSCALER1, "pclk_bts_m2mscaler1", "div_pclk_mscl",
+                       ENABLE_PCLK_MSCL, 6, 0, 0),
+       GATE(CLK_PCLK_BTS_M2MSCALER0, "pclk_bts_m2mscaler0", "div_pclk_mscl",
+                       ENABLE_PCLK_MSCL, 5, 0, 0),
+       GATE(CLK_PCLK_PMU_MSCL, "pclk_pmu_mscl", "div_pclk_mscl",
+                       ENABLE_PCLK_MSCL, 4, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SYSREG_MSCL, "pclk_sysreg_mscl", "div_pclk_mscl",
+                       ENABLE_PCLK_MSCL, 3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_JPEG, "pclk_jpeg", "div_pclk_mscl",
+                       ENABLE_PCLK_MSCL, 2, 0, 0),
+       GATE(CLK_PCLK_M2MSCALER1, "pclk_m2mscaler1", "div_pclk_mscl",
+                       ENABLE_PCLK_MSCL, 1, 0, 0),
+       GATE(CLK_PCLK_M2MSCALER0, "pclk_m2mscaler0", "div_pclk_mscl",
+                       ENABLE_PCLK_MSCL, 0, 0, 0),
+
+       /* ENABLE_PCLK_MSCL_SECURE_SMMU_M2MSCALER0 */
+       GATE(CLK_PCLK_SMMU_M2MSCALER0, "pclk_smmu_m2mscaler0", "div_pclk_mscl",
+                       ENABLE_PCLK_MSCL_SECURE_SMMU_M2MSCALER0,
+                       0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_PCLK_MSCL_SECURE_SMMU_M2MSCALER1 */
+       GATE(CLK_PCLK_SMMU_M2MSCALER1, "pclk_smmu_m2mscaler1", "div_pclk_mscl",
+                       ENABLE_PCLK_MSCL_SECURE_SMMU_M2MSCALER1,
+                       0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_PCLK_MSCL_SECURE_SMMU_JPEG */
+       GATE(CLK_PCLK_SMMU_JPEG, "pclk_smmu_jpeg", "div_pclk_mscl",
+                       ENABLE_PCLK_MSCL_SECURE_SMMU_JPEG,
+                       0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_SCLK_MSCL */
+       GATE(CLK_SCLK_JPEG, "sclk_jpeg", "mout_sclk_jpeg", ENABLE_SCLK_MSCL, 0,
+                       CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
+};
+
+static struct samsung_cmu_info mscl_cmu_info __initdata = {
+       .mux_clks               = mscl_mux_clks,
+       .nr_mux_clks            = ARRAY_SIZE(mscl_mux_clks),
+       .div_clks               = mscl_div_clks,
+       .nr_div_clks            = ARRAY_SIZE(mscl_div_clks),
+       .gate_clks              = mscl_gate_clks,
+       .nr_gate_clks           = ARRAY_SIZE(mscl_gate_clks),
+       .nr_clk_ids             = MSCL_NR_CLK,
+       .clk_regs               = mscl_clk_regs,
+       .nr_clk_regs            = ARRAY_SIZE(mscl_clk_regs),
+};
+
+static void __init exynos5433_cmu_mscl_init(struct device_node *np)
+{
+       samsung_cmu_register_one(np, &mscl_cmu_info);
+}
+CLK_OF_DECLARE(exynos5433_cmu_mscl, "samsung,exynos5433-cmu-mscl",
+               exynos5433_cmu_mscl_init);
+
+/*
+ * Register offset definitions for CMU_MFC
+ */
+#define MUX_SEL_MFC                            0x0200
+#define MUX_ENABLE_MFC                         0x0300
+#define MUX_STAT_MFC                           0x0400
+#define DIV_MFC                                        0x0600
+#define DIV_STAT_MFC                           0x0700
+#define ENABLE_ACLK_MFC                                0x0800
+#define ENABLE_ACLK_MFC_SECURE_SMMU_MFC                0x0804
+#define ENABLE_PCLK_MFC                                0x0900
+#define ENABLE_PCLK_MFC_SECURE_SMMU_MFC                0x0904
+#define ENABLE_IP_MFC0                         0x0b00
+#define ENABLE_IP_MFC1                         0x0b04
+#define ENABLE_IP_MFC_SECURE_SMMU_MFC          0x0b08
+
+static unsigned long mfc_clk_regs[] __initdata = {
+       MUX_SEL_MFC,
+       MUX_ENABLE_MFC,
+       MUX_STAT_MFC,
+       DIV_MFC,
+       DIV_STAT_MFC,
+       ENABLE_ACLK_MFC,
+       ENABLE_ACLK_MFC_SECURE_SMMU_MFC,
+       ENABLE_PCLK_MFC,
+       ENABLE_PCLK_MFC_SECURE_SMMU_MFC,
+       ENABLE_IP_MFC0,
+       ENABLE_IP_MFC1,
+       ENABLE_IP_MFC_SECURE_SMMU_MFC,
+};
+
+PNAME(mout_aclk_mfc_400_user_p)                = { "oscclk", "aclk_mfc_400", };
+
+static struct samsung_mux_clock mfc_mux_clks[] __initdata = {
+       /* MUX_SEL_MFC */
+       MUX(CLK_MOUT_ACLK_MFC_400_USER, "mout_aclk_mfc_400_user",
+                       mout_aclk_mfc_400_user_p, MUX_SEL_MFC, 0, 0),
+};
+
+static struct samsung_div_clock mfc_div_clks[] __initdata = {
+       /* DIV_MFC */
+       DIV(CLK_DIV_PCLK_MFC, "div_pclk_mfc", "mout_aclk_mfc_400_user",
+                       DIV_MFC, 0, 2),
+};
+
+static struct samsung_gate_clock mfc_gate_clks[] __initdata = {
+       /* ENABLE_ACLK_MFC */
+       GATE(CLK_ACLK_BTS_MFC_1, "aclk_bts_mfc_1", "mout_aclk_mfc_400_user",
+                       ENABLE_ACLK_MFC, 6, 0, 0),
+       GATE(CLK_ACLK_BTS_MFC_0, "aclk_bts_mfc_0", "mout_aclk_mfc_400_user",
+                       ENABLE_ACLK_MFC, 5, 0, 0),
+       GATE(CLK_ACLK_AHB2APB_MFCP, "aclk_ahb2apb_mfcp", "div_pclk_mfc",
+                       ENABLE_ACLK_MFC, 4, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_XIU_MFCX, "aclk_xiu_mfcx", "mout_aclk_mfc_400_user",
+                       ENABLE_ACLK_MFC, 3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_MFCNP_100, "aclk_mfcnp_100", "div_pclk_mfc",
+                       ENABLE_ACLK_MFC, 2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_MFCND_400, "aclk_mfcnd_400", "mout_aclk_mfc_400_user",
+                       ENABLE_ACLK_MFC, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_MFC, "aclk_mfc", "mout_aclk_mfc_400_user",
+                       ENABLE_ACLK_MFC, 0, 0, 0),
+
+       /* ENABLE_ACLK_MFC_SECURE_SMMU_MFC */
+       GATE(CLK_ACLK_SMMU_MFC_1, "aclk_smmu_mfc_1", "mout_aclk_mfc_400_user",
+                       ENABLE_ACLK_MFC_SECURE_SMMU_MFC,
+                       1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_SMMU_MFC_0, "aclk_smmu_mfc_0", "mout_aclk_mfc_400_user",
+                       ENABLE_ACLK_MFC_SECURE_SMMU_MFC,
+                       0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_PCLK_MFC */
+       GATE(CLK_PCLK_BTS_MFC_1, "pclk_bts_mfc_1", "div_pclk_mfc",
+                       ENABLE_PCLK_MFC, 4, 0, 0),
+       GATE(CLK_PCLK_BTS_MFC_0, "pclk_bts_mfc_0", "div_pclk_mfc",
+                       ENABLE_PCLK_MFC, 3, 0, 0),
+       GATE(CLK_PCLK_PMU_MFC, "pclk_pmu_mfc", "div_pclk_mfc",
+                       ENABLE_PCLK_MFC, 2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SYSREG_MFC, "pclk_sysreg_mfc", "div_pclk_mfc",
+                       ENABLE_PCLK_MFC, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_MFC, "pclk_mfc", "div_pclk_mfc",
+                       ENABLE_PCLK_MFC, 4, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_PCLK_MFC_SECURE_SMMU_MFC */
+       GATE(CLK_PCLK_SMMU_MFC_1, "pclk_smmu_mfc_1", "div_pclk_mfc",
+                       ENABLE_PCLK_MFC_SECURE_SMMU_MFC,
+                       1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SMMU_MFC_0, "pclk_smmu_mfc_0", "div_pclk_mfc",
+                       ENABLE_PCLK_MFC_SECURE_SMMU_MFC,
+                       0, CLK_IGNORE_UNUSED, 0),
+};
+
+static struct samsung_cmu_info mfc_cmu_info __initdata = {
+       .mux_clks               = mfc_mux_clks,
+       .nr_mux_clks            = ARRAY_SIZE(mfc_mux_clks),
+       .div_clks               = mfc_div_clks,
+       .nr_div_clks            = ARRAY_SIZE(mfc_div_clks),
+       .gate_clks              = mfc_gate_clks,
+       .nr_gate_clks           = ARRAY_SIZE(mfc_gate_clks),
+       .nr_clk_ids             = MFC_NR_CLK,
+       .clk_regs               = mfc_clk_regs,
+       .nr_clk_regs            = ARRAY_SIZE(mfc_clk_regs),
+};
+
+static void __init exynos5433_cmu_mfc_init(struct device_node *np)
+{
+       samsung_cmu_register_one(np, &mfc_cmu_info);
+}
+CLK_OF_DECLARE(exynos5433_cmu_mfc, "samsung,exynos5433-cmu-mfc",
+               exynos5433_cmu_mfc_init);
+
+/*
+ * Register offset definitions for CMU_HEVC
+ */
+#define MUX_SEL_HEVC                           0x0200
+#define MUX_ENABLE_HEVC                                0x0300
+#define MUX_STAT_HEVC                          0x0400
+#define DIV_HEVC                               0x0600
+#define DIV_STAT_HEVC                          0x0700
+#define ENABLE_ACLK_HEVC                       0x0800
+#define ENABLE_ACLK_HEVC_SECURE_SMMU_HEVC      0x0804
+#define ENABLE_PCLK_HEVC                       0x0900
+#define ENABLE_PCLK_HEVC_SECURE_SMMU_HEVC      0x0904
+#define ENABLE_IP_HEVC0                                0x0b00
+#define ENABLE_IP_HEVC1                                0x0b04
+#define ENABLE_IP_HEVC_SECURE_SMMU_HEVC                0x0b08
+
+static unsigned long hevc_clk_regs[] __initdata = {
+       MUX_SEL_HEVC,
+       MUX_ENABLE_HEVC,
+       MUX_STAT_HEVC,
+       DIV_HEVC,
+       DIV_STAT_HEVC,
+       ENABLE_ACLK_HEVC,
+       ENABLE_ACLK_HEVC_SECURE_SMMU_HEVC,
+       ENABLE_PCLK_HEVC,
+       ENABLE_PCLK_HEVC_SECURE_SMMU_HEVC,
+       ENABLE_IP_HEVC0,
+       ENABLE_IP_HEVC1,
+       ENABLE_IP_HEVC_SECURE_SMMU_HEVC,
+};
+
+PNAME(mout_aclk_hevc_400_user_p)       = { "oscclk", "aclk_hevc_400", };
+
+static struct samsung_mux_clock hevc_mux_clks[] __initdata = {
+       /* MUX_SEL_HEVC */
+       MUX(CLK_MOUT_ACLK_HEVC_400_USER, "mout_aclk_hevc_400_user",
+                       mout_aclk_hevc_400_user_p, MUX_SEL_HEVC, 0, 0),
+};
+
+static struct samsung_div_clock hevc_div_clks[] __initdata = {
+       /* DIV_HEVC */
+       DIV(CLK_DIV_PCLK_HEVC, "div_pclk_hevc", "mout_aclk_hevc_400_user",
+                       DIV_HEVC, 0, 2),
+};
+
+static struct samsung_gate_clock hevc_gate_clks[] __initdata = {
+       /* ENABLE_ACLK_HEVC */
+       GATE(CLK_ACLK_BTS_HEVC_1, "aclk_bts_hevc_1", "mout_aclk_hevc_400_user",
+                       ENABLE_ACLK_HEVC, 6, 0, 0),
+       GATE(CLK_ACLK_BTS_HEVC_0, "aclk_bts_hevc_0", "mout_aclk_hevc_400_user",
+                       ENABLE_ACLK_HEVC, 5, 0, 0),
+       GATE(CLK_ACLK_AHB2APB_HEVCP, "aclk_ahb2apb_hevcp", "div_pclk_hevc",
+                       ENABLE_ACLK_HEVC, 4, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_XIU_HEVCX, "aclk_xiu_hevcx", "mout_aclk_hevc_400_user",
+                       ENABLE_ACLK_HEVC, 3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_HEVCNP_100, "aclk_hevcnp_100", "div_pclk_hevc",
+                       ENABLE_ACLK_HEVC, 2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_HEVCND_400, "aclk_hevcnd_400", "mout_aclk_hevc_400_user",
+                       ENABLE_ACLK_HEVC, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_HEVC, "aclk_hevc", "mout_aclk_hevc_400_user",
+                       ENABLE_ACLK_HEVC, 0, 0, 0),
+
+       /* ENABLE_ACLK_HEVC_SECURE_SMMU_HEVC */
+       GATE(CLK_ACLK_SMMU_HEVC_1, "aclk_smmu_hevc_1",
+                       "mout_aclk_hevc_400_user",
+                       ENABLE_ACLK_HEVC_SECURE_SMMU_HEVC,
+                       1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_SMMU_HEVC_0, "aclk_smmu_hevc_0",
+                       "mout_aclk_hevc_400_user",
+                       ENABLE_ACLK_HEVC_SECURE_SMMU_HEVC,
+                       0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_PCLK_HEVC */
+       GATE(CLK_PCLK_BTS_HEVC_1, "pclk_bts_hevc_1", "div_pclk_hevc",
+                       ENABLE_PCLK_HEVC, 4, 0, 0),
+       GATE(CLK_PCLK_BTS_HEVC_0, "pclk_bts_hevc_0", "div_pclk_hevc",
+                       ENABLE_PCLK_HEVC, 3, 0, 0),
+       GATE(CLK_PCLK_PMU_HEVC, "pclk_pmu_hevc", "div_pclk_hevc",
+                       ENABLE_PCLK_HEVC, 2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SYSREG_HEVC, "pclk_sysreg_hevc", "div_pclk_hevc",
+                       ENABLE_PCLK_HEVC, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_HEVC, "pclk_hevc", "div_pclk_hevc",
+                       ENABLE_PCLK_HEVC, 4, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_PCLK_HEVC_SECURE_SMMU_HEVC */
+       GATE(CLK_PCLK_SMMU_HEVC_1, "pclk_smmu_hevc_1", "div_pclk_hevc",
+                       ENABLE_PCLK_HEVC_SECURE_SMMU_HEVC,
+                       1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SMMU_HEVC_0, "pclk_smmu_hevc_0", "div_pclk_hevc",
+                       ENABLE_PCLK_HEVC_SECURE_SMMU_HEVC,
+                       0, CLK_IGNORE_UNUSED, 0),
+};
+
+static struct samsung_cmu_info hevc_cmu_info __initdata = {
+       .mux_clks               = hevc_mux_clks,
+       .nr_mux_clks            = ARRAY_SIZE(hevc_mux_clks),
+       .div_clks               = hevc_div_clks,
+       .nr_div_clks            = ARRAY_SIZE(hevc_div_clks),
+       .gate_clks              = hevc_gate_clks,
+       .nr_gate_clks           = ARRAY_SIZE(hevc_gate_clks),
+       .nr_clk_ids             = HEVC_NR_CLK,
+       .clk_regs               = hevc_clk_regs,
+       .nr_clk_regs            = ARRAY_SIZE(hevc_clk_regs),
+};
+
+static void __init exynos5433_cmu_hevc_init(struct device_node *np)
+{
+       samsung_cmu_register_one(np, &hevc_cmu_info);
+}
+CLK_OF_DECLARE(exynos5433_cmu_hevc, "samsung,exynos5433-cmu-hevc",
+               exynos5433_cmu_hevc_init);
+
+/*
+ * Register offset definitions for CMU_ISP
+ */
+#define MUX_SEL_ISP                    0x0200
+#define MUX_ENABLE_ISP                 0x0300
+#define MUX_STAT_ISP                   0x0400
+#define DIV_ISP                                0x0600
+#define DIV_STAT_ISP                   0x0700
+#define ENABLE_ACLK_ISP0               0x0800
+#define ENABLE_ACLK_ISP1               0x0804
+#define ENABLE_ACLK_ISP2               0x0808
+#define ENABLE_PCLK_ISP                        0x0900
+#define ENABLE_SCLK_ISP                        0x0a00
+#define ENABLE_IP_ISP0                 0x0b00
+#define ENABLE_IP_ISP1                 0x0b04
+#define ENABLE_IP_ISP2                 0x0b08
+#define ENABLE_IP_ISP3                 0x0b0c
+
+static unsigned long isp_clk_regs[] __initdata = {
+       MUX_SEL_ISP,
+       MUX_ENABLE_ISP,
+       MUX_STAT_ISP,
+       DIV_ISP,
+       DIV_STAT_ISP,
+       ENABLE_ACLK_ISP0,
+       ENABLE_ACLK_ISP1,
+       ENABLE_ACLK_ISP2,
+       ENABLE_PCLK_ISP,
+       ENABLE_SCLK_ISP,
+       ENABLE_IP_ISP0,
+       ENABLE_IP_ISP1,
+       ENABLE_IP_ISP2,
+       ENABLE_IP_ISP3,
+};
+
+PNAME(mout_aclk_isp_dis_400_user_p)    = { "oscclk", "aclk_isp_dis_400", };
+PNAME(mout_aclk_isp_400_user_p)                = { "oscclk", "aclk_isp_400", };
+
+static struct samsung_mux_clock isp_mux_clks[] __initdata = {
+       /* MUX_SEL_ISP */
+       MUX(CLK_MOUT_ACLK_ISP_DIS_400_USER, "mout_aclk_isp_dis_400_user",
+                       mout_aclk_isp_dis_400_user_p, MUX_SEL_ISP, 4, 0),
+       MUX(CLK_MOUT_ACLK_ISP_400_USER, "mout_aclk_isp_400_user",
+                       mout_aclk_isp_400_user_p, MUX_SEL_ISP, 0, 0),
+};
+
+static struct samsung_div_clock isp_div_clks[] __initdata = {
+       /* DIV_ISP */
+       DIV(CLK_DIV_PCLK_ISP_DIS, "div_pclk_isp_dis",
+                       "mout_aclk_isp_dis_400_user", DIV_ISP, 12, 3),
+       DIV(CLK_DIV_PCLK_ISP, "div_pclk_isp", "mout_aclk_isp_400_user",
+                       DIV_ISP, 8, 3),
+       DIV(CLK_DIV_ACLK_ISP_D_200, "div_aclk_isp_d_200",
+                       "mout_aclk_isp_400_user", DIV_ISP, 4, 3),
+       DIV(CLK_DIV_ACLK_ISP_C_200, "div_aclk_isp_c_200",
+                       "mout_aclk_isp_400_user", DIV_ISP, 0, 3),
+};
+
+static struct samsung_gate_clock isp_gate_clks[] __initdata = {
+       /* ENABLE_ACLK_ISP0 */
+       GATE(CLK_ACLK_ISP_D_GLUE, "aclk_isp_d_glue", "mout_aclk_isp_400_user",
+                       ENABLE_ACLK_ISP0, 6, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_SCALERP, "aclk_scalerp", "mout_aclk_isp_400_user",
+                       ENABLE_ACLK_ISP0, 5, 0, 0),
+       GATE(CLK_ACLK_3DNR, "aclk_3dnr", "mout_aclk_isp_400_user",
+                       ENABLE_ACLK_ISP0, 4, 0, 0),
+       GATE(CLK_ACLK_DIS, "aclk_dis", "mout_aclk_isp_dis_400_user",
+                       ENABLE_ACLK_ISP0, 3, 0, 0),
+       GATE(CLK_ACLK_SCALERC, "aclk_scalerc", "mout_aclk_isp_400_user",
+                       ENABLE_ACLK_ISP0, 2, 0, 0),
+       GATE(CLK_ACLK_DRC, "aclk_drc", "mout_aclk_isp_400_user",
+                       ENABLE_ACLK_ISP0, 1, 0, 0),
+       GATE(CLK_ACLK_ISP, "aclk_isp", "mout_aclk_isp_400_user",
+                       ENABLE_ACLK_ISP0, 0, 0, 0),
+
+       /* ENABLE_ACLK_ISP1 */
+       GATE(CLK_ACLK_AXIUS_SCALERP, "aclk_axius_scalerp",
+                       "mout_aclk_isp_400_user", ENABLE_ACLK_ISP1,
+                       17, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AXIUS_SCALERC, "aclk_axius_scalerc",
+                       "mout_aclk_isp_400_user", ENABLE_ACLK_ISP1,
+                       16, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AXIUS_DRC, "aclk_axius_drc",
+                       "mout_aclk_isp_400_user", ENABLE_ACLK_ISP1,
+                       15, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAHBM_ISP2P, "aclk_asyncahbm_isp2p",
+                       "div_pclk_isp", ENABLE_ACLK_ISP1,
+                       14, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAHBM_ISP1P, "aclk_asyncahbm_isp1p",
+                       "div_pclk_isp", ENABLE_ACLK_ISP1,
+                       13, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIS_DIS1, "aclk_asyncaxis_dis1",
+                       "mout_aclk_isp_dis_400_user", ENABLE_ACLK_ISP1,
+                       12, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIS_DIS0, "aclk_asyncaxis_dis0",
+                       "mout_aclk_isp_dis_400_user", ENABLE_ACLK_ISP1,
+                       11, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIM_DIS1, "aclk_asyncaxim_dis1",
+                       "mout_aclk_isp_400_user", ENABLE_ACLK_ISP1,
+                       10, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIM_DIS0, "aclk_asyncaxim_dis0",
+                       "mout_aclk_isp_400_user", ENABLE_ACLK_ISP1,
+                       9, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIM_ISP2P, "aclk_asyncaxim_isp2p",
+                       "div_aclk_isp_d_200", ENABLE_ACLK_ISP1,
+                       8, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIM_ISP1P, "aclk_asyncaxim_isp1p",
+                       "div_aclk_isp_c_200", ENABLE_ACLK_ISP1,
+                       7, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AHB2APB_ISP2P, "aclk_ahb2apb_isp2p", "div_pclk_isp",
+                       ENABLE_ACLK_ISP1, 6, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AHB2APB_ISP1P, "aclk_ahb2apb_isp1p", "div_pclk_isp",
+                       ENABLE_ACLK_ISP1, 5, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AXI2APB_ISP2P, "aclk_axi2apb_isp2p",
+                       "div_aclk_isp_d_200", ENABLE_ACLK_ISP1,
+                       4, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AXI2APB_ISP1P, "aclk_axi2apb_isp1p",
+                       "div_aclk_isp_c_200", ENABLE_ACLK_ISP1,
+                       3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_XIU_ISPEX1, "aclk_xiu_ispex1", "mout_aclk_isp_400_user",
+                       ENABLE_ACLK_ISP1, 2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_XIU_ISPEX0, "aclk_xiu_ispex0", "mout_aclk_isp_400_user",
+                       ENABLE_ACLK_ISP1, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ISPND_400, "aclk_ispnd_400", "mout_aclk_isp_400_user",
+                       ENABLE_ACLK_ISP1, 1, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_ACLK_ISP2 */
+       GATE(CLK_ACLK_SMMU_SCALERP, "aclk_smmu_scalerp",
+                       "mout_aclk_isp_400_user", ENABLE_ACLK_ISP2,
+                       13, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_SMMU_3DNR, "aclk_smmu_3dnr", "mout_aclk_isp_400_user",
+                       ENABLE_ACLK_ISP2, 12, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_SMMU_DIS1, "aclk_smmu_dis1", "mout_aclk_isp_400_user",
+                       ENABLE_ACLK_ISP2, 11, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_SMMU_DIS0, "aclk_smmu_dis0", "mout_aclk_isp_400_user",
+                       ENABLE_ACLK_ISP2, 10, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_SMMU_SCALERC, "aclk_smmu_scalerc",
+                       "mout_aclk_isp_400_user", ENABLE_ACLK_ISP2,
+                       9, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_SMMU_DRC, "aclk_smmu_drc", "mout_aclk_isp_400_user",
+                       ENABLE_ACLK_ISP2, 8, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_SMMU_ISP, "aclk_smmu_isp", "mout_aclk_isp_400_user",
+                       ENABLE_ACLK_ISP2, 7, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_BTS_SCALERP, "aclk_bts_scalerp",
+                       "mout_aclk_isp_400_user", ENABLE_ACLK_ISP2,
+                       6, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_BTS_3DR, "aclk_bts_3dnr", "mout_aclk_isp_400_user",
+                       ENABLE_ACLK_ISP2, 5, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_BTS_DIS1, "aclk_bts_dis1", "mout_aclk_isp_400_user",
+                       ENABLE_ACLK_ISP2, 4, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_BTS_DIS0, "aclk_bts_dis0", "mout_aclk_isp_400_user",
+                       ENABLE_ACLK_ISP2, 3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_BTS_SCALERC, "aclk_bts_scalerc",
+                       "mout_aclk_isp_400_user", ENABLE_ACLK_ISP2,
+                       2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_BTS_DRC, "aclk_bts_drc", "mout_aclk_isp_400_user",
+                       ENABLE_ACLK_ISP2, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_BTS_ISP, "aclk_bts_isp", "mout_aclk_isp_400_user",
+                       ENABLE_ACLK_ISP2, 0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_PCLK_ISP */
+       GATE(CLK_PCLK_SMMU_SCALERP, "pclk_smmu_scalerp", "div_aclk_isp_d_200",
+                       ENABLE_PCLK_ISP, 25, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SMMU_3DNR, "pclk_smmu_3dnr", "div_aclk_isp_d_200",
+                       ENABLE_PCLK_ISP, 24, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SMMU_DIS1, "pclk_smmu_dis1", "div_aclk_isp_d_200",
+                       ENABLE_PCLK_ISP, 23, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SMMU_DIS0, "pclk_smmu_dis0", "div_aclk_isp_d_200",
+                       ENABLE_PCLK_ISP, 22, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SMMU_SCALERC, "pclk_smmu_scalerc", "div_aclk_isp_c_200",
+                       ENABLE_PCLK_ISP, 21, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SMMU_DRC, "pclk_smmu_drc", "div_aclk_isp_c_200",
+                       ENABLE_PCLK_ISP, 20, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SMMU_ISP, "pclk_smmu_isp", "div_aclk_isp_c_200",
+                       ENABLE_PCLK_ISP, 19, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_BTS_SCALERP, "pclk_bts_scalerp", "div_pclk_isp",
+                       ENABLE_PCLK_ISP, 18, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_BTS_3DNR, "pclk_bts_3dnr", "div_pclk_isp",
+                       ENABLE_PCLK_ISP, 17, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_BTS_DIS1, "pclk_bts_dis1", "div_pclk_isp",
+                       ENABLE_PCLK_ISP, 16, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_BTS_DIS0, "pclk_bts_dis0", "div_pclk_isp",
+                       ENABLE_PCLK_ISP, 15, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_BTS_SCALERC, "pclk_bts_scalerc", "div_pclk_isp",
+                       ENABLE_PCLK_ISP, 14, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_BTS_DRC, "pclk_bts_drc", "div_pclk_isp",
+                       ENABLE_PCLK_ISP, 13, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_BTS_ISP, "pclk_bts_isp", "div_pclk_isp",
+                       ENABLE_PCLK_ISP, 12, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_ASYNCAXI_DIS1, "pclk_asyncaxi_dis1", "div_pclk_isp",
+                       ENABLE_PCLK_ISP, 11, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_ASYNCAXI_DIS0, "pclk_asyncaxi_dis0", "div_pclk_isp",
+                       ENABLE_PCLK_ISP, 10, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_PMU_ISP, "pclk_pmu_isp", "div_pclk_isp",
+                       ENABLE_PCLK_ISP, 9, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SYSREG_ISP, "pclk_sysreg_isp", "div_pclk_isp",
+                       ENABLE_PCLK_ISP, 8, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_CMU_ISP_LOCAL, "pclk_cmu_isp_local",
+                       "div_aclk_isp_c_200", ENABLE_PCLK_ISP,
+                       7, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SCALERP, "pclk_scalerp", "div_aclk_isp_d_200",
+                       ENABLE_PCLK_ISP, 6, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_3DNR, "pclk_3dnr", "div_aclk_isp_d_200",
+                       ENABLE_PCLK_ISP, 5, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_DIS_CORE, "pclk_dis_core", "div_pclk_isp_dis",
+                       ENABLE_PCLK_ISP, 4, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_DIS, "pclk_dis", "div_aclk_isp_d_200",
+                       ENABLE_PCLK_ISP, 3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SCALERC, "pclk_scalerc", "div_aclk_isp_c_200",
+                       ENABLE_PCLK_ISP, 2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_DRC, "pclk_drc", "div_aclk_isp_c_200",
+                       ENABLE_PCLK_ISP, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_ISP, "pclk_isp", "div_aclk_isp_c_200",
+                       ENABLE_PCLK_ISP, 0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_SCLK_ISP */
+       GATE(CLK_SCLK_PIXELASYNCS_DIS, "sclk_pixelasyncs_dis",
+                       "mout_aclk_isp_dis_400_user", ENABLE_SCLK_ISP,
+                       5, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SCLK_PIXELASYNCM_DIS, "sclk_pixelasyncm_dis",
+                       "mout_aclk_isp_dis_400_user", ENABLE_SCLK_ISP,
+                       4, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SCLK_PIXELASYNCS_SCALERP, "sclk_pixelasyncs_scalerp",
+                       "mout_aclk_isp_400_user", ENABLE_SCLK_ISP,
+                       3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SCLK_PIXELASYNCM_ISPD, "sclk_pixelasyncm_ispd",
+                       "mout_aclk_isp_400_user", ENABLE_SCLK_ISP,
+                       2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SCLK_PIXELASYNCS_ISPC, "sclk_pixelasyncs_ispc",
+                       "mout_aclk_isp_400_user", ENABLE_SCLK_ISP,
+                       1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_SCLK_PIXELASYNCM_ISPC, "sclk_pixelasyncm_ispc",
+                       "mout_aclk_isp_400_user", ENABLE_SCLK_ISP,
+                       0, CLK_IGNORE_UNUSED, 0),
+};
+
+static struct samsung_cmu_info isp_cmu_info __initdata = {
+       .mux_clks               = isp_mux_clks,
+       .nr_mux_clks            = ARRAY_SIZE(isp_mux_clks),
+       .div_clks               = isp_div_clks,
+       .nr_div_clks            = ARRAY_SIZE(isp_div_clks),
+       .gate_clks              = isp_gate_clks,
+       .nr_gate_clks           = ARRAY_SIZE(isp_gate_clks),
+       .nr_clk_ids             = ISP_NR_CLK,
+       .clk_regs               = isp_clk_regs,
+       .nr_clk_regs            = ARRAY_SIZE(isp_clk_regs),
+};
+
+static void __init exynos5433_cmu_isp_init(struct device_node *np)
+{
+       samsung_cmu_register_one(np, &isp_cmu_info);
+}
+CLK_OF_DECLARE(exynos5433_cmu_isp, "samsung,exynos5433-cmu-isp",
+               exynos5433_cmu_isp_init);
+
+/*
+ * Register offset definitions for CMU_CAM0
+ */
+#define MUX_SEL_CAM00                  0x0200
+#define MUX_SEL_CAM01                  0x0204
+#define MUX_SEL_CAM02                  0x0208
+#define MUX_SEL_CAM03                  0x020c
+#define MUX_SEL_CAM04                  0x0210
+#define MUX_ENABLE_CAM00               0x0300
+#define MUX_ENABLE_CAM01               0x0304
+#define MUX_ENABLE_CAM02               0x0308
+#define MUX_ENABLE_CAM03               0x030c
+#define MUX_ENABLE_CAM04               0x0310
+#define MUX_STAT_CAM00                 0x0400
+#define MUX_STAT_CAM01                 0x0404
+#define MUX_STAT_CAM02                 0x0408
+#define MUX_STAT_CAM03                 0x040c
+#define MUX_STAT_CAM04                 0x0410
+#define MUX_IGNORE_CAM01               0x0504
+#define DIV_CAM00                      0x0600
+#define DIV_CAM01                      0x0604
+#define DIV_CAM02                      0x0608
+#define DIV_CAM03                      0x060c
+#define DIV_STAT_CAM00                 0x0700
+#define DIV_STAT_CAM01                 0x0704
+#define DIV_STAT_CAM02                 0x0708
+#define DIV_STAT_CAM03                 0x070c
+#define ENABLE_ACLK_CAM00              0X0800
+#define ENABLE_ACLK_CAM01              0X0804
+#define ENABLE_ACLK_CAM02              0X0808
+#define ENABLE_PCLK_CAM0               0X0900
+#define ENABLE_SCLK_CAM0               0X0a00
+#define ENABLE_IP_CAM00                        0X0b00
+#define ENABLE_IP_CAM01                        0X0b04
+#define ENABLE_IP_CAM02                        0X0b08
+#define ENABLE_IP_CAM03                        0X0b0C
+
+static unsigned long cam0_clk_regs[] __initdata = {
+       MUX_SEL_CAM00,
+       MUX_SEL_CAM01,
+       MUX_SEL_CAM02,
+       MUX_SEL_CAM03,
+       MUX_SEL_CAM04,
+       MUX_ENABLE_CAM00,
+       MUX_ENABLE_CAM01,
+       MUX_ENABLE_CAM02,
+       MUX_ENABLE_CAM03,
+       MUX_ENABLE_CAM04,
+       MUX_STAT_CAM00,
+       MUX_STAT_CAM01,
+       MUX_STAT_CAM02,
+       MUX_STAT_CAM03,
+       MUX_STAT_CAM04,
+       MUX_IGNORE_CAM01,
+       DIV_CAM00,
+       DIV_CAM01,
+       DIV_CAM02,
+       DIV_CAM03,
+       DIV_STAT_CAM00,
+       DIV_STAT_CAM01,
+       DIV_STAT_CAM02,
+       DIV_STAT_CAM03,
+       ENABLE_ACLK_CAM00,
+       ENABLE_ACLK_CAM01,
+       ENABLE_ACLK_CAM02,
+       ENABLE_PCLK_CAM0,
+       ENABLE_SCLK_CAM0,
+       ENABLE_IP_CAM00,
+       ENABLE_IP_CAM01,
+       ENABLE_IP_CAM02,
+       ENABLE_IP_CAM03,
+};
+PNAME(mout_aclk_cam0_333_user_p)       = { "oscclk", "aclk_cam0_333", };
+PNAME(mout_aclk_cam0_400_user_p)       = { "oscclk", "aclk_cam0_400", };
+PNAME(mout_aclk_cam0_552_user_p)       = { "oscclk", "aclk_cam0_552", };
+
+PNAME(mout_phyclk_rxbyteclkhs0_s4_user_p) = { "oscclk",
+                                             "phyclk_rxbyteclkhs0_s4_phy", };
+PNAME(mout_phyclk_rxbyteclkhs0_s2a_user_p) = { "oscclk",
+                                              "phyclk_rxbyteclkhs0_s2a_phy", };
+
+PNAME(mout_aclk_lite_d_b_p)            = { "mout_aclk_lite_d_a",
+                                           "mout_aclk_cam0_333_user", };
+PNAME(mout_aclk_lite_d_a_p)            = { "mout_aclk_cam0_552_user",
+                                           "mout_aclk_cam0_400_user", };
+PNAME(mout_aclk_lite_b_b_p)            = { "mout_aclk_lite_b_a",
+                                           "mout_aclk_cam0_333_user", };
+PNAME(mout_aclk_lite_b_a_p)            = { "mout_aclk_cam0_552_user",
+                                           "mout_aclk_cam0_400_user", };
+PNAME(mout_aclk_lite_a_b_p)            = { "mout_aclk_lite_a_a",
+                                           "mout_aclk_cam0_333_user", };
+PNAME(mout_aclk_lite_a_a_p)            = { "mout_aclk_cam0_552_user",
+                                           "mout_aclk_cam0_400_user", };
+PNAME(mout_aclk_cam0_400_p)            = { "mout_aclk_cam0_400_user",
+                                           "mout_aclk_cam0_333_user", };
+
+PNAME(mout_aclk_csis1_b_p)             = { "mout_aclk_csis1_a",
+                                           "mout_aclk_cam0_333_user" };
+PNAME(mout_aclk_csis1_a_p)             = { "mout_aclk_cam0_552_user",
+                                           "mout_aclk_cam0_400_user", };
+PNAME(mout_aclk_csis0_b_p)             = { "mout_aclk_csis0_a",
+                                           "mout_aclk_cam0_333_user", };
+PNAME(mout_aclk_csis0_a_p)             = { "mout_aclk_cam0_552_user",
+                                           "mout_aclk-cam0_400_user", };
+PNAME(mout_aclk_3aa1_b_p)              = { "mout_aclk_3aa1_a",
+                                           "mout_aclk_cam0_333_user", };
+PNAME(mout_aclk_3aa1_a_p)              = { "mout_aclk_cam0_552_user",
+                                           "mout_aclk_cam0_400_user", };
+PNAME(mout_aclk_3aa0_b_p)              = { "mout_aclk_3aa0_a",
+                                           "mout_aclk_cam0_333_user", };
+PNAME(mout_aclk_3aa0_a_p)              = { "mout_aclk_cam0_552_user",
+                                           "mout_aclk_cam0_400_user", };
+
+PNAME(mout_sclk_lite_freecnt_c_p)      = { "mout_sclk_lite_freecnt_b",
+                                           "div_pclk_lite_d", };
+PNAME(mout_sclk_lite_freecnt_b_p)      = { "mout_sclk_lite_freecnt_a",
+                                           "div_pclk_pixelasync_lite_c", };
+PNAME(mout_sclk_lite_freecnt_a_p)      = { "div_pclk_lite_a",
+                                           "div_pclk_lite_b", };
+PNAME(mout_sclk_pixelasync_lite_c_b_p) = { "mout_sclk_pixelasync_lite_c_a",
+                                           "mout_aclk_cam0_333_user", };
+PNAME(mout_sclk_pixelasync_lite_c_a_p) = { "mout_aclk_cam0_552_user",
+                                           "mout_aclk_cam0_400_user", };
+PNAME(mout_sclk_pixelasync_lite_c_init_b_p) = {
+                                       "mout_sclk_pixelasync_lite_c_init_a",
+                                       "mout_aclk_cam0_400_user", };
+PNAME(mout_sclk_pixelasync_lite_c_init_a_p) = {
+                                       "mout_aclk_cam0_552_user",
+                                       "mout_aclk_cam0_400_user", };
+
+static struct samsung_fixed_rate_clock cam0_fixed_clks[] __initdata = {
+       FRATE(CLK_PHYCLK_RXBYTEECLKHS0_S4_PHY, "phyclk_rxbyteclkhs0_s4_phy",
+                       NULL, CLK_IS_ROOT, 100000000),
+       FRATE(CLK_PHYCLK_RXBYTEECLKHS0_S2A_PHY, "phyclk_rxbyteclkhs0_s2a_phy",
+                       NULL, CLK_IS_ROOT, 100000000),
+};
+
+static struct samsung_mux_clock cam0_mux_clks[] __initdata = {
+       /* MUX_SEL_CAM00 */
+       MUX(CLK_MOUT_ACLK_CAM0_333_USER, "mout_aclk_cam0_333_user",
+                       mout_aclk_cam0_333_user_p, MUX_SEL_CAM00, 8, 1),
+       MUX(CLK_MOUT_ACLK_CAM0_400_USER, "mout_aclk_cam0_400_user",
+                       mout_aclk_cam0_400_user_p, MUX_SEL_CAM00, 4, 1),
+       MUX(CLK_MOUT_ACLK_CAM0_552_USER, "mout_aclk_cam0_552_user",
+                       mout_aclk_cam0_552_user_p, MUX_SEL_CAM00, 0, 1),
+
+       /* MUX_SEL_CAM01 */
+       MUX(CLK_MOUT_PHYCLK_RXBYTECLKHS0_S4_USER,
+                       "mout_phyclk_rxbyteclkhs0_s4_user",
+                       mout_phyclk_rxbyteclkhs0_s4_user_p,
+                       MUX_SEL_CAM01, 4, 1),
+       MUX(CLK_MOUT_PHYCLK_RXBYTECLKHS0_S2A_USER,
+                       "mout_phyclk_rxbyteclkhs0_s2a_user",
+                       mout_phyclk_rxbyteclkhs0_s2a_user_p,
+                       MUX_SEL_CAM01, 0, 1),
+
+       /* MUX_SEL_CAM02 */
+       MUX(CLK_MOUT_ACLK_LITE_D_B, "mout_aclk_lite_d_b", mout_aclk_lite_d_b_p,
+                       MUX_SEL_CAM02, 24, 1),
+       MUX(CLK_MOUT_ACLK_LITE_D_A, "mout_aclk_lite_d_a", mout_aclk_lite_d_a_p,
+                       MUX_SEL_CAM02, 20, 1),
+       MUX(CLK_MOUT_ACLK_LITE_B_B, "mout_aclk_lite_b_b", mout_aclk_lite_b_b_p,
+                       MUX_SEL_CAM02, 16, 1),
+       MUX(CLK_MOUT_ACLK_LITE_B_A, "mout_aclk_lite_b_a", mout_aclk_lite_b_a_p,
+                       MUX_SEL_CAM02, 12, 1),
+       MUX(CLK_MOUT_ACLK_LITE_A_B, "mout_aclk_lite_a_b", mout_aclk_lite_a_b_p,
+                       MUX_SEL_CAM02, 8, 1),
+       MUX(CLK_MOUT_ACLK_LITE_A_A, "mout_aclk_lite_a_a", mout_aclk_lite_a_a_p,
+                       MUX_SEL_CAM02, 4, 1),
+       MUX(CLK_MOUT_ACLK_CAM0_400, "mout_aclk_cam0_400", mout_aclk_cam0_400_p,
+                       MUX_SEL_CAM02, 0, 1),
+
+       /* MUX_SEL_CAM03 */
+       MUX(CLK_MOUT_ACLK_CSIS1_B, "mout_aclk_csis1_b", mout_aclk_csis1_b_p,
+                       MUX_SEL_CAM03, 28, 1),
+       MUX(CLK_MOUT_ACLK_CSIS1_A, "mout_aclk_csis1_a", mout_aclk_csis1_a_p,
+                       MUX_SEL_CAM03, 24, 1),
+       MUX(CLK_MOUT_ACLK_CSIS0_B, "mout_aclk_csis0_b", mout_aclk_csis0_b_p,
+                       MUX_SEL_CAM03, 20, 1),
+       MUX(CLK_MOUT_ACLK_CSIS0_A, "mout_aclk_csis0_a", mout_aclk_csis0_a_p,
+                       MUX_SEL_CAM03, 16, 1),
+       MUX(CLK_MOUT_ACLK_3AA1_B, "mout_aclk_3aa1_b", mout_aclk_3aa1_b_p,
+                       MUX_SEL_CAM03, 12, 1),
+       MUX(CLK_MOUT_ACLK_3AA1_A, "mout_aclk_3aa1_a", mout_aclk_3aa1_a_p,
+                       MUX_SEL_CAM03, 8, 1),
+       MUX(CLK_MOUT_ACLK_3AA0_B, "mout_aclk_3aa0_b", mout_aclk_3aa0_b_p,
+                       MUX_SEL_CAM03, 4, 1),
+       MUX(CLK_MOUT_ACLK_3AA0_A, "mout_aclk_3aa0_a", mout_aclk_3aa0_a_p,
+                       MUX_SEL_CAM03, 0, 1),
+
+       /* MUX_SEL_CAM04 */
+       MUX(CLK_MOUT_SCLK_LITE_FREECNT_C, "mout_sclk_lite_freecnt_c",
+                       mout_sclk_lite_freecnt_c_p, MUX_SEL_CAM04, 24, 1),
+       MUX(CLK_MOUT_SCLK_LITE_FREECNT_B, "mout_sclk_lite_freecnt_b",
+                       mout_sclk_lite_freecnt_b_p, MUX_SEL_CAM04, 24, 1),
+       MUX(CLK_MOUT_SCLK_LITE_FREECNT_A, "mout_sclk_lite_freecnt_a",
+                       mout_sclk_lite_freecnt_a_p, MUX_SEL_CAM04, 24, 1),
+       MUX(CLK_MOUT_SCLK_PIXELASYNC_LITE_C_B, "mout_sclk_pixelasync_lite_c_b",
+                       mout_sclk_pixelasync_lite_c_b_p, MUX_SEL_CAM04, 24, 1),
+       MUX(CLK_MOUT_SCLK_PIXELASYNC_LITE_C_A, "mout_sclk_pixelasync_lite_c_a",
+                       mout_sclk_pixelasync_lite_c_a_p, MUX_SEL_CAM04, 24, 1),
+       MUX(CLK_MOUT_SCLK_PIXELASYNC_LITE_C_INIT_B,
+                       "mout_sclk_pixelasync_lite_c_init_b",
+                       mout_sclk_pixelasync_lite_c_init_b_p,
+                       MUX_SEL_CAM04, 24, 1),
+       MUX(CLK_MOUT_SCLK_PIXELASYNC_LITE_C_INIT_A,
+                       "mout_sclk_pixelasync_lite_c_init_a",
+                       mout_sclk_pixelasync_lite_c_init_a_p,
+                       MUX_SEL_CAM04, 24, 1),
+};
+
+static struct samsung_div_clock cam0_div_clks[] __initdata = {
+       /* DIV_CAM00 */
+       DIV(CLK_DIV_PCLK_CAM0_50, "div_pclk_cam0_50", "div_aclk_cam0_200",
+                       DIV_CAM00, 8, 2),
+       DIV(CLK_DIV_ACLK_CAM0_200, "div_aclk_cam0_200", "mout_aclk_cam0_400",
+                       DIV_CAM00, 4, 3),
+       DIV(CLK_DIV_ACLK_CAM0_BUS_400, "div_aclk_cam0_bus_400",
+                       "mout_aclk_cam0_400", DIV_CAM00, 0, 3),
+
+       /* DIV_CAM01 */
+       DIV(CLK_DIV_PCLK_LITE_D, "div_pclk_lite_d", "div_aclk_lite_d",
+                       DIV_CAM01, 20, 2),
+       DIV(CLK_DIV_ACLK_LITE_D, "div_aclk_lite_d", "mout_aclk_lite_d_b",
+                       DIV_CAM01, 16, 3),
+       DIV(CLK_DIV_PCLK_LITE_B, "div_pclk_lite_b", "div_aclk_lite_b",
+                       DIV_CAM01, 12, 2),
+       DIV(CLK_DIV_ACLK_LITE_B, "div_aclk_lite_b", "mout_aclk_lite_b_b",
+                       DIV_CAM01, 8, 3),
+       DIV(CLK_DIV_PCLK_LITE_A, "div_pclk_lite_a", "div_aclk_lite_a",
+                       DIV_CAM01, 4, 2),
+       DIV(CLK_DIV_ACLK_LITE_A, "div_aclk_lite_a", "mout_aclk_lite_a_b",
+                       DIV_CAM01, 0, 3),
+
+       /* DIV_CAM02 */
+       DIV(CLK_DIV_ACLK_CSIS1, "div_aclk_csis1", "mout_aclk_csis1_b",
+                       DIV_CAM02, 20, 3),
+       DIV(CLK_DIV_ACLK_CSIS0, "div_aclk_csis0", "mout_aclk_csis0_b",
+                       DIV_CAM02, 16, 3),
+       DIV(CLK_DIV_PCLK_3AA1, "div_pclk_3aa1", "div_aclk_3aa1",
+                       DIV_CAM02, 12, 2),
+       DIV(CLK_DIV_ACLK_3AA1, "div_aclk_3aa1", "mout_aclk_3aa1_b",
+                       DIV_CAM02, 8, 3),
+       DIV(CLK_DIV_PCLK_3AA0, "div_pclk_3aa0", "div_aclk_3aa0",
+                       DIV_CAM02, 4, 2),
+       DIV(CLK_DIV_ACLK_3AA0, "div_aclk_3aa0", "mout_aclk_3aa0_b",
+                       DIV_CAM02, 0, 3),
+
+       /* DIV_CAM03 */
+       DIV(CLK_DIV_SCLK_PIXELASYNC_LITE_C, "div_sclk_pixelasync_lite_c",
+                       "mout_sclk_pixelasync_lite_c_b", DIV_CAM03, 8, 3),
+       DIV(CLK_DIV_PCLK_PIXELASYNC_LITE_C, "div_pclk_pixelasync_lite_c",
+                       "div_sclk_pixelasync_lite_c_init", DIV_CAM03, 4, 2),
+       DIV(CLK_DIV_SCLK_PIXELASYNC_LITE_C_INIT,
+                       "div_sclk_pixelasync_lite_c_init",
+                       "mout_sclk_pixelasync_lite_c_init_b", DIV_CAM03, 0, 3),
+};
+
+static struct samsung_gate_clock cam0_gate_clks[] __initdata = {
+       /* ENABLE_ACLK_CAM00 */
+       GATE(CLK_ACLK_CSIS1, "aclk_csis1", "div_aclk_csis1", ENABLE_ACLK_CAM00,
+                       6, 0, 0),
+       GATE(CLK_ACLK_CSIS0, "aclk_csis0", "div_aclk_csis0", ENABLE_ACLK_CAM00,
+                       5, 0, 0),
+       GATE(CLK_ACLK_3AA1, "aclk_3aa1", "div_aclk_3aa1", ENABLE_ACLK_CAM00,
+                       4, 0, 0),
+       GATE(CLK_ACLK_3AA0, "aclk_3aa0", "div_aclk_3aa0", ENABLE_ACLK_CAM00,
+                       3, 0, 0),
+       GATE(CLK_ACLK_LITE_D, "aclk_lite_d", "div_aclk_lite_d",
+                       ENABLE_ACLK_CAM00, 2, 0, 0),
+       GATE(CLK_ACLK_LITE_B, "aclk_lite_b", "div_aclk_lite_b",
+                       ENABLE_ACLK_CAM00, 1, 0, 0),
+       GATE(CLK_ACLK_LITE_A, "aclk_lite_a", "div_aclk_lite_a",
+                       ENABLE_ACLK_CAM00, 0, 0, 0),
+
+       /* ENABLE_ACLK_CAM01 */
+       GATE(CLK_ACLK_AHBSYNCDN, "aclk_ahbsyncdn", "div_aclk_cam0_200",
+                       ENABLE_ACLK_CAM01, 31, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AXIUS_LITE_D, "aclk_axius_lite_d", "div_aclk_cam0_bus_400",
+                       ENABLE_ACLK_CAM01, 30, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AXIUS_LITE_B, "aclk_axius_lite_b", "div_aclk_cam0_bus_400",
+                       ENABLE_ACLK_CAM01, 29, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AXIUS_LITE_A, "aclk_axius_lite_a", "div_aclk_cam0_bus_400",
+                       ENABLE_ACLK_CAM01, 28, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAPBM_3AA1, "aclk_asyncapbm_3aa1", "div_pclk_3aa1",
+                       ENABLE_ACLK_CAM01, 27, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAPBS_3AA1, "aclk_asyncapbs_3aa1", "div_aclk_3aa1",
+                       ENABLE_ACLK_CAM01, 26, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAPBM_3AA0, "aclk_asyncapbm_3aa0", "div_pclk_3aa0",
+                       ENABLE_ACLK_CAM01, 25, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAPBS_3AA0, "aclk_asyncapbs_3aa0", "div_aclk_3aa0",
+                       ENABLE_ACLK_CAM01, 24, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAPBM_LITE_D, "aclk_asyncapbm_lite_d",
+                       "div_pclk_lite_d", ENABLE_ACLK_CAM01,
+                       23, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAPBS_LITE_D, "aclk_asyncapbs_lite_d",
+                       "div_aclk_cam0_200", ENABLE_ACLK_CAM01,
+                       22, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAPBM_LITE_B, "aclk_asyncapbm_lite_b",
+                       "div_pclk_lite_b", ENABLE_ACLK_CAM01,
+                       21, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAPBS_LITE_B, "aclk_asyncapbs_lite_b",
+                       "div_aclk_cam0_200", ENABLE_ACLK_CAM01,
+                       20, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAPBM_LITE_A, "aclk_asyncapbm_lite_a",
+                       "div_pclk_lite_a", ENABLE_ACLK_CAM01,
+                       19, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAPBS_LITE_A, "aclk_asyncapbs_lite_a",
+                       "div_aclk_cam0_200", ENABLE_ACLK_CAM01,
+                       18, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIM_ISP0P, "aclk_asyncaxim_isp0p",
+                       "div_aclk_cam0_200", ENABLE_ACLK_CAM01,
+                       17, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIM_3AA1, "aclk_asyncaxim_3aa1",
+                       "div_aclk_cam0_bus_400", ENABLE_ACLK_CAM01,
+                       16, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIS_3AA1, "aclk_asyncaxis_3aa1",
+                       "div_aclk_3aa1", ENABLE_ACLK_CAM01,
+                       15, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIM_3AA0, "aclk_asyncaxim_3aa0",
+                       "div_aclk_cam0_bus_400", ENABLE_ACLK_CAM01,
+                       14, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIS_3AA0, "aclk_asyncaxis_3aa0",
+                       "div_aclk_3aa0", ENABLE_ACLK_CAM01,
+                       13, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIM_LITE_D, "aclk_asyncaxim_lite_d",
+                       "div_aclk_cam0_bus_400", ENABLE_ACLK_CAM01,
+                       12, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIS_LITE_D, "aclk_asyncaxis_lite_d",
+                       "div_aclk_lite_d", ENABLE_ACLK_CAM01,
+                       11, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIM_LITE_B, "aclk_asyncaxim_lite_b",
+                       "div_aclk_cam0_bus_400", ENABLE_ACLK_CAM01,
+                       10, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIS_LITE_B, "aclk_asyncaxis_lite_b",
+                       "div_aclk_lite_b", ENABLE_ACLK_CAM01,
+                       9, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIM_LITE_A, "aclk_asyncaxim_lite_a",
+                       "div_aclk_cam0_bus_400", ENABLE_ACLK_CAM01,
+                       8, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIS_LITE_A, "aclk_asyncaxis_lite_a",
+                       "div_aclk_lite_a", ENABLE_ACLK_CAM01,
+                       7, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AHB2APB_ISPSFRP, "aclk_ahb2apb_ispsfrp",
+                       "div_pclk_cam0_50", ENABLE_ACLK_CAM01,
+                       6, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AXI2APB_ISP0P, "aclk_axi2apb_isp0p", "div_aclk_cam0_200",
+                       ENABLE_ACLK_CAM01, 5, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AXI2AHB_ISP0P, "aclk_axi2ahb_isp0p", "div_aclk_cam0_200",
+                       ENABLE_ACLK_CAM01, 4, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_XIU_IS0X, "aclk_xiu_is0x", "div_aclk_cam0_200",
+                       ENABLE_ACLK_CAM01, 3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_XIU_ISP0EX, "aclk_xiu_isp0ex", "div_aclk_cam0_bus_400",
+                       ENABLE_ACLK_CAM01, 2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_CAM0NP_276, "aclk_cam0np_276", "div_aclk_cam0_200",
+                       ENABLE_ACLK_CAM01, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_CAM0ND_400, "aclk_cam0nd_400", "div_aclk_cam0_bus_400",
+                       ENABLE_ACLK_CAM01, 0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_ACLK_CAM02 */
+       GATE(CLK_ACLK_SMMU_3AA1, "aclk_smmu_3aa1", "div_aclk_cam0_bus_400",
+                       ENABLE_ACLK_CAM02, 9, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_SMMU_3AA0, "aclk_smmu_3aa0", "div_aclk_cam0_bus_400",
+                       ENABLE_ACLK_CAM02, 8, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_SMMU_LITE_D, "aclk_smmu_lite_d", "div_aclk_cam0_bus_400",
+                       ENABLE_ACLK_CAM02, 7, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_SMMU_LITE_B, "aclk_smmu_lite_b", "div_aclk_cam0_bus_400",
+                       ENABLE_ACLK_CAM02, 6, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_SMMU_LITE_A, "aclk_smmu_lite_a", "div_aclk_cam0_bus_400",
+                       ENABLE_ACLK_CAM02, 5, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_BTS_3AA1, "aclk_bts_3aa1", "div_aclk_cam0_bus_400",
+                       ENABLE_ACLK_CAM02, 4, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_BTS_3AA0, "aclk_bts_3aa0", "div_aclk_cam0_bus_400",
+                       ENABLE_ACLK_CAM02, 3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_BTS_LITE_D, "aclk_bts_lite_d", "div_aclk_cam0_bus_400",
+                       ENABLE_ACLK_CAM02, 2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_BTS_LITE_B, "aclk_bts_lite_b", "div_aclk_cam0_bus_400",
+                       ENABLE_ACLK_CAM02, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_BTS_LITE_A, "aclk_bts_lite_a", "div_aclk_cam0_bus_400",
+                       ENABLE_ACLK_CAM02, 0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_PCLK_CAM0 */
+       GATE(CLK_PCLK_SMMU_3AA1, "pclk_smmu_3aa1", "div_aclk_cam0_200",
+                       ENABLE_PCLK_CAM0, 25, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SMMU_3AA0, "pclk_smmu_3aa0", "div_aclk_cam0_200",
+                       ENABLE_PCLK_CAM0, 24, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SMMU_LITE_D, "pclk_smmu_lite_d", "div_aclk_cam0_200",
+                       ENABLE_PCLK_CAM0, 23, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SMMU_LITE_B, "pclk_smmu_lite_b", "div_aclk_cam0_200",
+                       ENABLE_PCLK_CAM0, 22, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SMMU_LITE_A, "pclk_smmu_lite_a", "div_aclk_cam0_200",
+                       ENABLE_PCLK_CAM0, 21, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_BTS_3AA1, "pclk_bts_3aa1", "div_pclk_cam0_50",
+                       ENABLE_PCLK_CAM0, 20, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_BTS_3AA0, "pclk_bts_3aa0", "div_pclk_cam0_50",
+                       ENABLE_PCLK_CAM0, 19, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_BTS_LITE_D, "pclk_bts_lite_d", "div_pclk_cam0_50",
+                       ENABLE_PCLK_CAM0, 18, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_BTS_LITE_B, "pclk_bts_lite_b", "div_pclk_cam0_50",
+                       ENABLE_PCLK_CAM0, 17, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_BTS_LITE_A, "pclk_bts_lite_a", "div_pclk_cam0_50",
+                       ENABLE_PCLK_CAM0, 16, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_ASYNCAXI_CAM1, "pclk_asyncaxi_cam1", "div_pclk_cam0_50",
+                       ENABLE_PCLK_CAM0, 15, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_ASYNCAXI_3AA1, "pclk_asyncaxi_3aa1", "div_pclk_cam0_50",
+                       ENABLE_PCLK_CAM0, 14, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_ASYNCAXI_3AA0, "pclk_asyncaxi_3aa0", "div_pclk_cam0_50",
+                       ENABLE_PCLK_CAM0, 13, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_ASYNCAXI_LITE_D, "pclk_asyncaxi_lite_d",
+                       "div_pclk_cam0_50", ENABLE_PCLK_CAM0,
+                       12, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_ASYNCAXI_LITE_B, "pclk_asyncaxi_lite_b",
+                       "div_pclk_cam0_50", ENABLE_PCLK_CAM0,
+                       11, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_ASYNCAXI_LITE_A, "pclk_asyncaxi_lite_a",
+                       "div_pclk_cam0_50", ENABLE_PCLK_CAM0,
+                       10, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_PMU_CAM0, "pclk_pmu_cam0", "div_pclk_cam0_50",
+                       ENABLE_PCLK_CAM0, 9, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SYSREG_CAM0, "pclk_sysreg_cam0", "div_pclk_cam0_50",
+                       ENABLE_PCLK_CAM0, 8, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_CMU_CAM0_LOCAL, "pclk_cmu_cam0_local",
+                       "div_aclk_cam0_200", ENABLE_PCLK_CAM0,
+                       7, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_CSIS1, "pclk_csis1", "div_aclk_cam0_200",
+                       ENABLE_PCLK_CAM0, 6, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_CSIS0, "pclk_csis0", "div_aclk_cam0_200",
+                       ENABLE_PCLK_CAM0, 5, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_3AA1, "pclk_3aa1", "div_pclk_3aa1",
+                       ENABLE_PCLK_CAM0, 4, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_3AA0, "pclk_3aa0", "div_pclk_3aa0",
+                       ENABLE_PCLK_CAM0, 3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_LITE_D, "pclk_lite_d", "div_pclk_lite_d",
+                       ENABLE_PCLK_CAM0, 2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_LITE_B, "pclk_lite_b", "div_pclk_lite_b",
+                       ENABLE_PCLK_CAM0, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_LITE_A, "pclk_lite_a", "div_pclk_lite_a",
+                       ENABLE_PCLK_CAM0, 0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_SCLK_CAM0 */
+       GATE(CLK_PHYCLK_RXBYTECLKHS0_S4, "phyclk_rxbyteclkhs0_s4",
+                       "mout_phyclk_rxbyteclkhs0_s4_user",
+                       ENABLE_SCLK_CAM0, 8, 0, 0),
+       GATE(CLK_PHYCLK_RXBYTECLKHS0_S2A, "phyclk_rxbyteclkhs0_s2a",
+                       "mout_phyclk_rxbyteclkhs0_s2a_user",
+                       ENABLE_SCLK_CAM0, 7, 0, 0),
+       GATE(CLK_SCLK_LITE_FREECNT, "sclk_lite_freecnt",
+                       "mout_sclk_lite_freecnt_c", ENABLE_SCLK_CAM0, 6, 0, 0),
+       GATE(CLK_SCLK_PIXELASYNCM_3AA1, "sclk_pixelasycm_3aa1",
+                       "div_aclk_3aa1", ENABLE_SCLK_CAM0, 5, 0, 0),
+       GATE(CLK_SCLK_PIXELASYNCM_3AA0, "sclk_pixelasycm_3aa0",
+                       "div_aclk_3aa0", ENABLE_SCLK_CAM0, 4, 0, 0),
+       GATE(CLK_SCLK_PIXELASYNCS_3AA0, "sclk_pixelasycs_3aa0",
+                       "div_aclk_3aa0", ENABLE_SCLK_CAM0, 3, 0, 0),
+       GATE(CLK_SCLK_PIXELASYNCM_LITE_C, "sclk_pixelasyncm_lite_c",
+                       "div_sclk_pixelasync_lite_c",
+                       ENABLE_SCLK_CAM0, 2, 0, 0),
+       GATE(CLK_SCLK_PIXELASYNCM_LITE_C_INIT, "sclk_pixelasyncm_lite_c_init",
+                       "div_sclk_pixelasync_lite_c_init",
+                       ENABLE_SCLK_CAM0, 1, 0, 0),
+       GATE(CLK_SCLK_PIXELASYNCS_LITE_C_INIT, "sclk_pixelasyncs_lite_c_init",
+                       "div_sclk_pixelasync_lite_c",
+                       ENABLE_SCLK_CAM0, 0, 0, 0),
+};
+
+static struct samsung_cmu_info cam0_cmu_info __initdata = {
+       .mux_clks               = cam0_mux_clks,
+       .nr_mux_clks            = ARRAY_SIZE(cam0_mux_clks),
+       .div_clks               = cam0_div_clks,
+       .nr_div_clks            = ARRAY_SIZE(cam0_div_clks),
+       .gate_clks              = cam0_gate_clks,
+       .nr_gate_clks           = ARRAY_SIZE(cam0_gate_clks),
+       .fixed_clks             = cam0_fixed_clks,
+       .nr_fixed_clks          = ARRAY_SIZE(cam0_fixed_clks),
+       .nr_clk_ids             = CAM0_NR_CLK,
+       .clk_regs               = cam0_clk_regs,
+       .nr_clk_regs            = ARRAY_SIZE(cam0_clk_regs),
+};
+
+static void __init exynos5433_cmu_cam0_init(struct device_node *np)
+{
+       samsung_cmu_register_one(np, &cam0_cmu_info);
+}
+CLK_OF_DECLARE(exynos5433_cmu_cam0, "samsung,exynos5433-cmu-cam0",
+               exynos5433_cmu_cam0_init);
+
+/*
+ * Register offset definitions for CMU_CAM1
+ */
+#define MUX_SEL_CAM10                  0x0200
+#define MUX_SEL_CAM11                  0x0204
+#define MUX_SEL_CAM12                  0x0208
+#define MUX_ENABLE_CAM10               0x0300
+#define MUX_ENABLE_CAM11               0x0304
+#define MUX_ENABLE_CAM12               0x0308
+#define MUX_STAT_CAM10                 0x0400
+#define MUX_STAT_CAM11                 0x0404
+#define MUX_STAT_CAM12                 0x0408
+#define MUX_IGNORE_CAM11               0x0504
+#define DIV_CAM10                      0x0600
+#define DIV_CAM11                      0x0604
+#define DIV_STAT_CAM10                 0x0700
+#define DIV_STAT_CAM11                 0x0704
+#define ENABLE_ACLK_CAM10              0X0800
+#define ENABLE_ACLK_CAM11              0X0804
+#define ENABLE_ACLK_CAM12              0X0808
+#define ENABLE_PCLK_CAM1               0X0900
+#define ENABLE_SCLK_CAM1               0X0a00
+#define ENABLE_IP_CAM10                        0X0b00
+#define ENABLE_IP_CAM11                        0X0b04
+#define ENABLE_IP_CAM12                        0X0b08
+
+static unsigned long cam1_clk_regs[] __initdata = {
+       MUX_SEL_CAM10,
+       MUX_SEL_CAM11,
+       MUX_SEL_CAM12,
+       MUX_ENABLE_CAM10,
+       MUX_ENABLE_CAM11,
+       MUX_ENABLE_CAM12,
+       MUX_STAT_CAM10,
+       MUX_STAT_CAM11,
+       MUX_STAT_CAM12,
+       MUX_IGNORE_CAM11,
+       DIV_CAM10,
+       DIV_CAM11,
+       DIV_STAT_CAM10,
+       DIV_STAT_CAM11,
+       ENABLE_ACLK_CAM10,
+       ENABLE_ACLK_CAM11,
+       ENABLE_ACLK_CAM12,
+       ENABLE_PCLK_CAM1,
+       ENABLE_SCLK_CAM1,
+       ENABLE_IP_CAM10,
+       ENABLE_IP_CAM11,
+       ENABLE_IP_CAM12,
+};
+
+PNAME(mout_sclk_isp_uart_user_p)       = { "oscclk", "sclk_isp_uart_cam1", };
+PNAME(mout_sclk_isp_spi1_user_p)       = { "oscclk", "sclk_isp_spi1_cam1", };
+PNAME(mout_sclk_isp_spi0_user_p)       = { "oscclk", "sclk_isp_spi0_cam1", };
+
+PNAME(mout_aclk_cam1_333_user_p)       = { "oscclk", "aclk_cam1_333", };
+PNAME(mout_aclk_cam1_400_user_p)       = { "oscclk", "aclk_cam1_400", };
+PNAME(mout_aclk_cam1_552_user_p)       = { "oscclk", "aclk_cam1_552", };
+
+PNAME(mout_phyclk_rxbyteclkhs0_s2b_user_p) = { "oscclk",
+                                              "phyclk_rxbyteclkhs0_s2b_phy", };
+
+PNAME(mout_aclk_csis2_b_p)             = { "mout_aclk_csis2_a",
+                                           "mout_aclk_cam1_333_user", };
+PNAME(mout_aclk_csis2_a_p)             = { "mout_aclk_cam1_552_user",
+                                           "mout_aclk_cam1_400_user", };
+
+PNAME(mout_aclk_fd_b_p)                        = { "mout_aclk_fd_a",
+                                           "mout_aclk_cam1_333_user", };
+PNAME(mout_aclk_fd_a_p)                        = { "mout_aclk_cam1_552_user",
+                                           "mout_aclk_cam1_400_user", };
+
+PNAME(mout_aclk_lite_c_b_p)            = { "mout_aclk_lite_c_a",
+                                           "mout_aclk_cam1_333_user", };
+PNAME(mout_aclk_lite_c_a_p)            = { "mout_aclk_cam1_552_user",
+                                           "mout_aclk_cam1_400_user", };
+
+static struct samsung_fixed_rate_clock cam1_fixed_clks[] __initdata = {
+       FRATE(CLK_PHYCLK_RXBYTEECLKHS0_S2B, "phyclk_rxbyteclkhs0_s2b_phy", NULL,
+                       CLK_IS_ROOT, 100000000),
+};
+
+static struct samsung_mux_clock cam1_mux_clks[] __initdata = {
+       /* MUX_SEL_CAM10 */
+       MUX(CLK_MOUT_SCLK_ISP_UART_USER, "mout_sclk_isp_uart_user",
+                       mout_sclk_isp_uart_user_p, MUX_SEL_CAM10, 20, 1),
+       MUX(CLK_MOUT_SCLK_ISP_SPI1_USER, "mout_sclk_isp_spi1_user",
+                       mout_sclk_isp_spi1_user_p, MUX_SEL_CAM10, 16, 1),
+       MUX(CLK_MOUT_SCLK_ISP_SPI0_USER, "mout_sclk_isp_spi0_user",
+                       mout_sclk_isp_spi0_user_p, MUX_SEL_CAM10, 12, 1),
+       MUX(CLK_MOUT_ACLK_CAM1_333_USER, "mout_aclk_cam1_333_user",
+                       mout_aclk_cam1_333_user_p, MUX_SEL_CAM10, 8, 1),
+       MUX(CLK_MOUT_ACLK_CAM1_400_USER, "mout_aclk_cam1_400_user",
+                       mout_aclk_cam1_400_user_p, MUX_SEL_CAM01, 4, 1),
+       MUX(CLK_MOUT_ACLK_CAM1_552_USER, "mout_aclk_cam1_552_user",
+                       mout_aclk_cam1_552_user_p, MUX_SEL_CAM01, 0, 1),
+
+       /* MUX_SEL_CAM11 */
+       MUX(CLK_MOUT_PHYCLK_RXBYTECLKHS0_S2B_USER,
+                       "mout_phyclk_rxbyteclkhs0_s2b_user",
+                       mout_phyclk_rxbyteclkhs0_s2b_user_p,
+                       MUX_SEL_CAM11, 0, 1),
+
+       /* MUX_SEL_CAM12 */
+       MUX(CLK_MOUT_ACLK_CSIS2_B, "mout_aclk_csis2_b", mout_aclk_csis2_b_p,
+                       MUX_SEL_CAM12, 20, 1),
+       MUX(CLK_MOUT_ACLK_CSIS2_A, "mout_aclk_csis2_a", mout_aclk_csis2_a_p,
+                       MUX_SEL_CAM12, 16, 1),
+       MUX(CLK_MOUT_ACLK_FD_B, "mout_aclk_fd_b", mout_aclk_fd_b_p,
+                       MUX_SEL_CAM12, 12, 1),
+       MUX(CLK_MOUT_ACLK_FD_A, "mout_aclk_fd_a", mout_aclk_fd_a_p,
+                       MUX_SEL_CAM12, 8, 1),
+       MUX(CLK_MOUT_ACLK_LITE_C_B, "mout_aclk_lite_c_b", mout_aclk_lite_c_b_p,
+                       MUX_SEL_CAM12, 4, 1),
+       MUX(CLK_MOUT_ACLK_LITE_C_A, "mout_aclk_lite_c_a", mout_aclk_lite_c_a_p,
+                       MUX_SEL_CAM12, 0, 1),
+};
+
+static struct samsung_div_clock cam1_div_clks[] __initdata = {
+       /* DIV_CAM10 */
+       DIV(CLK_DIV_SCLK_ISP_WPWM, "div_sclk_isp_wpwm",
+                       "div_pclk_cam1_83", DIV_CAM10, 16, 2),
+       DIV(CLK_DIV_PCLK_CAM1_83, "div_pclk_cam1_83",
+                       "mout_aclk_cam1_333_user", DIV_CAM10, 12, 2),
+       DIV(CLK_DIV_PCLK_CAM1_166, "div_pclk_cam1_166",
+                       "mout_aclk_cam1_333_user", DIV_CAM10, 8, 2),
+       DIV(CLK_DIV_PCLK_DBG_CAM1, "div_pclk_dbg_cam1",
+                       "mout_aclk_cam1_552_user", DIV_CAM10, 4, 3),
+       DIV(CLK_DIV_ATCLK_CAM1, "div_atclk_cam1", "mout_aclk_cam1_552_user",
+                       DIV_CAM10, 0, 3),
+
+       /* DIV_CAM11 */
+       DIV(CLK_DIV_ACLK_CSIS2, "div_aclk_csis2", "mout_aclk_csis2_b",
+                       DIV_CAM11, 16, 3),
+       DIV(CLK_DIV_PCLK_FD, "div_pclk_fd", "div_aclk_fd", DIV_CAM11, 12, 2),
+       DIV(CLK_DIV_ACLK_FD, "div_aclk_fd", "mout_aclk_fd_b", DIV_CAM11, 8, 3),
+       DIV(CLK_DIV_PCLK_LITE_C, "div_pclk_lite_c", "div_aclk_lite_c",
+                       DIV_CAM11, 4, 2),
+       DIV(CLK_DIV_ACLK_LITE_C, "div_aclk_lite_c", "mout_aclk_lite_c_b",
+                       DIV_CAM11, 0, 3),
+};
+
+static struct samsung_gate_clock cam1_gate_clks[] __initdata = {
+       /* ENABLE_ACLK_CAM10 */
+       GATE(CLK_ACLK_ISP_GIC, "aclk_isp_gic", "mout_aclk_cam1_333_user",
+                       ENABLE_ACLK_CAM10, 4, 0, 0),
+       GATE(CLK_ACLK_FD, "aclk_fd", "div_aclk_fd",
+                       ENABLE_ACLK_CAM10, 3, 0, 0),
+       GATE(CLK_ACLK_LITE_C, "aclk_lite_c", "div_aclk_lite_c",
+                       ENABLE_ACLK_CAM10, 1, 0, 0),
+       GATE(CLK_ACLK_CSIS2, "aclk_csis2", "div_aclk_csis2",
+                       ENABLE_ACLK_CAM10, 0, 0, 0),
+
+       /* ENABLE_ACLK_CAM11 */
+       GATE(CLK_ACLK_ASYNCAPBM_FD, "aclk_asyncapbm_fd", "div_pclk_fd",
+                       ENABLE_ACLK_CAM11, 29, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAPBS_FD, "aclk_asyncapbs_fd", "div_pclk_cam1_166",
+                       ENABLE_ACLK_CAM11, 28, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAPBM_LITE_C, "aclk_asyncapbm_lite_c",
+                       "div_pclk_lite_c", ENABLE_ACLK_CAM11,
+                       27, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAPBS_LITE_C, "aclk_asyncapbs_lite_c",
+                       "div_pclk_cam1_166", ENABLE_ACLK_CAM11,
+                       26, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAHBS_SFRISP2H2, "aclk_asyncahbs_sfrisp2h2",
+                       "div_pclk_cam1_83", ENABLE_ACLK_CAM11,
+                       25, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAHBS_SFRISP2H1, "aclk_asyncahbs_sfrisp2h1",
+                       "div_pclk_cam1_83", ENABLE_ACLK_CAM11,
+                       24, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIM_CA5, "aclk_asyncaxim_ca5",
+                       "mout_aclk_cam1_333_user", ENABLE_ACLK_CAM11,
+                       23, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIS_CA5, "aclk_asyncaxis_ca5",
+                       "mout_aclk_cam1_552_user", ENABLE_ACLK_CAM11,
+                       22, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIS_ISPX2, "aclk_asyncaxis_ispx2",
+                       "mout_aclk_cam1_333_user", ENABLE_ACLK_CAM11,
+                       21, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIS_ISPX1, "aclk_asyncaxis_ispx1",
+                       "mout_aclk_cam1_333_user", ENABLE_ACLK_CAM11,
+                       20, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIS_ISPX0, "aclk_asyncaxis_ispx0",
+                       "mout_aclk_cam1_333_user", ENABLE_ACLK_CAM11,
+                       19, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIM_ISPEX, "aclk_asyncaxim_ispex",
+                       "mout_aclk_cam1_400_user", ENABLE_ACLK_CAM11,
+                       18, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIM_ISP3P, "aclk_asyncaxim_isp3p",
+                       "mout_aclk_cam1_400_user", ENABLE_ACLK_CAM11,
+                       17, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIS_ISP3P, "aclk_asyncaxis_isp3p",
+                       "mout_aclk_cam1_333_user", ENABLE_ACLK_CAM11,
+                       16, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIM_FD, "aclk_asyncaxim_fd",
+                       "mout_aclk_cam1_400_user", ENABLE_ACLK_CAM11,
+                       15, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIS_FD, "aclk_asyncaxis_fd", "div_aclk_fd",
+                       ENABLE_ACLK_CAM11, 14, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIM_LITE_C, "aclk_asyncaxim_lite_c",
+                       "mout_aclk_cam1_400_user", ENABLE_ACLK_CAM11,
+                       13, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_ASYNCAXIS_LITE_C, "aclk_asyncaxis_lite_c",
+                       "div_aclk_lite_c", ENABLE_ACLK_CAM11,
+                       12, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AHB2APB_ISP5P, "aclk_ahb2apb_isp5p", "div_pclk_cam1_83",
+                       ENABLE_ACLK_CAM11, 11, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AHB2APB_ISP3P, "aclk_ahb2apb_isp3p", "div_pclk_cam1_83",
+                       ENABLE_ACLK_CAM11, 10, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AXI2APB_ISP3P, "aclk_axi2apb_isp3p",
+                       "mout_aclk_cam1_333_user", ENABLE_ACLK_CAM11,
+                       9, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AHB_SFRISP2H, "aclk_ahb_sfrisp2h", "div_pclk_cam1_83",
+                       ENABLE_ACLK_CAM11, 8, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AXI_ISP_HX_R, "aclk_axi_isp_hx_r", "div_pclk_cam1_166",
+                       ENABLE_ACLK_CAM11, 7, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AXI_ISP_CX_R, "aclk_axi_isp_cx_r", "div_pclk_cam1_166",
+                       ENABLE_ACLK_CAM11, 6, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AXI_ISP_HX, "aclk_axi_isp_hx", "mout_aclk_cam1_333_user",
+                       ENABLE_ACLK_CAM11, 5, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AXI_ISP_CX, "aclk_axi_isp_cx", "mout_aclk_cam1_333_user",
+                       ENABLE_ACLK_CAM11, 4, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_XIU_ISPX, "aclk_xiu_ispx", "mout_aclk_cam1_333_user",
+                       ENABLE_ACLK_CAM11, 3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_XIU_ISPEX, "aclk_xiu_ispex", "mout_aclk_cam1_400_user",
+                       ENABLE_ACLK_CAM11, 2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_CAM1NP_333, "aclk_cam1np_333", "mout_aclk_cam1_333_user",
+                       ENABLE_ACLK_CAM11, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_CAM1ND_400, "aclk_cam1nd_400", "mout_aclk_cam1_400_user",
+                       ENABLE_ACLK_CAM11, 0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_ACLK_CAM12 */
+       GATE(CLK_ACLK_SMMU_ISPCPU, "aclk_smmu_ispcpu",
+                       "mout_aclk_cam1_400_user", ENABLE_ACLK_CAM12,
+                       10, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_SMMU_FD, "aclk_smmu_fd", "mout_aclk_cam1_400_user",
+                       ENABLE_ACLK_CAM12, 9, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_SMMU_LITE_C, "aclk_smmu_lite_c",
+                       "mout_aclk_cam1_400_user", ENABLE_ACLK_CAM12,
+                       8, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_BTS_ISP3P, "aclk_bts_isp3p", "mout_aclk_cam1_400_user",
+                       ENABLE_ACLK_CAM12, 7, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_BTS_FD, "aclk_bts_fd", "mout_aclk_cam1_400_user",
+                       ENABLE_ACLK_CAM12, 6, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_BTS_LITE_C, "aclk_bts_lite_c", "mout_aclk_cam1_400_user",
+                       ENABLE_ACLK_CAM12, 5, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AHBDN_SFRISP2H, "aclk_ahbdn_sfrisp2h",
+                       "mout_aclk_cam1_333_user", ENABLE_ACLK_CAM12,
+                       4, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AHBDN_ISP5P, "aclk_aclk-shbdn_isp5p",
+                       "mout_aclk_cam1_333_user", ENABLE_ACLK_CAM12,
+                       3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AXIUS_ISP3P, "aclk_axius_isp3p",
+                       "mout_aclk_cam1_400_user", ENABLE_ACLK_CAM12,
+                       2, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AXIUS_FD, "aclk_axius_fd", "mout_aclk_cam1_400_user",
+                       ENABLE_ACLK_CAM12, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_ACLK_AXIUS_LITE_C, "aclk_axius_lite_c",
+                       "mout_aclk_cam1_400_user", ENABLE_ACLK_CAM12,
+                       0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_PCLK_CAM1 */
+       GATE(CLK_PCLK_SMMU_ISPCPU, "pclk_smmu_ispcpu", "div_pclk_cam1_166",
+                       ENABLE_PCLK_CAM1, 27, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SMMU_FD, "pclk_smmu_fd", "div_pclk_cam1_166",
+                       ENABLE_PCLK_CAM1, 26, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SMMU_LITE_C, "pclk_smmu_lite_c", "div_pclk_cam1_166",
+                       ENABLE_PCLK_CAM1, 25, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_BTS_ISP3P, "pclk_bts_isp3p", "div_pclk_cam1_83",
+                       ENABLE_PCLK_CAM1, 24, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_BTS_FD, "pclk_bts_fd", "div_pclk_cam1_83",
+                       ENABLE_PCLK_CAM1, 23, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_BTS_LITE_C, "pclk_bts_lite_c", "div_pclk_cam1_83",
+                       ENABLE_PCLK_CAM1, 22, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_ASYNCAXIM_CA5, "pclk_asyncaxim_ca5", "div_pclk_cam1_166",
+                       ENABLE_PCLK_CAM1, 21, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_ASYNCAXIM_ISPEX, "pclk_asyncaxim_ispex",
+                       "div_pclk_cam1_83", ENABLE_PCLK_CAM1,
+                       20, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_ASYNCAXIM_ISP3P, "pclk_asyncaxim_isp3p",
+                       "div_pclk_cam1_83", ENABLE_PCLK_CAM1,
+                       19, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_ASYNCAXIM_FD, "pclk_asyncaxim_fd", "div_pclk_cam1_83",
+                       ENABLE_PCLK_CAM1, 18, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_ASYNCAXIM_LITE_C, "pclk_asyncaxim_lite_c",
+                       "div_pclk_cam1_83", ENABLE_PCLK_CAM1,
+                       17, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_PMU_CAM1, "pclk_pmu_cam1", "div_pclk_cam1_83",
+                       ENABLE_PCLK_CAM1, 16, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_SYSREG_CAM1, "pclk_sysreg_cam1", "div_pclk_cam1_83",
+                       ENABLE_PCLK_CAM1, 15, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_CMU_CAM1_LOCAL, "pclk_cmu_cam1_local",
+                       "div_pclk_cam1_166", ENABLE_PCLK_CAM1,
+                       14, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_ISP_MCTADC, "pclk_isp_mctadc", "div_pclk_cam1_83",
+                       ENABLE_PCLK_CAM1, 13, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_ISP_WDT, "pclk_isp_wdt", "div_pclk_cam1_83",
+                       ENABLE_PCLK_CAM1, 12, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_ISP_PWM, "pclk_isp_pwm", "div_pclk_cam1_83",
+                       ENABLE_PCLK_CAM1, 11, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_ISP_UART, "pclk_isp_uart", "div_pclk_cam1_83",
+                       ENABLE_PCLK_CAM1, 10, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_ISP_MCUCTL, "pclk_isp_mcuctl", "div_pclk_cam1_83",
+                       ENABLE_PCLK_CAM1, 9, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_ISP_SPI1, "pclk_isp_spi1", "div_pclk_cam1_83",
+                       ENABLE_PCLK_CAM1, 8, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_ISP_SPI0, "pclk_isp_spi0", "div_pclk_cam1_83",
+                       ENABLE_PCLK_CAM1, 7, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_ISP_I2C2, "pclk_isp_i2c2", "div_pclk_cam1_83",
+                       ENABLE_PCLK_CAM1, 6, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_ISP_I2C1, "pclk_isp_i2c1", "div_pclk_cam1_83",
+                       ENABLE_PCLK_CAM1, 5, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_ISP_I2C0, "pclk_isp_i2c0", "div_pclk_cam1_83",
+                       ENABLE_PCLK_CAM1, 4, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_ISP_MPWM, "pclk_isp_wpwm", "div_pclk_cam1_83",
+                       ENABLE_PCLK_CAM1, 3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_FD, "pclk_fd", "div_pclk_fd",
+                       ENABLE_PCLK_CAM1, 3, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_LITE_C, "pclk_lite_c", "div_pclk_lite_c",
+                       ENABLE_PCLK_CAM1, 1, CLK_IGNORE_UNUSED, 0),
+       GATE(CLK_PCLK_CSIS2, "pclk_csis2", "div_pclk_cam1_166",
+                       ENABLE_PCLK_CAM1, 0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_SCLK_CAM1 */
+       GATE(CLK_SCLK_ISP_I2C2, "sclk_isp_i2c2", "oscclk", ENABLE_SCLK_CAM1,
+                       15, 0, 0),
+       GATE(CLK_SCLK_ISP_I2C1, "sclk_isp_i2c1", "oscclk", ENABLE_SCLK_CAM1,
+                       14, 0, 0),
+       GATE(CLK_SCLK_ISP_I2C0, "sclk_isp_i2c0", "oscclk", ENABLE_SCLK_CAM1,
+                       13, 0, 0),
+       GATE(CLK_SCLK_ISP_PWM, "sclk_isp_pwm", "oscclk", ENABLE_SCLK_CAM1,
+                       12, 0, 0),
+       GATE(CLK_PHYCLK_RXBYTECLKHS0_S2B, "phyclk_rxbyteclkhs0_s2b",
+                       "mout_phyclk_rxbyteclkhs0_s2b_user",
+                       ENABLE_SCLK_CAM1, 11, 0, 0),
+       GATE(CLK_SCLK_LITE_C_FREECNT, "sclk_lite_c_freecnt", "div_pclk_lite_c",
+                       ENABLE_SCLK_CAM1, 10, 0, 0),
+       GATE(CLK_SCLK_PIXELASYNCM_FD, "sclk_pixelasyncm_fd", "div_aclk_fd",
+                       ENABLE_SCLK_CAM1, 9, 0, 0),
+       GATE(CLK_SCLK_ISP_MCTADC, "sclk_isp_mctadc", "sclk_isp_mctadc_cam1",
+                       ENABLE_SCLK_CAM1, 7, 0, 0),
+       GATE(CLK_SCLK_ISP_UART, "sclk_isp_uart", "mout_sclk_isp_uart_user",
+                       ENABLE_SCLK_CAM1, 6, 0, 0),
+       GATE(CLK_SCLK_ISP_SPI1, "sclk_isp_spi1", "mout_sclk_isp_spi1_user",
+                       ENABLE_SCLK_CAM1, 5, 0, 0),
+       GATE(CLK_SCLK_ISP_SPI0, "sclk_isp_spi0", "mout_sclk_isp_spi0_user",
+                       ENABLE_SCLK_CAM1, 4, 0, 0),
+       GATE(CLK_SCLK_ISP_MPWM, "sclk_isp_wpwm", "div_sclk_isp_wpwm",
+                       ENABLE_SCLK_CAM1, 3, 0, 0),
+       GATE(CLK_PCLK_DBG_ISP, "sclk_dbg_isp", "div_pclk_dbg_cam1",
+                       ENABLE_SCLK_CAM1, 2, 0, 0),
+       GATE(CLK_ATCLK_ISP, "atclk_isp", "div_atclk_cam1",
+                       ENABLE_SCLK_CAM1, 1, 0, 0),
+       GATE(CLK_SCLK_ISP_CA5, "sclk_isp_ca5", "mout_aclk_cam1_552_user",
+                       ENABLE_SCLK_CAM1, 0, 0, 0),
+};
+
+static struct samsung_cmu_info cam1_cmu_info __initdata = {
+       .mux_clks               = cam1_mux_clks,
+       .nr_mux_clks            = ARRAY_SIZE(cam1_mux_clks),
+       .div_clks               = cam1_div_clks,
+       .nr_div_clks            = ARRAY_SIZE(cam1_div_clks),
+       .gate_clks              = cam1_gate_clks,
+       .nr_gate_clks           = ARRAY_SIZE(cam1_gate_clks),
+       .fixed_clks             = cam1_fixed_clks,
+       .nr_fixed_clks          = ARRAY_SIZE(cam1_fixed_clks),
+       .nr_clk_ids             = CAM1_NR_CLK,
+       .clk_regs               = cam1_clk_regs,
+       .nr_clk_regs            = ARRAY_SIZE(cam1_clk_regs),
+};
+
+static void __init exynos5433_cmu_cam1_init(struct device_node *np)
+{
+       samsung_cmu_register_one(np, &cam1_cmu_info);
+}
+CLK_OF_DECLARE(exynos5433_cmu_cam1, "samsung,exynos5433-cmu-cam1",
+               exynos5433_cmu_cam1_init);
index d270a2084644756786875f3d08b1709482d1adca..e668e479a6970301c9512711bb6b4f044ff670e5 100644 (file)
@@ -169,44 +169,44 @@ static inline void s5pv210_clk_sleep_init(void) { }
 #endif
 
 /* Mux parent lists. */
-static const char *fin_pll_p[] __initconst = {
+static const char *fin_pll_p[] __initdata = {
        "xxti",
        "xusbxti"
 };
 
-static const char *mout_apll_p[] __initconst = {
+static const char *mout_apll_p[] __initdata = {
        "fin_pll",
        "fout_apll"
 };
 
-static const char *mout_mpll_p[] __initconst = {
+static const char *mout_mpll_p[] __initdata = {
        "fin_pll",
        "fout_mpll"
 };
 
-static const char *mout_epll_p[] __initconst = {
+static const char *mout_epll_p[] __initdata = {
        "fin_pll",
        "fout_epll"
 };
 
-static const char *mout_vpllsrc_p[] __initconst = {
+static const char *mout_vpllsrc_p[] __initdata = {
        "fin_pll",
        "sclk_hdmi27m"
 };
 
-static const char *mout_vpll_p[] __initconst = {
+static const char *mout_vpll_p[] __initdata = {
        "mout_vpllsrc",
        "fout_vpll"
 };
 
-static const char *mout_group1_p[] __initconst = {
+static const char *mout_group1_p[] __initdata = {
        "dout_a2m",
        "mout_mpll",
        "mout_epll",
        "mout_vpll"
 };
 
-static const char *mout_group2_p[] __initconst = {
+static const char *mout_group2_p[] __initdata = {
        "xxti",
        "xusbxti",
        "sclk_hdmi27m",
@@ -218,7 +218,7 @@ static const char *mout_group2_p[] __initconst = {
        "mout_vpll",
 };
 
-static const char *mout_audio0_p[] __initconst = {
+static const char *mout_audio0_p[] __initdata = {
        "xxti",
        "pcmcdclk0",
        "sclk_hdmi27m",
@@ -230,7 +230,7 @@ static const char *mout_audio0_p[] __initconst = {
        "mout_vpll",
 };
 
-static const char *mout_audio1_p[] __initconst = {
+static const char *mout_audio1_p[] __initdata = {
        "i2scdclk1",
        "pcmcdclk1",
        "sclk_hdmi27m",
@@ -242,7 +242,7 @@ static const char *mout_audio1_p[] __initconst = {
        "mout_vpll",
 };
 
-static const char *mout_audio2_p[] __initconst = {
+static const char *mout_audio2_p[] __initdata = {
        "i2scdclk2",
        "pcmcdclk2",
        "sclk_hdmi27m",
@@ -254,63 +254,63 @@ static const char *mout_audio2_p[] __initconst = {
        "mout_vpll",
 };
 
-static const char *mout_spdif_p[] __initconst = {
+static const char *mout_spdif_p[] __initdata = {
        "dout_audio0",
        "dout_audio1",
        "dout_audio3",
 };
 
-static const char *mout_group3_p[] __initconst = {
+static const char *mout_group3_p[] __initdata = {
        "mout_apll",
        "mout_mpll"
 };
 
-static const char *mout_group4_p[] __initconst = {
+static const char *mout_group4_p[] __initdata = {
        "mout_mpll",
        "dout_a2m"
 };
 
-static const char *mout_flash_p[] __initconst = {
+static const char *mout_flash_p[] __initdata = {
        "dout_hclkd",
        "dout_hclkp"
 };
 
-static const char *mout_dac_p[] __initconst = {
+static const char *mout_dac_p[] __initdata = {
        "mout_vpll",
        "sclk_hdmiphy"
 };
 
-static const char *mout_hdmi_p[] __initconst = {
+static const char *mout_hdmi_p[] __initdata = {
        "sclk_hdmiphy",
        "dout_tblk"
 };
 
-static const char *mout_mixer_p[] __initconst = {
+static const char *mout_mixer_p[] __initdata = {
        "mout_dac",
        "mout_hdmi"
 };
 
-static const char *mout_vpll_6442_p[] __initconst = {
+static const char *mout_vpll_6442_p[] __initdata = {
        "fin_pll",
        "fout_vpll"
 };
 
-static const char *mout_mixer_6442_p[] __initconst = {
+static const char *mout_mixer_6442_p[] __initdata = {
        "mout_vpll",
        "dout_mixer"
 };
 
-static const char *mout_d0sync_6442_p[] __initconst = {
+static const char *mout_d0sync_6442_p[] __initdata = {
        "mout_dsys",
        "div_apll"
 };
 
-static const char *mout_d1sync_6442_p[] __initconst = {
+static const char *mout_d1sync_6442_p[] __initdata = {
        "mout_psys",
        "div_apll"
 };
 
-static const char *mout_group2_6442_p[] __initconst = {
+static const char *mout_group2_6442_p[] __initdata = {
        "fin_pll",
        "none",
        "none",
@@ -322,7 +322,7 @@ static const char *mout_group2_6442_p[] __initconst = {
        "mout_vpll",
 };
 
-static const char *mout_audio0_6442_p[] __initconst = {
+static const char *mout_audio0_6442_p[] __initdata = {
        "fin_pll",
        "pcmcdclk0",
        "none",
@@ -334,7 +334,7 @@ static const char *mout_audio0_6442_p[] __initconst = {
        "mout_vpll",
 };
 
-static const char *mout_audio1_6442_p[] __initconst = {
+static const char *mout_audio1_6442_p[] __initdata = {
        "i2scdclk1",
        "pcmcdclk1",
        "none",
@@ -347,7 +347,7 @@ static const char *mout_audio1_6442_p[] __initconst = {
        "fin_pll",
 };
 
-static const char *mout_clksel_p[] __initconst = {
+static const char *mout_clksel_p[] __initdata = {
        "fout_apll_clkout",
        "fout_mpll_clkout",
        "fout_epll",
@@ -370,7 +370,7 @@ static const char *mout_clksel_p[] __initconst = {
        "div_dclk"
 };
 
-static const char *mout_clksel_6442_p[] __initconst = {
+static const char *mout_clksel_6442_p[] __initdata = {
        "fout_apll_clkout",
        "fout_mpll_clkout",
        "fout_epll",
@@ -393,7 +393,7 @@ static const char *mout_clksel_6442_p[] __initconst = {
        "div_dclk"
 };
 
-static const char *mout_clkout_p[] __initconst = {
+static const char *mout_clkout_p[] __initdata = {
        "dout_clkout",
        "none",
        "xxti",
index 0689d7fb2666b1956728d85f9373b9cbd2c600b1..97c71c885e4f38c5714971818f0fb8d700e7a984 100644 (file)
@@ -2,6 +2,7 @@ obj-$(CONFIG_ARCH_EMEV2)                += clk-emev2.o
 obj-$(CONFIG_ARCH_R7S72100)            += clk-rz.o
 obj-$(CONFIG_ARCH_R8A73A4)             += clk-r8a73a4.o
 obj-$(CONFIG_ARCH_R8A7740)             += clk-r8a7740.o
+obj-$(CONFIG_ARCH_R8A7778)             += clk-r8a7778.o
 obj-$(CONFIG_ARCH_R8A7779)             += clk-r8a7779.o
 obj-$(CONFIG_ARCH_R8A7790)             += clk-rcar-gen2.o
 obj-$(CONFIG_ARCH_R8A7791)             += clk-rcar-gen2.o
diff --git a/drivers/clk/shmobile/clk-r8a7778.c b/drivers/clk/shmobile/clk-r8a7778.c
new file mode 100644 (file)
index 0000000..cb33b57
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * r8a7778 Core CPG Clocks
+ *
+ * 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk/shmobile.h>
+#include <linux/of_address.h>
+
+struct r8a7778_cpg {
+       struct clk_onecell_data data;
+       spinlock_t lock;
+       void __iomem *reg;
+};
+
+/* PLL multipliers per bits 11, 12, and 18 of MODEMR */
+struct {
+       unsigned long plla_mult;
+       unsigned long pllb_mult;
+} r8a7778_rates[] __initdata = {
+       [0] = { 21, 21 },
+       [1] = { 24, 24 },
+       [2] = { 28, 28 },
+       [3] = { 32, 32 },
+       [5] = { 24, 21 },
+       [6] = { 28, 21 },
+       [7] = { 32, 24 },
+};
+
+/* Clock dividers per bits 1 and 2 of MODEMR */
+struct {
+       const char *name;
+       unsigned int div[4];
+} r8a7778_divs[6] __initdata = {
+       { "b",   { 12, 12, 16, 18 } },
+       { "out", { 12, 12, 16, 18 } },
+       { "p",   { 16, 12, 16, 12 } },
+       { "s",   { 4,  3,  4,  3  } },
+       { "s1",  { 8,  6,  8,  6  } },
+};
+
+static u32 cpg_mode_rates __initdata;
+static u32 cpg_mode_divs __initdata;
+
+static struct clk * __init
+r8a7778_cpg_register_clock(struct device_node *np, struct r8a7778_cpg *cpg,
+                            const char *name)
+{
+       if (!strcmp(name, "plla")) {
+               return clk_register_fixed_factor(NULL, "plla",
+                       of_clk_get_parent_name(np, 0), 0,
+                       r8a7778_rates[cpg_mode_rates].plla_mult, 1);
+       } else if (!strcmp(name, "pllb")) {
+               return clk_register_fixed_factor(NULL, "pllb",
+                       of_clk_get_parent_name(np, 0), 0,
+                       r8a7778_rates[cpg_mode_rates].pllb_mult, 1);
+       } else {
+               unsigned int i;
+
+               for (i = 0; i < ARRAY_SIZE(r8a7778_divs); i++) {
+                       if (!strcmp(name, r8a7778_divs[i].name)) {
+                               return clk_register_fixed_factor(NULL,
+                                       r8a7778_divs[i].name,
+                                       "plla", 0, 1,
+                                       r8a7778_divs[i].div[cpg_mode_divs]);
+                       }
+               }
+       }
+
+       return ERR_PTR(-EINVAL);
+}
+
+
+static void __init r8a7778_cpg_clocks_init(struct device_node *np)
+{
+       struct r8a7778_cpg *cpg;
+       struct clk **clks;
+       unsigned int i;
+       int num_clks;
+
+       num_clks = of_property_count_strings(np, "clock-output-names");
+       if (num_clks < 0) {
+               pr_err("%s: failed to count clocks\n", __func__);
+               return;
+       }
+
+       cpg = kzalloc(sizeof(*cpg), GFP_KERNEL);
+       clks = kcalloc(num_clks, sizeof(*clks), GFP_KERNEL);
+       if (cpg == NULL || clks == NULL) {
+               /* We're leaking memory on purpose, there's no point in cleaning
+                * up as the system won't boot anyway.
+                */
+               return;
+       }
+
+       spin_lock_init(&cpg->lock);
+
+       cpg->data.clks = clks;
+       cpg->data.clk_num = num_clks;
+
+       cpg->reg = of_iomap(np, 0);
+       if (WARN_ON(cpg->reg == NULL))
+               return;
+
+       for (i = 0; i < num_clks; ++i) {
+               const char *name;
+               struct clk *clk;
+
+               of_property_read_string_index(np, "clock-output-names", i,
+                                             &name);
+
+               clk = r8a7778_cpg_register_clock(np, cpg, name);
+               if (IS_ERR(clk))
+                       pr_err("%s: failed to register %s %s clock (%ld)\n",
+                              __func__, np->name, name, PTR_ERR(clk));
+               else
+                       cpg->data.clks[i] = clk;
+       }
+
+       of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data);
+}
+
+CLK_OF_DECLARE(r8a7778_cpg_clks, "renesas,r8a7778-cpg-clocks",
+              r8a7778_cpg_clocks_init);
+
+void __init r8a7778_clocks_init(u32 mode)
+{
+       BUG_ON(!(mode & BIT(19)));
+
+       cpg_mode_rates = (!!(mode & BIT(18)) << 2) |
+                        (!!(mode & BIT(12)) << 1) |
+                        (!!(mode & BIT(11)));
+       cpg_mode_divs = (!!(mode & BIT(2)) << 1) |
+                       (!!(mode & BIT(1)));
+
+       of_clk_init(NULL);
+}
index af94ed82cfcb3c94ce9408d57a4a68a4cd08dda6..a917c4c7eaa9c2f6709985c544a4370494e29b38 100644 (file)
@@ -1057,7 +1057,7 @@ static struct clk * __init st_clk_register_quadfs_fsynth(
        return clk;
 }
 
-static struct of_device_id quadfs_of_match[] = {
+static const struct of_device_id quadfs_of_match[] = {
        {
                .compatible = "st,stih416-quadfs216",
                .data = &st_fs216c65_416
index 9a15ec344a85900ea68029c730c02ad01ede5335..fdcff10f6d3089ec389b21522e178db32eaaa911 100644 (file)
@@ -341,7 +341,7 @@ static struct clkgena_divmux_data st_divmux_c32odf3 = {
        .fb_start_bit_idx = 24,
 };
 
-static struct of_device_id clkgena_divmux_of_match[] = {
+static const struct of_device_id clkgena_divmux_of_match[] = {
        {
                .compatible = "st,clkgena-divmux-c65-hs",
                .data = &st_divmux_c65hs,
@@ -479,7 +479,7 @@ static struct clkgena_prediv_data prediv_c32_data = {
        .table = prediv_table16,
 };
 
-static struct of_device_id clkgena_prediv_of_match[] = {
+static const struct of_device_id clkgena_prediv_of_match[] = {
        { .compatible = "st,clkgena-prediv-c65", .data = &prediv_c65_data },
        { .compatible = "st,clkgena-prediv-c32", .data = &prediv_c32_data },
        {}
@@ -586,7 +586,7 @@ static struct clkgen_mux_data stih407_a9_mux_data = {
        .width = 2,
 };
 
-static struct of_device_id mux_of_match[] = {
+static const struct of_device_id mux_of_match[] = {
        {
                .compatible = "st,stih416-clkgenc-vcc-hd",
                .data = &clkgen_mux_c_vcc_hd_416,
@@ -693,7 +693,7 @@ static struct clkgen_vcc_data st_clkgenf_vcc_416 = {
        .lock = &clkgenf_lock,
 };
 
-static struct of_device_id vcc_of_match[] = {
+static const struct of_device_id vcc_of_match[] = {
        { .compatible = "st,stih416-clkgenc", .data = &st_clkgenc_vcc_416 },
        { .compatible = "st,stih416-clkgenf", .data = &st_clkgenf_vcc_416 },
        {}
index 29769d79e3065d8bfd32ed64c2fcc38e5c0d54cb..d204ba85db3a423d6b404cb825c873c2815850e2 100644 (file)
@@ -593,7 +593,7 @@ static struct clk * __init clkgen_odf_register(const char *parent_name,
        return clk;
 }
 
-static struct of_device_id c32_pll_of_match[] = {
+static const struct of_device_id c32_pll_of_match[] = {
        {
                .compatible = "st,plls-c32-a1x-0",
                .data = &st_pll3200c32_a1x_0,
@@ -708,7 +708,7 @@ err:
 }
 CLK_OF_DECLARE(clkgen_c32_pll, "st,clkgen-plls-c32", clkgen_c32_pll_setup);
 
-static struct of_device_id c32_gpu_pll_of_match[] = {
+static const struct of_device_id c32_gpu_pll_of_match[] = {
        {
                .compatible = "st,stih415-gpu-pll-c32",
                .data = &st_pll1200c32_gpu_415,
index 3a5292e3fcf8086f6418c8dceae6c59aab79b082..058f273d6154745d0fc4173677ee533cbd04a243 100644 (file)
@@ -9,6 +9,7 @@ obj-y += clk-mod0.o
 obj-y += clk-sun8i-mbus.o
 obj-y += clk-sun9i-core.o
 obj-y += clk-sun9i-mmc.o
+obj-y += clk-usb.o
 
 obj-$(CONFIG_MFD_SUN6I_PRCM) += \
        clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \
index 379324eb5486e1b332d19fcf66fc8d7a0c4aff15..7e1e2bd189b6a6f6f3c0047d6b3f4d6b5899c3c6 100644 (file)
@@ -481,6 +481,45 @@ static void sun6i_a31_get_pll6_factors(u32 *freq, u32 parent_rate,
        *n = DIV_ROUND_UP(div, (*k+1)) - 1;
 }
 
+/**
+ * sun5i_a13_get_ahb_factors() - calculates m, p factors for AHB
+ * AHB rate is calculated as follows
+ * rate = parent_rate >> p
+ */
+
+static void sun5i_a13_get_ahb_factors(u32 *freq, u32 parent_rate,
+                                      u8 *n, u8 *k, u8 *m, u8 *p)
+{
+       u32 div;
+
+       /* divide only */
+       if (parent_rate < *freq)
+               *freq = parent_rate;
+
+       /*
+        * user manual says valid speed is 8k ~ 276M, but tests show it
+        * can work at speeds up to 300M, just after reparenting to pll6
+        */
+       if (*freq < 8000)
+               *freq = 8000;
+       if (*freq > 300000000)
+               *freq = 300000000;
+
+       div = order_base_2(DIV_ROUND_UP(parent_rate, *freq));
+
+       /* p = 0 ~ 3 */
+       if (div > 3)
+               div = 3;
+
+       *freq = parent_rate >> div;
+
+       /* we were called to round the frequency, we can now return */
+       if (p == NULL)
+               return;
+
+       *p = div;
+}
+
 /**
  * sun4i_get_apb1_factors() - calculates m, p factors for APB1
  * APB1 rate is calculated as follows
@@ -616,6 +655,11 @@ static struct clk_factors_config sun6i_a31_pll6_config = {
        .n_start = 1,
 };
 
+static struct clk_factors_config sun5i_a13_ahb_config = {
+       .pshift = 4,
+       .pwidth = 2,
+};
+
 static struct clk_factors_config sun4i_apb1_config = {
        .mshift = 0,
        .mwidth = 5,
@@ -676,6 +720,13 @@ static const struct factors_data sun6i_a31_pll6_data __initconst = {
        .name = "pll6x2",
 };
 
+static const struct factors_data sun5i_a13_ahb_data __initconst = {
+       .mux = 6,
+       .muxmask = BIT(1) | BIT(0),
+       .table = &sun5i_a13_ahb_config,
+       .getter = sun5i_a13_get_ahb_factors,
+};
+
 static const struct factors_data sun4i_apb1_data __initconst = {
        .mux = 24,
        .muxmask = BIT(1) | BIT(0),
@@ -837,59 +888,6 @@ static void __init sunxi_divider_clk_setup(struct device_node *node,
 
 
 
-/**
- * sunxi_gates_reset... - reset bits in leaf gate clk registers handling
- */
-
-struct gates_reset_data {
-       void __iomem                    *reg;
-       spinlock_t                      *lock;
-       struct reset_controller_dev     rcdev;
-};
-
-static int sunxi_gates_reset_assert(struct reset_controller_dev *rcdev,
-                             unsigned long id)
-{
-       struct gates_reset_data *data = container_of(rcdev,
-                                                    struct gates_reset_data,
-                                                    rcdev);
-       unsigned long flags;
-       u32 reg;
-
-       spin_lock_irqsave(data->lock, flags);
-
-       reg = readl(data->reg);
-       writel(reg & ~BIT(id), data->reg);
-
-       spin_unlock_irqrestore(data->lock, flags);
-
-       return 0;
-}
-
-static int sunxi_gates_reset_deassert(struct reset_controller_dev *rcdev,
-                               unsigned long id)
-{
-       struct gates_reset_data *data = container_of(rcdev,
-                                                    struct gates_reset_data,
-                                                    rcdev);
-       unsigned long flags;
-       u32 reg;
-
-       spin_lock_irqsave(data->lock, flags);
-
-       reg = readl(data->reg);
-       writel(reg | BIT(id), data->reg);
-
-       spin_unlock_irqrestore(data->lock, flags);
-
-       return 0;
-}
-
-static struct reset_control_ops sunxi_gates_reset_ops = {
-       .assert         = sunxi_gates_reset_assert,
-       .deassert       = sunxi_gates_reset_deassert,
-};
-
 /**
  * sunxi_gates_clk_setup() - Setup function for leaf gates on clocks
  */
@@ -898,7 +896,6 @@ static struct reset_control_ops sunxi_gates_reset_ops = {
 
 struct gates_data {
        DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE);
-       u32 reset_mask;
 };
 
 static const struct gates_data sun4i_axi_gates_data __initconst = {
@@ -997,26 +994,10 @@ static const struct gates_data sun8i_a23_apb2_gates_data __initconst = {
        .mask = {0x1F0007},
 };
 
-static const struct gates_data sun4i_a10_usb_gates_data __initconst = {
-       .mask = {0x1C0},
-       .reset_mask = 0x07,
-};
-
-static const struct gates_data sun5i_a13_usb_gates_data __initconst = {
-       .mask = {0x140},
-       .reset_mask = 0x03,
-};
-
-static const struct gates_data sun6i_a31_usb_gates_data __initconst = {
-       .mask = { BIT(18) | BIT(17) | BIT(16) | BIT(10) | BIT(9) | BIT(8) },
-       .reset_mask = BIT(2) | BIT(1) | BIT(0),
-};
-
 static void __init sunxi_gates_clk_setup(struct device_node *node,
                                         struct gates_data *data)
 {
        struct clk_onecell_data *clk_data;
-       struct gates_reset_data *reset_data;
        const char *clk_parent;
        const char *clk_name;
        void __iomem *reg;
@@ -1057,21 +1038,6 @@ static void __init sunxi_gates_clk_setup(struct device_node *node,
        clk_data->clk_num = i;
 
        of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
-
-       /* Register a reset controler for gates with reset bits */
-       if (data->reset_mask == 0)
-               return;
-
-       reset_data = kzalloc(sizeof(*reset_data), GFP_KERNEL);
-       if (!reset_data)
-               return;
-
-       reset_data->reg = reg;
-       reset_data->lock = &clk_lock;
-       reset_data->rcdev.nr_resets = __fls(data->reset_mask) + 1;
-       reset_data->rcdev.ops = &sunxi_gates_reset_ops;
-       reset_data->rcdev.of_node = node;
-       reset_controller_register(&reset_data->rcdev);
 }
 
 
@@ -1080,13 +1046,20 @@ static void __init sunxi_gates_clk_setup(struct device_node *node,
  * sunxi_divs_clk_setup() helper data
  */
 
-#define SUNXI_DIVS_MAX_QTY     2
+#define SUNXI_DIVS_MAX_QTY     4
 #define SUNXI_DIVISOR_WIDTH    2
 
 struct divs_data {
        const struct factors_data *factors; /* data for the factor clock */
-       int ndivs; /* number of children */
+       int ndivs; /* number of outputs */
+       /*
+        * List of outputs. Refer to the diagram for sunxi_divs_clk_setup():
+        * self or base factor clock refers to the output from the pll
+        * itself. The remaining refer to fixed or configurable divider
+        * outputs.
+        */
        struct {
+               u8 self; /* is it the base factor clock? (only one) */
                u8 fixed; /* is it a fixed divisor? if not... */
                struct clk_div_table *table; /* is it a table based divisor? */
                u8 shift; /* otherwise it's a normal divisor with this shift */
@@ -1109,23 +1082,27 @@ static const struct divs_data pll5_divs_data __initconst = {
        .div = {
                { .shift = 0, .pow = 0, }, /* M, DDR */
                { .shift = 16, .pow = 1, }, /* P, other */
+               /* No output for the base factor clock */
        }
 };
 
 static const struct divs_data pll6_divs_data __initconst = {
        .factors = &sun4i_pll6_data,
-       .ndivs = 2,
+       .ndivs = 4,
        .div = {
                { .shift = 0, .table = pll6_sata_tbl, .gate = 14 }, /* M, SATA */
                { .fixed = 2 }, /* P, other */
+               { .self = 1 }, /* base factor clock, 2x */
+               { .fixed = 4 }, /* pll6 / 4, used as ahb input */
        }
 };
 
 static const struct divs_data sun6i_a31_pll6_divs_data __initconst = {
        .factors = &sun6i_a31_pll6_data,
-       .ndivs = 1,
+       .ndivs = 2,
        .div = {
                { .fixed = 2 }, /* normal output */
+               { .self = 1 }, /* base factor clock, 2x */
        }
 };
 
@@ -1156,6 +1133,10 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
        int ndivs = SUNXI_DIVS_MAX_QTY, i = 0;
        int flags, clkflags;
 
+       /* if number of children known, use it */
+       if (data->ndivs)
+               ndivs = data->ndivs;
+
        /* Set up factor clock that we will be dividing */
        pclk = sunxi_factors_clk_setup(node, data->factors);
        parent = __clk_get_name(pclk);
@@ -1166,7 +1147,7 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
        if (!clk_data)
                return;
 
-       clks = kzalloc((SUNXI_DIVS_MAX_QTY+1) * sizeof(*clks), GFP_KERNEL);
+       clks = kcalloc(ndivs, sizeof(*clks), GFP_KERNEL);
        if (!clks)
                goto free_clkdata;
 
@@ -1176,15 +1157,17 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
         * our RAM clock! */
        clkflags = !strcmp("pll5", parent) ? 0 : CLK_SET_RATE_PARENT;
 
-       /* if number of children known, use it */
-       if (data->ndivs)
-               ndivs = data->ndivs;
-
        for (i = 0; i < ndivs; i++) {
                if (of_property_read_string_index(node, "clock-output-names",
                                                  i, &clk_name) != 0)
                        break;
 
+               /* If this is the base factor clock, only update clks */
+               if (data->div[i].self) {
+                       clk_data->clks[i] = pclk;
+                       continue;
+               }
+
                gate_hw = NULL;
                rate_hw = NULL;
                rate_ops = NULL;
@@ -1243,9 +1226,6 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
                clk_register_clkdev(clks[i], clk_name, NULL);
        }
 
-       /* The last clock available on the getter is the parent */
-       clks[i++] = pclk;
-
        /* Adjust to the real max */
        clk_data->clk_num = i;
 
@@ -1269,6 +1249,7 @@ static const struct of_device_id clk_factors_match[] __initconst = {
        {.compatible = "allwinner,sun6i-a31-pll1-clk", .data = &sun6i_a31_pll1_data,},
        {.compatible = "allwinner,sun8i-a23-pll1-clk", .data = &sun8i_a23_pll1_data,},
        {.compatible = "allwinner,sun7i-a20-pll4-clk", .data = &sun7i_a20_pll4_data,},
+       {.compatible = "allwinner,sun5i-a13-ahb-clk", .data = &sun5i_a13_ahb_data,},
        {.compatible = "allwinner,sun4i-a10-apb1-clk", .data = &sun4i_apb1_data,},
        {.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,},
        {}
@@ -1324,9 +1305,6 @@ static const struct of_device_id clk_gates_match[] __initconst = {
        {.compatible = "allwinner,sun9i-a80-apb1-gates-clk", .data = &sun9i_a80_apb1_gates_data,},
        {.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,},
        {.compatible = "allwinner,sun8i-a23-apb2-gates-clk", .data = &sun8i_a23_apb2_gates_data,},
-       {.compatible = "allwinner,sun4i-a10-usb-clk", .data = &sun4i_a10_usb_gates_data,},
-       {.compatible = "allwinner,sun5i-a13-usb-clk", .data = &sun5i_a13_usb_gates_data,},
-       {.compatible = "allwinner,sun6i-a31-usb-clk", .data = &sun6i_a31_usb_gates_data,},
        {}
 };
 
@@ -1348,15 +1326,15 @@ static void __init sunxi_init_clocks(const char *clocks[], int nclocks)
 {
        unsigned int i;
 
+       /* Register divided output clocks */
+       of_sunxi_table_clock_setup(clk_divs_match, sunxi_divs_clk_setup);
+
        /* Register factor clocks */
        of_sunxi_table_clock_setup(clk_factors_match, sunxi_factors_clk_setup);
 
        /* Register divider clocks */
        of_sunxi_table_clock_setup(clk_div_match, sunxi_divider_clk_setup);
 
-       /* Register divided output clocks */
-       of_sunxi_table_clock_setup(clk_divs_match, sunxi_divs_clk_setup);
-
        /* Register mux clocks */
        of_sunxi_table_clock_setup(clk_mux_match, sunxi_mux_clk_setup);
 
@@ -1385,6 +1363,7 @@ static void __init sun4i_a10_init_clocks(struct device_node *node)
 CLK_OF_DECLARE(sun4i_a10_clk_init, "allwinner,sun4i-a10", sun4i_a10_init_clocks);
 
 static const char *sun5i_critical_clocks[] __initdata = {
+       "cpu",
        "pll5_ddr",
        "ahb_sdram",
 };
diff --git a/drivers/clk/sunxi/clk-usb.c b/drivers/clk/sunxi/clk-usb.c
new file mode 100644 (file)
index 0000000..a86ed2f
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * Copyright 2013-2015 Emilio López
+ *
+ * Emilio López <emilio@elopez.com.ar>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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-provider.h>
+#include <linux/clkdev.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/reset-controller.h>
+#include <linux/spinlock.h>
+
+
+/**
+ * sunxi_usb_reset... - reset bits in usb clk registers handling
+ */
+
+struct usb_reset_data {
+       void __iomem                    *reg;
+       spinlock_t                      *lock;
+       struct clk                      *clk;
+       struct reset_controller_dev     rcdev;
+};
+
+static int sunxi_usb_reset_assert(struct reset_controller_dev *rcdev,
+                             unsigned long id)
+{
+       struct usb_reset_data *data = container_of(rcdev,
+                                                  struct usb_reset_data,
+                                                  rcdev);
+       unsigned long flags;
+       u32 reg;
+
+       clk_prepare_enable(data->clk);
+       spin_lock_irqsave(data->lock, flags);
+
+       reg = readl(data->reg);
+       writel(reg & ~BIT(id), data->reg);
+
+       spin_unlock_irqrestore(data->lock, flags);
+       clk_disable_unprepare(data->clk);
+
+       return 0;
+}
+
+static int sunxi_usb_reset_deassert(struct reset_controller_dev *rcdev,
+                               unsigned long id)
+{
+       struct usb_reset_data *data = container_of(rcdev,
+                                                    struct usb_reset_data,
+                                                    rcdev);
+       unsigned long flags;
+       u32 reg;
+
+       clk_prepare_enable(data->clk);
+       spin_lock_irqsave(data->lock, flags);
+
+       reg = readl(data->reg);
+       writel(reg | BIT(id), data->reg);
+
+       spin_unlock_irqrestore(data->lock, flags);
+       clk_disable_unprepare(data->clk);
+
+       return 0;
+}
+
+static struct reset_control_ops sunxi_usb_reset_ops = {
+       .assert         = sunxi_usb_reset_assert,
+       .deassert       = sunxi_usb_reset_deassert,
+};
+
+/**
+ * sunxi_usb_clk_setup() - Setup function for usb gate clocks
+ */
+
+#define SUNXI_USB_MAX_SIZE 32
+
+struct usb_clk_data {
+       u32 clk_mask;
+       u32 reset_mask;
+       bool reset_needs_clk;
+};
+
+static void __init sunxi_usb_clk_setup(struct device_node *node,
+                                      const struct usb_clk_data *data,
+                                      spinlock_t *lock)
+{
+       struct clk_onecell_data *clk_data;
+       struct usb_reset_data *reset_data;
+       const char *clk_parent;
+       const char *clk_name;
+       void __iomem *reg;
+       int qty;
+       int i = 0;
+       int j = 0;
+
+       reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+       if (IS_ERR(reg))
+               return;
+
+       clk_parent = of_clk_get_parent_name(node, 0);
+       if (!clk_parent)
+               return;
+
+       /* Worst-case size approximation and memory allocation */
+       qty = find_last_bit((unsigned long *)&data->clk_mask,
+                           SUNXI_USB_MAX_SIZE);
+
+       clk_data = kmalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
+       if (!clk_data)
+               return;
+
+       clk_data->clks = kzalloc((qty+1) * sizeof(struct clk *), GFP_KERNEL);
+       if (!clk_data->clks) {
+               kfree(clk_data);
+               return;
+       }
+
+       for_each_set_bit(i, (unsigned long *)&data->clk_mask,
+                        SUNXI_USB_MAX_SIZE) {
+               of_property_read_string_index(node, "clock-output-names",
+                                             j, &clk_name);
+               clk_data->clks[i] = clk_register_gate(NULL, clk_name,
+                                                     clk_parent, 0,
+                                                     reg, i, 0, lock);
+               WARN_ON(IS_ERR(clk_data->clks[i]));
+
+               j++;
+       }
+
+       /* Adjust to the real max */
+       clk_data->clk_num = i;
+
+       of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+       /* Register a reset controller for usb with reset bits */
+       if (data->reset_mask == 0)
+               return;
+
+       reset_data = kzalloc(sizeof(*reset_data), GFP_KERNEL);
+       if (!reset_data)
+               return;
+
+       if (data->reset_needs_clk) {
+               reset_data->clk = of_clk_get(node, 0);
+               if (IS_ERR(reset_data->clk)) {
+                       pr_err("Could not get clock for reset controls\n");
+                       kfree(reset_data);
+                       return;
+               }
+       }
+
+       reset_data->reg = reg;
+       reset_data->lock = lock;
+       reset_data->rcdev.nr_resets = __fls(data->reset_mask) + 1;
+       reset_data->rcdev.ops = &sunxi_usb_reset_ops;
+       reset_data->rcdev.of_node = node;
+       reset_controller_register(&reset_data->rcdev);
+}
+
+static const struct usb_clk_data sun4i_a10_usb_clk_data __initconst = {
+       .clk_mask = BIT(8) | BIT(7) | BIT(6),
+       .reset_mask = BIT(2) | BIT(1) | BIT(0),
+};
+
+static DEFINE_SPINLOCK(sun4i_a10_usb_lock);
+
+static void __init sun4i_a10_usb_setup(struct device_node *node)
+{
+       sunxi_usb_clk_setup(node, &sun4i_a10_usb_clk_data, &sun4i_a10_usb_lock);
+}
+CLK_OF_DECLARE(sun4i_a10_usb, "allwinner,sun4i-a10-usb-clk", sun4i_a10_usb_setup);
+
+static const struct usb_clk_data sun5i_a13_usb_clk_data __initconst = {
+       .clk_mask = BIT(8) | BIT(6),
+       .reset_mask = BIT(1) | BIT(0),
+};
+
+static void __init sun5i_a13_usb_setup(struct device_node *node)
+{
+       sunxi_usb_clk_setup(node, &sun5i_a13_usb_clk_data, &sun4i_a10_usb_lock);
+}
+CLK_OF_DECLARE(sun5i_a13_usb, "allwinner,sun5i-a13-usb-clk", sun5i_a13_usb_setup);
+
+static const struct usb_clk_data sun6i_a31_usb_clk_data __initconst = {
+       .clk_mask = BIT(18) | BIT(17) | BIT(16) | BIT(10) | BIT(9) | BIT(8),
+       .reset_mask = BIT(2) | BIT(1) | BIT(0),
+};
+
+static void __init sun6i_a31_usb_setup(struct device_node *node)
+{
+       sunxi_usb_clk_setup(node, &sun6i_a31_usb_clk_data, &sun4i_a10_usb_lock);
+}
+CLK_OF_DECLARE(sun6i_a31_usb, "allwinner,sun6i-a31-usb-clk", sun6i_a31_usb_setup);
+
+static const struct usb_clk_data sun9i_a80_usb_mod_data __initconst = {
+       .clk_mask = BIT(6) | BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(1),
+       .reset_mask = BIT(19) | BIT(18) | BIT(17),
+       .reset_needs_clk = 1,
+};
+
+static DEFINE_SPINLOCK(a80_usb_mod_lock);
+
+static void __init sun9i_a80_usb_mod_setup(struct device_node *node)
+{
+       sunxi_usb_clk_setup(node, &sun9i_a80_usb_mod_data, &a80_usb_mod_lock);
+}
+CLK_OF_DECLARE(sun9i_a80_usb_mod, "allwinner,sun9i-a80-usb-mod-clk", sun9i_a80_usb_mod_setup);
+
+static const struct usb_clk_data sun9i_a80_usb_phy_data __initconst = {
+       .clk_mask = BIT(10) | BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(1),
+       .reset_mask = BIT(21) | BIT(20) | BIT(19) | BIT(18) | BIT(17),
+       .reset_needs_clk = 1,
+};
+
+static DEFINE_SPINLOCK(a80_usb_phy_lock);
+
+static void __init sun9i_a80_usb_phy_setup(struct device_node *node)
+{
+       sunxi_usb_clk_setup(node, &sun9i_a80_usb_phy_data, &a80_usb_phy_lock);
+}
+CLK_OF_DECLARE(sun9i_a80_usb_phy, "allwinner,sun9i-a80-usb-phy-clk", sun9i_a80_usb_phy_setup);
index bfef9abdf23250d39504587f7f41d3ca6ec6e06a..05c6d08a6695861344713919e0474cc05a3c701e 100644 (file)
@@ -981,7 +981,7 @@ static int clk_pllxc_set_rate(struct clk_hw *hw, unsigned long rate,
        struct tegra_clk_pll *pll = to_clk_pll(hw);
        struct tegra_clk_pll_freq_table cfg, old_cfg;
        unsigned long flags = 0;
-       int ret = 0;
+       int ret;
 
        ret = _pll_ramp_calc_pll(hw, &cfg, rate, parent_rate);
        if (ret < 0)
@@ -1005,7 +1005,7 @@ static long clk_pll_ramp_round_rate(struct clk_hw *hw, unsigned long rate,
                                unsigned long *prate)
 {
        struct tegra_clk_pll_freq_table cfg;
-       int ret = 0, p_div;
+       int ret, p_div;
        u64 output_rate = *prate;
 
        ret = _pll_ramp_calc_pll(hw, &cfg, rate, *prate);
@@ -1073,7 +1073,7 @@ static int clk_pllc_enable(struct clk_hw *hw)
 {
        struct tegra_clk_pll *pll = to_clk_pll(hw);
        u32 val;
-       int ret = 0;
+       int ret;
        unsigned long flags = 0;
 
        if (pll->lock)
@@ -1223,6 +1223,7 @@ static long _pllre_calc_rate(struct tegra_clk_pll *pll,
 
        return output_rate;
 }
+
 static int clk_pllre_set_rate(struct clk_hw *hw, unsigned long rate,
                                unsigned long parent_rate)
 {
index f3b773833429df14c1272fc0529e28c99cc2917b..605676d368eb49acdb7c57d1740e2af151a81279 100644 (file)
 #define OSC_CTRL_OSC_FREQ_SHIFT                28
 #define OSC_CTRL_PLL_REF_DIV_SHIFT     26
 
-int __init tegra_osc_clk_init(void __iomem *clk_base,
-                               struct tegra_clk *tegra_clks,
-                               unsigned long *input_freqs, int num,
-                               unsigned long *osc_freq,
-                               unsigned long *pll_ref_freq)
+int __init tegra_osc_clk_init(void __iomem *clk_base, struct tegra_clk *clks,
+                             unsigned long *input_freqs, unsigned int num,
+                             unsigned int clk_m_div, unsigned long *osc_freq,
+                             unsigned long *pll_ref_freq)
 {
-       struct clk *clk;
+       struct clk *clk, *osc;
        struct clk **dt_clk;
        u32 val, pll_ref_div;
        unsigned osc_idx;
@@ -54,22 +53,25 @@ int __init tegra_osc_clk_init(void __iomem *clk_base,
                return -EINVAL;
        }
 
-       dt_clk = tegra_lookup_dt_id(tegra_clk_clk_m, tegra_clks);
+       osc = clk_register_fixed_rate(NULL, "osc", NULL, CLK_IS_ROOT,
+                                     *osc_freq);
+
+       dt_clk = tegra_lookup_dt_id(tegra_clk_clk_m, clks);
        if (!dt_clk)
                return 0;
 
-       clk = clk_register_fixed_rate(NULL, "clk_m", NULL, CLK_IS_ROOT,
-                                     *osc_freq);
+       clk = clk_register_fixed_factor(NULL, "clk_m", "osc",
+                                       0, 1, clk_m_div);
        *dt_clk = clk;
 
        /* pll_ref */
        val = (val >> OSC_CTRL_PLL_REF_DIV_SHIFT) & 3;
        pll_ref_div = 1 << val;
-       dt_clk = tegra_lookup_dt_id(tegra_clk_pll_ref, tegra_clks);
+       dt_clk = tegra_lookup_dt_id(tegra_clk_pll_ref, clks);
        if (!dt_clk)
                return 0;
 
-       clk = clk_register_fixed_factor(NULL, "pll_ref", "clk_m",
+       clk = clk_register_fixed_factor(NULL, "pll_ref", "osc",
                                        0, 1, pll_ref_div);
        *dt_clk = clk;
 
index cef0727b9eec98b91de3db3c2373fe8e508e5750..46af9244ba74576f23e3e27dc9b2380cb0d39686 100644 (file)
                .clk_id = _clk_id,                                      \
                .p.parent_name = _parent_name,                          \
                .periph = TEGRA_CLK_PERIPH(0, 0, 0, 0, 0, 0, 0,         \
-                               _clk_num, _gate_flags, 0, NULL),        \
+                               _clk_num, _gate_flags, NULL, NULL),     \
                .flags = _flags                                         \
        }
 
index d0766423a5d607554ff8f9e9f9b7f610f5d875a3..8237d16b407597dab129c5a277802190898a061f 100644 (file)
@@ -940,36 +940,6 @@ static struct clk **clks;
 static unsigned long osc_freq;
 static unsigned long pll_ref_freq;
 
-static int __init tegra114_osc_clk_init(void __iomem *clk_base)
-{
-       struct clk *clk;
-       u32 val, pll_ref_div;
-
-       val = readl_relaxed(clk_base + OSC_CTRL);
-
-       osc_freq = tegra114_input_freq[val >> OSC_CTRL_OSC_FREQ_SHIFT];
-       if (!osc_freq) {
-               WARN_ON(1);
-               return -EINVAL;
-       }
-
-       /* clk_m */
-       clk = clk_register_fixed_rate(NULL, "clk_m", NULL, CLK_IS_ROOT,
-                                     osc_freq);
-       clks[TEGRA114_CLK_CLK_M] = clk;
-
-       /* pll_ref */
-       val = (val >> OSC_CTRL_PLL_REF_DIV_SHIFT) & 3;
-       pll_ref_div = 1 << val;
-       clk = clk_register_fixed_factor(NULL, "pll_ref", "clk_m",
-                                       CLK_SET_RATE_PARENT, 1, pll_ref_div);
-       clks[TEGRA114_CLK_PLL_REF] = clk;
-
-       pll_ref_freq = osc_freq / pll_ref_div;
-
-       return 0;
-}
-
 static void __init tegra114_fixed_clk_init(void __iomem *clk_base)
 {
        struct clk *clk;
@@ -1263,6 +1233,7 @@ static void tegra114_wait_cpu_in_reset(u32 cpu)
                cpu_relax();
        } while (!(reg & (1 << cpu)));  /* check CPU been reset or not */
 }
+
 static void tegra114_disable_cpu_clock(u32 cpu)
 {
        /* flow controller would take care in the power sequence. */
@@ -1351,7 +1322,6 @@ static void __init tegra114_clock_apply_init_table(void)
        tegra_init_from_table(init_table, clks, TEGRA114_CLK_CLK_MAX);
 }
 
-
 /**
  * tegra114_car_barrier - wait for pending writes to the CAR to complete
  *
@@ -1505,7 +1475,9 @@ static void __init tegra114_clock_init(struct device_node *np)
        if (!clks)
                return;
 
-       if (tegra114_osc_clk_init(clk_base) < 0)
+       if (tegra_osc_clk_init(clk_base, tegra114_clks, tegra114_input_freq,
+                              ARRAY_SIZE(tegra114_input_freq), 1, &osc_freq,
+                              &pll_ref_freq) < 0)
                return;
 
        tegra114_fixed_clk_init(clk_base);
index 9a893f2fe8e9889e7e1df95d12ba90d687763942..11f857cd5f6a2bf01d86dc2b95497905d971a85e 100644 (file)
@@ -1014,6 +1014,9 @@ static struct tegra_devclk devclks[] __initdata = {
        { .con_id = "fuse", .dt_id = TEGRA124_CLK_FUSE },
        { .dev_id = "rtc-tegra", .dt_id = TEGRA124_CLK_RTC },
        { .dev_id = "timer", .dt_id = TEGRA124_CLK_TIMER },
+       { .con_id = "hda", .dt_id = TEGRA124_CLK_HDA },
+       { .con_id = "hda2codec_2x", .dt_id = TEGRA124_CLK_HDA2CODEC_2X },
+       { .con_id = "hda2hdmi", .dt_id = TEGRA124_CLK_HDA2HDMI },
 };
 
 static struct clk **clks;
@@ -1110,16 +1113,18 @@ static __init void tegra124_periph_clk_init(void __iomem *clk_base,
                                        1, 2);
        clks[TEGRA124_CLK_XUSB_SS_DIV2] = clk;
 
-       clk = clk_register_gate(NULL, "plld_dsi", "plld_out0", 0,
+       clk = clk_register_gate(NULL, "pll_d_dsi_out", "pll_d_out0", 0,
                                clk_base + PLLD_MISC, 30, 0, &pll_d_lock);
-       clks[TEGRA124_CLK_PLLD_DSI] = clk;
+       clks[TEGRA124_CLK_PLL_D_DSI_OUT] = clk;
 
-       clk = tegra_clk_register_periph_gate("dsia", "plld_dsi", 0, clk_base,
-                                            0, 48, periph_clk_enb_refcnt);
+       clk = tegra_clk_register_periph_gate("dsia", "pll_d_dsi_out", 0,
+                                            clk_base, 0, 48,
+                                            periph_clk_enb_refcnt);
        clks[TEGRA124_CLK_DSIA] = clk;
 
-       clk = tegra_clk_register_periph_gate("dsib", "plld_dsi", 0, clk_base,
-                                            0, 82, periph_clk_enb_refcnt);
+       clk = tegra_clk_register_periph_gate("dsib", "pll_d_dsi_out", 0,
+                                            clk_base, 0, 82,
+                                            periph_clk_enb_refcnt);
        clks[TEGRA124_CLK_DSIB] = clk;
 
        /* emc mux */
@@ -1395,6 +1400,8 @@ static struct tegra_clk_init_table common_init_table[] __initdata = {
 static struct tegra_clk_init_table tegra124_init_table[] __initdata = {
        {TEGRA124_CLK_SOC_THERM, TEGRA124_CLK_PLL_P, 51000000, 0},
        {TEGRA124_CLK_CCLK_G, TEGRA124_CLK_CLK_MAX, 0, 1},
+       {TEGRA124_CLK_HDA, TEGRA124_CLK_PLL_P, 102000000, 0},
+       {TEGRA124_CLK_HDA2CODEC_2X, TEGRA124_CLK_PLL_P, 48000000, 0},
        /* This MUST be the last entry. */
        {TEGRA124_CLK_CLK_MAX, TEGRA124_CLK_CLK_MAX, 0, 0},
 };
@@ -1475,7 +1482,8 @@ static void __init tegra124_132_clock_init_pre(struct device_node *np)
                return;
 
        if (tegra_osc_clk_init(clk_base, tegra124_clks, tegra124_input_freq,
-               ARRAY_SIZE(tegra124_input_freq), &osc_freq, &pll_ref_freq) < 0)
+                              ARRAY_SIZE(tegra124_input_freq), 1, &osc_freq,
+                              &pll_ref_freq) < 0)
                return;
 
        tegra_fixed_clk_init(tegra124_clks);
index 4b9d8bd3d0bfdd8e93f0436ea3bd0f016d5091fb..4b26509fc21857ede7ea3c41ed79d4fad3175c8f 100644 (file)
@@ -657,16 +657,16 @@ static struct tegra_devclk devclks[] __initdata = {
        { .con_id = "fuse_burn", .dev_id = "fuse-tegra", .dt_id = TEGRA30_CLK_FUSE_BURN },
        { .con_id = "apbif", .dev_id = "tegra30-ahub", .dt_id = TEGRA30_CLK_APBIF },
        { .con_id = "hda2hdmi", .dev_id = "tegra30-hda", .dt_id = TEGRA30_CLK_HDA2HDMI },
-       { .dev_id =  "tegra-apbdma", .dt_id = TEGRA30_CLK_APBDMA },
-       { .dev_id =  "rtc-tegra", .dt_id = TEGRA30_CLK_RTC },
-       { .dev_id =  "timer", .dt_id = TEGRA30_CLK_TIMER },
-       { .dev_id =  "tegra-kbc", .dt_id = TEGRA30_CLK_KBC },
-       { .dev_id =  "fsl-tegra-udc", .dt_id = TEGRA30_CLK_USBD },
-       { .dev_id =  "tegra-ehci.1", .dt_id = TEGRA30_CLK_USB2 },
-       { .dev_id =  "tegra-ehci.2", .dt_id = TEGRA30_CLK_USB2 },
-       { .dev_id =  "kfuse-tegra", .dt_id = TEGRA30_CLK_KFUSE },
-       { .dev_id =  "tegra_sata_cold", .dt_id = TEGRA30_CLK_SATA_COLD },
-       { .dev_id =  "dtv", .dt_id = TEGRA30_CLK_DTV },
+       { .dev_id = "tegra-apbdma", .dt_id = TEGRA30_CLK_APBDMA },
+       { .dev_id = "rtc-tegra", .dt_id = TEGRA30_CLK_RTC },
+       { .dev_id = "timer", .dt_id = TEGRA30_CLK_TIMER },
+       { .dev_id = "tegra-kbc", .dt_id = TEGRA30_CLK_KBC },
+       { .dev_id = "fsl-tegra-udc", .dt_id = TEGRA30_CLK_USBD },
+       { .dev_id = "tegra-ehci.1", .dt_id = TEGRA30_CLK_USB2 },
+       { .dev_id = "tegra-ehci.2", .dt_id = TEGRA30_CLK_USB2 },
+       { .dev_id = "kfuse-tegra", .dt_id = TEGRA30_CLK_KFUSE },
+       { .dev_id = "tegra_sata_cold", .dt_id = TEGRA30_CLK_SATA_COLD },
+       { .dev_id = "dtv", .dt_id = TEGRA30_CLK_DTV },
        { .dev_id = "tegra30-i2s.0", .dt_id = TEGRA30_CLK_I2S0 },
        { .dev_id = "tegra30-i2s.1", .dt_id = TEGRA30_CLK_I2S1 },
        { .dev_id = "tegra30-i2s.2", .dt_id = TEGRA30_CLK_I2S2 },
@@ -1434,7 +1434,8 @@ static void __init tegra30_clock_init(struct device_node *np)
                return;
 
        if (tegra_osc_clk_init(clk_base, tegra30_clks, tegra30_input_freq,
-               ARRAY_SIZE(tegra30_input_freq), &input_freq, NULL) < 0)
+                              ARRAY_SIZE(tegra30_input_freq), 1, &input_freq,
+                              NULL) < 0)
                return;
 
 
index 9ddb7547cb431b4b234d5ec6a41fba457abc2678..41cd87c67be6a009a8b5a138672e21f6a4c0c003 100644 (file)
@@ -30,6 +30,7 @@
 #define CLK_OUT_ENB_V                  0x360
 #define CLK_OUT_ENB_W                  0x364
 #define CLK_OUT_ENB_X                  0x280
+#define CLK_OUT_ENB_Y                  0x298
 #define CLK_OUT_ENB_SET_L              0x320
 #define CLK_OUT_ENB_CLR_L              0x324
 #define CLK_OUT_ENB_SET_H              0x328
@@ -42,6 +43,8 @@
 #define CLK_OUT_ENB_CLR_W              0x44c
 #define CLK_OUT_ENB_SET_X              0x284
 #define CLK_OUT_ENB_CLR_X              0x288
+#define CLK_OUT_ENB_SET_Y              0x29c
+#define CLK_OUT_ENB_CLR_Y              0x2a0
 
 #define RST_DEVICES_L                  0x004
 #define RST_DEVICES_H                  0x008
@@ -50,6 +53,7 @@
 #define RST_DEVICES_V                  0x358
 #define RST_DEVICES_W                  0x35C
 #define RST_DEVICES_X                  0x28C
+#define RST_DEVICES_Y                  0x2a4
 #define RST_DEVICES_SET_L              0x300
 #define RST_DEVICES_CLR_L              0x304
 #define RST_DEVICES_SET_H              0x308
@@ -62,6 +66,8 @@
 #define RST_DEVICES_CLR_W              0x43c
 #define RST_DEVICES_SET_X              0x290
 #define RST_DEVICES_CLR_X              0x294
+#define RST_DEVICES_SET_Y              0x2a8
+#define RST_DEVICES_CLR_Y              0x2ac
 
 /* Global data of Tegra CPU CAR ops */
 static struct tegra_cpu_car_ops dummy_car_ops;
@@ -122,6 +128,14 @@ static struct tegra_clk_periph_regs periph_regs[] = {
                .rst_set_reg = RST_DEVICES_SET_X,
                .rst_clr_reg = RST_DEVICES_CLR_X,
        },
+       [6] = {
+               .enb_reg = CLK_OUT_ENB_Y,
+               .enb_set_reg = CLK_OUT_ENB_SET_Y,
+               .enb_clr_reg = CLK_OUT_ENB_CLR_Y,
+               .rst_reg = RST_DEVICES_Y,
+               .rst_set_reg = RST_DEVICES_SET_Y,
+               .rst_clr_reg = RST_DEVICES_CLR_Y,
+       },
 };
 
 static void __iomem *clk_base;
@@ -272,7 +286,7 @@ void __init tegra_add_of_provider(struct device_node *np)
        of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
 
        rst_ctlr.of_node = np;
-       rst_ctlr.nr_resets = clk_num * 32;
+       rst_ctlr.nr_resets = periph_banks * 32;
        reset_controller_register(&rst_ctlr);
 }
 
index 4e458aa8d45c19e6ec1ee3cf9050cfc044cdec28..d6ac00647fafb05311b646f208f7175fa0e618a4 100644 (file)
@@ -548,7 +548,7 @@ struct clk *tegra_clk_register_super_mux(const char *name,
                u8 width, u8 pllx_index, u8 div2_index, spinlock_t *lock);
 
 /**
- * struct clk_init_tabel - clock initialization table
+ * struct clk_init_table - clock initialization table
  * @clk_id:    clock id as mentioned in device tree bindings
  * @parent_id: parent clock id as mentioned in device tree bindings
  * @rate:      rate to set
@@ -615,10 +615,10 @@ void tegra_periph_clk_init(void __iomem *clk_base, void __iomem *pmc_base,
 
 void tegra_pmc_clk_init(void __iomem *pmc_base, struct tegra_clk *tegra_clks);
 void tegra_fixed_clk_init(struct tegra_clk *tegra_clks);
-int tegra_osc_clk_init(void __iomem *clk_base, struct tegra_clk *tegra_clks,
-                               unsigned long *input_freqs, int num,
-                               unsigned long *osc_freq,
-                               unsigned long *pll_ref_freq);
+int tegra_osc_clk_init(void __iomem *clk_base, struct tegra_clk *clks,
+                      unsigned long *input_freqs, unsigned int num,
+                      unsigned int clk_m_div, unsigned long *osc_freq,
+                      unsigned long *pll_ref_freq);
 void tegra_super_clk_gen4_init(void __iomem *clk_base,
                        void __iomem *pmc_base, struct tegra_clk *tegra_clks,
                        struct tegra_clk_pll_params *pll_params);
index 72d97279eae1b02f0d55341dcb4c19a28190e2be..49baf38315463d9e77cd6b34e3fdbd8cc21cc832 100644 (file)
@@ -203,7 +203,7 @@ static void __init of_dra7_apll_setup(struct device_node *node)
        ad->control_reg = ti_clk_get_reg_addr(node, 0);
        ad->idlest_reg = ti_clk_get_reg_addr(node, 1);
 
-       if (!ad->control_reg || !ad->idlest_reg)
+       if (IS_ERR(ad->control_reg) || IS_ERR(ad->idlest_reg))
                goto cleanup;
 
        ad->idlest_mask = 0x1;
@@ -384,7 +384,8 @@ static void __init of_omap2_apll_setup(struct device_node *node)
        ad->autoidle_reg = ti_clk_get_reg_addr(node, 1);
        ad->idlest_reg = ti_clk_get_reg_addr(node, 2);
 
-       if (!ad->control_reg || !ad->autoidle_reg || !ad->idlest_reg)
+       if (IS_ERR(ad->control_reg) || IS_ERR(ad->autoidle_reg) ||
+           IS_ERR(ad->idlest_reg))
                goto cleanup;
 
        clk = clk_register(NULL, &clk_hw->hw);
index 8912ff80af347c3d79a3939394fdedb25c14c7ac..e75c64c9e81c1d1c3dae2b9779e3538426a66e85 100644 (file)
@@ -119,7 +119,7 @@ int __init of_ti_clk_autoidle_setup(struct device_node *node)
        clk->name = node->name;
        clk->reg = ti_clk_get_reg_addr(node, 0);
 
-       if (!clk->reg) {
+       if (IS_ERR(clk->reg)) {
                kfree(clk);
                return -EINVAL;
        }
index e0732a4c8f26b7aa2ce41aa13dbee7f993fe6321..0b61548d569bc11acf976a9db71c846242e683aa 100644 (file)
@@ -4320,7 +4320,6 @@ static struct ti_clk_alias omap3xxx_clks[] = {
        CLK(NULL, "dpll3_m3x2_ck", &dpll3_m3x2_ck),
        CLK("etb", "emu_core_alwon_ck", &emu_core_alwon_ck),
        CLK(NULL, "sys_altclk", &sys_altclk),
-       CLK(NULL, "mcbsp_clks", &mcbsp_clks),
        CLK(NULL, "sys_clkout1", &sys_clkout1),
        CLK(NULL, "dpll3_m2_ck", &dpll3_m2_ck),
        CLK(NULL, "core_ck", &core_ck),
@@ -4369,8 +4368,6 @@ static struct ti_clk_alias omap3xxx_clks[] = {
        CLK(NULL, "i2c3_fck", &i2c3_fck),
        CLK(NULL, "i2c2_fck", &i2c2_fck),
        CLK(NULL, "i2c1_fck", &i2c1_fck),
-       CLK(NULL, "mcbsp5_fck", &mcbsp5_fck),
-       CLK(NULL, "mcbsp1_fck", &mcbsp1_fck),
        CLK(NULL, "core_48m_fck", &core_48m_fck),
        CLK(NULL, "mcspi4_fck", &mcspi4_fck),
        CLK(NULL, "mcspi3_fck", &mcspi3_fck),
@@ -4409,8 +4406,6 @@ static struct ti_clk_alias omap3xxx_clks[] = {
        CLK(NULL, "uart1_ick", &uart1_ick),
        CLK(NULL, "gpt11_ick", &gpt11_ick),
        CLK(NULL, "gpt10_ick", &gpt10_ick),
-       CLK("omap-mcbsp.5", "ick", &mcbsp5_ick),
-       CLK("omap-mcbsp.1", "ick", &mcbsp1_ick),
        CLK(NULL, "mcbsp5_ick", &mcbsp5_ick),
        CLK(NULL, "mcbsp1_ick", &mcbsp1_ick),
        CLK(NULL, "omapctrl_ick", &omapctrl_ick),
@@ -4467,15 +4462,22 @@ static struct ti_clk_alias omap3xxx_clks[] = {
        CLK(NULL, "gpt4_ick", &gpt4_ick),
        CLK(NULL, "gpt3_ick", &gpt3_ick),
        CLK(NULL, "gpt2_ick", &gpt2_ick),
+       CLK(NULL, "mcbsp_clks", &mcbsp_clks),
+       CLK("omap-mcbsp.1", "ick", &mcbsp1_ick),
        CLK("omap-mcbsp.2", "ick", &mcbsp2_ick),
        CLK("omap-mcbsp.3", "ick", &mcbsp3_ick),
        CLK("omap-mcbsp.4", "ick", &mcbsp4_ick),
-       CLK(NULL, "mcbsp4_ick", &mcbsp2_ick),
+       CLK("omap-mcbsp.5", "ick", &mcbsp5_ick),
+       CLK(NULL, "mcbsp1_ick", &mcbsp1_ick),
+       CLK(NULL, "mcbsp2_ick", &mcbsp2_ick),
        CLK(NULL, "mcbsp3_ick", &mcbsp3_ick),
-       CLK(NULL, "mcbsp2_ick", &mcbsp4_ick),
+       CLK(NULL, "mcbsp4_ick", &mcbsp4_ick),
+       CLK(NULL, "mcbsp5_ick", &mcbsp5_ick),
+       CLK(NULL, "mcbsp1_fck", &mcbsp1_fck),
        CLK(NULL, "mcbsp2_fck", &mcbsp2_fck),
        CLK(NULL, "mcbsp3_fck", &mcbsp3_fck),
        CLK(NULL, "mcbsp4_fck", &mcbsp4_fck),
+       CLK(NULL, "mcbsp5_fck", &mcbsp5_fck),
        CLK(NULL, "emu_src_mux_ck", &emu_src_mux_ck),
        CLK("etb", "emu_src_ck", &emu_src_ck),
        CLK(NULL, "emu_src_mux_ck", &emu_src_mux_ck),
index 383a06e49b09db95e465260369fe307afebb92e2..757636d166cff45035a355dc83830511c3640c74 100644 (file)
@@ -34,7 +34,6 @@ static struct ti_dt_clk omap3xxx_clks[] = {
        DT_CLK(NULL, "omap_96m_alwon_fck", "omap_96m_alwon_fck"),
        DT_CLK("etb", "emu_core_alwon_ck", "emu_core_alwon_ck"),
        DT_CLK(NULL, "sys_altclk", "sys_altclk"),
-       DT_CLK(NULL, "mcbsp_clks", "mcbsp_clks"),
        DT_CLK(NULL, "sys_clkout1", "sys_clkout1"),
        DT_CLK(NULL, "dpll1_ck", "dpll1_ck"),
        DT_CLK(NULL, "dpll1_x2_ck", "dpll1_x2_ck"),
@@ -82,8 +81,6 @@ static struct ti_dt_clk omap3xxx_clks[] = {
        DT_CLK(NULL, "i2c3_fck", "i2c3_fck"),
        DT_CLK(NULL, "i2c2_fck", "i2c2_fck"),
        DT_CLK(NULL, "i2c1_fck", "i2c1_fck"),
-       DT_CLK(NULL, "mcbsp5_fck", "mcbsp5_fck"),
-       DT_CLK(NULL, "mcbsp1_fck", "mcbsp1_fck"),
        DT_CLK(NULL, "core_48m_fck", "core_48m_fck"),
        DT_CLK(NULL, "mcspi4_fck", "mcspi4_fck"),
        DT_CLK(NULL, "mcspi3_fck", "mcspi3_fck"),
@@ -122,10 +119,6 @@ static struct ti_dt_clk omap3xxx_clks[] = {
        DT_CLK(NULL, "uart1_ick", "uart1_ick"),
        DT_CLK(NULL, "gpt11_ick", "gpt11_ick"),
        DT_CLK(NULL, "gpt10_ick", "gpt10_ick"),
-       DT_CLK("omap-mcbsp.5", "ick", "mcbsp5_ick"),
-       DT_CLK("omap-mcbsp.1", "ick", "mcbsp1_ick"),
-       DT_CLK(NULL, "mcbsp5_ick", "mcbsp5_ick"),
-       DT_CLK(NULL, "mcbsp1_ick", "mcbsp1_ick"),
        DT_CLK(NULL, "omapctrl_ick", "omapctrl_ick"),
        DT_CLK(NULL, "dss_tv_fck", "dss_tv_fck"),
        DT_CLK(NULL, "dss_96m_fck", "dss_96m_fck"),
@@ -179,15 +172,17 @@ static struct ti_dt_clk omap3xxx_clks[] = {
        DT_CLK(NULL, "gpt4_ick", "gpt4_ick"),
        DT_CLK(NULL, "gpt3_ick", "gpt3_ick"),
        DT_CLK(NULL, "gpt2_ick", "gpt2_ick"),
-       DT_CLK("omap-mcbsp.2", "ick", "mcbsp2_ick"),
-       DT_CLK("omap-mcbsp.3", "ick", "mcbsp3_ick"),
-       DT_CLK("omap-mcbsp.4", "ick", "mcbsp4_ick"),
-       DT_CLK(NULL, "mcbsp4_ick", "mcbsp2_ick"),
+       DT_CLK(NULL, "mcbsp_clks", "mcbsp_clks"),
+       DT_CLK(NULL, "mcbsp1_ick", "mcbsp1_ick"),
+       DT_CLK(NULL, "mcbsp2_ick", "mcbsp2_ick"),
        DT_CLK(NULL, "mcbsp3_ick", "mcbsp3_ick"),
-       DT_CLK(NULL, "mcbsp2_ick", "mcbsp4_ick"),
+       DT_CLK(NULL, "mcbsp4_ick", "mcbsp4_ick"),
+       DT_CLK(NULL, "mcbsp5_ick", "mcbsp5_ick"),
+       DT_CLK(NULL, "mcbsp1_fck", "mcbsp1_fck"),
        DT_CLK(NULL, "mcbsp2_fck", "mcbsp2_fck"),
        DT_CLK(NULL, "mcbsp3_fck", "mcbsp3_fck"),
        DT_CLK(NULL, "mcbsp4_fck", "mcbsp4_fck"),
+       DT_CLK(NULL, "mcbsp5_fck", "mcbsp5_fck"),
        DT_CLK("etb", "emu_src_ck", "emu_src_ck"),
        DT_CLK(NULL, "emu_src_ck", "emu_src_ck"),
        DT_CLK(NULL, "pclk_fck", "pclk_fck"),
index 4f4c87751db521d0ce05dcd82e2a62e81408f9d9..581db7711f511245ab95956427ca51225c5b5c83 100644 (file)
@@ -249,17 +249,6 @@ static struct ti_dt_clk omap44xx_clks[] = {
        DT_CLK("usbhs_tll", "usbtll_fck", "dummy_ck"),
        DT_CLK("omap_wdt", "ick", "dummy_ck"),
        DT_CLK(NULL, "timer_32k_ck", "sys_32k_ck"),
-       DT_CLK("omap_timer.1", "timer_sys_ck", "sys_clkin_ck"),
-       DT_CLK("omap_timer.2", "timer_sys_ck", "sys_clkin_ck"),
-       DT_CLK("omap_timer.3", "timer_sys_ck", "sys_clkin_ck"),
-       DT_CLK("omap_timer.4", "timer_sys_ck", "sys_clkin_ck"),
-       DT_CLK("omap_timer.9", "timer_sys_ck", "sys_clkin_ck"),
-       DT_CLK("omap_timer.10", "timer_sys_ck", "sys_clkin_ck"),
-       DT_CLK("omap_timer.11", "timer_sys_ck", "sys_clkin_ck"),
-       DT_CLK("omap_timer.5", "timer_sys_ck", "syc_clk_div_ck"),
-       DT_CLK("omap_timer.6", "timer_sys_ck", "syc_clk_div_ck"),
-       DT_CLK("omap_timer.7", "timer_sys_ck", "syc_clk_div_ck"),
-       DT_CLK("omap_timer.8", "timer_sys_ck", "syc_clk_div_ck"),
        DT_CLK("4a318000.timer", "timer_sys_ck", "sys_clkin_ck"),
        DT_CLK("48032000.timer", "timer_sys_ck", "sys_clkin_ck"),
        DT_CLK("48034000.timer", "timer_sys_ck", "sys_clkin_ck"),
index 14160b2235480f1b2855a5c1f3d16865321ce18a..96c69a335975a2a7cdccbd4060389f6e79378ba1 100644 (file)
@@ -208,17 +208,17 @@ static struct ti_dt_clk omap54xx_clks[] = {
        DT_CLK("usbhs_omap", "usbtll_fck", "dummy_ck"),
        DT_CLK("omap_wdt", "ick", "dummy_ck"),
        DT_CLK(NULL, "timer_32k_ck", "sys_32k_ck"),
-       DT_CLK("omap_timer.1", "sys_ck", "sys_clkin"),
-       DT_CLK("omap_timer.2", "sys_ck", "sys_clkin"),
-       DT_CLK("omap_timer.3", "sys_ck", "sys_clkin"),
-       DT_CLK("omap_timer.4", "sys_ck", "sys_clkin"),
-       DT_CLK("omap_timer.9", "sys_ck", "sys_clkin"),
-       DT_CLK("omap_timer.10", "sys_ck", "sys_clkin"),
-       DT_CLK("omap_timer.11", "sys_ck", "sys_clkin"),
-       DT_CLK("omap_timer.5", "sys_ck", "dss_syc_gfclk_div"),
-       DT_CLK("omap_timer.6", "sys_ck", "dss_syc_gfclk_div"),
-       DT_CLK("omap_timer.7", "sys_ck", "dss_syc_gfclk_div"),
-       DT_CLK("omap_timer.8", "sys_ck", "dss_syc_gfclk_div"),
+       DT_CLK("4ae18000.timer", "timer_sys_ck", "sys_clkin"),
+       DT_CLK("48032000.timer", "timer_sys_ck", "sys_clkin"),
+       DT_CLK("48034000.timer", "timer_sys_ck", "sys_clkin"),
+       DT_CLK("48036000.timer", "timer_sys_ck", "sys_clkin"),
+       DT_CLK("4803e000.timer", "timer_sys_ck", "sys_clkin"),
+       DT_CLK("48086000.timer", "timer_sys_ck", "sys_clkin"),
+       DT_CLK("48088000.timer", "timer_sys_ck", "sys_clkin"),
+       DT_CLK("40138000.timer", "timer_sys_ck", "dss_syc_gfclk_div"),
+       DT_CLK("4013a000.timer", "timer_sys_ck", "dss_syc_gfclk_div"),
+       DT_CLK("4013c000.timer", "timer_sys_ck", "dss_syc_gfclk_div"),
+       DT_CLK("4013e000.timer", "timer_sys_ck", "dss_syc_gfclk_div"),
        { .node_name = NULL },
 };
 
index ee32f4deebf40280be8e4d4e6e454e815c53cd67..5d2217ae447873656a9869649f0e89abe1028106 100644 (file)
@@ -289,17 +289,21 @@ static struct ti_dt_clk dra7xx_clks[] = {
        DT_CLK("usbhs_omap", "usbtll_fck", "dummy_ck"),
        DT_CLK("omap_wdt", "ick", "dummy_ck"),
        DT_CLK(NULL, "timer_32k_ck", "sys_32k_ck"),
-       DT_CLK("4ae18000.timer", "timer_sys_ck", "sys_clkin2"),
-       DT_CLK("48032000.timer", "timer_sys_ck", "sys_clkin2"),
-       DT_CLK("48034000.timer", "timer_sys_ck", "sys_clkin2"),
-       DT_CLK("48036000.timer", "timer_sys_ck", "sys_clkin2"),
-       DT_CLK("4803e000.timer", "timer_sys_ck", "sys_clkin2"),
-       DT_CLK("48086000.timer", "timer_sys_ck", "sys_clkin2"),
-       DT_CLK("48088000.timer", "timer_sys_ck", "sys_clkin2"),
+       DT_CLK("4ae18000.timer", "timer_sys_ck", "timer_sys_clk_div"),
+       DT_CLK("48032000.timer", "timer_sys_ck", "timer_sys_clk_div"),
+       DT_CLK("48034000.timer", "timer_sys_ck", "timer_sys_clk_div"),
+       DT_CLK("48036000.timer", "timer_sys_ck", "timer_sys_clk_div"),
+       DT_CLK("4803e000.timer", "timer_sys_ck", "timer_sys_clk_div"),
+       DT_CLK("48086000.timer", "timer_sys_ck", "timer_sys_clk_div"),
+       DT_CLK("48088000.timer", "timer_sys_ck", "timer_sys_clk_div"),
        DT_CLK("48820000.timer", "timer_sys_ck", "timer_sys_clk_div"),
        DT_CLK("48822000.timer", "timer_sys_ck", "timer_sys_clk_div"),
        DT_CLK("48824000.timer", "timer_sys_ck", "timer_sys_clk_div"),
        DT_CLK("48826000.timer", "timer_sys_ck", "timer_sys_clk_div"),
+       DT_CLK("48828000.timer", "timer_sys_ck", "timer_sys_clk_div"),
+       DT_CLK("4882a000.timer", "timer_sys_ck", "timer_sys_clk_div"),
+       DT_CLK("4882c000.timer", "timer_sys_ck", "timer_sys_clk_div"),
+       DT_CLK("4882e000.timer", "timer_sys_ck", "timer_sys_clk_div"),
        DT_CLK(NULL, "sys_clkin", "sys_clkin1"),
        { .node_name = NULL },
 };
index 59bb4b39d12e799f6d32d8f5a3d898e4dc9d1c46..d86bc46b93bdfeae630f94a55745315a0d8c1ec8 100644 (file)
@@ -294,7 +294,7 @@ static int of_dra7_atl_clk_remove(struct platform_device *pdev)
        return 0;
 }
 
-static struct of_device_id of_dra7_atl_clk_match_tbl[] = {
+static const struct of_device_id of_dra7_atl_clk_match_tbl[] = {
        { .compatible = "ti,dra7-atl", },
        {},
 };
index e22b95646e09a8357e5adb3786f726c8e6baab10..0ebe5c51062b9ee2c2aa8e3fbe5dd84fcb14f753 100644 (file)
@@ -103,7 +103,8 @@ int __init ti_clk_retry_init(struct device_node *node, struct clk_hw *hw,
  * @index: register index from the clock node
  *
  * Builds clock register address from device tree information. This
- * is a struct of type clk_omap_reg.
+ * is a struct of type clk_omap_reg. Returns a pointer to the register
+ * address, or a pointer error value in failure.
  */
 void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index)
 {
@@ -121,14 +122,14 @@ void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index)
 
        if (i == CLK_MAX_MEMMAPS) {
                pr_err("clk-provider not found for %s!\n", node->name);
-               return NULL;
+               return ERR_PTR(-ENOENT);
        }
 
        reg->index = i;
 
        if (of_property_read_u32_index(node, "reg", index, &val)) {
                pr_err("%s must have reg[%d]!\n", node->name, index);
-               return NULL;
+               return ERR_PTR(-EINVAL);
        }
 
        reg->offset = val;
index b4c5faccaece634c4c9459c6be311f64e4daaf45..35fe1085480cf33da68547e76a7e126d5b95738b 100644 (file)
@@ -52,7 +52,7 @@ static void __init of_ti_clockdomain_setup(struct device_node *node)
        }
 }
 
-static struct of_device_id ti_clkdm_match_table[] __initdata = {
+static const struct of_device_id ti_clkdm_match_table[] __initconst = {
        { .compatible = "ti,clockdomain" },
        { }
 };
index 3654f61912ebb7d099771f5f5e7fba9a5bbc4e92..96f83cedb4b3ca6426d1351bd5db6bbcc292fb90 100644 (file)
@@ -69,7 +69,7 @@ struct component_clk {
        struct list_head link;
 };
 
-static const char * __initconst component_clk_types[] = {
+static const char * const component_clk_types[] __initconst = {
        "gate", "divider", "mux"
 };
 
index 6211893c0980665749aa2c08577f9f3c17da4a78..ff5f117950a933b354c3bf5ba339e3e1a5b2dcd3 100644 (file)
@@ -530,8 +530,8 @@ static int __init ti_clk_divider_populate(struct device_node *node,
        u32 val;
 
        *reg = ti_clk_get_reg_addr(node, 0);
-       if (!*reg)
-               return -EINVAL;
+       if (IS_ERR(*reg))
+               return PTR_ERR(*reg);
 
        if (!of_property_read_u32(node, "ti,bit-shift", &val))
                *shift = val;
index 81dc4698dc41740e77e82411b00c67ae9aa148ba..11478a501c3074c53071bf9afb206b375fbda14c 100644 (file)
@@ -390,18 +390,18 @@ static void __init of_ti_dpll_setup(struct device_node *node,
 #endif
        } else {
                dd->idlest_reg = ti_clk_get_reg_addr(node, 1);
-               if (!dd->idlest_reg)
+               if (IS_ERR(dd->idlest_reg))
                        goto cleanup;
 
                dd->mult_div1_reg = ti_clk_get_reg_addr(node, 2);
        }
 
-       if (!dd->control_reg || !dd->mult_div1_reg)
+       if (IS_ERR(dd->control_reg) || IS_ERR(dd->mult_div1_reg))
                goto cleanup;
 
        if (dd->autoidle_mask) {
                dd->autoidle_reg = ti_clk_get_reg_addr(node, 3);
-               if (!dd->autoidle_reg)
+               if (IS_ERR(dd->autoidle_reg))
                        goto cleanup;
        }
 
index d21640634adf91e290537e28eb799aeea1042eed..ffcd8e09e85b9eae1a1ffea5dda006b976a93fc5 100644 (file)
 
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
-#include <linux/slab.h>
 #include <linux/err.h>
+#include <linux/math64.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/clk/ti.h>
-#include <asm/div64.h>
 
 /* FAPLL Control Register PLL_CTRL */
+#define FAPLL_MAIN_MULT_N_SHIFT        16
+#define FAPLL_MAIN_DIV_P_SHIFT 8
 #define FAPLL_MAIN_LOCK                BIT(7)
 #define FAPLL_MAIN_PLLEN       BIT(3)
 #define FAPLL_MAIN_BP          BIT(2)
 #define FAPLL_MAIN_LOC_CTL     BIT(0)
 
+#define FAPLL_MAIN_MAX_MULT_N  0xffff
+#define FAPLL_MAIN_MAX_DIV_P   0xff
+#define FAPLL_MAIN_CLEAR_MASK  \
+       ((FAPLL_MAIN_MAX_MULT_N << FAPLL_MAIN_MULT_N_SHIFT) | \
+        (FAPLL_MAIN_DIV_P_SHIFT << FAPLL_MAIN_DIV_P_SHIFT) | \
+        FAPLL_MAIN_LOC_CTL)
+
 /* FAPLL powerdown register PWD */
 #define FAPLL_PWD_OFFSET       4
 
 /* Synthesizer frequency register */
 #define SYNTH_LDFREQ           BIT(31)
 
+#define SYNTH_PHASE_K          8
+#define SYNTH_MAX_INT_DIV      0xf
+#define SYNTH_MAX_DIV_M                0xff
+
 struct fapll_data {
        struct clk_hw hw;
        void __iomem *base;
@@ -79,6 +91,48 @@ static bool ti_fapll_clock_is_bypass(struct fapll_data *fd)
                return !!(v & FAPLL_MAIN_BP);
 }
 
+static void ti_fapll_set_bypass(struct fapll_data *fd)
+{
+       u32 v = readl_relaxed(fd->base);
+
+       if (fd->bypass_bit_inverted)
+               v &= ~FAPLL_MAIN_BP;
+       else
+               v |= FAPLL_MAIN_BP;
+       writel_relaxed(v, fd->base);
+}
+
+static void ti_fapll_clear_bypass(struct fapll_data *fd)
+{
+       u32 v = readl_relaxed(fd->base);
+
+       if (fd->bypass_bit_inverted)
+               v |= FAPLL_MAIN_BP;
+       else
+               v &= ~FAPLL_MAIN_BP;
+       writel_relaxed(v, fd->base);
+}
+
+static int ti_fapll_wait_lock(struct fapll_data *fd)
+{
+       int retries = FAPLL_MAX_RETRIES;
+       u32 v;
+
+       while ((v = readl_relaxed(fd->base))) {
+               if (v & FAPLL_MAIN_LOCK)
+                       return 0;
+
+               if (retries-- <= 0)
+                       break;
+
+               udelay(1);
+       }
+
+       pr_err("%s failed to lock\n", fd->name);
+
+       return -ETIMEDOUT;
+}
+
 static int ti_fapll_enable(struct clk_hw *hw)
 {
        struct fapll_data *fd = to_fapll(hw);
@@ -86,6 +140,7 @@ static int ti_fapll_enable(struct clk_hw *hw)
 
        v |= FAPLL_MAIN_PLLEN;
        writel_relaxed(v, fd->base);
+       ti_fapll_wait_lock(fd);
 
        return 0;
 }
@@ -141,12 +196,85 @@ static u8 ti_fapll_get_parent(struct clk_hw *hw)
        return 0;
 }
 
+static int ti_fapll_set_div_mult(unsigned long rate,
+                                unsigned long parent_rate,
+                                u32 *pre_div_p, u32 *mult_n)
+{
+       /*
+        * So far no luck getting decent clock with PLL divider,
+        * PLL does not seem to lock and the signal does not look
+        * right. It seems the divider can only be used together
+        * with the multiplier?
+        */
+       if (rate < parent_rate) {
+               pr_warn("FAPLL main divider rates unsupported\n");
+               return -EINVAL;
+       }
+
+       *mult_n = rate / parent_rate;
+       if (*mult_n > FAPLL_MAIN_MAX_MULT_N)
+               return -EINVAL;
+       *pre_div_p = 1;
+
+       return 0;
+}
+
+static long ti_fapll_round_rate(struct clk_hw *hw, unsigned long rate,
+                               unsigned long *parent_rate)
+{
+       u32 pre_div_p, mult_n;
+       int error;
+
+       if (!rate)
+               return -EINVAL;
+
+       error = ti_fapll_set_div_mult(rate, *parent_rate,
+                                     &pre_div_p, &mult_n);
+       if (error)
+               return error;
+
+       rate = *parent_rate / pre_div_p;
+       rate *= mult_n;
+
+       return rate;
+}
+
+static int ti_fapll_set_rate(struct clk_hw *hw, unsigned long rate,
+                            unsigned long parent_rate)
+{
+       struct fapll_data *fd = to_fapll(hw);
+       u32 pre_div_p, mult_n, v;
+       int error;
+
+       if (!rate)
+               return -EINVAL;
+
+       error = ti_fapll_set_div_mult(rate, parent_rate,
+                                     &pre_div_p, &mult_n);
+       if (error)
+               return error;
+
+       ti_fapll_set_bypass(fd);
+       v = readl_relaxed(fd->base);
+       v &= ~FAPLL_MAIN_CLEAR_MASK;
+       v |= pre_div_p << FAPLL_MAIN_DIV_P_SHIFT;
+       v |= mult_n << FAPLL_MAIN_MULT_N_SHIFT;
+       writel_relaxed(v, fd->base);
+       if (ti_fapll_is_enabled(hw))
+               ti_fapll_wait_lock(fd);
+       ti_fapll_clear_bypass(fd);
+
+       return 0;
+}
+
 static struct clk_ops ti_fapll_ops = {
        .enable = ti_fapll_enable,
        .disable = ti_fapll_disable,
        .is_enabled = ti_fapll_is_enabled,
        .recalc_rate = ti_fapll_recalc_rate,
        .get_parent = ti_fapll_get_parent,
+       .round_rate = ti_fapll_round_rate,
+       .set_rate = ti_fapll_set_rate,
 };
 
 static int ti_fapll_synth_enable(struct clk_hw *hw)
@@ -204,7 +332,7 @@ static unsigned long ti_fapll_synth_recalc_rate(struct clk_hw *hw,
        /*
         * Synth frequency integer and fractional divider.
         * Note that the phase output K is 8, so the result needs
-        * to be multiplied by 8.
+        * to be multiplied by SYNTH_PHASE_K.
         */
        if (synth->freq) {
                u32 v, synth_int_div, synth_frac_div, synth_div_freq;
@@ -215,14 +343,138 @@ static unsigned long ti_fapll_synth_recalc_rate(struct clk_hw *hw,
                synth_div_freq = (synth_int_div * 10000000) + synth_frac_div;
                rate *= 10000000;
                do_div(rate, synth_div_freq);
-               rate *= 8;
+               rate *= SYNTH_PHASE_K;
        }
 
-       /* Synth ost-divider M */
-       synth_div_m = readl_relaxed(synth->div) & 0xff;
-       do_div(rate, synth_div_m);
+       /* Synth post-divider M */
+       synth_div_m = readl_relaxed(synth->div) & SYNTH_MAX_DIV_M;
 
-       return rate;
+       return DIV_ROUND_UP_ULL(rate, synth_div_m);
+}
+
+static unsigned long ti_fapll_synth_get_frac_rate(struct clk_hw *hw,
+                                                 unsigned long parent_rate)
+{
+       struct fapll_synth *synth = to_synth(hw);
+       unsigned long current_rate, frac_rate;
+       u32 post_div_m;
+
+       current_rate = ti_fapll_synth_recalc_rate(hw, parent_rate);
+       post_div_m = readl_relaxed(synth->div) & SYNTH_MAX_DIV_M;
+       frac_rate = current_rate * post_div_m;
+
+       return frac_rate;
+}
+
+static u32 ti_fapll_synth_set_frac_rate(struct fapll_synth *synth,
+                                       unsigned long rate,
+                                       unsigned long parent_rate)
+{
+       u32 post_div_m, synth_int_div = 0, synth_frac_div = 0, v;
+
+       post_div_m = DIV_ROUND_UP_ULL((u64)parent_rate * SYNTH_PHASE_K, rate);
+       post_div_m = post_div_m / SYNTH_MAX_INT_DIV;
+       if (post_div_m > SYNTH_MAX_DIV_M)
+               return -EINVAL;
+       if (!post_div_m)
+               post_div_m = 1;
+
+       for (; post_div_m < SYNTH_MAX_DIV_M; post_div_m++) {
+               synth_int_div = DIV_ROUND_UP_ULL((u64)parent_rate *
+                                                SYNTH_PHASE_K *
+                                                10000000,
+                                                rate * post_div_m);
+               synth_frac_div = synth_int_div % 10000000;
+               synth_int_div /= 10000000;
+
+               if (synth_int_div <= SYNTH_MAX_INT_DIV)
+                       break;
+       }
+
+       if (synth_int_div > SYNTH_MAX_INT_DIV)
+               return -EINVAL;
+
+       v = readl_relaxed(synth->freq);
+       v &= ~0x1fffffff;
+       v |= (synth_int_div & SYNTH_MAX_INT_DIV) << 24;
+       v |= (synth_frac_div & 0xffffff);
+       v |= SYNTH_LDFREQ;
+       writel_relaxed(v, synth->freq);
+
+       return post_div_m;
+}
+
+static long ti_fapll_synth_round_rate(struct clk_hw *hw, unsigned long rate,
+                                     unsigned long *parent_rate)
+{
+       struct fapll_synth *synth = to_synth(hw);
+       struct fapll_data *fd = synth->fd;
+       unsigned long r;
+
+       if (ti_fapll_clock_is_bypass(fd) || !synth->div || !rate)
+               return -EINVAL;
+
+       /* Only post divider m available with no fractional divider? */
+       if (!synth->freq) {
+               unsigned long frac_rate;
+               u32 synth_post_div_m;
+
+               frac_rate = ti_fapll_synth_get_frac_rate(hw, *parent_rate);
+               synth_post_div_m = DIV_ROUND_UP(frac_rate, rate);
+               r = DIV_ROUND_UP(frac_rate, synth_post_div_m);
+               goto out;
+       }
+
+       r = *parent_rate * SYNTH_PHASE_K;
+       if (rate > r)
+               goto out;
+
+       r = DIV_ROUND_UP_ULL(r, SYNTH_MAX_INT_DIV * SYNTH_MAX_DIV_M);
+       if (rate < r)
+               goto out;
+
+       r = rate;
+out:
+       return r;
+}
+
+static int ti_fapll_synth_set_rate(struct clk_hw *hw, unsigned long rate,
+                                  unsigned long parent_rate)
+{
+       struct fapll_synth *synth = to_synth(hw);
+       struct fapll_data *fd = synth->fd;
+       unsigned long frac_rate, post_rate = 0;
+       u32 post_div_m = 0, v;
+
+       if (ti_fapll_clock_is_bypass(fd) || !synth->div || !rate)
+               return -EINVAL;
+
+       /* Produce the rate with just post divider M? */
+       frac_rate = ti_fapll_synth_get_frac_rate(hw, parent_rate);
+       if (frac_rate < rate) {
+               if (!synth->freq)
+                       return -EINVAL;
+       } else {
+               post_div_m = DIV_ROUND_UP(frac_rate, rate);
+               if (post_div_m && (post_div_m <= SYNTH_MAX_DIV_M))
+                       post_rate = DIV_ROUND_UP(frac_rate, post_div_m);
+               if (!synth->freq && !post_rate)
+                       return -EINVAL;
+       }
+
+       /* Need to recalculate the fractional divider? */
+       if ((post_rate != rate) && synth->freq)
+               post_div_m = ti_fapll_synth_set_frac_rate(synth,
+                                                         rate,
+                                                         parent_rate);
+
+       v = readl_relaxed(synth->div);
+       v &= ~SYNTH_MAX_DIV_M;
+       v |= post_div_m;
+       v |= SYNTH_LDMDIV1;
+       writel_relaxed(v, synth->div);
+
+       return 0;
 }
 
 static struct clk_ops ti_fapll_synt_ops = {
@@ -230,6 +482,8 @@ static struct clk_ops ti_fapll_synt_ops = {
        .disable = ti_fapll_synth_disable,
        .is_enabled = ti_fapll_synth_is_enabled,
        .recalc_rate = ti_fapll_synth_recalc_rate,
+       .round_rate = ti_fapll_synth_round_rate,
+       .set_rate = ti_fapll_synth_set_rate,
 };
 
 static struct clk * __init ti_fapll_synth_setup(struct fapll_data *fd,
index d493307b73f42b0bdef4c36544e5146ce00b977e..0c6fdfcd5f93a911178e334a87f371576bd18939 100644 (file)
@@ -225,7 +225,7 @@ static void __init _of_ti_gate_clk_setup(struct device_node *node,
 
        if (ops != &omap_gate_clkdm_clk_ops) {
                reg = ti_clk_get_reg_addr(node, 0);
-               if (!reg)
+               if (IS_ERR(reg))
                        return;
 
                if (!of_property_read_u32(node, "ti,bit-shift", &val))
@@ -264,7 +264,7 @@ _of_ti_composite_gate_clk_setup(struct device_node *node,
                return;
 
        gate->enable_reg = ti_clk_get_reg_addr(node, 0);
-       if (!gate->enable_reg)
+       if (IS_ERR(gate->enable_reg))
                goto cleanup;
 
        of_property_read_u32(node, "ti,bit-shift", &val);
index 265d91f071c5e34554cc71c474278997917a7a6f..c76230d8dd0464a073097cb70c4303cdf0e06056 100644 (file)
@@ -111,7 +111,7 @@ static void __init _of_ti_interface_clk_setup(struct device_node *node,
        u32 val;
 
        reg = ti_clk_get_reg_addr(node, 0);
-       if (!reg)
+       if (IS_ERR(reg))
                return;
 
        if (!of_property_read_u32(node, "ti,bit-shift", &val))
index 728e253606bce51a9435e6915ee1a445dcfff606..5cdeed538b08a2eec168de48a94399c11af33472 100644 (file)
@@ -210,7 +210,7 @@ static void of_mux_clk_setup(struct device_node *node)
 
        reg = ti_clk_get_reg_addr(node, 0);
 
-       if (!reg)
+       if (IS_ERR(reg))
                goto cleanup;
 
        of_property_read_u32(node, "ti,bit-shift", &shift);
@@ -283,7 +283,7 @@ static void __init of_ti_composite_mux_clk_setup(struct device_node *node)
 
        mux->reg = ti_clk_get_reg_addr(node, 0);
 
-       if (!mux->reg)
+       if (IS_ERR(mux->reg))
                goto cleanup;
 
        if (!of_property_read_u32(node, "ti,bit-shift", &val))
index a76981e88cb6cc5d941d67095c44f7fbfbed2ae3..7a4f8635bd1eb31ce8bbb68e755f124bd5f12f00 100644 (file)
@@ -69,7 +69,7 @@ static void __init cm_osc_setup(struct device_node *np,
                struct device_node *parent;
 
                parent = of_get_parent(np);
-               if (!np) {
+               if (!parent) {
                        pr_err("no parent on core module clock\n");
                        return;
                }
index 765f1e0eeeb2a93e92aa3835dd09c4ea3d845e58..89c0609e180b1f40ed1cb8e66fb09f629eac3d8e 100644 (file)
@@ -110,7 +110,7 @@ static int vexpress_osc_probe(struct platform_device *pdev)
        return 0;
 }
 
-static struct of_device_id vexpress_osc_of_match[] = {
+static const struct of_device_id vexpress_osc_of_match[] = {
        { .compatible = "arm,vexpress-osc", },
        {}
 };
index f870aad57711f6a69d248dc56f0309251ed0da74..40cb113be6af110139bf533d142b3ea304cb6010 100644 (file)
@@ -85,22 +85,22 @@ static DEFINE_SPINLOCK(canmioclk_lock);
 static DEFINE_SPINLOCK(dbgclk_lock);
 static DEFINE_SPINLOCK(aperclk_lock);
 
-static const char *armpll_parents[] __initconst = {"armpll_int", "ps_clk"};
-static const char *ddrpll_parents[] __initconst = {"ddrpll_int", "ps_clk"};
-static const char *iopll_parents[] __initconst = {"iopll_int", "ps_clk"};
-static const char *gem0_mux_parents[] __initconst = {"gem0_div1", "dummy_name"};
-static const char *gem1_mux_parents[] __initconst = {"gem1_div1", "dummy_name"};
-static const char *can0_mio_mux2_parents[] __initconst = {"can0_gate",
+static const char *armpll_parents[] __initdata = {"armpll_int", "ps_clk"};
+static const char *ddrpll_parents[] __initdata = {"ddrpll_int", "ps_clk"};
+static const char *iopll_parents[] __initdata = {"iopll_int", "ps_clk"};
+static const char *gem0_mux_parents[] __initdata = {"gem0_div1", "dummy_name"};
+static const char *gem1_mux_parents[] __initdata = {"gem1_div1", "dummy_name"};
+static const char *can0_mio_mux2_parents[] __initdata = {"can0_gate",
        "can0_mio_mux"};
-static const char *can1_mio_mux2_parents[] __initconst = {"can1_gate",
+static const char *can1_mio_mux2_parents[] __initdata = {"can1_gate",
        "can1_mio_mux"};
-static const char *dbg_emio_mux_parents[] __initconst = {"dbg_div",
+static const char *dbg_emio_mux_parents[] __initdata = {"dbg_div",
        "dummy_name"};
 
-static const char *dbgtrc_emio_input_names[] __initconst = {"trace_emio_clk"};
-static const char *gem0_emio_input_names[] __initconst = {"gem0_emio_clk"};
-static const char *gem1_emio_input_names[] __initconst = {"gem1_emio_clk"};
-static const char *swdt_ext_clk_input_names[] __initconst = {"swdt_ext_clk"};
+static const char *dbgtrc_emio_input_names[] __initdata = {"trace_emio_clk"};
+static const char *gem0_emio_input_names[] __initdata = {"gem0_emio_clk"};
+static const char *gem1_emio_input_names[] __initdata = {"gem1_emio_clk"};
+static const char *swdt_ext_clk_input_names[] __initdata = {"swdt_ext_clk"};
 
 static void __init zynq_clk_register_fclk(enum zynq_clk fclk,
                const char *clk_name, void __iomem *fclk_ctrl_reg,
index b4ac7cfae4418d3ed904db7e697078ffa00cab86..51d7865fdddb6d59ae7a9406ae8d88cb4da30066 100644 (file)
@@ -143,6 +143,11 @@ config ATMEL_PIT
        select CLKSRC_OF if OF
        def_bool SOC_AT91SAM9 || SOC_SAMA5
 
+config ATMEL_ST
+       bool
+       select CLKSRC_OF
+       select MFD_SYSCON
+
 config CLKSRC_METAG_GENERIC
        def_bool y if METAG
        help
index 752d5c70b0ef5d57eda8b8219e3f9c93ac4240c7..5b85f6adb25834c807c24aafa08ed0529b2e8a53 100644 (file)
@@ -1,5 +1,6 @@
 obj-$(CONFIG_CLKSRC_OF)        += clksrc-of.o
 obj-$(CONFIG_ATMEL_PIT)                += timer-atmel-pit.o
+obj-$(CONFIG_ATMEL_ST)         += timer-atmel-st.o
 obj-$(CONFIG_ATMEL_TCB_CLKSRC) += tcb_clksrc.o
 obj-$(CONFIG_X86_PM_TIMER)     += acpi_pm.o
 obj-$(CONFIG_SCx200HR_TIMER)   += scx200_hrt.o
index 266469691e5820151ad3f70d1479863e5d820f9b..0aa135ddbf8069e780c60f34c05a44c9e0fc0dfb 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/sched_clock.h>
+#include <linux/acpi.h>
 
 #include <asm/arch_timer.h>
 #include <asm/virt.h>
@@ -371,8 +372,12 @@ arch_timer_detect_rate(void __iomem *cntbase, struct device_node *np)
        if (arch_timer_rate)
                return;
 
-       /* Try to determine the frequency from the device tree or CNTFRQ */
-       if (of_property_read_u32(np, "clock-frequency", &arch_timer_rate)) {
+       /*
+        * Try to determine the frequency from the device tree or CNTFRQ,
+        * if ACPI is enabled, get the frequency from CNTFRQ ONLY.
+        */
+       if (!acpi_disabled ||
+           of_property_read_u32(np, "clock-frequency", &arch_timer_rate)) {
                if (cntbase)
                        arch_timer_rate = readl_relaxed(cntbase + CNTFRQ);
                else
@@ -691,28 +696,8 @@ static void __init arch_timer_common_init(void)
        arch_timer_arch_init();
 }
 
-static void __init arch_timer_init(struct device_node *np)
+static void __init arch_timer_init(void)
 {
-       int i;
-
-       if (arch_timers_present & ARCH_CP15_TIMER) {
-               pr_warn("arch_timer: multiple nodes in dt, skipping\n");
-               return;
-       }
-
-       arch_timers_present |= ARCH_CP15_TIMER;
-       for (i = PHYS_SECURE_PPI; i < MAX_TIMER_PPI; i++)
-               arch_timer_ppi[i] = irq_of_parse_and_map(np, i);
-       arch_timer_detect_rate(NULL, np);
-
-       /*
-        * If we cannot rely on firmware initializing the timer registers then
-        * we should use the physical timers instead.
-        */
-       if (IS_ENABLED(CONFIG_ARM) &&
-           of_property_read_bool(np, "arm,cpu-registers-not-fw-configured"))
-                       arch_timer_use_virtual = false;
-
        /*
         * If HYP mode is available, we know that the physical timer
         * has been configured to be accessible from PL1. Use it, so
@@ -731,13 +716,39 @@ static void __init arch_timer_init(struct device_node *np)
                }
        }
 
-       arch_timer_c3stop = !of_property_read_bool(np, "always-on");
-
        arch_timer_register();
        arch_timer_common_init();
 }
-CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_init);
-CLOCKSOURCE_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", arch_timer_init);
+
+static void __init arch_timer_of_init(struct device_node *np)
+{
+       int i;
+
+       if (arch_timers_present & ARCH_CP15_TIMER) {
+               pr_warn("arch_timer: multiple nodes in dt, skipping\n");
+               return;
+       }
+
+       arch_timers_present |= ARCH_CP15_TIMER;
+       for (i = PHYS_SECURE_PPI; i < MAX_TIMER_PPI; i++)
+               arch_timer_ppi[i] = irq_of_parse_and_map(np, i);
+
+       arch_timer_detect_rate(NULL, np);
+
+       arch_timer_c3stop = !of_property_read_bool(np, "always-on");
+
+       /*
+        * If we cannot rely on firmware initializing the timer registers then
+        * we should use the physical timers instead.
+        */
+       if (IS_ENABLED(CONFIG_ARM) &&
+           of_property_read_bool(np, "arm,cpu-registers-not-fw-configured"))
+                       arch_timer_use_virtual = false;
+
+       arch_timer_init();
+}
+CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_of_init);
+CLOCKSOURCE_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", arch_timer_of_init);
 
 static void __init arch_timer_mem_init(struct device_node *np)
 {
@@ -804,3 +815,70 @@ static void __init arch_timer_mem_init(struct device_node *np)
 }
 CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
                       arch_timer_mem_init);
+
+#ifdef CONFIG_ACPI
+static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
+{
+       int trigger, polarity;
+
+       if (!interrupt)
+               return 0;
+
+       trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
+                       : ACPI_LEVEL_SENSITIVE;
+
+       polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
+                       : ACPI_ACTIVE_HIGH;
+
+       return acpi_register_gsi(NULL, interrupt, trigger, polarity);
+}
+
+/* Initialize per-processor generic timer */
+static int __init arch_timer_acpi_init(struct acpi_table_header *table)
+{
+       struct acpi_table_gtdt *gtdt;
+
+       if (arch_timers_present & ARCH_CP15_TIMER) {
+               pr_warn("arch_timer: already initialized, skipping\n");
+               return -EINVAL;
+       }
+
+       gtdt = container_of(table, struct acpi_table_gtdt, header);
+
+       arch_timers_present |= ARCH_CP15_TIMER;
+
+       arch_timer_ppi[PHYS_SECURE_PPI] =
+               map_generic_timer_interrupt(gtdt->secure_el1_interrupt,
+               gtdt->secure_el1_flags);
+
+       arch_timer_ppi[PHYS_NONSECURE_PPI] =
+               map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt,
+               gtdt->non_secure_el1_flags);
+
+       arch_timer_ppi[VIRT_PPI] =
+               map_generic_timer_interrupt(gtdt->virtual_timer_interrupt,
+               gtdt->virtual_timer_flags);
+
+       arch_timer_ppi[HYP_PPI] =
+               map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt,
+               gtdt->non_secure_el2_flags);
+
+       /* Get the frequency from CNTFRQ */
+       arch_timer_detect_rate(NULL, NULL);
+
+       /* Always-on capability */
+       arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON);
+
+       arch_timer_init();
+       return 0;
+}
+
+/* Initialize all the generic timers presented in GTDT */
+void __init acpi_generic_timer_init(void)
+{
+       if (acpi_disabled)
+               return;
+
+       acpi_table_parse(ACPI_SIG_GTDT, arch_timer_acpi_init);
+}
+#endif
diff --git a/drivers/clocksource/timer-atmel-st.c b/drivers/clocksource/timer-atmel-st.c
new file mode 100644 (file)
index 0000000..1692e17
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * linux/arch/arm/mach-at91/at91rm9200_time.c
+ *
+ *  Copyright (C) 2003 SAN People
+ *  Copyright (C) 2003 ATMEL
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/clockchips.h>
+#include <linux/export.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/atmel-st.h>
+#include <linux/of_irq.h>
+#include <linux/regmap.h>
+
+static unsigned long last_crtr;
+static u32 irqmask;
+static struct clock_event_device clkevt;
+static struct regmap *regmap_st;
+
+#define AT91_SLOW_CLOCK                32768
+#define RM9200_TIMER_LATCH     ((AT91_SLOW_CLOCK + HZ/2) / HZ)
+
+/*
+ * The ST_CRTR is updated asynchronously to the master clock ... but
+ * the updates as seen by the CPU don't seem to be strictly monotonic.
+ * Waiting until we read the same value twice avoids glitching.
+ */
+static inline unsigned long read_CRTR(void)
+{
+       unsigned int x1, x2;
+
+       regmap_read(regmap_st, AT91_ST_CRTR, &x1);
+       do {
+               regmap_read(regmap_st, AT91_ST_CRTR, &x2);
+               if (x1 == x2)
+                       break;
+               x1 = x2;
+       } while (1);
+       return x1;
+}
+
+/*
+ * IRQ handler for the timer.
+ */
+static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id)
+{
+       u32 sr;
+
+       regmap_read(regmap_st, AT91_ST_SR, &sr);
+       sr &= irqmask;
+
+       /*
+        * irqs should be disabled here, but as the irq is shared they are only
+        * guaranteed to be off if the timer irq is registered first.
+        */
+       WARN_ON_ONCE(!irqs_disabled());
+
+       /* simulate "oneshot" timer with alarm */
+       if (sr & AT91_ST_ALMS) {
+               clkevt.event_handler(&clkevt);
+               return IRQ_HANDLED;
+       }
+
+       /* periodic mode should handle delayed ticks */
+       if (sr & AT91_ST_PITS) {
+               u32     crtr = read_CRTR();
+
+               while (((crtr - last_crtr) & AT91_ST_CRTV) >= RM9200_TIMER_LATCH) {
+                       last_crtr += RM9200_TIMER_LATCH;
+                       clkevt.event_handler(&clkevt);
+               }
+               return IRQ_HANDLED;
+       }
+
+       /* this irq is shared ... */
+       return IRQ_NONE;
+}
+
+static cycle_t read_clk32k(struct clocksource *cs)
+{
+       return read_CRTR();
+}
+
+static struct clocksource clk32k = {
+       .name           = "32k_counter",
+       .rating         = 150,
+       .read           = read_clk32k,
+       .mask           = CLOCKSOURCE_MASK(20),
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static void
+clkevt32k_mode(enum clock_event_mode mode, struct clock_event_device *dev)
+{
+       unsigned int val;
+
+       /* Disable and flush pending timer interrupts */
+       regmap_write(regmap_st, AT91_ST_IDR, AT91_ST_PITS | AT91_ST_ALMS);
+       regmap_read(regmap_st, AT91_ST_SR, &val);
+
+       last_crtr = read_CRTR();
+       switch (mode) {
+       case CLOCK_EVT_MODE_PERIODIC:
+               /* PIT for periodic irqs; fixed rate of 1/HZ */
+               irqmask = AT91_ST_PITS;
+               regmap_write(regmap_st, AT91_ST_PIMR, RM9200_TIMER_LATCH);
+               break;
+       case CLOCK_EVT_MODE_ONESHOT:
+               /* ALM for oneshot irqs, set by next_event()
+                * before 32 seconds have passed
+                */
+               irqmask = AT91_ST_ALMS;
+               regmap_write(regmap_st, AT91_ST_RTAR, last_crtr);
+               break;
+       case CLOCK_EVT_MODE_SHUTDOWN:
+       case CLOCK_EVT_MODE_UNUSED:
+       case CLOCK_EVT_MODE_RESUME:
+               irqmask = 0;
+               break;
+       }
+       regmap_write(regmap_st, AT91_ST_IER, irqmask);
+}
+
+static int
+clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev)
+{
+       u32             alm;
+       int             status = 0;
+       unsigned int    val;
+
+       BUG_ON(delta < 2);
+
+       /* The alarm IRQ uses absolute time (now+delta), not the relative
+        * time (delta) in our calling convention.  Like all clockevents
+        * using such "match" hardware, we have a race to defend against.
+        *
+        * Our defense here is to have set up the clockevent device so the
+        * delta is at least two.  That way we never end up writing RTAR
+        * with the value then held in CRTR ... which would mean the match
+        * wouldn't trigger until 32 seconds later, after CRTR wraps.
+        */
+       alm = read_CRTR();
+
+       /* Cancel any pending alarm; flush any pending IRQ */
+       regmap_write(regmap_st, AT91_ST_RTAR, alm);
+       regmap_read(regmap_st, AT91_ST_SR, &val);
+
+       /* Schedule alarm by writing RTAR. */
+       alm += delta;
+       regmap_write(regmap_st, AT91_ST_RTAR, alm);
+
+       return status;
+}
+
+static struct clock_event_device clkevt = {
+       .name           = "at91_tick",
+       .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+       .rating         = 150,
+       .set_next_event = clkevt32k_next_event,
+       .set_mode       = clkevt32k_mode,
+};
+
+/*
+ * ST (system timer) module supports both clockevents and clocksource.
+ */
+static void __init atmel_st_timer_init(struct device_node *node)
+{
+       unsigned int val;
+       int irq, ret;
+
+       regmap_st = syscon_node_to_regmap(node);
+       if (IS_ERR(regmap_st))
+               panic(pr_fmt("Unable to get regmap\n"));
+
+       /* Disable all timer interrupts, and clear any pending ones */
+       regmap_write(regmap_st, AT91_ST_IDR,
+               AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS);
+       regmap_read(regmap_st, AT91_ST_SR, &val);
+
+       /* Get the interrupts property */
+       irq  = irq_of_parse_and_map(node, 0);
+       if (!irq)
+               panic(pr_fmt("Unable to get IRQ from DT\n"));
+
+       /* Make IRQs happen for the system timer */
+       ret = request_irq(irq, at91rm9200_timer_interrupt,
+                         IRQF_SHARED | IRQF_TIMER | IRQF_IRQPOLL,
+                         "at91_tick", regmap_st);
+       if (ret)
+               panic(pr_fmt("Unable to setup IRQ\n"));
+
+       /* The 32KiHz "Slow Clock" (tick every 30517.58 nanoseconds) is used
+        * directly for the clocksource and all clockevents, after adjusting
+        * its prescaler from the 1 Hz default.
+        */
+       regmap_write(regmap_st, AT91_ST_RTMR, 1);
+
+       /* Setup timer clockevent, with minimum of two ticks (important!!) */
+       clkevt.cpumask = cpumask_of(0);
+       clockevents_config_and_register(&clkevt, AT91_SLOW_CLOCK,
+                                       2, AT91_ST_ALMV);
+
+       /* register clocksource */
+       clocksource_register_hz(&clk32k, AT91_SLOW_CLOCK);
+}
+CLOCKSOURCE_OF_DECLARE(atmel_st_timer, "atmel,at91rm9200-st",
+                      atmel_st_timer_init);
diff --git a/drivers/coresight/Makefile b/drivers/coresight/Makefile
deleted file mode 100644 (file)
index 4b4bec8..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#
-# Makefile for CoreSight drivers.
-#
-obj-$(CONFIG_CORESIGHT) += coresight.o
-obj-$(CONFIG_OF) += of_coresight.o
-obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o
-obj-$(CONFIG_CORESIGHT_SINK_TPIU) += coresight-tpiu.o
-obj-$(CONFIG_CORESIGHT_SINK_ETBV10) += coresight-etb10.o
-obj-$(CONFIG_CORESIGHT_LINKS_AND_SINKS) += coresight-funnel.o \
-                                          coresight-replicator.o
-obj-$(CONFIG_CORESIGHT_SOURCE_ETM3X) += coresight-etm3x.o coresight-etm-cp14.o
diff --git a/drivers/coresight/coresight-etb10.c b/drivers/coresight/coresight-etb10.c
deleted file mode 100644 (file)
index c9acd40..0000000
+++ /dev/null
@@ -1,527 +0,0 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/device.h>
-#include <linux/io.h>
-#include <linux/err.h>
-#include <linux/fs.h>
-#include <linux/miscdevice.h>
-#include <linux/uaccess.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/clk.h>
-#include <linux/seq_file.h>
-#include <linux/coresight.h>
-#include <linux/amba/bus.h>
-
-#include "coresight-priv.h"
-
-#define ETB_RAM_DEPTH_REG      0x004
-#define ETB_STATUS_REG         0x00c
-#define ETB_RAM_READ_DATA_REG  0x010
-#define ETB_RAM_READ_POINTER   0x014
-#define ETB_RAM_WRITE_POINTER  0x018
-#define ETB_TRG                        0x01c
-#define ETB_CTL_REG            0x020
-#define ETB_RWD_REG            0x024
-#define ETB_FFSR               0x300
-#define ETB_FFCR               0x304
-#define ETB_ITMISCOP0          0xee0
-#define ETB_ITTRFLINACK                0xee4
-#define ETB_ITTRFLIN           0xee8
-#define ETB_ITATBDATA0         0xeeC
-#define ETB_ITATBCTR2          0xef0
-#define ETB_ITATBCTR1          0xef4
-#define ETB_ITATBCTR0          0xef8
-
-/* register description */
-/* STS - 0x00C */
-#define ETB_STATUS_RAM_FULL    BIT(0)
-/* CTL - 0x020 */
-#define ETB_CTL_CAPT_EN                BIT(0)
-/* FFCR - 0x304 */
-#define ETB_FFCR_EN_FTC                BIT(0)
-#define ETB_FFCR_FON_MAN       BIT(6)
-#define ETB_FFCR_STOP_FI       BIT(12)
-#define ETB_FFCR_STOP_TRIGGER  BIT(13)
-
-#define ETB_FFCR_BIT           6
-#define ETB_FFSR_BIT           1
-#define ETB_FRAME_SIZE_WORDS   4
-
-/**
- * struct etb_drvdata - specifics associated to an ETB component
- * @base:      memory mapped base address for this component.
- * @dev:       the device entity associated to this component.
- * @csdev:     component vitals needed by the framework.
- * @miscdev:   specifics to handle "/dev/xyz.etb" entry.
- * @clk:       the clock this component is associated to.
- * @spinlock:  only one at a time pls.
- * @in_use:    synchronise user space access to etb buffer.
- * @buf:       area of memory where ETB buffer content gets sent.
- * @buffer_depth: size of @buf.
- * @enable:    this ETB is being used.
- * @trigger_cntr: amount of words to store after a trigger.
- */
-struct etb_drvdata {
-       void __iomem            *base;
-       struct device           *dev;
-       struct coresight_device *csdev;
-       struct miscdevice       miscdev;
-       struct clk              *clk;
-       spinlock_t              spinlock;
-       atomic_t                in_use;
-       u8                      *buf;
-       u32                     buffer_depth;
-       bool                    enable;
-       u32                     trigger_cntr;
-};
-
-static unsigned int etb_get_buffer_depth(struct etb_drvdata *drvdata)
-{
-       int ret;
-       u32 depth = 0;
-
-       ret = clk_prepare_enable(drvdata->clk);
-       if (ret)
-               return ret;
-
-       /* RO registers don't need locking */
-       depth = readl_relaxed(drvdata->base + ETB_RAM_DEPTH_REG);
-
-       clk_disable_unprepare(drvdata->clk);
-       return depth;
-}
-
-static void etb_enable_hw(struct etb_drvdata *drvdata)
-{
-       int i;
-       u32 depth;
-
-       CS_UNLOCK(drvdata->base);
-
-       depth = drvdata->buffer_depth;
-       /* reset write RAM pointer address */
-       writel_relaxed(0x0, drvdata->base + ETB_RAM_WRITE_POINTER);
-       /* clear entire RAM buffer */
-       for (i = 0; i < depth; i++)
-               writel_relaxed(0x0, drvdata->base + ETB_RWD_REG);
-
-       /* reset write RAM pointer address */
-       writel_relaxed(0x0, drvdata->base + ETB_RAM_WRITE_POINTER);
-       /* reset read RAM pointer address */
-       writel_relaxed(0x0, drvdata->base + ETB_RAM_READ_POINTER);
-
-       writel_relaxed(drvdata->trigger_cntr, drvdata->base + ETB_TRG);
-       writel_relaxed(ETB_FFCR_EN_FTC | ETB_FFCR_STOP_TRIGGER,
-                      drvdata->base + ETB_FFCR);
-       /* ETB trace capture enable */
-       writel_relaxed(ETB_CTL_CAPT_EN, drvdata->base + ETB_CTL_REG);
-
-       CS_LOCK(drvdata->base);
-}
-
-static int etb_enable(struct coresight_device *csdev)
-{
-       struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-       int ret;
-       unsigned long flags;
-
-       ret = clk_prepare_enable(drvdata->clk);
-       if (ret)
-               return ret;
-
-       spin_lock_irqsave(&drvdata->spinlock, flags);
-       etb_enable_hw(drvdata);
-       drvdata->enable = true;
-       spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
-       dev_info(drvdata->dev, "ETB enabled\n");
-       return 0;
-}
-
-static void etb_disable_hw(struct etb_drvdata *drvdata)
-{
-       u32 ffcr;
-
-       CS_UNLOCK(drvdata->base);
-
-       ffcr = readl_relaxed(drvdata->base + ETB_FFCR);
-       /* stop formatter when a stop has completed */
-       ffcr |= ETB_FFCR_STOP_FI;
-       writel_relaxed(ffcr, drvdata->base + ETB_FFCR);
-       /* manually generate a flush of the system */
-       ffcr |= ETB_FFCR_FON_MAN;
-       writel_relaxed(ffcr, drvdata->base + ETB_FFCR);
-
-       if (coresight_timeout(drvdata->base, ETB_FFCR, ETB_FFCR_BIT, 0)) {
-               dev_err(drvdata->dev,
-                       "timeout observed when probing at offset %#x\n",
-                       ETB_FFCR);
-       }
-
-       /* disable trace capture */
-       writel_relaxed(0x0, drvdata->base + ETB_CTL_REG);
-
-       if (coresight_timeout(drvdata->base, ETB_FFSR, ETB_FFSR_BIT, 1)) {
-               dev_err(drvdata->dev,
-                       "timeout observed when probing at offset %#x\n",
-                       ETB_FFCR);
-       }
-
-       CS_LOCK(drvdata->base);
-}
-
-static void etb_dump_hw(struct etb_drvdata *drvdata)
-{
-       int i;
-       u8 *buf_ptr;
-       u32 read_data, depth;
-       u32 read_ptr, write_ptr;
-       u32 frame_off, frame_endoff;
-
-       CS_UNLOCK(drvdata->base);
-
-       read_ptr = readl_relaxed(drvdata->base + ETB_RAM_READ_POINTER);
-       write_ptr = readl_relaxed(drvdata->base + ETB_RAM_WRITE_POINTER);
-
-       frame_off = write_ptr % ETB_FRAME_SIZE_WORDS;
-       frame_endoff = ETB_FRAME_SIZE_WORDS - frame_off;
-       if (frame_off) {
-               dev_err(drvdata->dev,
-                       "write_ptr: %lu not aligned to formatter frame size\n",
-                       (unsigned long)write_ptr);
-               dev_err(drvdata->dev, "frameoff: %lu, frame_endoff: %lu\n",
-                       (unsigned long)frame_off, (unsigned long)frame_endoff);
-               write_ptr += frame_endoff;
-       }
-
-       if ((readl_relaxed(drvdata->base + ETB_STATUS_REG)
-                     & ETB_STATUS_RAM_FULL) == 0)
-               writel_relaxed(0x0, drvdata->base + ETB_RAM_READ_POINTER);
-       else
-               writel_relaxed(write_ptr, drvdata->base + ETB_RAM_READ_POINTER);
-
-       depth = drvdata->buffer_depth;
-       buf_ptr = drvdata->buf;
-       for (i = 0; i < depth; i++) {
-               read_data = readl_relaxed(drvdata->base +
-                                         ETB_RAM_READ_DATA_REG);
-               *buf_ptr++ = read_data >> 0;
-               *buf_ptr++ = read_data >> 8;
-               *buf_ptr++ = read_data >> 16;
-               *buf_ptr++ = read_data >> 24;
-       }
-
-       if (frame_off) {
-               buf_ptr -= (frame_endoff * 4);
-               for (i = 0; i < frame_endoff; i++) {
-                       *buf_ptr++ = 0x0;
-                       *buf_ptr++ = 0x0;
-                       *buf_ptr++ = 0x0;
-                       *buf_ptr++ = 0x0;
-               }
-       }
-
-       writel_relaxed(read_ptr, drvdata->base + ETB_RAM_READ_POINTER);
-
-       CS_LOCK(drvdata->base);
-}
-
-static void etb_disable(struct coresight_device *csdev)
-{
-       struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-       unsigned long flags;
-
-       spin_lock_irqsave(&drvdata->spinlock, flags);
-       etb_disable_hw(drvdata);
-       etb_dump_hw(drvdata);
-       drvdata->enable = false;
-       spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
-       clk_disable_unprepare(drvdata->clk);
-
-       dev_info(drvdata->dev, "ETB disabled\n");
-}
-
-static const struct coresight_ops_sink etb_sink_ops = {
-       .enable         = etb_enable,
-       .disable        = etb_disable,
-};
-
-static const struct coresight_ops etb_cs_ops = {
-       .sink_ops       = &etb_sink_ops,
-};
-
-static void etb_dump(struct etb_drvdata *drvdata)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&drvdata->spinlock, flags);
-       if (drvdata->enable) {
-               etb_disable_hw(drvdata);
-               etb_dump_hw(drvdata);
-               etb_enable_hw(drvdata);
-       }
-       spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
-       dev_info(drvdata->dev, "ETB dumped\n");
-}
-
-static int etb_open(struct inode *inode, struct file *file)
-{
-       struct etb_drvdata *drvdata = container_of(file->private_data,
-                                                  struct etb_drvdata, miscdev);
-
-       if (atomic_cmpxchg(&drvdata->in_use, 0, 1))
-               return -EBUSY;
-
-       dev_dbg(drvdata->dev, "%s: successfully opened\n", __func__);
-       return 0;
-}
-
-static ssize_t etb_read(struct file *file, char __user *data,
-                               size_t len, loff_t *ppos)
-{
-       u32 depth;
-       struct etb_drvdata *drvdata = container_of(file->private_data,
-                                                  struct etb_drvdata, miscdev);
-
-       etb_dump(drvdata);
-
-       depth = drvdata->buffer_depth;
-       if (*ppos + len > depth * 4)
-               len = depth * 4 - *ppos;
-
-       if (copy_to_user(data, drvdata->buf + *ppos, len)) {
-               dev_dbg(drvdata->dev, "%s: copy_to_user failed\n", __func__);
-               return -EFAULT;
-       }
-
-       *ppos += len;
-
-       dev_dbg(drvdata->dev, "%s: %d bytes copied, %d bytes left\n",
-               __func__, len, (int) (depth * 4 - *ppos));
-       return len;
-}
-
-static int etb_release(struct inode *inode, struct file *file)
-{
-       struct etb_drvdata *drvdata = container_of(file->private_data,
-                                                  struct etb_drvdata, miscdev);
-       atomic_set(&drvdata->in_use, 0);
-
-       dev_dbg(drvdata->dev, "%s: released\n", __func__);
-       return 0;
-}
-
-static const struct file_operations etb_fops = {
-       .owner          = THIS_MODULE,
-       .open           = etb_open,
-       .read           = etb_read,
-       .release        = etb_release,
-       .llseek         = no_llseek,
-};
-
-static ssize_t status_show(struct device *dev,
-                          struct device_attribute *attr, char *buf)
-{
-       int ret;
-       unsigned long flags;
-       u32 etb_rdr, etb_sr, etb_rrp, etb_rwp;
-       u32 etb_trg, etb_cr, etb_ffsr, etb_ffcr;
-       struct etb_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = clk_prepare_enable(drvdata->clk);
-       if (ret)
-               goto out;
-
-       spin_lock_irqsave(&drvdata->spinlock, flags);
-       CS_UNLOCK(drvdata->base);
-
-       etb_rdr = readl_relaxed(drvdata->base + ETB_RAM_DEPTH_REG);
-       etb_sr = readl_relaxed(drvdata->base + ETB_STATUS_REG);
-       etb_rrp = readl_relaxed(drvdata->base + ETB_RAM_READ_POINTER);
-       etb_rwp = readl_relaxed(drvdata->base + ETB_RAM_WRITE_POINTER);
-       etb_trg = readl_relaxed(drvdata->base + ETB_TRG);
-       etb_cr = readl_relaxed(drvdata->base + ETB_CTL_REG);
-       etb_ffsr = readl_relaxed(drvdata->base + ETB_FFSR);
-       etb_ffcr = readl_relaxed(drvdata->base + ETB_FFCR);
-
-       CS_LOCK(drvdata->base);
-       spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
-       clk_disable_unprepare(drvdata->clk);
-
-       return sprintf(buf,
-                      "Depth:\t\t0x%x\n"
-                      "Status:\t\t0x%x\n"
-                      "RAM read ptr:\t0x%x\n"
-                      "RAM wrt ptr:\t0x%x\n"
-                      "Trigger cnt:\t0x%x\n"
-                      "Control:\t0x%x\n"
-                      "Flush status:\t0x%x\n"
-                      "Flush ctrl:\t0x%x\n",
-                      etb_rdr, etb_sr, etb_rrp, etb_rwp,
-                      etb_trg, etb_cr, etb_ffsr, etb_ffcr);
-out:
-       return -EINVAL;
-}
-static DEVICE_ATTR_RO(status);
-
-static ssize_t trigger_cntr_show(struct device *dev,
-                           struct device_attribute *attr, char *buf)
-{
-       struct etb_drvdata *drvdata = dev_get_drvdata(dev->parent);
-       unsigned long val = drvdata->trigger_cntr;
-
-       return sprintf(buf, "%#lx\n", val);
-}
-
-static ssize_t trigger_cntr_store(struct device *dev,
-                            struct device_attribute *attr,
-                            const char *buf, size_t size)
-{
-       int ret;
-       unsigned long val;
-       struct etb_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = kstrtoul(buf, 16, &val);
-       if (ret)
-               return ret;
-
-       drvdata->trigger_cntr = val;
-       return size;
-}
-static DEVICE_ATTR_RW(trigger_cntr);
-
-static struct attribute *coresight_etb_attrs[] = {
-       &dev_attr_trigger_cntr.attr,
-       &dev_attr_status.attr,
-       NULL,
-};
-ATTRIBUTE_GROUPS(coresight_etb);
-
-static int etb_probe(struct amba_device *adev, const struct amba_id *id)
-{
-       int ret;
-       void __iomem *base;
-       struct device *dev = &adev->dev;
-       struct coresight_platform_data *pdata = NULL;
-       struct etb_drvdata *drvdata;
-       struct resource *res = &adev->res;
-       struct coresight_desc *desc;
-       struct device_node *np = adev->dev.of_node;
-
-       if (np) {
-               pdata = of_get_coresight_platform_data(dev, np);
-               if (IS_ERR(pdata))
-                       return PTR_ERR(pdata);
-               adev->dev.platform_data = pdata;
-       }
-
-       drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
-       if (!drvdata)
-               return -ENOMEM;
-
-       drvdata->dev = &adev->dev;
-       dev_set_drvdata(dev, drvdata);
-
-       /* validity for the resource is already checked by the AMBA core */
-       base = devm_ioremap_resource(dev, res);
-       if (IS_ERR(base))
-               return PTR_ERR(base);
-
-       drvdata->base = base;
-
-       spin_lock_init(&drvdata->spinlock);
-
-       drvdata->clk = adev->pclk;
-       ret = clk_prepare_enable(drvdata->clk);
-       if (ret)
-               return ret;
-
-       drvdata->buffer_depth = etb_get_buffer_depth(drvdata);
-       clk_disable_unprepare(drvdata->clk);
-
-       if (drvdata->buffer_depth < 0)
-               return -EINVAL;
-
-       drvdata->buf = devm_kzalloc(dev,
-                                   drvdata->buffer_depth * 4, GFP_KERNEL);
-       if (!drvdata->buf)
-               return -ENOMEM;
-
-       desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
-       if (!desc)
-               return -ENOMEM;
-
-       desc->type = CORESIGHT_DEV_TYPE_SINK;
-       desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
-       desc->ops = &etb_cs_ops;
-       desc->pdata = pdata;
-       desc->dev = dev;
-       desc->groups = coresight_etb_groups;
-       drvdata->csdev = coresight_register(desc);
-       if (IS_ERR(drvdata->csdev))
-               return PTR_ERR(drvdata->csdev);
-
-       drvdata->miscdev.name = pdata->name;
-       drvdata->miscdev.minor = MISC_DYNAMIC_MINOR;
-       drvdata->miscdev.fops = &etb_fops;
-       ret = misc_register(&drvdata->miscdev);
-       if (ret)
-               goto err_misc_register;
-
-       dev_info(dev, "ETB initialized\n");
-       return 0;
-
-err_misc_register:
-       coresight_unregister(drvdata->csdev);
-       return ret;
-}
-
-static int etb_remove(struct amba_device *adev)
-{
-       struct etb_drvdata *drvdata = amba_get_drvdata(adev);
-
-       misc_deregister(&drvdata->miscdev);
-       coresight_unregister(drvdata->csdev);
-       return 0;
-}
-
-static struct amba_id etb_ids[] = {
-       {
-               .id     = 0x0003b907,
-               .mask   = 0x0003ffff,
-       },
-       { 0, 0},
-};
-
-static struct amba_driver etb_driver = {
-       .drv = {
-               .name   = "coresight-etb10",
-               .owner  = THIS_MODULE,
-       },
-       .probe          = etb_probe,
-       .remove         = etb_remove,
-       .id_table       = etb_ids,
-};
-
-module_amba_driver(etb_driver);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("CoreSight Embedded Trace Buffer driver");
diff --git a/drivers/coresight/coresight-etm-cp14.c b/drivers/coresight/coresight-etm-cp14.c
deleted file mode 100644 (file)
index 12a2206..0000000
+++ /dev/null
@@ -1,591 +0,0 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only 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.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/bug.h>
-#include <asm/hardware/cp14.h>
-
-#include "coresight-etm.h"
-
-int etm_readl_cp14(u32 reg, unsigned int *val)
-{
-       switch (reg) {
-       case ETMCR:
-               *val = etm_read(ETMCR);
-               return 0;
-       case ETMCCR:
-               *val = etm_read(ETMCCR);
-               return 0;
-       case ETMTRIGGER:
-               *val = etm_read(ETMTRIGGER);
-               return 0;
-       case ETMSR:
-               *val = etm_read(ETMSR);
-               return 0;
-       case ETMSCR:
-               *val = etm_read(ETMSCR);
-               return 0;
-       case ETMTSSCR:
-               *val = etm_read(ETMTSSCR);
-               return 0;
-       case ETMTEEVR:
-               *val = etm_read(ETMTEEVR);
-               return 0;
-       case ETMTECR1:
-               *val = etm_read(ETMTECR1);
-               return 0;
-       case ETMFFLR:
-               *val = etm_read(ETMFFLR);
-               return 0;
-       case ETMACVRn(0):
-               *val = etm_read(ETMACVR0);
-               return 0;
-       case ETMACVRn(1):
-               *val = etm_read(ETMACVR1);
-               return 0;
-       case ETMACVRn(2):
-               *val = etm_read(ETMACVR2);
-               return 0;
-       case ETMACVRn(3):
-               *val = etm_read(ETMACVR3);
-               return 0;
-       case ETMACVRn(4):
-               *val = etm_read(ETMACVR4);
-               return 0;
-       case ETMACVRn(5):
-               *val = etm_read(ETMACVR5);
-               return 0;
-       case ETMACVRn(6):
-               *val = etm_read(ETMACVR6);
-               return 0;
-       case ETMACVRn(7):
-               *val = etm_read(ETMACVR7);
-               return 0;
-       case ETMACVRn(8):
-               *val = etm_read(ETMACVR8);
-               return 0;
-       case ETMACVRn(9):
-               *val = etm_read(ETMACVR9);
-               return 0;
-       case ETMACVRn(10):
-               *val = etm_read(ETMACVR10);
-               return 0;
-       case ETMACVRn(11):
-               *val = etm_read(ETMACVR11);
-               return 0;
-       case ETMACVRn(12):
-               *val = etm_read(ETMACVR12);
-               return 0;
-       case ETMACVRn(13):
-               *val = etm_read(ETMACVR13);
-               return 0;
-       case ETMACVRn(14):
-               *val = etm_read(ETMACVR14);
-               return 0;
-       case ETMACVRn(15):
-               *val = etm_read(ETMACVR15);
-               return 0;
-       case ETMACTRn(0):
-               *val = etm_read(ETMACTR0);
-               return 0;
-       case ETMACTRn(1):
-               *val = etm_read(ETMACTR1);
-               return 0;
-       case ETMACTRn(2):
-               *val = etm_read(ETMACTR2);
-               return 0;
-       case ETMACTRn(3):
-               *val = etm_read(ETMACTR3);
-               return 0;
-       case ETMACTRn(4):
-               *val = etm_read(ETMACTR4);
-               return 0;
-       case ETMACTRn(5):
-               *val = etm_read(ETMACTR5);
-               return 0;
-       case ETMACTRn(6):
-               *val = etm_read(ETMACTR6);
-               return 0;
-       case ETMACTRn(7):
-               *val = etm_read(ETMACTR7);
-               return 0;
-       case ETMACTRn(8):
-               *val = etm_read(ETMACTR8);
-               return 0;
-       case ETMACTRn(9):
-               *val = etm_read(ETMACTR9);
-               return 0;
-       case ETMACTRn(10):
-               *val = etm_read(ETMACTR10);
-               return 0;
-       case ETMACTRn(11):
-               *val = etm_read(ETMACTR11);
-               return 0;
-       case ETMACTRn(12):
-               *val = etm_read(ETMACTR12);
-               return 0;
-       case ETMACTRn(13):
-               *val = etm_read(ETMACTR13);
-               return 0;
-       case ETMACTRn(14):
-               *val = etm_read(ETMACTR14);
-               return 0;
-       case ETMACTRn(15):
-               *val = etm_read(ETMACTR15);
-               return 0;
-       case ETMCNTRLDVRn(0):
-               *val = etm_read(ETMCNTRLDVR0);
-               return 0;
-       case ETMCNTRLDVRn(1):
-               *val = etm_read(ETMCNTRLDVR1);
-               return 0;
-       case ETMCNTRLDVRn(2):
-               *val = etm_read(ETMCNTRLDVR2);
-               return 0;
-       case ETMCNTRLDVRn(3):
-               *val = etm_read(ETMCNTRLDVR3);
-               return 0;
-       case ETMCNTENRn(0):
-               *val = etm_read(ETMCNTENR0);
-               return 0;
-       case ETMCNTENRn(1):
-               *val = etm_read(ETMCNTENR1);
-               return 0;
-       case ETMCNTENRn(2):
-               *val = etm_read(ETMCNTENR2);
-               return 0;
-       case ETMCNTENRn(3):
-               *val = etm_read(ETMCNTENR3);
-               return 0;
-       case ETMCNTRLDEVRn(0):
-               *val = etm_read(ETMCNTRLDEVR0);
-               return 0;
-       case ETMCNTRLDEVRn(1):
-               *val = etm_read(ETMCNTRLDEVR1);
-               return 0;
-       case ETMCNTRLDEVRn(2):
-               *val = etm_read(ETMCNTRLDEVR2);
-               return 0;
-       case ETMCNTRLDEVRn(3):
-               *val = etm_read(ETMCNTRLDEVR3);
-               return 0;
-       case ETMCNTVRn(0):
-               *val = etm_read(ETMCNTVR0);
-               return 0;
-       case ETMCNTVRn(1):
-               *val = etm_read(ETMCNTVR1);
-               return 0;
-       case ETMCNTVRn(2):
-               *val = etm_read(ETMCNTVR2);
-               return 0;
-       case ETMCNTVRn(3):
-               *val = etm_read(ETMCNTVR3);
-               return 0;
-       case ETMSQ12EVR:
-               *val = etm_read(ETMSQ12EVR);
-               return 0;
-       case ETMSQ21EVR:
-               *val = etm_read(ETMSQ21EVR);
-               return 0;
-       case ETMSQ23EVR:
-               *val = etm_read(ETMSQ23EVR);
-               return 0;
-       case ETMSQ31EVR:
-               *val = etm_read(ETMSQ31EVR);
-               return 0;
-       case ETMSQ32EVR:
-               *val = etm_read(ETMSQ32EVR);
-               return 0;
-       case ETMSQ13EVR:
-               *val = etm_read(ETMSQ13EVR);
-               return 0;
-       case ETMSQR:
-               *val = etm_read(ETMSQR);
-               return 0;
-       case ETMEXTOUTEVRn(0):
-               *val = etm_read(ETMEXTOUTEVR0);
-               return 0;
-       case ETMEXTOUTEVRn(1):
-               *val = etm_read(ETMEXTOUTEVR1);
-               return 0;
-       case ETMEXTOUTEVRn(2):
-               *val = etm_read(ETMEXTOUTEVR2);
-               return 0;
-       case ETMEXTOUTEVRn(3):
-               *val = etm_read(ETMEXTOUTEVR3);
-               return 0;
-       case ETMCIDCVRn(0):
-               *val = etm_read(ETMCIDCVR0);
-               return 0;
-       case ETMCIDCVRn(1):
-               *val = etm_read(ETMCIDCVR1);
-               return 0;
-       case ETMCIDCVRn(2):
-               *val = etm_read(ETMCIDCVR2);
-               return 0;
-       case ETMCIDCMR:
-               *val = etm_read(ETMCIDCMR);
-               return 0;
-       case ETMIMPSPEC0:
-               *val = etm_read(ETMIMPSPEC0);
-               return 0;
-       case ETMIMPSPEC1:
-               *val = etm_read(ETMIMPSPEC1);
-               return 0;
-       case ETMIMPSPEC2:
-               *val = etm_read(ETMIMPSPEC2);
-               return 0;
-       case ETMIMPSPEC3:
-               *val = etm_read(ETMIMPSPEC3);
-               return 0;
-       case ETMIMPSPEC4:
-               *val = etm_read(ETMIMPSPEC4);
-               return 0;
-       case ETMIMPSPEC5:
-               *val = etm_read(ETMIMPSPEC5);
-               return 0;
-       case ETMIMPSPEC6:
-               *val = etm_read(ETMIMPSPEC6);
-               return 0;
-       case ETMIMPSPEC7:
-               *val = etm_read(ETMIMPSPEC7);
-               return 0;
-       case ETMSYNCFR:
-               *val = etm_read(ETMSYNCFR);
-               return 0;
-       case ETMIDR:
-               *val = etm_read(ETMIDR);
-               return 0;
-       case ETMCCER:
-               *val = etm_read(ETMCCER);
-               return 0;
-       case ETMEXTINSELR:
-               *val = etm_read(ETMEXTINSELR);
-               return 0;
-       case ETMTESSEICR:
-               *val = etm_read(ETMTESSEICR);
-               return 0;
-       case ETMEIBCR:
-               *val = etm_read(ETMEIBCR);
-               return 0;
-       case ETMTSEVR:
-               *val = etm_read(ETMTSEVR);
-               return 0;
-       case ETMAUXCR:
-               *val = etm_read(ETMAUXCR);
-               return 0;
-       case ETMTRACEIDR:
-               *val = etm_read(ETMTRACEIDR);
-               return 0;
-       case ETMVMIDCVR:
-               *val = etm_read(ETMVMIDCVR);
-               return 0;
-       case ETMOSLSR:
-               *val = etm_read(ETMOSLSR);
-               return 0;
-       case ETMOSSRR:
-               *val = etm_read(ETMOSSRR);
-               return 0;
-       case ETMPDCR:
-               *val = etm_read(ETMPDCR);
-               return 0;
-       case ETMPDSR:
-               *val = etm_read(ETMPDSR);
-               return 0;
-       default:
-               *val = 0;
-               return -EINVAL;
-       }
-}
-
-int etm_writel_cp14(u32 reg, u32 val)
-{
-       switch (reg) {
-       case ETMCR:
-               etm_write(val, ETMCR);
-               break;
-       case ETMTRIGGER:
-               etm_write(val, ETMTRIGGER);
-               break;
-       case ETMSR:
-               etm_write(val, ETMSR);
-               break;
-       case ETMTSSCR:
-               etm_write(val, ETMTSSCR);
-               break;
-       case ETMTEEVR:
-               etm_write(val, ETMTEEVR);
-               break;
-       case ETMTECR1:
-               etm_write(val, ETMTECR1);
-               break;
-       case ETMFFLR:
-               etm_write(val, ETMFFLR);
-               break;
-       case ETMACVRn(0):
-               etm_write(val, ETMACVR0);
-               break;
-       case ETMACVRn(1):
-               etm_write(val, ETMACVR1);
-               break;
-       case ETMACVRn(2):
-               etm_write(val, ETMACVR2);
-               break;
-       case ETMACVRn(3):
-               etm_write(val, ETMACVR3);
-               break;
-       case ETMACVRn(4):
-               etm_write(val, ETMACVR4);
-               break;
-       case ETMACVRn(5):
-               etm_write(val, ETMACVR5);
-               break;
-       case ETMACVRn(6):
-               etm_write(val, ETMACVR6);
-               break;
-       case ETMACVRn(7):
-               etm_write(val, ETMACVR7);
-               break;
-       case ETMACVRn(8):
-               etm_write(val, ETMACVR8);
-               break;
-       case ETMACVRn(9):
-               etm_write(val, ETMACVR9);
-               break;
-       case ETMACVRn(10):
-               etm_write(val, ETMACVR10);
-               break;
-       case ETMACVRn(11):
-               etm_write(val, ETMACVR11);
-               break;
-       case ETMACVRn(12):
-               etm_write(val, ETMACVR12);
-               break;
-       case ETMACVRn(13):
-               etm_write(val, ETMACVR13);
-               break;
-       case ETMACVRn(14):
-               etm_write(val, ETMACVR14);
-               break;
-       case ETMACVRn(15):
-               etm_write(val, ETMACVR15);
-               break;
-       case ETMACTRn(0):
-               etm_write(val, ETMACTR0);
-               break;
-       case ETMACTRn(1):
-               etm_write(val, ETMACTR1);
-               break;
-       case ETMACTRn(2):
-               etm_write(val, ETMACTR2);
-               break;
-       case ETMACTRn(3):
-               etm_write(val, ETMACTR3);
-               break;
-       case ETMACTRn(4):
-               etm_write(val, ETMACTR4);
-               break;
-       case ETMACTRn(5):
-               etm_write(val, ETMACTR5);
-               break;
-       case ETMACTRn(6):
-               etm_write(val, ETMACTR6);
-               break;
-       case ETMACTRn(7):
-               etm_write(val, ETMACTR7);
-               break;
-       case ETMACTRn(8):
-               etm_write(val, ETMACTR8);
-               break;
-       case ETMACTRn(9):
-               etm_write(val, ETMACTR9);
-               break;
-       case ETMACTRn(10):
-               etm_write(val, ETMACTR10);
-               break;
-       case ETMACTRn(11):
-               etm_write(val, ETMACTR11);
-               break;
-       case ETMACTRn(12):
-               etm_write(val, ETMACTR12);
-               break;
-       case ETMACTRn(13):
-               etm_write(val, ETMACTR13);
-               break;
-       case ETMACTRn(14):
-               etm_write(val, ETMACTR14);
-               break;
-       case ETMACTRn(15):
-               etm_write(val, ETMACTR15);
-               break;
-       case ETMCNTRLDVRn(0):
-               etm_write(val, ETMCNTRLDVR0);
-               break;
-       case ETMCNTRLDVRn(1):
-               etm_write(val, ETMCNTRLDVR1);
-               break;
-       case ETMCNTRLDVRn(2):
-               etm_write(val, ETMCNTRLDVR2);
-               break;
-       case ETMCNTRLDVRn(3):
-               etm_write(val, ETMCNTRLDVR3);
-               break;
-       case ETMCNTENRn(0):
-               etm_write(val, ETMCNTENR0);
-               break;
-       case ETMCNTENRn(1):
-               etm_write(val, ETMCNTENR1);
-               break;
-       case ETMCNTENRn(2):
-               etm_write(val, ETMCNTENR2);
-               break;
-       case ETMCNTENRn(3):
-               etm_write(val, ETMCNTENR3);
-               break;
-       case ETMCNTRLDEVRn(0):
-               etm_write(val, ETMCNTRLDEVR0);
-               break;
-       case ETMCNTRLDEVRn(1):
-               etm_write(val, ETMCNTRLDEVR1);
-               break;
-       case ETMCNTRLDEVRn(2):
-               etm_write(val, ETMCNTRLDEVR2);
-               break;
-       case ETMCNTRLDEVRn(3):
-               etm_write(val, ETMCNTRLDEVR3);
-               break;
-       case ETMCNTVRn(0):
-               etm_write(val, ETMCNTVR0);
-               break;
-       case ETMCNTVRn(1):
-               etm_write(val, ETMCNTVR1);
-               break;
-       case ETMCNTVRn(2):
-               etm_write(val, ETMCNTVR2);
-               break;
-       case ETMCNTVRn(3):
-               etm_write(val, ETMCNTVR3);
-               break;
-       case ETMSQ12EVR:
-               etm_write(val, ETMSQ12EVR);
-               break;
-       case ETMSQ21EVR:
-               etm_write(val, ETMSQ21EVR);
-               break;
-       case ETMSQ23EVR:
-               etm_write(val, ETMSQ23EVR);
-               break;
-       case ETMSQ31EVR:
-               etm_write(val, ETMSQ31EVR);
-               break;
-       case ETMSQ32EVR:
-               etm_write(val, ETMSQ32EVR);
-               break;
-       case ETMSQ13EVR:
-               etm_write(val, ETMSQ13EVR);
-               break;
-       case ETMSQR:
-               etm_write(val, ETMSQR);
-               break;
-       case ETMEXTOUTEVRn(0):
-               etm_write(val, ETMEXTOUTEVR0);
-               break;
-       case ETMEXTOUTEVRn(1):
-               etm_write(val, ETMEXTOUTEVR1);
-               break;
-       case ETMEXTOUTEVRn(2):
-               etm_write(val, ETMEXTOUTEVR2);
-               break;
-       case ETMEXTOUTEVRn(3):
-               etm_write(val, ETMEXTOUTEVR3);
-               break;
-       case ETMCIDCVRn(0):
-               etm_write(val, ETMCIDCVR0);
-               break;
-       case ETMCIDCVRn(1):
-               etm_write(val, ETMCIDCVR1);
-               break;
-       case ETMCIDCVRn(2):
-               etm_write(val, ETMCIDCVR2);
-               break;
-       case ETMCIDCMR:
-               etm_write(val, ETMCIDCMR);
-               break;
-       case ETMIMPSPEC0:
-               etm_write(val, ETMIMPSPEC0);
-               break;
-       case ETMIMPSPEC1:
-               etm_write(val, ETMIMPSPEC1);
-               break;
-       case ETMIMPSPEC2:
-               etm_write(val, ETMIMPSPEC2);
-               break;
-       case ETMIMPSPEC3:
-               etm_write(val, ETMIMPSPEC3);
-               break;
-       case ETMIMPSPEC4:
-               etm_write(val, ETMIMPSPEC4);
-               break;
-       case ETMIMPSPEC5:
-               etm_write(val, ETMIMPSPEC5);
-               break;
-       case ETMIMPSPEC6:
-               etm_write(val, ETMIMPSPEC6);
-               break;
-       case ETMIMPSPEC7:
-               etm_write(val, ETMIMPSPEC7);
-               break;
-       case ETMSYNCFR:
-               etm_write(val, ETMSYNCFR);
-               break;
-       case ETMEXTINSELR:
-               etm_write(val, ETMEXTINSELR);
-               break;
-       case ETMTESSEICR:
-               etm_write(val, ETMTESSEICR);
-               break;
-       case ETMEIBCR:
-               etm_write(val, ETMEIBCR);
-               break;
-       case ETMTSEVR:
-               etm_write(val, ETMTSEVR);
-               break;
-       case ETMAUXCR:
-               etm_write(val, ETMAUXCR);
-               break;
-       case ETMTRACEIDR:
-               etm_write(val, ETMTRACEIDR);
-               break;
-       case ETMVMIDCVR:
-               etm_write(val, ETMVMIDCVR);
-               break;
-       case ETMOSLAR:
-               etm_write(val, ETMOSLAR);
-               break;
-       case ETMOSSRR:
-               etm_write(val, ETMOSSRR);
-               break;
-       case ETMPDCR:
-               etm_write(val, ETMPDCR);
-               break;
-       case ETMPDSR:
-               etm_write(val, ETMPDSR);
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
diff --git a/drivers/coresight/coresight-etm.h b/drivers/coresight/coresight-etm.h
deleted file mode 100644 (file)
index 501c5fa..0000000
+++ /dev/null
@@ -1,251 +0,0 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef _CORESIGHT_CORESIGHT_ETM_H
-#define _CORESIGHT_CORESIGHT_ETM_H
-
-#include <linux/spinlock.h>
-#include "coresight-priv.h"
-
-/*
- * Device registers:
- * 0x000 - 0x2FC: Trace         registers
- * 0x300 - 0x314: Management    registers
- * 0x318 - 0xEFC: Trace         registers
- *
- * Coresight registers
- * 0xF00 - 0xF9C: Management    registers
- * 0xFA0 - 0xFA4: Management    registers in PFTv1.0
- *                Trace         registers in PFTv1.1
- * 0xFA8 - 0xFFC: Management    registers
- */
-
-/* Trace registers (0x000-0x2FC) */
-#define ETMCR                  0x000
-#define ETMCCR                 0x004
-#define ETMTRIGGER             0x008
-#define ETMSR                  0x010
-#define ETMSCR                 0x014
-#define ETMTSSCR               0x018
-#define ETMTECR2               0x01c
-#define ETMTEEVR               0x020
-#define ETMTECR1               0x024
-#define ETMFFLR                        0x02c
-#define ETMACVRn(n)            (0x040 + (n * 4))
-#define ETMACTRn(n)            (0x080 + (n * 4))
-#define ETMCNTRLDVRn(n)                (0x140 + (n * 4))
-#define ETMCNTENRn(n)          (0x150 + (n * 4))
-#define ETMCNTRLDEVRn(n)       (0x160 + (n * 4))
-#define ETMCNTVRn(n)           (0x170 + (n * 4))
-#define ETMSQ12EVR             0x180
-#define ETMSQ21EVR             0x184
-#define ETMSQ23EVR             0x188
-#define ETMSQ31EVR             0x18c
-#define ETMSQ32EVR             0x190
-#define ETMSQ13EVR             0x194
-#define ETMSQR                 0x19c
-#define ETMEXTOUTEVRn(n)       (0x1a0 + (n * 4))
-#define ETMCIDCVRn(n)          (0x1b0 + (n * 4))
-#define ETMCIDCMR              0x1bc
-#define ETMIMPSPEC0            0x1c0
-#define ETMIMPSPEC1            0x1c4
-#define ETMIMPSPEC2            0x1c8
-#define ETMIMPSPEC3            0x1cc
-#define ETMIMPSPEC4            0x1d0
-#define ETMIMPSPEC5            0x1d4
-#define ETMIMPSPEC6            0x1d8
-#define ETMIMPSPEC7            0x1dc
-#define ETMSYNCFR              0x1e0
-#define ETMIDR                 0x1e4
-#define ETMCCER                        0x1e8
-#define ETMEXTINSELR           0x1ec
-#define ETMTESSEICR            0x1f0
-#define ETMEIBCR               0x1f4
-#define ETMTSEVR               0x1f8
-#define ETMAUXCR               0x1fc
-#define ETMTRACEIDR            0x200
-#define ETMVMIDCVR             0x240
-/* Management registers (0x300-0x314) */
-#define ETMOSLAR               0x300
-#define ETMOSLSR               0x304
-#define ETMOSSRR               0x308
-#define ETMPDCR                        0x310
-#define ETMPDSR                        0x314
-#define ETM_MAX_ADDR_CMP       16
-#define ETM_MAX_CNTR           4
-#define ETM_MAX_CTXID_CMP      3
-
-/* Register definition */
-/* ETMCR - 0x00 */
-#define ETMCR_PWD_DWN          BIT(0)
-#define ETMCR_STALL_MODE       BIT(7)
-#define ETMCR_ETM_PRG          BIT(10)
-#define ETMCR_ETM_EN           BIT(11)
-#define ETMCR_CYC_ACC          BIT(12)
-#define ETMCR_CTXID_SIZE       (BIT(14)|BIT(15))
-#define ETMCR_TIMESTAMP_EN     BIT(28)
-/* ETMCCR - 0x04 */
-#define ETMCCR_FIFOFULL                BIT(23)
-/* ETMPDCR - 0x310 */
-#define ETMPDCR_PWD_UP         BIT(3)
-/* ETMTECR1 - 0x024 */
-#define ETMTECR1_ADDR_COMP_1   BIT(0)
-#define ETMTECR1_INC_EXC       BIT(24)
-#define ETMTECR1_START_STOP    BIT(25)
-/* ETMCCER - 0x1E8 */
-#define ETMCCER_TIMESTAMP      BIT(22)
-
-#define ETM_MODE_EXCLUDE       BIT(0)
-#define ETM_MODE_CYCACC                BIT(1)
-#define ETM_MODE_STALL         BIT(2)
-#define ETM_MODE_TIMESTAMP     BIT(3)
-#define ETM_MODE_CTXID         BIT(4)
-#define ETM_MODE_ALL           0x1f
-
-#define ETM_SQR_MASK           0x3
-#define ETM_TRACEID_MASK       0x3f
-#define ETM_EVENT_MASK         0x1ffff
-#define ETM_SYNC_MASK          0xfff
-#define ETM_ALL_MASK           0xffffffff
-
-#define ETMSR_PROG_BIT         1
-#define ETM_SEQ_STATE_MAX_VAL  (0x2)
-#define PORT_SIZE_MASK         (GENMASK(21, 21) | GENMASK(6, 4))
-
-#define ETM_HARD_WIRE_RES_A    /* Hard wired, always true */   \
-                               ((0x0f << 0)    |               \
-                               /* Resource index A */          \
-                               (0x06 << 4))
-
-#define ETM_ADD_COMP_0         /* Single addr comparator 1 */  \
-                               ((0x00 << 7)    |               \
-                               /* Resource index B */          \
-                               (0x00 << 11))
-
-#define ETM_EVENT_NOT_A                BIT(14) /* NOT(A) */
-
-#define ETM_DEFAULT_EVENT_VAL  (ETM_HARD_WIRE_RES_A    |       \
-                                ETM_ADD_COMP_0         |       \
-                                ETM_EVENT_NOT_A)
-/**
- * struct etm_drvdata - specifics associated to an ETM component
- * @base:      memory mapped base address for this component.
- * @dev:       the device entity associated to this component.
- * @csdev:     component vitals needed by the framework.
- * @clk:       the clock this component is associated to.
- * @spinlock:  only one at a time pls.
- * @cpu:       the cpu this component is affined to.
- * @port_size: port size as reported by ETMCR bit 4-6 and 21.
- * @arch:      ETM/PTM version number.
- * @use_cpu14: true if management registers need to be accessed via CP14.
- * @enable:    is this ETM/PTM currently tracing.
- * @sticky_enable: true if ETM base configuration has been done.
- * @boot_enable:true if we should start tracing at boot time.
- * @os_unlock: true if access to management registers is allowed.
- * @nr_addr_cmp:Number of pairs of address comparators as found in ETMCCR.
- * @nr_cntr:   Number of counters as found in ETMCCR bit 13-15.
- * @nr_ext_inp:        Number of external input as found in ETMCCR bit 17-19.
- * @nr_ext_out:        Number of external output as found in ETMCCR bit 20-22.
- * @nr_ctxid_cmp: Number of contextID comparators as found in ETMCCR bit 24-25.
- * @etmccr:    value of register ETMCCR.
- * @etmccer:   value of register ETMCCER.
- * @traceid:   value of the current ID for this component.
- * @mode:      controls various modes supported by this ETM/PTM.
- * @ctrl:      used in conjunction with @mode.
- * @trigger_event: setting for register ETMTRIGGER.
- * @startstop_ctrl: setting for register ETMTSSCR.
- * @enable_event: setting for register ETMTEEVR.
- * @enable_ctrl1: setting for register ETMTECR1.
- * @fifofull_level: setting for register ETMFFLR.
- * @addr_idx:  index for the address comparator selection.
- * @addr_val:  value for address comparator register.
- * @addr_acctype: access type for address comparator register.
- * @addr_type: current status of the comparator register.
- * @cntr_idx:  index for the counter register selection.
- * @cntr_rld_val: reload value of a counter register.
- * @cntr_event:        control for counter enable register.
- * @cntr_rld_event: value for counter reload event register.
- * @cntr_val:  counter value register.
- * @seq_12_event: event causing the transition from 1 to 2.
- * @seq_21_event: event causing the transition from 2 to 1.
- * @seq_23_event: event causing the transition from 2 to 3.
- * @seq_31_event: event causing the transition from 3 to 1.
- * @seq_32_event: event causing the transition from 3 to 2.
- * @seq_13_event: event causing the transition from 1 to 3.
- * @seq_curr_state: current value of the sequencer register.
- * @ctxid_idx: index for the context ID registers.
- * @ctxid_val: value for the context ID to trigger on.
- * @ctxid_mask: mask applicable to all the context IDs.
- * @sync_freq: Synchronisation frequency.
- * @timestamp_event: Defines an event that requests the insertion
-                    of a timestamp into the trace stream.
- */
-struct etm_drvdata {
-       void __iomem                    *base;
-       struct device                   *dev;
-       struct coresight_device         *csdev;
-       struct clk                      *clk;
-       spinlock_t                      spinlock;
-       int                             cpu;
-       int                             port_size;
-       u8                              arch;
-       bool                            use_cp14;
-       bool                            enable;
-       bool                            sticky_enable;
-       bool                            boot_enable;
-       bool                            os_unlock;
-       u8                              nr_addr_cmp;
-       u8                              nr_cntr;
-       u8                              nr_ext_inp;
-       u8                              nr_ext_out;
-       u8                              nr_ctxid_cmp;
-       u32                             etmccr;
-       u32                             etmccer;
-       u32                             traceid;
-       u32                             mode;
-       u32                             ctrl;
-       u32                             trigger_event;
-       u32                             startstop_ctrl;
-       u32                             enable_event;
-       u32                             enable_ctrl1;
-       u32                             fifofull_level;
-       u8                              addr_idx;
-       u32                             addr_val[ETM_MAX_ADDR_CMP];
-       u32                             addr_acctype[ETM_MAX_ADDR_CMP];
-       u32                             addr_type[ETM_MAX_ADDR_CMP];
-       u8                              cntr_idx;
-       u32                             cntr_rld_val[ETM_MAX_CNTR];
-       u32                             cntr_event[ETM_MAX_CNTR];
-       u32                             cntr_rld_event[ETM_MAX_CNTR];
-       u32                             cntr_val[ETM_MAX_CNTR];
-       u32                             seq_12_event;
-       u32                             seq_21_event;
-       u32                             seq_23_event;
-       u32                             seq_31_event;
-       u32                             seq_32_event;
-       u32                             seq_13_event;
-       u32                             seq_curr_state;
-       u8                              ctxid_idx;
-       u32                             ctxid_val[ETM_MAX_CTXID_CMP];
-       u32                             ctxid_mask;
-       u32                             sync_freq;
-       u32                             timestamp_event;
-};
-
-enum etm_addr_type {
-       ETM_ADDR_TYPE_NONE,
-       ETM_ADDR_TYPE_SINGLE,
-       ETM_ADDR_TYPE_RANGE,
-       ETM_ADDR_TYPE_START,
-       ETM_ADDR_TYPE_STOP,
-};
-#endif
diff --git a/drivers/coresight/coresight-etm3x.c b/drivers/coresight/coresight-etm3x.c
deleted file mode 100644 (file)
index c965f57..0000000
+++ /dev/null
@@ -1,1932 +0,0 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/device.h>
-#include <linux/io.h>
-#include <linux/err.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/smp.h>
-#include <linux/sysfs.h>
-#include <linux/stat.h>
-#include <linux/clk.h>
-#include <linux/cpu.h>
-#include <linux/of.h>
-#include <linux/coresight.h>
-#include <linux/amba/bus.h>
-#include <linux/seq_file.h>
-#include <linux/uaccess.h>
-#include <asm/sections.h>
-
-#include "coresight-etm.h"
-
-static int boot_enable;
-module_param_named(boot_enable, boot_enable, int, S_IRUGO);
-
-/* The number of ETM/PTM currently registered */
-static int etm_count;
-static struct etm_drvdata *etmdrvdata[NR_CPUS];
-
-static inline void etm_writel(struct etm_drvdata *drvdata,
-                             u32 val, u32 off)
-{
-       if (drvdata->use_cp14) {
-               if (etm_writel_cp14(off, val)) {
-                       dev_err(drvdata->dev,
-                               "invalid CP14 access to ETM reg: %#x", off);
-               }
-       } else {
-               writel_relaxed(val, drvdata->base + off);
-       }
-}
-
-static inline unsigned int etm_readl(struct etm_drvdata *drvdata, u32 off)
-{
-       u32 val;
-
-       if (drvdata->use_cp14) {
-               if (etm_readl_cp14(off, &val)) {
-                       dev_err(drvdata->dev,
-                               "invalid CP14 access to ETM reg: %#x", off);
-               }
-       } else {
-               val = readl_relaxed(drvdata->base + off);
-       }
-
-       return val;
-}
-
-/*
- * Memory mapped writes to clear os lock are not supported on some processors
- * and OS lock must be unlocked before any memory mapped access on such
- * processors, otherwise memory mapped reads/writes will be invalid.
- */
-static void etm_os_unlock(void *info)
-{
-       struct etm_drvdata *drvdata = (struct etm_drvdata *)info;
-       /* Writing any value to ETMOSLAR unlocks the trace registers */
-       etm_writel(drvdata, 0x0, ETMOSLAR);
-       isb();
-}
-
-static void etm_set_pwrdwn(struct etm_drvdata *drvdata)
-{
-       u32 etmcr;
-
-       /* Ensure pending cp14 accesses complete before setting pwrdwn */
-       mb();
-       isb();
-       etmcr = etm_readl(drvdata, ETMCR);
-       etmcr |= ETMCR_PWD_DWN;
-       etm_writel(drvdata, etmcr, ETMCR);
-}
-
-static void etm_clr_pwrdwn(struct etm_drvdata *drvdata)
-{
-       u32 etmcr;
-
-       etmcr = etm_readl(drvdata, ETMCR);
-       etmcr &= ~ETMCR_PWD_DWN;
-       etm_writel(drvdata, etmcr, ETMCR);
-       /* Ensure pwrup completes before subsequent cp14 accesses */
-       mb();
-       isb();
-}
-
-static void etm_set_pwrup(struct etm_drvdata *drvdata)
-{
-       u32 etmpdcr;
-
-       etmpdcr = readl_relaxed(drvdata->base + ETMPDCR);
-       etmpdcr |= ETMPDCR_PWD_UP;
-       writel_relaxed(etmpdcr, drvdata->base + ETMPDCR);
-       /* Ensure pwrup completes before subsequent cp14 accesses */
-       mb();
-       isb();
-}
-
-static void etm_clr_pwrup(struct etm_drvdata *drvdata)
-{
-       u32 etmpdcr;
-
-       /* Ensure pending cp14 accesses complete before clearing pwrup */
-       mb();
-       isb();
-       etmpdcr = readl_relaxed(drvdata->base + ETMPDCR);
-       etmpdcr &= ~ETMPDCR_PWD_UP;
-       writel_relaxed(etmpdcr, drvdata->base + ETMPDCR);
-}
-
-/**
- * coresight_timeout_etm - loop until a bit has changed to a specific state.
- * @drvdata: etm's private data structure.
- * @offset: address of a register, starting from @addr.
- * @position: the position of the bit of interest.
- * @value: the value the bit should have.
- *
- * Basically the same as @coresight_timeout except for the register access
- * method where we have to account for CP14 configurations.
-
- * Return: 0 as soon as the bit has taken the desired state or -EAGAIN if
- * TIMEOUT_US has elapsed, which ever happens first.
- */
-
-static int coresight_timeout_etm(struct etm_drvdata *drvdata, u32 offset,
-                                 int position, int value)
-{
-       int i;
-       u32 val;
-
-       for (i = TIMEOUT_US; i > 0; i--) {
-               val = etm_readl(drvdata, offset);
-               /* Waiting on the bit to go from 0 to 1 */
-               if (value) {
-                       if (val & BIT(position))
-                               return 0;
-               /* Waiting on the bit to go from 1 to 0 */
-               } else {
-                       if (!(val & BIT(position)))
-                               return 0;
-               }
-
-               /*
-                * Delay is arbitrary - the specification doesn't say how long
-                * we are expected to wait.  Extra check required to make sure
-                * we don't wait needlessly on the last iteration.
-                */
-               if (i - 1)
-                       udelay(1);
-       }
-
-       return -EAGAIN;
-}
-
-
-static void etm_set_prog(struct etm_drvdata *drvdata)
-{
-       u32 etmcr;
-
-       etmcr = etm_readl(drvdata, ETMCR);
-       etmcr |= ETMCR_ETM_PRG;
-       etm_writel(drvdata, etmcr, ETMCR);
-       /*
-        * Recommended by spec for cp14 accesses to ensure etmcr write is
-        * complete before polling etmsr
-        */
-       isb();
-       if (coresight_timeout_etm(drvdata, ETMSR, ETMSR_PROG_BIT, 1)) {
-               dev_err(drvdata->dev,
-                       "timeout observed when probing at offset %#x\n", ETMSR);
-       }
-}
-
-static void etm_clr_prog(struct etm_drvdata *drvdata)
-{
-       u32 etmcr;
-
-       etmcr = etm_readl(drvdata, ETMCR);
-       etmcr &= ~ETMCR_ETM_PRG;
-       etm_writel(drvdata, etmcr, ETMCR);
-       /*
-        * Recommended by spec for cp14 accesses to ensure etmcr write is
-        * complete before polling etmsr
-        */
-       isb();
-       if (coresight_timeout_etm(drvdata, ETMSR, ETMSR_PROG_BIT, 0)) {
-               dev_err(drvdata->dev,
-                       "timeout observed when probing at offset %#x\n", ETMSR);
-       }
-}
-
-static void etm_set_default(struct etm_drvdata *drvdata)
-{
-       int i;
-
-       drvdata->trigger_event = ETM_DEFAULT_EVENT_VAL;
-       drvdata->enable_event = ETM_HARD_WIRE_RES_A;
-
-       drvdata->seq_12_event = ETM_DEFAULT_EVENT_VAL;
-       drvdata->seq_21_event = ETM_DEFAULT_EVENT_VAL;
-       drvdata->seq_23_event = ETM_DEFAULT_EVENT_VAL;
-       drvdata->seq_31_event = ETM_DEFAULT_EVENT_VAL;
-       drvdata->seq_32_event = ETM_DEFAULT_EVENT_VAL;
-       drvdata->seq_13_event = ETM_DEFAULT_EVENT_VAL;
-       drvdata->timestamp_event = ETM_DEFAULT_EVENT_VAL;
-
-       for (i = 0; i < drvdata->nr_cntr; i++) {
-               drvdata->cntr_rld_val[i] = 0x0;
-               drvdata->cntr_event[i] = ETM_DEFAULT_EVENT_VAL;
-               drvdata->cntr_rld_event[i] = ETM_DEFAULT_EVENT_VAL;
-               drvdata->cntr_val[i] = 0x0;
-       }
-
-       drvdata->seq_curr_state = 0x0;
-       drvdata->ctxid_idx = 0x0;
-       for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
-               drvdata->ctxid_val[i] = 0x0;
-       drvdata->ctxid_mask = 0x0;
-}
-
-static void etm_enable_hw(void *info)
-{
-       int i;
-       u32 etmcr;
-       struct etm_drvdata *drvdata = info;
-
-       CS_UNLOCK(drvdata->base);
-
-       /* Turn engine on */
-       etm_clr_pwrdwn(drvdata);
-       /* Apply power to trace registers */
-       etm_set_pwrup(drvdata);
-       /* Make sure all registers are accessible */
-       etm_os_unlock(drvdata);
-
-       etm_set_prog(drvdata);
-
-       etmcr = etm_readl(drvdata, ETMCR);
-       etmcr &= (ETMCR_PWD_DWN | ETMCR_ETM_PRG);
-       etmcr |= drvdata->port_size;
-       etm_writel(drvdata, drvdata->ctrl | etmcr, ETMCR);
-       etm_writel(drvdata, drvdata->trigger_event, ETMTRIGGER);
-       etm_writel(drvdata, drvdata->startstop_ctrl, ETMTSSCR);
-       etm_writel(drvdata, drvdata->enable_event, ETMTEEVR);
-       etm_writel(drvdata, drvdata->enable_ctrl1, ETMTECR1);
-       etm_writel(drvdata, drvdata->fifofull_level, ETMFFLR);
-       for (i = 0; i < drvdata->nr_addr_cmp; i++) {
-               etm_writel(drvdata, drvdata->addr_val[i], ETMACVRn(i));
-               etm_writel(drvdata, drvdata->addr_acctype[i], ETMACTRn(i));
-       }
-       for (i = 0; i < drvdata->nr_cntr; i++) {
-               etm_writel(drvdata, drvdata->cntr_rld_val[i], ETMCNTRLDVRn(i));
-               etm_writel(drvdata, drvdata->cntr_event[i], ETMCNTENRn(i));
-               etm_writel(drvdata, drvdata->cntr_rld_event[i],
-                          ETMCNTRLDEVRn(i));
-               etm_writel(drvdata, drvdata->cntr_val[i], ETMCNTVRn(i));
-       }
-       etm_writel(drvdata, drvdata->seq_12_event, ETMSQ12EVR);
-       etm_writel(drvdata, drvdata->seq_21_event, ETMSQ21EVR);
-       etm_writel(drvdata, drvdata->seq_23_event, ETMSQ23EVR);
-       etm_writel(drvdata, drvdata->seq_31_event, ETMSQ31EVR);
-       etm_writel(drvdata, drvdata->seq_32_event, ETMSQ32EVR);
-       etm_writel(drvdata, drvdata->seq_13_event, ETMSQ13EVR);
-       etm_writel(drvdata, drvdata->seq_curr_state, ETMSQR);
-       for (i = 0; i < drvdata->nr_ext_out; i++)
-               etm_writel(drvdata, ETM_DEFAULT_EVENT_VAL, ETMEXTOUTEVRn(i));
-       for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
-               etm_writel(drvdata, drvdata->ctxid_val[i], ETMCIDCVRn(i));
-       etm_writel(drvdata, drvdata->ctxid_mask, ETMCIDCMR);
-       etm_writel(drvdata, drvdata->sync_freq, ETMSYNCFR);
-       /* No external input selected */
-       etm_writel(drvdata, 0x0, ETMEXTINSELR);
-       etm_writel(drvdata, drvdata->timestamp_event, ETMTSEVR);
-       /* No auxiliary control selected */
-       etm_writel(drvdata, 0x0, ETMAUXCR);
-       etm_writel(drvdata, drvdata->traceid, ETMTRACEIDR);
-       /* No VMID comparator value selected */
-       etm_writel(drvdata, 0x0, ETMVMIDCVR);
-
-       /* Ensures trace output is enabled from this ETM */
-       etm_writel(drvdata, drvdata->ctrl | ETMCR_ETM_EN | etmcr, ETMCR);
-
-       etm_clr_prog(drvdata);
-       CS_LOCK(drvdata->base);
-
-       dev_dbg(drvdata->dev, "cpu: %d enable smp call done\n", drvdata->cpu);
-}
-
-static int etm_trace_id_simple(struct etm_drvdata *drvdata)
-{
-       if (!drvdata->enable)
-               return drvdata->traceid;
-
-       return (etm_readl(drvdata, ETMTRACEIDR) & ETM_TRACEID_MASK);
-}
-
-static int etm_trace_id(struct coresight_device *csdev)
-{
-       struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-       unsigned long flags;
-       int trace_id = -1;
-
-       if (!drvdata->enable)
-               return drvdata->traceid;
-
-       if (clk_prepare_enable(drvdata->clk))
-               goto out;
-
-       spin_lock_irqsave(&drvdata->spinlock, flags);
-
-       CS_UNLOCK(drvdata->base);
-       trace_id = (etm_readl(drvdata, ETMTRACEIDR) & ETM_TRACEID_MASK);
-       CS_LOCK(drvdata->base);
-
-       spin_unlock_irqrestore(&drvdata->spinlock, flags);
-       clk_disable_unprepare(drvdata->clk);
-out:
-       return trace_id;
-}
-
-static int etm_enable(struct coresight_device *csdev)
-{
-       struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-       int ret;
-
-       ret = clk_prepare_enable(drvdata->clk);
-       if (ret)
-               goto err_clk;
-
-       spin_lock(&drvdata->spinlock);
-
-       /*
-        * Configure the ETM only if the CPU is online.  If it isn't online
-        * hw configuration will take place when 'CPU_STARTING' is received
-        * in @etm_cpu_callback.
-        */
-       if (cpu_online(drvdata->cpu)) {
-               ret = smp_call_function_single(drvdata->cpu,
-                                              etm_enable_hw, drvdata, 1);
-               if (ret)
-                       goto err;
-       }
-
-       drvdata->enable = true;
-       drvdata->sticky_enable = true;
-
-       spin_unlock(&drvdata->spinlock);
-
-       dev_info(drvdata->dev, "ETM tracing enabled\n");
-       return 0;
-err:
-       spin_unlock(&drvdata->spinlock);
-       clk_disable_unprepare(drvdata->clk);
-err_clk:
-       return ret;
-}
-
-static void etm_disable_hw(void *info)
-{
-       int i;
-       struct etm_drvdata *drvdata = info;
-
-       CS_UNLOCK(drvdata->base);
-       etm_set_prog(drvdata);
-
-       /* Program trace enable to low by using always false event */
-       etm_writel(drvdata, ETM_HARD_WIRE_RES_A | ETM_EVENT_NOT_A, ETMTEEVR);
-
-       /* Read back sequencer and counters for post trace analysis */
-       drvdata->seq_curr_state = (etm_readl(drvdata, ETMSQR) & ETM_SQR_MASK);
-
-       for (i = 0; i < drvdata->nr_cntr; i++)
-               drvdata->cntr_val[i] = etm_readl(drvdata, ETMCNTVRn(i));
-
-       etm_set_pwrdwn(drvdata);
-       CS_LOCK(drvdata->base);
-
-       dev_dbg(drvdata->dev, "cpu: %d disable smp call done\n", drvdata->cpu);
-}
-
-static void etm_disable(struct coresight_device *csdev)
-{
-       struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
-       /*
-        * Taking hotplug lock here protects from clocks getting disabled
-        * with tracing being left on (crash scenario) if user disable occurs
-        * after cpu online mask indicates the cpu is offline but before the
-        * DYING hotplug callback is serviced by the ETM driver.
-        */
-       get_online_cpus();
-       spin_lock(&drvdata->spinlock);
-
-       /*
-        * Executing etm_disable_hw on the cpu whose ETM is being disabled
-        * ensures that register writes occur when cpu is powered.
-        */
-       smp_call_function_single(drvdata->cpu, etm_disable_hw, drvdata, 1);
-       drvdata->enable = false;
-
-       spin_unlock(&drvdata->spinlock);
-       put_online_cpus();
-
-       clk_disable_unprepare(drvdata->clk);
-
-       dev_info(drvdata->dev, "ETM tracing disabled\n");
-}
-
-static const struct coresight_ops_source etm_source_ops = {
-       .trace_id       = etm_trace_id,
-       .enable         = etm_enable,
-       .disable        = etm_disable,
-};
-
-static const struct coresight_ops etm_cs_ops = {
-       .source_ops     = &etm_source_ops,
-};
-
-static ssize_t nr_addr_cmp_show(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       val = drvdata->nr_addr_cmp;
-       return sprintf(buf, "%#lx\n", val);
-}
-static DEVICE_ATTR_RO(nr_addr_cmp);
-
-static ssize_t nr_cntr_show(struct device *dev,
-                           struct device_attribute *attr, char *buf)
-{      unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       val = drvdata->nr_cntr;
-       return sprintf(buf, "%#lx\n", val);
-}
-static DEVICE_ATTR_RO(nr_cntr);
-
-static ssize_t nr_ctxid_cmp_show(struct device *dev,
-                                struct device_attribute *attr, char *buf)
-{
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       val = drvdata->nr_ctxid_cmp;
-       return sprintf(buf, "%#lx\n", val);
-}
-static DEVICE_ATTR_RO(nr_ctxid_cmp);
-
-static ssize_t etmsr_show(struct device *dev,
-                         struct device_attribute *attr, char *buf)
-{
-       int ret;
-       unsigned long flags, val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = clk_prepare_enable(drvdata->clk);
-       if (ret)
-               return ret;
-
-       spin_lock_irqsave(&drvdata->spinlock, flags);
-       CS_UNLOCK(drvdata->base);
-
-       val = etm_readl(drvdata, ETMSR);
-
-       CS_LOCK(drvdata->base);
-       spin_unlock_irqrestore(&drvdata->spinlock, flags);
-       clk_disable_unprepare(drvdata->clk);
-
-       return sprintf(buf, "%#lx\n", val);
-}
-static DEVICE_ATTR_RO(etmsr);
-
-static ssize_t reset_store(struct device *dev,
-                          struct device_attribute *attr,
-                          const char *buf, size_t size)
-{
-       int i, ret;
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = kstrtoul(buf, 16, &val);
-       if (ret)
-               return ret;
-
-       if (val) {
-               spin_lock(&drvdata->spinlock);
-               drvdata->mode = ETM_MODE_EXCLUDE;
-               drvdata->ctrl = 0x0;
-               drvdata->trigger_event = ETM_DEFAULT_EVENT_VAL;
-               drvdata->startstop_ctrl = 0x0;
-               drvdata->addr_idx = 0x0;
-               for (i = 0; i < drvdata->nr_addr_cmp; i++) {
-                       drvdata->addr_val[i] = 0x0;
-                       drvdata->addr_acctype[i] = 0x0;
-                       drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
-               }
-               drvdata->cntr_idx = 0x0;
-
-               etm_set_default(drvdata);
-               spin_unlock(&drvdata->spinlock);
-       }
-
-       return size;
-}
-static DEVICE_ATTR_WO(reset);
-
-static ssize_t mode_show(struct device *dev,
-                        struct device_attribute *attr, char *buf)
-{
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       val = drvdata->mode;
-       return sprintf(buf, "%#lx\n", val);
-}
-
-static ssize_t mode_store(struct device *dev,
-                         struct device_attribute *attr,
-                         const char *buf, size_t size)
-{
-       int ret;
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = kstrtoul(buf, 16, &val);
-       if (ret)
-               return ret;
-
-       spin_lock(&drvdata->spinlock);
-       drvdata->mode = val & ETM_MODE_ALL;
-
-       if (drvdata->mode & ETM_MODE_EXCLUDE)
-               drvdata->enable_ctrl1 |= ETMTECR1_INC_EXC;
-       else
-               drvdata->enable_ctrl1 &= ~ETMTECR1_INC_EXC;
-
-       if (drvdata->mode & ETM_MODE_CYCACC)
-               drvdata->ctrl |= ETMCR_CYC_ACC;
-       else
-               drvdata->ctrl &= ~ETMCR_CYC_ACC;
-
-       if (drvdata->mode & ETM_MODE_STALL) {
-               if (!(drvdata->etmccr & ETMCCR_FIFOFULL)) {
-                       dev_warn(drvdata->dev, "stall mode not supported\n");
-                       ret = -EINVAL;
-                       goto err_unlock;
-               }
-               drvdata->ctrl |= ETMCR_STALL_MODE;
-        } else
-               drvdata->ctrl &= ~ETMCR_STALL_MODE;
-
-       if (drvdata->mode & ETM_MODE_TIMESTAMP) {
-               if (!(drvdata->etmccer & ETMCCER_TIMESTAMP)) {
-                       dev_warn(drvdata->dev, "timestamp not supported\n");
-                       ret = -EINVAL;
-                       goto err_unlock;
-               }
-               drvdata->ctrl |= ETMCR_TIMESTAMP_EN;
-       } else
-               drvdata->ctrl &= ~ETMCR_TIMESTAMP_EN;
-
-       if (drvdata->mode & ETM_MODE_CTXID)
-               drvdata->ctrl |= ETMCR_CTXID_SIZE;
-       else
-               drvdata->ctrl &= ~ETMCR_CTXID_SIZE;
-       spin_unlock(&drvdata->spinlock);
-
-       return size;
-
-err_unlock:
-       spin_unlock(&drvdata->spinlock);
-       return ret;
-}
-static DEVICE_ATTR_RW(mode);
-
-static ssize_t trigger_event_show(struct device *dev,
-                                 struct device_attribute *attr, char *buf)
-{
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       val = drvdata->trigger_event;
-       return sprintf(buf, "%#lx\n", val);
-}
-
-static ssize_t trigger_event_store(struct device *dev,
-                                  struct device_attribute *attr,
-                                  const char *buf, size_t size)
-{
-       int ret;
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = kstrtoul(buf, 16, &val);
-       if (ret)
-               return ret;
-
-       drvdata->trigger_event = val & ETM_EVENT_MASK;
-
-       return size;
-}
-static DEVICE_ATTR_RW(trigger_event);
-
-static ssize_t enable_event_show(struct device *dev,
-                                struct device_attribute *attr, char *buf)
-{
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       val = drvdata->enable_event;
-       return sprintf(buf, "%#lx\n", val);
-}
-
-static ssize_t enable_event_store(struct device *dev,
-                                 struct device_attribute *attr,
-                                 const char *buf, size_t size)
-{
-       int ret;
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = kstrtoul(buf, 16, &val);
-       if (ret)
-               return ret;
-
-       drvdata->enable_event = val & ETM_EVENT_MASK;
-
-       return size;
-}
-static DEVICE_ATTR_RW(enable_event);
-
-static ssize_t fifofull_level_show(struct device *dev,
-                                  struct device_attribute *attr, char *buf)
-{
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       val = drvdata->fifofull_level;
-       return sprintf(buf, "%#lx\n", val);
-}
-
-static ssize_t fifofull_level_store(struct device *dev,
-                                   struct device_attribute *attr,
-                                   const char *buf, size_t size)
-{
-       int ret;
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = kstrtoul(buf, 16, &val);
-       if (ret)
-               return ret;
-
-       drvdata->fifofull_level = val;
-
-       return size;
-}
-static DEVICE_ATTR_RW(fifofull_level);
-
-static ssize_t addr_idx_show(struct device *dev,
-                            struct device_attribute *attr, char *buf)
-{
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       val = drvdata->addr_idx;
-       return sprintf(buf, "%#lx\n", val);
-}
-
-static ssize_t addr_idx_store(struct device *dev,
-                             struct device_attribute *attr,
-                             const char *buf, size_t size)
-{
-       int ret;
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = kstrtoul(buf, 16, &val);
-       if (ret)
-               return ret;
-
-       if (val >= drvdata->nr_addr_cmp)
-               return -EINVAL;
-
-       /*
-        * Use spinlock to ensure index doesn't change while it gets
-        * dereferenced multiple times within a spinlock block elsewhere.
-        */
-       spin_lock(&drvdata->spinlock);
-       drvdata->addr_idx = val;
-       spin_unlock(&drvdata->spinlock);
-
-       return size;
-}
-static DEVICE_ATTR_RW(addr_idx);
-
-static ssize_t addr_single_show(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-       u8 idx;
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       spin_lock(&drvdata->spinlock);
-       idx = drvdata->addr_idx;
-       if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
-             drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
-               spin_unlock(&drvdata->spinlock);
-               return -EINVAL;
-       }
-
-       val = drvdata->addr_val[idx];
-       spin_unlock(&drvdata->spinlock);
-
-       return sprintf(buf, "%#lx\n", val);
-}
-
-static ssize_t addr_single_store(struct device *dev,
-                                struct device_attribute *attr,
-                                const char *buf, size_t size)
-{
-       u8 idx;
-       int ret;
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = kstrtoul(buf, 16, &val);
-       if (ret)
-               return ret;
-
-       spin_lock(&drvdata->spinlock);
-       idx = drvdata->addr_idx;
-       if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
-             drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
-               spin_unlock(&drvdata->spinlock);
-               return -EINVAL;
-       }
-
-       drvdata->addr_val[idx] = val;
-       drvdata->addr_type[idx] = ETM_ADDR_TYPE_SINGLE;
-       spin_unlock(&drvdata->spinlock);
-
-       return size;
-}
-static DEVICE_ATTR_RW(addr_single);
-
-static ssize_t addr_range_show(struct device *dev,
-                              struct device_attribute *attr, char *buf)
-{
-       u8 idx;
-       unsigned long val1, val2;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       spin_lock(&drvdata->spinlock);
-       idx = drvdata->addr_idx;
-       if (idx % 2 != 0) {
-               spin_unlock(&drvdata->spinlock);
-               return -EPERM;
-       }
-       if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
-              drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
-             (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
-              drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
-               spin_unlock(&drvdata->spinlock);
-               return -EPERM;
-       }
-
-       val1 = drvdata->addr_val[idx];
-       val2 = drvdata->addr_val[idx + 1];
-       spin_unlock(&drvdata->spinlock);
-
-       return sprintf(buf, "%#lx %#lx\n", val1, val2);
-}
-
-static ssize_t addr_range_store(struct device *dev,
-                             struct device_attribute *attr,
-                             const char *buf, size_t size)
-{
-       u8 idx;
-       unsigned long val1, val2;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       if (sscanf(buf, "%lx %lx", &val1, &val2) != 2)
-               return -EINVAL;
-       /* Lower address comparator cannot have a higher address value */
-       if (val1 > val2)
-               return -EINVAL;
-
-       spin_lock(&drvdata->spinlock);
-       idx = drvdata->addr_idx;
-       if (idx % 2 != 0) {
-               spin_unlock(&drvdata->spinlock);
-               return -EPERM;
-       }
-       if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
-              drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
-             (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
-              drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
-               spin_unlock(&drvdata->spinlock);
-               return -EPERM;
-       }
-
-       drvdata->addr_val[idx] = val1;
-       drvdata->addr_type[idx] = ETM_ADDR_TYPE_RANGE;
-       drvdata->addr_val[idx + 1] = val2;
-       drvdata->addr_type[idx + 1] = ETM_ADDR_TYPE_RANGE;
-       drvdata->enable_ctrl1 |= (1 << (idx/2));
-       spin_unlock(&drvdata->spinlock);
-
-       return size;
-}
-static DEVICE_ATTR_RW(addr_range);
-
-static ssize_t addr_start_show(struct device *dev,
-                              struct device_attribute *attr, char *buf)
-{
-       u8 idx;
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       spin_lock(&drvdata->spinlock);
-       idx = drvdata->addr_idx;
-       if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
-             drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
-               spin_unlock(&drvdata->spinlock);
-               return -EPERM;
-       }
-
-       val = drvdata->addr_val[idx];
-       spin_unlock(&drvdata->spinlock);
-
-       return sprintf(buf, "%#lx\n", val);
-}
-
-static ssize_t addr_start_store(struct device *dev,
-                               struct device_attribute *attr,
-                               const char *buf, size_t size)
-{
-       u8 idx;
-       int ret;
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = kstrtoul(buf, 16, &val);
-       if (ret)
-               return ret;
-
-       spin_lock(&drvdata->spinlock);
-       idx = drvdata->addr_idx;
-       if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
-             drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
-               spin_unlock(&drvdata->spinlock);
-               return -EPERM;
-       }
-
-       drvdata->addr_val[idx] = val;
-       drvdata->addr_type[idx] = ETM_ADDR_TYPE_START;
-       drvdata->startstop_ctrl |= (1 << idx);
-       drvdata->enable_ctrl1 |= BIT(25);
-       spin_unlock(&drvdata->spinlock);
-
-       return size;
-}
-static DEVICE_ATTR_RW(addr_start);
-
-static ssize_t addr_stop_show(struct device *dev,
-                             struct device_attribute *attr, char *buf)
-{
-       u8 idx;
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       spin_lock(&drvdata->spinlock);
-       idx = drvdata->addr_idx;
-       if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
-             drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
-               spin_unlock(&drvdata->spinlock);
-               return -EPERM;
-       }
-
-       val = drvdata->addr_val[idx];
-       spin_unlock(&drvdata->spinlock);
-
-       return sprintf(buf, "%#lx\n", val);
-}
-
-static ssize_t addr_stop_store(struct device *dev,
-                              struct device_attribute *attr,
-                              const char *buf, size_t size)
-{
-       u8 idx;
-       int ret;
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = kstrtoul(buf, 16, &val);
-       if (ret)
-               return ret;
-
-       spin_lock(&drvdata->spinlock);
-       idx = drvdata->addr_idx;
-       if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
-             drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
-               spin_unlock(&drvdata->spinlock);
-               return -EPERM;
-       }
-
-       drvdata->addr_val[idx] = val;
-       drvdata->addr_type[idx] = ETM_ADDR_TYPE_STOP;
-       drvdata->startstop_ctrl |= (1 << (idx + 16));
-       drvdata->enable_ctrl1 |= ETMTECR1_START_STOP;
-       spin_unlock(&drvdata->spinlock);
-
-       return size;
-}
-static DEVICE_ATTR_RW(addr_stop);
-
-static ssize_t addr_acctype_show(struct device *dev,
-                                struct device_attribute *attr, char *buf)
-{
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       spin_lock(&drvdata->spinlock);
-       val = drvdata->addr_acctype[drvdata->addr_idx];
-       spin_unlock(&drvdata->spinlock);
-
-       return sprintf(buf, "%#lx\n", val);
-}
-
-static ssize_t addr_acctype_store(struct device *dev,
-                                 struct device_attribute *attr,
-                                 const char *buf, size_t size)
-{
-       int ret;
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = kstrtoul(buf, 16, &val);
-       if (ret)
-               return ret;
-
-       spin_lock(&drvdata->spinlock);
-       drvdata->addr_acctype[drvdata->addr_idx] = val;
-       spin_unlock(&drvdata->spinlock);
-
-       return size;
-}
-static DEVICE_ATTR_RW(addr_acctype);
-
-static ssize_t cntr_idx_show(struct device *dev,
-                            struct device_attribute *attr, char *buf)
-{
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       val = drvdata->cntr_idx;
-       return sprintf(buf, "%#lx\n", val);
-}
-
-static ssize_t cntr_idx_store(struct device *dev,
-                             struct device_attribute *attr,
-                             const char *buf, size_t size)
-{
-       int ret;
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = kstrtoul(buf, 16, &val);
-       if (ret)
-               return ret;
-
-       if (val >= drvdata->nr_cntr)
-               return -EINVAL;
-       /*
-        * Use spinlock to ensure index doesn't change while it gets
-        * dereferenced multiple times within a spinlock block elsewhere.
-        */
-       spin_lock(&drvdata->spinlock);
-       drvdata->cntr_idx = val;
-       spin_unlock(&drvdata->spinlock);
-
-       return size;
-}
-static DEVICE_ATTR_RW(cntr_idx);
-
-static ssize_t cntr_rld_val_show(struct device *dev,
-                                struct device_attribute *attr, char *buf)
-{
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       spin_lock(&drvdata->spinlock);
-       val = drvdata->cntr_rld_val[drvdata->cntr_idx];
-       spin_unlock(&drvdata->spinlock);
-
-       return sprintf(buf, "%#lx\n", val);
-}
-
-static ssize_t cntr_rld_val_store(struct device *dev,
-                                 struct device_attribute *attr,
-                                 const char *buf, size_t size)
-{
-       int ret;
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = kstrtoul(buf, 16, &val);
-       if (ret)
-               return ret;
-
-       spin_lock(&drvdata->spinlock);
-       drvdata->cntr_rld_val[drvdata->cntr_idx] = val;
-       spin_unlock(&drvdata->spinlock);
-
-       return size;
-}
-static DEVICE_ATTR_RW(cntr_rld_val);
-
-static ssize_t cntr_event_show(struct device *dev,
-                              struct device_attribute *attr, char *buf)
-{
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       spin_lock(&drvdata->spinlock);
-       val = drvdata->cntr_event[drvdata->cntr_idx];
-       spin_unlock(&drvdata->spinlock);
-
-       return sprintf(buf, "%#lx\n", val);
-}
-
-static ssize_t cntr_event_store(struct device *dev,
-                               struct device_attribute *attr,
-                               const char *buf, size_t size)
-{
-       int ret;
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = kstrtoul(buf, 16, &val);
-       if (ret)
-               return ret;
-
-       spin_lock(&drvdata->spinlock);
-       drvdata->cntr_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
-       spin_unlock(&drvdata->spinlock);
-
-       return size;
-}
-static DEVICE_ATTR_RW(cntr_event);
-
-static ssize_t cntr_rld_event_show(struct device *dev,
-                                  struct device_attribute *attr, char *buf)
-{
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       spin_lock(&drvdata->spinlock);
-       val = drvdata->cntr_rld_event[drvdata->cntr_idx];
-       spin_unlock(&drvdata->spinlock);
-
-       return sprintf(buf, "%#lx\n", val);
-}
-
-static ssize_t cntr_rld_event_store(struct device *dev,
-                                   struct device_attribute *attr,
-                                   const char *buf, size_t size)
-{
-       int ret;
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = kstrtoul(buf, 16, &val);
-       if (ret)
-               return ret;
-
-       spin_lock(&drvdata->spinlock);
-       drvdata->cntr_rld_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
-       spin_unlock(&drvdata->spinlock);
-
-       return size;
-}
-static DEVICE_ATTR_RW(cntr_rld_event);
-
-static ssize_t cntr_val_show(struct device *dev,
-                            struct device_attribute *attr, char *buf)
-{
-       int i, ret = 0;
-       u32 val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       if (!drvdata->enable) {
-               spin_lock(&drvdata->spinlock);
-               for (i = 0; i < drvdata->nr_cntr; i++)
-                       ret += sprintf(buf, "counter %d: %x\n",
-                                      i, drvdata->cntr_val[i]);
-               spin_unlock(&drvdata->spinlock);
-               return ret;
-       }
-
-       for (i = 0; i < drvdata->nr_cntr; i++) {
-               val = etm_readl(drvdata, ETMCNTVRn(i));
-               ret += sprintf(buf, "counter %d: %x\n", i, val);
-       }
-
-       return ret;
-}
-
-static ssize_t cntr_val_store(struct device *dev,
-                             struct device_attribute *attr,
-                             const char *buf, size_t size)
-{
-       int ret;
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = kstrtoul(buf, 16, &val);
-       if (ret)
-               return ret;
-
-       spin_lock(&drvdata->spinlock);
-       drvdata->cntr_val[drvdata->cntr_idx] = val;
-       spin_unlock(&drvdata->spinlock);
-
-       return size;
-}
-static DEVICE_ATTR_RW(cntr_val);
-
-static ssize_t seq_12_event_show(struct device *dev,
-                                struct device_attribute *attr, char *buf)
-{
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       val = drvdata->seq_12_event;
-       return sprintf(buf, "%#lx\n", val);
-}
-
-static ssize_t seq_12_event_store(struct device *dev,
-                                 struct device_attribute *attr,
-                                 const char *buf, size_t size)
-{
-       int ret;
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = kstrtoul(buf, 16, &val);
-       if (ret)
-               return ret;
-
-       drvdata->seq_12_event = val & ETM_EVENT_MASK;
-       return size;
-}
-static DEVICE_ATTR_RW(seq_12_event);
-
-static ssize_t seq_21_event_show(struct device *dev,
-                                struct device_attribute *attr, char *buf)
-{
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       val = drvdata->seq_21_event;
-       return sprintf(buf, "%#lx\n", val);
-}
-
-static ssize_t seq_21_event_store(struct device *dev,
-                                 struct device_attribute *attr,
-                                 const char *buf, size_t size)
-{
-       int ret;
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = kstrtoul(buf, 16, &val);
-       if (ret)
-               return ret;
-
-       drvdata->seq_21_event = val & ETM_EVENT_MASK;
-       return size;
-}
-static DEVICE_ATTR_RW(seq_21_event);
-
-static ssize_t seq_23_event_show(struct device *dev,
-                                struct device_attribute *attr, char *buf)
-{
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       val = drvdata->seq_23_event;
-       return sprintf(buf, "%#lx\n", val);
-}
-
-static ssize_t seq_23_event_store(struct device *dev,
-                                 struct device_attribute *attr,
-                                 const char *buf, size_t size)
-{
-       int ret;
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = kstrtoul(buf, 16, &val);
-       if (ret)
-               return ret;
-
-       drvdata->seq_23_event = val & ETM_EVENT_MASK;
-       return size;
-}
-static DEVICE_ATTR_RW(seq_23_event);
-
-static ssize_t seq_31_event_show(struct device *dev,
-                                struct device_attribute *attr, char *buf)
-{
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       val = drvdata->seq_31_event;
-       return sprintf(buf, "%#lx\n", val);
-}
-
-static ssize_t seq_31_event_store(struct device *dev,
-                                 struct device_attribute *attr,
-                                 const char *buf, size_t size)
-{
-       int ret;
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = kstrtoul(buf, 16, &val);
-       if (ret)
-               return ret;
-
-       drvdata->seq_31_event = val & ETM_EVENT_MASK;
-       return size;
-}
-static DEVICE_ATTR_RW(seq_31_event);
-
-static ssize_t seq_32_event_show(struct device *dev,
-                                struct device_attribute *attr, char *buf)
-{
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       val = drvdata->seq_32_event;
-       return sprintf(buf, "%#lx\n", val);
-}
-
-static ssize_t seq_32_event_store(struct device *dev,
-                                 struct device_attribute *attr,
-                                 const char *buf, size_t size)
-{
-       int ret;
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = kstrtoul(buf, 16, &val);
-       if (ret)
-               return ret;
-
-       drvdata->seq_32_event = val & ETM_EVENT_MASK;
-       return size;
-}
-static DEVICE_ATTR_RW(seq_32_event);
-
-static ssize_t seq_13_event_show(struct device *dev,
-                                struct device_attribute *attr, char *buf)
-{
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       val = drvdata->seq_13_event;
-       return sprintf(buf, "%#lx\n", val);
-}
-
-static ssize_t seq_13_event_store(struct device *dev,
-                                 struct device_attribute *attr,
-                                 const char *buf, size_t size)
-{
-       int ret;
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = kstrtoul(buf, 16, &val);
-       if (ret)
-               return ret;
-
-       drvdata->seq_13_event = val & ETM_EVENT_MASK;
-       return size;
-}
-static DEVICE_ATTR_RW(seq_13_event);
-
-static ssize_t seq_curr_state_show(struct device *dev,
-                                  struct device_attribute *attr, char *buf)
-{
-       int ret;
-       unsigned long val, flags;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       if (!drvdata->enable) {
-               val = drvdata->seq_curr_state;
-               goto out;
-       }
-
-       ret = clk_prepare_enable(drvdata->clk);
-       if (ret)
-               return ret;
-
-       spin_lock_irqsave(&drvdata->spinlock, flags);
-
-       CS_UNLOCK(drvdata->base);
-       val = (etm_readl(drvdata, ETMSQR) & ETM_SQR_MASK);
-       CS_LOCK(drvdata->base);
-
-       spin_unlock_irqrestore(&drvdata->spinlock, flags);
-       clk_disable_unprepare(drvdata->clk);
-out:
-       return sprintf(buf, "%#lx\n", val);
-}
-
-static ssize_t seq_curr_state_store(struct device *dev,
-                                   struct device_attribute *attr,
-                                   const char *buf, size_t size)
-{
-       int ret;
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = kstrtoul(buf, 16, &val);
-       if (ret)
-               return ret;
-
-       if (val > ETM_SEQ_STATE_MAX_VAL)
-               return -EINVAL;
-
-       drvdata->seq_curr_state = val;
-
-       return size;
-}
-static DEVICE_ATTR_RW(seq_curr_state);
-
-static ssize_t ctxid_idx_show(struct device *dev,
-                             struct device_attribute *attr, char *buf)
-{
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       val = drvdata->ctxid_idx;
-       return sprintf(buf, "%#lx\n", val);
-}
-
-static ssize_t ctxid_idx_store(struct device *dev,
-                               struct device_attribute *attr,
-                               const char *buf, size_t size)
-{
-       int ret;
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = kstrtoul(buf, 16, &val);
-       if (ret)
-               return ret;
-
-       if (val >= drvdata->nr_ctxid_cmp)
-               return -EINVAL;
-
-       /*
-        * Use spinlock to ensure index doesn't change while it gets
-        * dereferenced multiple times within a spinlock block elsewhere.
-        */
-       spin_lock(&drvdata->spinlock);
-       drvdata->ctxid_idx = val;
-       spin_unlock(&drvdata->spinlock);
-
-       return size;
-}
-static DEVICE_ATTR_RW(ctxid_idx);
-
-static ssize_t ctxid_val_show(struct device *dev,
-                             struct device_attribute *attr, char *buf)
-{
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       spin_lock(&drvdata->spinlock);
-       val = drvdata->ctxid_val[drvdata->ctxid_idx];
-       spin_unlock(&drvdata->spinlock);
-
-       return sprintf(buf, "%#lx\n", val);
-}
-
-static ssize_t ctxid_val_store(struct device *dev,
-                              struct device_attribute *attr,
-                              const char *buf, size_t size)
-{
-       int ret;
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = kstrtoul(buf, 16, &val);
-       if (ret)
-               return ret;
-
-       spin_lock(&drvdata->spinlock);
-       drvdata->ctxid_val[drvdata->ctxid_idx] = val;
-       spin_unlock(&drvdata->spinlock);
-
-       return size;
-}
-static DEVICE_ATTR_RW(ctxid_val);
-
-static ssize_t ctxid_mask_show(struct device *dev,
-                              struct device_attribute *attr, char *buf)
-{
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       val = drvdata->ctxid_mask;
-       return sprintf(buf, "%#lx\n", val);
-}
-
-static ssize_t ctxid_mask_store(struct device *dev,
-                               struct device_attribute *attr,
-                               const char *buf, size_t size)
-{
-       int ret;
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = kstrtoul(buf, 16, &val);
-       if (ret)
-               return ret;
-
-       drvdata->ctxid_mask = val;
-       return size;
-}
-static DEVICE_ATTR_RW(ctxid_mask);
-
-static ssize_t sync_freq_show(struct device *dev,
-                             struct device_attribute *attr, char *buf)
-{
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       val = drvdata->sync_freq;
-       return sprintf(buf, "%#lx\n", val);
-}
-
-static ssize_t sync_freq_store(struct device *dev,
-                              struct device_attribute *attr,
-                              const char *buf, size_t size)
-{
-       int ret;
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = kstrtoul(buf, 16, &val);
-       if (ret)
-               return ret;
-
-       drvdata->sync_freq = val & ETM_SYNC_MASK;
-       return size;
-}
-static DEVICE_ATTR_RW(sync_freq);
-
-static ssize_t timestamp_event_show(struct device *dev,
-                                   struct device_attribute *attr, char *buf)
-{
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       val = drvdata->timestamp_event;
-       return sprintf(buf, "%#lx\n", val);
-}
-
-static ssize_t timestamp_event_store(struct device *dev,
-                                    struct device_attribute *attr,
-                                    const char *buf, size_t size)
-{
-       int ret;
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = kstrtoul(buf, 16, &val);
-       if (ret)
-               return ret;
-
-       drvdata->timestamp_event = val & ETM_EVENT_MASK;
-       return size;
-}
-static DEVICE_ATTR_RW(timestamp_event);
-
-static ssize_t status_show(struct device *dev,
-                          struct device_attribute *attr, char *buf)
-{
-       int ret;
-       unsigned long flags;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = clk_prepare_enable(drvdata->clk);
-       if (ret)
-               return ret;
-
-       spin_lock_irqsave(&drvdata->spinlock, flags);
-
-       CS_UNLOCK(drvdata->base);
-       ret = sprintf(buf,
-                     "ETMCCR: 0x%08x\n"
-                     "ETMCCER: 0x%08x\n"
-                     "ETMSCR: 0x%08x\n"
-                     "ETMIDR: 0x%08x\n"
-                     "ETMCR: 0x%08x\n"
-                     "ETMTRACEIDR: 0x%08x\n"
-                     "Enable event: 0x%08x\n"
-                     "Enable start/stop: 0x%08x\n"
-                     "Enable control: CR1 0x%08x CR2 0x%08x\n"
-                     "CPU affinity: %d\n",
-                     drvdata->etmccr, drvdata->etmccer,
-                     etm_readl(drvdata, ETMSCR), etm_readl(drvdata, ETMIDR),
-                     etm_readl(drvdata, ETMCR), etm_trace_id_simple(drvdata),
-                     etm_readl(drvdata, ETMTEEVR),
-                     etm_readl(drvdata, ETMTSSCR),
-                     etm_readl(drvdata, ETMTECR1),
-                     etm_readl(drvdata, ETMTECR2),
-                     drvdata->cpu);
-       CS_LOCK(drvdata->base);
-
-       spin_unlock_irqrestore(&drvdata->spinlock, flags);
-       clk_disable_unprepare(drvdata->clk);
-
-       return ret;
-}
-static DEVICE_ATTR_RO(status);
-
-static ssize_t traceid_show(struct device *dev,
-                           struct device_attribute *attr, char *buf)
-{
-       int ret;
-       unsigned long val, flags;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       if (!drvdata->enable) {
-               val = drvdata->traceid;
-               goto out;
-       }
-
-       ret = clk_prepare_enable(drvdata->clk);
-       if (ret)
-               return ret;
-
-       spin_lock_irqsave(&drvdata->spinlock, flags);
-       CS_UNLOCK(drvdata->base);
-
-       val = (etm_readl(drvdata, ETMTRACEIDR) & ETM_TRACEID_MASK);
-
-       CS_LOCK(drvdata->base);
-       spin_unlock_irqrestore(&drvdata->spinlock, flags);
-       clk_disable_unprepare(drvdata->clk);
-out:
-       return sprintf(buf, "%#lx\n", val);
-}
-
-static ssize_t traceid_store(struct device *dev,
-                            struct device_attribute *attr,
-                            const char *buf, size_t size)
-{
-       int ret;
-       unsigned long val;
-       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = kstrtoul(buf, 16, &val);
-       if (ret)
-               return ret;
-
-       drvdata->traceid = val & ETM_TRACEID_MASK;
-       return size;
-}
-static DEVICE_ATTR_RW(traceid);
-
-static struct attribute *coresight_etm_attrs[] = {
-       &dev_attr_nr_addr_cmp.attr,
-       &dev_attr_nr_cntr.attr,
-       &dev_attr_nr_ctxid_cmp.attr,
-       &dev_attr_etmsr.attr,
-       &dev_attr_reset.attr,
-       &dev_attr_mode.attr,
-       &dev_attr_trigger_event.attr,
-       &dev_attr_enable_event.attr,
-       &dev_attr_fifofull_level.attr,
-       &dev_attr_addr_idx.attr,
-       &dev_attr_addr_single.attr,
-       &dev_attr_addr_range.attr,
-       &dev_attr_addr_start.attr,
-       &dev_attr_addr_stop.attr,
-       &dev_attr_addr_acctype.attr,
-       &dev_attr_cntr_idx.attr,
-       &dev_attr_cntr_rld_val.attr,
-       &dev_attr_cntr_event.attr,
-       &dev_attr_cntr_rld_event.attr,
-       &dev_attr_cntr_val.attr,
-       &dev_attr_seq_12_event.attr,
-       &dev_attr_seq_21_event.attr,
-       &dev_attr_seq_23_event.attr,
-       &dev_attr_seq_31_event.attr,
-       &dev_attr_seq_32_event.attr,
-       &dev_attr_seq_13_event.attr,
-       &dev_attr_seq_curr_state.attr,
-       &dev_attr_ctxid_idx.attr,
-       &dev_attr_ctxid_val.attr,
-       &dev_attr_ctxid_mask.attr,
-       &dev_attr_sync_freq.attr,
-       &dev_attr_timestamp_event.attr,
-       &dev_attr_status.attr,
-       &dev_attr_traceid.attr,
-       NULL,
-};
-ATTRIBUTE_GROUPS(coresight_etm);
-
-static int etm_cpu_callback(struct notifier_block *nfb, unsigned long action,
-                           void *hcpu)
-{
-       unsigned int cpu = (unsigned long)hcpu;
-
-       if (!etmdrvdata[cpu])
-               goto out;
-
-       switch (action & (~CPU_TASKS_FROZEN)) {
-       case CPU_STARTING:
-               spin_lock(&etmdrvdata[cpu]->spinlock);
-               if (!etmdrvdata[cpu]->os_unlock) {
-                       etm_os_unlock(etmdrvdata[cpu]);
-                       etmdrvdata[cpu]->os_unlock = true;
-               }
-
-               if (etmdrvdata[cpu]->enable)
-                       etm_enable_hw(etmdrvdata[cpu]);
-               spin_unlock(&etmdrvdata[cpu]->spinlock);
-               break;
-
-       case CPU_ONLINE:
-               if (etmdrvdata[cpu]->boot_enable &&
-                   !etmdrvdata[cpu]->sticky_enable)
-                       coresight_enable(etmdrvdata[cpu]->csdev);
-               break;
-
-       case CPU_DYING:
-               spin_lock(&etmdrvdata[cpu]->spinlock);
-               if (etmdrvdata[cpu]->enable)
-                       etm_disable_hw(etmdrvdata[cpu]);
-               spin_unlock(&etmdrvdata[cpu]->spinlock);
-               break;
-       }
-out:
-       return NOTIFY_OK;
-}
-
-static struct notifier_block etm_cpu_notifier = {
-       .notifier_call = etm_cpu_callback,
-};
-
-static bool etm_arch_supported(u8 arch)
-{
-       switch (arch) {
-       case ETM_ARCH_V3_3:
-               break;
-       case ETM_ARCH_V3_5:
-               break;
-       case PFT_ARCH_V1_0:
-               break;
-       case PFT_ARCH_V1_1:
-               break;
-       default:
-               return false;
-       }
-       return true;
-}
-
-static void etm_init_arch_data(void *info)
-{
-       u32 etmidr;
-       u32 etmccr;
-       struct etm_drvdata *drvdata = info;
-
-       CS_UNLOCK(drvdata->base);
-
-       /* First dummy read */
-       (void)etm_readl(drvdata, ETMPDSR);
-       /* Provide power to ETM: ETMPDCR[3] == 1 */
-       etm_set_pwrup(drvdata);
-       /*
-        * Clear power down bit since when this bit is set writes to
-        * certain registers might be ignored.
-        */
-       etm_clr_pwrdwn(drvdata);
-       /*
-        * Set prog bit. It will be set from reset but this is included to
-        * ensure it is set
-        */
-       etm_set_prog(drvdata);
-
-       /* Find all capabilities */
-       etmidr = etm_readl(drvdata, ETMIDR);
-       drvdata->arch = BMVAL(etmidr, 4, 11);
-       drvdata->port_size = etm_readl(drvdata, ETMCR) & PORT_SIZE_MASK;
-
-       drvdata->etmccer = etm_readl(drvdata, ETMCCER);
-       etmccr = etm_readl(drvdata, ETMCCR);
-       drvdata->etmccr = etmccr;
-       drvdata->nr_addr_cmp = BMVAL(etmccr, 0, 3) * 2;
-       drvdata->nr_cntr = BMVAL(etmccr, 13, 15);
-       drvdata->nr_ext_inp = BMVAL(etmccr, 17, 19);
-       drvdata->nr_ext_out = BMVAL(etmccr, 20, 22);
-       drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
-
-       etm_set_pwrdwn(drvdata);
-       etm_clr_pwrup(drvdata);
-       CS_LOCK(drvdata->base);
-}
-
-static void etm_init_default_data(struct etm_drvdata *drvdata)
-{
-       /*
-        * A trace ID of value 0 is invalid, so let's start at some
-        * random value that fits in 7 bits and will be just as good.
-        */
-       static int etm3x_traceid = 0x10;
-
-       u32 flags = (1 << 0 | /* instruction execute*/
-                    3 << 3 | /* ARM instruction */
-                    0 << 5 | /* No data value comparison */
-                    0 << 7 | /* No exact mach */
-                    0 << 8 | /* Ignore context ID */
-                    0 << 10); /* Security ignored */
-
-       /*
-        * Initial configuration only - guarantees sources handled by
-        * this driver have a unique ID at startup time but not between
-        * all other types of sources.  For that we lean on the core
-        * framework.
-        */
-       drvdata->traceid = etm3x_traceid++;
-       drvdata->ctrl = (ETMCR_CYC_ACC | ETMCR_TIMESTAMP_EN);
-       drvdata->enable_ctrl1 = ETMTECR1_ADDR_COMP_1;
-       if (drvdata->nr_addr_cmp >= 2) {
-               drvdata->addr_val[0] = (u32) _stext;
-               drvdata->addr_val[1] = (u32) _etext;
-               drvdata->addr_acctype[0] = flags;
-               drvdata->addr_acctype[1] = flags;
-               drvdata->addr_type[0] = ETM_ADDR_TYPE_RANGE;
-               drvdata->addr_type[1] = ETM_ADDR_TYPE_RANGE;
-       }
-
-       etm_set_default(drvdata);
-}
-
-static int etm_probe(struct amba_device *adev, const struct amba_id *id)
-{
-       int ret;
-       void __iomem *base;
-       struct device *dev = &adev->dev;
-       struct coresight_platform_data *pdata = NULL;
-       struct etm_drvdata *drvdata;
-       struct resource *res = &adev->res;
-       struct coresight_desc *desc;
-       struct device_node *np = adev->dev.of_node;
-
-       desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
-       if (!desc)
-               return -ENOMEM;
-
-       drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
-       if (!drvdata)
-               return -ENOMEM;
-
-       if (np) {
-               pdata = of_get_coresight_platform_data(dev, np);
-               if (IS_ERR(pdata))
-                       return PTR_ERR(pdata);
-
-               adev->dev.platform_data = pdata;
-               drvdata->use_cp14 = of_property_read_bool(np, "arm,cp14");
-       }
-
-       drvdata->dev = &adev->dev;
-       dev_set_drvdata(dev, drvdata);
-
-       /* Validity for the resource is already checked by the AMBA core */
-       base = devm_ioremap_resource(dev, res);
-       if (IS_ERR(base))
-               return PTR_ERR(base);
-
-       drvdata->base = base;
-
-       spin_lock_init(&drvdata->spinlock);
-
-       drvdata->clk = adev->pclk;
-       ret = clk_prepare_enable(drvdata->clk);
-       if (ret)
-               return ret;
-
-       drvdata->cpu = pdata ? pdata->cpu : 0;
-
-       get_online_cpus();
-       etmdrvdata[drvdata->cpu] = drvdata;
-
-       if (!smp_call_function_single(drvdata->cpu, etm_os_unlock, drvdata, 1))
-               drvdata->os_unlock = true;
-
-       if (smp_call_function_single(drvdata->cpu,
-                                    etm_init_arch_data,  drvdata, 1))
-               dev_err(dev, "ETM arch init failed\n");
-
-       if (!etm_count++)
-               register_hotcpu_notifier(&etm_cpu_notifier);
-
-       put_online_cpus();
-
-       if (etm_arch_supported(drvdata->arch) == false) {
-               ret = -EINVAL;
-               goto err_arch_supported;
-       }
-       etm_init_default_data(drvdata);
-
-       clk_disable_unprepare(drvdata->clk);
-
-       desc->type = CORESIGHT_DEV_TYPE_SOURCE;
-       desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
-       desc->ops = &etm_cs_ops;
-       desc->pdata = pdata;
-       desc->dev = dev;
-       desc->groups = coresight_etm_groups;
-       drvdata->csdev = coresight_register(desc);
-       if (IS_ERR(drvdata->csdev)) {
-               ret = PTR_ERR(drvdata->csdev);
-               goto err_arch_supported;
-       }
-
-       dev_info(dev, "ETM initialized\n");
-
-       if (boot_enable) {
-               coresight_enable(drvdata->csdev);
-               drvdata->boot_enable = true;
-       }
-
-       return 0;
-
-err_arch_supported:
-       clk_disable_unprepare(drvdata->clk);
-       if (--etm_count == 0)
-               unregister_hotcpu_notifier(&etm_cpu_notifier);
-       return ret;
-}
-
-static int etm_remove(struct amba_device *adev)
-{
-       struct etm_drvdata *drvdata = amba_get_drvdata(adev);
-
-       coresight_unregister(drvdata->csdev);
-       if (--etm_count == 0)
-               unregister_hotcpu_notifier(&etm_cpu_notifier);
-
-       return 0;
-}
-
-static struct amba_id etm_ids[] = {
-       {       /* ETM 3.3 */
-               .id     = 0x0003b921,
-               .mask   = 0x0003ffff,
-       },
-       {       /* ETM 3.5 */
-               .id     = 0x0003b956,
-               .mask   = 0x0003ffff,
-       },
-       {       /* PTM 1.0 */
-               .id     = 0x0003b950,
-               .mask   = 0x0003ffff,
-       },
-       {       /* PTM 1.1 */
-               .id     = 0x0003b95f,
-               .mask   = 0x0003ffff,
-       },
-       { 0, 0},
-};
-
-static struct amba_driver etm_driver = {
-       .drv = {
-               .name   = "coresight-etm3x",
-               .owner  = THIS_MODULE,
-       },
-       .probe          = etm_probe,
-       .remove         = etm_remove,
-       .id_table       = etm_ids,
-};
-
-int __init etm_init(void)
-{
-       return amba_driver_register(&etm_driver);
-}
-module_init(etm_init);
-
-void __exit etm_exit(void)
-{
-       amba_driver_unregister(&etm_driver);
-}
-module_exit(etm_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("CoreSight Program Flow Trace driver");
diff --git a/drivers/coresight/coresight-funnel.c b/drivers/coresight/coresight-funnel.c
deleted file mode 100644 (file)
index 3db36f7..0000000
+++ /dev/null
@@ -1,258 +0,0 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/clk.h>
-#include <linux/coresight.h>
-#include <linux/amba/bus.h>
-
-#include "coresight-priv.h"
-
-#define FUNNEL_FUNCTL          0x000
-#define FUNNEL_PRICTL          0x004
-
-#define FUNNEL_HOLDTIME_MASK   0xf00
-#define FUNNEL_HOLDTIME_SHFT   0x8
-#define FUNNEL_HOLDTIME                (0x7 << FUNNEL_HOLDTIME_SHFT)
-
-/**
- * struct funnel_drvdata - specifics associated to a funnel component
- * @base:      memory mapped base address for this component.
- * @dev:       the device entity associated to this component.
- * @csdev:     component vitals needed by the framework.
- * @clk:       the clock this component is associated to.
- * @priority:  port selection order.
- */
-struct funnel_drvdata {
-       void __iomem            *base;
-       struct device           *dev;
-       struct coresight_device *csdev;
-       struct clk              *clk;
-       unsigned long           priority;
-};
-
-static void funnel_enable_hw(struct funnel_drvdata *drvdata, int port)
-{
-       u32 functl;
-
-       CS_UNLOCK(drvdata->base);
-
-       functl = readl_relaxed(drvdata->base + FUNNEL_FUNCTL);
-       functl &= ~FUNNEL_HOLDTIME_MASK;
-       functl |= FUNNEL_HOLDTIME;
-       functl |= (1 << port);
-       writel_relaxed(functl, drvdata->base + FUNNEL_FUNCTL);
-       writel_relaxed(drvdata->priority, drvdata->base + FUNNEL_PRICTL);
-
-       CS_LOCK(drvdata->base);
-}
-
-static int funnel_enable(struct coresight_device *csdev, int inport,
-                        int outport)
-{
-       struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-       int ret;
-
-       ret = clk_prepare_enable(drvdata->clk);
-       if (ret)
-               return ret;
-
-       funnel_enable_hw(drvdata, inport);
-
-       dev_info(drvdata->dev, "FUNNEL inport %d enabled\n", inport);
-       return 0;
-}
-
-static void funnel_disable_hw(struct funnel_drvdata *drvdata, int inport)
-{
-       u32 functl;
-
-       CS_UNLOCK(drvdata->base);
-
-       functl = readl_relaxed(drvdata->base + FUNNEL_FUNCTL);
-       functl &= ~(1 << inport);
-       writel_relaxed(functl, drvdata->base + FUNNEL_FUNCTL);
-
-       CS_LOCK(drvdata->base);
-}
-
-static void funnel_disable(struct coresight_device *csdev, int inport,
-                          int outport)
-{
-       struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
-       funnel_disable_hw(drvdata, inport);
-
-       clk_disable_unprepare(drvdata->clk);
-
-       dev_info(drvdata->dev, "FUNNEL inport %d disabled\n", inport);
-}
-
-static const struct coresight_ops_link funnel_link_ops = {
-       .enable         = funnel_enable,
-       .disable        = funnel_disable,
-};
-
-static const struct coresight_ops funnel_cs_ops = {
-       .link_ops       = &funnel_link_ops,
-};
-
-static ssize_t priority_show(struct device *dev,
-                            struct device_attribute *attr, char *buf)
-{
-       struct funnel_drvdata *drvdata = dev_get_drvdata(dev->parent);
-       unsigned long val = drvdata->priority;
-
-       return sprintf(buf, "%#lx\n", val);
-}
-
-static ssize_t priority_store(struct device *dev,
-                             struct device_attribute *attr,
-                             const char *buf, size_t size)
-{
-       int ret;
-       unsigned long val;
-       struct funnel_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = kstrtoul(buf, 16, &val);
-       if (ret)
-               return ret;
-
-       drvdata->priority = val;
-       return size;
-}
-static DEVICE_ATTR_RW(priority);
-
-static u32 get_funnel_ctrl_hw(struct funnel_drvdata *drvdata)
-{
-       u32 functl;
-
-       CS_UNLOCK(drvdata->base);
-       functl = readl_relaxed(drvdata->base + FUNNEL_FUNCTL);
-       CS_LOCK(drvdata->base);
-
-       return functl;
-}
-
-static ssize_t funnel_ctrl_show(struct device *dev,
-                            struct device_attribute *attr, char *buf)
-{
-       int ret;
-       u32 val;
-       struct funnel_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = clk_prepare_enable(drvdata->clk);
-       if (ret)
-               return ret;
-
-       val = get_funnel_ctrl_hw(drvdata);
-       clk_disable_unprepare(drvdata->clk);
-
-       return sprintf(buf, "%#x\n", val);
-}
-static DEVICE_ATTR_RO(funnel_ctrl);
-
-static struct attribute *coresight_funnel_attrs[] = {
-       &dev_attr_funnel_ctrl.attr,
-       &dev_attr_priority.attr,
-       NULL,
-};
-ATTRIBUTE_GROUPS(coresight_funnel);
-
-static int funnel_probe(struct amba_device *adev, const struct amba_id *id)
-{
-       void __iomem *base;
-       struct device *dev = &adev->dev;
-       struct coresight_platform_data *pdata = NULL;
-       struct funnel_drvdata *drvdata;
-       struct resource *res = &adev->res;
-       struct coresight_desc *desc;
-       struct device_node *np = adev->dev.of_node;
-
-       if (np) {
-               pdata = of_get_coresight_platform_data(dev, np);
-               if (IS_ERR(pdata))
-                       return PTR_ERR(pdata);
-               adev->dev.platform_data = pdata;
-       }
-
-       drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
-       if (!drvdata)
-               return -ENOMEM;
-
-       drvdata->dev = &adev->dev;
-       dev_set_drvdata(dev, drvdata);
-
-       /* Validity for the resource is already checked by the AMBA core */
-       base = devm_ioremap_resource(dev, res);
-       if (IS_ERR(base))
-               return PTR_ERR(base);
-
-       drvdata->base = base;
-
-       drvdata->clk = adev->pclk;
-
-       desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
-       if (!desc)
-               return -ENOMEM;
-
-       desc->type = CORESIGHT_DEV_TYPE_LINK;
-       desc->subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_MERG;
-       desc->ops = &funnel_cs_ops;
-       desc->pdata = pdata;
-       desc->dev = dev;
-       desc->groups = coresight_funnel_groups;
-       drvdata->csdev = coresight_register(desc);
-       if (IS_ERR(drvdata->csdev))
-               return PTR_ERR(drvdata->csdev);
-
-       dev_info(dev, "FUNNEL initialized\n");
-       return 0;
-}
-
-static int funnel_remove(struct amba_device *adev)
-{
-       struct funnel_drvdata *drvdata = amba_get_drvdata(adev);
-
-       coresight_unregister(drvdata->csdev);
-       return 0;
-}
-
-static struct amba_id funnel_ids[] = {
-       {
-               .id     = 0x0003b908,
-               .mask   = 0x0003ffff,
-       },
-       { 0, 0},
-};
-
-static struct amba_driver funnel_driver = {
-       .drv = {
-               .name   = "coresight-funnel",
-               .owner  = THIS_MODULE,
-       },
-       .probe          = funnel_probe,
-       .remove         = funnel_remove,
-       .id_table       = funnel_ids,
-};
-
-module_amba_driver(funnel_driver);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("CoreSight Funnel driver");
diff --git a/drivers/coresight/coresight-priv.h b/drivers/coresight/coresight-priv.h
deleted file mode 100644 (file)
index 62fcd98..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef _CORESIGHT_PRIV_H
-#define _CORESIGHT_PRIV_H
-
-#include <linux/bitops.h>
-#include <linux/io.h>
-#include <linux/coresight.h>
-
-/*
- * Coresight management registers (0xf00-0xfcc)
- * 0xfa0 - 0xfa4: Management   registers in PFTv1.0
- *               Trace         registers in PFTv1.1
- */
-#define CORESIGHT_ITCTRL       0xf00
-#define CORESIGHT_CLAIMSET     0xfa0
-#define CORESIGHT_CLAIMCLR     0xfa4
-#define CORESIGHT_LAR          0xfb0
-#define CORESIGHT_LSR          0xfb4
-#define CORESIGHT_AUTHSTATUS   0xfb8
-#define CORESIGHT_DEVID                0xfc8
-#define CORESIGHT_DEVTYPE      0xfcc
-
-#define TIMEOUT_US             100
-#define BMVAL(val, lsb, msb)   ((val & GENMASK(msb, lsb)) >> lsb)
-
-static inline void CS_LOCK(void __iomem *addr)
-{
-       do {
-               /* Wait for things to settle */
-               mb();
-               writel_relaxed(0x0, addr + CORESIGHT_LAR);
-       } while (0);
-}
-
-static inline void CS_UNLOCK(void __iomem *addr)
-{
-       do {
-               writel_relaxed(CORESIGHT_UNLOCK, addr + CORESIGHT_LAR);
-               /* Make sure everyone has seen this */
-               mb();
-       } while (0);
-}
-
-#ifdef CONFIG_CORESIGHT_SOURCE_ETM3X
-extern int etm_readl_cp14(u32 off, unsigned int *val);
-extern int etm_writel_cp14(u32 off, u32 val);
-#else
-static inline int etm_readl_cp14(u32 off, unsigned int *val) { return 0; }
-static inline int etm_writel_cp14(u32 off, u32 val) { return 0; }
-#endif
-
-#endif
diff --git a/drivers/coresight/coresight-replicator.c b/drivers/coresight/coresight-replicator.c
deleted file mode 100644 (file)
index cdf0553..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/clk.h>
-#include <linux/of.h>
-#include <linux/coresight.h>
-
-#include "coresight-priv.h"
-
-/**
- * struct replicator_drvdata - specifics associated to a replicator component
- * @dev:       the device entity associated with this component
- * @csdev:     component vitals needed by the framework
- */
-struct replicator_drvdata {
-       struct device           *dev;
-       struct coresight_device *csdev;
-};
-
-static int replicator_enable(struct coresight_device *csdev, int inport,
-                            int outport)
-{
-       struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
-       dev_info(drvdata->dev, "REPLICATOR enabled\n");
-       return 0;
-}
-
-static void replicator_disable(struct coresight_device *csdev, int inport,
-                              int outport)
-{
-       struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
-       dev_info(drvdata->dev, "REPLICATOR disabled\n");
-}
-
-static const struct coresight_ops_link replicator_link_ops = {
-       .enable         = replicator_enable,
-       .disable        = replicator_disable,
-};
-
-static const struct coresight_ops replicator_cs_ops = {
-       .link_ops       = &replicator_link_ops,
-};
-
-static int replicator_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct coresight_platform_data *pdata = NULL;
-       struct replicator_drvdata *drvdata;
-       struct coresight_desc *desc;
-       struct device_node *np = pdev->dev.of_node;
-
-       if (np) {
-               pdata = of_get_coresight_platform_data(dev, np);
-               if (IS_ERR(pdata))
-                       return PTR_ERR(pdata);
-               pdev->dev.platform_data = pdata;
-       }
-
-       drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
-       if (!drvdata)
-               return -ENOMEM;
-
-       drvdata->dev = &pdev->dev;
-       platform_set_drvdata(pdev, drvdata);
-
-       desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
-       if (!desc)
-               return -ENOMEM;
-
-       desc->type = CORESIGHT_DEV_TYPE_LINK;
-       desc->subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_SPLIT;
-       desc->ops = &replicator_cs_ops;
-       desc->pdata = pdev->dev.platform_data;
-       desc->dev = &pdev->dev;
-       drvdata->csdev = coresight_register(desc);
-       if (IS_ERR(drvdata->csdev))
-               return PTR_ERR(drvdata->csdev);
-
-       dev_info(dev, "REPLICATOR initialized\n");
-       return 0;
-}
-
-static int replicator_remove(struct platform_device *pdev)
-{
-       struct replicator_drvdata *drvdata = platform_get_drvdata(pdev);
-
-       coresight_unregister(drvdata->csdev);
-       return 0;
-}
-
-static struct of_device_id replicator_match[] = {
-       {.compatible = "arm,coresight-replicator"},
-       {}
-};
-
-static struct platform_driver replicator_driver = {
-       .probe          = replicator_probe,
-       .remove         = replicator_remove,
-       .driver         = {
-               .name   = "coresight-replicator",
-               .of_match_table = replicator_match,
-       },
-};
-
-static int __init replicator_init(void)
-{
-       return platform_driver_register(&replicator_driver);
-}
-module_init(replicator_init);
-
-static void __exit replicator_exit(void)
-{
-       platform_driver_unregister(&replicator_driver);
-}
-module_exit(replicator_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("CoreSight Replicator driver");
diff --git a/drivers/coresight/coresight-tmc.c b/drivers/coresight/coresight-tmc.c
deleted file mode 100644 (file)
index 3ff232f..0000000
+++ /dev/null
@@ -1,766 +0,0 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/device.h>
-#include <linux/io.h>
-#include <linux/err.h>
-#include <linux/fs.h>
-#include <linux/miscdevice.h>
-#include <linux/uaccess.h>
-#include <linux/slab.h>
-#include <linux/dma-mapping.h>
-#include <linux/spinlock.h>
-#include <linux/clk.h>
-#include <linux/of.h>
-#include <linux/coresight.h>
-#include <linux/amba/bus.h>
-
-#include "coresight-priv.h"
-
-#define TMC_RSZ                        0x004
-#define TMC_STS                        0x00c
-#define TMC_RRD                        0x010
-#define TMC_RRP                        0x014
-#define TMC_RWP                        0x018
-#define TMC_TRG                        0x01c
-#define TMC_CTL                        0x020
-#define TMC_RWD                        0x024
-#define TMC_MODE               0x028
-#define TMC_LBUFLEVEL          0x02c
-#define TMC_CBUFLEVEL          0x030
-#define TMC_BUFWM              0x034
-#define TMC_RRPHI              0x038
-#define TMC_RWPHI              0x03c
-#define TMC_AXICTL             0x110
-#define TMC_DBALO              0x118
-#define TMC_DBAHI              0x11c
-#define TMC_FFSR               0x300
-#define TMC_FFCR               0x304
-#define TMC_PSCR               0x308
-#define TMC_ITMISCOP0          0xee0
-#define TMC_ITTRFLIN           0xee8
-#define TMC_ITATBDATA0         0xeec
-#define TMC_ITATBCTR2          0xef0
-#define TMC_ITATBCTR1          0xef4
-#define TMC_ITATBCTR0          0xef8
-
-/* register description */
-/* TMC_CTL - 0x020 */
-#define TMC_CTL_CAPT_EN                BIT(0)
-/* TMC_STS - 0x00C */
-#define TMC_STS_TRIGGERED      BIT(1)
-/* TMC_AXICTL - 0x110 */
-#define TMC_AXICTL_PROT_CTL_B0 BIT(0)
-#define TMC_AXICTL_PROT_CTL_B1 BIT(1)
-#define TMC_AXICTL_SCT_GAT_MODE        BIT(7)
-#define TMC_AXICTL_WR_BURST_LEN 0xF00
-/* TMC_FFCR - 0x304 */
-#define TMC_FFCR_EN_FMT                BIT(0)
-#define TMC_FFCR_EN_TI         BIT(1)
-#define TMC_FFCR_FON_FLIN      BIT(4)
-#define TMC_FFCR_FON_TRIG_EVT  BIT(5)
-#define TMC_FFCR_FLUSHMAN      BIT(6)
-#define TMC_FFCR_TRIGON_TRIGIN BIT(8)
-#define TMC_FFCR_STOP_ON_FLUSH BIT(12)
-
-#define TMC_STS_TRIGGERED_BIT  2
-#define TMC_FFCR_FLUSHMAN_BIT  6
-
-enum tmc_config_type {
-       TMC_CONFIG_TYPE_ETB,
-       TMC_CONFIG_TYPE_ETR,
-       TMC_CONFIG_TYPE_ETF,
-};
-
-enum tmc_mode {
-       TMC_MODE_CIRCULAR_BUFFER,
-       TMC_MODE_SOFTWARE_FIFO,
-       TMC_MODE_HARDWARE_FIFO,
-};
-
-enum tmc_mem_intf_width {
-       TMC_MEM_INTF_WIDTH_32BITS       = 0x2,
-       TMC_MEM_INTF_WIDTH_64BITS       = 0x3,
-       TMC_MEM_INTF_WIDTH_128BITS      = 0x4,
-       TMC_MEM_INTF_WIDTH_256BITS      = 0x5,
-};
-
-/**
- * struct tmc_drvdata - specifics associated to an TMC component
- * @base:      memory mapped base address for this component.
- * @dev:       the device entity associated to this component.
- * @csdev:     component vitals needed by the framework.
- * @miscdev:   specifics to handle "/dev/xyz.tmc" entry.
- * @clk:       the clock this component is associated to.
- * @spinlock:  only one at a time pls.
- * @read_count:        manages preparation of buffer for reading.
- * @buf:       area of memory where trace data get sent.
- * @paddr:     DMA start location in RAM.
- * @vaddr:     virtual representation of @paddr.
- * @size:      @buf size.
- * @enable:    this TMC is being used.
- * @config_type: TMC variant, must be of type @tmc_config_type.
- * @trigger_cntr: amount of words to store after a trigger.
- */
-struct tmc_drvdata {
-       void __iomem            *base;
-       struct device           *dev;
-       struct coresight_device *csdev;
-       struct miscdevice       miscdev;
-       struct clk              *clk;
-       spinlock_t              spinlock;
-       int                     read_count;
-       bool                    reading;
-       char                    *buf;
-       dma_addr_t              paddr;
-       void __iomem            *vaddr;
-       u32                     size;
-       bool                    enable;
-       enum tmc_config_type    config_type;
-       u32                     trigger_cntr;
-};
-
-static void tmc_wait_for_ready(struct tmc_drvdata *drvdata)
-{
-       /* Ensure formatter, unformatter and hardware fifo are empty */
-       if (coresight_timeout(drvdata->base,
-                             TMC_STS, TMC_STS_TRIGGERED_BIT, 1)) {
-               dev_err(drvdata->dev,
-                       "timeout observed when probing at offset %#x\n",
-                       TMC_STS);
-       }
-}
-
-static void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
-{
-       u32 ffcr;
-
-       ffcr = readl_relaxed(drvdata->base + TMC_FFCR);
-       ffcr |= TMC_FFCR_STOP_ON_FLUSH;
-       writel_relaxed(ffcr, drvdata->base + TMC_FFCR);
-       ffcr |= TMC_FFCR_FLUSHMAN;
-       writel_relaxed(ffcr, drvdata->base + TMC_FFCR);
-       /* Ensure flush completes */
-       if (coresight_timeout(drvdata->base,
-                             TMC_FFCR, TMC_FFCR_FLUSHMAN_BIT, 0)) {
-               dev_err(drvdata->dev,
-                       "timeout observed when probing at offset %#x\n",
-                       TMC_FFCR);
-       }
-
-       tmc_wait_for_ready(drvdata);
-}
-
-static void tmc_enable_hw(struct tmc_drvdata *drvdata)
-{
-       writel_relaxed(TMC_CTL_CAPT_EN, drvdata->base + TMC_CTL);
-}
-
-static void tmc_disable_hw(struct tmc_drvdata *drvdata)
-{
-       writel_relaxed(0x0, drvdata->base + TMC_CTL);
-}
-
-static void tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
-{
-       /* Zero out the memory to help with debug */
-       memset(drvdata->buf, 0, drvdata->size);
-
-       CS_UNLOCK(drvdata->base);
-
-       writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
-       writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
-                      TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
-                      TMC_FFCR_TRIGON_TRIGIN,
-                      drvdata->base + TMC_FFCR);
-
-       writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG);
-       tmc_enable_hw(drvdata);
-
-       CS_LOCK(drvdata->base);
-}
-
-static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
-{
-       u32 axictl;
-
-       /* Zero out the memory to help with debug */
-       memset(drvdata->vaddr, 0, drvdata->size);
-
-       CS_UNLOCK(drvdata->base);
-
-       writel_relaxed(drvdata->size / 4, drvdata->base + TMC_RSZ);
-       writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
-
-       axictl = readl_relaxed(drvdata->base + TMC_AXICTL);
-       axictl |= TMC_AXICTL_WR_BURST_LEN;
-       writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
-       axictl &= ~TMC_AXICTL_SCT_GAT_MODE;
-       writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
-       axictl = (axictl &
-                 ~(TMC_AXICTL_PROT_CTL_B0 | TMC_AXICTL_PROT_CTL_B1)) |
-                 TMC_AXICTL_PROT_CTL_B1;
-       writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
-
-       writel_relaxed(drvdata->paddr, drvdata->base + TMC_DBALO);
-       writel_relaxed(0x0, drvdata->base + TMC_DBAHI);
-       writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
-                      TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
-                      TMC_FFCR_TRIGON_TRIGIN,
-                      drvdata->base + TMC_FFCR);
-       writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG);
-       tmc_enable_hw(drvdata);
-
-       CS_LOCK(drvdata->base);
-}
-
-static void tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
-{
-       CS_UNLOCK(drvdata->base);
-
-       writel_relaxed(TMC_MODE_HARDWARE_FIFO, drvdata->base + TMC_MODE);
-       writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI,
-                      drvdata->base + TMC_FFCR);
-       writel_relaxed(0x0, drvdata->base + TMC_BUFWM);
-       tmc_enable_hw(drvdata);
-
-       CS_LOCK(drvdata->base);
-}
-
-static int tmc_enable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
-{
-       int ret;
-       unsigned long flags;
-
-       ret = clk_prepare_enable(drvdata->clk);
-       if (ret)
-               return ret;
-
-       spin_lock_irqsave(&drvdata->spinlock, flags);
-       if (drvdata->reading) {
-               spin_unlock_irqrestore(&drvdata->spinlock, flags);
-               clk_disable_unprepare(drvdata->clk);
-               return -EBUSY;
-       }
-
-       if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
-               tmc_etb_enable_hw(drvdata);
-       } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
-               tmc_etr_enable_hw(drvdata);
-       } else {
-               if (mode == TMC_MODE_CIRCULAR_BUFFER)
-                       tmc_etb_enable_hw(drvdata);
-               else
-                       tmc_etf_enable_hw(drvdata);
-       }
-       drvdata->enable = true;
-       spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
-       dev_info(drvdata->dev, "TMC enabled\n");
-       return 0;
-}
-
-static int tmc_enable_sink(struct coresight_device *csdev)
-{
-       struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
-       return tmc_enable(drvdata, TMC_MODE_CIRCULAR_BUFFER);
-}
-
-static int tmc_enable_link(struct coresight_device *csdev, int inport,
-                          int outport)
-{
-       struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
-       return tmc_enable(drvdata, TMC_MODE_HARDWARE_FIFO);
-}
-
-static void tmc_etb_dump_hw(struct tmc_drvdata *drvdata)
-{
-       enum tmc_mem_intf_width memwidth;
-       u8 memwords;
-       char *bufp;
-       u32 read_data;
-       int i;
-
-       memwidth = BMVAL(readl_relaxed(drvdata->base + CORESIGHT_DEVID), 8, 10);
-       if (memwidth == TMC_MEM_INTF_WIDTH_32BITS)
-               memwords = 1;
-       else if (memwidth == TMC_MEM_INTF_WIDTH_64BITS)
-               memwords = 2;
-       else if (memwidth == TMC_MEM_INTF_WIDTH_128BITS)
-               memwords = 4;
-       else
-               memwords = 8;
-
-       bufp = drvdata->buf;
-       while (1) {
-               for (i = 0; i < memwords; i++) {
-                       read_data = readl_relaxed(drvdata->base + TMC_RRD);
-                       if (read_data == 0xFFFFFFFF)
-                               return;
-                       memcpy(bufp, &read_data, 4);
-                       bufp += 4;
-               }
-       }
-}
-
-static void tmc_etb_disable_hw(struct tmc_drvdata *drvdata)
-{
-       CS_UNLOCK(drvdata->base);
-
-       tmc_flush_and_stop(drvdata);
-       tmc_etb_dump_hw(drvdata);
-       tmc_disable_hw(drvdata);
-
-       CS_LOCK(drvdata->base);
-}
-
-static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata)
-{
-       u32 rwp, val;
-
-       rwp = readl_relaxed(drvdata->base + TMC_RWP);
-       val = readl_relaxed(drvdata->base + TMC_STS);
-
-       /* How much memory do we still have */
-       if (val & BIT(0))
-               drvdata->buf = drvdata->vaddr + rwp - drvdata->paddr;
-       else
-               drvdata->buf = drvdata->vaddr;
-}
-
-static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
-{
-       CS_UNLOCK(drvdata->base);
-
-       tmc_flush_and_stop(drvdata);
-       tmc_etr_dump_hw(drvdata);
-       tmc_disable_hw(drvdata);
-
-       CS_LOCK(drvdata->base);
-}
-
-static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata)
-{
-       CS_UNLOCK(drvdata->base);
-
-       tmc_flush_and_stop(drvdata);
-       tmc_disable_hw(drvdata);
-
-       CS_LOCK(drvdata->base);
-}
-
-static void tmc_disable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&drvdata->spinlock, flags);
-       if (drvdata->reading)
-               goto out;
-
-       if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
-               tmc_etb_disable_hw(drvdata);
-       } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
-               tmc_etr_disable_hw(drvdata);
-       } else {
-               if (mode == TMC_MODE_CIRCULAR_BUFFER)
-                       tmc_etb_disable_hw(drvdata);
-               else
-                       tmc_etf_disable_hw(drvdata);
-       }
-out:
-       drvdata->enable = false;
-       spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
-       clk_disable_unprepare(drvdata->clk);
-
-       dev_info(drvdata->dev, "TMC disabled\n");
-}
-
-static void tmc_disable_sink(struct coresight_device *csdev)
-{
-       struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
-       tmc_disable(drvdata, TMC_MODE_CIRCULAR_BUFFER);
-}
-
-static void tmc_disable_link(struct coresight_device *csdev, int inport,
-                            int outport)
-{
-       struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
-       tmc_disable(drvdata, TMC_MODE_HARDWARE_FIFO);
-}
-
-static const struct coresight_ops_sink tmc_sink_ops = {
-       .enable         = tmc_enable_sink,
-       .disable        = tmc_disable_sink,
-};
-
-static const struct coresight_ops_link tmc_link_ops = {
-       .enable         = tmc_enable_link,
-       .disable        = tmc_disable_link,
-};
-
-static const struct coresight_ops tmc_etb_cs_ops = {
-       .sink_ops       = &tmc_sink_ops,
-};
-
-static const struct coresight_ops tmc_etr_cs_ops = {
-       .sink_ops       = &tmc_sink_ops,
-};
-
-static const struct coresight_ops tmc_etf_cs_ops = {
-       .sink_ops       = &tmc_sink_ops,
-       .link_ops       = &tmc_link_ops,
-};
-
-static int tmc_read_prepare(struct tmc_drvdata *drvdata)
-{
-       int ret;
-       unsigned long flags;
-       enum tmc_mode mode;
-
-       spin_lock_irqsave(&drvdata->spinlock, flags);
-       if (!drvdata->enable)
-               goto out;
-
-       if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
-               tmc_etb_disable_hw(drvdata);
-       } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
-               tmc_etr_disable_hw(drvdata);
-       } else {
-               mode = readl_relaxed(drvdata->base + TMC_MODE);
-               if (mode == TMC_MODE_CIRCULAR_BUFFER) {
-                       tmc_etb_disable_hw(drvdata);
-               } else {
-                       ret = -ENODEV;
-                       goto err;
-               }
-       }
-out:
-       drvdata->reading = true;
-       spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
-       dev_info(drvdata->dev, "TMC read start\n");
-       return 0;
-err:
-       spin_unlock_irqrestore(&drvdata->spinlock, flags);
-       return ret;
-}
-
-static void tmc_read_unprepare(struct tmc_drvdata *drvdata)
-{
-       unsigned long flags;
-       enum tmc_mode mode;
-
-       spin_lock_irqsave(&drvdata->spinlock, flags);
-       if (!drvdata->enable)
-               goto out;
-
-       if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
-               tmc_etb_enable_hw(drvdata);
-       } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
-               tmc_etr_enable_hw(drvdata);
-       } else {
-               mode = readl_relaxed(drvdata->base + TMC_MODE);
-               if (mode == TMC_MODE_CIRCULAR_BUFFER)
-                       tmc_etb_enable_hw(drvdata);
-       }
-out:
-       drvdata->reading = false;
-       spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
-       dev_info(drvdata->dev, "TMC read end\n");
-}
-
-static int tmc_open(struct inode *inode, struct file *file)
-{
-       struct tmc_drvdata *drvdata = container_of(file->private_data,
-                                                  struct tmc_drvdata, miscdev);
-       int ret = 0;
-
-       if (drvdata->read_count++)
-               goto out;
-
-       ret = tmc_read_prepare(drvdata);
-       if (ret)
-               return ret;
-out:
-       nonseekable_open(inode, file);
-
-       dev_dbg(drvdata->dev, "%s: successfully opened\n", __func__);
-       return 0;
-}
-
-static ssize_t tmc_read(struct file *file, char __user *data, size_t len,
-                       loff_t *ppos)
-{
-       struct tmc_drvdata *drvdata = container_of(file->private_data,
-                                                  struct tmc_drvdata, miscdev);
-       char *bufp = drvdata->buf + *ppos;
-
-       if (*ppos + len > drvdata->size)
-               len = drvdata->size - *ppos;
-
-       if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
-               if (bufp == (char *)(drvdata->vaddr + drvdata->size))
-                       bufp = drvdata->vaddr;
-               else if (bufp > (char *)(drvdata->vaddr + drvdata->size))
-                       bufp -= drvdata->size;
-               if ((bufp + len) > (char *)(drvdata->vaddr + drvdata->size))
-                       len = (char *)(drvdata->vaddr + drvdata->size) - bufp;
-       }
-
-       if (copy_to_user(data, bufp, len)) {
-               dev_dbg(drvdata->dev, "%s: copy_to_user failed\n", __func__);
-               return -EFAULT;
-       }
-
-       *ppos += len;
-
-       dev_dbg(drvdata->dev, "%s: %d bytes copied, %d bytes left\n",
-               __func__, len, (int) (drvdata->size - *ppos));
-       return len;
-}
-
-static int tmc_release(struct inode *inode, struct file *file)
-{
-       struct tmc_drvdata *drvdata = container_of(file->private_data,
-                                                  struct tmc_drvdata, miscdev);
-
-       if (--drvdata->read_count) {
-               if (drvdata->read_count < 0) {
-                       dev_err(drvdata->dev, "mismatched close\n");
-                       drvdata->read_count = 0;
-               }
-               goto out;
-       }
-
-       tmc_read_unprepare(drvdata);
-out:
-       dev_dbg(drvdata->dev, "%s: released\n", __func__);
-       return 0;
-}
-
-static const struct file_operations tmc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = tmc_open,
-       .read           = tmc_read,
-       .release        = tmc_release,
-       .llseek         = no_llseek,
-};
-
-static ssize_t trigger_cntr_show(struct device *dev,
-                           struct device_attribute *attr, char *buf)
-{
-       struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
-       unsigned long val = drvdata->trigger_cntr;
-
-       return sprintf(buf, "%#lx\n", val);
-}
-
-static ssize_t trigger_cntr_store(struct device *dev,
-                            struct device_attribute *attr,
-                            const char *buf, size_t size)
-{
-       int ret;
-       unsigned long val;
-       struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-       ret = kstrtoul(buf, 16, &val);
-       if (ret)
-               return ret;
-
-       drvdata->trigger_cntr = val;
-       return size;
-}
-static DEVICE_ATTR_RW(trigger_cntr);
-
-static struct attribute *coresight_etb_attrs[] = {
-       &dev_attr_trigger_cntr.attr,
-       NULL,
-};
-ATTRIBUTE_GROUPS(coresight_etb);
-
-static struct attribute *coresight_etr_attrs[] = {
-       &dev_attr_trigger_cntr.attr,
-       NULL,
-};
-ATTRIBUTE_GROUPS(coresight_etr);
-
-static struct attribute *coresight_etf_attrs[] = {
-       &dev_attr_trigger_cntr.attr,
-       NULL,
-};
-ATTRIBUTE_GROUPS(coresight_etf);
-
-static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
-{
-       int ret = 0;
-       u32 devid;
-       void __iomem *base;
-       struct device *dev = &adev->dev;
-       struct coresight_platform_data *pdata = NULL;
-       struct tmc_drvdata *drvdata;
-       struct resource *res = &adev->res;
-       struct coresight_desc *desc;
-       struct device_node *np = adev->dev.of_node;
-
-       if (np) {
-               pdata = of_get_coresight_platform_data(dev, np);
-               if (IS_ERR(pdata))
-                       return PTR_ERR(pdata);
-               adev->dev.platform_data = pdata;
-       }
-
-       drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
-       if (!drvdata)
-               return -ENOMEM;
-
-       drvdata->dev = &adev->dev;
-       dev_set_drvdata(dev, drvdata);
-
-       /* Validity for the resource is already checked by the AMBA core */
-       base = devm_ioremap_resource(dev, res);
-       if (IS_ERR(base))
-               return PTR_ERR(base);
-
-       drvdata->base = base;
-
-       spin_lock_init(&drvdata->spinlock);
-
-       drvdata->clk = adev->pclk;
-       ret = clk_prepare_enable(drvdata->clk);
-       if (ret)
-               return ret;
-
-       devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
-       drvdata->config_type = BMVAL(devid, 6, 7);
-
-       if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
-               if (np)
-                       ret = of_property_read_u32(np,
-                                                  "arm,buffer-size",
-                                                  &drvdata->size);
-               if (ret)
-                       drvdata->size = SZ_1M;
-       } else {
-               drvdata->size = readl_relaxed(drvdata->base + TMC_RSZ) * 4;
-       }
-
-       clk_disable_unprepare(drvdata->clk);
-
-       if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
-               drvdata->vaddr = dma_alloc_coherent(dev, drvdata->size,
-                                               &drvdata->paddr, GFP_KERNEL);
-               if (!drvdata->vaddr)
-                       return -ENOMEM;
-
-               memset(drvdata->vaddr, 0, drvdata->size);
-               drvdata->buf = drvdata->vaddr;
-       } else {
-               drvdata->buf = devm_kzalloc(dev, drvdata->size, GFP_KERNEL);
-               if (!drvdata->buf)
-                       return -ENOMEM;
-       }
-
-       desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
-       if (!desc) {
-               ret = -ENOMEM;
-               goto err_devm_kzalloc;
-       }
-
-       desc->pdata = pdata;
-       desc->dev = dev;
-       desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
-
-       if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
-               desc->type = CORESIGHT_DEV_TYPE_SINK;
-               desc->ops = &tmc_etb_cs_ops;
-               desc->groups = coresight_etb_groups;
-       } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
-               desc->type = CORESIGHT_DEV_TYPE_SINK;
-               desc->ops = &tmc_etr_cs_ops;
-               desc->groups = coresight_etr_groups;
-       } else {
-               desc->type = CORESIGHT_DEV_TYPE_LINKSINK;
-               desc->subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_FIFO;
-               desc->ops = &tmc_etf_cs_ops;
-               desc->groups = coresight_etf_groups;
-       }
-
-       drvdata->csdev = coresight_register(desc);
-       if (IS_ERR(drvdata->csdev)) {
-               ret = PTR_ERR(drvdata->csdev);
-               goto err_devm_kzalloc;
-       }
-
-       drvdata->miscdev.name = pdata->name;
-       drvdata->miscdev.minor = MISC_DYNAMIC_MINOR;
-       drvdata->miscdev.fops = &tmc_fops;
-       ret = misc_register(&drvdata->miscdev);
-       if (ret)
-               goto err_misc_register;
-
-       dev_info(dev, "TMC initialized\n");
-       return 0;
-
-err_misc_register:
-       coresight_unregister(drvdata->csdev);
-err_devm_kzalloc:
-       if (drvdata->config_type == TMC_CONFIG_TYPE_ETR)
-               dma_free_coherent(dev, drvdata->size,
-                               &drvdata->paddr, GFP_KERNEL);
-       return ret;
-}
-
-static int tmc_remove(struct amba_device *adev)
-{
-       struct tmc_drvdata *drvdata = amba_get_drvdata(adev);
-
-       misc_deregister(&drvdata->miscdev);
-       coresight_unregister(drvdata->csdev);
-       if (drvdata->config_type == TMC_CONFIG_TYPE_ETR)
-               dma_free_coherent(drvdata->dev, drvdata->size,
-                                 &drvdata->paddr, GFP_KERNEL);
-
-       return 0;
-}
-
-static struct amba_id tmc_ids[] = {
-       {
-               .id     = 0x0003b961,
-               .mask   = 0x0003ffff,
-       },
-       { 0, 0},
-};
-
-static struct amba_driver tmc_driver = {
-       .drv = {
-               .name   = "coresight-tmc",
-               .owner  = THIS_MODULE,
-       },
-       .probe          = tmc_probe,
-       .remove         = tmc_remove,
-       .id_table       = tmc_ids,
-};
-
-module_amba_driver(tmc_driver);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("CoreSight Trace Memory Controller driver");
diff --git a/drivers/coresight/coresight-tpiu.c b/drivers/coresight/coresight-tpiu.c
deleted file mode 100644 (file)
index 3b33af2..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/io.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/clk.h>
-#include <linux/coresight.h>
-#include <linux/amba/bus.h>
-
-#include "coresight-priv.h"
-
-#define TPIU_SUPP_PORTSZ       0x000
-#define TPIU_CURR_PORTSZ       0x004
-#define TPIU_SUPP_TRIGMODES    0x100
-#define TPIU_TRIG_CNTRVAL      0x104
-#define TPIU_TRIG_MULT         0x108
-#define TPIU_SUPP_TESTPATM     0x200
-#define TPIU_CURR_TESTPATM     0x204
-#define TPIU_TEST_PATREPCNTR   0x208
-#define TPIU_FFSR              0x300
-#define TPIU_FFCR              0x304
-#define TPIU_FSYNC_CNTR                0x308
-#define TPIU_EXTCTL_INPORT     0x400
-#define TPIU_EXTCTL_OUTPORT    0x404
-#define TPIU_ITTRFLINACK       0xee4
-#define TPIU_ITTRFLIN          0xee8
-#define TPIU_ITATBDATA0                0xeec
-#define TPIU_ITATBCTR2         0xef0
-#define TPIU_ITATBCTR1         0xef4
-#define TPIU_ITATBCTR0         0xef8
-
-/** register definition **/
-/* FFCR - 0x304 */
-#define FFCR_FON_MAN           BIT(6)
-
-/**
- * @base:      memory mapped base address for this component.
- * @dev:       the device entity associated to this component.
- * @csdev:     component vitals needed by the framework.
- * @clk:       the clock this component is associated to.
- */
-struct tpiu_drvdata {
-       void __iomem            *base;
-       struct device           *dev;
-       struct coresight_device *csdev;
-       struct clk              *clk;
-};
-
-static void tpiu_enable_hw(struct tpiu_drvdata *drvdata)
-{
-       CS_UNLOCK(drvdata->base);
-
-       /* TODO: fill this up */
-
-       CS_LOCK(drvdata->base);
-}
-
-static int tpiu_enable(struct coresight_device *csdev)
-{
-       struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-       int ret;
-
-       ret = clk_prepare_enable(drvdata->clk);
-       if (ret)
-               return ret;
-
-       tpiu_enable_hw(drvdata);
-
-       dev_info(drvdata->dev, "TPIU enabled\n");
-       return 0;
-}
-
-static void tpiu_disable_hw(struct tpiu_drvdata *drvdata)
-{
-       CS_UNLOCK(drvdata->base);
-
-       /* Clear formatter controle reg. */
-       writel_relaxed(0x0, drvdata->base + TPIU_FFCR);
-       /* Generate manual flush */
-       writel_relaxed(FFCR_FON_MAN, drvdata->base + TPIU_FFCR);
-
-       CS_LOCK(drvdata->base);
-}
-
-static void tpiu_disable(struct coresight_device *csdev)
-{
-       struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
-       tpiu_disable_hw(drvdata);
-
-       clk_disable_unprepare(drvdata->clk);
-
-       dev_info(drvdata->dev, "TPIU disabled\n");
-}
-
-static const struct coresight_ops_sink tpiu_sink_ops = {
-       .enable         = tpiu_enable,
-       .disable        = tpiu_disable,
-};
-
-static const struct coresight_ops tpiu_cs_ops = {
-       .sink_ops       = &tpiu_sink_ops,
-};
-
-static int tpiu_probe(struct amba_device *adev, const struct amba_id *id)
-{
-       int ret;
-       void __iomem *base;
-       struct device *dev = &adev->dev;
-       struct coresight_platform_data *pdata = NULL;
-       struct tpiu_drvdata *drvdata;
-       struct resource *res = &adev->res;
-       struct coresight_desc *desc;
-       struct device_node *np = adev->dev.of_node;
-
-       if (np) {
-               pdata = of_get_coresight_platform_data(dev, np);
-               if (IS_ERR(pdata))
-                       return PTR_ERR(pdata);
-               adev->dev.platform_data = pdata;
-       }
-
-       drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
-       if (!drvdata)
-               return -ENOMEM;
-
-       drvdata->dev = &adev->dev;
-       dev_set_drvdata(dev, drvdata);
-
-       /* Validity for the resource is already checked by the AMBA core */
-       base = devm_ioremap_resource(dev, res);
-       if (IS_ERR(base))
-               return PTR_ERR(base);
-
-       drvdata->base = base;
-
-       drvdata->clk = adev->pclk;
-       ret = clk_prepare_enable(drvdata->clk);
-       if (ret)
-               return ret;
-
-       /* Disable tpiu to support older devices */
-       tpiu_disable_hw(drvdata);
-
-       clk_disable_unprepare(drvdata->clk);
-
-       desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
-       if (!desc)
-               return -ENOMEM;
-
-       desc->type = CORESIGHT_DEV_TYPE_SINK;
-       desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_PORT;
-       desc->ops = &tpiu_cs_ops;
-       desc->pdata = pdata;
-       desc->dev = dev;
-       drvdata->csdev = coresight_register(desc);
-       if (IS_ERR(drvdata->csdev))
-               return PTR_ERR(drvdata->csdev);
-
-       dev_info(dev, "TPIU initialized\n");
-       return 0;
-}
-
-static int tpiu_remove(struct amba_device *adev)
-{
-       struct tpiu_drvdata *drvdata = amba_get_drvdata(adev);
-
-       coresight_unregister(drvdata->csdev);
-       return 0;
-}
-
-static struct amba_id tpiu_ids[] = {
-       {
-               .id     = 0x0003b912,
-               .mask   = 0x0003ffff,
-       },
-       { 0, 0},
-};
-
-static struct amba_driver tpiu_driver = {
-       .drv = {
-               .name   = "coresight-tpiu",
-               .owner  = THIS_MODULE,
-       },
-       .probe          = tpiu_probe,
-       .remove         = tpiu_remove,
-       .id_table       = tpiu_ids,
-};
-
-module_amba_driver(tpiu_driver);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("CoreSight Trace Port Interface Unit driver");
diff --git a/drivers/coresight/coresight.c b/drivers/coresight/coresight.c
deleted file mode 100644 (file)
index c5def93..0000000
+++ /dev/null
@@ -1,718 +0,0 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/device.h>
-#include <linux/io.h>
-#include <linux/err.h>
-#include <linux/export.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-#include <linux/clk.h>
-#include <linux/coresight.h>
-#include <linux/of_platform.h>
-#include <linux/delay.h>
-
-#include "coresight-priv.h"
-
-static DEFINE_MUTEX(coresight_mutex);
-
-static int coresight_id_match(struct device *dev, void *data)
-{
-       int trace_id, i_trace_id;
-       struct coresight_device *csdev, *i_csdev;
-
-       csdev = data;
-       i_csdev = to_coresight_device(dev);
-
-       /*
-        * No need to care about oneself and components that are not
-        * sources or not enabled
-        */
-       if (i_csdev == csdev || !i_csdev->enable ||
-           i_csdev->type != CORESIGHT_DEV_TYPE_SOURCE)
-               return 0;
-
-       /* Get the source ID for both compoment */
-       trace_id = source_ops(csdev)->trace_id(csdev);
-       i_trace_id = source_ops(i_csdev)->trace_id(i_csdev);
-
-       /* All you need is one */
-       if (trace_id == i_trace_id)
-               return 1;
-
-       return 0;
-}
-
-static int coresight_source_is_unique(struct coresight_device *csdev)
-{
-       int trace_id = source_ops(csdev)->trace_id(csdev);
-
-       /* this shouldn't happen */
-       if (trace_id < 0)
-               return 0;
-
-       return !bus_for_each_dev(&coresight_bustype, NULL,
-                                csdev, coresight_id_match);
-}
-
-static int coresight_find_link_inport(struct coresight_device *csdev)
-{
-       int i;
-       struct coresight_device *parent;
-       struct coresight_connection *conn;
-
-       parent = container_of(csdev->path_link.next,
-                             struct coresight_device, path_link);
-
-       for (i = 0; i < parent->nr_outport; i++) {
-               conn = &parent->conns[i];
-               if (conn->child_dev == csdev)
-                       return conn->child_port;
-       }
-
-       dev_err(&csdev->dev, "couldn't find inport, parent: %s, child: %s\n",
-               dev_name(&parent->dev), dev_name(&csdev->dev));
-
-       return 0;
-}
-
-static int coresight_find_link_outport(struct coresight_device *csdev)
-{
-       int i;
-       struct coresight_device *child;
-       struct coresight_connection *conn;
-
-       child = container_of(csdev->path_link.prev,
-                            struct coresight_device, path_link);
-
-       for (i = 0; i < csdev->nr_outport; i++) {
-               conn = &csdev->conns[i];
-               if (conn->child_dev == child)
-                       return conn->outport;
-       }
-
-       dev_err(&csdev->dev, "couldn't find outport, parent: %s, child: %s\n",
-               dev_name(&csdev->dev), dev_name(&child->dev));
-
-       return 0;
-}
-
-static int coresight_enable_sink(struct coresight_device *csdev)
-{
-       int ret;
-
-       if (!csdev->enable) {
-               if (sink_ops(csdev)->enable) {
-                       ret = sink_ops(csdev)->enable(csdev);
-                       if (ret)
-                               return ret;
-               }
-               csdev->enable = true;
-       }
-
-       atomic_inc(csdev->refcnt);
-
-       return 0;
-}
-
-static void coresight_disable_sink(struct coresight_device *csdev)
-{
-       if (atomic_dec_return(csdev->refcnt) == 0) {
-               if (sink_ops(csdev)->disable) {
-                       sink_ops(csdev)->disable(csdev);
-                       csdev->enable = false;
-               }
-       }
-}
-
-static int coresight_enable_link(struct coresight_device *csdev)
-{
-       int ret;
-       int link_subtype;
-       int refport, inport, outport;
-
-       inport = coresight_find_link_inport(csdev);
-       outport = coresight_find_link_outport(csdev);
-       link_subtype = csdev->subtype.link_subtype;
-
-       if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG)
-               refport = inport;
-       else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT)
-               refport = outport;
-       else
-               refport = 0;
-
-       if (atomic_inc_return(&csdev->refcnt[refport]) == 1) {
-               if (link_ops(csdev)->enable) {
-                       ret = link_ops(csdev)->enable(csdev, inport, outport);
-                       if (ret)
-                               return ret;
-               }
-       }
-
-       csdev->enable = true;
-
-       return 0;
-}
-
-static void coresight_disable_link(struct coresight_device *csdev)
-{
-       int i, nr_conns;
-       int link_subtype;
-       int refport, inport, outport;
-
-       inport = coresight_find_link_inport(csdev);
-       outport = coresight_find_link_outport(csdev);
-       link_subtype = csdev->subtype.link_subtype;
-
-       if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) {
-               refport = inport;
-               nr_conns = csdev->nr_inport;
-       } else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT) {
-               refport = outport;
-               nr_conns = csdev->nr_outport;
-       } else {
-               refport = 0;
-               nr_conns = 1;
-       }
-
-       if (atomic_dec_return(&csdev->refcnt[refport]) == 0) {
-               if (link_ops(csdev)->disable)
-                       link_ops(csdev)->disable(csdev, inport, outport);
-       }
-
-       for (i = 0; i < nr_conns; i++)
-               if (atomic_read(&csdev->refcnt[i]) != 0)
-                       return;
-
-       csdev->enable = false;
-}
-
-static int coresight_enable_source(struct coresight_device *csdev)
-{
-       int ret;
-
-       if (!coresight_source_is_unique(csdev)) {
-               dev_warn(&csdev->dev, "traceID %d not unique\n",
-                        source_ops(csdev)->trace_id(csdev));
-               return -EINVAL;
-       }
-
-       if (!csdev->enable) {
-               if (source_ops(csdev)->enable) {
-                       ret = source_ops(csdev)->enable(csdev);
-                       if (ret)
-                               return ret;
-               }
-               csdev->enable = true;
-       }
-
-       atomic_inc(csdev->refcnt);
-
-       return 0;
-}
-
-static void coresight_disable_source(struct coresight_device *csdev)
-{
-       if (atomic_dec_return(csdev->refcnt) == 0) {
-               if (source_ops(csdev)->disable) {
-                       source_ops(csdev)->disable(csdev);
-                       csdev->enable = false;
-               }
-       }
-}
-
-static int coresight_enable_path(struct list_head *path)
-{
-       int ret = 0;
-       struct coresight_device *cd;
-
-       list_for_each_entry(cd, path, path_link) {
-               if (cd == list_first_entry(path, struct coresight_device,
-                                          path_link)) {
-                       ret = coresight_enable_sink(cd);
-               } else if (list_is_last(&cd->path_link, path)) {
-                       /*
-                        * Don't enable the source just yet - this needs to
-                        * happen at the very end when all links and sink
-                        * along the path have been configured properly.
-                        */
-                       ;
-               } else {
-                       ret = coresight_enable_link(cd);
-               }
-               if (ret)
-                       goto err;
-       }
-
-       return 0;
-err:
-       list_for_each_entry_continue_reverse(cd, path, path_link) {
-               if (cd == list_first_entry(path, struct coresight_device,
-                                          path_link)) {
-                       coresight_disable_sink(cd);
-               } else if (list_is_last(&cd->path_link, path)) {
-                       ;
-               } else {
-                       coresight_disable_link(cd);
-               }
-       }
-
-       return ret;
-}
-
-static int coresight_disable_path(struct list_head *path)
-{
-       struct coresight_device *cd;
-
-       list_for_each_entry_reverse(cd, path, path_link) {
-               if (cd == list_first_entry(path, struct coresight_device,
-                                          path_link)) {
-                       coresight_disable_sink(cd);
-               } else if (list_is_last(&cd->path_link, path)) {
-                       /*
-                        * The source has already been stopped, no need
-                        * to do it again here.
-                        */
-                       ;
-               } else {
-                       coresight_disable_link(cd);
-               }
-       }
-
-       return 0;
-}
-
-static int coresight_build_paths(struct coresight_device *csdev,
-                                struct list_head *path,
-                                bool enable)
-{
-       int i, ret = -EINVAL;
-       struct coresight_connection *conn;
-
-       list_add(&csdev->path_link, path);
-
-       if (csdev->type == CORESIGHT_DEV_TYPE_SINK && csdev->activated) {
-               if (enable)
-                       ret = coresight_enable_path(path);
-               else
-                       ret = coresight_disable_path(path);
-       } else {
-               for (i = 0; i < csdev->nr_outport; i++) {
-                       conn = &csdev->conns[i];
-                       if (coresight_build_paths(conn->child_dev,
-                                                   path, enable) == 0)
-                               ret = 0;
-               }
-       }
-
-       if (list_first_entry(path, struct coresight_device, path_link) != csdev)
-               dev_err(&csdev->dev, "wrong device in %s\n", __func__);
-
-       list_del(&csdev->path_link);
-
-       return ret;
-}
-
-int coresight_enable(struct coresight_device *csdev)
-{
-       int ret = 0;
-       LIST_HEAD(path);
-
-       mutex_lock(&coresight_mutex);
-       if (csdev->type != CORESIGHT_DEV_TYPE_SOURCE) {
-               ret = -EINVAL;
-               dev_err(&csdev->dev, "wrong device type in %s\n", __func__);
-               goto out;
-       }
-       if (csdev->enable)
-               goto out;
-
-       if (coresight_build_paths(csdev, &path, true)) {
-               dev_err(&csdev->dev, "building path(s) failed\n");
-               goto out;
-       }
-
-       if (coresight_enable_source(csdev))
-               dev_err(&csdev->dev, "source enable failed\n");
-out:
-       mutex_unlock(&coresight_mutex);
-       return ret;
-}
-EXPORT_SYMBOL_GPL(coresight_enable);
-
-void coresight_disable(struct coresight_device *csdev)
-{
-       LIST_HEAD(path);
-
-       mutex_lock(&coresight_mutex);
-       if (csdev->type != CORESIGHT_DEV_TYPE_SOURCE) {
-               dev_err(&csdev->dev, "wrong device type in %s\n", __func__);
-               goto out;
-       }
-       if (!csdev->enable)
-               goto out;
-
-       coresight_disable_source(csdev);
-       if (coresight_build_paths(csdev, &path, false))
-               dev_err(&csdev->dev, "releasing path(s) failed\n");
-
-out:
-       mutex_unlock(&coresight_mutex);
-}
-EXPORT_SYMBOL_GPL(coresight_disable);
-
-static ssize_t enable_sink_show(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-       struct coresight_device *csdev = to_coresight_device(dev);
-
-       return scnprintf(buf, PAGE_SIZE, "%u\n", (unsigned)csdev->activated);
-}
-
-static ssize_t enable_sink_store(struct device *dev,
-                                struct device_attribute *attr,
-                                const char *buf, size_t size)
-{
-       int ret;
-       unsigned long val;
-       struct coresight_device *csdev = to_coresight_device(dev);
-
-       ret = kstrtoul(buf, 10, &val);
-       if (ret)
-               return ret;
-
-       if (val)
-               csdev->activated = true;
-       else
-               csdev->activated = false;
-
-       return size;
-
-}
-static DEVICE_ATTR_RW(enable_sink);
-
-static ssize_t enable_source_show(struct device *dev,
-                                 struct device_attribute *attr, char *buf)
-{
-       struct coresight_device *csdev = to_coresight_device(dev);
-
-       return scnprintf(buf, PAGE_SIZE, "%u\n", (unsigned)csdev->enable);
-}
-
-static ssize_t enable_source_store(struct device *dev,
-                                  struct device_attribute *attr,
-                                  const char *buf, size_t size)
-{
-       int ret = 0;
-       unsigned long val;
-       struct coresight_device *csdev = to_coresight_device(dev);
-
-       ret = kstrtoul(buf, 10, &val);
-       if (ret)
-               return ret;
-
-       if (val) {
-               ret = coresight_enable(csdev);
-               if (ret)
-                       return ret;
-       } else {
-               coresight_disable(csdev);
-       }
-
-       return size;
-}
-static DEVICE_ATTR_RW(enable_source);
-
-static struct attribute *coresight_sink_attrs[] = {
-       &dev_attr_enable_sink.attr,
-       NULL,
-};
-ATTRIBUTE_GROUPS(coresight_sink);
-
-static struct attribute *coresight_source_attrs[] = {
-       &dev_attr_enable_source.attr,
-       NULL,
-};
-ATTRIBUTE_GROUPS(coresight_source);
-
-static struct device_type coresight_dev_type[] = {
-       {
-               .name = "none",
-       },
-       {
-               .name = "sink",
-               .groups = coresight_sink_groups,
-       },
-       {
-               .name = "link",
-       },
-       {
-               .name = "linksink",
-               .groups = coresight_sink_groups,
-       },
-       {
-               .name = "source",
-               .groups = coresight_source_groups,
-       },
-};
-
-static void coresight_device_release(struct device *dev)
-{
-       struct coresight_device *csdev = to_coresight_device(dev);
-
-       kfree(csdev);
-}
-
-static int coresight_orphan_match(struct device *dev, void *data)
-{
-       int i;
-       bool still_orphan = false;
-       struct coresight_device *csdev, *i_csdev;
-       struct coresight_connection *conn;
-
-       csdev = data;
-       i_csdev = to_coresight_device(dev);
-
-       /* No need to check oneself */
-       if (csdev == i_csdev)
-               return 0;
-
-       /* Move on to another component if no connection is orphan */
-       if (!i_csdev->orphan)
-               return 0;
-       /*
-        * Circle throuch all the connection of that component.  If we find
-        * an orphan connection whose name matches @csdev, link it.
-        */
-       for (i = 0; i < i_csdev->nr_outport; i++) {
-               conn = &i_csdev->conns[i];
-
-               /* We have found at least one orphan connection */
-               if (conn->child_dev == NULL) {
-                       /* Does it match this newly added device? */
-                       if (!strcmp(dev_name(&csdev->dev), conn->child_name)) {
-                               conn->child_dev = csdev;
-                       } else {
-                               /* This component still has an orphan */
-                               still_orphan = true;
-                       }
-               }
-       }
-
-       i_csdev->orphan = still_orphan;
-
-       /*
-        * Returning '0' ensures that all known component on the
-        * bus will be checked.
-        */
-       return 0;
-}
-
-static void coresight_fixup_orphan_conns(struct coresight_device *csdev)
-{
-       /*
-        * No need to check for a return value as orphan connection(s)
-        * are hooked-up with each newly added component.
-        */
-       bus_for_each_dev(&coresight_bustype, NULL,
-                                csdev, coresight_orphan_match);
-}
-
-
-static int coresight_name_match(struct device *dev, void *data)
-{
-       char *to_match;
-       struct coresight_device *i_csdev;
-
-       to_match = data;
-       i_csdev = to_coresight_device(dev);
-
-       if (!strcmp(to_match, dev_name(&i_csdev->dev)))
-               return 1;
-
-       return 0;
-}
-
-static void coresight_fixup_device_conns(struct coresight_device *csdev)
-{
-       int i;
-       struct device *dev = NULL;
-       struct coresight_connection *conn;
-
-       for (i = 0; i < csdev->nr_outport; i++) {
-               conn = &csdev->conns[i];
-               dev = bus_find_device(&coresight_bustype, NULL,
-                                     (void *)conn->child_name,
-                                     coresight_name_match);
-
-               if (dev) {
-                       conn->child_dev = to_coresight_device(dev);
-               } else {
-                       csdev->orphan = true;
-                       conn->child_dev = NULL;
-               }
-       }
-}
-
-/**
- * coresight_timeout - loop until a bit has changed to a specific state.
- * @addr: base address of the area of interest.
- * @offset: address of a register, starting from @addr.
- * @position: the position of the bit of interest.
- * @value: the value the bit should have.
- *
- * Return: 0 as soon as the bit has taken the desired state or -EAGAIN if
- * TIMEOUT_US has elapsed, which ever happens first.
- */
-
-int coresight_timeout(void __iomem *addr, u32 offset, int position, int value)
-{
-       int i;
-       u32 val;
-
-       for (i = TIMEOUT_US; i > 0; i--) {
-               val = __raw_readl(addr + offset);
-               /* waiting on the bit to go from 0 to 1 */
-               if (value) {
-                       if (val & BIT(position))
-                               return 0;
-               /* waiting on the bit to go from 1 to 0 */
-               } else {
-                       if (!(val & BIT(position)))
-                               return 0;
-               }
-
-               /*
-                * Delay is arbitrary - the specification doesn't say how long
-                * we are expected to wait.  Extra check required to make sure
-                * we don't wait needlessly on the last iteration.
-                */
-               if (i - 1)
-                       udelay(1);
-       }
-
-       return -EAGAIN;
-}
-
-struct bus_type coresight_bustype = {
-       .name   = "coresight",
-};
-
-static int __init coresight_init(void)
-{
-       return bus_register(&coresight_bustype);
-}
-postcore_initcall(coresight_init);
-
-struct coresight_device *coresight_register(struct coresight_desc *desc)
-{
-       int i;
-       int ret;
-       int link_subtype;
-       int nr_refcnts = 1;
-       atomic_t *refcnts = NULL;
-       struct coresight_device *csdev;
-       struct coresight_connection *conns;
-
-       csdev = kzalloc(sizeof(*csdev), GFP_KERNEL);
-       if (!csdev) {
-               ret = -ENOMEM;
-               goto err_kzalloc_csdev;
-       }
-
-       if (desc->type == CORESIGHT_DEV_TYPE_LINK ||
-           desc->type == CORESIGHT_DEV_TYPE_LINKSINK) {
-               link_subtype = desc->subtype.link_subtype;
-
-               if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG)
-                       nr_refcnts = desc->pdata->nr_inport;
-               else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT)
-                       nr_refcnts = desc->pdata->nr_outport;
-       }
-
-       refcnts = kcalloc(nr_refcnts, sizeof(*refcnts), GFP_KERNEL);
-       if (!refcnts) {
-               ret = -ENOMEM;
-               goto err_kzalloc_refcnts;
-       }
-
-       csdev->refcnt = refcnts;
-
-       csdev->nr_inport = desc->pdata->nr_inport;
-       csdev->nr_outport = desc->pdata->nr_outport;
-       conns = kcalloc(csdev->nr_outport, sizeof(*conns), GFP_KERNEL);
-       if (!conns) {
-               ret = -ENOMEM;
-               goto err_kzalloc_conns;
-       }
-
-       for (i = 0; i < csdev->nr_outport; i++) {
-               conns[i].outport = desc->pdata->outports[i];
-               conns[i].child_name = desc->pdata->child_names[i];
-               conns[i].child_port = desc->pdata->child_ports[i];
-       }
-
-       csdev->conns = conns;
-
-       csdev->type = desc->type;
-       csdev->subtype = desc->subtype;
-       csdev->ops = desc->ops;
-       csdev->orphan = false;
-
-       csdev->dev.type = &coresight_dev_type[desc->type];
-       csdev->dev.groups = desc->groups;
-       csdev->dev.parent = desc->dev;
-       csdev->dev.release = coresight_device_release;
-       csdev->dev.bus = &coresight_bustype;
-       dev_set_name(&csdev->dev, "%s", desc->pdata->name);
-
-       ret = device_register(&csdev->dev);
-       if (ret)
-               goto err_device_register;
-
-       mutex_lock(&coresight_mutex);
-
-       coresight_fixup_device_conns(csdev);
-       coresight_fixup_orphan_conns(csdev);
-
-       mutex_unlock(&coresight_mutex);
-
-       return csdev;
-
-err_device_register:
-       kfree(conns);
-err_kzalloc_conns:
-       kfree(refcnts);
-err_kzalloc_refcnts:
-       kfree(csdev);
-err_kzalloc_csdev:
-       return ERR_PTR(ret);
-}
-EXPORT_SYMBOL_GPL(coresight_register);
-
-void coresight_unregister(struct coresight_device *csdev)
-{
-       mutex_lock(&coresight_mutex);
-
-       kfree(csdev->conns);
-       device_unregister(&csdev->dev);
-
-       mutex_unlock(&coresight_mutex);
-}
-EXPORT_SYMBOL_GPL(coresight_unregister);
-
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/coresight/of_coresight.c b/drivers/coresight/of_coresight.c
deleted file mode 100644 (file)
index 6f75e9d..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/clk.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_graph.h>
-#include <linux/of_platform.h>
-#include <linux/platform_device.h>
-#include <linux/amba/bus.h>
-#include <linux/coresight.h>
-#include <asm/smp_plat.h>
-
-
-static int of_dev_node_match(struct device *dev, void *data)
-{
-       return dev->of_node == data;
-}
-
-static struct device *
-of_coresight_get_endpoint_device(struct device_node *endpoint)
-{
-       struct device *dev = NULL;
-
-       /*
-        * If we have a non-configuable replicator, it will be found on the
-        * platform bus.
-        */
-       dev = bus_find_device(&platform_bus_type, NULL,
-                             endpoint, of_dev_node_match);
-       if (dev)
-               return dev;
-
-       /*
-        * We have a configurable component - circle through the AMBA bus
-        * looking for the device that matches the endpoint node.
-        */
-       return bus_find_device(&amba_bustype, NULL,
-                              endpoint, of_dev_node_match);
-}
-
-static void of_coresight_get_ports(struct device_node *node,
-                                  int *nr_inport, int *nr_outport)
-{
-       struct device_node *ep = NULL;
-       int in = 0, out = 0;
-
-       do {
-               ep = of_graph_get_next_endpoint(node, ep);
-               if (!ep)
-                       break;
-
-               if (of_property_read_bool(ep, "slave-mode"))
-                       in++;
-               else
-                       out++;
-
-       } while (ep);
-
-       *nr_inport = in;
-       *nr_outport = out;
-}
-
-static int of_coresight_alloc_memory(struct device *dev,
-                       struct coresight_platform_data *pdata)
-{
-       /* List of output port on this component */
-       pdata->outports = devm_kzalloc(dev, pdata->nr_outport *
-                                      sizeof(*pdata->outports),
-                                      GFP_KERNEL);
-       if (!pdata->outports)
-               return -ENOMEM;
-
-       /* Children connected to this component via @outports */
-        pdata->child_names = devm_kzalloc(dev, pdata->nr_outport *
-                                         sizeof(*pdata->child_names),
-                                         GFP_KERNEL);
-       if (!pdata->child_names)
-               return -ENOMEM;
-
-       /* Port number on the child this component is connected to */
-       pdata->child_ports = devm_kzalloc(dev, pdata->nr_outport *
-                                         sizeof(*pdata->child_ports),
-                                         GFP_KERNEL);
-       if (!pdata->child_ports)
-               return -ENOMEM;
-
-       return 0;
-}
-
-struct coresight_platform_data *of_get_coresight_platform_data(
-                               struct device *dev, struct device_node *node)
-{
-       int i = 0, ret = 0;
-       struct coresight_platform_data *pdata;
-       struct of_endpoint endpoint, rendpoint;
-       struct device *rdev;
-       struct device_node *dn;
-       struct device_node *ep = NULL;
-       struct device_node *rparent = NULL;
-       struct device_node *rport = NULL;
-
-       pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
-       if (!pdata)
-               return ERR_PTR(-ENOMEM);
-
-       /* Use device name as sysfs handle */
-       pdata->name = dev_name(dev);
-
-       /* Get the number of input and output port for this component */
-       of_coresight_get_ports(node, &pdata->nr_inport, &pdata->nr_outport);
-
-       if (pdata->nr_outport) {
-               ret = of_coresight_alloc_memory(dev, pdata);
-               if (ret)
-                       return ERR_PTR(ret);
-
-               /* Iterate through each port to discover topology */
-               do {
-                       /* Get a handle on a port */
-                       ep = of_graph_get_next_endpoint(node, ep);
-                       if (!ep)
-                               break;
-
-                       /*
-                        * No need to deal with input ports, processing for as
-                        * processing for output ports will deal with them.
-                        */
-                       if (of_find_property(ep, "slave-mode", NULL))
-                               continue;
-
-                       /* Get a handle on the local endpoint */
-                       ret = of_graph_parse_endpoint(ep, &endpoint);
-
-                       if (ret)
-                               continue;
-
-                       /* The local out port number */
-                       pdata->outports[i] = endpoint.id;
-
-                       /*
-                        * Get a handle on the remote port and parent
-                        * attached to it.
-                        */
-                       rparent = of_graph_get_remote_port_parent(ep);
-                       rport = of_graph_get_remote_port(ep);
-
-                       if (!rparent || !rport)
-                               continue;
-
-                       if (of_graph_parse_endpoint(rport, &rendpoint))
-                               continue;
-
-                       rdev = of_coresight_get_endpoint_device(rparent);
-                       if (!rdev)
-                               continue;
-
-                       pdata->child_names[i] = dev_name(rdev);
-                       pdata->child_ports[i] = rendpoint.id;
-
-                       i++;
-               } while (ep);
-       }
-
-       /* Affinity defaults to CPU0 */
-       pdata->cpu = 0;
-       dn = of_parse_phandle(node, "cpu", 0);
-       if (dn) {
-               const u32 *cell;
-               int len, index;
-               u64 hwid;
-
-               cell = of_get_property(dn, "reg", &len);
-               if (cell) {
-                       hwid = of_read_number(cell, of_n_addr_cells(dn));
-                       index = get_logical_index(hwid);
-                       if (index != -EINVAL)
-                               pdata->cpu = index;
-               }
-       }
-
-       return pdata;
-}
-EXPORT_SYMBOL_GPL(of_get_coresight_platform_data);
index c5b81beccc8e31e2d7f66a1580e4f206c0cd7297..6414661ac1c46a2ccdbaa2408e2491ac93e4dc46 100644 (file)
@@ -31,6 +31,7 @@
 #include <asm/div64.h>
 #include <asm/msr.h>
 #include <asm/cpu_device_id.h>
+#include <asm/cpufeature.h>
 
 #define BYT_RATIOS             0x66a
 #define BYT_VIDS               0x66b
@@ -649,7 +650,7 @@ static struct cpu_defaults byt_params = {
        .pid_policy = {
                .sample_rate_ms = 10,
                .deadband = 0,
-               .setpoint = 97,
+               .setpoint = 60,
                .p_gain_pct = 14,
                .d_gain_pct = 0,
                .i_gain_pct = 4,
@@ -1200,8 +1201,7 @@ static int __init intel_pstate_init(void)
 {
        int cpu, rc = 0;
        const struct x86_cpu_id *id;
-       struct cpu_defaults *cpu_info;
-       struct cpuinfo_x86 *c = &boot_cpu_data;
+       struct cpu_defaults *cpu_def;
 
        if (no_load)
                return -ENODEV;
@@ -1217,10 +1217,10 @@ static int __init intel_pstate_init(void)
        if (intel_pstate_platform_pwr_mgmt_exists())
                return -ENODEV;
 
-       cpu_info = (struct cpu_defaults *)id->driver_data;
+       cpu_def = (struct cpu_defaults *)id->driver_data;
 
-       copy_pid_params(&cpu_info->pid_policy);
-       copy_cpu_funcs(&cpu_info->funcs);
+       copy_pid_params(&cpu_def->pid_policy);
+       copy_cpu_funcs(&cpu_def->funcs);
 
        if (intel_pstate_msrs_not_valid())
                return -ENODEV;
@@ -1231,7 +1231,7 @@ static int __init intel_pstate_init(void)
        if (!all_cpu_data)
                return -ENOMEM;
 
-       if (cpu_has(c,X86_FEATURE_HWP) && !no_hwp)
+       if (static_cpu_has_safe(X86_FEATURE_HWP) && !no_hwp)
                intel_pstate_hwp_enable();
 
        if (!hwp_active && hwp_only)
index 0c06ea2f50bb906fe44727a534924371b2917c0e..b5f0a9cc8185c593688a9b9f75b0ec6547800da3 100644 (file)
@@ -116,7 +116,8 @@ static int exynos_cpuidle_probe(struct platform_device *pdev)
 {
        int ret;
 
-       if (of_machine_is_compatible("samsung,exynos4210")) {
+       if (IS_ENABLED(CONFIG_SMP) &&
+           of_machine_is_compatible("samsung,exynos4210")) {
                exynos_cpuidle_pdata = pdev->dev.platform_data;
 
                ret = cpuidle_register(&exynos_coupled_idle_driver,
index 7a73a279e179a52b9ea209e00b3f61f797c4d4cb..61c417b9e53f8795175b29d71dfd201f15be151c 100644 (file)
@@ -158,9 +158,18 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv,
        int entered_state;
 
        struct cpuidle_state *target_state = &drv->states[index];
+       bool broadcast = !!(target_state->flags & CPUIDLE_FLAG_TIMER_STOP);
        ktime_t time_start, time_end;
        s64 diff;
 
+       /*
+        * Tell the time framework to switch to a broadcast timer because our
+        * local timer will be shut down.  If a local timer is used from another
+        * CPU as a broadcast timer, this call may fail if it is not available.
+        */
+       if (broadcast && tick_broadcast_enter())
+               return -EBUSY;
+
        trace_cpu_idle_rcuidle(index, dev->cpu);
        time_start = ktime_get();
 
@@ -169,6 +178,13 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv,
        time_end = ktime_get();
        trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu);
 
+       if (broadcast) {
+               if (WARN_ON_ONCE(!irqs_disabled()))
+                       local_irq_disable();
+
+               tick_broadcast_exit();
+       }
+
        if (!cpuidle_state_is_coupled(dev, drv, entered_state))
                local_irq_enable();
 
index 800bf41718e185e8337bce952e4f1783412f8741..033c0c86f6ec051af426b970825f84146223f840 100644 (file)
@@ -446,8 +446,9 @@ config CRYPTO_DEV_VMX
 source "drivers/crypto/vmx/Kconfig"
 
 config CRYPTO_DEV_IMGTEC_HASH
-       depends on MIPS || COMPILE_TEST
        tristate "Imagination Technologies hardware hash accelerator"
+       depends on MIPS || COMPILE_TEST
+       depends on HAS_DMA
        select CRYPTO_ALGAPI
        select CRYPTO_MD5
        select CRYPTO_SHA1
index 5be225c2ba98d5ea11760217d9afdfa5240215d3..c5a9138a6a8d69508c2a062a48baf359379928ef 100644 (file)
@@ -265,43 +265,40 @@ static inline int is_dma_buf_file(struct file *file)
 }
 
 /**
- * dma_buf_export_named - Creates a new dma_buf, and associates an anon file
+ * dma_buf_export - Creates a new dma_buf, and associates an anon file
  * with this buffer, so it can be exported.
  * Also connect the allocator specific data and ops to the buffer.
  * Additionally, provide a name string for exporter; useful in debugging.
  *
- * @priv:      [in]    Attach private data of allocator to this buffer
- * @ops:       [in]    Attach allocator-defined dma buf ops to the new buffer.
- * @size:      [in]    Size of the buffer
- * @flags:     [in]    mode flags for the file.
- * @exp_name:  [in]    name of the exporting module - useful for debugging.
- * @resv:      [in]    reservation-object, NULL to allocate default one.
+ * @exp_info:  [in]    holds all the export related information provided
+ *                     by the exporter. see struct dma_buf_export_info
+ *                     for further details.
  *
  * Returns, on success, a newly created dma_buf object, which wraps the
  * supplied private data and operations for dma_buf_ops. On either missing
  * ops, or error in allocating struct dma_buf, will return negative error.
  *
  */
-struct dma_buf *dma_buf_export_named(void *priv, const struct dma_buf_ops *ops,
-                               size_t size, int flags, const char *exp_name,
-                               struct reservation_object *resv)
+struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
 {
        struct dma_buf *dmabuf;
+       struct reservation_object *resv = exp_info->resv;
        struct file *file;
        size_t alloc_size = sizeof(struct dma_buf);
-       if (!resv)
+       if (!exp_info->resv)
                alloc_size += sizeof(struct reservation_object);
        else
                /* prevent &dma_buf[1] == dma_buf->resv */
                alloc_size += 1;
 
-       if (WARN_ON(!priv || !ops
-                         || !ops->map_dma_buf
-                         || !ops->unmap_dma_buf
-                         || !ops->release
-                         || !ops->kmap_atomic
-                         || !ops->kmap
-                         || !ops->mmap)) {
+       if (WARN_ON(!exp_info->priv
+                         || !exp_info->ops
+                         || !exp_info->ops->map_dma_buf
+                         || !exp_info->ops->unmap_dma_buf
+                         || !exp_info->ops->release
+                         || !exp_info->ops->kmap_atomic
+                         || !exp_info->ops->kmap
+                         || !exp_info->ops->mmap)) {
                return ERR_PTR(-EINVAL);
        }
 
@@ -309,10 +306,10 @@ struct dma_buf *dma_buf_export_named(void *priv, const struct dma_buf_ops *ops,
        if (dmabuf == NULL)
                return ERR_PTR(-ENOMEM);
 
-       dmabuf->priv = priv;
-       dmabuf->ops = ops;
-       dmabuf->size = size;
-       dmabuf->exp_name = exp_name;
+       dmabuf->priv = exp_info->priv;
+       dmabuf->ops = exp_info->ops;
+       dmabuf->size = exp_info->size;
+       dmabuf->exp_name = exp_info->exp_name;
        init_waitqueue_head(&dmabuf->poll);
        dmabuf->cb_excl.poll = dmabuf->cb_shared.poll = &dmabuf->poll;
        dmabuf->cb_excl.active = dmabuf->cb_shared.active = 0;
@@ -323,7 +320,8 @@ struct dma_buf *dma_buf_export_named(void *priv, const struct dma_buf_ops *ops,
        }
        dmabuf->resv = resv;
 
-       file = anon_inode_getfile("dmabuf", &dma_buf_fops, dmabuf, flags);
+       file = anon_inode_getfile("dmabuf", &dma_buf_fops, dmabuf,
+                                       exp_info->flags);
        if (IS_ERR(file)) {
                kfree(dmabuf);
                return ERR_CAST(file);
@@ -341,8 +339,7 @@ struct dma_buf *dma_buf_export_named(void *priv, const struct dma_buf_ops *ops,
 
        return dmabuf;
 }
-EXPORT_SYMBOL_GPL(dma_buf_export_named);
-
+EXPORT_SYMBOL_GPL(dma_buf_export);
 
 /**
  * dma_buf_fd - returns a file descriptor for the given dma_buf
index 942ca541dcbdc293e7a3dc11ef494584503f4a4e..bda2cb06dc7a450c6e58e0145edba08acbc6f376 100644 (file)
@@ -112,6 +112,19 @@ config FSL_DMA
          EloPlus is on mpc85xx and mpc86xx and Pxxx parts, and the Elo3 is on
          some Txxx and Bxxx parts.
 
+config FSL_RAID
+        tristate "Freescale RAID engine Support"
+        depends on FSL_SOC && !ASYNC_TX_ENABLE_CHANNEL_SWITCH
+        select DMA_ENGINE
+        select DMA_ENGINE_RAID
+        ---help---
+          Enable support for Freescale RAID Engine. RAID Engine is
+          available on some QorIQ SoCs (like P5020/P5040). It has
+          the capability to offload memcpy, xor and pq computation
+         for raid5/6.
+
+source "drivers/dma/hsu/Kconfig"
+
 config MPC512X_DMA
        tristate "Freescale MPC512x built-in DMA engine support"
        depends on PPC_MPC512x || PPC_MPC831x
@@ -345,6 +358,16 @@ config DMA_JZ4740
        select DMA_ENGINE
        select DMA_VIRTUAL_CHANNELS
 
+config DMA_JZ4780
+       tristate "JZ4780 DMA support"
+       depends on MACH_JZ4780
+       select DMA_ENGINE
+       select DMA_VIRTUAL_CHANNELS
+       help
+         This selects support for the DMA controller in Ingenic JZ4780 SoCs.
+         If you have a board based on such a SoC and wish to use DMA for
+         devices which can use the DMA controller, say Y or M here.
+
 config K3_DMA
        tristate "Hisilicon K3 DMA support"
        depends on ARCH_HI3xxx
@@ -412,6 +435,15 @@ config IMG_MDC_DMA
        help
          Enable support for the IMG multi-threaded DMA controller (MDC).
 
+config XGENE_DMA
+       tristate "APM X-Gene DMA support"
+       depends on ARCH_XGENE || COMPILE_TEST
+       select DMA_ENGINE
+       select DMA_ENGINE_RAID
+       select ASYNC_TX_ENABLE_CHANNEL_SWITCH
+       help
+         Enable support for the APM X-Gene SoC DMA engine.
+
 config DMA_ENGINE
        bool
 
index 539d4825bd766ed956629e0b1d0aa4e9b91acf25..69f77d5ba53bb00ede8ea1ea0ed4a003e90d7f19 100644 (file)
@@ -10,6 +10,7 @@ obj-$(CONFIG_DMATEST) += dmatest.o
 obj-$(CONFIG_INTEL_IOATDMA) += ioat/
 obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
 obj-$(CONFIG_FSL_DMA) += fsldma.o
+obj-$(CONFIG_HSU_DMA) += hsu/
 obj-$(CONFIG_MPC512X_DMA) += mpc512x_dma.o
 obj-$(CONFIG_PPC_BESTCOMM) += bestcomm/
 obj-$(CONFIG_MV_XOR) += mv_xor.o
@@ -40,9 +41,11 @@ obj-$(CONFIG_DMA_OMAP) += omap-dma.o
 obj-$(CONFIG_DMA_BCM2835) += bcm2835-dma.o
 obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o
 obj-$(CONFIG_DMA_JZ4740) += dma-jz4740.o
+obj-$(CONFIG_DMA_JZ4780) += dma-jz4780.o
 obj-$(CONFIG_TI_CPPI41) += cppi41.o
 obj-$(CONFIG_K3_DMA) += k3dma.o
 obj-$(CONFIG_MOXART_DMA) += moxart-dma.o
+obj-$(CONFIG_FSL_RAID) += fsl_raid.o
 obj-$(CONFIG_FSL_EDMA) += fsl-edma.o
 obj-$(CONFIG_QCOM_BAM_DMA) += qcom_bam_dma.o
 obj-y += xilinx/
@@ -50,3 +53,4 @@ obj-$(CONFIG_INTEL_MIC_X100_DMA) += mic_x100_dma.o
 obj-$(CONFIG_NBPFAXI_DMA) += nbpfaxi.o
 obj-$(CONFIG_DMA_SUN6I) += sun6i-dma.o
 obj-$(CONFIG_IMG_MDC_DMA) += img-mdc-dma.o
+obj-$(CONFIG_XGENE_DMA) += xgene-dma.o
index 83aa55d6fa5d65e6243abc13e29c1d4766768eeb..49d396ec06e58f7f5e1a530fdf30b29f3e91808c 100644 (file)
  * 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.
- *
  * The full GNU General Public License is in this distribution in the file
  * called COPYING.
  *
@@ -1195,11 +1191,6 @@ static void pl08x_free_txd_list(struct pl08x_driver_data *pl08x,
 /*
  * The DMA ENGINE API
  */
-static int pl08x_alloc_chan_resources(struct dma_chan *chan)
-{
-       return 0;
-}
-
 static void pl08x_free_chan_resources(struct dma_chan *chan)
 {
        /* Ensure all queued descriptors are freed */
@@ -2066,7 +2057,6 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
        /* Initialize memcpy engine */
        dma_cap_set(DMA_MEMCPY, pl08x->memcpy.cap_mask);
        pl08x->memcpy.dev = &adev->dev;
-       pl08x->memcpy.device_alloc_chan_resources = pl08x_alloc_chan_resources;
        pl08x->memcpy.device_free_chan_resources = pl08x_free_chan_resources;
        pl08x->memcpy.device_prep_dma_memcpy = pl08x_prep_dma_memcpy;
        pl08x->memcpy.device_prep_dma_interrupt = pl08x_prep_dma_interrupt;
@@ -2085,7 +2075,6 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
        dma_cap_set(DMA_SLAVE, pl08x->slave.cap_mask);
        dma_cap_set(DMA_CYCLIC, pl08x->slave.cap_mask);
        pl08x->slave.dev = &adev->dev;
-       pl08x->slave.device_alloc_chan_resources = pl08x_alloc_chan_resources;
        pl08x->slave.device_free_chan_resources = pl08x_free_chan_resources;
        pl08x->slave.device_prep_dma_interrupt = pl08x_prep_dma_interrupt;
        pl08x->slave.device_tx_status = pl08x_dma_tx_status;
index 0b4fc6fb48ce7c5cec62d9a1ef4291e0b175cfaf..57b2141ddddc1abca862197b78f8bd2e1cb51f57 100644 (file)
@@ -65,6 +65,21 @@ static void atc_issue_pending(struct dma_chan *chan);
 
 /*----------------------------------------------------------------------*/
 
+static inline unsigned int atc_get_xfer_width(dma_addr_t src, dma_addr_t dst,
+                                               size_t len)
+{
+       unsigned int width;
+
+       if (!((src | dst  | len) & 3))
+               width = 2;
+       else if (!((src | dst | len) & 1))
+               width = 1;
+       else
+               width = 0;
+
+       return width;
+}
+
 static struct at_desc *atc_first_active(struct at_dma_chan *atchan)
 {
        return list_first_entry(&atchan->active_list,
@@ -659,16 +674,10 @@ atc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
         * We can be a lot more clever here, but this should take care
         * of the most common optimization.
         */
-       if (!((src | dest  | len) & 3)) {
-               ctrla = ATC_SRC_WIDTH_WORD | ATC_DST_WIDTH_WORD;
-               src_width = dst_width = 2;
-       } else if (!((src | dest | len) & 1)) {
-               ctrla = ATC_SRC_WIDTH_HALFWORD | ATC_DST_WIDTH_HALFWORD;
-               src_width = dst_width = 1;
-       } else {
-               ctrla = ATC_SRC_WIDTH_BYTE | ATC_DST_WIDTH_BYTE;
-               src_width = dst_width = 0;
-       }
+       src_width = dst_width = atc_get_xfer_width(src, dest, len);
+
+       ctrla = ATC_SRC_WIDTH(src_width) |
+               ATC_DST_WIDTH(dst_width);
 
        for (offset = 0; offset < len; offset += xfer_count << src_width) {
                xfer_count = min_t(size_t, (len - offset) >> src_width,
@@ -861,6 +870,144 @@ err:
        return NULL;
 }
 
+/**
+ * atc_prep_dma_sg - prepare memory to memory scather-gather operation
+ * @chan: the channel to prepare operation on
+ * @dst_sg: destination scatterlist
+ * @dst_nents: number of destination scatterlist entries
+ * @src_sg: source scatterlist
+ * @src_nents: number of source scatterlist entries
+ * @flags: tx descriptor status flags
+ */
+static struct dma_async_tx_descriptor *
+atc_prep_dma_sg(struct dma_chan *chan,
+               struct scatterlist *dst_sg, unsigned int dst_nents,
+               struct scatterlist *src_sg, unsigned int src_nents,
+               unsigned long flags)
+{
+       struct at_dma_chan      *atchan = to_at_dma_chan(chan);
+       struct at_desc          *desc = NULL;
+       struct at_desc          *first = NULL;
+       struct at_desc          *prev = NULL;
+       unsigned int            src_width;
+       unsigned int            dst_width;
+       size_t                  xfer_count;
+       u32                     ctrla;
+       u32                     ctrlb;
+       size_t                  dst_len = 0, src_len = 0;
+       dma_addr_t              dst = 0, src = 0;
+       size_t                  len = 0, total_len = 0;
+
+       if (unlikely(dst_nents == 0 || src_nents == 0))
+               return NULL;
+
+       if (unlikely(dst_sg == NULL || src_sg == NULL))
+               return NULL;
+
+       ctrlb =   ATC_DEFAULT_CTRLB | ATC_IEN
+               | ATC_SRC_ADDR_MODE_INCR
+               | ATC_DST_ADDR_MODE_INCR
+               | ATC_FC_MEM2MEM;
+
+       /*
+        * loop until there is either no more source or no more destination
+        * scatterlist entry
+        */
+       while (true) {
+
+               /* prepare the next transfer */
+               if (dst_len == 0) {
+
+                       /* no more destination scatterlist entries */
+                       if (!dst_sg || !dst_nents)
+                               break;
+
+                       dst = sg_dma_address(dst_sg);
+                       dst_len = sg_dma_len(dst_sg);
+
+                       dst_sg = sg_next(dst_sg);
+                       dst_nents--;
+               }
+
+               if (src_len == 0) {
+
+                       /* no more source scatterlist entries */
+                       if (!src_sg || !src_nents)
+                               break;
+
+                       src = sg_dma_address(src_sg);
+                       src_len = sg_dma_len(src_sg);
+
+                       src_sg = sg_next(src_sg);
+                       src_nents--;
+               }
+
+               len = min_t(size_t, src_len, dst_len);
+               if (len == 0)
+                       continue;
+
+               /* take care for the alignment */
+               src_width = dst_width = atc_get_xfer_width(src, dst, len);
+
+               ctrla = ATC_SRC_WIDTH(src_width) |
+                       ATC_DST_WIDTH(dst_width);
+
+               /*
+                * The number of transfers to set up refer to the source width
+                * that depends on the alignment.
+                */
+               xfer_count = len >> src_width;
+               if (xfer_count > ATC_BTSIZE_MAX) {
+                       xfer_count = ATC_BTSIZE_MAX;
+                       len = ATC_BTSIZE_MAX << src_width;
+               }
+
+               /* create the transfer */
+               desc = atc_desc_get(atchan);
+               if (!desc)
+                       goto err_desc_get;
+
+               desc->lli.saddr = src;
+               desc->lli.daddr = dst;
+               desc->lli.ctrla = ctrla | xfer_count;
+               desc->lli.ctrlb = ctrlb;
+
+               desc->txd.cookie = 0;
+               desc->len = len;
+
+               /*
+                * Although we only need the transfer width for the first and
+                * the last descriptor, its easier to set it to all descriptors.
+                */
+               desc->tx_width = src_width;
+
+               atc_desc_chain(&first, &prev, desc);
+
+               /* update the lengths and addresses for the next loop cycle */
+               dst_len -= len;
+               src_len -= len;
+               dst += len;
+               src += len;
+
+               total_len += len;
+       }
+
+       /* First descriptor of the chain embedds additional information */
+       first->txd.cookie = -EBUSY;
+       first->total_len = total_len;
+
+       /* set end-of-link to the last link descriptor of list*/
+       set_desc_eol(desc);
+
+       first->txd.flags = flags; /* client is in control of this ack */
+
+       return &first->txd;
+
+err_desc_get:
+       atc_desc_put(atchan, first);
+       return NULL;
+}
+
 /**
  * atc_dma_cyclic_check_values
  * Check for too big/unaligned periods and unaligned DMA buffer
@@ -1461,8 +1608,10 @@ static int __init at_dma_probe(struct platform_device *pdev)
 
        /* setup platform data for each SoC */
        dma_cap_set(DMA_MEMCPY, at91sam9rl_config.cap_mask);
+       dma_cap_set(DMA_SG, at91sam9rl_config.cap_mask);
        dma_cap_set(DMA_MEMCPY, at91sam9g45_config.cap_mask);
        dma_cap_set(DMA_SLAVE, at91sam9g45_config.cap_mask);
+       dma_cap_set(DMA_SG, at91sam9g45_config.cap_mask);
 
        /* get DMA parameters from controller type */
        plat_dat = at_dma_get_driver_data(pdev);
@@ -1582,11 +1731,15 @@ static int __init at_dma_probe(struct platform_device *pdev)
                atdma->dma_common.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
        }
 
+       if (dma_has_cap(DMA_SG, atdma->dma_common.cap_mask))
+               atdma->dma_common.device_prep_dma_sg = atc_prep_dma_sg;
+
        dma_writel(atdma, EN, AT_DMA_ENABLE);
 
-       dev_info(&pdev->dev, "Atmel AHB DMA Controller ( %s%s), %d channels\n",
+       dev_info(&pdev->dev, "Atmel AHB DMA Controller ( %s%s%s), %d channels\n",
          dma_has_cap(DMA_MEMCPY, atdma->dma_common.cap_mask) ? "cpy " : "",
          dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask)  ? "slave " : "",
+         dma_has_cap(DMA_SG, atdma->dma_common.cap_mask)  ? "sg-cpy " : "",
          plat_dat->nr_channels);
 
        dma_async_device_register(&atdma->dma_common);
index d9891d3461f6fbd42f5cb85041147513ca07ba73..933e4b338459284465d7970e3ff7dbf0f37314b8 100644 (file)
@@ -1154,8 +1154,10 @@ static int at_xdmac_device_resume(struct dma_chan *chan)
        dev_dbg(chan2dev(chan), "%s\n", __func__);
 
        spin_lock_bh(&atchan->lock);
-       if (!at_xdmac_chan_is_paused(atchan))
+       if (!at_xdmac_chan_is_paused(atchan)) {
+               spin_unlock_bh(&atchan->lock);
                return 0;
+       }
 
        at_xdmac_write(atxdmac, AT_XDMAC_GRWR, atchan->mask);
        clear_bit(AT_XDMAC_CHAN_IS_PAUSED, &atchan->status);
index fa378d88f6c89e87987f2388703bb7bb8b496d85..180fedb418cc1983720072bb6a40b05ff9ea3a82 100644 (file)
@@ -30,7 +30,7 @@
 #define DRIVER_NAME "bestcomm-core"
 
 /* MPC5200 device tree match tables */
-static struct of_device_id mpc52xx_sram_ids[] = {
+static const struct of_device_id mpc52xx_sram_ids[] = {
        { .compatible = "fsl,mpc5200-sram", },
        { .compatible = "mpc5200-sram", },
        {}
@@ -481,7 +481,7 @@ static int mpc52xx_bcom_remove(struct platform_device *op)
        return 0;
 }
 
-static struct of_device_id mpc52xx_bcom_of_match[] = {
+static const struct of_device_id mpc52xx_bcom_of_match[] = {
        { .compatible = "fsl,mpc5200-bestcomm", },
        { .compatible = "mpc5200-bestcomm", },
        {},
index 84884418fd30fc73a700bde9c0bebd67d72ea0a5..7638b24ce8d0dac2672da6d4e83ce9956f054607 100644 (file)
@@ -7,10 +7,6 @@
  *  Free Software Foundation;  either version 2 of the License, or (at your
  *  option) any later version.
  *
- *  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/dmaengine.h>
@@ -343,7 +339,7 @@ static void jz4740_dma_chan_irq(struct jz4740_dmaengine_chan *chan)
 {
        spin_lock(&chan->vchan.lock);
        if (chan->desc) {
-               if (chan->desc && chan->desc->cyclic) {
+               if (chan->desc->cyclic) {
                        vchan_cyclic_callback(&chan->desc->vdesc);
                } else {
                        if (chan->next_sg == chan->desc->num_sgs) {
@@ -496,11 +492,6 @@ static enum dma_status jz4740_dma_tx_status(struct dma_chan *c,
        return status;
 }
 
-static int jz4740_dma_alloc_chan_resources(struct dma_chan *c)
-{
-       return 0;
-}
-
 static void jz4740_dma_free_chan_resources(struct dma_chan *c)
 {
        vchan_free_chan_resources(to_virt_chan(c));
@@ -543,7 +534,6 @@ static int jz4740_dma_probe(struct platform_device *pdev)
 
        dma_cap_set(DMA_SLAVE, dd->cap_mask);
        dma_cap_set(DMA_CYCLIC, dd->cap_mask);
-       dd->device_alloc_chan_resources = jz4740_dma_alloc_chan_resources;
        dd->device_free_chan_resources = jz4740_dma_free_chan_resources;
        dd->device_tx_status = jz4740_dma_tx_status;
        dd->device_issue_pending = jz4740_dma_issue_pending;
diff --git a/drivers/dma/dma-jz4780.c b/drivers/dma/dma-jz4780.c
new file mode 100644 (file)
index 0000000..26d2f0e
--- /dev/null
@@ -0,0 +1,877 @@
+/*
+ * Ingenic JZ4780 DMA controller
+ *
+ * Copyright (c) 2015 Imagination Technologies
+ * Author: Alex Smith <alex@alex-smith.me.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/dmapool.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_dma.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "dmaengine.h"
+#include "virt-dma.h"
+
+#define JZ_DMA_NR_CHANNELS     32
+
+/* Global registers. */
+#define JZ_DMA_REG_DMAC                0x1000
+#define JZ_DMA_REG_DIRQP       0x1004
+#define JZ_DMA_REG_DDR         0x1008
+#define JZ_DMA_REG_DDRS                0x100c
+#define JZ_DMA_REG_DMACP       0x101c
+#define JZ_DMA_REG_DSIRQP      0x1020
+#define JZ_DMA_REG_DSIRQM      0x1024
+#define JZ_DMA_REG_DCIRQP      0x1028
+#define JZ_DMA_REG_DCIRQM      0x102c
+
+/* Per-channel registers. */
+#define JZ_DMA_REG_CHAN(n)     (n * 0x20)
+#define JZ_DMA_REG_DSA(n)      (0x00 + JZ_DMA_REG_CHAN(n))
+#define JZ_DMA_REG_DTA(n)      (0x04 + JZ_DMA_REG_CHAN(n))
+#define JZ_DMA_REG_DTC(n)      (0x08 + JZ_DMA_REG_CHAN(n))
+#define JZ_DMA_REG_DRT(n)      (0x0c + JZ_DMA_REG_CHAN(n))
+#define JZ_DMA_REG_DCS(n)      (0x10 + JZ_DMA_REG_CHAN(n))
+#define JZ_DMA_REG_DCM(n)      (0x14 + JZ_DMA_REG_CHAN(n))
+#define JZ_DMA_REG_DDA(n)      (0x18 + JZ_DMA_REG_CHAN(n))
+#define JZ_DMA_REG_DSD(n)      (0x1c + JZ_DMA_REG_CHAN(n))
+
+#define JZ_DMA_DMAC_DMAE       BIT(0)
+#define JZ_DMA_DMAC_AR         BIT(2)
+#define JZ_DMA_DMAC_HLT                BIT(3)
+#define JZ_DMA_DMAC_FMSC       BIT(31)
+
+#define JZ_DMA_DRT_AUTO                0x8
+
+#define JZ_DMA_DCS_CTE         BIT(0)
+#define JZ_DMA_DCS_HLT         BIT(2)
+#define JZ_DMA_DCS_TT          BIT(3)
+#define JZ_DMA_DCS_AR          BIT(4)
+#define JZ_DMA_DCS_DES8                BIT(30)
+
+#define JZ_DMA_DCM_LINK                BIT(0)
+#define JZ_DMA_DCM_TIE         BIT(1)
+#define JZ_DMA_DCM_STDE                BIT(2)
+#define JZ_DMA_DCM_TSZ_SHIFT   8
+#define JZ_DMA_DCM_TSZ_MASK    (0x7 << JZ_DMA_DCM_TSZ_SHIFT)
+#define JZ_DMA_DCM_DP_SHIFT    12
+#define JZ_DMA_DCM_SP_SHIFT    14
+#define JZ_DMA_DCM_DAI         BIT(22)
+#define JZ_DMA_DCM_SAI         BIT(23)
+
+#define JZ_DMA_SIZE_4_BYTE     0x0
+#define JZ_DMA_SIZE_1_BYTE     0x1
+#define JZ_DMA_SIZE_2_BYTE     0x2
+#define JZ_DMA_SIZE_16_BYTE    0x3
+#define JZ_DMA_SIZE_32_BYTE    0x4
+#define JZ_DMA_SIZE_64_BYTE    0x5
+#define JZ_DMA_SIZE_128_BYTE   0x6
+
+#define JZ_DMA_WIDTH_32_BIT    0x0
+#define JZ_DMA_WIDTH_8_BIT     0x1
+#define JZ_DMA_WIDTH_16_BIT    0x2
+
+#define JZ_DMA_BUSWIDTHS       (BIT(DMA_SLAVE_BUSWIDTH_1_BYTE)  | \
+                                BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \
+                                BIT(DMA_SLAVE_BUSWIDTH_4_BYTES))
+
+/**
+ * struct jz4780_dma_hwdesc - descriptor structure read by the DMA controller.
+ * @dcm: value for the DCM (channel command) register
+ * @dsa: source address
+ * @dta: target address
+ * @dtc: transfer count (number of blocks of the transfer size specified in DCM
+ * to transfer) in the low 24 bits, offset of the next descriptor from the
+ * descriptor base address in the upper 8 bits.
+ * @sd: target/source stride difference (in stride transfer mode).
+ * @drt: request type
+ */
+struct jz4780_dma_hwdesc {
+       uint32_t dcm;
+       uint32_t dsa;
+       uint32_t dta;
+       uint32_t dtc;
+       uint32_t sd;
+       uint32_t drt;
+       uint32_t reserved[2];
+};
+
+/* Size of allocations for hardware descriptor blocks. */
+#define JZ_DMA_DESC_BLOCK_SIZE PAGE_SIZE
+#define JZ_DMA_MAX_DESC                \
+       (JZ_DMA_DESC_BLOCK_SIZE / sizeof(struct jz4780_dma_hwdesc))
+
+struct jz4780_dma_desc {
+       struct virt_dma_desc vdesc;
+
+       struct jz4780_dma_hwdesc *desc;
+       dma_addr_t desc_phys;
+       unsigned int count;
+       enum dma_transaction_type type;
+       uint32_t status;
+};
+
+struct jz4780_dma_chan {
+       struct virt_dma_chan vchan;
+       unsigned int id;
+       struct dma_pool *desc_pool;
+
+       uint32_t transfer_type;
+       uint32_t transfer_shift;
+       struct dma_slave_config config;
+
+       struct jz4780_dma_desc *desc;
+       unsigned int curr_hwdesc;
+};
+
+struct jz4780_dma_dev {
+       struct dma_device dma_device;
+       void __iomem *base;
+       struct clk *clk;
+       unsigned int irq;
+
+       uint32_t chan_reserved;
+       struct jz4780_dma_chan chan[JZ_DMA_NR_CHANNELS];
+};
+
+struct jz4780_dma_data {
+       uint32_t transfer_type;
+       int channel;
+};
+
+static inline struct jz4780_dma_chan *to_jz4780_dma_chan(struct dma_chan *chan)
+{
+       return container_of(chan, struct jz4780_dma_chan, vchan.chan);
+}
+
+static inline struct jz4780_dma_desc *to_jz4780_dma_desc(
+       struct virt_dma_desc *vdesc)
+{
+       return container_of(vdesc, struct jz4780_dma_desc, vdesc);
+}
+
+static inline struct jz4780_dma_dev *jz4780_dma_chan_parent(
+       struct jz4780_dma_chan *jzchan)
+{
+       return container_of(jzchan->vchan.chan.device, struct jz4780_dma_dev,
+                           dma_device);
+}
+
+static inline uint32_t jz4780_dma_readl(struct jz4780_dma_dev *jzdma,
+       unsigned int reg)
+{
+       return readl(jzdma->base + reg);
+}
+
+static inline void jz4780_dma_writel(struct jz4780_dma_dev *jzdma,
+       unsigned int reg, uint32_t val)
+{
+       writel(val, jzdma->base + reg);
+}
+
+static struct jz4780_dma_desc *jz4780_dma_desc_alloc(
+       struct jz4780_dma_chan *jzchan, unsigned int count,
+       enum dma_transaction_type type)
+{
+       struct jz4780_dma_desc *desc;
+
+       if (count > JZ_DMA_MAX_DESC)
+               return NULL;
+
+       desc = kzalloc(sizeof(*desc), GFP_NOWAIT);
+       if (!desc)
+               return NULL;
+
+       desc->desc = dma_pool_alloc(jzchan->desc_pool, GFP_NOWAIT,
+                                   &desc->desc_phys);
+       if (!desc->desc) {
+               kfree(desc);
+               return NULL;
+       }
+
+       desc->count = count;
+       desc->type = type;
+       return desc;
+}
+
+static void jz4780_dma_desc_free(struct virt_dma_desc *vdesc)
+{
+       struct jz4780_dma_desc *desc = to_jz4780_dma_desc(vdesc);
+       struct jz4780_dma_chan *jzchan = to_jz4780_dma_chan(vdesc->tx.chan);
+
+       dma_pool_free(jzchan->desc_pool, desc->desc, desc->desc_phys);
+       kfree(desc);
+}
+
+static uint32_t jz4780_dma_transfer_size(unsigned long val, int *ord)
+{
+       *ord = ffs(val) - 1;
+
+       switch (*ord) {
+       case 0:
+               return JZ_DMA_SIZE_1_BYTE;
+       case 1:
+               return JZ_DMA_SIZE_2_BYTE;
+       case 2:
+               return JZ_DMA_SIZE_4_BYTE;
+       case 4:
+               return JZ_DMA_SIZE_16_BYTE;
+       case 5:
+               return JZ_DMA_SIZE_32_BYTE;
+       case 6:
+               return JZ_DMA_SIZE_64_BYTE;
+       case 7:
+               return JZ_DMA_SIZE_128_BYTE;
+       default:
+               return -EINVAL;
+       }
+}
+
+static uint32_t jz4780_dma_setup_hwdesc(struct jz4780_dma_chan *jzchan,
+       struct jz4780_dma_hwdesc *desc, dma_addr_t addr, size_t len,
+       enum dma_transfer_direction direction)
+{
+       struct dma_slave_config *config = &jzchan->config;
+       uint32_t width, maxburst, tsz;
+       int ord;
+
+       if (direction == DMA_MEM_TO_DEV) {
+               desc->dcm = JZ_DMA_DCM_SAI;
+               desc->dsa = addr;
+               desc->dta = config->dst_addr;
+               desc->drt = jzchan->transfer_type;
+
+               width = config->dst_addr_width;
+               maxburst = config->dst_maxburst;
+       } else {
+               desc->dcm = JZ_DMA_DCM_DAI;
+               desc->dsa = config->src_addr;
+               desc->dta = addr;
+               desc->drt = jzchan->transfer_type;
+
+               width = config->src_addr_width;
+               maxburst = config->src_maxburst;
+       }
+
+       /*
+        * This calculates the maximum transfer size that can be used with the
+        * given address, length, width and maximum burst size. The address
+        * must be aligned to the transfer size, the total length must be
+        * divisible by the transfer size, and we must not use more than the
+        * maximum burst specified by the user.
+        */
+       tsz = jz4780_dma_transfer_size(addr | len | (width * maxburst), &ord);
+       jzchan->transfer_shift = ord;
+
+       switch (width) {
+       case DMA_SLAVE_BUSWIDTH_1_BYTE:
+       case DMA_SLAVE_BUSWIDTH_2_BYTES:
+               break;
+       case DMA_SLAVE_BUSWIDTH_4_BYTES:
+               width = JZ_DMA_WIDTH_32_BIT;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       desc->dcm |= tsz << JZ_DMA_DCM_TSZ_SHIFT;
+       desc->dcm |= width << JZ_DMA_DCM_SP_SHIFT;
+       desc->dcm |= width << JZ_DMA_DCM_DP_SHIFT;
+
+       desc->dtc = len >> ord;
+}
+
+static struct dma_async_tx_descriptor *jz4780_dma_prep_slave_sg(
+       struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len,
+       enum dma_transfer_direction direction, unsigned long flags)
+{
+       struct jz4780_dma_chan *jzchan = to_jz4780_dma_chan(chan);
+       struct jz4780_dma_desc *desc;
+       unsigned int i;
+       int err;
+
+       desc = jz4780_dma_desc_alloc(jzchan, sg_len, DMA_SLAVE);
+       if (!desc)
+               return NULL;
+
+       for (i = 0; i < sg_len; i++) {
+               err = jz4780_dma_setup_hwdesc(jzchan, &desc->desc[i],
+                                       sg_dma_address(&sgl[i]),
+                                       sg_dma_len(&sgl[i]),
+                                       direction);
+               if (err < 0)
+                       return ERR_PTR(err);
+
+
+               desc->desc[i].dcm |= JZ_DMA_DCM_TIE;
+
+               if (i != (sg_len - 1)) {
+                       /* Automatically proceeed to the next descriptor. */
+                       desc->desc[i].dcm |= JZ_DMA_DCM_LINK;
+
+                       /*
+                        * The upper 8 bits of the DTC field in the descriptor
+                        * must be set to (offset from descriptor base of next
+                        * descriptor >> 4).
+                        */
+                       desc->desc[i].dtc |=
+                               (((i + 1) * sizeof(*desc->desc)) >> 4) << 24;
+               }
+       }
+
+       return vchan_tx_prep(&jzchan->vchan, &desc->vdesc, flags);
+}
+
+static struct dma_async_tx_descriptor *jz4780_dma_prep_dma_cyclic(
+       struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
+       size_t period_len, enum dma_transfer_direction direction,
+       unsigned long flags)
+{
+       struct jz4780_dma_chan *jzchan = to_jz4780_dma_chan(chan);
+       struct jz4780_dma_desc *desc;
+       unsigned int periods, i;
+       int err;
+
+       if (buf_len % period_len)
+               return NULL;
+
+       periods = buf_len / period_len;
+
+       desc = jz4780_dma_desc_alloc(jzchan, periods, DMA_CYCLIC);
+       if (!desc)
+               return NULL;
+
+       for (i = 0; i < periods; i++) {
+               err = jz4780_dma_setup_hwdesc(jzchan, &desc->desc[i], buf_addr,
+                                       period_len, direction);
+               if (err < 0)
+                       return ERR_PTR(err);
+
+               buf_addr += period_len;
+
+               /*
+                * Set the link bit to indicate that the controller should
+                * automatically proceed to the next descriptor. In
+                * jz4780_dma_begin(), this will be cleared if we need to issue
+                * an interrupt after each period.
+                */
+               desc->desc[i].dcm |= JZ_DMA_DCM_TIE | JZ_DMA_DCM_LINK;
+
+               /*
+                * The upper 8 bits of the DTC field in the descriptor must be
+                * set to (offset from descriptor base of next descriptor >> 4).
+                * If this is the last descriptor, link it back to the first,
+                * i.e. leave offset set to 0, otherwise point to the next one.
+                */
+               if (i != (periods - 1)) {
+                       desc->desc[i].dtc |=
+                               (((i + 1) * sizeof(*desc->desc)) >> 4) << 24;
+               }
+       }
+
+       return vchan_tx_prep(&jzchan->vchan, &desc->vdesc, flags);
+}
+
+struct dma_async_tx_descriptor *jz4780_dma_prep_dma_memcpy(
+       struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
+       size_t len, unsigned long flags)
+{
+       struct jz4780_dma_chan *jzchan = to_jz4780_dma_chan(chan);
+       struct jz4780_dma_desc *desc;
+       uint32_t tsz;
+       int ord;
+
+       desc = jz4780_dma_desc_alloc(jzchan, 1, DMA_MEMCPY);
+       if (!desc)
+               return NULL;
+
+       tsz = jz4780_dma_transfer_size(dest | src | len, &ord);
+       if (tsz < 0)
+               return ERR_PTR(tsz);
+
+       desc->desc[0].dsa = src;
+       desc->desc[0].dta = dest;
+       desc->desc[0].drt = JZ_DMA_DRT_AUTO;
+       desc->desc[0].dcm = JZ_DMA_DCM_TIE | JZ_DMA_DCM_SAI | JZ_DMA_DCM_DAI |
+                           tsz << JZ_DMA_DCM_TSZ_SHIFT |
+                           JZ_DMA_WIDTH_32_BIT << JZ_DMA_DCM_SP_SHIFT |
+                           JZ_DMA_WIDTH_32_BIT << JZ_DMA_DCM_DP_SHIFT;
+       desc->desc[0].dtc = len >> ord;
+
+       return vchan_tx_prep(&jzchan->vchan, &desc->vdesc, flags);
+}
+
+static void jz4780_dma_begin(struct jz4780_dma_chan *jzchan)
+{
+       struct jz4780_dma_dev *jzdma = jz4780_dma_chan_parent(jzchan);
+       struct virt_dma_desc *vdesc;
+       unsigned int i;
+       dma_addr_t desc_phys;
+
+       if (!jzchan->desc) {
+               vdesc = vchan_next_desc(&jzchan->vchan);
+               if (!vdesc)
+                       return;
+
+               list_del(&vdesc->node);
+
+               jzchan->desc = to_jz4780_dma_desc(vdesc);
+               jzchan->curr_hwdesc = 0;
+
+               if (jzchan->desc->type == DMA_CYCLIC && vdesc->tx.callback) {
+                       /*
+                        * The DMA controller doesn't support triggering an
+                        * interrupt after processing each descriptor, only
+                        * after processing an entire terminated list of
+                        * descriptors. For a cyclic DMA setup the list of
+                        * descriptors is not terminated so we can never get an
+                        * interrupt.
+                        *
+                        * If the user requested a callback for a cyclic DMA
+                        * setup then we workaround this hardware limitation
+                        * here by degrading to a set of unlinked descriptors
+                        * which we will submit in sequence in response to the
+                        * completion of processing the previous descriptor.
+                        */
+                       for (i = 0; i < jzchan->desc->count; i++)
+                               jzchan->desc->desc[i].dcm &= ~JZ_DMA_DCM_LINK;
+               }
+       } else {
+               /*
+                * There is an existing transfer, therefore this must be one
+                * for which we unlinked the descriptors above. Advance to the
+                * next one in the list.
+                */
+               jzchan->curr_hwdesc =
+                       (jzchan->curr_hwdesc + 1) % jzchan->desc->count;
+       }
+
+       /* Use 8-word descriptors. */
+       jz4780_dma_writel(jzdma, JZ_DMA_REG_DCS(jzchan->id), JZ_DMA_DCS_DES8);
+
+       /* Write descriptor address and initiate descriptor fetch. */
+       desc_phys = jzchan->desc->desc_phys +
+                   (jzchan->curr_hwdesc * sizeof(*jzchan->desc->desc));
+       jz4780_dma_writel(jzdma, JZ_DMA_REG_DDA(jzchan->id), desc_phys);
+       jz4780_dma_writel(jzdma, JZ_DMA_REG_DDRS, BIT(jzchan->id));
+
+       /* Enable the channel. */
+       jz4780_dma_writel(jzdma, JZ_DMA_REG_DCS(jzchan->id),
+                         JZ_DMA_DCS_DES8 | JZ_DMA_DCS_CTE);
+}
+
+static void jz4780_dma_issue_pending(struct dma_chan *chan)
+{
+       struct jz4780_dma_chan *jzchan = to_jz4780_dma_chan(chan);
+       unsigned long flags;
+
+       spin_lock_irqsave(&jzchan->vchan.lock, flags);
+
+       if (vchan_issue_pending(&jzchan->vchan) && !jzchan->desc)
+               jz4780_dma_begin(jzchan);
+
+       spin_unlock_irqrestore(&jzchan->vchan.lock, flags);
+}
+
+static int jz4780_dma_terminate_all(struct jz4780_dma_chan *jzchan)
+{
+       struct jz4780_dma_dev *jzdma = jz4780_dma_chan_parent(jzchan);
+       unsigned long flags;
+       LIST_HEAD(head);
+
+       spin_lock_irqsave(&jzchan->vchan.lock, flags);
+
+       /* Clear the DMA status and stop the transfer. */
+       jz4780_dma_writel(jzdma, JZ_DMA_REG_DCS(jzchan->id), 0);
+       if (jzchan->desc) {
+               jz4780_dma_desc_free(&jzchan->desc->vdesc);
+               jzchan->desc = NULL;
+       }
+
+       vchan_get_all_descriptors(&jzchan->vchan, &head);
+
+       spin_unlock_irqrestore(&jzchan->vchan.lock, flags);
+
+       vchan_dma_desc_free_list(&jzchan->vchan, &head);
+       return 0;
+}
+
+static int jz4780_dma_slave_config(struct jz4780_dma_chan *jzchan,
+       const struct dma_slave_config *config)
+{
+       if ((config->src_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES)
+          || (config->dst_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES))
+               return -EINVAL;
+
+       /* Copy the reset of the slave configuration, it is used later. */
+       memcpy(&jzchan->config, config, sizeof(jzchan->config));
+
+       return 0;
+}
+
+static size_t jz4780_dma_desc_residue(struct jz4780_dma_chan *jzchan,
+       struct jz4780_dma_desc *desc, unsigned int next_sg)
+{
+       struct jz4780_dma_dev *jzdma = jz4780_dma_chan_parent(jzchan);
+       unsigned int residue, count;
+       unsigned int i;
+
+       residue = 0;
+
+       for (i = next_sg; i < desc->count; i++)
+               residue += desc->desc[i].dtc << jzchan->transfer_shift;
+
+       if (next_sg != 0) {
+               count = jz4780_dma_readl(jzdma,
+                                        JZ_DMA_REG_DTC(jzchan->id));
+               residue += count << jzchan->transfer_shift;
+       }
+
+       return residue;
+}
+
+static enum dma_status jz4780_dma_tx_status(struct dma_chan *chan,
+       dma_cookie_t cookie, struct dma_tx_state *txstate)
+{
+       struct jz4780_dma_chan *jzchan = to_jz4780_dma_chan(chan);
+       struct virt_dma_desc *vdesc;
+       enum dma_status status;
+       unsigned long flags;
+
+       status = dma_cookie_status(chan, cookie, txstate);
+       if ((status == DMA_COMPLETE) || (txstate == NULL))
+               return status;
+
+       spin_lock_irqsave(&jzchan->vchan.lock, flags);
+
+       vdesc = vchan_find_desc(&jzchan->vchan, cookie);
+       if (vdesc) {
+               /* On the issued list, so hasn't been processed yet */
+               txstate->residue = jz4780_dma_desc_residue(jzchan,
+                                       to_jz4780_dma_desc(vdesc), 0);
+       } else if (cookie == jzchan->desc->vdesc.tx.cookie) {
+               txstate->residue = jz4780_dma_desc_residue(jzchan, jzchan->desc,
+                         (jzchan->curr_hwdesc + 1) % jzchan->desc->count);
+       } else
+               txstate->residue = 0;
+
+       if (vdesc && jzchan->desc && vdesc == &jzchan->desc->vdesc
+               && jzchan->desc->status & (JZ_DMA_DCS_AR | JZ_DMA_DCS_HLT))
+                       status = DMA_ERROR;
+
+       spin_unlock_irqrestore(&jzchan->vchan.lock, flags);
+       return status;
+}
+
+static void jz4780_dma_chan_irq(struct jz4780_dma_dev *jzdma,
+       struct jz4780_dma_chan *jzchan)
+{
+       uint32_t dcs;
+
+       spin_lock(&jzchan->vchan.lock);
+
+       dcs = jz4780_dma_readl(jzdma, JZ_DMA_REG_DCS(jzchan->id));
+       jz4780_dma_writel(jzdma, JZ_DMA_REG_DCS(jzchan->id), 0);
+
+       if (dcs & JZ_DMA_DCS_AR) {
+               dev_warn(&jzchan->vchan.chan.dev->device,
+                        "address error (DCS=0x%x)\n", dcs);
+       }
+
+       if (dcs & JZ_DMA_DCS_HLT) {
+               dev_warn(&jzchan->vchan.chan.dev->device,
+                        "channel halt (DCS=0x%x)\n", dcs);
+       }
+
+       if (jzchan->desc) {
+               jzchan->desc->status = dcs;
+
+               if ((dcs & (JZ_DMA_DCS_AR | JZ_DMA_DCS_HLT)) == 0) {
+                       if (jzchan->desc->type == DMA_CYCLIC) {
+                               vchan_cyclic_callback(&jzchan->desc->vdesc);
+                       } else {
+                               vchan_cookie_complete(&jzchan->desc->vdesc);
+                               jzchan->desc = NULL;
+                       }
+
+                       jz4780_dma_begin(jzchan);
+               }
+       } else {
+               dev_err(&jzchan->vchan.chan.dev->device,
+                       "channel IRQ with no active transfer\n");
+       }
+
+       spin_unlock(&jzchan->vchan.lock);
+}
+
+static irqreturn_t jz4780_dma_irq_handler(int irq, void *data)
+{
+       struct jz4780_dma_dev *jzdma = data;
+       uint32_t pending, dmac;
+       int i;
+
+       pending = jz4780_dma_readl(jzdma, JZ_DMA_REG_DIRQP);
+
+       for (i = 0; i < JZ_DMA_NR_CHANNELS; i++) {
+               if (!(pending & (1<<i)))
+                       continue;
+
+               jz4780_dma_chan_irq(jzdma, &jzdma->chan[i]);
+       }
+
+       /* Clear halt and address error status of all channels. */
+       dmac = jz4780_dma_readl(jzdma, JZ_DMA_REG_DMAC);
+       dmac &= ~(JZ_DMA_DMAC_HLT | JZ_DMA_DMAC_AR);
+       jz4780_dma_writel(jzdma, JZ_DMA_REG_DMAC, dmac);
+
+       /* Clear interrupt pending status. */
+       jz4780_dma_writel(jzdma, JZ_DMA_REG_DIRQP, 0);
+
+       return IRQ_HANDLED;
+}
+
+static int jz4780_dma_alloc_chan_resources(struct dma_chan *chan)
+{
+       struct jz4780_dma_chan *jzchan = to_jz4780_dma_chan(chan);
+
+       jzchan->desc_pool = dma_pool_create(dev_name(&chan->dev->device),
+                                           chan->device->dev,
+                                           JZ_DMA_DESC_BLOCK_SIZE,
+                                           PAGE_SIZE, 0);
+       if (!jzchan->desc_pool) {
+               dev_err(&chan->dev->device,
+                       "failed to allocate descriptor pool\n");
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+static void jz4780_dma_free_chan_resources(struct dma_chan *chan)
+{
+       struct jz4780_dma_chan *jzchan = to_jz4780_dma_chan(chan);
+
+       vchan_free_chan_resources(&jzchan->vchan);
+       dma_pool_destroy(jzchan->desc_pool);
+       jzchan->desc_pool = NULL;
+}
+
+static bool jz4780_dma_filter_fn(struct dma_chan *chan, void *param)
+{
+       struct jz4780_dma_chan *jzchan = to_jz4780_dma_chan(chan);
+       struct jz4780_dma_dev *jzdma = jz4780_dma_chan_parent(jzchan);
+       struct jz4780_dma_data *data = param;
+
+       if (data->channel > -1) {
+               if (data->channel != jzchan->id)
+                       return false;
+       } else if (jzdma->chan_reserved & BIT(jzchan->id)) {
+               return false;
+       }
+
+       jzchan->transfer_type = data->transfer_type;
+
+       return true;
+}
+
+static struct dma_chan *jz4780_of_dma_xlate(struct of_phandle_args *dma_spec,
+       struct of_dma *ofdma)
+{
+       struct jz4780_dma_dev *jzdma = ofdma->of_dma_data;
+       dma_cap_mask_t mask = jzdma->dma_device.cap_mask;
+       struct jz4780_dma_data data;
+
+       if (dma_spec->args_count != 2)
+               return NULL;
+
+       data.transfer_type = dma_spec->args[0];
+       data.channel = dma_spec->args[1];
+
+       if (data.channel > -1) {
+               if (data.channel >= JZ_DMA_NR_CHANNELS) {
+                       dev_err(jzdma->dma_device.dev,
+                               "device requested non-existent channel %u\n",
+                               data.channel);
+                       return NULL;
+               }
+
+               /* Can only select a channel marked as reserved. */
+               if (!(jzdma->chan_reserved & BIT(data.channel))) {
+                       dev_err(jzdma->dma_device.dev,
+                               "device requested unreserved channel %u\n",
+                               data.channel);
+                       return NULL;
+               }
+       }
+
+       return dma_request_channel(mask, jz4780_dma_filter_fn, &data);
+}
+
+static int jz4780_dma_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct jz4780_dma_dev *jzdma;
+       struct jz4780_dma_chan *jzchan;
+       struct dma_device *dd;
+       struct resource *res;
+       int i, ret;
+
+       jzdma = devm_kzalloc(dev, sizeof(*jzdma), GFP_KERNEL);
+       if (!jzdma)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, jzdma);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(dev, "failed to get I/O memory\n");
+               return -EINVAL;
+       }
+
+       jzdma->base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(jzdma->base))
+               return PTR_ERR(jzdma->base);
+
+       jzdma->irq = platform_get_irq(pdev, 0);
+       if (jzdma->irq < 0) {
+               dev_err(dev, "failed to get IRQ: %d\n", ret);
+               return jzdma->irq;
+       }
+
+       ret = devm_request_irq(dev, jzdma->irq, jz4780_dma_irq_handler, 0,
+                              dev_name(dev), jzdma);
+       if (ret) {
+               dev_err(dev, "failed to request IRQ %u!\n", jzdma->irq);
+               return -EINVAL;
+       }
+
+       jzdma->clk = devm_clk_get(dev, NULL);
+       if (IS_ERR(jzdma->clk)) {
+               dev_err(dev, "failed to get clock\n");
+               return PTR_ERR(jzdma->clk);
+       }
+
+       clk_prepare_enable(jzdma->clk);
+
+       /* Property is optional, if it doesn't exist the value will remain 0. */
+       of_property_read_u32_index(dev->of_node, "ingenic,reserved-channels",
+                                  0, &jzdma->chan_reserved);
+
+       dd = &jzdma->dma_device;
+
+       dma_cap_set(DMA_MEMCPY, dd->cap_mask);
+       dma_cap_set(DMA_SLAVE, dd->cap_mask);
+       dma_cap_set(DMA_CYCLIC, dd->cap_mask);
+
+       dd->dev = dev;
+       dd->copy_align = 2; /* 2^2 = 4 byte alignment */
+       dd->device_alloc_chan_resources = jz4780_dma_alloc_chan_resources;
+       dd->device_free_chan_resources = jz4780_dma_free_chan_resources;
+       dd->device_prep_slave_sg = jz4780_dma_prep_slave_sg;
+       dd->device_prep_dma_cyclic = jz4780_dma_prep_dma_cyclic;
+       dd->device_prep_dma_memcpy = jz4780_dma_prep_dma_memcpy;
+       dd->device_config = jz4780_dma_slave_config;
+       dd->device_terminate_all = jz4780_dma_terminate_all;
+       dd->device_tx_status = jz4780_dma_tx_status;
+       dd->device_issue_pending = jz4780_dma_issue_pending;
+       dd->src_addr_widths = JZ_DMA_BUSWIDTHS;
+       dd->dst_addr_widths = JZ_DMA_BUSWIDTHS;
+       dd->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
+       dd->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
+
+
+       /*
+        * Enable DMA controller, mark all channels as not programmable.
+        * Also set the FMSC bit - it increases MSC performance, so it makes
+        * little sense not to enable it.
+        */
+       jz4780_dma_writel(jzdma, JZ_DMA_REG_DMAC,
+                         JZ_DMA_DMAC_DMAE | JZ_DMA_DMAC_FMSC);
+       jz4780_dma_writel(jzdma, JZ_DMA_REG_DMACP, 0);
+
+       INIT_LIST_HEAD(&dd->channels);
+
+       for (i = 0; i < JZ_DMA_NR_CHANNELS; i++) {
+               jzchan = &jzdma->chan[i];
+               jzchan->id = i;
+
+               vchan_init(&jzchan->vchan, dd);
+               jzchan->vchan.desc_free = jz4780_dma_desc_free;
+       }
+
+       ret = dma_async_device_register(dd);
+       if (ret) {
+               dev_err(dev, "failed to register device\n");
+               goto err_disable_clk;
+       }
+
+       /* Register with OF DMA helpers. */
+       ret = of_dma_controller_register(dev->of_node, jz4780_of_dma_xlate,
+                                        jzdma);
+       if (ret) {
+               dev_err(dev, "failed to register OF DMA controller\n");
+               goto err_unregister_dev;
+       }
+
+       dev_info(dev, "JZ4780 DMA controller initialised\n");
+       return 0;
+
+err_unregister_dev:
+       dma_async_device_unregister(dd);
+
+err_disable_clk:
+       clk_disable_unprepare(jzdma->clk);
+       return ret;
+}
+
+static int jz4780_dma_remove(struct platform_device *pdev)
+{
+       struct jz4780_dma_dev *jzdma = platform_get_drvdata(pdev);
+
+       of_dma_controller_free(pdev->dev.of_node);
+       devm_free_irq(&pdev->dev, jzdma->irq, jzdma);
+       dma_async_device_unregister(&jzdma->dma_device);
+       return 0;
+}
+
+static const struct of_device_id jz4780_dma_dt_match[] = {
+       { .compatible = "ingenic,jz4780-dma", .data = NULL },
+       {},
+};
+MODULE_DEVICE_TABLE(of, jz4780_dma_dt_match);
+
+static struct platform_driver jz4780_dma_driver = {
+       .probe          = jz4780_dma_probe,
+       .remove         = jz4780_dma_remove,
+       .driver = {
+               .name   = "jz4780-dma",
+               .of_match_table = of_match_ptr(jz4780_dma_dt_match),
+       },
+};
+
+static int __init jz4780_dma_init(void)
+{
+       return platform_driver_register(&jz4780_dma_driver);
+}
+subsys_initcall(jz4780_dma_init);
+
+static void __exit jz4780_dma_exit(void)
+{
+       platform_driver_unregister(&jz4780_dma_driver);
+}
+module_exit(jz4780_dma_exit);
+
+MODULE_AUTHOR("Alex Smith <alex@alex-smith.me.uk>");
+MODULE_DESCRIPTION("Ingenic JZ4780 DMA controller driver");
+MODULE_LICENSE("GPL");
index ac336a961dea97be01894027b9f4bd16d5566bad..2890d744bb1bb902cc095fb87841c492cef7542c 100644 (file)
  * 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.
- *
  * The full GNU General Public License is included in this distribution in the
  * file called COPYING.
  */
@@ -355,20 +351,6 @@ struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type)
 }
 EXPORT_SYMBOL(dma_find_channel);
 
-/*
- * net_dma_find_channel - find a channel for net_dma
- * net_dma has alignment requirements
- */
-struct dma_chan *net_dma_find_channel(void)
-{
-       struct dma_chan *chan = dma_find_channel(DMA_MEMCPY);
-       if (chan && !is_dma_copy_aligned(chan->device, 1, 1, 1))
-               return NULL;
-
-       return chan;
-}
-EXPORT_SYMBOL(net_dma_find_channel);
-
 /**
  * dma_issue_pending_all - flush all pending operations across all channels
  */
@@ -589,11 +571,15 @@ struct dma_chan *dma_get_any_slave_channel(struct dma_device *device)
 
        chan = private_candidate(&mask, device, NULL, NULL);
        if (chan) {
+               dma_cap_set(DMA_PRIVATE, device->cap_mask);
+               device->privatecnt++;
                err = dma_chan_get(chan);
                if (err) {
                        pr_debug("%s: failed to get %s: (%d)\n",
                                __func__, dma_chan_name(chan), err);
                        chan = NULL;
+                       if (--device->privatecnt == 0)
+                               dma_cap_clear(DMA_PRIVATE, device->cap_mask);
                }
        }
 
index dcfe964cc8dc3138da6262fb6f453b3a421b45f7..36e02f0f645e33382412a4d6718ef43ce8f12d13 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 config DW_DMAC_CORE
-       tristate "Synopsys DesignWare AHB DMA support"
+       tristate
        select DMA_ENGINE
 
 config DW_DMAC
index a8ad05291b274498b55deef4bba88a2dbf1ffbd3..1022c2e1a2b0adeac7e5954cd55363e2df7f7dab 100644 (file)
@@ -230,7 +230,8 @@ static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first)
        /* ASSERT:  channel is idle */
        if (dma_readl(dw, CH_EN) & dwc->mask) {
                dev_err(chan2dev(&dwc->chan),
-                       "BUG: Attempted to start non-idle channel\n");
+                       "%s: BUG: Attempted to start non-idle channel\n",
+                       __func__);
                dwc_dump_chan_regs(dwc);
 
                /* The tasklet will hopefully advance the queue... */
@@ -814,11 +815,8 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 
 slave_sg_todev_fill_desc:
                        desc = dwc_desc_get(dwc);
-                       if (!desc) {
-                               dev_err(chan2dev(chan),
-                                       "not enough descriptors available\n");
+                       if (!desc)
                                goto err_desc_get;
-                       }
 
                        desc->lli.sar = mem;
                        desc->lli.dar = reg;
@@ -874,11 +872,8 @@ slave_sg_todev_fill_desc:
 
 slave_sg_fromdev_fill_desc:
                        desc = dwc_desc_get(dwc);
-                       if (!desc) {
-                               dev_err(chan2dev(chan),
-                                               "not enough descriptors available\n");
+                       if (!desc)
                                goto err_desc_get;
-                       }
 
                        desc->lli.sar = reg;
                        desc->lli.dar = mem;
@@ -922,6 +917,8 @@ slave_sg_fromdev_fill_desc:
        return &first->txd;
 
 err_desc_get:
+       dev_err(chan2dev(chan),
+               "not enough descriptors available. Direction %d\n", direction);
        dwc_desc_put(dwc, first);
        return NULL;
 }
@@ -1261,7 +1258,8 @@ int dw_dma_cyclic_start(struct dma_chan *chan)
        /* Assert channel is idle */
        if (dma_readl(dw, CH_EN) & dwc->mask) {
                dev_err(chan2dev(&dwc->chan),
-                       "BUG: Attempted to start non-idle channel\n");
+                       "%s: BUG: Attempted to start non-idle channel\n",
+                       __func__);
                dwc_dump_chan_regs(dwc);
                spin_unlock_irqrestore(&dwc->lock, flags);
                return -EBUSY;
index 53dbd3b3384cfd8b00940f7a7cd752b28bcac71a..bf09db7ca9ee9c691bcb59888575d2679b4ddd3e 100644 (file)
@@ -812,7 +812,7 @@ static int edma_alloc_chan_resources(struct dma_chan *chan)
        LIST_HEAD(descs);
 
        a_ch_num = edma_alloc_channel(echan->ch_num, edma_callback,
-                                       chan, EVENTQ_DEFAULT);
+                                       echan, EVENTQ_DEFAULT);
 
        if (a_ch_num < 0) {
                ret = -ENODEV;
diff --git a/drivers/dma/fsl_raid.c b/drivers/dma/fsl_raid.c
new file mode 100644 (file)
index 0000000..4d9470f
--- /dev/null
@@ -0,0 +1,904 @@
+/*
+ * drivers/dma/fsl_raid.c
+ *
+ * Freescale RAID Engine device driver
+ *
+ * Author:
+ *     Harninder Rai <harninder.rai@freescale.com>
+ *     Naveen Burmi <naveenburmi@freescale.com>
+ *
+ * Rewrite:
+ *     Xuelin Shi <xuelin.shi@freescale.com>
+ *
+ * Copyright (c) 2010-2014 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Theory of operation:
+ *
+ * General capabilities:
+ *     RAID Engine (RE) block is capable of offloading XOR, memcpy and P/Q
+ *     calculations required in RAID5 and RAID6 operations. RE driver
+ *     registers with Linux's ASYNC layer as dma driver. RE hardware
+ *     maintains strict ordering of the requests through chained
+ *     command queueing.
+ *
+ * Data flow:
+ *     Software RAID layer of Linux (MD layer) maintains RAID partitions,
+ *     strips, stripes etc. It sends requests to the underlying ASYNC layer
+ *     which further passes it to RE driver. ASYNC layer decides which request
+ *     goes to which job ring of RE hardware. For every request processed by
+ *     RAID Engine, driver gets an interrupt unless coalescing is set. The
+ *     per job ring interrupt handler checks the status register for errors,
+ *     clears the interrupt and leave the post interrupt processing to the irq
+ *     thread.
+ */
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/dmaengine.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+
+#include "dmaengine.h"
+#include "fsl_raid.h"
+
+#define FSL_RE_MAX_XOR_SRCS    16
+#define FSL_RE_MAX_PQ_SRCS     16
+#define FSL_RE_MIN_DESCS       256
+#define FSL_RE_MAX_DESCS       (4 * FSL_RE_MIN_DESCS)
+#define FSL_RE_FRAME_FORMAT    0x1
+#define FSL_RE_MAX_DATA_LEN    (1024*1024)
+
+#define to_fsl_re_dma_desc(tx) container_of(tx, struct fsl_re_desc, async_tx)
+
+/* Add descriptors into per chan software queue - submit_q */
+static dma_cookie_t fsl_re_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+       struct fsl_re_desc *desc;
+       struct fsl_re_chan *re_chan;
+       dma_cookie_t cookie;
+       unsigned long flags;
+
+       desc = to_fsl_re_dma_desc(tx);
+       re_chan = container_of(tx->chan, struct fsl_re_chan, chan);
+
+       spin_lock_irqsave(&re_chan->desc_lock, flags);
+       cookie = dma_cookie_assign(tx);
+       list_add_tail(&desc->node, &re_chan->submit_q);
+       spin_unlock_irqrestore(&re_chan->desc_lock, flags);
+
+       return cookie;
+}
+
+/* Copy descriptor from per chan software queue into hardware job ring */
+static void fsl_re_issue_pending(struct dma_chan *chan)
+{
+       struct fsl_re_chan *re_chan;
+       int avail;
+       struct fsl_re_desc *desc, *_desc;
+       unsigned long flags;
+
+       re_chan = container_of(chan, struct fsl_re_chan, chan);
+
+       spin_lock_irqsave(&re_chan->desc_lock, flags);
+       avail = FSL_RE_SLOT_AVAIL(
+               in_be32(&re_chan->jrregs->inbring_slot_avail));
+
+       list_for_each_entry_safe(desc, _desc, &re_chan->submit_q, node) {
+               if (!avail)
+                       break;
+
+               list_move_tail(&desc->node, &re_chan->active_q);
+
+               memcpy(&re_chan->inb_ring_virt_addr[re_chan->inb_count],
+                      &desc->hwdesc, sizeof(struct fsl_re_hw_desc));
+
+               re_chan->inb_count = (re_chan->inb_count + 1) &
+                                               FSL_RE_RING_SIZE_MASK;
+               out_be32(&re_chan->jrregs->inbring_add_job, FSL_RE_ADD_JOB(1));
+               avail--;
+       }
+       spin_unlock_irqrestore(&re_chan->desc_lock, flags);
+}
+
+static void fsl_re_desc_done(struct fsl_re_desc *desc)
+{
+       dma_async_tx_callback callback;
+       void *callback_param;
+
+       dma_cookie_complete(&desc->async_tx);
+
+       callback = desc->async_tx.callback;
+       callback_param = desc->async_tx.callback_param;
+       if (callback)
+               callback(callback_param);
+
+       dma_descriptor_unmap(&desc->async_tx);
+}
+
+static void fsl_re_cleanup_descs(struct fsl_re_chan *re_chan)
+{
+       struct fsl_re_desc *desc, *_desc;
+       unsigned long flags;
+
+       spin_lock_irqsave(&re_chan->desc_lock, flags);
+       list_for_each_entry_safe(desc, _desc, &re_chan->ack_q, node) {
+               if (async_tx_test_ack(&desc->async_tx))
+                       list_move_tail(&desc->node, &re_chan->free_q);
+       }
+       spin_unlock_irqrestore(&re_chan->desc_lock, flags);
+
+       fsl_re_issue_pending(&re_chan->chan);
+}
+
+static void fsl_re_dequeue(unsigned long data)
+{
+       struct fsl_re_chan *re_chan;
+       struct fsl_re_desc *desc, *_desc;
+       struct fsl_re_hw_desc *hwdesc;
+       unsigned long flags;
+       unsigned int count, oub_count;
+       int found;
+
+       re_chan = dev_get_drvdata((struct device *)data);
+
+       fsl_re_cleanup_descs(re_chan);
+
+       spin_lock_irqsave(&re_chan->desc_lock, flags);
+       count = FSL_RE_SLOT_FULL(in_be32(&re_chan->jrregs->oubring_slot_full));
+       while (count--) {
+               found = 0;
+               hwdesc = &re_chan->oub_ring_virt_addr[re_chan->oub_count];
+               list_for_each_entry_safe(desc, _desc, &re_chan->active_q,
+                                        node) {
+                       /* compare the hw dma addr to find the completed */
+                       if (desc->hwdesc.lbea32 == hwdesc->lbea32 &&
+                           desc->hwdesc.addr_low == hwdesc->addr_low) {
+                               found = 1;
+                               break;
+                       }
+               }
+
+               if (found) {
+                       fsl_re_desc_done(desc);
+                       list_move_tail(&desc->node, &re_chan->ack_q);
+               } else {
+                       dev_err(re_chan->dev,
+                               "found hwdesc not in sw queue, discard it\n");
+               }
+
+               oub_count = (re_chan->oub_count + 1) & FSL_RE_RING_SIZE_MASK;
+               re_chan->oub_count = oub_count;
+
+               out_be32(&re_chan->jrregs->oubring_job_rmvd,
+                        FSL_RE_RMVD_JOB(1));
+       }
+       spin_unlock_irqrestore(&re_chan->desc_lock, flags);
+}
+
+/* Per Job Ring interrupt handler */
+static irqreturn_t fsl_re_isr(int irq, void *data)
+{
+       struct fsl_re_chan *re_chan;
+       u32 irqstate, status;
+
+       re_chan = dev_get_drvdata((struct device *)data);
+
+       irqstate = in_be32(&re_chan->jrregs->jr_interrupt_status);
+       if (!irqstate)
+               return IRQ_NONE;
+
+       /*
+        * There's no way in upper layer (read MD layer) to recover from
+        * error conditions except restart everything. In long term we
+        * need to do something more than just crashing
+        */
+       if (irqstate & FSL_RE_ERROR) {
+               status = in_be32(&re_chan->jrregs->jr_status);
+               dev_err(re_chan->dev, "chan error irqstate: %x, status: %x\n",
+                       irqstate, status);
+       }
+
+       /* Clear interrupt */
+       out_be32(&re_chan->jrregs->jr_interrupt_status, FSL_RE_CLR_INTR);
+
+       tasklet_schedule(&re_chan->irqtask);
+
+       return IRQ_HANDLED;
+}
+
+static enum dma_status fsl_re_tx_status(struct dma_chan *chan,
+                                       dma_cookie_t cookie,
+                                       struct dma_tx_state *txstate)
+{
+       return dma_cookie_status(chan, cookie, txstate);
+}
+
+static void fill_cfd_frame(struct fsl_re_cmpnd_frame *cf, u8 index,
+                          size_t length, dma_addr_t addr, bool final)
+{
+       u32 efrl = length & FSL_RE_CF_LENGTH_MASK;
+
+       efrl |= final << FSL_RE_CF_FINAL_SHIFT;
+       cf[index].efrl32 = efrl;
+       cf[index].addr_high = upper_32_bits(addr);
+       cf[index].addr_low = lower_32_bits(addr);
+}
+
+static struct fsl_re_desc *fsl_re_init_desc(struct fsl_re_chan *re_chan,
+                                           struct fsl_re_desc *desc,
+                                           void *cf, dma_addr_t paddr)
+{
+       desc->re_chan = re_chan;
+       desc->async_tx.tx_submit = fsl_re_tx_submit;
+       dma_async_tx_descriptor_init(&desc->async_tx, &re_chan->chan);
+       INIT_LIST_HEAD(&desc->node);
+
+       desc->hwdesc.fmt32 = FSL_RE_FRAME_FORMAT << FSL_RE_HWDESC_FMT_SHIFT;
+       desc->hwdesc.lbea32 = upper_32_bits(paddr);
+       desc->hwdesc.addr_low = lower_32_bits(paddr);
+       desc->cf_addr = cf;
+       desc->cf_paddr = paddr;
+
+       desc->cdb_addr = (void *)(cf + FSL_RE_CF_DESC_SIZE);
+       desc->cdb_paddr = paddr + FSL_RE_CF_DESC_SIZE;
+
+       return desc;
+}
+
+static struct fsl_re_desc *fsl_re_chan_alloc_desc(struct fsl_re_chan *re_chan,
+                                                 unsigned long flags)
+{
+       struct fsl_re_desc *desc = NULL;
+       void *cf;
+       dma_addr_t paddr;
+       unsigned long lock_flag;
+
+       fsl_re_cleanup_descs(re_chan);
+
+       spin_lock_irqsave(&re_chan->desc_lock, lock_flag);
+       if (!list_empty(&re_chan->free_q)) {
+               /* take one desc from free_q */
+               desc = list_first_entry(&re_chan->free_q,
+                                       struct fsl_re_desc, node);
+               list_del(&desc->node);
+
+               desc->async_tx.flags = flags;
+       }
+       spin_unlock_irqrestore(&re_chan->desc_lock, lock_flag);
+
+       if (!desc) {
+               desc = kzalloc(sizeof(*desc), GFP_NOWAIT);
+               if (!desc)
+                       return NULL;
+
+               cf = dma_pool_alloc(re_chan->re_dev->cf_desc_pool, GFP_NOWAIT,
+                                   &paddr);
+               if (!cf) {
+                       kfree(desc);
+                       return NULL;
+               }
+
+               desc = fsl_re_init_desc(re_chan, desc, cf, paddr);
+               desc->async_tx.flags = flags;
+
+               spin_lock_irqsave(&re_chan->desc_lock, lock_flag);
+               re_chan->alloc_count++;
+               spin_unlock_irqrestore(&re_chan->desc_lock, lock_flag);
+       }
+
+       return desc;
+}
+
+static struct dma_async_tx_descriptor *fsl_re_prep_dma_genq(
+               struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src,
+               unsigned int src_cnt, const unsigned char *scf, size_t len,
+               unsigned long flags)
+{
+       struct fsl_re_chan *re_chan;
+       struct fsl_re_desc *desc;
+       struct fsl_re_xor_cdb *xor;
+       struct fsl_re_cmpnd_frame *cf;
+       u32 cdb;
+       unsigned int i, j;
+       unsigned int save_src_cnt = src_cnt;
+       int cont_q = 0;
+
+       re_chan = container_of(chan, struct fsl_re_chan, chan);
+       if (len > FSL_RE_MAX_DATA_LEN) {
+               dev_err(re_chan->dev, "genq tx length %lu, max length %d\n",
+                       len, FSL_RE_MAX_DATA_LEN);
+               return NULL;
+       }
+
+       desc = fsl_re_chan_alloc_desc(re_chan, flags);
+       if (desc <= 0)
+               return NULL;
+
+       if (scf && (flags & DMA_PREP_CONTINUE)) {
+               cont_q = 1;
+               src_cnt += 1;
+       }
+
+       /* Filling xor CDB */
+       cdb = FSL_RE_XOR_OPCODE << FSL_RE_CDB_OPCODE_SHIFT;
+       cdb |= (src_cnt - 1) << FSL_RE_CDB_NRCS_SHIFT;
+       cdb |= FSL_RE_BLOCK_SIZE << FSL_RE_CDB_BLKSIZE_SHIFT;
+       cdb |= FSL_RE_INTR_ON_ERROR << FSL_RE_CDB_ERROR_SHIFT;
+       cdb |= FSL_RE_DATA_DEP << FSL_RE_CDB_DEPEND_SHIFT;
+       xor = desc->cdb_addr;
+       xor->cdb32 = cdb;
+
+       if (scf) {
+               /* compute q = src0*coef0^src1*coef1^..., * is GF(8) mult */
+               for (i = 0; i < save_src_cnt; i++)
+                       xor->gfm[i] = scf[i];
+               if (cont_q)
+                       xor->gfm[i++] = 1;
+       } else {
+               /* compute P, that is XOR all srcs */
+               for (i = 0; i < src_cnt; i++)
+                       xor->gfm[i] = 1;
+       }
+
+       /* Filling frame 0 of compound frame descriptor with CDB */
+       cf = desc->cf_addr;
+       fill_cfd_frame(cf, 0, sizeof(*xor), desc->cdb_paddr, 0);
+
+       /* Fill CFD's 1st frame with dest buffer */
+       fill_cfd_frame(cf, 1, len, dest, 0);
+
+       /* Fill CFD's rest of the frames with source buffers */
+       for (i = 2, j = 0; j < save_src_cnt; i++, j++)
+               fill_cfd_frame(cf, i, len, src[j], 0);
+
+       if (cont_q)
+               fill_cfd_frame(cf, i++, len, dest, 0);
+
+       /* Setting the final bit in the last source buffer frame in CFD */
+       cf[i - 1].efrl32 |= 1 << FSL_RE_CF_FINAL_SHIFT;
+
+       return &desc->async_tx;
+}
+
+/*
+ * Prep function for P parity calculation.In RAID Engine terminology,
+ * XOR calculation is called GenQ calculation done through GenQ command
+ */
+static struct dma_async_tx_descriptor *fsl_re_prep_dma_xor(
+               struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src,
+               unsigned int src_cnt, size_t len, unsigned long flags)
+{
+       /* NULL let genq take all coef as 1 */
+       return fsl_re_prep_dma_genq(chan, dest, src, src_cnt, NULL, len, flags);
+}
+
+/*
+ * Prep function for P/Q parity calculation.In RAID Engine terminology,
+ * P/Q calculation is called GenQQ done through GenQQ command
+ */
+static struct dma_async_tx_descriptor *fsl_re_prep_dma_pq(
+               struct dma_chan *chan, dma_addr_t *dest, dma_addr_t *src,
+               unsigned int src_cnt, const unsigned char *scf, size_t len,
+               unsigned long flags)
+{
+       struct fsl_re_chan *re_chan;
+       struct fsl_re_desc *desc;
+       struct fsl_re_pq_cdb *pq;
+       struct fsl_re_cmpnd_frame *cf;
+       u32 cdb;
+       u8 *p;
+       int gfmq_len, i, j;
+       unsigned int save_src_cnt = src_cnt;
+
+       re_chan = container_of(chan, struct fsl_re_chan, chan);
+       if (len > FSL_RE_MAX_DATA_LEN) {
+               dev_err(re_chan->dev, "pq tx length is %lu, max length is %d\n",
+                       len, FSL_RE_MAX_DATA_LEN);
+               return NULL;
+       }
+
+       /*
+        * RE requires at least 2 sources, if given only one source, we pass the
+        * second source same as the first one.
+        * With only one source, generating P is meaningless, only generate Q.
+        */
+       if (src_cnt == 1) {
+               struct dma_async_tx_descriptor *tx;
+               dma_addr_t dma_src[2];
+               unsigned char coef[2];
+
+               dma_src[0] = *src;
+               coef[0] = *scf;
+               dma_src[1] = *src;
+               coef[1] = 0;
+               tx = fsl_re_prep_dma_genq(chan, dest[1], dma_src, 2, coef, len,
+                                         flags);
+               if (tx)
+                       desc = to_fsl_re_dma_desc(tx);
+
+               return tx;
+       }
+
+       /*
+        * During RAID6 array creation, Linux's MD layer gets P and Q
+        * calculated separately in two steps. But our RAID Engine has
+        * the capability to calculate both P and Q with a single command
+        * Hence to merge well with MD layer, we need to provide a hook
+        * here and call re_jq_prep_dma_genq() function
+        */
+
+       if (flags & DMA_PREP_PQ_DISABLE_P)
+               return fsl_re_prep_dma_genq(chan, dest[1], src, src_cnt,
+                               scf, len, flags);
+
+       if (flags & DMA_PREP_CONTINUE)
+               src_cnt += 3;
+
+       desc = fsl_re_chan_alloc_desc(re_chan, flags);
+       if (desc <= 0)
+               return NULL;
+
+       /* Filling GenQQ CDB */
+       cdb = FSL_RE_PQ_OPCODE << FSL_RE_CDB_OPCODE_SHIFT;
+       cdb |= (src_cnt - 1) << FSL_RE_CDB_NRCS_SHIFT;
+       cdb |= FSL_RE_BLOCK_SIZE << FSL_RE_CDB_BLKSIZE_SHIFT;
+       cdb |= FSL_RE_BUFFER_OUTPUT << FSL_RE_CDB_BUFFER_SHIFT;
+       cdb |= FSL_RE_DATA_DEP << FSL_RE_CDB_DEPEND_SHIFT;
+
+       pq = desc->cdb_addr;
+       pq->cdb32 = cdb;
+
+       p = pq->gfm_q1;
+       /* Init gfm_q1[] */
+       for (i = 0; i < src_cnt; i++)
+               p[i] = 1;
+
+       /* Align gfm[] to 32bit */
+       gfmq_len = ALIGN(src_cnt, 4);
+
+       /* Init gfm_q2[] */
+       p += gfmq_len;
+       for (i = 0; i < src_cnt; i++)
+               p[i] = scf[i];
+
+       /* Filling frame 0 of compound frame descriptor with CDB */
+       cf = desc->cf_addr;
+       fill_cfd_frame(cf, 0, sizeof(struct fsl_re_pq_cdb), desc->cdb_paddr, 0);
+
+       /* Fill CFD's 1st & 2nd frame with dest buffers */
+       for (i = 1, j = 0; i < 3; i++, j++)
+               fill_cfd_frame(cf, i, len, dest[j], 0);
+
+       /* Fill CFD's rest of the frames with source buffers */
+       for (i = 3, j = 0; j < save_src_cnt; i++, j++)
+               fill_cfd_frame(cf, i, len, src[j], 0);
+
+       /* PQ computation continuation */
+       if (flags & DMA_PREP_CONTINUE) {
+               if (src_cnt - save_src_cnt == 3) {
+                       p[save_src_cnt] = 0;
+                       p[save_src_cnt + 1] = 0;
+                       p[save_src_cnt + 2] = 1;
+                       fill_cfd_frame(cf, i++, len, dest[0], 0);
+                       fill_cfd_frame(cf, i++, len, dest[1], 0);
+                       fill_cfd_frame(cf, i++, len, dest[1], 0);
+               } else {
+                       dev_err(re_chan->dev, "PQ tx continuation error!\n");
+                       return NULL;
+               }
+       }
+
+       /* Setting the final bit in the last source buffer frame in CFD */
+       cf[i - 1].efrl32 |= 1 << FSL_RE_CF_FINAL_SHIFT;
+
+       return &desc->async_tx;
+}
+
+/*
+ * Prep function for memcpy. In RAID Engine, memcpy is done through MOVE
+ * command. Logic of this function will need to be modified once multipage
+ * support is added in Linux's MD/ASYNC Layer
+ */
+static struct dma_async_tx_descriptor *fsl_re_prep_dma_memcpy(
+               struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
+               size_t len, unsigned long flags)
+{
+       struct fsl_re_chan *re_chan;
+       struct fsl_re_desc *desc;
+       size_t length;
+       struct fsl_re_cmpnd_frame *cf;
+       struct fsl_re_move_cdb *move;
+       u32 cdb;
+
+       re_chan = container_of(chan, struct fsl_re_chan, chan);
+
+       if (len > FSL_RE_MAX_DATA_LEN) {
+               dev_err(re_chan->dev, "cp tx length is %lu, max length is %d\n",
+                       len, FSL_RE_MAX_DATA_LEN);
+               return NULL;
+       }
+
+       desc = fsl_re_chan_alloc_desc(re_chan, flags);
+       if (desc <= 0)
+               return NULL;
+
+       /* Filling move CDB */
+       cdb = FSL_RE_MOVE_OPCODE << FSL_RE_CDB_OPCODE_SHIFT;
+       cdb |= FSL_RE_BLOCK_SIZE << FSL_RE_CDB_BLKSIZE_SHIFT;
+       cdb |= FSL_RE_INTR_ON_ERROR << FSL_RE_CDB_ERROR_SHIFT;
+       cdb |= FSL_RE_DATA_DEP << FSL_RE_CDB_DEPEND_SHIFT;
+
+       move = desc->cdb_addr;
+       move->cdb32 = cdb;
+
+       /* Filling frame 0 of CFD with move CDB */
+       cf = desc->cf_addr;
+       fill_cfd_frame(cf, 0, sizeof(*move), desc->cdb_paddr, 0);
+
+       length = min_t(size_t, len, FSL_RE_MAX_DATA_LEN);
+
+       /* Fill CFD's 1st frame with dest buffer */
+       fill_cfd_frame(cf, 1, length, dest, 0);
+
+       /* Fill CFD's 2nd frame with src buffer */
+       fill_cfd_frame(cf, 2, length, src, 1);
+
+       return &desc->async_tx;
+}
+
+static int fsl_re_alloc_chan_resources(struct dma_chan *chan)
+{
+       struct fsl_re_chan *re_chan;
+       struct fsl_re_desc *desc;
+       void *cf;
+       dma_addr_t paddr;
+       int i;
+
+       re_chan = container_of(chan, struct fsl_re_chan, chan);
+       for (i = 0; i < FSL_RE_MIN_DESCS; i++) {
+               desc = kzalloc(sizeof(*desc), GFP_KERNEL);
+               if (!desc)
+                       break;
+
+               cf = dma_pool_alloc(re_chan->re_dev->cf_desc_pool, GFP_KERNEL,
+                                   &paddr);
+               if (!cf) {
+                       kfree(desc);
+                       break;
+               }
+
+               INIT_LIST_HEAD(&desc->node);
+               fsl_re_init_desc(re_chan, desc, cf, paddr);
+
+               list_add_tail(&desc->node, &re_chan->free_q);
+               re_chan->alloc_count++;
+       }
+       return re_chan->alloc_count;
+}
+
+static void fsl_re_free_chan_resources(struct dma_chan *chan)
+{
+       struct fsl_re_chan *re_chan;
+       struct fsl_re_desc *desc;
+
+       re_chan = container_of(chan, struct fsl_re_chan, chan);
+       while (re_chan->alloc_count--) {
+               desc = list_first_entry(&re_chan->free_q,
+                                       struct fsl_re_desc,
+                                       node);
+
+               list_del(&desc->node);
+               dma_pool_free(re_chan->re_dev->cf_desc_pool, desc->cf_addr,
+                             desc->cf_paddr);
+               kfree(desc);
+       }
+
+       if (!list_empty(&re_chan->free_q))
+               dev_err(re_chan->dev, "chan resource cannot be cleaned!\n");
+}
+
+static int fsl_re_chan_probe(struct platform_device *ofdev,
+                     struct device_node *np, u8 q, u32 off)
+{
+       struct device *dev, *chandev;
+       struct fsl_re_drv_private *re_priv;
+       struct fsl_re_chan *chan;
+       struct dma_device *dma_dev;
+       u32 ptr;
+       u32 status;
+       int ret = 0, rc;
+       struct platform_device *chan_ofdev;
+
+       dev = &ofdev->dev;
+       re_priv = dev_get_drvdata(dev);
+       dma_dev = &re_priv->dma_dev;
+
+       chan = devm_kzalloc(dev, sizeof(*chan), GFP_KERNEL);
+       if (!chan)
+               return -ENOMEM;
+
+       /* create platform device for chan node */
+       chan_ofdev = of_platform_device_create(np, NULL, dev);
+       if (!chan_ofdev) {
+               dev_err(dev, "Not able to create ofdev for jr %d\n", q);
+               ret = -EINVAL;
+               goto err_free;
+       }
+
+       /* read reg property from dts */
+       rc = of_property_read_u32(np, "reg", &ptr);
+       if (rc) {
+               dev_err(dev, "Reg property not found in jr %d\n", q);
+               ret = -ENODEV;
+               goto err_free;
+       }
+
+       chan->jrregs = (struct fsl_re_chan_cfg *)((u8 *)re_priv->re_regs +
+                       off + ptr);
+
+       /* read irq property from dts */
+       chan->irq = irq_of_parse_and_map(np, 0);
+       if (chan->irq == NO_IRQ) {
+               dev_err(dev, "No IRQ defined for JR %d\n", q);
+               ret = -ENODEV;
+               goto err_free;
+       }
+
+       snprintf(chan->name, sizeof(chan->name), "re_jr%02d", q);
+
+       chandev = &chan_ofdev->dev;
+       tasklet_init(&chan->irqtask, fsl_re_dequeue, (unsigned long)chandev);
+
+       ret = request_irq(chan->irq, fsl_re_isr, 0, chan->name, chandev);
+       if (ret) {
+               dev_err(dev, "Unable to register interrupt for JR %d\n", q);
+               ret = -EINVAL;
+               goto err_free;
+       }
+
+       re_priv->re_jrs[q] = chan;
+       chan->chan.device = dma_dev;
+       chan->chan.private = chan;
+       chan->dev = chandev;
+       chan->re_dev = re_priv;
+
+       spin_lock_init(&chan->desc_lock);
+       INIT_LIST_HEAD(&chan->ack_q);
+       INIT_LIST_HEAD(&chan->active_q);
+       INIT_LIST_HEAD(&chan->submit_q);
+       INIT_LIST_HEAD(&chan->free_q);
+
+       chan->inb_ring_virt_addr = dma_pool_alloc(chan->re_dev->hw_desc_pool,
+               GFP_KERNEL, &chan->inb_phys_addr);
+       if (!chan->inb_ring_virt_addr) {
+               dev_err(dev, "No dma memory for inb_ring_virt_addr\n");
+               ret = -ENOMEM;
+               goto err_free;
+       }
+
+       chan->oub_ring_virt_addr = dma_pool_alloc(chan->re_dev->hw_desc_pool,
+               GFP_KERNEL, &chan->oub_phys_addr);
+       if (!chan->oub_ring_virt_addr) {
+               dev_err(dev, "No dma memory for oub_ring_virt_addr\n");
+               ret = -ENOMEM;
+               goto err_free_1;
+       }
+
+       /* Program the Inbound/Outbound ring base addresses and size */
+       out_be32(&chan->jrregs->inbring_base_h,
+                chan->inb_phys_addr & FSL_RE_ADDR_BIT_MASK);
+       out_be32(&chan->jrregs->oubring_base_h,
+                chan->oub_phys_addr & FSL_RE_ADDR_BIT_MASK);
+       out_be32(&chan->jrregs->inbring_base_l,
+                chan->inb_phys_addr >> FSL_RE_ADDR_BIT_SHIFT);
+       out_be32(&chan->jrregs->oubring_base_l,
+                chan->oub_phys_addr >> FSL_RE_ADDR_BIT_SHIFT);
+       out_be32(&chan->jrregs->inbring_size,
+                FSL_RE_RING_SIZE << FSL_RE_RING_SIZE_SHIFT);
+       out_be32(&chan->jrregs->oubring_size,
+                FSL_RE_RING_SIZE << FSL_RE_RING_SIZE_SHIFT);
+
+       /* Read LIODN value from u-boot */
+       status = in_be32(&chan->jrregs->jr_config_1) & FSL_RE_REG_LIODN_MASK;
+
+       /* Program the CFG reg */
+       out_be32(&chan->jrregs->jr_config_1,
+                FSL_RE_CFG1_CBSI | FSL_RE_CFG1_CBS0 | status);
+
+       dev_set_drvdata(chandev, chan);
+
+       /* Enable RE/CHAN */
+       out_be32(&chan->jrregs->jr_command, FSL_RE_ENABLE);
+
+       return 0;
+
+err_free_1:
+       dma_pool_free(chan->re_dev->hw_desc_pool, chan->inb_ring_virt_addr,
+                     chan->inb_phys_addr);
+err_free:
+       return ret;
+}
+
+/* Probe function for RAID Engine */
+static int fsl_re_probe(struct platform_device *ofdev)
+{
+       struct fsl_re_drv_private *re_priv;
+       struct device_node *np;
+       struct device_node *child;
+       u32 off;
+       u8 ridx = 0;
+       struct dma_device *dma_dev;
+       struct resource *res;
+       int rc;
+       struct device *dev = &ofdev->dev;
+
+       re_priv = devm_kzalloc(dev, sizeof(*re_priv), GFP_KERNEL);
+       if (!re_priv)
+               return -ENOMEM;
+
+       res = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENODEV;
+
+       /* IOMAP the entire RAID Engine region */
+       re_priv->re_regs = devm_ioremap(dev, res->start, resource_size(res));
+       if (!re_priv->re_regs)
+               return -EBUSY;
+
+       /* Program the RE mode */
+       out_be32(&re_priv->re_regs->global_config, FSL_RE_NON_DPAA_MODE);
+
+       /* Program Galois Field polynomial */
+       out_be32(&re_priv->re_regs->galois_field_config, FSL_RE_GFM_POLY);
+
+       dev_info(dev, "version %x, mode %x, gfp %x\n",
+                in_be32(&re_priv->re_regs->re_version_id),
+                in_be32(&re_priv->re_regs->global_config),
+                in_be32(&re_priv->re_regs->galois_field_config));
+
+       dma_dev = &re_priv->dma_dev;
+       dma_dev->dev = dev;
+       INIT_LIST_HEAD(&dma_dev->channels);
+       dma_set_mask(dev, DMA_BIT_MASK(40));
+
+       dma_dev->device_alloc_chan_resources = fsl_re_alloc_chan_resources;
+       dma_dev->device_tx_status = fsl_re_tx_status;
+       dma_dev->device_issue_pending = fsl_re_issue_pending;
+
+       dma_dev->max_xor = FSL_RE_MAX_XOR_SRCS;
+       dma_dev->device_prep_dma_xor = fsl_re_prep_dma_xor;
+       dma_cap_set(DMA_XOR, dma_dev->cap_mask);
+
+       dma_dev->max_pq = FSL_RE_MAX_PQ_SRCS;
+       dma_dev->device_prep_dma_pq = fsl_re_prep_dma_pq;
+       dma_cap_set(DMA_PQ, dma_dev->cap_mask);
+
+       dma_dev->device_prep_dma_memcpy = fsl_re_prep_dma_memcpy;
+       dma_cap_set(DMA_MEMCPY, dma_dev->cap_mask);
+
+       dma_dev->device_free_chan_resources = fsl_re_free_chan_resources;
+
+       re_priv->total_chans = 0;
+
+       re_priv->cf_desc_pool = dmam_pool_create("fsl_re_cf_desc_pool", dev,
+                                       FSL_RE_CF_CDB_SIZE,
+                                       FSL_RE_CF_CDB_ALIGN, 0);
+
+       if (!re_priv->cf_desc_pool) {
+               dev_err(dev, "No memory for fsl re_cf desc pool\n");
+               return -ENOMEM;
+       }
+
+       re_priv->hw_desc_pool = dmam_pool_create("fsl_re_hw_desc_pool", dev,
+                       sizeof(struct fsl_re_hw_desc) * FSL_RE_RING_SIZE,
+                       FSL_RE_FRAME_ALIGN, 0);
+       if (!re_priv->hw_desc_pool) {
+               dev_err(dev, "No memory for fsl re_hw desc pool\n");
+               return -ENOMEM;
+       }
+
+       dev_set_drvdata(dev, re_priv);
+
+       /* Parse Device tree to find out the total number of JQs present */
+       for_each_compatible_node(np, NULL, "fsl,raideng-v1.0-job-queue") {
+               rc = of_property_read_u32(np, "reg", &off);
+               if (rc) {
+                       dev_err(dev, "Reg property not found in JQ node\n");
+                       return -ENODEV;
+               }
+               /* Find out the Job Rings present under each JQ */
+               for_each_child_of_node(np, child) {
+                       rc = of_device_is_compatible(child,
+                                            "fsl,raideng-v1.0-job-ring");
+                       if (rc) {
+                               fsl_re_chan_probe(ofdev, child, ridx++, off);
+                               re_priv->total_chans++;
+                       }
+               }
+       }
+
+       dma_async_device_register(dma_dev);
+
+       return 0;
+}
+
+static void fsl_re_remove_chan(struct fsl_re_chan *chan)
+{
+       dma_pool_free(chan->re_dev->hw_desc_pool, chan->inb_ring_virt_addr,
+                     chan->inb_phys_addr);
+
+       dma_pool_free(chan->re_dev->hw_desc_pool, chan->oub_ring_virt_addr,
+                     chan->oub_phys_addr);
+}
+
+static int fsl_re_remove(struct platform_device *ofdev)
+{
+       struct fsl_re_drv_private *re_priv;
+       struct device *dev;
+       int i;
+
+       dev = &ofdev->dev;
+       re_priv = dev_get_drvdata(dev);
+
+       /* Cleanup chan related memory areas */
+       for (i = 0; i < re_priv->total_chans; i++)
+               fsl_re_remove_chan(re_priv->re_jrs[i]);
+
+       /* Unregister the driver */
+       dma_async_device_unregister(&re_priv->dma_dev);
+
+       return 0;
+}
+
+static struct of_device_id fsl_re_ids[] = {
+       { .compatible = "fsl,raideng-v1.0", },
+       {}
+};
+
+static struct platform_driver fsl_re_driver = {
+       .driver = {
+               .name = "fsl-raideng",
+               .owner = THIS_MODULE,
+               .of_match_table = fsl_re_ids,
+       },
+       .probe = fsl_re_probe,
+       .remove = fsl_re_remove,
+};
+
+module_platform_driver(fsl_re_driver);
+
+MODULE_AUTHOR("Harninder Rai <harninder.rai@freescale.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Freescale RAID Engine Device Driver");
diff --git a/drivers/dma/fsl_raid.h b/drivers/dma/fsl_raid.h
new file mode 100644 (file)
index 0000000..69d743c
--- /dev/null
@@ -0,0 +1,306 @@
+/*
+ * drivers/dma/fsl_raid.h
+ *
+ * Freescale RAID Engine device driver
+ *
+ * Author:
+ *     Harninder Rai <harninder.rai@freescale.com>
+ *     Naveen Burmi <naveenburmi@freescale.com>
+ *
+ * Rewrite:
+ *     Xuelin Shi <xuelin.shi@freescale.com>
+
+ * Copyright (c) 2010-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define FSL_RE_MAX_CHANS               4
+#define FSL_RE_DPAA_MODE               BIT(30)
+#define FSL_RE_NON_DPAA_MODE           BIT(31)
+#define FSL_RE_GFM_POLY                        0x1d000000
+#define FSL_RE_ADD_JOB(x)              ((x) << 16)
+#define FSL_RE_RMVD_JOB(x)             ((x) << 16)
+#define FSL_RE_CFG1_CBSI               0x08000000
+#define FSL_RE_CFG1_CBS0               0x00080000
+#define FSL_RE_SLOT_FULL_SHIFT         8
+#define FSL_RE_SLOT_FULL(x)            ((x) >> FSL_RE_SLOT_FULL_SHIFT)
+#define FSL_RE_SLOT_AVAIL_SHIFT                8
+#define FSL_RE_SLOT_AVAIL(x)           ((x) >> FSL_RE_SLOT_AVAIL_SHIFT)
+#define FSL_RE_PQ_OPCODE               0x1B
+#define FSL_RE_XOR_OPCODE              0x1A
+#define FSL_RE_MOVE_OPCODE             0x8
+#define FSL_RE_FRAME_ALIGN             16
+#define FSL_RE_BLOCK_SIZE              0x3 /* 4096 bytes */
+#define FSL_RE_CACHEABLE_IO            0x0
+#define FSL_RE_BUFFER_OUTPUT           0x0
+#define FSL_RE_INTR_ON_ERROR           0x1
+#define FSL_RE_DATA_DEP                        0x1
+#define FSL_RE_ENABLE_DPI              0x0
+#define FSL_RE_RING_SIZE               0x400
+#define FSL_RE_RING_SIZE_MASK          (FSL_RE_RING_SIZE - 1)
+#define FSL_RE_RING_SIZE_SHIFT         8
+#define FSL_RE_ADDR_BIT_SHIFT          4
+#define FSL_RE_ADDR_BIT_MASK           (BIT(FSL_RE_ADDR_BIT_SHIFT) - 1)
+#define FSL_RE_ERROR                   0x40000000
+#define FSL_RE_INTR                    0x80000000
+#define FSL_RE_CLR_INTR                        0x80000000
+#define FSL_RE_PAUSE                   0x80000000
+#define FSL_RE_ENABLE                  0x80000000
+#define FSL_RE_REG_LIODN_MASK          0x00000FFF
+
+#define FSL_RE_CDB_OPCODE_MASK         0xF8000000
+#define FSL_RE_CDB_OPCODE_SHIFT                27
+#define FSL_RE_CDB_EXCLEN_MASK         0x03000000
+#define FSL_RE_CDB_EXCLEN_SHIFT                24
+#define FSL_RE_CDB_EXCLQ1_MASK         0x00F00000
+#define FSL_RE_CDB_EXCLQ1_SHIFT                20
+#define FSL_RE_CDB_EXCLQ2_MASK         0x000F0000
+#define FSL_RE_CDB_EXCLQ2_SHIFT                16
+#define FSL_RE_CDB_BLKSIZE_MASK                0x0000C000
+#define FSL_RE_CDB_BLKSIZE_SHIFT       14
+#define FSL_RE_CDB_CACHE_MASK          0x00003000
+#define FSL_RE_CDB_CACHE_SHIFT         12
+#define FSL_RE_CDB_BUFFER_MASK         0x00000800
+#define FSL_RE_CDB_BUFFER_SHIFT                11
+#define FSL_RE_CDB_ERROR_MASK          0x00000400
+#define FSL_RE_CDB_ERROR_SHIFT         10
+#define FSL_RE_CDB_NRCS_MASK           0x0000003C
+#define FSL_RE_CDB_NRCS_SHIFT          6
+#define FSL_RE_CDB_DEPEND_MASK         0x00000008
+#define FSL_RE_CDB_DEPEND_SHIFT                3
+#define FSL_RE_CDB_DPI_MASK            0x00000004
+#define FSL_RE_CDB_DPI_SHIFT           2
+
+/*
+ * the largest cf block is 19*sizeof(struct cmpnd_frame), which is 304 bytes.
+ * here 19 = 1(cdb)+2(dest)+16(src), align to 64bytes, that is 320 bytes.
+ * the largest cdb block: struct pq_cdb which is 180 bytes, adding to cf block
+ * 320+180=500, align to 64bytes, that is 512 bytes.
+ */
+#define FSL_RE_CF_DESC_SIZE            320
+#define FSL_RE_CF_CDB_SIZE             512
+#define FSL_RE_CF_CDB_ALIGN            64
+
+struct fsl_re_ctrl {
+       /* General Configuration Registers */
+       __be32 global_config;   /* Global Configuration Register */
+       u8     rsvd1[4];
+       __be32 galois_field_config; /* Galois Field Configuration Register */
+       u8     rsvd2[4];
+       __be32 jq_wrr_config;   /* WRR Configuration register */
+       u8     rsvd3[4];
+       __be32 crc_config;      /* CRC Configuration register */
+       u8     rsvd4[228];
+       __be32 system_reset;    /* System Reset Register */
+       u8     rsvd5[252];
+       __be32 global_status;   /* Global Status Register */
+       u8     rsvd6[832];
+       __be32 re_liodn_base;   /* LIODN Base Register */
+       u8     rsvd7[1712];
+       __be32 re_version_id;   /* Version ID register of RE */
+       __be32 re_version_id_2; /* Version ID 2 register of RE */
+       u8     rsvd8[512];
+       __be32 host_config;     /* Host I/F Configuration Register */
+};
+
+struct fsl_re_chan_cfg {
+       /* Registers for JR interface */
+       __be32 jr_config_0;     /* Job Queue Configuration 0 Register */
+       __be32 jr_config_1;     /* Job Queue Configuration 1 Register */
+       __be32 jr_interrupt_status; /* Job Queue Interrupt Status Register */
+       u8     rsvd1[4];
+       __be32 jr_command;      /* Job Queue Command Register */
+       u8     rsvd2[4];
+       __be32 jr_status;       /* Job Queue Status Register */
+       u8     rsvd3[228];
+
+       /* Input Ring */
+       __be32 inbring_base_h;  /* Inbound Ring Base Address Register - High */
+       __be32 inbring_base_l;  /* Inbound Ring Base Address Register - Low */
+       __be32 inbring_size;    /* Inbound Ring Size Register */
+       u8     rsvd4[4];
+       __be32 inbring_slot_avail; /* Inbound Ring Slot Available Register */
+       u8     rsvd5[4];
+       __be32 inbring_add_job; /* Inbound Ring Add Job Register */
+       u8     rsvd6[4];
+       __be32 inbring_cnsmr_indx; /* Inbound Ring Consumer Index Register */
+       u8     rsvd7[220];
+
+       /* Output Ring */
+       __be32 oubring_base_h;  /* Outbound Ring Base Address Register - High */
+       __be32 oubring_base_l;  /* Outbound Ring Base Address Register - Low */
+       __be32 oubring_size;    /* Outbound Ring Size Register */
+       u8     rsvd8[4];
+       __be32 oubring_job_rmvd; /* Outbound Ring Job Removed Register */
+       u8     rsvd9[4];
+       __be32 oubring_slot_full; /* Outbound Ring Slot Full Register */
+       u8     rsvd10[4];
+       __be32 oubring_prdcr_indx; /* Outbound Ring Producer Index */
+};
+
+/*
+ * Command Descriptor Block (CDB) for unicast move command.
+ * In RAID Engine terms, memcpy is done through move command
+ */
+struct fsl_re_move_cdb {
+       __be32 cdb32;
+};
+
+/* Data protection/integrity related fields */
+#define FSL_RE_DPI_APPS_MASK           0xC0000000
+#define FSL_RE_DPI_APPS_SHIFT          30
+#define FSL_RE_DPI_REF_MASK            0x30000000
+#define FSL_RE_DPI_REF_SHIFT           28
+#define FSL_RE_DPI_GUARD_MASK          0x0C000000
+#define FSL_RE_DPI_GUARD_SHIFT         26
+#define FSL_RE_DPI_ATTR_MASK           0x03000000
+#define FSL_RE_DPI_ATTR_SHIFT          24
+#define FSL_RE_DPI_META_MASK           0x0000FFFF
+
+struct fsl_re_dpi {
+       __be32 dpi32;
+       __be32 ref;
+};
+
+/*
+ * CDB for GenQ command. In RAID Engine terminology, XOR is
+ * done through this command
+ */
+struct fsl_re_xor_cdb {
+       __be32 cdb32;
+       u8 gfm[16];
+       struct fsl_re_dpi dpi_dest_spec;
+       struct fsl_re_dpi dpi_src_spec[16];
+};
+
+/* CDB for no-op command */
+struct fsl_re_noop_cdb {
+       __be32 cdb32;
+};
+
+/*
+ * CDB for GenQQ command. In RAID Engine terminology, P/Q is
+ * done through this command
+ */
+struct fsl_re_pq_cdb {
+       __be32 cdb32;
+       u8 gfm_q1[16];
+       u8 gfm_q2[16];
+       struct fsl_re_dpi dpi_dest_spec[2];
+       struct fsl_re_dpi dpi_src_spec[16];
+};
+
+/* Compound frame */
+#define FSL_RE_CF_ADDR_HIGH_MASK       0x000000FF
+#define FSL_RE_CF_EXT_MASK             0x80000000
+#define FSL_RE_CF_EXT_SHIFT            31
+#define FSL_RE_CF_FINAL_MASK           0x40000000
+#define FSL_RE_CF_FINAL_SHIFT          30
+#define FSL_RE_CF_LENGTH_MASK          0x000FFFFF
+#define FSL_RE_CF_BPID_MASK            0x00FF0000
+#define FSL_RE_CF_BPID_SHIFT           16
+#define FSL_RE_CF_OFFSET_MASK          0x00001FFF
+
+struct fsl_re_cmpnd_frame {
+       __be32 addr_high;
+       __be32 addr_low;
+       __be32 efrl32;
+       __be32 rbro32;
+};
+
+/* Frame descriptor */
+#define FSL_RE_HWDESC_LIODN_MASK       0x3F000000
+#define FSL_RE_HWDESC_LIODN_SHIFT      24
+#define FSL_RE_HWDESC_BPID_MASK                0x00FF0000
+#define FSL_RE_HWDESC_BPID_SHIFT       16
+#define FSL_RE_HWDESC_ELIODN_MASK      0x0000F000
+#define FSL_RE_HWDESC_ELIODN_SHIFT     12
+#define FSL_RE_HWDESC_FMT_SHIFT                29
+#define FSL_RE_HWDESC_FMT_MASK         (0x3 << FSL_RE_HWDESC_FMT_SHIFT)
+
+struct fsl_re_hw_desc {
+       __be32 lbea32;
+       __be32 addr_low;
+       __be32 fmt32;
+       __be32 status;
+};
+
+/* Raid Engine device private data */
+struct fsl_re_drv_private {
+       u8 total_chans;
+       struct dma_device dma_dev;
+       struct fsl_re_ctrl *re_regs;
+       struct fsl_re_chan *re_jrs[FSL_RE_MAX_CHANS];
+       struct dma_pool *cf_desc_pool;
+       struct dma_pool *hw_desc_pool;
+};
+
+/* Per job ring data structure */
+struct fsl_re_chan {
+       char name[16];
+       spinlock_t desc_lock; /* queue lock */
+       struct list_head ack_q;  /* wait to acked queue */
+       struct list_head active_q; /* already issued on hw, not completed */
+       struct list_head submit_q;
+       struct list_head free_q; /* alloc available queue */
+       struct device *dev;
+       struct fsl_re_drv_private *re_dev;
+       struct dma_chan chan;
+       struct fsl_re_chan_cfg *jrregs;
+       int irq;
+       struct tasklet_struct irqtask;
+       u32 alloc_count;
+
+       /* hw descriptor ring for inbound queue*/
+       dma_addr_t inb_phys_addr;
+       struct fsl_re_hw_desc *inb_ring_virt_addr;
+       u32 inb_count;
+
+       /* hw descriptor ring for outbound queue */
+       dma_addr_t oub_phys_addr;
+       struct fsl_re_hw_desc *oub_ring_virt_addr;
+       u32 oub_count;
+};
+
+/* Async transaction descriptor */
+struct fsl_re_desc {
+       struct dma_async_tx_descriptor async_tx;
+       struct list_head node;
+       struct fsl_re_hw_desc hwdesc;
+       struct fsl_re_chan *re_chan;
+
+       /* hwdesc will point to cf_addr */
+       void *cf_addr;
+       dma_addr_t cf_paddr;
+
+       void *cdb_addr;
+       dma_addr_t cdb_paddr;
+       int status;
+};
diff --git a/drivers/dma/hsu/Kconfig b/drivers/dma/hsu/Kconfig
new file mode 100644 (file)
index 0000000..2810dca
--- /dev/null
@@ -0,0 +1,14 @@
+# DMA engine configuration for hsu
+config HSU_DMA
+       tristate
+       select DMA_ENGINE
+       select DMA_VIRTUAL_CHANNELS
+
+config HSU_DMA_PCI
+       tristate "High Speed UART DMA PCI driver"
+       depends on PCI
+       select HSU_DMA
+       help
+         Support the High Speed UART DMA on the platfroms that
+         enumerate it as a PCI device. For example, Intel Medfield
+         has integrated this HSU DMA controller.
diff --git a/drivers/dma/hsu/Makefile b/drivers/dma/hsu/Makefile
new file mode 100644 (file)
index 0000000..b8f9af0
--- /dev/null
@@ -0,0 +1,5 @@
+obj-$(CONFIG_HSU_DMA)          += hsu_dma.o
+hsu_dma-objs           := hsu.o
+
+obj-$(CONFIG_HSU_DMA_PCI)      += hsu_dma_pci.o
+hsu_dma_pci-objs       := pci.o
diff --git a/drivers/dma/hsu/hsu.c b/drivers/dma/hsu/hsu.c
new file mode 100644 (file)
index 0000000..9b84def
--- /dev/null
@@ -0,0 +1,495 @@
+/*
+ * Core driver for the High Speed UART DMA
+ *
+ * Copyright (C) 2015 Intel Corporation
+ * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+ *
+ * Partially based on the bits found in drivers/tty/serial/mfd.c.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * DMA channel allocation:
+ * 1. Even number chans are used for DMA Read (UART TX), odd chans for DMA
+ *    Write (UART RX).
+ * 2. 0/1 channel are assigned to port 0, 2/3 chan to port 1, 4/5 chan to
+ *    port 3, and so on.
+ */
+
+#include <linux/delay.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "hsu.h"
+
+#define HSU_DMA_BUSWIDTHS                              \
+       BIT(DMA_SLAVE_BUSWIDTH_UNDEFINED)       |       \
+       BIT(DMA_SLAVE_BUSWIDTH_1_BYTE)          |       \
+       BIT(DMA_SLAVE_BUSWIDTH_2_BYTES)         |       \
+       BIT(DMA_SLAVE_BUSWIDTH_3_BYTES)         |       \
+       BIT(DMA_SLAVE_BUSWIDTH_4_BYTES)         |       \
+       BIT(DMA_SLAVE_BUSWIDTH_8_BYTES)         |       \
+       BIT(DMA_SLAVE_BUSWIDTH_16_BYTES)
+
+static inline void hsu_chan_disable(struct hsu_dma_chan *hsuc)
+{
+       hsu_chan_writel(hsuc, HSU_CH_CR, 0);
+}
+
+static inline void hsu_chan_enable(struct hsu_dma_chan *hsuc)
+{
+       u32 cr = HSU_CH_CR_CHA;
+
+       if (hsuc->direction == DMA_MEM_TO_DEV)
+               cr &= ~HSU_CH_CR_CHD;
+       else if (hsuc->direction == DMA_DEV_TO_MEM)
+               cr |= HSU_CH_CR_CHD;
+
+       hsu_chan_writel(hsuc, HSU_CH_CR, cr);
+}
+
+static void hsu_dma_chan_start(struct hsu_dma_chan *hsuc)
+{
+       struct dma_slave_config *config = &hsuc->config;
+       struct hsu_dma_desc *desc = hsuc->desc;
+       u32 bsr = 0, mtsr = 0;  /* to shut the compiler up */
+       u32 dcr = HSU_CH_DCR_CHSOE | HSU_CH_DCR_CHEI;
+       unsigned int i, count;
+
+       if (hsuc->direction == DMA_MEM_TO_DEV) {
+               bsr = config->dst_maxburst;
+               mtsr = config->dst_addr_width;
+       } else if (hsuc->direction == DMA_DEV_TO_MEM) {
+               bsr = config->src_maxburst;
+               mtsr = config->src_addr_width;
+       }
+
+       hsu_chan_disable(hsuc);
+
+       hsu_chan_writel(hsuc, HSU_CH_DCR, 0);
+       hsu_chan_writel(hsuc, HSU_CH_BSR, bsr);
+       hsu_chan_writel(hsuc, HSU_CH_MTSR, mtsr);
+
+       /* Set descriptors */
+       count = (desc->nents - desc->active) % HSU_DMA_CHAN_NR_DESC;
+       for (i = 0; i < count; i++) {
+               hsu_chan_writel(hsuc, HSU_CH_DxSAR(i), desc->sg[i].addr);
+               hsu_chan_writel(hsuc, HSU_CH_DxTSR(i), desc->sg[i].len);
+
+               /* Prepare value for DCR */
+               dcr |= HSU_CH_DCR_DESCA(i);
+               dcr |= HSU_CH_DCR_CHTOI(i);     /* timeout bit, see HSU Errata 1 */
+
+               desc->active++;
+       }
+       /* Only for the last descriptor in the chain */
+       dcr |= HSU_CH_DCR_CHSOD(count - 1);
+       dcr |= HSU_CH_DCR_CHDI(count - 1);
+
+       hsu_chan_writel(hsuc, HSU_CH_DCR, dcr);
+
+       hsu_chan_enable(hsuc);
+}
+
+static void hsu_dma_stop_channel(struct hsu_dma_chan *hsuc)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&hsuc->lock, flags);
+       hsu_chan_disable(hsuc);
+       hsu_chan_writel(hsuc, HSU_CH_DCR, 0);
+       spin_unlock_irqrestore(&hsuc->lock, flags);
+}
+
+static void hsu_dma_start_channel(struct hsu_dma_chan *hsuc)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&hsuc->lock, flags);
+       hsu_dma_chan_start(hsuc);
+       spin_unlock_irqrestore(&hsuc->lock, flags);
+}
+
+static void hsu_dma_start_transfer(struct hsu_dma_chan *hsuc)
+{
+       struct virt_dma_desc *vdesc;
+
+       /* Get the next descriptor */
+       vdesc = vchan_next_desc(&hsuc->vchan);
+       if (!vdesc) {
+               hsuc->desc = NULL;
+               return;
+       }
+
+       list_del(&vdesc->node);
+       hsuc->desc = to_hsu_dma_desc(vdesc);
+
+       /* Start the channel with a new descriptor */
+       hsu_dma_start_channel(hsuc);
+}
+
+static u32 hsu_dma_chan_get_sr(struct hsu_dma_chan *hsuc)
+{
+       unsigned long flags;
+       u32 sr;
+
+       spin_lock_irqsave(&hsuc->lock, flags);
+       sr = hsu_chan_readl(hsuc, HSU_CH_SR);
+       spin_unlock_irqrestore(&hsuc->lock, flags);
+
+       return sr;
+}
+
+irqreturn_t hsu_dma_irq(struct hsu_dma_chip *chip, unsigned short nr)
+{
+       struct hsu_dma_chan *hsuc;
+       struct hsu_dma_desc *desc;
+       unsigned long flags;
+       u32 sr;
+
+       /* Sanity check */
+       if (nr >= chip->pdata->nr_channels)
+               return IRQ_NONE;
+
+       hsuc = &chip->hsu->chan[nr];
+
+       /*
+        * No matter what situation, need read clear the IRQ status
+        * There is a bug, see Errata 5, HSD 2900918
+        */
+       sr = hsu_dma_chan_get_sr(hsuc);
+       if (!sr)
+               return IRQ_NONE;
+
+       /* Timeout IRQ, need wait some time, see Errata 2 */
+       if (hsuc->direction == DMA_DEV_TO_MEM && (sr & HSU_CH_SR_DESCTO_ANY))
+               udelay(2);
+
+       sr &= ~HSU_CH_SR_DESCTO_ANY;
+       if (!sr)
+               return IRQ_HANDLED;
+
+       spin_lock_irqsave(&hsuc->vchan.lock, flags);
+       desc = hsuc->desc;
+       if (desc) {
+               if (sr & HSU_CH_SR_CHE) {
+                       desc->status = DMA_ERROR;
+               } else if (desc->active < desc->nents) {
+                       hsu_dma_start_channel(hsuc);
+               } else {
+                       vchan_cookie_complete(&desc->vdesc);
+                       desc->status = DMA_COMPLETE;
+                       hsu_dma_start_transfer(hsuc);
+               }
+       }
+       spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
+
+       return IRQ_HANDLED;
+}
+EXPORT_SYMBOL_GPL(hsu_dma_irq);
+
+static struct hsu_dma_desc *hsu_dma_alloc_desc(unsigned int nents)
+{
+       struct hsu_dma_desc *desc;
+
+       desc = kzalloc(sizeof(*desc), GFP_NOWAIT);
+       if (!desc)
+               return NULL;
+
+       desc->sg = kcalloc(nents, sizeof(*desc->sg), GFP_NOWAIT);
+       if (!desc->sg) {
+               kfree(desc);
+               return NULL;
+       }
+
+       return desc;
+}
+
+static void hsu_dma_desc_free(struct virt_dma_desc *vdesc)
+{
+       struct hsu_dma_desc *desc = to_hsu_dma_desc(vdesc);
+
+       kfree(desc->sg);
+       kfree(desc);
+}
+
+static struct dma_async_tx_descriptor *hsu_dma_prep_slave_sg(
+               struct dma_chan *chan, struct scatterlist *sgl,
+               unsigned int sg_len, enum dma_transfer_direction direction,
+               unsigned long flags, void *context)
+{
+       struct hsu_dma_chan *hsuc = to_hsu_dma_chan(chan);
+       struct hsu_dma_desc *desc;
+       struct scatterlist *sg;
+       unsigned int i;
+
+       desc = hsu_dma_alloc_desc(sg_len);
+       if (!desc)
+               return NULL;
+
+       for_each_sg(sgl, sg, sg_len, i) {
+               desc->sg[i].addr = sg_dma_address(sg);
+               desc->sg[i].len = sg_dma_len(sg);
+       }
+
+       desc->nents = sg_len;
+       desc->direction = direction;
+       /* desc->active = 0 by kzalloc */
+       desc->status = DMA_IN_PROGRESS;
+
+       return vchan_tx_prep(&hsuc->vchan, &desc->vdesc, flags);
+}
+
+static void hsu_dma_issue_pending(struct dma_chan *chan)
+{
+       struct hsu_dma_chan *hsuc = to_hsu_dma_chan(chan);
+       unsigned long flags;
+
+       spin_lock_irqsave(&hsuc->vchan.lock, flags);
+       if (vchan_issue_pending(&hsuc->vchan) && !hsuc->desc)
+               hsu_dma_start_transfer(hsuc);
+       spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
+}
+
+static size_t hsu_dma_desc_size(struct hsu_dma_desc *desc)
+{
+       size_t bytes = 0;
+       unsigned int i;
+
+       for (i = desc->active; i < desc->nents; i++)
+               bytes += desc->sg[i].len;
+
+       return bytes;
+}
+
+static size_t hsu_dma_active_desc_size(struct hsu_dma_chan *hsuc)
+{
+       struct hsu_dma_desc *desc = hsuc->desc;
+       size_t bytes = hsu_dma_desc_size(desc);
+       int i;
+       unsigned long flags;
+
+       spin_lock_irqsave(&hsuc->lock, flags);
+       i = desc->active % HSU_DMA_CHAN_NR_DESC;
+       do {
+               bytes += hsu_chan_readl(hsuc, HSU_CH_DxTSR(i));
+       } while (--i >= 0);
+       spin_unlock_irqrestore(&hsuc->lock, flags);
+
+       return bytes;
+}
+
+static enum dma_status hsu_dma_tx_status(struct dma_chan *chan,
+       dma_cookie_t cookie, struct dma_tx_state *state)
+{
+       struct hsu_dma_chan *hsuc = to_hsu_dma_chan(chan);
+       struct virt_dma_desc *vdesc;
+       enum dma_status status;
+       size_t bytes;
+       unsigned long flags;
+
+       status = dma_cookie_status(chan, cookie, state);
+       if (status == DMA_COMPLETE)
+               return status;
+
+       spin_lock_irqsave(&hsuc->vchan.lock, flags);
+       vdesc = vchan_find_desc(&hsuc->vchan, cookie);
+       if (hsuc->desc && cookie == hsuc->desc->vdesc.tx.cookie) {
+               bytes = hsu_dma_active_desc_size(hsuc);
+               dma_set_residue(state, bytes);
+               status = hsuc->desc->status;
+       } else if (vdesc) {
+               bytes = hsu_dma_desc_size(to_hsu_dma_desc(vdesc));
+               dma_set_residue(state, bytes);
+       }
+       spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
+
+       return status;
+}
+
+static int hsu_dma_slave_config(struct dma_chan *chan,
+                               struct dma_slave_config *config)
+{
+       struct hsu_dma_chan *hsuc = to_hsu_dma_chan(chan);
+
+       /* Check if chan will be configured for slave transfers */
+       if (!is_slave_direction(config->direction))
+               return -EINVAL;
+
+       memcpy(&hsuc->config, config, sizeof(hsuc->config));
+
+       return 0;
+}
+
+static void hsu_dma_chan_deactivate(struct hsu_dma_chan *hsuc)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&hsuc->lock, flags);
+       hsu_chan_disable(hsuc);
+       spin_unlock_irqrestore(&hsuc->lock, flags);
+}
+
+static void hsu_dma_chan_activate(struct hsu_dma_chan *hsuc)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&hsuc->lock, flags);
+       hsu_chan_enable(hsuc);
+       spin_unlock_irqrestore(&hsuc->lock, flags);
+}
+
+static int hsu_dma_pause(struct dma_chan *chan)
+{
+       struct hsu_dma_chan *hsuc = to_hsu_dma_chan(chan);
+       unsigned long flags;
+
+       spin_lock_irqsave(&hsuc->vchan.lock, flags);
+       if (hsuc->desc && hsuc->desc->status == DMA_IN_PROGRESS) {
+               hsu_dma_chan_deactivate(hsuc);
+               hsuc->desc->status = DMA_PAUSED;
+       }
+       spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
+
+       return 0;
+}
+
+static int hsu_dma_resume(struct dma_chan *chan)
+{
+       struct hsu_dma_chan *hsuc = to_hsu_dma_chan(chan);
+       unsigned long flags;
+
+       spin_lock_irqsave(&hsuc->vchan.lock, flags);
+       if (hsuc->desc && hsuc->desc->status == DMA_PAUSED) {
+               hsuc->desc->status = DMA_IN_PROGRESS;
+               hsu_dma_chan_activate(hsuc);
+       }
+       spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
+
+       return 0;
+}
+
+static int hsu_dma_terminate_all(struct dma_chan *chan)
+{
+       struct hsu_dma_chan *hsuc = to_hsu_dma_chan(chan);
+       unsigned long flags;
+       LIST_HEAD(head);
+
+       spin_lock_irqsave(&hsuc->vchan.lock, flags);
+
+       hsu_dma_stop_channel(hsuc);
+       hsuc->desc = NULL;
+
+       vchan_get_all_descriptors(&hsuc->vchan, &head);
+       spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
+       vchan_dma_desc_free_list(&hsuc->vchan, &head);
+
+       return 0;
+}
+
+static void hsu_dma_free_chan_resources(struct dma_chan *chan)
+{
+       vchan_free_chan_resources(to_virt_chan(chan));
+}
+
+int hsu_dma_probe(struct hsu_dma_chip *chip)
+{
+       struct hsu_dma *hsu;
+       struct hsu_dma_platform_data *pdata = chip->pdata;
+       void __iomem *addr = chip->regs + chip->offset;
+       unsigned short i;
+       int ret;
+
+       hsu = devm_kzalloc(chip->dev, sizeof(*hsu), GFP_KERNEL);
+       if (!hsu)
+               return -ENOMEM;
+
+       chip->hsu = hsu;
+
+       if (!pdata) {
+               pdata = devm_kzalloc(chip->dev, sizeof(*pdata), GFP_KERNEL);
+               if (!pdata)
+                       return -ENOMEM;
+
+               chip->pdata = pdata;
+
+               /* Guess nr_channels from the IO space length */
+               pdata->nr_channels = (chip->length - chip->offset) /
+                                    HSU_DMA_CHAN_LENGTH;
+       }
+
+       hsu->chan = devm_kcalloc(chip->dev, pdata->nr_channels,
+                                sizeof(*hsu->chan), GFP_KERNEL);
+       if (!hsu->chan)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(&hsu->dma.channels);
+       for (i = 0; i < pdata->nr_channels; i++) {
+               struct hsu_dma_chan *hsuc = &hsu->chan[i];
+
+               hsuc->vchan.desc_free = hsu_dma_desc_free;
+               vchan_init(&hsuc->vchan, &hsu->dma);
+
+               hsuc->direction = (i & 0x1) ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV;
+               hsuc->reg = addr + i * HSU_DMA_CHAN_LENGTH;
+
+               spin_lock_init(&hsuc->lock);
+       }
+
+       dma_cap_set(DMA_SLAVE, hsu->dma.cap_mask);
+       dma_cap_set(DMA_PRIVATE, hsu->dma.cap_mask);
+
+       hsu->dma.device_free_chan_resources = hsu_dma_free_chan_resources;
+
+       hsu->dma.device_prep_slave_sg = hsu_dma_prep_slave_sg;
+
+       hsu->dma.device_issue_pending = hsu_dma_issue_pending;
+       hsu->dma.device_tx_status = hsu_dma_tx_status;
+
+       hsu->dma.device_config = hsu_dma_slave_config;
+       hsu->dma.device_pause = hsu_dma_pause;
+       hsu->dma.device_resume = hsu_dma_resume;
+       hsu->dma.device_terminate_all = hsu_dma_terminate_all;
+
+       hsu->dma.src_addr_widths = HSU_DMA_BUSWIDTHS;
+       hsu->dma.dst_addr_widths = HSU_DMA_BUSWIDTHS;
+       hsu->dma.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
+       hsu->dma.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
+
+       hsu->dma.dev = chip->dev;
+
+       ret = dma_async_device_register(&hsu->dma);
+       if (ret)
+               return ret;
+
+       dev_info(chip->dev, "Found HSU DMA, %d channels\n", pdata->nr_channels);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(hsu_dma_probe);
+
+int hsu_dma_remove(struct hsu_dma_chip *chip)
+{
+       struct hsu_dma *hsu = chip->hsu;
+       unsigned short i;
+
+       dma_async_device_unregister(&hsu->dma);
+
+       for (i = 0; i < chip->pdata->nr_channels; i++) {
+               struct hsu_dma_chan *hsuc = &hsu->chan[i];
+
+               tasklet_kill(&hsuc->vchan.task);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(hsu_dma_remove);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("High Speed UART DMA core driver");
+MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
diff --git a/drivers/dma/hsu/hsu.h b/drivers/dma/hsu/hsu.h
new file mode 100644 (file)
index 0000000..0275233
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Driver for the High Speed UART DMA
+ *
+ * Copyright (C) 2015 Intel Corporation
+ *
+ * Partially based on the bits found in drivers/tty/serial/mfd.c.
+ *
+ * This program is free software; you can 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 __DMA_HSU_H__
+#define __DMA_HSU_H__
+
+#include <linux/spinlock.h>
+#include <linux/dma/hsu.h>
+
+#include "../virt-dma.h"
+
+#define HSU_CH_SR              0x00                    /* channel status */
+#define HSU_CH_CR              0x04                    /* channel control */
+#define HSU_CH_DCR             0x08                    /* descriptor control */
+#define HSU_CH_BSR             0x10                    /* FIFO buffer size */
+#define HSU_CH_MTSR            0x14                    /* minimum transfer size */
+#define HSU_CH_DxSAR(x)                (0x20 + 8 * (x))        /* desc start addr */
+#define HSU_CH_DxTSR(x)                (0x24 + 8 * (x))        /* desc transfer size */
+#define HSU_CH_D0SAR           0x20                    /* desc 0 start addr */
+#define HSU_CH_D0TSR           0x24                    /* desc 0 transfer size */
+#define HSU_CH_D1SAR           0x28
+#define HSU_CH_D1TSR           0x2c
+#define HSU_CH_D2SAR           0x30
+#define HSU_CH_D2TSR           0x34
+#define HSU_CH_D3SAR           0x38
+#define HSU_CH_D3TSR           0x3c
+
+#define HSU_DMA_CHAN_NR_DESC   4
+#define HSU_DMA_CHAN_LENGTH    0x40
+
+/* Bits in HSU_CH_SR */
+#define HSU_CH_SR_DESCTO(x)    BIT(8 + (x))
+#define HSU_CH_SR_DESCTO_ANY   (BIT(11) | BIT(10) | BIT(9) | BIT(8))
+#define HSU_CH_SR_CHE          BIT(15)
+
+/* Bits in HSU_CH_CR */
+#define HSU_CH_CR_CHA          BIT(0)
+#define HSU_CH_CR_CHD          BIT(1)
+
+/* Bits in HSU_CH_DCR */
+#define HSU_CH_DCR_DESCA(x)    BIT(0 + (x))
+#define HSU_CH_DCR_CHSOD(x)    BIT(8 + (x))
+#define HSU_CH_DCR_CHSOTO      BIT(14)
+#define HSU_CH_DCR_CHSOE       BIT(15)
+#define HSU_CH_DCR_CHDI(x)     BIT(16 + (x))
+#define HSU_CH_DCR_CHEI                BIT(23)
+#define HSU_CH_DCR_CHTOI(x)    BIT(24 + (x))
+
+struct hsu_dma_sg {
+       dma_addr_t addr;
+       unsigned int len;
+};
+
+struct hsu_dma_desc {
+       struct virt_dma_desc vdesc;
+       enum dma_transfer_direction direction;
+       struct hsu_dma_sg *sg;
+       unsigned int nents;
+       unsigned int active;
+       enum dma_status status;
+};
+
+static inline struct hsu_dma_desc *to_hsu_dma_desc(struct virt_dma_desc *vdesc)
+{
+       return container_of(vdesc, struct hsu_dma_desc, vdesc);
+}
+
+struct hsu_dma_chan {
+       struct virt_dma_chan vchan;
+
+       void __iomem *reg;
+       spinlock_t lock;
+
+       /* hardware configuration */
+       enum dma_transfer_direction direction;
+       struct dma_slave_config config;
+
+       struct hsu_dma_desc *desc;
+};
+
+static inline struct hsu_dma_chan *to_hsu_dma_chan(struct dma_chan *chan)
+{
+       return container_of(chan, struct hsu_dma_chan, vchan.chan);
+}
+
+static inline u32 hsu_chan_readl(struct hsu_dma_chan *hsuc, int offset)
+{
+       return readl(hsuc->reg + offset);
+}
+
+static inline void hsu_chan_writel(struct hsu_dma_chan *hsuc, int offset,
+                                  u32 value)
+{
+       writel(value, hsuc->reg + offset);
+}
+
+struct hsu_dma {
+       struct dma_device               dma;
+
+       /* channels */
+       struct hsu_dma_chan             *chan;
+};
+
+static inline struct hsu_dma *to_hsu_dma(struct dma_device *ddev)
+{
+       return container_of(ddev, struct hsu_dma, dma);
+}
+
+#endif /* __DMA_HSU_H__ */
diff --git a/drivers/dma/hsu/pci.c b/drivers/dma/hsu/pci.c
new file mode 100644 (file)
index 0000000..77879e6
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * PCI driver for the High Speed UART DMA
+ *
+ * Copyright (C) 2015 Intel Corporation
+ * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+ *
+ * Partially based on the bits found in drivers/tty/serial/mfd.c.
+ *
+ * This program is free software; you can 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/bitops.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include "hsu.h"
+
+#define HSU_PCI_DMASR          0x00
+#define HSU_PCI_DMAISR         0x04
+
+#define HSU_PCI_CHAN_OFFSET    0x100
+
+static irqreturn_t hsu_pci_irq(int irq, void *dev)
+{
+       struct hsu_dma_chip *chip = dev;
+       u32 dmaisr;
+       unsigned short i;
+       irqreturn_t ret = IRQ_NONE;
+
+       dmaisr = readl(chip->regs + HSU_PCI_DMAISR);
+       for (i = 0; i < chip->pdata->nr_channels; i++) {
+               if (dmaisr & 0x1)
+                       ret |= hsu_dma_irq(chip, i);
+               dmaisr >>= 1;
+       }
+
+       return ret;
+}
+
+static int hsu_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+       struct hsu_dma_chip *chip;
+       int ret;
+
+       ret = pcim_enable_device(pdev);
+       if (ret)
+               return ret;
+
+       ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev));
+       if (ret) {
+               dev_err(&pdev->dev, "I/O memory remapping failed\n");
+               return ret;
+       }
+
+       pci_set_master(pdev);
+       pci_try_set_mwi(pdev);
+
+       ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
+
+       ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
+
+       chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
+       if (!chip)
+               return -ENOMEM;
+
+       chip->dev = &pdev->dev;
+       chip->regs = pcim_iomap_table(pdev)[0];
+       chip->length = pci_resource_len(pdev, 0);
+       chip->offset = HSU_PCI_CHAN_OFFSET;
+       chip->irq = pdev->irq;
+
+       pci_enable_msi(pdev);
+
+       ret = hsu_dma_probe(chip);
+       if (ret)
+               return ret;
+
+       ret = request_irq(chip->irq, hsu_pci_irq, 0, "hsu_dma_pci", chip);
+       if (ret)
+               goto err_register_irq;
+
+       pci_set_drvdata(pdev, chip);
+
+       return 0;
+
+err_register_irq:
+       hsu_dma_remove(chip);
+       return ret;
+}
+
+static void hsu_pci_remove(struct pci_dev *pdev)
+{
+       struct hsu_dma_chip *chip = pci_get_drvdata(pdev);
+
+       free_irq(chip->irq, chip);
+       hsu_dma_remove(chip);
+}
+
+static const struct pci_device_id hsu_pci_id_table[] = {
+       { PCI_VDEVICE(INTEL, 0x081e), 0 },
+       { PCI_VDEVICE(INTEL, 0x1192), 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(pci, hsu_pci_id_table);
+
+static struct pci_driver hsu_pci_driver = {
+       .name           = "hsu_dma_pci",
+       .id_table       = hsu_pci_id_table,
+       .probe          = hsu_pci_probe,
+       .remove         = hsu_pci_remove,
+};
+
+module_pci_driver(hsu_pci_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("High Speed UART DMA PCI driver");
+MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
index ed045a9ad634a4d898967aa0d26c74d5ec4d91c2..9ca56830cc63d6d21dd3ea0c1961339680ff909c 100644 (file)
@@ -689,11 +689,6 @@ static int mdc_slave_config(struct dma_chan *chan,
        return 0;
 }
 
-static int mdc_alloc_chan_resources(struct dma_chan *chan)
-{
-       return 0;
-}
-
 static void mdc_free_chan_resources(struct dma_chan *chan)
 {
        struct mdc_chan *mchan = to_mdc_chan(chan);
@@ -910,7 +905,6 @@ static int mdc_dma_probe(struct platform_device *pdev)
        mdma->dma_dev.device_prep_slave_sg = mdc_prep_slave_sg;
        mdma->dma_dev.device_prep_dma_cyclic = mdc_prep_dma_cyclic;
        mdma->dma_dev.device_prep_dma_memcpy = mdc_prep_dma_memcpy;
-       mdma->dma_dev.device_alloc_chan_resources = mdc_alloc_chan_resources;
        mdma->dma_dev.device_free_chan_resources = mdc_free_chan_resources;
        mdma->dma_dev.device_tx_status = mdc_tx_status;
        mdma->dma_dev.device_issue_pending = mdc_issue_pending;
index 66a0efb9651d3d8f3240701fafe2299b9abca598..62bbd79338e05e26d37ead9cf0a78dbfefb84c2b 100644 (file)
@@ -1260,6 +1260,7 @@ static void sdma_issue_pending(struct dma_chan *chan)
 
 #define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1        34
 #define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V2        38
+#define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V3        41
 
 static void sdma_add_scripts(struct sdma_engine *sdma,
                const struct sdma_script_start_addrs *addr)
@@ -1306,6 +1307,9 @@ static void sdma_load_firmware(const struct firmware *fw, void *context)
        case 2:
                sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V2;
                break;
+       case 3:
+               sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V3;
+               break;
        default:
                dev_err(sdma->dev, "unknown firmware version\n");
                goto err_firmware;
index 3b55bb8d969a6e609e839e6fc5eb26f2713ffe28..ea1e107ae884bc66a19e60d6f42b8f76351513ce 100644 (file)
  * 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.
- *
  * The full GNU General Public License is included in this distribution in
  * the file called "COPYING".
  *
index 940c1502a8b58e34ec4d31d2f5ac1c5b01637018..ee0aa9f4ccfa5e98126caa69850a255ec7370c33 100644 (file)
  * 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.
- *
  * The full GNU General Public License is included in this distribution in
  * the file called "COPYING".
  *
index d63f68b1aa35de56272fafa4b37e55cf504bc184..30f5c7eede166b4b0ee290069b2d5d199ea9455f 100644 (file)
  * 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.
- *
  * The full GNU General Public License is included in this distribution in the
  * file called COPYING.
  */
index 695483e6be32971ead5d9c11b0896dae865b8966..69c7dfcad0235fd7df04ed5753707156a5ec510e 100644 (file)
  * 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.
- *
  * The full GNU General Public License is included in this distribution in
  * the file called "COPYING".
  *
index 470292767e68e81e390e1b9065954fd2546e04e6..bf24ebe874b002f1e5abcdcd53cd2b860df21a54 100644 (file)
  * 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.
- *
  * The full GNU General Public License is included in this distribution in the
  * file called COPYING.
  */
index 194ec20c940841c9b0de473ac43417f4235c0482..64790a45ef5d8aed5bf8abbaa14a7b276f89e2de 100644 (file)
  * 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.
- *
  * The full GNU General Public License is included in this distribution in
  * the file called "COPYING".
  *
index 02177ecf09f89b899b92a18edb06512f79f0f383..a3e731edce5714b258f8124189f8a23b1e7bcec0 100644 (file)
  * 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.
- *
  * The full GNU General Public License is included in this distribution in the
  * file called COPYING.
  */
index 5501eb072d6981c9a5c6d7a79c87777376979093..76f0dc688a19937dcdfddc25b4611677c8389fb8 100644 (file)
  * 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.
- *
  * The full GNU General Public License is included in this distribution in
  * the file called "COPYING".
  *
index 2f1cfa0f1f475bfa7992c5daf944d093e7970232..909352f74c89237835c3ba306595b47f5cbceab3 100644 (file)
  * 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.
- *
  * The full GNU General Public License is included in this distribution in the
  * file called COPYING.
  */
index 263d9f6a207e9f5d0ffd6d5059e18c94b067cdf2..998826854fddeba51a4acb3ea62e57723f43f285 100644 (file)
  * 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.
- *
  */
 
 /*
index 6f7f43529ccb17a23be497defc32f7e9b424b0c7..647e362f01fd178d769259061fdedc49bfe53f9c 100644 (file)
@@ -313,11 +313,6 @@ static void k3_dma_tasklet(unsigned long arg)
        }
 }
 
-static int k3_dma_alloc_chan_resources(struct dma_chan *chan)
-{
-       return 0;
-}
-
 static void k3_dma_free_chan_resources(struct dma_chan *chan)
 {
        struct k3_dma_chan *c = to_k3_chan(chan);
@@ -654,7 +649,7 @@ static void k3_dma_free_desc(struct virt_dma_desc *vd)
        kfree(ds);
 }
 
-static struct of_device_id k3_pdma_dt_ids[] = {
+static const struct of_device_id k3_pdma_dt_ids[] = {
        { .compatible = "hisilicon,k3-dma-1.0", },
        {}
 };
@@ -728,7 +723,6 @@ static int k3_dma_probe(struct platform_device *op)
        dma_cap_set(DMA_SLAVE, d->slave.cap_mask);
        dma_cap_set(DMA_MEMCPY, d->slave.cap_mask);
        d->slave.dev = &op->dev;
-       d->slave.device_alloc_chan_resources = k3_dma_alloc_chan_resources;
        d->slave.device_free_chan_resources = k3_dma_free_chan_resources;
        d->slave.device_tx_status = k3_dma_tx_status;
        d->slave.device_prep_dma_memcpy = k3_dma_prep_memcpy;
index eb410044e1af5415f4aa1aad48f7564588be1bb1..462a0229a743099253ee06a479ff41b2a855e5e9 100644 (file)
@@ -973,7 +973,7 @@ static int mmp_pdma_chan_init(struct mmp_pdma_device *pdev, int idx, int irq)
        return 0;
 }
 
-static struct of_device_id mmp_pdma_dt_ids[] = {
+static const struct of_device_id mmp_pdma_dt_ids[] = {
        { .compatible = "marvell,pdma-1.0", },
        {}
 };
index b6f4e1fc9c784cc0a3fce3d76877774760cd8c59..449e785def17d2af759a4b82e1a0b5723b85d4ca 100644 (file)
@@ -613,7 +613,7 @@ struct dma_chan *mmp_tdma_xlate(struct of_phandle_args *dma_spec,
        return dma_request_channel(mask, mmp_tdma_filter_fn, &param);
 }
 
-static struct of_device_id mmp_tdma_dt_ids[] = {
+static const struct of_device_id mmp_tdma_dt_ids[] = {
        { .compatible = "marvell,adma-1.0", .data = (void *)MMP_AUD_TDMA},
        { .compatible = "marvell,pxa910-squ", .data = (void *)PXA910_SQU},
        {}
index 57d2457545f3d47ff274c04b62460c6354b31e24..e6281e7aa46e89da548912db37c4fd5868705b2a 100644 (file)
  * 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.
- *
  * The full GNU General Public License is included in this distribution in the
  * file called COPYING.
  */
@@ -1072,7 +1068,7 @@ static int mpc_dma_remove(struct platform_device *op)
        return 0;
 }
 
-static struct of_device_id mpc_dma_match[] = {
+static const struct of_device_id mpc_dma_match[] = {
        { .compatible = "fsl,mpc5121-dma", },
        { .compatible = "fsl,mpc8308-dma", },
        {},
index b03e8137b918881891bde603576f659612c40c47..1c56001df676c048a8ec30c206e0a215375eada7 100644 (file)
  * 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/init.h>
@@ -1249,7 +1245,7 @@ static int mv_xor_remove(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_OF
-static struct of_device_id mv_xor_dt_ids[] = {
+static const struct of_device_id mv_xor_dt_ids[] = {
        { .compatible = "marvell,orion-xor", },
        {},
 };
index 78edc7e44569f468da8a5fcb8e84abcc9dc5faf0..91958dba39a210648badadcdefa1fe28b75ce31f 100644 (file)
@@ -9,10 +9,6 @@
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
 #ifndef MV_XOR_H
index 35c143cb88da1c676d47f714f3fed146010083fc..b859792dde955bc7acdc11eea9686009a0ddfd1c 100644 (file)
@@ -949,6 +949,7 @@ err_free_res:
 err_disable_pdev:
        pci_disable_device(pdev);
 err_free_mem:
+       kfree(pd);
        return err;
 }
 
index 0e1f56772855d8fc7f1194099a4c113a6b1c8ddf..a7d9d3029b145dfa29babeee33022bc1f7354d52 100644 (file)
@@ -556,7 +556,7 @@ static inline u32 _emit_ADDH(unsigned dry_run, u8 buf[],
 
        buf[0] = CMD_DMAADDH;
        buf[0] |= (da << 1);
-       *((u16 *)&buf[1]) = val;
+       *((__le16 *)&buf[1]) = cpu_to_le16(val);
 
        PL330_DBGCMD_DUMP(SZ_DMAADDH, "\tDMAADDH %s %u\n",
                da == 1 ? "DA" : "SA", val);
@@ -710,7 +710,7 @@ static inline u32 _emit_MOV(unsigned dry_run, u8 buf[],
 
        buf[0] = CMD_DMAMOV;
        buf[1] = dst;
-       *((u32 *)&buf[2]) = val;
+       *((__le32 *)&buf[2]) = cpu_to_le32(val);
 
        PL330_DBGCMD_DUMP(SZ_DMAMOV, "\tDMAMOV %s 0x%x\n",
                dst == SAR ? "SAR" : (dst == DAR ? "DAR" : "CCR"), val);
@@ -888,7 +888,7 @@ static inline u32 _emit_GO(unsigned dry_run, u8 buf[],
 
        buf[1] = chan & 0x7;
 
-       *((u32 *)&buf[2]) = addr;
+       *((__le32 *)&buf[2]) = cpu_to_le32(addr);
 
        return SZ_DMAGO;
 }
@@ -928,7 +928,7 @@ static inline void _execute_DBGINSN(struct pl330_thread *thrd,
        }
        writel(val, regs + DBGINST0);
 
-       val = *((u32 *)&insn[2]);
+       val = le32_to_cpu(*((__le32 *)&insn[2]));
        writel(val, regs + DBGINST1);
 
        /* If timed out due to halted state-machine */
@@ -2162,7 +2162,7 @@ static int pl330_terminate_all(struct dma_chan *chan)
  * DMA transfer again. This pause feature was implemented to
  * allow safely read residue before channel termination.
  */
-int pl330_pause(struct dma_chan *chan)
+static int pl330_pause(struct dma_chan *chan)
 {
        struct dma_pl330_chan *pch = to_pchan(chan);
        struct pl330_dmac *pl330 = pch->dmac;
@@ -2203,8 +2203,8 @@ static void pl330_free_chan_resources(struct dma_chan *chan)
        pm_runtime_put_autosuspend(pch->dmac->ddma.dev);
 }
 
-int pl330_get_current_xferred_count(struct dma_pl330_chan *pch,
-               struct dma_pl330_desc *desc)
+static int pl330_get_current_xferred_count(struct dma_pl330_chan *pch,
+                                          struct dma_pl330_desc *desc)
 {
        struct pl330_thread *thrd = pch->thread;
        struct pl330_dmac *pl330 = pch->dmac;
@@ -2259,7 +2259,17 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
                        transferred = 0;
                residual += desc->bytes_requested - transferred;
                if (desc->txd.cookie == cookie) {
-                       ret = desc->status;
+                       switch (desc->status) {
+                       case DONE:
+                               ret = DMA_COMPLETE;
+                               break;
+                       case PREP:
+                       case BUSY:
+                               ret = DMA_IN_PROGRESS;
+                               break;
+                       default:
+                               WARN_ON(1);
+                       }
                        break;
                }
                if (desc->last)
index fa764a39cd36ed40de0211ec621749ca30cd97b2..9217f893b0d1af7efec3d56bdc281beeb426fcfe 100644 (file)
  * 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.
- *
  * The full GNU General Public License is included in this distribution in the
  * file called COPYING.
  */
index 9c914d62590626fb8f407d7f0bed63b27c37a4f1..5a250cdc83769f0d4aaff65530c76b705a474e25 100644 (file)
@@ -171,6 +171,35 @@ static const struct reg_offset_data bam_v1_4_reg_info[] = {
        [BAM_P_FIFO_SIZES]      = { 0x1820, 0x00, 0x1000, 0x00 },
 };
 
+static const struct reg_offset_data bam_v1_7_reg_info[] = {
+       [BAM_CTRL]              = { 0x00000, 0x00, 0x00, 0x00 },
+       [BAM_REVISION]          = { 0x01000, 0x00, 0x00, 0x00 },
+       [BAM_NUM_PIPES]         = { 0x01008, 0x00, 0x00, 0x00 },
+       [BAM_DESC_CNT_TRSHLD]   = { 0x00008, 0x00, 0x00, 0x00 },
+       [BAM_IRQ_SRCS]          = { 0x03010, 0x00, 0x00, 0x00 },
+       [BAM_IRQ_SRCS_MSK]      = { 0x03014, 0x00, 0x00, 0x00 },
+       [BAM_IRQ_SRCS_UNMASKED] = { 0x03018, 0x00, 0x00, 0x00 },
+       [BAM_IRQ_STTS]          = { 0x00014, 0x00, 0x00, 0x00 },
+       [BAM_IRQ_CLR]           = { 0x00018, 0x00, 0x00, 0x00 },
+       [BAM_IRQ_EN]            = { 0x0001C, 0x00, 0x00, 0x00 },
+       [BAM_CNFG_BITS]         = { 0x0007C, 0x00, 0x00, 0x00 },
+       [BAM_IRQ_SRCS_EE]       = { 0x03000, 0x00, 0x00, 0x1000 },
+       [BAM_IRQ_SRCS_MSK_EE]   = { 0x03004, 0x00, 0x00, 0x1000 },
+       [BAM_P_CTRL]            = { 0x13000, 0x1000, 0x00, 0x00 },
+       [BAM_P_RST]             = { 0x13004, 0x1000, 0x00, 0x00 },
+       [BAM_P_HALT]            = { 0x13008, 0x1000, 0x00, 0x00 },
+       [BAM_P_IRQ_STTS]        = { 0x13010, 0x1000, 0x00, 0x00 },
+       [BAM_P_IRQ_CLR]         = { 0x13014, 0x1000, 0x00, 0x00 },
+       [BAM_P_IRQ_EN]          = { 0x13018, 0x1000, 0x00, 0x00 },
+       [BAM_P_EVNT_DEST_ADDR]  = { 0x1382C, 0x00, 0x1000, 0x00 },
+       [BAM_P_EVNT_REG]        = { 0x13818, 0x00, 0x1000, 0x00 },
+       [BAM_P_SW_OFSTS]        = { 0x13800, 0x00, 0x1000, 0x00 },
+       [BAM_P_DATA_FIFO_ADDR]  = { 0x13824, 0x00, 0x1000, 0x00 },
+       [BAM_P_DESC_FIFO_ADDR]  = { 0x1381C, 0x00, 0x1000, 0x00 },
+       [BAM_P_EVNT_GEN_TRSHLD] = { 0x13828, 0x00, 0x1000, 0x00 },
+       [BAM_P_FIFO_SIZES]      = { 0x13820, 0x00, 0x1000, 0x00 },
+};
+
 /* BAM CTRL */
 #define BAM_SW_RST                     BIT(0)
 #define BAM_EN                         BIT(1)
@@ -1051,6 +1080,7 @@ static void bam_channel_init(struct bam_device *bdev, struct bam_chan *bchan,
 static const struct of_device_id bam_of_match[] = {
        { .compatible = "qcom,bam-v1.3.0", .data = &bam_v1_3_reg_info },
        { .compatible = "qcom,bam-v1.4.0", .data = &bam_v1_4_reg_info },
+       { .compatible = "qcom,bam-v1.7.0", .data = &bam_v1_7_reg_info },
        {}
 };
 
@@ -1113,7 +1143,7 @@ static int bam_dma_probe(struct platform_device *pdev)
 
        if (!bdev->channels) {
                ret = -ENOMEM;
-               goto err_disable_clk;
+               goto err_tasklet_kill;
        }
 
        /* allocate and initialize channels */
@@ -1125,7 +1155,7 @@ static int bam_dma_probe(struct platform_device *pdev)
        ret = devm_request_irq(bdev->dev, bdev->irq, bam_dma_irq,
                        IRQF_TRIGGER_HIGH, "bam_dma", bdev);
        if (ret)
-               goto err_disable_clk;
+               goto err_bam_channel_exit;
 
        /* set max dma segment size */
        bdev->common.dev = bdev->dev;
@@ -1133,7 +1163,7 @@ static int bam_dma_probe(struct platform_device *pdev)
        ret = dma_set_max_seg_size(bdev->common.dev, BAM_MAX_DATA_SIZE);
        if (ret) {
                dev_err(bdev->dev, "cannot set maximum segment size\n");
-               goto err_disable_clk;
+               goto err_bam_channel_exit;
        }
 
        platform_set_drvdata(pdev, bdev);
@@ -1161,7 +1191,7 @@ static int bam_dma_probe(struct platform_device *pdev)
        ret = dma_async_device_register(&bdev->common);
        if (ret) {
                dev_err(bdev->dev, "failed to register dma async device\n");
-               goto err_disable_clk;
+               goto err_bam_channel_exit;
        }
 
        ret = of_dma_controller_register(pdev->dev.of_node, bam_dma_xlate,
@@ -1173,8 +1203,14 @@ static int bam_dma_probe(struct platform_device *pdev)
 
 err_unregister_dma:
        dma_async_device_unregister(&bdev->common);
+err_bam_channel_exit:
+       for (i = 0; i < bdev->num_channels; i++)
+               tasklet_kill(&bdev->channels[i].vc.task);
+err_tasklet_kill:
+       tasklet_kill(&bdev->task);
 err_disable_clk:
        clk_disable_unprepare(bdev->bamclk);
+
        return ret;
 }
 
index 2f91da3db8361cdba3dbd51e120b299607a42485..01dcaf21b98820507cf33ec7b6a5b19e20aea890 100644 (file)
@@ -749,11 +749,6 @@ unlock:
        return ret;
 }
 
-static int s3c24xx_dma_alloc_chan_resources(struct dma_chan *chan)
-{
-       return 0;
-}
-
 static void s3c24xx_dma_free_chan_resources(struct dma_chan *chan)
 {
        /* Ensure all queued descriptors are freed */
@@ -1238,7 +1233,7 @@ static int s3c24xx_dma_probe(struct platform_device *pdev)
        if (!s3cdma->phy_chans)
                return -ENOMEM;
 
-       /* aquire irqs and clocks for all physical channels */
+       /* acquire irqs and clocks for all physical channels */
        for (i = 0; i < pdata->num_phy_channels; i++) {
                struct s3c24xx_dma_phy *phy = &s3cdma->phy_chans[i];
                char clk_name[6];
@@ -1266,7 +1261,7 @@ static int s3c24xx_dma_probe(struct platform_device *pdev)
                        sprintf(clk_name, "dma.%d", i);
                        phy->clk = devm_clk_get(&pdev->dev, clk_name);
                        if (IS_ERR(phy->clk) && sdata->has_clocks) {
-                               dev_err(&pdev->dev, "unable to aquire clock for channel %d, error %lu",
+                               dev_err(&pdev->dev, "unable to acquire clock for channel %d, error %lu\n",
                                        i, PTR_ERR(phy->clk));
                                continue;
                        }
@@ -1290,8 +1285,6 @@ static int s3c24xx_dma_probe(struct platform_device *pdev)
        dma_cap_set(DMA_MEMCPY, s3cdma->memcpy.cap_mask);
        dma_cap_set(DMA_PRIVATE, s3cdma->memcpy.cap_mask);
        s3cdma->memcpy.dev = &pdev->dev;
-       s3cdma->memcpy.device_alloc_chan_resources =
-                                       s3c24xx_dma_alloc_chan_resources;
        s3cdma->memcpy.device_free_chan_resources =
                                        s3c24xx_dma_free_chan_resources;
        s3cdma->memcpy.device_prep_dma_memcpy = s3c24xx_dma_prep_memcpy;
@@ -1305,8 +1298,6 @@ static int s3c24xx_dma_probe(struct platform_device *pdev)
        dma_cap_set(DMA_CYCLIC, s3cdma->slave.cap_mask);
        dma_cap_set(DMA_PRIVATE, s3cdma->slave.cap_mask);
        s3cdma->slave.dev = &pdev->dev;
-       s3cdma->slave.device_alloc_chan_resources =
-                                       s3c24xx_dma_alloc_chan_resources;
        s3cdma->slave.device_free_chan_resources =
                                        s3c24xx_dma_free_chan_resources;
        s3cdma->slave.device_tx_status = s3c24xx_dma_tx_status;
index 5adf5407a8cb83a70faec26c6182538df958bcb5..43db255050d238ff365c40280ec0f54c5605f32c 100644 (file)
@@ -389,11 +389,6 @@ static void sa11x0_dma_tasklet(unsigned long arg)
 }
 
 
-static int sa11x0_dma_alloc_chan_resources(struct dma_chan *chan)
-{
-       return 0;
-}
-
 static void sa11x0_dma_free_chan_resources(struct dma_chan *chan)
 {
        struct sa11x0_dma_chan *c = to_sa11x0_dma_chan(chan);
@@ -835,7 +830,6 @@ static int sa11x0_dma_init_dmadev(struct dma_device *dmadev,
 
        INIT_LIST_HEAD(&dmadev->channels);
        dmadev->dev = dev;
-       dmadev->device_alloc_chan_resources = sa11x0_dma_alloc_chan_resources;
        dmadev->device_free_chan_resources = sa11x0_dma_free_chan_resources;
        dmadev->device_config = sa11x0_dma_device_config;
        dmadev->device_pause = sa11x0_dma_device_pause;
@@ -948,6 +942,12 @@ static int sa11x0_dma_probe(struct platform_device *pdev)
        dma_cap_set(DMA_CYCLIC, d->slave.cap_mask);
        d->slave.device_prep_slave_sg = sa11x0_dma_prep_slave_sg;
        d->slave.device_prep_dma_cyclic = sa11x0_dma_prep_dma_cyclic;
+       d->slave.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
+       d->slave.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
+       d->slave.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+                                  BIT(DMA_SLAVE_BUSWIDTH_2_BYTES);
+       d->slave.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+                                  BIT(DMA_SLAVE_BUSWIDTH_2_BYTES);
        ret = sa11x0_dma_init_dmadev(&d->slave, &pdev->dev);
        if (ret) {
                dev_warn(d->slave.dev, "failed to register slave async device: %d\n",
index 8190ad225a1b80bdad6daab9d43904421b8481f7..0f371524a4d965e53cd1a2af040030f02ab83dc0 100644 (file)
@@ -51,12 +51,6 @@ config RCAR_HPB_DMAE
        help
          Enable support for the Renesas R-Car series DMA controllers.
 
-config RCAR_AUDMAC_PP
-       tristate "Renesas R-Car Audio DMAC Peripheral Peripheral support"
-       depends on SH_DMAE_BASE
-       help
-         Enable support for the Renesas R-Car Audio DMAC Peripheral Peripheral controllers.
-
 config RCAR_DMAC
        tristate "Renesas R-Car Gen2 DMA Controller"
        depends on ARCH_SHMOBILE || COMPILE_TEST
@@ -64,3 +58,12 @@ config RCAR_DMAC
        help
          This driver supports the general purpose DMA controller found in the
          Renesas R-Car second generation SoCs.
+
+config RENESAS_USB_DMAC
+       tristate "Renesas USB-DMA Controller"
+       depends on ARCH_SHMOBILE || COMPILE_TEST
+       select RENESAS_DMA
+       select DMA_VIRTUAL_CHANNELS
+       help
+         This driver supports the USB-DMA controller found in the Renesas
+         SoCs.
index 2852f9db61a40a668f3140299c6a2760226aea13..b8a598066ce28a657d62af90a1a2ef57fbc2c866 100644 (file)
@@ -15,5 +15,5 @@ obj-$(CONFIG_SH_DMAE) += shdma.o
 
 obj-$(CONFIG_SUDMAC) += sudmac.o
 obj-$(CONFIG_RCAR_HPB_DMAE) += rcar-hpbdma.o
-obj-$(CONFIG_RCAR_AUDMAC_PP) += rcar-audmapp.o
 obj-$(CONFIG_RCAR_DMAC) += rcar-dmac.o
+obj-$(CONFIG_RENESAS_USB_DMAC) += usb-dmac.o
diff --git a/drivers/dma/sh/rcar-audmapp.c b/drivers/dma/sh/rcar-audmapp.c
deleted file mode 100644 (file)
index d95bbdd..0000000
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- * This is for Renesas R-Car Audio-DMAC-peri-peri.
- *
- * Copyright (C) 2014 Renesas Electronics Corporation
- * Copyright (C) 2014 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
- *
- * based on the drivers/dma/sh/shdma.c
- *
- * Copyright (C) 2011-2012 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
- * Copyright (C) 2009 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
- * Copyright (C) 2009 Renesas Solutions, Inc. All rights reserved.
- * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/dmaengine.h>
-#include <linux/of_dma.h>
-#include <linux/platform_data/dma-rcar-audmapp.h>
-#include <linux/platform_device.h>
-#include <linux/shdma-base.h>
-
-/*
- * DMA register
- */
-#define PDMASAR                0x00
-#define PDMADAR                0x04
-#define PDMACHCR       0x0c
-
-/* PDMACHCR */
-#define PDMACHCR_DE            (1 << 0)
-
-#define AUDMAPP_MAX_CHANNELS   29
-
-/* Default MEMCPY transfer size = 2^2 = 4 bytes */
-#define LOG2_DEFAULT_XFER_SIZE 2
-#define AUDMAPP_SLAVE_NUMBER   256
-#define AUDMAPP_LEN_MAX                (16 * 1024 * 1024)
-
-struct audmapp_chan {
-       struct shdma_chan shdma_chan;
-       void __iomem *base;
-       dma_addr_t slave_addr;
-       u32 chcr;
-};
-
-struct audmapp_device {
-       struct shdma_dev shdma_dev;
-       struct audmapp_pdata *pdata;
-       struct device *dev;
-       void __iomem *chan_reg;
-};
-
-struct audmapp_desc {
-       struct shdma_desc shdma_desc;
-       dma_addr_t src;
-       dma_addr_t dst;
-};
-
-#define to_shdma_chan(c) container_of(c, struct shdma_chan, dma_chan)
-
-#define to_chan(chan) container_of(chan, struct audmapp_chan, shdma_chan)
-#define to_desc(sdesc) container_of(sdesc, struct audmapp_desc, shdma_desc)
-#define to_dev(chan) container_of(chan->shdma_chan.dma_chan.device,    \
-                                 struct audmapp_device, shdma_dev.dma_dev)
-
-static void audmapp_write(struct audmapp_chan *auchan, u32 data, u32 reg)
-{
-       struct audmapp_device *audev = to_dev(auchan);
-       struct device *dev = audev->dev;
-
-       dev_dbg(dev, "w %p : %08x\n", auchan->base + reg, data);
-
-       iowrite32(data, auchan->base + reg);
-}
-
-static u32 audmapp_read(struct audmapp_chan *auchan, u32 reg)
-{
-       return ioread32(auchan->base + reg);
-}
-
-static void audmapp_halt(struct shdma_chan *schan)
-{
-       struct audmapp_chan *auchan = to_chan(schan);
-       int i;
-
-       audmapp_write(auchan, 0, PDMACHCR);
-
-       for (i = 0; i < 1024; i++) {
-               if (0 == audmapp_read(auchan, PDMACHCR))
-                       return;
-               udelay(1);
-       }
-}
-
-static void audmapp_start_xfer(struct shdma_chan *schan,
-                              struct shdma_desc *sdesc)
-{
-       struct audmapp_chan *auchan = to_chan(schan);
-       struct audmapp_device *audev = to_dev(auchan);
-       struct audmapp_desc *desc = to_desc(sdesc);
-       struct device *dev = audev->dev;
-       u32 chcr = auchan->chcr | PDMACHCR_DE;
-
-       dev_dbg(dev, "src/dst/chcr = %pad/%pad/%08x\n",
-               &desc->src, &desc->dst, chcr);
-
-       audmapp_write(auchan, desc->src,        PDMASAR);
-       audmapp_write(auchan, desc->dst,        PDMADAR);
-       audmapp_write(auchan, chcr,     PDMACHCR);
-}
-
-static int audmapp_get_config(struct audmapp_chan *auchan, int slave_id,
-                             u32 *chcr, dma_addr_t *dst)
-{
-       struct audmapp_device *audev = to_dev(auchan);
-       struct audmapp_pdata *pdata = audev->pdata;
-       struct audmapp_slave_config *cfg;
-       int i;
-
-       *chcr   = 0;
-       *dst    = 0;
-
-       if (!pdata) { /* DT */
-               *chcr = ((u32)slave_id) << 16;
-               auchan->shdma_chan.slave_id = (slave_id) >> 8;
-               return 0;
-       }
-
-       /* non-DT */
-
-       if (slave_id >= AUDMAPP_SLAVE_NUMBER)
-               return -ENXIO;
-
-       for (i = 0, cfg = pdata->slave; i < pdata->slave_num; i++, cfg++)
-               if (cfg->slave_id == slave_id) {
-                       *chcr   = cfg->chcr;
-                       *dst    = cfg->dst;
-                       return 0;
-               }
-
-       return -ENXIO;
-}
-
-static int audmapp_set_slave(struct shdma_chan *schan, int slave_id,
-                            dma_addr_t slave_addr, bool try)
-{
-       struct audmapp_chan *auchan = to_chan(schan);
-       u32 chcr;
-       dma_addr_t dst;
-       int ret;
-
-       ret = audmapp_get_config(auchan, slave_id, &chcr, &dst);
-       if (ret < 0)
-               return ret;
-
-       if (try)
-               return 0;
-
-       auchan->chcr            = chcr;
-       auchan->slave_addr      = slave_addr ? : dst;
-
-       return 0;
-}
-
-static int audmapp_desc_setup(struct shdma_chan *schan,
-                             struct shdma_desc *sdesc,
-                             dma_addr_t src, dma_addr_t dst, size_t *len)
-{
-       struct audmapp_desc *desc = to_desc(sdesc);
-
-       if (*len > (size_t)AUDMAPP_LEN_MAX)
-               *len = (size_t)AUDMAPP_LEN_MAX;
-
-       desc->src = src;
-       desc->dst = dst;
-
-       return 0;
-}
-
-static void audmapp_setup_xfer(struct shdma_chan *schan,
-                              int slave_id)
-{
-}
-
-static dma_addr_t audmapp_slave_addr(struct shdma_chan *schan)
-{
-       struct audmapp_chan *auchan = to_chan(schan);
-
-       return auchan->slave_addr;
-}
-
-static bool audmapp_channel_busy(struct shdma_chan *schan)
-{
-       struct audmapp_chan *auchan = to_chan(schan);
-       u32 chcr = audmapp_read(auchan, PDMACHCR);
-
-       return chcr & ~PDMACHCR_DE;
-}
-
-static bool audmapp_desc_completed(struct shdma_chan *schan,
-                                  struct shdma_desc *sdesc)
-{
-       return true;
-}
-
-static struct shdma_desc *audmapp_embedded_desc(void *buf, int i)
-{
-       return &((struct audmapp_desc *)buf)[i].shdma_desc;
-}
-
-static const struct shdma_ops audmapp_shdma_ops = {
-       .halt_channel   = audmapp_halt,
-       .desc_setup     = audmapp_desc_setup,
-       .set_slave      = audmapp_set_slave,
-       .start_xfer     = audmapp_start_xfer,
-       .embedded_desc  = audmapp_embedded_desc,
-       .setup_xfer     = audmapp_setup_xfer,
-       .slave_addr     = audmapp_slave_addr,
-       .channel_busy   = audmapp_channel_busy,
-       .desc_completed = audmapp_desc_completed,
-};
-
-static int audmapp_chan_probe(struct platform_device *pdev,
-                             struct audmapp_device *audev, int id)
-{
-       struct shdma_dev *sdev = &audev->shdma_dev;
-       struct audmapp_chan *auchan;
-       struct shdma_chan *schan;
-       struct device *dev = audev->dev;
-
-       auchan = devm_kzalloc(dev, sizeof(*auchan), GFP_KERNEL);
-       if (!auchan)
-               return -ENOMEM;
-
-       schan = &auchan->shdma_chan;
-       schan->max_xfer_len = AUDMAPP_LEN_MAX;
-
-       shdma_chan_probe(sdev, schan, id);
-
-       auchan->base = audev->chan_reg + 0x20 + (0x10 * id);
-       dev_dbg(dev, "%02d : %p / %p", id, auchan->base, audev->chan_reg);
-
-       return 0;
-}
-
-static void audmapp_chan_remove(struct audmapp_device *audev)
-{
-       struct shdma_chan *schan;
-       int i;
-
-       shdma_for_each_chan(schan, &audev->shdma_dev, i) {
-               BUG_ON(!schan);
-               shdma_chan_remove(schan);
-       }
-}
-
-static struct dma_chan *audmapp_of_xlate(struct of_phandle_args *dma_spec,
-                                        struct of_dma *ofdma)
-{
-       dma_cap_mask_t mask;
-       struct dma_chan *chan;
-       u32 chcr = dma_spec->args[0];
-
-       if (dma_spec->args_count != 1)
-               return NULL;
-
-       dma_cap_zero(mask);
-       dma_cap_set(DMA_SLAVE, mask);
-
-       chan = dma_request_channel(mask, shdma_chan_filter, NULL);
-       if (chan)
-               to_shdma_chan(chan)->hw_req = chcr;
-
-       return chan;
-}
-
-static int audmapp_probe(struct platform_device *pdev)
-{
-       struct audmapp_pdata *pdata = pdev->dev.platform_data;
-       struct device_node *np = pdev->dev.of_node;
-       struct audmapp_device *audev;
-       struct shdma_dev *sdev;
-       struct dma_device *dma_dev;
-       struct resource *res;
-       int err, i;
-
-       if (np)
-               of_dma_controller_register(np, audmapp_of_xlate, pdev);
-       else if (!pdata)
-               return -ENODEV;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-       audev = devm_kzalloc(&pdev->dev, sizeof(*audev), GFP_KERNEL);
-       if (!audev)
-               return -ENOMEM;
-
-       audev->dev      = &pdev->dev;
-       audev->pdata    = pdata;
-       audev->chan_reg = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(audev->chan_reg))
-               return PTR_ERR(audev->chan_reg);
-
-       sdev            = &audev->shdma_dev;
-       sdev->ops       = &audmapp_shdma_ops;
-       sdev->desc_size = sizeof(struct audmapp_desc);
-
-       dma_dev                 = &sdev->dma_dev;
-       dma_dev->copy_align     = LOG2_DEFAULT_XFER_SIZE;
-       dma_cap_set(DMA_SLAVE, dma_dev->cap_mask);
-
-       err = shdma_init(&pdev->dev, sdev, AUDMAPP_MAX_CHANNELS);
-       if (err < 0)
-               return err;
-
-       platform_set_drvdata(pdev, audev);
-
-       /* Create DMA Channel */
-       for (i = 0; i < AUDMAPP_MAX_CHANNELS; i++) {
-               err = audmapp_chan_probe(pdev, audev, i);
-               if (err)
-                       goto chan_probe_err;
-       }
-
-       err = dma_async_device_register(dma_dev);
-       if (err < 0)
-               goto chan_probe_err;
-
-       return err;
-
-chan_probe_err:
-       audmapp_chan_remove(audev);
-       shdma_cleanup(sdev);
-
-       return err;
-}
-
-static int audmapp_remove(struct platform_device *pdev)
-{
-       struct audmapp_device *audev = platform_get_drvdata(pdev);
-       struct dma_device *dma_dev = &audev->shdma_dev.dma_dev;
-
-       dma_async_device_unregister(dma_dev);
-
-       audmapp_chan_remove(audev);
-       shdma_cleanup(&audev->shdma_dev);
-
-       return 0;
-}
-
-static const struct of_device_id audmapp_of_match[] = {
-       { .compatible = "renesas,rcar-audmapp", },
-       {},
-};
-
-static struct platform_driver audmapp_driver = {
-       .probe          = audmapp_probe,
-       .remove         = audmapp_remove,
-       .driver         = {
-               .name   = "rcar-audmapp-engine",
-               .of_match_table = audmapp_of_match,
-       },
-};
-module_platform_driver(audmapp_driver);
-
-MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
-MODULE_DESCRIPTION("Renesas R-Car Audio DMAC peri-peri driver");
-MODULE_LICENSE("GPL");
index 8ee383d339a513187fb9c6f354cc96b8407eb22d..10fcabad80f3c65c7dfee9ce5e49f28bbef36a48 100644 (file)
@@ -171,8 +171,7 @@ static struct shdma_desc *shdma_get_desc(struct shdma_chan *schan)
        return NULL;
 }
 
-static int shdma_setup_slave(struct shdma_chan *schan, int slave_id,
-                            dma_addr_t slave_addr)
+static int shdma_setup_slave(struct shdma_chan *schan, dma_addr_t slave_addr)
 {
        struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
        const struct shdma_ops *ops = sdev->ops;
@@ -183,25 +182,23 @@ static int shdma_setup_slave(struct shdma_chan *schan, int slave_id,
                ret = ops->set_slave(schan, match, slave_addr, true);
                if (ret < 0)
                        return ret;
-
-               slave_id = schan->slave_id;
        } else {
-               match = slave_id;
+               match = schan->real_slave_id;
        }
 
-       if (slave_id < 0 || slave_id >= slave_num)
+       if (schan->real_slave_id < 0 || schan->real_slave_id >= slave_num)
                return -EINVAL;
 
-       if (test_and_set_bit(slave_id, shdma_slave_used))
+       if (test_and_set_bit(schan->real_slave_id, shdma_slave_used))
                return -EBUSY;
 
        ret = ops->set_slave(schan, match, slave_addr, false);
        if (ret < 0) {
-               clear_bit(slave_id, shdma_slave_used);
+               clear_bit(schan->real_slave_id, shdma_slave_used);
                return ret;
        }
 
-       schan->slave_id = slave_id;
+       schan->slave_id = schan->real_slave_id;
 
        return 0;
 }
@@ -221,10 +218,12 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan)
         */
        if (slave) {
                /* Legacy mode: .private is set in filter */
-               ret = shdma_setup_slave(schan, slave->slave_id, 0);
+               schan->real_slave_id = slave->slave_id;
+               ret = shdma_setup_slave(schan, 0);
                if (ret < 0)
                        goto esetslave;
        } else {
+               /* Normal mode: real_slave_id was set by filter */
                schan->slave_id = -EINVAL;
        }
 
@@ -258,11 +257,14 @@ esetslave:
 
 /*
  * This is the standard shdma filter function to be used as a replacement to the
- * "old" method, using the .private pointer. If for some reason you allocate a
- * channel without slave data, use something like ERR_PTR(-EINVAL) as a filter
+ * "old" method, using the .private pointer.
+ * You always have to pass a valid slave id as the argument, old drivers that
+ * pass ERR_PTR(-EINVAL) as a filter parameter and set it up in dma_slave_config
+ * need to be updated so we can remove the slave_id field from dma_slave_config.
  * parameter. If this filter is used, the slave driver, after calling
  * dma_request_channel(), will also have to call dmaengine_slave_config() with
- * .slave_id, .direction, and either .src_addr or .dst_addr set.
+ * .direction, and either .src_addr or .dst_addr set.
+ *
  * NOTE: this filter doesn't support multiple DMAC drivers with the DMA_SLAVE
  * capability! If this becomes a requirement, hardware glue drivers, using this
  * services would have to provide their own filters, which first would check
@@ -276,7 +278,7 @@ bool shdma_chan_filter(struct dma_chan *chan, void *arg)
 {
        struct shdma_chan *schan;
        struct shdma_dev *sdev;
-       int match = (long)arg;
+       int slave_id = (long)arg;
        int ret;
 
        /* Only support channels handled by this driver. */
@@ -284,19 +286,39 @@ bool shdma_chan_filter(struct dma_chan *chan, void *arg)
            shdma_alloc_chan_resources)
                return false;
 
-       if (match < 0)
+       schan = to_shdma_chan(chan);
+       sdev = to_shdma_dev(chan->device);
+
+       /*
+        * For DT, the schan->slave_id field is generated by the
+        * set_slave function from the slave ID that is passed in
+        * from xlate. For the non-DT case, the slave ID is
+        * directly passed into the filter function by the driver
+        */
+       if (schan->dev->of_node) {
+               ret = sdev->ops->set_slave(schan, slave_id, 0, true);
+               if (ret < 0)
+                       return false;
+
+               schan->real_slave_id = schan->slave_id;
+               return true;
+       }
+
+       if (slave_id < 0) {
                /* No slave requested - arbitrary channel */
+               dev_warn(sdev->dma_dev.dev, "invalid slave ID passed to dma_request_slave\n");
                return true;
+       }
 
-       schan = to_shdma_chan(chan);
-       if (!schan->dev->of_node && match >= slave_num)
+       if (slave_id >= slave_num)
                return false;
 
-       sdev = to_shdma_dev(schan->dma_chan.device);
-       ret = sdev->ops->set_slave(schan, match, 0, true);
+       ret = sdev->ops->set_slave(schan, slave_id, 0, true);
        if (ret < 0)
                return false;
 
+       schan->real_slave_id = slave_id;
+
        return true;
 }
 EXPORT_SYMBOL(shdma_chan_filter);
@@ -452,6 +474,8 @@ static void shdma_free_chan_resources(struct dma_chan *chan)
                chan->private = NULL;
        }
 
+       schan->real_slave_id = 0;
+
        spin_lock_irq(&schan->chan_lock);
 
        list_splice_init(&schan->ld_free, &list);
@@ -764,11 +788,20 @@ static int shdma_config(struct dma_chan *chan,
         */
        if (!config)
                return -EINVAL;
+
+       /*
+        * overriding the slave_id through dma_slave_config is deprecated,
+        * but possibly some out-of-tree drivers still do it.
+        */
+       if (WARN_ON_ONCE(config->slave_id &&
+                        config->slave_id != schan->real_slave_id))
+               schan->real_slave_id = config->slave_id;
+
        /*
         * We could lock this, but you shouldn't be configuring the
         * channel, while using it...
         */
-       return shdma_setup_slave(schan, config->slave_id,
+       return shdma_setup_slave(schan,
                                 config->direction == DMA_DEV_TO_MEM ?
                                 config->src_addr : config->dst_addr);
 }
index 9f1d4c7dbab8389039e4ae1da636ca13521314ee..11707df1a68944979c99579605c0afcd25a41364 100644 (file)
@@ -443,7 +443,7 @@ static bool sh_dmae_reset(struct sh_dmae_device *shdev)
        return ret;
 }
 
-#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARM)
+#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
 static irqreturn_t sh_dmae_err(int irq, void *data)
 {
        struct sh_dmae_device *shdev = data;
@@ -689,7 +689,7 @@ static int sh_dmae_probe(struct platform_device *pdev)
        const struct sh_dmae_pdata *pdata;
        unsigned long chan_flag[SH_DMAE_MAX_CHANNELS] = {};
        int chan_irq[SH_DMAE_MAX_CHANNELS];
-#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARM)
+#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
        unsigned long irqflags = 0;
        int errirq;
 #endif
diff --git a/drivers/dma/sh/usb-dmac.c b/drivers/dma/sh/usb-dmac.c
new file mode 100644 (file)
index 0000000..ebd8a5f
--- /dev/null
@@ -0,0 +1,912 @@
+/*
+ * Renesas USB DMA Controller Driver
+ *
+ * Copyright (C) 2015 Renesas Electronics Corporation
+ *
+ * based on rcar-dmac.c
+ * Copyright (C) 2014 Renesas Electronics Inc.
+ * Author: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This 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/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_dma.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include "../dmaengine.h"
+#include "../virt-dma.h"
+
+/*
+ * struct usb_dmac_sg - Descriptor for a hardware transfer
+ * @mem_addr: memory address
+ * @size: transfer size in bytes
+ */
+struct usb_dmac_sg {
+       dma_addr_t mem_addr;
+       u32 size;
+};
+
+/*
+ * struct usb_dmac_desc - USB DMA Transfer Descriptor
+ * @vd: base virtual channel DMA transaction descriptor
+ * @direction: direction of the DMA transfer
+ * @sg_allocated_len: length of allocated sg
+ * @sg_len: length of sg
+ * @sg_index: index of sg
+ * @residue: residue after the DMAC completed a transfer
+ * @node: node for desc_got and desc_freed
+ * @done_cookie: cookie after the DMAC completed a transfer
+ * @sg: information for the transfer
+ */
+struct usb_dmac_desc {
+       struct virt_dma_desc vd;
+       enum dma_transfer_direction direction;
+       unsigned int sg_allocated_len;
+       unsigned int sg_len;
+       unsigned int sg_index;
+       u32 residue;
+       struct list_head node;
+       dma_cookie_t done_cookie;
+       struct usb_dmac_sg sg[0];
+};
+
+#define to_usb_dmac_desc(vd)   container_of(vd, struct usb_dmac_desc, vd)
+
+/*
+ * struct usb_dmac_chan - USB DMA Controller Channel
+ * @vc: base virtual DMA channel object
+ * @iomem: channel I/O memory base
+ * @index: index of this channel in the controller
+ * @irq: irq number of this channel
+ * @desc: the current descriptor
+ * @descs_allocated: number of descriptors allocated
+ * @desc_got: got descriptors
+ * @desc_freed: freed descriptors after the DMAC completed a transfer
+ */
+struct usb_dmac_chan {
+       struct virt_dma_chan vc;
+       void __iomem *iomem;
+       unsigned int index;
+       int irq;
+       struct usb_dmac_desc *desc;
+       int descs_allocated;
+       struct list_head desc_got;
+       struct list_head desc_freed;
+};
+
+#define to_usb_dmac_chan(c) container_of(c, struct usb_dmac_chan, vc.chan)
+
+/*
+ * struct usb_dmac - USB DMA Controller
+ * @engine: base DMA engine object
+ * @dev: the hardware device
+ * @iomem: remapped I/O memory base
+ * @n_channels: number of available channels
+ * @channels: array of DMAC channels
+ */
+struct usb_dmac {
+       struct dma_device engine;
+       struct device *dev;
+       void __iomem *iomem;
+
+       unsigned int n_channels;
+       struct usb_dmac_chan *channels;
+};
+
+#define to_usb_dmac(d)         container_of(d, struct usb_dmac, engine)
+
+/* -----------------------------------------------------------------------------
+ * Registers
+ */
+
+#define USB_DMAC_CHAN_OFFSET(i)                (0x20 + 0x20 * (i))
+
+#define USB_DMASWR                     0x0008
+#define USB_DMASWR_SWR                 (1 << 0)
+#define USB_DMAOR                      0x0060
+#define USB_DMAOR_AE                   (1 << 2)
+#define USB_DMAOR_DME                  (1 << 0)
+
+#define USB_DMASAR                     0x0000
+#define USB_DMADAR                     0x0004
+#define USB_DMATCR                     0x0008
+#define USB_DMATCR_MASK                        0x00ffffff
+#define USB_DMACHCR                    0x0014
+#define USB_DMACHCR_FTE                        (1 << 24)
+#define USB_DMACHCR_NULLE              (1 << 16)
+#define USB_DMACHCR_NULL               (1 << 12)
+#define USB_DMACHCR_TS_8B              ((0 << 7) | (0 << 6))
+#define USB_DMACHCR_TS_16B             ((0 << 7) | (1 << 6))
+#define USB_DMACHCR_TS_32B             ((1 << 7) | (0 << 6))
+#define USB_DMACHCR_IE                 (1 << 5)
+#define USB_DMACHCR_SP                 (1 << 2)
+#define USB_DMACHCR_TE                 (1 << 1)
+#define USB_DMACHCR_DE                 (1 << 0)
+#define USB_DMATEND                    0x0018
+
+/* Hardcode the xfer_shift to 5 (32bytes) */
+#define USB_DMAC_XFER_SHIFT    5
+#define USB_DMAC_XFER_SIZE     (1 << USB_DMAC_XFER_SHIFT)
+#define USB_DMAC_CHCR_TS       USB_DMACHCR_TS_32B
+#define USB_DMAC_SLAVE_BUSWIDTH        DMA_SLAVE_BUSWIDTH_32_BYTES
+
+/* for descriptors */
+#define USB_DMAC_INITIAL_NR_DESC       16
+#define USB_DMAC_INITIAL_NR_SG         8
+
+/* -----------------------------------------------------------------------------
+ * Device access
+ */
+
+static void usb_dmac_write(struct usb_dmac *dmac, u32 reg, u32 data)
+{
+       writel(data, dmac->iomem + reg);
+}
+
+static u32 usb_dmac_read(struct usb_dmac *dmac, u32 reg)
+{
+       return readl(dmac->iomem + reg);
+}
+
+static u32 usb_dmac_chan_read(struct usb_dmac_chan *chan, u32 reg)
+{
+       return readl(chan->iomem + reg);
+}
+
+static void usb_dmac_chan_write(struct usb_dmac_chan *chan, u32 reg, u32 data)
+{
+       writel(data, chan->iomem + reg);
+}
+
+/* -----------------------------------------------------------------------------
+ * Initialization and configuration
+ */
+
+static bool usb_dmac_chan_is_busy(struct usb_dmac_chan *chan)
+{
+       u32 chcr = usb_dmac_chan_read(chan, USB_DMACHCR);
+
+       return (chcr & (USB_DMACHCR_DE | USB_DMACHCR_TE)) == USB_DMACHCR_DE;
+}
+
+static u32 usb_dmac_calc_tend(u32 size)
+{
+       /*
+        * Please refer to the Figure "Example of Final Transaction Valid
+        * Data Transfer Enable (EDTEN) Setting" in the data sheet.
+        */
+       return 0xffffffff << (32 - (size % USB_DMAC_XFER_SIZE ? :
+                                               USB_DMAC_XFER_SIZE));
+}
+
+/* This function is already held by vc.lock */
+static void usb_dmac_chan_start_sg(struct usb_dmac_chan *chan,
+                                  unsigned int index)
+{
+       struct usb_dmac_desc *desc = chan->desc;
+       struct usb_dmac_sg *sg = desc->sg + index;
+       dma_addr_t src_addr = 0, dst_addr = 0;
+
+       WARN_ON_ONCE(usb_dmac_chan_is_busy(chan));
+
+       if (desc->direction == DMA_DEV_TO_MEM)
+               dst_addr = sg->mem_addr;
+       else
+               src_addr = sg->mem_addr;
+
+       dev_dbg(chan->vc.chan.device->dev,
+               "chan%u: queue sg %p: %u@%pad -> %pad\n",
+               chan->index, sg, sg->size, &src_addr, &dst_addr);
+
+       usb_dmac_chan_write(chan, USB_DMASAR, src_addr & 0xffffffff);
+       usb_dmac_chan_write(chan, USB_DMADAR, dst_addr & 0xffffffff);
+       usb_dmac_chan_write(chan, USB_DMATCR,
+                           DIV_ROUND_UP(sg->size, USB_DMAC_XFER_SIZE));
+       usb_dmac_chan_write(chan, USB_DMATEND, usb_dmac_calc_tend(sg->size));
+
+       usb_dmac_chan_write(chan, USB_DMACHCR, USB_DMAC_CHCR_TS |
+                       USB_DMACHCR_NULLE | USB_DMACHCR_IE | USB_DMACHCR_DE);
+}
+
+/* This function is already held by vc.lock */
+static void usb_dmac_chan_start_desc(struct usb_dmac_chan *chan)
+{
+       struct virt_dma_desc *vd;
+
+       vd = vchan_next_desc(&chan->vc);
+       if (!vd) {
+               chan->desc = NULL;
+               return;
+       }
+
+       /*
+        * Remove this request from vc->desc_issued. Otherwise, this driver
+        * will get the previous value from vchan_next_desc() after a transfer
+        * was completed.
+        */
+       list_del(&vd->node);
+
+       chan->desc = to_usb_dmac_desc(vd);
+       chan->desc->sg_index = 0;
+       usb_dmac_chan_start_sg(chan, 0);
+}
+
+static int usb_dmac_init(struct usb_dmac *dmac)
+{
+       u16 dmaor;
+
+       /* Clear all channels and enable the DMAC globally. */
+       usb_dmac_write(dmac, USB_DMAOR, USB_DMAOR_DME);
+
+       dmaor = usb_dmac_read(dmac, USB_DMAOR);
+       if ((dmaor & (USB_DMAOR_AE | USB_DMAOR_DME)) != USB_DMAOR_DME) {
+               dev_warn(dmac->dev, "DMAOR initialization failed.\n");
+               return -EIO;
+       }
+
+       return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Descriptors allocation and free
+ */
+static int usb_dmac_desc_alloc(struct usb_dmac_chan *chan, unsigned int sg_len,
+                              gfp_t gfp)
+{
+       struct usb_dmac_desc *desc;
+       unsigned long flags;
+
+       desc = kzalloc(sizeof(*desc) + sg_len * sizeof(desc->sg[0]), gfp);
+       if (!desc)
+               return -ENOMEM;
+
+       desc->sg_allocated_len = sg_len;
+       INIT_LIST_HEAD(&desc->node);
+
+       spin_lock_irqsave(&chan->vc.lock, flags);
+       list_add_tail(&desc->node, &chan->desc_freed);
+       spin_unlock_irqrestore(&chan->vc.lock, flags);
+
+       return 0;
+}
+
+static void usb_dmac_desc_free(struct usb_dmac_chan *chan)
+{
+       struct usb_dmac_desc *desc, *_desc;
+       LIST_HEAD(list);
+
+       list_splice_init(&chan->desc_freed, &list);
+       list_splice_init(&chan->desc_got, &list);
+
+       list_for_each_entry_safe(desc, _desc, &list, node) {
+               list_del(&desc->node);
+               kfree(desc);
+       }
+       chan->descs_allocated = 0;
+}
+
+static struct usb_dmac_desc *usb_dmac_desc_get(struct usb_dmac_chan *chan,
+                                              unsigned int sg_len, gfp_t gfp)
+{
+       struct usb_dmac_desc *desc = NULL;
+       unsigned long flags;
+
+       /* Get a freed descritpor */
+       spin_lock_irqsave(&chan->vc.lock, flags);
+       list_for_each_entry(desc, &chan->desc_freed, node) {
+               if (sg_len <= desc->sg_allocated_len) {
+                       list_move_tail(&desc->node, &chan->desc_got);
+                       spin_unlock_irqrestore(&chan->vc.lock, flags);
+                       return desc;
+               }
+       }
+       spin_unlock_irqrestore(&chan->vc.lock, flags);
+
+       /* Allocate a new descriptor */
+       if (!usb_dmac_desc_alloc(chan, sg_len, gfp)) {
+               /* If allocated the desc, it was added to tail of the list */
+               spin_lock_irqsave(&chan->vc.lock, flags);
+               desc = list_last_entry(&chan->desc_freed, struct usb_dmac_desc,
+                                      node);
+               list_move_tail(&desc->node, &chan->desc_got);
+               spin_unlock_irqrestore(&chan->vc.lock, flags);
+               return desc;
+       }
+
+       return NULL;
+}
+
+static void usb_dmac_desc_put(struct usb_dmac_chan *chan,
+                             struct usb_dmac_desc *desc)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&chan->vc.lock, flags);
+       list_move_tail(&desc->node, &chan->desc_freed);
+       spin_unlock_irqrestore(&chan->vc.lock, flags);
+}
+
+/* -----------------------------------------------------------------------------
+ * Stop and reset
+ */
+
+static void usb_dmac_soft_reset(struct usb_dmac_chan *uchan)
+{
+       struct dma_chan *chan = &uchan->vc.chan;
+       struct usb_dmac *dmac = to_usb_dmac(chan->device);
+       int i;
+
+       /* Don't issue soft reset if any one of channels is busy */
+       for (i = 0; i < dmac->n_channels; ++i) {
+               if (usb_dmac_chan_is_busy(uchan))
+                       return;
+       }
+
+       usb_dmac_write(dmac, USB_DMAOR, 0);
+       usb_dmac_write(dmac, USB_DMASWR, USB_DMASWR_SWR);
+       udelay(100);
+       usb_dmac_write(dmac, USB_DMASWR, 0);
+       usb_dmac_write(dmac, USB_DMAOR, 1);
+}
+
+static void usb_dmac_chan_halt(struct usb_dmac_chan *chan)
+{
+       u32 chcr = usb_dmac_chan_read(chan, USB_DMACHCR);
+
+       chcr &= ~(USB_DMACHCR_IE | USB_DMACHCR_TE | USB_DMACHCR_DE);
+       usb_dmac_chan_write(chan, USB_DMACHCR, chcr);
+
+       usb_dmac_soft_reset(chan);
+}
+
+static void usb_dmac_stop(struct usb_dmac *dmac)
+{
+       usb_dmac_write(dmac, USB_DMAOR, 0);
+}
+
+/* -----------------------------------------------------------------------------
+ * DMA engine operations
+ */
+
+static int usb_dmac_alloc_chan_resources(struct dma_chan *chan)
+{
+       struct usb_dmac_chan *uchan = to_usb_dmac_chan(chan);
+       int ret;
+
+       while (uchan->descs_allocated < USB_DMAC_INITIAL_NR_DESC) {
+               ret = usb_dmac_desc_alloc(uchan, USB_DMAC_INITIAL_NR_SG,
+                                         GFP_KERNEL);
+               if (ret < 0) {
+                       usb_dmac_desc_free(uchan);
+                       return ret;
+               }
+               uchan->descs_allocated++;
+       }
+
+       return pm_runtime_get_sync(chan->device->dev);
+}
+
+static void usb_dmac_free_chan_resources(struct dma_chan *chan)
+{
+       struct usb_dmac_chan *uchan = to_usb_dmac_chan(chan);
+       unsigned long flags;
+
+       /* Protect against ISR */
+       spin_lock_irqsave(&uchan->vc.lock, flags);
+       usb_dmac_chan_halt(uchan);
+       spin_unlock_irqrestore(&uchan->vc.lock, flags);
+
+       usb_dmac_desc_free(uchan);
+       vchan_free_chan_resources(&uchan->vc);
+
+       pm_runtime_put(chan->device->dev);
+}
+
+static struct dma_async_tx_descriptor *
+usb_dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
+                      unsigned int sg_len, enum dma_transfer_direction dir,
+                      unsigned long dma_flags, void *context)
+{
+       struct usb_dmac_chan *uchan = to_usb_dmac_chan(chan);
+       struct usb_dmac_desc *desc;
+       struct scatterlist *sg;
+       int i;
+
+       if (!sg_len) {
+               dev_warn(chan->device->dev,
+                        "%s: bad parameter: len=%d\n", __func__, sg_len);
+               return NULL;
+       }
+
+       desc = usb_dmac_desc_get(uchan, sg_len, GFP_NOWAIT);
+       if (!desc)
+               return NULL;
+
+       desc->direction = dir;
+       desc->sg_len = sg_len;
+       for_each_sg(sgl, sg, sg_len, i) {
+               desc->sg[i].mem_addr = sg_dma_address(sg);
+               desc->sg[i].size = sg_dma_len(sg);
+       }
+
+       return vchan_tx_prep(&uchan->vc, &desc->vd, dma_flags);
+}
+
+static int usb_dmac_chan_terminate_all(struct dma_chan *chan)
+{
+       struct usb_dmac_chan *uchan = to_usb_dmac_chan(chan);
+       struct usb_dmac_desc *desc;
+       unsigned long flags;
+       LIST_HEAD(head);
+       LIST_HEAD(list);
+
+       spin_lock_irqsave(&uchan->vc.lock, flags);
+       usb_dmac_chan_halt(uchan);
+       vchan_get_all_descriptors(&uchan->vc, &head);
+       if (uchan->desc)
+               uchan->desc = NULL;
+       list_splice_init(&uchan->desc_got, &list);
+       list_for_each_entry(desc, &list, node)
+               list_move_tail(&desc->node, &uchan->desc_freed);
+       spin_unlock_irqrestore(&uchan->vc.lock, flags);
+       vchan_dma_desc_free_list(&uchan->vc, &head);
+
+       return 0;
+}
+
+static unsigned int usb_dmac_get_current_residue(struct usb_dmac_chan *chan,
+                                                struct usb_dmac_desc *desc,
+                                                int sg_index)
+{
+       struct usb_dmac_sg *sg = desc->sg + sg_index;
+       u32 mem_addr = sg->mem_addr & 0xffffffff;
+       unsigned int residue = sg->size;
+
+       /*
+        * We cannot use USB_DMATCR to calculate residue because USB_DMATCR
+        * has unsuited value to calculate.
+        */
+       if (desc->direction == DMA_DEV_TO_MEM)
+               residue -= usb_dmac_chan_read(chan, USB_DMADAR) - mem_addr;
+       else
+               residue -= usb_dmac_chan_read(chan, USB_DMASAR) - mem_addr;
+
+       return residue;
+}
+
+static u32 usb_dmac_chan_get_residue_if_complete(struct usb_dmac_chan *chan,
+                                                dma_cookie_t cookie)
+{
+       struct usb_dmac_desc *desc;
+       u32 residue = 0;
+
+       list_for_each_entry_reverse(desc, &chan->desc_freed, node) {
+               if (desc->done_cookie == cookie) {
+                       residue = desc->residue;
+                       break;
+               }
+       }
+
+       return residue;
+}
+
+static u32 usb_dmac_chan_get_residue(struct usb_dmac_chan *chan,
+                                    dma_cookie_t cookie)
+{
+       u32 residue = 0;
+       struct virt_dma_desc *vd;
+       struct usb_dmac_desc *desc = chan->desc;
+       int i;
+
+       if (!desc) {
+               vd = vchan_find_desc(&chan->vc, cookie);
+               if (!vd)
+                       return 0;
+               desc = to_usb_dmac_desc(vd);
+       }
+
+       /* Compute the size of all usb_dmac_sg still to be transferred */
+       for (i = desc->sg_index + 1; i < desc->sg_len; i++)
+               residue += desc->sg[i].size;
+
+       /* Add the residue for the current sg */
+       residue += usb_dmac_get_current_residue(chan, desc, desc->sg_index);
+
+       return residue;
+}
+
+static enum dma_status usb_dmac_tx_status(struct dma_chan *chan,
+                                         dma_cookie_t cookie,
+                                         struct dma_tx_state *txstate)
+{
+       struct usb_dmac_chan *uchan = to_usb_dmac_chan(chan);
+       enum dma_status status;
+       unsigned int residue = 0;
+       unsigned long flags;
+
+       status = dma_cookie_status(chan, cookie, txstate);
+       /* a client driver will get residue after DMA_COMPLETE */
+       if (!txstate)
+               return status;
+
+       spin_lock_irqsave(&uchan->vc.lock, flags);
+       if (status == DMA_COMPLETE)
+               residue = usb_dmac_chan_get_residue_if_complete(uchan, cookie);
+       else
+               residue = usb_dmac_chan_get_residue(uchan, cookie);
+       spin_unlock_irqrestore(&uchan->vc.lock, flags);
+
+       dma_set_residue(txstate, residue);
+
+       return status;
+}
+
+static void usb_dmac_issue_pending(struct dma_chan *chan)
+{
+       struct usb_dmac_chan *uchan = to_usb_dmac_chan(chan);
+       unsigned long flags;
+
+       spin_lock_irqsave(&uchan->vc.lock, flags);
+       if (vchan_issue_pending(&uchan->vc) && !uchan->desc)
+               usb_dmac_chan_start_desc(uchan);
+       spin_unlock_irqrestore(&uchan->vc.lock, flags);
+}
+
+static void usb_dmac_virt_desc_free(struct virt_dma_desc *vd)
+{
+       struct usb_dmac_desc *desc = to_usb_dmac_desc(vd);
+       struct usb_dmac_chan *chan = to_usb_dmac_chan(vd->tx.chan);
+
+       usb_dmac_desc_put(chan, desc);
+}
+
+/* -----------------------------------------------------------------------------
+ * IRQ handling
+ */
+
+static void usb_dmac_isr_transfer_end(struct usb_dmac_chan *chan)
+{
+       struct usb_dmac_desc *desc = chan->desc;
+
+       BUG_ON(!desc);
+
+       if (++desc->sg_index < desc->sg_len) {
+               usb_dmac_chan_start_sg(chan, desc->sg_index);
+       } else {
+               desc->residue = usb_dmac_get_current_residue(chan, desc,
+                                                       desc->sg_index - 1);
+               desc->done_cookie = desc->vd.tx.cookie;
+               vchan_cookie_complete(&desc->vd);
+
+               /* Restart the next transfer if this driver has a next desc */
+               usb_dmac_chan_start_desc(chan);
+       }
+}
+
+static irqreturn_t usb_dmac_isr_channel(int irq, void *dev)
+{
+       struct usb_dmac_chan *chan = dev;
+       irqreturn_t ret = IRQ_NONE;
+       u32 mask = USB_DMACHCR_TE;
+       u32 check_bits = USB_DMACHCR_TE | USB_DMACHCR_SP;
+       u32 chcr;
+
+       spin_lock(&chan->vc.lock);
+
+       chcr = usb_dmac_chan_read(chan, USB_DMACHCR);
+       if (chcr & check_bits)
+               mask |= USB_DMACHCR_DE | check_bits;
+       if (chcr & USB_DMACHCR_NULL) {
+               /* An interruption of TE will happen after we set FTE */
+               mask |= USB_DMACHCR_NULL;
+               chcr |= USB_DMACHCR_FTE;
+               ret |= IRQ_HANDLED;
+       }
+       usb_dmac_chan_write(chan, USB_DMACHCR, chcr & ~mask);
+
+       if (chcr & check_bits) {
+               usb_dmac_isr_transfer_end(chan);
+               ret |= IRQ_HANDLED;
+       }
+
+       spin_unlock(&chan->vc.lock);
+
+       return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * OF xlate and channel filter
+ */
+
+static bool usb_dmac_chan_filter(struct dma_chan *chan, void *arg)
+{
+       struct usb_dmac_chan *uchan = to_usb_dmac_chan(chan);
+       struct of_phandle_args *dma_spec = arg;
+
+       if (dma_spec->np != chan->device->dev->of_node)
+               return false;
+
+       /* USB-DMAC should be used with fixed usb controller's FIFO */
+       if (uchan->index != dma_spec->args[0])
+               return false;
+
+       return true;
+}
+
+static struct dma_chan *usb_dmac_of_xlate(struct of_phandle_args *dma_spec,
+                                         struct of_dma *ofdma)
+{
+       struct usb_dmac_chan *uchan;
+       struct dma_chan *chan;
+       dma_cap_mask_t mask;
+
+       if (dma_spec->args_count != 1)
+               return NULL;
+
+       /* Only slave DMA channels can be allocated via DT */
+       dma_cap_zero(mask);
+       dma_cap_set(DMA_SLAVE, mask);
+
+       chan = dma_request_channel(mask, usb_dmac_chan_filter, dma_spec);
+       if (!chan)
+               return NULL;
+
+       uchan = to_usb_dmac_chan(chan);
+
+       return chan;
+}
+
+/* -----------------------------------------------------------------------------
+ * Power management
+ */
+
+#ifdef CONFIG_PM
+static int usb_dmac_runtime_suspend(struct device *dev)
+{
+       struct usb_dmac *dmac = dev_get_drvdata(dev);
+       int i;
+
+       for (i = 0; i < dmac->n_channels; ++i)
+               usb_dmac_chan_halt(&dmac->channels[i]);
+
+       return 0;
+}
+
+static int usb_dmac_runtime_resume(struct device *dev)
+{
+       struct usb_dmac *dmac = dev_get_drvdata(dev);
+
+       return usb_dmac_init(dmac);
+}
+#endif /* CONFIG_PM */
+
+static const struct dev_pm_ops usb_dmac_pm = {
+       SET_RUNTIME_PM_OPS(usb_dmac_runtime_suspend, usb_dmac_runtime_resume,
+                          NULL)
+};
+
+/* -----------------------------------------------------------------------------
+ * Probe and remove
+ */
+
+static int usb_dmac_chan_probe(struct usb_dmac *dmac,
+                              struct usb_dmac_chan *uchan,
+                              unsigned int index)
+{
+       struct platform_device *pdev = to_platform_device(dmac->dev);
+       char pdev_irqname[5];
+       char *irqname;
+       int ret;
+
+       uchan->index = index;
+       uchan->iomem = dmac->iomem + USB_DMAC_CHAN_OFFSET(index);
+
+       /* Request the channel interrupt. */
+       sprintf(pdev_irqname, "ch%u", index);
+       uchan->irq = platform_get_irq_byname(pdev, pdev_irqname);
+       if (uchan->irq < 0) {
+               dev_err(dmac->dev, "no IRQ specified for channel %u\n", index);
+               return -ENODEV;
+       }
+
+       irqname = devm_kasprintf(dmac->dev, GFP_KERNEL, "%s:%u",
+                                dev_name(dmac->dev), index);
+       if (!irqname)
+               return -ENOMEM;
+
+       ret = devm_request_irq(dmac->dev, uchan->irq, usb_dmac_isr_channel,
+                              IRQF_SHARED, irqname, uchan);
+       if (ret) {
+               dev_err(dmac->dev, "failed to request IRQ %u (%d)\n",
+                       uchan->irq, ret);
+               return ret;
+       }
+
+       uchan->vc.desc_free = usb_dmac_virt_desc_free;
+       vchan_init(&uchan->vc, &dmac->engine);
+       INIT_LIST_HEAD(&uchan->desc_freed);
+       INIT_LIST_HEAD(&uchan->desc_got);
+
+       return 0;
+}
+
+static int usb_dmac_parse_of(struct device *dev, struct usb_dmac *dmac)
+{
+       struct device_node *np = dev->of_node;
+       int ret;
+
+       ret = of_property_read_u32(np, "dma-channels", &dmac->n_channels);
+       if (ret < 0) {
+               dev_err(dev, "unable to read dma-channels property\n");
+               return ret;
+       }
+
+       if (dmac->n_channels <= 0 || dmac->n_channels >= 100) {
+               dev_err(dev, "invalid number of channels %u\n",
+                       dmac->n_channels);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int usb_dmac_probe(struct platform_device *pdev)
+{
+       const enum dma_slave_buswidth widths = USB_DMAC_SLAVE_BUSWIDTH;
+       struct dma_device *engine;
+       struct usb_dmac *dmac;
+       struct resource *mem;
+       unsigned int i;
+       int ret;
+
+       dmac = devm_kzalloc(&pdev->dev, sizeof(*dmac), GFP_KERNEL);
+       if (!dmac)
+               return -ENOMEM;
+
+       dmac->dev = &pdev->dev;
+       platform_set_drvdata(pdev, dmac);
+
+       ret = usb_dmac_parse_of(&pdev->dev, dmac);
+       if (ret < 0)
+               return ret;
+
+       dmac->channels = devm_kcalloc(&pdev->dev, dmac->n_channels,
+                                     sizeof(*dmac->channels), GFP_KERNEL);
+       if (!dmac->channels)
+               return -ENOMEM;
+
+       /* Request resources. */
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       dmac->iomem = devm_ioremap_resource(&pdev->dev, mem);
+       if (IS_ERR(dmac->iomem))
+               return PTR_ERR(dmac->iomem);
+
+       /* Enable runtime PM and initialize the device. */
+       pm_runtime_enable(&pdev->dev);
+       ret = pm_runtime_get_sync(&pdev->dev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "runtime PM get sync failed (%d)\n", ret);
+               return ret;
+       }
+
+       ret = usb_dmac_init(dmac);
+       pm_runtime_put(&pdev->dev);
+
+       if (ret) {
+               dev_err(&pdev->dev, "failed to reset device\n");
+               goto error;
+       }
+
+       /* Initialize the channels. */
+       INIT_LIST_HEAD(&dmac->engine.channels);
+
+       for (i = 0; i < dmac->n_channels; ++i) {
+               ret = usb_dmac_chan_probe(dmac, &dmac->channels[i], i);
+               if (ret < 0)
+                       goto error;
+       }
+
+       /* Register the DMAC as a DMA provider for DT. */
+       ret = of_dma_controller_register(pdev->dev.of_node, usb_dmac_of_xlate,
+                                        NULL);
+       if (ret < 0)
+               goto error;
+
+       /*
+        * Register the DMA engine device.
+        *
+        * Default transfer size of 32 bytes requires 32-byte alignment.
+        */
+       engine = &dmac->engine;
+       dma_cap_set(DMA_SLAVE, engine->cap_mask);
+
+       engine->dev = &pdev->dev;
+
+       engine->src_addr_widths = widths;
+       engine->dst_addr_widths = widths;
+       engine->directions = BIT(DMA_MEM_TO_DEV) | BIT(DMA_DEV_TO_MEM);
+       engine->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
+
+       engine->device_alloc_chan_resources = usb_dmac_alloc_chan_resources;
+       engine->device_free_chan_resources = usb_dmac_free_chan_resources;
+       engine->device_prep_slave_sg = usb_dmac_prep_slave_sg;
+       engine->device_terminate_all = usb_dmac_chan_terminate_all;
+       engine->device_tx_status = usb_dmac_tx_status;
+       engine->device_issue_pending = usb_dmac_issue_pending;
+
+       ret = dma_async_device_register(engine);
+       if (ret < 0)
+               goto error;
+
+       return 0;
+
+error:
+       of_dma_controller_free(pdev->dev.of_node);
+       pm_runtime_disable(&pdev->dev);
+       return ret;
+}
+
+static void usb_dmac_chan_remove(struct usb_dmac *dmac,
+                                struct usb_dmac_chan *uchan)
+{
+       usb_dmac_chan_halt(uchan);
+       devm_free_irq(dmac->dev, uchan->irq, uchan);
+}
+
+static int usb_dmac_remove(struct platform_device *pdev)
+{
+       struct usb_dmac *dmac = platform_get_drvdata(pdev);
+       int i;
+
+       for (i = 0; i < dmac->n_channels; ++i)
+               usb_dmac_chan_remove(dmac, &dmac->channels[i]);
+       of_dma_controller_free(pdev->dev.of_node);
+       dma_async_device_unregister(&dmac->engine);
+
+       pm_runtime_disable(&pdev->dev);
+
+       return 0;
+}
+
+static void usb_dmac_shutdown(struct platform_device *pdev)
+{
+       struct usb_dmac *dmac = platform_get_drvdata(pdev);
+
+       usb_dmac_stop(dmac);
+}
+
+static const struct of_device_id usb_dmac_of_ids[] = {
+       { .compatible = "renesas,usb-dmac", },
+       { /* Sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, usb_dmac_of_ids);
+
+static struct platform_driver usb_dmac_driver = {
+       .driver         = {
+               .pm     = &usb_dmac_pm,
+               .name   = "usb-dmac",
+               .of_match_table = usb_dmac_of_ids,
+       },
+       .probe          = usb_dmac_probe,
+       .remove         = usb_dmac_remove,
+       .shutdown       = usb_dmac_shutdown,
+};
+
+module_platform_driver(usb_dmac_driver);
+
+MODULE_DESCRIPTION("Renesas USB DMA Controller Driver");
+MODULE_AUTHOR("Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>");
+MODULE_LICENSE("GPL v2");
index d0086e9f20824efa697144a8ea4f5adf345f3635..a1afda43b8ef2b2278c523f6cc89b0b09aae9eec 100644 (file)
@@ -896,7 +896,7 @@ static const struct dev_pm_ops sirfsoc_dma_pm_ops = {
        SET_SYSTEM_SLEEP_PM_OPS(sirfsoc_dma_pm_suspend, sirfsoc_dma_pm_resume)
 };
 
-static struct of_device_id sirfsoc_dma_match[] = {
+static const struct of_device_id sirfsoc_dma_match[] = {
        { .compatible = "sirf,prima2-dmac", },
        { .compatible = "sirf,marco-dmac", },
        {},
index 1332b1d4d541cb37c99f4a4ada988f3cbaee0f7f..3c10f034d4b935490113a7f8471ff08053cf7c3c 100644 (file)
@@ -2514,7 +2514,8 @@ static struct dma_async_tx_descriptor *d40_prep_memcpy(struct dma_chan *chan,
        sg_dma_len(&dst_sg) = size;
        sg_dma_len(&src_sg) = size;
 
-       return d40_prep_sg(chan, &src_sg, &dst_sg, 1, DMA_NONE, dma_flags);
+       return d40_prep_sg(chan, &src_sg, &dst_sg, 1,
+                          DMA_MEM_TO_MEM, dma_flags);
 }
 
 static struct dma_async_tx_descriptor *
@@ -2526,7 +2527,8 @@ d40_prep_memcpy_sg(struct dma_chan *chan,
        if (dst_nents != src_nents)
                return NULL;
 
-       return d40_prep_sg(chan, src_sg, dst_sg, src_nents, DMA_NONE, dma_flags);
+       return d40_prep_sg(chan, src_sg, dst_sg, src_nents,
+                          DMA_MEM_TO_MEM, dma_flags);
 }
 
 static struct dma_async_tx_descriptor *
index 7ebcf9bec6984c675b0ad42f50879171e9e5f83c..11e536586812facd94b00e15cf0d278fa2c9a78d 100644 (file)
@@ -796,11 +796,6 @@ static void sun6i_dma_issue_pending(struct dma_chan *chan)
        spin_unlock_irqrestore(&vchan->vc.lock, flags);
 }
 
-static int sun6i_dma_alloc_chan_resources(struct dma_chan *chan)
-{
-       return 0;
-}
-
 static void sun6i_dma_free_chan_resources(struct dma_chan *chan)
 {
        struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(chan->device);
@@ -896,7 +891,7 @@ static struct sun6i_dma_config sun8i_a23_dma_cfg = {
        .nr_max_vchans   = 37,
 };
 
-static struct of_device_id sun6i_dma_match[] = {
+static const struct of_device_id sun6i_dma_match[] = {
        { .compatible = "allwinner,sun6i-a31-dma", .data = &sun6i_a31_dma_cfg },
        { .compatible = "allwinner,sun8i-a23-dma", .data = &sun8i_a23_dma_cfg },
        { /* sentinel */ }
@@ -957,7 +952,6 @@ static int sun6i_dma_probe(struct platform_device *pdev)
        dma_cap_set(DMA_SLAVE, sdc->slave.cap_mask);
 
        INIT_LIST_HEAD(&sdc->slave.channels);
-       sdc->slave.device_alloc_chan_resources  = sun6i_dma_alloc_chan_resources;
        sdc->slave.device_free_chan_resources   = sun6i_dma_free_chan_resources;
        sdc->slave.device_tx_status             = sun6i_dma_tx_status;
        sdc->slave.device_issue_pending         = sun6i_dma_issue_pending;
diff --git a/drivers/dma/xgene-dma.c b/drivers/dma/xgene-dma.c
new file mode 100755 (executable)
index 0000000..f52e375
--- /dev/null
@@ -0,0 +1,2089 @@
+/*
+ * Applied Micro X-Gene SoC DMA engine Driver
+ *
+ * Copyright (c) 2015, Applied Micro Circuits Corporation
+ * Authors: Rameshwar Prasad Sahu <rsahu@apm.com>
+ *         Loc Ho <lho@apm.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * NOTE: PM support is currently not available.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/dmapool.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+
+#include "dmaengine.h"
+
+/* X-Gene DMA ring csr registers and bit definations */
+#define XGENE_DMA_RING_CONFIG                  0x04
+#define XGENE_DMA_RING_ENABLE                  BIT(31)
+#define XGENE_DMA_RING_ID                      0x08
+#define XGENE_DMA_RING_ID_SETUP(v)             ((v) | BIT(31))
+#define XGENE_DMA_RING_ID_BUF                  0x0C
+#define XGENE_DMA_RING_ID_BUF_SETUP(v)         (((v) << 9) | BIT(21))
+#define XGENE_DMA_RING_THRESLD0_SET1           0x30
+#define XGENE_DMA_RING_THRESLD0_SET1_VAL       0X64
+#define XGENE_DMA_RING_THRESLD1_SET1           0x34
+#define XGENE_DMA_RING_THRESLD1_SET1_VAL       0xC8
+#define XGENE_DMA_RING_HYSTERESIS              0x68
+#define XGENE_DMA_RING_HYSTERESIS_VAL          0xFFFFFFFF
+#define XGENE_DMA_RING_STATE                   0x6C
+#define XGENE_DMA_RING_STATE_WR_BASE           0x70
+#define XGENE_DMA_RING_NE_INT_MODE             0x017C
+#define XGENE_DMA_RING_NE_INT_MODE_SET(m, v)   \
+       ((m) = ((m) & ~BIT(31 - (v))) | BIT(31 - (v)))
+#define XGENE_DMA_RING_NE_INT_MODE_RESET(m, v) \
+       ((m) &= (~BIT(31 - (v))))
+#define XGENE_DMA_RING_CLKEN                   0xC208
+#define XGENE_DMA_RING_SRST                    0xC200
+#define XGENE_DMA_RING_MEM_RAM_SHUTDOWN                0xD070
+#define XGENE_DMA_RING_BLK_MEM_RDY             0xD074
+#define XGENE_DMA_RING_BLK_MEM_RDY_VAL         0xFFFFFFFF
+#define XGENE_DMA_RING_DESC_CNT(v)             (((v) & 0x0001FFFE) >> 1)
+#define XGENE_DMA_RING_ID_GET(owner, num)      (((owner) << 6) | (num))
+#define XGENE_DMA_RING_DST_ID(v)               ((1 << 10) | (v))
+#define XGENE_DMA_RING_CMD_OFFSET              0x2C
+#define XGENE_DMA_RING_CMD_BASE_OFFSET(v)      ((v) << 6)
+#define XGENE_DMA_RING_COHERENT_SET(m)         \
+       (((u32 *)(m))[2] |= BIT(4))
+#define XGENE_DMA_RING_ADDRL_SET(m, v)         \
+       (((u32 *)(m))[2] |= (((v) >> 8) << 5))
+#define XGENE_DMA_RING_ADDRH_SET(m, v)         \
+       (((u32 *)(m))[3] |= ((v) >> 35))
+#define XGENE_DMA_RING_ACCEPTLERR_SET(m)       \
+       (((u32 *)(m))[3] |= BIT(19))
+#define XGENE_DMA_RING_SIZE_SET(m, v)          \
+       (((u32 *)(m))[3] |= ((v) << 23))
+#define XGENE_DMA_RING_RECOMBBUF_SET(m)                \
+       (((u32 *)(m))[3] |= BIT(27))
+#define XGENE_DMA_RING_RECOMTIMEOUTL_SET(m)    \
+       (((u32 *)(m))[3] |= (0x7 << 28))
+#define XGENE_DMA_RING_RECOMTIMEOUTH_SET(m)    \
+       (((u32 *)(m))[4] |= 0x3)
+#define XGENE_DMA_RING_SELTHRSH_SET(m)         \
+       (((u32 *)(m))[4] |= BIT(3))
+#define XGENE_DMA_RING_TYPE_SET(m, v)          \
+       (((u32 *)(m))[4] |= ((v) << 19))
+
+/* X-Gene DMA device csr registers and bit definitions */
+#define XGENE_DMA_IPBRR                                0x0
+#define XGENE_DMA_DEV_ID_RD(v)                 ((v) & 0x00000FFF)
+#define XGENE_DMA_BUS_ID_RD(v)                 (((v) >> 12) & 3)
+#define XGENE_DMA_REV_NO_RD(v)                 (((v) >> 14) & 3)
+#define XGENE_DMA_GCR                          0x10
+#define XGENE_DMA_CH_SETUP(v)                  \
+       ((v) = ((v) & ~0x000FFFFF) | 0x000AAFFF)
+#define XGENE_DMA_ENABLE(v)                    ((v) |= BIT(31))
+#define XGENE_DMA_DISABLE(v)                   ((v) &= ~BIT(31))
+#define XGENE_DMA_RAID6_CONT                   0x14
+#define XGENE_DMA_RAID6_MULTI_CTRL(v)          ((v) << 24)
+#define XGENE_DMA_INT                          0x70
+#define XGENE_DMA_INT_MASK                     0x74
+#define XGENE_DMA_INT_ALL_MASK                 0xFFFFFFFF
+#define XGENE_DMA_INT_ALL_UNMASK               0x0
+#define XGENE_DMA_INT_MASK_SHIFT               0x14
+#define XGENE_DMA_RING_INT0_MASK               0x90A0
+#define XGENE_DMA_RING_INT1_MASK               0x90A8
+#define XGENE_DMA_RING_INT2_MASK               0x90B0
+#define XGENE_DMA_RING_INT3_MASK               0x90B8
+#define XGENE_DMA_RING_INT4_MASK               0x90C0
+#define XGENE_DMA_CFG_RING_WQ_ASSOC            0x90E0
+#define XGENE_DMA_ASSOC_RING_MNGR1             0xFFFFFFFF
+#define XGENE_DMA_MEM_RAM_SHUTDOWN             0xD070
+#define XGENE_DMA_BLK_MEM_RDY                  0xD074
+#define XGENE_DMA_BLK_MEM_RDY_VAL              0xFFFFFFFF
+
+/* X-Gene SoC EFUSE csr register and bit defination */
+#define XGENE_SOC_JTAG1_SHADOW                 0x18
+#define XGENE_DMA_PQ_DISABLE_MASK              BIT(13)
+
+/* X-Gene DMA Descriptor format */
+#define XGENE_DMA_DESC_NV_BIT                  BIT_ULL(50)
+#define XGENE_DMA_DESC_IN_BIT                  BIT_ULL(55)
+#define XGENE_DMA_DESC_C_BIT                   BIT_ULL(63)
+#define XGENE_DMA_DESC_DR_BIT                  BIT_ULL(61)
+#define XGENE_DMA_DESC_ELERR_POS               46
+#define XGENE_DMA_DESC_RTYPE_POS               56
+#define XGENE_DMA_DESC_LERR_POS                        60
+#define XGENE_DMA_DESC_FLYBY_POS               4
+#define XGENE_DMA_DESC_BUFLEN_POS              48
+#define XGENE_DMA_DESC_HOENQ_NUM_POS           48
+
+#define XGENE_DMA_DESC_NV_SET(m)               \
+       (((u64 *)(m))[0] |= XGENE_DMA_DESC_NV_BIT)
+#define XGENE_DMA_DESC_IN_SET(m)               \
+       (((u64 *)(m))[0] |= XGENE_DMA_DESC_IN_BIT)
+#define XGENE_DMA_DESC_RTYPE_SET(m, v)         \
+       (((u64 *)(m))[0] |= ((u64)(v) << XGENE_DMA_DESC_RTYPE_POS))
+#define XGENE_DMA_DESC_BUFADDR_SET(m, v)       \
+       (((u64 *)(m))[0] |= (v))
+#define XGENE_DMA_DESC_BUFLEN_SET(m, v)                \
+       (((u64 *)(m))[0] |= ((u64)(v) << XGENE_DMA_DESC_BUFLEN_POS))
+#define XGENE_DMA_DESC_C_SET(m)                        \
+       (((u64 *)(m))[1] |= XGENE_DMA_DESC_C_BIT)
+#define XGENE_DMA_DESC_FLYBY_SET(m, v)         \
+       (((u64 *)(m))[2] |= ((v) << XGENE_DMA_DESC_FLYBY_POS))
+#define XGENE_DMA_DESC_MULTI_SET(m, v, i)      \
+       (((u64 *)(m))[2] |= ((u64)(v) << (((i) + 1) * 8)))
+#define XGENE_DMA_DESC_DR_SET(m)               \
+       (((u64 *)(m))[2] |= XGENE_DMA_DESC_DR_BIT)
+#define XGENE_DMA_DESC_DST_ADDR_SET(m, v)      \
+       (((u64 *)(m))[3] |= (v))
+#define XGENE_DMA_DESC_H0ENQ_NUM_SET(m, v)     \
+       (((u64 *)(m))[3] |= ((u64)(v) << XGENE_DMA_DESC_HOENQ_NUM_POS))
+#define XGENE_DMA_DESC_ELERR_RD(m)             \
+       (((m) >> XGENE_DMA_DESC_ELERR_POS) & 0x3)
+#define XGENE_DMA_DESC_LERR_RD(m)              \
+       (((m) >> XGENE_DMA_DESC_LERR_POS) & 0x7)
+#define XGENE_DMA_DESC_STATUS(elerr, lerr)     \
+       (((elerr) << 4) | (lerr))
+
+/* X-Gene DMA descriptor empty s/w signature */
+#define XGENE_DMA_DESC_EMPTY_INDEX             0
+#define XGENE_DMA_DESC_EMPTY_SIGNATURE         ~0ULL
+#define XGENE_DMA_DESC_SET_EMPTY(m)            \
+       (((u64 *)(m))[XGENE_DMA_DESC_EMPTY_INDEX] =     \
+        XGENE_DMA_DESC_EMPTY_SIGNATURE)
+#define XGENE_DMA_DESC_IS_EMPTY(m)             \
+       (((u64 *)(m))[XGENE_DMA_DESC_EMPTY_INDEX] ==    \
+        XGENE_DMA_DESC_EMPTY_SIGNATURE)
+
+/* X-Gene DMA configurable parameters defines */
+#define XGENE_DMA_RING_NUM             512
+#define XGENE_DMA_BUFNUM               0x0
+#define XGENE_DMA_CPU_BUFNUM           0x18
+#define XGENE_DMA_RING_OWNER_DMA       0x03
+#define XGENE_DMA_RING_OWNER_CPU       0x0F
+#define XGENE_DMA_RING_TYPE_REGULAR    0x01
+#define XGENE_DMA_RING_WQ_DESC_SIZE    32      /* 32 Bytes */
+#define XGENE_DMA_RING_NUM_CONFIG      5
+#define XGENE_DMA_MAX_CHANNEL          4
+#define XGENE_DMA_XOR_CHANNEL          0
+#define XGENE_DMA_PQ_CHANNEL           1
+#define XGENE_DMA_MAX_BYTE_CNT         0x4000  /* 16 KB */
+#define XGENE_DMA_MAX_64B_DESC_BYTE_CNT        0x14000 /* 80 KB */
+#define XGENE_DMA_XOR_ALIGNMENT                6       /* 64 Bytes */
+#define XGENE_DMA_MAX_XOR_SRC          5
+#define XGENE_DMA_16K_BUFFER_LEN_CODE  0x0
+#define XGENE_DMA_INVALID_LEN_CODE     0x7800
+
+/* X-Gene DMA descriptor error codes */
+#define ERR_DESC_AXI                   0x01
+#define ERR_BAD_DESC                   0x02
+#define ERR_READ_DATA_AXI              0x03
+#define ERR_WRITE_DATA_AXI             0x04
+#define ERR_FBP_TIMEOUT                        0x05
+#define ERR_ECC                                0x06
+#define ERR_DIFF_SIZE                  0x08
+#define ERR_SCT_GAT_LEN                        0x09
+#define ERR_CRC_ERR                    0x11
+#define ERR_CHKSUM                     0x12
+#define ERR_DIF                                0x13
+
+/* X-Gene DMA error interrupt codes */
+#define ERR_DIF_SIZE_INT               0x0
+#define ERR_GS_ERR_INT                 0x1
+#define ERR_FPB_TIMEO_INT              0x2
+#define ERR_WFIFO_OVF_INT              0x3
+#define ERR_RFIFO_OVF_INT              0x4
+#define ERR_WR_TIMEO_INT               0x5
+#define ERR_RD_TIMEO_INT               0x6
+#define ERR_WR_ERR_INT                 0x7
+#define ERR_RD_ERR_INT                 0x8
+#define ERR_BAD_DESC_INT               0x9
+#define ERR_DESC_DST_INT               0xA
+#define ERR_DESC_SRC_INT               0xB
+
+/* X-Gene DMA flyby operation code */
+#define FLYBY_2SRC_XOR                 0x8
+#define FLYBY_3SRC_XOR                 0x9
+#define FLYBY_4SRC_XOR                 0xA
+#define FLYBY_5SRC_XOR                 0xB
+
+/* X-Gene DMA SW descriptor flags */
+#define XGENE_DMA_FLAG_64B_DESC                BIT(0)
+
+/* Define to dump X-Gene DMA descriptor */
+#define XGENE_DMA_DESC_DUMP(desc, m)   \
+       print_hex_dump(KERN_ERR, (m),   \
+                       DUMP_PREFIX_ADDRESS, 16, 8, (desc), 32, 0)
+
+#define to_dma_desc_sw(tx)             \
+       container_of(tx, struct xgene_dma_desc_sw, tx)
+#define to_dma_chan(dchan)             \
+       container_of(dchan, struct xgene_dma_chan, dma_chan)
+
+#define chan_dbg(chan, fmt, arg...)    \
+       dev_dbg(chan->dev, "%s: " fmt, chan->name, ##arg)
+#define chan_err(chan, fmt, arg...)    \
+       dev_err(chan->dev, "%s: " fmt, chan->name, ##arg)
+
+struct xgene_dma_desc_hw {
+       u64 m0;
+       u64 m1;
+       u64 m2;
+       u64 m3;
+};
+
+enum xgene_dma_ring_cfgsize {
+       XGENE_DMA_RING_CFG_SIZE_512B,
+       XGENE_DMA_RING_CFG_SIZE_2KB,
+       XGENE_DMA_RING_CFG_SIZE_16KB,
+       XGENE_DMA_RING_CFG_SIZE_64KB,
+       XGENE_DMA_RING_CFG_SIZE_512KB,
+       XGENE_DMA_RING_CFG_SIZE_INVALID
+};
+
+struct xgene_dma_ring {
+       struct xgene_dma *pdma;
+       u8 buf_num;
+       u16 id;
+       u16 num;
+       u16 head;
+       u16 owner;
+       u16 slots;
+       u16 dst_ring_num;
+       u32 size;
+       void __iomem *cmd;
+       void __iomem *cmd_base;
+       dma_addr_t desc_paddr;
+       u32 state[XGENE_DMA_RING_NUM_CONFIG];
+       enum xgene_dma_ring_cfgsize cfgsize;
+       union {
+               void *desc_vaddr;
+               struct xgene_dma_desc_hw *desc_hw;
+       };
+};
+
+struct xgene_dma_desc_sw {
+       struct xgene_dma_desc_hw desc1;
+       struct xgene_dma_desc_hw desc2;
+       u32 flags;
+       struct list_head node;
+       struct list_head tx_list;
+       struct dma_async_tx_descriptor tx;
+};
+
+/**
+ * struct xgene_dma_chan - internal representation of an X-Gene DMA channel
+ * @dma_chan: dmaengine channel object member
+ * @pdma: X-Gene DMA device structure reference
+ * @dev: struct device reference for dma mapping api
+ * @id: raw id of this channel
+ * @rx_irq: channel IRQ
+ * @name: name of X-Gene DMA channel
+ * @lock: serializes enqueue/dequeue operations to the descriptor pool
+ * @pending: number of transaction request pushed to DMA controller for
+ *     execution, but still waiting for completion,
+ * @max_outstanding: max number of outstanding request we can push to channel
+ * @ld_pending: descriptors which are queued to run, but have not yet been
+ *     submitted to the hardware for execution
+ * @ld_running: descriptors which are currently being executing by the hardware
+ * @ld_completed: descriptors which have finished execution by the hardware.
+ *     These descriptors have already had their cleanup actions run. They
+ *     are waiting for the ACK bit to be set by the async tx API.
+ * @desc_pool: descriptor pool for DMA operations
+ * @tasklet: bottom half where all completed descriptors cleans
+ * @tx_ring: transmit ring descriptor that we use to prepare actual
+ *     descriptors for further executions
+ * @rx_ring: receive ring descriptor that we use to get completed DMA
+ *     descriptors during cleanup time
+ */
+struct xgene_dma_chan {
+       struct dma_chan dma_chan;
+       struct xgene_dma *pdma;
+       struct device *dev;
+       int id;
+       int rx_irq;
+       char name[10];
+       spinlock_t lock;
+       int pending;
+       int max_outstanding;
+       struct list_head ld_pending;
+       struct list_head ld_running;
+       struct list_head ld_completed;
+       struct dma_pool *desc_pool;
+       struct tasklet_struct tasklet;
+       struct xgene_dma_ring tx_ring;
+       struct xgene_dma_ring rx_ring;
+};
+
+/**
+ * struct xgene_dma - internal representation of an X-Gene DMA device
+ * @err_irq: DMA error irq number
+ * @ring_num: start id number for DMA ring
+ * @csr_dma: base for DMA register access
+ * @csr_ring: base for DMA ring register access
+ * @csr_ring_cmd: base for DMA ring command register access
+ * @csr_efuse: base for efuse register access
+ * @dma_dev: embedded struct dma_device
+ * @chan: reference to X-Gene DMA channels
+ */
+struct xgene_dma {
+       struct device *dev;
+       struct clk *clk;
+       int err_irq;
+       int ring_num;
+       void __iomem *csr_dma;
+       void __iomem *csr_ring;
+       void __iomem *csr_ring_cmd;
+       void __iomem *csr_efuse;
+       struct dma_device dma_dev[XGENE_DMA_MAX_CHANNEL];
+       struct xgene_dma_chan chan[XGENE_DMA_MAX_CHANNEL];
+};
+
+static const char * const xgene_dma_desc_err[] = {
+       [ERR_DESC_AXI] = "AXI error when reading src/dst link list",
+       [ERR_BAD_DESC] = "ERR or El_ERR fields not set to zero in desc",
+       [ERR_READ_DATA_AXI] = "AXI error when reading data",
+       [ERR_WRITE_DATA_AXI] = "AXI error when writing data",
+       [ERR_FBP_TIMEOUT] = "Timeout on bufpool fetch",
+       [ERR_ECC] = "ECC double bit error",
+       [ERR_DIFF_SIZE] = "Bufpool too small to hold all the DIF result",
+       [ERR_SCT_GAT_LEN] = "Gather and scatter data length not same",
+       [ERR_CRC_ERR] = "CRC error",
+       [ERR_CHKSUM] = "Checksum error",
+       [ERR_DIF] = "DIF error",
+};
+
+static const char * const xgene_dma_err[] = {
+       [ERR_DIF_SIZE_INT] = "DIF size error",
+       [ERR_GS_ERR_INT] = "Gather scatter not same size error",
+       [ERR_FPB_TIMEO_INT] = "Free pool time out error",
+       [ERR_WFIFO_OVF_INT] = "Write FIFO over flow error",
+       [ERR_RFIFO_OVF_INT] = "Read FIFO over flow error",
+       [ERR_WR_TIMEO_INT] = "Write time out error",
+       [ERR_RD_TIMEO_INT] = "Read time out error",
+       [ERR_WR_ERR_INT] = "HBF bus write error",
+       [ERR_RD_ERR_INT] = "HBF bus read error",
+       [ERR_BAD_DESC_INT] = "Ring descriptor HE0 not set error",
+       [ERR_DESC_DST_INT] = "HFB reading dst link address error",
+       [ERR_DESC_SRC_INT] = "HFB reading src link address error",
+};
+
+static bool is_pq_enabled(struct xgene_dma *pdma)
+{
+       u32 val;
+
+       val = ioread32(pdma->csr_efuse + XGENE_SOC_JTAG1_SHADOW);
+       return !(val & XGENE_DMA_PQ_DISABLE_MASK);
+}
+
+static void xgene_dma_cpu_to_le64(u64 *desc, int count)
+{
+       int i;
+
+       for (i = 0; i < count; i++)
+               desc[i] = cpu_to_le64(desc[i]);
+}
+
+static u16 xgene_dma_encode_len(u32 len)
+{
+       return (len < XGENE_DMA_MAX_BYTE_CNT) ?
+               len : XGENE_DMA_16K_BUFFER_LEN_CODE;
+}
+
+static u8 xgene_dma_encode_xor_flyby(u32 src_cnt)
+{
+       static u8 flyby_type[] = {
+               FLYBY_2SRC_XOR, /* Dummy */
+               FLYBY_2SRC_XOR, /* Dummy */
+               FLYBY_2SRC_XOR,
+               FLYBY_3SRC_XOR,
+               FLYBY_4SRC_XOR,
+               FLYBY_5SRC_XOR
+       };
+
+       return flyby_type[src_cnt];
+}
+
+static u32 xgene_dma_ring_desc_cnt(struct xgene_dma_ring *ring)
+{
+       u32 __iomem *cmd_base = ring->cmd_base;
+       u32 ring_state = ioread32(&cmd_base[1]);
+
+       return XGENE_DMA_RING_DESC_CNT(ring_state);
+}
+
+static void xgene_dma_set_src_buffer(void *ext8, size_t *len,
+                                    dma_addr_t *paddr)
+{
+       size_t nbytes = (*len < XGENE_DMA_MAX_BYTE_CNT) ?
+                       *len : XGENE_DMA_MAX_BYTE_CNT;
+
+       XGENE_DMA_DESC_BUFADDR_SET(ext8, *paddr);
+       XGENE_DMA_DESC_BUFLEN_SET(ext8, xgene_dma_encode_len(nbytes));
+       *len -= nbytes;
+       *paddr += nbytes;
+}
+
+static void xgene_dma_invalidate_buffer(void *ext8)
+{
+       XGENE_DMA_DESC_BUFLEN_SET(ext8, XGENE_DMA_INVALID_LEN_CODE);
+}
+
+static void *xgene_dma_lookup_ext8(u64 *desc, int idx)
+{
+       return (idx % 2) ? (desc + idx - 1) : (desc + idx + 1);
+}
+
+static void xgene_dma_init_desc(void *desc, u16 dst_ring_num)
+{
+       XGENE_DMA_DESC_C_SET(desc); /* Coherent IO */
+       XGENE_DMA_DESC_IN_SET(desc);
+       XGENE_DMA_DESC_H0ENQ_NUM_SET(desc, dst_ring_num);
+       XGENE_DMA_DESC_RTYPE_SET(desc, XGENE_DMA_RING_OWNER_DMA);
+}
+
+static void xgene_dma_prep_cpy_desc(struct xgene_dma_chan *chan,
+                                   struct xgene_dma_desc_sw *desc_sw,
+                                   dma_addr_t dst, dma_addr_t src,
+                                   size_t len)
+{
+       void *desc1, *desc2;
+       int i;
+
+       /* Get 1st descriptor */
+       desc1 = &desc_sw->desc1;
+       xgene_dma_init_desc(desc1, chan->tx_ring.dst_ring_num);
+
+       /* Set destination address */
+       XGENE_DMA_DESC_DR_SET(desc1);
+       XGENE_DMA_DESC_DST_ADDR_SET(desc1, dst);
+
+       /* Set 1st source address */
+       xgene_dma_set_src_buffer(desc1 + 8, &len, &src);
+
+       if (len <= 0) {
+               desc2 = NULL;
+               goto skip_additional_src;
+       }
+
+       /*
+        * We need to split this source buffer,
+        * and need to use 2nd descriptor
+        */
+       desc2 = &desc_sw->desc2;
+       XGENE_DMA_DESC_NV_SET(desc1);
+
+       /* Set 2nd to 5th source address */
+       for (i = 0; i < 4 && len; i++)
+               xgene_dma_set_src_buffer(xgene_dma_lookup_ext8(desc2, i),
+                                        &len, &src);
+
+       /* Invalidate unused source address field */
+       for (; i < 4; i++)
+               xgene_dma_invalidate_buffer(xgene_dma_lookup_ext8(desc2, i));
+
+       /* Updated flag that we have prepared 64B descriptor */
+       desc_sw->flags |= XGENE_DMA_FLAG_64B_DESC;
+
+skip_additional_src:
+       /* Hardware stores descriptor in little endian format */
+       xgene_dma_cpu_to_le64(desc1, 4);
+       if (desc2)
+               xgene_dma_cpu_to_le64(desc2, 4);
+}
+
+static void xgene_dma_prep_xor_desc(struct xgene_dma_chan *chan,
+                                   struct xgene_dma_desc_sw *desc_sw,
+                                   dma_addr_t *dst, dma_addr_t *src,
+                                   u32 src_cnt, size_t *nbytes,
+                                   const u8 *scf)
+{
+       void *desc1, *desc2;
+       size_t len = *nbytes;
+       int i;
+
+       desc1 = &desc_sw->desc1;
+       desc2 = &desc_sw->desc2;
+
+       /* Initialize DMA descriptor */
+       xgene_dma_init_desc(desc1, chan->tx_ring.dst_ring_num);
+
+       /* Set destination address */
+       XGENE_DMA_DESC_DR_SET(desc1);
+       XGENE_DMA_DESC_DST_ADDR_SET(desc1, *dst);
+
+       /* We have multiple source addresses, so need to set NV bit*/
+       XGENE_DMA_DESC_NV_SET(desc1);
+
+       /* Set flyby opcode */
+       XGENE_DMA_DESC_FLYBY_SET(desc1, xgene_dma_encode_xor_flyby(src_cnt));
+
+       /* Set 1st to 5th source addresses */
+       for (i = 0; i < src_cnt; i++) {
+               len = *nbytes;
+               xgene_dma_set_src_buffer((i == 0) ? (desc1 + 8) :
+                                        xgene_dma_lookup_ext8(desc2, i - 1),
+                                        &len, &src[i]);
+               XGENE_DMA_DESC_MULTI_SET(desc1, scf[i], i);
+       }
+
+       /* Hardware stores descriptor in little endian format */
+       xgene_dma_cpu_to_le64(desc1, 4);
+       xgene_dma_cpu_to_le64(desc2, 4);
+
+       /* Update meta data */
+       *nbytes = len;
+       *dst += XGENE_DMA_MAX_BYTE_CNT;
+
+       /* We need always 64B descriptor to perform xor or pq operations */
+       desc_sw->flags |= XGENE_DMA_FLAG_64B_DESC;
+}
+
+static dma_cookie_t xgene_dma_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+       struct xgene_dma_desc_sw *desc;
+       struct xgene_dma_chan *chan;
+       dma_cookie_t cookie;
+
+       if (unlikely(!tx))
+               return -EINVAL;
+
+       chan = to_dma_chan(tx->chan);
+       desc = to_dma_desc_sw(tx);
+
+       spin_lock_bh(&chan->lock);
+
+       cookie = dma_cookie_assign(tx);
+
+       /* Add this transaction list onto the tail of the pending queue */
+       list_splice_tail_init(&desc->tx_list, &chan->ld_pending);
+
+       spin_unlock_bh(&chan->lock);
+
+       return cookie;
+}
+
+static void xgene_dma_clean_descriptor(struct xgene_dma_chan *chan,
+                                      struct xgene_dma_desc_sw *desc)
+{
+       list_del(&desc->node);
+       chan_dbg(chan, "LD %p free\n", desc);
+       dma_pool_free(chan->desc_pool, desc, desc->tx.phys);
+}
+
+static struct xgene_dma_desc_sw *xgene_dma_alloc_descriptor(
+                                struct xgene_dma_chan *chan)
+{
+       struct xgene_dma_desc_sw *desc;
+       dma_addr_t phys;
+
+       desc = dma_pool_alloc(chan->desc_pool, GFP_NOWAIT, &phys);
+       if (!desc) {
+               chan_err(chan, "Failed to allocate LDs\n");
+               return NULL;
+       }
+
+       memset(desc, 0, sizeof(*desc));
+
+       INIT_LIST_HEAD(&desc->tx_list);
+       desc->tx.phys = phys;
+       desc->tx.tx_submit = xgene_dma_tx_submit;
+       dma_async_tx_descriptor_init(&desc->tx, &chan->dma_chan);
+
+       chan_dbg(chan, "LD %p allocated\n", desc);
+
+       return desc;
+}
+
+/**
+ * xgene_dma_clean_completed_descriptor - free all descriptors which
+ * has been completed and acked
+ * @chan: X-Gene DMA channel
+ *
+ * This function is used on all completed and acked descriptors.
+ */
+static void xgene_dma_clean_completed_descriptor(struct xgene_dma_chan *chan)
+{
+       struct xgene_dma_desc_sw *desc, *_desc;
+
+       /* Run the callback for each descriptor, in order */
+       list_for_each_entry_safe(desc, _desc, &chan->ld_completed, node) {
+               if (async_tx_test_ack(&desc->tx))
+                       xgene_dma_clean_descriptor(chan, desc);
+       }
+}
+
+/**
+ * xgene_dma_run_tx_complete_actions - cleanup a single link descriptor
+ * @chan: X-Gene DMA channel
+ * @desc: descriptor to cleanup and free
+ *
+ * This function is used on a descriptor which has been executed by the DMA
+ * controller. It will run any callbacks, submit any dependencies.
+ */
+static void xgene_dma_run_tx_complete_actions(struct xgene_dma_chan *chan,
+                                             struct xgene_dma_desc_sw *desc)
+{
+       struct dma_async_tx_descriptor *tx = &desc->tx;
+
+       /*
+        * If this is not the last transaction in the group,
+        * then no need to complete cookie and run any callback as
+        * this is not the tx_descriptor which had been sent to caller
+        * of this DMA request
+        */
+
+       if (tx->cookie == 0)
+               return;
+
+       dma_cookie_complete(tx);
+
+       /* Run the link descriptor callback function */
+       if (tx->callback)
+               tx->callback(tx->callback_param);
+
+       dma_descriptor_unmap(tx);
+
+       /* Run any dependencies */
+       dma_run_dependencies(tx);
+}
+
+/**
+ * xgene_dma_clean_running_descriptor - move the completed descriptor from
+ * ld_running to ld_completed
+ * @chan: X-Gene DMA channel
+ * @desc: the descriptor which is completed
+ *
+ * Free the descriptor directly if acked by async_tx api,
+ * else move it to queue ld_completed.
+ */
+static void xgene_dma_clean_running_descriptor(struct xgene_dma_chan *chan,
+                                              struct xgene_dma_desc_sw *desc)
+{
+       /* Remove from the list of running transactions */
+       list_del(&desc->node);
+
+       /*
+        * the client is allowed to attach dependent operations
+        * until 'ack' is set
+        */
+       if (!async_tx_test_ack(&desc->tx)) {
+               /*
+                * Move this descriptor to the list of descriptors which is
+                * completed, but still awaiting the 'ack' bit to be set.
+                */
+               list_add_tail(&desc->node, &chan->ld_completed);
+               return;
+       }
+
+       chan_dbg(chan, "LD %p free\n", desc);
+       dma_pool_free(chan->desc_pool, desc, desc->tx.phys);
+}
+
+static int xgene_chan_xfer_request(struct xgene_dma_ring *ring,
+                                  struct xgene_dma_desc_sw *desc_sw)
+{
+       struct xgene_dma_desc_hw *desc_hw;
+
+       /* Check if can push more descriptor to hw for execution */
+       if (xgene_dma_ring_desc_cnt(ring) > (ring->slots - 2))
+               return -EBUSY;
+
+       /* Get hw descriptor from DMA tx ring */
+       desc_hw = &ring->desc_hw[ring->head];
+
+       /*
+        * Increment the head count to point next
+        * descriptor for next time
+        */
+       if (++ring->head == ring->slots)
+               ring->head = 0;
+
+       /* Copy prepared sw descriptor data to hw descriptor */
+       memcpy(desc_hw, &desc_sw->desc1, sizeof(*desc_hw));
+
+       /*
+        * Check if we have prepared 64B descriptor,
+        * in this case we need one more hw descriptor
+        */
+       if (desc_sw->flags & XGENE_DMA_FLAG_64B_DESC) {
+               desc_hw = &ring->desc_hw[ring->head];
+
+               if (++ring->head == ring->slots)
+                       ring->head = 0;
+
+               memcpy(desc_hw, &desc_sw->desc2, sizeof(*desc_hw));
+       }
+
+       /* Notify the hw that we have descriptor ready for execution */
+       iowrite32((desc_sw->flags & XGENE_DMA_FLAG_64B_DESC) ?
+                 2 : 1, ring->cmd);
+
+       return 0;
+}
+
+/**
+ * xgene_chan_xfer_ld_pending - push any pending transactions to hw
+ * @chan : X-Gene DMA channel
+ *
+ * LOCKING: must hold chan->desc_lock
+ */
+static void xgene_chan_xfer_ld_pending(struct xgene_dma_chan *chan)
+{
+       struct xgene_dma_desc_sw *desc_sw, *_desc_sw;
+       int ret;
+
+       /*
+        * If the list of pending descriptors is empty, then we
+        * don't need to do any work at all
+        */
+       if (list_empty(&chan->ld_pending)) {
+               chan_dbg(chan, "No pending LDs\n");
+               return;
+       }
+
+       /*
+        * Move elements from the queue of pending transactions onto the list
+        * of running transactions and push it to hw for further executions
+        */
+       list_for_each_entry_safe(desc_sw, _desc_sw, &chan->ld_pending, node) {
+               /*
+                * Check if have pushed max number of transactions to hw
+                * as capable, so let's stop here and will push remaining
+                * elements from pening ld queue after completing some
+                * descriptors that we have already pushed
+                */
+               if (chan->pending >= chan->max_outstanding)
+                       return;
+
+               ret = xgene_chan_xfer_request(&chan->tx_ring, desc_sw);
+               if (ret)
+                       return;
+
+               /*
+                * Delete this element from ld pending queue and append it to
+                * ld running queue
+                */
+               list_move_tail(&desc_sw->node, &chan->ld_running);
+
+               /* Increment the pending transaction count */
+               chan->pending++;
+       }
+}
+
+/**
+ * xgene_dma_cleanup_descriptors - cleanup link descriptors which are completed
+ * and move them to ld_completed to free until flag 'ack' is set
+ * @chan: X-Gene DMA channel
+ *
+ * This function is used on descriptors which have been executed by the DMA
+ * controller. It will run any callbacks, submit any dependencies, then
+ * free these descriptors if flag 'ack' is set.
+ */
+static void xgene_dma_cleanup_descriptors(struct xgene_dma_chan *chan)
+{
+       struct xgene_dma_ring *ring = &chan->rx_ring;
+       struct xgene_dma_desc_sw *desc_sw, *_desc_sw;
+       struct xgene_dma_desc_hw *desc_hw;
+       u8 status;
+
+       /* Clean already completed and acked descriptors */
+       xgene_dma_clean_completed_descriptor(chan);
+
+       /* Run the callback for each descriptor, in order */
+       list_for_each_entry_safe(desc_sw, _desc_sw, &chan->ld_running, node) {
+               /* Get subsequent hw descriptor from DMA rx ring */
+               desc_hw = &ring->desc_hw[ring->head];
+
+               /* Check if this descriptor has been completed */
+               if (unlikely(XGENE_DMA_DESC_IS_EMPTY(desc_hw)))
+                       break;
+
+               if (++ring->head == ring->slots)
+                       ring->head = 0;
+
+               /* Check if we have any error with DMA transactions */
+               status = XGENE_DMA_DESC_STATUS(
+                               XGENE_DMA_DESC_ELERR_RD(le64_to_cpu(
+                                                       desc_hw->m0)),
+                               XGENE_DMA_DESC_LERR_RD(le64_to_cpu(
+                                                      desc_hw->m0)));
+               if (status) {
+                       /* Print the DMA error type */
+                       chan_err(chan, "%s\n", xgene_dma_desc_err[status]);
+
+                       /*
+                        * We have DMA transactions error here. Dump DMA Tx
+                        * and Rx descriptors for this request */
+                       XGENE_DMA_DESC_DUMP(&desc_sw->desc1,
+                                           "X-Gene DMA TX DESC1: ");
+
+                       if (desc_sw->flags & XGENE_DMA_FLAG_64B_DESC)
+                               XGENE_DMA_DESC_DUMP(&desc_sw->desc2,
+                                                   "X-Gene DMA TX DESC2: ");
+
+                       XGENE_DMA_DESC_DUMP(desc_hw,
+                                           "X-Gene DMA RX ERR DESC: ");
+               }
+
+               /* Notify the hw about this completed descriptor */
+               iowrite32(-1, ring->cmd);
+
+               /* Mark this hw descriptor as processed */
+               XGENE_DMA_DESC_SET_EMPTY(desc_hw);
+
+               xgene_dma_run_tx_complete_actions(chan, desc_sw);
+
+               xgene_dma_clean_running_descriptor(chan, desc_sw);
+
+               /*
+                * Decrement the pending transaction count
+                * as we have processed one
+                */
+               chan->pending--;
+       }
+
+       /*
+        * Start any pending transactions automatically
+        * In the ideal case, we keep the DMA controller busy while we go
+        * ahead and free the descriptors below.
+        */
+       xgene_chan_xfer_ld_pending(chan);
+}
+
+static int xgene_dma_alloc_chan_resources(struct dma_chan *dchan)
+{
+       struct xgene_dma_chan *chan = to_dma_chan(dchan);
+
+       /* Has this channel already been allocated? */
+       if (chan->desc_pool)
+               return 1;
+
+       chan->desc_pool = dma_pool_create(chan->name, chan->dev,
+                                         sizeof(struct xgene_dma_desc_sw),
+                                         0, 0);
+       if (!chan->desc_pool) {
+               chan_err(chan, "Failed to allocate descriptor pool\n");
+               return -ENOMEM;
+       }
+
+       chan_dbg(chan, "Allocate descripto pool\n");
+
+       return 1;
+}
+
+/**
+ * xgene_dma_free_desc_list - Free all descriptors in a queue
+ * @chan: X-Gene DMA channel
+ * @list: the list to free
+ *
+ * LOCKING: must hold chan->desc_lock
+ */
+static void xgene_dma_free_desc_list(struct xgene_dma_chan *chan,
+                                    struct list_head *list)
+{
+       struct xgene_dma_desc_sw *desc, *_desc;
+
+       list_for_each_entry_safe(desc, _desc, list, node)
+               xgene_dma_clean_descriptor(chan, desc);
+}
+
+static void xgene_dma_free_tx_desc_list(struct xgene_dma_chan *chan,
+                                       struct list_head *list)
+{
+       struct xgene_dma_desc_sw *desc, *_desc;
+
+       list_for_each_entry_safe(desc, _desc, list, node)
+               xgene_dma_clean_descriptor(chan, desc);
+}
+
+static void xgene_dma_free_chan_resources(struct dma_chan *dchan)
+{
+       struct xgene_dma_chan *chan = to_dma_chan(dchan);
+
+       chan_dbg(chan, "Free all resources\n");
+
+       if (!chan->desc_pool)
+               return;
+
+       spin_lock_bh(&chan->lock);
+
+       /* Process all running descriptor */
+       xgene_dma_cleanup_descriptors(chan);
+
+       /* Clean all link descriptor queues */
+       xgene_dma_free_desc_list(chan, &chan->ld_pending);
+       xgene_dma_free_desc_list(chan, &chan->ld_running);
+       xgene_dma_free_desc_list(chan, &chan->ld_completed);
+
+       spin_unlock_bh(&chan->lock);
+
+       /* Delete this channel DMA pool */
+       dma_pool_destroy(chan->desc_pool);
+       chan->desc_pool = NULL;
+}
+
+static struct dma_async_tx_descriptor *xgene_dma_prep_memcpy(
+       struct dma_chan *dchan, dma_addr_t dst, dma_addr_t src,
+       size_t len, unsigned long flags)
+{
+       struct xgene_dma_desc_sw *first = NULL, *new;
+       struct xgene_dma_chan *chan;
+       size_t copy;
+
+       if (unlikely(!dchan || !len))
+               return NULL;
+
+       chan = to_dma_chan(dchan);
+
+       do {
+               /* Allocate the link descriptor from DMA pool */
+               new = xgene_dma_alloc_descriptor(chan);
+               if (!new)
+                       goto fail;
+
+               /* Create the largest transaction possible */
+               copy = min_t(size_t, len, XGENE_DMA_MAX_64B_DESC_BYTE_CNT);
+
+               /* Prepare DMA descriptor */
+               xgene_dma_prep_cpy_desc(chan, new, dst, src, copy);
+
+               if (!first)
+                       first = new;
+
+               new->tx.cookie = 0;
+               async_tx_ack(&new->tx);
+
+               /* Update metadata */
+               len -= copy;
+               dst += copy;
+               src += copy;
+
+               /* Insert the link descriptor to the LD ring */
+               list_add_tail(&new->node, &first->tx_list);
+       } while (len);
+
+       new->tx.flags = flags; /* client is in control of this ack */
+       new->tx.cookie = -EBUSY;
+       list_splice(&first->tx_list, &new->tx_list);
+
+       return &new->tx;
+
+fail:
+       if (!first)
+               return NULL;
+
+       xgene_dma_free_tx_desc_list(chan, &first->tx_list);
+       return NULL;
+}
+
+static struct dma_async_tx_descriptor *xgene_dma_prep_sg(
+       struct dma_chan *dchan, struct scatterlist *dst_sg,
+       u32 dst_nents, struct scatterlist *src_sg,
+       u32 src_nents, unsigned long flags)
+{
+       struct xgene_dma_desc_sw *first = NULL, *new = NULL;
+       struct xgene_dma_chan *chan;
+       size_t dst_avail, src_avail;
+       dma_addr_t dst, src;
+       size_t len;
+
+       if (unlikely(!dchan))
+               return NULL;
+
+       if (unlikely(!dst_nents || !src_nents))
+               return NULL;
+
+       if (unlikely(!dst_sg || !src_sg))
+               return NULL;
+
+       chan = to_dma_chan(dchan);
+
+       /* Get prepared for the loop */
+       dst_avail = sg_dma_len(dst_sg);
+       src_avail = sg_dma_len(src_sg);
+       dst_nents--;
+       src_nents--;
+
+       /* Run until we are out of scatterlist entries */
+       while (true) {
+               /* Create the largest transaction possible */
+               len = min_t(size_t, src_avail, dst_avail);
+               len = min_t(size_t, len, XGENE_DMA_MAX_64B_DESC_BYTE_CNT);
+               if (len == 0)
+                       goto fetch;
+
+               dst = sg_dma_address(dst_sg) + sg_dma_len(dst_sg) - dst_avail;
+               src = sg_dma_address(src_sg) + sg_dma_len(src_sg) - src_avail;
+
+               /* Allocate the link descriptor from DMA pool */
+               new = xgene_dma_alloc_descriptor(chan);
+               if (!new)
+                       goto fail;
+
+               /* Prepare DMA descriptor */
+               xgene_dma_prep_cpy_desc(chan, new, dst, src, len);
+
+               if (!first)
+                       first = new;
+
+               new->tx.cookie = 0;
+               async_tx_ack(&new->tx);
+
+               /* update metadata */
+               dst_avail -= len;
+               src_avail -= len;
+
+               /* Insert the link descriptor to the LD ring */
+               list_add_tail(&new->node, &first->tx_list);
+
+fetch:
+               /* fetch the next dst scatterlist entry */
+               if (dst_avail == 0) {
+                       /* no more entries: we're done */
+                       if (dst_nents == 0)
+                               break;
+
+                       /* fetch the next entry: if there are no more: done */
+                       dst_sg = sg_next(dst_sg);
+                       if (!dst_sg)
+                               break;
+
+                       dst_nents--;
+                       dst_avail = sg_dma_len(dst_sg);
+               }
+
+               /* fetch the next src scatterlist entry */
+               if (src_avail == 0) {
+                       /* no more entries: we're done */
+                       if (src_nents == 0)
+                               break;
+
+                       /* fetch the next entry: if there are no more: done */
+                       src_sg = sg_next(src_sg);
+                       if (!src_sg)
+                               break;
+
+                       src_nents--;
+                       src_avail = sg_dma_len(src_sg);
+               }
+       }
+
+       if (!new)
+               return NULL;
+
+       new->tx.flags = flags; /* client is in control of this ack */
+       new->tx.cookie = -EBUSY;
+       list_splice(&first->tx_list, &new->tx_list);
+
+       return &new->tx;
+fail:
+       if (!first)
+               return NULL;
+
+       xgene_dma_free_tx_desc_list(chan, &first->tx_list);
+       return NULL;
+}
+
+static struct dma_async_tx_descriptor *xgene_dma_prep_xor(
+       struct dma_chan *dchan, dma_addr_t dst, dma_addr_t *src,
+       u32 src_cnt, size_t len, unsigned long flags)
+{
+       struct xgene_dma_desc_sw *first = NULL, *new;
+       struct xgene_dma_chan *chan;
+       static u8 multi[XGENE_DMA_MAX_XOR_SRC] = {
+                               0x01, 0x01, 0x01, 0x01, 0x01};
+
+       if (unlikely(!dchan || !len))
+               return NULL;
+
+       chan = to_dma_chan(dchan);
+
+       do {
+               /* Allocate the link descriptor from DMA pool */
+               new = xgene_dma_alloc_descriptor(chan);
+               if (!new)
+                       goto fail;
+
+               /* Prepare xor DMA descriptor */
+               xgene_dma_prep_xor_desc(chan, new, &dst, src,
+                                       src_cnt, &len, multi);
+
+               if (!first)
+                       first = new;
+
+               new->tx.cookie = 0;
+               async_tx_ack(&new->tx);
+
+               /* Insert the link descriptor to the LD ring */
+               list_add_tail(&new->node, &first->tx_list);
+       } while (len);
+
+       new->tx.flags = flags; /* client is in control of this ack */
+       new->tx.cookie = -EBUSY;
+       list_splice(&first->tx_list, &new->tx_list);
+
+       return &new->tx;
+
+fail:
+       if (!first)
+               return NULL;
+
+       xgene_dma_free_tx_desc_list(chan, &first->tx_list);
+       return NULL;
+}
+
+static struct dma_async_tx_descriptor *xgene_dma_prep_pq(
+       struct dma_chan *dchan, dma_addr_t *dst, dma_addr_t *src,
+       u32 src_cnt, const u8 *scf, size_t len, unsigned long flags)
+{
+       struct xgene_dma_desc_sw *first = NULL, *new;
+       struct xgene_dma_chan *chan;
+       size_t _len = len;
+       dma_addr_t _src[XGENE_DMA_MAX_XOR_SRC];
+       static u8 multi[XGENE_DMA_MAX_XOR_SRC] = {0x01, 0x01, 0x01, 0x01, 0x01};
+
+       if (unlikely(!dchan || !len))
+               return NULL;
+
+       chan = to_dma_chan(dchan);
+
+       /*
+        * Save source addresses on local variable, may be we have to
+        * prepare two descriptor to generate P and Q if both enabled
+        * in the flags by client
+        */
+       memcpy(_src, src, sizeof(*src) * src_cnt);
+
+       if (flags & DMA_PREP_PQ_DISABLE_P)
+               len = 0;
+
+       if (flags & DMA_PREP_PQ_DISABLE_Q)
+               _len = 0;
+
+       do {
+               /* Allocate the link descriptor from DMA pool */
+               new = xgene_dma_alloc_descriptor(chan);
+               if (!new)
+                       goto fail;
+
+               if (!first)
+                       first = new;
+
+               new->tx.cookie = 0;
+               async_tx_ack(&new->tx);
+
+               /* Insert the link descriptor to the LD ring */
+               list_add_tail(&new->node, &first->tx_list);
+
+               /*
+                * Prepare DMA descriptor to generate P,
+                * if DMA_PREP_PQ_DISABLE_P flag is not set
+                */
+               if (len) {
+                       xgene_dma_prep_xor_desc(chan, new, &dst[0], src,
+                                               src_cnt, &len, multi);
+                       continue;
+               }
+
+               /*
+                * Prepare DMA descriptor to generate Q,
+                * if DMA_PREP_PQ_DISABLE_Q flag is not set
+                */
+               if (_len) {
+                       xgene_dma_prep_xor_desc(chan, new, &dst[1], _src,
+                                               src_cnt, &_len, scf);
+               }
+       } while (len || _len);
+
+       new->tx.flags = flags; /* client is in control of this ack */
+       new->tx.cookie = -EBUSY;
+       list_splice(&first->tx_list, &new->tx_list);
+
+       return &new->tx;
+
+fail:
+       if (!first)
+               return NULL;
+
+       xgene_dma_free_tx_desc_list(chan, &first->tx_list);
+       return NULL;
+}
+
+static void xgene_dma_issue_pending(struct dma_chan *dchan)
+{
+       struct xgene_dma_chan *chan = to_dma_chan(dchan);
+
+       spin_lock_bh(&chan->lock);
+       xgene_chan_xfer_ld_pending(chan);
+       spin_unlock_bh(&chan->lock);
+}
+
+static enum dma_status xgene_dma_tx_status(struct dma_chan *dchan,
+                                          dma_cookie_t cookie,
+                                          struct dma_tx_state *txstate)
+{
+       return dma_cookie_status(dchan, cookie, txstate);
+}
+
+static void xgene_dma_tasklet_cb(unsigned long data)
+{
+       struct xgene_dma_chan *chan = (struct xgene_dma_chan *)data;
+
+       spin_lock_bh(&chan->lock);
+
+       /* Run all cleanup for descriptors which have been completed */
+       xgene_dma_cleanup_descriptors(chan);
+
+       /* Re-enable DMA channel IRQ */
+       enable_irq(chan->rx_irq);
+
+       spin_unlock_bh(&chan->lock);
+}
+
+static irqreturn_t xgene_dma_chan_ring_isr(int irq, void *id)
+{
+       struct xgene_dma_chan *chan = (struct xgene_dma_chan *)id;
+
+       BUG_ON(!chan);
+
+       /*
+        * Disable DMA channel IRQ until we process completed
+        * descriptors
+        */
+       disable_irq_nosync(chan->rx_irq);
+
+       /*
+        * Schedule the tasklet to handle all cleanup of the current
+        * transaction. It will start a new transaction if there is
+        * one pending.
+        */
+       tasklet_schedule(&chan->tasklet);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t xgene_dma_err_isr(int irq, void *id)
+{
+       struct xgene_dma *pdma = (struct xgene_dma *)id;
+       unsigned long int_mask;
+       u32 val, i;
+
+       val = ioread32(pdma->csr_dma + XGENE_DMA_INT);
+
+       /* Clear DMA interrupts */
+       iowrite32(val, pdma->csr_dma + XGENE_DMA_INT);
+
+       /* Print DMA error info */
+       int_mask = val >> XGENE_DMA_INT_MASK_SHIFT;
+       for_each_set_bit(i, &int_mask, ARRAY_SIZE(xgene_dma_err))
+               dev_err(pdma->dev,
+                       "Interrupt status 0x%08X %s\n", val, xgene_dma_err[i]);
+
+       return IRQ_HANDLED;
+}
+
+static void xgene_dma_wr_ring_state(struct xgene_dma_ring *ring)
+{
+       int i;
+
+       iowrite32(ring->num, ring->pdma->csr_ring + XGENE_DMA_RING_STATE);
+
+       for (i = 0; i < XGENE_DMA_RING_NUM_CONFIG; i++)
+               iowrite32(ring->state[i], ring->pdma->csr_ring +
+                         XGENE_DMA_RING_STATE_WR_BASE + (i * 4));
+}
+
+static void xgene_dma_clr_ring_state(struct xgene_dma_ring *ring)
+{
+       memset(ring->state, 0, sizeof(u32) * XGENE_DMA_RING_NUM_CONFIG);
+       xgene_dma_wr_ring_state(ring);
+}
+
+static void xgene_dma_setup_ring(struct xgene_dma_ring *ring)
+{
+       void *ring_cfg = ring->state;
+       u64 addr = ring->desc_paddr;
+       void *desc;
+       u32 i, val;
+
+       ring->slots = ring->size / XGENE_DMA_RING_WQ_DESC_SIZE;
+
+       /* Clear DMA ring state */
+       xgene_dma_clr_ring_state(ring);
+
+       /* Set DMA ring type */
+       XGENE_DMA_RING_TYPE_SET(ring_cfg, XGENE_DMA_RING_TYPE_REGULAR);
+
+       if (ring->owner == XGENE_DMA_RING_OWNER_DMA) {
+               /* Set recombination buffer and timeout */
+               XGENE_DMA_RING_RECOMBBUF_SET(ring_cfg);
+               XGENE_DMA_RING_RECOMTIMEOUTL_SET(ring_cfg);
+               XGENE_DMA_RING_RECOMTIMEOUTH_SET(ring_cfg);
+       }
+
+       /* Initialize DMA ring state */
+       XGENE_DMA_RING_SELTHRSH_SET(ring_cfg);
+       XGENE_DMA_RING_ACCEPTLERR_SET(ring_cfg);
+       XGENE_DMA_RING_COHERENT_SET(ring_cfg);
+       XGENE_DMA_RING_ADDRL_SET(ring_cfg, addr);
+       XGENE_DMA_RING_ADDRH_SET(ring_cfg, addr);
+       XGENE_DMA_RING_SIZE_SET(ring_cfg, ring->cfgsize);
+
+       /* Write DMA ring configurations */
+       xgene_dma_wr_ring_state(ring);
+
+       /* Set DMA ring id */
+       iowrite32(XGENE_DMA_RING_ID_SETUP(ring->id),
+                 ring->pdma->csr_ring + XGENE_DMA_RING_ID);
+
+       /* Set DMA ring buffer */
+       iowrite32(XGENE_DMA_RING_ID_BUF_SETUP(ring->num),
+                 ring->pdma->csr_ring + XGENE_DMA_RING_ID_BUF);
+
+       if (ring->owner != XGENE_DMA_RING_OWNER_CPU)
+               return;
+
+       /* Set empty signature to DMA Rx ring descriptors */
+       for (i = 0; i < ring->slots; i++) {
+               desc = &ring->desc_hw[i];
+               XGENE_DMA_DESC_SET_EMPTY(desc);
+       }
+
+       /* Enable DMA Rx ring interrupt */
+       val = ioread32(ring->pdma->csr_ring + XGENE_DMA_RING_NE_INT_MODE);
+       XGENE_DMA_RING_NE_INT_MODE_SET(val, ring->buf_num);
+       iowrite32(val, ring->pdma->csr_ring + XGENE_DMA_RING_NE_INT_MODE);
+}
+
+static void xgene_dma_clear_ring(struct xgene_dma_ring *ring)
+{
+       u32 ring_id, val;
+
+       if (ring->owner == XGENE_DMA_RING_OWNER_CPU) {
+               /* Disable DMA Rx ring interrupt */
+               val = ioread32(ring->pdma->csr_ring +
+                              XGENE_DMA_RING_NE_INT_MODE);
+               XGENE_DMA_RING_NE_INT_MODE_RESET(val, ring->buf_num);
+               iowrite32(val, ring->pdma->csr_ring +
+                         XGENE_DMA_RING_NE_INT_MODE);
+       }
+
+       /* Clear DMA ring state */
+       ring_id = XGENE_DMA_RING_ID_SETUP(ring->id);
+       iowrite32(ring_id, ring->pdma->csr_ring + XGENE_DMA_RING_ID);
+
+       iowrite32(0, ring->pdma->csr_ring + XGENE_DMA_RING_ID_BUF);
+       xgene_dma_clr_ring_state(ring);
+}
+
+static void xgene_dma_set_ring_cmd(struct xgene_dma_ring *ring)
+{
+       ring->cmd_base = ring->pdma->csr_ring_cmd +
+                               XGENE_DMA_RING_CMD_BASE_OFFSET((ring->num -
+                                                         XGENE_DMA_RING_NUM));
+
+       ring->cmd = ring->cmd_base + XGENE_DMA_RING_CMD_OFFSET;
+}
+
+static int xgene_dma_get_ring_size(struct xgene_dma_chan *chan,
+                                  enum xgene_dma_ring_cfgsize cfgsize)
+{
+       int size;
+
+       switch (cfgsize) {
+       case XGENE_DMA_RING_CFG_SIZE_512B:
+               size = 0x200;
+               break;
+       case XGENE_DMA_RING_CFG_SIZE_2KB:
+               size = 0x800;
+               break;
+       case XGENE_DMA_RING_CFG_SIZE_16KB:
+               size = 0x4000;
+               break;
+       case XGENE_DMA_RING_CFG_SIZE_64KB:
+               size = 0x10000;
+               break;
+       case XGENE_DMA_RING_CFG_SIZE_512KB:
+               size = 0x80000;
+               break;
+       default:
+               chan_err(chan, "Unsupported cfg ring size %d\n", cfgsize);
+               return -EINVAL;
+       }
+
+       return size;
+}
+
+static void xgene_dma_delete_ring_one(struct xgene_dma_ring *ring)
+{
+       /* Clear DMA ring configurations */
+       xgene_dma_clear_ring(ring);
+
+       /* De-allocate DMA ring descriptor */
+       if (ring->desc_vaddr) {
+               dma_free_coherent(ring->pdma->dev, ring->size,
+                                 ring->desc_vaddr, ring->desc_paddr);
+               ring->desc_vaddr = NULL;
+       }
+}
+
+static void xgene_dma_delete_chan_rings(struct xgene_dma_chan *chan)
+{
+       xgene_dma_delete_ring_one(&chan->rx_ring);
+       xgene_dma_delete_ring_one(&chan->tx_ring);
+}
+
+static int xgene_dma_create_ring_one(struct xgene_dma_chan *chan,
+                                    struct xgene_dma_ring *ring,
+                                    enum xgene_dma_ring_cfgsize cfgsize)
+{
+       /* Setup DMA ring descriptor variables */
+       ring->pdma = chan->pdma;
+       ring->cfgsize = cfgsize;
+       ring->num = chan->pdma->ring_num++;
+       ring->id = XGENE_DMA_RING_ID_GET(ring->owner, ring->buf_num);
+
+       ring->size = xgene_dma_get_ring_size(chan, cfgsize);
+       if (ring->size <= 0)
+               return ring->size;
+
+       /* Allocate memory for DMA ring descriptor */
+       ring->desc_vaddr = dma_zalloc_coherent(chan->dev, ring->size,
+                                              &ring->desc_paddr, GFP_KERNEL);
+       if (!ring->desc_vaddr) {
+               chan_err(chan, "Failed to allocate ring desc\n");
+               return -ENOMEM;
+       }
+
+       /* Configure and enable DMA ring */
+       xgene_dma_set_ring_cmd(ring);
+       xgene_dma_setup_ring(ring);
+
+       return 0;
+}
+
+static int xgene_dma_create_chan_rings(struct xgene_dma_chan *chan)
+{
+       struct xgene_dma_ring *rx_ring = &chan->rx_ring;
+       struct xgene_dma_ring *tx_ring = &chan->tx_ring;
+       int ret;
+
+       /* Create DMA Rx ring descriptor */
+       rx_ring->owner = XGENE_DMA_RING_OWNER_CPU;
+       rx_ring->buf_num = XGENE_DMA_CPU_BUFNUM + chan->id;
+
+       ret = xgene_dma_create_ring_one(chan, rx_ring,
+                                       XGENE_DMA_RING_CFG_SIZE_64KB);
+       if (ret)
+               return ret;
+
+       chan_dbg(chan, "Rx ring id 0x%X num %d desc 0x%p\n",
+                rx_ring->id, rx_ring->num, rx_ring->desc_vaddr);
+
+       /* Create DMA Tx ring descriptor */
+       tx_ring->owner = XGENE_DMA_RING_OWNER_DMA;
+       tx_ring->buf_num = XGENE_DMA_BUFNUM + chan->id;
+
+       ret = xgene_dma_create_ring_one(chan, tx_ring,
+                                       XGENE_DMA_RING_CFG_SIZE_64KB);
+       if (ret) {
+               xgene_dma_delete_ring_one(rx_ring);
+               return ret;
+       }
+
+       tx_ring->dst_ring_num = XGENE_DMA_RING_DST_ID(rx_ring->num);
+
+       chan_dbg(chan,
+                "Tx ring id 0x%X num %d desc 0x%p\n",
+                tx_ring->id, tx_ring->num, tx_ring->desc_vaddr);
+
+       /* Set the max outstanding request possible to this channel */
+       chan->max_outstanding = rx_ring->slots;
+
+       return ret;
+}
+
+static int xgene_dma_init_rings(struct xgene_dma *pdma)
+{
+       int ret, i, j;
+
+       for (i = 0; i < XGENE_DMA_MAX_CHANNEL; i++) {
+               ret = xgene_dma_create_chan_rings(&pdma->chan[i]);
+               if (ret) {
+                       for (j = 0; j < i; j++)
+                               xgene_dma_delete_chan_rings(&pdma->chan[j]);
+                       return ret;
+               }
+       }
+
+       return ret;
+}
+
+static void xgene_dma_enable(struct xgene_dma *pdma)
+{
+       u32 val;
+
+       /* Configure and enable DMA engine */
+       val = ioread32(pdma->csr_dma + XGENE_DMA_GCR);
+       XGENE_DMA_CH_SETUP(val);
+       XGENE_DMA_ENABLE(val);
+       iowrite32(val, pdma->csr_dma + XGENE_DMA_GCR);
+}
+
+static void xgene_dma_disable(struct xgene_dma *pdma)
+{
+       u32 val;
+
+       val = ioread32(pdma->csr_dma + XGENE_DMA_GCR);
+       XGENE_DMA_DISABLE(val);
+       iowrite32(val, pdma->csr_dma + XGENE_DMA_GCR);
+}
+
+static void xgene_dma_mask_interrupts(struct xgene_dma *pdma)
+{
+       /*
+        * Mask DMA ring overflow, underflow and
+        * AXI write/read error interrupts
+        */
+       iowrite32(XGENE_DMA_INT_ALL_MASK,
+                 pdma->csr_dma + XGENE_DMA_RING_INT0_MASK);
+       iowrite32(XGENE_DMA_INT_ALL_MASK,
+                 pdma->csr_dma + XGENE_DMA_RING_INT1_MASK);
+       iowrite32(XGENE_DMA_INT_ALL_MASK,
+                 pdma->csr_dma + XGENE_DMA_RING_INT2_MASK);
+       iowrite32(XGENE_DMA_INT_ALL_MASK,
+                 pdma->csr_dma + XGENE_DMA_RING_INT3_MASK);
+       iowrite32(XGENE_DMA_INT_ALL_MASK,
+                 pdma->csr_dma + XGENE_DMA_RING_INT4_MASK);
+
+       /* Mask DMA error interrupts */
+       iowrite32(XGENE_DMA_INT_ALL_MASK, pdma->csr_dma + XGENE_DMA_INT_MASK);
+}
+
+static void xgene_dma_unmask_interrupts(struct xgene_dma *pdma)
+{
+       /*
+        * Unmask DMA ring overflow, underflow and
+        * AXI write/read error interrupts
+        */
+       iowrite32(XGENE_DMA_INT_ALL_UNMASK,
+                 pdma->csr_dma + XGENE_DMA_RING_INT0_MASK);
+       iowrite32(XGENE_DMA_INT_ALL_UNMASK,
+                 pdma->csr_dma + XGENE_DMA_RING_INT1_MASK);
+       iowrite32(XGENE_DMA_INT_ALL_UNMASK,
+                 pdma->csr_dma + XGENE_DMA_RING_INT2_MASK);
+       iowrite32(XGENE_DMA_INT_ALL_UNMASK,
+                 pdma->csr_dma + XGENE_DMA_RING_INT3_MASK);
+       iowrite32(XGENE_DMA_INT_ALL_UNMASK,
+                 pdma->csr_dma + XGENE_DMA_RING_INT4_MASK);
+
+       /* Unmask DMA error interrupts */
+       iowrite32(XGENE_DMA_INT_ALL_UNMASK,
+                 pdma->csr_dma + XGENE_DMA_INT_MASK);
+}
+
+static void xgene_dma_init_hw(struct xgene_dma *pdma)
+{
+       u32 val;
+
+       /* Associate DMA ring to corresponding ring HW */
+       iowrite32(XGENE_DMA_ASSOC_RING_MNGR1,
+                 pdma->csr_dma + XGENE_DMA_CFG_RING_WQ_ASSOC);
+
+       /* Configure RAID6 polynomial control setting */
+       if (is_pq_enabled(pdma))
+               iowrite32(XGENE_DMA_RAID6_MULTI_CTRL(0x1D),
+                         pdma->csr_dma + XGENE_DMA_RAID6_CONT);
+       else
+               dev_info(pdma->dev, "PQ is disabled in HW\n");
+
+       xgene_dma_enable(pdma);
+       xgene_dma_unmask_interrupts(pdma);
+
+       /* Get DMA id and version info */
+       val = ioread32(pdma->csr_dma + XGENE_DMA_IPBRR);
+
+       /* DMA device info */
+       dev_info(pdma->dev,
+                "X-Gene DMA v%d.%02d.%02d driver registered %d channels",
+                XGENE_DMA_REV_NO_RD(val), XGENE_DMA_BUS_ID_RD(val),
+                XGENE_DMA_DEV_ID_RD(val), XGENE_DMA_MAX_CHANNEL);
+}
+
+static int xgene_dma_init_ring_mngr(struct xgene_dma *pdma)
+{
+       if (ioread32(pdma->csr_ring + XGENE_DMA_RING_CLKEN) &&
+           (!ioread32(pdma->csr_ring + XGENE_DMA_RING_SRST)))
+               return 0;
+
+       iowrite32(0x3, pdma->csr_ring + XGENE_DMA_RING_CLKEN);
+       iowrite32(0x0, pdma->csr_ring + XGENE_DMA_RING_SRST);
+
+       /* Bring up memory */
+       iowrite32(0x0, pdma->csr_ring + XGENE_DMA_RING_MEM_RAM_SHUTDOWN);
+
+       /* Force a barrier */
+       ioread32(pdma->csr_ring + XGENE_DMA_RING_MEM_RAM_SHUTDOWN);
+
+       /* reset may take up to 1ms */
+       usleep_range(1000, 1100);
+
+       if (ioread32(pdma->csr_ring + XGENE_DMA_RING_BLK_MEM_RDY)
+               != XGENE_DMA_RING_BLK_MEM_RDY_VAL) {
+               dev_err(pdma->dev,
+                       "Failed to release ring mngr memory from shutdown\n");
+               return -ENODEV;
+       }
+
+       /* program threshold set 1 and all hysteresis */
+       iowrite32(XGENE_DMA_RING_THRESLD0_SET1_VAL,
+                 pdma->csr_ring + XGENE_DMA_RING_THRESLD0_SET1);
+       iowrite32(XGENE_DMA_RING_THRESLD1_SET1_VAL,
+                 pdma->csr_ring + XGENE_DMA_RING_THRESLD1_SET1);
+       iowrite32(XGENE_DMA_RING_HYSTERESIS_VAL,
+                 pdma->csr_ring + XGENE_DMA_RING_HYSTERESIS);
+
+       /* Enable QPcore and assign error queue */
+       iowrite32(XGENE_DMA_RING_ENABLE,
+                 pdma->csr_ring + XGENE_DMA_RING_CONFIG);
+
+       return 0;
+}
+
+static int xgene_dma_init_mem(struct xgene_dma *pdma)
+{
+       int ret;
+
+       ret = xgene_dma_init_ring_mngr(pdma);
+       if (ret)
+               return ret;
+
+       /* Bring up memory */
+       iowrite32(0x0, pdma->csr_dma + XGENE_DMA_MEM_RAM_SHUTDOWN);
+
+       /* Force a barrier */
+       ioread32(pdma->csr_dma + XGENE_DMA_MEM_RAM_SHUTDOWN);
+
+       /* reset may take up to 1ms */
+       usleep_range(1000, 1100);
+
+       if (ioread32(pdma->csr_dma + XGENE_DMA_BLK_MEM_RDY)
+               != XGENE_DMA_BLK_MEM_RDY_VAL) {
+               dev_err(pdma->dev,
+                       "Failed to release DMA memory from shutdown\n");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static int xgene_dma_request_irqs(struct xgene_dma *pdma)
+{
+       struct xgene_dma_chan *chan;
+       int ret, i, j;
+
+       /* Register DMA error irq */
+       ret = devm_request_irq(pdma->dev, pdma->err_irq, xgene_dma_err_isr,
+                              0, "dma_error", pdma);
+       if (ret) {
+               dev_err(pdma->dev,
+                       "Failed to register error IRQ %d\n", pdma->err_irq);
+               return ret;
+       }
+
+       /* Register DMA channel rx irq */
+       for (i = 0; i < XGENE_DMA_MAX_CHANNEL; i++) {
+               chan = &pdma->chan[i];
+               ret = devm_request_irq(chan->dev, chan->rx_irq,
+                                      xgene_dma_chan_ring_isr,
+                                      0, chan->name, chan);
+               if (ret) {
+                       chan_err(chan, "Failed to register Rx IRQ %d\n",
+                                chan->rx_irq);
+                       devm_free_irq(pdma->dev, pdma->err_irq, pdma);
+
+                       for (j = 0; j < i; j++) {
+                               chan = &pdma->chan[i];
+                               devm_free_irq(chan->dev, chan->rx_irq, chan);
+                       }
+
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static void xgene_dma_free_irqs(struct xgene_dma *pdma)
+{
+       struct xgene_dma_chan *chan;
+       int i;
+
+       /* Free DMA device error irq */
+       devm_free_irq(pdma->dev, pdma->err_irq, pdma);
+
+       for (i = 0; i < XGENE_DMA_MAX_CHANNEL; i++) {
+               chan = &pdma->chan[i];
+               devm_free_irq(chan->dev, chan->rx_irq, chan);
+       }
+}
+
+static void xgene_dma_set_caps(struct xgene_dma_chan *chan,
+                              struct dma_device *dma_dev)
+{
+       /* Initialize DMA device capability mask */
+       dma_cap_zero(dma_dev->cap_mask);
+
+       /* Set DMA device capability */
+       dma_cap_set(DMA_MEMCPY, dma_dev->cap_mask);
+       dma_cap_set(DMA_SG, dma_dev->cap_mask);
+
+       /* Basically here, the X-Gene SoC DMA engine channel 0 supports XOR
+        * and channel 1 supports XOR, PQ both. First thing here is we have
+        * mechanism in hw to enable/disable PQ/XOR supports on channel 1,
+        * we can make sure this by reading SoC Efuse register.
+        * Second thing, we have hw errata that if we run channel 0 and
+        * channel 1 simultaneously with executing XOR and PQ request,
+        * suddenly DMA engine hangs, So here we enable XOR on channel 0 only
+        * if XOR and PQ supports on channel 1 is disabled.
+        */
+       if ((chan->id == XGENE_DMA_PQ_CHANNEL) &&
+           is_pq_enabled(chan->pdma)) {
+               dma_cap_set(DMA_PQ, dma_dev->cap_mask);
+               dma_cap_set(DMA_XOR, dma_dev->cap_mask);
+       } else if ((chan->id == XGENE_DMA_XOR_CHANNEL) &&
+                  !is_pq_enabled(chan->pdma)) {
+               dma_cap_set(DMA_XOR, dma_dev->cap_mask);
+       }
+
+       /* Set base and prep routines */
+       dma_dev->dev = chan->dev;
+       dma_dev->device_alloc_chan_resources = xgene_dma_alloc_chan_resources;
+       dma_dev->device_free_chan_resources = xgene_dma_free_chan_resources;
+       dma_dev->device_issue_pending = xgene_dma_issue_pending;
+       dma_dev->device_tx_status = xgene_dma_tx_status;
+       dma_dev->device_prep_dma_memcpy = xgene_dma_prep_memcpy;
+       dma_dev->device_prep_dma_sg = xgene_dma_prep_sg;
+
+       if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) {
+               dma_dev->device_prep_dma_xor = xgene_dma_prep_xor;
+               dma_dev->max_xor = XGENE_DMA_MAX_XOR_SRC;
+               dma_dev->xor_align = XGENE_DMA_XOR_ALIGNMENT;
+       }
+
+       if (dma_has_cap(DMA_PQ, dma_dev->cap_mask)) {
+               dma_dev->device_prep_dma_pq = xgene_dma_prep_pq;
+               dma_dev->max_pq = XGENE_DMA_MAX_XOR_SRC;
+               dma_dev->pq_align = XGENE_DMA_XOR_ALIGNMENT;
+       }
+}
+
+static int xgene_dma_async_register(struct xgene_dma *pdma, int id)
+{
+       struct xgene_dma_chan *chan = &pdma->chan[id];
+       struct dma_device *dma_dev = &pdma->dma_dev[id];
+       int ret;
+
+       chan->dma_chan.device = dma_dev;
+
+       spin_lock_init(&chan->lock);
+       INIT_LIST_HEAD(&chan->ld_pending);
+       INIT_LIST_HEAD(&chan->ld_running);
+       INIT_LIST_HEAD(&chan->ld_completed);
+       tasklet_init(&chan->tasklet, xgene_dma_tasklet_cb,
+                    (unsigned long)chan);
+
+       chan->pending = 0;
+       chan->desc_pool = NULL;
+       dma_cookie_init(&chan->dma_chan);
+
+       /* Setup dma device capabilities and prep routines */
+       xgene_dma_set_caps(chan, dma_dev);
+
+       /* Initialize DMA device list head */
+       INIT_LIST_HEAD(&dma_dev->channels);
+       list_add_tail(&chan->dma_chan.device_node, &dma_dev->channels);
+
+       /* Register with Linux async DMA framework*/
+       ret = dma_async_device_register(dma_dev);
+       if (ret) {
+               chan_err(chan, "Failed to register async device %d", ret);
+               tasklet_kill(&chan->tasklet);
+
+               return ret;
+       }
+
+       /* DMA capability info */
+       dev_info(pdma->dev,
+                "%s: CAPABILITY ( %s%s%s%s)\n", dma_chan_name(&chan->dma_chan),
+                dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask) ? "MEMCPY " : "",
+                dma_has_cap(DMA_SG, dma_dev->cap_mask) ? "SGCPY " : "",
+                dma_has_cap(DMA_XOR, dma_dev->cap_mask) ? "XOR " : "",
+                dma_has_cap(DMA_PQ, dma_dev->cap_mask) ? "PQ " : "");
+
+       return 0;
+}
+
+static int xgene_dma_init_async(struct xgene_dma *pdma)
+{
+       int ret, i, j;
+
+       for (i = 0; i < XGENE_DMA_MAX_CHANNEL ; i++) {
+               ret = xgene_dma_async_register(pdma, i);
+               if (ret) {
+                       for (j = 0; j < i; j++) {
+                               dma_async_device_unregister(&pdma->dma_dev[j]);
+                               tasklet_kill(&pdma->chan[j].tasklet);
+                       }
+
+                       return ret;
+               }
+       }
+
+       return ret;
+}
+
+static void xgene_dma_async_unregister(struct xgene_dma *pdma)
+{
+       int i;
+
+       for (i = 0; i < XGENE_DMA_MAX_CHANNEL; i++)
+               dma_async_device_unregister(&pdma->dma_dev[i]);
+}
+
+static void xgene_dma_init_channels(struct xgene_dma *pdma)
+{
+       struct xgene_dma_chan *chan;
+       int i;
+
+       pdma->ring_num = XGENE_DMA_RING_NUM;
+
+       for (i = 0; i < XGENE_DMA_MAX_CHANNEL; i++) {
+               chan = &pdma->chan[i];
+               chan->dev = pdma->dev;
+               chan->pdma = pdma;
+               chan->id = i;
+               snprintf(chan->name, sizeof(chan->name), "dmachan%d", chan->id);
+       }
+}
+
+static int xgene_dma_get_resources(struct platform_device *pdev,
+                                  struct xgene_dma *pdma)
+{
+       struct resource *res;
+       int irq, i;
+
+       /* Get DMA csr region */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "Failed to get csr region\n");
+               return -ENXIO;
+       }
+
+       pdma->csr_dma = devm_ioremap(&pdev->dev, res->start,
+                                    resource_size(res));
+       if (!pdma->csr_dma) {
+               dev_err(&pdev->dev, "Failed to ioremap csr region");
+               return -ENOMEM;
+       }
+
+       /* Get DMA ring csr region */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+       if (!res) {
+               dev_err(&pdev->dev, "Failed to get ring csr region\n");
+               return -ENXIO;
+       }
+
+       pdma->csr_ring =  devm_ioremap(&pdev->dev, res->start,
+                                      resource_size(res));
+       if (!pdma->csr_ring) {
+               dev_err(&pdev->dev, "Failed to ioremap ring csr region");
+               return -ENOMEM;
+       }
+
+       /* Get DMA ring cmd csr region */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+       if (!res) {
+               dev_err(&pdev->dev, "Failed to get ring cmd csr region\n");
+               return -ENXIO;
+       }
+
+       pdma->csr_ring_cmd = devm_ioremap(&pdev->dev, res->start,
+                                         resource_size(res));
+       if (!pdma->csr_ring_cmd) {
+               dev_err(&pdev->dev, "Failed to ioremap ring cmd csr region");
+               return -ENOMEM;
+       }
+
+       /* Get efuse csr region */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
+       if (!res) {
+               dev_err(&pdev->dev, "Failed to get efuse csr region\n");
+               return -ENXIO;
+       }
+
+       pdma->csr_efuse = devm_ioremap(&pdev->dev, res->start,
+                                      resource_size(res));
+       if (!pdma->csr_efuse) {
+               dev_err(&pdev->dev, "Failed to ioremap efuse csr region");
+               return -ENOMEM;
+       }
+
+       /* Get DMA error interrupt */
+       irq = platform_get_irq(pdev, 0);
+       if (irq <= 0) {
+               dev_err(&pdev->dev, "Failed to get Error IRQ\n");
+               return -ENXIO;
+       }
+
+       pdma->err_irq = irq;
+
+       /* Get DMA Rx ring descriptor interrupts for all DMA channels */
+       for (i = 1; i <= XGENE_DMA_MAX_CHANNEL; i++) {
+               irq = platform_get_irq(pdev, i);
+               if (irq <= 0) {
+                       dev_err(&pdev->dev, "Failed to get Rx IRQ\n");
+                       return -ENXIO;
+               }
+
+               pdma->chan[i - 1].rx_irq = irq;
+       }
+
+       return 0;
+}
+
+static int xgene_dma_probe(struct platform_device *pdev)
+{
+       struct xgene_dma *pdma;
+       int ret, i;
+
+       pdma = devm_kzalloc(&pdev->dev, sizeof(*pdma), GFP_KERNEL);
+       if (!pdma)
+               return -ENOMEM;
+
+       pdma->dev = &pdev->dev;
+       platform_set_drvdata(pdev, pdma);
+
+       ret = xgene_dma_get_resources(pdev, pdma);
+       if (ret)
+               return ret;
+
+       pdma->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(pdma->clk)) {
+               dev_err(&pdev->dev, "Failed to get clk\n");
+               return PTR_ERR(pdma->clk);
+       }
+
+       /* Enable clk before accessing registers */
+       ret = clk_prepare_enable(pdma->clk);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to enable clk %d\n", ret);
+               return ret;
+       }
+
+       /* Remove DMA RAM out of shutdown */
+       ret = xgene_dma_init_mem(pdma);
+       if (ret)
+               goto err_clk_enable;
+
+       ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(42));
+       if (ret) {
+               dev_err(&pdev->dev, "No usable DMA configuration\n");
+               goto err_dma_mask;
+       }
+
+       /* Initialize DMA channels software state */
+       xgene_dma_init_channels(pdma);
+
+       /* Configue DMA rings */
+       ret = xgene_dma_init_rings(pdma);
+       if (ret)
+               goto err_clk_enable;
+
+       ret = xgene_dma_request_irqs(pdma);
+       if (ret)
+               goto err_request_irq;
+
+       /* Configure and enable DMA engine */
+       xgene_dma_init_hw(pdma);
+
+       /* Register DMA device with linux async framework */
+       ret = xgene_dma_init_async(pdma);
+       if (ret)
+               goto err_async_init;
+
+       return 0;
+
+err_async_init:
+       xgene_dma_free_irqs(pdma);
+
+err_request_irq:
+       for (i = 0; i < XGENE_DMA_MAX_CHANNEL; i++)
+               xgene_dma_delete_chan_rings(&pdma->chan[i]);
+
+err_dma_mask:
+err_clk_enable:
+       clk_disable_unprepare(pdma->clk);
+
+       return ret;
+}
+
+static int xgene_dma_remove(struct platform_device *pdev)
+{
+       struct xgene_dma *pdma = platform_get_drvdata(pdev);
+       struct xgene_dma_chan *chan;
+       int i;
+
+       xgene_dma_async_unregister(pdma);
+
+       /* Mask interrupts and disable DMA engine */
+       xgene_dma_mask_interrupts(pdma);
+       xgene_dma_disable(pdma);
+       xgene_dma_free_irqs(pdma);
+
+       for (i = 0; i < XGENE_DMA_MAX_CHANNEL; i++) {
+               chan = &pdma->chan[i];
+               tasklet_kill(&chan->tasklet);
+               xgene_dma_delete_chan_rings(chan);
+       }
+
+       clk_disable_unprepare(pdma->clk);
+
+       return 0;
+}
+
+static const struct of_device_id xgene_dma_of_match_ptr[] = {
+       {.compatible = "apm,xgene-storm-dma",},
+       {},
+};
+MODULE_DEVICE_TABLE(of, xgene_dma_of_match_ptr);
+
+static struct platform_driver xgene_dma_driver = {
+       .probe = xgene_dma_probe,
+       .remove = xgene_dma_remove,
+       .driver = {
+               .name = "X-Gene-DMA",
+               .of_match_table = xgene_dma_of_match_ptr,
+       },
+};
+
+module_platform_driver(xgene_dma_driver);
+
+MODULE_DESCRIPTION("APM X-Gene SoC DMA driver");
+MODULE_AUTHOR("Rameshwar Prasad Sahu <rsahu@apm.com>");
+MODULE_AUTHOR("Loc Ho <lho@apm.com>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0");
index bdd2a5dd7220cbb2067732fbb79b49fcbc7a09d7..d8434d4658851baa56a5181dbf6639e55e31d676 100644 (file)
@@ -22,9 +22,9 @@
  * (at your option) any later version.
  */
 
-#include <linux/amba/xilinx_dma.h>
 #include <linux/bitops.h>
 #include <linux/dmapool.h>
+#include <linux/dma/xilinx_dma.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
index 6a1f7de6fa542f3da3ceb472e39c784efcc161ab..fdc0bf0543ce43ec8bf34ad601a03eee40089eb6 100644 (file)
@@ -55,6 +55,16 @@ config EXTCON_MAX77693
          Maxim MAX77693 PMIC. The MAX77693 MUIC is a USB port accessory
          detector and switch.
 
+config EXTCON_MAX77843
+       tristate "MAX77843 EXTCON Support"
+       depends on MFD_MAX77843
+       select IRQ_DOMAIN
+       select REGMAP_I2C
+       help
+         If you say yes here you get support for the MUIC device of
+         Maxim MAX77843. The MAX77843 MUIC is a USB port accessory
+         detector add switch.
+
 config EXTCON_MAX8997
        tristate "MAX8997 EXTCON Support"
        depends on MFD_MAX8997 && IRQ_DOMAIN
@@ -93,4 +103,11 @@ config EXTCON_SM5502
          Silicon Mitus SM5502. The SM5502 is a USB port accessory
          detector and switch.
 
+config EXTCON_USB_GPIO
+       tristate "USB GPIO extcon support"
+       depends on GPIOLIB
+       help
+         Say Y here to enable GPIO based USB cable detection extcon support.
+         Used typically if GPIO is used for USB ID pin detection.
+
 endif # MULTISTATE_SWITCH
index 0370b42e5a27e97425417e075fe3ca5db649e0ce..9204114791a3f749fac44d88ade5e8f4f8d7d175 100644 (file)
@@ -2,13 +2,15 @@
 # Makefile for external connector class (extcon) devices
 #
 
-obj-$(CONFIG_EXTCON)           += extcon-class.o
+obj-$(CONFIG_EXTCON)           += extcon.o
 obj-$(CONFIG_EXTCON_ADC_JACK)  += extcon-adc-jack.o
 obj-$(CONFIG_EXTCON_ARIZONA)   += extcon-arizona.o
 obj-$(CONFIG_EXTCON_GPIO)      += extcon-gpio.o
 obj-$(CONFIG_EXTCON_MAX14577)  += extcon-max14577.o
 obj-$(CONFIG_EXTCON_MAX77693)  += extcon-max77693.o
+obj-$(CONFIG_EXTCON_MAX77843)  += extcon-max77843.o
 obj-$(CONFIG_EXTCON_MAX8997)   += extcon-max8997.o
 obj-$(CONFIG_EXTCON_PALMAS)    += extcon-palmas.o
 obj-$(CONFIG_EXTCON_RT8973A)   += extcon-rt8973a.o
 obj-$(CONFIG_EXTCON_SM5502)    += extcon-sm5502.o
+obj-$(CONFIG_EXTCON_USB_GPIO)  += extcon-usb-gpio.o
index 6b5e795f3fe201cc0c29542a7ef61399fc4cb658..a0ed35b336e499e4c9e22e2cba97fa80f01287dd 100644 (file)
@@ -136,18 +136,35 @@ static const char *arizona_cable[] = {
 
 static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info);
 
-static void arizona_extcon_do_magic(struct arizona_extcon_info *info,
-                                   unsigned int magic)
+static void arizona_extcon_hp_clamp(struct arizona_extcon_info *info,
+                                   bool clamp)
 {
        struct arizona *arizona = info->arizona;
+       unsigned int mask = 0, val = 0;
        int ret;
 
+       switch (arizona->type) {
+       case WM5110:
+               mask = ARIZONA_HP1L_SHRTO | ARIZONA_HP1L_FLWR |
+                      ARIZONA_HP1L_SHRTI;
+               if (clamp)
+                       val = ARIZONA_HP1L_SHRTO;
+               else
+                       val = ARIZONA_HP1L_FLWR | ARIZONA_HP1L_SHRTI;
+               break;
+       default:
+               mask = ARIZONA_RMV_SHRT_HP1L;
+               if (clamp)
+                       val = ARIZONA_RMV_SHRT_HP1L;
+               break;
+       };
+
        mutex_lock(&arizona->dapm->card->dapm_mutex);
 
-       arizona->hpdet_magic = magic;
+       arizona->hpdet_clamp = clamp;
 
-       /* Keep the HP output stages disabled while doing the magic */
-       if (magic) {
+       /* Keep the HP output stages disabled while doing the clamp */
+       if (clamp) {
                ret = regmap_update_bits(arizona->regmap,
                                         ARIZONA_OUTPUT_ENABLES_1,
                                         ARIZONA_OUT1L_ENA |
@@ -158,20 +175,20 @@ static void arizona_extcon_do_magic(struct arizona_extcon_info *info,
                                 ret);
        }
 
-       ret = regmap_update_bits(arizona->regmap, 0x225, 0x4000,
-                                magic);
+       ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1L,
+                                mask, val);
        if (ret != 0)
-               dev_warn(arizona->dev, "Failed to do magic: %d\n",
+               dev_warn(arizona->dev, "Failed to do clamp: %d\n",
                                 ret);
 
-       ret = regmap_update_bits(arizona->regmap, 0x226, 0x4000,
-                                magic);
+       ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1R,
+                                mask, val);
        if (ret != 0)
-               dev_warn(arizona->dev, "Failed to do magic: %d\n",
+               dev_warn(arizona->dev, "Failed to do clamp: %d\n",
                         ret);
 
-       /* Restore the desired state while not doing the magic */
-       if (!magic) {
+       /* Restore the desired state while not doing the clamp */
+       if (!clamp) {
                ret = regmap_update_bits(arizona->regmap,
                                         ARIZONA_OUTPUT_ENABLES_1,
                                         ARIZONA_OUT1L_ENA |
@@ -603,7 +620,7 @@ done:
                           ARIZONA_HP_IMPEDANCE_RANGE_MASK | ARIZONA_HP_POLL,
                           0);
 
-       arizona_extcon_do_magic(info, 0);
+       arizona_extcon_hp_clamp(info, false);
 
        if (id_gpio)
                gpio_set_value_cansleep(id_gpio, 0);
@@ -648,7 +665,7 @@ static void arizona_identify_headphone(struct arizona_extcon_info *info)
        if (info->mic)
                arizona_stop_mic(info);
 
-       arizona_extcon_do_magic(info, 0x4000);
+       arizona_extcon_hp_clamp(info, true);
 
        ret = regmap_update_bits(arizona->regmap,
                                 ARIZONA_ACCESSORY_DETECT_MODE_1,
@@ -699,7 +716,7 @@ static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info)
 
        info->hpdet_active = true;
 
-       arizona_extcon_do_magic(info, 0x4000);
+       arizona_extcon_hp_clamp(info, true);
 
        ret = regmap_update_bits(arizona->regmap,
                                 ARIZONA_ACCESSORY_DETECT_MODE_1,
diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c
deleted file mode 100644 (file)
index 8319f25..0000000
+++ /dev/null
@@ -1,1038 +0,0 @@
-/*
- *  drivers/extcon/extcon_class.c
- *
- *  External connector (extcon) class driver
- *
- * Copyright (C) 2012 Samsung Electronics
- * Author: Donggeun Kim <dg77.kim@samsung.com>
- * Author: MyungJoo Ham <myungjoo.ham@samsung.com>
- *
- * based on android/drivers/switch/switch_class.c
- * Copyright (C) 2008 Google, Inc.
- * Author: Mike Lockwood <lockwood@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
-*/
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/fs.h>
-#include <linux/err.h>
-#include <linux/extcon.h>
-#include <linux/of.h>
-#include <linux/slab.h>
-#include <linux/sysfs.h>
-
-/*
- * extcon_cable_name suggests the standard cable names for commonly used
- * cable types.
- *
- * However, please do not use extcon_cable_name directly for extcon_dev
- * struct's supported_cable pointer unless your device really supports
- * every single port-type of the following cable names. Please choose cable
- * names that are actually used in your extcon device.
- */
-const char extcon_cable_name[][CABLE_NAME_MAX + 1] = {
-       [EXTCON_USB]            = "USB",
-       [EXTCON_USB_HOST]       = "USB-Host",
-       [EXTCON_TA]             = "TA",
-       [EXTCON_FAST_CHARGER]   = "Fast-charger",
-       [EXTCON_SLOW_CHARGER]   = "Slow-charger",
-       [EXTCON_CHARGE_DOWNSTREAM]      = "Charge-downstream",
-       [EXTCON_HDMI]           = "HDMI",
-       [EXTCON_MHL]            = "MHL",
-       [EXTCON_DVI]            = "DVI",
-       [EXTCON_VGA]            = "VGA",
-       [EXTCON_DOCK]           = "Dock",
-       [EXTCON_LINE_IN]        = "Line-in",
-       [EXTCON_LINE_OUT]       = "Line-out",
-       [EXTCON_MIC_IN]         = "Microphone",
-       [EXTCON_HEADPHONE_OUT]  = "Headphone",
-       [EXTCON_SPDIF_IN]       = "SPDIF-in",
-       [EXTCON_SPDIF_OUT]      = "SPDIF-out",
-       [EXTCON_VIDEO_IN]       = "Video-in",
-       [EXTCON_VIDEO_OUT]      = "Video-out",
-       [EXTCON_MECHANICAL]     = "Mechanical",
-};
-
-static struct class *extcon_class;
-#if defined(CONFIG_ANDROID)
-static struct class_compat *switch_class;
-#endif /* CONFIG_ANDROID */
-
-static LIST_HEAD(extcon_dev_list);
-static DEFINE_MUTEX(extcon_dev_list_lock);
-
-/**
- * check_mutually_exclusive - Check if new_state violates mutually_exclusive
- *                           condition.
- * @edev:      the extcon device
- * @new_state: new cable attach status for @edev
- *
- * Returns 0 if nothing violates. Returns the index + 1 for the first
- * violated condition.
- */
-static int check_mutually_exclusive(struct extcon_dev *edev, u32 new_state)
-{
-       int i = 0;
-
-       if (!edev->mutually_exclusive)
-               return 0;
-
-       for (i = 0; edev->mutually_exclusive[i]; i++) {
-               int weight;
-               u32 correspondants = new_state & edev->mutually_exclusive[i];
-
-               /* calculate the total number of bits set */
-               weight = hweight32(correspondants);
-               if (weight > 1)
-                       return i + 1;
-       }
-
-       return 0;
-}
-
-static ssize_t state_show(struct device *dev, struct device_attribute *attr,
-                         char *buf)
-{
-       int i, count = 0;
-       struct extcon_dev *edev = dev_get_drvdata(dev);
-
-       if (edev->print_state) {
-               int ret = edev->print_state(edev, buf);
-
-               if (ret >= 0)
-                       return ret;
-               /* Use default if failed */
-       }
-
-       if (edev->max_supported == 0)
-               return sprintf(buf, "%u\n", edev->state);
-
-       for (i = 0; i < SUPPORTED_CABLE_MAX; i++) {
-               if (!edev->supported_cable[i])
-                       break;
-               count += sprintf(buf + count, "%s=%d\n",
-                                edev->supported_cable[i],
-                                !!(edev->state & (1 << i)));
-       }
-
-       return count;
-}
-
-static ssize_t state_store(struct device *dev, struct device_attribute *attr,
-                          const char *buf, size_t count)
-{
-       u32 state;
-       ssize_t ret = 0;
-       struct extcon_dev *edev = dev_get_drvdata(dev);
-
-       ret = sscanf(buf, "0x%x", &state);
-       if (ret == 0)
-               ret = -EINVAL;
-       else
-               ret = extcon_set_state(edev, state);
-
-       if (ret < 0)
-               return ret;
-
-       return count;
-}
-static DEVICE_ATTR_RW(state);
-
-static ssize_t name_show(struct device *dev, struct device_attribute *attr,
-               char *buf)
-{
-       struct extcon_dev *edev = dev_get_drvdata(dev);
-
-       /* Optional callback given by the user */
-       if (edev->print_name) {
-               int ret = edev->print_name(edev, buf);
-               if (ret >= 0)
-                       return ret;
-       }
-
-       return sprintf(buf, "%s\n", dev_name(&edev->dev));
-}
-static DEVICE_ATTR_RO(name);
-
-static ssize_t cable_name_show(struct device *dev,
-                              struct device_attribute *attr, char *buf)
-{
-       struct extcon_cable *cable = container_of(attr, struct extcon_cable,
-                                                 attr_name);
-
-       return sprintf(buf, "%s\n",
-                      cable->edev->supported_cable[cable->cable_index]);
-}
-
-static ssize_t cable_state_show(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-       struct extcon_cable *cable = container_of(attr, struct extcon_cable,
-                                                 attr_state);
-
-       return sprintf(buf, "%d\n",
-                      extcon_get_cable_state_(cable->edev,
-                                              cable->cable_index));
-}
-
-/**
- * extcon_update_state() - Update the cable attach states of the extcon device
- *                        only for the masked bits.
- * @edev:      the extcon device
- * @mask:      the bit mask to designate updated bits.
- * @state:     new cable attach status for @edev
- *
- * Changing the state sends uevent with environment variable containing
- * the name of extcon device (envp[0]) and the state output (envp[1]).
- * Tizen uses this format for extcon device to get events from ports.
- * Android uses this format as well.
- *
- * Note that the notifier provides which bits are changed in the state
- * variable with the val parameter (second) to the callback.
- */
-int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state)
-{
-       char name_buf[120];
-       char state_buf[120];
-       char *prop_buf;
-       char *envp[3];
-       int env_offset = 0;
-       int length;
-       unsigned long flags;
-
-       spin_lock_irqsave(&edev->lock, flags);
-
-       if (edev->state != ((edev->state & ~mask) | (state & mask))) {
-               u32 old_state = edev->state;
-
-               if (check_mutually_exclusive(edev, (edev->state & ~mask) |
-                                                  (state & mask))) {
-                       spin_unlock_irqrestore(&edev->lock, flags);
-                       return -EPERM;
-               }
-
-               edev->state &= ~mask;
-               edev->state |= state & mask;
-
-               raw_notifier_call_chain(&edev->nh, old_state, edev);
-               /* This could be in interrupt handler */
-               prop_buf = (char *)get_zeroed_page(GFP_ATOMIC);
-               if (prop_buf) {
-                       length = name_show(&edev->dev, NULL, prop_buf);
-                       if (length > 0) {
-                               if (prop_buf[length - 1] == '\n')
-                                       prop_buf[length - 1] = 0;
-                               snprintf(name_buf, sizeof(name_buf),
-                                       "NAME=%s", prop_buf);
-                               envp[env_offset++] = name_buf;
-                       }
-                       length = state_show(&edev->dev, NULL, prop_buf);
-                       if (length > 0) {
-                               if (prop_buf[length - 1] == '\n')
-                                       prop_buf[length - 1] = 0;
-                               snprintf(state_buf, sizeof(state_buf),
-                                       "STATE=%s", prop_buf);
-                               envp[env_offset++] = state_buf;
-                       }
-                       envp[env_offset] = NULL;
-                       /* Unlock early before uevent */
-                       spin_unlock_irqrestore(&edev->lock, flags);
-
-                       kobject_uevent_env(&edev->dev.kobj, KOBJ_CHANGE, envp);
-                       free_page((unsigned long)prop_buf);
-               } else {
-                       /* Unlock early before uevent */
-                       spin_unlock_irqrestore(&edev->lock, flags);
-
-                       dev_err(&edev->dev, "out of memory in extcon_set_state\n");
-                       kobject_uevent(&edev->dev.kobj, KOBJ_CHANGE);
-               }
-       } else {
-               /* No changes */
-               spin_unlock_irqrestore(&edev->lock, flags);
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(extcon_update_state);
-
-/**
- * extcon_set_state() - Set the cable attach states of the extcon device.
- * @edev:      the extcon device
- * @state:     new cable attach status for @edev
- *
- * Note that notifier provides which bits are changed in the state
- * variable with the val parameter (second) to the callback.
- */
-int extcon_set_state(struct extcon_dev *edev, u32 state)
-{
-       return extcon_update_state(edev, 0xffffffff, state);
-}
-EXPORT_SYMBOL_GPL(extcon_set_state);
-
-/**
- * extcon_find_cable_index() - Get the cable index based on the cable name.
- * @edev:      the extcon device that has the cable.
- * @cable_name:        cable name to be searched.
- *
- * Note that accessing a cable state based on cable_index is faster than
- * cable_name because using cable_name induces a loop with strncmp().
- * Thus, when get/set_cable_state is repeatedly used, using cable_index
- * is recommended.
- */
-int extcon_find_cable_index(struct extcon_dev *edev, const char *cable_name)
-{
-       int i;
-
-       if (edev->supported_cable) {
-               for (i = 0; edev->supported_cable[i]; i++) {
-                       if (!strncmp(edev->supported_cable[i],
-                               cable_name, CABLE_NAME_MAX))
-                               return i;
-               }
-       }
-
-       return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(extcon_find_cable_index);
-
-/**
- * extcon_get_cable_state_() - Get the status of a specific cable.
- * @edev:      the extcon device that has the cable.
- * @index:     cable index that can be retrieved by extcon_find_cable_index().
- */
-int extcon_get_cable_state_(struct extcon_dev *edev, int index)
-{
-       if (index < 0 || (edev->max_supported && edev->max_supported <= index))
-               return -EINVAL;
-
-       return !!(edev->state & (1 << index));
-}
-EXPORT_SYMBOL_GPL(extcon_get_cable_state_);
-
-/**
- * extcon_get_cable_state() - Get the status of a specific cable.
- * @edev:      the extcon device that has the cable.
- * @cable_name:        cable name.
- *
- * Note that this is slower than extcon_get_cable_state_.
- */
-int extcon_get_cable_state(struct extcon_dev *edev, const char *cable_name)
-{
-       return extcon_get_cable_state_(edev, extcon_find_cable_index
-                                               (edev, cable_name));
-}
-EXPORT_SYMBOL_GPL(extcon_get_cable_state);
-
-/**
- * extcon_set_cable_state_() - Set the status of a specific cable.
- * @edev:              the extcon device that has the cable.
- * @index:             cable index that can be retrieved by
- *                     extcon_find_cable_index().
- * @cable_state:       the new cable status. The default semantics is
- *                     true: attached / false: detached.
- */
-int extcon_set_cable_state_(struct extcon_dev *edev,
-                       int index, bool cable_state)
-{
-       u32 state;
-
-       if (index < 0 || (edev->max_supported && edev->max_supported <= index))
-               return -EINVAL;
-
-       state = cable_state ? (1 << index) : 0;
-       return extcon_update_state(edev, 1 << index, state);
-}
-EXPORT_SYMBOL_GPL(extcon_set_cable_state_);
-
-/**
- * extcon_set_cable_state() - Set the status of a specific cable.
- * @edev:              the extcon device that has the cable.
- * @cable_name:                cable name.
- * @cable_state:       the new cable status. The default semantics is
- *                     true: attached / false: detached.
- *
- * Note that this is slower than extcon_set_cable_state_.
- */
-int extcon_set_cable_state(struct extcon_dev *edev,
-                       const char *cable_name, bool cable_state)
-{
-       return extcon_set_cable_state_(edev, extcon_find_cable_index
-                                       (edev, cable_name), cable_state);
-}
-EXPORT_SYMBOL_GPL(extcon_set_cable_state);
-
-/**
- * extcon_get_extcon_dev() - Get the extcon device instance from the name
- * @extcon_name:       The extcon name provided with extcon_dev_register()
- */
-struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name)
-{
-       struct extcon_dev *sd;
-
-       mutex_lock(&extcon_dev_list_lock);
-       list_for_each_entry(sd, &extcon_dev_list, entry) {
-               if (!strcmp(sd->name, extcon_name))
-                       goto out;
-       }
-       sd = NULL;
-out:
-       mutex_unlock(&extcon_dev_list_lock);
-       return sd;
-}
-EXPORT_SYMBOL_GPL(extcon_get_extcon_dev);
-
-static int _call_per_cable(struct notifier_block *nb, unsigned long val,
-                          void *ptr)
-{
-       struct extcon_specific_cable_nb *obj = container_of(nb,
-                       struct extcon_specific_cable_nb, internal_nb);
-       struct extcon_dev *edev = ptr;
-
-       if ((val & (1 << obj->cable_index)) !=
-           (edev->state & (1 << obj->cable_index))) {
-               bool cable_state = true;
-
-               obj->previous_value = val;
-
-               if (val & (1 << obj->cable_index))
-                       cable_state = false;
-
-               return obj->user_nb->notifier_call(obj->user_nb,
-                               cable_state, ptr);
-       }
-
-       return NOTIFY_OK;
-}
-
-/**
- * extcon_register_interest() - Register a notifier for a state change of a
- *                             specific cable, not an entier set of cables of a
- *                             extcon device.
- * @obj:               an empty extcon_specific_cable_nb object to be returned.
- * @extcon_name:       the name of extcon device.
- *                     if NULL, extcon_register_interest will register
- *                     every cable with the target cable_name given.
- * @cable_name:                the target cable name.
- * @nb:                        the notifier block to get notified.
- *
- * Provide an empty extcon_specific_cable_nb. extcon_register_interest() sets
- * the struct for you.
- *
- * extcon_register_interest is a helper function for those who want to get
- * notification for a single specific cable's status change. If a user wants
- * to get notification for any changes of all cables of a extcon device,
- * he/she should use the general extcon_register_notifier().
- *
- * Note that the second parameter given to the callback of nb (val) is
- * "old_state", not the current state. The current state can be retrieved
- * by looking at the third pameter (edev pointer)'s state value.
- */
-int extcon_register_interest(struct extcon_specific_cable_nb *obj,
-                            const char *extcon_name, const char *cable_name,
-                            struct notifier_block *nb)
-{
-       if (!obj || !cable_name || !nb)
-               return -EINVAL;
-
-       if (extcon_name) {
-               obj->edev = extcon_get_extcon_dev(extcon_name);
-               if (!obj->edev)
-                       return -ENODEV;
-
-               obj->cable_index = extcon_find_cable_index(obj->edev,
-                                                         cable_name);
-               if (obj->cable_index < 0)
-                       return obj->cable_index;
-
-               obj->user_nb = nb;
-
-               obj->internal_nb.notifier_call = _call_per_cable;
-
-               return raw_notifier_chain_register(&obj->edev->nh,
-                                                 &obj->internal_nb);
-       } else {
-               struct class_dev_iter iter;
-               struct extcon_dev *extd;
-               struct device *dev;
-
-               if (!extcon_class)
-                       return -ENODEV;
-               class_dev_iter_init(&iter, extcon_class, NULL, NULL);
-               while ((dev = class_dev_iter_next(&iter))) {
-                       extd = dev_get_drvdata(dev);
-
-                       if (extcon_find_cable_index(extd, cable_name) < 0)
-                               continue;
-
-                       class_dev_iter_exit(&iter);
-                       return extcon_register_interest(obj, extd->name,
-                                               cable_name, nb);
-               }
-
-               return -ENODEV;
-       }
-}
-EXPORT_SYMBOL_GPL(extcon_register_interest);
-
-/**
- * extcon_unregister_interest() - Unregister the notifier registered by
- *                               extcon_register_interest().
- * @obj:       the extcon_specific_cable_nb object returned by
- *             extcon_register_interest().
- */
-int extcon_unregister_interest(struct extcon_specific_cable_nb *obj)
-{
-       if (!obj)
-               return -EINVAL;
-
-       return raw_notifier_chain_unregister(&obj->edev->nh, &obj->internal_nb);
-}
-EXPORT_SYMBOL_GPL(extcon_unregister_interest);
-
-/**
- * extcon_register_notifier() - Register a notifiee to get notified by
- *                             any attach status changes from the extcon.
- * @edev:      the extcon device.
- * @nb:                a notifier block to be registered.
- *
- * Note that the second parameter given to the callback of nb (val) is
- * "old_state", not the current state. The current state can be retrieved
- * by looking at the third pameter (edev pointer)'s state value.
- */
-int extcon_register_notifier(struct extcon_dev *edev,
-                       struct notifier_block *nb)
-{
-       return raw_notifier_chain_register(&edev->nh, nb);
-}
-EXPORT_SYMBOL_GPL(extcon_register_notifier);
-
-/**
- * extcon_unregister_notifier() - Unregister a notifiee from the extcon device.
- * @edev:      the extcon device.
- * @nb:                a registered notifier block to be unregistered.
- */
-int extcon_unregister_notifier(struct extcon_dev *edev,
-                       struct notifier_block *nb)
-{
-       return raw_notifier_chain_unregister(&edev->nh, nb);
-}
-EXPORT_SYMBOL_GPL(extcon_unregister_notifier);
-
-static struct attribute *extcon_attrs[] = {
-       &dev_attr_state.attr,
-       &dev_attr_name.attr,
-       NULL,
-};
-ATTRIBUTE_GROUPS(extcon);
-
-static int create_extcon_class(void)
-{
-       if (!extcon_class) {
-               extcon_class = class_create(THIS_MODULE, "extcon");
-               if (IS_ERR(extcon_class))
-                       return PTR_ERR(extcon_class);
-               extcon_class->dev_groups = extcon_groups;
-
-#if defined(CONFIG_ANDROID)
-               switch_class = class_compat_register("switch");
-               if (WARN(!switch_class, "cannot allocate"))
-                       return -ENOMEM;
-#endif /* CONFIG_ANDROID */
-       }
-
-       return 0;
-}
-
-static void extcon_dev_release(struct device *dev)
-{
-}
-
-static const char *muex_name = "mutually_exclusive";
-static void dummy_sysfs_dev_release(struct device *dev)
-{
-}
-
-/*
- * extcon_dev_allocate() - Allocate the memory of extcon device.
- * @supported_cable:   Array of supported cable names ending with NULL.
- *                     If supported_cable is NULL, cable name related APIs
- *                     are disabled.
- *
- * This function allocates the memory for extcon device without allocating
- * memory in each extcon provider driver and initialize default setting for
- * extcon device.
- *
- * Return the pointer of extcon device if success or ERR_PTR(err) if fail
- */
-struct extcon_dev *extcon_dev_allocate(const char **supported_cable)
-{
-       struct extcon_dev *edev;
-
-       edev = kzalloc(sizeof(*edev), GFP_KERNEL);
-       if (!edev)
-               return ERR_PTR(-ENOMEM);
-
-       edev->max_supported = 0;
-       edev->supported_cable = supported_cable;
-
-       return edev;
-}
-
-/*
- * extcon_dev_free() - Free the memory of extcon device.
- * @edev:      the extcon device to free
- */
-void extcon_dev_free(struct extcon_dev *edev)
-{
-       kfree(edev);
-}
-EXPORT_SYMBOL_GPL(extcon_dev_free);
-
-static int devm_extcon_dev_match(struct device *dev, void *res, void *data)
-{
-       struct extcon_dev **r = res;
-
-       if (WARN_ON(!r || !*r))
-               return 0;
-
-       return *r == data;
-}
-
-static void devm_extcon_dev_release(struct device *dev, void *res)
-{
-       extcon_dev_free(*(struct extcon_dev **)res);
-}
-
-/**
- * devm_extcon_dev_allocate - Allocate managed extcon device
- * @dev:               device owning the extcon device being created
- * @supported_cable:   Array of supported cable names ending with NULL.
- *                     If supported_cable is NULL, cable name related APIs
- *                     are disabled.
- *
- * This function manages automatically the memory of extcon device using device
- * resource management and simplify the control of freeing the memory of extcon
- * device.
- *
- * Returns the pointer memory of allocated extcon_dev if success
- * or ERR_PTR(err) if fail
- */
-struct extcon_dev *devm_extcon_dev_allocate(struct device *dev,
-                                           const char **supported_cable)
-{
-       struct extcon_dev **ptr, *edev;
-
-       ptr = devres_alloc(devm_extcon_dev_release, sizeof(*ptr), GFP_KERNEL);
-       if (!ptr)
-               return ERR_PTR(-ENOMEM);
-
-       edev = extcon_dev_allocate(supported_cable);
-       if (IS_ERR(edev)) {
-               devres_free(ptr);
-               return edev;
-       }
-
-       edev->dev.parent = dev;
-
-       *ptr = edev;
-       devres_add(dev, ptr);
-
-       return edev;
-}
-EXPORT_SYMBOL_GPL(devm_extcon_dev_allocate);
-
-void devm_extcon_dev_free(struct device *dev, struct extcon_dev *edev)
-{
-       WARN_ON(devres_release(dev, devm_extcon_dev_release,
-                              devm_extcon_dev_match, edev));
-}
-EXPORT_SYMBOL_GPL(devm_extcon_dev_free);
-
-/**
- * extcon_dev_register() - Register a new extcon device
- * @edev       : the new extcon device (should be allocated before calling)
- *
- * Among the members of edev struct, please set the "user initializing data"
- * in any case and set the "optional callbacks" if required. However, please
- * do not set the values of "internal data", which are initialized by
- * this function.
- */
-int extcon_dev_register(struct extcon_dev *edev)
-{
-       int ret, index = 0;
-
-       if (!extcon_class) {
-               ret = create_extcon_class();
-               if (ret < 0)
-                       return ret;
-       }
-
-       if (edev->supported_cable) {
-               /* Get size of array */
-               for (index = 0; edev->supported_cable[index]; index++)
-                       ;
-               edev->max_supported = index;
-       } else {
-               edev->max_supported = 0;
-       }
-
-       if (index > SUPPORTED_CABLE_MAX) {
-               dev_err(&edev->dev, "extcon: maximum number of supported cables exceeded.\n");
-               return -EINVAL;
-       }
-
-       edev->dev.class = extcon_class;
-       edev->dev.release = extcon_dev_release;
-
-       edev->name = edev->name ? edev->name : dev_name(edev->dev.parent);
-       if (IS_ERR_OR_NULL(edev->name)) {
-               dev_err(&edev->dev,
-                       "extcon device name is null\n");
-               return -EINVAL;
-       }
-       dev_set_name(&edev->dev, "%s", edev->name);
-
-       if (edev->max_supported) {
-               char buf[10];
-               char *str;
-               struct extcon_cable *cable;
-
-               edev->cables = kzalloc(sizeof(struct extcon_cable) *
-                                      edev->max_supported, GFP_KERNEL);
-               if (!edev->cables) {
-                       ret = -ENOMEM;
-                       goto err_sysfs_alloc;
-               }
-               for (index = 0; index < edev->max_supported; index++) {
-                       cable = &edev->cables[index];
-
-                       snprintf(buf, 10, "cable.%d", index);
-                       str = kzalloc(sizeof(char) * (strlen(buf) + 1),
-                                     GFP_KERNEL);
-                       if (!str) {
-                               for (index--; index >= 0; index--) {
-                                       cable = &edev->cables[index];
-                                       kfree(cable->attr_g.name);
-                               }
-                               ret = -ENOMEM;
-
-                               goto err_alloc_cables;
-                       }
-                       strcpy(str, buf);
-
-                       cable->edev = edev;
-                       cable->cable_index = index;
-                       cable->attrs[0] = &cable->attr_name.attr;
-                       cable->attrs[1] = &cable->attr_state.attr;
-                       cable->attrs[2] = NULL;
-                       cable->attr_g.name = str;
-                       cable->attr_g.attrs = cable->attrs;
-
-                       sysfs_attr_init(&cable->attr_name.attr);
-                       cable->attr_name.attr.name = "name";
-                       cable->attr_name.attr.mode = 0444;
-                       cable->attr_name.show = cable_name_show;
-
-                       sysfs_attr_init(&cable->attr_state.attr);
-                       cable->attr_state.attr.name = "state";
-                       cable->attr_state.attr.mode = 0444;
-                       cable->attr_state.show = cable_state_show;
-               }
-       }
-
-       if (edev->max_supported && edev->mutually_exclusive) {
-               char buf[80];
-               char *name;
-
-               /* Count the size of mutually_exclusive array */
-               for (index = 0; edev->mutually_exclusive[index]; index++)
-                       ;
-
-               edev->attrs_muex = kzalloc(sizeof(struct attribute *) *
-                                          (index + 1), GFP_KERNEL);
-               if (!edev->attrs_muex) {
-                       ret = -ENOMEM;
-                       goto err_muex;
-               }
-
-               edev->d_attrs_muex = kzalloc(sizeof(struct device_attribute) *
-                                            index, GFP_KERNEL);
-               if (!edev->d_attrs_muex) {
-                       ret = -ENOMEM;
-                       kfree(edev->attrs_muex);
-                       goto err_muex;
-               }
-
-               for (index = 0; edev->mutually_exclusive[index]; index++) {
-                       sprintf(buf, "0x%x", edev->mutually_exclusive[index]);
-                       name = kzalloc(sizeof(char) * (strlen(buf) + 1),
-                                      GFP_KERNEL);
-                       if (!name) {
-                               for (index--; index >= 0; index--) {
-                                       kfree(edev->d_attrs_muex[index].attr.
-                                             name);
-                               }
-                               kfree(edev->d_attrs_muex);
-                               kfree(edev->attrs_muex);
-                               ret = -ENOMEM;
-                               goto err_muex;
-                       }
-                       strcpy(name, buf);
-                       sysfs_attr_init(&edev->d_attrs_muex[index].attr);
-                       edev->d_attrs_muex[index].attr.name = name;
-                       edev->d_attrs_muex[index].attr.mode = 0000;
-                       edev->attrs_muex[index] = &edev->d_attrs_muex[index]
-                                                       .attr;
-               }
-               edev->attr_g_muex.name = muex_name;
-               edev->attr_g_muex.attrs = edev->attrs_muex;
-
-       }
-
-       if (edev->max_supported) {
-               edev->extcon_dev_type.groups =
-                       kzalloc(sizeof(struct attribute_group *) *
-                               (edev->max_supported + 2), GFP_KERNEL);
-               if (!edev->extcon_dev_type.groups) {
-                       ret = -ENOMEM;
-                       goto err_alloc_groups;
-               }
-
-               edev->extcon_dev_type.name = dev_name(&edev->dev);
-               edev->extcon_dev_type.release = dummy_sysfs_dev_release;
-
-               for (index = 0; index < edev->max_supported; index++)
-                       edev->extcon_dev_type.groups[index] =
-                               &edev->cables[index].attr_g;
-               if (edev->mutually_exclusive)
-                       edev->extcon_dev_type.groups[index] =
-                               &edev->attr_g_muex;
-
-               edev->dev.type = &edev->extcon_dev_type;
-       }
-
-       ret = device_register(&edev->dev);
-       if (ret) {
-               put_device(&edev->dev);
-               goto err_dev;
-       }
-#if defined(CONFIG_ANDROID)
-       if (switch_class)
-               ret = class_compat_create_link(switch_class, &edev->dev, NULL);
-#endif /* CONFIG_ANDROID */
-
-       spin_lock_init(&edev->lock);
-
-       RAW_INIT_NOTIFIER_HEAD(&edev->nh);
-
-       dev_set_drvdata(&edev->dev, edev);
-       edev->state = 0;
-
-       mutex_lock(&extcon_dev_list_lock);
-       list_add(&edev->entry, &extcon_dev_list);
-       mutex_unlock(&extcon_dev_list_lock);
-
-       return 0;
-
-err_dev:
-       if (edev->max_supported)
-               kfree(edev->extcon_dev_type.groups);
-err_alloc_groups:
-       if (edev->max_supported && edev->mutually_exclusive) {
-               for (index = 0; edev->mutually_exclusive[index]; index++)
-                       kfree(edev->d_attrs_muex[index].attr.name);
-               kfree(edev->d_attrs_muex);
-               kfree(edev->attrs_muex);
-       }
-err_muex:
-       for (index = 0; index < edev->max_supported; index++)
-               kfree(edev->cables[index].attr_g.name);
-err_alloc_cables:
-       if (edev->max_supported)
-               kfree(edev->cables);
-err_sysfs_alloc:
-       return ret;
-}
-EXPORT_SYMBOL_GPL(extcon_dev_register);
-
-/**
- * extcon_dev_unregister() - Unregister the extcon device.
- * @edev:      the extcon device instance to be unregistered.
- *
- * Note that this does not call kfree(edev) because edev was not allocated
- * by this class.
- */
-void extcon_dev_unregister(struct extcon_dev *edev)
-{
-       int index;
-
-       mutex_lock(&extcon_dev_list_lock);
-       list_del(&edev->entry);
-       mutex_unlock(&extcon_dev_list_lock);
-
-       if (IS_ERR_OR_NULL(get_device(&edev->dev))) {
-               dev_err(&edev->dev, "Failed to unregister extcon_dev (%s)\n",
-                               dev_name(&edev->dev));
-               return;
-       }
-
-       device_unregister(&edev->dev);
-
-       if (edev->mutually_exclusive && edev->max_supported) {
-               for (index = 0; edev->mutually_exclusive[index];
-                               index++)
-                       kfree(edev->d_attrs_muex[index].attr.name);
-               kfree(edev->d_attrs_muex);
-               kfree(edev->attrs_muex);
-       }
-
-       for (index = 0; index < edev->max_supported; index++)
-               kfree(edev->cables[index].attr_g.name);
-
-       if (edev->max_supported) {
-               kfree(edev->extcon_dev_type.groups);
-               kfree(edev->cables);
-       }
-
-#if defined(CONFIG_ANDROID)
-       if (switch_class)
-               class_compat_remove_link(switch_class, &edev->dev, NULL);
-#endif
-       put_device(&edev->dev);
-}
-EXPORT_SYMBOL_GPL(extcon_dev_unregister);
-
-static void devm_extcon_dev_unreg(struct device *dev, void *res)
-{
-       extcon_dev_unregister(*(struct extcon_dev **)res);
-}
-
-/**
- * devm_extcon_dev_register() - Resource-managed extcon_dev_register()
- * @dev:       device to allocate extcon device
- * @edev:      the new extcon device to register
- *
- * Managed extcon_dev_register() function. If extcon device is attached with
- * this function, that extcon device is automatically unregistered on driver
- * detach. Internally this function calls extcon_dev_register() function.
- * To get more information, refer that function.
- *
- * If extcon device is registered with this function and the device needs to be
- * unregistered separately, devm_extcon_dev_unregister() should be used.
- *
- * Returns 0 if success or negaive error number if failure.
- */
-int devm_extcon_dev_register(struct device *dev, struct extcon_dev *edev)
-{
-       struct extcon_dev **ptr;
-       int ret;
-
-       ptr = devres_alloc(devm_extcon_dev_unreg, sizeof(*ptr), GFP_KERNEL);
-       if (!ptr)
-               return -ENOMEM;
-
-       ret = extcon_dev_register(edev);
-       if (ret) {
-               devres_free(ptr);
-               return ret;
-       }
-
-       *ptr = edev;
-       devres_add(dev, ptr);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(devm_extcon_dev_register);
-
-/**
- * devm_extcon_dev_unregister() - Resource-managed extcon_dev_unregister()
- * @dev:       device the extcon belongs to
- * @edev:      the extcon device to unregister
- *
- * Unregister extcon device that is registered with devm_extcon_dev_register()
- * function.
- */
-void devm_extcon_dev_unregister(struct device *dev, struct extcon_dev *edev)
-{
-       WARN_ON(devres_release(dev, devm_extcon_dev_unreg,
-                              devm_extcon_dev_match, edev));
-}
-EXPORT_SYMBOL_GPL(devm_extcon_dev_unregister);
-
-#ifdef CONFIG_OF
-/*
- * extcon_get_edev_by_phandle - Get the extcon device from devicetree
- * @dev - instance to the given device
- * @index - index into list of extcon_dev
- *
- * return the instance of extcon device
- */
-struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index)
-{
-       struct device_node *node;
-       struct extcon_dev *edev;
-
-       if (!dev->of_node) {
-               dev_err(dev, "device does not have a device node entry\n");
-               return ERR_PTR(-EINVAL);
-       }
-
-       node = of_parse_phandle(dev->of_node, "extcon", index);
-       if (!node) {
-               dev_err(dev, "failed to get phandle in %s node\n",
-                       dev->of_node->full_name);
-               return ERR_PTR(-ENODEV);
-       }
-
-       mutex_lock(&extcon_dev_list_lock);
-       list_for_each_entry(edev, &extcon_dev_list, entry) {
-               if (edev->dev.parent && edev->dev.parent->of_node == node) {
-                       mutex_unlock(&extcon_dev_list_lock);
-                       return edev;
-               }
-       }
-       mutex_unlock(&extcon_dev_list_lock);
-
-       return ERR_PTR(-EPROBE_DEFER);
-}
-#else
-struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index)
-{
-       return ERR_PTR(-ENOSYS);
-}
-#endif /* CONFIG_OF */
-EXPORT_SYMBOL_GPL(extcon_get_edev_by_phandle);
-
-static int __init extcon_class_init(void)
-{
-       return create_extcon_class();
-}
-module_init(extcon_class_init);
-
-static void __exit extcon_class_exit(void)
-{
-#if defined(CONFIG_ANDROID)
-       class_compat_unregister(switch_class);
-#endif
-       class_destroy(extcon_class);
-}
-module_exit(extcon_class_exit);
-
-MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
-MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
-MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
-MODULE_DESCRIPTION("External connector (extcon) class driver");
-MODULE_LICENSE("GPL");
index c1bf0cf747b09fc7e414aecf8349cb5e5a449878..3823aa4a3a8093631c616131dd9c06fc7a77ce33 100644 (file)
@@ -539,8 +539,6 @@ static void max14577_muic_irq_work(struct work_struct *work)
                dev_err(info->dev, "failed to handle MUIC interrupt\n");
 
        mutex_unlock(&info->mutex);
-
-       return;
 }
 
 /*
@@ -730,8 +728,7 @@ static int max14577_muic_probe(struct platform_device *pdev)
                                muic_irq->name, info);
                if (ret) {
                        dev_err(&pdev->dev,
-                               "failed: irq request (IRQ: %d,"
-                               " error :%d)\n",
+                               "failed: irq request (IRQ: %d, error :%d)\n",
                                muic_irq->irq, ret);
                        return ret;
                }
index af165fd0c6f54761a56d1cf75d81663173ff400a..a66bec8f6252dc140fbe6919b3cb846740f70a64 100644 (file)
@@ -190,8 +190,8 @@ enum max77693_muic_acc_type {
        /* The below accessories have same ADC value so ADCLow and
           ADC1K bit is used to separate specific accessory */
                                                /* ADC|VBVolot|ADCLow|ADC1K| */
-       MAX77693_MUIC_GND_USB_OTG = 0x100,      /* 0x0|      0|     0|    0| */
-       MAX77693_MUIC_GND_USB_OTG_VB = 0x104,   /* 0x0|      1|     0|    0| */
+       MAX77693_MUIC_GND_USB_HOST = 0x100,     /* 0x0|      0|     0|    0| */
+       MAX77693_MUIC_GND_USB_HOST_VB = 0x104,  /* 0x0|      1|     0|    0| */
        MAX77693_MUIC_GND_AV_CABLE_LOAD = 0x102,/* 0x0|      0|     1|    0| */
        MAX77693_MUIC_GND_MHL = 0x103,          /* 0x0|      0|     1|    1| */
        MAX77693_MUIC_GND_MHL_VB = 0x107,       /* 0x0|      1|     1|    1| */
@@ -228,7 +228,7 @@ static const char *max77693_extcon_cable[] = {
        [EXTCON_CABLE_SLOW_CHARGER]             = "Slow-charger",
        [EXTCON_CABLE_CHARGE_DOWNSTREAM]        = "Charge-downstream",
        [EXTCON_CABLE_MHL]                      = "MHL",
-       [EXTCON_CABLE_MHL_TA]                   = "MHL_TA",
+       [EXTCON_CABLE_MHL_TA]                   = "MHL-TA",
        [EXTCON_CABLE_JIG_USB_ON]               = "JIG-USB-ON",
        [EXTCON_CABLE_JIG_USB_OFF]              = "JIG-USB-OFF",
        [EXTCON_CABLE_JIG_UART_OFF]             = "JIG-UART-OFF",
@@ -403,8 +403,8 @@ static int max77693_muic_get_cable_type(struct max77693_muic_info *info,
 
                        /**
                         * [0x1|VBVolt|ADCLow|ADC1K]
-                        * [0x1|     0|     0|    0] USB_OTG
-                        * [0x1|     1|     0|    0] USB_OTG_VB
+                        * [0x1|     0|     0|    0] USB_HOST
+                        * [0x1|     1|     0|    0] USB_HSOT_VB
                         * [0x1|     0|     1|    0] Audio Video cable with load
                         * [0x1|     0|     1|    1] MHL without charging cable
                         * [0x1|     1|     1|    1] MHL with charging cable
@@ -523,7 +523,7 @@ static int max77693_muic_dock_handler(struct max77693_muic_info *info,
                 * - Support charging and data connection through micro-usb port
                 *           if USB cable is connected between target and host
                 *           device.
-                * - Support OTG device (Mouse/Keyboard)
+                * - Support OTG(On-The-Go) device (Ex: Mouse/Keyboard)
                 */
                ret = max77693_muic_set_path(info, info->path_usb, attached);
                if (ret < 0)
@@ -609,9 +609,9 @@ static int max77693_muic_adc_ground_handler(struct max77693_muic_info *info)
                                MAX77693_CABLE_GROUP_ADC_GND, &attached);
 
        switch (cable_type_gnd) {
-       case MAX77693_MUIC_GND_USB_OTG:
-       case MAX77693_MUIC_GND_USB_OTG_VB:
-               /* USB_OTG, PATH: AP_USB */
+       case MAX77693_MUIC_GND_USB_HOST:
+       case MAX77693_MUIC_GND_USB_HOST_VB:
+               /* USB_HOST, PATH: AP_USB */
                ret = max77693_muic_set_path(info, CONTROL1_SW_USB, attached);
                if (ret < 0)
                        return ret;
@@ -704,7 +704,7 @@ static int max77693_muic_adc_handler(struct max77693_muic_info *info)
 
        switch (cable_type) {
        case MAX77693_MUIC_ADC_GROUND:
-               /* USB_OTG/MHL/Audio */
+               /* USB_HOST/MHL/Audio */
                max77693_muic_adc_ground_handler(info);
                break;
        case MAX77693_MUIC_ADC_FACTORY_MODE_USB_OFF:
@@ -823,19 +823,19 @@ static int max77693_muic_chg_handler(struct max77693_muic_info *info)
                case MAX77693_MUIC_GND_MHL:
                case MAX77693_MUIC_GND_MHL_VB:
                        /*
-                        * MHL cable with MHL_TA(USB/TA) cable
+                        * MHL cable with MHL-TA(USB/TA) cable
                         * - MHL cable include two port(HDMI line and separate
                         * micro-usb port. When the target connect MHL cable,
-                        * extcon driver check whether MHL_TA(USB/TA) cable is
-                        * connected. If MHL_TA cable is connected, extcon
+                        * extcon driver check whether MHL-TA(USB/TA) cable is
+                        * connected. If MHL-TA cable is connected, extcon
                         * driver notify state to notifiee for charging battery.
                         *
-                        * Features of 'MHL_TA(USB/TA) with MHL cable'
+                        * Features of 'MHL-TA(USB/TA) with MHL cable'
                         * - Support MHL
                         * - Support charging through micro-usb port without
                         *   data connection
                         */
-                       extcon_set_cable_state(info->edev, "MHL_TA", attached);
+                       extcon_set_cable_state(info->edev, "MHL-TA", attached);
                        if (!cable_attached)
                                extcon_set_cable_state(info->edev,
                                                      "MHL", cable_attached);
@@ -886,7 +886,7 @@ static int max77693_muic_chg_handler(struct max77693_muic_info *info)
                         * - Support charging and data connection through micro-
                         *   usb port if USB cable is connected between target
                         *   and host device
-                        * - Support OTG device (Mouse/Keyboard)
+                        * - Support OTG(On-The-Go) device (Ex: Mouse/Keyboard)
                         */
                        ret = max77693_muic_set_path(info, info->path_usb,
                                                    attached);
@@ -1019,8 +1019,6 @@ static void max77693_muic_irq_work(struct work_struct *work)
                dev_err(info->dev, "failed to handle MUIC interrupt\n");
 
        mutex_unlock(&info->mutex);
-
-       return;
 }
 
 static irqreturn_t max77693_muic_irq_handler(int irq, void *data)
@@ -1171,8 +1169,7 @@ static int max77693_muic_probe(struct platform_device *pdev)
                                muic_irq->name, info);
                if (ret) {
                        dev_err(&pdev->dev,
-                               "failed: irq request (IRQ: %d,"
-                               " error :%d)\n",
+                               "failed: irq request (IRQ: %d, error :%d)\n",
                                muic_irq->irq, ret);
                        return ret;
                }
diff --git a/drivers/extcon/extcon-max77843.c b/drivers/extcon/extcon-max77843.c
new file mode 100644 (file)
index 0000000..8db6a92
--- /dev/null
@@ -0,0 +1,881 @@
+/*
+ * extcon-max77843.c - Maxim MAX77843 extcon driver to support
+ *                     MUIC(Micro USB Interface Controller)
+ *
+ * Copyright (C) 2015 Samsung Electronics
+ * Author: Jaewon Kim <jaewon02.kim@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.
+ */
+
+#include <linux/extcon.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mfd/max77843-private.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+
+#define DELAY_MS_DEFAULT               15000   /* unit: millisecond */
+
+enum max77843_muic_status {
+       MAX77843_MUIC_STATUS1 = 0,
+       MAX77843_MUIC_STATUS2,
+       MAX77843_MUIC_STATUS3,
+
+       MAX77843_MUIC_STATUS_NUM,
+};
+
+struct max77843_muic_info {
+       struct device *dev;
+       struct max77843 *max77843;
+       struct extcon_dev *edev;
+
+       struct mutex mutex;
+       struct work_struct irq_work;
+       struct delayed_work wq_detcable;
+
+       u8 status[MAX77843_MUIC_STATUS_NUM];
+       int prev_cable_type;
+       int prev_chg_type;
+       int prev_gnd_type;
+
+       bool irq_adc;
+       bool irq_chg;
+};
+
+enum max77843_muic_cable_group {
+       MAX77843_CABLE_GROUP_ADC = 0,
+       MAX77843_CABLE_GROUP_ADC_GND,
+       MAX77843_CABLE_GROUP_CHG,
+};
+
+enum max77843_muic_adc_debounce_time {
+       MAX77843_DEBOUNCE_TIME_5MS = 0,
+       MAX77843_DEBOUNCE_TIME_10MS,
+       MAX77843_DEBOUNCE_TIME_25MS,
+       MAX77843_DEBOUNCE_TIME_38_62MS,
+};
+
+/* Define accessory cable type */
+enum max77843_muic_accessory_type {
+       MAX77843_MUIC_ADC_GROUND = 0,
+       MAX77843_MUIC_ADC_SEND_END_BUTTON,
+       MAX77843_MUIC_ADC_REMOTE_S1_BUTTON,
+       MAX77843_MUIC_ADC_REMOTE_S2_BUTTON,
+       MAX77843_MUIC_ADC_REMOTE_S3_BUTTON,
+       MAX77843_MUIC_ADC_REMOTE_S4_BUTTON,
+       MAX77843_MUIC_ADC_REMOTE_S5_BUTTON,
+       MAX77843_MUIC_ADC_REMOTE_S6_BUTTON,
+       MAX77843_MUIC_ADC_REMOTE_S7_BUTTON,
+       MAX77843_MUIC_ADC_REMOTE_S8_BUTTON,
+       MAX77843_MUIC_ADC_REMOTE_S9_BUTTON,
+       MAX77843_MUIC_ADC_REMOTE_S10_BUTTON,
+       MAX77843_MUIC_ADC_REMOTE_S11_BUTTON,
+       MAX77843_MUIC_ADC_REMOTE_S12_BUTTON,
+       MAX77843_MUIC_ADC_RESERVED_ACC_1,
+       MAX77843_MUIC_ADC_RESERVED_ACC_2,
+       MAX77843_MUIC_ADC_RESERVED_ACC_3,
+       MAX77843_MUIC_ADC_RESERVED_ACC_4,
+       MAX77843_MUIC_ADC_RESERVED_ACC_5,
+       MAX77843_MUIC_ADC_AUDIO_DEVICE_TYPE2,
+       MAX77843_MUIC_ADC_PHONE_POWERED_DEV,
+       MAX77843_MUIC_ADC_TTY_CONVERTER,
+       MAX77843_MUIC_ADC_UART_CABLE,
+       MAX77843_MUIC_ADC_CEA936A_TYPE1_CHG,
+       MAX77843_MUIC_ADC_FACTORY_MODE_USB_OFF,
+       MAX77843_MUIC_ADC_FACTORY_MODE_USB_ON,
+       MAX77843_MUIC_ADC_AV_CABLE_NOLOAD,
+       MAX77843_MUIC_ADC_CEA936A_TYPE2_CHG,
+       MAX77843_MUIC_ADC_FACTORY_MODE_UART_OFF,
+       MAX77843_MUIC_ADC_FACTORY_MODE_UART_ON,
+       MAX77843_MUIC_ADC_AUDIO_DEVICE_TYPE1,
+       MAX77843_MUIC_ADC_OPEN,
+
+       /* The blow accessories should check
+          not only ADC value but also ADC1K and VBVolt value. */
+                                               /* Offset|ADC1K|VBVolt| */
+       MAX77843_MUIC_GND_USB_HOST = 0x100,     /*    0x1|    0|     0| */
+       MAX77843_MUIC_GND_USB_HOST_VB = 0x101,  /*    0x1|    0|     1| */
+       MAX77843_MUIC_GND_MHL = 0x102,          /*    0x1|    1|     0| */
+       MAX77843_MUIC_GND_MHL_VB = 0x103,       /*    0x1|    1|     1| */
+};
+
+/* Define charger cable type */
+enum max77843_muic_charger_type {
+       MAX77843_MUIC_CHG_NONE = 0,
+       MAX77843_MUIC_CHG_USB,
+       MAX77843_MUIC_CHG_DOWNSTREAM,
+       MAX77843_MUIC_CHG_DEDICATED,
+       MAX77843_MUIC_CHG_SPECIAL_500MA,
+       MAX77843_MUIC_CHG_SPECIAL_1A,
+       MAX77843_MUIC_CHG_SPECIAL_BIAS,
+       MAX77843_MUIC_CHG_RESERVED,
+       MAX77843_MUIC_CHG_GND,
+};
+
+enum {
+       MAX77843_CABLE_USB = 0,
+       MAX77843_CABLE_USB_HOST,
+       MAX77843_CABLE_TA,
+       MAX77843_CABLE_CHARGE_DOWNSTREAM,
+       MAX77843_CABLE_FAST_CHARGER,
+       MAX77843_CABLE_SLOW_CHARGER,
+       MAX77843_CABLE_MHL,
+       MAX77843_CABLE_MHL_TA,
+       MAX77843_CABLE_JIG_USB_ON,
+       MAX77843_CABLE_JIG_USB_OFF,
+       MAX77843_CABLE_JIG_UART_ON,
+       MAX77843_CABLE_JIG_UART_OFF,
+
+       MAX77843_CABLE_NUM,
+};
+
+static const char *max77843_extcon_cable[] = {
+       [MAX77843_CABLE_USB]                    = "USB",
+       [MAX77843_CABLE_USB_HOST]               = "USB-HOST",
+       [MAX77843_CABLE_TA]                     = "TA",
+       [MAX77843_CABLE_CHARGE_DOWNSTREAM]      = "CHARGER-DOWNSTREAM",
+       [MAX77843_CABLE_FAST_CHARGER]           = "FAST-CHARGER",
+       [MAX77843_CABLE_SLOW_CHARGER]           = "SLOW-CHARGER",
+       [MAX77843_CABLE_MHL]                    = "MHL",
+       [MAX77843_CABLE_MHL_TA]                 = "MHL-TA",
+       [MAX77843_CABLE_JIG_USB_ON]             = "JIG-USB-ON",
+       [MAX77843_CABLE_JIG_USB_OFF]            = "JIG-USB-OFF",
+       [MAX77843_CABLE_JIG_UART_ON]            = "JIG-UART-ON",
+       [MAX77843_CABLE_JIG_UART_OFF]           = "JIG-UART-OFF",
+};
+
+struct max77843_muic_irq {
+       unsigned int irq;
+       const char *name;
+       unsigned int virq;
+};
+
+static struct max77843_muic_irq max77843_muic_irqs[] = {
+       { MAX77843_MUIC_IRQ_INT1_ADC,           "MUIC-ADC" },
+       { MAX77843_MUIC_IRQ_INT1_ADCERROR,      "MUIC-ADC_ERROR" },
+       { MAX77843_MUIC_IRQ_INT1_ADC1K,         "MUIC-ADC1K" },
+       { MAX77843_MUIC_IRQ_INT2_CHGTYP,        "MUIC-CHGTYP" },
+       { MAX77843_MUIC_IRQ_INT2_CHGDETRUN,     "MUIC-CHGDETRUN" },
+       { MAX77843_MUIC_IRQ_INT2_DCDTMR,        "MUIC-DCDTMR" },
+       { MAX77843_MUIC_IRQ_INT2_DXOVP,         "MUIC-DXOVP" },
+       { MAX77843_MUIC_IRQ_INT2_VBVOLT,        "MUIC-VBVOLT" },
+       { MAX77843_MUIC_IRQ_INT3_VBADC,         "MUIC-VBADC" },
+       { MAX77843_MUIC_IRQ_INT3_VDNMON,        "MUIC-VDNMON" },
+       { MAX77843_MUIC_IRQ_INT3_DNRES,         "MUIC-DNRES" },
+       { MAX77843_MUIC_IRQ_INT3_MPNACK,        "MUIC-MPNACK"},
+       { MAX77843_MUIC_IRQ_INT3_MRXBUFOW,      "MUIC-MRXBUFOW"},
+       { MAX77843_MUIC_IRQ_INT3_MRXTRF,        "MUIC-MRXTRF"},
+       { MAX77843_MUIC_IRQ_INT3_MRXPERR,       "MUIC-MRXPERR"},
+       { MAX77843_MUIC_IRQ_INT3_MRXRDY,        "MUIC-MRXRDY"},
+};
+
+static const struct regmap_config max77843_muic_regmap_config = {
+       .reg_bits       = 8,
+       .val_bits       = 8,
+       .max_register   = MAX77843_MUIC_REG_END,
+};
+
+static const struct regmap_irq max77843_muic_irq[] = {
+       /* INT1 interrupt */
+       { .reg_offset = 0, .mask = MAX77843_MUIC_ADC, },
+       { .reg_offset = 0, .mask = MAX77843_MUIC_ADCERROR, },
+       { .reg_offset = 0, .mask = MAX77843_MUIC_ADC1K, },
+
+       /* INT2 interrupt */
+       { .reg_offset = 1, .mask = MAX77843_MUIC_CHGTYP, },
+       { .reg_offset = 1, .mask = MAX77843_MUIC_CHGDETRUN, },
+       { .reg_offset = 1, .mask = MAX77843_MUIC_DCDTMR, },
+       { .reg_offset = 1, .mask = MAX77843_MUIC_DXOVP, },
+       { .reg_offset = 1, .mask = MAX77843_MUIC_VBVOLT, },
+
+       /* INT3 interrupt */
+       { .reg_offset = 2, .mask = MAX77843_MUIC_VBADC, },
+       { .reg_offset = 2, .mask = MAX77843_MUIC_VDNMON, },
+       { .reg_offset = 2, .mask = MAX77843_MUIC_DNRES, },
+       { .reg_offset = 2, .mask = MAX77843_MUIC_MPNACK, },
+       { .reg_offset = 2, .mask = MAX77843_MUIC_MRXBUFOW, },
+       { .reg_offset = 2, .mask = MAX77843_MUIC_MRXTRF, },
+       { .reg_offset = 2, .mask = MAX77843_MUIC_MRXPERR, },
+       { .reg_offset = 2, .mask = MAX77843_MUIC_MRXRDY, },
+};
+
+static const struct regmap_irq_chip max77843_muic_irq_chip = {
+       .name           = "max77843-muic",
+       .status_base    = MAX77843_MUIC_REG_INT1,
+       .mask_base      = MAX77843_MUIC_REG_INTMASK1,
+       .mask_invert    = true,
+       .num_regs       = 3,
+       .irqs           = max77843_muic_irq,
+       .num_irqs       = ARRAY_SIZE(max77843_muic_irq),
+};
+
+static int max77843_muic_set_path(struct max77843_muic_info *info,
+               u8 val, bool attached)
+{
+       struct max77843 *max77843 = info->max77843;
+       int ret = 0;
+       unsigned int ctrl1, ctrl2;
+
+       if (attached)
+               ctrl1 = val;
+       else
+               ctrl1 = CONTROL1_SW_OPEN;
+
+       ret = regmap_update_bits(max77843->regmap_muic,
+                       MAX77843_MUIC_REG_CONTROL1,
+                       CONTROL1_COM_SW, ctrl1);
+       if (ret < 0) {
+               dev_err(info->dev, "Cannot switch MUIC port\n");
+               return ret;
+       }
+
+       if (attached)
+               ctrl2 = MAX77843_MUIC_CONTROL2_CPEN_MASK;
+       else
+               ctrl2 = MAX77843_MUIC_CONTROL2_LOWPWR_MASK;
+
+       ret = regmap_update_bits(max77843->regmap_muic,
+                       MAX77843_MUIC_REG_CONTROL2,
+                       MAX77843_MUIC_CONTROL2_LOWPWR_MASK |
+                       MAX77843_MUIC_CONTROL2_CPEN_MASK, ctrl2);
+       if (ret < 0) {
+               dev_err(info->dev, "Cannot update lowpower mode\n");
+               return ret;
+       }
+
+       dev_dbg(info->dev,
+               "CONTROL1 : 0x%02x, CONTROL2 : 0x%02x, state : %s\n",
+               ctrl1, ctrl2, attached ? "attached" : "detached");
+
+       return 0;
+}
+
+static int max77843_muic_get_cable_type(struct max77843_muic_info *info,
+               enum max77843_muic_cable_group group, bool *attached)
+{
+       int adc, chg_type, cable_type, gnd_type;
+
+       adc = info->status[MAX77843_MUIC_STATUS1] &
+                       MAX77843_MUIC_STATUS1_ADC_MASK;
+       adc >>= STATUS1_ADC_SHIFT;
+
+       switch (group) {
+       case MAX77843_CABLE_GROUP_ADC:
+               if (adc == MAX77843_MUIC_ADC_OPEN) {
+                       *attached = false;
+                       cable_type = info->prev_cable_type;
+                       info->prev_cable_type = MAX77843_MUIC_ADC_OPEN;
+               } else {
+                       *attached = true;
+                       cable_type = info->prev_cable_type = adc;
+               }
+               break;
+       case MAX77843_CABLE_GROUP_CHG:
+               chg_type = info->status[MAX77843_MUIC_STATUS2] &
+                               MAX77843_MUIC_STATUS2_CHGTYP_MASK;
+
+               /* Check GROUND accessory with charger cable */
+               if (adc == MAX77843_MUIC_ADC_GROUND) {
+                       if (chg_type == MAX77843_MUIC_CHG_NONE) {
+                               /* The following state when charger cable is
+                                * disconnected but the GROUND accessory still
+                                * connected */
+                               *attached = false;
+                               cable_type = info->prev_chg_type;
+                               info->prev_chg_type = MAX77843_MUIC_CHG_NONE;
+                       } else {
+
+                               /* The following state when charger cable is
+                                * connected on the GROUND accessory */
+                               *attached = true;
+                               cable_type = MAX77843_MUIC_CHG_GND;
+                               info->prev_chg_type = MAX77843_MUIC_CHG_GND;
+                       }
+                       break;
+               }
+
+               if (chg_type == MAX77843_MUIC_CHG_NONE) {
+                       *attached = false;
+                       cable_type = info->prev_chg_type;
+                       info->prev_chg_type = MAX77843_MUIC_CHG_NONE;
+               } else {
+                       *attached = true;
+                       cable_type = info->prev_chg_type = chg_type;
+               }
+               break;
+       case MAX77843_CABLE_GROUP_ADC_GND:
+               if (adc == MAX77843_MUIC_ADC_OPEN) {
+                       *attached = false;
+                       cable_type = info->prev_gnd_type;
+                       info->prev_gnd_type = MAX77843_MUIC_ADC_OPEN;
+               } else {
+                       *attached = true;
+
+                       /* Offset|ADC1K|VBVolt|
+                        *    0x1|    0|     0| USB-HOST
+                        *    0x1|    0|     1| USB-HOST with VB
+                        *    0x1|    1|     0| MHL
+                        *    0x1|    1|     1| MHL with VB */
+                       /* Get ADC1K register bit */
+                       gnd_type = (info->status[MAX77843_MUIC_STATUS1] &
+                                       MAX77843_MUIC_STATUS1_ADC1K_MASK);
+
+                       /* Get VBVolt register bit */
+                       gnd_type |= (info->status[MAX77843_MUIC_STATUS2] &
+                                       MAX77843_MUIC_STATUS2_VBVOLT_MASK);
+                       gnd_type >>= STATUS2_VBVOLT_SHIFT;
+
+                       /* Offset of GND cable */
+                       gnd_type |= MAX77843_MUIC_GND_USB_HOST;
+                       cable_type = info->prev_gnd_type = gnd_type;
+               }
+               break;
+       default:
+               dev_err(info->dev, "Unknown cable group (%d)\n", group);
+               cable_type = -EINVAL;
+               break;
+       }
+
+       return cable_type;
+}
+
+static int max77843_muic_adc_gnd_handler(struct max77843_muic_info *info)
+{
+       int ret, gnd_cable_type;
+       bool attached;
+
+       gnd_cable_type = max77843_muic_get_cable_type(info,
+                       MAX77843_CABLE_GROUP_ADC_GND, &attached);
+       dev_dbg(info->dev, "external connector is %s (gnd:0x%02x)\n",
+                       attached ? "attached" : "detached", gnd_cable_type);
+
+       switch (gnd_cable_type) {
+       case MAX77843_MUIC_GND_USB_HOST:
+       case MAX77843_MUIC_GND_USB_HOST_VB:
+               ret = max77843_muic_set_path(info, CONTROL1_SW_USB, attached);
+               if (ret < 0)
+                       return ret;
+
+               extcon_set_cable_state(info->edev, "USB-HOST", attached);
+               break;
+       case MAX77843_MUIC_GND_MHL_VB:
+       case MAX77843_MUIC_GND_MHL:
+               ret = max77843_muic_set_path(info, CONTROL1_SW_OPEN, attached);
+               if (ret < 0)
+                       return ret;
+
+               extcon_set_cable_state(info->edev, "MHL", attached);
+               break;
+       default:
+               dev_err(info->dev, "failed to detect %s accessory(gnd:0x%x)\n",
+                       attached ? "attached" : "detached", gnd_cable_type);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int max77843_muic_jig_handler(struct max77843_muic_info *info,
+               int cable_type, bool attached)
+{
+       int ret;
+
+       dev_dbg(info->dev, "external connector is %s (adc:0x%02x)\n",
+                       attached ? "attached" : "detached", cable_type);
+
+       switch (cable_type) {
+       case MAX77843_MUIC_ADC_FACTORY_MODE_USB_OFF:
+               ret = max77843_muic_set_path(info, CONTROL1_SW_USB, attached);
+               if (ret < 0)
+                       return ret;
+               extcon_set_cable_state(info->edev, "JIG-USB-OFF", attached);
+               break;
+       case MAX77843_MUIC_ADC_FACTORY_MODE_USB_ON:
+               ret = max77843_muic_set_path(info, CONTROL1_SW_USB, attached);
+               if (ret < 0)
+                       return ret;
+               extcon_set_cable_state(info->edev, "JIG-USB-ON", attached);
+               break;
+       case MAX77843_MUIC_ADC_FACTORY_MODE_UART_OFF:
+               ret = max77843_muic_set_path(info, CONTROL1_SW_UART, attached);
+               if (ret < 0)
+                       return ret;
+               extcon_set_cable_state(info->edev, "JIG-UART-OFF", attached);
+               break;
+       default:
+               ret = max77843_muic_set_path(info, CONTROL1_SW_OPEN, attached);
+               if (ret < 0)
+                       return ret;
+               break;
+       }
+
+       return 0;
+}
+
+static int max77843_muic_adc_handler(struct max77843_muic_info *info)
+{
+       int ret, cable_type;
+       bool attached;
+
+       cable_type = max77843_muic_get_cable_type(info,
+                       MAX77843_CABLE_GROUP_ADC, &attached);
+
+       dev_dbg(info->dev,
+               "external connector is %s (adc:0x%02x, prev_adc:0x%x)\n",
+               attached ? "attached" : "detached", cable_type,
+               info->prev_cable_type);
+
+       switch (cable_type) {
+       case MAX77843_MUIC_ADC_GROUND:
+               ret = max77843_muic_adc_gnd_handler(info);
+               if (ret < 0)
+                       return ret;
+               break;
+       case MAX77843_MUIC_ADC_FACTORY_MODE_USB_OFF:
+       case MAX77843_MUIC_ADC_FACTORY_MODE_USB_ON:
+       case MAX77843_MUIC_ADC_FACTORY_MODE_UART_OFF:
+               ret = max77843_muic_jig_handler(info, cable_type, attached);
+               if (ret < 0)
+                       return ret;
+               break;
+       case MAX77843_MUIC_ADC_SEND_END_BUTTON:
+       case MAX77843_MUIC_ADC_REMOTE_S1_BUTTON:
+       case MAX77843_MUIC_ADC_REMOTE_S2_BUTTON:
+       case MAX77843_MUIC_ADC_REMOTE_S3_BUTTON:
+       case MAX77843_MUIC_ADC_REMOTE_S4_BUTTON:
+       case MAX77843_MUIC_ADC_REMOTE_S5_BUTTON:
+       case MAX77843_MUIC_ADC_REMOTE_S6_BUTTON:
+       case MAX77843_MUIC_ADC_REMOTE_S7_BUTTON:
+       case MAX77843_MUIC_ADC_REMOTE_S8_BUTTON:
+       case MAX77843_MUIC_ADC_REMOTE_S9_BUTTON:
+       case MAX77843_MUIC_ADC_REMOTE_S10_BUTTON:
+       case MAX77843_MUIC_ADC_REMOTE_S11_BUTTON:
+       case MAX77843_MUIC_ADC_REMOTE_S12_BUTTON:
+       case MAX77843_MUIC_ADC_RESERVED_ACC_1:
+       case MAX77843_MUIC_ADC_RESERVED_ACC_2:
+       case MAX77843_MUIC_ADC_RESERVED_ACC_3:
+       case MAX77843_MUIC_ADC_RESERVED_ACC_4:
+       case MAX77843_MUIC_ADC_RESERVED_ACC_5:
+       case MAX77843_MUIC_ADC_AUDIO_DEVICE_TYPE2:
+       case MAX77843_MUIC_ADC_PHONE_POWERED_DEV:
+       case MAX77843_MUIC_ADC_TTY_CONVERTER:
+       case MAX77843_MUIC_ADC_UART_CABLE:
+       case MAX77843_MUIC_ADC_CEA936A_TYPE1_CHG:
+       case MAX77843_MUIC_ADC_AV_CABLE_NOLOAD:
+       case MAX77843_MUIC_ADC_CEA936A_TYPE2_CHG:
+       case MAX77843_MUIC_ADC_FACTORY_MODE_UART_ON:
+       case MAX77843_MUIC_ADC_AUDIO_DEVICE_TYPE1:
+       case MAX77843_MUIC_ADC_OPEN:
+               dev_err(info->dev,
+                       "accessory is %s but it isn't used (adc:0x%x)\n",
+                       attached ? "attached" : "detached", cable_type);
+               return -EAGAIN;
+       default:
+               dev_err(info->dev,
+                       "failed to detect %s accessory (adc:0x%x)\n",
+                       attached ? "attached" : "detached", cable_type);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int max77843_muic_chg_handler(struct max77843_muic_info *info)
+{
+       int ret, chg_type, gnd_type;
+       bool attached;
+
+       chg_type = max77843_muic_get_cable_type(info,
+                       MAX77843_CABLE_GROUP_CHG, &attached);
+
+       dev_dbg(info->dev,
+               "external connector is %s(chg_type:0x%x, prev_chg_type:0x%x)\n",
+               attached ? "attached" : "detached",
+               chg_type, info->prev_chg_type);
+
+       switch (chg_type) {
+       case MAX77843_MUIC_CHG_USB:
+               ret = max77843_muic_set_path(info, CONTROL1_SW_USB, attached);
+               if (ret < 0)
+                       return ret;
+
+               extcon_set_cable_state(info->edev, "USB", attached);
+               break;
+       case MAX77843_MUIC_CHG_DOWNSTREAM:
+               ret = max77843_muic_set_path(info, CONTROL1_SW_OPEN, attached);
+               if (ret < 0)
+                       return ret;
+
+               extcon_set_cable_state(info->edev,
+                               "CHARGER-DOWNSTREAM", attached);
+               break;
+       case MAX77843_MUIC_CHG_DEDICATED:
+               ret = max77843_muic_set_path(info, CONTROL1_SW_OPEN, attached);
+               if (ret < 0)
+                       return ret;
+
+               extcon_set_cable_state(info->edev, "TA", attached);
+               break;
+       case MAX77843_MUIC_CHG_SPECIAL_500MA:
+               ret = max77843_muic_set_path(info, CONTROL1_SW_OPEN, attached);
+               if (ret < 0)
+                       return ret;
+
+               extcon_set_cable_state(info->edev, "SLOW-CHAREGER", attached);
+               break;
+       case MAX77843_MUIC_CHG_SPECIAL_1A:
+               ret = max77843_muic_set_path(info, CONTROL1_SW_OPEN, attached);
+               if (ret < 0)
+                       return ret;
+
+               extcon_set_cable_state(info->edev, "FAST-CHARGER", attached);
+               break;
+       case MAX77843_MUIC_CHG_GND:
+               gnd_type = max77843_muic_get_cable_type(info,
+                               MAX77843_CABLE_GROUP_ADC_GND, &attached);
+
+               /* Charger cable on MHL accessory is attach or detach */
+               if (gnd_type == MAX77843_MUIC_GND_MHL_VB)
+                       extcon_set_cable_state(info->edev, "MHL-TA", true);
+               else if (gnd_type == MAX77843_MUIC_GND_MHL)
+                       extcon_set_cable_state(info->edev, "MHL-TA", false);
+               break;
+       case MAX77843_MUIC_CHG_NONE:
+               break;
+       default:
+               dev_err(info->dev,
+                       "failed to detect %s accessory (chg_type:0x%x)\n",
+                       attached ? "attached" : "detached", chg_type);
+
+               max77843_muic_set_path(info, CONTROL1_SW_OPEN, attached);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void max77843_muic_irq_work(struct work_struct *work)
+{
+       struct max77843_muic_info *info = container_of(work,
+                       struct max77843_muic_info, irq_work);
+       struct max77843 *max77843 = info->max77843;
+       int ret = 0;
+
+       mutex_lock(&info->mutex);
+
+       ret = regmap_bulk_read(max77843->regmap_muic,
+                       MAX77843_MUIC_REG_STATUS1, info->status,
+                       MAX77843_MUIC_STATUS_NUM);
+       if (ret) {
+               dev_err(info->dev, "Cannot read STATUS registers\n");
+               mutex_unlock(&info->mutex);
+               return;
+       }
+
+       if (info->irq_adc) {
+               ret = max77843_muic_adc_handler(info);
+               if (ret)
+                       dev_err(info->dev, "Unknown cable type\n");
+               info->irq_adc = false;
+       }
+
+       if (info->irq_chg) {
+               ret = max77843_muic_chg_handler(info);
+               if (ret)
+                       dev_err(info->dev, "Unknown charger type\n");
+               info->irq_chg = false;
+       }
+
+       mutex_unlock(&info->mutex);
+}
+
+static irqreturn_t max77843_muic_irq_handler(int irq, void *data)
+{
+       struct max77843_muic_info *info = data;
+       int i, irq_type = -1;
+
+       for (i = 0; i < ARRAY_SIZE(max77843_muic_irqs); i++)
+               if (irq == max77843_muic_irqs[i].virq)
+                       irq_type = max77843_muic_irqs[i].irq;
+
+       switch (irq_type) {
+       case MAX77843_MUIC_IRQ_INT1_ADC:
+       case MAX77843_MUIC_IRQ_INT1_ADCERROR:
+       case MAX77843_MUIC_IRQ_INT1_ADC1K:
+               info->irq_adc = true;
+               break;
+       case MAX77843_MUIC_IRQ_INT2_CHGTYP:
+       case MAX77843_MUIC_IRQ_INT2_CHGDETRUN:
+       case MAX77843_MUIC_IRQ_INT2_DCDTMR:
+       case MAX77843_MUIC_IRQ_INT2_DXOVP:
+       case MAX77843_MUIC_IRQ_INT2_VBVOLT:
+               info->irq_chg = true;
+               break;
+       case MAX77843_MUIC_IRQ_INT3_VBADC:
+       case MAX77843_MUIC_IRQ_INT3_VDNMON:
+       case MAX77843_MUIC_IRQ_INT3_DNRES:
+       case MAX77843_MUIC_IRQ_INT3_MPNACK:
+       case MAX77843_MUIC_IRQ_INT3_MRXBUFOW:
+       case MAX77843_MUIC_IRQ_INT3_MRXTRF:
+       case MAX77843_MUIC_IRQ_INT3_MRXPERR:
+       case MAX77843_MUIC_IRQ_INT3_MRXRDY:
+               break;
+       default:
+               dev_err(info->dev, "Cannot recognize IRQ(%d)\n", irq_type);
+               break;
+       }
+
+       schedule_work(&info->irq_work);
+
+       return IRQ_HANDLED;
+}
+
+static void max77843_muic_detect_cable_wq(struct work_struct *work)
+{
+       struct max77843_muic_info *info = container_of(to_delayed_work(work),
+                       struct max77843_muic_info, wq_detcable);
+       struct max77843 *max77843 = info->max77843;
+       int chg_type, adc, ret;
+       bool attached;
+
+       mutex_lock(&info->mutex);
+
+       ret = regmap_bulk_read(max77843->regmap_muic,
+                       MAX77843_MUIC_REG_STATUS1, info->status,
+                       MAX77843_MUIC_STATUS_NUM);
+       if (ret) {
+               dev_err(info->dev, "Cannot read STATUS registers\n");
+               goto err_cable_wq;
+       }
+
+       adc = max77843_muic_get_cable_type(info,
+                       MAX77843_CABLE_GROUP_ADC, &attached);
+       if (attached && adc != MAX77843_MUIC_ADC_OPEN) {
+               ret = max77843_muic_adc_handler(info);
+               if (ret < 0) {
+                       dev_err(info->dev, "Cannot detect accessory\n");
+                       goto err_cable_wq;
+               }
+       }
+
+       chg_type = max77843_muic_get_cable_type(info,
+                       MAX77843_CABLE_GROUP_CHG, &attached);
+       if (attached && chg_type != MAX77843_MUIC_CHG_NONE) {
+               ret = max77843_muic_chg_handler(info);
+               if (ret < 0) {
+                       dev_err(info->dev, "Cannot detect charger accessory\n");
+                       goto err_cable_wq;
+               }
+       }
+
+err_cable_wq:
+       mutex_unlock(&info->mutex);
+}
+
+static int max77843_muic_set_debounce_time(struct max77843_muic_info *info,
+               enum max77843_muic_adc_debounce_time time)
+{
+       struct max77843 *max77843 = info->max77843;
+       int ret;
+
+       switch (time) {
+       case MAX77843_DEBOUNCE_TIME_5MS:
+       case MAX77843_DEBOUNCE_TIME_10MS:
+       case MAX77843_DEBOUNCE_TIME_25MS:
+       case MAX77843_DEBOUNCE_TIME_38_62MS:
+               ret = regmap_update_bits(max77843->regmap_muic,
+                               MAX77843_MUIC_REG_CONTROL4,
+                               MAX77843_MUIC_CONTROL4_ADCDBSET_MASK,
+                               time << CONTROL4_ADCDBSET_SHIFT);
+               if (ret < 0) {
+                       dev_err(info->dev, "Cannot write MUIC regmap\n");
+                       return ret;
+               }
+               break;
+       default:
+               dev_err(info->dev, "Invalid ADC debounce time\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int max77843_init_muic_regmap(struct max77843 *max77843)
+{
+       int ret;
+
+       max77843->i2c_muic = i2c_new_dummy(max77843->i2c->adapter,
+                       I2C_ADDR_MUIC);
+       if (!max77843->i2c_muic) {
+               dev_err(&max77843->i2c->dev,
+                               "Cannot allocate I2C device for MUIC\n");
+               return -ENOMEM;
+       }
+
+       i2c_set_clientdata(max77843->i2c_muic, max77843);
+
+       max77843->regmap_muic = devm_regmap_init_i2c(max77843->i2c_muic,
+                       &max77843_muic_regmap_config);
+       if (IS_ERR(max77843->regmap_muic)) {
+               ret = PTR_ERR(max77843->regmap_muic);
+               goto err_muic_i2c;
+       }
+
+       ret = regmap_add_irq_chip(max77843->regmap_muic, max77843->irq,
+                       IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,
+                       0, &max77843_muic_irq_chip, &max77843->irq_data_muic);
+       if (ret < 0) {
+               dev_err(&max77843->i2c->dev, "Cannot add MUIC IRQ chip\n");
+               goto err_muic_i2c;
+       }
+
+       return 0;
+
+err_muic_i2c:
+       i2c_unregister_device(max77843->i2c_muic);
+
+       return ret;
+}
+
+static int max77843_muic_probe(struct platform_device *pdev)
+{
+       struct max77843 *max77843 = dev_get_drvdata(pdev->dev.parent);
+       struct max77843_muic_info *info;
+       unsigned int id;
+       int i, ret;
+
+       info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+
+       info->dev = &pdev->dev;
+       info->max77843 = max77843;
+
+       platform_set_drvdata(pdev, info);
+       mutex_init(&info->mutex);
+
+       /* Initialize i2c and regmap */
+       ret = max77843_init_muic_regmap(max77843);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to init MUIC regmap\n");
+               return ret;
+       }
+
+       /* Turn off auto detection configuration */
+       ret = regmap_update_bits(max77843->regmap_muic,
+                       MAX77843_MUIC_REG_CONTROL4,
+                       MAX77843_MUIC_CONTROL4_USBAUTO_MASK |
+                       MAX77843_MUIC_CONTROL4_FCTAUTO_MASK,
+                       CONTROL4_AUTO_DISABLE);
+
+       /* Initialize extcon device */
+       info->edev = devm_extcon_dev_allocate(&pdev->dev,
+                       max77843_extcon_cable);
+       if (IS_ERR(info->edev)) {
+               dev_err(&pdev->dev, "Failed to allocate memory for extcon\n");
+               ret = -ENODEV;
+               goto err_muic_irq;
+       }
+
+       ret = devm_extcon_dev_register(&pdev->dev, info->edev);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to register extcon device\n");
+               goto err_muic_irq;
+       }
+
+       /* Set ADC debounce time */
+       max77843_muic_set_debounce_time(info, MAX77843_DEBOUNCE_TIME_25MS);
+
+       /* Set initial path for UART */
+       max77843_muic_set_path(info, CONTROL1_SW_UART, true);
+
+       /* Check revision number of MUIC device */
+       ret = regmap_read(max77843->regmap_muic, MAX77843_MUIC_REG_ID, &id);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to read revision number\n");
+               goto err_muic_irq;
+       }
+       dev_info(info->dev, "MUIC device ID : 0x%x\n", id);
+
+       /* Support virtual irq domain for max77843 MUIC device */
+       INIT_WORK(&info->irq_work, max77843_muic_irq_work);
+
+       for (i = 0; i < ARRAY_SIZE(max77843_muic_irqs); i++) {
+               struct max77843_muic_irq *muic_irq = &max77843_muic_irqs[i];
+               unsigned int virq = 0;
+
+               virq = regmap_irq_get_virq(max77843->irq_data_muic,
+                               muic_irq->irq);
+               if (virq <= 0) {
+                       ret = -EINVAL;
+                       goto err_muic_irq;
+               }
+               muic_irq->virq = virq;
+
+               ret = devm_request_threaded_irq(&pdev->dev, virq, NULL,
+                               max77843_muic_irq_handler, IRQF_NO_SUSPEND,
+                               muic_irq->name, info);
+               if (ret) {
+                       dev_err(&pdev->dev,
+                               "Failed to request irq (IRQ: %d, error: %d)\n",
+                               muic_irq->irq, ret);
+                       goto err_muic_irq;
+               }
+       }
+
+       /* Detect accessory after completing the initialization of platform */
+       INIT_DELAYED_WORK(&info->wq_detcable, max77843_muic_detect_cable_wq);
+       queue_delayed_work(system_power_efficient_wq,
+                       &info->wq_detcable, msecs_to_jiffies(DELAY_MS_DEFAULT));
+
+       return 0;
+
+err_muic_irq:
+       regmap_del_irq_chip(max77843->irq, max77843->irq_data_muic);
+       i2c_unregister_device(max77843->i2c_muic);
+
+       return ret;
+}
+
+static int max77843_muic_remove(struct platform_device *pdev)
+{
+       struct max77843_muic_info *info = platform_get_drvdata(pdev);
+       struct max77843 *max77843 = info->max77843;
+
+       cancel_work_sync(&info->irq_work);
+       regmap_del_irq_chip(max77843->irq, max77843->irq_data_muic);
+       i2c_unregister_device(max77843->i2c_muic);
+
+       return 0;
+}
+
+static const struct platform_device_id max77843_muic_id[] = {
+       { "max77843-muic", },
+       { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(platform, max77843_muic_id);
+
+static struct platform_driver max77843_muic_driver = {
+       .driver         = {
+               .name           = "max77843-muic",
+       },
+       .probe          = max77843_muic_probe,
+       .remove         = max77843_muic_remove,
+       .id_table       = max77843_muic_id,
+};
+
+static int __init max77843_muic_init(void)
+{
+       return platform_driver_register(&max77843_muic_driver);
+}
+subsys_initcall(max77843_muic_init);
+
+MODULE_DESCRIPTION("Maxim MAX77843 Extcon driver");
+MODULE_AUTHOR("Jaewon Kim <jaewon02.kim@samsung.com>");
+MODULE_LICENSE("GPL");
index fc1678fa95c4cd258401a1eee871c8ed8ee6f59f..5774e56c64222a43f21eb28e9baeecc79bc176e1 100644 (file)
@@ -579,8 +579,6 @@ static void max8997_muic_irq_work(struct work_struct *work)
                dev_err(info->dev, "failed to handle MUIC interrupt\n");
 
        mutex_unlock(&info->mutex);
-
-       return;
 }
 
 static irqreturn_t max8997_muic_irq_handler(int irq, void *data)
@@ -689,8 +687,7 @@ static int max8997_muic_probe(struct platform_device *pdev)
                                muic_irq->name, info);
                if (ret) {
                        dev_err(&pdev->dev,
-                               "failed: irq request (IRQ: %d,"
-                               " error :%d)\n",
+                               "failed: irq request (IRQ: %d, error :%d)\n",
                                muic_irq->irq, ret);
                        goto err_irq;
                }
index a784b2d5ee72b57fb1537438a661c7ead9d88f15..9ccd5af89d1c058bab1564340f63a337a7d17c47 100644 (file)
@@ -582,10 +582,8 @@ static int rt8973a_muic_i2c_probe(struct i2c_client *i2c,
                return -EINVAL;
 
        info = devm_kzalloc(&i2c->dev, sizeof(*info), GFP_KERNEL);
-       if (!info) {
-               dev_err(&i2c->dev, "failed to allocate memory\n");
+       if (!info)
                return -ENOMEM;
-       }
        i2c_set_clientdata(i2c, info);
 
        info->dev = &i2c->dev;
@@ -681,7 +679,7 @@ static int rt8973a_muic_i2c_remove(struct i2c_client *i2c)
        return 0;
 }
 
-static struct of_device_id rt8973a_dt_match[] = {
+static const struct of_device_id rt8973a_dt_match[] = {
        { .compatible = "richtek,rt8973a-muic" },
        { },
 };
index b0f7bd82af90436d7e433a7350f80195f57d7e52..2f93cf3078521e7c2f635ed9320b1d7984a383e5 100644 (file)
@@ -359,8 +359,8 @@ static unsigned int sm5502_muic_get_cable_type(struct sm5502_muic_info *info)
                        break;
                default:
                        dev_dbg(info->dev,
-                               "cannot identify the cable type: adc(0x%x) "
-                               "dev_type1(0x%x)\n", adc, dev_type1);
+                               "cannot identify the cable type: adc(0x%x)\n",
+                               adc);
                        return -EINVAL;
                };
                break;
@@ -659,7 +659,7 @@ static int sm5502_muic_i2c_remove(struct i2c_client *i2c)
        return 0;
 }
 
-static struct of_device_id sm5502_dt_match[] = {
+static const struct of_device_id sm5502_dt_match[] = {
        { .compatible = "siliconmitus,sm5502-muic" },
        { },
 };
diff --git a/drivers/extcon/extcon-usb-gpio.c b/drivers/extcon/extcon-usb-gpio.c
new file mode 100644 (file)
index 0000000..de67fce
--- /dev/null
@@ -0,0 +1,237 @@
+/**
+ * drivers/extcon/extcon-usb-gpio.c - USB GPIO extcon driver
+ *
+ * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com
+ * Author: Roger Quadros <rogerq@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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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/extcon.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+
+#define USB_GPIO_DEBOUNCE_MS   20      /* ms */
+
+struct usb_extcon_info {
+       struct device *dev;
+       struct extcon_dev *edev;
+
+       struct gpio_desc *id_gpiod;
+       int id_irq;
+
+       unsigned long debounce_jiffies;
+       struct delayed_work wq_detcable;
+};
+
+/* List of detectable cables */
+enum {
+       EXTCON_CABLE_USB = 0,
+       EXTCON_CABLE_USB_HOST,
+
+       EXTCON_CABLE_END,
+};
+
+static const char *usb_extcon_cable[] = {
+       [EXTCON_CABLE_USB] = "USB",
+       [EXTCON_CABLE_USB_HOST] = "USB-HOST",
+       NULL,
+};
+
+static void usb_extcon_detect_cable(struct work_struct *work)
+{
+       int id;
+       struct usb_extcon_info *info = container_of(to_delayed_work(work),
+                                                   struct usb_extcon_info,
+                                                   wq_detcable);
+
+       /* check ID and update cable state */
+       id = gpiod_get_value_cansleep(info->id_gpiod);
+       if (id) {
+               /*
+                * ID = 1 means USB HOST cable detached.
+                * As we don't have event for USB peripheral cable attached,
+                * we simulate USB peripheral attach here.
+                */
+               extcon_set_cable_state(info->edev,
+                                      usb_extcon_cable[EXTCON_CABLE_USB_HOST],
+                                      false);
+               extcon_set_cable_state(info->edev,
+                                      usb_extcon_cable[EXTCON_CABLE_USB],
+                                      true);
+       } else {
+               /*
+                * ID = 0 means USB HOST cable attached.
+                * As we don't have event for USB peripheral cable detached,
+                * we simulate USB peripheral detach here.
+                */
+               extcon_set_cable_state(info->edev,
+                                      usb_extcon_cable[EXTCON_CABLE_USB],
+                                      false);
+               extcon_set_cable_state(info->edev,
+                                      usb_extcon_cable[EXTCON_CABLE_USB_HOST],
+                                      true);
+       }
+}
+
+static irqreturn_t usb_irq_handler(int irq, void *dev_id)
+{
+       struct usb_extcon_info *info = dev_id;
+
+       queue_delayed_work(system_power_efficient_wq, &info->wq_detcable,
+                          info->debounce_jiffies);
+
+       return IRQ_HANDLED;
+}
+
+static int usb_extcon_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       struct usb_extcon_info *info;
+       int ret;
+
+       if (!np)
+               return -EINVAL;
+
+       info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+
+       info->dev = dev;
+       info->id_gpiod = devm_gpiod_get(&pdev->dev, "id");
+       if (IS_ERR(info->id_gpiod)) {
+               dev_err(dev, "failed to get ID GPIO\n");
+               return PTR_ERR(info->id_gpiod);
+       }
+
+       ret = gpiod_set_debounce(info->id_gpiod,
+                                USB_GPIO_DEBOUNCE_MS * 1000);
+       if (ret < 0)
+               info->debounce_jiffies = msecs_to_jiffies(USB_GPIO_DEBOUNCE_MS);
+
+       INIT_DELAYED_WORK(&info->wq_detcable, usb_extcon_detect_cable);
+
+       info->id_irq = gpiod_to_irq(info->id_gpiod);
+       if (info->id_irq < 0) {
+               dev_err(dev, "failed to get ID IRQ\n");
+               return info->id_irq;
+       }
+
+       ret = devm_request_threaded_irq(dev, info->id_irq, NULL,
+                                       usb_irq_handler,
+                                       IRQF_TRIGGER_RISING |
+                                       IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+                                       pdev->name, info);
+       if (ret < 0) {
+               dev_err(dev, "failed to request handler for ID IRQ\n");
+               return ret;
+       }
+
+       info->edev = devm_extcon_dev_allocate(dev, usb_extcon_cable);
+       if (IS_ERR(info->edev)) {
+               dev_err(dev, "failed to allocate extcon device\n");
+               return -ENOMEM;
+       }
+
+       ret = devm_extcon_dev_register(dev, info->edev);
+       if (ret < 0) {
+               dev_err(dev, "failed to register extcon device\n");
+               return ret;
+       }
+
+       platform_set_drvdata(pdev, info);
+       device_init_wakeup(dev, 1);
+
+       /* Perform initial detection */
+       usb_extcon_detect_cable(&info->wq_detcable.work);
+
+       return 0;
+}
+
+static int usb_extcon_remove(struct platform_device *pdev)
+{
+       struct usb_extcon_info *info = platform_get_drvdata(pdev);
+
+       cancel_delayed_work_sync(&info->wq_detcable);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int usb_extcon_suspend(struct device *dev)
+{
+       struct usb_extcon_info *info = dev_get_drvdata(dev);
+       int ret = 0;
+
+       if (device_may_wakeup(dev)) {
+               ret = enable_irq_wake(info->id_irq);
+               if (ret)
+                       return ret;
+       }
+
+       /*
+        * We don't want to process any IRQs after this point
+        * as GPIOs used behind I2C subsystem might not be
+        * accessible until resume completes. So disable IRQ.
+        */
+       disable_irq(info->id_irq);
+
+       return ret;
+}
+
+static int usb_extcon_resume(struct device *dev)
+{
+       struct usb_extcon_info *info = dev_get_drvdata(dev);
+       int ret = 0;
+
+       if (device_may_wakeup(dev)) {
+               ret = disable_irq_wake(info->id_irq);
+               if (ret)
+                       return ret;
+       }
+
+       enable_irq(info->id_irq);
+
+       return ret;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(usb_extcon_pm_ops,
+                        usb_extcon_suspend, usb_extcon_resume);
+
+static const struct of_device_id usb_extcon_dt_match[] = {
+       { .compatible = "linux,extcon-usb-gpio", },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, usb_extcon_dt_match);
+
+static struct platform_driver usb_extcon_driver = {
+       .probe          = usb_extcon_probe,
+       .remove         = usb_extcon_remove,
+       .driver         = {
+               .name   = "extcon-usb-gpio",
+               .pm     = &usb_extcon_pm_ops,
+               .of_match_table = usb_extcon_dt_match,
+       },
+};
+
+module_platform_driver(usb_extcon_driver);
+
+MODULE_AUTHOR("Roger Quadros <rogerq@ti.com>");
+MODULE_DESCRIPTION("USB GPIO extcon driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c
new file mode 100644 (file)
index 0000000..4c9f165
--- /dev/null
@@ -0,0 +1,1066 @@
+/*
+ *  drivers/extcon/extcon_class.c
+ *
+ *  External connector (extcon) class driver
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * Author: Donggeun Kim <dg77.kim@samsung.com>
+ * Author: MyungJoo Ham <myungjoo.ham@samsung.com>
+ *
+ * based on android/drivers/switch/switch_class.c
+ * Copyright (C) 2008 Google, Inc.
+ * Author: Mike Lockwood <lockwood@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+*/
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/err.h>
+#include <linux/extcon.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+
+/*
+ * extcon_cable_name suggests the standard cable names for commonly used
+ * cable types.
+ *
+ * However, please do not use extcon_cable_name directly for extcon_dev
+ * struct's supported_cable pointer unless your device really supports
+ * every single port-type of the following cable names. Please choose cable
+ * names that are actually used in your extcon device.
+ */
+const char extcon_cable_name[][CABLE_NAME_MAX + 1] = {
+       [EXTCON_USB]            = "USB",
+       [EXTCON_USB_HOST]       = "USB-Host",
+       [EXTCON_TA]             = "TA",
+       [EXTCON_FAST_CHARGER]   = "Fast-charger",
+       [EXTCON_SLOW_CHARGER]   = "Slow-charger",
+       [EXTCON_CHARGE_DOWNSTREAM]      = "Charge-downstream",
+       [EXTCON_HDMI]           = "HDMI",
+       [EXTCON_MHL]            = "MHL",
+       [EXTCON_DVI]            = "DVI",
+       [EXTCON_VGA]            = "VGA",
+       [EXTCON_DOCK]           = "Dock",
+       [EXTCON_LINE_IN]        = "Line-in",
+       [EXTCON_LINE_OUT]       = "Line-out",
+       [EXTCON_MIC_IN]         = "Microphone",
+       [EXTCON_HEADPHONE_OUT]  = "Headphone",
+       [EXTCON_SPDIF_IN]       = "SPDIF-in",
+       [EXTCON_SPDIF_OUT]      = "SPDIF-out",
+       [EXTCON_VIDEO_IN]       = "Video-in",
+       [EXTCON_VIDEO_OUT]      = "Video-out",
+       [EXTCON_MECHANICAL]     = "Mechanical",
+};
+
+static struct class *extcon_class;
+#if defined(CONFIG_ANDROID)
+static struct class_compat *switch_class;
+#endif /* CONFIG_ANDROID */
+
+static LIST_HEAD(extcon_dev_list);
+static DEFINE_MUTEX(extcon_dev_list_lock);
+
+/**
+ * check_mutually_exclusive - Check if new_state violates mutually_exclusive
+ *                           condition.
+ * @edev:      the extcon device
+ * @new_state: new cable attach status for @edev
+ *
+ * Returns 0 if nothing violates. Returns the index + 1 for the first
+ * violated condition.
+ */
+static int check_mutually_exclusive(struct extcon_dev *edev, u32 new_state)
+{
+       int i = 0;
+
+       if (!edev->mutually_exclusive)
+               return 0;
+
+       for (i = 0; edev->mutually_exclusive[i]; i++) {
+               int weight;
+               u32 correspondants = new_state & edev->mutually_exclusive[i];
+
+               /* calculate the total number of bits set */
+               weight = hweight32(correspondants);
+               if (weight > 1)
+                       return i + 1;
+       }
+
+       return 0;
+}
+
+static ssize_t state_show(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       int i, count = 0;
+       struct extcon_dev *edev = dev_get_drvdata(dev);
+
+       if (edev->print_state) {
+               int ret = edev->print_state(edev, buf);
+
+               if (ret >= 0)
+                       return ret;
+               /* Use default if failed */
+       }
+
+       if (edev->max_supported == 0)
+               return sprintf(buf, "%u\n", edev->state);
+
+       for (i = 0; i < SUPPORTED_CABLE_MAX; i++) {
+               if (!edev->supported_cable[i])
+                       break;
+               count += sprintf(buf + count, "%s=%d\n",
+                                edev->supported_cable[i],
+                                !!(edev->state & (1 << i)));
+       }
+
+       return count;
+}
+
+static ssize_t state_store(struct device *dev, struct device_attribute *attr,
+                          const char *buf, size_t count)
+{
+       u32 state;
+       ssize_t ret = 0;
+       struct extcon_dev *edev = dev_get_drvdata(dev);
+
+       ret = sscanf(buf, "0x%x", &state);
+       if (ret == 0)
+               ret = -EINVAL;
+       else
+               ret = extcon_set_state(edev, state);
+
+       if (ret < 0)
+               return ret;
+
+       return count;
+}
+static DEVICE_ATTR_RW(state);
+
+static ssize_t name_show(struct device *dev, struct device_attribute *attr,
+               char *buf)
+{
+       struct extcon_dev *edev = dev_get_drvdata(dev);
+
+       /* Optional callback given by the user */
+       if (edev->print_name) {
+               int ret = edev->print_name(edev, buf);
+
+               if (ret >= 0)
+                       return ret;
+       }
+
+       return sprintf(buf, "%s\n", dev_name(&edev->dev));
+}
+static DEVICE_ATTR_RO(name);
+
+static ssize_t cable_name_show(struct device *dev,
+                              struct device_attribute *attr, char *buf)
+{
+       struct extcon_cable *cable = container_of(attr, struct extcon_cable,
+                                                 attr_name);
+
+       return sprintf(buf, "%s\n",
+                      cable->edev->supported_cable[cable->cable_index]);
+}
+
+static ssize_t cable_state_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct extcon_cable *cable = container_of(attr, struct extcon_cable,
+                                                 attr_state);
+
+       return sprintf(buf, "%d\n",
+                      extcon_get_cable_state_(cable->edev,
+                                              cable->cable_index));
+}
+
+/**
+ * extcon_update_state() - Update the cable attach states of the extcon device
+ *                        only for the masked bits.
+ * @edev:      the extcon device
+ * @mask:      the bit mask to designate updated bits.
+ * @state:     new cable attach status for @edev
+ *
+ * Changing the state sends uevent with environment variable containing
+ * the name of extcon device (envp[0]) and the state output (envp[1]).
+ * Tizen uses this format for extcon device to get events from ports.
+ * Android uses this format as well.
+ *
+ * Note that the notifier provides which bits are changed in the state
+ * variable with the val parameter (second) to the callback.
+ */
+int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state)
+{
+       char name_buf[120];
+       char state_buf[120];
+       char *prop_buf;
+       char *envp[3];
+       int env_offset = 0;
+       int length;
+       unsigned long flags;
+
+       spin_lock_irqsave(&edev->lock, flags);
+
+       if (edev->state != ((edev->state & ~mask) | (state & mask))) {
+               u32 old_state = edev->state;
+
+               if (check_mutually_exclusive(edev, (edev->state & ~mask) |
+                                                  (state & mask))) {
+                       spin_unlock_irqrestore(&edev->lock, flags);
+                       return -EPERM;
+               }
+
+               edev->state &= ~mask;
+               edev->state |= state & mask;
+
+               raw_notifier_call_chain(&edev->nh, old_state, edev);
+               /* This could be in interrupt handler */
+               prop_buf = (char *)get_zeroed_page(GFP_ATOMIC);
+               if (prop_buf) {
+                       length = name_show(&edev->dev, NULL, prop_buf);
+                       if (length > 0) {
+                               if (prop_buf[length - 1] == '\n')
+                                       prop_buf[length - 1] = 0;
+                               snprintf(name_buf, sizeof(name_buf),
+                                       "NAME=%s", prop_buf);
+                               envp[env_offset++] = name_buf;
+                       }
+                       length = state_show(&edev->dev, NULL, prop_buf);
+                       if (length > 0) {
+                               if (prop_buf[length - 1] == '\n')
+                                       prop_buf[length - 1] = 0;
+                               snprintf(state_buf, sizeof(state_buf),
+                                       "STATE=%s", prop_buf);
+                               envp[env_offset++] = state_buf;
+                       }
+                       envp[env_offset] = NULL;
+                       /* Unlock early before uevent */
+                       spin_unlock_irqrestore(&edev->lock, flags);
+
+                       kobject_uevent_env(&edev->dev.kobj, KOBJ_CHANGE, envp);
+                       free_page((unsigned long)prop_buf);
+               } else {
+                       /* Unlock early before uevent */
+                       spin_unlock_irqrestore(&edev->lock, flags);
+
+                       dev_err(&edev->dev, "out of memory in extcon_set_state\n");
+                       kobject_uevent(&edev->dev.kobj, KOBJ_CHANGE);
+               }
+       } else {
+               /* No changes */
+               spin_unlock_irqrestore(&edev->lock, flags);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(extcon_update_state);
+
+/**
+ * extcon_set_state() - Set the cable attach states of the extcon device.
+ * @edev:      the extcon device
+ * @state:     new cable attach status for @edev
+ *
+ * Note that notifier provides which bits are changed in the state
+ * variable with the val parameter (second) to the callback.
+ */
+int extcon_set_state(struct extcon_dev *edev, u32 state)
+{
+       return extcon_update_state(edev, 0xffffffff, state);
+}
+EXPORT_SYMBOL_GPL(extcon_set_state);
+
+/**
+ * extcon_find_cable_index() - Get the cable index based on the cable name.
+ * @edev:      the extcon device that has the cable.
+ * @cable_name:        cable name to be searched.
+ *
+ * Note that accessing a cable state based on cable_index is faster than
+ * cable_name because using cable_name induces a loop with strncmp().
+ * Thus, when get/set_cable_state is repeatedly used, using cable_index
+ * is recommended.
+ */
+int extcon_find_cable_index(struct extcon_dev *edev, const char *cable_name)
+{
+       int i;
+
+       if (edev->supported_cable) {
+               for (i = 0; edev->supported_cable[i]; i++) {
+                       if (!strncmp(edev->supported_cable[i],
+                               cable_name, CABLE_NAME_MAX))
+                               return i;
+               }
+       }
+
+       return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(extcon_find_cable_index);
+
+/**
+ * extcon_get_cable_state_() - Get the status of a specific cable.
+ * @edev:      the extcon device that has the cable.
+ * @index:     cable index that can be retrieved by extcon_find_cable_index().
+ */
+int extcon_get_cable_state_(struct extcon_dev *edev, int index)
+{
+       if (index < 0 || (edev->max_supported && edev->max_supported <= index))
+               return -EINVAL;
+
+       return !!(edev->state & (1 << index));
+}
+EXPORT_SYMBOL_GPL(extcon_get_cable_state_);
+
+/**
+ * extcon_get_cable_state() - Get the status of a specific cable.
+ * @edev:      the extcon device that has the cable.
+ * @cable_name:        cable name.
+ *
+ * Note that this is slower than extcon_get_cable_state_.
+ */
+int extcon_get_cable_state(struct extcon_dev *edev, const char *cable_name)
+{
+       return extcon_get_cable_state_(edev, extcon_find_cable_index
+                                               (edev, cable_name));
+}
+EXPORT_SYMBOL_GPL(extcon_get_cable_state);
+
+/**
+ * extcon_set_cable_state_() - Set the status of a specific cable.
+ * @edev:              the extcon device that has the cable.
+ * @index:             cable index that can be retrieved by
+ *                     extcon_find_cable_index().
+ * @cable_state:       the new cable status. The default semantics is
+ *                     true: attached / false: detached.
+ */
+int extcon_set_cable_state_(struct extcon_dev *edev,
+                       int index, bool cable_state)
+{
+       u32 state;
+
+       if (index < 0 || (edev->max_supported && edev->max_supported <= index))
+               return -EINVAL;
+
+       state = cable_state ? (1 << index) : 0;
+       return extcon_update_state(edev, 1 << index, state);
+}
+EXPORT_SYMBOL_GPL(extcon_set_cable_state_);
+
+/**
+ * extcon_set_cable_state() - Set the status of a specific cable.
+ * @edev:              the extcon device that has the cable.
+ * @cable_name:                cable name.
+ * @cable_state:       the new cable status. The default semantics is
+ *                     true: attached / false: detached.
+ *
+ * Note that this is slower than extcon_set_cable_state_.
+ */
+int extcon_set_cable_state(struct extcon_dev *edev,
+                       const char *cable_name, bool cable_state)
+{
+       return extcon_set_cable_state_(edev, extcon_find_cable_index
+                                       (edev, cable_name), cable_state);
+}
+EXPORT_SYMBOL_GPL(extcon_set_cable_state);
+
+/**
+ * extcon_get_extcon_dev() - Get the extcon device instance from the name
+ * @extcon_name:       The extcon name provided with extcon_dev_register()
+ */
+struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name)
+{
+       struct extcon_dev *sd;
+
+       mutex_lock(&extcon_dev_list_lock);
+       list_for_each_entry(sd, &extcon_dev_list, entry) {
+               if (!strcmp(sd->name, extcon_name))
+                       goto out;
+       }
+       sd = NULL;
+out:
+       mutex_unlock(&extcon_dev_list_lock);
+       return sd;
+}
+EXPORT_SYMBOL_GPL(extcon_get_extcon_dev);
+
+static int _call_per_cable(struct notifier_block *nb, unsigned long val,
+                          void *ptr)
+{
+       struct extcon_specific_cable_nb *obj = container_of(nb,
+                       struct extcon_specific_cable_nb, internal_nb);
+       struct extcon_dev *edev = ptr;
+
+       if ((val & (1 << obj->cable_index)) !=
+           (edev->state & (1 << obj->cable_index))) {
+               bool cable_state = true;
+
+               obj->previous_value = val;
+
+               if (val & (1 << obj->cable_index))
+                       cable_state = false;
+
+               return obj->user_nb->notifier_call(obj->user_nb,
+                               cable_state, ptr);
+       }
+
+       return NOTIFY_OK;
+}
+
+/**
+ * extcon_register_interest() - Register a notifier for a state change of a
+ *                             specific cable, not an entier set of cables of a
+ *                             extcon device.
+ * @obj:               an empty extcon_specific_cable_nb object to be returned.
+ * @extcon_name:       the name of extcon device.
+ *                     if NULL, extcon_register_interest will register
+ *                     every cable with the target cable_name given.
+ * @cable_name:                the target cable name.
+ * @nb:                        the notifier block to get notified.
+ *
+ * Provide an empty extcon_specific_cable_nb. extcon_register_interest() sets
+ * the struct for you.
+ *
+ * extcon_register_interest is a helper function for those who want to get
+ * notification for a single specific cable's status change. If a user wants
+ * to get notification for any changes of all cables of a extcon device,
+ * he/she should use the general extcon_register_notifier().
+ *
+ * Note that the second parameter given to the callback of nb (val) is
+ * "old_state", not the current state. The current state can be retrieved
+ * by looking at the third pameter (edev pointer)'s state value.
+ */
+int extcon_register_interest(struct extcon_specific_cable_nb *obj,
+                            const char *extcon_name, const char *cable_name,
+                            struct notifier_block *nb)
+{
+       unsigned long flags;
+       int ret;
+
+       if (!obj || !cable_name || !nb)
+               return -EINVAL;
+
+       if (extcon_name) {
+               obj->edev = extcon_get_extcon_dev(extcon_name);
+               if (!obj->edev)
+                       return -ENODEV;
+
+               obj->cable_index = extcon_find_cable_index(obj->edev,
+                                                         cable_name);
+               if (obj->cable_index < 0)
+                       return obj->cable_index;
+
+               obj->user_nb = nb;
+
+               obj->internal_nb.notifier_call = _call_per_cable;
+
+               spin_lock_irqsave(&obj->edev->lock, flags);
+               ret = raw_notifier_chain_register(&obj->edev->nh,
+                                                 &obj->internal_nb);
+               spin_unlock_irqrestore(&obj->edev->lock, flags);
+               return ret;
+       } else {
+               struct class_dev_iter iter;
+               struct extcon_dev *extd;
+               struct device *dev;
+
+               if (!extcon_class)
+                       return -ENODEV;
+               class_dev_iter_init(&iter, extcon_class, NULL, NULL);
+               while ((dev = class_dev_iter_next(&iter))) {
+                       extd = dev_get_drvdata(dev);
+
+                       if (extcon_find_cable_index(extd, cable_name) < 0)
+                               continue;
+
+                       class_dev_iter_exit(&iter);
+                       return extcon_register_interest(obj, extd->name,
+                                               cable_name, nb);
+               }
+
+               return -ENODEV;
+       }
+}
+EXPORT_SYMBOL_GPL(extcon_register_interest);
+
+/**
+ * extcon_unregister_interest() - Unregister the notifier registered by
+ *                               extcon_register_interest().
+ * @obj:       the extcon_specific_cable_nb object returned by
+ *             extcon_register_interest().
+ */
+int extcon_unregister_interest(struct extcon_specific_cable_nb *obj)
+{
+       unsigned long flags;
+       int ret;
+
+       if (!obj)
+               return -EINVAL;
+
+       spin_lock_irqsave(&obj->edev->lock, flags);
+       ret = raw_notifier_chain_unregister(&obj->edev->nh, &obj->internal_nb);
+       spin_unlock_irqrestore(&obj->edev->lock, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(extcon_unregister_interest);
+
+/**
+ * extcon_register_notifier() - Register a notifiee to get notified by
+ *                             any attach status changes from the extcon.
+ * @edev:      the extcon device.
+ * @nb:                a notifier block to be registered.
+ *
+ * Note that the second parameter given to the callback of nb (val) is
+ * "old_state", not the current state. The current state can be retrieved
+ * by looking at the third pameter (edev pointer)'s state value.
+ */
+int extcon_register_notifier(struct extcon_dev *edev,
+                       struct notifier_block *nb)
+{
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&edev->lock, flags);
+       ret = raw_notifier_chain_register(&edev->nh, nb);
+       spin_unlock_irqrestore(&edev->lock, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(extcon_register_notifier);
+
+/**
+ * extcon_unregister_notifier() - Unregister a notifiee from the extcon device.
+ * @edev:      the extcon device.
+ * @nb:                a registered notifier block to be unregistered.
+ */
+int extcon_unregister_notifier(struct extcon_dev *edev,
+                       struct notifier_block *nb)
+{
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&edev->lock, flags);
+       ret = raw_notifier_chain_unregister(&edev->nh, nb);
+       spin_unlock_irqrestore(&edev->lock, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(extcon_unregister_notifier);
+
+static struct attribute *extcon_attrs[] = {
+       &dev_attr_state.attr,
+       &dev_attr_name.attr,
+       NULL,
+};
+ATTRIBUTE_GROUPS(extcon);
+
+static int create_extcon_class(void)
+{
+       if (!extcon_class) {
+               extcon_class = class_create(THIS_MODULE, "extcon");
+               if (IS_ERR(extcon_class))
+                       return PTR_ERR(extcon_class);
+               extcon_class->dev_groups = extcon_groups;
+
+#if defined(CONFIG_ANDROID)
+               switch_class = class_compat_register("switch");
+               if (WARN(!switch_class, "cannot allocate"))
+                       return -ENOMEM;
+#endif /* CONFIG_ANDROID */
+       }
+
+       return 0;
+}
+
+static void extcon_dev_release(struct device *dev)
+{
+}
+
+static const char *muex_name = "mutually_exclusive";
+static void dummy_sysfs_dev_release(struct device *dev)
+{
+}
+
+/*
+ * extcon_dev_allocate() - Allocate the memory of extcon device.
+ * @supported_cable:   Array of supported cable names ending with NULL.
+ *                     If supported_cable is NULL, cable name related APIs
+ *                     are disabled.
+ *
+ * This function allocates the memory for extcon device without allocating
+ * memory in each extcon provider driver and initialize default setting for
+ * extcon device.
+ *
+ * Return the pointer of extcon device if success or ERR_PTR(err) if fail
+ */
+struct extcon_dev *extcon_dev_allocate(const char **supported_cable)
+{
+       struct extcon_dev *edev;
+
+       edev = kzalloc(sizeof(*edev), GFP_KERNEL);
+       if (!edev)
+               return ERR_PTR(-ENOMEM);
+
+       edev->max_supported = 0;
+       edev->supported_cable = supported_cable;
+
+       return edev;
+}
+
+/*
+ * extcon_dev_free() - Free the memory of extcon device.
+ * @edev:      the extcon device to free
+ */
+void extcon_dev_free(struct extcon_dev *edev)
+{
+       kfree(edev);
+}
+EXPORT_SYMBOL_GPL(extcon_dev_free);
+
+static int devm_extcon_dev_match(struct device *dev, void *res, void *data)
+{
+       struct extcon_dev **r = res;
+
+       if (WARN_ON(!r || !*r))
+               return 0;
+
+       return *r == data;
+}
+
+static void devm_extcon_dev_release(struct device *dev, void *res)
+{
+       extcon_dev_free(*(struct extcon_dev **)res);
+}
+
+/**
+ * devm_extcon_dev_allocate - Allocate managed extcon device
+ * @dev:               device owning the extcon device being created
+ * @supported_cable:   Array of supported cable names ending with NULL.
+ *                     If supported_cable is NULL, cable name related APIs
+ *                     are disabled.
+ *
+ * This function manages automatically the memory of extcon device using device
+ * resource management and simplify the control of freeing the memory of extcon
+ * device.
+ *
+ * Returns the pointer memory of allocated extcon_dev if success
+ * or ERR_PTR(err) if fail
+ */
+struct extcon_dev *devm_extcon_dev_allocate(struct device *dev,
+                                           const char **supported_cable)
+{
+       struct extcon_dev **ptr, *edev;
+
+       ptr = devres_alloc(devm_extcon_dev_release, sizeof(*ptr), GFP_KERNEL);
+       if (!ptr)
+               return ERR_PTR(-ENOMEM);
+
+       edev = extcon_dev_allocate(supported_cable);
+       if (IS_ERR(edev)) {
+               devres_free(ptr);
+               return edev;
+       }
+
+       edev->dev.parent = dev;
+
+       *ptr = edev;
+       devres_add(dev, ptr);
+
+       return edev;
+}
+EXPORT_SYMBOL_GPL(devm_extcon_dev_allocate);
+
+void devm_extcon_dev_free(struct device *dev, struct extcon_dev *edev)
+{
+       WARN_ON(devres_release(dev, devm_extcon_dev_release,
+                              devm_extcon_dev_match, edev));
+}
+EXPORT_SYMBOL_GPL(devm_extcon_dev_free);
+
+/**
+ * extcon_dev_register() - Register a new extcon device
+ * @edev       : the new extcon device (should be allocated before calling)
+ *
+ * Among the members of edev struct, please set the "user initializing data"
+ * in any case and set the "optional callbacks" if required. However, please
+ * do not set the values of "internal data", which are initialized by
+ * this function.
+ */
+int extcon_dev_register(struct extcon_dev *edev)
+{
+       int ret, index = 0;
+
+       if (!extcon_class) {
+               ret = create_extcon_class();
+               if (ret < 0)
+                       return ret;
+       }
+
+       if (edev->supported_cable) {
+               /* Get size of array */
+               for (index = 0; edev->supported_cable[index]; index++)
+                       ;
+               edev->max_supported = index;
+       } else {
+               edev->max_supported = 0;
+       }
+
+       if (index > SUPPORTED_CABLE_MAX) {
+               dev_err(&edev->dev, "extcon: maximum number of supported cables exceeded.\n");
+               return -EINVAL;
+       }
+
+       edev->dev.class = extcon_class;
+       edev->dev.release = extcon_dev_release;
+
+       edev->name = edev->name ? edev->name : dev_name(edev->dev.parent);
+       if (IS_ERR_OR_NULL(edev->name)) {
+               dev_err(&edev->dev,
+                       "extcon device name is null\n");
+               return -EINVAL;
+       }
+       dev_set_name(&edev->dev, "%s", edev->name);
+
+       if (edev->max_supported) {
+               char buf[10];
+               char *str;
+               struct extcon_cable *cable;
+
+               edev->cables = kzalloc(sizeof(struct extcon_cable) *
+                                      edev->max_supported, GFP_KERNEL);
+               if (!edev->cables) {
+                       ret = -ENOMEM;
+                       goto err_sysfs_alloc;
+               }
+               for (index = 0; index < edev->max_supported; index++) {
+                       cable = &edev->cables[index];
+
+                       snprintf(buf, 10, "cable.%d", index);
+                       str = kzalloc(sizeof(char) * (strlen(buf) + 1),
+                                     GFP_KERNEL);
+                       if (!str) {
+                               for (index--; index >= 0; index--) {
+                                       cable = &edev->cables[index];
+                                       kfree(cable->attr_g.name);
+                               }
+                               ret = -ENOMEM;
+
+                               goto err_alloc_cables;
+                       }
+                       strcpy(str, buf);
+
+                       cable->edev = edev;
+                       cable->cable_index = index;
+                       cable->attrs[0] = &cable->attr_name.attr;
+                       cable->attrs[1] = &cable->attr_state.attr;
+                       cable->attrs[2] = NULL;
+                       cable->attr_g.name = str;
+                       cable->attr_g.attrs = cable->attrs;
+
+                       sysfs_attr_init(&cable->attr_name.attr);
+                       cable->attr_name.attr.name = "name";
+                       cable->attr_name.attr.mode = 0444;
+                       cable->attr_name.show = cable_name_show;
+
+                       sysfs_attr_init(&cable->attr_state.attr);
+                       cable->attr_state.attr.name = "state";
+                       cable->attr_state.attr.mode = 0444;
+                       cable->attr_state.show = cable_state_show;
+               }
+       }
+
+       if (edev->max_supported && edev->mutually_exclusive) {
+               char buf[80];
+               char *name;
+
+               /* Count the size of mutually_exclusive array */
+               for (index = 0; edev->mutually_exclusive[index]; index++)
+                       ;
+
+               edev->attrs_muex = kzalloc(sizeof(struct attribute *) *
+                                          (index + 1), GFP_KERNEL);
+               if (!edev->attrs_muex) {
+                       ret = -ENOMEM;
+                       goto err_muex;
+               }
+
+               edev->d_attrs_muex = kzalloc(sizeof(struct device_attribute) *
+                                            index, GFP_KERNEL);
+               if (!edev->d_attrs_muex) {
+                       ret = -ENOMEM;
+                       kfree(edev->attrs_muex);
+                       goto err_muex;
+               }
+
+               for (index = 0; edev->mutually_exclusive[index]; index++) {
+                       sprintf(buf, "0x%x", edev->mutually_exclusive[index]);
+                       name = kzalloc(sizeof(char) * (strlen(buf) + 1),
+                                      GFP_KERNEL);
+                       if (!name) {
+                               for (index--; index >= 0; index--) {
+                                       kfree(edev->d_attrs_muex[index].attr.
+                                             name);
+                               }
+                               kfree(edev->d_attrs_muex);
+                               kfree(edev->attrs_muex);
+                               ret = -ENOMEM;
+                               goto err_muex;
+                       }
+                       strcpy(name, buf);
+                       sysfs_attr_init(&edev->d_attrs_muex[index].attr);
+                       edev->d_attrs_muex[index].attr.name = name;
+                       edev->d_attrs_muex[index].attr.mode = 0000;
+                       edev->attrs_muex[index] = &edev->d_attrs_muex[index]
+                                                       .attr;
+               }
+               edev->attr_g_muex.name = muex_name;
+               edev->attr_g_muex.attrs = edev->attrs_muex;
+
+       }
+
+       if (edev->max_supported) {
+               edev->extcon_dev_type.groups =
+                       kzalloc(sizeof(struct attribute_group *) *
+                               (edev->max_supported + 2), GFP_KERNEL);
+               if (!edev->extcon_dev_type.groups) {
+                       ret = -ENOMEM;
+                       goto err_alloc_groups;
+               }
+
+               edev->extcon_dev_type.name = dev_name(&edev->dev);
+               edev->extcon_dev_type.release = dummy_sysfs_dev_release;
+
+               for (index = 0; index < edev->max_supported; index++)
+                       edev->extcon_dev_type.groups[index] =
+                               &edev->cables[index].attr_g;
+               if (edev->mutually_exclusive)
+                       edev->extcon_dev_type.groups[index] =
+                               &edev->attr_g_muex;
+
+               edev->dev.type = &edev->extcon_dev_type;
+       }
+
+       ret = device_register(&edev->dev);
+       if (ret) {
+               put_device(&edev->dev);
+               goto err_dev;
+       }
+#if defined(CONFIG_ANDROID)
+       if (switch_class)
+               ret = class_compat_create_link(switch_class, &edev->dev, NULL);
+#endif /* CONFIG_ANDROID */
+
+       spin_lock_init(&edev->lock);
+
+       RAW_INIT_NOTIFIER_HEAD(&edev->nh);
+
+       dev_set_drvdata(&edev->dev, edev);
+       edev->state = 0;
+
+       mutex_lock(&extcon_dev_list_lock);
+       list_add(&edev->entry, &extcon_dev_list);
+       mutex_unlock(&extcon_dev_list_lock);
+
+       return 0;
+
+err_dev:
+       if (edev->max_supported)
+               kfree(edev->extcon_dev_type.groups);
+err_alloc_groups:
+       if (edev->max_supported && edev->mutually_exclusive) {
+               for (index = 0; edev->mutually_exclusive[index]; index++)
+                       kfree(edev->d_attrs_muex[index].attr.name);
+               kfree(edev->d_attrs_muex);
+               kfree(edev->attrs_muex);
+       }
+err_muex:
+       for (index = 0; index < edev->max_supported; index++)
+               kfree(edev->cables[index].attr_g.name);
+err_alloc_cables:
+       if (edev->max_supported)
+               kfree(edev->cables);
+err_sysfs_alloc:
+       return ret;
+}
+EXPORT_SYMBOL_GPL(extcon_dev_register);
+
+/**
+ * extcon_dev_unregister() - Unregister the extcon device.
+ * @edev:      the extcon device instance to be unregistered.
+ *
+ * Note that this does not call kfree(edev) because edev was not allocated
+ * by this class.
+ */
+void extcon_dev_unregister(struct extcon_dev *edev)
+{
+       int index;
+
+       mutex_lock(&extcon_dev_list_lock);
+       list_del(&edev->entry);
+       mutex_unlock(&extcon_dev_list_lock);
+
+       if (IS_ERR_OR_NULL(get_device(&edev->dev))) {
+               dev_err(&edev->dev, "Failed to unregister extcon_dev (%s)\n",
+                               dev_name(&edev->dev));
+               return;
+       }
+
+       device_unregister(&edev->dev);
+
+       if (edev->mutually_exclusive && edev->max_supported) {
+               for (index = 0; edev->mutually_exclusive[index];
+                               index++)
+                       kfree(edev->d_attrs_muex[index].attr.name);
+               kfree(edev->d_attrs_muex);
+               kfree(edev->attrs_muex);
+       }
+
+       for (index = 0; index < edev->max_supported; index++)
+               kfree(edev->cables[index].attr_g.name);
+
+       if (edev->max_supported) {
+               kfree(edev->extcon_dev_type.groups);
+               kfree(edev->cables);
+       }
+
+#if defined(CONFIG_ANDROID)
+       if (switch_class)
+               class_compat_remove_link(switch_class, &edev->dev, NULL);
+#endif
+       put_device(&edev->dev);
+}
+EXPORT_SYMBOL_GPL(extcon_dev_unregister);
+
+static void devm_extcon_dev_unreg(struct device *dev, void *res)
+{
+       extcon_dev_unregister(*(struct extcon_dev **)res);
+}
+
+/**
+ * devm_extcon_dev_register() - Resource-managed extcon_dev_register()
+ * @dev:       device to allocate extcon device
+ * @edev:      the new extcon device to register
+ *
+ * Managed extcon_dev_register() function. If extcon device is attached with
+ * this function, that extcon device is automatically unregistered on driver
+ * detach. Internally this function calls extcon_dev_register() function.
+ * To get more information, refer that function.
+ *
+ * If extcon device is registered with this function and the device needs to be
+ * unregistered separately, devm_extcon_dev_unregister() should be used.
+ *
+ * Returns 0 if success or negaive error number if failure.
+ */
+int devm_extcon_dev_register(struct device *dev, struct extcon_dev *edev)
+{
+       struct extcon_dev **ptr;
+       int ret;
+
+       ptr = devres_alloc(devm_extcon_dev_unreg, sizeof(*ptr), GFP_KERNEL);
+       if (!ptr)
+               return -ENOMEM;
+
+       ret = extcon_dev_register(edev);
+       if (ret) {
+               devres_free(ptr);
+               return ret;
+       }
+
+       *ptr = edev;
+       devres_add(dev, ptr);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(devm_extcon_dev_register);
+
+/**
+ * devm_extcon_dev_unregister() - Resource-managed extcon_dev_unregister()
+ * @dev:       device the extcon belongs to
+ * @edev:      the extcon device to unregister
+ *
+ * Unregister extcon device that is registered with devm_extcon_dev_register()
+ * function.
+ */
+void devm_extcon_dev_unregister(struct device *dev, struct extcon_dev *edev)
+{
+       WARN_ON(devres_release(dev, devm_extcon_dev_unreg,
+                              devm_extcon_dev_match, edev));
+}
+EXPORT_SYMBOL_GPL(devm_extcon_dev_unregister);
+
+#ifdef CONFIG_OF
+/*
+ * extcon_get_edev_by_phandle - Get the extcon device from devicetree
+ * @dev - instance to the given device
+ * @index - index into list of extcon_dev
+ *
+ * return the instance of extcon device
+ */
+struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index)
+{
+       struct device_node *node;
+       struct extcon_dev *edev;
+
+       if (!dev->of_node) {
+               dev_err(dev, "device does not have a device node entry\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       node = of_parse_phandle(dev->of_node, "extcon", index);
+       if (!node) {
+               dev_err(dev, "failed to get phandle in %s node\n",
+                       dev->of_node->full_name);
+               return ERR_PTR(-ENODEV);
+       }
+
+       mutex_lock(&extcon_dev_list_lock);
+       list_for_each_entry(edev, &extcon_dev_list, entry) {
+               if (edev->dev.parent && edev->dev.parent->of_node == node) {
+                       mutex_unlock(&extcon_dev_list_lock);
+                       return edev;
+               }
+       }
+       mutex_unlock(&extcon_dev_list_lock);
+
+       return ERR_PTR(-EPROBE_DEFER);
+}
+#else
+struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index)
+{
+       return ERR_PTR(-ENOSYS);
+}
+#endif /* CONFIG_OF */
+EXPORT_SYMBOL_GPL(extcon_get_edev_by_phandle);
+
+static int __init extcon_class_init(void)
+{
+       return create_extcon_class();
+}
+module_init(extcon_class_init);
+
+static void __exit extcon_class_exit(void)
+{
+#if defined(CONFIG_ANDROID)
+       class_compat_unregister(switch_class);
+#endif
+       class_destroy(extcon_class);
+}
+module_exit(extcon_class_exit);
+
+MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
+MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
+MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
+MODULE_DESCRIPTION("External connector (extcon) class driver");
+MODULE_LICENSE("GPL");
index 41983883cef47da740612a9966d39ec97094d593..6517132e5d8b5900baebcbc4620e10dbb4a876e0 100644 (file)
@@ -132,6 +132,10 @@ config ISCSI_IBFT
          detect iSCSI boot parameters dynamically during system boot, say Y.
          Otherwise, say N.
 
+config QCOM_SCM
+       bool
+       depends on ARM || ARM64
+
 source "drivers/firmware/google/Kconfig"
 source "drivers/firmware/efi/Kconfig"
 
index 5373dc5b60114f31af5cf66cdbb923bdc6b0f973..3fdd3912709af54950f84f7f2dacb1e9a5aee366 100644 (file)
@@ -11,6 +11,8 @@ obj-$(CONFIG_DMIID)           += dmi-id.o
 obj-$(CONFIG_ISCSI_IBFT_FIND)  += iscsi_ibft_find.o
 obj-$(CONFIG_ISCSI_IBFT)       += iscsi_ibft.o
 obj-$(CONFIG_FIRMWARE_MEMMAP)  += memmap.o
+obj-$(CONFIG_QCOM_SCM)         += qcom_scm.o
+CFLAGS_qcom_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
 
 obj-$(CONFIG_GOOGLE_FIRMWARE)  += google/
 obj-$(CONFIG_EFI)              += efi/
index 87b8e3b900d2195bc44ae471003db4ad610b7d77..5c55227a34c8fd8ba0b95a6babfb28e4726da8fe 100644 (file)
@@ -120,7 +120,8 @@ add_sysfs_runtime_map_entry(struct kobject *kobj, int nr)
        entry = kzalloc(sizeof(*entry), GFP_KERNEL);
        if (!entry) {
                kset_unregister(map_kset);
-               return entry;
+               map_kset = NULL;
+               return ERR_PTR(-ENOMEM);
        }
 
        memcpy(&entry->md, efi_runtime_map + nr * efi_memdesc_size,
@@ -132,6 +133,7 @@ add_sysfs_runtime_map_entry(struct kobject *kobj, int nr)
        if (ret) {
                kobject_put(&entry->kobj);
                kset_unregister(map_kset);
+               map_kset = NULL;
                return ERR_PTR(ret);
        }
 
@@ -195,8 +197,6 @@ out_add_entry:
                entry = *(map_entries + j);
                kobject_put(&entry->kobj);
        }
-       if (map_kset)
-               kset_unregister(map_kset);
 out:
        return ret;
 }
index a330492e06f9597e9d8abcf82561b248bee1753c..75273a2516039116da1d706d5f44565cadc2b41a 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/console.h>
 #include <linux/efi.h>
 #include <linux/serial.h>
-#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
 #include <asm/vga.h>
 #include "pcdp.h"
 
@@ -43,7 +43,7 @@ setup_serial_console(struct pcdp_uart *uart)
        }
 
        add_preferred_console("uart", 8250, &options[9]);
-       return setup_early_serial8250_console(options);
+       return setup_earlycon(options);
 #else
        return -ENODEV;
 #endif
diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
new file mode 100644 (file)
index 0000000..994b50f
--- /dev/null
@@ -0,0 +1,494 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ * Copyright (C) 2015 Linaro 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 and
+ * only 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/qcom_scm.h>
+
+#include <asm/outercache.h>
+#include <asm/cacheflush.h>
+
+
+#define QCOM_SCM_ENOMEM                -5
+#define QCOM_SCM_EOPNOTSUPP    -4
+#define QCOM_SCM_EINVAL_ADDR   -3
+#define QCOM_SCM_EINVAL_ARG    -2
+#define QCOM_SCM_ERROR         -1
+#define QCOM_SCM_INTERRUPTED   1
+
+#define QCOM_SCM_FLAG_COLDBOOT_CPU0    0x00
+#define QCOM_SCM_FLAG_COLDBOOT_CPU1    0x01
+#define QCOM_SCM_FLAG_COLDBOOT_CPU2    0x08
+#define QCOM_SCM_FLAG_COLDBOOT_CPU3    0x20
+
+#define QCOM_SCM_FLAG_WARMBOOT_CPU0    0x04
+#define QCOM_SCM_FLAG_WARMBOOT_CPU1    0x02
+#define QCOM_SCM_FLAG_WARMBOOT_CPU2    0x10
+#define QCOM_SCM_FLAG_WARMBOOT_CPU3    0x40
+
+struct qcom_scm_entry {
+       int flag;
+       void *entry;
+};
+
+static struct qcom_scm_entry qcom_scm_wb[] = {
+       { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU0 },
+       { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU1 },
+       { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU2 },
+       { .flag = QCOM_SCM_FLAG_WARMBOOT_CPU3 },
+};
+
+static DEFINE_MUTEX(qcom_scm_lock);
+
+/**
+ * struct qcom_scm_command - one SCM command buffer
+ * @len: total available memory for command and response
+ * @buf_offset: start of command buffer
+ * @resp_hdr_offset: start of response buffer
+ * @id: command to be executed
+ * @buf: buffer returned from qcom_scm_get_command_buffer()
+ *
+ * An SCM command is laid out in memory as follows:
+ *
+ *     ------------------- <--- struct qcom_scm_command
+ *     | command header  |
+ *     ------------------- <--- qcom_scm_get_command_buffer()
+ *     | command buffer  |
+ *     ------------------- <--- struct qcom_scm_response and
+ *     | response header |      qcom_scm_command_to_response()
+ *     ------------------- <--- qcom_scm_get_response_buffer()
+ *     | response buffer |
+ *     -------------------
+ *
+ * There can be arbitrary padding between the headers and buffers so
+ * you should always use the appropriate qcom_scm_get_*_buffer() routines
+ * to access the buffers in a safe manner.
+ */
+struct qcom_scm_command {
+       __le32 len;
+       __le32 buf_offset;
+       __le32 resp_hdr_offset;
+       __le32 id;
+       __le32 buf[0];
+};
+
+/**
+ * struct qcom_scm_response - one SCM response buffer
+ * @len: total available memory for response
+ * @buf_offset: start of response data relative to start of qcom_scm_response
+ * @is_complete: indicates if the command has finished processing
+ */
+struct qcom_scm_response {
+       __le32 len;
+       __le32 buf_offset;
+       __le32 is_complete;
+};
+
+/**
+ * alloc_qcom_scm_command() - Allocate an SCM command
+ * @cmd_size: size of the command buffer
+ * @resp_size: size of the response buffer
+ *
+ * Allocate an SCM command, including enough room for the command
+ * and response headers as well as the command and response buffers.
+ *
+ * Returns a valid &qcom_scm_command on success or %NULL if the allocation fails.
+ */
+static struct qcom_scm_command *alloc_qcom_scm_command(size_t cmd_size, size_t resp_size)
+{
+       struct qcom_scm_command *cmd;
+       size_t len = sizeof(*cmd) + sizeof(struct qcom_scm_response) + cmd_size +
+               resp_size;
+       u32 offset;
+
+       cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL);
+       if (cmd) {
+               cmd->len = cpu_to_le32(len);
+               offset = offsetof(struct qcom_scm_command, buf);
+               cmd->buf_offset = cpu_to_le32(offset);
+               cmd->resp_hdr_offset = cpu_to_le32(offset + cmd_size);
+       }
+       return cmd;
+}
+
+/**
+ * free_qcom_scm_command() - Free an SCM command
+ * @cmd: command to free
+ *
+ * Free an SCM command.
+ */
+static inline void free_qcom_scm_command(struct qcom_scm_command *cmd)
+{
+       kfree(cmd);
+}
+
+/**
+ * qcom_scm_command_to_response() - Get a pointer to a qcom_scm_response
+ * @cmd: command
+ *
+ * Returns a pointer to a response for a command.
+ */
+static inline struct qcom_scm_response *qcom_scm_command_to_response(
+               const struct qcom_scm_command *cmd)
+{
+       return (void *)cmd + le32_to_cpu(cmd->resp_hdr_offset);
+}
+
+/**
+ * qcom_scm_get_command_buffer() - Get a pointer to a command buffer
+ * @cmd: command
+ *
+ * Returns a pointer to the command buffer of a command.
+ */
+static inline void *qcom_scm_get_command_buffer(const struct qcom_scm_command *cmd)
+{
+       return (void *)cmd->buf;
+}
+
+/**
+ * qcom_scm_get_response_buffer() - Get a pointer to a response buffer
+ * @rsp: response
+ *
+ * Returns a pointer to a response buffer of a response.
+ */
+static inline void *qcom_scm_get_response_buffer(const struct qcom_scm_response *rsp)
+{
+       return (void *)rsp + le32_to_cpu(rsp->buf_offset);
+}
+
+static int qcom_scm_remap_error(int err)
+{
+       pr_err("qcom_scm_call failed with error code %d\n", err);
+       switch (err) {
+       case QCOM_SCM_ERROR:
+               return -EIO;
+       case QCOM_SCM_EINVAL_ADDR:
+       case QCOM_SCM_EINVAL_ARG:
+               return -EINVAL;
+       case QCOM_SCM_EOPNOTSUPP:
+               return -EOPNOTSUPP;
+       case QCOM_SCM_ENOMEM:
+               return -ENOMEM;
+       }
+       return -EINVAL;
+}
+
+static u32 smc(u32 cmd_addr)
+{
+       int context_id;
+       register u32 r0 asm("r0") = 1;
+       register u32 r1 asm("r1") = (u32)&context_id;
+       register u32 r2 asm("r2") = cmd_addr;
+       do {
+               asm volatile(
+                       __asmeq("%0", "r0")
+                       __asmeq("%1", "r0")
+                       __asmeq("%2", "r1")
+                       __asmeq("%3", "r2")
+#ifdef REQUIRES_SEC
+                       ".arch_extension sec\n"
+#endif
+                       "smc    #0      @ switch to secure world\n"
+                       : "=r" (r0)
+                       : "r" (r0), "r" (r1), "r" (r2)
+                       : "r3");
+       } while (r0 == QCOM_SCM_INTERRUPTED);
+
+       return r0;
+}
+
+static int __qcom_scm_call(const struct qcom_scm_command *cmd)
+{
+       int ret;
+       u32 cmd_addr = virt_to_phys(cmd);
+
+       /*
+        * Flush the command buffer so that the secure world sees
+        * the correct data.
+        */
+       __cpuc_flush_dcache_area((void *)cmd, cmd->len);
+       outer_flush_range(cmd_addr, cmd_addr + cmd->len);
+
+       ret = smc(cmd_addr);
+       if (ret < 0)
+               ret = qcom_scm_remap_error(ret);
+
+       return ret;
+}
+
+static void qcom_scm_inv_range(unsigned long start, unsigned long end)
+{
+       u32 cacheline_size, ctr;
+
+       asm volatile("mrc p15, 0, %0, c0, c0, 1" : "=r" (ctr));
+       cacheline_size = 4 << ((ctr >> 16) & 0xf);
+
+       start = round_down(start, cacheline_size);
+       end = round_up(end, cacheline_size);
+       outer_inv_range(start, end);
+       while (start < end) {
+               asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start)
+                    : "memory");
+               start += cacheline_size;
+       }
+       dsb();
+       isb();
+}
+
+/**
+ * qcom_scm_call() - Send an SCM command
+ * @svc_id: service identifier
+ * @cmd_id: command identifier
+ * @cmd_buf: command buffer
+ * @cmd_len: length of the command buffer
+ * @resp_buf: response buffer
+ * @resp_len: length of the response buffer
+ *
+ * Sends a command to the SCM and waits for the command to finish processing.
+ *
+ * A note on cache maintenance:
+ * Note that any buffers that are expected to be accessed by the secure world
+ * must be flushed before invoking qcom_scm_call and invalidated in the cache
+ * immediately after qcom_scm_call returns. Cache maintenance on the command
+ * and response buffers is taken care of by qcom_scm_call; however, callers are
+ * responsible for any other cached buffers passed over to the secure world.
+ */
+static int qcom_scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf,
+                       size_t cmd_len, void *resp_buf, size_t resp_len)
+{
+       int ret;
+       struct qcom_scm_command *cmd;
+       struct qcom_scm_response *rsp;
+       unsigned long start, end;
+
+       cmd = alloc_qcom_scm_command(cmd_len, resp_len);
+       if (!cmd)
+               return -ENOMEM;
+
+       cmd->id = cpu_to_le32((svc_id << 10) | cmd_id);
+       if (cmd_buf)
+               memcpy(qcom_scm_get_command_buffer(cmd), cmd_buf, cmd_len);
+
+       mutex_lock(&qcom_scm_lock);
+       ret = __qcom_scm_call(cmd);
+       mutex_unlock(&qcom_scm_lock);
+       if (ret)
+               goto out;
+
+       rsp = qcom_scm_command_to_response(cmd);
+       start = (unsigned long)rsp;
+
+       do {
+               qcom_scm_inv_range(start, start + sizeof(*rsp));
+       } while (!rsp->is_complete);
+
+       end = (unsigned long)qcom_scm_get_response_buffer(rsp) + resp_len;
+       qcom_scm_inv_range(start, end);
+
+       if (resp_buf)
+               memcpy(resp_buf, qcom_scm_get_response_buffer(rsp), resp_len);
+out:
+       free_qcom_scm_command(cmd);
+       return ret;
+}
+
+#define SCM_CLASS_REGISTER     (0x2 << 8)
+#define SCM_MASK_IRQS          BIT(5)
+#define SCM_ATOMIC(svc, cmd, n) (((((svc) << 10)|((cmd) & 0x3ff)) << 12) | \
+                               SCM_CLASS_REGISTER | \
+                               SCM_MASK_IRQS | \
+                               (n & 0xf))
+
+/**
+ * qcom_scm_call_atomic1() - Send an atomic SCM command with one argument
+ * @svc_id: service identifier
+ * @cmd_id: command identifier
+ * @arg1: first argument
+ *
+ * This shall only be used with commands that are guaranteed to be
+ * uninterruptable, atomic and SMP safe.
+ */
+static s32 qcom_scm_call_atomic1(u32 svc, u32 cmd, u32 arg1)
+{
+       int context_id;
+
+       register u32 r0 asm("r0") = SCM_ATOMIC(svc, cmd, 1);
+       register u32 r1 asm("r1") = (u32)&context_id;
+       register u32 r2 asm("r2") = arg1;
+
+       asm volatile(
+                       __asmeq("%0", "r0")
+                       __asmeq("%1", "r0")
+                       __asmeq("%2", "r1")
+                       __asmeq("%3", "r2")
+#ifdef REQUIRES_SEC
+                       ".arch_extension sec\n"
+#endif
+                       "smc    #0      @ switch to secure world\n"
+                       : "=r" (r0)
+                       : "r" (r0), "r" (r1), "r" (r2)
+                       : "r3");
+       return r0;
+}
+
+u32 qcom_scm_get_version(void)
+{
+       int context_id;
+       static u32 version = -1;
+       register u32 r0 asm("r0");
+       register u32 r1 asm("r1");
+
+       if (version != -1)
+               return version;
+
+       mutex_lock(&qcom_scm_lock);
+
+       r0 = 0x1 << 8;
+       r1 = (u32)&context_id;
+       do {
+               asm volatile(
+                       __asmeq("%0", "r0")
+                       __asmeq("%1", "r1")
+                       __asmeq("%2", "r0")
+                       __asmeq("%3", "r1")
+#ifdef REQUIRES_SEC
+                       ".arch_extension sec\n"
+#endif
+                       "smc    #0      @ switch to secure world\n"
+                       : "=r" (r0), "=r" (r1)
+                       : "r" (r0), "r" (r1)
+                       : "r2", "r3");
+       } while (r0 == QCOM_SCM_INTERRUPTED);
+
+       version = r1;
+       mutex_unlock(&qcom_scm_lock);
+
+       return version;
+}
+EXPORT_SYMBOL(qcom_scm_get_version);
+
+#define QCOM_SCM_SVC_BOOT                      0x1
+#define QCOM_SCM_BOOT_ADDR                     0x1
+/*
+ * Set the cold/warm boot address for one of the CPU cores.
+ */
+static int qcom_scm_set_boot_addr(u32 addr, int flags)
+{
+       struct {
+               __le32 flags;
+               __le32 addr;
+       } cmd;
+
+       cmd.addr = cpu_to_le32(addr);
+       cmd.flags = cpu_to_le32(flags);
+       return qcom_scm_call(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR,
+                       &cmd, sizeof(cmd), NULL, 0);
+}
+
+/**
+ * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus
+ * @entry: Entry point function for the cpus
+ * @cpus: The cpumask of cpus that will use the entry point
+ *
+ * Set the cold boot address of the cpus. Any cpu outside the supported
+ * range would be removed from the cpu present mask.
+ */
+int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
+{
+       int flags = 0;
+       int cpu;
+       int scm_cb_flags[] = {
+               QCOM_SCM_FLAG_COLDBOOT_CPU0,
+               QCOM_SCM_FLAG_COLDBOOT_CPU1,
+               QCOM_SCM_FLAG_COLDBOOT_CPU2,
+               QCOM_SCM_FLAG_COLDBOOT_CPU3,
+       };
+
+       if (!cpus || (cpus && cpumask_empty(cpus)))
+               return -EINVAL;
+
+       for_each_cpu(cpu, cpus) {
+               if (cpu < ARRAY_SIZE(scm_cb_flags))
+                       flags |= scm_cb_flags[cpu];
+               else
+                       set_cpu_present(cpu, false);
+       }
+
+       return qcom_scm_set_boot_addr(virt_to_phys(entry), flags);
+}
+EXPORT_SYMBOL(qcom_scm_set_cold_boot_addr);
+
+/**
+ * qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus
+ * @entry: Entry point function for the cpus
+ * @cpus: The cpumask of cpus that will use the entry point
+ *
+ * Set the Linux entry point for the SCM to transfer control to when coming
+ * out of a power down. CPU power down may be executed on cpuidle or hotplug.
+ */
+int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
+{
+       int ret;
+       int flags = 0;
+       int cpu;
+
+       /*
+        * Reassign only if we are switching from hotplug entry point
+        * to cpuidle entry point or vice versa.
+        */
+       for_each_cpu(cpu, cpus) {
+               if (entry == qcom_scm_wb[cpu].entry)
+                       continue;
+               flags |= qcom_scm_wb[cpu].flag;
+       }
+
+       /* No change in entry function */
+       if (!flags)
+               return 0;
+
+       ret = qcom_scm_set_boot_addr(virt_to_phys(entry), flags);
+       if (!ret) {
+               for_each_cpu(cpu, cpus)
+                       qcom_scm_wb[cpu].entry = entry;
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr);
+
+#define QCOM_SCM_CMD_TERMINATE_PC      0x2
+#define QCOM_SCM_FLUSH_FLAG_MASK       0x3
+
+/**
+ * qcom_scm_cpu_power_down() - Power down the cpu
+ * @flags - Flags to flush cache
+ *
+ * This is an end point to power down cpu. If there was a pending interrupt,
+ * the control would return from this function, otherwise, the cpu jumps to the
+ * warm boot entry point set for this cpu upon reset.
+ */
+void qcom_scm_cpu_power_down(u32 flags)
+{
+       qcom_scm_call_atomic1(QCOM_SCM_SVC_BOOT, QCOM_SCM_CMD_TERMINATE_PC,
+                       flags & QCOM_SCM_FLUSH_FLAG_MASK);
+}
+EXPORT_SYMBOL(qcom_scm_cpu_power_down);
index 38d875d0e4c866cd22f541ab1e3d74ec60699c7b..caefe806db5e6dfaff04a22b2efb0cf27111e33c 100644 (file)
@@ -272,14 +272,6 @@ config GPIO_MPC8XXX
          Say Y here if you're going to use hardware that connects to the
          MPC512x/831x/834x/837x/8572/8610 GPIOs.
 
-config GPIO_MSM_V1
-       tristate "Qualcomm MSM GPIO v1"
-       depends on GPIOLIB && ARCH_MSM && (ARCH_MSM7X00A || ARCH_MSM7X30 || ARCH_QSD8X50)
-       help
-         Say yes here to support the GPIO interface on ARM v6 based
-         Qualcomm MSM chips.  Most of the pins on the MSM can be
-         selected for GPIO, and are controlled by this driver.
-
 config GPIO_MSM_V2
        tristate "Qualcomm MSM GPIO v2"
        depends on GPIOLIB && OF && ARCH_QCOM
index 07b816b9b630dbbb8d46b6442eab3d4614918182..f71bb971329c9efe96f2bc58c2ab63f2d1673d69 100644 (file)
@@ -60,7 +60,6 @@ obj-$(CONFIG_GPIO_MOXART)     += gpio-moxart.o
 obj-$(CONFIG_GPIO_MPC5200)     += gpio-mpc5200.o
 obj-$(CONFIG_GPIO_MPC8XXX)     += gpio-mpc8xxx.o
 obj-$(CONFIG_GPIO_MSIC)                += gpio-msic.o
-obj-$(CONFIG_GPIO_MSM_V1)      += gpio-msm-v1.o
 obj-$(CONFIG_GPIO_MSM_V2)      += gpio-msm-v2.o
 obj-$(CONFIG_GPIO_MVEBU)        += gpio-mvebu.o
 obj-$(CONFIG_GPIO_MXC)         += gpio-mxc.o
diff --git a/drivers/gpio/gpio-msm-v1.c b/drivers/gpio/gpio-msm-v1.c
deleted file mode 100644 (file)
index edf285e..0000000
+++ /dev/null
@@ -1,714 +0,0 @@
-/*
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/bitops.h>
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
-
-#include <mach/msm_gpiomux.h>
-
-/* see 80-VA736-2 Rev C pp 695-751
-**
-** These are actually the *shadow* gpio registers, since the
-** real ones (which allow full access) are only available to the
-** ARM9 side of the world.
-**
-** Since the _BASE need to be page-aligned when we're mapping them
-** to virtual addresses, adjust for the additional offset in these
-** macros.
-*/
-
-#define MSM_GPIO1_REG(off) (off)
-#define MSM_GPIO2_REG(off) (off)
-#define MSM_GPIO1_SHADOW_REG(off) (off)
-#define MSM_GPIO2_SHADOW_REG(off) (off)
-
-/*
- * MSM7X00 registers
- */
-/* output value */
-#define MSM7X00_GPIO_OUT_0     MSM_GPIO1_SHADOW_REG(0x00)  /* gpio  15-0  */
-#define MSM7X00_GPIO_OUT_1     MSM_GPIO2_SHADOW_REG(0x00)  /* gpio  42-16 */
-#define MSM7X00_GPIO_OUT_2     MSM_GPIO1_SHADOW_REG(0x04)  /* gpio  67-43 */
-#define MSM7X00_GPIO_OUT_3     MSM_GPIO1_SHADOW_REG(0x08)  /* gpio  94-68 */
-#define MSM7X00_GPIO_OUT_4     MSM_GPIO1_SHADOW_REG(0x0C)  /* gpio 106-95 */
-#define MSM7X00_GPIO_OUT_5     MSM_GPIO1_SHADOW_REG(0x50)  /* gpio 107-121 */
-
-/* same pin map as above, output enable */
-#define MSM7X00_GPIO_OE_0      MSM_GPIO1_SHADOW_REG(0x10)
-#define MSM7X00_GPIO_OE_1      MSM_GPIO2_SHADOW_REG(0x08)
-#define MSM7X00_GPIO_OE_2      MSM_GPIO1_SHADOW_REG(0x14)
-#define MSM7X00_GPIO_OE_3      MSM_GPIO1_SHADOW_REG(0x18)
-#define MSM7X00_GPIO_OE_4      MSM_GPIO1_SHADOW_REG(0x1C)
-#define MSM7X00_GPIO_OE_5      MSM_GPIO1_SHADOW_REG(0x54)
-
-/* same pin map as above, input read */
-#define MSM7X00_GPIO_IN_0      MSM_GPIO1_SHADOW_REG(0x34)
-#define MSM7X00_GPIO_IN_1      MSM_GPIO2_SHADOW_REG(0x20)
-#define MSM7X00_GPIO_IN_2      MSM_GPIO1_SHADOW_REG(0x38)
-#define MSM7X00_GPIO_IN_3      MSM_GPIO1_SHADOW_REG(0x3C)
-#define MSM7X00_GPIO_IN_4      MSM_GPIO1_SHADOW_REG(0x40)
-#define MSM7X00_GPIO_IN_5      MSM_GPIO1_SHADOW_REG(0x44)
-
-/* same pin map as above, 1=edge 0=level interrup */
-#define MSM7X00_GPIO_INT_EDGE_0        MSM_GPIO1_SHADOW_REG(0x60)
-#define MSM7X00_GPIO_INT_EDGE_1        MSM_GPIO2_SHADOW_REG(0x50)
-#define MSM7X00_GPIO_INT_EDGE_2        MSM_GPIO1_SHADOW_REG(0x64)
-#define MSM7X00_GPIO_INT_EDGE_3        MSM_GPIO1_SHADOW_REG(0x68)
-#define MSM7X00_GPIO_INT_EDGE_4        MSM_GPIO1_SHADOW_REG(0x6C)
-#define MSM7X00_GPIO_INT_EDGE_5        MSM_GPIO1_SHADOW_REG(0xC0)
-
-/* same pin map as above, 1=positive 0=negative */
-#define MSM7X00_GPIO_INT_POS_0 MSM_GPIO1_SHADOW_REG(0x70)
-#define MSM7X00_GPIO_INT_POS_1 MSM_GPIO2_SHADOW_REG(0x58)
-#define MSM7X00_GPIO_INT_POS_2 MSM_GPIO1_SHADOW_REG(0x74)
-#define MSM7X00_GPIO_INT_POS_3 MSM_GPIO1_SHADOW_REG(0x78)
-#define MSM7X00_GPIO_INT_POS_4 MSM_GPIO1_SHADOW_REG(0x7C)
-#define MSM7X00_GPIO_INT_POS_5 MSM_GPIO1_SHADOW_REG(0xBC)
-
-/* same pin map as above, interrupt enable */
-#define MSM7X00_GPIO_INT_EN_0  MSM_GPIO1_SHADOW_REG(0x80)
-#define MSM7X00_GPIO_INT_EN_1  MSM_GPIO2_SHADOW_REG(0x60)
-#define MSM7X00_GPIO_INT_EN_2  MSM_GPIO1_SHADOW_REG(0x84)
-#define MSM7X00_GPIO_INT_EN_3  MSM_GPIO1_SHADOW_REG(0x88)
-#define MSM7X00_GPIO_INT_EN_4  MSM_GPIO1_SHADOW_REG(0x8C)
-#define MSM7X00_GPIO_INT_EN_5  MSM_GPIO1_SHADOW_REG(0xB8)
-
-/* same pin map as above, write 1 to clear interrupt */
-#define MSM7X00_GPIO_INT_CLEAR_0       MSM_GPIO1_SHADOW_REG(0x90)
-#define MSM7X00_GPIO_INT_CLEAR_1       MSM_GPIO2_SHADOW_REG(0x68)
-#define MSM7X00_GPIO_INT_CLEAR_2       MSM_GPIO1_SHADOW_REG(0x94)
-#define MSM7X00_GPIO_INT_CLEAR_3       MSM_GPIO1_SHADOW_REG(0x98)
-#define MSM7X00_GPIO_INT_CLEAR_4       MSM_GPIO1_SHADOW_REG(0x9C)
-#define MSM7X00_GPIO_INT_CLEAR_5       MSM_GPIO1_SHADOW_REG(0xB4)
-
-/* same pin map as above, 1=interrupt pending */
-#define MSM7X00_GPIO_INT_STATUS_0      MSM_GPIO1_SHADOW_REG(0xA0)
-#define MSM7X00_GPIO_INT_STATUS_1      MSM_GPIO2_SHADOW_REG(0x70)
-#define MSM7X00_GPIO_INT_STATUS_2      MSM_GPIO1_SHADOW_REG(0xA4)
-#define MSM7X00_GPIO_INT_STATUS_3      MSM_GPIO1_SHADOW_REG(0xA8)
-#define MSM7X00_GPIO_INT_STATUS_4      MSM_GPIO1_SHADOW_REG(0xAC)
-#define MSM7X00_GPIO_INT_STATUS_5      MSM_GPIO1_SHADOW_REG(0xB0)
-
-/*
- * QSD8X50 registers
- */
-/* output value */
-#define QSD8X50_GPIO_OUT_0     MSM_GPIO1_SHADOW_REG(0x00)  /* gpio  15-0   */
-#define QSD8X50_GPIO_OUT_1     MSM_GPIO2_SHADOW_REG(0x00)  /* gpio  42-16  */
-#define QSD8X50_GPIO_OUT_2     MSM_GPIO1_SHADOW_REG(0x04)  /* gpio  67-43  */
-#define QSD8X50_GPIO_OUT_3     MSM_GPIO1_SHADOW_REG(0x08)  /* gpio  94-68  */
-#define QSD8X50_GPIO_OUT_4     MSM_GPIO1_SHADOW_REG(0x0C)  /* gpio 103-95  */
-#define QSD8X50_GPIO_OUT_5     MSM_GPIO1_SHADOW_REG(0x10)  /* gpio 121-104 */
-#define QSD8X50_GPIO_OUT_6     MSM_GPIO1_SHADOW_REG(0x14)  /* gpio 152-122 */
-#define QSD8X50_GPIO_OUT_7     MSM_GPIO1_SHADOW_REG(0x18)  /* gpio 164-153 */
-
-/* same pin map as above, output enable */
-#define QSD8X50_GPIO_OE_0      MSM_GPIO1_SHADOW_REG(0x20)
-#define QSD8X50_GPIO_OE_1      MSM_GPIO2_SHADOW_REG(0x08)
-#define QSD8X50_GPIO_OE_2      MSM_GPIO1_SHADOW_REG(0x24)
-#define QSD8X50_GPIO_OE_3      MSM_GPIO1_SHADOW_REG(0x28)
-#define QSD8X50_GPIO_OE_4      MSM_GPIO1_SHADOW_REG(0x2C)
-#define QSD8X50_GPIO_OE_5      MSM_GPIO1_SHADOW_REG(0x30)
-#define QSD8X50_GPIO_OE_6      MSM_GPIO1_SHADOW_REG(0x34)
-#define QSD8X50_GPIO_OE_7      MSM_GPIO1_SHADOW_REG(0x38)
-
-/* same pin map as above, input read */
-#define QSD8X50_GPIO_IN_0      MSM_GPIO1_SHADOW_REG(0x50)
-#define QSD8X50_GPIO_IN_1      MSM_GPIO2_SHADOW_REG(0x20)
-#define QSD8X50_GPIO_IN_2      MSM_GPIO1_SHADOW_REG(0x54)
-#define QSD8X50_GPIO_IN_3      MSM_GPIO1_SHADOW_REG(0x58)
-#define QSD8X50_GPIO_IN_4      MSM_GPIO1_SHADOW_REG(0x5C)
-#define QSD8X50_GPIO_IN_5      MSM_GPIO1_SHADOW_REG(0x60)
-#define QSD8X50_GPIO_IN_6      MSM_GPIO1_SHADOW_REG(0x64)
-#define QSD8X50_GPIO_IN_7      MSM_GPIO1_SHADOW_REG(0x68)
-
-/* same pin map as above, 1=edge 0=level interrup */
-#define QSD8X50_GPIO_INT_EDGE_0        MSM_GPIO1_SHADOW_REG(0x70)
-#define QSD8X50_GPIO_INT_EDGE_1        MSM_GPIO2_SHADOW_REG(0x50)
-#define QSD8X50_GPIO_INT_EDGE_2        MSM_GPIO1_SHADOW_REG(0x74)
-#define QSD8X50_GPIO_INT_EDGE_3        MSM_GPIO1_SHADOW_REG(0x78)
-#define QSD8X50_GPIO_INT_EDGE_4        MSM_GPIO1_SHADOW_REG(0x7C)
-#define QSD8X50_GPIO_INT_EDGE_5        MSM_GPIO1_SHADOW_REG(0x80)
-#define QSD8X50_GPIO_INT_EDGE_6        MSM_GPIO1_SHADOW_REG(0x84)
-#define QSD8X50_GPIO_INT_EDGE_7        MSM_GPIO1_SHADOW_REG(0x88)
-
-/* same pin map as above, 1=positive 0=negative */
-#define QSD8X50_GPIO_INT_POS_0 MSM_GPIO1_SHADOW_REG(0x90)
-#define QSD8X50_GPIO_INT_POS_1 MSM_GPIO2_SHADOW_REG(0x58)
-#define QSD8X50_GPIO_INT_POS_2 MSM_GPIO1_SHADOW_REG(0x94)
-#define QSD8X50_GPIO_INT_POS_3 MSM_GPIO1_SHADOW_REG(0x98)
-#define QSD8X50_GPIO_INT_POS_4 MSM_GPIO1_SHADOW_REG(0x9C)
-#define QSD8X50_GPIO_INT_POS_5 MSM_GPIO1_SHADOW_REG(0xA0)
-#define QSD8X50_GPIO_INT_POS_6 MSM_GPIO1_SHADOW_REG(0xA4)
-#define QSD8X50_GPIO_INT_POS_7 MSM_GPIO1_SHADOW_REG(0xA8)
-
-/* same pin map as above, interrupt enable */
-#define QSD8X50_GPIO_INT_EN_0  MSM_GPIO1_SHADOW_REG(0xB0)
-#define QSD8X50_GPIO_INT_EN_1  MSM_GPIO2_SHADOW_REG(0x60)
-#define QSD8X50_GPIO_INT_EN_2  MSM_GPIO1_SHADOW_REG(0xB4)
-#define QSD8X50_GPIO_INT_EN_3  MSM_GPIO1_SHADOW_REG(0xB8)
-#define QSD8X50_GPIO_INT_EN_4  MSM_GPIO1_SHADOW_REG(0xBC)
-#define QSD8X50_GPIO_INT_EN_5  MSM_GPIO1_SHADOW_REG(0xC0)
-#define QSD8X50_GPIO_INT_EN_6  MSM_GPIO1_SHADOW_REG(0xC4)
-#define QSD8X50_GPIO_INT_EN_7  MSM_GPIO1_SHADOW_REG(0xC8)
-
-/* same pin map as above, write 1 to clear interrupt */
-#define QSD8X50_GPIO_INT_CLEAR_0       MSM_GPIO1_SHADOW_REG(0xD0)
-#define QSD8X50_GPIO_INT_CLEAR_1       MSM_GPIO2_SHADOW_REG(0x68)
-#define QSD8X50_GPIO_INT_CLEAR_2       MSM_GPIO1_SHADOW_REG(0xD4)
-#define QSD8X50_GPIO_INT_CLEAR_3       MSM_GPIO1_SHADOW_REG(0xD8)
-#define QSD8X50_GPIO_INT_CLEAR_4       MSM_GPIO1_SHADOW_REG(0xDC)
-#define QSD8X50_GPIO_INT_CLEAR_5       MSM_GPIO1_SHADOW_REG(0xE0)
-#define QSD8X50_GPIO_INT_CLEAR_6       MSM_GPIO1_SHADOW_REG(0xE4)
-#define QSD8X50_GPIO_INT_CLEAR_7       MSM_GPIO1_SHADOW_REG(0xE8)
-
-/* same pin map as above, 1=interrupt pending */
-#define QSD8X50_GPIO_INT_STATUS_0      MSM_GPIO1_SHADOW_REG(0xF0)
-#define QSD8X50_GPIO_INT_STATUS_1      MSM_GPIO2_SHADOW_REG(0x70)
-#define QSD8X50_GPIO_INT_STATUS_2      MSM_GPIO1_SHADOW_REG(0xF4)
-#define QSD8X50_GPIO_INT_STATUS_3      MSM_GPIO1_SHADOW_REG(0xF8)
-#define QSD8X50_GPIO_INT_STATUS_4      MSM_GPIO1_SHADOW_REG(0xFC)
-#define QSD8X50_GPIO_INT_STATUS_5      MSM_GPIO1_SHADOW_REG(0x100)
-#define QSD8X50_GPIO_INT_STATUS_6      MSM_GPIO1_SHADOW_REG(0x104)
-#define QSD8X50_GPIO_INT_STATUS_7      MSM_GPIO1_SHADOW_REG(0x108)
-
-/*
- * MSM7X30 registers
- */
-/* output value */
-#define MSM7X30_GPIO_OUT_0     MSM_GPIO1_REG(0x00)   /* gpio  15-0   */
-#define MSM7X30_GPIO_OUT_1     MSM_GPIO2_REG(0x00)   /* gpio  43-16  */
-#define MSM7X30_GPIO_OUT_2     MSM_GPIO1_REG(0x04)   /* gpio  67-44  */
-#define MSM7X30_GPIO_OUT_3     MSM_GPIO1_REG(0x08)   /* gpio  94-68  */
-#define MSM7X30_GPIO_OUT_4     MSM_GPIO1_REG(0x0C)   /* gpio 106-95  */
-#define MSM7X30_GPIO_OUT_5     MSM_GPIO1_REG(0x50)   /* gpio 133-107 */
-#define MSM7X30_GPIO_OUT_6     MSM_GPIO1_REG(0xC4)   /* gpio 150-134 */
-#define MSM7X30_GPIO_OUT_7     MSM_GPIO1_REG(0x214)  /* gpio 181-151 */
-
-/* same pin map as above, output enable */
-#define MSM7X30_GPIO_OE_0      MSM_GPIO1_REG(0x10)
-#define MSM7X30_GPIO_OE_1      MSM_GPIO2_REG(0x08)
-#define MSM7X30_GPIO_OE_2      MSM_GPIO1_REG(0x14)
-#define MSM7X30_GPIO_OE_3      MSM_GPIO1_REG(0x18)
-#define MSM7X30_GPIO_OE_4      MSM_GPIO1_REG(0x1C)
-#define MSM7X30_GPIO_OE_5      MSM_GPIO1_REG(0x54)
-#define MSM7X30_GPIO_OE_6      MSM_GPIO1_REG(0xC8)
-#define MSM7X30_GPIO_OE_7      MSM_GPIO1_REG(0x218)
-
-/* same pin map as above, input read */
-#define MSM7X30_GPIO_IN_0      MSM_GPIO1_REG(0x34)
-#define MSM7X30_GPIO_IN_1      MSM_GPIO2_REG(0x20)
-#define MSM7X30_GPIO_IN_2      MSM_GPIO1_REG(0x38)
-#define MSM7X30_GPIO_IN_3      MSM_GPIO1_REG(0x3C)
-#define MSM7X30_GPIO_IN_4      MSM_GPIO1_REG(0x40)
-#define MSM7X30_GPIO_IN_5      MSM_GPIO1_REG(0x44)
-#define MSM7X30_GPIO_IN_6      MSM_GPIO1_REG(0xCC)
-#define MSM7X30_GPIO_IN_7      MSM_GPIO1_REG(0x21C)
-
-/* same pin map as above, 1=edge 0=level interrup */
-#define MSM7X30_GPIO_INT_EDGE_0        MSM_GPIO1_REG(0x60)
-#define MSM7X30_GPIO_INT_EDGE_1        MSM_GPIO2_REG(0x50)
-#define MSM7X30_GPIO_INT_EDGE_2        MSM_GPIO1_REG(0x64)
-#define MSM7X30_GPIO_INT_EDGE_3        MSM_GPIO1_REG(0x68)
-#define MSM7X30_GPIO_INT_EDGE_4        MSM_GPIO1_REG(0x6C)
-#define MSM7X30_GPIO_INT_EDGE_5        MSM_GPIO1_REG(0xC0)
-#define MSM7X30_GPIO_INT_EDGE_6        MSM_GPIO1_REG(0xD0)
-#define MSM7X30_GPIO_INT_EDGE_7        MSM_GPIO1_REG(0x240)
-
-/* same pin map as above, 1=positive 0=negative */
-#define MSM7X30_GPIO_INT_POS_0 MSM_GPIO1_REG(0x70)
-#define MSM7X30_GPIO_INT_POS_1 MSM_GPIO2_REG(0x58)
-#define MSM7X30_GPIO_INT_POS_2 MSM_GPIO1_REG(0x74)
-#define MSM7X30_GPIO_INT_POS_3 MSM_GPIO1_REG(0x78)
-#define MSM7X30_GPIO_INT_POS_4 MSM_GPIO1_REG(0x7C)
-#define MSM7X30_GPIO_INT_POS_5 MSM_GPIO1_REG(0xBC)
-#define MSM7X30_GPIO_INT_POS_6 MSM_GPIO1_REG(0xD4)
-#define MSM7X30_GPIO_INT_POS_7 MSM_GPIO1_REG(0x228)
-
-/* same pin map as above, interrupt enable */
-#define MSM7X30_GPIO_INT_EN_0  MSM_GPIO1_REG(0x80)
-#define MSM7X30_GPIO_INT_EN_1  MSM_GPIO2_REG(0x60)
-#define MSM7X30_GPIO_INT_EN_2  MSM_GPIO1_REG(0x84)
-#define MSM7X30_GPIO_INT_EN_3  MSM_GPIO1_REG(0x88)
-#define MSM7X30_GPIO_INT_EN_4  MSM_GPIO1_REG(0x8C)
-#define MSM7X30_GPIO_INT_EN_5  MSM_GPIO1_REG(0xB8)
-#define MSM7X30_GPIO_INT_EN_6  MSM_GPIO1_REG(0xD8)
-#define MSM7X30_GPIO_INT_EN_7  MSM_GPIO1_REG(0x22C)
-
-/* same pin map as above, write 1 to clear interrupt */
-#define MSM7X30_GPIO_INT_CLEAR_0       MSM_GPIO1_REG(0x90)
-#define MSM7X30_GPIO_INT_CLEAR_1       MSM_GPIO2_REG(0x68)
-#define MSM7X30_GPIO_INT_CLEAR_2       MSM_GPIO1_REG(0x94)
-#define MSM7X30_GPIO_INT_CLEAR_3       MSM_GPIO1_REG(0x98)
-#define MSM7X30_GPIO_INT_CLEAR_4       MSM_GPIO1_REG(0x9C)
-#define MSM7X30_GPIO_INT_CLEAR_5       MSM_GPIO1_REG(0xB4)
-#define MSM7X30_GPIO_INT_CLEAR_6       MSM_GPIO1_REG(0xDC)
-#define MSM7X30_GPIO_INT_CLEAR_7       MSM_GPIO1_REG(0x230)
-
-/* same pin map as above, 1=interrupt pending */
-#define MSM7X30_GPIO_INT_STATUS_0      MSM_GPIO1_REG(0xA0)
-#define MSM7X30_GPIO_INT_STATUS_1      MSM_GPIO2_REG(0x70)
-#define MSM7X30_GPIO_INT_STATUS_2      MSM_GPIO1_REG(0xA4)
-#define MSM7X30_GPIO_INT_STATUS_3      MSM_GPIO1_REG(0xA8)
-#define MSM7X30_GPIO_INT_STATUS_4      MSM_GPIO1_REG(0xAC)
-#define MSM7X30_GPIO_INT_STATUS_5      MSM_GPIO1_REG(0xB0)
-#define MSM7X30_GPIO_INT_STATUS_6      MSM_GPIO1_REG(0xE0)
-#define MSM7X30_GPIO_INT_STATUS_7      MSM_GPIO1_REG(0x234)
-
-#define FIRST_GPIO_IRQ MSM_GPIO_TO_INT(0)
-
-#define MSM_GPIO_BANK(soc, bank, first, last)                          \
-       {                                                               \
-               .regs[MSM_GPIO_OUT] =         soc##_GPIO_OUT_##bank,    \
-               .regs[MSM_GPIO_IN] =          soc##_GPIO_IN_##bank,     \
-               .regs[MSM_GPIO_INT_STATUS] =  soc##_GPIO_INT_STATUS_##bank, \
-               .regs[MSM_GPIO_INT_CLEAR] =   soc##_GPIO_INT_CLEAR_##bank, \
-               .regs[MSM_GPIO_INT_EN] =      soc##_GPIO_INT_EN_##bank, \
-               .regs[MSM_GPIO_INT_EDGE] =    soc##_GPIO_INT_EDGE_##bank, \
-               .regs[MSM_GPIO_INT_POS] =     soc##_GPIO_INT_POS_##bank, \
-               .regs[MSM_GPIO_OE] =          soc##_GPIO_OE_##bank,     \
-               .chip = {                                               \
-                       .base = (first),                                \
-                       .ngpio = (last) - (first) + 1,                  \
-                       .get = msm_gpio_get,                            \
-                       .set = msm_gpio_set,                            \
-                       .direction_input = msm_gpio_direction_input,    \
-                       .direction_output = msm_gpio_direction_output,  \
-                       .to_irq = msm_gpio_to_irq,                      \
-                       .request = msm_gpio_request,                    \
-                       .free = msm_gpio_free,                          \
-               }                                                       \
-       }
-
-#define MSM_GPIO_BROKEN_INT_CLEAR 1
-
-enum msm_gpio_reg {
-       MSM_GPIO_IN,
-       MSM_GPIO_OUT,
-       MSM_GPIO_INT_STATUS,
-       MSM_GPIO_INT_CLEAR,
-       MSM_GPIO_INT_EN,
-       MSM_GPIO_INT_EDGE,
-       MSM_GPIO_INT_POS,
-       MSM_GPIO_OE,
-       MSM_GPIO_REG_NR
-};
-
-struct msm_gpio_chip {
-       spinlock_t              lock;
-       struct gpio_chip        chip;
-       unsigned long           regs[MSM_GPIO_REG_NR];
-#if MSM_GPIO_BROKEN_INT_CLEAR
-       unsigned                int_status_copy;
-#endif
-       unsigned int            both_edge_detect;
-       unsigned int            int_enable[2]; /* 0: awake, 1: sleep */
-       void __iomem            *base;
-};
-
-struct msm_gpio_initdata {
-       struct msm_gpio_chip *chips;
-       int count;
-};
-
-static void msm_gpio_writel(struct msm_gpio_chip *chip, u32 val,
-                           enum msm_gpio_reg reg)
-{
-       writel(val, chip->base + chip->regs[reg]);
-}
-
-static u32 msm_gpio_readl(struct msm_gpio_chip *chip, enum msm_gpio_reg reg)
-{
-       return readl(chip->base + chip->regs[reg]);
-}
-
-static int msm_gpio_write(struct msm_gpio_chip *msm_chip,
-                         unsigned offset, unsigned on)
-{
-       unsigned mask = BIT(offset);
-       unsigned val;
-
-       val = msm_gpio_readl(msm_chip, MSM_GPIO_OUT);
-       if (on)
-               msm_gpio_writel(msm_chip, val | mask, MSM_GPIO_OUT);
-       else
-               msm_gpio_writel(msm_chip, val & ~mask, MSM_GPIO_OUT);
-       return 0;
-}
-
-static void msm_gpio_update_both_edge_detect(struct msm_gpio_chip *msm_chip)
-{
-       int loop_limit = 100;
-       unsigned pol, val, val2, intstat;
-       do {
-               val = msm_gpio_readl(msm_chip, MSM_GPIO_IN);
-               pol = msm_gpio_readl(msm_chip, MSM_GPIO_INT_POS);
-               pol = (pol & ~msm_chip->both_edge_detect) |
-                     (~val & msm_chip->both_edge_detect);
-               msm_gpio_writel(msm_chip, pol, MSM_GPIO_INT_POS);
-               intstat = msm_gpio_readl(msm_chip, MSM_GPIO_INT_STATUS);
-               val2 = msm_gpio_readl(msm_chip, MSM_GPIO_IN);
-               if (((val ^ val2) & msm_chip->both_edge_detect & ~intstat) == 0)
-                       return;
-       } while (loop_limit-- > 0);
-       printk(KERN_ERR "msm_gpio_update_both_edge_detect, "
-              "failed to reach stable state %x != %x\n", val, val2);
-}
-
-static int msm_gpio_clear_detect_status(struct msm_gpio_chip *msm_chip,
-                                       unsigned offset)
-{
-       unsigned bit = BIT(offset);
-
-#if MSM_GPIO_BROKEN_INT_CLEAR
-       /* Save interrupts that already triggered before we loose them. */
-       /* Any interrupt that triggers between the read of int_status */
-       /* and the write to int_clear will still be lost though. */
-       msm_chip->int_status_copy |=
-               msm_gpio_readl(msm_chip, MSM_GPIO_INT_STATUS);
-       msm_chip->int_status_copy &= ~bit;
-#endif
-       msm_gpio_writel(msm_chip, bit, MSM_GPIO_INT_CLEAR);
-       msm_gpio_update_both_edge_detect(msm_chip);
-       return 0;
-}
-
-static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-       struct msm_gpio_chip *msm_chip;
-       unsigned long irq_flags;
-       u32 val;
-
-       msm_chip = container_of(chip, struct msm_gpio_chip, chip);
-       spin_lock_irqsave(&msm_chip->lock, irq_flags);
-       val = msm_gpio_readl(msm_chip, MSM_GPIO_OE) & ~BIT(offset);
-       msm_gpio_writel(msm_chip, val, MSM_GPIO_OE);
-       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
-       return 0;
-}
-
-static int
-msm_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value)
-{
-       struct msm_gpio_chip *msm_chip;
-       unsigned long irq_flags;
-       u32 val;
-
-       msm_chip = container_of(chip, struct msm_gpio_chip, chip);
-       spin_lock_irqsave(&msm_chip->lock, irq_flags);
-       msm_gpio_write(msm_chip, offset, value);
-       val = msm_gpio_readl(msm_chip, MSM_GPIO_OE) | BIT(offset);
-       msm_gpio_writel(msm_chip, val, MSM_GPIO_OE);
-       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
-       return 0;
-}
-
-static int msm_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-       struct msm_gpio_chip *msm_chip;
-
-       msm_chip = container_of(chip, struct msm_gpio_chip, chip);
-       return (msm_gpio_readl(msm_chip, MSM_GPIO_IN) & (1U << offset)) ? 1 : 0;
-}
-
-static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-       struct msm_gpio_chip *msm_chip;
-       unsigned long irq_flags;
-
-       msm_chip = container_of(chip, struct msm_gpio_chip, chip);
-       spin_lock_irqsave(&msm_chip->lock, irq_flags);
-       msm_gpio_write(msm_chip, offset, value);
-       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
-}
-
-static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-       return MSM_GPIO_TO_INT(chip->base + offset);
-}
-
-#ifdef CONFIG_MSM_GPIOMUX
-static int msm_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
-       return msm_gpiomux_get(chip->base + offset);
-}
-
-static void msm_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
-       msm_gpiomux_put(chip->base + offset);
-}
-#else
-#define msm_gpio_request NULL
-#define msm_gpio_free NULL
-#endif
-
-static struct msm_gpio_chip *msm_gpio_chips;
-static int msm_gpio_count;
-
-static struct msm_gpio_chip msm_gpio_chips_msm7x01[] = {
-       MSM_GPIO_BANK(MSM7X00, 0,   0,  15),
-       MSM_GPIO_BANK(MSM7X00, 1,  16,  42),
-       MSM_GPIO_BANK(MSM7X00, 2,  43,  67),
-       MSM_GPIO_BANK(MSM7X00, 3,  68,  94),
-       MSM_GPIO_BANK(MSM7X00, 4,  95, 106),
-       MSM_GPIO_BANK(MSM7X00, 5, 107, 121),
-};
-
-static struct msm_gpio_initdata msm_gpio_7x01_init = {
-       .chips = msm_gpio_chips_msm7x01,
-       .count = ARRAY_SIZE(msm_gpio_chips_msm7x01),
-};
-
-static struct msm_gpio_chip msm_gpio_chips_msm7x30[] = {
-       MSM_GPIO_BANK(MSM7X30, 0,   0,  15),
-       MSM_GPIO_BANK(MSM7X30, 1,  16,  43),
-       MSM_GPIO_BANK(MSM7X30, 2,  44,  67),
-       MSM_GPIO_BANK(MSM7X30, 3,  68,  94),
-       MSM_GPIO_BANK(MSM7X30, 4,  95, 106),
-       MSM_GPIO_BANK(MSM7X30, 5, 107, 133),
-       MSM_GPIO_BANK(MSM7X30, 6, 134, 150),
-       MSM_GPIO_BANK(MSM7X30, 7, 151, 181),
-};
-
-static struct msm_gpio_initdata msm_gpio_7x30_init = {
-       .chips = msm_gpio_chips_msm7x30,
-       .count = ARRAY_SIZE(msm_gpio_chips_msm7x30),
-};
-
-static struct msm_gpio_chip msm_gpio_chips_qsd8x50[] = {
-       MSM_GPIO_BANK(QSD8X50, 0,   0,  15),
-       MSM_GPIO_BANK(QSD8X50, 1,  16,  42),
-       MSM_GPIO_BANK(QSD8X50, 2,  43,  67),
-       MSM_GPIO_BANK(QSD8X50, 3,  68,  94),
-       MSM_GPIO_BANK(QSD8X50, 4,  95, 103),
-       MSM_GPIO_BANK(QSD8X50, 5, 104, 121),
-       MSM_GPIO_BANK(QSD8X50, 6, 122, 152),
-       MSM_GPIO_BANK(QSD8X50, 7, 153, 164),
-};
-
-static struct msm_gpio_initdata msm_gpio_8x50_init = {
-       .chips = msm_gpio_chips_qsd8x50,
-       .count = ARRAY_SIZE(msm_gpio_chips_qsd8x50),
-};
-
-static void msm_gpio_irq_ack(struct irq_data *d)
-{
-       unsigned long irq_flags;
-       struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
-       spin_lock_irqsave(&msm_chip->lock, irq_flags);
-       msm_gpio_clear_detect_status(msm_chip,
-                                    d->irq - gpio_to_irq(msm_chip->chip.base));
-       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
-}
-
-static void msm_gpio_irq_mask(struct irq_data *d)
-{
-       unsigned long irq_flags;
-       struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
-       unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
-
-       spin_lock_irqsave(&msm_chip->lock, irq_flags);
-       /* level triggered interrupts are also latched */
-       if (!(msm_gpio_readl(msm_chip, MSM_GPIO_INT_EDGE) & BIT(offset)))
-               msm_gpio_clear_detect_status(msm_chip, offset);
-       msm_chip->int_enable[0] &= ~BIT(offset);
-       msm_gpio_writel(msm_chip, msm_chip->int_enable[0], MSM_GPIO_INT_EN);
-       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
-}
-
-static void msm_gpio_irq_unmask(struct irq_data *d)
-{
-       unsigned long irq_flags;
-       struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
-       unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
-
-       spin_lock_irqsave(&msm_chip->lock, irq_flags);
-       /* level triggered interrupts are also latched */
-       if (!(msm_gpio_readl(msm_chip, MSM_GPIO_INT_EDGE) & BIT(offset)))
-               msm_gpio_clear_detect_status(msm_chip, offset);
-       msm_chip->int_enable[0] |= BIT(offset);
-       msm_gpio_writel(msm_chip, msm_chip->int_enable[0], MSM_GPIO_INT_EN);
-       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
-}
-
-static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
-{
-       unsigned long irq_flags;
-       struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
-       unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
-
-       spin_lock_irqsave(&msm_chip->lock, irq_flags);
-
-       if (on)
-               msm_chip->int_enable[1] |= BIT(offset);
-       else
-               msm_chip->int_enable[1] &= ~BIT(offset);
-
-       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
-       return 0;
-}
-
-static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type)
-{
-       unsigned long irq_flags;
-       struct msm_gpio_chip *msm_chip = irq_data_get_irq_chip_data(d);
-       unsigned offset = d->irq - gpio_to_irq(msm_chip->chip.base);
-       unsigned val, mask = BIT(offset);
-
-       spin_lock_irqsave(&msm_chip->lock, irq_flags);
-       val = msm_gpio_readl(msm_chip, MSM_GPIO_INT_EDGE);
-       if (flow_type & IRQ_TYPE_EDGE_BOTH) {
-               msm_gpio_writel(msm_chip, val | mask, MSM_GPIO_INT_EDGE);
-               __irq_set_handler_locked(d->irq, handle_edge_irq);
-       } else {
-               msm_gpio_writel(msm_chip, val & ~mask, MSM_GPIO_INT_EDGE);
-               __irq_set_handler_locked(d->irq, handle_level_irq);
-       }
-       if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
-               msm_chip->both_edge_detect |= mask;
-               msm_gpio_update_both_edge_detect(msm_chip);
-       } else {
-               msm_chip->both_edge_detect &= ~mask;
-               val = msm_gpio_readl(msm_chip, MSM_GPIO_INT_POS);
-               if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_HIGH))
-                       val |= mask;
-               else
-                       val &= ~mask;
-               msm_gpio_writel(msm_chip, val, MSM_GPIO_INT_POS);
-       }
-       spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
-       return 0;
-}
-
-static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
-{
-       int i, j, mask;
-       unsigned val;
-
-       for (i = 0; i < msm_gpio_count; i++) {
-               struct msm_gpio_chip *msm_chip = &msm_gpio_chips[i];
-               val = msm_gpio_readl(msm_chip, MSM_GPIO_INT_STATUS);
-               val &= msm_chip->int_enable[0];
-               while (val) {
-                       mask = val & -val;
-                       j = fls(mask) - 1;
-                       /* printk("%s %08x %08x bit %d gpio %d irq %d\n",
-                               __func__, v, m, j, msm_chip->chip.start + j,
-                               FIRST_GPIO_IRQ + msm_chip->chip.start + j); */
-                       val &= ~mask;
-                       generic_handle_irq(FIRST_GPIO_IRQ +
-                                          msm_chip->chip.base + j);
-               }
-       }
-       desc->irq_data.chip->irq_ack(&desc->irq_data);
-}
-
-static struct irq_chip msm_gpio_irq_chip = {
-       .name          = "msmgpio",
-       .irq_ack       = msm_gpio_irq_ack,
-       .irq_mask      = msm_gpio_irq_mask,
-       .irq_unmask    = msm_gpio_irq_unmask,
-       .irq_set_wake  = msm_gpio_irq_set_wake,
-       .irq_set_type  = msm_gpio_irq_set_type,
-};
-
-static int gpio_msm_v1_probe(struct platform_device *pdev)
-{
-       int i, j = 0;
-       const struct platform_device_id *dev_id = platform_get_device_id(pdev);
-       struct msm_gpio_initdata *data;
-       int irq1, irq2;
-       struct resource *res;
-       void __iomem *base1, __iomem *base2;
-
-       data = (struct msm_gpio_initdata *)dev_id->driver_data;
-       msm_gpio_chips = data->chips;
-       msm_gpio_count = data->count;
-
-       irq1 = platform_get_irq(pdev, 0);
-       if (irq1 < 0)
-               return irq1;
-
-       irq2 = platform_get_irq(pdev, 1);
-       if (irq2 < 0)
-               return irq2;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       base1 = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(base1))
-               return PTR_ERR(base1);
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       base2 = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(base2))
-               return PTR_ERR(base2);
-
-       for (i = FIRST_GPIO_IRQ; i < FIRST_GPIO_IRQ + NR_GPIO_IRQS; i++) {
-               if (i - FIRST_GPIO_IRQ >=
-                       msm_gpio_chips[j].chip.base +
-                       msm_gpio_chips[j].chip.ngpio)
-                       j++;
-               irq_set_chip_data(i, &msm_gpio_chips[j]);
-               irq_set_chip_and_handler(i, &msm_gpio_irq_chip,
-                                        handle_edge_irq);
-               set_irq_flags(i, IRQF_VALID);
-       }
-
-       for (i = 0; i < msm_gpio_count; i++) {
-               if (i == 1)
-                       msm_gpio_chips[i].base = base2;
-               else
-                       msm_gpio_chips[i].base = base1;
-               spin_lock_init(&msm_gpio_chips[i].lock);
-               msm_gpio_writel(&msm_gpio_chips[i], 0, MSM_GPIO_INT_EN);
-               gpiochip_add(&msm_gpio_chips[i].chip);
-       }
-
-       irq_set_chained_handler(irq1, msm_gpio_irq_handler);
-       irq_set_chained_handler(irq2, msm_gpio_irq_handler);
-       irq_set_irq_wake(irq1, 1);
-       irq_set_irq_wake(irq2, 1);
-       return 0;
-}
-
-static struct platform_device_id gpio_msm_v1_device_ids[] = {
-       { "gpio-msm-7201", (unsigned long)&msm_gpio_7x01_init },
-       { "gpio-msm-7x30", (unsigned long)&msm_gpio_7x30_init },
-       { "gpio-msm-8x50", (unsigned long)&msm_gpio_8x50_init },
-       { }
-};
-MODULE_DEVICE_TABLE(platform, gpio_msm_v1_device_ids);
-
-static struct platform_driver gpio_msm_v1_driver = {
-       .driver = {
-               .name = "gpio-msm-v1",
-       },
-       .probe = gpio_msm_v1_probe,
-       .id_table = gpio_msm_v1_device_ids,
-};
-
-static int __init gpio_msm_v1_init(void)
-{
-       return platform_driver_register(&gpio_msm_v1_driver);
-}
-postcore_initcall(gpio_msm_v1_init);
-MODULE_LICENSE("GPL v2");
index ef5feeecec8489d9c816b3d74e5c7f539850afc9..580e10acaa3ace493c16305eabecd75394c6e49a 100644 (file)
@@ -538,8 +538,14 @@ struct dma_buf *
 armada_gem_prime_export(struct drm_device *dev, struct drm_gem_object *obj,
        int flags)
 {
-       return dma_buf_export(obj, &armada_gem_prime_dmabuf_ops, obj->size,
-                             O_RDWR, NULL);
+       DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+
+       exp_info.ops = &armada_gem_prime_dmabuf_ops;
+       exp_info.size = obj->size;
+       exp_info.flags = O_RDWR;
+       exp_info.priv = obj;
+
+       return dma_buf_export(&exp_info);
 }
 
 struct drm_gem_object *
index 7482b06cd08fc60f35da2099ed0d3ed88cf11802..7fec191b45f757737ec9525d51298d844cbd29d4 100644 (file)
@@ -339,13 +339,17 @@ static const struct dma_buf_ops drm_gem_prime_dmabuf_ops =  {
 struct dma_buf *drm_gem_prime_export(struct drm_device *dev,
                                     struct drm_gem_object *obj, int flags)
 {
-       struct reservation_object *robj = NULL;
+       DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+
+       exp_info.ops = &drm_gem_prime_dmabuf_ops;
+       exp_info.size = obj->size;
+       exp_info.flags = flags;
+       exp_info.priv = obj;
 
        if (dev->driver->gem_prime_res_obj)
-               robj = dev->driver->gem_prime_res_obj(obj);
+               exp_info.resv = dev->driver->gem_prime_res_obj(obj);
 
-       return dma_buf_export(obj, &drm_gem_prime_dmabuf_ops, obj->size,
-                             flags, robj);
+       return dma_buf_export(&exp_info);
 }
 EXPORT_SYMBOL(drm_gem_prime_export);
 
index 3833bf8ca0258be7919ecfb690868b8c53b11837..cd485c091b30dcf3219ef1edc778a1aa17c4fdfa 100644 (file)
@@ -185,9 +185,14 @@ struct dma_buf *exynos_dmabuf_prime_export(struct drm_device *drm_dev,
                                struct drm_gem_object *obj, int flags)
 {
        struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
+       DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
 
-       return dma_buf_export(obj, &exynos_dmabuf_ops,
-                               exynos_gem_obj->base.size, flags, NULL);
+       exp_info.ops = &exynos_dmabuf_ops;
+       exp_info.size = exynos_gem_obj->base.size;
+       exp_info.flags = flags;
+       exp_info.priv = obj;
+
+       return dma_buf_export(&exp_info);
 }
 
 struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
index c24c3f1ff8a30ca042dba35c82c8e7b179d5d891..c302ffb5a16814b41086abe52a25c7f7debd40a8 100644 (file)
@@ -1038,7 +1038,7 @@ static void vlv_save_gunit_s0ix_state(struct drm_i915_private *dev_priv)
                s->lra_limits[i] = I915_READ(GEN7_LRA_LIMITS_BASE + i * 4);
 
        s->media_max_req_count  = I915_READ(GEN7_MEDIA_MAX_REQ_COUNT);
-       s->gfx_max_req_count    = I915_READ(GEN7_MEDIA_MAX_REQ_COUNT);
+       s->gfx_max_req_count    = I915_READ(GEN7_GFX_MAX_REQ_COUNT);
 
        s->render_hwsp          = I915_READ(RENDER_HWS_PGA_GEN7);
        s->ecochk               = I915_READ(GAM_ECOCHK);
@@ -1120,7 +1120,7 @@ static void vlv_restore_gunit_s0ix_state(struct drm_i915_private *dev_priv)
                I915_WRITE(GEN7_LRA_LIMITS_BASE + i * 4, s->lra_limits[i]);
 
        I915_WRITE(GEN7_MEDIA_MAX_REQ_COUNT, s->media_max_req_count);
-       I915_WRITE(GEN7_MEDIA_MAX_REQ_COUNT, s->gfx_max_req_count);
+       I915_WRITE(GEN7_GFX_MAX_REQ_COUNT, s->gfx_max_req_count);
 
        I915_WRITE(RENDER_HWS_PGA_GEN7, s->render_hwsp);
        I915_WRITE(GAM_ECOCHK,          s->ecochk);
index d07c0b1fb498264ba0f6224db81434e98c7c6ff5..53394f998a1f9429f87b78598a69e232a48d5b38 100644 (file)
@@ -2377,10 +2377,11 @@ int __i915_add_request(struct intel_engine_cs *ring,
                ret = ring->add_request(ring);
                if (ret)
                        return ret;
+
+               request->tail = intel_ring_get_tail(ringbuf);
        }
 
        request->head = request_start;
-       request->tail = intel_ring_get_tail(ringbuf);
 
        /* Whilst this request exists, batch_obj will be on the
         * active_list, and so will hold the active reference. Only when this
index 82a1f4b57778e29a105316b1b74b7be654be2550..7998da27c500744c78fd0897193b19f778244ca7 100644 (file)
@@ -230,6 +230,13 @@ struct dma_buf *i915_gem_prime_export(struct drm_device *dev,
                                      struct drm_gem_object *gem_obj, int flags)
 {
        struct drm_i915_gem_object *obj = to_intel_bo(gem_obj);
+       DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+
+       exp_info.ops = &i915_dmabuf_ops;
+       exp_info.size = gem_obj->size;
+       exp_info.flags = flags;
+       exp_info.priv = gem_obj;
+
 
        if (obj->ops->dmabuf_export) {
                int ret = obj->ops->dmabuf_export(obj);
@@ -237,8 +244,7 @@ struct dma_buf *i915_gem_prime_export(struct drm_device *dev,
                        return ERR_PTR(ret);
        }
 
-       return dma_buf_export(gem_obj, &i915_dmabuf_ops, gem_obj->size, flags,
-                             NULL);
+       return dma_buf_export(&exp_info);
 }
 
 static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj)
index b522eb6e59a486d2305aec3f2a7982473f322753..773d1d24e604ccc74b92552d07264bb1b3991938 100644 (file)
@@ -1807,6 +1807,7 @@ enum skl_disp_power_wells {
 #define   GMBUS_CYCLE_INDEX    (2<<25)
 #define   GMBUS_CYCLE_STOP     (4<<25)
 #define   GMBUS_BYTE_COUNT_SHIFT 16
+#define   GMBUS_BYTE_COUNT_MAX   256U
 #define   GMBUS_SLAVE_INDEX_SHIFT 8
 #define   GMBUS_SLAVE_ADDR_SHIFT 1
 #define   GMBUS_SLAVE_READ     (1<<0)
@@ -6073,6 +6074,8 @@ enum skl_disp_power_wells {
 #define  GTFIFOCTL                             0x120008
 #define    GT_FIFO_FREE_ENTRIES_MASK           0x7f
 #define    GT_FIFO_NUM_RESERVED_ENTRIES                20
+#define    GT_FIFO_CTL_BLOCK_ALL_POLICY_STALL  (1 << 12)
+#define    GT_FIFO_CTL_RC6_POLICY_STALL                (1 << 11)
 
 #define  HSW_IDICR                             0x9008
 #define    IDIHASHMSK(x)                       (((x) & 0x3f) << 16)
index b31088a551f20ffc376d5e65a14d257164ec1afe..56e437e3158021a09641d188affc6129f0b1eda8 100644 (file)
@@ -270,18 +270,17 @@ gmbus_wait_idle(struct drm_i915_private *dev_priv)
 }
 
 static int
-gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
-               u32 gmbus1_index)
+gmbus_xfer_read_chunk(struct drm_i915_private *dev_priv,
+                     unsigned short addr, u8 *buf, unsigned int len,
+                     u32 gmbus1_index)
 {
        int reg_offset = dev_priv->gpio_mmio_base;
-       u16 len = msg->len;
-       u8 *buf = msg->buf;
 
        I915_WRITE(GMBUS1 + reg_offset,
                   gmbus1_index |
                   GMBUS_CYCLE_WAIT |
                   (len << GMBUS_BYTE_COUNT_SHIFT) |
-                  (msg->addr << GMBUS_SLAVE_ADDR_SHIFT) |
+                  (addr << GMBUS_SLAVE_ADDR_SHIFT) |
                   GMBUS_SLAVE_READ | GMBUS_SW_RDY);
        while (len) {
                int ret;
@@ -303,11 +302,35 @@ gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
 }
 
 static int
-gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg)
+gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
+               u32 gmbus1_index)
 {
-       int reg_offset = dev_priv->gpio_mmio_base;
-       u16 len = msg->len;
        u8 *buf = msg->buf;
+       unsigned int rx_size = msg->len;
+       unsigned int len;
+       int ret;
+
+       do {
+               len = min(rx_size, GMBUS_BYTE_COUNT_MAX);
+
+               ret = gmbus_xfer_read_chunk(dev_priv, msg->addr,
+                                           buf, len, gmbus1_index);
+               if (ret)
+                       return ret;
+
+               rx_size -= len;
+               buf += len;
+       } while (rx_size != 0);
+
+       return 0;
+}
+
+static int
+gmbus_xfer_write_chunk(struct drm_i915_private *dev_priv,
+                      unsigned short addr, u8 *buf, unsigned int len)
+{
+       int reg_offset = dev_priv->gpio_mmio_base;
+       unsigned int chunk_size = len;
        u32 val, loop;
 
        val = loop = 0;
@@ -319,8 +342,8 @@ gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg)
        I915_WRITE(GMBUS3 + reg_offset, val);
        I915_WRITE(GMBUS1 + reg_offset,
                   GMBUS_CYCLE_WAIT |
-                  (msg->len << GMBUS_BYTE_COUNT_SHIFT) |
-                  (msg->addr << GMBUS_SLAVE_ADDR_SHIFT) |
+                  (chunk_size << GMBUS_BYTE_COUNT_SHIFT) |
+                  (addr << GMBUS_SLAVE_ADDR_SHIFT) |
                   GMBUS_SLAVE_WRITE | GMBUS_SW_RDY);
        while (len) {
                int ret;
@@ -337,6 +360,29 @@ gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg)
                if (ret)
                        return ret;
        }
+
+       return 0;
+}
+
+static int
+gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg)
+{
+       u8 *buf = msg->buf;
+       unsigned int tx_size = msg->len;
+       unsigned int len;
+       int ret;
+
+       do {
+               len = min(tx_size, GMBUS_BYTE_COUNT_MAX);
+
+               ret = gmbus_xfer_write_chunk(dev_priv, msg->addr, buf, len);
+               if (ret)
+                       return ret;
+
+               buf += len;
+               tx_size -= len;
+       } while (tx_size != 0);
+
        return 0;
 }
 
index fcb074bd55dcb088308c49b862fd087698c27420..09df74b8e917b1dac90d460be50d1c4c5152881c 100644 (file)
@@ -393,6 +393,26 @@ static void execlists_context_unqueue(struct intel_engine_cs *ring)
                }
        }
 
+       if (IS_GEN8(ring->dev) || IS_GEN9(ring->dev)) {
+               /*
+                * WaIdleLiteRestore: make sure we never cause a lite
+                * restore with HEAD==TAIL
+                */
+               if (req0 && req0->elsp_submitted) {
+                       /*
+                        * Apply the wa NOOPS to prevent ring:HEAD == req:TAIL
+                        * as we resubmit the request. See gen8_emit_request()
+                        * for where we prepare the padding after the end of the
+                        * request.
+                        */
+                       struct intel_ringbuffer *ringbuf;
+
+                       ringbuf = req0->ctx->engine[ring->id].ringbuf;
+                       req0->tail += 8;
+                       req0->tail &= ringbuf->size - 1;
+               }
+       }
+
        WARN_ON(req1 && req1->elsp_submitted);
 
        execlists_submit_contexts(ring, req0->ctx, req0->tail,
@@ -1315,7 +1335,12 @@ static int gen8_emit_request(struct intel_ringbuffer *ringbuf,
        u32 cmd;
        int ret;
 
-       ret = intel_logical_ring_begin(ringbuf, request->ctx, 6);
+       /*
+        * Reserve space for 2 NOOPs at the end of each request to be
+        * used as a workaround for not being allowed to do lite
+        * restore with HEAD==TAIL (WaIdleLiteRestore).
+        */
+       ret = intel_logical_ring_begin(ringbuf, request->ctx, 8);
        if (ret)
                return ret;
 
@@ -1333,6 +1358,14 @@ static int gen8_emit_request(struct intel_ringbuffer *ringbuf,
        intel_logical_ring_emit(ringbuf, MI_NOOP);
        intel_logical_ring_advance_and_submit(ringbuf, request->ctx, request);
 
+       /*
+        * Here we add two extra NOOPs as padding to avoid
+        * lite restore of a context with HEAD==TAIL.
+        */
+       intel_logical_ring_emit(ringbuf, MI_NOOP);
+       intel_logical_ring_emit(ringbuf, MI_NOOP);
+       intel_logical_ring_advance(ringbuf);
+
        return 0;
 }
 
index ab5cc94588e10d1ac1ac81e3330073ea92d17ac7..ff2a74651dd48561c0170427ca9b89f3db54c9d4 100644 (file)
@@ -360,6 +360,14 @@ static void __intel_uncore_early_sanitize(struct drm_device *dev,
                __raw_i915_write32(dev_priv, GTFIFODBG,
                                   __raw_i915_read32(dev_priv, GTFIFODBG));
 
+       /* WaDisableShadowRegForCpd:chv */
+       if (IS_CHERRYVIEW(dev)) {
+               __raw_i915_write32(dev_priv, GTFIFOCTL,
+                                  __raw_i915_read32(dev_priv, GTFIFOCTL) |
+                                  GT_FIFO_CTL_BLOCK_ALL_POLICY_STALL |
+                                  GT_FIFO_CTL_RC6_POLICY_STALL);
+       }
+
        intel_uncore_forcewake_reset(dev, restore_forcewake);
 }
 
index b46dabd9faf75690c6782b20a7dd0b1c501bc160..344fd789170d763264cb4b8585d612745daddff6 100644 (file)
@@ -171,7 +171,14 @@ static struct dma_buf_ops omap_dmabuf_ops = {
 struct dma_buf *omap_gem_prime_export(struct drm_device *dev,
                struct drm_gem_object *obj, int flags)
 {
-       return dma_buf_export(obj, &omap_dmabuf_ops, obj->size, flags, NULL);
+       DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+
+       exp_info.ops = &omap_dmabuf_ops;
+       exp_info.size = obj->size;
+       exp_info.flags = flags;
+       exp_info.priv = obj;
+
+       return dma_buf_export(&exp_info);
 }
 
 struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev,
index dac78ad24b31558aa53d917fb802865b6a122b61..42b2ea3fdcf3584680235e6d5cab14942f7f84b1 100644 (file)
@@ -580,6 +580,9 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
                else
                        radeon_crtc->pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
 
+               /* if there is no audio, set MINM_OVER_MAXP  */
+               if (!drm_detect_monitor_audio(radeon_connector_edid(connector)))
+                       radeon_crtc->pll_flags |= RADEON_PLL_PREFER_MINM_OVER_MAXP;
                if (rdev->family < CHIP_RV770)
                        radeon_crtc->pll_flags |= RADEON_PLL_PREFER_MINM_OVER_MAXP;
                /* use frac fb div on APUs */
index f57c1ab617bc877b4576e828ee203381626b177c..dd39f434b4a7eccf1446ff5cd1857a2cf5de972d 100644 (file)
@@ -1761,17 +1761,15 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
        struct drm_device *dev = encoder->dev;
        struct radeon_device *rdev = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
        int encoder_mode = atombios_get_encoder_mode(encoder);
 
        DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",
                  radeon_encoder->encoder_id, mode, radeon_encoder->devices,
                  radeon_encoder->active_device);
 
-       if (connector && (radeon_audio != 0) &&
+       if ((radeon_audio != 0) &&
            ((encoder_mode == ATOM_ENCODER_MODE_HDMI) ||
-            (ENCODER_MODE_IS_DP(encoder_mode) &&
-             drm_detect_monitor_audio(radeon_connector_edid(connector)))))
+            ENCODER_MODE_IS_DP(encoder_mode)))
                radeon_audio_dpms(encoder, mode);
 
        switch (radeon_encoder->encoder_id) {
index 3adc2afe32aa6be372abcdd925001bbc79176745..68fd9fc677e35f1ca161295694301ec21c089e4d 100644 (file)
@@ -295,28 +295,3 @@ void dce6_dp_audio_set_dto(struct radeon_device *rdev,
                WREG32(DCCG_AUDIO_DTO1_MODULE, clock);
        }
 }
-
-void dce6_dp_enable(struct drm_encoder *encoder, bool enable)
-{
-       struct drm_device *dev = encoder->dev;
-       struct radeon_device *rdev = dev->dev_private;
-       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-
-       if (!dig || !dig->afmt)
-               return;
-
-       if (enable) {
-               WREG32(EVERGREEN_DP_SEC_TIMESTAMP + dig->afmt->offset,
-                      EVERGREEN_DP_SEC_TIMESTAMP_MODE(1));
-               WREG32(EVERGREEN_DP_SEC_CNTL + dig->afmt->offset,
-                      EVERGREEN_DP_SEC_ASP_ENABLE |            /* Audio packet transmission */
-                      EVERGREEN_DP_SEC_ATP_ENABLE |            /* Audio timestamp packet transmission */
-                      EVERGREEN_DP_SEC_AIP_ENABLE |            /* Audio infoframe packet transmission */
-                      EVERGREEN_DP_SEC_STREAM_ENABLE); /* Master enable for secondary stream engine */
-       } else {
-               WREG32(EVERGREEN_DP_SEC_CNTL + dig->afmt->offset, 0);
-       }
-
-       dig->afmt->enabled = enable;
-}
index c18d4ecbd95d02baa907d4d15b6da43f282f4e67..0926739c9fa7c40d17dd09bb318cc19c4ca194c1 100644 (file)
@@ -219,13 +219,9 @@ void evergreen_set_avi_packet(struct radeon_device *rdev, u32 offset,
        WREG32(AFMT_AVI_INFO3 + offset,
                frame[0xC] | (frame[0xD] << 8) | (buffer[1] << 24));
 
-       WREG32_OR(HDMI_INFOFRAME_CONTROL0 + offset,
-               HDMI_AVI_INFO_SEND |    /* enable AVI info frames */
-               HDMI_AVI_INFO_CONT);    /* required for audio info values to be updated */
-
        WREG32_P(HDMI_INFOFRAME_CONTROL1 + offset,
-               HDMI_AVI_INFO_LINE(2),  /* anything other than 0 */
-               ~HDMI_AVI_INFO_LINE_MASK);
+                HDMI_AVI_INFO_LINE(2), /* anything other than 0 */
+                ~HDMI_AVI_INFO_LINE_MASK);
 }
 
 void dce4_hdmi_audio_set_dto(struct radeon_device *rdev,
@@ -370,9 +366,13 @@ void dce4_set_audio_packet(struct drm_encoder *encoder, u32 offset)
        WREG32(AFMT_AUDIO_PACKET_CONTROL2 + offset,
                AFMT_AUDIO_CHANNEL_ENABLE(0xff));
 
+       WREG32(HDMI_AUDIO_PACKET_CONTROL + offset,
+              HDMI_AUDIO_DELAY_EN(1) | /* set the default audio delay */
+              HDMI_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */
+
        /* allow 60958 channel status and send audio packets fields to be updated */
-       WREG32(AFMT_AUDIO_PACKET_CONTROL + offset,
-               AFMT_AUDIO_SAMPLE_SEND | AFMT_RESET_FIFO_WHEN_AUDIO_DIS | AFMT_60958_CS_UPDATE);
+       WREG32_OR(AFMT_AUDIO_PACKET_CONTROL + offset,
+                 AFMT_RESET_FIFO_WHEN_AUDIO_DIS | AFMT_60958_CS_UPDATE);
 }
 
 
@@ -398,17 +398,26 @@ void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable)
                return;
 
        if (enable) {
-               WREG32(HDMI_INFOFRAME_CONTROL1 + dig->afmt->offset,
-                      HDMI_AUDIO_INFO_LINE(2)); /* anything other than 0 */
-
-               WREG32(HDMI_AUDIO_PACKET_CONTROL + dig->afmt->offset,
-                      HDMI_AUDIO_DELAY_EN(1) | /* set the default audio delay */
-                      HDMI_AUDIO_PACKETS_PER_LINE(3)); /* should be suffient for all audio modes and small enough for all hblanks */
+               struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
 
-               WREG32(HDMI_INFOFRAME_CONTROL0 + dig->afmt->offset,
-                      HDMI_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */
-                      HDMI_AUDIO_INFO_CONT); /* required for audio info values to be updated */
+               if (drm_detect_monitor_audio(radeon_connector_edid(connector))) {
+                       WREG32(HDMI_INFOFRAME_CONTROL0 + dig->afmt->offset,
+                              HDMI_AVI_INFO_SEND | /* enable AVI info frames */
+                              HDMI_AVI_INFO_CONT | /* required for audio info values to be updated */
+                              HDMI_AUDIO_INFO_SEND | /* enable audio info frames (frames won't be set until audio is enabled) */
+                              HDMI_AUDIO_INFO_CONT); /* required for audio info values to be updated */
+                       WREG32_OR(AFMT_AUDIO_PACKET_CONTROL + dig->afmt->offset,
+                                 AFMT_AUDIO_SAMPLE_SEND);
+               } else {
+                       WREG32(HDMI_INFOFRAME_CONTROL0 + dig->afmt->offset,
+                              HDMI_AVI_INFO_SEND | /* enable AVI info frames */
+                              HDMI_AVI_INFO_CONT); /* required for audio info values to be updated */
+                       WREG32_AND(AFMT_AUDIO_PACKET_CONTROL + dig->afmt->offset,
+                                  ~AFMT_AUDIO_SAMPLE_SEND);
+               }
        } else {
+               WREG32_AND(AFMT_AUDIO_PACKET_CONTROL + dig->afmt->offset,
+                          ~AFMT_AUDIO_SAMPLE_SEND);
                WREG32(HDMI_INFOFRAME_CONTROL0 + dig->afmt->offset, 0);
        }
 
@@ -424,20 +433,24 @@ void evergreen_dp_enable(struct drm_encoder *encoder, bool enable)
        struct radeon_device *rdev = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+       struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
 
        if (!dig || !dig->afmt)
                return;
 
-       if (enable) {
+       if (enable && drm_detect_monitor_audio(radeon_connector_edid(connector))) {
                struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
                struct radeon_connector *radeon_connector = to_radeon_connector(connector);
                struct radeon_connector_atom_dig *dig_connector;
                uint32_t val;
 
+               WREG32_OR(AFMT_AUDIO_PACKET_CONTROL + dig->afmt->offset,
+                         AFMT_AUDIO_SAMPLE_SEND);
+
                WREG32(EVERGREEN_DP_SEC_TIMESTAMP + dig->afmt->offset,
                       EVERGREEN_DP_SEC_TIMESTAMP_MODE(1));
 
-               if (radeon_connector->con_priv) {
+               if (!ASIC_IS_DCE6(rdev) && radeon_connector->con_priv) {
                        dig_connector = radeon_connector->con_priv;
                        val = RREG32(EVERGREEN_DP_SEC_AUD_N + dig->afmt->offset);
                        val &= ~EVERGREEN_DP_SEC_N_BASE_MULTIPLE(0xf);
@@ -457,6 +470,8 @@ void evergreen_dp_enable(struct drm_encoder *encoder, bool enable)
                        EVERGREEN_DP_SEC_STREAM_ENABLE);        /* Master enable for secondary stream engine */
        } else {
                WREG32(EVERGREEN_DP_SEC_CNTL + dig->afmt->offset, 0);
+               WREG32_AND(AFMT_AUDIO_PACKET_CONTROL + dig->afmt->offset,
+                          ~AFMT_AUDIO_SAMPLE_SEND);
        }
 
        dig->afmt->enabled = enable;
index dd6606b8e23ca9a3bfd3f7be414b17d01af2aacb..e85894ade95c44ab61d73f58f6452efb01bee0da 100644 (file)
@@ -228,12 +228,13 @@ void r600_set_avi_packet(struct radeon_device *rdev, u32 offset,
        WREG32(HDMI0_AVI_INFO3 + offset,
                frame[0xC] | (frame[0xD] << 8) | (buffer[1] << 24));
 
+       WREG32_OR(HDMI0_INFOFRAME_CONTROL1 + offset,
+                 HDMI0_AVI_INFO_LINE(2));      /* anything other than 0 */
+
        WREG32_OR(HDMI0_INFOFRAME_CONTROL0 + offset,
-               HDMI0_AVI_INFO_SEND |   /* enable AVI info frames */
-               HDMI0_AVI_INFO_CONT);   /* send AVI info frames every frame/field */
+                 HDMI0_AVI_INFO_SEND | /* enable AVI info frames */
+                 HDMI0_AVI_INFO_CONT); /* send AVI info frames every frame/field */
 
-       WREG32_OR(HDMI0_INFOFRAME_CONTROL1 + offset,
-               HDMI0_AVI_INFO_LINE(2));        /* anything other than 0 */
 }
 
 /*
index 48d49e651a30cf94212fe2b4482178e7870ed029..8b82abb78df159d877f27c1ec67cd7502010634d 100644 (file)
@@ -102,7 +102,6 @@ static void radeon_audio_dp_mode_set(struct drm_encoder *encoder,
 void r600_hdmi_enable(struct drm_encoder *encoder, bool enable);
 void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable);
 void evergreen_dp_enable(struct drm_encoder *encoder, bool enable);
-void dce6_dp_enable(struct drm_encoder *encoder, bool enable);
 
 static const u32 pin_offsets[7] =
 {
@@ -240,7 +239,7 @@ static struct radeon_audio_funcs dce6_dp_funcs = {
        .set_avi_packet = evergreen_set_avi_packet,
        .set_audio_packet = dce4_set_audio_packet,
        .mode_set = radeon_audio_dp_mode_set,
-       .dpms = dce6_dp_enable,
+       .dpms = evergreen_dp_enable,
 };
 
 static void radeon_audio_interface_init(struct radeon_device *rdev)
@@ -461,30 +460,33 @@ void radeon_audio_detect(struct drm_connector *connector,
        if (!connector || !connector->encoder)
                return;
 
+       if (!radeon_encoder_is_digital(connector->encoder))
+               return;
+
        rdev = connector->encoder->dev->dev_private;
        radeon_encoder = to_radeon_encoder(connector->encoder);
        dig = radeon_encoder->enc_priv;
 
-       if (status == connector_status_connected) {
-               struct radeon_connector *radeon_connector;
-               int sink_type;
-
-               if (!drm_detect_monitor_audio(radeon_connector_edid(connector))) {
-                       radeon_encoder->audio = NULL;
-                       return;
-               }
+       if (!dig->afmt)
+               return;
 
-               radeon_connector = to_radeon_connector(connector);
-               sink_type = radeon_dp_getsinktype(radeon_connector);
+       if (status == connector_status_connected) {
+               struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 
                if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort &&
-                       sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT)
+                   radeon_dp_getsinktype(radeon_connector) ==
+                   CONNECTOR_OBJECT_ID_DISPLAYPORT)
                        radeon_encoder->audio = rdev->audio.dp_funcs;
                else
                        radeon_encoder->audio = rdev->audio.hdmi_funcs;
 
                dig->afmt->pin = radeon_audio_get_pin(connector->encoder);
-               radeon_audio_enable(rdev, dig->afmt->pin, 0xf);
+               if (drm_detect_monitor_audio(radeon_connector_edid(connector))) {
+                       radeon_audio_enable(rdev, dig->afmt->pin, 0xf);
+               } else {
+                       radeon_audio_enable(rdev, dig->afmt->pin, 0);
+                       dig->afmt->pin = NULL;
+               }
        } else {
                radeon_audio_enable(rdev, dig->afmt->pin, 0);
                dig->afmt->pin = NULL;
index cebb65e07e1d13f0bee01ee753f4c8a76e0e22d5..d17d251dbd4fe5a1ac99a238fd7aebcf552682ba 100644 (file)
@@ -1379,8 +1379,10 @@ out:
        /* updated in get modes as well since we need to know if it's analog or digital */
        radeon_connector_update_scratch_regs(connector, ret);
 
-       if (radeon_audio != 0)
+       if (radeon_audio != 0) {
+               radeon_connector_get_edid(connector);
                radeon_audio_detect(connector, ret);
+       }
 
 exit:
        pm_runtime_mark_last_busy(connector->dev->dev);
@@ -1717,8 +1719,10 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
 
        radeon_connector_update_scratch_regs(connector, ret);
 
-       if (radeon_audio != 0)
+       if (radeon_audio != 0) {
+               radeon_connector_get_edid(connector);
                radeon_audio_detect(connector, ret);
+       }
 
 out:
        pm_runtime_mark_last_busy(connector->dev->dev);
index 4d0f96cc3da4488b0a324058533d26500011293f..ab39b85e0f76d4cd2f926594dd1e4bc1d83a56dd 100644 (file)
@@ -88,7 +88,7 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
        p->dma_reloc_idx = 0;
        /* FIXME: we assume that each relocs use 4 dwords */
        p->nrelocs = chunk->length_dw / 4;
-       p->relocs = kcalloc(p->nrelocs, sizeof(struct radeon_bo_list), GFP_KERNEL);
+       p->relocs = drm_calloc_large(p->nrelocs, sizeof(struct radeon_bo_list));
        if (p->relocs == NULL) {
                return -ENOMEM;
        }
@@ -428,7 +428,7 @@ static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error, bo
                }
        }
        kfree(parser->track);
-       kfree(parser->relocs);
+       drm_free_large(parser->relocs);
        drm_free_large(parser->vm_bos);
        for (i = 0; i < parser->nchunks; i++)
                drm_free_large(parser->chunks[i].kdata);
index 01701376b23987c624a8d48a899e065d10d4bb8b..535bf404b725f8aea3f58ddcb5a082b992212329 100644 (file)
@@ -135,7 +135,7 @@ static void radeon_mn_invalidate_range_start(struct mmu_notifier *mn,
        while (it) {
                struct radeon_mn_node *node;
                struct radeon_bo *bo;
-               int r;
+               long r;
 
                node = container_of(it, struct radeon_mn_node, it);
                it = interval_tree_iter_next(it, start, end);
@@ -144,19 +144,19 @@ static void radeon_mn_invalidate_range_start(struct mmu_notifier *mn,
 
                        r = radeon_bo_reserve(bo, true);
                        if (r) {
-                               DRM_ERROR("(%d) failed to reserve user bo\n", r);
+                               DRM_ERROR("(%ld) failed to reserve user bo\n", r);
                                continue;
                        }
 
                        r = reservation_object_wait_timeout_rcu(bo->tbo.resv,
                                true, false, MAX_SCHEDULE_TIMEOUT);
-                       if (r)
-                               DRM_ERROR("(%d) failed to wait for user bo\n", r);
+                       if (r <= 0)
+                               DRM_ERROR("(%ld) failed to wait for user bo\n", r);
 
                        radeon_ttm_placement_from_domain(bo, RADEON_GEM_DOMAIN_CPU);
                        r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
                        if (r)
-                               DRM_ERROR("(%d) failed to validate user bo\n", r);
+                               DRM_ERROR("(%ld) failed to validate user bo\n", r);
 
                        radeon_bo_unreserve(bo);
                }
index 2a5a4a9e772d6668ee844b94c61219a0c3100340..de42fc4a22b869296ff44c85c859678c6155ddd7 100644 (file)
@@ -473,6 +473,23 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev,
        }
 
        mutex_lock(&vm->mutex);
+       soffset /= RADEON_GPU_PAGE_SIZE;
+       eoffset /= RADEON_GPU_PAGE_SIZE;
+       if (soffset || eoffset) {
+               struct interval_tree_node *it;
+               it = interval_tree_iter_first(&vm->va, soffset, eoffset - 1);
+               if (it && it != &bo_va->it) {
+                       struct radeon_bo_va *tmp;
+                       tmp = container_of(it, struct radeon_bo_va, it);
+                       /* bo and tmp overlap, invalid offset */
+                       dev_err(rdev->dev, "bo %p va 0x%010Lx conflict with "
+                               "(bo %p 0x%010lx 0x%010lx)\n", bo_va->bo,
+                               soffset, tmp->bo, tmp->it.start, tmp->it.last);
+                       mutex_unlock(&vm->mutex);
+                       return -EINVAL;
+               }
+       }
+
        if (bo_va->it.start || bo_va->it.last) {
                if (bo_va->addr) {
                        /* add a clone of the bo_va to clear the old address */
@@ -490,6 +507,8 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev,
                        spin_lock(&vm->status_lock);
                        list_add(&tmp->vm_status, &vm->freed);
                        spin_unlock(&vm->status_lock);
+
+                       bo_va->addr = 0;
                }
 
                interval_tree_remove(&bo_va->it, &vm->va);
@@ -497,21 +516,7 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev,
                bo_va->it.last = 0;
        }
 
-       soffset /= RADEON_GPU_PAGE_SIZE;
-       eoffset /= RADEON_GPU_PAGE_SIZE;
        if (soffset || eoffset) {
-               struct interval_tree_node *it;
-               it = interval_tree_iter_first(&vm->va, soffset, eoffset - 1);
-               if (it) {
-                       struct radeon_bo_va *tmp;
-                       tmp = container_of(it, struct radeon_bo_va, it);
-                       /* bo and tmp overlap, invalid offset */
-                       dev_err(rdev->dev, "bo %p va 0x%010Lx conflict with "
-                               "(bo %p 0x%010lx 0x%010lx)\n", bo_va->bo,
-                               soffset, tmp->bo, tmp->it.start, tmp->it.last);
-                       mutex_unlock(&vm->mutex);
-                       return -EINVAL;
-               }
                bo_va->it.start = soffset;
                bo_va->it.last = eoffset - 1;
                interval_tree_insert(&bo_va->it, &vm->va);
@@ -1107,7 +1112,8 @@ void radeon_vm_bo_rmv(struct radeon_device *rdev,
        list_del(&bo_va->bo_list);
 
        mutex_lock(&vm->mutex);
-       interval_tree_remove(&bo_va->it, &vm->va);
+       if (bo_va->it.start || bo_va->it.last)
+               interval_tree_remove(&bo_va->it, &vm->va);
        spin_lock(&vm->status_lock);
        list_del(&bo_va->vm_status);
 
index b35bccfeef79c402c33b6406e0e70755fd4098ad..ff8b83f5e929a851943e61e76fc3d45b2967a2a3 100644 (file)
@@ -2924,6 +2924,7 @@ struct si_dpm_quirk {
 static struct si_dpm_quirk si_dpm_quirk_list[] = {
        /* PITCAIRN - https://bugs.freedesktop.org/show_bug.cgi?id=76490 */
        { PCI_VENDOR_ID_ATI, 0x6810, 0x1462, 0x3036, 0, 120000 },
+       { PCI_VENDOR_ID_ATI, 0x6811, 0x174b, 0xe271, 0, 120000 },
        { 0, 0, 0, 0 },
 };
 
index ccb0ce073ef2af6f2233fbc88428ea176dbea855..4557f335a8a56f243ad4aa326a1826572116d3a5 100644 (file)
@@ -1409,7 +1409,7 @@ static int vop_bind(struct device *dev, struct device *master, void *data)
        struct vop *vop;
        struct resource *res;
        size_t alloc_size;
-       int ret;
+       int ret, irq;
 
        of_id = of_match_device(vop_driver_dt_match, dev);
        vop_data = of_id->data;
@@ -1445,11 +1445,12 @@ static int vop_bind(struct device *dev, struct device *master, void *data)
                return ret;
        }
 
-       vop->irq = platform_get_irq(pdev, 0);
-       if (vop->irq < 0) {
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
                dev_err(dev, "cannot find irq for vop\n");
-               return vop->irq;
+               return irq;
        }
+       vop->irq = (unsigned int)irq;
 
        spin_lock_init(&vop->reg_lock);
        spin_lock_init(&vop->irq_lock);
index cfb481943b6b5741e6538fa4ebf1bc5b56c9d4a7..1217272a51f2cf64173f632690123a9920233097 100644 (file)
@@ -627,8 +627,14 @@ struct dma_buf *tegra_gem_prime_export(struct drm_device *drm,
                                       struct drm_gem_object *gem,
                                       int flags)
 {
-       return dma_buf_export(gem, &tegra_gem_prime_dmabuf_ops, gem->size,
-                             flags, NULL);
+       DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+
+       exp_info.ops = &tegra_gem_prime_dmabuf_ops;
+       exp_info.size = gem->size;
+       exp_info.flags = flags;
+       exp_info.priv = gem;
+
+       return dma_buf_export(&exp_info);
 }
 
 struct drm_gem_object *tegra_gem_prime_import(struct drm_device *drm,
index 12c87110db3ad2bf4aca3a9ca0c7daed0a26bef7..4f5fa8d65fe932a7e10803d10d0e0fc3090a7d59 100644 (file)
@@ -683,6 +683,12 @@ int ttm_prime_handle_to_fd(struct ttm_object_file *tfile,
 
        dma_buf = prime->dma_buf;
        if (!dma_buf || !get_dma_buf_unless_doomed(dma_buf)) {
+               DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+
+               exp_info.ops = &tdev->ops;
+               exp_info.size = prime->size;
+               exp_info.flags = flags;
+               exp_info.priv = prime;
 
                /*
                 * Need to create a new dma_buf, with memory accounting.
@@ -694,8 +700,7 @@ int ttm_prime_handle_to_fd(struct ttm_object_file *tfile,
                        goto out_unref;
                }
 
-               dma_buf = dma_buf_export(prime, &tdev->ops,
-                                        prime->size, flags, NULL);
+               dma_buf = dma_buf_export(&exp_info);
                if (IS_ERR(dma_buf)) {
                        ret = PTR_ERR(dma_buf);
                        ttm_mem_global_free(tdev->mem_glob,
index ac8a66b4dfc2053ec8b8f7314601bb4d30d49e6a..e2243edd1ce31d6aeaa98e7e1f3ea7bc2ebb31cf 100644 (file)
@@ -202,7 +202,14 @@ static struct dma_buf_ops udl_dmabuf_ops = {
 struct dma_buf *udl_gem_prime_export(struct drm_device *dev,
                                     struct drm_gem_object *obj, int flags)
 {
-       return dma_buf_export(obj, &udl_dmabuf_ops, obj->size, flags, NULL);
+       DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+
+       exp_info.ops = &udl_dmabuf_ops;
+       exp_info.size = obj->size;
+       exp_info.flags = flags;
+       exp_info.priv = obj;
+
+       return dma_buf_export(&exp_info);
 }
 
 static int udl_prime_create(struct drm_device *dev,
index 2978f5ee8d2a0abdeacdc8f7fc2121d35c0260a2..54da66dc7d16c033db21664606a0fe7efc576535 100644 (file)
@@ -71,7 +71,8 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
        struct vmbus_channel_msginfo *open_info = NULL;
        void *in, *out;
        unsigned long flags;
-       int ret, t, err = 0;
+       int ret, err = 0;
+       unsigned long t;
 
        spin_lock_irqsave(&newchannel->lock, flags);
        if (newchannel->state == CHANNEL_OPEN_STATE) {
@@ -89,9 +90,10 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
        out = (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
                get_order(send_ringbuffer_size + recv_ringbuffer_size));
 
-       if (!out)
-               return -ENOMEM;
-
+       if (!out) {
+               err = -ENOMEM;
+               goto error0;
+       }
 
        in = (void *)((unsigned long)out + send_ringbuffer_size);
 
@@ -135,7 +137,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
                           GFP_KERNEL);
        if (!open_info) {
                err = -ENOMEM;
-               goto error0;
+               goto error_gpadl;
        }
 
        init_completion(&open_info->waitevent);
@@ -151,7 +153,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
 
        if (userdatalen > MAX_USER_DEFINED_BYTES) {
                err = -EINVAL;
-               goto error0;
+               goto error_gpadl;
        }
 
        if (userdatalen)
@@ -195,10 +197,14 @@ error1:
        list_del(&open_info->msglistentry);
        spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
 
+error_gpadl:
+       vmbus_teardown_gpadl(newchannel, newchannel->ringbuffer_gpadlhandle);
+
 error0:
        free_pages((unsigned long)out,
                get_order(send_ringbuffer_size + recv_ringbuffer_size));
        kfree(open_info);
+       newchannel->state = CHANNEL_OPEN_STATE;
        return err;
 }
 EXPORT_SYMBOL_GPL(vmbus_open);
@@ -534,6 +540,12 @@ static int vmbus_close_internal(struct vmbus_channel *channel)
        free_pages((unsigned long)channel->ringbuffer_pages,
                get_order(channel->ringbuffer_pagecount * PAGE_SIZE));
 
+       /*
+        * If the channel has been rescinded; process device removal.
+        */
+       if (channel->rescind)
+               hv_process_channel_removal(channel,
+                                          channel->offermsg.child_relid);
        return ret;
 }
 
@@ -569,23 +581,9 @@ void vmbus_close(struct vmbus_channel *channel)
 }
 EXPORT_SYMBOL_GPL(vmbus_close);
 
-/**
- * vmbus_sendpacket() - Send the specified buffer on the given channel
- * @channel: Pointer to vmbus_channel structure.
- * @buffer: Pointer to the buffer you want to receive the data into.
- * @bufferlen: Maximum size of what the the buffer will hold
- * @requestid: Identifier of the request
- * @type: Type of packet that is being send e.g. negotiate, time
- * packet etc.
- *
- * Sends data in @buffer directly to hyper-v via the vmbus
- * This will send the data unparsed to hyper-v.
- *
- * Mainly used by Hyper-V drivers.
- */
-int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer,
+int vmbus_sendpacket_ctl(struct vmbus_channel *channel, void *buffer,
                           u32 bufferlen, u64 requestid,
-                          enum vmbus_packet_type type, u32 flags)
+                          enum vmbus_packet_type type, u32 flags, bool kick_q)
 {
        struct vmpacket_descriptor desc;
        u32 packetlen = sizeof(struct vmpacket_descriptor) + bufferlen;
@@ -613,21 +611,61 @@ int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer,
 
        ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);
 
-       if (ret == 0 && signal)
+       /*
+        * Signalling the host is conditional on many factors:
+        * 1. The ring state changed from being empty to non-empty.
+        *    This is tracked by the variable "signal".
+        * 2. The variable kick_q tracks if more data will be placed
+        *    on the ring. We will not signal if more data is
+        *    to be placed.
+        *
+        * If we cannot write to the ring-buffer; signal the host
+        * even if we may not have written anything. This is a rare
+        * enough condition that it should not matter.
+        */
+       if (((ret == 0) && kick_q && signal) || (ret))
                vmbus_setevent(channel);
 
        return ret;
 }
+EXPORT_SYMBOL(vmbus_sendpacket_ctl);
+
+/**
+ * vmbus_sendpacket() - Send the specified buffer on the given channel
+ * @channel: Pointer to vmbus_channel structure.
+ * @buffer: Pointer to the buffer you want to receive the data into.
+ * @bufferlen: Maximum size of what the the buffer will hold
+ * @requestid: Identifier of the request
+ * @type: Type of packet that is being send e.g. negotiate, time
+ * packet etc.
+ *
+ * Sends data in @buffer directly to hyper-v via the vmbus
+ * This will send the data unparsed to hyper-v.
+ *
+ * Mainly used by Hyper-V drivers.
+ */
+int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer,
+                          u32 bufferlen, u64 requestid,
+                          enum vmbus_packet_type type, u32 flags)
+{
+       return vmbus_sendpacket_ctl(channel, buffer, bufferlen, requestid,
+                                   type, flags, true);
+}
 EXPORT_SYMBOL(vmbus_sendpacket);
 
 /*
- * vmbus_sendpacket_pagebuffer - Send a range of single-page buffer
- * packets using a GPADL Direct packet type.
+ * vmbus_sendpacket_pagebuffer_ctl - Send a range of single-page buffer
+ * packets using a GPADL Direct packet type. This interface allows you
+ * to control notifying the host. This will be useful for sending
+ * batched data. Also the sender can control the send flags
+ * explicitly.
  */
-int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
+int vmbus_sendpacket_pagebuffer_ctl(struct vmbus_channel *channel,
                                     struct hv_page_buffer pagebuffers[],
                                     u32 pagecount, void *buffer, u32 bufferlen,
-                                    u64 requestid)
+                                    u64 requestid,
+                                    u32 flags,
+                                    bool kick_q)
 {
        int ret;
        int i;
@@ -655,7 +693,7 @@ int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
 
        /* Setup the descriptor */
        desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
-       desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
+       desc.flags = flags;
        desc.dataoffset8 = descsize >> 3; /* in 8-bytes grandularity */
        desc.length8 = (u16)(packetlen_aligned >> 3);
        desc.transactionid = requestid;
@@ -676,11 +714,40 @@ int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
 
        ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);
 
-       if (ret == 0 && signal)
+       /*
+        * Signalling the host is conditional on many factors:
+        * 1. The ring state changed from being empty to non-empty.
+        *    This is tracked by the variable "signal".
+        * 2. The variable kick_q tracks if more data will be placed
+        *    on the ring. We will not signal if more data is
+        *    to be placed.
+        *
+        * If we cannot write to the ring-buffer; signal the host
+        * even if we may not have written anything. This is a rare
+        * enough condition that it should not matter.
+        */
+       if (((ret == 0) && kick_q && signal) || (ret))
                vmbus_setevent(channel);
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer_ctl);
+
+/*
+ * vmbus_sendpacket_pagebuffer - Send a range of single-page buffer
+ * packets using a GPADL Direct packet type.
+ */
+int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
+                                    struct hv_page_buffer pagebuffers[],
+                                    u32 pagecount, void *buffer, u32 bufferlen,
+                                    u64 requestid)
+{
+       u32 flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
+       return vmbus_sendpacket_pagebuffer_ctl(channel, pagebuffers, pagecount,
+                                              buffer, bufferlen, requestid,
+                                              flags, true);
+
+}
 EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer);
 
 /*
index 3736f71bdec5ba3ea314fd2f0ae069dfb70133bf..0eeb1b3bc0484ce75572b0f6326ca0857cb73268 100644 (file)
 
 #include "hyperv_vmbus.h"
 
-struct vmbus_channel_message_table_entry {
-       enum vmbus_channel_message_type message_type;
-       void (*message_handler)(struct vmbus_channel_message_header *msg);
-};
-
-
 /**
  * vmbus_prep_negotiate_resp() - Create default response for Hyper-V Negotiate message
  * @icmsghdrp: Pointer to msg header structure
@@ -139,54 +133,29 @@ EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp);
  */
 static struct vmbus_channel *alloc_channel(void)
 {
+       static atomic_t chan_num = ATOMIC_INIT(0);
        struct vmbus_channel *channel;
 
        channel = kzalloc(sizeof(*channel), GFP_ATOMIC);
        if (!channel)
                return NULL;
 
+       channel->id = atomic_inc_return(&chan_num);
        spin_lock_init(&channel->inbound_lock);
        spin_lock_init(&channel->lock);
 
        INIT_LIST_HEAD(&channel->sc_list);
        INIT_LIST_HEAD(&channel->percpu_list);
 
-       channel->controlwq = create_workqueue("hv_vmbus_ctl");
-       if (!channel->controlwq) {
-               kfree(channel);
-               return NULL;
-       }
-
        return channel;
 }
 
-/*
- * release_hannel - Release the vmbus channel object itself
- */
-static void release_channel(struct work_struct *work)
-{
-       struct vmbus_channel *channel = container_of(work,
-                                                    struct vmbus_channel,
-                                                    work);
-
-       destroy_workqueue(channel->controlwq);
-
-       kfree(channel);
-}
-
 /*
  * free_channel - Release the resources used by the vmbus channel object
  */
 static void free_channel(struct vmbus_channel *channel)
 {
-
-       /*
-        * We have to release the channel's workqueue/thread in the vmbus's
-        * workqueue/thread context
-        * ie we can't destroy ourselves.
-        */
-       INIT_WORK(&channel->work, release_channel);
-       queue_work(vmbus_connection.work_queue, &channel->work);
+       kfree(channel);
 }
 
 static void percpu_channel_enq(void *arg)
@@ -204,33 +173,21 @@ static void percpu_channel_deq(void *arg)
        list_del(&channel->percpu_list);
 }
 
-/*
- * vmbus_process_rescind_offer -
- * Rescind the offer by initiating a device removal
- */
-static void vmbus_process_rescind_offer(struct work_struct *work)
+
+void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid)
 {
-       struct vmbus_channel *channel = container_of(work,
-                                                    struct vmbus_channel,
-                                                    work);
+       struct vmbus_channel_relid_released msg;
        unsigned long flags;
        struct vmbus_channel *primary_channel;
-       struct vmbus_channel_relid_released msg;
-       struct device *dev;
-
-       if (channel->device_obj) {
-               dev = get_device(&channel->device_obj->device);
-               if (dev) {
-                       vmbus_device_unregister(channel->device_obj);
-                       put_device(dev);
-               }
-       }
 
        memset(&msg, 0, sizeof(struct vmbus_channel_relid_released));
-       msg.child_relid = channel->offermsg.child_relid;
+       msg.child_relid = relid;
        msg.header.msgtype = CHANNELMSG_RELID_RELEASED;
        vmbus_post_msg(&msg, sizeof(struct vmbus_channel_relid_released));
 
+       if (channel == NULL)
+               return;
+
        if (channel->target_cpu != get_cpu()) {
                put_cpu();
                smp_call_function_single(channel->target_cpu,
@@ -259,7 +216,6 @@ void vmbus_free_channels(void)
 
        list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) {
                vmbus_device_unregister(channel->device_obj);
-               kfree(channel->device_obj);
                free_channel(channel);
        }
 }
@@ -268,15 +224,11 @@ void vmbus_free_channels(void)
  * vmbus_process_offer - Process the offer by creating a channel/device
  * associated with this offer
  */
-static void vmbus_process_offer(struct work_struct *work)
+static void vmbus_process_offer(struct vmbus_channel *newchannel)
 {
-       struct vmbus_channel *newchannel = container_of(work,
-                                                       struct vmbus_channel,
-                                                       work);
        struct vmbus_channel *channel;
        bool fnew = true;
        bool enq = false;
-       int ret;
        unsigned long flags;
 
        /* Make sure this is a new offer */
@@ -335,10 +287,11 @@ static void vmbus_process_offer(struct work_struct *work)
                        }
 
                        newchannel->state = CHANNEL_OPEN_STATE;
+                       channel->num_sc++;
                        if (channel->sc_creation_callback != NULL)
                                channel->sc_creation_callback(newchannel);
 
-                       goto done_init_rescind;
+                       return;
                }
 
                goto err_free_chan;
@@ -361,33 +314,35 @@ static void vmbus_process_offer(struct work_struct *work)
                &newchannel->offermsg.offer.if_instance,
                newchannel);
        if (!newchannel->device_obj)
-               goto err_free_chan;
+               goto err_deq_chan;
 
        /*
         * Add the new device to the bus. This will kick off device-driver
         * binding which eventually invokes the device driver's AddDevice()
         * method.
         */
-       ret = vmbus_device_register(newchannel->device_obj);
-       if (ret != 0) {
+       if (vmbus_device_register(newchannel->device_obj) != 0) {
                pr_err("unable to add child device object (relid %d)\n",
-                          newchannel->offermsg.child_relid);
-
-               spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
-               list_del(&newchannel->listentry);
-               spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
+                       newchannel->offermsg.child_relid);
                kfree(newchannel->device_obj);
-               goto err_free_chan;
+               goto err_deq_chan;
        }
-done_init_rescind:
-       spin_lock_irqsave(&newchannel->lock, flags);
-       /* The next possible work is rescind handling */
-       INIT_WORK(&newchannel->work, vmbus_process_rescind_offer);
-       /* Check if rescind offer was already received */
-       if (newchannel->rescind)
-               queue_work(newchannel->controlwq, &newchannel->work);
-       spin_unlock_irqrestore(&newchannel->lock, flags);
        return;
+
+err_deq_chan:
+       spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
+       list_del(&newchannel->listentry);
+       spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
+
+       if (newchannel->target_cpu != get_cpu()) {
+               put_cpu();
+               smp_call_function_single(newchannel->target_cpu,
+                                        percpu_channel_deq, newchannel, true);
+       } else {
+               percpu_channel_deq(newchannel);
+               put_cpu();
+       }
+
 err_free_chan:
        free_channel(newchannel);
 }
@@ -411,6 +366,8 @@ static const struct hv_vmbus_device_id hp_devs[] = {
        { HV_SCSI_GUID, },
        /* Network */
        { HV_NIC_GUID, },
+       /* NetworkDirect Guest RDMA */
+       { HV_ND_GUID, },
 };
 
 
@@ -511,8 +468,7 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr)
        newchannel->monitor_grp = (u8)offer->monitorid / 32;
        newchannel->monitor_bit = (u8)offer->monitorid % 32;
 
-       INIT_WORK(&newchannel->work, vmbus_process_offer);
-       queue_work(newchannel->controlwq, &newchannel->work);
+       vmbus_process_offer(newchannel);
 }
 
 /*
@@ -525,28 +481,34 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
        struct vmbus_channel_rescind_offer *rescind;
        struct vmbus_channel *channel;
        unsigned long flags;
+       struct device *dev;
 
        rescind = (struct vmbus_channel_rescind_offer *)hdr;
        channel = relid2channel(rescind->child_relid);
 
-       if (channel == NULL)
-               /* Just return here, no channel found */
+       if (channel == NULL) {
+               hv_process_channel_removal(NULL, rescind->child_relid);
                return;
+       }
 
        spin_lock_irqsave(&channel->lock, flags);
        channel->rescind = true;
-       /*
-        * channel->work.func != vmbus_process_rescind_offer means we are still
-        * processing offer request and the rescind offer processing should be
-        * postponed. It will be done at the very end of vmbus_process_offer()
-        * as rescind flag is being checked there.
-        */
-       if (channel->work.func == vmbus_process_rescind_offer)
-               /* work is initialized for vmbus_process_rescind_offer() from
-                * vmbus_process_offer() where the channel got created */
-               queue_work(channel->controlwq, &channel->work);
-
        spin_unlock_irqrestore(&channel->lock, flags);
+
+       if (channel->device_obj) {
+               /*
+                * We will have to unregister this device from the
+                * driver core.
+                */
+               dev = get_device(&channel->device_obj->device);
+               if (dev) {
+                       vmbus_device_unregister(channel->device_obj);
+                       put_device(dev);
+               }
+       } else {
+               hv_process_channel_removal(channel,
+                       channel->offermsg.child_relid);
+       }
 }
 
 /*
@@ -731,25 +693,25 @@ static void vmbus_onversion_response(
 }
 
 /* Channel message dispatch table */
-static struct vmbus_channel_message_table_entry
+struct vmbus_channel_message_table_entry
        channel_message_table[CHANNELMSG_COUNT] = {
-       {CHANNELMSG_INVALID,                    NULL},
-       {CHANNELMSG_OFFERCHANNEL,               vmbus_onoffer},
-       {CHANNELMSG_RESCIND_CHANNELOFFER,       vmbus_onoffer_rescind},
-       {CHANNELMSG_REQUESTOFFERS,              NULL},
-       {CHANNELMSG_ALLOFFERS_DELIVERED,        vmbus_onoffers_delivered},
-       {CHANNELMSG_OPENCHANNEL,                NULL},
-       {CHANNELMSG_OPENCHANNEL_RESULT, vmbus_onopen_result},
-       {CHANNELMSG_CLOSECHANNEL,               NULL},
-       {CHANNELMSG_GPADL_HEADER,               NULL},
-       {CHANNELMSG_GPADL_BODY,         NULL},
-       {CHANNELMSG_GPADL_CREATED,              vmbus_ongpadl_created},
-       {CHANNELMSG_GPADL_TEARDOWN,             NULL},
-       {CHANNELMSG_GPADL_TORNDOWN,             vmbus_ongpadl_torndown},
-       {CHANNELMSG_RELID_RELEASED,             NULL},
-       {CHANNELMSG_INITIATE_CONTACT,           NULL},
-       {CHANNELMSG_VERSION_RESPONSE,           vmbus_onversion_response},
-       {CHANNELMSG_UNLOAD,                     NULL},
+       {CHANNELMSG_INVALID,                    0, NULL},
+       {CHANNELMSG_OFFERCHANNEL,               0, vmbus_onoffer},
+       {CHANNELMSG_RESCIND_CHANNELOFFER,       0, vmbus_onoffer_rescind},
+       {CHANNELMSG_REQUESTOFFERS,              0, NULL},
+       {CHANNELMSG_ALLOFFERS_DELIVERED,        1, vmbus_onoffers_delivered},
+       {CHANNELMSG_OPENCHANNEL,                0, NULL},
+       {CHANNELMSG_OPENCHANNEL_RESULT,         1, vmbus_onopen_result},
+       {CHANNELMSG_CLOSECHANNEL,               0, NULL},
+       {CHANNELMSG_GPADL_HEADER,               0, NULL},
+       {CHANNELMSG_GPADL_BODY,                 0, NULL},
+       {CHANNELMSG_GPADL_CREATED,              1, vmbus_ongpadl_created},
+       {CHANNELMSG_GPADL_TEARDOWN,             0, NULL},
+       {CHANNELMSG_GPADL_TORNDOWN,             1, vmbus_ongpadl_torndown},
+       {CHANNELMSG_RELID_RELEASED,             0, NULL},
+       {CHANNELMSG_INITIATE_CONTACT,           0, NULL},
+       {CHANNELMSG_VERSION_RESPONSE,           1, vmbus_onversion_response},
+       {CHANNELMSG_UNLOAD,                     0, NULL},
 };
 
 /*
@@ -787,7 +749,7 @@ int vmbus_request_offers(void)
 {
        struct vmbus_channel_message_header *msg;
        struct vmbus_channel_msginfo *msginfo;
-       int ret, t;
+       int ret;
 
        msginfo = kmalloc(sizeof(*msginfo) +
                          sizeof(struct vmbus_channel_message_header),
@@ -795,8 +757,6 @@ int vmbus_request_offers(void)
        if (!msginfo)
                return -ENOMEM;
 
-       init_completion(&msginfo->waitevent);
-
        msg = (struct vmbus_channel_message_header *)msginfo->msg;
 
        msg->msgtype = CHANNELMSG_REQUESTOFFERS;
@@ -810,14 +770,6 @@ int vmbus_request_offers(void)
                goto cleanup;
        }
 
-       t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ);
-       if (t == 0) {
-               ret = -ETIMEDOUT;
-               goto cleanup;
-       }
-
-
-
 cleanup:
        kfree(msginfo);
 
@@ -826,9 +778,8 @@ cleanup:
 
 /*
  * Retrieve the (sub) channel on which to send an outgoing request.
- * When a primary channel has multiple sub-channels, we choose a
- * channel whose VCPU binding is closest to the VCPU on which
- * this call is being made.
+ * When a primary channel has multiple sub-channels, we try to
+ * distribute the load equally amongst all available channels.
  */
 struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary)
 {
@@ -836,11 +787,19 @@ struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary)
        int cur_cpu;
        struct vmbus_channel *cur_channel;
        struct vmbus_channel *outgoing_channel = primary;
-       int cpu_distance, new_cpu_distance;
+       int next_channel;
+       int i = 1;
 
        if (list_empty(&primary->sc_list))
                return outgoing_channel;
 
+       next_channel = primary->next_oc++;
+
+       if (next_channel > (primary->num_sc)) {
+               primary->next_oc = 0;
+               return outgoing_channel;
+       }
+
        cur_cpu = hv_context.vp_index[get_cpu()];
        put_cpu();
        list_for_each_safe(cur, tmp, &primary->sc_list) {
@@ -851,18 +810,10 @@ struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary)
                if (cur_channel->target_vp == cur_cpu)
                        return cur_channel;
 
-               cpu_distance = ((outgoing_channel->target_vp > cur_cpu) ?
-                               (outgoing_channel->target_vp - cur_cpu) :
-                               (cur_cpu - outgoing_channel->target_vp));
-
-               new_cpu_distance = ((cur_channel->target_vp > cur_cpu) ?
-                               (cur_channel->target_vp - cur_cpu) :
-                               (cur_cpu - cur_channel->target_vp));
-
-               if (cpu_distance < new_cpu_distance)
-                       continue;
+               if (i == next_channel)
+                       return cur_channel;
 
-               outgoing_channel = cur_channel;
+               i++;
        }
 
        return outgoing_channel;
index a63a795300b9ebbec393154fdfdce27e38ad3b0c..b27220a425f4a44b6b1143f39017998f1b77533a 100644 (file)
@@ -216,10 +216,21 @@ int vmbus_connect(void)
 
 cleanup:
        pr_err("Unable to connect to host\n");
+
        vmbus_connection.conn_state = DISCONNECTED;
+       vmbus_disconnect();
+
+       kfree(msginfo);
 
-       if (vmbus_connection.work_queue)
+       return ret;
+}
+
+void vmbus_disconnect(void)
+{
+       if (vmbus_connection.work_queue) {
+               drain_workqueue(vmbus_connection.work_queue);
                destroy_workqueue(vmbus_connection.work_queue);
+       }
 
        if (vmbus_connection.int_page) {
                free_pages((unsigned long)vmbus_connection.int_page, 0);
@@ -230,10 +241,6 @@ cleanup:
        free_pages((unsigned long)vmbus_connection.monitor_pages[1], 0);
        vmbus_connection.monitor_pages[0] = NULL;
        vmbus_connection.monitor_pages[1] = NULL;
-
-       kfree(msginfo);
-
-       return ret;
 }
 
 /*
@@ -311,10 +318,8 @@ static void process_chn_event(u32 relid)
         */
        channel = pcpu_relid2channel(relid);
 
-       if (!channel) {
-               pr_err("channel not found for relid - %u\n", relid);
+       if (!channel)
                return;
-       }
 
        /*
         * A channel once created is persistent even when there
@@ -349,10 +354,7 @@ static void process_chn_event(u32 relid)
                        else
                                bytes_to_read = 0;
                } while (read_state && (bytes_to_read != 0));
-       } else {
-               pr_err("no channel callback for relid - %u\n", relid);
        }
-
 }
 
 /*
@@ -420,6 +422,7 @@ int vmbus_post_msg(void *buffer, size_t buflen)
        union hv_connection_id conn_id;
        int ret = 0;
        int retries = 0;
+       u32 msec = 1;
 
        conn_id.asu32 = 0;
        conn_id.u.id = VMBUS_MESSAGE_CONNECTION_ID;
@@ -429,13 +432,20 @@ int vmbus_post_msg(void *buffer, size_t buflen)
         * insufficient resources. Retry the operation a couple of
         * times before giving up.
         */
-       while (retries < 10) {
+       while (retries < 20) {
                ret = hv_post_message(conn_id, 1, buffer, buflen);
 
                switch (ret) {
+               case HV_STATUS_INVALID_CONNECTION_ID:
+                       /*
+                        * We could get this if we send messages too
+                        * frequently.
+                        */
+                       ret = -EAGAIN;
+                       break;
+               case HV_STATUS_INSUFFICIENT_MEMORY:
                case HV_STATUS_INSUFFICIENT_BUFFERS:
                        ret = -ENOMEM;
-               case -ENOMEM:
                        break;
                case HV_STATUS_SUCCESS:
                        return ret;
@@ -445,7 +455,9 @@ int vmbus_post_msg(void *buffer, size_t buflen)
                }
 
                retries++;
-               msleep(100);
+               msleep(msec);
+               if (msec < 2048)
+                       msec *= 2;
        }
        return ret;
 }
index 50e51a51ff8bde317def929e744a810e2ccaa62d..d3943bceecc367c7b5241de3ba7933aae45f41c4 100644 (file)
@@ -312,7 +312,11 @@ static void hv_init_clockevent_device(struct clock_event_device *dev, int cpu)
        dev->features = CLOCK_EVT_FEAT_ONESHOT;
        dev->cpumask = cpumask_of(cpu);
        dev->rating = 1000;
-       dev->owner = THIS_MODULE;
+       /*
+        * Avoid settint dev->owner = THIS_MODULE deliberately as doing so will
+        * result in clockevents_config_and_register() taking additional
+        * references to the hv_vmbus module making it impossible to unload.
+        */
 
        dev->set_mode = hv_ce_setmode;
        dev->set_next_event = hv_ce_set_next_event;
@@ -469,6 +473,20 @@ void hv_synic_init(void *arg)
        return;
 }
 
+/*
+ * hv_synic_clockevents_cleanup - Cleanup clockevent devices
+ */
+void hv_synic_clockevents_cleanup(void)
+{
+       int cpu;
+
+       if (!(ms_hyperv.features & HV_X64_MSR_SYNTIMER_AVAILABLE))
+               return;
+
+       for_each_online_cpu(cpu)
+               clockevents_unbind_device(hv_context.clk_evt[cpu], cpu);
+}
+
 /*
  * hv_synic_cleanup - Cleanup routine for hv_synic_init().
  */
@@ -477,11 +495,17 @@ void hv_synic_cleanup(void *arg)
        union hv_synic_sint shared_sint;
        union hv_synic_simp simp;
        union hv_synic_siefp siefp;
+       union hv_synic_scontrol sctrl;
        int cpu = smp_processor_id();
 
        if (!hv_context.synic_initialized)
                return;
 
+       /* Turn off clockevent device */
+       if (ms_hyperv.features & HV_X64_MSR_SYNTIMER_AVAILABLE)
+               hv_ce_setmode(CLOCK_EVT_MODE_SHUTDOWN,
+                             hv_context.clk_evt[cpu]);
+
        rdmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
 
        shared_sint.masked = 1;
@@ -502,6 +526,10 @@ void hv_synic_cleanup(void *arg)
 
        wrmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64);
 
-       free_page((unsigned long)hv_context.synic_message_page[cpu]);
-       free_page((unsigned long)hv_context.synic_event_page[cpu]);
+       /* Disable the global synic bit */
+       rdmsrl(HV_X64_MSR_SCONTROL, sctrl.as_uint64);
+       sctrl.enable = 0;
+       wrmsrl(HV_X64_MSR_SCONTROL, sctrl.as_uint64);
+
+       hv_synic_free_cpu(cpu);
 }
index ff169386b2c716bc04c8dcd03f54ad28615cc9de..cb5b7dc9797fad344f1ddba31d80ab135bcec5a3 100644 (file)
@@ -428,14 +428,13 @@ struct dm_info_msg {
  * currently hot added. We hot add in multiples of 128M
  * chunks; it is possible that we may not be able to bring
  * online all the pages in the region. The range
- * covered_start_pfn : covered_end_pfn defines the pages that can
+ * covered_end_pfn defines the pages that can
  * be brough online.
  */
 
 struct hv_hotadd_state {
        struct list_head list;
        unsigned long start_pfn;
-       unsigned long covered_start_pfn;
        unsigned long covered_end_pfn;
        unsigned long ha_end_pfn;
        unsigned long end_pfn;
@@ -503,6 +502,8 @@ struct hv_dynmem_device {
         * Number of pages we have currently ballooned out.
         */
        unsigned int num_pages_ballooned;
+       unsigned int num_pages_onlined;
+       unsigned int num_pages_added;
 
        /*
         * State to manage the ballooning (up) operation.
@@ -534,7 +535,6 @@ struct hv_dynmem_device {
        struct task_struct *thread;
 
        struct mutex ha_region_mutex;
-       struct completion waiter_event;
 
        /*
         * A list of hot-add regions.
@@ -554,46 +554,32 @@ static struct hv_dynmem_device dm_device;
 static void post_status(struct hv_dynmem_device *dm);
 
 #ifdef CONFIG_MEMORY_HOTPLUG
-static void acquire_region_mutex(bool trylock)
-{
-       if (trylock) {
-               reinit_completion(&dm_device.waiter_event);
-               while (!mutex_trylock(&dm_device.ha_region_mutex))
-                       wait_for_completion(&dm_device.waiter_event);
-       } else {
-               mutex_lock(&dm_device.ha_region_mutex);
-       }
-}
-
-static void release_region_mutex(bool trylock)
-{
-       if (trylock) {
-               mutex_unlock(&dm_device.ha_region_mutex);
-       } else {
-               mutex_unlock(&dm_device.ha_region_mutex);
-               complete(&dm_device.waiter_event);
-       }
-}
-
 static int hv_memory_notifier(struct notifier_block *nb, unsigned long val,
                              void *v)
 {
+       struct memory_notify *mem = (struct memory_notify *)v;
+
        switch (val) {
        case MEM_GOING_ONLINE:
-               acquire_region_mutex(true);
+               mutex_lock(&dm_device.ha_region_mutex);
                break;
 
        case MEM_ONLINE:
+               dm_device.num_pages_onlined += mem->nr_pages;
        case MEM_CANCEL_ONLINE:
-               release_region_mutex(true);
+               mutex_unlock(&dm_device.ha_region_mutex);
                if (dm_device.ha_waiting) {
                        dm_device.ha_waiting = false;
                        complete(&dm_device.ol_waitevent);
                }
                break;
 
-       case MEM_GOING_OFFLINE:
        case MEM_OFFLINE:
+               mutex_lock(&dm_device.ha_region_mutex);
+               dm_device.num_pages_onlined -= mem->nr_pages;
+               mutex_unlock(&dm_device.ha_region_mutex);
+               break;
+       case MEM_GOING_OFFLINE:
        case MEM_CANCEL_OFFLINE:
                break;
        }
@@ -646,7 +632,7 @@ static void hv_mem_hot_add(unsigned long start, unsigned long size,
                init_completion(&dm_device.ol_waitevent);
                dm_device.ha_waiting = true;
 
-               release_region_mutex(false);
+               mutex_unlock(&dm_device.ha_region_mutex);
                nid = memory_add_physaddr_to_nid(PFN_PHYS(start_pfn));
                ret = add_memory(nid, PFN_PHYS((start_pfn)),
                                (HA_CHUNK << PAGE_SHIFT));
@@ -665,6 +651,7 @@ static void hv_mem_hot_add(unsigned long start, unsigned long size,
                        }
                        has->ha_end_pfn -= HA_CHUNK;
                        has->covered_end_pfn -=  processed_pfn;
+                       mutex_lock(&dm_device.ha_region_mutex);
                        break;
                }
 
@@ -675,7 +662,7 @@ static void hv_mem_hot_add(unsigned long start, unsigned long size,
                 * have not been "onlined" within the allowed time.
                 */
                wait_for_completion_timeout(&dm_device.ol_waitevent, 5*HZ);
-               acquire_region_mutex(false);
+               mutex_lock(&dm_device.ha_region_mutex);
                post_status(&dm_device);
        }
 
@@ -691,8 +678,7 @@ static void hv_online_page(struct page *pg)
 
        list_for_each(cur, &dm_device.ha_region_list) {
                has = list_entry(cur, struct hv_hotadd_state, list);
-               cur_start_pgp = (unsigned long)
-                               pfn_to_page(has->covered_start_pfn);
+               cur_start_pgp = (unsigned long)pfn_to_page(has->start_pfn);
                cur_end_pgp = (unsigned long)pfn_to_page(has->covered_end_pfn);
 
                if (((unsigned long)pg >= cur_start_pgp) &&
@@ -704,7 +690,6 @@ static void hv_online_page(struct page *pg)
                        __online_page_set_limits(pg);
                        __online_page_increment_counters(pg);
                        __online_page_free(pg);
-                       has->covered_start_pfn++;
                }
        }
 }
@@ -748,10 +733,9 @@ static bool pfn_covered(unsigned long start_pfn, unsigned long pfn_cnt)
                 * is, update it.
                 */
 
-               if (has->covered_end_pfn != start_pfn) {
+               if (has->covered_end_pfn != start_pfn)
                        has->covered_end_pfn = start_pfn;
-                       has->covered_start_pfn = start_pfn;
-               }
+
                return true;
 
        }
@@ -794,9 +778,18 @@ static unsigned long handle_pg_range(unsigned long pg_start,
                        pgs_ol = has->ha_end_pfn - start_pfn;
                        if (pgs_ol > pfn_cnt)
                                pgs_ol = pfn_cnt;
-                       hv_bring_pgs_online(start_pfn, pgs_ol);
+
+                       /*
+                        * Check if the corresponding memory block is already
+                        * online by checking its last previously backed page.
+                        * In case it is we need to bring rest (which was not
+                        * backed previously) online too.
+                        */
+                       if (start_pfn > has->start_pfn &&
+                           !PageReserved(pfn_to_page(start_pfn - 1)))
+                               hv_bring_pgs_online(start_pfn, pgs_ol);
+
                        has->covered_end_pfn +=  pgs_ol;
-                       has->covered_start_pfn +=  pgs_ol;
                        pfn_cnt -= pgs_ol;
                }
 
@@ -857,7 +850,6 @@ static unsigned long process_hot_add(unsigned long pg_start,
                list_add_tail(&ha_region->list, &dm_device.ha_region_list);
                ha_region->start_pfn = rg_start;
                ha_region->ha_end_pfn = rg_start;
-               ha_region->covered_start_pfn = pg_start;
                ha_region->covered_end_pfn = pg_start;
                ha_region->end_pfn = rg_start + rg_size;
        }
@@ -886,7 +878,7 @@ static void hot_add_req(struct work_struct *dummy)
        resp.hdr.size = sizeof(struct dm_hot_add_response);
 
 #ifdef CONFIG_MEMORY_HOTPLUG
-       acquire_region_mutex(false);
+       mutex_lock(&dm_device.ha_region_mutex);
        pg_start = dm->ha_wrk.ha_page_range.finfo.start_page;
        pfn_cnt = dm->ha_wrk.ha_page_range.finfo.page_cnt;
 
@@ -918,7 +910,9 @@ static void hot_add_req(struct work_struct *dummy)
        if (do_hot_add)
                resp.page_count = process_hot_add(pg_start, pfn_cnt,
                                                rg_start, rg_sz);
-       release_region_mutex(false);
+
+       dm->num_pages_added += resp.page_count;
+       mutex_unlock(&dm_device.ha_region_mutex);
 #endif
        /*
         * The result field of the response structure has the
@@ -982,8 +976,8 @@ static unsigned long compute_balloon_floor(void)
         *     128        72    (1/2)
         *     512       168    (1/4)
         *    2048       360    (1/8)
-        *    8192       768    (1/16)
-        *   32768      1536    (1/32)
+        *    8192       744    (1/16)
+        *   32768      1512    (1/32)
         */
        if (totalram_pages < MB2PAGES(128))
                min_pages = MB2PAGES(8) + (totalram_pages >> 1);
@@ -992,9 +986,9 @@ static unsigned long compute_balloon_floor(void)
        else if (totalram_pages < MB2PAGES(2048))
                min_pages = MB2PAGES(104) + (totalram_pages >> 3);
        else if (totalram_pages < MB2PAGES(8192))
-               min_pages = MB2PAGES(256) + (totalram_pages >> 4);
+               min_pages = MB2PAGES(232) + (totalram_pages >> 4);
        else
-               min_pages = MB2PAGES(512) + (totalram_pages >> 5);
+               min_pages = MB2PAGES(488) + (totalram_pages >> 5);
 #undef MB2PAGES
        return min_pages;
 }
@@ -1031,17 +1025,21 @@ static void post_status(struct hv_dynmem_device *dm)
        status.hdr.trans_id = atomic_inc_return(&trans_id);
 
        /*
-        * The host expects the guest to report free memory.
-        * Further, the host expects the pressure information to
-        * include the ballooned out pages.
-        * For a given amount of memory that we are managing, we
-        * need to compute a floor below which we should not balloon.
-        * Compute this and add it to the pressure report.
+        * The host expects the guest to report free and committed memory.
+        * Furthermore, the host expects the pressure information to include
+        * the ballooned out pages. For a given amount of memory that we are
+        * managing we need to compute a floor below which we should not
+        * balloon. Compute this and add it to the pressure report.
+        * We also need to report all offline pages (num_pages_added -
+        * num_pages_onlined) as committed to the host, otherwise it can try
+        * asking us to balloon them out.
         */
        status.num_avail = val.freeram;
        status.num_committed = vm_memory_committed() +
-                               dm->num_pages_ballooned +
-                               compute_balloon_floor();
+               dm->num_pages_ballooned +
+               (dm->num_pages_added > dm->num_pages_onlined ?
+                dm->num_pages_added - dm->num_pages_onlined : 0) +
+               compute_balloon_floor();
 
        /*
         * If our transaction ID is no longer current, just don't
@@ -1083,11 +1081,12 @@ static void free_balloon_pages(struct hv_dynmem_device *dm,
 
 
 
-static int  alloc_balloon_pages(struct hv_dynmem_device *dm, int num_pages,
-                        struct dm_balloon_response *bl_resp, int alloc_unit,
-                        bool *alloc_error)
+static unsigned int alloc_balloon_pages(struct hv_dynmem_device *dm,
+                                       unsigned int num_pages,
+                                       struct dm_balloon_response *bl_resp,
+                                       int alloc_unit)
 {
-       int i = 0;
+       unsigned int i = 0;
        struct page *pg;
 
        if (num_pages < alloc_unit)
@@ -1106,11 +1105,8 @@ static int  alloc_balloon_pages(struct hv_dynmem_device *dm, int num_pages,
                                __GFP_NOMEMALLOC | __GFP_NOWARN,
                                get_order(alloc_unit << PAGE_SHIFT));
 
-               if (!pg) {
-                       *alloc_error = true;
+               if (!pg)
                        return i * alloc_unit;
-               }
-
 
                dm->num_pages_ballooned += alloc_unit;
 
@@ -1137,14 +1133,15 @@ static int  alloc_balloon_pages(struct hv_dynmem_device *dm, int num_pages,
 
 static void balloon_up(struct work_struct *dummy)
 {
-       int num_pages = dm_device.balloon_wrk.num_pages;
-       int num_ballooned = 0;
+       unsigned int num_pages = dm_device.balloon_wrk.num_pages;
+       unsigned int num_ballooned = 0;
        struct dm_balloon_response *bl_resp;
        int alloc_unit;
        int ret;
-       bool alloc_error;
        bool done = false;
        int i;
+       struct sysinfo val;
+       unsigned long floor;
 
        /* The host balloons pages in 2M granularity. */
        WARN_ON_ONCE(num_pages % PAGES_IN_2M != 0);
@@ -1155,6 +1152,15 @@ static void balloon_up(struct work_struct *dummy)
         */
        alloc_unit = 512;
 
+       si_meminfo(&val);
+       floor = compute_balloon_floor();
+
+       /* Refuse to balloon below the floor, keep the 2M granularity. */
+       if (val.freeram < num_pages || val.freeram - num_pages < floor) {
+               num_pages = val.freeram > floor ? (val.freeram - floor) : 0;
+               num_pages -= num_pages % PAGES_IN_2M;
+       }
+
        while (!done) {
                bl_resp = (struct dm_balloon_response *)send_buffer;
                memset(send_buffer, 0, PAGE_SIZE);
@@ -1164,18 +1170,15 @@ static void balloon_up(struct work_struct *dummy)
 
 
                num_pages -= num_ballooned;
-               alloc_error = false;
                num_ballooned = alloc_balloon_pages(&dm_device, num_pages,
-                                               bl_resp, alloc_unit,
-                                                &alloc_error);
+                                                   bl_resp, alloc_unit);
 
                if (alloc_unit != 1 && num_ballooned == 0) {
                        alloc_unit = 1;
                        continue;
                }
 
-               if ((alloc_unit == 1 && alloc_error) ||
-                       (num_ballooned == num_pages)) {
+               if (num_ballooned == 0 || num_ballooned == num_pages) {
                        bl_resp->more_pages = 0;
                        done = true;
                        dm_device.state = DM_INITIALIZED;
@@ -1414,7 +1417,8 @@ static void balloon_onchannelcallback(void *context)
 static int balloon_probe(struct hv_device *dev,
                        const struct hv_vmbus_device_id *dev_id)
 {
-       int ret, t;
+       int ret;
+       unsigned long t;
        struct dm_version_request version_req;
        struct dm_capabilities cap_msg;
 
@@ -1439,7 +1443,6 @@ static int balloon_probe(struct hv_device *dev,
        dm_device.next_version = DYNMEM_PROTOCOL_VERSION_WIN7;
        init_completion(&dm_device.host_event);
        init_completion(&dm_device.config_event);
-       init_completion(&dm_device.waiter_event);
        INIT_LIST_HEAD(&dm_device.ha_region_list);
        mutex_init(&dm_device.ha_region_mutex);
        INIT_WORK(&dm_device.balloon_wrk.wrk, balloon_up);
index 3b9c9ef0deb8788da071344a4948c933100e9529..7994ec2e4151b085bbcb596d8ddbd4d8765b939e 100644 (file)
@@ -340,12 +340,8 @@ static int util_probe(struct hv_device *dev,
 
        set_channel_read_state(dev->channel, false);
 
-       ret = vmbus_open(dev->channel, 4 * PAGE_SIZE, 4 * PAGE_SIZE, NULL, 0,
-                       srv->util_cb, dev->channel);
-       if (ret)
-               goto error;
-
        hv_set_drvdata(dev, srv);
+
        /*
         * Based on the host; initialize the framework and
         * service version numbers we will negotiate.
@@ -365,6 +361,11 @@ static int util_probe(struct hv_device *dev,
                hb_srv_version = HB_VERSION;
        }
 
+       ret = vmbus_open(dev->channel, 4 * PAGE_SIZE, 4 * PAGE_SIZE, NULL, 0,
+                       srv->util_cb, dev->channel);
+       if (ret)
+               goto error;
+
        return 0;
 
 error:
@@ -379,9 +380,9 @@ static int util_remove(struct hv_device *dev)
 {
        struct hv_util_service *srv = hv_get_drvdata(dev);
 
-       vmbus_close(dev->channel);
        if (srv->util_deinit)
                srv->util_deinit();
+       vmbus_close(dev->channel);
        kfree(srv->recv_buffer);
 
        return 0;
index 44b1c94247129b8e1d17467b4871c919b5a2b40f..887287ad411f767dd3b7329e8494cd3a8a6d37aa 100644 (file)
@@ -49,6 +49,17 @@ enum hv_cpuid_function {
        HVCPUID_IMPLEMENTATION_LIMITS           = 0x40000005,
 };
 
+#define  HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE   0x400
+
+#define HV_X64_MSR_CRASH_P0   0x40000100
+#define HV_X64_MSR_CRASH_P1   0x40000101
+#define HV_X64_MSR_CRASH_P2   0x40000102
+#define HV_X64_MSR_CRASH_P3   0x40000103
+#define HV_X64_MSR_CRASH_P4   0x40000104
+#define HV_X64_MSR_CRASH_CTL  0x40000105
+
+#define HV_CRASH_CTL_CRASH_NOTIFY (1ULL << 63)
+
 /* Define version of the synthetic interrupt controller. */
 #define HV_SYNIC_VERSION               (1)
 
@@ -572,6 +583,8 @@ extern void hv_synic_init(void *irqarg);
 
 extern void hv_synic_cleanup(void *arg);
 
+extern void hv_synic_clockevents_cleanup(void);
+
 /*
  * Host version information.
  */
@@ -672,6 +685,23 @@ struct vmbus_msginfo {
 
 extern struct vmbus_connection vmbus_connection;
 
+enum vmbus_message_handler_type {
+       /* The related handler can sleep. */
+       VMHT_BLOCKING = 0,
+
+       /* The related handler must NOT sleep. */
+       VMHT_NON_BLOCKING = 1,
+};
+
+struct vmbus_channel_message_table_entry {
+       enum vmbus_channel_message_type message_type;
+       enum vmbus_message_handler_type handler_type;
+       void (*message_handler)(struct vmbus_channel_message_header *msg);
+};
+
+extern struct vmbus_channel_message_table_entry
+       channel_message_table[CHANNELMSG_COUNT];
+
 /* General vmbus interface */
 
 struct hv_device *vmbus_device_create(const uuid_le *type,
@@ -692,6 +722,7 @@ void vmbus_free_channels(void);
 /* Connection interface */
 
 int vmbus_connect(void);
+void vmbus_disconnect(void);
 
 int vmbus_post_msg(void *buffer, size_t buflen);
 
index f518b8d7a5b5190eb01b741d0961f6b9fbf6cd33..c85235e9f245b6d210384673168bef12c6f9f0de 100644 (file)
 #include <linux/hyperv.h>
 #include <linux/kernel_stat.h>
 #include <linux/clockchips.h>
+#include <linux/cpu.h>
 #include <asm/hyperv.h>
 #include <asm/hypervisor.h>
 #include <asm/mshyperv.h>
+#include <linux/notifier.h>
+#include <linux/ptrace.h>
 #include "hyperv_vmbus.h"
 
 static struct acpi_device  *hv_acpi_dev;
@@ -44,6 +47,31 @@ static struct tasklet_struct msg_dpc;
 static struct completion probe_event;
 static int irq;
 
+
+static int hyperv_panic_event(struct notifier_block *nb,
+                       unsigned long event, void *ptr)
+{
+       struct pt_regs *regs;
+
+       regs = current_pt_regs();
+
+       wrmsrl(HV_X64_MSR_CRASH_P0, regs->ip);
+       wrmsrl(HV_X64_MSR_CRASH_P1, regs->ax);
+       wrmsrl(HV_X64_MSR_CRASH_P2, regs->bx);
+       wrmsrl(HV_X64_MSR_CRASH_P3, regs->cx);
+       wrmsrl(HV_X64_MSR_CRASH_P4, regs->dx);
+
+       /*
+        * Let Hyper-V know there is crash data available
+        */
+       wrmsrl(HV_X64_MSR_CRASH_CTL, HV_CRASH_CTL_CRASH_NOTIFY);
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block hyperv_panic_block = {
+       .notifier_call = hyperv_panic_event,
+};
+
 struct resource hyperv_mmio = {
        .name  = "hyperv mmio",
        .flags = IORESOURCE_MEM,
@@ -507,14 +535,26 @@ static int vmbus_probe(struct device *child_device)
  */
 static int vmbus_remove(struct device *child_device)
 {
-       struct hv_driver *drv = drv_to_hv_drv(child_device->driver);
+       struct hv_driver *drv;
        struct hv_device *dev = device_to_hv_device(child_device);
-
-       if (drv->remove)
-               drv->remove(dev);
-       else
-               pr_err("remove not set for driver %s\n",
-                       dev_name(child_device));
+       u32 relid = dev->channel->offermsg.child_relid;
+
+       if (child_device->driver) {
+               drv = drv_to_hv_drv(child_device->driver);
+               if (drv->remove)
+                       drv->remove(dev);
+               else {
+                       hv_process_channel_removal(dev->channel, relid);
+                       pr_err("remove not set for driver %s\n",
+                               dev_name(child_device));
+               }
+       } else {
+               /*
+                * We don't have a driver for this device; deal with the
+                * rescind message by removing the channel.
+                */
+               hv_process_channel_removal(dev->channel, relid);
+       }
 
        return 0;
 }
@@ -573,6 +613,10 @@ static void vmbus_onmessage_work(struct work_struct *work)
 {
        struct onmessage_work_context *ctx;
 
+       /* Do not process messages if we're in DISCONNECTED state */
+       if (vmbus_connection.conn_state == DISCONNECTED)
+               return;
+
        ctx = container_of(work, struct onmessage_work_context,
                           work);
        vmbus_onmessage(&ctx->msg);
@@ -613,21 +657,36 @@ static void vmbus_on_msg_dpc(unsigned long data)
        void *page_addr = hv_context.synic_message_page[cpu];
        struct hv_message *msg = (struct hv_message *)page_addr +
                                  VMBUS_MESSAGE_SINT;
+       struct vmbus_channel_message_header *hdr;
+       struct vmbus_channel_message_table_entry *entry;
        struct onmessage_work_context *ctx;
 
        while (1) {
-               if (msg->header.message_type == HVMSG_NONE) {
+               if (msg->header.message_type == HVMSG_NONE)
                        /* no msg */
                        break;
-               } else {
+
+               hdr = (struct vmbus_channel_message_header *)msg->u.payload;
+
+               if (hdr->msgtype >= CHANNELMSG_COUNT) {
+                       WARN_ONCE(1, "unknown msgtype=%d\n", hdr->msgtype);
+                       goto msg_handled;
+               }
+
+               entry = &channel_message_table[hdr->msgtype];
+               if (entry->handler_type == VMHT_BLOCKING) {
                        ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC);
                        if (ctx == NULL)
                                continue;
+
                        INIT_WORK(&ctx->work, vmbus_onmessage_work);
                        memcpy(&ctx->msg, msg, sizeof(*msg));
+
                        queue_work(vmbus_connection.work_queue, &ctx->work);
-               }
+               } else
+                       entry->message_handler(hdr);
 
+msg_handled:
                msg->header.message_type = HVMSG_NONE;
 
                /*
@@ -704,6 +763,39 @@ static void vmbus_isr(void)
        }
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+static int hyperv_cpu_disable(void)
+{
+       return -ENOSYS;
+}
+
+static void hv_cpu_hotplug_quirk(bool vmbus_loaded)
+{
+       static void *previous_cpu_disable;
+
+       /*
+        * Offlining a CPU when running on newer hypervisors (WS2012R2, Win8,
+        * ...) is not supported at this moment as channel interrupts are
+        * distributed across all of them.
+        */
+
+       if ((vmbus_proto_version == VERSION_WS2008) ||
+           (vmbus_proto_version == VERSION_WIN7))
+               return;
+
+       if (vmbus_loaded) {
+               previous_cpu_disable = smp_ops.cpu_disable;
+               smp_ops.cpu_disable = hyperv_cpu_disable;
+               pr_notice("CPU offlining is not supported by hypervisor\n");
+       } else if (previous_cpu_disable)
+               smp_ops.cpu_disable = previous_cpu_disable;
+}
+#else
+static void hv_cpu_hotplug_quirk(bool vmbus_loaded)
+{
+}
+#endif
+
 /*
  * vmbus_bus_init -Main vmbus driver initialization routine.
  *
@@ -744,6 +836,16 @@ static int vmbus_bus_init(int irq)
        if (ret)
                goto err_alloc;
 
+       hv_cpu_hotplug_quirk(true);
+
+       /*
+        * Only register if the crash MSRs are available
+        */
+       if (ms_hyperv.features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) {
+               atomic_notifier_chain_register(&panic_notifier_list,
+                                              &hyperv_panic_block);
+       }
+
        vmbus_request_offers();
 
        return 0;
@@ -840,10 +942,8 @@ int vmbus_device_register(struct hv_device *child_device_obj)
 {
        int ret = 0;
 
-       static atomic_t device_num = ATOMIC_INIT(0);
-
-       dev_set_name(&child_device_obj->device, "vmbus_0_%d",
-                    atomic_inc_return(&device_num));
+       dev_set_name(&child_device_obj->device, "vmbus_%d",
+                    child_device_obj->channel->id);
 
        child_device_obj->device.bus = &hv_bus;
        child_device_obj->device.parent = &hv_acpi_dev->dev;
@@ -992,11 +1092,19 @@ cleanup:
 
 static void __exit vmbus_exit(void)
 {
+       int cpu;
+
+       vmbus_connection.conn_state = DISCONNECTED;
+       hv_synic_clockevents_cleanup();
        hv_remove_vmbus_irq();
        vmbus_free_channels();
        bus_unregister(&hv_bus);
        hv_cleanup();
+       for_each_online_cpu(cpu)
+               smp_call_function_single(cpu, hv_synic_cleanup, NULL, 1);
        acpi_bus_unregister_driver(&vmbus_acpi_driver);
+       hv_cpu_hotplug_quirk(false);
+       vmbus_disconnect();
 }
 
 
diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig
new file mode 100644 (file)
index 0000000..fc1f1ae
--- /dev/null
@@ -0,0 +1,61 @@
+#
+# Coresight configuration
+#
+menuconfig CORESIGHT
+       bool "CoreSight Tracing Support"
+       select ARM_AMBA
+       help
+         This framework provides a kernel interface for the CoreSight debug
+         and trace drivers to register themselves with. It's intended to build
+         a topological view of the CoreSight components based on a DT
+         specification and configure the right serie of components when a
+         trace source gets enabled.
+
+if CORESIGHT
+config CORESIGHT_LINKS_AND_SINKS
+       bool "CoreSight Link and Sink drivers"
+       help
+         This enables support for CoreSight link and sink drivers that are
+         responsible for transporting and collecting the trace data
+         respectively.  Link and sinks are dynamically aggregated with a trace
+         entity at run time to form a complete trace path.
+
+config CORESIGHT_LINK_AND_SINK_TMC
+       bool "Coresight generic TMC driver"
+       depends on CORESIGHT_LINKS_AND_SINKS
+       help
+         This enables support for the Trace Memory Controller driver.
+         Depending on its configuration the device can act as a link (embedded
+         trace router - ETR) or sink (embedded trace FIFO).  The driver
+         complies with the generic implementation of the component without
+         special enhancement or added features.
+
+config CORESIGHT_SINK_TPIU
+       bool "Coresight generic TPIU driver"
+       depends on CORESIGHT_LINKS_AND_SINKS
+       help
+         This enables support for the Trace Port Interface Unit driver,
+         responsible for bridging the gap between the on-chip coresight
+         components and a trace for bridging the gap between the on-chip
+         coresight components and a trace port collection engine, typically
+         connected to an external host for use case capturing more traces than
+         the on-board coresight memory can handle.
+
+config CORESIGHT_SINK_ETBV10
+       bool "Coresight ETBv1.0 driver"
+       depends on CORESIGHT_LINKS_AND_SINKS
+       help
+         This enables support for the Embedded Trace Buffer version 1.0 driver
+         that complies with the generic implementation of the component without
+         special enhancement or added features.
+
+config CORESIGHT_SOURCE_ETM3X
+       bool "CoreSight Embedded Trace Macrocell 3.x driver"
+       depends on !ARM64
+       select CORESIGHT_LINKS_AND_SINKS
+       help
+         This driver provides support for processor ETM3.x and PTM1.x modules,
+         which allows tracing the instructions that a processor is executing
+         This is primarily useful for instruction level tracing.  Depending
+         the ETM version data tracing may also be available.
+endif
diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
new file mode 100644 (file)
index 0000000..4b4bec8
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# Makefile for CoreSight drivers.
+#
+obj-$(CONFIG_CORESIGHT) += coresight.o
+obj-$(CONFIG_OF) += of_coresight.o
+obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o
+obj-$(CONFIG_CORESIGHT_SINK_TPIU) += coresight-tpiu.o
+obj-$(CONFIG_CORESIGHT_SINK_ETBV10) += coresight-etb10.o
+obj-$(CONFIG_CORESIGHT_LINKS_AND_SINKS) += coresight-funnel.o \
+                                          coresight-replicator.o
+obj-$(CONFIG_CORESIGHT_SOURCE_ETM3X) += coresight-etm3x.o coresight-etm-cp14.o
diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
new file mode 100644 (file)
index 0000000..4004986
--- /dev/null
@@ -0,0 +1,527 @@
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/clk.h>
+#include <linux/seq_file.h>
+#include <linux/coresight.h>
+#include <linux/amba/bus.h>
+
+#include "coresight-priv.h"
+
+#define ETB_RAM_DEPTH_REG      0x004
+#define ETB_STATUS_REG         0x00c
+#define ETB_RAM_READ_DATA_REG  0x010
+#define ETB_RAM_READ_POINTER   0x014
+#define ETB_RAM_WRITE_POINTER  0x018
+#define ETB_TRG                        0x01c
+#define ETB_CTL_REG            0x020
+#define ETB_RWD_REG            0x024
+#define ETB_FFSR               0x300
+#define ETB_FFCR               0x304
+#define ETB_ITMISCOP0          0xee0
+#define ETB_ITTRFLINACK                0xee4
+#define ETB_ITTRFLIN           0xee8
+#define ETB_ITATBDATA0         0xeeC
+#define ETB_ITATBCTR2          0xef0
+#define ETB_ITATBCTR1          0xef4
+#define ETB_ITATBCTR0          0xef8
+
+/* register description */
+/* STS - 0x00C */
+#define ETB_STATUS_RAM_FULL    BIT(0)
+/* CTL - 0x020 */
+#define ETB_CTL_CAPT_EN                BIT(0)
+/* FFCR - 0x304 */
+#define ETB_FFCR_EN_FTC                BIT(0)
+#define ETB_FFCR_FON_MAN       BIT(6)
+#define ETB_FFCR_STOP_FI       BIT(12)
+#define ETB_FFCR_STOP_TRIGGER  BIT(13)
+
+#define ETB_FFCR_BIT           6
+#define ETB_FFSR_BIT           1
+#define ETB_FRAME_SIZE_WORDS   4
+
+/**
+ * struct etb_drvdata - specifics associated to an ETB component
+ * @base:      memory mapped base address for this component.
+ * @dev:       the device entity associated to this component.
+ * @csdev:     component vitals needed by the framework.
+ * @miscdev:   specifics to handle "/dev/xyz.etb" entry.
+ * @clk:       the clock this component is associated to.
+ * @spinlock:  only one at a time pls.
+ * @in_use:    synchronise user space access to etb buffer.
+ * @buf:       area of memory where ETB buffer content gets sent.
+ * @buffer_depth: size of @buf.
+ * @enable:    this ETB is being used.
+ * @trigger_cntr: amount of words to store after a trigger.
+ */
+struct etb_drvdata {
+       void __iomem            *base;
+       struct device           *dev;
+       struct coresight_device *csdev;
+       struct miscdevice       miscdev;
+       struct clk              *clk;
+       spinlock_t              spinlock;
+       atomic_t                in_use;
+       u8                      *buf;
+       u32                     buffer_depth;
+       bool                    enable;
+       u32                     trigger_cntr;
+};
+
+static unsigned int etb_get_buffer_depth(struct etb_drvdata *drvdata)
+{
+       int ret;
+       u32 depth = 0;
+
+       ret = clk_prepare_enable(drvdata->clk);
+       if (ret)
+               return ret;
+
+       /* RO registers don't need locking */
+       depth = readl_relaxed(drvdata->base + ETB_RAM_DEPTH_REG);
+
+       clk_disable_unprepare(drvdata->clk);
+       return depth;
+}
+
+static void etb_enable_hw(struct etb_drvdata *drvdata)
+{
+       int i;
+       u32 depth;
+
+       CS_UNLOCK(drvdata->base);
+
+       depth = drvdata->buffer_depth;
+       /* reset write RAM pointer address */
+       writel_relaxed(0x0, drvdata->base + ETB_RAM_WRITE_POINTER);
+       /* clear entire RAM buffer */
+       for (i = 0; i < depth; i++)
+               writel_relaxed(0x0, drvdata->base + ETB_RWD_REG);
+
+       /* reset write RAM pointer address */
+       writel_relaxed(0x0, drvdata->base + ETB_RAM_WRITE_POINTER);
+       /* reset read RAM pointer address */
+       writel_relaxed(0x0, drvdata->base + ETB_RAM_READ_POINTER);
+
+       writel_relaxed(drvdata->trigger_cntr, drvdata->base + ETB_TRG);
+       writel_relaxed(ETB_FFCR_EN_FTC | ETB_FFCR_STOP_TRIGGER,
+                      drvdata->base + ETB_FFCR);
+       /* ETB trace capture enable */
+       writel_relaxed(ETB_CTL_CAPT_EN, drvdata->base + ETB_CTL_REG);
+
+       CS_LOCK(drvdata->base);
+}
+
+static int etb_enable(struct coresight_device *csdev)
+{
+       struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+       int ret;
+       unsigned long flags;
+
+       ret = clk_prepare_enable(drvdata->clk);
+       if (ret)
+               return ret;
+
+       spin_lock_irqsave(&drvdata->spinlock, flags);
+       etb_enable_hw(drvdata);
+       drvdata->enable = true;
+       spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+       dev_info(drvdata->dev, "ETB enabled\n");
+       return 0;
+}
+
+static void etb_disable_hw(struct etb_drvdata *drvdata)
+{
+       u32 ffcr;
+
+       CS_UNLOCK(drvdata->base);
+
+       ffcr = readl_relaxed(drvdata->base + ETB_FFCR);
+       /* stop formatter when a stop has completed */
+       ffcr |= ETB_FFCR_STOP_FI;
+       writel_relaxed(ffcr, drvdata->base + ETB_FFCR);
+       /* manually generate a flush of the system */
+       ffcr |= ETB_FFCR_FON_MAN;
+       writel_relaxed(ffcr, drvdata->base + ETB_FFCR);
+
+       if (coresight_timeout(drvdata->base, ETB_FFCR, ETB_FFCR_BIT, 0)) {
+               dev_err(drvdata->dev,
+                       "timeout observed when probing at offset %#x\n",
+                       ETB_FFCR);
+       }
+
+       /* disable trace capture */
+       writel_relaxed(0x0, drvdata->base + ETB_CTL_REG);
+
+       if (coresight_timeout(drvdata->base, ETB_FFSR, ETB_FFSR_BIT, 1)) {
+               dev_err(drvdata->dev,
+                       "timeout observed when probing at offset %#x\n",
+                       ETB_FFCR);
+       }
+
+       CS_LOCK(drvdata->base);
+}
+
+static void etb_dump_hw(struct etb_drvdata *drvdata)
+{
+       int i;
+       u8 *buf_ptr;
+       u32 read_data, depth;
+       u32 read_ptr, write_ptr;
+       u32 frame_off, frame_endoff;
+
+       CS_UNLOCK(drvdata->base);
+
+       read_ptr = readl_relaxed(drvdata->base + ETB_RAM_READ_POINTER);
+       write_ptr = readl_relaxed(drvdata->base + ETB_RAM_WRITE_POINTER);
+
+       frame_off = write_ptr % ETB_FRAME_SIZE_WORDS;
+       frame_endoff = ETB_FRAME_SIZE_WORDS - frame_off;
+       if (frame_off) {
+               dev_err(drvdata->dev,
+                       "write_ptr: %lu not aligned to formatter frame size\n",
+                       (unsigned long)write_ptr);
+               dev_err(drvdata->dev, "frameoff: %lu, frame_endoff: %lu\n",
+                       (unsigned long)frame_off, (unsigned long)frame_endoff);
+               write_ptr += frame_endoff;
+       }
+
+       if ((readl_relaxed(drvdata->base + ETB_STATUS_REG)
+                     & ETB_STATUS_RAM_FULL) == 0)
+               writel_relaxed(0x0, drvdata->base + ETB_RAM_READ_POINTER);
+       else
+               writel_relaxed(write_ptr, drvdata->base + ETB_RAM_READ_POINTER);
+
+       depth = drvdata->buffer_depth;
+       buf_ptr = drvdata->buf;
+       for (i = 0; i < depth; i++) {
+               read_data = readl_relaxed(drvdata->base +
+                                         ETB_RAM_READ_DATA_REG);
+               *buf_ptr++ = read_data >> 0;
+               *buf_ptr++ = read_data >> 8;
+               *buf_ptr++ = read_data >> 16;
+               *buf_ptr++ = read_data >> 24;
+       }
+
+       if (frame_off) {
+               buf_ptr -= (frame_endoff * 4);
+               for (i = 0; i < frame_endoff; i++) {
+                       *buf_ptr++ = 0x0;
+                       *buf_ptr++ = 0x0;
+                       *buf_ptr++ = 0x0;
+                       *buf_ptr++ = 0x0;
+               }
+       }
+
+       writel_relaxed(read_ptr, drvdata->base + ETB_RAM_READ_POINTER);
+
+       CS_LOCK(drvdata->base);
+}
+
+static void etb_disable(struct coresight_device *csdev)
+{
+       struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+       unsigned long flags;
+
+       spin_lock_irqsave(&drvdata->spinlock, flags);
+       etb_disable_hw(drvdata);
+       etb_dump_hw(drvdata);
+       drvdata->enable = false;
+       spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+       clk_disable_unprepare(drvdata->clk);
+
+       dev_info(drvdata->dev, "ETB disabled\n");
+}
+
+static const struct coresight_ops_sink etb_sink_ops = {
+       .enable         = etb_enable,
+       .disable        = etb_disable,
+};
+
+static const struct coresight_ops etb_cs_ops = {
+       .sink_ops       = &etb_sink_ops,
+};
+
+static void etb_dump(struct etb_drvdata *drvdata)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&drvdata->spinlock, flags);
+       if (drvdata->enable) {
+               etb_disable_hw(drvdata);
+               etb_dump_hw(drvdata);
+               etb_enable_hw(drvdata);
+       }
+       spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+       dev_info(drvdata->dev, "ETB dumped\n");
+}
+
+static int etb_open(struct inode *inode, struct file *file)
+{
+       struct etb_drvdata *drvdata = container_of(file->private_data,
+                                                  struct etb_drvdata, miscdev);
+
+       if (atomic_cmpxchg(&drvdata->in_use, 0, 1))
+               return -EBUSY;
+
+       dev_dbg(drvdata->dev, "%s: successfully opened\n", __func__);
+       return 0;
+}
+
+static ssize_t etb_read(struct file *file, char __user *data,
+                               size_t len, loff_t *ppos)
+{
+       u32 depth;
+       struct etb_drvdata *drvdata = container_of(file->private_data,
+                                                  struct etb_drvdata, miscdev);
+
+       etb_dump(drvdata);
+
+       depth = drvdata->buffer_depth;
+       if (*ppos + len > depth * 4)
+               len = depth * 4 - *ppos;
+
+       if (copy_to_user(data, drvdata->buf + *ppos, len)) {
+               dev_dbg(drvdata->dev, "%s: copy_to_user failed\n", __func__);
+               return -EFAULT;
+       }
+
+       *ppos += len;
+
+       dev_dbg(drvdata->dev, "%s: %zu bytes copied, %d bytes left\n",
+               __func__, len, (int)(depth * 4 - *ppos));
+       return len;
+}
+
+static int etb_release(struct inode *inode, struct file *file)
+{
+       struct etb_drvdata *drvdata = container_of(file->private_data,
+                                                  struct etb_drvdata, miscdev);
+       atomic_set(&drvdata->in_use, 0);
+
+       dev_dbg(drvdata->dev, "%s: released\n", __func__);
+       return 0;
+}
+
+static const struct file_operations etb_fops = {
+       .owner          = THIS_MODULE,
+       .open           = etb_open,
+       .read           = etb_read,
+       .release        = etb_release,
+       .llseek         = no_llseek,
+};
+
+static ssize_t status_show(struct device *dev,
+                          struct device_attribute *attr, char *buf)
+{
+       int ret;
+       unsigned long flags;
+       u32 etb_rdr, etb_sr, etb_rrp, etb_rwp;
+       u32 etb_trg, etb_cr, etb_ffsr, etb_ffcr;
+       struct etb_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = clk_prepare_enable(drvdata->clk);
+       if (ret)
+               goto out;
+
+       spin_lock_irqsave(&drvdata->spinlock, flags);
+       CS_UNLOCK(drvdata->base);
+
+       etb_rdr = readl_relaxed(drvdata->base + ETB_RAM_DEPTH_REG);
+       etb_sr = readl_relaxed(drvdata->base + ETB_STATUS_REG);
+       etb_rrp = readl_relaxed(drvdata->base + ETB_RAM_READ_POINTER);
+       etb_rwp = readl_relaxed(drvdata->base + ETB_RAM_WRITE_POINTER);
+       etb_trg = readl_relaxed(drvdata->base + ETB_TRG);
+       etb_cr = readl_relaxed(drvdata->base + ETB_CTL_REG);
+       etb_ffsr = readl_relaxed(drvdata->base + ETB_FFSR);
+       etb_ffcr = readl_relaxed(drvdata->base + ETB_FFCR);
+
+       CS_LOCK(drvdata->base);
+       spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+       clk_disable_unprepare(drvdata->clk);
+
+       return sprintf(buf,
+                      "Depth:\t\t0x%x\n"
+                      "Status:\t\t0x%x\n"
+                      "RAM read ptr:\t0x%x\n"
+                      "RAM wrt ptr:\t0x%x\n"
+                      "Trigger cnt:\t0x%x\n"
+                      "Control:\t0x%x\n"
+                      "Flush status:\t0x%x\n"
+                      "Flush ctrl:\t0x%x\n",
+                      etb_rdr, etb_sr, etb_rrp, etb_rwp,
+                      etb_trg, etb_cr, etb_ffsr, etb_ffcr);
+out:
+       return -EINVAL;
+}
+static DEVICE_ATTR_RO(status);
+
+static ssize_t trigger_cntr_show(struct device *dev,
+                           struct device_attribute *attr, char *buf)
+{
+       struct etb_drvdata *drvdata = dev_get_drvdata(dev->parent);
+       unsigned long val = drvdata->trigger_cntr;
+
+       return sprintf(buf, "%#lx\n", val);
+}
+
+static ssize_t trigger_cntr_store(struct device *dev,
+                            struct device_attribute *attr,
+                            const char *buf, size_t size)
+{
+       int ret;
+       unsigned long val;
+       struct etb_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = kstrtoul(buf, 16, &val);
+       if (ret)
+               return ret;
+
+       drvdata->trigger_cntr = val;
+       return size;
+}
+static DEVICE_ATTR_RW(trigger_cntr);
+
+static struct attribute *coresight_etb_attrs[] = {
+       &dev_attr_trigger_cntr.attr,
+       &dev_attr_status.attr,
+       NULL,
+};
+ATTRIBUTE_GROUPS(coresight_etb);
+
+static int etb_probe(struct amba_device *adev, const struct amba_id *id)
+{
+       int ret;
+       void __iomem *base;
+       struct device *dev = &adev->dev;
+       struct coresight_platform_data *pdata = NULL;
+       struct etb_drvdata *drvdata;
+       struct resource *res = &adev->res;
+       struct coresight_desc *desc;
+       struct device_node *np = adev->dev.of_node;
+
+       if (np) {
+               pdata = of_get_coresight_platform_data(dev, np);
+               if (IS_ERR(pdata))
+                       return PTR_ERR(pdata);
+               adev->dev.platform_data = pdata;
+       }
+
+       drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+       if (!drvdata)
+               return -ENOMEM;
+
+       drvdata->dev = &adev->dev;
+       dev_set_drvdata(dev, drvdata);
+
+       /* validity for the resource is already checked by the AMBA core */
+       base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       drvdata->base = base;
+
+       spin_lock_init(&drvdata->spinlock);
+
+       drvdata->clk = adev->pclk;
+       ret = clk_prepare_enable(drvdata->clk);
+       if (ret)
+               return ret;
+
+       drvdata->buffer_depth = etb_get_buffer_depth(drvdata);
+       clk_disable_unprepare(drvdata->clk);
+
+       if (drvdata->buffer_depth < 0)
+               return -EINVAL;
+
+       drvdata->buf = devm_kzalloc(dev,
+                                   drvdata->buffer_depth * 4, GFP_KERNEL);
+       if (!drvdata->buf)
+               return -ENOMEM;
+
+       desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+       if (!desc)
+               return -ENOMEM;
+
+       desc->type = CORESIGHT_DEV_TYPE_SINK;
+       desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
+       desc->ops = &etb_cs_ops;
+       desc->pdata = pdata;
+       desc->dev = dev;
+       desc->groups = coresight_etb_groups;
+       drvdata->csdev = coresight_register(desc);
+       if (IS_ERR(drvdata->csdev))
+               return PTR_ERR(drvdata->csdev);
+
+       drvdata->miscdev.name = pdata->name;
+       drvdata->miscdev.minor = MISC_DYNAMIC_MINOR;
+       drvdata->miscdev.fops = &etb_fops;
+       ret = misc_register(&drvdata->miscdev);
+       if (ret)
+               goto err_misc_register;
+
+       dev_info(dev, "ETB initialized\n");
+       return 0;
+
+err_misc_register:
+       coresight_unregister(drvdata->csdev);
+       return ret;
+}
+
+static int etb_remove(struct amba_device *adev)
+{
+       struct etb_drvdata *drvdata = amba_get_drvdata(adev);
+
+       misc_deregister(&drvdata->miscdev);
+       coresight_unregister(drvdata->csdev);
+       return 0;
+}
+
+static struct amba_id etb_ids[] = {
+       {
+               .id     = 0x0003b907,
+               .mask   = 0x0003ffff,
+       },
+       { 0, 0},
+};
+
+static struct amba_driver etb_driver = {
+       .drv = {
+               .name   = "coresight-etb10",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = etb_probe,
+       .remove         = etb_remove,
+       .id_table       = etb_ids,
+};
+
+module_amba_driver(etb_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CoreSight Embedded Trace Buffer driver");
diff --git a/drivers/hwtracing/coresight/coresight-etm-cp14.c b/drivers/hwtracing/coresight/coresight-etm-cp14.c
new file mode 100644 (file)
index 0000000..12a2206
--- /dev/null
@@ -0,0 +1,591 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/bug.h>
+#include <asm/hardware/cp14.h>
+
+#include "coresight-etm.h"
+
+int etm_readl_cp14(u32 reg, unsigned int *val)
+{
+       switch (reg) {
+       case ETMCR:
+               *val = etm_read(ETMCR);
+               return 0;
+       case ETMCCR:
+               *val = etm_read(ETMCCR);
+               return 0;
+       case ETMTRIGGER:
+               *val = etm_read(ETMTRIGGER);
+               return 0;
+       case ETMSR:
+               *val = etm_read(ETMSR);
+               return 0;
+       case ETMSCR:
+               *val = etm_read(ETMSCR);
+               return 0;
+       case ETMTSSCR:
+               *val = etm_read(ETMTSSCR);
+               return 0;
+       case ETMTEEVR:
+               *val = etm_read(ETMTEEVR);
+               return 0;
+       case ETMTECR1:
+               *val = etm_read(ETMTECR1);
+               return 0;
+       case ETMFFLR:
+               *val = etm_read(ETMFFLR);
+               return 0;
+       case ETMACVRn(0):
+               *val = etm_read(ETMACVR0);
+               return 0;
+       case ETMACVRn(1):
+               *val = etm_read(ETMACVR1);
+               return 0;
+       case ETMACVRn(2):
+               *val = etm_read(ETMACVR2);
+               return 0;
+       case ETMACVRn(3):
+               *val = etm_read(ETMACVR3);
+               return 0;
+       case ETMACVRn(4):
+               *val = etm_read(ETMACVR4);
+               return 0;
+       case ETMACVRn(5):
+               *val = etm_read(ETMACVR5);
+               return 0;
+       case ETMACVRn(6):
+               *val = etm_read(ETMACVR6);
+               return 0;
+       case ETMACVRn(7):
+               *val = etm_read(ETMACVR7);
+               return 0;
+       case ETMACVRn(8):
+               *val = etm_read(ETMACVR8);
+               return 0;
+       case ETMACVRn(9):
+               *val = etm_read(ETMACVR9);
+               return 0;
+       case ETMACVRn(10):
+               *val = etm_read(ETMACVR10);
+               return 0;
+       case ETMACVRn(11):
+               *val = etm_read(ETMACVR11);
+               return 0;
+       case ETMACVRn(12):
+               *val = etm_read(ETMACVR12);
+               return 0;
+       case ETMACVRn(13):
+               *val = etm_read(ETMACVR13);
+               return 0;
+       case ETMACVRn(14):
+               *val = etm_read(ETMACVR14);
+               return 0;
+       case ETMACVRn(15):
+               *val = etm_read(ETMACVR15);
+               return 0;
+       case ETMACTRn(0):
+               *val = etm_read(ETMACTR0);
+               return 0;
+       case ETMACTRn(1):
+               *val = etm_read(ETMACTR1);
+               return 0;
+       case ETMACTRn(2):
+               *val = etm_read(ETMACTR2);
+               return 0;
+       case ETMACTRn(3):
+               *val = etm_read(ETMACTR3);
+               return 0;
+       case ETMACTRn(4):
+               *val = etm_read(ETMACTR4);
+               return 0;
+       case ETMACTRn(5):
+               *val = etm_read(ETMACTR5);
+               return 0;
+       case ETMACTRn(6):
+               *val = etm_read(ETMACTR6);
+               return 0;
+       case ETMACTRn(7):
+               *val = etm_read(ETMACTR7);
+               return 0;
+       case ETMACTRn(8):
+               *val = etm_read(ETMACTR8);
+               return 0;
+       case ETMACTRn(9):
+               *val = etm_read(ETMACTR9);
+               return 0;
+       case ETMACTRn(10):
+               *val = etm_read(ETMACTR10);
+               return 0;
+       case ETMACTRn(11):
+               *val = etm_read(ETMACTR11);
+               return 0;
+       case ETMACTRn(12):
+               *val = etm_read(ETMACTR12);
+               return 0;
+       case ETMACTRn(13):
+               *val = etm_read(ETMACTR13);
+               return 0;
+       case ETMACTRn(14):
+               *val = etm_read(ETMACTR14);
+               return 0;
+       case ETMACTRn(15):
+               *val = etm_read(ETMACTR15);
+               return 0;
+       case ETMCNTRLDVRn(0):
+               *val = etm_read(ETMCNTRLDVR0);
+               return 0;
+       case ETMCNTRLDVRn(1):
+               *val = etm_read(ETMCNTRLDVR1);
+               return 0;
+       case ETMCNTRLDVRn(2):
+               *val = etm_read(ETMCNTRLDVR2);
+               return 0;
+       case ETMCNTRLDVRn(3):
+               *val = etm_read(ETMCNTRLDVR3);
+               return 0;
+       case ETMCNTENRn(0):
+               *val = etm_read(ETMCNTENR0);
+               return 0;
+       case ETMCNTENRn(1):
+               *val = etm_read(ETMCNTENR1);
+               return 0;
+       case ETMCNTENRn(2):
+               *val = etm_read(ETMCNTENR2);
+               return 0;
+       case ETMCNTENRn(3):
+               *val = etm_read(ETMCNTENR3);
+               return 0;
+       case ETMCNTRLDEVRn(0):
+               *val = etm_read(ETMCNTRLDEVR0);
+               return 0;
+       case ETMCNTRLDEVRn(1):
+               *val = etm_read(ETMCNTRLDEVR1);
+               return 0;
+       case ETMCNTRLDEVRn(2):
+               *val = etm_read(ETMCNTRLDEVR2);
+               return 0;
+       case ETMCNTRLDEVRn(3):
+               *val = etm_read(ETMCNTRLDEVR3);
+               return 0;
+       case ETMCNTVRn(0):
+               *val = etm_read(ETMCNTVR0);
+               return 0;
+       case ETMCNTVRn(1):
+               *val = etm_read(ETMCNTVR1);
+               return 0;
+       case ETMCNTVRn(2):
+               *val = etm_read(ETMCNTVR2);
+               return 0;
+       case ETMCNTVRn(3):
+               *val = etm_read(ETMCNTVR3);
+               return 0;
+       case ETMSQ12EVR:
+               *val = etm_read(ETMSQ12EVR);
+               return 0;
+       case ETMSQ21EVR:
+               *val = etm_read(ETMSQ21EVR);
+               return 0;
+       case ETMSQ23EVR:
+               *val = etm_read(ETMSQ23EVR);
+               return 0;
+       case ETMSQ31EVR:
+               *val = etm_read(ETMSQ31EVR);
+               return 0;
+       case ETMSQ32EVR:
+               *val = etm_read(ETMSQ32EVR);
+               return 0;
+       case ETMSQ13EVR:
+               *val = etm_read(ETMSQ13EVR);
+               return 0;
+       case ETMSQR:
+               *val = etm_read(ETMSQR);
+               return 0;
+       case ETMEXTOUTEVRn(0):
+               *val = etm_read(ETMEXTOUTEVR0);
+               return 0;
+       case ETMEXTOUTEVRn(1):
+               *val = etm_read(ETMEXTOUTEVR1);
+               return 0;
+       case ETMEXTOUTEVRn(2):
+               *val = etm_read(ETMEXTOUTEVR2);
+               return 0;
+       case ETMEXTOUTEVRn(3):
+               *val = etm_read(ETMEXTOUTEVR3);
+               return 0;
+       case ETMCIDCVRn(0):
+               *val = etm_read(ETMCIDCVR0);
+               return 0;
+       case ETMCIDCVRn(1):
+               *val = etm_read(ETMCIDCVR1);
+               return 0;
+       case ETMCIDCVRn(2):
+               *val = etm_read(ETMCIDCVR2);
+               return 0;
+       case ETMCIDCMR:
+               *val = etm_read(ETMCIDCMR);
+               return 0;
+       case ETMIMPSPEC0:
+               *val = etm_read(ETMIMPSPEC0);
+               return 0;
+       case ETMIMPSPEC1:
+               *val = etm_read(ETMIMPSPEC1);
+               return 0;
+       case ETMIMPSPEC2:
+               *val = etm_read(ETMIMPSPEC2);
+               return 0;
+       case ETMIMPSPEC3:
+               *val = etm_read(ETMIMPSPEC3);
+               return 0;
+       case ETMIMPSPEC4:
+               *val = etm_read(ETMIMPSPEC4);
+               return 0;
+       case ETMIMPSPEC5:
+               *val = etm_read(ETMIMPSPEC5);
+               return 0;
+       case ETMIMPSPEC6:
+               *val = etm_read(ETMIMPSPEC6);
+               return 0;
+       case ETMIMPSPEC7:
+               *val = etm_read(ETMIMPSPEC7);
+               return 0;
+       case ETMSYNCFR:
+               *val = etm_read(ETMSYNCFR);
+               return 0;
+       case ETMIDR:
+               *val = etm_read(ETMIDR);
+               return 0;
+       case ETMCCER:
+               *val = etm_read(ETMCCER);
+               return 0;
+       case ETMEXTINSELR:
+               *val = etm_read(ETMEXTINSELR);
+               return 0;
+       case ETMTESSEICR:
+               *val = etm_read(ETMTESSEICR);
+               return 0;
+       case ETMEIBCR:
+               *val = etm_read(ETMEIBCR);
+               return 0;
+       case ETMTSEVR:
+               *val = etm_read(ETMTSEVR);
+               return 0;
+       case ETMAUXCR:
+               *val = etm_read(ETMAUXCR);
+               return 0;
+       case ETMTRACEIDR:
+               *val = etm_read(ETMTRACEIDR);
+               return 0;
+       case ETMVMIDCVR:
+               *val = etm_read(ETMVMIDCVR);
+               return 0;
+       case ETMOSLSR:
+               *val = etm_read(ETMOSLSR);
+               return 0;
+       case ETMOSSRR:
+               *val = etm_read(ETMOSSRR);
+               return 0;
+       case ETMPDCR:
+               *val = etm_read(ETMPDCR);
+               return 0;
+       case ETMPDSR:
+               *val = etm_read(ETMPDSR);
+               return 0;
+       default:
+               *val = 0;
+               return -EINVAL;
+       }
+}
+
+int etm_writel_cp14(u32 reg, u32 val)
+{
+       switch (reg) {
+       case ETMCR:
+               etm_write(val, ETMCR);
+               break;
+       case ETMTRIGGER:
+               etm_write(val, ETMTRIGGER);
+               break;
+       case ETMSR:
+               etm_write(val, ETMSR);
+               break;
+       case ETMTSSCR:
+               etm_write(val, ETMTSSCR);
+               break;
+       case ETMTEEVR:
+               etm_write(val, ETMTEEVR);
+               break;
+       case ETMTECR1:
+               etm_write(val, ETMTECR1);
+               break;
+       case ETMFFLR:
+               etm_write(val, ETMFFLR);
+               break;
+       case ETMACVRn(0):
+               etm_write(val, ETMACVR0);
+               break;
+       case ETMACVRn(1):
+               etm_write(val, ETMACVR1);
+               break;
+       case ETMACVRn(2):
+               etm_write(val, ETMACVR2);
+               break;
+       case ETMACVRn(3):
+               etm_write(val, ETMACVR3);
+               break;
+       case ETMACVRn(4):
+               etm_write(val, ETMACVR4);
+               break;
+       case ETMACVRn(5):
+               etm_write(val, ETMACVR5);
+               break;
+       case ETMACVRn(6):
+               etm_write(val, ETMACVR6);
+               break;
+       case ETMACVRn(7):
+               etm_write(val, ETMACVR7);
+               break;
+       case ETMACVRn(8):
+               etm_write(val, ETMACVR8);
+               break;
+       case ETMACVRn(9):
+               etm_write(val, ETMACVR9);
+               break;
+       case ETMACVRn(10):
+               etm_write(val, ETMACVR10);
+               break;
+       case ETMACVRn(11):
+               etm_write(val, ETMACVR11);
+               break;
+       case ETMACVRn(12):
+               etm_write(val, ETMACVR12);
+               break;
+       case ETMACVRn(13):
+               etm_write(val, ETMACVR13);
+               break;
+       case ETMACVRn(14):
+               etm_write(val, ETMACVR14);
+               break;
+       case ETMACVRn(15):
+               etm_write(val, ETMACVR15);
+               break;
+       case ETMACTRn(0):
+               etm_write(val, ETMACTR0);
+               break;
+       case ETMACTRn(1):
+               etm_write(val, ETMACTR1);
+               break;
+       case ETMACTRn(2):
+               etm_write(val, ETMACTR2);
+               break;
+       case ETMACTRn(3):
+               etm_write(val, ETMACTR3);
+               break;
+       case ETMACTRn(4):
+               etm_write(val, ETMACTR4);
+               break;
+       case ETMACTRn(5):
+               etm_write(val, ETMACTR5);
+               break;
+       case ETMACTRn(6):
+               etm_write(val, ETMACTR6);
+               break;
+       case ETMACTRn(7):
+               etm_write(val, ETMACTR7);
+               break;
+       case ETMACTRn(8):
+               etm_write(val, ETMACTR8);
+               break;
+       case ETMACTRn(9):
+               etm_write(val, ETMACTR9);
+               break;
+       case ETMACTRn(10):
+               etm_write(val, ETMACTR10);
+               break;
+       case ETMACTRn(11):
+               etm_write(val, ETMACTR11);
+               break;
+       case ETMACTRn(12):
+               etm_write(val, ETMACTR12);
+               break;
+       case ETMACTRn(13):
+               etm_write(val, ETMACTR13);
+               break;
+       case ETMACTRn(14):
+               etm_write(val, ETMACTR14);
+               break;
+       case ETMACTRn(15):
+               etm_write(val, ETMACTR15);
+               break;
+       case ETMCNTRLDVRn(0):
+               etm_write(val, ETMCNTRLDVR0);
+               break;
+       case ETMCNTRLDVRn(1):
+               etm_write(val, ETMCNTRLDVR1);
+               break;
+       case ETMCNTRLDVRn(2):
+               etm_write(val, ETMCNTRLDVR2);
+               break;
+       case ETMCNTRLDVRn(3):
+               etm_write(val, ETMCNTRLDVR3);
+               break;
+       case ETMCNTENRn(0):
+               etm_write(val, ETMCNTENR0);
+               break;
+       case ETMCNTENRn(1):
+               etm_write(val, ETMCNTENR1);
+               break;
+       case ETMCNTENRn(2):
+               etm_write(val, ETMCNTENR2);
+               break;
+       case ETMCNTENRn(3):
+               etm_write(val, ETMCNTENR3);
+               break;
+       case ETMCNTRLDEVRn(0):
+               etm_write(val, ETMCNTRLDEVR0);
+               break;
+       case ETMCNTRLDEVRn(1):
+               etm_write(val, ETMCNTRLDEVR1);
+               break;
+       case ETMCNTRLDEVRn(2):
+               etm_write(val, ETMCNTRLDEVR2);
+               break;
+       case ETMCNTRLDEVRn(3):
+               etm_write(val, ETMCNTRLDEVR3);
+               break;
+       case ETMCNTVRn(0):
+               etm_write(val, ETMCNTVR0);
+               break;
+       case ETMCNTVRn(1):
+               etm_write(val, ETMCNTVR1);
+               break;
+       case ETMCNTVRn(2):
+               etm_write(val, ETMCNTVR2);
+               break;
+       case ETMCNTVRn(3):
+               etm_write(val, ETMCNTVR3);
+               break;
+       case ETMSQ12EVR:
+               etm_write(val, ETMSQ12EVR);
+               break;
+       case ETMSQ21EVR:
+               etm_write(val, ETMSQ21EVR);
+               break;
+       case ETMSQ23EVR:
+               etm_write(val, ETMSQ23EVR);
+               break;
+       case ETMSQ31EVR:
+               etm_write(val, ETMSQ31EVR);
+               break;
+       case ETMSQ32EVR:
+               etm_write(val, ETMSQ32EVR);
+               break;
+       case ETMSQ13EVR:
+               etm_write(val, ETMSQ13EVR);
+               break;
+       case ETMSQR:
+               etm_write(val, ETMSQR);
+               break;
+       case ETMEXTOUTEVRn(0):
+               etm_write(val, ETMEXTOUTEVR0);
+               break;
+       case ETMEXTOUTEVRn(1):
+               etm_write(val, ETMEXTOUTEVR1);
+               break;
+       case ETMEXTOUTEVRn(2):
+               etm_write(val, ETMEXTOUTEVR2);
+               break;
+       case ETMEXTOUTEVRn(3):
+               etm_write(val, ETMEXTOUTEVR3);
+               break;
+       case ETMCIDCVRn(0):
+               etm_write(val, ETMCIDCVR0);
+               break;
+       case ETMCIDCVRn(1):
+               etm_write(val, ETMCIDCVR1);
+               break;
+       case ETMCIDCVRn(2):
+               etm_write(val, ETMCIDCVR2);
+               break;
+       case ETMCIDCMR:
+               etm_write(val, ETMCIDCMR);
+               break;
+       case ETMIMPSPEC0:
+               etm_write(val, ETMIMPSPEC0);
+               break;
+       case ETMIMPSPEC1:
+               etm_write(val, ETMIMPSPEC1);
+               break;
+       case ETMIMPSPEC2:
+               etm_write(val, ETMIMPSPEC2);
+               break;
+       case ETMIMPSPEC3:
+               etm_write(val, ETMIMPSPEC3);
+               break;
+       case ETMIMPSPEC4:
+               etm_write(val, ETMIMPSPEC4);
+               break;
+       case ETMIMPSPEC5:
+               etm_write(val, ETMIMPSPEC5);
+               break;
+       case ETMIMPSPEC6:
+               etm_write(val, ETMIMPSPEC6);
+               break;
+       case ETMIMPSPEC7:
+               etm_write(val, ETMIMPSPEC7);
+               break;
+       case ETMSYNCFR:
+               etm_write(val, ETMSYNCFR);
+               break;
+       case ETMEXTINSELR:
+               etm_write(val, ETMEXTINSELR);
+               break;
+       case ETMTESSEICR:
+               etm_write(val, ETMTESSEICR);
+               break;
+       case ETMEIBCR:
+               etm_write(val, ETMEIBCR);
+               break;
+       case ETMTSEVR:
+               etm_write(val, ETMTSEVR);
+               break;
+       case ETMAUXCR:
+               etm_write(val, ETMAUXCR);
+               break;
+       case ETMTRACEIDR:
+               etm_write(val, ETMTRACEIDR);
+               break;
+       case ETMVMIDCVR:
+               etm_write(val, ETMVMIDCVR);
+               break;
+       case ETMOSLAR:
+               etm_write(val, ETMOSLAR);
+               break;
+       case ETMOSSRR:
+               etm_write(val, ETMOSSRR);
+               break;
+       case ETMPDCR:
+               etm_write(val, ETMPDCR);
+               break;
+       case ETMPDSR:
+               etm_write(val, ETMPDSR);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
diff --git a/drivers/hwtracing/coresight/coresight-etm.h b/drivers/hwtracing/coresight/coresight-etm.h
new file mode 100644 (file)
index 0000000..501c5fa
--- /dev/null
@@ -0,0 +1,251 @@
+/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CORESIGHT_CORESIGHT_ETM_H
+#define _CORESIGHT_CORESIGHT_ETM_H
+
+#include <linux/spinlock.h>
+#include "coresight-priv.h"
+
+/*
+ * Device registers:
+ * 0x000 - 0x2FC: Trace         registers
+ * 0x300 - 0x314: Management    registers
+ * 0x318 - 0xEFC: Trace         registers
+ *
+ * Coresight registers
+ * 0xF00 - 0xF9C: Management    registers
+ * 0xFA0 - 0xFA4: Management    registers in PFTv1.0
+ *                Trace         registers in PFTv1.1
+ * 0xFA8 - 0xFFC: Management    registers
+ */
+
+/* Trace registers (0x000-0x2FC) */
+#define ETMCR                  0x000
+#define ETMCCR                 0x004
+#define ETMTRIGGER             0x008
+#define ETMSR                  0x010
+#define ETMSCR                 0x014
+#define ETMTSSCR               0x018
+#define ETMTECR2               0x01c
+#define ETMTEEVR               0x020
+#define ETMTECR1               0x024
+#define ETMFFLR                        0x02c
+#define ETMACVRn(n)            (0x040 + (n * 4))
+#define ETMACTRn(n)            (0x080 + (n * 4))
+#define ETMCNTRLDVRn(n)                (0x140 + (n * 4))
+#define ETMCNTENRn(n)          (0x150 + (n * 4))
+#define ETMCNTRLDEVRn(n)       (0x160 + (n * 4))
+#define ETMCNTVRn(n)           (0x170 + (n * 4))
+#define ETMSQ12EVR             0x180
+#define ETMSQ21EVR             0x184
+#define ETMSQ23EVR             0x188
+#define ETMSQ31EVR             0x18c
+#define ETMSQ32EVR             0x190
+#define ETMSQ13EVR             0x194
+#define ETMSQR                 0x19c
+#define ETMEXTOUTEVRn(n)       (0x1a0 + (n * 4))
+#define ETMCIDCVRn(n)          (0x1b0 + (n * 4))
+#define ETMCIDCMR              0x1bc
+#define ETMIMPSPEC0            0x1c0
+#define ETMIMPSPEC1            0x1c4
+#define ETMIMPSPEC2            0x1c8
+#define ETMIMPSPEC3            0x1cc
+#define ETMIMPSPEC4            0x1d0
+#define ETMIMPSPEC5            0x1d4
+#define ETMIMPSPEC6            0x1d8
+#define ETMIMPSPEC7            0x1dc
+#define ETMSYNCFR              0x1e0
+#define ETMIDR                 0x1e4
+#define ETMCCER                        0x1e8
+#define ETMEXTINSELR           0x1ec
+#define ETMTESSEICR            0x1f0
+#define ETMEIBCR               0x1f4
+#define ETMTSEVR               0x1f8
+#define ETMAUXCR               0x1fc
+#define ETMTRACEIDR            0x200
+#define ETMVMIDCVR             0x240
+/* Management registers (0x300-0x314) */
+#define ETMOSLAR               0x300
+#define ETMOSLSR               0x304
+#define ETMOSSRR               0x308
+#define ETMPDCR                        0x310
+#define ETMPDSR                        0x314
+#define ETM_MAX_ADDR_CMP       16
+#define ETM_MAX_CNTR           4
+#define ETM_MAX_CTXID_CMP      3
+
+/* Register definition */
+/* ETMCR - 0x00 */
+#define ETMCR_PWD_DWN          BIT(0)
+#define ETMCR_STALL_MODE       BIT(7)
+#define ETMCR_ETM_PRG          BIT(10)
+#define ETMCR_ETM_EN           BIT(11)
+#define ETMCR_CYC_ACC          BIT(12)
+#define ETMCR_CTXID_SIZE       (BIT(14)|BIT(15))
+#define ETMCR_TIMESTAMP_EN     BIT(28)
+/* ETMCCR - 0x04 */
+#define ETMCCR_FIFOFULL                BIT(23)
+/* ETMPDCR - 0x310 */
+#define ETMPDCR_PWD_UP         BIT(3)
+/* ETMTECR1 - 0x024 */
+#define ETMTECR1_ADDR_COMP_1   BIT(0)
+#define ETMTECR1_INC_EXC       BIT(24)
+#define ETMTECR1_START_STOP    BIT(25)
+/* ETMCCER - 0x1E8 */
+#define ETMCCER_TIMESTAMP      BIT(22)
+
+#define ETM_MODE_EXCLUDE       BIT(0)
+#define ETM_MODE_CYCACC                BIT(1)
+#define ETM_MODE_STALL         BIT(2)
+#define ETM_MODE_TIMESTAMP     BIT(3)
+#define ETM_MODE_CTXID         BIT(4)
+#define ETM_MODE_ALL           0x1f
+
+#define ETM_SQR_MASK           0x3
+#define ETM_TRACEID_MASK       0x3f
+#define ETM_EVENT_MASK         0x1ffff
+#define ETM_SYNC_MASK          0xfff
+#define ETM_ALL_MASK           0xffffffff
+
+#define ETMSR_PROG_BIT         1
+#define ETM_SEQ_STATE_MAX_VAL  (0x2)
+#define PORT_SIZE_MASK         (GENMASK(21, 21) | GENMASK(6, 4))
+
+#define ETM_HARD_WIRE_RES_A    /* Hard wired, always true */   \
+                               ((0x0f << 0)    |               \
+                               /* Resource index A */          \
+                               (0x06 << 4))
+
+#define ETM_ADD_COMP_0         /* Single addr comparator 1 */  \
+                               ((0x00 << 7)    |               \
+                               /* Resource index B */          \
+                               (0x00 << 11))
+
+#define ETM_EVENT_NOT_A                BIT(14) /* NOT(A) */
+
+#define ETM_DEFAULT_EVENT_VAL  (ETM_HARD_WIRE_RES_A    |       \
+                                ETM_ADD_COMP_0         |       \
+                                ETM_EVENT_NOT_A)
+/**
+ * struct etm_drvdata - specifics associated to an ETM component
+ * @base:      memory mapped base address for this component.
+ * @dev:       the device entity associated to this component.
+ * @csdev:     component vitals needed by the framework.
+ * @clk:       the clock this component is associated to.
+ * @spinlock:  only one at a time pls.
+ * @cpu:       the cpu this component is affined to.
+ * @port_size: port size as reported by ETMCR bit 4-6 and 21.
+ * @arch:      ETM/PTM version number.
+ * @use_cpu14: true if management registers need to be accessed via CP14.
+ * @enable:    is this ETM/PTM currently tracing.
+ * @sticky_enable: true if ETM base configuration has been done.
+ * @boot_enable:true if we should start tracing at boot time.
+ * @os_unlock: true if access to management registers is allowed.
+ * @nr_addr_cmp:Number of pairs of address comparators as found in ETMCCR.
+ * @nr_cntr:   Number of counters as found in ETMCCR bit 13-15.
+ * @nr_ext_inp:        Number of external input as found in ETMCCR bit 17-19.
+ * @nr_ext_out:        Number of external output as found in ETMCCR bit 20-22.
+ * @nr_ctxid_cmp: Number of contextID comparators as found in ETMCCR bit 24-25.
+ * @etmccr:    value of register ETMCCR.
+ * @etmccer:   value of register ETMCCER.
+ * @traceid:   value of the current ID for this component.
+ * @mode:      controls various modes supported by this ETM/PTM.
+ * @ctrl:      used in conjunction with @mode.
+ * @trigger_event: setting for register ETMTRIGGER.
+ * @startstop_ctrl: setting for register ETMTSSCR.
+ * @enable_event: setting for register ETMTEEVR.
+ * @enable_ctrl1: setting for register ETMTECR1.
+ * @fifofull_level: setting for register ETMFFLR.
+ * @addr_idx:  index for the address comparator selection.
+ * @addr_val:  value for address comparator register.
+ * @addr_acctype: access type for address comparator register.
+ * @addr_type: current status of the comparator register.
+ * @cntr_idx:  index for the counter register selection.
+ * @cntr_rld_val: reload value of a counter register.
+ * @cntr_event:        control for counter enable register.
+ * @cntr_rld_event: value for counter reload event register.
+ * @cntr_val:  counter value register.
+ * @seq_12_event: event causing the transition from 1 to 2.
+ * @seq_21_event: event causing the transition from 2 to 1.
+ * @seq_23_event: event causing the transition from 2 to 3.
+ * @seq_31_event: event causing the transition from 3 to 1.
+ * @seq_32_event: event causing the transition from 3 to 2.
+ * @seq_13_event: event causing the transition from 1 to 3.
+ * @seq_curr_state: current value of the sequencer register.
+ * @ctxid_idx: index for the context ID registers.
+ * @ctxid_val: value for the context ID to trigger on.
+ * @ctxid_mask: mask applicable to all the context IDs.
+ * @sync_freq: Synchronisation frequency.
+ * @timestamp_event: Defines an event that requests the insertion
+                    of a timestamp into the trace stream.
+ */
+struct etm_drvdata {
+       void __iomem                    *base;
+       struct device                   *dev;
+       struct coresight_device         *csdev;
+       struct clk                      *clk;
+       spinlock_t                      spinlock;
+       int                             cpu;
+       int                             port_size;
+       u8                              arch;
+       bool                            use_cp14;
+       bool                            enable;
+       bool                            sticky_enable;
+       bool                            boot_enable;
+       bool                            os_unlock;
+       u8                              nr_addr_cmp;
+       u8                              nr_cntr;
+       u8                              nr_ext_inp;
+       u8                              nr_ext_out;
+       u8                              nr_ctxid_cmp;
+       u32                             etmccr;
+       u32                             etmccer;
+       u32                             traceid;
+       u32                             mode;
+       u32                             ctrl;
+       u32                             trigger_event;
+       u32                             startstop_ctrl;
+       u32                             enable_event;
+       u32                             enable_ctrl1;
+       u32                             fifofull_level;
+       u8                              addr_idx;
+       u32                             addr_val[ETM_MAX_ADDR_CMP];
+       u32                             addr_acctype[ETM_MAX_ADDR_CMP];
+       u32                             addr_type[ETM_MAX_ADDR_CMP];
+       u8                              cntr_idx;
+       u32                             cntr_rld_val[ETM_MAX_CNTR];
+       u32                             cntr_event[ETM_MAX_CNTR];
+       u32                             cntr_rld_event[ETM_MAX_CNTR];
+       u32                             cntr_val[ETM_MAX_CNTR];
+       u32                             seq_12_event;
+       u32                             seq_21_event;
+       u32                             seq_23_event;
+       u32                             seq_31_event;
+       u32                             seq_32_event;
+       u32                             seq_13_event;
+       u32                             seq_curr_state;
+       u8                              ctxid_idx;
+       u32                             ctxid_val[ETM_MAX_CTXID_CMP];
+       u32                             ctxid_mask;
+       u32                             sync_freq;
+       u32                             timestamp_event;
+};
+
+enum etm_addr_type {
+       ETM_ADDR_TYPE_NONE,
+       ETM_ADDR_TYPE_SINGLE,
+       ETM_ADDR_TYPE_RANGE,
+       ETM_ADDR_TYPE_START,
+       ETM_ADDR_TYPE_STOP,
+};
+#endif
diff --git a/drivers/hwtracing/coresight/coresight-etm3x.c b/drivers/hwtracing/coresight/coresight-etm3x.c
new file mode 100644 (file)
index 0000000..c965f57
--- /dev/null
@@ -0,0 +1,1932 @@
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/smp.h>
+#include <linux/sysfs.h>
+#include <linux/stat.h>
+#include <linux/clk.h>
+#include <linux/cpu.h>
+#include <linux/of.h>
+#include <linux/coresight.h>
+#include <linux/amba/bus.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
+#include <asm/sections.h>
+
+#include "coresight-etm.h"
+
+static int boot_enable;
+module_param_named(boot_enable, boot_enable, int, S_IRUGO);
+
+/* The number of ETM/PTM currently registered */
+static int etm_count;
+static struct etm_drvdata *etmdrvdata[NR_CPUS];
+
+static inline void etm_writel(struct etm_drvdata *drvdata,
+                             u32 val, u32 off)
+{
+       if (drvdata->use_cp14) {
+               if (etm_writel_cp14(off, val)) {
+                       dev_err(drvdata->dev,
+                               "invalid CP14 access to ETM reg: %#x", off);
+               }
+       } else {
+               writel_relaxed(val, drvdata->base + off);
+       }
+}
+
+static inline unsigned int etm_readl(struct etm_drvdata *drvdata, u32 off)
+{
+       u32 val;
+
+       if (drvdata->use_cp14) {
+               if (etm_readl_cp14(off, &val)) {
+                       dev_err(drvdata->dev,
+                               "invalid CP14 access to ETM reg: %#x", off);
+               }
+       } else {
+               val = readl_relaxed(drvdata->base + off);
+       }
+
+       return val;
+}
+
+/*
+ * Memory mapped writes to clear os lock are not supported on some processors
+ * and OS lock must be unlocked before any memory mapped access on such
+ * processors, otherwise memory mapped reads/writes will be invalid.
+ */
+static void etm_os_unlock(void *info)
+{
+       struct etm_drvdata *drvdata = (struct etm_drvdata *)info;
+       /* Writing any value to ETMOSLAR unlocks the trace registers */
+       etm_writel(drvdata, 0x0, ETMOSLAR);
+       isb();
+}
+
+static void etm_set_pwrdwn(struct etm_drvdata *drvdata)
+{
+       u32 etmcr;
+
+       /* Ensure pending cp14 accesses complete before setting pwrdwn */
+       mb();
+       isb();
+       etmcr = etm_readl(drvdata, ETMCR);
+       etmcr |= ETMCR_PWD_DWN;
+       etm_writel(drvdata, etmcr, ETMCR);
+}
+
+static void etm_clr_pwrdwn(struct etm_drvdata *drvdata)
+{
+       u32 etmcr;
+
+       etmcr = etm_readl(drvdata, ETMCR);
+       etmcr &= ~ETMCR_PWD_DWN;
+       etm_writel(drvdata, etmcr, ETMCR);
+       /* Ensure pwrup completes before subsequent cp14 accesses */
+       mb();
+       isb();
+}
+
+static void etm_set_pwrup(struct etm_drvdata *drvdata)
+{
+       u32 etmpdcr;
+
+       etmpdcr = readl_relaxed(drvdata->base + ETMPDCR);
+       etmpdcr |= ETMPDCR_PWD_UP;
+       writel_relaxed(etmpdcr, drvdata->base + ETMPDCR);
+       /* Ensure pwrup completes before subsequent cp14 accesses */
+       mb();
+       isb();
+}
+
+static void etm_clr_pwrup(struct etm_drvdata *drvdata)
+{
+       u32 etmpdcr;
+
+       /* Ensure pending cp14 accesses complete before clearing pwrup */
+       mb();
+       isb();
+       etmpdcr = readl_relaxed(drvdata->base + ETMPDCR);
+       etmpdcr &= ~ETMPDCR_PWD_UP;
+       writel_relaxed(etmpdcr, drvdata->base + ETMPDCR);
+}
+
+/**
+ * coresight_timeout_etm - loop until a bit has changed to a specific state.
+ * @drvdata: etm's private data structure.
+ * @offset: address of a register, starting from @addr.
+ * @position: the position of the bit of interest.
+ * @value: the value the bit should have.
+ *
+ * Basically the same as @coresight_timeout except for the register access
+ * method where we have to account for CP14 configurations.
+
+ * Return: 0 as soon as the bit has taken the desired state or -EAGAIN if
+ * TIMEOUT_US has elapsed, which ever happens first.
+ */
+
+static int coresight_timeout_etm(struct etm_drvdata *drvdata, u32 offset,
+                                 int position, int value)
+{
+       int i;
+       u32 val;
+
+       for (i = TIMEOUT_US; i > 0; i--) {
+               val = etm_readl(drvdata, offset);
+               /* Waiting on the bit to go from 0 to 1 */
+               if (value) {
+                       if (val & BIT(position))
+                               return 0;
+               /* Waiting on the bit to go from 1 to 0 */
+               } else {
+                       if (!(val & BIT(position)))
+                               return 0;
+               }
+
+               /*
+                * Delay is arbitrary - the specification doesn't say how long
+                * we are expected to wait.  Extra check required to make sure
+                * we don't wait needlessly on the last iteration.
+                */
+               if (i - 1)
+                       udelay(1);
+       }
+
+       return -EAGAIN;
+}
+
+
+static void etm_set_prog(struct etm_drvdata *drvdata)
+{
+       u32 etmcr;
+
+       etmcr = etm_readl(drvdata, ETMCR);
+       etmcr |= ETMCR_ETM_PRG;
+       etm_writel(drvdata, etmcr, ETMCR);
+       /*
+        * Recommended by spec for cp14 accesses to ensure etmcr write is
+        * complete before polling etmsr
+        */
+       isb();
+       if (coresight_timeout_etm(drvdata, ETMSR, ETMSR_PROG_BIT, 1)) {
+               dev_err(drvdata->dev,
+                       "timeout observed when probing at offset %#x\n", ETMSR);
+       }
+}
+
+static void etm_clr_prog(struct etm_drvdata *drvdata)
+{
+       u32 etmcr;
+
+       etmcr = etm_readl(drvdata, ETMCR);
+       etmcr &= ~ETMCR_ETM_PRG;
+       etm_writel(drvdata, etmcr, ETMCR);
+       /*
+        * Recommended by spec for cp14 accesses to ensure etmcr write is
+        * complete before polling etmsr
+        */
+       isb();
+       if (coresight_timeout_etm(drvdata, ETMSR, ETMSR_PROG_BIT, 0)) {
+               dev_err(drvdata->dev,
+                       "timeout observed when probing at offset %#x\n", ETMSR);
+       }
+}
+
+static void etm_set_default(struct etm_drvdata *drvdata)
+{
+       int i;
+
+       drvdata->trigger_event = ETM_DEFAULT_EVENT_VAL;
+       drvdata->enable_event = ETM_HARD_WIRE_RES_A;
+
+       drvdata->seq_12_event = ETM_DEFAULT_EVENT_VAL;
+       drvdata->seq_21_event = ETM_DEFAULT_EVENT_VAL;
+       drvdata->seq_23_event = ETM_DEFAULT_EVENT_VAL;
+       drvdata->seq_31_event = ETM_DEFAULT_EVENT_VAL;
+       drvdata->seq_32_event = ETM_DEFAULT_EVENT_VAL;
+       drvdata->seq_13_event = ETM_DEFAULT_EVENT_VAL;
+       drvdata->timestamp_event = ETM_DEFAULT_EVENT_VAL;
+
+       for (i = 0; i < drvdata->nr_cntr; i++) {
+               drvdata->cntr_rld_val[i] = 0x0;
+               drvdata->cntr_event[i] = ETM_DEFAULT_EVENT_VAL;
+               drvdata->cntr_rld_event[i] = ETM_DEFAULT_EVENT_VAL;
+               drvdata->cntr_val[i] = 0x0;
+       }
+
+       drvdata->seq_curr_state = 0x0;
+       drvdata->ctxid_idx = 0x0;
+       for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
+               drvdata->ctxid_val[i] = 0x0;
+       drvdata->ctxid_mask = 0x0;
+}
+
+static void etm_enable_hw(void *info)
+{
+       int i;
+       u32 etmcr;
+       struct etm_drvdata *drvdata = info;
+
+       CS_UNLOCK(drvdata->base);
+
+       /* Turn engine on */
+       etm_clr_pwrdwn(drvdata);
+       /* Apply power to trace registers */
+       etm_set_pwrup(drvdata);
+       /* Make sure all registers are accessible */
+       etm_os_unlock(drvdata);
+
+       etm_set_prog(drvdata);
+
+       etmcr = etm_readl(drvdata, ETMCR);
+       etmcr &= (ETMCR_PWD_DWN | ETMCR_ETM_PRG);
+       etmcr |= drvdata->port_size;
+       etm_writel(drvdata, drvdata->ctrl | etmcr, ETMCR);
+       etm_writel(drvdata, drvdata->trigger_event, ETMTRIGGER);
+       etm_writel(drvdata, drvdata->startstop_ctrl, ETMTSSCR);
+       etm_writel(drvdata, drvdata->enable_event, ETMTEEVR);
+       etm_writel(drvdata, drvdata->enable_ctrl1, ETMTECR1);
+       etm_writel(drvdata, drvdata->fifofull_level, ETMFFLR);
+       for (i = 0; i < drvdata->nr_addr_cmp; i++) {
+               etm_writel(drvdata, drvdata->addr_val[i], ETMACVRn(i));
+               etm_writel(drvdata, drvdata->addr_acctype[i], ETMACTRn(i));
+       }
+       for (i = 0; i < drvdata->nr_cntr; i++) {
+               etm_writel(drvdata, drvdata->cntr_rld_val[i], ETMCNTRLDVRn(i));
+               etm_writel(drvdata, drvdata->cntr_event[i], ETMCNTENRn(i));
+               etm_writel(drvdata, drvdata->cntr_rld_event[i],
+                          ETMCNTRLDEVRn(i));
+               etm_writel(drvdata, drvdata->cntr_val[i], ETMCNTVRn(i));
+       }
+       etm_writel(drvdata, drvdata->seq_12_event, ETMSQ12EVR);
+       etm_writel(drvdata, drvdata->seq_21_event, ETMSQ21EVR);
+       etm_writel(drvdata, drvdata->seq_23_event, ETMSQ23EVR);
+       etm_writel(drvdata, drvdata->seq_31_event, ETMSQ31EVR);
+       etm_writel(drvdata, drvdata->seq_32_event, ETMSQ32EVR);
+       etm_writel(drvdata, drvdata->seq_13_event, ETMSQ13EVR);
+       etm_writel(drvdata, drvdata->seq_curr_state, ETMSQR);
+       for (i = 0; i < drvdata->nr_ext_out; i++)
+               etm_writel(drvdata, ETM_DEFAULT_EVENT_VAL, ETMEXTOUTEVRn(i));
+       for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
+               etm_writel(drvdata, drvdata->ctxid_val[i], ETMCIDCVRn(i));
+       etm_writel(drvdata, drvdata->ctxid_mask, ETMCIDCMR);
+       etm_writel(drvdata, drvdata->sync_freq, ETMSYNCFR);
+       /* No external input selected */
+       etm_writel(drvdata, 0x0, ETMEXTINSELR);
+       etm_writel(drvdata, drvdata->timestamp_event, ETMTSEVR);
+       /* No auxiliary control selected */
+       etm_writel(drvdata, 0x0, ETMAUXCR);
+       etm_writel(drvdata, drvdata->traceid, ETMTRACEIDR);
+       /* No VMID comparator value selected */
+       etm_writel(drvdata, 0x0, ETMVMIDCVR);
+
+       /* Ensures trace output is enabled from this ETM */
+       etm_writel(drvdata, drvdata->ctrl | ETMCR_ETM_EN | etmcr, ETMCR);
+
+       etm_clr_prog(drvdata);
+       CS_LOCK(drvdata->base);
+
+       dev_dbg(drvdata->dev, "cpu: %d enable smp call done\n", drvdata->cpu);
+}
+
+static int etm_trace_id_simple(struct etm_drvdata *drvdata)
+{
+       if (!drvdata->enable)
+               return drvdata->traceid;
+
+       return (etm_readl(drvdata, ETMTRACEIDR) & ETM_TRACEID_MASK);
+}
+
+static int etm_trace_id(struct coresight_device *csdev)
+{
+       struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+       unsigned long flags;
+       int trace_id = -1;
+
+       if (!drvdata->enable)
+               return drvdata->traceid;
+
+       if (clk_prepare_enable(drvdata->clk))
+               goto out;
+
+       spin_lock_irqsave(&drvdata->spinlock, flags);
+
+       CS_UNLOCK(drvdata->base);
+       trace_id = (etm_readl(drvdata, ETMTRACEIDR) & ETM_TRACEID_MASK);
+       CS_LOCK(drvdata->base);
+
+       spin_unlock_irqrestore(&drvdata->spinlock, flags);
+       clk_disable_unprepare(drvdata->clk);
+out:
+       return trace_id;
+}
+
+static int etm_enable(struct coresight_device *csdev)
+{
+       struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+       int ret;
+
+       ret = clk_prepare_enable(drvdata->clk);
+       if (ret)
+               goto err_clk;
+
+       spin_lock(&drvdata->spinlock);
+
+       /*
+        * Configure the ETM only if the CPU is online.  If it isn't online
+        * hw configuration will take place when 'CPU_STARTING' is received
+        * in @etm_cpu_callback.
+        */
+       if (cpu_online(drvdata->cpu)) {
+               ret = smp_call_function_single(drvdata->cpu,
+                                              etm_enable_hw, drvdata, 1);
+               if (ret)
+                       goto err;
+       }
+
+       drvdata->enable = true;
+       drvdata->sticky_enable = true;
+
+       spin_unlock(&drvdata->spinlock);
+
+       dev_info(drvdata->dev, "ETM tracing enabled\n");
+       return 0;
+err:
+       spin_unlock(&drvdata->spinlock);
+       clk_disable_unprepare(drvdata->clk);
+err_clk:
+       return ret;
+}
+
+static void etm_disable_hw(void *info)
+{
+       int i;
+       struct etm_drvdata *drvdata = info;
+
+       CS_UNLOCK(drvdata->base);
+       etm_set_prog(drvdata);
+
+       /* Program trace enable to low by using always false event */
+       etm_writel(drvdata, ETM_HARD_WIRE_RES_A | ETM_EVENT_NOT_A, ETMTEEVR);
+
+       /* Read back sequencer and counters for post trace analysis */
+       drvdata->seq_curr_state = (etm_readl(drvdata, ETMSQR) & ETM_SQR_MASK);
+
+       for (i = 0; i < drvdata->nr_cntr; i++)
+               drvdata->cntr_val[i] = etm_readl(drvdata, ETMCNTVRn(i));
+
+       etm_set_pwrdwn(drvdata);
+       CS_LOCK(drvdata->base);
+
+       dev_dbg(drvdata->dev, "cpu: %d disable smp call done\n", drvdata->cpu);
+}
+
+static void etm_disable(struct coresight_device *csdev)
+{
+       struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+       /*
+        * Taking hotplug lock here protects from clocks getting disabled
+        * with tracing being left on (crash scenario) if user disable occurs
+        * after cpu online mask indicates the cpu is offline but before the
+        * DYING hotplug callback is serviced by the ETM driver.
+        */
+       get_online_cpus();
+       spin_lock(&drvdata->spinlock);
+
+       /*
+        * Executing etm_disable_hw on the cpu whose ETM is being disabled
+        * ensures that register writes occur when cpu is powered.
+        */
+       smp_call_function_single(drvdata->cpu, etm_disable_hw, drvdata, 1);
+       drvdata->enable = false;
+
+       spin_unlock(&drvdata->spinlock);
+       put_online_cpus();
+
+       clk_disable_unprepare(drvdata->clk);
+
+       dev_info(drvdata->dev, "ETM tracing disabled\n");
+}
+
+static const struct coresight_ops_source etm_source_ops = {
+       .trace_id       = etm_trace_id,
+       .enable         = etm_enable,
+       .disable        = etm_disable,
+};
+
+static const struct coresight_ops etm_cs_ops = {
+       .source_ops     = &etm_source_ops,
+};
+
+static ssize_t nr_addr_cmp_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       val = drvdata->nr_addr_cmp;
+       return sprintf(buf, "%#lx\n", val);
+}
+static DEVICE_ATTR_RO(nr_addr_cmp);
+
+static ssize_t nr_cntr_show(struct device *dev,
+                           struct device_attribute *attr, char *buf)
+{      unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       val = drvdata->nr_cntr;
+       return sprintf(buf, "%#lx\n", val);
+}
+static DEVICE_ATTR_RO(nr_cntr);
+
+static ssize_t nr_ctxid_cmp_show(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       val = drvdata->nr_ctxid_cmp;
+       return sprintf(buf, "%#lx\n", val);
+}
+static DEVICE_ATTR_RO(nr_ctxid_cmp);
+
+static ssize_t etmsr_show(struct device *dev,
+                         struct device_attribute *attr, char *buf)
+{
+       int ret;
+       unsigned long flags, val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = clk_prepare_enable(drvdata->clk);
+       if (ret)
+               return ret;
+
+       spin_lock_irqsave(&drvdata->spinlock, flags);
+       CS_UNLOCK(drvdata->base);
+
+       val = etm_readl(drvdata, ETMSR);
+
+       CS_LOCK(drvdata->base);
+       spin_unlock_irqrestore(&drvdata->spinlock, flags);
+       clk_disable_unprepare(drvdata->clk);
+
+       return sprintf(buf, "%#lx\n", val);
+}
+static DEVICE_ATTR_RO(etmsr);
+
+static ssize_t reset_store(struct device *dev,
+                          struct device_attribute *attr,
+                          const char *buf, size_t size)
+{
+       int i, ret;
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = kstrtoul(buf, 16, &val);
+       if (ret)
+               return ret;
+
+       if (val) {
+               spin_lock(&drvdata->spinlock);
+               drvdata->mode = ETM_MODE_EXCLUDE;
+               drvdata->ctrl = 0x0;
+               drvdata->trigger_event = ETM_DEFAULT_EVENT_VAL;
+               drvdata->startstop_ctrl = 0x0;
+               drvdata->addr_idx = 0x0;
+               for (i = 0; i < drvdata->nr_addr_cmp; i++) {
+                       drvdata->addr_val[i] = 0x0;
+                       drvdata->addr_acctype[i] = 0x0;
+                       drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
+               }
+               drvdata->cntr_idx = 0x0;
+
+               etm_set_default(drvdata);
+               spin_unlock(&drvdata->spinlock);
+       }
+
+       return size;
+}
+static DEVICE_ATTR_WO(reset);
+
+static ssize_t mode_show(struct device *dev,
+                        struct device_attribute *attr, char *buf)
+{
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       val = drvdata->mode;
+       return sprintf(buf, "%#lx\n", val);
+}
+
+static ssize_t mode_store(struct device *dev,
+                         struct device_attribute *attr,
+                         const char *buf, size_t size)
+{
+       int ret;
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = kstrtoul(buf, 16, &val);
+       if (ret)
+               return ret;
+
+       spin_lock(&drvdata->spinlock);
+       drvdata->mode = val & ETM_MODE_ALL;
+
+       if (drvdata->mode & ETM_MODE_EXCLUDE)
+               drvdata->enable_ctrl1 |= ETMTECR1_INC_EXC;
+       else
+               drvdata->enable_ctrl1 &= ~ETMTECR1_INC_EXC;
+
+       if (drvdata->mode & ETM_MODE_CYCACC)
+               drvdata->ctrl |= ETMCR_CYC_ACC;
+       else
+               drvdata->ctrl &= ~ETMCR_CYC_ACC;
+
+       if (drvdata->mode & ETM_MODE_STALL) {
+               if (!(drvdata->etmccr & ETMCCR_FIFOFULL)) {
+                       dev_warn(drvdata->dev, "stall mode not supported\n");
+                       ret = -EINVAL;
+                       goto err_unlock;
+               }
+               drvdata->ctrl |= ETMCR_STALL_MODE;
+        } else
+               drvdata->ctrl &= ~ETMCR_STALL_MODE;
+
+       if (drvdata->mode & ETM_MODE_TIMESTAMP) {
+               if (!(drvdata->etmccer & ETMCCER_TIMESTAMP)) {
+                       dev_warn(drvdata->dev, "timestamp not supported\n");
+                       ret = -EINVAL;
+                       goto err_unlock;
+               }
+               drvdata->ctrl |= ETMCR_TIMESTAMP_EN;
+       } else
+               drvdata->ctrl &= ~ETMCR_TIMESTAMP_EN;
+
+       if (drvdata->mode & ETM_MODE_CTXID)
+               drvdata->ctrl |= ETMCR_CTXID_SIZE;
+       else
+               drvdata->ctrl &= ~ETMCR_CTXID_SIZE;
+       spin_unlock(&drvdata->spinlock);
+
+       return size;
+
+err_unlock:
+       spin_unlock(&drvdata->spinlock);
+       return ret;
+}
+static DEVICE_ATTR_RW(mode);
+
+static ssize_t trigger_event_show(struct device *dev,
+                                 struct device_attribute *attr, char *buf)
+{
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       val = drvdata->trigger_event;
+       return sprintf(buf, "%#lx\n", val);
+}
+
+static ssize_t trigger_event_store(struct device *dev,
+                                  struct device_attribute *attr,
+                                  const char *buf, size_t size)
+{
+       int ret;
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = kstrtoul(buf, 16, &val);
+       if (ret)
+               return ret;
+
+       drvdata->trigger_event = val & ETM_EVENT_MASK;
+
+       return size;
+}
+static DEVICE_ATTR_RW(trigger_event);
+
+static ssize_t enable_event_show(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       val = drvdata->enable_event;
+       return sprintf(buf, "%#lx\n", val);
+}
+
+static ssize_t enable_event_store(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t size)
+{
+       int ret;
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = kstrtoul(buf, 16, &val);
+       if (ret)
+               return ret;
+
+       drvdata->enable_event = val & ETM_EVENT_MASK;
+
+       return size;
+}
+static DEVICE_ATTR_RW(enable_event);
+
+static ssize_t fifofull_level_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       val = drvdata->fifofull_level;
+       return sprintf(buf, "%#lx\n", val);
+}
+
+static ssize_t fifofull_level_store(struct device *dev,
+                                   struct device_attribute *attr,
+                                   const char *buf, size_t size)
+{
+       int ret;
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = kstrtoul(buf, 16, &val);
+       if (ret)
+               return ret;
+
+       drvdata->fifofull_level = val;
+
+       return size;
+}
+static DEVICE_ATTR_RW(fifofull_level);
+
+static ssize_t addr_idx_show(struct device *dev,
+                            struct device_attribute *attr, char *buf)
+{
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       val = drvdata->addr_idx;
+       return sprintf(buf, "%#lx\n", val);
+}
+
+static ssize_t addr_idx_store(struct device *dev,
+                             struct device_attribute *attr,
+                             const char *buf, size_t size)
+{
+       int ret;
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = kstrtoul(buf, 16, &val);
+       if (ret)
+               return ret;
+
+       if (val >= drvdata->nr_addr_cmp)
+               return -EINVAL;
+
+       /*
+        * Use spinlock to ensure index doesn't change while it gets
+        * dereferenced multiple times within a spinlock block elsewhere.
+        */
+       spin_lock(&drvdata->spinlock);
+       drvdata->addr_idx = val;
+       spin_unlock(&drvdata->spinlock);
+
+       return size;
+}
+static DEVICE_ATTR_RW(addr_idx);
+
+static ssize_t addr_single_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       u8 idx;
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       spin_lock(&drvdata->spinlock);
+       idx = drvdata->addr_idx;
+       if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
+             drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
+               spin_unlock(&drvdata->spinlock);
+               return -EINVAL;
+       }
+
+       val = drvdata->addr_val[idx];
+       spin_unlock(&drvdata->spinlock);
+
+       return sprintf(buf, "%#lx\n", val);
+}
+
+static ssize_t addr_single_store(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buf, size_t size)
+{
+       u8 idx;
+       int ret;
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = kstrtoul(buf, 16, &val);
+       if (ret)
+               return ret;
+
+       spin_lock(&drvdata->spinlock);
+       idx = drvdata->addr_idx;
+       if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
+             drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
+               spin_unlock(&drvdata->spinlock);
+               return -EINVAL;
+       }
+
+       drvdata->addr_val[idx] = val;
+       drvdata->addr_type[idx] = ETM_ADDR_TYPE_SINGLE;
+       spin_unlock(&drvdata->spinlock);
+
+       return size;
+}
+static DEVICE_ATTR_RW(addr_single);
+
+static ssize_t addr_range_show(struct device *dev,
+                              struct device_attribute *attr, char *buf)
+{
+       u8 idx;
+       unsigned long val1, val2;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       spin_lock(&drvdata->spinlock);
+       idx = drvdata->addr_idx;
+       if (idx % 2 != 0) {
+               spin_unlock(&drvdata->spinlock);
+               return -EPERM;
+       }
+       if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
+              drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
+             (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
+              drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
+               spin_unlock(&drvdata->spinlock);
+               return -EPERM;
+       }
+
+       val1 = drvdata->addr_val[idx];
+       val2 = drvdata->addr_val[idx + 1];
+       spin_unlock(&drvdata->spinlock);
+
+       return sprintf(buf, "%#lx %#lx\n", val1, val2);
+}
+
+static ssize_t addr_range_store(struct device *dev,
+                             struct device_attribute *attr,
+                             const char *buf, size_t size)
+{
+       u8 idx;
+       unsigned long val1, val2;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       if (sscanf(buf, "%lx %lx", &val1, &val2) != 2)
+               return -EINVAL;
+       /* Lower address comparator cannot have a higher address value */
+       if (val1 > val2)
+               return -EINVAL;
+
+       spin_lock(&drvdata->spinlock);
+       idx = drvdata->addr_idx;
+       if (idx % 2 != 0) {
+               spin_unlock(&drvdata->spinlock);
+               return -EPERM;
+       }
+       if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
+              drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
+             (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
+              drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
+               spin_unlock(&drvdata->spinlock);
+               return -EPERM;
+       }
+
+       drvdata->addr_val[idx] = val1;
+       drvdata->addr_type[idx] = ETM_ADDR_TYPE_RANGE;
+       drvdata->addr_val[idx + 1] = val2;
+       drvdata->addr_type[idx + 1] = ETM_ADDR_TYPE_RANGE;
+       drvdata->enable_ctrl1 |= (1 << (idx/2));
+       spin_unlock(&drvdata->spinlock);
+
+       return size;
+}
+static DEVICE_ATTR_RW(addr_range);
+
+static ssize_t addr_start_show(struct device *dev,
+                              struct device_attribute *attr, char *buf)
+{
+       u8 idx;
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       spin_lock(&drvdata->spinlock);
+       idx = drvdata->addr_idx;
+       if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
+             drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
+               spin_unlock(&drvdata->spinlock);
+               return -EPERM;
+       }
+
+       val = drvdata->addr_val[idx];
+       spin_unlock(&drvdata->spinlock);
+
+       return sprintf(buf, "%#lx\n", val);
+}
+
+static ssize_t addr_start_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t size)
+{
+       u8 idx;
+       int ret;
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = kstrtoul(buf, 16, &val);
+       if (ret)
+               return ret;
+
+       spin_lock(&drvdata->spinlock);
+       idx = drvdata->addr_idx;
+       if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
+             drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
+               spin_unlock(&drvdata->spinlock);
+               return -EPERM;
+       }
+
+       drvdata->addr_val[idx] = val;
+       drvdata->addr_type[idx] = ETM_ADDR_TYPE_START;
+       drvdata->startstop_ctrl |= (1 << idx);
+       drvdata->enable_ctrl1 |= BIT(25);
+       spin_unlock(&drvdata->spinlock);
+
+       return size;
+}
+static DEVICE_ATTR_RW(addr_start);
+
+static ssize_t addr_stop_show(struct device *dev,
+                             struct device_attribute *attr, char *buf)
+{
+       u8 idx;
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       spin_lock(&drvdata->spinlock);
+       idx = drvdata->addr_idx;
+       if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
+             drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
+               spin_unlock(&drvdata->spinlock);
+               return -EPERM;
+       }
+
+       val = drvdata->addr_val[idx];
+       spin_unlock(&drvdata->spinlock);
+
+       return sprintf(buf, "%#lx\n", val);
+}
+
+static ssize_t addr_stop_store(struct device *dev,
+                              struct device_attribute *attr,
+                              const char *buf, size_t size)
+{
+       u8 idx;
+       int ret;
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = kstrtoul(buf, 16, &val);
+       if (ret)
+               return ret;
+
+       spin_lock(&drvdata->spinlock);
+       idx = drvdata->addr_idx;
+       if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
+             drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
+               spin_unlock(&drvdata->spinlock);
+               return -EPERM;
+       }
+
+       drvdata->addr_val[idx] = val;
+       drvdata->addr_type[idx] = ETM_ADDR_TYPE_STOP;
+       drvdata->startstop_ctrl |= (1 << (idx + 16));
+       drvdata->enable_ctrl1 |= ETMTECR1_START_STOP;
+       spin_unlock(&drvdata->spinlock);
+
+       return size;
+}
+static DEVICE_ATTR_RW(addr_stop);
+
+static ssize_t addr_acctype_show(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       spin_lock(&drvdata->spinlock);
+       val = drvdata->addr_acctype[drvdata->addr_idx];
+       spin_unlock(&drvdata->spinlock);
+
+       return sprintf(buf, "%#lx\n", val);
+}
+
+static ssize_t addr_acctype_store(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t size)
+{
+       int ret;
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = kstrtoul(buf, 16, &val);
+       if (ret)
+               return ret;
+
+       spin_lock(&drvdata->spinlock);
+       drvdata->addr_acctype[drvdata->addr_idx] = val;
+       spin_unlock(&drvdata->spinlock);
+
+       return size;
+}
+static DEVICE_ATTR_RW(addr_acctype);
+
+static ssize_t cntr_idx_show(struct device *dev,
+                            struct device_attribute *attr, char *buf)
+{
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       val = drvdata->cntr_idx;
+       return sprintf(buf, "%#lx\n", val);
+}
+
+static ssize_t cntr_idx_store(struct device *dev,
+                             struct device_attribute *attr,
+                             const char *buf, size_t size)
+{
+       int ret;
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = kstrtoul(buf, 16, &val);
+       if (ret)
+               return ret;
+
+       if (val >= drvdata->nr_cntr)
+               return -EINVAL;
+       /*
+        * Use spinlock to ensure index doesn't change while it gets
+        * dereferenced multiple times within a spinlock block elsewhere.
+        */
+       spin_lock(&drvdata->spinlock);
+       drvdata->cntr_idx = val;
+       spin_unlock(&drvdata->spinlock);
+
+       return size;
+}
+static DEVICE_ATTR_RW(cntr_idx);
+
+static ssize_t cntr_rld_val_show(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       spin_lock(&drvdata->spinlock);
+       val = drvdata->cntr_rld_val[drvdata->cntr_idx];
+       spin_unlock(&drvdata->spinlock);
+
+       return sprintf(buf, "%#lx\n", val);
+}
+
+static ssize_t cntr_rld_val_store(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t size)
+{
+       int ret;
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = kstrtoul(buf, 16, &val);
+       if (ret)
+               return ret;
+
+       spin_lock(&drvdata->spinlock);
+       drvdata->cntr_rld_val[drvdata->cntr_idx] = val;
+       spin_unlock(&drvdata->spinlock);
+
+       return size;
+}
+static DEVICE_ATTR_RW(cntr_rld_val);
+
+static ssize_t cntr_event_show(struct device *dev,
+                              struct device_attribute *attr, char *buf)
+{
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       spin_lock(&drvdata->spinlock);
+       val = drvdata->cntr_event[drvdata->cntr_idx];
+       spin_unlock(&drvdata->spinlock);
+
+       return sprintf(buf, "%#lx\n", val);
+}
+
+static ssize_t cntr_event_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t size)
+{
+       int ret;
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = kstrtoul(buf, 16, &val);
+       if (ret)
+               return ret;
+
+       spin_lock(&drvdata->spinlock);
+       drvdata->cntr_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
+       spin_unlock(&drvdata->spinlock);
+
+       return size;
+}
+static DEVICE_ATTR_RW(cntr_event);
+
+static ssize_t cntr_rld_event_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       spin_lock(&drvdata->spinlock);
+       val = drvdata->cntr_rld_event[drvdata->cntr_idx];
+       spin_unlock(&drvdata->spinlock);
+
+       return sprintf(buf, "%#lx\n", val);
+}
+
+static ssize_t cntr_rld_event_store(struct device *dev,
+                                   struct device_attribute *attr,
+                                   const char *buf, size_t size)
+{
+       int ret;
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = kstrtoul(buf, 16, &val);
+       if (ret)
+               return ret;
+
+       spin_lock(&drvdata->spinlock);
+       drvdata->cntr_rld_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
+       spin_unlock(&drvdata->spinlock);
+
+       return size;
+}
+static DEVICE_ATTR_RW(cntr_rld_event);
+
+static ssize_t cntr_val_show(struct device *dev,
+                            struct device_attribute *attr, char *buf)
+{
+       int i, ret = 0;
+       u32 val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       if (!drvdata->enable) {
+               spin_lock(&drvdata->spinlock);
+               for (i = 0; i < drvdata->nr_cntr; i++)
+                       ret += sprintf(buf, "counter %d: %x\n",
+                                      i, drvdata->cntr_val[i]);
+               spin_unlock(&drvdata->spinlock);
+               return ret;
+       }
+
+       for (i = 0; i < drvdata->nr_cntr; i++) {
+               val = etm_readl(drvdata, ETMCNTVRn(i));
+               ret += sprintf(buf, "counter %d: %x\n", i, val);
+       }
+
+       return ret;
+}
+
+static ssize_t cntr_val_store(struct device *dev,
+                             struct device_attribute *attr,
+                             const char *buf, size_t size)
+{
+       int ret;
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = kstrtoul(buf, 16, &val);
+       if (ret)
+               return ret;
+
+       spin_lock(&drvdata->spinlock);
+       drvdata->cntr_val[drvdata->cntr_idx] = val;
+       spin_unlock(&drvdata->spinlock);
+
+       return size;
+}
+static DEVICE_ATTR_RW(cntr_val);
+
+static ssize_t seq_12_event_show(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       val = drvdata->seq_12_event;
+       return sprintf(buf, "%#lx\n", val);
+}
+
+static ssize_t seq_12_event_store(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t size)
+{
+       int ret;
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = kstrtoul(buf, 16, &val);
+       if (ret)
+               return ret;
+
+       drvdata->seq_12_event = val & ETM_EVENT_MASK;
+       return size;
+}
+static DEVICE_ATTR_RW(seq_12_event);
+
+static ssize_t seq_21_event_show(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       val = drvdata->seq_21_event;
+       return sprintf(buf, "%#lx\n", val);
+}
+
+static ssize_t seq_21_event_store(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t size)
+{
+       int ret;
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = kstrtoul(buf, 16, &val);
+       if (ret)
+               return ret;
+
+       drvdata->seq_21_event = val & ETM_EVENT_MASK;
+       return size;
+}
+static DEVICE_ATTR_RW(seq_21_event);
+
+static ssize_t seq_23_event_show(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       val = drvdata->seq_23_event;
+       return sprintf(buf, "%#lx\n", val);
+}
+
+static ssize_t seq_23_event_store(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t size)
+{
+       int ret;
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = kstrtoul(buf, 16, &val);
+       if (ret)
+               return ret;
+
+       drvdata->seq_23_event = val & ETM_EVENT_MASK;
+       return size;
+}
+static DEVICE_ATTR_RW(seq_23_event);
+
+static ssize_t seq_31_event_show(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       val = drvdata->seq_31_event;
+       return sprintf(buf, "%#lx\n", val);
+}
+
+static ssize_t seq_31_event_store(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t size)
+{
+       int ret;
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = kstrtoul(buf, 16, &val);
+       if (ret)
+               return ret;
+
+       drvdata->seq_31_event = val & ETM_EVENT_MASK;
+       return size;
+}
+static DEVICE_ATTR_RW(seq_31_event);
+
+static ssize_t seq_32_event_show(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       val = drvdata->seq_32_event;
+       return sprintf(buf, "%#lx\n", val);
+}
+
+static ssize_t seq_32_event_store(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t size)
+{
+       int ret;
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = kstrtoul(buf, 16, &val);
+       if (ret)
+               return ret;
+
+       drvdata->seq_32_event = val & ETM_EVENT_MASK;
+       return size;
+}
+static DEVICE_ATTR_RW(seq_32_event);
+
+static ssize_t seq_13_event_show(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       val = drvdata->seq_13_event;
+       return sprintf(buf, "%#lx\n", val);
+}
+
+static ssize_t seq_13_event_store(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t size)
+{
+       int ret;
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = kstrtoul(buf, 16, &val);
+       if (ret)
+               return ret;
+
+       drvdata->seq_13_event = val & ETM_EVENT_MASK;
+       return size;
+}
+static DEVICE_ATTR_RW(seq_13_event);
+
+static ssize_t seq_curr_state_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       int ret;
+       unsigned long val, flags;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       if (!drvdata->enable) {
+               val = drvdata->seq_curr_state;
+               goto out;
+       }
+
+       ret = clk_prepare_enable(drvdata->clk);
+       if (ret)
+               return ret;
+
+       spin_lock_irqsave(&drvdata->spinlock, flags);
+
+       CS_UNLOCK(drvdata->base);
+       val = (etm_readl(drvdata, ETMSQR) & ETM_SQR_MASK);
+       CS_LOCK(drvdata->base);
+
+       spin_unlock_irqrestore(&drvdata->spinlock, flags);
+       clk_disable_unprepare(drvdata->clk);
+out:
+       return sprintf(buf, "%#lx\n", val);
+}
+
+static ssize_t seq_curr_state_store(struct device *dev,
+                                   struct device_attribute *attr,
+                                   const char *buf, size_t size)
+{
+       int ret;
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = kstrtoul(buf, 16, &val);
+       if (ret)
+               return ret;
+
+       if (val > ETM_SEQ_STATE_MAX_VAL)
+               return -EINVAL;
+
+       drvdata->seq_curr_state = val;
+
+       return size;
+}
+static DEVICE_ATTR_RW(seq_curr_state);
+
+static ssize_t ctxid_idx_show(struct device *dev,
+                             struct device_attribute *attr, char *buf)
+{
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       val = drvdata->ctxid_idx;
+       return sprintf(buf, "%#lx\n", val);
+}
+
+static ssize_t ctxid_idx_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t size)
+{
+       int ret;
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = kstrtoul(buf, 16, &val);
+       if (ret)
+               return ret;
+
+       if (val >= drvdata->nr_ctxid_cmp)
+               return -EINVAL;
+
+       /*
+        * Use spinlock to ensure index doesn't change while it gets
+        * dereferenced multiple times within a spinlock block elsewhere.
+        */
+       spin_lock(&drvdata->spinlock);
+       drvdata->ctxid_idx = val;
+       spin_unlock(&drvdata->spinlock);
+
+       return size;
+}
+static DEVICE_ATTR_RW(ctxid_idx);
+
+static ssize_t ctxid_val_show(struct device *dev,
+                             struct device_attribute *attr, char *buf)
+{
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       spin_lock(&drvdata->spinlock);
+       val = drvdata->ctxid_val[drvdata->ctxid_idx];
+       spin_unlock(&drvdata->spinlock);
+
+       return sprintf(buf, "%#lx\n", val);
+}
+
+static ssize_t ctxid_val_store(struct device *dev,
+                              struct device_attribute *attr,
+                              const char *buf, size_t size)
+{
+       int ret;
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = kstrtoul(buf, 16, &val);
+       if (ret)
+               return ret;
+
+       spin_lock(&drvdata->spinlock);
+       drvdata->ctxid_val[drvdata->ctxid_idx] = val;
+       spin_unlock(&drvdata->spinlock);
+
+       return size;
+}
+static DEVICE_ATTR_RW(ctxid_val);
+
+static ssize_t ctxid_mask_show(struct device *dev,
+                              struct device_attribute *attr, char *buf)
+{
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       val = drvdata->ctxid_mask;
+       return sprintf(buf, "%#lx\n", val);
+}
+
+static ssize_t ctxid_mask_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t size)
+{
+       int ret;
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = kstrtoul(buf, 16, &val);
+       if (ret)
+               return ret;
+
+       drvdata->ctxid_mask = val;
+       return size;
+}
+static DEVICE_ATTR_RW(ctxid_mask);
+
+static ssize_t sync_freq_show(struct device *dev,
+                             struct device_attribute *attr, char *buf)
+{
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       val = drvdata->sync_freq;
+       return sprintf(buf, "%#lx\n", val);
+}
+
+static ssize_t sync_freq_store(struct device *dev,
+                              struct device_attribute *attr,
+                              const char *buf, size_t size)
+{
+       int ret;
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = kstrtoul(buf, 16, &val);
+       if (ret)
+               return ret;
+
+       drvdata->sync_freq = val & ETM_SYNC_MASK;
+       return size;
+}
+static DEVICE_ATTR_RW(sync_freq);
+
+static ssize_t timestamp_event_show(struct device *dev,
+                                   struct device_attribute *attr, char *buf)
+{
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       val = drvdata->timestamp_event;
+       return sprintf(buf, "%#lx\n", val);
+}
+
+static ssize_t timestamp_event_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t size)
+{
+       int ret;
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = kstrtoul(buf, 16, &val);
+       if (ret)
+               return ret;
+
+       drvdata->timestamp_event = val & ETM_EVENT_MASK;
+       return size;
+}
+static DEVICE_ATTR_RW(timestamp_event);
+
+static ssize_t status_show(struct device *dev,
+                          struct device_attribute *attr, char *buf)
+{
+       int ret;
+       unsigned long flags;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = clk_prepare_enable(drvdata->clk);
+       if (ret)
+               return ret;
+
+       spin_lock_irqsave(&drvdata->spinlock, flags);
+
+       CS_UNLOCK(drvdata->base);
+       ret = sprintf(buf,
+                     "ETMCCR: 0x%08x\n"
+                     "ETMCCER: 0x%08x\n"
+                     "ETMSCR: 0x%08x\n"
+                     "ETMIDR: 0x%08x\n"
+                     "ETMCR: 0x%08x\n"
+                     "ETMTRACEIDR: 0x%08x\n"
+                     "Enable event: 0x%08x\n"
+                     "Enable start/stop: 0x%08x\n"
+                     "Enable control: CR1 0x%08x CR2 0x%08x\n"
+                     "CPU affinity: %d\n",
+                     drvdata->etmccr, drvdata->etmccer,
+                     etm_readl(drvdata, ETMSCR), etm_readl(drvdata, ETMIDR),
+                     etm_readl(drvdata, ETMCR), etm_trace_id_simple(drvdata),
+                     etm_readl(drvdata, ETMTEEVR),
+                     etm_readl(drvdata, ETMTSSCR),
+                     etm_readl(drvdata, ETMTECR1),
+                     etm_readl(drvdata, ETMTECR2),
+                     drvdata->cpu);
+       CS_LOCK(drvdata->base);
+
+       spin_unlock_irqrestore(&drvdata->spinlock, flags);
+       clk_disable_unprepare(drvdata->clk);
+
+       return ret;
+}
+static DEVICE_ATTR_RO(status);
+
+static ssize_t traceid_show(struct device *dev,
+                           struct device_attribute *attr, char *buf)
+{
+       int ret;
+       unsigned long val, flags;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       if (!drvdata->enable) {
+               val = drvdata->traceid;
+               goto out;
+       }
+
+       ret = clk_prepare_enable(drvdata->clk);
+       if (ret)
+               return ret;
+
+       spin_lock_irqsave(&drvdata->spinlock, flags);
+       CS_UNLOCK(drvdata->base);
+
+       val = (etm_readl(drvdata, ETMTRACEIDR) & ETM_TRACEID_MASK);
+
+       CS_LOCK(drvdata->base);
+       spin_unlock_irqrestore(&drvdata->spinlock, flags);
+       clk_disable_unprepare(drvdata->clk);
+out:
+       return sprintf(buf, "%#lx\n", val);
+}
+
+static ssize_t traceid_store(struct device *dev,
+                            struct device_attribute *attr,
+                            const char *buf, size_t size)
+{
+       int ret;
+       unsigned long val;
+       struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = kstrtoul(buf, 16, &val);
+       if (ret)
+               return ret;
+
+       drvdata->traceid = val & ETM_TRACEID_MASK;
+       return size;
+}
+static DEVICE_ATTR_RW(traceid);
+
+static struct attribute *coresight_etm_attrs[] = {
+       &dev_attr_nr_addr_cmp.attr,
+       &dev_attr_nr_cntr.attr,
+       &dev_attr_nr_ctxid_cmp.attr,
+       &dev_attr_etmsr.attr,
+       &dev_attr_reset.attr,
+       &dev_attr_mode.attr,
+       &dev_attr_trigger_event.attr,
+       &dev_attr_enable_event.attr,
+       &dev_attr_fifofull_level.attr,
+       &dev_attr_addr_idx.attr,
+       &dev_attr_addr_single.attr,
+       &dev_attr_addr_range.attr,
+       &dev_attr_addr_start.attr,
+       &dev_attr_addr_stop.attr,
+       &dev_attr_addr_acctype.attr,
+       &dev_attr_cntr_idx.attr,
+       &dev_attr_cntr_rld_val.attr,
+       &dev_attr_cntr_event.attr,
+       &dev_attr_cntr_rld_event.attr,
+       &dev_attr_cntr_val.attr,
+       &dev_attr_seq_12_event.attr,
+       &dev_attr_seq_21_event.attr,
+       &dev_attr_seq_23_event.attr,
+       &dev_attr_seq_31_event.attr,
+       &dev_attr_seq_32_event.attr,
+       &dev_attr_seq_13_event.attr,
+       &dev_attr_seq_curr_state.attr,
+       &dev_attr_ctxid_idx.attr,
+       &dev_attr_ctxid_val.attr,
+       &dev_attr_ctxid_mask.attr,
+       &dev_attr_sync_freq.attr,
+       &dev_attr_timestamp_event.attr,
+       &dev_attr_status.attr,
+       &dev_attr_traceid.attr,
+       NULL,
+};
+ATTRIBUTE_GROUPS(coresight_etm);
+
+static int etm_cpu_callback(struct notifier_block *nfb, unsigned long action,
+                           void *hcpu)
+{
+       unsigned int cpu = (unsigned long)hcpu;
+
+       if (!etmdrvdata[cpu])
+               goto out;
+
+       switch (action & (~CPU_TASKS_FROZEN)) {
+       case CPU_STARTING:
+               spin_lock(&etmdrvdata[cpu]->spinlock);
+               if (!etmdrvdata[cpu]->os_unlock) {
+                       etm_os_unlock(etmdrvdata[cpu]);
+                       etmdrvdata[cpu]->os_unlock = true;
+               }
+
+               if (etmdrvdata[cpu]->enable)
+                       etm_enable_hw(etmdrvdata[cpu]);
+               spin_unlock(&etmdrvdata[cpu]->spinlock);
+               break;
+
+       case CPU_ONLINE:
+               if (etmdrvdata[cpu]->boot_enable &&
+                   !etmdrvdata[cpu]->sticky_enable)
+                       coresight_enable(etmdrvdata[cpu]->csdev);
+               break;
+
+       case CPU_DYING:
+               spin_lock(&etmdrvdata[cpu]->spinlock);
+               if (etmdrvdata[cpu]->enable)
+                       etm_disable_hw(etmdrvdata[cpu]);
+               spin_unlock(&etmdrvdata[cpu]->spinlock);
+               break;
+       }
+out:
+       return NOTIFY_OK;
+}
+
+static struct notifier_block etm_cpu_notifier = {
+       .notifier_call = etm_cpu_callback,
+};
+
+static bool etm_arch_supported(u8 arch)
+{
+       switch (arch) {
+       case ETM_ARCH_V3_3:
+               break;
+       case ETM_ARCH_V3_5:
+               break;
+       case PFT_ARCH_V1_0:
+               break;
+       case PFT_ARCH_V1_1:
+               break;
+       default:
+               return false;
+       }
+       return true;
+}
+
+static void etm_init_arch_data(void *info)
+{
+       u32 etmidr;
+       u32 etmccr;
+       struct etm_drvdata *drvdata = info;
+
+       CS_UNLOCK(drvdata->base);
+
+       /* First dummy read */
+       (void)etm_readl(drvdata, ETMPDSR);
+       /* Provide power to ETM: ETMPDCR[3] == 1 */
+       etm_set_pwrup(drvdata);
+       /*
+        * Clear power down bit since when this bit is set writes to
+        * certain registers might be ignored.
+        */
+       etm_clr_pwrdwn(drvdata);
+       /*
+        * Set prog bit. It will be set from reset but this is included to
+        * ensure it is set
+        */
+       etm_set_prog(drvdata);
+
+       /* Find all capabilities */
+       etmidr = etm_readl(drvdata, ETMIDR);
+       drvdata->arch = BMVAL(etmidr, 4, 11);
+       drvdata->port_size = etm_readl(drvdata, ETMCR) & PORT_SIZE_MASK;
+
+       drvdata->etmccer = etm_readl(drvdata, ETMCCER);
+       etmccr = etm_readl(drvdata, ETMCCR);
+       drvdata->etmccr = etmccr;
+       drvdata->nr_addr_cmp = BMVAL(etmccr, 0, 3) * 2;
+       drvdata->nr_cntr = BMVAL(etmccr, 13, 15);
+       drvdata->nr_ext_inp = BMVAL(etmccr, 17, 19);
+       drvdata->nr_ext_out = BMVAL(etmccr, 20, 22);
+       drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
+
+       etm_set_pwrdwn(drvdata);
+       etm_clr_pwrup(drvdata);
+       CS_LOCK(drvdata->base);
+}
+
+static void etm_init_default_data(struct etm_drvdata *drvdata)
+{
+       /*
+        * A trace ID of value 0 is invalid, so let's start at some
+        * random value that fits in 7 bits and will be just as good.
+        */
+       static int etm3x_traceid = 0x10;
+
+       u32 flags = (1 << 0 | /* instruction execute*/
+                    3 << 3 | /* ARM instruction */
+                    0 << 5 | /* No data value comparison */
+                    0 << 7 | /* No exact mach */
+                    0 << 8 | /* Ignore context ID */
+                    0 << 10); /* Security ignored */
+
+       /*
+        * Initial configuration only - guarantees sources handled by
+        * this driver have a unique ID at startup time but not between
+        * all other types of sources.  For that we lean on the core
+        * framework.
+        */
+       drvdata->traceid = etm3x_traceid++;
+       drvdata->ctrl = (ETMCR_CYC_ACC | ETMCR_TIMESTAMP_EN);
+       drvdata->enable_ctrl1 = ETMTECR1_ADDR_COMP_1;
+       if (drvdata->nr_addr_cmp >= 2) {
+               drvdata->addr_val[0] = (u32) _stext;
+               drvdata->addr_val[1] = (u32) _etext;
+               drvdata->addr_acctype[0] = flags;
+               drvdata->addr_acctype[1] = flags;
+               drvdata->addr_type[0] = ETM_ADDR_TYPE_RANGE;
+               drvdata->addr_type[1] = ETM_ADDR_TYPE_RANGE;
+       }
+
+       etm_set_default(drvdata);
+}
+
+static int etm_probe(struct amba_device *adev, const struct amba_id *id)
+{
+       int ret;
+       void __iomem *base;
+       struct device *dev = &adev->dev;
+       struct coresight_platform_data *pdata = NULL;
+       struct etm_drvdata *drvdata;
+       struct resource *res = &adev->res;
+       struct coresight_desc *desc;
+       struct device_node *np = adev->dev.of_node;
+
+       desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+       if (!desc)
+               return -ENOMEM;
+
+       drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+       if (!drvdata)
+               return -ENOMEM;
+
+       if (np) {
+               pdata = of_get_coresight_platform_data(dev, np);
+               if (IS_ERR(pdata))
+                       return PTR_ERR(pdata);
+
+               adev->dev.platform_data = pdata;
+               drvdata->use_cp14 = of_property_read_bool(np, "arm,cp14");
+       }
+
+       drvdata->dev = &adev->dev;
+       dev_set_drvdata(dev, drvdata);
+
+       /* Validity for the resource is already checked by the AMBA core */
+       base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       drvdata->base = base;
+
+       spin_lock_init(&drvdata->spinlock);
+
+       drvdata->clk = adev->pclk;
+       ret = clk_prepare_enable(drvdata->clk);
+       if (ret)
+               return ret;
+
+       drvdata->cpu = pdata ? pdata->cpu : 0;
+
+       get_online_cpus();
+       etmdrvdata[drvdata->cpu] = drvdata;
+
+       if (!smp_call_function_single(drvdata->cpu, etm_os_unlock, drvdata, 1))
+               drvdata->os_unlock = true;
+
+       if (smp_call_function_single(drvdata->cpu,
+                                    etm_init_arch_data,  drvdata, 1))
+               dev_err(dev, "ETM arch init failed\n");
+
+       if (!etm_count++)
+               register_hotcpu_notifier(&etm_cpu_notifier);
+
+       put_online_cpus();
+
+       if (etm_arch_supported(drvdata->arch) == false) {
+               ret = -EINVAL;
+               goto err_arch_supported;
+       }
+       etm_init_default_data(drvdata);
+
+       clk_disable_unprepare(drvdata->clk);
+
+       desc->type = CORESIGHT_DEV_TYPE_SOURCE;
+       desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
+       desc->ops = &etm_cs_ops;
+       desc->pdata = pdata;
+       desc->dev = dev;
+       desc->groups = coresight_etm_groups;
+       drvdata->csdev = coresight_register(desc);
+       if (IS_ERR(drvdata->csdev)) {
+               ret = PTR_ERR(drvdata->csdev);
+               goto err_arch_supported;
+       }
+
+       dev_info(dev, "ETM initialized\n");
+
+       if (boot_enable) {
+               coresight_enable(drvdata->csdev);
+               drvdata->boot_enable = true;
+       }
+
+       return 0;
+
+err_arch_supported:
+       clk_disable_unprepare(drvdata->clk);
+       if (--etm_count == 0)
+               unregister_hotcpu_notifier(&etm_cpu_notifier);
+       return ret;
+}
+
+static int etm_remove(struct amba_device *adev)
+{
+       struct etm_drvdata *drvdata = amba_get_drvdata(adev);
+
+       coresight_unregister(drvdata->csdev);
+       if (--etm_count == 0)
+               unregister_hotcpu_notifier(&etm_cpu_notifier);
+
+       return 0;
+}
+
+static struct amba_id etm_ids[] = {
+       {       /* ETM 3.3 */
+               .id     = 0x0003b921,
+               .mask   = 0x0003ffff,
+       },
+       {       /* ETM 3.5 */
+               .id     = 0x0003b956,
+               .mask   = 0x0003ffff,
+       },
+       {       /* PTM 1.0 */
+               .id     = 0x0003b950,
+               .mask   = 0x0003ffff,
+       },
+       {       /* PTM 1.1 */
+               .id     = 0x0003b95f,
+               .mask   = 0x0003ffff,
+       },
+       { 0, 0},
+};
+
+static struct amba_driver etm_driver = {
+       .drv = {
+               .name   = "coresight-etm3x",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = etm_probe,
+       .remove         = etm_remove,
+       .id_table       = etm_ids,
+};
+
+int __init etm_init(void)
+{
+       return amba_driver_register(&etm_driver);
+}
+module_init(etm_init);
+
+void __exit etm_exit(void)
+{
+       amba_driver_unregister(&etm_driver);
+}
+module_exit(etm_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CoreSight Program Flow Trace driver");
diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c
new file mode 100644 (file)
index 0000000..3db36f7
--- /dev/null
@@ -0,0 +1,258 @@
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/coresight.h>
+#include <linux/amba/bus.h>
+
+#include "coresight-priv.h"
+
+#define FUNNEL_FUNCTL          0x000
+#define FUNNEL_PRICTL          0x004
+
+#define FUNNEL_HOLDTIME_MASK   0xf00
+#define FUNNEL_HOLDTIME_SHFT   0x8
+#define FUNNEL_HOLDTIME                (0x7 << FUNNEL_HOLDTIME_SHFT)
+
+/**
+ * struct funnel_drvdata - specifics associated to a funnel component
+ * @base:      memory mapped base address for this component.
+ * @dev:       the device entity associated to this component.
+ * @csdev:     component vitals needed by the framework.
+ * @clk:       the clock this component is associated to.
+ * @priority:  port selection order.
+ */
+struct funnel_drvdata {
+       void __iomem            *base;
+       struct device           *dev;
+       struct coresight_device *csdev;
+       struct clk              *clk;
+       unsigned long           priority;
+};
+
+static void funnel_enable_hw(struct funnel_drvdata *drvdata, int port)
+{
+       u32 functl;
+
+       CS_UNLOCK(drvdata->base);
+
+       functl = readl_relaxed(drvdata->base + FUNNEL_FUNCTL);
+       functl &= ~FUNNEL_HOLDTIME_MASK;
+       functl |= FUNNEL_HOLDTIME;
+       functl |= (1 << port);
+       writel_relaxed(functl, drvdata->base + FUNNEL_FUNCTL);
+       writel_relaxed(drvdata->priority, drvdata->base + FUNNEL_PRICTL);
+
+       CS_LOCK(drvdata->base);
+}
+
+static int funnel_enable(struct coresight_device *csdev, int inport,
+                        int outport)
+{
+       struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+       int ret;
+
+       ret = clk_prepare_enable(drvdata->clk);
+       if (ret)
+               return ret;
+
+       funnel_enable_hw(drvdata, inport);
+
+       dev_info(drvdata->dev, "FUNNEL inport %d enabled\n", inport);
+       return 0;
+}
+
+static void funnel_disable_hw(struct funnel_drvdata *drvdata, int inport)
+{
+       u32 functl;
+
+       CS_UNLOCK(drvdata->base);
+
+       functl = readl_relaxed(drvdata->base + FUNNEL_FUNCTL);
+       functl &= ~(1 << inport);
+       writel_relaxed(functl, drvdata->base + FUNNEL_FUNCTL);
+
+       CS_LOCK(drvdata->base);
+}
+
+static void funnel_disable(struct coresight_device *csdev, int inport,
+                          int outport)
+{
+       struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+       funnel_disable_hw(drvdata, inport);
+
+       clk_disable_unprepare(drvdata->clk);
+
+       dev_info(drvdata->dev, "FUNNEL inport %d disabled\n", inport);
+}
+
+static const struct coresight_ops_link funnel_link_ops = {
+       .enable         = funnel_enable,
+       .disable        = funnel_disable,
+};
+
+static const struct coresight_ops funnel_cs_ops = {
+       .link_ops       = &funnel_link_ops,
+};
+
+static ssize_t priority_show(struct device *dev,
+                            struct device_attribute *attr, char *buf)
+{
+       struct funnel_drvdata *drvdata = dev_get_drvdata(dev->parent);
+       unsigned long val = drvdata->priority;
+
+       return sprintf(buf, "%#lx\n", val);
+}
+
+static ssize_t priority_store(struct device *dev,
+                             struct device_attribute *attr,
+                             const char *buf, size_t size)
+{
+       int ret;
+       unsigned long val;
+       struct funnel_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = kstrtoul(buf, 16, &val);
+       if (ret)
+               return ret;
+
+       drvdata->priority = val;
+       return size;
+}
+static DEVICE_ATTR_RW(priority);
+
+static u32 get_funnel_ctrl_hw(struct funnel_drvdata *drvdata)
+{
+       u32 functl;
+
+       CS_UNLOCK(drvdata->base);
+       functl = readl_relaxed(drvdata->base + FUNNEL_FUNCTL);
+       CS_LOCK(drvdata->base);
+
+       return functl;
+}
+
+static ssize_t funnel_ctrl_show(struct device *dev,
+                            struct device_attribute *attr, char *buf)
+{
+       int ret;
+       u32 val;
+       struct funnel_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = clk_prepare_enable(drvdata->clk);
+       if (ret)
+               return ret;
+
+       val = get_funnel_ctrl_hw(drvdata);
+       clk_disable_unprepare(drvdata->clk);
+
+       return sprintf(buf, "%#x\n", val);
+}
+static DEVICE_ATTR_RO(funnel_ctrl);
+
+static struct attribute *coresight_funnel_attrs[] = {
+       &dev_attr_funnel_ctrl.attr,
+       &dev_attr_priority.attr,
+       NULL,
+};
+ATTRIBUTE_GROUPS(coresight_funnel);
+
+static int funnel_probe(struct amba_device *adev, const struct amba_id *id)
+{
+       void __iomem *base;
+       struct device *dev = &adev->dev;
+       struct coresight_platform_data *pdata = NULL;
+       struct funnel_drvdata *drvdata;
+       struct resource *res = &adev->res;
+       struct coresight_desc *desc;
+       struct device_node *np = adev->dev.of_node;
+
+       if (np) {
+               pdata = of_get_coresight_platform_data(dev, np);
+               if (IS_ERR(pdata))
+                       return PTR_ERR(pdata);
+               adev->dev.platform_data = pdata;
+       }
+
+       drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+       if (!drvdata)
+               return -ENOMEM;
+
+       drvdata->dev = &adev->dev;
+       dev_set_drvdata(dev, drvdata);
+
+       /* Validity for the resource is already checked by the AMBA core */
+       base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       drvdata->base = base;
+
+       drvdata->clk = adev->pclk;
+
+       desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+       if (!desc)
+               return -ENOMEM;
+
+       desc->type = CORESIGHT_DEV_TYPE_LINK;
+       desc->subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_MERG;
+       desc->ops = &funnel_cs_ops;
+       desc->pdata = pdata;
+       desc->dev = dev;
+       desc->groups = coresight_funnel_groups;
+       drvdata->csdev = coresight_register(desc);
+       if (IS_ERR(drvdata->csdev))
+               return PTR_ERR(drvdata->csdev);
+
+       dev_info(dev, "FUNNEL initialized\n");
+       return 0;
+}
+
+static int funnel_remove(struct amba_device *adev)
+{
+       struct funnel_drvdata *drvdata = amba_get_drvdata(adev);
+
+       coresight_unregister(drvdata->csdev);
+       return 0;
+}
+
+static struct amba_id funnel_ids[] = {
+       {
+               .id     = 0x0003b908,
+               .mask   = 0x0003ffff,
+       },
+       { 0, 0},
+};
+
+static struct amba_driver funnel_driver = {
+       .drv = {
+               .name   = "coresight-funnel",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = funnel_probe,
+       .remove         = funnel_remove,
+       .id_table       = funnel_ids,
+};
+
+module_amba_driver(funnel_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CoreSight Funnel driver");
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
new file mode 100644 (file)
index 0000000..62fcd98
--- /dev/null
@@ -0,0 +1,63 @@
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CORESIGHT_PRIV_H
+#define _CORESIGHT_PRIV_H
+
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/coresight.h>
+
+/*
+ * Coresight management registers (0xf00-0xfcc)
+ * 0xfa0 - 0xfa4: Management   registers in PFTv1.0
+ *               Trace         registers in PFTv1.1
+ */
+#define CORESIGHT_ITCTRL       0xf00
+#define CORESIGHT_CLAIMSET     0xfa0
+#define CORESIGHT_CLAIMCLR     0xfa4
+#define CORESIGHT_LAR          0xfb0
+#define CORESIGHT_LSR          0xfb4
+#define CORESIGHT_AUTHSTATUS   0xfb8
+#define CORESIGHT_DEVID                0xfc8
+#define CORESIGHT_DEVTYPE      0xfcc
+
+#define TIMEOUT_US             100
+#define BMVAL(val, lsb, msb)   ((val & GENMASK(msb, lsb)) >> lsb)
+
+static inline void CS_LOCK(void __iomem *addr)
+{
+       do {
+               /* Wait for things to settle */
+               mb();
+               writel_relaxed(0x0, addr + CORESIGHT_LAR);
+       } while (0);
+}
+
+static inline void CS_UNLOCK(void __iomem *addr)
+{
+       do {
+               writel_relaxed(CORESIGHT_UNLOCK, addr + CORESIGHT_LAR);
+               /* Make sure everyone has seen this */
+               mb();
+       } while (0);
+}
+
+#ifdef CONFIG_CORESIGHT_SOURCE_ETM3X
+extern int etm_readl_cp14(u32 off, unsigned int *val);
+extern int etm_writel_cp14(u32 off, u32 val);
+#else
+static inline int etm_readl_cp14(u32 off, unsigned int *val) { return 0; }
+static inline int etm_writel_cp14(u32 off, u32 val) { return 0; }
+#endif
+
+#endif
diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c
new file mode 100644 (file)
index 0000000..75b9abd
--- /dev/null
@@ -0,0 +1,137 @@
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/coresight.h>
+
+#include "coresight-priv.h"
+
+/**
+ * struct replicator_drvdata - specifics associated to a replicator component
+ * @dev:       the device entity associated with this component
+ * @csdev:     component vitals needed by the framework
+ */
+struct replicator_drvdata {
+       struct device           *dev;
+       struct coresight_device *csdev;
+};
+
+static int replicator_enable(struct coresight_device *csdev, int inport,
+                            int outport)
+{
+       struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+       dev_info(drvdata->dev, "REPLICATOR enabled\n");
+       return 0;
+}
+
+static void replicator_disable(struct coresight_device *csdev, int inport,
+                              int outport)
+{
+       struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+       dev_info(drvdata->dev, "REPLICATOR disabled\n");
+}
+
+static const struct coresight_ops_link replicator_link_ops = {
+       .enable         = replicator_enable,
+       .disable        = replicator_disable,
+};
+
+static const struct coresight_ops replicator_cs_ops = {
+       .link_ops       = &replicator_link_ops,
+};
+
+static int replicator_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct coresight_platform_data *pdata = NULL;
+       struct replicator_drvdata *drvdata;
+       struct coresight_desc *desc;
+       struct device_node *np = pdev->dev.of_node;
+
+       if (np) {
+               pdata = of_get_coresight_platform_data(dev, np);
+               if (IS_ERR(pdata))
+                       return PTR_ERR(pdata);
+               pdev->dev.platform_data = pdata;
+       }
+
+       drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+       if (!drvdata)
+               return -ENOMEM;
+
+       drvdata->dev = &pdev->dev;
+       platform_set_drvdata(pdev, drvdata);
+
+       desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+       if (!desc)
+               return -ENOMEM;
+
+       desc->type = CORESIGHT_DEV_TYPE_LINK;
+       desc->subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_SPLIT;
+       desc->ops = &replicator_cs_ops;
+       desc->pdata = pdev->dev.platform_data;
+       desc->dev = &pdev->dev;
+       drvdata->csdev = coresight_register(desc);
+       if (IS_ERR(drvdata->csdev))
+               return PTR_ERR(drvdata->csdev);
+
+       dev_info(dev, "REPLICATOR initialized\n");
+       return 0;
+}
+
+static int replicator_remove(struct platform_device *pdev)
+{
+       struct replicator_drvdata *drvdata = platform_get_drvdata(pdev);
+
+       coresight_unregister(drvdata->csdev);
+       return 0;
+}
+
+static const struct of_device_id replicator_match[] = {
+       {.compatible = "arm,coresight-replicator"},
+       {}
+};
+
+static struct platform_driver replicator_driver = {
+       .probe          = replicator_probe,
+       .remove         = replicator_remove,
+       .driver         = {
+               .name   = "coresight-replicator",
+               .of_match_table = replicator_match,
+       },
+};
+
+static int __init replicator_init(void)
+{
+       return platform_driver_register(&replicator_driver);
+}
+module_init(replicator_init);
+
+static void __exit replicator_exit(void)
+{
+       platform_driver_unregister(&replicator_driver);
+}
+module_exit(replicator_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CoreSight Replicator driver");
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
new file mode 100644 (file)
index 0000000..7147f3d
--- /dev/null
@@ -0,0 +1,822 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/spinlock.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/coresight.h>
+#include <linux/amba/bus.h>
+
+#include "coresight-priv.h"
+
+#define TMC_RSZ                        0x004
+#define TMC_STS                        0x00c
+#define TMC_RRD                        0x010
+#define TMC_RRP                        0x014
+#define TMC_RWP                        0x018
+#define TMC_TRG                        0x01c
+#define TMC_CTL                        0x020
+#define TMC_RWD                        0x024
+#define TMC_MODE               0x028
+#define TMC_LBUFLEVEL          0x02c
+#define TMC_CBUFLEVEL          0x030
+#define TMC_BUFWM              0x034
+#define TMC_RRPHI              0x038
+#define TMC_RWPHI              0x03c
+#define TMC_AXICTL             0x110
+#define TMC_DBALO              0x118
+#define TMC_DBAHI              0x11c
+#define TMC_FFSR               0x300
+#define TMC_FFCR               0x304
+#define TMC_PSCR               0x308
+#define TMC_ITMISCOP0          0xee0
+#define TMC_ITTRFLIN           0xee8
+#define TMC_ITATBDATA0         0xeec
+#define TMC_ITATBCTR2          0xef0
+#define TMC_ITATBCTR1          0xef4
+#define TMC_ITATBCTR0          0xef8
+
+/* register description */
+/* TMC_CTL - 0x020 */
+#define TMC_CTL_CAPT_EN                BIT(0)
+/* TMC_STS - 0x00C */
+#define TMC_STS_TRIGGERED      BIT(1)
+/* TMC_AXICTL - 0x110 */
+#define TMC_AXICTL_PROT_CTL_B0 BIT(0)
+#define TMC_AXICTL_PROT_CTL_B1 BIT(1)
+#define TMC_AXICTL_SCT_GAT_MODE        BIT(7)
+#define TMC_AXICTL_WR_BURST_LEN 0xF00
+/* TMC_FFCR - 0x304 */
+#define TMC_FFCR_EN_FMT                BIT(0)
+#define TMC_FFCR_EN_TI         BIT(1)
+#define TMC_FFCR_FON_FLIN      BIT(4)
+#define TMC_FFCR_FON_TRIG_EVT  BIT(5)
+#define TMC_FFCR_FLUSHMAN      BIT(6)
+#define TMC_FFCR_TRIGON_TRIGIN BIT(8)
+#define TMC_FFCR_STOP_ON_FLUSH BIT(12)
+
+#define TMC_STS_TRIGGERED_BIT  2
+#define TMC_FFCR_FLUSHMAN_BIT  6
+
+enum tmc_config_type {
+       TMC_CONFIG_TYPE_ETB,
+       TMC_CONFIG_TYPE_ETR,
+       TMC_CONFIG_TYPE_ETF,
+};
+
+enum tmc_mode {
+       TMC_MODE_CIRCULAR_BUFFER,
+       TMC_MODE_SOFTWARE_FIFO,
+       TMC_MODE_HARDWARE_FIFO,
+};
+
+enum tmc_mem_intf_width {
+       TMC_MEM_INTF_WIDTH_32BITS       = 0x2,
+       TMC_MEM_INTF_WIDTH_64BITS       = 0x3,
+       TMC_MEM_INTF_WIDTH_128BITS      = 0x4,
+       TMC_MEM_INTF_WIDTH_256BITS      = 0x5,
+};
+
+/**
+ * struct tmc_drvdata - specifics associated to an TMC component
+ * @base:      memory mapped base address for this component.
+ * @dev:       the device entity associated to this component.
+ * @csdev:     component vitals needed by the framework.
+ * @miscdev:   specifics to handle "/dev/xyz.tmc" entry.
+ * @clk:       the clock this component is associated to.
+ * @spinlock:  only one at a time pls.
+ * @read_count:        manages preparation of buffer for reading.
+ * @buf:       area of memory where trace data get sent.
+ * @paddr:     DMA start location in RAM.
+ * @vaddr:     virtual representation of @paddr.
+ * @size:      @buf size.
+ * @enable:    this TMC is being used.
+ * @config_type: TMC variant, must be of type @tmc_config_type.
+ * @trigger_cntr: amount of words to store after a trigger.
+ */
+struct tmc_drvdata {
+       void __iomem            *base;
+       struct device           *dev;
+       struct coresight_device *csdev;
+       struct miscdevice       miscdev;
+       struct clk              *clk;
+       spinlock_t              spinlock;
+       int                     read_count;
+       bool                    reading;
+       char                    *buf;
+       dma_addr_t              paddr;
+       void __iomem            *vaddr;
+       u32                     size;
+       bool                    enable;
+       enum tmc_config_type    config_type;
+       u32                     trigger_cntr;
+};
+
+static void tmc_wait_for_ready(struct tmc_drvdata *drvdata)
+{
+       /* Ensure formatter, unformatter and hardware fifo are empty */
+       if (coresight_timeout(drvdata->base,
+                             TMC_STS, TMC_STS_TRIGGERED_BIT, 1)) {
+               dev_err(drvdata->dev,
+                       "timeout observed when probing at offset %#x\n",
+                       TMC_STS);
+       }
+}
+
+static void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
+{
+       u32 ffcr;
+
+       ffcr = readl_relaxed(drvdata->base + TMC_FFCR);
+       ffcr |= TMC_FFCR_STOP_ON_FLUSH;
+       writel_relaxed(ffcr, drvdata->base + TMC_FFCR);
+       ffcr |= TMC_FFCR_FLUSHMAN;
+       writel_relaxed(ffcr, drvdata->base + TMC_FFCR);
+       /* Ensure flush completes */
+       if (coresight_timeout(drvdata->base,
+                             TMC_FFCR, TMC_FFCR_FLUSHMAN_BIT, 0)) {
+               dev_err(drvdata->dev,
+                       "timeout observed when probing at offset %#x\n",
+                       TMC_FFCR);
+       }
+
+       tmc_wait_for_ready(drvdata);
+}
+
+static void tmc_enable_hw(struct tmc_drvdata *drvdata)
+{
+       writel_relaxed(TMC_CTL_CAPT_EN, drvdata->base + TMC_CTL);
+}
+
+static void tmc_disable_hw(struct tmc_drvdata *drvdata)
+{
+       writel_relaxed(0x0, drvdata->base + TMC_CTL);
+}
+
+static void tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
+{
+       /* Zero out the memory to help with debug */
+       memset(drvdata->buf, 0, drvdata->size);
+
+       CS_UNLOCK(drvdata->base);
+
+       writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
+       writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
+                      TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
+                      TMC_FFCR_TRIGON_TRIGIN,
+                      drvdata->base + TMC_FFCR);
+
+       writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG);
+       tmc_enable_hw(drvdata);
+
+       CS_LOCK(drvdata->base);
+}
+
+static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
+{
+       u32 axictl;
+
+       /* Zero out the memory to help with debug */
+       memset(drvdata->vaddr, 0, drvdata->size);
+
+       CS_UNLOCK(drvdata->base);
+
+       writel_relaxed(drvdata->size / 4, drvdata->base + TMC_RSZ);
+       writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
+
+       axictl = readl_relaxed(drvdata->base + TMC_AXICTL);
+       axictl |= TMC_AXICTL_WR_BURST_LEN;
+       writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
+       axictl &= ~TMC_AXICTL_SCT_GAT_MODE;
+       writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
+       axictl = (axictl &
+                 ~(TMC_AXICTL_PROT_CTL_B0 | TMC_AXICTL_PROT_CTL_B1)) |
+                 TMC_AXICTL_PROT_CTL_B1;
+       writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
+
+       writel_relaxed(drvdata->paddr, drvdata->base + TMC_DBALO);
+       writel_relaxed(0x0, drvdata->base + TMC_DBAHI);
+       writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
+                      TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
+                      TMC_FFCR_TRIGON_TRIGIN,
+                      drvdata->base + TMC_FFCR);
+       writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG);
+       tmc_enable_hw(drvdata);
+
+       CS_LOCK(drvdata->base);
+}
+
+static void tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
+{
+       CS_UNLOCK(drvdata->base);
+
+       writel_relaxed(TMC_MODE_HARDWARE_FIFO, drvdata->base + TMC_MODE);
+       writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI,
+                      drvdata->base + TMC_FFCR);
+       writel_relaxed(0x0, drvdata->base + TMC_BUFWM);
+       tmc_enable_hw(drvdata);
+
+       CS_LOCK(drvdata->base);
+}
+
+static int tmc_enable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
+{
+       int ret;
+       unsigned long flags;
+
+       ret = clk_prepare_enable(drvdata->clk);
+       if (ret)
+               return ret;
+
+       spin_lock_irqsave(&drvdata->spinlock, flags);
+       if (drvdata->reading) {
+               spin_unlock_irqrestore(&drvdata->spinlock, flags);
+               clk_disable_unprepare(drvdata->clk);
+               return -EBUSY;
+       }
+
+       if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
+               tmc_etb_enable_hw(drvdata);
+       } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
+               tmc_etr_enable_hw(drvdata);
+       } else {
+               if (mode == TMC_MODE_CIRCULAR_BUFFER)
+                       tmc_etb_enable_hw(drvdata);
+               else
+                       tmc_etf_enable_hw(drvdata);
+       }
+       drvdata->enable = true;
+       spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+       dev_info(drvdata->dev, "TMC enabled\n");
+       return 0;
+}
+
+static int tmc_enable_sink(struct coresight_device *csdev)
+{
+       struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+       return tmc_enable(drvdata, TMC_MODE_CIRCULAR_BUFFER);
+}
+
+static int tmc_enable_link(struct coresight_device *csdev, int inport,
+                          int outport)
+{
+       struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+       return tmc_enable(drvdata, TMC_MODE_HARDWARE_FIFO);
+}
+
+static void tmc_etb_dump_hw(struct tmc_drvdata *drvdata)
+{
+       enum tmc_mem_intf_width memwidth;
+       u8 memwords;
+       char *bufp;
+       u32 read_data;
+       int i;
+
+       memwidth = BMVAL(readl_relaxed(drvdata->base + CORESIGHT_DEVID), 8, 10);
+       if (memwidth == TMC_MEM_INTF_WIDTH_32BITS)
+               memwords = 1;
+       else if (memwidth == TMC_MEM_INTF_WIDTH_64BITS)
+               memwords = 2;
+       else if (memwidth == TMC_MEM_INTF_WIDTH_128BITS)
+               memwords = 4;
+       else
+               memwords = 8;
+
+       bufp = drvdata->buf;
+       while (1) {
+               for (i = 0; i < memwords; i++) {
+                       read_data = readl_relaxed(drvdata->base + TMC_RRD);
+                       if (read_data == 0xFFFFFFFF)
+                               return;
+                       memcpy(bufp, &read_data, 4);
+                       bufp += 4;
+               }
+       }
+}
+
+static void tmc_etb_disable_hw(struct tmc_drvdata *drvdata)
+{
+       CS_UNLOCK(drvdata->base);
+
+       tmc_flush_and_stop(drvdata);
+       tmc_etb_dump_hw(drvdata);
+       tmc_disable_hw(drvdata);
+
+       CS_LOCK(drvdata->base);
+}
+
+static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata)
+{
+       u32 rwp, val;
+
+       rwp = readl_relaxed(drvdata->base + TMC_RWP);
+       val = readl_relaxed(drvdata->base + TMC_STS);
+
+       /* How much memory do we still have */
+       if (val & BIT(0))
+               drvdata->buf = drvdata->vaddr + rwp - drvdata->paddr;
+       else
+               drvdata->buf = drvdata->vaddr;
+}
+
+static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
+{
+       CS_UNLOCK(drvdata->base);
+
+       tmc_flush_and_stop(drvdata);
+       tmc_etr_dump_hw(drvdata);
+       tmc_disable_hw(drvdata);
+
+       CS_LOCK(drvdata->base);
+}
+
+static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata)
+{
+       CS_UNLOCK(drvdata->base);
+
+       tmc_flush_and_stop(drvdata);
+       tmc_disable_hw(drvdata);
+
+       CS_LOCK(drvdata->base);
+}
+
+static void tmc_disable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&drvdata->spinlock, flags);
+       if (drvdata->reading)
+               goto out;
+
+       if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
+               tmc_etb_disable_hw(drvdata);
+       } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
+               tmc_etr_disable_hw(drvdata);
+       } else {
+               if (mode == TMC_MODE_CIRCULAR_BUFFER)
+                       tmc_etb_disable_hw(drvdata);
+               else
+                       tmc_etf_disable_hw(drvdata);
+       }
+out:
+       drvdata->enable = false;
+       spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+       clk_disable_unprepare(drvdata->clk);
+
+       dev_info(drvdata->dev, "TMC disabled\n");
+}
+
+static void tmc_disable_sink(struct coresight_device *csdev)
+{
+       struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+       tmc_disable(drvdata, TMC_MODE_CIRCULAR_BUFFER);
+}
+
+static void tmc_disable_link(struct coresight_device *csdev, int inport,
+                            int outport)
+{
+       struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+       tmc_disable(drvdata, TMC_MODE_HARDWARE_FIFO);
+}
+
+static const struct coresight_ops_sink tmc_sink_ops = {
+       .enable         = tmc_enable_sink,
+       .disable        = tmc_disable_sink,
+};
+
+static const struct coresight_ops_link tmc_link_ops = {
+       .enable         = tmc_enable_link,
+       .disable        = tmc_disable_link,
+};
+
+static const struct coresight_ops tmc_etb_cs_ops = {
+       .sink_ops       = &tmc_sink_ops,
+};
+
+static const struct coresight_ops tmc_etr_cs_ops = {
+       .sink_ops       = &tmc_sink_ops,
+};
+
+static const struct coresight_ops tmc_etf_cs_ops = {
+       .sink_ops       = &tmc_sink_ops,
+       .link_ops       = &tmc_link_ops,
+};
+
+static int tmc_read_prepare(struct tmc_drvdata *drvdata)
+{
+       int ret;
+       unsigned long flags;
+       enum tmc_mode mode;
+
+       spin_lock_irqsave(&drvdata->spinlock, flags);
+       if (!drvdata->enable)
+               goto out;
+
+       if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
+               tmc_etb_disable_hw(drvdata);
+       } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
+               tmc_etr_disable_hw(drvdata);
+       } else {
+               mode = readl_relaxed(drvdata->base + TMC_MODE);
+               if (mode == TMC_MODE_CIRCULAR_BUFFER) {
+                       tmc_etb_disable_hw(drvdata);
+               } else {
+                       ret = -ENODEV;
+                       goto err;
+               }
+       }
+out:
+       drvdata->reading = true;
+       spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+       dev_info(drvdata->dev, "TMC read start\n");
+       return 0;
+err:
+       spin_unlock_irqrestore(&drvdata->spinlock, flags);
+       return ret;
+}
+
+static void tmc_read_unprepare(struct tmc_drvdata *drvdata)
+{
+       unsigned long flags;
+       enum tmc_mode mode;
+
+       spin_lock_irqsave(&drvdata->spinlock, flags);
+       if (!drvdata->enable)
+               goto out;
+
+       if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
+               tmc_etb_enable_hw(drvdata);
+       } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
+               tmc_etr_enable_hw(drvdata);
+       } else {
+               mode = readl_relaxed(drvdata->base + TMC_MODE);
+               if (mode == TMC_MODE_CIRCULAR_BUFFER)
+                       tmc_etb_enable_hw(drvdata);
+       }
+out:
+       drvdata->reading = false;
+       spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+       dev_info(drvdata->dev, "TMC read end\n");
+}
+
+static int tmc_open(struct inode *inode, struct file *file)
+{
+       struct tmc_drvdata *drvdata = container_of(file->private_data,
+                                                  struct tmc_drvdata, miscdev);
+       int ret = 0;
+
+       if (drvdata->read_count++)
+               goto out;
+
+       ret = tmc_read_prepare(drvdata);
+       if (ret)
+               return ret;
+out:
+       nonseekable_open(inode, file);
+
+       dev_dbg(drvdata->dev, "%s: successfully opened\n", __func__);
+       return 0;
+}
+
+static ssize_t tmc_read(struct file *file, char __user *data, size_t len,
+                       loff_t *ppos)
+{
+       struct tmc_drvdata *drvdata = container_of(file->private_data,
+                                                  struct tmc_drvdata, miscdev);
+       char *bufp = drvdata->buf + *ppos;
+
+       if (*ppos + len > drvdata->size)
+               len = drvdata->size - *ppos;
+
+       if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
+               if (bufp == (char *)(drvdata->vaddr + drvdata->size))
+                       bufp = drvdata->vaddr;
+               else if (bufp > (char *)(drvdata->vaddr + drvdata->size))
+                       bufp -= drvdata->size;
+               if ((bufp + len) > (char *)(drvdata->vaddr + drvdata->size))
+                       len = (char *)(drvdata->vaddr + drvdata->size) - bufp;
+       }
+
+       if (copy_to_user(data, bufp, len)) {
+               dev_dbg(drvdata->dev, "%s: copy_to_user failed\n", __func__);
+               return -EFAULT;
+       }
+
+       *ppos += len;
+
+       dev_dbg(drvdata->dev, "%s: %zu bytes copied, %d bytes left\n",
+               __func__, len, (int)(drvdata->size - *ppos));
+       return len;
+}
+
+static int tmc_release(struct inode *inode, struct file *file)
+{
+       struct tmc_drvdata *drvdata = container_of(file->private_data,
+                                                  struct tmc_drvdata, miscdev);
+
+       if (--drvdata->read_count) {
+               if (drvdata->read_count < 0) {
+                       dev_err(drvdata->dev, "mismatched close\n");
+                       drvdata->read_count = 0;
+               }
+               goto out;
+       }
+
+       tmc_read_unprepare(drvdata);
+out:
+       dev_dbg(drvdata->dev, "%s: released\n", __func__);
+       return 0;
+}
+
+static const struct file_operations tmc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = tmc_open,
+       .read           = tmc_read,
+       .release        = tmc_release,
+       .llseek         = no_llseek,
+};
+
+static ssize_t status_show(struct device *dev,
+                          struct device_attribute *attr, char *buf)
+{
+       int ret;
+       unsigned long flags;
+       u32 tmc_rsz, tmc_sts, tmc_rrp, tmc_rwp, tmc_trg;
+       u32 tmc_ctl, tmc_ffsr, tmc_ffcr, tmc_mode, tmc_pscr;
+       u32 devid;
+       struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = clk_prepare_enable(drvdata->clk);
+       if (ret)
+               goto out;
+
+       spin_lock_irqsave(&drvdata->spinlock, flags);
+       CS_UNLOCK(drvdata->base);
+
+       tmc_rsz = readl_relaxed(drvdata->base + TMC_RSZ);
+       tmc_sts = readl_relaxed(drvdata->base + TMC_STS);
+       tmc_rrp = readl_relaxed(drvdata->base + TMC_RRP);
+       tmc_rwp = readl_relaxed(drvdata->base + TMC_RWP);
+       tmc_trg = readl_relaxed(drvdata->base + TMC_TRG);
+       tmc_ctl = readl_relaxed(drvdata->base + TMC_CTL);
+       tmc_ffsr = readl_relaxed(drvdata->base + TMC_FFSR);
+       tmc_ffcr = readl_relaxed(drvdata->base + TMC_FFCR);
+       tmc_mode = readl_relaxed(drvdata->base + TMC_MODE);
+       tmc_pscr = readl_relaxed(drvdata->base + TMC_PSCR);
+       devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
+
+       CS_LOCK(drvdata->base);
+       spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+       clk_disable_unprepare(drvdata->clk);
+
+       return sprintf(buf,
+                      "Depth:\t\t0x%x\n"
+                      "Status:\t\t0x%x\n"
+                      "RAM read ptr:\t0x%x\n"
+                      "RAM wrt ptr:\t0x%x\n"
+                      "Trigger cnt:\t0x%x\n"
+                      "Control:\t0x%x\n"
+                      "Flush status:\t0x%x\n"
+                      "Flush ctrl:\t0x%x\n"
+                      "Mode:\t\t0x%x\n"
+                      "PSRC:\t\t0x%x\n"
+                      "DEVID:\t\t0x%x\n",
+                       tmc_rsz, tmc_sts, tmc_rrp, tmc_rwp, tmc_trg,
+                       tmc_ctl, tmc_ffsr, tmc_ffcr, tmc_mode, tmc_pscr, devid);
+out:
+       return -EINVAL;
+}
+static DEVICE_ATTR_RO(status);
+
+static ssize_t trigger_cntr_show(struct device *dev,
+                           struct device_attribute *attr, char *buf)
+{
+       struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
+       unsigned long val = drvdata->trigger_cntr;
+
+       return sprintf(buf, "%#lx\n", val);
+}
+
+static ssize_t trigger_cntr_store(struct device *dev,
+                            struct device_attribute *attr,
+                            const char *buf, size_t size)
+{
+       int ret;
+       unsigned long val;
+       struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+       ret = kstrtoul(buf, 16, &val);
+       if (ret)
+               return ret;
+
+       drvdata->trigger_cntr = val;
+       return size;
+}
+static DEVICE_ATTR_RW(trigger_cntr);
+
+static struct attribute *coresight_etb_attrs[] = {
+       &dev_attr_trigger_cntr.attr,
+       &dev_attr_status.attr,
+       NULL,
+};
+ATTRIBUTE_GROUPS(coresight_etb);
+
+static struct attribute *coresight_etr_attrs[] = {
+       &dev_attr_trigger_cntr.attr,
+       &dev_attr_status.attr,
+       NULL,
+};
+ATTRIBUTE_GROUPS(coresight_etr);
+
+static struct attribute *coresight_etf_attrs[] = {
+       &dev_attr_trigger_cntr.attr,
+       &dev_attr_status.attr,
+       NULL,
+};
+ATTRIBUTE_GROUPS(coresight_etf);
+
+static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
+{
+       int ret = 0;
+       u32 devid;
+       void __iomem *base;
+       struct device *dev = &adev->dev;
+       struct coresight_platform_data *pdata = NULL;
+       struct tmc_drvdata *drvdata;
+       struct resource *res = &adev->res;
+       struct coresight_desc *desc;
+       struct device_node *np = adev->dev.of_node;
+
+       if (np) {
+               pdata = of_get_coresight_platform_data(dev, np);
+               if (IS_ERR(pdata))
+                       return PTR_ERR(pdata);
+               adev->dev.platform_data = pdata;
+       }
+
+       drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+       if (!drvdata)
+               return -ENOMEM;
+
+       drvdata->dev = &adev->dev;
+       dev_set_drvdata(dev, drvdata);
+
+       /* Validity for the resource is already checked by the AMBA core */
+       base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       drvdata->base = base;
+
+       spin_lock_init(&drvdata->spinlock);
+
+       drvdata->clk = adev->pclk;
+       ret = clk_prepare_enable(drvdata->clk);
+       if (ret)
+               return ret;
+
+       devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
+       drvdata->config_type = BMVAL(devid, 6, 7);
+
+       if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
+               if (np)
+                       ret = of_property_read_u32(np,
+                                                  "arm,buffer-size",
+                                                  &drvdata->size);
+               if (ret)
+                       drvdata->size = SZ_1M;
+       } else {
+               drvdata->size = readl_relaxed(drvdata->base + TMC_RSZ) * 4;
+       }
+
+       clk_disable_unprepare(drvdata->clk);
+
+       if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
+               drvdata->vaddr = dma_alloc_coherent(dev, drvdata->size,
+                                               &drvdata->paddr, GFP_KERNEL);
+               if (!drvdata->vaddr)
+                       return -ENOMEM;
+
+               memset(drvdata->vaddr, 0, drvdata->size);
+               drvdata->buf = drvdata->vaddr;
+       } else {
+               drvdata->buf = devm_kzalloc(dev, drvdata->size, GFP_KERNEL);
+               if (!drvdata->buf)
+                       return -ENOMEM;
+       }
+
+       desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+       if (!desc) {
+               ret = -ENOMEM;
+               goto err_devm_kzalloc;
+       }
+
+       desc->pdata = pdata;
+       desc->dev = dev;
+       desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
+
+       if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
+               desc->type = CORESIGHT_DEV_TYPE_SINK;
+               desc->ops = &tmc_etb_cs_ops;
+               desc->groups = coresight_etb_groups;
+       } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
+               desc->type = CORESIGHT_DEV_TYPE_SINK;
+               desc->ops = &tmc_etr_cs_ops;
+               desc->groups = coresight_etr_groups;
+       } else {
+               desc->type = CORESIGHT_DEV_TYPE_LINKSINK;
+               desc->subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_FIFO;
+               desc->ops = &tmc_etf_cs_ops;
+               desc->groups = coresight_etf_groups;
+       }
+
+       drvdata->csdev = coresight_register(desc);
+       if (IS_ERR(drvdata->csdev)) {
+               ret = PTR_ERR(drvdata->csdev);
+               goto err_devm_kzalloc;
+       }
+
+       drvdata->miscdev.name = pdata->name;
+       drvdata->miscdev.minor = MISC_DYNAMIC_MINOR;
+       drvdata->miscdev.fops = &tmc_fops;
+       ret = misc_register(&drvdata->miscdev);
+       if (ret)
+               goto err_misc_register;
+
+       dev_info(dev, "TMC initialized\n");
+       return 0;
+
+err_misc_register:
+       coresight_unregister(drvdata->csdev);
+err_devm_kzalloc:
+       if (drvdata->config_type == TMC_CONFIG_TYPE_ETR)
+               dma_free_coherent(dev, drvdata->size,
+                               &drvdata->paddr, GFP_KERNEL);
+       return ret;
+}
+
+static int tmc_remove(struct amba_device *adev)
+{
+       struct tmc_drvdata *drvdata = amba_get_drvdata(adev);
+
+       misc_deregister(&drvdata->miscdev);
+       coresight_unregister(drvdata->csdev);
+       if (drvdata->config_type == TMC_CONFIG_TYPE_ETR)
+               dma_free_coherent(drvdata->dev, drvdata->size,
+                                 &drvdata->paddr, GFP_KERNEL);
+
+       return 0;
+}
+
+static struct amba_id tmc_ids[] = {
+       {
+               .id     = 0x0003b961,
+               .mask   = 0x0003ffff,
+       },
+       { 0, 0},
+};
+
+static struct amba_driver tmc_driver = {
+       .drv = {
+               .name   = "coresight-tmc",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = tmc_probe,
+       .remove         = tmc_remove,
+       .id_table       = tmc_ids,
+};
+
+module_amba_driver(tmc_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CoreSight Trace Memory Controller driver");
diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c
new file mode 100644 (file)
index 0000000..3b33af2
--- /dev/null
@@ -0,0 +1,207 @@
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/coresight.h>
+#include <linux/amba/bus.h>
+
+#include "coresight-priv.h"
+
+#define TPIU_SUPP_PORTSZ       0x000
+#define TPIU_CURR_PORTSZ       0x004
+#define TPIU_SUPP_TRIGMODES    0x100
+#define TPIU_TRIG_CNTRVAL      0x104
+#define TPIU_TRIG_MULT         0x108
+#define TPIU_SUPP_TESTPATM     0x200
+#define TPIU_CURR_TESTPATM     0x204
+#define TPIU_TEST_PATREPCNTR   0x208
+#define TPIU_FFSR              0x300
+#define TPIU_FFCR              0x304
+#define TPIU_FSYNC_CNTR                0x308
+#define TPIU_EXTCTL_INPORT     0x400
+#define TPIU_EXTCTL_OUTPORT    0x404
+#define TPIU_ITTRFLINACK       0xee4
+#define TPIU_ITTRFLIN          0xee8
+#define TPIU_ITATBDATA0                0xeec
+#define TPIU_ITATBCTR2         0xef0
+#define TPIU_ITATBCTR1         0xef4
+#define TPIU_ITATBCTR0         0xef8
+
+/** register definition **/
+/* FFCR - 0x304 */
+#define FFCR_FON_MAN           BIT(6)
+
+/**
+ * @base:      memory mapped base address for this component.
+ * @dev:       the device entity associated to this component.
+ * @csdev:     component vitals needed by the framework.
+ * @clk:       the clock this component is associated to.
+ */
+struct tpiu_drvdata {
+       void __iomem            *base;
+       struct device           *dev;
+       struct coresight_device *csdev;
+       struct clk              *clk;
+};
+
+static void tpiu_enable_hw(struct tpiu_drvdata *drvdata)
+{
+       CS_UNLOCK(drvdata->base);
+
+       /* TODO: fill this up */
+
+       CS_LOCK(drvdata->base);
+}
+
+static int tpiu_enable(struct coresight_device *csdev)
+{
+       struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+       int ret;
+
+       ret = clk_prepare_enable(drvdata->clk);
+       if (ret)
+               return ret;
+
+       tpiu_enable_hw(drvdata);
+
+       dev_info(drvdata->dev, "TPIU enabled\n");
+       return 0;
+}
+
+static void tpiu_disable_hw(struct tpiu_drvdata *drvdata)
+{
+       CS_UNLOCK(drvdata->base);
+
+       /* Clear formatter controle reg. */
+       writel_relaxed(0x0, drvdata->base + TPIU_FFCR);
+       /* Generate manual flush */
+       writel_relaxed(FFCR_FON_MAN, drvdata->base + TPIU_FFCR);
+
+       CS_LOCK(drvdata->base);
+}
+
+static void tpiu_disable(struct coresight_device *csdev)
+{
+       struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+       tpiu_disable_hw(drvdata);
+
+       clk_disable_unprepare(drvdata->clk);
+
+       dev_info(drvdata->dev, "TPIU disabled\n");
+}
+
+static const struct coresight_ops_sink tpiu_sink_ops = {
+       .enable         = tpiu_enable,
+       .disable        = tpiu_disable,
+};
+
+static const struct coresight_ops tpiu_cs_ops = {
+       .sink_ops       = &tpiu_sink_ops,
+};
+
+static int tpiu_probe(struct amba_device *adev, const struct amba_id *id)
+{
+       int ret;
+       void __iomem *base;
+       struct device *dev = &adev->dev;
+       struct coresight_platform_data *pdata = NULL;
+       struct tpiu_drvdata *drvdata;
+       struct resource *res = &adev->res;
+       struct coresight_desc *desc;
+       struct device_node *np = adev->dev.of_node;
+
+       if (np) {
+               pdata = of_get_coresight_platform_data(dev, np);
+               if (IS_ERR(pdata))
+                       return PTR_ERR(pdata);
+               adev->dev.platform_data = pdata;
+       }
+
+       drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+       if (!drvdata)
+               return -ENOMEM;
+
+       drvdata->dev = &adev->dev;
+       dev_set_drvdata(dev, drvdata);
+
+       /* Validity for the resource is already checked by the AMBA core */
+       base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       drvdata->base = base;
+
+       drvdata->clk = adev->pclk;
+       ret = clk_prepare_enable(drvdata->clk);
+       if (ret)
+               return ret;
+
+       /* Disable tpiu to support older devices */
+       tpiu_disable_hw(drvdata);
+
+       clk_disable_unprepare(drvdata->clk);
+
+       desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+       if (!desc)
+               return -ENOMEM;
+
+       desc->type = CORESIGHT_DEV_TYPE_SINK;
+       desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_PORT;
+       desc->ops = &tpiu_cs_ops;
+       desc->pdata = pdata;
+       desc->dev = dev;
+       drvdata->csdev = coresight_register(desc);
+       if (IS_ERR(drvdata->csdev))
+               return PTR_ERR(drvdata->csdev);
+
+       dev_info(dev, "TPIU initialized\n");
+       return 0;
+}
+
+static int tpiu_remove(struct amba_device *adev)
+{
+       struct tpiu_drvdata *drvdata = amba_get_drvdata(adev);
+
+       coresight_unregister(drvdata->csdev);
+       return 0;
+}
+
+static struct amba_id tpiu_ids[] = {
+       {
+               .id     = 0x0003b912,
+               .mask   = 0x0003ffff,
+       },
+       { 0, 0},
+};
+
+static struct amba_driver tpiu_driver = {
+       .drv = {
+               .name   = "coresight-tpiu",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = tpiu_probe,
+       .remove         = tpiu_remove,
+       .id_table       = tpiu_ids,
+};
+
+module_amba_driver(tpiu_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CoreSight Trace Port Interface Unit driver");
diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
new file mode 100644 (file)
index 0000000..894531d
--- /dev/null
@@ -0,0 +1,720 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/clk.h>
+#include <linux/coresight.h>
+#include <linux/of_platform.h>
+#include <linux/delay.h>
+
+#include "coresight-priv.h"
+
+static DEFINE_MUTEX(coresight_mutex);
+
+static int coresight_id_match(struct device *dev, void *data)
+{
+       int trace_id, i_trace_id;
+       struct coresight_device *csdev, *i_csdev;
+
+       csdev = data;
+       i_csdev = to_coresight_device(dev);
+
+       /*
+        * No need to care about oneself and components that are not
+        * sources or not enabled
+        */
+       if (i_csdev == csdev || !i_csdev->enable ||
+           i_csdev->type != CORESIGHT_DEV_TYPE_SOURCE)
+               return 0;
+
+       /* Get the source ID for both compoment */
+       trace_id = source_ops(csdev)->trace_id(csdev);
+       i_trace_id = source_ops(i_csdev)->trace_id(i_csdev);
+
+       /* All you need is one */
+       if (trace_id == i_trace_id)
+               return 1;
+
+       return 0;
+}
+
+static int coresight_source_is_unique(struct coresight_device *csdev)
+{
+       int trace_id = source_ops(csdev)->trace_id(csdev);
+
+       /* this shouldn't happen */
+       if (trace_id < 0)
+               return 0;
+
+       return !bus_for_each_dev(&coresight_bustype, NULL,
+                                csdev, coresight_id_match);
+}
+
+static int coresight_find_link_inport(struct coresight_device *csdev)
+{
+       int i;
+       struct coresight_device *parent;
+       struct coresight_connection *conn;
+
+       parent = container_of(csdev->path_link.next,
+                             struct coresight_device, path_link);
+
+       for (i = 0; i < parent->nr_outport; i++) {
+               conn = &parent->conns[i];
+               if (conn->child_dev == csdev)
+                       return conn->child_port;
+       }
+
+       dev_err(&csdev->dev, "couldn't find inport, parent: %s, child: %s\n",
+               dev_name(&parent->dev), dev_name(&csdev->dev));
+
+       return 0;
+}
+
+static int coresight_find_link_outport(struct coresight_device *csdev)
+{
+       int i;
+       struct coresight_device *child;
+       struct coresight_connection *conn;
+
+       child = container_of(csdev->path_link.prev,
+                            struct coresight_device, path_link);
+
+       for (i = 0; i < csdev->nr_outport; i++) {
+               conn = &csdev->conns[i];
+               if (conn->child_dev == child)
+                       return conn->outport;
+       }
+
+       dev_err(&csdev->dev, "couldn't find outport, parent: %s, child: %s\n",
+               dev_name(&csdev->dev), dev_name(&child->dev));
+
+       return 0;
+}
+
+static int coresight_enable_sink(struct coresight_device *csdev)
+{
+       int ret;
+
+       if (!csdev->enable) {
+               if (sink_ops(csdev)->enable) {
+                       ret = sink_ops(csdev)->enable(csdev);
+                       if (ret)
+                               return ret;
+               }
+               csdev->enable = true;
+       }
+
+       atomic_inc(csdev->refcnt);
+
+       return 0;
+}
+
+static void coresight_disable_sink(struct coresight_device *csdev)
+{
+       if (atomic_dec_return(csdev->refcnt) == 0) {
+               if (sink_ops(csdev)->disable) {
+                       sink_ops(csdev)->disable(csdev);
+                       csdev->enable = false;
+               }
+       }
+}
+
+static int coresight_enable_link(struct coresight_device *csdev)
+{
+       int ret;
+       int link_subtype;
+       int refport, inport, outport;
+
+       inport = coresight_find_link_inport(csdev);
+       outport = coresight_find_link_outport(csdev);
+       link_subtype = csdev->subtype.link_subtype;
+
+       if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG)
+               refport = inport;
+       else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT)
+               refport = outport;
+       else
+               refport = 0;
+
+       if (atomic_inc_return(&csdev->refcnt[refport]) == 1) {
+               if (link_ops(csdev)->enable) {
+                       ret = link_ops(csdev)->enable(csdev, inport, outport);
+                       if (ret)
+                               return ret;
+               }
+       }
+
+       csdev->enable = true;
+
+       return 0;
+}
+
+static void coresight_disable_link(struct coresight_device *csdev)
+{
+       int i, nr_conns;
+       int link_subtype;
+       int refport, inport, outport;
+
+       inport = coresight_find_link_inport(csdev);
+       outport = coresight_find_link_outport(csdev);
+       link_subtype = csdev->subtype.link_subtype;
+
+       if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) {
+               refport = inport;
+               nr_conns = csdev->nr_inport;
+       } else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT) {
+               refport = outport;
+               nr_conns = csdev->nr_outport;
+       } else {
+               refport = 0;
+               nr_conns = 1;
+       }
+
+       if (atomic_dec_return(&csdev->refcnt[refport]) == 0) {
+               if (link_ops(csdev)->disable)
+                       link_ops(csdev)->disable(csdev, inport, outport);
+       }
+
+       for (i = 0; i < nr_conns; i++)
+               if (atomic_read(&csdev->refcnt[i]) != 0)
+                       return;
+
+       csdev->enable = false;
+}
+
+static int coresight_enable_source(struct coresight_device *csdev)
+{
+       int ret;
+
+       if (!coresight_source_is_unique(csdev)) {
+               dev_warn(&csdev->dev, "traceID %d not unique\n",
+                        source_ops(csdev)->trace_id(csdev));
+               return -EINVAL;
+       }
+
+       if (!csdev->enable) {
+               if (source_ops(csdev)->enable) {
+                       ret = source_ops(csdev)->enable(csdev);
+                       if (ret)
+                               return ret;
+               }
+               csdev->enable = true;
+       }
+
+       atomic_inc(csdev->refcnt);
+
+       return 0;
+}
+
+static void coresight_disable_source(struct coresight_device *csdev)
+{
+       if (atomic_dec_return(csdev->refcnt) == 0) {
+               if (source_ops(csdev)->disable) {
+                       source_ops(csdev)->disable(csdev);
+                       csdev->enable = false;
+               }
+       }
+}
+
+static int coresight_enable_path(struct list_head *path)
+{
+       int ret = 0;
+       struct coresight_device *cd;
+
+       list_for_each_entry(cd, path, path_link) {
+               if (cd == list_first_entry(path, struct coresight_device,
+                                          path_link)) {
+                       ret = coresight_enable_sink(cd);
+               } else if (list_is_last(&cd->path_link, path)) {
+                       /*
+                        * Don't enable the source just yet - this needs to
+                        * happen at the very end when all links and sink
+                        * along the path have been configured properly.
+                        */
+                       ;
+               } else {
+                       ret = coresight_enable_link(cd);
+               }
+               if (ret)
+                       goto err;
+       }
+
+       return 0;
+err:
+       list_for_each_entry_continue_reverse(cd, path, path_link) {
+               if (cd == list_first_entry(path, struct coresight_device,
+                                          path_link)) {
+                       coresight_disable_sink(cd);
+               } else if (list_is_last(&cd->path_link, path)) {
+                       ;
+               } else {
+                       coresight_disable_link(cd);
+               }
+       }
+
+       return ret;
+}
+
+static int coresight_disable_path(struct list_head *path)
+{
+       struct coresight_device *cd;
+
+       list_for_each_entry_reverse(cd, path, path_link) {
+               if (cd == list_first_entry(path, struct coresight_device,
+                                          path_link)) {
+                       coresight_disable_sink(cd);
+               } else if (list_is_last(&cd->path_link, path)) {
+                       /*
+                        * The source has already been stopped, no need
+                        * to do it again here.
+                        */
+                       ;
+               } else {
+                       coresight_disable_link(cd);
+               }
+       }
+
+       return 0;
+}
+
+static int coresight_build_paths(struct coresight_device *csdev,
+                                struct list_head *path,
+                                bool enable)
+{
+       int i, ret = -EINVAL;
+       struct coresight_connection *conn;
+
+       list_add(&csdev->path_link, path);
+
+       if ((csdev->type == CORESIGHT_DEV_TYPE_SINK ||
+           csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) &&
+           csdev->activated) {
+               if (enable)
+                       ret = coresight_enable_path(path);
+               else
+                       ret = coresight_disable_path(path);
+       } else {
+               for (i = 0; i < csdev->nr_outport; i++) {
+                       conn = &csdev->conns[i];
+                       if (coresight_build_paths(conn->child_dev,
+                                                   path, enable) == 0)
+                               ret = 0;
+               }
+       }
+
+       if (list_first_entry(path, struct coresight_device, path_link) != csdev)
+               dev_err(&csdev->dev, "wrong device in %s\n", __func__);
+
+       list_del(&csdev->path_link);
+
+       return ret;
+}
+
+int coresight_enable(struct coresight_device *csdev)
+{
+       int ret = 0;
+       LIST_HEAD(path);
+
+       mutex_lock(&coresight_mutex);
+       if (csdev->type != CORESIGHT_DEV_TYPE_SOURCE) {
+               ret = -EINVAL;
+               dev_err(&csdev->dev, "wrong device type in %s\n", __func__);
+               goto out;
+       }
+       if (csdev->enable)
+               goto out;
+
+       if (coresight_build_paths(csdev, &path, true)) {
+               dev_err(&csdev->dev, "building path(s) failed\n");
+               goto out;
+       }
+
+       if (coresight_enable_source(csdev))
+               dev_err(&csdev->dev, "source enable failed\n");
+out:
+       mutex_unlock(&coresight_mutex);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(coresight_enable);
+
+void coresight_disable(struct coresight_device *csdev)
+{
+       LIST_HEAD(path);
+
+       mutex_lock(&coresight_mutex);
+       if (csdev->type != CORESIGHT_DEV_TYPE_SOURCE) {
+               dev_err(&csdev->dev, "wrong device type in %s\n", __func__);
+               goto out;
+       }
+       if (!csdev->enable)
+               goto out;
+
+       coresight_disable_source(csdev);
+       if (coresight_build_paths(csdev, &path, false))
+               dev_err(&csdev->dev, "releasing path(s) failed\n");
+
+out:
+       mutex_unlock(&coresight_mutex);
+}
+EXPORT_SYMBOL_GPL(coresight_disable);
+
+static ssize_t enable_sink_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct coresight_device *csdev = to_coresight_device(dev);
+
+       return scnprintf(buf, PAGE_SIZE, "%u\n", (unsigned)csdev->activated);
+}
+
+static ssize_t enable_sink_store(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buf, size_t size)
+{
+       int ret;
+       unsigned long val;
+       struct coresight_device *csdev = to_coresight_device(dev);
+
+       ret = kstrtoul(buf, 10, &val);
+       if (ret)
+               return ret;
+
+       if (val)
+               csdev->activated = true;
+       else
+               csdev->activated = false;
+
+       return size;
+
+}
+static DEVICE_ATTR_RW(enable_sink);
+
+static ssize_t enable_source_show(struct device *dev,
+                                 struct device_attribute *attr, char *buf)
+{
+       struct coresight_device *csdev = to_coresight_device(dev);
+
+       return scnprintf(buf, PAGE_SIZE, "%u\n", (unsigned)csdev->enable);
+}
+
+static ssize_t enable_source_store(struct device *dev,
+                                  struct device_attribute *attr,
+                                  const char *buf, size_t size)
+{
+       int ret = 0;
+       unsigned long val;
+       struct coresight_device *csdev = to_coresight_device(dev);
+
+       ret = kstrtoul(buf, 10, &val);
+       if (ret)
+               return ret;
+
+       if (val) {
+               ret = coresight_enable(csdev);
+               if (ret)
+                       return ret;
+       } else {
+               coresight_disable(csdev);
+       }
+
+       return size;
+}
+static DEVICE_ATTR_RW(enable_source);
+
+static struct attribute *coresight_sink_attrs[] = {
+       &dev_attr_enable_sink.attr,
+       NULL,
+};
+ATTRIBUTE_GROUPS(coresight_sink);
+
+static struct attribute *coresight_source_attrs[] = {
+       &dev_attr_enable_source.attr,
+       NULL,
+};
+ATTRIBUTE_GROUPS(coresight_source);
+
+static struct device_type coresight_dev_type[] = {
+       {
+               .name = "none",
+       },
+       {
+               .name = "sink",
+               .groups = coresight_sink_groups,
+       },
+       {
+               .name = "link",
+       },
+       {
+               .name = "linksink",
+               .groups = coresight_sink_groups,
+       },
+       {
+               .name = "source",
+               .groups = coresight_source_groups,
+       },
+};
+
+static void coresight_device_release(struct device *dev)
+{
+       struct coresight_device *csdev = to_coresight_device(dev);
+
+       kfree(csdev);
+}
+
+static int coresight_orphan_match(struct device *dev, void *data)
+{
+       int i;
+       bool still_orphan = false;
+       struct coresight_device *csdev, *i_csdev;
+       struct coresight_connection *conn;
+
+       csdev = data;
+       i_csdev = to_coresight_device(dev);
+
+       /* No need to check oneself */
+       if (csdev == i_csdev)
+               return 0;
+
+       /* Move on to another component if no connection is orphan */
+       if (!i_csdev->orphan)
+               return 0;
+       /*
+        * Circle throuch all the connection of that component.  If we find
+        * an orphan connection whose name matches @csdev, link it.
+        */
+       for (i = 0; i < i_csdev->nr_outport; i++) {
+               conn = &i_csdev->conns[i];
+
+               /* We have found at least one orphan connection */
+               if (conn->child_dev == NULL) {
+                       /* Does it match this newly added device? */
+                       if (!strcmp(dev_name(&csdev->dev), conn->child_name)) {
+                               conn->child_dev = csdev;
+                       } else {
+                               /* This component still has an orphan */
+                               still_orphan = true;
+                       }
+               }
+       }
+
+       i_csdev->orphan = still_orphan;
+
+       /*
+        * Returning '0' ensures that all known component on the
+        * bus will be checked.
+        */
+       return 0;
+}
+
+static void coresight_fixup_orphan_conns(struct coresight_device *csdev)
+{
+       /*
+        * No need to check for a return value as orphan connection(s)
+        * are hooked-up with each newly added component.
+        */
+       bus_for_each_dev(&coresight_bustype, NULL,
+                                csdev, coresight_orphan_match);
+}
+
+
+static int coresight_name_match(struct device *dev, void *data)
+{
+       char *to_match;
+       struct coresight_device *i_csdev;
+
+       to_match = data;
+       i_csdev = to_coresight_device(dev);
+
+       if (!strcmp(to_match, dev_name(&i_csdev->dev)))
+               return 1;
+
+       return 0;
+}
+
+static void coresight_fixup_device_conns(struct coresight_device *csdev)
+{
+       int i;
+       struct device *dev = NULL;
+       struct coresight_connection *conn;
+
+       for (i = 0; i < csdev->nr_outport; i++) {
+               conn = &csdev->conns[i];
+               dev = bus_find_device(&coresight_bustype, NULL,
+                                     (void *)conn->child_name,
+                                     coresight_name_match);
+
+               if (dev) {
+                       conn->child_dev = to_coresight_device(dev);
+               } else {
+                       csdev->orphan = true;
+                       conn->child_dev = NULL;
+               }
+       }
+}
+
+/**
+ * coresight_timeout - loop until a bit has changed to a specific state.
+ * @addr: base address of the area of interest.
+ * @offset: address of a register, starting from @addr.
+ * @position: the position of the bit of interest.
+ * @value: the value the bit should have.
+ *
+ * Return: 0 as soon as the bit has taken the desired state or -EAGAIN if
+ * TIMEOUT_US has elapsed, which ever happens first.
+ */
+
+int coresight_timeout(void __iomem *addr, u32 offset, int position, int value)
+{
+       int i;
+       u32 val;
+
+       for (i = TIMEOUT_US; i > 0; i--) {
+               val = __raw_readl(addr + offset);
+               /* waiting on the bit to go from 0 to 1 */
+               if (value) {
+                       if (val & BIT(position))
+                               return 0;
+               /* waiting on the bit to go from 1 to 0 */
+               } else {
+                       if (!(val & BIT(position)))
+                               return 0;
+               }
+
+               /*
+                * Delay is arbitrary - the specification doesn't say how long
+                * we are expected to wait.  Extra check required to make sure
+                * we don't wait needlessly on the last iteration.
+                */
+               if (i - 1)
+                       udelay(1);
+       }
+
+       return -EAGAIN;
+}
+
+struct bus_type coresight_bustype = {
+       .name   = "coresight",
+};
+
+static int __init coresight_init(void)
+{
+       return bus_register(&coresight_bustype);
+}
+postcore_initcall(coresight_init);
+
+struct coresight_device *coresight_register(struct coresight_desc *desc)
+{
+       int i;
+       int ret;
+       int link_subtype;
+       int nr_refcnts = 1;
+       atomic_t *refcnts = NULL;
+       struct coresight_device *csdev;
+       struct coresight_connection *conns;
+
+       csdev = kzalloc(sizeof(*csdev), GFP_KERNEL);
+       if (!csdev) {
+               ret = -ENOMEM;
+               goto err_kzalloc_csdev;
+       }
+
+       if (desc->type == CORESIGHT_DEV_TYPE_LINK ||
+           desc->type == CORESIGHT_DEV_TYPE_LINKSINK) {
+               link_subtype = desc->subtype.link_subtype;
+
+               if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG)
+                       nr_refcnts = desc->pdata->nr_inport;
+               else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT)
+                       nr_refcnts = desc->pdata->nr_outport;
+       }
+
+       refcnts = kcalloc(nr_refcnts, sizeof(*refcnts), GFP_KERNEL);
+       if (!refcnts) {
+               ret = -ENOMEM;
+               goto err_kzalloc_refcnts;
+       }
+
+       csdev->refcnt = refcnts;
+
+       csdev->nr_inport = desc->pdata->nr_inport;
+       csdev->nr_outport = desc->pdata->nr_outport;
+       conns = kcalloc(csdev->nr_outport, sizeof(*conns), GFP_KERNEL);
+       if (!conns) {
+               ret = -ENOMEM;
+               goto err_kzalloc_conns;
+       }
+
+       for (i = 0; i < csdev->nr_outport; i++) {
+               conns[i].outport = desc->pdata->outports[i];
+               conns[i].child_name = desc->pdata->child_names[i];
+               conns[i].child_port = desc->pdata->child_ports[i];
+       }
+
+       csdev->conns = conns;
+
+       csdev->type = desc->type;
+       csdev->subtype = desc->subtype;
+       csdev->ops = desc->ops;
+       csdev->orphan = false;
+
+       csdev->dev.type = &coresight_dev_type[desc->type];
+       csdev->dev.groups = desc->groups;
+       csdev->dev.parent = desc->dev;
+       csdev->dev.release = coresight_device_release;
+       csdev->dev.bus = &coresight_bustype;
+       dev_set_name(&csdev->dev, "%s", desc->pdata->name);
+
+       ret = device_register(&csdev->dev);
+       if (ret)
+               goto err_device_register;
+
+       mutex_lock(&coresight_mutex);
+
+       coresight_fixup_device_conns(csdev);
+       coresight_fixup_orphan_conns(csdev);
+
+       mutex_unlock(&coresight_mutex);
+
+       return csdev;
+
+err_device_register:
+       kfree(conns);
+err_kzalloc_conns:
+       kfree(refcnts);
+err_kzalloc_refcnts:
+       kfree(csdev);
+err_kzalloc_csdev:
+       return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(coresight_register);
+
+void coresight_unregister(struct coresight_device *csdev)
+{
+       mutex_lock(&coresight_mutex);
+
+       kfree(csdev->conns);
+       device_unregister(&csdev->dev);
+
+       mutex_unlock(&coresight_mutex);
+}
+EXPORT_SYMBOL_GPL(coresight_unregister);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hwtracing/coresight/of_coresight.c b/drivers/hwtracing/coresight/of_coresight.c
new file mode 100644 (file)
index 0000000..35e51ce
--- /dev/null
@@ -0,0 +1,191 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_graph.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/amba/bus.h>
+#include <linux/coresight.h>
+#include <linux/cpumask.h>
+#include <asm/smp_plat.h>
+
+
+static int of_dev_node_match(struct device *dev, void *data)
+{
+       return dev->of_node == data;
+}
+
+static struct device *
+of_coresight_get_endpoint_device(struct device_node *endpoint)
+{
+       struct device *dev = NULL;
+
+       /*
+        * If we have a non-configuable replicator, it will be found on the
+        * platform bus.
+        */
+       dev = bus_find_device(&platform_bus_type, NULL,
+                             endpoint, of_dev_node_match);
+       if (dev)
+               return dev;
+
+       /*
+        * We have a configurable component - circle through the AMBA bus
+        * looking for the device that matches the endpoint node.
+        */
+       return bus_find_device(&amba_bustype, NULL,
+                              endpoint, of_dev_node_match);
+}
+
+static void of_coresight_get_ports(struct device_node *node,
+                                  int *nr_inport, int *nr_outport)
+{
+       struct device_node *ep = NULL;
+       int in = 0, out = 0;
+
+       do {
+               ep = of_graph_get_next_endpoint(node, ep);
+               if (!ep)
+                       break;
+
+               if (of_property_read_bool(ep, "slave-mode"))
+                       in++;
+               else
+                       out++;
+
+       } while (ep);
+
+       *nr_inport = in;
+       *nr_outport = out;
+}
+
+static int of_coresight_alloc_memory(struct device *dev,
+                       struct coresight_platform_data *pdata)
+{
+       /* List of output port on this component */
+       pdata->outports = devm_kzalloc(dev, pdata->nr_outport *
+                                      sizeof(*pdata->outports),
+                                      GFP_KERNEL);
+       if (!pdata->outports)
+               return -ENOMEM;
+
+       /* Children connected to this component via @outports */
+        pdata->child_names = devm_kzalloc(dev, pdata->nr_outport *
+                                         sizeof(*pdata->child_names),
+                                         GFP_KERNEL);
+       if (!pdata->child_names)
+               return -ENOMEM;
+
+       /* Port number on the child this component is connected to */
+       pdata->child_ports = devm_kzalloc(dev, pdata->nr_outport *
+                                         sizeof(*pdata->child_ports),
+                                         GFP_KERNEL);
+       if (!pdata->child_ports)
+               return -ENOMEM;
+
+       return 0;
+}
+
+struct coresight_platform_data *of_get_coresight_platform_data(
+                               struct device *dev, struct device_node *node)
+{
+       int i = 0, ret = 0, cpu;
+       struct coresight_platform_data *pdata;
+       struct of_endpoint endpoint, rendpoint;
+       struct device *rdev;
+       struct device_node *dn;
+       struct device_node *ep = NULL;
+       struct device_node *rparent = NULL;
+       struct device_node *rport = NULL;
+
+       pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return ERR_PTR(-ENOMEM);
+
+       /* Use device name as sysfs handle */
+       pdata->name = dev_name(dev);
+
+       /* Get the number of input and output port for this component */
+       of_coresight_get_ports(node, &pdata->nr_inport, &pdata->nr_outport);
+
+       if (pdata->nr_outport) {
+               ret = of_coresight_alloc_memory(dev, pdata);
+               if (ret)
+                       return ERR_PTR(ret);
+
+               /* Iterate through each port to discover topology */
+               do {
+                       /* Get a handle on a port */
+                       ep = of_graph_get_next_endpoint(node, ep);
+                       if (!ep)
+                               break;
+
+                       /*
+                        * No need to deal with input ports, processing for as
+                        * processing for output ports will deal with them.
+                        */
+                       if (of_find_property(ep, "slave-mode", NULL))
+                               continue;
+
+                       /* Get a handle on the local endpoint */
+                       ret = of_graph_parse_endpoint(ep, &endpoint);
+
+                       if (ret)
+                               continue;
+
+                       /* The local out port number */
+                       pdata->outports[i] = endpoint.id;
+
+                       /*
+                        * Get a handle on the remote port and parent
+                        * attached to it.
+                        */
+                       rparent = of_graph_get_remote_port_parent(ep);
+                       rport = of_graph_get_remote_port(ep);
+
+                       if (!rparent || !rport)
+                               continue;
+
+                       if (of_graph_parse_endpoint(rport, &rendpoint))
+                               continue;
+
+                       rdev = of_coresight_get_endpoint_device(rparent);
+                       if (!rdev)
+                               continue;
+
+                       pdata->child_names[i] = dev_name(rdev);
+                       pdata->child_ports[i] = rendpoint.id;
+
+                       i++;
+               } while (ep);
+       }
+
+       /* Affinity defaults to CPU0 */
+       pdata->cpu = 0;
+       dn = of_parse_phandle(node, "cpu", 0);
+       for (cpu = 0; dn && cpu < nr_cpu_ids; cpu++) {
+               if (dn == of_get_cpu_node(cpu, NULL)) {
+                       pdata->cpu = cpu;
+                       break;
+               }
+       }
+
+       return pdata;
+}
+EXPORT_SYMBOL_GPL(of_get_coresight_platform_data);
index 875c22ae54004d4aba33c4a72c4bc398d47ac0a8..fa8dedd8c3a2f88ca0fdf05ce784b79f3852c51c 100644 (file)
@@ -182,72 +182,41 @@ static int ec_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg i2c_msgs[],
        const u16 bus_num = bus->remote_bus;
        int request_len;
        int response_len;
-       u8 *request = NULL;
-       u8 *response = NULL;
        int result;
-       struct cros_ec_command msg;
+       struct cros_ec_command msg = { };
 
        request_len = ec_i2c_count_message(i2c_msgs, num);
        if (request_len < 0) {
                dev_warn(dev, "Error constructing message %d\n", request_len);
-               result = request_len;
-               goto exit;
+               return request_len;
        }
+
        response_len = ec_i2c_count_response(i2c_msgs, num);
        if (response_len < 0) {
                /* Unexpected; no errors should come when NULL response */
                dev_warn(dev, "Error preparing response %d\n", response_len);
-               result = response_len;
-               goto exit;
-       }
-
-       if (request_len <= ARRAY_SIZE(bus->request_buf)) {
-               request = bus->request_buf;
-       } else {
-               request = kzalloc(request_len, GFP_KERNEL);
-               if (request == NULL) {
-                       result = -ENOMEM;
-                       goto exit;
-               }
-       }
-       if (response_len <= ARRAY_SIZE(bus->response_buf)) {
-               response = bus->response_buf;
-       } else {
-               response = kzalloc(response_len, GFP_KERNEL);
-               if (response == NULL) {
-                       result = -ENOMEM;
-                       goto exit;
-               }
+               return response_len;
        }
 
-       result = ec_i2c_construct_message(request, i2c_msgs, num, bus_num);
+       result = ec_i2c_construct_message(msg.outdata, i2c_msgs, num, bus_num);
        if (result)
-               goto exit;
+               return result;
 
        msg.version = 0;
        msg.command = EC_CMD_I2C_PASSTHRU;
-       msg.outdata = request;
        msg.outsize = request_len;
-       msg.indata = response;
        msg.insize = response_len;
 
        result = cros_ec_cmd_xfer(bus->ec, &msg);
        if (result < 0)
-               goto exit;
+               return result;
 
-       result = ec_i2c_parse_response(response, i2c_msgs, &num);
+       result = ec_i2c_parse_response(msg.indata, i2c_msgs, &num);
        if (result < 0)
-               goto exit;
+               return result;
 
        /* Indicate success by saying how many messages were sent */
-       result = num;
-exit:
-       if (request != bus->request_buf)
-               kfree(request);
-       if (response != bus->response_buf)
-               kfree(response);
-
-       return result;
+       return num;
 }
 
 static u32 ec_i2c_functionality(struct i2c_adapter *adap)
index 03f1e5549896dcda86a1f9b1e73a882bcdc8a923..9604024e0eb0959e4b77816214eaf3ac939c29ca 100644 (file)
 
 #include <linux/clk.h>
 #include <linux/completion.h>
+#include <linux/delay.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/of.h>
index 56fceff6ba1422eb5eb3b0d32f1835a489925c28..3e84f6c090a56979279fa4508d486461b9ede17b 100644 (file)
@@ -913,7 +913,7 @@ static void __exit mxs_i2c_exit(void)
 module_exit(mxs_i2c_exit);
 
 MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
-MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>");
+MODULE_AUTHOR("Wolfram Sang <kernel@pengutronix.de>");
 MODULE_DESCRIPTION("MXS I2C Bus Driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:" DRIVER_NAME);
index 6336f02ec56682913e5862b4539024e047b2f25e..3bd2e7d06e4bbed113c48056d6130d59d01e5513 100644 (file)
@@ -285,6 +285,6 @@ static struct platform_driver i2c_pca_pf_driver = {
 
 module_platform_driver(i2c_pca_pf_driver);
 
-MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>");
+MODULE_AUTHOR("Wolfram Sang <kernel@pengutronix.de>");
 MODULE_DESCRIPTION("I2C-PCA9564/PCA9665 platform driver");
 MODULE_LICENSE("GPL");
index 5f96b1b3e3a5a30e2163098e4afe94fc4a06deeb..019d5426fe529edeead3f4f86f0bde9f388f1803 100644 (file)
@@ -833,7 +833,7 @@ static int rk3x_i2c_xfer(struct i2c_adapter *adap,
        clk_disable(i2c->clk);
        spin_unlock_irqrestore(&i2c->lock, flags);
 
-       return ret;
+       return ret < 0 ? ret : num;
 }
 
 static u32 rk3x_i2c_func(struct i2c_adapter *adap)
index 88057fad9dfef494e2d6a4ee0f0ab337bbbb3dc9..ea72dca32fdfde83cfdd223525a915a5721d6816 100644 (file)
  * published by the Free Software Foundation.
  */
 
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
 #include <linux/clk.h>
-#include <linux/io.h>
 #include <linux/delay.h>
-#include <linux/interrupt.h>
 #include <linux/err.h>
-#include <linux/of.h>
+#include <linux/i2c.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/of.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
 
 /* SSC registers */
 #define SSC_BRG                                0x000
index 098f698fe8f4708afc6b2d5785a7b4be8635a428..987c124432c501f7a5cabb83bdc638c0f337fcb7 100644 (file)
@@ -1413,6 +1413,8 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
 
        dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
 
+       pm_runtime_no_callbacks(&adap->dev);
+
 #ifdef CONFIG_I2C_COMPAT
        res = class_compat_create_link(i2c_adapter_compat_class, &adap->dev,
                                       adap->dev.parent);
index 593f7ca9adc783fb4f859f324b05e3acce882b7e..06cc1ff088f12bf332bc7e47d2d97603574a2e96 100644 (file)
@@ -32,8 +32,9 @@ struct i2c_mux_priv {
        struct i2c_algorithm algo;
 
        struct i2c_adapter *parent;
-       void *mux_priv; /* the mux chip/device */
-       u32  chan_id;   /* the channel id */
+       struct device *mux_dev;
+       void *mux_priv;
+       u32 chan_id;
 
        int (*select)(struct i2c_adapter *, void *mux_priv, u32 chan_id);
        int (*deselect)(struct i2c_adapter *, void *mux_priv, u32 chan_id);
@@ -119,6 +120,7 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
 
        /* Set up private adapter data */
        priv->parent = parent;
+       priv->mux_dev = mux_dev;
        priv->mux_priv = mux_priv;
        priv->chan_id = chan_id;
        priv->select = select;
@@ -203,7 +205,7 @@ void i2c_del_mux_adapter(struct i2c_adapter *adap)
        char symlink_name[20];
 
        snprintf(symlink_name, sizeof(symlink_name), "channel-%u", priv->chan_id);
-       sysfs_remove_link(&adap->dev.parent->kobj, symlink_name);
+       sysfs_remove_link(&priv->mux_dev->kobj, symlink_name);
 
        sysfs_remove_link(&priv->adap.dev.kobj, "mux_device");
        i2c_del_adapter(adap);
index f80da50d84a5b6585a10656b369bcc33aedd0507..38339d220d7f52c402c08f581f20cf4ad8acea49 100644 (file)
@@ -472,13 +472,8 @@ int rdma_addr_find_dmac_by_grh(union ib_gid *sgid, union ib_gid *dgid, u8 *dmac,
        } sgid_addr, dgid_addr;
 
 
-       ret = rdma_gid2ip(&sgid_addr._sockaddr, sgid);
-       if (ret)
-               return ret;
-
-       ret = rdma_gid2ip(&dgid_addr._sockaddr, dgid);
-       if (ret)
-               return ret;
+       rdma_gid2ip(&sgid_addr._sockaddr, sgid);
+       rdma_gid2ip(&dgid_addr._sockaddr, dgid);
 
        memset(&dev_addr, 0, sizeof(dev_addr));
 
@@ -512,10 +507,8 @@ int rdma_addr_find_smac_by_sgid(union ib_gid *sgid, u8 *smac, u16 *vlan_id)
                struct sockaddr_in6 _sockaddr_in6;
        } gid_addr;
 
-       ret = rdma_gid2ip(&gid_addr._sockaddr, sgid);
+       rdma_gid2ip(&gid_addr._sockaddr, sgid);
 
-       if (ret)
-               return ret;
        memset(&dev_addr, 0, sizeof(dev_addr));
        ret = rdma_translate_ip(&gid_addr._sockaddr, &dev_addr, vlan_id);
        if (ret)
index e28a494e2a3a0f72b41af479b269262c6472cb77..0c1419105ff083ce40bb576e60f03911dee91270 100644 (file)
@@ -437,39 +437,38 @@ static struct cm_id_private * cm_acquire_id(__be32 local_id, __be32 remote_id)
        return cm_id_priv;
 }
 
-static void cm_mask_copy(u8 *dst, u8 *src, u8 *mask)
+static void cm_mask_copy(u32 *dst, const u32 *src, const u32 *mask)
 {
        int i;
 
-       for (i = 0; i < IB_CM_COMPARE_SIZE / sizeof(unsigned long); i++)
-               ((unsigned long *) dst)[i] = ((unsigned long *) src)[i] &
-                                            ((unsigned long *) mask)[i];
+       for (i = 0; i < IB_CM_COMPARE_SIZE; i++)
+               dst[i] = src[i] & mask[i];
 }
 
 static int cm_compare_data(struct ib_cm_compare_data *src_data,
                           struct ib_cm_compare_data *dst_data)
 {
-       u8 src[IB_CM_COMPARE_SIZE];
-       u8 dst[IB_CM_COMPARE_SIZE];
+       u32 src[IB_CM_COMPARE_SIZE];
+       u32 dst[IB_CM_COMPARE_SIZE];
 
        if (!src_data || !dst_data)
                return 0;
 
        cm_mask_copy(src, src_data->data, dst_data->mask);
        cm_mask_copy(dst, dst_data->data, src_data->mask);
-       return memcmp(src, dst, IB_CM_COMPARE_SIZE);
+       return memcmp(src, dst, sizeof(src));
 }
 
-static int cm_compare_private_data(u8 *private_data,
+static int cm_compare_private_data(u32 *private_data,
                                   struct ib_cm_compare_data *dst_data)
 {
-       u8 src[IB_CM_COMPARE_SIZE];
+       u32 src[IB_CM_COMPARE_SIZE];
 
        if (!dst_data)
                return 0;
 
        cm_mask_copy(src, private_data, dst_data->mask);
-       return memcmp(src, dst_data->data, IB_CM_COMPARE_SIZE);
+       return memcmp(src, dst_data->data, sizeof(src));
 }
 
 /*
@@ -538,7 +537,7 @@ static struct cm_id_private * cm_insert_listen(struct cm_id_private *cm_id_priv)
 
 static struct cm_id_private * cm_find_listen(struct ib_device *device,
                                             __be64 service_id,
-                                            u8 *private_data)
+                                            u32 *private_data)
 {
        struct rb_node *node = cm.listen_service_table.rb_node;
        struct cm_id_private *cm_id_priv;
@@ -953,7 +952,7 @@ int ib_cm_listen(struct ib_cm_id *cm_id, __be64 service_id, __be64 service_mask,
                cm_mask_copy(cm_id_priv->compare_data->data,
                             compare_data->data, compare_data->mask);
                memcpy(cm_id_priv->compare_data->mask, compare_data->mask,
-                      IB_CM_COMPARE_SIZE);
+                      sizeof(compare_data->mask));
        }
 
        cm_id->state = IB_CM_LISTEN;
index be068f47e47e86b79065356e62bf1d193c1da36f..8b76f0ef965e88d7171e8cebcbaf2a0c9a29f962 100644 (file)
@@ -103,7 +103,7 @@ struct cm_req_msg {
        /* local ACK timeout:5, rsvd:3 */
        u8 alt_offset139;
 
-       u8 private_data[IB_CM_REQ_PRIVATE_DATA_SIZE];
+       u32 private_data[IB_CM_REQ_PRIVATE_DATA_SIZE / sizeof(u32)];
 
 } __attribute__ ((packed));
 
@@ -801,7 +801,7 @@ struct cm_sidr_req_msg {
        __be16 rsvd;
        __be64 service_id;
 
-       u8 private_data[IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE];
+       u32 private_data[IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE / sizeof(u32)];
 } __attribute__ ((packed));
 
 struct cm_sidr_rep_msg {
index d570030d899c0c662d2b208ce30dd2cd20bc3f78..06441a43c3aacd1c6aecb22e15a17529b4a890a8 100644 (file)
@@ -859,19 +859,27 @@ static void cma_save_ib_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_id
        memcpy(&ib->sib_addr, &path->dgid, 16);
 }
 
+static __be16 ss_get_port(const struct sockaddr_storage *ss)
+{
+       if (ss->ss_family == AF_INET)
+               return ((struct sockaddr_in *)ss)->sin_port;
+       else if (ss->ss_family == AF_INET6)
+               return ((struct sockaddr_in6 *)ss)->sin6_port;
+       BUG();
+}
+
 static void cma_save_ip4_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_id,
                              struct cma_hdr *hdr)
 {
-       struct sockaddr_in *listen4, *ip4;
+       struct sockaddr_in *ip4;
 
-       listen4 = (struct sockaddr_in *) &listen_id->route.addr.src_addr;
        ip4 = (struct sockaddr_in *) &id->route.addr.src_addr;
-       ip4->sin_family = listen4->sin_family;
+       ip4->sin_family = AF_INET;
        ip4->sin_addr.s_addr = hdr->dst_addr.ip4.addr;
-       ip4->sin_port = listen4->sin_port;
+       ip4->sin_port = ss_get_port(&listen_id->route.addr.src_addr);
 
        ip4 = (struct sockaddr_in *) &id->route.addr.dst_addr;
-       ip4->sin_family = listen4->sin_family;
+       ip4->sin_family = AF_INET;
        ip4->sin_addr.s_addr = hdr->src_addr.ip4.addr;
        ip4->sin_port = hdr->port;
 }
@@ -879,16 +887,15 @@ static void cma_save_ip4_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_i
 static void cma_save_ip6_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_id,
                              struct cma_hdr *hdr)
 {
-       struct sockaddr_in6 *listen6, *ip6;
+       struct sockaddr_in6 *ip6;
 
-       listen6 = (struct sockaddr_in6 *) &listen_id->route.addr.src_addr;
        ip6 = (struct sockaddr_in6 *) &id->route.addr.src_addr;
-       ip6->sin6_family = listen6->sin6_family;
+       ip6->sin6_family = AF_INET6;
        ip6->sin6_addr = hdr->dst_addr.ip6;
-       ip6->sin6_port = listen6->sin6_port;
+       ip6->sin6_port = ss_get_port(&listen_id->route.addr.src_addr);
 
        ip6 = (struct sockaddr_in6 *) &id->route.addr.dst_addr;
-       ip6->sin6_family = listen6->sin6_family;
+       ip6->sin6_family = AF_INET6;
        ip6->sin6_addr = hdr->src_addr.ip6;
        ip6->sin6_port = hdr->port;
 }
index b85ddbc979e069e909cee12ac37cd31be244652d..ab081702566fc47fd3fbbfe26a6ca7ef6bef58bc 100644 (file)
@@ -468,7 +468,8 @@ add_mapping_response_exit:
 }
 EXPORT_SYMBOL(iwpm_add_mapping_cb);
 
-/* netlink attribute policy for the response to add and query mapping request */
+/* netlink attribute policy for the response to add and query mapping request
+ * and response with remote address info */
 static const struct nla_policy resp_query_policy[IWPM_NLA_RQUERY_MAPPING_MAX] = {
        [IWPM_NLA_QUERY_MAPPING_SEQ]      = { .type = NLA_U32 },
        [IWPM_NLA_QUERY_LOCAL_ADDR]       = { .len = sizeof(struct sockaddr_storage) },
@@ -559,6 +560,76 @@ query_mapping_response_exit:
 }
 EXPORT_SYMBOL(iwpm_add_and_query_mapping_cb);
 
+/*
+ * iwpm_remote_info_cb - Process a port mapper message, containing
+ *                       the remote connecting peer address info
+ */
+int iwpm_remote_info_cb(struct sk_buff *skb, struct netlink_callback *cb)
+{
+       struct nlattr *nltb[IWPM_NLA_RQUERY_MAPPING_MAX];
+       struct sockaddr_storage *local_sockaddr, *remote_sockaddr;
+       struct sockaddr_storage *mapped_loc_sockaddr, *mapped_rem_sockaddr;
+       struct iwpm_remote_info *rem_info;
+       const char *msg_type;
+       u8 nl_client;
+       int ret = -EINVAL;
+
+       msg_type = "Remote Mapping info";
+       if (iwpm_parse_nlmsg(cb, IWPM_NLA_RQUERY_MAPPING_MAX,
+                               resp_query_policy, nltb, msg_type))
+               return ret;
+
+       nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type);
+       if (!iwpm_valid_client(nl_client)) {
+               pr_info("%s: Invalid port mapper client = %d\n",
+                               __func__, nl_client);
+               return ret;
+       }
+       atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
+
+       local_sockaddr = (struct sockaddr_storage *)
+                       nla_data(nltb[IWPM_NLA_QUERY_LOCAL_ADDR]);
+       remote_sockaddr = (struct sockaddr_storage *)
+                       nla_data(nltb[IWPM_NLA_QUERY_REMOTE_ADDR]);
+       mapped_loc_sockaddr = (struct sockaddr_storage *)
+                       nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_LOC_ADDR]);
+       mapped_rem_sockaddr = (struct sockaddr_storage *)
+                       nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_REM_ADDR]);
+
+       if (mapped_loc_sockaddr->ss_family != local_sockaddr->ss_family ||
+               mapped_rem_sockaddr->ss_family != remote_sockaddr->ss_family) {
+               pr_info("%s: Sockaddr family doesn't match the requested one\n",
+                               __func__);
+               return ret;
+       }
+       rem_info = kzalloc(sizeof(struct iwpm_remote_info), GFP_ATOMIC);
+       if (!rem_info) {
+               pr_err("%s: Unable to allocate a remote info\n", __func__);
+               ret = -ENOMEM;
+               return ret;
+       }
+       memcpy(&rem_info->mapped_loc_sockaddr, mapped_loc_sockaddr,
+              sizeof(struct sockaddr_storage));
+       memcpy(&rem_info->remote_sockaddr, remote_sockaddr,
+              sizeof(struct sockaddr_storage));
+       memcpy(&rem_info->mapped_rem_sockaddr, mapped_rem_sockaddr,
+              sizeof(struct sockaddr_storage));
+       rem_info->nl_client = nl_client;
+
+       iwpm_add_remote_info(rem_info);
+
+       iwpm_print_sockaddr(local_sockaddr,
+                       "remote_info: Local sockaddr:");
+       iwpm_print_sockaddr(mapped_loc_sockaddr,
+                       "remote_info: Mapped local sockaddr:");
+       iwpm_print_sockaddr(remote_sockaddr,
+                       "remote_info: Remote sockaddr:");
+       iwpm_print_sockaddr(mapped_rem_sockaddr,
+                       "remote_info: Mapped remote sockaddr:");
+       return ret;
+}
+EXPORT_SYMBOL(iwpm_remote_info_cb);
+
 /* netlink attribute policy for the received request for mapping info */
 static const struct nla_policy resp_mapinfo_policy[IWPM_NLA_MAPINFO_REQ_MAX] = {
        [IWPM_NLA_MAPINFO_ULIB_NAME] = { .type = NLA_STRING,
index 69e9f84c16056246bd5d45ca08293ce5b272ec84..a626795bf9c71f43f7d526d07ae3a490399fdb79 100644 (file)
 
 #include "iwpm_util.h"
 
-#define IWPM_HASH_BUCKET_SIZE  512
-#define IWPM_HASH_BUCKET_MASK  (IWPM_HASH_BUCKET_SIZE - 1)
+#define IWPM_MAPINFO_HASH_SIZE 512
+#define IWPM_MAPINFO_HASH_MASK (IWPM_MAPINFO_HASH_SIZE - 1)
+#define IWPM_REMINFO_HASH_SIZE 64
+#define IWPM_REMINFO_HASH_MASK (IWPM_REMINFO_HASH_SIZE - 1)
 
 static LIST_HEAD(iwpm_nlmsg_req_list);
 static DEFINE_SPINLOCK(iwpm_nlmsg_req_lock);
@@ -42,31 +44,49 @@ static DEFINE_SPINLOCK(iwpm_nlmsg_req_lock);
 static struct hlist_head *iwpm_hash_bucket;
 static DEFINE_SPINLOCK(iwpm_mapinfo_lock);
 
+static struct hlist_head *iwpm_reminfo_bucket;
+static DEFINE_SPINLOCK(iwpm_reminfo_lock);
+
 static DEFINE_MUTEX(iwpm_admin_lock);
 static struct iwpm_admin_data iwpm_admin;
 
 int iwpm_init(u8 nl_client)
 {
+       int ret = 0;
        if (iwpm_valid_client(nl_client))
                return -EINVAL;
        mutex_lock(&iwpm_admin_lock);
        if (atomic_read(&iwpm_admin.refcount) == 0) {
-               iwpm_hash_bucket = kzalloc(IWPM_HASH_BUCKET_SIZE *
+               iwpm_hash_bucket = kzalloc(IWPM_MAPINFO_HASH_SIZE *
                                        sizeof(struct hlist_head), GFP_KERNEL);
                if (!iwpm_hash_bucket) {
-                       mutex_unlock(&iwpm_admin_lock);
+                       ret = -ENOMEM;
                        pr_err("%s Unable to create mapinfo hash table\n", __func__);
-                       return -ENOMEM;
+                       goto init_exit;
+               }
+               iwpm_reminfo_bucket = kzalloc(IWPM_REMINFO_HASH_SIZE *
+                                       sizeof(struct hlist_head), GFP_KERNEL);
+               if (!iwpm_reminfo_bucket) {
+                       kfree(iwpm_hash_bucket);
+                       ret = -ENOMEM;
+                       pr_err("%s Unable to create reminfo hash table\n", __func__);
+                       goto init_exit;
                }
        }
        atomic_inc(&iwpm_admin.refcount);
+init_exit:
        mutex_unlock(&iwpm_admin_lock);
-       iwpm_set_valid(nl_client, 1);
-       return 0;
+       if (!ret) {
+               iwpm_set_valid(nl_client, 1);
+               pr_debug("%s: Mapinfo and reminfo tables are created\n",
+                               __func__);
+       }
+       return ret;
 }
 EXPORT_SYMBOL(iwpm_init);
 
 static void free_hash_bucket(void);
+static void free_reminfo_bucket(void);
 
 int iwpm_exit(u8 nl_client)
 {
@@ -81,7 +101,8 @@ int iwpm_exit(u8 nl_client)
        }
        if (atomic_dec_and_test(&iwpm_admin.refcount)) {
                free_hash_bucket();
-               pr_debug("%s: Mapinfo hash table is destroyed\n", __func__);
+               free_reminfo_bucket();
+               pr_debug("%s: Resources are destroyed\n", __func__);
        }
        mutex_unlock(&iwpm_admin_lock);
        iwpm_set_valid(nl_client, 0);
@@ -89,7 +110,7 @@ int iwpm_exit(u8 nl_client)
 }
 EXPORT_SYMBOL(iwpm_exit);
 
-static struct hlist_head *get_hash_bucket_head(struct sockaddr_storage *,
+static struct hlist_head *get_mapinfo_hash_bucket(struct sockaddr_storage *,
                                               struct sockaddr_storage *);
 
 int iwpm_create_mapinfo(struct sockaddr_storage *local_sockaddr,
@@ -99,9 +120,10 @@ int iwpm_create_mapinfo(struct sockaddr_storage *local_sockaddr,
        struct hlist_head *hash_bucket_head;
        struct iwpm_mapping_info *map_info;
        unsigned long flags;
+       int ret = -EINVAL;
 
        if (!iwpm_valid_client(nl_client))
-               return -EINVAL;
+               return ret;
        map_info = kzalloc(sizeof(struct iwpm_mapping_info), GFP_KERNEL);
        if (!map_info) {
                pr_err("%s: Unable to allocate a mapping info\n", __func__);
@@ -115,13 +137,16 @@ int iwpm_create_mapinfo(struct sockaddr_storage *local_sockaddr,
 
        spin_lock_irqsave(&iwpm_mapinfo_lock, flags);
        if (iwpm_hash_bucket) {
-               hash_bucket_head = get_hash_bucket_head(
+               hash_bucket_head = get_mapinfo_hash_bucket(
                                        &map_info->local_sockaddr,
                                        &map_info->mapped_sockaddr);
-               hlist_add_head(&map_info->hlist_node, hash_bucket_head);
+               if (hash_bucket_head) {
+                       hlist_add_head(&map_info->hlist_node, hash_bucket_head);
+                       ret = 0;
+               }
        }
        spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags);
-       return 0;
+       return ret;
 }
 EXPORT_SYMBOL(iwpm_create_mapinfo);
 
@@ -136,9 +161,12 @@ int iwpm_remove_mapinfo(struct sockaddr_storage *local_sockaddr,
 
        spin_lock_irqsave(&iwpm_mapinfo_lock, flags);
        if (iwpm_hash_bucket) {
-               hash_bucket_head = get_hash_bucket_head(
+               hash_bucket_head = get_mapinfo_hash_bucket(
                                        local_sockaddr,
                                        mapped_local_addr);
+               if (!hash_bucket_head)
+                       goto remove_mapinfo_exit;
+
                hlist_for_each_entry_safe(map_info, tmp_hlist_node,
                                        hash_bucket_head, hlist_node) {
 
@@ -152,6 +180,7 @@ int iwpm_remove_mapinfo(struct sockaddr_storage *local_sockaddr,
                        }
                }
        }
+remove_mapinfo_exit:
        spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags);
        return ret;
 }
@@ -166,7 +195,7 @@ static void free_hash_bucket(void)
 
        /* remove all the mapinfo data from the list */
        spin_lock_irqsave(&iwpm_mapinfo_lock, flags);
-       for (i = 0; i < IWPM_HASH_BUCKET_SIZE; i++) {
+       for (i = 0; i < IWPM_MAPINFO_HASH_SIZE; i++) {
                hlist_for_each_entry_safe(map_info, tmp_hlist_node,
                        &iwpm_hash_bucket[i], hlist_node) {
 
@@ -180,6 +209,96 @@ static void free_hash_bucket(void)
        spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags);
 }
 
+static void free_reminfo_bucket(void)
+{
+       struct hlist_node *tmp_hlist_node;
+       struct iwpm_remote_info *rem_info;
+       unsigned long flags;
+       int i;
+
+       /* remove all the remote info from the list */
+       spin_lock_irqsave(&iwpm_reminfo_lock, flags);
+       for (i = 0; i < IWPM_REMINFO_HASH_SIZE; i++) {
+               hlist_for_each_entry_safe(rem_info, tmp_hlist_node,
+                       &iwpm_reminfo_bucket[i], hlist_node) {
+
+                               hlist_del_init(&rem_info->hlist_node);
+                               kfree(rem_info);
+                       }
+       }
+       /* free the hash list */
+       kfree(iwpm_reminfo_bucket);
+       iwpm_reminfo_bucket = NULL;
+       spin_unlock_irqrestore(&iwpm_reminfo_lock, flags);
+}
+
+static struct hlist_head *get_reminfo_hash_bucket(struct sockaddr_storage *,
+                                               struct sockaddr_storage *);
+
+void iwpm_add_remote_info(struct iwpm_remote_info *rem_info)
+{
+       struct hlist_head *hash_bucket_head;
+       unsigned long flags;
+
+       spin_lock_irqsave(&iwpm_reminfo_lock, flags);
+       if (iwpm_reminfo_bucket) {
+               hash_bucket_head = get_reminfo_hash_bucket(
+                                       &rem_info->mapped_loc_sockaddr,
+                                       &rem_info->mapped_rem_sockaddr);
+               if (hash_bucket_head)
+                       hlist_add_head(&rem_info->hlist_node, hash_bucket_head);
+       }
+       spin_unlock_irqrestore(&iwpm_reminfo_lock, flags);
+}
+
+int iwpm_get_remote_info(struct sockaddr_storage *mapped_loc_addr,
+                               struct sockaddr_storage *mapped_rem_addr,
+                               struct sockaddr_storage *remote_addr,
+                               u8 nl_client)
+{
+       struct hlist_node *tmp_hlist_node;
+       struct hlist_head *hash_bucket_head;
+       struct iwpm_remote_info *rem_info = NULL;
+       unsigned long flags;
+       int ret = -EINVAL;
+
+       if (!iwpm_valid_client(nl_client)) {
+               pr_info("%s: Invalid client = %d\n", __func__, nl_client);
+               return ret;
+       }
+       spin_lock_irqsave(&iwpm_reminfo_lock, flags);
+       if (iwpm_reminfo_bucket) {
+               hash_bucket_head = get_reminfo_hash_bucket(
+                                       mapped_loc_addr,
+                                       mapped_rem_addr);
+               if (!hash_bucket_head)
+                       goto get_remote_info_exit;
+               hlist_for_each_entry_safe(rem_info, tmp_hlist_node,
+                                       hash_bucket_head, hlist_node) {
+
+                       if (!iwpm_compare_sockaddr(&rem_info->mapped_loc_sockaddr,
+                               mapped_loc_addr) &&
+                               !iwpm_compare_sockaddr(&rem_info->mapped_rem_sockaddr,
+                               mapped_rem_addr)) {
+
+                               memcpy(remote_addr, &rem_info->remote_sockaddr,
+                                       sizeof(struct sockaddr_storage));
+                               iwpm_print_sockaddr(remote_addr,
+                                               "get_remote_info: Remote sockaddr:");
+
+                               hlist_del_init(&rem_info->hlist_node);
+                               kfree(rem_info);
+                               ret = 0;
+                               break;
+                       }
+               }
+       }
+get_remote_info_exit:
+       spin_unlock_irqrestore(&iwpm_reminfo_lock, flags);
+       return ret;
+}
+EXPORT_SYMBOL(iwpm_get_remote_info);
+
 struct iwpm_nlmsg_request *iwpm_get_nlmsg_request(__u32 nlmsg_seq,
                                        u8 nl_client, gfp_t gfp)
 {
@@ -409,31 +528,54 @@ static u32 iwpm_ipv4_jhash(struct sockaddr_in *ipv4_sockaddr)
        return hash;
 }
 
-static struct hlist_head *get_hash_bucket_head(struct sockaddr_storage
-                                              *local_sockaddr,
-                                              struct sockaddr_storage
-                                              *mapped_sockaddr)
+static int get_hash_bucket(struct sockaddr_storage *a_sockaddr,
+                               struct sockaddr_storage *b_sockaddr, u32 *hash)
 {
-       u32 local_hash, mapped_hash, hash;
+       u32 a_hash, b_hash;
 
-       if (local_sockaddr->ss_family == AF_INET) {
-               local_hash = iwpm_ipv4_jhash((struct sockaddr_in *) local_sockaddr);
-               mapped_hash = iwpm_ipv4_jhash((struct sockaddr_in *) mapped_sockaddr);
+       if (a_sockaddr->ss_family == AF_INET) {
+               a_hash = iwpm_ipv4_jhash((struct sockaddr_in *) a_sockaddr);
+               b_hash = iwpm_ipv4_jhash((struct sockaddr_in *) b_sockaddr);
 
-       } else if (local_sockaddr->ss_family == AF_INET6) {
-               local_hash = iwpm_ipv6_jhash((struct sockaddr_in6 *) local_sockaddr);
-               mapped_hash = iwpm_ipv6_jhash((struct sockaddr_in6 *) mapped_sockaddr);
+       } else if (a_sockaddr->ss_family == AF_INET6) {
+               a_hash = iwpm_ipv6_jhash((struct sockaddr_in6 *) a_sockaddr);
+               b_hash = iwpm_ipv6_jhash((struct sockaddr_in6 *) b_sockaddr);
        } else {
                pr_err("%s: Invalid sockaddr family\n", __func__);
-               return NULL;
+               return -EINVAL;
        }
 
-       if (local_hash == mapped_hash) /* if port mapper isn't available */
-               hash = local_hash;
+       if (a_hash == b_hash) /* if port mapper isn't available */
+               *hash = a_hash;
        else
-               hash = jhash_2words(local_hash, mapped_hash, 0);
+               *hash = jhash_2words(a_hash, b_hash, 0);
+       return 0;
+}
+
+static struct hlist_head *get_mapinfo_hash_bucket(struct sockaddr_storage
+                               *local_sockaddr, struct sockaddr_storage
+                               *mapped_sockaddr)
+{
+       u32 hash;
+       int ret;
 
-       return &iwpm_hash_bucket[hash & IWPM_HASH_BUCKET_MASK];
+       ret = get_hash_bucket(local_sockaddr, mapped_sockaddr, &hash);
+       if (ret)
+               return NULL;
+       return &iwpm_hash_bucket[hash & IWPM_MAPINFO_HASH_MASK];
+}
+
+static struct hlist_head *get_reminfo_hash_bucket(struct sockaddr_storage
+                               *mapped_loc_sockaddr, struct sockaddr_storage
+                               *mapped_rem_sockaddr)
+{
+       u32 hash;
+       int ret;
+
+       ret = get_hash_bucket(mapped_loc_sockaddr, mapped_rem_sockaddr, &hash);
+       if (ret)
+               return NULL;
+       return &iwpm_reminfo_bucket[hash & IWPM_REMINFO_HASH_MASK];
 }
 
 static int send_mapinfo_num(u32 mapping_num, u8 nl_client, int iwpm_pid)
@@ -512,7 +654,7 @@ int iwpm_send_mapinfo(u8 nl_client, int iwpm_pid)
        }
        skb_num++;
        spin_lock_irqsave(&iwpm_mapinfo_lock, flags);
-       for (i = 0; i < IWPM_HASH_BUCKET_SIZE; i++) {
+       for (i = 0; i < IWPM_MAPINFO_HASH_SIZE; i++) {
                hlist_for_each_entry(map_info, &iwpm_hash_bucket[i],
                                     hlist_node) {
                        if (map_info->nl_client != nl_client)
@@ -595,7 +737,7 @@ int iwpm_mapinfo_available(void)
 
        spin_lock_irqsave(&iwpm_mapinfo_lock, flags);
        if (iwpm_hash_bucket) {
-               for (i = 0; i < IWPM_HASH_BUCKET_SIZE; i++) {
+               for (i = 0; i < IWPM_MAPINFO_HASH_SIZE; i++) {
                        if (!hlist_empty(&iwpm_hash_bucket[i])) {
                                full_bucket = 1;
                                break;
index 9777c869a1405d54ab47f5132595bd3868953383..ee2d9ff095be2d68d14c9c48eb551f9647ca562f 100644 (file)
@@ -76,6 +76,14 @@ struct iwpm_mapping_info {
        u8     nl_client;
 };
 
+struct iwpm_remote_info {
+       struct hlist_node hlist_node;
+       struct sockaddr_storage remote_sockaddr;
+       struct sockaddr_storage mapped_loc_sockaddr;
+       struct sockaddr_storage mapped_rem_sockaddr;
+       u8     nl_client;
+};
+
 struct iwpm_admin_data {
        atomic_t refcount;
        atomic_t nlmsg_seq;
@@ -127,6 +135,13 @@ int iwpm_wait_complete_req(struct iwpm_nlmsg_request *nlmsg_request);
  */
 int iwpm_get_nlmsg_seq(void);
 
+/**
+ * iwpm_add_reminfo - Add remote address info of the connecting peer
+ *                    to the remote info hash table
+ * @reminfo: The remote info to be added
+ */
+void iwpm_add_remote_info(struct iwpm_remote_info *reminfo);
+
 /**
  * iwpm_valid_client - Check if the port mapper client is valid
  * @nl_client: The index of the netlink client
index 8c014b5dab4c82ff805a744c89655555a56094fc..38acb3cfc545f91658f0d465b69914de99f281b2 100644 (file)
@@ -99,12 +99,15 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
        if (dmasync)
                dma_set_attr(DMA_ATTR_WRITE_BARRIER, &attrs);
 
+       if (!size)
+               return ERR_PTR(-EINVAL);
+
        /*
         * If the combination of the addr and size requested for this memory
         * region causes an integer overflow, return error.
         */
-       if ((PAGE_ALIGN(addr + size) <= size) ||
-           (PAGE_ALIGN(addr + size) <= addr))
+       if (((addr + size) < addr) ||
+           PAGE_ALIGN(addr + size) < (addr + size))
                return ERR_PTR(-EINVAL);
 
        if (!can_do_mlock())
index 8b8cc6fa0ab0c1ebf966b2ace4932807d9181bf1..40becdb3196e07b97c94ade818af5755bfaae4db 100644 (file)
@@ -446,7 +446,6 @@ static int ib_umem_odp_map_dma_single_page(
        int remove_existing_mapping = 0;
        int ret = 0;
 
-       mutex_lock(&umem->odp_data->umem_mutex);
        /*
         * Note: we avoid writing if seq is different from the initial seq, to
         * handle case of a racing notifier. This check also allows us to bail
@@ -479,8 +478,6 @@ static int ib_umem_odp_map_dma_single_page(
        }
 
 out:
-       mutex_unlock(&umem->odp_data->umem_mutex);
-
        /* On Demand Paging - avoid pinning the page */
        if (umem->context->invalidate_range || !stored_page)
                put_page(page);
@@ -586,6 +583,7 @@ int ib_umem_odp_map_dma_pages(struct ib_umem *umem, u64 user_virt, u64 bcnt,
 
                bcnt -= min_t(size_t, npages << PAGE_SHIFT, bcnt);
                user_virt += npages << PAGE_SHIFT;
+               mutex_lock(&umem->odp_data->umem_mutex);
                for (j = 0; j < npages; ++j) {
                        ret = ib_umem_odp_map_dma_single_page(
                                umem, k, base_virt_addr, local_page_list[j],
@@ -594,6 +592,7 @@ int ib_umem_odp_map_dma_pages(struct ib_umem *umem, u64 user_virt, u64 bcnt,
                                break;
                        k++;
                }
+               mutex_unlock(&umem->odp_data->umem_mutex);
 
                if (ret < 0) {
                        /* Release left over pages when handling errors. */
@@ -633,12 +632,11 @@ void ib_umem_odp_unmap_dma_pages(struct ib_umem *umem, u64 virt,
         * faults from completion. We might be racing with other
         * invalidations, so we must make sure we free each page only
         * once. */
+       mutex_lock(&umem->odp_data->umem_mutex);
        for (addr = virt; addr < bound; addr += (u64)umem->page_size) {
                idx = (addr - ib_umem_start(umem)) / PAGE_SIZE;
-               mutex_lock(&umem->odp_data->umem_mutex);
                if (umem->odp_data->page_list[idx]) {
                        struct page *page = umem->odp_data->page_list[idx];
-                       struct page *head_page = compound_head(page);
                        dma_addr_t dma = umem->odp_data->dma_list[idx];
                        dma_addr_t dma_addr = dma & ODP_DMA_ADDR_MASK;
 
@@ -646,7 +644,8 @@ void ib_umem_odp_unmap_dma_pages(struct ib_umem *umem, u64 virt,
 
                        ib_dma_unmap_page(dev, dma_addr, PAGE_SIZE,
                                          DMA_BIDIRECTIONAL);
-                       if (dma & ODP_WRITE_ALLOWED_BIT)
+                       if (dma & ODP_WRITE_ALLOWED_BIT) {
+                               struct page *head_page = compound_head(page);
                                /*
                                 * set_page_dirty prefers being called with
                                 * the page lock. However, MMU notifiers are
@@ -657,13 +656,14 @@ void ib_umem_odp_unmap_dma_pages(struct ib_umem *umem, u64 virt,
                                 * be removed.
                                 */
                                set_page_dirty(head_page);
+                       }
                        /* on demand pinning support */
                        if (!umem->context->invalidate_range)
                                put_page(page);
                        umem->odp_data->page_list[idx] = NULL;
                        umem->odp_data->dma_list[idx] = 0;
                }
-               mutex_unlock(&umem->odp_data->umem_mutex);
        }
+       mutex_unlock(&umem->odp_data->umem_mutex);
 }
 EXPORT_SYMBOL(ib_umem_odp_unmap_dma_pages);
index 259dcc7779f5e01bc95b66ca90e64d20f7c94087..88cce9bb72fea78a7d03f9c556b394807ca87215 100644 (file)
@@ -246,6 +246,17 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
                kfree(uqp);
        }
 
+       list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) {
+               struct ib_srq *srq = uobj->object;
+               struct ib_uevent_object *uevent =
+                       container_of(uobj, struct ib_uevent_object, uobject);
+
+               idr_remove_uobj(&ib_uverbs_srq_idr, uobj);
+               ib_destroy_srq(srq);
+               ib_uverbs_release_uevent(file, uevent);
+               kfree(uevent);
+       }
+
        list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) {
                struct ib_cq *cq = uobj->object;
                struct ib_uverbs_event_file *ev_file = cq->cq_context;
@@ -258,17 +269,6 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
                kfree(ucq);
        }
 
-       list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) {
-               struct ib_srq *srq = uobj->object;
-               struct ib_uevent_object *uevent =
-                       container_of(uobj, struct ib_uevent_object, uobject);
-
-               idr_remove_uobj(&ib_uverbs_srq_idr, uobj);
-               ib_destroy_srq(srq);
-               ib_uverbs_release_uevent(file, uevent);
-               kfree(uevent);
-       }
-
        list_for_each_entry_safe(uobj, tmp, &context->mr_list, list) {
                struct ib_mr *mr = uobj->object;
 
index 57176ddd4c50ff677da5c711b8b7d14e9a020d0d..bb95a6c0477bb434cdcfd0e5e8f4408f6ec9e963 100644 (file)
@@ -583,6 +583,22 @@ static void c4iw_record_pm_msg(struct c4iw_ep *ep,
                sizeof(ep->com.mapped_remote_addr));
 }
 
+static int get_remote_addr(struct c4iw_ep *ep)
+{
+       int ret;
+
+       print_addr(&ep->com, __func__, "get_remote_addr");
+
+       ret = iwpm_get_remote_info(&ep->com.mapped_local_addr,
+                                  &ep->com.mapped_remote_addr,
+                                  &ep->com.remote_addr, RDMA_NL_C4IW);
+       if (ret)
+               pr_info(MOD "Unable to find remote peer addr info - err %d\n",
+                       ret);
+
+       return ret;
+}
+
 static void best_mtu(const unsigned short *mtus, unsigned short mtu,
                     unsigned int *idx, int use_ts, int ipv6)
 {
@@ -675,7 +691,7 @@ static int send_connect(struct c4iw_ep *ep)
        if (is_t5(ep->com.dev->rdev.lldi.adapter_type)) {
                opt2 |= T5_OPT_2_VALID_F;
                opt2 |= CONG_CNTRL_V(CONG_ALG_TAHOE);
-               opt2 |= CONG_CNTRL_VALID; /* OPT_2_ISS for T5 */
+               opt2 |= T5_ISS_F;
        }
        t4_set_arp_err_handler(skb, ep, act_open_req_arp_failure);
 
@@ -2042,9 +2058,12 @@ static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
             status, status2errno(status));
 
        if (is_neg_adv(status)) {
-               dev_warn(&dev->rdev.lldi.pdev->dev,
-                        "Connection problems for atid %u status %u (%s)\n",
-                        atid, status, neg_adv_str(status));
+               PDBG("%s Connection problems for atid %u status %u (%s)\n",
+                    __func__, atid, status, neg_adv_str(status));
+               ep->stats.connect_neg_adv++;
+               mutex_lock(&dev->rdev.stats.lock);
+               dev->rdev.stats.neg_adv++;
+               mutex_unlock(&dev->rdev.stats.lock);
                return 0;
        }
 
@@ -2214,7 +2233,7 @@ static void accept_cr(struct c4iw_ep *ep, struct sk_buff *skb,
                u32 isn = (prandom_u32() & ~7UL) - 1;
                opt2 |= T5_OPT_2_VALID_F;
                opt2 |= CONG_CNTRL_V(CONG_ALG_TAHOE);
-               opt2 |= CONG_CNTRL_VALID; /* OPT_2_ISS for T5 */
+               opt2 |= T5_ISS_F;
                rpl5 = (void *)rpl;
                memset(&rpl5->iss, 0, roundup(sizeof(*rpl5)-sizeof(*rpl), 16));
                if (peer2peer)
@@ -2352,27 +2371,57 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
        state_set(&child_ep->com, CONNECTING);
        child_ep->com.dev = dev;
        child_ep->com.cm_id = NULL;
+
+       /*
+        * The mapped_local and mapped_remote addresses get setup with
+        * the actual 4-tuple.  The local address will be based on the
+        * actual local address of the connection, but on the port number
+        * of the parent listening endpoint.  The remote address is
+        * setup based on a query to the IWPM since we don't know what it
+        * originally was before mapping.  If no mapping was done, then
+        * mapped_remote == remote, and mapped_local == local.
+        */
        if (iptype == 4) {
                struct sockaddr_in *sin = (struct sockaddr_in *)
-                       &child_ep->com.local_addr;
+                       &child_ep->com.mapped_local_addr;
+
                sin->sin_family = PF_INET;
                sin->sin_port = local_port;
                sin->sin_addr.s_addr = *(__be32 *)local_ip;
-               sin = (struct sockaddr_in *)&child_ep->com.remote_addr;
+
+               sin = (struct sockaddr_in *)&child_ep->com.local_addr;
+               sin->sin_family = PF_INET;
+               sin->sin_port = ((struct sockaddr_in *)
+                                &parent_ep->com.local_addr)->sin_port;
+               sin->sin_addr.s_addr = *(__be32 *)local_ip;
+
+               sin = (struct sockaddr_in *)&child_ep->com.mapped_remote_addr;
                sin->sin_family = PF_INET;
                sin->sin_port = peer_port;
                sin->sin_addr.s_addr = *(__be32 *)peer_ip;
        } else {
                struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)
-                       &child_ep->com.local_addr;
+                       &child_ep->com.mapped_local_addr;
+
                sin6->sin6_family = PF_INET6;
                sin6->sin6_port = local_port;
                memcpy(sin6->sin6_addr.s6_addr, local_ip, 16);
-               sin6 = (struct sockaddr_in6 *)&child_ep->com.remote_addr;
+
+               sin6 = (struct sockaddr_in6 *)&child_ep->com.local_addr;
+               sin6->sin6_family = PF_INET6;
+               sin6->sin6_port = ((struct sockaddr_in6 *)
+                                  &parent_ep->com.local_addr)->sin6_port;
+               memcpy(sin6->sin6_addr.s6_addr, local_ip, 16);
+
+               sin6 = (struct sockaddr_in6 *)&child_ep->com.mapped_remote_addr;
                sin6->sin6_family = PF_INET6;
                sin6->sin6_port = peer_port;
                memcpy(sin6->sin6_addr.s6_addr, peer_ip, 16);
        }
+       memcpy(&child_ep->com.remote_addr, &child_ep->com.mapped_remote_addr,
+              sizeof(child_ep->com.remote_addr));
+       get_remote_addr(child_ep);
+
        c4iw_get_ep(&parent_ep->com);
        child_ep->parent_ep = parent_ep;
        child_ep->tos = PASS_OPEN_TOS_G(ntohl(req->tos_stid));
@@ -2520,9 +2569,13 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
 
        ep = lookup_tid(t, tid);
        if (is_neg_adv(req->status)) {
-               dev_warn(&dev->rdev.lldi.pdev->dev,
-                        "Negative advice on abort - tid %u status %d (%s)\n",
-                        ep->hwtid, req->status, neg_adv_str(req->status));
+               PDBG("%s Negative advice on abort- tid %u status %d (%s)\n",
+                    __func__, ep->hwtid, req->status,
+                    neg_adv_str(req->status));
+               ep->stats.abort_neg_adv++;
+               mutex_lock(&dev->rdev.stats.lock);
+               dev->rdev.stats.neg_adv++;
+               mutex_unlock(&dev->rdev.stats.lock);
                return 0;
        }
        PDBG("%s ep %p tid %u state %u\n", __func__, ep, ep->hwtid,
@@ -3571,7 +3624,7 @@ static void send_fw_pass_open_req(struct c4iw_dev *dev, struct sk_buff *skb,
         * TP will ignore any value > 0 for MSS index.
         */
        req->tcb.opt0 = cpu_to_be64(MSS_IDX_V(0xF));
-       req->cookie = (unsigned long)skb;
+       req->cookie = (uintptr_t)skb;
 
        set_wr_txq(req_skb, CPL_PRIORITY_CONTROL, port_id);
        ret = cxgb4_ofld_send(dev->rdev.lldi.ports[0], req_skb);
@@ -3931,9 +3984,11 @@ static int peer_abort_intr(struct c4iw_dev *dev, struct sk_buff *skb)
                return 0;
        }
        if (is_neg_adv(req->status)) {
-               dev_warn(&dev->rdev.lldi.pdev->dev,
-                        "Negative advice on abort - tid %u status %d (%s)\n",
-                        ep->hwtid, req->status, neg_adv_str(req->status));
+               PDBG("%s Negative advice on abort- tid %u status %d (%s)\n",
+                    __func__, ep->hwtid, req->status,
+                    neg_adv_str(req->status));
+               ep->stats.abort_neg_adv++;
+               dev->rdev.stats.neg_adv++;
                kfree_skb(skb);
                return 0;
        }
index ab7692ac2044b0a351c10681f08f63759f1934e8..68ddb37102152ec5382a7bbee7e9bab89e681b94 100644 (file)
@@ -55,7 +55,7 @@ static int destroy_cq(struct c4iw_rdev *rdev, struct t4_cq *cq,
                        FW_RI_RES_WR_NRES_V(1) |
                        FW_WR_COMPL_F);
        res_wr->len16_pkd = cpu_to_be32(DIV_ROUND_UP(wr_len, 16));
-       res_wr->cookie = (unsigned long) &wr_wait;
+       res_wr->cookie = (uintptr_t)&wr_wait;
        res = res_wr->res;
        res->u.cq.restype = FW_RI_RES_TYPE_CQ;
        res->u.cq.op = FW_RI_RES_OP_RESET;
@@ -125,7 +125,7 @@ static int create_cq(struct c4iw_rdev *rdev, struct t4_cq *cq,
                        FW_RI_RES_WR_NRES_V(1) |
                        FW_WR_COMPL_F);
        res_wr->len16_pkd = cpu_to_be32(DIV_ROUND_UP(wr_len, 16));
-       res_wr->cookie = (unsigned long) &wr_wait;
+       res_wr->cookie = (uintptr_t)&wr_wait;
        res = res_wr->res;
        res->u.cq.restype = FW_RI_RES_TYPE_CQ;
        res->u.cq.op = FW_RI_RES_OP_WRITE;
@@ -156,12 +156,19 @@ static int create_cq(struct c4iw_rdev *rdev, struct t4_cq *cq,
                goto err4;
 
        cq->gen = 1;
-       cq->gts = rdev->lldi.gts_reg;
        cq->rdev = rdev;
        if (user) {
-               cq->ugts = (u64)pci_resource_start(rdev->lldi.pdev, 2) +
-                                       (cq->cqid << rdev->cqshift);
-               cq->ugts &= PAGE_MASK;
+               u32 off = (cq->cqid << rdev->cqshift) & PAGE_MASK;
+
+               cq->ugts = (u64)rdev->bar2_pa + off;
+       } else if (is_t4(rdev->lldi.adapter_type)) {
+               cq->gts = rdev->lldi.gts_reg;
+               cq->qid_mask = -1U;
+       } else {
+               u32 off = ((cq->cqid << rdev->cqshift) & PAGE_MASK) + 12;
+
+               cq->gts = rdev->bar2_kva + off;
+               cq->qid_mask = rdev->qpmask;
        }
        return 0;
 err4:
@@ -970,8 +977,7 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, int entries,
        }
        PDBG("%s cqid 0x%0x chp %p size %u memsize %zu, dma_addr 0x%0llx\n",
             __func__, chp->cq.cqid, chp, chp->cq.size,
-            chp->cq.memsize,
-            (unsigned long long) chp->cq.dma_addr);
+            chp->cq.memsize, (unsigned long long) chp->cq.dma_addr);
        return &chp->ibcq;
 err5:
        kfree(mm2);
index 8fb295e4a9ab7199a385dc7778ee6ae1e409a5c1..cf54d6922dc47d18135253ffaf7d194bd1e39cc4 100644 (file)
@@ -93,6 +93,7 @@ static struct ibnl_client_cbs c4iw_nl_cb_table[] = {
        [RDMA_NL_IWPM_ADD_MAPPING] = {.dump = iwpm_add_mapping_cb},
        [RDMA_NL_IWPM_QUERY_MAPPING] = {.dump = iwpm_add_and_query_mapping_cb},
        [RDMA_NL_IWPM_HANDLE_ERR] = {.dump = iwpm_mapping_error_cb},
+       [RDMA_NL_IWPM_REMOTE_INFO] = {.dump = iwpm_remote_info_cb},
        [RDMA_NL_IWPM_MAPINFO] = {.dump = iwpm_mapping_info_cb},
        [RDMA_NL_IWPM_MAPINFO_NUM] = {.dump = iwpm_ack_mapping_info_cb}
 };
@@ -151,7 +152,7 @@ static int wr_log_show(struct seq_file *seq, void *v)
        int prev_ts_set = 0;
        int idx, end;
 
-#define ts2ns(ts) div64_ul((ts) * dev->rdev.lldi.cclk_ps, 1000)
+#define ts2ns(ts) div64_u64((ts) * dev->rdev.lldi.cclk_ps, 1000)
 
        idx = atomic_read(&dev->rdev.wr_log_idx) &
                (dev->rdev.wr_log_size - 1);
@@ -489,6 +490,7 @@ static int stats_show(struct seq_file *seq, void *v)
                   dev->rdev.stats.act_ofld_conn_fails);
        seq_printf(seq, "PAS_OFLD_CONN_FAILS: %10llu\n",
                   dev->rdev.stats.pas_ofld_conn_fails);
+       seq_printf(seq, "NEG_ADV_RCVD: %10llu\n", dev->rdev.stats.neg_adv);
        seq_printf(seq, "AVAILABLE IRD: %10u\n", dev->avail_ird);
        return 0;
 }
@@ -560,10 +562,13 @@ static int dump_ep(int id, void *p, void *data)
                cc = snprintf(epd->buf + epd->pos, space,
                              "ep %p cm_id %p qp %p state %d flags 0x%lx "
                              "history 0x%lx hwtid %d atid %d "
+                             "conn_na %u abort_na %u "
                              "%pI4:%d/%d <-> %pI4:%d/%d\n",
                              ep, ep->com.cm_id, ep->com.qp,
                              (int)ep->com.state, ep->com.flags,
                              ep->com.history, ep->hwtid, ep->atid,
+                             ep->stats.connect_neg_adv,
+                             ep->stats.abort_neg_adv,
                              &lsin->sin_addr, ntohs(lsin->sin_port),
                              ntohs(mapped_lsin->sin_port),
                              &rsin->sin_addr, ntohs(rsin->sin_port),
@@ -581,10 +586,13 @@ static int dump_ep(int id, void *p, void *data)
                cc = snprintf(epd->buf + epd->pos, space,
                              "ep %p cm_id %p qp %p state %d flags 0x%lx "
                              "history 0x%lx hwtid %d atid %d "
+                             "conn_na %u abort_na %u "
                              "%pI6:%d/%d <-> %pI6:%d/%d\n",
                              ep, ep->com.cm_id, ep->com.qp,
                              (int)ep->com.state, ep->com.flags,
                              ep->com.history, ep->hwtid, ep->atid,
+                             ep->stats.connect_neg_adv,
+                             ep->stats.abort_neg_adv,
                              &lsin6->sin6_addr, ntohs(lsin6->sin6_port),
                              ntohs(mapped_lsin6->sin6_port),
                              &rsin6->sin6_addr, ntohs(rsin6->sin6_port),
@@ -764,6 +772,29 @@ static int c4iw_rdev_open(struct c4iw_rdev *rdev)
 
        c4iw_init_dev_ucontext(rdev, &rdev->uctx);
 
+       /*
+        * This implementation assumes udb_density == ucq_density!  Eventually
+        * we might need to support this but for now fail the open. Also the
+        * cqid and qpid range must match for now.
+        */
+       if (rdev->lldi.udb_density != rdev->lldi.ucq_density) {
+               pr_err(MOD "%s: unsupported udb/ucq densities %u/%u\n",
+                      pci_name(rdev->lldi.pdev), rdev->lldi.udb_density,
+                      rdev->lldi.ucq_density);
+               err = -EINVAL;
+               goto err1;
+       }
+       if (rdev->lldi.vr->qp.start != rdev->lldi.vr->cq.start ||
+           rdev->lldi.vr->qp.size != rdev->lldi.vr->cq.size) {
+               pr_err(MOD "%s: unsupported qp and cq id ranges "
+                      "qp start %u size %u cq start %u size %u\n",
+                      pci_name(rdev->lldi.pdev), rdev->lldi.vr->qp.start,
+                      rdev->lldi.vr->qp.size, rdev->lldi.vr->cq.size,
+                      rdev->lldi.vr->cq.size);
+               err = -EINVAL;
+               goto err1;
+       }
+
        /*
         * qpshift is the number of bits to shift the qpid left in order
         * to get the correct address of the doorbell for that qp.
@@ -784,10 +815,10 @@ static int c4iw_rdev_open(struct c4iw_rdev *rdev)
             rdev->lldi.vr->qp.size,
             rdev->lldi.vr->cq.start,
             rdev->lldi.vr->cq.size);
-       PDBG("udb len 0x%x udb base %llx db_reg %p gts_reg %p qpshift %lu "
+       PDBG("udb len 0x%x udb base %p db_reg %p gts_reg %p qpshift %lu "
             "qpmask 0x%x cqshift %lu cqmask 0x%x\n",
             (unsigned)pci_resource_len(rdev->lldi.pdev, 2),
-            (u64)pci_resource_start(rdev->lldi.pdev, 2),
+            (void *)pci_resource_start(rdev->lldi.pdev, 2),
             rdev->lldi.db_reg,
             rdev->lldi.gts_reg,
             rdev->qpshift, rdev->qpmask,
index d87e1650f6437835f3660c21d3a59ec920fa8f7c..97bb5550a6cf64bd77eb3d429b43b6c9d3e10b7e 100644 (file)
@@ -137,6 +137,7 @@ struct c4iw_stats {
        u64  tcam_full;
        u64  act_ofld_conn_fails;
        u64  pas_ofld_conn_fails;
+       u64  neg_adv;
 };
 
 struct c4iw_hw_queue {
@@ -814,6 +815,11 @@ struct c4iw_listen_ep {
        int backlog;
 };
 
+struct c4iw_ep_stats {
+       unsigned connect_neg_adv;
+       unsigned abort_neg_adv;
+};
+
 struct c4iw_ep {
        struct c4iw_ep_common com;
        struct c4iw_ep *parent_ep;
@@ -846,6 +852,7 @@ struct c4iw_ep {
        unsigned int retry_count;
        int snd_win;
        int rcv_win;
+       struct c4iw_ep_stats stats;
 };
 
 static inline void print_addr(struct c4iw_ep_common *epc, const char *func,
index 3ef0cf9f5c4403863310ffc5a7d92cd6bfc970d9..cff815b9170716a01bca790c586b7a9b14c586e7 100644 (file)
@@ -144,7 +144,7 @@ static int _c4iw_write_mem_inline(struct c4iw_rdev *rdev, u32 addr, u32 len,
                if (i == (num_wqe-1)) {
                        req->wr.wr_hi = cpu_to_be32(FW_WR_OP_V(FW_ULPTX_WR) |
                                                    FW_WR_COMPL_F);
-                       req->wr.wr_lo = (__force __be64)(unsigned long) &wr_wait;
+                       req->wr.wr_lo = (__force __be64)&wr_wait;
                } else
                        req->wr.wr_hi = cpu_to_be32(FW_WR_OP_V(FW_ULPTX_WR));
                req->wr.wr_mid = cpu_to_be32(
@@ -676,12 +676,12 @@ struct ib_mr *c4iw_get_dma_mr(struct ib_pd *pd, int acc)
        mhp->attr.zbva = 0;
        mhp->attr.va_fbo = 0;
        mhp->attr.page_size = 0;
-       mhp->attr.len = ~0UL;
+       mhp->attr.len = ~0ULL;
        mhp->attr.pbl_size = 0;
 
        ret = write_tpt_entry(&rhp->rdev, 0, &stag, 1, php->pdid,
                              FW_RI_STAG_NSMR, mhp->attr.perms,
-                             mhp->attr.mw_bind_enable, 0, 0, ~0UL, 0, 0, 0);
+                             mhp->attr.mw_bind_enable, 0, 0, ~0ULL, 0, 0, 0);
        if (ret)
                goto err1;
 
index 15cae5a3101851ed1a0cb049ff43987651a8955c..389ced335bc5cc528f7ef4ba1e4121c5ec79295c 100644 (file)
@@ -275,7 +275,7 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
                        FW_RI_RES_WR_NRES_V(2) |
                        FW_WR_COMPL_F);
        res_wr->len16_pkd = cpu_to_be32(DIV_ROUND_UP(wr_len, 16));
-       res_wr->cookie = (unsigned long) &wr_wait;
+       res_wr->cookie = (uintptr_t)&wr_wait;
        res = res_wr->res;
        res->u.sqrq.restype = FW_RI_RES_TYPE_SQ;
        res->u.sqrq.op = FW_RI_RES_OP_WRITE;
@@ -1209,7 +1209,7 @@ static int rdma_fini(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
        wqe->flowid_len16 = cpu_to_be32(
                FW_WR_FLOWID_V(ep->hwtid) |
                FW_WR_LEN16_V(DIV_ROUND_UP(sizeof(*wqe), 16)));
-       wqe->cookie = (unsigned long) &ep->com.wr_wait;
+       wqe->cookie = (uintptr_t)&ep->com.wr_wait;
 
        wqe->u.fini.type = FW_RI_TYPE_FINI;
        ret = c4iw_ofld_send(&rhp->rdev, skb);
@@ -1279,7 +1279,7 @@ static int rdma_init(struct c4iw_dev *rhp, struct c4iw_qp *qhp)
                FW_WR_FLOWID_V(qhp->ep->hwtid) |
                FW_WR_LEN16_V(DIV_ROUND_UP(sizeof(*wqe), 16)));
 
-       wqe->cookie = (unsigned long) &qhp->ep->com.wr_wait;
+       wqe->cookie = (uintptr_t)&qhp->ep->com.wr_wait;
 
        wqe->u.init.type = FW_RI_TYPE_INIT;
        wqe->u.init.mpareqbit_p2ptype =
@@ -1766,11 +1766,11 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
                mm2->len = PAGE_ALIGN(qhp->wq.rq.memsize);
                insert_mmap(ucontext, mm2);
                mm3->key = uresp.sq_db_gts_key;
-               mm3->addr = (__force unsigned long) qhp->wq.sq.udb;
+               mm3->addr = (__force unsigned long)qhp->wq.sq.udb;
                mm3->len = PAGE_SIZE;
                insert_mmap(ucontext, mm3);
                mm4->key = uresp.rq_db_gts_key;
-               mm4->addr = (__force unsigned long) qhp->wq.rq.udb;
+               mm4->addr = (__force unsigned long)qhp->wq.rq.udb;
                mm4->len = PAGE_SIZE;
                insert_mmap(ucontext, mm4);
                if (mm5) {
index 871cdcac7be26a3479f78eb34c3f799f5a8b840f..7f2a6c244d25d67ea922ab35ba568e8b73196ffe 100644 (file)
@@ -539,6 +539,7 @@ struct t4_cq {
        size_t memsize;
        __be64 bits_type_ts;
        u32 cqid;
+       u32 qid_mask;
        int vector;
        u16 size; /* including status page */
        u16 cidx;
@@ -563,12 +564,12 @@ static inline int t4_arm_cq(struct t4_cq *cq, int se)
        set_bit(CQ_ARMED, &cq->flags);
        while (cq->cidx_inc > CIDXINC_M) {
                val = SEINTARM_V(0) | CIDXINC_V(CIDXINC_M) | TIMERREG_V(7) |
-                     INGRESSQID_V(cq->cqid);
+                     INGRESSQID_V(cq->cqid & cq->qid_mask);
                writel(val, cq->gts);
                cq->cidx_inc -= CIDXINC_M;
        }
        val = SEINTARM_V(se) | CIDXINC_V(cq->cidx_inc) | TIMERREG_V(6) |
-             INGRESSQID_V(cq->cqid);
+             INGRESSQID_V(cq->cqid & cq->qid_mask);
        writel(val, cq->gts);
        cq->cidx_inc = 0;
        return 0;
@@ -601,7 +602,7 @@ static inline void t4_hwcq_consume(struct t4_cq *cq)
                u32 val;
 
                val = SEINTARM_V(0) | CIDXINC_V(cq->cidx_inc) | TIMERREG_V(7) |
-                     INGRESSQID_V(cq->cqid);
+                     INGRESSQID_V(cq->cqid & cq->qid_mask);
                writel(val, cq->gts);
                cq->cidx_inc = 0;
        }
index 5e53327fc6476b678227609bee4aee90bbb0c7c0..343e8daf2270dbc07680d2ef2e2b2027181f292c 100644 (file)
@@ -848,6 +848,8 @@ enum {                     /* TCP congestion control algorithms */
 #define CONG_CNTRL_V(x) ((x) << CONG_CNTRL_S)
 #define CONG_CNTRL_G(x) (((x) >> CONG_CNTRL_S) & CONG_CNTRL_M)
 
-#define CONG_CNTRL_VALID   (1 << 18)
+#define T5_ISS_S    18
+#define T5_ISS_V(x) ((x) << T5_ISS_S)
+#define T5_ISS_F    T5_ISS_V(1U)
 
 #endif /* _T4FW_RI_API_H_ */
index 33c45dfcbd88cb11a05c637e22159cc34008a718..1ca8e32a95927961a326f33bae480c11a02a226f 100644 (file)
@@ -82,14 +82,14 @@ static int create_file(const char *name, umode_t mode,
 {
        int error;
 
-       mutex_lock(&parent->d_inode->i_mutex);
+       mutex_lock(&d_inode(parent)->i_mutex);
        *dentry = lookup_one_len(name, parent, strlen(name));
        if (!IS_ERR(*dentry))
-               error = ipathfs_mknod(parent->d_inode, *dentry,
+               error = ipathfs_mknod(d_inode(parent), *dentry,
                                      mode, fops, data);
        else
                error = PTR_ERR(*dentry);
-       mutex_unlock(&parent->d_inode->i_mutex);
+       mutex_unlock(&d_inode(parent)->i_mutex);
 
        return error;
 }
@@ -277,11 +277,11 @@ static int remove_file(struct dentry *parent, char *name)
        }
 
        spin_lock(&tmp->d_lock);
-       if (!d_unhashed(tmp) && tmp->d_inode) {
+       if (!d_unhashed(tmp) && d_really_is_positive(tmp)) {
                dget_dlock(tmp);
                __d_drop(tmp);
                spin_unlock(&tmp->d_lock);
-               simple_unlink(parent->d_inode, tmp);
+               simple_unlink(d_inode(parent), tmp);
        } else
                spin_unlock(&tmp->d_lock);
 
@@ -302,7 +302,7 @@ static int remove_device_files(struct super_block *sb,
        int ret;
 
        root = dget(sb->s_root);
-       mutex_lock(&root->d_inode->i_mutex);
+       mutex_lock(&d_inode(root)->i_mutex);
        snprintf(unit, sizeof unit, "%02d", dd->ipath_unit);
        dir = lookup_one_len(unit, root, strlen(unit));
 
@@ -315,10 +315,10 @@ static int remove_device_files(struct super_block *sb,
        remove_file(dir, "flash");
        remove_file(dir, "atomic_counters");
        d_delete(dir);
-       ret = simple_rmdir(root->d_inode, dir);
+       ret = simple_rmdir(d_inode(root), dir);
 
 bail:
-       mutex_unlock(&root->d_inode->i_mutex);
+       mutex_unlock(&d_inode(root)->i_mutex);
        dput(root);
        return ret;
 }
index a31e031afd87486ce0c876c541d4efc7cb981f8c..0f00204d2ecea0e19f0a9917431e4bb8cbbdfa49 100644 (file)
@@ -58,14 +58,19 @@ struct mlx4_alias_guid_work_context {
        int                     query_id;
        struct list_head        list;
        int                     block_num;
+       ib_sa_comp_mask         guid_indexes;
+       u8                      method;
 };
 
 struct mlx4_next_alias_guid_work {
        u8 port;
        u8 block_num;
+       u8 method;
        struct mlx4_sriov_alias_guid_info_rec_det rec_det;
 };
 
+static int get_low_record_time_index(struct mlx4_ib_dev *dev, u8 port,
+                                    int *resched_delay_sec);
 
 void mlx4_ib_update_cache_on_guid_change(struct mlx4_ib_dev *dev, int block_num,
                                         u8 port_num, u8 *p_data)
@@ -118,6 +123,57 @@ ib_sa_comp_mask mlx4_ib_get_aguid_comp_mask_from_ix(int index)
        return IB_SA_COMP_MASK(4 + index);
 }
 
+void mlx4_ib_slave_alias_guid_event(struct mlx4_ib_dev *dev, int slave,
+                                   int port,  int slave_init)
+{
+       __be64 curr_guid, required_guid;
+       int record_num = slave / 8;
+       int index = slave % 8;
+       int port_index = port - 1;
+       unsigned long flags;
+       int do_work = 0;
+
+       spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags);
+       if (dev->sriov.alias_guid.ports_guid[port_index].state_flags &
+           GUID_STATE_NEED_PORT_INIT)
+               goto unlock;
+       if (!slave_init) {
+               curr_guid = *(__be64 *)&dev->sriov.
+                       alias_guid.ports_guid[port_index].
+                       all_rec_per_port[record_num].
+                       all_recs[GUID_REC_SIZE * index];
+               if (curr_guid == cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL) ||
+                   !curr_guid)
+                       goto unlock;
+               required_guid = cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL);
+       } else {
+               required_guid = mlx4_get_admin_guid(dev->dev, slave, port);
+               if (required_guid == cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL))
+                       goto unlock;
+       }
+       *(__be64 *)&dev->sriov.alias_guid.ports_guid[port_index].
+               all_rec_per_port[record_num].
+               all_recs[GUID_REC_SIZE * index] = required_guid;
+       dev->sriov.alias_guid.ports_guid[port_index].
+               all_rec_per_port[record_num].guid_indexes
+               |= mlx4_ib_get_aguid_comp_mask_from_ix(index);
+       dev->sriov.alias_guid.ports_guid[port_index].
+               all_rec_per_port[record_num].status
+               = MLX4_GUID_INFO_STATUS_IDLE;
+       /* set to run immediately */
+       dev->sriov.alias_guid.ports_guid[port_index].
+               all_rec_per_port[record_num].time_to_run = 0;
+       dev->sriov.alias_guid.ports_guid[port_index].
+               all_rec_per_port[record_num].
+               guids_retry_schedule[index] = 0;
+       do_work = 1;
+unlock:
+       spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags);
+
+       if (do_work)
+               mlx4_ib_init_alias_guid_work(dev, port_index);
+}
+
 /*
  * Whenever new GUID is set/unset (guid table change) create event and
  * notify the relevant slave (master also should be notified).
@@ -138,10 +194,15 @@ void mlx4_ib_notify_slaves_on_guid_change(struct mlx4_ib_dev *dev,
        enum slave_port_state prev_state;
        __be64 tmp_cur_ag, form_cache_ag;
        enum slave_port_gen_event gen_event;
+       struct mlx4_sriov_alias_guid_info_rec_det *rec;
+       unsigned long flags;
+       __be64 required_value;
 
        if (!mlx4_is_master(dev->dev))
                return;
 
+       rec = &dev->sriov.alias_guid.ports_guid[port_num - 1].
+                       all_rec_per_port[block_num];
        guid_indexes = be64_to_cpu((__force __be64) dev->sriov.alias_guid.
                                   ports_guid[port_num - 1].
                                   all_rec_per_port[block_num].guid_indexes);
@@ -166,8 +227,27 @@ void mlx4_ib_notify_slaves_on_guid_change(struct mlx4_ib_dev *dev,
                 */
                if (tmp_cur_ag != form_cache_ag)
                        continue;
-               mlx4_gen_guid_change_eqe(dev->dev, slave_id, port_num);
 
+               spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags);
+               required_value = *(__be64 *)&rec->all_recs[i * GUID_REC_SIZE];
+
+               if (required_value == cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL))
+                       required_value = 0;
+
+               if (tmp_cur_ag == required_value) {
+                       rec->guid_indexes = rec->guid_indexes &
+                              ~mlx4_ib_get_aguid_comp_mask_from_ix(i);
+               } else {
+                       /* may notify port down if value is 0 */
+                       if (tmp_cur_ag != MLX4_NOT_SET_GUID) {
+                               spin_unlock_irqrestore(&dev->sriov.
+                                       alias_guid.ag_work_lock, flags);
+                               continue;
+                       }
+               }
+               spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock,
+                                      flags);
+               mlx4_gen_guid_change_eqe(dev->dev, slave_id, port_num);
                /*2 cases: Valid GUID, and Invalid Guid*/
 
                if (tmp_cur_ag != MLX4_NOT_SET_GUID) { /*valid GUID*/
@@ -188,10 +268,14 @@ void mlx4_ib_notify_slaves_on_guid_change(struct mlx4_ib_dev *dev,
                        set_and_calc_slave_port_state(dev->dev, slave_id, port_num,
                                                      MLX4_PORT_STATE_IB_EVENT_GID_INVALID,
                                                      &gen_event);
-                       pr_debug("sending PORT DOWN event to slave: %d, port: %d\n",
-                                slave_id, port_num);
-                       mlx4_gen_port_state_change_eqe(dev->dev, slave_id, port_num,
-                                                      MLX4_PORT_CHANGE_SUBTYPE_DOWN);
+                       if (gen_event == SLAVE_PORT_GEN_EVENT_DOWN) {
+                               pr_debug("sending PORT DOWN event to slave: %d, port: %d\n",
+                                        slave_id, port_num);
+                               mlx4_gen_port_state_change_eqe(dev->dev,
+                                                              slave_id,
+                                                              port_num,
+                                                              MLX4_PORT_CHANGE_SUBTYPE_DOWN);
+                       }
                }
        }
 }
@@ -206,6 +290,9 @@ static void aliasguid_query_handler(int status,
        int i;
        struct mlx4_sriov_alias_guid_info_rec_det *rec;
        unsigned long flags, flags1;
+       ib_sa_comp_mask declined_guid_indexes = 0;
+       ib_sa_comp_mask applied_guid_indexes = 0;
+       unsigned int resched_delay_sec = 0;
 
        if (!context)
                return;
@@ -216,9 +303,9 @@ static void aliasguid_query_handler(int status,
                all_rec_per_port[cb_ctx->block_num];
 
        if (status) {
-               rec->status = MLX4_GUID_INFO_STATUS_IDLE;
                pr_debug("(port: %d) failed: status = %d\n",
                         cb_ctx->port, status);
+               rec->time_to_run = ktime_get_real_ns() + 1 * NSEC_PER_SEC;
                goto out;
        }
 
@@ -235,57 +322,101 @@ static void aliasguid_query_handler(int status,
        rec = &dev->sriov.alias_guid.ports_guid[port_index].
                all_rec_per_port[guid_rec->block_num];
 
-       rec->status = MLX4_GUID_INFO_STATUS_SET;
-       rec->method = MLX4_GUID_INFO_RECORD_SET;
-
+       spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags);
        for (i = 0 ; i < NUM_ALIAS_GUID_IN_REC; i++) {
-               __be64 tmp_cur_ag;
-               tmp_cur_ag = *(__be64 *)&guid_rec->guid_info_list[i * GUID_REC_SIZE];
+               __be64 sm_response, required_val;
+
+               if (!(cb_ctx->guid_indexes &
+                       mlx4_ib_get_aguid_comp_mask_from_ix(i)))
+                       continue;
+               sm_response = *(__be64 *)&guid_rec->guid_info_list
+                               [i * GUID_REC_SIZE];
+               required_val = *(__be64 *)&rec->all_recs[i * GUID_REC_SIZE];
+               if (cb_ctx->method == MLX4_GUID_INFO_RECORD_DELETE) {
+                       if (required_val ==
+                           cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL))
+                               goto next_entry;
+
+                       /* A new value was set till we got the response */
+                       pr_debug("need to set new value %llx, record num %d, block_num:%d\n",
+                                be64_to_cpu(required_val),
+                                i, guid_rec->block_num);
+                       goto entry_declined;
+               }
+
                /* check if the SM didn't assign one of the records.
-                * if it didn't, if it was not sysadmin request:
-                * ask the SM to give a new GUID, (instead of the driver request).
+                * if it didn't, re-ask for.
                 */
-               if (tmp_cur_ag == MLX4_NOT_SET_GUID) {
-                       mlx4_ib_warn(&dev->ib_dev, "%s:Record num %d in "
-                                    "block_num: %d was declined by SM, "
-                                    "ownership by %d (0 = driver, 1=sysAdmin,"
-                                    " 2=None)\n", __func__, i,
-                                    guid_rec->block_num, rec->ownership);
-                       if (rec->ownership == MLX4_GUID_DRIVER_ASSIGN) {
-                               /* if it is driver assign, asks for new GUID from SM*/
-                               *(__be64 *)&rec->all_recs[i * GUID_REC_SIZE] =
-                                       MLX4_NOT_SET_GUID;
-
-                               /* Mark the record as not assigned, and let it
-                                * be sent again in the next work sched.*/
-                               rec->status = MLX4_GUID_INFO_STATUS_IDLE;
-                               rec->guid_indexes |= mlx4_ib_get_aguid_comp_mask_from_ix(i);
-                       }
+               if (sm_response == MLX4_NOT_SET_GUID) {
+                       if (rec->guids_retry_schedule[i] == 0)
+                               mlx4_ib_warn(&dev->ib_dev,
+                                            "%s:Record num %d in  block_num: %d was declined by SM\n",
+                                            __func__, i,
+                                            guid_rec->block_num);
+                       goto entry_declined;
                } else {
                       /* properly assigned record. */
                       /* We save the GUID we just got from the SM in the
                        * admin_guid in order to be persistent, and in the
                        * request from the sm the process will ask for the same GUID */
-                       if (rec->ownership == MLX4_GUID_SYSADMIN_ASSIGN &&
-                           tmp_cur_ag != *(__be64 *)&rec->all_recs[i * GUID_REC_SIZE]) {
-                               /* the sysadmin assignment failed.*/
-                               mlx4_ib_warn(&dev->ib_dev, "%s: Failed to set"
-                                            " admin guid after SysAdmin "
-                                            "configuration. "
-                                            "Record num %d in block_num:%d "
-                                            "was declined by SM, "
-                                            "new val(0x%llx) was kept\n",
-                                             __func__, i,
-                                            guid_rec->block_num,
-                                            be64_to_cpu(*(__be64 *) &
-                                                        rec->all_recs[i * GUID_REC_SIZE]));
+                       if (required_val &&
+                           sm_response != required_val) {
+                               /* Warn only on first retry */
+                               if (rec->guids_retry_schedule[i] == 0)
+                                       mlx4_ib_warn(&dev->ib_dev, "%s: Failed to set"
+                                                    " admin guid after SysAdmin "
+                                                    "configuration. "
+                                                    "Record num %d in block_num:%d "
+                                                    "was declined by SM, "
+                                                    "new val(0x%llx) was kept, SM returned (0x%llx)\n",
+                                                     __func__, i,
+                                                    guid_rec->block_num,
+                                                    be64_to_cpu(required_val),
+                                                    be64_to_cpu(sm_response));
+                               goto entry_declined;
                        } else {
-                               memcpy(&rec->all_recs[i * GUID_REC_SIZE],
-                                      &guid_rec->guid_info_list[i * GUID_REC_SIZE],
-                                      GUID_REC_SIZE);
+                               *(__be64 *)&rec->all_recs[i * GUID_REC_SIZE] =
+                                       sm_response;
+                               if (required_val == 0)
+                                       mlx4_set_admin_guid(dev->dev,
+                                                           sm_response,
+                                                           (guid_rec->block_num
+                                                           * NUM_ALIAS_GUID_IN_REC) + i,
+                                                           cb_ctx->port);
+                               goto next_entry;
                        }
                }
+entry_declined:
+               declined_guid_indexes |= mlx4_ib_get_aguid_comp_mask_from_ix(i);
+               rec->guids_retry_schedule[i] =
+                       (rec->guids_retry_schedule[i] == 0) ?  1 :
+                       min((unsigned int)60,
+                           rec->guids_retry_schedule[i] * 2);
+               /* using the minimum value among all entries in that record */
+               resched_delay_sec = (resched_delay_sec == 0) ?
+                               rec->guids_retry_schedule[i] :
+                               min(resched_delay_sec,
+                                   rec->guids_retry_schedule[i]);
+               continue;
+
+next_entry:
+               rec->guids_retry_schedule[i] = 0;
        }
+
+       applied_guid_indexes =  cb_ctx->guid_indexes & ~declined_guid_indexes;
+       if (declined_guid_indexes ||
+           rec->guid_indexes & ~(applied_guid_indexes)) {
+               pr_debug("record=%d wasn't fully set, guid_indexes=0x%llx applied_indexes=0x%llx, declined_indexes=0x%llx\n",
+                        guid_rec->block_num,
+                        be64_to_cpu((__force __be64)rec->guid_indexes),
+                        be64_to_cpu((__force __be64)applied_guid_indexes),
+                        be64_to_cpu((__force __be64)declined_guid_indexes));
+               rec->time_to_run = ktime_get_real_ns() +
+                       resched_delay_sec * NSEC_PER_SEC;
+       } else {
+               rec->status = MLX4_GUID_INFO_STATUS_SET;
+       }
+       spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags);
        /*
        The func is call here to close the cases when the
        sm doesn't send smp, so in the sa response the driver
@@ -297,10 +428,13 @@ static void aliasguid_query_handler(int status,
 out:
        spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
        spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
-       if (!dev->sriov.is_going_down)
+       if (!dev->sriov.is_going_down) {
+               get_low_record_time_index(dev, port_index, &resched_delay_sec);
                queue_delayed_work(dev->sriov.alias_guid.ports_guid[port_index].wq,
                                   &dev->sriov.alias_guid.ports_guid[port_index].
-                                  alias_guid_work, 0);
+                                  alias_guid_work,
+                                  msecs_to_jiffies(resched_delay_sec * 1000));
+       }
        if (cb_ctx->sa_query) {
                list_del(&cb_ctx->list);
                kfree(cb_ctx);
@@ -317,9 +451,7 @@ static void invalidate_guid_record(struct mlx4_ib_dev *dev, u8 port, int index)
        ib_sa_comp_mask comp_mask = 0;
 
        dev->sriov.alias_guid.ports_guid[port - 1].all_rec_per_port[index].status
-               = MLX4_GUID_INFO_STATUS_IDLE;
-       dev->sriov.alias_guid.ports_guid[port - 1].all_rec_per_port[index].method
-               = MLX4_GUID_INFO_RECORD_SET;
+               = MLX4_GUID_INFO_STATUS_SET;
 
        /* calculate the comp_mask for that record.*/
        for (i = 0; i < NUM_ALIAS_GUID_IN_REC; i++) {
@@ -333,19 +465,21 @@ static void invalidate_guid_record(struct mlx4_ib_dev *dev, u8 port, int index)
                need to assign GUIDs, then don't put it up for assignment.
                */
                if (MLX4_GUID_FOR_DELETE_VAL == cur_admin_val ||
-                   (!index && !i) ||
-                   MLX4_GUID_NONE_ASSIGN == dev->sriov.alias_guid.
-                   ports_guid[port - 1].all_rec_per_port[index].ownership)
+                   (!index && !i))
                        continue;
                comp_mask |= mlx4_ib_get_aguid_comp_mask_from_ix(i);
        }
        dev->sriov.alias_guid.ports_guid[port - 1].
-               all_rec_per_port[index].guid_indexes = comp_mask;
+               all_rec_per_port[index].guid_indexes |= comp_mask;
+       if (dev->sriov.alias_guid.ports_guid[port - 1].
+           all_rec_per_port[index].guid_indexes)
+               dev->sriov.alias_guid.ports_guid[port - 1].
+               all_rec_per_port[index].status = MLX4_GUID_INFO_STATUS_IDLE;
+
 }
 
 static int set_guid_rec(struct ib_device *ibdev,
-                       u8 port, int index,
-                       struct mlx4_sriov_alias_guid_info_rec_det *rec_det)
+                       struct mlx4_next_alias_guid_work *rec)
 {
        int err;
        struct mlx4_ib_dev *dev = to_mdev(ibdev);
@@ -354,6 +488,9 @@ static int set_guid_rec(struct ib_device *ibdev,
        struct ib_port_attr attr;
        struct mlx4_alias_guid_work_context *callback_context;
        unsigned long resched_delay, flags, flags1;
+       u8 port = rec->port + 1;
+       int index = rec->block_num;
+       struct mlx4_sriov_alias_guid_info_rec_det *rec_det = &rec->rec_det;
        struct list_head *head =
                &dev->sriov.alias_guid.ports_guid[port - 1].cb_list;
 
@@ -380,6 +517,8 @@ static int set_guid_rec(struct ib_device *ibdev,
        callback_context->port = port;
        callback_context->dev = dev;
        callback_context->block_num = index;
+       callback_context->guid_indexes = rec_det->guid_indexes;
+       callback_context->method = rec->method;
 
        memset(&guid_info_rec, 0, sizeof (struct ib_sa_guidinfo_rec));
 
@@ -399,7 +538,7 @@ static int set_guid_rec(struct ib_device *ibdev,
        callback_context->query_id =
                ib_sa_guid_info_rec_query(dev->sriov.alias_guid.sa_client,
                                          ibdev, port, &guid_info_rec,
-                                         comp_mask, rec_det->method, 1000,
+                                         comp_mask, rec->method, 1000,
                                          GFP_KERNEL, aliasguid_query_handler,
                                          callback_context,
                                          &callback_context->sa_query);
@@ -434,6 +573,30 @@ out:
        return err;
 }
 
+static void mlx4_ib_guid_port_init(struct mlx4_ib_dev *dev, int port)
+{
+       int j, k, entry;
+       __be64 guid;
+
+       /*Check if the SM doesn't need to assign the GUIDs*/
+       for (j = 0; j < NUM_ALIAS_GUID_REC_IN_PORT; j++) {
+               for (k = 0; k < NUM_ALIAS_GUID_IN_REC; k++) {
+                       entry = j * NUM_ALIAS_GUID_IN_REC + k;
+                       /* no request for the 0 entry (hw guid) */
+                       if (!entry || entry > dev->dev->persist->num_vfs ||
+                           !mlx4_is_slave_active(dev->dev, entry))
+                               continue;
+                       guid = mlx4_get_admin_guid(dev->dev, entry, port);
+                       *(__be64 *)&dev->sriov.alias_guid.ports_guid[port - 1].
+                               all_rec_per_port[j].all_recs
+                               [GUID_REC_SIZE * k] = guid;
+                       pr_debug("guid was set, entry=%d, val=0x%llx, port=%d\n",
+                                entry,
+                                be64_to_cpu(guid),
+                                port);
+               }
+       }
+}
 void mlx4_ib_invalidate_all_guid_record(struct mlx4_ib_dev *dev, int port)
 {
        int i;
@@ -443,6 +606,13 @@ void mlx4_ib_invalidate_all_guid_record(struct mlx4_ib_dev *dev, int port)
 
        spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
        spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
+
+       if (dev->sriov.alias_guid.ports_guid[port - 1].state_flags &
+               GUID_STATE_NEED_PORT_INIT) {
+               mlx4_ib_guid_port_init(dev, port);
+               dev->sriov.alias_guid.ports_guid[port - 1].state_flags &=
+                       (~GUID_STATE_NEED_PORT_INIT);
+       }
        for (i = 0; i < NUM_ALIAS_GUID_REC_IN_PORT; i++)
                invalidate_guid_record(dev, port, i);
 
@@ -462,60 +632,107 @@ void mlx4_ib_invalidate_all_guid_record(struct mlx4_ib_dev *dev, int port)
        spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
 }
 
-/* The function returns the next record that was
- * not configured (or failed to be configured) */
-static int get_next_record_to_update(struct mlx4_ib_dev *dev, u8 port,
-                                    struct mlx4_next_alias_guid_work *rec)
+static void set_required_record(struct mlx4_ib_dev *dev, u8 port,
+                               struct mlx4_next_alias_guid_work *next_rec,
+                               int record_index)
 {
-       int j;
-       unsigned long flags;
+       int i;
+       int lowset_time_entry = -1;
+       int lowest_time = 0;
+       ib_sa_comp_mask delete_guid_indexes = 0;
+       ib_sa_comp_mask set_guid_indexes = 0;
+       struct mlx4_sriov_alias_guid_info_rec_det *rec =
+                       &dev->sriov.alias_guid.ports_guid[port].
+                       all_rec_per_port[record_index];
 
-       for (j = 0; j < NUM_ALIAS_GUID_REC_IN_PORT; j++) {
-               spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags);
-               if (dev->sriov.alias_guid.ports_guid[port].all_rec_per_port[j].status ==
-                   MLX4_GUID_INFO_STATUS_IDLE) {
-                       memcpy(&rec->rec_det,
-                              &dev->sriov.alias_guid.ports_guid[port].all_rec_per_port[j],
-                              sizeof (struct mlx4_sriov_alias_guid_info_rec_det));
-                       rec->port = port;
-                       rec->block_num = j;
-                       dev->sriov.alias_guid.ports_guid[port].all_rec_per_port[j].status =
-                               MLX4_GUID_INFO_STATUS_PENDING;
-                       spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags);
-                       return 0;
+       for (i = 0; i < NUM_ALIAS_GUID_IN_REC; i++) {
+               if (!(rec->guid_indexes &
+                       mlx4_ib_get_aguid_comp_mask_from_ix(i)))
+                       continue;
+
+               if (*(__be64 *)&rec->all_recs[i * GUID_REC_SIZE] ==
+                               cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL))
+                       delete_guid_indexes |=
+                               mlx4_ib_get_aguid_comp_mask_from_ix(i);
+               else
+                       set_guid_indexes |=
+                               mlx4_ib_get_aguid_comp_mask_from_ix(i);
+
+               if (lowset_time_entry == -1 || rec->guids_retry_schedule[i] <=
+                       lowest_time) {
+                       lowset_time_entry = i;
+                       lowest_time = rec->guids_retry_schedule[i];
                }
-               spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags);
        }
-       return -ENOENT;
+
+       memcpy(&next_rec->rec_det, rec, sizeof(*rec));
+       next_rec->port = port;
+       next_rec->block_num = record_index;
+
+       if (*(__be64 *)&rec->all_recs[lowset_time_entry * GUID_REC_SIZE] ==
+                               cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL)) {
+               next_rec->rec_det.guid_indexes = delete_guid_indexes;
+               next_rec->method = MLX4_GUID_INFO_RECORD_DELETE;
+       } else {
+               next_rec->rec_det.guid_indexes = set_guid_indexes;
+               next_rec->method = MLX4_GUID_INFO_RECORD_SET;
+       }
 }
 
-static void set_administratively_guid_record(struct mlx4_ib_dev *dev, int port,
-                                            int rec_index,
-                                            struct mlx4_sriov_alias_guid_info_rec_det *rec_det)
+/* return index of record that should be updated based on lowest
+ * rescheduled time
+ */
+static int get_low_record_time_index(struct mlx4_ib_dev *dev, u8 port,
+                                    int *resched_delay_sec)
 {
-       dev->sriov.alias_guid.ports_guid[port].all_rec_per_port[rec_index].guid_indexes =
-               rec_det->guid_indexes;
-       memcpy(dev->sriov.alias_guid.ports_guid[port].all_rec_per_port[rec_index].all_recs,
-              rec_det->all_recs, NUM_ALIAS_GUID_IN_REC * GUID_REC_SIZE);
-       dev->sriov.alias_guid.ports_guid[port].all_rec_per_port[rec_index].status =
-               rec_det->status;
+       int record_index = -1;
+       u64 low_record_time = 0;
+       struct mlx4_sriov_alias_guid_info_rec_det rec;
+       int j;
+
+       for (j = 0; j < NUM_ALIAS_GUID_REC_IN_PORT; j++) {
+               rec = dev->sriov.alias_guid.ports_guid[port].
+                       all_rec_per_port[j];
+               if (rec.status == MLX4_GUID_INFO_STATUS_IDLE &&
+                   rec.guid_indexes) {
+                       if (record_index == -1 ||
+                           rec.time_to_run < low_record_time) {
+                               record_index = j;
+                               low_record_time = rec.time_to_run;
+                       }
+               }
+       }
+       if (resched_delay_sec) {
+               u64 curr_time = ktime_get_real_ns();
+
+               *resched_delay_sec = (low_record_time < curr_time) ? 0 :
+                       div_u64((low_record_time - curr_time), NSEC_PER_SEC);
+       }
+
+       return record_index;
 }
 
-static void set_all_slaves_guids(struct mlx4_ib_dev *dev, int port)
+/* The function returns the next record that was
+ * not configured (or failed to be configured) */
+static int get_next_record_to_update(struct mlx4_ib_dev *dev, u8 port,
+                                    struct mlx4_next_alias_guid_work *rec)
 {
-       int j;
-       struct mlx4_sriov_alias_guid_info_rec_det rec_det ;
-
-       for (j = 0 ; j < NUM_ALIAS_GUID_REC_IN_PORT ; j++) {
-               memset(rec_det.all_recs, 0, NUM_ALIAS_GUID_IN_REC * GUID_REC_SIZE);
-               rec_det.guid_indexes = (!j ? 0 : IB_SA_GUIDINFO_REC_GID0) |
-                       IB_SA_GUIDINFO_REC_GID1 | IB_SA_GUIDINFO_REC_GID2 |
-                       IB_SA_GUIDINFO_REC_GID3 | IB_SA_GUIDINFO_REC_GID4 |
-                       IB_SA_GUIDINFO_REC_GID5 | IB_SA_GUIDINFO_REC_GID6 |
-                       IB_SA_GUIDINFO_REC_GID7;
-               rec_det.status = MLX4_GUID_INFO_STATUS_IDLE;
-               set_administratively_guid_record(dev, port, j, &rec_det);
+       unsigned long flags;
+       int record_index;
+       int ret = 0;
+
+       spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags);
+       record_index = get_low_record_time_index(dev, port, NULL);
+
+       if (record_index < 0) {
+               ret = -ENOENT;
+               goto out;
        }
+
+       set_required_record(dev, port, rec, record_index);
+out:
+       spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags);
+       return ret;
 }
 
 static void alias_guid_work(struct work_struct *work)
@@ -545,9 +762,7 @@ static void alias_guid_work(struct work_struct *work)
                goto out;
        }
 
-       set_guid_rec(&dev->ib_dev, rec->port + 1, rec->block_num,
-                    &rec->rec_det);
-
+       set_guid_rec(&dev->ib_dev, rec);
 out:
        kfree(rec);
 }
@@ -562,6 +777,12 @@ void mlx4_ib_init_alias_guid_work(struct mlx4_ib_dev *dev, int port)
        spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
        spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
        if (!dev->sriov.is_going_down) {
+               /* If there is pending one should cancell then run, otherwise
+                 * won't run till previous one is ended as same work
+                 * struct is used.
+                 */
+               cancel_delayed_work(&dev->sriov.alias_guid.ports_guid[port].
+                                   alias_guid_work);
                queue_delayed_work(dev->sriov.alias_guid.ports_guid[port].wq,
                           &dev->sriov.alias_guid.ports_guid[port].alias_guid_work, 0);
        }
@@ -609,7 +830,7 @@ int mlx4_ib_init_alias_guid_service(struct mlx4_ib_dev *dev)
 {
        char alias_wq_name[15];
        int ret = 0;
-       int i, j, k;
+       int i, j;
        union ib_gid gid;
 
        if (!mlx4_is_master(dev->dev))
@@ -633,33 +854,25 @@ int mlx4_ib_init_alias_guid_service(struct mlx4_ib_dev *dev)
        for (i = 0 ; i < dev->num_ports; i++) {
                memset(&dev->sriov.alias_guid.ports_guid[i], 0,
                       sizeof (struct mlx4_sriov_alias_guid_port_rec_det));
-               /*Check if the SM doesn't need to assign the GUIDs*/
+               dev->sriov.alias_guid.ports_guid[i].state_flags |=
+                               GUID_STATE_NEED_PORT_INIT;
                for (j = 0; j < NUM_ALIAS_GUID_REC_IN_PORT; j++) {
-                       if (mlx4_ib_sm_guid_assign) {
-                               dev->sriov.alias_guid.ports_guid[i].
-                                       all_rec_per_port[j].
-                                       ownership = MLX4_GUID_DRIVER_ASSIGN;
-                               continue;
-                       }
-                       dev->sriov.alias_guid.ports_guid[i].all_rec_per_port[j].
-                                       ownership = MLX4_GUID_NONE_ASSIGN;
-                       /*mark each val as it was deleted,
-                         till the sysAdmin will give it valid val*/
-                       for (k = 0; k < NUM_ALIAS_GUID_IN_REC; k++) {
-                               *(__be64 *)&dev->sriov.alias_guid.ports_guid[i].
-                                       all_rec_per_port[j].all_recs[GUID_REC_SIZE * k] =
-                                               cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL);
-                       }
+                       /* mark each val as it was deleted */
+                       memset(dev->sriov.alias_guid.ports_guid[i].
+                               all_rec_per_port[j].all_recs, 0xFF,
+                               sizeof(dev->sriov.alias_guid.ports_guid[i].
+                               all_rec_per_port[j].all_recs));
                }
                INIT_LIST_HEAD(&dev->sriov.alias_guid.ports_guid[i].cb_list);
                /*prepare the records, set them to be allocated by sm*/
+               if (mlx4_ib_sm_guid_assign)
+                       for (j = 1; j < NUM_ALIAS_GUID_PER_PORT; j++)
+                               mlx4_set_admin_guid(dev->dev, 0, j, i + 1);
                for (j = 0 ; j < NUM_ALIAS_GUID_REC_IN_PORT; j++)
                        invalidate_guid_record(dev, i + 1, j);
 
                dev->sriov.alias_guid.ports_guid[i].parent = &dev->sriov.alias_guid;
                dev->sriov.alias_guid.ports_guid[i].port  = i;
-               if (mlx4_ib_sm_guid_assign)
-                       set_all_slaves_guids(dev, i);
 
                snprintf(alias_wq_name, sizeof alias_wq_name, "alias_guid%d", i);
                dev->sriov.alias_guid.ports_guid[i].wq =
index 59040265e3614a23fc8508e88dd5b2138e7107e8..9cd2b002d7ae57fb4f33944cbaa14a3e2a27dedd 100644 (file)
@@ -1430,6 +1430,10 @@ static int mlx4_ib_alloc_pv_bufs(struct mlx4_ib_demux_pv_ctx *ctx,
                                                        tun_qp->ring[i].addr,
                                                        rx_buf_size,
                                                        DMA_FROM_DEVICE);
+               if (ib_dma_mapping_error(ctx->ib_dev, tun_qp->ring[i].map)) {
+                       kfree(tun_qp->ring[i].addr);
+                       goto err;
+               }
        }
 
        for (i = 0; i < MLX4_NUM_TUNNEL_BUFS; i++) {
@@ -1442,6 +1446,11 @@ static int mlx4_ib_alloc_pv_bufs(struct mlx4_ib_demux_pv_ctx *ctx,
                                          tun_qp->tx_ring[i].buf.addr,
                                          tx_buf_size,
                                          DMA_TO_DEVICE);
+               if (ib_dma_mapping_error(ctx->ib_dev,
+                                        tun_qp->tx_ring[i].buf.map)) {
+                       kfree(tun_qp->tx_ring[i].buf.addr);
+                       goto tx_err;
+               }
                tun_qp->tx_ring[i].ah = NULL;
        }
        spin_lock_init(&tun_qp->tx_lock);
index 976bea794b5f7726cd642cb08de4073abd5dcb58..57070c529dfb5ca038e2118212684dc54bb3d21b 100644 (file)
@@ -66,9 +66,9 @@ MODULE_DESCRIPTION("Mellanox ConnectX HCA InfiniBand driver");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_VERSION(DRV_VERSION);
 
-int mlx4_ib_sm_guid_assign = 1;
+int mlx4_ib_sm_guid_assign = 0;
 module_param_named(sm_guid_assign, mlx4_ib_sm_guid_assign, int, 0444);
-MODULE_PARM_DESC(sm_guid_assign, "Enable SM alias_GUID assignment if sm_guid_assign > 0 (Default: 1)");
+MODULE_PARM_DESC(sm_guid_assign, "Enable SM alias_GUID assignment if sm_guid_assign > 0 (Default: 0)");
 
 static const char mlx4_ib_version[] =
        DRV_NAME ": Mellanox ConnectX InfiniBand driver v"
@@ -2791,9 +2791,31 @@ static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr,
        case MLX4_DEV_EVENT_SLAVE_INIT:
                /* here, p is the slave id */
                do_slave_init(ibdev, p, 1);
+               if (mlx4_is_master(dev)) {
+                       int i;
+
+                       for (i = 1; i <= ibdev->num_ports; i++) {
+                               if (rdma_port_get_link_layer(&ibdev->ib_dev, i)
+                                       == IB_LINK_LAYER_INFINIBAND)
+                                       mlx4_ib_slave_alias_guid_event(ibdev,
+                                                                      p, i,
+                                                                      1);
+                       }
+               }
                return;
 
        case MLX4_DEV_EVENT_SLAVE_SHUTDOWN:
+               if (mlx4_is_master(dev)) {
+                       int i;
+
+                       for (i = 1; i <= ibdev->num_ports; i++) {
+                               if (rdma_port_get_link_layer(&ibdev->ib_dev, i)
+                                       == IB_LINK_LAYER_INFINIBAND)
+                                       mlx4_ib_slave_alias_guid_event(ibdev,
+                                                                      p, i,
+                                                                      0);
+                       }
+               }
                /* here, p is the slave id */
                do_slave_init(ibdev, p, 0);
                return;
index f829fd935b7901b82649a9d3307b46add1aa2ed5..fce3934372a161680e4e4f2dd9716963e1178790 100644 (file)
@@ -342,14 +342,9 @@ struct mlx4_ib_ah {
 enum mlx4_guid_alias_rec_status {
        MLX4_GUID_INFO_STATUS_IDLE,
        MLX4_GUID_INFO_STATUS_SET,
-       MLX4_GUID_INFO_STATUS_PENDING,
 };
 
-enum mlx4_guid_alias_rec_ownership {
-       MLX4_GUID_DRIVER_ASSIGN,
-       MLX4_GUID_SYSADMIN_ASSIGN,
-       MLX4_GUID_NONE_ASSIGN, /*init state of each record*/
-};
+#define GUID_STATE_NEED_PORT_INIT 0x01
 
 enum mlx4_guid_alias_rec_method {
        MLX4_GUID_INFO_RECORD_SET       = IB_MGMT_METHOD_SET,
@@ -360,8 +355,8 @@ struct mlx4_sriov_alias_guid_info_rec_det {
        u8 all_recs[GUID_REC_SIZE * NUM_ALIAS_GUID_IN_REC];
        ib_sa_comp_mask guid_indexes; /*indicates what from the 8 records are valid*/
        enum mlx4_guid_alias_rec_status status; /*indicates the administraively status of the record.*/
-       u8 method; /*set or delete*/
-       enum mlx4_guid_alias_rec_ownership ownership; /*indicates who assign that alias_guid record*/
+       unsigned int guids_retry_schedule[NUM_ALIAS_GUID_IN_REC];
+       u64 time_to_run;
 };
 
 struct mlx4_sriov_alias_guid_port_rec_det {
@@ -369,6 +364,7 @@ struct mlx4_sriov_alias_guid_port_rec_det {
        struct workqueue_struct *wq;
        struct delayed_work alias_guid_work;
        u8 port;
+       u32 state_flags;
        struct mlx4_sriov_alias_guid *parent;
        struct list_head cb_list;
 };
@@ -802,6 +798,8 @@ int add_sysfs_port_mcg_attr(struct mlx4_ib_dev *device, int port_num,
 void del_sysfs_port_mcg_attr(struct mlx4_ib_dev *device, int port_num,
                             struct attribute *attr);
 ib_sa_comp_mask mlx4_ib_get_aguid_comp_mask_from_ix(int index);
+void mlx4_ib_slave_alias_guid_event(struct mlx4_ib_dev *dev, int slave,
+                                   int port, int slave_init);
 
 int mlx4_ib_device_register_sysfs(struct mlx4_ib_dev *device) ;
 
index ed2bd6701f9b131c3dc3261cb2eae21a2d835524..02fc91c6802787e0f8f723417d9c7655b6123d3a 100644 (file)
@@ -566,6 +566,10 @@ static int alloc_proxy_bufs(struct ib_device *dev, struct mlx4_ib_qp *qp)
                        ib_dma_map_single(dev, qp->sqp_proxy_rcv[i].addr,
                                          sizeof (struct mlx4_ib_proxy_sqp_hdr),
                                          DMA_FROM_DEVICE);
+               if (ib_dma_mapping_error(dev, qp->sqp_proxy_rcv[i].map)) {
+                       kfree(qp->sqp_proxy_rcv[i].addr);
+                       goto err;
+               }
        }
        return 0;
 
@@ -2605,8 +2609,7 @@ static int build_lso_seg(struct mlx4_wqe_lso_seg *wqe, struct ib_send_wr *wr,
 
        memcpy(wqe->header, wr->wr.ud.header, wr->wr.ud.hlen);
 
-       *lso_hdr_sz  = cpu_to_be32((wr->wr.ud.mss - wr->wr.ud.hlen) << 16 |
-                                  wr->wr.ud.hlen);
+       *lso_hdr_sz  = cpu_to_be32(wr->wr.ud.mss << 16 | wr->wr.ud.hlen);
        *lso_seg_len = halign;
        return 0;
 }
index d10c2b8a5dadbe7eef1774c2eb29471ac317cb27..6797108ce8735b7aa11b08b4c09d8b62c29ec364 100644 (file)
 static ssize_t show_admin_alias_guid(struct device *dev,
                              struct device_attribute *attr, char *buf)
 {
-       int record_num;/*0-15*/
-       int guid_index_in_rec; /*0 - 7*/
        struct mlx4_ib_iov_sysfs_attr *mlx4_ib_iov_dentry =
                container_of(attr, struct mlx4_ib_iov_sysfs_attr, dentry);
        struct mlx4_ib_iov_port *port = mlx4_ib_iov_dentry->ctx;
        struct mlx4_ib_dev *mdev = port->dev;
+       __be64 sysadmin_ag_val;
 
-       record_num = mlx4_ib_iov_dentry->entry_num / 8 ;
-       guid_index_in_rec = mlx4_ib_iov_dentry->entry_num % 8 ;
+       sysadmin_ag_val = mlx4_get_admin_guid(mdev->dev,
+                                             mlx4_ib_iov_dentry->entry_num,
+                                             port->num);
 
-       return sprintf(buf, "%llx\n",
-                      be64_to_cpu(*(__be64 *)&mdev->sriov.alias_guid.
-                                  ports_guid[port->num - 1].
-                                  all_rec_per_port[record_num].
-                                  all_recs[8 * guid_index_in_rec]));
+       return sprintf(buf, "%llx\n", be64_to_cpu(sysadmin_ag_val));
 }
 
 /* store_admin_alias_guid stores the (new) administratively assigned value of that GUID.
@@ -80,6 +76,7 @@ static ssize_t store_admin_alias_guid(struct device *dev,
        struct mlx4_ib_iov_port *port = mlx4_ib_iov_dentry->ctx;
        struct mlx4_ib_dev *mdev = port->dev;
        u64 sysadmin_ag_val;
+       unsigned long flags;
 
        record_num = mlx4_ib_iov_dentry->entry_num / 8;
        guid_index_in_rec = mlx4_ib_iov_dentry->entry_num % 8;
@@ -87,6 +84,7 @@ static ssize_t store_admin_alias_guid(struct device *dev,
                pr_err("GUID 0 block 0 is RO\n");
                return count;
        }
+       spin_lock_irqsave(&mdev->sriov.alias_guid.ag_work_lock, flags);
        sscanf(buf, "%llx", &sysadmin_ag_val);
        *(__be64 *)&mdev->sriov.alias_guid.ports_guid[port->num - 1].
                all_rec_per_port[record_num].
@@ -96,33 +94,15 @@ static ssize_t store_admin_alias_guid(struct device *dev,
        /* Change the state to be pending for update */
        mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].status
                = MLX4_GUID_INFO_STATUS_IDLE ;
-
-       mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].method
-               = MLX4_GUID_INFO_RECORD_SET;
-
-       switch (sysadmin_ag_val) {
-       case MLX4_GUID_FOR_DELETE_VAL:
-               mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].method
-                       = MLX4_GUID_INFO_RECORD_DELETE;
-               mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].ownership
-                       = MLX4_GUID_SYSADMIN_ASSIGN;
-               break;
-       /* The sysadmin requests the SM to re-assign */
-       case MLX4_NOT_SET_GUID:
-               mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].ownership
-                       = MLX4_GUID_DRIVER_ASSIGN;
-               break;
-       /* The sysadmin requests a specific value.*/
-       default:
-               mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].ownership
-                       = MLX4_GUID_SYSADMIN_ASSIGN;
-               break;
-       }
+       mlx4_set_admin_guid(mdev->dev, cpu_to_be64(sysadmin_ag_val),
+                           mlx4_ib_iov_dentry->entry_num,
+                           port->num);
 
        /* set the record index */
        mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].guid_indexes
-               = mlx4_ib_get_aguid_comp_mask_from_ix(guid_index_in_rec);
+               |= mlx4_ib_get_aguid_comp_mask_from_ix(guid_index_in_rec);
 
+       spin_unlock_irqrestore(&mdev->sriov.alias_guid.ag_work_lock, flags);
        mlx4_ib_init_alias_guid_work(mdev, port->num - 1);
 
        return count;
index 3b2a6dc8ea99d734645a24cef66a78867f66a2cd..9f9d5c563a614c0c273368966d380c82d9b2a1a4 100644 (file)
@@ -116,6 +116,7 @@ static struct ibnl_client_cbs nes_nl_cb_table[] = {
        [RDMA_NL_IWPM_REG_PID] = {.dump = iwpm_register_pid_cb},
        [RDMA_NL_IWPM_ADD_MAPPING] = {.dump = iwpm_add_mapping_cb},
        [RDMA_NL_IWPM_QUERY_MAPPING] = {.dump = iwpm_add_and_query_mapping_cb},
+       [RDMA_NL_IWPM_REMOTE_INFO] = {.dump = iwpm_remote_info_cb},
        [RDMA_NL_IWPM_HANDLE_ERR] = {.dump = iwpm_mapping_error_cb},
        [RDMA_NL_IWPM_MAPINFO] = {.dump = iwpm_mapping_info_cb},
        [RDMA_NL_IWPM_MAPINFO_NUM] = {.dump = iwpm_ack_mapping_info_cb}
index 6f09a72e78d7d8ec9690413924e079af764aeaf3..72b43417cbe382aed9164b5554e80b449270c3ad 100644 (file)
@@ -596,27 +596,52 @@ static void nes_form_reg_msg(struct nes_vnic *nesvnic,
        memcpy(pm_msg->if_name, nesvnic->netdev->name, IWPM_IFNAME_SIZE);
 }
 
+static void record_sockaddr_info(struct sockaddr_storage *addr_info,
+                                       nes_addr_t *ip_addr, u16 *port_num)
+{
+       struct sockaddr_in *in_addr = (struct sockaddr_in *)addr_info;
+
+       if (in_addr->sin_family == AF_INET) {
+               *ip_addr = ntohl(in_addr->sin_addr.s_addr);
+               *port_num = ntohs(in_addr->sin_port);
+       }
+}
+
 /*
  * nes_record_pm_msg - Save the received mapping info
  */
 static void nes_record_pm_msg(struct nes_cm_info *cm_info,
                        struct iwpm_sa_data *pm_msg)
 {
-       struct sockaddr_in *mapped_loc_addr =
-                       (struct sockaddr_in *)&pm_msg->mapped_loc_addr;
-       struct sockaddr_in *mapped_rem_addr =
-                       (struct sockaddr_in *)&pm_msg->mapped_rem_addr;
-
-       if (mapped_loc_addr->sin_family == AF_INET) {
-               cm_info->mapped_loc_addr =
-                       ntohl(mapped_loc_addr->sin_addr.s_addr);
-               cm_info->mapped_loc_port = ntohs(mapped_loc_addr->sin_port);
-       }
-       if (mapped_rem_addr->sin_family == AF_INET) {
-               cm_info->mapped_rem_addr =
-                       ntohl(mapped_rem_addr->sin_addr.s_addr);
-               cm_info->mapped_rem_port = ntohs(mapped_rem_addr->sin_port);
-       }
+       record_sockaddr_info(&pm_msg->mapped_loc_addr,
+               &cm_info->mapped_loc_addr, &cm_info->mapped_loc_port);
+
+       record_sockaddr_info(&pm_msg->mapped_rem_addr,
+               &cm_info->mapped_rem_addr, &cm_info->mapped_rem_port);
+}
+
+/*
+ * nes_get_reminfo - Get the address info of the remote connecting peer
+ */
+static int nes_get_remote_addr(struct nes_cm_node *cm_node)
+{
+       struct sockaddr_storage mapped_loc_addr, mapped_rem_addr;
+       struct sockaddr_storage remote_addr;
+       int ret;
+
+       nes_create_sockaddr(htonl(cm_node->mapped_loc_addr),
+                       htons(cm_node->mapped_loc_port), &mapped_loc_addr);
+       nes_create_sockaddr(htonl(cm_node->mapped_rem_addr),
+                       htons(cm_node->mapped_rem_port), &mapped_rem_addr);
+
+       ret = iwpm_get_remote_info(&mapped_loc_addr, &mapped_rem_addr,
+                               &remote_addr, RDMA_NL_NES);
+       if (ret)
+               nes_debug(NES_DBG_CM, "Unable to find remote peer address info\n");
+       else
+               record_sockaddr_info(&remote_addr, &cm_node->rem_addr,
+                               &cm_node->rem_port);
+       return ret;
 }
 
 /**
@@ -1566,9 +1591,14 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
                return NULL;
 
        /* set our node specific transport info */
-       cm_node->loc_addr = cm_info->loc_addr;
+       if (listener) {
+               cm_node->loc_addr = listener->loc_addr;
+               cm_node->loc_port = listener->loc_port;
+       } else {
+               cm_node->loc_addr = cm_info->loc_addr;
+               cm_node->loc_port = cm_info->loc_port;
+       }
        cm_node->rem_addr = cm_info->rem_addr;
-       cm_node->loc_port = cm_info->loc_port;
        cm_node->rem_port = cm_info->rem_port;
 
        cm_node->mapped_loc_addr = cm_info->mapped_loc_addr;
@@ -2151,6 +2181,7 @@ static int handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
                cm_node->state = NES_CM_STATE_ESTABLISHED;
                if (datasize) {
                        cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
+                       nes_get_remote_addr(cm_node);
                        handle_rcv_mpa(cm_node, skb);
                } else { /* rcvd ACK only */
                        dev_kfree_skb_any(skb);
index ffd48bfc4923457e5383345acfa3620fa5f6a52f..ba5173e249738cb123560a29701bdacb496e9fc8 100644 (file)
@@ -1136,7 +1136,6 @@ extern struct qib_devdata *qib_lookup(int unit);
 extern u32 qib_cpulist_count;
 extern unsigned long *qib_cpulist;
 
-extern unsigned qib_wc_pat;
 extern unsigned qib_cc_table_size;
 int qib_init(struct qib_devdata *, int);
 int init_chip_wc_pat(struct qib_devdata *dd, u32);
index 9ea6c440a00ca7012f6422f1ffd7f525b8d80548..725881890c4a217247993f9fbb933ff11bb27e27 100644 (file)
@@ -835,7 +835,8 @@ static int mmap_piobufs(struct vm_area_struct *vma,
        vma->vm_flags &= ~VM_MAYREAD;
        vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND;
 
-       if (qib_wc_pat)
+       /* We used PAT if wc_cookie == 0 */
+       if (!dd->wc_cookie)
                vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
 
        ret = io_remap_pfn_range(vma, vma->vm_start, phys >> PAGE_SHIFT,
index 650897a8591e872f338d03994da3ed18e5a51bf7..bdd5d3857203198bca5c8f04f701b14c9c53dcb1 100644 (file)
@@ -89,14 +89,14 @@ static int create_file(const char *name, umode_t mode,
 {
        int error;
 
-       mutex_lock(&parent->d_inode->i_mutex);
+       mutex_lock(&d_inode(parent)->i_mutex);
        *dentry = lookup_one_len(name, parent, strlen(name));
        if (!IS_ERR(*dentry))
-               error = qibfs_mknod(parent->d_inode, *dentry,
+               error = qibfs_mknod(d_inode(parent), *dentry,
                                    mode, fops, data);
        else
                error = PTR_ERR(*dentry);
-       mutex_unlock(&parent->d_inode->i_mutex);
+       mutex_unlock(&d_inode(parent)->i_mutex);
 
        return error;
 }
@@ -455,10 +455,10 @@ static int remove_file(struct dentry *parent, char *name)
        }
 
        spin_lock(&tmp->d_lock);
-       if (!d_unhashed(tmp) && tmp->d_inode) {
+       if (!d_unhashed(tmp) && d_really_is_positive(tmp)) {
                __d_drop(tmp);
                spin_unlock(&tmp->d_lock);
-               simple_unlink(parent->d_inode, tmp);
+               simple_unlink(d_inode(parent), tmp);
        } else {
                spin_unlock(&tmp->d_lock);
        }
@@ -481,7 +481,7 @@ static int remove_device_files(struct super_block *sb,
        int ret, i;
 
        root = dget(sb->s_root);
-       mutex_lock(&root->d_inode->i_mutex);
+       mutex_lock(&d_inode(root)->i_mutex);
        snprintf(unit, sizeof(unit), "%u", dd->unit);
        dir = lookup_one_len(unit, root, strlen(unit));
 
@@ -491,7 +491,7 @@ static int remove_device_files(struct super_block *sb,
                goto bail;
        }
 
-       mutex_lock(&dir->d_inode->i_mutex);
+       mutex_lock(&d_inode(dir)->i_mutex);
        remove_file(dir, "counters");
        remove_file(dir, "counter_names");
        remove_file(dir, "portcounter_names");
@@ -506,13 +506,13 @@ static int remove_device_files(struct super_block *sb,
                }
        }
        remove_file(dir, "flash");
-       mutex_unlock(&dir->d_inode->i_mutex);
-       ret = simple_rmdir(root->d_inode, dir);
+       mutex_unlock(&d_inode(dir)->i_mutex);
+       ret = simple_rmdir(d_inode(root), dir);
        d_delete(dir);
        dput(dir);
 
 bail:
-       mutex_unlock(&root->d_inode->i_mutex);
+       mutex_unlock(&d_inode(root)->i_mutex);
        dput(root);
        return ret;
 }
index 0d2ba59af30af66bce01ef8132c8182cc6e44a33..4b927809d1a1191004799435c7aa9163d8d6f086 100644 (file)
@@ -3315,11 +3315,9 @@ static int init_6120_variables(struct qib_devdata *dd)
        qib_6120_config_ctxts(dd);
        qib_set_ctxtcnt(dd);
 
-       if (qib_wc_pat) {
-               ret = init_chip_wc_pat(dd, 0);
-               if (ret)
-                       goto bail;
-       }
+       ret = init_chip_wc_pat(dd, 0);
+       if (ret)
+               goto bail;
        set_6120_baseaddrs(dd); /* set chip access pointers now */
 
        ret = 0;
index 22affda8af88eacbd11f21abab55ba299dfb0e0b..00b2af211157b5513092e495d62a0a014a1e1c2f 100644 (file)
@@ -4126,11 +4126,9 @@ static int qib_init_7220_variables(struct qib_devdata *dd)
        qib_7220_config_ctxts(dd);
        qib_set_ctxtcnt(dd);  /* needed for PAT setup */
 
-       if (qib_wc_pat) {
-               ret = init_chip_wc_pat(dd, 0);
-               if (ret)
-                       goto bail;
-       }
+       ret = init_chip_wc_pat(dd, 0);
+       if (ret)
+               goto bail;
        set_7220_baseaddrs(dd); /* set chip access pointers now */
 
        ret = 0;
index ef97b71c8f7dd713a77401f593c6a10320a046e6..f32b4628e9913e17dfd0606e1713945ff65930f2 100644 (file)
@@ -6429,6 +6429,7 @@ static int qib_init_7322_variables(struct qib_devdata *dd)
        unsigned features, pidx, sbufcnt;
        int ret, mtu;
        u32 sbufs, updthresh;
+       resource_size_t vl15off;
 
        /* pport structs are contiguous, allocated after devdata */
        ppd = (struct qib_pportdata *)(dd + 1);
@@ -6677,29 +6678,27 @@ static int qib_init_7322_variables(struct qib_devdata *dd)
        qib_7322_config_ctxts(dd);
        qib_set_ctxtcnt(dd);
 
-       if (qib_wc_pat) {
-               resource_size_t vl15off;
-               /*
-                * We do not set WC on the VL15 buffers to avoid
-                * a rare problem with unaligned writes from
-                * interrupt-flushed store buffers, so we need
-                * to map those separately here.  We can't solve
-                * this for the rarely used mtrr case.
-                */
-               ret = init_chip_wc_pat(dd, 0);
-               if (ret)
-                       goto bail;
+       /*
+        * We do not set WC on the VL15 buffers to avoid
+        * a rare problem with unaligned writes from
+        * interrupt-flushed store buffers, so we need
+        * to map those separately here.  We can't solve
+        * this for the rarely used mtrr case.
+        */
+       ret = init_chip_wc_pat(dd, 0);
+       if (ret)
+               goto bail;
 
-               /* vl15 buffers start just after the 4k buffers */
-               vl15off = dd->physaddr + (dd->piobufbase >> 32) +
-                       dd->piobcnt4k * dd->align4k;
-               dd->piovl15base = ioremap_nocache(vl15off,
-                                                 NUM_VL15_BUFS * dd->align4k);
-               if (!dd->piovl15base) {
-                       ret = -ENOMEM;
-                       goto bail;
-               }
+       /* vl15 buffers start just after the 4k buffers */
+       vl15off = dd->physaddr + (dd->piobufbase >> 32) +
+                 dd->piobcnt4k * dd->align4k;
+       dd->piovl15base = ioremap_nocache(vl15off,
+                                         NUM_VL15_BUFS * dd->align4k);
+       if (!dd->piovl15base) {
+               ret = -ENOMEM;
+               goto bail;
        }
+
        qib_7322_set_baseaddrs(dd); /* set chip access pointers now */
 
        ret = 0;
index 2ee36953e234c46ff704bc6e5dfbed8339c09974..7e00470adc30223c183f0e287f7a7d0d9beff944 100644 (file)
@@ -91,15 +91,6 @@ MODULE_PARM_DESC(krcvqs, "number of kernel receive queues per IB port");
 unsigned qib_cc_table_size;
 module_param_named(cc_table_size, qib_cc_table_size, uint, S_IRUGO);
 MODULE_PARM_DESC(cc_table_size, "Congestion control table entries 0 (CCA disabled - default), min = 128, max = 1984");
-/*
- * qib_wc_pat parameter:
- *      0 is WC via MTRR
- *      1 is WC via PAT
- *      If PAT initialization fails, code reverts back to MTRR
- */
-unsigned qib_wc_pat = 1; /* default (1) is to use PAT, not MTRR */
-module_param_named(wc_pat, qib_wc_pat, uint, S_IRUGO);
-MODULE_PARM_DESC(wc_pat, "enable write-combining via PAT mechanism");
 
 static void verify_interrupt(unsigned long);
 
@@ -1377,8 +1368,7 @@ static void cleanup_device_data(struct qib_devdata *dd)
                spin_unlock(&dd->pport[pidx].cc_shadow_lock);
        }
 
-       if (!qib_wc_pat)
-               qib_disable_wc(dd);
+       qib_disable_wc(dd);
 
        if (dd->pioavailregs_dma) {
                dma_free_coherent(&dd->pcidev->dev, PAGE_SIZE,
@@ -1547,14 +1537,12 @@ static int qib_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto bail;
        }
 
-       if (!qib_wc_pat) {
-               ret = qib_enable_wc(dd);
-               if (ret) {
-                       qib_dev_err(dd,
-                               "Write combining not enabled (err %d): performance may be poor\n",
-                               -ret);
-                       ret = 0;
-               }
+       ret = qib_enable_wc(dd);
+       if (ret) {
+               qib_dev_err(dd,
+                       "Write combining not enabled (err %d): performance may be poor\n",
+                       -ret);
+               ret = 0;
        }
 
        qib_verify_pioperf(dd);
index 81b225f2300aed34eab9b88077bd4c4097dceae2..6d61ef98721cb02f6b4baeead132cbe1d399753c 100644 (file)
@@ -116,21 +116,9 @@ int qib_enable_wc(struct qib_devdata *dd)
        }
 
        if (!ret) {
-               int cookie;
-
-               cookie = mtrr_add(pioaddr, piolen, MTRR_TYPE_WRCOMB, 0);
-               if (cookie < 0) {
-                       {
-                               qib_devinfo(dd->pcidev,
-                                        "mtrr_add()  WC for PIO bufs failed (%d)\n",
-                                        cookie);
-                               ret = -EINVAL;
-                       }
-               } else {
-                       dd->wc_cookie = cookie;
-                       dd->wc_base = (unsigned long) pioaddr;
-                       dd->wc_len = (unsigned long) piolen;
-               }
+               dd->wc_cookie = arch_phys_wc_add(pioaddr, piolen);
+               if (dd->wc_cookie < 0)
+                       ret = -EINVAL;
        }
 
        return ret;
@@ -142,18 +130,7 @@ int qib_enable_wc(struct qib_devdata *dd)
  */
 void qib_disable_wc(struct qib_devdata *dd)
 {
-       if (dd->wc_cookie) {
-               int r;
-
-               r = mtrr_del(dd->wc_cookie, dd->wc_base,
-                            dd->wc_len);
-               if (r < 0)
-                       qib_devinfo(dd->pcidev,
-                                "mtrr_del(%lx, %lx, %lx) failed: %d\n",
-                                dd->wc_cookie, dd->wc_base,
-                                dd->wc_len, r);
-               dd->wc_cookie = 0; /* even on failure */
-       }
+       arch_phys_wc_del(dd->wc_cookie);
 }
 
 /**
index d7562beb542367faf1b93d7ba66e8ef879c73bf4..bd94b0a6e9e535f8d8b4a9e1fa1428e0696e2947 100644 (file)
@@ -87,7 +87,6 @@ enum {
        IPOIB_FLAG_ADMIN_UP       = 2,
        IPOIB_PKEY_ASSIGNED       = 3,
        IPOIB_FLAG_SUBINTERFACE   = 5,
-       IPOIB_MCAST_RUN           = 6,
        IPOIB_STOP_REAPER         = 7,
        IPOIB_FLAG_ADMIN_CM       = 9,
        IPOIB_FLAG_UMCAST         = 10,
@@ -98,9 +97,15 @@ enum {
 
        IPOIB_MCAST_FLAG_FOUND    = 0,  /* used in set_multicast_list */
        IPOIB_MCAST_FLAG_SENDONLY = 1,
-       IPOIB_MCAST_FLAG_BUSY     = 2,  /* joining or already joined */
+       /*
+        * For IPOIB_MCAST_FLAG_BUSY
+        * When set, in flight join and mcast->mc is unreliable
+        * When clear and mcast->mc IS_ERR_OR_NULL, need to restart or
+        *   haven't started yet
+        * When clear and mcast->mc is valid pointer, join was successful
+        */
+       IPOIB_MCAST_FLAG_BUSY     = 2,
        IPOIB_MCAST_FLAG_ATTACHED = 3,
-       IPOIB_MCAST_JOIN_STARTED  = 4,
 
        MAX_SEND_CQE              = 16,
        IPOIB_CM_COPYBREAK        = 256,
@@ -148,6 +153,7 @@ struct ipoib_mcast {
 
        unsigned long created;
        unsigned long backoff;
+       unsigned long delay_until;
 
        unsigned long flags;
        unsigned char logcount;
@@ -292,6 +298,11 @@ struct ipoib_neigh_table {
        struct completion               deleted;
 };
 
+struct ipoib_qp_state_validate {
+       struct work_struct work;
+       struct ipoib_dev_priv   *priv;
+};
+
 /*
  * Device private locking: network stack tx_lock protects members used
  * in TX fast path, lock protects everything else.  lock nests inside
@@ -317,6 +328,7 @@ struct ipoib_dev_priv {
        struct list_head multicast_list;
        struct rb_root multicast_tree;
 
+       struct workqueue_struct *wq;
        struct delayed_work mcast_task;
        struct work_struct carrier_on_task;
        struct work_struct flush_light;
@@ -426,11 +438,6 @@ struct ipoib_neigh {
 #define IPOIB_UD_MTU(ib_mtu)           (ib_mtu - IPOIB_ENCAP_LEN)
 #define IPOIB_UD_BUF_SIZE(ib_mtu)      (ib_mtu + IB_GRH_BYTES)
 
-static inline int ipoib_ud_need_sg(unsigned int ib_mtu)
-{
-       return IPOIB_UD_BUF_SIZE(ib_mtu) > PAGE_SIZE;
-}
-
 void ipoib_neigh_dtor(struct ipoib_neigh *neigh);
 static inline void ipoib_neigh_put(struct ipoib_neigh *neigh)
 {
@@ -477,10 +484,10 @@ void ipoib_ib_dev_flush_heavy(struct work_struct *work);
 void ipoib_pkey_event(struct work_struct *work);
 void ipoib_ib_dev_cleanup(struct net_device *dev);
 
-int ipoib_ib_dev_open(struct net_device *dev, int flush);
+int ipoib_ib_dev_open(struct net_device *dev);
 int ipoib_ib_dev_up(struct net_device *dev);
-int ipoib_ib_dev_down(struct net_device *dev, int flush);
-int ipoib_ib_dev_stop(struct net_device *dev, int flush);
+int ipoib_ib_dev_down(struct net_device *dev);
+int ipoib_ib_dev_stop(struct net_device *dev);
 void ipoib_pkey_dev_check_presence(struct net_device *dev);
 
 int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port);
@@ -492,7 +499,7 @@ void ipoib_mcast_send(struct net_device *dev, u8 *daddr, struct sk_buff *skb);
 
 void ipoib_mcast_restart_task(struct work_struct *work);
 int ipoib_mcast_start_thread(struct net_device *dev);
-int ipoib_mcast_stop_thread(struct net_device *dev, int flush);
+int ipoib_mcast_stop_thread(struct net_device *dev);
 
 void ipoib_mcast_dev_down(struct net_device *dev);
 void ipoib_mcast_dev_flush(struct net_device *dev);
index 933efcea0d03f11b4da3967b8eedc137da21e08a..cf32a778e7d0ccc0b6225d9c01442f5d2ec4cdb1 100644 (file)
@@ -386,8 +386,8 @@ static int ipoib_cm_nonsrq_init_rx(struct net_device *dev, struct ib_cm_id *cm_i
                                           rx->rx_ring[i].mapping,
                                           GFP_KERNEL)) {
                        ipoib_warn(priv, "failed to allocate receive buffer %d\n", i);
-                               ret = -ENOMEM;
-                               goto err_count;
+                       ret = -ENOMEM;
+                       goto err_count;
                }
                ret = ipoib_cm_post_receive_nonsrq(dev, rx, &t->wr, t->sge, i);
                if (ret) {
@@ -474,7 +474,7 @@ static int ipoib_cm_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *even
        }
 
        spin_lock_irq(&priv->lock);
-       queue_delayed_work(ipoib_workqueue,
+       queue_delayed_work(priv->wq,
                           &priv->cm.stale_task, IPOIB_CM_RX_DELAY);
        /* Add this entry to passive ids list head, but do not re-add it
         * if IB_EVENT_QP_LAST_WQE_REACHED has moved it to flush list. */
@@ -576,7 +576,7 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
                        spin_lock_irqsave(&priv->lock, flags);
                        list_splice_init(&priv->cm.rx_drain_list, &priv->cm.rx_reap_list);
                        ipoib_cm_start_rx_drain(priv);
-                       queue_work(ipoib_workqueue, &priv->cm.rx_reap_task);
+                       queue_work(priv->wq, &priv->cm.rx_reap_task);
                        spin_unlock_irqrestore(&priv->lock, flags);
                } else
                        ipoib_warn(priv, "cm recv completion event with wrid %d (> %d)\n",
@@ -603,7 +603,7 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
                                spin_lock_irqsave(&priv->lock, flags);
                                list_move(&p->list, &priv->cm.rx_reap_list);
                                spin_unlock_irqrestore(&priv->lock, flags);
-                               queue_work(ipoib_workqueue, &priv->cm.rx_reap_task);
+                               queue_work(priv->wq, &priv->cm.rx_reap_task);
                        }
                        return;
                }
@@ -827,7 +827,7 @@ void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
 
                if (test_and_clear_bit(IPOIB_FLAG_INITIALIZED, &tx->flags)) {
                        list_move(&tx->list, &priv->cm.reap_list);
-                       queue_work(ipoib_workqueue, &priv->cm.reap_task);
+                       queue_work(priv->wq, &priv->cm.reap_task);
                }
 
                clear_bit(IPOIB_FLAG_OPER_UP, &tx->flags);
@@ -1255,7 +1255,7 @@ static int ipoib_cm_tx_handler(struct ib_cm_id *cm_id,
 
                if (test_and_clear_bit(IPOIB_FLAG_INITIALIZED, &tx->flags)) {
                        list_move(&tx->list, &priv->cm.reap_list);
-                       queue_work(ipoib_workqueue, &priv->cm.reap_task);
+                       queue_work(priv->wq, &priv->cm.reap_task);
                }
 
                spin_unlock_irqrestore(&priv->lock, flags);
@@ -1284,7 +1284,7 @@ struct ipoib_cm_tx *ipoib_cm_create_tx(struct net_device *dev, struct ipoib_path
        tx->dev = dev;
        list_add(&tx->list, &priv->cm.start_list);
        set_bit(IPOIB_FLAG_INITIALIZED, &tx->flags);
-       queue_work(ipoib_workqueue, &priv->cm.start_task);
+       queue_work(priv->wq, &priv->cm.start_task);
        return tx;
 }
 
@@ -1295,7 +1295,7 @@ void ipoib_cm_destroy_tx(struct ipoib_cm_tx *tx)
        if (test_and_clear_bit(IPOIB_FLAG_INITIALIZED, &tx->flags)) {
                spin_lock_irqsave(&priv->lock, flags);
                list_move(&tx->list, &priv->cm.reap_list);
-               queue_work(ipoib_workqueue, &priv->cm.reap_task);
+               queue_work(priv->wq, &priv->cm.reap_task);
                ipoib_dbg(priv, "Reap connection for gid %pI6\n",
                          tx->neigh->daddr + 4);
                tx->neigh = NULL;
@@ -1417,7 +1417,7 @@ void ipoib_cm_skb_too_long(struct net_device *dev, struct sk_buff *skb,
 
        skb_queue_tail(&priv->cm.skb_queue, skb);
        if (e)
-               queue_work(ipoib_workqueue, &priv->cm.skb_task);
+               queue_work(priv->wq, &priv->cm.skb_task);
 }
 
 static void ipoib_cm_rx_reap(struct work_struct *work)
@@ -1450,7 +1450,7 @@ static void ipoib_cm_stale_task(struct work_struct *work)
        }
 
        if (!list_empty(&priv->cm.passive_ids))
-               queue_delayed_work(ipoib_workqueue,
+               queue_delayed_work(priv->wq,
                                   &priv->cm.stale_task, IPOIB_CM_RX_DELAY);
        spin_unlock_irq(&priv->lock);
 }
index 72626c3481749b962fe96b79722d7c8e9c99c585..63b92cbb29ad0ad1f0165a738a47efbe0f650e04 100644 (file)
@@ -94,39 +94,9 @@ void ipoib_free_ah(struct kref *kref)
 static void ipoib_ud_dma_unmap_rx(struct ipoib_dev_priv *priv,
                                  u64 mapping[IPOIB_UD_RX_SG])
 {
-       if (ipoib_ud_need_sg(priv->max_ib_mtu)) {
-               ib_dma_unmap_single(priv->ca, mapping[0], IPOIB_UD_HEAD_SIZE,
-                                   DMA_FROM_DEVICE);
-               ib_dma_unmap_page(priv->ca, mapping[1], PAGE_SIZE,
-                                 DMA_FROM_DEVICE);
-       } else
-               ib_dma_unmap_single(priv->ca, mapping[0],
-                                   IPOIB_UD_BUF_SIZE(priv->max_ib_mtu),
-                                   DMA_FROM_DEVICE);
-}
-
-static void ipoib_ud_skb_put_frags(struct ipoib_dev_priv *priv,
-                                  struct sk_buff *skb,
-                                  unsigned int length)
-{
-       if (ipoib_ud_need_sg(priv->max_ib_mtu)) {
-               skb_frag_t *frag = &skb_shinfo(skb)->frags[0];
-               unsigned int size;
-               /*
-                * There is only two buffers needed for max_payload = 4K,
-                * first buf size is IPOIB_UD_HEAD_SIZE
-                */
-               skb->tail += IPOIB_UD_HEAD_SIZE;
-               skb->len  += length;
-
-               size = length - IPOIB_UD_HEAD_SIZE;
-
-               skb_frag_size_set(frag, size);
-               skb->data_len += size;
-               skb->truesize += PAGE_SIZE;
-       } else
-               skb_put(skb, length);
-
+       ib_dma_unmap_single(priv->ca, mapping[0],
+                           IPOIB_UD_BUF_SIZE(priv->max_ib_mtu),
+                           DMA_FROM_DEVICE);
 }
 
 static int ipoib_ib_post_receive(struct net_device *dev, int id)
@@ -156,18 +126,11 @@ static struct sk_buff *ipoib_alloc_rx_skb(struct net_device *dev, int id)
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        struct sk_buff *skb;
        int buf_size;
-       int tailroom;
        u64 *mapping;
 
-       if (ipoib_ud_need_sg(priv->max_ib_mtu)) {
-               buf_size = IPOIB_UD_HEAD_SIZE;
-               tailroom = 128; /* reserve some tailroom for IP/TCP headers */
-       } else {
-               buf_size = IPOIB_UD_BUF_SIZE(priv->max_ib_mtu);
-               tailroom = 0;
-       }
+       buf_size = IPOIB_UD_BUF_SIZE(priv->max_ib_mtu);
 
-       skb = dev_alloc_skb(buf_size + tailroom + 4);
+       skb = dev_alloc_skb(buf_size + IPOIB_ENCAP_LEN);
        if (unlikely(!skb))
                return NULL;
 
@@ -184,23 +147,8 @@ static struct sk_buff *ipoib_alloc_rx_skb(struct net_device *dev, int id)
        if (unlikely(ib_dma_mapping_error(priv->ca, mapping[0])))
                goto error;
 
-       if (ipoib_ud_need_sg(priv->max_ib_mtu)) {
-               struct page *page = alloc_page(GFP_ATOMIC);
-               if (!page)
-                       goto partial_error;
-               skb_fill_page_desc(skb, 0, page, 0, PAGE_SIZE);
-               mapping[1] =
-                       ib_dma_map_page(priv->ca, page,
-                                       0, PAGE_SIZE, DMA_FROM_DEVICE);
-               if (unlikely(ib_dma_mapping_error(priv->ca, mapping[1])))
-                       goto partial_error;
-       }
-
        priv->rx_ring[id].skb = skb;
        return skb;
-
-partial_error:
-       ib_dma_unmap_single(priv->ca, mapping[0], buf_size, DMA_FROM_DEVICE);
 error:
        dev_kfree_skb_any(skb);
        return NULL;
@@ -278,7 +226,8 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
                       wc->byte_len, wc->slid);
 
        ipoib_ud_dma_unmap_rx(priv, mapping);
-       ipoib_ud_skb_put_frags(priv, skb, wc->byte_len);
+
+       skb_put(skb, wc->byte_len);
 
        /* First byte of dgid signals multicast when 0xff */
        dgid = &((struct ib_grh *)skb->data)->dgid;
@@ -296,6 +245,8 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
        skb_reset_mac_header(skb);
        skb_pull(skb, IPOIB_ENCAP_LEN);
 
+       skb->truesize = SKB_TRUESIZE(skb->len);
+
        ++dev->stats.rx_packets;
        dev->stats.rx_bytes += skb->len;
 
@@ -376,6 +327,51 @@ static void ipoib_dma_unmap_tx(struct ib_device *ca,
        }
 }
 
+/*
+ * As the result of a completion error the QP Can be transferred to SQE states.
+ * The function checks if the (send)QP is in SQE state and
+ * moves it back to RTS state, that in order to have it functional again.
+ */
+static void ipoib_qp_state_validate_work(struct work_struct *work)
+{
+       struct ipoib_qp_state_validate *qp_work =
+               container_of(work, struct ipoib_qp_state_validate, work);
+
+       struct ipoib_dev_priv *priv = qp_work->priv;
+       struct ib_qp_attr qp_attr;
+       struct ib_qp_init_attr query_init_attr;
+       int ret;
+
+       ret = ib_query_qp(priv->qp, &qp_attr, IB_QP_STATE, &query_init_attr);
+       if (ret) {
+               ipoib_warn(priv, "%s: Failed to query QP ret: %d\n",
+                          __func__, ret);
+               goto free_res;
+       }
+       pr_info("%s: QP: 0x%x is in state: %d\n",
+               __func__, priv->qp->qp_num, qp_attr.qp_state);
+
+       /* currently support only in SQE->RTS transition*/
+       if (qp_attr.qp_state == IB_QPS_SQE) {
+               qp_attr.qp_state = IB_QPS_RTS;
+
+               ret = ib_modify_qp(priv->qp, &qp_attr, IB_QP_STATE);
+               if (ret) {
+                       pr_warn("failed(%d) modify QP:0x%x SQE->RTS\n",
+                               ret, priv->qp->qp_num);
+                       goto free_res;
+               }
+               pr_info("%s: QP: 0x%x moved from IB_QPS_SQE to IB_QPS_RTS\n",
+                       __func__, priv->qp->qp_num);
+       } else {
+               pr_warn("QP (%d) will stay in state: %d\n",
+                       priv->qp->qp_num, qp_attr.qp_state);
+       }
+
+free_res:
+       kfree(qp_work);
+}
+
 static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
@@ -407,10 +403,22 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
                netif_wake_queue(dev);
 
        if (wc->status != IB_WC_SUCCESS &&
-           wc->status != IB_WC_WR_FLUSH_ERR)
+           wc->status != IB_WC_WR_FLUSH_ERR) {
+               struct ipoib_qp_state_validate *qp_work;
                ipoib_warn(priv, "failed send event "
                           "(status=%d, wrid=%d vend_err %x)\n",
                           wc->status, wr_id, wc->vendor_err);
+               qp_work = kzalloc(sizeof(*qp_work), GFP_ATOMIC);
+               if (!qp_work) {
+                       ipoib_warn(priv, "%s Failed alloc ipoib_qp_state_validate for qp: 0x%x\n",
+                                  __func__, priv->qp->qp_num);
+                       return;
+               }
+
+               INIT_WORK(&qp_work->work, ipoib_qp_state_validate_work);
+               qp_work->priv = priv;
+               queue_work(priv->wq, &qp_work->work);
+       }
 }
 
 static int poll_tx(struct ipoib_dev_priv *priv)
@@ -655,16 +663,33 @@ void ipoib_reap_ah(struct work_struct *work)
        __ipoib_reap_ah(dev);
 
        if (!test_bit(IPOIB_STOP_REAPER, &priv->flags))
-               queue_delayed_work(ipoib_workqueue, &priv->ah_reap_task,
+               queue_delayed_work(priv->wq, &priv->ah_reap_task,
                                   round_jiffies_relative(HZ));
 }
 
+static void ipoib_flush_ah(struct net_device *dev)
+{
+       struct ipoib_dev_priv *priv = netdev_priv(dev);
+
+       cancel_delayed_work(&priv->ah_reap_task);
+       flush_workqueue(priv->wq);
+       ipoib_reap_ah(&priv->ah_reap_task.work);
+}
+
+static void ipoib_stop_ah(struct net_device *dev)
+{
+       struct ipoib_dev_priv *priv = netdev_priv(dev);
+
+       set_bit(IPOIB_STOP_REAPER, &priv->flags);
+       ipoib_flush_ah(dev);
+}
+
 static void ipoib_ib_tx_timer_func(unsigned long ctx)
 {
        drain_tx_cq((struct net_device *)ctx);
 }
 
-int ipoib_ib_dev_open(struct net_device *dev, int flush)
+int ipoib_ib_dev_open(struct net_device *dev)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        int ret;
@@ -696,7 +721,7 @@ int ipoib_ib_dev_open(struct net_device *dev, int flush)
        }
 
        clear_bit(IPOIB_STOP_REAPER, &priv->flags);
-       queue_delayed_work(ipoib_workqueue, &priv->ah_reap_task,
+       queue_delayed_work(priv->wq, &priv->ah_reap_task,
                           round_jiffies_relative(HZ));
 
        if (!test_and_set_bit(IPOIB_FLAG_INITIALIZED, &priv->flags))
@@ -706,7 +731,7 @@ int ipoib_ib_dev_open(struct net_device *dev, int flush)
 dev_stop:
        if (!test_and_set_bit(IPOIB_FLAG_INITIALIZED, &priv->flags))
                napi_enable(&priv->napi);
-       ipoib_ib_dev_stop(dev, flush);
+       ipoib_ib_dev_stop(dev);
        return -1;
 }
 
@@ -738,7 +763,7 @@ int ipoib_ib_dev_up(struct net_device *dev)
        return ipoib_mcast_start_thread(dev);
 }
 
-int ipoib_ib_dev_down(struct net_device *dev, int flush)
+int ipoib_ib_dev_down(struct net_device *dev)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
 
@@ -747,7 +772,7 @@ int ipoib_ib_dev_down(struct net_device *dev, int flush)
        clear_bit(IPOIB_FLAG_OPER_UP, &priv->flags);
        netif_carrier_off(dev);
 
-       ipoib_mcast_stop_thread(dev, flush);
+       ipoib_mcast_stop_thread(dev);
        ipoib_mcast_dev_flush(dev);
 
        ipoib_flush_paths(dev);
@@ -807,7 +832,7 @@ void ipoib_drain_cq(struct net_device *dev)
        local_bh_enable();
 }
 
-int ipoib_ib_dev_stop(struct net_device *dev, int flush)
+int ipoib_ib_dev_stop(struct net_device *dev)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        struct ib_qp_attr qp_attr;
@@ -877,24 +902,7 @@ timeout:
        if (ib_modify_qp(priv->qp, &qp_attr, IB_QP_STATE))
                ipoib_warn(priv, "Failed to modify QP to RESET state\n");
 
-       /* Wait for all AHs to be reaped */
-       set_bit(IPOIB_STOP_REAPER, &priv->flags);
-       cancel_delayed_work(&priv->ah_reap_task);
-       if (flush)
-               flush_workqueue(ipoib_workqueue);
-
-       begin = jiffies;
-
-       while (!list_empty(&priv->dead_ahs)) {
-               __ipoib_reap_ah(dev);
-
-               if (time_after(jiffies, begin + HZ)) {
-                       ipoib_warn(priv, "timing out; will leak address handles\n");
-                       break;
-               }
-
-               msleep(1);
-       }
+       ipoib_flush_ah(dev);
 
        ib_req_notify_cq(priv->recv_cq, IB_CQ_NEXT_COMP);
 
@@ -918,7 +926,7 @@ int ipoib_ib_dev_init(struct net_device *dev, struct ib_device *ca, int port)
                    (unsigned long) dev);
 
        if (dev->flags & IFF_UP) {
-               if (ipoib_ib_dev_open(dev, 1)) {
+               if (ipoib_ib_dev_open(dev)) {
                        ipoib_transport_dev_cleanup(dev);
                        return -ENODEV;
                }
@@ -1037,15 +1045,16 @@ static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv,
        if (level == IPOIB_FLUSH_LIGHT) {
                ipoib_mark_paths_invalid(dev);
                ipoib_mcast_dev_flush(dev);
+               ipoib_flush_ah(dev);
        }
 
        if (level >= IPOIB_FLUSH_NORMAL)
-               ipoib_ib_dev_down(dev, 0);
+               ipoib_ib_dev_down(dev);
 
        if (level == IPOIB_FLUSH_HEAVY) {
                if (test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags))
-                       ipoib_ib_dev_stop(dev, 0);
-               if (ipoib_ib_dev_open(dev, 0) != 0)
+                       ipoib_ib_dev_stop(dev);
+               if (ipoib_ib_dev_open(dev) != 0)
                        return;
                if (netif_queue_stopped(dev))
                        netif_start_queue(dev);
@@ -1097,9 +1106,17 @@ void ipoib_ib_dev_cleanup(struct net_device *dev)
         */
        ipoib_flush_paths(dev);
 
-       ipoib_mcast_stop_thread(dev, 1);
+       ipoib_mcast_stop_thread(dev);
        ipoib_mcast_dev_flush(dev);
 
+       /*
+        * All of our ah references aren't free until after
+        * ipoib_mcast_dev_flush(), ipoib_flush_paths, and
+        * the neighbor garbage collection is stopped and reaped.
+        * That should all be done now, so make a final ah flush.
+        */
+       ipoib_stop_ah(dev);
+
        ipoib_transport_dev_cleanup(dev);
 }
 
index 915ad04a827e860125815cfc50296ea4ce0695b6..9e1b203d756d272dfd4c8066b3f4bf64d681e0d5 100644 (file)
@@ -108,7 +108,7 @@ int ipoib_open(struct net_device *dev)
 
        set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags);
 
-       if (ipoib_ib_dev_open(dev, 1)) {
+       if (ipoib_ib_dev_open(dev)) {
                if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags))
                        return 0;
                goto err_disable;
@@ -139,7 +139,7 @@ int ipoib_open(struct net_device *dev)
        return 0;
 
 err_stop:
-       ipoib_ib_dev_stop(dev, 1);
+       ipoib_ib_dev_stop(dev);
 
 err_disable:
        clear_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags);
@@ -157,8 +157,8 @@ static int ipoib_stop(struct net_device *dev)
 
        netif_stop_queue(dev);
 
-       ipoib_ib_dev_down(dev, 1);
-       ipoib_ib_dev_stop(dev, 0);
+       ipoib_ib_dev_down(dev);
+       ipoib_ib_dev_stop(dev);
 
        if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) {
                struct ipoib_dev_priv *cpriv;
@@ -640,8 +640,10 @@ static void neigh_add_path(struct sk_buff *skb, u8 *daddr,
 
                if (!path->query && path_rec_start(dev, path))
                        goto err_path;
-
-               __skb_queue_tail(&neigh->queue, skb);
+               if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE)
+                       __skb_queue_tail(&neigh->queue, skb);
+               else
+                       goto err_drop;
        }
 
        spin_unlock_irqrestore(&priv->lock, flags);
@@ -676,7 +678,12 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
                        new_path = 1;
                }
                if (path) {
-                       __skb_queue_tail(&path->queue, skb);
+                       if (skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
+                               __skb_queue_tail(&path->queue, skb);
+                       } else {
+                               ++dev->stats.tx_dropped;
+                               dev_kfree_skb_any(skb);
+                       }
 
                        if (!path->query && path_rec_start(dev, path)) {
                                spin_unlock_irqrestore(&priv->lock, flags);
@@ -839,7 +846,7 @@ static void ipoib_set_mcast_list(struct net_device *dev)
                return;
        }
 
-       queue_work(ipoib_workqueue, &priv->restart_task);
+       queue_work(priv->wq, &priv->restart_task);
 }
 
 static int ipoib_get_iflink(const struct net_device *dev)
@@ -966,7 +973,7 @@ static void ipoib_reap_neigh(struct work_struct *work)
        __ipoib_reap_neigh(priv);
 
        if (!test_bit(IPOIB_STOP_NEIGH_GC, &priv->flags))
-               queue_delayed_work(ipoib_workqueue, &priv->neigh_reap_task,
+               queue_delayed_work(priv->wq, &priv->neigh_reap_task,
                                   arp_tbl.gc_interval);
 }
 
@@ -1145,7 +1152,7 @@ static int ipoib_neigh_hash_init(struct ipoib_dev_priv *priv)
 
        /* start garbage collection */
        clear_bit(IPOIB_STOP_NEIGH_GC, &priv->flags);
-       queue_delayed_work(ipoib_workqueue, &priv->neigh_reap_task,
+       queue_delayed_work(priv->wq, &priv->neigh_reap_task,
                           arp_tbl.gc_interval);
 
        return 0;
@@ -1274,15 +1281,13 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
 
-       if (ipoib_neigh_hash_init(priv) < 0)
-               goto out;
        /* Allocate RX/TX "rings" to hold queued skbs */
        priv->rx_ring = kzalloc(ipoib_recvq_size * sizeof *priv->rx_ring,
                                GFP_KERNEL);
        if (!priv->rx_ring) {
                printk(KERN_WARNING "%s: failed to allocate RX ring (%d entries)\n",
                       ca->name, ipoib_recvq_size);
-               goto out_neigh_hash_cleanup;
+               goto out;
        }
 
        priv->tx_ring = vzalloc(ipoib_sendq_size * sizeof *priv->tx_ring);
@@ -1297,16 +1302,24 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port)
        if (ipoib_ib_dev_init(dev, ca, port))
                goto out_tx_ring_cleanup;
 
+       /*
+        * Must be after ipoib_ib_dev_init so we can allocate a per
+        * device wq there and use it here
+        */
+       if (ipoib_neigh_hash_init(priv) < 0)
+               goto out_dev_uninit;
+
        return 0;
 
+out_dev_uninit:
+       ipoib_ib_dev_cleanup(dev);
+
 out_tx_ring_cleanup:
        vfree(priv->tx_ring);
 
 out_rx_ring_cleanup:
        kfree(priv->rx_ring);
 
-out_neigh_hash_cleanup:
-       ipoib_neigh_hash_uninit(dev);
 out:
        return -ENOMEM;
 }
@@ -1329,6 +1342,12 @@ void ipoib_dev_cleanup(struct net_device *dev)
        }
        unregister_netdevice_many(&head);
 
+       /*
+        * Must be before ipoib_ib_dev_cleanup or we delete an in use
+        * work queue
+        */
+       ipoib_neigh_hash_uninit(dev);
+
        ipoib_ib_dev_cleanup(dev);
 
        kfree(priv->rx_ring);
@@ -1336,8 +1355,6 @@ void ipoib_dev_cleanup(struct net_device *dev)
 
        priv->rx_ring = NULL;
        priv->tx_ring = NULL;
-
-       ipoib_neigh_hash_uninit(dev);
 }
 
 static const struct header_ops ipoib_header_ops = {
@@ -1646,10 +1663,11 @@ sysfs_failed:
 
 register_failed:
        ib_unregister_event_handler(&priv->event_handler);
+       flush_workqueue(ipoib_workqueue);
        /* Stop GC if started before flush */
        set_bit(IPOIB_STOP_NEIGH_GC, &priv->flags);
        cancel_delayed_work(&priv->neigh_reap_task);
-       flush_workqueue(ipoib_workqueue);
+       flush_workqueue(priv->wq);
 
 event_failed:
        ipoib_dev_cleanup(priv->dev);
@@ -1712,6 +1730,7 @@ static void ipoib_remove_one(struct ib_device *device)
 
        list_for_each_entry_safe(priv, tmp, dev_list, list) {
                ib_unregister_event_handler(&priv->event_handler);
+               flush_workqueue(ipoib_workqueue);
 
                rtnl_lock();
                dev_change_flags(priv->dev, priv->dev->flags & ~IFF_UP);
@@ -1720,7 +1739,7 @@ static void ipoib_remove_one(struct ib_device *device)
                /* Stop GC */
                set_bit(IPOIB_STOP_NEIGH_GC, &priv->flags);
                cancel_delayed_work(&priv->neigh_reap_task);
-               flush_workqueue(ipoib_workqueue);
+               flush_workqueue(priv->wq);
 
                unregister_netdev(priv->dev);
                free_netdev(priv->dev);
@@ -1755,14 +1774,16 @@ static int __init ipoib_init_module(void)
                return ret;
 
        /*
-        * We create our own workqueue mainly because we want to be
-        * able to flush it when devices are being removed.  We can't
-        * use schedule_work()/flush_scheduled_work() because both
-        * unregister_netdev() and linkwatch_event take the rtnl lock,
-        * so flush_scheduled_work() can deadlock during device
-        * removal.
+        * We create a global workqueue here that is used for all flush
+        * operations.  However, if you attempt to flush a workqueue
+        * from a task on that same workqueue, it deadlocks the system.
+        * We want to be able to flush the tasks associated with a
+        * specific net device, so we also create a workqueue for each
+        * netdevice.  We queue up the tasks for that device only on
+        * its private workqueue, and we only queue up flush events
+        * on our global flush workqueue.  This avoids the deadlocks.
         */
-       ipoib_workqueue = create_singlethread_workqueue("ipoib");
+       ipoib_workqueue = create_singlethread_workqueue("ipoib_flush");
        if (!ipoib_workqueue) {
                ret = -ENOMEM;
                goto err_fs;
index ffb83b5f7e805e411f1506d66a53f8465b90c439..0d23e0568deb6fee19247ddbe43fbaabc477edf4 100644 (file)
@@ -55,8 +55,6 @@ MODULE_PARM_DESC(mcast_debug_level,
                 "Enable multicast debug tracing if > 0");
 #endif
 
-static DEFINE_MUTEX(mcast_mutex);
-
 struct ipoib_mcast_iter {
        struct net_device *dev;
        union ib_gid       mgid;
@@ -66,6 +64,48 @@ struct ipoib_mcast_iter {
        unsigned int       send_only;
 };
 
+/*
+ * This should be called with the priv->lock held
+ */
+static void __ipoib_mcast_schedule_join_thread(struct ipoib_dev_priv *priv,
+                                              struct ipoib_mcast *mcast,
+                                              bool delay)
+{
+       if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
+               return;
+
+       /*
+        * We will be scheduling *something*, so cancel whatever is
+        * currently scheduled first
+        */
+       cancel_delayed_work(&priv->mcast_task);
+       if (mcast && delay) {
+               /*
+                * We had a failure and want to schedule a retry later
+                */
+               mcast->backoff *= 2;
+               if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS)
+                       mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS;
+               mcast->delay_until = jiffies + (mcast->backoff * HZ);
+               /*
+                * Mark this mcast for its delay, but restart the
+                * task immediately.  The join task will make sure to
+                * clear out all entries without delays, and then
+                * schedule itself to run again when the earliest
+                * delay expires
+                */
+               queue_delayed_work(priv->wq, &priv->mcast_task, 0);
+       } else if (delay) {
+               /*
+                * Special case of retrying after a failure to
+                * allocate the broadcast multicast group, wait
+                * 1 second and try again
+                */
+               queue_delayed_work(priv->wq, &priv->mcast_task, HZ);
+       } else
+               queue_delayed_work(priv->wq, &priv->mcast_task, 0);
+}
+
 static void ipoib_mcast_free(struct ipoib_mcast *mcast)
 {
        struct net_device *dev = mcast->dev;
@@ -103,6 +143,7 @@ static struct ipoib_mcast *ipoib_mcast_alloc(struct net_device *dev,
 
        mcast->dev = dev;
        mcast->created = jiffies;
+       mcast->delay_until = jiffies;
        mcast->backoff = 1;
 
        INIT_LIST_HEAD(&mcast->list);
@@ -185,17 +226,27 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
                        spin_unlock_irq(&priv->lock);
                        return -EAGAIN;
                }
-               priv->mcast_mtu = IPOIB_UD_MTU(ib_mtu_enum_to_int(priv->broadcast->mcmember.mtu));
+               /*update priv member according to the new mcast*/
+               priv->broadcast->mcmember.qkey = mcmember->qkey;
+               priv->broadcast->mcmember.mtu = mcmember->mtu;
+               priv->broadcast->mcmember.traffic_class = mcmember->traffic_class;
+               priv->broadcast->mcmember.rate = mcmember->rate;
+               priv->broadcast->mcmember.sl = mcmember->sl;
+               priv->broadcast->mcmember.flow_label = mcmember->flow_label;
+               priv->broadcast->mcmember.hop_limit = mcmember->hop_limit;
+               /* assume if the admin and the mcast are the same both can be changed */
+               if (priv->mcast_mtu == priv->admin_mtu)
+                       priv->admin_mtu =
+                       priv->mcast_mtu =
+                       IPOIB_UD_MTU(ib_mtu_enum_to_int(priv->broadcast->mcmember.mtu));
+               else
+                       priv->mcast_mtu =
+                       IPOIB_UD_MTU(ib_mtu_enum_to_int(priv->broadcast->mcmember.mtu));
+
                priv->qkey = be32_to_cpu(priv->broadcast->mcmember.qkey);
                spin_unlock_irq(&priv->lock);
                priv->tx_wr.wr.ud.remote_qkey = priv->qkey;
                set_qkey = 1;
-
-               if (!ipoib_cm_admin_enabled(dev)) {
-                       rtnl_lock();
-                       dev_set_mtu(dev, min(priv->mcast_mtu, priv->admin_mtu));
-                       rtnl_unlock();
-               }
        }
 
        if (!test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) {
@@ -270,107 +321,35 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
        return 0;
 }
 
-static int
-ipoib_mcast_sendonly_join_complete(int status,
-                                  struct ib_sa_multicast *multicast)
-{
-       struct ipoib_mcast *mcast = multicast->context;
-       struct net_device *dev = mcast->dev;
-
-       /* We trap for port events ourselves. */
-       if (status == -ENETRESET)
-               return 0;
-
-       if (!status)
-               status = ipoib_mcast_join_finish(mcast, &multicast->rec);
-
-       if (status) {
-               if (mcast->logcount++ < 20)
-                       ipoib_dbg_mcast(netdev_priv(dev), "multicast join failed for %pI6, status %d\n",
-                                       mcast->mcmember.mgid.raw, status);
-
-               /* Flush out any queued packets */
-               netif_tx_lock_bh(dev);
-               while (!skb_queue_empty(&mcast->pkt_queue)) {
-                       ++dev->stats.tx_dropped;
-                       dev_kfree_skb_any(skb_dequeue(&mcast->pkt_queue));
-               }
-               netif_tx_unlock_bh(dev);
-
-               /* Clear the busy flag so we try again */
-               status = test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY,
-                                           &mcast->flags);
-       }
-       return status;
-}
-
-static int ipoib_mcast_sendonly_join(struct ipoib_mcast *mcast)
-{
-       struct net_device *dev = mcast->dev;
-       struct ipoib_dev_priv *priv = netdev_priv(dev);
-       struct ib_sa_mcmember_rec rec = {
-#if 0                          /* Some SMs don't support send-only yet */
-               .join_state = 4
-#else
-               .join_state = 1
-#endif
-       };
-       int ret = 0;
-
-       if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) {
-               ipoib_dbg_mcast(priv, "device shutting down, no multicast joins\n");
-               return -ENODEV;
-       }
-
-       if (test_and_set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags)) {
-               ipoib_dbg_mcast(priv, "multicast entry busy, skipping\n");
-               return -EBUSY;
-       }
-
-       rec.mgid     = mcast->mcmember.mgid;
-       rec.port_gid = priv->local_gid;
-       rec.pkey     = cpu_to_be16(priv->pkey);
-
-       mcast->mc = ib_sa_join_multicast(&ipoib_sa_client, priv->ca,
-                                        priv->port, &rec,
-                                        IB_SA_MCMEMBER_REC_MGID        |
-                                        IB_SA_MCMEMBER_REC_PORT_GID    |
-                                        IB_SA_MCMEMBER_REC_PKEY        |
-                                        IB_SA_MCMEMBER_REC_JOIN_STATE,
-                                        GFP_ATOMIC,
-                                        ipoib_mcast_sendonly_join_complete,
-                                        mcast);
-       if (IS_ERR(mcast->mc)) {
-               ret = PTR_ERR(mcast->mc);
-               clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
-               ipoib_warn(priv, "ib_sa_join_multicast failed (ret = %d)\n",
-                          ret);
-       } else {
-               ipoib_dbg_mcast(priv, "no multicast record for %pI6, starting join\n",
-                               mcast->mcmember.mgid.raw);
-       }
-
-       return ret;
-}
-
 void ipoib_mcast_carrier_on_task(struct work_struct *work)
 {
        struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv,
                                                   carrier_on_task);
        struct ib_port_attr attr;
 
-       /*
-        * Take rtnl_lock to avoid racing with ipoib_stop() and
-        * turning the carrier back on while a device is being
-        * removed.
-        */
        if (ib_query_port(priv->ca, priv->port, &attr) ||
            attr.state != IB_PORT_ACTIVE) {
                ipoib_dbg(priv, "Keeping carrier off until IB port is active\n");
                return;
        }
 
-       rtnl_lock();
+       /*
+        * Take rtnl_lock to avoid racing with ipoib_stop() and
+        * turning the carrier back on while a device is being
+        * removed.  However, ipoib_stop() will attempt to flush
+        * the workqueue while holding the rtnl lock, so loop
+        * on trylock until either we get the lock or we see
+        * FLAG_OPER_UP go away as that signals that we are bailing
+        * and can safely ignore the carrier on work.
+        */
+       while (!rtnl_trylock()) {
+               if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
+                       return;
+               else
+                       msleep(20);
+       }
+       if (!ipoib_cm_admin_enabled(priv->dev))
+               dev_set_mtu(priv->dev, min(priv->mcast_mtu, priv->admin_mtu));
        netif_carrier_on(priv->dev);
        rtnl_unlock();
 }
@@ -382,7 +361,9 @@ static int ipoib_mcast_join_complete(int status,
        struct net_device *dev = mcast->dev;
        struct ipoib_dev_priv *priv = netdev_priv(dev);
 
-       ipoib_dbg_mcast(priv, "join completion for %pI6 (status %d)\n",
+       ipoib_dbg_mcast(priv, "%sjoin completion for %pI6 (status %d)\n",
+                       test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags) ?
+                       "sendonly " : "",
                        mcast->mcmember.mgid.raw, status);
 
        /* We trap for port events ourselves. */
@@ -396,49 +377,74 @@ static int ipoib_mcast_join_complete(int status,
 
        if (!status) {
                mcast->backoff = 1;
-               mutex_lock(&mcast_mutex);
-               if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
-                       queue_delayed_work(ipoib_workqueue,
-                                          &priv->mcast_task, 0);
-               mutex_unlock(&mcast_mutex);
+               mcast->delay_until = jiffies;
 
                /*
-                * Defer carrier on work to ipoib_workqueue to avoid a
-                * deadlock on rtnl_lock here.
+                * Defer carrier on work to priv->wq to avoid a
+                * deadlock on rtnl_lock here.  Requeue our multicast
+                * work too, which will end up happening right after
+                * our carrier on task work and will allow us to
+                * send out all of the non-broadcast joins
                 */
-               if (mcast == priv->broadcast)
-                       queue_work(ipoib_workqueue, &priv->carrier_on_task);
-
-               status = 0;
-               goto out;
-       }
+               if (mcast == priv->broadcast) {
+                       spin_lock_irq(&priv->lock);
+                       queue_work(priv->wq, &priv->carrier_on_task);
+                       __ipoib_mcast_schedule_join_thread(priv, NULL, 0);
+                       goto out_locked;
+               }
+       } else {
+               if (mcast->logcount++ < 20) {
+                       if (status == -ETIMEDOUT || status == -EAGAIN) {
+                               ipoib_dbg_mcast(priv, "%smulticast join failed for %pI6, status %d\n",
+                                               test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags) ? "sendonly " : "",
+                                               mcast->mcmember.mgid.raw, status);
+                       } else {
+                               ipoib_warn(priv, "%smulticast join failed for %pI6, status %d\n",
+                                               test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags) ? "sendonly " : "",
+                                          mcast->mcmember.mgid.raw, status);
+                       }
+               }
 
-       if (mcast->logcount++ < 20) {
-               if (status == -ETIMEDOUT || status == -EAGAIN) {
-                       ipoib_dbg_mcast(priv, "multicast join failed for %pI6, status %d\n",
-                                       mcast->mcmember.mgid.raw, status);
+               if (test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags) &&
+                   mcast->backoff >= 2) {
+                       /*
+                        * We only retry sendonly joins once before we drop
+                        * the packet and quit trying to deal with the
+                        * group.  However, we leave the group in the
+                        * mcast list as an unjoined group.  If we want to
+                        * try joining again, we simply queue up a packet
+                        * and restart the join thread.  The empty queue
+                        * is why the join thread ignores this group.
+                        */
+                       mcast->backoff = 1;
+                       netif_tx_lock_bh(dev);
+                       while (!skb_queue_empty(&mcast->pkt_queue)) {
+                               ++dev->stats.tx_dropped;
+                               dev_kfree_skb_any(skb_dequeue(&mcast->pkt_queue));
+                       }
+                       netif_tx_unlock_bh(dev);
                } else {
-                       ipoib_warn(priv, "multicast join failed for %pI6, status %d\n",
-                                  mcast->mcmember.mgid.raw, status);
+                       spin_lock_irq(&priv->lock);
+                       /* Requeue this join task with a backoff delay */
+                       __ipoib_mcast_schedule_join_thread(priv, mcast, 1);
+                       goto out_locked;
                }
        }
-
-       mcast->backoff *= 2;
-       if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS)
-               mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS;
-
-       /* Clear the busy flag so we try again */
-       status = test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
-
-       mutex_lock(&mcast_mutex);
+out:
        spin_lock_irq(&priv->lock);
-       if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
-               queue_delayed_work(ipoib_workqueue, &priv->mcast_task,
-                                  mcast->backoff * HZ);
+out_locked:
+       /*
+        * Make sure to set mcast->mc before we clear the busy flag to avoid
+        * racing with code that checks for BUSY before checking mcast->mc
+        */
+       if (status)
+               mcast->mc = NULL;
+       else
+               mcast->mc = multicast;
+       clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
        spin_unlock_irq(&priv->lock);
-       mutex_unlock(&mcast_mutex);
-out:
        complete(&mcast->done);
+
        return status;
 }
 
@@ -446,6 +452,7 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast,
                             int create)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
+       struct ib_sa_multicast *multicast;
        struct ib_sa_mcmember_rec rec = {
                .join_state = 1
        };
@@ -487,29 +494,18 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast,
                rec.hop_limit     = priv->broadcast->mcmember.hop_limit;
        }
 
-       set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
-       init_completion(&mcast->done);
-       set_bit(IPOIB_MCAST_JOIN_STARTED, &mcast->flags);
-
-       mcast->mc = ib_sa_join_multicast(&ipoib_sa_client, priv->ca, priv->port,
+       multicast = ib_sa_join_multicast(&ipoib_sa_client, priv->ca, priv->port,
                                         &rec, comp_mask, GFP_KERNEL,
                                         ipoib_mcast_join_complete, mcast);
-       if (IS_ERR(mcast->mc)) {
+       if (IS_ERR(multicast)) {
+               ret = PTR_ERR(multicast);
+               ipoib_warn(priv, "ib_sa_join_multicast failed, status %d\n", ret);
+               spin_lock_irq(&priv->lock);
+               /* Requeue this join task with a backoff delay */
+               __ipoib_mcast_schedule_join_thread(priv, mcast, 1);
                clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
+               spin_unlock_irq(&priv->lock);
                complete(&mcast->done);
-               ret = PTR_ERR(mcast->mc);
-               ipoib_warn(priv, "ib_sa_join_multicast failed, status %d\n", ret);
-
-               mcast->backoff *= 2;
-               if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS)
-                       mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS;
-
-               mutex_lock(&mcast_mutex);
-               if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
-                       queue_delayed_work(ipoib_workqueue,
-                                          &priv->mcast_task,
-                                          mcast->backoff * HZ);
-               mutex_unlock(&mcast_mutex);
        }
 }
 
@@ -519,8 +515,11 @@ void ipoib_mcast_join_task(struct work_struct *work)
                container_of(work, struct ipoib_dev_priv, mcast_task.work);
        struct net_device *dev = priv->dev;
        struct ib_port_attr port_attr;
+       unsigned long delay_until = 0;
+       struct ipoib_mcast *mcast = NULL;
+       int create = 1;
 
-       if (!test_bit(IPOIB_MCAST_RUN, &priv->flags))
+       if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
                return;
 
        if (ib_query_port(priv->ca, priv->port, &port_attr) ||
@@ -536,93 +535,118 @@ void ipoib_mcast_join_task(struct work_struct *work)
        else
                memcpy(priv->dev->dev_addr + 4, priv->local_gid.raw, sizeof (union ib_gid));
 
+       spin_lock_irq(&priv->lock);
+       if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
+               goto out;
+
        if (!priv->broadcast) {
                struct ipoib_mcast *broadcast;
 
-               if (!test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags))
-                       return;
-
-               broadcast = ipoib_mcast_alloc(dev, 1);
+               broadcast = ipoib_mcast_alloc(dev, 0);
                if (!broadcast) {
                        ipoib_warn(priv, "failed to allocate broadcast group\n");
-                       mutex_lock(&mcast_mutex);
-                       if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
-                               queue_delayed_work(ipoib_workqueue,
-                                                  &priv->mcast_task, HZ);
-                       mutex_unlock(&mcast_mutex);
-                       return;
+                       /*
+                        * Restart us after a 1 second delay to retry
+                        * creating our broadcast group and attaching to
+                        * it.  Until this succeeds, this ipoib dev is
+                        * completely stalled (multicast wise).
+                        */
+                       __ipoib_mcast_schedule_join_thread(priv, NULL, 1);
+                       goto out;
                }
 
-               spin_lock_irq(&priv->lock);
                memcpy(broadcast->mcmember.mgid.raw, priv->dev->broadcast + 4,
                       sizeof (union ib_gid));
                priv->broadcast = broadcast;
 
                __ipoib_mcast_add(dev, priv->broadcast);
-               spin_unlock_irq(&priv->lock);
        }
 
        if (!test_bit(IPOIB_MCAST_FLAG_ATTACHED, &priv->broadcast->flags)) {
-               if (!test_bit(IPOIB_MCAST_FLAG_BUSY, &priv->broadcast->flags))
-                       ipoib_mcast_join(dev, priv->broadcast, 0);
-               return;
-       }
-
-       while (1) {
-               struct ipoib_mcast *mcast = NULL;
-
-               spin_lock_irq(&priv->lock);
-               list_for_each_entry(mcast, &priv->multicast_list, list) {
-                       if (!test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)
-                           && !test_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags)
-                           && !test_bit(IPOIB_MCAST_FLAG_ATTACHED, &mcast->flags)) {
-                               /* Found the next unjoined group */
-                               break;
+               if (IS_ERR_OR_NULL(priv->broadcast->mc) &&
+                   !test_bit(IPOIB_MCAST_FLAG_BUSY, &priv->broadcast->flags)) {
+                       mcast = priv->broadcast;
+                       create = 0;
+                       if (mcast->backoff > 1 &&
+                           time_before(jiffies, mcast->delay_until)) {
+                               delay_until = mcast->delay_until;
+                               mcast = NULL;
                        }
                }
-               spin_unlock_irq(&priv->lock);
+               goto out;
+       }
 
-               if (&mcast->list == &priv->multicast_list) {
-                       /* All done */
-                       break;
+       /*
+        * We'll never get here until the broadcast group is both allocated
+        * and attached
+        */
+       list_for_each_entry(mcast, &priv->multicast_list, list) {
+               if (IS_ERR_OR_NULL(mcast->mc) &&
+                   !test_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags) &&
+                   (!test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags) ||
+                    !skb_queue_empty(&mcast->pkt_queue))) {
+                       if (mcast->backoff == 1 ||
+                           time_after_eq(jiffies, mcast->delay_until)) {
+                               /* Found the next unjoined group */
+                               init_completion(&mcast->done);
+                               set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
+                               if (test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags))
+                                       create = 0;
+                               else
+                                       create = 1;
+                               spin_unlock_irq(&priv->lock);
+                               ipoib_mcast_join(dev, mcast, create);
+                               spin_lock_irq(&priv->lock);
+                       } else if (!delay_until ||
+                                time_before(mcast->delay_until, delay_until))
+                               delay_until = mcast->delay_until;
                }
-
-               ipoib_mcast_join(dev, mcast, 1);
-               return;
        }
 
-       ipoib_dbg_mcast(priv, "successfully joined all multicast groups\n");
+       mcast = NULL;
+       ipoib_dbg_mcast(priv, "successfully started all multicast joins\n");
 
-       clear_bit(IPOIB_MCAST_RUN, &priv->flags);
+out:
+       if (delay_until) {
+               cancel_delayed_work(&priv->mcast_task);
+               queue_delayed_work(priv->wq, &priv->mcast_task,
+                                  delay_until - jiffies);
+       }
+       if (mcast) {
+               init_completion(&mcast->done);
+               set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
+       }
+       spin_unlock_irq(&priv->lock);
+       if (mcast)
+               ipoib_mcast_join(dev, mcast, create);
 }
 
 int ipoib_mcast_start_thread(struct net_device *dev)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
+       unsigned long flags;
 
        ipoib_dbg_mcast(priv, "starting multicast thread\n");
 
-       mutex_lock(&mcast_mutex);
-       if (!test_and_set_bit(IPOIB_MCAST_RUN, &priv->flags))
-               queue_delayed_work(ipoib_workqueue, &priv->mcast_task, 0);
-       mutex_unlock(&mcast_mutex);
+       spin_lock_irqsave(&priv->lock, flags);
+       __ipoib_mcast_schedule_join_thread(priv, NULL, 0);
+       spin_unlock_irqrestore(&priv->lock, flags);
 
        return 0;
 }
 
-int ipoib_mcast_stop_thread(struct net_device *dev, int flush)
+int ipoib_mcast_stop_thread(struct net_device *dev)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
+       unsigned long flags;
 
        ipoib_dbg_mcast(priv, "stopping multicast thread\n");
 
-       mutex_lock(&mcast_mutex);
-       clear_bit(IPOIB_MCAST_RUN, &priv->flags);
+       spin_lock_irqsave(&priv->lock, flags);
        cancel_delayed_work(&priv->mcast_task);
-       mutex_unlock(&mcast_mutex);
+       spin_unlock_irqrestore(&priv->lock, flags);
 
-       if (flush)
-               flush_workqueue(ipoib_workqueue);
+       flush_workqueue(priv->wq);
 
        return 0;
 }
@@ -633,6 +657,9 @@ static int ipoib_mcast_leave(struct net_device *dev, struct ipoib_mcast *mcast)
        int ret = 0;
 
        if (test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags))
+               ipoib_warn(priv, "ipoib_mcast_leave on an in-flight join\n");
+
+       if (!IS_ERR_OR_NULL(mcast->mc))
                ib_sa_free_multicast(mcast->mc);
 
        if (test_and_clear_bit(IPOIB_MCAST_FLAG_ATTACHED, &mcast->flags)) {
@@ -644,7 +671,9 @@ static int ipoib_mcast_leave(struct net_device *dev, struct ipoib_mcast *mcast)
                                      be16_to_cpu(mcast->mcmember.mlid));
                if (ret)
                        ipoib_warn(priv, "ib_detach_mcast failed (result = %d)\n", ret);
-       }
+       } else if (!test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags))
+               ipoib_dbg(priv, "leaving with no mcmember but not a "
+                         "SENDONLY join\n");
 
        return 0;
 }
@@ -667,49 +696,37 @@ void ipoib_mcast_send(struct net_device *dev, u8 *daddr, struct sk_buff *skb)
        }
 
        mcast = __ipoib_mcast_find(dev, mgid);
-       if (!mcast) {
-               /* Let's create a new send only group now */
-               ipoib_dbg_mcast(priv, "setting up send only multicast group for %pI6\n",
-                               mgid);
-
-               mcast = ipoib_mcast_alloc(dev, 0);
+       if (!mcast || !mcast->ah) {
                if (!mcast) {
-                       ipoib_warn(priv, "unable to allocate memory for "
-                                  "multicast structure\n");
-                       ++dev->stats.tx_dropped;
-                       dev_kfree_skb_any(skb);
-                       goto out;
-               }
-
-               set_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags);
-               memcpy(mcast->mcmember.mgid.raw, mgid, sizeof (union ib_gid));
-               __ipoib_mcast_add(dev, mcast);
-               list_add_tail(&mcast->list, &priv->multicast_list);
-       }
+                       /* Let's create a new send only group now */
+                       ipoib_dbg_mcast(priv, "setting up send only multicast group for %pI6\n",
+                                       mgid);
+
+                       mcast = ipoib_mcast_alloc(dev, 0);
+                       if (!mcast) {
+                               ipoib_warn(priv, "unable to allocate memory "
+                                          "for multicast structure\n");
+                               ++dev->stats.tx_dropped;
+                               dev_kfree_skb_any(skb);
+                               goto unlock;
+                       }
 
-       if (!mcast->ah) {
+                       set_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags);
+                       memcpy(mcast->mcmember.mgid.raw, mgid,
+                              sizeof (union ib_gid));
+                       __ipoib_mcast_add(dev, mcast);
+                       list_add_tail(&mcast->list, &priv->multicast_list);
+               }
                if (skb_queue_len(&mcast->pkt_queue) < IPOIB_MAX_MCAST_QUEUE)
                        skb_queue_tail(&mcast->pkt_queue, skb);
                else {
                        ++dev->stats.tx_dropped;
                        dev_kfree_skb_any(skb);
                }
-
-               if (test_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags))
-                       ipoib_dbg_mcast(priv, "no address vector, "
-                                       "but multicast join already started\n");
-               else if (test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags))
-                       ipoib_mcast_sendonly_join(mcast);
-
-               /*
-                * If lookup completes between here and out:, don't
-                * want to send packet twice.
-                */
-               mcast = NULL;
-       }
-
-out:
-       if (mcast && mcast->ah) {
+               if (!test_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags)) {
+                       __ipoib_mcast_schedule_join_thread(priv, NULL, 0);
+               }
+       } else {
                struct ipoib_neigh *neigh;
 
                spin_unlock_irqrestore(&priv->lock, flags);
@@ -759,9 +776,12 @@ void ipoib_mcast_dev_flush(struct net_device *dev)
 
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       /* seperate between the wait to the leave*/
+       /*
+        * make sure the in-flight joins have finished before we attempt
+        * to leave
+        */
        list_for_each_entry_safe(mcast, tmcast, &remove_list, list)
-               if (test_bit(IPOIB_MCAST_JOIN_STARTED, &mcast->flags))
+               if (test_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags))
                        wait_for_completion(&mcast->done);
 
        list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
@@ -792,9 +812,14 @@ void ipoib_mcast_restart_task(struct work_struct *work)
        unsigned long flags;
        struct ib_sa_mcmember_rec rec;
 
-       ipoib_dbg_mcast(priv, "restarting multicast task\n");
+       if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
+               /*
+                * shortcut...on shutdown flush is called next, just
+                * let it do all the work
+                */
+               return;
 
-       ipoib_mcast_stop_thread(dev, 0);
+       ipoib_dbg_mcast(priv, "restarting multicast task\n");
 
        local_irq_save(flags);
        netif_addr_lock(dev);
@@ -880,14 +905,27 @@ void ipoib_mcast_restart_task(struct work_struct *work)
        netif_addr_unlock(dev);
        local_irq_restore(flags);
 
-       /* We have to cancel outside of the spinlock */
+       /*
+        * make sure the in-flight joins have finished before we attempt
+        * to leave
+        */
+       list_for_each_entry_safe(mcast, tmcast, &remove_list, list)
+               if (test_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags))
+                       wait_for_completion(&mcast->done);
+
        list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
                ipoib_mcast_leave(mcast->dev, mcast);
                ipoib_mcast_free(mcast);
        }
 
-       if (test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags))
-               ipoib_mcast_start_thread(dev);
+       /*
+        * Double check that we are still up
+        */
+       if (test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) {
+               spin_lock_irqsave(&priv->lock, flags);
+               __ipoib_mcast_schedule_join_thread(priv, NULL, 0);
+               spin_unlock_irqrestore(&priv->lock, flags);
+       }
 }
 
 #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
index c56d5d44c53b3f11725b6d6da220ea2c440fe496..e5cc43074196dbab1ae216cb43135f7e5f081c66 100644 (file)
@@ -157,6 +157,16 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
                goto out_free_pd;
        }
 
+       /*
+        * the various IPoIB tasks assume they will never race against
+        * themselves, so always use a single thread workqueue
+        */
+       priv->wq = create_singlethread_workqueue("ipoib_wq");
+       if (!priv->wq) {
+               printk(KERN_WARNING "ipoib: failed to allocate device WQ\n");
+               goto out_free_mr;
+       }
+
        size = ipoib_recvq_size + 1;
        ret = ipoib_cm_dev_init(dev);
        if (!ret) {
@@ -165,12 +175,13 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
                        size += ipoib_recvq_size + 1; /* 1 extra for rx_drain_qp */
                else
                        size += ipoib_recvq_size * ipoib_max_conn_qp;
-       }
+       } else
+               goto out_free_wq;
 
        priv->recv_cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL, dev, size, 0);
        if (IS_ERR(priv->recv_cq)) {
                printk(KERN_WARNING "%s: failed to create receive CQ\n", ca->name);
-               goto out_free_mr;
+               goto out_cm_dev_cleanup;
        }
 
        priv->send_cq = ib_create_cq(priv->ca, ipoib_send_comp_handler, NULL,
@@ -216,15 +227,10 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
        priv->tx_wr.send_flags  = IB_SEND_SIGNALED;
 
        priv->rx_sge[0].lkey = priv->mr->lkey;
-       if (ipoib_ud_need_sg(priv->max_ib_mtu)) {
-               priv->rx_sge[0].length = IPOIB_UD_HEAD_SIZE;
-               priv->rx_sge[1].length = PAGE_SIZE;
-               priv->rx_sge[1].lkey = priv->mr->lkey;
-               priv->rx_wr.num_sge = IPOIB_UD_RX_SG;
-       } else {
-               priv->rx_sge[0].length = IPOIB_UD_BUF_SIZE(priv->max_ib_mtu);
-               priv->rx_wr.num_sge = 1;
-       }
+
+       priv->rx_sge[0].length = IPOIB_UD_BUF_SIZE(priv->max_ib_mtu);
+       priv->rx_wr.num_sge = 1;
+
        priv->rx_wr.next = NULL;
        priv->rx_wr.sg_list = priv->rx_sge;
 
@@ -236,12 +242,19 @@ out_free_send_cq:
 out_free_recv_cq:
        ib_destroy_cq(priv->recv_cq);
 
+out_cm_dev_cleanup:
+       ipoib_cm_dev_cleanup(dev);
+
+out_free_wq:
+       destroy_workqueue(priv->wq);
+       priv->wq = NULL;
+
 out_free_mr:
        ib_dereg_mr(priv->mr);
-       ipoib_cm_dev_cleanup(dev);
 
 out_free_pd:
        ib_dealloc_pd(priv->pd);
+
        return -ENODEV;
 }
 
@@ -265,11 +278,18 @@ void ipoib_transport_dev_cleanup(struct net_device *dev)
 
        ipoib_cm_dev_cleanup(dev);
 
+       if (priv->wq) {
+               flush_workqueue(priv->wq);
+               destroy_workqueue(priv->wq);
+               priv->wq = NULL;
+       }
+
        if (ib_dereg_mr(priv->mr))
                ipoib_warn(priv, "ib_dereg_mr failed\n");
 
        if (ib_dealloc_pd(priv->pd))
                ipoib_warn(priv, "ib_dealloc_pd failed\n");
+
 }
 
 void ipoib_event(struct ib_event_handler *handler,
index b47aea1094b2d9f7e434cf8a442f4b83b1a28f3c..262ba1f8ee507d30111b98b7970b5bbc86e051c6 100644 (file)
@@ -69,7 +69,7 @@
 
 #define DRV_NAME       "iser"
 #define PFX            DRV_NAME ": "
-#define DRV_VER                "1.5"
+#define DRV_VER                "1.6"
 
 #define iser_dbg(fmt, arg...)                           \
        do {                                             \
@@ -218,22 +218,21 @@ enum iser_data_dir {
 /**
  * struct iser_data_buf - iSER data buffer
  *
- * @buf:          pointer to the sg list
+ * @sg:           pointer to the sg list
  * @size:         num entries of this sg
  * @data_len:     total beffer byte len
  * @dma_nents:    returned by dma_map_sg
- * @copy_buf:     allocated copy buf for SGs unaligned
- *                for rdma which are copied
- * @sg_single:    SG-ified clone of a non SG SC or
- *                unaligned SG
+ * @orig_sg:      pointer to the original sg list (in case
+ *                we used a copy)
+ * @orig_size:    num entris of orig sg list
  */
 struct iser_data_buf {
-       void               *buf;
+       struct scatterlist *sg;
        unsigned int       size;
        unsigned long      data_len;
        unsigned int       dma_nents;
-       char               *copy_buf;
-       struct scatterlist sg_single;
+       struct scatterlist *orig_sg;
+       unsigned int       orig_size;
   };
 
 /* fwd declarations */
@@ -244,35 +243,14 @@ struct iscsi_endpoint;
 /**
  * struct iser_mem_reg - iSER memory registration info
  *
- * @lkey:         MR local key
- * @rkey:         MR remote key
- * @va:           MR start address (buffer va)
- * @len:          MR length
+ * @sge:          memory region sg element
+ * @rkey:         memory region remote key
  * @mem_h:        pointer to registration context (FMR/Fastreg)
  */
 struct iser_mem_reg {
-       u32  lkey;
-       u32  rkey;
-       u64  va;
-       u64  len;
-       void *mem_h;
-};
-
-/**
- * struct iser_regd_buf - iSER buffer registration desc
- *
- * @reg:          memory registration info
- * @virt_addr:    virtual address of buffer
- * @device:       reference to iser device
- * @direction:    dma direction (for dma_unmap)
- * @data_size:    data buffer size in bytes
- */
-struct iser_regd_buf {
-       struct iser_mem_reg     reg;
-       void                    *virt_addr;
-       struct iser_device      *device;
-       enum dma_data_direction direction;
-       unsigned int            data_size;
+       struct ib_sge    sge;
+       u32              rkey;
+       void            *mem_h;
 };
 
 enum iser_desc_type {
@@ -534,11 +512,9 @@ struct iser_conn {
  * @sc:               link to scsi command
  * @command_sent:     indicate if command was sent
  * @dir:              iser data direction
- * @rdma_regd:        task rdma registration desc
+ * @rdma_reg        task rdma registration desc
  * @data:             iser data buffer desc
- * @data_copy:        iser data copy buffer desc (bounce buffer)
  * @prot:             iser protection buffer desc
- * @prot_copy:        iser protection copy buffer desc (bounce buffer)
  */
 struct iscsi_iser_task {
        struct iser_tx_desc          desc;
@@ -547,11 +523,9 @@ struct iscsi_iser_task {
        struct scsi_cmnd             *sc;
        int                          command_sent;
        int                          dir[ISER_DIRS_NUM];
-       struct iser_regd_buf         rdma_regd[ISER_DIRS_NUM];
+       struct iser_mem_reg          rdma_reg[ISER_DIRS_NUM];
        struct iser_data_buf         data[ISER_DIRS_NUM];
-       struct iser_data_buf         data_copy[ISER_DIRS_NUM];
        struct iser_data_buf         prot[ISER_DIRS_NUM];
-       struct iser_data_buf         prot_copy[ISER_DIRS_NUM];
 };
 
 struct iser_page_vec {
@@ -621,7 +595,6 @@ void iser_free_rx_descriptors(struct iser_conn *iser_conn);
 
 void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_task *iser_task,
                                     struct iser_data_buf *mem,
-                                    struct iser_data_buf *mem_copy,
                                     enum iser_data_dir cmd_dir);
 
 int  iser_reg_rdma_mem_fmr(struct iscsi_iser_task *task,
@@ -634,10 +607,6 @@ int  iser_connect(struct iser_conn *iser_conn,
                  struct sockaddr *dst_addr,
                  int non_blocking);
 
-int  iser_reg_page_vec(struct ib_conn *ib_conn,
-                      struct iser_page_vec *page_vec,
-                      struct iser_mem_reg *mem_reg);
-
 void iser_unreg_mem_fmr(struct iscsi_iser_task *iser_task,
                        enum iser_data_dir cmd_dir);
 void iser_unreg_mem_fastreg(struct iscsi_iser_task *iser_task,
@@ -667,4 +636,9 @@ int iser_create_fastreg_pool(struct ib_conn *ib_conn, unsigned cmds_max);
 void iser_free_fastreg_pool(struct ib_conn *ib_conn);
 u8 iser_check_task_pi_status(struct iscsi_iser_task *iser_task,
                             enum iser_data_dir cmd_dir, sector_t *sector);
+struct fast_reg_descriptor *
+iser_reg_desc_get(struct ib_conn *ib_conn);
+void
+iser_reg_desc_put(struct ib_conn *ib_conn,
+                 struct fast_reg_descriptor *desc);
 #endif
index 20e859a6f1a63b2fede51dcb2b02b9b6f638a36e..3e2118e8ed8798e4c7946d980ce0351e31088f34 100644 (file)
@@ -50,7 +50,7 @@ static int iser_prepare_read_cmd(struct iscsi_task *task)
 {
        struct iscsi_iser_task *iser_task = task->dd_data;
        struct iser_device  *device = iser_task->iser_conn->ib_conn.device;
-       struct iser_regd_buf *regd_buf;
+       struct iser_mem_reg *mem_reg;
        int err;
        struct iser_hdr *hdr = &iser_task->desc.iser_header;
        struct iser_data_buf *buf_in = &iser_task->data[ISER_DIR_IN];
@@ -78,15 +78,15 @@ static int iser_prepare_read_cmd(struct iscsi_task *task)
                iser_err("Failed to set up Data-IN RDMA\n");
                return err;
        }
-       regd_buf = &iser_task->rdma_regd[ISER_DIR_IN];
+       mem_reg = &iser_task->rdma_reg[ISER_DIR_IN];
 
        hdr->flags    |= ISER_RSV;
-       hdr->read_stag = cpu_to_be32(regd_buf->reg.rkey);
-       hdr->read_va   = cpu_to_be64(regd_buf->reg.va);
+       hdr->read_stag = cpu_to_be32(mem_reg->rkey);
+       hdr->read_va   = cpu_to_be64(mem_reg->sge.addr);
 
        iser_dbg("Cmd itt:%d READ tags RKEY:%#.4X VA:%#llX\n",
-                task->itt, regd_buf->reg.rkey,
-                (unsigned long long)regd_buf->reg.va);
+                task->itt, mem_reg->rkey,
+                (unsigned long long)mem_reg->sge.addr);
 
        return 0;
 }
@@ -104,7 +104,7 @@ iser_prepare_write_cmd(struct iscsi_task *task,
 {
        struct iscsi_iser_task *iser_task = task->dd_data;
        struct iser_device  *device = iser_task->iser_conn->ib_conn.device;
-       struct iser_regd_buf *regd_buf;
+       struct iser_mem_reg *mem_reg;
        int err;
        struct iser_hdr *hdr = &iser_task->desc.iser_header;
        struct iser_data_buf *buf_out = &iser_task->data[ISER_DIR_OUT];
@@ -134,25 +134,25 @@ iser_prepare_write_cmd(struct iscsi_task *task,
                return err;
        }
 
-       regd_buf = &iser_task->rdma_regd[ISER_DIR_OUT];
+       mem_reg = &iser_task->rdma_reg[ISER_DIR_OUT];
 
        if (unsol_sz < edtl) {
                hdr->flags     |= ISER_WSV;
-               hdr->write_stag = cpu_to_be32(regd_buf->reg.rkey);
-               hdr->write_va   = cpu_to_be64(regd_buf->reg.va + unsol_sz);
+               hdr->write_stag = cpu_to_be32(mem_reg->rkey);
+               hdr->write_va   = cpu_to_be64(mem_reg->sge.addr + unsol_sz);
 
                iser_dbg("Cmd itt:%d, WRITE tags, RKEY:%#.4X "
                         "VA:%#llX + unsol:%d\n",
-                        task->itt, regd_buf->reg.rkey,
-                        (unsigned long long)regd_buf->reg.va, unsol_sz);
+                        task->itt, mem_reg->rkey,
+                        (unsigned long long)mem_reg->sge.addr, unsol_sz);
        }
 
        if (imm_sz > 0) {
                iser_dbg("Cmd itt:%d, WRITE, adding imm.data sz: %d\n",
                         task->itt, imm_sz);
-               tx_dsg->addr   = regd_buf->reg.va;
+               tx_dsg->addr = mem_reg->sge.addr;
                tx_dsg->length = imm_sz;
-               tx_dsg->lkey   = regd_buf->reg.lkey;
+               tx_dsg->lkey = mem_reg->sge.lkey;
                iser_task->desc.num_sge = 2;
        }
 
@@ -401,16 +401,16 @@ int iser_send_command(struct iscsi_conn *conn,
        }
 
        if (scsi_sg_count(sc)) { /* using a scatter list */
-               data_buf->buf  = scsi_sglist(sc);
+               data_buf->sg = scsi_sglist(sc);
                data_buf->size = scsi_sg_count(sc);
        }
        data_buf->data_len = scsi_bufflen(sc);
 
        if (scsi_prot_sg_count(sc)) {
-               prot_buf->buf  = scsi_prot_sglist(sc);
+               prot_buf->sg  = scsi_prot_sglist(sc);
                prot_buf->size = scsi_prot_sg_count(sc);
-               prot_buf->data_len = data_buf->data_len >>
-                                    ilog2(sc->device->sector_size) * 8;
+               prot_buf->data_len = (data_buf->data_len >>
+                                    ilog2(sc->device->sector_size)) * 8;
        }
 
        if (hdr->flags & ISCSI_FLAG_CMD_READ) {
@@ -450,7 +450,7 @@ int iser_send_data_out(struct iscsi_conn *conn,
        struct iser_conn *iser_conn = conn->dd_data;
        struct iscsi_iser_task *iser_task = task->dd_data;
        struct iser_tx_desc *tx_desc = NULL;
-       struct iser_regd_buf *regd_buf;
+       struct iser_mem_reg *mem_reg;
        unsigned long buf_offset;
        unsigned long data_seg_len;
        uint32_t itt;
@@ -477,11 +477,11 @@ int iser_send_data_out(struct iscsi_conn *conn,
        /* build the tx desc */
        iser_initialize_task_headers(task, tx_desc);
 
-       regd_buf = &iser_task->rdma_regd[ISER_DIR_OUT];
+       mem_reg = &iser_task->rdma_reg[ISER_DIR_OUT];
        tx_dsg = &tx_desc->tx_sg[1];
-       tx_dsg->addr    = regd_buf->reg.va + buf_offset;
-       tx_dsg->length  = data_seg_len;
-       tx_dsg->lkey    = regd_buf->reg.lkey;
+       tx_dsg->addr = mem_reg->sge.addr + buf_offset;
+       tx_dsg->length = data_seg_len;
+       tx_dsg->lkey = mem_reg->sge.lkey;
        tx_desc->num_sge = 2;
 
        if (buf_offset + data_seg_len > iser_task->data[ISER_DIR_OUT].data_len) {
@@ -658,10 +658,10 @@ void iser_task_rdma_init(struct iscsi_iser_task *iser_task)
        iser_task->prot[ISER_DIR_IN].data_len  = 0;
        iser_task->prot[ISER_DIR_OUT].data_len = 0;
 
-       memset(&iser_task->rdma_regd[ISER_DIR_IN], 0,
-              sizeof(struct iser_regd_buf));
-       memset(&iser_task->rdma_regd[ISER_DIR_OUT], 0,
-              sizeof(struct iser_regd_buf));
+       memset(&iser_task->rdma_reg[ISER_DIR_IN], 0,
+              sizeof(struct iser_mem_reg));
+       memset(&iser_task->rdma_reg[ISER_DIR_OUT], 0,
+              sizeof(struct iser_mem_reg));
 }
 
 void iser_task_rdma_finalize(struct iscsi_iser_task *iser_task)
@@ -674,35 +674,31 @@ void iser_task_rdma_finalize(struct iscsi_iser_task *iser_task)
        /* if we were reading, copy back to unaligned sglist,
         * anyway dma_unmap and free the copy
         */
-       if (iser_task->data_copy[ISER_DIR_IN].copy_buf != NULL) {
+       if (iser_task->data[ISER_DIR_IN].orig_sg) {
                is_rdma_data_aligned = 0;
                iser_finalize_rdma_unaligned_sg(iser_task,
                                                &iser_task->data[ISER_DIR_IN],
-                                               &iser_task->data_copy[ISER_DIR_IN],
                                                ISER_DIR_IN);
        }
 
-       if (iser_task->data_copy[ISER_DIR_OUT].copy_buf != NULL) {
+       if (iser_task->data[ISER_DIR_OUT].orig_sg) {
                is_rdma_data_aligned = 0;
                iser_finalize_rdma_unaligned_sg(iser_task,
                                                &iser_task->data[ISER_DIR_OUT],
-                                               &iser_task->data_copy[ISER_DIR_OUT],
                                                ISER_DIR_OUT);
        }
 
-       if (iser_task->prot_copy[ISER_DIR_IN].copy_buf != NULL) {
+       if (iser_task->prot[ISER_DIR_IN].orig_sg) {
                is_rdma_prot_aligned = 0;
                iser_finalize_rdma_unaligned_sg(iser_task,
                                                &iser_task->prot[ISER_DIR_IN],
-                                               &iser_task->prot_copy[ISER_DIR_IN],
                                                ISER_DIR_IN);
        }
 
-       if (iser_task->prot_copy[ISER_DIR_OUT].copy_buf != NULL) {
+       if (iser_task->prot[ISER_DIR_OUT].orig_sg) {
                is_rdma_prot_aligned = 0;
                iser_finalize_rdma_unaligned_sg(iser_task,
                                                &iser_task->prot[ISER_DIR_OUT],
-                                               &iser_task->prot_copy[ISER_DIR_OUT],
                                                ISER_DIR_OUT);
        }
 
index 341040bf09849d41e4e01c613e0d0e01683fceda..f0cdc961eb11b92dd5a80930dab123a7587c8f2c 100644 (file)
 
 #include "iscsi_iser.h"
 
-#define ISER_KMALLOC_THRESHOLD 0x20000 /* 128K - kmalloc limit */
+static void
+iser_free_bounce_sg(struct iser_data_buf *data)
+{
+       struct scatterlist *sg;
+       int count;
 
-/**
- * iser_start_rdma_unaligned_sg
- */
-static int iser_start_rdma_unaligned_sg(struct iscsi_iser_task *iser_task,
-                                       struct iser_data_buf *data,
-                                       struct iser_data_buf *data_copy,
-                                       enum iser_data_dir cmd_dir)
+       for_each_sg(data->sg, sg, data->size, count)
+               __free_page(sg_page(sg));
+
+       kfree(data->sg);
+
+       data->sg = data->orig_sg;
+       data->size = data->orig_size;
+       data->orig_sg = NULL;
+       data->orig_size = 0;
+}
+
+static int
+iser_alloc_bounce_sg(struct iser_data_buf *data)
 {
-       struct ib_device *dev = iser_task->iser_conn->ib_conn.device->ib_device;
-       struct scatterlist *sgl = (struct scatterlist *)data->buf;
        struct scatterlist *sg;
-       char *mem = NULL;
-       unsigned long  cmd_data_len = 0;
-       int dma_nents, i;
+       struct page *page;
+       unsigned long length = data->data_len;
+       int i = 0, nents = DIV_ROUND_UP(length, PAGE_SIZE);
 
-       for_each_sg(sgl, sg, data->size, i)
-               cmd_data_len += ib_sg_dma_len(dev, sg);
+       sg = kcalloc(nents, sizeof(*sg), GFP_ATOMIC);
+       if (!sg)
+               goto err;
 
-       if (cmd_data_len > ISER_KMALLOC_THRESHOLD)
-               mem = (void *)__get_free_pages(GFP_ATOMIC,
-                     ilog2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT);
-       else
-               mem = kmalloc(cmd_data_len, GFP_ATOMIC);
+       sg_init_table(sg, nents);
+       while (length) {
+               u32 page_len = min_t(u32, length, PAGE_SIZE);
 
-       if (mem == NULL) {
-               iser_err("Failed to allocate mem size %d %d for copying sglist\n",
-                        data->size, (int)cmd_data_len);
-               return -ENOMEM;
+               page = alloc_page(GFP_ATOMIC);
+               if (!page)
+                       goto err;
+
+               sg_set_page(&sg[i], page, page_len, 0);
+               length -= page_len;
+               i++;
        }
 
-       if (cmd_dir == ISER_DIR_OUT) {
-               /* copy the unaligned sg the buffer which is used for RDMA */
-               char *p, *from;
-
-               sgl = (struct scatterlist *)data->buf;
-               p = mem;
-               for_each_sg(sgl, sg, data->size, i) {
-                       from = kmap_atomic(sg_page(sg));
-                       memcpy(p,
-                              from + sg->offset,
-                              sg->length);
-                       kunmap_atomic(from);
-                       p += sg->length;
+       data->orig_sg = data->sg;
+       data->orig_size = data->size;
+       data->sg = sg;
+       data->size = nents;
+
+       return 0;
+
+err:
+       for (; i > 0; i--)
+               __free_page(sg_page(&sg[i - 1]));
+       kfree(sg);
+
+       return -ENOMEM;
+}
+
+static void
+iser_copy_bounce(struct iser_data_buf *data, bool to_buffer)
+{
+       struct scatterlist *osg, *bsg = data->sg;
+       void *oaddr, *baddr;
+       unsigned int left = data->data_len;
+       unsigned int bsg_off = 0;
+       int i;
+
+       for_each_sg(data->orig_sg, osg, data->orig_size, i) {
+               unsigned int copy_len, osg_off = 0;
+
+               oaddr = kmap_atomic(sg_page(osg)) + osg->offset;
+               copy_len = min(left, osg->length);
+               while (copy_len) {
+                       unsigned int len = min(copy_len, bsg->length - bsg_off);
+
+                       baddr = kmap_atomic(sg_page(bsg)) + bsg->offset;
+                       if (to_buffer)
+                               memcpy(baddr + bsg_off, oaddr + osg_off, len);
+                       else
+                               memcpy(oaddr + osg_off, baddr + bsg_off, len);
+
+                       kunmap_atomic(baddr - bsg->offset);
+                       osg_off += len;
+                       bsg_off += len;
+                       copy_len -= len;
+
+                       if (bsg_off >= bsg->length) {
+                               bsg = sg_next(bsg);
+                               bsg_off = 0;
+                       }
                }
+               kunmap_atomic(oaddr - osg->offset);
+               left -= osg_off;
        }
+}
+
+static inline void
+iser_copy_from_bounce(struct iser_data_buf *data)
+{
+       iser_copy_bounce(data, false);
+}
+
+static inline void
+iser_copy_to_bounce(struct iser_data_buf *data)
+{
+       iser_copy_bounce(data, true);
+}
+
+struct fast_reg_descriptor *
+iser_reg_desc_get(struct ib_conn *ib_conn)
+{
+       struct fast_reg_descriptor *desc;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ib_conn->lock, flags);
+       desc = list_first_entry(&ib_conn->fastreg.pool,
+                               struct fast_reg_descriptor, list);
+       list_del(&desc->list);
+       spin_unlock_irqrestore(&ib_conn->lock, flags);
+
+       return desc;
+}
+
+void
+iser_reg_desc_put(struct ib_conn *ib_conn,
+                 struct fast_reg_descriptor *desc)
+{
+       unsigned long flags;
 
-       sg_init_one(&data_copy->sg_single, mem, cmd_data_len);
-       data_copy->buf = &data_copy->sg_single;
-       data_copy->size = 1;
-       data_copy->copy_buf = mem;
+       spin_lock_irqsave(&ib_conn->lock, flags);
+       list_add(&desc->list, &ib_conn->fastreg.pool);
+       spin_unlock_irqrestore(&ib_conn->lock, flags);
+}
 
-       dma_nents = ib_dma_map_sg(dev, &data_copy->sg_single, 1,
-                                 (cmd_dir == ISER_DIR_OUT) ?
-                                 DMA_TO_DEVICE : DMA_FROM_DEVICE);
-       BUG_ON(dma_nents == 0);
+/**
+ * iser_start_rdma_unaligned_sg
+ */
+static int iser_start_rdma_unaligned_sg(struct iscsi_iser_task *iser_task,
+                                       struct iser_data_buf *data,
+                                       enum iser_data_dir cmd_dir)
+{
+       struct ib_device *dev = iser_task->iser_conn->ib_conn.device->ib_device;
+       int rc;
+
+       rc = iser_alloc_bounce_sg(data);
+       if (rc) {
+               iser_err("Failed to allocate bounce for data len %lu\n",
+                        data->data_len);
+               return rc;
+       }
+
+       if (cmd_dir == ISER_DIR_OUT)
+               iser_copy_to_bounce(data);
 
-       data_copy->dma_nents = dma_nents;
-       data_copy->data_len = cmd_data_len;
+       data->dma_nents = ib_dma_map_sg(dev, data->sg, data->size,
+                                       (cmd_dir == ISER_DIR_OUT) ?
+                                       DMA_TO_DEVICE : DMA_FROM_DEVICE);
+       if (!data->dma_nents) {
+               iser_err("Got dma_nents %d, something went wrong...\n",
+                        data->dma_nents);
+               rc = -ENOMEM;
+               goto err;
+       }
 
        return 0;
+err:
+       iser_free_bounce_sg(data);
+       return rc;
 }
 
 /**
@@ -109,51 +214,18 @@ static int iser_start_rdma_unaligned_sg(struct iscsi_iser_task *iser_task,
 
 void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_task *iser_task,
                                     struct iser_data_buf *data,
-                                    struct iser_data_buf *data_copy,
                                     enum iser_data_dir cmd_dir)
 {
-       struct ib_device *dev;
-       unsigned long  cmd_data_len;
-
-       dev = iser_task->iser_conn->ib_conn.device->ib_device;
+       struct ib_device *dev = iser_task->iser_conn->ib_conn.device->ib_device;
 
-       ib_dma_unmap_sg(dev, &data_copy->sg_single, 1,
+       ib_dma_unmap_sg(dev, data->sg, data->size,
                        (cmd_dir == ISER_DIR_OUT) ?
                        DMA_TO_DEVICE : DMA_FROM_DEVICE);
 
-       if (cmd_dir == ISER_DIR_IN) {
-               char *mem;
-               struct scatterlist *sgl, *sg;
-               unsigned char *p, *to;
-               unsigned int sg_size;
-               int i;
-
-               /* copy back read RDMA to unaligned sg */
-               mem = data_copy->copy_buf;
-
-               sgl = (struct scatterlist *)data->buf;
-               sg_size = data->size;
-
-               p = mem;
-               for_each_sg(sgl, sg, sg_size, i) {
-                       to = kmap_atomic(sg_page(sg));
-                       memcpy(to + sg->offset,
-                              p,
-                              sg->length);
-                       kunmap_atomic(to);
-                       p += sg->length;
-               }
-       }
+       if (cmd_dir == ISER_DIR_IN)
+               iser_copy_from_bounce(data);
 
-       cmd_data_len = data->data_len;
-
-       if (cmd_data_len > ISER_KMALLOC_THRESHOLD)
-               free_pages((unsigned long)data_copy->copy_buf,
-                          ilog2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT);
-       else
-               kfree(data_copy->copy_buf);
-
-       data_copy->copy_buf = NULL;
+       iser_free_bounce_sg(data);
 }
 
 #define IS_4K_ALIGNED(addr)    ((((unsigned long)addr) & ~MASK_4K) == 0)
@@ -175,7 +247,7 @@ static int iser_sg_to_page_vec(struct iser_data_buf *data,
                               struct ib_device *ibdev, u64 *pages,
                               int *offset, int *data_size)
 {
-       struct scatterlist *sg, *sgl = (struct scatterlist *)data->buf;
+       struct scatterlist *sg, *sgl = data->sg;
        u64 start_addr, end_addr, page, chunk_start = 0;
        unsigned long total_sz = 0;
        unsigned int dma_len;
@@ -227,14 +299,14 @@ static int iser_sg_to_page_vec(struct iser_data_buf *data,
 static int iser_data_buf_aligned_len(struct iser_data_buf *data,
                                      struct ib_device *ibdev)
 {
-       struct scatterlist *sgl, *sg, *next_sg = NULL;
+       struct scatterlist *sg, *sgl, *next_sg = NULL;
        u64 start_addr, end_addr;
        int i, ret_len, start_check = 0;
 
        if (data->dma_nents == 1)
                return 1;
 
-       sgl = (struct scatterlist *)data->buf;
+       sgl = data->sg;
        start_addr  = ib_sg_dma_address(ibdev, sgl);
 
        for_each_sg(sgl, sg, data->dma_nents, i) {
@@ -266,11 +338,10 @@ static int iser_data_buf_aligned_len(struct iser_data_buf *data,
 static void iser_data_buf_dump(struct iser_data_buf *data,
                               struct ib_device *ibdev)
 {
-       struct scatterlist *sgl = (struct scatterlist *)data->buf;
        struct scatterlist *sg;
        int i;
 
-       for_each_sg(sgl, sg, data->dma_nents, i)
+       for_each_sg(data->sg, sg, data->dma_nents, i)
                iser_dbg("sg[%d] dma_addr:0x%lX page:0x%p "
                         "off:0x%x sz:0x%x dma_len:0x%x\n",
                         i, (unsigned long)ib_sg_dma_address(ibdev, sg),
@@ -288,31 +359,6 @@ static void iser_dump_page_vec(struct iser_page_vec *page_vec)
                iser_err("%d %lx\n",i,(unsigned long)page_vec->pages[i]);
 }
 
-static void iser_page_vec_build(struct iser_data_buf *data,
-                               struct iser_page_vec *page_vec,
-                               struct ib_device *ibdev)
-{
-       int page_vec_len = 0;
-
-       page_vec->length = 0;
-       page_vec->offset = 0;
-
-       iser_dbg("Translating sg sz: %d\n", data->dma_nents);
-       page_vec_len = iser_sg_to_page_vec(data, ibdev, page_vec->pages,
-                                          &page_vec->offset,
-                                          &page_vec->data_size);
-       iser_dbg("sg len %d page_vec_len %d\n", data->dma_nents, page_vec_len);
-
-       page_vec->length = page_vec_len;
-
-       if (page_vec_len * SIZE_4K < page_vec->data_size) {
-               iser_err("page_vec too short to hold this SG\n");
-               iser_data_buf_dump(data, ibdev);
-               iser_dump_page_vec(page_vec);
-               BUG();
-       }
-}
-
 int iser_dma_map_task_data(struct iscsi_iser_task *iser_task,
                            struct iser_data_buf *data,
                            enum iser_data_dir iser_dir,
@@ -323,7 +369,7 @@ int iser_dma_map_task_data(struct iscsi_iser_task *iser_task,
        iser_task->dir[iser_dir] = 1;
        dev = iser_task->iser_conn->ib_conn.device->ib_device;
 
-       data->dma_nents = ib_dma_map_sg(dev, data->buf, data->size, dma_dir);
+       data->dma_nents = ib_dma_map_sg(dev, data->sg, data->size, dma_dir);
        if (data->dma_nents == 0) {
                iser_err("dma_map_sg failed!!!\n");
                return -EINVAL;
@@ -338,24 +384,41 @@ void iser_dma_unmap_task_data(struct iscsi_iser_task *iser_task,
        struct ib_device *dev;
 
        dev = iser_task->iser_conn->ib_conn.device->ib_device;
-       ib_dma_unmap_sg(dev, data->buf, data->size, dir);
+       ib_dma_unmap_sg(dev, data->sg, data->size, dir);
+}
+
+static int
+iser_reg_dma(struct iser_device *device, struct iser_data_buf *mem,
+            struct iser_mem_reg *reg)
+{
+       struct scatterlist *sg = mem->sg;
+
+       reg->sge.lkey = device->mr->lkey;
+       reg->rkey = device->mr->rkey;
+       reg->sge.addr = ib_sg_dma_address(device->ib_device, &sg[0]);
+       reg->sge.length = ib_sg_dma_len(device->ib_device, &sg[0]);
+
+       iser_dbg("Single DMA entry: lkey=0x%x, rkey=0x%x, addr=0x%llx,"
+                " length=0x%x\n", reg->sge.lkey, reg->rkey,
+                reg->sge.addr, reg->sge.length);
+
+       return 0;
 }
 
 static int fall_to_bounce_buf(struct iscsi_iser_task *iser_task,
-                             struct ib_device *ibdev,
                              struct iser_data_buf *mem,
-                             struct iser_data_buf *mem_copy,
                              enum iser_data_dir cmd_dir,
                              int aligned_len)
 {
-       struct iscsi_conn    *iscsi_conn = iser_task->iser_conn->iscsi_conn;
+       struct iscsi_conn *iscsi_conn = iser_task->iser_conn->iscsi_conn;
+       struct iser_device *device = iser_task->iser_conn->ib_conn.device;
 
        iscsi_conn->fmr_unalign_cnt++;
        iser_warn("rdma alignment violation (%d/%d aligned) or FMR not supported\n",
                  aligned_len, mem->size);
 
        if (iser_debug_level > 0)
-               iser_data_buf_dump(mem, ibdev);
+               iser_data_buf_dump(mem, device->ib_device);
 
        /* unmap the command data before accessing it */
        iser_dma_unmap_task_data(iser_task, mem,
@@ -364,12 +427,94 @@ static int fall_to_bounce_buf(struct iscsi_iser_task *iser_task,
 
        /* allocate copy buf, if we are writing, copy the */
        /* unaligned scatterlist, dma map the copy        */
-       if (iser_start_rdma_unaligned_sg(iser_task, mem, mem_copy, cmd_dir) != 0)
+       if (iser_start_rdma_unaligned_sg(iser_task, mem, cmd_dir) != 0)
                return -ENOMEM;
 
        return 0;
 }
 
+/**
+ * iser_reg_page_vec - Register physical memory
+ *
+ * returns: 0 on success, errno code on failure
+ */
+static
+int iser_reg_page_vec(struct iscsi_iser_task *iser_task,
+                     struct iser_data_buf *mem,
+                     struct iser_page_vec *page_vec,
+                     struct iser_mem_reg *mem_reg)
+{
+       struct ib_conn *ib_conn = &iser_task->iser_conn->ib_conn;
+       struct iser_device *device = ib_conn->device;
+       struct ib_pool_fmr *fmr;
+       int ret, plen;
+
+       plen = iser_sg_to_page_vec(mem, device->ib_device,
+                                  page_vec->pages,
+                                  &page_vec->offset,
+                                  &page_vec->data_size);
+       page_vec->length = plen;
+       if (plen * SIZE_4K < page_vec->data_size) {
+               iser_err("page vec too short to hold this SG\n");
+               iser_data_buf_dump(mem, device->ib_device);
+               iser_dump_page_vec(page_vec);
+               return -EINVAL;
+       }
+
+       fmr  = ib_fmr_pool_map_phys(ib_conn->fmr.pool,
+                                   page_vec->pages,
+                                   page_vec->length,
+                                   page_vec->pages[0]);
+       if (IS_ERR(fmr)) {
+               ret = PTR_ERR(fmr);
+               iser_err("ib_fmr_pool_map_phys failed: %d\n", ret);
+               return ret;
+       }
+
+       mem_reg->sge.lkey = fmr->fmr->lkey;
+       mem_reg->rkey = fmr->fmr->rkey;
+       mem_reg->sge.addr = page_vec->pages[0] + page_vec->offset;
+       mem_reg->sge.length = page_vec->data_size;
+       mem_reg->mem_h = fmr;
+
+       return 0;
+}
+
+/**
+ * Unregister (previosuly registered using FMR) memory.
+ * If memory is non-FMR does nothing.
+ */
+void iser_unreg_mem_fmr(struct iscsi_iser_task *iser_task,
+                       enum iser_data_dir cmd_dir)
+{
+       struct iser_mem_reg *reg = &iser_task->rdma_reg[cmd_dir];
+       int ret;
+
+       if (!reg->mem_h)
+               return;
+
+       iser_dbg("PHYSICAL Mem.Unregister mem_h %p\n", reg->mem_h);
+
+       ret = ib_fmr_pool_unmap((struct ib_pool_fmr *)reg->mem_h);
+       if (ret)
+               iser_err("ib_fmr_pool_unmap failed %d\n", ret);
+
+       reg->mem_h = NULL;
+}
+
+void iser_unreg_mem_fastreg(struct iscsi_iser_task *iser_task,
+                           enum iser_data_dir cmd_dir)
+{
+       struct iser_mem_reg *reg = &iser_task->rdma_reg[cmd_dir];
+
+       if (!reg->mem_h)
+               return;
+
+       iser_reg_desc_put(&iser_task->iser_conn->ib_conn,
+                         reg->mem_h);
+       reg->mem_h = NULL;
+}
+
 /**
  * iser_reg_rdma_mem_fmr - Registers memory intended for RDMA,
  * using FMR (if possible) obtaining rkey and va
@@ -383,45 +528,29 @@ int iser_reg_rdma_mem_fmr(struct iscsi_iser_task *iser_task,
        struct iser_device   *device = ib_conn->device;
        struct ib_device     *ibdev = device->ib_device;
        struct iser_data_buf *mem = &iser_task->data[cmd_dir];
-       struct iser_regd_buf *regd_buf;
+       struct iser_mem_reg *mem_reg;
        int aligned_len;
        int err;
        int i;
-       struct scatterlist *sg;
 
-       regd_buf = &iser_task->rdma_regd[cmd_dir];
+       mem_reg = &iser_task->rdma_reg[cmd_dir];
 
        aligned_len = iser_data_buf_aligned_len(mem, ibdev);
        if (aligned_len != mem->dma_nents) {
-               err = fall_to_bounce_buf(iser_task, ibdev, mem,
-                                        &iser_task->data_copy[cmd_dir],
+               err = fall_to_bounce_buf(iser_task, mem,
                                         cmd_dir, aligned_len);
                if (err) {
                        iser_err("failed to allocate bounce buffer\n");
                        return err;
                }
-               mem = &iser_task->data_copy[cmd_dir];
        }
 
        /* if there a single dma entry, FMR is not needed */
        if (mem->dma_nents == 1) {
-               sg = (struct scatterlist *)mem->buf;
-
-               regd_buf->reg.lkey = device->mr->lkey;
-               regd_buf->reg.rkey = device->mr->rkey;
-               regd_buf->reg.len  = ib_sg_dma_len(ibdev, &sg[0]);
-               regd_buf->reg.va   = ib_sg_dma_address(ibdev, &sg[0]);
-
-               iser_dbg("PHYSICAL Mem.register: lkey: 0x%08X rkey: 0x%08X  "
-                        "va: 0x%08lX sz: %ld]\n",
-                        (unsigned int)regd_buf->reg.lkey,
-                        (unsigned int)regd_buf->reg.rkey,
-                        (unsigned long)regd_buf->reg.va,
-                        (unsigned long)regd_buf->reg.len);
+               return iser_reg_dma(device, mem, mem_reg);
        } else { /* use FMR for multiple dma entries */
-               iser_page_vec_build(mem, ib_conn->fmr.page_vec, ibdev);
-               err = iser_reg_page_vec(ib_conn, ib_conn->fmr.page_vec,
-                                       &regd_buf->reg);
+               err = iser_reg_page_vec(iser_task, mem, ib_conn->fmr.page_vec,
+                                       mem_reg);
                if (err && err != -EAGAIN) {
                        iser_data_buf_dump(mem, ibdev);
                        iser_err("mem->dma_nents = %d (dlength = 0x%x)\n",
@@ -519,8 +648,10 @@ iser_inv_rkey(struct ib_send_wr *inv_wr, struct ib_mr *mr)
 
 static int
 iser_reg_sig_mr(struct iscsi_iser_task *iser_task,
-               struct fast_reg_descriptor *desc, struct ib_sge *data_sge,
-               struct ib_sge *prot_sge, struct ib_sge *sig_sge)
+               struct fast_reg_descriptor *desc,
+               struct iser_mem_reg *data_reg,
+               struct iser_mem_reg *prot_reg,
+               struct iser_mem_reg *sig_reg)
 {
        struct ib_conn *ib_conn = &iser_task->iser_conn->ib_conn;
        struct iser_pi_context *pi_ctx = desc->pi_ctx;
@@ -544,12 +675,12 @@ iser_reg_sig_mr(struct iscsi_iser_task *iser_task,
        memset(&sig_wr, 0, sizeof(sig_wr));
        sig_wr.opcode = IB_WR_REG_SIG_MR;
        sig_wr.wr_id = ISER_FASTREG_LI_WRID;
-       sig_wr.sg_list = data_sge;
+       sig_wr.sg_list = &data_reg->sge;
        sig_wr.num_sge = 1;
        sig_wr.wr.sig_handover.sig_attrs = &sig_attrs;
        sig_wr.wr.sig_handover.sig_mr = pi_ctx->sig_mr;
        if (scsi_prot_sg_count(iser_task->sc))
-               sig_wr.wr.sig_handover.prot = prot_sge;
+               sig_wr.wr.sig_handover.prot = &prot_reg->sge;
        sig_wr.wr.sig_handover.access_flags = IB_ACCESS_LOCAL_WRITE |
                                              IB_ACCESS_REMOTE_READ |
                                              IB_ACCESS_REMOTE_WRITE;
@@ -566,27 +697,26 @@ iser_reg_sig_mr(struct iscsi_iser_task *iser_task,
        }
        desc->reg_indicators &= ~ISER_SIG_KEY_VALID;
 
-       sig_sge->lkey = pi_ctx->sig_mr->lkey;
-       sig_sge->addr = 0;
-       sig_sge->length = scsi_transfer_length(iser_task->sc);
+       sig_reg->sge.lkey = pi_ctx->sig_mr->lkey;
+       sig_reg->rkey = pi_ctx->sig_mr->rkey;
+       sig_reg->sge.addr = 0;
+       sig_reg->sge.length = scsi_transfer_length(iser_task->sc);
 
-       iser_dbg("sig_sge: addr: 0x%llx  length: %u lkey: 0x%x\n",
-                sig_sge->addr, sig_sge->length,
-                sig_sge->lkey);
+       iser_dbg("sig_sge: lkey: 0x%x, rkey: 0x%x, addr: 0x%llx, length: %u\n",
+                sig_reg->sge.lkey, sig_reg->rkey, sig_reg->sge.addr,
+                sig_reg->sge.length);
 err:
        return ret;
 }
 
 static int iser_fast_reg_mr(struct iscsi_iser_task *iser_task,
-                           struct iser_regd_buf *regd_buf,
                            struct iser_data_buf *mem,
+                           struct fast_reg_descriptor *desc,
                            enum iser_reg_indicator ind,
-                           struct ib_sge *sge)
+                           struct iser_mem_reg *reg)
 {
-       struct fast_reg_descriptor *desc = regd_buf->reg.mem_h;
        struct ib_conn *ib_conn = &iser_task->iser_conn->ib_conn;
        struct iser_device *device = ib_conn->device;
-       struct ib_device *ibdev = device->ib_device;
        struct ib_mr *mr;
        struct ib_fast_reg_page_list *frpl;
        struct ib_send_wr fastreg_wr, inv_wr;
@@ -594,17 +724,8 @@ static int iser_fast_reg_mr(struct iscsi_iser_task *iser_task,
        int ret, offset, size, plen;
 
        /* if there a single dma entry, dma mr suffices */
-       if (mem->dma_nents == 1) {
-               struct scatterlist *sg = (struct scatterlist *)mem->buf;
-
-               sge->lkey = device->mr->lkey;
-               sge->addr   = ib_sg_dma_address(ibdev, &sg[0]);
-               sge->length  = ib_sg_dma_len(ibdev, &sg[0]);
-
-               iser_dbg("Single DMA entry: lkey=0x%x, addr=0x%llx, length=0x%x\n",
-                        sge->lkey, sge->addr, sge->length);
-               return 0;
-       }
+       if (mem->dma_nents == 1)
+               return iser_reg_dma(device, mem, reg);
 
        if (ind == ISER_DATA_KEY_VALID) {
                mr = desc->data_mr;
@@ -652,9 +773,10 @@ static int iser_fast_reg_mr(struct iscsi_iser_task *iser_task,
        }
        desc->reg_indicators &= ~ind;
 
-       sge->lkey = mr->lkey;
-       sge->addr = frpl->page_list[0] + offset;
-       sge->length = size;
+       reg->sge.lkey = mr->lkey;
+       reg->rkey = mr->rkey;
+       reg->sge.addr = frpl->page_list[0] + offset;
+       reg->sge.length = size;
 
        return ret;
 }
@@ -672,93 +794,66 @@ int iser_reg_rdma_mem_fastreg(struct iscsi_iser_task *iser_task,
        struct iser_device *device = ib_conn->device;
        struct ib_device *ibdev = device->ib_device;
        struct iser_data_buf *mem = &iser_task->data[cmd_dir];
-       struct iser_regd_buf *regd_buf = &iser_task->rdma_regd[cmd_dir];
+       struct iser_mem_reg *mem_reg = &iser_task->rdma_reg[cmd_dir];
        struct fast_reg_descriptor *desc = NULL;
-       struct ib_sge data_sge;
        int err, aligned_len;
-       unsigned long flags;
 
        aligned_len = iser_data_buf_aligned_len(mem, ibdev);
        if (aligned_len != mem->dma_nents) {
-               err = fall_to_bounce_buf(iser_task, ibdev, mem,
-                                        &iser_task->data_copy[cmd_dir],
+               err = fall_to_bounce_buf(iser_task, mem,
                                         cmd_dir, aligned_len);
                if (err) {
                        iser_err("failed to allocate bounce buffer\n");
                        return err;
                }
-               mem = &iser_task->data_copy[cmd_dir];
        }
 
        if (mem->dma_nents != 1 ||
            scsi_get_prot_op(iser_task->sc) != SCSI_PROT_NORMAL) {
-               spin_lock_irqsave(&ib_conn->lock, flags);
-               desc = list_first_entry(&ib_conn->fastreg.pool,
-                                       struct fast_reg_descriptor, list);
-               list_del(&desc->list);
-               spin_unlock_irqrestore(&ib_conn->lock, flags);
-               regd_buf->reg.mem_h = desc;
+               desc = iser_reg_desc_get(ib_conn);
+               mem_reg->mem_h = desc;
        }
 
-       err = iser_fast_reg_mr(iser_task, regd_buf, mem,
-                              ISER_DATA_KEY_VALID, &data_sge);
+       err = iser_fast_reg_mr(iser_task, mem, desc,
+                              ISER_DATA_KEY_VALID, mem_reg);
        if (err)
                goto err_reg;
 
        if (scsi_get_prot_op(iser_task->sc) != SCSI_PROT_NORMAL) {
-               struct ib_sge prot_sge, sig_sge;
+               struct iser_mem_reg prot_reg;
 
-               memset(&prot_sge, 0, sizeof(prot_sge));
+               memset(&prot_reg, 0, sizeof(prot_reg));
                if (scsi_prot_sg_count(iser_task->sc)) {
                        mem = &iser_task->prot[cmd_dir];
                        aligned_len = iser_data_buf_aligned_len(mem, ibdev);
                        if (aligned_len != mem->dma_nents) {
-                               err = fall_to_bounce_buf(iser_task, ibdev, mem,
-                                                        &iser_task->prot_copy[cmd_dir],
+                               err = fall_to_bounce_buf(iser_task, mem,
                                                         cmd_dir, aligned_len);
                                if (err) {
                                        iser_err("failed to allocate bounce buffer\n");
                                        return err;
                                }
-                               mem = &iser_task->prot_copy[cmd_dir];
                        }
 
-                       err = iser_fast_reg_mr(iser_task, regd_buf, mem,
-                                              ISER_PROT_KEY_VALID, &prot_sge);
+                       err = iser_fast_reg_mr(iser_task, mem, desc,
+                                              ISER_PROT_KEY_VALID, &prot_reg);
                        if (err)
                                goto err_reg;
                }
 
-               err = iser_reg_sig_mr(iser_task, desc, &data_sge,
-                                     &prot_sge, &sig_sge);
+               err = iser_reg_sig_mr(iser_task, desc, mem_reg,
+                                     &prot_reg, mem_reg);
                if (err) {
                        iser_err("Failed to register signature mr\n");
                        return err;
                }
                desc->reg_indicators |= ISER_FASTREG_PROTECTED;
-
-               regd_buf->reg.lkey = sig_sge.lkey;
-               regd_buf->reg.rkey = desc->pi_ctx->sig_mr->rkey;
-               regd_buf->reg.va = sig_sge.addr;
-               regd_buf->reg.len = sig_sge.length;
-       } else {
-               if (desc)
-                       regd_buf->reg.rkey = desc->data_mr->rkey;
-               else
-                       regd_buf->reg.rkey = device->mr->rkey;
-
-               regd_buf->reg.lkey = data_sge.lkey;
-               regd_buf->reg.va = data_sge.addr;
-               regd_buf->reg.len = data_sge.length;
        }
 
        return 0;
 err_reg:
-       if (desc) {
-               spin_lock_irqsave(&ib_conn->lock, flags);
-               list_add_tail(&desc->list, &ib_conn->fastreg.pool);
-               spin_unlock_irqrestore(&ib_conn->lock, flags);
-       }
+       if (desc)
+               iser_reg_desc_put(ib_conn, desc);
 
        return err;
 }
index 4065abe28829f78356c5ee7cd76ffa7b7330b3d5..cc2dd35ffbc08616af0ffddd854d1f4858570515 100644 (file)
@@ -273,6 +273,65 @@ void iser_free_fmr_pool(struct ib_conn *ib_conn)
        ib_conn->fmr.page_vec = NULL;
 }
 
+static int
+iser_alloc_pi_ctx(struct ib_device *ib_device, struct ib_pd *pd,
+                 struct fast_reg_descriptor *desc)
+{
+       struct iser_pi_context *pi_ctx = NULL;
+       struct ib_mr_init_attr mr_init_attr = {.max_reg_descriptors = 2,
+                                              .flags = IB_MR_SIGNATURE_EN};
+       int ret = 0;
+
+       desc->pi_ctx = kzalloc(sizeof(*desc->pi_ctx), GFP_KERNEL);
+       if (!desc->pi_ctx)
+               return -ENOMEM;
+
+       pi_ctx = desc->pi_ctx;
+
+       pi_ctx->prot_frpl = ib_alloc_fast_reg_page_list(ib_device,
+                                           ISCSI_ISER_SG_TABLESIZE);
+       if (IS_ERR(pi_ctx->prot_frpl)) {
+               ret = PTR_ERR(pi_ctx->prot_frpl);
+               goto prot_frpl_failure;
+       }
+
+       pi_ctx->prot_mr = ib_alloc_fast_reg_mr(pd,
+                                       ISCSI_ISER_SG_TABLESIZE + 1);
+       if (IS_ERR(pi_ctx->prot_mr)) {
+               ret = PTR_ERR(pi_ctx->prot_mr);
+               goto prot_mr_failure;
+       }
+       desc->reg_indicators |= ISER_PROT_KEY_VALID;
+
+       pi_ctx->sig_mr = ib_create_mr(pd, &mr_init_attr);
+       if (IS_ERR(pi_ctx->sig_mr)) {
+               ret = PTR_ERR(pi_ctx->sig_mr);
+               goto sig_mr_failure;
+       }
+       desc->reg_indicators |= ISER_SIG_KEY_VALID;
+       desc->reg_indicators &= ~ISER_FASTREG_PROTECTED;
+
+       return 0;
+
+sig_mr_failure:
+       ib_dereg_mr(desc->pi_ctx->prot_mr);
+prot_mr_failure:
+       ib_free_fast_reg_page_list(desc->pi_ctx->prot_frpl);
+prot_frpl_failure:
+       kfree(desc->pi_ctx);
+
+       return ret;
+}
+
+static void
+iser_free_pi_ctx(struct iser_pi_context *pi_ctx)
+{
+       ib_free_fast_reg_page_list(pi_ctx->prot_frpl);
+       ib_dereg_mr(pi_ctx->prot_mr);
+       ib_destroy_mr(pi_ctx->sig_mr);
+       kfree(pi_ctx);
+}
+
 static int
 iser_create_fastreg_desc(struct ib_device *ib_device, struct ib_pd *pd,
                         bool pi_enable, struct fast_reg_descriptor *desc)
@@ -297,59 +356,12 @@ iser_create_fastreg_desc(struct ib_device *ib_device, struct ib_pd *pd,
        desc->reg_indicators |= ISER_DATA_KEY_VALID;
 
        if (pi_enable) {
-               struct ib_mr_init_attr mr_init_attr = {0};
-               struct iser_pi_context *pi_ctx = NULL;
-
-               desc->pi_ctx = kzalloc(sizeof(*desc->pi_ctx), GFP_KERNEL);
-               if (!desc->pi_ctx) {
-                       iser_err("Failed to allocate pi context\n");
-                       ret = -ENOMEM;
+               ret = iser_alloc_pi_ctx(ib_device, pd, desc);
+               if (ret)
                        goto pi_ctx_alloc_failure;
-               }
-               pi_ctx = desc->pi_ctx;
-
-               pi_ctx->prot_frpl = ib_alloc_fast_reg_page_list(ib_device,
-                                                   ISCSI_ISER_SG_TABLESIZE);
-               if (IS_ERR(pi_ctx->prot_frpl)) {
-                       ret = PTR_ERR(pi_ctx->prot_frpl);
-                       iser_err("Failed to allocate prot frpl ret=%d\n",
-                                ret);
-                       goto prot_frpl_failure;
-               }
-
-               pi_ctx->prot_mr = ib_alloc_fast_reg_mr(pd,
-                                               ISCSI_ISER_SG_TABLESIZE + 1);
-               if (IS_ERR(pi_ctx->prot_mr)) {
-                       ret = PTR_ERR(pi_ctx->prot_mr);
-                       iser_err("Failed to allocate prot frmr ret=%d\n",
-                                ret);
-                       goto prot_mr_failure;
-               }
-               desc->reg_indicators |= ISER_PROT_KEY_VALID;
-
-               mr_init_attr.max_reg_descriptors = 2;
-               mr_init_attr.flags |= IB_MR_SIGNATURE_EN;
-               pi_ctx->sig_mr = ib_create_mr(pd, &mr_init_attr);
-               if (IS_ERR(pi_ctx->sig_mr)) {
-                       ret = PTR_ERR(pi_ctx->sig_mr);
-                       iser_err("Failed to allocate signature enabled mr err=%d\n",
-                                ret);
-                       goto sig_mr_failure;
-               }
-               desc->reg_indicators |= ISER_SIG_KEY_VALID;
        }
-       desc->reg_indicators &= ~ISER_FASTREG_PROTECTED;
-
-       iser_dbg("Create fr_desc %p page_list %p\n",
-                desc, desc->data_frpl->page_list);
 
        return 0;
-sig_mr_failure:
-       ib_dereg_mr(desc->pi_ctx->prot_mr);
-prot_mr_failure:
-       ib_free_fast_reg_page_list(desc->pi_ctx->prot_frpl);
-prot_frpl_failure:
-       kfree(desc->pi_ctx);
 pi_ctx_alloc_failure:
        ib_dereg_mr(desc->data_mr);
 fast_reg_mr_failure:
@@ -416,12 +428,8 @@ void iser_free_fastreg_pool(struct ib_conn *ib_conn)
                list_del(&desc->list);
                ib_free_fast_reg_page_list(desc->data_frpl);
                ib_dereg_mr(desc->data_mr);
-               if (desc->pi_ctx) {
-                       ib_free_fast_reg_page_list(desc->pi_ctx->prot_frpl);
-                       ib_dereg_mr(desc->pi_ctx->prot_mr);
-                       ib_destroy_mr(desc->pi_ctx->sig_mr);
-                       kfree(desc->pi_ctx);
-               }
+               if (desc->pi_ctx)
+                       iser_free_pi_ctx(desc->pi_ctx);
                kfree(desc);
                ++i;
        }
@@ -721,7 +729,7 @@ static void iser_connect_error(struct rdma_cm_id *cma_id)
        struct iser_conn *iser_conn;
 
        iser_conn = (struct iser_conn *)cma_id->context;
-       iser_conn->state = ISER_CONN_DOWN;
+       iser_conn->state = ISER_CONN_TERMINATING;
 }
 
 /**
@@ -992,93 +1000,6 @@ connect_failure:
        return err;
 }
 
-/**
- * iser_reg_page_vec - Register physical memory
- *
- * returns: 0 on success, errno code on failure
- */
-int iser_reg_page_vec(struct ib_conn *ib_conn,
-                     struct iser_page_vec *page_vec,
-                     struct iser_mem_reg  *mem_reg)
-{
-       struct ib_pool_fmr *mem;
-       u64                io_addr;
-       u64                *page_list;
-       int                status;
-
-       page_list = page_vec->pages;
-       io_addr   = page_list[0];
-
-       mem  = ib_fmr_pool_map_phys(ib_conn->fmr.pool,
-                                   page_list,
-                                   page_vec->length,
-                                   io_addr);
-
-       if (IS_ERR(mem)) {
-               status = (int)PTR_ERR(mem);
-               iser_err("ib_fmr_pool_map_phys failed: %d\n", status);
-               return status;
-       }
-
-       mem_reg->lkey  = mem->fmr->lkey;
-       mem_reg->rkey  = mem->fmr->rkey;
-       mem_reg->len   = page_vec->length * SIZE_4K;
-       mem_reg->va    = io_addr;
-       mem_reg->mem_h = (void *)mem;
-
-       mem_reg->va   += page_vec->offset;
-       mem_reg->len   = page_vec->data_size;
-
-       iser_dbg("PHYSICAL Mem.register, [PHYS p_array: 0x%p, sz: %d, "
-                "entry[0]: (0x%08lx,%ld)] -> "
-                "[lkey: 0x%08X mem_h: 0x%p va: 0x%08lX sz: %ld]\n",
-                page_vec, page_vec->length,
-                (unsigned long)page_vec->pages[0],
-                (unsigned long)page_vec->data_size,
-                (unsigned int)mem_reg->lkey, mem_reg->mem_h,
-                (unsigned long)mem_reg->va, (unsigned long)mem_reg->len);
-       return 0;
-}
-
-/**
- * Unregister (previosuly registered using FMR) memory.
- * If memory is non-FMR does nothing.
- */
-void iser_unreg_mem_fmr(struct iscsi_iser_task *iser_task,
-                       enum iser_data_dir cmd_dir)
-{
-       struct iser_mem_reg *reg = &iser_task->rdma_regd[cmd_dir].reg;
-       int ret;
-
-       if (!reg->mem_h)
-               return;
-
-       iser_dbg("PHYSICAL Mem.Unregister mem_h %p\n",reg->mem_h);
-
-       ret = ib_fmr_pool_unmap((struct ib_pool_fmr *)reg->mem_h);
-       if (ret)
-               iser_err("ib_fmr_pool_unmap failed %d\n", ret);
-
-       reg->mem_h = NULL;
-}
-
-void iser_unreg_mem_fastreg(struct iscsi_iser_task *iser_task,
-                           enum iser_data_dir cmd_dir)
-{
-       struct iser_mem_reg *reg = &iser_task->rdma_regd[cmd_dir].reg;
-       struct iser_conn *iser_conn = iser_task->iser_conn;
-       struct ib_conn *ib_conn = &iser_conn->ib_conn;
-       struct fast_reg_descriptor *desc = reg->mem_h;
-
-       if (!desc)
-               return;
-
-       reg->mem_h = NULL;
-       spin_lock_bh(&ib_conn->lock);
-       list_add_tail(&desc->list, &ib_conn->fastreg.pool);
-       spin_unlock_bh(&ib_conn->lock);
-}
-
 int iser_post_recvl(struct iser_conn *iser_conn)
 {
        struct ib_recv_wr rx_wr, *rx_wr_failed;
@@ -1210,6 +1131,9 @@ iser_handle_comp_error(struct ib_conn *ib_conn,
                        iscsi_conn_failure(iser_conn->iscsi_conn,
                                           ISCSI_ERR_CONN_FAILED);
 
+       if (wc->wr_id == ISER_FASTREG_LI_WRID)
+               return;
+
        if (is_iser_tx_desc(iser_conn, wr_id)) {
                struct iser_tx_desc *desc = wr_id;
 
@@ -1254,13 +1178,11 @@ static void iser_handle_wc(struct ib_wc *wc)
                else
                        iser_dbg("flush error: wr id %llx\n", wc->wr_id);
 
-               if (wc->wr_id != ISER_FASTREG_LI_WRID &&
-                   wc->wr_id != ISER_BEACON_WRID)
-                       iser_handle_comp_error(ib_conn, wc);
-
-               /* complete in case all flush errors were consumed */
                if (wc->wr_id == ISER_BEACON_WRID)
+                       /* all flush errors were consumed */
                        complete(&ib_conn->flush_comp);
+               else
+                       iser_handle_comp_error(ib_conn, wc);
        }
 }
 
@@ -1306,7 +1228,7 @@ static void iser_cq_callback(struct ib_cq *cq, void *cq_context)
 u8 iser_check_task_pi_status(struct iscsi_iser_task *iser_task,
                             enum iser_data_dir cmd_dir, sector_t *sector)
 {
-       struct iser_mem_reg *reg = &iser_task->rdma_regd[cmd_dir].reg;
+       struct iser_mem_reg *reg = &iser_task->rdma_reg[cmd_dir];
        struct fast_reg_descriptor *desc = reg->mem_h;
        unsigned long sector_size = iser_task->sc->device->sector_size;
        struct ib_mr_status mr_status;
index 075b19cc78e89d11d73ba19bcffcd68c18323907..327529ee85eb1ed20bb8b7afad8022df94118108 100644 (file)
@@ -76,12 +76,12 @@ isert_prot_cmd(struct isert_conn *conn, struct se_cmd *cmd)
 static void
 isert_qp_event_callback(struct ib_event *e, void *context)
 {
-       struct isert_conn *isert_conn = (struct isert_conn *)context;
+       struct isert_conn *isert_conn = context;
 
        isert_err("conn %p event: %d\n", isert_conn, e->event);
        switch (e->event) {
        case IB_EVENT_COMM_EST:
-               rdma_notify(isert_conn->conn_cm_id, IB_EVENT_COMM_EST);
+               rdma_notify(isert_conn->cm_id, IB_EVENT_COMM_EST);
                break;
        case IB_EVENT_QP_LAST_WQE_REACHED:
                isert_warn("Reached TX IB_EVENT_QP_LAST_WQE_REACHED\n");
@@ -107,13 +107,12 @@ isert_query_device(struct ib_device *ib_dev, struct ib_device_attr *devattr)
        return 0;
 }
 
-static int
-isert_conn_setup_qp(struct isert_conn *isert_conn, struct rdma_cm_id *cma_id)
+static struct isert_comp *
+isert_comp_get(struct isert_conn *isert_conn)
 {
-       struct isert_device *device = isert_conn->conn_device;
-       struct ib_qp_init_attr attr;
+       struct isert_device *device = isert_conn->device;
        struct isert_comp *comp;
-       int ret, i, min = 0;
+       int i, min = 0;
 
        mutex_lock(&device_list_mutex);
        for (i = 0; i < device->comps_used; i++)
@@ -122,9 +121,30 @@ isert_conn_setup_qp(struct isert_conn *isert_conn, struct rdma_cm_id *cma_id)
                        min = i;
        comp = &device->comps[min];
        comp->active_qps++;
+       mutex_unlock(&device_list_mutex);
+
        isert_info("conn %p, using comp %p min_index: %d\n",
                   isert_conn, comp, min);
+
+       return comp;
+}
+
+static void
+isert_comp_put(struct isert_comp *comp)
+{
+       mutex_lock(&device_list_mutex);
+       comp->active_qps--;
        mutex_unlock(&device_list_mutex);
+}
+
+static struct ib_qp *
+isert_create_qp(struct isert_conn *isert_conn,
+               struct isert_comp *comp,
+               struct rdma_cm_id *cma_id)
+{
+       struct isert_device *device = isert_conn->device;
+       struct ib_qp_init_attr attr;
+       int ret;
 
        memset(&attr, 0, sizeof(struct ib_qp_init_attr));
        attr.event_handler = isert_qp_event_callback;
@@ -149,19 +169,31 @@ isert_conn_setup_qp(struct isert_conn *isert_conn, struct rdma_cm_id *cma_id)
        if (device->pi_capable)
                attr.create_flags |= IB_QP_CREATE_SIGNATURE_EN;
 
-       ret = rdma_create_qp(cma_id, isert_conn->conn_pd, &attr);
+       ret = rdma_create_qp(cma_id, device->pd, &attr);
        if (ret) {
                isert_err("rdma_create_qp failed for cma_id %d\n", ret);
+               return ERR_PTR(ret);
+       }
+
+       return cma_id->qp;
+}
+
+static int
+isert_conn_setup_qp(struct isert_conn *isert_conn, struct rdma_cm_id *cma_id)
+{
+       struct isert_comp *comp;
+       int ret;
+
+       comp = isert_comp_get(isert_conn);
+       isert_conn->qp = isert_create_qp(isert_conn, comp, cma_id);
+       if (IS_ERR(isert_conn->qp)) {
+               ret = PTR_ERR(isert_conn->qp);
                goto err;
        }
-       isert_conn->conn_qp = cma_id->qp;
 
        return 0;
 err:
-       mutex_lock(&device_list_mutex);
-       comp->active_qps--;
-       mutex_unlock(&device_list_mutex);
-
+       isert_comp_put(comp);
        return ret;
 }
 
@@ -174,18 +206,19 @@ isert_cq_event_callback(struct ib_event *e, void *context)
 static int
 isert_alloc_rx_descriptors(struct isert_conn *isert_conn)
 {
-       struct ib_device *ib_dev = isert_conn->conn_cm_id->device;
+       struct isert_device *device = isert_conn->device;
+       struct ib_device *ib_dev = device->ib_device;
        struct iser_rx_desc *rx_desc;
        struct ib_sge *rx_sg;
        u64 dma_addr;
        int i, j;
 
-       isert_conn->conn_rx_descs = kzalloc(ISERT_QP_MAX_RECV_DTOS *
+       isert_conn->rx_descs = kzalloc(ISERT_QP_MAX_RECV_DTOS *
                                sizeof(struct iser_rx_desc), GFP_KERNEL);
-       if (!isert_conn->conn_rx_descs)
+       if (!isert_conn->rx_descs)
                goto fail;
 
-       rx_desc = isert_conn->conn_rx_descs;
+       rx_desc = isert_conn->rx_descs;
 
        for (i = 0; i < ISERT_QP_MAX_RECV_DTOS; i++, rx_desc++)  {
                dma_addr = ib_dma_map_single(ib_dev, (void *)rx_desc,
@@ -198,21 +231,21 @@ isert_alloc_rx_descriptors(struct isert_conn *isert_conn)
                rx_sg = &rx_desc->rx_sg;
                rx_sg->addr = rx_desc->dma_addr;
                rx_sg->length = ISER_RX_PAYLOAD_SIZE;
-               rx_sg->lkey = isert_conn->conn_mr->lkey;
+               rx_sg->lkey = device->mr->lkey;
        }
 
-       isert_conn->conn_rx_desc_head = 0;
+       isert_conn->rx_desc_head = 0;
 
        return 0;
 
 dma_map_fail:
-       rx_desc = isert_conn->conn_rx_descs;
+       rx_desc = isert_conn->rx_descs;
        for (j = 0; j < i; j++, rx_desc++) {
                ib_dma_unmap_single(ib_dev, rx_desc->dma_addr,
                                    ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
        }
-       kfree(isert_conn->conn_rx_descs);
-       isert_conn->conn_rx_descs = NULL;
+       kfree(isert_conn->rx_descs);
+       isert_conn->rx_descs = NULL;
 fail:
        isert_err("conn %p failed to allocate rx descriptors\n", isert_conn);
 
@@ -222,59 +255,51 @@ fail:
 static void
 isert_free_rx_descriptors(struct isert_conn *isert_conn)
 {
-       struct ib_device *ib_dev = isert_conn->conn_cm_id->device;
+       struct ib_device *ib_dev = isert_conn->device->ib_device;
        struct iser_rx_desc *rx_desc;
        int i;
 
-       if (!isert_conn->conn_rx_descs)
+       if (!isert_conn->rx_descs)
                return;
 
-       rx_desc = isert_conn->conn_rx_descs;
+       rx_desc = isert_conn->rx_descs;
        for (i = 0; i < ISERT_QP_MAX_RECV_DTOS; i++, rx_desc++)  {
                ib_dma_unmap_single(ib_dev, rx_desc->dma_addr,
                                    ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
        }
 
-       kfree(isert_conn->conn_rx_descs);
-       isert_conn->conn_rx_descs = NULL;
+       kfree(isert_conn->rx_descs);
+       isert_conn->rx_descs = NULL;
 }
 
 static void isert_cq_work(struct work_struct *);
 static void isert_cq_callback(struct ib_cq *, void *);
 
-static int
-isert_create_device_ib_res(struct isert_device *device)
+static void
+isert_free_comps(struct isert_device *device)
 {
-       struct ib_device *ib_dev = device->ib_device;
-       struct ib_device_attr *dev_attr;
-       int ret = 0, i;
-       int max_cqe;
-
-       dev_attr = &device->dev_attr;
-       ret = isert_query_device(ib_dev, dev_attr);
-       if (ret)
-               return ret;
+       int i;
 
-       max_cqe = min(ISER_MAX_CQ_LEN, dev_attr->max_cqe);
+       for (i = 0; i < device->comps_used; i++) {
+               struct isert_comp *comp = &device->comps[i];
 
-       /* asign function handlers */
-       if (dev_attr->device_cap_flags & IB_DEVICE_MEM_MGT_EXTENSIONS &&
-           dev_attr->device_cap_flags & IB_DEVICE_SIGNATURE_HANDOVER) {
-               device->use_fastreg = 1;
-               device->reg_rdma_mem = isert_reg_rdma;
-               device->unreg_rdma_mem = isert_unreg_rdma;
-       } else {
-               device->use_fastreg = 0;
-               device->reg_rdma_mem = isert_map_rdma;
-               device->unreg_rdma_mem = isert_unmap_cmd;
+               if (comp->cq) {
+                       cancel_work_sync(&comp->work);
+                       ib_destroy_cq(comp->cq);
+               }
        }
+       kfree(device->comps);
+}
 
-       /* Check signature cap */
-       device->pi_capable = dev_attr->device_cap_flags &
-                            IB_DEVICE_SIGNATURE_HANDOVER ? true : false;
+static int
+isert_alloc_comps(struct isert_device *device,
+                 struct ib_device_attr *attr)
+{
+       int i, max_cqe, ret = 0;
 
        device->comps_used = min(ISERT_MAX_CQ, min_t(int, num_online_cpus(),
-                                       device->ib_device->num_comp_vectors));
+                                device->ib_device->num_comp_vectors));
+
        isert_info("Using %d CQs, %s supports %d vectors support "
                   "Fast registration %d pi_capable %d\n",
                   device->comps_used, device->ib_device->name,
@@ -288,6 +313,8 @@ isert_create_device_ib_res(struct isert_device *device)
                return -ENOMEM;
        }
 
+       max_cqe = min(ISER_MAX_CQ_LEN, attr->max_cqe);
+
        for (i = 0; i < device->comps_used; i++) {
                struct isert_comp *comp = &device->comps[i];
 
@@ -299,6 +326,7 @@ isert_create_device_ib_res(struct isert_device *device)
                                        (void *)comp,
                                        max_cqe, i);
                if (IS_ERR(comp->cq)) {
+                       isert_err("Unable to allocate cq\n");
                        ret = PTR_ERR(comp->cq);
                        comp->cq = NULL;
                        goto out_cq;
@@ -310,40 +338,79 @@ isert_create_device_ib_res(struct isert_device *device)
        }
 
        return 0;
-
 out_cq:
-       for (i = 0; i < device->comps_used; i++) {
-               struct isert_comp *comp = &device->comps[i];
+       isert_free_comps(device);
+       return ret;
+}
 
-               if (comp->cq) {
-                       cancel_work_sync(&comp->work);
-                       ib_destroy_cq(comp->cq);
-               }
+static int
+isert_create_device_ib_res(struct isert_device *device)
+{
+       struct ib_device_attr *dev_attr;
+       int ret;
+
+       dev_attr = &device->dev_attr;
+       ret = isert_query_device(device->ib_device, dev_attr);
+       if (ret)
+               return ret;
+
+       /* asign function handlers */
+       if (dev_attr->device_cap_flags & IB_DEVICE_MEM_MGT_EXTENSIONS &&
+           dev_attr->device_cap_flags & IB_DEVICE_SIGNATURE_HANDOVER) {
+               device->use_fastreg = 1;
+               device->reg_rdma_mem = isert_reg_rdma;
+               device->unreg_rdma_mem = isert_unreg_rdma;
+       } else {
+               device->use_fastreg = 0;
+               device->reg_rdma_mem = isert_map_rdma;
+               device->unreg_rdma_mem = isert_unmap_cmd;
        }
-       kfree(device->comps);
 
+       ret = isert_alloc_comps(device, dev_attr);
+       if (ret)
+               return ret;
+
+       device->pd = ib_alloc_pd(device->ib_device);
+       if (IS_ERR(device->pd)) {
+               ret = PTR_ERR(device->pd);
+               isert_err("failed to allocate pd, device %p, ret=%d\n",
+                         device, ret);
+               goto out_cq;
+       }
+
+       device->mr = ib_get_dma_mr(device->pd, IB_ACCESS_LOCAL_WRITE);
+       if (IS_ERR(device->mr)) {
+               ret = PTR_ERR(device->mr);
+               isert_err("failed to create dma mr, device %p, ret=%d\n",
+                         device, ret);
+               goto out_mr;
+       }
+
+       /* Check signature cap */
+       device->pi_capable = dev_attr->device_cap_flags &
+                            IB_DEVICE_SIGNATURE_HANDOVER ? true : false;
+
+       return 0;
+
+out_mr:
+       ib_dealloc_pd(device->pd);
+out_cq:
+       isert_free_comps(device);
        return ret;
 }
 
 static void
 isert_free_device_ib_res(struct isert_device *device)
 {
-       int i;
-
        isert_info("device %p\n", device);
 
-       for (i = 0; i < device->comps_used; i++) {
-               struct isert_comp *comp = &device->comps[i];
-
-               cancel_work_sync(&comp->work);
-               ib_destroy_cq(comp->cq);
-               comp->cq = NULL;
-       }
-       kfree(device->comps);
+       ib_dereg_mr(device->mr);
+       ib_dealloc_pd(device->pd);
+       isert_free_comps(device);
 }
 
 static void
-isert_device_try_release(struct isert_device *device)
+isert_device_put(struct isert_device *device)
 {
        mutex_lock(&device_list_mutex);
        device->refcount--;
@@ -357,7 +424,7 @@ isert_device_try_release(struct isert_device *device)
 }
 
 static struct isert_device *
-isert_device_find_by_ib_dev(struct rdma_cm_id *cma_id)
+isert_device_get(struct rdma_cm_id *cma_id)
 {
        struct isert_device *device;
        int ret;
@@ -404,13 +471,13 @@ isert_conn_free_fastreg_pool(struct isert_conn *isert_conn)
        struct fast_reg_descriptor *fr_desc, *tmp;
        int i = 0;
 
-       if (list_empty(&isert_conn->conn_fr_pool))
+       if (list_empty(&isert_conn->fr_pool))
                return;
 
        isert_info("Freeing conn %p fastreg pool", isert_conn);
 
        list_for_each_entry_safe(fr_desc, tmp,
-                                &isert_conn->conn_fr_pool, list) {
+                                &isert_conn->fr_pool, list) {
                list_del(&fr_desc->list);
                ib_free_fast_reg_page_list(fr_desc->data_frpl);
                ib_dereg_mr(fr_desc->data_mr);
@@ -424,9 +491,9 @@ isert_conn_free_fastreg_pool(struct isert_conn *isert_conn)
                ++i;
        }
 
-       if (i < isert_conn->conn_fr_pool_size)
+       if (i < isert_conn->fr_pool_size)
                isert_warn("Pool still has %d regions registered\n",
-                       isert_conn->conn_fr_pool_size - i);
+                       isert_conn->fr_pool_size - i);
 }
 
 static int
@@ -526,7 +593,7 @@ static int
 isert_conn_create_fastreg_pool(struct isert_conn *isert_conn)
 {
        struct fast_reg_descriptor *fr_desc;
-       struct isert_device *device = isert_conn->conn_device;
+       struct isert_device *device = isert_conn->device;
        struct se_session *se_sess = isert_conn->conn->sess->se_sess;
        struct se_node_acl *se_nacl = se_sess->se_node_acl;
        int i, ret, tag_num;
@@ -537,7 +604,7 @@ isert_conn_create_fastreg_pool(struct isert_conn *isert_conn)
        tag_num = max_t(u32, ISCSIT_MIN_TAGS, se_nacl->queue_depth);
        tag_num = (tag_num * 2) + ISCSIT_EXTRA_TAGS;
 
-       isert_conn->conn_fr_pool_size = 0;
+       isert_conn->fr_pool_size = 0;
        for (i = 0; i < tag_num; i++) {
                fr_desc = kzalloc(sizeof(*fr_desc), GFP_KERNEL);
                if (!fr_desc) {
@@ -547,7 +614,7 @@ isert_conn_create_fastreg_pool(struct isert_conn *isert_conn)
                }
 
                ret = isert_create_fr_desc(device->ib_device,
-                                          isert_conn->conn_pd, fr_desc);
+                                          device->pd, fr_desc);
                if (ret) {
                        isert_err("Failed to create fastreg descriptor err=%d\n",
                               ret);
@@ -555,12 +622,12 @@ isert_conn_create_fastreg_pool(struct isert_conn *isert_conn)
                        goto err;
                }
 
-               list_add_tail(&fr_desc->list, &isert_conn->conn_fr_pool);
-               isert_conn->conn_fr_pool_size++;
+               list_add_tail(&fr_desc->list, &isert_conn->fr_pool);
+               isert_conn->fr_pool_size++;
        }
 
        isert_dbg("Creating conn %p fastreg pool size=%d",
-                isert_conn, isert_conn->conn_fr_pool_size);
+                isert_conn, isert_conn->fr_pool_size);
 
        return 0;
 
@@ -569,55 +636,50 @@ err:
        return ret;
 }
 
-static int
-isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
+static void
+isert_init_conn(struct isert_conn *isert_conn)
 {
-       struct isert_np *isert_np = cma_id->context;
-       struct iscsi_np *np = isert_np->np;
-       struct isert_conn *isert_conn;
-       struct isert_device *device;
-       struct ib_device *ib_dev = cma_id->device;
-       int ret = 0;
-
-       spin_lock_bh(&np->np_thread_lock);
-       if (!np->enabled) {
-               spin_unlock_bh(&np->np_thread_lock);
-               isert_dbg("iscsi_np is not enabled, reject connect request\n");
-               return rdma_reject(cma_id, NULL, 0);
-       }
-       spin_unlock_bh(&np->np_thread_lock);
-
-       isert_dbg("cma_id: %p, portal: %p\n",
-                cma_id, cma_id->context);
-
-       isert_conn = kzalloc(sizeof(struct isert_conn), GFP_KERNEL);
-       if (!isert_conn) {
-               isert_err("Unable to allocate isert_conn\n");
-               return -ENOMEM;
-       }
        isert_conn->state = ISER_CONN_INIT;
-       INIT_LIST_HEAD(&isert_conn->conn_accept_node);
-       init_completion(&isert_conn->conn_login_comp);
+       INIT_LIST_HEAD(&isert_conn->accept_node);
+       init_completion(&isert_conn->login_comp);
        init_completion(&isert_conn->login_req_comp);
-       init_completion(&isert_conn->conn_wait);
-       kref_init(&isert_conn->conn_kref);
-       mutex_init(&isert_conn->conn_mutex);
-       spin_lock_init(&isert_conn->conn_lock);
-       INIT_LIST_HEAD(&isert_conn->conn_fr_pool);
+       init_completion(&isert_conn->wait);
+       kref_init(&isert_conn->kref);
+       mutex_init(&isert_conn->mutex);
+       spin_lock_init(&isert_conn->pool_lock);
+       INIT_LIST_HEAD(&isert_conn->fr_pool);
+}
+
+static void
+isert_free_login_buf(struct isert_conn *isert_conn)
+{
+       struct ib_device *ib_dev = isert_conn->device->ib_device;
 
-       isert_conn->conn_cm_id = cma_id;
+       ib_dma_unmap_single(ib_dev, isert_conn->login_rsp_dma,
+                           ISER_RX_LOGIN_SIZE, DMA_TO_DEVICE);
+       ib_dma_unmap_single(ib_dev, isert_conn->login_req_dma,
+                           ISCSI_DEF_MAX_RECV_SEG_LEN,
+                           DMA_FROM_DEVICE);
+       kfree(isert_conn->login_buf);
+}
+
+static int
+isert_alloc_login_buf(struct isert_conn *isert_conn,
+                     struct ib_device *ib_dev)
+{
+       int ret;
 
        isert_conn->login_buf = kzalloc(ISCSI_DEF_MAX_RECV_SEG_LEN +
                                        ISER_RX_LOGIN_SIZE, GFP_KERNEL);
        if (!isert_conn->login_buf) {
                isert_err("Unable to allocate isert_conn->login_buf\n");
-               ret = -ENOMEM;
-               goto out;
+               return -ENOMEM;
        }
 
        isert_conn->login_req_buf = isert_conn->login_buf;
        isert_conn->login_rsp_buf = isert_conn->login_buf +
                                    ISCSI_DEF_MAX_RECV_SEG_LEN;
+
        isert_dbg("Set login_buf: %p login_req_buf: %p login_rsp_buf: %p\n",
                 isert_conn->login_buf, isert_conn->login_req_buf,
                 isert_conn->login_rsp_buf);
@@ -628,8 +690,7 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
 
        ret = ib_dma_mapping_error(ib_dev, isert_conn->login_req_dma);
        if (ret) {
-               isert_err("ib_dma_mapping_error failed for login_req_dma: %d\n",
-                      ret);
+               isert_err("login_req_dma mapping error: %d\n", ret);
                isert_conn->login_req_dma = 0;
                goto out_login_buf;
        }
@@ -640,17 +701,58 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
 
        ret = ib_dma_mapping_error(ib_dev, isert_conn->login_rsp_dma);
        if (ret) {
-               isert_err("ib_dma_mapping_error failed for login_rsp_dma: %d\n",
-                      ret);
+               isert_err("login_rsp_dma mapping error: %d\n", ret);
                isert_conn->login_rsp_dma = 0;
                goto out_req_dma_map;
        }
 
-       device = isert_device_find_by_ib_dev(cma_id);
+       return 0;
+
+out_req_dma_map:
+       ib_dma_unmap_single(ib_dev, isert_conn->login_req_dma,
+                           ISCSI_DEF_MAX_RECV_SEG_LEN, DMA_FROM_DEVICE);
+out_login_buf:
+       kfree(isert_conn->login_buf);
+       return ret;
+}
+
+static int
+isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
+{
+       struct isert_np *isert_np = cma_id->context;
+       struct iscsi_np *np = isert_np->np;
+       struct isert_conn *isert_conn;
+       struct isert_device *device;
+       int ret = 0;
+
+       spin_lock_bh(&np->np_thread_lock);
+       if (!np->enabled) {
+               spin_unlock_bh(&np->np_thread_lock);
+               isert_dbg("iscsi_np is not enabled, reject connect request\n");
+               return rdma_reject(cma_id, NULL, 0);
+       }
+       spin_unlock_bh(&np->np_thread_lock);
+
+       isert_dbg("cma_id: %p, portal: %p\n",
+                cma_id, cma_id->context);
+
+       isert_conn = kzalloc(sizeof(struct isert_conn), GFP_KERNEL);
+       if (!isert_conn)
+               return -ENOMEM;
+
+       isert_init_conn(isert_conn);
+       isert_conn->cm_id = cma_id;
+
+       ret = isert_alloc_login_buf(isert_conn, cma_id->device);
+       if (ret)
+               goto out;
+
+       device = isert_device_get(cma_id);
        if (IS_ERR(device)) {
                ret = PTR_ERR(device);
                goto out_rsp_dma_map;
        }
+       isert_conn->device = device;
 
        /* Set max inflight RDMA READ requests */
        isert_conn->initiator_depth = min_t(u8,
@@ -658,24 +760,6 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
                                device->dev_attr.max_qp_init_rd_atom);
        isert_dbg("Using initiator_depth: %u\n", isert_conn->initiator_depth);
 
-       isert_conn->conn_device = device;
-       isert_conn->conn_pd = ib_alloc_pd(isert_conn->conn_device->ib_device);
-       if (IS_ERR(isert_conn->conn_pd)) {
-               ret = PTR_ERR(isert_conn->conn_pd);
-               isert_err("ib_alloc_pd failed for conn %p: ret=%d\n",
-                      isert_conn, ret);
-               goto out_pd;
-       }
-
-       isert_conn->conn_mr = ib_get_dma_mr(isert_conn->conn_pd,
-                                          IB_ACCESS_LOCAL_WRITE);
-       if (IS_ERR(isert_conn->conn_mr)) {
-               ret = PTR_ERR(isert_conn->conn_mr);
-               isert_err("ib_get_dma_mr failed for conn %p: ret=%d\n",
-                      isert_conn, ret);
-               goto out_mr;
-       }
-
        ret = isert_conn_setup_qp(isert_conn, cma_id);
        if (ret)
                goto out_conn_dev;
@@ -689,7 +773,7 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
                goto out_conn_dev;
 
        mutex_lock(&isert_np->np_accept_mutex);
-       list_add_tail(&isert_conn->conn_accept_node, &isert_np->np_accept_list);
+       list_add_tail(&isert_conn->accept_node, &isert_np->np_accept_list);
        mutex_unlock(&isert_np->np_accept_mutex);
 
        isert_info("np %p: Allow accept_np to continue\n", np);
@@ -697,19 +781,9 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
        return 0;
 
 out_conn_dev:
-       ib_dereg_mr(isert_conn->conn_mr);
-out_mr:
-       ib_dealloc_pd(isert_conn->conn_pd);
-out_pd:
-       isert_device_try_release(device);
+       isert_device_put(device);
 out_rsp_dma_map:
-       ib_dma_unmap_single(ib_dev, isert_conn->login_rsp_dma,
-                           ISER_RX_LOGIN_SIZE, DMA_TO_DEVICE);
-out_req_dma_map:
-       ib_dma_unmap_single(ib_dev, isert_conn->login_req_dma,
-                           ISCSI_DEF_MAX_RECV_SEG_LEN, DMA_FROM_DEVICE);
-out_login_buf:
-       kfree(isert_conn->login_buf);
+       isert_free_login_buf(isert_conn);
 out:
        kfree(isert_conn);
        rdma_reject(cma_id, NULL, 0);
@@ -719,43 +793,32 @@ out:
 static void
 isert_connect_release(struct isert_conn *isert_conn)
 {
-       struct ib_device *ib_dev = isert_conn->conn_cm_id->device;
-       struct isert_device *device = isert_conn->conn_device;
+       struct isert_device *device = isert_conn->device;
 
        isert_dbg("conn %p\n", isert_conn);
 
-       if (device && device->use_fastreg)
+       BUG_ON(!device);
+
+       if (device->use_fastreg)
                isert_conn_free_fastreg_pool(isert_conn);
 
        isert_free_rx_descriptors(isert_conn);
-       rdma_destroy_id(isert_conn->conn_cm_id);
+       if (isert_conn->cm_id)
+               rdma_destroy_id(isert_conn->cm_id);
 
-       if (isert_conn->conn_qp) {
-               struct isert_comp *comp = isert_conn->conn_qp->recv_cq->cq_context;
+       if (isert_conn->qp) {
+               struct isert_comp *comp = isert_conn->qp->recv_cq->cq_context;
 
-               isert_dbg("dec completion context %p active_qps\n", comp);
-               mutex_lock(&device_list_mutex);
-               comp->active_qps--;
-               mutex_unlock(&device_list_mutex);
-
-               ib_destroy_qp(isert_conn->conn_qp);
+               isert_comp_put(comp);
+               ib_destroy_qp(isert_conn->qp);
        }
 
-       ib_dereg_mr(isert_conn->conn_mr);
-       ib_dealloc_pd(isert_conn->conn_pd);
+       if (isert_conn->login_buf)
+               isert_free_login_buf(isert_conn);
 
-       if (isert_conn->login_buf) {
-               ib_dma_unmap_single(ib_dev, isert_conn->login_rsp_dma,
-                                   ISER_RX_LOGIN_SIZE, DMA_TO_DEVICE);
-               ib_dma_unmap_single(ib_dev, isert_conn->login_req_dma,
-                                   ISCSI_DEF_MAX_RECV_SEG_LEN,
-                                   DMA_FROM_DEVICE);
-               kfree(isert_conn->login_buf);
-       }
-       kfree(isert_conn);
+       isert_device_put(device);
 
-       if (device)
-               isert_device_try_release(device);
+       kfree(isert_conn);
 }
 
 static void
@@ -765,22 +828,22 @@ isert_connected_handler(struct rdma_cm_id *cma_id)
 
        isert_info("conn %p\n", isert_conn);
 
-       if (!kref_get_unless_zero(&isert_conn->conn_kref)) {
+       if (!kref_get_unless_zero(&isert_conn->kref)) {
                isert_warn("conn %p connect_release is running\n", isert_conn);
                return;
        }
 
-       mutex_lock(&isert_conn->conn_mutex);
+       mutex_lock(&isert_conn->mutex);
        if (isert_conn->state != ISER_CONN_FULL_FEATURE)
                isert_conn->state = ISER_CONN_UP;
-       mutex_unlock(&isert_conn->conn_mutex);
+       mutex_unlock(&isert_conn->mutex);
 }
 
 static void
-isert_release_conn_kref(struct kref *kref)
+isert_release_kref(struct kref *kref)
 {
        struct isert_conn *isert_conn = container_of(kref,
-                               struct isert_conn, conn_kref);
+                               struct isert_conn, kref);
 
        isert_info("conn %p final kref %s/%d\n", isert_conn, current->comm,
                   current->pid);
@@ -791,7 +854,7 @@ isert_release_conn_kref(struct kref *kref)
 static void
 isert_put_conn(struct isert_conn *isert_conn)
 {
-       kref_put(&isert_conn->conn_kref, isert_release_conn_kref);
+       kref_put(&isert_conn->kref, isert_release_kref);
 }
 
 /**
@@ -803,7 +866,7 @@ isert_put_conn(struct isert_conn *isert_conn)
  * to TEMINATING and start teardown sequence (rdma_disconnect).
  * In case the connection state is UP, complete flush as well.
  *
- * This routine must be called with conn_mutex held. Thus it is
+ * This routine must be called with mutex held. Thus it is
  * safe to call multiple times.
  */
 static void
@@ -819,7 +882,7 @@ isert_conn_terminate(struct isert_conn *isert_conn)
                isert_info("Terminating conn %p state %d\n",
                           isert_conn, isert_conn->state);
                isert_conn->state = ISER_CONN_TERMINATING;
-               err = rdma_disconnect(isert_conn->conn_cm_id);
+               err = rdma_disconnect(isert_conn->cm_id);
                if (err)
                        isert_warn("Failed rdma_disconnect isert_conn %p\n",
                                   isert_conn);
@@ -868,22 +931,25 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id,
 
        isert_conn = cma_id->qp->qp_context;
 
-       mutex_lock(&isert_conn->conn_mutex);
+       mutex_lock(&isert_conn->mutex);
        isert_conn_terminate(isert_conn);
-       mutex_unlock(&isert_conn->conn_mutex);
+       mutex_unlock(&isert_conn->mutex);
 
-       isert_info("conn %p completing conn_wait\n", isert_conn);
-       complete(&isert_conn->conn_wait);
+       isert_info("conn %p completing wait\n", isert_conn);
+       complete(&isert_conn->wait);
 
        return 0;
 }
 
-static void
+static int
 isert_connect_error(struct rdma_cm_id *cma_id)
 {
        struct isert_conn *isert_conn = cma_id->qp->qp_context;
 
+       isert_conn->cm_id = NULL;
        isert_put_conn(isert_conn);
+
+       return -1;
 }
 
 static int
@@ -912,7 +978,7 @@ isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
        case RDMA_CM_EVENT_REJECTED:       /* FALLTHRU */
        case RDMA_CM_EVENT_UNREACHABLE:    /* FALLTHRU */
        case RDMA_CM_EVENT_CONNECT_ERROR:
-               isert_connect_error(cma_id);
+               ret = isert_connect_error(cma_id);
                break;
        default:
                isert_err("Unhandled RDMA CMA event: %d\n", event->event);
@@ -927,11 +993,11 @@ isert_post_recv(struct isert_conn *isert_conn, u32 count)
 {
        struct ib_recv_wr *rx_wr, *rx_wr_failed;
        int i, ret;
-       unsigned int rx_head = isert_conn->conn_rx_desc_head;
+       unsigned int rx_head = isert_conn->rx_desc_head;
        struct iser_rx_desc *rx_desc;
 
-       for (rx_wr = isert_conn->conn_rx_wr, i = 0; i < count; i++, rx_wr++) {
-               rx_desc         = &isert_conn->conn_rx_descs[rx_head];
+       for (rx_wr = isert_conn->rx_wr, i = 0; i < count; i++, rx_wr++) {
+               rx_desc         = &isert_conn->rx_descs[rx_head];
                rx_wr->wr_id    = (uintptr_t)rx_desc;
                rx_wr->sg_list  = &rx_desc->rx_sg;
                rx_wr->num_sge  = 1;
@@ -943,14 +1009,14 @@ isert_post_recv(struct isert_conn *isert_conn, u32 count)
        rx_wr->next = NULL; /* mark end of work requests list */
 
        isert_conn->post_recv_buf_count += count;
-       ret = ib_post_recv(isert_conn->conn_qp, isert_conn->conn_rx_wr,
+       ret = ib_post_recv(isert_conn->qp, isert_conn->rx_wr,
                                &rx_wr_failed);
        if (ret) {
                isert_err("ib_post_recv() failed with ret: %d\n", ret);
                isert_conn->post_recv_buf_count -= count;
        } else {
                isert_dbg("Posted %d RX buffers\n", count);
-               isert_conn->conn_rx_desc_head = rx_head;
+               isert_conn->rx_desc_head = rx_head;
        }
        return ret;
 }
@@ -958,7 +1024,7 @@ isert_post_recv(struct isert_conn *isert_conn, u32 count)
 static int
 isert_post_send(struct isert_conn *isert_conn, struct iser_tx_desc *tx_desc)
 {
-       struct ib_device *ib_dev = isert_conn->conn_cm_id->device;
+       struct ib_device *ib_dev = isert_conn->cm_id->device;
        struct ib_send_wr send_wr, *send_wr_failed;
        int ret;
 
@@ -972,7 +1038,7 @@ isert_post_send(struct isert_conn *isert_conn, struct iser_tx_desc *tx_desc)
        send_wr.opcode  = IB_WR_SEND;
        send_wr.send_flags = IB_SEND_SIGNALED;
 
-       ret = ib_post_send(isert_conn->conn_qp, &send_wr, &send_wr_failed);
+       ret = ib_post_send(isert_conn->qp, &send_wr, &send_wr_failed);
        if (ret)
                isert_err("ib_post_send() failed, ret: %d\n", ret);
 
@@ -984,7 +1050,8 @@ isert_create_send_desc(struct isert_conn *isert_conn,
                       struct isert_cmd *isert_cmd,
                       struct iser_tx_desc *tx_desc)
 {
-       struct ib_device *ib_dev = isert_conn->conn_cm_id->device;
+       struct isert_device *device = isert_conn->device;
+       struct ib_device *ib_dev = device->ib_device;
 
        ib_dma_sync_single_for_cpu(ib_dev, tx_desc->dma_addr,
                                   ISER_HEADERS_LEN, DMA_TO_DEVICE);
@@ -995,8 +1062,8 @@ isert_create_send_desc(struct isert_conn *isert_conn,
        tx_desc->num_sge = 1;
        tx_desc->isert_cmd = isert_cmd;
 
-       if (tx_desc->tx_sg[0].lkey != isert_conn->conn_mr->lkey) {
-               tx_desc->tx_sg[0].lkey = isert_conn->conn_mr->lkey;
+       if (tx_desc->tx_sg[0].lkey != device->mr->lkey) {
+               tx_desc->tx_sg[0].lkey = device->mr->lkey;
                isert_dbg("tx_desc %p lkey mismatch, fixing\n", tx_desc);
        }
 }
@@ -1005,7 +1072,8 @@ static int
 isert_init_tx_hdrs(struct isert_conn *isert_conn,
                   struct iser_tx_desc *tx_desc)
 {
-       struct ib_device *ib_dev = isert_conn->conn_cm_id->device;
+       struct isert_device *device = isert_conn->device;
+       struct ib_device *ib_dev = device->ib_device;
        u64 dma_addr;
 
        dma_addr = ib_dma_map_single(ib_dev, (void *)tx_desc,
@@ -1018,7 +1086,7 @@ isert_init_tx_hdrs(struct isert_conn *isert_conn,
        tx_desc->dma_addr = dma_addr;
        tx_desc->tx_sg[0].addr  = tx_desc->dma_addr;
        tx_desc->tx_sg[0].length = ISER_HEADERS_LEN;
-       tx_desc->tx_sg[0].lkey = isert_conn->conn_mr->lkey;
+       tx_desc->tx_sg[0].lkey = device->mr->lkey;
 
        isert_dbg("Setup tx_sg[0].addr: 0x%llx length: %u lkey: 0x%x\n",
                  tx_desc->tx_sg[0].addr, tx_desc->tx_sg[0].length,
@@ -1051,7 +1119,7 @@ isert_rdma_post_recvl(struct isert_conn *isert_conn)
        memset(&sge, 0, sizeof(struct ib_sge));
        sge.addr = isert_conn->login_req_dma;
        sge.length = ISER_RX_LOGIN_SIZE;
-       sge.lkey = isert_conn->conn_mr->lkey;
+       sge.lkey = isert_conn->device->mr->lkey;
 
        isert_dbg("Setup sge: addr: %llx length: %d 0x%08x\n",
                sge.addr, sge.length, sge.lkey);
@@ -1062,7 +1130,7 @@ isert_rdma_post_recvl(struct isert_conn *isert_conn)
        rx_wr.num_sge = 1;
 
        isert_conn->post_recv_buf_count++;
-       ret = ib_post_recv(isert_conn->conn_qp, &rx_wr, &rx_wr_fail);
+       ret = ib_post_recv(isert_conn->qp, &rx_wr, &rx_wr_fail);
        if (ret) {
                isert_err("ib_post_recv() failed: %d\n", ret);
                isert_conn->post_recv_buf_count--;
@@ -1076,8 +1144,9 @@ isert_put_login_tx(struct iscsi_conn *conn, struct iscsi_login *login,
                   u32 length)
 {
        struct isert_conn *isert_conn = conn->context;
-       struct ib_device *ib_dev = isert_conn->conn_cm_id->device;
-       struct iser_tx_desc *tx_desc = &isert_conn->conn_login_tx_desc;
+       struct isert_device *device = isert_conn->device;
+       struct ib_device *ib_dev = device->ib_device;
+       struct iser_tx_desc *tx_desc = &isert_conn->login_tx_desc;
        int ret;
 
        isert_create_send_desc(isert_conn, NULL, tx_desc);
@@ -1100,13 +1169,13 @@ isert_put_login_tx(struct iscsi_conn *conn, struct iscsi_login *login,
 
                tx_dsg->addr    = isert_conn->login_rsp_dma;
                tx_dsg->length  = length;
-               tx_dsg->lkey    = isert_conn->conn_mr->lkey;
+               tx_dsg->lkey    = isert_conn->device->mr->lkey;
                tx_desc->num_sge = 2;
        }
        if (!login->login_failed) {
                if (login->login_complete) {
                        if (!conn->sess->sess_ops->SessionType &&
-                           isert_conn->conn_device->use_fastreg) {
+                           isert_conn->device->use_fastreg) {
                                ret = isert_conn_create_fastreg_pool(isert_conn);
                                if (ret) {
                                        isert_err("Conn: %p failed to create"
@@ -1124,9 +1193,9 @@ isert_put_login_tx(struct iscsi_conn *conn, struct iscsi_login *login,
                                return ret;
 
                        /* Now we are in FULL_FEATURE phase */
-                       mutex_lock(&isert_conn->conn_mutex);
+                       mutex_lock(&isert_conn->mutex);
                        isert_conn->state = ISER_CONN_FULL_FEATURE;
-                       mutex_unlock(&isert_conn->conn_mutex);
+                       mutex_unlock(&isert_conn->mutex);
                        goto post_send;
                }
 
@@ -1185,7 +1254,7 @@ isert_rx_login_req(struct isert_conn *isert_conn)
        memcpy(login->req_buf, &rx_desc->data[0], size);
 
        if (login->first_request) {
-               complete(&isert_conn->conn_login_comp);
+               complete(&isert_conn->login_comp);
                return;
        }
        schedule_delayed_work(&conn->login_work, 0);
@@ -1194,7 +1263,7 @@ isert_rx_login_req(struct isert_conn *isert_conn)
 static struct iscsi_cmd
 *isert_allocate_cmd(struct iscsi_conn *conn)
 {
-       struct isert_conn *isert_conn = (struct isert_conn *)conn->context;
+       struct isert_conn *isert_conn = conn->context;
        struct isert_cmd *isert_cmd;
        struct iscsi_cmd *cmd;
 
@@ -1379,13 +1448,12 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc,
 {
        struct iscsi_hdr *hdr = &rx_desc->iscsi_header;
        struct iscsi_conn *conn = isert_conn->conn;
-       struct iscsi_session *sess = conn->sess;
        struct iscsi_cmd *cmd;
        struct isert_cmd *isert_cmd;
        int ret = -EINVAL;
        u8 opcode = (hdr->opcode & ISCSI_OPCODE_MASK);
 
-       if (sess->sess_ops->SessionType &&
+       if (conn->sess->sess_ops->SessionType &&
           (!(opcode & ISCSI_OP_TEXT) || !(opcode & ISCSI_OP_LOGOUT))) {
                isert_err("Got illegal opcode: 0x%02x in SessionType=Discovery,"
                          " ignoring\n", opcode);
@@ -1497,10 +1565,11 @@ isert_rx_do_work(struct iser_rx_desc *rx_desc, struct isert_conn *isert_conn)
 }
 
 static void
-isert_rx_completion(struct iser_rx_desc *desc, struct isert_conn *isert_conn,
-                   u32 xfer_len)
+isert_rcv_completion(struct iser_rx_desc *desc,
+                    struct isert_conn *isert_conn,
+                    u32 xfer_len)
 {
-       struct ib_device *ib_dev = isert_conn->conn_cm_id->device;
+       struct ib_device *ib_dev = isert_conn->cm_id->device;
        struct iscsi_hdr *hdr;
        u64 rx_dma;
        int rx_buflen, outstanding;
@@ -1532,9 +1601,9 @@ isert_rx_completion(struct iser_rx_desc *desc, struct isert_conn *isert_conn,
                        if (login && !login->first_request)
                                isert_rx_login_req(isert_conn);
                }
-               mutex_lock(&isert_conn->conn_mutex);
+               mutex_lock(&isert_conn->mutex);
                complete(&isert_conn->login_req_comp);
-               mutex_unlock(&isert_conn->conn_mutex);
+               mutex_unlock(&isert_conn->mutex);
        } else {
                isert_rx_do_work(desc, isert_conn);
        }
@@ -1566,7 +1635,7 @@ isert_map_data_buf(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd,
                   struct scatterlist *sg, u32 nents, u32 length, u32 offset,
                   enum iser_ib_op_code op, struct isert_data_buf *data)
 {
-       struct ib_device *ib_dev = isert_conn->conn_cm_id->device;
+       struct ib_device *ib_dev = isert_conn->cm_id->device;
 
        data->dma_dir = op == ISER_IB_RDMA_WRITE ?
                              DMA_TO_DEVICE : DMA_FROM_DEVICE;
@@ -1597,7 +1666,7 @@ isert_map_data_buf(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd,
 static void
 isert_unmap_data_buf(struct isert_conn *isert_conn, struct isert_data_buf *data)
 {
-       struct ib_device *ib_dev = isert_conn->conn_cm_id->device;
+       struct ib_device *ib_dev = isert_conn->cm_id->device;
 
        ib_dma_unmap_sg(ib_dev, data->sg, data->nents, data->dma_dir);
        memset(data, 0, sizeof(*data));
@@ -1634,7 +1703,6 @@ static void
 isert_unreg_rdma(struct isert_cmd *isert_cmd, struct isert_conn *isert_conn)
 {
        struct isert_rdma_wr *wr = &isert_cmd->rdma_wr;
-       LIST_HEAD(unmap_list);
 
        isert_dbg("Cmd %p\n", isert_cmd);
 
@@ -1644,9 +1712,9 @@ isert_unreg_rdma(struct isert_cmd *isert_cmd, struct isert_conn *isert_conn)
                        isert_unmap_data_buf(isert_conn, &wr->prot);
                        wr->fr_desc->ind &= ~ISERT_PROTECTED;
                }
-               spin_lock_bh(&isert_conn->conn_lock);
-               list_add_tail(&wr->fr_desc->list, &isert_conn->conn_fr_pool);
-               spin_unlock_bh(&isert_conn->conn_lock);
+               spin_lock_bh(&isert_conn->pool_lock);
+               list_add_tail(&wr->fr_desc->list, &isert_conn->fr_pool);
+               spin_unlock_bh(&isert_conn->pool_lock);
                wr->fr_desc = NULL;
        }
 
@@ -1665,7 +1733,7 @@ isert_put_cmd(struct isert_cmd *isert_cmd, bool comp_err)
        struct iscsi_cmd *cmd = isert_cmd->iscsi_cmd;
        struct isert_conn *isert_conn = isert_cmd->conn;
        struct iscsi_conn *conn = isert_conn->conn;
-       struct isert_device *device = isert_conn->conn_device;
+       struct isert_device *device = isert_conn->device;
        struct iscsi_text_rsp *hdr;
 
        isert_dbg("Cmd %p\n", isert_cmd);
@@ -1815,7 +1883,7 @@ isert_completion_rdma_write(struct iser_tx_desc *tx_desc,
        struct iscsi_cmd *cmd = isert_cmd->iscsi_cmd;
        struct se_cmd *se_cmd = &cmd->se_cmd;
        struct isert_conn *isert_conn = isert_cmd->conn;
-       struct isert_device *device = isert_conn->conn_device;
+       struct isert_device *device = isert_conn->device;
        int ret = 0;
 
        if (wr->fr_desc && wr->fr_desc->ind & ISERT_PROTECTED) {
@@ -1841,7 +1909,7 @@ isert_completion_rdma_read(struct iser_tx_desc *tx_desc,
        struct iscsi_cmd *cmd = isert_cmd->iscsi_cmd;
        struct se_cmd *se_cmd = &cmd->se_cmd;
        struct isert_conn *isert_conn = isert_cmd->conn;
-       struct isert_device *device = isert_conn->conn_device;
+       struct isert_device *device = isert_conn->device;
        int ret = 0;
 
        if (wr->fr_desc && wr->fr_desc->ind & ISERT_PROTECTED) {
@@ -1861,11 +1929,13 @@ isert_completion_rdma_read(struct iser_tx_desc *tx_desc,
        cmd->i_state = ISTATE_RECEIVED_LAST_DATAOUT;
        spin_unlock_bh(&cmd->istate_lock);
 
-       if (ret)
+       if (ret) {
+               target_put_sess_cmd(se_cmd->se_sess, se_cmd);
                transport_send_check_condition_and_sense(se_cmd,
                                                         se_cmd->pi_err, 0);
-       else
+       } else {
                target_execute_cmd(se_cmd);
+       }
 }
 
 static void
@@ -1874,7 +1944,7 @@ isert_do_control_comp(struct work_struct *work)
        struct isert_cmd *isert_cmd = container_of(work,
                        struct isert_cmd, comp_work);
        struct isert_conn *isert_conn = isert_cmd->conn;
-       struct ib_device *ib_dev = isert_conn->conn_cm_id->device;
+       struct ib_device *ib_dev = isert_conn->cm_id->device;
        struct iscsi_cmd *cmd = isert_cmd->iscsi_cmd;
 
        isert_dbg("Cmd %p i_state %d\n", isert_cmd, cmd->i_state);
@@ -1922,10 +1992,10 @@ isert_response_completion(struct iser_tx_desc *tx_desc,
 }
 
 static void
-isert_send_completion(struct iser_tx_desc *tx_desc,
+isert_snd_completion(struct iser_tx_desc *tx_desc,
                      struct isert_conn *isert_conn)
 {
-       struct ib_device *ib_dev = isert_conn->conn_cm_id->device;
+       struct ib_device *ib_dev = isert_conn->cm_id->device;
        struct isert_cmd *isert_cmd = tx_desc->isert_cmd;
        struct isert_rdma_wr *wr;
 
@@ -1938,10 +2008,6 @@ isert_send_completion(struct iser_tx_desc *tx_desc,
        isert_dbg("Cmd %p iser_ib_op %d\n", isert_cmd, wr->iser_ib_op);
 
        switch (wr->iser_ib_op) {
-       case ISER_IB_RECV:
-               isert_err("Got ISER_IB_RECV\n");
-               dump_stack();
-               break;
        case ISER_IB_SEND:
                isert_response_completion(tx_desc, isert_cmd,
                                          isert_conn, ib_dev);
@@ -1973,8 +2039,8 @@ isert_send_completion(struct iser_tx_desc *tx_desc,
 static inline bool
 is_isert_tx_desc(struct isert_conn *isert_conn, void *wr_id)
 {
-       void *start = isert_conn->conn_rx_descs;
-       int len = ISERT_QP_MAX_RECV_DTOS * sizeof(*isert_conn->conn_rx_descs);
+       void *start = isert_conn->rx_descs;
+       int len = ISERT_QP_MAX_RECV_DTOS * sizeof(*isert_conn->rx_descs);
 
        if (wr_id >= start && wr_id < start + len)
                return false;
@@ -1986,11 +2052,11 @@ static void
 isert_cq_comp_err(struct isert_conn *isert_conn, struct ib_wc *wc)
 {
        if (wc->wr_id == ISER_BEACON_WRID) {
-               isert_info("conn %p completing conn_wait_comp_err\n",
+               isert_info("conn %p completing wait_comp_err\n",
                           isert_conn);
-               complete(&isert_conn->conn_wait_comp_err);
+               complete(&isert_conn->wait_comp_err);
        } else if (is_isert_tx_desc(isert_conn, (void *)(uintptr_t)wc->wr_id)) {
-               struct ib_device *ib_dev = isert_conn->conn_cm_id->device;
+               struct ib_device *ib_dev = isert_conn->cm_id->device;
                struct isert_cmd *isert_cmd;
                struct iser_tx_desc *desc;
 
@@ -2018,10 +2084,10 @@ isert_handle_wc(struct ib_wc *wc)
        if (likely(wc->status == IB_WC_SUCCESS)) {
                if (wc->opcode == IB_WC_RECV) {
                        rx_desc = (struct iser_rx_desc *)(uintptr_t)wc->wr_id;
-                       isert_rx_completion(rx_desc, isert_conn, wc->byte_len);
+                       isert_rcv_completion(rx_desc, isert_conn, wc->byte_len);
                } else {
                        tx_desc = (struct iser_tx_desc *)(uintptr_t)wc->wr_id;
-                       isert_send_completion(tx_desc, isert_conn);
+                       isert_snd_completion(tx_desc, isert_conn);
                }
        } else {
                if (wc->status != IB_WC_WR_FLUSH_ERR)
@@ -2070,7 +2136,7 @@ isert_post_response(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd)
        struct ib_send_wr *wr_failed;
        int ret;
 
-       ret = ib_post_send(isert_conn->conn_qp, &isert_cmd->tx_desc.send_wr,
+       ret = ib_post_send(isert_conn->qp, &isert_cmd->tx_desc.send_wr,
                           &wr_failed);
        if (ret) {
                isert_err("ib_post_send failed with %d\n", ret);
@@ -2083,7 +2149,7 @@ static int
 isert_put_response(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
 {
        struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd);
-       struct isert_conn *isert_conn = (struct isert_conn *)conn->context;
+       struct isert_conn *isert_conn = conn->context;
        struct ib_send_wr *send_wr = &isert_cmd->tx_desc.send_wr;
        struct iscsi_scsi_rsp *hdr = (struct iscsi_scsi_rsp *)
                                &isert_cmd->tx_desc.iscsi_header;
@@ -2097,7 +2163,8 @@ isert_put_response(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
        if (cmd->se_cmd.sense_buffer &&
            ((cmd->se_cmd.se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) ||
            (cmd->se_cmd.se_cmd_flags & SCF_EMULATED_TASK_SENSE))) {
-               struct ib_device *ib_dev = isert_conn->conn_cm_id->device;
+               struct isert_device *device = isert_conn->device;
+               struct ib_device *ib_dev = device->ib_device;
                struct ib_sge *tx_dsg = &isert_cmd->tx_desc.tx_sg[1];
                u32 padding, pdu_len;
 
@@ -2116,7 +2183,7 @@ isert_put_response(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
                isert_cmd->pdu_buf_len = pdu_len;
                tx_dsg->addr    = isert_cmd->pdu_buf_dma;
                tx_dsg->length  = pdu_len;
-               tx_dsg->lkey    = isert_conn->conn_mr->lkey;
+               tx_dsg->lkey    = device->mr->lkey;
                isert_cmd->tx_desc.num_sge = 2;
        }
 
@@ -2131,8 +2198,8 @@ static void
 isert_aborted_task(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
 {
        struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd);
-       struct isert_conn *isert_conn = (struct isert_conn *)conn->context;
-       struct isert_device *device = isert_conn->conn_device;
+       struct isert_conn *isert_conn = conn->context;
+       struct isert_device *device = isert_conn->device;
 
        spin_lock_bh(&conn->cmd_lock);
        if (!list_empty(&cmd->i_conn_node))
@@ -2148,8 +2215,8 @@ isert_aborted_task(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
 static enum target_prot_op
 isert_get_sup_prot_ops(struct iscsi_conn *conn)
 {
-       struct isert_conn *isert_conn = (struct isert_conn *)conn->context;
-       struct isert_device *device = isert_conn->conn_device;
+       struct isert_conn *isert_conn = conn->context;
+       struct isert_device *device = isert_conn->device;
 
        if (conn->tpg->tpg_attrib.t10_pi) {
                if (device->pi_capable) {
@@ -2170,7 +2237,7 @@ isert_put_nopin(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
                bool nopout_response)
 {
        struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd);
-       struct isert_conn *isert_conn = (struct isert_conn *)conn->context;
+       struct isert_conn *isert_conn = conn->context;
        struct ib_send_wr *send_wr = &isert_cmd->tx_desc.send_wr;
 
        isert_create_send_desc(isert_conn, isert_cmd, &isert_cmd->tx_desc);
@@ -2189,7 +2256,7 @@ static int
 isert_put_logout_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
 {
        struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd);
-       struct isert_conn *isert_conn = (struct isert_conn *)conn->context;
+       struct isert_conn *isert_conn = conn->context;
        struct ib_send_wr *send_wr = &isert_cmd->tx_desc.send_wr;
 
        isert_create_send_desc(isert_conn, isert_cmd, &isert_cmd->tx_desc);
@@ -2207,7 +2274,7 @@ static int
 isert_put_tm_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
 {
        struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd);
-       struct isert_conn *isert_conn = (struct isert_conn *)conn->context;
+       struct isert_conn *isert_conn = conn->context;
        struct ib_send_wr *send_wr = &isert_cmd->tx_desc.send_wr;
 
        isert_create_send_desc(isert_conn, isert_cmd, &isert_cmd->tx_desc);
@@ -2225,9 +2292,10 @@ static int
 isert_put_reject(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
 {
        struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd);
-       struct isert_conn *isert_conn = (struct isert_conn *)conn->context;
+       struct isert_conn *isert_conn = conn->context;
        struct ib_send_wr *send_wr = &isert_cmd->tx_desc.send_wr;
-       struct ib_device *ib_dev = isert_conn->conn_cm_id->device;
+       struct isert_device *device = isert_conn->device;
+       struct ib_device *ib_dev = device->ib_device;
        struct ib_sge *tx_dsg = &isert_cmd->tx_desc.tx_sg[1];
        struct iscsi_reject *hdr =
                (struct iscsi_reject *)&isert_cmd->tx_desc.iscsi_header;
@@ -2243,7 +2311,7 @@ isert_put_reject(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
        isert_cmd->pdu_buf_len = ISCSI_HDR_LEN;
        tx_dsg->addr    = isert_cmd->pdu_buf_dma;
        tx_dsg->length  = ISCSI_HDR_LEN;
-       tx_dsg->lkey    = isert_conn->conn_mr->lkey;
+       tx_dsg->lkey    = device->mr->lkey;
        isert_cmd->tx_desc.num_sge = 2;
 
        isert_init_send_wr(isert_conn, isert_cmd, send_wr);
@@ -2257,7 +2325,7 @@ static int
 isert_put_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
 {
        struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd);
-       struct isert_conn *isert_conn = (struct isert_conn *)conn->context;
+       struct isert_conn *isert_conn = conn->context;
        struct ib_send_wr *send_wr = &isert_cmd->tx_desc.send_wr;
        struct iscsi_text_rsp *hdr =
                (struct iscsi_text_rsp *)&isert_cmd->tx_desc.iscsi_header;
@@ -2273,7 +2341,8 @@ isert_put_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
        isert_init_tx_hdrs(isert_conn, &isert_cmd->tx_desc);
 
        if (txt_rsp_len) {
-               struct ib_device *ib_dev = isert_conn->conn_cm_id->device;
+               struct isert_device *device = isert_conn->device;
+               struct ib_device *ib_dev = device->ib_device;
                struct ib_sge *tx_dsg = &isert_cmd->tx_desc.tx_sg[1];
                void *txt_rsp_buf = cmd->buf_ptr;
 
@@ -2283,7 +2352,7 @@ isert_put_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
                isert_cmd->pdu_buf_len = txt_rsp_len;
                tx_dsg->addr    = isert_cmd->pdu_buf_dma;
                tx_dsg->length  = txt_rsp_len;
-               tx_dsg->lkey    = isert_conn->conn_mr->lkey;
+               tx_dsg->lkey    = device->mr->lkey;
                isert_cmd->tx_desc.num_sge = 2;
        }
        isert_init_send_wr(isert_conn, isert_cmd, send_wr);
@@ -2300,7 +2369,8 @@ isert_build_rdma_wr(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd,
 {
        struct iscsi_cmd *cmd = isert_cmd->iscsi_cmd;
        struct scatterlist *sg_start, *tmp_sg;
-       struct ib_device *ib_dev = isert_conn->conn_cm_id->device;
+       struct isert_device *device = isert_conn->device;
+       struct ib_device *ib_dev = device->ib_device;
        u32 sg_off, page_off;
        int i = 0, sg_nents;
 
@@ -2324,7 +2394,7 @@ isert_build_rdma_wr(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd,
                ib_sge->addr = ib_sg_dma_address(ib_dev, tmp_sg) + page_off;
                ib_sge->length = min_t(u32, data_left,
                                ib_sg_dma_len(ib_dev, tmp_sg) - page_off);
-               ib_sge->lkey = isert_conn->conn_mr->lkey;
+               ib_sge->lkey = device->mr->lkey;
 
                isert_dbg("RDMA ib_sge: addr: 0x%llx  length: %u lkey: %x\n",
                          ib_sge->addr, ib_sge->length, ib_sge->lkey);
@@ -2346,7 +2416,7 @@ isert_map_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
 {
        struct se_cmd *se_cmd = &cmd->se_cmd;
        struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd);
-       struct isert_conn *isert_conn = (struct isert_conn *)conn->context;
+       struct isert_conn *isert_conn = conn->context;
        struct isert_data_buf *data = &wr->data;
        struct ib_send_wr *send_wr;
        struct ib_sge *ib_sge;
@@ -2485,7 +2555,8 @@ isert_fast_reg_mr(struct isert_conn *isert_conn,
                  enum isert_indicator ind,
                  struct ib_sge *sge)
 {
-       struct ib_device *ib_dev = isert_conn->conn_cm_id->device;
+       struct isert_device *device = isert_conn->device;
+       struct ib_device *ib_dev = device->ib_device;
        struct ib_mr *mr;
        struct ib_fast_reg_page_list *frpl;
        struct ib_send_wr fr_wr, inv_wr;
@@ -2494,7 +2565,7 @@ isert_fast_reg_mr(struct isert_conn *isert_conn,
        u32 page_off;
 
        if (mem->dma_nents == 1) {
-               sge->lkey = isert_conn->conn_mr->lkey;
+               sge->lkey = device->mr->lkey;
                sge->addr = ib_sg_dma_address(ib_dev, &mem->sg[0]);
                sge->length = ib_sg_dma_len(ib_dev, &mem->sg[0]);
                isert_dbg("sge: addr: 0x%llx  length: %u lkey: %x\n",
@@ -2542,7 +2613,7 @@ isert_fast_reg_mr(struct isert_conn *isert_conn,
        else
                wr->next = &fr_wr;
 
-       ret = ib_post_send(isert_conn->conn_qp, wr, &bad_wr);
+       ret = ib_post_send(isert_conn->qp, wr, &bad_wr);
        if (ret) {
                isert_err("fast registration failed, ret:%d\n", ret);
                return ret;
@@ -2655,7 +2726,7 @@ isert_reg_sig_mr(struct isert_conn *isert_conn,
        else
                wr->next = &sig_wr;
 
-       ret = ib_post_send(isert_conn->conn_qp, wr, &bad_wr);
+       ret = ib_post_send(isert_conn->qp, wr, &bad_wr);
        if (ret) {
                isert_err("fast registration failed, ret:%d\n", ret);
                goto err;
@@ -2685,14 +2756,14 @@ isert_handle_prot_cmd(struct isert_conn *isert_conn,
                      struct isert_cmd *isert_cmd,
                      struct isert_rdma_wr *wr)
 {
-       struct isert_device *device = isert_conn->conn_device;
+       struct isert_device *device = isert_conn->device;
        struct se_cmd *se_cmd = &isert_cmd->iscsi_cmd->se_cmd;
        int ret;
 
        if (!wr->fr_desc->pi_ctx) {
                ret = isert_create_pi_ctx(wr->fr_desc,
                                          device->ib_device,
-                                         isert_conn->conn_pd);
+                                         device->pd);
                if (ret) {
                        isert_err("conn %p failed to allocate pi_ctx\n",
                                  isert_conn);
@@ -2763,11 +2834,11 @@ isert_reg_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
                return ret;
 
        if (wr->data.dma_nents != 1 || isert_prot_cmd(isert_conn, se_cmd)) {
-               spin_lock_irqsave(&isert_conn->conn_lock, flags);
-               fr_desc = list_first_entry(&isert_conn->conn_fr_pool,
+               spin_lock_irqsave(&isert_conn->pool_lock, flags);
+               fr_desc = list_first_entry(&isert_conn->fr_pool,
                                           struct fast_reg_descriptor, list);
                list_del(&fr_desc->list);
-               spin_unlock_irqrestore(&isert_conn->conn_lock, flags);
+               spin_unlock_irqrestore(&isert_conn->pool_lock, flags);
                wr->fr_desc = fr_desc;
        }
 
@@ -2814,9 +2885,9 @@ isert_reg_rdma(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
 
 unmap_cmd:
        if (fr_desc) {
-               spin_lock_irqsave(&isert_conn->conn_lock, flags);
-               list_add_tail(&fr_desc->list, &isert_conn->conn_fr_pool);
-               spin_unlock_irqrestore(&isert_conn->conn_lock, flags);
+               spin_lock_irqsave(&isert_conn->pool_lock, flags);
+               list_add_tail(&fr_desc->list, &isert_conn->fr_pool);
+               spin_unlock_irqrestore(&isert_conn->pool_lock, flags);
        }
        isert_unmap_data_buf(isert_conn, &wr->data);
 
@@ -2829,8 +2900,8 @@ isert_put_datain(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
        struct se_cmd *se_cmd = &cmd->se_cmd;
        struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd);
        struct isert_rdma_wr *wr = &isert_cmd->rdma_wr;
-       struct isert_conn *isert_conn = (struct isert_conn *)conn->context;
-       struct isert_device *device = isert_conn->conn_device;
+       struct isert_conn *isert_conn = conn->context;
+       struct isert_device *device = isert_conn->device;
        struct ib_send_wr *wr_failed;
        int rc;
 
@@ -2859,7 +2930,7 @@ isert_put_datain(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
                wr->send_wr_num += 1;
        }
 
-       rc = ib_post_send(isert_conn->conn_qp, wr->send_wr, &wr_failed);
+       rc = ib_post_send(isert_conn->qp, wr->send_wr, &wr_failed);
        if (rc)
                isert_warn("ib_post_send() failed for IB_WR_RDMA_WRITE\n");
 
@@ -2879,8 +2950,8 @@ isert_get_dataout(struct iscsi_conn *conn, struct iscsi_cmd *cmd, bool recovery)
        struct se_cmd *se_cmd = &cmd->se_cmd;
        struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd);
        struct isert_rdma_wr *wr = &isert_cmd->rdma_wr;
-       struct isert_conn *isert_conn = (struct isert_conn *)conn->context;
-       struct isert_device *device = isert_conn->conn_device;
+       struct isert_conn *isert_conn = conn->context;
+       struct isert_device *device = isert_conn->device;
        struct ib_send_wr *wr_failed;
        int rc;
 
@@ -2893,7 +2964,7 @@ isert_get_dataout(struct iscsi_conn *conn, struct iscsi_cmd *cmd, bool recovery)
                return rc;
        }
 
-       rc = ib_post_send(isert_conn->conn_qp, wr->send_wr, &wr_failed);
+       rc = ib_post_send(isert_conn->qp, wr->send_wr, &wr_failed);
        if (rc)
                isert_warn("ib_post_send() failed for IB_WR_RDMA_READ\n");
 
@@ -2987,7 +3058,7 @@ isert_setup_id(struct isert_np *isert_np)
                goto out_id;
        }
 
-       ret = rdma_listen(id, ISERT_RDMA_LISTEN_BACKLOG);
+       ret = rdma_listen(id, 0);
        if (ret) {
                isert_err("rdma_listen() failed: %d\n", ret);
                goto out_id;
@@ -3046,7 +3117,7 @@ out:
 static int
 isert_rdma_accept(struct isert_conn *isert_conn)
 {
-       struct rdma_cm_id *cm_id = isert_conn->conn_cm_id;
+       struct rdma_cm_id *cm_id = isert_conn->cm_id;
        struct rdma_conn_param cp;
        int ret;
 
@@ -3067,7 +3138,7 @@ isert_rdma_accept(struct isert_conn *isert_conn)
 static int
 isert_get_login_rx(struct iscsi_conn *conn, struct iscsi_login *login)
 {
-       struct isert_conn *isert_conn = (struct isert_conn *)conn->context;
+       struct isert_conn *isert_conn = conn->context;
        int ret;
 
        isert_info("before login_req comp conn: %p\n", isert_conn);
@@ -3090,8 +3161,8 @@ isert_get_login_rx(struct iscsi_conn *conn, struct iscsi_login *login)
 
        isert_rx_login_req(isert_conn);
 
-       isert_info("before conn_login_comp conn: %p\n", conn);
-       ret = wait_for_completion_interruptible(&isert_conn->conn_login_comp);
+       isert_info("before login_comp conn: %p\n", conn);
+       ret = wait_for_completion_interruptible(&isert_conn->login_comp);
        if (ret)
                return ret;
 
@@ -3104,7 +3175,7 @@ static void
 isert_set_conn_info(struct iscsi_np *np, struct iscsi_conn *conn,
                    struct isert_conn *isert_conn)
 {
-       struct rdma_cm_id *cm_id = isert_conn->conn_cm_id;
+       struct rdma_cm_id *cm_id = isert_conn->cm_id;
        struct rdma_route *cm_route = &cm_id->route;
        struct sockaddr_in *sock_in;
        struct sockaddr_in6 *sock_in6;
@@ -3137,13 +3208,13 @@ isert_set_conn_info(struct iscsi_np *np, struct iscsi_conn *conn,
 static int
 isert_accept_np(struct iscsi_np *np, struct iscsi_conn *conn)
 {
-       struct isert_np *isert_np = (struct isert_np *)np->np_context;
+       struct isert_np *isert_np = np->np_context;
        struct isert_conn *isert_conn;
-       int max_accept = 0, ret;
+       int ret;
 
 accept_wait:
        ret = down_interruptible(&isert_np->np_sem);
-       if (ret || max_accept > 5)
+       if (ret)
                return -ENODEV;
 
        spin_lock_bh(&np->np_thread_lock);
@@ -3162,17 +3233,15 @@ accept_wait:
        mutex_lock(&isert_np->np_accept_mutex);
        if (list_empty(&isert_np->np_accept_list)) {
                mutex_unlock(&isert_np->np_accept_mutex);
-               max_accept++;
                goto accept_wait;
        }
        isert_conn = list_first_entry(&isert_np->np_accept_list,
-                       struct isert_conn, conn_accept_node);
-       list_del_init(&isert_conn->conn_accept_node);
+                       struct isert_conn, accept_node);
+       list_del_init(&isert_conn->accept_node);
        mutex_unlock(&isert_np->np_accept_mutex);
 
        conn->context = isert_conn;
        isert_conn->conn = conn;
-       max_accept = 0;
 
        isert_set_conn_info(np, conn, isert_conn);
 
@@ -3184,7 +3253,7 @@ accept_wait:
 static void
 isert_free_np(struct iscsi_np *np)
 {
-       struct isert_np *isert_np = (struct isert_np *)np->np_context;
+       struct isert_np *isert_np = np->np_context;
        struct isert_conn *isert_conn, *n;
 
        if (isert_np->np_cm_id)
@@ -3202,7 +3271,7 @@ isert_free_np(struct iscsi_np *np)
                isert_info("Still have isert connections, cleaning up...\n");
                list_for_each_entry_safe(isert_conn, n,
                                         &isert_np->np_accept_list,
-                                        conn_accept_node) {
+                                        accept_node) {
                        isert_info("cleaning isert_conn %p state (%d)\n",
                                   isert_conn, isert_conn->state);
                        isert_connect_release(isert_conn);
@@ -3222,11 +3291,11 @@ static void isert_release_work(struct work_struct *work)
 
        isert_info("Starting release conn %p\n", isert_conn);
 
-       wait_for_completion(&isert_conn->conn_wait);
+       wait_for_completion(&isert_conn->wait);
 
-       mutex_lock(&isert_conn->conn_mutex);
+       mutex_lock(&isert_conn->mutex);
        isert_conn->state = ISER_CONN_DOWN;
-       mutex_unlock(&isert_conn->conn_mutex);
+       mutex_unlock(&isert_conn->mutex);
 
        isert_info("Destroying conn %p\n", isert_conn);
        isert_put_conn(isert_conn);
@@ -3264,15 +3333,15 @@ isert_wait4flush(struct isert_conn *isert_conn)
 
        isert_info("conn %p\n", isert_conn);
 
-       init_completion(&isert_conn->conn_wait_comp_err);
+       init_completion(&isert_conn->wait_comp_err);
        isert_conn->beacon.wr_id = ISER_BEACON_WRID;
        /* post an indication that all flush errors were consumed */
-       if (ib_post_recv(isert_conn->conn_qp, &isert_conn->beacon, &bad_wr)) {
+       if (ib_post_recv(isert_conn->qp, &isert_conn->beacon, &bad_wr)) {
                isert_err("conn %p failed to post beacon", isert_conn);
                return;
        }
 
-       wait_for_completion(&isert_conn->conn_wait_comp_err);
+       wait_for_completion(&isert_conn->wait_comp_err);
 }
 
 static void isert_wait_conn(struct iscsi_conn *conn)
@@ -3281,17 +3350,17 @@ static void isert_wait_conn(struct iscsi_conn *conn)
 
        isert_info("Starting conn %p\n", isert_conn);
 
-       mutex_lock(&isert_conn->conn_mutex);
+       mutex_lock(&isert_conn->mutex);
        /*
-        * Only wait for conn_wait_comp_err if the isert_conn made it
+        * Only wait for wait_comp_err if the isert_conn made it
         * into full feature phase..
         */
        if (isert_conn->state == ISER_CONN_INIT) {
-               mutex_unlock(&isert_conn->conn_mutex);
+               mutex_unlock(&isert_conn->mutex);
                return;
        }
        isert_conn_terminate(isert_conn);
-       mutex_unlock(&isert_conn->conn_mutex);
+       mutex_unlock(&isert_conn->mutex);
 
        isert_wait4cmds(conn);
        isert_wait4flush(isert_conn);
@@ -3370,7 +3439,7 @@ static void __exit isert_exit(void)
 }
 
 MODULE_DESCRIPTION("iSER-Target for mainline target infrastructure");
-MODULE_VERSION("0.1");
+MODULE_VERSION("1.0");
 MODULE_AUTHOR("nab@Linux-iSCSI.org");
 MODULE_LICENSE("GPL");
 
index 8dc8415d152d00ca550f9cfa993d0da0bacb27c2..9ec23a786c029a15b9480377e8b46721b67f9c8a 100644 (file)
@@ -31,7 +31,6 @@
 #define isert_err(fmt, arg...) \
        pr_err(PFX "%s: " fmt, __func__ , ## arg)
 
-#define ISERT_RDMA_LISTEN_BACKLOG      10
 #define ISCSI_ISER_SG_TABLESIZE                256
 #define ISER_FASTREG_LI_WRID           0xffffffffffffffffULL
 #define ISER_BEACON_WRID               0xfffffffffffffffeULL
@@ -160,27 +159,25 @@ struct isert_conn {
        u64                     login_req_dma;
        int                     login_req_len;
        u64                     login_rsp_dma;
-       unsigned int            conn_rx_desc_head;
-       struct iser_rx_desc     *conn_rx_descs;
-       struct ib_recv_wr       conn_rx_wr[ISERT_MIN_POSTED_RX];
+       unsigned int            rx_desc_head;
+       struct iser_rx_desc     *rx_descs;
+       struct ib_recv_wr       rx_wr[ISERT_MIN_POSTED_RX];
        struct iscsi_conn       *conn;
-       struct list_head        conn_accept_node;
-       struct completion       conn_login_comp;
+       struct list_head        accept_node;
+       struct completion       login_comp;
        struct completion       login_req_comp;
-       struct iser_tx_desc     conn_login_tx_desc;
-       struct rdma_cm_id       *conn_cm_id;
-       struct ib_pd            *conn_pd;
-       struct ib_mr            *conn_mr;
-       struct ib_qp            *conn_qp;
-       struct isert_device     *conn_device;
-       struct mutex            conn_mutex;
-       struct completion       conn_wait;
-       struct completion       conn_wait_comp_err;
-       struct kref             conn_kref;
-       struct list_head        conn_fr_pool;
-       int                     conn_fr_pool_size;
+       struct iser_tx_desc     login_tx_desc;
+       struct rdma_cm_id       *cm_id;
+       struct ib_qp            *qp;
+       struct isert_device     *device;
+       struct mutex            mutex;
+       struct completion       wait;
+       struct completion       wait_comp_err;
+       struct kref             kref;
+       struct list_head        fr_pool;
+       int                     fr_pool_size;
        /* lock to protect fastreg pool */
-       spinlock_t              conn_lock;
+       spinlock_t              pool_lock;
        struct work_struct      release_work;
        struct ib_recv_wr       beacon;
        bool                    logout_posted;
@@ -211,6 +208,8 @@ struct isert_device {
        bool                    pi_capable;
        int                     refcount;
        struct ib_device        *ib_device;
+       struct ib_pd            *pd;
+       struct ib_mr            *mr;
        struct isert_comp       *comps;
        int                     comps_used;
        struct list_head        dev_node;
index 0747c0595a9d42b2ff8c9cb231b38be939821ddb..918814cd0f806f5344e5f293e2bb059010237727 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/parser.h>
 #include <linux/random.h>
 #include <linux/jiffies.h>
+#include <rdma/ib_cache.h>
 
 #include <linux/atomic.h>
 
@@ -265,10 +266,10 @@ static int srp_init_qp(struct srp_target_port *target,
        if (!attr)
                return -ENOMEM;
 
-       ret = ib_find_pkey(target->srp_host->srp_dev->dev,
-                          target->srp_host->port,
-                          be16_to_cpu(target->pkey),
-                          &attr->pkey_index);
+       ret = ib_find_cached_pkey(target->srp_host->srp_dev->dev,
+                                 target->srp_host->port,
+                                 be16_to_cpu(target->pkey),
+                                 &attr->pkey_index);
        if (ret)
                goto out;
 
index 6e0a477681e90b0efe53330de1b9118000bcc85a..9b84b4c0a000a32bdc896d6142fb63c7d5b13a3a 100644 (file)
@@ -93,7 +93,7 @@ MODULE_PARM_DESC(srpt_service_guid,
                 " instead of using the node_guid of the first HCA.");
 
 static struct ib_client srpt_client;
-static struct target_fabric_configfs *srpt_target;
+static const struct target_core_fabric_ops srpt_template;
 static void srpt_release_channel(struct srpt_rdma_ch *ch);
 static int srpt_queue_status(struct se_cmd *cmd);
 
@@ -207,7 +207,7 @@ static void srpt_event_handler(struct ib_event_handler *handler,
                }
                break;
        default:
-               printk(KERN_ERR "received unrecognized IB event %d\n",
+               pr_err("received unrecognized IB event %d\n",
                       event->event);
                break;
        }
@@ -218,7 +218,7 @@ static void srpt_event_handler(struct ib_event_handler *handler,
  */
 static void srpt_srq_event(struct ib_event *event, void *ctx)
 {
-       printk(KERN_INFO "SRQ event %d\n", event->event);
+       pr_info("SRQ event %d\n", event->event);
 }
 
 /**
@@ -242,8 +242,7 @@ static void srpt_qp_event(struct ib_event *event, struct srpt_rdma_ch *ch)
                                 ch->sess_name, srpt_get_ch_state(ch));
                break;
        default:
-               printk(KERN_ERR "received unrecognized IB QP event %d\n",
-                      event->event);
+               pr_err("received unrecognized IB QP event %d\n", event->event);
                break;
        }
 }
@@ -602,7 +601,7 @@ static void srpt_unregister_mad_agent(struct srpt_device *sdev)
                sport = &sdev->port[i - 1];
                WARN_ON(sport->port != i);
                if (ib_modify_port(sdev->device, i, 0, &port_modify) < 0)
-                       printk(KERN_ERR "disabling MAD processing failed.\n");
+                       pr_err("disabling MAD processing failed.\n");
                if (sport->mad_agent) {
                        ib_unregister_mad_agent(sport->mad_agent);
                        sport->mad_agent = NULL;
@@ -810,7 +809,7 @@ static int srpt_post_send(struct srpt_rdma_ch *ch,
 
        ret = -ENOMEM;
        if (unlikely(atomic_dec_return(&ch->sq_wr_avail) < 0)) {
-               printk(KERN_WARNING "IB send queue full (needed 1)\n");
+               pr_warn("IB send queue full (needed 1)\n");
                goto out;
        }
 
@@ -912,7 +911,7 @@ static int srpt_get_desc_tbl(struct srpt_send_ioctx *ioctx,
 
                if (ioctx->n_rbuf >
                    (srp_cmd->data_out_desc_cnt + srp_cmd->data_in_desc_cnt)) {
-                       printk(KERN_ERR "received unsupported SRP_CMD request"
+                       pr_err("received unsupported SRP_CMD request"
                               " type (%u out + %u in != %u / %zu)\n",
                               srp_cmd->data_out_desc_cnt,
                               srp_cmd->data_in_desc_cnt,
@@ -1432,7 +1431,7 @@ static void srpt_handle_send_comp(struct srpt_rdma_ch *ch,
                srpt_unmap_sg_to_ib_sge(ch, ioctx);
                transport_generic_free_cmd(&ioctx->cmd, 0);
        } else {
-               printk(KERN_ERR "IB completion has been received too late for"
+               pr_err("IB completion has been received too late for"
                       " wr_id = %u.\n", ioctx->ioctx.index);
        }
 }
@@ -1457,7 +1456,7 @@ static void srpt_handle_rdma_comp(struct srpt_rdma_ch *ch,
                                                SRPT_STATE_DATA_IN))
                        target_execute_cmd(&ioctx->cmd);
                else
-                       printk(KERN_ERR "%s[%d]: wrong state = %d\n", __func__,
+                       pr_err("%s[%d]: wrong state = %d\n", __func__,
                               __LINE__, srpt_get_cmd_state(ioctx));
        } else if (opcode == SRPT_RDMA_ABORT) {
                ioctx->rdma_aborted = true;
@@ -1481,7 +1480,7 @@ static void srpt_handle_rdma_err_comp(struct srpt_rdma_ch *ch,
        switch (opcode) {
        case SRPT_RDMA_READ_LAST:
                if (ioctx->n_rdma <= 0) {
-                       printk(KERN_ERR "Received invalid RDMA read"
+                       pr_err("Received invalid RDMA read"
                               " error completion with idx %d\n",
                               ioctx->ioctx.index);
                        break;
@@ -1490,14 +1489,13 @@ static void srpt_handle_rdma_err_comp(struct srpt_rdma_ch *ch,
                if (state == SRPT_STATE_NEED_DATA)
                        srpt_abort_cmd(ioctx);
                else
-                       printk(KERN_ERR "%s[%d]: wrong state = %d\n",
+                       pr_err("%s[%d]: wrong state = %d\n",
                               __func__, __LINE__, state);
                break;
        case SRPT_RDMA_WRITE_LAST:
                break;
        default:
-               printk(KERN_ERR "%s[%d]: opcode = %u\n", __func__,
-                      __LINE__, opcode);
+               pr_err("%s[%d]: opcode = %u\n", __func__, __LINE__, opcode);
                break;
        }
 }
@@ -1549,8 +1547,8 @@ static int srpt_build_cmd_rsp(struct srpt_rdma_ch *ch,
                BUILD_BUG_ON(MIN_MAX_RSP_SIZE <= sizeof(*srp_rsp));
                max_sense_len = ch->max_ti_iu_len - sizeof(*srp_rsp);
                if (sense_data_len > max_sense_len) {
-                       printk(KERN_WARNING "truncated sense data from %d to %d"
-                              " bytes\n", sense_data_len, max_sense_len);
+                       pr_warn("truncated sense data from %d to %d"
+                               " bytes\n", sense_data_len, max_sense_len);
                        sense_data_len = max_sense_len;
                }
 
@@ -1628,8 +1626,8 @@ static uint64_t srpt_unpack_lun(const uint8_t *lun, int len)
        int addressing_method;
 
        if (unlikely(len < 2)) {
-               printk(KERN_ERR "Illegal LUN length %d, expected 2 bytes or "
-                      "more", len);
+               pr_err("Illegal LUN length %d, expected 2 bytes or more\n",
+                      len);
                goto out;
        }
 
@@ -1663,7 +1661,7 @@ static uint64_t srpt_unpack_lun(const uint8_t *lun, int len)
 
        case SCSI_LUN_ADDR_METHOD_EXTENDED_LUN:
        default:
-               printk(KERN_ERR "Unimplemented LUN addressing method %u",
+               pr_err("Unimplemented LUN addressing method %u\n",
                       addressing_method);
                break;
        }
@@ -1672,8 +1670,7 @@ out:
        return res;
 
 out_err:
-       printk(KERN_ERR "Support for multi-level LUNs has not yet been"
-              " implemented");
+       pr_err("Support for multi-level LUNs has not yet been implemented\n");
        goto out;
 }
 
@@ -1723,7 +1720,7 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch,
        }
 
        if (srpt_get_desc_tbl(send_ioctx, srp_cmd, &dir, &data_len)) {
-               printk(KERN_ERR "0x%llx: parsing SRP descriptor table failed.\n",
+               pr_err("0x%llx: parsing SRP descriptor table failed.\n",
                       srp_cmd->tag);
                ret = TCM_INVALID_CDB_FIELD;
                goto send_sense;
@@ -1912,7 +1909,7 @@ static void srpt_handle_new_iu(struct srpt_rdma_ch *ch,
                srpt_handle_tsk_mgmt(ch, recv_ioctx, send_ioctx);
                break;
        case SRP_I_LOGOUT:
-               printk(KERN_ERR "Not yet implemented: SRP_I_LOGOUT\n");
+               pr_err("Not yet implemented: SRP_I_LOGOUT\n");
                break;
        case SRP_CRED_RSP:
                pr_debug("received SRP_CRED_RSP\n");
@@ -1921,10 +1918,10 @@ static void srpt_handle_new_iu(struct srpt_rdma_ch *ch,
                pr_debug("received SRP_AER_RSP\n");
                break;
        case SRP_RSP:
-               printk(KERN_ERR "Received SRP_RSP\n");
+               pr_err("Received SRP_RSP\n");
                break;
        default:
-               printk(KERN_ERR "received IU with unknown opcode 0x%x\n",
+               pr_err("received IU with unknown opcode 0x%x\n",
                       srp_cmd->opcode);
                break;
        }
@@ -1948,12 +1945,12 @@ static void srpt_process_rcv_completion(struct ib_cq *cq,
 
                req_lim = atomic_dec_return(&ch->req_lim);
                if (unlikely(req_lim < 0))
-                       printk(KERN_ERR "req_lim = %d < 0\n", req_lim);
+                       pr_err("req_lim = %d < 0\n", req_lim);
                ioctx = sdev->ioctx_ring[index];
                srpt_handle_new_iu(ch, ioctx, NULL);
        } else {
-               printk(KERN_INFO "receiving failed for idx %u with status %d\n",
-                      index, wc->status);
+               pr_info("receiving failed for idx %u with status %d\n",
+                       index, wc->status);
        }
 }
 
@@ -1993,12 +1990,12 @@ static void srpt_process_send_completion(struct ib_cq *cq,
                }
        } else {
                if (opcode == SRPT_SEND) {
-                       printk(KERN_INFO "sending response for idx %u failed"
-                              " with status %d\n", index, wc->status);
+                       pr_info("sending response for idx %u failed"
+                               " with status %d\n", index, wc->status);
                        srpt_handle_send_err_comp(ch, wc->wr_id);
                } else if (opcode != SRPT_RDMA_MID) {
-                       printk(KERN_INFO "RDMA t %d for idx %u failed with"
-                               " status %d", opcode, index, wc->status);
+                       pr_info("RDMA t %d for idx %u failed with"
+                               " status %d\n", opcode, index, wc->status);
                        srpt_handle_rdma_err_comp(ch, send_ioctx, opcode);
                }
        }
@@ -2062,15 +2059,15 @@ static int srpt_compl_thread(void *arg)
 
        ch = arg;
        BUG_ON(!ch);
-       printk(KERN_INFO "Session %s: kernel thread %s (PID %d) started\n",
-              ch->sess_name, ch->thread->comm, current->pid);
+       pr_info("Session %s: kernel thread %s (PID %d) started\n",
+               ch->sess_name, ch->thread->comm, current->pid);
        while (!kthread_should_stop()) {
                wait_event_interruptible(ch->wait_queue,
                        (srpt_process_completion(ch->cq, ch),
                         kthread_should_stop()));
        }
-       printk(KERN_INFO "Session %s: kernel thread %s (PID %d) stopped\n",
-              ch->sess_name, ch->thread->comm, current->pid);
+       pr_info("Session %s: kernel thread %s (PID %d) stopped\n",
+               ch->sess_name, ch->thread->comm, current->pid);
        return 0;
 }
 
@@ -2097,7 +2094,7 @@ retry:
                              ch->rq_size + srp_sq_size, 0);
        if (IS_ERR(ch->cq)) {
                ret = PTR_ERR(ch->cq);
-               printk(KERN_ERR "failed to create CQ cqe= %d ret= %d\n",
+               pr_err("failed to create CQ cqe= %d ret= %d\n",
                       ch->rq_size + srp_sq_size, ret);
                goto out;
        }
@@ -2123,7 +2120,7 @@ retry:
                                goto retry;
                        }
                }
-               printk(KERN_ERR "failed to create_qp ret= %d\n", ret);
+               pr_err("failed to create_qp ret= %d\n", ret);
                goto err_destroy_cq;
        }
 
@@ -2143,7 +2140,7 @@ retry:
 
        ch->thread = kthread_run(srpt_compl_thread, ch, "ib_srpt_compl");
        if (IS_ERR(ch->thread)) {
-               printk(KERN_ERR "failed to create kernel thread %ld\n",
+               pr_err("failed to create kernel thread %ld\n",
                       PTR_ERR(ch->thread));
                ch->thread = NULL;
                goto err_destroy_qp;
@@ -2204,7 +2201,7 @@ static void __srpt_close_ch(struct srpt_rdma_ch *ch)
                /* fall through */
        case CH_LIVE:
                if (ib_send_cm_dreq(ch->cm_id, NULL, 0) < 0)
-                       printk(KERN_ERR "sending CM DREQ failed.\n");
+                       pr_err("sending CM DREQ failed.\n");
                break;
        case CH_DISCONNECTING:
                break;
@@ -2291,7 +2288,7 @@ static void srpt_drain_channel(struct ib_cm_id *cm_id)
 
                ret = srpt_ch_qp_err(ch);
                if (ret < 0)
-                       printk(KERN_ERR "Setting queue pair in error state"
+                       pr_err("Setting queue pair in error state"
                               " failed: %d\n", ret);
        }
 }
@@ -2435,17 +2432,17 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
 
        it_iu_len = be32_to_cpu(req->req_it_iu_len);
 
-       printk(KERN_INFO "Received SRP_LOGIN_REQ with i_port_id 0x%llx:0x%llx,"
-              " t_port_id 0x%llx:0x%llx and it_iu_len %d on port %d"
-              " (guid=0x%llx:0x%llx)\n",
-              be64_to_cpu(*(__be64 *)&req->initiator_port_id[0]),
-              be64_to_cpu(*(__be64 *)&req->initiator_port_id[8]),
-              be64_to_cpu(*(__be64 *)&req->target_port_id[0]),
-              be64_to_cpu(*(__be64 *)&req->target_port_id[8]),
-              it_iu_len,
-              param->port,
-              be64_to_cpu(*(__be64 *)&sdev->port[param->port - 1].gid.raw[0]),
-              be64_to_cpu(*(__be64 *)&sdev->port[param->port - 1].gid.raw[8]));
+       pr_info("Received SRP_LOGIN_REQ with i_port_id 0x%llx:0x%llx,"
+               " t_port_id 0x%llx:0x%llx and it_iu_len %d on port %d"
+               " (guid=0x%llx:0x%llx)\n",
+               be64_to_cpu(*(__be64 *)&req->initiator_port_id[0]),
+               be64_to_cpu(*(__be64 *)&req->initiator_port_id[8]),
+               be64_to_cpu(*(__be64 *)&req->target_port_id[0]),
+               be64_to_cpu(*(__be64 *)&req->target_port_id[8]),
+               it_iu_len,
+               param->port,
+               be64_to_cpu(*(__be64 *)&sdev->port[param->port - 1].gid.raw[0]),
+               be64_to_cpu(*(__be64 *)&sdev->port[param->port - 1].gid.raw[8]));
 
        rsp = kzalloc(sizeof *rsp, GFP_KERNEL);
        rej = kzalloc(sizeof *rej, GFP_KERNEL);
@@ -2460,7 +2457,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
                rej->reason = __constant_cpu_to_be32(
                                SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE);
                ret = -EINVAL;
-               printk(KERN_ERR "rejected SRP_LOGIN_REQ because its"
+               pr_err("rejected SRP_LOGIN_REQ because its"
                       " length (%d bytes) is out of range (%d .. %d)\n",
                       it_iu_len, 64, srp_max_req_size);
                goto reject;
@@ -2470,7 +2467,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
                rej->reason = __constant_cpu_to_be32(
                             SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
                ret = -EINVAL;
-               printk(KERN_ERR "rejected SRP_LOGIN_REQ because the target port"
+               pr_err("rejected SRP_LOGIN_REQ because the target port"
                       " has not yet been enabled\n");
                goto reject;
        }
@@ -2516,7 +2513,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
                rej->reason = __constant_cpu_to_be32(
                                SRP_LOGIN_REJ_UNABLE_ASSOCIATE_CHANNEL);
                ret = -ENOMEM;
-               printk(KERN_ERR "rejected SRP_LOGIN_REQ because it"
+               pr_err("rejected SRP_LOGIN_REQ because it"
                       " has an invalid target port identifier.\n");
                goto reject;
        }
@@ -2525,7 +2522,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
        if (!ch) {
                rej->reason = __constant_cpu_to_be32(
                                        SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
-               printk(KERN_ERR "rejected SRP_LOGIN_REQ because no memory.\n");
+               pr_err("rejected SRP_LOGIN_REQ because no memory.\n");
                ret = -ENOMEM;
                goto reject;
        }
@@ -2562,7 +2559,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
        if (ret) {
                rej->reason = __constant_cpu_to_be32(
                                SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
-               printk(KERN_ERR "rejected SRP_LOGIN_REQ because creating"
+               pr_err("rejected SRP_LOGIN_REQ because creating"
                       " a new RDMA channel failed.\n");
                goto free_ring;
        }
@@ -2571,7 +2568,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
        if (ret) {
                rej->reason = __constant_cpu_to_be32(
                                SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
-               printk(KERN_ERR "rejected SRP_LOGIN_REQ because enabling"
+               pr_err("rejected SRP_LOGIN_REQ because enabling"
                       " RTR failed (error code = %d)\n", ret);
                goto destroy_ib;
        }
@@ -2586,8 +2583,8 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
 
        nacl = srpt_lookup_acl(sport, ch->i_port_id);
        if (!nacl) {
-               printk(KERN_INFO "Rejected login because no ACL has been"
-                      " configured yet for initiator %s.\n", ch->sess_name);
+               pr_info("Rejected login because no ACL has been"
+                       " configured yet for initiator %s.\n", ch->sess_name);
                rej->reason = __constant_cpu_to_be32(
                                SRP_LOGIN_REJ_CHANNEL_LIMIT_REACHED);
                goto destroy_ib;
@@ -2631,7 +2628,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
 
        ret = ib_send_cm_rep(cm_id, rep_param);
        if (ret) {
-               printk(KERN_ERR "sending SRP_LOGIN_REQ response failed"
+               pr_err("sending SRP_LOGIN_REQ response failed"
                       " (error code = %d)\n", ret);
                goto release_channel;
        }
@@ -2679,7 +2676,7 @@ out:
 
 static void srpt_cm_rej_recv(struct ib_cm_id *cm_id)
 {
-       printk(KERN_INFO "Received IB REJ for cm_id %p.\n", cm_id);
+       pr_info("Received IB REJ for cm_id %p.\n", cm_id);
        srpt_drain_channel(cm_id);
 }
 
@@ -2714,13 +2711,13 @@ static void srpt_cm_rtu_recv(struct ib_cm_id *cm_id)
 
 static void srpt_cm_timewait_exit(struct ib_cm_id *cm_id)
 {
-       printk(KERN_INFO "Received IB TimeWait exit for cm_id %p.\n", cm_id);
+       pr_info("Received IB TimeWait exit for cm_id %p.\n", cm_id);
        srpt_drain_channel(cm_id);
 }
 
 static void srpt_cm_rep_error(struct ib_cm_id *cm_id)
 {
-       printk(KERN_INFO "Received IB REP error for cm_id %p.\n", cm_id);
+       pr_info("Received IB REP error for cm_id %p.\n", cm_id);
        srpt_drain_channel(cm_id);
 }
 
@@ -2755,9 +2752,9 @@ static void srpt_cm_dreq_recv(struct ib_cm_id *cm_id)
 
        if (send_drep) {
                if (ib_send_cm_drep(ch->cm_id, NULL, 0) < 0)
-                       printk(KERN_ERR "Sending IB DREP failed.\n");
-               printk(KERN_INFO "Received DREQ and sent DREP for session %s.\n",
-                      ch->sess_name);
+                       pr_err("Sending IB DREP failed.\n");
+               pr_info("Received DREQ and sent DREP for session %s.\n",
+                       ch->sess_name);
        }
 }
 
@@ -2766,8 +2763,7 @@ static void srpt_cm_dreq_recv(struct ib_cm_id *cm_id)
  */
 static void srpt_cm_drep_recv(struct ib_cm_id *cm_id)
 {
-       printk(KERN_INFO "Received InfiniBand DREP message for cm_id %p.\n",
-              cm_id);
+       pr_info("Received InfiniBand DREP message for cm_id %p.\n", cm_id);
        srpt_drain_channel(cm_id);
 }
 
@@ -2811,14 +2807,13 @@ static int srpt_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
                srpt_cm_rep_error(cm_id);
                break;
        case IB_CM_DREQ_ERROR:
-               printk(KERN_INFO "Received IB DREQ ERROR event.\n");
+               pr_info("Received IB DREQ ERROR event.\n");
                break;
        case IB_CM_MRA_RECEIVED:
-               printk(KERN_INFO "Received IB MRA event\n");
+               pr_info("Received IB MRA event\n");
                break;
        default:
-               printk(KERN_ERR "received unrecognized IB CM event %d\n",
-                      event->event);
+               pr_err("received unrecognized IB CM event %d\n", event->event);
                break;
        }
 
@@ -2848,8 +2843,8 @@ static int srpt_perform_rdmas(struct srpt_rdma_ch *ch,
                ret = -ENOMEM;
                sq_wr_avail = atomic_sub_return(n_rdma, &ch->sq_wr_avail);
                if (sq_wr_avail < 0) {
-                       printk(KERN_WARNING "IB send queue full (needed %d)\n",
-                              n_rdma);
+                       pr_warn("IB send queue full (needed %d)\n",
+                               n_rdma);
                        goto out;
                }
        }
@@ -2889,7 +2884,7 @@ static int srpt_perform_rdmas(struct srpt_rdma_ch *ch,
        }
 
        if (ret)
-               printk(KERN_ERR "%s[%d]: ib_post_send() returned %d for %d/%d",
+               pr_err("%s[%d]: ib_post_send() returned %d for %d/%d\n",
                                 __func__, __LINE__, ret, i, n_rdma);
        if (ret && i > 0) {
                wr.num_sge = 0;
@@ -2897,12 +2892,12 @@ static int srpt_perform_rdmas(struct srpt_rdma_ch *ch,
                wr.send_flags = IB_SEND_SIGNALED;
                while (ch->state == CH_LIVE &&
                        ib_post_send(ch->qp, &wr, &bad_wr) != 0) {
-                       printk(KERN_INFO "Trying to abort failed RDMA transfer [%d]",
+                       pr_info("Trying to abort failed RDMA transfer [%d]\n",
                                ioctx->ioctx.index);
                        msleep(1000);
                }
                while (ch->state != CH_RELEASING && !ioctx->rdma_aborted) {
-                       printk(KERN_INFO "Waiting until RDMA abort finished [%d]",
+                       pr_info("Waiting until RDMA abort finished [%d]\n",
                                ioctx->ioctx.index);
                        msleep(1000);
                }
@@ -2923,17 +2918,17 @@ static int srpt_xfer_data(struct srpt_rdma_ch *ch,
 
        ret = srpt_map_sg_to_ib_sge(ch, ioctx);
        if (ret) {
-               printk(KERN_ERR "%s[%d] ret=%d\n", __func__, __LINE__, ret);
+               pr_err("%s[%d] ret=%d\n", __func__, __LINE__, ret);
                goto out;
        }
 
        ret = srpt_perform_rdmas(ch, ioctx);
        if (ret) {
                if (ret == -EAGAIN || ret == -ENOMEM)
-                       printk(KERN_INFO "%s[%d] queue full -- ret=%d\n",
-                                  __func__, __LINE__, ret);
+                       pr_info("%s[%d] queue full -- ret=%d\n",
+                               __func__, __LINE__, ret);
                else
-                       printk(KERN_ERR "%s[%d] fatal error -- ret=%d\n",
+                       pr_err("%s[%d] fatal error -- ret=%d\n",
                               __func__, __LINE__, ret);
                goto out_unmap;
        }
@@ -3058,7 +3053,7 @@ static void srpt_queue_response(struct se_cmd *cmd)
            !ioctx->queue_status_only) {
                ret = srpt_xfer_data(ch, ioctx);
                if (ret) {
-                       printk(KERN_ERR "xfer_data failed for tag %llu\n",
+                       pr_err("xfer_data failed for tag %llu\n",
                               ioctx->tag);
                        return;
                }
@@ -3075,7 +3070,7 @@ static void srpt_queue_response(struct se_cmd *cmd)
        }
        ret = srpt_post_send(ch, ioctx, resp_len);
        if (ret) {
-               printk(KERN_ERR "sending cmd response failed for tag %llu\n",
+               pr_err("sending cmd response failed for tag %llu\n",
                       ioctx->tag);
                srpt_unmap_sg_to_ib_sge(ch, ioctx);
                srpt_set_cmd_state(ioctx, SRPT_STATE_DONE);
@@ -3154,7 +3149,7 @@ static int srpt_release_sdev(struct srpt_device *sdev)
        res = wait_event_interruptible(sdev->ch_releaseQ,
                                       srpt_ch_list_empty(sdev));
        if (res)
-               printk(KERN_ERR "%s: interrupted.\n", __func__);
+               pr_err("%s: interrupted.\n", __func__);
 
        return 0;
 }
@@ -3293,7 +3288,7 @@ static void srpt_add_one(struct ib_device *device)
                spin_lock_init(&sport->port_acl_lock);
 
                if (srpt_refresh_port(sport)) {
-                       printk(KERN_ERR "MAD registration failed for %s-%d.\n",
+                       pr_err("MAD registration failed for %s-%d.\n",
                               srpt_sdev_name(sdev), i);
                        goto err_ring;
                }
@@ -3330,7 +3325,7 @@ free_dev:
        kfree(sdev);
 err:
        sdev = NULL;
-       printk(KERN_INFO "%s(%s) failed.\n", __func__, device->name);
+       pr_info("%s(%s) failed.\n", __func__, device->name);
        goto out;
 }
 
@@ -3344,8 +3339,7 @@ static void srpt_remove_one(struct ib_device *device)
 
        sdev = ib_get_client_data(device, &srpt_client);
        if (!sdev) {
-               printk(KERN_INFO "%s(%s): nothing to do.\n", __func__,
-                      device->name);
+               pr_info("%s(%s): nothing to do.\n", __func__, device->name);
                return;
        }
 
@@ -3464,7 +3458,7 @@ static struct se_node_acl *srpt_alloc_fabric_acl(struct se_portal_group *se_tpg)
 
        nacl = kzalloc(sizeof(struct srpt_node_acl), GFP_KERNEL);
        if (!nacl) {
-               printk(KERN_ERR "Unable to allocate struct srpt_node_acl\n");
+               pr_err("Unable to allocate struct srpt_node_acl\n");
                return NULL;
        }
 
@@ -3615,7 +3609,7 @@ static struct se_node_acl *srpt_make_nodeacl(struct se_portal_group *tpg,
        u8 i_port_id[16];
 
        if (srpt_parse_i_port_id(i_port_id, name) < 0) {
-               printk(KERN_ERR "invalid initiator port ID %s\n", name);
+               pr_err("invalid initiator port ID %s\n", name);
                ret = -EINVAL;
                goto err;
        }
@@ -3816,12 +3810,12 @@ static ssize_t srpt_tpg_store_enable(
 
        ret = kstrtoul(page, 0, &tmp);
        if (ret < 0) {
-               printk(KERN_ERR "Unable to extract srpt_tpg_store_enable\n");
+               pr_err("Unable to extract srpt_tpg_store_enable\n");
                return -EINVAL;
        }
 
        if ((tmp != 0) && (tmp != 1)) {
-               printk(KERN_ERR "Illegal value for srpt_tpg_store_enable: %lu\n", tmp);
+               pr_err("Illegal value for srpt_tpg_store_enable: %lu\n", tmp);
                return -EINVAL;
        }
        if (tmp == 1)
@@ -3851,7 +3845,7 @@ static struct se_portal_group *srpt_make_tpg(struct se_wwn *wwn,
        int res;
 
        /* Initialize sport->port_wwn and sport->port_tpg_1 */
-       res = core_tpg_register(&srpt_target->tf_ops, &sport->port_wwn,
+       res = core_tpg_register(&srpt_template, &sport->port_wwn,
                        &sport->port_tpg_1, sport, TRANSPORT_TPG_TYPE_NORMAL);
        if (res)
                return ERR_PTR(res);
@@ -3919,7 +3913,9 @@ static struct configfs_attribute *srpt_wwn_attrs[] = {
        NULL,
 };
 
-static struct target_core_fabric_ops srpt_template = {
+static const struct target_core_fabric_ops srpt_template = {
+       .module                         = THIS_MODULE,
+       .name                           = "srpt",
        .get_fabric_name                = srpt_get_fabric_name,
        .get_fabric_proto_ident         = srpt_get_fabric_proto_ident,
        .tpg_get_wwn                    = srpt_get_fabric_wwn,
@@ -3964,6 +3960,10 @@ static struct target_core_fabric_ops srpt_template = {
        .fabric_drop_np                 = NULL,
        .fabric_make_nodeacl            = srpt_make_nodeacl,
        .fabric_drop_nodeacl            = srpt_drop_nodeacl,
+
+       .tfc_wwn_attrs                  = srpt_wwn_attrs,
+       .tfc_tpg_base_attrs             = srpt_tpg_attrs,
+       .tfc_tpg_attrib_attrs           = srpt_tpg_attrib_attrs,
 };
 
 /**
@@ -3980,7 +3980,7 @@ static int __init srpt_init_module(void)
 
        ret = -EINVAL;
        if (srp_max_req_size < MIN_MAX_REQ_SIZE) {
-               printk(KERN_ERR "invalid value %d for kernel module parameter"
+               pr_err("invalid value %d for kernel module parameter"
                       " srp_max_req_size -- must be at least %d.\n",
                       srp_max_req_size, MIN_MAX_REQ_SIZE);
                goto out;
@@ -3988,54 +3988,26 @@ static int __init srpt_init_module(void)
 
        if (srpt_srq_size < MIN_SRPT_SRQ_SIZE
            || srpt_srq_size > MAX_SRPT_SRQ_SIZE) {
-               printk(KERN_ERR "invalid value %d for kernel module parameter"
+               pr_err("invalid value %d for kernel module parameter"
                       " srpt_srq_size -- must be in the range [%d..%d].\n",
                       srpt_srq_size, MIN_SRPT_SRQ_SIZE, MAX_SRPT_SRQ_SIZE);
                goto out;
        }
 
-       srpt_target = target_fabric_configfs_init(THIS_MODULE, "srpt");
-       if (IS_ERR(srpt_target)) {
-               printk(KERN_ERR "couldn't register\n");
-               ret = PTR_ERR(srpt_target);
+       ret = target_register_template(&srpt_template);
+       if (ret)
                goto out;
-       }
-
-       srpt_target->tf_ops = srpt_template;
-
-       /*
-        * Set up default attribute lists.
-        */
-       srpt_target->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = srpt_wwn_attrs;
-       srpt_target->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = srpt_tpg_attrs;
-       srpt_target->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = srpt_tpg_attrib_attrs;
-       srpt_target->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL;
-       srpt_target->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;
-       srpt_target->tf_cit_tmpl.tfc_tpg_nacl_base_cit.ct_attrs = NULL;
-       srpt_target->tf_cit_tmpl.tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;
-       srpt_target->tf_cit_tmpl.tfc_tpg_nacl_auth_cit.ct_attrs = NULL;
-       srpt_target->tf_cit_tmpl.tfc_tpg_nacl_param_cit.ct_attrs = NULL;
-
-       ret = target_fabric_configfs_register(srpt_target);
-       if (ret < 0) {
-               printk(KERN_ERR "couldn't register\n");
-               goto out_free_target;
-       }
 
        ret = ib_register_client(&srpt_client);
        if (ret) {
-               printk(KERN_ERR "couldn't register IB client\n");
+               pr_err("couldn't register IB client\n");
                goto out_unregister_target;
        }
 
        return 0;
 
 out_unregister_target:
-       target_fabric_configfs_deregister(srpt_target);
-       srpt_target = NULL;
-out_free_target:
-       if (srpt_target)
-               target_fabric_configfs_free(srpt_target);
+       target_unregister_template(&srpt_template);
 out:
        return ret;
 }
@@ -4043,8 +4015,7 @@ out:
 static void __exit srpt_cleanup_module(void)
 {
        ib_unregister_client(&srpt_client);
-       target_fabric_configfs_deregister(srpt_target);
-       srpt_target = NULL;
+       target_unregister_template(&srpt_template);
 }
 
 module_init(srpt_init_module);
index f50f6dd92274c3d25f686c02e5f710d71a9f4102..b81c88c434521020d46d7fe4d9337fc2b5921579 100644 (file)
@@ -23,8 +23,6 @@
 
 /* #define DEBUG */
 
-#define pr_fmt(fmt) KBUILD_BASENAME ": " fmt
-
 #include <linux/input.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
@@ -116,7 +114,7 @@ int input_ff_upload(struct input_dev *dev, struct ff_effect *effect,
 
        if (effect->type < FF_EFFECT_MIN || effect->type > FF_EFFECT_MAX ||
            !test_bit(effect->type, dev->ffbit)) {
-               pr_debug("invalid or not supported effect type in upload\n");
+               dev_dbg(&dev->dev, "invalid or not supported effect type in upload\n");
                return -EINVAL;
        }
 
@@ -124,7 +122,7 @@ int input_ff_upload(struct input_dev *dev, struct ff_effect *effect,
            (effect->u.periodic.waveform < FF_WAVEFORM_MIN ||
             effect->u.periodic.waveform > FF_WAVEFORM_MAX ||
             !test_bit(effect->u.periodic.waveform, dev->ffbit))) {
-               pr_debug("invalid or not supported wave form in upload\n");
+               dev_dbg(&dev->dev, "invalid or not supported wave form in upload\n");
                return -EINVAL;
        }
 
@@ -246,7 +244,7 @@ static int flush_effects(struct input_dev *dev, struct file *file)
        struct ff_device *ff = dev->ff;
        int i;
 
-       pr_debug("flushing now\n");
+       dev_dbg(&dev->dev, "flushing now\n");
 
        mutex_lock(&ff->mutex);
 
@@ -316,7 +314,7 @@ int input_ff_create(struct input_dev *dev, unsigned int max_effects)
        int i;
 
        if (!max_effects) {
-               pr_err("cannot allocate device without any effects\n");
+               dev_err(&dev->dev, "cannot allocate device without any effects\n");
                return -EINVAL;
        }
 
index 74c0d8c6002aca6f74957c7f3a596f63e550199c..fcc6c3368182b9c376c01a4506d60a276dbceb1a 100644 (file)
@@ -237,6 +237,18 @@ static u16 ml_calculate_direction(u16 direction, u16 force,
                (force + new_force)) << 1;
 }
 
+#define FRAC_N 8
+static inline s16 fixp_new16(s16 a)
+{
+       return ((s32)a) >> (16 - FRAC_N);
+}
+
+static inline s16 fixp_mult(s16 a, s16 b)
+{
+       a = ((s32)a * 0x100) / 0x7fff;
+       return ((s32)(a * b)) >> FRAC_N;
+}
+
 /*
  * Combine two effects and apply gain.
  */
@@ -247,7 +259,7 @@ static void ml_combine_effects(struct ff_effect *effect,
        struct ff_effect *new = state->effect;
        unsigned int strong, weak, i;
        int x, y;
-       fixp_t level;
+       s16 level;
 
        switch (new->type) {
        case FF_CONSTANT:
@@ -255,8 +267,8 @@ static void ml_combine_effects(struct ff_effect *effect,
                level = fixp_new16(apply_envelope(state,
                                        new->u.constant.level,
                                        &new->u.constant.envelope));
-               x = fixp_mult(fixp_sin(i), level) * gain / 0xffff;
-               y = fixp_mult(-fixp_cos(i), level) * gain / 0xffff;
+               x = fixp_mult(fixp_sin16(i), level) * gain / 0xffff;
+               y = fixp_mult(-fixp_cos16(i), level) * gain / 0xffff;
                /*
                 * here we abuse ff_ramp to hold x and y of constant force
                 * If in future any driver wants something else than x and y
index 3aa2f3f3da5bcb2b3e8ad781b0fd3d07fd2c66e3..61c7611563712d9cfc829217701061af4bcdd3fa 100644 (file)
  *  - the iForce driver    drivers/char/joystick/iforce.c
  *  - the skeleton-driver  drivers/usb/usb-skeleton.c
  *  - Xbox 360 information http://www.free60.org/wiki/Gamepad
+ *  - Xbox One information https://github.com/quantus/xbox-one-controller-protocol
  *
  * Thanks to:
  *  - ITO Takayuki for providing essential xpad information on his website
  *  - Vojtech Pavlik     - iforce driver / input subsystem
  *  - Greg Kroah-Hartman - usb-skeleton driver
  *  - XBOX Linux project - extra USB id's
+ *  - Pekka Pöyry (quantus) - Xbox One controller reverse engineering
  *
  * TODO:
  *  - fine tune axes (especially trigger axes)
@@ -828,6 +830,23 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect
 
                        return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
 
+               case XTYPE_XBOXONE:
+                       xpad->odata[0] = 0x09; /* activate rumble */
+                       xpad->odata[1] = 0x08;
+                       xpad->odata[2] = 0x00;
+                       xpad->odata[3] = 0x08; /* continuous effect */
+                       xpad->odata[4] = 0x00; /* simple rumble mode */
+                       xpad->odata[5] = 0x03; /* L and R actuator only */
+                       xpad->odata[6] = 0x00; /* TODO: LT actuator */
+                       xpad->odata[7] = 0x00; /* TODO: RT actuator */
+                       xpad->odata[8] = strong / 256;  /* left actuator */
+                       xpad->odata[9] = weak / 256;    /* right actuator */
+                       xpad->odata[10] = 0x80; /* length of pulse */
+                       xpad->odata[11] = 0x00; /* stop period of pulse */
+                       xpad->irq_out->transfer_buffer_length = 12;
+
+                       return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
+
                default:
                        dev_dbg(&xpad->dev->dev,
                                "%s - rumble command sent to unsupported xpad type: %d\n",
@@ -841,7 +860,7 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect
 
 static int xpad_init_ff(struct usb_xpad *xpad)
 {
-       if (xpad->xtype == XTYPE_UNKNOWN || xpad->xtype == XTYPE_XBOXONE)
+       if (xpad->xtype == XTYPE_UNKNOWN)
                return 0;
 
        input_set_capability(xpad->dev, EV_FF, FF_RUMBLE);
index 64b9b59ad4cbf434e658336dc7351496ba38d94e..b50c5b8b8a4de4bc121743c4dace3aa5f4dd5636 100644 (file)
@@ -148,16 +148,19 @@ static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev,
 
 static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t *kb_state)
 {
+       int ret;
        struct cros_ec_command msg = {
-               .version = 0,
                .command = EC_CMD_MKBP_STATE,
-               .outdata = NULL,
-               .outsize = 0,
-               .indata = kb_state,
                .insize = ckdev->cols,
        };
 
-       return cros_ec_cmd_xfer(ckdev->ec, &msg);
+       ret = cros_ec_cmd_xfer(ckdev->ec, &msg);
+       if (ret < 0)
+               return ret;
+
+       memcpy(kb_state, msg.indata, ckdev->cols);
+
+       return 0;
 }
 
 static irqreturn_t cros_ec_keyb_irq(int irq, void *data)
index 9081cbef11ea126d4c46097416dce9cff21aa799..0ad422b8a2607c3cae027ca7c54b3cf0331094c3 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * LM8333 keypad driver
- * Copyright (C) 2012 Wolfram Sang, Pengutronix <w.sang@pengutronix.de>
+ * Copyright (C) 2012 Wolfram Sang, Pengutronix <kernel@pengutronix.de>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -231,6 +231,6 @@ static struct i2c_driver lm8333_driver = {
 };
 module_i2c_driver(lm8333_driver);
 
-MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>");
+MODULE_AUTHOR("Wolfram Sang <kernel@pengutronix.de>");
 MODULE_DESCRIPTION("LM8333 keyboard driver");
 MODULE_LICENSE("GPL v2");
index 4658b5d41dd715360e959f88c8810182673a20cc..7462d2fc8cfed8d4bf11d77fb2bb5e853d9f00eb 100644 (file)
@@ -149,6 +149,18 @@ config MOUSE_PS2_FOCALTECH
 
          If unsure, say Y.
 
+config MOUSE_PS2_VMMOUSE
+       bool "Virtual mouse (vmmouse)"
+       depends on MOUSE_PS2 && X86 && HYPERVISOR_GUEST
+       help
+         Say Y here if you are running under control of VMware hypervisor
+         (ESXi, Workstation or Fusion). Also make sure that when you enable
+         this option, you remove the xf86-input-vmmouse user-space driver
+         or upgrade it to at least xf86-input-vmmouse 13.0.1, which doesn't
+         load in the presence of an in-kernel vmmouse driver.
+
+         If unsure, say N.
+
 config MOUSE_SERIAL
        tristate "Serial mouse"
        select SERIO
index 8a9c98e76d9c148cfe7e424c975f02c47478f945..793300bfbddda44aba927fc4ce28650da3389b0b 100644 (file)
@@ -36,6 +36,7 @@ psmouse-$(CONFIG_MOUSE_PS2_SENTELIC)  += sentelic.o
 psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o
 psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT)   += touchkit_ps2.o
 psmouse-$(CONFIG_MOUSE_PS2_CYPRESS)    += cypress_ps2.o
+psmouse-$(CONFIG_MOUSE_PS2_VMMOUSE)    += vmmouse.o
 
 elan_i2c-objs := elan_i2c_core.o
 elan_i2c-$(CONFIG_MOUSE_ELAN_I2C_I2C)  += elan_i2c_i2c.o
index 58f4f6fa4857c34eb6a831154f039e063653992a..efe148474e7f6b4dcf758ac628bf2f081a18d6c4 100644 (file)
@@ -723,7 +723,7 @@ static ssize_t cyapa_update_suspend_scanrate(struct device *dev,
        } else if (sysfs_streq(buf, OFF_MODE_NAME)) {
                cyapa->suspend_power_mode = PWR_MODE_OFF;
        } else if (!kstrtou16(buf, 10, &sleep_time)) {
-               cyapa->suspend_sleep_time = max_t(u16, sleep_time, 1000);
+               cyapa->suspend_sleep_time = min_t(u16, sleep_time, 1000);
                cyapa->suspend_power_mode =
                        cyapa_sleep_time_to_pwr_cmd(cyapa->suspend_sleep_time);
        } else {
@@ -840,7 +840,7 @@ static ssize_t cyapa_update_rt_suspend_scanrate(struct device *dev,
        if (error)
                return error;
 
-       cyapa->runtime_suspend_sleep_time = max_t(u16, time, 1000);
+       cyapa->runtime_suspend_sleep_time = min_t(u16, time, 1000);
        cyapa->runtime_suspend_power_mode =
                cyapa_sleep_time_to_pwr_cmd(cyapa->runtime_suspend_sleep_time);
 
index 9b2dc015f20c8a24d65bb1019a2e39e8e1bf1279..6d5f8a4c1748861b547d218b4eda3ab14de5da5e 100644 (file)
@@ -25,6 +25,7 @@
 #define ETP_ENABLE_CALIBRATE   0x0002
 #define ETP_DISABLE_CALIBRATE  0x0000
 #define ETP_DISABLE_POWER      0x0001
+#define ETP_PRESSURE_OFFSET    25
 
 /* IAP Firmware handling */
 #define ETP_FW_NAME            "elan_i2c.bin"
@@ -79,6 +80,8 @@ struct elan_transport_ops {
                                struct completion *reset_done);
 
        int (*get_report)(struct i2c_client *client, u8 *report);
+       int (*get_pressure_adjustment)(struct i2c_client *client,
+                                      int *adjustment);
 };
 
 extern const struct elan_transport_ops elan_smbus_ops, elan_i2c_ops;
index 375d98f47483d309f35a561de11a376982713b17..fd5068b2542db7d58df4900058376f7285243c1e 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (c) 2013 ELAN Microelectronics Corp.
  *
  * Author: 林政維 (Duson Lin) <dusonlin@emc.com.tw>
- * Version: 1.5.6
+ * Version: 1.5.7
  *
  * Based on cyapa driver:
  * copyright (c) 2011-2012 Cypress Semiconductor, Inc.
@@ -40,8 +40,7 @@
 #include "elan_i2c.h"
 
 #define DRIVER_NAME            "elan_i2c"
-#define ELAN_DRIVER_VERSION    "1.5.6"
-#define ETP_PRESSURE_OFFSET    25
+#define ELAN_DRIVER_VERSION    "1.5.7"
 #define ETP_MAX_PRESSURE       255
 #define ETP_FWIDTH_REDUCE      90
 #define ETP_FINGER_WIDTH       15
@@ -53,6 +52,7 @@
 #define ETP_REPORT_ID_OFFSET   2
 #define ETP_TOUCH_INFO_OFFSET  3
 #define ETP_FINGER_DATA_OFFSET 4
+#define ETP_HOVER_INFO_OFFSET  30
 #define ETP_MAX_REPORT_LEN     34
 
 /* The main device structure */
@@ -81,7 +81,7 @@ struct elan_tp_data {
        u8                      sm_version;
        u8                      iap_version;
        u16                     fw_checksum;
-
+       int                     pressure_adjustment;
        u8                      mode;
 
        bool                    irq_wake;
@@ -229,6 +229,11 @@ static int elan_query_device_info(struct elan_tp_data *data)
        if (error)
                return error;
 
+       error = data->ops->get_pressure_adjustment(data->client,
+                                                  &data->pressure_adjustment);
+       if (error)
+               return error;
+
        return 0;
 }
 
@@ -721,13 +726,13 @@ static const struct attribute_group *elan_sysfs_groups[] = {
  */
 static void elan_report_contact(struct elan_tp_data *data,
                                int contact_num, bool contact_valid,
-                               u8 *finger_data)
+                               bool hover_event, u8 *finger_data)
 {
        struct input_dev *input = data->input;
        unsigned int pos_x, pos_y;
        unsigned int pressure, mk_x, mk_y;
-       unsigned int area_x, area_y, major, minor, new_pressure;
-
+       unsigned int area_x, area_y, major, minor;
+       unsigned int scaled_pressure;
 
        if (contact_valid) {
                pos_x = ((finger_data[0] & 0xf0) << 4) |
@@ -756,15 +761,18 @@ static void elan_report_contact(struct elan_tp_data *data,
                major = max(area_x, area_y);
                minor = min(area_x, area_y);
 
-               new_pressure = pressure + ETP_PRESSURE_OFFSET;
-               if (new_pressure > ETP_MAX_PRESSURE)
-                       new_pressure = ETP_MAX_PRESSURE;
+               scaled_pressure = pressure + data->pressure_adjustment;
+
+               if (scaled_pressure > ETP_MAX_PRESSURE)
+                       scaled_pressure = ETP_MAX_PRESSURE;
 
                input_mt_slot(input, contact_num);
                input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
                input_report_abs(input, ABS_MT_POSITION_X, pos_x);
                input_report_abs(input, ABS_MT_POSITION_Y, data->max_y - pos_y);
-               input_report_abs(input, ABS_MT_PRESSURE, new_pressure);
+               input_report_abs(input, ABS_MT_DISTANCE, hover_event);
+               input_report_abs(input, ABS_MT_PRESSURE,
+                                hover_event ? 0 : scaled_pressure);
                input_report_abs(input, ABS_TOOL_WIDTH, mk_x);
                input_report_abs(input, ABS_MT_TOUCH_MAJOR, major);
                input_report_abs(input, ABS_MT_TOUCH_MINOR, minor);
@@ -780,11 +788,14 @@ static void elan_report_absolute(struct elan_tp_data *data, u8 *packet)
        u8 *finger_data = &packet[ETP_FINGER_DATA_OFFSET];
        int i;
        u8 tp_info = packet[ETP_TOUCH_INFO_OFFSET];
-       bool contact_valid;
+       u8 hover_info = packet[ETP_HOVER_INFO_OFFSET];
+       bool contact_valid, hover_event;
 
+       hover_event = hover_info & 0x40;
        for (i = 0; i < ETP_MAX_FINGERS; i++) {
                contact_valid = tp_info & (1U << (3 + i));
-               elan_report_contact(data, i, contact_valid, finger_data);
+               elan_report_contact(data, i, contact_valid, hover_event,
+                                   finger_data);
 
                if (contact_valid)
                        finger_data += ETP_FINGER_DATA_LEN;
@@ -878,6 +889,7 @@ static int elan_setup_input_device(struct elan_tp_data *data)
                             ETP_FINGER_WIDTH * max_width, 0, 0);
        input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0,
                             ETP_FINGER_WIDTH * min_width, 0, 0);
+       input_set_abs_params(input, ABS_MT_DISTANCE, 0, 1, 0, 0);
 
        data->input = input;
 
index 6cf0def6d35ee764cb686bb5c9d2f90bb9f81a86..a0acbbf83bfd4faaa7d14a09dbe332848dc648e4 100644 (file)
@@ -41,6 +41,7 @@
 #define ETP_I2C_MAX_X_AXIS_CMD         0x0106
 #define ETP_I2C_MAX_Y_AXIS_CMD         0x0107
 #define ETP_I2C_RESOLUTION_CMD         0x0108
+#define ETP_I2C_PRESSURE_CMD           0x010A
 #define ETP_I2C_IAP_VERSION_CMD                0x0110
 #define ETP_I2C_SET_CMD                        0x0300
 #define ETP_I2C_POWER_CMD              0x0307
@@ -364,8 +365,29 @@ static int elan_i2c_get_num_traces(struct i2c_client *client,
                return error;
        }
 
-       *x_traces = val[0] - 1;
-       *y_traces = val[1] - 1;
+       *x_traces = val[0];
+       *y_traces = val[1];
+
+       return 0;
+}
+
+static int elan_i2c_get_pressure_adjustment(struct i2c_client *client,
+                                           int *adjustment)
+{
+       int error;
+       u8 val[3];
+
+       error = elan_i2c_read_cmd(client, ETP_I2C_PRESSURE_CMD, val);
+       if (error) {
+               dev_err(&client->dev, "failed to get pressure format: %d\n",
+                       error);
+               return error;
+       }
+
+       if ((val[0] >> 4) & 0x1)
+               *adjustment = 0;
+       else
+               *adjustment = ETP_PRESSURE_OFFSET;
 
        return 0;
 }
@@ -602,6 +624,7 @@ const struct elan_transport_ops elan_i2c_ops = {
        .get_sm_version         = elan_i2c_get_sm_version,
        .get_product_id         = elan_i2c_get_product_id,
        .get_checksum           = elan_i2c_get_checksum,
+       .get_pressure_adjustment = elan_i2c_get_pressure_adjustment,
 
        .get_max                = elan_i2c_get_max,
        .get_resolution         = elan_i2c_get_resolution,
index 06a2bcd1cda267f87cfe11b8eb09fe4d8bb52aaf..30ab80dbcdd6e013d6854c63fb7bbe1874169596 100644 (file)
@@ -268,12 +268,19 @@ static int elan_smbus_get_num_traces(struct i2c_client *client,
                return error;
        }
 
-       *x_traces = val[1] - 1;
-       *y_traces = val[2] - 1;
+       *x_traces = val[1];
+       *y_traces = val[2];
 
        return 0;
 }
 
+static int elan_smbus_get_pressure_adjustment(struct i2c_client *client,
+                                             int *adjustment)
+{
+       *adjustment = ETP_PRESSURE_OFFSET;
+       return 0;
+}
+
 static int elan_smbus_iap_get_mode(struct i2c_client *client,
                                   enum tp_mode *mode)
 {
@@ -497,6 +504,7 @@ const struct elan_transport_ops elan_smbus_ops = {
        .get_sm_version         = elan_smbus_get_sm_version,
        .get_product_id         = elan_smbus_get_product_id,
        .get_checksum           = elan_smbus_get_checksum,
+       .get_pressure_adjustment = elan_smbus_get_pressure_adjustment,
 
        .get_max                = elan_smbus_get_max,
        .get_resolution         = elan_smbus_get_resolution,
index 27057df7ba74eeeba06f24f0e24fcf6d4387eda3..5bb1658f60c746f29efd4f5d7008068701f4d08d 100644 (file)
@@ -36,6 +36,7 @@
 #include "sentelic.h"
 #include "cypress_ps2.h"
 #include "focaltech.h"
+#include "vmmouse.h"
 
 #define DRIVER_DESC    "PS/2 mouse driver"
 
@@ -790,6 +791,13 @@ static int psmouse_extensions(struct psmouse *psmouse,
                }
        }
 
+       if (psmouse_do_detect(vmmouse_detect, psmouse, set_properties) == 0) {
+               if (max_proto > PSMOUSE_IMEX) {
+                       if (!set_properties || vmmouse_init(psmouse) == 0)
+                               return PSMOUSE_VMMOUSE;
+               }
+       }
+
 /*
  * Try Kensington ThinkingMouse (we try first, because synaptics probe
  * upsets the thinkingmouse).
@@ -1112,6 +1120,15 @@ static const struct psmouse_protocol psmouse_protocols[] = {
                .detect         = focaltech_detect,
                .init           = focaltech_init,
        },
+#endif
+#ifdef CONFIG_MOUSE_PS2_VMMOUSE
+       {
+               .type           = PSMOUSE_VMMOUSE,
+               .name           = VMMOUSE_PSNAME,
+               .alias          = "vmmouse",
+               .detect         = vmmouse_detect,
+               .init           = vmmouse_init,
+       },
 #endif
        {
                .type           = PSMOUSE_AUTO,
index d02e1bdc9ae4934d56e5290f8adedcb3a2297566..ad5a5a1ea872cd17389d623e109e0299b90f1429 100644 (file)
@@ -103,6 +103,7 @@ enum psmouse_type {
        PSMOUSE_SYNAPTICS_RELATIVE,
        PSMOUSE_CYPRESS,
        PSMOUSE_FOCALTECH,
+       PSMOUSE_VMMOUSE,
        PSMOUSE_AUTO            /* This one should always be last */
 };
 
diff --git a/drivers/input/mouse/vmmouse.c b/drivers/input/mouse/vmmouse.c
new file mode 100644 (file)
index 0000000..e272f06
--- /dev/null
@@ -0,0 +1,508 @@
+/*
+ * Driver for Virtual PS/2 Mouse on VMware and QEMU hypervisors.
+ *
+ * Copyright (C) 2014, VMware, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * Twin device code is hugely inspired by the ALPS driver.
+ * Authors:
+ *   Dmitry Torokhov <dmitry.torokhov@gmail.com>
+ *   Thomas Hellstrom <thellstrom@vmware.com>
+ */
+
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/libps2.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <asm/hypervisor.h>
+
+#include "psmouse.h"
+#include "vmmouse.h"
+
+#define VMMOUSE_PROTO_MAGIC                    0x564D5868U
+#define VMMOUSE_PROTO_PORT                     0x5658
+
+/*
+ * Main commands supported by the vmmouse hypervisor port.
+ */
+#define VMMOUSE_PROTO_CMD_GETVERSION           10
+#define VMMOUSE_PROTO_CMD_ABSPOINTER_DATA      39
+#define VMMOUSE_PROTO_CMD_ABSPOINTER_STATUS    40
+#define VMMOUSE_PROTO_CMD_ABSPOINTER_COMMAND   41
+#define VMMOUSE_PROTO_CMD_ABSPOINTER_RESTRICT   86
+
+/*
+ * Subcommands for VMMOUSE_PROTO_CMD_ABSPOINTER_COMMAND
+ */
+#define VMMOUSE_CMD_ENABLE                     0x45414552U
+#define VMMOUSE_CMD_DISABLE                    0x000000f5U
+#define VMMOUSE_CMD_REQUEST_RELATIVE           0x4c455252U
+#define VMMOUSE_CMD_REQUEST_ABSOLUTE           0x53424152U
+
+#define VMMOUSE_ERROR                          0xffff0000U
+
+#define VMMOUSE_VERSION_ID                     0x3442554aU
+
+#define VMMOUSE_RELATIVE_PACKET                        0x00010000U
+
+#define VMMOUSE_LEFT_BUTTON                    0x20
+#define VMMOUSE_RIGHT_BUTTON                   0x10
+#define VMMOUSE_MIDDLE_BUTTON                  0x08
+
+/*
+ * VMMouse Restrict command
+ */
+#define VMMOUSE_RESTRICT_ANY                    0x00
+#define VMMOUSE_RESTRICT_CPL0                   0x01
+#define VMMOUSE_RESTRICT_IOPL                   0x02
+
+#define VMMOUSE_MAX_X                           0xFFFF
+#define VMMOUSE_MAX_Y                           0xFFFF
+
+#define VMMOUSE_VENDOR "VMware"
+#define VMMOUSE_NAME   "VMMouse"
+
+/**
+ * struct vmmouse_data - private data structure for the vmmouse driver
+ *
+ * @abs_dev: "Absolute" device used to report absolute mouse movement.
+ * @phys: Physical path for the absolute device.
+ * @dev_name: Name attribute name for the absolute device.
+ */
+struct vmmouse_data {
+       struct input_dev *abs_dev;
+       char phys[32];
+       char dev_name[128];
+};
+
+/**
+ * Hypervisor-specific bi-directional communication channel
+ * implementing the vmmouse protocol. Should never execute on
+ * bare metal hardware.
+ */
+#define VMMOUSE_CMD(cmd, in1, out1, out2, out3, out4)  \
+({                                                     \
+       unsigned long __dummy1, __dummy2;               \
+       __asm__ __volatile__ ("inl %%dx" :              \
+               "=a"(out1),                             \
+               "=b"(out2),                             \
+               "=c"(out3),                             \
+               "=d"(out4),                             \
+               "=S"(__dummy1),                         \
+               "=D"(__dummy2) :                        \
+               "a"(VMMOUSE_PROTO_MAGIC),               \
+               "b"(in1),                               \
+               "c"(VMMOUSE_PROTO_CMD_##cmd),           \
+               "d"(VMMOUSE_PROTO_PORT) :               \
+               "memory");                              \
+})
+
+/**
+ * vmmouse_report_button - report button state on the correct input device
+ *
+ * @psmouse:  Pointer to the psmouse struct
+ * @abs_dev:  The absolute input device
+ * @rel_dev:  The relative input device
+ * @pref_dev: The preferred device for reporting
+ * @code:     Button code
+ * @value:    Button value
+ *
+ * Report @value and @code on @pref_dev, unless the button is already
+ * pressed on the other device, in which case the state is reported on that
+ * device.
+ */
+static void vmmouse_report_button(struct psmouse *psmouse,
+                                 struct input_dev *abs_dev,
+                                 struct input_dev *rel_dev,
+                                 struct input_dev *pref_dev,
+                                 unsigned int code, int value)
+{
+       if (test_bit(code, abs_dev->key))
+               pref_dev = abs_dev;
+       else if (test_bit(code, rel_dev->key))
+               pref_dev = rel_dev;
+
+       input_report_key(pref_dev, code, value);
+}
+
+/**
+ * vmmouse_report_events - process events on the vmmouse communications channel
+ *
+ * @psmouse: Pointer to the psmouse struct
+ *
+ * This function pulls events from the vmmouse communications channel and
+ * reports them on the correct (absolute or relative) input device. When the
+ * communications channel is drained, or if we've processed more than 255
+ * psmouse commands, the function returns PSMOUSE_FULL_PACKET. If there is a
+ * host- or synchronization error, the function returns PSMOUSE_BAD_DATA in
+ * the hope that the caller will reset the communications channel.
+ */
+static psmouse_ret_t vmmouse_report_events(struct psmouse *psmouse)
+{
+       struct input_dev *rel_dev = psmouse->dev;
+       struct vmmouse_data *priv = psmouse->private;
+       struct input_dev *abs_dev = priv->abs_dev;
+       struct input_dev *pref_dev;
+       u32 status, x, y, z;
+       u32 dummy1, dummy2, dummy3;
+       unsigned int queue_length;
+       unsigned int count = 255;
+
+       while (count--) {
+               /* See if we have motion data. */
+               VMMOUSE_CMD(ABSPOINTER_STATUS, 0,
+                           status, dummy1, dummy2, dummy3);
+               if ((status & VMMOUSE_ERROR) == VMMOUSE_ERROR) {
+                       psmouse_err(psmouse, "failed to fetch status data\n");
+                       /*
+                        * After a few attempts this will result in
+                        * reconnect.
+                        */
+                       return PSMOUSE_BAD_DATA;
+               }
+
+               queue_length = status & 0xffff;
+               if (queue_length == 0)
+                       break;
+
+               if (queue_length % 4) {
+                       psmouse_err(psmouse, "invalid queue length\n");
+                       return PSMOUSE_BAD_DATA;
+               }
+
+               /* Now get it */
+               VMMOUSE_CMD(ABSPOINTER_DATA, 4, status, x, y, z);
+
+               /*
+                * And report what we've got. Prefer to report button
+                * events on the same device where we report motion events.
+                * This doesn't work well with the mouse wheel, though. See
+                * below. Ideally we would want to report that on the
+                * preferred device as well.
+                */
+               if (status & VMMOUSE_RELATIVE_PACKET) {
+                       pref_dev = rel_dev;
+                       input_report_rel(rel_dev, REL_X, (s32)x);
+                       input_report_rel(rel_dev, REL_Y, -(s32)y);
+               } else {
+                       pref_dev = abs_dev;
+                       input_report_abs(abs_dev, ABS_X, x);
+                       input_report_abs(abs_dev, ABS_Y, y);
+               }
+
+               /* Xorg seems to ignore wheel events on absolute devices */
+               input_report_rel(rel_dev, REL_WHEEL, -(s8)((u8) z));
+
+               vmmouse_report_button(psmouse, abs_dev, rel_dev,
+                                     pref_dev, BTN_LEFT,
+                                     status & VMMOUSE_LEFT_BUTTON);
+               vmmouse_report_button(psmouse, abs_dev, rel_dev,
+                                     pref_dev, BTN_RIGHT,
+                                     status & VMMOUSE_RIGHT_BUTTON);
+               vmmouse_report_button(psmouse, abs_dev, rel_dev,
+                                     pref_dev, BTN_MIDDLE,
+                                     status & VMMOUSE_MIDDLE_BUTTON);
+               input_sync(abs_dev);
+               input_sync(rel_dev);
+       }
+
+       return PSMOUSE_FULL_PACKET;
+}
+
+/**
+ * vmmouse_process_byte - process data on the ps/2 channel
+ *
+ * @psmouse: Pointer to the psmouse struct
+ *
+ * When the ps/2 channel indicates that there is vmmouse data available,
+ * call vmmouse channel processing. Otherwise, continue to accept bytes. If
+ * there is a synchronization or communication data error, return
+ * PSMOUSE_BAD_DATA in the hope that the caller will reset the mouse.
+ */
+static psmouse_ret_t vmmouse_process_byte(struct psmouse *psmouse)
+{
+       unsigned char *packet = psmouse->packet;
+
+       switch (psmouse->pktcnt) {
+       case 1:
+               return (packet[0] & 0x8) == 0x8 ?
+                       PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA;
+
+       case 2:
+               return PSMOUSE_GOOD_DATA;
+
+       default:
+               return vmmouse_report_events(psmouse);
+       }
+}
+
+/**
+ * vmmouse_disable - Disable vmmouse
+ *
+ * @psmouse: Pointer to the psmouse struct
+ *
+ * Tries to disable vmmouse mode.
+ */
+static void vmmouse_disable(struct psmouse *psmouse)
+{
+       u32 status;
+       u32 dummy1, dummy2, dummy3, dummy4;
+
+       VMMOUSE_CMD(ABSPOINTER_COMMAND, VMMOUSE_CMD_DISABLE,
+                   dummy1, dummy2, dummy3, dummy4);
+
+       VMMOUSE_CMD(ABSPOINTER_STATUS, 0,
+                   status, dummy1, dummy2, dummy3);
+
+       if ((status & VMMOUSE_ERROR) != VMMOUSE_ERROR)
+               psmouse_warn(psmouse, "failed to disable vmmouse device\n");
+}
+
+/**
+ * vmmouse_enable - Enable vmmouse and request absolute mode.
+ *
+ * @psmouse: Pointer to the psmouse struct
+ *
+ * Tries to enable vmmouse mode. Performs basic checks and requests
+ * absolute vmmouse mode.
+ * Returns 0 on success, -ENODEV on failure.
+ */
+static int vmmouse_enable(struct psmouse *psmouse)
+{
+       u32 status, version;
+       u32 dummy1, dummy2, dummy3, dummy4;
+
+       /*
+        * Try enabling the device. If successful, we should be able to
+        * read valid version ID back from it.
+        */
+       VMMOUSE_CMD(ABSPOINTER_COMMAND, VMMOUSE_CMD_ENABLE,
+                   dummy1, dummy2, dummy3, dummy4);
+
+       /*
+        * See if version ID can be retrieved.
+        */
+       VMMOUSE_CMD(ABSPOINTER_STATUS, 0, status, dummy1, dummy2, dummy3);
+       if ((status & 0x0000ffff) == 0) {
+               psmouse_dbg(psmouse, "empty flags - assuming no device\n");
+               return -ENXIO;
+       }
+
+       VMMOUSE_CMD(ABSPOINTER_DATA, 1 /* single item */,
+                   version, dummy1, dummy2, dummy3);
+       if (version != VMMOUSE_VERSION_ID) {
+               psmouse_dbg(psmouse, "Unexpected version value: %u vs %u\n",
+                           (unsigned) version, VMMOUSE_VERSION_ID);
+               vmmouse_disable(psmouse);
+               return -ENXIO;
+       }
+
+       /*
+        * Restrict ioport access, if possible.
+        */
+       VMMOUSE_CMD(ABSPOINTER_RESTRICT, VMMOUSE_RESTRICT_CPL0,
+                   dummy1, dummy2, dummy3, dummy4);
+
+       VMMOUSE_CMD(ABSPOINTER_COMMAND, VMMOUSE_CMD_REQUEST_ABSOLUTE,
+                   dummy1, dummy2, dummy3, dummy4);
+
+       return 0;
+}
+
+/*
+ * Array of supported hypervisors.
+ */
+static const struct hypervisor_x86 *vmmouse_supported_hypervisors[] = {
+       &x86_hyper_vmware,
+#ifdef CONFIG_KVM_GUEST
+       &x86_hyper_kvm,
+#endif
+};
+
+/**
+ * vmmouse_check_hypervisor - Check if we're running on a supported hypervisor
+ */
+static bool vmmouse_check_hypervisor(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(vmmouse_supported_hypervisors); i++)
+               if (vmmouse_supported_hypervisors[i] == x86_hyper)
+                       return true;
+
+       return false;
+}
+
+/**
+ * vmmouse_detect - Probe whether vmmouse is available
+ *
+ * @psmouse: Pointer to the psmouse struct
+ * @set_properties: Whether to set psmouse name and vendor
+ *
+ * Returns 0 if vmmouse channel is available. Negative error code if not.
+ */
+int vmmouse_detect(struct psmouse *psmouse, bool set_properties)
+{
+       u32 response, version, dummy1, dummy2;
+
+       if (!vmmouse_check_hypervisor()) {
+               psmouse_dbg(psmouse,
+                           "VMMouse not running on supported hypervisor.\n");
+               return -ENXIO;
+       }
+
+       if (!request_region(VMMOUSE_PROTO_PORT, 4, "vmmouse")) {
+               psmouse_dbg(psmouse, "VMMouse port in use.\n");
+               return -EBUSY;
+       }
+
+       /* Check if the device is present */
+       response = ~VMMOUSE_PROTO_MAGIC;
+       VMMOUSE_CMD(GETVERSION, 0, version, response, dummy1, dummy2);
+       if (response != VMMOUSE_PROTO_MAGIC || version == 0xffffffffU) {
+               release_region(VMMOUSE_PROTO_PORT, 4);
+               return -ENXIO;
+       }
+
+       if (set_properties) {
+               psmouse->vendor = VMMOUSE_VENDOR;
+               psmouse->name = VMMOUSE_NAME;
+               psmouse->model = version;
+       }
+
+       release_region(VMMOUSE_PROTO_PORT, 4);
+
+       return 0;
+}
+
+/**
+ * vmmouse_disconnect - Take down vmmouse driver
+ *
+ * @psmouse: Pointer to the psmouse struct
+ *
+ * Takes down vmmouse driver and frees resources set up in vmmouse_init().
+ */
+static void vmmouse_disconnect(struct psmouse *psmouse)
+{
+       struct vmmouse_data *priv = psmouse->private;
+
+       vmmouse_disable(psmouse);
+       psmouse_reset(psmouse);
+       input_unregister_device(priv->abs_dev);
+       kfree(priv);
+       release_region(VMMOUSE_PROTO_PORT, 4);
+}
+
+/**
+ * vmmouse_reconnect - Reset the ps/2 - and vmmouse connections
+ *
+ * @psmouse: Pointer to the psmouse struct
+ *
+ * Attempts to reset the mouse connections. Returns 0 on success and
+ * -1 on failure.
+ */
+static int vmmouse_reconnect(struct psmouse *psmouse)
+{
+       int error;
+
+       psmouse_reset(psmouse);
+       vmmouse_disable(psmouse);
+       error = vmmouse_enable(psmouse);
+       if (error) {
+               psmouse_err(psmouse,
+                           "Unable to re-enable mouse when reconnecting, err: %d\n",
+                           error);
+               return error;
+       }
+
+       return 0;
+}
+
+/**
+ * vmmouse_init - Initialize the vmmouse driver
+ *
+ * @psmouse: Pointer to the psmouse struct
+ *
+ * Requests the device and tries to enable vmmouse mode.
+ * If successful, sets up the input device for relative movement events.
+ * It also allocates another input device and sets it up for absolute motion
+ * events. Returns 0 on success and -1 on failure.
+ */
+int vmmouse_init(struct psmouse *psmouse)
+{
+       struct vmmouse_data *priv;
+       struct input_dev *rel_dev = psmouse->dev, *abs_dev;
+       int error;
+
+       if (!request_region(VMMOUSE_PROTO_PORT, 4, "vmmouse")) {
+               psmouse_dbg(psmouse, "VMMouse port in use.\n");
+               return -EBUSY;
+       }
+
+       psmouse_reset(psmouse);
+       error = vmmouse_enable(psmouse);
+       if (error)
+               goto release_region;
+
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       abs_dev = input_allocate_device();
+       if (!priv || !abs_dev) {
+               error = -ENOMEM;
+               goto init_fail;
+       }
+
+       priv->abs_dev = abs_dev;
+       psmouse->private = priv;
+
+       input_set_capability(rel_dev, EV_REL, REL_WHEEL);
+
+       /* Set up and register absolute device */
+       snprintf(priv->phys, sizeof(priv->phys), "%s/input1",
+                psmouse->ps2dev.serio->phys);
+
+       /* Mimic name setup for relative device in psmouse-base.c */
+       snprintf(priv->dev_name, sizeof(priv->dev_name), "%s %s %s",
+                VMMOUSE_PSNAME, VMMOUSE_VENDOR, VMMOUSE_NAME);
+       abs_dev->phys = priv->phys;
+       abs_dev->name = priv->dev_name;
+       abs_dev->id.bustype = BUS_I8042;
+       abs_dev->id.vendor = 0x0002;
+       abs_dev->id.product = PSMOUSE_VMMOUSE;
+       abs_dev->id.version = psmouse->model;
+       abs_dev->dev.parent = &psmouse->ps2dev.serio->dev;
+
+       error = input_register_device(priv->abs_dev);
+       if (error)
+               goto init_fail;
+
+       /* Set absolute device capabilities */
+       input_set_capability(abs_dev, EV_KEY, BTN_LEFT);
+       input_set_capability(abs_dev, EV_KEY, BTN_RIGHT);
+       input_set_capability(abs_dev, EV_KEY, BTN_MIDDLE);
+       input_set_capability(abs_dev, EV_ABS, ABS_X);
+       input_set_capability(abs_dev, EV_ABS, ABS_Y);
+       input_set_abs_params(abs_dev, ABS_X, 0, VMMOUSE_MAX_X, 0, 0);
+       input_set_abs_params(abs_dev, ABS_Y, 0, VMMOUSE_MAX_Y, 0, 0);
+
+       psmouse->protocol_handler = vmmouse_process_byte;
+       psmouse->disconnect = vmmouse_disconnect;
+       psmouse->reconnect = vmmouse_reconnect;
+
+       return 0;
+
+init_fail:
+       vmmouse_disable(psmouse);
+       psmouse_reset(psmouse);
+       input_free_device(abs_dev);
+       kfree(priv);
+       psmouse->private = NULL;
+
+release_region:
+       release_region(VMMOUSE_PROTO_PORT, 4);
+
+       return error;
+}
diff --git a/drivers/input/mouse/vmmouse.h b/drivers/input/mouse/vmmouse.h
new file mode 100644 (file)
index 0000000..6f12601
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Driver for Virtual PS/2 Mouse on VMware and QEMU hypervisors.
+ *
+ * Copyright (C) 2014, VMware, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#ifndef _VMMOUSE_H
+#define _VMMOUSE_H
+
+#ifdef CONFIG_MOUSE_PS2_VMMOUSE
+#define VMMOUSE_PSNAME  "VirtualPS/2"
+
+int vmmouse_detect(struct psmouse *psmouse, bool set_properties);
+int vmmouse_init(struct psmouse *psmouse);
+#else
+static inline int vmmouse_detect(struct psmouse *psmouse, bool set_properties)
+{
+       return -ENOSYS;
+}
+static inline int vmmouse_init(struct psmouse *psmouse)
+{
+       return -ENOSYS;
+}
+#endif
+
+#endif
index 547f67d653728a09601f43ce9beb8a6471ff2145..80f6386709bffc7330499694968c43e62e331ded 100644 (file)
@@ -980,7 +980,9 @@ config TOUCHSCREEN_SUN4I
 config TOUCHSCREEN_SUR40
        tristate "Samsung SUR40 (Surface 2.0/PixelSense) touchscreen"
        depends on USB
+       depends on MEDIA_USB_SUPPORT
        select INPUT_POLLDEV
+       select VIDEOBUF2_DMA_SG
        help
          Say Y here if you want support for the Samsung SUR40 touchscreen
          (also known as Microsoft Surface 2.0 or Microsoft PixelSense).
index 2875ddf37289521c2059ad64d1301e6bb40b3ba4..40b98dda8f38be802c7896e4652bb7591c57c88c 100644 (file)
@@ -14,6 +14,8 @@
  *
  */
 
+#include <linux/acpi.h>
+#include <linux/dmi.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/completion.h>
@@ -2371,7 +2373,7 @@ static void mxt_input_close(struct input_dev *dev)
 }
 
 #ifdef CONFIG_OF
-static struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client)
+static const struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client)
 {
        struct mxt_platform_data *pdata;
        u32 *keymap;
@@ -2379,7 +2381,7 @@ static struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client)
        int proplen, i, ret;
 
        if (!client->dev.of_node)
-               return ERR_PTR(-ENODEV);
+               return ERR_PTR(-ENOENT);
 
        pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
        if (!pdata)
@@ -2410,25 +2412,132 @@ static struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client)
        return pdata;
 }
 #else
-static struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client)
+static const struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client)
 {
-       dev_dbg(&client->dev, "No platform data specified\n");
-       return ERR_PTR(-EINVAL);
+       return ERR_PTR(-ENOENT);
+}
+#endif
+
+#ifdef CONFIG_ACPI
+
+struct mxt_acpi_platform_data {
+       const char *hid;
+       struct mxt_platform_data pdata;
+};
+
+static unsigned int samus_touchpad_buttons[] = {
+       KEY_RESERVED,
+       KEY_RESERVED,
+       KEY_RESERVED,
+       BTN_LEFT
+};
+
+static struct mxt_acpi_platform_data samus_platform_data[] = {
+       {
+               /* Touchpad */
+               .hid    = "ATML0000",
+               .pdata  = {
+                       .t19_num_keys   = ARRAY_SIZE(samus_touchpad_buttons),
+                       .t19_keymap     = samus_touchpad_buttons,
+               },
+       },
+       {
+               /* Touchscreen */
+               .hid    = "ATML0001",
+       },
+       { }
+};
+
+static const struct dmi_system_id mxt_dmi_table[] = {
+       {
+               /* 2015 Google Pixel */
+               .ident = "Chromebook Pixel 2",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Samus"),
+               },
+               .driver_data = samus_platform_data,
+       },
+       { }
+};
+
+static const struct mxt_platform_data *mxt_parse_acpi(struct i2c_client *client)
+{
+       struct acpi_device *adev;
+       const struct dmi_system_id *system_id;
+       const struct mxt_acpi_platform_data *acpi_pdata;
+
+       /*
+        * Ignore ACPI devices representing bootloader mode.
+        *
+        * This is a bit of a hack: Google Chromebook BIOS creates ACPI
+        * devices for both application and bootloader modes, but we are
+        * interested in application mode only (if device is in bootloader
+        * mode we'll end up switching into application anyway). So far
+        * application mode addresses were all above 0x40, so we'll use it
+        * as a threshold.
+        */
+       if (client->addr < 0x40)
+               return ERR_PTR(-ENXIO);
+
+       adev = ACPI_COMPANION(&client->dev);
+       if (!adev)
+               return ERR_PTR(-ENOENT);
+
+       system_id = dmi_first_match(mxt_dmi_table);
+       if (!system_id)
+               return ERR_PTR(-ENOENT);
+
+       acpi_pdata = system_id->driver_data;
+       if (!acpi_pdata)
+               return ERR_PTR(-ENOENT);
+
+       while (acpi_pdata->hid) {
+               if (!strcmp(acpi_device_hid(adev), acpi_pdata->hid))
+                       return &acpi_pdata->pdata;
+
+               acpi_pdata++;
+       }
+
+       return ERR_PTR(-ENOENT);
+}
+#else
+static const struct mxt_platform_data *mxt_parse_acpi(struct i2c_client *client)
+{
+       return ERR_PTR(-ENOENT);
 }
 #endif
 
+static const struct mxt_platform_data *
+mxt_get_platform_data(struct i2c_client *client)
+{
+       const struct mxt_platform_data *pdata;
+
+       pdata = dev_get_platdata(&client->dev);
+       if (pdata)
+               return pdata;
+
+       pdata = mxt_parse_dt(client);
+       if (!IS_ERR(pdata) || PTR_ERR(pdata) != -ENOENT)
+               return pdata;
+
+       pdata = mxt_parse_acpi(client);
+       if (!IS_ERR(pdata) || PTR_ERR(pdata) != -ENOENT)
+               return pdata;
+
+       dev_err(&client->dev, "No platform data specified\n");
+       return ERR_PTR(-EINVAL);
+}
+
 static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
        struct mxt_data *data;
        const struct mxt_platform_data *pdata;
        int error;
 
-       pdata = dev_get_platdata(&client->dev);
-       if (!pdata) {
-               pdata = mxt_parse_dt(client);
-               if (IS_ERR(pdata))
-                       return PTR_ERR(pdata);
-       }
+       pdata = mxt_get_platform_data(client);
+       if (IS_ERR(pdata))
+               return PTR_ERR(pdata);
 
        data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
        if (!data) {
@@ -2536,6 +2645,15 @@ static const struct of_device_id mxt_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, mxt_of_match);
 
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id mxt_acpi_id[] = {
+       { "ATML0000", 0 },      /* Touchpad */
+       { "ATML0001", 0 },      /* Touchscreen */
+       { }
+};
+MODULE_DEVICE_TABLE(acpi, mxt_acpi_id);
+#endif
+
 static const struct i2c_device_id mxt_id[] = {
        { "qt602240_ts", 0 },
        { "atmel_mxt_ts", 0 },
@@ -2550,6 +2668,7 @@ static struct i2c_driver mxt_driver = {
                .name   = "atmel_mxt_ts",
                .owner  = THIS_MODULE,
                .of_match_table = of_match_ptr(mxt_of_match),
+               .acpi_match_table = ACPI_PTR(mxt_acpi_id),
                .pm     = &mxt_pm_ops,
        },
        .probe          = mxt_probe,
index 43b3c9c2d788ed2637178e4e6b4395cec3a552af..0efd766a545bc677cce1fa2f753265dd06bfe8d9 100644 (file)
@@ -699,7 +699,7 @@ static int elants_i2c_fw_update(struct elants_data *ts)
        char *fw_name;
        int error;
 
-       fw_name = kasprintf(GFP_KERNEL, "elants_i2c_%4x.bin", ts->hw_version);
+       fw_name = kasprintf(GFP_KERNEL, "elants_i2c_%04x.bin", ts->hw_version);
        if (!fw_name)
                return -ENOMEM;
 
index f1cb05148b46826c7075e238f24e530a6a32720c..a24eba5ea843e632af7e07962e520d2271f7ae6b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Surface2.0/SUR40/PixelSense input driver
  *
- * Copyright (c) 2013 by Florian 'floe' Echtler <floe@butterbrot.org>
+ * Copyright (c) 2014 by Florian 'floe' Echtler <floe@butterbrot.org>
  *
  * Derived from the USB Skeleton driver 1.1,
  * Copyright (c) 2003 Greg Kroah-Hartman (greg@kroah.com)
@@ -12,6 +12,9 @@
  * and from the generic hid-multitouch driver,
  * Copyright (c) 2010-2012 Stephane Chatty <chatty@enac.fr>
  *
+ * and from the v4l2-pci-skeleton driver,
+ * Copyright (c) Copyright 2014 Cisco Systems, 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
 #include <linux/input-polldev.h>
 #include <linux/input/mt.h>
 #include <linux/usb/input.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf2-dma-sg.h>
 
 /* read 512 bytes from endpoint 0x86 -> get header + blobs */
 struct sur40_header {
@@ -82,9 +90,19 @@ struct sur40_data {
        struct sur40_blob   blobs[];
 } __packed;
 
+/* read 512 bytes from endpoint 0x82 -> get header below
+ * continue reading 16k blocks until header.size bytes read */
+struct sur40_image_header {
+       __le32 magic;     /* "SUBF" */
+       __le32 packet_id;
+       __le32 size;      /* always 0x0007e900 = 960x540 */
+       __le32 timestamp; /* milliseconds (increases by 16 or 17 each frame) */
+       __le32 unknown;   /* "epoch?" always 02/03 00 00 00 */
+} __packed;
 
 /* version information */
 #define DRIVER_SHORT   "sur40"
+#define DRIVER_LONG    "Samsung SUR40"
 #define DRIVER_AUTHOR  "Florian 'floe' Echtler <floe@butterbrot.org>"
 #define DRIVER_DESC    "Surface2.0/SUR40/PixelSense input driver"
 
@@ -99,6 +117,13 @@ struct sur40_data {
 /* touch data endpoint */
 #define TOUCH_ENDPOINT 0x86
 
+/* video data endpoint */
+#define VIDEO_ENDPOINT 0x82
+
+/* video header fields */
+#define VIDEO_HEADER_MAGIC 0x46425553
+#define VIDEO_PACKET_SIZE  16384
+
 /* polling interval (ms) */
 #define POLL_INTERVAL 10
 
@@ -113,21 +138,23 @@ struct sur40_data {
 #define SUR40_GET_STATE   0xc5 /*  4 bytes state (?) */
 #define SUR40_GET_SENSORS 0xb1 /*  8 bytes sensors   */
 
-/*
- * Note: an earlier, non-public version of this driver used USB_RECIP_ENDPOINT
- * here by mistake which is very likely to have corrupted the firmware EEPROM
- * on two separate SUR40 devices. Thanks to Alan Stern who spotted this bug.
- * Should you ever run into a similar problem, the background story to this
- * incident and instructions on how to fix the corrupted EEPROM are available
- * at https://floe.butterbrot.org/matrix/hacking/surface/brick.html
-*/
-
+/* master device state */
 struct sur40_state {
 
        struct usb_device *usbdev;
        struct device *dev;
        struct input_polled_dev *input;
 
+       struct v4l2_device v4l2;
+       struct video_device vdev;
+       struct mutex lock;
+
+       struct vb2_queue queue;
+       struct vb2_alloc_ctx *alloc_ctx;
+       struct list_head buf_list;
+       spinlock_t qlock;
+       int sequence;
+
        struct sur40_data *bulk_in_buffer;
        size_t bulk_in_size;
        u8 bulk_in_epaddr;
@@ -135,6 +162,27 @@ struct sur40_state {
        char phys[64];
 };
 
+struct sur40_buffer {
+       struct vb2_buffer vb;
+       struct list_head list;
+};
+
+/* forward declarations */
+static const struct video_device sur40_video_device;
+static const struct v4l2_pix_format sur40_video_format;
+static const struct vb2_queue sur40_queue;
+static void sur40_process_video(struct sur40_state *sur40);
+
+/*
+ * Note: an earlier, non-public version of this driver used USB_RECIP_ENDPOINT
+ * here by mistake which is very likely to have corrupted the firmware EEPROM
+ * on two separate SUR40 devices. Thanks to Alan Stern who spotted this bug.
+ * Should you ever run into a similar problem, the background story to this
+ * incident and instructions on how to fix the corrupted EEPROM are available
+ * at https://floe.butterbrot.org/matrix/hacking/surface/brick.html
+*/
+
+/* command wrapper */
 static int sur40_command(struct sur40_state *dev,
                         u8 command, u16 index, void *buffer, u16 size)
 {
@@ -247,7 +295,6 @@ static void sur40_report_blob(struct sur40_blob *blob, struct input_dev *input)
 /* core function: poll for new input data */
 static void sur40_poll(struct input_polled_dev *polldev)
 {
-
        struct sur40_state *sur40 = polldev->private;
        struct input_dev *input = polldev->input;
        int result, bulk_read, need_blobs, packet_blobs, i;
@@ -314,6 +361,86 @@ static void sur40_poll(struct input_polled_dev *polldev)
 
        input_mt_sync_frame(input);
        input_sync(input);
+
+       sur40_process_video(sur40);
+}
+
+/* deal with video data */
+static void sur40_process_video(struct sur40_state *sur40)
+{
+
+       struct sur40_image_header *img = (void *)(sur40->bulk_in_buffer);
+       struct sur40_buffer *new_buf;
+       struct usb_sg_request sgr;
+       struct sg_table *sgt;
+       int result, bulk_read;
+
+       if (!vb2_start_streaming_called(&sur40->queue))
+               return;
+
+       /* get a new buffer from the list */
+       spin_lock(&sur40->qlock);
+       if (list_empty(&sur40->buf_list)) {
+               dev_dbg(sur40->dev, "buffer queue empty\n");
+               spin_unlock(&sur40->qlock);
+               return;
+       }
+       new_buf = list_entry(sur40->buf_list.next, struct sur40_buffer, list);
+       list_del(&new_buf->list);
+       spin_unlock(&sur40->qlock);
+
+       /* retrieve data via bulk read */
+       result = usb_bulk_msg(sur40->usbdev,
+                       usb_rcvbulkpipe(sur40->usbdev, VIDEO_ENDPOINT),
+                       sur40->bulk_in_buffer, sur40->bulk_in_size,
+                       &bulk_read, 1000);
+
+       if (result < 0) {
+               dev_err(sur40->dev, "error in usb_bulk_read\n");
+               goto err_poll;
+       }
+
+       if (bulk_read != sizeof(struct sur40_image_header)) {
+               dev_err(sur40->dev, "received %d bytes (%zd expected)\n",
+                       bulk_read, sizeof(struct sur40_image_header));
+               goto err_poll;
+       }
+
+       if (le32_to_cpu(img->magic) != VIDEO_HEADER_MAGIC) {
+               dev_err(sur40->dev, "image magic mismatch\n");
+               goto err_poll;
+       }
+
+       if (le32_to_cpu(img->size) != sur40_video_format.sizeimage) {
+               dev_err(sur40->dev, "image size mismatch\n");
+               goto err_poll;
+       }
+
+       sgt = vb2_dma_sg_plane_desc(&new_buf->vb, 0);
+
+       result = usb_sg_init(&sgr, sur40->usbdev,
+               usb_rcvbulkpipe(sur40->usbdev, VIDEO_ENDPOINT), 0,
+               sgt->sgl, sgt->nents, sur40_video_format.sizeimage, 0);
+       if (result < 0) {
+               dev_err(sur40->dev, "error %d in usb_sg_init\n", result);
+               goto err_poll;
+       }
+
+       usb_sg_wait(&sgr);
+       if (sgr.status < 0) {
+               dev_err(sur40->dev, "error %d in usb_sg_wait\n", sgr.status);
+               goto err_poll;
+       }
+
+       /* mark as finished */
+       v4l2_get_timestamp(&new_buf->vb.v4l2_buf.timestamp);
+       new_buf->vb.v4l2_buf.sequence = sur40->sequence++;
+       new_buf->vb.v4l2_buf.field = V4L2_FIELD_NONE;
+       vb2_buffer_done(&new_buf->vb, VB2_BUF_STATE_DONE);
+       return;
+
+err_poll:
+       vb2_buffer_done(&new_buf->vb, VB2_BUF_STATE_ERROR);
 }
 
 /* Initialize input device parameters. */
@@ -377,6 +504,11 @@ static int sur40_probe(struct usb_interface *interface,
                goto err_free_dev;
        }
 
+       /* initialize locks/lists */
+       INIT_LIST_HEAD(&sur40->buf_list);
+       spin_lock_init(&sur40->qlock);
+       mutex_init(&sur40->lock);
+
        /* Set up polled input device control structure */
        poll_dev->private = sur40;
        poll_dev->poll_interval = POLL_INTERVAL;
@@ -387,7 +519,7 @@ static int sur40_probe(struct usb_interface *interface,
        /* Set up regular input device structure */
        sur40_input_setup(poll_dev->input);
 
-       poll_dev->input->name = "Samsung SUR40";
+       poll_dev->input->name = DRIVER_LONG;
        usb_to_input_id(usbdev, &poll_dev->input->id);
        usb_make_path(usbdev, sur40->phys, sizeof(sur40->phys));
        strlcat(sur40->phys, "/input0", sizeof(sur40->phys));
@@ -408,6 +540,7 @@ static int sur40_probe(struct usb_interface *interface,
                goto err_free_polldev;
        }
 
+       /* register the polled input device */
        error = input_register_polled_device(poll_dev);
        if (error) {
                dev_err(&interface->dev,
@@ -415,12 +548,54 @@ static int sur40_probe(struct usb_interface *interface,
                goto err_free_buffer;
        }
 
+       /* register the video master device */
+       snprintf(sur40->v4l2.name, sizeof(sur40->v4l2.name), "%s", DRIVER_LONG);
+       error = v4l2_device_register(sur40->dev, &sur40->v4l2);
+       if (error) {
+               dev_err(&interface->dev,
+                       "Unable to register video master device.");
+               goto err_unreg_v4l2;
+       }
+
+       /* initialize the lock and subdevice */
+       sur40->queue = sur40_queue;
+       sur40->queue.drv_priv = sur40;
+       sur40->queue.lock = &sur40->lock;
+
+       /* initialize the queue */
+       error = vb2_queue_init(&sur40->queue);
+       if (error)
+               goto err_unreg_v4l2;
+
+       sur40->alloc_ctx = vb2_dma_sg_init_ctx(sur40->dev);
+       if (IS_ERR(sur40->alloc_ctx)) {
+               dev_err(sur40->dev, "Can't allocate buffer context");
+               goto err_unreg_v4l2;
+       }
+
+       sur40->vdev = sur40_video_device;
+       sur40->vdev.v4l2_dev = &sur40->v4l2;
+       sur40->vdev.lock = &sur40->lock;
+       sur40->vdev.queue = &sur40->queue;
+       video_set_drvdata(&sur40->vdev, sur40);
+
+       error = video_register_device(&sur40->vdev, VFL_TYPE_GRABBER, -1);
+       if (error) {
+               dev_err(&interface->dev,
+                       "Unable to register video subdevice.");
+               goto err_unreg_video;
+       }
+
        /* we can register the device now, as it is ready */
        usb_set_intfdata(interface, sur40);
        dev_dbg(&interface->dev, "%s is now attached\n", DRIVER_DESC);
 
        return 0;
 
+err_unreg_video:
+       video_unregister_device(&sur40->vdev);
+err_unreg_v4l2:
+       v4l2_device_unregister(&sur40->v4l2);
 err_free_buffer:
        kfree(sur40->bulk_in_buffer);
 err_free_polldev:
@@ -436,6 +611,10 @@ static void sur40_disconnect(struct usb_interface *interface)
 {
        struct sur40_state *sur40 = usb_get_intfdata(interface);
 
+       video_unregister_device(&sur40->vdev);
+       v4l2_device_unregister(&sur40->v4l2);
+       vb2_dma_sg_cleanup_ctx(sur40->alloc_ctx);
+
        input_unregister_polled_device(sur40->input);
        input_free_polled_device(sur40->input);
        kfree(sur40->bulk_in_buffer);
@@ -445,12 +624,243 @@ static void sur40_disconnect(struct usb_interface *interface)
        dev_dbg(&interface->dev, "%s is now disconnected\n", DRIVER_DESC);
 }
 
+/*
+ * Setup the constraints of the queue: besides setting the number of planes
+ * per buffer and the size and allocation context of each plane, it also
+ * checks if sufficient buffers have been allocated. Usually 3 is a good
+ * minimum number: many DMA engines need a minimum of 2 buffers in the
+ * queue and you need to have another available for userspace processing.
+ */
+static int sur40_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+                      unsigned int *nbuffers, unsigned int *nplanes,
+                      unsigned int sizes[], void *alloc_ctxs[])
+{
+       struct sur40_state *sur40 = vb2_get_drv_priv(q);
+
+       if (q->num_buffers + *nbuffers < 3)
+               *nbuffers = 3 - q->num_buffers;
+
+       if (fmt && fmt->fmt.pix.sizeimage < sur40_video_format.sizeimage)
+               return -EINVAL;
+
+       *nplanes = 1;
+       sizes[0] = fmt ? fmt->fmt.pix.sizeimage : sur40_video_format.sizeimage;
+       alloc_ctxs[0] = sur40->alloc_ctx;
+
+       return 0;
+}
+
+/*
+ * Prepare the buffer for queueing to the DMA engine: check and set the
+ * payload size.
+ */
+static int sur40_buffer_prepare(struct vb2_buffer *vb)
+{
+       struct sur40_state *sur40 = vb2_get_drv_priv(vb->vb2_queue);
+       unsigned long size = sur40_video_format.sizeimage;
+
+       if (vb2_plane_size(vb, 0) < size) {
+               dev_err(&sur40->usbdev->dev, "buffer too small (%lu < %lu)\n",
+                        vb2_plane_size(vb, 0), size);
+               return -EINVAL;
+       }
+
+       vb2_set_plane_payload(vb, 0, size);
+       return 0;
+}
+
+/*
+ * Queue this buffer to the DMA engine.
+ */
+static void sur40_buffer_queue(struct vb2_buffer *vb)
+{
+       struct sur40_state *sur40 = vb2_get_drv_priv(vb->vb2_queue);
+       struct sur40_buffer *buf = (struct sur40_buffer *)vb;
+
+       spin_lock(&sur40->qlock);
+       list_add_tail(&buf->list, &sur40->buf_list);
+       spin_unlock(&sur40->qlock);
+}
+
+static void return_all_buffers(struct sur40_state *sur40,
+                              enum vb2_buffer_state state)
+{
+       struct sur40_buffer *buf, *node;
+
+       spin_lock(&sur40->qlock);
+       list_for_each_entry_safe(buf, node, &sur40->buf_list, list) {
+               vb2_buffer_done(&buf->vb, state);
+               list_del(&buf->list);
+       }
+       spin_unlock(&sur40->qlock);
+}
+
+/*
+ * Start streaming. First check if the minimum number of buffers have been
+ * queued. If not, then return -ENOBUFS and the vb2 framework will call
+ * this function again the next time a buffer has been queued until enough
+ * buffers are available to actually start the DMA engine.
+ */
+static int sur40_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+       struct sur40_state *sur40 = vb2_get_drv_priv(vq);
+
+       sur40->sequence = 0;
+       return 0;
+}
+
+/*
+ * Stop the DMA engine. Any remaining buffers in the DMA queue are dequeued
+ * and passed on to the vb2 framework marked as STATE_ERROR.
+ */
+static void sur40_stop_streaming(struct vb2_queue *vq)
+{
+       struct sur40_state *sur40 = vb2_get_drv_priv(vq);
+
+       /* Release all active buffers */
+       return_all_buffers(sur40, VB2_BUF_STATE_ERROR);
+}
+
+/* V4L ioctl */
+static int sur40_vidioc_querycap(struct file *file, void *priv,
+                                struct v4l2_capability *cap)
+{
+       struct sur40_state *sur40 = video_drvdata(file);
+
+       strlcpy(cap->driver, DRIVER_SHORT, sizeof(cap->driver));
+       strlcpy(cap->card, DRIVER_LONG, sizeof(cap->card));
+       usb_make_path(sur40->usbdev, cap->bus_info, sizeof(cap->bus_info));
+       cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
+               V4L2_CAP_READWRITE |
+               V4L2_CAP_STREAMING;
+       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+       return 0;
+}
+
+static int sur40_vidioc_enum_input(struct file *file, void *priv,
+                                  struct v4l2_input *i)
+{
+       if (i->index != 0)
+               return -EINVAL;
+       i->type = V4L2_INPUT_TYPE_CAMERA;
+       i->std = V4L2_STD_UNKNOWN;
+       strlcpy(i->name, "In-Cell Sensor", sizeof(i->name));
+       i->capabilities = 0;
+       return 0;
+}
+
+static int sur40_vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+       return (i == 0) ? 0 : -EINVAL;
+}
+
+static int sur40_vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+       *i = 0;
+       return 0;
+}
+
+static int sur40_vidioc_fmt(struct file *file, void *priv,
+                           struct v4l2_format *f)
+{
+       f->fmt.pix = sur40_video_format;
+       return 0;
+}
+
+static int sur40_vidioc_enum_fmt(struct file *file, void *priv,
+                                struct v4l2_fmtdesc *f)
+{
+       if (f->index != 0)
+               return -EINVAL;
+       strlcpy(f->description, "8-bit greyscale", sizeof(f->description));
+       f->pixelformat = V4L2_PIX_FMT_GREY;
+       f->flags = 0;
+       return 0;
+}
+
 static const struct usb_device_id sur40_table[] = {
        { USB_DEVICE(ID_MICROSOFT, ID_SUR40) },  /* Samsung SUR40 */
        { }                                      /* terminating null entry */
 };
 MODULE_DEVICE_TABLE(usb, sur40_table);
 
+/* V4L2 structures */
+static const struct vb2_ops sur40_queue_ops = {
+       .queue_setup            = sur40_queue_setup,
+       .buf_prepare            = sur40_buffer_prepare,
+       .buf_queue              = sur40_buffer_queue,
+       .start_streaming        = sur40_start_streaming,
+       .stop_streaming         = sur40_stop_streaming,
+       .wait_prepare           = vb2_ops_wait_prepare,
+       .wait_finish            = vb2_ops_wait_finish,
+};
+
+static const struct vb2_queue sur40_queue = {
+       .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+       /*
+        * VB2_USERPTR in currently not enabled: passing a user pointer to
+        * dma-sg will result in segment sizes that are not a multiple of
+        * 512 bytes, which is required by the host controller.
+       */
+       .io_modes = VB2_MMAP | VB2_READ | VB2_DMABUF,
+       .buf_struct_size = sizeof(struct sur40_buffer),
+       .ops = &sur40_queue_ops,
+       .mem_ops = &vb2_dma_sg_memops,
+       .timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC,
+       .min_buffers_needed = 3,
+};
+
+static const struct v4l2_file_operations sur40_video_fops = {
+       .owner = THIS_MODULE,
+       .open = v4l2_fh_open,
+       .release = vb2_fop_release,
+       .unlocked_ioctl = video_ioctl2,
+       .read = vb2_fop_read,
+       .mmap = vb2_fop_mmap,
+       .poll = vb2_fop_poll,
+};
+
+static const struct v4l2_ioctl_ops sur40_video_ioctl_ops = {
+
+       .vidioc_querycap        = sur40_vidioc_querycap,
+
+       .vidioc_enum_fmt_vid_cap = sur40_vidioc_enum_fmt,
+       .vidioc_try_fmt_vid_cap = sur40_vidioc_fmt,
+       .vidioc_s_fmt_vid_cap   = sur40_vidioc_fmt,
+       .vidioc_g_fmt_vid_cap   = sur40_vidioc_fmt,
+
+       .vidioc_enum_input      = sur40_vidioc_enum_input,
+       .vidioc_g_input         = sur40_vidioc_g_input,
+       .vidioc_s_input         = sur40_vidioc_s_input,
+
+       .vidioc_reqbufs         = vb2_ioctl_reqbufs,
+       .vidioc_create_bufs     = vb2_ioctl_create_bufs,
+       .vidioc_querybuf        = vb2_ioctl_querybuf,
+       .vidioc_qbuf            = vb2_ioctl_qbuf,
+       .vidioc_dqbuf           = vb2_ioctl_dqbuf,
+       .vidioc_expbuf          = vb2_ioctl_expbuf,
+
+       .vidioc_streamon        = vb2_ioctl_streamon,
+       .vidioc_streamoff       = vb2_ioctl_streamoff,
+};
+
+static const struct video_device sur40_video_device = {
+       .name = DRIVER_LONG,
+       .fops = &sur40_video_fops,
+       .ioctl_ops = &sur40_video_ioctl_ops,
+       .release = video_device_release_empty,
+};
+
+static const struct v4l2_pix_format sur40_video_format = {
+       .pixelformat = V4L2_PIX_FMT_GREY,
+       .width  = SENSOR_RES_X / 2,
+       .height = SENSOR_RES_Y / 2,
+       .field = V4L2_FIELD_NONE,
+       .colorspace = V4L2_COLORSPACE_SRGB,
+       .bytesperline = SENSOR_RES_X / 2,
+       .sizeimage = (SENSOR_RES_X/2) * (SENSOR_RES_Y/2),
+};
+
 /* USB-specific object needed to register this driver with the USB subsystem. */
 static struct usb_driver sur40_driver = {
        .name = DRIVER_SHORT,
index a35927cd42e515cc81294a94e3c1c3500d51d293..68d43beccb7e560f845ad49b8ae7d9e38872fcf7 100644 (file)
@@ -50,6 +50,7 @@
 #define CONTEXT_SIZE           VTD_PAGE_SIZE
 
 #define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
+#define IS_USB_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_SERIAL_USB)
 #define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA)
 #define IS_AZALIA(pdev) ((pdev)->vendor == 0x8086 && (pdev)->device == 0x3a3e)
 
@@ -184,32 +185,11 @@ static int force_on = 0;
  * 64-127: Reserved
  */
 struct root_entry {
-       u64     val;
-       u64     rsvd1;
+       u64     lo;
+       u64     hi;
 };
 #define ROOT_ENTRY_NR (VTD_PAGE_SIZE/sizeof(struct root_entry))
-static inline bool root_present(struct root_entry *root)
-{
-       return (root->val & 1);
-}
-static inline void set_root_present(struct root_entry *root)
-{
-       root->val |= 1;
-}
-static inline void set_root_value(struct root_entry *root, unsigned long value)
-{
-       root->val &= ~VTD_PAGE_MASK;
-       root->val |= value & VTD_PAGE_MASK;
-}
 
-static inline struct context_entry *
-get_context_addr_from_root(struct root_entry *root)
-{
-       return (struct context_entry *)
-               (root_present(root)?phys_to_virt(
-               root->val & VTD_PAGE_MASK) :
-               NULL);
-}
 
 /*
  * low 64 bits:
@@ -682,6 +662,40 @@ static void domain_update_iommu_cap(struct dmar_domain *domain)
        domain->iommu_superpage = domain_update_iommu_superpage(NULL);
 }
 
+static inline struct context_entry *iommu_context_addr(struct intel_iommu *iommu,
+                                                      u8 bus, u8 devfn, int alloc)
+{
+       struct root_entry *root = &iommu->root_entry[bus];
+       struct context_entry *context;
+       u64 *entry;
+
+       if (ecap_ecs(iommu->ecap)) {
+               if (devfn >= 0x80) {
+                       devfn -= 0x80;
+                       entry = &root->hi;
+               }
+               devfn *= 2;
+       }
+       entry = &root->lo;
+       if (*entry & 1)
+               context = phys_to_virt(*entry & VTD_PAGE_MASK);
+       else {
+               unsigned long phy_addr;
+               if (!alloc)
+                       return NULL;
+
+               context = alloc_pgtable_page(iommu->node);
+               if (!context)
+                       return NULL;
+
+               __iommu_flush_cache(iommu, (void *)context, CONTEXT_SIZE);
+               phy_addr = virt_to_phys((void *)context);
+               *entry = phy_addr | 1;
+               __iommu_flush_cache(iommu, entry, sizeof(*entry));
+       }
+       return &context[devfn];
+}
+
 static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devfn)
 {
        struct dmar_drhd_unit *drhd = NULL;
@@ -741,75 +755,36 @@ static void domain_flush_cache(struct dmar_domain *domain,
                clflush_cache_range(addr, size);
 }
 
-/* Gets context entry for a given bus and devfn */
-static struct context_entry * device_to_context_entry(struct intel_iommu *iommu,
-               u8 bus, u8 devfn)
-{
-       struct root_entry *root;
-       struct context_entry *context;
-       unsigned long phy_addr;
-       unsigned long flags;
-
-       spin_lock_irqsave(&iommu->lock, flags);
-       root = &iommu->root_entry[bus];
-       context = get_context_addr_from_root(root);
-       if (!context) {
-               context = (struct context_entry *)
-                               alloc_pgtable_page(iommu->node);
-               if (!context) {
-                       spin_unlock_irqrestore(&iommu->lock, flags);
-                       return NULL;
-               }
-               __iommu_flush_cache(iommu, (void *)context, CONTEXT_SIZE);
-               phy_addr = virt_to_phys((void *)context);
-               set_root_value(root, phy_addr);
-               set_root_present(root);
-               __iommu_flush_cache(iommu, root, sizeof(*root));
-       }
-       spin_unlock_irqrestore(&iommu->lock, flags);
-       return &context[devfn];
-}
-
 static int device_context_mapped(struct intel_iommu *iommu, u8 bus, u8 devfn)
 {
-       struct root_entry *root;
        struct context_entry *context;
-       int ret;
+       int ret = 0;
        unsigned long flags;
 
        spin_lock_irqsave(&iommu->lock, flags);
-       root = &iommu->root_entry[bus];
-       context = get_context_addr_from_root(root);
-       if (!context) {
-               ret = 0;
-               goto out;
-       }
-       ret = context_present(&context[devfn]);
-out:
+       context = iommu_context_addr(iommu, bus, devfn, 0);
+       if (context)
+               ret = context_present(context);
        spin_unlock_irqrestore(&iommu->lock, flags);
        return ret;
 }
 
 static void clear_context_table(struct intel_iommu *iommu, u8 bus, u8 devfn)
 {
-       struct root_entry *root;
        struct context_entry *context;
        unsigned long flags;
 
        spin_lock_irqsave(&iommu->lock, flags);
-       root = &iommu->root_entry[bus];
-       context = get_context_addr_from_root(root);
+       context = iommu_context_addr(iommu, bus, devfn, 0);
        if (context) {
-               context_clear_entry(&context[devfn]);
-               __iommu_flush_cache(iommu, &context[devfn], \
-                       sizeof(*context));
+               context_clear_entry(context);
+               __iommu_flush_cache(iommu, context, sizeof(*context));
        }
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
 static void free_context_table(struct intel_iommu *iommu)
 {
-       struct root_entry *root;
        int i;
        unsigned long flags;
        struct context_entry *context;
@@ -819,10 +794,17 @@ static void free_context_table(struct intel_iommu *iommu)
                goto out;
        }
        for (i = 0; i < ROOT_ENTRY_NR; i++) {
-               root = &iommu->root_entry[i];
-               context = get_context_addr_from_root(root);
+               context = iommu_context_addr(iommu, i, 0, 0);
+               if (context)
+                       free_pgtable_page(context);
+
+               if (!ecap_ecs(iommu->ecap))
+                       continue;
+
+               context = iommu_context_addr(iommu, i, 0x80, 0);
                if (context)
                        free_pgtable_page(context);
+
        }
        free_pgtable_page(iommu->root_entry);
        iommu->root_entry = NULL;
@@ -1146,14 +1128,16 @@ static int iommu_alloc_root_entry(struct intel_iommu *iommu)
 
 static void iommu_set_root_entry(struct intel_iommu *iommu)
 {
-       void *addr;
+       u64 addr;
        u32 sts;
        unsigned long flag;
 
-       addr = iommu->root_entry;
+       addr = virt_to_phys(iommu->root_entry);
+       if (ecap_ecs(iommu->ecap))
+               addr |= DMA_RTADDR_RTT;
 
        raw_spin_lock_irqsave(&iommu->register_lock, flag);
-       dmar_writeq(iommu->reg + DMAR_RTADDR_REG, virt_to_phys(addr));
+       dmar_writeq(iommu->reg + DMAR_RTADDR_REG, addr);
 
        writel(iommu->gcmd | DMA_GCMD_SRTP, iommu->reg + DMAR_GCMD_REG);
 
@@ -1800,7 +1784,9 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
        BUG_ON(translation != CONTEXT_TT_PASS_THROUGH &&
               translation != CONTEXT_TT_MULTI_LEVEL);
 
-       context = device_to_context_entry(iommu, bus, devfn);
+       spin_lock_irqsave(&iommu->lock, flags);
+       context = iommu_context_addr(iommu, bus, devfn, 1);
+       spin_unlock_irqrestore(&iommu->lock, flags);
        if (!context)
                return -ENOMEM;
        spin_lock_irqsave(&iommu->lock, flags);
@@ -2564,6 +2550,10 @@ static bool device_has_rmrr(struct device *dev)
  * In both cases we assume that PCI USB devices with RMRRs have them largely
  * for historical reasons and that the RMRR space is not actively used post
  * boot.  This exclusion may change if vendors begin to abuse it.
+ *
+ * The same exception is made for graphics devices, with the requirement that
+ * any use of the RMRR regions will be torn down before assigning the device
+ * to a guest.
  */
 static bool device_is_rmrr_locked(struct device *dev)
 {
@@ -2573,7 +2563,7 @@ static bool device_is_rmrr_locked(struct device *dev)
        if (dev_is_pci(dev)) {
                struct pci_dev *pdev = to_pci_dev(dev);
 
-               if ((pdev->class >> 8) == PCI_CLASS_SERIAL_USB)
+               if (IS_USB_DEVICE(pdev) || IS_GFX_DEVICE(pdev))
                        return false;
        }
 
index 7ecc6b3180ba8b1b9aa5e065ddc42851a5cc5dbd..8fad71cc27e79ca2d29ac6e80698294a2d4c3d52 100644 (file)
@@ -581,10 +581,7 @@ static int __init intel_enable_irq_remapping(void)
        if (x2apic_supported()) {
                eim = !dmar_x2apic_optout();
                if (!eim)
-                       printk(KERN_WARNING
-                               "Your BIOS is broken and requested that x2apic be disabled.\n"
-                               "This will slightly decrease performance.\n"
-                               "Use 'intremap=no_x2apic_optout' to override BIOS request.\n");
+                       pr_info("x2apic is disabled because BIOS sets x2apic opt out bit. You can use 'intremap=no_x2apic_optout' to override the BIOS setting.\n");
        }
 
        for_each_iommu(iommu, drhd) {
index a6ce3476834e4e218db5de2ec03d0a25df7e54da..7b315e385ba3a0bba8de91fa851ab03c3ef653e8 100644 (file)
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
+#include <linux/acpi.h>
 #include <linux/irqdomain.h>
 #include <linux/interrupt.h>
 #include <linux/percpu.h>
 #include <linux/slab.h>
 #include <linux/irqchip/chained_irq.h>
 #include <linux/irqchip/arm-gic.h>
+#include <linux/irqchip/arm-gic-acpi.h>
 
 #include <asm/cputype.h>
 #include <asm/irq.h>
@@ -1107,3 +1109,105 @@ IRQCHIP_DECLARE(msm_8660_qgic, "qcom,msm-8660-qgic", gic_of_init);
 IRQCHIP_DECLARE(msm_qgic2, "qcom,msm-qgic2", gic_of_init);
 
 #endif
+
+#ifdef CONFIG_ACPI
+static phys_addr_t dist_phy_base, cpu_phy_base __initdata;
+
+static int __init
+gic_acpi_parse_madt_cpu(struct acpi_subtable_header *header,
+                       const unsigned long end)
+{
+       struct acpi_madt_generic_interrupt *processor;
+       phys_addr_t gic_cpu_base;
+       static int cpu_base_assigned;
+
+       processor = (struct acpi_madt_generic_interrupt *)header;
+
+       if (BAD_MADT_ENTRY(processor, end))
+               return -EINVAL;
+
+       /*
+        * There is no support for non-banked GICv1/2 register in ACPI spec.
+        * All CPU interface addresses have to be the same.
+        */
+       gic_cpu_base = processor->base_address;
+       if (cpu_base_assigned && gic_cpu_base != cpu_phy_base)
+               return -EINVAL;
+
+       cpu_phy_base = gic_cpu_base;
+       cpu_base_assigned = 1;
+       return 0;
+}
+
+static int __init
+gic_acpi_parse_madt_distributor(struct acpi_subtable_header *header,
+                               const unsigned long end)
+{
+       struct acpi_madt_generic_distributor *dist;
+
+       dist = (struct acpi_madt_generic_distributor *)header;
+
+       if (BAD_MADT_ENTRY(dist, end))
+               return -EINVAL;
+
+       dist_phy_base = dist->base_address;
+       return 0;
+}
+
+int __init
+gic_v2_acpi_init(struct acpi_table_header *table)
+{
+       void __iomem *cpu_base, *dist_base;
+       int count;
+
+       /* Collect CPU base addresses */
+       count = acpi_parse_entries(ACPI_SIG_MADT,
+                                  sizeof(struct acpi_table_madt),
+                                  gic_acpi_parse_madt_cpu, table,
+                                  ACPI_MADT_TYPE_GENERIC_INTERRUPT, 0);
+       if (count <= 0) {
+               pr_err("No valid GICC entries exist\n");
+               return -EINVAL;
+       }
+
+       /*
+        * Find distributor base address. We expect one distributor entry since
+        * ACPI 5.1 spec neither support multi-GIC instances nor GIC cascade.
+        */
+       count = acpi_parse_entries(ACPI_SIG_MADT,
+                                  sizeof(struct acpi_table_madt),
+                                  gic_acpi_parse_madt_distributor, table,
+                                  ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR, 0);
+       if (count <= 0) {
+               pr_err("No valid GICD entries exist\n");
+               return -EINVAL;
+       } else if (count > 1) {
+               pr_err("More than one GICD entry detected\n");
+               return -EINVAL;
+       }
+
+       cpu_base = ioremap(cpu_phy_base, ACPI_GIC_CPU_IF_MEM_SIZE);
+       if (!cpu_base) {
+               pr_err("Unable to map GICC registers\n");
+               return -ENOMEM;
+       }
+
+       dist_base = ioremap(dist_phy_base, ACPI_GICV2_DIST_MEM_SIZE);
+       if (!dist_base) {
+               pr_err("Unable to map GICD registers\n");
+               iounmap(cpu_base);
+               return -ENOMEM;
+       }
+
+       /*
+        * Initialize zero GIC instance (no multi-GIC support). Also, set GIC
+        * as default IRQ domain to allow for GSI registration and GSI to IRQ
+        * number translation (see acpi_register_gsi() and acpi_gsi_to_irq()).
+        */
+       gic_init_bases(0, -1, dist_base, cpu_base, 0, NULL);
+       irq_set_default_host(gic_data[0].domain);
+
+       acpi_irq_model = ACPI_IRQ_MODEL_GIC;
+       return 0;
+}
+#endif
index 0fe2f718d81c1ddca935c4b29d2fec25ccdb8fe7..afd1af3dfe5a231692cd0904c5b5a18e5c3f8245 100644 (file)
@@ -8,6 +8,7 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/acpi_irq.h>
 #include <linux/init.h>
 #include <linux/of_irq.h>
 #include <linux/irqchip.h>
@@ -26,4 +27,6 @@ extern struct of_device_id __irqchip_of_table[];
 void __init irqchip_init(void)
 {
        of_irq_init(__irqchip_of_table);
+
+       acpi_irq_init();
 }
index 1219af493c0f186bf0ccc71c5bac6b8c88564dbb..19a32280731db99e05661d3ae5c46b6a8f168dd2 100644 (file)
@@ -211,10 +211,9 @@ static void initialize(struct lg_cpu *cpu)
 
        /*
         * The Guest tells us where we're not to deliver interrupts by putting
-        * the range of addresses into "struct lguest_data".
+        * the instruction address into "struct lguest_data".
         */
-       if (get_user(cpu->lg->noirq_start, &cpu->lg->lguest_data->noirq_start)
-           || get_user(cpu->lg->noirq_end, &cpu->lg->lguest_data->noirq_end))
+       if (get_user(cpu->lg->noirq_iret, &cpu->lg->lguest_data->noirq_iret))
                kill_guest(cpu, "bad guest page %p", cpu->lg->lguest_data);
 
        /*
index 70dfcdc29f1f9e9d8cfc764d69ab7a965daf5c25..eb934b0242e0e17652b7fc17c3255b5e70e40d15 100644 (file)
@@ -20,7 +20,7 @@
 #include "lg.h"
 
 /* Allow Guests to use a non-128 (ie. non-Linux) syscall trap. */
-static unsigned int syscall_vector = SYSCALL_VECTOR;
+static unsigned int syscall_vector = IA32_SYSCALL_VECTOR;
 module_param(syscall_vector, uint, 0444);
 
 /* The address of the interrupt handler is split into two bits: */
@@ -56,21 +56,16 @@ static void push_guest_stack(struct lg_cpu *cpu, unsigned long *gstack, u32 val)
 }
 
 /*H:210
- * The set_guest_interrupt() routine actually delivers the interrupt or
- * trap.  The mechanics of delivering traps and interrupts to the Guest are the
- * same, except some traps have an "error code" which gets pushed onto the
- * stack as well: the caller tells us if this is one.
- *
- * "lo" and "hi" are the two parts of the Interrupt Descriptor Table for this
- * interrupt or trap.  It's split into two parts for traditional reasons: gcc
- * on i386 used to be frightened by 64 bit numbers.
+ * The push_guest_interrupt_stack() routine saves Guest state on the stack for
+ * an interrupt or trap.  The mechanics of delivering traps and interrupts to
+ * the Guest are the same, except some traps have an "error code" which gets
+ * pushed onto the stack as well: the caller tells us if this is one.
  *
  * We set up the stack just like the CPU does for a real interrupt, so it's
  * identical for the Guest (and the standard "iret" instruction will undo
  * it).
  */
-static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi,
-                               bool has_err)
+static void push_guest_interrupt_stack(struct lg_cpu *cpu, bool has_err)
 {
        unsigned long gstack, origstack;
        u32 eflags, ss, irq_enable;
@@ -130,12 +125,28 @@ static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi,
        if (has_err)
                push_guest_stack(cpu, &gstack, cpu->regs->errcode);
 
-       /*
-        * Now we've pushed all the old state, we change the stack, the code
-        * segment and the address to execute.
-        */
+       /* Adjust the stack pointer and stack segment. */
        cpu->regs->ss = ss;
        cpu->regs->esp = virtstack + (gstack - origstack);
+}
+
+/*
+ * This actually makes the Guest start executing the given interrupt/trap
+ * handler.
+ *
+ * "lo" and "hi" are the two parts of the Interrupt Descriptor Table for this
+ * interrupt or trap.  It's split into two parts for traditional reasons: gcc
+ * on i386 used to be frightened by 64 bit numbers.
+ */
+static void guest_run_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi)
+{
+       /* If we're already in the kernel, we don't change stacks. */
+       if ((cpu->regs->ss&0x3) != GUEST_PL)
+               cpu->regs->ss = cpu->esp1;
+
+       /*
+        * Set the code segment and the address to execute.
+        */
        cpu->regs->cs = (__KERNEL_CS|GUEST_PL);
        cpu->regs->eip = idt_address(lo, hi);
 
@@ -158,6 +169,24 @@ static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi,
                        kill_guest(cpu, "Disabling interrupts");
 }
 
+/* This restores the eflags word which was pushed on the stack by a trap */
+static void restore_eflags(struct lg_cpu *cpu)
+{
+       /* This is the physical address of the stack. */
+       unsigned long stack_pa = guest_pa(cpu, cpu->regs->esp);
+
+       /*
+        * Stack looks like this:
+        * Address      Contents
+        * esp          EIP
+        * esp + 4      CS
+        * esp + 8      EFLAGS
+        */
+       cpu->regs->eflags = lgread(cpu, stack_pa + 8, u32);
+       cpu->regs->eflags &=
+               ~(X86_EFLAGS_TF|X86_EFLAGS_VM|X86_EFLAGS_RF|X86_EFLAGS_NT);
+}
+
 /*H:205
  * Virtual Interrupts.
  *
@@ -200,14 +229,6 @@ void try_deliver_interrupt(struct lg_cpu *cpu, unsigned int irq, bool more)
 
        BUG_ON(irq >= LGUEST_IRQS);
 
-       /*
-        * They may be in the middle of an iret, where they asked us never to
-        * deliver interrupts.
-        */
-       if (cpu->regs->eip >= cpu->lg->noirq_start &&
-          (cpu->regs->eip < cpu->lg->noirq_end))
-               return;
-
        /* If they're halted, interrupts restart them. */
        if (cpu->halted) {
                /* Re-enable interrupts. */
@@ -237,12 +258,34 @@ void try_deliver_interrupt(struct lg_cpu *cpu, unsigned int irq, bool more)
        if (idt_present(idt->a, idt->b)) {
                /* OK, mark it no longer pending and deliver it. */
                clear_bit(irq, cpu->irqs_pending);
+
                /*
-                * set_guest_interrupt() takes the interrupt descriptor and a
-                * flag to say whether this interrupt pushes an error code onto
-                * the stack as well: virtual interrupts never do.
+                * They may be about to iret, where they asked us never to
+                * deliver interrupts.  In this case, we can emulate that iret
+                * then immediately deliver the interrupt.  This is basically
+                * a noop: the iret would pop the interrupt frame and restore
+                * eflags, and then we'd set it up again.  So just restore the
+                * eflags word and jump straight to the handler in this case.
+                *
+                * Denys Vlasenko points out that this isn't quite right: if
+                * the iret was returning to userspace, then that interrupt
+                * would reset the stack pointer (which the Guest told us
+                * about via LHCALL_SET_STACK).  But unless the Guest is being
+                * *really* weird, that will be the same as the current stack
+                * anyway.
                 */
-               set_guest_interrupt(cpu, idt->a, idt->b, false);
+               if (cpu->regs->eip == cpu->lg->noirq_iret) {
+                       restore_eflags(cpu);
+               } else {
+                       /*
+                        * set_guest_interrupt() takes a flag to say whether
+                        * this interrupt pushes an error code onto the stack
+                        * as well: virtual interrupts never do.
+                        */
+                       push_guest_interrupt_stack(cpu, false);
+               }
+               /* Actually make Guest cpu jump to handler. */
+               guest_run_interrupt(cpu, idt->a, idt->b);
        }
 
        /*
@@ -290,8 +333,8 @@ void set_interrupt(struct lg_cpu *cpu, unsigned int irq)
  */
 static bool could_be_syscall(unsigned int num)
 {
-       /* Normal Linux SYSCALL_VECTOR or reserved vector? */
-       return num == SYSCALL_VECTOR || num == syscall_vector;
+       /* Normal Linux IA32_SYSCALL_VECTOR or reserved vector? */
+       return num == IA32_SYSCALL_VECTOR || num == syscall_vector;
 }
 
 /* The syscall vector it wants must be unused by Host. */
@@ -308,7 +351,7 @@ bool check_syscall_vector(struct lguest *lg)
 int init_interrupts(void)
 {
        /* If they want some strange system call vector, reserve it now */
-       if (syscall_vector != SYSCALL_VECTOR) {
+       if (syscall_vector != IA32_SYSCALL_VECTOR) {
                if (test_bit(syscall_vector, used_vectors) ||
                    vector_used_by_percpu_irq(syscall_vector)) {
                        printk(KERN_ERR "lg: couldn't reserve syscall %u\n",
@@ -323,7 +366,7 @@ int init_interrupts(void)
 
 void free_interrupts(void)
 {
-       if (syscall_vector != SYSCALL_VECTOR)
+       if (syscall_vector != IA32_SYSCALL_VECTOR)
                clear_bit(syscall_vector, used_vectors);
 }
 
@@ -353,8 +396,9 @@ bool deliver_trap(struct lg_cpu *cpu, unsigned int num)
         */
        if (!idt_present(cpu->arch.idt[num].a, cpu->arch.idt[num].b))
                return false;
-       set_guest_interrupt(cpu, cpu->arch.idt[num].a,
-                           cpu->arch.idt[num].b, has_err(num));
+       push_guest_interrupt_stack(cpu, has_err(num));
+       guest_run_interrupt(cpu, cpu->arch.idt[num].a,
+                           cpu->arch.idt[num].b);
        return true;
 }
 
@@ -395,8 +439,9 @@ static bool direct_trap(unsigned int num)
  * The Guest has the ability to turn its interrupt gates into trap gates,
  * if it is careful.  The Host will let trap gates can go directly to the
  * Guest, but the Guest needs the interrupts atomically disabled for an
- * interrupt gate.  It can do this by pointing the trap gate at instructions
- * within noirq_start and noirq_end, where it can safely disable interrupts.
+ * interrupt gate.  The Host could provide a mechanism to register more
+ * "no-interrupt" regions, and the Guest could point the trap gate at
+ * instructions within that region, where it can safely disable interrupts.
  */
 
 /*M:006
index 307e8b39e7d1dd2b0bdbe69bbefb6ca36b7b5567..ac8ad0461e809db526bfc1db1ca2290ac612a43d 100644 (file)
@@ -102,7 +102,7 @@ struct lguest {
 
        struct pgdir pgdirs[4];
 
-       unsigned long noirq_start, noirq_end;
+       unsigned long noirq_iret;
 
        unsigned int stack_pages;
        u32 tsc_khz;
index c4c6113eb9a617a95f684ffa45ac87386b289095..30c60687d277c47efb20ea0a1bba4826444af09d 100644 (file)
@@ -339,6 +339,13 @@ static ssize_t write(struct file *file, const char __user *in,
        }
 }
 
+static int open(struct inode *inode, struct file *file)
+{
+       file->private_data = NULL;
+
+       return 0;
+}
+
 /*L:060
  * The final piece of interface code is the close() routine.  It reverses
  * everything done in initialize().  This is usually called because the
@@ -409,6 +416,7 @@ static int close(struct inode *inode, struct file *file)
  */
 static const struct file_operations lguest_fops = {
        .owner   = THIS_MODULE,
+       .open    = open,
        .release = close,
        .write   = write,
        .read    = read,
index 0af7361e377f61565258346f3f84a3933b9f15ba..de36237d7c6b45de10fca57cc1870fde5a0620e5 100644 (file)
@@ -56,9 +56,9 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        res = request_mem_region(priv->mapbase, CHAM_HEADER_SIZE,
                                 KBUILD_MODNAME);
-       if (IS_ERR(res)) {
+       if (!res) {
                dev_err(&pdev->dev, "Failed to request PCI memory\n");
-               ret = PTR_ERR(res);
+               ret = -EBUSY;
                goto out_disable;
        }
 
index 6ddc983417d5a8120700fbfa98508d1db3e35546..edcf4ab66e0046eafc0ac05a10d32d602c4f6829 100644 (file)
@@ -175,6 +175,22 @@ config MD_FAULTY
 
          In unsure, say N.
 
+
+config MD_CLUSTER
+       tristate "Cluster Support for MD (EXPERIMENTAL)"
+       depends on BLK_DEV_MD
+       depends on DLM
+       default n
+       ---help---
+       Clustering support for MD devices. This enables locking and
+       synchronization across multiple systems on the cluster, so all
+       nodes in the cluster can access the MD devices simultaneously.
+
+       This brings the redundancy (and uptime) of RAID levels across the
+       nodes of the cluster.
+
+       If unsure, say N.
+
 source "drivers/md/bcache/Kconfig"
 
 config BLK_DEV_DM_BUILTIN
index 1863feaa584612eb862ff20d7806c8c12608b17c..dba4db5985fb9f179a19c82b95ed53e83282d7e9 100644 (file)
@@ -30,6 +30,7 @@ obj-$(CONFIG_MD_RAID10)               += raid10.o
 obj-$(CONFIG_MD_RAID456)       += raid456.o
 obj-$(CONFIG_MD_MULTIPATH)     += multipath.o
 obj-$(CONFIG_MD_FAULTY)                += faulty.o
+obj-$(CONFIG_MD_CLUSTER)       += md-cluster.o
 obj-$(CONFIG_BCACHE)           += bcache/
 obj-$(CONFIG_BLK_DEV_MD)       += md-mod.o
 obj-$(CONFIG_BLK_DEV_DM)       += dm-mod.o
index 3a5767968ba06c3083180f4299c5851f454289a8..2bc56e2a35262141859f8da21d09a54dec852e52 100644 (file)
@@ -205,6 +205,10 @@ static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait)
        struct block_device *bdev;
        struct mddev *mddev = bitmap->mddev;
        struct bitmap_storage *store = &bitmap->storage;
+       int node_offset = 0;
+
+       if (mddev_is_clustered(bitmap->mddev))
+               node_offset = bitmap->cluster_slot * store->file_pages;
 
        while ((rdev = next_active_rdev(rdev, mddev)) != NULL) {
                int size = PAGE_SIZE;
@@ -433,6 +437,7 @@ void bitmap_update_sb(struct bitmap *bitmap)
        /* This might have been changed by a reshape */
        sb->sync_size = cpu_to_le64(bitmap->mddev->resync_max_sectors);
        sb->chunksize = cpu_to_le32(bitmap->mddev->bitmap_info.chunksize);
+       sb->nodes = cpu_to_le32(bitmap->mddev->bitmap_info.nodes);
        sb->sectors_reserved = cpu_to_le32(bitmap->mddev->
                                           bitmap_info.space);
        kunmap_atomic(sb);
@@ -544,6 +549,7 @@ static int bitmap_read_sb(struct bitmap *bitmap)
        bitmap_super_t *sb;
        unsigned long chunksize, daemon_sleep, write_behind;
        unsigned long long events;
+       int nodes = 0;
        unsigned long sectors_reserved = 0;
        int err = -EINVAL;
        struct page *sb_page;
@@ -562,6 +568,22 @@ static int bitmap_read_sb(struct bitmap *bitmap)
                return -ENOMEM;
        bitmap->storage.sb_page = sb_page;
 
+re_read:
+       /* If cluster_slot is set, the cluster is setup */
+       if (bitmap->cluster_slot >= 0) {
+               sector_t bm_blocks = bitmap->mddev->resync_max_sectors;
+
+               sector_div(bm_blocks,
+                          bitmap->mddev->bitmap_info.chunksize >> 9);
+               /* bits to bytes */
+               bm_blocks = ((bm_blocks+7) >> 3) + sizeof(bitmap_super_t);
+               /* to 4k blocks */
+               bm_blocks = DIV_ROUND_UP_SECTOR_T(bm_blocks, 4096);
+               bitmap->mddev->bitmap_info.offset += bitmap->cluster_slot * (bm_blocks << 3);
+               pr_info("%s:%d bm slot: %d offset: %llu\n", __func__, __LINE__,
+                       bitmap->cluster_slot, (unsigned long long)bitmap->mddev->bitmap_info.offset);
+       }
+
        if (bitmap->storage.file) {
                loff_t isize = i_size_read(bitmap->storage.file->f_mapping->host);
                int bytes = isize > PAGE_SIZE ? PAGE_SIZE : isize;
@@ -577,12 +599,15 @@ static int bitmap_read_sb(struct bitmap *bitmap)
        if (err)
                return err;
 
+       err = -EINVAL;
        sb = kmap_atomic(sb_page);
 
        chunksize = le32_to_cpu(sb->chunksize);
        daemon_sleep = le32_to_cpu(sb->daemon_sleep) * HZ;
        write_behind = le32_to_cpu(sb->write_behind);
        sectors_reserved = le32_to_cpu(sb->sectors_reserved);
+       nodes = le32_to_cpu(sb->nodes);
+       strlcpy(bitmap->mddev->bitmap_info.cluster_name, sb->cluster_name, 64);
 
        /* verify that the bitmap-specific fields are valid */
        if (sb->magic != cpu_to_le32(BITMAP_MAGIC))
@@ -619,7 +644,7 @@ static int bitmap_read_sb(struct bitmap *bitmap)
                        goto out;
                }
                events = le64_to_cpu(sb->events);
-               if (events < bitmap->mddev->events) {
+               if (!nodes && (events < bitmap->mddev->events)) {
                        printk(KERN_INFO
                               "%s: bitmap file is out of date (%llu < %llu) "
                               "-- forcing full recovery\n",
@@ -634,20 +659,40 @@ static int bitmap_read_sb(struct bitmap *bitmap)
        if (le32_to_cpu(sb->version) == BITMAP_MAJOR_HOSTENDIAN)
                set_bit(BITMAP_HOSTENDIAN, &bitmap->flags);
        bitmap->events_cleared = le64_to_cpu(sb->events_cleared);
+       strlcpy(bitmap->mddev->bitmap_info.cluster_name, sb->cluster_name, 64);
        err = 0;
+
 out:
        kunmap_atomic(sb);
+       /* Assiging chunksize is required for "re_read" */
+       bitmap->mddev->bitmap_info.chunksize = chunksize;
+       if (nodes && (bitmap->cluster_slot < 0)) {
+               err = md_setup_cluster(bitmap->mddev, nodes);
+               if (err) {
+                       pr_err("%s: Could not setup cluster service (%d)\n",
+                                       bmname(bitmap), err);
+                       goto out_no_sb;
+               }
+               bitmap->cluster_slot = md_cluster_ops->slot_number(bitmap->mddev);
+               goto re_read;
+       }
+
+
 out_no_sb:
        if (test_bit(BITMAP_STALE, &bitmap->flags))
                bitmap->events_cleared = bitmap->mddev->events;
        bitmap->mddev->bitmap_info.chunksize = chunksize;
        bitmap->mddev->bitmap_info.daemon_sleep = daemon_sleep;
        bitmap->mddev->bitmap_info.max_write_behind = write_behind;
+       bitmap->mddev->bitmap_info.nodes = nodes;
        if (bitmap->mddev->bitmap_info.space == 0 ||
            bitmap->mddev->bitmap_info.space > sectors_reserved)
                bitmap->mddev->bitmap_info.space = sectors_reserved;
-       if (err)
+       if (err) {
                bitmap_print_sb(bitmap);
+               if (bitmap->cluster_slot < 0)
+                       md_cluster_stop(bitmap->mddev);
+       }
        return err;
 }
 
@@ -692,9 +737,10 @@ static inline struct page *filemap_get_page(struct bitmap_storage *store,
 }
 
 static int bitmap_storage_alloc(struct bitmap_storage *store,
-                               unsigned long chunks, int with_super)
+                               unsigned long chunks, int with_super,
+                               int slot_number)
 {
-       int pnum;
+       int pnum, offset = 0;
        unsigned long num_pages;
        unsigned long bytes;
 
@@ -703,6 +749,7 @@ static int bitmap_storage_alloc(struct bitmap_storage *store,
                bytes += sizeof(bitmap_super_t);
 
        num_pages = DIV_ROUND_UP(bytes, PAGE_SIZE);
+       offset = slot_number * (num_pages - 1);
 
        store->filemap = kmalloc(sizeof(struct page *)
                                 * num_pages, GFP_KERNEL);
@@ -713,20 +760,22 @@ static int bitmap_storage_alloc(struct bitmap_storage *store,
                store->sb_page = alloc_page(GFP_KERNEL|__GFP_ZERO);
                if (store->sb_page == NULL)
                        return -ENOMEM;
-               store->sb_page->index = 0;
        }
+
        pnum = 0;
        if (store->sb_page) {
                store->filemap[0] = store->sb_page;
                pnum = 1;
+               store->sb_page->index = offset;
        }
+
        for ( ; pnum < num_pages; pnum++) {
                store->filemap[pnum] = alloc_page(GFP_KERNEL|__GFP_ZERO);
                if (!store->filemap[pnum]) {
                        store->file_pages = pnum;
                        return -ENOMEM;
                }
-               store->filemap[pnum]->index = pnum;
+               store->filemap[pnum]->index = pnum + offset;
        }
        store->file_pages = pnum;
 
@@ -885,6 +934,28 @@ static void bitmap_file_clear_bit(struct bitmap *bitmap, sector_t block)
        }
 }
 
+static int bitmap_file_test_bit(struct bitmap *bitmap, sector_t block)
+{
+       unsigned long bit;
+       struct page *page;
+       void *paddr;
+       unsigned long chunk = block >> bitmap->counts.chunkshift;
+       int set = 0;
+
+       page = filemap_get_page(&bitmap->storage, chunk);
+       if (!page)
+               return -EINVAL;
+       bit = file_page_offset(&bitmap->storage, chunk);
+       paddr = kmap_atomic(page);
+       if (test_bit(BITMAP_HOSTENDIAN, &bitmap->flags))
+               set = test_bit(bit, paddr);
+       else
+               set = test_bit_le(bit, paddr);
+       kunmap_atomic(paddr);
+       return set;
+}
+
+
 /* this gets called when the md device is ready to unplug its underlying
  * (slave) device queues -- before we let any writes go down, we need to
  * sync the dirty pages of the bitmap file to disk */
@@ -935,7 +1006,7 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int n
  */
 static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
 {
-       unsigned long i, chunks, index, oldindex, bit;
+       unsigned long i, chunks, index, oldindex, bit, node_offset = 0;
        struct page *page = NULL;
        unsigned long bit_cnt = 0;
        struct file *file;
@@ -981,6 +1052,9 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
        if (!bitmap->mddev->bitmap_info.external)
                offset = sizeof(bitmap_super_t);
 
+       if (mddev_is_clustered(bitmap->mddev))
+               node_offset = bitmap->cluster_slot * (DIV_ROUND_UP(store->bytes, PAGE_SIZE));
+
        for (i = 0; i < chunks; i++) {
                int b;
                index = file_page_index(&bitmap->storage, i);
@@ -1001,7 +1075,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
                                        bitmap->mddev,
                                        bitmap->mddev->bitmap_info.offset,
                                        page,
-                                       index, count);
+                                       index + node_offset, count);
 
                        if (ret)
                                goto err;
@@ -1207,7 +1281,6 @@ void bitmap_daemon_work(struct mddev *mddev)
             j < bitmap->storage.file_pages
                     && !test_bit(BITMAP_STALE, &bitmap->flags);
             j++) {
-
                if (test_page_attr(bitmap, j,
                                   BITMAP_PAGE_DIRTY))
                        /* bitmap_unplug will handle the rest */
@@ -1530,11 +1603,13 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int n
                return;
        }
        if (!*bmc) {
-               *bmc = 2 | (needed ? NEEDED_MASK : 0);
+               *bmc = 2;
                bitmap_count_page(&bitmap->counts, offset, 1);
                bitmap_set_pending(&bitmap->counts, offset);
                bitmap->allclean = 0;
        }
+       if (needed)
+               *bmc |= NEEDED_MASK;
        spin_unlock_irq(&bitmap->counts.lock);
 }
 
@@ -1591,6 +1666,10 @@ static void bitmap_free(struct bitmap *bitmap)
        if (!bitmap) /* there was no bitmap */
                return;
 
+       if (mddev_is_clustered(bitmap->mddev) && bitmap->mddev->cluster_info &&
+               bitmap->cluster_slot == md_cluster_ops->slot_number(bitmap->mddev))
+               md_cluster_stop(bitmap->mddev);
+
        /* Shouldn't be needed - but just in case.... */
        wait_event(bitmap->write_wait,
                   atomic_read(&bitmap->pending_writes) == 0);
@@ -1636,7 +1715,7 @@ void bitmap_destroy(struct mddev *mddev)
  * initialize the bitmap structure
  * if this returns an error, bitmap_destroy must be called to do clean up
  */
-int bitmap_create(struct mddev *mddev)
+struct bitmap *bitmap_create(struct mddev *mddev, int slot)
 {
        struct bitmap *bitmap;
        sector_t blocks = mddev->resync_max_sectors;
@@ -1650,7 +1729,7 @@ int bitmap_create(struct mddev *mddev)
 
        bitmap = kzalloc(sizeof(*bitmap), GFP_KERNEL);
        if (!bitmap)
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
 
        spin_lock_init(&bitmap->counts.lock);
        atomic_set(&bitmap->pending_writes, 0);
@@ -1659,6 +1738,7 @@ int bitmap_create(struct mddev *mddev)
        init_waitqueue_head(&bitmap->behind_wait);
 
        bitmap->mddev = mddev;
+       bitmap->cluster_slot = slot;
 
        if (mddev->kobj.sd)
                bm = sysfs_get_dirent(mddev->kobj.sd, "bitmap");
@@ -1706,12 +1786,14 @@ int bitmap_create(struct mddev *mddev)
        printk(KERN_INFO "created bitmap (%lu pages) for device %s\n",
               bitmap->counts.pages, bmname(bitmap));
 
-       mddev->bitmap = bitmap;
-       return test_bit(BITMAP_WRITE_ERROR, &bitmap->flags) ? -EIO : 0;
+       err = test_bit(BITMAP_WRITE_ERROR, &bitmap->flags) ? -EIO : 0;
+       if (err)
+               goto error;
 
+       return bitmap;
  error:
        bitmap_free(bitmap);
-       return err;
+       return ERR_PTR(err);
 }
 
 int bitmap_load(struct mddev *mddev)
@@ -1765,6 +1847,60 @@ out:
 }
 EXPORT_SYMBOL_GPL(bitmap_load);
 
+/* Loads the bitmap associated with slot and copies the resync information
+ * to our bitmap
+ */
+int bitmap_copy_from_slot(struct mddev *mddev, int slot,
+               sector_t *low, sector_t *high, bool clear_bits)
+{
+       int rv = 0, i, j;
+       sector_t block, lo = 0, hi = 0;
+       struct bitmap_counts *counts;
+       struct bitmap *bitmap = bitmap_create(mddev, slot);
+
+       if (IS_ERR(bitmap))
+               return PTR_ERR(bitmap);
+
+       rv = bitmap_read_sb(bitmap);
+       if (rv)
+               goto err;
+
+       rv = bitmap_init_from_disk(bitmap, 0);
+       if (rv)
+               goto err;
+
+       counts = &bitmap->counts;
+       for (j = 0; j < counts->chunks; j++) {
+               block = (sector_t)j << counts->chunkshift;
+               if (bitmap_file_test_bit(bitmap, block)) {
+                       if (!lo)
+                               lo = block;
+                       hi = block;
+                       bitmap_file_clear_bit(bitmap, block);
+                       bitmap_set_memory_bits(mddev->bitmap, block, 1);
+                       bitmap_file_set_bit(mddev->bitmap, block);
+               }
+       }
+
+       if (clear_bits) {
+               bitmap_update_sb(bitmap);
+               /* Setting this for the ev_page should be enough.
+                * And we do not require both write_all and PAGE_DIRT either
+                */
+               for (i = 0; i < bitmap->storage.file_pages; i++)
+                       set_page_attr(bitmap, i, BITMAP_PAGE_DIRTY);
+               bitmap_write_all(bitmap);
+               bitmap_unplug(bitmap);
+       }
+       *low = lo;
+       *high = hi;
+err:
+       bitmap_free(bitmap);
+       return rv;
+}
+EXPORT_SYMBOL_GPL(bitmap_copy_from_slot);
+
+
 void bitmap_status(struct seq_file *seq, struct bitmap *bitmap)
 {
        unsigned long chunk_kb;
@@ -1849,7 +1985,8 @@ int bitmap_resize(struct bitmap *bitmap, sector_t blocks,
        memset(&store, 0, sizeof(store));
        if (bitmap->mddev->bitmap_info.offset || bitmap->mddev->bitmap_info.file)
                ret = bitmap_storage_alloc(&store, chunks,
-                                          !bitmap->mddev->bitmap_info.external);
+                                          !bitmap->mddev->bitmap_info.external,
+                                          bitmap->cluster_slot);
        if (ret)
                goto err;
 
@@ -2021,13 +2158,18 @@ location_store(struct mddev *mddev, const char *buf, size_t len)
                                return -EINVAL;
                        mddev->bitmap_info.offset = offset;
                        if (mddev->pers) {
+                               struct bitmap *bitmap;
                                mddev->pers->quiesce(mddev, 1);
-                               rv = bitmap_create(mddev);
-                               if (!rv)
+                               bitmap = bitmap_create(mddev, -1);
+                               if (IS_ERR(bitmap))
+                                       rv = PTR_ERR(bitmap);
+                               else {
+                                       mddev->bitmap = bitmap;
                                        rv = bitmap_load(mddev);
-                               if (rv) {
-                                       bitmap_destroy(mddev);
-                                       mddev->bitmap_info.offset = 0;
+                                       if (rv) {
+                                               bitmap_destroy(mddev);
+                                               mddev->bitmap_info.offset = 0;
+                                       }
                                }
                                mddev->pers->quiesce(mddev, 0);
                                if (rv)
@@ -2186,6 +2328,8 @@ __ATTR(chunksize, S_IRUGO|S_IWUSR, chunksize_show, chunksize_store);
 
 static ssize_t metadata_show(struct mddev *mddev, char *page)
 {
+       if (mddev_is_clustered(mddev))
+               return sprintf(page, "clustered\n");
        return sprintf(page, "%s\n", (mddev->bitmap_info.external
                                      ? "external" : "internal"));
 }
@@ -2198,7 +2342,8 @@ static ssize_t metadata_store(struct mddev *mddev, const char *buf, size_t len)
                return -EBUSY;
        if (strncmp(buf, "external", 8) == 0)
                mddev->bitmap_info.external = 1;
-       else if (strncmp(buf, "internal", 8) == 0)
+       else if ((strncmp(buf, "internal", 8) == 0) ||
+                       (strncmp(buf, "clustered", 9) == 0))
                mddev->bitmap_info.external = 0;
        else
                return -EINVAL;
index 30210b9c4ef972e8ee1fcb79866f2c62d551c5d2..f1f4dd01090d3782dc22743201c7b2f264ae256f 100644 (file)
@@ -130,8 +130,9 @@ typedef struct bitmap_super_s {
        __le32 write_behind; /* 60  number of outstanding write-behind writes */
        __le32 sectors_reserved; /* 64 number of 512-byte sectors that are
                                  * reserved for the bitmap. */
-
-       __u8  pad[256 - 68]; /* set to zero */
+       __le32 nodes;        /* 68 the maximum number of nodes in cluster. */
+       __u8 cluster_name[64]; /* 72 cluster name to which this md belongs */
+       __u8  pad[256 - 136]; /* set to zero */
 } bitmap_super_t;
 
 /* notes:
@@ -226,12 +227,13 @@ struct bitmap {
        wait_queue_head_t behind_wait;
 
        struct kernfs_node *sysfs_can_clear;
+       int cluster_slot;               /* Slot offset for clustered env */
 };
 
 /* the bitmap API */
 
 /* these are used only by md/bitmap */
-int  bitmap_create(struct mddev *mddev);
+struct bitmap *bitmap_create(struct mddev *mddev, int slot);
 int bitmap_load(struct mddev *mddev);
 void bitmap_flush(struct mddev *mddev);
 void bitmap_destroy(struct mddev *mddev);
@@ -260,6 +262,8 @@ void bitmap_daemon_work(struct mddev *mddev);
 
 int bitmap_resize(struct bitmap *bitmap, sector_t blocks,
                  int chunksize, int init);
+int bitmap_copy_from_slot(struct mddev *mddev, int slot,
+                               sector_t *lo, sector_t *hi, bool clear_bits);
 #endif
 
 #endif
index c8a18e4ee9dce262bb2c5bb87392018176b6ccfc..720ceeb7fa9b29118bea02dcb59e82a9f2638ee6 100644 (file)
@@ -1298,21 +1298,22 @@ static int table_load(struct dm_ioctl *param, size_t param_size)
                goto err_unlock_md_type;
        }
 
-       if (dm_get_md_type(md) == DM_TYPE_NONE)
+       if (dm_get_md_type(md) == DM_TYPE_NONE) {
                /* Initial table load: acquire type of table. */
                dm_set_md_type(md, dm_table_get_type(t));
-       else if (dm_get_md_type(md) != dm_table_get_type(t)) {
+
+               /* setup md->queue to reflect md's type (may block) */
+               r = dm_setup_md_queue(md);
+               if (r) {
+                       DMWARN("unable to set up device queue for new table.");
+                       goto err_unlock_md_type;
+               }
+       } else if (dm_get_md_type(md) != dm_table_get_type(t)) {
                DMWARN("can't change device type after initial table load.");
                r = -EINVAL;
                goto err_unlock_md_type;
        }
 
-       /* setup md->queue to reflect md's type (may block) */
-       r = dm_setup_md_queue(md);
-       if (r) {
-               DMWARN("unable to set up device queue for new table.");
-               goto err_unlock_md_type;
-       }
        dm_unlock_md_type(md);
 
        /* stage inactive table */
index f8c7ca3e8947378484a6d3f9745c363c78ab2879..a930b72314ac985da702f8b47a8054a75b2e2ba8 100644 (file)
@@ -1082,18 +1082,26 @@ static void rq_completed(struct mapped_device *md, int rw, bool run_queue)
        dm_put(md);
 }
 
-static void free_rq_clone(struct request *clone)
+static void free_rq_clone(struct request *clone, bool must_be_mapped)
 {
        struct dm_rq_target_io *tio = clone->end_io_data;
        struct mapped_device *md = tio->md;
 
+       WARN_ON_ONCE(must_be_mapped && !clone->q);
+
        blk_rq_unprep_clone(clone);
 
-       if (clone->q->mq_ops)
+       if (md->type == DM_TYPE_MQ_REQUEST_BASED)
+               /* stacked on blk-mq queue(s) */
                tio->ti->type->release_clone_rq(clone);
        else if (!md->queue->mq_ops)
                /* request_fn queue stacked on request_fn queue(s) */
                free_clone_request(md, clone);
+       /*
+        * NOTE: for the blk-mq queue stacked on request_fn queue(s) case:
+        * no need to call free_clone_request() because we leverage blk-mq by
+        * allocating the clone at the end of the blk-mq pdu (see: clone_rq)
+        */
 
        if (!md->queue->mq_ops)
                free_rq_tio(tio);
@@ -1124,7 +1132,7 @@ static void dm_end_request(struct request *clone, int error)
                        rq->sense_len = clone->sense_len;
        }
 
-       free_rq_clone(clone);
+       free_rq_clone(clone, true);
        if (!rq->q->mq_ops)
                blk_end_request_all(rq, error);
        else
@@ -1143,7 +1151,7 @@ static void dm_unprep_request(struct request *rq)
        }
 
        if (clone)
-               free_rq_clone(clone);
+               free_rq_clone(clone, false);
 }
 
 /*
@@ -2662,9 +2670,6 @@ static int dm_init_request_based_queue(struct mapped_device *md)
 {
        struct request_queue *q = NULL;
 
-       if (md->queue->elevator)
-               return 0;
-
        /* Fully initialize the queue */
        q = blk_init_allocated_queue(md->queue, dm_request_fn, NULL);
        if (!q)
diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c
new file mode 100644 (file)
index 0000000..fcfc4b9
--- /dev/null
@@ -0,0 +1,965 @@
+/*
+ * Copyright (C) 2015, SUSE
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ */
+
+
+#include <linux/module.h>
+#include <linux/dlm.h>
+#include <linux/sched.h>
+#include <linux/raid/md_p.h>
+#include "md.h"
+#include "bitmap.h"
+#include "md-cluster.h"
+
+#define LVB_SIZE       64
+#define NEW_DEV_TIMEOUT 5000
+
+struct dlm_lock_resource {
+       dlm_lockspace_t *ls;
+       struct dlm_lksb lksb;
+       char *name; /* lock name. */
+       uint32_t flags; /* flags to pass to dlm_lock() */
+       struct completion completion; /* completion for synchronized locking */
+       void (*bast)(void *arg, int mode); /* blocking AST function pointer*/
+       struct mddev *mddev; /* pointing back to mddev. */
+};
+
+struct suspend_info {
+       int slot;
+       sector_t lo;
+       sector_t hi;
+       struct list_head list;
+};
+
+struct resync_info {
+       __le64 lo;
+       __le64 hi;
+};
+
+/* md_cluster_info flags */
+#define                MD_CLUSTER_WAITING_FOR_NEWDISK          1
+
+
+struct md_cluster_info {
+       /* dlm lock space and resources for clustered raid. */
+       dlm_lockspace_t *lockspace;
+       int slot_number;
+       struct completion completion;
+       struct dlm_lock_resource *sb_lock;
+       struct mutex sb_mutex;
+       struct dlm_lock_resource *bitmap_lockres;
+       struct list_head suspend_list;
+       spinlock_t suspend_lock;
+       struct md_thread *recovery_thread;
+       unsigned long recovery_map;
+       /* communication loc resources */
+       struct dlm_lock_resource *ack_lockres;
+       struct dlm_lock_resource *message_lockres;
+       struct dlm_lock_resource *token_lockres;
+       struct dlm_lock_resource *no_new_dev_lockres;
+       struct md_thread *recv_thread;
+       struct completion newdisk_completion;
+       unsigned long state;
+};
+
+enum msg_type {
+       METADATA_UPDATED = 0,
+       RESYNCING,
+       NEWDISK,
+       REMOVE,
+       RE_ADD,
+};
+
+struct cluster_msg {
+       int type;
+       int slot;
+       /* TODO: Unionize this for smaller footprint */
+       sector_t low;
+       sector_t high;
+       char uuid[16];
+       int raid_slot;
+};
+
+static void sync_ast(void *arg)
+{
+       struct dlm_lock_resource *res;
+
+       res = (struct dlm_lock_resource *) arg;
+       complete(&res->completion);
+}
+
+static int dlm_lock_sync(struct dlm_lock_resource *res, int mode)
+{
+       int ret = 0;
+
+       init_completion(&res->completion);
+       ret = dlm_lock(res->ls, mode, &res->lksb,
+                       res->flags, res->name, strlen(res->name),
+                       0, sync_ast, res, res->bast);
+       if (ret)
+               return ret;
+       wait_for_completion(&res->completion);
+       return res->lksb.sb_status;
+}
+
+static int dlm_unlock_sync(struct dlm_lock_resource *res)
+{
+       return dlm_lock_sync(res, DLM_LOCK_NL);
+}
+
+static struct dlm_lock_resource *lockres_init(struct mddev *mddev,
+               char *name, void (*bastfn)(void *arg, int mode), int with_lvb)
+{
+       struct dlm_lock_resource *res = NULL;
+       int ret, namelen;
+       struct md_cluster_info *cinfo = mddev->cluster_info;
+
+       res = kzalloc(sizeof(struct dlm_lock_resource), GFP_KERNEL);
+       if (!res)
+               return NULL;
+       res->ls = cinfo->lockspace;
+       res->mddev = mddev;
+       namelen = strlen(name);
+       res->name = kzalloc(namelen + 1, GFP_KERNEL);
+       if (!res->name) {
+               pr_err("md-cluster: Unable to allocate resource name for resource %s\n", name);
+               goto out_err;
+       }
+       strlcpy(res->name, name, namelen + 1);
+       if (with_lvb) {
+               res->lksb.sb_lvbptr = kzalloc(LVB_SIZE, GFP_KERNEL);
+               if (!res->lksb.sb_lvbptr) {
+                       pr_err("md-cluster: Unable to allocate LVB for resource %s\n", name);
+                       goto out_err;
+               }
+               res->flags = DLM_LKF_VALBLK;
+       }
+
+       if (bastfn)
+               res->bast = bastfn;
+
+       res->flags |= DLM_LKF_EXPEDITE;
+
+       ret = dlm_lock_sync(res, DLM_LOCK_NL);
+       if (ret) {
+               pr_err("md-cluster: Unable to lock NL on new lock resource %s\n", name);
+               goto out_err;
+       }
+       res->flags &= ~DLM_LKF_EXPEDITE;
+       res->flags |= DLM_LKF_CONVERT;
+
+       return res;
+out_err:
+       kfree(res->lksb.sb_lvbptr);
+       kfree(res->name);
+       kfree(res);
+       return NULL;
+}
+
+static void lockres_free(struct dlm_lock_resource *res)
+{
+       if (!res)
+               return;
+
+       init_completion(&res->completion);
+       dlm_unlock(res->ls, res->lksb.sb_lkid, 0, &res->lksb, res);
+       wait_for_completion(&res->completion);
+
+       kfree(res->name);
+       kfree(res->lksb.sb_lvbptr);
+       kfree(res);
+}
+
+static char *pretty_uuid(char *dest, char *src)
+{
+       int i, len = 0;
+
+       for (i = 0; i < 16; i++) {
+               if (i == 4 || i == 6 || i == 8 || i == 10)
+                       len += sprintf(dest + len, "-");
+               len += sprintf(dest + len, "%02x", (__u8)src[i]);
+       }
+       return dest;
+}
+
+static void add_resync_info(struct mddev *mddev, struct dlm_lock_resource *lockres,
+               sector_t lo, sector_t hi)
+{
+       struct resync_info *ri;
+
+       ri = (struct resync_info *)lockres->lksb.sb_lvbptr;
+       ri->lo = cpu_to_le64(lo);
+       ri->hi = cpu_to_le64(hi);
+}
+
+static struct suspend_info *read_resync_info(struct mddev *mddev, struct dlm_lock_resource *lockres)
+{
+       struct resync_info ri;
+       struct suspend_info *s = NULL;
+       sector_t hi = 0;
+
+       dlm_lock_sync(lockres, DLM_LOCK_CR);
+       memcpy(&ri, lockres->lksb.sb_lvbptr, sizeof(struct resync_info));
+       hi = le64_to_cpu(ri.hi);
+       if (ri.hi > 0) {
+               s = kzalloc(sizeof(struct suspend_info), GFP_KERNEL);
+               if (!s)
+                       goto out;
+               s->hi = hi;
+               s->lo = le64_to_cpu(ri.lo);
+       }
+       dlm_unlock_sync(lockres);
+out:
+       return s;
+}
+
+static void recover_bitmaps(struct md_thread *thread)
+{
+       struct mddev *mddev = thread->mddev;
+       struct md_cluster_info *cinfo = mddev->cluster_info;
+       struct dlm_lock_resource *bm_lockres;
+       char str[64];
+       int slot, ret;
+       struct suspend_info *s, *tmp;
+       sector_t lo, hi;
+
+       while (cinfo->recovery_map) {
+               slot = fls64((u64)cinfo->recovery_map) - 1;
+
+               /* Clear suspend_area associated with the bitmap */
+               spin_lock_irq(&cinfo->suspend_lock);
+               list_for_each_entry_safe(s, tmp, &cinfo->suspend_list, list)
+                       if (slot == s->slot) {
+                               list_del(&s->list);
+                               kfree(s);
+                       }
+               spin_unlock_irq(&cinfo->suspend_lock);
+
+               snprintf(str, 64, "bitmap%04d", slot);
+               bm_lockres = lockres_init(mddev, str, NULL, 1);
+               if (!bm_lockres) {
+                       pr_err("md-cluster: Cannot initialize bitmaps\n");
+                       goto clear_bit;
+               }
+
+               ret = dlm_lock_sync(bm_lockres, DLM_LOCK_PW);
+               if (ret) {
+                       pr_err("md-cluster: Could not DLM lock %s: %d\n",
+                                       str, ret);
+                       goto clear_bit;
+               }
+               ret = bitmap_copy_from_slot(mddev, slot, &lo, &hi, true);
+               if (ret) {
+                       pr_err("md-cluster: Could not copy data from bitmap %d\n", slot);
+                       goto dlm_unlock;
+               }
+               if (hi > 0) {
+                       /* TODO:Wait for current resync to get over */
+                       set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+                       if (lo < mddev->recovery_cp)
+                               mddev->recovery_cp = lo;
+                       md_check_recovery(mddev);
+               }
+dlm_unlock:
+               dlm_unlock_sync(bm_lockres);
+clear_bit:
+               clear_bit(slot, &cinfo->recovery_map);
+       }
+}
+
+static void recover_prep(void *arg)
+{
+}
+
+static void recover_slot(void *arg, struct dlm_slot *slot)
+{
+       struct mddev *mddev = arg;
+       struct md_cluster_info *cinfo = mddev->cluster_info;
+
+       pr_info("md-cluster: %s Node %d/%d down. My slot: %d. Initiating recovery.\n",
+                       mddev->bitmap_info.cluster_name,
+                       slot->nodeid, slot->slot,
+                       cinfo->slot_number);
+       set_bit(slot->slot - 1, &cinfo->recovery_map);
+       if (!cinfo->recovery_thread) {
+               cinfo->recovery_thread = md_register_thread(recover_bitmaps,
+                               mddev, "recover");
+               if (!cinfo->recovery_thread) {
+                       pr_warn("md-cluster: Could not create recovery thread\n");
+                       return;
+               }
+       }
+       md_wakeup_thread(cinfo->recovery_thread);
+}
+
+static void recover_done(void *arg, struct dlm_slot *slots,
+               int num_slots, int our_slot,
+               uint32_t generation)
+{
+       struct mddev *mddev = arg;
+       struct md_cluster_info *cinfo = mddev->cluster_info;
+
+       cinfo->slot_number = our_slot;
+       complete(&cinfo->completion);
+}
+
+static const struct dlm_lockspace_ops md_ls_ops = {
+       .recover_prep = recover_prep,
+       .recover_slot = recover_slot,
+       .recover_done = recover_done,
+};
+
+/*
+ * The BAST function for the ack lock resource
+ * This function wakes up the receive thread in
+ * order to receive and process the message.
+ */
+static void ack_bast(void *arg, int mode)
+{
+       struct dlm_lock_resource *res = (struct dlm_lock_resource *)arg;
+       struct md_cluster_info *cinfo = res->mddev->cluster_info;
+
+       if (mode == DLM_LOCK_EX)
+               md_wakeup_thread(cinfo->recv_thread);
+}
+
+static void __remove_suspend_info(struct md_cluster_info *cinfo, int slot)
+{
+       struct suspend_info *s, *tmp;
+
+       list_for_each_entry_safe(s, tmp, &cinfo->suspend_list, list)
+               if (slot == s->slot) {
+                       pr_info("%s:%d Deleting suspend_info: %d\n",
+                                       __func__, __LINE__, slot);
+                       list_del(&s->list);
+                       kfree(s);
+                       break;
+               }
+}
+
+static void remove_suspend_info(struct md_cluster_info *cinfo, int slot)
+{
+       spin_lock_irq(&cinfo->suspend_lock);
+       __remove_suspend_info(cinfo, slot);
+       spin_unlock_irq(&cinfo->suspend_lock);
+}
+
+
+static void process_suspend_info(struct md_cluster_info *cinfo,
+               int slot, sector_t lo, sector_t hi)
+{
+       struct suspend_info *s;
+
+       if (!hi) {
+               remove_suspend_info(cinfo, slot);
+               return;
+       }
+       s = kzalloc(sizeof(struct suspend_info), GFP_KERNEL);
+       if (!s)
+               return;
+       s->slot = slot;
+       s->lo = lo;
+       s->hi = hi;
+       spin_lock_irq(&cinfo->suspend_lock);
+       /* Remove existing entry (if exists) before adding */
+       __remove_suspend_info(cinfo, slot);
+       list_add(&s->list, &cinfo->suspend_list);
+       spin_unlock_irq(&cinfo->suspend_lock);
+}
+
+static void process_add_new_disk(struct mddev *mddev, struct cluster_msg *cmsg)
+{
+       char disk_uuid[64];
+       struct md_cluster_info *cinfo = mddev->cluster_info;
+       char event_name[] = "EVENT=ADD_DEVICE";
+       char raid_slot[16];
+       char *envp[] = {event_name, disk_uuid, raid_slot, NULL};
+       int len;
+
+       len = snprintf(disk_uuid, 64, "DEVICE_UUID=");
+       pretty_uuid(disk_uuid + len, cmsg->uuid);
+       snprintf(raid_slot, 16, "RAID_DISK=%d", cmsg->raid_slot);
+       pr_info("%s:%d Sending kobject change with %s and %s\n", __func__, __LINE__, disk_uuid, raid_slot);
+       init_completion(&cinfo->newdisk_completion);
+       set_bit(MD_CLUSTER_WAITING_FOR_NEWDISK, &cinfo->state);
+       kobject_uevent_env(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE, envp);
+       wait_for_completion_timeout(&cinfo->newdisk_completion,
+                       NEW_DEV_TIMEOUT);
+       clear_bit(MD_CLUSTER_WAITING_FOR_NEWDISK, &cinfo->state);
+}
+
+
+static void process_metadata_update(struct mddev *mddev, struct cluster_msg *msg)
+{
+       struct md_cluster_info *cinfo = mddev->cluster_info;
+
+       md_reload_sb(mddev);
+       dlm_lock_sync(cinfo->no_new_dev_lockres, DLM_LOCK_CR);
+}
+
+static void process_remove_disk(struct mddev *mddev, struct cluster_msg *msg)
+{
+       struct md_rdev *rdev = md_find_rdev_nr_rcu(mddev, msg->raid_slot);
+
+       if (rdev)
+               md_kick_rdev_from_array(rdev);
+       else
+               pr_warn("%s: %d Could not find disk(%d) to REMOVE\n", __func__, __LINE__, msg->raid_slot);
+}
+
+static void process_readd_disk(struct mddev *mddev, struct cluster_msg *msg)
+{
+       struct md_rdev *rdev = md_find_rdev_nr_rcu(mddev, msg->raid_slot);
+
+       if (rdev && test_bit(Faulty, &rdev->flags))
+               clear_bit(Faulty, &rdev->flags);
+       else
+               pr_warn("%s: %d Could not find disk(%d) which is faulty", __func__, __LINE__, msg->raid_slot);
+}
+
+static void process_recvd_msg(struct mddev *mddev, struct cluster_msg *msg)
+{
+       switch (msg->type) {
+       case METADATA_UPDATED:
+               pr_info("%s: %d Received message: METADATA_UPDATE from %d\n",
+                       __func__, __LINE__, msg->slot);
+               process_metadata_update(mddev, msg);
+               break;
+       case RESYNCING:
+               pr_info("%s: %d Received message: RESYNCING from %d\n",
+                       __func__, __LINE__, msg->slot);
+               process_suspend_info(mddev->cluster_info, msg->slot,
+                               msg->low, msg->high);
+               break;
+       case NEWDISK:
+               pr_info("%s: %d Received message: NEWDISK from %d\n",
+                       __func__, __LINE__, msg->slot);
+               process_add_new_disk(mddev, msg);
+               break;
+       case REMOVE:
+               pr_info("%s: %d Received REMOVE from %d\n",
+                       __func__, __LINE__, msg->slot);
+               process_remove_disk(mddev, msg);
+               break;
+       case RE_ADD:
+               pr_info("%s: %d Received RE_ADD from %d\n",
+                       __func__, __LINE__, msg->slot);
+               process_readd_disk(mddev, msg);
+               break;
+       default:
+               pr_warn("%s:%d Received unknown message from %d\n",
+                       __func__, __LINE__, msg->slot);
+       }
+}
+
+/*
+ * thread for receiving message
+ */
+static void recv_daemon(struct md_thread *thread)
+{
+       struct md_cluster_info *cinfo = thread->mddev->cluster_info;
+       struct dlm_lock_resource *ack_lockres = cinfo->ack_lockres;
+       struct dlm_lock_resource *message_lockres = cinfo->message_lockres;
+       struct cluster_msg msg;
+
+       /*get CR on Message*/
+       if (dlm_lock_sync(message_lockres, DLM_LOCK_CR)) {
+               pr_err("md/raid1:failed to get CR on MESSAGE\n");
+               return;
+       }
+
+       /* read lvb and wake up thread to process this message_lockres */
+       memcpy(&msg, message_lockres->lksb.sb_lvbptr, sizeof(struct cluster_msg));
+       process_recvd_msg(thread->mddev, &msg);
+
+       /*release CR on ack_lockres*/
+       dlm_unlock_sync(ack_lockres);
+       /*up-convert to EX on message_lockres*/
+       dlm_lock_sync(message_lockres, DLM_LOCK_EX);
+       /*get CR on ack_lockres again*/
+       dlm_lock_sync(ack_lockres, DLM_LOCK_CR);
+       /*release CR on message_lockres*/
+       dlm_unlock_sync(message_lockres);
+}
+
+/* lock_comm()
+ * Takes the lock on the TOKEN lock resource so no other
+ * node can communicate while the operation is underway.
+ */
+static int lock_comm(struct md_cluster_info *cinfo)
+{
+       int error;
+
+       error = dlm_lock_sync(cinfo->token_lockres, DLM_LOCK_EX);
+       if (error)
+               pr_err("md-cluster(%s:%d): failed to get EX on TOKEN (%d)\n",
+                               __func__, __LINE__, error);
+       return error;
+}
+
+static void unlock_comm(struct md_cluster_info *cinfo)
+{
+       dlm_unlock_sync(cinfo->token_lockres);
+}
+
+/* __sendmsg()
+ * This function performs the actual sending of the message. This function is
+ * usually called after performing the encompassing operation
+ * The function:
+ * 1. Grabs the message lockresource in EX mode
+ * 2. Copies the message to the message LVB
+ * 3. Downconverts message lockresource to CR
+ * 4. Upconverts ack lock resource from CR to EX. This forces the BAST on other nodes
+ *    and the other nodes read the message. The thread will wait here until all other
+ *    nodes have released ack lock resource.
+ * 5. Downconvert ack lockresource to CR
+ */
+static int __sendmsg(struct md_cluster_info *cinfo, struct cluster_msg *cmsg)
+{
+       int error;
+       int slot = cinfo->slot_number - 1;
+
+       cmsg->slot = cpu_to_le32(slot);
+       /*get EX on Message*/
+       error = dlm_lock_sync(cinfo->message_lockres, DLM_LOCK_EX);
+       if (error) {
+               pr_err("md-cluster: failed to get EX on MESSAGE (%d)\n", error);
+               goto failed_message;
+       }
+
+       memcpy(cinfo->message_lockres->lksb.sb_lvbptr, (void *)cmsg,
+                       sizeof(struct cluster_msg));
+       /*down-convert EX to CR on Message*/
+       error = dlm_lock_sync(cinfo->message_lockres, DLM_LOCK_CR);
+       if (error) {
+               pr_err("md-cluster: failed to convert EX to CR on MESSAGE(%d)\n",
+                               error);
+               goto failed_message;
+       }
+
+       /*up-convert CR to EX on Ack*/
+       error = dlm_lock_sync(cinfo->ack_lockres, DLM_LOCK_EX);
+       if (error) {
+               pr_err("md-cluster: failed to convert CR to EX on ACK(%d)\n",
+                               error);
+               goto failed_ack;
+       }
+
+       /*down-convert EX to CR on Ack*/
+       error = dlm_lock_sync(cinfo->ack_lockres, DLM_LOCK_CR);
+       if (error) {
+               pr_err("md-cluster: failed to convert EX to CR on ACK(%d)\n",
+                               error);
+               goto failed_ack;
+       }
+
+failed_ack:
+       dlm_unlock_sync(cinfo->message_lockres);
+failed_message:
+       return error;
+}
+
+static int sendmsg(struct md_cluster_info *cinfo, struct cluster_msg *cmsg)
+{
+       int ret;
+
+       lock_comm(cinfo);
+       ret = __sendmsg(cinfo, cmsg);
+       unlock_comm(cinfo);
+       return ret;
+}
+
+static int gather_all_resync_info(struct mddev *mddev, int total_slots)
+{
+       struct md_cluster_info *cinfo = mddev->cluster_info;
+       int i, ret = 0;
+       struct dlm_lock_resource *bm_lockres;
+       struct suspend_info *s;
+       char str[64];
+
+
+       for (i = 0; i < total_slots; i++) {
+               memset(str, '\0', 64);
+               snprintf(str, 64, "bitmap%04d", i);
+               bm_lockres = lockres_init(mddev, str, NULL, 1);
+               if (!bm_lockres)
+                       return -ENOMEM;
+               if (i == (cinfo->slot_number - 1))
+                       continue;
+
+               bm_lockres->flags |= DLM_LKF_NOQUEUE;
+               ret = dlm_lock_sync(bm_lockres, DLM_LOCK_PW);
+               if (ret == -EAGAIN) {
+                       memset(bm_lockres->lksb.sb_lvbptr, '\0', LVB_SIZE);
+                       s = read_resync_info(mddev, bm_lockres);
+                       if (s) {
+                               pr_info("%s:%d Resync[%llu..%llu] in progress on %d\n",
+                                               __func__, __LINE__,
+                                               (unsigned long long) s->lo,
+                                               (unsigned long long) s->hi, i);
+                               spin_lock_irq(&cinfo->suspend_lock);
+                               s->slot = i;
+                               list_add(&s->list, &cinfo->suspend_list);
+                               spin_unlock_irq(&cinfo->suspend_lock);
+                       }
+                       ret = 0;
+                       lockres_free(bm_lockres);
+                       continue;
+               }
+               if (ret)
+                       goto out;
+               /* TODO: Read the disk bitmap sb and check if it needs recovery */
+               dlm_unlock_sync(bm_lockres);
+               lockres_free(bm_lockres);
+       }
+out:
+       return ret;
+}
+
+static int join(struct mddev *mddev, int nodes)
+{
+       struct md_cluster_info *cinfo;
+       int ret, ops_rv;
+       char str[64];
+
+       if (!try_module_get(THIS_MODULE))
+               return -ENOENT;
+
+       cinfo = kzalloc(sizeof(struct md_cluster_info), GFP_KERNEL);
+       if (!cinfo)
+               return -ENOMEM;
+
+       init_completion(&cinfo->completion);
+
+       mutex_init(&cinfo->sb_mutex);
+       mddev->cluster_info = cinfo;
+
+       memset(str, 0, 64);
+       pretty_uuid(str, mddev->uuid);
+       ret = dlm_new_lockspace(str, mddev->bitmap_info.cluster_name,
+                               DLM_LSFL_FS, LVB_SIZE,
+                               &md_ls_ops, mddev, &ops_rv, &cinfo->lockspace);
+       if (ret)
+               goto err;
+       wait_for_completion(&cinfo->completion);
+       if (nodes < cinfo->slot_number) {
+               pr_err("md-cluster: Slot allotted(%d) is greater than available slots(%d).",
+                       cinfo->slot_number, nodes);
+               ret = -ERANGE;
+               goto err;
+       }
+       cinfo->sb_lock = lockres_init(mddev, "cmd-super",
+                                       NULL, 0);
+       if (!cinfo->sb_lock) {
+               ret = -ENOMEM;
+               goto err;
+       }
+       /* Initiate the communication resources */
+       ret = -ENOMEM;
+       cinfo->recv_thread = md_register_thread(recv_daemon, mddev, "cluster_recv");
+       if (!cinfo->recv_thread) {
+               pr_err("md-cluster: cannot allocate memory for recv_thread!\n");
+               goto err;
+       }
+       cinfo->message_lockres = lockres_init(mddev, "message", NULL, 1);
+       if (!cinfo->message_lockres)
+               goto err;
+       cinfo->token_lockres = lockres_init(mddev, "token", NULL, 0);
+       if (!cinfo->token_lockres)
+               goto err;
+       cinfo->ack_lockres = lockres_init(mddev, "ack", ack_bast, 0);
+       if (!cinfo->ack_lockres)
+               goto err;
+       cinfo->no_new_dev_lockres = lockres_init(mddev, "no-new-dev", NULL, 0);
+       if (!cinfo->no_new_dev_lockres)
+               goto err;
+
+       /* get sync CR lock on ACK. */
+       if (dlm_lock_sync(cinfo->ack_lockres, DLM_LOCK_CR))
+               pr_err("md-cluster: failed to get a sync CR lock on ACK!(%d)\n",
+                               ret);
+       /* get sync CR lock on no-new-dev. */
+       if (dlm_lock_sync(cinfo->no_new_dev_lockres, DLM_LOCK_CR))
+               pr_err("md-cluster: failed to get a sync CR lock on no-new-dev!(%d)\n", ret);
+
+
+       pr_info("md-cluster: Joined cluster %s slot %d\n", str, cinfo->slot_number);
+       snprintf(str, 64, "bitmap%04d", cinfo->slot_number - 1);
+       cinfo->bitmap_lockres = lockres_init(mddev, str, NULL, 1);
+       if (!cinfo->bitmap_lockres)
+               goto err;
+       if (dlm_lock_sync(cinfo->bitmap_lockres, DLM_LOCK_PW)) {
+               pr_err("Failed to get bitmap lock\n");
+               ret = -EINVAL;
+               goto err;
+       }
+
+       INIT_LIST_HEAD(&cinfo->suspend_list);
+       spin_lock_init(&cinfo->suspend_lock);
+
+       ret = gather_all_resync_info(mddev, nodes);
+       if (ret)
+               goto err;
+
+       return 0;
+err:
+       lockres_free(cinfo->message_lockres);
+       lockres_free(cinfo->token_lockres);
+       lockres_free(cinfo->ack_lockres);
+       lockres_free(cinfo->no_new_dev_lockres);
+       lockres_free(cinfo->bitmap_lockres);
+       lockres_free(cinfo->sb_lock);
+       if (cinfo->lockspace)
+               dlm_release_lockspace(cinfo->lockspace, 2);
+       mddev->cluster_info = NULL;
+       kfree(cinfo);
+       module_put(THIS_MODULE);
+       return ret;
+}
+
+static int leave(struct mddev *mddev)
+{
+       struct md_cluster_info *cinfo = mddev->cluster_info;
+
+       if (!cinfo)
+               return 0;
+       md_unregister_thread(&cinfo->recovery_thread);
+       md_unregister_thread(&cinfo->recv_thread);
+       lockres_free(cinfo->message_lockres);
+       lockres_free(cinfo->token_lockres);
+       lockres_free(cinfo->ack_lockres);
+       lockres_free(cinfo->no_new_dev_lockres);
+       lockres_free(cinfo->sb_lock);
+       lockres_free(cinfo->bitmap_lockres);
+       dlm_release_lockspace(cinfo->lockspace, 2);
+       return 0;
+}
+
+/* slot_number(): Returns the MD slot number to use
+ * DLM starts the slot numbers from 1, wheras cluster-md
+ * wants the number to be from zero, so we deduct one
+ */
+static int slot_number(struct mddev *mddev)
+{
+       struct md_cluster_info *cinfo = mddev->cluster_info;
+
+       return cinfo->slot_number - 1;
+}
+
+static void resync_info_update(struct mddev *mddev, sector_t lo, sector_t hi)
+{
+       struct md_cluster_info *cinfo = mddev->cluster_info;
+
+       add_resync_info(mddev, cinfo->bitmap_lockres, lo, hi);
+       /* Re-acquire the lock to refresh LVB */
+       dlm_lock_sync(cinfo->bitmap_lockres, DLM_LOCK_PW);
+}
+
+static int metadata_update_start(struct mddev *mddev)
+{
+       return lock_comm(mddev->cluster_info);
+}
+
+static int metadata_update_finish(struct mddev *mddev)
+{
+       struct md_cluster_info *cinfo = mddev->cluster_info;
+       struct cluster_msg cmsg;
+       int ret;
+
+       memset(&cmsg, 0, sizeof(cmsg));
+       cmsg.type = cpu_to_le32(METADATA_UPDATED);
+       ret = __sendmsg(cinfo, &cmsg);
+       unlock_comm(cinfo);
+       return ret;
+}
+
+static int metadata_update_cancel(struct mddev *mddev)
+{
+       struct md_cluster_info *cinfo = mddev->cluster_info;
+
+       return dlm_unlock_sync(cinfo->token_lockres);
+}
+
+static int resync_send(struct mddev *mddev, enum msg_type type,
+               sector_t lo, sector_t hi)
+{
+       struct md_cluster_info *cinfo = mddev->cluster_info;
+       struct cluster_msg cmsg;
+       int slot = cinfo->slot_number - 1;
+
+       pr_info("%s:%d lo: %llu hi: %llu\n", __func__, __LINE__,
+                       (unsigned long long)lo,
+                       (unsigned long long)hi);
+       resync_info_update(mddev, lo, hi);
+       cmsg.type = cpu_to_le32(type);
+       cmsg.slot = cpu_to_le32(slot);
+       cmsg.low = cpu_to_le64(lo);
+       cmsg.high = cpu_to_le64(hi);
+       return sendmsg(cinfo, &cmsg);
+}
+
+static int resync_start(struct mddev *mddev, sector_t lo, sector_t hi)
+{
+       pr_info("%s:%d\n", __func__, __LINE__);
+       return resync_send(mddev, RESYNCING, lo, hi);
+}
+
+static void resync_finish(struct mddev *mddev)
+{
+       pr_info("%s:%d\n", __func__, __LINE__);
+       resync_send(mddev, RESYNCING, 0, 0);
+}
+
+static int area_resyncing(struct mddev *mddev, sector_t lo, sector_t hi)
+{
+       struct md_cluster_info *cinfo = mddev->cluster_info;
+       int ret = 0;
+       struct suspend_info *s;
+
+       spin_lock_irq(&cinfo->suspend_lock);
+       if (list_empty(&cinfo->suspend_list))
+               goto out;
+       list_for_each_entry(s, &cinfo->suspend_list, list)
+               if (hi > s->lo && lo < s->hi) {
+                       ret = 1;
+                       break;
+               }
+out:
+       spin_unlock_irq(&cinfo->suspend_lock);
+       return ret;
+}
+
+static int add_new_disk_start(struct mddev *mddev, struct md_rdev *rdev)
+{
+       struct md_cluster_info *cinfo = mddev->cluster_info;
+       struct cluster_msg cmsg;
+       int ret = 0;
+       struct mdp_superblock_1 *sb = page_address(rdev->sb_page);
+       char *uuid = sb->device_uuid;
+
+       memset(&cmsg, 0, sizeof(cmsg));
+       cmsg.type = cpu_to_le32(NEWDISK);
+       memcpy(cmsg.uuid, uuid, 16);
+       cmsg.raid_slot = rdev->desc_nr;
+       lock_comm(cinfo);
+       ret = __sendmsg(cinfo, &cmsg);
+       if (ret)
+               return ret;
+       cinfo->no_new_dev_lockres->flags |= DLM_LKF_NOQUEUE;
+       ret = dlm_lock_sync(cinfo->no_new_dev_lockres, DLM_LOCK_EX);
+       cinfo->no_new_dev_lockres->flags &= ~DLM_LKF_NOQUEUE;
+       /* Some node does not "see" the device */
+       if (ret == -EAGAIN)
+               ret = -ENOENT;
+       else
+               dlm_lock_sync(cinfo->no_new_dev_lockres, DLM_LOCK_CR);
+       return ret;
+}
+
+static int add_new_disk_finish(struct mddev *mddev)
+{
+       struct cluster_msg cmsg;
+       struct md_cluster_info *cinfo = mddev->cluster_info;
+       int ret;
+       /* Write sb and inform others */
+       md_update_sb(mddev, 1);
+       cmsg.type = METADATA_UPDATED;
+       ret = __sendmsg(cinfo, &cmsg);
+       unlock_comm(cinfo);
+       return ret;
+}
+
+static int new_disk_ack(struct mddev *mddev, bool ack)
+{
+       struct md_cluster_info *cinfo = mddev->cluster_info;
+
+       if (!test_bit(MD_CLUSTER_WAITING_FOR_NEWDISK, &cinfo->state)) {
+               pr_warn("md-cluster(%s): Spurious cluster confirmation\n", mdname(mddev));
+               return -EINVAL;
+       }
+
+       if (ack)
+               dlm_unlock_sync(cinfo->no_new_dev_lockres);
+       complete(&cinfo->newdisk_completion);
+       return 0;
+}
+
+static int remove_disk(struct mddev *mddev, struct md_rdev *rdev)
+{
+       struct cluster_msg cmsg;
+       struct md_cluster_info *cinfo = mddev->cluster_info;
+       cmsg.type = REMOVE;
+       cmsg.raid_slot = rdev->desc_nr;
+       return __sendmsg(cinfo, &cmsg);
+}
+
+static int gather_bitmaps(struct md_rdev *rdev)
+{
+       int sn, err;
+       sector_t lo, hi;
+       struct cluster_msg cmsg;
+       struct mddev *mddev = rdev->mddev;
+       struct md_cluster_info *cinfo = mddev->cluster_info;
+
+       cmsg.type = RE_ADD;
+       cmsg.raid_slot = rdev->desc_nr;
+       err = sendmsg(cinfo, &cmsg);
+       if (err)
+               goto out;
+
+       for (sn = 0; sn < mddev->bitmap_info.nodes; sn++) {
+               if (sn == (cinfo->slot_number - 1))
+                       continue;
+               err = bitmap_copy_from_slot(mddev, sn, &lo, &hi, false);
+               if (err) {
+                       pr_warn("md-cluster: Could not gather bitmaps from slot %d", sn);
+                       goto out;
+               }
+               if ((hi > 0) && (lo < mddev->recovery_cp))
+                       mddev->recovery_cp = lo;
+       }
+out:
+       return err;
+}
+
+static struct md_cluster_operations cluster_ops = {
+       .join   = join,
+       .leave  = leave,
+       .slot_number = slot_number,
+       .resync_info_update = resync_info_update,
+       .resync_start = resync_start,
+       .resync_finish = resync_finish,
+       .metadata_update_start = metadata_update_start,
+       .metadata_update_finish = metadata_update_finish,
+       .metadata_update_cancel = metadata_update_cancel,
+       .area_resyncing = area_resyncing,
+       .add_new_disk_start = add_new_disk_start,
+       .add_new_disk_finish = add_new_disk_finish,
+       .new_disk_ack = new_disk_ack,
+       .remove_disk = remove_disk,
+       .gather_bitmaps = gather_bitmaps,
+};
+
+static int __init cluster_init(void)
+{
+       pr_warn("md-cluster: EXPERIMENTAL. Use with caution\n");
+       pr_info("Registering Cluster MD functions\n");
+       register_md_cluster_operations(&cluster_ops, THIS_MODULE);
+       return 0;
+}
+
+static void cluster_exit(void)
+{
+       unregister_md_cluster_operations();
+}
+
+module_init(cluster_init);
+module_exit(cluster_exit);
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Clustering support for MD");
diff --git a/drivers/md/md-cluster.h b/drivers/md/md-cluster.h
new file mode 100644 (file)
index 0000000..6817ee0
--- /dev/null
@@ -0,0 +1,29 @@
+
+
+#ifndef _MD_CLUSTER_H
+#define _MD_CLUSTER_H
+
+#include "md.h"
+
+struct mddev;
+struct md_rdev;
+
+struct md_cluster_operations {
+       int (*join)(struct mddev *mddev, int nodes);
+       int (*leave)(struct mddev *mddev);
+       int (*slot_number)(struct mddev *mddev);
+       void (*resync_info_update)(struct mddev *mddev, sector_t lo, sector_t hi);
+       int (*resync_start)(struct mddev *mddev, sector_t lo, sector_t hi);
+       void (*resync_finish)(struct mddev *mddev);
+       int (*metadata_update_start)(struct mddev *mddev);
+       int (*metadata_update_finish)(struct mddev *mddev);
+       int (*metadata_update_cancel)(struct mddev *mddev);
+       int (*area_resyncing)(struct mddev *mddev, sector_t lo, sector_t hi);
+       int (*add_new_disk_start)(struct mddev *mddev, struct md_rdev *rdev);
+       int (*add_new_disk_finish)(struct mddev *mddev);
+       int (*new_disk_ack)(struct mddev *mddev, bool ack);
+       int (*remove_disk)(struct mddev *mddev, struct md_rdev *rdev);
+       int (*gather_bitmaps)(struct md_rdev *rdev);
+};
+
+#endif /* _MD_CLUSTER_H */
index e6178787ce3dd4a9b0e33b80b72ac39f73e25e33..d4f31e195e26ebcc4233c9b333624d8b73191826 100644 (file)
@@ -53,6 +53,7 @@
 #include <linux/slab.h>
 #include "md.h"
 #include "bitmap.h"
+#include "md-cluster.h"
 
 #ifndef MODULE
 static void autostart_arrays(int part);
@@ -66,6 +67,11 @@ static void autostart_arrays(int part);
 static LIST_HEAD(pers_list);
 static DEFINE_SPINLOCK(pers_lock);
 
+struct md_cluster_operations *md_cluster_ops;
+EXPORT_SYMBOL(md_cluster_ops);
+struct module *md_cluster_mod;
+EXPORT_SYMBOL(md_cluster_mod);
+
 static DECLARE_WAIT_QUEUE_HEAD(resync_wait);
 static struct workqueue_struct *md_wq;
 static struct workqueue_struct *md_misc_wq;
@@ -640,7 +646,7 @@ void mddev_unlock(struct mddev *mddev)
 }
 EXPORT_SYMBOL_GPL(mddev_unlock);
 
-static struct md_rdev *find_rdev_nr_rcu(struct mddev *mddev, int nr)
+struct md_rdev *md_find_rdev_nr_rcu(struct mddev *mddev, int nr)
 {
        struct md_rdev *rdev;
 
@@ -650,6 +656,7 @@ static struct md_rdev *find_rdev_nr_rcu(struct mddev *mddev, int nr)
 
        return NULL;
 }
+EXPORT_SYMBOL_GPL(md_find_rdev_nr_rcu);
 
 static struct md_rdev *find_rdev(struct mddev *mddev, dev_t dev)
 {
@@ -2047,11 +2054,11 @@ static int bind_rdev_to_array(struct md_rdev *rdev, struct mddev *mddev)
                int choice = 0;
                if (mddev->pers)
                        choice = mddev->raid_disks;
-               while (find_rdev_nr_rcu(mddev, choice))
+               while (md_find_rdev_nr_rcu(mddev, choice))
                        choice++;
                rdev->desc_nr = choice;
        } else {
-               if (find_rdev_nr_rcu(mddev, rdev->desc_nr)) {
+               if (md_find_rdev_nr_rcu(mddev, rdev->desc_nr)) {
                        rcu_read_unlock();
                        return -EBUSY;
                }
@@ -2166,11 +2173,12 @@ static void export_rdev(struct md_rdev *rdev)
        kobject_put(&rdev->kobj);
 }
 
-static void kick_rdev_from_array(struct md_rdev *rdev)
+void md_kick_rdev_from_array(struct md_rdev *rdev)
 {
        unbind_rdev_from_array(rdev);
        export_rdev(rdev);
 }
+EXPORT_SYMBOL_GPL(md_kick_rdev_from_array);
 
 static void export_array(struct mddev *mddev)
 {
@@ -2179,7 +2187,7 @@ static void export_array(struct mddev *mddev)
        while (!list_empty(&mddev->disks)) {
                rdev = list_first_entry(&mddev->disks, struct md_rdev,
                                        same_set);
-               kick_rdev_from_array(rdev);
+               md_kick_rdev_from_array(rdev);
        }
        mddev->raid_disks = 0;
        mddev->major_version = 0;
@@ -2208,7 +2216,7 @@ static void sync_sbs(struct mddev *mddev, int nospares)
        }
 }
 
-static void md_update_sb(struct mddev *mddev, int force_change)
+void md_update_sb(struct mddev *mddev, int force_change)
 {
        struct md_rdev *rdev;
        int sync_req;
@@ -2369,6 +2377,37 @@ repeat:
                wake_up(&rdev->blocked_wait);
        }
 }
+EXPORT_SYMBOL(md_update_sb);
+
+static int add_bound_rdev(struct md_rdev *rdev)
+{
+       struct mddev *mddev = rdev->mddev;
+       int err = 0;
+
+       if (!mddev->pers->hot_remove_disk) {
+               /* If there is hot_add_disk but no hot_remove_disk
+                * then added disks for geometry changes,
+                * and should be added immediately.
+                */
+               super_types[mddev->major_version].
+                       validate_super(mddev, rdev);
+               err = mddev->pers->hot_add_disk(mddev, rdev);
+               if (err) {
+                       unbind_rdev_from_array(rdev);
+                       export_rdev(rdev);
+                       return err;
+               }
+       }
+       sysfs_notify_dirent_safe(rdev->sysfs_state);
+
+       set_bit(MD_CHANGE_DEVS, &mddev->flags);
+       if (mddev->degraded)
+               set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
+       set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+       md_new_event(mddev);
+       md_wakeup_thread(mddev->thread);
+       return 0;
+}
 
 /* words written to sysfs files may, or may not, be \n terminated.
  * We want to accept with case. For this we use cmd_match.
@@ -2471,10 +2510,16 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len)
                        err = -EBUSY;
                else {
                        struct mddev *mddev = rdev->mddev;
-                       kick_rdev_from_array(rdev);
+                       if (mddev_is_clustered(mddev))
+                               md_cluster_ops->remove_disk(mddev, rdev);
+                       md_kick_rdev_from_array(rdev);
+                       if (mddev_is_clustered(mddev))
+                               md_cluster_ops->metadata_update_start(mddev);
                        if (mddev->pers)
                                md_update_sb(mddev, 1);
                        md_new_event(mddev);
+                       if (mddev_is_clustered(mddev))
+                               md_cluster_ops->metadata_update_finish(mddev);
                        err = 0;
                }
        } else if (cmd_match(buf, "writemostly")) {
@@ -2553,6 +2598,21 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len)
                        clear_bit(Replacement, &rdev->flags);
                        err = 0;
                }
+       } else if (cmd_match(buf, "re-add")) {
+               if (test_bit(Faulty, &rdev->flags) && (rdev->raid_disk == -1)) {
+                       /* clear_bit is performed _after_ all the devices
+                        * have their local Faulty bit cleared. If any writes
+                        * happen in the meantime in the local node, they
+                        * will land in the local bitmap, which will be synced
+                        * by this node eventually
+                        */
+                       if (!mddev_is_clustered(rdev->mddev) ||
+                           (err = md_cluster_ops->gather_bitmaps(rdev)) == 0) {
+                               clear_bit(Faulty, &rdev->flags);
+                               err = add_bound_rdev(rdev);
+                       }
+               } else
+                       err = -EBUSY;
        }
        if (!err)
                sysfs_notify_dirent_safe(rdev->sysfs_state);
@@ -3127,7 +3187,7 @@ static void analyze_sbs(struct mddev *mddev)
                                "md: fatal superblock inconsistency in %s"
                                " -- removing from array\n",
                                bdevname(rdev->bdev,b));
-                       kick_rdev_from_array(rdev);
+                       md_kick_rdev_from_array(rdev);
                }
 
        super_types[mddev->major_version].
@@ -3142,18 +3202,27 @@ static void analyze_sbs(struct mddev *mddev)
                               "md: %s: %s: only %d devices permitted\n",
                               mdname(mddev), bdevname(rdev->bdev, b),
                               mddev->max_disks);
-                       kick_rdev_from_array(rdev);
+                       md_kick_rdev_from_array(rdev);
                        continue;
                }
-               if (rdev != freshest)
+               if (rdev != freshest) {
                        if (super_types[mddev->major_version].
                            validate_super(mddev, rdev)) {
                                printk(KERN_WARNING "md: kicking non-fresh %s"
                                        " from array!\n",
                                        bdevname(rdev->bdev,b));
-                               kick_rdev_from_array(rdev);
+                               md_kick_rdev_from_array(rdev);
                                continue;
                        }
+                       /* No device should have a Candidate flag
+                        * when reading devices
+                        */
+                       if (test_bit(Candidate, &rdev->flags)) {
+                               pr_info("md: kicking Cluster Candidate %s from array!\n",
+                                       bdevname(rdev->bdev, b));
+                               md_kick_rdev_from_array(rdev);
+                       }
+               }
                if (mddev->level == LEVEL_MULTIPATH) {
                        rdev->desc_nr = i++;
                        rdev->raid_disk = rdev->desc_nr;
@@ -4008,8 +4077,12 @@ size_store(struct mddev *mddev, const char *buf, size_t len)
        if (err)
                return err;
        if (mddev->pers) {
+               if (mddev_is_clustered(mddev))
+                       md_cluster_ops->metadata_update_start(mddev);
                err = update_size(mddev, sectors);
                md_update_sb(mddev, 1);
+               if (mddev_is_clustered(mddev))
+                       md_cluster_ops->metadata_update_finish(mddev);
        } else {
                if (mddev->dev_sectors == 0 ||
                    mddev->dev_sectors > sectors)
@@ -4354,7 +4427,6 @@ min_sync_store(struct mddev *mddev, const char *buf, size_t len)
 {
        unsigned long long min;
        int err;
-       int chunk;
 
        if (kstrtoull(buf, 10, &min))
                return -EINVAL;
@@ -4368,16 +4440,8 @@ min_sync_store(struct mddev *mddev, const char *buf, size_t len)
        if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
                goto out_unlock;
 
-       /* Must be a multiple of chunk_size */
-       chunk = mddev->chunk_sectors;
-       if (chunk) {
-               sector_t temp = min;
-
-               err = -EINVAL;
-               if (sector_div(temp, chunk))
-                       goto out_unlock;
-       }
-       mddev->resync_min = min;
+       /* Round down to multiple of 4K for safety */
+       mddev->resync_min = round_down(min, 8);
        err = 0;
 
 out_unlock:
@@ -5077,10 +5141,16 @@ int md_run(struct mddev *mddev)
        }
        if (err == 0 && pers->sync_request &&
            (mddev->bitmap_info.file || mddev->bitmap_info.offset)) {
-               err = bitmap_create(mddev);
-               if (err)
+               struct bitmap *bitmap;
+
+               bitmap = bitmap_create(mddev, -1);
+               if (IS_ERR(bitmap)) {
+                       err = PTR_ERR(bitmap);
                        printk(KERN_ERR "%s: failed to create bitmap (%d)\n",
                               mdname(mddev), err);
+               } else
+                       mddev->bitmap = bitmap;
+
        }
        if (err) {
                mddev_detach(mddev);
@@ -5232,6 +5302,8 @@ static void md_clean(struct mddev *mddev)
 
 static void __md_stop_writes(struct mddev *mddev)
 {
+       if (mddev_is_clustered(mddev))
+               md_cluster_ops->metadata_update_start(mddev);
        set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
        flush_workqueue(md_misc_wq);
        if (mddev->sync_thread) {
@@ -5250,6 +5322,8 @@ static void __md_stop_writes(struct mddev *mddev)
                mddev->in_sync = 1;
                md_update_sb(mddev, 1);
        }
+       if (mddev_is_clustered(mddev))
+               md_cluster_ops->metadata_update_finish(mddev);
 }
 
 void md_stop_writes(struct mddev *mddev)
@@ -5636,6 +5710,8 @@ static int get_array_info(struct mddev *mddev, void __user *arg)
                info.state = (1<<MD_SB_CLEAN);
        if (mddev->bitmap && mddev->bitmap_info.offset)
                info.state |= (1<<MD_SB_BITMAP_PRESENT);
+       if (mddev_is_clustered(mddev))
+               info.state |= (1<<MD_SB_CLUSTERED);
        info.active_disks  = insync;
        info.working_disks = working;
        info.failed_disks  = failed;
@@ -5691,7 +5767,7 @@ static int get_disk_info(struct mddev *mddev, void __user * arg)
                return -EFAULT;
 
        rcu_read_lock();
-       rdev = find_rdev_nr_rcu(mddev, info.number);
+       rdev = md_find_rdev_nr_rcu(mddev, info.number);
        if (rdev) {
                info.major = MAJOR(rdev->bdev->bd_dev);
                info.minor = MINOR(rdev->bdev->bd_dev);
@@ -5724,6 +5800,13 @@ static int add_new_disk(struct mddev *mddev, mdu_disk_info_t *info)
        struct md_rdev *rdev;
        dev_t dev = MKDEV(info->major,info->minor);
 
+       if (mddev_is_clustered(mddev) &&
+               !(info->state & ((1 << MD_DISK_CLUSTER_ADD) | (1 << MD_DISK_CANDIDATE)))) {
+               pr_err("%s: Cannot add to clustered mddev.\n",
+                              mdname(mddev));
+               return -EINVAL;
+       }
+
        if (info->major != MAJOR(dev) || info->minor != MINOR(dev))
                return -EOVERFLOW;
 
@@ -5810,31 +5893,38 @@ static int add_new_disk(struct mddev *mddev, mdu_disk_info_t *info)
                else
                        clear_bit(WriteMostly, &rdev->flags);
 
+               /*
+                * check whether the device shows up in other nodes
+                */
+               if (mddev_is_clustered(mddev)) {
+                       if (info->state & (1 << MD_DISK_CANDIDATE)) {
+                               /* Through --cluster-confirm */
+                               set_bit(Candidate, &rdev->flags);
+                               err = md_cluster_ops->new_disk_ack(mddev, true);
+                               if (err) {
+                                       export_rdev(rdev);
+                                       return err;
+                               }
+                       } else if (info->state & (1 << MD_DISK_CLUSTER_ADD)) {
+                               /* --add initiated by this node */
+                               err = md_cluster_ops->add_new_disk_start(mddev, rdev);
+                               if (err) {
+                                       md_cluster_ops->add_new_disk_finish(mddev);
+                                       export_rdev(rdev);
+                                       return err;
+                               }
+                       }
+               }
+
                rdev->raid_disk = -1;
                err = bind_rdev_to_array(rdev, mddev);
-               if (!err && !mddev->pers->hot_remove_disk) {
-                       /* If there is hot_add_disk but no hot_remove_disk
-                        * then added disks for geometry changes,
-                        * and should be added immediately.
-                        */
-                       super_types[mddev->major_version].
-                               validate_super(mddev, rdev);
-                       err = mddev->pers->hot_add_disk(mddev, rdev);
-                       if (err)
-                               unbind_rdev_from_array(rdev);
-               }
                if (err)
                        export_rdev(rdev);
                else
-                       sysfs_notify_dirent_safe(rdev->sysfs_state);
-
-               set_bit(MD_CHANGE_DEVS, &mddev->flags);
-               if (mddev->degraded)
-                       set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
-               set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
-               if (!err)
-                       md_new_event(mddev);
-               md_wakeup_thread(mddev->thread);
+                       err = add_bound_rdev(rdev);
+               if (mddev_is_clustered(mddev) &&
+                               (info->state & (1 << MD_DISK_CLUSTER_ADD)))
+                       md_cluster_ops->add_new_disk_finish(mddev);
                return err;
        }
 
@@ -5895,18 +5985,29 @@ static int hot_remove_disk(struct mddev *mddev, dev_t dev)
        if (!rdev)
                return -ENXIO;
 
+       if (mddev_is_clustered(mddev))
+               md_cluster_ops->metadata_update_start(mddev);
+
        clear_bit(Blocked, &rdev->flags);
        remove_and_add_spares(mddev, rdev);
 
        if (rdev->raid_disk >= 0)
                goto busy;
 
-       kick_rdev_from_array(rdev);
+       if (mddev_is_clustered(mddev))
+               md_cluster_ops->remove_disk(mddev, rdev);
+
+       md_kick_rdev_from_array(rdev);
        md_update_sb(mddev, 1);
        md_new_event(mddev);
 
+       if (mddev_is_clustered(mddev))
+               md_cluster_ops->metadata_update_finish(mddev);
+
        return 0;
 busy:
+       if (mddev_is_clustered(mddev))
+               md_cluster_ops->metadata_update_cancel(mddev);
        printk(KERN_WARNING "md: cannot remove active disk %s from %s ...\n",
                bdevname(rdev->bdev,b), mdname(mddev));
        return -EBUSY;
@@ -5956,12 +6057,15 @@ static int hot_add_disk(struct mddev *mddev, dev_t dev)
                err = -EINVAL;
                goto abort_export;
        }
+
+       if (mddev_is_clustered(mddev))
+               md_cluster_ops->metadata_update_start(mddev);
        clear_bit(In_sync, &rdev->flags);
        rdev->desc_nr = -1;
        rdev->saved_raid_disk = -1;
        err = bind_rdev_to_array(rdev, mddev);
        if (err)
-               goto abort_export;
+               goto abort_clustered;
 
        /*
         * The rest should better be atomic, we can have disk failures
@@ -5972,6 +6076,8 @@ static int hot_add_disk(struct mddev *mddev, dev_t dev)
 
        md_update_sb(mddev, 1);
 
+       if (mddev_is_clustered(mddev))
+               md_cluster_ops->metadata_update_finish(mddev);
        /*
         * Kick recovery, maybe this spare has to be added to the
         * array immediately.
@@ -5981,6 +6087,9 @@ static int hot_add_disk(struct mddev *mddev, dev_t dev)
        md_new_event(mddev);
        return 0;
 
+abort_clustered:
+       if (mddev_is_clustered(mddev))
+               md_cluster_ops->metadata_update_cancel(mddev);
 abort_export:
        export_rdev(rdev);
        return err;
@@ -6038,9 +6147,14 @@ static int set_bitmap_file(struct mddev *mddev, int fd)
        if (mddev->pers) {
                mddev->pers->quiesce(mddev, 1);
                if (fd >= 0) {
-                       err = bitmap_create(mddev);
-                       if (!err)
+                       struct bitmap *bitmap;
+
+                       bitmap = bitmap_create(mddev, -1);
+                       if (!IS_ERR(bitmap)) {
+                               mddev->bitmap = bitmap;
                                err = bitmap_load(mddev);
+                       } else
+                               err = PTR_ERR(bitmap);
                }
                if (fd < 0 || err) {
                        bitmap_destroy(mddev);
@@ -6293,6 +6407,8 @@ static int update_array_info(struct mddev *mddev, mdu_array_info_t *info)
                        return rv;
                }
        }
+       if (mddev_is_clustered(mddev))
+               md_cluster_ops->metadata_update_start(mddev);
        if (info->size >= 0 && mddev->dev_sectors / 2 != info->size)
                rv = update_size(mddev, (sector_t)info->size * 2);
 
@@ -6300,33 +6416,49 @@ static int update_array_info(struct mddev *mddev, mdu_array_info_t *info)
                rv = update_raid_disks(mddev, info->raid_disks);
 
        if ((state ^ info->state) & (1<<MD_SB_BITMAP_PRESENT)) {
-               if (mddev->pers->quiesce == NULL || mddev->thread == NULL)
-                       return -EINVAL;
-               if (mddev->recovery || mddev->sync_thread)
-                       return -EBUSY;
+               if (mddev->pers->quiesce == NULL || mddev->thread == NULL) {
+                       rv = -EINVAL;
+                       goto err;
+               }
+               if (mddev->recovery || mddev->sync_thread) {
+                       rv = -EBUSY;
+                       goto err;
+               }
                if (info->state & (1<<MD_SB_BITMAP_PRESENT)) {
+                       struct bitmap *bitmap;
                        /* add the bitmap */
-                       if (mddev->bitmap)
-                               return -EEXIST;
-                       if (mddev->bitmap_info.default_offset == 0)
-                               return -EINVAL;
+                       if (mddev->bitmap) {
+                               rv = -EEXIST;
+                               goto err;
+                       }
+                       if (mddev->bitmap_info.default_offset == 0) {
+                               rv = -EINVAL;
+                               goto err;
+                       }
                        mddev->bitmap_info.offset =
                                mddev->bitmap_info.default_offset;
                        mddev->bitmap_info.space =
                                mddev->bitmap_info.default_space;
                        mddev->pers->quiesce(mddev, 1);
-                       rv = bitmap_create(mddev);
-                       if (!rv)
+                       bitmap = bitmap_create(mddev, -1);
+                       if (!IS_ERR(bitmap)) {
+                               mddev->bitmap = bitmap;
                                rv = bitmap_load(mddev);
+                       } else
+                               rv = PTR_ERR(bitmap);
                        if (rv)
                                bitmap_destroy(mddev);
                        mddev->pers->quiesce(mddev, 0);
                } else {
                        /* remove the bitmap */
-                       if (!mddev->bitmap)
-                               return -ENOENT;
-                       if (mddev->bitmap->storage.file)
-                               return -EINVAL;
+                       if (!mddev->bitmap) {
+                               rv = -ENOENT;
+                               goto err;
+                       }
+                       if (mddev->bitmap->storage.file) {
+                               rv = -EINVAL;
+                               goto err;
+                       }
                        mddev->pers->quiesce(mddev, 1);
                        bitmap_destroy(mddev);
                        mddev->pers->quiesce(mddev, 0);
@@ -6334,6 +6466,12 @@ static int update_array_info(struct mddev *mddev, mdu_array_info_t *info)
                }
        }
        md_update_sb(mddev, 1);
+       if (mddev_is_clustered(mddev))
+               md_cluster_ops->metadata_update_finish(mddev);
+       return rv;
+err:
+       if (mddev_is_clustered(mddev))
+               md_cluster_ops->metadata_update_cancel(mddev);
        return rv;
 }
 
@@ -6393,6 +6531,7 @@ static inline bool md_ioctl_valid(unsigned int cmd)
        case SET_DISK_FAULTY:
        case STOP_ARRAY:
        case STOP_ARRAY_RO:
+       case CLUSTERED_DISK_NACK:
                return true;
        default:
                return false;
@@ -6665,6 +6804,13 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
                goto unlock;
        }
 
+       case CLUSTERED_DISK_NACK:
+               if (mddev_is_clustered(mddev))
+                       md_cluster_ops->new_disk_ack(mddev, false);
+               else
+                       err = -EINVAL;
+               goto unlock;
+
        case HOT_ADD_DISK:
                err = hot_add_disk(mddev, new_decode_dev(arg));
                goto unlock;
@@ -7238,6 +7384,55 @@ int unregister_md_personality(struct md_personality *p)
 }
 EXPORT_SYMBOL(unregister_md_personality);
 
+int register_md_cluster_operations(struct md_cluster_operations *ops, struct module *module)
+{
+       if (md_cluster_ops != NULL)
+               return -EALREADY;
+       spin_lock(&pers_lock);
+       md_cluster_ops = ops;
+       md_cluster_mod = module;
+       spin_unlock(&pers_lock);
+       return 0;
+}
+EXPORT_SYMBOL(register_md_cluster_operations);
+
+int unregister_md_cluster_operations(void)
+{
+       spin_lock(&pers_lock);
+       md_cluster_ops = NULL;
+       spin_unlock(&pers_lock);
+       return 0;
+}
+EXPORT_SYMBOL(unregister_md_cluster_operations);
+
+int md_setup_cluster(struct mddev *mddev, int nodes)
+{
+       int err;
+
+       err = request_module("md-cluster");
+       if (err) {
+               pr_err("md-cluster module not found.\n");
+               return err;
+       }
+
+       spin_lock(&pers_lock);
+       if (!md_cluster_ops || !try_module_get(md_cluster_mod)) {
+               spin_unlock(&pers_lock);
+               return -ENOENT;
+       }
+       spin_unlock(&pers_lock);
+
+       return md_cluster_ops->join(mddev, nodes);
+}
+
+void md_cluster_stop(struct mddev *mddev)
+{
+       if (!md_cluster_ops)
+               return;
+       md_cluster_ops->leave(mddev);
+       module_put(md_cluster_mod);
+}
+
 static int is_mddev_idle(struct mddev *mddev, int init)
 {
        struct md_rdev *rdev;
@@ -7375,7 +7570,11 @@ int md_allow_write(struct mddev *mddev)
                    mddev->safemode == 0)
                        mddev->safemode = 1;
                spin_unlock(&mddev->lock);
+               if (mddev_is_clustered(mddev))
+                       md_cluster_ops->metadata_update_start(mddev);
                md_update_sb(mddev, 0);
+               if (mddev_is_clustered(mddev))
+                       md_cluster_ops->metadata_update_finish(mddev);
                sysfs_notify_dirent_safe(mddev->sysfs_state);
        } else
                spin_unlock(&mddev->lock);
@@ -7576,6 +7775,9 @@ void md_do_sync(struct md_thread *thread)
        md_new_event(mddev);
        update_time = jiffies;
 
+       if (mddev_is_clustered(mddev))
+               md_cluster_ops->resync_start(mddev, j, max_sectors);
+
        blk_start_plug(&plug);
        while (j < max_sectors) {
                sector_t sectors;
@@ -7618,8 +7820,7 @@ void md_do_sync(struct md_thread *thread)
                if (test_bit(MD_RECOVERY_INTR, &mddev->recovery))
                        break;
 
-               sectors = mddev->pers->sync_request(mddev, j, &skipped,
-                                                 currspeed < speed_min(mddev));
+               sectors = mddev->pers->sync_request(mddev, j, &skipped);
                if (sectors == 0) {
                        set_bit(MD_RECOVERY_INTR, &mddev->recovery);
                        break;
@@ -7636,6 +7837,8 @@ void md_do_sync(struct md_thread *thread)
                j += sectors;
                if (j > 2)
                        mddev->curr_resync = j;
+               if (mddev_is_clustered(mddev))
+                       md_cluster_ops->resync_info_update(mddev, j, max_sectors);
                mddev->curr_mark_cnt = io_sectors;
                if (last_check == 0)
                        /* this is the earliest that rebuild will be
@@ -7677,11 +7880,18 @@ void md_do_sync(struct md_thread *thread)
                        /((jiffies-mddev->resync_mark)/HZ +1) +1;
 
                if (currspeed > speed_min(mddev)) {
-                       if ((currspeed > speed_max(mddev)) ||
-                                       !is_mddev_idle(mddev, 0)) {
+                       if (currspeed > speed_max(mddev)) {
                                msleep(500);
                                goto repeat;
                        }
+                       if (!is_mddev_idle(mddev, 0)) {
+                               /*
+                                * Give other IO more of a chance.
+                                * The faster the devices, the less we wait.
+                                */
+                               wait_event(mddev->recovery_wait,
+                                          !atomic_read(&mddev->recovery_active));
+                       }
                }
        }
        printk(KERN_INFO "md: %s: %s %s.\n",mdname(mddev), desc,
@@ -7694,7 +7904,10 @@ void md_do_sync(struct md_thread *thread)
        wait_event(mddev->recovery_wait, !atomic_read(&mddev->recovery_active));
 
        /* tell personality that we are finished */
-       mddev->pers->sync_request(mddev, max_sectors, &skipped, 1);
+       mddev->pers->sync_request(mddev, max_sectors, &skipped);
+
+       if (mddev_is_clustered(mddev))
+               md_cluster_ops->resync_finish(mddev);
 
        if (!test_bit(MD_RECOVERY_CHECK, &mddev->recovery) &&
            mddev->curr_resync > 2) {
@@ -7925,8 +8138,13 @@ void md_check_recovery(struct mddev *mddev)
                                sysfs_notify_dirent_safe(mddev->sysfs_state);
                }
 
-               if (mddev->flags & MD_UPDATE_SB_FLAGS)
+               if (mddev->flags & MD_UPDATE_SB_FLAGS) {
+                       if (mddev_is_clustered(mddev))
+                               md_cluster_ops->metadata_update_start(mddev);
                        md_update_sb(mddev, 0);
+                       if (mddev_is_clustered(mddev))
+                               md_cluster_ops->metadata_update_finish(mddev);
+               }
 
                if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) &&
                    !test_bit(MD_RECOVERY_DONE, &mddev->recovery)) {
@@ -8024,6 +8242,8 @@ void md_reap_sync_thread(struct mddev *mddev)
                        set_bit(MD_CHANGE_DEVS, &mddev->flags);
                }
        }
+       if (mddev_is_clustered(mddev))
+               md_cluster_ops->metadata_update_start(mddev);
        if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
            mddev->pers->finish_reshape)
                mddev->pers->finish_reshape(mddev);
@@ -8036,6 +8256,8 @@ void md_reap_sync_thread(struct mddev *mddev)
                        rdev->saved_raid_disk = -1;
 
        md_update_sb(mddev, 1);
+       if (mddev_is_clustered(mddev))
+               md_cluster_ops->metadata_update_finish(mddev);
        clear_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
        clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
        clear_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
@@ -8656,6 +8878,28 @@ err_wq:
        return ret;
 }
 
+void md_reload_sb(struct mddev *mddev)
+{
+       struct md_rdev *rdev, *tmp;
+
+       rdev_for_each_safe(rdev, tmp, mddev) {
+               rdev->sb_loaded = 0;
+               ClearPageUptodate(rdev->sb_page);
+       }
+       mddev->raid_disks = 0;
+       analyze_sbs(mddev);
+       rdev_for_each_safe(rdev, tmp, mddev) {
+               struct mdp_superblock_1 *sb = page_address(rdev->sb_page);
+               /* since we don't write to faulty devices, we figure out if the
+                *  disk is faulty by comparing events
+                */
+               if (mddev->events > sb->events)
+                       set_bit(Faulty, &rdev->flags);
+       }
+
+}
+EXPORT_SYMBOL(md_reload_sb);
+
 #ifndef MODULE
 
 /*
index 318ca8fd430f1f9cd422d84cde77ac6a1fff435a..4046a6c6f223b0b4a923404c52c582308843b887 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/timer.h>
 #include <linux/wait.h>
 #include <linux/workqueue.h>
+#include "md-cluster.h"
 
 #define MaxSector (~(sector_t)0)
 
@@ -170,6 +171,10 @@ enum flag_bits {
                                 * a want_replacement device with same
                                 * raid_disk number.
                                 */
+       Candidate,              /* For clustered environments only:
+                                * This device is seen locally but not
+                                * by the whole cluster
+                                */
 };
 
 #define BB_LEN_MASK    (0x00000000000001FFULL)
@@ -202,6 +207,8 @@ extern int rdev_clear_badblocks(struct md_rdev *rdev, sector_t s, int sectors,
                                int is_new);
 extern void md_ack_all_badblocks(struct badblocks *bb);
 
+struct md_cluster_info;
+
 struct mddev {
        void                            *private;
        struct md_personality           *pers;
@@ -430,6 +437,8 @@ struct mddev {
                unsigned long           daemon_sleep; /* how many jiffies between updates? */
                unsigned long           max_write_behind; /* write-behind mode */
                int                     external;
+               int                     nodes; /* Maximum number of nodes in the cluster */
+               char                    cluster_name[64]; /* Name of the cluster */
        } bitmap_info;
 
        atomic_t                        max_corr_read_errors; /* max read retries */
@@ -448,6 +457,7 @@ struct mddev {
        struct work_struct flush_work;
        struct work_struct event_work;  /* used by dm to report failure event */
        void (*sync_super)(struct mddev *mddev, struct md_rdev *rdev);
+       struct md_cluster_info          *cluster_info;
 };
 
 static inline int __must_check mddev_lock(struct mddev *mddev)
@@ -496,7 +506,7 @@ struct md_personality
        int (*hot_add_disk) (struct mddev *mddev, struct md_rdev *rdev);
        int (*hot_remove_disk) (struct mddev *mddev, struct md_rdev *rdev);
        int (*spare_active) (struct mddev *mddev);
-       sector_t (*sync_request)(struct mddev *mddev, sector_t sector_nr, int *skipped, int go_faster);
+       sector_t (*sync_request)(struct mddev *mddev, sector_t sector_nr, int *skipped);
        int (*resize) (struct mddev *mddev, sector_t sectors);
        sector_t (*size) (struct mddev *mddev, sector_t sectors, int raid_disks);
        int (*check_reshape) (struct mddev *mddev);
@@ -608,6 +618,11 @@ static inline void safe_put_page(struct page *p)
 
 extern int register_md_personality(struct md_personality *p);
 extern int unregister_md_personality(struct md_personality *p);
+extern int register_md_cluster_operations(struct md_cluster_operations *ops,
+               struct module *module);
+extern int unregister_md_cluster_operations(void);
+extern int md_setup_cluster(struct mddev *mddev, int nodes);
+extern void md_cluster_stop(struct mddev *mddev);
 extern struct md_thread *md_register_thread(
        void (*run)(struct md_thread *thread),
        struct mddev *mddev,
@@ -654,6 +669,10 @@ extern struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs,
                                   struct mddev *mddev);
 
 extern void md_unplug(struct blk_plug_cb *cb, bool from_schedule);
+extern void md_reload_sb(struct mddev *mddev);
+extern void md_update_sb(struct mddev *mddev, int force);
+extern void md_kick_rdev_from_array(struct md_rdev * rdev);
+struct md_rdev *md_find_rdev_nr_rcu(struct mddev *mddev, int nr);
 static inline int mddev_check_plugged(struct mddev *mddev)
 {
        return !!blk_check_plugged(md_unplug, mddev,
@@ -669,4 +688,9 @@ static inline void rdev_dec_pending(struct md_rdev *rdev, struct mddev *mddev)
        }
 }
 
+extern struct md_cluster_operations *md_cluster_ops;
+static inline int mddev_is_clustered(struct mddev *mddev)
+{
+       return mddev->cluster_info && mddev->bitmap_info.nodes > 1;
+}
 #endif /* _MD_MD_H */
index 3b5d7f704aa346ad27b4806c9e36ee9ba984edc7..2cb59a641cd24417d996df89c2e2c81cc9eb087b 100644 (file)
@@ -271,14 +271,16 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf)
                goto abort;
        }
 
-       blk_queue_io_min(mddev->queue, mddev->chunk_sectors << 9);
-       blk_queue_io_opt(mddev->queue,
-                        (mddev->chunk_sectors << 9) * mddev->raid_disks);
-
-       if (!discard_supported)
-               queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
-       else
-               queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
+       if (mddev->queue) {
+               blk_queue_io_min(mddev->queue, mddev->chunk_sectors << 9);
+               blk_queue_io_opt(mddev->queue,
+                                (mddev->chunk_sectors << 9) * mddev->raid_disks);
+
+               if (!discard_supported)
+                       queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
+               else
+                       queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
+       }
 
        pr_debug("md/raid0:%s: done.\n", mdname(mddev));
        *private_conf = conf;
@@ -429,9 +431,12 @@ static int raid0_run(struct mddev *mddev)
        }
        if (md_check_no_bitmap(mddev))
                return -EINVAL;
-       blk_queue_max_hw_sectors(mddev->queue, mddev->chunk_sectors);
-       blk_queue_max_write_same_sectors(mddev->queue, mddev->chunk_sectors);
-       blk_queue_max_discard_sectors(mddev->queue, mddev->chunk_sectors);
+
+       if (mddev->queue) {
+               blk_queue_max_hw_sectors(mddev->queue, mddev->chunk_sectors);
+               blk_queue_max_write_same_sectors(mddev->queue, mddev->chunk_sectors);
+               blk_queue_max_discard_sectors(mddev->queue, mddev->chunk_sectors);
+       }
 
        /* if private is not null, we are here after takeover */
        if (mddev->private == NULL) {
@@ -448,16 +453,17 @@ static int raid0_run(struct mddev *mddev)
        printk(KERN_INFO "md/raid0:%s: md_size is %llu sectors.\n",
               mdname(mddev),
               (unsigned long long)mddev->array_sectors);
-       /* calculate the max read-ahead size.
-        * For read-ahead of large files to be effective, we need to
-        * readahead at least twice a whole stripe. i.e. number of devices
-        * multiplied by chunk size times 2.
-        * If an individual device has an ra_pages greater than the
-        * chunk size, then we will not drive that device as hard as it
-        * wants.  We consider this a configuration error: a larger
-        * chunksize should be used in that case.
-        */
-       {
+
+       if (mddev->queue) {
+               /* calculate the max read-ahead size.
+                * For read-ahead of large files to be effective, we need to
+                * readahead at least twice a whole stripe. i.e. number of devices
+                * multiplied by chunk size times 2.
+                * If an individual device has an ra_pages greater than the
+                * chunk size, then we will not drive that device as hard as it
+                * wants.  We consider this a configuration error: a larger
+                * chunksize should be used in that case.
+                */
                int stripe = mddev->raid_disks *
                        (mddev->chunk_sectors << 9) / PAGE_SIZE;
                if (mddev->queue->backing_dev_info.ra_pages < 2* stripe)
index d34e238afa54c24ccaefbc7c6d58974dc2104be6..9157a29c8dbf133c713d67bdaaea45aaf650a255 100644 (file)
@@ -539,7 +539,13 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect
        has_nonrot_disk = 0;
        choose_next_idle = 0;
 
-       choose_first = (conf->mddev->recovery_cp < this_sector + sectors);
+       if ((conf->mddev->recovery_cp < this_sector + sectors) ||
+           (mddev_is_clustered(conf->mddev) &&
+           md_cluster_ops->area_resyncing(conf->mddev, this_sector,
+                   this_sector + sectors)))
+               choose_first = 1;
+       else
+               choose_first = 0;
 
        for (disk = 0 ; disk < conf->raid_disks * 2 ; disk++) {
                sector_t dist;
@@ -1102,8 +1108,10 @@ static void make_request(struct mddev *mddev, struct bio * bio)
        md_write_start(mddev, bio); /* wait on superblock update early */
 
        if (bio_data_dir(bio) == WRITE &&
-           bio_end_sector(bio) > mddev->suspend_lo &&
-           bio->bi_iter.bi_sector < mddev->suspend_hi) {
+           ((bio_end_sector(bio) > mddev->suspend_lo &&
+           bio->bi_iter.bi_sector < mddev->suspend_hi) ||
+           (mddev_is_clustered(mddev) &&
+            md_cluster_ops->area_resyncing(mddev, bio->bi_iter.bi_sector, bio_end_sector(bio))))) {
                /* As the suspend_* range is controlled by
                 * userspace, we want an interruptible
                 * wait.
@@ -1114,7 +1122,10 @@ static void make_request(struct mddev *mddev, struct bio * bio)
                        prepare_to_wait(&conf->wait_barrier,
                                        &w, TASK_INTERRUPTIBLE);
                        if (bio_end_sector(bio) <= mddev->suspend_lo ||
-                           bio->bi_iter.bi_sector >= mddev->suspend_hi)
+                           bio->bi_iter.bi_sector >= mddev->suspend_hi ||
+                           (mddev_is_clustered(mddev) &&
+                            !md_cluster_ops->area_resyncing(mddev,
+                                    bio->bi_iter.bi_sector, bio_end_sector(bio))))
                                break;
                        schedule();
                }
@@ -1561,6 +1572,7 @@ static int raid1_spare_active(struct mddev *mddev)
                struct md_rdev *rdev = conf->mirrors[i].rdev;
                struct md_rdev *repl = conf->mirrors[conf->raid_disks + i].rdev;
                if (repl
+                   && !test_bit(Candidate, &repl->flags)
                    && repl->recovery_offset == MaxSector
                    && !test_bit(Faulty, &repl->flags)
                    && !test_and_set_bit(In_sync, &repl->flags)) {
@@ -2468,7 +2480,7 @@ static int init_resync(struct r1conf *conf)
  * that can be installed to exclude normal IO requests.
  */
 
-static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipped, int go_faster)
+static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipped)
 {
        struct r1conf *conf = mddev->private;
        struct r1bio *r1_bio;
@@ -2521,13 +2533,6 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipp
                *skipped = 1;
                return sync_blocks;
        }
-       /*
-        * If there is non-resync activity waiting for a turn,
-        * and resync is going fast enough,
-        * then let it though before starting on this new sync request.
-        */
-       if (!go_faster && conf->nr_waiting)
-               msleep_interruptible(1000);
 
        bitmap_cond_end_sync(mddev->bitmap, sector_nr);
        r1_bio = mempool_alloc(conf->r1buf_pool, GFP_NOIO);
index a7196c49d15d5265df304ac6c2591ff8e1d1a5f3..e793ab6b35705e0ed1ad6904ebe9353b6dbf6fd6 100644 (file)
@@ -2889,7 +2889,7 @@ static int init_resync(struct r10conf *conf)
  */
 
 static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
-                            int *skipped, int go_faster)
+                            int *skipped)
 {
        struct r10conf *conf = mddev->private;
        struct r10bio *r10_bio;
@@ -2994,12 +2994,6 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
        if (conf->geo.near_copies < conf->geo.raid_disks &&
            max_sector > (sector_nr | chunk_mask))
                max_sector = (sector_nr | chunk_mask) + 1;
-       /*
-        * If there is non-resync activity waiting for us then
-        * put in a delay to throttle resync.
-        */
-       if (!go_faster && conf->nr_waiting)
-               msleep_interruptible(1000);
 
        /* Again, very different code for resync and recovery.
         * Both must result in an r10bio with a list of bios that
index cd2f96b2c57263628ef0816af3b114ad9437b740..77dfd720aaa00ebc55d14234cd40b6e9b65bae5f 100644 (file)
@@ -54,6 +54,7 @@
 #include <linux/slab.h>
 #include <linux/ratelimit.h>
 #include <linux/nodemask.h>
+#include <linux/flex_array.h>
 #include <trace/events/block.h>
 
 #include "md.h"
@@ -496,7 +497,7 @@ static void shrink_buffers(struct stripe_head *sh)
        }
 }
 
-static int grow_buffers(struct stripe_head *sh)
+static int grow_buffers(struct stripe_head *sh, gfp_t gfp)
 {
        int i;
        int num = sh->raid_conf->pool_size;
@@ -504,7 +505,7 @@ static int grow_buffers(struct stripe_head *sh)
        for (i = 0; i < num; i++) {
                struct page *page;
 
-               if (!(page = alloc_page(GFP_KERNEL))) {
+               if (!(page = alloc_page(gfp))) {
                        return 1;
                }
                sh->dev[i].page = page;
@@ -525,6 +526,7 @@ static void init_stripe(struct stripe_head *sh, sector_t sector, int previous)
        BUG_ON(atomic_read(&sh->count) != 0);
        BUG_ON(test_bit(STRIPE_HANDLE, &sh->state));
        BUG_ON(stripe_operations_active(sh));
+       BUG_ON(sh->batch_head);
 
        pr_debug("init_stripe called, stripe %llu\n",
                (unsigned long long)sector);
@@ -552,8 +554,10 @@ retry:
        }
        if (read_seqcount_retry(&conf->gen_lock, seq))
                goto retry;
+       sh->overwrite_disks = 0;
        insert_hash(conf, sh);
        sh->cpu = smp_processor_id();
+       set_bit(STRIPE_BATCH_READY, &sh->state);
 }
 
 static struct stripe_head *__find_stripe(struct r5conf *conf, sector_t sector,
@@ -668,20 +672,28 @@ get_active_stripe(struct r5conf *conf, sector_t sector,
                                    *(conf->hash_locks + hash));
                sh = __find_stripe(conf, sector, conf->generation - previous);
                if (!sh) {
-                       if (!conf->inactive_blocked)
+                       if (!test_bit(R5_INACTIVE_BLOCKED, &conf->cache_state)) {
                                sh = get_free_stripe(conf, hash);
+                               if (!sh && llist_empty(&conf->released_stripes) &&
+                                   !test_bit(R5_DID_ALLOC, &conf->cache_state))
+                                       set_bit(R5_ALLOC_MORE,
+                                               &conf->cache_state);
+                       }
                        if (noblock && sh == NULL)
                                break;
                        if (!sh) {
-                               conf->inactive_blocked = 1;
+                               set_bit(R5_INACTIVE_BLOCKED,
+                                       &conf->cache_state);
                                wait_event_lock_irq(
                                        conf->wait_for_stripe,
                                        !list_empty(conf->inactive_list + hash) &&
                                        (atomic_read(&conf->active_stripes)
                                         < (conf->max_nr_stripes * 3 / 4)
-                                        || !conf->inactive_blocked),
+                                        || !test_bit(R5_INACTIVE_BLOCKED,
+                                                     &conf->cache_state)),
                                        *(conf->hash_locks + hash));
-                               conf->inactive_blocked = 0;
+                               clear_bit(R5_INACTIVE_BLOCKED,
+                                         &conf->cache_state);
                        } else {
                                init_stripe(sh, sector, previous);
                                atomic_inc(&sh->count);
@@ -708,6 +720,130 @@ get_active_stripe(struct r5conf *conf, sector_t sector,
        return sh;
 }
 
+static bool is_full_stripe_write(struct stripe_head *sh)
+{
+       BUG_ON(sh->overwrite_disks > (sh->disks - sh->raid_conf->max_degraded));
+       return sh->overwrite_disks == (sh->disks - sh->raid_conf->max_degraded);
+}
+
+static void lock_two_stripes(struct stripe_head *sh1, struct stripe_head *sh2)
+{
+       local_irq_disable();
+       if (sh1 > sh2) {
+               spin_lock(&sh2->stripe_lock);
+               spin_lock_nested(&sh1->stripe_lock, 1);
+       } else {
+               spin_lock(&sh1->stripe_lock);
+               spin_lock_nested(&sh2->stripe_lock, 1);
+       }
+}
+
+static void unlock_two_stripes(struct stripe_head *sh1, struct stripe_head *sh2)
+{
+       spin_unlock(&sh1->stripe_lock);
+       spin_unlock(&sh2->stripe_lock);
+       local_irq_enable();
+}
+
+/* Only freshly new full stripe normal write stripe can be added to a batch list */
+static bool stripe_can_batch(struct stripe_head *sh)
+{
+       return test_bit(STRIPE_BATCH_READY, &sh->state) &&
+               is_full_stripe_write(sh);
+}
+
+/* we only do back search */
+static void stripe_add_to_batch_list(struct r5conf *conf, struct stripe_head *sh)
+{
+       struct stripe_head *head;
+       sector_t head_sector, tmp_sec;
+       int hash;
+       int dd_idx;
+
+       if (!stripe_can_batch(sh))
+               return;
+       /* Don't cross chunks, so stripe pd_idx/qd_idx is the same */
+       tmp_sec = sh->sector;
+       if (!sector_div(tmp_sec, conf->chunk_sectors))
+               return;
+       head_sector = sh->sector - STRIPE_SECTORS;
+
+       hash = stripe_hash_locks_hash(head_sector);
+       spin_lock_irq(conf->hash_locks + hash);
+       head = __find_stripe(conf, head_sector, conf->generation);
+       if (head && !atomic_inc_not_zero(&head->count)) {
+               spin_lock(&conf->device_lock);
+               if (!atomic_read(&head->count)) {
+                       if (!test_bit(STRIPE_HANDLE, &head->state))
+                               atomic_inc(&conf->active_stripes);
+                       BUG_ON(list_empty(&head->lru) &&
+                              !test_bit(STRIPE_EXPANDING, &head->state));
+                       list_del_init(&head->lru);
+                       if (head->group) {
+                               head->group->stripes_cnt--;
+                               head->group = NULL;
+                       }
+               }
+               atomic_inc(&head->count);
+               spin_unlock(&conf->device_lock);
+       }
+       spin_unlock_irq(conf->hash_locks + hash);
+
+       if (!head)
+               return;
+       if (!stripe_can_batch(head))
+               goto out;
+
+       lock_two_stripes(head, sh);
+       /* clear_batch_ready clear the flag */
+       if (!stripe_can_batch(head) || !stripe_can_batch(sh))
+               goto unlock_out;
+
+       if (sh->batch_head)
+               goto unlock_out;
+
+       dd_idx = 0;
+       while (dd_idx == sh->pd_idx || dd_idx == sh->qd_idx)
+               dd_idx++;
+       if (head->dev[dd_idx].towrite->bi_rw != sh->dev[dd_idx].towrite->bi_rw)
+               goto unlock_out;
+
+       if (head->batch_head) {
+               spin_lock(&head->batch_head->batch_lock);
+               /* This batch list is already running */
+               if (!stripe_can_batch(head)) {
+                       spin_unlock(&head->batch_head->batch_lock);
+                       goto unlock_out;
+               }
+
+               /*
+                * at this point, head's BATCH_READY could be cleared, but we
+                * can still add the stripe to batch list
+                */
+               list_add(&sh->batch_list, &head->batch_list);
+               spin_unlock(&head->batch_head->batch_lock);
+
+               sh->batch_head = head->batch_head;
+       } else {
+               head->batch_head = head;
+               sh->batch_head = head->batch_head;
+               spin_lock(&head->batch_lock);
+               list_add_tail(&sh->batch_list, &head->batch_list);
+               spin_unlock(&head->batch_lock);
+       }
+
+       if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
+               if (atomic_dec_return(&conf->preread_active_stripes)
+                   < IO_THRESHOLD)
+                       md_wakeup_thread(conf->mddev->thread);
+
+       atomic_inc(&sh->count);
+unlock_out:
+       unlock_two_stripes(head, sh);
+out:
+       release_stripe(head);
+}
+
 /* Determine if 'data_offset' or 'new_data_offset' should be used
  * in this stripe_head.
  */
@@ -738,6 +874,7 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
 {
        struct r5conf *conf = sh->raid_conf;
        int i, disks = sh->disks;
+       struct stripe_head *head_sh = sh;
 
        might_sleep();
 
@@ -746,6 +883,8 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
                int replace_only = 0;
                struct bio *bi, *rbi;
                struct md_rdev *rdev, *rrdev = NULL;
+
+               sh = head_sh;
                if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags)) {
                        if (test_and_clear_bit(R5_WantFUA, &sh->dev[i].flags))
                                rw = WRITE_FUA;
@@ -764,6 +903,7 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
                if (test_and_clear_bit(R5_SyncIO, &sh->dev[i].flags))
                        rw |= REQ_SYNC;
 
+again:
                bi = &sh->dev[i].req;
                rbi = &sh->dev[i].rreq; /* For writing to replacement */
 
@@ -782,7 +922,7 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
                                /* We raced and saw duplicates */
                                rrdev = NULL;
                } else {
-                       if (test_bit(R5_ReadRepl, &sh->dev[i].flags) && rrdev)
+                       if (test_bit(R5_ReadRepl, &head_sh->dev[i].flags) && rrdev)
                                rdev = rrdev;
                        rrdev = NULL;
                }
@@ -853,13 +993,15 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
                                __func__, (unsigned long long)sh->sector,
                                bi->bi_rw, i);
                        atomic_inc(&sh->count);
+                       if (sh != head_sh)
+                               atomic_inc(&head_sh->count);
                        if (use_new_offset(conf, sh))
                                bi->bi_iter.bi_sector = (sh->sector
                                                 + rdev->new_data_offset);
                        else
                                bi->bi_iter.bi_sector = (sh->sector
                                                 + rdev->data_offset);
-                       if (test_bit(R5_ReadNoMerge, &sh->dev[i].flags))
+                       if (test_bit(R5_ReadNoMerge, &head_sh->dev[i].flags))
                                bi->bi_rw |= REQ_NOMERGE;
 
                        if (test_bit(R5_SkipCopy, &sh->dev[i].flags))
@@ -903,6 +1045,8 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
                                __func__, (unsigned long long)sh->sector,
                                rbi->bi_rw, i);
                        atomic_inc(&sh->count);
+                       if (sh != head_sh)
+                               atomic_inc(&head_sh->count);
                        if (use_new_offset(conf, sh))
                                rbi->bi_iter.bi_sector = (sh->sector
                                                  + rrdev->new_data_offset);
@@ -934,8 +1078,18 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
                        pr_debug("skip op %ld on disc %d for sector %llu\n",
                                bi->bi_rw, i, (unsigned long long)sh->sector);
                        clear_bit(R5_LOCKED, &sh->dev[i].flags);
+                       if (sh->batch_head)
+                               set_bit(STRIPE_BATCH_ERR,
+                                       &sh->batch_head->state);
                        set_bit(STRIPE_HANDLE, &sh->state);
                }
+
+               if (!head_sh->batch_head)
+                       continue;
+               sh = list_first_entry(&sh->batch_list, struct stripe_head,
+                                     batch_list);
+               if (sh != head_sh)
+                       goto again;
        }
 }
 
@@ -1051,6 +1205,7 @@ static void ops_run_biofill(struct stripe_head *sh)
        struct async_submit_ctl submit;
        int i;
 
+       BUG_ON(sh->batch_head);
        pr_debug("%s: stripe %llu\n", __func__,
                (unsigned long long)sh->sector);
 
@@ -1109,16 +1264,28 @@ static void ops_complete_compute(void *stripe_head_ref)
 
 /* return a pointer to the address conversion region of the scribble buffer */
 static addr_conv_t *to_addr_conv(struct stripe_head *sh,
-                                struct raid5_percpu *percpu)
+                                struct raid5_percpu *percpu, int i)
 {
-       return percpu->scribble + sizeof(struct page *) * (sh->disks + 2);
+       void *addr;
+
+       addr = flex_array_get(percpu->scribble, i);
+       return addr + sizeof(struct page *) * (sh->disks + 2);
+}
+
+/* return a pointer to the address conversion region of the scribble buffer */
+static struct page **to_addr_page(struct raid5_percpu *percpu, int i)
+{
+       void *addr;
+
+       addr = flex_array_get(percpu->scribble, i);
+       return addr;
 }
 
 static struct dma_async_tx_descriptor *
 ops_run_compute5(struct stripe_head *sh, struct raid5_percpu *percpu)
 {
        int disks = sh->disks;
-       struct page **xor_srcs = percpu->scribble;
+       struct page **xor_srcs = to_addr_page(percpu, 0);
        int target = sh->ops.target;
        struct r5dev *tgt = &sh->dev[target];
        struct page *xor_dest = tgt->page;
@@ -1127,6 +1294,8 @@ ops_run_compute5(struct stripe_head *sh, struct raid5_percpu *percpu)
        struct async_submit_ctl submit;
        int i;
 
+       BUG_ON(sh->batch_head);
+
        pr_debug("%s: stripe %llu block: %d\n",
                __func__, (unsigned long long)sh->sector, target);
        BUG_ON(!test_bit(R5_Wantcompute, &tgt->flags));
@@ -1138,7 +1307,7 @@ ops_run_compute5(struct stripe_head *sh, struct raid5_percpu *percpu)
        atomic_inc(&sh->count);
 
        init_async_submit(&submit, ASYNC_TX_FENCE|ASYNC_TX_XOR_ZERO_DST, NULL,
-                         ops_complete_compute, sh, to_addr_conv(sh, percpu));
+                         ops_complete_compute, sh, to_addr_conv(sh, percpu, 0));
        if (unlikely(count == 1))
                tx = async_memcpy(xor_dest, xor_srcs[0], 0, 0, STRIPE_SIZE, &submit);
        else
@@ -1156,7 +1325,9 @@ ops_run_compute5(struct stripe_head *sh, struct raid5_percpu *percpu)
  * destination buffer is recorded in srcs[count] and the Q destination
  * is recorded in srcs[count+1]].
  */
-static int set_syndrome_sources(struct page **srcs, struct stripe_head *sh)
+static int set_syndrome_sources(struct page **srcs,
+                               struct stripe_head *sh,
+                               int srctype)
 {
        int disks = sh->disks;
        int syndrome_disks = sh->ddf_layout ? disks : (disks - 2);
@@ -1171,8 +1342,15 @@ static int set_syndrome_sources(struct page **srcs, struct stripe_head *sh)
        i = d0_idx;
        do {
                int slot = raid6_idx_to_slot(i, sh, &count, syndrome_disks);
+               struct r5dev *dev = &sh->dev[i];
 
-               srcs[slot] = sh->dev[i].page;
+               if (i == sh->qd_idx || i == sh->pd_idx ||
+                   (srctype == SYNDROME_SRC_ALL) ||
+                   (srctype == SYNDROME_SRC_WANT_DRAIN &&
+                    test_bit(R5_Wantdrain, &dev->flags)) ||
+                   (srctype == SYNDROME_SRC_WRITTEN &&
+                    dev->written))
+                       srcs[slot] = sh->dev[i].page;
                i = raid6_next_disk(i, disks);
        } while (i != d0_idx);
 
@@ -1183,7 +1361,7 @@ static struct dma_async_tx_descriptor *
 ops_run_compute6_1(struct stripe_head *sh, struct raid5_percpu *percpu)
 {
        int disks = sh->disks;
-       struct page **blocks = percpu->scribble;
+       struct page **blocks = to_addr_page(percpu, 0);
        int target;
        int qd_idx = sh->qd_idx;
        struct dma_async_tx_descriptor *tx;
@@ -1193,6 +1371,7 @@ ops_run_compute6_1(struct stripe_head *sh, struct raid5_percpu *percpu)
        int i;
        int count;
 
+       BUG_ON(sh->batch_head);
        if (sh->ops.target < 0)
                target = sh->ops.target2;
        else if (sh->ops.target2 < 0)
@@ -1211,12 +1390,12 @@ ops_run_compute6_1(struct stripe_head *sh, struct raid5_percpu *percpu)
        atomic_inc(&sh->count);
 
        if (target == qd_idx) {
-               count = set_syndrome_sources(blocks, sh);
+               count = set_syndrome_sources(blocks, sh, SYNDROME_SRC_ALL);
                blocks[count] = NULL; /* regenerating p is not necessary */
                BUG_ON(blocks[count+1] != dest); /* q should already be set */
                init_async_submit(&submit, ASYNC_TX_FENCE, NULL,
                                  ops_complete_compute, sh,
-                                 to_addr_conv(sh, percpu));
+                                 to_addr_conv(sh, percpu, 0));
                tx = async_gen_syndrome(blocks, 0, count+2, STRIPE_SIZE, &submit);
        } else {
                /* Compute any data- or p-drive using XOR */
@@ -1229,7 +1408,7 @@ ops_run_compute6_1(struct stripe_head *sh, struct raid5_percpu *percpu)
 
                init_async_submit(&submit, ASYNC_TX_FENCE|ASYNC_TX_XOR_ZERO_DST,
                                  NULL, ops_complete_compute, sh,
-                                 to_addr_conv(sh, percpu));
+                                 to_addr_conv(sh, percpu, 0));
                tx = async_xor(dest, blocks, 0, count, STRIPE_SIZE, &submit);
        }
 
@@ -1248,9 +1427,10 @@ ops_run_compute6_2(struct stripe_head *sh, struct raid5_percpu *percpu)
        struct r5dev *tgt = &sh->dev[target];
        struct r5dev *tgt2 = &sh->dev[target2];
        struct dma_async_tx_descriptor *tx;
-       struct page **blocks = percpu->scribble;
+       struct page **blocks = to_addr_page(percpu, 0);
        struct async_submit_ctl submit;
 
+       BUG_ON(sh->batch_head);
        pr_debug("%s: stripe %llu block1: %d block2: %d\n",
                 __func__, (unsigned long long)sh->sector, target, target2);
        BUG_ON(target < 0 || target2 < 0);
@@ -1290,7 +1470,7 @@ ops_run_compute6_2(struct stripe_head *sh, struct raid5_percpu *percpu)
                        /* Missing P+Q, just recompute */
                        init_async_submit(&submit, ASYNC_TX_FENCE, NULL,
                                          ops_complete_compute, sh,
-                                         to_addr_conv(sh, percpu));
+                                         to_addr_conv(sh, percpu, 0));
                        return async_gen_syndrome(blocks, 0, syndrome_disks+2,
                                                  STRIPE_SIZE, &submit);
                } else {
@@ -1314,21 +1494,21 @@ ops_run_compute6_2(struct stripe_head *sh, struct raid5_percpu *percpu)
                        init_async_submit(&submit,
                                          ASYNC_TX_FENCE|ASYNC_TX_XOR_ZERO_DST,
                                          NULL, NULL, NULL,
-                                         to_addr_conv(sh, percpu));
+                                         to_addr_conv(sh, percpu, 0));
                        tx = async_xor(dest, blocks, 0, count, STRIPE_SIZE,
                                       &submit);
 
-                       count = set_syndrome_sources(blocks, sh);
+                       count = set_syndrome_sources(blocks, sh, SYNDROME_SRC_ALL);
                        init_async_submit(&submit, ASYNC_TX_FENCE, tx,
                                          ops_complete_compute, sh,
-                                         to_addr_conv(sh, percpu));
+                                         to_addr_conv(sh, percpu, 0));
                        return async_gen_syndrome(blocks, 0, count+2,
                                                  STRIPE_SIZE, &submit);
                }
        } else {
                init_async_submit(&submit, ASYNC_TX_FENCE, NULL,
                                  ops_complete_compute, sh,
-                                 to_addr_conv(sh, percpu));
+                                 to_addr_conv(sh, percpu, 0));
                if (failb == syndrome_disks) {
                        /* We're missing D+P. */
                        return async_raid6_datap_recov(syndrome_disks+2,
@@ -1352,17 +1532,18 @@ static void ops_complete_prexor(void *stripe_head_ref)
 }
 
 static struct dma_async_tx_descriptor *
-ops_run_prexor(struct stripe_head *sh, struct raid5_percpu *percpu,
-              struct dma_async_tx_descriptor *tx)
+ops_run_prexor5(struct stripe_head *sh, struct raid5_percpu *percpu,
+               struct dma_async_tx_descriptor *tx)
 {
        int disks = sh->disks;
-       struct page **xor_srcs = percpu->scribble;
+       struct page **xor_srcs = to_addr_page(percpu, 0);
        int count = 0, pd_idx = sh->pd_idx, i;
        struct async_submit_ctl submit;
 
        /* existing parity data subtracted */
        struct page *xor_dest = xor_srcs[count++] = sh->dev[pd_idx].page;
 
+       BUG_ON(sh->batch_head);
        pr_debug("%s: stripe %llu\n", __func__,
                (unsigned long long)sh->sector);
 
@@ -1374,31 +1555,56 @@ ops_run_prexor(struct stripe_head *sh, struct raid5_percpu *percpu,
        }
 
        init_async_submit(&submit, ASYNC_TX_FENCE|ASYNC_TX_XOR_DROP_DST, tx,
-                         ops_complete_prexor, sh, to_addr_conv(sh, percpu));
+                         ops_complete_prexor, sh, to_addr_conv(sh, percpu, 0));
        tx = async_xor(xor_dest, xor_srcs, 0, count, STRIPE_SIZE, &submit);
 
        return tx;
 }
 
+static struct dma_async_tx_descriptor *
+ops_run_prexor6(struct stripe_head *sh, struct raid5_percpu *percpu,
+               struct dma_async_tx_descriptor *tx)
+{
+       struct page **blocks = to_addr_page(percpu, 0);
+       int count;
+       struct async_submit_ctl submit;
+
+       pr_debug("%s: stripe %llu\n", __func__,
+               (unsigned long long)sh->sector);
+
+       count = set_syndrome_sources(blocks, sh, SYNDROME_SRC_WANT_DRAIN);
+
+       init_async_submit(&submit, ASYNC_TX_FENCE|ASYNC_TX_PQ_XOR_DST, tx,
+                         ops_complete_prexor, sh, to_addr_conv(sh, percpu, 0));
+       tx = async_gen_syndrome(blocks, 0, count+2, STRIPE_SIZE,  &submit);
+
+       return tx;
+}
+
 static struct dma_async_tx_descriptor *
 ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
 {
        int disks = sh->disks;
        int i;
+       struct stripe_head *head_sh = sh;
 
        pr_debug("%s: stripe %llu\n", __func__,
                (unsigned long long)sh->sector);
 
        for (i = disks; i--; ) {
-               struct r5dev *dev = &sh->dev[i];
+               struct r5dev *dev;
                struct bio *chosen;
 
-               if (test_and_clear_bit(R5_Wantdrain, &dev->flags)) {
+               sh = head_sh;
+               if (test_and_clear_bit(R5_Wantdrain, &head_sh->dev[i].flags)) {
                        struct bio *wbi;
 
+again:
+                       dev = &sh->dev[i];
                        spin_lock_irq(&sh->stripe_lock);
                        chosen = dev->towrite;
                        dev->towrite = NULL;
+                       sh->overwrite_disks = 0;
                        BUG_ON(dev->written);
                        wbi = dev->written = chosen;
                        spin_unlock_irq(&sh->stripe_lock);
@@ -1423,6 +1629,15 @@ ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
                                }
                                wbi = r5_next_bio(wbi, dev->sector);
                        }
+
+                       if (head_sh->batch_head) {
+                               sh = list_first_entry(&sh->batch_list,
+                                                     struct stripe_head,
+                                                     batch_list);
+                               if (sh == head_sh)
+                                       continue;
+                               goto again;
+                       }
                }
        }
 
@@ -1478,12 +1693,15 @@ ops_run_reconstruct5(struct stripe_head *sh, struct raid5_percpu *percpu,
                     struct dma_async_tx_descriptor *tx)
 {
        int disks = sh->disks;
-       struct page **xor_srcs = percpu->scribble;
+       struct page **xor_srcs;
        struct async_submit_ctl submit;
-       int count = 0, pd_idx = sh->pd_idx, i;
+       int count, pd_idx = sh->pd_idx, i;
        struct page *xor_dest;
        int prexor = 0;
        unsigned long flags;
+       int j = 0;
+       struct stripe_head *head_sh = sh;
+       int last_stripe;
 
        pr_debug("%s: stripe %llu\n", __func__,
                (unsigned long long)sh->sector);
@@ -1500,15 +1718,18 @@ ops_run_reconstruct5(struct stripe_head *sh, struct raid5_percpu *percpu,
                ops_complete_reconstruct(sh);
                return;
        }
+again:
+       count = 0;
+       xor_srcs = to_addr_page(percpu, j);
        /* check if prexor is active which means only process blocks
         * that are part of a read-modify-write (written)
         */
-       if (sh->reconstruct_state == reconstruct_state_prexor_drain_run) {
+       if (head_sh->reconstruct_state == reconstruct_state_prexor_drain_run) {
                prexor = 1;
                xor_dest = xor_srcs[count++] = sh->dev[pd_idx].page;
                for (i = disks; i--; ) {
                        struct r5dev *dev = &sh->dev[i];
-                       if (dev->written)
+                       if (head_sh->dev[i].written)
                                xor_srcs[count++] = dev->page;
                }
        } else {
@@ -1525,17 +1746,32 @@ ops_run_reconstruct5(struct stripe_head *sh, struct raid5_percpu *percpu,
         * set ASYNC_TX_XOR_DROP_DST and ASYNC_TX_XOR_ZERO_DST
         * for the synchronous xor case
         */
-       flags = ASYNC_TX_ACK |
-               (prexor ? ASYNC_TX_XOR_DROP_DST : ASYNC_TX_XOR_ZERO_DST);
-
-       atomic_inc(&sh->count);
+       last_stripe = !head_sh->batch_head ||
+               list_first_entry(&sh->batch_list,
+                                struct stripe_head, batch_list) == head_sh;
+       if (last_stripe) {
+               flags = ASYNC_TX_ACK |
+                       (prexor ? ASYNC_TX_XOR_DROP_DST : ASYNC_TX_XOR_ZERO_DST);
+
+               atomic_inc(&head_sh->count);
+               init_async_submit(&submit, flags, tx, ops_complete_reconstruct, head_sh,
+                                 to_addr_conv(sh, percpu, j));
+       } else {
+               flags = prexor ? ASYNC_TX_XOR_DROP_DST : ASYNC_TX_XOR_ZERO_DST;
+               init_async_submit(&submit, flags, tx, NULL, NULL,
+                                 to_addr_conv(sh, percpu, j));
+       }
 
-       init_async_submit(&submit, flags, tx, ops_complete_reconstruct, sh,
-                         to_addr_conv(sh, percpu));
        if (unlikely(count == 1))
                tx = async_memcpy(xor_dest, xor_srcs[0], 0, 0, STRIPE_SIZE, &submit);
        else
                tx = async_xor(xor_dest, xor_srcs, 0, count, STRIPE_SIZE, &submit);
+       if (!last_stripe) {
+               j++;
+               sh = list_first_entry(&sh->batch_list, struct stripe_head,
+                                     batch_list);
+               goto again;
+       }
 }
 
 static void
@@ -1543,8 +1779,12 @@ ops_run_reconstruct6(struct stripe_head *sh, struct raid5_percpu *percpu,
                     struct dma_async_tx_descriptor *tx)
 {
        struct async_submit_ctl submit;
-       struct page **blocks = percpu->scribble;
-       int count, i;
+       struct page **blocks;
+       int count, i, j = 0;
+       struct stripe_head *head_sh = sh;
+       int last_stripe;
+       int synflags;
+       unsigned long txflags;
 
        pr_debug("%s: stripe %llu\n", __func__, (unsigned long long)sh->sector);
 
@@ -1562,13 +1802,36 @@ ops_run_reconstruct6(struct stripe_head *sh, struct raid5_percpu *percpu,
                return;
        }
 
-       count = set_syndrome_sources(blocks, sh);
+again:
+       blocks = to_addr_page(percpu, j);
 
-       atomic_inc(&sh->count);
+       if (sh->reconstruct_state == reconstruct_state_prexor_drain_run) {
+               synflags = SYNDROME_SRC_WRITTEN;
+               txflags = ASYNC_TX_ACK | ASYNC_TX_PQ_XOR_DST;
+       } else {
+               synflags = SYNDROME_SRC_ALL;
+               txflags = ASYNC_TX_ACK;
+       }
+
+       count = set_syndrome_sources(blocks, sh, synflags);
+       last_stripe = !head_sh->batch_head ||
+               list_first_entry(&sh->batch_list,
+                                struct stripe_head, batch_list) == head_sh;
 
-       init_async_submit(&submit, ASYNC_TX_ACK, tx, ops_complete_reconstruct,
-                         sh, to_addr_conv(sh, percpu));
+       if (last_stripe) {
+               atomic_inc(&head_sh->count);
+               init_async_submit(&submit, txflags, tx, ops_complete_reconstruct,
+                                 head_sh, to_addr_conv(sh, percpu, j));
+       } else
+               init_async_submit(&submit, 0, tx, NULL, NULL,
+                                 to_addr_conv(sh, percpu, j));
        async_gen_syndrome(blocks, 0, count+2, STRIPE_SIZE,  &submit);
+       if (!last_stripe) {
+               j++;
+               sh = list_first_entry(&sh->batch_list, struct stripe_head,
+                                     batch_list);
+               goto again;
+       }
 }
 
 static void ops_complete_check(void *stripe_head_ref)
@@ -1589,7 +1852,7 @@ static void ops_run_check_p(struct stripe_head *sh, struct raid5_percpu *percpu)
        int pd_idx = sh->pd_idx;
        int qd_idx = sh->qd_idx;
        struct page *xor_dest;
-       struct page **xor_srcs = percpu->scribble;
+       struct page **xor_srcs = to_addr_page(percpu, 0);
        struct dma_async_tx_descriptor *tx;
        struct async_submit_ctl submit;
        int count;
@@ -1598,6 +1861,7 @@ static void ops_run_check_p(struct stripe_head *sh, struct raid5_percpu *percpu)
        pr_debug("%s: stripe %llu\n", __func__,
                (unsigned long long)sh->sector);
 
+       BUG_ON(sh->batch_head);
        count = 0;
        xor_dest = sh->dev[pd_idx].page;
        xor_srcs[count++] = xor_dest;
@@ -1608,7 +1872,7 @@ static void ops_run_check_p(struct stripe_head *sh, struct raid5_percpu *percpu)
        }
 
        init_async_submit(&submit, 0, NULL, NULL, NULL,
-                         to_addr_conv(sh, percpu));
+                         to_addr_conv(sh, percpu, 0));
        tx = async_xor_val(xor_dest, xor_srcs, 0, count, STRIPE_SIZE,
                           &sh->ops.zero_sum_result, &submit);
 
@@ -1619,20 +1883,21 @@ static void ops_run_check_p(struct stripe_head *sh, struct raid5_percpu *percpu)
 
 static void ops_run_check_pq(struct stripe_head *sh, struct raid5_percpu *percpu, int checkp)
 {
-       struct page **srcs = percpu->scribble;
+       struct page **srcs = to_addr_page(percpu, 0);
        struct async_submit_ctl submit;
        int count;
 
        pr_debug("%s: stripe %llu checkp: %d\n", __func__,
                (unsigned long long)sh->sector, checkp);
 
-       count = set_syndrome_sources(srcs, sh);
+       BUG_ON(sh->batch_head);
+       count = set_syndrome_sources(srcs, sh, SYNDROME_SRC_ALL);
        if (!checkp)
                srcs[count] = NULL;
 
        atomic_inc(&sh->count);
        init_async_submit(&submit, ASYNC_TX_ACK, NULL, ops_complete_check,
-                         sh, to_addr_conv(sh, percpu));
+                         sh, to_addr_conv(sh, percpu, 0));
        async_syndrome_val(srcs, 0, count+2, STRIPE_SIZE,
                           &sh->ops.zero_sum_result, percpu->spare_page, &submit);
 }
@@ -1667,8 +1932,12 @@ static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request)
                        async_tx_ack(tx);
        }
 
-       if (test_bit(STRIPE_OP_PREXOR, &ops_request))
-               tx = ops_run_prexor(sh, percpu, tx);
+       if (test_bit(STRIPE_OP_PREXOR, &ops_request)) {
+               if (level < 6)
+                       tx = ops_run_prexor5(sh, percpu, tx);
+               else
+                       tx = ops_run_prexor6(sh, percpu, tx);
+       }
 
        if (test_bit(STRIPE_OP_BIODRAIN, &ops_request)) {
                tx = ops_run_biodrain(sh, tx);
@@ -1693,7 +1962,7 @@ static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request)
                        BUG();
        }
 
-       if (overlap_clear)
+       if (overlap_clear && !sh->batch_head)
                for (i = disks; i--; ) {
                        struct r5dev *dev = &sh->dev[i];
                        if (test_and_clear_bit(R5_Overlap, &dev->flags))
@@ -1702,10 +1971,10 @@ static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request)
        put_cpu();
 }
 
-static int grow_one_stripe(struct r5conf *conf, int hash)
+static int grow_one_stripe(struct r5conf *conf, gfp_t gfp)
 {
        struct stripe_head *sh;
-       sh = kmem_cache_zalloc(conf->slab_cache, GFP_KERNEL);
+       sh = kmem_cache_zalloc(conf->slab_cache, gfp);
        if (!sh)
                return 0;
 
@@ -1713,17 +1982,23 @@ static int grow_one_stripe(struct r5conf *conf, int hash)
 
        spin_lock_init(&sh->stripe_lock);
 
-       if (grow_buffers(sh)) {
+       if (grow_buffers(sh, gfp)) {
                shrink_buffers(sh);
                kmem_cache_free(conf->slab_cache, sh);
                return 0;
        }
-       sh->hash_lock_index = hash;
+       sh->hash_lock_index =
+               conf->max_nr_stripes % NR_STRIPE_HASH_LOCKS;
        /* we just created an active stripe so... */
        atomic_set(&sh->count, 1);
        atomic_inc(&conf->active_stripes);
        INIT_LIST_HEAD(&sh->lru);
+
+       spin_lock_init(&sh->batch_lock);
+       INIT_LIST_HEAD(&sh->batch_list);
+       sh->batch_head = NULL;
        release_stripe(sh);
+       conf->max_nr_stripes++;
        return 1;
 }
 
@@ -1731,7 +2006,6 @@ static int grow_stripes(struct r5conf *conf, int num)
 {
        struct kmem_cache *sc;
        int devs = max(conf->raid_disks, conf->previous_raid_disks);
-       int hash;
 
        if (conf->mddev->gendisk)
                sprintf(conf->cache_name[0],
@@ -1749,13 +2023,10 @@ static int grow_stripes(struct r5conf *conf, int num)
                return 1;
        conf->slab_cache = sc;
        conf->pool_size = devs;
-       hash = conf->max_nr_stripes % NR_STRIPE_HASH_LOCKS;
-       while (num--) {
-               if (!grow_one_stripe(conf, hash))
+       while (num--)
+               if (!grow_one_stripe(conf, GFP_KERNEL))
                        return 1;
-               conf->max_nr_stripes++;
-               hash = (hash + 1) % NR_STRIPE_HASH_LOCKS;
-       }
+
        return 0;
 }
 
@@ -1772,13 +2043,21 @@ static int grow_stripes(struct r5conf *conf, int num)
  * calculate over all devices (not just the data blocks), using zeros in place
  * of the P and Q blocks.
  */
-static size_t scribble_len(int num)
+static struct flex_array *scribble_alloc(int num, int cnt, gfp_t flags)
 {
+       struct flex_array *ret;
        size_t len;
 
        len = sizeof(struct page *) * (num+2) + sizeof(addr_conv_t) * (num+2);
-
-       return len;
+       ret = flex_array_alloc(len, cnt, flags);
+       if (!ret)
+               return NULL;
+       /* always prealloc all elements, so no locking is required */
+       if (flex_array_prealloc(ret, 0, cnt, flags)) {
+               flex_array_free(ret);
+               return NULL;
+       }
+       return ret;
 }
 
 static int resize_stripes(struct r5conf *conf, int newsize)
@@ -1896,16 +2175,16 @@ static int resize_stripes(struct r5conf *conf, int newsize)
                err = -ENOMEM;
 
        get_online_cpus();
-       conf->scribble_len = scribble_len(newsize);
        for_each_present_cpu(cpu) {
                struct raid5_percpu *percpu;
-               void *scribble;
+               struct flex_array *scribble;
 
                percpu = per_cpu_ptr(conf->percpu, cpu);
-               scribble = kmalloc(conf->scribble_len, GFP_NOIO);
+               scribble = scribble_alloc(newsize, conf->chunk_sectors /
+                       STRIPE_SECTORS, GFP_NOIO);
 
                if (scribble) {
-                       kfree(percpu->scribble);
+                       flex_array_free(percpu->scribble);
                        percpu->scribble = scribble;
                } else {
                        err = -ENOMEM;
@@ -1937,9 +2216,10 @@ static int resize_stripes(struct r5conf *conf, int newsize)
        return err;
 }
 
-static int drop_one_stripe(struct r5conf *conf, int hash)
+static int drop_one_stripe(struct r5conf *conf)
 {
        struct stripe_head *sh;
+       int hash = (conf->max_nr_stripes - 1) % NR_STRIPE_HASH_LOCKS;
 
        spin_lock_irq(conf->hash_locks + hash);
        sh = get_free_stripe(conf, hash);
@@ -1950,15 +2230,15 @@ static int drop_one_stripe(struct r5conf *conf, int hash)
        shrink_buffers(sh);
        kmem_cache_free(conf->slab_cache, sh);
        atomic_dec(&conf->active_stripes);
+       conf->max_nr_stripes--;
        return 1;
 }
 
 static void shrink_stripes(struct r5conf *conf)
 {
-       int hash;
-       for (hash = 0; hash < NR_STRIPE_HASH_LOCKS; hash++)
-               while (drop_one_stripe(conf, hash))
-                       ;
+       while (conf->max_nr_stripes &&
+              drop_one_stripe(conf))
+               ;
 
        if (conf->slab_cache)
                kmem_cache_destroy(conf->slab_cache);
@@ -2154,10 +2434,16 @@ static void raid5_end_write_request(struct bio *bi, int error)
        }
        rdev_dec_pending(rdev, conf->mddev);
 
+       if (sh->batch_head && !uptodate)
+               set_bit(STRIPE_BATCH_ERR, &sh->batch_head->state);
+
        if (!test_and_clear_bit(R5_DOUBLE_LOCKED, &sh->dev[i].flags))
                clear_bit(R5_LOCKED, &sh->dev[i].flags);
        set_bit(STRIPE_HANDLE, &sh->state);
        release_stripe(sh);
+
+       if (sh->batch_head && sh != sh->batch_head)
+               release_stripe(sh->batch_head);
 }
 
 static sector_t compute_blocknr(struct stripe_head *sh, int i, int previous);
@@ -2535,7 +2821,7 @@ static void
 schedule_reconstruction(struct stripe_head *sh, struct stripe_head_state *s,
                         int rcw, int expand)
 {
-       int i, pd_idx = sh->pd_idx, disks = sh->disks;
+       int i, pd_idx = sh->pd_idx, qd_idx = sh->qd_idx, disks = sh->disks;
        struct r5conf *conf = sh->raid_conf;
        int level = conf->level;
 
@@ -2571,13 +2857,15 @@ schedule_reconstruction(struct stripe_head *sh, struct stripe_head_state *s,
                        if (!test_and_set_bit(STRIPE_FULL_WRITE, &sh->state))
                                atomic_inc(&conf->pending_full_writes);
        } else {
-               BUG_ON(level == 6);
                BUG_ON(!(test_bit(R5_UPTODATE, &sh->dev[pd_idx].flags) ||
                        test_bit(R5_Wantcompute, &sh->dev[pd_idx].flags)));
+               BUG_ON(level == 6 &&
+                       (!(test_bit(R5_UPTODATE, &sh->dev[qd_idx].flags) ||
+                          test_bit(R5_Wantcompute, &sh->dev[qd_idx].flags))));
 
                for (i = disks; i--; ) {
                        struct r5dev *dev = &sh->dev[i];
-                       if (i == pd_idx)
+                       if (i == pd_idx || i == qd_idx)
                                continue;
 
                        if (dev->towrite &&
@@ -2624,7 +2912,8 @@ schedule_reconstruction(struct stripe_head *sh, struct stripe_head_state *s,
  * toread/towrite point to the first in a chain.
  * The bi_next chain must be in order.
  */
-static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, int forwrite)
+static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx,
+                         int forwrite, int previous)
 {
        struct bio **bip;
        struct r5conf *conf = sh->raid_conf;
@@ -2643,6 +2932,9 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
         * protect it.
         */
        spin_lock_irq(&sh->stripe_lock);
+       /* Don't allow new IO added to stripes in batch list */
+       if (sh->batch_head)
+               goto overlap;
        if (forwrite) {
                bip = &sh->dev[dd_idx].towrite;
                if (*bip == NULL)
@@ -2657,6 +2949,9 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
        if (*bip && (*bip)->bi_iter.bi_sector < bio_end_sector(bi))
                goto overlap;
 
+       if (!forwrite || previous)
+               clear_bit(STRIPE_BATCH_READY, &sh->state);
+
        BUG_ON(*bip && bi->bi_next && (*bip) != bi->bi_next);
        if (*bip)
                bi->bi_next = *bip;
@@ -2674,7 +2969,8 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
                                sector = bio_end_sector(bi);
                }
                if (sector >= sh->dev[dd_idx].sector + STRIPE_SECTORS)
-                       set_bit(R5_OVERWRITE, &sh->dev[dd_idx].flags);
+                       if (!test_and_set_bit(R5_OVERWRITE, &sh->dev[dd_idx].flags))
+                               sh->overwrite_disks++;
        }
 
        pr_debug("added bi b#%llu to stripe s#%llu, disk %d.\n",
@@ -2688,6 +2984,9 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
                sh->bm_seq = conf->seq_flush+1;
                set_bit(STRIPE_BIT_DELAY, &sh->state);
        }
+
+       if (stripe_can_batch(sh))
+               stripe_add_to_batch_list(conf, sh);
        return 1;
 
  overlap:
@@ -2720,6 +3019,7 @@ handle_failed_stripe(struct r5conf *conf, struct stripe_head *sh,
                                struct bio **return_bi)
 {
        int i;
+       BUG_ON(sh->batch_head);
        for (i = disks; i--; ) {
                struct bio *bi;
                int bitmap_end = 0;
@@ -2746,6 +3046,7 @@ handle_failed_stripe(struct r5conf *conf, struct stripe_head *sh,
                /* fail all writes first */
                bi = sh->dev[i].towrite;
                sh->dev[i].towrite = NULL;
+               sh->overwrite_disks = 0;
                spin_unlock_irq(&sh->stripe_lock);
                if (bi)
                        bitmap_end = 1;
@@ -2834,6 +3135,7 @@ handle_failed_sync(struct r5conf *conf, struct stripe_head *sh,
        int abort = 0;
        int i;
 
+       BUG_ON(sh->batch_head);
        clear_bit(STRIPE_SYNCING, &sh->state);
        if (test_and_clear_bit(R5_Overlap, &sh->dev[sh->pd_idx].flags))
                wake_up(&conf->wait_for_overlap);
@@ -3064,6 +3366,7 @@ static void handle_stripe_fill(struct stripe_head *sh,
 {
        int i;
 
+       BUG_ON(sh->batch_head);
        /* look for blocks to read/compute, skip this if a compute
         * is already in flight, or if the stripe contents are in the
         * midst of changing due to a write
@@ -3087,6 +3390,9 @@ static void handle_stripe_clean_event(struct r5conf *conf,
        int i;
        struct r5dev *dev;
        int discard_pending = 0;
+       struct stripe_head *head_sh = sh;
+       bool do_endio = false;
+       int wakeup_nr = 0;
 
        for (i = disks; i--; )
                if (sh->dev[i].written) {
@@ -3102,8 +3408,11 @@ static void handle_stripe_clean_event(struct r5conf *conf,
                                        clear_bit(R5_UPTODATE, &dev->flags);
                                if (test_and_clear_bit(R5_SkipCopy, &dev->flags)) {
                                        WARN_ON(test_bit(R5_UPTODATE, &dev->flags));
-                                       dev->page = dev->orig_page;
                                }
+                               do_endio = true;
+
+returnbi:
+                               dev->page = dev->orig_page;
                                wbi = dev->written;
                                dev->written = NULL;
                                while (wbi && wbi->bi_iter.bi_sector <
@@ -3120,6 +3429,17 @@ static void handle_stripe_clean_event(struct r5conf *conf,
                                                STRIPE_SECTORS,
                                         !test_bit(STRIPE_DEGRADED, &sh->state),
                                                0);
+                               if (head_sh->batch_head) {
+                                       sh = list_first_entry(&sh->batch_list,
+                                                             struct stripe_head,
+                                                             batch_list);
+                                       if (sh != head_sh) {
+                                               dev = &sh->dev[i];
+                                               goto returnbi;
+                                       }
+                               }
+                               sh = head_sh;
+                               dev = &sh->dev[i];
                        } else if (test_bit(R5_Discard, &dev->flags))
                                discard_pending = 1;
                        WARN_ON(test_bit(R5_SkipCopy, &dev->flags));
@@ -3141,8 +3461,17 @@ static void handle_stripe_clean_event(struct r5conf *conf,
                 * will be reinitialized
                 */
                spin_lock_irq(&conf->device_lock);
+unhash:
                remove_hash(sh);
+               if (head_sh->batch_head) {
+                       sh = list_first_entry(&sh->batch_list,
+                                             struct stripe_head, batch_list);
+                       if (sh != head_sh)
+                                       goto unhash;
+               }
                spin_unlock_irq(&conf->device_lock);
+               sh = head_sh;
+
                if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state))
                        set_bit(STRIPE_HANDLE, &sh->state);
 
@@ -3151,6 +3480,45 @@ static void handle_stripe_clean_event(struct r5conf *conf,
        if (test_and_clear_bit(STRIPE_FULL_WRITE, &sh->state))
                if (atomic_dec_and_test(&conf->pending_full_writes))
                        md_wakeup_thread(conf->mddev->thread);
+
+       if (!head_sh->batch_head || !do_endio)
+               return;
+       for (i = 0; i < head_sh->disks; i++) {
+               if (test_and_clear_bit(R5_Overlap, &head_sh->dev[i].flags))
+                       wakeup_nr++;
+       }
+       while (!list_empty(&head_sh->batch_list)) {
+               int i;
+               sh = list_first_entry(&head_sh->batch_list,
+                                     struct stripe_head, batch_list);
+               list_del_init(&sh->batch_list);
+
+               set_mask_bits(&sh->state, ~STRIPE_EXPAND_SYNC_FLAG,
+                             head_sh->state & ~((1 << STRIPE_ACTIVE) |
+                                                (1 << STRIPE_PREREAD_ACTIVE) |
+                                                STRIPE_EXPAND_SYNC_FLAG));
+               sh->check_state = head_sh->check_state;
+               sh->reconstruct_state = head_sh->reconstruct_state;
+               for (i = 0; i < sh->disks; i++) {
+                       if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
+                               wakeup_nr++;
+                       sh->dev[i].flags = head_sh->dev[i].flags;
+               }
+
+               spin_lock_irq(&sh->stripe_lock);
+               sh->batch_head = NULL;
+               spin_unlock_irq(&sh->stripe_lock);
+               if (sh->state & STRIPE_EXPAND_SYNC_FLAG)
+                       set_bit(STRIPE_HANDLE, &sh->state);
+               release_stripe(sh);
+       }
+
+       spin_lock_irq(&head_sh->stripe_lock);
+       head_sh->batch_head = NULL;
+       spin_unlock_irq(&head_sh->stripe_lock);
+       wake_up_nr(&conf->wait_for_overlap, wakeup_nr);
+       if (head_sh->state & STRIPE_EXPAND_SYNC_FLAG)
+               set_bit(STRIPE_HANDLE, &head_sh->state);
 }
 
 static void handle_stripe_dirtying(struct r5conf *conf,
@@ -3161,28 +3529,27 @@ static void handle_stripe_dirtying(struct r5conf *conf,
        int rmw = 0, rcw = 0, i;
        sector_t recovery_cp = conf->mddev->recovery_cp;
 
-       /* RAID6 requires 'rcw' in current implementation.
-        * Otherwise, check whether resync is now happening or should start.
+       /* Check whether resync is now happening or should start.
         * If yes, then the array is dirty (after unclean shutdown or
         * initial creation), so parity in some stripes might be inconsistent.
         * In this case, we need to always do reconstruct-write, to ensure
         * that in case of drive failure or read-error correction, we
         * generate correct data from the parity.
         */
-       if (conf->max_degraded == 2 ||
+       if (conf->rmw_level == PARITY_DISABLE_RMW ||
            (recovery_cp < MaxSector && sh->sector >= recovery_cp &&
             s->failed == 0)) {
                /* Calculate the real rcw later - for now make it
                 * look like rcw is cheaper
                 */
                rcw = 1; rmw = 2;
-               pr_debug("force RCW max_degraded=%u, recovery_cp=%llu sh->sector=%llu\n",
-                        conf->max_degraded, (unsigned long long)recovery_cp,
+               pr_debug("force RCW rmw_level=%u, recovery_cp=%llu sh->sector=%llu\n",
+                        conf->rmw_level, (unsigned long long)recovery_cp,
                         (unsigned long long)sh->sector);
        } else for (i = disks; i--; ) {
                /* would I have to read this buffer for read_modify_write */
                struct r5dev *dev = &sh->dev[i];
-               if ((dev->towrite || i == sh->pd_idx) &&
+               if ((dev->towrite || i == sh->pd_idx || i == sh->qd_idx) &&
                    !test_bit(R5_LOCKED, &dev->flags) &&
                    !(test_bit(R5_UPTODATE, &dev->flags) ||
                      test_bit(R5_Wantcompute, &dev->flags))) {
@@ -3192,7 +3559,8 @@ static void handle_stripe_dirtying(struct r5conf *conf,
                                rmw += 2*disks;  /* cannot read it */
                }
                /* Would I have to read this buffer for reconstruct_write */
-               if (!test_bit(R5_OVERWRITE, &dev->flags) && i != sh->pd_idx &&
+               if (!test_bit(R5_OVERWRITE, &dev->flags) &&
+                   i != sh->pd_idx && i != sh->qd_idx &&
                    !test_bit(R5_LOCKED, &dev->flags) &&
                    !(test_bit(R5_UPTODATE, &dev->flags) ||
                    test_bit(R5_Wantcompute, &dev->flags))) {
@@ -3205,7 +3573,7 @@ static void handle_stripe_dirtying(struct r5conf *conf,
        pr_debug("for sector %llu, rmw=%d rcw=%d\n",
                (unsigned long long)sh->sector, rmw, rcw);
        set_bit(STRIPE_HANDLE, &sh->state);
-       if (rmw < rcw && rmw > 0) {
+       if ((rmw < rcw || (rmw == rcw && conf->rmw_level == PARITY_ENABLE_RMW)) && rmw > 0) {
                /* prefer read-modify-write, but need to get some data */
                if (conf->mddev->queue)
                        blk_add_trace_msg(conf->mddev->queue,
@@ -3213,7 +3581,7 @@ static void handle_stripe_dirtying(struct r5conf *conf,
                                          (unsigned long long)sh->sector, rmw);
                for (i = disks; i--; ) {
                        struct r5dev *dev = &sh->dev[i];
-                       if ((dev->towrite || i == sh->pd_idx) &&
+                       if ((dev->towrite || i == sh->pd_idx || i == sh->qd_idx) &&
                            !test_bit(R5_LOCKED, &dev->flags) &&
                            !(test_bit(R5_UPTODATE, &dev->flags) ||
                            test_bit(R5_Wantcompute, &dev->flags)) &&
@@ -3232,7 +3600,7 @@ static void handle_stripe_dirtying(struct r5conf *conf,
                        }
                }
        }
-       if (rcw <= rmw && rcw > 0) {
+       if ((rcw < rmw || (rcw == rmw && conf->rmw_level != PARITY_ENABLE_RMW)) && rcw > 0) {
                /* want reconstruct write, but need to get some data */
                int qread =0;
                rcw = 0;
@@ -3290,6 +3658,7 @@ static void handle_parity_checks5(struct r5conf *conf, struct stripe_head *sh,
 {
        struct r5dev *dev = NULL;
 
+       BUG_ON(sh->batch_head);
        set_bit(STRIPE_HANDLE, &sh->state);
 
        switch (sh->check_state) {
@@ -3380,6 +3749,7 @@ static void handle_parity_checks6(struct r5conf *conf, struct stripe_head *sh,
        int qd_idx = sh->qd_idx;
        struct r5dev *dev;
 
+       BUG_ON(sh->batch_head);
        set_bit(STRIPE_HANDLE, &sh->state);
 
        BUG_ON(s->failed > 2);
@@ -3543,6 +3913,7 @@ static void handle_stripe_expansion(struct r5conf *conf, struct stripe_head *sh)
         * copy some of them into a target stripe for expand.
         */
        struct dma_async_tx_descriptor *tx = NULL;
+       BUG_ON(sh->batch_head);
        clear_bit(STRIPE_EXPAND_SOURCE, &sh->state);
        for (i = 0; i < sh->disks; i++)
                if (i != sh->pd_idx && i != sh->qd_idx) {
@@ -3615,8 +3986,8 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s)
 
        memset(s, 0, sizeof(*s));
 
-       s->expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state);
-       s->expanded = test_bit(STRIPE_EXPAND_READY, &sh->state);
+       s->expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state) && !sh->batch_head;
+       s->expanded = test_bit(STRIPE_EXPAND_READY, &sh->state) && !sh->batch_head;
        s->failed_num[0] = -1;
        s->failed_num[1] = -1;
 
@@ -3786,6 +4157,80 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s)
        rcu_read_unlock();
 }
 
+static int clear_batch_ready(struct stripe_head *sh)
+{
+       struct stripe_head *tmp;
+       if (!test_and_clear_bit(STRIPE_BATCH_READY, &sh->state))
+               return 0;
+       spin_lock(&sh->stripe_lock);
+       if (!sh->batch_head) {
+               spin_unlock(&sh->stripe_lock);
+               return 0;
+       }
+
+       /*
+        * this stripe could be added to a batch list before we check
+        * BATCH_READY, skips it
+        */
+       if (sh->batch_head != sh) {
+               spin_unlock(&sh->stripe_lock);
+               return 1;
+       }
+       spin_lock(&sh->batch_lock);
+       list_for_each_entry(tmp, &sh->batch_list, batch_list)
+               clear_bit(STRIPE_BATCH_READY, &tmp->state);
+       spin_unlock(&sh->batch_lock);
+       spin_unlock(&sh->stripe_lock);
+
+       /*
+        * BATCH_READY is cleared, no new stripes can be added.
+        * batch_list can be accessed without lock
+        */
+       return 0;
+}
+
+static void check_break_stripe_batch_list(struct stripe_head *sh)
+{
+       struct stripe_head *head_sh, *next;
+       int i;
+
+       if (!test_and_clear_bit(STRIPE_BATCH_ERR, &sh->state))
+               return;
+
+       head_sh = sh;
+       do {
+               sh = list_first_entry(&sh->batch_list,
+                                     struct stripe_head, batch_list);
+               BUG_ON(sh == head_sh);
+       } while (!test_bit(STRIPE_DEGRADED, &sh->state));
+
+       while (sh != head_sh) {
+               next = list_first_entry(&sh->batch_list,
+                                       struct stripe_head, batch_list);
+               list_del_init(&sh->batch_list);
+
+               set_mask_bits(&sh->state, ~STRIPE_EXPAND_SYNC_FLAG,
+                             head_sh->state & ~((1 << STRIPE_ACTIVE) |
+                                                (1 << STRIPE_PREREAD_ACTIVE) |
+                                                (1 << STRIPE_DEGRADED) |
+                                                STRIPE_EXPAND_SYNC_FLAG));
+               sh->check_state = head_sh->check_state;
+               sh->reconstruct_state = head_sh->reconstruct_state;
+               for (i = 0; i < sh->disks; i++)
+                       sh->dev[i].flags = head_sh->dev[i].flags &
+                               (~((1 << R5_WriteError) | (1 << R5_Overlap)));
+
+               spin_lock_irq(&sh->stripe_lock);
+               sh->batch_head = NULL;
+               spin_unlock_irq(&sh->stripe_lock);
+
+               set_bit(STRIPE_HANDLE, &sh->state);
+               release_stripe(sh);
+
+               sh = next;
+       }
+}
+
 static void handle_stripe(struct stripe_head *sh)
 {
        struct stripe_head_state s;
@@ -3803,7 +4248,14 @@ static void handle_stripe(struct stripe_head *sh)
                return;
        }
 
-       if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state)) {
+       if (clear_batch_ready(sh) ) {
+               clear_bit_unlock(STRIPE_ACTIVE, &sh->state);
+               return;
+       }
+
+       check_break_stripe_batch_list(sh);
+
+       if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state) && !sh->batch_head) {
                spin_lock(&sh->stripe_lock);
                /* Cannot process 'sync' concurrently with 'discard' */
                if (!test_bit(STRIPE_DISCARD, &sh->state) &&
@@ -4158,7 +4610,7 @@ static int raid5_congested(struct mddev *mddev, int bits)
         * how busy the stripe_cache is
         */
 
-       if (conf->inactive_blocked)
+       if (test_bit(R5_INACTIVE_BLOCKED, &conf->cache_state))
                return 1;
        if (conf->quiesce)
                return 1;
@@ -4180,8 +4632,12 @@ static int raid5_mergeable_bvec(struct mddev *mddev,
        unsigned int chunk_sectors = mddev->chunk_sectors;
        unsigned int bio_sectors = bvm->bi_size >> 9;
 
-       if ((bvm->bi_rw & 1) == WRITE)
-               return biovec->bv_len; /* always allow writes to be mergeable */
+       /*
+        * always allow writes to be mergeable, read as well if array
+        * is degraded as we'll go through stripe cache anyway.
+        */
+       if ((bvm->bi_rw & 1) == WRITE || mddev->degraded)
+               return biovec->bv_len;
 
        if (mddev->new_chunk_sectors < mddev->chunk_sectors)
                chunk_sectors = mddev->new_chunk_sectors;
@@ -4603,12 +5059,14 @@ static void make_discard_request(struct mddev *mddev, struct bio *bi)
                }
                set_bit(STRIPE_DISCARD, &sh->state);
                finish_wait(&conf->wait_for_overlap, &w);
+               sh->overwrite_disks = 0;
                for (d = 0; d < conf->raid_disks; d++) {
                        if (d == sh->pd_idx || d == sh->qd_idx)
                                continue;
                        sh->dev[d].towrite = bi;
                        set_bit(R5_OVERWRITE, &sh->dev[d].flags);
                        raid5_inc_bi_active_stripes(bi);
+                       sh->overwrite_disks++;
                }
                spin_unlock_irq(&sh->stripe_lock);
                if (conf->mddev->bitmap) {
@@ -4656,7 +5114,12 @@ static void make_request(struct mddev *mddev, struct bio * bi)
 
        md_write_start(mddev, bi);
 
-       if (rw == READ &&
+       /*
+        * If array is degraded, better not do chunk aligned read because
+        * later we might have to read it again in order to reconstruct
+        * data on failed drives.
+        */
+       if (rw == READ && mddev->degraded == 0 &&
             mddev->reshape_position == MaxSector &&
             chunk_aligned_read(mddev,bi))
                return;
@@ -4772,7 +5235,7 @@ static void make_request(struct mddev *mddev, struct bio * bi)
                        }
 
                        if (test_bit(STRIPE_EXPANDING, &sh->state) ||
-                           !add_stripe_bio(sh, bi, dd_idx, rw)) {
+                           !add_stripe_bio(sh, bi, dd_idx, rw, previous)) {
                                /* Stripe is busy expanding or
                                 * add failed due to overlap.  Flush everything
                                 * and wait a while
@@ -4785,7 +5248,8 @@ static void make_request(struct mddev *mddev, struct bio * bi)
                        }
                        set_bit(STRIPE_HANDLE, &sh->state);
                        clear_bit(STRIPE_DELAYED, &sh->state);
-                       if ((bi->bi_rw & REQ_SYNC) &&
+                       if ((!sh->batch_head || sh == sh->batch_head) &&
+                           (bi->bi_rw & REQ_SYNC) &&
                            !test_and_set_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
                                atomic_inc(&conf->preread_active_stripes);
                        release_stripe_plug(mddev, sh);
@@ -5050,8 +5514,7 @@ ret:
        return reshape_sectors;
 }
 
-/* FIXME go_faster isn't used */
-static inline sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipped, int go_faster)
+static inline sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipped)
 {
        struct r5conf *conf = mddev->private;
        struct stripe_head *sh;
@@ -5186,7 +5649,7 @@ static int  retry_aligned_read(struct r5conf *conf, struct bio *raid_bio)
                        return handled;
                }
 
-               if (!add_stripe_bio(sh, raid_bio, dd_idx, 0)) {
+               if (!add_stripe_bio(sh, raid_bio, dd_idx, 0, 0)) {
                        release_stripe(sh);
                        raid5_set_bi_processed_stripes(raid_bio, scnt);
                        conf->retry_read_aligned = raid_bio;
@@ -5312,6 +5775,8 @@ static void raid5d(struct md_thread *thread)
                int batch_size, released;
 
                released = release_stripe_list(conf, conf->temp_inactive_list);
+               if (released)
+                       clear_bit(R5_DID_ALLOC, &conf->cache_state);
 
                if (
                    !list_empty(&conf->bitmap_list)) {
@@ -5350,6 +5815,13 @@ static void raid5d(struct md_thread *thread)
        pr_debug("%d stripes handled\n", handled);
 
        spin_unlock_irq(&conf->device_lock);
+       if (test_and_clear_bit(R5_ALLOC_MORE, &conf->cache_state)) {
+               grow_one_stripe(conf, __GFP_NOWARN);
+               /* Set flag even if allocation failed.  This helps
+                * slow down allocation requests when mem is short
+                */
+               set_bit(R5_DID_ALLOC, &conf->cache_state);
+       }
 
        async_tx_issue_pending_all();
        blk_finish_plug(&plug);
@@ -5365,7 +5837,7 @@ raid5_show_stripe_cache_size(struct mddev *mddev, char *page)
        spin_lock(&mddev->lock);
        conf = mddev->private;
        if (conf)
-               ret = sprintf(page, "%d\n", conf->max_nr_stripes);
+               ret = sprintf(page, "%d\n", conf->min_nr_stripes);
        spin_unlock(&mddev->lock);
        return ret;
 }
@@ -5375,30 +5847,24 @@ raid5_set_cache_size(struct mddev *mddev, int size)
 {
        struct r5conf *conf = mddev->private;
        int err;
-       int hash;
 
        if (size <= 16 || size > 32768)
                return -EINVAL;
-       hash = (conf->max_nr_stripes - 1) % NR_STRIPE_HASH_LOCKS;
-       while (size < conf->max_nr_stripes) {
-               if (drop_one_stripe(conf, hash))
-                       conf->max_nr_stripes--;
-               else
-                       break;
-               hash--;
-               if (hash < 0)
-                       hash = NR_STRIPE_HASH_LOCKS - 1;
-       }
+
+       conf->min_nr_stripes = size;
+       while (size < conf->max_nr_stripes &&
+              drop_one_stripe(conf))
+               ;
+
+
        err = md_allow_write(mddev);
        if (err)
                return err;
-       hash = conf->max_nr_stripes % NR_STRIPE_HASH_LOCKS;
-       while (size > conf->max_nr_stripes) {
-               if (grow_one_stripe(conf, hash))
-                       conf->max_nr_stripes++;
-               else break;
-               hash = (hash + 1) % NR_STRIPE_HASH_LOCKS;
-       }
+
+       while (size > conf->max_nr_stripes)
+               if (!grow_one_stripe(conf, GFP_KERNEL))
+                       break;
+
        return 0;
 }
 EXPORT_SYMBOL(raid5_set_cache_size);
@@ -5432,6 +5898,49 @@ raid5_stripecache_size = __ATTR(stripe_cache_size, S_IRUGO | S_IWUSR,
                                raid5_show_stripe_cache_size,
                                raid5_store_stripe_cache_size);
 
+static ssize_t
+raid5_show_rmw_level(struct mddev  *mddev, char *page)
+{
+       struct r5conf *conf = mddev->private;
+       if (conf)
+               return sprintf(page, "%d\n", conf->rmw_level);
+       else
+               return 0;
+}
+
+static ssize_t
+raid5_store_rmw_level(struct mddev  *mddev, const char *page, size_t len)
+{
+       struct r5conf *conf = mddev->private;
+       unsigned long new;
+
+       if (!conf)
+               return -ENODEV;
+
+       if (len >= PAGE_SIZE)
+               return -EINVAL;
+
+       if (kstrtoul(page, 10, &new))
+               return -EINVAL;
+
+       if (new != PARITY_DISABLE_RMW && !raid6_call.xor_syndrome)
+               return -EINVAL;
+
+       if (new != PARITY_DISABLE_RMW &&
+           new != PARITY_ENABLE_RMW &&
+           new != PARITY_PREFER_RMW)
+               return -EINVAL;
+
+       conf->rmw_level = new;
+       return len;
+}
+
+static struct md_sysfs_entry
+raid5_rmw_level = __ATTR(rmw_level, S_IRUGO | S_IWUSR,
+                        raid5_show_rmw_level,
+                        raid5_store_rmw_level);
+
+
 static ssize_t
 raid5_show_preread_threshold(struct mddev *mddev, char *page)
 {
@@ -5463,7 +5972,7 @@ raid5_store_preread_threshold(struct mddev *mddev, const char *page, size_t len)
        conf = mddev->private;
        if (!conf)
                err = -ENODEV;
-       else if (new > conf->max_nr_stripes)
+       else if (new > conf->min_nr_stripes)
                err = -EINVAL;
        else
                conf->bypass_threshold = new;
@@ -5618,6 +6127,7 @@ static struct attribute *raid5_attrs[] =  {
        &raid5_preread_bypass_threshold.attr,
        &raid5_group_thread_cnt.attr,
        &raid5_skip_copy.attr,
+       &raid5_rmw_level.attr,
        NULL,
 };
 static struct attribute_group raid5_attrs_group = {
@@ -5699,7 +6209,8 @@ raid5_size(struct mddev *mddev, sector_t sectors, int raid_disks)
 static void free_scratch_buffer(struct r5conf *conf, struct raid5_percpu *percpu)
 {
        safe_put_page(percpu->spare_page);
-       kfree(percpu->scribble);
+       if (percpu->scribble)
+               flex_array_free(percpu->scribble);
        percpu->spare_page = NULL;
        percpu->scribble = NULL;
 }
@@ -5709,7 +6220,9 @@ static int alloc_scratch_buffer(struct r5conf *conf, struct raid5_percpu *percpu
        if (conf->level == 6 && !percpu->spare_page)
                percpu->spare_page = alloc_page(GFP_KERNEL);
        if (!percpu->scribble)
-               percpu->scribble = kmalloc(conf->scribble_len, GFP_KERNEL);
+               percpu->scribble = scribble_alloc(max(conf->raid_disks,
+                       conf->previous_raid_disks), conf->chunk_sectors /
+                       STRIPE_SECTORS, GFP_KERNEL);
 
        if (!percpu->scribble || (conf->level == 6 && !percpu->spare_page)) {
                free_scratch_buffer(conf, percpu);
@@ -5740,6 +6253,8 @@ static void raid5_free_percpu(struct r5conf *conf)
 
 static void free_conf(struct r5conf *conf)
 {
+       if (conf->shrinker.seeks)
+               unregister_shrinker(&conf->shrinker);
        free_thread_groups(conf);
        shrink_stripes(conf);
        raid5_free_percpu(conf);
@@ -5807,6 +6322,30 @@ static int raid5_alloc_percpu(struct r5conf *conf)
        return err;
 }
 
+static unsigned long raid5_cache_scan(struct shrinker *shrink,
+                                     struct shrink_control *sc)
+{
+       struct r5conf *conf = container_of(shrink, struct r5conf, shrinker);
+       int ret = 0;
+       while (ret < sc->nr_to_scan) {
+               if (drop_one_stripe(conf) == 0)
+                       return SHRINK_STOP;
+               ret++;
+       }
+       return ret;
+}
+
+static unsigned long raid5_cache_count(struct shrinker *shrink,
+                                      struct shrink_control *sc)
+{
+       struct r5conf *conf = container_of(shrink, struct r5conf, shrinker);
+
+       if (conf->max_nr_stripes < conf->min_nr_stripes)
+               /* unlikely, but not impossible */
+               return 0;
+       return conf->max_nr_stripes - conf->min_nr_stripes;
+}
+
 static struct r5conf *setup_conf(struct mddev *mddev)
 {
        struct r5conf *conf;
@@ -5879,7 +6418,6 @@ static struct r5conf *setup_conf(struct mddev *mddev)
        else
                conf->previous_raid_disks = mddev->raid_disks - mddev->delta_disks;
        max_disks = max(conf->raid_disks, conf->previous_raid_disks);
-       conf->scribble_len = scribble_len(max_disks);
 
        conf->disks = kzalloc(max_disks * sizeof(struct disk_info),
                              GFP_KERNEL);
@@ -5907,6 +6445,7 @@ static struct r5conf *setup_conf(struct mddev *mddev)
                INIT_LIST_HEAD(conf->temp_inactive_list + i);
 
        conf->level = mddev->new_level;
+       conf->chunk_sectors = mddev->new_chunk_sectors;
        if (raid5_alloc_percpu(conf) != 0)
                goto abort;
 
@@ -5939,12 +6478,17 @@ static struct r5conf *setup_conf(struct mddev *mddev)
                        conf->fullsync = 1;
        }
 
-       conf->chunk_sectors = mddev->new_chunk_sectors;
        conf->level = mddev->new_level;
-       if (conf->level == 6)
+       if (conf->level == 6) {
                conf->max_degraded = 2;
-       else
+               if (raid6_call.xor_syndrome)
+                       conf->rmw_level = PARITY_ENABLE_RMW;
+               else
+                       conf->rmw_level = PARITY_DISABLE_RMW;
+       } else {
                conf->max_degraded = 1;
+               conf->rmw_level = PARITY_ENABLE_RMW;
+       }
        conf->algorithm = mddev->new_layout;
        conf->reshape_progress = mddev->reshape_position;
        if (conf->reshape_progress != MaxSector) {
@@ -5952,10 +6496,11 @@ static struct r5conf *setup_conf(struct mddev *mddev)
                conf->prev_algo = mddev->layout;
        }
 
-       memory = conf->max_nr_stripes * (sizeof(struct stripe_head) +
+       conf->min_nr_stripes = NR_STRIPES;
+       memory = conf->min_nr_stripes * (sizeof(struct stripe_head) +
                 max_disks * ((sizeof(struct bio) + PAGE_SIZE))) / 1024;
        atomic_set(&conf->empty_inactive_list_nr, NR_STRIPE_HASH_LOCKS);
-       if (grow_stripes(conf, NR_STRIPES)) {
+       if (grow_stripes(conf, conf->min_nr_stripes)) {
                printk(KERN_ERR
                       "md/raid:%s: couldn't allocate %dkB for buffers\n",
                       mdname(mddev), memory);
@@ -5963,6 +6508,17 @@ static struct r5conf *setup_conf(struct mddev *mddev)
        } else
                printk(KERN_INFO "md/raid:%s: allocated %dkB\n",
                       mdname(mddev), memory);
+       /*
+        * Losing a stripe head costs more than the time to refill it,
+        * it reduces the queue depth and so can hurt throughput.
+        * So set it rather large, scaled by number of devices.
+        */
+       conf->shrinker.seeks = DEFAULT_SEEKS * conf->raid_disks * 4;
+       conf->shrinker.scan_objects = raid5_cache_scan;
+       conf->shrinker.count_objects = raid5_cache_count;
+       conf->shrinker.batch = 128;
+       conf->shrinker.flags = 0;
+       register_shrinker(&conf->shrinker);
 
        sprintf(pers_name, "raid%d", mddev->new_level);
        conf->thread = md_register_thread(raid5d, mddev, pers_name);
@@ -6604,9 +7160,9 @@ static int check_stripe_cache(struct mddev *mddev)
         */
        struct r5conf *conf = mddev->private;
        if (((mddev->chunk_sectors << 9) / STRIPE_SIZE) * 4
-           > conf->max_nr_stripes ||
+           > conf->min_nr_stripes ||
            ((mddev->new_chunk_sectors << 9) / STRIPE_SIZE) * 4
-           > conf->max_nr_stripes) {
+           > conf->min_nr_stripes) {
                printk(KERN_WARNING "md/raid:%s: reshape: not enough stripes.  Needed %lu\n",
                       mdname(mddev),
                       ((max(mddev->chunk_sectors, mddev->new_chunk_sectors) << 9)
index 983e18a83db138e4f99079e45159df39285d3b80..7dc0dd86074b1702276ccb51ba166a38d5d0f7e3 100644 (file)
@@ -210,11 +210,19 @@ struct stripe_head {
        atomic_t                count;        /* nr of active thread/requests */
        int                     bm_seq; /* sequence number for bitmap flushes */
        int                     disks;          /* disks in stripe */
+       int                     overwrite_disks; /* total overwrite disks in stripe,
+                                                 * this is only checked when stripe
+                                                 * has STRIPE_BATCH_READY
+                                                 */
        enum check_states       check_state;
        enum reconstruct_states reconstruct_state;
        spinlock_t              stripe_lock;
        int                     cpu;
        struct r5worker_group   *group;
+
+       struct stripe_head      *batch_head; /* protected by stripe lock */
+       spinlock_t              batch_lock; /* only header's lock is useful */
+       struct list_head        batch_list; /* protected by head's batch lock*/
        /**
         * struct stripe_operations
         * @target - STRIPE_OP_COMPUTE_BLK target
@@ -327,8 +335,15 @@ enum {
        STRIPE_ON_UNPLUG_LIST,
        STRIPE_DISCARD,
        STRIPE_ON_RELEASE_LIST,
+       STRIPE_BATCH_READY,
+       STRIPE_BATCH_ERR,
 };
 
+#define STRIPE_EXPAND_SYNC_FLAG \
+       ((1 << STRIPE_EXPAND_SOURCE) |\
+       (1 << STRIPE_EXPAND_READY) |\
+       (1 << STRIPE_EXPANDING) |\
+       (1 << STRIPE_SYNC_REQUESTED))
 /*
  * Operation request flags
  */
@@ -340,6 +355,24 @@ enum {
        STRIPE_OP_RECONSTRUCT,
        STRIPE_OP_CHECK,
 };
+
+/*
+ * RAID parity calculation preferences
+ */
+enum {
+       PARITY_DISABLE_RMW = 0,
+       PARITY_ENABLE_RMW,
+       PARITY_PREFER_RMW,
+};
+
+/*
+ * Pages requested from set_syndrome_sources()
+ */
+enum {
+       SYNDROME_SRC_ALL,
+       SYNDROME_SRC_WANT_DRAIN,
+       SYNDROME_SRC_WRITTEN,
+};
 /*
  * Plugging:
  *
@@ -396,10 +429,11 @@ struct r5conf {
        spinlock_t              hash_locks[NR_STRIPE_HASH_LOCKS];
        struct mddev            *mddev;
        int                     chunk_sectors;
-       int                     level, algorithm;
+       int                     level, algorithm, rmw_level;
        int                     max_degraded;
        int                     raid_disks;
        int                     max_nr_stripes;
+       int                     min_nr_stripes;
 
        /* reshape_progress is the leading edge of a 'reshape'
         * It has value MaxSector when no reshape is happening
@@ -458,15 +492,11 @@ struct r5conf {
        /* per cpu variables */
        struct raid5_percpu {
                struct page     *spare_page; /* Used when checking P/Q in raid6 */
-               void            *scribble;   /* space for constructing buffer
+               struct flex_array *scribble;   /* space for constructing buffer
                                              * lists and performing address
                                              * conversions
                                              */
        } __percpu *percpu;
-       size_t                  scribble_len; /* size of scribble region must be
-                                              * associated with conf to handle
-                                              * cpu hotplug while reshaping
-                                              */
 #ifdef CONFIG_HOTPLUG_CPU
        struct notifier_block   cpu_notify;
 #endif
@@ -480,9 +510,19 @@ struct r5conf {
        struct llist_head       released_stripes;
        wait_queue_head_t       wait_for_stripe;
        wait_queue_head_t       wait_for_overlap;
-       int                     inactive_blocked;       /* release of inactive stripes blocked,
-                                                        * waiting for 25% to be free
-                                                        */
+       unsigned long           cache_state;
+#define R5_INACTIVE_BLOCKED    1       /* release of inactive stripes blocked,
+                                        * waiting for 25% to be free
+                                        */
+#define R5_ALLOC_MORE          2       /* It might help to allocate another
+                                        * stripe.
+                                        */
+#define R5_DID_ALLOC           4       /* A stripe was allocated, don't allocate
+                                        * more until at least one has been
+                                        * released.  This avoids flooding
+                                        * the cache.
+                                        */
+       struct shrinker         shrinker;
        int                     pool_size; /* number of disks in stripeheads in pool */
        spinlock_t              device_lock;
        struct disk_info        *disks;
@@ -497,6 +537,7 @@ struct r5conf {
        int                     worker_cnt_per_group;
 };
 
+
 /*
  * Our supported algorithms
  */
index 49cd30870e0d6ff6fb293fc33fd0af850cd6590c..3ef0f90b128fc5bdf6d5e5dff0d5bbfbd5190d7b 100644 (file)
@@ -87,13 +87,21 @@ config MEDIA_RC_SUPPORT
 
 config MEDIA_CONTROLLER
        bool "Media Controller API"
-       depends on MEDIA_CAMERA_SUPPORT
+       depends on MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT
        ---help---
          Enable the media controller API used to query media devices internal
          topology and configure it dynamically.
 
          This API is mostly used by camera interfaces in embedded platforms.
 
+config MEDIA_CONTROLLER_DVB
+       bool "Enable Media controller for DVB"
+       depends on MEDIA_CONTROLLER
+       ---help---
+         Enable the media controller API support for DVB.
+
+         This is currently experimental.
+
 #
 # Video4Linux support
 #      Only enables if one of the V4L2 types (ATV, webcam, radio) is selected
index b7d63933dae61a6adbac2d95edfe1bb19c6aacf1..df1e8c975cd82d97b6b5d9bb4edf0e2db7f006bd 100644 (file)
@@ -587,26 +587,20 @@ int saa7146_vv_release(struct saa7146_dev* dev)
 }
 EXPORT_SYMBOL_GPL(saa7146_vv_release);
 
-int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
+int saa7146_register_device(struct video_device *vfd, struct saa7146_dev *dev,
                            char *name, int type)
 {
-       struct video_device *vfd;
        int err;
        int i;
 
        DEB_EE("dev:%p, name:'%s', type:%d\n", dev, name, type);
 
-       // released by vfd->release
-       vfd = video_device_alloc();
-       if (vfd == NULL)
-               return -ENOMEM;
-
        vfd->fops = &video_fops;
        if (type == VFL_TYPE_GRABBER)
                vfd->ioctl_ops = &dev->ext_vv_data->vid_ops;
        else
                vfd->ioctl_ops = &dev->ext_vv_data->vbi_ops;
-       vfd->release = video_device_release;
+       vfd->release = video_device_release_empty;
        vfd->lock = &dev->v4l2_lock;
        vfd->v4l2_dev = &dev->v4l2_dev;
        vfd->tvnorms = 0;
@@ -618,25 +612,20 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
        err = video_register_device(vfd, type, -1);
        if (err < 0) {
                ERR("cannot register v4l2 device. skipping.\n");
-               video_device_release(vfd);
                return err;
        }
 
        pr_info("%s: registered device %s [v4l2]\n",
                dev->name, video_device_node_name(vfd));
-
-       *vid = vfd;
        return 0;
 }
 EXPORT_SYMBOL_GPL(saa7146_register_device);
 
-int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev)
+int saa7146_unregister_device(struct video_device *vfd, struct saa7146_dev *dev)
 {
        DEB_EE("dev:%p\n", dev);
 
-       video_unregister_device(*vid);
-       *vid = NULL;
-
+       video_unregister_device(vfd);
        return 0;
 }
 EXPORT_SYMBOL_GPL(saa7146_unregister_device);
index 1e71e374bbfebe8b0eecc30d1516ccd983108059..2da99575877802157f0e20358419cee638f1af00 100644 (file)
@@ -95,7 +95,7 @@ static int vbi_workaround(struct saa7146_dev *dev)
 
                /* prepare to wait to be woken up by the irq-handler */
                add_wait_queue(&vv->vbi_wq, &wait);
-               current->state = TASK_INTERRUPTIBLE;
+               set_current_state(TASK_INTERRUPTIBLE);
 
                /* start rps1 to enable workaround */
                saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
@@ -106,7 +106,7 @@ static int vbi_workaround(struct saa7146_dev *dev)
                DEB_VBI("brs bug workaround %d/1\n", i);
 
                remove_wait_queue(&vv->vbi_wq, &wait);
-               current->state = TASK_RUNNING;
+               __set_current_state(TASK_RUNNING);
 
                /* disable rps1 irqs */
                SAA7146_IER_DISABLE(dev,MASK_28);
index 82c7a1289f053313bb7f866bb08a9288e2a67db6..ca2f80c7740cd62baa90ff8511a07a02015b55f7 100644 (file)
 #include "smsir.h"
 #include <linux/module.h>
 
-static int sms_dbg;
-module_param_named(cards_dbg, sms_dbg, int, 0644);
-MODULE_PARM_DESC(cards_dbg, "set debug level (info=1, adv=2 (or-able))");
-
 static struct sms_board sms_boards[] = {
        [SMS_BOARD_UNKNOWN] = {
                .name   = "Unknown board",
@@ -232,7 +228,7 @@ int sms_board_event(struct smscore_device_t *coredev,
                break; /* BOARD_EVENT_MULTIPLEX_ERRORS */
 
        default:
-               sms_err("Unknown SMS board event");
+               pr_err("Unknown SMS board event\n");
                break;
        }
        return 0;
@@ -342,7 +338,7 @@ int sms_board_lna_control(struct smscore_device_t *coredev, int onoff)
        int board_id = smscore_get_board_id(coredev);
        struct sms_board *board = sms_get_board(board_id);
 
-       sms_debug("%s: LNA %s", __func__, onoff ? "enabled" : "disabled");
+       pr_debug("%s: LNA %s\n", __func__, onoff ? "enabled" : "disabled");
 
        switch (board_id) {
        case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
index 4c4caddf986984e2aa94ce2da8bf7f1229718767..bb3d733f092b5b79b0ac69181095fcb3ac689d39 100644 (file)
@@ -20,8 +20,9 @@
 #ifndef __SMS_CARDS_H__
 #define __SMS_CARDS_H__
 
-#include <linux/usb.h>
 #include "smscoreapi.h"
+
+#include <linux/usb.h>
 #include "smsir.h"
 
 #define SMS_BOARD_UNKNOWN 0
index a3677438205e8c88824e6f10f854168755725da9..2a8d9a36d6f02c27f1bcabaea018fc72b60a0ac6 100644 (file)
@@ -21,6 +21,8 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include "smscoreapi.h"
+
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/wait.h>
 #include <asm/byteorder.h>
 
-#include "smscoreapi.h"
 #include "sms-cards.h"
 #include "smsir.h"
 
-static int sms_dbg;
-module_param_named(debug, sms_dbg, int, 0644);
-MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
-
 struct smscore_device_notifyee_t {
        struct list_head entry;
        hotplug_t hotplug;
@@ -460,7 +457,7 @@ static struct smscore_registry_entry_t *smscore_find_registry(char *devpath)
                strcpy(entry->devpath, devpath);
                list_add(&entry->entry, &g_smscore_registry);
        } else
-               sms_err("failed to create smscore_registry.");
+               pr_err("failed to create smscore_registry.\n");
        kmutex_unlock(&g_smscore_registrylock);
        return entry;
 }
@@ -473,7 +470,7 @@ int smscore_registry_getmode(char *devpath)
        if (entry)
                return entry->mode;
        else
-               sms_err("No registry found.");
+               pr_err("No registry found.\n");
 
        return default_mode;
 }
@@ -487,7 +484,7 @@ static enum sms_device_type_st smscore_registry_gettype(char *devpath)
        if (entry)
                return entry->type;
        else
-               sms_err("No registry found.");
+               pr_err("No registry found.\n");
 
        return -EINVAL;
 }
@@ -500,7 +497,7 @@ static void smscore_registry_setmode(char *devpath, int mode)
        if (entry)
                entry->mode = mode;
        else
-               sms_err("No registry found.");
+               pr_err("No registry found.\n");
 }
 
 static void smscore_registry_settype(char *devpath,
@@ -512,7 +509,7 @@ static void smscore_registry_settype(char *devpath,
        if (entry)
                entry->type = type;
        else
-               sms_err("No registry found.");
+               pr_err("No registry found.\n");
 }
 
 
@@ -635,10 +632,8 @@ smscore_buffer_t *smscore_createbuffer(u8 *buffer, void *common_buffer,
        struct smscore_buffer_t *cb;
 
        cb = kzalloc(sizeof(struct smscore_buffer_t), GFP_KERNEL);
-       if (!cb) {
-               sms_info("kzalloc(...) failed");
+       if (!cb)
                return NULL;
-       }
 
        cb->p = buffer;
        cb->offset_in_common = buffer - (u8 *) common_buffer;
@@ -658,16 +653,19 @@ smscore_buffer_t *smscore_createbuffer(u8 *buffer, void *common_buffer,
  * @return 0 on success, <0 on error.
  */
 int smscore_register_device(struct smsdevice_params_t *params,
-                           struct smscore_device_t **coredev)
+                           struct smscore_device_t **coredev,
+                           void *mdev)
 {
        struct smscore_device_t *dev;
        u8 *buffer;
 
        dev = kzalloc(sizeof(struct smscore_device_t), GFP_KERNEL);
-       if (!dev) {
-               sms_info("kzalloc(...) failed");
+       if (!dev)
                return -ENOMEM;
-       }
+
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+       dev->media_dev = mdev;
+#endif
 
        /* init list entry so it could be safe in smscore_unregister_device */
        INIT_LIST_HEAD(&dev->entry);
@@ -722,7 +720,7 @@ int smscore_register_device(struct smsdevice_params_t *params,
                smscore_putbuffer(dev, cb);
        }
 
-       sms_info("allocated %d buffers", dev->num_buffers);
+       pr_debug("allocated %d buffers\n", dev->num_buffers);
 
        dev->mode = DEVICE_MODE_NONE;
        dev->board_id = SMS_BOARD_UNKNOWN;
@@ -746,7 +744,7 @@ int smscore_register_device(struct smsdevice_params_t *params,
 
        *coredev = dev;
 
-       sms_info("device %p created", dev);
+       pr_debug("device %p created\n", dev);
 
        return 0;
 }
@@ -763,7 +761,7 @@ static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev,
 
        rc = coredev->sendrequest_handler(coredev->context, buffer, size);
        if (rc < 0) {
-               sms_info("sendrequest returned error %d", rc);
+               pr_info("sendrequest returned error %d\n", rc);
                return rc;
        }
 
@@ -786,11 +784,11 @@ static int smscore_init_ir(struct smscore_device_t *coredev)
        coredev->ir.dev = NULL;
        ir_io = sms_get_board(smscore_get_board_id(coredev))->board_cfg.ir;
        if (ir_io) {/* only if IR port exist we use IR sub-module */
-               sms_info("IR loading");
+               pr_debug("IR loading\n");
                rc = sms_ir_init(coredev);
 
                if      (rc != 0)
-                       sms_err("Error initialization DTV IR sub-module");
+                       pr_err("Error initialization DTV IR sub-module\n");
                else {
                        buffer = kmalloc(sizeof(struct sms_msg_data2) +
                                                SMS_DMA_ALIGNMENT,
@@ -812,11 +810,10 @@ static int smscore_init_ir(struct smscore_device_t *coredev)
 
                                kfree(buffer);
                        } else
-                               sms_err
-                               ("Sending IR initialization message failed");
+                               pr_err("Sending IR initialization message failed\n");
                }
        } else
-               sms_info("IR port has not been detected");
+               pr_info("IR port has not been detected\n");
 
        return 0;
 }
@@ -835,13 +832,13 @@ static int smscore_configure_board(struct smscore_device_t *coredev)
 
        board = sms_get_board(coredev->board_id);
        if (!board) {
-               sms_err("no board configuration exist.");
+               pr_err("no board configuration exist.\n");
                return -EINVAL;
        }
 
        if (board->mtu) {
                struct sms_msg_data mtu_msg;
-               sms_debug("set max transmit unit %d", board->mtu);
+               pr_debug("set max transmit unit %d\n", board->mtu);
 
                mtu_msg.x_msg_header.msg_src_id = 0;
                mtu_msg.x_msg_header.msg_dst_id = HIF_TASK;
@@ -856,7 +853,7 @@ static int smscore_configure_board(struct smscore_device_t *coredev)
 
        if (board->crystal) {
                struct sms_msg_data crys_msg;
-               sms_debug("set crystal value %d", board->crystal);
+               pr_debug("set crystal value %d\n", board->crystal);
 
                SMS_INIT_MSG(&crys_msg.x_msg_header,
                                MSG_SMS_NEW_CRYSTAL_REQ,
@@ -890,12 +887,12 @@ int smscore_start_device(struct smscore_device_t *coredev)
 
        rc = smscore_set_device_mode(coredev, mode);
        if (rc < 0) {
-               sms_info("set device mode faile , rc %d", rc);
+               pr_info("set device mode failed , rc %d\n", rc);
                return rc;
        }
        rc = smscore_configure_board(coredev);
        if (rc < 0) {
-               sms_info("configure board failed , rc %d", rc);
+               pr_info("configure board failed , rc %d\n", rc);
                return rc;
        }
 
@@ -904,7 +901,7 @@ int smscore_start_device(struct smscore_device_t *coredev)
        rc = smscore_notify_callbacks(coredev, coredev->device, 1);
        smscore_init_ir(coredev);
 
-       sms_info("device %p started, rc %d", coredev, rc);
+       pr_debug("device %p started, rc %d\n", coredev, rc);
 
        kmutex_unlock(&g_smscore_deviceslock);
 
@@ -927,7 +924,7 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
 
        mem_address = firmware->start_address;
 
-       sms_info("loading FW to addr 0x%x size %d",
+       pr_debug("loading FW to addr 0x%x size %d\n",
                 mem_address, firmware->length);
        if (coredev->preload_handler) {
                rc = coredev->preload_handler(coredev->context);
@@ -941,14 +938,14 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
                return -ENOMEM;
 
        if (coredev->mode != DEVICE_MODE_NONE) {
-               sms_debug("sending reload command.");
+               pr_debug("sending reload command.\n");
                SMS_INIT_MSG(&msg->x_msg_header, MSG_SW_RELOAD_START_REQ,
                             sizeof(struct sms_msg_hdr));
                rc = smscore_sendrequest_and_wait(coredev, msg,
                                                  msg->x_msg_header.msg_length,
                                                  &coredev->reload_start_done);
                if (rc < 0) {
-                       sms_err("device reload failed, rc %d", rc);
+                       pr_err("device reload failed, rc %d\n", rc);
                        goto exit_fw_download;
                }
                mem_address = *(u32 *) &payload[20];
@@ -982,7 +979,7 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
        if (rc < 0)
                goto exit_fw_download;
 
-       sms_debug("sending MSG_SMS_DATA_VALIDITY_REQ expecting 0x%x",
+       pr_debug("sending MSG_SMS_DATA_VALIDITY_REQ expecting 0x%x\n",
                calc_checksum);
        SMS_INIT_MSG(&msg->x_msg_header, MSG_SMS_DATA_VALIDITY_REQ,
                        sizeof(msg->x_msg_header) +
@@ -1001,7 +998,7 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
                struct sms_msg_data *trigger_msg =
                        (struct sms_msg_data *) msg;
 
-               sms_debug("sending MSG_SMS_SWDOWNLOAD_TRIGGER_REQ");
+               pr_debug("sending MSG_SMS_SWDOWNLOAD_TRIGGER_REQ\n");
                SMS_INIT_MSG(&msg->x_msg_header,
                                MSG_SMS_SWDOWNLOAD_TRIGGER_REQ,
                                sizeof(struct sms_msg_hdr) +
@@ -1037,12 +1034,13 @@ exit_fw_download:
        kfree(msg);
 
        if (coredev->postload_handler) {
-               sms_debug("rc=%d, postload=0x%p", rc, coredev->postload_handler);
+               pr_debug("rc=%d, postload=0x%p\n",
+                        rc, coredev->postload_handler);
                if (rc >= 0)
                        return coredev->postload_handler(coredev->context);
        }
 
-       sms_debug("rc=%d", rc);
+       pr_debug("rc=%d\n", rc);
        return rc;
 }
 
@@ -1121,11 +1119,11 @@ static char *smscore_get_fw_filename(struct smscore_device_t *coredev,
        if (mode <= DEVICE_MODE_NONE || mode >= DEVICE_MODE_MAX)
                return NULL;
 
-       sms_debug("trying to get fw name from sms_boards board_id %d mode %d",
+       pr_debug("trying to get fw name from sms_boards board_id %d mode %d\n",
                  board_id, mode);
        fw = sms_get_board(board_id)->fw;
        if (!fw || !fw[mode]) {
-               sms_debug("cannot find fw name in sms_boards, getting from lookup table mode %d type %d",
+               pr_debug("cannot find fw name in sms_boards, getting from lookup table mode %d type %d\n",
                          mode, type);
                return smscore_fw_lkup[type][mode];
        }
@@ -1154,10 +1152,10 @@ static int smscore_load_firmware_from_file(struct smscore_device_t *coredev,
 
        char *fw_filename = smscore_get_fw_filename(coredev, mode);
        if (!fw_filename) {
-               sms_err("mode %d not supported on this device", mode);
+               pr_err("mode %d not supported on this device\n", mode);
                return -ENOENT;
        }
-       sms_debug("Firmware name: %s", fw_filename);
+       pr_debug("Firmware name: %s\n", fw_filename);
 
        if (loadfirmware_handler == NULL && !(coredev->device_flags
                        & SMS_DEVICE_FAMILY2))
@@ -1165,14 +1163,14 @@ static int smscore_load_firmware_from_file(struct smscore_device_t *coredev,
 
        rc = request_firmware(&fw, fw_filename, coredev->device);
        if (rc < 0) {
-               sms_err("failed to open firmware file \"%s\"", fw_filename);
+               pr_err("failed to open firmware file '%s'\n", fw_filename);
                return rc;
        }
-       sms_info("read fw %s, buffer size=0x%zx", fw_filename, fw->size);
+       pr_debug("read fw %s, buffer size=0x%zx\n", fw_filename, fw->size);
        fw_buf = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT),
                         GFP_KERNEL | GFP_DMA);
        if (!fw_buf) {
-               sms_err("failed to allocate firmware buffer");
+               pr_err("failed to allocate firmware buffer\n");
                rc = -ENOMEM;
        } else {
                memcpy(fw_buf, fw->data, fw->size);
@@ -1226,18 +1224,18 @@ void smscore_unregister_device(struct smscore_device_t *coredev)
                if (num_buffers == coredev->num_buffers)
                        break;
                if (++retry > 10) {
-                       sms_info("exiting although not all buffers released.");
+                       pr_info("exiting although not all buffers released.\n");
                        break;
                }
 
-               sms_info("waiting for %d buffer(s)",
+               pr_debug("waiting for %d buffer(s)\n",
                         coredev->num_buffers - num_buffers);
                kmutex_unlock(&g_smscore_deviceslock);
                msleep(100);
                kmutex_lock(&g_smscore_deviceslock);
        }
 
-       sms_info("freed %d buffers", num_buffers);
+       pr_debug("freed %d buffers\n", num_buffers);
 
        if (coredev->common_buffer)
                dma_free_coherent(NULL, coredev->common_buffer_size,
@@ -1250,7 +1248,7 @@ void smscore_unregister_device(struct smscore_device_t *coredev)
 
        kmutex_unlock(&g_smscore_deviceslock);
 
-       sms_info("device %p destroyed", coredev);
+       pr_debug("device %p destroyed\n", coredev);
 }
 EXPORT_SYMBOL_GPL(smscore_unregister_device);
 
@@ -1271,7 +1269,7 @@ static int smscore_detect_mode(struct smscore_device_t *coredev)
        rc = smscore_sendrequest_and_wait(coredev, msg, msg->msg_length,
                                          &coredev->version_ex_done);
        if (rc == -ETIME) {
-               sms_err("MSG_SMS_GET_VERSION_EX_REQ failed first try");
+               pr_err("MSG_SMS_GET_VERSION_EX_REQ failed first try\n");
 
                if (wait_for_completion_timeout(&coredev->resume_done,
                                                msecs_to_jiffies(5000))) {
@@ -1279,7 +1277,7 @@ static int smscore_detect_mode(struct smscore_device_t *coredev)
                                coredev, msg, msg->msg_length,
                                &coredev->version_ex_done);
                        if (rc < 0)
-                               sms_err("MSG_SMS_GET_VERSION_EX_REQ failed second try, rc %d",
+                               pr_err("MSG_SMS_GET_VERSION_EX_REQ failed second try, rc %d\n",
                                        rc);
                } else
                        rc = -ETIME;
@@ -1308,7 +1306,7 @@ static int smscore_init_device(struct smscore_device_t *coredev, int mode)
        buffer = kmalloc(sizeof(struct sms_msg_data) +
                        SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
        if (!buffer) {
-               sms_err("Could not allocate buffer for init device message.");
+               pr_err("Could not allocate buffer for init device message.\n");
                return -ENOMEM;
        }
 
@@ -1339,10 +1337,10 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
 {
        int rc = 0;
 
-       sms_debug("set device mode to %d", mode);
+       pr_debug("set device mode to %d\n", mode);
        if (coredev->device_flags & SMS_DEVICE_FAMILY2) {
                if (mode <= DEVICE_MODE_NONE || mode >= DEVICE_MODE_MAX) {
-                       sms_err("invalid mode specified %d", mode);
+                       pr_err("invalid mode specified %d\n", mode);
                        return -EINVAL;
                }
 
@@ -1351,13 +1349,13 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
                if (!(coredev->device_flags & SMS_DEVICE_NOT_READY)) {
                        rc = smscore_detect_mode(coredev);
                        if (rc < 0) {
-                               sms_err("mode detect failed %d", rc);
+                               pr_err("mode detect failed %d\n", rc);
                                return rc;
                        }
                }
 
                if (coredev->mode == mode) {
-                       sms_info("device mode %d already set", mode);
+                       pr_debug("device mode %d already set\n", mode);
                        return 0;
                }
 
@@ -1365,19 +1363,19 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
                        rc = smscore_load_firmware_from_file(coredev,
                                                             mode, NULL);
                        if (rc >= 0)
-                               sms_info("firmware download success");
+                               pr_debug("firmware download success\n");
                } else {
-                       sms_info("mode %d is already supported by running firmware",
+                       pr_debug("mode %d is already supported by running firmware\n",
                                 mode);
                }
                if (coredev->fw_version >= 0x800) {
                        rc = smscore_init_device(coredev, mode);
                        if (rc < 0)
-                               sms_err("device init failed, rc %d.", rc);
+                               pr_err("device init failed, rc %d.\n", rc);
                }
        } else {
                if (mode <= DEVICE_MODE_NONE || mode >= DEVICE_MODE_MAX) {
-                       sms_err("invalid mode specified %d", mode);
+                       pr_err("invalid mode specified %d\n", mode);
                        return -EINVAL;
                }
 
@@ -1414,9 +1412,9 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
        }
 
        if (rc < 0)
-               sms_err("return error code %d.", rc);
+               pr_err("return error code %d.\n", rc);
        else
-               sms_debug("Success setting device mode.");
+               pr_debug("Success setting device mode.\n");
 
        return rc;
 }
@@ -1495,7 +1493,7 @@ void smscore_onresponse(struct smscore_device_t *coredev,
                last_sample_time = time_now;
 
        if (time_now - last_sample_time > 10000) {
-               sms_debug("data rate %d bytes/secs",
+               pr_debug("data rate %d bytes/secs\n",
                          (int)((data_total * 1000) /
                                (time_now - last_sample_time)));
 
@@ -1539,7 +1537,7 @@ void smscore_onresponse(struct smscore_device_t *coredev,
                {
                        struct sms_version_res *ver =
                                (struct sms_version_res *) phdr;
-                       sms_debug("Firmware id %d prots 0x%x ver %d.%d",
+                       pr_debug("Firmware id %d prots 0x%x ver %d.%d\n",
                                  ver->firmware_id, ver->supported_protocols,
                                  ver->rom_ver_major, ver->rom_ver_minor);
 
@@ -1562,7 +1560,7 @@ void smscore_onresponse(struct smscore_device_t *coredev,
                {
                        struct sms_msg_data *validity = (struct sms_msg_data *) phdr;
 
-                       sms_debug("MSG_SMS_DATA_VALIDITY_RES, checksum = 0x%x",
+                       pr_debug("MSG_SMS_DATA_VALIDITY_RES, checksum = 0x%x\n",
                                validity->msg_data[0]);
                        complete(&coredev->data_validity_done);
                        break;
@@ -1588,7 +1586,7 @@ void smscore_onresponse(struct smscore_device_t *coredev,
                {
                        u32 *msgdata = (u32 *) phdr;
                        coredev->gpio_get_res = msgdata[1];
-                       sms_debug("gpio level %d",
+                       pr_debug("gpio level %d\n",
                                        coredev->gpio_get_res);
                        complete(&coredev->gpio_get_level_done);
                        break;
@@ -1615,7 +1613,7 @@ void smscore_onresponse(struct smscore_device_t *coredev,
                        break;
 
                default:
-                       sms_debug("message %s(%d) not handled.",
+                       pr_debug("message %s(%d) not handled.\n",
                                  smscore_translate_msg(phdr->msg_type),
                                  phdr->msg_type);
                        break;
@@ -1681,7 +1679,7 @@ static int smscore_validate_client(struct smscore_device_t *coredev,
        struct smscore_client_t *registered_client;
 
        if (!client) {
-               sms_err("bad parameter.");
+               pr_err("bad parameter.\n");
                return -EINVAL;
        }
        registered_client = smscore_find_client(coredev, data_type, id);
@@ -1689,12 +1687,12 @@ static int smscore_validate_client(struct smscore_device_t *coredev,
                return 0;
 
        if (registered_client) {
-               sms_err("The msg ID already registered to another client.");
+               pr_err("The msg ID already registered to another client.\n");
                return -EEXIST;
        }
        listentry = kzalloc(sizeof(struct smscore_idlist_t), GFP_KERNEL);
        if (!listentry) {
-               sms_err("Can't allocate memory for client id.");
+               pr_err("Can't allocate memory for client id.\n");
                return -ENOMEM;
        }
        listentry->id = id;
@@ -1726,13 +1724,13 @@ int smscore_register_client(struct smscore_device_t *coredev,
        /* check that no other channel with same parameters exists */
        if (smscore_find_client(coredev, params->data_type,
                                params->initial_id)) {
-               sms_err("Client already exist.");
+               pr_err("Client already exist.\n");
                return -EEXIST;
        }
 
        newclient = kzalloc(sizeof(struct smscore_client_t), GFP_KERNEL);
        if (!newclient) {
-               sms_err("Failed to allocate memory for client.");
+               pr_err("Failed to allocate memory for client.\n");
                return -ENOMEM;
        }
 
@@ -1746,7 +1744,7 @@ int smscore_register_client(struct smscore_device_t *coredev,
        smscore_validate_client(coredev, newclient, params->data_type,
                                params->initial_id);
        *client = newclient;
-       sms_debug("%p %d %d", params->context, params->data_type,
+       pr_debug("%p %d %d\n", params->context, params->data_type,
                  params->initial_id);
 
        return 0;
@@ -1775,7 +1773,7 @@ void smscore_unregister_client(struct smscore_client_t *client)
                kfree(identry);
        }
 
-       sms_info("%p", client->context);
+       pr_debug("%p\n", client->context);
 
        list_del(&client->entry);
        kfree(client);
@@ -1803,7 +1801,7 @@ int smsclient_sendrequest(struct smscore_client_t *client,
        int rc;
 
        if (client == NULL) {
-               sms_err("Got NULL client");
+               pr_err("Got NULL client\n");
                return -EINVAL;
        }
 
@@ -1811,7 +1809,7 @@ int smsclient_sendrequest(struct smscore_client_t *client,
 
        /* check that no other channel with same id exists */
        if (coredev == NULL) {
-               sms_err("Got NULL coredev");
+               pr_err("Got NULL coredev\n");
                return -EINVAL;
        }
 
@@ -2016,9 +2014,9 @@ int smscore_gpio_configure(struct smscore_device_t *coredev, u8 pin_num,
 
        if (rc != 0) {
                if (rc == -ETIME)
-                       sms_err("smscore_gpio_configure timeout");
+                       pr_err("smscore_gpio_configure timeout\n");
                else
-                       sms_err("smscore_gpio_configure error");
+                       pr_err("smscore_gpio_configure error\n");
        }
 free:
        kfree(buffer);
@@ -2065,9 +2063,9 @@ int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 pin_num,
 
        if (rc != 0) {
                if (rc == -ETIME)
-                       sms_err("smscore_gpio_set_level timeout");
+                       pr_err("smscore_gpio_set_level timeout\n");
                else
-                       sms_err("smscore_gpio_set_level error");
+                       pr_err("smscore_gpio_set_level error\n");
        }
        kfree(buffer);
 
@@ -2113,9 +2111,9 @@ int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 pin_num,
 
        if (rc != 0) {
                if (rc == -ETIME)
-                       sms_err("smscore_gpio_get_level timeout");
+                       pr_err("smscore_gpio_get_level timeout\n");
                else
-                       sms_err("smscore_gpio_get_level error");
+                       pr_err("smscore_gpio_get_level error\n");
        }
        kfree(buffer);
 
@@ -2163,7 +2161,7 @@ static void __exit smscore_module_exit(void)
        }
        kmutex_unlock(&g_smscore_registrylock);
 
-       sms_debug("");
+       pr_debug("\n");
 }
 
 module_init(smscore_module_init);
index 9c9063cd3208909d5840a7c2cc745d1bf124f542..eb8bd689b936621b95e4d02df534616d5a5afa85 100644 (file)
@@ -22,6 +22,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #ifndef __SMS_CORE_API_H__
 #define __SMS_CORE_API_H__
 
+#define pr_fmt(fmt) "%s:%s: " fmt, KBUILD_MODNAME, __func__
+
 #include <linux/device.h>
 #include <linux/list.h>
 #include <linux/mm.h>
@@ -31,6 +33,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include <linux/wait.h>
 #include <linux/timer.h>
 
+#include <media/media-device.h>
+
 #include <asm/page.h>
 
 #include "smsir.h"
@@ -215,6 +219,10 @@ struct smscore_device_t {
        bool is_usb_device;
 
        int led_state;
+
+#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
+       struct media_device *media_dev;
+#endif
 };
 
 /* GPIO definitions for antenna frequency domain control (SMS8021) */
@@ -1115,7 +1123,8 @@ extern int smscore_register_hotplug(hotplug_t hotplug);
 extern void smscore_unregister_hotplug(hotplug_t hotplug);
 
 extern int smscore_register_device(struct smsdevice_params_t *params,
-                                  struct smscore_device_t **coredev);
+                                  struct smscore_device_t **coredev,
+                                  void *mdev);
 extern void smscore_unregister_device(struct smscore_device_t *coredev);
 
 extern int smscore_start_device(struct smscore_device_t *coredev);
@@ -1168,25 +1177,4 @@ int smscore_led_state(struct smscore_device_t *core, int led);
 
 /* ------------------------------------------------------------------------ */
 
-#define DBG_INFO 1
-#define DBG_ADV  2
-
-#define sms_printk(kern, fmt, arg...) \
-       printk(kern "%s: " fmt "\n", __func__, ##arg)
-
-#define dprintk(kern, lvl, fmt, arg...) do {\
-       if (sms_dbg & lvl) \
-               sms_printk(kern, fmt, ##arg); \
-} while (0)
-
-#define sms_log(fmt, arg...) sms_printk(KERN_INFO, fmt, ##arg)
-#define sms_err(fmt, arg...) \
-       sms_printk(KERN_ERR, "line: %d: " fmt, __LINE__, ##arg)
-#define sms_warn(fmt, arg...)  sms_printk(KERN_WARNING, fmt, ##arg)
-#define sms_info(fmt, arg...) \
-       dprintk(KERN_INFO, DBG_INFO, fmt, ##arg)
-#define sms_debug(fmt, arg...) \
-       dprintk(KERN_DEBUG, DBG_ADV, fmt, ##arg)
-
-
 #endif /* __SMS_CORE_API_H__ */
index 2408d7e9451eaea0608fdbb3ea9ef3b0ee0c36c2..1a8677ade39172f44440df009162727a0b1ff0b3 100644 (file)
@@ -17,7 +17,7 @@
  *
  ***********************************************************************/
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include "smscoreapi.h"
 
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -31,8 +31,6 @@
 #include "dvb_demux.h"
 #include "dvb_frontend.h"
 
-#include "smscoreapi.h"
-
 #include "smsdvb.h"
 
 static struct dentry *smsdvb_debugfs_usb_root;
@@ -536,7 +534,7 @@ int smsdvb_debugfs_register(void)
         */
        d = debugfs_create_dir("smsdvb", usb_debug_root);
        if (IS_ERR_OR_NULL(d)) {
-               sms_err("Couldn't create sysfs node for smsdvb");
+               pr_err("Couldn't create sysfs node for smsdvb\n");
                return PTR_ERR(d);
        } else {
                smsdvb_debugfs_usb_root = d;
index 85151efdd94c75d96db013151ba6b6d2c0d04841..367b8e77feb831a2372bfbd03126221413634ba3 100644 (file)
@@ -19,6 +19,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 ****************************************************************/
 
+#include "smscoreapi.h"
+
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/init.h>
@@ -29,7 +31,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include "dvb_demux.h"
 #include "dvb_frontend.h"
 
-#include "smscoreapi.h"
 #include "sms-cards.h"
 
 #include "smsdvb.h"
@@ -39,11 +40,6 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 static struct list_head g_smsdvb_clients;
 static struct mutex g_smsdvb_clientslock;
 
-static int sms_dbg;
-module_param_named(debug, sms_dbg, int, 0644);
-MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
-
-
 static u32 sms_to_guard_interval_table[] = {
        [0] = GUARD_INTERVAL_1_32,
        [1] = GUARD_INTERVAL_1_16,
@@ -82,48 +78,48 @@ static void sms_board_dvb3_event(struct smsdvb_client_t *client,
        struct smscore_device_t *coredev = client->coredev;
        switch (event) {
        case DVB3_EVENT_INIT:
-               sms_debug("DVB3_EVENT_INIT");
+               pr_debug("DVB3_EVENT_INIT\n");
                sms_board_event(coredev, BOARD_EVENT_BIND);
                break;
        case DVB3_EVENT_SLEEP:
-               sms_debug("DVB3_EVENT_SLEEP");
+               pr_debug("DVB3_EVENT_SLEEP\n");
                sms_board_event(coredev, BOARD_EVENT_POWER_SUSPEND);
                break;
        case DVB3_EVENT_HOTPLUG:
-               sms_debug("DVB3_EVENT_HOTPLUG");
+               pr_debug("DVB3_EVENT_HOTPLUG\n");
                sms_board_event(coredev, BOARD_EVENT_POWER_INIT);
                break;
        case DVB3_EVENT_FE_LOCK:
                if (client->event_fe_state != DVB3_EVENT_FE_LOCK) {
                        client->event_fe_state = DVB3_EVENT_FE_LOCK;
-                       sms_debug("DVB3_EVENT_FE_LOCK");
+                       pr_debug("DVB3_EVENT_FE_LOCK\n");
                        sms_board_event(coredev, BOARD_EVENT_FE_LOCK);
                }
                break;
        case DVB3_EVENT_FE_UNLOCK:
                if (client->event_fe_state != DVB3_EVENT_FE_UNLOCK) {
                        client->event_fe_state = DVB3_EVENT_FE_UNLOCK;
-                       sms_debug("DVB3_EVENT_FE_UNLOCK");
+                       pr_debug("DVB3_EVENT_FE_UNLOCK\n");
                        sms_board_event(coredev, BOARD_EVENT_FE_UNLOCK);
                }
                break;
        case DVB3_EVENT_UNC_OK:
                if (client->event_unc_state != DVB3_EVENT_UNC_OK) {
                        client->event_unc_state = DVB3_EVENT_UNC_OK;
-                       sms_debug("DVB3_EVENT_UNC_OK");
+                       pr_debug("DVB3_EVENT_UNC_OK\n");
                        sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_OK);
                }
                break;
        case DVB3_EVENT_UNC_ERR:
                if (client->event_unc_state != DVB3_EVENT_UNC_ERR) {
                        client->event_unc_state = DVB3_EVENT_UNC_ERR;
-                       sms_debug("DVB3_EVENT_UNC_ERR");
+                       pr_debug("DVB3_EVENT_UNC_ERR\n");
                        sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_ERRORS);
                }
                break;
 
        default:
-               sms_err("Unknown dvb3 api event");
+               pr_err("Unknown dvb3 api event\n");
                break;
        }
 }
@@ -590,7 +586,7 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
                is_status_update = true;
                break;
        default:
-               sms_info("message not handled");
+               pr_debug("message not handled\n");
        }
        smscore_putbuffer(client->coredev, cb);
 
@@ -613,6 +609,19 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
        return 0;
 }
 
+static void smsdvb_media_device_unregister(struct smsdvb_client_t *client)
+{
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+       struct smscore_device_t *coredev = client->coredev;
+
+       if (!coredev->media_dev)
+               return;
+       media_device_unregister(coredev->media_dev);
+       kfree(coredev->media_dev);
+       coredev->media_dev = NULL;
+#endif
+}
+
 static void smsdvb_unregister_client(struct smsdvb_client_t *client)
 {
        /* must be called under clientslock */
@@ -624,6 +633,7 @@ static void smsdvb_unregister_client(struct smsdvb_client_t *client)
        dvb_unregister_frontend(&client->frontend);
        dvb_dmxdev_release(&client->dmxdev);
        dvb_dmx_release(&client->demux);
+       smsdvb_media_device_unregister(client);
        dvb_unregister_adapter(&client->adapter);
        kfree(client);
 }
@@ -643,7 +653,7 @@ static int smsdvb_start_feed(struct dvb_demux_feed *feed)
                container_of(feed->demux, struct smsdvb_client_t, demux);
        struct sms_msg_data pid_msg;
 
-       sms_debug("add pid %d(%x)",
+       pr_debug("add pid %d(%x)\n",
                  feed->pid, feed->pid);
 
        client->feed_users++;
@@ -665,7 +675,7 @@ static int smsdvb_stop_feed(struct dvb_demux_feed *feed)
                container_of(feed->demux, struct smsdvb_client_t, demux);
        struct sms_msg_data pid_msg;
 
-       sms_debug("remove pid %d(%x)",
+       pr_debug("remove pid %d(%x)\n",
                  feed->pid, feed->pid);
 
        client->feed_users--;
@@ -835,7 +845,7 @@ static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
 static int smsdvb_get_tune_settings(struct dvb_frontend *fe,
                                    struct dvb_frontend_tune_settings *tune)
 {
-       sms_debug("");
+       pr_debug("\n");
 
        tune->min_delay_ms = 400;
        tune->step_size = 250000;
@@ -869,7 +879,7 @@ static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe)
        msg.Data[0] = c->frequency;
        msg.Data[2] = 12000000;
 
-       sms_info("%s: freq %d band %d", __func__, c->frequency,
+       pr_debug("%s: freq %d band %d\n", __func__, c->frequency,
                 c->bandwidth_hz);
 
        switch (c->bandwidth_hz / 1000000) {
@@ -954,7 +964,7 @@ static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe)
 
        c->bandwidth_hz = 6000000;
 
-       sms_info("%s: freq %d segwidth %d segindex %d", __func__,
+       pr_debug("freq %d segwidth %d segindex %d\n",
                 c->frequency, c->isdbt_sb_segment_count,
                 c->isdbt_sb_segment_idx);
 
@@ -1082,10 +1092,8 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev,
        if (!arrival)
                return 0;
        client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL);
-       if (!client) {
-               sms_err("kmalloc() failed");
+       if (!client)
                return -ENOMEM;
-       }
 
        /* register dvb adapter */
        rc = dvb_register_adapter(&client->adapter,
@@ -1093,9 +1101,10 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev,
                                        smscore_get_board_id(coredev))->name,
                                  THIS_MODULE, device, adapter_nr);
        if (rc < 0) {
-               sms_err("dvb_register_adapter() failed %d", rc);
+               pr_err("dvb_register_adapter() failed %d\n", rc);
                goto adapter_error;
        }
+       dvb_register_media_controller(&client->adapter, coredev->media_dev);
 
        /* init dvb demux */
        client->demux.dmx.capabilities = DMX_TS_FILTERING;
@@ -1106,7 +1115,7 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev,
 
        rc = dvb_dmx_init(&client->demux);
        if (rc < 0) {
-               sms_err("dvb_dmx_init failed %d", rc);
+               pr_err("dvb_dmx_init failed %d\n", rc);
                goto dvbdmx_error;
        }
 
@@ -1117,7 +1126,7 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev,
 
        rc = dvb_dmxdev_init(&client->dmxdev, &client->adapter);
        if (rc < 0) {
-               sms_err("dvb_dmxdev_init failed %d", rc);
+               pr_err("dvb_dmxdev_init failed %d\n", rc);
                goto dmxdev_error;
        }
 
@@ -1138,7 +1147,7 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev,
 
        rc = dvb_register_frontend(&client->adapter, &client->frontend);
        if (rc < 0) {
-               sms_err("frontend registration failed %d", rc);
+               pr_err("frontend registration failed %d\n", rc);
                goto frontend_error;
        }
 
@@ -1150,7 +1159,7 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev,
 
        rc = smscore_register_client(coredev, &params, &client->smsclient);
        if (rc < 0) {
-               sms_err("smscore_register_client() failed %d", rc);
+               pr_err("smscore_register_client() failed %d\n", rc);
                goto client_error;
        }
 
@@ -1169,12 +1178,14 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev,
        client->event_unc_state = -1;
        sms_board_dvb3_event(client, DVB3_EVENT_HOTPLUG);
 
-       sms_info("success");
        sms_board_setup(coredev);
 
        if (smsdvb_debugfs_create(client) < 0)
-               sms_info("failed to create debugfs node");
+               pr_info("failed to create debugfs node\n");
+
+       dvb_create_media_graph(&client->adapter);
 
+       pr_info("DVB interface registered.\n");
        return 0;
 
 client_error:
@@ -1187,6 +1198,7 @@ dmxdev_error:
        dvb_dmx_release(&client->demux);
 
 dvbdmx_error:
+       smsdvb_media_device_unregister(client);
        dvb_unregister_adapter(&client->adapter);
 
 adapter_error:
@@ -1205,7 +1217,7 @@ static int __init smsdvb_module_init(void)
 
        rc = smscore_register_hotplug(smsdvb_hotplug);
 
-       sms_debug("");
+       pr_debug("\n");
 
        return rc;
 }
index 35d0e887bd6562ea53eda53482f9075ac282186e..1d60d200d9ab1d7a23becbfd0259b9e728d0a22e 100644 (file)
  ****************************************************************/
 
 
+#include "smscoreapi.h"
+
 #include <linux/types.h>
 #include <linux/input.h>
 
-#include "smscoreapi.h"
 #include "smsir.h"
 #include "sms-cards.h"
 
@@ -56,16 +57,14 @@ int sms_ir_init(struct smscore_device_t *coredev)
        int board_id = smscore_get_board_id(coredev);
        struct rc_dev *dev;
 
-       sms_log("Allocating rc device");
+       pr_debug("Allocating rc device\n");
        dev = rc_allocate_device();
-       if (!dev) {
-               sms_err("Not enough memory");
+       if (!dev)
                return -ENOMEM;
-       }
 
        coredev->ir.controller = 0;     /* Todo: vega/nova SPI number */
        coredev->ir.timeout = IR_DEFAULT_TIMEOUT;
-       sms_log("IR port %d, timeout %d ms",
+       pr_debug("IR port %d, timeout %d ms\n",
                        coredev->ir.controller, coredev->ir.timeout);
 
        snprintf(coredev->ir.name, sizeof(coredev->ir.name),
@@ -92,11 +91,12 @@ int sms_ir_init(struct smscore_device_t *coredev)
        dev->map_name = sms_get_board(board_id)->rc_codes;
        dev->driver_name = MODULE_NAME;
 
-       sms_log("Input device (IR) %s is set for key events", dev->input_name);
+       pr_debug("Input device (IR) %s is set for key events\n",
+                dev->input_name);
 
        err = rc_register_device(dev);
        if (err < 0) {
-               sms_err("Failed to register device");
+               pr_err("Failed to register device\n");
                rc_free_device(dev);
                return err;
        }
@@ -109,5 +109,5 @@ void sms_ir_exit(struct smscore_device_t *coredev)
 {
        rc_unregister_device(coredev->ir.dev);
 
-       sms_log("");
+       pr_debug("\n");
 }
index abff803ad69a7e9e55818e5fd42d04ff475cd2d5..d0e3f9d85f34c7eb9d2c42b88b597ab128025c02 100644 (file)
@@ -1136,10 +1136,13 @@ static const struct file_operations dvb_demux_fops = {
        .llseek = default_llseek,
 };
 
-static struct dvb_device dvbdev_demux = {
+static const struct dvb_device dvbdev_demux = {
        .priv = NULL,
        .users = 1,
        .writers = 1,
+#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
+       .name = "dvb-demux",
+#endif
        .fops = &dvb_demux_fops
 };
 
@@ -1209,13 +1212,15 @@ static const struct file_operations dvb_dvr_fops = {
        .llseek = default_llseek,
 };
 
-static struct dvb_device dvbdev_dvr = {
+static const struct dvb_device dvbdev_dvr = {
        .priv = NULL,
        .readers = 1,
        .users = 1,
+#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
+       .name = "dvb-dvr",
+#endif
        .fops = &dvb_dvr_fops
 };
-
 int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
 {
        int i;
index 80ab8d0ff6e09af129a628594f8e48ff07a8d8a2..c117fb3b4aff676dc3bd7a124411e211b18f30b4 100644 (file)
 #define USB_PID_TECHNOTREND_CONNECT_S2400               0x3006
 #define USB_PID_TECHNOTREND_CONNECT_S2400_8KEEPROM     0x3009
 #define USB_PID_TECHNOTREND_CONNECT_CT3650             0x300d
+#define USB_PID_TECHNOTREND_CONNECT_S2_4600             0x3011
 #define USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI                0x3012
 #define USB_PID_TECHNOTREND_TVSTICK_CT2_4400           0x3014
 #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY       0x005a
 #define USB_PID_GRANDTEC_DVBT_USB2_COLD                        0x0bc6
 #define USB_PID_GRANDTEC_DVBT_USB2_WARM                        0x0bc7
 #define USB_PID_WINFAST_DTV2000DS                      0x6a04
+#define USB_PID_WINFAST_DTV2000DS_PLUS                 0x6f12
 #define USB_PID_WINFAST_DTV_DONGLE_COLD                        0x6025
 #define USB_PID_WINFAST_DTV_DONGLE_WARM                        0x6026
 #define USB_PID_WINFAST_DTV_DONGLE_STK7700P            0x6f00
 #define USB_PID_PCTV_2002E                              0x025c
 #define USB_PID_PCTV_2002E_SE                           0x025d
 #define USB_PID_SVEON_STV27                             0xd3af
+#define USB_PID_TURBOX_DTT_2000                         0xd3a4
 #endif
index 0aac3096728ee1faafa49a2ca8ad0986d18b0158..72937756f60c6f1e4b942366460aaad23cf4d0c7 100644 (file)
@@ -1638,15 +1638,17 @@ static const struct file_operations dvb_ca_fops = {
        .llseek = noop_llseek,
 };
 
-static struct dvb_device dvbdev_ca = {
+static const struct dvb_device dvbdev_ca = {
        .priv = NULL,
        .users = 1,
        .readers = 1,
        .writers = 1,
+#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
+       .name = "dvb-ca-en50221",
+#endif
        .fops = &dvb_ca_fops,
 };
 
-
 /* ******************************************************************************** */
 /* Initialisation/shutdown functions */
 
@@ -1676,14 +1678,14 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
        /* initialise the system data */
        if ((ca = kzalloc(sizeof(struct dvb_ca_private), GFP_KERNEL)) == NULL) {
                ret = -ENOMEM;
-               goto error;
+               goto exit;
        }
        ca->pub = pubca;
        ca->flags = flags;
        ca->slot_count = slot_count;
        if ((ca->slot_info = kcalloc(slot_count, sizeof(struct dvb_ca_slot), GFP_KERNEL)) == NULL) {
                ret = -ENOMEM;
-               goto error;
+               goto free_ca;
        }
        init_waitqueue_head(&ca->wait_queue);
        ca->open = 0;
@@ -1694,7 +1696,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
        /* register the DVB device */
        ret = dvb_register_device(dvb_adapter, &ca->dvbdev, &dvbdev_ca, ca, DVB_DEVICE_CA);
        if (ret)
-               goto error;
+               goto free_slot_info;
 
        /* now initialise each slot */
        for (i = 0; i < slot_count; i++) {
@@ -1709,7 +1711,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
 
        if (signal_pending(current)) {
                ret = -EINTR;
-               goto error;
+               goto unregister_device;
        }
        mb();
 
@@ -1720,17 +1722,17 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
                ret = PTR_ERR(ca->thread);
                printk("dvb_ca_init: failed to start kernel_thread (%d)\n",
                        ret);
-               goto error;
+               goto unregister_device;
        }
        return 0;
 
-error:
-       if (ca != NULL) {
-               if (ca->dvbdev != NULL)
-                       dvb_unregister_device(ca->dvbdev);
-               kfree(ca->slot_info);
-               kfree(ca);
-       }
+unregister_device:
+       dvb_unregister_device(ca->dvbdev);
+free_slot_info:
+       kfree(ca->slot_info);
+free_ca:
+       kfree(ca);
+exit:
        pubca->private = NULL;
        return ret;
 }
index 2cf30576bf39cca0b4ec889ca22705d0f2a185aa..882ca417f328a3b7f7c20f09e63992e642923981 100644 (file)
@@ -131,6 +131,11 @@ struct dvb_frontend_private {
        int quality;
        unsigned int check_wrapped;
        enum dvbfe_search algo_status;
+
+#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
+       struct media_pipeline pipe;
+       struct media_entity *pipe_start_entity;
+#endif
 };
 
 static void dvb_frontend_wakeup(struct dvb_frontend *fe);
@@ -590,12 +595,106 @@ static void dvb_frontend_wakeup(struct dvb_frontend *fe)
        wake_up_interruptible(&fepriv->wait_queue);
 }
 
+/**
+ * dvb_enable_media_tuner() - tries to enable the DVB tuner
+ *
+ * @fe:                struct dvb_frontend pointer
+ *
+ * This function ensures that just one media tuner is enabled for a given
+ * frontend. It has two different behaviors:
+ * - For trivial devices with just one tuner:
+ *   it just enables the existing tuner->fe link
+ * - For devices with more than one tuner:
+ *   It is up to the driver to implement the logic that will enable one tuner
+ *   and disable the other ones. However, if more than one tuner is enabled for
+ *   the same frontend, it will print an error message and return -EINVAL.
+ *
+ * At return, it will return the error code returned by media_entity_setup_link,
+ * or 0 if everything is OK, if no tuner is linked to the frontend or if the
+ * mdev is NULL.
+ */
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+static int dvb_enable_media_tuner(struct dvb_frontend *fe)
+{
+       struct dvb_frontend_private *fepriv = fe->frontend_priv;
+       struct dvb_adapter *adapter = fe->dvb;
+       struct media_device *mdev = adapter->mdev;
+       struct media_entity  *entity, *source;
+       struct media_link *link, *found_link = NULL;
+       int i, ret, n_links = 0, active_links = 0;
+
+       fepriv->pipe_start_entity = NULL;
+
+       if (!mdev)
+               return 0;
+
+       entity = fepriv->dvbdev->entity;
+       fepriv->pipe_start_entity = entity;
+
+       for (i = 0; i < entity->num_links; i++) {
+               link = &entity->links[i];
+               if (link->sink->entity == entity) {
+                       found_link = link;
+                       n_links++;
+                       if (link->flags & MEDIA_LNK_FL_ENABLED)
+                               active_links++;
+               }
+       }
+
+       if (!n_links || active_links == 1 || !found_link)
+               return 0;
+
+       /*
+        * If a frontend has more than one tuner linked, it is up to the driver
+        * to select with one will be the active one, as the frontend core can't
+        * guess. If the driver doesn't do that, it is a bug.
+        */
+       if (n_links > 1 && active_links != 1) {
+               dev_err(fe->dvb->device,
+                       "WARNING: there are %d active links among %d tuners. This is a driver's bug!\n",
+                       active_links, n_links);
+               return -EINVAL;
+       }
+
+       source = found_link->source->entity;
+       fepriv->pipe_start_entity = source;
+       for (i = 0; i < source->num_links; i++) {
+               struct media_entity *sink;
+               int flags = 0;
+
+               link = &source->links[i];
+               sink = link->sink->entity;
+
+               if (sink == entity)
+                       flags = MEDIA_LNK_FL_ENABLED;
+
+               ret = media_entity_setup_link(link, flags);
+               if (ret) {
+                       dev_err(fe->dvb->device,
+                               "Couldn't change link %s->%s to %s. Error %d\n",
+                               source->name, sink->name,
+                               flags ? "enabled" : "disabled",
+                               ret);
+                       return ret;
+               } else
+                       dev_dbg(fe->dvb->device,
+                               "link %s->%s was %s\n",
+                               source->name, sink->name,
+                               flags ? "ENABLED" : "disabled");
+       }
+       return 0;
+}
+#endif
+
 static int dvb_frontend_thread(void *data)
 {
        struct dvb_frontend *fe = data;
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
        fe_status_t s;
        enum dvbfe_algo algo;
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+       int ret;
+#endif
 
        bool re_tune = false;
        bool semheld = false;
@@ -609,6 +708,20 @@ static int dvb_frontend_thread(void *data)
        fepriv->wakeup = 0;
        fepriv->reinitialise = 0;
 
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+       ret = dvb_enable_media_tuner(fe);
+       if (ret) {
+               /* FIXME: return an error if it fails */
+               dev_info(fe->dvb->device,
+                       "proceeding with FE task\n");
+       } else if (fepriv->pipe_start_entity) {
+               ret = media_entity_pipeline_start(fepriv->pipe_start_entity,
+                                                 &fepriv->pipe);
+               if (ret)
+                       return ret;
+       }
+#endif
+
        dvb_frontend_init(fe);
 
        set_freezable();
@@ -718,6 +831,12 @@ restart:
                }
        }
 
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+       if (fepriv->pipe_start_entity)
+               media_entity_pipeline_stop(fepriv->pipe_start_entity);
+       fepriv->pipe_start_entity = NULL;
+#endif
+
        if (dvb_powerdown_on_sleep) {
                if (fe->ops.set_voltage)
                        fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF);
@@ -2612,11 +2731,14 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
                          struct dvb_frontend* fe)
 {
        struct dvb_frontend_private *fepriv;
-       static const struct dvb_device dvbdev_template = {
+       const struct dvb_device dvbdev_template = {
                .users = ~0,
                .writers = 1,
                .readers = (~0)-1,
                .fops = &dvb_frontend_fops,
+#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
+               .name = fe->ops.info.name,
+#endif
                .kernel_ioctl = dvb_frontend_ioctl
        };
 
index 4a77cb02dffc3edeb42cc8cff8c8ad10af38306b..a694fb1ea2287b56d7d7bc272937688208d19786 100644 (file)
@@ -1461,14 +1461,16 @@ static const struct file_operations dvb_net_fops = {
        .llseek = noop_llseek,
 };
 
-static struct dvb_device dvbdev_net = {
+static const struct dvb_device dvbdev_net = {
        .priv = NULL,
        .users = 1,
        .writers = 1,
+#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
+       .name = "dvb-net",
+#endif
        .fops = &dvb_net_fops,
 };
 
-
 void dvb_net_release (struct dvb_net *dvbnet)
 {
        int i;
index 983db75de3503952545f88700858f7a24131a9f9..13bb57f0457f7f9514628c177ae00784bc4e4461 100644 (file)
@@ -180,6 +180,93 @@ skip:
        return -ENFILE;
 }
 
+static void dvb_register_media_device(struct dvb_device *dvbdev,
+                                     int type, int minor)
+{
+#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
+       int ret = 0, npads;
+
+       if (!dvbdev->adapter->mdev)
+               return;
+
+       dvbdev->entity = kzalloc(sizeof(*dvbdev->entity), GFP_KERNEL);
+       if (!dvbdev->entity)
+               return;
+
+       dvbdev->entity->info.dev.major = DVB_MAJOR;
+       dvbdev->entity->info.dev.minor = minor;
+       dvbdev->entity->name = dvbdev->name;
+
+       switch (type) {
+       case DVB_DEVICE_CA:
+       case DVB_DEVICE_DEMUX:
+       case DVB_DEVICE_FRONTEND:
+               npads = 2;
+               break;
+       case DVB_DEVICE_NET:
+               npads = 0;
+               break;
+       default:
+               npads = 1;
+       }
+
+       if (npads) {
+               dvbdev->pads = kcalloc(npads, sizeof(*dvbdev->pads),
+                                      GFP_KERNEL);
+               if (!dvbdev->pads) {
+                       kfree(dvbdev->entity);
+                       return;
+               }
+       }
+
+       switch (type) {
+       case DVB_DEVICE_FRONTEND:
+               dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_FE;
+               dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
+               dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
+               break;
+       case DVB_DEVICE_DEMUX:
+               dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_DEMUX;
+               dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
+               dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
+               break;
+       case DVB_DEVICE_DVR:
+               dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_DVR;
+               dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
+               break;
+       case DVB_DEVICE_CA:
+               dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_CA;
+               dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
+               dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
+               break;
+       case DVB_DEVICE_NET:
+               dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_NET;
+               break;
+       default:
+               kfree(dvbdev->entity);
+               dvbdev->entity = NULL;
+               return;
+       }
+
+       if (npads)
+               ret = media_entity_init(dvbdev->entity, npads, dvbdev->pads, 0);
+       if (!ret)
+               ret = media_device_register_entity(dvbdev->adapter->mdev,
+                                                  dvbdev->entity);
+       if (ret < 0) {
+               printk(KERN_ERR
+                       "%s: media_device_register_entity failed for %s\n",
+                       __func__, dvbdev->entity->name);
+               kfree(dvbdev->pads);
+               kfree(dvbdev->entity);
+               dvbdev->entity = NULL;
+               return;
+       }
+
+       printk(KERN_DEBUG "%s: media device '%s' registered.\n",
+               __func__, dvbdev->entity->name);
+#endif
+}
 
 int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
                        const struct dvb_device *template, void *priv, int type)
@@ -258,10 +345,11 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
                       __func__, adap->num, dnames[type], id, PTR_ERR(clsdev));
                return PTR_ERR(clsdev);
        }
-
        dprintk(KERN_DEBUG "DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
                adap->num, dnames[type], id, minor, minor);
 
+       dvb_register_media_device(dvbdev, type, minor);
+
        return 0;
 }
 EXPORT_SYMBOL(dvb_register_device);
@@ -278,12 +366,66 @@ void dvb_unregister_device(struct dvb_device *dvbdev)
 
        device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor));
 
+#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
+       if (dvbdev->entity) {
+               media_device_unregister_entity(dvbdev->entity);
+               kfree(dvbdev->entity);
+               kfree(dvbdev->pads);
+       }
+#endif
+
        list_del (&dvbdev->list_head);
        kfree (dvbdev->fops);
        kfree (dvbdev);
 }
 EXPORT_SYMBOL(dvb_unregister_device);
 
+
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+void dvb_create_media_graph(struct dvb_adapter *adap)
+{
+       struct media_device *mdev = adap->mdev;
+       struct media_entity *entity, *tuner = NULL, *fe = NULL;
+       struct media_entity *demux = NULL, *dvr = NULL, *ca = NULL;
+
+       if (!mdev)
+               return;
+
+       media_device_for_each_entity(entity, mdev) {
+               switch (entity->type) {
+               case MEDIA_ENT_T_V4L2_SUBDEV_TUNER:
+                       tuner = entity;
+                       break;
+               case MEDIA_ENT_T_DEVNODE_DVB_FE:
+                       fe = entity;
+                       break;
+               case MEDIA_ENT_T_DEVNODE_DVB_DEMUX:
+                       demux = entity;
+                       break;
+               case MEDIA_ENT_T_DEVNODE_DVB_DVR:
+                       dvr = entity;
+                       break;
+               case MEDIA_ENT_T_DEVNODE_DVB_CA:
+                       ca = entity;
+                       break;
+               }
+       }
+
+       if (tuner && fe)
+               media_entity_create_link(tuner, 0, fe, 0, 0);
+
+       if (fe && demux)
+               media_entity_create_link(fe, 1, demux, 0, MEDIA_LNK_FL_ENABLED);
+
+       if (demux && dvr)
+               media_entity_create_link(demux, 1, dvr, 0, MEDIA_LNK_FL_ENABLED);
+
+       if (demux && ca)
+               media_entity_create_link(demux, 1, ca, 0, MEDIA_LNK_FL_ENABLED);
+}
+EXPORT_SYMBOL_GPL(dvb_create_media_graph);
+#endif
+
 static int dvbdev_check_free_adapter_num(int num)
 {
        struct list_head *entry;
index f96b28e7fc952f210000b39879e91fb29192d292..12629b8ecb0cd7c322f806535e1ffa2274dcf95e 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/poll.h>
 #include <linux/fs.h>
 #include <linux/list.h>
+#include <media/media-device.h>
 
 #define DVB_MAJOR 212
 
@@ -71,6 +72,10 @@ struct dvb_adapter {
        int mfe_shared;                 /* indicates mutually exclusive frontends */
        struct dvb_device *mfe_dvbdev;  /* frontend device in use */
        struct mutex mfe_lock;          /* access lock for thread creation */
+
+#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
+       struct media_device *mdev;
+#endif
 };
 
 
@@ -92,6 +97,15 @@ struct dvb_device {
        /* don't really need those !? -- FIXME: use video_usercopy  */
        int (*kernel_ioctl)(struct file *file, unsigned int cmd, void *arg);
 
+       /* Needed for media controller register/unregister */
+#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
+       const char *name;
+
+       /* Allocated and filled inside dvbdev.c */
+       struct media_entity *entity;
+       struct media_pad *pads;
+#endif
+
        void *priv;
 };
 
@@ -109,6 +123,19 @@ extern int dvb_register_device (struct dvb_adapter *adap,
 
 extern void dvb_unregister_device (struct dvb_device *dvbdev);
 
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+void dvb_create_media_graph(struct dvb_adapter *adap);
+static inline void dvb_register_media_controller(struct dvb_adapter *adap,
+                                                struct media_device *mdev)
+{
+       adap->mdev = mdev;
+}
+
+#else
+static inline void dvb_create_media_graph(struct dvb_adapter *adap) {}
+#define dvb_register_media_controller(a, b) {}
+#endif
+
 extern int dvb_generic_open (struct inode *inode, struct file *file);
 extern int dvb_generic_release (struct inode *inode, struct file *file);
 extern long dvb_generic_ioctl (struct file *file,
index bb76727d924ebd0931bedf2940e8cee3143a67a5..97c151d5b2e1a0a5e68fd5936dc2e8f196eeb782 100644 (file)
@@ -577,6 +577,14 @@ config DVB_LGDT3305
          An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
          to support this frontend.
 
+config DVB_LGDT3306A
+       tristate "LG Electronics LGDT3306A based"
+       depends on DVB_CORE && I2C
+       default m if !MEDIA_SUBDRV_AUTOSELECT
+       help
+         An ATSC 8VSB and QAM-B 64/256 demodulator module. Say Y when you want
+         to support this frontend.
+
 config DVB_LG2160
        tristate "LG Electronics LG216x based"
        depends on DVB_CORE && I2C
index ba59df63d05082062ca03bb2f4ca6ffe2418e7b0..23d399bec804f65464700db92566bca4e9aaa2f0 100644 (file)
@@ -54,6 +54,7 @@ obj-$(CONFIG_DVB_BCM3510) += bcm3510.o
 obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
 obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
 obj-$(CONFIG_DVB_LGDT3305) += lgdt3305.o
+obj-$(CONFIG_DVB_LGDT3306A) += lgdt3306a.o
 obj-$(CONFIG_DVB_LG2160) += lg2160.o
 obj-$(CONFIG_DVB_CX24123) += cx24123.o
 obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
index b6ef6427cfa5ebaf422cc8a72d66f05f2581bbf8..5f0411939ffc632496750e27be745b63178dd6ef 100644 (file)
@@ -27,7 +27,7 @@ struct a8293_config {
        u8 i2c_addr;
 };
 
-#if IS_ENABLED(CONFIG_DVB_A8293)
+#if IS_REACHABLE(CONFIG_DVB_A8293)
 extern struct dvb_frontend *a8293_attach(struct dvb_frontend *fe,
        struct i2c_adapter *i2c, const struct a8293_config *cfg);
 #else
index 09273b2cd310d6fcd8cf74c5df9fc8e38a377a5f..1dcc936e1661829789e17a2fea4b65a9e6aa0d7b 100644 (file)
@@ -103,7 +103,7 @@ struct af9013_config {
        u8 gpio[4];
 };
 
-#if IS_ENABLED(CONFIG_DVB_AF9013)
+#if IS_REACHABLE(CONFIG_DVB_AF9013)
 extern struct dvb_frontend *af9013_attach(const struct af9013_config *config,
        struct i2c_adapter *i2c);
 #else
index 8e0ac98f8d0832a357caf6788220be58d4a06ae2..5446d13fdfe88e6e06e3ae17afbd7208bd806d5f 100644 (file)
@@ -61,7 +61,7 @@ struct atbm8830_config {
        u8 agc_hold_loop;
 };
 
-#if IS_ENABLED(CONFIG_DVB_ATBM8830)
+#if IS_REACHABLE(CONFIG_DVB_ATBM8830)
 extern struct dvb_frontend *atbm8830_attach(const struct atbm8830_config *config,
                struct i2c_adapter *i2c);
 #else
index 6122519588551c457568b4f7054de6a85ba5e84e..dde61582c158399153c8d4ccb15d9575d068c21b 100644 (file)
@@ -61,7 +61,7 @@ struct au8522_config {
        enum au8522_if_freq qam_if;
 };
 
-#if IS_ENABLED(CONFIG_DVB_AU8522_DTV)
+#if IS_REACHABLE(CONFIG_DVB_AU8522_DTV)
 extern struct dvb_frontend *au8522_attach(const struct au8522_config *config,
                                          struct i2c_adapter *i2c);
 #else
index 5bd56b1623bfdbba8a8cb1b85ce9f0d2794871d5..ff66492fb9408f5324c749d64638df67929d1077 100644 (file)
@@ -34,7 +34,7 @@ struct bcm3510_config
        int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
 };
 
-#if IS_ENABLED(CONFIG_DVB_BCM3510)
+#if IS_REACHABLE(CONFIG_DVB_BCM3510)
 extern struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config,
                                           struct i2c_adapter* i2c);
 #else
index 382a7b1f3618aca5770e15225ab7cbb95ee1a488..e0a764868e6f9d2f44af8bed2d7be039ac8d07ba 100644 (file)
@@ -31,7 +31,7 @@ struct cx22700_config
        u8 demod_address;
 };
 
-#if IS_ENABLED(CONFIG_DVB_CX22700)
+#if IS_REACHABLE(CONFIG_DVB_CX22700)
 extern struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
                                           struct i2c_adapter* i2c);
 #else
index 0b1a6c2f9d5fa6a316656626034dc60242e79628..68b69a7660d2a0bae09fa03b6588f1ef54ba1d81 100644 (file)
@@ -41,7 +41,7 @@ struct cx22702_config {
        u8 output_mode;
 };
 
-#if IS_ENABLED(CONFIG_DVB_CX22702)
+#if IS_REACHABLE(CONFIG_DVB_CX22702)
 extern struct dvb_frontend *cx22702_attach(
        const struct cx22702_config *config,
        struct i2c_adapter *i2c);
index 527aff1f27233557f88b7922e7f0f18edfc32f92..d5453ed20b281622039ae6d71b2771c3d9ae3638 100644 (file)
@@ -46,7 +46,7 @@ static inline int cx24110_pll_write(struct dvb_frontend *fe, u32 val)
        return 0;
 }
 
-#if IS_ENABLED(CONFIG_DVB_CX24110)
+#if IS_REACHABLE(CONFIG_DVB_CX24110)
 extern struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
                                           struct i2c_adapter* i2c);
 #else
index 782711ba1a325805f01fed11b379eb81e2231aa4..962919b9b6e62455829578629869d7d120db3179 100644 (file)
@@ -32,7 +32,7 @@ struct cx24113_config {
        u32 xtal_khz;
 };
 
-#if IS_ENABLED(CONFIG_DVB_TUNER_CX24113)
+#if IS_REACHABLE(CONFIG_DVB_TUNER_CX24113)
 extern struct dvb_frontend *cx24113_attach(struct dvb_frontend *,
        const struct cx24113_config *config, struct i2c_adapter *i2c);
 
index 2ec84fae3f9fa69bc1e728d61a9ce0b66e822913..f6dbabc1d62b7e56cc00696ded605ca1500cf2f7 100644 (file)
@@ -41,7 +41,7 @@ struct cx24116_config {
        u16 i2c_wr_max;
 };
 
-#if IS_ENABLED(CONFIG_DVB_CX24116)
+#if IS_REACHABLE(CONFIG_DVB_CX24116)
 extern struct dvb_frontend *cx24116_attach(
        const struct cx24116_config *config,
        struct i2c_adapter *i2c);
index 4e59e9574fa72258e91e9e5c3c49326f82d3924c..1648ab43216879f3482f7ebaa7302819b9a1c6d3 100644 (file)
@@ -30,7 +30,7 @@ struct cx24117_config {
        u8 demod_address;
 };
 
-#if IS_ENABLED(CONFIG_DVB_CX24117)
+#if IS_REACHABLE(CONFIG_DVB_CX24117)
 extern struct dvb_frontend *cx24117_attach(
        const struct cx24117_config *config,
        struct i2c_adapter *i2c);
index 102e70d17c43d8f30f1d03ec37b6851016e2ccfb..758aee5a072f727c8a149f5d0f9767459243b77b 100644 (file)
@@ -39,7 +39,7 @@ struct cx24123_config {
        void (*agc_callback) (struct dvb_frontend *);
 };
 
-#if IS_ENABLED(CONFIG_DVB_CX24123)
+#if IS_REACHABLE(CONFIG_DVB_CX24123)
 extern struct dvb_frontend *cx24123_attach(const struct cx24123_config *config,
                                           struct i2c_adapter *i2c);
 extern struct i2c_adapter *cx24123_get_tuner_i2c_adapter(struct dvb_frontend *);
index 6095dbcf785091ddc8009134b04e905483e19ec1..56d42760263d86143805fdf27af822f01ec2ba44 100644 (file)
@@ -72,7 +72,7 @@ struct cxd2820r_config {
 };
 
 
-#if IS_ENABLED(CONFIG_DVB_CXD2820R)
+#if IS_REACHABLE(CONFIG_DVB_CXD2820R)
 extern struct dvb_frontend *cxd2820r_attach(
        const struct cxd2820r_config *config,
        struct i2c_adapter *i2c,
index 0c6befcc9143ad9a48ecd26792c8f99c1cd7b048..6c0b6672b1d9e50a09b2c09106c507ce70ca3a68 100644 (file)
@@ -48,7 +48,7 @@ struct dib0070_config {
        u8 vga_filter;
 };
 
-#if IS_ENABLED(CONFIG_DVB_TUNER_DIB0070)
+#if IS_REACHABLE(CONFIG_DVB_TUNER_DIB0070)
 extern struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg);
 extern u16 dib0070_wbd_offset(struct dvb_frontend *);
 extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, u8 open);
index 6a090954fa10c6da7d2c0f87f8dfdb3840e184d8..ad74bc823f08c469fd517dc9bb7f857be88bf589 100644 (file)
@@ -75,7 +75,7 @@ struct dib0090_config {
        u8 force_crystal_mode;
 };
 
-#if IS_ENABLED(CONFIG_DVB_TUNER_DIB0090)
+#if IS_REACHABLE(CONFIG_DVB_TUNER_DIB0090)
 extern struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config);
 extern struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config);
 extern void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast);
index 9b6c3bbc983af2c6ce26cb9970db9ec6df6d8002..6ae9899b5b450bec39a56601134accd686dbd990 100644 (file)
@@ -41,7 +41,7 @@ struct dib_fe_xfer_ops
        int (*tuner_pass_ctrl)(struct dvb_frontend *fe, int onoff, u8 pll_ctrl);
 };
 
-#if IS_ENABLED(CONFIG_DVB_DIB3000MB)
+#if IS_REACHABLE(CONFIG_DVB_DIB3000MB)
 extern struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
                                             struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops);
 #else
index 129d1425516a175943708129938c214de7a7970c..74816f79361180c0191c4cdd69239121371543f5 100644 (file)
@@ -41,7 +41,7 @@ struct dib3000mc_config {
 #define DEFAULT_DIB3000MC_I2C_ADDRESS 16
 #define DEFAULT_DIB3000P_I2C_ADDRESS  24
 
-#if IS_ENABLED(CONFIG_DVB_DIB3000MC)
+#if IS_REACHABLE(CONFIG_DVB_DIB3000MC)
 extern struct dvb_frontend *dib3000mc_attach(struct i2c_adapter *i2c_adap,
                                             u8 i2c_addr,
                                             struct dib3000mc_config *cfg);
index b585413f9a29834c74ef0a9e6f63e7f1e6d7022b..6468c278cc4d371da8828bdf0924393bba0a4251 100644 (file)
@@ -40,7 +40,7 @@ struct dib7000m_config {
 
 #define DEFAULT_DIB7000M_I2C_ADDRESS 18
 
-#if IS_ENABLED(CONFIG_DVB_DIB7000M)
+#if IS_REACHABLE(CONFIG_DVB_DIB7000M)
 extern struct dvb_frontend *dib7000m_attach(struct i2c_adapter *i2c_adap,
                                            u8 i2c_addr,
                                            struct dib7000m_config *cfg);
index 1fea0e97265446fbd38b811b95d1601c840f9d82..baa278928cf3405ffb390818666423dc9bdd50d9 100644 (file)
@@ -66,7 +66,7 @@ struct dib7000p_ops {
        struct dvb_frontend *(*init)(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg);
 };
 
-#if IS_ENABLED(CONFIG_DVB_DIB7000P)
+#if IS_REACHABLE(CONFIG_DVB_DIB7000P)
 void *dib7000p_attach(struct dib7000p_ops *ops);
 #else
 static inline void *dib7000p_attach(struct dib7000p_ops *ops)
index 84cc10383dcd226efd764a834fc8ac083f64c853..780c37bdcb7295e6c97730e45a61970cb17b2ac8 100644 (file)
@@ -63,7 +63,7 @@ struct dib8000_ops {
        struct dvb_frontend *(*init)(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg);
 };
 
-#if IS_ENABLED(CONFIG_DVB_DIB8000)
+#if IS_REACHABLE(CONFIG_DVB_DIB8000)
 void *dib8000_attach(struct dib8000_ops *ops);
 #else
 static inline int dib8000_attach(struct dib8000_ops *ops)
index f3639f045ff0decc32b3ebdeda1f35499da53b93..b10a70aa7c9fdfcfaed67b367bcd563c06af459d 100644 (file)
@@ -27,7 +27,7 @@ struct dib9000_config {
 
 #define DEFAULT_DIB9000_I2C_ADDRESS 18
 
-#if IS_ENABLED(CONFIG_DVB_DIB9000)
+#if IS_REACHABLE(CONFIG_DVB_DIB9000)
 extern struct dvb_frontend *dib9000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, const struct dib9000_config *cfg);
 extern int dib9000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr);
 extern struct i2c_adapter *dib9000_get_tuner_interface(struct dvb_frontend *fe);
index cfd0b96b69391136b8b9bd31c013a32fb6503704..8188062953afac9277c2e30f8649323c9eeb26aa 100644 (file)
@@ -34,7 +34,7 @@ struct drx39xxj_state {
        const struct firmware *fw;
 };
 
-#if IS_ENABLED(CONFIG_DVB_DRX39XYJ)
+#if IS_REACHABLE(CONFIG_DVB_DRX39XYJ)
 struct dvb_frontend *drx39xxj_attach(struct i2c_adapter *i2c);
 #else
 static inline struct dvb_frontend *drx39xxj_attach(struct i2c_adapter *i2c) {
index d998e4d5a7fc7756e13c726ff847a6266273c45b..a47c22d6667eb88ba41bdaa68bbbafe642ef696f 100644 (file)
@@ -52,7 +52,7 @@ struct drxd_config {
         s16(*osc_deviation) (void *priv, s16 dev, int flag);
 };
 
-#if IS_ENABLED(CONFIG_DVB_DRXD)
+#if IS_REACHABLE(CONFIG_DVB_DRXD)
 extern
 struct dvb_frontend *drxd_attach(const struct drxd_config *config,
                                 void *priv, struct i2c_adapter *i2c,
index f6cb3466032778882cfc30925866c4da86910490..8f0b9eec528f6ff0290dc462b8ed780b14991eaa 100644 (file)
@@ -51,7 +51,7 @@ struct drxk_config {
        int              qam_demod_parameter_count;
 };
 
-#if IS_ENABLED(CONFIG_DVB_DRXK)
+#if IS_REACHABLE(CONFIG_DVB_DRXK)
 extern struct dvb_frontend *drxk_attach(const struct drxk_config *config,
                                        struct i2c_adapter *i2c);
 #else
index f9c21fb7af13d9570ebbd8058a452a1aa4bdb97f..153169da90179dbadc0b71978834b38415b67543 100644 (file)
@@ -35,7 +35,7 @@ struct ds3000_config {
        void (*set_lock_led)(struct dvb_frontend *fe, int offon);
 };
 
-#if IS_ENABLED(CONFIG_DVB_DS3000)
+#if IS_REACHABLE(CONFIG_DVB_DS3000)
 extern struct dvb_frontend *ds3000_attach(const struct ds3000_config *config,
                                        struct i2c_adapter *i2c);
 #else
index f4b5a0601c3aa79dd443a2b0b191986f1ef05723..bf9602a88b6c5a0bbee8e38aa0db7d90bb0c6e8e 100644 (file)
@@ -38,7 +38,7 @@
  * @param pll_desc_id dvb_pll_desc to use.
  * @return Frontend pointer on success, NULL on failure
  */
-#if IS_ENABLED(CONFIG_DVB_PLL)
+#if IS_REACHABLE(CONFIG_DVB_PLL)
 extern struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe,
                                           int pll_addr,
                                           struct i2c_adapter *i2c,
index 0cbf96105631383eadb553c0d930b59e31fe833d..15e4ceab869ab32d572ce96a387fd1e051b235e6 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/dvb/frontend.h>
 #include "dvb_frontend.h"
 
-#if IS_ENABLED(CONFIG_DVB_DUMMY_FE)
+#if IS_REACHABLE(CONFIG_DVB_DUMMY_FE)
 extern struct dvb_frontend* dvb_dummy_fe_ofdm_attach(void);
 extern struct dvb_frontend* dvb_dummy_fe_qpsk_attach(void);
 extern struct dvb_frontend* dvb_dummy_fe_qam_attach(void);
index 37558403068d189588d6ed76bc3694bced381261..9544bab5cd1d14d6c14100d2370131ce13f84652 100644 (file)
@@ -31,7 +31,7 @@ struct ec100_config {
 };
 
 
-#if IS_ENABLED(CONFIG_DVB_EC100)
+#if IS_REACHABLE(CONFIG_DVB_EC100)
 extern struct dvb_frontend *ec100_attach(const struct ec100_config *config,
        struct i2c_adapter *i2c);
 #else
index 05cd13028a91ab68c19bc74fb7915e3af772a2b1..48e9ab74c8831580f15446579c346763a66bddec 100644 (file)
@@ -51,7 +51,7 @@ struct hd29l2_config {
 };
 
 
-#if IS_ENABLED(CONFIG_DVB_HD29L2)
+#if IS_REACHABLE(CONFIG_DVB_HD29L2)
 extern struct dvb_frontend *hd29l2_attach(const struct hd29l2_config *config,
        struct i2c_adapter *i2c);
 #else
index 8abb70c26fd9428a0b6d4eed68426b8e7d237aad..3c148b830bd199f6e72b3bb2bee1554568689488 100644 (file)
@@ -55,7 +55,7 @@
 #define ISL6405_ENT2   0x20
 #define ISL6405_ISEL2  0x40
 
-#if IS_ENABLED(CONFIG_DVB_ISL6405)
+#if IS_REACHABLE(CONFIG_DVB_ISL6405)
 /* override_set and override_clear control which system register bits (above)
  * to always set & clear
  */
index 630e7f8a150e64f650cc4c492f8396e577810565..3273597833fda0c9d683ef3f0df65978363de9d2 100644 (file)
@@ -39,7 +39,7 @@
 #define ISL6421_ISEL1  0x20
 #define ISL6421_DCL    0x40
 
-#if IS_ENABLED(CONFIG_DVB_ISL6421)
+#if IS_REACHABLE(CONFIG_DVB_ISL6421)
 /* override_set and override_clear control which system register bits (above) to always set & clear */
 extern struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
                          u8 override_set, u8 override_clear, bool override_tone);
index 80dfd9cc4f41e31b47fc4df73e378a875dc1b12f..a64df0ee256babb921e7ea3178707b794d6bf6e2 100644 (file)
@@ -42,7 +42,7 @@ struct isl6423_config {
        u8 mod_extern;
 };
 
-#if IS_ENABLED(CONFIG_DVB_ISL6423)
+#if IS_REACHABLE(CONFIG_DVB_ISL6423)
 
 
 extern struct dvb_frontend *isl6423_attach(struct dvb_frontend *fe,
index edae0902f4fd3e5f307da0e10d1005964d3ed30c..a691bb6f26de7d89f6b582b77120231a4efc1412 100644 (file)
@@ -29,7 +29,7 @@ struct itd1000_config {
        u8 i2c_address;
 };
 
-#if IS_ENABLED(CONFIG_DVB_TUNER_ITD1000)
+#if IS_REACHABLE(CONFIG_DVB_TUNER_ITD1000)
 extern struct dvb_frontend *itd1000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct itd1000_config *cfg);
 #else
 static inline struct dvb_frontend *itd1000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct itd1000_config *cfg)
index 1a735a75aa984cb05ff2c269d34090dd7e5057fa..af107a2dd3578aa61c9591e1778d3e516c028311 100644 (file)
@@ -49,7 +49,7 @@ struct ix2505v_config {
 
 };
 
-#if IS_ENABLED(CONFIG_DVB_IX2505V)
+#if IS_REACHABLE(CONFIG_DVB_IX2505V)
 extern struct dvb_frontend *ix2505v_attach(struct dvb_frontend *fe,
        const struct ix2505v_config *config, struct i2c_adapter *i2c);
 #else
index 6813b08a774d8ff472466b709776410fa47789c3..8697e2c2ba36415b7657ceef018ca736af7a885a 100644 (file)
@@ -31,7 +31,7 @@ struct l64781_config
        u8 demod_address;
 };
 
-#if IS_ENABLED(CONFIG_DVB_L64781)
+#if IS_REACHABLE(CONFIG_DVB_L64781)
 extern struct dvb_frontend* l64781_attach(const struct l64781_config* config,
                                          struct i2c_adapter* i2c);
 #else
index 194a07a78dc11a72f8f95de6c98ed7b07ceb618f..d20bd909de394b0585c6b77a4996e210d73728f4 100644 (file)
@@ -67,7 +67,7 @@ struct lg2160_config {
        enum lg_chip_type lg_chip;
 };
 
-#if IS_ENABLED(CONFIG_DVB_LG2160)
+#if IS_REACHABLE(CONFIG_DVB_LG2160)
 extern
 struct dvb_frontend *lg2160_attach(const struct lg2160_config *config,
                                     struct i2c_adapter *i2c_adap);
index 9c03e530e01b41e8c611d93f652e60a5db28392c..f91a1b49ce2f93d06bf7cfd75cd8563b1bcb3884 100644 (file)
@@ -80,7 +80,7 @@ struct lgdt3305_config {
        enum lgdt_demod_chip_type demod_chip;
 };
 
-#if IS_ENABLED(CONFIG_DVB_LGDT3305)
+#if IS_REACHABLE(CONFIG_DVB_LGDT3305)
 extern
 struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config,
                                     struct i2c_adapter *i2c_adap);
diff --git a/drivers/media/dvb-frontends/lgdt3306a.c b/drivers/media/dvb-frontends/lgdt3306a.c
new file mode 100644 (file)
index 0000000..d9a2b0e
--- /dev/null
@@ -0,0 +1,2144 @@
+/*
+ *    Support for LGDT3306A - 8VSB/QAM-B
+ *
+ *    Copyright (C) 2013 Fred Richter <frichter@hauppauge.com>
+ *    - driver structure based on lgdt3305.[ch] by Michael Krufky
+ *    - code based on LG3306_V0.35 API by LG Electronics Inc.
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <asm/div64.h>
+#include <linux/dvb/frontend.h>
+#include "dvb_math.h"
+#include "lgdt3306a.h"
+
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debug level (info=1, reg=2 (or-able))");
+
+#define DBG_INFO 1
+#define DBG_REG  2
+#define DBG_DUMP 4 /* FGR - comment out to remove dump code */
+
+#define lg_debug(fmt, arg...) \
+       printk(KERN_DEBUG pr_fmt(fmt), ## arg)
+
+#define dbg_info(fmt, arg...)                                  \
+       do {                                                    \
+               if (debug & DBG_INFO)                           \
+                       lg_debug(fmt, ## arg);                  \
+       } while (0)
+
+#define dbg_reg(fmt, arg...)                                   \
+       do {                                                    \
+               if (debug & DBG_REG)                            \
+                       lg_debug(fmt, ## arg);                  \
+       } while (0)
+
+#define lg_chkerr(ret)                                                 \
+({                                                                     \
+       int __ret;                                                      \
+       __ret = (ret < 0);                                              \
+       if (__ret)                                                      \
+               pr_err("error %d on line %d\n", ret, __LINE__);         \
+       __ret;                                                          \
+})
+
+struct lgdt3306a_state {
+       struct i2c_adapter *i2c_adap;
+       const struct lgdt3306a_config *cfg;
+
+       struct dvb_frontend frontend;
+
+       fe_modulation_t current_modulation;
+       u32 current_frequency;
+       u32 snr;
+};
+
+/*
+ * LG3306A Register Usage
+ *  (LG does not really name the registers, so this code does not either)
+ *
+ * 0000 -> 00FF Common control and status
+ * 1000 -> 10FF Synchronizer control and status
+ * 1F00 -> 1FFF Smart Antenna control and status
+ * 2100 -> 21FF VSB Equalizer control and status
+ * 2800 -> 28FF QAM Equalizer control and status
+ * 3000 -> 30FF FEC control and status
+ */
+
+enum lgdt3306a_lock_status {
+       LG3306_UNLOCK       = 0x00,
+       LG3306_LOCK         = 0x01,
+       LG3306_UNKNOWN_LOCK = 0xff
+};
+
+enum lgdt3306a_neverlock_status {
+       LG3306_NL_INIT    = 0x00,
+       LG3306_NL_PROCESS = 0x01,
+       LG3306_NL_LOCK    = 0x02,
+       LG3306_NL_FAIL    = 0x03,
+       LG3306_NL_UNKNOWN = 0xff
+};
+
+enum lgdt3306a_modulation {
+       LG3306_VSB          = 0x00,
+       LG3306_QAM64        = 0x01,
+       LG3306_QAM256       = 0x02,
+       LG3306_UNKNOWN_MODE = 0xff
+};
+
+enum lgdt3306a_lock_check {
+       LG3306_SYNC_LOCK,
+       LG3306_FEC_LOCK,
+       LG3306_TR_LOCK,
+       LG3306_AGC_LOCK,
+};
+
+
+#ifdef DBG_DUMP
+static void lgdt3306a_DumpAllRegs(struct lgdt3306a_state *state);
+static void lgdt3306a_DumpRegs(struct lgdt3306a_state *state);
+#endif
+
+
+static int lgdt3306a_write_reg(struct lgdt3306a_state *state, u16 reg, u8 val)
+{
+       int ret;
+       u8 buf[] = { reg >> 8, reg & 0xff, val };
+       struct i2c_msg msg = {
+               .addr = state->cfg->i2c_addr, .flags = 0,
+               .buf = buf, .len = 3,
+       };
+
+       dbg_reg("reg: 0x%04x, val: 0x%02x\n", reg, val);
+
+       ret = i2c_transfer(state->i2c_adap, &msg, 1);
+
+       if (ret != 1) {
+               pr_err("error (addr %02x %02x <- %02x, err = %i)\n",
+                      msg.buf[0], msg.buf[1], msg.buf[2], ret);
+               if (ret < 0)
+                       return ret;
+               else
+                       return -EREMOTEIO;
+       }
+       return 0;
+}
+
+static int lgdt3306a_read_reg(struct lgdt3306a_state *state, u16 reg, u8 *val)
+{
+       int ret;
+       u8 reg_buf[] = { reg >> 8, reg & 0xff };
+       struct i2c_msg msg[] = {
+               { .addr = state->cfg->i2c_addr,
+                 .flags = 0, .buf = reg_buf, .len = 2 },
+               { .addr = state->cfg->i2c_addr,
+                 .flags = I2C_M_RD, .buf = val, .len = 1 },
+       };
+
+       ret = i2c_transfer(state->i2c_adap, msg, 2);
+
+       if (ret != 2) {
+               pr_err("error (addr %02x reg %04x error (ret == %i)\n",
+                      state->cfg->i2c_addr, reg, ret);
+               if (ret < 0)
+                       return ret;
+               else
+                       return -EREMOTEIO;
+       }
+       dbg_reg("reg: 0x%04x, val: 0x%02x\n", reg, *val);
+
+       return 0;
+}
+
+#define read_reg(state, reg)                                           \
+({                                                                     \
+       u8 __val;                                                       \
+       int ret = lgdt3306a_read_reg(state, reg, &__val);               \
+       if (lg_chkerr(ret))                                             \
+               __val = 0;                                              \
+       __val;                                                          \
+})
+
+static int lgdt3306a_set_reg_bit(struct lgdt3306a_state *state,
+                               u16 reg, int bit, int onoff)
+{
+       u8 val;
+       int ret;
+
+       dbg_reg("reg: 0x%04x, bit: %d, level: %d\n", reg, bit, onoff);
+
+       ret = lgdt3306a_read_reg(state, reg, &val);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       val &= ~(1 << bit);
+       val |= (onoff & 1) << bit;
+
+       ret = lgdt3306a_write_reg(state, reg, val);
+       lg_chkerr(ret);
+fail:
+       return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lgdt3306a_soft_reset(struct lgdt3306a_state *state)
+{
+       int ret;
+
+       dbg_info("\n");
+
+       ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 0);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       msleep(20);
+       ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 1);
+       lg_chkerr(ret);
+
+fail:
+       return ret;
+}
+
+static int lgdt3306a_mpeg_mode(struct lgdt3306a_state *state,
+                                    enum lgdt3306a_mpeg_mode mode)
+{
+       u8 val;
+       int ret;
+
+       dbg_info("(%d)\n", mode);
+       /* transport packet format - TPSENB=0x80 */
+       ret = lgdt3306a_set_reg_bit(state, 0x0071, 7,
+                                    mode == LGDT3306A_MPEG_PARALLEL ? 1 : 0);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       /*
+        * start of packet signal duration
+        * TPSSOPBITEN=0x40; 0=byte duration, 1=bit duration
+        */
+       ret = lgdt3306a_set_reg_bit(state, 0x0071, 6, 0);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       ret = lgdt3306a_read_reg(state, 0x0070, &val);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       val |= 0x10; /* TPCLKSUPB=0x10 */
+
+       if (mode == LGDT3306A_MPEG_PARALLEL)
+               val &= ~0x10;
+
+       ret = lgdt3306a_write_reg(state, 0x0070, val);
+       lg_chkerr(ret);
+
+fail:
+       return ret;
+}
+
+static int lgdt3306a_mpeg_mode_polarity(struct lgdt3306a_state *state,
+                                      enum lgdt3306a_tp_clock_edge edge,
+                                      enum lgdt3306a_tp_valid_polarity valid)
+{
+       u8 val;
+       int ret;
+
+       dbg_info("edge=%d, valid=%d\n", edge, valid);
+
+       ret = lgdt3306a_read_reg(state, 0x0070, &val);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       val &= ~0x06; /* TPCLKPOL=0x04, TPVALPOL=0x02 */
+
+       if (edge == LGDT3306A_TPCLK_RISING_EDGE)
+               val |= 0x04;
+       if (valid == LGDT3306A_TP_VALID_HIGH)
+               val |= 0x02;
+
+       ret = lgdt3306a_write_reg(state, 0x0070, val);
+       lg_chkerr(ret);
+
+fail:
+       return ret;
+}
+
+static int lgdt3306a_mpeg_tristate(struct lgdt3306a_state *state,
+                                    int mode)
+{
+       u8 val;
+       int ret;
+
+       dbg_info("(%d)\n", mode);
+
+       if (mode) {
+               ret = lgdt3306a_read_reg(state, 0x0070, &val);
+               if (lg_chkerr(ret))
+                       goto fail;
+               /*
+                * Tristate bus; TPOUTEN=0x80, TPCLKOUTEN=0x20,
+                * TPDATAOUTEN=0x08
+                */
+               val &= ~0xa8;
+               ret = lgdt3306a_write_reg(state, 0x0070, val);
+               if (lg_chkerr(ret))
+                       goto fail;
+
+               /* AGCIFOUTENB=0x40; 1=Disable IFAGC pin */
+               ret = lgdt3306a_set_reg_bit(state, 0x0003, 6, 1);
+               if (lg_chkerr(ret))
+                       goto fail;
+
+       } else {
+               /* enable IFAGC pin */
+               ret = lgdt3306a_set_reg_bit(state, 0x0003, 6, 0);
+               if (lg_chkerr(ret))
+                       goto fail;
+
+               ret = lgdt3306a_read_reg(state, 0x0070, &val);
+               if (lg_chkerr(ret))
+                       goto fail;
+
+               val |= 0xa8; /* enable bus */
+               ret = lgdt3306a_write_reg(state, 0x0070, val);
+               if (lg_chkerr(ret))
+                       goto fail;
+       }
+
+fail:
+       return ret;
+}
+
+static int lgdt3306a_ts_bus_ctrl(struct dvb_frontend *fe, int acquire)
+{
+       struct lgdt3306a_state *state = fe->demodulator_priv;
+
+       dbg_info("acquire=%d\n", acquire);
+
+       return lgdt3306a_mpeg_tristate(state, acquire ? 0 : 1);
+
+}
+
+static int lgdt3306a_power(struct lgdt3306a_state *state,
+                                    int mode)
+{
+       int ret;
+
+       dbg_info("(%d)\n", mode);
+
+       if (mode == 0) {
+               /* into reset */
+               ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 0);
+               if (lg_chkerr(ret))
+                       goto fail;
+
+               /* power down */
+               ret = lgdt3306a_set_reg_bit(state, 0x0000, 0, 0);
+               if (lg_chkerr(ret))
+                       goto fail;
+
+       } else {
+               /* out of reset */
+               ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 1);
+               if (lg_chkerr(ret))
+                       goto fail;
+
+               /* power up */
+               ret = lgdt3306a_set_reg_bit(state, 0x0000, 0, 1);
+               if (lg_chkerr(ret))
+                       goto fail;
+       }
+
+#ifdef DBG_DUMP
+       lgdt3306a_DumpAllRegs(state);
+#endif
+fail:
+       return ret;
+}
+
+
+static int lgdt3306a_set_vsb(struct lgdt3306a_state *state)
+{
+       u8 val;
+       int ret;
+
+       dbg_info("\n");
+
+       /* 0. Spectrum inversion detection manual; spectrum inverted */
+       ret = lgdt3306a_read_reg(state, 0x0002, &val);
+       val &= 0xf7; /* SPECINVAUTO Off */
+       val |= 0x04; /* SPECINV On */
+       ret = lgdt3306a_write_reg(state, 0x0002, val);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       /* 1. Selection of standard mode(0x08=QAM, 0x80=VSB) */
+       ret = lgdt3306a_write_reg(state, 0x0008, 0x80);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       /* 2. Bandwidth mode for VSB(6MHz) */
+       ret = lgdt3306a_read_reg(state, 0x0009, &val);
+       val &= 0xe3;
+       val |= 0x0c; /* STDOPDETTMODE[2:0]=3 */
+       ret = lgdt3306a_write_reg(state, 0x0009, val);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       /* 3. QAM mode detection mode(None) */
+       ret = lgdt3306a_read_reg(state, 0x0009, &val);
+       val &= 0xfc; /* STDOPDETCMODE[1:0]=0 */
+       ret = lgdt3306a_write_reg(state, 0x0009, val);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       /* 4. ADC sampling frequency rate(2x sampling) */
+       ret = lgdt3306a_read_reg(state, 0x000d, &val);
+       val &= 0xbf; /* SAMPLING4XFEN=0 */
+       ret = lgdt3306a_write_reg(state, 0x000d, val);
+       if (lg_chkerr(ret))
+               goto fail;
+
+#if 0
+       /* FGR - disable any AICC filtering, testing only */
+
+       ret = lgdt3306a_write_reg(state, 0x0024, 0x00);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       /* AICCFIXFREQ0 NT N-1(Video rejection) */
+       ret = lgdt3306a_write_reg(state, 0x002e, 0x00);
+       ret = lgdt3306a_write_reg(state, 0x002f, 0x00);
+       ret = lgdt3306a_write_reg(state, 0x0030, 0x00);
+
+       /* AICCFIXFREQ1 NT N-1(Audio rejection) */
+       ret = lgdt3306a_write_reg(state, 0x002b, 0x00);
+       ret = lgdt3306a_write_reg(state, 0x002c, 0x00);
+       ret = lgdt3306a_write_reg(state, 0x002d, 0x00);
+
+       /* AICCFIXFREQ2 NT Co-Channel(Video rejection) */
+       ret = lgdt3306a_write_reg(state, 0x0028, 0x00);
+       ret = lgdt3306a_write_reg(state, 0x0029, 0x00);
+       ret = lgdt3306a_write_reg(state, 0x002a, 0x00);
+
+       /* AICCFIXFREQ3 NT Co-Channel(Audio rejection) */
+       ret = lgdt3306a_write_reg(state, 0x0025, 0x00);
+       ret = lgdt3306a_write_reg(state, 0x0026, 0x00);
+       ret = lgdt3306a_write_reg(state, 0x0027, 0x00);
+
+#else
+       /* FGR - this works well for HVR-1955,1975 */
+
+       /* 5. AICCOPMODE  NT N-1 Adj. */
+       ret = lgdt3306a_write_reg(state, 0x0024, 0x5A);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       /* AICCFIXFREQ0 NT N-1(Video rejection) */
+       ret = lgdt3306a_write_reg(state, 0x002e, 0x5A);
+       ret = lgdt3306a_write_reg(state, 0x002f, 0x00);
+       ret = lgdt3306a_write_reg(state, 0x0030, 0x00);
+
+       /* AICCFIXFREQ1 NT N-1(Audio rejection) */
+       ret = lgdt3306a_write_reg(state, 0x002b, 0x36);
+       ret = lgdt3306a_write_reg(state, 0x002c, 0x00);
+       ret = lgdt3306a_write_reg(state, 0x002d, 0x00);
+
+       /* AICCFIXFREQ2 NT Co-Channel(Video rejection) */
+       ret = lgdt3306a_write_reg(state, 0x0028, 0x2A);
+       ret = lgdt3306a_write_reg(state, 0x0029, 0x00);
+       ret = lgdt3306a_write_reg(state, 0x002a, 0x00);
+
+       /* AICCFIXFREQ3 NT Co-Channel(Audio rejection) */
+       ret = lgdt3306a_write_reg(state, 0x0025, 0x06);
+       ret = lgdt3306a_write_reg(state, 0x0026, 0x00);
+       ret = lgdt3306a_write_reg(state, 0x0027, 0x00);
+#endif
+
+       ret = lgdt3306a_read_reg(state, 0x001e, &val);
+       val &= 0x0f;
+       val |= 0xa0;
+       ret = lgdt3306a_write_reg(state, 0x001e, val);
+
+       ret = lgdt3306a_write_reg(state, 0x0022, 0x08);
+
+       ret = lgdt3306a_write_reg(state, 0x0023, 0xFF);
+
+       ret = lgdt3306a_read_reg(state, 0x211f, &val);
+       val &= 0xef;
+       ret = lgdt3306a_write_reg(state, 0x211f, val);
+
+       ret = lgdt3306a_write_reg(state, 0x2173, 0x01);
+
+       ret = lgdt3306a_read_reg(state, 0x1061, &val);
+       val &= 0xf8;
+       val |= 0x04;
+       ret = lgdt3306a_write_reg(state, 0x1061, val);
+
+       ret = lgdt3306a_read_reg(state, 0x103d, &val);
+       val &= 0xcf;
+       ret = lgdt3306a_write_reg(state, 0x103d, val);
+
+       ret = lgdt3306a_write_reg(state, 0x2122, 0x40);
+
+       ret = lgdt3306a_read_reg(state, 0x2141, &val);
+       val &= 0x3f;
+       ret = lgdt3306a_write_reg(state, 0x2141, val);
+
+       ret = lgdt3306a_read_reg(state, 0x2135, &val);
+       val &= 0x0f;
+       val |= 0x70;
+       ret = lgdt3306a_write_reg(state, 0x2135, val);
+
+       ret = lgdt3306a_read_reg(state, 0x0003, &val);
+       val &= 0xf7;
+       ret = lgdt3306a_write_reg(state, 0x0003, val);
+
+       ret = lgdt3306a_read_reg(state, 0x001c, &val);
+       val &= 0x7f;
+       ret = lgdt3306a_write_reg(state, 0x001c, val);
+
+       /* 6. EQ step size */
+       ret = lgdt3306a_read_reg(state, 0x2179, &val);
+       val &= 0xf8;
+       ret = lgdt3306a_write_reg(state, 0x2179, val);
+
+       ret = lgdt3306a_read_reg(state, 0x217a, &val);
+       val &= 0xf8;
+       ret = lgdt3306a_write_reg(state, 0x217a, val);
+
+       /* 7. Reset */
+       ret = lgdt3306a_soft_reset(state);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       dbg_info("complete\n");
+fail:
+       return ret;
+}
+
+static int lgdt3306a_set_qam(struct lgdt3306a_state *state, int modulation)
+{
+       u8 val;
+       int ret;
+
+       dbg_info("modulation=%d\n", modulation);
+
+       /* 1. Selection of standard mode(0x08=QAM, 0x80=VSB) */
+       ret = lgdt3306a_write_reg(state, 0x0008, 0x08);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       /* 1a. Spectrum inversion detection to Auto */
+       ret = lgdt3306a_read_reg(state, 0x0002, &val);
+       val &= 0xfb; /* SPECINV Off */
+       val |= 0x08; /* SPECINVAUTO On */
+       ret = lgdt3306a_write_reg(state, 0x0002, val);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       /* 2. Bandwidth mode for QAM */
+       ret = lgdt3306a_read_reg(state, 0x0009, &val);
+       val &= 0xe3; /* STDOPDETTMODE[2:0]=0 VSB Off */
+       ret = lgdt3306a_write_reg(state, 0x0009, val);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       /* 3. : 64QAM/256QAM detection(manual, auto) */
+       ret = lgdt3306a_read_reg(state, 0x0009, &val);
+       val &= 0xfc;
+       val |= 0x02; /* STDOPDETCMODE[1:0]=1=Manual 2=Auto */
+       ret = lgdt3306a_write_reg(state, 0x0009, val);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       /* 3a. : 64QAM/256QAM selection for manual */
+       ret = lgdt3306a_read_reg(state, 0x101a, &val);
+       val &= 0xf8;
+       if (modulation == QAM_64)
+               val |= 0x02; /* QMDQMODE[2:0]=2=QAM64 */
+       else
+               val |= 0x04; /* QMDQMODE[2:0]=4=QAM256 */
+
+       ret = lgdt3306a_write_reg(state, 0x101a, val);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       /* 4. ADC sampling frequency rate(4x sampling) */
+       ret = lgdt3306a_read_reg(state, 0x000d, &val);
+       val &= 0xbf;
+       val |= 0x40; /* SAMPLING4XFEN=1 */
+       ret = lgdt3306a_write_reg(state, 0x000d, val);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       /* 5. No AICC operation in QAM mode */
+       ret = lgdt3306a_read_reg(state, 0x0024, &val);
+       val &= 0x00;
+       ret = lgdt3306a_write_reg(state, 0x0024, val);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       /* 6. Reset */
+       ret = lgdt3306a_soft_reset(state);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       dbg_info("complete\n");
+fail:
+       return ret;
+}
+
+static int lgdt3306a_set_modulation(struct lgdt3306a_state *state,
+                                  struct dtv_frontend_properties *p)
+{
+       int ret;
+
+       dbg_info("\n");
+
+       switch (p->modulation) {
+       case VSB_8:
+               ret = lgdt3306a_set_vsb(state);
+               break;
+       case QAM_64:
+               ret = lgdt3306a_set_qam(state, QAM_64);
+               break;
+       case QAM_256:
+               ret = lgdt3306a_set_qam(state, QAM_256);
+               break;
+       default:
+               return -EINVAL;
+       }
+       if (lg_chkerr(ret))
+               goto fail;
+
+       state->current_modulation = p->modulation;
+
+fail:
+       return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lgdt3306a_agc_setup(struct lgdt3306a_state *state,
+                             struct dtv_frontend_properties *p)
+{
+       /* TODO: anything we want to do here??? */
+       dbg_info("\n");
+
+       switch (p->modulation) {
+       case VSB_8:
+               break;
+       case QAM_64:
+       case QAM_256:
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lgdt3306a_set_inversion(struct lgdt3306a_state *state,
+                                      int inversion)
+{
+       int ret;
+
+       dbg_info("(%d)\n", inversion);
+
+       ret = lgdt3306a_set_reg_bit(state, 0x0002, 2, inversion ? 1 : 0);
+       return ret;
+}
+
+static int lgdt3306a_set_inversion_auto(struct lgdt3306a_state *state,
+                                      int enabled)
+{
+       int ret;
+
+       dbg_info("(%d)\n", enabled);
+
+       /* 0=Manual 1=Auto(QAM only) - SPECINVAUTO=0x04 */
+       ret = lgdt3306a_set_reg_bit(state, 0x0002, 3, enabled);
+       return ret;
+}
+
+static int lgdt3306a_spectral_inversion(struct lgdt3306a_state *state,
+                                      struct dtv_frontend_properties *p,
+                                      int inversion)
+{
+       int ret = 0;
+
+       dbg_info("(%d)\n", inversion);
+#if 0
+       /*
+        * FGR - spectral_inversion defaults already set for VSB and QAM;
+        * can enable later if desired
+        */
+
+       ret = lgdt3306a_set_inversion(state, inversion);
+
+       switch (p->modulation) {
+       case VSB_8:
+               /* Manual only for VSB */
+               ret = lgdt3306a_set_inversion_auto(state, 0);
+               break;
+       case QAM_64:
+       case QAM_256:
+               /* Auto ok for QAM */
+               ret = lgdt3306a_set_inversion_auto(state, 1);
+               break;
+       default:
+               ret = -EINVAL;
+       }
+#endif
+       return ret;
+}
+
+static int lgdt3306a_set_if(struct lgdt3306a_state *state,
+                          struct dtv_frontend_properties *p)
+{
+       int ret;
+       u16 if_freq_khz;
+       u8 nco1, nco2;
+
+       switch (p->modulation) {
+       case VSB_8:
+               if_freq_khz = state->cfg->vsb_if_khz;
+               break;
+       case QAM_64:
+       case QAM_256:
+               if_freq_khz = state->cfg->qam_if_khz;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (if_freq_khz) {
+       default:
+               pr_warn("IF=%d KHz is not supportted, 3250 assumed\n",
+                       if_freq_khz);
+               /* fallthrough */
+       case 3250: /* 3.25Mhz */
+               nco1 = 0x34;
+               nco2 = 0x00;
+               break;
+       case 3500: /* 3.50Mhz */
+               nco1 = 0x38;
+               nco2 = 0x00;
+               break;
+       case 4000: /* 4.00Mhz */
+               nco1 = 0x40;
+               nco2 = 0x00;
+               break;
+       case 5000: /* 5.00Mhz */
+               nco1 = 0x50;
+               nco2 = 0x00;
+               break;
+       case 5380: /* 5.38Mhz */
+               nco1 = 0x56;
+               nco2 = 0x14;
+               break;
+       }
+       ret = lgdt3306a_write_reg(state, 0x0010, nco1);
+       if (ret)
+               return ret;
+       ret = lgdt3306a_write_reg(state, 0x0011, nco2);
+       if (ret)
+               return ret;
+
+       dbg_info("if_freq=%d KHz->[%04x]\n", if_freq_khz, nco1<<8 | nco2);
+
+       return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lgdt3306a_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+       struct lgdt3306a_state *state = fe->demodulator_priv;
+
+       if (state->cfg->deny_i2c_rptr) {
+               dbg_info("deny_i2c_rptr=%d\n", state->cfg->deny_i2c_rptr);
+               return 0;
+       }
+       dbg_info("(%d)\n", enable);
+
+       /* NI2CRPTEN=0x80 */
+       return lgdt3306a_set_reg_bit(state, 0x0002, 7, enable ? 0 : 1);
+}
+
+static int lgdt3306a_sleep(struct lgdt3306a_state *state)
+{
+       int ret;
+
+       dbg_info("\n");
+       state->current_frequency = -1; /* force re-tune, when we wake */
+
+       ret = lgdt3306a_mpeg_tristate(state, 1); /* disable data bus */
+       if (lg_chkerr(ret))
+               goto fail;
+
+       ret = lgdt3306a_power(state, 0); /* power down */
+       lg_chkerr(ret);
+
+fail:
+       return 0;
+}
+
+static int lgdt3306a_fe_sleep(struct dvb_frontend *fe)
+{
+       struct lgdt3306a_state *state = fe->demodulator_priv;
+
+       return lgdt3306a_sleep(state);
+}
+
+static int lgdt3306a_init(struct dvb_frontend *fe)
+{
+       struct lgdt3306a_state *state = fe->demodulator_priv;
+       u8 val;
+       int ret;
+
+       dbg_info("\n");
+
+       /* 1. Normal operation mode */
+       ret = lgdt3306a_set_reg_bit(state, 0x0001, 0, 1); /* SIMFASTENB=0x01 */
+       if (lg_chkerr(ret))
+               goto fail;
+
+       /* 2. Spectrum inversion auto detection (Not valid for VSB) */
+       ret = lgdt3306a_set_inversion_auto(state, 0);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       /* 3. Spectrum inversion(According to the tuner configuration) */
+       ret = lgdt3306a_set_inversion(state, 1);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       /* 4. Peak-to-peak voltage of ADC input signal */
+
+       /* ADCSEL1V=0x80=1Vpp; 0x00=2Vpp */
+       ret = lgdt3306a_set_reg_bit(state, 0x0004, 7, 1);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       /* 5. ADC output data capture clock phase */
+
+       /* 0=same phase as ADC clock */
+       ret = lgdt3306a_set_reg_bit(state, 0x0004, 2, 0);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       /* 5a. ADC sampling clock source */
+
+       /* ADCCLKPLLSEL=0x08; 0=use ext clock, not PLL */
+       ret = lgdt3306a_set_reg_bit(state, 0x0004, 3, 0);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       /* 6. Automatic PLL set */
+
+       /* PLLSETAUTO=0x40; 0=off */
+       ret = lgdt3306a_set_reg_bit(state, 0x0005, 6, 0);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       if (state->cfg->xtalMHz == 24) {        /* 24MHz */
+               /* 7. Frequency for PLL output(0x2564 for 192MHz for 24MHz) */
+               ret = lgdt3306a_read_reg(state, 0x0005, &val);
+               if (lg_chkerr(ret))
+                       goto fail;
+               val &= 0xc0;
+               val |= 0x25;
+               ret = lgdt3306a_write_reg(state, 0x0005, val);
+               if (lg_chkerr(ret))
+                       goto fail;
+               ret = lgdt3306a_write_reg(state, 0x0006, 0x64);
+               if (lg_chkerr(ret))
+                       goto fail;
+
+               /* 8. ADC sampling frequency(0x180000 for 24MHz sampling) */
+               ret = lgdt3306a_read_reg(state, 0x000d, &val);
+               if (lg_chkerr(ret))
+                       goto fail;
+               val &= 0xc0;
+               val |= 0x18;
+               ret = lgdt3306a_write_reg(state, 0x000d, val);
+               if (lg_chkerr(ret))
+                       goto fail;
+
+       } else if (state->cfg->xtalMHz == 25) { /* 25MHz */
+               /* 7. Frequency for PLL output */
+               ret = lgdt3306a_read_reg(state, 0x0005, &val);
+               if (lg_chkerr(ret))
+                       goto fail;
+               val &= 0xc0;
+               val |= 0x25;
+               ret = lgdt3306a_write_reg(state, 0x0005, val);
+               if (lg_chkerr(ret))
+                       goto fail;
+               ret = lgdt3306a_write_reg(state, 0x0006, 0x64);
+               if (lg_chkerr(ret))
+                       goto fail;
+
+               /* 8. ADC sampling frequency(0x190000 for 25MHz sampling) */
+               ret = lgdt3306a_read_reg(state, 0x000d, &val);
+               if (lg_chkerr(ret))
+                       goto fail;
+               val &= 0xc0;
+               val |= 0x19;
+               ret = lgdt3306a_write_reg(state, 0x000d, val);
+               if (lg_chkerr(ret))
+                       goto fail;
+       } else {
+               pr_err("Bad xtalMHz=%d\n", state->cfg->xtalMHz);
+       }
+#if 0
+       ret = lgdt3306a_write_reg(state, 0x000e, 0x00);
+       ret = lgdt3306a_write_reg(state, 0x000f, 0x00);
+#endif
+
+       /* 9. Center frequency of input signal of ADC */
+       ret = lgdt3306a_write_reg(state, 0x0010, 0x34); /* 3.25MHz */
+       ret = lgdt3306a_write_reg(state, 0x0011, 0x00);
+
+       /* 10. Fixed gain error value */
+       ret = lgdt3306a_write_reg(state, 0x0014, 0); /* gain error=0 */
+
+       /* 10a. VSB TR BW gear shift initial step */
+       ret = lgdt3306a_read_reg(state, 0x103c, &val);
+       val &= 0x0f;
+       val |= 0x20; /* SAMGSAUTOSTL_V[3:0] = 2 */
+       ret = lgdt3306a_write_reg(state, 0x103c, val);
+
+       /* 10b. Timing offset calibration in low temperature for VSB */
+       ret = lgdt3306a_read_reg(state, 0x103d, &val);
+       val &= 0xfc;
+       val |= 0x03;
+       ret = lgdt3306a_write_reg(state, 0x103d, val);
+
+       /* 10c. Timing offset calibration in low temperature for QAM */
+       ret = lgdt3306a_read_reg(state, 0x1036, &val);
+       val &= 0xf0;
+       val |= 0x0c;
+       ret = lgdt3306a_write_reg(state, 0x1036, val);
+
+       /* 11. Using the imaginary part of CIR in CIR loading */
+       ret = lgdt3306a_read_reg(state, 0x211f, &val);
+       val &= 0xef; /* do not use imaginary of CIR */
+       ret = lgdt3306a_write_reg(state, 0x211f, val);
+
+       /* 12. Control of no signal detector function */
+       ret = lgdt3306a_read_reg(state, 0x2849, &val);
+       val &= 0xef; /* NOUSENOSIGDET=0, enable no signal detector */
+       ret = lgdt3306a_write_reg(state, 0x2849, val);
+
+       /* FGR - put demod in some known mode */
+       ret = lgdt3306a_set_vsb(state);
+
+       /* 13. TP stream format */
+       ret = lgdt3306a_mpeg_mode(state, state->cfg->mpeg_mode);
+
+       /* 14. disable output buses */
+       ret = lgdt3306a_mpeg_tristate(state, 1);
+
+       /* 15. Sleep (in reset) */
+       ret = lgdt3306a_sleep(state);
+       lg_chkerr(ret);
+
+fail:
+       return ret;
+}
+
+static int lgdt3306a_set_parameters(struct dvb_frontend *fe)
+{
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+       struct lgdt3306a_state *state = fe->demodulator_priv;
+       int ret;
+
+       dbg_info("(%d, %d)\n", p->frequency, p->modulation);
+
+       if (state->current_frequency  == p->frequency &&
+          state->current_modulation == p->modulation) {
+               dbg_info(" (already set, skipping ...)\n");
+               return 0;
+       }
+       state->current_frequency = -1;
+       state->current_modulation = -1;
+
+       ret = lgdt3306a_power(state, 1); /* power up */
+       if (lg_chkerr(ret))
+               goto fail;
+
+       if (fe->ops.tuner_ops.set_params) {
+               ret = fe->ops.tuner_ops.set_params(fe);
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 0);
+#if 0
+               if (lg_chkerr(ret))
+                       goto fail;
+               state->current_frequency = p->frequency;
+#endif
+       }
+
+       ret = lgdt3306a_set_modulation(state, p);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       ret = lgdt3306a_agc_setup(state, p);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       ret = lgdt3306a_set_if(state, p);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       ret = lgdt3306a_spectral_inversion(state, p,
+                                       state->cfg->spectral_inversion ? 1 : 0);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       ret = lgdt3306a_mpeg_mode(state, state->cfg->mpeg_mode);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       ret = lgdt3306a_mpeg_mode_polarity(state,
+                                         state->cfg->tpclk_edge,
+                                         state->cfg->tpvalid_polarity);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       ret = lgdt3306a_mpeg_tristate(state, 0); /* enable data bus */
+       if (lg_chkerr(ret))
+               goto fail;
+
+       ret = lgdt3306a_soft_reset(state);
+       if (lg_chkerr(ret))
+               goto fail;
+
+#ifdef DBG_DUMP
+       lgdt3306a_DumpAllRegs(state);
+#endif
+       state->current_frequency = p->frequency;
+fail:
+       return ret;
+}
+
+static int lgdt3306a_get_frontend(struct dvb_frontend *fe)
+{
+       struct lgdt3306a_state *state = fe->demodulator_priv;
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+
+       dbg_info("(%u, %d)\n",
+                state->current_frequency, state->current_modulation);
+
+       p->modulation = state->current_modulation;
+       p->frequency = state->current_frequency;
+       return 0;
+}
+
+static enum dvbfe_algo lgdt3306a_get_frontend_algo(struct dvb_frontend *fe)
+{
+#if 1
+       return DVBFE_ALGO_CUSTOM;
+#else
+       return DVBFE_ALGO_HW;
+#endif
+}
+
+/* ------------------------------------------------------------------------ */
+static int lgdt3306a_monitor_vsb(struct lgdt3306a_state *state)
+{
+       u8 val;
+       int ret;
+       u8 snrRef, maxPowerMan, nCombDet;
+       u16 fbDlyCir;
+
+       ret = lgdt3306a_read_reg(state, 0x21a1, &val);
+       if (ret)
+               return ret;
+       snrRef = val & 0x3f;
+
+       ret = lgdt3306a_read_reg(state, 0x2185, &maxPowerMan);
+       if (ret)
+               return ret;
+
+       ret = lgdt3306a_read_reg(state, 0x2191, &val);
+       if (ret)
+               return ret;
+       nCombDet = (val & 0x80) >> 7;
+
+       ret = lgdt3306a_read_reg(state, 0x2180, &val);
+       if (ret)
+               return ret;
+       fbDlyCir = (val & 0x03) << 8;
+
+       ret = lgdt3306a_read_reg(state, 0x2181, &val);
+       if (ret)
+               return ret;
+       fbDlyCir |= val;
+
+       dbg_info("snrRef=%d maxPowerMan=0x%x nCombDet=%d fbDlyCir=0x%x\n",
+               snrRef, maxPowerMan, nCombDet, fbDlyCir);
+
+       /* Carrier offset sub loop bandwidth */
+       ret = lgdt3306a_read_reg(state, 0x1061, &val);
+       if (ret)
+               return ret;
+       val &= 0xf8;
+       if ((snrRef > 18) && (maxPowerMan > 0x68)
+           && (nCombDet == 0x01)
+           && ((fbDlyCir == 0x03FF) || (fbDlyCir < 0x6C))) {
+               /* SNR is over 18dB and no ghosting */
+               val |= 0x00; /* final bandwidth = 0 */
+       } else {
+               val |= 0x04; /* final bandwidth = 4 */
+       }
+       ret = lgdt3306a_write_reg(state, 0x1061, val);
+       if (ret)
+               return ret;
+
+       /* Adjust Notch Filter */
+       ret = lgdt3306a_read_reg(state, 0x0024, &val);
+       if (ret)
+               return ret;
+       val &= 0x0f;
+       if (nCombDet == 0) { /* Turn on the Notch Filter */
+               val |= 0x50;
+       }
+       ret = lgdt3306a_write_reg(state, 0x0024, val);
+       if (ret)
+               return ret;
+
+       /* VSB Timing Recovery output normalization */
+       ret = lgdt3306a_read_reg(state, 0x103d, &val);
+       if (ret)
+               return ret;
+       val &= 0xcf;
+       val |= 0x20;
+       ret = lgdt3306a_write_reg(state, 0x103d, val);
+
+       return ret;
+}
+
+static enum lgdt3306a_modulation
+lgdt3306a_check_oper_mode(struct lgdt3306a_state *state)
+{
+       u8 val = 0;
+       int ret;
+
+       ret = lgdt3306a_read_reg(state, 0x0081, &val);
+       if (ret)
+               goto err;
+
+       if (val & 0x80) {
+               dbg_info("VSB\n");
+               return LG3306_VSB;
+       }
+       if (val & 0x08) {
+               ret = lgdt3306a_read_reg(state, 0x00a6, &val);
+               if (ret)
+                       goto err;
+               val = val >> 2;
+               if (val & 0x01) {
+                       dbg_info("QAM256\n");
+                       return LG3306_QAM256;
+               }
+               dbg_info("QAM64\n");
+               return LG3306_QAM64;
+       }
+err:
+       pr_warn("UNKNOWN\n");
+       return LG3306_UNKNOWN_MODE;
+}
+
+static enum lgdt3306a_lock_status
+lgdt3306a_check_lock_status(struct lgdt3306a_state *state,
+                           enum lgdt3306a_lock_check whatLock)
+{
+       u8 val = 0;
+       int ret;
+       enum lgdt3306a_modulation       modeOper;
+       enum lgdt3306a_lock_status lockStatus;
+
+       modeOper = LG3306_UNKNOWN_MODE;
+
+       switch (whatLock) {
+       case LG3306_SYNC_LOCK:
+       {
+               ret = lgdt3306a_read_reg(state, 0x00a6, &val);
+               if (ret)
+                       return ret;
+
+               if ((val & 0x80) == 0x80)
+                       lockStatus = LG3306_LOCK;
+               else
+                       lockStatus = LG3306_UNLOCK;
+
+               dbg_info("SYNC_LOCK=%x\n", lockStatus);
+               break;
+       }
+       case LG3306_AGC_LOCK:
+       {
+               ret = lgdt3306a_read_reg(state, 0x0080, &val);
+               if (ret)
+                       return ret;
+
+               if ((val & 0x40) == 0x40)
+                       lockStatus = LG3306_LOCK;
+               else
+                       lockStatus = LG3306_UNLOCK;
+
+               dbg_info("AGC_LOCK=%x\n", lockStatus);
+               break;
+       }
+       case LG3306_TR_LOCK:
+       {
+               modeOper = lgdt3306a_check_oper_mode(state);
+               if ((modeOper == LG3306_QAM64) || (modeOper == LG3306_QAM256)) {
+                       ret = lgdt3306a_read_reg(state, 0x1094, &val);
+                       if (ret)
+                               return ret;
+
+                       if ((val & 0x80) == 0x80)
+                               lockStatus = LG3306_LOCK;
+                       else
+                               lockStatus = LG3306_UNLOCK;
+               } else
+                       lockStatus = LG3306_UNKNOWN_LOCK;
+
+               dbg_info("TR_LOCK=%x\n", lockStatus);
+               break;
+       }
+       case LG3306_FEC_LOCK:
+       {
+               modeOper = lgdt3306a_check_oper_mode(state);
+               if ((modeOper == LG3306_QAM64) || (modeOper == LG3306_QAM256)) {
+                       ret = lgdt3306a_read_reg(state, 0x0080, &val);
+                       if (ret)
+                               return ret;
+
+                       if ((val & 0x10) == 0x10)
+                               lockStatus = LG3306_LOCK;
+                       else
+                               lockStatus = LG3306_UNLOCK;
+               } else
+                       lockStatus = LG3306_UNKNOWN_LOCK;
+
+               dbg_info("FEC_LOCK=%x\n", lockStatus);
+               break;
+       }
+
+       default:
+               lockStatus = LG3306_UNKNOWN_LOCK;
+               pr_warn("UNKNOWN whatLock=%d\n", whatLock);
+               break;
+       }
+
+       return lockStatus;
+}
+
+static enum lgdt3306a_neverlock_status
+lgdt3306a_check_neverlock_status(struct lgdt3306a_state *state)
+{
+       u8 val = 0;
+       int ret;
+       enum lgdt3306a_neverlock_status lockStatus;
+
+       ret = lgdt3306a_read_reg(state, 0x0080, &val);
+       if (ret)
+               return ret;
+       lockStatus = (enum lgdt3306a_neverlock_status)(val & 0x03);
+
+       dbg_info("NeverLock=%d", lockStatus);
+
+       return lockStatus;
+}
+
+static int lgdt3306a_pre_monitoring(struct lgdt3306a_state *state)
+{
+       u8 val = 0;
+       int ret;
+       u8 currChDiffACQ, snrRef, mainStrong, aiccrejStatus;
+
+       /* Channel variation */
+       ret = lgdt3306a_read_reg(state, 0x21bc, &currChDiffACQ);
+       if (ret)
+               return ret;
+
+       /* SNR of Frame sync */
+       ret = lgdt3306a_read_reg(state, 0x21a1, &val);
+       if (ret)
+               return ret;
+       snrRef = val & 0x3f;
+
+       /* Strong Main CIR */
+       ret = lgdt3306a_read_reg(state, 0x2199, &val);
+       if (ret)
+               return ret;
+       mainStrong = (val & 0x40) >> 6;
+
+       ret = lgdt3306a_read_reg(state, 0x0090, &val);
+       if (ret)
+               return ret;
+       aiccrejStatus = (val & 0xf0) >> 4;
+
+       dbg_info("snrRef=%d mainStrong=%d aiccrejStatus=%d currChDiffACQ=0x%x\n",
+               snrRef, mainStrong, aiccrejStatus, currChDiffACQ);
+
+#if 0
+       /* Dynamic ghost exists */
+       if ((mainStrong == 0) && (currChDiffACQ > 0x70))
+#endif
+       if (mainStrong == 0) {
+               ret = lgdt3306a_read_reg(state, 0x2135, &val);
+               if (ret)
+                       return ret;
+               val &= 0x0f;
+               val |= 0xa0;
+               ret = lgdt3306a_write_reg(state, 0x2135, val);
+               if (ret)
+                       return ret;
+
+               ret = lgdt3306a_read_reg(state, 0x2141, &val);
+               if (ret)
+                       return ret;
+               val &= 0x3f;
+               val |= 0x80;
+               ret = lgdt3306a_write_reg(state, 0x2141, val);
+               if (ret)
+                       return ret;
+
+               ret = lgdt3306a_write_reg(state, 0x2122, 0x70);
+               if (ret)
+                       return ret;
+       } else { /* Weak ghost or static channel */
+               ret = lgdt3306a_read_reg(state, 0x2135, &val);
+               if (ret)
+                       return ret;
+               val &= 0x0f;
+               val |= 0x70;
+               ret = lgdt3306a_write_reg(state, 0x2135, val);
+               if (ret)
+                       return ret;
+
+               ret = lgdt3306a_read_reg(state, 0x2141, &val);
+               if (ret)
+                       return ret;
+               val &= 0x3f;
+               val |= 0x40;
+               ret = lgdt3306a_write_reg(state, 0x2141, val);
+               if (ret)
+                       return ret;
+
+               ret = lgdt3306a_write_reg(state, 0x2122, 0x40);
+               if (ret)
+                       return ret;
+       }
+       return 0;
+}
+
+static enum lgdt3306a_lock_status
+lgdt3306a_sync_lock_poll(struct lgdt3306a_state *state)
+{
+       enum lgdt3306a_lock_status syncLockStatus = LG3306_UNLOCK;
+       int     i;
+
+       for (i = 0; i < 2; i++) {
+               msleep(30);
+
+               syncLockStatus = lgdt3306a_check_lock_status(state,
+                                                            LG3306_SYNC_LOCK);
+
+               if (syncLockStatus == LG3306_LOCK) {
+                       dbg_info("locked(%d)\n", i);
+                       return LG3306_LOCK;
+               }
+       }
+       dbg_info("not locked\n");
+       return LG3306_UNLOCK;
+}
+
+static enum lgdt3306a_lock_status
+lgdt3306a_fec_lock_poll(struct lgdt3306a_state *state)
+{
+       enum lgdt3306a_lock_status FECLockStatus = LG3306_UNLOCK;
+       int     i;
+
+       for (i = 0; i < 2; i++) {
+               msleep(30);
+
+               FECLockStatus = lgdt3306a_check_lock_status(state,
+                                                           LG3306_FEC_LOCK);
+
+               if (FECLockStatus == LG3306_LOCK) {
+                       dbg_info("locked(%d)\n", i);
+                       return FECLockStatus;
+               }
+       }
+       dbg_info("not locked\n");
+       return FECLockStatus;
+}
+
+static enum lgdt3306a_neverlock_status
+lgdt3306a_neverlock_poll(struct lgdt3306a_state *state)
+{
+       enum lgdt3306a_neverlock_status NLLockStatus = LG3306_NL_FAIL;
+       int     i;
+
+       for (i = 0; i < 5; i++) {
+               msleep(30);
+
+               NLLockStatus = lgdt3306a_check_neverlock_status(state);
+
+               if (NLLockStatus == LG3306_NL_LOCK) {
+                       dbg_info("NL_LOCK(%d)\n", i);
+                       return NLLockStatus;
+               }
+       }
+       dbg_info("NLLockStatus=%d\n", NLLockStatus);
+       return NLLockStatus;
+}
+
+static u8 lgdt3306a_get_packet_error(struct lgdt3306a_state *state)
+{
+       u8 val;
+       int ret;
+
+       ret = lgdt3306a_read_reg(state, 0x00fa, &val);
+       if (ret)
+               return ret;
+
+       return val;
+}
+
+static const u32 valx_x10[] = {
+       10,  11,  13,  15,  17,  20,  25,  33,  41,  50,  59,  73,  87,  100
+};
+static const u32 log10x_x1000[] = {
+       0,   41, 114, 176, 230, 301, 398, 518, 613, 699, 771, 863, 939, 1000
+};
+
+static u32 log10_x1000(u32 x)
+{
+       u32 diff_val, step_val, step_log10;
+       u32 log_val = 0;
+       u32 i;
+
+       if (x <= 0)
+               return -1000000; /* signal error */
+
+       if (x == 10)
+               return 0; /* log(1)=0 */
+
+       if (x < 10) {
+               while (x < 10) {
+                       x = x * 10;
+                       log_val--;
+               }
+       } else {        /* x > 10 */
+               while (x >= 100) {
+                       x = x / 10;
+                       log_val++;
+               }
+       }
+       log_val *= 1000;
+
+       if (x == 10) /* was our input an exact multiple of 10 */
+               return log_val; /* don't need to interpolate */
+
+       /* find our place on the log curve */
+       for (i = 1; i < ARRAY_SIZE(valx_x10); i++) {
+               if (valx_x10[i] >= x)
+                       break;
+       }
+       if (i == ARRAY_SIZE(valx_x10))
+               return log_val + log10x_x1000[i - 1];
+
+       diff_val   = x - valx_x10[i-1];
+       step_val   = valx_x10[i] - valx_x10[i - 1];
+       step_log10 = log10x_x1000[i] - log10x_x1000[i - 1];
+
+       /* do a linear interpolation to get in-between values */
+       return log_val + log10x_x1000[i - 1] +
+               ((diff_val*step_log10) / step_val);
+}
+
+static u32 lgdt3306a_calculate_snr_x100(struct lgdt3306a_state *state)
+{
+       u32 mse; /* Mean-Square Error */
+       u32 pwr; /* Constelation power */
+       u32 snr_x100;
+
+       mse = (read_reg(state, 0x00ec) << 8) |
+             (read_reg(state, 0x00ed));
+       pwr = (read_reg(state, 0x00e8) << 8) |
+             (read_reg(state, 0x00e9));
+
+       if (mse == 0) /* no signal */
+               return 0;
+
+       snr_x100 = log10_x1000((pwr * 10000) / mse) - 3000;
+       dbg_info("mse=%u, pwr=%u, snr_x100=%d\n", mse, pwr, snr_x100);
+
+       return snr_x100;
+}
+
+static enum lgdt3306a_lock_status
+lgdt3306a_vsb_lock_poll(struct lgdt3306a_state *state)
+{
+       int ret;
+       u8 cnt = 0;
+       u8 packet_error;
+       u32 snr;
+
+       for (cnt = 0; cnt < 10; cnt++) {
+               if (lgdt3306a_sync_lock_poll(state) == LG3306_UNLOCK) {
+                       dbg_info("no sync lock!\n");
+                       return LG3306_UNLOCK;
+               }
+
+               msleep(20);
+               ret = lgdt3306a_pre_monitoring(state);
+               if (ret)
+                       break;
+
+               packet_error = lgdt3306a_get_packet_error(state);
+               snr = lgdt3306a_calculate_snr_x100(state);
+               dbg_info("cnt=%d errors=%d snr=%d\n", cnt, packet_error, snr);
+
+               if ((snr >= 1500) && (packet_error < 0xff))
+                       return LG3306_LOCK;
+       }
+
+       dbg_info("not locked!\n");
+       return LG3306_UNLOCK;
+}
+
+static enum lgdt3306a_lock_status
+lgdt3306a_qam_lock_poll(struct lgdt3306a_state *state)
+{
+       u8 cnt;
+       u8 packet_error;
+       u32     snr;
+
+       for (cnt = 0; cnt < 10; cnt++) {
+               if (lgdt3306a_fec_lock_poll(state) == LG3306_UNLOCK) {
+                       dbg_info("no fec lock!\n");
+                       return LG3306_UNLOCK;
+               }
+
+               msleep(20);
+
+               packet_error = lgdt3306a_get_packet_error(state);
+               snr = lgdt3306a_calculate_snr_x100(state);
+               dbg_info("cnt=%d errors=%d snr=%d\n", cnt, packet_error, snr);
+
+               if ((snr >= 1500) && (packet_error < 0xff))
+                       return LG3306_LOCK;
+       }
+
+       dbg_info("not locked!\n");
+       return LG3306_UNLOCK;
+}
+
+static int lgdt3306a_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+       struct lgdt3306a_state *state = fe->demodulator_priv;
+       u16 strength = 0;
+       int ret = 0;
+
+       if (fe->ops.tuner_ops.get_rf_strength) {
+               ret = fe->ops.tuner_ops.get_rf_strength(fe, &strength);
+               if (ret == 0)
+                       dbg_info("strength=%d\n", strength);
+               else
+                       dbg_info("fe->ops.tuner_ops.get_rf_strength() failed\n");
+       }
+
+       *status = 0;
+       if (lgdt3306a_neverlock_poll(state) == LG3306_NL_LOCK) {
+               *status |= FE_HAS_SIGNAL;
+               *status |= FE_HAS_CARRIER;
+
+               switch (state->current_modulation) {
+               case QAM_256:
+               case QAM_64:
+                       if (lgdt3306a_qam_lock_poll(state) == LG3306_LOCK) {
+                               *status |= FE_HAS_VITERBI;
+                               *status |= FE_HAS_SYNC;
+
+                               *status |= FE_HAS_LOCK;
+                       }
+                       break;
+               case VSB_8:
+                       if (lgdt3306a_vsb_lock_poll(state) == LG3306_LOCK) {
+                               *status |= FE_HAS_VITERBI;
+                               *status |= FE_HAS_SYNC;
+
+                               *status |= FE_HAS_LOCK;
+
+                               ret = lgdt3306a_monitor_vsb(state);
+                       }
+                       break;
+               default:
+                       ret = -EINVAL;
+               }
+       }
+       return ret;
+}
+
+
+static int lgdt3306a_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+       struct lgdt3306a_state *state = fe->demodulator_priv;
+
+       state->snr = lgdt3306a_calculate_snr_x100(state);
+       /* report SNR in dB * 10 */
+       *snr = state->snr/10;
+
+       return 0;
+}
+
+static int lgdt3306a_read_signal_strength(struct dvb_frontend *fe,
+                                        u16 *strength)
+{
+       /*
+        * Calculate some sort of "strength" from SNR
+        */
+       struct lgdt3306a_state *state = fe->demodulator_priv;
+       u16 snr; /* snr_x10 */
+       int ret;
+       u32 ref_snr; /* snr*100 */
+       u32 str;
+
+       *strength = 0;
+
+       switch (state->current_modulation) {
+       case VSB_8:
+                ref_snr = 1600; /* 16dB */
+                break;
+       case QAM_64:
+                ref_snr = 2200; /* 22dB */
+                break;
+       case QAM_256:
+                ref_snr = 2800; /* 28dB */
+                break;
+       default:
+               return -EINVAL;
+       }
+
+       ret = fe->ops.read_snr(fe, &snr);
+       if (lg_chkerr(ret))
+               goto fail;
+
+       if (state->snr <= (ref_snr - 100))
+               str = 0;
+       else if (state->snr <= ref_snr)
+               str = (0xffff * 65) / 100; /* 65% */
+       else {
+               str = state->snr - ref_snr;
+               str /= 50;
+               str += 78; /* 78%-100% */
+               if (str > 100)
+                       str = 100;
+               str = (0xffff * str) / 100;
+       }
+       *strength = (u16)str;
+       dbg_info("strength=%u\n", *strength);
+
+fail:
+       return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lgdt3306a_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+       struct lgdt3306a_state *state = fe->demodulator_priv;
+       u32 tmp;
+
+       *ber = 0;
+#if 1
+       /* FGR - FIXME - I don't know what value is expected by dvb_core
+        * what is the scale of the value?? */
+       tmp =              read_reg(state, 0x00fc); /* NBERVALUE[24-31] */
+       tmp = (tmp << 8) | read_reg(state, 0x00fd); /* NBERVALUE[16-23] */
+       tmp = (tmp << 8) | read_reg(state, 0x00fe); /* NBERVALUE[8-15] */
+       tmp = (tmp << 8) | read_reg(state, 0x00ff); /* NBERVALUE[0-7] */
+       *ber = tmp;
+       dbg_info("ber=%u\n", tmp);
+#endif
+       return 0;
+}
+
+static int lgdt3306a_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+       struct lgdt3306a_state *state = fe->demodulator_priv;
+
+       *ucblocks = 0;
+#if 1
+       /* FGR - FIXME - I don't know what value is expected by dvb_core
+        * what happens when value wraps? */
+       *ucblocks = read_reg(state, 0x00f4); /* TPIFTPERRCNT[0-7] */
+       dbg_info("ucblocks=%u\n", *ucblocks);
+#endif
+
+       return 0;
+}
+
+static int lgdt3306a_tune(struct dvb_frontend *fe, bool re_tune,
+                         unsigned int mode_flags, unsigned int *delay,
+                         fe_status_t *status)
+{
+       int ret = 0;
+       struct lgdt3306a_state *state = fe->demodulator_priv;
+
+       dbg_info("re_tune=%u\n", re_tune);
+
+       if (re_tune) {
+               state->current_frequency = -1; /* force re-tune */
+               ret = lgdt3306a_set_parameters(fe);
+               if (ret != 0)
+                       return ret;
+       }
+       *delay = 125;
+       ret = lgdt3306a_read_status(fe, status);
+
+       return ret;
+}
+
+static int lgdt3306a_get_tune_settings(struct dvb_frontend *fe,
+                                      struct dvb_frontend_tune_settings
+                                      *fe_tune_settings)
+{
+       fe_tune_settings->min_delay_ms = 100;
+       dbg_info("\n");
+       return 0;
+}
+
+static int lgdt3306a_search(struct dvb_frontend *fe)
+{
+       fe_status_t status = 0;
+       int i, ret;
+
+       /* set frontend */
+       ret = lgdt3306a_set_parameters(fe);
+       if (ret)
+               goto error;
+
+       /* wait frontend lock */
+       for (i = 20; i > 0; i--) {
+               dbg_info(": loop=%d\n", i);
+               msleep(50);
+               ret = lgdt3306a_read_status(fe, &status);
+               if (ret)
+                       goto error;
+
+               if (status & FE_HAS_LOCK)
+                       break;
+       }
+
+       /* check if we have a valid signal */
+       if (status & FE_HAS_LOCK)
+               return DVBFE_ALGO_SEARCH_SUCCESS;
+       else
+               return DVBFE_ALGO_SEARCH_AGAIN;
+
+error:
+       dbg_info("failed (%d)\n", ret);
+       return DVBFE_ALGO_SEARCH_ERROR;
+}
+
+static void lgdt3306a_release(struct dvb_frontend *fe)
+{
+       struct lgdt3306a_state *state = fe->demodulator_priv;
+
+       dbg_info("\n");
+       kfree(state);
+}
+
+static struct dvb_frontend_ops lgdt3306a_ops;
+
+struct dvb_frontend *lgdt3306a_attach(const struct lgdt3306a_config *config,
+                                     struct i2c_adapter *i2c_adap)
+{
+       struct lgdt3306a_state *state = NULL;
+       int ret;
+       u8 val;
+
+       dbg_info("(%d-%04x)\n",
+              i2c_adap ? i2c_adapter_id(i2c_adap) : 0,
+              config ? config->i2c_addr : 0);
+
+       state = kzalloc(sizeof(struct lgdt3306a_state), GFP_KERNEL);
+       if (state == NULL)
+               goto fail;
+
+       state->cfg = config;
+       state->i2c_adap = i2c_adap;
+
+       memcpy(&state->frontend.ops, &lgdt3306a_ops,
+              sizeof(struct dvb_frontend_ops));
+       state->frontend.demodulator_priv = state;
+
+       /* verify that we're talking to a lg3306a */
+       /* FGR - NOTE - there is no obvious ChipId to check; we check
+        * some "known" bits after reset, but it's still just a guess */
+       ret = lgdt3306a_read_reg(state, 0x0000, &val);
+       if (lg_chkerr(ret))
+               goto fail;
+       if ((val & 0x74) != 0x74) {
+               pr_warn("expected 0x74, got 0x%x\n", (val & 0x74));
+#if 0
+               /* FIXME - re-enable when we know this is right */
+               goto fail;
+#endif
+       }
+       ret = lgdt3306a_read_reg(state, 0x0001, &val);
+       if (lg_chkerr(ret))
+               goto fail;
+       if ((val & 0xf6) != 0xc6) {
+               pr_warn("expected 0xc6, got 0x%x\n", (val & 0xf6));
+#if 0
+               /* FIXME - re-enable when we know this is right */
+               goto fail;
+#endif
+       }
+       ret = lgdt3306a_read_reg(state, 0x0002, &val);
+       if (lg_chkerr(ret))
+               goto fail;
+       if ((val & 0x73) != 0x03) {
+               pr_warn("expected 0x03, got 0x%x\n", (val & 0x73));
+#if 0
+               /* FIXME - re-enable when we know this is right */
+               goto fail;
+#endif
+       }
+
+       state->current_frequency = -1;
+       state->current_modulation = -1;
+
+       lgdt3306a_sleep(state);
+
+       return &state->frontend;
+
+fail:
+       pr_warn("unable to detect LGDT3306A hardware\n");
+       kfree(state);
+       return NULL;
+}
+EXPORT_SYMBOL(lgdt3306a_attach);
+
+#ifdef DBG_DUMP
+
+static const short regtab[] = {
+       0x0000, /* SOFTRSTB 1'b1 1'b1 1'b1 ADCPDB 1'b1 PLLPDB GBBPDB 11111111 */
+       0x0001, /* 1'b1 1'b1 1'b0 1'b0 AUTORPTRS */
+       0x0002, /* NI2CRPTEN 1'b0 1'b0 1'b0 SPECINVAUT */
+       0x0003, /* AGCRFOUT */
+       0x0004, /* ADCSEL1V ADCCNT ADCCNF ADCCNS ADCCLKPLL */
+       0x0005, /* PLLINDIVSE */
+       0x0006, /* PLLCTRL[7:0] 11100001 */
+       0x0007, /* SYSINITWAITTIME[7:0] (msec) 00001000 */
+       0x0008, /* STDOPMODE[7:0] 10000000 */
+       0x0009, /* 1'b0 1'b0 1'b0 STDOPDETTMODE[2:0] STDOPDETCMODE[1:0] 00011110 */
+       0x000a, /* DAFTEN 1'b1 x x SCSYSLOCK */
+       0x000b, /* SCSYSLOCKCHKTIME[7:0] (10msec) 01100100 */
+       0x000d, /* x SAMPLING4 */
+       0x000e, /* SAMFREQ[15:8] 00000000 */
+       0x000f, /* SAMFREQ[7:0] 00000000 */
+       0x0010, /* IFFREQ[15:8] 01100000 */
+       0x0011, /* IFFREQ[7:0] 00000000 */
+       0x0012, /* AGCEN AGCREFMO */
+       0x0013, /* AGCRFFIXB AGCIFFIXB AGCLOCKDETRNGSEL[1:0] 1'b1 1'b0 1'b0 1'b0 11101000 */
+       0x0014, /* AGCFIXVALUE[7:0] 01111111 */
+       0x0015, /* AGCREF[15:8] 00001010 */
+       0x0016, /* AGCREF[7:0] 11100100 */
+       0x0017, /* AGCDELAY[7:0] 00100000 */
+       0x0018, /* AGCRFBW[3:0] AGCIFBW[3:0] 10001000 */
+       0x0019, /* AGCUDOUTMODE[1:0] AGCUDCTRLLEN[1:0] AGCUDCTRL */
+       0x001c, /* 1'b1 PFEN MFEN AICCVSYNC */
+       0x001d, /* 1'b0 1'b1 1'b0 1'b1 AICCVSYNC */
+       0x001e, /* AICCALPHA[3:0] 1'b1 1'b0 1'b1 1'b0 01111010 */
+       0x001f, /* AICCDETTH[19:16] AICCOFFTH[19:16] 00000000 */
+       0x0020, /* AICCDETTH[15:8] 01111100 */
+       0x0021, /* AICCDETTH[7:0] 00000000 */
+       0x0022, /* AICCOFFTH[15:8] 00000101 */
+       0x0023, /* AICCOFFTH[7:0] 11100000 */
+       0x0024, /* AICCOPMODE3[1:0] AICCOPMODE2[1:0] AICCOPMODE1[1:0] AICCOPMODE0[1:0] 00000000 */
+       0x0025, /* AICCFIXFREQ3[23:16] 00000000 */
+       0x0026, /* AICCFIXFREQ3[15:8] 00000000 */
+       0x0027, /* AICCFIXFREQ3[7:0] 00000000 */
+       0x0028, /* AICCFIXFREQ2[23:16] 00000000 */
+       0x0029, /* AICCFIXFREQ2[15:8] 00000000 */
+       0x002a, /* AICCFIXFREQ2[7:0] 00000000 */
+       0x002b, /* AICCFIXFREQ1[23:16] 00000000 */
+       0x002c, /* AICCFIXFREQ1[15:8] 00000000 */
+       0x002d, /* AICCFIXFREQ1[7:0] 00000000 */
+       0x002e, /* AICCFIXFREQ0[23:16] 00000000 */
+       0x002f, /* AICCFIXFREQ0[15:8] 00000000 */
+       0x0030, /* AICCFIXFREQ0[7:0] 00000000 */
+       0x0031, /* 1'b0 1'b1 1'b0 1'b0 x DAGC1STER */
+       0x0032, /* DAGC1STEN DAGC1STER */
+       0x0033, /* DAGC1STREF[15:8] 00001010 */
+       0x0034, /* DAGC1STREF[7:0] 11100100 */
+       0x0035, /* DAGC2NDE */
+       0x0036, /* DAGC2NDREF[15:8] 00001010 */
+       0x0037, /* DAGC2NDREF[7:0] 10000000 */
+       0x0038, /* DAGC2NDLOCKDETRNGSEL[1:0] */
+       0x003d, /* 1'b1 SAMGEARS */
+       0x0040, /* SAMLFGMA */
+       0x0041, /* SAMLFBWM */
+       0x0044, /* 1'b1 CRGEARSHE */
+       0x0045, /* CRLFGMAN */
+       0x0046, /* CFLFBWMA */
+       0x0047, /* CRLFGMAN */
+       0x0048, /* x x x x CRLFGSTEP_VS[3:0] xxxx1001 */
+       0x0049, /* CRLFBWMA */
+       0x004a, /* CRLFBWMA */
+       0x0050, /* 1'b0 1'b1 1'b1 1'b0 MSECALCDA */
+       0x0070, /* TPOUTEN TPIFEN TPCLKOUTE */
+       0x0071, /* TPSENB TPSSOPBITE */
+       0x0073, /* TP47HINS x x CHBERINT PERMODE[1:0] PERINT[1:0] 1xx11100 */
+       0x0075, /* x x x x x IQSWAPCTRL[2:0] xxxxx000 */
+       0x0076, /* NBERCON NBERST NBERPOL NBERWSYN */
+       0x0077, /* x NBERLOSTTH[2:0] NBERACQTH[3:0] x0000000 */
+       0x0078, /* NBERPOLY[31:24] 00000000 */
+       0x0079, /* NBERPOLY[23:16] 00000000 */
+       0x007a, /* NBERPOLY[15:8] 00000000 */
+       0x007b, /* NBERPOLY[7:0] 00000000 */
+       0x007c, /* NBERPED[31:24] 00000000 */
+       0x007d, /* NBERPED[23:16] 00000000 */
+       0x007e, /* NBERPED[15:8] 00000000 */
+       0x007f, /* NBERPED[7:0] 00000000 */
+       0x0080, /* x AGCLOCK DAGCLOCK SYSLOCK x x NEVERLOCK[1:0] */
+       0x0085, /* SPECINVST */
+       0x0088, /* SYSLOCKTIME[15:8] */
+       0x0089, /* SYSLOCKTIME[7:0] */
+       0x008c, /* FECLOCKTIME[15:8] */
+       0x008d, /* FECLOCKTIME[7:0] */
+       0x008e, /* AGCACCOUT[15:8] */
+       0x008f, /* AGCACCOUT[7:0] */
+       0x0090, /* AICCREJSTATUS[3:0] AICCREJBUSY[3:0] */
+       0x0091, /* AICCVSYNC */
+       0x009c, /* CARRFREQOFFSET[15:8] */
+       0x009d, /* CARRFREQOFFSET[7:0] */
+       0x00a1, /* SAMFREQOFFSET[23:16] */
+       0x00a2, /* SAMFREQOFFSET[15:8] */
+       0x00a3, /* SAMFREQOFFSET[7:0] */
+       0x00a6, /* SYNCLOCK SYNCLOCKH */
+#if 0 /* covered elsewhere */
+       0x00e8, /* CONSTPWR[15:8] */
+       0x00e9, /* CONSTPWR[7:0] */
+       0x00ea, /* BMSE[15:8] */
+       0x00eb, /* BMSE[7:0] */
+       0x00ec, /* MSE[15:8] */
+       0x00ed, /* MSE[7:0] */
+       0x00ee, /* CONSTI[7:0] */
+       0x00ef, /* CONSTQ[7:0] */
+#endif
+       0x00f4, /* TPIFTPERRCNT[7:0] */
+       0x00f5, /* TPCORREC */
+       0x00f6, /* VBBER[15:8] */
+       0x00f7, /* VBBER[7:0] */
+       0x00f8, /* VABER[15:8] */
+       0x00f9, /* VABER[7:0] */
+       0x00fa, /* TPERRCNT[7:0] */
+       0x00fb, /* NBERLOCK x x x x x x x */
+       0x00fc, /* NBERVALUE[31:24] */
+       0x00fd, /* NBERVALUE[23:16] */
+       0x00fe, /* NBERVALUE[15:8] */
+       0x00ff, /* NBERVALUE[7:0] */
+       0x1000, /* 1'b0 WODAGCOU */
+       0x1005, /* x x 1'b1 1'b1 x SRD_Q_QM */
+       0x1009, /* SRDWAITTIME[7:0] (10msec) 00100011 */
+       0x100a, /* SRDWAITTIME_CQS[7:0] (msec) 01100100 */
+       0x101a, /* x 1'b1 1'b0 1'b0 x QMDQAMMODE[2:0] x100x010 */
+       0x1036, /* 1'b0 1'b1 1'b0 1'b0 SAMGSEND_CQS[3:0] 01001110 */
+       0x103c, /* SAMGSAUTOSTL_V[3:0] SAMGSAUTOEDL_V[3:0] 01000110 */
+       0x103d, /* 1'b1 1'b1 SAMCNORMBP_V[1:0] 1'b0 1'b0 SAMMODESEL_V[1:0] 11100001 */
+       0x103f, /* SAMZTEDSE */
+       0x105d, /* EQSTATUSE */
+       0x105f, /* x PMAPG2_V[2:0] x DMAPG2_V[2:0] x001x011 */
+       0x1060, /* 1'b1 EQSTATUSE */
+       0x1061, /* CRMAPBWSTL_V[3:0] CRMAPBWEDL_V[3:0] 00000100 */
+       0x1065, /* 1'b0 x CRMODE_V[1:0] 1'b1 x 1'b1 x 0x111x1x */
+       0x1066, /* 1'b0 1'b0 1'b1 1'b0 1'b1 PNBOOSTSE */
+       0x1068, /* CREPHNGAIN2_V[3:0] CREPHNPBW_V[3:0] 10010001 */
+       0x106e, /* x x x x x CREPHNEN_ */
+       0x106f, /* CREPHNTH_V[7:0] 00010101 */
+       0x1072, /* CRSWEEPN */
+       0x1073, /* CRPGAIN_V[3:0] x x 1'b1 1'b1 1001xx11 */
+       0x1074, /* CRPBW_V[3:0] x x 1'b1 1'b1 0001xx11 */
+       0x1080, /* DAFTSTATUS[1:0] x x x x x x */
+       0x1081, /* SRDSTATUS[1:0] x x x x x SRDLOCK */
+       0x10a9, /* EQSTATUS_CQS[1:0] x x x x x x */
+       0x10b7, /* EQSTATUS_V[1:0] x x x x x x */
+#if 0 /* SMART_ANT */
+       0x1f00, /* MODEDETE */
+       0x1f01, /* x x x x x x x SFNRST xxxxxxx0 */
+       0x1f03, /* NUMOFANT[7:0] 10000000 */
+       0x1f04, /* x SELMASK[6:0] x0000000 */
+       0x1f05, /* x SETMASK[6:0] x0000000 */
+       0x1f06, /* x TXDATA[6:0] x0000000 */
+       0x1f07, /* x CHNUMBER[6:0] x0000000 */
+       0x1f09, /* AGCTIME[23:16] 10011000 */
+       0x1f0a, /* AGCTIME[15:8] 10010110 */
+       0x1f0b, /* AGCTIME[7:0] 10000000 */
+       0x1f0c, /* ANTTIME[31:24] 00000000 */
+       0x1f0d, /* ANTTIME[23:16] 00000011 */
+       0x1f0e, /* ANTTIME[15:8] 10010000 */
+       0x1f0f, /* ANTTIME[7:0] 10010000 */
+       0x1f11, /* SYNCTIME[23:16] 10011000 */
+       0x1f12, /* SYNCTIME[15:8] 10010110 */
+       0x1f13, /* SYNCTIME[7:0] 10000000 */
+       0x1f14, /* SNRTIME[31:24] 00000001 */
+       0x1f15, /* SNRTIME[23:16] 01111101 */
+       0x1f16, /* SNRTIME[15:8] 01111000 */
+       0x1f17, /* SNRTIME[7:0] 01000000 */
+       0x1f19, /* FECTIME[23:16] 00000000 */
+       0x1f1a, /* FECTIME[15:8] 01110010 */
+       0x1f1b, /* FECTIME[7:0] 01110000 */
+       0x1f1d, /* FECTHD[7:0] 00000011 */
+       0x1f1f, /* SNRTHD[23:16] 00001000 */
+       0x1f20, /* SNRTHD[15:8] 01111111 */
+       0x1f21, /* SNRTHD[7:0] 10000101 */
+       0x1f80, /* IRQFLG x x SFSDRFLG MODEBFLG SAVEFLG SCANFLG TRACKFLG */
+       0x1f81, /* x SYNCCON SNRCON FECCON x STDBUSY SYNCRST AGCFZCO */
+       0x1f82, /* x x x SCANOPCD[4:0] */
+       0x1f83, /* x x x x MAINOPCD[3:0] */
+       0x1f84, /* x x RXDATA[13:8] */
+       0x1f85, /* RXDATA[7:0] */
+       0x1f86, /* x x SDTDATA[13:8] */
+       0x1f87, /* SDTDATA[7:0] */
+       0x1f89, /* ANTSNR[23:16] */
+       0x1f8a, /* ANTSNR[15:8] */
+       0x1f8b, /* ANTSNR[7:0] */
+       0x1f8c, /* x x x x ANTFEC[13:8] */
+       0x1f8d, /* ANTFEC[7:0] */
+       0x1f8e, /* MAXCNT[7:0] */
+       0x1f8f, /* SCANCNT[7:0] */
+       0x1f91, /* MAXPW[23:16] */
+       0x1f92, /* MAXPW[15:8] */
+       0x1f93, /* MAXPW[7:0] */
+       0x1f95, /* CURPWMSE[23:16] */
+       0x1f96, /* CURPWMSE[15:8] */
+       0x1f97, /* CURPWMSE[7:0] */
+#endif /* SMART_ANT */
+       0x211f, /* 1'b1 1'b1 1'b1 CIRQEN x x 1'b0 1'b0 1111xx00 */
+       0x212a, /* EQAUTOST */
+       0x2122, /* CHFAST[7:0] 01100000 */
+       0x212b, /* FFFSTEP_V[3:0] x FBFSTEP_V[2:0] 0001x001 */
+       0x212c, /* PHDEROTBWSEL[3:0] 1'b1 1'b1 1'b1 1'b0 10001110 */
+       0x212d, /* 1'b1 1'b1 1'b1 1'b1 x x TPIFLOCKS */
+       0x2135, /* DYNTRACKFDEQ[3:0] x 1'b0 1'b0 1'b0 1010x000 */
+       0x2141, /* TRMODE[1:0] 1'b1 1'b1 1'b0 1'b1 1'b1 1'b1 01110111 */
+       0x2162, /* AICCCTRLE */
+       0x2173, /* PHNCNFCNT[7:0] 00000100 */
+       0x2179, /* 1'b0 1'b0 1'b0 1'b1 x BADSINGLEDYNTRACKFBF[2:0] 0001x001 */
+       0x217a, /* 1'b0 1'b0 1'b0 1'b1 x BADSLOWSINGLEDYNTRACKFBF[2:0] 0001x001 */
+       0x217e, /* CNFCNTTPIF[7:0] 00001000 */
+       0x217f, /* TPERRCNTTPIF[7:0] 00000001 */
+       0x2180, /* x x x x x x FBDLYCIR[9:8] */
+       0x2181, /* FBDLYCIR[7:0] */
+       0x2185, /* MAXPWRMAIN[7:0] */
+       0x2191, /* NCOMBDET x x x x x x x */
+       0x2199, /* x MAINSTRON */
+       0x219a, /* FFFEQSTEPOUT_V[3:0] FBFSTEPOUT_V[2:0] */
+       0x21a1, /* x x SNRREF[5:0] */
+       0x2845, /* 1'b0 1'b1 x x FFFSTEP_CQS[1:0] FFFCENTERTAP[1:0] 01xx1110 */
+       0x2846, /* 1'b0 x 1'b0 1'b1 FBFSTEP_CQS[1:0] 1'b1 1'b0 0x011110 */
+       0x2847, /* ENNOSIGDE */
+       0x2849, /* 1'b1 1'b1 NOUSENOSI */
+       0x284a, /* EQINITWAITTIME[7:0] 01100100 */
+       0x3000, /* 1'b1 1'b1 1'b1 x x x 1'b0 RPTRSTM */
+       0x3001, /* RPTRSTWAITTIME[7:0] (100msec) 00110010 */
+       0x3031, /* FRAMELOC */
+       0x3032, /* 1'b1 1'b0 1'b0 1'b0 x x FRAMELOCKMODE_CQS[1:0] 1000xx11 */
+       0x30a9, /* VDLOCK_Q FRAMELOCK */
+       0x30aa, /* MPEGLOCK */
+};
+
+#define numDumpRegs (sizeof(regtab)/sizeof(regtab[0]))
+static u8 regval1[numDumpRegs] = {0, };
+static u8 regval2[numDumpRegs] = {0, };
+
+static void lgdt3306a_DumpAllRegs(struct lgdt3306a_state *state)
+{
+               memset(regval2, 0xff, sizeof(regval2));
+               lgdt3306a_DumpRegs(state);
+}
+
+static void lgdt3306a_DumpRegs(struct lgdt3306a_state *state)
+{
+       int i;
+       int sav_debug = debug;
+
+       if ((debug & DBG_DUMP) == 0)
+               return;
+       debug &= ~DBG_REG; /* suppress DBG_REG during reg dump */
+
+       lg_debug("\n");
+
+       for (i = 0; i < numDumpRegs; i++) {
+               lgdt3306a_read_reg(state, regtab[i], &regval1[i]);
+               if (regval1[i] != regval2[i]) {
+                       lg_debug(" %04X = %02X\n", regtab[i], regval1[i]);
+                                regval2[i] = regval1[i];
+               }
+       }
+       debug = sav_debug;
+}
+#endif /* DBG_DUMP */
+
+
+
+static struct dvb_frontend_ops lgdt3306a_ops = {
+       .delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
+       .info = {
+               .name = "LG Electronics LGDT3306A VSB/QAM Frontend",
+               .frequency_min      = 54000000,
+               .frequency_max      = 858000000,
+               .frequency_stepsize = 62500,
+               .caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
+       },
+       .i2c_gate_ctrl        = lgdt3306a_i2c_gate_ctrl,
+       .init                 = lgdt3306a_init,
+       .sleep                = lgdt3306a_fe_sleep,
+       /* if this is set, it overrides the default swzigzag */
+       .tune                 = lgdt3306a_tune,
+       .set_frontend         = lgdt3306a_set_parameters,
+       .get_frontend         = lgdt3306a_get_frontend,
+       .get_frontend_algo    = lgdt3306a_get_frontend_algo,
+       .get_tune_settings    = lgdt3306a_get_tune_settings,
+       .read_status          = lgdt3306a_read_status,
+       .read_ber             = lgdt3306a_read_ber,
+       .read_signal_strength = lgdt3306a_read_signal_strength,
+       .read_snr             = lgdt3306a_read_snr,
+       .read_ucblocks        = lgdt3306a_read_ucblocks,
+       .release              = lgdt3306a_release,
+       .ts_bus_ctrl          = lgdt3306a_ts_bus_ctrl,
+       .search               = lgdt3306a_search,
+};
+
+MODULE_DESCRIPTION("LG Electronics LGDT3306A ATSC/QAM-B Demodulator Driver");
+MODULE_AUTHOR("Fred Richter <frichter@hauppauge.com>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.2");
diff --git a/drivers/media/dvb-frontends/lgdt3306a.h b/drivers/media/dvb-frontends/lgdt3306a.h
new file mode 100644 (file)
index 0000000..9dbb2dc
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ *    Support for LGDT3306A - 8VSB/QAM-B
+ *
+ *    Copyright (C) 2013,2014 Fred Richter <frichter@hauppauge.com>
+ *      based on lgdt3305.[ch] by Michael Krufky
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ */
+
+#ifndef _LGDT3306A_H_
+#define _LGDT3306A_H_
+
+#include <linux/i2c.h>
+#include "dvb_frontend.h"
+
+
+enum lgdt3306a_mpeg_mode {
+       LGDT3306A_MPEG_PARALLEL = 0,
+       LGDT3306A_MPEG_SERIAL = 1,
+};
+
+enum lgdt3306a_tp_clock_edge {
+       LGDT3306A_TPCLK_RISING_EDGE = 0,
+       LGDT3306A_TPCLK_FALLING_EDGE = 1,
+};
+
+enum lgdt3306a_tp_valid_polarity {
+       LGDT3306A_TP_VALID_LOW = 0,
+       LGDT3306A_TP_VALID_HIGH = 1,
+};
+
+struct lgdt3306a_config {
+       u8 i2c_addr;
+
+       /* user defined IF frequency in KHz */
+       u16 qam_if_khz;
+       u16 vsb_if_khz;
+
+       /* disable i2c repeater - 0:repeater enabled 1:repeater disabled */
+       unsigned int deny_i2c_rptr:1;
+
+       /* spectral inversion - 0:disabled 1:enabled */
+       unsigned int spectral_inversion:1;
+
+       enum lgdt3306a_mpeg_mode mpeg_mode;
+       enum lgdt3306a_tp_clock_edge tpclk_edge;
+       enum lgdt3306a_tp_valid_polarity tpvalid_polarity;
+
+       /* demod clock freq in MHz; 24 or 25 supported */
+       int  xtalMHz;
+};
+
+#if IS_REACHABLE(CONFIG_DVB_LGDT3306A)
+struct dvb_frontend *lgdt3306a_attach(const struct lgdt3306a_config *config,
+                                     struct i2c_adapter *i2c_adap);
+#else
+static inline
+struct dvb_frontend *lgdt3306a_attach(const struct lgdt3306a_config *config,
+                                     struct i2c_adapter *i2c_adap)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+#endif /* CONFIG_DVB_LGDT3306A */
+
+#endif /* _LGDT3306A_H_ */
index 8bb332219fc496af77ec129e8fa4ff183ce8f5f4..c73eeb45e3305cf3ea043df4b119d8183549cc03 100644 (file)
@@ -52,7 +52,7 @@ struct lgdt330x_config
        int clock_polarity_flip;
 };
 
-#if IS_ENABLED(CONFIG_DVB_LGDT330X)
+#if IS_REACHABLE(CONFIG_DVB_LGDT330X)
 extern struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
                                            struct i2c_adapter* i2c);
 #else
index c2da5961472782982b095b5fb632af3b2b82cf62..a5b3faf121f0f0d7e3a46b29c80f5a7def2caa96 100644 (file)
@@ -31,7 +31,7 @@ struct lgs8gl5_config {
        u8 demod_address;
 };
 
-#if IS_ENABLED(CONFIG_DVB_LGS8GL5)
+#if IS_REACHABLE(CONFIG_DVB_LGS8GL5)
 extern struct dvb_frontend *lgs8gl5_attach(
        const struct lgs8gl5_config *config, struct i2c_adapter *i2c);
 #else
index dadb78bf61a9782bc6f322dd20b7985402e07826..368c9928ef7fd6cc23d54160683b7f795d52b939 100644 (file)
@@ -80,7 +80,7 @@ struct lgs8gxx_config {
        u8 tuner_address;
 };
 
-#if IS_ENABLED(CONFIG_DVB_LGS8GXX)
+#if IS_REACHABLE(CONFIG_DVB_LGS8GXX)
 extern struct dvb_frontend *lgs8gxx_attach(const struct lgs8gxx_config *config,
                                           struct i2c_adapter *i2c);
 #else
index b327a4f31d16638e1a3d73b65fd9a92ecfeb25ee..a088b8ec1e535e0578397200cd504a92d1149c4a 100644 (file)
@@ -37,7 +37,7 @@
 
 #include <linux/dvb/frontend.h>
 
-#if IS_ENABLED(CONFIG_DVB_LNBP21)
+#if IS_REACHABLE(CONFIG_DVB_LNBP21)
 /* override_set and override_clear control which
    system register bits (above) to always set & clear */
 extern struct dvb_frontend *lnbh24_attach(struct dvb_frontend *fe,
index dbcbcc2f20a30ec9421c3a4707e68c28befd5987..a9b530de62a60582a6574ab3325baac003d229ed 100644 (file)
@@ -57,7 +57,7 @@
 
 #include <linux/dvb/frontend.h>
 
-#if IS_ENABLED(CONFIG_DVB_LNBP21)
+#if IS_REACHABLE(CONFIG_DVB_LNBP21)
 /* override_set and override_clear control which
  system register bits (above) to always set & clear */
 extern struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe,
index 63861b311dd887826672fda54cda66cd5e9cea29..628148385182af8a8ab2eebeb3d6f726b0e6166a 100644 (file)
@@ -39,7 +39,7 @@
 
 #include <linux/dvb/frontend.h>
 
-#if IS_ENABLED(CONFIG_DVB_LNBP22)
+#if IS_REACHABLE(CONFIG_DVB_LNBP22)
 /*
  * override_set and override_clear control which system register bits (above)
  * to always set & clear
index 0a50ea90736bfa62c22d07fc386a6e0c9270b82e..de7430178e9e142c2c75be0e9606087f836ab0f9 100644 (file)
@@ -41,7 +41,7 @@ enum {
        CALL_IS_READ,
 };
 
-#if IS_ENABLED(CONFIG_DVB_M88RS2000)
+#if IS_REACHABLE(CONFIG_DVB_M88RS2000)
 extern struct dvb_frontend *m88rs2000_attach(
        const struct m88rs2000_config *config, struct i2c_adapter *i2c);
 #else
index 277ce061acf9e2b57b1945bf24bdd9c11777d465..e486dc0d8e6077f8eb2256cb9cbc442a6203b382 100644 (file)
@@ -33,7 +33,7 @@ struct mb86a16_config {
 
 
 
-#if IS_ENABLED(CONFIG_DVB_MB86A16)
+#if IS_REACHABLE(CONFIG_DVB_MB86A16)
 
 extern struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config,
                                           struct i2c_adapter *i2c_adap);
index cbeb941fba7c16c11d7b4c46f82f7be23492aa65..f749c8ac5f398c39b2ac09feff026294b8fdd7b5 100644 (file)
@@ -34,7 +34,7 @@ struct mb86a20s_config {
        bool    is_serial;
 };
 
-#if IS_ENABLED(CONFIG_DVB_MB86A20S)
+#if IS_REACHABLE(CONFIG_DVB_MB86A20S)
 extern struct dvb_frontend *mb86a20s_attach(const struct mb86a20s_config *config,
                                           struct i2c_adapter *i2c);
 extern struct i2c_adapter *mb86a20s_get_tuner_i2c_adapter(struct dvb_frontend *);
index e4e0b80d3091f93cd660e1822201817d11b64d77..095294d292f36bf97f5a2709866020e4a85d2621 100644 (file)
 
 #include <linux/dvb/frontend.h>
 
+enum ts_clock {
+       VARIABLE_TS_CLOCK,
+       FIXED_TS_CLOCK,
+};
+
+enum ts_mode {
+       SERIAL_TS_MODE,
+       PARALLEL_TS_MODE,
+};
+
 struct mn88472_config {
        /*
         * Max num of bytes given I2C adapter could write at once.
@@ -39,6 +49,8 @@ struct mn88472_config {
         * Hz
         */
        u32 xtal;
+       int ts_mode;
+       int ts_clock;
 };
 
 #endif
index a373ec93cbe00a317ec16668d9753a3e4a3c27ae..c717ebed0e03a44b15f86bcd3987a9bc7a72ae99 100644 (file)
@@ -33,6 +33,12 @@ struct mn88473_config {
         * DVB frontend.
         */
        struct dvb_frontend **fe;
+
+       /*
+        * Xtal frequency.
+        * Hz
+        */
+       u32 xtal;
 };
 
 #endif
index 5706621ad79d9784cc905fd9c2758ff573ffb77d..386939a90555e438d015bbdd626e038f2e7047f5 100644 (file)
@@ -36,7 +36,7 @@ struct mt312_config {
        unsigned int voltage_inverted:1;
 };
 
-#if IS_ENABLED(CONFIG_DVB_MT312)
+#if IS_REACHABLE(CONFIG_DVB_MT312)
 struct dvb_frontend *mt312_attach(const struct mt312_config *config,
                                        struct i2c_adapter *i2c);
 #else
index 451d904e1500264339f7ab8d10172a39623fa28e..5873263bd1af16fdaf5c6b9fd9638cc870ba9b82 100644 (file)
@@ -51,7 +51,7 @@ struct mt352_config
        int (*demod_init)(struct dvb_frontend* fe);
 };
 
-#if IS_ENABLED(CONFIG_DVB_MT352)
+#if IS_REACHABLE(CONFIG_DVB_MT352)
 extern struct dvb_frontend* mt352_attach(const struct mt352_config* config,
                                         struct i2c_adapter* i2c);
 #else
index e38d01fb6c2b076441a18454b18446ddccfa11ad..825b928ef54235958e58020f9a4afc0cc4c6f613 100644 (file)
@@ -42,7 +42,7 @@ struct nxt200x_config
        int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
 };
 
-#if IS_ENABLED(CONFIG_DVB_NXT200X)
+#if IS_REACHABLE(CONFIG_DVB_NXT200X)
 extern struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
                                           struct i2c_adapter* i2c);
 #else
index b5867c2ae681554759ff4976fd31e316a6e56cf2..a94cefcc6dfd830c3017c7a3d9b026edd9312ba3 100644 (file)
@@ -33,7 +33,7 @@ struct nxt6000_config
        u8 clock_inversion:1;
 };
 
-#if IS_ENABLED(CONFIG_DVB_NXT6000)
+#if IS_REACHABLE(CONFIG_DVB_NXT6000)
 extern struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
                                           struct i2c_adapter* i2c);
 #else
index cdb5be3c65d630ab9eee3d93b4969c37998ffea8..9acf8dc87413283be5a55a00f6dc1446d72bf73f 100644 (file)
@@ -34,7 +34,7 @@ struct or51132_config
        int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
 };
 
-#if IS_ENABLED(CONFIG_DVB_OR51132)
+#if IS_REACHABLE(CONFIG_DVB_OR51132)
 extern struct dvb_frontend* or51132_attach(const struct or51132_config* config,
                                           struct i2c_adapter* i2c);
 #else
index 9a8ae936b62dee36d0074911b565f2c396041fba..cc6adab63249bbb9041a32ac2fd21d1fe21817a7 100644 (file)
@@ -37,7 +37,7 @@ struct or51211_config
        void (*sleep)(struct dvb_frontend * fe);
 };
 
-#if IS_ENABLED(CONFIG_DVB_OR51211)
+#if IS_REACHABLE(CONFIG_DVB_OR51211)
 extern struct dvb_frontend* or51211_attach(const struct or51211_config* config,
                                           struct i2c_adapter* i2c);
 #else
index 67faa8d6950efb1e4f8b24c0aad0e99027473b43..b400f7b3c2e7c189a3f0b04d66c5000b812683db 100644 (file)
@@ -685,7 +685,7 @@ static int rtl2832_read_status(struct dvb_frontend *fe, fe_status_t *status)
        struct rtl2832_dev *dev = fe->demodulator_priv;
        struct i2c_client *client = dev->client;
        int ret;
-       u32 tmp;
+       u32 uninitialized_var(tmp);
 
        dev_dbg(&client->dev, "\n");
 
index 9e143f5c810798166abec1156a1b1297931b7e7e..f58b9ca5557ad7c7cf36a4e26ca33b1f8af81cfe 100644 (file)
@@ -67,7 +67,7 @@ struct s5h1409_config {
        u8 hvr1600_opt;
 };
 
-#if IS_ENABLED(CONFIG_DVB_S5H1409)
+#if IS_REACHABLE(CONFIG_DVB_S5H1409)
 extern struct dvb_frontend *s5h1409_attach(const struct s5h1409_config *config,
                                           struct i2c_adapter *i2c);
 #else
index 1d7deb6156743c39028822ed14a6f8bc84870c53..f3a87f7ec3601579386835c360322059670eac6f 100644 (file)
@@ -69,7 +69,7 @@ struct s5h1411_config {
        u8 status_mode;
 };
 
-#if IS_ENABLED(CONFIG_DVB_S5H1411)
+#if IS_REACHABLE(CONFIG_DVB_S5H1411)
 extern struct dvb_frontend *s5h1411_attach(const struct s5h1411_config *config,
                                           struct i2c_adapter *i2c);
 #else
index 210049b5cf307ccc8a47f72e5f948ee52277cdfe..142d93e7d02bf27f257bfcea7b5497caba6050b9 100644 (file)
@@ -40,7 +40,7 @@ struct s5h1420_config
        u8 serial_mpeg:1;
 };
 
-#if IS_ENABLED(CONFIG_DVB_S5H1420)
+#if IS_REACHABLE(CONFIG_DVB_S5H1420)
 extern struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config,
             struct i2c_adapter *i2c);
 extern struct i2c_adapter *s5h1420_get_tuner_i2c_adapter(struct dvb_frontend *fe);
index 70917dd2533a52659fdf7fd94969731d11d1f2d6..f490c5ee58015d0015a31ecf055f2053c079b41d 100644 (file)
@@ -75,7 +75,7 @@ struct s5h1432_config {
        u8 status_mode;
 };
 
-#if IS_ENABLED(CONFIG_DVB_S5H1432)
+#if IS_REACHABLE(CONFIG_DVB_S5H1432)
 extern struct dvb_frontend *s5h1432_attach(const struct s5h1432_config *config,
                                           struct i2c_adapter *i2c);
 #else
index 9b20c9e0eb88d7f18f6df0fda01f673ded6108f4..7d3999a4e9743b311cbd3377a310005dfc8170bb 100644 (file)
@@ -25,7 +25,7 @@ struct s921_config {
        u8 demod_address;
 };
 
-#if IS_ENABLED(CONFIG_DVB_S921)
+#if IS_REACHABLE(CONFIG_DVB_S921)
 extern struct dvb_frontend *s921_attach(const struct s921_config *config,
                                           struct i2c_adapter *i2c);
 extern struct i2c_adapter *s921_get_tuner_i2c_adapter(struct dvb_frontend *);
index 98ddb49ad52b1a27a268ef6fabab3d3de97496e7..4cc5d10ed0d43e2740f54846f529569a675829fb 100644 (file)
@@ -505,7 +505,7 @@ static int si2165_upload_firmware(struct si2165_state *state)
        /* reset crc */
        ret = si2165_writereg8(state, 0x0379, 0x01);
        if (ret)
-               return ret;
+               goto error;
 
        ret = si2165_upload_firmware_block(state, data, len,
                                           &offset, block_count);
index efaa08123b921218bf1fc2c864baa867f0e320af..8a15d6a9c552597914f9615d26259bcd00f8f514 100644 (file)
@@ -45,7 +45,7 @@ struct si2165_config {
        bool inversion;
 };
 
-#if IS_ENABLED(CONFIG_DVB_SI2165)
+#if IS_REACHABLE(CONFIG_DVB_SI2165)
 struct dvb_frontend *si2165_attach(
        const struct si2165_config *config,
        struct i2c_adapter *i2c);
index 1509fed44a3aa8e31e76480c93942df7b98280db..ef5f351ca68ea17c74b12a9616782e18ea172543 100644 (file)
@@ -13,7 +13,7 @@ struct si21xx_config {
        int min_delay_ms;
 };
 
-#if IS_ENABLED(CONFIG_DVB_SI21XX)
+#if IS_REACHABLE(CONFIG_DVB_SI21XX)
 extern struct dvb_frontend *si21xx_attach(const struct si21xx_config *config,
                                                struct i2c_adapter *i2c);
 #else
index cc1ef966f99f2b6cd937f0b921144bcdcd2ade0a..8fd42767e263da4998d2e3e5676bd258a1d5246c 100644 (file)
@@ -413,11 +413,8 @@ static int sp2_remove(struct i2c_client *client)
        struct sp2 *s = i2c_get_clientdata(client);
 
        dev_dbg(&client->dev, "\n");
-
        sp2_exit(client);
-       if (s != NULL)
-               kfree(s);
-
+       kfree(s);
        return 0;
 }
 
index 065ec67d4e30d72a6be42a81f63b1689f673dba5..f507b9fd707bbe630f5edf0fc8bf69262aa41728 100644 (file)
@@ -35,7 +35,7 @@ struct sp8870_config
        int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
 };
 
-#if IS_ENABLED(CONFIG_DVB_SP8870)
+#if IS_REACHABLE(CONFIG_DVB_SP8870)
 extern struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
                                          struct i2c_adapter* i2c);
 #else
index 2cdc4e8bc9cd6e2eae28be98c84038c673b8ba3a..412f011e6dfda83464c3fe7be9acf1a5df9ce203 100644 (file)
@@ -17,7 +17,7 @@ struct sp887x_config
        int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
 };
 
-#if IS_ENABLED(CONFIG_DVB_SP887X)
+#if IS_REACHABLE(CONFIG_DVB_SP887X)
 extern struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
                                          struct i2c_adapter* i2c);
 #else
index 139264d19263539bf68eef8c4a919eb3756b7b19..0a72131a57dbf3dfae36b285271b1cd6da9bae21 100644 (file)
@@ -141,7 +141,7 @@ struct stb0899_config {
        int (*tuner_set_rfsiggain)(struct dvb_frontend *fe, u32 rf_gain);
 };
 
-#if IS_ENABLED(CONFIG_DVB_STB0899)
+#if IS_REACHABLE(CONFIG_DVB_STB0899)
 
 extern struct dvb_frontend *stb0899_attach(struct stb0899_config *config,
                                           struct i2c_adapter *i2c);
index a768189bfaad7d8950c350a1cebd1de826950caa..da581b652cb93866b82dd881709d3e36f7388c28 100644 (file)
@@ -35,7 +35,7 @@
  * @param i2c i2c adapter to use.
  * @return FE pointer on success, NULL on failure.
  */
-#if IS_ENABLED(CONFIG_DVB_STB6000)
+#if IS_REACHABLE(CONFIG_DVB_STB6000)
 extern struct dvb_frontend *stb6000_attach(struct dvb_frontend *fe, int addr,
                                           struct i2c_adapter *i2c);
 #else
index 3a1e40f3b8be2d9ee519f59e33996955dfcf3ac3..218c8188865d160577d820c73b21f87fa27c4876 100644 (file)
@@ -94,7 +94,7 @@ struct stb6100_state {
        u32 reference;
 };
 
-#if IS_ENABLED(CONFIG_DVB_STB6100)
+#if IS_REACHABLE(CONFIG_DVB_STB6100)
 
 extern struct dvb_frontend *stb6100_attach(struct dvb_frontend *fe,
                                           const struct stb6100_config *config,
index a0bd9310715417b49f28386c525c2d878ad42962..b58603c00c80a24b6853588d951b38c355ee5222 100644 (file)
@@ -43,7 +43,7 @@ struct stv0288_config {
        int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
 };
 
-#if IS_ENABLED(CONFIG_DVB_STV0288)
+#if IS_REACHABLE(CONFIG_DVB_STV0288)
 extern struct dvb_frontend *stv0288_attach(const struct stv0288_config *config,
                                           struct i2c_adapter *i2c);
 #else
index c8ff3639ce000275ae57983a328291b79212f620..b30632a6733307872913361eb41ca542907689dc 100644 (file)
@@ -42,7 +42,7 @@ struct stv0297_config
        u8 stop_during_read:1;
 };
 
-#if IS_ENABLED(CONFIG_DVB_STV0297)
+#if IS_REACHABLE(CONFIG_DVB_STV0297)
 extern struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
                                           struct i2c_adapter* i2c);
 #else
index 06f70fc8327b39115c7286934dc445309a776189..0aca30a8ec257c3342b9c954ef9e91278abe7a1a 100644 (file)
@@ -95,7 +95,7 @@ struct stv0299_config
        int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
 };
 
-#if IS_ENABLED(CONFIG_DVB_STV0299)
+#if IS_REACHABLE(CONFIG_DVB_STV0299)
 extern struct dvb_frontend *stv0299_attach(const struct stv0299_config *config,
                                           struct i2c_adapter *i2c);
 #else
index ea80b341f094cf8a3c4417f2d99615c9e5f60bfc..92b3e85fb818c0e22523265fe92dc08486e0eded 100644 (file)
@@ -39,7 +39,7 @@ struct stv0367_config {
        int clk_pol;
 };
 
-#if IS_ENABLED(CONFIG_DVB_STV0367)
+#if IS_REACHABLE(CONFIG_DVB_STV0367)
 extern struct
 dvb_frontend *stv0367ter_attach(const struct stv0367_config *config,
                                        struct i2c_adapter *i2c);
index e2a6dc69ecb46a59071b60a2355e6762e0f4408e..c90bf00ea9ce14c0d32c55a29cb23061bb7df6c6 100644 (file)
@@ -58,7 +58,7 @@ struct stv0900_config {
        void (*set_lock_led)(struct dvb_frontend *fe, int offon);
 };
 
-#if IS_ENABLED(CONFIG_DVB_STV0900)
+#if IS_REACHABLE(CONFIG_DVB_STV0900)
 extern struct dvb_frontend *stv0900_attach(const struct stv0900_config *config,
                                        struct i2c_adapter *i2c, int demod);
 #else
index 742eeda9900018ee3dde4b9f5b7aab831a6af158..012e55e5032e62ff5b394c4513636761b1d69d4f 100644 (file)
@@ -107,7 +107,7 @@ struct stv090x_config {
                        u8 xor_value);
 };
 
-#if IS_ENABLED(CONFIG_DVB_STV090x)
+#if IS_REACHABLE(CONFIG_DVB_STV090x)
 
 struct dvb_frontend *stv090x_attach(struct stv090x_config *config,
                                    struct i2c_adapter *i2c,
index 8fa07e6a6745712e65328aab285f8b8dafd88919..f3c8a5c6b77d1af7f664ac51b4c96522783a1690 100644 (file)
@@ -46,7 +46,7 @@ struct stv6110_config {
        u8 clk_div;     /* divisor value for the output clock */
 };
 
-#if IS_ENABLED(CONFIG_DVB_STV6110)
+#if IS_REACHABLE(CONFIG_DVB_STV6110)
 extern struct dvb_frontend *stv6110_attach(struct dvb_frontend *fe,
                                        const struct stv6110_config *config,
                                        struct i2c_adapter *i2c);
index bc4766db29c52403b4f21b8be422902faa3fc8de..9f7eb251aec32cb0a6d7bf821000a95690674332 100644 (file)
@@ -53,7 +53,7 @@ struct stv6110x_devctl {
 };
 
 
-#if IS_ENABLED(CONFIG_DVB_STV6110x)
+#if IS_REACHABLE(CONFIG_DVB_STV6110x)
 
 extern struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
                                               const struct stv6110x_config *config,
index e404b6e4480249e43ce6355abc222dc49191f69c..0d334613de1b94e9a11e1c007219fe2cfc657970 100644 (file)
@@ -57,7 +57,7 @@ struct tda10023_config {
        u16 deltaf;
 };
 
-#if IS_ENABLED(CONFIG_DVB_TDA10021)
+#if IS_REACHABLE(CONFIG_DVB_TDA10021)
 extern struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config,
                                            struct i2c_adapter* i2c, u8 pwm);
 #else
@@ -69,7 +69,7 @@ static inline struct dvb_frontend* tda10021_attach(const struct tda1002x_config*
 }
 #endif // CONFIG_DVB_TDA10021
 
-#if IS_ENABLED(CONFIG_DVB_TDA10023)
+#if IS_REACHABLE(CONFIG_DVB_TDA10023)
 extern struct dvb_frontend *tda10023_attach(
        const struct tda10023_config *config,
        struct i2c_adapter *i2c, u8 pwm);
index 5e7bf4e47cb367ee6847b402bd6fd32da7bef0d2..bc77a7311de1610394c8c4c856873c6f3b7c66d9 100644 (file)
@@ -73,7 +73,7 @@ struct tda10048_config {
        u8 pll_n;
 };
 
-#if IS_ENABLED(CONFIG_DVB_TDA10048)
+#if IS_REACHABLE(CONFIG_DVB_TDA10048)
 extern struct dvb_frontend *tda10048_attach(
        const struct tda10048_config *config,
        struct i2c_adapter *i2c);
index dd283fbb61c061c4e1ae83f10b88ec9520ffadfd..efd7659dace919b594c572965f680665af4e3588 100644 (file)
@@ -117,7 +117,7 @@ struct tda1004x_state {
        enum tda1004x_demod demod_type;
 };
 
-#if IS_ENABLED(CONFIG_DVB_TDA1004X)
+#if IS_REACHABLE(CONFIG_DVB_TDA1004X)
 extern struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
                                            struct i2c_adapter* i2c);
 
index 331b5a819383dbad3464ecb8bfaac9ac5a2dc89f..da89f42498466cca798f4236b741e9e6fb76386f 100644 (file)
@@ -72,7 +72,7 @@ struct tda10071_config {
 };
 
 
-#if IS_ENABLED(CONFIG_DVB_TDA10071)
+#if IS_REACHABLE(CONFIG_DVB_TDA10071)
 extern struct dvb_frontend *tda10071_attach(
        const struct tda10071_config *config, struct i2c_adapter *i2c);
 #else
index 458fe91c1b88b2843cf469bc8d314e14b0df0b7e..690e469995b62f8b860cc6b1f963b98337fe5211 100644 (file)
@@ -46,7 +46,7 @@ struct tda10086_config
        enum tda10086_xtal xtal_freq;
 };
 
-#if IS_ENABLED(CONFIG_DVB_TDA10086)
+#if IS_REACHABLE(CONFIG_DVB_TDA10086)
 extern struct dvb_frontend* tda10086_attach(const struct tda10086_config* config,
                                            struct i2c_adapter* i2c);
 #else
index dd84f7b69bece134f3b0c1ce4ff8e8deefd8c72c..7ebd8eaff4eb5d2610382e6f37ec53b8ff61bee8 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <linux/kconfig.h>
 
-#if IS_ENABLED(CONFIG_DVB_TDA18271C2DD)
+#if IS_REACHABLE(CONFIG_DVB_TDA18271C2DD)
 struct dvb_frontend *tda18271c2dd_attach(struct dvb_frontend *fe,
                                         struct i2c_adapter *i2c, u8 adr);
 #else
index 03a0da6d5cf2181298866f13fe2462c2f9cd44e8..baf520baa42e6398f0a7214aa112d19fdbb32ddd 100644 (file)
@@ -31,7 +31,7 @@ struct tda665x_config {
        u32     ref_divider;
 };
 
-#if IS_ENABLED(CONFIG_DVB_TDA665x)
+#if IS_REACHABLE(CONFIG_DVB_TDA665x)
 
 extern struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe,
                                           const struct tda665x_config *config,
index de6b1860dfdd226e3935d43f95beb302633125ac..46be06fa7e0d9126f0936c31f4c6aeae5573816f 100644 (file)
@@ -35,7 +35,7 @@ struct tda8083_config
        u8 demod_address;
 };
 
-#if IS_ENABLED(CONFIG_DVB_TDA8083)
+#if IS_REACHABLE(CONFIG_DVB_TDA8083)
 extern struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
                                           struct i2c_adapter* i2c);
 #else
index 55cf4ffcbfdfd64f55d471d70487fbda234e4609..9fa5b3076d5bd6e738cbd8c5c13d1e241054f43c 100644 (file)
@@ -34,7 +34,7 @@ struct tda8261_config {
        enum tda8261_step       step_size;
 };
 
-#if IS_ENABLED(CONFIG_DVB_TDA8261)
+#if IS_REACHABLE(CONFIG_DVB_TDA8261)
 
 extern struct dvb_frontend *tda8261_attach(struct dvb_frontend *fe,
                                           const struct tda8261_config *config,
index 5f0f20e7e4f81e91cb374859ae8cc00df085bcdc..81abe1aebe9fba8d6746a2a34bf8430b1a4332ad 100644 (file)
@@ -35,7 +35,7 @@
  * @param has_loopthrough Set to 1 if the card has a loopthrough RF connector.
  * @return FE pointer on success, NULL on failure.
  */
-#if IS_ENABLED(CONFIG_DVB_TDA826X)
+#if IS_REACHABLE(CONFIG_DVB_TDA826X)
 extern struct dvb_frontend* tda826x_attach(struct dvb_frontend *fe, int addr,
                                           struct i2c_adapter *i2c,
                                           int has_loopthrough);
index 9aba044dabedbb1fe0610560854e3b7ecd28ac44..90164a38cd366bd5627140f2dc55d370cd62d7f1 100644 (file)
 #define FREQ_OFFSET_LOW_SYM_RATE 3000
 
 struct ts2020_priv {
+       struct dvb_frontend *fe;
        /* i2c details */
        int i2c_address;
        struct i2c_adapter *i2c;
-       u8 clk_out_div;
+       u8 clk_out:2;
+       u8 clk_out_div:5;
        u32 frequency;
        u32 frequency_div;
+#define TS2020_M88TS2020 0
+#define TS2020_M88TS2022 1
+       u8 tuner;
+       u8 loop_through:1;
+};
+
+struct ts2020_reg_val {
+       u8 reg;
+       u8 val;
 };
 
 static int ts2020_release(struct dvb_frontend *fe)
@@ -112,40 +123,77 @@ static int ts2020_readreg(struct dvb_frontend *fe, u8 reg)
 static int ts2020_sleep(struct dvb_frontend *fe)
 {
        struct ts2020_priv *priv = fe->tuner_priv;
-       int ret;
-       u8 buf[] = { 10, 0 };
-       struct i2c_msg msg = {
-               .addr = priv->i2c_address,
-               .flags = 0,
-               .buf = buf,
-               .len = 2
-       };
+       u8 u8tmp;
 
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-
-       ret = i2c_transfer(priv->i2c, &msg, 1);
-       if (ret != 1)
-               printk(KERN_ERR "%s: i2c error\n", __func__);
-
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 0);
+       if (priv->tuner == TS2020_M88TS2020)
+               u8tmp = 0x0a; /* XXX: probably wrong */
+       else
+               u8tmp = 0x00;
 
-       return (ret == 1) ? 0 : ret;
+       return ts2020_writereg(fe, u8tmp, 0x00);
 }
 
 static int ts2020_init(struct dvb_frontend *fe)
 {
        struct ts2020_priv *priv = fe->tuner_priv;
+       int i;
+       u8 u8tmp;
+
+       if (priv->tuner == TS2020_M88TS2020) {
+               ts2020_writereg(fe, 0x42, 0x73);
+               ts2020_writereg(fe, 0x05, priv->clk_out_div);
+               ts2020_writereg(fe, 0x20, 0x27);
+               ts2020_writereg(fe, 0x07, 0x02);
+               ts2020_writereg(fe, 0x11, 0xff);
+               ts2020_writereg(fe, 0x60, 0xf9);
+               ts2020_writereg(fe, 0x08, 0x01);
+               ts2020_writereg(fe, 0x00, 0x41);
+       } else {
+               static const struct ts2020_reg_val reg_vals[] = {
+                       {0x7d, 0x9d},
+                       {0x7c, 0x9a},
+                       {0x7a, 0x76},
+                       {0x3b, 0x01},
+                       {0x63, 0x88},
+                       {0x61, 0x85},
+                       {0x22, 0x30},
+                       {0x30, 0x40},
+                       {0x20, 0x23},
+                       {0x24, 0x02},
+                       {0x12, 0xa0},
+               };
+
+               ts2020_writereg(fe, 0x00, 0x01);
+               ts2020_writereg(fe, 0x00, 0x03);
+
+               switch (priv->clk_out) {
+               case TS2020_CLK_OUT_DISABLED:
+                       u8tmp = 0x60;
+                       break;
+               case TS2020_CLK_OUT_ENABLED:
+                       u8tmp = 0x70;
+                       ts2020_writereg(fe, 0x05, priv->clk_out_div);
+                       break;
+               case TS2020_CLK_OUT_ENABLED_XTALOUT:
+                       u8tmp = 0x6c;
+                       break;
+               default:
+                       u8tmp = 0x60;
+                       break;
+               }
 
-       ts2020_writereg(fe, 0x42, 0x73);
-       ts2020_writereg(fe, 0x05, priv->clk_out_div);
-       ts2020_writereg(fe, 0x20, 0x27);
-       ts2020_writereg(fe, 0x07, 0x02);
-       ts2020_writereg(fe, 0x11, 0xff);
-       ts2020_writereg(fe, 0x60, 0xf9);
-       ts2020_writereg(fe, 0x08, 0x01);
-       ts2020_writereg(fe, 0x00, 0x41);
+               ts2020_writereg(fe, 0x42, u8tmp);
+
+               if (priv->loop_through)
+                       u8tmp = 0xec;
+               else
+                       u8tmp = 0x6c;
+
+               ts2020_writereg(fe, 0x62, u8tmp);
+
+               for (i = 0; i < ARRAY_SIZE(reg_vals); i++)
+                       ts2020_writereg(fe, reg_vals[i].reg, reg_vals[i].val);
+       }
 
        return 0;
 }
@@ -203,7 +251,14 @@ static int ts2020_set_params(struct dvb_frontend *fe)
        ndiv = ndiv + ndiv % 2;
        ndiv = ndiv - 1024;
 
-       ret = ts2020_writereg(fe, 0x10, 0x80 | lo);
+       if (priv->tuner == TS2020_M88TS2020) {
+               lpf_coeff = 2766;
+               ret = ts2020_writereg(fe, 0x10, 0x80 | lo);
+       } else {
+               lpf_coeff = 3200;
+               ret = ts2020_writereg(fe, 0x10, 0x0b);
+               ret |= ts2020_writereg(fe, 0x11, 0x40);
+       }
 
        /* Set frequency divider */
        ret |= ts2020_writereg(fe, 0x01, (ndiv >> 8) & 0xf);
@@ -220,7 +275,8 @@ static int ts2020_set_params(struct dvb_frontend *fe)
        ret |= ts2020_tuner_gate_ctrl(fe, 0x08);
 
        /* Tuner RF */
-       ret |= ts2020_set_tuner_rf(fe);
+       if (priv->tuner == TS2020_M88TS2020)
+               ret |= ts2020_set_tuner_rf(fe);
 
        gdiv28 = (TS2020_XTAL_FREQ / 1000 * 1694 + 500) / 1000;
        ret |= ts2020_writereg(fe, 0x04, gdiv28 & 0xff);
@@ -228,6 +284,15 @@ static int ts2020_set_params(struct dvb_frontend *fe)
        if (ret < 0)
                return -ENODEV;
 
+       if (priv->tuner == TS2020_M88TS2022) {
+               ret = ts2020_writereg(fe, 0x25, 0x00);
+               ret |= ts2020_writereg(fe, 0x27, 0x70);
+               ret |= ts2020_writereg(fe, 0x41, 0x09);
+               ret |= ts2020_writereg(fe, 0x08, 0x0b);
+               if (ret < 0)
+                       return -ENODEV;
+       }
+
        value = ts2020_readreg(fe, 0x26);
 
        f3db = (symbol_rate * 135) / 200 + 2000;
@@ -243,8 +308,6 @@ static int ts2020_set_params(struct dvb_frontend *fe)
        if (mlpf_max > 63)
                mlpf_max = 63;
 
-       lpf_coeff = 2766;
-
        nlpf = (f3db * gdiv28 * 2 / lpf_coeff /
                (TS2020_XTAL_FREQ / 1000)  + 1) / 2;
        if (nlpf > 23)
@@ -285,6 +348,13 @@ static int ts2020_get_frequency(struct dvb_frontend *fe, u32 *frequency)
 {
        struct ts2020_priv *priv = fe->tuner_priv;
        *frequency = priv->frequency;
+
+       return 0;
+}
+
+static int ts2020_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+       *frequency = 0; /* Zero-IF */
        return 0;
 }
 
@@ -324,6 +394,7 @@ static struct dvb_tuner_ops ts2020_tuner_ops = {
        .sleep = ts2020_sleep,
        .set_params = ts2020_set_params,
        .get_frequency = ts2020_get_frequency,
+       .get_if_frequency = ts2020_get_if_frequency,
        .get_rf_strength = ts2020_read_signal_strength,
 };
 
@@ -340,8 +411,10 @@ struct dvb_frontend *ts2020_attach(struct dvb_frontend *fe,
 
        priv->i2c_address = config->tuner_address;
        priv->i2c = i2c;
+       priv->clk_out = config->clk_out;
        priv->clk_out_div = config->clk_out_div;
        priv->frequency_div = config->frequency_div;
+       priv->fe = fe;
        fe->tuner_priv = priv;
 
        if (!priv->frequency_div)
@@ -358,9 +431,13 @@ struct dvb_frontend *ts2020_attach(struct dvb_frontend *fe,
 
        /* Check the tuner version */
        buf = ts2020_readreg(fe, 0x00);
-       if ((buf == 0x01) || (buf == 0x41) || (buf == 0x81))
+       if ((buf == 0x01) || (buf == 0x41) || (buf == 0x81)) {
                printk(KERN_INFO "%s: Find tuner TS2020!\n", __func__);
-       else {
+               priv->tuner = TS2020_M88TS2020;
+       } else if ((buf == 0x83) || (buf == 0xc3)) {
+               printk(KERN_INFO "%s: Find tuner TS2022!\n", __func__);
+               priv->tuner = TS2020_M88TS2022;
+       } else {
                printk(KERN_ERR "%s: Read tuner reg[0] = %d\n", __func__, buf);
                kfree(priv);
                return NULL;
@@ -373,6 +450,165 @@ struct dvb_frontend *ts2020_attach(struct dvb_frontend *fe,
 }
 EXPORT_SYMBOL(ts2020_attach);
 
+static int ts2020_probe(struct i2c_client *client,
+               const struct i2c_device_id *id)
+{
+       struct ts2020_config *pdata = client->dev.platform_data;
+       struct dvb_frontend *fe = pdata->fe;
+       struct ts2020_priv *dev;
+       int ret;
+       u8 u8tmp;
+       unsigned int utmp;
+       char *chip_str;
+
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (!dev) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       dev->i2c = client->adapter;
+       dev->i2c_address = client->addr;
+       dev->clk_out = pdata->clk_out;
+       dev->clk_out_div = pdata->clk_out_div;
+       dev->frequency_div = pdata->frequency_div;
+       dev->fe = fe;
+       fe->tuner_priv = dev;
+
+       /* check if the tuner is there */
+       ret = ts2020_readreg(fe, 0x00);
+       if (ret < 0)
+               goto err;
+       utmp = ret;
+
+       if ((utmp & 0x03) == 0x00) {
+               ret = ts2020_writereg(fe, 0x00, 0x01);
+               if (ret)
+                       goto err;
+
+               usleep_range(2000, 50000);
+       }
+
+       ret = ts2020_writereg(fe, 0x00, 0x03);
+       if (ret)
+               goto err;
+
+       usleep_range(2000, 50000);
+
+       ret = ts2020_readreg(fe, 0x00);
+       if (ret < 0)
+               goto err;
+       utmp = ret;
+
+       dev_dbg(&client->dev, "chip_id=%02x\n", utmp);
+
+       switch (utmp) {
+       case 0x01:
+       case 0x41:
+       case 0x81:
+               dev->tuner = TS2020_M88TS2020;
+               chip_str = "TS2020";
+               if (!dev->frequency_div)
+                       dev->frequency_div = 1060000;
+               break;
+       case 0xc3:
+       case 0x83:
+               dev->tuner = TS2020_M88TS2022;
+               chip_str = "TS2022";
+               if (!dev->frequency_div)
+                       dev->frequency_div = 1103000;
+               break;
+       default:
+               ret = -ENODEV;
+               goto err;
+       }
+
+       if (dev->tuner == TS2020_M88TS2022) {
+               switch (dev->clk_out) {
+               case TS2020_CLK_OUT_DISABLED:
+                       u8tmp = 0x60;
+                       break;
+               case TS2020_CLK_OUT_ENABLED:
+                       u8tmp = 0x70;
+                       ret = ts2020_writereg(fe, 0x05, dev->clk_out_div);
+                       if (ret)
+                               goto err;
+                       break;
+               case TS2020_CLK_OUT_ENABLED_XTALOUT:
+                       u8tmp = 0x6c;
+                       break;
+               default:
+                       ret = -EINVAL;
+                       goto err;
+               }
+
+               ret = ts2020_writereg(fe, 0x42, u8tmp);
+               if (ret)
+                       goto err;
+
+               if (dev->loop_through)
+                       u8tmp = 0xec;
+               else
+                       u8tmp = 0x6c;
+
+               ret = ts2020_writereg(fe, 0x62, u8tmp);
+               if (ret)
+                       goto err;
+       }
+
+       /* sleep */
+       ret = ts2020_writereg(fe, 0x00, 0x00);
+       if (ret)
+               goto err;
+
+       dev_info(&client->dev,
+                "Montage Technology %s successfully identified\n", chip_str);
+
+       memcpy(&fe->ops.tuner_ops, &ts2020_tuner_ops,
+                       sizeof(struct dvb_tuner_ops));
+       fe->ops.tuner_ops.release = NULL;
+
+       i2c_set_clientdata(client, dev);
+       return 0;
+err:
+       dev_dbg(&client->dev, "failed=%d\n", ret);
+       kfree(dev);
+       return ret;
+}
+
+static int ts2020_remove(struct i2c_client *client)
+{
+       struct ts2020_priv *dev = i2c_get_clientdata(client);
+       struct dvb_frontend *fe = dev->fe;
+
+       dev_dbg(&client->dev, "\n");
+
+       memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));
+       fe->tuner_priv = NULL;
+       kfree(dev);
+
+       return 0;
+}
+
+static const struct i2c_device_id ts2020_id_table[] = {
+       {"ts2020", 0},
+       {"ts2022", 0},
+       {}
+};
+MODULE_DEVICE_TABLE(i2c, ts2020_id_table);
+
+static struct i2c_driver ts2020_driver = {
+       .driver = {
+               .owner  = THIS_MODULE,
+               .name   = "ts2020",
+       },
+       .probe          = ts2020_probe,
+       .remove         = ts2020_remove,
+       .id_table       = ts2020_id_table,
+};
+
+module_i2c_driver(ts2020_driver);
+
 MODULE_AUTHOR("Konstantin Dimitrov <kosio.dimitrov@gmail.com>");
 MODULE_DESCRIPTION("Montage Technology TS2020 - Silicon tuner driver module");
 MODULE_LICENSE("GPL");
index b2fe6bb3a38b0c425d2d31b167351382f1cae2dd..1714af94eca249418b82c0748540dd23c770740b 100644 (file)
 
 struct ts2020_config {
        u8 tuner_address;
-       u8 clk_out_div;
        u32 frequency_div;
+
+       /*
+        * RF loop-through
+        */
+       u8 loop_through:1;
+
+       /*
+        * clock output
+        */
+#define TS2020_CLK_OUT_DISABLED        0
+#define TS2020_CLK_OUT_ENABLED         1
+#define TS2020_CLK_OUT_ENABLED_XTALOUT 2
+       u8 clk_out:2;
+
+       /*
+        * clock output divider
+        * 1 - 31
+        */
+       u8 clk_out_div:5;
+
+       /*
+        * pointer to DVB frontend
+        */
+       struct dvb_frontend *fe;
 };
 
-#if IS_ENABLED(CONFIG_DVB_TS2020)
+#if IS_REACHABLE(CONFIG_DVB_TS2020)
 
 extern struct dvb_frontend *ts2020_attach(
        struct dvb_frontend *fe,
index 83a9c30e67ca07aa3538c3d9cfe772a4c90d75ac..52919e04e25852b35f7e85d6c86425d02dbfe12d 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/i2c.h>
 #include "dvb_frontend.h"
 
-#if IS_ENABLED(CONFIG_DVB_TUA6100)
+#if IS_REACHABLE(CONFIG_DVB_TUA6100)
 extern struct dvb_frontend *tua6100_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c);
 #else
 static inline struct dvb_frontend* tua6100_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c)
index c073f353ac387e4fd4dce10e99a99784ed0c603e..ece46fdcd7141dbe032ea4efdc794838ba22d422 100644 (file)
@@ -41,7 +41,7 @@ struct ves1820_config
        u8 selagc:1;
 };
 
-#if IS_ENABLED(CONFIG_DVB_VES1820)
+#if IS_REACHABLE(CONFIG_DVB_VES1820)
 extern struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
                                           struct i2c_adapter* i2c, u8 pwm);
 #else
index 2307caea6aecfe6bd7a22b3b7f270c1e494dd10d..4510fe2f6676c0113faeacc4cdf2e0db6c256fe2 100644 (file)
@@ -40,7 +40,7 @@ struct ves1x93_config
        u8 invert_pwm:1;
 };
 
-#if IS_ENABLED(CONFIG_DVB_VES1X93)
+#if IS_REACHABLE(CONFIG_DVB_VES1X93)
 extern struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
                                           struct i2c_adapter* i2c);
 #else
index 5f1e8217eeb61c21388d3137f92e7bf3ea339cd8..670e76a654ee4f8a7556075d3539e96236a50d11 100644 (file)
@@ -38,7 +38,7 @@ struct zl10036_config {
        int rf_loop_enable;
 };
 
-#if IS_ENABLED(CONFIG_DVB_ZL10036)
+#if IS_REACHABLE(CONFIG_DVB_ZL10036)
 extern struct dvb_frontend *zl10036_attach(struct dvb_frontend *fe,
        const struct zl10036_config *config, struct i2c_adapter *i2c);
 #else
index 750b9bca9d02d117198b20852a9a93db395f97ff..070929444e7111453403844d87d0a9b0321c762e 100644 (file)
@@ -24,7 +24,7 @@
 
 #include <linux/kconfig.h>
 
-#if IS_ENABLED(CONFIG_DVB_ZL10039)
+#if IS_REACHABLE(CONFIG_DVB_ZL10039)
 struct dvb_frontend *zl10039_attach(struct dvb_frontend *fe,
                                        u8 i2c_addr,
                                        struct i2c_adapter *i2c);
index 50c1004aef366ef1f3080c8c9fadb267109fe074..37aa6e8f454a71977795fdb2e2f0b494052013fb 100644 (file)
@@ -47,7 +47,7 @@ struct zl10353_config
        u8 pll_0;        /* default: 0x15 */
 };
 
-#if IS_ENABLED(CONFIG_DVB_ZL10353)
+#if IS_REACHABLE(CONFIG_DVB_ZL10353)
 extern struct dvb_frontend* zl10353_attach(const struct zl10353_config *config,
                                           struct i2c_adapter *i2c);
 #else
index da58c9bb67c2d2c39094c8dff003aa742c502d76..6f30ea76151a9730aef1d113921f946ba56d32b3 100644 (file)
@@ -466,6 +466,17 @@ config VIDEO_APTINA_PLL
 config VIDEO_SMIAPP_PLL
        tristate
 
+config VIDEO_OV2659
+       tristate "OmniVision OV2659 sensor support"
+       depends on VIDEO_V4L2 && I2C
+       depends on MEDIA_CAMERA_SUPPORT
+       ---help---
+         This is a Video4Linux2 sensor-level driver for the OmniVision
+         OV2659 camera.
+
+         To compile this driver as a module, choose M here: the
+         module will be called ov2659.
+
 config VIDEO_OV7640
        tristate "OmniVision OV7640 sensor support"
        depends on I2C && VIDEO_V4L2
index 9858900168bfe967dc4d1957361b1c9622f83689..f165faea5b3f97c9134617dd752abceebff746ff 100644 (file)
@@ -77,3 +77,4 @@ obj-$(CONFIG_VIDEO_SMIAPP_PLL)        += smiapp-pll.o
 obj-$(CONFIG_VIDEO_AK881X)             += ak881x.o
 obj-$(CONFIG_VIDEO_IR_I2C)  += ir-kbd-i2c.o
 obj-$(CONFIG_VIDEO_ML86V7667)  += ml86v7667.o
+obj-$(CONFIG_VIDEO_OV2659)     += ov2659.o
index fada17566205015d32d5923ed068d21efcc6ae5a..69094ab047b1d955040f6f6e2a7afd10287fec6c 100644 (file)
@@ -239,8 +239,8 @@ static void ad9389b_set_IT_content_AVI_InfoFrame(struct v4l2_subdev *sd)
 {
        struct ad9389b_state *state = get_ad9389b_state(sd);
 
-       if (state->dv_timings.bt.standards & V4L2_DV_BT_STD_CEA861) {
-               /* CEA format, not IT  */
+       if (state->dv_timings.bt.flags & V4L2_DV_FL_IS_CE_VIDEO) {
+               /* CE format, not IT  */
                ad9389b_wr_and_or(sd, 0xcd, 0xbf, 0x00);
        } else {
                /* IT format */
@@ -255,11 +255,11 @@ static int ad9389b_set_rgb_quantization_mode(struct v4l2_subdev *sd, struct v4l2
        switch (ctrl->val) {
        case V4L2_DV_RGB_RANGE_AUTO:
                /* automatic */
-               if (state->dv_timings.bt.standards & V4L2_DV_BT_STD_CEA861) {
-                       /* cea format, RGB limited range (16-235) */
+               if (state->dv_timings.bt.flags & V4L2_DV_FL_IS_CE_VIDEO) {
+                       /* CE format, RGB limited range (16-235) */
                        ad9389b_csc_rgb_full2limit(sd, true);
                } else {
-                       /* not cea format, RGB full range (0-255) */
+                       /* not CE format, RGB full range (0-255) */
                        ad9389b_csc_rgb_full2limit(sd, false);
                }
                break;
index b75878c27c2a3474c28420be0c3341ce03986b0f..a493c0b0b5fefc7ea3d2f9d531d4e0074efe825d 100644 (file)
@@ -582,7 +582,7 @@ static void adv7180_exit_controls(struct adv7180_state *state)
 }
 
 static int adv7180_enum_mbus_code(struct v4l2_subdev *sd,
-                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_pad_config *cfg,
                                  struct v4l2_subdev_mbus_code_enum *code)
 {
        if (code->index != 0)
@@ -645,13 +645,13 @@ static int adv7180_set_field_mode(struct adv7180_state *state)
 }
 
 static int adv7180_get_pad_format(struct v4l2_subdev *sd,
-                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_pad_config *cfg,
                                  struct v4l2_subdev_format *format)
 {
        struct adv7180_state *state = to_state(sd);
 
        if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
-               format->format = *v4l2_subdev_get_try_format(fh, 0);
+               format->format = *v4l2_subdev_get_try_format(sd, cfg, 0);
        } else {
                adv7180_mbus_fmt(sd, &format->format);
                format->format.field = state->field;
@@ -661,7 +661,7 @@ static int adv7180_get_pad_format(struct v4l2_subdev *sd,
 }
 
 static int adv7180_set_pad_format(struct v4l2_subdev *sd,
-                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_pad_config *cfg,
                                  struct v4l2_subdev_format *format)
 {
        struct adv7180_state *state = to_state(sd);
@@ -686,7 +686,7 @@ static int adv7180_set_pad_format(struct v4l2_subdev *sd,
                        adv7180_set_power(state, true);
                }
        } else {
-               framefmt = v4l2_subdev_get_try_format(fh, 0);
+               framefmt = v4l2_subdev_get_try_format(sd, cfg, 0);
                *framefmt = format->format;
        }
 
index 9d38f7b36cd10296aa301bde712503bafb60621d..7c50833e7d172bb1108c1fc229ec3f26896ae9da 100644 (file)
@@ -506,7 +506,6 @@ static int adv7343_remove(struct i2c_client *client)
        struct adv7343_state *state = to_state(sd);
 
        v4l2_async_unregister_subdev(&state->sd);
-       v4l2_device_unregister_subdev(sd);
        v4l2_ctrl_handler_free(&state->hdl);
 
        return 0;
index 81736aaf0f311cc5899555ea635417e7b9863f77..12d93203d405b8de9512287eb31007b2c3d31333 100644 (file)
@@ -312,8 +312,8 @@ static void adv7511_csc_rgb_full2limit(struct v4l2_subdev *sd, bool enable)
 static void adv7511_set_IT_content_AVI_InfoFrame(struct v4l2_subdev *sd)
 {
        struct adv7511_state *state = get_adv7511_state(sd);
-       if (state->dv_timings.bt.standards & V4L2_DV_BT_STD_CEA861) {
-               /* CEA format, not IT  */
+       if (state->dv_timings.bt.flags & V4L2_DV_FL_IS_CE_VIDEO) {
+               /* CE format, not IT  */
                adv7511_wr_and_or(sd, 0x57, 0x7f, 0x00);
        } else {
                /* IT format */
@@ -331,11 +331,11 @@ static int adv7511_set_rgb_quantization_mode(struct v4l2_subdev *sd, struct v4l2
                /* automatic */
                struct adv7511_state *state = get_adv7511_state(sd);
 
-               if (state->dv_timings.bt.standards & V4L2_DV_BT_STD_CEA861) {
-                       /* cea format, RGB limited range (16-235) */
+               if (state->dv_timings.bt.flags & V4L2_DV_FL_IS_CE_VIDEO) {
+                       /* CE format, RGB limited range (16-235) */
                        adv7511_csc_rgb_full2limit(sd, true);
                } else {
-                       /* not cea format, RGB full range (0-255) */
+                       /* not CE format, RGB full range (0-255) */
                        adv7511_csc_rgb_full2limit(sd, false);
                }
        }
@@ -810,7 +810,7 @@ static int adv7511_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
 }
 
 static int adv7511_enum_mbus_code(struct v4l2_subdev *sd,
-                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_pad_config *cfg,
                                  struct v4l2_subdev_mbus_code_enum *code)
 {
        if (code->pad != 0)
@@ -842,8 +842,9 @@ static void adv7511_fill_format(struct adv7511_state *state,
        format->field = V4L2_FIELD_NONE;
 }
 
-static int adv7511_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
-                             struct v4l2_subdev_format *format)
+static int adv7511_get_fmt(struct v4l2_subdev *sd,
+                          struct v4l2_subdev_pad_config *cfg,
+                          struct v4l2_subdev_format *format)
 {
        struct adv7511_state *state = get_adv7511_state(sd);
 
@@ -855,7 +856,7 @@ static int adv7511_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
                struct v4l2_mbus_framefmt *fmt;
 
-               fmt = v4l2_subdev_get_try_format(fh, format->pad);
+               fmt = v4l2_subdev_get_try_format(sd, cfg, format->pad);
                format->format.code = fmt->code;
                format->format.colorspace = fmt->colorspace;
                format->format.ycbcr_enc = fmt->ycbcr_enc;
@@ -870,8 +871,9 @@ static int adv7511_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        return 0;
 }
 
-static int adv7511_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
-                      struct v4l2_subdev_format *format)
+static int adv7511_set_fmt(struct v4l2_subdev *sd,
+                          struct v4l2_subdev_pad_config *cfg,
+                          struct v4l2_subdev_format *format)
 {
        struct adv7511_state *state = get_adv7511_state(sd);
        /*
@@ -905,7 +907,7 @@ static int adv7511_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
                struct v4l2_mbus_framefmt *fmt;
 
-               fmt = v4l2_subdev_get_try_format(fh, format->pad);
+               fmt = v4l2_subdev_get_try_format(sd, cfg, format->pad);
                fmt->code = format->format.code;
                fmt->colorspace = format->format.colorspace;
                fmt->ycbcr_enc = format->format.ycbcr_enc;
index d228b7c82310c4d5c8cd0b4fca9e5f714e78d35d..60ffcf098befa991021ae43f161ebdb1fd7f2037 100644 (file)
@@ -53,41 +53,41 @@ MODULE_AUTHOR("Mats Randgaard <mats.randgaard@cisco.com>");
 MODULE_LICENSE("GPL");
 
 /* ADV7604 system clock frequency */
-#define ADV7604_fsc (28636360)
+#define ADV76XX_FSC (28636360)
 
-#define ADV7604_RGB_OUT                                        (1 << 1)
+#define ADV76XX_RGB_OUT                                        (1 << 1)
 
-#define ADV7604_OP_FORMAT_SEL_8BIT                     (0 << 0)
+#define ADV76XX_OP_FORMAT_SEL_8BIT                     (0 << 0)
 #define ADV7604_OP_FORMAT_SEL_10BIT                    (1 << 0)
-#define ADV7604_OP_FORMAT_SEL_12BIT                    (2 << 0)
+#define ADV76XX_OP_FORMAT_SEL_12BIT                    (2 << 0)
 
-#define ADV7604_OP_MODE_SEL_SDR_422                    (0 << 5)
+#define ADV76XX_OP_MODE_SEL_SDR_422                    (0 << 5)
 #define ADV7604_OP_MODE_SEL_DDR_422                    (1 << 5)
-#define ADV7604_OP_MODE_SEL_SDR_444                    (2 << 5)
+#define ADV76XX_OP_MODE_SEL_SDR_444                    (2 << 5)
 #define ADV7604_OP_MODE_SEL_DDR_444                    (3 << 5)
-#define ADV7604_OP_MODE_SEL_SDR_422_2X                 (4 << 5)
+#define ADV76XX_OP_MODE_SEL_SDR_422_2X                 (4 << 5)
 #define ADV7604_OP_MODE_SEL_ADI_CM                     (5 << 5)
 
-#define ADV7604_OP_CH_SEL_GBR                          (0 << 5)
-#define ADV7604_OP_CH_SEL_GRB                          (1 << 5)
-#define ADV7604_OP_CH_SEL_BGR                          (2 << 5)
-#define ADV7604_OP_CH_SEL_RGB                          (3 << 5)
-#define ADV7604_OP_CH_SEL_BRG                          (4 << 5)
-#define ADV7604_OP_CH_SEL_RBG                          (5 << 5)
+#define ADV76XX_OP_CH_SEL_GBR                          (0 << 5)
+#define ADV76XX_OP_CH_SEL_GRB                          (1 << 5)
+#define ADV76XX_OP_CH_SEL_BGR                          (2 << 5)
+#define ADV76XX_OP_CH_SEL_RGB                          (3 << 5)
+#define ADV76XX_OP_CH_SEL_BRG                          (4 << 5)
+#define ADV76XX_OP_CH_SEL_RBG                          (5 << 5)
 
-#define ADV7604_OP_SWAP_CB_CR                          (1 << 0)
+#define ADV76XX_OP_SWAP_CB_CR                          (1 << 0)
 
-enum adv7604_type {
+enum adv76xx_type {
        ADV7604,
        ADV7611,
 };
 
-struct adv7604_reg_seq {
+struct adv76xx_reg_seq {
        unsigned int reg;
        u8 val;
 };
 
-struct adv7604_format_info {
+struct adv76xx_format_info {
        u32 code;
        u8 op_ch_sel;
        bool rgb_out;
@@ -95,8 +95,8 @@ struct adv7604_format_info {
        u8 op_format_sel;
 };
 
-struct adv7604_chip_info {
-       enum adv7604_type type;
+struct adv76xx_chip_info {
+       enum adv76xx_type type;
 
        bool has_afe;
        unsigned int max_port;
@@ -109,8 +109,9 @@ struct adv7604_chip_info {
        unsigned int cable_det_mask;
        unsigned int tdms_lock_mask;
        unsigned int fmt_change_digital_mask;
+       unsigned int cp_csc;
 
-       const struct adv7604_format_info *formats;
+       const struct adv76xx_format_info *formats;
        unsigned int nformats;
 
        void (*set_termination)(struct v4l2_subdev *sd, bool enable);
@@ -119,7 +120,7 @@ struct adv7604_chip_info {
        unsigned int (*read_cable_det)(struct v4l2_subdev *sd);
 
        /* 0 = AFE, 1 = HDMI */
-       const struct adv7604_reg_seq *recommended_settings[2];
+       const struct adv76xx_reg_seq *recommended_settings[2];
        unsigned int num_recommended_settings[2];
 
        unsigned long page_mask;
@@ -133,22 +134,22 @@ struct adv7604_chip_info {
  **********************************************************************
  */
 
-struct adv7604_state {
-       const struct adv7604_chip_info *info;
-       struct adv7604_platform_data pdata;
+struct adv76xx_state {
+       const struct adv76xx_chip_info *info;
+       struct adv76xx_platform_data pdata;
 
        struct gpio_desc *hpd_gpio[4];
 
        struct v4l2_subdev sd;
-       struct media_pad pads[ADV7604_PAD_MAX];
+       struct media_pad pads[ADV76XX_PAD_MAX];
        unsigned int source_pad;
 
        struct v4l2_ctrl_handler hdl;
 
-       enum adv7604_pad selected_input;
+       enum adv76xx_pad selected_input;
 
        struct v4l2_dv_timings timings;
-       const struct adv7604_format_info *format;
+       const struct adv76xx_format_info *format;
 
        struct {
                u8 edid[256];
@@ -163,7 +164,7 @@ struct adv7604_state {
        bool restart_stdi_once;
 
        /* i2c clients */
-       struct i2c_client *i2c_clients[ADV7604_PAGE_MAX];
+       struct i2c_client *i2c_clients[ADV76XX_PAGE_MAX];
 
        /* controls */
        struct v4l2_ctrl *detect_tx_5v_ctrl;
@@ -173,13 +174,13 @@ struct adv7604_state {
        struct v4l2_ctrl *rgb_quantization_range_ctrl;
 };
 
-static bool adv7604_has_afe(struct adv7604_state *state)
+static bool adv76xx_has_afe(struct adv76xx_state *state)
 {
        return state->info->has_afe;
 }
 
 /* Supported CEA and DMT timings */
-static const struct v4l2_dv_timings adv7604_timings[] = {
+static const struct v4l2_dv_timings adv76xx_timings[] = {
        V4L2_DV_BT_CEA_720X480P59_94,
        V4L2_DV_BT_CEA_720X576P50,
        V4L2_DV_BT_CEA_1280X720P24,
@@ -243,14 +244,14 @@ static const struct v4l2_dv_timings adv7604_timings[] = {
        { },
 };
 
-struct adv7604_video_standards {
+struct adv76xx_video_standards {
        struct v4l2_dv_timings timings;
        u8 vid_std;
        u8 v_freq;
 };
 
 /* sorted by number of lines */
-static const struct adv7604_video_standards adv7604_prim_mode_comp[] = {
+static const struct adv76xx_video_standards adv7604_prim_mode_comp[] = {
        /* { V4L2_DV_BT_CEA_720X480P59_94, 0x0a, 0x00 }, TODO flickering */
        { V4L2_DV_BT_CEA_720X576P50, 0x0b, 0x00 },
        { V4L2_DV_BT_CEA_1280X720P50, 0x19, 0x01 },
@@ -265,7 +266,7 @@ static const struct adv7604_video_standards adv7604_prim_mode_comp[] = {
 };
 
 /* sorted by number of lines */
-static const struct adv7604_video_standards adv7604_prim_mode_gr[] = {
+static const struct adv76xx_video_standards adv7604_prim_mode_gr[] = {
        { V4L2_DV_BT_DMT_640X480P60, 0x08, 0x00 },
        { V4L2_DV_BT_DMT_640X480P72, 0x09, 0x00 },
        { V4L2_DV_BT_DMT_640X480P75, 0x0a, 0x00 },
@@ -293,7 +294,7 @@ static const struct adv7604_video_standards adv7604_prim_mode_gr[] = {
 };
 
 /* sorted by number of lines */
-static const struct adv7604_video_standards adv7604_prim_mode_hdmi_comp[] = {
+static const struct adv76xx_video_standards adv76xx_prim_mode_hdmi_comp[] = {
        { V4L2_DV_BT_CEA_720X480P59_94, 0x0a, 0x00 },
        { V4L2_DV_BT_CEA_720X576P50, 0x0b, 0x00 },
        { V4L2_DV_BT_CEA_1280X720P50, 0x13, 0x01 },
@@ -307,7 +308,7 @@ static const struct adv7604_video_standards adv7604_prim_mode_hdmi_comp[] = {
 };
 
 /* sorted by number of lines */
-static const struct adv7604_video_standards adv7604_prim_mode_hdmi_gr[] = {
+static const struct adv76xx_video_standards adv76xx_prim_mode_hdmi_gr[] = {
        { V4L2_DV_BT_DMT_640X480P60, 0x08, 0x00 },
        { V4L2_DV_BT_DMT_640X480P72, 0x09, 0x00 },
        { V4L2_DV_BT_DMT_640X480P75, 0x0a, 0x00 },
@@ -328,9 +329,9 @@ static const struct adv7604_video_standards adv7604_prim_mode_hdmi_gr[] = {
 
 /* ----------------------------------------------------------------------- */
 
-static inline struct adv7604_state *to_state(struct v4l2_subdev *sd)
+static inline struct adv76xx_state *to_state(struct v4l2_subdev *sd)
 {
-       return container_of(sd, struct adv7604_state, sd);
+       return container_of(sd, struct adv76xx_state, sd);
 }
 
 static inline unsigned htotal(const struct v4l2_bt_timings *t)
@@ -360,15 +361,15 @@ static s32 adv_smbus_read_byte_data_check(struct i2c_client *client,
        return -EIO;
 }
 
-static s32 adv_smbus_read_byte_data(struct adv7604_state *state,
-                                   enum adv7604_page page, u8 command)
+static s32 adv_smbus_read_byte_data(struct adv76xx_state *state,
+                                   enum adv76xx_page page, u8 command)
 {
        return adv_smbus_read_byte_data_check(state->i2c_clients[page],
                                              command, true);
 }
 
-static s32 adv_smbus_write_byte_data(struct adv7604_state *state,
-                                    enum adv7604_page page, u8 command,
+static s32 adv_smbus_write_byte_data(struct adv76xx_state *state,
+                                    enum adv76xx_page page, u8 command,
                                     u8 value)
 {
        struct i2c_client *client = state->i2c_clients[page];
@@ -391,8 +392,8 @@ static s32 adv_smbus_write_byte_data(struct adv7604_state *state,
        return err;
 }
 
-static s32 adv_smbus_write_i2c_block_data(struct adv7604_state *state,
-                                         enum adv7604_page page, u8 command,
+static s32 adv_smbus_write_i2c_block_data(struct adv76xx_state *state,
+                                         enum adv76xx_page page, u8 command,
                                          unsigned length, const u8 *values)
 {
        struct i2c_client *client = state->i2c_clients[page];
@@ -411,16 +412,16 @@ static s32 adv_smbus_write_i2c_block_data(struct adv7604_state *state,
 
 static inline int io_read(struct v4l2_subdev *sd, u8 reg)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
-       return adv_smbus_read_byte_data(state, ADV7604_PAGE_IO, reg);
+       return adv_smbus_read_byte_data(state, ADV76XX_PAGE_IO, reg);
 }
 
 static inline int io_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
-       return adv_smbus_write_byte_data(state, ADV7604_PAGE_IO, reg, val);
+       return adv_smbus_write_byte_data(state, ADV76XX_PAGE_IO, reg, val);
 }
 
 static inline int io_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
@@ -430,73 +431,73 @@ static inline int io_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 v
 
 static inline int avlink_read(struct v4l2_subdev *sd, u8 reg)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
        return adv_smbus_read_byte_data(state, ADV7604_PAGE_AVLINK, reg);
 }
 
 static inline int avlink_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
        return adv_smbus_write_byte_data(state, ADV7604_PAGE_AVLINK, reg, val);
 }
 
 static inline int cec_read(struct v4l2_subdev *sd, u8 reg)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
-       return adv_smbus_read_byte_data(state, ADV7604_PAGE_CEC, reg);
+       return adv_smbus_read_byte_data(state, ADV76XX_PAGE_CEC, reg);
 }
 
 static inline int cec_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
-       return adv_smbus_write_byte_data(state, ADV7604_PAGE_CEC, reg, val);
+       return adv_smbus_write_byte_data(state, ADV76XX_PAGE_CEC, reg, val);
 }
 
 static inline int infoframe_read(struct v4l2_subdev *sd, u8 reg)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
-       return adv_smbus_read_byte_data(state, ADV7604_PAGE_INFOFRAME, reg);
+       return adv_smbus_read_byte_data(state, ADV76XX_PAGE_INFOFRAME, reg);
 }
 
 static inline int infoframe_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
-       return adv_smbus_write_byte_data(state, ADV7604_PAGE_INFOFRAME,
+       return adv_smbus_write_byte_data(state, ADV76XX_PAGE_INFOFRAME,
                                         reg, val);
 }
 
 static inline int afe_read(struct v4l2_subdev *sd, u8 reg)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
-       return adv_smbus_read_byte_data(state, ADV7604_PAGE_AFE, reg);
+       return adv_smbus_read_byte_data(state, ADV76XX_PAGE_AFE, reg);
 }
 
 static inline int afe_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
-       return adv_smbus_write_byte_data(state, ADV7604_PAGE_AFE, reg, val);
+       return adv_smbus_write_byte_data(state, ADV76XX_PAGE_AFE, reg, val);
 }
 
 static inline int rep_read(struct v4l2_subdev *sd, u8 reg)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
-       return adv_smbus_read_byte_data(state, ADV7604_PAGE_REP, reg);
+       return adv_smbus_read_byte_data(state, ADV76XX_PAGE_REP, reg);
 }
 
 static inline int rep_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
-       return adv_smbus_write_byte_data(state, ADV7604_PAGE_REP, reg, val);
+       return adv_smbus_write_byte_data(state, ADV76XX_PAGE_REP, reg, val);
 }
 
 static inline int rep_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
@@ -506,64 +507,60 @@ static inline int rep_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8
 
 static inline int edid_read(struct v4l2_subdev *sd, u8 reg)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
-       return adv_smbus_read_byte_data(state, ADV7604_PAGE_EDID, reg);
+       return adv_smbus_read_byte_data(state, ADV76XX_PAGE_EDID, reg);
 }
 
 static inline int edid_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
-       return adv_smbus_write_byte_data(state, ADV7604_PAGE_EDID, reg, val);
+       return adv_smbus_write_byte_data(state, ADV76XX_PAGE_EDID, reg, val);
 }
 
 static inline int edid_write_block(struct v4l2_subdev *sd,
                                        unsigned len, const u8 *val)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
        int err = 0;
        int i;
 
        v4l2_dbg(2, debug, sd, "%s: write EDID block (%d byte)\n", __func__, len);
 
        for (i = 0; !err && i < len; i += I2C_SMBUS_BLOCK_MAX)
-               err = adv_smbus_write_i2c_block_data(state, ADV7604_PAGE_EDID,
+               err = adv_smbus_write_i2c_block_data(state, ADV76XX_PAGE_EDID,
                                i, I2C_SMBUS_BLOCK_MAX, val + i);
        return err;
 }
 
-static void adv7604_set_hpd(struct adv7604_state *state, unsigned int hpd)
+static void adv76xx_set_hpd(struct adv76xx_state *state, unsigned int hpd)
 {
        unsigned int i;
 
-       for (i = 0; i < state->info->num_dv_ports; ++i) {
-               if (IS_ERR(state->hpd_gpio[i]))
-                       continue;
-
+       for (i = 0; i < state->info->num_dv_ports; ++i)
                gpiod_set_value_cansleep(state->hpd_gpio[i], hpd & BIT(i));
-       }
 
-       v4l2_subdev_notify(&state->sd, ADV7604_HOTPLUG, &hpd);
+       v4l2_subdev_notify(&state->sd, ADV76XX_HOTPLUG, &hpd);
 }
 
-static void adv7604_delayed_work_enable_hotplug(struct work_struct *work)
+static void adv76xx_delayed_work_enable_hotplug(struct work_struct *work)
 {
        struct delayed_work *dwork = to_delayed_work(work);
-       struct adv7604_state *state = container_of(dwork, struct adv7604_state,
+       struct adv76xx_state *state = container_of(dwork, struct adv76xx_state,
                                                delayed_work_enable_hotplug);
        struct v4l2_subdev *sd = &state->sd;
 
        v4l2_dbg(2, debug, sd, "%s: enable hotplug\n", __func__);
 
-       adv7604_set_hpd(state, state->edid.present);
+       adv76xx_set_hpd(state, state->edid.present);
 }
 
 static inline int hdmi_read(struct v4l2_subdev *sd, u8 reg)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
-       return adv_smbus_read_byte_data(state, ADV7604_PAGE_HDMI, reg);
+       return adv_smbus_read_byte_data(state, ADV76XX_PAGE_HDMI, reg);
 }
 
 static u16 hdmi_read16(struct v4l2_subdev *sd, u8 reg, u16 mask)
@@ -573,9 +570,9 @@ static u16 hdmi_read16(struct v4l2_subdev *sd, u8 reg, u16 mask)
 
 static inline int hdmi_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
-       return adv_smbus_write_byte_data(state, ADV7604_PAGE_HDMI, reg, val);
+       return adv_smbus_write_byte_data(state, ADV76XX_PAGE_HDMI, reg, val);
 }
 
 static inline int hdmi_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
@@ -585,16 +582,16 @@ static inline int hdmi_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8
 
 static inline int test_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
-       return adv_smbus_write_byte_data(state, ADV7604_PAGE_TEST, reg, val);
+       return adv_smbus_write_byte_data(state, ADV76XX_PAGE_TEST, reg, val);
 }
 
 static inline int cp_read(struct v4l2_subdev *sd, u8 reg)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
-       return adv_smbus_read_byte_data(state, ADV7604_PAGE_CP, reg);
+       return adv_smbus_read_byte_data(state, ADV76XX_PAGE_CP, reg);
 }
 
 static u16 cp_read16(struct v4l2_subdev *sd, u8 reg, u16 mask)
@@ -604,9 +601,9 @@ static u16 cp_read16(struct v4l2_subdev *sd, u8 reg, u16 mask)
 
 static inline int cp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
-       return adv_smbus_write_byte_data(state, ADV7604_PAGE_CP, reg, val);
+       return adv_smbus_write_byte_data(state, ADV76XX_PAGE_CP, reg, val);
 }
 
 static inline int cp_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
@@ -616,25 +613,25 @@ static inline int cp_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 v
 
 static inline int vdp_read(struct v4l2_subdev *sd, u8 reg)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
        return adv_smbus_read_byte_data(state, ADV7604_PAGE_VDP, reg);
 }
 
 static inline int vdp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
        return adv_smbus_write_byte_data(state, ADV7604_PAGE_VDP, reg, val);
 }
 
-#define ADV7604_REG(page, offset)      (((page) << 8) | (offset))
-#define ADV7604_REG_SEQ_TERM           0xffff
+#define ADV76XX_REG(page, offset)      (((page) << 8) | (offset))
+#define ADV76XX_REG_SEQ_TERM           0xffff
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-static int adv7604_read_reg(struct v4l2_subdev *sd, unsigned int reg)
+static int adv76xx_read_reg(struct v4l2_subdev *sd, unsigned int reg)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
        unsigned int page = reg >> 8;
 
        if (!(BIT(page) & state->info->page_mask))
@@ -646,9 +643,9 @@ static int adv7604_read_reg(struct v4l2_subdev *sd, unsigned int reg)
 }
 #endif
 
-static int adv7604_write_reg(struct v4l2_subdev *sd, unsigned int reg, u8 val)
+static int adv76xx_write_reg(struct v4l2_subdev *sd, unsigned int reg, u8 val)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
        unsigned int page = reg >> 8;
 
        if (!(BIT(page) & state->info->page_mask))
@@ -659,91 +656,91 @@ static int adv7604_write_reg(struct v4l2_subdev *sd, unsigned int reg, u8 val)
        return adv_smbus_write_byte_data(state, page, reg, val);
 }
 
-static void adv7604_write_reg_seq(struct v4l2_subdev *sd,
-                                 const struct adv7604_reg_seq *reg_seq)
+static void adv76xx_write_reg_seq(struct v4l2_subdev *sd,
+                                 const struct adv76xx_reg_seq *reg_seq)
 {
        unsigned int i;
 
-       for (i = 0; reg_seq[i].reg != ADV7604_REG_SEQ_TERM; i++)
-               adv7604_write_reg(sd, reg_seq[i].reg, reg_seq[i].val);
+       for (i = 0; reg_seq[i].reg != ADV76XX_REG_SEQ_TERM; i++)
+               adv76xx_write_reg(sd, reg_seq[i].reg, reg_seq[i].val);
 }
 
 /* -----------------------------------------------------------------------------
  * Format helpers
  */
 
-static const struct adv7604_format_info adv7604_formats[] = {
-       { MEDIA_BUS_FMT_RGB888_1X24, ADV7604_OP_CH_SEL_RGB, true, false,
-         ADV7604_OP_MODE_SEL_SDR_444 | ADV7604_OP_FORMAT_SEL_8BIT },
-       { MEDIA_BUS_FMT_YUYV8_2X8, ADV7604_OP_CH_SEL_RGB, false, false,
-         ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
-       { MEDIA_BUS_FMT_YVYU8_2X8, ADV7604_OP_CH_SEL_RGB, false, true,
-         ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
-       { MEDIA_BUS_FMT_YUYV10_2X10, ADV7604_OP_CH_SEL_RGB, false, false,
-         ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_10BIT },
-       { MEDIA_BUS_FMT_YVYU10_2X10, ADV7604_OP_CH_SEL_RGB, false, true,
-         ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_10BIT },
-       { MEDIA_BUS_FMT_YUYV12_2X12, ADV7604_OP_CH_SEL_RGB, false, false,
-         ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
-       { MEDIA_BUS_FMT_YVYU12_2X12, ADV7604_OP_CH_SEL_RGB, false, true,
-         ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
-       { MEDIA_BUS_FMT_UYVY8_1X16, ADV7604_OP_CH_SEL_RBG, false, false,
-         ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
-       { MEDIA_BUS_FMT_VYUY8_1X16, ADV7604_OP_CH_SEL_RBG, false, true,
-         ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
-       { MEDIA_BUS_FMT_YUYV8_1X16, ADV7604_OP_CH_SEL_RGB, false, false,
-         ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
-       { MEDIA_BUS_FMT_YVYU8_1X16, ADV7604_OP_CH_SEL_RGB, false, true,
-         ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
-       { MEDIA_BUS_FMT_UYVY10_1X20, ADV7604_OP_CH_SEL_RBG, false, false,
-         ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
-       { MEDIA_BUS_FMT_VYUY10_1X20, ADV7604_OP_CH_SEL_RBG, false, true,
-         ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
-       { MEDIA_BUS_FMT_YUYV10_1X20, ADV7604_OP_CH_SEL_RGB, false, false,
-         ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
-       { MEDIA_BUS_FMT_YVYU10_1X20, ADV7604_OP_CH_SEL_RGB, false, true,
-         ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
-       { MEDIA_BUS_FMT_UYVY12_1X24, ADV7604_OP_CH_SEL_RBG, false, false,
-         ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
-       { MEDIA_BUS_FMT_VYUY12_1X24, ADV7604_OP_CH_SEL_RBG, false, true,
-         ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
-       { MEDIA_BUS_FMT_YUYV12_1X24, ADV7604_OP_CH_SEL_RGB, false, false,
-         ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
-       { MEDIA_BUS_FMT_YVYU12_1X24, ADV7604_OP_CH_SEL_RGB, false, true,
-         ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
+static const struct adv76xx_format_info adv7604_formats[] = {
+       { MEDIA_BUS_FMT_RGB888_1X24, ADV76XX_OP_CH_SEL_RGB, true, false,
+         ADV76XX_OP_MODE_SEL_SDR_444 | ADV76XX_OP_FORMAT_SEL_8BIT },
+       { MEDIA_BUS_FMT_YUYV8_2X8, ADV76XX_OP_CH_SEL_RGB, false, false,
+         ADV76XX_OP_MODE_SEL_SDR_422 | ADV76XX_OP_FORMAT_SEL_8BIT },
+       { MEDIA_BUS_FMT_YVYU8_2X8, ADV76XX_OP_CH_SEL_RGB, false, true,
+         ADV76XX_OP_MODE_SEL_SDR_422 | ADV76XX_OP_FORMAT_SEL_8BIT },
+       { MEDIA_BUS_FMT_YUYV10_2X10, ADV76XX_OP_CH_SEL_RGB, false, false,
+         ADV76XX_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_10BIT },
+       { MEDIA_BUS_FMT_YVYU10_2X10, ADV76XX_OP_CH_SEL_RGB, false, true,
+         ADV76XX_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_10BIT },
+       { MEDIA_BUS_FMT_YUYV12_2X12, ADV76XX_OP_CH_SEL_RGB, false, false,
+         ADV76XX_OP_MODE_SEL_SDR_422 | ADV76XX_OP_FORMAT_SEL_12BIT },
+       { MEDIA_BUS_FMT_YVYU12_2X12, ADV76XX_OP_CH_SEL_RGB, false, true,
+         ADV76XX_OP_MODE_SEL_SDR_422 | ADV76XX_OP_FORMAT_SEL_12BIT },
+       { MEDIA_BUS_FMT_UYVY8_1X16, ADV76XX_OP_CH_SEL_RBG, false, false,
+         ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_8BIT },
+       { MEDIA_BUS_FMT_VYUY8_1X16, ADV76XX_OP_CH_SEL_RBG, false, true,
+         ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_8BIT },
+       { MEDIA_BUS_FMT_YUYV8_1X16, ADV76XX_OP_CH_SEL_RGB, false, false,
+         ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_8BIT },
+       { MEDIA_BUS_FMT_YVYU8_1X16, ADV76XX_OP_CH_SEL_RGB, false, true,
+         ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_8BIT },
+       { MEDIA_BUS_FMT_UYVY10_1X20, ADV76XX_OP_CH_SEL_RBG, false, false,
+         ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
+       { MEDIA_BUS_FMT_VYUY10_1X20, ADV76XX_OP_CH_SEL_RBG, false, true,
+         ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
+       { MEDIA_BUS_FMT_YUYV10_1X20, ADV76XX_OP_CH_SEL_RGB, false, false,
+         ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
+       { MEDIA_BUS_FMT_YVYU10_1X20, ADV76XX_OP_CH_SEL_RGB, false, true,
+         ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
+       { MEDIA_BUS_FMT_UYVY12_1X24, ADV76XX_OP_CH_SEL_RBG, false, false,
+         ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_12BIT },
+       { MEDIA_BUS_FMT_VYUY12_1X24, ADV76XX_OP_CH_SEL_RBG, false, true,
+         ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_12BIT },
+       { MEDIA_BUS_FMT_YUYV12_1X24, ADV76XX_OP_CH_SEL_RGB, false, false,
+         ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_12BIT },
+       { MEDIA_BUS_FMT_YVYU12_1X24, ADV76XX_OP_CH_SEL_RGB, false, true,
+         ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_12BIT },
 };
 
-static const struct adv7604_format_info adv7611_formats[] = {
-       { MEDIA_BUS_FMT_RGB888_1X24, ADV7604_OP_CH_SEL_RGB, true, false,
-         ADV7604_OP_MODE_SEL_SDR_444 | ADV7604_OP_FORMAT_SEL_8BIT },
-       { MEDIA_BUS_FMT_YUYV8_2X8, ADV7604_OP_CH_SEL_RGB, false, false,
-         ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
-       { MEDIA_BUS_FMT_YVYU8_2X8, ADV7604_OP_CH_SEL_RGB, false, true,
-         ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
-       { MEDIA_BUS_FMT_YUYV12_2X12, ADV7604_OP_CH_SEL_RGB, false, false,
-         ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
-       { MEDIA_BUS_FMT_YVYU12_2X12, ADV7604_OP_CH_SEL_RGB, false, true,
-         ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
-       { MEDIA_BUS_FMT_UYVY8_1X16, ADV7604_OP_CH_SEL_RBG, false, false,
-         ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
-       { MEDIA_BUS_FMT_VYUY8_1X16, ADV7604_OP_CH_SEL_RBG, false, true,
-         ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
-       { MEDIA_BUS_FMT_YUYV8_1X16, ADV7604_OP_CH_SEL_RGB, false, false,
-         ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
-       { MEDIA_BUS_FMT_YVYU8_1X16, ADV7604_OP_CH_SEL_RGB, false, true,
-         ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
-       { MEDIA_BUS_FMT_UYVY12_1X24, ADV7604_OP_CH_SEL_RBG, false, false,
-         ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
-       { MEDIA_BUS_FMT_VYUY12_1X24, ADV7604_OP_CH_SEL_RBG, false, true,
-         ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
-       { MEDIA_BUS_FMT_YUYV12_1X24, ADV7604_OP_CH_SEL_RGB, false, false,
-         ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
-       { MEDIA_BUS_FMT_YVYU12_1X24, ADV7604_OP_CH_SEL_RGB, false, true,
-         ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
+static const struct adv76xx_format_info adv7611_formats[] = {
+       { MEDIA_BUS_FMT_RGB888_1X24, ADV76XX_OP_CH_SEL_RGB, true, false,
+         ADV76XX_OP_MODE_SEL_SDR_444 | ADV76XX_OP_FORMAT_SEL_8BIT },
+       { MEDIA_BUS_FMT_YUYV8_2X8, ADV76XX_OP_CH_SEL_RGB, false, false,
+         ADV76XX_OP_MODE_SEL_SDR_422 | ADV76XX_OP_FORMAT_SEL_8BIT },
+       { MEDIA_BUS_FMT_YVYU8_2X8, ADV76XX_OP_CH_SEL_RGB, false, true,
+         ADV76XX_OP_MODE_SEL_SDR_422 | ADV76XX_OP_FORMAT_SEL_8BIT },
+       { MEDIA_BUS_FMT_YUYV12_2X12, ADV76XX_OP_CH_SEL_RGB, false, false,
+         ADV76XX_OP_MODE_SEL_SDR_422 | ADV76XX_OP_FORMAT_SEL_12BIT },
+       { MEDIA_BUS_FMT_YVYU12_2X12, ADV76XX_OP_CH_SEL_RGB, false, true,
+         ADV76XX_OP_MODE_SEL_SDR_422 | ADV76XX_OP_FORMAT_SEL_12BIT },
+       { MEDIA_BUS_FMT_UYVY8_1X16, ADV76XX_OP_CH_SEL_RBG, false, false,
+         ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_8BIT },
+       { MEDIA_BUS_FMT_VYUY8_1X16, ADV76XX_OP_CH_SEL_RBG, false, true,
+         ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_8BIT },
+       { MEDIA_BUS_FMT_YUYV8_1X16, ADV76XX_OP_CH_SEL_RGB, false, false,
+         ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_8BIT },
+       { MEDIA_BUS_FMT_YVYU8_1X16, ADV76XX_OP_CH_SEL_RGB, false, true,
+         ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_8BIT },
+       { MEDIA_BUS_FMT_UYVY12_1X24, ADV76XX_OP_CH_SEL_RBG, false, false,
+         ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_12BIT },
+       { MEDIA_BUS_FMT_VYUY12_1X24, ADV76XX_OP_CH_SEL_RBG, false, true,
+         ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_12BIT },
+       { MEDIA_BUS_FMT_YUYV12_1X24, ADV76XX_OP_CH_SEL_RGB, false, false,
+         ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_12BIT },
+       { MEDIA_BUS_FMT_YVYU12_1X24, ADV76XX_OP_CH_SEL_RGB, false, true,
+         ADV76XX_OP_MODE_SEL_SDR_422_2X | ADV76XX_OP_FORMAT_SEL_12BIT },
 };
 
-static const struct adv7604_format_info *
-adv7604_format_info(struct adv7604_state *state, u32 code)
+static const struct adv76xx_format_info *
+adv76xx_format_info(struct adv76xx_state *state, u32 code)
 {
        unsigned int i;
 
@@ -759,7 +756,7 @@ adv7604_format_info(struct adv7604_state *state, u32 code)
 
 static inline bool is_analog_input(struct v4l2_subdev *sd)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
        return state->selected_input == ADV7604_PAD_VGA_RGB ||
               state->selected_input == ADV7604_PAD_VGA_COMP;
@@ -767,9 +764,9 @@ static inline bool is_analog_input(struct v4l2_subdev *sd)
 
 static inline bool is_digital_input(struct v4l2_subdev *sd)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
-       return state->selected_input == ADV7604_PAD_HDMI_PORT_A ||
+       return state->selected_input == ADV76XX_PAD_HDMI_PORT_A ||
               state->selected_input == ADV7604_PAD_HDMI_PORT_B ||
               state->selected_input == ADV7604_PAD_HDMI_PORT_C ||
               state->selected_input == ADV7604_PAD_HDMI_PORT_D;
@@ -778,7 +775,7 @@ static inline bool is_digital_input(struct v4l2_subdev *sd)
 /* ----------------------------------------------------------------------- */
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-static void adv7604_inv_register(struct v4l2_subdev *sd)
+static void adv76xx_inv_register(struct v4l2_subdev *sd)
 {
        v4l2_info(sd, "0x000-0x0ff: IO Map\n");
        v4l2_info(sd, "0x100-0x1ff: AVLink Map\n");
@@ -795,15 +792,15 @@ static void adv7604_inv_register(struct v4l2_subdev *sd)
        v4l2_info(sd, "0xc00-0xcff: VDP Map\n");
 }
 
-static int adv7604_g_register(struct v4l2_subdev *sd,
+static int adv76xx_g_register(struct v4l2_subdev *sd,
                                        struct v4l2_dbg_register *reg)
 {
        int ret;
 
-       ret = adv7604_read_reg(sd, reg->reg);
+       ret = adv76xx_read_reg(sd, reg->reg);
        if (ret < 0) {
                v4l2_info(sd, "Register %03llx not supported\n", reg->reg);
-               adv7604_inv_register(sd);
+               adv76xx_inv_register(sd);
                return ret;
        }
 
@@ -813,15 +810,15 @@ static int adv7604_g_register(struct v4l2_subdev *sd,
        return 0;
 }
 
-static int adv7604_s_register(struct v4l2_subdev *sd,
+static int adv76xx_s_register(struct v4l2_subdev *sd,
                                        const struct v4l2_dbg_register *reg)
 {
        int ret;
 
-       ret = adv7604_write_reg(sd, reg->reg, reg->val);
+       ret = adv76xx_write_reg(sd, reg->reg, reg->val);
        if (ret < 0) {
                v4l2_info(sd, "Register %03llx not supported\n", reg->reg);
-               adv7604_inv_register(sd);
+               adv76xx_inv_register(sd);
                return ret;
        }
 
@@ -846,10 +843,10 @@ static unsigned int adv7611_read_cable_det(struct v4l2_subdev *sd)
        return value & 1;
 }
 
-static int adv7604_s_detect_tx_5v_ctrl(struct v4l2_subdev *sd)
+static int adv76xx_s_detect_tx_5v_ctrl(struct v4l2_subdev *sd)
 {
-       struct adv7604_state *state = to_state(sd);
-       const struct adv7604_chip_info *info = state->info;
+       struct adv76xx_state *state = to_state(sd);
+       const struct adv76xx_chip_info *info = state->info;
 
        return v4l2_ctrl_s_ctrl(state->detect_tx_5v_ctrl,
                                info->read_cable_det(sd));
@@ -857,7 +854,7 @@ static int adv7604_s_detect_tx_5v_ctrl(struct v4l2_subdev *sd)
 
 static int find_and_set_predefined_video_timings(struct v4l2_subdev *sd,
                u8 prim_mode,
-               const struct adv7604_video_standards *predef_vid_timings,
+               const struct adv76xx_video_standards *predef_vid_timings,
                const struct v4l2_dv_timings *timings)
 {
        int i;
@@ -878,12 +875,12 @@ static int find_and_set_predefined_video_timings(struct v4l2_subdev *sd,
 static int configure_predefined_video_timings(struct v4l2_subdev *sd,
                struct v4l2_dv_timings *timings)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
        int err;
 
        v4l2_dbg(1, debug, sd, "%s", __func__);
 
-       if (adv7604_has_afe(state)) {
+       if (adv76xx_has_afe(state)) {
                /* reset to default values */
                io_write(sd, 0x16, 0x43);
                io_write(sd, 0x17, 0x5a);
@@ -909,10 +906,10 @@ static int configure_predefined_video_timings(struct v4l2_subdev *sd,
                                        0x02, adv7604_prim_mode_gr, timings);
        } else if (is_digital_input(sd)) {
                err = find_and_set_predefined_video_timings(sd,
-                               0x05, adv7604_prim_mode_hdmi_comp, timings);
+                               0x05, adv76xx_prim_mode_hdmi_comp, timings);
                if (err)
                        err = find_and_set_predefined_video_timings(sd,
-                                       0x06, adv7604_prim_mode_hdmi_gr, timings);
+                                       0x06, adv76xx_prim_mode_hdmi_gr, timings);
        } else {
                v4l2_dbg(2, debug, sd, "%s: Unknown port %d selected\n",
                                __func__, state->selected_input);
@@ -926,7 +923,7 @@ static int configure_predefined_video_timings(struct v4l2_subdev *sd,
 static void configure_custom_video_timings(struct v4l2_subdev *sd,
                const struct v4l2_bt_timings *bt)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
        u32 width = htotal(bt);
        u32 height = vtotal(bt);
        u16 cp_start_sav = bt->hsync + bt->hbackporch - 4;
@@ -934,7 +931,7 @@ static void configure_custom_video_timings(struct v4l2_subdev *sd,
        u16 cp_start_vbi = height - bt->vfrontporch;
        u16 cp_end_vbi = bt->vsync + bt->vbackporch;
        u16 ch1_fr_ll = (((u32)bt->pixelclock / 100) > 0) ?
-               ((width * (ADV7604_fsc / 100)) / ((u32)bt->pixelclock / 100)) : 0;
+               ((width * (ADV76XX_FSC / 100)) / ((u32)bt->pixelclock / 100)) : 0;
        const u8 pll[2] = {
                0xc0 | ((width >> 8) & 0x1f),
                width & 0xff
@@ -952,7 +949,7 @@ static void configure_custom_video_timings(struct v4l2_subdev *sd,
                /* Should only be set in auto-graphics mode [REF_02, p. 91-92] */
                /* setup PLL_DIV_MAN_EN and PLL_DIV_RATIO */
                /* IO-map reg. 0x16 and 0x17 should be written in sequence */
-               if (adv_smbus_write_i2c_block_data(state, ADV7604_PAGE_IO,
+               if (adv_smbus_write_i2c_block_data(state, ADV76XX_PAGE_IO,
                                                   0x16, 2, pll))
                        v4l2_err(sd, "writing to reg 0x16 and 0x17 failed\n");
 
@@ -983,9 +980,9 @@ static void configure_custom_video_timings(struct v4l2_subdev *sd,
        cp_write(sd, 0xac, (height & 0x0f) << 4);
 }
 
-static void adv7604_set_offset(struct v4l2_subdev *sd, bool auto_offset, u16 offset_a, u16 offset_b, u16 offset_c)
+static void adv76xx_set_offset(struct v4l2_subdev *sd, bool auto_offset, u16 offset_a, u16 offset_b, u16 offset_c)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
        u8 offset_buf[4];
 
        if (auto_offset) {
@@ -1004,14 +1001,14 @@ static void adv7604_set_offset(struct v4l2_subdev *sd, bool auto_offset, u16 off
        offset_buf[3] = offset_c & 0x0ff;
 
        /* Registers must be written in this order with no i2c access in between */
-       if (adv_smbus_write_i2c_block_data(state, ADV7604_PAGE_CP,
+       if (adv_smbus_write_i2c_block_data(state, ADV76XX_PAGE_CP,
                                           0x77, 4, offset_buf))
                v4l2_err(sd, "%s: i2c error writing to CP reg 0x77, 0x78, 0x79, 0x7a\n", __func__);
 }
 
-static void adv7604_set_gain(struct v4l2_subdev *sd, bool auto_gain, u16 gain_a, u16 gain_b, u16 gain_c)
+static void adv76xx_set_gain(struct v4l2_subdev *sd, bool auto_gain, u16 gain_a, u16 gain_b, u16 gain_c)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
        u8 gain_buf[4];
        u8 gain_man = 1;
        u8 agc_mode_man = 1;
@@ -1034,14 +1031,14 @@ static void adv7604_set_gain(struct v4l2_subdev *sd, bool auto_gain, u16 gain_a,
        gain_buf[3] = ((gain_c & 0x0ff));
 
        /* Registers must be written in this order with no i2c access in between */
-       if (adv_smbus_write_i2c_block_data(state, ADV7604_PAGE_CP,
+       if (adv_smbus_write_i2c_block_data(state, ADV76XX_PAGE_CP,
                                           0x73, 4, gain_buf))
                v4l2_err(sd, "%s: i2c error writing to CP reg 0x73, 0x74, 0x75, 0x76\n", __func__);
 }
 
 static void set_rgb_quantization_range(struct v4l2_subdev *sd)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
        bool rgb_output = io_read(sd, 0x02) & 0x02;
        bool hdmi_signal = hdmi_read(sd, 0x05) & 0x80;
 
@@ -1049,8 +1046,8 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
                        __func__, state->rgb_quantization_range,
                        rgb_output, hdmi_signal);
 
-       adv7604_set_gain(sd, true, 0x0, 0x0, 0x0);
-       adv7604_set_offset(sd, true, 0x0, 0x0, 0x0);
+       adv76xx_set_gain(sd, true, 0x0, 0x0, 0x0);
+       adv76xx_set_offset(sd, true, 0x0, 0x0, 0x0);
 
        switch (state->rgb_quantization_range) {
        case V4L2_DV_RGB_RANGE_AUTO:
@@ -1078,7 +1075,7 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
                /* Receiving DVI-D signal
                 * ADV7604 selects RGB limited range regardless of
                 * input format (CE/IT) in automatic mode */
-               if (state->timings.bt.standards & V4L2_DV_BT_STD_CEA861) {
+               if (state->timings.bt.flags & V4L2_DV_FL_IS_CE_VIDEO) {
                        /* RGB limited range (16-235) */
                        io_write_clr_set(sd, 0x02, 0xf0, 0x00);
                } else {
@@ -1086,10 +1083,10 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
                        io_write_clr_set(sd, 0x02, 0xf0, 0x10);
 
                        if (is_digital_input(sd) && rgb_output) {
-                               adv7604_set_offset(sd, false, 0x40, 0x40, 0x40);
+                               adv76xx_set_offset(sd, false, 0x40, 0x40, 0x40);
                        } else {
-                               adv7604_set_gain(sd, false, 0xe0, 0xe0, 0xe0);
-                               adv7604_set_offset(sd, false, 0x70, 0x70, 0x70);
+                               adv76xx_set_gain(sd, false, 0xe0, 0xe0, 0xe0);
+                               adv76xx_set_offset(sd, false, 0x70, 0x70, 0x70);
                        }
                }
                break;
@@ -1119,21 +1116,21 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
 
                /* Adjust gain/offset for DVI-D signals only */
                if (rgb_output) {
-                       adv7604_set_offset(sd, false, 0x40, 0x40, 0x40);
+                       adv76xx_set_offset(sd, false, 0x40, 0x40, 0x40);
                } else {
-                       adv7604_set_gain(sd, false, 0xe0, 0xe0, 0xe0);
-                       adv7604_set_offset(sd, false, 0x70, 0x70, 0x70);
+                       adv76xx_set_gain(sd, false, 0xe0, 0xe0, 0xe0);
+                       adv76xx_set_offset(sd, false, 0x70, 0x70, 0x70);
                }
                break;
        }
 }
 
-static int adv7604_s_ctrl(struct v4l2_ctrl *ctrl)
+static int adv76xx_s_ctrl(struct v4l2_ctrl *ctrl)
 {
        struct v4l2_subdev *sd =
-               &container_of(ctrl->handler, struct adv7604_state, hdl)->sd;
+               &container_of(ctrl->handler, struct adv76xx_state, hdl)->sd;
 
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
        switch (ctrl->id) {
        case V4L2_CID_BRIGHTNESS:
@@ -1153,7 +1150,7 @@ static int adv7604_s_ctrl(struct v4l2_ctrl *ctrl)
                set_rgb_quantization_range(sd);
                return 0;
        case V4L2_CID_ADV_RX_ANALOG_SAMPLING_PHASE:
-               if (!adv7604_has_afe(state))
+               if (!adv76xx_has_afe(state))
                        return -EINVAL;
                /* Set the analog sampling phase. This is needed to find the
                   best sampling phase for analog video: an application or
@@ -1185,15 +1182,15 @@ static inline bool no_power(struct v4l2_subdev *sd)
 
 static inline bool no_signal_tmds(struct v4l2_subdev *sd)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
        return !(io_read(sd, 0x6a) & (0x10 >> state->selected_input));
 }
 
 static inline bool no_lock_tmds(struct v4l2_subdev *sd)
 {
-       struct adv7604_state *state = to_state(sd);
-       const struct adv7604_chip_info *info = state->info;
+       struct adv76xx_state *state = to_state(sd);
+       const struct adv76xx_chip_info *info = state->info;
 
        return (io_read(sd, 0x6a) & info->tdms_lock_mask) != info->tdms_lock_mask;
 }
@@ -1205,13 +1202,13 @@ static inline bool is_hdmi(struct v4l2_subdev *sd)
 
 static inline bool no_lock_sspd(struct v4l2_subdev *sd)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
        /*
         * Chips without a AFE don't expose registers for the SSPD, so just assume
         * that we have a lock.
         */
-       if (adv7604_has_afe(state))
+       if (adv76xx_has_afe(state))
                return false;
 
        /* TODO channel 2 */
@@ -1243,9 +1240,9 @@ static inline bool no_signal(struct v4l2_subdev *sd)
 
 static inline bool no_lock_cp(struct v4l2_subdev *sd)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
-       if (!adv7604_has_afe(state))
+       if (!adv76xx_has_afe(state))
                return false;
 
        /* CP has detected a non standard number of lines on the incoming
@@ -1253,13 +1250,19 @@ static inline bool no_lock_cp(struct v4l2_subdev *sd)
        return io_read(sd, 0x12) & 0x01;
 }
 
-static int adv7604_g_input_status(struct v4l2_subdev *sd, u32 *status)
+static inline bool in_free_run(struct v4l2_subdev *sd)
+{
+       return cp_read(sd, 0xff) & 0x10;
+}
+
+static int adv76xx_g_input_status(struct v4l2_subdev *sd, u32 *status)
 {
        *status = 0;
        *status |= no_power(sd) ? V4L2_IN_ST_NO_POWER : 0;
        *status |= no_signal(sd) ? V4L2_IN_ST_NO_SIGNAL : 0;
-       if (no_lock_cp(sd))
-               *status |= is_digital_input(sd) ? V4L2_IN_ST_NO_SYNC : V4L2_IN_ST_NO_H_LOCK;
+       if (!in_free_run(sd) && no_lock_cp(sd))
+               *status |= is_digital_input(sd) ?
+                          V4L2_IN_ST_NO_SYNC : V4L2_IN_ST_NO_H_LOCK;
 
        v4l2_dbg(1, debug, sd, "%s: status = 0x%x\n", __func__, *status);
 
@@ -1278,22 +1281,22 @@ static int stdi2dv_timings(struct v4l2_subdev *sd,
                struct stdi_readback *stdi,
                struct v4l2_dv_timings *timings)
 {
-       struct adv7604_state *state = to_state(sd);
-       u32 hfreq = (ADV7604_fsc * 8) / stdi->bl;
+       struct adv76xx_state *state = to_state(sd);
+       u32 hfreq = (ADV76XX_FSC * 8) / stdi->bl;
        u32 pix_clk;
        int i;
 
-       for (i = 0; adv7604_timings[i].bt.height; i++) {
-               if (vtotal(&adv7604_timings[i].bt) != stdi->lcf + 1)
+       for (i = 0; adv76xx_timings[i].bt.height; i++) {
+               if (vtotal(&adv76xx_timings[i].bt) != stdi->lcf + 1)
                        continue;
-               if (adv7604_timings[i].bt.vsync != stdi->lcvs)
+               if (adv76xx_timings[i].bt.vsync != stdi->lcvs)
                        continue;
 
-               pix_clk = hfreq * htotal(&adv7604_timings[i].bt);
+               pix_clk = hfreq * htotal(&adv76xx_timings[i].bt);
 
-               if ((pix_clk < adv7604_timings[i].bt.pixelclock + 1000000) &&
-                   (pix_clk > adv7604_timings[i].bt.pixelclock - 1000000)) {
-                       *timings = adv7604_timings[i];
+               if ((pix_clk < adv76xx_timings[i].bt.pixelclock + 1000000) &&
+                   (pix_clk > adv76xx_timings[i].bt.pixelclock - 1000000)) {
+                       *timings = adv76xx_timings[i];
                        return 0;
                }
        }
@@ -1319,8 +1322,8 @@ static int stdi2dv_timings(struct v4l2_subdev *sd,
 
 static int read_stdi(struct v4l2_subdev *sd, struct stdi_readback *stdi)
 {
-       struct adv7604_state *state = to_state(sd);
-       const struct adv7604_chip_info *info = state->info;
+       struct adv76xx_state *state = to_state(sd);
+       const struct adv76xx_chip_info *info = state->info;
        u8 polarity;
 
        if (no_lock_stdi(sd) || no_lock_sspd(sd)) {
@@ -1334,7 +1337,7 @@ static int read_stdi(struct v4l2_subdev *sd, struct stdi_readback *stdi)
        stdi->lcvs = cp_read(sd, 0xb3) >> 3;
        stdi->interlaced = io_read(sd, 0x12) & 0x10;
 
-       if (adv7604_has_afe(state)) {
+       if (adv76xx_has_afe(state)) {
                /* read SSPD */
                polarity = cp_read(sd, 0xb5);
                if ((polarity & 0x03) == 0x01) {
@@ -1373,26 +1376,26 @@ static int read_stdi(struct v4l2_subdev *sd, struct stdi_readback *stdi)
        return 0;
 }
 
-static int adv7604_enum_dv_timings(struct v4l2_subdev *sd,
+static int adv76xx_enum_dv_timings(struct v4l2_subdev *sd,
                        struct v4l2_enum_dv_timings *timings)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
-       if (timings->index >= ARRAY_SIZE(adv7604_timings) - 1)
+       if (timings->index >= ARRAY_SIZE(adv76xx_timings) - 1)
                return -EINVAL;
 
        if (timings->pad >= state->source_pad)
                return -EINVAL;
 
        memset(timings->reserved, 0, sizeof(timings->reserved));
-       timings->timings = adv7604_timings[timings->index];
+       timings->timings = adv76xx_timings[timings->index];
        return 0;
 }
 
-static int adv7604_dv_timings_cap(struct v4l2_subdev *sd,
+static int adv76xx_dv_timings_cap(struct v4l2_subdev *sd,
                        struct v4l2_dv_timings_cap *cap)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
        if (cap->pad >= state->source_pad)
                return -EINVAL;
@@ -1403,7 +1406,7 @@ static int adv7604_dv_timings_cap(struct v4l2_subdev *sd,
        cap->bt.min_pixelclock = 25000000;
 
        switch (cap->pad) {
-       case ADV7604_PAD_HDMI_PORT_A:
+       case ADV76XX_PAD_HDMI_PORT_A:
        case ADV7604_PAD_HDMI_PORT_B:
        case ADV7604_PAD_HDMI_PORT_C:
        case ADV7604_PAD_HDMI_PORT_D:
@@ -1424,16 +1427,16 @@ static int adv7604_dv_timings_cap(struct v4l2_subdev *sd,
 }
 
 /* Fill the optional fields .standards and .flags in struct v4l2_dv_timings
-   if the format is listed in adv7604_timings[] */
-static void adv7604_fill_optional_dv_timings_fields(struct v4l2_subdev *sd,
+   if the format is listed in adv76xx_timings[] */
+static void adv76xx_fill_optional_dv_timings_fields(struct v4l2_subdev *sd,
                struct v4l2_dv_timings *timings)
 {
        int i;
 
-       for (i = 0; adv7604_timings[i].bt.width; i++) {
-               if (v4l2_match_dv_timings(timings, &adv7604_timings[i],
+       for (i = 0; adv76xx_timings[i].bt.width; i++) {
+               if (v4l2_match_dv_timings(timings, &adv76xx_timings[i],
                                        is_digital_input(sd) ? 250000 : 1000000)) {
-                       *timings = adv7604_timings[i];
+                       *timings = adv76xx_timings[i];
                        break;
                }
        }
@@ -1471,11 +1474,11 @@ static unsigned int adv7611_read_hdmi_pixelclock(struct v4l2_subdev *sd)
        return ((a << 1) | (b >> 7)) * 1000000 + (b & 0x7f) * 1000000 / 128;
 }
 
-static int adv7604_query_dv_timings(struct v4l2_subdev *sd,
+static int adv76xx_query_dv_timings(struct v4l2_subdev *sd,
                        struct v4l2_dv_timings *timings)
 {
-       struct adv7604_state *state = to_state(sd);
-       const struct adv7604_chip_info *info = state->info;
+       struct adv76xx_state *state = to_state(sd);
+       const struct adv76xx_chip_info *info = state->info;
        struct v4l2_bt_timings *bt = &timings->bt;
        struct stdi_readback stdi;
 
@@ -1519,7 +1522,7 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd,
                        bt->il_vsync = hdmi_read16(sd, 0x30, 0x1fff) / 2;
                        bt->il_vbackporch = hdmi_read16(sd, 0x34, 0x1fff) / 2;
                }
-               adv7604_fill_optional_dv_timings_fields(sd, timings);
+               adv76xx_fill_optional_dv_timings_fields(sd, timings);
        } else {
                /* find format
                 * Since LCVS values are inaccurate [REF_03, p. 275-276],
@@ -1576,16 +1579,16 @@ found:
        }
 
        if (debug > 1)
-               v4l2_print_dv_timings(sd->name, "adv7604_query_dv_timings: ",
+               v4l2_print_dv_timings(sd->name, "adv76xx_query_dv_timings: ",
                                      timings, true);
 
        return 0;
 }
 
-static int adv7604_s_dv_timings(struct v4l2_subdev *sd,
+static int adv76xx_s_dv_timings(struct v4l2_subdev *sd,
                struct v4l2_dv_timings *timings)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
        struct v4l2_bt_timings *bt;
        int err;
 
@@ -1606,7 +1609,7 @@ static int adv7604_s_dv_timings(struct v4l2_subdev *sd,
                return -ERANGE;
        }
 
-       adv7604_fill_optional_dv_timings_fields(sd, timings);
+       adv76xx_fill_optional_dv_timings_fields(sd, timings);
 
        state->timings = *timings;
 
@@ -1623,15 +1626,15 @@ static int adv7604_s_dv_timings(struct v4l2_subdev *sd,
        set_rgb_quantization_range(sd);
 
        if (debug > 1)
-               v4l2_print_dv_timings(sd->name, "adv7604_s_dv_timings: ",
+               v4l2_print_dv_timings(sd->name, "adv76xx_s_dv_timings: ",
                                      timings, true);
        return 0;
 }
 
-static int adv7604_g_dv_timings(struct v4l2_subdev *sd,
+static int adv76xx_g_dv_timings(struct v4l2_subdev *sd,
                struct v4l2_dv_timings *timings)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
        *timings = state->timings;
        return 0;
@@ -1649,7 +1652,7 @@ static void adv7611_set_termination(struct v4l2_subdev *sd, bool enable)
 
 static void enable_input(struct v4l2_subdev *sd)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
        if (is_analog_input(sd)) {
                io_write(sd, 0x15, 0xb0);   /* Disable Tristate of Pins (no audio) */
@@ -1666,7 +1669,7 @@ static void enable_input(struct v4l2_subdev *sd)
 
 static void disable_input(struct v4l2_subdev *sd)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
        hdmi_write_clr_set(sd, 0x1a, 0x10, 0x10); /* Mute audio */
        msleep(16); /* 512 samples with >= 32 kHz sample rate [REF_03, c. 7.16.10] */
@@ -1676,11 +1679,11 @@ static void disable_input(struct v4l2_subdev *sd)
 
 static void select_input(struct v4l2_subdev *sd)
 {
-       struct adv7604_state *state = to_state(sd);
-       const struct adv7604_chip_info *info = state->info;
+       struct adv76xx_state *state = to_state(sd);
+       const struct adv76xx_chip_info *info = state->info;
 
        if (is_analog_input(sd)) {
-               adv7604_write_reg_seq(sd, info->recommended_settings[0]);
+               adv76xx_write_reg_seq(sd, info->recommended_settings[0]);
 
                afe_write(sd, 0x00, 0x08); /* power up ADC */
                afe_write(sd, 0x01, 0x06); /* power up Analog Front End */
@@ -1688,9 +1691,9 @@ static void select_input(struct v4l2_subdev *sd)
        } else if (is_digital_input(sd)) {
                hdmi_write(sd, 0x00, state->selected_input & 0x03);
 
-               adv7604_write_reg_seq(sd, info->recommended_settings[1]);
+               adv76xx_write_reg_seq(sd, info->recommended_settings[1]);
 
-               if (adv7604_has_afe(state)) {
+               if (adv76xx_has_afe(state)) {
                        afe_write(sd, 0x00, 0xff); /* power down ADC */
                        afe_write(sd, 0x01, 0xfe); /* power down Analog Front End */
                        afe_write(sd, 0xc8, 0x40); /* phase control */
@@ -1705,10 +1708,10 @@ static void select_input(struct v4l2_subdev *sd)
        }
 }
 
-static int adv7604_s_routing(struct v4l2_subdev *sd,
+static int adv76xx_s_routing(struct v4l2_subdev *sd,
                u32 input, u32 output, u32 config)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
        v4l2_dbg(2, debug, sd, "%s: input %d, selected input %d",
                        __func__, input, state->selected_input);
@@ -1730,11 +1733,11 @@ static int adv7604_s_routing(struct v4l2_subdev *sd,
        return 0;
 }
 
-static int adv7604_enum_mbus_code(struct v4l2_subdev *sd,
-                                 struct v4l2_subdev_fh *fh,
+static int adv76xx_enum_mbus_code(struct v4l2_subdev *sd,
+                                 struct v4l2_subdev_pad_config *cfg,
                                  struct v4l2_subdev_mbus_code_enum *code)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
        if (code->index >= state->info->nformats)
                return -EINVAL;
@@ -1744,7 +1747,7 @@ static int adv7604_enum_mbus_code(struct v4l2_subdev *sd,
        return 0;
 }
 
-static void adv7604_fill_format(struct adv7604_state *state,
+static void adv76xx_fill_format(struct adv76xx_state *state,
                                struct v4l2_mbus_framefmt *format)
 {
        memset(format, 0, sizeof(*format));
@@ -1752,8 +1755,9 @@ static void adv7604_fill_format(struct adv7604_state *state,
        format->width = state->timings.bt.width;
        format->height = state->timings.bt.height;
        format->field = V4L2_FIELD_NONE;
+       format->colorspace = V4L2_COLORSPACE_SRGB;
 
-       if (state->timings.bt.standards & V4L2_DV_BT_STD_CEA861)
+       if (state->timings.bt.flags & V4L2_DV_FL_IS_CE_VIDEO)
                format->colorspace = (state->timings.bt.height <= 576) ?
                        V4L2_COLORSPACE_SMPTE170M : V4L2_COLORSPACE_REC709;
 }
@@ -1765,7 +1769,7 @@ static void adv7604_fill_format(struct adv7604_state *state,
  *
  * The following table gives the op_ch_value from the format component order
  * (expressed as op_ch_sel value in column) and the bus reordering (expressed as
- * adv7604_bus_order value in row).
+ * adv76xx_bus_order value in row).
  *
  *           | GBR(0)  GRB(1)  BGR(2)  RGB(3)  BRG(4)  RBG(5)
  * ----------+-------------------------------------------------
@@ -1776,11 +1780,11 @@ static void adv7604_fill_format(struct adv7604_state *state,
  * BRG (ROR) | BRG     RBG     GRB     GBR     RGB     BGR
  * GBR (ROL) | RGB     BGR     RBG     BRG     GBR     GRB
  */
-static unsigned int adv7604_op_ch_sel(struct adv7604_state *state)
+static unsigned int adv76xx_op_ch_sel(struct adv76xx_state *state)
 {
 #define _SEL(a,b,c,d,e,f)      { \
-       ADV7604_OP_CH_SEL_##a, ADV7604_OP_CH_SEL_##b, ADV7604_OP_CH_SEL_##c, \
-       ADV7604_OP_CH_SEL_##d, ADV7604_OP_CH_SEL_##e, ADV7604_OP_CH_SEL_##f }
+       ADV76XX_OP_CH_SEL_##a, ADV76XX_OP_CH_SEL_##b, ADV76XX_OP_CH_SEL_##c, \
+       ADV76XX_OP_CH_SEL_##d, ADV76XX_OP_CH_SEL_##e, ADV76XX_OP_CH_SEL_##f }
 #define _BUS(x)                        [ADV7604_BUS_ORDER_##x]
 
        static const unsigned int op_ch_sel[6][6] = {
@@ -1795,33 +1799,34 @@ static unsigned int adv7604_op_ch_sel(struct adv7604_state *state)
        return op_ch_sel[state->pdata.bus_order][state->format->op_ch_sel >> 5];
 }
 
-static void adv7604_setup_format(struct adv7604_state *state)
+static void adv76xx_setup_format(struct adv76xx_state *state)
 {
        struct v4l2_subdev *sd = &state->sd;
 
        io_write_clr_set(sd, 0x02, 0x02,
-                       state->format->rgb_out ? ADV7604_RGB_OUT : 0);
+                       state->format->rgb_out ? ADV76XX_RGB_OUT : 0);
        io_write(sd, 0x03, state->format->op_format_sel |
                 state->pdata.op_format_mode_sel);
-       io_write_clr_set(sd, 0x04, 0xe0, adv7604_op_ch_sel(state));
+       io_write_clr_set(sd, 0x04, 0xe0, adv76xx_op_ch_sel(state));
        io_write_clr_set(sd, 0x05, 0x01,
-                       state->format->swap_cb_cr ? ADV7604_OP_SWAP_CB_CR : 0);
+                       state->format->swap_cb_cr ? ADV76XX_OP_SWAP_CB_CR : 0);
 }
 
-static int adv7604_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int adv76xx_get_format(struct v4l2_subdev *sd,
+                             struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_format *format)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
        if (format->pad != state->source_pad)
                return -EINVAL;
 
-       adv7604_fill_format(state, &format->format);
+       adv76xx_fill_format(state, &format->format);
 
        if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
                struct v4l2_mbus_framefmt *fmt;
 
-               fmt = v4l2_subdev_get_try_format(fh, format->pad);
+               fmt = v4l2_subdev_get_try_format(sd, cfg, format->pad);
                format->format.code = fmt->code;
        } else {
                format->format.code = state->format->code;
@@ -1830,39 +1835,40 @@ static int adv7604_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        return 0;
 }
 
-static int adv7604_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int adv76xx_set_format(struct v4l2_subdev *sd,
+                             struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_format *format)
 {
-       struct adv7604_state *state = to_state(sd);
-       const struct adv7604_format_info *info;
+       struct adv76xx_state *state = to_state(sd);
+       const struct adv76xx_format_info *info;
 
        if (format->pad != state->source_pad)
                return -EINVAL;
 
-       info = adv7604_format_info(state, format->format.code);
+       info = adv76xx_format_info(state, format->format.code);
        if (info == NULL)
-               info = adv7604_format_info(state, MEDIA_BUS_FMT_YUYV8_2X8);
+               info = adv76xx_format_info(state, MEDIA_BUS_FMT_YUYV8_2X8);
 
-       adv7604_fill_format(state, &format->format);
+       adv76xx_fill_format(state, &format->format);
        format->format.code = info->code;
 
        if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
                struct v4l2_mbus_framefmt *fmt;
 
-               fmt = v4l2_subdev_get_try_format(fh, format->pad);
+               fmt = v4l2_subdev_get_try_format(sd, cfg, format->pad);
                fmt->code = format->format.code;
        } else {
                state->format = info;
-               adv7604_setup_format(state);
+               adv76xx_setup_format(state);
        }
 
        return 0;
 }
 
-static int adv7604_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
+static int adv76xx_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
 {
-       struct adv7604_state *state = to_state(sd);
-       const struct adv7604_chip_info *info = state->info;
+       struct adv76xx_state *state = to_state(sd);
+       const struct adv76xx_chip_info *info = state->info;
        const u8 irq_reg_0x43 = io_read(sd, 0x43);
        const u8 irq_reg_0x6b = io_read(sd, 0x6b);
        const u8 irq_reg_0x70 = io_read(sd, 0x70);
@@ -1890,7 +1896,7 @@ static int adv7604_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
                        "%s: fmt_change = 0x%x, fmt_change_digital = 0x%x\n",
                        __func__, fmt_change, fmt_change_digital);
 
-               v4l2_subdev_notify(sd, ADV7604_FMT_CHANGE, NULL);
+               v4l2_subdev_notify(sd, ADV76XX_FMT_CHANGE, NULL);
 
                if (handled)
                        *handled = true;
@@ -1909,22 +1915,22 @@ static int adv7604_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
        if (tx_5v) {
                v4l2_dbg(1, debug, sd, "%s: tx_5v: 0x%x\n", __func__, tx_5v);
                io_write(sd, 0x71, tx_5v);
-               adv7604_s_detect_tx_5v_ctrl(sd);
+               adv76xx_s_detect_tx_5v_ctrl(sd);
                if (handled)
                        *handled = true;
        }
        return 0;
 }
 
-static int adv7604_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
+static int adv76xx_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
 {
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
        u8 *data = NULL;
 
        memset(edid->reserved, 0, sizeof(edid->reserved));
 
        switch (edid->pad) {
-       case ADV7604_PAD_HDMI_PORT_A:
+       case ADV76XX_PAD_HDMI_PORT_A:
        case ADV7604_PAD_HDMI_PORT_B:
        case ADV7604_PAD_HDMI_PORT_C:
        case ADV7604_PAD_HDMI_PORT_D:
@@ -1982,10 +1988,10 @@ static int get_edid_spa_location(const u8 *edid)
        return -1;
 }
 
-static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
+static int adv76xx_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
 {
-       struct adv7604_state *state = to_state(sd);
-       const struct adv7604_chip_info *info = state->info;
+       struct adv76xx_state *state = to_state(sd);
+       const struct adv76xx_chip_info *info = state->info;
        int spa_loc;
        int err;
        int i;
@@ -1999,7 +2005,7 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
        if (edid->blocks == 0) {
                /* Disable hotplug and I2C access to EDID RAM from DDC port */
                state->edid.present &= ~(1 << edid->pad);
-               adv7604_set_hpd(state, state->edid.present);
+               adv76xx_set_hpd(state, state->edid.present);
                rep_write_clr_set(sd, info->edid_enable_reg, 0x0f, state->edid.present);
 
                /* Fall back to a 16:9 aspect ratio */
@@ -2023,7 +2029,7 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
 
        /* Disable hotplug and I2C access to EDID RAM from DDC port */
        cancel_delayed_work_sync(&state->delayed_work_enable_hotplug);
-       adv7604_set_hpd(state, 0);
+       adv76xx_set_hpd(state, 0);
        rep_write_clr_set(sd, info->edid_enable_reg, 0x0f, 0x00);
 
        spa_loc = get_edid_spa_location(edid->edid);
@@ -2031,7 +2037,7 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
                spa_loc = 0xc0; /* Default value [REF_02, p. 116] */
 
        switch (edid->pad) {
-       case ADV7604_PAD_HDMI_PORT_A:
+       case ADV76XX_PAD_HDMI_PORT_A:
                state->spa_port_a[0] = edid->edid[spa_loc];
                state->spa_port_a[1] = edid->edid[spa_loc + 1];
                break;
@@ -2074,7 +2080,7 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
                return err;
        }
 
-       /* adv7604 calculates the checksums and enables I2C access to internal
+       /* adv76xx calculates the checksums and enables I2C access to internal
           EDID RAM from DDC port. */
        rep_write_clr_set(sd, info->edid_enable_reg, 0x0f, state->edid.present);
 
@@ -2138,10 +2144,10 @@ static void print_avi_infoframe(struct v4l2_subdev *sd)
                buf[8], buf[9], buf[10], buf[11], buf[12], buf[13]);
 }
 
-static int adv7604_log_status(struct v4l2_subdev *sd)
+static int adv76xx_log_status(struct v4l2_subdev *sd)
 {
-       struct adv7604_state *state = to_state(sd);
-       const struct adv7604_chip_info *info = state->info;
+       struct adv76xx_state *state = to_state(sd);
+       const struct adv76xx_chip_info *info = state->info;
        struct v4l2_dv_timings timings;
        struct stdi_readback stdi;
        u8 reg_io_0x02 = io_read(sd, 0x02);
@@ -2200,7 +2206,7 @@ static int adv7604_log_status(struct v4l2_subdev *sd)
        v4l2_info(sd, "STDI locked: %s\n", no_lock_stdi(sd) ? "false" : "true");
        v4l2_info(sd, "CP locked: %s\n", no_lock_cp(sd) ? "false" : "true");
        v4l2_info(sd, "CP free run: %s\n",
-                       (!!(cp_read(sd, 0xff) & 0x10) ? "on" : "off"));
+                       (in_free_run(sd)) ? "on" : "off");
        v4l2_info(sd, "Prim-mode = 0x%x, video std = 0x%x, v_freq = 0x%x\n",
                        io_read(sd, 0x01) & 0x0f, io_read(sd, 0x00) & 0x3f,
                        (io_read(sd, 0x01) & 0x70) >> 4);
@@ -2213,7 +2219,7 @@ static int adv7604_log_status(struct v4l2_subdev *sd)
                                stdi.lcf, stdi.bl, stdi.lcvs,
                                stdi.interlaced ? "interlaced" : "progressive",
                                stdi.hs_pol, stdi.vs_pol);
-       if (adv7604_query_dv_timings(sd, &timings))
+       if (adv76xx_query_dv_timings(sd, &timings))
                v4l2_info(sd, "No video detected\n");
        else
                v4l2_print_dv_timings(sd->name, "Detected format: ",
@@ -2235,7 +2241,7 @@ static int adv7604_log_status(struct v4l2_subdev *sd)
                        ((reg_io_0x02 & 0x04) ^ (reg_io_0x02 & 0x01)) ?
                                "enabled" : "disabled");
        v4l2_info(sd, "Color space conversion: %s\n",
-                       csc_coeff_sel_rb[cp_read(sd, 0xfc) >> 4]);
+                       csc_coeff_sel_rb[cp_read(sd, info->cp_csc) >> 4]);
 
        if (!is_digital_input(sd))
                return 0;
@@ -2279,47 +2285,47 @@ static int adv7604_log_status(struct v4l2_subdev *sd)
 
 /* ----------------------------------------------------------------------- */
 
-static const struct v4l2_ctrl_ops adv7604_ctrl_ops = {
-       .s_ctrl = adv7604_s_ctrl,
+static const struct v4l2_ctrl_ops adv76xx_ctrl_ops = {
+       .s_ctrl = adv76xx_s_ctrl,
 };
 
-static const struct v4l2_subdev_core_ops adv7604_core_ops = {
-       .log_status = adv7604_log_status,
-       .interrupt_service_routine = adv7604_isr,
+static const struct v4l2_subdev_core_ops adv76xx_core_ops = {
+       .log_status = adv76xx_log_status,
+       .interrupt_service_routine = adv76xx_isr,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-       .g_register = adv7604_g_register,
-       .s_register = adv7604_s_register,
+       .g_register = adv76xx_g_register,
+       .s_register = adv76xx_s_register,
 #endif
 };
 
-static const struct v4l2_subdev_video_ops adv7604_video_ops = {
-       .s_routing = adv7604_s_routing,
-       .g_input_status = adv7604_g_input_status,
-       .s_dv_timings = adv7604_s_dv_timings,
-       .g_dv_timings = adv7604_g_dv_timings,
-       .query_dv_timings = adv7604_query_dv_timings,
+static const struct v4l2_subdev_video_ops adv76xx_video_ops = {
+       .s_routing = adv76xx_s_routing,
+       .g_input_status = adv76xx_g_input_status,
+       .s_dv_timings = adv76xx_s_dv_timings,
+       .g_dv_timings = adv76xx_g_dv_timings,
+       .query_dv_timings = adv76xx_query_dv_timings,
 };
 
-static const struct v4l2_subdev_pad_ops adv7604_pad_ops = {
-       .enum_mbus_code = adv7604_enum_mbus_code,
-       .get_fmt = adv7604_get_format,
-       .set_fmt = adv7604_set_format,
-       .get_edid = adv7604_get_edid,
-       .set_edid = adv7604_set_edid,
-       .dv_timings_cap = adv7604_dv_timings_cap,
-       .enum_dv_timings = adv7604_enum_dv_timings,
+static const struct v4l2_subdev_pad_ops adv76xx_pad_ops = {
+       .enum_mbus_code = adv76xx_enum_mbus_code,
+       .get_fmt = adv76xx_get_format,
+       .set_fmt = adv76xx_set_format,
+       .get_edid = adv76xx_get_edid,
+       .set_edid = adv76xx_set_edid,
+       .dv_timings_cap = adv76xx_dv_timings_cap,
+       .enum_dv_timings = adv76xx_enum_dv_timings,
 };
 
-static const struct v4l2_subdev_ops adv7604_ops = {
-       .core = &adv7604_core_ops,
-       .video = &adv7604_video_ops,
-       .pad = &adv7604_pad_ops,
+static const struct v4l2_subdev_ops adv76xx_ops = {
+       .core = &adv76xx_core_ops,
+       .video = &adv76xx_video_ops,
+       .pad = &adv76xx_pad_ops,
 };
 
 /* -------------------------- custom ctrls ---------------------------------- */
 
 static const struct v4l2_ctrl_config adv7604_ctrl_analog_sampling_phase = {
-       .ops = &adv7604_ctrl_ops,
+       .ops = &adv76xx_ctrl_ops,
        .id = V4L2_CID_ADV_RX_ANALOG_SAMPLING_PHASE,
        .name = "Analog Sampling Phase",
        .type = V4L2_CTRL_TYPE_INTEGER,
@@ -2329,8 +2335,8 @@ static const struct v4l2_ctrl_config adv7604_ctrl_analog_sampling_phase = {
        .def = 0,
 };
 
-static const struct v4l2_ctrl_config adv7604_ctrl_free_run_color_manual = {
-       .ops = &adv7604_ctrl_ops,
+static const struct v4l2_ctrl_config adv76xx_ctrl_free_run_color_manual = {
+       .ops = &adv76xx_ctrl_ops,
        .id = V4L2_CID_ADV_RX_FREE_RUN_COLOR_MANUAL,
        .name = "Free Running Color, Manual",
        .type = V4L2_CTRL_TYPE_BOOLEAN,
@@ -2340,8 +2346,8 @@ static const struct v4l2_ctrl_config adv7604_ctrl_free_run_color_manual = {
        .def = false,
 };
 
-static const struct v4l2_ctrl_config adv7604_ctrl_free_run_color = {
-       .ops = &adv7604_ctrl_ops,
+static const struct v4l2_ctrl_config adv76xx_ctrl_free_run_color = {
+       .ops = &adv76xx_ctrl_ops,
        .id = V4L2_CID_ADV_RX_FREE_RUN_COLOR,
        .name = "Free Running Color",
        .type = V4L2_CTRL_TYPE_INTEGER,
@@ -2353,11 +2359,11 @@ static const struct v4l2_ctrl_config adv7604_ctrl_free_run_color = {
 
 /* ----------------------------------------------------------------------- */
 
-static int adv7604_core_init(struct v4l2_subdev *sd)
+static int adv76xx_core_init(struct v4l2_subdev *sd)
 {
-       struct adv7604_state *state = to_state(sd);
-       const struct adv7604_chip_info *info = state->info;
-       struct adv7604_platform_data *pdata = &state->pdata;
+       struct adv76xx_state *state = to_state(sd);
+       const struct adv76xx_chip_info *info = state->info;
+       struct adv76xx_platform_data *pdata = &state->pdata;
 
        hdmi_write(sd, 0x48,
                (pdata->disable_pwrdnb ? 0x80 : 0) |
@@ -2385,7 +2391,7 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
        io_write_clr_set(sd, 0x05, 0x0e, pdata->blank_data << 3 |
                        pdata->insert_av_codes << 2 |
                        pdata->replicate_av_codes << 1);
-       adv7604_setup_format(state);
+       adv76xx_setup_format(state);
 
        cp_write(sd, 0x69, 0x30);   /* Enable CP CSC */
 
@@ -2415,7 +2421,7 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
        /* TODO from platform data */
        afe_write(sd, 0xb5, 0x01);  /* Setting MCLK to 256Fs */
 
-       if (adv7604_has_afe(state)) {
+       if (adv76xx_has_afe(state)) {
                afe_write(sd, 0x02, pdata->ain_sel); /* Select analog input muxing mode */
                io_write_clr_set(sd, 0x30, 1 << 4, pdata->output_bus_lsb_to_msb << 4);
        }
@@ -2440,7 +2446,7 @@ static void adv7611_setup_irqs(struct v4l2_subdev *sd)
        io_write(sd, 0x41, 0xd0); /* STDI irq for any change, disable INT2 */
 }
 
-static void adv7604_unregister_clients(struct adv7604_state *state)
+static void adv76xx_unregister_clients(struct adv76xx_state *state)
 {
        unsigned int i;
 
@@ -2450,7 +2456,7 @@ static void adv7604_unregister_clients(struct adv7604_state *state)
        }
 }
 
-static struct i2c_client *adv7604_dummy_client(struct v4l2_subdev *sd,
+static struct i2c_client *adv76xx_dummy_client(struct v4l2_subdev *sd,
                                                        u8 addr, u8 io_reg)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -2460,74 +2466,74 @@ static struct i2c_client *adv7604_dummy_client(struct v4l2_subdev *sd,
        return i2c_new_dummy(client->adapter, io_read(sd, io_reg) >> 1);
 }
 
-static const struct adv7604_reg_seq adv7604_recommended_settings_afe[] = {
+static const struct adv76xx_reg_seq adv7604_recommended_settings_afe[] = {
        /* reset ADI recommended settings for HDMI: */
        /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x0d), 0x04 }, /* HDMI filter optimization */
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x0d), 0x04 }, /* HDMI filter optimization */
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x3d), 0x00 }, /* DDC bus active pull-up control */
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x3e), 0x74 }, /* TMDS PLL optimization */
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x4e), 0x3b }, /* TMDS PLL optimization */
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x57), 0x74 }, /* TMDS PLL optimization */
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x58), 0x63 }, /* TMDS PLL optimization */
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x8d), 0x18 }, /* equaliser */
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x8e), 0x34 }, /* equaliser */
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x93), 0x88 }, /* equaliser */
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x94), 0x2e }, /* equaliser */
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x96), 0x00 }, /* enable automatic EQ changing */
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x0d), 0x04 }, /* HDMI filter optimization */
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x0d), 0x04 }, /* HDMI filter optimization */
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x3d), 0x00 }, /* DDC bus active pull-up control */
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x3e), 0x74 }, /* TMDS PLL optimization */
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x4e), 0x3b }, /* TMDS PLL optimization */
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x57), 0x74 }, /* TMDS PLL optimization */
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x58), 0x63 }, /* TMDS PLL optimization */
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x8d), 0x18 }, /* equaliser */
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x8e), 0x34 }, /* equaliser */
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x93), 0x88 }, /* equaliser */
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x94), 0x2e }, /* equaliser */
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x96), 0x00 }, /* enable automatic EQ changing */
 
        /* set ADI recommended settings for digitizer */
        /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 17. */
-       { ADV7604_REG(ADV7604_PAGE_AFE, 0x12), 0x7b }, /* ADC noise shaping filter controls */
-       { ADV7604_REG(ADV7604_PAGE_AFE, 0x0c), 0x1f }, /* CP core gain controls */
-       { ADV7604_REG(ADV7604_PAGE_CP, 0x3e), 0x04 }, /* CP core pre-gain control */
-       { ADV7604_REG(ADV7604_PAGE_CP, 0xc3), 0x39 }, /* CP coast control. Graphics mode */
-       { ADV7604_REG(ADV7604_PAGE_CP, 0x40), 0x5c }, /* CP core pre-gain control. Graphics mode */
+       { ADV76XX_REG(ADV76XX_PAGE_AFE, 0x12), 0x7b }, /* ADC noise shaping filter controls */
+       { ADV76XX_REG(ADV76XX_PAGE_AFE, 0x0c), 0x1f }, /* CP core gain controls */
+       { ADV76XX_REG(ADV76XX_PAGE_CP, 0x3e), 0x04 }, /* CP core pre-gain control */
+       { ADV76XX_REG(ADV76XX_PAGE_CP, 0xc3), 0x39 }, /* CP coast control. Graphics mode */
+       { ADV76XX_REG(ADV76XX_PAGE_CP, 0x40), 0x5c }, /* CP core pre-gain control. Graphics mode */
 
-       { ADV7604_REG_SEQ_TERM, 0 },
+       { ADV76XX_REG_SEQ_TERM, 0 },
 };
 
-static const struct adv7604_reg_seq adv7604_recommended_settings_hdmi[] = {
+static const struct adv76xx_reg_seq adv7604_recommended_settings_hdmi[] = {
        /* set ADI recommended settings for HDMI: */
        /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x0d), 0x84 }, /* HDMI filter optimization */
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x3d), 0x10 }, /* DDC bus active pull-up control */
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x3e), 0x39 }, /* TMDS PLL optimization */
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x4e), 0x3b }, /* TMDS PLL optimization */
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x57), 0xb6 }, /* TMDS PLL optimization */
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x58), 0x03 }, /* TMDS PLL optimization */
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x8d), 0x18 }, /* equaliser */
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x8e), 0x34 }, /* equaliser */
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x93), 0x8b }, /* equaliser */
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x94), 0x2d }, /* equaliser */
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x96), 0x01 }, /* enable automatic EQ changing */
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x0d), 0x84 }, /* HDMI filter optimization */
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x3d), 0x10 }, /* DDC bus active pull-up control */
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x3e), 0x39 }, /* TMDS PLL optimization */
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x4e), 0x3b }, /* TMDS PLL optimization */
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x57), 0xb6 }, /* TMDS PLL optimization */
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x58), 0x03 }, /* TMDS PLL optimization */
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x8d), 0x18 }, /* equaliser */
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x8e), 0x34 }, /* equaliser */
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x93), 0x8b }, /* equaliser */
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x94), 0x2d }, /* equaliser */
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x96), 0x01 }, /* enable automatic EQ changing */
 
        /* reset ADI recommended settings for digitizer */
        /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 17. */
-       { ADV7604_REG(ADV7604_PAGE_AFE, 0x12), 0xfb }, /* ADC noise shaping filter controls */
-       { ADV7604_REG(ADV7604_PAGE_AFE, 0x0c), 0x0d }, /* CP core gain controls */
+       { ADV76XX_REG(ADV76XX_PAGE_AFE, 0x12), 0xfb }, /* ADC noise shaping filter controls */
+       { ADV76XX_REG(ADV76XX_PAGE_AFE, 0x0c), 0x0d }, /* CP core gain controls */
 
-       { ADV7604_REG_SEQ_TERM, 0 },
+       { ADV76XX_REG_SEQ_TERM, 0 },
 };
 
-static const struct adv7604_reg_seq adv7611_recommended_settings_hdmi[] = {
+static const struct adv76xx_reg_seq adv7611_recommended_settings_hdmi[] = {
        /* ADV7611 Register Settings Recommendations Rev 1.5, May 2014 */
-       { ADV7604_REG(ADV7604_PAGE_CP, 0x6c), 0x00 },
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x9b), 0x03 },
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x6f), 0x08 },
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x85), 0x1f },
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x87), 0x70 },
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x57), 0xda },
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x58), 0x01 },
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x03), 0x98 },
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x4c), 0x44 },
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x8d), 0x04 },
-       { ADV7604_REG(ADV7604_PAGE_HDMI, 0x8e), 0x1e },
-
-       { ADV7604_REG_SEQ_TERM, 0 },
+       { ADV76XX_REG(ADV76XX_PAGE_CP, 0x6c), 0x00 },
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x9b), 0x03 },
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x6f), 0x08 },
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x85), 0x1f },
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x87), 0x70 },
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x57), 0xda },
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x58), 0x01 },
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x03), 0x98 },
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x4c), 0x44 },
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x8d), 0x04 },
+       { ADV76XX_REG(ADV76XX_PAGE_HDMI, 0x8e), 0x1e },
+
+       { ADV76XX_REG_SEQ_TERM, 0 },
 };
 
-static const struct adv7604_chip_info adv7604_chip_info[] = {
+static const struct adv76xx_chip_info adv76xx_chip_info[] = {
        [ADV7604] = {
                .type = ADV7604,
                .has_afe = true,
@@ -2539,6 +2545,7 @@ static const struct adv7604_chip_info adv7604_chip_info[] = {
                .tdms_lock_mask = 0xe0,
                .cable_det_mask = 0x1e,
                .fmt_change_digital_mask = 0xc1,
+               .cp_csc = 0xfc,
                .formats = adv7604_formats,
                .nformats = ARRAY_SIZE(adv7604_formats),
                .set_termination = adv7604_set_termination,
@@ -2553,18 +2560,18 @@ static const struct adv7604_chip_info adv7604_chip_info[] = {
                    [0] = ARRAY_SIZE(adv7604_recommended_settings_afe),
                    [1] = ARRAY_SIZE(adv7604_recommended_settings_hdmi),
                },
-               .page_mask = BIT(ADV7604_PAGE_IO) | BIT(ADV7604_PAGE_AVLINK) |
-                       BIT(ADV7604_PAGE_CEC) | BIT(ADV7604_PAGE_INFOFRAME) |
+               .page_mask = BIT(ADV76XX_PAGE_IO) | BIT(ADV7604_PAGE_AVLINK) |
+                       BIT(ADV76XX_PAGE_CEC) | BIT(ADV76XX_PAGE_INFOFRAME) |
                        BIT(ADV7604_PAGE_ESDP) | BIT(ADV7604_PAGE_DPP) |
-                       BIT(ADV7604_PAGE_AFE) | BIT(ADV7604_PAGE_REP) |
-                       BIT(ADV7604_PAGE_EDID) | BIT(ADV7604_PAGE_HDMI) |
-                       BIT(ADV7604_PAGE_TEST) | BIT(ADV7604_PAGE_CP) |
+                       BIT(ADV76XX_PAGE_AFE) | BIT(ADV76XX_PAGE_REP) |
+                       BIT(ADV76XX_PAGE_EDID) | BIT(ADV76XX_PAGE_HDMI) |
+                       BIT(ADV76XX_PAGE_TEST) | BIT(ADV76XX_PAGE_CP) |
                        BIT(ADV7604_PAGE_VDP),
        },
        [ADV7611] = {
                .type = ADV7611,
                .has_afe = false,
-               .max_port = ADV7604_PAD_HDMI_PORT_A,
+               .max_port = ADV76XX_PAD_HDMI_PORT_A,
                .num_dv_ports = 1,
                .edid_enable_reg = 0x74,
                .edid_status_reg = 0x76,
@@ -2572,6 +2579,7 @@ static const struct adv7604_chip_info adv7604_chip_info[] = {
                .tdms_lock_mask = 0x43,
                .cable_det_mask = 0x01,
                .fmt_change_digital_mask = 0x03,
+               .cp_csc = 0xf4,
                .formats = adv7611_formats,
                .nformats = ARRAY_SIZE(adv7611_formats),
                .set_termination = adv7611_set_termination,
@@ -2584,34 +2592,34 @@ static const struct adv7604_chip_info adv7604_chip_info[] = {
                .num_recommended_settings = {
                    [1] = ARRAY_SIZE(adv7611_recommended_settings_hdmi),
                },
-               .page_mask = BIT(ADV7604_PAGE_IO) | BIT(ADV7604_PAGE_CEC) |
-                       BIT(ADV7604_PAGE_INFOFRAME) | BIT(ADV7604_PAGE_AFE) |
-                       BIT(ADV7604_PAGE_REP) |  BIT(ADV7604_PAGE_EDID) |
-                       BIT(ADV7604_PAGE_HDMI) | BIT(ADV7604_PAGE_CP),
+               .page_mask = BIT(ADV76XX_PAGE_IO) | BIT(ADV76XX_PAGE_CEC) |
+                       BIT(ADV76XX_PAGE_INFOFRAME) | BIT(ADV76XX_PAGE_AFE) |
+                       BIT(ADV76XX_PAGE_REP) |  BIT(ADV76XX_PAGE_EDID) |
+                       BIT(ADV76XX_PAGE_HDMI) | BIT(ADV76XX_PAGE_CP),
        },
 };
 
-static struct i2c_device_id adv7604_i2c_id[] = {
-       { "adv7604", (kernel_ulong_t)&adv7604_chip_info[ADV7604] },
-       { "adv7611", (kernel_ulong_t)&adv7604_chip_info[ADV7611] },
+static struct i2c_device_id adv76xx_i2c_id[] = {
+       { "adv7604", (kernel_ulong_t)&adv76xx_chip_info[ADV7604] },
+       { "adv7611", (kernel_ulong_t)&adv76xx_chip_info[ADV7611] },
        { }
 };
-MODULE_DEVICE_TABLE(i2c, adv7604_i2c_id);
+MODULE_DEVICE_TABLE(i2c, adv76xx_i2c_id);
 
-static struct of_device_id adv7604_of_id[] __maybe_unused = {
-       { .compatible = "adi,adv7611", .data = &adv7604_chip_info[ADV7611] },
+static struct of_device_id adv76xx_of_id[] __maybe_unused = {
+       { .compatible = "adi,adv7611", .data = &adv76xx_chip_info[ADV7611] },
        { }
 };
-MODULE_DEVICE_TABLE(of, adv7604_of_id);
+MODULE_DEVICE_TABLE(of, adv76xx_of_id);
 
-static int adv7604_parse_dt(struct adv7604_state *state)
+static int adv76xx_parse_dt(struct adv76xx_state *state)
 {
        struct v4l2_of_endpoint bus_cfg;
        struct device_node *endpoint;
        struct device_node *np;
        unsigned int flags;
 
-       np = state->i2c_clients[ADV7604_PAGE_IO]->dev.of_node;
+       np = state->i2c_clients[ADV76XX_PAGE_IO]->dev.of_node;
 
        /* Parse the endpoint. */
        endpoint = of_graph_get_next_endpoint(np, NULL);
@@ -2638,20 +2646,20 @@ static int adv7604_parse_dt(struct adv7604_state *state)
        }
 
        /* Disable the interrupt for now as no DT-based board uses it. */
-       state->pdata.int1_config = ADV7604_INT1_CONFIG_DISABLED;
+       state->pdata.int1_config = ADV76XX_INT1_CONFIG_DISABLED;
 
        /* Use the default I2C addresses. */
        state->pdata.i2c_addresses[ADV7604_PAGE_AVLINK] = 0x42;
-       state->pdata.i2c_addresses[ADV7604_PAGE_CEC] = 0x40;
-       state->pdata.i2c_addresses[ADV7604_PAGE_INFOFRAME] = 0x3e;
+       state->pdata.i2c_addresses[ADV76XX_PAGE_CEC] = 0x40;
+       state->pdata.i2c_addresses[ADV76XX_PAGE_INFOFRAME] = 0x3e;
        state->pdata.i2c_addresses[ADV7604_PAGE_ESDP] = 0x38;
        state->pdata.i2c_addresses[ADV7604_PAGE_DPP] = 0x3c;
-       state->pdata.i2c_addresses[ADV7604_PAGE_AFE] = 0x26;
-       state->pdata.i2c_addresses[ADV7604_PAGE_REP] = 0x32;
-       state->pdata.i2c_addresses[ADV7604_PAGE_EDID] = 0x36;
-       state->pdata.i2c_addresses[ADV7604_PAGE_HDMI] = 0x34;
-       state->pdata.i2c_addresses[ADV7604_PAGE_TEST] = 0x30;
-       state->pdata.i2c_addresses[ADV7604_PAGE_CP] = 0x22;
+       state->pdata.i2c_addresses[ADV76XX_PAGE_AFE] = 0x26;
+       state->pdata.i2c_addresses[ADV76XX_PAGE_REP] = 0x32;
+       state->pdata.i2c_addresses[ADV76XX_PAGE_EDID] = 0x36;
+       state->pdata.i2c_addresses[ADV76XX_PAGE_HDMI] = 0x34;
+       state->pdata.i2c_addresses[ADV76XX_PAGE_TEST] = 0x30;
+       state->pdata.i2c_addresses[ADV76XX_PAGE_CP] = 0x22;
        state->pdata.i2c_addresses[ADV7604_PAGE_VDP] = 0x24;
 
        /* Hardcode the remaining platform data fields. */
@@ -2666,12 +2674,12 @@ static int adv7604_parse_dt(struct adv7604_state *state)
        return 0;
 }
 
-static int adv7604_probe(struct i2c_client *client,
+static int adv76xx_probe(struct i2c_client *client,
                         const struct i2c_device_id *id)
 {
        static const struct v4l2_dv_timings cea640x480 =
                V4L2_DV_BT_CEA_640X480P59_94;
-       struct adv7604_state *state;
+       struct adv76xx_state *state;
        struct v4l2_ctrl_handler *hdl;
        struct v4l2_subdev *sd;
        unsigned int i;
@@ -2681,16 +2689,16 @@ static int adv7604_probe(struct i2c_client *client,
        /* Check if the adapter supports the needed features */
        if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
                return -EIO;
-       v4l_dbg(1, debug, client, "detecting adv7604 client on address 0x%x\n",
+       v4l_dbg(1, debug, client, "detecting adv76xx client on address 0x%x\n",
                        client->addr << 1);
 
        state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
        if (!state) {
-               v4l_err(client, "Could not allocate adv7604_state memory!\n");
+               v4l_err(client, "Could not allocate adv76xx_state memory!\n");
                return -ENOMEM;
        }
 
-       state->i2c_clients[ADV7604_PAGE_IO] = client;
+       state->i2c_clients[ADV76XX_PAGE_IO] = client;
 
        /* initialize variables */
        state->restart_stdi_once = true;
@@ -2699,18 +2707,18 @@ static int adv7604_probe(struct i2c_client *client,
        if (IS_ENABLED(CONFIG_OF) && client->dev.of_node) {
                const struct of_device_id *oid;
 
-               oid = of_match_node(adv7604_of_id, client->dev.of_node);
+               oid = of_match_node(adv76xx_of_id, client->dev.of_node);
                state->info = oid->data;
 
-               err = adv7604_parse_dt(state);
+               err = adv76xx_parse_dt(state);
                if (err < 0) {
                        v4l_err(client, "DT parsing error\n");
                        return err;
                }
        } else if (client->dev.platform_data) {
-               struct adv7604_platform_data *pdata = client->dev.platform_data;
+               struct adv76xx_platform_data *pdata = client->dev.platform_data;
 
-               state->info = (const struct adv7604_chip_info *)id->driver_data;
+               state->info = (const struct adv76xx_chip_info *)id->driver_data;
                state->pdata = *pdata;
        } else {
                v4l_err(client, "No platform data!\n");
@@ -2720,20 +2728,20 @@ static int adv7604_probe(struct i2c_client *client,
        /* Request GPIOs. */
        for (i = 0; i < state->info->num_dv_ports; ++i) {
                state->hpd_gpio[i] =
-                       devm_gpiod_get_index(&client->dev, "hpd", i);
+                       devm_gpiod_get_index_optional(&client->dev, "hpd", i,
+                                                     GPIOD_OUT_LOW);
                if (IS_ERR(state->hpd_gpio[i]))
-                       continue;
-
-               gpiod_direction_output(state->hpd_gpio[i], 0);
+                       return PTR_ERR(state->hpd_gpio[i]);
 
-               v4l_info(client, "Handling HPD %u GPIO\n", i);
+               if (state->hpd_gpio[i])
+                       v4l_info(client, "Handling HPD %u GPIO\n", i);
        }
 
        state->timings = cea640x480;
-       state->format = adv7604_format_info(state, MEDIA_BUS_FMT_YUYV8_2X8);
+       state->format = adv76xx_format_info(state, MEDIA_BUS_FMT_YUYV8_2X8);
 
        sd = &state->sd;
-       v4l2_i2c_subdev_init(sd, client, &adv7604_ops);
+       v4l2_i2c_subdev_init(sd, client, &adv76xx_ops);
        snprintf(sd->name, sizeof(sd->name), "%s %d-%04x",
                id->name, i2c_adapter_id(client->adapter),
                client->addr);
@@ -2763,15 +2771,15 @@ static int adv7604_probe(struct i2c_client *client,
 
        /* control handlers */
        hdl = &state->hdl;
-       v4l2_ctrl_handler_init(hdl, adv7604_has_afe(state) ? 9 : 8);
+       v4l2_ctrl_handler_init(hdl, adv76xx_has_afe(state) ? 9 : 8);
 
-       v4l2_ctrl_new_std(hdl, &adv7604_ctrl_ops,
+       v4l2_ctrl_new_std(hdl, &adv76xx_ctrl_ops,
                        V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
-       v4l2_ctrl_new_std(hdl, &adv7604_ctrl_ops,
+       v4l2_ctrl_new_std(hdl, &adv76xx_ctrl_ops,
                        V4L2_CID_CONTRAST, 0, 255, 1, 128);
-       v4l2_ctrl_new_std(hdl, &adv7604_ctrl_ops,
+       v4l2_ctrl_new_std(hdl, &adv76xx_ctrl_ops,
                        V4L2_CID_SATURATION, 0, 255, 1, 128);
-       v4l2_ctrl_new_std(hdl, &adv7604_ctrl_ops,
+       v4l2_ctrl_new_std(hdl, &adv76xx_ctrl_ops,
                        V4L2_CID_HUE, 0, 128, 1, 0);
 
        /* private controls */
@@ -2779,18 +2787,18 @@ static int adv7604_probe(struct i2c_client *client,
                        V4L2_CID_DV_RX_POWER_PRESENT, 0,
                        (1 << state->info->num_dv_ports) - 1, 0, 0);
        state->rgb_quantization_range_ctrl =
-               v4l2_ctrl_new_std_menu(hdl, &adv7604_ctrl_ops,
+               v4l2_ctrl_new_std_menu(hdl, &adv76xx_ctrl_ops,
                        V4L2_CID_DV_RX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL,
                        0, V4L2_DV_RGB_RANGE_AUTO);
 
        /* custom controls */
-       if (adv7604_has_afe(state))
+       if (adv76xx_has_afe(state))
                state->analog_sampling_phase_ctrl =
                        v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_analog_sampling_phase, NULL);
        state->free_run_color_manual_ctrl =
-               v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_free_run_color_manual, NULL);
+               v4l2_ctrl_new_custom(hdl, &adv76xx_ctrl_free_run_color_manual, NULL);
        state->free_run_color_ctrl =
-               v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_free_run_color, NULL);
+               v4l2_ctrl_new_custom(hdl, &adv76xx_ctrl_free_run_color, NULL);
 
        sd->ctrl_handler = hdl;
        if (hdl->error) {
@@ -2799,22 +2807,22 @@ static int adv7604_probe(struct i2c_client *client,
        }
        state->detect_tx_5v_ctrl->is_private = true;
        state->rgb_quantization_range_ctrl->is_private = true;
-       if (adv7604_has_afe(state))
+       if (adv76xx_has_afe(state))
                state->analog_sampling_phase_ctrl->is_private = true;
        state->free_run_color_manual_ctrl->is_private = true;
        state->free_run_color_ctrl->is_private = true;
 
-       if (adv7604_s_detect_tx_5v_ctrl(sd)) {
+       if (adv76xx_s_detect_tx_5v_ctrl(sd)) {
                err = -ENODEV;
                goto err_hdl;
        }
 
-       for (i = 1; i < ADV7604_PAGE_MAX; ++i) {
+       for (i = 1; i < ADV76XX_PAGE_MAX; ++i) {
                if (!(BIT(i) & state->info->page_mask))
                        continue;
 
                state->i2c_clients[i] =
-                       adv7604_dummy_client(sd, state->pdata.i2c_addresses[i],
+                       adv76xx_dummy_client(sd, state->pdata.i2c_addresses[i],
                                             0xf2 + i);
                if (state->i2c_clients[i] == NULL) {
                        err = -ENOMEM;
@@ -2832,7 +2840,7 @@ static int adv7604_probe(struct i2c_client *client,
        }
 
        INIT_DELAYED_WORK(&state->delayed_work_enable_hotplug,
-                       adv7604_delayed_work_enable_hotplug);
+                       adv76xx_delayed_work_enable_hotplug);
 
        state->source_pad = state->info->num_dv_ports
                          + (state->info->has_afe ? 2 : 0);
@@ -2845,7 +2853,7 @@ static int adv7604_probe(struct i2c_client *client,
        if (err)
                goto err_work_queues;
 
-       err = adv7604_core_init(sd);
+       err = adv76xx_core_init(sd);
        if (err)
                goto err_entity;
        v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
@@ -2863,7 +2871,7 @@ err_work_queues:
        cancel_delayed_work(&state->delayed_work_enable_hotplug);
        destroy_workqueue(state->work_queues);
 err_i2c:
-       adv7604_unregister_clients(state);
+       adv76xx_unregister_clients(state);
 err_hdl:
        v4l2_ctrl_handler_free(hdl);
        return err;
@@ -2871,32 +2879,31 @@ err_hdl:
 
 /* ----------------------------------------------------------------------- */
 
-static int adv7604_remove(struct i2c_client *client)
+static int adv76xx_remove(struct i2c_client *client)
 {
        struct v4l2_subdev *sd = i2c_get_clientdata(client);
-       struct adv7604_state *state = to_state(sd);
+       struct adv76xx_state *state = to_state(sd);
 
        cancel_delayed_work(&state->delayed_work_enable_hotplug);
        destroy_workqueue(state->work_queues);
        v4l2_async_unregister_subdev(sd);
-       v4l2_device_unregister_subdev(sd);
        media_entity_cleanup(&sd->entity);
-       adv7604_unregister_clients(to_state(sd));
+       adv76xx_unregister_clients(to_state(sd));
        v4l2_ctrl_handler_free(sd->ctrl_handler);
        return 0;
 }
 
 /* ----------------------------------------------------------------------- */
 
-static struct i2c_driver adv7604_driver = {
+static struct i2c_driver adv76xx_driver = {
        .driver = {
                .owner = THIS_MODULE,
                .name = "adv7604",
-               .of_match_table = of_match_ptr(adv7604_of_id),
+               .of_match_table = of_match_ptr(adv76xx_of_id),
        },
-       .probe = adv7604_probe,
-       .remove = adv7604_remove,
-       .id_table = adv7604_i2c_id,
+       .probe = adv76xx_probe,
+       .remove = adv76xx_remove,
+       .id_table = adv76xx_i2c_id,
 };
 
-module_i2c_driver(adv7604_driver);
+module_i2c_driver(adv76xx_driver);
index 7c215ee142c4057a040c6ccfd46a1bb987ce4b9d..b5a37fe10a6a5d423ff63af635894e028e6abcf3 100644 (file)
@@ -1119,7 +1119,7 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
                /* Receiving DVI-D signal
                 * ADV7842 selects RGB limited range regardless of
                 * input format (CE/IT) in automatic mode */
-               if (state->timings.bt.standards & V4L2_DV_BT_STD_CEA861) {
+               if (state->timings.bt.flags & V4L2_DV_FL_IS_CE_VIDEO) {
                        /* RGB limited range (16-235) */
                        io_write_and_or(sd, 0x02, 0x0f, 0x00);
                } else {
@@ -1901,7 +1901,8 @@ static int adv7842_g_mbus_fmt(struct v4l2_subdev *sd,
                return 0;
        }
 
-       if (state->timings.bt.standards & V4L2_DV_BT_STD_CEA861) {
+       fmt->colorspace = V4L2_COLORSPACE_SRGB;
+       if (state->timings.bt.flags & V4L2_DV_FL_IS_CE_VIDEO) {
                fmt->colorspace = (state->timings.bt.height <= 576) ?
                        V4L2_COLORSPACE_SMPTE170M : V4L2_COLORSPACE_REC709;
        }
index 573e08826b9bb4bdc21a3f33d8344c4fef2e0c1a..bd496447749a1e413023b18a6c17e174f5719a2e 100644 (file)
@@ -5137,6 +5137,9 @@ static int cx25840_probe(struct i2c_client *client,
        int default_volume;
        u32 id;
        u16 device_id;
+#if defined(CONFIG_MEDIA_CONTROLLER)
+       int ret;
+#endif
 
        /* Check if the adapter supports the needed features */
        if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
@@ -5178,6 +5181,33 @@ static int cx25840_probe(struct i2c_client *client,
 
        sd = &state->sd;
        v4l2_i2c_subdev_init(sd, client, &cx25840_ops);
+#if defined(CONFIG_MEDIA_CONTROLLER)
+       /*
+        * TODO: add media controller support for analog video inputs like
+        * composite, svideo, etc.
+        * A real input pad for this analog demod would be like:
+        *                 ___________
+        * TUNER --------> |         |
+        *                 |         |
+        * SVIDEO .......> | cx25840 |
+        *                 |         |
+        * COMPOSITE1 ...> |_________|
+        *
+        * However, at least for now, there's no much gain on modelling
+        * those extra inputs. So, let's add it only when needed.
+        */
+       state->pads[CX25840_PAD_INPUT].flags = MEDIA_PAD_FL_SINK;
+       state->pads[CX25840_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
+       state->pads[CX25840_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE;
+       sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_DECODER;
+
+       ret = media_entity_init(&sd->entity, ARRAY_SIZE(state->pads),
+                               state->pads, 0);
+       if (ret < 0) {
+               v4l_info(client, "failed to initialize media entity!\n");
+               return ret;
+       }
+#endif
 
        switch (id) {
        case CX23885_AV:
index 37bc04217c4457cae322c91ce8fb9ed3ece6167f..fdea48ce0c036253c9e3a443a361fdcc36e0b076 100644 (file)
@@ -41,6 +41,14 @@ enum cx25840_model {
        CX25837,
 };
 
+enum cx25840_media_pads {
+       CX25840_PAD_INPUT,
+       CX25840_PAD_VID_OUT,
+       CX25840_PAD_VBI_OUT,
+
+       CX25840_NUM_PADS
+};
+
 struct cx25840_state {
        struct i2c_client *c;
        struct v4l2_subdev sd;
@@ -64,6 +72,9 @@ struct cx25840_state {
        wait_queue_head_t fw_wait;    /* wake up when the fw load is finished */
        struct work_struct fw_work;   /* work entry for fw load */
        struct cx25840_ir_state *ir_state;
+#if defined(CONFIG_MEDIA_CONTROLLER)
+       struct media_pad        pads[CX25840_NUM_PADS];
+#endif
 };
 
 static inline struct cx25840_state *to_state(struct v4l2_subdev *sd)
index 6ed16e569bbf51775b19903058837e86c765086f..6404c0d93e7af9d95602bca1a2349faa355b674d 100644 (file)
@@ -531,17 +531,17 @@ static int __find_resolution(struct v4l2_subdev *sd,
 }
 
 static struct v4l2_mbus_framefmt *__find_format(struct m5mols_info *info,
-                               struct v4l2_subdev_fh *fh,
+                               struct v4l2_subdev_pad_config *cfg,
                                enum v4l2_subdev_format_whence which,
                                enum m5mols_restype type)
 {
        if (which == V4L2_SUBDEV_FORMAT_TRY)
-               return fh ? v4l2_subdev_get_try_format(fh, 0) : NULL;
+               return cfg ? v4l2_subdev_get_try_format(&info->sd, cfg, 0) : NULL;
 
        return &info->ffmt[type];
 }
 
-static int m5mols_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int m5mols_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                          struct v4l2_subdev_format *fmt)
 {
        struct m5mols_info *info = to_m5mols(sd);
@@ -550,7 +550,7 @@ static int m5mols_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 
        mutex_lock(&info->lock);
 
-       format = __find_format(info, fh, fmt->which, info->res_type);
+       format = __find_format(info, cfg, fmt->which, info->res_type);
        if (format)
                fmt->format = *format;
        else
@@ -560,7 +560,7 @@ static int m5mols_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        return ret;
 }
 
-static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                          struct v4l2_subdev_format *fmt)
 {
        struct m5mols_info *info = to_m5mols(sd);
@@ -574,7 +574,7 @@ static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        if (ret < 0)
                return ret;
 
-       sfmt = __find_format(info, fh, fmt->which, type);
+       sfmt = __find_format(info, cfg, fmt->which, type);
        if (!sfmt)
                return 0;
 
@@ -640,7 +640,7 @@ static int m5mols_set_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
 
 
 static int m5mols_enum_mbus_code(struct v4l2_subdev *sd,
-                                struct v4l2_subdev_fh *fh,
+                                struct v4l2_subdev_pad_config *cfg,
                                 struct v4l2_subdev_mbus_code_enum *code)
 {
        if (!code || code->index >= SIZE_DEFAULT_FFMT)
@@ -895,7 +895,7 @@ static const struct v4l2_subdev_core_ops m5mols_core_ops = {
  */
 static int m5mols_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 {
-       struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0);
+       struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(sd, fh->pad, 0);
 
        *format = m5mols_default_ffmt[0];
        return 0;
index 76431223f0ff3b0fe8d47ce4e0afd6c707604ddd..c7747bd0cabbcd9a53dfb754f5af626f916dc618 100644 (file)
@@ -317,7 +317,7 @@ static int mt9m032_setup_pll(struct mt9m032 *sensor)
  */
 
 static int mt9m032_enum_mbus_code(struct v4l2_subdev *subdev,
-                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_pad_config *cfg,
                                  struct v4l2_subdev_mbus_code_enum *code)
 {
        if (code->index != 0)
@@ -328,7 +328,7 @@ static int mt9m032_enum_mbus_code(struct v4l2_subdev *subdev,
 }
 
 static int mt9m032_enum_frame_size(struct v4l2_subdev *subdev,
-                                  struct v4l2_subdev_fh *fh,
+                                  struct v4l2_subdev_pad_config *cfg,
                                   struct v4l2_subdev_frame_size_enum *fse)
 {
        if (fse->index != 0 || fse->code != MEDIA_BUS_FMT_Y8_1X8)
@@ -345,18 +345,18 @@ static int mt9m032_enum_frame_size(struct v4l2_subdev *subdev,
 /**
  * __mt9m032_get_pad_crop() - get crop rect
  * @sensor: pointer to the sensor struct
- * @fh: file handle for getting the try crop rect from
+ * @cfg: v4l2_subdev_pad_config for getting the try crop rect from
  * @which: select try or active crop rect
  *
  * Returns a pointer the current active or fh relative try crop rect
  */
 static struct v4l2_rect *
-__mt9m032_get_pad_crop(struct mt9m032 *sensor, struct v4l2_subdev_fh *fh,
+__mt9m032_get_pad_crop(struct mt9m032 *sensor, struct v4l2_subdev_pad_config *cfg,
                       enum v4l2_subdev_format_whence which)
 {
        switch (which) {
        case V4L2_SUBDEV_FORMAT_TRY:
-               return v4l2_subdev_get_try_crop(fh, 0);
+               return v4l2_subdev_get_try_crop(&sensor->subdev, cfg, 0);
        case V4L2_SUBDEV_FORMAT_ACTIVE:
                return &sensor->crop;
        default:
@@ -367,18 +367,18 @@ __mt9m032_get_pad_crop(struct mt9m032 *sensor, struct v4l2_subdev_fh *fh,
 /**
  * __mt9m032_get_pad_format() - get format
  * @sensor: pointer to the sensor struct
- * @fh: file handle for getting the try format from
+ * @cfg: v4l2_subdev_pad_config for getting the try format from
  * @which: select try or active format
  *
  * Returns a pointer the current active or fh relative try format
  */
 static struct v4l2_mbus_framefmt *
-__mt9m032_get_pad_format(struct mt9m032 *sensor, struct v4l2_subdev_fh *fh,
+__mt9m032_get_pad_format(struct mt9m032 *sensor, struct v4l2_subdev_pad_config *cfg,
                         enum v4l2_subdev_format_whence which)
 {
        switch (which) {
        case V4L2_SUBDEV_FORMAT_TRY:
-               return v4l2_subdev_get_try_format(fh, 0);
+               return v4l2_subdev_get_try_format(&sensor->subdev, cfg, 0);
        case V4L2_SUBDEV_FORMAT_ACTIVE:
                return &sensor->format;
        default:
@@ -387,20 +387,20 @@ __mt9m032_get_pad_format(struct mt9m032 *sensor, struct v4l2_subdev_fh *fh,
 }
 
 static int mt9m032_get_pad_format(struct v4l2_subdev *subdev,
-                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_pad_config *cfg,
                                  struct v4l2_subdev_format *fmt)
 {
        struct mt9m032 *sensor = to_mt9m032(subdev);
 
        mutex_lock(&sensor->lock);
-       fmt->format = *__mt9m032_get_pad_format(sensor, fh, fmt->which);
+       fmt->format = *__mt9m032_get_pad_format(sensor, cfg, fmt->which);
        mutex_unlock(&sensor->lock);
 
        return 0;
 }
 
 static int mt9m032_set_pad_format(struct v4l2_subdev *subdev,
-                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_pad_config *cfg,
                                  struct v4l2_subdev_format *fmt)
 {
        struct mt9m032 *sensor = to_mt9m032(subdev);
@@ -414,7 +414,7 @@ static int mt9m032_set_pad_format(struct v4l2_subdev *subdev,
        }
 
        /* Scaling is not supported, the format is thus fixed. */
-       fmt->format = *__mt9m032_get_pad_format(sensor, fh, fmt->which);
+       fmt->format = *__mt9m032_get_pad_format(sensor, cfg, fmt->which);
        ret = 0;
 
 done:
@@ -423,7 +423,7 @@ done:
 }
 
 static int mt9m032_get_pad_selection(struct v4l2_subdev *subdev,
-                                    struct v4l2_subdev_fh *fh,
+                                    struct v4l2_subdev_pad_config *cfg,
                                     struct v4l2_subdev_selection *sel)
 {
        struct mt9m032 *sensor = to_mt9m032(subdev);
@@ -432,14 +432,14 @@ static int mt9m032_get_pad_selection(struct v4l2_subdev *subdev,
                return -EINVAL;
 
        mutex_lock(&sensor->lock);
-       sel->r = *__mt9m032_get_pad_crop(sensor, fh, sel->which);
+       sel->r = *__mt9m032_get_pad_crop(sensor, cfg, sel->which);
        mutex_unlock(&sensor->lock);
 
        return 0;
 }
 
 static int mt9m032_set_pad_selection(struct v4l2_subdev *subdev,
-                                    struct v4l2_subdev_fh *fh,
+                                    struct v4l2_subdev_pad_config *cfg,
                                     struct v4l2_subdev_selection *sel)
 {
        struct mt9m032 *sensor = to_mt9m032(subdev);
@@ -475,13 +475,13 @@ static int mt9m032_set_pad_selection(struct v4l2_subdev *subdev,
        rect.height = min_t(unsigned int, rect.height,
                            MT9M032_PIXEL_ARRAY_HEIGHT - rect.top);
 
-       __crop = __mt9m032_get_pad_crop(sensor, fh, sel->which);
+       __crop = __mt9m032_get_pad_crop(sensor, cfg, sel->which);
 
        if (rect.width != __crop->width || rect.height != __crop->height) {
                /* Reset the output image size if the crop rectangle size has
                 * been modified.
                 */
-               format = __mt9m032_get_pad_format(sensor, fh, sel->which);
+               format = __mt9m032_get_pad_format(sensor, cfg, sel->which);
                format->width = rect.width;
                format->height = rect.height;
        }
index e3acae9a2ec3995e80cdc341f1ead6378492154c..0db15f528ac1c252d5199b33db41d38c2535175d 100644 (file)
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/device.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/i2c.h>
 #include <linux/log2.h>
 #include <linux/module.h>
 #include <linux/of.h>
-#include <linux/of_gpio.h>
 #include <linux/of_graph.h>
 #include <linux/pm.h>
 #include <linux/regulator/consumer.h>
@@ -28,6 +27,7 @@
 #include <linux/videodev2.h>
 
 #include <media/mt9p031.h>
+#include <media/v4l2-async.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-subdev.h>
@@ -135,7 +135,7 @@ struct mt9p031 {
        struct aptina_pll pll;
        unsigned int clk_div;
        bool use_pll;
-       int reset;
+       struct gpio_desc *reset;
 
        struct v4l2_ctrl_handler ctrls;
        struct v4l2_ctrl *blc_auto;
@@ -251,7 +251,7 @@ static int mt9p031_clk_setup(struct mt9p031 *mt9p031)
                div = DIV_ROUND_UP(pdata->ext_freq, pdata->target_freq);
                div = roundup_pow_of_two(div) / 2;
 
-               mt9p031->clk_div = max_t(unsigned int, div, 64);
+               mt9p031->clk_div = min_t(unsigned int, div, 64);
                mt9p031->use_pll = false;
 
                return 0;
@@ -308,9 +308,9 @@ static int mt9p031_power_on(struct mt9p031 *mt9p031)
 {
        int ret;
 
-       /* Ensure RESET_BAR is low */
-       if (gpio_is_valid(mt9p031->reset)) {
-               gpio_set_value(mt9p031->reset, 0);
+       /* Ensure RESET_BAR is active */
+       if (mt9p031->reset) {
+               gpiod_set_value(mt9p031->reset, 1);
                usleep_range(1000, 2000);
        }
 
@@ -331,8 +331,8 @@ static int mt9p031_power_on(struct mt9p031 *mt9p031)
        }
 
        /* Now RESET_BAR must be high */
-       if (gpio_is_valid(mt9p031->reset)) {
-               gpio_set_value(mt9p031->reset, 1);
+       if (mt9p031->reset) {
+               gpiod_set_value(mt9p031->reset, 0);
                usleep_range(1000, 2000);
        }
 
@@ -341,8 +341,8 @@ static int mt9p031_power_on(struct mt9p031 *mt9p031)
 
 static void mt9p031_power_off(struct mt9p031 *mt9p031)
 {
-       if (gpio_is_valid(mt9p031->reset)) {
-               gpio_set_value(mt9p031->reset, 0);
+       if (mt9p031->reset) {
+               gpiod_set_value(mt9p031->reset, 1);
                usleep_range(1000, 2000);
        }
 
@@ -474,7 +474,7 @@ static int mt9p031_s_stream(struct v4l2_subdev *subdev, int enable)
 }
 
 static int mt9p031_enum_mbus_code(struct v4l2_subdev *subdev,
-                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_pad_config *cfg,
                                  struct v4l2_subdev_mbus_code_enum *code)
 {
        struct mt9p031 *mt9p031 = to_mt9p031(subdev);
@@ -487,7 +487,7 @@ static int mt9p031_enum_mbus_code(struct v4l2_subdev *subdev,
 }
 
 static int mt9p031_enum_frame_size(struct v4l2_subdev *subdev,
-                                  struct v4l2_subdev_fh *fh,
+                                  struct v4l2_subdev_pad_config *cfg,
                                   struct v4l2_subdev_frame_size_enum *fse)
 {
        struct mt9p031 *mt9p031 = to_mt9p031(subdev);
@@ -505,12 +505,12 @@ static int mt9p031_enum_frame_size(struct v4l2_subdev *subdev,
 }
 
 static struct v4l2_mbus_framefmt *
-__mt9p031_get_pad_format(struct mt9p031 *mt9p031, struct v4l2_subdev_fh *fh,
+__mt9p031_get_pad_format(struct mt9p031 *mt9p031, struct v4l2_subdev_pad_config *cfg,
                         unsigned int pad, u32 which)
 {
        switch (which) {
        case V4L2_SUBDEV_FORMAT_TRY:
-               return v4l2_subdev_get_try_format(fh, pad);
+               return v4l2_subdev_get_try_format(&mt9p031->subdev, cfg, pad);
        case V4L2_SUBDEV_FORMAT_ACTIVE:
                return &mt9p031->format;
        default:
@@ -519,12 +519,12 @@ __mt9p031_get_pad_format(struct mt9p031 *mt9p031, struct v4l2_subdev_fh *fh,
 }
 
 static struct v4l2_rect *
-__mt9p031_get_pad_crop(struct mt9p031 *mt9p031, struct v4l2_subdev_fh *fh,
+__mt9p031_get_pad_crop(struct mt9p031 *mt9p031, struct v4l2_subdev_pad_config *cfg,
                     unsigned int pad, u32 which)
 {
        switch (which) {
        case V4L2_SUBDEV_FORMAT_TRY:
-               return v4l2_subdev_get_try_crop(fh, pad);
+               return v4l2_subdev_get_try_crop(&mt9p031->subdev, cfg, pad);
        case V4L2_SUBDEV_FORMAT_ACTIVE:
                return &mt9p031->crop;
        default:
@@ -533,18 +533,18 @@ __mt9p031_get_pad_crop(struct mt9p031 *mt9p031, struct v4l2_subdev_fh *fh,
 }
 
 static int mt9p031_get_format(struct v4l2_subdev *subdev,
-                             struct v4l2_subdev_fh *fh,
+                             struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_format *fmt)
 {
        struct mt9p031 *mt9p031 = to_mt9p031(subdev);
 
-       fmt->format = *__mt9p031_get_pad_format(mt9p031, fh, fmt->pad,
+       fmt->format = *__mt9p031_get_pad_format(mt9p031, cfg, fmt->pad,
                                                fmt->which);
        return 0;
 }
 
 static int mt9p031_set_format(struct v4l2_subdev *subdev,
-                             struct v4l2_subdev_fh *fh,
+                             struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_format *format)
 {
        struct mt9p031 *mt9p031 = to_mt9p031(subdev);
@@ -555,7 +555,7 @@ static int mt9p031_set_format(struct v4l2_subdev *subdev,
        unsigned int hratio;
        unsigned int vratio;
 
-       __crop = __mt9p031_get_pad_crop(mt9p031, fh, format->pad,
+       __crop = __mt9p031_get_pad_crop(mt9p031, cfg, format->pad,
                                        format->which);
 
        /* Clamp the width and height to avoid dividing by zero. */
@@ -571,7 +571,7 @@ static int mt9p031_set_format(struct v4l2_subdev *subdev,
        hratio = DIV_ROUND_CLOSEST(__crop->width, width);
        vratio = DIV_ROUND_CLOSEST(__crop->height, height);
 
-       __format = __mt9p031_get_pad_format(mt9p031, fh, format->pad,
+       __format = __mt9p031_get_pad_format(mt9p031, cfg, format->pad,
                                            format->which);
        __format->width = __crop->width / hratio;
        __format->height = __crop->height / vratio;
@@ -582,7 +582,7 @@ static int mt9p031_set_format(struct v4l2_subdev *subdev,
 }
 
 static int mt9p031_get_selection(struct v4l2_subdev *subdev,
-                                struct v4l2_subdev_fh *fh,
+                                struct v4l2_subdev_pad_config *cfg,
                                 struct v4l2_subdev_selection *sel)
 {
        struct mt9p031 *mt9p031 = to_mt9p031(subdev);
@@ -590,12 +590,12 @@ static int mt9p031_get_selection(struct v4l2_subdev *subdev,
        if (sel->target != V4L2_SEL_TGT_CROP)
                return -EINVAL;
 
-       sel->r = *__mt9p031_get_pad_crop(mt9p031, fh, sel->pad, sel->which);
+       sel->r = *__mt9p031_get_pad_crop(mt9p031, cfg, sel->pad, sel->which);
        return 0;
 }
 
 static int mt9p031_set_selection(struct v4l2_subdev *subdev,
-                                struct v4l2_subdev_fh *fh,
+                                struct v4l2_subdev_pad_config *cfg,
                                 struct v4l2_subdev_selection *sel)
 {
        struct mt9p031 *mt9p031 = to_mt9p031(subdev);
@@ -625,13 +625,13 @@ static int mt9p031_set_selection(struct v4l2_subdev *subdev,
        rect.height = min_t(unsigned int, rect.height,
                            MT9P031_PIXEL_ARRAY_HEIGHT - rect.top);
 
-       __crop = __mt9p031_get_pad_crop(mt9p031, fh, sel->pad, sel->which);
+       __crop = __mt9p031_get_pad_crop(mt9p031, cfg, sel->pad, sel->which);
 
        if (rect.width != __crop->width || rect.height != __crop->height) {
                /* Reset the output image size if the crop rectangle size has
                 * been modified.
                 */
-               __format = __mt9p031_get_pad_format(mt9p031, fh, sel->pad,
+               __format = __mt9p031_get_pad_format(mt9p031, cfg, sel->pad,
                                                    sel->which);
                __format->width = rect.width;
                __format->height = rect.height;
@@ -946,13 +946,13 @@ static int mt9p031_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
        struct v4l2_mbus_framefmt *format;
        struct v4l2_rect *crop;
 
-       crop = v4l2_subdev_get_try_crop(fh, 0);
+       crop = v4l2_subdev_get_try_crop(subdev, fh->pad, 0);
        crop->left = MT9P031_COLUMN_START_DEF;
        crop->top = MT9P031_ROW_START_DEF;
        crop->width = MT9P031_WINDOW_WIDTH_DEF;
        crop->height = MT9P031_WINDOW_HEIGHT_DEF;
 
-       format = v4l2_subdev_get_try_format(fh, 0);
+       format = v4l2_subdev_get_try_format(subdev, fh->pad, 0);
 
        if (mt9p031->model == MT9P031_MODEL_MONOCHROME)
                format->code = MEDIA_BUS_FMT_Y12_1X12;
@@ -1022,7 +1022,6 @@ mt9p031_get_pdata(struct i2c_client *client)
        if (!pdata)
                goto done;
 
-       pdata->reset = of_get_named_gpio(client->dev.of_node, "reset-gpios", 0);
        of_property_read_u32(np, "input-clock-frequency", &pdata->ext_freq);
        of_property_read_u32(np, "pixel-clock-frequency", &pdata->target_freq);
 
@@ -1059,7 +1058,6 @@ static int mt9p031_probe(struct i2c_client *client,
        mt9p031->output_control = MT9P031_OUTPUT_CONTROL_DEF;
        mt9p031->mode2 = MT9P031_READ_MODE_2_ROW_BLC;
        mt9p031->model = did->driver_data;
-       mt9p031->reset = -1;
 
        mt9p031->regulators[0].supply = "vdd";
        mt9p031->regulators[1].supply = "vdd_io";
@@ -1071,6 +1069,8 @@ static int mt9p031_probe(struct i2c_client *client,
                return ret;
        }
 
+       mutex_init(&mt9p031->power_lock);
+
        v4l2_ctrl_handler_init(&mt9p031->ctrls, ARRAY_SIZE(mt9p031_ctrls) + 6);
 
        v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
@@ -1108,7 +1108,6 @@ static int mt9p031_probe(struct i2c_client *client,
        mt9p031->blc_offset = v4l2_ctrl_find(&mt9p031->ctrls,
                                             V4L2_CID_BLC_DIGITAL_OFFSET);
 
-       mutex_init(&mt9p031->power_lock);
        v4l2_i2c_subdev_init(&mt9p031->subdev, client, &mt9p031_subdev_ops);
        mt9p031->subdev.internal_ops = &mt9p031_subdev_internal_ops;
 
@@ -1134,21 +1133,20 @@ static int mt9p031_probe(struct i2c_client *client,
        mt9p031->format.field = V4L2_FIELD_NONE;
        mt9p031->format.colorspace = V4L2_COLORSPACE_SRGB;
 
-       if (gpio_is_valid(pdata->reset)) {
-               ret = devm_gpio_request_one(&client->dev, pdata->reset,
-                                           GPIOF_OUT_INIT_LOW, "mt9p031_rst");
-               if (ret < 0)
-                       goto done;
-
-               mt9p031->reset = pdata->reset;
-       }
+       mt9p031->reset = devm_gpiod_get_optional(&client->dev, "reset",
+                                                GPIOD_OUT_HIGH);
 
        ret = mt9p031_clk_setup(mt9p031);
+       if (ret)
+               goto done;
+
+       ret = v4l2_async_register_subdev(&mt9p031->subdev);
 
 done:
        if (ret < 0) {
                v4l2_ctrl_handler_free(&mt9p031->ctrls);
                media_entity_cleanup(&mt9p031->subdev.entity);
+               mutex_destroy(&mt9p031->power_lock);
        }
 
        return ret;
@@ -1160,8 +1158,9 @@ static int mt9p031_remove(struct i2c_client *client)
        struct mt9p031 *mt9p031 = to_mt9p031(subdev);
 
        v4l2_ctrl_handler_free(&mt9p031->ctrls);
-       v4l2_device_unregister_subdev(subdev);
+       v4l2_async_unregister_subdev(subdev);
        media_entity_cleanup(&subdev->entity);
+       mutex_destroy(&mt9p031->power_lock);
 
        return 0;
 }
index f6ca636b538dc8888b5a9230ee311680029f15d4..8ae99f7f254caef7b16a792558d4299e5934e152 100644 (file)
@@ -244,12 +244,12 @@ static int __mt9t001_set_power(struct mt9t001 *mt9t001, bool on)
  */
 
 static struct v4l2_mbus_framefmt *
-__mt9t001_get_pad_format(struct mt9t001 *mt9t001, struct v4l2_subdev_fh *fh,
+__mt9t001_get_pad_format(struct mt9t001 *mt9t001, struct v4l2_subdev_pad_config *cfg,
                         unsigned int pad, enum v4l2_subdev_format_whence which)
 {
        switch (which) {
        case V4L2_SUBDEV_FORMAT_TRY:
-               return v4l2_subdev_get_try_format(fh, pad);
+               return v4l2_subdev_get_try_format(&mt9t001->subdev, cfg, pad);
        case V4L2_SUBDEV_FORMAT_ACTIVE:
                return &mt9t001->format;
        default:
@@ -258,12 +258,12 @@ __mt9t001_get_pad_format(struct mt9t001 *mt9t001, struct v4l2_subdev_fh *fh,
 }
 
 static struct v4l2_rect *
-__mt9t001_get_pad_crop(struct mt9t001 *mt9t001, struct v4l2_subdev_fh *fh,
+__mt9t001_get_pad_crop(struct mt9t001 *mt9t001, struct v4l2_subdev_pad_config *cfg,
                       unsigned int pad, enum v4l2_subdev_format_whence which)
 {
        switch (which) {
        case V4L2_SUBDEV_FORMAT_TRY:
-               return v4l2_subdev_get_try_crop(fh, pad);
+               return v4l2_subdev_get_try_crop(&mt9t001->subdev, cfg, pad);
        case V4L2_SUBDEV_FORMAT_ACTIVE:
                return &mt9t001->crop;
        default:
@@ -327,7 +327,7 @@ static int mt9t001_s_stream(struct v4l2_subdev *subdev, int enable)
 }
 
 static int mt9t001_enum_mbus_code(struct v4l2_subdev *subdev,
-                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_pad_config *cfg,
                                  struct v4l2_subdev_mbus_code_enum *code)
 {
        if (code->index > 0)
@@ -338,7 +338,7 @@ static int mt9t001_enum_mbus_code(struct v4l2_subdev *subdev,
 }
 
 static int mt9t001_enum_frame_size(struct v4l2_subdev *subdev,
-                                  struct v4l2_subdev_fh *fh,
+                                  struct v4l2_subdev_pad_config *cfg,
                                   struct v4l2_subdev_frame_size_enum *fse)
 {
        if (fse->index >= 8 || fse->code != MEDIA_BUS_FMT_SGRBG10_1X10)
@@ -353,18 +353,18 @@ static int mt9t001_enum_frame_size(struct v4l2_subdev *subdev,
 }
 
 static int mt9t001_get_format(struct v4l2_subdev *subdev,
-                             struct v4l2_subdev_fh *fh,
+                             struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_format *format)
 {
        struct mt9t001 *mt9t001 = to_mt9t001(subdev);
 
-       format->format = *__mt9t001_get_pad_format(mt9t001, fh, format->pad,
+       format->format = *__mt9t001_get_pad_format(mt9t001, cfg, format->pad,
                                                   format->which);
        return 0;
 }
 
 static int mt9t001_set_format(struct v4l2_subdev *subdev,
-                             struct v4l2_subdev_fh *fh,
+                             struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_format *format)
 {
        struct mt9t001 *mt9t001 = to_mt9t001(subdev);
@@ -375,7 +375,7 @@ static int mt9t001_set_format(struct v4l2_subdev *subdev,
        unsigned int hratio;
        unsigned int vratio;
 
-       __crop = __mt9t001_get_pad_crop(mt9t001, fh, format->pad,
+       __crop = __mt9t001_get_pad_crop(mt9t001, cfg, format->pad,
                                        format->which);
 
        /* Clamp the width and height to avoid dividing by zero. */
@@ -391,7 +391,7 @@ static int mt9t001_set_format(struct v4l2_subdev *subdev,
        hratio = DIV_ROUND_CLOSEST(__crop->width, width);
        vratio = DIV_ROUND_CLOSEST(__crop->height, height);
 
-       __format = __mt9t001_get_pad_format(mt9t001, fh, format->pad,
+       __format = __mt9t001_get_pad_format(mt9t001, cfg, format->pad,
                                            format->which);
        __format->width = __crop->width / hratio;
        __format->height = __crop->height / vratio;
@@ -402,7 +402,7 @@ static int mt9t001_set_format(struct v4l2_subdev *subdev,
 }
 
 static int mt9t001_get_selection(struct v4l2_subdev *subdev,
-                                struct v4l2_subdev_fh *fh,
+                                struct v4l2_subdev_pad_config *cfg,
                                 struct v4l2_subdev_selection *sel)
 {
        struct mt9t001 *mt9t001 = to_mt9t001(subdev);
@@ -410,12 +410,12 @@ static int mt9t001_get_selection(struct v4l2_subdev *subdev,
        if (sel->target != V4L2_SEL_TGT_CROP)
                return -EINVAL;
 
-       sel->r = *__mt9t001_get_pad_crop(mt9t001, fh, sel->pad, sel->which);
+       sel->r = *__mt9t001_get_pad_crop(mt9t001, cfg, sel->pad, sel->which);
        return 0;
 }
 
 static int mt9t001_set_selection(struct v4l2_subdev *subdev,
-                                struct v4l2_subdev_fh *fh,
+                                struct v4l2_subdev_pad_config *cfg,
                                 struct v4l2_subdev_selection *sel)
 {
        struct mt9t001 *mt9t001 = to_mt9t001(subdev);
@@ -447,13 +447,13 @@ static int mt9t001_set_selection(struct v4l2_subdev *subdev,
        rect.height = min_t(unsigned int, rect.height,
                            MT9T001_PIXEL_ARRAY_HEIGHT - rect.top);
 
-       __crop = __mt9t001_get_pad_crop(mt9t001, fh, sel->pad, sel->which);
+       __crop = __mt9t001_get_pad_crop(mt9t001, cfg, sel->pad, sel->which);
 
        if (rect.width != __crop->width || rect.height != __crop->height) {
                /* Reset the output image size if the crop rectangle size has
                 * been modified.
                 */
-               __format = __mt9t001_get_pad_format(mt9t001, fh, sel->pad,
+               __format = __mt9t001_get_pad_format(mt9t001, cfg, sel->pad,
                                                    sel->which);
                __format->width = rect.width;
                __format->height = rect.height;
@@ -790,13 +790,13 @@ static int mt9t001_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
        struct v4l2_mbus_framefmt *format;
        struct v4l2_rect *crop;
 
-       crop = v4l2_subdev_get_try_crop(fh, 0);
+       crop = v4l2_subdev_get_try_crop(subdev, fh->pad, 0);
        crop->left = MT9T001_COLUMN_START_DEF;
        crop->top = MT9T001_ROW_START_DEF;
        crop->width = MT9T001_WINDOW_WIDTH_DEF + 1;
        crop->height = MT9T001_WINDOW_HEIGHT_DEF + 1;
 
-       format = v4l2_subdev_get_try_format(fh, 0);
+       format = v4l2_subdev_get_try_format(subdev, fh->pad, 0);
        format->code = MEDIA_BUS_FMT_SGRBG10_1X10;
        format->width = MT9T001_WINDOW_WIDTH_DEF + 1;
        format->height = MT9T001_WINDOW_HEIGHT_DEF + 1;
index bd3f979a4d49920c4dfa0f6c4d9b366878f23b69..977f4006edbd496dfa9d45a7e0f4f2ab6dfc40c0 100644 (file)
@@ -17,6 +17,8 @@
 #include <linux/i2c.h>
 #include <linux/log2.h>
 #include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
 #include <linux/regmap.h>
 #include <linux/slab.h>
 #include <linux/videodev2.h>
@@ -26,6 +28,7 @@
 #include <media/mt9v032.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
+#include <media/v4l2-of.h>
 #include <media/v4l2-subdev.h>
 
 /* The first four rows are black rows. The active area spans 753x481 pixels. */
@@ -371,12 +374,12 @@ static int __mt9v032_set_power(struct mt9v032 *mt9v032, bool on)
  */
 
 static struct v4l2_mbus_framefmt *
-__mt9v032_get_pad_format(struct mt9v032 *mt9v032, struct v4l2_subdev_fh *fh,
+__mt9v032_get_pad_format(struct mt9v032 *mt9v032, struct v4l2_subdev_pad_config *cfg,
                         unsigned int pad, enum v4l2_subdev_format_whence which)
 {
        switch (which) {
        case V4L2_SUBDEV_FORMAT_TRY:
-               return v4l2_subdev_get_try_format(fh, pad);
+               return v4l2_subdev_get_try_format(&mt9v032->subdev, cfg, pad);
        case V4L2_SUBDEV_FORMAT_ACTIVE:
                return &mt9v032->format;
        default:
@@ -385,12 +388,12 @@ __mt9v032_get_pad_format(struct mt9v032 *mt9v032, struct v4l2_subdev_fh *fh,
 }
 
 static struct v4l2_rect *
-__mt9v032_get_pad_crop(struct mt9v032 *mt9v032, struct v4l2_subdev_fh *fh,
+__mt9v032_get_pad_crop(struct mt9v032 *mt9v032, struct v4l2_subdev_pad_config *cfg,
                       unsigned int pad, enum v4l2_subdev_format_whence which)
 {
        switch (which) {
        case V4L2_SUBDEV_FORMAT_TRY:
-               return v4l2_subdev_get_try_crop(fh, pad);
+               return v4l2_subdev_get_try_crop(&mt9v032->subdev, cfg, pad);
        case V4L2_SUBDEV_FORMAT_ACTIVE:
                return &mt9v032->crop;
        default:
@@ -448,7 +451,7 @@ static int mt9v032_s_stream(struct v4l2_subdev *subdev, int enable)
 }
 
 static int mt9v032_enum_mbus_code(struct v4l2_subdev *subdev,
-                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_pad_config *cfg,
                                  struct v4l2_subdev_mbus_code_enum *code)
 {
        if (code->index > 0)
@@ -459,7 +462,7 @@ static int mt9v032_enum_mbus_code(struct v4l2_subdev *subdev,
 }
 
 static int mt9v032_enum_frame_size(struct v4l2_subdev *subdev,
-                                  struct v4l2_subdev_fh *fh,
+                                  struct v4l2_subdev_pad_config *cfg,
                                   struct v4l2_subdev_frame_size_enum *fse)
 {
        if (fse->index >= 3 || fse->code != MEDIA_BUS_FMT_SGRBG10_1X10)
@@ -474,12 +477,12 @@ static int mt9v032_enum_frame_size(struct v4l2_subdev *subdev,
 }
 
 static int mt9v032_get_format(struct v4l2_subdev *subdev,
-                             struct v4l2_subdev_fh *fh,
+                             struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_format *format)
 {
        struct mt9v032 *mt9v032 = to_mt9v032(subdev);
 
-       format->format = *__mt9v032_get_pad_format(mt9v032, fh, format->pad,
+       format->format = *__mt9v032_get_pad_format(mt9v032, cfg, format->pad,
                                                   format->which);
        return 0;
 }
@@ -509,7 +512,7 @@ static unsigned int mt9v032_calc_ratio(unsigned int input, unsigned int output)
 }
 
 static int mt9v032_set_format(struct v4l2_subdev *subdev,
-                             struct v4l2_subdev_fh *fh,
+                             struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_format *format)
 {
        struct mt9v032 *mt9v032 = to_mt9v032(subdev);
@@ -520,7 +523,7 @@ static int mt9v032_set_format(struct v4l2_subdev *subdev,
        unsigned int hratio;
        unsigned int vratio;
 
-       __crop = __mt9v032_get_pad_crop(mt9v032, fh, format->pad,
+       __crop = __mt9v032_get_pad_crop(mt9v032, cfg, format->pad,
                                        format->which);
 
        /* Clamp the width and height to avoid dividing by zero. */
@@ -536,7 +539,7 @@ static int mt9v032_set_format(struct v4l2_subdev *subdev,
        hratio = mt9v032_calc_ratio(__crop->width, width);
        vratio = mt9v032_calc_ratio(__crop->height, height);
 
-       __format = __mt9v032_get_pad_format(mt9v032, fh, format->pad,
+       __format = __mt9v032_get_pad_format(mt9v032, cfg, format->pad,
                                            format->which);
        __format->width = __crop->width / hratio;
        __format->height = __crop->height / vratio;
@@ -553,7 +556,7 @@ static int mt9v032_set_format(struct v4l2_subdev *subdev,
 }
 
 static int mt9v032_get_selection(struct v4l2_subdev *subdev,
-                                struct v4l2_subdev_fh *fh,
+                                struct v4l2_subdev_pad_config *cfg,
                                 struct v4l2_subdev_selection *sel)
 {
        struct mt9v032 *mt9v032 = to_mt9v032(subdev);
@@ -561,12 +564,12 @@ static int mt9v032_get_selection(struct v4l2_subdev *subdev,
        if (sel->target != V4L2_SEL_TGT_CROP)
                return -EINVAL;
 
-       sel->r = *__mt9v032_get_pad_crop(mt9v032, fh, sel->pad, sel->which);
+       sel->r = *__mt9v032_get_pad_crop(mt9v032, cfg, sel->pad, sel->which);
        return 0;
 }
 
 static int mt9v032_set_selection(struct v4l2_subdev *subdev,
-                                struct v4l2_subdev_fh *fh,
+                                struct v4l2_subdev_pad_config *cfg,
                                 struct v4l2_subdev_selection *sel)
 {
        struct mt9v032 *mt9v032 = to_mt9v032(subdev);
@@ -598,13 +601,13 @@ static int mt9v032_set_selection(struct v4l2_subdev *subdev,
        rect.height = min_t(unsigned int,
                            rect.height, MT9V032_PIXEL_ARRAY_HEIGHT - rect.top);
 
-       __crop = __mt9v032_get_pad_crop(mt9v032, fh, sel->pad, sel->which);
+       __crop = __mt9v032_get_pad_crop(mt9v032, cfg, sel->pad, sel->which);
 
        if (rect.width != __crop->width || rect.height != __crop->height) {
                /* Reset the output image size if the crop rectangle size has
                 * been modified.
                 */
-               __format = __mt9v032_get_pad_format(mt9v032, fh, sel->pad,
+               __format = __mt9v032_get_pad_format(mt9v032, cfg, sel->pad,
                                                    sel->which);
                __format->width = rect.width;
                __format->height = rect.height;
@@ -810,13 +813,13 @@ static int mt9v032_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
        struct v4l2_mbus_framefmt *format;
        struct v4l2_rect *crop;
 
-       crop = v4l2_subdev_get_try_crop(fh, 0);
+       crop = v4l2_subdev_get_try_crop(subdev, fh->pad, 0);
        crop->left = MT9V032_COLUMN_START_DEF;
        crop->top = MT9V032_ROW_START_DEF;
        crop->width = MT9V032_WINDOW_WIDTH_DEF;
        crop->height = MT9V032_WINDOW_HEIGHT_DEF;
 
-       format = v4l2_subdev_get_try_format(fh, 0);
+       format = v4l2_subdev_get_try_format(subdev, fh->pad, 0);
 
        if (mt9v032->model->color)
                format->code = MEDIA_BUS_FMT_SGRBG10_1X10;
@@ -876,10 +879,58 @@ static const struct regmap_config mt9v032_regmap_config = {
  * Driver initialization and probing
  */
 
+static struct mt9v032_platform_data *
+mt9v032_get_pdata(struct i2c_client *client)
+{
+       struct mt9v032_platform_data *pdata;
+       struct v4l2_of_endpoint endpoint;
+       struct device_node *np;
+       struct property *prop;
+
+       if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node)
+               return client->dev.platform_data;
+
+       np = of_graph_get_next_endpoint(client->dev.of_node, NULL);
+       if (!np)
+               return NULL;
+
+       if (v4l2_of_parse_endpoint(np, &endpoint) < 0)
+               goto done;
+
+       pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               goto done;
+
+       prop = of_find_property(np, "link-frequencies", NULL);
+       if (prop) {
+               u64 *link_freqs;
+               size_t size = prop->length / sizeof(*link_freqs);
+
+               link_freqs = devm_kcalloc(&client->dev, size,
+                                         sizeof(*link_freqs), GFP_KERNEL);
+               if (!link_freqs)
+                       goto done;
+
+               if (of_property_read_u64_array(np, "link-frequencies",
+                                              link_freqs, size) < 0)
+                       goto done;
+
+               pdata->link_freqs = link_freqs;
+               pdata->link_def_freq = link_freqs[0];
+       }
+
+       pdata->clk_pol = !!(endpoint.bus.parallel.flags &
+                           V4L2_MBUS_PCLK_SAMPLE_RISING);
+
+done:
+       of_node_put(np);
+       return pdata;
+}
+
 static int mt9v032_probe(struct i2c_client *client,
                const struct i2c_device_id *did)
 {
-       struct mt9v032_platform_data *pdata = client->dev.platform_data;
+       struct mt9v032_platform_data *pdata = mt9v032_get_pdata(client);
        struct mt9v032 *mt9v032;
        unsigned int i;
        int ret;
@@ -961,9 +1012,12 @@ static int mt9v032_probe(struct i2c_client *client,
 
        mt9v032->subdev.ctrl_handler = &mt9v032->ctrls;
 
-       if (mt9v032->ctrls.error)
-               printk(KERN_INFO "%s: control initialization error %d\n",
-                      __func__, mt9v032->ctrls.error);
+       if (mt9v032->ctrls.error) {
+               dev_err(&client->dev, "control initialization error %d\n",
+                       mt9v032->ctrls.error);
+               ret = mt9v032->ctrls.error;
+               goto err;
+       }
 
        mt9v032->crop.left = MT9V032_COLUMN_START_DEF;
        mt9v032->crop.top = MT9V032_ROW_START_DEF;
@@ -1016,7 +1070,6 @@ static int mt9v032_remove(struct i2c_client *client)
 
        v4l2_async_unregister_subdev(subdev);
        v4l2_ctrl_handler_free(&mt9v032->ctrls);
-       v4l2_device_unregister_subdev(subdev);
        media_entity_cleanup(&subdev->entity);
 
        return 0;
@@ -1035,9 +1088,25 @@ static const struct i2c_device_id mt9v032_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, mt9v032_id);
 
+#if IS_ENABLED(CONFIG_OF)
+static const struct of_device_id mt9v032_of_match[] = {
+       { .compatible = "aptina,mt9v022" },
+       { .compatible = "aptina,mt9v022m" },
+       { .compatible = "aptina,mt9v024" },
+       { .compatible = "aptina,mt9v024m" },
+       { .compatible = "aptina,mt9v032" },
+       { .compatible = "aptina,mt9v032m" },
+       { .compatible = "aptina,mt9v034" },
+       { .compatible = "aptina,mt9v034m" },
+       { /* Sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mt9v032_of_match);
+#endif
+
 static struct i2c_driver mt9v032_driver = {
        .driver = {
                .name = "mt9v032",
+               .of_match_table = of_match_ptr(mt9v032_of_match),
        },
        .probe          = mt9v032_probe,
        .remove         = mt9v032_remove,
index 00c7b26f48239f325cf1b5cbf53c58339ace6fe3..f197b6cbd4075431d3921b838edb80eac25c358e 100644 (file)
@@ -492,7 +492,7 @@ unlock:
 }
 
 static int noon010_enum_mbus_code(struct v4l2_subdev *sd,
-                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_pad_config *cfg,
                                  struct v4l2_subdev_mbus_code_enum *code)
 {
        if (code->index >= ARRAY_SIZE(noon010_formats))
@@ -502,15 +502,16 @@ static int noon010_enum_mbus_code(struct v4l2_subdev *sd,
        return 0;
 }
 
-static int noon010_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int noon010_get_fmt(struct v4l2_subdev *sd,
+                          struct v4l2_subdev_pad_config *cfg,
                           struct v4l2_subdev_format *fmt)
 {
        struct noon010_info *info = to_noon010(sd);
        struct v4l2_mbus_framefmt *mf;
 
        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-               if (fh) {
-                       mf = v4l2_subdev_get_try_format(fh, 0);
+               if (cfg) {
+                       mf = v4l2_subdev_get_try_format(sd, cfg, 0);
                        fmt->format = *mf;
                }
                return 0;
@@ -542,7 +543,7 @@ static const struct noon010_format *noon010_try_fmt(struct v4l2_subdev *sd,
        return &noon010_formats[i];
 }
 
-static int noon010_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int noon010_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                           struct v4l2_subdev_format *fmt)
 {
        struct noon010_info *info = to_noon010(sd);
@@ -557,8 +558,8 @@ static int noon010_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        fmt->format.field = V4L2_FIELD_NONE;
 
        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-               if (fh) {
-                       mf = v4l2_subdev_get_try_format(fh, 0);
+               if (cfg) {
+                       mf = v4l2_subdev_get_try_format(sd, cfg, 0);
                        *mf = fmt->format;
                }
                return 0;
@@ -640,7 +641,7 @@ static int noon010_log_status(struct v4l2_subdev *sd)
 
 static int noon010_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 {
-       struct v4l2_mbus_framefmt *mf = v4l2_subdev_get_try_format(fh, 0);
+       struct v4l2_mbus_framefmt *mf = v4l2_subdev_get_try_format(sd, fh->pad, 0);
 
        mf->width = noon010_sizes[0].width;
        mf->height = noon010_sizes[0].height;
diff --git a/drivers/media/i2c/ov2659.c b/drivers/media/i2c/ov2659.c
new file mode 100644 (file)
index 0000000..edebd11
--- /dev/null
@@ -0,0 +1,1509 @@
+/*
+ * Omnivision OV2659 CMOS Image Sensor driver
+ *
+ * Copyright (C) 2015 Texas Instruments, Inc.
+ *
+ * Benoit Parrot <bparrot@ti.com>
+ * Lad, Prabhakar <prabhakar.csengg@gmail.com>
+ *
+ * This program is free software; you may 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.
+ *
+ * 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 <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/media.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_graph.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/videodev2.h>
+
+#include <media/media-entity.h>
+#include <media/ov2659.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-image-sizes.h>
+#include <media/v4l2-mediabus.h>
+#include <media/v4l2-of.h>
+#include <media/v4l2-subdev.h>
+
+#define DRIVER_NAME "ov2659"
+
+/*
+ * OV2659 register definitions
+ */
+#define REG_SOFTWARE_STANDBY           0x0100
+#define REG_SOFTWARE_RESET             0x0103
+#define REG_IO_CTRL00                  0x3000
+#define REG_IO_CTRL01                  0x3001
+#define REG_IO_CTRL02                  0x3002
+#define REG_OUTPUT_VALUE00             0x3008
+#define REG_OUTPUT_VALUE01             0x3009
+#define REG_OUTPUT_VALUE02             0x300d
+#define REG_OUTPUT_SELECT00            0x300e
+#define REG_OUTPUT_SELECT01            0x300f
+#define REG_OUTPUT_SELECT02            0x3010
+#define REG_OUTPUT_DRIVE               0x3011
+#define REG_INPUT_READOUT00            0x302d
+#define REG_INPUT_READOUT01            0x302e
+#define REG_INPUT_READOUT02            0x302f
+
+#define REG_SC_PLL_CTRL0               0x3003
+#define REG_SC_PLL_CTRL1               0x3004
+#define REG_SC_PLL_CTRL2               0x3005
+#define REG_SC_PLL_CTRL3               0x3006
+#define REG_SC_CHIP_ID_H               0x300a
+#define REG_SC_CHIP_ID_L               0x300b
+#define REG_SC_PWC                     0x3014
+#define REG_SC_CLKRST0                 0x301a
+#define REG_SC_CLKRST1                 0x301b
+#define REG_SC_CLKRST2                 0x301c
+#define REG_SC_CLKRST3                 0x301d
+#define REG_SC_SUB_ID                  0x302a
+#define REG_SC_SCCB_ID                 0x302b
+
+#define REG_GROUP_ADDRESS_00           0x3200
+#define REG_GROUP_ADDRESS_01           0x3201
+#define REG_GROUP_ADDRESS_02           0x3202
+#define REG_GROUP_ADDRESS_03           0x3203
+#define REG_GROUP_ACCESS               0x3208
+
+#define REG_AWB_R_GAIN_H               0x3400
+#define REG_AWB_R_GAIN_L               0x3401
+#define REG_AWB_G_GAIN_H               0x3402
+#define REG_AWB_G_GAIN_L               0x3403
+#define REG_AWB_B_GAIN_H               0x3404
+#define REG_AWB_B_GAIN_L               0x3405
+#define REG_AWB_MANUAL_CONTROL         0x3406
+
+#define REG_TIMING_HS_H                        0x3800
+#define REG_TIMING_HS_L                        0x3801
+#define REG_TIMING_VS_H                        0x3802
+#define REG_TIMING_VS_L                        0x3803
+#define REG_TIMING_HW_H                        0x3804
+#define REG_TIMING_HW_L                        0x3805
+#define REG_TIMING_VH_H                        0x3806
+#define REG_TIMING_VH_L                        0x3807
+#define REG_TIMING_DVPHO_H             0x3808
+#define REG_TIMING_DVPHO_L             0x3809
+#define REG_TIMING_DVPVO_H             0x380a
+#define REG_TIMING_DVPVO_L             0x380b
+#define REG_TIMING_HTS_H               0x380c
+#define REG_TIMING_HTS_L               0x380d
+#define REG_TIMING_VTS_H               0x380e
+#define REG_TIMING_VTS_L               0x380f
+#define REG_TIMING_HOFFS_H             0x3810
+#define REG_TIMING_HOFFS_L             0x3811
+#define REG_TIMING_VOFFS_H             0x3812
+#define REG_TIMING_VOFFS_L             0x3813
+#define REG_TIMING_XINC                        0x3814
+#define REG_TIMING_YINC                        0x3815
+#define REG_TIMING_VERT_FORMAT         0x3820
+#define REG_TIMING_HORIZ_FORMAT                0x3821
+
+#define REG_FORMAT_CTRL00              0x4300
+
+#define REG_VFIFO_READ_START_H         0x4608
+#define REG_VFIFO_READ_START_L         0x4609
+
+#define REG_DVP_CTRL02                 0x4708
+
+#define REG_ISP_CTRL00                 0x5000
+#define REG_ISP_CTRL01                 0x5001
+#define REG_ISP_CTRL02                 0x5002
+
+#define REG_LENC_RED_X0_H              0x500c
+#define REG_LENC_RED_X0_L              0x500d
+#define REG_LENC_RED_Y0_H              0x500e
+#define REG_LENC_RED_Y0_L              0x500f
+#define REG_LENC_RED_A1                        0x5010
+#define REG_LENC_RED_B1                        0x5011
+#define REG_LENC_RED_A2_B2             0x5012
+#define REG_LENC_GREEN_X0_H            0x5013
+#define REG_LENC_GREEN_X0_L            0x5014
+#define REG_LENC_GREEN_Y0_H            0x5015
+#define REG_LENC_GREEN_Y0_L            0x5016
+#define REG_LENC_GREEN_A1              0x5017
+#define REG_LENC_GREEN_B1              0x5018
+#define REG_LENC_GREEN_A2_B2           0x5019
+#define REG_LENC_BLUE_X0_H             0x501a
+#define REG_LENC_BLUE_X0_L             0x501b
+#define REG_LENC_BLUE_Y0_H             0x501c
+#define REG_LENC_BLUE_Y0_L             0x501d
+#define REG_LENC_BLUE_A1               0x501e
+#define REG_LENC_BLUE_B1               0x501f
+#define REG_LENC_BLUE_A2_B2            0x5020
+
+#define REG_AWB_CTRL00                 0x5035
+#define REG_AWB_CTRL01                 0x5036
+#define REG_AWB_CTRL02                 0x5037
+#define REG_AWB_CTRL03                 0x5038
+#define REG_AWB_CTRL04                 0x5039
+#define REG_AWB_LOCAL_LIMIT            0x503a
+#define REG_AWB_CTRL12                 0x5049
+#define REG_AWB_CTRL13                 0x504a
+#define REG_AWB_CTRL14                 0x504b
+
+#define REG_SHARPENMT_THRESH1          0x5064
+#define REG_SHARPENMT_THRESH2          0x5065
+#define REG_SHARPENMT_OFFSET1          0x5066
+#define REG_SHARPENMT_OFFSET2          0x5067
+#define REG_DENOISE_THRESH1            0x5068
+#define REG_DENOISE_THRESH2            0x5069
+#define REG_DENOISE_OFFSET1            0x506a
+#define REG_DENOISE_OFFSET2            0x506b
+#define REG_SHARPEN_THRESH1            0x506c
+#define REG_SHARPEN_THRESH2            0x506d
+#define REG_CIP_CTRL00                 0x506e
+#define REG_CIP_CTRL01                 0x506f
+
+#define REG_CMX_SIGN                   0x5079
+#define REG_CMX_MISC_CTRL              0x507a
+
+#define REG_PRE_ISP_CTRL00             0x50a0
+#define TEST_PATTERN_ENABLE            BIT(7)
+#define VERTICAL_COLOR_BAR_MASK                0x53
+
+#define REG_NULL                       0x0000  /* Array end token */
+
+#define OV265X_ID(_msb, _lsb)          ((_msb) << 8 | (_lsb))
+#define OV2659_ID                      0x2656
+
+struct sensor_register {
+       u16 addr;
+       u8 value;
+};
+
+struct ov2659_framesize {
+       u16 width;
+       u16 height;
+       u16 max_exp_lines;
+       const struct sensor_register *regs;
+};
+
+struct ov2659_pll_ctrl {
+       u8 ctrl1;
+       u8 ctrl2;
+       u8 ctrl3;
+};
+
+struct ov2659_pixfmt {
+       u32 code;
+       /* Output format Register Value (REG_FORMAT_CTRL00) */
+       struct sensor_register *format_ctrl_regs;
+};
+
+struct pll_ctrl_reg {
+       unsigned int div;
+       unsigned char reg;
+};
+
+struct ov2659 {
+       struct v4l2_subdev sd;
+       struct media_pad pad;
+       struct v4l2_mbus_framefmt format;
+       unsigned int xvclk_frequency;
+       const struct ov2659_platform_data *pdata;
+       struct mutex lock;
+       struct i2c_client *client;
+       struct v4l2_ctrl_handler ctrls;
+       struct v4l2_ctrl *link_frequency;
+       const struct ov2659_framesize *frame_size;
+       struct sensor_register *format_ctrl_regs;
+       struct ov2659_pll_ctrl pll;
+       int streaming;
+};
+
+static const struct sensor_register ov2659_init_regs[] = {
+       { REG_IO_CTRL00, 0x03 },
+       { REG_IO_CTRL01, 0xff },
+       { REG_IO_CTRL02, 0xe0 },
+       { 0x3633, 0x3d },
+       { 0x3620, 0x02 },
+       { 0x3631, 0x11 },
+       { 0x3612, 0x04 },
+       { 0x3630, 0x20 },
+       { 0x4702, 0x02 },
+       { 0x370c, 0x34 },
+       { REG_TIMING_HS_H, 0x00 },
+       { REG_TIMING_HS_L, 0x00 },
+       { REG_TIMING_VS_H, 0x00 },
+       { REG_TIMING_VS_L, 0x00 },
+       { REG_TIMING_HW_H, 0x06 },
+       { REG_TIMING_HW_L, 0x5f },
+       { REG_TIMING_VH_H, 0x04 },
+       { REG_TIMING_VH_L, 0xb7 },
+       { REG_TIMING_DVPHO_H, 0x03 },
+       { REG_TIMING_DVPHO_L, 0x20 },
+       { REG_TIMING_DVPVO_H, 0x02 },
+       { REG_TIMING_DVPVO_L, 0x58 },
+       { REG_TIMING_HTS_H, 0x05 },
+       { REG_TIMING_HTS_L, 0x14 },
+       { REG_TIMING_VTS_H, 0x02 },
+       { REG_TIMING_VTS_L, 0x68 },
+       { REG_TIMING_HOFFS_L, 0x08 },
+       { REG_TIMING_VOFFS_L, 0x02 },
+       { REG_TIMING_XINC, 0x31 },
+       { REG_TIMING_YINC, 0x31 },
+       { 0x3a02, 0x02 },
+       { 0x3a03, 0x68 },
+       { 0x3a08, 0x00 },
+       { 0x3a09, 0x5c },
+       { 0x3a0a, 0x00 },
+       { 0x3a0b, 0x4d },
+       { 0x3a0d, 0x08 },
+       { 0x3a0e, 0x06 },
+       { 0x3a14, 0x02 },
+       { 0x3a15, 0x28 },
+       { REG_DVP_CTRL02, 0x01 },
+       { 0x3623, 0x00 },
+       { 0x3634, 0x76 },
+       { 0x3701, 0x44 },
+       { 0x3702, 0x18 },
+       { 0x3703, 0x24 },
+       { 0x3704, 0x24 },
+       { 0x3705, 0x0c },
+       { REG_TIMING_VERT_FORMAT, 0x81 },
+       { REG_TIMING_HORIZ_FORMAT, 0x01 },
+       { 0x370a, 0x52 },
+       { REG_VFIFO_READ_START_H, 0x00 },
+       { REG_VFIFO_READ_START_L, 0x80 },
+       { REG_FORMAT_CTRL00, 0x30 },
+       { 0x5086, 0x02 },
+       { REG_ISP_CTRL00, 0xfb },
+       { REG_ISP_CTRL01, 0x1f },
+       { REG_ISP_CTRL02, 0x00 },
+       { 0x5025, 0x0e },
+       { 0x5026, 0x18 },
+       { 0x5027, 0x34 },
+       { 0x5028, 0x4c },
+       { 0x5029, 0x62 },
+       { 0x502a, 0x74 },
+       { 0x502b, 0x85 },
+       { 0x502c, 0x92 },
+       { 0x502d, 0x9e },
+       { 0x502e, 0xb2 },
+       { 0x502f, 0xc0 },
+       { 0x5030, 0xcc },
+       { 0x5031, 0xe0 },
+       { 0x5032, 0xee },
+       { 0x5033, 0xf6 },
+       { 0x5034, 0x11 },
+       { 0x5070, 0x1c },
+       { 0x5071, 0x5b },
+       { 0x5072, 0x05 },
+       { 0x5073, 0x20 },
+       { 0x5074, 0x94 },
+       { 0x5075, 0xb4 },
+       { 0x5076, 0xb4 },
+       { 0x5077, 0xaf },
+       { 0x5078, 0x05 },
+       { REG_CMX_SIGN, 0x98 },
+       { REG_CMX_MISC_CTRL, 0x21 },
+       { REG_AWB_CTRL00, 0x6a },
+       { REG_AWB_CTRL01, 0x11 },
+       { REG_AWB_CTRL02, 0x92 },
+       { REG_AWB_CTRL03, 0x21 },
+       { REG_AWB_CTRL04, 0xe1 },
+       { REG_AWB_LOCAL_LIMIT, 0x01 },
+       { 0x503c, 0x05 },
+       { 0x503d, 0x08 },
+       { 0x503e, 0x08 },
+       { 0x503f, 0x64 },
+       { 0x5040, 0x58 },
+       { 0x5041, 0x2a },
+       { 0x5042, 0xc5 },
+       { 0x5043, 0x2e },
+       { 0x5044, 0x3a },
+       { 0x5045, 0x3c },
+       { 0x5046, 0x44 },
+       { 0x5047, 0xf8 },
+       { 0x5048, 0x08 },
+       { REG_AWB_CTRL12, 0x70 },
+       { REG_AWB_CTRL13, 0xf0 },
+       { REG_AWB_CTRL14, 0xf0 },
+       { REG_LENC_RED_X0_H, 0x03 },
+       { REG_LENC_RED_X0_L, 0x20 },
+       { REG_LENC_RED_Y0_H, 0x02 },
+       { REG_LENC_RED_Y0_L, 0x5c },
+       { REG_LENC_RED_A1, 0x48 },
+       { REG_LENC_RED_B1, 0x00 },
+       { REG_LENC_RED_A2_B2, 0x66 },
+       { REG_LENC_GREEN_X0_H, 0x03 },
+       { REG_LENC_GREEN_X0_L, 0x30 },
+       { REG_LENC_GREEN_Y0_H, 0x02 },
+       { REG_LENC_GREEN_Y0_L, 0x7c },
+       { REG_LENC_GREEN_A1, 0x40 },
+       { REG_LENC_GREEN_B1, 0x00 },
+       { REG_LENC_GREEN_A2_B2, 0x66 },
+       { REG_LENC_BLUE_X0_H, 0x03 },
+       { REG_LENC_BLUE_X0_L, 0x10 },
+       { REG_LENC_BLUE_Y0_H, 0x02 },
+       { REG_LENC_BLUE_Y0_L, 0x7c },
+       { REG_LENC_BLUE_A1, 0x3a },
+       { REG_LENC_BLUE_B1, 0x00 },
+       { REG_LENC_BLUE_A2_B2, 0x66 },
+       { REG_CIP_CTRL00, 0x44 },
+       { REG_SHARPENMT_THRESH1, 0x08 },
+       { REG_SHARPENMT_THRESH2, 0x10 },
+       { REG_SHARPENMT_OFFSET1, 0x12 },
+       { REG_SHARPENMT_OFFSET2, 0x02 },
+       { REG_SHARPEN_THRESH1, 0x08 },
+       { REG_SHARPEN_THRESH2, 0x10 },
+       { REG_CIP_CTRL01, 0xa6 },
+       { REG_DENOISE_THRESH1, 0x08 },
+       { REG_DENOISE_THRESH2, 0x10 },
+       { REG_DENOISE_OFFSET1, 0x04 },
+       { REG_DENOISE_OFFSET2, 0x12 },
+       { 0x507e, 0x40 },
+       { 0x507f, 0x20 },
+       { 0x507b, 0x02 },
+       { REG_CMX_MISC_CTRL, 0x01 },
+       { 0x5084, 0x0c },
+       { 0x5085, 0x3e },
+       { 0x5005, 0x80 },
+       { 0x3a0f, 0x30 },
+       { 0x3a10, 0x28 },
+       { 0x3a1b, 0x32 },
+       { 0x3a1e, 0x26 },
+       { 0x3a11, 0x60 },
+       { 0x3a1f, 0x14 },
+       { 0x5060, 0x69 },
+       { 0x5061, 0x7d },
+       { 0x5062, 0x7d },
+       { 0x5063, 0x69 },
+       { REG_NULL, 0x00 },
+};
+
+/* 1280X720 720p */
+static struct sensor_register ov2659_720p[] = {
+       { REG_TIMING_HS_H, 0x00 },
+       { REG_TIMING_HS_L, 0xa0 },
+       { REG_TIMING_VS_H, 0x00 },
+       { REG_TIMING_VS_L, 0xf0 },
+       { REG_TIMING_HW_H, 0x05 },
+       { REG_TIMING_HW_L, 0xbf },
+       { REG_TIMING_VH_H, 0x03 },
+       { REG_TIMING_VH_L, 0xcb },
+       { REG_TIMING_DVPHO_H, 0x05 },
+       { REG_TIMING_DVPHO_L, 0x00 },
+       { REG_TIMING_DVPVO_H, 0x02 },
+       { REG_TIMING_DVPVO_L, 0xd0 },
+       { REG_TIMING_HTS_H, 0x06 },
+       { REG_TIMING_HTS_L, 0x4c },
+       { REG_TIMING_VTS_H, 0x02 },
+       { REG_TIMING_VTS_L, 0xe8 },
+       { REG_TIMING_HOFFS_L, 0x10 },
+       { REG_TIMING_VOFFS_L, 0x06 },
+       { REG_TIMING_XINC, 0x11 },
+       { REG_TIMING_YINC, 0x11 },
+       { REG_TIMING_VERT_FORMAT, 0x80 },
+       { REG_TIMING_HORIZ_FORMAT, 0x00 },
+       { 0x3a03, 0xe8 },
+       { 0x3a09, 0x6f },
+       { 0x3a0b, 0x5d },
+       { 0x3a15, 0x9a },
+       { REG_NULL, 0x00 },
+};
+
+/* 1600X1200 UXGA */
+static struct sensor_register ov2659_uxga[] = {
+       { REG_TIMING_HS_H, 0x00 },
+       { REG_TIMING_HS_L, 0x00 },
+       { REG_TIMING_VS_H, 0x00 },
+       { REG_TIMING_VS_L, 0x00 },
+       { REG_TIMING_HW_H, 0x06 },
+       { REG_TIMING_HW_L, 0x5f },
+       { REG_TIMING_VH_H, 0x04 },
+       { REG_TIMING_VH_L, 0xbb },
+       { REG_TIMING_DVPHO_H, 0x06 },
+       { REG_TIMING_DVPHO_L, 0x40 },
+       { REG_TIMING_DVPVO_H, 0x04 },
+       { REG_TIMING_DVPVO_L, 0xb0 },
+       { REG_TIMING_HTS_H, 0x07 },
+       { REG_TIMING_HTS_L, 0x9f },
+       { REG_TIMING_VTS_H, 0x04 },
+       { REG_TIMING_VTS_L, 0xd0 },
+       { REG_TIMING_HOFFS_L, 0x10 },
+       { REG_TIMING_VOFFS_L, 0x06 },
+       { REG_TIMING_XINC, 0x11 },
+       { REG_TIMING_YINC, 0x11 },
+       { 0x3a02, 0x04 },
+       { 0x3a03, 0xd0 },
+       { 0x3a08, 0x00 },
+       { 0x3a09, 0xb8 },
+       { 0x3a0a, 0x00 },
+       { 0x3a0b, 0x9a },
+       { 0x3a0d, 0x08 },
+       { 0x3a0e, 0x06 },
+       { 0x3a14, 0x04 },
+       { 0x3a15, 0x50 },
+       { 0x3623, 0x00 },
+       { 0x3634, 0x44 },
+       { 0x3701, 0x44 },
+       { 0x3702, 0x30 },
+       { 0x3703, 0x48 },
+       { 0x3704, 0x48 },
+       { 0x3705, 0x18 },
+       { REG_TIMING_VERT_FORMAT, 0x80 },
+       { REG_TIMING_HORIZ_FORMAT, 0x00 },
+       { 0x370a, 0x12 },
+       { REG_VFIFO_READ_START_H, 0x00 },
+       { REG_VFIFO_READ_START_L, 0x80 },
+       { REG_ISP_CTRL02, 0x00 },
+       { REG_NULL, 0x00 },
+};
+
+/* 1280X1024 SXGA */
+static struct sensor_register ov2659_sxga[] = {
+       { REG_TIMING_HS_H, 0x00 },
+       { REG_TIMING_HS_L, 0x00 },
+       { REG_TIMING_VS_H, 0x00 },
+       { REG_TIMING_VS_L, 0x00 },
+       { REG_TIMING_HW_H, 0x06 },
+       { REG_TIMING_HW_L, 0x5f },
+       { REG_TIMING_VH_H, 0x04 },
+       { REG_TIMING_VH_L, 0xb7 },
+       { REG_TIMING_DVPHO_H, 0x05 },
+       { REG_TIMING_DVPHO_L, 0x00 },
+       { REG_TIMING_DVPVO_H, 0x04 },
+       { REG_TIMING_DVPVO_L, 0x00 },
+       { REG_TIMING_HTS_H, 0x07 },
+       { REG_TIMING_HTS_L, 0x9c },
+       { REG_TIMING_VTS_H, 0x04 },
+       { REG_TIMING_VTS_L, 0xd0 },
+       { REG_TIMING_HOFFS_L, 0x10 },
+       { REG_TIMING_VOFFS_L, 0x06 },
+       { REG_TIMING_XINC, 0x11 },
+       { REG_TIMING_YINC, 0x11 },
+       { 0x3a02, 0x02 },
+       { 0x3a03, 0x68 },
+       { 0x3a08, 0x00 },
+       { 0x3a09, 0x5c },
+       { 0x3a0a, 0x00 },
+       { 0x3a0b, 0x4d },
+       { 0x3a0d, 0x08 },
+       { 0x3a0e, 0x06 },
+       { 0x3a14, 0x02 },
+       { 0x3a15, 0x28 },
+       { 0x3623, 0x00 },
+       { 0x3634, 0x76 },
+       { 0x3701, 0x44 },
+       { 0x3702, 0x18 },
+       { 0x3703, 0x24 },
+       { 0x3704, 0x24 },
+       { 0x3705, 0x0c },
+       { REG_TIMING_VERT_FORMAT, 0x80 },
+       { REG_TIMING_HORIZ_FORMAT, 0x00 },
+       { 0x370a, 0x52 },
+       { REG_VFIFO_READ_START_H, 0x00 },
+       { REG_VFIFO_READ_START_L, 0x80 },
+       { REG_ISP_CTRL02, 0x00 },
+       { REG_NULL, 0x00 },
+};
+
+/* 1024X768 SXGA */
+static struct sensor_register ov2659_xga[] = {
+       { REG_TIMING_HS_H, 0x00 },
+       { REG_TIMING_HS_L, 0x00 },
+       { REG_TIMING_VS_H, 0x00 },
+       { REG_TIMING_VS_L, 0x00 },
+       { REG_TIMING_HW_H, 0x06 },
+       { REG_TIMING_HW_L, 0x5f },
+       { REG_TIMING_VH_H, 0x04 },
+       { REG_TIMING_VH_L, 0xb7 },
+       { REG_TIMING_DVPHO_H, 0x04 },
+       { REG_TIMING_DVPHO_L, 0x00 },
+       { REG_TIMING_DVPVO_H, 0x03 },
+       { REG_TIMING_DVPVO_L, 0x00 },
+       { REG_TIMING_HTS_H, 0x07 },
+       { REG_TIMING_HTS_L, 0x9c },
+       { REG_TIMING_VTS_H, 0x04 },
+       { REG_TIMING_VTS_L, 0xd0 },
+       { REG_TIMING_HOFFS_L, 0x10 },
+       { REG_TIMING_VOFFS_L, 0x06 },
+       { REG_TIMING_XINC, 0x11 },
+       { REG_TIMING_YINC, 0x11 },
+       { 0x3a02, 0x02 },
+       { 0x3a03, 0x68 },
+       { 0x3a08, 0x00 },
+       { 0x3a09, 0x5c },
+       { 0x3a0a, 0x00 },
+       { 0x3a0b, 0x4d },
+       { 0x3a0d, 0x08 },
+       { 0x3a0e, 0x06 },
+       { 0x3a14, 0x02 },
+       { 0x3a15, 0x28 },
+       { 0x3623, 0x00 },
+       { 0x3634, 0x76 },
+       { 0x3701, 0x44 },
+       { 0x3702, 0x18 },
+       { 0x3703, 0x24 },
+       { 0x3704, 0x24 },
+       { 0x3705, 0x0c },
+       { REG_TIMING_VERT_FORMAT, 0x80 },
+       { REG_TIMING_HORIZ_FORMAT, 0x00 },
+       { 0x370a, 0x52 },
+       { REG_VFIFO_READ_START_H, 0x00 },
+       { REG_VFIFO_READ_START_L, 0x80 },
+       { REG_ISP_CTRL02, 0x00 },
+       { REG_NULL, 0x00 },
+};
+
+/* 800X600 SVGA */
+static struct sensor_register ov2659_svga[] = {
+       { REG_TIMING_HS_H, 0x00 },
+       { REG_TIMING_HS_L, 0x00 },
+       { REG_TIMING_VS_H, 0x00 },
+       { REG_TIMING_VS_L, 0x00 },
+       { REG_TIMING_HW_H, 0x06 },
+       { REG_TIMING_HW_L, 0x5f },
+       { REG_TIMING_VH_H, 0x04 },
+       { REG_TIMING_VH_L, 0xb7 },
+       { REG_TIMING_DVPHO_H, 0x03 },
+       { REG_TIMING_DVPHO_L, 0x20 },
+       { REG_TIMING_DVPVO_H, 0x02 },
+       { REG_TIMING_DVPVO_L, 0x58 },
+       { REG_TIMING_HTS_H, 0x05 },
+       { REG_TIMING_HTS_L, 0x14 },
+       { REG_TIMING_VTS_H, 0x02 },
+       { REG_TIMING_VTS_L, 0x68 },
+       { REG_TIMING_HOFFS_L, 0x08 },
+       { REG_TIMING_VOFFS_L, 0x02 },
+       { REG_TIMING_XINC, 0x31 },
+       { REG_TIMING_YINC, 0x31 },
+       { 0x3a02, 0x02 },
+       { 0x3a03, 0x68 },
+       { 0x3a08, 0x00 },
+       { 0x3a09, 0x5c },
+       { 0x3a0a, 0x00 },
+       { 0x3a0b, 0x4d },
+       { 0x3a0d, 0x08 },
+       { 0x3a0e, 0x06 },
+       { 0x3a14, 0x02 },
+       { 0x3a15, 0x28 },
+       { 0x3623, 0x00 },
+       { 0x3634, 0x76 },
+       { 0x3701, 0x44 },
+       { 0x3702, 0x18 },
+       { 0x3703, 0x24 },
+       { 0x3704, 0x24 },
+       { 0x3705, 0x0c },
+       { REG_TIMING_VERT_FORMAT, 0x81 },
+       { REG_TIMING_HORIZ_FORMAT, 0x01 },
+       { 0x370a, 0x52 },
+       { REG_VFIFO_READ_START_H, 0x00 },
+       { REG_VFIFO_READ_START_L, 0x80 },
+       { REG_ISP_CTRL02, 0x00 },
+       { REG_NULL, 0x00 },
+};
+
+/* 640X480 VGA */
+static struct sensor_register ov2659_vga[] = {
+       { REG_TIMING_HS_H, 0x00 },
+       { REG_TIMING_HS_L, 0x00 },
+       { REG_TIMING_VS_H, 0x00 },
+       { REG_TIMING_VS_L, 0x00 },
+       { REG_TIMING_HW_H, 0x06 },
+       { REG_TIMING_HW_L, 0x5f },
+       { REG_TIMING_VH_H, 0x04 },
+       { REG_TIMING_VH_L, 0xb7 },
+       { REG_TIMING_DVPHO_H, 0x02 },
+       { REG_TIMING_DVPHO_L, 0x80 },
+       { REG_TIMING_DVPVO_H, 0x01 },
+       { REG_TIMING_DVPVO_L, 0xe0 },
+       { REG_TIMING_HTS_H, 0x05 },
+       { REG_TIMING_HTS_L, 0x14 },
+       { REG_TIMING_VTS_H, 0x02 },
+       { REG_TIMING_VTS_L, 0x68 },
+       { REG_TIMING_HOFFS_L, 0x08 },
+       { REG_TIMING_VOFFS_L, 0x02 },
+       { REG_TIMING_XINC, 0x31 },
+       { REG_TIMING_YINC, 0x31 },
+       { 0x3a02, 0x02 },
+       { 0x3a03, 0x68 },
+       { 0x3a08, 0x00 },
+       { 0x3a09, 0x5c },
+       { 0x3a0a, 0x00 },
+       { 0x3a0b, 0x4d },
+       { 0x3a0d, 0x08 },
+       { 0x3a0e, 0x06 },
+       { 0x3a14, 0x02 },
+       { 0x3a15, 0x28 },
+       { 0x3623, 0x00 },
+       { 0x3634, 0x76 },
+       { 0x3701, 0x44 },
+       { 0x3702, 0x18 },
+       { 0x3703, 0x24 },
+       { 0x3704, 0x24 },
+       { 0x3705, 0x0c },
+       { REG_TIMING_VERT_FORMAT, 0x81 },
+       { REG_TIMING_HORIZ_FORMAT, 0x01 },
+       { 0x370a, 0x52 },
+       { REG_VFIFO_READ_START_H, 0x00 },
+       { REG_VFIFO_READ_START_L, 0x80 },
+       { REG_ISP_CTRL02, 0x10 },
+       { REG_NULL, 0x00 },
+};
+
+/* 320X240 QVGA */
+static  struct sensor_register ov2659_qvga[] = {
+       { REG_TIMING_HS_H, 0x00 },
+       { REG_TIMING_HS_L, 0x00 },
+       { REG_TIMING_VS_H, 0x00 },
+       { REG_TIMING_VS_L, 0x00 },
+       { REG_TIMING_HW_H, 0x06 },
+       { REG_TIMING_HW_L, 0x5f },
+       { REG_TIMING_VH_H, 0x04 },
+       { REG_TIMING_VH_L, 0xb7 },
+       { REG_TIMING_DVPHO_H, 0x01 },
+       { REG_TIMING_DVPHO_L, 0x40 },
+       { REG_TIMING_DVPVO_H, 0x00 },
+       { REG_TIMING_DVPVO_L, 0xf0 },
+       { REG_TIMING_HTS_H, 0x05 },
+       { REG_TIMING_HTS_L, 0x14 },
+       { REG_TIMING_VTS_H, 0x02 },
+       { REG_TIMING_VTS_L, 0x68 },
+       { REG_TIMING_HOFFS_L, 0x08 },
+       { REG_TIMING_VOFFS_L, 0x02 },
+       { REG_TIMING_XINC, 0x31 },
+       { REG_TIMING_YINC, 0x31 },
+       { 0x3a02, 0x02 },
+       { 0x3a03, 0x68 },
+       { 0x3a08, 0x00 },
+       { 0x3a09, 0x5c },
+       { 0x3a0a, 0x00 },
+       { 0x3a0b, 0x4d },
+       { 0x3a0d, 0x08 },
+       { 0x3a0e, 0x06 },
+       { 0x3a14, 0x02 },
+       { 0x3a15, 0x28 },
+       { 0x3623, 0x00 },
+       { 0x3634, 0x76 },
+       { 0x3701, 0x44 },
+       { 0x3702, 0x18 },
+       { 0x3703, 0x24 },
+       { 0x3704, 0x24 },
+       { 0x3705, 0x0c },
+       { REG_TIMING_VERT_FORMAT, 0x81 },
+       { REG_TIMING_HORIZ_FORMAT, 0x01 },
+       { 0x370a, 0x52 },
+       { REG_VFIFO_READ_START_H, 0x00 },
+       { REG_VFIFO_READ_START_L, 0x80 },
+       { REG_ISP_CTRL02, 0x10 },
+       { REG_NULL, 0x00 },
+};
+
+static const struct pll_ctrl_reg ctrl3[] = {
+       { 1, 0x00 },
+       { 2, 0x02 },
+       { 3, 0x03 },
+       { 4, 0x06 },
+       { 6, 0x0d },
+       { 8, 0x0e },
+       { 12, 0x0f },
+       { 16, 0x12 },
+       { 24, 0x13 },
+       { 32, 0x16 },
+       { 48, 0x1b },
+       { 64, 0x1e },
+       { 96, 0x1f },
+       { 0, 0x00 },
+};
+
+static const struct pll_ctrl_reg ctrl1[] = {
+       { 2, 0x10 },
+       { 4, 0x20 },
+       { 6, 0x30 },
+       { 8, 0x40 },
+       { 10, 0x50 },
+       { 12, 0x60 },
+       { 14, 0x70 },
+       { 16, 0x80 },
+       { 18, 0x90 },
+       { 20, 0xa0 },
+       { 22, 0xb0 },
+       { 24, 0xc0 },
+       { 26, 0xd0 },
+       { 28, 0xe0 },
+       { 30, 0xf0 },
+       { 0, 0x00 },
+};
+
+static const struct ov2659_framesize ov2659_framesizes[] = {
+       { /* QVGA */
+               .width          = 320,
+               .height         = 240,
+               .regs           = ov2659_qvga,
+               .max_exp_lines  = 248,
+       }, { /* VGA */
+               .width          = 640,
+               .height         = 480,
+               .regs           = ov2659_vga,
+               .max_exp_lines  = 498,
+       }, { /* SVGA */
+               .width          = 800,
+               .height         = 600,
+               .regs           = ov2659_svga,
+               .max_exp_lines  = 498,
+       }, { /* XGA */
+               .width          = 1024,
+               .height         = 768,
+               .regs           = ov2659_xga,
+               .max_exp_lines  = 498,
+       }, { /* 720P */
+               .width          = 1280,
+               .height         = 720,
+               .regs           = ov2659_720p,
+               .max_exp_lines  = 498,
+       }, { /* SXGA */
+               .width          = 1280,
+               .height         = 1024,
+               .regs           = ov2659_sxga,
+               .max_exp_lines  = 1048,
+       }, { /* UXGA */
+               .width          = 1600,
+               .height         = 1200,
+               .regs           = ov2659_uxga,
+               .max_exp_lines  = 498,
+       },
+};
+
+/* YUV422 YUYV*/
+static struct sensor_register ov2659_format_yuyv[] = {
+       { REG_FORMAT_CTRL00, 0x30 },
+       { REG_NULL, 0x0 },
+};
+
+/* YUV422 UYVY  */
+static struct sensor_register ov2659_format_uyvy[] = {
+       { REG_FORMAT_CTRL00, 0x32 },
+       { REG_NULL, 0x0 },
+};
+
+/* Raw Bayer BGGR */
+static struct sensor_register ov2659_format_bggr[] = {
+       { REG_FORMAT_CTRL00, 0x00 },
+       { REG_NULL, 0x0 },
+};
+
+/* RGB565 */
+static struct sensor_register ov2659_format_rgb565[] = {
+       { REG_FORMAT_CTRL00, 0x60 },
+       { REG_NULL, 0x0 },
+};
+
+static const struct ov2659_pixfmt ov2659_formats[] = {
+       {
+               .code = MEDIA_BUS_FMT_YUYV8_2X8,
+               .format_ctrl_regs = ov2659_format_yuyv,
+       }, {
+               .code = MEDIA_BUS_FMT_UYVY8_2X8,
+               .format_ctrl_regs = ov2659_format_uyvy,
+       }, {
+               .code = MEDIA_BUS_FMT_RGB565_2X8_BE,
+               .format_ctrl_regs = ov2659_format_rgb565,
+       }, {
+               .code = MEDIA_BUS_FMT_SBGGR8_1X8,
+               .format_ctrl_regs = ov2659_format_bggr,
+       },
+};
+
+static inline struct ov2659 *to_ov2659(struct v4l2_subdev *sd)
+{
+       return container_of(sd, struct ov2659, sd);
+}
+
+/* sensor register write */
+static int ov2659_write(struct i2c_client *client, u16 reg, u8 val)
+{
+       struct i2c_msg msg;
+       u8 buf[3];
+       int ret;
+
+       buf[0] = reg >> 8;
+       buf[1] = reg & 0xFF;
+       buf[2] = val;
+
+       msg.addr = client->addr;
+       msg.flags = client->flags;
+       msg.buf = buf;
+       msg.len = sizeof(buf);
+
+       ret = i2c_transfer(client->adapter, &msg, 1);
+       if (ret >= 0)
+               return 0;
+
+       dev_dbg(&client->dev,
+               "ov2659 write reg(0x%x val:0x%x) failed !\n", reg, val);
+
+       return ret;
+}
+
+/* sensor register read */
+static int ov2659_read(struct i2c_client *client, u16 reg, u8 *val)
+{
+       struct i2c_msg msg[2];
+       u8 buf[2];
+       int ret;
+
+       buf[0] = reg >> 8;
+       buf[1] = reg & 0xFF;
+
+       msg[0].addr = client->addr;
+       msg[0].flags = client->flags;
+       msg[0].buf = buf;
+       msg[0].len = sizeof(buf);
+
+       msg[1].addr = client->addr;
+       msg[1].flags = client->flags | I2C_M_RD;
+       msg[1].buf = buf;
+       msg[1].len = 1;
+
+       ret = i2c_transfer(client->adapter, msg, 2);
+       if (ret >= 0) {
+               *val = buf[0];
+               return 0;
+       }
+
+       dev_dbg(&client->dev,
+               "ov2659 read reg(0x%x val:0x%x) failed !\n", reg, *val);
+
+       return ret;
+}
+
+static int ov2659_write_array(struct i2c_client *client,
+                             const struct sensor_register *regs)
+{
+       int i, ret = 0;
+
+       for (i = 0; ret == 0 && regs[i].addr; i++)
+               ret = ov2659_write(client, regs[i].addr, regs[i].value);
+
+       return ret;
+}
+
+static void ov2659_pll_calc_params(struct ov2659 *ov2659)
+{
+       const struct ov2659_platform_data *pdata = ov2659->pdata;
+       u8 ctrl1_reg = 0, ctrl2_reg = 0, ctrl3_reg = 0;
+       struct i2c_client *client = ov2659->client;
+       unsigned int desired = pdata->link_frequency;
+       u32 s_prediv = 1, s_postdiv = 1, s_mult = 1;
+       u32 prediv, postdiv, mult;
+       u32 bestdelta = -1;
+       u32 delta, actual;
+       int i, j;
+
+       for (i = 0; ctrl1[i].div != 0; i++) {
+               postdiv = ctrl1[i].div;
+               for (j = 0; ctrl3[j].div != 0; j++) {
+                       prediv = ctrl3[j].div;
+                       for (mult = 1; mult <= 63; mult++) {
+                               actual  = ov2659->xvclk_frequency;
+                               actual *= mult;
+                               actual /= prediv;
+                               actual /= postdiv;
+                               delta = actual - desired;
+                               delta = abs(delta);
+
+                               if ((delta < bestdelta) || (bestdelta == -1)) {
+                                       bestdelta = delta;
+                                       s_mult    = mult;
+                                       s_prediv  = prediv;
+                                       s_postdiv = postdiv;
+                                       ctrl1_reg = ctrl1[i].reg;
+                                       ctrl2_reg = mult;
+                                       ctrl3_reg = ctrl3[j].reg;
+                               }
+                       }
+               }
+       }
+
+       ov2659->pll.ctrl1 = ctrl1_reg;
+       ov2659->pll.ctrl2 = ctrl2_reg;
+       ov2659->pll.ctrl3 = ctrl3_reg;
+
+       dev_dbg(&client->dev,
+               "Actual reg config: ctrl1_reg: %02x ctrl2_reg: %02x ctrl3_reg: %02x\n",
+               ctrl1_reg, ctrl2_reg, ctrl3_reg);
+}
+
+static int ov2659_set_pixel_clock(struct ov2659 *ov2659)
+{
+       struct i2c_client *client = ov2659->client;
+       struct sensor_register pll_regs[] = {
+               {REG_SC_PLL_CTRL1, ov2659->pll.ctrl1},
+               {REG_SC_PLL_CTRL2, ov2659->pll.ctrl2},
+               {REG_SC_PLL_CTRL3, ov2659->pll.ctrl3},
+               {REG_NULL, 0x00},
+       };
+
+       dev_dbg(&client->dev, "%s\n", __func__);
+
+       return ov2659_write_array(client, pll_regs);
+};
+
+static void ov2659_get_default_format(struct v4l2_mbus_framefmt *format)
+{
+       format->width = ov2659_framesizes[2].width;
+       format->height = ov2659_framesizes[2].height;
+       format->colorspace = V4L2_COLORSPACE_SRGB;
+       format->code = ov2659_formats[0].code;
+       format->field = V4L2_FIELD_NONE;
+}
+
+static void ov2659_set_streaming(struct ov2659 *ov2659, int on)
+{
+       struct i2c_client *client = ov2659->client;
+       int ret;
+
+       on = !!on;
+
+       dev_dbg(&client->dev, "%s: on: %d\n", __func__, on);
+
+       ret = ov2659_write(client, REG_SOFTWARE_STANDBY, on);
+       if (ret)
+               dev_err(&client->dev, "ov2659 soft standby failed\n");
+}
+
+static int ov2659_init(struct v4l2_subdev *sd, u32 val)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+       return ov2659_write_array(client, ov2659_init_regs);
+}
+
+/*
+ * V4L2 subdev video and pad level operations
+ */
+
+static int ov2659_enum_mbus_code(struct v4l2_subdev *sd,
+                                struct v4l2_subdev_pad_config *cfg,
+                                struct v4l2_subdev_mbus_code_enum *code)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+       dev_dbg(&client->dev, "%s:\n", __func__);
+
+       if (code->index >= ARRAY_SIZE(ov2659_formats))
+               return -EINVAL;
+
+       code->code = ov2659_formats[code->index].code;
+
+       return 0;
+}
+
+static int ov2659_enum_frame_sizes(struct v4l2_subdev *sd,
+                                  struct v4l2_subdev_pad_config *cfg,
+                                  struct v4l2_subdev_frame_size_enum *fse)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       int i = ARRAY_SIZE(ov2659_formats);
+
+       dev_dbg(&client->dev, "%s:\n", __func__);
+
+       if (fse->index >= ARRAY_SIZE(ov2659_framesizes))
+               return -EINVAL;
+
+       while (--i)
+               if (fse->code == ov2659_formats[i].code)
+                       break;
+
+       fse->code = ov2659_formats[i].code;
+
+       fse->min_width  = ov2659_framesizes[fse->index].width;
+       fse->max_width  = fse->min_width;
+       fse->max_height = ov2659_framesizes[fse->index].height;
+       fse->min_height = fse->max_height;
+
+       return 0;
+}
+
+static int ov2659_get_fmt(struct v4l2_subdev *sd,
+                         struct v4l2_subdev_pad_config *cfg,
+                         struct v4l2_subdev_format *fmt)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct ov2659 *ov2659 = to_ov2659(sd);
+       struct v4l2_mbus_framefmt *mf;
+
+       dev_dbg(&client->dev, "ov2659_get_fmt\n");
+
+       if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+               mf = v4l2_subdev_get_try_format(sd, cfg, 0);
+               mutex_lock(&ov2659->lock);
+               fmt->format = *mf;
+               mutex_unlock(&ov2659->lock);
+               return 0;
+       }
+
+       mutex_lock(&ov2659->lock);
+       fmt->format = ov2659->format;
+       mutex_unlock(&ov2659->lock);
+
+       dev_dbg(&client->dev, "ov2659_get_fmt: %x %dx%d\n",
+               ov2659->format.code, ov2659->format.width,
+               ov2659->format.height);
+
+       return 0;
+}
+
+static void __ov2659_try_frame_size(struct v4l2_mbus_framefmt *mf,
+                                   const struct ov2659_framesize **size)
+{
+       const struct ov2659_framesize *fsize = &ov2659_framesizes[0];
+       const struct ov2659_framesize *match = NULL;
+       int i = ARRAY_SIZE(ov2659_framesizes);
+       unsigned int min_err = UINT_MAX;
+
+       while (i--) {
+               int err = abs(fsize->width - mf->width)
+                               + abs(fsize->height - mf->height);
+               if ((err < min_err) && (fsize->regs[0].addr)) {
+                       min_err = err;
+                       match = fsize;
+               }
+               fsize++;
+       }
+
+       if (!match)
+               match = &ov2659_framesizes[2];
+
+       mf->width  = match->width;
+       mf->height = match->height;
+
+       if (size)
+               *size = match;
+}
+
+static int ov2659_set_fmt(struct v4l2_subdev *sd,
+                         struct v4l2_subdev_pad_config *cfg,
+                         struct v4l2_subdev_format *fmt)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       unsigned int index = ARRAY_SIZE(ov2659_formats);
+       struct v4l2_mbus_framefmt *mf = &fmt->format;
+       const struct ov2659_framesize *size = NULL;
+       struct ov2659 *ov2659 = to_ov2659(sd);
+       int ret = 0;
+
+       dev_dbg(&client->dev, "ov2659_set_fmt\n");
+
+       __ov2659_try_frame_size(mf, &size);
+
+       while (--index >= 0)
+               if (ov2659_formats[index].code == mf->code)
+                       break;
+
+       if (index < 0)
+               return -EINVAL;
+
+       mf->colorspace = V4L2_COLORSPACE_SRGB;
+       mf->code = ov2659_formats[index].code;
+       mf->field = V4L2_FIELD_NONE;
+
+       mutex_lock(&ov2659->lock);
+
+       if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+               mf = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
+               *mf = fmt->format;
+       } else {
+               s64 val;
+
+               if (ov2659->streaming) {
+                       mutex_unlock(&ov2659->lock);
+                       return -EBUSY;
+               }
+
+               ov2659->frame_size = size;
+               ov2659->format = fmt->format;
+               ov2659->format_ctrl_regs =
+                       ov2659_formats[index].format_ctrl_regs;
+
+               if (ov2659->format.code != MEDIA_BUS_FMT_SBGGR8_1X8)
+                       val = ov2659->pdata->link_frequency / 2;
+               else
+                       val = ov2659->pdata->link_frequency;
+
+               ret = v4l2_ctrl_s_ctrl_int64(ov2659->link_frequency, val);
+               if (ret < 0)
+                       dev_warn(&client->dev,
+                                "failed to set link_frequency rate (%d)\n",
+                                ret);
+       }
+
+       mutex_unlock(&ov2659->lock);
+       return ret;
+}
+
+static int ov2659_set_frame_size(struct ov2659 *ov2659)
+{
+       struct i2c_client *client = ov2659->client;
+
+       dev_dbg(&client->dev, "%s\n", __func__);
+
+       return ov2659_write_array(ov2659->client, ov2659->frame_size->regs);
+}
+
+static int ov2659_set_format(struct ov2659 *ov2659)
+{
+       struct i2c_client *client = ov2659->client;
+
+       dev_dbg(&client->dev, "%s\n", __func__);
+
+       return ov2659_write_array(ov2659->client, ov2659->format_ctrl_regs);
+}
+
+static int ov2659_s_stream(struct v4l2_subdev *sd, int on)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct ov2659 *ov2659 = to_ov2659(sd);
+       int ret = 0;
+
+       dev_dbg(&client->dev, "%s: on: %d\n", __func__, on);
+
+       mutex_lock(&ov2659->lock);
+
+       on = !!on;
+
+       if (ov2659->streaming == on)
+               goto unlock;
+
+       if (!on) {
+               /* Stop Streaming Sequence */
+               ov2659_set_streaming(ov2659, 0);
+               ov2659->streaming = on;
+               goto unlock;
+       }
+
+       ov2659_set_pixel_clock(ov2659);
+       ov2659_set_frame_size(ov2659);
+       ov2659_set_format(ov2659);
+       ov2659_set_streaming(ov2659, 1);
+       ov2659->streaming = on;
+
+unlock:
+       mutex_unlock(&ov2659->lock);
+       return ret;
+}
+
+static int ov2659_set_test_pattern(struct ov2659 *ov2659, int value)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(&ov2659->sd);
+       int ret;
+       u8 val;
+
+       ret = ov2659_read(client, REG_PRE_ISP_CTRL00, &val);
+       if (ret < 0)
+               return ret;
+
+       switch (value) {
+       case 0:
+               val &= ~TEST_PATTERN_ENABLE;
+               break;
+       case 1:
+               val &= VERTICAL_COLOR_BAR_MASK;
+               val |= TEST_PATTERN_ENABLE;
+               break;
+       }
+
+       return ov2659_write(client, REG_PRE_ISP_CTRL00, val);
+}
+
+static int ov2659_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct ov2659 *ov2659 =
+                       container_of(ctrl->handler, struct ov2659, ctrls);
+
+       switch (ctrl->id) {
+       case V4L2_CID_TEST_PATTERN:
+               return ov2659_set_test_pattern(ov2659, ctrl->val);
+       }
+
+       return 0;
+}
+
+static struct v4l2_ctrl_ops ov2659_ctrl_ops = {
+       .s_ctrl = ov2659_s_ctrl,
+};
+
+static const char * const ov2659_test_pattern_menu[] = {
+       "Disabled",
+       "Vertical Color Bars",
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev internal operations
+ */
+
+static int ov2659_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct v4l2_mbus_framefmt *format =
+                               v4l2_subdev_get_try_format(sd, fh->pad, 0);
+
+       dev_dbg(&client->dev, "%s:\n", __func__);
+
+       ov2659_get_default_format(format);
+
+       return 0;
+}
+
+static const struct v4l2_subdev_core_ops ov2659_subdev_core_ops = {
+       .log_status = v4l2_ctrl_subdev_log_status,
+       .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
+       .unsubscribe_event = v4l2_event_subdev_unsubscribe,
+};
+
+static const struct v4l2_subdev_video_ops ov2659_subdev_video_ops = {
+       .s_stream = ov2659_s_stream,
+};
+
+static const struct v4l2_subdev_pad_ops ov2659_subdev_pad_ops = {
+       .enum_mbus_code = ov2659_enum_mbus_code,
+       .enum_frame_size = ov2659_enum_frame_sizes,
+       .get_fmt = ov2659_get_fmt,
+       .set_fmt = ov2659_set_fmt,
+};
+
+static const struct v4l2_subdev_ops ov2659_subdev_ops = {
+       .core  = &ov2659_subdev_core_ops,
+       .video = &ov2659_subdev_video_ops,
+       .pad   = &ov2659_subdev_pad_ops,
+};
+
+static const struct v4l2_subdev_internal_ops ov2659_subdev_internal_ops = {
+       .open = ov2659_open,
+};
+
+static int ov2659_detect(struct v4l2_subdev *sd)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       u8 pid, ver;
+       int ret;
+
+       dev_dbg(&client->dev, "%s:\n", __func__);
+
+       ret = ov2659_write(client, REG_SOFTWARE_RESET, 0x01);
+       if (ret != 0) {
+               dev_err(&client->dev, "Sensor soft reset failed\n");
+               return -ENODEV;
+       }
+       usleep_range(1000, 2000);
+
+       ret = ov2659_init(sd, 0);
+       if (ret < 0)
+               return ret;
+
+       /* Check sensor revision */
+       ret = ov2659_read(client, REG_SC_CHIP_ID_H, &pid);
+       if (!ret)
+               ret = ov2659_read(client, REG_SC_CHIP_ID_L, &ver);
+
+       if (!ret) {
+               unsigned short id;
+
+               id = OV265X_ID(pid, ver);
+               if (id != OV2659_ID)
+                       dev_err(&client->dev,
+                               "Sensor detection failed (%04X, %d)\n",
+                               id, ret);
+               else
+                       dev_info(&client->dev, "Found OV%04X sensor\n", id);
+       }
+
+       return ret;
+}
+
+static struct ov2659_platform_data *
+ov2659_get_pdata(struct i2c_client *client)
+{
+       struct ov2659_platform_data *pdata;
+       struct device_node *endpoint;
+       int ret;
+
+       if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node)
+               return client->dev.platform_data;
+
+       endpoint = of_graph_get_next_endpoint(client->dev.of_node, NULL);
+       if (!endpoint)
+               return NULL;
+
+       pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               goto done;
+
+       ret = of_property_read_u64(endpoint, "link-frequencies",
+                                  &pdata->link_frequency);
+       if (ret) {
+               dev_err(&client->dev, "link-frequencies property not found\n");
+               pdata = NULL;
+       }
+
+done:
+       of_node_put(endpoint);
+       return pdata;
+}
+
+static int ov2659_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
+{
+       const struct ov2659_platform_data *pdata = ov2659_get_pdata(client);
+       struct v4l2_subdev *sd;
+       struct ov2659 *ov2659;
+       struct clk *clk;
+       int ret;
+
+       if (!pdata) {
+               dev_err(&client->dev, "platform data not specified\n");
+               return -EINVAL;
+       }
+
+       ov2659 = devm_kzalloc(&client->dev, sizeof(*ov2659), GFP_KERNEL);
+       if (!ov2659)
+               return -ENOMEM;
+
+       ov2659->pdata = pdata;
+       ov2659->client = client;
+
+       clk = devm_clk_get(&client->dev, "xvclk");
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       ov2659->xvclk_frequency = clk_get_rate(clk);
+       if (ov2659->xvclk_frequency < 6000000 ||
+           ov2659->xvclk_frequency > 27000000)
+               return -EINVAL;
+
+       v4l2_ctrl_handler_init(&ov2659->ctrls, 2);
+       ov2659->link_frequency =
+                       v4l2_ctrl_new_std(&ov2659->ctrls, &ov2659_ctrl_ops,
+                                         V4L2_CID_PIXEL_RATE,
+                                         pdata->link_frequency / 2,
+                                         pdata->link_frequency, 1,
+                                         pdata->link_frequency);
+       v4l2_ctrl_new_std_menu_items(&ov2659->ctrls, &ov2659_ctrl_ops,
+                                    V4L2_CID_TEST_PATTERN,
+                                    ARRAY_SIZE(ov2659_test_pattern_menu) - 1,
+                                    0, 0, ov2659_test_pattern_menu);
+       ov2659->sd.ctrl_handler = &ov2659->ctrls;
+
+       if (ov2659->ctrls.error) {
+               dev_err(&client->dev, "%s: control initialization error %d\n",
+                       __func__, ov2659->ctrls.error);
+               return  ov2659->ctrls.error;
+       }
+
+       sd = &ov2659->sd;
+       client->flags |= I2C_CLIENT_SCCB;
+       v4l2_i2c_subdev_init(sd, client, &ov2659_subdev_ops);
+
+       sd->internal_ops = &ov2659_subdev_internal_ops;
+       sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
+                    V4L2_SUBDEV_FL_HAS_EVENTS;
+
+#if defined(CONFIG_MEDIA_CONTROLLER)
+       ov2659->pad.flags = MEDIA_PAD_FL_SOURCE;
+       sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
+       ret = media_entity_init(&sd->entity, 1, &ov2659->pad, 0);
+       if (ret < 0) {
+               v4l2_ctrl_handler_free(&ov2659->ctrls);
+               return ret;
+       }
+#endif
+
+       mutex_init(&ov2659->lock);
+
+       ov2659_get_default_format(&ov2659->format);
+       ov2659->frame_size = &ov2659_framesizes[2];
+       ov2659->format_ctrl_regs = ov2659_formats[0].format_ctrl_regs;
+
+       ret = ov2659_detect(sd);
+       if (ret < 0)
+               goto error;
+
+       /* Calculate the PLL register value needed */
+       ov2659_pll_calc_params(ov2659);
+
+       ret = v4l2_async_register_subdev(&ov2659->sd);
+       if (ret)
+               goto error;
+
+       dev_info(&client->dev, "%s sensor driver registered !!\n", sd->name);
+
+       return 0;
+
+error:
+       v4l2_ctrl_handler_free(&ov2659->ctrls);
+#if defined(CONFIG_MEDIA_CONTROLLER)
+       media_entity_cleanup(&sd->entity);
+#endif
+       mutex_destroy(&ov2659->lock);
+       return ret;
+}
+
+static int ov2659_remove(struct i2c_client *client)
+{
+       struct v4l2_subdev *sd = i2c_get_clientdata(client);
+       struct ov2659 *ov2659 = to_ov2659(sd);
+
+       v4l2_ctrl_handler_free(&ov2659->ctrls);
+       v4l2_async_unregister_subdev(sd);
+#if defined(CONFIG_MEDIA_CONTROLLER)
+       media_entity_cleanup(&sd->entity);
+#endif
+       mutex_destroy(&ov2659->lock);
+
+       return 0;
+}
+
+static const struct i2c_device_id ov2659_id[] = {
+       { "ov2659", 0 },
+       { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(i2c, ov2659_id);
+
+#if IS_ENABLED(CONFIG_OF)
+static const struct of_device_id ov2659_of_match[] = {
+       { .compatible = "ovti,ov2659", },
+       { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, ov2659_of_match);
+#endif
+
+static struct i2c_driver ov2659_i2c_driver = {
+       .driver = {
+               .name   = DRIVER_NAME,
+               .of_match_table = of_match_ptr(ov2659_of_match),
+       },
+       .probe          = ov2659_probe,
+       .remove         = ov2659_remove,
+       .id_table       = ov2659_id,
+};
+
+module_i2c_driver(ov2659_i2c_driver);
+
+MODULE_AUTHOR("Benoit Parrot <bparrot@ti.com>");
+MODULE_DESCRIPTION("OV2659 CMOS Image Sensor driver");
+MODULE_LICENSE("GPL v2");
index 957927f7a3532c11548abbc1680a63149860cd08..b9847527eb5a3866965b1f15d21be96c8c96f3ad 100644 (file)
@@ -1069,29 +1069,35 @@ static int ov7670_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
 
 static int ov7670_frame_rates[] = { 30, 15, 10, 5, 1 };
 
-static int ov7670_enum_frameintervals(struct v4l2_subdev *sd,
-               struct v4l2_frmivalenum *interval)
+static int ov7670_enum_frame_interval(struct v4l2_subdev *sd,
+                                     struct v4l2_subdev_pad_config *cfg,
+                                     struct v4l2_subdev_frame_interval_enum *fie)
 {
-       if (interval->index >= ARRAY_SIZE(ov7670_frame_rates))
+       if (fie->pad)
                return -EINVAL;
-       interval->type = V4L2_FRMIVAL_TYPE_DISCRETE;
-       interval->discrete.numerator = 1;
-       interval->discrete.denominator = ov7670_frame_rates[interval->index];
+       if (fie->index >= ARRAY_SIZE(ov7670_frame_rates))
+               return -EINVAL;
+       fie->interval.numerator = 1;
+       fie->interval.denominator = ov7670_frame_rates[fie->index];
        return 0;
 }
 
 /*
  * Frame size enumeration
  */
-static int ov7670_enum_framesizes(struct v4l2_subdev *sd,
-               struct v4l2_frmsizeenum *fsize)
+static int ov7670_enum_frame_size(struct v4l2_subdev *sd,
+                                 struct v4l2_subdev_pad_config *cfg,
+                                 struct v4l2_subdev_frame_size_enum *fse)
 {
        struct ov7670_info *info = to_state(sd);
        int i;
        int num_valid = -1;
-       __u32 index = fsize->index;
+       __u32 index = fse->index;
        unsigned int n_win_sizes = info->devtype->n_win_sizes;
 
+       if (fse->pad)
+               return -EINVAL;
+
        /*
         * If a minimum width/height was requested, filter out the capture
         * windows that fall outside that.
@@ -1103,9 +1109,8 @@ static int ov7670_enum_framesizes(struct v4l2_subdev *sd,
                if (info->min_height && win->height < info->min_height)
                        continue;
                if (index == ++num_valid) {
-                       fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
-                       fsize->discrete.width = win->width;
-                       fsize->discrete.height = win->height;
+                       fse->min_width = fse->max_width = win->width;
+                       fse->min_height = fse->max_height = win->height;
                        return 0;
                }
        }
@@ -1485,13 +1490,17 @@ static const struct v4l2_subdev_video_ops ov7670_video_ops = {
        .s_mbus_fmt = ov7670_s_mbus_fmt,
        .s_parm = ov7670_s_parm,
        .g_parm = ov7670_g_parm,
-       .enum_frameintervals = ov7670_enum_frameintervals,
-       .enum_framesizes = ov7670_enum_framesizes,
+};
+
+static const struct v4l2_subdev_pad_ops ov7670_pad_ops = {
+       .enum_frame_interval = ov7670_enum_frame_interval,
+       .enum_frame_size = ov7670_enum_frame_size,
 };
 
 static const struct v4l2_subdev_ops ov7670_ops = {
        .core = &ov7670_core_ops,
        .video = &ov7670_video_ops,
+       .pad = &ov7670_pad_ops,
 };
 
 /* ----------------------------------------------------------------------- */
index 2246bd5436adfe40cee6b9d313f53cd6608276b8..2bc473385c9143aaea64a3616d08c5d8a64b8325 100644 (file)
@@ -1067,7 +1067,7 @@ static void ov965x_get_default_format(struct v4l2_mbus_framefmt *mf)
 }
 
 static int ov965x_enum_mbus_code(struct v4l2_subdev *sd,
-                                struct v4l2_subdev_fh *fh,
+                                struct v4l2_subdev_pad_config *cfg,
                                 struct v4l2_subdev_mbus_code_enum *code)
 {
        if (code->index >= ARRAY_SIZE(ov965x_formats))
@@ -1078,7 +1078,7 @@ static int ov965x_enum_mbus_code(struct v4l2_subdev *sd,
 }
 
 static int ov965x_enum_frame_sizes(struct v4l2_subdev *sd,
-                                  struct v4l2_subdev_fh *fh,
+                                  struct v4l2_subdev_pad_config *cfg,
                                   struct v4l2_subdev_frame_size_enum *fse)
 {
        int i = ARRAY_SIZE(ov965x_formats);
@@ -1164,14 +1164,14 @@ static int ov965x_s_frame_interval(struct v4l2_subdev *sd,
        return ret;
 }
 
-static int ov965x_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int ov965x_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                          struct v4l2_subdev_format *fmt)
 {
        struct ov965x *ov965x = to_ov965x(sd);
        struct v4l2_mbus_framefmt *mf;
 
        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-               mf = v4l2_subdev_get_try_format(fh, 0);
+               mf = v4l2_subdev_get_try_format(sd, cfg, 0);
                fmt->format = *mf;
                return 0;
        }
@@ -1208,7 +1208,7 @@ static void __ov965x_try_frame_size(struct v4l2_mbus_framefmt *mf,
                *size = match;
 }
 
-static int ov965x_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int ov965x_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                          struct v4l2_subdev_format *fmt)
 {
        unsigned int index = ARRAY_SIZE(ov965x_formats);
@@ -1230,8 +1230,8 @@ static int ov965x_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        mutex_lock(&ov965x->lock);
 
        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-               if (fh != NULL) {
-                       mf = v4l2_subdev_get_try_format(fh, fmt->pad);
+               if (cfg != NULL) {
+                       mf = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
                        *mf = fmt->format;
                }
        } else {
@@ -1361,7 +1361,7 @@ static int ov965x_s_stream(struct v4l2_subdev *sd, int on)
  */
 static int ov965x_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 {
-       struct v4l2_mbus_framefmt *mf = v4l2_subdev_get_try_format(fh, 0);
+       struct v4l2_mbus_framefmt *mf = v4l2_subdev_get_try_format(sd, fh->pad, 0);
 
        ov965x_get_default_format(mf);
        return 0;
index ee0f57e01b5677df58c9f74565767bcaf57d54af..08b234bd2962cdcfe7674b05ded5fb0fb65b096b 100644 (file)
@@ -824,10 +824,11 @@ static const struct s5c73m3_frame_size *s5c73m3_find_frame_size(
 }
 
 static void s5c73m3_oif_try_format(struct s5c73m3 *state,
-                                  struct v4l2_subdev_fh *fh,
+                                  struct v4l2_subdev_pad_config *cfg,
                                   struct v4l2_subdev_format *fmt,
                                   const struct s5c73m3_frame_size **fs)
 {
+       struct v4l2_subdev *sd = &state->sensor_sd;
        u32 code;
 
        switch (fmt->pad) {
@@ -850,7 +851,7 @@ static void s5c73m3_oif_try_format(struct s5c73m3 *state,
                        *fs = state->oif_pix_size[RES_ISP];
                else
                        *fs = s5c73m3_find_frame_size(
-                                               v4l2_subdev_get_try_format(fh,
+                                               v4l2_subdev_get_try_format(sd, cfg,
                                                        OIF_ISP_PAD),
                                                RES_ISP);
                break;
@@ -860,7 +861,7 @@ static void s5c73m3_oif_try_format(struct s5c73m3 *state,
 }
 
 static void s5c73m3_try_format(struct s5c73m3 *state,
-                             struct v4l2_subdev_fh *fh,
+                             struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_format *fmt,
                              const struct s5c73m3_frame_size **fs)
 {
@@ -952,7 +953,7 @@ static int s5c73m3_oif_s_frame_interval(struct v4l2_subdev *sd,
 }
 
 static int s5c73m3_oif_enum_frame_interval(struct v4l2_subdev *sd,
-                             struct v4l2_subdev_fh *fh,
+                             struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_frame_interval_enum *fie)
 {
        struct s5c73m3 *state = oif_sd_to_s5c73m3(sd);
@@ -990,7 +991,7 @@ static int s5c73m3_oif_get_pad_code(int pad, int index)
 }
 
 static int s5c73m3_get_fmt(struct v4l2_subdev *sd,
-                          struct v4l2_subdev_fh *fh,
+                          struct v4l2_subdev_pad_config *cfg,
                           struct v4l2_subdev_format *fmt)
 {
        struct s5c73m3 *state = sensor_sd_to_s5c73m3(sd);
@@ -998,7 +999,7 @@ static int s5c73m3_get_fmt(struct v4l2_subdev *sd,
        u32 code;
 
        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-               fmt->format = *v4l2_subdev_get_try_format(fh, fmt->pad);
+               fmt->format = *v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
                return 0;
        }
 
@@ -1024,7 +1025,7 @@ static int s5c73m3_get_fmt(struct v4l2_subdev *sd,
 }
 
 static int s5c73m3_oif_get_fmt(struct v4l2_subdev *sd,
-                          struct v4l2_subdev_fh *fh,
+                          struct v4l2_subdev_pad_config *cfg,
                           struct v4l2_subdev_format *fmt)
 {
        struct s5c73m3 *state = oif_sd_to_s5c73m3(sd);
@@ -1032,7 +1033,7 @@ static int s5c73m3_oif_get_fmt(struct v4l2_subdev *sd,
        u32 code;
 
        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-               fmt->format = *v4l2_subdev_get_try_format(fh, fmt->pad);
+               fmt->format = *v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
                return 0;
        }
 
@@ -1062,7 +1063,7 @@ static int s5c73m3_oif_get_fmt(struct v4l2_subdev *sd,
 }
 
 static int s5c73m3_set_fmt(struct v4l2_subdev *sd,
-                          struct v4l2_subdev_fh *fh,
+                          struct v4l2_subdev_pad_config *cfg,
                           struct v4l2_subdev_format *fmt)
 {
        const struct s5c73m3_frame_size *frame_size = NULL;
@@ -1072,10 +1073,10 @@ static int s5c73m3_set_fmt(struct v4l2_subdev *sd,
 
        mutex_lock(&state->lock);
 
-       s5c73m3_try_format(state, fh, fmt, &frame_size);
+       s5c73m3_try_format(state, cfg, fmt, &frame_size);
 
        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-               mf = v4l2_subdev_get_try_format(fh, fmt->pad);
+               mf = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
                *mf = fmt->format;
        } else {
                switch (fmt->pad) {
@@ -1101,7 +1102,7 @@ static int s5c73m3_set_fmt(struct v4l2_subdev *sd,
 }
 
 static int s5c73m3_oif_set_fmt(struct v4l2_subdev *sd,
-                        struct v4l2_subdev_fh *fh,
+                        struct v4l2_subdev_pad_config *cfg,
                         struct v4l2_subdev_format *fmt)
 {
        const struct s5c73m3_frame_size *frame_size = NULL;
@@ -1111,13 +1112,13 @@ static int s5c73m3_oif_set_fmt(struct v4l2_subdev *sd,
 
        mutex_lock(&state->lock);
 
-       s5c73m3_oif_try_format(state, fh, fmt, &frame_size);
+       s5c73m3_oif_try_format(state, cfg, fmt, &frame_size);
 
        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-               mf = v4l2_subdev_get_try_format(fh, fmt->pad);
+               mf = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
                *mf = fmt->format;
                if (fmt->pad == OIF_ISP_PAD) {
-                       mf = v4l2_subdev_get_try_format(fh, OIF_SOURCE_PAD);
+                       mf = v4l2_subdev_get_try_format(sd, cfg, OIF_SOURCE_PAD);
                        mf->width = fmt->format.width;
                        mf->height = fmt->format.height;
                }
@@ -1189,7 +1190,7 @@ static int s5c73m3_oif_set_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
 }
 
 static int s5c73m3_enum_mbus_code(struct v4l2_subdev *sd,
-                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_pad_config *cfg,
                                  struct v4l2_subdev_mbus_code_enum *code)
 {
        static const int codes[] = {
@@ -1205,7 +1206,7 @@ static int s5c73m3_enum_mbus_code(struct v4l2_subdev *sd,
 }
 
 static int s5c73m3_oif_enum_mbus_code(struct v4l2_subdev *sd,
-                               struct v4l2_subdev_fh *fh,
+                               struct v4l2_subdev_pad_config *cfg,
                                struct v4l2_subdev_mbus_code_enum *code)
 {
        int ret;
@@ -1220,7 +1221,7 @@ static int s5c73m3_oif_enum_mbus_code(struct v4l2_subdev *sd,
 }
 
 static int s5c73m3_enum_frame_size(struct v4l2_subdev *sd,
-                                  struct v4l2_subdev_fh *fh,
+                                  struct v4l2_subdev_pad_config *cfg,
                                   struct v4l2_subdev_frame_size_enum *fse)
 {
        int idx;
@@ -1247,9 +1248,10 @@ static int s5c73m3_enum_frame_size(struct v4l2_subdev *sd,
 }
 
 static int s5c73m3_oif_enum_frame_size(struct v4l2_subdev *sd,
-                                  struct v4l2_subdev_fh *fh,
+                                  struct v4l2_subdev_pad_config *cfg,
                                   struct v4l2_subdev_frame_size_enum *fse)
 {
+       struct s5c73m3 *state = oif_sd_to_s5c73m3(sd);
        int idx;
 
        if (fse->pad == OIF_SOURCE_PAD) {
@@ -1259,11 +1261,25 @@ static int s5c73m3_oif_enum_frame_size(struct v4l2_subdev *sd,
                switch (fse->code) {
                case S5C73M3_JPEG_FMT:
                case S5C73M3_ISP_FMT: {
-                       struct v4l2_mbus_framefmt *mf =
-                               v4l2_subdev_get_try_format(fh, OIF_ISP_PAD);
+                       unsigned w, h;
+
+                       if (fse->which == V4L2_SUBDEV_FORMAT_TRY) {
+                               struct v4l2_mbus_framefmt *mf;
+
+                               mf = v4l2_subdev_get_try_format(sd, cfg,
+                                                               OIF_ISP_PAD);
+
+                               w = mf->width;
+                               h = mf->height;
+                       } else {
+                               const struct s5c73m3_frame_size *fs;
 
-                       fse->max_width = fse->min_width = mf->width;
-                       fse->max_height = fse->min_height = mf->height;
+                               fs = state->oif_pix_size[RES_ISP];
+                               w = fs->width;
+                               h = fs->height;
+                       }
+                       fse->max_width = fse->min_width = w;
+                       fse->max_height = fse->min_height = h;
                        return 0;
                }
                default:
@@ -1306,11 +1322,11 @@ static int s5c73m3_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 {
        struct v4l2_mbus_framefmt *mf;
 
-       mf = v4l2_subdev_get_try_format(fh, S5C73M3_ISP_PAD);
+       mf = v4l2_subdev_get_try_format(sd, fh->pad, S5C73M3_ISP_PAD);
        s5c73m3_fill_mbus_fmt(mf, &s5c73m3_isp_resolutions[1],
                                                S5C73M3_ISP_FMT);
 
-       mf = v4l2_subdev_get_try_format(fh, S5C73M3_JPEG_PAD);
+       mf = v4l2_subdev_get_try_format(sd, fh->pad, S5C73M3_JPEG_PAD);
        s5c73m3_fill_mbus_fmt(mf, &s5c73m3_jpeg_resolutions[1],
                                        S5C73M3_JPEG_FMT);
 
@@ -1321,15 +1337,15 @@ static int s5c73m3_oif_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 {
        struct v4l2_mbus_framefmt *mf;
 
-       mf = v4l2_subdev_get_try_format(fh, OIF_ISP_PAD);
+       mf = v4l2_subdev_get_try_format(sd, fh->pad, OIF_ISP_PAD);
        s5c73m3_fill_mbus_fmt(mf, &s5c73m3_isp_resolutions[1],
                                                S5C73M3_ISP_FMT);
 
-       mf = v4l2_subdev_get_try_format(fh, OIF_JPEG_PAD);
+       mf = v4l2_subdev_get_try_format(sd, fh->pad, OIF_JPEG_PAD);
        s5c73m3_fill_mbus_fmt(mf, &s5c73m3_jpeg_resolutions[1],
                                        S5C73M3_JPEG_FMT);
 
-       mf = v4l2_subdev_get_try_format(fh, OIF_SOURCE_PAD);
+       mf = v4l2_subdev_get_try_format(sd, fh->pad, OIF_SOURCE_PAD);
        s5c73m3_fill_mbus_fmt(mf, &s5c73m3_isp_resolutions[1],
                                                S5C73M3_ISP_FMT);
        return 0;
index f60b265b4da15a949701fac80c7de4927e0a49fd..63eb19093381d2abad3a39871167c7c237051be5 100644 (file)
@@ -52,7 +52,7 @@ static int spi_xmit(struct spi_device *spi_dev, void *addr, const int len,
                xfer.rx_buf = addr;
 
        if (spi_dev == NULL) {
-               dev_err(&spi_dev->dev, "SPI device is uninitialized\n");
+               pr_err("SPI device is uninitialized\n");
                return -ENODEV;
        }
 
index 70071314789e977b29c52bfd1770a9e770e15c4a..97084237275dcafcc2b3edcd01ccaa4b6831cec6 100644 (file)
@@ -531,7 +531,7 @@ static int s5k4ecgx_try_frame_size(struct v4l2_mbus_framefmt *mf,
 }
 
 static int s5k4ecgx_enum_mbus_code(struct v4l2_subdev *sd,
-                                  struct v4l2_subdev_fh *fh,
+                                  struct v4l2_subdev_pad_config *cfg,
                                   struct v4l2_subdev_mbus_code_enum *code)
 {
        if (code->index >= ARRAY_SIZE(s5k4ecgx_formats))
@@ -541,15 +541,15 @@ static int s5k4ecgx_enum_mbus_code(struct v4l2_subdev *sd,
        return 0;
 }
 
-static int s5k4ecgx_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int s5k4ecgx_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                           struct v4l2_subdev_format *fmt)
 {
        struct s5k4ecgx *priv = to_s5k4ecgx(sd);
        struct v4l2_mbus_framefmt *mf;
 
        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-               if (fh) {
-                       mf = v4l2_subdev_get_try_format(fh, 0);
+               if (cfg) {
+                       mf = v4l2_subdev_get_try_format(sd, cfg, 0);
                        fmt->format = *mf;
                }
                return 0;
@@ -581,7 +581,7 @@ static const struct s5k4ecgx_pixfmt *s5k4ecgx_try_fmt(struct v4l2_subdev *sd,
        return &s5k4ecgx_formats[i];
 }
 
-static int s5k4ecgx_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int s5k4ecgx_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                            struct v4l2_subdev_format *fmt)
 {
        struct s5k4ecgx *priv = to_s5k4ecgx(sd);
@@ -596,8 +596,8 @@ static int s5k4ecgx_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        fmt->format.field = V4L2_FIELD_NONE;
 
        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-               if (fh) {
-                       mf = v4l2_subdev_get_try_format(fh, 0);
+               if (cfg) {
+                       mf = v4l2_subdev_get_try_format(sd, cfg, 0);
                        *mf = fmt->format;
                }
                return 0;
@@ -692,7 +692,7 @@ static int s5k4ecgx_registered(struct v4l2_subdev *sd)
  */
 static int s5k4ecgx_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 {
-       struct v4l2_mbus_framefmt *mf = v4l2_subdev_get_try_format(fh, 0);
+       struct v4l2_mbus_framefmt *mf = v4l2_subdev_get_try_format(sd, fh->pad, 0);
 
        mf->width = s5k4ecgx_prev_sizes[0].size.width;
        mf->height = s5k4ecgx_prev_sizes[0].size.height;
index a3d7d0391302fdd78f3faac097193c095542c73e..297ef04e146a390da983d17996d62de587cf9b71 100644 (file)
@@ -374,6 +374,8 @@ static int s5k5baf_fw_parse(struct device *dev, struct s5k5baf_fw **fw,
        count -= S5K5BAG_FW_TAG_LEN;
 
        d = devm_kzalloc(dev, count * sizeof(u16), GFP_KERNEL);
+       if (!d)
+               return -ENOMEM;
 
        for (i = 0; i < count; ++i)
                d[i] = le16_to_cpu(data[i]);
@@ -1182,7 +1184,7 @@ static int s5k5baf_s_frame_interval(struct v4l2_subdev *sd,
  * V4L2 subdev pad level and video operations
  */
 static int s5k5baf_enum_frame_interval(struct v4l2_subdev *sd,
-                             struct v4l2_subdev_fh *fh,
+                             struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_frame_interval_enum *fie)
 {
        if (fie->index > S5K5BAF_MAX_FR_TIME - S5K5BAF_MIN_FR_TIME ||
@@ -1201,7 +1203,7 @@ static int s5k5baf_enum_frame_interval(struct v4l2_subdev *sd,
 }
 
 static int s5k5baf_enum_mbus_code(struct v4l2_subdev *sd,
-                                struct v4l2_subdev_fh *fh,
+                                struct v4l2_subdev_pad_config *cfg,
                                 struct v4l2_subdev_mbus_code_enum *code)
 {
        if (code->pad == PAD_CIS) {
@@ -1219,7 +1221,7 @@ static int s5k5baf_enum_mbus_code(struct v4l2_subdev *sd,
 }
 
 static int s5k5baf_enum_frame_size(struct v4l2_subdev *sd,
-                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_pad_config *cfg,
                                  struct v4l2_subdev_frame_size_enum *fse)
 {
        int i;
@@ -1276,7 +1278,7 @@ static int s5k5baf_try_isp_format(struct v4l2_mbus_framefmt *mf)
        return pixfmt;
 }
 
-static int s5k5baf_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int s5k5baf_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                          struct v4l2_subdev_format *fmt)
 {
        struct s5k5baf *state = to_s5k5baf(sd);
@@ -1284,7 +1286,7 @@ static int s5k5baf_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        struct v4l2_mbus_framefmt *mf;
 
        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-               mf = v4l2_subdev_get_try_format(fh, fmt->pad);
+               mf = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
                fmt->format = *mf;
                return 0;
        }
@@ -1306,7 +1308,7 @@ static int s5k5baf_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        return 0;
 }
 
-static int s5k5baf_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int s5k5baf_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                          struct v4l2_subdev_format *fmt)
 {
        struct v4l2_mbus_framefmt *mf = &fmt->format;
@@ -1317,7 +1319,7 @@ static int s5k5baf_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        mf->field = V4L2_FIELD_NONE;
 
        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-               *v4l2_subdev_get_try_format(fh, fmt->pad) = *mf;
+               *v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = *mf;
                return 0;
        }
 
@@ -1369,7 +1371,7 @@ static int s5k5baf_is_bound_target(u32 target)
 }
 
 static int s5k5baf_get_selection(struct v4l2_subdev *sd,
-                                struct v4l2_subdev_fh *fh,
+                                struct v4l2_subdev_pad_config *cfg,
                                 struct v4l2_subdev_selection *sel)
 {
        static enum selection_rect rtype;
@@ -1389,9 +1391,9 @@ static int s5k5baf_get_selection(struct v4l2_subdev *sd,
 
        if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
                if (rtype == R_COMPOSE)
-                       sel->r = *v4l2_subdev_get_try_compose(fh, sel->pad);
+                       sel->r = *v4l2_subdev_get_try_compose(sd, cfg, sel->pad);
                else
-                       sel->r = *v4l2_subdev_get_try_crop(fh, sel->pad);
+                       sel->r = *v4l2_subdev_get_try_crop(sd, cfg, sel->pad);
                return 0;
        }
 
@@ -1460,7 +1462,7 @@ static bool s5k5baf_cmp_rect(const struct v4l2_rect *r1,
 }
 
 static int s5k5baf_set_selection(struct v4l2_subdev *sd,
-                                struct v4l2_subdev_fh *fh,
+                                struct v4l2_subdev_pad_config *cfg,
                                 struct v4l2_subdev_selection *sel)
 {
        static enum selection_rect rtype;
@@ -1481,9 +1483,9 @@ static int s5k5baf_set_selection(struct v4l2_subdev *sd,
        if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
                rects = (struct v4l2_rect * []) {
                                &s5k5baf_cis_rect,
-                               v4l2_subdev_get_try_crop(fh, PAD_CIS),
-                               v4l2_subdev_get_try_compose(fh, PAD_CIS),
-                               v4l2_subdev_get_try_crop(fh, PAD_OUT)
+                               v4l2_subdev_get_try_crop(sd, cfg, PAD_CIS),
+                               v4l2_subdev_get_try_compose(sd, cfg, PAD_CIS),
+                               v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT)
                        };
                s5k5baf_set_rect_and_adjust(rects, rtype, &sel->r);
                return 0;
@@ -1701,22 +1703,22 @@ static int s5k5baf_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 {
        struct v4l2_mbus_framefmt *mf;
 
-       mf = v4l2_subdev_get_try_format(fh, PAD_CIS);
+       mf = v4l2_subdev_get_try_format(sd, fh->pad, PAD_CIS);
        s5k5baf_try_cis_format(mf);
 
        if (s5k5baf_is_cis_subdev(sd))
                return 0;
 
-       mf = v4l2_subdev_get_try_format(fh, PAD_OUT);
+       mf = v4l2_subdev_get_try_format(sd, fh->pad, PAD_OUT);
        mf->colorspace = s5k5baf_formats[0].colorspace;
        mf->code = s5k5baf_formats[0].code;
        mf->width = s5k5baf_cis_rect.width;
        mf->height = s5k5baf_cis_rect.height;
        mf->field = V4L2_FIELD_NONE;
 
-       *v4l2_subdev_get_try_crop(fh, PAD_CIS) = s5k5baf_cis_rect;
-       *v4l2_subdev_get_try_compose(fh, PAD_CIS) = s5k5baf_cis_rect;
-       *v4l2_subdev_get_try_crop(fh, PAD_OUT) = s5k5baf_cis_rect;
+       *v4l2_subdev_get_try_crop(sd, fh->pad, PAD_CIS) = s5k5baf_cis_rect;
+       *v4l2_subdev_get_try_compose(sd, fh->pad, PAD_CIS) = s5k5baf_cis_rect;
+       *v4l2_subdev_get_try_crop(sd, fh->pad, PAD_OUT) = s5k5baf_cis_rect;
 
        return 0;
 }
index 91b841a1b8509741254d97691db789ae9d8ddac9..bc389d5e42ae2cb2ee1635c2b999ba59ce5304a1 100644 (file)
@@ -99,7 +99,7 @@ static const struct v4l2_mbus_framefmt *find_sensor_format(
 }
 
 static int s5k6a3_enum_mbus_code(struct v4l2_subdev *sd,
-                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_pad_config *cfg,
                                  struct v4l2_subdev_mbus_code_enum *code)
 {
        if (code->index >= ARRAY_SIZE(s5k6a3_formats))
@@ -123,17 +123,17 @@ static void s5k6a3_try_format(struct v4l2_mbus_framefmt *mf)
 }
 
 static struct v4l2_mbus_framefmt *__s5k6a3_get_format(
-               struct s5k6a3 *sensor, struct v4l2_subdev_fh *fh,
+               struct s5k6a3 *sensor, struct v4l2_subdev_pad_config *cfg,
                u32 pad, enum v4l2_subdev_format_whence which)
 {
        if (which == V4L2_SUBDEV_FORMAT_TRY)
-               return fh ? v4l2_subdev_get_try_format(fh, pad) : NULL;
+               return cfg ? v4l2_subdev_get_try_format(&sensor->subdev, cfg, pad) : NULL;
 
        return &sensor->format;
 }
 
 static int s5k6a3_set_fmt(struct v4l2_subdev *sd,
-                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_pad_config *cfg,
                                  struct v4l2_subdev_format *fmt)
 {
        struct s5k6a3 *sensor = sd_to_s5k6a3(sd);
@@ -141,7 +141,7 @@ static int s5k6a3_set_fmt(struct v4l2_subdev *sd,
 
        s5k6a3_try_format(&fmt->format);
 
-       mf = __s5k6a3_get_format(sensor, fh, fmt->pad, fmt->which);
+       mf = __s5k6a3_get_format(sensor, cfg, fmt->pad, fmt->which);
        if (mf) {
                mutex_lock(&sensor->lock);
                if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
@@ -152,13 +152,13 @@ static int s5k6a3_set_fmt(struct v4l2_subdev *sd,
 }
 
 static int s5k6a3_get_fmt(struct v4l2_subdev *sd,
-                                 struct v4l2_subdev_fh *fh,
-                                 struct v4l2_subdev_format *fmt)
+                         struct v4l2_subdev_pad_config *cfg,
+                         struct v4l2_subdev_format *fmt)
 {
        struct s5k6a3 *sensor = sd_to_s5k6a3(sd);
        struct v4l2_mbus_framefmt *mf;
 
-       mf = __s5k6a3_get_format(sensor, fh, fmt->pad, fmt->which);
+       mf = __s5k6a3_get_format(sensor, cfg, fmt->pad, fmt->which);
 
        mutex_lock(&sensor->lock);
        fmt->format = *mf;
@@ -174,7 +174,7 @@ static struct v4l2_subdev_pad_ops s5k6a3_pad_ops = {
 
 static int s5k6a3_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 {
-       struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0);
+       struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(sd, fh->pad, 0);
 
        *format         = s5k6a3_formats[0];
        format->width   = S5K6A3_DEFAULT_WIDTH;
index b1c583239dabd24fdf395395c1c4a5c964936590..de803a11efb41419f96841266bce1de37f56010f 100644 (file)
@@ -996,7 +996,7 @@ static int s5k6aa_s_frame_interval(struct v4l2_subdev *sd,
  * V4L2 subdev pad level and video operations
  */
 static int s5k6aa_enum_frame_interval(struct v4l2_subdev *sd,
-                             struct v4l2_subdev_fh *fh,
+                             struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_frame_interval_enum *fie)
 {
        struct s5k6aa *s5k6aa = to_s5k6aa(sd);
@@ -1023,7 +1023,7 @@ static int s5k6aa_enum_frame_interval(struct v4l2_subdev *sd,
 }
 
 static int s5k6aa_enum_mbus_code(struct v4l2_subdev *sd,
-                                struct v4l2_subdev_fh *fh,
+                                struct v4l2_subdev_pad_config *cfg,
                                 struct v4l2_subdev_mbus_code_enum *code)
 {
        if (code->index >= ARRAY_SIZE(s5k6aa_formats))
@@ -1034,7 +1034,7 @@ static int s5k6aa_enum_mbus_code(struct v4l2_subdev *sd,
 }
 
 static int s5k6aa_enum_frame_size(struct v4l2_subdev *sd,
-                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_pad_config *cfg,
                                  struct v4l2_subdev_frame_size_enum *fse)
 {
        int i = ARRAY_SIZE(s5k6aa_formats);
@@ -1056,14 +1056,14 @@ static int s5k6aa_enum_frame_size(struct v4l2_subdev *sd,
 }
 
 static struct v4l2_rect *
-__s5k6aa_get_crop_rect(struct s5k6aa *s5k6aa, struct v4l2_subdev_fh *fh,
+__s5k6aa_get_crop_rect(struct s5k6aa *s5k6aa, struct v4l2_subdev_pad_config *cfg,
                       enum v4l2_subdev_format_whence which)
 {
        if (which == V4L2_SUBDEV_FORMAT_ACTIVE)
                return &s5k6aa->ccd_rect;
 
        WARN_ON(which != V4L2_SUBDEV_FORMAT_TRY);
-       return v4l2_subdev_get_try_crop(fh, 0);
+       return v4l2_subdev_get_try_crop(&s5k6aa->sd, cfg, 0);
 }
 
 static void s5k6aa_try_format(struct s5k6aa *s5k6aa,
@@ -1087,7 +1087,7 @@ static void s5k6aa_try_format(struct s5k6aa *s5k6aa,
        mf->field       = V4L2_FIELD_NONE;
 }
 
-static int s5k6aa_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int s5k6aa_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                          struct v4l2_subdev_format *fmt)
 {
        struct s5k6aa *s5k6aa = to_s5k6aa(sd);
@@ -1096,7 +1096,7 @@ static int s5k6aa_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        memset(fmt->reserved, 0, sizeof(fmt->reserved));
 
        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-               mf = v4l2_subdev_get_try_format(fh, 0);
+               mf = v4l2_subdev_get_try_format(sd, cfg, 0);
                fmt->format = *mf;
                return 0;
        }
@@ -1108,7 +1108,7 @@ static int s5k6aa_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        return 0;
 }
 
-static int s5k6aa_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int s5k6aa_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                          struct v4l2_subdev_format *fmt)
 {
        struct s5k6aa *s5k6aa = to_s5k6aa(sd);
@@ -1121,8 +1121,8 @@ static int s5k6aa_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        s5k6aa_try_format(s5k6aa, &fmt->format);
 
        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-               mf = v4l2_subdev_get_try_format(fh, fmt->pad);
-               crop = v4l2_subdev_get_try_crop(fh, 0);
+               mf = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
+               crop = v4l2_subdev_get_try_crop(sd, cfg, 0);
        } else {
                if (s5k6aa->streaming) {
                        ret = -EBUSY;
@@ -1162,7 +1162,7 @@ static int s5k6aa_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 }
 
 static int s5k6aa_get_selection(struct v4l2_subdev *sd,
-                               struct v4l2_subdev_fh *fh,
+                               struct v4l2_subdev_pad_config *cfg,
                                struct v4l2_subdev_selection *sel)
 {
        struct s5k6aa *s5k6aa = to_s5k6aa(sd);
@@ -1174,7 +1174,7 @@ static int s5k6aa_get_selection(struct v4l2_subdev *sd,
        memset(sel->reserved, 0, sizeof(sel->reserved));
 
        mutex_lock(&s5k6aa->lock);
-       rect = __s5k6aa_get_crop_rect(s5k6aa, fh, sel->which);
+       rect = __s5k6aa_get_crop_rect(s5k6aa, cfg, sel->which);
        sel->r = *rect;
        mutex_unlock(&s5k6aa->lock);
 
@@ -1185,7 +1185,7 @@ static int s5k6aa_get_selection(struct v4l2_subdev *sd,
 }
 
 static int s5k6aa_set_selection(struct v4l2_subdev *sd,
-                               struct v4l2_subdev_fh *fh,
+                               struct v4l2_subdev_pad_config *cfg,
                                struct v4l2_subdev_selection *sel)
 {
        struct s5k6aa *s5k6aa = to_s5k6aa(sd);
@@ -1197,13 +1197,13 @@ static int s5k6aa_set_selection(struct v4l2_subdev *sd,
                return -EINVAL;
 
        mutex_lock(&s5k6aa->lock);
-       crop_r = __s5k6aa_get_crop_rect(s5k6aa, fh, sel->which);
+       crop_r = __s5k6aa_get_crop_rect(s5k6aa, cfg, sel->which);
 
        if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
                mf = &s5k6aa->preset->mbus_fmt;
                s5k6aa->apply_crop = 1;
        } else {
-               mf = v4l2_subdev_get_try_format(fh, 0);
+               mf = v4l2_subdev_get_try_format(sd, cfg, 0);
        }
        v4l_bound_align_image(&sel->r.width, mf->width,
                              S5K6AA_WIN_WIDTH_MAX, 1,
@@ -1424,8 +1424,8 @@ static int s5k6aa_initialize_ctrls(struct s5k6aa *s5k6aa)
  */
 static int s5k6aa_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 {
-       struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0);
-       struct v4l2_rect *crop = v4l2_subdev_get_try_crop(fh, 0);
+       struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(sd, fh->pad, 0);
+       struct v4l2_rect *crop = v4l2_subdev_get_try_crop(sd, fh->pad, 0);
 
        format->colorspace = s5k6aa_formats[0].colorspace;
        format->code = s5k6aa_formats[0].code;
index d47eff5d310159680853b6f91c8f0a5e70b69620..557f25def3a08bf8f99bddbd81e505da974b7fad 100644 (file)
@@ -344,7 +344,7 @@ static const struct smiapp_csi_data_format smiapp_csi_data_formats[] = {
        { MEDIA_BUS_FMT_SGBRG8_1X8, 8, 8, SMIAPP_PIXEL_ORDER_GBRG, },
 };
 
-const char *pixel_order_str[] = { "GRBG", "RGGB", "BGGR", "GBRG" };
+static const char *pixel_order_str[] = { "GRBG", "RGGB", "BGGR", "GBRG" };
 
 #define to_csi_format_idx(fmt) (((unsigned long)(fmt)                  \
                                 - (unsigned long)smiapp_csi_data_formats) \
@@ -1557,7 +1557,7 @@ static int smiapp_set_stream(struct v4l2_subdev *subdev, int enable)
 }
 
 static int smiapp_enum_mbus_code(struct v4l2_subdev *subdev,
-                                struct v4l2_subdev_fh *fh,
+                                struct v4l2_subdev_pad_config *cfg,
                                 struct v4l2_subdev_mbus_code_enum *code)
 {
        struct i2c_client *client = v4l2_get_subdevdata(subdev);
@@ -1611,13 +1611,13 @@ static u32 __smiapp_get_mbus_code(struct v4l2_subdev *subdev,
 }
 
 static int __smiapp_get_format(struct v4l2_subdev *subdev,
-                              struct v4l2_subdev_fh *fh,
+                              struct v4l2_subdev_pad_config *cfg,
                               struct v4l2_subdev_format *fmt)
 {
        struct smiapp_subdev *ssd = to_smiapp_subdev(subdev);
 
        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-               fmt->format = *v4l2_subdev_get_try_format(fh, fmt->pad);
+               fmt->format = *v4l2_subdev_get_try_format(subdev, cfg, fmt->pad);
        } else {
                struct v4l2_rect *r;
 
@@ -1636,21 +1636,21 @@ static int __smiapp_get_format(struct v4l2_subdev *subdev,
 }
 
 static int smiapp_get_format(struct v4l2_subdev *subdev,
-                            struct v4l2_subdev_fh *fh,
+                            struct v4l2_subdev_pad_config *cfg,
                             struct v4l2_subdev_format *fmt)
 {
        struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
        int rval;
 
        mutex_lock(&sensor->mutex);
-       rval = __smiapp_get_format(subdev, fh, fmt);
+       rval = __smiapp_get_format(subdev, cfg, fmt);
        mutex_unlock(&sensor->mutex);
 
        return rval;
 }
 
 static void smiapp_get_crop_compose(struct v4l2_subdev *subdev,
-                                   struct v4l2_subdev_fh *fh,
+                                   struct v4l2_subdev_pad_config *cfg,
                                    struct v4l2_rect **crops,
                                    struct v4l2_rect **comps, int which)
 {
@@ -1666,12 +1666,12 @@ static void smiapp_get_crop_compose(struct v4l2_subdev *subdev,
        } else {
                if (crops) {
                        for (i = 0; i < subdev->entity.num_pads; i++) {
-                               crops[i] = v4l2_subdev_get_try_crop(fh, i);
+                               crops[i] = v4l2_subdev_get_try_crop(subdev, cfg, i);
                                BUG_ON(!crops[i]);
                        }
                }
                if (comps) {
-                       *comps = v4l2_subdev_get_try_compose(fh,
+                       *comps = v4l2_subdev_get_try_compose(subdev, cfg,
                                                             SMIAPP_PAD_SINK);
                        BUG_ON(!*comps);
                }
@@ -1680,14 +1680,14 @@ static void smiapp_get_crop_compose(struct v4l2_subdev *subdev,
 
 /* Changes require propagation only on sink pad. */
 static void smiapp_propagate(struct v4l2_subdev *subdev,
-                            struct v4l2_subdev_fh *fh, int which,
+                            struct v4l2_subdev_pad_config *cfg, int which,
                             int target)
 {
        struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
        struct smiapp_subdev *ssd = to_smiapp_subdev(subdev);
        struct v4l2_rect *comp, *crops[SMIAPP_PADS];
 
-       smiapp_get_crop_compose(subdev, fh, crops, &comp, which);
+       smiapp_get_crop_compose(subdev, cfg, crops, &comp, which);
 
        switch (target) {
        case V4L2_SEL_TGT_CROP:
@@ -1730,7 +1730,7 @@ static const struct smiapp_csi_data_format
 }
 
 static int smiapp_set_format_source(struct v4l2_subdev *subdev,
-                                   struct v4l2_subdev_fh *fh,
+                                   struct v4l2_subdev_pad_config *cfg,
                                    struct v4l2_subdev_format *fmt)
 {
        struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
@@ -1741,7 +1741,7 @@ static int smiapp_set_format_source(struct v4l2_subdev *subdev,
        unsigned int i;
        int rval;
 
-       rval = __smiapp_get_format(subdev, fh, fmt);
+       rval = __smiapp_get_format(subdev, cfg, fmt);
        if (rval)
                return rval;
 
@@ -1783,7 +1783,7 @@ static int smiapp_set_format_source(struct v4l2_subdev *subdev,
 }
 
 static int smiapp_set_format(struct v4l2_subdev *subdev,
-                            struct v4l2_subdev_fh *fh,
+                            struct v4l2_subdev_pad_config *cfg,
                             struct v4l2_subdev_format *fmt)
 {
        struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
@@ -1795,7 +1795,7 @@ static int smiapp_set_format(struct v4l2_subdev *subdev,
        if (fmt->pad == ssd->source_pad) {
                int rval;
 
-               rval = smiapp_set_format_source(subdev, fh, fmt);
+               rval = smiapp_set_format_source(subdev, cfg, fmt);
 
                mutex_unlock(&sensor->mutex);
 
@@ -1817,7 +1817,7 @@ static int smiapp_set_format(struct v4l2_subdev *subdev,
                      sensor->limits[SMIAPP_LIMIT_MIN_Y_OUTPUT_SIZE],
                      sensor->limits[SMIAPP_LIMIT_MAX_Y_OUTPUT_SIZE]);
 
-       smiapp_get_crop_compose(subdev, fh, crops, NULL, fmt->which);
+       smiapp_get_crop_compose(subdev, cfg, crops, NULL, fmt->which);
 
        crops[ssd->sink_pad]->left = 0;
        crops[ssd->sink_pad]->top = 0;
@@ -1825,7 +1825,7 @@ static int smiapp_set_format(struct v4l2_subdev *subdev,
        crops[ssd->sink_pad]->height = fmt->format.height;
        if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
                ssd->sink_fmt = *crops[ssd->sink_pad];
-       smiapp_propagate(subdev, fh, fmt->which,
+       smiapp_propagate(subdev, cfg, fmt->which,
                         V4L2_SEL_TGT_CROP);
 
        mutex_unlock(&sensor->mutex);
@@ -1878,7 +1878,7 @@ static int scaling_goodness(struct v4l2_subdev *subdev, int w, int ask_w,
 }
 
 static void smiapp_set_compose_binner(struct v4l2_subdev *subdev,
-                                     struct v4l2_subdev_fh *fh,
+                                     struct v4l2_subdev_pad_config *cfg,
                                      struct v4l2_subdev_selection *sel,
                                      struct v4l2_rect **crops,
                                      struct v4l2_rect *comp)
@@ -1926,7 +1926,7 @@ static void smiapp_set_compose_binner(struct v4l2_subdev *subdev,
  * result.
  */
 static void smiapp_set_compose_scaler(struct v4l2_subdev *subdev,
-                                     struct v4l2_subdev_fh *fh,
+                                     struct v4l2_subdev_pad_config *cfg,
                                      struct v4l2_subdev_selection *sel,
                                      struct v4l2_rect **crops,
                                      struct v4l2_rect *comp)
@@ -2042,25 +2042,25 @@ static void smiapp_set_compose_scaler(struct v4l2_subdev *subdev,
 }
 /* We're only called on source pads. This function sets scaling. */
 static int smiapp_set_compose(struct v4l2_subdev *subdev,
-                             struct v4l2_subdev_fh *fh,
+                             struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_selection *sel)
 {
        struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
        struct smiapp_subdev *ssd = to_smiapp_subdev(subdev);
        struct v4l2_rect *comp, *crops[SMIAPP_PADS];
 
-       smiapp_get_crop_compose(subdev, fh, crops, &comp, sel->which);
+       smiapp_get_crop_compose(subdev, cfg, crops, &comp, sel->which);
 
        sel->r.top = 0;
        sel->r.left = 0;
 
        if (ssd == sensor->binner)
-               smiapp_set_compose_binner(subdev, fh, sel, crops, comp);
+               smiapp_set_compose_binner(subdev, cfg, sel, crops, comp);
        else
-               smiapp_set_compose_scaler(subdev, fh, sel, crops, comp);
+               smiapp_set_compose_scaler(subdev, cfg, sel, crops, comp);
 
        *comp = sel->r;
-       smiapp_propagate(subdev, fh, sel->which,
+       smiapp_propagate(subdev, cfg, sel->which,
                         V4L2_SEL_TGT_COMPOSE);
 
        if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE)
@@ -2113,7 +2113,7 @@ static int __smiapp_sel_supported(struct v4l2_subdev *subdev,
 }
 
 static int smiapp_set_crop(struct v4l2_subdev *subdev,
-                          struct v4l2_subdev_fh *fh,
+                          struct v4l2_subdev_pad_config *cfg,
                           struct v4l2_subdev_selection *sel)
 {
        struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
@@ -2121,7 +2121,7 @@ static int smiapp_set_crop(struct v4l2_subdev *subdev,
        struct v4l2_rect *src_size, *crops[SMIAPP_PADS];
        struct v4l2_rect _r;
 
-       smiapp_get_crop_compose(subdev, fh, crops, NULL, sel->which);
+       smiapp_get_crop_compose(subdev, cfg, crops, NULL, sel->which);
 
        if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
                if (sel->pad == ssd->sink_pad)
@@ -2132,15 +2132,15 @@ static int smiapp_set_crop(struct v4l2_subdev *subdev,
                if (sel->pad == ssd->sink_pad) {
                        _r.left = 0;
                        _r.top = 0;
-                       _r.width = v4l2_subdev_get_try_format(fh, sel->pad)
+                       _r.width = v4l2_subdev_get_try_format(subdev, cfg, sel->pad)
                                ->width;
-                       _r.height = v4l2_subdev_get_try_format(fh, sel->pad)
+                       _r.height = v4l2_subdev_get_try_format(subdev, cfg, sel->pad)
                                ->height;
                        src_size = &_r;
                } else {
                        src_size =
                                v4l2_subdev_get_try_compose(
-                                       fh, ssd->sink_pad);
+                                       subdev, cfg, ssd->sink_pad);
                }
        }
 
@@ -2158,14 +2158,14 @@ static int smiapp_set_crop(struct v4l2_subdev *subdev,
        *crops[sel->pad] = sel->r;
 
        if (ssd != sensor->pixel_array && sel->pad == SMIAPP_PAD_SINK)
-               smiapp_propagate(subdev, fh, sel->which,
+               smiapp_propagate(subdev, cfg, sel->which,
                                 V4L2_SEL_TGT_CROP);
 
        return 0;
 }
 
 static int __smiapp_get_selection(struct v4l2_subdev *subdev,
-                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_pad_config *cfg,
                                  struct v4l2_subdev_selection *sel)
 {
        struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
@@ -2178,13 +2178,13 @@ static int __smiapp_get_selection(struct v4l2_subdev *subdev,
        if (ret)
                return ret;
 
-       smiapp_get_crop_compose(subdev, fh, crops, &comp, sel->which);
+       smiapp_get_crop_compose(subdev, cfg, crops, &comp, sel->which);
 
        if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
                sink_fmt = ssd->sink_fmt;
        } else {
                struct v4l2_mbus_framefmt *fmt =
-                       v4l2_subdev_get_try_format(fh, ssd->sink_pad);
+                       v4l2_subdev_get_try_format(subdev, cfg, ssd->sink_pad);
 
                sink_fmt.left = 0;
                sink_fmt.top = 0;
@@ -2220,20 +2220,20 @@ static int __smiapp_get_selection(struct v4l2_subdev *subdev,
 }
 
 static int smiapp_get_selection(struct v4l2_subdev *subdev,
-                               struct v4l2_subdev_fh *fh,
+                               struct v4l2_subdev_pad_config *cfg,
                                struct v4l2_subdev_selection *sel)
 {
        struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
        int rval;
 
        mutex_lock(&sensor->mutex);
-       rval = __smiapp_get_selection(subdev, fh, sel);
+       rval = __smiapp_get_selection(subdev, cfg, sel);
        mutex_unlock(&sensor->mutex);
 
        return rval;
 }
 static int smiapp_set_selection(struct v4l2_subdev *subdev,
-                               struct v4l2_subdev_fh *fh,
+                               struct v4l2_subdev_pad_config *cfg,
                                struct v4l2_subdev_selection *sel)
 {
        struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
@@ -2259,10 +2259,10 @@ static int smiapp_set_selection(struct v4l2_subdev *subdev,
 
        switch (sel->target) {
        case V4L2_SEL_TGT_CROP:
-               ret = smiapp_set_crop(subdev, fh, sel);
+               ret = smiapp_set_crop(subdev, cfg, sel);
                break;
        case V4L2_SEL_TGT_COMPOSE:
-               ret = smiapp_set_compose(subdev, fh, sel);
+               ret = smiapp_set_compose(subdev, cfg, sel);
                break;
        default:
                ret = -EINVAL;
@@ -2841,8 +2841,8 @@ static int smiapp_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 
        for (i = 0; i < ssd->npads; i++) {
                struct v4l2_mbus_framefmt *try_fmt =
-                       v4l2_subdev_get_try_format(fh, i);
-               struct v4l2_rect *try_crop = v4l2_subdev_get_try_crop(fh, i);
+                       v4l2_subdev_get_try_format(sd, fh->pad, i);
+               struct v4l2_rect *try_crop = v4l2_subdev_get_try_crop(sd, fh->pad, i);
                struct v4l2_rect *try_comp;
 
                try_fmt->width = sensor->limits[SMIAPP_LIMIT_X_ADDR_MAX] + 1;
@@ -2858,7 +2858,7 @@ static int smiapp_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
                if (ssd != sensor->pixel_array)
                        continue;
 
-               try_comp = v4l2_subdev_get_try_compose(fh, i);
+               try_comp = v4l2_subdev_get_try_compose(sd, fh->pad, i);
                *try_comp = *try_crop;
        }
 
@@ -2977,12 +2977,7 @@ static struct smiapp_platform_data *smiapp_get_pdata(struct device *dev)
        struct smiapp_platform_data *pdata;
        struct v4l2_of_endpoint bus_cfg;
        struct device_node *ep;
-       struct property *prop;
-       __be32 *val;
        uint32_t asize;
-#ifdef CONFIG_OF
-       unsigned int i;
-#endif
        int rval;
 
        if (!dev->of_node)
@@ -2993,10 +2988,8 @@ static struct smiapp_platform_data *smiapp_get_pdata(struct device *dev)
                return NULL;
 
        pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
-       if (!pdata) {
-               rval = -ENOMEM;
+       if (!pdata)
                goto out_err;
-       }
 
        v4l2_of_parse_endpoint(ep, &bus_cfg);
 
@@ -3006,7 +2999,6 @@ static struct smiapp_platform_data *smiapp_get_pdata(struct device *dev)
                break;
                /* FIXME: add CCP2 support. */
        default:
-               rval = -EINVAL;
                goto out_err;
        }
 
@@ -3030,8 +3022,7 @@ static struct smiapp_platform_data *smiapp_get_pdata(struct device *dev)
        dev_dbg(dev, "reset %d, nvm %d, clk %d, csi %d\n", pdata->xshutdown,
                pdata->nvm_size, pdata->ext_clk, pdata->csi_signalling_mode);
 
-       rval = of_get_property(
-               dev->of_node, "link-frequencies", &asize) ? 0 : -ENOENT;
+       rval = of_get_property(ep, "link-frequencies", &asize) ? 0 : -ENOENT;
        if (rval) {
                dev_warn(dev, "can't get link-frequencies array size\n");
                goto out_err;
@@ -3044,25 +3035,12 @@ static struct smiapp_platform_data *smiapp_get_pdata(struct device *dev)
        }
 
        asize /= sizeof(*pdata->op_sys_clock);
-       /*
-        * Read a 64-bit array --- this will be replaced with a
-        * of_property_read_u64_array() once it's merged.
-        */
-       prop = of_find_property(dev->of_node, "link-frequencies", NULL);
-       if (!prop)
-               goto out_err;
-       if (!prop->value)
-               goto out_err;
-       if (asize * sizeof(*pdata->op_sys_clock) > prop->length)
-               goto out_err;
-       val = prop->value;
-       if (IS_ERR(val))
+       rval = of_property_read_u64_array(
+               ep, "link-frequencies", pdata->op_sys_clock, asize);
+       if (rval) {
+               dev_warn(dev, "can't get link-frequencies\n");
                goto out_err;
-
-#ifdef CONFIG_OF
-       for (i = 0; i < asize; i++)
-               pdata->op_sys_clock[i] = of_read_number(val + i * 2, 2);
-#endif
+       }
 
        for (; asize > 0; asize--)
                dev_dbg(dev, "freq %d: %lld\n", asize - 1,
index 5992ea93257a0c6e6803e311c9befe50b643bf06..441e0fda24fea3c2867300805a6366548d4b053b 100644 (file)
@@ -1016,7 +1016,6 @@ static int mt9m111_remove(struct i2c_client *client)
 
        v4l2_async_unregister_subdev(&mt9m111->subdev);
        v4l2_clk_put(mt9m111->clk);
-       v4l2_device_unregister_subdev(&mt9m111->subdev);
        v4l2_ctrl_handler_free(&mt9m111->hdl);
 
        return 0;
index 1fdce2f6f880bdbac3cd8d389f0b4c91cb7e333a..e3c907a977651a1f852db87e44f661f2dc502493 100644 (file)
@@ -18,6 +18,9 @@
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
+#include <linux/of_gpio.h>
 #include <linux/v4l2-mediabus.h>
 #include <linux/videodev2.h>
 
@@ -283,6 +286,10 @@ struct ov2640_priv {
        u32     cfmt_code;
        struct v4l2_clk                 *clk;
        const struct ov2640_win_size    *win;
+
+       struct soc_camera_subdev_desc   ssdd_dt;
+       struct gpio_desc *resetb_gpio;
+       struct gpio_desc *pwdn_gpio;
 };
 
 /*
@@ -1038,6 +1045,63 @@ static struct v4l2_subdev_ops ov2640_subdev_ops = {
        .video  = &ov2640_subdev_video_ops,
 };
 
+/* OF probe functions */
+static int ov2640_hw_power(struct device *dev, int on)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct ov2640_priv *priv = to_ov2640(client);
+
+       dev_dbg(&client->dev, "%s: %s the camera\n",
+                       __func__, on ? "ENABLE" : "DISABLE");
+
+       if (priv->pwdn_gpio)
+               gpiod_direction_output(priv->pwdn_gpio, !on);
+
+       return 0;
+}
+
+static int ov2640_hw_reset(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct ov2640_priv *priv = to_ov2640(client);
+
+       if (priv->resetb_gpio) {
+               /* Active the resetb pin to perform a reset pulse */
+               gpiod_direction_output(priv->resetb_gpio, 1);
+               usleep_range(3000, 5000);
+               gpiod_direction_output(priv->resetb_gpio, 0);
+       }
+
+       return 0;
+}
+
+static int ov2640_probe_dt(struct i2c_client *client,
+               struct ov2640_priv *priv)
+{
+       /* Request the reset GPIO deasserted */
+       priv->resetb_gpio = devm_gpiod_get_optional(&client->dev, "resetb",
+                       GPIOD_OUT_LOW);
+       if (!priv->resetb_gpio)
+               dev_dbg(&client->dev, "resetb gpio is not assigned!\n");
+       else if (IS_ERR(priv->resetb_gpio))
+               return PTR_ERR(priv->resetb_gpio);
+
+       /* Request the power down GPIO asserted */
+       priv->pwdn_gpio = devm_gpiod_get_optional(&client->dev, "pwdn",
+                       GPIOD_OUT_HIGH);
+       if (!priv->pwdn_gpio)
+               dev_dbg(&client->dev, "pwdn gpio is not assigned!\n");
+       else if (IS_ERR(priv->pwdn_gpio))
+               return PTR_ERR(priv->pwdn_gpio);
+
+       /* Initialize the soc_camera_subdev_desc */
+       priv->ssdd_dt.power = ov2640_hw_power;
+       priv->ssdd_dt.reset = ov2640_hw_reset;
+       client->dev.platform_data = &priv->ssdd_dt;
+
+       return 0;
+}
+
 /*
  * i2c_driver functions
  */
@@ -1049,12 +1113,6 @@ static int ov2640_probe(struct i2c_client *client,
        struct i2c_adapter      *adapter = to_i2c_adapter(client->dev.parent);
        int                     ret;
 
-       if (!ssdd) {
-               dev_err(&adapter->dev,
-                       "OV2640: Missing platform_data for driver\n");
-               return -EINVAL;
-       }
-
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
                dev_err(&adapter->dev,
                        "OV2640: I2C-Adapter doesn't support SMBUS\n");
@@ -1068,6 +1126,22 @@ static int ov2640_probe(struct i2c_client *client,
                return -ENOMEM;
        }
 
+       priv->clk = v4l2_clk_get(&client->dev, "xvclk");
+       if (IS_ERR(priv->clk))
+               return -EPROBE_DEFER;
+
+       if (!ssdd && !client->dev.of_node) {
+               dev_err(&client->dev, "Missing platform_data for driver\n");
+               ret = -EINVAL;
+               goto err_clk;
+       }
+
+       if (!ssdd) {
+               ret = ov2640_probe_dt(client, priv);
+               if (ret)
+                       goto err_clk;
+       }
+
        v4l2_i2c_subdev_init(&priv->subdev, client, &ov2640_subdev_ops);
        v4l2_ctrl_handler_init(&priv->hdl, 2);
        v4l2_ctrl_new_std(&priv->hdl, &ov2640_ctrl_ops,
@@ -1075,24 +1149,27 @@ static int ov2640_probe(struct i2c_client *client,
        v4l2_ctrl_new_std(&priv->hdl, &ov2640_ctrl_ops,
                        V4L2_CID_HFLIP, 0, 1, 1, 0);
        priv->subdev.ctrl_handler = &priv->hdl;
-       if (priv->hdl.error)
-               return priv->hdl.error;
-
-       priv->clk = v4l2_clk_get(&client->dev, "mclk");
-       if (IS_ERR(priv->clk)) {
-               ret = PTR_ERR(priv->clk);
-               goto eclkget;
+       if (priv->hdl.error) {
+               ret = priv->hdl.error;
+               goto err_clk;
        }
 
        ret = ov2640_video_probe(client);
-       if (ret) {
-               v4l2_clk_put(priv->clk);
-eclkget:
-               v4l2_ctrl_handler_free(&priv->hdl);
-       } else {
-               dev_info(&adapter->dev, "OV2640 Probed\n");
-       }
+       if (ret < 0)
+               goto err_videoprobe;
+
+       ret = v4l2_async_register_subdev(&priv->subdev);
+       if (ret < 0)
+               goto err_videoprobe;
+
+       dev_info(&adapter->dev, "OV2640 Probed\n");
 
+       return 0;
+
+err_videoprobe:
+       v4l2_ctrl_handler_free(&priv->hdl);
+err_clk:
+       v4l2_clk_put(priv->clk);
        return ret;
 }
 
@@ -1100,6 +1177,7 @@ static int ov2640_remove(struct i2c_client *client)
 {
        struct ov2640_priv       *priv = to_ov2640(client);
 
+       v4l2_async_unregister_subdev(&priv->subdev);
        v4l2_clk_put(priv->clk);
        v4l2_device_unregister_subdev(&priv->subdev);
        v4l2_ctrl_handler_free(&priv->hdl);
@@ -1112,9 +1190,16 @@ static const struct i2c_device_id ov2640_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, ov2640_id);
 
+static const struct of_device_id ov2640_of_match[] = {
+       {.compatible = "ovti,ov2640", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, ov2640_of_match);
+
 static struct i2c_driver ov2640_i2c_driver = {
        .driver = {
                .name = "ov2640",
+               .of_match_table = of_match_ptr(ov2640_of_match),
        },
        .probe    = ov2640_probe,
        .remove   = ov2640_remove,
index ed9ae8875348b6abdd226e3026e4b1d6f117c12f..9f7fdb6b61ca84a6c9f58feaa3600510911b9316 100644 (file)
@@ -52,10 +52,6 @@ MODULE_DESCRIPTION("TI THS7303 video amplifier driver");
 MODULE_AUTHOR("Chaithrika U S");
 MODULE_LICENSE("GPL");
 
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Debug level 0-1");
-
 static inline struct ths7303_state *to_state(struct v4l2_subdev *sd)
 {
        return container_of(sd, struct ths7303_state, sd);
index 4ebd329d7b426d8d8374691a4d03bf61947df2fd..73fc42bc2de65accfcb9bee95fdaa253be5ca1d4 100644 (file)
@@ -479,7 +479,6 @@ static int ths8200_remove(struct i2c_client *client)
 
        ths8200_s_power(sd, false);
        v4l2_async_unregister_subdev(&decoder->sd);
-       v4l2_device_unregister_subdev(sd);
 
        return 0;
 }
index 204204259ac654d85dc67d5ae3720bb13021c9d7..1c6bc306ecdcbf93489dd00d5cde6c5b410d7a72 100644 (file)
@@ -923,13 +923,13 @@ static const struct v4l2_ctrl_ops tvp514x_ctrl_ops = {
 /**
  * tvp514x_enum_mbus_code() - V4L2 decoder interface handler for enum_mbus_code
  * @sd: pointer to standard V4L2 sub-device structure
- * @fh: file handle
+ * @cfg: pad configuration
  * @code: pointer to v4l2_subdev_mbus_code_enum structure
  *
  * Enumertaes mbus codes supported
  */
 static int tvp514x_enum_mbus_code(struct v4l2_subdev *sd,
-                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_pad_config *cfg,
                                  struct v4l2_subdev_mbus_code_enum *code)
 {
        u32 pad = code->pad;
@@ -950,13 +950,13 @@ static int tvp514x_enum_mbus_code(struct v4l2_subdev *sd,
 /**
  * tvp514x_get_pad_format() - V4L2 decoder interface handler for get pad format
  * @sd: pointer to standard V4L2 sub-device structure
- * @fh: file handle
+ * @cfg: pad configuration
  * @format: pointer to v4l2_subdev_format structure
  *
  * Retrieves pad format which is active or tried based on requirement
  */
 static int tvp514x_get_pad_format(struct v4l2_subdev *sd,
-                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_pad_config *cfg,
                                  struct v4l2_subdev_format *format)
 {
        struct tvp514x_decoder *decoder = to_decoder(sd);
@@ -979,13 +979,13 @@ static int tvp514x_get_pad_format(struct v4l2_subdev *sd,
 /**
  * tvp514x_set_pad_format() - V4L2 decoder interface handler for set pad format
  * @sd: pointer to standard V4L2 sub-device structure
- * @fh: file handle
+ * @cfg: pad configuration
  * @format: pointer to v4l2_subdev_format structure
  *
  * Set pad format for the output pad
  */
 static int tvp514x_set_pad_format(struct v4l2_subdev *sd,
-                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_pad_config *cfg,
                                  struct v4l2_subdev_format *fmt)
 {
        struct tvp514x_decoder *decoder = to_decoder(sd);
@@ -1209,7 +1209,6 @@ static int tvp514x_remove(struct i2c_client *client)
        struct tvp514x_decoder *decoder = to_decoder(sd);
 
        v4l2_async_unregister_subdev(&decoder->sd);
-       v4l2_device_unregister_subdev(sd);
 #if defined(CONFIG_MEDIA_CONTROLLER)
        media_entity_cleanup(&decoder->sd.entity);
 #endif
index fe4870e22cfe687d421e7351c71ab226e4a63aea..787cdfb0874959c99ad9f662395964fb6c404e4c 100644 (file)
@@ -846,13 +846,13 @@ static const struct v4l2_ctrl_ops tvp7002_ctrl_ops = {
 /*
  * tvp7002_enum_mbus_code() - Enum supported digital video format on pad
  * @sd: pointer to standard V4L2 sub-device structure
- * @fh: file handle for the subdev
+ * @cfg: pad configuration
  * @code: pointer to subdev enum mbus code struct
  *
  * Enumerate supported digital video formats for pad.
  */
 static int
-tvp7002_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+tvp7002_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                       struct v4l2_subdev_mbus_code_enum *code)
 {
        /* Check requested format index is within range */
@@ -867,13 +867,13 @@ tvp7002_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 /*
  * tvp7002_get_pad_format() - get video format on pad
  * @sd: pointer to standard V4L2 sub-device structure
- * @fh: file handle for the subdev
+ * @cfg: pad configuration
  * @fmt: pointer to subdev format struct
  *
  * get video format for pad.
  */
 static int
-tvp7002_get_pad_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+tvp7002_get_pad_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                       struct v4l2_subdev_format *fmt)
 {
        struct tvp7002 *tvp7002 = to_tvp7002(sd);
@@ -890,16 +890,16 @@ tvp7002_get_pad_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 /*
  * tvp7002_set_pad_format() - set video format on pad
  * @sd: pointer to standard V4L2 sub-device structure
- * @fh: file handle for the subdev
+ * @cfg: pad configuration
  * @fmt: pointer to subdev format struct
  *
  * set video format for pad.
  */
 static int
-tvp7002_set_pad_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+tvp7002_set_pad_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                       struct v4l2_subdev_format *fmt)
 {
-       return tvp7002_get_pad_format(sd, fh, fmt);
+       return tvp7002_get_pad_format(sd, cfg, fmt);
 }
 
 /* V4L2 core operation handlers */
@@ -1116,7 +1116,6 @@ static int tvp7002_remove(struct i2c_client *c)
 #if defined(CONFIG_MEDIA_CONTROLLER)
        media_entity_cleanup(&device->sd.entity);
 #endif
-       v4l2_device_unregister_subdev(sd);
        v4l2_ctrl_handler_free(&device->hdl);
        return 0;
 }
index 912c2814c6cf3ec8ac77f29f487076691c2f7618..fee2d710bbf88fc1b839719d34a4d9c5b6a0a3cf 100644 (file)
@@ -32,6 +32,8 @@
  * Fix stop command
  */
 
+#include "smscoreapi.h"
+
 #include <linux/moduleparam.h>
 #include <linux/slab.h>
 #include <linux/firmware.h>
@@ -41,7 +43,6 @@
 #include <linux/mmc/sdio_ids.h>
 #include <linux/module.h>
 
-#include "smscoreapi.h"
 #include "sms-cards.h"
 #include "smsendian.h"
 
@@ -141,14 +142,14 @@ static void smssdio_interrupt(struct sdio_func *func)
         */
        (void)sdio_readb(func, SMSSDIO_INT, &ret);
        if (ret) {
-               sms_err("Unable to read interrupt register!\n");
+               pr_err("Unable to read interrupt register!\n");
                return;
        }
 
        if (smsdev->split_cb == NULL) {
                cb = smscore_getbuffer(smsdev->coredev);
                if (!cb) {
-                       sms_err("Unable to allocate data buffer!\n");
+                       pr_err("Unable to allocate data buffer!\n");
                        return;
                }
 
@@ -157,7 +158,7 @@ static void smssdio_interrupt(struct sdio_func *func)
                                         SMSSDIO_DATA,
                                         SMSSDIO_BLOCK_SIZE);
                if (ret) {
-                       sms_err("Error %d reading initial block!\n", ret);
+                       pr_err("Error %d reading initial block!\n", ret);
                        return;
                }
 
@@ -198,7 +199,7 @@ static void smssdio_interrupt(struct sdio_func *func)
                                         size);
                if (ret && ret != -EINVAL) {
                        smscore_putbuffer(smsdev->coredev, cb);
-                       sms_err("Error %d reading data from card!\n", ret);
+                       pr_err("Error %d reading data from card!\n", ret);
                        return;
                }
 
@@ -216,8 +217,8 @@ static void smssdio_interrupt(struct sdio_func *func)
                                                  smsdev->func->cur_blksize);
                                if (ret) {
                                        smscore_putbuffer(smsdev->coredev, cb);
-                                       sms_err("Error %d reading "
-                                               "data from card!\n", ret);
+                                       pr_err("Error %d reading data from card!\n",
+                                              ret);
                                        return;
                                }
 
@@ -278,7 +279,7 @@ static int smssdio_probe(struct sdio_func *func,
                goto free;
        }
 
-       ret = smscore_register_device(&params, &smsdev->coredev);
+       ret = smscore_register_device(&params, &smsdev->coredev, NULL);
        if (ret < 0)
                goto free;
 
index 4ec2a3c3f23c1642e939206ce808cd24c99e53f4..bc12060e0882109b06053bce2dc7c17ffb60fdea 100644 (file)
@@ -2474,7 +2474,7 @@ static int bttv_querycap(struct file *file, void  *priv,
                return -EINVAL;
 
        strlcpy(cap->driver, "bttv", sizeof(cap->driver));
-       strlcpy(cap->card, btv->video_dev->name, sizeof(cap->card));
+       strlcpy(cap->card, btv->video_dev.name, sizeof(cap->card));
        snprintf(cap->bus_info, sizeof(cap->bus_info),
                 "PCI:%s", pci_name(btv->c.pci));
        cap->capabilities =
@@ -2484,9 +2484,9 @@ static int bttv_querycap(struct file *file, void  *priv,
                V4L2_CAP_DEVICE_CAPS;
        if (no_overlay <= 0)
                cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
-       if (btv->vbi_dev)
+       if (video_is_registered(&btv->vbi_dev))
                cap->capabilities |= V4L2_CAP_VBI_CAPTURE;
-       if (btv->radio_dev)
+       if (video_is_registered(&btv->radio_dev))
                cap->capabilities |= V4L2_CAP_RADIO;
 
        /*
@@ -3905,18 +3905,14 @@ static irqreturn_t bttv_irq(int irq, void *dev_id)
 /* ----------------------------------------------------------------------- */
 /* initialization                                                          */
 
-static struct video_device *vdev_init(struct bttv *btv,
-                                     const struct video_device *template,
-                                     const char *type_name)
+static void vdev_init(struct bttv *btv,
+                     struct video_device *vfd,
+                     const struct video_device *template,
+                     const char *type_name)
 {
-       struct video_device *vfd;
-
-       vfd = video_device_alloc();
-       if (NULL == vfd)
-               return NULL;
        *vfd = *template;
        vfd->v4l2_dev = &btv->c.v4l2_dev;
-       vfd->release = video_device_release;
+       vfd->release = video_device_release_empty;
        video_set_drvdata(vfd, btv);
        snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
                 btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "",
@@ -3927,32 +3923,13 @@ static struct video_device *vdev_init(struct bttv *btv,
                v4l2_disable_ioctl(vfd, VIDIOC_G_TUNER);
                v4l2_disable_ioctl(vfd, VIDIOC_S_TUNER);
        }
-       return vfd;
 }
 
 static void bttv_unregister_video(struct bttv *btv)
 {
-       if (btv->video_dev) {
-               if (video_is_registered(btv->video_dev))
-                       video_unregister_device(btv->video_dev);
-               else
-                       video_device_release(btv->video_dev);
-               btv->video_dev = NULL;
-       }
-       if (btv->vbi_dev) {
-               if (video_is_registered(btv->vbi_dev))
-                       video_unregister_device(btv->vbi_dev);
-               else
-                       video_device_release(btv->vbi_dev);
-               btv->vbi_dev = NULL;
-       }
-       if (btv->radio_dev) {
-               if (video_is_registered(btv->radio_dev))
-                       video_unregister_device(btv->radio_dev);
-               else
-                       video_device_release(btv->radio_dev);
-               btv->radio_dev = NULL;
-       }
+       video_unregister_device(&btv->video_dev);
+       video_unregister_device(&btv->vbi_dev);
+       video_unregister_device(&btv->radio_dev);
 }
 
 /* register video4linux devices */
@@ -3962,44 +3939,38 @@ static int bttv_register_video(struct bttv *btv)
                pr_notice("Overlay support disabled\n");
 
        /* video */
-       btv->video_dev = vdev_init(btv, &bttv_video_template, "video");
+       vdev_init(btv, &btv->video_dev, &bttv_video_template, "video");
 
-       if (NULL == btv->video_dev)
-               goto err;
-       if (video_register_device(btv->video_dev, VFL_TYPE_GRABBER,
+       if (video_register_device(&btv->video_dev, VFL_TYPE_GRABBER,
                                  video_nr[btv->c.nr]) < 0)
                goto err;
        pr_info("%d: registered device %s\n",
-               btv->c.nr, video_device_node_name(btv->video_dev));
-       if (device_create_file(&btv->video_dev->dev,
+               btv->c.nr, video_device_node_name(&btv->video_dev));
+       if (device_create_file(&btv->video_dev.dev,
                                     &dev_attr_card)<0) {
                pr_err("%d: device_create_file 'card' failed\n", btv->c.nr);
                goto err;
        }
 
        /* vbi */
-       btv->vbi_dev = vdev_init(btv, &bttv_video_template, "vbi");
+       vdev_init(btv, &btv->vbi_dev, &bttv_video_template, "vbi");
 
-       if (NULL == btv->vbi_dev)
-               goto err;
-       if (video_register_device(btv->vbi_dev, VFL_TYPE_VBI,
+       if (video_register_device(&btv->vbi_dev, VFL_TYPE_VBI,
                                  vbi_nr[btv->c.nr]) < 0)
                goto err;
        pr_info("%d: registered device %s\n",
-               btv->c.nr, video_device_node_name(btv->vbi_dev));
+               btv->c.nr, video_device_node_name(&btv->vbi_dev));
 
        if (!btv->has_radio)
                return 0;
        /* radio */
-       btv->radio_dev = vdev_init(btv, &radio_template, "radio");
-       if (NULL == btv->radio_dev)
-               goto err;
-       btv->radio_dev->ctrl_handler = &btv->radio_ctrl_handler;
-       if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,
+       vdev_init(btv, &btv->radio_dev, &radio_template, "radio");
+       btv->radio_dev.ctrl_handler = &btv->radio_ctrl_handler;
+       if (video_register_device(&btv->radio_dev, VFL_TYPE_RADIO,
                                  radio_nr[btv->c.nr]) < 0)
                goto err;
        pr_info("%d: registered device %s\n",
-               btv->c.nr, video_device_node_name(btv->radio_dev));
+               btv->c.nr, video_device_node_name(&btv->radio_dev));
 
        /* all done */
        return 0;
index bc048c586b1fe0e78cea38fa95ee72a2fab8c6de..a444cfb35c0b8a37cc6f9d1ffc78e1918aab008a 100644 (file)
@@ -404,9 +404,9 @@ struct bttv {
        struct v4l2_subdev        *sd_tda7432;
 
        /* video4linux (1) */
-       struct video_device *video_dev;
-       struct video_device *radio_dev;
-       struct video_device *vbi_dev;
+       struct video_device video_dev;
+       struct video_device radio_dev;
+       struct video_device vbi_dev;
 
        /* controls */
        struct v4l2_ctrl_handler   ctrl_handler;
index ea272bcb38df14e086f226fe024ec17e0ef98574..0b0e8015ad34bf6a8a8554c73352080e54932cc9 100644 (file)
@@ -216,7 +216,7 @@ static int cx18_alsa_load(struct cx18 *cx)
        }
 
        s = &cx->streams[CX18_ENC_STREAM_TYPE_PCM];
-       if (s->video_dev == NULL) {
+       if (s->video_dev.v4l2_dev == NULL) {
                CX18_DEBUG_ALSA_INFO("%s: PCM stream for card is disabled - "
                                     "skipping\n", __func__);
                return 0;
index 207d6e82403bd382266270c45881771d3b0d080d..b15beed2dc143f6f3fabcbcadc34be76165ea2be 100644 (file)
@@ -373,7 +373,7 @@ struct cx18_in_work_order {
 struct cx18_stream {
        /* These first five fields are always set, even if the stream
           is not actually created. */
-       struct video_device *video_dev; /* NULL when stream not created */
+       struct video_device video_dev;  /* v4l2_dev is NULL when stream not created */
        struct cx18_dvb *dvb;           /* DVB / Digital Transport */
        struct cx18 *cx;                /* for ease of use */
        const char *name;               /* name of the stream */
@@ -409,6 +409,7 @@ struct cx18_stream {
        /* Videobuf for YUV video */
        u32 pixelformat;
        u32 vb_bytes_per_frame;
+       u32 vb_bytes_per_line;
        struct list_head vb_capture;    /* video capture queue */
        spinlock_t vb_lock;
        struct timer_list vb_timeout;
index 76a3b4ac541e10670e0cb24c931d076bdd100af5..df837408efd595f67dc9c2c8e6263039f54d4177 100644 (file)
@@ -34,6 +34,7 @@
 #include "cx18-controls.h"
 #include "cx18-ioctl.h"
 #include "cx18-cards.h"
+#include <media/v4l2-event.h>
 
 /* This function tries to claim the stream for a specific file descriptor.
    If no one else is using this stream then the stream is claimed and
@@ -609,13 +610,16 @@ ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count,
 
 unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait)
 {
+       unsigned long req_events = poll_requested_events(wait);
        struct cx18_open_id *id = file2id(filp);
        struct cx18 *cx = id->cx;
        struct cx18_stream *s = &cx->streams[id->type];
        int eof = test_bit(CX18_F_S_STREAMOFF, &s->s_flags);
+       unsigned res = 0;
 
        /* Start a capture if there is none */
-       if (!eof && !test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
+       if (!eof && !test_bit(CX18_F_S_STREAMING, &s->s_flags) &&
+                       (req_events & (POLLIN | POLLRDNORM))) {
                int rc;
 
                mutex_lock(&cx->serialize_lock);
@@ -632,21 +636,26 @@ unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait)
        if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
                (id->type == CX18_ENC_STREAM_TYPE_YUV)) {
                int videobuf_poll = videobuf_poll_stream(filp, &s->vbuf_q, wait);
+
+               if (v4l2_event_pending(&id->fh))
+                       res |= POLLPRI;
                 if (eof && videobuf_poll == POLLERR)
-                        return POLLHUP;
-                else
-                        return videobuf_poll;
+                       return res | POLLHUP;
+               return res | videobuf_poll;
        }
 
        /* add stream's waitq to the poll list */
        CX18_DEBUG_HI_FILE("Encoder poll\n");
-       poll_wait(filp, &s->waitq, wait);
+       if (v4l2_event_pending(&id->fh))
+               res |= POLLPRI;
+       else
+               poll_wait(filp, &s->waitq, wait);
 
        if (atomic_read(&s->q_full.depth))
-               return POLLIN | POLLRDNORM;
+               return res | POLLIN | POLLRDNORM;
        if (eof)
-               return POLLHUP;
-       return 0;
+               return res | POLLHUP;
+       return res;
 }
 
 int cx18_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
@@ -797,7 +806,7 @@ static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
                CX18_DEBUG_WARN("nomem on v4l2 open\n");
                return -ENOMEM;
        }
-       v4l2_fh_init(&item->fh, s->video_dev);
+       v4l2_fh_init(&item->fh, &s->video_dev);
 
        item->cx = cx;
        item->type = s->type;
index b8e4b68a91963c1c0d10d6f0bb011d9ae4f222e1..79aee30d5fd8631379214519ae01df54f8837b95 100644 (file)
@@ -39,6 +39,7 @@
 #include "cx18-cards.h"
 #include "cx18-av-core.h"
 #include <media/tveeprom.h>
+#include <media/v4l2-event.h>
 
 u16 cx18_service2vbi(int type)
 {
@@ -159,7 +160,7 @@ static int cx18_g_fmt_vid_cap(struct file *file, void *fh,
        if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
                pixfmt->pixelformat = s->pixelformat;
                pixfmt->sizeimage = s->vb_bytes_per_frame;
-               pixfmt->bytesperline = 720;
+               pixfmt->bytesperline = s->vb_bytes_per_line;
        } else {
                pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
                pixfmt->sizeimage = 128 * 1024;
@@ -287,10 +288,13 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh,
        s->pixelformat = fmt->fmt.pix.pixelformat;
        /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
           UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
-       if (s->pixelformat == V4L2_PIX_FMT_HM12)
+       if (s->pixelformat == V4L2_PIX_FMT_HM12) {
                s->vb_bytes_per_frame = h * 720 * 3 / 2;
-       else
+               s->vb_bytes_per_line = 720; /* First plane */
+       } else {
                s->vb_bytes_per_frame = h * 720 * 2;
+               s->vb_bytes_per_line = 1440; /* Packed */
+       }
 
        mbus_fmt.width = cx->cxhdl.width = w;
        mbus_fmt.height = cx->cxhdl.height = h;
@@ -447,34 +451,29 @@ static int cx18_cropcap(struct file *file, void *fh,
 
        if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
                return -EINVAL;
-       cropcap->bounds.top = cropcap->bounds.left = 0;
-       cropcap->bounds.width = 720;
-       cropcap->bounds.height = cx->is_50hz ? 576 : 480;
        cropcap->pixelaspect.numerator = cx->is_50hz ? 59 : 10;
        cropcap->pixelaspect.denominator = cx->is_50hz ? 54 : 11;
-       cropcap->defrect = cropcap->bounds;
        return 0;
 }
 
-static int cx18_s_crop(struct file *file, void *fh, const struct v4l2_crop *crop)
-{
-       struct cx18_open_id *id = fh2id(fh);
-       struct cx18 *cx = id->cx;
-
-       if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-       CX18_DEBUG_WARN("VIDIOC_S_CROP not implemented\n");
-       return -EINVAL;
-}
-
-static int cx18_g_crop(struct file *file, void *fh, struct v4l2_crop *crop)
+static int cx18_g_selection(struct file *file, void *fh,
+                           struct v4l2_selection *sel)
 {
        struct cx18 *cx = fh2id(fh)->cx;
 
-       if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+       if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
                return -EINVAL;
-       CX18_DEBUG_WARN("VIDIOC_G_CROP not implemented\n");
-       return -EINVAL;
+       switch (sel->target) {
+       case V4L2_SEL_TGT_CROP_BOUNDS:
+       case V4L2_SEL_TGT_CROP_DEFAULT:
+               sel->r.top = sel->r.left = 0;
+               sel->r.width = 720;
+               sel->r.height = cx->is_50hz ? 576 : 480;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
 }
 
 static int cx18_enum_fmt_vid_cap(struct file *file, void *fh,
@@ -510,6 +509,9 @@ int cx18_s_input(struct file *file, void *fh, unsigned int inp)
 {
        struct cx18_open_id *id = fh2id(fh);
        struct cx18 *cx = id->cx;
+       v4l2_std_id std = V4L2_STD_ALL;
+       const struct cx18_card_video_input *card_input =
+                               cx->card->video_inputs + inp;
 
        if (inp >= cx->nof_inputs)
                return -EINVAL;
@@ -525,6 +527,11 @@ int cx18_s_input(struct file *file, void *fh, unsigned int inp)
        cx->active_input = inp;
        /* Set the audio input to whatever is appropriate for the input type. */
        cx->audio_input = cx->card->video_inputs[inp].audio_index;
+       if (card_input->video_type == V4L2_INPUT_TYPE_TUNER)
+               std = cx->tuner_std;
+       cx->streams[CX18_ENC_STREAM_TYPE_MPG].video_dev.tvnorms = std;
+       cx->streams[CX18_ENC_STREAM_TYPE_YUV].video_dev.tvnorms = std;
+       cx->streams[CX18_ENC_STREAM_TYPE_VBI].video_dev.tvnorms = std;
 
        /* prevent others from messing with the streams until
           we're finished changing inputs. */
@@ -1036,7 +1043,7 @@ static int cx18_log_status(struct file *file, void *fh)
        for (i = 0; i < CX18_MAX_STREAMS; i++) {
                struct cx18_stream *s = &cx->streams[i];
 
-               if (s->video_dev == NULL || s->buffers == 0)
+               if (s->video_dev.v4l2_dev == NULL || s->buffers == 0)
                        continue;
                CX18_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n",
                          s->name, s->s_flags,
@@ -1078,8 +1085,7 @@ static const struct v4l2_ioctl_ops cx18_ioctl_ops = {
        .vidioc_enumaudio               = cx18_enumaudio,
        .vidioc_enum_input              = cx18_enum_input,
        .vidioc_cropcap                 = cx18_cropcap,
-       .vidioc_s_crop                  = cx18_s_crop,
-       .vidioc_g_crop                  = cx18_g_crop,
+       .vidioc_g_selection             = cx18_g_selection,
        .vidioc_g_input                 = cx18_g_input,
        .vidioc_s_input                 = cx18_s_input,
        .vidioc_g_frequency             = cx18_g_frequency,
@@ -1114,6 +1120,8 @@ static const struct v4l2_ioctl_ops cx18_ioctl_ops = {
        .vidioc_querybuf                = cx18_querybuf,
        .vidioc_qbuf                    = cx18_qbuf,
        .vidioc_dqbuf                   = cx18_dqbuf,
+       .vidioc_subscribe_event         = v4l2_ctrl_subscribe_event,
+       .vidioc_unsubscribe_event       = v4l2_event_unsubscribe,
 };
 
 void cx18_set_funcs(struct video_device *vdev)
index 369445fcf3e5bea7016969365fa0e2cc988821d0..c82d25d53341615d5da907a071aacb85cb4437b9 100644 (file)
@@ -254,11 +254,8 @@ static struct videobuf_queue_ops cx18_videobuf_qops = {
 static void cx18_stream_init(struct cx18 *cx, int type)
 {
        struct cx18_stream *s = &cx->streams[type];
-       struct video_device *video_dev = s->video_dev;
 
-       /* we need to keep video_dev, so restore it afterwards */
        memset(s, 0, sizeof(*s));
-       s->video_dev = video_dev;
 
        /* initialize cx18_stream fields */
        s->dvb = NULL;
@@ -307,6 +304,7 @@ static void cx18_stream_init(struct cx18 *cx, int type)
                /* Assume the previous pixel default */
                s->pixelformat = V4L2_PIX_FMT_HM12;
                s->vb_bytes_per_frame = cx->cxhdl.height * 720 * 3 / 2;
+               s->vb_bytes_per_line = 720;
        }
 }
 
@@ -319,12 +317,12 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
 
        /*
         * These five fields are always initialized.
-        * For analog capture related streams, if video_dev == NULL then the
+        * For analog capture related streams, if video_dev.v4l2_dev == NULL then the
         * stream is not in use.
         * For the TS stream, if dvb == NULL then the stream is not in use.
         * In those cases no other fields but these four can be used.
         */
-       s->video_dev = NULL;
+       s->video_dev.v4l2_dev = NULL;
        s->dvb = NULL;
        s->cx = cx;
        s->type = type;
@@ -367,24 +365,20 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
        if (num_offset == -1)
                return 0;
 
-       /* allocate and initialize the v4l2 video device structure */
-       s->video_dev = video_device_alloc();
-       if (s->video_dev == NULL) {
-               CX18_ERR("Couldn't allocate v4l2 video_device for %s\n",
-                               s->name);
-               return -ENOMEM;
-       }
-
-       snprintf(s->video_dev->name, sizeof(s->video_dev->name), "%s %s",
+       /* initialize the v4l2 video device structure */
+       snprintf(s->video_dev.name, sizeof(s->video_dev.name), "%s %s",
                 cx->v4l2_dev.name, s->name);
 
-       s->video_dev->num = num;
-       s->video_dev->v4l2_dev = &cx->v4l2_dev;
-       s->video_dev->fops = &cx18_v4l2_enc_fops;
-       s->video_dev->release = video_device_release;
-       s->video_dev->tvnorms = V4L2_STD_ALL;
-       s->video_dev->lock = &cx->serialize_lock;
-       cx18_set_funcs(s->video_dev);
+       s->video_dev.num = num;
+       s->video_dev.v4l2_dev = &cx->v4l2_dev;
+       s->video_dev.fops = &cx18_v4l2_enc_fops;
+       s->video_dev.release = video_device_release_empty;
+       if (cx->card->video_inputs->video_type == CX18_CARD_INPUT_VID_TUNER)
+               s->video_dev.tvnorms = cx->tuner_std;
+       else
+               s->video_dev.tvnorms = V4L2_STD_ALL;
+       s->video_dev.lock = &cx->serialize_lock;
+       cx18_set_funcs(&s->video_dev);
        return 0;
 }
 
@@ -428,31 +422,30 @@ static int cx18_reg_dev(struct cx18 *cx, int type)
                }
        }
 
-       if (s->video_dev == NULL)
+       if (s->video_dev.v4l2_dev == NULL)
                return 0;
 
-       num = s->video_dev->num;
+       num = s->video_dev.num;
        /* card number + user defined offset + device offset */
        if (type != CX18_ENC_STREAM_TYPE_MPG) {
                struct cx18_stream *s_mpg = &cx->streams[CX18_ENC_STREAM_TYPE_MPG];
 
-               if (s_mpg->video_dev)
-                       num = s_mpg->video_dev->num
+               if (s_mpg->video_dev.v4l2_dev)
+                       num = s_mpg->video_dev.num
                            + cx18_stream_info[type].num_offset;
        }
-       video_set_drvdata(s->video_dev, s);
+       video_set_drvdata(&s->video_dev, s);
 
        /* Register device. First try the desired minor, then any free one. */
-       ret = video_register_device_no_warn(s->video_dev, vfl_type, num);
+       ret = video_register_device_no_warn(&s->video_dev, vfl_type, num);
        if (ret < 0) {
                CX18_ERR("Couldn't register v4l2 device for %s (device node number %d)\n",
                        s->name, num);
-               video_device_release(s->video_dev);
-               s->video_dev = NULL;
+               s->video_dev.v4l2_dev = NULL;
                return ret;
        }
 
-       name = video_device_node_name(s->video_dev);
+       name = video_device_node_name(&s->video_dev);
 
        switch (vfl_type) {
        case VFL_TYPE_GRABBER:
@@ -542,10 +535,9 @@ void cx18_streams_cleanup(struct cx18 *cx, int unregister)
                }
 
                /* If struct video_device exists, can have buffers allocated */
-               vdev = cx->streams[type].video_dev;
+               vdev = &cx->streams[type].video_dev;
 
-               cx->streams[type].video_dev = NULL;
-               if (vdev == NULL)
+               if (vdev->v4l2_dev == NULL)
                        continue;
 
                if (type == CX18_ENC_STREAM_TYPE_YUV)
@@ -553,11 +545,7 @@ void cx18_streams_cleanup(struct cx18 *cx, int unregister)
 
                cx18_stream_free(&cx->streams[type]);
 
-               /* Unregister or release device */
-               if (unregister)
-                       video_unregister_device(vdev);
-               else
-                       video_device_release(vdev);
+               video_unregister_device(vdev);
        }
 }
 
@@ -1042,7 +1030,7 @@ u32 cx18_find_handle(struct cx18 *cx)
        for (i = 0; i < CX18_MAX_STREAMS; i++) {
                struct cx18_stream *s = &cx->streams[i];
 
-               if (s->video_dev && (s->handle != CX18_INVALID_TASK_HANDLE))
+               if (s->video_dev.v4l2_dev && (s->handle != CX18_INVALID_TASK_HANDLE))
                        return s->handle;
        }
        return CX18_INVALID_TASK_HANDLE;
index 713b0e61536dd6a8f9edd330d708c0388f13d447..27f8af9b11cdbdea0536ecf63655e3ba09b7a441 100644 (file)
@@ -33,7 +33,7 @@ void cx18_stream_rotate_idx_mdls(struct cx18 *cx);
 
 static inline bool cx18_stream_enabled(struct cx18_stream *s)
 {
-       return s->video_dev ||
+       return s->video_dev.v4l2_dev ||
               (s->dvb && s->dvb->enabled) ||
               (s->type == CX18_ENC_STREAM_TYPE_IDX &&
                s->cx->stream_buffers[CX18_ENC_STREAM_TYPE_IDX] != 0);
index 74d774e5227be102d8552cdb5e71026bb20dc684..2e1b88ccdbf23d16c9adac53812d210c89f9cc35 100644 (file)
@@ -40,7 +40,6 @@ config VIDEO_CX23885
        select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT
        select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT
        select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT
-       select MEDIA_TUNER_M88TS2022 if MEDIA_SUBDRV_AUTOSELECT
        select MEDIA_TUNER_M88RS6000T if MEDIA_SUBDRV_AUTOSELECT
        select DVB_TUNER_DIB0070 if MEDIA_SUBDRV_AUTOSELECT
        ---help---
index 2bbbf545b0422d0eca0548e4e30989c22bc5a0dc..0a91df2c9f085c5327ec7245eebabdec8d816680 100644 (file)
@@ -483,7 +483,6 @@ static void altera_hw_filt_release(void *main_dev, int filt_nr)
        }
 
 }
-EXPORT_SYMBOL(altera_hw_filt_release);
 
 void altera_ci_release(void *dev, int ci_nr)
 {
@@ -598,7 +597,6 @@ static int altera_pid_feed_control(void *demux_dev, int filt_nr,
 
        return 0;
 }
-EXPORT_SYMBOL(altera_pid_feed_control);
 
 static int altera_ci_start_feed(struct dvb_demux_feed *feed, int num)
 {
@@ -699,7 +697,6 @@ err:
 
        return ret;
 }
-EXPORT_SYMBOL(altera_hw_filt_init);
 
 int altera_ci_init(struct altera_ci_config *config, int ci_nr)
 {
index 5028f0cf83f43a87b7e93270c0d6fb8c277bb584..6c511723fd1ba5b291d28b67c33d20f7aaf82cee 100644 (file)
@@ -39,7 +39,7 @@ struct altera_ci_config {
        int (*fpga_rw) (void *dev, int ad_rg, int val, int rw);
 };
 
-#if IS_ENABLED(CONFIG_MEDIA_ALTERA_CI)
+#if IS_REACHABLE(CONFIG_MEDIA_ALTERA_CI)
 
 extern int altera_ci_init(struct altera_ci_config *config, int ci_nr);
 extern void altera_ci_release(void *dev, int ci_nr);
index 1ad49946d7fa9c1ef8f6cb71d8e91c85d566e4a6..7aee76af7a85552526dcf73cf8c70330d1bfd411 100644 (file)
@@ -825,6 +825,7 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
        int i;
 
        spin_lock_init(&dev->pci_irqmask_lock);
+       spin_lock_init(&dev->slock);
 
        mutex_init(&dev->lock);
        mutex_init(&dev->gpio_lock);
index 45fbe1e4d2d06348977d7163a1febd150efc7315..745caabe33971f1d279c58d220117d41ce5cb99b 100644 (file)
@@ -73,7 +73,6 @@
 #include "si2157.h"
 #include "sp2.h"
 #include "m88ds3103.h"
-#include "m88ts2022.h"
 #include "m88rs6000t.h"
 
 static unsigned int debug;
@@ -1187,7 +1186,7 @@ static int dvb_register(struct cx23885_tsport *port)
        struct vb2_dvb_frontend *fe0, *fe1 = NULL;
        struct si2168_config si2168_config;
        struct si2157_config si2157_config;
-       struct m88ts2022_config m88ts2022_config;
+       struct ts2020_config ts2020_config;
        struct i2c_board_info info;
        struct i2c_adapter *adapter;
        struct i2c_client *client_demod = NULL, *client_tuner = NULL;
@@ -1856,13 +1855,12 @@ static int dvb_register(struct cx23885_tsport *port)
                                break;
 
                        /* attach tuner */
-                       memset(&m88ts2022_config, 0, sizeof(m88ts2022_config));
-                       m88ts2022_config.fe = fe0->dvb.frontend;
-                       m88ts2022_config.clock = 27000000;
+                       memset(&ts2020_config, 0, sizeof(ts2020_config));
+                       ts2020_config.fe = fe0->dvb.frontend;
                        memset(&info, 0, sizeof(struct i2c_board_info));
-                       strlcpy(info.type, "m88ts2022", I2C_NAME_SIZE);
+                       strlcpy(info.type, "ts2020", I2C_NAME_SIZE);
                        info.addr = 0x60;
-                       info.platform_data = &m88ts2022_config;
+                       info.platform_data = &ts2020_config;
                        request_module(info.type);
                        client_tuner = i2c_new_device(adapter, &info);
                        if (client_tuner == NULL ||
@@ -1986,13 +1984,12 @@ static int dvb_register(struct cx23885_tsport *port)
                        break;
 
                /* attach tuner */
-               memset(&m88ts2022_config, 0, sizeof(m88ts2022_config));
-               m88ts2022_config.fe = fe0->dvb.frontend;
-               m88ts2022_config.clock = 27000000;
+               memset(&ts2020_config, 0, sizeof(ts2020_config));
+               ts2020_config.fe = fe0->dvb.frontend;
                memset(&info, 0, sizeof(struct i2c_board_info));
-               strlcpy(info.type, "m88ts2022", I2C_NAME_SIZE);
+               strlcpy(info.type, "ts2020", I2C_NAME_SIZE);
                info.addr = 0x60;
-               info.platform_data = &m88ts2022_config;
+               info.platform_data = &ts2020_config;
                request_module(info.type);
                client_tuner = i2c_new_device(adapter, &info);
                if (client_tuner == NULL || client_tuner->dev.driver == NULL)
@@ -2032,13 +2029,12 @@ static int dvb_register(struct cx23885_tsport *port)
                        break;
 
                /* attach tuner */
-               memset(&m88ts2022_config, 0, sizeof(m88ts2022_config));
-               m88ts2022_config.fe = fe0->dvb.frontend;
-               m88ts2022_config.clock = 27000000;
+               memset(&ts2020_config, 0, sizeof(ts2020_config));
+               ts2020_config.fe = fe0->dvb.frontend;
                memset(&info, 0, sizeof(struct i2c_board_info));
-               strlcpy(info.type, "m88ts2022", I2C_NAME_SIZE);
+               strlcpy(info.type, "ts2020", I2C_NAME_SIZE);
                info.addr = 0x60;
-               info.platform_data = &m88ts2022_config;
+               info.platform_data = &ts2020_config;
                request_module(info.type);
                client_tuner = i2c_new_device(adapter, &info);
                if (client_tuner == NULL || client_tuner->dev.driver == NULL)
index 5e93c682a3f5b7a3d915092f3128a3b5daa62977..2232b389c441dce40da4d79992a5fd7d1655b8a6 100644 (file)
@@ -1137,7 +1137,6 @@ int cx23885_video_register(struct cx23885_dev *dev)
        int err;
 
        dprintk(1, "%s()\n", __func__);
-       spin_lock_init(&dev->slock);
 
        /* Initialize VBI template */
        cx23885_vbi_template = cx23885_video_template;
index b6be46e942895d43a179eafa00728b36ff876cf5..24216efa56e76fda79e7cf42c799f74e9fe81d4e 100644 (file)
@@ -1102,32 +1102,26 @@ static int cx8802_blackbird_advise_release(struct cx8802_driver *drv)
 
 static void blackbird_unregister_video(struct cx8802_dev *dev)
 {
-       if (dev->mpeg_dev) {
-               if (video_is_registered(dev->mpeg_dev))
-                       video_unregister_device(dev->mpeg_dev);
-               else
-                       video_device_release(dev->mpeg_dev);
-               dev->mpeg_dev = NULL;
-       }
+       video_unregister_device(&dev->mpeg_dev);
 }
 
 static int blackbird_register_video(struct cx8802_dev *dev)
 {
        int err;
 
-       dev->mpeg_dev = cx88_vdev_init(dev->core, dev->pci,
-                                      &cx8802_mpeg_template, "mpeg");
-       dev->mpeg_dev->ctrl_handler = &dev->cxhdl.hdl;
-       video_set_drvdata(dev->mpeg_dev, dev);
-       dev->mpeg_dev->queue = &dev->vb2_mpegq;
-       err = video_register_device(dev->mpeg_dev, VFL_TYPE_GRABBER, -1);
+       cx88_vdev_init(dev->core, dev->pci, &dev->mpeg_dev,
+                      &cx8802_mpeg_template, "mpeg");
+       dev->mpeg_dev.ctrl_handler = &dev->cxhdl.hdl;
+       video_set_drvdata(&dev->mpeg_dev, dev);
+       dev->mpeg_dev.queue = &dev->vb2_mpegq;
+       err = video_register_device(&dev->mpeg_dev, VFL_TYPE_GRABBER, -1);
        if (err < 0) {
                printk(KERN_INFO "%s/2: can't register mpeg device\n",
                       dev->core->name);
                return err;
        }
        printk(KERN_INFO "%s/2: registered device %s [mpeg]\n",
-              dev->core->name, video_device_node_name(dev->mpeg_dev));
+              dev->core->name, video_device_node_name(&dev->mpeg_dev));
        return 0;
 }
 
index c38d5a12e277fc808dc146a41c75f8e9a1ac507b..3501be9f19d8646b3d2c22ecbfc20bd9b8b590ac 100644 (file)
@@ -985,17 +985,14 @@ int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm)
 
 /* ------------------------------------------------------------------ */
 
-struct video_device *cx88_vdev_init(struct cx88_core *core,
-                                   struct pci_dev *pci,
-                                   const struct video_device *template_,
-                                   const char *type)
+void cx88_vdev_init(struct cx88_core *core,
+                   struct pci_dev *pci,
+                   struct video_device *vfd,
+                   const struct video_device *template_,
+                   const char *type)
 {
-       struct video_device *vfd;
-
-       vfd = video_device_alloc();
-       if (NULL == vfd)
-               return NULL;
        *vfd = *template_;
+
        /*
         * The dev pointer of v4l2_device is NULL, instead we set the
         * video_device dev_parent pointer to the correct PCI bus device.
@@ -1004,11 +1001,10 @@ struct video_device *cx88_vdev_init(struct cx88_core *core,
         */
        vfd->v4l2_dev = &core->v4l2_dev;
        vfd->dev_parent = &pci->dev;
-       vfd->release = video_device_release;
+       vfd->release = video_device_release_empty;
        vfd->lock = &core->lock;
        snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
                 core->name, type, core->board.name);
-       return vfd;
 }
 
 struct cx88_core* cx88_core_get(struct pci_dev *pci)
index a369b0840acffde2584e78bdba236eb0ed9c2e5f..98344540c51f83bb57be721a98d9c8b6288357c2 100644 (file)
@@ -732,7 +732,7 @@ static int cx8802_probe(struct pci_dev *pci_dev,
        dev->alloc_ctx = vb2_dma_sg_init_ctx(&pci_dev->dev);
        if (IS_ERR(dev->alloc_ctx)) {
                err = PTR_ERR(dev->alloc_ctx);
-               goto fail_core;
+               goto fail_dev;
        }
        dev->core = core;
 
@@ -754,6 +754,7 @@ static int cx8802_probe(struct pci_dev *pci_dev,
 
  fail_free:
        vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
+ fail_dev:
        kfree(dev);
  fail_core:
        core->dvbdev = NULL;
index 860c98fc72c7f95f12763fc2c0edfaacb8a76890..c9decd80bf619c0e750350f4c39fb89dd1cb1d45 100644 (file)
@@ -1274,27 +1274,9 @@ static const struct v4l2_ctrl_ops cx8800_ctrl_aud_ops = {
 
 static void cx8800_unregister_video(struct cx8800_dev *dev)
 {
-       if (dev->radio_dev) {
-               if (video_is_registered(dev->radio_dev))
-                       video_unregister_device(dev->radio_dev);
-               else
-                       video_device_release(dev->radio_dev);
-               dev->radio_dev = NULL;
-       }
-       if (dev->vbi_dev) {
-               if (video_is_registered(dev->vbi_dev))
-                       video_unregister_device(dev->vbi_dev);
-               else
-                       video_device_release(dev->vbi_dev);
-               dev->vbi_dev = NULL;
-       }
-       if (dev->video_dev) {
-               if (video_is_registered(dev->video_dev))
-                       video_unregister_device(dev->video_dev);
-               else
-                       video_device_release(dev->video_dev);
-               dev->video_dev = NULL;
-       }
+       video_unregister_device(&dev->radio_dev);
+       video_unregister_device(&dev->vbi_dev);
+       video_unregister_device(&dev->video_dev);
 }
 
 static int cx8800_initdev(struct pci_dev *pci_dev,
@@ -1485,12 +1467,12 @@ static int cx8800_initdev(struct pci_dev *pci_dev,
                goto fail_unreg;
 
        /* register v4l devices */
-       dev->video_dev = cx88_vdev_init(core,dev->pci,
-                                       &cx8800_video_template,"video");
-       video_set_drvdata(dev->video_dev, dev);
-       dev->video_dev->ctrl_handler = &core->video_hdl;
-       dev->video_dev->queue = &dev->vb2_vidq;
-       err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER,
+       cx88_vdev_init(core, dev->pci, &dev->video_dev,
+                      &cx8800_video_template, "video");
+       video_set_drvdata(&dev->video_dev, dev);
+       dev->video_dev.ctrl_handler = &core->video_hdl;
+       dev->video_dev.queue = &dev->vb2_vidq;
+       err = video_register_device(&dev->video_dev, VFL_TYPE_GRABBER,
                                    video_nr[core->nr]);
        if (err < 0) {
                printk(KERN_ERR "%s/0: can't register video device\n",
@@ -1498,12 +1480,13 @@ static int cx8800_initdev(struct pci_dev *pci_dev,
                goto fail_unreg;
        }
        printk(KERN_INFO "%s/0: registered device %s [v4l2]\n",
-              core->name, video_device_node_name(dev->video_dev));
+              core->name, video_device_node_name(&dev->video_dev));
 
-       dev->vbi_dev = cx88_vdev_init(core,dev->pci,&cx8800_vbi_template,"vbi");
-       video_set_drvdata(dev->vbi_dev, dev);
-       dev->vbi_dev->queue = &dev->vb2_vbiq;
-       err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI,
+       cx88_vdev_init(core, dev->pci, &dev->vbi_dev,
+                      &cx8800_vbi_template, "vbi");
+       video_set_drvdata(&dev->vbi_dev, dev);
+       dev->vbi_dev.queue = &dev->vb2_vbiq;
+       err = video_register_device(&dev->vbi_dev, VFL_TYPE_VBI,
                                    vbi_nr[core->nr]);
        if (err < 0) {
                printk(KERN_ERR "%s/0: can't register vbi device\n",
@@ -1511,14 +1494,14 @@ static int cx8800_initdev(struct pci_dev *pci_dev,
                goto fail_unreg;
        }
        printk(KERN_INFO "%s/0: registered device %s\n",
-              core->name, video_device_node_name(dev->vbi_dev));
+              core->name, video_device_node_name(&dev->vbi_dev));
 
        if (core->board.radio.type == CX88_RADIO) {
-               dev->radio_dev = cx88_vdev_init(core,dev->pci,
-                                               &cx8800_radio_template,"radio");
-               video_set_drvdata(dev->radio_dev, dev);
-               dev->radio_dev->ctrl_handler = &core->audio_hdl;
-               err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO,
+               cx88_vdev_init(core, dev->pci, &dev->radio_dev,
+                              &cx8800_radio_template, "radio");
+               video_set_drvdata(&dev->radio_dev, dev);
+               dev->radio_dev.ctrl_handler = &core->audio_hdl;
+               err = video_register_device(&dev->radio_dev, VFL_TYPE_RADIO,
                                            radio_nr[core->nr]);
                if (err < 0) {
                        printk(KERN_ERR "%s/0: can't register radio device\n",
@@ -1526,7 +1509,7 @@ static int cx8800_initdev(struct pci_dev *pci_dev,
                        goto fail_unreg;
                }
                printk(KERN_INFO "%s/0: registered device %s\n",
-                      core->name, video_device_node_name(dev->radio_dev));
+                      core->name, video_device_node_name(&dev->radio_dev));
        }
 
        /* start tvaudio thread */
index 7748ca9abb09c31a462d9450aea1f6a06e1af19c..b9fe1ac248030518b984857566aa72707394ef8a 100644 (file)
@@ -478,9 +478,9 @@ struct cx8800_dev {
 
        /* various device info */
        unsigned int               resources;
-       struct video_device        *video_dev;
-       struct video_device        *vbi_dev;
-       struct video_device        *radio_dev;
+       struct video_device        video_dev;
+       struct video_device        vbi_dev;
+       struct video_device        radio_dev;
 
        /* pci i/o */
        struct pci_dev             *pci;
@@ -563,7 +563,7 @@ struct cx8802_dev {
        /* for blackbird only */
        struct list_head           devlist;
 #if IS_ENABLED(CONFIG_VIDEO_CX88_BLACKBIRD)
-       struct video_device        *mpeg_dev;
+       struct video_device        mpeg_dev;
        u32                        mailbox;
 
        /* mpeg params */
@@ -647,10 +647,11 @@ extern int cx88_set_scale(struct cx88_core *core, unsigned int width,
                          unsigned int height, enum v4l2_field field);
 extern int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm);
 
-extern struct video_device *cx88_vdev_init(struct cx88_core *core,
-                                          struct pci_dev *pci,
-                                          const struct video_device *template_,
-                                          const char *type);
+extern void cx88_vdev_init(struct cx88_core *core,
+                          struct pci_dev *pci,
+                          struct video_device *vfd,
+                          const struct video_device *template_,
+                          const char *type);
 extern struct cx88_core *cx88_core_get(struct pci_dev *pci);
 extern void cx88_core_put(struct cx88_core *core,
                          struct pci_dev *pci);
index 39b52929755aca482839c01f46f4fd2251183bd6..41fa21534edf1ae2de7f84924fe2606dbbc83fbf 100644 (file)
@@ -224,7 +224,7 @@ static int ivtv_alsa_load(struct ivtv *itv)
        }
 
        s = &itv->streams[IVTV_ENC_STREAM_TYPE_PCM];
-       if (s->vdev == NULL) {
+       if (s->vdev.v4l2_dev == NULL) {
                IVTV_DEBUG_ALSA_INFO("%s: PCM stream for card is disabled - "
                                     "skipping\n", __func__);
                return 0;
index 7bf9cbca4fa64fe3e63c3d17ea7432e661069e85..f198b9826ed8d63d5c43e623ba096eea0d853de7 100644 (file)
@@ -167,7 +167,7 @@ static int snd_ivtv_pcm_capture_open(struct snd_pcm_substream *substream)
 
        s = &itv->streams[IVTV_ENC_STREAM_TYPE_PCM];
 
-       v4l2_fh_init(&item.fh, s->vdev);
+       v4l2_fh_init(&item.fh, &s->vdev);
        item.itv = itv;
        item.type = s->type;
 
index 802642d266438ffaaf6f136a30e141ffb452810e..c2e60b4f292d1d8d9791b5c44b0fa76c0ffd854b 100644 (file)
@@ -1284,7 +1284,7 @@ static int ivtv_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
        return 0;
 
 free_streams:
-       ivtv_streams_cleanup(itv, 1);
+       ivtv_streams_cleanup(itv);
 free_irq:
        free_irq(itv->pdev->irq, (void *)itv);
 free_i2c:
@@ -1444,7 +1444,7 @@ static void ivtv_remove(struct pci_dev *pdev)
        flush_kthread_worker(&itv->irq_worker);
        kthread_stop(itv->irq_worker_task);
 
-       ivtv_streams_cleanup(itv, 1);
+       ivtv_streams_cleanup(itv);
        ivtv_udma_free(itv);
 
        v4l2_ctrl_handler_free(&itv->cxhdl.hdl);
index bc309f42c8ed29bb2782cb70521250b6f809c7d4..e8b6c7ad2ba9bcfc5ddf620d33c58996db63e993 100644 (file)
@@ -327,7 +327,7 @@ struct ivtv;                                /* forward reference */
 struct ivtv_stream {
        /* These first four fields are always set, even if the stream
           is not actually created. */
-       struct video_device *vdev;      /* NULL when stream not created */
+       struct video_device vdev;       /* vdev.v4l2_dev is NULL if there is no device */
        struct ivtv *itv;               /* for ease of use */
        const char *name;               /* name of the stream */
        int type;                       /* stream type */
index e5ff6277ca854704143398b43e585af5c6204dc5..605d280d8a5f00f2f142498532eb2c53f40be8fa 100644 (file)
@@ -995,7 +995,7 @@ static int ivtv_open(struct file *filp)
                IVTV_DEBUG_WARN("nomem on v4l2 open\n");
                return -ENOMEM;
        }
-       v4l2_fh_init(&item->fh, s->vdev);
+       v4l2_fh_init(&item->fh, &s->vdev);
        item->itv = itv;
        item->type = s->type;
 
index 4d8ee18c3feb17978d048c3bbec8c5e4efe79763..6fe6c4a0e85854c294c9e1939a0788e92142562b 100644 (file)
@@ -448,9 +448,12 @@ static int ivtv_g_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *f
 static int ivtv_g_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
 {
        struct ivtv *itv = fh2id(fh)->itv;
+       struct ivtv_stream *s = &itv->streams[fh2id(fh)->type];
        struct v4l2_window *winfmt = &fmt->fmt.win;
 
-       if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+       if (!(s->caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
+               return -EINVAL;
+       if (!itv->osd_video_pbase)
                return -EINVAL;
        winfmt->chromakey = itv->osd_chroma_key;
        winfmt->global_alpha = itv->osd_global_alpha;
@@ -555,10 +558,13 @@ static int ivtv_try_fmt_vid_out(struct file *file, void *fh, struct v4l2_format
 static int ivtv_try_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
 {
        struct ivtv *itv = fh2id(fh)->itv;
+       struct ivtv_stream *s = &itv->streams[fh2id(fh)->type];
        u32 chromakey = fmt->fmt.win.chromakey;
        u8 global_alpha = fmt->fmt.win.global_alpha;
 
-       if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+       if (!(s->caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
+               return -EINVAL;
+       if (!itv->osd_video_pbase)
                return -EINVAL;
        ivtv_g_fmt_vid_out_overlay(file, fh, fmt);
        fmt->fmt.win.chromakey = chromakey;
@@ -741,6 +747,11 @@ static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vc
        snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->pdev));
        vcap->capabilities = itv->v4l2_cap | V4L2_CAP_DEVICE_CAPS;
        vcap->device_caps = s->caps;
+       if ((s->caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY) &&
+           !itv->osd_video_pbase) {
+               vcap->capabilities &= ~V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
+               vcap->device_caps &= ~V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
+       }
        return 0;
 }
 
@@ -816,80 +827,103 @@ static int ivtv_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropca
 {
        struct ivtv_open_id *id = fh2id(fh);
        struct ivtv *itv = id->itv;
-       struct yuv_playback_info *yi = &itv->yuv_info;
-       int streamtype;
-
-       streamtype = id->type;
 
-       if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
-               return -EINVAL;
-       cropcap->bounds.top = cropcap->bounds.left = 0;
-       cropcap->bounds.width = 720;
        if (cropcap->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-               cropcap->bounds.height = itv->is_50hz ? 576 : 480;
                cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10;
                cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11;
-       } else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
-               if (yi->track_osd) {
-                       cropcap->bounds.width = yi->osd_full_w;
-                       cropcap->bounds.height = yi->osd_full_h;
-               } else {
-                       cropcap->bounds.width = 720;
-                       cropcap->bounds.height =
-                                       itv->is_out_50hz ? 576 : 480;
-               }
+       } else if (cropcap->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
                cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
                cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
        } else {
-               cropcap->bounds.height = itv->is_out_50hz ? 576 : 480;
-               cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
-               cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
+               return -EINVAL;
        }
-       cropcap->defrect = cropcap->bounds;
        return 0;
 }
 
-static int ivtv_s_crop(struct file *file, void *fh, const struct v4l2_crop *crop)
+static int ivtv_s_selection(struct file *file, void *fh,
+                           struct v4l2_selection *sel)
 {
        struct ivtv_open_id *id = fh2id(fh);
        struct ivtv *itv = id->itv;
        struct yuv_playback_info *yi = &itv->yuv_info;
-       int streamtype;
+       struct v4l2_rect r = { 0, 0, 720, 0 };
+       int streamtype = id->type;
 
-       streamtype = id->type;
+       if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT ||
+           !(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+               return -EINVAL;
 
-       if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
-           (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
-               if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
-                       yi->main_rect = crop->c;
-                       return 0;
-               } else {
-                       if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
-                               crop->c.width, crop->c.height, crop->c.left, crop->c.top)) {
-                               itv->main_rect = crop->c;
-                               return 0;
-                       }
-               }
+       if (sel->target != V4L2_SEL_TGT_COMPOSE)
                return -EINVAL;
+
+
+       if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT ||
+           !(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+               return -EINVAL;
+
+       r.height = itv->is_out_50hz ? 576 : 480;
+       if (streamtype == IVTV_DEC_STREAM_TYPE_YUV && yi->track_osd) {
+               r.width = yi->osd_full_w;
+               r.height = yi->osd_full_h;
+       }
+       sel->r.width = clamp(sel->r.width, 16U, r.width);
+       sel->r.height = clamp(sel->r.height, 16U, r.height);
+       sel->r.left = clamp_t(unsigned, sel->r.left, 0, r.width - sel->r.width);
+       sel->r.top = clamp_t(unsigned, sel->r.top, 0, r.height - sel->r.height);
+
+       if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
+               yi->main_rect = sel->r;
+               return 0;
+       }
+       if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
+                       sel->r.width, sel->r.height, sel->r.left, sel->r.top)) {
+               itv->main_rect = sel->r;
+               return 0;
        }
        return -EINVAL;
 }
 
-static int ivtv_g_crop(struct file *file, void *fh, struct v4l2_crop *crop)
+static int ivtv_g_selection(struct file *file, void *fh,
+                           struct v4l2_selection *sel)
 {
        struct ivtv_open_id *id = fh2id(fh);
        struct ivtv *itv = id->itv;
        struct yuv_playback_info *yi = &itv->yuv_info;
-       int streamtype;
+       struct v4l2_rect r = { 0, 0, 720, 0 };
+       int streamtype = id->type;
+
+       if (sel->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               switch (sel->target) {
+               case V4L2_SEL_TGT_CROP_DEFAULT:
+               case V4L2_SEL_TGT_CROP_BOUNDS:
+                       sel->r.top = sel->r.left = 0;
+                       sel->r.width = 720;
+                       sel->r.height = itv->is_50hz ? 576 : 480;
+                       return 0;
+               default:
+                       return -EINVAL;
+               }
+       }
 
-       streamtype = id->type;
+       if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT ||
+           !(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+               return -EINVAL;
 
-       if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
-           (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
+       switch (sel->target) {
+       case V4L2_SEL_TGT_COMPOSE:
                if (streamtype == IVTV_DEC_STREAM_TYPE_YUV)
-                       crop->c = yi->main_rect;
+                       sel->r = yi->main_rect;
                else
-                       crop->c = itv->main_rect;
+                       sel->r = itv->main_rect;
+               return 0;
+       case V4L2_SEL_TGT_COMPOSE_DEFAULT:
+       case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+               r.height = itv->is_out_50hz ? 576 : 480;
+               if (streamtype == IVTV_DEC_STREAM_TYPE_YUV && yi->track_osd) {
+                       r.width = yi->osd_full_w;
+                       r.height = yi->osd_full_h;
+               }
+               sel->r = r;
                return 0;
        }
        return -EINVAL;
@@ -987,7 +1021,7 @@ int ivtv_s_input(struct file *file, void *fh, unsigned int inp)
        else
                std = V4L2_STD_ALL;
        for (i = 0; i <= IVTV_ENC_STREAM_TYPE_VBI; i++)
-               itv->streams[i].vdev->tvnorms = std;
+               itv->streams[i].vdev.tvnorms = std;
 
        /* prevent others from messing with the streams until
           we're finished changing inputs. */
@@ -1038,7 +1072,7 @@ static int ivtv_g_frequency(struct file *file, void *fh, struct v4l2_frequency *
        struct ivtv *itv = fh2id(fh)->itv;
        struct ivtv_stream *s = &itv->streams[fh2id(fh)->type];
 
-       if (s->vdev->vfl_dir)
+       if (s->vdev.vfl_dir)
                return -ENOTTY;
        if (vf->tuner != 0)
                return -EINVAL;
@@ -1052,7 +1086,7 @@ int ivtv_s_frequency(struct file *file, void *fh, const struct v4l2_frequency *v
        struct ivtv *itv = fh2id(fh)->itv;
        struct ivtv_stream *s = &itv->streams[fh2id(fh)->type];
 
-       if (s->vdev->vfl_dir)
+       if (s->vdev.vfl_dir)
                return -ENOTTY;
        if (vf->tuner != 0)
                return -EINVAL;
@@ -1340,6 +1374,7 @@ static int ivtv_try_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder
 static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
 {
        struct ivtv *itv = fh2id(fh)->itv;
+       struct ivtv_stream *s = &itv->streams[fh2id(fh)->type];
        u32 data[CX2341X_MBOX_MAX_DATA];
        struct yuv_playback_info *yi = &itv->yuv_info;
 
@@ -1363,10 +1398,10 @@ static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
                0,
        };
 
-       if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
-               return -EINVAL;
+       if (!(s->caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
+               return -ENOTTY;
        if (!itv->osd_video_pbase)
-               return -EINVAL;
+               return -ENOTTY;
 
        fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | V4L2_FBUF_CAP_CHROMAKEY |
                V4L2_FBUF_CAP_GLOBAL_ALPHA;
@@ -1427,12 +1462,13 @@ static int ivtv_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffe
 {
        struct ivtv_open_id *id = fh2id(fh);
        struct ivtv *itv = id->itv;
+       struct ivtv_stream *s = &itv->streams[fh2id(fh)->type];
        struct yuv_playback_info *yi = &itv->yuv_info;
 
-       if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
-               return -EINVAL;
+       if (!(s->caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
+               return -ENOTTY;
        if (!itv->osd_video_pbase)
-               return -EINVAL;
+               return -ENOTTY;
 
        itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0;
        itv->osd_local_alpha_state =
@@ -1447,9 +1483,12 @@ static int ivtv_overlay(struct file *file, void *fh, unsigned int on)
 {
        struct ivtv_open_id *id = fh2id(fh);
        struct ivtv *itv = id->itv;
+       struct ivtv_stream *s = &itv->streams[fh2id(fh)->type];
 
-       if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
-               return -EINVAL;
+       if (!(s->caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
+               return -ENOTTY;
+       if (!itv->osd_video_pbase)
+               return -ENOTTY;
 
        ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, on != 0);
 
@@ -1547,7 +1586,7 @@ static int ivtv_log_status(struct file *file, void *fh)
        for (i = 0; i < IVTV_MAX_STREAMS; i++) {
                struct ivtv_stream *s = &itv->streams[i];
 
-               if (s->vdev == NULL || s->buffers == 0)
+               if (s->vdev.v4l2_dev == NULL || s->buffers == 0)
                        continue;
                IVTV_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags,
                                (s->buffers - s->q_free.buffers) * 100 / s->buffers,
@@ -1837,8 +1876,8 @@ static const struct v4l2_ioctl_ops ivtv_ioctl_ops = {
        .vidioc_enum_output                 = ivtv_enum_output,
        .vidioc_enumaudout                  = ivtv_enumaudout,
        .vidioc_cropcap                     = ivtv_cropcap,
-       .vidioc_s_crop                      = ivtv_s_crop,
-       .vidioc_g_crop                      = ivtv_g_crop,
+       .vidioc_s_selection                 = ivtv_s_selection,
+       .vidioc_g_selection                 = ivtv_g_selection,
        .vidioc_g_input                     = ivtv_g_input,
        .vidioc_s_input                     = ivtv_s_input,
        .vidioc_g_output                    = ivtv_g_output,
index e7d701777e53fe44af8426685c7aaf57996c90ab..36ca2d67c812189ffe9f1cc3b0a85c1251e4cbf3 100644 (file)
@@ -75,7 +75,7 @@ static void ivtv_pio_work_handler(struct ivtv *itv)
 
        IVTV_DEBUG_HI_DMA("ivtv_pio_work_handler\n");
        if (itv->cur_pio_stream < 0 || itv->cur_pio_stream >= IVTV_MAX_STREAMS ||
-                       s->vdev == NULL || !ivtv_use_pio(s)) {
+                       s->vdev.v4l2_dev == NULL || !ivtv_use_pio(s)) {
                itv->cur_pio_stream = -1;
                /* trigger PIO complete user interrupt */
                write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44);
@@ -132,7 +132,7 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA
        int rc;
 
        /* sanity checks */
-       if (s->vdev == NULL) {
+       if (s->vdev.v4l2_dev == NULL) {
                IVTV_DEBUG_WARN("Stream %s not started\n", s->name);
                return -1;
        }
@@ -890,8 +890,8 @@ static void ivtv_irq_vsync(struct ivtv *itv)
                        if (s)
                                wake_up(&s->waitq);
                }
-               if (s && s->vdev)
-                       v4l2_event_queue(s->vdev, frame ? &evtop : &evbottom);
+               if (s && s->vdev.v4l2_dev)
+                       v4l2_event_queue(&s->vdev, frame ? &evtop : &evbottom);
                wake_up(&itv->vsync_waitq);
 
                /* Send VBI to saa7127 */
index f0a1cc472313cc5c42292c59900539f2e43494f1..d27c6df975668423cd6ed57d626a0cb8aac60de3 100644 (file)
@@ -130,7 +130,8 @@ static struct {
                "decoder MPG",
                VFL_TYPE_GRABBER, IVTV_V4L2_DEC_MPG_OFFSET,
                PCI_DMA_TODEVICE, 0,
-               V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
+               V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE |
+               V4L2_CAP_VIDEO_OUTPUT_OVERLAY,
                &ivtv_v4l2_dec_fops
        },
        {       /* IVTV_DEC_STREAM_TYPE_VBI */
@@ -151,7 +152,8 @@ static struct {
                "decoder YUV",
                VFL_TYPE_GRABBER, IVTV_V4L2_DEC_YUV_OFFSET,
                PCI_DMA_TODEVICE, 0,
-               V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
+               V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE |
+               V4L2_CAP_VIDEO_OUTPUT_OVERLAY,
                &ivtv_v4l2_dec_fops
        }
 };
@@ -159,11 +161,9 @@ static struct {
 static void ivtv_stream_init(struct ivtv *itv, int type)
 {
        struct ivtv_stream *s = &itv->streams[type];
-       struct video_device *vdev = s->vdev;
 
        /* we need to keep vdev, so restore it afterwards */
        memset(s, 0, sizeof(*s));
-       s->vdev = vdev;
 
        /* initialize ivtv_stream fields */
        s->itv = itv;
@@ -194,10 +194,10 @@ static int ivtv_prep_dev(struct ivtv *itv, int type)
        int num_offset = ivtv_stream_info[type].num_offset;
        int num = itv->instance + ivtv_first_minor + num_offset;
 
-       /* These four fields are always initialized. If vdev == NULL, then
+       /* These four fields are always initialized. If vdev.v4l2_dev == NULL, then
           this stream is not in use. In that case no other fields but these
           four can be used. */
-       s->vdev = NULL;
+       s->vdev.v4l2_dev = NULL;
        s->itv = itv;
        s->type = type;
        s->name = ivtv_stream_info[type].name;
@@ -218,40 +218,33 @@ static int ivtv_prep_dev(struct ivtv *itv, int type)
 
        ivtv_stream_init(itv, type);
 
-       /* allocate and initialize the v4l2 video device structure */
-       s->vdev = video_device_alloc();
-       if (s->vdev == NULL) {
-               IVTV_ERR("Couldn't allocate v4l2 video_device for %s\n", s->name);
-               return -ENOMEM;
-       }
-
-       snprintf(s->vdev->name, sizeof(s->vdev->name), "%s %s",
+       snprintf(s->vdev.name, sizeof(s->vdev.name), "%s %s",
                        itv->v4l2_dev.name, s->name);
 
-       s->vdev->num = num;
-       s->vdev->v4l2_dev = &itv->v4l2_dev;
+       s->vdev.num = num;
+       s->vdev.v4l2_dev = &itv->v4l2_dev;
        if (ivtv_stream_info[type].v4l2_caps &
                        (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_SLICED_VBI_OUTPUT))
-               s->vdev->vfl_dir = VFL_DIR_TX;
-       s->vdev->fops = ivtv_stream_info[type].fops;
-       s->vdev->ctrl_handler = itv->v4l2_dev.ctrl_handler;
-       s->vdev->release = video_device_release;
-       s->vdev->tvnorms = V4L2_STD_ALL;
-       s->vdev->lock = &itv->serialize_lock;
+               s->vdev.vfl_dir = VFL_DIR_TX;
+       s->vdev.fops = ivtv_stream_info[type].fops;
+       s->vdev.ctrl_handler = itv->v4l2_dev.ctrl_handler;
+       s->vdev.release = video_device_release_empty;
+       s->vdev.tvnorms = V4L2_STD_ALL;
+       s->vdev.lock = &itv->serialize_lock;
        if (s->type == IVTV_DEC_STREAM_TYPE_VBI) {
-               v4l2_disable_ioctl(s->vdev, VIDIOC_S_AUDIO);
-               v4l2_disable_ioctl(s->vdev, VIDIOC_G_AUDIO);
-               v4l2_disable_ioctl(s->vdev, VIDIOC_ENUMAUDIO);
-               v4l2_disable_ioctl(s->vdev, VIDIOC_ENUMINPUT);
-               v4l2_disable_ioctl(s->vdev, VIDIOC_S_INPUT);
-               v4l2_disable_ioctl(s->vdev, VIDIOC_G_INPUT);
-               v4l2_disable_ioctl(s->vdev, VIDIOC_S_FREQUENCY);
-               v4l2_disable_ioctl(s->vdev, VIDIOC_G_FREQUENCY);
-               v4l2_disable_ioctl(s->vdev, VIDIOC_S_TUNER);
-               v4l2_disable_ioctl(s->vdev, VIDIOC_G_TUNER);
-               v4l2_disable_ioctl(s->vdev, VIDIOC_S_STD);
+               v4l2_disable_ioctl(&s->vdev, VIDIOC_S_AUDIO);
+               v4l2_disable_ioctl(&s->vdev, VIDIOC_G_AUDIO);
+               v4l2_disable_ioctl(&s->vdev, VIDIOC_ENUMAUDIO);
+               v4l2_disable_ioctl(&s->vdev, VIDIOC_ENUMINPUT);
+               v4l2_disable_ioctl(&s->vdev, VIDIOC_S_INPUT);
+               v4l2_disable_ioctl(&s->vdev, VIDIOC_G_INPUT);
+               v4l2_disable_ioctl(&s->vdev, VIDIOC_S_FREQUENCY);
+               v4l2_disable_ioctl(&s->vdev, VIDIOC_G_FREQUENCY);
+               v4l2_disable_ioctl(&s->vdev, VIDIOC_S_TUNER);
+               v4l2_disable_ioctl(&s->vdev, VIDIOC_G_TUNER);
+               v4l2_disable_ioctl(&s->vdev, VIDIOC_S_STD);
        }
-       ivtv_set_funcs(s->vdev);
+       ivtv_set_funcs(&s->vdev);
        return 0;
 }
 
@@ -266,7 +259,7 @@ int ivtv_streams_setup(struct ivtv *itv)
                if (ivtv_prep_dev(itv, type))
                        break;
 
-               if (itv->streams[type].vdev == NULL)
+               if (itv->streams[type].vdev.v4l2_dev == NULL)
                        continue;
 
                /* Allocate Stream */
@@ -277,7 +270,7 @@ int ivtv_streams_setup(struct ivtv *itv)
                return 0;
 
        /* One or more streams could not be initialized. Clean 'em all up. */
-       ivtv_streams_cleanup(itv, 0);
+       ivtv_streams_cleanup(itv);
        return -ENOMEM;
 }
 
@@ -288,28 +281,26 @@ static int ivtv_reg_dev(struct ivtv *itv, int type)
        const char *name;
        int num;
 
-       if (s->vdev == NULL)
+       if (s->vdev.v4l2_dev == NULL)
                return 0;
 
-       num = s->vdev->num;
+       num = s->vdev.num;
        /* card number + user defined offset + device offset */
        if (type != IVTV_ENC_STREAM_TYPE_MPG) {
                struct ivtv_stream *s_mpg = &itv->streams[IVTV_ENC_STREAM_TYPE_MPG];
 
-               if (s_mpg->vdev)
-                       num = s_mpg->vdev->num + ivtv_stream_info[type].num_offset;
+               if (s_mpg->vdev.v4l2_dev)
+                       num = s_mpg->vdev.num + ivtv_stream_info[type].num_offset;
        }
-       video_set_drvdata(s->vdev, s);
+       video_set_drvdata(&s->vdev, s);
 
        /* Register device. First try the desired minor, then any free one. */
-       if (video_register_device_no_warn(s->vdev, vfl_type, num)) {
+       if (video_register_device_no_warn(&s->vdev, vfl_type, num)) {
                IVTV_ERR("Couldn't register v4l2 device for %s (device node number %d)\n",
                                s->name, num);
-               video_device_release(s->vdev);
-               s->vdev = NULL;
                return -ENOMEM;
        }
-       name = video_device_node_name(s->vdev);
+       name = video_device_node_name(&s->vdev);
 
        switch (vfl_type) {
        case VFL_TYPE_GRABBER:
@@ -346,29 +337,25 @@ int ivtv_streams_register(struct ivtv *itv)
                return 0;
 
        /* One or more streams could not be initialized. Clean 'em all up. */
-       ivtv_streams_cleanup(itv, 1);
+       ivtv_streams_cleanup(itv);
        return -ENOMEM;
 }
 
 /* Unregister v4l2 devices */
-void ivtv_streams_cleanup(struct ivtv *itv, int unregister)
+void ivtv_streams_cleanup(struct ivtv *itv)
 {
        int type;
 
        /* Teardown all streams */
        for (type = 0; type < IVTV_MAX_STREAMS; type++) {
-               struct video_device *vdev = itv->streams[type].vdev;
+               struct video_device *vdev = &itv->streams[type].vdev;
 
-               itv->streams[type].vdev = NULL;
-               if (vdev == NULL)
+               if (vdev->v4l2_dev == NULL)
                        continue;
 
+               video_unregister_device(vdev);
                ivtv_stream_free(&itv->streams[type]);
-               /* Unregister or release device */
-               if (unregister)
-                       video_unregister_device(vdev);
-               else
-                       video_device_release(vdev);
+               itv->streams[type].vdev.v4l2_dev = NULL;
        }
 }
 
@@ -492,7 +479,7 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
        int captype = 0, subtype = 0;
        int enable_passthrough = 0;
 
-       if (s->vdev == NULL)
+       if (s->vdev.v4l2_dev == NULL)
                return -EINVAL;
 
        IVTV_DEBUG_INFO("Start encoder stream %s\n", s->name);
@@ -661,7 +648,7 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s)
        u16 width;
        u16 height;
 
-       if (s->vdev == NULL)
+       if (s->vdev.v4l2_dev == NULL)
                return -EINVAL;
 
        IVTV_DEBUG_INFO("Setting some initial decoder settings\n");
@@ -723,7 +710,7 @@ int ivtv_start_v4l2_decode_stream(struct ivtv_stream *s, int gop_offset)
        struct ivtv *itv = s->itv;
        int rc;
 
-       if (s->vdev == NULL)
+       if (s->vdev.v4l2_dev == NULL)
                return -EINVAL;
 
        if (test_and_set_bit(IVTV_F_S_STREAMING, &s->s_flags))
@@ -778,7 +765,7 @@ void ivtv_stop_all_captures(struct ivtv *itv)
        for (i = IVTV_MAX_STREAMS - 1; i >= 0; i--) {
                struct ivtv_stream *s = &itv->streams[i];
 
-               if (s->vdev == NULL)
+               if (s->vdev.v4l2_dev == NULL)
                        continue;
                if (test_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
                        ivtv_stop_v4l2_encode_stream(s, 0);
@@ -793,7 +780,7 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end)
        int cap_type;
        int stopmode;
 
-       if (s->vdev == NULL)
+       if (s->vdev.v4l2_dev == NULL)
                return -EINVAL;
 
        /* This function assumes that you are allowed to stop the capture
@@ -917,7 +904,7 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts)
        };
        struct ivtv *itv = s->itv;
 
-       if (s->vdev == NULL)
+       if (s->vdev.v4l2_dev == NULL)
                return -EINVAL;
 
        if (s->type != IVTV_DEC_STREAM_TYPE_YUV && s->type != IVTV_DEC_STREAM_TYPE_MPG)
@@ -969,7 +956,7 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts)
 
        set_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags);
        wake_up(&itv->event_waitq);
-       v4l2_event_queue(s->vdev, &ev);
+       v4l2_event_queue(&s->vdev, &ev);
 
        /* wake up wait queues */
        wake_up(&s->waitq);
@@ -982,7 +969,7 @@ int ivtv_passthrough_mode(struct ivtv *itv, int enable)
        struct ivtv_stream *yuv_stream = &itv->streams[IVTV_ENC_STREAM_TYPE_YUV];
        struct ivtv_stream *dec_stream = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV];
 
-       if (yuv_stream->vdev == NULL || dec_stream->vdev == NULL)
+       if (yuv_stream->vdev.v4l2_dev == NULL || dec_stream->vdev.v4l2_dev == NULL)
                return -EINVAL;
 
        IVTV_DEBUG_INFO("ivtv ioctl: Select passthrough mode\n");
index a653a5136417df1bbf7eb4abdbb3789a3cd55bc8..3d76a415fbd8892a1b425873259177a1314d2d02 100644 (file)
@@ -23,7 +23,7 @@
 
 int ivtv_streams_setup(struct ivtv *itv);
 int ivtv_streams_register(struct ivtv *itv);
-void ivtv_streams_cleanup(struct ivtv *itv, int unregister);
+void ivtv_streams_cleanup(struct ivtv *itv);
 
 /* Capture related */
 int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s);
index 9d9f90cb774050df5e228861bf250be66ae83583..ba887e8e1b171110f2bac5716fc8a24f38f69230 100644 (file)
@@ -1546,7 +1546,7 @@ static struct video_device meye_template = {
        .name           = "meye",
        .fops           = &meye_fops,
        .ioctl_ops      = &meye_ioctl_ops,
-       .release        = video_device_release,
+       .release        = video_device_release_empty,
 };
 
 static const struct v4l2_ctrl_ops meye_ctrl_ops = {
@@ -1623,7 +1623,7 @@ static int meye_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
 
        if (meye.mchip_dev != NULL) {
                printk(KERN_ERR "meye: only one device allowed!\n");
-               goto outnotdev;
+               return ret;
        }
 
        ret = v4l2_device_register(&pcidev->dev, v4l2_dev);
@@ -1633,11 +1633,6 @@ static int meye_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
        }
        ret = -ENOMEM;
        meye.mchip_dev = pcidev;
-       meye.vdev = video_device_alloc();
-       if (!meye.vdev) {
-               v4l2_err(v4l2_dev, "video_device_alloc() failed!\n");
-               goto outnotdev;
-       }
 
        meye.grab_temp = vmalloc(MCHIP_NB_PAGES_MJPEG * PAGE_SIZE);
        if (!meye.grab_temp) {
@@ -1658,8 +1653,8 @@ static int meye_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
                goto outkfifoalloc2;
        }
 
-       memcpy(meye.vdev, &meye_template, sizeof(meye_template));
-       meye.vdev->v4l2_dev = &meye.v4l2_dev;
+       meye.vdev = meye_template;
+       meye.vdev.v4l2_dev = &meye.v4l2_dev;
 
        ret = -EIO;
        if ((ret = sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 1))) {
@@ -1743,9 +1738,9 @@ static int meye_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
        }
 
        v4l2_ctrl_handler_setup(&meye.hdl);
-       meye.vdev->ctrl_handler = &meye.hdl;
+       meye.vdev.ctrl_handler = &meye.hdl;
 
-       if (video_register_device(meye.vdev, VFL_TYPE_GRABBER,
+       if (video_register_device(&meye.vdev, VFL_TYPE_GRABBER,
                                  video_nr) < 0) {
                v4l2_err(v4l2_dev, "video_register_device failed\n");
                goto outvideoreg;
@@ -1777,14 +1772,12 @@ outkfifoalloc2:
 outkfifoalloc1:
        vfree(meye.grab_temp);
 outvmalloc:
-       video_device_release(meye.vdev);
-outnotdev:
        return ret;
 }
 
 static void meye_remove(struct pci_dev *pcidev)
 {
-       video_unregister_device(meye.vdev);
+       video_unregister_device(&meye.vdev);
 
        mchip_hic_stop();
 
index 6fed9274cfa530ad5904b669dda6a586373bec09..751be5e533c7e12eeff2ff40a78396223b4943b6 100644 (file)
@@ -311,7 +311,7 @@ struct meye {
        struct kfifo doneq;             /* queue for grabbed buffers */
        spinlock_t doneq_lock;          /* lock protecting the queue */
        wait_queue_head_t proc_list;    /* wait queue */
-       struct video_device *vdev;      /* video device parameters */
+       struct video_device vdev;       /* video device parameters */
        u16 brightness;
        u16 hue;
        u16 contrast;
index 366434f5647e66299a7f4e9aadb20d083f518d0b..03cbcd2095c6e18848cdb47ce399843fb9406f78 100644 (file)
@@ -66,7 +66,7 @@ struct hexium
 {
        int type;
 
-       struct video_device     *video_dev;
+       struct video_device     video_dev;
        struct i2c_adapter      i2c_adapter;
 
        int             cur_input;      /* current input */
index a1eb26d11070afa4b89ff2c6fa657223cf802c00..15f0d66ff78a237a85101c7ee04bd50d6830a9ab 100644 (file)
@@ -63,7 +63,7 @@ struct hexium_data
 struct hexium
 {
        int type;
-       struct video_device     *video_dev;
+       struct video_device     video_dev;
        struct i2c_adapter      i2c_adapter;
 
        int cur_input;  /* current input */
index c4c8fce8f2b48fcf26520b06cf8ad90c0f895212..0ca1e07ae7837f7cfe6acb239f30186dc8698a2d 100644 (file)
@@ -151,8 +151,8 @@ static struct mxb_routing TEA6420_line[MXB_AUDIOS + 1][2] = {
 
 struct mxb
 {
-       struct video_device     *video_dev;
-       struct video_device     *vbi_dev;
+       struct video_device     video_dev;
+       struct video_device     vbi_dev;
 
        struct i2c_adapter      i2c_adapter;
 
index 4b0bec3766ed31233e13aecc38e87d9cf6bfb154..9cf3c6cba4984b6ae415212b2af3ef7cde0f85a4 100644 (file)
@@ -1436,11 +1436,11 @@ static void saa7164_finidev(struct pci_dev *pci_dev)
        saa7164_i2c_unregister(&dev->i2c_bus[1]);
        saa7164_i2c_unregister(&dev->i2c_bus[2]);
 
-       pci_disable_device(pci_dev);
-
        /* unregister stuff */
        free_irq(pci_dev->irq, dev);
 
+       pci_disable_device(pci_dev);
+
        mutex_lock(&devlist);
        list_del(&dev->devlist);
        mutex_unlock(&devlist);
index c8de53f5ea28d8d01367462abd78ce4e2e4b4f24..21a1583dbd8f93866c01c957643544fc900f46cd 100644 (file)
@@ -4,7 +4,7 @@ config DVB_SMIPCIE
        select I2C_ALGOBIT
        select DVB_M88DS3103 if MEDIA_SUBDRV_AUTOSELECT
        select DVB_SI2168 if MEDIA_SUBDRV_AUTOSELECT
-       select MEDIA_TUNER_M88TS2022 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TS2020 if MEDIA_SUBDRV_AUTOSELECT
        select MEDIA_TUNER_M88RS6000T if MEDIA_SUBDRV_AUTOSELECT
        select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT
        help
index 36c8ed77309ce63d04f5daa1472406b8fbeb85f1..411592524c63501f23504ec44e3964c57ff22539 100644 (file)
@@ -16,7 +16,7 @@
 
 #include "smipcie.h"
 #include "m88ds3103.h"
-#include "m88ts2022.h"
+#include "ts2020.h"
 #include "m88rs6000t.h"
 #include "si2168.h"
 #include "si2157.h"
@@ -532,9 +532,7 @@ static int smi_dvbsky_m88ds3103_fe_attach(struct smi_port *port)
        struct i2c_adapter *tuner_i2c_adapter;
        struct i2c_client *tuner_client;
        struct i2c_board_info tuner_info;
-       struct m88ts2022_config m88ts2022_config = {
-               .clock = 27000000,
-       };
+       struct ts2020_config ts2020_config = {};
        memset(&tuner_info, 0, sizeof(struct i2c_board_info));
        i2c = (port->idx == 0) ? &dev->i2c_bus[0] : &dev->i2c_bus[1];
 
@@ -546,10 +544,10 @@ static int smi_dvbsky_m88ds3103_fe_attach(struct smi_port *port)
                return ret;
        }
        /* attach tuner */
-       m88ts2022_config.fe = port->fe;
-       strlcpy(tuner_info.type, "m88ts2022", I2C_NAME_SIZE);
+       ts2020_config.fe = port->fe;
+       strlcpy(tuner_info.type, "ts2020", I2C_NAME_SIZE);
        tuner_info.addr = 0x60;
-       tuner_info.platform_data = &m88ts2022_config;
+       tuner_info.platform_data = &ts2020_config;
        tuner_client = smi_add_i2c_client(tuner_i2c_adapter, &tuner_info);
        if (!tuner_client) {
                ret = -ENODEV;
index 22450f583da1750e743b27aeb1fa4b7ce7f805f8..d384a6b0b09f58a81d6b9dd70a45f5404f14dabf 100644 (file)
@@ -127,7 +127,7 @@ static inline struct vip_buffer *to_vip_buffer(struct vb2_buffer *vb2)
  */
 struct sta2x11_vip {
        struct v4l2_device v4l2_dev;
-       struct video_device *video_dev;
+       struct video_device video_dev;
        struct pci_dev *pdev;
        struct i2c_adapter *adapter;
        unsigned int register_save_area[IRQ_COUNT + SAVE_COUNT + AUX_COUNT];
@@ -763,7 +763,7 @@ static const struct v4l2_ioctl_ops vip_ioctl_ops = {
 
 static struct video_device video_dev_template = {
        .name = KBUILD_MODNAME,
-       .release = video_device_release,
+       .release = video_device_release_empty,
        .fops = &vip_fops,
        .ioctl_ops = &vip_ioctl_ops,
        .tvnorms = V4L2_STD_ALL,
@@ -1082,19 +1082,13 @@ static int sta2x11_vip_init_one(struct pci_dev *pdev,
                goto release_buf;
        }
 
-       /* Alloc, initialize and register video device */
-       vip->video_dev = video_device_alloc();
-       if (!vip->video_dev) {
-               ret = -ENOMEM;
-               goto release_irq;
-       }
+       /* Initialize and register video device */
+       vip->video_dev = video_dev_template;
+       vip->video_dev.v4l2_dev = &vip->v4l2_dev;
+       vip->video_dev.queue = &vip->vb_vidq;
+       video_set_drvdata(&vip->video_dev, vip);
 
-       vip->video_dev = &video_dev_template;
-       vip->video_dev->v4l2_dev = &vip->v4l2_dev;
-       vip->video_dev->queue = &vip->vb_vidq;
-       video_set_drvdata(vip->video_dev, vip);
-
-       ret = video_register_device(vip->video_dev, VFL_TYPE_GRABBER, -1);
+       ret = video_register_device(&vip->video_dev, VFL_TYPE_GRABBER, -1);
        if (ret)
                goto vrelease;
 
@@ -1124,13 +1118,9 @@ static int sta2x11_vip_init_one(struct pci_dev *pdev,
        return 0;
 
 vunreg:
-       video_set_drvdata(vip->video_dev, NULL);
+       video_set_drvdata(&vip->video_dev, NULL);
 vrelease:
-       if (video_is_registered(vip->video_dev))
-               video_unregister_device(vip->video_dev);
-       else
-               video_device_release(vip->video_dev);
-release_irq:
+       video_unregister_device(&vip->video_dev);
        free_irq(pdev->irq, vip);
 release_buf:
        sta2x11_vip_release_buffer(vip);
@@ -1175,9 +1165,8 @@ static void sta2x11_vip_remove_one(struct pci_dev *pdev)
 
        sta2x11_vip_clear_register(vip);
 
-       video_set_drvdata(vip->video_dev, NULL);
-       video_unregister_device(vip->video_dev);
-       /*do not call video_device_release() here, is already done */
+       video_set_drvdata(&vip->video_dev, NULL);
+       video_unregister_device(&vip->video_dev);
        free_irq(pdev->irq, vip);
        pci_disable_msi(pdev);
        vb2_queue_release(&vip->vb_vidq);
index ef3d9606b2695844f8f01dda48c294f72218b822..835635b0c71298b6832b53ec103d38453e534a6e 100644 (file)
@@ -102,8 +102,8 @@ struct av7110 {
        struct dvb_device       dvb_dev;
        struct dvb_net          dvb_net;
 
-       struct video_device     *v4l_dev;
-       struct video_device     *vbi_dev;
+       struct video_device     v4l_dev;
+       struct video_device     vbi_dev;
 
        struct saa7146_dev      *dev;
 
index 0ba3875af22e1cf06f675e37ad15f43ad4fa9bab..54c9910256f8cd4dc81ef339df56bcafe0df158e 100644 (file)
@@ -68,7 +68,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
 struct budget_av {
        struct budget budget;
-       struct video_device *vd;
+       struct video_device vd;
        int cur_input;
        int has_saa7113;
        struct tasklet_struct ciintf_irq_tasklet;
index d9b872b9285a3460579b62df17ad88a75e64ce26..421f53188c6ce9c5fbe26d0b93762e759ed5a874 100644 (file)
@@ -56,7 +56,7 @@ config VIDEO_VIU
 
 config VIDEO_TIMBERDALE
        tristate "Support for timberdale Video In/LogiWIN"
-       depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
+       depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && HAS_DMA
        depends on (MFD_TIMBERDALE && TIMB_DMA) || COMPILE_TEST
        select VIDEO_ADV7180
        select VIDEOBUF_DMA_CONTIG
@@ -90,6 +90,7 @@ config VIDEO_OMAP3
        select ARM_DMA_USE_IOMMU
        select OMAP_IOMMU
        select VIDEOBUF2_DMA_CONTIG
+       select MFD_SYSCON
        ---help---
          Driver for an OMAP 3 camera controller.
 
@@ -117,6 +118,7 @@ source "drivers/media/platform/soc_camera/Kconfig"
 source "drivers/media/platform/exynos4-is/Kconfig"
 source "drivers/media/platform/s5p-tv/Kconfig"
 source "drivers/media/platform/am437x/Kconfig"
+source "drivers/media/platform/xilinx/Kconfig"
 
 endif # V4L_PLATFORM_DRIVERS
 
index 3ec15474208360d9f891eb2a19cab55a21c73114..8f855616c23760504cdf31177bb6911b4fd5fca0 100644 (file)
@@ -48,4 +48,6 @@ obj-y += omap/
 
 obj-$(CONFIG_VIDEO_AM437X_VPFE)                += am437x/
 
+obj-$(CONFIG_VIDEO_XILINX)             += xilinx/
+
 ccflags-y += -I$(srctree)/drivers/media/i2c
index 7b023a76e32ebabc8e5d5176284fb7094b37327e..42d9c186710a6423a71741528860bb58fff63128 100644 (file)
@@ -1,6 +1,6 @@
 config VIDEO_AM437X_VPFE
        tristate "TI AM437x VPFE video capture driver"
-       depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+       depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && HAS_DMA
        depends on SOC_AM43XX || COMPILE_TEST
        select VIDEOBUF2_DMA_CONTIG
        help
index 0d07fca756fee2e8b5b8680b945ff3c2bed188ef..a30cc2f7e4f1268445c8cb2763bcacda57665beb 100644 (file)
@@ -1645,6 +1645,7 @@ static int vpfe_enum_size(struct file *file, void  *priv,
        fse.index = fsize->index;
        fse.pad = 0;
        fse.code = mbus.code;
+       fse.which = V4L2_SUBDEV_FORMAT_ACTIVE;
        ret = v4l2_subdev_call(sdinfo->sd, pad, enum_frame_size, NULL, &fse);
        if (ret)
                return -EINVAL;
@@ -1700,11 +1701,16 @@ static int vpfe_get_app_input_index(struct vpfe_device *vpfe,
 {
        struct vpfe_config *cfg = vpfe->cfg;
        struct vpfe_subdev_info *sdinfo;
+       struct i2c_client *client;
+       struct i2c_client *curr_client;
        int i, j = 0;
 
+       curr_client = v4l2_get_subdevdata(vpfe->current_subdev->sd);
        for (i = 0; i < ARRAY_SIZE(vpfe->cfg->asd); i++) {
                sdinfo = &cfg->sub_devs[i];
-               if (!strcmp(sdinfo->name, vpfe->current_subdev->name)) {
+               client = v4l2_get_subdevdata(sdinfo->sd);
+               if (client->addr == curr_client->addr &&
+                   client->adapter->nr == client->adapter->nr) {
                        if (vpfe->current_input >= 1)
                                return -1;
                        *app_input_index = j + vpfe->current_input;
@@ -2296,20 +2302,10 @@ vpfe_async_bound(struct v4l2_async_notifier *notifier,
        vpfe_dbg(1, vpfe, "vpfe_async_bound\n");
 
        for (i = 0; i < ARRAY_SIZE(vpfe->cfg->asd); i++) {
-               sdinfo = &vpfe->cfg->sub_devs[i];
-
-               if (!strcmp(sdinfo->name, subdev->name)) {
+               if (vpfe->cfg->asd[i]->match.of.node == asd[i].match.of.node) {
+                       sdinfo = &vpfe->cfg->sub_devs[i];
                        vpfe->sd[i] = subdev;
-                       vpfe_info(vpfe,
-                                "v4l2 sub device %s registered\n",
-                                subdev->name);
-                       vpfe->sd[i]->grp_id =
-                                       sdinfo->grp_id;
-                       /* update tvnorms from the sub devices */
-                       for (j = 0; j < 1; j++)
-                               vpfe->video_dev->tvnorms |=
-                                       sdinfo->inputs[j].std;
-
+                       vpfe->sd[i]->grp_id = sdinfo->grp_id;
                        found = true;
                        break;
                }
@@ -2320,6 +2316,8 @@ vpfe_async_bound(struct v4l2_async_notifier *notifier,
                return -EINVAL;
        }
 
+       vpfe->video_dev.tvnorms |= sdinfo->inputs[0].std;
+
        /* setup the supported formats & indexes */
        for (j = 0, i = 0; ; ++j) {
                struct vpfe_fmt *fmt;
@@ -2327,6 +2325,7 @@ vpfe_async_bound(struct v4l2_async_notifier *notifier,
 
                memset(&mbus_code, 0, sizeof(mbus_code));
                mbus_code.index = j;
+               mbus_code.which = V4L2_SUBDEV_FORMAT_ACTIVE;
                ret = v4l2_subdev_call(subdev, pad, enum_mbus_code,
                               NULL, &mbus_code);
                if (ret)
@@ -2390,9 +2389,9 @@ static int vpfe_probe_complete(struct vpfe_device *vpfe)
 
        INIT_LIST_HEAD(&vpfe->dma_queue);
 
-       vdev = vpfe->video_dev;
+       vdev = &vpfe->video_dev;
        strlcpy(vdev->name, VPFE_MODULE_NAME, sizeof(vdev->name));
-       vdev->release = video_device_release;
+       vdev->release = video_device_release_empty;
        vdev->fops = &vpfe_fops;
        vdev->ioctl_ops = &vpfe_ioctl_ops;
        vdev->v4l2_dev = &vpfe->v4l2_dev;
@@ -2400,7 +2399,7 @@ static int vpfe_probe_complete(struct vpfe_device *vpfe)
        vdev->queue = q;
        vdev->lock = &vpfe->lock;
        video_set_drvdata(vdev, vpfe);
-       err = video_register_device(vpfe->video_dev, VFL_TYPE_GRABBER, -1);
+       err = video_register_device(&vpfe->video_dev, VFL_TYPE_GRABBER, -1);
        if (err) {
                vpfe_err(vpfe,
                        "Unable to register video device.\n");
@@ -2425,7 +2424,7 @@ static int vpfe_async_complete(struct v4l2_async_notifier *notifier)
 static struct vpfe_config *
 vpfe_get_pdata(struct platform_device *pdev)
 {
-       struct device_node *endpoint = NULL, *rem = NULL;
+       struct device_node *endpoint = NULL;
        struct v4l2_of_endpoint bus_cfg;
        struct vpfe_subdev_info *sdinfo;
        struct vpfe_config *pdata;
@@ -2443,6 +2442,8 @@ vpfe_get_pdata(struct platform_device *pdev)
                return NULL;
 
        for (i = 0; ; i++) {
+               struct device_node *rem;
+
                endpoint = of_graph_get_next_endpoint(pdev->dev.of_node,
                                                      endpoint);
                if (!endpoint)
@@ -2497,11 +2498,15 @@ vpfe_get_pdata(struct platform_device *pdev)
                        goto done;
                }
 
-               strncpy(sdinfo->name, rem->name, sizeof(sdinfo->name));
-
                pdata->asd[i] = devm_kzalloc(&pdev->dev,
                                             sizeof(struct v4l2_async_subdev),
                                             GFP_KERNEL);
+               if (!pdata->asd[i]) {
+                       of_node_put(rem);
+                       pdata = NULL;
+                       goto done;
+               }
+
                pdata->asd[i]->match_type = V4L2_ASYNC_MATCH_OF;
                pdata->asd[i]->match.of.node = rem;
                of_node_put(rem);
@@ -2512,7 +2517,6 @@ vpfe_get_pdata(struct platform_device *pdev)
 
 done:
        of_node_put(endpoint);
-       of_node_put(rem);
        return NULL;
 }
 
@@ -2560,17 +2564,11 @@ static int vpfe_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       vpfe->video_dev = video_device_alloc();
-       if (!vpfe->video_dev) {
-               dev_err(&pdev->dev, "Unable to allocate video device\n");
-               return -ENOMEM;
-       }
-
        ret = v4l2_device_register(&pdev->dev, &vpfe->v4l2_dev);
        if (ret) {
                vpfe_err(vpfe,
                        "Unable to register v4l2 device.\n");
-               goto probe_out_video_release;
+               return ret;
        }
 
        /* set the driver data in platform device */
@@ -2608,9 +2606,6 @@ static int vpfe_probe(struct platform_device *pdev)
 
 probe_out_v4l2_unregister:
        v4l2_device_unregister(&vpfe->v4l2_dev);
-probe_out_video_release:
-       if (!video_is_registered(vpfe->video_dev))
-               video_device_release(vpfe->video_dev);
        return ret;
 }
 
@@ -2627,7 +2622,7 @@ static int vpfe_remove(struct platform_device *pdev)
 
        v4l2_async_notifier_unregister(&vpfe->notifier);
        v4l2_device_unregister(&vpfe->v4l2_dev);
-       video_unregister_device(vpfe->video_dev);
+       video_unregister_device(&vpfe->video_dev);
 
        return 0;
 }
index 0f557352313d8bf29705837e2aad103da24fdd8d..5bfb35649a39b92494dfd35594fc9cb824a43c98 100644 (file)
@@ -83,7 +83,6 @@ struct vpfe_route {
 };
 
 struct vpfe_subdev_info {
-        char name[32];
        /* Sub device group id */
        int grp_id;
        /* inputs available at the sub device */
@@ -223,7 +222,7 @@ struct vpfe_ccdc {
 struct vpfe_device {
        /* V4l2 specific parameters */
        /* Identifies video device for this channel */
-       struct video_device *video_dev;
+       struct video_device video_dev;
        /* sub devices */
        struct v4l2_subdev **sd;
        /* vpfe cfg */
index 8f6698668ecfb49e90ea34cb61285886fa725b8b..6a437f86dcdc61b55fd2cb0d59187ca381ae4d08 100644 (file)
@@ -44,7 +44,6 @@
 #include <media/blackfin/ppi.h>
 
 #define CAPTURE_DRV_NAME        "bfin_capture"
-#define BCAP_MIN_NUM_BUF        2
 
 struct bcap_format {
        char *desc;
@@ -65,7 +64,7 @@ struct bcap_device {
        /* v4l2 control handler */
        struct v4l2_ctrl_handler ctrl_handler;
        /* device node data */
-       struct video_device *video_dev;
+       struct video_device video_dev;
        /* sub device instance */
        struct v4l2_subdev *sd;
        /* capture config */
@@ -104,12 +103,8 @@ struct bcap_device {
        struct completion comp;
        /* prepare to stop */
        bool stop;
-};
-
-struct bcap_fh {
-       struct v4l2_fh fh;
-       /* indicates whether this file handle is doing IO */
-       bool io_allowed;
+       /* vb2 buffer sequence counter */
+       unsigned sequence;
 };
 
 static const struct bcap_format bcap_formats[] = {
@@ -201,90 +196,6 @@ static void bcap_free_sensor_formats(struct bcap_device *bcap_dev)
        bcap_dev->sensor_formats = NULL;
 }
 
-static int bcap_open(struct file *file)
-{
-       struct bcap_device *bcap_dev = video_drvdata(file);
-       struct video_device *vfd = bcap_dev->video_dev;
-       struct bcap_fh *bcap_fh;
-
-       if (!bcap_dev->sd) {
-               v4l2_err(&bcap_dev->v4l2_dev, "No sub device registered\n");
-               return -ENODEV;
-       }
-
-       bcap_fh = kzalloc(sizeof(*bcap_fh), GFP_KERNEL);
-       if (!bcap_fh) {
-               v4l2_err(&bcap_dev->v4l2_dev,
-                        "unable to allocate memory for file handle object\n");
-               return -ENOMEM;
-       }
-
-       v4l2_fh_init(&bcap_fh->fh, vfd);
-
-       /* store pointer to v4l2_fh in private_data member of file */
-       file->private_data = &bcap_fh->fh;
-       v4l2_fh_add(&bcap_fh->fh);
-       bcap_fh->io_allowed = false;
-       return 0;
-}
-
-static int bcap_release(struct file *file)
-{
-       struct bcap_device *bcap_dev = video_drvdata(file);
-       struct v4l2_fh *fh = file->private_data;
-       struct bcap_fh *bcap_fh = container_of(fh, struct bcap_fh, fh);
-
-       /* if this instance is doing IO */
-       if (bcap_fh->io_allowed)
-               vb2_queue_release(&bcap_dev->buffer_queue);
-
-       file->private_data = NULL;
-       v4l2_fh_del(&bcap_fh->fh);
-       v4l2_fh_exit(&bcap_fh->fh);
-       kfree(bcap_fh);
-       return 0;
-}
-
-static int bcap_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct bcap_device *bcap_dev = video_drvdata(file);
-       int ret;
-
-       if (mutex_lock_interruptible(&bcap_dev->mutex))
-               return -ERESTARTSYS;
-       ret = vb2_mmap(&bcap_dev->buffer_queue, vma);
-       mutex_unlock(&bcap_dev->mutex);
-       return ret;
-}
-
-#ifndef CONFIG_MMU
-static unsigned long bcap_get_unmapped_area(struct file *file,
-                                           unsigned long addr,
-                                           unsigned long len,
-                                           unsigned long pgoff,
-                                           unsigned long flags)
-{
-       struct bcap_device *bcap_dev = video_drvdata(file);
-
-       return vb2_get_unmapped_area(&bcap_dev->buffer_queue,
-                                    addr,
-                                    len,
-                                    pgoff,
-                                    flags);
-}
-#endif
-
-static unsigned int bcap_poll(struct file *file, poll_table *wait)
-{
-       struct bcap_device *bcap_dev = video_drvdata(file);
-       unsigned int res;
-
-       mutex_lock(&bcap_dev->mutex);
-       res = vb2_poll(&bcap_dev->buffer_queue, file, wait);
-       mutex_unlock(&bcap_dev->mutex);
-       return res;
-}
-
 static int bcap_queue_setup(struct vb2_queue *vq,
                                const struct v4l2_format *fmt,
                                unsigned int *nbuffers, unsigned int *nplanes,
@@ -292,37 +203,32 @@ static int bcap_queue_setup(struct vb2_queue *vq,
 {
        struct bcap_device *bcap_dev = vb2_get_drv_priv(vq);
 
-       if (*nbuffers < BCAP_MIN_NUM_BUF)
-               *nbuffers = BCAP_MIN_NUM_BUF;
+       if (fmt && fmt->fmt.pix.sizeimage < bcap_dev->fmt.sizeimage)
+               return -EINVAL;
+
+       if (vq->num_buffers + *nbuffers < 2)
+               *nbuffers = 2;
 
        *nplanes = 1;
-       sizes[0] = bcap_dev->fmt.sizeimage;
+       sizes[0] = fmt ? fmt->fmt.pix.sizeimage : bcap_dev->fmt.sizeimage;
        alloc_ctxs[0] = bcap_dev->alloc_ctx;
 
        return 0;
 }
 
-static int bcap_buffer_init(struct vb2_buffer *vb)
-{
-       struct bcap_buffer *buf = to_bcap_vb(vb);
-
-       INIT_LIST_HEAD(&buf->list);
-       return 0;
-}
-
 static int bcap_buffer_prepare(struct vb2_buffer *vb)
 {
        struct bcap_device *bcap_dev = vb2_get_drv_priv(vb->vb2_queue);
-       struct bcap_buffer *buf = to_bcap_vb(vb);
-       unsigned long size;
+       unsigned long size = bcap_dev->fmt.sizeimage;
 
-       size = bcap_dev->fmt.sizeimage;
        if (vb2_plane_size(vb, 0) < size) {
                v4l2_err(&bcap_dev->v4l2_dev, "buffer too small (%lu < %lu)\n",
                                vb2_plane_size(vb, 0), size);
                return -EINVAL;
        }
-       vb2_set_plane_payload(&buf->vb, 0, size);
+       vb2_set_plane_payload(vb, 0, size);
+
+       vb->v4l2_buf.field = bcap_dev->fmt.field;
 
        return 0;
 }
@@ -353,14 +259,16 @@ static int bcap_start_streaming(struct vb2_queue *vq, unsigned int count)
 {
        struct bcap_device *bcap_dev = vb2_get_drv_priv(vq);
        struct ppi_if *ppi = bcap_dev->ppi;
+       struct bcap_buffer *buf, *tmp;
        struct ppi_params params;
+       dma_addr_t addr;
        int ret;
 
        /* enable streamon on the sub device */
        ret = v4l2_subdev_call(bcap_dev->sd, video, s_stream, 1);
        if (ret && (ret != -ENOIOCTLCMD)) {
                v4l2_err(&bcap_dev->v4l2_dev, "stream on failed in subdev\n");
-               return ret;
+               goto err;
        }
 
        /* set ppi params */
@@ -399,7 +307,7 @@ static int bcap_start_streaming(struct vb2_queue *vq, unsigned int count)
        if (ret < 0) {
                v4l2_err(&bcap_dev->v4l2_dev,
                                "Error in setting ppi params\n");
-               return ret;
+               goto err;
        }
 
        /* attach ppi DMA irq handler */
@@ -407,12 +315,34 @@ static int bcap_start_streaming(struct vb2_queue *vq, unsigned int count)
        if (ret < 0) {
                v4l2_err(&bcap_dev->v4l2_dev,
                                "Error in attaching interrupt handler\n");
-               return ret;
+               goto err;
        }
 
+       bcap_dev->sequence = 0;
+
        reinit_completion(&bcap_dev->comp);
        bcap_dev->stop = false;
+
+       /* get the next frame from the dma queue */
+       bcap_dev->cur_frm = list_entry(bcap_dev->dma_queue.next,
+                                       struct bcap_buffer, list);
+       /* remove buffer from the dma queue */
+       list_del_init(&bcap_dev->cur_frm->list);
+       addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->cur_frm->vb, 0);
+       /* update DMA address */
+       ppi->ops->update_addr(ppi, (unsigned long)addr);
+       /* enable ppi */
+       ppi->ops->start(ppi);
+
        return 0;
+
+err:
+       list_for_each_entry_safe(buf, tmp, &bcap_dev->dma_queue, list) {
+               list_del(&buf->list);
+               vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+       }
+
+       return ret;
 }
 
 static void bcap_stop_streaming(struct vb2_queue *vq)
@@ -431,6 +361,9 @@ static void bcap_stop_streaming(struct vb2_queue *vq)
                                "stream off failed in subdev\n");
 
        /* release all active buffers */
+       if (bcap_dev->cur_frm)
+               vb2_buffer_done(&bcap_dev->cur_frm->vb, VB2_BUF_STATE_ERROR);
+
        while (!list_empty(&bcap_dev->dma_queue)) {
                bcap_dev->cur_frm = list_entry(bcap_dev->dma_queue.next,
                                                struct bcap_buffer, list);
@@ -441,7 +374,6 @@ static void bcap_stop_streaming(struct vb2_queue *vq)
 
 static struct vb2_ops bcap_video_qops = {
        .queue_setup            = bcap_queue_setup,
-       .buf_init               = bcap_buffer_init,
        .buf_prepare            = bcap_buffer_prepare,
        .buf_cleanup            = bcap_buffer_cleanup,
        .buf_queue              = bcap_buffer_queue,
@@ -451,57 +383,6 @@ static struct vb2_ops bcap_video_qops = {
        .stop_streaming         = bcap_stop_streaming,
 };
 
-static int bcap_reqbufs(struct file *file, void *priv,
-                       struct v4l2_requestbuffers *req_buf)
-{
-       struct bcap_device *bcap_dev = video_drvdata(file);
-       struct vb2_queue *vq = &bcap_dev->buffer_queue;
-       struct v4l2_fh *fh = file->private_data;
-       struct bcap_fh *bcap_fh = container_of(fh, struct bcap_fh, fh);
-
-       if (vb2_is_busy(vq))
-               return -EBUSY;
-
-       bcap_fh->io_allowed = true;
-
-       return vb2_reqbufs(vq, req_buf);
-}
-
-static int bcap_querybuf(struct file *file, void *priv,
-                               struct v4l2_buffer *buf)
-{
-       struct bcap_device *bcap_dev = video_drvdata(file);
-
-       return vb2_querybuf(&bcap_dev->buffer_queue, buf);
-}
-
-static int bcap_qbuf(struct file *file, void *priv,
-                       struct v4l2_buffer *buf)
-{
-       struct bcap_device *bcap_dev = video_drvdata(file);
-       struct v4l2_fh *fh = file->private_data;
-       struct bcap_fh *bcap_fh = container_of(fh, struct bcap_fh, fh);
-
-       if (!bcap_fh->io_allowed)
-               return -EBUSY;
-
-       return vb2_qbuf(&bcap_dev->buffer_queue, buf);
-}
-
-static int bcap_dqbuf(struct file *file, void *priv,
-                       struct v4l2_buffer *buf)
-{
-       struct bcap_device *bcap_dev = video_drvdata(file);
-       struct v4l2_fh *fh = file->private_data;
-       struct bcap_fh *bcap_fh = container_of(fh, struct bcap_fh, fh);
-
-       if (!bcap_fh->io_allowed)
-               return -EBUSY;
-
-       return vb2_dqbuf(&bcap_dev->buffer_queue,
-                               buf, file->f_flags & O_NONBLOCK);
-}
-
 static irqreturn_t bcap_isr(int irq, void *dev_id)
 {
        struct ppi_if *ppi = dev_id;
@@ -517,6 +398,7 @@ static irqreturn_t bcap_isr(int irq, void *dev_id)
                        vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
                        ppi->err = false;
                } else {
+                       vb->v4l2_buf.sequence = bcap_dev->sequence++;
                        vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
                }
                bcap_dev->cur_frm = list_entry(bcap_dev->dma_queue.next,
@@ -543,62 +425,14 @@ static irqreturn_t bcap_isr(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int bcap_streamon(struct file *file, void *priv,
-                               enum v4l2_buf_type buf_type)
-{
-       struct bcap_device *bcap_dev = video_drvdata(file);
-       struct bcap_fh *fh = file->private_data;
-       struct ppi_if *ppi = bcap_dev->ppi;
-       dma_addr_t addr;
-       int ret;
-
-       if (!fh->io_allowed)
-               return -EBUSY;
-
-       /* call streamon to start streaming in videobuf */
-       ret = vb2_streamon(&bcap_dev->buffer_queue, buf_type);
-       if (ret)
-               return ret;
-
-       /* if dma queue is empty, return error */
-       if (list_empty(&bcap_dev->dma_queue)) {
-               v4l2_err(&bcap_dev->v4l2_dev, "dma queue is empty\n");
-               ret = -EINVAL;
-               goto err;
-       }
-
-       /* get the next frame from the dma queue */
-       bcap_dev->cur_frm = list_entry(bcap_dev->dma_queue.next,
-                                       struct bcap_buffer, list);
-       /* remove buffer from the dma queue */
-       list_del_init(&bcap_dev->cur_frm->list);
-       addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->cur_frm->vb, 0);
-       /* update DMA address */
-       ppi->ops->update_addr(ppi, (unsigned long)addr);
-       /* enable ppi */
-       ppi->ops->start(ppi);
-
-       return 0;
-err:
-       vb2_streamoff(&bcap_dev->buffer_queue, buf_type);
-       return ret;
-}
-
-static int bcap_streamoff(struct file *file, void *priv,
-                               enum v4l2_buf_type buf_type)
-{
-       struct bcap_device *bcap_dev = video_drvdata(file);
-       struct bcap_fh *fh = file->private_data;
-
-       if (!fh->io_allowed)
-               return -EBUSY;
-
-       return vb2_streamoff(&bcap_dev->buffer_queue, buf_type);
-}
-
 static int bcap_querystd(struct file *file, void *priv, v4l2_std_id *std)
 {
        struct bcap_device *bcap_dev = video_drvdata(file);
+       struct v4l2_input input;
+
+       input = bcap_dev->cfg->inputs[bcap_dev->cur_input];
+       if (!(input.capabilities & V4L2_IN_CAP_STD))
+               return -ENODATA;
 
        return v4l2_subdev_call(bcap_dev->sd, video, querystd, std);
 }
@@ -606,6 +440,11 @@ static int bcap_querystd(struct file *file, void *priv, v4l2_std_id *std)
 static int bcap_g_std(struct file *file, void *priv, v4l2_std_id *std)
 {
        struct bcap_device *bcap_dev = video_drvdata(file);
+       struct v4l2_input input;
+
+       input = bcap_dev->cfg->inputs[bcap_dev->cur_input];
+       if (!(input.capabilities & V4L2_IN_CAP_STD))
+               return -ENODATA;
 
        *std = bcap_dev->std;
        return 0;
@@ -614,8 +453,13 @@ static int bcap_g_std(struct file *file, void *priv, v4l2_std_id *std)
 static int bcap_s_std(struct file *file, void *priv, v4l2_std_id std)
 {
        struct bcap_device *bcap_dev = video_drvdata(file);
+       struct v4l2_input input;
        int ret;
 
+       input = bcap_dev->cfg->inputs[bcap_dev->cur_input];
+       if (!(input.capabilities & V4L2_IN_CAP_STD))
+               return -ENODATA;
+
        if (vb2_is_busy(&bcap_dev->buffer_queue))
                return -EBUSY;
 
@@ -631,6 +475,11 @@ static int bcap_enum_dv_timings(struct file *file, void *priv,
                                struct v4l2_enum_dv_timings *timings)
 {
        struct bcap_device *bcap_dev = video_drvdata(file);
+       struct v4l2_input input;
+
+       input = bcap_dev->cfg->inputs[bcap_dev->cur_input];
+       if (!(input.capabilities & V4L2_IN_CAP_DV_TIMINGS))
+               return -ENODATA;
 
        timings->pad = 0;
 
@@ -642,6 +491,11 @@ static int bcap_query_dv_timings(struct file *file, void *priv,
                                struct v4l2_dv_timings *timings)
 {
        struct bcap_device *bcap_dev = video_drvdata(file);
+       struct v4l2_input input;
+
+       input = bcap_dev->cfg->inputs[bcap_dev->cur_input];
+       if (!(input.capabilities & V4L2_IN_CAP_DV_TIMINGS))
+               return -ENODATA;
 
        return v4l2_subdev_call(bcap_dev->sd, video,
                                query_dv_timings, timings);
@@ -651,6 +505,11 @@ static int bcap_g_dv_timings(struct file *file, void *priv,
                                struct v4l2_dv_timings *timings)
 {
        struct bcap_device *bcap_dev = video_drvdata(file);
+       struct v4l2_input input;
+
+       input = bcap_dev->cfg->inputs[bcap_dev->cur_input];
+       if (!(input.capabilities & V4L2_IN_CAP_DV_TIMINGS))
+               return -ENODATA;
 
        *timings = bcap_dev->dv_timings;
        return 0;
@@ -660,7 +519,13 @@ static int bcap_s_dv_timings(struct file *file, void *priv,
                                struct v4l2_dv_timings *timings)
 {
        struct bcap_device *bcap_dev = video_drvdata(file);
+       struct v4l2_input input;
        int ret;
+
+       input = bcap_dev->cfg->inputs[bcap_dev->cur_input];
+       if (!(input.capabilities & V4L2_IN_CAP_DV_TIMINGS))
+               return -ENODATA;
+
        if (vb2_is_busy(&bcap_dev->buffer_queue))
                return -EBUSY;
 
@@ -881,12 +746,14 @@ static const struct v4l2_ioctl_ops bcap_ioctl_ops = {
        .vidioc_g_dv_timings     = bcap_g_dv_timings,
        .vidioc_query_dv_timings = bcap_query_dv_timings,
        .vidioc_enum_dv_timings  = bcap_enum_dv_timings,
-       .vidioc_reqbufs          = bcap_reqbufs,
-       .vidioc_querybuf         = bcap_querybuf,
-       .vidioc_qbuf             = bcap_qbuf,
-       .vidioc_dqbuf            = bcap_dqbuf,
-       .vidioc_streamon         = bcap_streamon,
-       .vidioc_streamoff        = bcap_streamoff,
+       .vidioc_reqbufs          = vb2_ioctl_reqbufs,
+       .vidioc_create_bufs      = vb2_ioctl_create_bufs,
+       .vidioc_querybuf         = vb2_ioctl_querybuf,
+       .vidioc_qbuf             = vb2_ioctl_qbuf,
+       .vidioc_dqbuf            = vb2_ioctl_dqbuf,
+       .vidioc_expbuf           = vb2_ioctl_expbuf,
+       .vidioc_streamon         = vb2_ioctl_streamon,
+       .vidioc_streamoff        = vb2_ioctl_streamoff,
        .vidioc_g_parm           = bcap_g_parm,
        .vidioc_s_parm           = bcap_s_parm,
        .vidioc_log_status       = bcap_log_status,
@@ -894,14 +761,14 @@ static const struct v4l2_ioctl_ops bcap_ioctl_ops = {
 
 static struct v4l2_file_operations bcap_fops = {
        .owner = THIS_MODULE,
-       .open = bcap_open,
-       .release = bcap_release,
+       .open = v4l2_fh_open,
+       .release = vb2_fop_release,
        .unlocked_ioctl = video_ioctl2,
-       .mmap = bcap_mmap,
+       .mmap = vb2_fop_mmap,
 #ifndef CONFIG_MMU
-       .get_unmapped_area = bcap_get_unmapped_area,
+       .get_unmapped_area = vb2_fop_get_unmapped_area,
 #endif
-       .poll = bcap_poll
+       .poll = vb2_fop_poll
 };
 
 static int bcap_probe(struct platform_device *pdev)
@@ -942,27 +809,20 @@ static int bcap_probe(struct platform_device *pdev)
                goto err_free_ppi;
        }
 
-       vfd = video_device_alloc();
-       if (!vfd) {
-               ret = -ENOMEM;
-               v4l2_err(pdev->dev.driver, "Unable to alloc video device\n");
-               goto err_cleanup_ctx;
-       }
-
+       vfd = &bcap_dev->video_dev;
        /* initialize field of video device */
-       vfd->release            = video_device_release;
+       vfd->release            = video_device_release_empty;
        vfd->fops               = &bcap_fops;
        vfd->ioctl_ops          = &bcap_ioctl_ops;
        vfd->tvnorms            = 0;
        vfd->v4l2_dev           = &bcap_dev->v4l2_dev;
        strncpy(vfd->name, CAPTURE_DRV_NAME, sizeof(vfd->name));
-       bcap_dev->video_dev     = vfd;
 
        ret = v4l2_device_register(&pdev->dev, &bcap_dev->v4l2_dev);
        if (ret) {
                v4l2_err(pdev->dev.driver,
                                "Unable to register v4l2 device\n");
-               goto err_release_vdev;
+               goto err_cleanup_ctx;
        }
        v4l2_info(&bcap_dev->v4l2_dev, "v4l2 device registered\n");
 
@@ -978,13 +838,14 @@ static int bcap_probe(struct platform_device *pdev)
        /* initialize queue */
        q = &bcap_dev->buffer_queue;
        q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       q->io_modes = VB2_MMAP;
+       q->io_modes = VB2_MMAP | VB2_DMABUF;
        q->drv_priv = bcap_dev;
        q->buf_struct_size = sizeof(struct bcap_buffer);
        q->ops = &bcap_video_qops;
        q->mem_ops = &vb2_dma_contig_memops;
        q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
        q->lock = &bcap_dev->mutex;
+       q->min_buffers_needed = 1;
 
        ret = vb2_queue_init(q);
        if (ret)
@@ -997,15 +858,16 @@ static int bcap_probe(struct platform_device *pdev)
        INIT_LIST_HEAD(&bcap_dev->dma_queue);
 
        vfd->lock = &bcap_dev->mutex;
+       vfd->queue = q;
 
        /* register video device */
-       ret = video_register_device(bcap_dev->video_dev, VFL_TYPE_GRABBER, -1);
+       ret = video_register_device(&bcap_dev->video_dev, VFL_TYPE_GRABBER, -1);
        if (ret) {
                v4l2_err(&bcap_dev->v4l2_dev,
                                "Unable to register video device\n");
                goto err_free_handler;
        }
-       video_set_drvdata(bcap_dev->video_dev, bcap_dev);
+       video_set_drvdata(&bcap_dev->video_dev, bcap_dev);
        v4l2_info(&bcap_dev->v4l2_dev, "video device registered as: %s\n",
                        video_device_node_name(vfd));
 
@@ -1083,15 +945,11 @@ static int bcap_probe(struct platform_device *pdev)
        }
        return 0;
 err_unreg_vdev:
-       video_unregister_device(bcap_dev->video_dev);
-       bcap_dev->video_dev = NULL;
+       video_unregister_device(&bcap_dev->video_dev);
 err_free_handler:
        v4l2_ctrl_handler_free(&bcap_dev->ctrl_handler);
 err_unreg_v4l2:
        v4l2_device_unregister(&bcap_dev->v4l2_dev);
-err_release_vdev:
-       if (bcap_dev->video_dev)
-               video_device_release(bcap_dev->video_dev);
 err_cleanup_ctx:
        vb2_dma_contig_cleanup_ctx(bcap_dev->alloc_ctx);
 err_free_ppi:
@@ -1108,7 +966,7 @@ static int bcap_remove(struct platform_device *pdev)
                                                struct bcap_device, v4l2_dev);
 
        bcap_free_sensor_formats(bcap_dev);
-       video_unregister_device(bcap_dev->video_dev);
+       video_unregister_device(&bcap_dev->video_dev);
        v4l2_ctrl_handler_free(&bcap_dev->ctrl_handler);
        v4l2_device_unregister(v4l2_dev);
        vb2_dma_contig_cleanup_ctx(bcap_dev->alloc_ctx);
index 25ce15561695de6a214798f35f1ace978b1978ca..834e504bf0854cae2db5be814278cebfbd910aae 100644 (file)
@@ -1,3 +1,5 @@
+ccflags-y += -I$(src)
+
 coda-objs := coda-common.o coda-bit.o coda-h264.o coda-jpeg.o
 
 obj-$(CONFIG_VIDEO_CODA) += coda.o
index 856b542b35b9c4a3c6d2930edcf8773304003d5e..d0430071d2eea38bb32299b78092b31447b6329c 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/clk.h>
 #include <linux/irqreturn.h>
 #include <linux/kernel.h>
+#include <linux/log2.h>
 #include <linux/platform_device.h>
 #include <linux/reset.h>
 #include <linux/slab.h>
 #include <media/videobuf2-vmalloc.h>
 
 #include "coda.h"
+#define CREATE_TRACE_POINTS
+#include "trace.h"
 
+#define CODA_PARA_BUF_SIZE     (10 * 1024)
 #define CODA7_PS_BUF_SIZE      0x28000
 #define CODA9_PS_SAVE_SIZE     (512 * 1024)
 
 #define CODA_DEFAULT_GAMMA     4096
 #define CODA9_DEFAULT_GAMMA    24576   /* 0.75 * 32768 */
 
+static void coda_free_bitstream_buffer(struct coda_ctx *ctx);
+
 static inline int coda_is_initialized(struct coda_dev *dev)
 {
        return coda_read(dev, CODA_REG_BIT_CUR_PC) != 0;
@@ -84,15 +90,21 @@ static void coda_command_async(struct coda_ctx *ctx, int cmd)
        coda_write(dev, ctx->params.codec_mode, CODA_REG_BIT_RUN_COD_STD);
        coda_write(dev, ctx->params.codec_mode_aux, CODA7_REG_BIT_RUN_AUX_STD);
 
+       trace_coda_bit_run(ctx, cmd);
+
        coda_write(dev, cmd, CODA_REG_BIT_RUN_COMMAND);
 }
 
 static int coda_command_sync(struct coda_ctx *ctx, int cmd)
 {
        struct coda_dev *dev = ctx->dev;
+       int ret;
 
        coda_command_async(ctx, cmd);
-       return coda_wait_timeout(dev);
+       ret = coda_wait_timeout(dev);
+       trace_coda_bit_done(ctx);
+
+       return ret;
 }
 
 int coda_hw_reset(struct coda_ctx *ctx)
@@ -177,10 +189,6 @@ static int coda_bitstream_queue(struct coda_ctx *ctx,
        if (n < src_size)
                return -ENOSPC;
 
-       dma_sync_single_for_device(&ctx->dev->plat_dev->dev,
-                                  ctx->bitstream.paddr, ctx->bitstream.size,
-                                  DMA_TO_DEVICE);
-
        src_buf->v4l2_buf.sequence = ctx->qsequence++;
 
        return 0;
@@ -214,7 +222,7 @@ static bool coda_bitstream_try_queue(struct coda_ctx *ctx,
        return true;
 }
 
-void coda_fill_bitstream(struct coda_ctx *ctx)
+void coda_fill_bitstream(struct coda_ctx *ctx, bool streaming)
 {
        struct vb2_buffer *src_buf;
        struct coda_buffer_meta *meta;
@@ -235,9 +243,12 @@ void coda_fill_bitstream(struct coda_ctx *ctx)
                if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG &&
                    !coda_jpeg_check_buffer(ctx, src_buf)) {
                        v4l2_err(&ctx->dev->v4l2_dev,
-                                "dropping invalid JPEG frame\n");
+                                "dropping invalid JPEG frame %d\n",
+                                ctx->qsequence);
                        src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
-                       v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR);
+                       v4l2_m2m_buf_done(src_buf, streaming ?
+                                         VB2_BUF_STATE_ERROR :
+                                         VB2_BUF_STATE_QUEUED);
                        continue;
                }
 
@@ -262,6 +273,8 @@ void coda_fill_bitstream(struct coda_ctx *ctx)
                                            ctx->bitstream_fifo.kfifo.mask;
                                list_add_tail(&meta->list,
                                              &ctx->buffer_meta_list);
+
+                               trace_coda_bit_queue(ctx, src_buf, meta);
                        }
 
                        v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
@@ -297,6 +310,14 @@ static void coda_parabuf_write(struct coda_ctx *ctx, int index, u32 value)
                p[index ^ 1] = value;
 }
 
+static inline int coda_alloc_context_buf(struct coda_ctx *ctx,
+                                        struct coda_aux_buf *buf, size_t size,
+                                        const char *name)
+{
+       return coda_alloc_aux_buf(ctx->dev, buf, size, name, ctx->debugfs_entry);
+}
+
+
 static void coda_free_framebuffers(struct coda_ctx *ctx)
 {
        int i;
@@ -377,6 +398,7 @@ static void coda_free_context_buffers(struct coda_ctx *ctx)
        coda_free_aux_buf(dev, &ctx->psbuf);
        if (dev->devtype->product != CODA_DX6)
                coda_free_aux_buf(dev, &ctx->workbuf);
+       coda_free_aux_buf(dev, &ctx->parabuf);
 }
 
 static int coda_alloc_context_buffers(struct coda_ctx *ctx,
@@ -386,57 +408,42 @@ static int coda_alloc_context_buffers(struct coda_ctx *ctx,
        size_t size;
        int ret;
 
+       if (!ctx->parabuf.vaddr) {
+               ret = coda_alloc_context_buf(ctx, &ctx->parabuf,
+                                            CODA_PARA_BUF_SIZE, "parabuf");
+               if (ret < 0)
+                       return ret;
+       }
+
        if (dev->devtype->product == CODA_DX6)
                return 0;
 
-       if (ctx->psbuf.vaddr) {
-               v4l2_err(&dev->v4l2_dev, "psmembuf still allocated\n");
-               return -EBUSY;
-       }
-       if (ctx->slicebuf.vaddr) {
-               v4l2_err(&dev->v4l2_dev, "slicebuf still allocated\n");
-               return -EBUSY;
-       }
-       if (ctx->workbuf.vaddr) {
-               v4l2_err(&dev->v4l2_dev, "context buffer still allocated\n");
-               ret = -EBUSY;
-               return -ENOMEM;
-       }
-
-       if (q_data->fourcc == V4L2_PIX_FMT_H264) {
+       if (!ctx->slicebuf.vaddr && q_data->fourcc == V4L2_PIX_FMT_H264) {
                /* worst case slice size */
                size = (DIV_ROUND_UP(q_data->width, 16) *
                        DIV_ROUND_UP(q_data->height, 16)) * 3200 / 8 + 512;
                ret = coda_alloc_context_buf(ctx, &ctx->slicebuf, size,
                                             "slicebuf");
-               if (ret < 0) {
-                       v4l2_err(&dev->v4l2_dev,
-                                "failed to allocate %d byte slice buffer",
-                                ctx->slicebuf.size);
-                       return ret;
-               }
+               if (ret < 0)
+                       goto err;
        }
 
-       if (dev->devtype->product == CODA_7541) {
+       if (!ctx->psbuf.vaddr && dev->devtype->product == CODA_7541) {
                ret = coda_alloc_context_buf(ctx, &ctx->psbuf,
                                             CODA7_PS_BUF_SIZE, "psbuf");
-               if (ret < 0) {
-                       v4l2_err(&dev->v4l2_dev,
-                                "failed to allocate psmem buffer");
+               if (ret < 0)
                        goto err;
-               }
        }
 
-       size = dev->devtype->workbuf_size;
-       if (dev->devtype->product == CODA_960 &&
-           q_data->fourcc == V4L2_PIX_FMT_H264)
-               size += CODA9_PS_SAVE_SIZE;
-       ret = coda_alloc_context_buf(ctx, &ctx->workbuf, size, "workbuf");
-       if (ret < 0) {
-               v4l2_err(&dev->v4l2_dev,
-                        "failed to allocate %d byte context buffer",
-                        ctx->workbuf.size);
-               goto err;
+       if (!ctx->workbuf.vaddr) {
+               size = dev->devtype->workbuf_size;
+               if (dev->devtype->product == CODA_960 &&
+                   q_data->fourcc == V4L2_PIX_FMT_H264)
+                       size += CODA9_PS_SAVE_SIZE;
+               ret = coda_alloc_context_buf(ctx, &ctx->workbuf, size,
+                                            "workbuf");
+               if (ret < 0)
+                       goto err;
        }
 
        return 0;
@@ -709,6 +716,27 @@ err_clk_per:
  * Encoder context operations
  */
 
+static int coda_encoder_reqbufs(struct coda_ctx *ctx,
+                               struct v4l2_requestbuffers *rb)
+{
+       struct coda_q_data *q_data_src;
+       int ret;
+
+       if (rb->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+               return 0;
+
+       if (rb->count) {
+               q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+               ret = coda_alloc_context_buffers(ctx, q_data_src);
+               if (ret < 0)
+                       return ret;
+       } else {
+               coda_free_context_buffers(ctx);
+       }
+
+       return 0;
+}
+
 static int coda_start_encoding(struct coda_ctx *ctx)
 {
        struct coda_dev *dev = ctx->dev;
@@ -725,11 +753,6 @@ static int coda_start_encoding(struct coda_ctx *ctx)
        q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
        dst_fourcc = q_data_dst->fourcc;
 
-       /* Allocate per-instance buffers */
-       ret = coda_alloc_context_buffers(ctx, q_data_src);
-       if (ret < 0)
-               return ret;
-
        buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
        bitstream_buf = vb2_dma_contig_plane_dma_addr(buf, 0);
        bitstream_size = q_data_dst->sizeimage;
@@ -1227,6 +1250,8 @@ static int coda_prepare_encode(struct coda_ctx *ctx)
                coda_write(dev, ctx->iram_info.axi_sram_use,
                                CODA7_REG_BIT_AXI_SRAM_USE);
 
+       trace_coda_enc_pic_run(ctx, src_buf);
+
        coda_command_async(ctx, CODA_COMMAND_PIC_RUN);
 
        return 0;
@@ -1241,6 +1266,8 @@ static void coda_finish_encode(struct coda_ctx *ctx)
        src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
        dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
 
+       trace_coda_enc_pic_done(ctx, dst_buf);
+
        /* Get results from the coda */
        start_ptr = coda_read(dev, CODA_CMD_ENC_PIC_BB_START);
        wr_ptr = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx));
@@ -1311,7 +1338,6 @@ static void coda_seq_end_work(struct work_struct *work)
                ctx->bitstream.vaddr, ctx->bitstream.size);
 
        coda_free_framebuffers(ctx);
-       coda_free_context_buffers(ctx);
 
        mutex_unlock(&dev->coda_mutex);
        mutex_unlock(&ctx->buffer_mutex);
@@ -1322,11 +1348,13 @@ static void coda_bit_release(struct coda_ctx *ctx)
        mutex_lock(&ctx->buffer_mutex);
        coda_free_framebuffers(ctx);
        coda_free_context_buffers(ctx);
+       coda_free_bitstream_buffer(ctx);
        mutex_unlock(&ctx->buffer_mutex);
 }
 
 const struct coda_context_ops coda_bit_encode_ops = {
        .queue_init = coda_encoder_queue_init,
+       .reqbufs = coda_encoder_reqbufs,
        .start_streaming = coda_start_encoding,
        .prepare_run = coda_prepare_encode,
        .finish_run = coda_finish_encode,
@@ -1338,6 +1366,65 @@ const struct coda_context_ops coda_bit_encode_ops = {
  * Decoder context operations
  */
 
+static int coda_alloc_bitstream_buffer(struct coda_ctx *ctx,
+                                      struct coda_q_data *q_data)
+{
+       if (ctx->bitstream.vaddr)
+               return 0;
+
+       ctx->bitstream.size = roundup_pow_of_two(q_data->sizeimage * 2);
+       ctx->bitstream.vaddr = dma_alloc_writecombine(
+                       &ctx->dev->plat_dev->dev, ctx->bitstream.size,
+                       &ctx->bitstream.paddr, GFP_KERNEL);
+       if (!ctx->bitstream.vaddr) {
+               v4l2_err(&ctx->dev->v4l2_dev,
+                        "failed to allocate bitstream ringbuffer");
+               return -ENOMEM;
+       }
+       kfifo_init(&ctx->bitstream_fifo,
+                  ctx->bitstream.vaddr, ctx->bitstream.size);
+
+       return 0;
+}
+
+static void coda_free_bitstream_buffer(struct coda_ctx *ctx)
+{
+       if (ctx->bitstream.vaddr == NULL)
+               return;
+
+       dma_free_writecombine(&ctx->dev->plat_dev->dev, ctx->bitstream.size,
+                             ctx->bitstream.vaddr, ctx->bitstream.paddr);
+       ctx->bitstream.vaddr = NULL;
+       kfifo_init(&ctx->bitstream_fifo, NULL, 0);
+}
+
+static int coda_decoder_reqbufs(struct coda_ctx *ctx,
+                               struct v4l2_requestbuffers *rb)
+{
+       struct coda_q_data *q_data_src;
+       int ret;
+
+       if (rb->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+               return 0;
+
+       if (rb->count) {
+               q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+               ret = coda_alloc_context_buffers(ctx, q_data_src);
+               if (ret < 0)
+                       return ret;
+               ret = coda_alloc_bitstream_buffer(ctx, q_data_src);
+               if (ret < 0) {
+                       coda_free_context_buffers(ctx);
+                       return ret;
+               }
+       } else {
+               coda_free_bitstream_buffer(ctx);
+               coda_free_context_buffers(ctx);
+       }
+
+       return 0;
+}
+
 static int __coda_start_decoding(struct coda_ctx *ctx)
 {
        struct coda_q_data *q_data_src, *q_data_dst;
@@ -1356,11 +1443,6 @@ static int __coda_start_decoding(struct coda_ctx *ctx)
        src_fourcc = q_data_src->fourcc;
        dst_fourcc = q_data_dst->fourcc;
 
-       /* Allocate per-instance buffers */
-       ret = coda_alloc_context_buffers(ctx, q_data_src);
-       if (ret < 0)
-               return ret;
-
        coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR);
 
        /* Update coda bitstream read and write pointers from kfifo */
@@ -1579,7 +1661,7 @@ static int coda_prepare_decode(struct coda_ctx *ctx)
 
        /* Try to copy source buffer contents into the bitstream ringbuffer */
        mutex_lock(&ctx->bitstream_mutex);
-       coda_fill_bitstream(ctx);
+       coda_fill_bitstream(ctx, true);
        mutex_unlock(&ctx->bitstream_mutex);
 
        if (coda_get_bitstream_payload(ctx) < 512 &&
@@ -1675,6 +1757,8 @@ static int coda_prepare_decode(struct coda_ctx *ctx)
        /* Clear decode success flag */
        coda_write(dev, 0, CODA_RET_DEC_PIC_SUCCESS);
 
+       trace_coda_dec_pic_run(ctx, meta);
+
        coda_command_async(ctx, CODA_COMMAND_PIC_RUN);
 
        return 0;
@@ -1704,7 +1788,7 @@ static void coda_finish_decode(struct coda_ctx *ctx)
         * by up to 512 bytes
         */
        if (ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG) {
-               if (coda_get_bitstream_payload(ctx) >= CODA_MAX_FRAME_SIZE - 512)
+               if (coda_get_bitstream_payload(ctx) >= ctx->bitstream.size - 512)
                        kfifo_init(&ctx->bitstream_fifo,
                                ctx->bitstream.vaddr, ctx->bitstream.size);
        }
@@ -1835,6 +1919,8 @@ static void coda_finish_decode(struct coda_ctx *ctx)
                }
                mutex_unlock(&ctx->bitstream_mutex);
 
+               trace_coda_dec_pic_done(ctx, &ctx->frame_metas[decoded_idx]);
+
                val = coda_read(dev, CODA_RET_DEC_PIC_TYPE) & 0x7;
                if (val == 0)
                        ctx->frame_types[decoded_idx] = V4L2_BUF_FLAG_KEYFRAME;
@@ -1874,6 +1960,8 @@ static void coda_finish_decode(struct coda_ctx *ctx)
                dst_buf->v4l2_buf.timecode = meta->timecode;
                dst_buf->v4l2_buf.timestamp = meta->timestamp;
 
+               trace_coda_dec_rot_done(ctx, meta, dst_buf);
+
                switch (q_data_dst->fourcc) {
                case V4L2_PIX_FMT_YUV420:
                case V4L2_PIX_FMT_YVU420:
@@ -1906,6 +1994,7 @@ static void coda_finish_decode(struct coda_ctx *ctx)
 
 const struct coda_context_ops coda_bit_decode_ops = {
        .queue_init = coda_decoder_queue_init,
+       .reqbufs = coda_decoder_reqbufs,
        .start_streaming = coda_start_decoding,
        .prepare_run = coda_prepare_decode,
        .finish_run = coda_finish_decode,
@@ -1931,6 +2020,8 @@ irqreturn_t coda_irq_handler(int irq, void *data)
                return IRQ_HANDLED;
        }
 
+       trace_coda_bit_done(ctx);
+
        if (ctx->aborting) {
                v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
                         "task has been aborted\n");
index 6f32e6d6b156003bbef00adbee47e701b1b866e7..8e6fe0200117f671eb223b3289c63d7ee0073651 100644 (file)
@@ -46,7 +46,6 @@
 #define CODADX6_MAX_INSTANCES  4
 #define CODA_MAX_FORMATS       4
 
-#define CODA_PARA_BUF_SIZE     (10 * 1024)
 #define CODA_ISRAM_SIZE        (2048 * 2)
 
 #define MIN_W 176
@@ -696,6 +695,26 @@ static int coda_s_fmt_vid_out(struct file *file, void *priv,
        return coda_s_fmt(ctx, &f_cap);
 }
 
+static int coda_reqbufs(struct file *file, void *priv,
+                       struct v4l2_requestbuffers *rb)
+{
+       struct coda_ctx *ctx = fh_to_ctx(priv);
+       int ret;
+
+       ret = v4l2_m2m_reqbufs(file, ctx->fh.m2m_ctx, rb);
+       if (ret)
+               return ret;
+
+       /*
+        * Allow to allocate instance specific per-context buffers, such as
+        * bitstream ringbuffer, slice buffer, work buffer, etc. if needed.
+        */
+       if (rb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && ctx->ops->reqbufs)
+               return ctx->ops->reqbufs(ctx, rb);
+
+       return 0;
+}
+
 static int coda_qbuf(struct file *file, void *priv,
                     struct v4l2_buffer *buf)
 {
@@ -841,7 +860,7 @@ static const struct v4l2_ioctl_ops coda_ioctl_ops = {
        .vidioc_try_fmt_vid_out = coda_try_fmt_vid_out,
        .vidioc_s_fmt_vid_out   = coda_s_fmt_vid_out,
 
-       .vidioc_reqbufs         = v4l2_m2m_ioctl_reqbufs,
+       .vidioc_reqbufs         = coda_reqbufs,
        .vidioc_querybuf        = v4l2_m2m_ioctl_querybuf,
 
        .vidioc_qbuf            = coda_qbuf,
@@ -1173,7 +1192,7 @@ static void coda_buf_queue(struct vb2_buffer *vb)
                mutex_lock(&ctx->bitstream_mutex);
                v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb);
                if (vb2_is_streaming(vb->vb2_queue))
-                       coda_fill_bitstream(ctx);
+                       coda_fill_bitstream(ctx, true);
                mutex_unlock(&ctx->bitstream_mutex);
        } else {
                v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb);
@@ -1215,8 +1234,9 @@ void coda_free_aux_buf(struct coda_dev *dev,
                                  buf->vaddr, buf->paddr);
                buf->vaddr = NULL;
                buf->size = 0;
+               debugfs_remove(buf->dentry);
+               buf->dentry = NULL;
        }
-       debugfs_remove(buf->dentry);
 }
 
 static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
@@ -1232,9 +1252,9 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
                if (q_data_src->fourcc == V4L2_PIX_FMT_H264 ||
                    (q_data_src->fourcc == V4L2_PIX_FMT_JPEG &&
                     ctx->dev->devtype->product == CODA_7541)) {
-                       /* copy the buffers that where queued before streamon */
+                       /* copy the buffers that were queued before streamon */
                        mutex_lock(&ctx->bitstream_mutex);
-                       coda_fill_bitstream(ctx);
+                       coda_fill_bitstream(ctx, false);
                        mutex_unlock(&ctx->bitstream_mutex);
 
                        if (coda_get_bitstream_payload(ctx) < 512) {
@@ -1262,12 +1282,23 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
        if (!(ctx->streamon_out & ctx->streamon_cap))
                return 0;
 
+       q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+       if ((q_data_src->width != q_data_dst->width &&
+            round_up(q_data_src->width, 16) != q_data_dst->width) ||
+           (q_data_src->height != q_data_dst->height &&
+            round_up(q_data_src->height, 16) != q_data_dst->height)) {
+               v4l2_err(v4l2_dev, "can't convert %dx%d to %dx%d\n",
+                        q_data_src->width, q_data_src->height,
+                        q_data_dst->width, q_data_dst->height);
+               ret = -EINVAL;
+               goto err;
+       }
+
        /* Allow BIT decoder device_run with no new buffers queued */
        if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit)
                v4l2_m2m_set_src_buffered(ctx->fh.m2m_ctx, true);
 
        ctx->gopcounter = ctx->params.gop_size - 1;
-       q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
 
        ctx->codec = coda_find_codec(ctx->dev, q_data_src->fourcc,
                                     q_data_dst->fourcc);
@@ -1308,6 +1339,9 @@ static void coda_stop_streaming(struct vb2_queue *q)
        struct coda_ctx *ctx = vb2_get_drv_priv(q);
        struct coda_dev *dev = ctx->dev;
        struct vb2_buffer *buf;
+       bool stop;
+
+       stop = ctx->streamon_out && ctx->streamon_cap;
 
        if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
                v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
@@ -1332,7 +1366,7 @@ static void coda_stop_streaming(struct vb2_queue *q)
                        v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR);
        }
 
-       if (!ctx->streamon_out && !ctx->streamon_cap) {
+       if (stop) {
                struct coda_buffer_meta *meta;
 
                if (ctx->ops->seq_end_work) {
@@ -1457,7 +1491,7 @@ static const struct v4l2_ctrl_ops coda_ctrl_ops = {
 static void coda_encode_ctrls(struct coda_ctx *ctx)
 {
        v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-               V4L2_CID_MPEG_VIDEO_BITRATE, 0, 32767000, 1, 0);
+               V4L2_CID_MPEG_VIDEO_BITRATE, 0, 32767000, 1000, 0);
        v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
                V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1, 60, 1, 16);
        v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
@@ -1541,6 +1575,13 @@ static int coda_queue_init(struct coda_ctx *ctx, struct vb2_queue *vq)
        vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
        vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
        vq->lock = &ctx->dev->dev_mutex;
+       /* One way to indicate end-of-stream for coda is to set the
+        * bytesused == 0. However by default videobuf2 handles bytesused
+        * equal to 0 as a special case and changes its value to the size
+        * of the buffer. Set the allow_zero_bytesused flag, so
+        * that videobuf2 will keep the value of bytesused intact.
+        */
+       vq->allow_zero_bytesused = 1;
 
        return vb2_queue_init(vq);
 }
@@ -1621,6 +1662,11 @@ static int coda_open(struct file *file)
        set_bit(idx, &dev->instance_mask);
 
        name = kasprintf(GFP_KERNEL, "context%d", idx);
+       if (!name) {
+               ret = -ENOMEM;
+               goto err_coda_name_init;
+       }
+
        ctx->debugfs_entry = debugfs_create_dir(name, dev->debugfs_root);
        kfree(name);
 
@@ -1682,28 +1728,6 @@ static int coda_open(struct file *file)
 
        ctx->fh.ctrl_handler = &ctx->ctrls;
 
-       if (ctx->use_bit) {
-               ret = coda_alloc_context_buf(ctx, &ctx->parabuf,
-                                            CODA_PARA_BUF_SIZE, "parabuf");
-               if (ret < 0) {
-                       v4l2_err(&dev->v4l2_dev, "failed to allocate parabuf");
-                       goto err_dma_alloc;
-               }
-       }
-       if (ctx->use_bit && ctx->inst_type == CODA_INST_DECODER) {
-               ctx->bitstream.size = CODA_MAX_FRAME_SIZE;
-               ctx->bitstream.vaddr = dma_alloc_writecombine(
-                               &dev->plat_dev->dev, ctx->bitstream.size,
-                               &ctx->bitstream.paddr, GFP_KERNEL);
-               if (!ctx->bitstream.vaddr) {
-                       v4l2_err(&dev->v4l2_dev,
-                                "failed to allocate bitstream ringbuffer");
-                       ret = -ENOMEM;
-                       goto err_dma_writecombine;
-               }
-       }
-       kfifo_init(&ctx->bitstream_fifo,
-               ctx->bitstream.vaddr, ctx->bitstream.size);
        mutex_init(&ctx->bitstream_mutex);
        mutex_init(&ctx->buffer_mutex);
        INIT_LIST_HEAD(&ctx->buffer_meta_list);
@@ -1717,12 +1741,6 @@ static int coda_open(struct file *file)
 
        return 0;
 
-err_dma_writecombine:
-       if (ctx->dev->devtype->product == CODA_DX6)
-               coda_free_aux_buf(dev, &ctx->workbuf);
-       coda_free_aux_buf(dev, &ctx->parabuf);
-err_dma_alloc:
-       v4l2_ctrl_handler_free(&ctx->ctrls);
 err_ctrls_setup:
        v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
 err_ctx_init:
@@ -1735,6 +1753,7 @@ err_pm_get:
        v4l2_fh_del(&ctx->fh);
        v4l2_fh_exit(&ctx->fh);
        clear_bit(ctx->idx, &dev->instance_mask);
+err_coda_name_init:
 err_coda_max:
        kfree(ctx);
        return ret;
@@ -1764,14 +1783,9 @@ static int coda_release(struct file *file)
        list_del(&ctx->list);
        coda_unlock(ctx);
 
-       if (ctx->bitstream.vaddr) {
-               dma_free_writecombine(&dev->plat_dev->dev, ctx->bitstream.size,
-                       ctx->bitstream.vaddr, ctx->bitstream.paddr);
-       }
        if (ctx->dev->devtype->product == CODA_DX6)
                coda_free_aux_buf(dev, &ctx->workbuf);
 
-       coda_free_aux_buf(dev, &ctx->parabuf);
        v4l2_ctrl_handler_free(&ctx->ctrls);
        clk_disable_unprepare(dev->clk_ahb);
        clk_disable_unprepare(dev->clk_per);
@@ -1901,8 +1915,7 @@ static int coda_register_device(struct coda_dev *dev, int i)
        if (i >= dev->devtype->num_vdevs)
                return -EINVAL;
 
-       snprintf(vfd->name, sizeof(vfd->name), "%s",
-                dev->devtype->vdevs[i]->name);
+       strlcpy(vfd->name, dev->devtype->vdevs[i]->name, sizeof(vfd->name));
        vfd->fops       = &coda_fops;
        vfd->ioctl_ops  = &coda_ioctl_ops;
        vfd->release    = video_device_release_empty,
@@ -1933,10 +1946,8 @@ static void coda_fw_callback(const struct firmware *fw, void *context)
        /* allocate auxiliary per-device code buffer for the BIT processor */
        ret = coda_alloc_aux_buf(dev, &dev->codebuf, fw->size, "codebuf",
                                 dev->debugfs_root);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "failed to allocate code buffer\n");
+       if (ret < 0)
                goto put_pm;
-       }
 
        /* Copy the whole firmware image to the code buffer */
        memcpy(dev->codebuf.vaddr, fw->data, fw->size);
@@ -2174,20 +2185,16 @@ static int coda_probe(struct platform_device *pdev)
                ret = coda_alloc_aux_buf(dev, &dev->workbuf,
                                         dev->devtype->workbuf_size, "workbuf",
                                         dev->debugfs_root);
-               if (ret < 0) {
-                       dev_err(&pdev->dev, "failed to allocate work buffer\n");
+               if (ret < 0)
                        goto err_v4l2_register;
-               }
        }
 
        if (dev->devtype->tempbuf_size) {
                ret = coda_alloc_aux_buf(dev, &dev->tempbuf,
                                         dev->devtype->tempbuf_size, "tempbuf",
                                         dev->debugfs_root);
-               if (ret < 0) {
-                       dev_err(&pdev->dev, "failed to allocate temp buffer\n");
+               if (ret < 0)
                        goto err_v4l2_register;
-               }
        }
 
        dev->iram.size = dev->devtype->iram_size;
index 8fa3e353f9e2d4409ef81a678b20e8b47b81119f..11e734bc2cbd53bcd483c706006fb682ab983bdb 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/swab.h>
 
 #include "coda.h"
+#include "trace.h"
 
 #define SOI_MARKER     0xffd8
 #define EOI_MARKER     0xffd9
index 0c35cd5032ff0d6a0176634f0e3b08af3e840586..6a5c8f6c688e5d621d8d428e4454dc6d67d43191 100644 (file)
@@ -12,6 +12,9 @@
  * (at your option) any later version.
  */
 
+#ifndef __CODA_H__
+#define __CODA_H__
+
 #include <linux/debugfs.h>
 #include <linux/irqreturn.h>
 #include <linux/mutex.h>
@@ -26,7 +29,6 @@
 #include "coda_regs.h"
 
 #define CODA_MAX_FRAMEBUFFERS  8
-#define CODA_MAX_FRAME_SIZE    0x100000
 #define FMO_SLICE_SAVE_BUF_SIZE        (32)
 
 enum {
@@ -178,6 +180,7 @@ struct coda_ctx;
 struct coda_context_ops {
        int (*queue_init)(void *priv, struct vb2_queue *src_vq,
                          struct vb2_queue *dst_vq);
+       int (*reqbufs)(struct coda_ctx *ctx, struct v4l2_requestbuffers *rb);
        int (*start_streaming)(struct coda_ctx *ctx);
        int (*prepare_run)(struct coda_ctx *ctx);
        void (*finish_run)(struct coda_ctx *ctx);
@@ -249,13 +252,6 @@ int coda_alloc_aux_buf(struct coda_dev *dev, struct coda_aux_buf *buf,
                       size_t size, const char *name, struct dentry *parent);
 void coda_free_aux_buf(struct coda_dev *dev, struct coda_aux_buf *buf);
 
-static inline int coda_alloc_context_buf(struct coda_ctx *ctx,
-                                        struct coda_aux_buf *buf, size_t size,
-                                        const char *name)
-{
-       return coda_alloc_aux_buf(ctx->dev, buf, size, name, ctx->debugfs_entry);
-}
-
 int coda_encoder_queue_init(void *priv, struct vb2_queue *src_vq,
                            struct vb2_queue *dst_vq);
 int coda_decoder_queue_init(void *priv, struct vb2_queue *src_vq,
@@ -263,7 +259,7 @@ int coda_decoder_queue_init(void *priv, struct vb2_queue *src_vq,
 
 int coda_hw_reset(struct coda_ctx *ctx);
 
-void coda_fill_bitstream(struct coda_ctx *ctx);
+void coda_fill_bitstream(struct coda_ctx *ctx, bool streaming);
 
 void coda_set_gdi_regs(struct coda_ctx *ctx);
 
@@ -284,7 +280,7 @@ const char *coda_product_name(int product);
 
 int coda_check_firmware(struct coda_dev *dev);
 
-static inline int coda_get_bitstream_payload(struct coda_ctx *ctx)
+static inline unsigned int coda_get_bitstream_payload(struct coda_ctx *ctx)
 {
        return kfifo_len(&ctx->bitstream_fifo);
 }
@@ -301,3 +297,5 @@ extern const struct coda_context_ops coda_bit_encode_ops;
 extern const struct coda_context_ops coda_bit_decode_ops;
 
 irqreturn_t coda_irq_handler(int irq, void *data);
+
+#endif /* __CODA_H__ */
diff --git a/drivers/media/platform/coda/trace.h b/drivers/media/platform/coda/trace.h
new file mode 100644 (file)
index 0000000..d1d06cb
--- /dev/null
@@ -0,0 +1,203 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM coda
+
+#if !defined(__CODA_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ)
+#define __CODA_TRACE_H__
+
+#include <linux/tracepoint.h>
+#include <media/videobuf2-core.h>
+
+#include "coda.h"
+
+#define TRACE_SYSTEM_STRING __stringify(TRACE_SYSTEM)
+
+TRACE_EVENT(coda_bit_run,
+       TP_PROTO(struct coda_ctx *ctx, int cmd),
+
+       TP_ARGS(ctx, cmd),
+
+       TP_STRUCT__entry(
+               __field(int, minor)
+               __field(int, ctx)
+               __field(int, cmd)
+       ),
+
+       TP_fast_assign(
+               __entry->minor = ctx->fh.vdev->minor;
+               __entry->ctx = ctx->idx;
+               __entry->cmd = cmd;
+       ),
+
+       TP_printk("minor = %d, ctx = %d, cmd = %d",
+                 __entry->minor, __entry->ctx, __entry->cmd)
+);
+
+TRACE_EVENT(coda_bit_done,
+       TP_PROTO(struct coda_ctx *ctx),
+
+       TP_ARGS(ctx),
+
+       TP_STRUCT__entry(
+               __field(int, minor)
+               __field(int, ctx)
+       ),
+
+       TP_fast_assign(
+               __entry->minor = ctx->fh.vdev->minor;
+               __entry->ctx = ctx->idx;
+       ),
+
+       TP_printk("minor = %d, ctx = %d", __entry->minor, __entry->ctx)
+);
+
+TRACE_EVENT(coda_enc_pic_run,
+       TP_PROTO(struct coda_ctx *ctx, struct vb2_buffer *buf),
+
+       TP_ARGS(ctx, buf),
+
+       TP_STRUCT__entry(
+               __field(int, minor)
+               __field(int, index)
+               __field(int, ctx)
+       ),
+
+       TP_fast_assign(
+               __entry->minor = ctx->fh.vdev->minor;
+               __entry->index = buf->v4l2_buf.index;
+               __entry->ctx = ctx->idx;
+       ),
+
+       TP_printk("minor = %d, index = %d, ctx = %d",
+                 __entry->minor, __entry->index, __entry->ctx)
+);
+
+TRACE_EVENT(coda_enc_pic_done,
+       TP_PROTO(struct coda_ctx *ctx, struct vb2_buffer *buf),
+
+       TP_ARGS(ctx, buf),
+
+       TP_STRUCT__entry(
+               __field(int, minor)
+               __field(int, index)
+               __field(int, ctx)
+       ),
+
+       TP_fast_assign(
+               __entry->minor = ctx->fh.vdev->minor;
+               __entry->index = buf->v4l2_buf.index;
+               __entry->ctx = ctx->idx;
+       ),
+
+       TP_printk("minor = %d, index = %d, ctx = %d",
+                 __entry->minor, __entry->index, __entry->ctx)
+);
+
+TRACE_EVENT(coda_bit_queue,
+       TP_PROTO(struct coda_ctx *ctx, struct vb2_buffer *buf,
+                struct coda_buffer_meta *meta),
+
+       TP_ARGS(ctx, buf, meta),
+
+       TP_STRUCT__entry(
+               __field(int, minor)
+               __field(int, index)
+               __field(int, start)
+               __field(int, end)
+               __field(int, ctx)
+       ),
+
+       TP_fast_assign(
+               __entry->minor = ctx->fh.vdev->minor;
+               __entry->index = buf->v4l2_buf.index;
+               __entry->start = meta->start;
+               __entry->end = meta->end;
+               __entry->ctx = ctx->idx;
+       ),
+
+       TP_printk("minor = %d, index = %d, start = 0x%x, end = 0x%x, ctx = %d",
+                 __entry->minor, __entry->index, __entry->start, __entry->end,
+                 __entry->ctx)
+);
+
+TRACE_EVENT(coda_dec_pic_run,
+       TP_PROTO(struct coda_ctx *ctx, struct coda_buffer_meta *meta),
+
+       TP_ARGS(ctx, meta),
+
+       TP_STRUCT__entry(
+               __field(int, minor)
+               __field(int, start)
+               __field(int, end)
+               __field(int, ctx)
+       ),
+
+       TP_fast_assign(
+               __entry->minor = ctx->fh.vdev->minor;
+               __entry->start = meta ? meta->start : 0;
+               __entry->end = meta ? meta->end : 0;
+               __entry->ctx = ctx->idx;
+       ),
+
+       TP_printk("minor = %d, start = 0x%x, end = 0x%x, ctx = %d",
+                 __entry->minor, __entry->start, __entry->end, __entry->ctx)
+);
+
+TRACE_EVENT(coda_dec_pic_done,
+       TP_PROTO(struct coda_ctx *ctx, struct coda_buffer_meta *meta),
+
+       TP_ARGS(ctx, meta),
+
+       TP_STRUCT__entry(
+               __field(int, minor)
+               __field(int, start)
+               __field(int, end)
+               __field(int, ctx)
+       ),
+
+       TP_fast_assign(
+               __entry->minor = ctx->fh.vdev->minor;
+               __entry->start = meta->start;
+               __entry->end = meta->end;
+               __entry->ctx = ctx->idx;
+       ),
+
+       TP_printk("minor = %d, start = 0x%x, end = 0x%x, ctx = %d",
+                 __entry->minor, __entry->start, __entry->end, __entry->ctx)
+);
+
+TRACE_EVENT(coda_dec_rot_done,
+       TP_PROTO(struct coda_ctx *ctx, struct coda_buffer_meta *meta,
+                struct vb2_buffer *buf),
+
+       TP_ARGS(ctx, meta, buf),
+
+       TP_STRUCT__entry(
+               __field(int, minor)
+               __field(int, start)
+               __field(int, end)
+               __field(int, index)
+               __field(int, ctx)
+       ),
+
+       TP_fast_assign(
+               __entry->minor = ctx->fh.vdev->minor;
+               __entry->start = meta->start;
+               __entry->end = meta->end;
+               __entry->index = buf->v4l2_buf.index;
+               __entry->ctx = ctx->idx;
+       ),
+
+       TP_printk("minor = %d, start = 0x%x, end = 0x%x, index = %d, ctx = %d",
+                 __entry->minor, __entry->start, __entry->end, __entry->index,
+                 __entry->ctx)
+);
+
+#endif /* __CODA_TRACE_H__ */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE trace
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
index b41bf7e822c82dddc934c8eab78228add0cd8f4a..ccfcf3f528d377f314c3483b04327dcb6ae53031 100644 (file)
@@ -1871,16 +1871,9 @@ static int vpfe_probe(struct platform_device *pdev)
                goto probe_free_ccdc_cfg_mem;
        }
 
-       /* Allocate memory for video device */
-       vfd = video_device_alloc();
-       if (NULL == vfd) {
-               ret = -ENOMEM;
-               v4l2_err(pdev->dev.driver, "Unable to alloc video device\n");
-               goto probe_out_release_irq;
-       }
-
+       vfd = &vpfe_dev->video_dev;
        /* Initialize field of video device */
-       vfd->release            = video_device_release;
+       vfd->release            = video_device_release_empty;
        vfd->fops               = &vpfe_fops;
        vfd->ioctl_ops          = &vpfe_ioctl_ops;
        vfd->tvnorms            = 0;
@@ -1891,14 +1884,12 @@ static int vpfe_probe(struct platform_device *pdev)
                 (VPFE_CAPTURE_VERSION_CODE >> 16) & 0xff,
                 (VPFE_CAPTURE_VERSION_CODE >> 8) & 0xff,
                 (VPFE_CAPTURE_VERSION_CODE) & 0xff);
-       /* Set video_dev to the video device */
-       vpfe_dev->video_dev     = vfd;
 
        ret = v4l2_device_register(&pdev->dev, &vpfe_dev->v4l2_dev);
        if (ret) {
                v4l2_err(pdev->dev.driver,
                        "Unable to register v4l2 device.\n");
-               goto probe_out_video_release;
+               goto probe_out_release_irq;
        }
        v4l2_info(&vpfe_dev->v4l2_dev, "v4l2 device registered\n");
        spin_lock_init(&vpfe_dev->irqlock);
@@ -1914,7 +1905,7 @@ static int vpfe_probe(struct platform_device *pdev)
        v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
                "video_dev=%p\n", &vpfe_dev->video_dev);
        vpfe_dev->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       ret = video_register_device(vpfe_dev->video_dev,
+       ret = video_register_device(&vpfe_dev->video_dev,
                                    VFL_TYPE_GRABBER, -1);
 
        if (ret) {
@@ -1927,7 +1918,7 @@ static int vpfe_probe(struct platform_device *pdev)
        /* set the driver data in platform device */
        platform_set_drvdata(pdev, vpfe_dev);
        /* set driver private data */
-       video_set_drvdata(vpfe_dev->video_dev, vpfe_dev);
+       video_set_drvdata(&vpfe_dev->video_dev, vpfe_dev);
        i2c_adap = i2c_get_adapter(vpfe_cfg->i2c_adapter_id);
        num_subdevs = vpfe_cfg->num_subdevs;
        vpfe_dev->sd = kmalloc(sizeof(struct v4l2_subdev *) * num_subdevs,
@@ -1979,12 +1970,9 @@ static int vpfe_probe(struct platform_device *pdev)
 probe_sd_out:
        kfree(vpfe_dev->sd);
 probe_out_video_unregister:
-       video_unregister_device(vpfe_dev->video_dev);
+       video_unregister_device(&vpfe_dev->video_dev);
 probe_out_v4l2_unregister:
        v4l2_device_unregister(&vpfe_dev->v4l2_dev);
-probe_out_video_release:
-       if (!video_is_registered(vpfe_dev->video_dev))
-               video_device_release(vpfe_dev->video_dev);
 probe_out_release_irq:
        free_irq(vpfe_dev->ccdc_irq0, vpfe_dev);
 probe_free_ccdc_cfg_mem:
@@ -2007,7 +1995,7 @@ static int vpfe_remove(struct platform_device *pdev)
        free_irq(vpfe_dev->ccdc_irq0, vpfe_dev);
        kfree(vpfe_dev->sd);
        v4l2_device_unregister(&vpfe_dev->v4l2_dev);
-       video_unregister_device(vpfe_dev->video_dev);
+       video_unregister_device(&vpfe_dev->video_dev);
        kfree(vpfe_dev);
        kfree(ccdc_cfg);
        return 0;
index fa0a51521772543316a27ec6d98cae3461d7e886..a5f548138b91b4d000b70178b71c94ebda35fcdc 100644 (file)
@@ -712,7 +712,7 @@ static int vpif_set_input(
        ch->vpifparams.iface = chan_cfg->vpif_if;
 
        /* update tvnorms from the sub device input info */
-       ch->video_dev->tvnorms = chan_cfg->inputs[index].input.std;
+       ch->video_dev.tvnorms = chan_cfg->inputs[index].input.std;
        return 0;
 }
 
@@ -1337,7 +1337,7 @@ static int vpif_probe_complete(void)
        struct video_device *vdev;
        struct channel_obj *ch;
        struct vb2_queue *q;
-       int i, j, err, k;
+       int j, err, k;
 
        for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) {
                ch = vpif_obj.dev[j];
@@ -1384,16 +1384,16 @@ static int vpif_probe_complete(void)
                INIT_LIST_HEAD(&common->dma_queue);
 
                /* Initialize the video_device structure */
-               vdev = ch->video_dev;
+               vdev = &ch->video_dev;
                strlcpy(vdev->name, VPIF_DRIVER_NAME, sizeof(vdev->name));
-               vdev->release = video_device_release;
+               vdev->release = video_device_release_empty;
                vdev->fops = &vpif_fops;
                vdev->ioctl_ops = &vpif_ioctl_ops;
                vdev->v4l2_dev = &vpif_obj.v4l2_dev;
                vdev->vfl_dir = VFL_DIR_RX;
                vdev->queue = q;
                vdev->lock = &common->lock;
-               video_set_drvdata(ch->video_dev, ch);
+               video_set_drvdata(&ch->video_dev, ch);
                err = video_register_device(vdev,
                                            VFL_TYPE_GRABBER, (j ? 1 : 0));
                if (err)
@@ -1410,14 +1410,9 @@ probe_out:
                common = &ch->common[k];
                vb2_dma_contig_cleanup_ctx(common->alloc_ctx);
                /* Unregister video device */
-               video_unregister_device(ch->video_dev);
+               video_unregister_device(&ch->video_dev);
        }
        kfree(vpif_obj.sd);
-       for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
-               ch = vpif_obj.dev[i];
-               /* Note: does nothing if ch->video_dev == NULL */
-               video_device_release(ch->video_dev);
-       }
        v4l2_device_unregister(&vpif_obj.v4l2_dev);
 
        return err;
@@ -1438,13 +1433,11 @@ static int vpif_async_complete(struct v4l2_async_notifier *notifier)
 static __init int vpif_probe(struct platform_device *pdev)
 {
        struct vpif_subdev_info *subdevdata;
-       int i, j, err;
-       int res_idx = 0;
        struct i2c_adapter *i2c_adap;
-       struct channel_obj *ch;
-       struct video_device *vfd;
        struct resource *res;
        int subdev_count;
+       int res_idx = 0;
+       int i, err;
 
        vpif_dev = &pdev->dev;
 
@@ -1472,24 +1465,6 @@ static __init int vpif_probe(struct platform_device *pdev)
                res_idx++;
        }
 
-       for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
-               /* Get the pointer to the channel object */
-               ch = vpif_obj.dev[i];
-               /* Allocate memory for video device */
-               vfd = video_device_alloc();
-               if (NULL == vfd) {
-                       for (j = 0; j < i; j++) {
-                               ch = vpif_obj.dev[j];
-                               video_device_release(ch->video_dev);
-                       }
-                       err = -ENOMEM;
-                       goto vpif_unregister;
-               }
-
-               /* Set video_dev to the video device */
-               ch->video_dev = vfd;
-       }
-
        vpif_obj.config = pdev->dev.platform_data;
 
        subdev_count = vpif_obj.config->subdev_count;
@@ -1498,7 +1473,7 @@ static __init int vpif_probe(struct platform_device *pdev)
        if (vpif_obj.sd == NULL) {
                vpif_err("unable to allocate memory for subdevice pointers\n");
                err = -ENOMEM;
-               goto vpif_sd_error;
+               goto vpif_unregister;
        }
 
        if (!vpif_obj.config->asd_sizes) {
@@ -1541,13 +1516,6 @@ static __init int vpif_probe(struct platform_device *pdev)
 probe_subdev_out:
        /* free sub devices memory */
        kfree(vpif_obj.sd);
-
-vpif_sd_error:
-       for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
-               ch = vpif_obj.dev[i];
-               /* Note: does nothing if ch->video_dev == NULL */
-               video_device_release(ch->video_dev);
-       }
 vpif_unregister:
        v4l2_device_unregister(&vpif_obj.v4l2_dev);
 
@@ -1576,7 +1544,7 @@ static int vpif_remove(struct platform_device *device)
                common = &ch->common[VPIF_VIDEO_INDEX];
                vb2_dma_contig_cleanup_ctx(common->alloc_ctx);
                /* Unregister video device */
-               video_unregister_device(ch->video_dev);
+               video_unregister_device(&ch->video_dev);
                kfree(vpif_obj.dev[i]);
        }
        return 0;
index f65d28d38e66de6be2294ac45df3724de57799b7..8b8a663f6b2213ac18e1c0b15d236a960c07780a 100644 (file)
@@ -92,7 +92,7 @@ struct common_obj {
 
 struct channel_obj {
        /* Identifies video device for this channel */
-       struct video_device *video_dev;
+       struct video_device video_dev;
        /* Indicates id of the field which is being displayed */
        u32 field_id;
        /* flag to indicate whether decoder is initialized */
index 839c24de1fd8f7a1d64fa97f9f9c73152eb1cee1..682e5d578bf7b843f73317b7a7c3a34bdf0fe5bd 100644 (file)
@@ -829,7 +829,7 @@ static int vpif_set_output(struct vpif_display_config *vpif_cfg,
        ch->sd = sd;
        if (chan_cfg->outputs != NULL)
                /* update tvnorms from the sub device output info */
-               ch->video_dev->tvnorms = chan_cfg->outputs[index].output.std;
+               ch->video_dev.tvnorms = chan_cfg->outputs[index].output.std;
        return 0;
 }
 
@@ -1204,16 +1204,16 @@ static int vpif_probe_complete(void)
                         ch, &ch->video_dev);
 
                /* Initialize the video_device structure */
-               vdev = ch->video_dev;
+               vdev = &ch->video_dev;
                strlcpy(vdev->name, VPIF_DRIVER_NAME, sizeof(vdev->name));
-               vdev->release = video_device_release;
+               vdev->release = video_device_release_empty;
                vdev->fops = &vpif_fops;
                vdev->ioctl_ops = &vpif_ioctl_ops;
                vdev->v4l2_dev = &vpif_obj.v4l2_dev;
                vdev->vfl_dir = VFL_DIR_TX;
                vdev->queue = q;
                vdev->lock = &common->lock;
-               video_set_drvdata(ch->video_dev, ch);
+               video_set_drvdata(&ch->video_dev, ch);
                err = video_register_device(vdev, VFL_TYPE_GRABBER,
                                            (j ? 3 : 2));
                if (err < 0)
@@ -1227,9 +1227,7 @@ probe_out:
                ch = vpif_obj.dev[k];
                common = &ch->common[k];
                vb2_dma_contig_cleanup_ctx(common->alloc_ctx);
-               video_unregister_device(ch->video_dev);
-               video_device_release(ch->video_dev);
-               ch->video_dev = NULL;
+               video_unregister_device(&ch->video_dev);
        }
        return err;
 }
@@ -1246,13 +1244,11 @@ static int vpif_async_complete(struct v4l2_async_notifier *notifier)
 static __init int vpif_probe(struct platform_device *pdev)
 {
        struct vpif_subdev_info *subdevdata;
-       int i, j = 0, err = 0;
-       int res_idx = 0;
        struct i2c_adapter *i2c_adap;
-       struct channel_obj *ch;
-       struct video_device *vfd;
        struct resource *res;
        int subdev_count;
+       int res_idx = 0;
+       int i, err;
 
        vpif_dev = &pdev->dev;
        err = initialize_vpif();
@@ -1281,25 +1277,6 @@ static __init int vpif_probe(struct platform_device *pdev)
                res_idx++;
        }
 
-       for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) {
-               /* Get the pointer to the channel object */
-               ch = vpif_obj.dev[i];
-
-               /* Allocate memory for video device */
-               vfd = video_device_alloc();
-               if (vfd == NULL) {
-                       for (j = 0; j < i; j++) {
-                               ch = vpif_obj.dev[j];
-                               video_device_release(ch->video_dev);
-                       }
-                       err = -ENOMEM;
-                       goto vpif_unregister;
-               }
-
-               /* Set video_dev to the video device */
-               ch->video_dev = vfd;
-       }
-
        vpif_obj.config = pdev->dev.platform_data;
        subdev_count = vpif_obj.config->subdev_count;
        subdevdata = vpif_obj.config->subdevinfo;
@@ -1308,7 +1285,7 @@ static __init int vpif_probe(struct platform_device *pdev)
        if (vpif_obj.sd == NULL) {
                vpif_err("unable to allocate memory for subdevice pointers\n");
                err = -ENOMEM;
-               goto vpif_sd_error;
+               goto vpif_unregister;
        }
 
        if (!vpif_obj.config->asd_sizes) {
@@ -1348,12 +1325,6 @@ static __init int vpif_probe(struct platform_device *pdev)
 
 probe_subdev_out:
        kfree(vpif_obj.sd);
-vpif_sd_error:
-       for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) {
-               ch = vpif_obj.dev[i];
-               /* Note: does nothing if ch->video_dev == NULL */
-               video_device_release(ch->video_dev);
-       }
 vpif_unregister:
        v4l2_device_unregister(&vpif_obj.v4l2_dev);
 
@@ -1379,9 +1350,7 @@ static int vpif_remove(struct platform_device *device)
                common = &ch->common[VPIF_VIDEO_INDEX];
                vb2_dma_contig_cleanup_ctx(common->alloc_ctx);
                /* Unregister video device */
-               video_unregister_device(ch->video_dev);
-
-               ch->video_dev = NULL;
+               video_unregister_device(&ch->video_dev);
                kfree(vpif_obj.dev[i]);
        }
 
index 7b21a76076749177882bde810fae2dae55d73d5b..849e0e385f182f0c1324e19c1d44b15b2024327d 100644 (file)
@@ -100,7 +100,7 @@ struct common_obj {
 
 struct channel_obj {
        /* V4l2 specific parameters */
-       struct video_device *video_dev; /* Identifies video device for
+       struct video_device video_dev;  /* Identifies video device for
                                         * this channel */
        u32 field_id;                   /* Indicates id of the field
                                         * which is being displayed */
index 8a2fd8c33d421625c0d02e9d592b94ed7c6d63cd..cfebf292e15a9290b6130b9881760180163f7e0f 100644 (file)
@@ -1482,7 +1482,7 @@ void fimc_sensor_notify(struct v4l2_subdev *sd, unsigned int notification,
 }
 
 static int fimc_subdev_enum_mbus_code(struct v4l2_subdev *sd,
-                                     struct v4l2_subdev_fh *fh,
+                                     struct v4l2_subdev_pad_config *cfg,
                                      struct v4l2_subdev_mbus_code_enum *code)
 {
        struct fimc_fmt *fmt;
@@ -1495,7 +1495,7 @@ static int fimc_subdev_enum_mbus_code(struct v4l2_subdev *sd,
 }
 
 static int fimc_subdev_get_fmt(struct v4l2_subdev *sd,
-                              struct v4l2_subdev_fh *fh,
+                              struct v4l2_subdev_pad_config *cfg,
                               struct v4l2_subdev_format *fmt)
 {
        struct fimc_dev *fimc = v4l2_get_subdevdata(sd);
@@ -1504,7 +1504,7 @@ static int fimc_subdev_get_fmt(struct v4l2_subdev *sd,
        struct v4l2_mbus_framefmt *mf;
 
        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-               mf = v4l2_subdev_get_try_format(fh, fmt->pad);
+               mf = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
                fmt->format = *mf;
                return 0;
        }
@@ -1536,7 +1536,7 @@ static int fimc_subdev_get_fmt(struct v4l2_subdev *sd,
 }
 
 static int fimc_subdev_set_fmt(struct v4l2_subdev *sd,
-                              struct v4l2_subdev_fh *fh,
+                              struct v4l2_subdev_pad_config *cfg,
                               struct v4l2_subdev_format *fmt)
 {
        struct fimc_dev *fimc = v4l2_get_subdevdata(sd);
@@ -1559,7 +1559,7 @@ static int fimc_subdev_set_fmt(struct v4l2_subdev *sd,
        mf->colorspace = V4L2_COLORSPACE_JPEG;
 
        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-               mf = v4l2_subdev_get_try_format(fh, fmt->pad);
+               mf = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
                *mf = fmt->format;
                return 0;
        }
@@ -1602,7 +1602,7 @@ static int fimc_subdev_set_fmt(struct v4l2_subdev *sd,
 }
 
 static int fimc_subdev_get_selection(struct v4l2_subdev *sd,
-                                    struct v4l2_subdev_fh *fh,
+                                    struct v4l2_subdev_pad_config *cfg,
                                     struct v4l2_subdev_selection *sel)
 {
        struct fimc_dev *fimc = v4l2_get_subdevdata(sd);
@@ -1628,10 +1628,10 @@ static int fimc_subdev_get_selection(struct v4l2_subdev *sd,
                return 0;
 
        case V4L2_SEL_TGT_CROP:
-               try_sel = v4l2_subdev_get_try_crop(fh, sel->pad);
+               try_sel = v4l2_subdev_get_try_crop(sd, cfg, sel->pad);
                break;
        case V4L2_SEL_TGT_COMPOSE:
-               try_sel = v4l2_subdev_get_try_compose(fh, sel->pad);
+               try_sel = v4l2_subdev_get_try_compose(sd, cfg, sel->pad);
                f = &ctx->d_frame;
                break;
        default:
@@ -1657,7 +1657,7 @@ static int fimc_subdev_get_selection(struct v4l2_subdev *sd,
 }
 
 static int fimc_subdev_set_selection(struct v4l2_subdev *sd,
-                                    struct v4l2_subdev_fh *fh,
+                                    struct v4l2_subdev_pad_config *cfg,
                                     struct v4l2_subdev_selection *sel)
 {
        struct fimc_dev *fimc = v4l2_get_subdevdata(sd);
@@ -1675,10 +1675,10 @@ static int fimc_subdev_set_selection(struct v4l2_subdev *sd,
 
        switch (sel->target) {
        case V4L2_SEL_TGT_CROP:
-               try_sel = v4l2_subdev_get_try_crop(fh, sel->pad);
+               try_sel = v4l2_subdev_get_try_crop(sd, cfg, sel->pad);
                break;
        case V4L2_SEL_TGT_COMPOSE:
-               try_sel = v4l2_subdev_get_try_compose(fh, sel->pad);
+               try_sel = v4l2_subdev_get_try_compose(sd, cfg, sel->pad);
                f = &ctx->d_frame;
                break;
        default:
index 60c74491554982a7fd8bd62316674ad815fb6bcd..5d78f5716f3b8d2f77e27fde9192e2601c437867 100644 (file)
@@ -112,7 +112,7 @@ static const struct media_entity_operations fimc_is_subdev_media_ops = {
 };
 
 static int fimc_is_subdev_enum_mbus_code(struct v4l2_subdev *sd,
-                               struct v4l2_subdev_fh *fh,
+                               struct v4l2_subdev_pad_config *cfg,
                                struct v4l2_subdev_mbus_code_enum *code)
 {
        const struct fimc_fmt *fmt;
@@ -125,14 +125,14 @@ static int fimc_is_subdev_enum_mbus_code(struct v4l2_subdev *sd,
 }
 
 static int fimc_isp_subdev_get_fmt(struct v4l2_subdev *sd,
-                                  struct v4l2_subdev_fh *fh,
+                                  struct v4l2_subdev_pad_config *cfg,
                                   struct v4l2_subdev_format *fmt)
 {
        struct fimc_isp *isp = v4l2_get_subdevdata(sd);
        struct v4l2_mbus_framefmt *mf = &fmt->format;
 
        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-               *mf = *v4l2_subdev_get_try_format(fh, fmt->pad);
+               *mf = *v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
                return 0;
        }
 
@@ -162,7 +162,7 @@ static int fimc_isp_subdev_get_fmt(struct v4l2_subdev *sd,
 }
 
 static void __isp_subdev_try_format(struct fimc_isp *isp,
-                                   struct v4l2_subdev_fh *fh,
+                                   struct v4l2_subdev_pad_config *cfg,
                                    struct v4l2_subdev_format *fmt)
 {
        struct v4l2_mbus_framefmt *mf = &fmt->format;
@@ -178,7 +178,7 @@ static void __isp_subdev_try_format(struct fimc_isp *isp,
                mf->code = MEDIA_BUS_FMT_SGRBG10_1X10;
        } else {
                if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
-                       format = v4l2_subdev_get_try_format(fh,
+                       format = v4l2_subdev_get_try_format(&isp->subdev, cfg,
                                                FIMC_ISP_SD_PAD_SINK);
                else
                        format = &isp->sink_fmt;
@@ -197,7 +197,7 @@ static void __isp_subdev_try_format(struct fimc_isp *isp,
 }
 
 static int fimc_isp_subdev_set_fmt(struct v4l2_subdev *sd,
-                                  struct v4l2_subdev_fh *fh,
+                                  struct v4l2_subdev_pad_config *cfg,
                                   struct v4l2_subdev_format *fmt)
 {
        struct fimc_isp *isp = v4l2_get_subdevdata(sd);
@@ -209,10 +209,10 @@ static int fimc_isp_subdev_set_fmt(struct v4l2_subdev *sd,
                 __func__, fmt->pad, mf->code, mf->width, mf->height);
 
        mutex_lock(&isp->subdev_lock);
-       __isp_subdev_try_format(isp, fh, fmt);
+       __isp_subdev_try_format(isp, cfg, fmt);
 
        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-               mf = v4l2_subdev_get_try_format(fh, fmt->pad);
+               mf = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
                *mf = fmt->format;
 
                /* Propagate format to the source pads */
@@ -223,8 +223,8 @@ static int fimc_isp_subdev_set_fmt(struct v4l2_subdev *sd,
                        for (pad = FIMC_ISP_SD_PAD_SRC_FIFO;
                                        pad < FIMC_ISP_SD_PADS_NUM; pad++) {
                                format.pad = pad;
-                               __isp_subdev_try_format(isp, fh, &format);
-                               mf = v4l2_subdev_get_try_format(fh, pad);
+                               __isp_subdev_try_format(isp, cfg, &format);
+                               mf = v4l2_subdev_get_try_format(sd, cfg, pad);
                                *mf = format.format;
                        }
                }
@@ -236,7 +236,7 @@ static int fimc_isp_subdev_set_fmt(struct v4l2_subdev *sd,
                                isp->sink_fmt = *mf;
 
                                format.pad = FIMC_ISP_SD_PAD_SRC_DMA;
-                               __isp_subdev_try_format(isp, fh, &format);
+                               __isp_subdev_try_format(isp, cfg, &format);
 
                                isp->src_fmt = format.format;
                                __is_set_frame_size(is, &isp->src_fmt);
@@ -369,7 +369,7 @@ static int fimc_isp_subdev_open(struct v4l2_subdev *sd,
        struct v4l2_mbus_framefmt fmt;
        struct v4l2_mbus_framefmt *format;
 
-       format = v4l2_subdev_get_try_format(fh, FIMC_ISP_SD_PAD_SINK);
+       format = v4l2_subdev_get_try_format(sd, fh->pad, FIMC_ISP_SD_PAD_SINK);
 
        fmt.colorspace = V4L2_COLORSPACE_SRGB;
        fmt.code = fimc_isp_formats[0].mbus_code;
@@ -378,12 +378,12 @@ static int fimc_isp_subdev_open(struct v4l2_subdev *sd,
        fmt.field = V4L2_FIELD_NONE;
        *format = fmt;
 
-       format = v4l2_subdev_get_try_format(fh, FIMC_ISP_SD_PAD_SRC_FIFO);
+       format = v4l2_subdev_get_try_format(sd, fh->pad, FIMC_ISP_SD_PAD_SRC_FIFO);
        fmt.width = DEFAULT_PREVIEW_STILL_WIDTH;
        fmt.height = DEFAULT_PREVIEW_STILL_HEIGHT;
        *format = fmt;
 
-       format = v4l2_subdev_get_try_format(fh, FIMC_ISP_SD_PAD_SRC_DMA);
+       format = v4l2_subdev_get_try_format(sd, fh->pad, FIMC_ISP_SD_PAD_SRC_DMA);
        *format = fmt;
 
        return 0;
index 2510f189e242dacef456cbffc7f8541c6e4862fc..ca6261a86a5f39a3c68424920f0f2979723d300a 100644 (file)
@@ -568,7 +568,7 @@ static const struct v4l2_file_operations fimc_lite_fops = {
  */
 
 static const struct fimc_fmt *fimc_lite_subdev_try_fmt(struct fimc_lite *fimc,
-                                       struct v4l2_subdev_fh *fh,
+                                       struct v4l2_subdev_pad_config *cfg,
                                        struct v4l2_subdev_format *format)
 {
        struct flite_drvdata *dd = fimc->dd;
@@ -592,13 +592,13 @@ static const struct fimc_fmt *fimc_lite_subdev_try_fmt(struct fimc_lite *fimc,
                struct v4l2_rect *rect;
 
                if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
-                       sink_fmt = v4l2_subdev_get_try_format(fh,
+                       sink_fmt = v4l2_subdev_get_try_format(&fimc->subdev, cfg,
                                                FLITE_SD_PAD_SINK);
 
                        mf->code = sink_fmt->code;
                        mf->colorspace = sink_fmt->colorspace;
 
-                       rect = v4l2_subdev_get_try_crop(fh,
+                       rect = v4l2_subdev_get_try_crop(&fimc->subdev, cfg,
                                                FLITE_SD_PAD_SINK);
                } else {
                        mf->code = sink->fmt->mbus_code;
@@ -1047,7 +1047,7 @@ static const struct media_entity_operations fimc_lite_subdev_media_ops = {
 };
 
 static int fimc_lite_subdev_enum_mbus_code(struct v4l2_subdev *sd,
-                                          struct v4l2_subdev_fh *fh,
+                                          struct v4l2_subdev_pad_config *cfg,
                                           struct v4l2_subdev_mbus_code_enum *code)
 {
        const struct fimc_fmt *fmt;
@@ -1060,16 +1060,17 @@ static int fimc_lite_subdev_enum_mbus_code(struct v4l2_subdev *sd,
 }
 
 static struct v4l2_mbus_framefmt *__fimc_lite_subdev_get_try_fmt(
-                       struct v4l2_subdev_fh *fh, unsigned int pad)
+               struct v4l2_subdev *sd,
+               struct v4l2_subdev_pad_config *cfg, unsigned int pad)
 {
        if (pad != FLITE_SD_PAD_SINK)
                pad = FLITE_SD_PAD_SOURCE_DMA;
 
-       return v4l2_subdev_get_try_format(fh, pad);
+       return v4l2_subdev_get_try_format(sd, cfg, pad);
 }
 
 static int fimc_lite_subdev_get_fmt(struct v4l2_subdev *sd,
-                                   struct v4l2_subdev_fh *fh,
+                                   struct v4l2_subdev_pad_config *cfg,
                                    struct v4l2_subdev_format *fmt)
 {
        struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
@@ -1077,7 +1078,7 @@ static int fimc_lite_subdev_get_fmt(struct v4l2_subdev *sd,
        struct flite_frame *f = &fimc->inp_frame;
 
        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-               mf = __fimc_lite_subdev_get_try_fmt(fh, fmt->pad);
+               mf = __fimc_lite_subdev_get_try_fmt(sd, cfg, fmt->pad);
                fmt->format = *mf;
                return 0;
        }
@@ -1100,7 +1101,7 @@ static int fimc_lite_subdev_get_fmt(struct v4l2_subdev *sd,
 }
 
 static int fimc_lite_subdev_set_fmt(struct v4l2_subdev *sd,
-                                   struct v4l2_subdev_fh *fh,
+                                   struct v4l2_subdev_pad_config *cfg,
                                    struct v4l2_subdev_format *fmt)
 {
        struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
@@ -1122,17 +1123,17 @@ static int fimc_lite_subdev_set_fmt(struct v4l2_subdev *sd,
                return -EBUSY;
        }
 
-       ffmt = fimc_lite_subdev_try_fmt(fimc, fh, fmt);
+       ffmt = fimc_lite_subdev_try_fmt(fimc, cfg, fmt);
 
        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
                struct v4l2_mbus_framefmt *src_fmt;
 
-               mf = __fimc_lite_subdev_get_try_fmt(fh, fmt->pad);
+               mf = __fimc_lite_subdev_get_try_fmt(sd, cfg, fmt->pad);
                *mf = fmt->format;
 
                if (fmt->pad == FLITE_SD_PAD_SINK) {
                        unsigned int pad = FLITE_SD_PAD_SOURCE_DMA;
-                       src_fmt = __fimc_lite_subdev_get_try_fmt(fh, pad);
+                       src_fmt = __fimc_lite_subdev_get_try_fmt(sd, cfg, pad);
                        *src_fmt = *mf;
                }
 
@@ -1160,7 +1161,7 @@ static int fimc_lite_subdev_set_fmt(struct v4l2_subdev *sd,
 }
 
 static int fimc_lite_subdev_get_selection(struct v4l2_subdev *sd,
-                                         struct v4l2_subdev_fh *fh,
+                                         struct v4l2_subdev_pad_config *cfg,
                                          struct v4l2_subdev_selection *sel)
 {
        struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
@@ -1172,7 +1173,7 @@ static int fimc_lite_subdev_get_selection(struct v4l2_subdev *sd,
                return -EINVAL;
 
        if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
-               sel->r = *v4l2_subdev_get_try_crop(fh, sel->pad);
+               sel->r = *v4l2_subdev_get_try_crop(sd, cfg, sel->pad);
                return 0;
        }
 
@@ -1195,7 +1196,7 @@ static int fimc_lite_subdev_get_selection(struct v4l2_subdev *sd,
 }
 
 static int fimc_lite_subdev_set_selection(struct v4l2_subdev *sd,
-                                         struct v4l2_subdev_fh *fh,
+                                         struct v4l2_subdev_pad_config *cfg,
                                          struct v4l2_subdev_selection *sel)
 {
        struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
@@ -1209,7 +1210,7 @@ static int fimc_lite_subdev_set_selection(struct v4l2_subdev *sd,
        fimc_lite_try_crop(fimc, &sel->r);
 
        if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
-               *v4l2_subdev_get_try_crop(fh, sel->pad) = sel->r;
+               *v4l2_subdev_get_try_crop(sd, cfg, sel->pad) = sel->r;
        } else {
                unsigned long flags;
                spin_lock_irqsave(&fimc->slock, flags);
index 2504aa89a6f44436e6b85f3cef17491c5170467e..d74e1bec3d867b608c4c6a70039c484b833f6599 100644 (file)
@@ -540,7 +540,7 @@ unlock:
 }
 
 static int s5pcsis_enum_mbus_code(struct v4l2_subdev *sd,
-                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_pad_config *cfg,
                                  struct v4l2_subdev_mbus_code_enum *code)
 {
        if (code->index >= ARRAY_SIZE(s5pcsis_formats))
@@ -568,23 +568,23 @@ static struct csis_pix_format const *s5pcsis_try_format(
 }
 
 static struct v4l2_mbus_framefmt *__s5pcsis_get_format(
-               struct csis_state *state, struct v4l2_subdev_fh *fh,
+               struct csis_state *state, struct v4l2_subdev_pad_config *cfg,
                enum v4l2_subdev_format_whence which)
 {
        if (which == V4L2_SUBDEV_FORMAT_TRY)
-               return fh ? v4l2_subdev_get_try_format(fh, 0) : NULL;
+               return cfg ? v4l2_subdev_get_try_format(&state->sd, cfg, 0) : NULL;
 
        return &state->format;
 }
 
-static int s5pcsis_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int s5pcsis_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                           struct v4l2_subdev_format *fmt)
 {
        struct csis_state *state = sd_to_csis_state(sd);
        struct csis_pix_format const *csis_fmt;
        struct v4l2_mbus_framefmt *mf;
 
-       mf = __s5pcsis_get_format(state, fh, fmt->which);
+       mf = __s5pcsis_get_format(state, cfg, fmt->which);
 
        if (fmt->pad == CSIS_PAD_SOURCE) {
                if (mf) {
@@ -605,13 +605,13 @@ static int s5pcsis_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        return 0;
 }
 
-static int s5pcsis_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int s5pcsis_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                           struct v4l2_subdev_format *fmt)
 {
        struct csis_state *state = sd_to_csis_state(sd);
        struct v4l2_mbus_framefmt *mf;
 
-       mf = __s5pcsis_get_format(state, fh, fmt->which);
+       mf = __s5pcsis_get_format(state, cfg, fmt->which);
        if (!mf)
                return -EINVAL;
 
@@ -651,7 +651,7 @@ static int s5pcsis_log_status(struct v4l2_subdev *sd)
 
 static int s5pcsis_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 {
-       struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0);
+       struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(sd, fh->pad, 0);
 
        format->colorspace = V4L2_COLORSPACE_JPEG;
        format->code = s5pcsis_formats[0].code;
index b70c1aecca37bce55018a9139ec64bb5e22ab1fa..92d954973ccf50be453a1bba217c893cd5452358 100644 (file)
@@ -127,7 +127,7 @@ static struct deinterlace_fmt *find_format(struct v4l2_format *f)
 
 struct deinterlace_dev {
        struct v4l2_device      v4l2_dev;
-       struct video_device     *vfd;
+       struct video_device     vfd;
 
        atomic_t                busy;
        struct mutex            dev_mutex;
@@ -983,7 +983,7 @@ static struct video_device deinterlace_videodev = {
        .fops           = &deinterlace_fops,
        .ioctl_ops      = &deinterlace_ioctl_ops,
        .minor          = -1,
-       .release        = video_device_release,
+       .release        = video_device_release_empty,
        .vfl_dir        = VFL_DIR_M2M,
 };
 
@@ -1026,13 +1026,7 @@ static int deinterlace_probe(struct platform_device *pdev)
        atomic_set(&pcdev->busy, 0);
        mutex_init(&pcdev->dev_mutex);
 
-       vfd = video_device_alloc();
-       if (!vfd) {
-               v4l2_err(&pcdev->v4l2_dev, "Failed to allocate video device\n");
-               ret = -ENOMEM;
-               goto unreg_dev;
-       }
-
+       vfd = &pcdev->vfd;
        *vfd = deinterlace_videodev;
        vfd->lock = &pcdev->dev_mutex;
        vfd->v4l2_dev = &pcdev->v4l2_dev;
@@ -1040,12 +1034,11 @@ static int deinterlace_probe(struct platform_device *pdev)
        ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
        if (ret) {
                v4l2_err(&pcdev->v4l2_dev, "Failed to register video device\n");
-               goto rel_vdev;
+               goto unreg_dev;
        }
 
        video_set_drvdata(vfd, pcdev);
        snprintf(vfd->name, sizeof(vfd->name), "%s", deinterlace_videodev.name);
-       pcdev->vfd = vfd;
        v4l2_info(&pcdev->v4l2_dev, MEM2MEM_TEST_MODULE_NAME
                        " Device registered as /dev/video%d\n", vfd->num);
 
@@ -1069,11 +1062,9 @@ static int deinterlace_probe(struct platform_device *pdev)
 
        v4l2_m2m_release(pcdev->m2m_dev);
 err_m2m:
-       video_unregister_device(pcdev->vfd);
+       video_unregister_device(&pcdev->vfd);
 err_ctx:
        vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
-rel_vdev:
-       video_device_release(vfd);
 unreg_dev:
        v4l2_device_unregister(&pcdev->v4l2_dev);
 rel_dma:
@@ -1088,7 +1079,7 @@ static int deinterlace_remove(struct platform_device *pdev)
 
        v4l2_info(&pcdev->v4l2_dev, "Removing " MEM2MEM_TEST_MODULE_NAME);
        v4l2_m2m_release(pcdev->m2m_dev);
-       video_unregister_device(pcdev->vfd);
+       video_unregister_device(&pcdev->vfd);
        v4l2_device_unregister(&pcdev->v4l2_dev);
        vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
        dma_release_channel(pcdev->dma_chan);
index dd5b1415f97444103835c677fc1cde879876fe8c..110fd70c73269dbbf5cdbdfb6461fe26eb511b1e 100644 (file)
@@ -116,8 +116,8 @@ static struct mcam_format_struct {
                .planar         = false,
        },
        {
-               .desc           = "UYVY 4:2:2",
-               .pixelformat    = V4L2_PIX_FMT_UYVY,
+               .desc           = "YVYU 4:2:2",
+               .pixelformat    = V4L2_PIX_FMT_YVYU,
                .mbus_code      = MEDIA_BUS_FMT_YUYV8_2X8,
                .bpp            = 2,
                .planar         = false,
@@ -748,7 +748,7 @@ static void mcam_ctlr_image(struct mcam_camera *cam)
 
        switch (fmt->pixelformat) {
        case V4L2_PIX_FMT_YUYV:
-       case V4L2_PIX_FMT_UYVY:
+       case V4L2_PIX_FMT_YVYU:
                widthy = fmt->width * 2;
                widthuv = 0;
                break;
@@ -784,15 +784,15 @@ static void mcam_ctlr_image(struct mcam_camera *cam)
        case V4L2_PIX_FMT_YUV420:
        case V4L2_PIX_FMT_YVU420:
                mcam_reg_write_mask(cam, REG_CTRL0,
-                       C0_DF_YUV | C0_YUV_420PL | C0_YUVE_YVYU, C0_DF_MASK);
+                       C0_DF_YUV | C0_YUV_420PL | C0_YUVE_VYUY, C0_DF_MASK);
                break;
        case V4L2_PIX_FMT_YUYV:
                mcam_reg_write_mask(cam, REG_CTRL0,
-                       C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_UYVY, C0_DF_MASK);
+                       C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_NOSWAP, C0_DF_MASK);
                break;
-       case V4L2_PIX_FMT_UYVY:
+       case V4L2_PIX_FMT_YVYU:
                mcam_reg_write_mask(cam, REG_CTRL0,
-                       C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_YUYV, C0_DF_MASK);
+                       C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_SWAP24, C0_DF_MASK);
                break;
        case V4L2_PIX_FMT_JPEG:
                mcam_reg_write_mask(cam, REG_CTRL0,
@@ -1568,24 +1568,64 @@ static int mcam_vidioc_enum_framesizes(struct file *filp, void *priv,
                struct v4l2_frmsizeenum *sizes)
 {
        struct mcam_camera *cam = priv;
+       struct mcam_format_struct *f;
+       struct v4l2_subdev_frame_size_enum fse = {
+               .index = sizes->index,
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        int ret;
 
+       f = mcam_find_format(sizes->pixel_format);
+       if (f->pixelformat != sizes->pixel_format)
+               return -EINVAL;
+       fse.code = f->mbus_code;
        mutex_lock(&cam->s_mutex);
-       ret = sensor_call(cam, video, enum_framesizes, sizes);
+       ret = sensor_call(cam, pad, enum_frame_size, NULL, &fse);
        mutex_unlock(&cam->s_mutex);
-       return ret;
+       if (ret)
+               return ret;
+       if (fse.min_width == fse.max_width &&
+           fse.min_height == fse.max_height) {
+               sizes->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+               sizes->discrete.width = fse.min_width;
+               sizes->discrete.height = fse.min_height;
+               return 0;
+       }
+       sizes->type = V4L2_FRMSIZE_TYPE_CONTINUOUS;
+       sizes->stepwise.min_width = fse.min_width;
+       sizes->stepwise.max_width = fse.max_width;
+       sizes->stepwise.min_height = fse.min_height;
+       sizes->stepwise.max_height = fse.max_height;
+       sizes->stepwise.step_width = 1;
+       sizes->stepwise.step_height = 1;
+       return 0;
 }
 
 static int mcam_vidioc_enum_frameintervals(struct file *filp, void *priv,
                struct v4l2_frmivalenum *interval)
 {
        struct mcam_camera *cam = priv;
+       struct mcam_format_struct *f;
+       struct v4l2_subdev_frame_interval_enum fie = {
+               .index = interval->index,
+               .width = interval->width,
+               .height = interval->height,
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        int ret;
 
+       f = mcam_find_format(interval->pixel_format);
+       if (f->pixelformat != interval->pixel_format)
+               return -EINVAL;
+       fie.code = f->mbus_code;
        mutex_lock(&cam->s_mutex);
-       ret = sensor_call(cam, video, enum_frameintervals, interval);
+       ret = sensor_call(cam, pad, enum_frame_interval, NULL, &fie);
        mutex_unlock(&cam->s_mutex);
-       return ret;
+       if (ret)
+               return ret;
+       interval->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+       interval->discrete = fie.interval;
+       return 0;
 }
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
index aa0c6eac254a4cd5813dd660d279334202e9e747..7ffdf4dbaf8cc2de76dee0bdd6044d53bcecc11b 100644 (file)
@@ -330,10 +330,10 @@ int mccic_resume(struct mcam_camera *cam);
 #define          C0_YUVE_YVYU    0x00010000    /* Y1CrY0Cb             */
 #define          C0_YUVE_VYUY    0x00020000    /* CrY1CbY0             */
 #define          C0_YUVE_UYVY    0x00030000    /* CbY1CrY0             */
-#define          C0_YUVE_XYUV    0x00000000    /* 420: .YUV            */
-#define          C0_YUVE_XYVU    0x00010000    /* 420: .YVU            */
-#define          C0_YUVE_XUVY    0x00020000    /* 420: .UVY            */
-#define          C0_YUVE_XVUY    0x00030000    /* 420: .VUY            */
+#define          C0_YUVE_NOSWAP  0x00000000    /* no bytes swapping    */
+#define          C0_YUVE_SWAP13  0x00010000    /* swap byte 1 and 3    */
+#define          C0_YUVE_SWAP24  0x00020000    /* swap byte 2 and 4    */
+#define          C0_YUVE_SWAP1324 0x00030000   /* swap bytes 1&3 and 2&4 */
 /* Bayer bits 18,19 if needed */
 #define          C0_EOF_VSYNC    0x00400000    /* Generate EOF by VSYNC */
 #define          C0_VEDGE_CTRL   0x00800000    /* Detect falling edge of VSYNC */
index ba2d8f973d580aca85e4195dd9d9eb68cf86568e..17b189a81ec597ccbc2d470247155c27bcd00848 100644 (file)
@@ -1978,7 +1978,7 @@ static int __init omap_vout_setup_video_bufs(struct platform_device *pdev,
        vout->cropped_offset = 0;
 
        if (ovid->rotation_type == VOUT_ROT_VRFB) {
-               int static_vrfb_allocation = (vid_num == 0) ?
+               bool static_vrfb_allocation = (vid_num == 0) ?
                        vid1_static_vrfb_alloc : vid2_static_vrfb_alloc;
                ret = omap_vout_setup_vrfb_bufs(pdev, vid_num,
                                static_vrfb_allocation);
index aa39306afc73ac84439655314460acfa3202b43d..c6e252760c621d52a6f96ded885cb1a292735539 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "omap_voutdef.h"
 #include "omap_voutlib.h"
+#include "omap_vout_vrfb.h"
 
 #define OMAP_DMA_NO_DEVICE     0
 
index 4c2314839b487768a9257d61ac3e9a30a46da2c6..c976975024df29a19b66794ec5cf28b6a89c4dc3 100644 (file)
@@ -15,7 +15,7 @@
 #ifdef CONFIG_VIDEO_OMAP2_VOUT_VRFB
 void omap_vout_free_vrfb_buffers(struct omap_vout_device *vout);
 int omap_vout_setup_vrfb_bufs(struct platform_device *pdev, int vid_num,
-                       u32 static_vrfb_allocation);
+                       bool static_vrfb_allocation);
 void omap_vout_release_vrfb(struct omap_vout_device *vout);
 int omap_vout_vrfb_buffer_setup(struct omap_vout_device *vout,
                        unsigned int *count, unsigned int startindex);
@@ -25,7 +25,7 @@ void omap_vout_calculate_vrfb_offset(struct omap_vout_device *vout);
 #else
 static inline void omap_vout_free_vrfb_buffers(struct omap_vout_device *vout) { };
 static inline int omap_vout_setup_vrfb_bufs(struct platform_device *pdev, int vid_num,
-                       u32 static_vrfb_allocation)
+                       bool static_vrfb_allocation)
                { return 0; };
 static inline void omap_vout_release_vrfb(struct omap_vout_device *vout) { };
 static inline int omap_vout_vrfb_buffer_setup(struct omap_vout_device *vout,
index deca80903c3a08fd59e875b110d4cb0fa3b5189f..18d0a871747fe95e2714d4ada0bf40b42a6389b5 100644 (file)
@@ -51,6 +51,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
+#include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/omap-iommu.h>
 #include <linux/platform_device.h>
@@ -63,6 +64,7 @@
 
 #include <media/v4l2-common.h>
 #include <media/v4l2-device.h>
+#include <media/v4l2-of.h>
 
 #include "isp.h"
 #include "ispreg.h"
@@ -85,35 +87,45 @@ static void isp_restore_ctx(struct isp_device *isp);
 static const struct isp_res_mapping isp_res_maps[] = {
        {
                .isp_rev = ISP_REVISION_2_0,
-               .map = 1 << OMAP3_ISP_IOMEM_MAIN |
-                      1 << OMAP3_ISP_IOMEM_CCP2 |
-                      1 << OMAP3_ISP_IOMEM_CCDC |
-                      1 << OMAP3_ISP_IOMEM_HIST |
-                      1 << OMAP3_ISP_IOMEM_H3A |
-                      1 << OMAP3_ISP_IOMEM_PREV |
-                      1 << OMAP3_ISP_IOMEM_RESZ |
-                      1 << OMAP3_ISP_IOMEM_SBL |
-                      1 << OMAP3_ISP_IOMEM_CSI2A_REGS1 |
-                      1 << OMAP3_ISP_IOMEM_CSIPHY2 |
-                      1 << OMAP3_ISP_IOMEM_343X_CONTROL_CSIRXFE,
+               .offset = {
+                       /* first MMIO area */
+                       0x0000, /* base, len 0x0070 */
+                       0x0400, /* ccp2, len 0x01f0 */
+                       0x0600, /* ccdc, len 0x00a8 */
+                       0x0a00, /* hist, len 0x0048 */
+                       0x0c00, /* h3a, len 0x0060 */
+                       0x0e00, /* preview, len 0x00a0 */
+                       0x1000, /* resizer, len 0x00ac */
+                       0x1200, /* sbl, len 0x00fc */
+                       /* second MMIO area */
+                       0x0000, /* csi2a, len 0x0170 */
+                       0x0170, /* csiphy2, len 0x000c */
+               },
+               .syscon_offset = 0xdc,
+               .phy_type = ISP_PHY_TYPE_3430,
        },
        {
                .isp_rev = ISP_REVISION_15_0,
-               .map = 1 << OMAP3_ISP_IOMEM_MAIN |
-                      1 << OMAP3_ISP_IOMEM_CCP2 |
-                      1 << OMAP3_ISP_IOMEM_CCDC |
-                      1 << OMAP3_ISP_IOMEM_HIST |
-                      1 << OMAP3_ISP_IOMEM_H3A |
-                      1 << OMAP3_ISP_IOMEM_PREV |
-                      1 << OMAP3_ISP_IOMEM_RESZ |
-                      1 << OMAP3_ISP_IOMEM_SBL |
-                      1 << OMAP3_ISP_IOMEM_CSI2A_REGS1 |
-                      1 << OMAP3_ISP_IOMEM_CSIPHY2 |
-                      1 << OMAP3_ISP_IOMEM_CSI2A_REGS2 |
-                      1 << OMAP3_ISP_IOMEM_CSI2C_REGS1 |
-                      1 << OMAP3_ISP_IOMEM_CSIPHY1 |
-                      1 << OMAP3_ISP_IOMEM_CSI2C_REGS2 |
-                      1 << OMAP3_ISP_IOMEM_3630_CONTROL_CAMERA_PHY_CTRL,
+               .offset = {
+                       /* first MMIO area */
+                       0x0000, /* base, len 0x0070 */
+                       0x0400, /* ccp2, len 0x01f0 */
+                       0x0600, /* ccdc, len 0x00a8 */
+                       0x0a00, /* hist, len 0x0048 */
+                       0x0c00, /* h3a, len 0x0060 */
+                       0x0e00, /* preview, len 0x00a0 */
+                       0x1000, /* resizer, len 0x00ac */
+                       0x1200, /* sbl, len 0x00fc */
+                       /* second MMIO area */
+                       0x0000, /* csi2a, len 0x0170 (1st area) */
+                       0x0170, /* csiphy2, len 0x000c */
+                       0x01c0, /* csi2a, len 0x0040 (2nd area) */
+                       0x0400, /* csi2c, len 0x0170 (1st area) */
+                       0x0570, /* csiphy1, len 0x000c */
+                       0x05c0, /* csi2c, len 0x0040 (2nd area) */
+               },
+               .syscon_offset = 0x2f0,
+               .phy_type = ISP_PHY_TYPE_3630,
        },
 };
 
@@ -279,9 +291,20 @@ static const struct clk_init_data isp_xclk_init_data = {
        .num_parents = 1,
 };
 
+static struct clk *isp_xclk_src_get(struct of_phandle_args *clkspec, void *data)
+{
+       unsigned int idx = clkspec->args[0];
+       struct isp_device *isp = data;
+
+       if (idx >= ARRAY_SIZE(isp->xclks))
+               return ERR_PTR(-ENOENT);
+
+       return isp->xclks[idx].clk;
+}
+
 static int isp_xclk_init(struct isp_device *isp)
 {
-       struct isp_platform_data *pdata = isp->pdata;
+       struct device_node *np = isp->dev->of_node;
        struct clk_init_data init;
        unsigned int i;
 
@@ -311,37 +334,27 @@ static int isp_xclk_init(struct isp_device *isp)
                xclk->clk = clk_register(NULL, &xclk->hw);
                if (IS_ERR(xclk->clk))
                        return PTR_ERR(xclk->clk);
-
-               if (pdata->xclks[i].con_id == NULL &&
-                   pdata->xclks[i].dev_id == NULL)
-                       continue;
-
-               xclk->lookup = kzalloc(sizeof(*xclk->lookup), GFP_KERNEL);
-               if (xclk->lookup == NULL)
-                       return -ENOMEM;
-
-               xclk->lookup->con_id = pdata->xclks[i].con_id;
-               xclk->lookup->dev_id = pdata->xclks[i].dev_id;
-               xclk->lookup->clk = xclk->clk;
-
-               clkdev_add(xclk->lookup);
        }
 
+       if (np)
+               of_clk_add_provider(np, isp_xclk_src_get, isp);
+
        return 0;
 }
 
 static void isp_xclk_cleanup(struct isp_device *isp)
 {
+       struct device_node *np = isp->dev->of_node;
        unsigned int i;
 
+       if (np)
+               of_clk_del_provider(np);
+
        for (i = 0; i < ARRAY_SIZE(isp->xclks); ++i) {
                struct isp_xclk *xclk = &isp->xclks[i];
 
                if (!IS_ERR(xclk->clk))
                        clk_unregister(xclk->clk);
-
-               if (xclk->lookup)
-                       clkdev_drop(xclk->lookup);
        }
 }
 
@@ -422,7 +435,7 @@ static void isp_core_init(struct isp_device *isp, int idle)
  */
 void omap3isp_configure_bridge(struct isp_device *isp,
                               enum ccdc_input_entity input,
-                              const struct isp_parallel_platform_data *pdata,
+                              const struct isp_parallel_cfg *parcfg,
                               unsigned int shift, unsigned int bridge)
 {
        u32 ispctrl_val;
@@ -437,8 +450,8 @@ void omap3isp_configure_bridge(struct isp_device *isp,
        switch (input) {
        case CCDC_INPUT_PARALLEL:
                ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_PARALLEL;
-               ispctrl_val |= pdata->clk_pol << ISPCTRL_PAR_CLK_POL_SHIFT;
-               shift += pdata->data_lane_shift * 2;
+               ispctrl_val |= parcfg->clk_pol << ISPCTRL_PAR_CLK_POL_SHIFT;
+               shift += parcfg->data_lane_shift * 2;
                break;
 
        case CCDC_INPUT_CSI2A:
@@ -1784,58 +1797,121 @@ static void isp_unregister_entities(struct isp_device *isp)
 }
 
 /*
- * isp_register_subdev_group - Register a group of subdevices
+ * isp_register_subdev - Register a sub-device
  * @isp: OMAP3 ISP device
- * @board_info: I2C subdevs board information array
+ * @isp_subdev: platform data related to a sub-device
  *
- * Register all I2C subdevices in the board_info array. The array must be
- * terminated by a NULL entry, and the first entry must be the sensor.
+ * Register an I2C sub-device which has not been registered by other
+ * means (such as the Device Tree).
  *
- * Return a pointer to the sensor media entity if it has been successfully
+ * Return a pointer to the sub-device if it has been successfully
  * registered, or NULL otherwise.
  */
 static struct v4l2_subdev *
-isp_register_subdev_group(struct isp_device *isp,
-                    struct isp_subdev_i2c_board_info *board_info)
+isp_register_subdev(struct isp_device *isp,
+                   struct isp_platform_subdev *isp_subdev)
 {
-       struct v4l2_subdev *sensor = NULL;
-       unsigned int first;
+       struct i2c_adapter *adapter;
+       struct v4l2_subdev *sd;
 
-       if (board_info->board_info == NULL)
+       if (isp_subdev->board_info == NULL)
                return NULL;
 
-       for (first = 1; board_info->board_info; ++board_info, first = 0) {
-               struct v4l2_subdev *subdev;
-               struct i2c_adapter *adapter;
+       adapter = i2c_get_adapter(isp_subdev->i2c_adapter_id);
+       if (adapter == NULL) {
+               dev_err(isp->dev,
+                       "%s: Unable to get I2C adapter %d for device %s\n",
+                       __func__, isp_subdev->i2c_adapter_id,
+                       isp_subdev->board_info->type);
+               return NULL;
+       }
 
-               adapter = i2c_get_adapter(board_info->i2c_adapter_id);
-               if (adapter == NULL) {
-                       dev_err(isp->dev, "%s: Unable to get I2C adapter %d for "
-                               "device %s\n", __func__,
-                               board_info->i2c_adapter_id,
-                               board_info->board_info->type);
-                       continue;
-               }
+       sd = v4l2_i2c_new_subdev_board(&isp->v4l2_dev, adapter,
+                                      isp_subdev->board_info, NULL);
+       if (sd == NULL) {
+               dev_err(isp->dev, "%s: Unable to register subdev %s\n",
+                       __func__, isp_subdev->board_info->type);
+               return NULL;
+       }
 
-               subdev = v4l2_i2c_new_subdev_board(&isp->v4l2_dev, adapter,
-                               board_info->board_info, NULL);
-               if (subdev == NULL) {
-                       dev_err(isp->dev, "%s: Unable to register subdev %s\n",
-                               __func__, board_info->board_info->type);
-                       continue;
-               }
+       return sd;
+}
+
+static int isp_link_entity(
+       struct isp_device *isp, struct media_entity *entity,
+       enum isp_interface_type interface)
+{
+       struct media_entity *input;
+       unsigned int flags;
+       unsigned int pad;
+       unsigned int i;
+
+       /* Connect the sensor to the correct interface module.
+        * Parallel sensors are connected directly to the CCDC, while
+        * serial sensors are connected to the CSI2a, CCP2b or CSI2c
+        * receiver through CSIPHY1 or CSIPHY2.
+        */
+       switch (interface) {
+       case ISP_INTERFACE_PARALLEL:
+               input = &isp->isp_ccdc.subdev.entity;
+               pad = CCDC_PAD_SINK;
+               flags = 0;
+               break;
+
+       case ISP_INTERFACE_CSI2A_PHY2:
+               input = &isp->isp_csi2a.subdev.entity;
+               pad = CSI2_PAD_SINK;
+               flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED;
+               break;
+
+       case ISP_INTERFACE_CCP2B_PHY1:
+       case ISP_INTERFACE_CCP2B_PHY2:
+               input = &isp->isp_ccp2.subdev.entity;
+               pad = CCP2_PAD_SINK;
+               flags = 0;
+               break;
+
+       case ISP_INTERFACE_CSI2C_PHY1:
+               input = &isp->isp_csi2c.subdev.entity;
+               pad = CSI2_PAD_SINK;
+               flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED;
+               break;
 
-               if (first)
-                       sensor = subdev;
+       default:
+               dev_err(isp->dev, "%s: invalid interface type %u\n", __func__,
+                       interface);
+               return -EINVAL;
+       }
+
+       /*
+        * Not all interfaces are available on all revisions of the
+        * ISP. The sub-devices of those interfaces aren't initialised
+        * in such a case. Check this by ensuring the num_pads is
+        * non-zero.
+        */
+       if (!input->num_pads) {
+               dev_err(isp->dev, "%s: invalid input %u\n", entity->name,
+                       interface);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < entity->num_pads; i++) {
+               if (entity->pads[i].flags & MEDIA_PAD_FL_SOURCE)
+                       break;
+       }
+       if (i == entity->num_pads) {
+               dev_err(isp->dev, "%s: no source pad in external entity\n",
+                       __func__);
+               return -EINVAL;
        }
 
-       return sensor;
+       return media_entity_create_link(entity, i, input, pad, flags);
 }
 
 static int isp_register_entities(struct isp_device *isp)
 {
        struct isp_platform_data *pdata = isp->pdata;
-       struct isp_v4l2_subdevs_group *subdevs;
+       struct isp_platform_subdev *isp_subdev;
        int ret;
 
        isp->media_dev.dev = isp->dev;
@@ -1892,74 +1968,31 @@ static int isp_register_entities(struct isp_device *isp)
        if (ret < 0)
                goto done;
 
+       /*
+        * Device Tree --- the external sub-devices will be registered
+        * later. The same goes for the sub-device node registration.
+        */
+       if (isp->dev->of_node)
+               return 0;
+
        /* Register external entities */
-       for (subdevs = pdata->subdevs; subdevs && subdevs->subdevs; ++subdevs) {
-               struct v4l2_subdev *sensor;
-               struct media_entity *input;
-               unsigned int flags;
-               unsigned int pad;
-               unsigned int i;
-
-               sensor = isp_register_subdev_group(isp, subdevs->subdevs);
-               if (sensor == NULL)
-                       continue;
+       for (isp_subdev = pdata ? pdata->subdevs : NULL;
+            isp_subdev && isp_subdev->board_info; isp_subdev++) {
+               struct v4l2_subdev *sd;
 
-               sensor->host_priv = subdevs;
+               sd = isp_register_subdev(isp, isp_subdev);
 
-               /* Connect the sensor to the correct interface module. Parallel
-                * sensors are connected directly to the CCDC, while serial
-                * sensors are connected to the CSI2a, CCP2b or CSI2c receiver
-                * through CSIPHY1 or CSIPHY2.
+               /*
+                * No bus information --- this is either a flash or a
+                * lens subdev.
                 */
-               switch (subdevs->interface) {
-               case ISP_INTERFACE_PARALLEL:
-                       input = &isp->isp_ccdc.subdev.entity;
-                       pad = CCDC_PAD_SINK;
-                       flags = 0;
-                       break;
-
-               case ISP_INTERFACE_CSI2A_PHY2:
-                       input = &isp->isp_csi2a.subdev.entity;
-                       pad = CSI2_PAD_SINK;
-                       flags = MEDIA_LNK_FL_IMMUTABLE
-                             | MEDIA_LNK_FL_ENABLED;
-                       break;
-
-               case ISP_INTERFACE_CCP2B_PHY1:
-               case ISP_INTERFACE_CCP2B_PHY2:
-                       input = &isp->isp_ccp2.subdev.entity;
-                       pad = CCP2_PAD_SINK;
-                       flags = 0;
-                       break;
-
-               case ISP_INTERFACE_CSI2C_PHY1:
-                       input = &isp->isp_csi2c.subdev.entity;
-                       pad = CSI2_PAD_SINK;
-                       flags = MEDIA_LNK_FL_IMMUTABLE
-                             | MEDIA_LNK_FL_ENABLED;
-                       break;
-
-               default:
-                       dev_err(isp->dev, "%s: invalid interface type %u\n",
-                               __func__, subdevs->interface);
-                       ret = -EINVAL;
-                       goto done;
-               }
+               if (!sd || !isp_subdev->bus)
+                       continue;
 
-               for (i = 0; i < sensor->entity.num_pads; i++) {
-                       if (sensor->entity.pads[i].flags & MEDIA_PAD_FL_SOURCE)
-                               break;
-               }
-               if (i == sensor->entity.num_pads) {
-                       dev_err(isp->dev,
-                               "%s: no source pad in external entity\n",
-                               __func__);
-                       ret = -EINVAL;
-                       goto done;
-               }
+               sd->host_priv = isp_subdev->bus;
 
-               ret = media_entity_create_link(&sensor->entity, i, input, pad,
-                                              flags);
+               ret = isp_link_entity(isp, &sd->entity,
+                                     isp_subdev->bus->interface);
                if (ret < 0)
                        goto done;
        }
@@ -1967,8 +2000,10 @@ static int isp_register_entities(struct isp_device *isp)
        ret = v4l2_device_register_subdev_nodes(&isp->v4l2_dev);
 
 done:
-       if (ret < 0)
+       if (ret < 0) {
                isp_unregister_entities(isp);
+               v4l2_async_notifier_unregister(&isp->notifier);
+       }
 
        return ret;
 }
@@ -2183,6 +2218,7 @@ static int isp_remove(struct platform_device *pdev)
 {
        struct isp_device *isp = platform_get_drvdata(pdev);
 
+       v4l2_async_notifier_unregister(&isp->notifier);
        isp_unregister_entities(isp);
        isp_cleanup_modules(isp);
        isp_xclk_cleanup(isp);
@@ -2194,26 +2230,156 @@ static int isp_remove(struct platform_device *pdev)
        return 0;
 }
 
-static int isp_map_mem_resource(struct platform_device *pdev,
-                               struct isp_device *isp,
-                               enum isp_mem_resources res)
+enum isp_of_phy {
+       ISP_OF_PHY_PARALLEL = 0,
+       ISP_OF_PHY_CSIPHY1,
+       ISP_OF_PHY_CSIPHY2,
+};
+
+static int isp_of_parse_node(struct device *dev, struct device_node *node,
+                            struct isp_async_subdev *isd)
 {
-       struct resource *mem;
+       struct isp_bus_cfg *buscfg = &isd->bus;
+       struct v4l2_of_endpoint vep;
+       unsigned int i;
 
-       /* request the mem region for the camera registers */
+       v4l2_of_parse_endpoint(node, &vep);
+
+       dev_dbg(dev, "parsing endpoint %s, interface %u\n", node->full_name,
+               vep.base.port);
+
+       switch (vep.base.port) {
+       case ISP_OF_PHY_PARALLEL:
+               buscfg->interface = ISP_INTERFACE_PARALLEL;
+               buscfg->bus.parallel.data_lane_shift =
+                       vep.bus.parallel.data_shift;
+               buscfg->bus.parallel.clk_pol =
+                       !!(vep.bus.parallel.flags
+                          & V4L2_MBUS_PCLK_SAMPLE_FALLING);
+               buscfg->bus.parallel.hs_pol =
+                       !!(vep.bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW);
+               buscfg->bus.parallel.vs_pol =
+                       !!(vep.bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW);
+               buscfg->bus.parallel.fld_pol =
+                       !!(vep.bus.parallel.flags & V4L2_MBUS_FIELD_EVEN_LOW);
+               buscfg->bus.parallel.data_pol =
+                       !!(vep.bus.parallel.flags & V4L2_MBUS_DATA_ACTIVE_LOW);
+               break;
 
-       mem = platform_get_resource(pdev, IORESOURCE_MEM, res);
+       case ISP_OF_PHY_CSIPHY1:
+       case ISP_OF_PHY_CSIPHY2:
+               /* FIXME: always assume CSI-2 for now. */
+               switch (vep.base.port) {
+               case ISP_OF_PHY_CSIPHY1:
+                       buscfg->interface = ISP_INTERFACE_CSI2C_PHY1;
+                       break;
+               case ISP_OF_PHY_CSIPHY2:
+                       buscfg->interface = ISP_INTERFACE_CSI2A_PHY2;
+                       break;
+               }
+               buscfg->bus.csi2.lanecfg.clk.pos = vep.bus.mipi_csi2.clock_lane;
+               buscfg->bus.csi2.lanecfg.clk.pol =
+                       vep.bus.mipi_csi2.lane_polarities[0];
+               dev_dbg(dev, "clock lane polarity %u, pos %u\n",
+                       buscfg->bus.csi2.lanecfg.clk.pol,
+                       buscfg->bus.csi2.lanecfg.clk.pos);
+
+               for (i = 0; i < ISP_CSIPHY2_NUM_DATA_LANES; i++) {
+                       buscfg->bus.csi2.lanecfg.data[i].pos =
+                               vep.bus.mipi_csi2.data_lanes[i];
+                       buscfg->bus.csi2.lanecfg.data[i].pol =
+                               vep.bus.mipi_csi2.lane_polarities[i + 1];
+                       dev_dbg(dev, "data lane %u polarity %u, pos %u\n", i,
+                               buscfg->bus.csi2.lanecfg.data[i].pol,
+                               buscfg->bus.csi2.lanecfg.data[i].pos);
+               }
 
-       /* map the region */
-       isp->mmio_base[res] = devm_ioremap_resource(isp->dev, mem);
-       if (IS_ERR(isp->mmio_base[res]))
-               return PTR_ERR(isp->mmio_base[res]);
+               /*
+                * FIXME: now we assume the CRC is always there.
+                * Implement a way to obtain this information from the
+                * sensor. Frame descriptors, perhaps?
+                */
+               buscfg->bus.csi2.crc = 1;
+               break;
 
-       isp->mmio_base_phys[res] = mem->start;
+       default:
+               dev_warn(dev, "%s: invalid interface %u\n", node->full_name,
+                        vep.base.port);
+               break;
+       }
 
        return 0;
 }
 
+static int isp_of_parse_nodes(struct device *dev,
+                             struct v4l2_async_notifier *notifier)
+{
+       struct device_node *node = NULL;
+
+       notifier->subdevs = devm_kcalloc(
+               dev, ISP_MAX_SUBDEVS, sizeof(*notifier->subdevs), GFP_KERNEL);
+       if (!notifier->subdevs)
+               return -ENOMEM;
+
+       while (notifier->num_subdevs < ISP_MAX_SUBDEVS &&
+              (node = of_graph_get_next_endpoint(dev->of_node, node))) {
+               struct isp_async_subdev *isd;
+
+               isd = devm_kzalloc(dev, sizeof(*isd), GFP_KERNEL);
+               if (!isd) {
+                       of_node_put(node);
+                       return -ENOMEM;
+               }
+
+               notifier->subdevs[notifier->num_subdevs] = &isd->asd;
+
+               if (isp_of_parse_node(dev, node, isd)) {
+                       of_node_put(node);
+                       return -EINVAL;
+               }
+
+               isd->asd.match.of.node = of_graph_get_remote_port_parent(node);
+               of_node_put(node);
+               if (!isd->asd.match.of.node) {
+                       dev_warn(dev, "bad remote port parent\n");
+                       return -EINVAL;
+               }
+
+               isd->asd.match_type = V4L2_ASYNC_MATCH_OF;
+               notifier->num_subdevs++;
+       }
+
+       return notifier->num_subdevs;
+}
+
+static int isp_subdev_notifier_bound(struct v4l2_async_notifier *async,
+                                    struct v4l2_subdev *subdev,
+                                    struct v4l2_async_subdev *asd)
+{
+       struct isp_device *isp = container_of(async, struct isp_device,
+                                             notifier);
+       struct isp_async_subdev *isd =
+               container_of(asd, struct isp_async_subdev, asd);
+       int ret;
+
+       ret = isp_link_entity(isp, &subdev->entity, isd->bus.interface);
+       if (ret < 0)
+               return ret;
+
+       isd->sd = subdev;
+       isd->sd->host_priv = &isd->bus;
+
+       return ret;
+}
+
+static int isp_subdev_notifier_complete(struct v4l2_async_notifier *async)
+{
+       struct isp_device *isp = container_of(async, struct isp_device,
+                                             notifier);
+
+       return v4l2_device_register_subdev_nodes(&isp->v4l2_dev);
+}
+
 /*
  * isp_probe - Probe ISP platform device
  * @pdev: Pointer to ISP platform device
@@ -2227,47 +2393,86 @@ static int isp_map_mem_resource(struct platform_device *pdev,
  */
 static int isp_probe(struct platform_device *pdev)
 {
-       struct isp_platform_data *pdata = pdev->dev.platform_data;
        struct isp_device *isp;
+       struct resource *mem;
        int ret;
        int i, m;
 
-       if (pdata == NULL)
-               return -EINVAL;
-
        isp = devm_kzalloc(&pdev->dev, sizeof(*isp), GFP_KERNEL);
        if (!isp) {
                dev_err(&pdev->dev, "could not allocate memory\n");
                return -ENOMEM;
        }
 
+       if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {
+               ret = of_property_read_u32(pdev->dev.of_node, "ti,phy-type",
+                                          &isp->phy_type);
+               if (ret)
+                       return ret;
+
+               isp->syscon = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+                                                             "syscon");
+               if (IS_ERR(isp->syscon))
+                       return PTR_ERR(isp->syscon);
+
+               ret = of_property_read_u32_index(pdev->dev.of_node, "syscon", 1,
+                                                &isp->syscon_offset);
+               if (ret)
+                       return ret;
+
+               ret = isp_of_parse_nodes(&pdev->dev, &isp->notifier);
+               if (ret < 0)
+                       return ret;
+               ret = v4l2_async_notifier_register(&isp->v4l2_dev,
+                                                  &isp->notifier);
+               if (ret)
+                       return ret;
+       } else {
+               isp->pdata = pdev->dev.platform_data;
+               isp->syscon = syscon_regmap_lookup_by_pdevname("syscon.0");
+               if (IS_ERR(isp->syscon))
+                       return PTR_ERR(isp->syscon);
+               dev_warn(&pdev->dev,
+                        "Platform data support is deprecated! Please move to DT now!\n");
+       }
+
        isp->autoidle = autoidle;
 
        mutex_init(&isp->isp_mutex);
        spin_lock_init(&isp->stat_lock);
 
        isp->dev = &pdev->dev;
-       isp->pdata = pdata;
        isp->ref_count = 0;
 
        ret = dma_coerce_mask_and_coherent(isp->dev, DMA_BIT_MASK(32));
        if (ret)
-               return ret;
+               goto error;
 
        platform_set_drvdata(pdev, isp);
 
        /* Regulators */
-       isp->isp_csiphy1.vdd = devm_regulator_get(&pdev->dev, "VDD_CSIPHY1");
-       isp->isp_csiphy2.vdd = devm_regulator_get(&pdev->dev, "VDD_CSIPHY2");
+       isp->isp_csiphy1.vdd = devm_regulator_get(&pdev->dev, "vdd-csiphy1");
+       isp->isp_csiphy2.vdd = devm_regulator_get(&pdev->dev, "vdd-csiphy2");
 
        /* Clocks
         *
         * The ISP clock tree is revision-dependent. We thus need to enable ICLK
         * manually to read the revision before calling __omap3isp_get().
+        *
+        * Start by mapping the ISP MMIO area, which is in two pieces.
+        * The ISP IOMMU is in between. Map both now, and fill in the
+        * ISP revision specific portions a little later in the
+        * function.
         */
-       ret = isp_map_mem_resource(pdev, isp, OMAP3_ISP_IOMEM_MAIN);
-       if (ret < 0)
-               goto error;
+       for (i = 0; i < 2; i++) {
+               unsigned int map_idx = i ? OMAP3_ISP_IOMEM_CSI2A_REGS1 : 0;
+
+               mem = platform_get_resource(pdev, IORESOURCE_MEM, i);
+               isp->mmio_base[map_idx] =
+                       devm_ioremap_resource(isp->dev, mem);
+               if (IS_ERR(isp->mmio_base[map_idx]))
+                       return PTR_ERR(isp->mmio_base[map_idx]);
+       }
 
        ret = isp_get_clocks(isp);
        if (ret < 0)
@@ -2308,14 +2513,23 @@ static int isp_probe(struct platform_device *pdev)
                goto error_isp;
        }
 
-       for (i = 1; i < OMAP3_ISP_IOMEM_LAST; i++) {
-               if (isp_res_maps[m].map & 1 << i) {
-                       ret = isp_map_mem_resource(pdev, isp, i);
-                       if (ret)
-                               goto error_isp;
-               }
+       if (!IS_ENABLED(CONFIG_OF) || !pdev->dev.of_node) {
+               isp->syscon_offset = isp_res_maps[m].syscon_offset;
+               isp->phy_type = isp_res_maps[m].phy_type;
        }
 
+       for (i = 1; i < OMAP3_ISP_IOMEM_CSI2A_REGS1; i++)
+               isp->mmio_base[i] =
+                       isp->mmio_base[0] + isp_res_maps[m].offset[i];
+
+       for (i = OMAP3_ISP_IOMEM_CSIPHY2; i < OMAP3_ISP_IOMEM_LAST; i++)
+               isp->mmio_base[i] =
+                       isp->mmio_base[OMAP3_ISP_IOMEM_CSI2A_REGS1]
+                       + isp_res_maps[m].offset[i];
+
+       isp->mmio_hist_base_phys =
+               mem->start + isp_res_maps[m].offset[OMAP3_ISP_IOMEM_HIST];
+
        /* IOMMU */
        ret = isp_attach_iommu(isp);
        if (ret < 0) {
@@ -2343,6 +2557,9 @@ static int isp_probe(struct platform_device *pdev)
        if (ret < 0)
                goto error_iommu;
 
+       isp->notifier.bound = isp_subdev_notifier_bound;
+       isp->notifier.complete = isp_subdev_notifier_complete;
+
        ret = isp_register_entities(isp);
        if (ret < 0)
                goto error_modules;
@@ -2378,6 +2595,11 @@ static struct platform_device_id omap3isp_id_table[] = {
 };
 MODULE_DEVICE_TABLE(platform, omap3isp_id_table);
 
+static const struct of_device_id omap3isp_of_table[] = {
+       { .compatible = "ti,omap3-isp" },
+       { },
+};
+
 static struct platform_driver omap3isp_driver = {
        .probe = isp_probe,
        .remove = isp_remove,
@@ -2385,6 +2607,7 @@ static struct platform_driver omap3isp_driver = {
        .driver = {
                .name = "omap3isp",
                .pm     = &omap3isp_pm_ops,
+               .of_match_table = omap3isp_of_table,
        },
 };
 
index cfdfc8714b6b8f7fb7d633a75b48b82971b0e482..e579943175c4cfcd419e45ccf01dfe6ac3c52447 100644 (file)
@@ -18,6 +18,7 @@
 #define OMAP3_ISP_CORE_H
 
 #include <media/omap3isp.h>
+#include <media/v4l2-async.h>
 #include <media/v4l2-device.h>
 #include <linux/clk-provider.h>
 #include <linux/device.h>
@@ -59,8 +60,6 @@ enum isp_mem_resources {
        OMAP3_ISP_IOMEM_CSI2C_REGS1,
        OMAP3_ISP_IOMEM_CSIPHY1,
        OMAP3_ISP_IOMEM_CSI2C_REGS2,
-       OMAP3_ISP_IOMEM_343X_CONTROL_CSIRXFE,
-       OMAP3_ISP_IOMEM_3630_CONTROL_CAMERA_PHY_CTRL,
        OMAP3_ISP_IOMEM_LAST
 };
 
@@ -93,14 +92,25 @@ enum isp_subclk_resource {
 /* ISP2P: OMAP 36xx */
 #define ISP_REVISION_15_0              0xF0
 
+#define ISP_PHY_TYPE_3430              0
+#define ISP_PHY_TYPE_3630              1
+
+struct regmap;
+
 /*
  * struct isp_res_mapping - Map ISP io resources to ISP revision.
  * @isp_rev: ISP_REVISION_x_x
- * @map: bitmap for enum isp_mem_resources
+ * @offset: register offsets of various ISP sub-blocks
+ * @syscon_offset: offset of the syscon register for 343x / 3630
+ *         (CONTROL_CSIRXFE / CONTROL_CAMERA_PHY_CTRL, respectively)
+ *         from the syscon base address
+ * @phy_type: ISP_PHY_TYPE_{3430,3630}
  */
 struct isp_res_mapping {
        u32 isp_rev;
-       u32 map;
+       u32 offset[OMAP3_ISP_IOMEM_LAST];
+       u32 syscon_offset;
+       u32 phy_type;
 };
 
 /*
@@ -122,7 +132,6 @@ enum isp_xclk_id {
 struct isp_xclk {
        struct isp_device *isp;
        struct clk_hw hw;
-       struct clk_lookup *lookup;
        struct clk *clk;
        enum isp_xclk_id id;
 
@@ -138,8 +147,11 @@ struct isp_xclk {
  * @irq_num: Currently used IRQ number.
  * @mmio_base: Array with kernel base addresses for ioremapped ISP register
  *             regions.
- * @mmio_base_phys: Array with physical L4 bus addresses for ISP register
- *                  regions.
+ * @mmio_hist_base_phys: Physical L4 bus address for ISP hist block register
+ *                      region.
+ * @syscon: Regmap for the syscon register space
+ * @syscon_offset: Offset of the CSIPHY control register in syscon
+ * @phy_type: ISP_PHY_TYPE_{3430,3630}
  * @mapping: IOMMU mapping
  * @stat_lock: Spinlock for handling statistics
  * @isp_mutex: Mutex for serializing requests to ISP.
@@ -166,6 +178,7 @@ struct isp_xclk {
  */
 struct isp_device {
        struct v4l2_device v4l2_dev;
+       struct v4l2_async_notifier notifier;
        struct media_device media_dev;
        struct device *dev;
        u32 revision;
@@ -175,7 +188,10 @@ struct isp_device {
        unsigned int irq_num;
 
        void __iomem *mmio_base[OMAP3_ISP_IOMEM_LAST];
-       unsigned long mmio_base_phys[OMAP3_ISP_IOMEM_LAST];
+       unsigned long mmio_hist_base_phys;
+       struct regmap *syscon;
+       u32 syscon_offset;
+       u32 phy_type;
 
        struct dma_iommu_mapping *mapping;
 
@@ -209,6 +225,15 @@ struct isp_device {
 
        unsigned int sbl_resources;
        unsigned int subclk_resources;
+
+#define ISP_MAX_SUBDEVS                8
+       struct v4l2_subdev *subdevs[ISP_MAX_SUBDEVS];
+};
+
+struct isp_async_subdev {
+       struct v4l2_subdev *sd;
+       struct isp_bus_cfg bus;
+       struct v4l2_async_subdev asd;
 };
 
 #define v4l2_dev_to_isp_device(dev) \
@@ -229,7 +254,7 @@ int omap3isp_pipeline_set_stream(struct isp_pipeline *pipe,
 void omap3isp_pipeline_cancel_stream(struct isp_pipeline *pipe);
 void omap3isp_configure_bridge(struct isp_device *isp,
                               enum ccdc_input_entity input,
-                              const struct isp_parallel_platform_data *pdata,
+                              const struct isp_parallel_cfg *buscfg,
                               unsigned int shift, unsigned int bridge);
 
 struct isp_device *omap3isp_get(struct isp_device *isp);
index 587489a072d5f5a634e98faf9546028277ef1c3f..a6a61cce43ddadf6ca095990289852f5b3d86aca 100644 (file)
@@ -32,7 +32,7 @@
 #define CCDC_MIN_HEIGHT                32
 
 static struct v4l2_mbus_framefmt *
-__ccdc_get_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
+__ccdc_get_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_pad_config *cfg,
                  unsigned int pad, enum v4l2_subdev_format_whence which);
 
 static const unsigned int ccdc_fmts[] = {
@@ -958,11 +958,11 @@ void omap3isp_ccdc_max_rate(struct isp_ccdc_device *ccdc,
 /*
  * ccdc_config_sync_if - Set CCDC sync interface configuration
  * @ccdc: Pointer to ISP CCDC device.
- * @pdata: Parallel interface platform data (may be NULL)
+ * @parcfg: Parallel interface platform data (may be NULL)
  * @data_size: Data size
  */
 static void ccdc_config_sync_if(struct isp_ccdc_device *ccdc,
-                               struct isp_parallel_platform_data *pdata,
+                               struct isp_parallel_cfg *parcfg,
                                unsigned int data_size)
 {
        struct isp_device *isp = to_isp_device(ccdc);
@@ -1000,19 +1000,19 @@ static void ccdc_config_sync_if(struct isp_ccdc_device *ccdc,
                break;
        }
 
-       if (pdata && pdata->data_pol)
+       if (parcfg && parcfg->data_pol)
                syn_mode |= ISPCCDC_SYN_MODE_DATAPOL;
 
-       if (pdata && pdata->hs_pol)
+       if (parcfg && parcfg->hs_pol)
                syn_mode |= ISPCCDC_SYN_MODE_HDPOL;
 
        /* The polarity of the vertical sync signal output by the BT.656
         * decoder is not documented and seems to be active low.
         */
-       if ((pdata && pdata->vs_pol) || ccdc->bt656)
+       if ((parcfg && parcfg->vs_pol) || ccdc->bt656)
                syn_mode |= ISPCCDC_SYN_MODE_VDPOL;
 
-       if (pdata && pdata->fld_pol)
+       if (parcfg && parcfg->fld_pol)
                syn_mode |= ISPCCDC_SYN_MODE_FLDPOL;
 
        isp_reg_writel(isp, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
@@ -1115,7 +1115,7 @@ static const u32 ccdc_sgbrg_pattern =
 static void ccdc_configure(struct isp_ccdc_device *ccdc)
 {
        struct isp_device *isp = to_isp_device(ccdc);
-       struct isp_parallel_platform_data *pdata = NULL;
+       struct isp_parallel_cfg *parcfg = NULL;
        struct v4l2_subdev *sensor;
        struct v4l2_mbus_framefmt *format;
        const struct v4l2_rect *crop;
@@ -1145,7 +1145,7 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc)
                if (!ret)
                        ccdc->bt656 = cfg.type == V4L2_MBUS_BT656;
 
-               pdata = &((struct isp_v4l2_subdevs_group *)sensor->host_priv)
+               parcfg = &((struct isp_bus_cfg *)sensor->host_priv)
                        ->bus.parallel;
        }
 
@@ -1175,10 +1175,10 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc)
        else
                bridge = ISPCTRL_PAR_BRIDGE_DISABLE;
 
-       omap3isp_configure_bridge(isp, ccdc->input, pdata, shift, bridge);
+       omap3isp_configure_bridge(isp, ccdc->input, parcfg, shift, bridge);
 
        /* Configure the sync interface. */
-       ccdc_config_sync_if(ccdc, pdata, depth_out);
+       ccdc_config_sync_if(ccdc, parcfg, depth_out);
 
        syn_mode = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
 
@@ -1935,21 +1935,21 @@ static int ccdc_set_stream(struct v4l2_subdev *sd, int enable)
 }
 
 static struct v4l2_mbus_framefmt *
-__ccdc_get_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
+__ccdc_get_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_pad_config *cfg,
                  unsigned int pad, enum v4l2_subdev_format_whence which)
 {
        if (which == V4L2_SUBDEV_FORMAT_TRY)
-               return v4l2_subdev_get_try_format(fh, pad);
+               return v4l2_subdev_get_try_format(&ccdc->subdev, cfg, pad);
        else
                return &ccdc->formats[pad];
 }
 
 static struct v4l2_rect *
-__ccdc_get_crop(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
+__ccdc_get_crop(struct isp_ccdc_device *ccdc, struct v4l2_subdev_pad_config *cfg,
                enum v4l2_subdev_format_whence which)
 {
        if (which == V4L2_SUBDEV_FORMAT_TRY)
-               return v4l2_subdev_get_try_crop(fh, CCDC_PAD_SOURCE_OF);
+               return v4l2_subdev_get_try_crop(&ccdc->subdev, cfg, CCDC_PAD_SOURCE_OF);
        else
                return &ccdc->crop;
 }
@@ -1957,12 +1957,12 @@ __ccdc_get_crop(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
 /*
  * ccdc_try_format - Try video format on a pad
  * @ccdc: ISP CCDC device
- * @fh : V4L2 subdev file handle
+ * @cfg : V4L2 subdev pad configuration
  * @pad: Pad number
  * @fmt: Format
  */
 static void
-ccdc_try_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
+ccdc_try_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_pad_config *cfg,
                unsigned int pad, struct v4l2_mbus_framefmt *fmt,
                enum v4l2_subdev_format_whence which)
 {
@@ -1998,7 +1998,7 @@ ccdc_try_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
        case CCDC_PAD_SOURCE_OF:
                pixelcode = fmt->code;
                field = fmt->field;
-               *fmt = *__ccdc_get_format(ccdc, fh, CCDC_PAD_SINK, which);
+               *fmt = *__ccdc_get_format(ccdc, cfg, CCDC_PAD_SINK, which);
 
                /* In SYNC mode the bridge converts YUV formats from 2X8 to
                 * 1X16. In BT.656 no such conversion occurs. As we don't know
@@ -2023,7 +2023,7 @@ ccdc_try_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
                }
 
                /* Hardcode the output size to the crop rectangle size. */
-               crop = __ccdc_get_crop(ccdc, fh, which);
+               crop = __ccdc_get_crop(ccdc, cfg, which);
                fmt->width = crop->width;
                fmt->height = crop->height;
 
@@ -2040,7 +2040,7 @@ ccdc_try_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
                break;
 
        case CCDC_PAD_SOURCE_VP:
-               *fmt = *__ccdc_get_format(ccdc, fh, CCDC_PAD_SINK, which);
+               *fmt = *__ccdc_get_format(ccdc, cfg, CCDC_PAD_SINK, which);
 
                /* The video port interface truncates the data to 10 bits. */
                info = omap3isp_video_format_info(fmt->code);
@@ -2112,12 +2112,12 @@ static void ccdc_try_crop(struct isp_ccdc_device *ccdc,
 /*
  * ccdc_enum_mbus_code - Handle pixel format enumeration
  * @sd     : pointer to v4l2 subdev structure
- * @fh : V4L2 subdev file handle
+ * @cfg : V4L2 subdev pad configuration
  * @code   : pointer to v4l2_subdev_mbus_code_enum structure
  * return -EINVAL or zero on success
  */
 static int ccdc_enum_mbus_code(struct v4l2_subdev *sd,
-                              struct v4l2_subdev_fh *fh,
+                              struct v4l2_subdev_pad_config *cfg,
                               struct v4l2_subdev_mbus_code_enum *code)
 {
        struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
@@ -2132,8 +2132,8 @@ static int ccdc_enum_mbus_code(struct v4l2_subdev *sd,
                break;
 
        case CCDC_PAD_SOURCE_OF:
-               format = __ccdc_get_format(ccdc, fh, code->pad,
-                                          V4L2_SUBDEV_FORMAT_TRY);
+               format = __ccdc_get_format(ccdc, cfg, code->pad,
+                                          code->which);
 
                if (format->code == MEDIA_BUS_FMT_YUYV8_2X8 ||
                    format->code == MEDIA_BUS_FMT_UYVY8_2X8) {
@@ -2163,8 +2163,8 @@ static int ccdc_enum_mbus_code(struct v4l2_subdev *sd,
                if (code->index != 0)
                        return -EINVAL;
 
-               format = __ccdc_get_format(ccdc, fh, code->pad,
-                                          V4L2_SUBDEV_FORMAT_TRY);
+               format = __ccdc_get_format(ccdc, cfg, code->pad,
+                                          code->which);
 
                /* A pixel code equal to 0 means that the video port doesn't
                 * support the input format. Don't enumerate any pixel code.
@@ -2183,7 +2183,7 @@ static int ccdc_enum_mbus_code(struct v4l2_subdev *sd,
 }
 
 static int ccdc_enum_frame_size(struct v4l2_subdev *sd,
-                               struct v4l2_subdev_fh *fh,
+                               struct v4l2_subdev_pad_config *cfg,
                                struct v4l2_subdev_frame_size_enum *fse)
 {
        struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
@@ -2195,7 +2195,7 @@ static int ccdc_enum_frame_size(struct v4l2_subdev *sd,
        format.code = fse->code;
        format.width = 1;
        format.height = 1;
-       ccdc_try_format(ccdc, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+       ccdc_try_format(ccdc, cfg, fse->pad, &format, fse->which);
        fse->min_width = format.width;
        fse->min_height = format.height;
 
@@ -2205,7 +2205,7 @@ static int ccdc_enum_frame_size(struct v4l2_subdev *sd,
        format.code = fse->code;
        format.width = -1;
        format.height = -1;
-       ccdc_try_format(ccdc, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+       ccdc_try_format(ccdc, cfg, fse->pad, &format, fse->which);
        fse->max_width = format.width;
        fse->max_height = format.height;
 
@@ -2215,7 +2215,7 @@ static int ccdc_enum_frame_size(struct v4l2_subdev *sd,
 /*
  * ccdc_get_selection - Retrieve a selection rectangle on a pad
  * @sd: ISP CCDC V4L2 subdevice
- * @fh: V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad configuration
  * @sel: Selection rectangle
  *
  * The only supported rectangles are the crop rectangles on the output formatter
@@ -2223,7 +2223,7 @@ static int ccdc_enum_frame_size(struct v4l2_subdev *sd,
  *
  * Return 0 on success or a negative error code otherwise.
  */
-static int ccdc_get_selection(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int ccdc_get_selection(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_selection *sel)
 {
        struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
@@ -2239,12 +2239,12 @@ static int ccdc_get_selection(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
                sel->r.width = INT_MAX;
                sel->r.height = INT_MAX;
 
-               format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SINK, sel->which);
+               format = __ccdc_get_format(ccdc, cfg, CCDC_PAD_SINK, sel->which);
                ccdc_try_crop(ccdc, format, &sel->r);
                break;
 
        case V4L2_SEL_TGT_CROP:
-               sel->r = *__ccdc_get_crop(ccdc, fh, sel->which);
+               sel->r = *__ccdc_get_crop(ccdc, cfg, sel->which);
                break;
 
        default:
@@ -2257,7 +2257,7 @@ static int ccdc_get_selection(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 /*
  * ccdc_set_selection - Set a selection rectangle on a pad
  * @sd: ISP CCDC V4L2 subdevice
- * @fh: V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad configuration
  * @sel: Selection rectangle
  *
  * The only supported rectangle is the actual crop rectangle on the output
@@ -2265,7 +2265,7 @@ static int ccdc_get_selection(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
  *
  * Return 0 on success or a negative error code otherwise.
  */
-static int ccdc_set_selection(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int ccdc_set_selection(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_selection *sel)
 {
        struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
@@ -2284,17 +2284,17 @@ static int ccdc_set_selection(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
         * rectangle.
         */
        if (sel->flags & V4L2_SEL_FLAG_KEEP_CONFIG) {
-               sel->r = *__ccdc_get_crop(ccdc, fh, sel->which);
+               sel->r = *__ccdc_get_crop(ccdc, cfg, sel->which);
                return 0;
        }
 
-       format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SINK, sel->which);
+       format = __ccdc_get_format(ccdc, cfg, CCDC_PAD_SINK, sel->which);
        ccdc_try_crop(ccdc, format, &sel->r);
-       *__ccdc_get_crop(ccdc, fh, sel->which) = sel->r;
+       *__ccdc_get_crop(ccdc, cfg, sel->which) = sel->r;
 
        /* Update the source format. */
-       format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SOURCE_OF, sel->which);
-       ccdc_try_format(ccdc, fh, CCDC_PAD_SOURCE_OF, format, sel->which);
+       format = __ccdc_get_format(ccdc, cfg, CCDC_PAD_SOURCE_OF, sel->which);
+       ccdc_try_format(ccdc, cfg, CCDC_PAD_SOURCE_OF, format, sel->which);
 
        return 0;
 }
@@ -2302,19 +2302,19 @@ static int ccdc_set_selection(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 /*
  * ccdc_get_format - Retrieve the video format on a pad
  * @sd : ISP CCDC V4L2 subdevice
- * @fh : V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad configuration
  * @fmt: Format
  *
  * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
  * to the format type.
  */
-static int ccdc_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int ccdc_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                           struct v4l2_subdev_format *fmt)
 {
        struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
        struct v4l2_mbus_framefmt *format;
 
-       format = __ccdc_get_format(ccdc, fh, fmt->pad, fmt->which);
+       format = __ccdc_get_format(ccdc, cfg, fmt->pad, fmt->which);
        if (format == NULL)
                return -EINVAL;
 
@@ -2325,30 +2325,30 @@ static int ccdc_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 /*
  * ccdc_set_format - Set the video format on a pad
  * @sd : ISP CCDC V4L2 subdevice
- * @fh : V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad configuration
  * @fmt: Format
  *
  * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
  * to the format type.
  */
-static int ccdc_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int ccdc_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                           struct v4l2_subdev_format *fmt)
 {
        struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
        struct v4l2_mbus_framefmt *format;
        struct v4l2_rect *crop;
 
-       format = __ccdc_get_format(ccdc, fh, fmt->pad, fmt->which);
+       format = __ccdc_get_format(ccdc, cfg, fmt->pad, fmt->which);
        if (format == NULL)
                return -EINVAL;
 
-       ccdc_try_format(ccdc, fh, fmt->pad, &fmt->format, fmt->which);
+       ccdc_try_format(ccdc, cfg, fmt->pad, &fmt->format, fmt->which);
        *format = fmt->format;
 
        /* Propagate the format from sink to source */
        if (fmt->pad == CCDC_PAD_SINK) {
                /* Reset the crop rectangle. */
-               crop = __ccdc_get_crop(ccdc, fh, fmt->which);
+               crop = __ccdc_get_crop(ccdc, cfg, fmt->which);
                crop->left = 0;
                crop->top = 0;
                crop->width = fmt->format.width;
@@ -2357,16 +2357,16 @@ static int ccdc_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
                ccdc_try_crop(ccdc, &fmt->format, crop);
 
                /* Update the source formats. */
-               format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SOURCE_OF,
+               format = __ccdc_get_format(ccdc, cfg, CCDC_PAD_SOURCE_OF,
                                           fmt->which);
                *format = fmt->format;
-               ccdc_try_format(ccdc, fh, CCDC_PAD_SOURCE_OF, format,
+               ccdc_try_format(ccdc, cfg, CCDC_PAD_SOURCE_OF, format,
                                fmt->which);
 
-               format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SOURCE_VP,
+               format = __ccdc_get_format(ccdc, cfg, CCDC_PAD_SOURCE_VP,
                                           fmt->which);
                *format = fmt->format;
-               ccdc_try_format(ccdc, fh, CCDC_PAD_SOURCE_VP, format,
+               ccdc_try_format(ccdc, cfg, CCDC_PAD_SOURCE_VP, format,
                                fmt->which);
        }
 
@@ -2417,11 +2417,11 @@ static int ccdc_link_validate(struct v4l2_subdev *sd,
 
        /* We've got a parallel sensor here. */
        if (ccdc->input == CCDC_INPUT_PARALLEL) {
-               struct isp_parallel_platform_data *pdata =
-                       &((struct isp_v4l2_subdevs_group *)
+               struct isp_parallel_cfg *parcfg =
+                       &((struct isp_bus_cfg *)
                          media_entity_to_v4l2_subdev(link->source->entity)
                          ->host_priv)->bus.parallel;
-               parallel_shift = pdata->data_lane_shift * 2;
+               parallel_shift = parcfg->data_lane_shift * 2;
        } else {
                parallel_shift = 0;
        }
@@ -2453,7 +2453,7 @@ static int ccdc_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
        format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
        format.format.width = 4096;
        format.format.height = 4096;
-       ccdc_set_format(sd, fh, &format);
+       ccdc_set_format(sd, fh ? fh->pad : NULL, &format);
 
        return 0;
 }
index f4aedb37e41e2b97f6e3defca64270fd40df7dab..38e6a974c5b1e8cd58ae6263d936ea0c42d791e4 100644 (file)
@@ -201,14 +201,14 @@ static void ccp2_mem_enable(struct isp_ccp2_device *ccp2, u8 enable)
 /*
  * ccp2_phyif_config - Initialize CCP2 phy interface config
  * @ccp2: Pointer to ISP CCP2 device
- * @pdata: CCP2 platform data
+ * @buscfg: CCP2 platform data
  *
  * Configure the CCP2 physical interface module from platform data.
  *
  * Returns -EIO if strobe is chosen in CSI1 mode, or 0 on success.
  */
 static int ccp2_phyif_config(struct isp_ccp2_device *ccp2,
-                            const struct isp_ccp2_platform_data *pdata)
+                            const struct isp_ccp2_cfg *buscfg)
 {
        struct isp_device *isp = to_isp_device(ccp2);
        u32 val;
@@ -218,16 +218,16 @@ static int ccp2_phyif_config(struct isp_ccp2_device *ccp2,
                            ISPCCP2_CTRL_IO_OUT_SEL | ISPCCP2_CTRL_MODE;
        /* Data/strobe physical layer */
        BIT_SET(val, ISPCCP2_CTRL_PHY_SEL_SHIFT, ISPCCP2_CTRL_PHY_SEL_MASK,
-               pdata->phy_layer);
+               buscfg->phy_layer);
        BIT_SET(val, ISPCCP2_CTRL_INV_SHIFT, ISPCCP2_CTRL_INV_MASK,
-               pdata->strobe_clk_pol);
+               buscfg->strobe_clk_pol);
        isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL);
 
        val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL);
        if (!(val & ISPCCP2_CTRL_MODE)) {
-               if (pdata->ccp2_mode == ISP_CCP2_MODE_CCP2)
+               if (buscfg->ccp2_mode == ISP_CCP2_MODE_CCP2)
                        dev_warn(isp->dev, "OMAP3 CCP2 bus not available\n");
-               if (pdata->phy_layer == ISP_CCP2_PHY_DATA_STROBE)
+               if (buscfg->phy_layer == ISP_CCP2_PHY_DATA_STROBE)
                        /* Strobe mode requires CCP2 */
                        return -EIO;
        }
@@ -347,7 +347,7 @@ static void ccp2_lcx_config(struct isp_ccp2_device *ccp2,
  */
 static int ccp2_if_configure(struct isp_ccp2_device *ccp2)
 {
-       const struct isp_v4l2_subdevs_group *pdata;
+       const struct isp_bus_cfg *buscfg;
        struct v4l2_mbus_framefmt *format;
        struct media_pad *pad;
        struct v4l2_subdev *sensor;
@@ -358,20 +358,20 @@ static int ccp2_if_configure(struct isp_ccp2_device *ccp2)
 
        pad = media_entity_remote_pad(&ccp2->pads[CCP2_PAD_SINK]);
        sensor = media_entity_to_v4l2_subdev(pad->entity);
-       pdata = sensor->host_priv;
+       buscfg = sensor->host_priv;
 
-       ret = ccp2_phyif_config(ccp2, &pdata->bus.ccp2);
+       ret = ccp2_phyif_config(ccp2, &buscfg->bus.ccp2);
        if (ret < 0)
                return ret;
 
-       ccp2_vp_config(ccp2, pdata->bus.ccp2.vpclk_div + 1);
+       ccp2_vp_config(ccp2, buscfg->bus.ccp2.vpclk_div + 1);
 
        v4l2_subdev_call(sensor, sensor, g_skip_top_lines, &lines);
 
        format = &ccp2->formats[CCP2_PAD_SINK];
 
        ccp2->if_cfg.data_start = lines;
-       ccp2->if_cfg.crc = pdata->bus.ccp2.crc;
+       ccp2->if_cfg.crc = buscfg->bus.ccp2.crc;
        ccp2->if_cfg.format = format->code;
        ccp2->if_cfg.data_size = format->height;
 
@@ -611,17 +611,17 @@ static const unsigned int ccp2_fmts[] = {
 /*
  * __ccp2_get_format - helper function for getting ccp2 format
  * @ccp2  : Pointer to ISP CCP2 device
- * @fh    : V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad configuration
  * @pad   : pad number
  * @which : wanted subdev format
  * return format structure or NULL on error
  */
 static struct v4l2_mbus_framefmt *
-__ccp2_get_format(struct isp_ccp2_device *ccp2, struct v4l2_subdev_fh *fh,
+__ccp2_get_format(struct isp_ccp2_device *ccp2, struct v4l2_subdev_pad_config *cfg,
                     unsigned int pad, enum v4l2_subdev_format_whence which)
 {
        if (which == V4L2_SUBDEV_FORMAT_TRY)
-               return v4l2_subdev_get_try_format(fh, pad);
+               return v4l2_subdev_get_try_format(&ccp2->subdev, cfg, pad);
        else
                return &ccp2->formats[pad];
 }
@@ -629,13 +629,13 @@ __ccp2_get_format(struct isp_ccp2_device *ccp2, struct v4l2_subdev_fh *fh,
 /*
  * ccp2_try_format - Handle try format by pad subdev method
  * @ccp2  : Pointer to ISP CCP2 device
- * @fh    : V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad configuration
  * @pad   : pad num
  * @fmt   : pointer to v4l2 mbus format structure
  * @which : wanted subdev format
  */
 static void ccp2_try_format(struct isp_ccp2_device *ccp2,
-                              struct v4l2_subdev_fh *fh, unsigned int pad,
+                              struct v4l2_subdev_pad_config *cfg, unsigned int pad,
                               struct v4l2_mbus_framefmt *fmt,
                               enum v4l2_subdev_format_whence which)
 {
@@ -669,7 +669,7 @@ static void ccp2_try_format(struct isp_ccp2_device *ccp2,
                 * When CCP2 write to memory feature will be added this
                 * should be changed properly.
                 */
-               format = __ccp2_get_format(ccp2, fh, CCP2_PAD_SINK, which);
+               format = __ccp2_get_format(ccp2, cfg, CCP2_PAD_SINK, which);
                memcpy(fmt, format, sizeof(*fmt));
                fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
                break;
@@ -682,12 +682,12 @@ static void ccp2_try_format(struct isp_ccp2_device *ccp2,
 /*
  * ccp2_enum_mbus_code - Handle pixel format enumeration
  * @sd     : pointer to v4l2 subdev structure
- * @fh     : V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad configuration
  * @code   : pointer to v4l2_subdev_mbus_code_enum structure
  * return -EINVAL or zero on success
  */
 static int ccp2_enum_mbus_code(struct v4l2_subdev *sd,
-                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_pad_config *cfg,
                                  struct v4l2_subdev_mbus_code_enum *code)
 {
        struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
@@ -702,8 +702,8 @@ static int ccp2_enum_mbus_code(struct v4l2_subdev *sd,
                if (code->index != 0)
                        return -EINVAL;
 
-               format = __ccp2_get_format(ccp2, fh, CCP2_PAD_SINK,
-                                             V4L2_SUBDEV_FORMAT_TRY);
+               format = __ccp2_get_format(ccp2, cfg, CCP2_PAD_SINK,
+                                             code->which);
                code->code = format->code;
        }
 
@@ -711,7 +711,7 @@ static int ccp2_enum_mbus_code(struct v4l2_subdev *sd,
 }
 
 static int ccp2_enum_frame_size(struct v4l2_subdev *sd,
-                                  struct v4l2_subdev_fh *fh,
+                                  struct v4l2_subdev_pad_config *cfg,
                                   struct v4l2_subdev_frame_size_enum *fse)
 {
        struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
@@ -723,7 +723,7 @@ static int ccp2_enum_frame_size(struct v4l2_subdev *sd,
        format.code = fse->code;
        format.width = 1;
        format.height = 1;
-       ccp2_try_format(ccp2, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+       ccp2_try_format(ccp2, cfg, fse->pad, &format, fse->which);
        fse->min_width = format.width;
        fse->min_height = format.height;
 
@@ -733,7 +733,7 @@ static int ccp2_enum_frame_size(struct v4l2_subdev *sd,
        format.code = fse->code;
        format.width = -1;
        format.height = -1;
-       ccp2_try_format(ccp2, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+       ccp2_try_format(ccp2, cfg, fse->pad, &format, fse->which);
        fse->max_width = format.width;
        fse->max_height = format.height;
 
@@ -743,17 +743,17 @@ static int ccp2_enum_frame_size(struct v4l2_subdev *sd,
 /*
  * ccp2_get_format - Handle get format by pads subdev method
  * @sd    : pointer to v4l2 subdev structure
- * @fh    : V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad configuration
  * @fmt   : pointer to v4l2 subdev format structure
  * return -EINVAL or zero on success
  */
-static int ccp2_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int ccp2_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_format *fmt)
 {
        struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
        struct v4l2_mbus_framefmt *format;
 
-       format = __ccp2_get_format(ccp2, fh, fmt->pad, fmt->which);
+       format = __ccp2_get_format(ccp2, cfg, fmt->pad, fmt->which);
        if (format == NULL)
                return -EINVAL;
 
@@ -764,29 +764,29 @@ static int ccp2_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 /*
  * ccp2_set_format - Handle set format by pads subdev method
  * @sd    : pointer to v4l2 subdev structure
- * @fh    : V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad configuration
  * @fmt   : pointer to v4l2 subdev format structure
  * returns zero
  */
-static int ccp2_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int ccp2_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_format *fmt)
 {
        struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
        struct v4l2_mbus_framefmt *format;
 
-       format = __ccp2_get_format(ccp2, fh, fmt->pad, fmt->which);
+       format = __ccp2_get_format(ccp2, cfg, fmt->pad, fmt->which);
        if (format == NULL)
                return -EINVAL;
 
-       ccp2_try_format(ccp2, fh, fmt->pad, &fmt->format, fmt->which);
+       ccp2_try_format(ccp2, cfg, fmt->pad, &fmt->format, fmt->which);
        *format = fmt->format;
 
        /* Propagate the format from sink to source */
        if (fmt->pad == CCP2_PAD_SINK) {
-               format = __ccp2_get_format(ccp2, fh, CCP2_PAD_SOURCE,
+               format = __ccp2_get_format(ccp2, cfg, CCP2_PAD_SOURCE,
                                           fmt->which);
                *format = fmt->format;
-               ccp2_try_format(ccp2, fh, CCP2_PAD_SOURCE, format, fmt->which);
+               ccp2_try_format(ccp2, cfg, CCP2_PAD_SOURCE, format, fmt->which);
        }
 
        return 0;
@@ -811,7 +811,7 @@ static int ccp2_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
        format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
        format.format.width = 4096;
        format.format.height = 4096;
-       ccp2_set_format(sd, fh, &format);
+       ccp2_set_format(sd, fh ? fh->pad : NULL, &format);
 
        return 0;
 }
index 09c686d96ae8ac25792658a228aeff257625c468..a78338d012b4df76cea20b0ff882c62a2d28edf0 100644 (file)
@@ -548,7 +548,8 @@ int omap3isp_csi2_reset(struct isp_csi2_device *csi2)
 
 static int csi2_configure(struct isp_csi2_device *csi2)
 {
-       const struct isp_v4l2_subdevs_group *pdata;
+       struct isp_pipeline *pipe = to_isp_pipeline(&csi2->subdev.entity);
+       const struct isp_bus_cfg *buscfg;
        struct isp_device *isp = csi2->isp;
        struct isp_csi2_timing_cfg *timing = &csi2->timing[0];
        struct v4l2_subdev *sensor;
@@ -565,14 +566,19 @@ static int csi2_configure(struct isp_csi2_device *csi2)
 
        pad = media_entity_remote_pad(&csi2->pads[CSI2_PAD_SINK]);
        sensor = media_entity_to_v4l2_subdev(pad->entity);
-       pdata = sensor->host_priv;
+       buscfg = sensor->host_priv;
 
        csi2->frame_skip = 0;
        v4l2_subdev_call(sensor, sensor, g_skip_frames, &csi2->frame_skip);
 
-       csi2->ctrl.vp_out_ctrl = pdata->bus.csi2.vpclk_div;
+       csi2->ctrl.vp_out_ctrl =
+               clamp_t(unsigned int, pipe->l3_ick / pipe->external_rate - 1,
+                       1, 3);
+       dev_dbg(isp->dev, "%s: l3_ick %lu, external_rate %u, vp_out_ctrl %u\n",
+               __func__, pipe->l3_ick,  pipe->external_rate,
+               csi2->ctrl.vp_out_ctrl);
        csi2->ctrl.frame_mode = ISP_CSI2_FRAME_IMMEDIATE;
-       csi2->ctrl.ecc_enable = pdata->bus.csi2.crc;
+       csi2->ctrl.ecc_enable = buscfg->bus.csi2.crc;
 
        timing->ionum = 1;
        timing->force_rx_mode = 1;
@@ -829,17 +835,17 @@ static const struct isp_video_operations csi2_ispvideo_ops = {
  */
 
 static struct v4l2_mbus_framefmt *
-__csi2_get_format(struct isp_csi2_device *csi2, struct v4l2_subdev_fh *fh,
+__csi2_get_format(struct isp_csi2_device *csi2, struct v4l2_subdev_pad_config *cfg,
                  unsigned int pad, enum v4l2_subdev_format_whence which)
 {
        if (which == V4L2_SUBDEV_FORMAT_TRY)
-               return v4l2_subdev_get_try_format(fh, pad);
+               return v4l2_subdev_get_try_format(&csi2->subdev, cfg, pad);
        else
                return &csi2->formats[pad];
 }
 
 static void
-csi2_try_format(struct isp_csi2_device *csi2, struct v4l2_subdev_fh *fh,
+csi2_try_format(struct isp_csi2_device *csi2, struct v4l2_subdev_pad_config *cfg,
                unsigned int pad, struct v4l2_mbus_framefmt *fmt,
                enum v4l2_subdev_format_whence which)
 {
@@ -869,7 +875,7 @@ csi2_try_format(struct isp_csi2_device *csi2, struct v4l2_subdev_fh *fh,
                 * compression.
                 */
                pixelcode = fmt->code;
-               format = __csi2_get_format(csi2, fh, CSI2_PAD_SINK, which);
+               format = __csi2_get_format(csi2, cfg, CSI2_PAD_SINK, which);
                memcpy(fmt, format, sizeof(*fmt));
 
                /*
@@ -890,12 +896,12 @@ csi2_try_format(struct isp_csi2_device *csi2, struct v4l2_subdev_fh *fh,
 /*
  * csi2_enum_mbus_code - Handle pixel format enumeration
  * @sd     : pointer to v4l2 subdev structure
- * @fh     : V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad configuration
  * @code   : pointer to v4l2_subdev_mbus_code_enum structure
  * return -EINVAL or zero on success
  */
 static int csi2_enum_mbus_code(struct v4l2_subdev *sd,
-                              struct v4l2_subdev_fh *fh,
+                              struct v4l2_subdev_pad_config *cfg,
                               struct v4l2_subdev_mbus_code_enum *code)
 {
        struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd);
@@ -908,8 +914,8 @@ static int csi2_enum_mbus_code(struct v4l2_subdev *sd,
 
                code->code = csi2_input_fmts[code->index];
        } else {
-               format = __csi2_get_format(csi2, fh, CSI2_PAD_SINK,
-                                          V4L2_SUBDEV_FORMAT_TRY);
+               format = __csi2_get_format(csi2, cfg, CSI2_PAD_SINK,
+                                          code->which);
                switch (code->index) {
                case 0:
                        /* Passthrough sink pad code */
@@ -932,7 +938,7 @@ static int csi2_enum_mbus_code(struct v4l2_subdev *sd,
 }
 
 static int csi2_enum_frame_size(struct v4l2_subdev *sd,
-                               struct v4l2_subdev_fh *fh,
+                               struct v4l2_subdev_pad_config *cfg,
                                struct v4l2_subdev_frame_size_enum *fse)
 {
        struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd);
@@ -944,7 +950,7 @@ static int csi2_enum_frame_size(struct v4l2_subdev *sd,
        format.code = fse->code;
        format.width = 1;
        format.height = 1;
-       csi2_try_format(csi2, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+       csi2_try_format(csi2, cfg, fse->pad, &format, fse->which);
        fse->min_width = format.width;
        fse->min_height = format.height;
 
@@ -954,7 +960,7 @@ static int csi2_enum_frame_size(struct v4l2_subdev *sd,
        format.code = fse->code;
        format.width = -1;
        format.height = -1;
-       csi2_try_format(csi2, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+       csi2_try_format(csi2, cfg, fse->pad, &format, fse->which);
        fse->max_width = format.width;
        fse->max_height = format.height;
 
@@ -964,17 +970,17 @@ static int csi2_enum_frame_size(struct v4l2_subdev *sd,
 /*
  * csi2_get_format - Handle get format by pads subdev method
  * @sd : pointer to v4l2 subdev structure
- * @fh : V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad configuration
  * @fmt: pointer to v4l2 subdev format structure
  * return -EINVAL or zero on success
  */
-static int csi2_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int csi2_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                           struct v4l2_subdev_format *fmt)
 {
        struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd);
        struct v4l2_mbus_framefmt *format;
 
-       format = __csi2_get_format(csi2, fh, fmt->pad, fmt->which);
+       format = __csi2_get_format(csi2, cfg, fmt->pad, fmt->which);
        if (format == NULL)
                return -EINVAL;
 
@@ -985,29 +991,29 @@ static int csi2_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 /*
  * csi2_set_format - Handle set format by pads subdev method
  * @sd : pointer to v4l2 subdev structure
- * @fh : V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad configuration
  * @fmt: pointer to v4l2 subdev format structure
  * return -EINVAL or zero on success
  */
-static int csi2_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int csi2_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                           struct v4l2_subdev_format *fmt)
 {
        struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd);
        struct v4l2_mbus_framefmt *format;
 
-       format = __csi2_get_format(csi2, fh, fmt->pad, fmt->which);
+       format = __csi2_get_format(csi2, cfg, fmt->pad, fmt->which);
        if (format == NULL)
                return -EINVAL;
 
-       csi2_try_format(csi2, fh, fmt->pad, &fmt->format, fmt->which);
+       csi2_try_format(csi2, cfg, fmt->pad, &fmt->format, fmt->which);
        *format = fmt->format;
 
        /* Propagate the format from sink to source */
        if (fmt->pad == CSI2_PAD_SINK) {
-               format = __csi2_get_format(csi2, fh, CSI2_PAD_SOURCE,
+               format = __csi2_get_format(csi2, cfg, CSI2_PAD_SOURCE,
                                           fmt->which);
                *format = fmt->format;
-               csi2_try_format(csi2, fh, CSI2_PAD_SOURCE, format, fmt->which);
+               csi2_try_format(csi2, cfg, CSI2_PAD_SOURCE, format, fmt->which);
        }
 
        return 0;
@@ -1032,7 +1038,7 @@ static int csi2_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
        format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
        format.format.width = 4096;
        format.format.height = 4096;
-       csi2_set_format(sd, fh, &format);
+       csi2_set_format(sd, fh ? fh->pad : NULL, &format);
 
        return 0;
 }
index e033f2237a72f4383236556d984b6bd773b3832d..495447d66cfddb0a5b7785c1a6f5ba12c0fe3a42 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/delay.h>
 #include <linux/device.h>
+#include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 
 #include "isp.h"
@@ -26,10 +27,11 @@ static void csiphy_routing_cfg_3630(struct isp_csiphy *phy,
                                    enum isp_interface_type iface,
                                    bool ccp2_strobe)
 {
-       u32 reg = isp_reg_readl(
-               phy->isp, OMAP3_ISP_IOMEM_3630_CONTROL_CAMERA_PHY_CTRL, 0);
+       u32 reg;
        u32 shift, mode;
 
+       regmap_read(phy->isp->syscon, phy->isp->syscon_offset, &reg);
+
        switch (iface) {
        default:
        /* Should not happen in practice, but let's keep the compiler happy. */
@@ -63,8 +65,7 @@ static void csiphy_routing_cfg_3630(struct isp_csiphy *phy,
        reg &= ~(OMAP3630_CONTROL_CAMERA_PHY_CTRL_CAMMODE_MASK << shift);
        reg |= mode << shift;
 
-       isp_reg_writel(phy->isp, reg,
-                      OMAP3_ISP_IOMEM_3630_CONTROL_CAMERA_PHY_CTRL, 0);
+       regmap_write(phy->isp->syscon, phy->isp->syscon_offset, reg);
 }
 
 static void csiphy_routing_cfg_3430(struct isp_csiphy *phy, u32 iface, bool on,
@@ -78,16 +79,14 @@ static void csiphy_routing_cfg_3430(struct isp_csiphy *phy, u32 iface, bool on,
                return;
 
        if (!on) {
-               isp_reg_writel(phy->isp, 0,
-                              OMAP3_ISP_IOMEM_343X_CONTROL_CSIRXFE, 0);
+               regmap_write(phy->isp->syscon, phy->isp->syscon_offset, 0);
                return;
        }
 
        if (ccp2_strobe)
                csirxfe |= OMAP343X_CONTROL_CSIRXFE_SELFORM;
 
-       isp_reg_writel(phy->isp, csirxfe,
-                      OMAP3_ISP_IOMEM_343X_CONTROL_CSIRXFE, 0);
+       regmap_write(phy->isp->syscon, phy->isp->syscon_offset, csirxfe);
 }
 
 /*
@@ -106,10 +105,9 @@ static void csiphy_routing_cfg(struct isp_csiphy *phy,
                               enum isp_interface_type iface, bool on,
                               bool ccp2_strobe)
 {
-       if (phy->isp->mmio_base[OMAP3_ISP_IOMEM_3630_CONTROL_CAMERA_PHY_CTRL]
-           && on)
+       if (phy->isp->phy_type == ISP_PHY_TYPE_3630 && on)
                return csiphy_routing_cfg_3630(phy, iface, ccp2_strobe);
-       if (phy->isp->mmio_base[OMAP3_ISP_IOMEM_343X_CONTROL_CSIRXFE])
+       if (phy->isp->phy_type == ISP_PHY_TYPE_3430)
                return csiphy_routing_cfg_3430(phy, iface, on, ccp2_strobe);
 }
 
@@ -168,18 +166,25 @@ static int omap3isp_csiphy_config(struct isp_csiphy *phy)
 {
        struct isp_csi2_device *csi2 = phy->csi2;
        struct isp_pipeline *pipe = to_isp_pipeline(&csi2->subdev.entity);
-       struct isp_v4l2_subdevs_group *subdevs = pipe->external->host_priv;
+       struct isp_bus_cfg *buscfg = pipe->external->host_priv;
        struct isp_csiphy_lanes_cfg *lanes;
        int csi2_ddrclk_khz;
        unsigned int used_lanes = 0;
        unsigned int i;
        u32 reg;
 
-       if (subdevs->interface == ISP_INTERFACE_CCP2B_PHY1
-           || subdevs->interface == ISP_INTERFACE_CCP2B_PHY2)
-               lanes = &subdevs->bus.ccp2.lanecfg;
+       if (!buscfg) {
+               struct isp_async_subdev *isd =
+                       container_of(pipe->external->asd,
+                                    struct isp_async_subdev, asd);
+               buscfg = &isd->bus;
+       }
+
+       if (buscfg->interface == ISP_INTERFACE_CCP2B_PHY1
+           || buscfg->interface == ISP_INTERFACE_CCP2B_PHY2)
+               lanes = &buscfg->bus.ccp2.lanecfg;
        else
-               lanes = &subdevs->bus.csi2.lanecfg;
+               lanes = &buscfg->bus.csi2.lanecfg;
 
        /* Clock and data lanes verification */
        for (i = 0; i < phy->num_data_lanes; i++) {
@@ -203,8 +208,8 @@ static int omap3isp_csiphy_config(struct isp_csiphy *phy)
         * issue since the MPU power domain is forced on whilst the
         * ISP is in use.
         */
-       csiphy_routing_cfg(phy, subdevs->interface, true,
-                          subdevs->bus.ccp2.phy_layer);
+       csiphy_routing_cfg(phy, buscfg->interface, true,
+                          buscfg->bus.ccp2.phy_layer);
 
        /* DPHY timing configuration */
        /* CSI-2 is DDR and we only count used lanes. */
@@ -302,11 +307,10 @@ void omap3isp_csiphy_release(struct isp_csiphy *phy)
                struct isp_csi2_device *csi2 = phy->csi2;
                struct isp_pipeline *pipe =
                        to_isp_pipeline(&csi2->subdev.entity);
-               struct isp_v4l2_subdevs_group *subdevs =
-                       pipe->external->host_priv;
+               struct isp_bus_cfg *buscfg = pipe->external->host_priv;
 
-               csiphy_routing_cfg(phy, subdevs->interface, false,
-                                  subdevs->bus.ccp2.phy_layer);
+               csiphy_routing_cfg(phy, buscfg->interface, false,
+                                  buscfg->bus.ccp2.phy_layer);
                csiphy_power_autoswitch_enable(phy, false);
                csiphy_set_power(phy, ISPCSI2_PHY_CFG_PWR_CMD_OFF);
                regulator_disable(phy->vdd);
index b208c5417146e081facc8675f345f221e346f567..ccaf92f39236c9d43a3ccd549b1e7a98492c0a03 100644 (file)
@@ -297,7 +297,6 @@ int omap3isp_h3a_aewb_init(struct isp_device *isp)
 
        aewb->ops = &h3a_aewb_ops;
        aewb->priv = aewb_cfg;
-       aewb->dma_ch = -1;
        aewb->event_type = V4L2_EVENT_OMAP3ISP_AEWB;
        aewb->isp = isp;
 
index 8a83e195f3e30443dc914a4d10dc12edc90f02a9..92937f7eeceff799c8ba79f4dd59b2579ab97203 100644 (file)
@@ -360,7 +360,6 @@ int omap3isp_h3a_af_init(struct isp_device *isp)
 
        af->ops = &h3a_af_ops;
        af->priv = af_cfg;
-       af->dma_ch = -1;
        af->event_type = V4L2_EVENT_OMAP3ISP_AF;
        af->isp = isp;
 
index ce822c34c843a7d9c92c020ccd9d19526ac32af1..7138b043a4aa8eec4c373a8eb4ddbdd093ad5433 100644 (file)
  */
 
 #include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dmaengine.h>
+#include <linux/omap-dmaengine.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
-#include <linux/device.h>
 
 #include "isp.h"
 #include "ispreg.h"
 #include "isphist.h"
 
-#define OMAP24XX_DMA_NO_DEVICE         0
-
 #define HIST_CONFIG_DMA        1
 
-#define HIST_USING_DMA(hist) ((hist)->dma_ch >= 0)
-
 /*
  * hist_reset_mem - clear Histogram memory before start stats engine.
  */
@@ -62,20 +60,6 @@ static void hist_reset_mem(struct ispstat *hist)
        hist->wait_acc_frames = conf->num_acc_frames;
 }
 
-static void hist_dma_config(struct ispstat *hist)
-{
-       struct isp_device *isp = hist->isp;
-
-       hist->dma_config.data_type = OMAP_DMA_DATA_TYPE_S32;
-       hist->dma_config.sync_mode = OMAP_DMA_SYNC_ELEMENT;
-       hist->dma_config.frame_count = 1;
-       hist->dma_config.src_amode = OMAP_DMA_AMODE_CONSTANT;
-       hist->dma_config.src_start = isp->mmio_base_phys[OMAP3_ISP_IOMEM_HIST]
-                                  + ISPHIST_DATA;
-       hist->dma_config.dst_amode = OMAP_DMA_AMODE_POST_INC;
-       hist->dma_config.src_or_dst_synch = OMAP_DMA_SRC_SYNC;
-}
-
 /*
  * hist_setup_regs - Helper function to update Histogram registers.
  */
@@ -176,17 +160,12 @@ static int hist_busy(struct ispstat *hist)
                                                & ISPHIST_PCR_BUSY;
 }
 
-static void hist_dma_cb(int lch, u16 ch_status, void *data)
+static void hist_dma_cb(void *data)
 {
        struct ispstat *hist = data;
 
-       if (ch_status & ~OMAP_DMA_BLOCK_IRQ) {
-               dev_dbg(hist->isp->dev, "hist: DMA error. status = 0x%04x\n",
-                       ch_status);
-               omap_stop_dma(lch);
-               hist_reset_mem(hist);
-               atomic_set(&hist->buf_err, 1);
-       }
+       /* FIXME: The DMA engine API can't report transfer errors :-/ */
+
        isp_reg_clr(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT,
                    ISPHIST_CNT_CLEAR);
 
@@ -198,24 +177,57 @@ static void hist_dma_cb(int lch, u16 ch_status, void *data)
 static int hist_buf_dma(struct ispstat *hist)
 {
        dma_addr_t dma_addr = hist->active_buf->dma_addr;
+       struct dma_async_tx_descriptor *tx;
+       struct dma_slave_config cfg;
+       dma_cookie_t cookie;
+       int ret;
 
        if (unlikely(!dma_addr)) {
                dev_dbg(hist->isp->dev, "hist: invalid DMA buffer address\n");
-               hist_reset_mem(hist);
-               return STAT_NO_BUF;
+               goto error;
        }
 
        isp_reg_writel(hist->isp, 0, OMAP3_ISP_IOMEM_HIST, ISPHIST_ADDR);
        isp_reg_set(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT,
                    ISPHIST_CNT_CLEAR);
        omap3isp_flush(hist->isp);
-       hist->dma_config.dst_start = dma_addr;
-       hist->dma_config.elem_count = hist->buf_size / sizeof(u32);
-       omap_set_dma_params(hist->dma_ch, &hist->dma_config);
 
-       omap_start_dma(hist->dma_ch);
+       memset(&cfg, 0, sizeof(cfg));
+       cfg.src_addr = hist->isp->mmio_hist_base_phys + ISPHIST_DATA;
+       cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+       cfg.src_maxburst = hist->buf_size / 4;
+
+       ret = dmaengine_slave_config(hist->dma_ch, &cfg);
+       if (ret < 0) {
+               dev_dbg(hist->isp->dev,
+                       "hist: DMA slave configuration failed\n");
+               goto error;
+       }
+
+       tx = dmaengine_prep_slave_single(hist->dma_ch, dma_addr,
+                                        hist->buf_size, DMA_DEV_TO_MEM,
+                                        DMA_CTRL_ACK);
+       if (tx == NULL) {
+               dev_dbg(hist->isp->dev,
+                       "hist: DMA slave preparation failed\n");
+               goto error;
+       }
+
+       tx->callback = hist_dma_cb;
+       tx->callback_param = hist;
+       cookie = tx->tx_submit(tx);
+       if (dma_submit_error(cookie)) {
+               dev_dbg(hist->isp->dev, "hist: DMA submission failed\n");
+               goto error;
+       }
+
+       dma_async_issue_pending(hist->dma_ch);
 
        return STAT_BUF_WAITING_DMA;
+
+error:
+       hist_reset_mem(hist);
+       return STAT_NO_BUF;
 }
 
 static int hist_buf_pio(struct ispstat *hist)
@@ -272,7 +284,7 @@ static int hist_buf_process(struct ispstat *hist)
        if (--(hist->wait_acc_frames))
                return STAT_NO_BUF;
 
-       if (HIST_USING_DMA(hist))
+       if (hist->dma_ch)
                ret = hist_buf_dma(hist);
        else
                ret = hist_buf_pio(hist);
@@ -473,18 +485,28 @@ int omap3isp_hist_init(struct isp_device *isp)
 
        hist->isp = isp;
 
-       if (HIST_CONFIG_DMA)
-               ret = omap_request_dma(OMAP24XX_DMA_NO_DEVICE, "DMA_ISP_HIST",
-                                      hist_dma_cb, hist, &hist->dma_ch);
-       if (ret) {
-               if (HIST_CONFIG_DMA)
-                       dev_warn(isp->dev, "hist: DMA request channel failed. "
-                                          "Using PIO only.\n");
-               hist->dma_ch = -1;
-       } else {
-               dev_dbg(isp->dev, "hist: DMA channel = %d\n", hist->dma_ch);
-               hist_dma_config(hist);
-               omap_enable_dma_irq(hist->dma_ch, OMAP_DMA_BLOCK_IRQ);
+       if (HIST_CONFIG_DMA) {
+               struct platform_device *pdev = to_platform_device(isp->dev);
+               struct resource *res;
+               unsigned int sig = 0;
+               dma_cap_mask_t mask;
+
+               dma_cap_zero(mask);
+               dma_cap_set(DMA_SLAVE, mask);
+
+               res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
+                                                  "hist");
+               if (res)
+                       sig = res->start;
+
+               hist->dma_ch = dma_request_slave_channel_compat(mask,
+                               omap_dma_filter_fn, &sig, isp->dev, "hist");
+               if (!hist->dma_ch)
+                       dev_warn(isp->dev,
+                                "hist: DMA channel request failed, using PIO\n");
+               else
+                       dev_dbg(isp->dev, "hist: using DMA channel %s\n",
+                               dma_chan_name(hist->dma_ch));
        }
 
        hist->ops = &hist_ops;
@@ -493,8 +515,8 @@ int omap3isp_hist_init(struct isp_device *isp)
 
        ret = omap3isp_stat_init(hist, "histogram", &hist_subdev_ops);
        if (ret) {
-               if (HIST_USING_DMA(hist))
-                       omap_free_dma(hist->dma_ch);
+               if (hist->dma_ch)
+                       dma_release_channel(hist->dma_ch);
        }
 
        return ret;
@@ -505,7 +527,10 @@ int omap3isp_hist_init(struct isp_device *isp)
  */
 void omap3isp_hist_cleanup(struct isp_device *isp)
 {
-       if (HIST_USING_DMA(&isp->isp_hist))
-               omap_free_dma(isp->isp_hist.dma_ch);
-       omap3isp_stat_cleanup(&isp->isp_hist);
+       struct ispstat *hist = &isp->isp_hist;
+
+       if (hist->dma_ch)
+               dma_release_channel(hist->dma_ch);
+
+       omap3isp_stat_cleanup(hist);
 }
index dd9eed45d853d74c5f37a8e743acd46b15b46572..15cb254ccc39df0eba6b3f07d5e68e2245ae182b 100644 (file)
@@ -1686,21 +1686,21 @@ static int preview_set_stream(struct v4l2_subdev *sd, int enable)
 }
 
 static struct v4l2_mbus_framefmt *
-__preview_get_format(struct isp_prev_device *prev, struct v4l2_subdev_fh *fh,
+__preview_get_format(struct isp_prev_device *prev, struct v4l2_subdev_pad_config *cfg,
                     unsigned int pad, enum v4l2_subdev_format_whence which)
 {
        if (which == V4L2_SUBDEV_FORMAT_TRY)
-               return v4l2_subdev_get_try_format(fh, pad);
+               return v4l2_subdev_get_try_format(&prev->subdev, cfg, pad);
        else
                return &prev->formats[pad];
 }
 
 static struct v4l2_rect *
-__preview_get_crop(struct isp_prev_device *prev, struct v4l2_subdev_fh *fh,
+__preview_get_crop(struct isp_prev_device *prev, struct v4l2_subdev_pad_config *cfg,
                   enum v4l2_subdev_format_whence which)
 {
        if (which == V4L2_SUBDEV_FORMAT_TRY)
-               return v4l2_subdev_get_try_crop(fh, PREV_PAD_SINK);
+               return v4l2_subdev_get_try_crop(&prev->subdev, cfg, PREV_PAD_SINK);
        else
                return &prev->crop;
 }
@@ -1727,7 +1727,7 @@ static const unsigned int preview_output_fmts[] = {
 /*
  * preview_try_format - Validate a format
  * @prev: ISP preview engine
- * @fh: V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad configuration
  * @pad: pad number
  * @fmt: format to be validated
  * @which: try/active format selector
@@ -1736,7 +1736,7 @@ static const unsigned int preview_output_fmts[] = {
  * engine limits and the format and crop rectangles on other pads.
  */
 static void preview_try_format(struct isp_prev_device *prev,
-                              struct v4l2_subdev_fh *fh, unsigned int pad,
+                              struct v4l2_subdev_pad_config *cfg, unsigned int pad,
                               struct v4l2_mbus_framefmt *fmt,
                               enum v4l2_subdev_format_whence which)
 {
@@ -1777,7 +1777,7 @@ static void preview_try_format(struct isp_prev_device *prev,
 
        case PREV_PAD_SOURCE:
                pixelcode = fmt->code;
-               *fmt = *__preview_get_format(prev, fh, PREV_PAD_SINK, which);
+               *fmt = *__preview_get_format(prev, cfg, PREV_PAD_SINK, which);
 
                switch (pixelcode) {
                case MEDIA_BUS_FMT_YUYV8_1X16:
@@ -1795,7 +1795,7 @@ static void preview_try_format(struct isp_prev_device *prev,
                 * is not supported yet, hardcode the output size to the crop
                 * rectangle size.
                 */
-               crop = __preview_get_crop(prev, fh, which);
+               crop = __preview_get_crop(prev, cfg, which);
                fmt->width = crop->width;
                fmt->height = crop->height;
 
@@ -1864,12 +1864,12 @@ static void preview_try_crop(struct isp_prev_device *prev,
 /*
  * preview_enum_mbus_code - Handle pixel format enumeration
  * @sd     : pointer to v4l2 subdev structure
- * @fh     : V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad configuration
  * @code   : pointer to v4l2_subdev_mbus_code_enum structure
  * return -EINVAL or zero on success
  */
 static int preview_enum_mbus_code(struct v4l2_subdev *sd,
-                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_pad_config *cfg,
                                  struct v4l2_subdev_mbus_code_enum *code)
 {
        switch (code->pad) {
@@ -1893,7 +1893,7 @@ static int preview_enum_mbus_code(struct v4l2_subdev *sd,
 }
 
 static int preview_enum_frame_size(struct v4l2_subdev *sd,
-                                  struct v4l2_subdev_fh *fh,
+                                  struct v4l2_subdev_pad_config *cfg,
                                   struct v4l2_subdev_frame_size_enum *fse)
 {
        struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
@@ -1905,7 +1905,7 @@ static int preview_enum_frame_size(struct v4l2_subdev *sd,
        format.code = fse->code;
        format.width = 1;
        format.height = 1;
-       preview_try_format(prev, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+       preview_try_format(prev, cfg, fse->pad, &format, fse->which);
        fse->min_width = format.width;
        fse->min_height = format.height;
 
@@ -1915,7 +1915,7 @@ static int preview_enum_frame_size(struct v4l2_subdev *sd,
        format.code = fse->code;
        format.width = -1;
        format.height = -1;
-       preview_try_format(prev, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+       preview_try_format(prev, cfg, fse->pad, &format, fse->which);
        fse->max_width = format.width;
        fse->max_height = format.height;
 
@@ -1925,7 +1925,7 @@ static int preview_enum_frame_size(struct v4l2_subdev *sd,
 /*
  * preview_get_selection - Retrieve a selection rectangle on a pad
  * @sd: ISP preview V4L2 subdevice
- * @fh: V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad configuration
  * @sel: Selection rectangle
  *
  * The only supported rectangles are the crop rectangles on the sink pad.
@@ -1933,7 +1933,7 @@ static int preview_enum_frame_size(struct v4l2_subdev *sd,
  * Return 0 on success or a negative error code otherwise.
  */
 static int preview_get_selection(struct v4l2_subdev *sd,
-                                struct v4l2_subdev_fh *fh,
+                                struct v4l2_subdev_pad_config *cfg,
                                 struct v4l2_subdev_selection *sel)
 {
        struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
@@ -1949,13 +1949,13 @@ static int preview_get_selection(struct v4l2_subdev *sd,
                sel->r.width = INT_MAX;
                sel->r.height = INT_MAX;
 
-               format = __preview_get_format(prev, fh, PREV_PAD_SINK,
+               format = __preview_get_format(prev, cfg, PREV_PAD_SINK,
                                              sel->which);
                preview_try_crop(prev, format, &sel->r);
                break;
 
        case V4L2_SEL_TGT_CROP:
-               sel->r = *__preview_get_crop(prev, fh, sel->which);
+               sel->r = *__preview_get_crop(prev, cfg, sel->which);
                break;
 
        default:
@@ -1968,7 +1968,7 @@ static int preview_get_selection(struct v4l2_subdev *sd,
 /*
  * preview_set_selection - Set a selection rectangle on a pad
  * @sd: ISP preview V4L2 subdevice
- * @fh: V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad configuration
  * @sel: Selection rectangle
  *
  * The only supported rectangle is the actual crop rectangle on the sink pad.
@@ -1976,7 +1976,7 @@ static int preview_get_selection(struct v4l2_subdev *sd,
  * Return 0 on success or a negative error code otherwise.
  */
 static int preview_set_selection(struct v4l2_subdev *sd,
-                                struct v4l2_subdev_fh *fh,
+                                struct v4l2_subdev_pad_config *cfg,
                                 struct v4l2_subdev_selection *sel)
 {
        struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
@@ -1995,17 +1995,17 @@ static int preview_set_selection(struct v4l2_subdev *sd,
         * rectangle.
         */
        if (sel->flags & V4L2_SEL_FLAG_KEEP_CONFIG) {
-               sel->r = *__preview_get_crop(prev, fh, sel->which);
+               sel->r = *__preview_get_crop(prev, cfg, sel->which);
                return 0;
        }
 
-       format = __preview_get_format(prev, fh, PREV_PAD_SINK, sel->which);
+       format = __preview_get_format(prev, cfg, PREV_PAD_SINK, sel->which);
        preview_try_crop(prev, format, &sel->r);
-       *__preview_get_crop(prev, fh, sel->which) = sel->r;
+       *__preview_get_crop(prev, cfg, sel->which) = sel->r;
 
        /* Update the source format. */
-       format = __preview_get_format(prev, fh, PREV_PAD_SOURCE, sel->which);
-       preview_try_format(prev, fh, PREV_PAD_SOURCE, format, sel->which);
+       format = __preview_get_format(prev, cfg, PREV_PAD_SOURCE, sel->which);
+       preview_try_format(prev, cfg, PREV_PAD_SOURCE, format, sel->which);
 
        return 0;
 }
@@ -2013,17 +2013,17 @@ static int preview_set_selection(struct v4l2_subdev *sd,
 /*
  * preview_get_format - Handle get format by pads subdev method
  * @sd : pointer to v4l2 subdev structure
- * @fh : V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad configuration
  * @fmt: pointer to v4l2 subdev format structure
  * return -EINVAL or zero on success
  */
-static int preview_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int preview_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_format *fmt)
 {
        struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
        struct v4l2_mbus_framefmt *format;
 
-       format = __preview_get_format(prev, fh, fmt->pad, fmt->which);
+       format = __preview_get_format(prev, cfg, fmt->pad, fmt->which);
        if (format == NULL)
                return -EINVAL;
 
@@ -2034,28 +2034,28 @@ static int preview_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 /*
  * preview_set_format - Handle set format by pads subdev method
  * @sd : pointer to v4l2 subdev structure
- * @fh : V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad configuration
  * @fmt: pointer to v4l2 subdev format structure
  * return -EINVAL or zero on success
  */
-static int preview_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int preview_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_format *fmt)
 {
        struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
        struct v4l2_mbus_framefmt *format;
        struct v4l2_rect *crop;
 
-       format = __preview_get_format(prev, fh, fmt->pad, fmt->which);
+       format = __preview_get_format(prev, cfg, fmt->pad, fmt->which);
        if (format == NULL)
                return -EINVAL;
 
-       preview_try_format(prev, fh, fmt->pad, &fmt->format, fmt->which);
+       preview_try_format(prev, cfg, fmt->pad, &fmt->format, fmt->which);
        *format = fmt->format;
 
        /* Propagate the format from sink to source */
        if (fmt->pad == PREV_PAD_SINK) {
                /* Reset the crop rectangle. */
-               crop = __preview_get_crop(prev, fh, fmt->which);
+               crop = __preview_get_crop(prev, cfg, fmt->which);
                crop->left = 0;
                crop->top = 0;
                crop->width = fmt->format.width;
@@ -2064,9 +2064,9 @@ static int preview_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
                preview_try_crop(prev, &fmt->format, crop);
 
                /* Update the source format. */
-               format = __preview_get_format(prev, fh, PREV_PAD_SOURCE,
+               format = __preview_get_format(prev, cfg, PREV_PAD_SOURCE,
                                              fmt->which);
-               preview_try_format(prev, fh, PREV_PAD_SOURCE, format,
+               preview_try_format(prev, cfg, PREV_PAD_SOURCE, format,
                                   fmt->which);
        }
 
@@ -2093,7 +2093,7 @@ static int preview_init_formats(struct v4l2_subdev *sd,
        format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
        format.format.width = 4096;
        format.format.height = 4096;
-       preview_set_format(sd, fh, &format);
+       preview_set_format(sd, fh ? fh->pad : NULL, &format);
 
        return 0;
 }
index 2b9bc4839876e635ada8c326ba948f45aaf4b90f..7cfb43dc0ffd7764c89bc95eae87ac97e53271e8 100644 (file)
@@ -112,16 +112,16 @@ static const struct isprsz_coef filter_coefs = {
  * __resizer_get_format - helper function for getting resizer format
  * @res   : pointer to resizer private structure
  * @pad   : pad number
- * @fh    : V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad configuration
  * @which : wanted subdev format
  * return zero
  */
 static struct v4l2_mbus_framefmt *
-__resizer_get_format(struct isp_res_device *res, struct v4l2_subdev_fh *fh,
+__resizer_get_format(struct isp_res_device *res, struct v4l2_subdev_pad_config *cfg,
                     unsigned int pad, enum v4l2_subdev_format_whence which)
 {
        if (which == V4L2_SUBDEV_FORMAT_TRY)
-               return v4l2_subdev_get_try_format(fh, pad);
+               return v4l2_subdev_get_try_format(&res->subdev, cfg, pad);
        else
                return &res->formats[pad];
 }
@@ -129,15 +129,15 @@ __resizer_get_format(struct isp_res_device *res, struct v4l2_subdev_fh *fh,
 /*
  * __resizer_get_crop - helper function for getting resizer crop rectangle
  * @res   : pointer to resizer private structure
- * @fh    : V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad configuration
  * @which : wanted subdev crop rectangle
  */
 static struct v4l2_rect *
-__resizer_get_crop(struct isp_res_device *res, struct v4l2_subdev_fh *fh,
+__resizer_get_crop(struct isp_res_device *res, struct v4l2_subdev_pad_config *cfg,
                   enum v4l2_subdev_format_whence which)
 {
        if (which == V4L2_SUBDEV_FORMAT_TRY)
-               return v4l2_subdev_get_try_crop(fh, RESZ_PAD_SINK);
+               return v4l2_subdev_get_try_crop(&res->subdev, cfg, RESZ_PAD_SINK);
        else
                return &res->crop.request;
 }
@@ -1215,7 +1215,7 @@ static void resizer_try_crop(const struct v4l2_mbus_framefmt *sink,
 /*
  * resizer_get_selection - Retrieve a selection rectangle on a pad
  * @sd: ISP resizer V4L2 subdevice
- * @fh: V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad configuration
  * @sel: Selection rectangle
  *
  * The only supported rectangles are the crop rectangles on the sink pad.
@@ -1223,7 +1223,7 @@ static void resizer_try_crop(const struct v4l2_mbus_framefmt *sink,
  * Return 0 on success or a negative error code otherwise.
  */
 static int resizer_get_selection(struct v4l2_subdev *sd,
-                                struct v4l2_subdev_fh *fh,
+                                struct v4l2_subdev_pad_config *cfg,
                                 struct v4l2_subdev_selection *sel)
 {
        struct isp_res_device *res = v4l2_get_subdevdata(sd);
@@ -1234,9 +1234,9 @@ static int resizer_get_selection(struct v4l2_subdev *sd,
        if (sel->pad != RESZ_PAD_SINK)
                return -EINVAL;
 
-       format_sink = __resizer_get_format(res, fh, RESZ_PAD_SINK,
+       format_sink = __resizer_get_format(res, cfg, RESZ_PAD_SINK,
                                           sel->which);
-       format_source = __resizer_get_format(res, fh, RESZ_PAD_SOURCE,
+       format_source = __resizer_get_format(res, cfg, RESZ_PAD_SOURCE,
                                             sel->which);
 
        switch (sel->target) {
@@ -1251,7 +1251,7 @@ static int resizer_get_selection(struct v4l2_subdev *sd,
                break;
 
        case V4L2_SEL_TGT_CROP:
-               sel->r = *__resizer_get_crop(res, fh, sel->which);
+               sel->r = *__resizer_get_crop(res, cfg, sel->which);
                resizer_calc_ratios(res, &sel->r, format_source, &ratio);
                break;
 
@@ -1265,7 +1265,7 @@ static int resizer_get_selection(struct v4l2_subdev *sd,
 /*
  * resizer_set_selection - Set a selection rectangle on a pad
  * @sd: ISP resizer V4L2 subdevice
- * @fh: V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad configuration
  * @sel: Selection rectangle
  *
  * The only supported rectangle is the actual crop rectangle on the sink pad.
@@ -1276,7 +1276,7 @@ static int resizer_get_selection(struct v4l2_subdev *sd,
  * Return 0 on success or a negative error code otherwise.
  */
 static int resizer_set_selection(struct v4l2_subdev *sd,
-                                struct v4l2_subdev_fh *fh,
+                                struct v4l2_subdev_pad_config *cfg,
                                 struct v4l2_subdev_selection *sel)
 {
        struct isp_res_device *res = v4l2_get_subdevdata(sd);
@@ -1290,9 +1290,9 @@ static int resizer_set_selection(struct v4l2_subdev *sd,
            sel->pad != RESZ_PAD_SINK)
                return -EINVAL;
 
-       format_sink = __resizer_get_format(res, fh, RESZ_PAD_SINK,
+       format_sink = __resizer_get_format(res, cfg, RESZ_PAD_SINK,
                                           sel->which);
-       format_source = *__resizer_get_format(res, fh, RESZ_PAD_SOURCE,
+       format_source = *__resizer_get_format(res, cfg, RESZ_PAD_SOURCE,
                                              sel->which);
 
        dev_dbg(isp->dev, "%s(%s): req %ux%u -> (%d,%d)/%ux%u -> %ux%u\n",
@@ -1310,7 +1310,7 @@ static int resizer_set_selection(struct v4l2_subdev *sd,
         * stored the mangled rectangle.
         */
        resizer_try_crop(format_sink, &format_source, &sel->r);
-       *__resizer_get_crop(res, fh, sel->which) = sel->r;
+       *__resizer_get_crop(res, cfg, sel->which) = sel->r;
        resizer_calc_ratios(res, &sel->r, &format_source, &ratio);
 
        dev_dbg(isp->dev, "%s(%s): got %ux%u -> (%d,%d)/%ux%u -> %ux%u\n",
@@ -1320,7 +1320,7 @@ static int resizer_set_selection(struct v4l2_subdev *sd,
                format_source.width, format_source.height);
 
        if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
-               *__resizer_get_format(res, fh, RESZ_PAD_SOURCE, sel->which) =
+               *__resizer_get_format(res, cfg, RESZ_PAD_SOURCE, sel->which) =
                        format_source;
                return 0;
        }
@@ -1331,7 +1331,7 @@ static int resizer_set_selection(struct v4l2_subdev *sd,
         */
        spin_lock_irqsave(&res->lock, flags);
 
-       *__resizer_get_format(res, fh, RESZ_PAD_SOURCE, sel->which) =
+       *__resizer_get_format(res, cfg, RESZ_PAD_SOURCE, sel->which) =
                format_source;
 
        res->ratio = ratio;
@@ -1368,13 +1368,13 @@ static unsigned int resizer_max_in_width(struct isp_res_device *res)
 /*
  * resizer_try_format - Handle try format by pad subdev method
  * @res   : ISP resizer device
- * @fh    : V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad configuration
  * @pad   : pad num
  * @fmt   : pointer to v4l2 format structure
  * @which : wanted subdev format
  */
 static void resizer_try_format(struct isp_res_device *res,
-                              struct v4l2_subdev_fh *fh, unsigned int pad,
+                              struct v4l2_subdev_pad_config *cfg, unsigned int pad,
                               struct v4l2_mbus_framefmt *fmt,
                               enum v4l2_subdev_format_whence which)
 {
@@ -1395,10 +1395,10 @@ static void resizer_try_format(struct isp_res_device *res,
                break;
 
        case RESZ_PAD_SOURCE:
-               format = __resizer_get_format(res, fh, RESZ_PAD_SINK, which);
+               format = __resizer_get_format(res, cfg, RESZ_PAD_SINK, which);
                fmt->code = format->code;
 
-               crop = *__resizer_get_crop(res, fh, which);
+               crop = *__resizer_get_crop(res, cfg, which);
                resizer_calc_ratios(res, &crop, fmt, &ratio);
                break;
        }
@@ -1410,12 +1410,12 @@ static void resizer_try_format(struct isp_res_device *res,
 /*
  * resizer_enum_mbus_code - Handle pixel format enumeration
  * @sd     : pointer to v4l2 subdev structure
- * @fh     : V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad configuration
  * @code   : pointer to v4l2_subdev_mbus_code_enum structure
  * return -EINVAL or zero on success
  */
 static int resizer_enum_mbus_code(struct v4l2_subdev *sd,
-                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_pad_config *cfg,
                                  struct v4l2_subdev_mbus_code_enum *code)
 {
        struct isp_res_device *res = v4l2_get_subdevdata(sd);
@@ -1430,8 +1430,8 @@ static int resizer_enum_mbus_code(struct v4l2_subdev *sd,
                if (code->index != 0)
                        return -EINVAL;
 
-               format = __resizer_get_format(res, fh, RESZ_PAD_SINK,
-                                             V4L2_SUBDEV_FORMAT_TRY);
+               format = __resizer_get_format(res, cfg, RESZ_PAD_SINK,
+                                             code->which);
                code->code = format->code;
        }
 
@@ -1439,7 +1439,7 @@ static int resizer_enum_mbus_code(struct v4l2_subdev *sd,
 }
 
 static int resizer_enum_frame_size(struct v4l2_subdev *sd,
-                                  struct v4l2_subdev_fh *fh,
+                                  struct v4l2_subdev_pad_config *cfg,
                                   struct v4l2_subdev_frame_size_enum *fse)
 {
        struct isp_res_device *res = v4l2_get_subdevdata(sd);
@@ -1451,7 +1451,7 @@ static int resizer_enum_frame_size(struct v4l2_subdev *sd,
        format.code = fse->code;
        format.width = 1;
        format.height = 1;
-       resizer_try_format(res, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+       resizer_try_format(res, cfg, fse->pad, &format, fse->which);
        fse->min_width = format.width;
        fse->min_height = format.height;
 
@@ -1461,7 +1461,7 @@ static int resizer_enum_frame_size(struct v4l2_subdev *sd,
        format.code = fse->code;
        format.width = -1;
        format.height = -1;
-       resizer_try_format(res, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+       resizer_try_format(res, cfg, fse->pad, &format, fse->which);
        fse->max_width = format.width;
        fse->max_height = format.height;
 
@@ -1471,17 +1471,17 @@ static int resizer_enum_frame_size(struct v4l2_subdev *sd,
 /*
  * resizer_get_format - Handle get format by pads subdev method
  * @sd    : pointer to v4l2 subdev structure
- * @fh    : V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad configuration
  * @fmt   : pointer to v4l2 subdev format structure
  * return -EINVAL or zero on success
  */
-static int resizer_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int resizer_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_format *fmt)
 {
        struct isp_res_device *res = v4l2_get_subdevdata(sd);
        struct v4l2_mbus_framefmt *format;
 
-       format = __resizer_get_format(res, fh, fmt->pad, fmt->which);
+       format = __resizer_get_format(res, cfg, fmt->pad, fmt->which);
        if (format == NULL)
                return -EINVAL;
 
@@ -1492,37 +1492,37 @@ static int resizer_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 /*
  * resizer_set_format - Handle set format by pads subdev method
  * @sd    : pointer to v4l2 subdev structure
- * @fh    : V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad configuration
  * @fmt   : pointer to v4l2 subdev format structure
  * return -EINVAL or zero on success
  */
-static int resizer_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int resizer_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_format *fmt)
 {
        struct isp_res_device *res = v4l2_get_subdevdata(sd);
        struct v4l2_mbus_framefmt *format;
        struct v4l2_rect *crop;
 
-       format = __resizer_get_format(res, fh, fmt->pad, fmt->which);
+       format = __resizer_get_format(res, cfg, fmt->pad, fmt->which);
        if (format == NULL)
                return -EINVAL;
 
-       resizer_try_format(res, fh, fmt->pad, &fmt->format, fmt->which);
+       resizer_try_format(res, cfg, fmt->pad, &fmt->format, fmt->which);
        *format = fmt->format;
 
        if (fmt->pad == RESZ_PAD_SINK) {
                /* reset crop rectangle */
-               crop = __resizer_get_crop(res, fh, fmt->which);
+               crop = __resizer_get_crop(res, cfg, fmt->which);
                crop->left = 0;
                crop->top = 0;
                crop->width = fmt->format.width;
                crop->height = fmt->format.height;
 
                /* Propagate the format from sink to source */
-               format = __resizer_get_format(res, fh, RESZ_PAD_SOURCE,
+               format = __resizer_get_format(res, cfg, RESZ_PAD_SOURCE,
                                              fmt->which);
                *format = fmt->format;
-               resizer_try_format(res, fh, RESZ_PAD_SOURCE, format,
+               resizer_try_format(res, cfg, RESZ_PAD_SOURCE, format,
                                   fmt->which);
        }
 
@@ -1573,7 +1573,7 @@ static int resizer_init_formats(struct v4l2_subdev *sd,
        format.format.code = MEDIA_BUS_FMT_YUYV8_1X16;
        format.format.width = 4096;
        format.format.height = 4096;
-       resizer_set_format(sd, fh, &format);
+       resizer_set_format(sd, fh ? fh->pad : NULL, &format);
 
        return 0;
 }
index a94e8340508f703efea86f51232578e30912f496..20434e83e801c1bae242509e666321b63e2437c5 100644 (file)
@@ -21,7 +21,7 @@
 
 #include "isp.h"
 
-#define ISP_STAT_USES_DMAENGINE(stat)  ((stat)->dma_ch >= 0)
+#define ISP_STAT_USES_DMAENGINE(stat)  ((stat)->dma_ch != NULL)
 
 /*
  * MAGIC_SIZE must always be the greatest common divisor of
index b32b29677e2c48f3fc3bd4dbe9d9208452ee1cf5..b79380d83fcfacb1f8e1ff43f5964b10db1df1b7 100644 (file)
@@ -20,7 +20,6 @@
 
 #include <linux/types.h>
 #include <linux/omap3isp.h>
-#include <linux/omap-dma.h>
 #include <media/v4l2-event.h>
 
 #include "isp.h"
@@ -33,6 +32,7 @@
 #define STAT_NO_BUF            1       /* An error has occurred */
 #define STAT_BUF_WAITING_DMA   2       /* Histogram only: DMA is running */
 
+struct dma_chan;
 struct ispstat;
 
 struct ispstat_buffer {
@@ -96,7 +96,6 @@ struct ispstat {
        u8 inc_config;
        atomic_t buf_err;
        enum ispstat_state_t state;     /* enabling/disabling state */
-       struct omap_dma_channel_params dma_config;
        struct isp_device *isp;
        void *priv;             /* pointer to priv config struct */
        void *recover_priv;     /* pointer to recover priv configuration */
@@ -110,7 +109,7 @@ struct ispstat {
        u32 frame_number;
        u32 buf_size;
        u32 buf_alloc_size;
-       int dma_ch;
+       struct dma_chan *dma_ch;
        unsigned long event_type;
        struct ispstat_buffer *buf;
        struct ispstat_buffer *active_buf;
index 3fe9047ef466faddcb822453e08282bf381c366b..d285af18df7ffa4c4b50ad630f3e13bae966296f 100644 (file)
@@ -452,7 +452,6 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video)
        enum isp_pipeline_state state;
        struct isp_buffer *buf;
        unsigned long flags;
-       struct timespec ts;
 
        spin_lock_irqsave(&video->irqlock, flags);
        if (WARN_ON(list_empty(&video->dmaqueue))) {
@@ -465,9 +464,7 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video)
        list_del(&buf->irqlist);
        spin_unlock_irqrestore(&video->irqlock, flags);
 
-       ktime_get_ts(&ts);
-       buf->vb.v4l2_buf.timestamp.tv_sec = ts.tv_sec;
-       buf->vb.v4l2_buf.timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+       v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
 
        /* Do frame number propagation only if this is the output video node.
         * Frame number either comes from the CSI receivers or it gets
@@ -524,7 +521,6 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video)
 
        buf = list_first_entry(&video->dmaqueue, struct isp_buffer,
                               irqlist);
-       buf->vb.state = VB2_BUF_STATE_ACTIVE;
 
        spin_unlock_irqrestore(&video->irqlock, flags);
 
@@ -1022,7 +1018,7 @@ isp_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
 
        pipe->entities = 0;
 
-       if (video->isp->pdata->set_constraints)
+       if (video->isp->pdata && video->isp->pdata->set_constraints)
                video->isp->pdata->set_constraints(video->isp, true);
        pipe->l3_ick = clk_get_rate(video->isp->clock[ISP_CLK_L3_ICK]);
        pipe->max_rate = pipe->l3_ick;
@@ -1104,7 +1100,7 @@ err_set_stream:
 err_check_format:
        media_entity_pipeline_stop(&video->video.entity);
 err_pipeline_start:
-       if (video->isp->pdata->set_constraints)
+       if (video->isp->pdata && video->isp->pdata->set_constraints)
                video->isp->pdata->set_constraints(video->isp, false);
        /* The DMA queue must be emptied here, otherwise CCDC interrupts that
         * will get triggered the next time the CCDC is powered up will try to
@@ -1165,7 +1161,7 @@ isp_video_streamoff(struct file *file, void *fh, enum v4l2_buf_type type)
        video->queue = NULL;
        video->error = false;
 
-       if (video->isp->pdata->set_constraints)
+       if (video->isp->pdata && video->isp->pdata->set_constraints)
                video->isp->pdata->set_constraints(video->isp, false);
        media_entity_pipeline_stop(&video->video.entity);
 
@@ -1326,14 +1322,8 @@ static unsigned int isp_video_poll(struct file *file, poll_table *wait)
 static int isp_video_mmap(struct file *file, struct vm_area_struct *vma)
 {
        struct isp_video_fh *vfh = to_isp_video_fh(file->private_data);
-       struct isp_video *video = video_drvdata(file);
-       int ret;
-
-       mutex_lock(&video->queue_lock);
-       ret = vb2_mmap(&vfh->queue, vma);
-       mutex_unlock(&video->queue_lock);
 
-       return ret;
+       return vb2_mmap(&vfh->queue, vma);
 }
 
 static struct v4l2_file_operations isp_video_fops = {
index 54479d60cc0d927a82fd72b83efaf1d60f6fde36..f6a61b9ceff4ac048b236247915b834be81e756a 100644 (file)
@@ -1219,7 +1219,7 @@ static const u32 camif_mbus_formats[] = {
  */
 
 static int s3c_camif_subdev_enum_mbus_code(struct v4l2_subdev *sd,
-                                       struct v4l2_subdev_fh *fh,
+                                       struct v4l2_subdev_pad_config *cfg,
                                        struct v4l2_subdev_mbus_code_enum *code)
 {
        if (code->index >= ARRAY_SIZE(camif_mbus_formats))
@@ -1230,14 +1230,14 @@ static int s3c_camif_subdev_enum_mbus_code(struct v4l2_subdev *sd,
 }
 
 static int s3c_camif_subdev_get_fmt(struct v4l2_subdev *sd,
-                                   struct v4l2_subdev_fh *fh,
+                                   struct v4l2_subdev_pad_config *cfg,
                                    struct v4l2_subdev_format *fmt)
 {
        struct camif_dev *camif = v4l2_get_subdevdata(sd);
        struct v4l2_mbus_framefmt *mf = &fmt->format;
 
        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-               mf = v4l2_subdev_get_try_format(fh, fmt->pad);
+               mf = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
                fmt->format = *mf;
                return 0;
        }
@@ -1297,7 +1297,7 @@ static void __camif_subdev_try_format(struct camif_dev *camif,
 }
 
 static int s3c_camif_subdev_set_fmt(struct v4l2_subdev *sd,
-                                   struct v4l2_subdev_fh *fh,
+                                   struct v4l2_subdev_pad_config *cfg,
                                    struct v4l2_subdev_format *fmt)
 {
        struct camif_dev *camif = v4l2_get_subdevdata(sd);
@@ -1325,7 +1325,7 @@ static int s3c_camif_subdev_set_fmt(struct v4l2_subdev *sd,
        __camif_subdev_try_format(camif, mf, fmt->pad);
 
        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-               mf = v4l2_subdev_get_try_format(fh, fmt->pad);
+               mf = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
                *mf = fmt->format;
                mutex_unlock(&camif->lock);
                return 0;
@@ -1364,7 +1364,7 @@ static int s3c_camif_subdev_set_fmt(struct v4l2_subdev *sd,
 }
 
 static int s3c_camif_subdev_get_selection(struct v4l2_subdev *sd,
-                                         struct v4l2_subdev_fh *fh,
+                                         struct v4l2_subdev_pad_config *cfg,
                                          struct v4l2_subdev_selection *sel)
 {
        struct camif_dev *camif = v4l2_get_subdevdata(sd);
@@ -1377,7 +1377,7 @@ static int s3c_camif_subdev_get_selection(struct v4l2_subdev *sd,
                return -EINVAL;
 
        if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
-               sel->r = *v4l2_subdev_get_try_crop(fh, sel->pad);
+               sel->r = *v4l2_subdev_get_try_crop(sd, cfg, sel->pad);
                return 0;
        }
 
@@ -1451,7 +1451,7 @@ static void __camif_try_crop(struct camif_dev *camif, struct v4l2_rect *r)
 }
 
 static int s3c_camif_subdev_set_selection(struct v4l2_subdev *sd,
-                                         struct v4l2_subdev_fh *fh,
+                                         struct v4l2_subdev_pad_config *cfg,
                                          struct v4l2_subdev_selection *sel)
 {
        struct camif_dev *camif = v4l2_get_subdevdata(sd);
@@ -1465,7 +1465,7 @@ static int s3c_camif_subdev_set_selection(struct v4l2_subdev *sd,
        __camif_try_crop(camif, &sel->r);
 
        if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
-               *v4l2_subdev_get_try_crop(fh, sel->pad) = sel->r;
+               *v4l2_subdev_get_try_crop(sd, cfg, sel->pad) = sel->r;
        } else {
                unsigned long flags;
                unsigned int i;
index a92ff4249d100d33e84acaf50b372eb5e2a190b0..bfbf1575677ca93c2d81426daaef885f7675022f 100644 (file)
@@ -621,6 +621,7 @@ static int s5p_jpeg_to_user_subsampling(struct s5p_jpeg_ctx *ctx)
                        return V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY;
                return ctx->subsampling;
        case SJPEG_EXYNOS3250:
+       case SJPEG_EXYNOS5420:
                if (ctx->subsampling > 3)
                        return V4L2_JPEG_CHROMA_SUBSAMPLING_411;
                return exynos3250_decoded_subsampling[ctx->subsampling];
@@ -1142,13 +1143,13 @@ static void jpeg_bound_align_image(struct s5p_jpeg_ctx *ctx,
        w_step = 1 << walign;
        h_step = 1 << halign;
 
-       if (ctx->jpeg->variant->version == SJPEG_EXYNOS3250) {
+       if (ctx->jpeg->variant->hw3250_compat) {
                /*
                 * Rightmost and bottommost pixels are cropped by the
-                * Exynos3250 JPEG IP for RGB formats, for the specific
-                * width and height values respectively. This assignment
-                * will result in v4l_bound_align_image returning dimensions
-                * reduced by 1 for the aforementioned cases.
+                * Exynos3250/compatible JPEG IP for RGB formats, for the
+                * specific width and height values respectively. This
+                * assignment will result in v4l_bound_align_image returning
+                * dimensions reduced by 1 for the aforementioned cases.
                 */
                if (w_step == 4 && ((width & 3) == 1)) {
                        wmax = width;
@@ -1384,12 +1385,12 @@ static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f)
 
        /*
         * Prevent downscaling to YUV420 format by more than 2
-        * for Exynos3250 SoC as it produces broken raw image
+        * for Exynos3250/compatible SoC as it produces broken raw image
         * in such cases.
         */
        if (ct->mode == S5P_JPEG_DECODE &&
            f_type == FMT_TYPE_CAPTURE &&
-           ct->jpeg->variant->version == SJPEG_EXYNOS3250 &&
+           ct->jpeg->variant->hw3250_compat &&
            pix->pixelformat == V4L2_PIX_FMT_YUV420 &&
            ct->scale_factor > 2) {
                scale_rect.width = ct->out_q.w / 2;
@@ -1569,12 +1570,12 @@ static int s5p_jpeg_s_selection(struct file *file, void *fh,
        if (s->target == V4L2_SEL_TGT_COMPOSE) {
                if (ctx->mode != S5P_JPEG_DECODE)
                        return -EINVAL;
-               if (ctx->jpeg->variant->version == SJPEG_EXYNOS3250)
+               if (ctx->jpeg->variant->hw3250_compat)
                        ret = exynos3250_jpeg_try_downscale(ctx, rect);
        } else if (s->target == V4L2_SEL_TGT_CROP) {
                if (ctx->mode != S5P_JPEG_ENCODE)
                        return -EINVAL;
-               if (ctx->jpeg->variant->version == SJPEG_EXYNOS3250)
+               if (ctx->jpeg->variant->hw3250_compat)
                        ret = exynos3250_jpeg_try_crop(ctx, rect);
        }
 
@@ -1604,8 +1605,9 @@ static int s5p_jpeg_adjust_subs_ctrl(struct s5p_jpeg_ctx *ctx, int *ctrl_val)
        case SJPEG_S5P:
                return 0;
        case SJPEG_EXYNOS3250:
+       case SJPEG_EXYNOS5420:
                /*
-                * The exynos3250 device can produce JPEG image only
+                * The exynos3250/compatible device can produce JPEG image only
                 * of 4:4:4 subsampling when given RGB32 source image.
                 */
                if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB32)
@@ -1624,7 +1626,7 @@ static int s5p_jpeg_adjust_subs_ctrl(struct s5p_jpeg_ctx *ctx, int *ctrl_val)
        }
 
        /*
-        * The exynos4x12 and exynos3250 devices require resulting
+        * The exynos4x12 and exynos3250/compatible devices require resulting
         * jpeg subsampling not to be lower than the input raw image
         * subsampling.
         */
@@ -1842,7 +1844,7 @@ static void exynos4_jpeg_set_img_addr(struct s5p_jpeg_ctx *ctx)
        struct s5p_jpeg *jpeg = ctx->jpeg;
        struct s5p_jpeg_fmt *fmt;
        struct vb2_buffer *vb;
-       struct s5p_jpeg_addr jpeg_addr;
+       struct s5p_jpeg_addr jpeg_addr = {};
        u32 pix_size, padding_bytes = 0;
 
        jpeg_addr.cb = 0;
@@ -1946,7 +1948,7 @@ static void exynos3250_jpeg_set_img_addr(struct s5p_jpeg_ctx *ctx)
        struct s5p_jpeg *jpeg = ctx->jpeg;
        struct s5p_jpeg_fmt *fmt;
        struct vb2_buffer *vb;
-       struct s5p_jpeg_addr jpeg_addr;
+       struct s5p_jpeg_addr jpeg_addr = {};
        u32 pix_size;
 
        pix_size = ctx->cap_q.w * ctx->cap_q.h;
@@ -2020,6 +2022,16 @@ static void exynos3250_jpeg_device_run(void *priv)
                exynos3250_jpeg_qtbl(jpeg->regs, 2, 1);
                exynos3250_jpeg_qtbl(jpeg->regs, 3, 1);
 
+               /*
+                * Some SoCs require setting Huffman tables before each run
+                */
+               if (jpeg->variant->htbl_reinit) {
+                       s5p_jpeg_set_hdctbl(jpeg->regs);
+                       s5p_jpeg_set_hdctblg(jpeg->regs);
+                       s5p_jpeg_set_hactbl(jpeg->regs);
+                       s5p_jpeg_set_hactblg(jpeg->regs);
+               }
+
                /* Y, Cb, Cr use Huffman table 0 */
                exynos3250_jpeg_htbl_ac(jpeg->regs, 1);
                exynos3250_jpeg_htbl_dc(jpeg->regs, 1);
@@ -2663,13 +2675,12 @@ static int s5p_jpeg_runtime_resume(struct device *dev)
        /*
         * JPEG IP allows storing two Huffman tables for each component.
         * We fill table 0 for each component and do this here only
-        * for S5PC210 and Exynos3250 SoCs. Exynos4x12 SoC requires
-        * programming its Huffman tables each time the encoding process
-        * is initialized, and thus it is accomplished in the device_run
-        * callback of m2m_ops.
+        * for S5PC210 and Exynos3250 SoCs. Exynos4x12 and Exynos542x SoC
+        * require programming their Huffman tables each time the encoding
+        * process is initialized, and thus it is accomplished in the
+        * device_run callback of m2m_ops.
         */
-       if (jpeg->variant->version == SJPEG_S5P ||
-           jpeg->variant->version == SJPEG_EXYNOS3250) {
+       if (!jpeg->variant->htbl_reinit) {
                s5p_jpeg_set_hdctbl(jpeg->regs);
                s5p_jpeg_set_hdctblg(jpeg->regs);
                s5p_jpeg_set_hactbl(jpeg->regs);
@@ -2717,6 +2728,7 @@ static struct s5p_jpeg_variant exynos3250_jpeg_drvdata = {
        .jpeg_irq       = exynos3250_jpeg_irq,
        .m2m_ops        = &exynos3250_jpeg_m2m_ops,
        .fmt_ver_flag   = SJPEG_FMT_FLAG_EXYNOS3250,
+       .hw3250_compat  = 1,
 };
 
 static struct s5p_jpeg_variant exynos4_jpeg_drvdata = {
@@ -2724,6 +2736,16 @@ static struct s5p_jpeg_variant exynos4_jpeg_drvdata = {
        .jpeg_irq       = exynos4_jpeg_irq,
        .m2m_ops        = &exynos4_jpeg_m2m_ops,
        .fmt_ver_flag   = SJPEG_FMT_FLAG_EXYNOS4,
+       .htbl_reinit    = 1,
+};
+
+static struct s5p_jpeg_variant exynos5420_jpeg_drvdata = {
+       .version        = SJPEG_EXYNOS5420,
+       .jpeg_irq       = exynos3250_jpeg_irq,          /* intentionally 3250 */
+       .m2m_ops        = &exynos3250_jpeg_m2m_ops,     /* intentionally 3250 */
+       .fmt_ver_flag   = SJPEG_FMT_FLAG_EXYNOS3250,    /* intentionally 3250 */
+       .hw3250_compat  = 1,
+       .htbl_reinit    = 1,
 };
 
 static const struct of_device_id samsung_jpeg_match[] = {
@@ -2739,6 +2761,9 @@ static const struct of_device_id samsung_jpeg_match[] = {
        }, {
                .compatible = "samsung,exynos4212-jpeg",
                .data = &exynos4_jpeg_drvdata,
+       }, {
+               .compatible = "samsung,exynos5420-jpeg",
+               .data = &exynos5420_jpeg_drvdata,
        },
        {},
 };
index 764b32de326b2cd4e31ab0b5bc4b5641b260e09d..7d9a9ed19cea882de59b53e40fb0a5ca5df7f203 100644 (file)
 #define SJPEG_SUBSAMPLING_420  0x22
 
 /* Version numbers */
-
-#define SJPEG_S5P              1
-#define SJPEG_EXYNOS3250       2
-#define SJPEG_EXYNOS4          3
+enum sjpeg_version {
+       SJPEG_S5P,
+       SJPEG_EXYNOS3250,
+       SJPEG_EXYNOS4,
+       SJPEG_EXYNOS5420,
+};
 
 enum exynos4_jpeg_result {
        OK_ENC_OR_DEC,
@@ -130,6 +132,8 @@ struct s5p_jpeg {
 struct s5p_jpeg_variant {
        unsigned int            version;
        unsigned int            fmt_ver_flag;
+       unsigned int            hw3250_compat:1;
+       unsigned int            htbl_reinit:1;
        struct v4l2_m2m_ops     *m2m_ops;
        irqreturn_t             (*jpeg_irq)(int irq, void *priv);
 };
index e3b8e67e005f12fa21a37045844fce373aef134d..b5f20e722b635c56ec0c8eba81d74ce4132196c2 100644 (file)
@@ -51,18 +51,6 @@ void s5p_jpeg_input_raw_mode(void __iomem *regs, unsigned long mode)
        writel(reg, regs + S5P_JPGCMOD);
 }
 
-void s5p_jpeg_input_raw_y16(void __iomem *regs, bool y16)
-{
-       unsigned long reg;
-
-       reg = readl(regs + S5P_JPGCMOD);
-       if (y16)
-               reg |= S5P_MODE_Y16;
-       else
-               reg &= ~S5P_MODE_Y16_MASK;
-       writel(reg, regs + S5P_JPGCMOD);
-}
-
 void s5p_jpeg_proc_mode(void __iomem *regs, unsigned long mode)
 {
        unsigned long reg, m;
@@ -208,26 +196,6 @@ void s5p_jpeg_final_mcu_num_int_enable(void __iomem *regs, bool enbl)
        writel(reg, regs + S5P_JPGINTSE);
 }
 
-void s5p_jpeg_timer_enable(void __iomem *regs, unsigned long val)
-{
-       unsigned long reg;
-
-       reg = readl(regs + S5P_JPG_TIMER_SE);
-       reg |= S5P_TIMER_INT_EN;
-       reg &= ~S5P_TIMER_INIT_MASK;
-       reg |= val & S5P_TIMER_INIT_MASK;
-       writel(reg, regs + S5P_JPG_TIMER_SE);
-}
-
-void s5p_jpeg_timer_disable(void __iomem *regs)
-{
-       unsigned long reg;
-
-       reg = readl(regs + S5P_JPG_TIMER_SE);
-       reg &= ~S5P_TIMER_INT_EN_MASK;
-       writel(reg, regs + S5P_JPG_TIMER_SE);
-}
-
 int s5p_jpeg_timer_stat(void __iomem *regs)
 {
        return (int)((readl(regs + S5P_JPG_TIMER_ST) & S5P_TIMER_INT_STAT_MASK)
index c11ebe86b9c908f3d720ade836228efbd219250a..f208fa3ed7386190b366cbd4339282d83dc30593 100644 (file)
@@ -29,7 +29,6 @@
 void s5p_jpeg_reset(void __iomem *regs);
 void s5p_jpeg_poweron(void __iomem *regs);
 void s5p_jpeg_input_raw_mode(void __iomem *regs, unsigned long mode);
-void s5p_jpeg_input_raw_y16(void __iomem *regs, bool y16);
 void s5p_jpeg_proc_mode(void __iomem *regs, unsigned long mode);
 void s5p_jpeg_subsampling_mode(void __iomem *regs, unsigned int mode);
 unsigned int s5p_jpeg_get_subsampling_mode(void __iomem *regs);
@@ -42,8 +41,6 @@ void s5p_jpeg_x(void __iomem *regs, unsigned int x);
 void s5p_jpeg_rst_int_enable(void __iomem *regs, bool enable);
 void s5p_jpeg_data_num_int_enable(void __iomem *regs, bool enable);
 void s5p_jpeg_final_mcu_num_int_enable(void __iomem *regs, bool enbl);
-void s5p_jpeg_timer_enable(void __iomem *regs, unsigned long val);
-void s5p_jpeg_timer_disable(void __iomem *regs);
 int s5p_jpeg_timer_stat(void __iomem *regs);
 void s5p_jpeg_clear_timer_stat(void __iomem *regs);
 void s5p_jpeg_enc_stream_int(void __iomem *regs, unsigned long size);
index 98374e8bad3e99ffdf5a70d26b923e6e0c265bf3..8333fbc2fe96c18c66f2e17c1949874001821ab3 100644 (file)
@@ -844,6 +844,13 @@ static int s5p_mfc_open(struct file *file)
                ret = -ENOENT;
                goto err_queue_init;
        }
+       /* One way to indicate end-of-stream for MFC is to set the
+        * bytesused == 0. However by default videobuf2 handles bytesused
+        * equal to 0 as a special case and changes its value to the size
+        * of the buffer. Set the allow_zero_bytesused flag so that videobuf2
+        * will keep the value of bytesused intact.
+        */
+       q->allow_zero_bytesused = 1;
        q->mem_ops = &vb2_dma_contig_memops;
        q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
        ret = vb2_queue_init(q);
index 72d4f2e1efc01a5291dd28b5d6ef2568d1f601cb..751f3b618337cea77b7eff822842f95a3ef0f8d9 100644 (file)
@@ -287,7 +287,7 @@ static void mxr_mplane_fill(struct v4l2_plane_pix_format *planes,
                u32 bl_width = divup(width, blk->width);
                u32 bl_height = divup(height, blk->height);
                u32 sizeimage = bl_width * bl_height * blk->size;
-               u16 bytesperline = bl_width * blk->size / blk->height;
+               u32 bytesperline = bl_width * blk->size / blk->height;
 
                plane->sizeimage += sizeimage;
                plane->bytesperline = max(plane->bytesperline, bytesperline);
index 261f1195b49ffea4a0f823cd3bb575c119bf58f1..dde1ccc730be0c7d32e2ea8bf276cf80148b4fd1 100644 (file)
@@ -62,7 +62,7 @@ enum sh_vou_status {
 
 struct sh_vou_device {
        struct v4l2_device v4l2_dev;
-       struct video_device *vdev;
+       struct video_device vdev;
        atomic_t use_count;
        struct sh_vou_pdata *pdata;
        spinlock_t lock;
@@ -890,7 +890,7 @@ static int sh_vou_s_std(struct file *file, void *priv, v4l2_std_id std_id)
 
        dev_dbg(vou_dev->v4l2_dev.dev, "%s(): 0x%llx\n", __func__, std_id);
 
-       if (std_id & ~vou_dev->vdev->tvnorms)
+       if (std_id & ~vou_dev->vdev.tvnorms)
                return -EINVAL;
 
        ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, video,
@@ -1168,10 +1168,10 @@ static int sh_vou_open(struct file *file)
 
        dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__);
 
-       file->private_data = vou_file;
-
-       if (mutex_lock_interruptible(&vou_dev->fop_lock))
+       if (mutex_lock_interruptible(&vou_dev->fop_lock)) {
+               kfree(vou_file);
                return -ERESTARTSYS;
+       }
        if (atomic_inc_return(&vou_dev->use_count) == 1) {
                int ret;
                /* First open */
@@ -1183,6 +1183,7 @@ static int sh_vou_open(struct file *file)
                        pm_runtime_put(vou_dev->v4l2_dev.dev);
                        vou_dev->status = SH_VOU_IDLE;
                        mutex_unlock(&vou_dev->fop_lock);
+                       kfree(vou_file);
                        return ret;
                }
        }
@@ -1192,9 +1193,11 @@ static int sh_vou_open(struct file *file)
                                       V4L2_BUF_TYPE_VIDEO_OUTPUT,
                                       V4L2_FIELD_NONE,
                                       sizeof(struct videobuf_buffer),
-                                      vou_dev->vdev, &vou_dev->fop_lock);
+                                      &vou_dev->vdev, &vou_dev->fop_lock);
        mutex_unlock(&vou_dev->fop_lock);
 
+       file->private_data = vou_file;
+
        return 0;
 }
 
@@ -1358,21 +1361,14 @@ static int sh_vou_probe(struct platform_device *pdev)
                goto ev4l2devreg;
        }
 
-       /* Allocate memory for video device */
-       vdev = video_device_alloc();
-       if (vdev == NULL) {
-               ret = -ENOMEM;
-               goto evdevalloc;
-       }
-
+       vdev = &vou_dev->vdev;
        *vdev = sh_vou_video_template;
        if (vou_pdata->bus_fmt == SH_VOU_BUS_8BIT)
                vdev->tvnorms |= V4L2_STD_PAL;
        vdev->v4l2_dev = &vou_dev->v4l2_dev;
-       vdev->release = video_device_release;
+       vdev->release = video_device_release_empty;
        vdev->lock = &vou_dev->fop_lock;
 
-       vou_dev->vdev = vdev;
        video_set_drvdata(vdev, vou_dev);
 
        pm_runtime_enable(&pdev->dev);
@@ -1406,9 +1402,7 @@ ei2cnd:
 ereset:
        i2c_put_adapter(i2c_adap);
 ei2cgadap:
-       video_device_release(vdev);
        pm_runtime_disable(&pdev->dev);
-evdevalloc:
        v4l2_device_unregister(&vou_dev->v4l2_dev);
 ev4l2devreg:
        free_irq(irq, vou_dev);
@@ -1435,7 +1429,7 @@ static int sh_vou_remove(struct platform_device *pdev)
        if (irq > 0)
                free_irq(irq, vou_dev);
        pm_runtime_disable(&pdev->dev);
-       video_unregister_device(vou_dev->vdev);
+       video_unregister_device(&vou_dev->vdev);
        i2c_put_adapter(client->adapter);
        v4l2_device_unregister(&vou_dev->v4l2_dev);
        iounmap(vou_dev->base);
index 279ab9f6ae38f950ea549d062ab7a9db587097bb..6460f8e1b07fc6e41e4e31b90338fb7fa73ab48f 100644 (file)
 #define VIN_MAX_WIDTH          2048
 #define VIN_MAX_HEIGHT         2048
 
+#define TIMEOUT_MS             100
+
 enum chip_id {
        RCAR_GEN2,
        RCAR_H1,
@@ -820,7 +822,10 @@ static void rcar_vin_wait_stop_streaming(struct rcar_vin_priv *priv)
                if (priv->state == STOPPING) {
                        priv->request_to_stop = true;
                        spin_unlock_irq(&priv->lock);
-                       wait_for_completion(&priv->capture_stop);
+                       if (!wait_for_completion_timeout(
+                                       &priv->capture_stop,
+                                       msecs_to_jiffies(TIMEOUT_MS)))
+                               priv->state = STOPPED;
                        spin_lock_irq(&priv->lock);
                }
        }
@@ -977,19 +982,6 @@ static void rcar_vin_remove_device(struct soc_camera_device *icd)
                icd->devnum);
 }
 
-/* Called with .host_lock held */
-static int rcar_vin_clock_start(struct soc_camera_host *ici)
-{
-       /* VIN does not have "mclk" */
-       return 0;
-}
-
-/* Called with .host_lock held */
-static void rcar_vin_clock_stop(struct soc_camera_host *ici)
-{
-       /* VIN does not have "mclk" */
-}
-
 static void set_coeff(struct rcar_vin_priv *priv, unsigned short xs)
 {
        int i;
@@ -1803,8 +1795,6 @@ static struct soc_camera_host_ops rcar_vin_host_ops = {
        .owner          = THIS_MODULE,
        .add            = rcar_vin_add_device,
        .remove         = rcar_vin_remove_device,
-       .clock_start    = rcar_vin_clock_start,
-       .clock_stop     = rcar_vin_clock_stop,
        .get_formats    = rcar_vin_get_formats,
        .put_formats    = rcar_vin_put_formats,
        .get_crop       = rcar_vin_get_crop,
index c4e7aa0ee7e1eb3275e3bfc3b1d89aa3720892d2..cd93241eb4976c0b770a01037b27a863999e7f7a 100644 (file)
@@ -380,7 +380,6 @@ static int sh_csi2_remove(struct platform_device *pdev)
        struct sh_csi2 *priv = container_of(subdev, struct sh_csi2, subdev);
 
        v4l2_async_unregister_subdev(&priv->subdev);
-       v4l2_device_unregister_subdev(subdev);
        pm_runtime_disable(&pdev->dev);
 
        return 0;
index 9039d989c01ccc5d0928be7be5db3297f96fa164..7bfe7665687fadd6e33bc0e22903c365e6d95480 100644 (file)
@@ -177,6 +177,30 @@ static int __soc_camera_power_off(struct soc_camera_device *icd)
        return 0;
 }
 
+static int soc_camera_clock_start(struct soc_camera_host *ici)
+{
+       int ret;
+
+       if (!ici->ops->clock_start)
+               return 0;
+
+       mutex_lock(&ici->clk_lock);
+       ret = ici->ops->clock_start(ici);
+       mutex_unlock(&ici->clk_lock);
+
+       return ret;
+}
+
+static void soc_camera_clock_stop(struct soc_camera_host *ici)
+{
+       if (!ici->ops->clock_stop)
+               return;
+
+       mutex_lock(&ici->clk_lock);
+       ici->ops->clock_stop(ici);
+       mutex_unlock(&ici->clk_lock);
+}
+
 const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc(
        struct soc_camera_device *icd, unsigned int fourcc)
 {
@@ -584,9 +608,7 @@ static int soc_camera_add_device(struct soc_camera_device *icd)
                return -EBUSY;
 
        if (!icd->clk) {
-               mutex_lock(&ici->clk_lock);
-               ret = ici->ops->clock_start(ici);
-               mutex_unlock(&ici->clk_lock);
+               ret = soc_camera_clock_start(ici);
                if (ret < 0)
                        return ret;
        }
@@ -602,11 +624,8 @@ static int soc_camera_add_device(struct soc_camera_device *icd)
        return 0;
 
 eadd:
-       if (!icd->clk) {
-               mutex_lock(&ici->clk_lock);
-               ici->ops->clock_stop(ici);
-               mutex_unlock(&ici->clk_lock);
-       }
+       if (!icd->clk)
+               soc_camera_clock_stop(ici);
        return ret;
 }
 
@@ -619,11 +638,8 @@ static void soc_camera_remove_device(struct soc_camera_device *icd)
 
        if (ici->ops->remove)
                ici->ops->remove(icd);
-       if (!icd->clk) {
-               mutex_lock(&ici->clk_lock);
-               ici->ops->clock_stop(ici);
-               mutex_unlock(&ici->clk_lock);
-       }
+       if (!icd->clk)
+               soc_camera_clock_stop(ici);
        ici->icd = NULL;
 }
 
@@ -688,7 +704,8 @@ static int soc_camera_open(struct file *file)
 
                /* The camera could have been already on, try to reset */
                if (sdesc->subdev_desc.reset)
-                       sdesc->subdev_desc.reset(icd->pdev);
+                       if (icd->control)
+                               sdesc->subdev_desc.reset(icd->control);
 
                ret = soc_camera_add_device(icd);
                if (ret < 0) {
@@ -1159,7 +1176,8 @@ static void scan_add_host(struct soc_camera_host *ici)
 
                        /* The camera could have been already on, try to reset */
                        if (ssdd->reset)
-                               ssdd->reset(icd->pdev);
+                               if (icd->control)
+                                       ssdd->reset(icd->control);
 
                        icd->parent = ici->v4l2_dev.dev;
 
@@ -1178,7 +1196,6 @@ static int soc_camera_clk_enable(struct v4l2_clk *clk)
 {
        struct soc_camera_device *icd = clk->priv;
        struct soc_camera_host *ici;
-       int ret;
 
        if (!icd || !icd->parent)
                return -ENODEV;
@@ -1192,10 +1209,7 @@ static int soc_camera_clk_enable(struct v4l2_clk *clk)
         * If a different client is currently being probed, the host will tell
         * you to go
         */
-       mutex_lock(&ici->clk_lock);
-       ret = ici->ops->clock_start(ici);
-       mutex_unlock(&ici->clk_lock);
-       return ret;
+       return soc_camera_clock_start(ici);
 }
 
 static void soc_camera_clk_disable(struct v4l2_clk *clk)
@@ -1208,9 +1222,7 @@ static void soc_camera_clk_disable(struct v4l2_clk *clk)
 
        ici = to_soc_camera_host(icd->parent);
 
-       mutex_lock(&ici->clk_lock);
-       ici->ops->clock_stop(ici);
-       mutex_unlock(&ici->clk_lock);
+       soc_camera_clock_stop(ici);
 
        module_put(ici->ops->owner);
 }
@@ -1364,7 +1376,7 @@ static int soc_camera_i2c_init(struct soc_camera_device *icd,
        snprintf(clk_name, sizeof(clk_name), "%d-%04x",
                 shd->i2c_adapter_id, shd->board_info->addr);
 
-       icd->clk = v4l2_clk_register(&soc_camera_clk_ops, clk_name, "mclk", icd);
+       icd->clk = v4l2_clk_register(&soc_camera_clk_ops, clk_name, icd);
        if (IS_ERR(icd->clk)) {
                ret = PTR_ERR(icd->clk);
                goto eclkreg;
@@ -1445,7 +1457,7 @@ static int soc_camera_async_bound(struct v4l2_async_notifier *notifier,
                                memcpy(&sdesc->subdev_desc, ssdd,
                                       sizeof(sdesc->subdev_desc));
                                if (ssdd->reset)
-                                       ssdd->reset(icd->pdev);
+                                       ssdd->reset(&client->dev);
                        }
 
                        icd->control = &client->dev;
@@ -1545,7 +1557,7 @@ static int scan_async_group(struct soc_camera_host *ici,
        snprintf(clk_name, sizeof(clk_name), "%d-%04x",
                 sasd->asd.match.i2c.adapter_id, sasd->asd.match.i2c.address);
 
-       icd->clk = v4l2_clk_register(&soc_camera_clk_ops, clk_name, "mclk", icd);
+       icd->clk = v4l2_clk_register(&soc_camera_clk_ops, clk_name, icd);
        if (IS_ERR(icd->clk)) {
                ret = PTR_ERR(icd->clk);
                goto eclkreg;
@@ -1650,7 +1662,7 @@ static int soc_of_bind(struct soc_camera_host *ici,
                snprintf(clk_name, sizeof(clk_name), "of-%s",
                         of_node_full_name(remote));
 
-       icd->clk = v4l2_clk_register(&soc_camera_clk_ops, clk_name, "mclk", icd);
+       icd->clk = v4l2_clk_register(&soc_camera_clk_ops, clk_name, icd);
        if (IS_ERR(icd->clk)) {
                ret = PTR_ERR(icd->clk);
                goto eclkreg;
@@ -1659,6 +1671,8 @@ static int soc_of_bind(struct soc_camera_host *ici,
        ret = v4l2_async_notifier_register(&ici->v4l2_dev, &sasc->notifier);
        if (!ret)
                return 0;
+
+       v4l2_clk_unregister(icd->clk);
 eclkreg:
        icd->clk = NULL;
        platform_device_del(sasc->pdev);
@@ -1751,9 +1765,7 @@ static int soc_camera_probe(struct soc_camera_host *ici,
                ret = -EINVAL;
                goto eadd;
        } else {
-               mutex_lock(&ici->clk_lock);
-               ret = ici->ops->clock_start(ici);
-               mutex_unlock(&ici->clk_lock);
+               ret = soc_camera_clock_start(ici);
                if (ret < 0)
                        goto eadd;
 
@@ -1793,9 +1805,7 @@ efinish:
                module_put(control->driver->owner);
 enodrv:
 eadddev:
-               mutex_lock(&ici->clk_lock);
-               ici->ops->clock_stop(ici);
-               mutex_unlock(&ici->clk_lock);
+               soc_camera_clock_stop(ici);
        }
 eadd:
        if (icd->vdev) {
@@ -1889,22 +1899,34 @@ static int default_enum_framesizes(struct soc_camera_device *icd,
        int ret;
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        const struct soc_camera_format_xlate *xlate;
-       __u32 pixfmt = fsize->pixel_format;
-       struct v4l2_frmsizeenum fsize_mbus = *fsize;
+       struct v4l2_subdev_frame_size_enum fse = {
+               .index = fsize->index,
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
 
-       xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
+       xlate = soc_camera_xlate_by_fourcc(icd, fsize->pixel_format);
        if (!xlate)
                return -EINVAL;
-       /* map xlate-code to pixel_format, sensor only handle xlate-code*/
-       fsize_mbus.pixel_format = xlate->code;
+       fse.code = xlate->code;
 
-       ret = v4l2_subdev_call(sd, video, enum_framesizes, &fsize_mbus);
+       ret = v4l2_subdev_call(sd, pad, enum_frame_size, NULL, &fse);
        if (ret < 0)
                return ret;
 
-       *fsize = fsize_mbus;
-       fsize->pixel_format = pixfmt;
-
+       if (fse.min_width == fse.max_width &&
+           fse.min_height == fse.max_height) {
+               fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+               fsize->discrete.width = fse.min_width;
+               fsize->discrete.height = fse.min_height;
+               return 0;
+       }
+       fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS;
+       fsize->stepwise.min_width = fse.min_width;
+       fsize->stepwise.max_width = fse.max_width;
+       fsize->stepwise.min_height = fse.min_height;
+       fsize->stepwise.max_height = fse.max_height;
+       fsize->stepwise.step_width = 1;
+       fsize->stepwise.step_height = 1;
        return 0;
 }
 
@@ -1921,8 +1943,6 @@ int soc_camera_host_register(struct soc_camera_host *ici)
            ((!ici->ops->init_videobuf ||
              !ici->ops->reqbufs) &&
             !ici->ops->init_videobuf2) ||
-           !ici->ops->clock_start ||
-           !ici->ops->clock_stop ||
            !ici->ops->poll ||
            !ici->v4l2_dev.dev)
                return -EINVAL;
index 86989d86abfaeb26bf3b191fef55bf25ecd10104..678ed9f353cbb6011c5deeafebd545fb5a13c4db 100644 (file)
@@ -1147,12 +1147,23 @@ static int viacam_enum_frameintervals(struct file *filp, void *priv,
                struct v4l2_frmivalenum *interval)
 {
        struct via_camera *cam = priv;
+       struct v4l2_subdev_frame_interval_enum fie = {
+               .index = interval->index,
+               .code = cam->mbus_code,
+               .width = cam->sensor_format.width,
+               .height = cam->sensor_format.height,
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        int ret;
 
        mutex_lock(&cam->lock);
-       ret = sensor_call(cam, video, enum_frameintervals, interval);
+       ret = sensor_call(cam, pad, enum_frame_interval, NULL, &fie);
        mutex_unlock(&cam->lock);
-       return ret;
+       if (ret)
+               return ret;
+       interval->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+       interval->discrete = fie.interval;
+       return 0;
 }
 
 
index d9d844aab39b76aa49d43bf5bcb8ade5fdfaf826..4d6b4cc57c577e4c1295d646a5e4a57668df2253 100644 (file)
@@ -142,7 +142,7 @@ static struct vim2m_fmt *find_format(struct v4l2_format *f)
 
 struct vim2m_dev {
        struct v4l2_device      v4l2_dev;
-       struct video_device     *vfd;
+       struct video_device     vfd;
 
        atomic_t                num_inst;
        struct mutex            dev_mutex;
@@ -968,7 +968,7 @@ static struct video_device vim2m_videodev = {
        .fops           = &vim2m_fops,
        .ioctl_ops      = &vim2m_ioctl_ops,
        .minor          = -1,
-       .release        = video_device_release,
+       .release        = video_device_release_empty,
 };
 
 static struct v4l2_m2m_ops m2m_ops = {
@@ -996,26 +996,19 @@ static int vim2m_probe(struct platform_device *pdev)
        atomic_set(&dev->num_inst, 0);
        mutex_init(&dev->dev_mutex);
 
-       vfd = video_device_alloc();
-       if (!vfd) {
-               v4l2_err(&dev->v4l2_dev, "Failed to allocate video device\n");
-               ret = -ENOMEM;
-               goto unreg_dev;
-       }
-
-       *vfd = vim2m_videodev;
+       dev->vfd = vim2m_videodev;
+       vfd = &dev->vfd;
        vfd->lock = &dev->dev_mutex;
        vfd->v4l2_dev = &dev->v4l2_dev;
 
        ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
        if (ret) {
                v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
-               goto rel_vdev;
+               goto unreg_dev;
        }
 
        video_set_drvdata(vfd, dev);
        snprintf(vfd->name, sizeof(vfd->name), "%s", vim2m_videodev.name);
-       dev->vfd = vfd;
        v4l2_info(&dev->v4l2_dev,
                        "Device registered as /dev/video%d\n", vfd->num);
 
@@ -1033,9 +1026,7 @@ static int vim2m_probe(struct platform_device *pdev)
 
 err_m2m:
        v4l2_m2m_release(dev->m2m_dev);
-       video_unregister_device(dev->vfd);
-rel_vdev:
-       video_device_release(vfd);
+       video_unregister_device(&dev->vfd);
 unreg_dev:
        v4l2_device_unregister(&dev->v4l2_dev);
 
@@ -1049,7 +1040,7 @@ static int vim2m_remove(struct platform_device *pdev)
        v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_NAME);
        v4l2_m2m_release(dev->m2m_dev);
        del_timer_sync(&dev->timer);
-       video_unregister_device(dev->vfd);
+       video_unregister_device(&dev->vfd);
        v4l2_device_unregister(&dev->v4l2_dev);
 
        return 0;
index a7e033a5d291fdfc874931e6138884083622a929..d33f16495dbce50d7a5b42e6d1e98f107effb61a 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/vmalloc.h>
 #include <linux/font.h>
 #include <linux/mutex.h>
+#include <linux/platform_device.h>
 #include <linux/videodev2.h>
 #include <linux/v4l2-dv-timings.h>
 #include <media/videobuf2-vmalloc.h>
@@ -618,7 +619,23 @@ static const struct v4l2_ioctl_ops vivid_ioctl_ops = {
        Initialization and module stuff
    ------------------------------------------------------------------*/
 
-static int __init vivid_create_instance(int inst)
+static void vivid_dev_release(struct v4l2_device *v4l2_dev)
+{
+       struct vivid_dev *dev = container_of(v4l2_dev, struct vivid_dev, v4l2_dev);
+
+       vivid_free_controls(dev);
+       v4l2_device_unregister(&dev->v4l2_dev);
+       vfree(dev->scaled_line);
+       vfree(dev->blended_line);
+       vfree(dev->edid);
+       vfree(dev->bitmap_cap);
+       vfree(dev->bitmap_out);
+       tpg_free(&dev->tpg);
+       kfree(dev->query_dv_timings_qmenu);
+       kfree(dev);
+}
+
+static int vivid_create_instance(struct platform_device *pdev, int inst)
 {
        static const struct v4l2_dv_timings def_dv_timings =
                                        V4L2_DV_BT_CEA_1280X720P60;
@@ -646,9 +663,12 @@ static int __init vivid_create_instance(int inst)
        /* register v4l2_device */
        snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
                        "%s-%03d", VIVID_MODULE_NAME, inst);
-       ret = v4l2_device_register(NULL, &dev->v4l2_dev);
-       if (ret)
-               goto free_dev;
+       ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
+       if (ret) {
+               kfree(dev);
+               return ret;
+       }
+       dev->v4l2_dev.release = vivid_dev_release;
 
        /* start detecting feature set */
 
@@ -1256,15 +1276,8 @@ unreg_dev:
        video_unregister_device(&dev->vbi_cap_dev);
        video_unregister_device(&dev->vid_out_dev);
        video_unregister_device(&dev->vid_cap_dev);
-       vivid_free_controls(dev);
-       v4l2_device_unregister(&dev->v4l2_dev);
 free_dev:
-       vfree(dev->scaled_line);
-       vfree(dev->blended_line);
-       vfree(dev->edid);
-       tpg_free(&dev->tpg);
-       kfree(dev->query_dv_timings_qmenu);
-       kfree(dev);
+       v4l2_device_put(&dev->v4l2_dev);
        return ret;
 }
 
@@ -1274,7 +1287,7 @@ free_dev:
    will succeed. This is limited to the maximum number of devices that
    videodev supports, which is equal to VIDEO_NUM_DEVICES.
  */
-static int __init vivid_init(void)
+static int vivid_probe(struct platform_device *pdev)
 {
        const struct font_desc *font = find_font("VGA8x16");
        int ret = 0, i;
@@ -1289,7 +1302,7 @@ static int __init vivid_init(void)
        n_devs = clamp_t(unsigned, n_devs, 1, VIVID_MAX_DEVS);
 
        for (i = 0; i < n_devs; i++) {
-               ret = vivid_create_instance(i);
+               ret = vivid_create_instance(pdev, i);
                if (ret) {
                        /* If some instantiations succeeded, keep driver */
                        if (i)
@@ -1309,7 +1322,7 @@ static int __init vivid_init(void)
        return ret;
 }
 
-static void __exit vivid_exit(void)
+static int vivid_remove(struct platform_device *pdev)
 {
        struct vivid_dev *dev;
        unsigned i;
@@ -1358,18 +1371,48 @@ static void __exit vivid_exit(void)
                        unregister_framebuffer(&dev->fb_info);
                        vivid_fb_release_buffers(dev);
                }
-               v4l2_device_unregister(&dev->v4l2_dev);
-               vivid_free_controls(dev);
-               vfree(dev->scaled_line);
-               vfree(dev->blended_line);
-               vfree(dev->edid);
-               vfree(dev->bitmap_cap);
-               vfree(dev->bitmap_out);
-               tpg_free(&dev->tpg);
-               kfree(dev->query_dv_timings_qmenu);
-               kfree(dev);
+               v4l2_device_put(&dev->v4l2_dev);
                vivid_devs[i] = NULL;
        }
+       return 0;
+}
+
+static void vivid_pdev_release(struct device *dev)
+{
+}
+
+static struct platform_device vivid_pdev = {
+       .name           = "vivid",
+       .dev.release    = vivid_pdev_release,
+};
+
+static struct platform_driver vivid_pdrv = {
+       .probe          = vivid_probe,
+       .remove         = vivid_remove,
+       .driver         = {
+               .name   = "vivid",
+       },
+};
+
+static int __init vivid_init(void)
+{
+       int ret;
+
+       ret = platform_device_register(&vivid_pdev);
+       if (ret)
+               return ret;
+
+       ret = platform_driver_register(&vivid_pdrv);
+       if (ret)
+               platform_device_unregister(&vivid_pdev);
+
+       return ret;
+}
+
+static void __exit vivid_exit(void)
+{
+       platform_driver_unregister(&vivid_pdrv);
+       platform_device_unregister(&vivid_pdev);
 }
 
 module_init(vivid_init);
index 4b497df4b6a433f0522ffb334dc0ec570e3faa8e..9e15aee9a52e152e8f1ce93451030d4acdded6c1 100644 (file)
@@ -79,12 +79,14 @@ extern unsigned vivid_debug;
 struct vivid_fmt {
        const char *name;
        u32     fourcc;          /* v4l2 format id */
-       u8      depth;
        bool    is_yuv;
        bool    can_do_overlay;
+       u8      vdownsampling[TPG_MAX_PLANES];
        u32     alpha_mask;
        u8      planes;
-       u32     data_offset[2];
+       u8      buffers;
+       u32     data_offset[TPG_MAX_PLANES];
+       u32     bit_depth[TPG_MAX_PLANES];
 };
 
 extern struct vivid_fmt vivid_formats[];
@@ -332,7 +334,7 @@ struct vivid_dev {
        u32                             ycbcr_enc_out;
        u32                             quantization_out;
        u32                             service_set_out;
-       u32                             bytesperline_out[2];
+       unsigned                        bytesperline_out[TPG_MAX_PLANES];
        unsigned                        tv_field_out;
        unsigned                        tv_audio_output;
        bool                            vbi_out_have_wss;
index 32a798f2d9539d802d21e5415448d20cdcf89ccc..2b9070098b084cb73048cf6fbb56fac7d18cc12d 100644 (file)
@@ -818,7 +818,7 @@ static int vivid_vid_out_s_ctrl(struct v4l2_ctrl *ctrl)
                dev->dvi_d_out = ctrl->val == V4L2_DV_TX_MODE_DVI_D;
                if (!vivid_is_hdmi_out(dev))
                        break;
-               if (!dev->dvi_d_out && (bt->standards & V4L2_DV_BT_STD_CEA861)) {
+               if (!dev->dvi_d_out && (bt->flags & V4L2_DV_FL_IS_CE_VIDEO)) {
                        if (bt->width == 720 && bt->height <= 576)
                                dev->colorspace_out = V4L2_COLORSPACE_SMPTE170M;
                        else
index 39a67cfae120079985598e8fc6500dac85d95265..1727f5453f0bb33c77dc5b3fc7422466ced39408 100644 (file)
@@ -229,14 +229,29 @@ static void vivid_precalc_copy_rects(struct vivid_dev *dev)
                dev->loop_vid_overlay_cap.left, dev->loop_vid_overlay_cap.top);
 }
 
+static void *plane_vaddr(struct tpg_data *tpg, struct vivid_buffer *buf,
+                        unsigned p, unsigned bpl[TPG_MAX_PLANES], unsigned h)
+{
+       unsigned i;
+       void *vbuf;
+
+       if (p == 0 || tpg_g_buffers(tpg) > 1)
+               return vb2_plane_vaddr(&buf->vb, p);
+       vbuf = vb2_plane_vaddr(&buf->vb, 0);
+       for (i = 0; i < p; i++)
+               vbuf += bpl[i] * h / tpg->vdownsampling[i];
+       return vbuf;
+}
+
 static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf,
                struct vivid_buffer *vid_cap_buf)
 {
        bool blank = dev->must_blank[vid_cap_buf->vb.v4l2_buf.index];
        struct tpg_data *tpg = &dev->tpg;
        struct vivid_buffer *vid_out_buf = NULL;
-       unsigned pixsize = tpg_g_twopixelsize(tpg, p) / 2;
-       unsigned img_width = dev->compose_cap.width;
+       unsigned vdiv = dev->fmt_out->vdownsampling[p];
+       unsigned twopixsize = tpg_g_twopixelsize(tpg, p);
+       unsigned img_width = tpg_hdiv(tpg, p, dev->compose_cap.width);
        unsigned img_height = dev->compose_cap.height;
        unsigned stride_cap = tpg->bytesperline[p];
        unsigned stride_out = dev->bytesperline_out[p];
@@ -255,6 +270,7 @@ static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf,
        unsigned vid_overlay_fract_part = 0;
        unsigned vid_overlay_y = 0;
        unsigned vid_overlay_error = 0;
+       unsigned vid_cap_left = tpg_hdiv(tpg, p, dev->loop_vid_cap.left);
        unsigned vid_cap_right;
        bool quick;
 
@@ -269,25 +285,29 @@ static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf,
 
        vid_cap_buf->vb.v4l2_buf.field = vid_out_buf->vb.v4l2_buf.field;
 
-       voutbuf = vb2_plane_vaddr(&vid_out_buf->vb, p) +
-                                 vid_out_buf->vb.v4l2_planes[p].data_offset;
-       voutbuf += dev->loop_vid_out.left * pixsize + dev->loop_vid_out.top * stride_out;
-       vcapbuf += dev->compose_cap.left * pixsize + dev->compose_cap.top * stride_cap;
+       voutbuf = plane_vaddr(tpg, vid_out_buf, p,
+                             dev->bytesperline_out, dev->fmt_out_rect.height);
+       if (p < dev->fmt_out->buffers)
+               voutbuf += vid_out_buf->vb.v4l2_planes[p].data_offset;
+       voutbuf += tpg_hdiv(tpg, p, dev->loop_vid_out.left) +
+               (dev->loop_vid_out.top / vdiv) * stride_out;
+       vcapbuf += tpg_hdiv(tpg, p, dev->compose_cap.left) +
+               (dev->compose_cap.top / vdiv) * stride_cap;
 
        if (dev->loop_vid_copy.width == 0 || dev->loop_vid_copy.height == 0) {
                /*
                 * If there is nothing to copy, then just fill the capture window
                 * with black.
                 */
-               for (y = 0; y < hmax; y++, vcapbuf += stride_cap)
-                       memcpy(vcapbuf, tpg->black_line[p], img_width * pixsize);
+               for (y = 0; y < hmax / vdiv; y++, vcapbuf += stride_cap)
+                       memcpy(vcapbuf, tpg->black_line[p], img_width);
                return 0;
        }
 
        if (dev->overlay_out_enabled &&
            dev->loop_vid_overlay.width && dev->loop_vid_overlay.height) {
                vosdbuf = dev->video_vbase;
-               vosdbuf += dev->loop_fb_copy.left * pixsize +
+               vosdbuf += (dev->loop_fb_copy.left * twopixsize) / 2 +
                           dev->loop_fb_copy.top * stride_osd;
                vid_overlay_int_part = dev->loop_vid_overlay.height /
                                       dev->loop_vid_overlay_cap.height;
@@ -295,12 +315,12 @@ static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf,
                                         dev->loop_vid_overlay_cap.height;
        }
 
-       vid_cap_right = dev->loop_vid_cap.left + dev->loop_vid_cap.width;
+       vid_cap_right = tpg_hdiv(tpg, p, dev->loop_vid_cap.left + dev->loop_vid_cap.width);
        /* quick is true if no video scaling is needed */
        quick = dev->loop_vid_out.width == dev->loop_vid_cap.width;
 
        dev->cur_scaled_line = dev->loop_vid_out.height;
-       for (y = 0; y < hmax; y++, vcapbuf += stride_cap) {
+       for (y = 0; y < hmax; y += vdiv, vcapbuf += stride_cap) {
                /* osdline is true if this line requires overlay blending */
                bool osdline = vosdbuf && y >= dev->loop_vid_overlay_cap.top &&
                          y < dev->loop_vid_overlay_cap.top + dev->loop_vid_overlay_cap.height;
@@ -311,34 +331,34 @@ static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf,
                 */
                if (y < dev->loop_vid_cap.top ||
                    y >= dev->loop_vid_cap.top + dev->loop_vid_cap.height) {
-                       memcpy(vcapbuf, tpg->black_line[p], img_width * pixsize);
+                       memcpy(vcapbuf, tpg->black_line[p], img_width);
                        continue;
                }
 
                /* fill the left border with black */
                if (dev->loop_vid_cap.left)
-                       memcpy(vcapbuf, tpg->black_line[p], dev->loop_vid_cap.left * pixsize);
+                       memcpy(vcapbuf, tpg->black_line[p], vid_cap_left);
 
                /* fill the right border with black */
                if (vid_cap_right < img_width)
-                       memcpy(vcapbuf + vid_cap_right * pixsize,
-                               tpg->black_line[p], (img_width - vid_cap_right) * pixsize);
+                       memcpy(vcapbuf + vid_cap_right, tpg->black_line[p],
+                               img_width - vid_cap_right);
 
                if (quick && !osdline) {
-                       memcpy(vcapbuf + dev->loop_vid_cap.left * pixsize,
+                       memcpy(vcapbuf + vid_cap_left,
                               voutbuf + vid_out_y * stride_out,
-                              dev->loop_vid_cap.width * pixsize);
+                              tpg_hdiv(tpg, p, dev->loop_vid_cap.width));
                        goto update_vid_out_y;
                }
                if (dev->cur_scaled_line == vid_out_y) {
-                       memcpy(vcapbuf + dev->loop_vid_cap.left * pixsize,
-                              dev->scaled_line,
-                              dev->loop_vid_cap.width * pixsize);
+                       memcpy(vcapbuf + vid_cap_left, dev->scaled_line,
+                              tpg_hdiv(tpg, p, dev->loop_vid_cap.width));
                        goto update_vid_out_y;
                }
                if (!osdline) {
                        scale_line(voutbuf + vid_out_y * stride_out, dev->scaled_line,
-                               dev->loop_vid_out.width, dev->loop_vid_cap.width,
+                               tpg_hdiv(tpg, p, dev->loop_vid_out.width),
+                               tpg_hdiv(tpg, p, dev->loop_vid_cap.width),
                                tpg_g_twopixelsize(tpg, p));
                } else {
                        /*
@@ -346,7 +366,8 @@ static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf,
                         * loop_vid_overlay rectangle.
                         */
                        unsigned offset =
-                               (dev->loop_vid_overlay.left - dev->loop_vid_copy.left) * pixsize;
+                               ((dev->loop_vid_overlay.left - dev->loop_vid_copy.left) *
+                                twopixsize) / 2;
                        u8 *osd = vosdbuf + vid_overlay_y * stride_osd;
 
                        scale_line(voutbuf + vid_out_y * stride_out, dev->blended_line,
@@ -356,18 +377,17 @@ static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf,
                                blend_line(dev, vid_overlay_y + dev->loop_vid_overlay.top,
                                           dev->loop_vid_overlay.left,
                                           dev->blended_line + offset, osd,
-                                          dev->loop_vid_overlay.width, pixsize);
+                                          dev->loop_vid_overlay.width, twopixsize / 2);
                        else
                                memcpy(dev->blended_line + offset,
-                                      osd, dev->loop_vid_overlay.width * pixsize);
+                                      osd, (dev->loop_vid_overlay.width * twopixsize) / 2);
                        scale_line(dev->blended_line, dev->scaled_line,
                                        dev->loop_vid_copy.width, dev->loop_vid_cap.width,
                                        tpg_g_twopixelsize(tpg, p));
                }
                dev->cur_scaled_line = vid_out_y;
-               memcpy(vcapbuf + dev->loop_vid_cap.left * pixsize,
-                      dev->scaled_line,
-                      dev->loop_vid_cap.width * pixsize);
+               memcpy(vcapbuf + vid_cap_left, dev->scaled_line,
+                      tpg_hdiv(tpg, p, dev->loop_vid_cap.width));
 
 update_vid_out_y:
                if (osdline) {
@@ -380,21 +400,22 @@ update_vid_out_y:
                }
                vid_out_y += vid_out_int_part;
                vid_out_error += vid_out_fract_part;
-               if (vid_out_error >= dev->loop_vid_cap.height) {
-                       vid_out_error -= dev->loop_vid_cap.height;
+               if (vid_out_error >= dev->loop_vid_cap.height / vdiv) {
+                       vid_out_error -= dev->loop_vid_cap.height / vdiv;
                        vid_out_y++;
                }
        }
 
        if (!blank)
                return 0;
-       for (; y < img_height; y++, vcapbuf += stride_cap)
-               memcpy(vcapbuf, tpg->contrast_line[p], img_width * pixsize);
+       for (; y < img_height; y += vdiv, vcapbuf += stride_cap)
+               memcpy(vcapbuf, tpg->contrast_line[p], img_width);
        return 0;
 }
 
 static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
 {
+       struct tpg_data *tpg = &dev->tpg;
        unsigned factor = V4L2_FIELD_HAS_T_OR_B(dev->field_cap) ? 2 : 1;
        unsigned line_height = 16 / factor;
        bool is_tv = vivid_is_sdtv_cap(dev);
@@ -427,7 +448,7 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
                 * standards.
                 */
                buf->vb.v4l2_buf.field = ((dev->vid_cap_seq_count & 1) ^ is_60hz) ?
-                       V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM;
+                       V4L2_FIELD_BOTTOM : V4L2_FIELD_TOP;
                /*
                 * The sequence counter counts frames, not fields. So divide
                 * by two.
@@ -436,27 +457,29 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
        } else {
                buf->vb.v4l2_buf.field = dev->field_cap;
        }
-       tpg_s_field(&dev->tpg, buf->vb.v4l2_buf.field);
-       tpg_s_perc_fill_blank(&dev->tpg, dev->must_blank[buf->vb.v4l2_buf.index]);
+       tpg_s_field(tpg, buf->vb.v4l2_buf.field,
+                   dev->field_cap == V4L2_FIELD_ALTERNATE);
+       tpg_s_perc_fill_blank(tpg, dev->must_blank[buf->vb.v4l2_buf.index]);
 
        vivid_precalc_copy_rects(dev);
 
-       for (p = 0; p < tpg_g_planes(&dev->tpg); p++) {
-               void *vbuf = vb2_plane_vaddr(&buf->vb, p);
+       for (p = 0; p < tpg_g_planes(tpg); p++) {
+               void *vbuf = plane_vaddr(tpg, buf, p,
+                                        tpg->bytesperline, tpg->buf_height);
 
                /*
                 * The first plane of a multiplanar format has a non-zero
                 * data_offset. This helps testing whether the application
                 * correctly supports non-zero data offsets.
                 */
-               if (dev->fmt_cap->data_offset[p]) {
+               if (p < tpg_g_buffers(tpg) && dev->fmt_cap->data_offset[p]) {
                        memset(vbuf, dev->fmt_cap->data_offset[p] & 0xff,
                               dev->fmt_cap->data_offset[p]);
                        vbuf += dev->fmt_cap->data_offset[p];
                }
-               tpg_calc_text_basep(&dev->tpg, basep, p, vbuf);
+               tpg_calc_text_basep(tpg, basep, p, vbuf);
                if (!is_loop || vivid_copy_buffer(dev, p, vbuf, buf))
-                       tpg_fillbuffer(&dev->tpg, vivid_get_std_cap(dev), p, vbuf);
+                       tpg_fill_plane_buffer(tpg, vivid_get_std_cap(dev), p, vbuf);
        }
        dev->must_blank[buf->vb.v4l2_buf.index] = false;
 
@@ -475,12 +498,12 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
                                (dev->field_cap == V4L2_FIELD_ALTERNATE) ?
                                        (buf->vb.v4l2_buf.field == V4L2_FIELD_TOP ?
                                         " top" : " bottom") : "");
-               tpg_gen_text(&dev->tpg, basep, line++ * line_height, 16, str);
+               tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
        }
        if (dev->osd_mode == 0) {
                snprintf(str, sizeof(str), " %dx%d, input %d ",
                                dev->src_rect.width, dev->src_rect.height, dev->input);
-               tpg_gen_text(&dev->tpg, basep, line++ * line_height, 16, str);
+               tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
 
                gain = v4l2_ctrl_g_ctrl(dev->gain);
                mutex_lock(dev->ctrl_hdl_user_vid.lock);
@@ -490,38 +513,38 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
                        dev->contrast->cur.val,
                        dev->saturation->cur.val,
                        dev->hue->cur.val);
-               tpg_gen_text(&dev->tpg, basep, line++ * line_height, 16, str);
+               tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
                snprintf(str, sizeof(str),
                        " autogain %d, gain %3d, alpha 0x%02x ",
                        dev->autogain->cur.val, gain, dev->alpha->cur.val);
                mutex_unlock(dev->ctrl_hdl_user_vid.lock);
-               tpg_gen_text(&dev->tpg, basep, line++ * line_height, 16, str);
+               tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
                mutex_lock(dev->ctrl_hdl_user_aud.lock);
                snprintf(str, sizeof(str),
                        " volume %3d, mute %d ",
                        dev->volume->cur.val, dev->mute->cur.val);
                mutex_unlock(dev->ctrl_hdl_user_aud.lock);
-               tpg_gen_text(&dev->tpg, basep, line++ * line_height, 16, str);
+               tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
                mutex_lock(dev->ctrl_hdl_user_gen.lock);
                snprintf(str, sizeof(str), " int32 %d, int64 %lld, bitmask %08x ",
                        dev->int32->cur.val,
                        *dev->int64->p_cur.p_s64,
                        dev->bitmask->cur.val);
-               tpg_gen_text(&dev->tpg, basep, line++ * line_height, 16, str);
+               tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
                snprintf(str, sizeof(str), " boolean %d, menu %s, string \"%s\" ",
                        dev->boolean->cur.val,
                        dev->menu->qmenu[dev->menu->cur.val],
                        dev->string->p_cur.p_char);
-               tpg_gen_text(&dev->tpg, basep, line++ * line_height, 16, str);
+               tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
                snprintf(str, sizeof(str), " integer_menu %lld, value %d ",
                        dev->int_menu->qmenu_int[dev->int_menu->cur.val],
                        dev->int_menu->cur.val);
                mutex_unlock(dev->ctrl_hdl_user_gen.lock);
-               tpg_gen_text(&dev->tpg, basep, line++ * line_height, 16, str);
+               tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
                if (dev->button_pressed) {
                        dev->button_pressed--;
                        snprintf(str, sizeof(str), " button pressed!");
-                       tpg_gen_text(&dev->tpg, basep, line++ * line_height, 16, str);
+                       tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
                }
        }
 
@@ -585,6 +608,12 @@ static void vivid_overlay(struct vivid_dev *dev, struct vivid_buffer *buf)
        bool quick = dev->bitmap_cap == NULL && dev->clipcount_cap == 0;
        int x, y, w, out_x = 0;
 
+       /*
+        * Overlay support is only supported for formats that have a twopixelsize
+        * that's >= 2. Warn and bail out if that's not the case.
+        */
+       if (WARN_ON(pixsize == 0))
+               return;
        if ((dev->overlay_cap_field == V4L2_FIELD_TOP ||
             dev->overlay_cap_field == V4L2_FIELD_BOTTOM) &&
            dev->overlay_cap_field != buf->vb.v4l2_buf.field)
index 4af55f18829f78eb640d2677d6535cfb387a291a..caf131666e37426f63029462b10839c83634fcdd 100644 (file)
@@ -27,6 +27,7 @@
 #include <media/v4l2-common.h>
 #include <media/v4l2-event.h>
 #include <media/v4l2-dv-timings.h>
+#include <linux/fixp-arith.h>
 
 #include "vivid-core.h"
 #include "vivid-ctrls.h"
@@ -423,40 +424,19 @@ int vidioc_g_fmt_sdr_cap(struct file *file, void *fh, struct v4l2_format *f)
        return 0;
 }
 
-#define FIXP_FRAC    (1 << 15)
-#define FIXP_PI      ((int)(FIXP_FRAC * 3.141592653589))
-
-/* cos() from cx88 driver: cx88-dsp.c */
-static s32 fixp_cos(unsigned int x)
-{
-       u32 t2, t4, t6, t8;
-       u16 period = x / FIXP_PI;
-
-       if (period % 2)
-               return -fixp_cos(x - FIXP_PI);
-       x = x % FIXP_PI;
-       if (x > FIXP_PI/2)
-               return -fixp_cos(FIXP_PI/2 - (x % (FIXP_PI/2)));
-       /* Now x is between 0 and FIXP_PI/2.
-        * To calculate cos(x) we use it's Taylor polinom. */
-       t2 = x*x/FIXP_FRAC/2;
-       t4 = t2*x/FIXP_FRAC*x/FIXP_FRAC/3/4;
-       t6 = t4*x/FIXP_FRAC*x/FIXP_FRAC/5/6;
-       t8 = t6*x/FIXP_FRAC*x/FIXP_FRAC/7/8;
-       return FIXP_FRAC-t2+t4-t6+t8;
-}
-
-static inline s32 fixp_sin(unsigned int x)
-{
-       return -fixp_cos(x + (FIXP_PI / 2));
-}
+#define FIXP_N    (15)
+#define FIXP_FRAC (1 << FIXP_N)
+#define FIXP_2PI  ((int)(2 * 3.141592653589 * FIXP_FRAC))
 
 void vivid_sdr_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf)
 {
        u8 *vbuf = vb2_plane_vaddr(&buf->vb, 0);
        unsigned long i;
        unsigned long plane_size = vb2_plane_size(&buf->vb, 0);
-       int fixp_src_phase_step, fixp_i, fixp_q;
+       s32 src_phase_step;
+       s32 mod_phase_step;
+       s32 fixp_i;
+       s32 fixp_q;
 
        /*
         * TODO: Generated beep tone goes very crackly when sample rate is
@@ -466,28 +446,36 @@ void vivid_sdr_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf)
 
        /* calculate phase step */
        #define BEEP_FREQ 1000 /* 1kHz beep */
-       fixp_src_phase_step = DIV_ROUND_CLOSEST(2 * FIXP_PI * BEEP_FREQ,
+       src_phase_step = DIV_ROUND_CLOSEST(FIXP_2PI * BEEP_FREQ,
                        dev->sdr_adc_freq);
 
        for (i = 0; i < plane_size; i += 2) {
-               dev->sdr_fixp_mod_phase += fixp_cos(dev->sdr_fixp_src_phase);
-               dev->sdr_fixp_src_phase += fixp_src_phase_step;
+               mod_phase_step = fixp_cos32_rad(dev->sdr_fixp_src_phase,
+                                               FIXP_2PI) >> (31 - FIXP_N);
+
+               dev->sdr_fixp_src_phase += src_phase_step;
+               dev->sdr_fixp_mod_phase += mod_phase_step / 4;
 
                /*
                 * Transfer phases to [0 / 2xPI] in order to avoid variable
                 * overflow and make it suitable for cosine implementation
                 * used, which does not support negative angles.
                 */
-               while (dev->sdr_fixp_mod_phase < (0 * FIXP_PI))
-                       dev->sdr_fixp_mod_phase += (2 * FIXP_PI);
-               while (dev->sdr_fixp_mod_phase > (2 * FIXP_PI))
-                       dev->sdr_fixp_mod_phase -= (2 * FIXP_PI);
+               while (dev->sdr_fixp_mod_phase < FIXP_2PI)
+                       dev->sdr_fixp_mod_phase += FIXP_2PI;
+               while (dev->sdr_fixp_mod_phase > FIXP_2PI)
+                       dev->sdr_fixp_mod_phase -= FIXP_2PI;
+
+               while (dev->sdr_fixp_src_phase > FIXP_2PI)
+                       dev->sdr_fixp_src_phase -= FIXP_2PI;
 
-               while (dev->sdr_fixp_src_phase > (2 * FIXP_PI))
-                       dev->sdr_fixp_src_phase -= (2 * FIXP_PI);
+               fixp_i = fixp_cos32_rad(dev->sdr_fixp_mod_phase, FIXP_2PI);
+               fixp_q = fixp_sin32_rad(dev->sdr_fixp_mod_phase, FIXP_2PI);
 
-               fixp_i = fixp_cos(dev->sdr_fixp_mod_phase);
-               fixp_q = fixp_sin(dev->sdr_fixp_mod_phase);
+               /* Normalize fraction values represented with 32 bit precision
+                * to fixed point representation with FIXP_N bits */
+               fixp_i >>= (31 - FIXP_N);
+               fixp_q >>= (31 - FIXP_N);
 
                /* convert 'fixp float' to u8 */
                /* u8 = X * 127.5f + 127.5f; where X is float [-1.0 / +1.0] */
index 34493f435d5ab42906f682ca9356eabffcadbbb4..cb766eb154e71eff55004bbf0e667fc44964dde7 100644 (file)
@@ -35,7 +35,10 @@ const char * const tpg_pattern_strings[] = {
        "100% Green",
        "100% Blue",
        "16x16 Checkers",
+       "2x2 Checkers",
        "1x1 Checkers",
+       "2x2 Red/Green Checkers",
+       "1x1 Red/Green Checkers",
        "Alternating Hor Lines",
        "Alternating Vert Lines",
        "One Pixel Wide Cross",
@@ -120,15 +123,20 @@ int tpg_alloc(struct tpg_data *tpg, unsigned max_w)
        tpg->max_line_width = max_w;
        for (pat = 0; pat < TPG_MAX_PAT_LINES; pat++) {
                for (plane = 0; plane < TPG_MAX_PLANES; plane++) {
-                       unsigned pixelsz = plane ? 1 : 4;
+                       unsigned pixelsz = plane ? 2 : 4;
 
                        tpg->lines[pat][plane] = vzalloc(max_w * 2 * pixelsz);
                        if (!tpg->lines[pat][plane])
                                return -ENOMEM;
+                       if (plane == 0)
+                               continue;
+                       tpg->downsampled_lines[pat][plane] = vzalloc(max_w * 2 * pixelsz);
+                       if (!tpg->downsampled_lines[pat][plane])
+                               return -ENOMEM;
                }
        }
        for (plane = 0; plane < TPG_MAX_PLANES; plane++) {
-               unsigned pixelsz = plane ? 1 : 4;
+               unsigned pixelsz = plane ? 2 : 4;
 
                tpg->contrast_line[plane] = vzalloc(max_w * pixelsz);
                if (!tpg->contrast_line[plane])
@@ -152,6 +160,10 @@ void tpg_free(struct tpg_data *tpg)
                for (plane = 0; plane < TPG_MAX_PLANES; plane++) {
                        vfree(tpg->lines[pat][plane]);
                        tpg->lines[pat][plane] = NULL;
+                       if (plane == 0)
+                               continue;
+                       vfree(tpg->downsampled_lines[pat][plane]);
+                       tpg->downsampled_lines[pat][plane] = NULL;
                }
        for (plane = 0; plane < TPG_MAX_PLANES; plane++) {
                vfree(tpg->contrast_line[plane]);
@@ -167,14 +179,38 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc)
 {
        tpg->fourcc = fourcc;
        tpg->planes = 1;
+       tpg->buffers = 1;
        tpg->recalc_colors = true;
+       tpg->interleaved = false;
+       tpg->vdownsampling[0] = 1;
+       tpg->hdownsampling[0] = 1;
+       tpg->hmask[0] = ~0;
+       tpg->hmask[1] = ~0;
+       tpg->hmask[2] = ~0;
+
        switch (fourcc) {
+       case V4L2_PIX_FMT_SBGGR8:
+       case V4L2_PIX_FMT_SGBRG8:
+       case V4L2_PIX_FMT_SGRBG8:
+       case V4L2_PIX_FMT_SRGGB8:
+               tpg->interleaved = true;
+               tpg->vdownsampling[1] = 1;
+               tpg->hdownsampling[1] = 1;
+               tpg->planes = 2;
+               /* fall through */
+       case V4L2_PIX_FMT_RGB332:
        case V4L2_PIX_FMT_RGB565:
        case V4L2_PIX_FMT_RGB565X:
+       case V4L2_PIX_FMT_RGB444:
+       case V4L2_PIX_FMT_XRGB444:
+       case V4L2_PIX_FMT_ARGB444:
        case V4L2_PIX_FMT_RGB555:
        case V4L2_PIX_FMT_XRGB555:
        case V4L2_PIX_FMT_ARGB555:
        case V4L2_PIX_FMT_RGB555X:
+       case V4L2_PIX_FMT_XRGB555X:
+       case V4L2_PIX_FMT_ARGB555X:
+       case V4L2_PIX_FMT_BGR666:
        case V4L2_PIX_FMT_RGB24:
        case V4L2_PIX_FMT_BGR24:
        case V4L2_PIX_FMT_RGB32:
@@ -183,16 +219,72 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc)
        case V4L2_PIX_FMT_XBGR32:
        case V4L2_PIX_FMT_ARGB32:
        case V4L2_PIX_FMT_ABGR32:
+       case V4L2_PIX_FMT_GREY:
                tpg->is_yuv = false;
                break;
+       case V4L2_PIX_FMT_YUV444:
+       case V4L2_PIX_FMT_YUV555:
+       case V4L2_PIX_FMT_YUV565:
+       case V4L2_PIX_FMT_YUV32:
+               tpg->is_yuv = true;
+               break;
+       case V4L2_PIX_FMT_YUV420M:
+       case V4L2_PIX_FMT_YVU420M:
+               tpg->buffers = 3;
+               /* fall through */
+       case V4L2_PIX_FMT_YUV420:
+       case V4L2_PIX_FMT_YVU420:
+               tpg->vdownsampling[1] = 2;
+               tpg->vdownsampling[2] = 2;
+               tpg->hdownsampling[1] = 2;
+               tpg->hdownsampling[2] = 2;
+               tpg->planes = 3;
+               tpg->is_yuv = true;
+               break;
+       case V4L2_PIX_FMT_YUV422P:
+               tpg->vdownsampling[1] = 1;
+               tpg->vdownsampling[2] = 1;
+               tpg->hdownsampling[1] = 2;
+               tpg->hdownsampling[2] = 2;
+               tpg->planes = 3;
+               tpg->is_yuv = true;
+               break;
        case V4L2_PIX_FMT_NV16M:
        case V4L2_PIX_FMT_NV61M:
+               tpg->buffers = 2;
+               /* fall through */
+       case V4L2_PIX_FMT_NV16:
+       case V4L2_PIX_FMT_NV61:
+               tpg->vdownsampling[1] = 1;
+               tpg->hdownsampling[1] = 1;
+               tpg->hmask[1] = ~1;
                tpg->planes = 2;
-               /* fall-through */
+               tpg->is_yuv = true;
+               break;
+       case V4L2_PIX_FMT_NV12M:
+       case V4L2_PIX_FMT_NV21M:
+               tpg->buffers = 2;
+               /* fall through */
+       case V4L2_PIX_FMT_NV12:
+       case V4L2_PIX_FMT_NV21:
+               tpg->vdownsampling[1] = 2;
+               tpg->hdownsampling[1] = 1;
+               tpg->hmask[1] = ~1;
+               tpg->planes = 2;
+               tpg->is_yuv = true;
+               break;
+       case V4L2_PIX_FMT_NV24:
+       case V4L2_PIX_FMT_NV42:
+               tpg->vdownsampling[1] = 1;
+               tpg->hdownsampling[1] = 1;
+               tpg->planes = 2;
+               tpg->is_yuv = true;
+               break;
        case V4L2_PIX_FMT_YUYV:
        case V4L2_PIX_FMT_UYVY:
        case V4L2_PIX_FMT_YVYU:
        case V4L2_PIX_FMT_VYUY:
+               tpg->hmask[0] = ~1;
                tpg->is_yuv = true;
                break;
        default:
@@ -200,35 +292,75 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc)
        }
 
        switch (fourcc) {
+       case V4L2_PIX_FMT_RGB332:
+               tpg->twopixelsize[0] = 2;
+               break;
        case V4L2_PIX_FMT_RGB565:
        case V4L2_PIX_FMT_RGB565X:
+       case V4L2_PIX_FMT_RGB444:
+       case V4L2_PIX_FMT_XRGB444:
+       case V4L2_PIX_FMT_ARGB444:
        case V4L2_PIX_FMT_RGB555:
        case V4L2_PIX_FMT_XRGB555:
        case V4L2_PIX_FMT_ARGB555:
        case V4L2_PIX_FMT_RGB555X:
+       case V4L2_PIX_FMT_XRGB555X:
+       case V4L2_PIX_FMT_ARGB555X:
        case V4L2_PIX_FMT_YUYV:
        case V4L2_PIX_FMT_UYVY:
        case V4L2_PIX_FMT_YVYU:
        case V4L2_PIX_FMT_VYUY:
+       case V4L2_PIX_FMT_YUV444:
+       case V4L2_PIX_FMT_YUV555:
+       case V4L2_PIX_FMT_YUV565:
                tpg->twopixelsize[0] = 2 * 2;
                break;
        case V4L2_PIX_FMT_RGB24:
        case V4L2_PIX_FMT_BGR24:
                tpg->twopixelsize[0] = 2 * 3;
                break;
+       case V4L2_PIX_FMT_BGR666:
        case V4L2_PIX_FMT_RGB32:
        case V4L2_PIX_FMT_BGR32:
        case V4L2_PIX_FMT_XRGB32:
        case V4L2_PIX_FMT_XBGR32:
        case V4L2_PIX_FMT_ARGB32:
        case V4L2_PIX_FMT_ABGR32:
+       case V4L2_PIX_FMT_YUV32:
                tpg->twopixelsize[0] = 2 * 4;
                break;
+       case V4L2_PIX_FMT_GREY:
+               tpg->twopixelsize[0] = 2;
+               break;
+       case V4L2_PIX_FMT_NV12:
+       case V4L2_PIX_FMT_NV21:
+       case V4L2_PIX_FMT_NV12M:
+       case V4L2_PIX_FMT_NV21M:
+       case V4L2_PIX_FMT_NV16:
+       case V4L2_PIX_FMT_NV61:
        case V4L2_PIX_FMT_NV16M:
        case V4L2_PIX_FMT_NV61M:
+       case V4L2_PIX_FMT_SBGGR8:
+       case V4L2_PIX_FMT_SGBRG8:
+       case V4L2_PIX_FMT_SGRBG8:
+       case V4L2_PIX_FMT_SRGGB8:
                tpg->twopixelsize[0] = 2;
                tpg->twopixelsize[1] = 2;
                break;
+       case V4L2_PIX_FMT_YUV422P:
+       case V4L2_PIX_FMT_YUV420:
+       case V4L2_PIX_FMT_YVU420:
+       case V4L2_PIX_FMT_YUV420M:
+       case V4L2_PIX_FMT_YVU420M:
+               tpg->twopixelsize[0] = 2;
+               tpg->twopixelsize[1] = 2;
+               tpg->twopixelsize[2] = 2;
+               break;
+       case V4L2_PIX_FMT_NV24:
+       case V4L2_PIX_FMT_NV42:
+               tpg->twopixelsize[0] = 2;
+               tpg->twopixelsize[1] = 4;
+               break;
        }
        return true;
 }
@@ -267,7 +399,8 @@ void tpg_reset_source(struct tpg_data *tpg, unsigned width, unsigned height,
        tpg->compose.width = width;
        tpg->compose.height = tpg->buf_height;
        for (p = 0; p < tpg->planes; p++)
-               tpg->bytesperline[p] = width * tpg->twopixelsize[p] / 2;
+               tpg->bytesperline[p] = (width * tpg->twopixelsize[p]) /
+                                      (2 * tpg->hdownsampling[p]);
        tpg->recalc_square_border = true;
 }
 
@@ -347,9 +480,9 @@ static void color_to_ycbcr(struct tpg_data *tpg, int r, int g, int b,
                { COEFF(0.5, 224),    COEFF(-0.445, 224), COEFF(-0.055, 224) },
        };
        static const int bt2020[3][3] = {
-               { COEFF(0.2726, 219),  COEFF(0.6780, 219),  COEFF(0.0593, 219)  },
+               { COEFF(0.2627, 219),  COEFF(0.6780, 219),  COEFF(0.0593, 219)  },
                { COEFF(-0.1396, 224), COEFF(-0.3604, 224), COEFF(0.5, 224)     },
-               { COEFF(0.5, 224),     COEFF(-0.4629, 224), COEFF(-0.0405, 224) },
+               { COEFF(0.5, 224),     COEFF(-0.4598, 224), COEFF(-0.0402, 224) },
        };
        bool full = tpg->real_quantization == V4L2_QUANTIZATION_FULL_RANGE;
        unsigned y_offset = full ? 0 : 16;
@@ -524,10 +657,10 @@ static void precalculate_color(struct tpg_data *tpg, int k)
                g <<= 4;
                b <<= 4;
        }
-       if (tpg->qual == TPG_QUAL_GRAY) {
+       if (tpg->qual == TPG_QUAL_GRAY || tpg->fourcc == V4L2_PIX_FMT_GREY) {
                /* Rec. 709 Luma function */
                /* (0.2126, 0.7152, 0.0722) * (255 * 256) */
-               r = g = b = ((13879 * r + 46688 * g + 4713 * b) >> 16) + (16 << 4);
+               r = g = b = (13879 * r + 46688 * g + 4713 * b) >> 16;
        }
 
        /*
@@ -601,9 +734,29 @@ static void precalculate_color(struct tpg_data *tpg, int k)
                        cb = clamp(cb, 16 << 4, 240 << 4);
                        cr = clamp(cr, 16 << 4, 240 << 4);
                }
-               tpg->colors[k][0] = clamp(y >> 4, 1, 254);
-               tpg->colors[k][1] = clamp(cb >> 4, 1, 254);
-               tpg->colors[k][2] = clamp(cr >> 4, 1, 254);
+               y = clamp(y >> 4, 1, 254);
+               cb = clamp(cb >> 4, 1, 254);
+               cr = clamp(cr >> 4, 1, 254);
+               switch (tpg->fourcc) {
+               case V4L2_PIX_FMT_YUV444:
+                       y >>= 4;
+                       cb >>= 4;
+                       cr >>= 4;
+                       break;
+               case V4L2_PIX_FMT_YUV555:
+                       y >>= 3;
+                       cb >>= 3;
+                       cr >>= 3;
+                       break;
+               case V4L2_PIX_FMT_YUV565:
+                       y >>= 3;
+                       cb >>= 2;
+                       cr >>= 3;
+                       break;
+               }
+               tpg->colors[k][0] = y;
+               tpg->colors[k][1] = cb;
+               tpg->colors[k][2] = cr;
        } else {
                if (tpg->real_quantization == V4L2_QUANTIZATION_LIM_RANGE) {
                        r = (r * 219) / 255 + (16 << 4);
@@ -611,20 +764,39 @@ static void precalculate_color(struct tpg_data *tpg, int k)
                        b = (b * 219) / 255 + (16 << 4);
                }
                switch (tpg->fourcc) {
+               case V4L2_PIX_FMT_RGB332:
+                       r >>= 9;
+                       g >>= 9;
+                       b >>= 10;
+                       break;
                case V4L2_PIX_FMT_RGB565:
                case V4L2_PIX_FMT_RGB565X:
                        r >>= 7;
                        g >>= 6;
                        b >>= 7;
                        break;
+               case V4L2_PIX_FMT_RGB444:
+               case V4L2_PIX_FMT_XRGB444:
+               case V4L2_PIX_FMT_ARGB444:
+                       r >>= 8;
+                       g >>= 8;
+                       b >>= 8;
+                       break;
                case V4L2_PIX_FMT_RGB555:
                case V4L2_PIX_FMT_XRGB555:
                case V4L2_PIX_FMT_ARGB555:
                case V4L2_PIX_FMT_RGB555X:
+               case V4L2_PIX_FMT_XRGB555X:
+               case V4L2_PIX_FMT_ARGB555X:
                        r >>= 7;
                        g >>= 7;
                        b >>= 7;
                        break;
+               case V4L2_PIX_FMT_BGR666:
+                       r >>= 6;
+                       g >>= 6;
+                       b >>= 6;
+                       break;
                default:
                        r >>= 4;
                        g >>= 4;
@@ -665,31 +837,120 @@ static void gen_twopix(struct tpg_data *tpg,
        b_v = tpg->colors[color][2]; /* B or precalculated V */
 
        switch (tpg->fourcc) {
+       case V4L2_PIX_FMT_GREY:
+               buf[0][offset] = r_y;
+               break;
+       case V4L2_PIX_FMT_YUV422P:
+       case V4L2_PIX_FMT_YUV420:
+       case V4L2_PIX_FMT_YUV420M:
+               buf[0][offset] = r_y;
+               if (odd) {
+                       buf[1][0] = (buf[1][0] + g_u) / 2;
+                       buf[2][0] = (buf[2][0] + b_v) / 2;
+                       buf[1][1] = buf[1][0];
+                       buf[2][1] = buf[2][0];
+                       break;
+               }
+               buf[1][0] = g_u;
+               buf[2][0] = b_v;
+               break;
+       case V4L2_PIX_FMT_YVU420:
+       case V4L2_PIX_FMT_YVU420M:
+               buf[0][offset] = r_y;
+               if (odd) {
+                       buf[1][0] = (buf[1][0] + b_v) / 2;
+                       buf[2][0] = (buf[2][0] + g_u) / 2;
+                       buf[1][1] = buf[1][0];
+                       buf[2][1] = buf[2][0];
+                       break;
+               }
+               buf[1][0] = b_v;
+               buf[2][0] = g_u;
+               break;
+
+       case V4L2_PIX_FMT_NV12:
+       case V4L2_PIX_FMT_NV12M:
+       case V4L2_PIX_FMT_NV16:
        case V4L2_PIX_FMT_NV16M:
                buf[0][offset] = r_y;
-               buf[1][offset] = odd ? b_v : g_u;
+               if (odd) {
+                       buf[1][0] = (buf[1][0] + g_u) / 2;
+                       buf[1][1] = (buf[1][1] + b_v) / 2;
+                       break;
+               }
+               buf[1][0] = g_u;
+               buf[1][1] = b_v;
                break;
+       case V4L2_PIX_FMT_NV21:
+       case V4L2_PIX_FMT_NV21M:
+       case V4L2_PIX_FMT_NV61:
        case V4L2_PIX_FMT_NV61M:
                buf[0][offset] = r_y;
-               buf[1][offset] = odd ? g_u : b_v;
+               if (odd) {
+                       buf[1][0] = (buf[1][0] + b_v) / 2;
+                       buf[1][1] = (buf[1][1] + g_u) / 2;
+                       break;
+               }
+               buf[1][0] = b_v;
+               buf[1][1] = g_u;
+               break;
+
+       case V4L2_PIX_FMT_NV24:
+               buf[0][offset] = r_y;
+               buf[1][2 * offset] = g_u;
+               buf[1][2 * offset + 1] = b_v;
+               break;
+
+       case V4L2_PIX_FMT_NV42:
+               buf[0][offset] = r_y;
+               buf[1][2 * offset] = b_v;
+               buf[1][2 * offset + 1] = g_u;
                break;
 
        case V4L2_PIX_FMT_YUYV:
                buf[0][offset] = r_y;
-               buf[0][offset + 1] = odd ? b_v : g_u;
+               if (odd) {
+                       buf[0][1] = (buf[0][1] + g_u) / 2;
+                       buf[0][3] = (buf[0][3] + b_v) / 2;
+                       break;
+               }
+               buf[0][1] = g_u;
+               buf[0][3] = b_v;
                break;
        case V4L2_PIX_FMT_UYVY:
-               buf[0][offset] = odd ? b_v : g_u;
                buf[0][offset + 1] = r_y;
+               if (odd) {
+                       buf[0][0] = (buf[0][0] + g_u) / 2;
+                       buf[0][2] = (buf[0][2] + b_v) / 2;
+                       break;
+               }
+               buf[0][0] = g_u;
+               buf[0][2] = b_v;
                break;
        case V4L2_PIX_FMT_YVYU:
                buf[0][offset] = r_y;
-               buf[0][offset + 1] = odd ? g_u : b_v;
+               if (odd) {
+                       buf[0][1] = (buf[0][1] + b_v) / 2;
+                       buf[0][3] = (buf[0][3] + g_u) / 2;
+                       break;
+               }
+               buf[0][1] = b_v;
+               buf[0][3] = g_u;
                break;
        case V4L2_PIX_FMT_VYUY:
-               buf[0][offset] = odd ? g_u : b_v;
                buf[0][offset + 1] = r_y;
+               if (odd) {
+                       buf[0][0] = (buf[0][0] + b_v) / 2;
+                       buf[0][2] = (buf[0][2] + g_u) / 2;
+                       break;
+               }
+               buf[0][0] = b_v;
+               buf[0][2] = g_u;
+               break;
+       case V4L2_PIX_FMT_RGB332:
+               buf[0][offset] = (r_y << 5) | (g_u << 2) | b_v;
                break;
+       case V4L2_PIX_FMT_YUV565:
        case V4L2_PIX_FMT_RGB565:
                buf[0][offset] = (g_u << 5) | b_v;
                buf[0][offset + 1] = (r_y << 3) | (g_u >> 3);
@@ -698,15 +959,29 @@ static void gen_twopix(struct tpg_data *tpg,
                buf[0][offset] = (r_y << 3) | (g_u >> 3);
                buf[0][offset + 1] = (g_u << 5) | b_v;
                break;
+       case V4L2_PIX_FMT_RGB444:
+       case V4L2_PIX_FMT_XRGB444:
+               alpha = 0;
+               /* fall through */
+       case V4L2_PIX_FMT_YUV444:
+       case V4L2_PIX_FMT_ARGB444:
+               buf[0][offset] = (g_u << 4) | b_v;
+               buf[0][offset + 1] = (alpha & 0xf0) | r_y;
+               break;
        case V4L2_PIX_FMT_RGB555:
        case V4L2_PIX_FMT_XRGB555:
                alpha = 0;
                /* fall through */
+       case V4L2_PIX_FMT_YUV555:
        case V4L2_PIX_FMT_ARGB555:
                buf[0][offset] = (g_u << 5) | b_v;
                buf[0][offset + 1] = (alpha & 0x80) | (r_y << 2) | (g_u >> 3);
                break;
        case V4L2_PIX_FMT_RGB555X:
+       case V4L2_PIX_FMT_XRGB555X:
+               alpha = 0;
+               /* fall through */
+       case V4L2_PIX_FMT_ARGB555X:
                buf[0][offset] = (alpha & 0x80) | (r_y << 2) | (g_u >> 3);
                buf[0][offset + 1] = (g_u << 5) | b_v;
                break;
@@ -720,10 +995,17 @@ static void gen_twopix(struct tpg_data *tpg,
                buf[0][offset + 1] = g_u;
                buf[0][offset + 2] = r_y;
                break;
+       case V4L2_PIX_FMT_BGR666:
+               buf[0][offset] = (b_v << 2) | (g_u >> 4);
+               buf[0][offset + 1] = (g_u << 4) | (r_y >> 2);
+               buf[0][offset + 2] = r_y << 6;
+               buf[0][offset + 3] = 0;
+               break;
        case V4L2_PIX_FMT_RGB32:
        case V4L2_PIX_FMT_XRGB32:
                alpha = 0;
                /* fall through */
+       case V4L2_PIX_FMT_YUV32:
        case V4L2_PIX_FMT_ARGB32:
                buf[0][offset] = alpha;
                buf[0][offset + 1] = r_y;
@@ -740,15 +1022,47 @@ static void gen_twopix(struct tpg_data *tpg,
                buf[0][offset + 2] = r_y;
                buf[0][offset + 3] = alpha;
                break;
+       case V4L2_PIX_FMT_SBGGR8:
+               buf[0][offset] = odd ? g_u : b_v;
+               buf[1][offset] = odd ? r_y : g_u;
+               break;
+       case V4L2_PIX_FMT_SGBRG8:
+               buf[0][offset] = odd ? b_v : g_u;
+               buf[1][offset] = odd ? g_u : r_y;
+               break;
+       case V4L2_PIX_FMT_SGRBG8:
+               buf[0][offset] = odd ? r_y : g_u;
+               buf[1][offset] = odd ? g_u : b_v;
+               break;
+       case V4L2_PIX_FMT_SRGGB8:
+               buf[0][offset] = odd ? g_u : r_y;
+               buf[1][offset] = odd ? b_v : g_u;
+               break;
+       }
+}
+
+unsigned tpg_g_interleaved_plane(const struct tpg_data *tpg, unsigned buf_line)
+{
+       switch (tpg->fourcc) {
+       case V4L2_PIX_FMT_SBGGR8:
+       case V4L2_PIX_FMT_SGBRG8:
+       case V4L2_PIX_FMT_SGRBG8:
+       case V4L2_PIX_FMT_SRGGB8:
+               return buf_line & 1;
+       default:
+               return 0;
        }
 }
 
 /* Return how many pattern lines are used by the current pattern. */
-static unsigned tpg_get_pat_lines(struct tpg_data *tpg)
+static unsigned tpg_get_pat_lines(const struct tpg_data *tpg)
 {
        switch (tpg->pattern) {
        case TPG_PAT_CHECKERS_16X16:
+       case TPG_PAT_CHECKERS_2X2:
        case TPG_PAT_CHECKERS_1X1:
+       case TPG_PAT_COLOR_CHECKERS_2X2:
+       case TPG_PAT_COLOR_CHECKERS_1X1:
        case TPG_PAT_ALTERNATING_HLINES:
        case TPG_PAT_CROSS_1_PIXEL:
        case TPG_PAT_CROSS_2_PIXELS:
@@ -763,14 +1077,18 @@ static unsigned tpg_get_pat_lines(struct tpg_data *tpg)
 }
 
 /* Which pattern line should be used for the given frame line. */
-static unsigned tpg_get_pat_line(struct tpg_data *tpg, unsigned line)
+static unsigned tpg_get_pat_line(const struct tpg_data *tpg, unsigned line)
 {
        switch (tpg->pattern) {
        case TPG_PAT_CHECKERS_16X16:
                return (line >> 4) & 1;
        case TPG_PAT_CHECKERS_1X1:
+       case TPG_PAT_COLOR_CHECKERS_1X1:
        case TPG_PAT_ALTERNATING_HLINES:
                return line & 1;
+       case TPG_PAT_CHECKERS_2X2:
+       case TPG_PAT_COLOR_CHECKERS_2X2:
+               return (line & 2) >> 1;
        case TPG_PAT_100_COLORSQUARES:
        case TPG_PAT_100_HCOLORBAR:
                return (line * 8) / tpg->src_height;
@@ -789,7 +1107,8 @@ static unsigned tpg_get_pat_line(struct tpg_data *tpg, unsigned line)
  * Which color should be used for the given pattern line and X coordinate.
  * Note: x is in the range 0 to 2 * tpg->src_width.
  */
-static enum tpg_color tpg_get_color(struct tpg_data *tpg, unsigned pat_line, unsigned x)
+static enum tpg_color tpg_get_color(const struct tpg_data *tpg,
+                                   unsigned pat_line, unsigned x)
 {
        /* Maximum number of bars are TPG_COLOR_MAX - otherwise, the input print code
           should be modified */
@@ -836,6 +1155,15 @@ static enum tpg_color tpg_get_color(struct tpg_data *tpg, unsigned pat_line, uns
        case TPG_PAT_CHECKERS_1X1:
                return ((x & 1) ^ (pat_line & 1)) ?
                        TPG_COLOR_100_WHITE : TPG_COLOR_100_BLACK;
+       case TPG_PAT_COLOR_CHECKERS_1X1:
+               return ((x & 1) ^ (pat_line & 1)) ?
+                       TPG_COLOR_100_RED : TPG_COLOR_100_BLUE;
+       case TPG_PAT_CHECKERS_2X2:
+               return (((x >> 1) & 1) ^ (pat_line & 1)) ?
+                       TPG_COLOR_100_WHITE : TPG_COLOR_100_BLACK;
+       case TPG_PAT_COLOR_CHECKERS_2X2:
+               return (((x >> 1) & 1) ^ (pat_line & 1)) ?
+                       TPG_COLOR_100_RED : TPG_COLOR_100_BLUE;
        case TPG_PAT_ALTERNATING_HLINES:
                return pat_line ? TPG_COLOR_100_WHITE : TPG_COLOR_100_BLACK;
        case TPG_PAT_ALTERNATING_VLINES:
@@ -948,6 +1276,7 @@ static void tpg_calculate_square_border(struct tpg_data *tpg)
 static void tpg_precalculate_line(struct tpg_data *tpg)
 {
        enum tpg_color contrast;
+       u8 pix[TPG_MAX_PLANES][8];
        unsigned pat;
        unsigned p;
        unsigned x;
@@ -974,7 +1303,6 @@ static void tpg_precalculate_line(struct tpg_data *tpg)
                for (x = 0; x < tpg->scaled_width * 2; x += 2) {
                        unsigned real_x = src_x;
                        enum tpg_color color1, color2;
-                       u8 pix[TPG_MAX_PLANES][8];
 
                        real_x = tpg->hflip ? tpg->src_width * 2 - real_x - 2 : real_x;
                        color1 = tpg_get_color(tpg, pat, real_x);
@@ -1001,39 +1329,53 @@ static void tpg_precalculate_line(struct tpg_data *tpg)
                        gen_twopix(tpg, pix, tpg->hflip ? color1 : color2, 1);
                        for (p = 0; p < tpg->planes; p++) {
                                unsigned twopixsize = tpg->twopixelsize[p];
-                               u8 *pos = tpg->lines[pat][p] + x * twopixsize / 2;
+                               unsigned hdiv = tpg->hdownsampling[p];
+                               u8 *pos = tpg->lines[pat][p] + tpg_hdiv(tpg, p, x);
 
-                               memcpy(pos, pix[p], twopixsize);
+                               memcpy(pos, pix[p], twopixsize / hdiv);
                        }
                }
        }
-       for (x = 0; x < tpg->scaled_width; x += 2) {
-               u8 pix[TPG_MAX_PLANES][8];
 
-               gen_twopix(tpg, pix, contrast, 0);
-               gen_twopix(tpg, pix, contrast, 1);
-               for (p = 0; p < tpg->planes; p++) {
-                       unsigned twopixsize = tpg->twopixelsize[p];
-                       u8 *pos = tpg->contrast_line[p] + x * twopixsize / 2;
+       if (tpg->vdownsampling[tpg->planes - 1] > 1) {
+               unsigned pat_lines = tpg_get_pat_lines(tpg);
 
-                       memcpy(pos, pix[p], twopixsize);
+               for (pat = 0; pat < pat_lines; pat++) {
+                       unsigned next_pat = (pat + 1) % pat_lines;
+
+                       for (p = 1; p < tpg->planes; p++) {
+                               unsigned w = tpg_hdiv(tpg, p, tpg->scaled_width * 2);
+                               u8 *pos1 = tpg->lines[pat][p];
+                               u8 *pos2 = tpg->lines[next_pat][p];
+                               u8 *dest = tpg->downsampled_lines[pat][p];
+
+                               for (x = 0; x < w; x++, pos1++, pos2++, dest++)
+                                       *dest = ((u16)*pos1 + (u16)*pos2) / 2;
+                       }
                }
        }
-       for (x = 0; x < tpg->scaled_width; x += 2) {
-               u8 pix[TPG_MAX_PLANES][8];
 
-               gen_twopix(tpg, pix, TPG_COLOR_100_BLACK, 0);
-               gen_twopix(tpg, pix, TPG_COLOR_100_BLACK, 1);
-               for (p = 0; p < tpg->planes; p++) {
-                       unsigned twopixsize = tpg->twopixelsize[p];
-                       u8 *pos = tpg->black_line[p] + x * twopixsize / 2;
+       gen_twopix(tpg, pix, contrast, 0);
+       gen_twopix(tpg, pix, contrast, 1);
+       for (p = 0; p < tpg->planes; p++) {
+               unsigned twopixsize = tpg->twopixelsize[p];
+               u8 *pos = tpg->contrast_line[p];
 
+               for (x = 0; x < tpg->scaled_width; x += 2, pos += twopixsize)
+                       memcpy(pos, pix[p], twopixsize);
+       }
+
+       gen_twopix(tpg, pix, TPG_COLOR_100_BLACK, 0);
+       gen_twopix(tpg, pix, TPG_COLOR_100_BLACK, 1);
+       for (p = 0; p < tpg->planes; p++) {
+               unsigned twopixsize = tpg->twopixelsize[p];
+               u8 *pos = tpg->black_line[p];
+
+               for (x = 0; x < tpg->scaled_width; x += 2, pos += twopixsize)
                        memcpy(pos, pix[p], twopixsize);
-               }
        }
-       for (x = 0; x < tpg->scaled_width * 2; x += 2) {
-               u8 pix[TPG_MAX_PLANES][8];
 
+       for (x = 0; x < tpg->scaled_width * 2; x += 2) {
                gen_twopix(tpg, pix, TPG_COLOR_RANDOM, 0);
                gen_twopix(tpg, pix, TPG_COLOR_RANDOM, 1);
                for (p = 0; p < tpg->planes; p++) {
@@ -1043,6 +1385,7 @@ static void tpg_precalculate_line(struct tpg_data *tpg)
                        memcpy(pos, pix[p], twopixsize);
                }
        }
+
        gen_twopix(tpg, tpg->textbg, TPG_COLOR_TEXTBG, 0);
        gen_twopix(tpg, tpg->textbg, TPG_COLOR_TEXTBG, 1);
        gen_twopix(tpg, tpg->textfg, TPG_COLOR_TEXTFG, 0);
@@ -1052,8 +1395,8 @@ static void tpg_precalculate_line(struct tpg_data *tpg)
 /* need this to do rgb24 rendering */
 typedef struct { u16 __; u8 _; } __packed x24;
 
-void tpg_gen_text(struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2],
-               int y, int x, char *text)
+void tpg_gen_text(const struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2],
+                 int y, int x, char *text)
 {
        int line;
        unsigned step = V4L2_FIELD_HAS_T_OR_B(tpg->field) ? 2 : 1;
@@ -1083,24 +1426,37 @@ void tpg_gen_text(struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2],
                div = 2;
 
        for (p = 0; p < tpg->planes; p++) {
-               /* Print stream time */
+               unsigned vdiv = tpg->vdownsampling[p];
+               unsigned hdiv = tpg->hdownsampling[p];
+
+               /* Print text */
 #define PRINTSTR(PIXTYPE) do { \
        PIXTYPE fg;     \
        PIXTYPE bg;     \
        memcpy(&fg, tpg->textfg[p], sizeof(PIXTYPE));   \
        memcpy(&bg, tpg->textbg[p], sizeof(PIXTYPE));   \
        \
-       for (line = first; line < 16; line += step) {   \
+       for (line = first; line < 16; line += vdiv * step) {    \
                int l = tpg->vflip ? 15 - line : line; \
-               PIXTYPE *pos = (PIXTYPE *)(basep[p][line & 1] + \
-                              ((y * step + l) / div) * tpg->bytesperline[p] + \
-                              x * sizeof(PIXTYPE));    \
+               PIXTYPE *pos = (PIXTYPE *)(basep[p][(line / vdiv) & 1] + \
+                              ((y * step + l) / (vdiv * div)) * tpg->bytesperline[p] + \
+                              (x / hdiv) * sizeof(PIXTYPE));   \
                unsigned s;     \
        \
                for (s = 0; s < len; s++) {     \
                        u8 chr = font8x16[text[s] * 16 + line]; \
        \
-                       if (tpg->hflip) { \
+                       if (hdiv == 2 && tpg->hflip) { \
+                               pos[3] = (chr & (0x01 << 6) ? fg : bg); \
+                               pos[2] = (chr & (0x01 << 4) ? fg : bg); \
+                               pos[1] = (chr & (0x01 << 2) ? fg : bg); \
+                               pos[0] = (chr & (0x01 << 0) ? fg : bg); \
+                       } else if (hdiv == 2) { \
+                               pos[0] = (chr & (0x01 << 7) ? fg : bg); \
+                               pos[1] = (chr & (0x01 << 5) ? fg : bg); \
+                               pos[2] = (chr & (0x01 << 3) ? fg : bg); \
+                               pos[3] = (chr & (0x01 << 1) ? fg : bg); \
+                       } else if (tpg->hflip) { \
                                pos[7] = (chr & (0x01 << 7) ? fg : bg); \
                                pos[6] = (chr & (0x01 << 6) ? fg : bg); \
                                pos[5] = (chr & (0x01 << 5) ? fg : bg); \
@@ -1120,7 +1476,7 @@ void tpg_gen_text(struct tpg_data *tpg, u8 *basep[TPG_MAX_PLANES][2],
                                pos[7] = (chr & (0x01 << 0) ? fg : bg); \
                        } \
        \
-                       pos += tpg->hflip ? -8 : 8;     \
+                       pos += (tpg->hflip ? -8 : 8) / hdiv;    \
                }       \
        }       \
 } while (0)
@@ -1187,7 +1543,7 @@ void tpg_update_mv_step(struct tpg_data *tpg)
 }
 
 /* Map the line number relative to the crop rectangle to a frame line number */
-static unsigned tpg_calc_frameline(struct tpg_data *tpg, unsigned src_y,
+static unsigned tpg_calc_frameline(const struct tpg_data *tpg, unsigned src_y,
                                    unsigned field)
 {
        switch (field) {
@@ -1204,7 +1560,7 @@ static unsigned tpg_calc_frameline(struct tpg_data *tpg, unsigned src_y,
  * Map the line number relative to the compose rectangle to a destination
  * buffer line number.
  */
-static unsigned tpg_calc_buffer_line(struct tpg_data *tpg, unsigned y,
+static unsigned tpg_calc_buffer_line(const struct tpg_data *tpg, unsigned y,
                                    unsigned field)
 {
        y += tpg->compose.top;
@@ -1265,6 +1621,10 @@ static void tpg_recalc(struct tpg_data *tpg)
                                                V4L2_QUANTIZATION_LIM_RANGE;
                                        break;
                                }
+                       } else if (tpg->colorspace == V4L2_COLORSPACE_BT2020) {
+                               /* R'G'B' BT.2020 is limited range */
+                               tpg->real_quantization =
+                                       V4L2_QUANTIZATION_LIM_RANGE;
                        }
                }
                tpg_precalculate_colors(tpg);
@@ -1283,191 +1643,388 @@ void tpg_calc_text_basep(struct tpg_data *tpg,
                u8 *basep[TPG_MAX_PLANES][2], unsigned p, u8 *vbuf)
 {
        unsigned stride = tpg->bytesperline[p];
+       unsigned h = tpg->buf_height;
 
        tpg_recalc(tpg);
 
        basep[p][0] = vbuf;
        basep[p][1] = vbuf;
+       h /= tpg->vdownsampling[p];
        if (tpg->field == V4L2_FIELD_SEQ_TB)
-               basep[p][1] += tpg->buf_height * stride / 2;
+               basep[p][1] += h * stride / 2;
        else if (tpg->field == V4L2_FIELD_SEQ_BT)
-               basep[p][0] += tpg->buf_height * stride / 2;
+               basep[p][0] += h * stride / 2;
+       if (p == 0 && tpg->interleaved)
+               tpg_calc_text_basep(tpg, basep, 1, vbuf);
 }
 
-void tpg_fillbuffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8 *vbuf)
+static int tpg_pattern_avg(const struct tpg_data *tpg,
+                          unsigned pat1, unsigned pat2)
 {
-       bool is_tv = std;
-       bool is_60hz = is_tv && (std & V4L2_STD_525_60);
-       unsigned mv_hor_old = tpg->mv_hor_count % tpg->src_width;
-       unsigned mv_hor_new = (tpg->mv_hor_count + tpg->mv_hor_step) % tpg->src_width;
-       unsigned mv_vert_old = tpg->mv_vert_count % tpg->src_height;
-       unsigned mv_vert_new = (tpg->mv_vert_count + tpg->mv_vert_step) % tpg->src_height;
+       unsigned pat_lines = tpg_get_pat_lines(tpg);
+
+       if (pat1 == (pat2 + 1) % pat_lines)
+               return pat2;
+       if (pat2 == (pat1 + 1) % pat_lines)
+               return pat1;
+       return -1;
+}
+
+/*
+ * This struct contains common parameters used by both the drawing of the
+ * test pattern and the drawing of the extras (borders, square, etc.)
+ */
+struct tpg_draw_params {
+       /* common data */
+       bool is_tv;
+       bool is_60hz;
+       unsigned twopixsize;
+       unsigned img_width;
+       unsigned stride;
+       unsigned hmax;
+       unsigned frame_line;
+       unsigned frame_line_next;
+
+       /* test pattern */
+       unsigned mv_hor_old;
+       unsigned mv_hor_new;
+       unsigned mv_vert_old;
+       unsigned mv_vert_new;
+
+       /* extras */
        unsigned wss_width;
-       unsigned f;
-       int hmax = (tpg->compose.height * tpg->perc_fill) / 100;
-       int h;
-       unsigned twopixsize = tpg->twopixelsize[p];
-       unsigned img_width = tpg->compose.width * twopixsize / 2;
-       unsigned line_offset;
-       unsigned left_pillar_width = 0;
-       unsigned right_pillar_start = img_width;
-       unsigned stride = tpg->bytesperline[p];
-       unsigned factor = V4L2_FIELD_HAS_T_OR_B(tpg->field) ? 2 : 1;
-       u8 *orig_vbuf = vbuf;
+       unsigned wss_random_offset;
+       unsigned sav_eav_f;
+       unsigned left_pillar_width;
+       unsigned right_pillar_start;
+};
 
-       /* Coarse scaling with Bresenham */
-       unsigned int_part = (tpg->crop.height / factor) / tpg->compose.height;
-       unsigned fract_part = (tpg->crop.height / factor) % tpg->compose.height;
-       unsigned src_y = 0;
-       unsigned error = 0;
+static void tpg_fill_params_pattern(const struct tpg_data *tpg, unsigned p,
+                                   struct tpg_draw_params *params)
+{
+       params->mv_hor_old =
+               tpg_hscale_div(tpg, p, tpg->mv_hor_count % tpg->src_width);
+       params->mv_hor_new =
+               tpg_hscale_div(tpg, p, (tpg->mv_hor_count + tpg->mv_hor_step) %
+                              tpg->src_width);
+       params->mv_vert_old = tpg->mv_vert_count % tpg->src_height;
+       params->mv_vert_new =
+               (tpg->mv_vert_count + tpg->mv_vert_step) % tpg->src_height;
+}
 
-       tpg_recalc(tpg);
+static void tpg_fill_params_extras(const struct tpg_data *tpg,
+                                  unsigned p,
+                                  struct tpg_draw_params *params)
+{
+       unsigned left_pillar_width = 0;
+       unsigned right_pillar_start = params->img_width;
+
+       params->wss_width = tpg->crop.left < tpg->src_width / 2 ?
+               tpg->src_width / 2 - tpg->crop.left : 0;
+       if (params->wss_width > tpg->crop.width)
+               params->wss_width = tpg->crop.width;
+       params->wss_width = tpg_hscale_div(tpg, p, params->wss_width);
+       params->wss_random_offset =
+               params->twopixsize * prandom_u32_max(tpg->src_width / 2);
 
-       mv_hor_old = (mv_hor_old * tpg->scaled_width / tpg->src_width) & ~1;
-       mv_hor_new = (mv_hor_new * tpg->scaled_width / tpg->src_width) & ~1;
-       wss_width = tpg->crop.left < tpg->src_width / 2 ?
-                       tpg->src_width / 2 - tpg->crop.left : 0;
-       if (wss_width > tpg->crop.width)
-               wss_width = tpg->crop.width;
-       wss_width = wss_width * tpg->scaled_width / tpg->src_width;
-
-       vbuf += tpg->compose.left * twopixsize / 2;
-       line_offset = tpg->crop.left * tpg->scaled_width / tpg->src_width;
-       line_offset = (line_offset & ~1) * twopixsize / 2;
        if (tpg->crop.left < tpg->border.left) {
                left_pillar_width = tpg->border.left - tpg->crop.left;
                if (left_pillar_width > tpg->crop.width)
                        left_pillar_width = tpg->crop.width;
-               left_pillar_width = (left_pillar_width * tpg->scaled_width) / tpg->src_width;
-               left_pillar_width = (left_pillar_width & ~1) * twopixsize / 2;
+               left_pillar_width = tpg_hscale_div(tpg, p, left_pillar_width);
        }
-       if (tpg->crop.left + tpg->crop.width > tpg->border.left + tpg->border.width) {
-               right_pillar_start = tpg->border.left + tpg->border.width - tpg->crop.left;
-               right_pillar_start = (right_pillar_start * tpg->scaled_width) / tpg->src_width;
-               right_pillar_start = (right_pillar_start & ~1) * twopixsize / 2;
-               if (right_pillar_start > img_width)
-                       right_pillar_start = img_width;
+       params->left_pillar_width = left_pillar_width;
+
+       if (tpg->crop.left + tpg->crop.width >
+           tpg->border.left + tpg->border.width) {
+               right_pillar_start =
+                       tpg->border.left + tpg->border.width - tpg->crop.left;
+               right_pillar_start =
+                       tpg_hscale_div(tpg, p, right_pillar_start);
+               if (right_pillar_start > params->img_width)
+                       right_pillar_start = params->img_width;
        }
+       params->right_pillar_start = right_pillar_start;
 
-       f = tpg->field == (is_60hz ? V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM);
+       params->sav_eav_f = tpg->field ==
+                       (params->is_60hz ? V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM);
+}
 
-       for (h = 0; h < tpg->compose.height; h++) {
-               bool even;
-               bool fill_blank = false;
-               unsigned frame_line;
-               unsigned buf_line;
-               unsigned pat_line_old;
-               unsigned pat_line_new;
-               u8 *linestart_older;
-               u8 *linestart_newer;
-               u8 *linestart_top;
-               u8 *linestart_bottom;
-
-               frame_line = tpg_calc_frameline(tpg, src_y, tpg->field);
-               even = !(frame_line & 1);
-               buf_line = tpg_calc_buffer_line(tpg, h, tpg->field);
-               src_y += int_part;
-               error += fract_part;
-               if (error >= tpg->compose.height) {
-                       error -= tpg->compose.height;
-                       src_y++;
-               }
+static void tpg_fill_plane_extras(const struct tpg_data *tpg,
+                                 const struct tpg_draw_params *params,
+                                 unsigned p, unsigned h, u8 *vbuf)
+{
+       unsigned twopixsize = params->twopixsize;
+       unsigned img_width = params->img_width;
+       unsigned frame_line = params->frame_line;
+       const struct v4l2_rect *sq = &tpg->square;
+       const struct v4l2_rect *b = &tpg->border;
+       const struct v4l2_rect *c = &tpg->crop;
+
+       if (params->is_tv && !params->is_60hz &&
+           frame_line == 0 && params->wss_width) {
+               /*
+                * Replace the first half of the top line of a 50 Hz frame
+                * with random data to simulate a WSS signal.
+                */
+               u8 *wss = tpg->random_line[p] + params->wss_random_offset;
 
-               if (h >= hmax) {
-                       if (hmax == tpg->compose.height)
-                               continue;
-                       if (!tpg->perc_fill_blank)
-                               continue;
-                       fill_blank = true;
-               }
+               memcpy(vbuf, wss, params->wss_width);
+       }
+
+       if (tpg->show_border && frame_line >= b->top &&
+           frame_line < b->top + b->height) {
+               unsigned bottom = b->top + b->height - 1;
+               unsigned left = params->left_pillar_width;
+               unsigned right = params->right_pillar_start;
 
-               if (tpg->vflip)
-                       frame_line = tpg->src_height - frame_line - 1;
-
-               if (fill_blank) {
-                       linestart_older = tpg->contrast_line[p];
-                       linestart_newer = tpg->contrast_line[p];
-               } else if (tpg->qual != TPG_QUAL_NOISE &&
-                          (frame_line < tpg->border.top ||
-                           frame_line >= tpg->border.top + tpg->border.height)) {
-                       linestart_older = tpg->black_line[p];
-                       linestart_newer = tpg->black_line[p];
-               } else if (tpg->pattern == TPG_PAT_NOISE || tpg->qual == TPG_QUAL_NOISE) {
-                       linestart_older = tpg->random_line[p] +
-                                         twopixsize * prandom_u32_max(tpg->src_width / 2);
-                       linestart_newer = tpg->random_line[p] +
-                                         twopixsize * prandom_u32_max(tpg->src_width / 2);
+               if (frame_line == b->top || frame_line == b->top + 1 ||
+                   frame_line == bottom || frame_line == bottom - 1) {
+                       memcpy(vbuf + left, tpg->contrast_line[p],
+                                       right - left);
                } else {
-                       pat_line_old = tpg_get_pat_line(tpg,
-                                               (frame_line + mv_vert_old) % tpg->src_height);
-                       pat_line_new = tpg_get_pat_line(tpg,
-                                               (frame_line + mv_vert_new) % tpg->src_height);
-                       linestart_older = tpg->lines[pat_line_old][p] +
-                                         mv_hor_old * twopixsize / 2;
-                       linestart_newer = tpg->lines[pat_line_new][p] +
-                                         mv_hor_new * twopixsize / 2;
-                       linestart_older += line_offset;
-                       linestart_newer += line_offset;
+                       if (b->left >= c->left &&
+                           b->left < c->left + c->width)
+                               memcpy(vbuf + left,
+                                       tpg->contrast_line[p], twopixsize);
+                       if (b->left + b->width > c->left &&
+                           b->left + b->width <= c->left + c->width)
+                               memcpy(vbuf + right - twopixsize,
+                                       tpg->contrast_line[p], twopixsize);
                }
-               if (is_60hz) {
-                       linestart_top = linestart_newer;
-                       linestart_bottom = linestart_older;
-               } else {
-                       linestart_top = linestart_older;
-                       linestart_bottom = linestart_newer;
+       }
+       if (tpg->qual != TPG_QUAL_NOISE && frame_line >= b->top &&
+           frame_line < b->top + b->height) {
+               memcpy(vbuf, tpg->black_line[p], params->left_pillar_width);
+               memcpy(vbuf + params->right_pillar_start, tpg->black_line[p],
+                      img_width - params->right_pillar_start);
+       }
+       if (tpg->show_square && frame_line >= sq->top &&
+           frame_line < sq->top + sq->height &&
+           sq->left < c->left + c->width &&
+           sq->left + sq->width >= c->left) {
+               unsigned left = sq->left;
+               unsigned width = sq->width;
+
+               if (c->left > left) {
+                       width -= c->left - left;
+                       left = c->left;
                }
+               if (c->left + c->width < left + width)
+                       width -= left + width - c->left - c->width;
+               left -= c->left;
+               left = tpg_hscale_div(tpg, p, left);
+               width = tpg_hscale_div(tpg, p, width);
+               memcpy(vbuf + left, tpg->contrast_line[p], width);
+       }
+       if (tpg->insert_sav) {
+               unsigned offset = tpg_hdiv(tpg, p, tpg->compose.width / 3);
+               u8 *p = vbuf + offset;
+               unsigned vact = 0, hact = 0;
+
+               p[0] = 0xff;
+               p[1] = 0;
+               p[2] = 0;
+               p[3] = 0x80 | (params->sav_eav_f << 6) |
+                       (vact << 5) | (hact << 4) |
+                       ((hact ^ vact) << 3) |
+                       ((hact ^ params->sav_eav_f) << 2) |
+                       ((params->sav_eav_f ^ vact) << 1) |
+                       (hact ^ vact ^ params->sav_eav_f);
+       }
+       if (tpg->insert_eav) {
+               unsigned offset = tpg_hdiv(tpg, p, tpg->compose.width * 2 / 3);
+               u8 *p = vbuf + offset;
+               unsigned vact = 0, hact = 1;
+
+               p[0] = 0xff;
+               p[1] = 0;
+               p[2] = 0;
+               p[3] = 0x80 | (params->sav_eav_f << 6) |
+                       (vact << 5) | (hact << 4) |
+                       ((hact ^ vact) << 3) |
+                       ((hact ^ params->sav_eav_f) << 2) |
+                       ((params->sav_eav_f ^ vact) << 1) |
+                       (hact ^ vact ^ params->sav_eav_f);
+       }
+}
 
-               switch (tpg->field) {
-               case V4L2_FIELD_INTERLACED:
-               case V4L2_FIELD_INTERLACED_TB:
-               case V4L2_FIELD_SEQ_TB:
-               case V4L2_FIELD_SEQ_BT:
-                       if (even)
-                               memcpy(vbuf + buf_line * stride, linestart_top, img_width);
-                       else
-                               memcpy(vbuf + buf_line * stride, linestart_bottom, img_width);
-                       break;
-               case V4L2_FIELD_INTERLACED_BT:
-                       if (even)
-                               memcpy(vbuf + buf_line * stride, linestart_bottom, img_width);
-                       else
-                               memcpy(vbuf + buf_line * stride, linestart_top, img_width);
-                       break;
-               case V4L2_FIELD_TOP:
-                       memcpy(vbuf + buf_line * stride, linestart_top, img_width);
-                       break;
-               case V4L2_FIELD_BOTTOM:
-                       memcpy(vbuf + buf_line * stride, linestart_bottom, img_width);
-                       break;
-               case V4L2_FIELD_NONE:
-               default:
-                       memcpy(vbuf + buf_line * stride, linestart_older, img_width);
-                       break;
-               }
+static void tpg_fill_plane_pattern(const struct tpg_data *tpg,
+                                  const struct tpg_draw_params *params,
+                                  unsigned p, unsigned h, u8 *vbuf)
+{
+       unsigned twopixsize = params->twopixsize;
+       unsigned img_width = params->img_width;
+       unsigned mv_hor_old = params->mv_hor_old;
+       unsigned mv_hor_new = params->mv_hor_new;
+       unsigned mv_vert_old = params->mv_vert_old;
+       unsigned mv_vert_new = params->mv_vert_new;
+       unsigned frame_line = params->frame_line;
+       unsigned frame_line_next = params->frame_line_next;
+       unsigned line_offset = tpg_hscale_div(tpg, p, tpg->crop.left);
+       bool even;
+       bool fill_blank = false;
+       unsigned pat_line_old;
+       unsigned pat_line_new;
+       u8 *linestart_older;
+       u8 *linestart_newer;
+       u8 *linestart_top;
+       u8 *linestart_bottom;
+
+       even = !(frame_line & 1);
+
+       if (h >= params->hmax) {
+               if (params->hmax == tpg->compose.height)
+                       return;
+               if (!tpg->perc_fill_blank)
+                       return;
+               fill_blank = true;
+       }
 
-               if (is_tv && !is_60hz && frame_line == 0 && wss_width) {
-                       /*
-                        * Replace the first half of the top line of a 50 Hz frame
-                        * with random data to simulate a WSS signal.
-                        */
-                       u8 *wss = tpg->random_line[p] +
+       if (tpg->vflip) {
+               frame_line = tpg->src_height - frame_line - 1;
+               frame_line_next = tpg->src_height - frame_line_next - 1;
+       }
+
+       if (fill_blank) {
+               linestart_older = tpg->contrast_line[p];
+               linestart_newer = tpg->contrast_line[p];
+       } else if (tpg->qual != TPG_QUAL_NOISE &&
+                  (frame_line < tpg->border.top ||
+                   frame_line >= tpg->border.top + tpg->border.height)) {
+               linestart_older = tpg->black_line[p];
+               linestart_newer = tpg->black_line[p];
+       } else if (tpg->pattern == TPG_PAT_NOISE || tpg->qual == TPG_QUAL_NOISE) {
+               linestart_older = tpg->random_line[p] +
+                                 twopixsize * prandom_u32_max(tpg->src_width / 2);
+               linestart_newer = tpg->random_line[p] +
                                  twopixsize * prandom_u32_max(tpg->src_width / 2);
+       } else {
+               unsigned frame_line_old =
+                       (frame_line + mv_vert_old) % tpg->src_height;
+               unsigned frame_line_new =
+                       (frame_line + mv_vert_new) % tpg->src_height;
+               unsigned pat_line_next_old;
+               unsigned pat_line_next_new;
 
-                       memcpy(vbuf + buf_line * stride, wss, wss_width * twopixsize / 2);
+               pat_line_old = tpg_get_pat_line(tpg, frame_line_old);
+               pat_line_new = tpg_get_pat_line(tpg, frame_line_new);
+               linestart_older = tpg->lines[pat_line_old][p] + mv_hor_old;
+               linestart_newer = tpg->lines[pat_line_new][p] + mv_hor_new;
+
+               if (tpg->vdownsampling[p] > 1 && frame_line != frame_line_next) {
+                       int avg_pat;
+
+                       /*
+                        * Now decide whether we need to use downsampled_lines[].
+                        * That's necessary if the two lines use different patterns.
+                        */
+                       pat_line_next_old = tpg_get_pat_line(tpg,
+                                       (frame_line_next + mv_vert_old) % tpg->src_height);
+                       pat_line_next_new = tpg_get_pat_line(tpg,
+                                       (frame_line_next + mv_vert_new) % tpg->src_height);
+
+                       switch (tpg->field) {
+                       case V4L2_FIELD_INTERLACED:
+                       case V4L2_FIELD_INTERLACED_BT:
+                       case V4L2_FIELD_INTERLACED_TB:
+                               avg_pat = tpg_pattern_avg(tpg, pat_line_old, pat_line_new);
+                               if (avg_pat < 0)
+                                       break;
+                               linestart_older = tpg->downsampled_lines[avg_pat][p] + mv_hor_old;
+                               linestart_newer = linestart_older;
+                               break;
+                       case V4L2_FIELD_NONE:
+                       case V4L2_FIELD_TOP:
+                       case V4L2_FIELD_BOTTOM:
+                       case V4L2_FIELD_SEQ_BT:
+                       case V4L2_FIELD_SEQ_TB:
+                               avg_pat = tpg_pattern_avg(tpg, pat_line_old, pat_line_next_old);
+                               if (avg_pat >= 0)
+                                       linestart_older = tpg->downsampled_lines[avg_pat][p] +
+                                               mv_hor_old;
+                               avg_pat = tpg_pattern_avg(tpg, pat_line_new, pat_line_next_new);
+                               if (avg_pat >= 0)
+                                       linestart_newer = tpg->downsampled_lines[avg_pat][p] +
+                                               mv_hor_new;
+                               break;
+                       }
                }
+               linestart_older += line_offset;
+               linestart_newer += line_offset;
+       }
+       if (tpg->field_alternate) {
+               linestart_top = linestart_bottom = linestart_older;
+       } else if (params->is_60hz) {
+               linestart_top = linestart_newer;
+               linestart_bottom = linestart_older;
+       } else {
+               linestart_top = linestart_older;
+               linestart_bottom = linestart_newer;
+       }
+
+       switch (tpg->field) {
+       case V4L2_FIELD_INTERLACED:
+       case V4L2_FIELD_INTERLACED_TB:
+       case V4L2_FIELD_SEQ_TB:
+       case V4L2_FIELD_SEQ_BT:
+               if (even)
+                       memcpy(vbuf, linestart_top, img_width);
+               else
+                       memcpy(vbuf, linestart_bottom, img_width);
+               break;
+       case V4L2_FIELD_INTERLACED_BT:
+               if (even)
+                       memcpy(vbuf, linestart_bottom, img_width);
+               else
+                       memcpy(vbuf, linestart_top, img_width);
+               break;
+       case V4L2_FIELD_TOP:
+               memcpy(vbuf, linestart_top, img_width);
+               break;
+       case V4L2_FIELD_BOTTOM:
+               memcpy(vbuf, linestart_bottom, img_width);
+               break;
+       case V4L2_FIELD_NONE:
+       default:
+               memcpy(vbuf, linestart_older, img_width);
+               break;
        }
+}
+
+void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std,
+                          unsigned p, u8 *vbuf)
+{
+       struct tpg_draw_params params;
+       unsigned factor = V4L2_FIELD_HAS_T_OR_B(tpg->field) ? 2 : 1;
+
+       /* Coarse scaling with Bresenham */
+       unsigned int_part = (tpg->crop.height / factor) / tpg->compose.height;
+       unsigned fract_part = (tpg->crop.height / factor) % tpg->compose.height;
+       unsigned src_y = 0;
+       unsigned error = 0;
+       unsigned h;
+
+       tpg_recalc(tpg);
+
+       params.is_tv = std;
+       params.is_60hz = std & V4L2_STD_525_60;
+       params.twopixsize = tpg->twopixelsize[p];
+       params.img_width = tpg_hdiv(tpg, p, tpg->compose.width);
+       params.stride = tpg->bytesperline[p];
+       params.hmax = (tpg->compose.height * tpg->perc_fill) / 100;
+
+       tpg_fill_params_pattern(tpg, p, &params);
+       tpg_fill_params_extras(tpg, p, &params);
+
+       vbuf += tpg_hdiv(tpg, p, tpg->compose.left);
 
-       vbuf = orig_vbuf;
-       vbuf += tpg->compose.left * twopixsize / 2;
-       src_y = 0;
-       error = 0;
        for (h = 0; h < tpg->compose.height; h++) {
-               unsigned frame_line = tpg_calc_frameline(tpg, src_y, tpg->field);
-               unsigned buf_line = tpg_calc_buffer_line(tpg, h, tpg->field);
-               const struct v4l2_rect *sq = &tpg->square;
-               const struct v4l2_rect *b = &tpg->border;
-               const struct v4l2_rect *c = &tpg->crop;
+               unsigned buf_line;
 
+               params.frame_line = tpg_calc_frameline(tpg, src_y, tpg->field);
+               params.frame_line_next = params.frame_line;
+               buf_line = tpg_calc_buffer_line(tpg, h, tpg->field);
                src_y += int_part;
                error += fract_part;
                if (error >= tpg->compose.height) {
@@ -1475,80 +2032,61 @@ void tpg_fillbuffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8 *vbuf)
                        src_y++;
                }
 
-               if (tpg->show_border && frame_line >= b->top &&
-                   frame_line < b->top + b->height) {
-                       unsigned bottom = b->top + b->height - 1;
-                       unsigned left = left_pillar_width;
-                       unsigned right = right_pillar_start;
+               /*
+                * For line-interleaved formats determine the 'plane'
+                * based on the buffer line.
+                */
+               if (tpg_g_interleaved(tpg))
+                       p = tpg_g_interleaved_plane(tpg, buf_line);
 
-                       if (frame_line == b->top || frame_line == b->top + 1 ||
-                           frame_line == bottom || frame_line == bottom - 1) {
-                               memcpy(vbuf + buf_line * stride + left, tpg->contrast_line[p],
-                                               right - left);
+               if (tpg->vdownsampling[p] > 1) {
+                       /*
+                        * When doing vertical downsampling the field setting
+                        * matters: for SEQ_BT/TB we downsample each field
+                        * separately (i.e. lines 0+2 are combined, as are
+                        * lines 1+3), for the other field settings we combine
+                        * odd and even lines. Doing that for SEQ_BT/TB would
+                        * be really weird.
+                        */
+                       if (tpg->field == V4L2_FIELD_SEQ_BT ||
+                           tpg->field == V4L2_FIELD_SEQ_TB) {
+                               unsigned next_src_y = src_y;
+
+                               if ((h & 3) >= 2)
+                                       continue;
+                               next_src_y += int_part;
+                               if (error + fract_part >= tpg->compose.height)
+                                       next_src_y++;
+                               params.frame_line_next =
+                                       tpg_calc_frameline(tpg, next_src_y, tpg->field);
                        } else {
-                               if (b->left >= c->left &&
-                                   b->left < c->left + c->width)
-                                       memcpy(vbuf + buf_line * stride + left,
-                                               tpg->contrast_line[p], twopixsize);
-                               if (b->left + b->width > c->left &&
-                                   b->left + b->width <= c->left + c->width)
-                                       memcpy(vbuf + buf_line * stride + right - twopixsize,
-                                               tpg->contrast_line[p], twopixsize);
+                               if (h & 1)
+                                       continue;
+                               params.frame_line_next =
+                                       tpg_calc_frameline(tpg, src_y, tpg->field);
                        }
+
+                       buf_line /= tpg->vdownsampling[p];
                }
-               if (tpg->qual != TPG_QUAL_NOISE && frame_line >= b->top &&
-                   frame_line < b->top + b->height) {
-                       memcpy(vbuf + buf_line * stride, tpg->black_line[p], left_pillar_width);
-                       memcpy(vbuf + buf_line * stride + right_pillar_start, tpg->black_line[p],
-                              img_width - right_pillar_start);
-               }
-               if (tpg->show_square && frame_line >= sq->top &&
-                   frame_line < sq->top + sq->height &&
-                   sq->left < c->left + c->width &&
-                   sq->left + sq->width >= c->left) {
-                       unsigned left = sq->left;
-                       unsigned width = sq->width;
-
-                       if (c->left > left) {
-                               width -= c->left - left;
-                               left = c->left;
-                       }
-                       if (c->left + c->width < left + width)
-                               width -= left + width - c->left - c->width;
-                       left -= c->left;
-                       left = (left * tpg->scaled_width) / tpg->src_width;
-                       left = (left & ~1) * twopixsize / 2;
-                       width = (width * tpg->scaled_width) / tpg->src_width;
-                       width = (width & ~1) * twopixsize / 2;
-                       memcpy(vbuf + buf_line * stride + left, tpg->contrast_line[p], width);
-               }
-               if (tpg->insert_sav) {
-                       unsigned offset = (tpg->compose.width / 6) * twopixsize;
-                       u8 *p = vbuf + buf_line * stride + offset;
-                       unsigned vact = 0, hact = 0;
-
-                       p[0] = 0xff;
-                       p[1] = 0;
-                       p[2] = 0;
-                       p[3] = 0x80 | (f << 6) | (vact << 5) | (hact << 4) |
-                               ((hact ^ vact) << 3) |
-                               ((hact ^ f) << 2) |
-                               ((f ^ vact) << 1) |
-                               (hact ^ vact ^ f);
-               }
-               if (tpg->insert_eav) {
-                       unsigned offset = (tpg->compose.width / 6) * 2 * twopixsize;
-                       u8 *p = vbuf + buf_line * stride + offset;
-                       unsigned vact = 0, hact = 1;
-
-                       p[0] = 0xff;
-                       p[1] = 0;
-                       p[2] = 0;
-                       p[3] = 0x80 | (f << 6) | (vact << 5) | (hact << 4) |
-                               ((hact ^ vact) << 3) |
-                               ((hact ^ f) << 2) |
-                               ((f ^ vact) << 1) |
-                               (hact ^ vact ^ f);
-               }
+               tpg_fill_plane_pattern(tpg, &params, p, h,
+                               vbuf + buf_line * params.stride);
+               tpg_fill_plane_extras(tpg, &params, p, h,
+                               vbuf + buf_line * params.stride);
+       }
+}
+
+void tpg_fillbuffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8 *vbuf)
+{
+       unsigned offset = 0;
+       unsigned i;
+
+       if (tpg->buffers > 1) {
+               tpg_fill_plane_buffer(tpg, std, p, vbuf);
+               return;
+       }
+
+       for (i = 0; i < tpg_g_planes(tpg); i++) {
+               tpg_fill_plane_buffer(tpg, std, i, vbuf + offset);
+               offset += tpg_calc_plane_size(tpg, i);
        }
 }
index bd8b1c760b3f01d140085e39ef073fecfd824b98..a50cd2e2535bf188103e9418ce1722ea00124273 100644 (file)
@@ -41,7 +41,10 @@ enum tpg_pattern {
        TPG_PAT_GREEN,
        TPG_PAT_BLUE,
        TPG_PAT_CHECKERS_16X16,
+       TPG_PAT_CHECKERS_2X2,
        TPG_PAT_CHECKERS_1X1,
+       TPG_PAT_COLOR_CHECKERS_2X2,
+       TPG_PAT_COLOR_CHECKERS_1X1,
        TPG_PAT_ALTERNATING_HLINES,
        TPG_PAT_ALTERNATING_VLINES,
        TPG_PAT_CROSS_1_PIXEL,
@@ -87,7 +90,7 @@ enum tpg_move_mode {
 
 extern const char * const tpg_aspect_strings[];
 
-#define TPG_MAX_PLANES 2
+#define TPG_MAX_PLANES 3
 #define TPG_MAX_PAT_LINES 8
 
 struct tpg_data {
@@ -98,6 +101,7 @@ struct tpg_data {
        /* Scaled output frame size */
        unsigned                        scaled_width;
        u32                             field;
+       bool                            field_alternate;
        /* crop coordinates are frame-based */
        struct v4l2_rect                crop;
        /* compose coordinates are format-based */
@@ -134,7 +138,16 @@ struct tpg_data {
        enum tpg_pixel_aspect           pix_aspect;
        unsigned                        rgb_range;
        unsigned                        real_rgb_range;
+       unsigned                        buffers;
        unsigned                        planes;
+       bool                            interleaved;
+       u8                              vdownsampling[TPG_MAX_PLANES];
+       u8                              hdownsampling[TPG_MAX_PLANES];
+       /*
+        * horizontal positions must be ANDed with this value to enforce
+        * correct boundaries for packed YUYV values.
+        */
+       unsigned                        hmask[TPG_MAX_PLANES];
        /* Used to store the colors in native format, either RGB or YUV */
        u8                              colors[TPG_COLOR_MAX][3];
        u8                              textfg[TPG_MAX_PLANES][8], textbg[TPG_MAX_PLANES][8];
@@ -168,6 +181,7 @@ struct tpg_data {
        /* Used to store TPG_MAX_PAT_LINES lines, each with up to two planes */
        unsigned                        max_line_width;
        u8                              *lines[TPG_MAX_PAT_LINES][TPG_MAX_PLANES];
+       u8                              *downsampled_lines[TPG_MAX_PAT_LINES][TPG_MAX_PLANES];
        u8                              *random_line[TPG_MAX_PLANES];
        u8                              *contrast_line[TPG_MAX_PLANES];
        u8                              *black_line[TPG_MAX_PLANES];
@@ -180,11 +194,15 @@ void tpg_reset_source(struct tpg_data *tpg, unsigned width, unsigned height,
                       u32 field);
 
 void tpg_set_font(const u8 *f);
-void tpg_gen_text(struct tpg_data *tpg,
+void tpg_gen_text(const struct tpg_data *tpg,
                u8 *basep[TPG_MAX_PLANES][2], int y, int x, char *text);
 void tpg_calc_text_basep(struct tpg_data *tpg,
                u8 *basep[TPG_MAX_PLANES][2], unsigned p, u8 *vbuf);
-void tpg_fillbuffer(struct tpg_data *tpg, v4l2_std_id std, unsigned p, u8 *vbuf);
+unsigned tpg_g_interleaved_plane(const struct tpg_data *tpg, unsigned buf_line);
+void tpg_fill_plane_buffer(struct tpg_data *tpg, v4l2_std_id std,
+                          unsigned p, u8 *vbuf);
+void tpg_fillbuffer(struct tpg_data *tpg, v4l2_std_id std,
+                   unsigned p, u8 *vbuf);
 bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc);
 void tpg_s_crop_compose(struct tpg_data *tpg, const struct v4l2_rect *crop,
                const struct v4l2_rect *compose);
@@ -323,9 +341,19 @@ static inline u32 tpg_g_quantization(const struct tpg_data *tpg)
        return tpg->quantization;
 }
 
+static inline unsigned tpg_g_buffers(const struct tpg_data *tpg)
+{
+       return tpg->buffers;
+}
+
 static inline unsigned tpg_g_planes(const struct tpg_data *tpg)
 {
-       return tpg->planes;
+       return tpg->interleaved ? 1 : tpg->planes;
+}
+
+static inline bool tpg_g_interleaved(const struct tpg_data *tpg)
+{
+       return tpg->interleaved;
 }
 
 static inline unsigned tpg_g_twopixelsize(const struct tpg_data *tpg, unsigned plane)
@@ -333,6 +361,24 @@ static inline unsigned tpg_g_twopixelsize(const struct tpg_data *tpg, unsigned p
        return tpg->twopixelsize[plane];
 }
 
+static inline unsigned tpg_hdiv(const struct tpg_data *tpg,
+                                 unsigned plane, unsigned x)
+{
+       return ((x / tpg->hdownsampling[plane]) & tpg->hmask[plane]) *
+               tpg->twopixelsize[plane] / 2;
+}
+
+static inline unsigned tpg_hscale(const struct tpg_data *tpg, unsigned x)
+{
+       return (x * tpg->scaled_width) / tpg->src_width;
+}
+
+static inline unsigned tpg_hscale_div(const struct tpg_data *tpg,
+                                     unsigned plane, unsigned x)
+{
+       return tpg_hdiv(tpg, plane, tpg_hscale(tpg, x));
+}
+
 static inline unsigned tpg_g_bytesperline(const struct tpg_data *tpg, unsigned plane)
 {
        return tpg->bytesperline[plane];
@@ -340,7 +386,60 @@ static inline unsigned tpg_g_bytesperline(const struct tpg_data *tpg, unsigned p
 
 static inline void tpg_s_bytesperline(struct tpg_data *tpg, unsigned plane, unsigned bpl)
 {
-       tpg->bytesperline[plane] = bpl;
+       unsigned p;
+
+       if (tpg->buffers > 1) {
+               tpg->bytesperline[plane] = bpl;
+               return;
+       }
+
+       for (p = 0; p < tpg_g_planes(tpg); p++) {
+               unsigned plane_w = bpl * tpg->twopixelsize[p] / tpg->twopixelsize[0];
+
+               tpg->bytesperline[p] = plane_w / tpg->hdownsampling[p];
+       }
+}
+
+
+static inline unsigned tpg_g_line_width(const struct tpg_data *tpg, unsigned plane)
+{
+       unsigned w = 0;
+       unsigned p;
+
+       if (tpg->buffers > 1)
+               return tpg_g_bytesperline(tpg, plane);
+       for (p = 0; p < tpg_g_planes(tpg); p++) {
+               unsigned plane_w = tpg_g_bytesperline(tpg, p);
+
+               w += plane_w / tpg->vdownsampling[p];
+       }
+       return w;
+}
+
+static inline unsigned tpg_calc_line_width(const struct tpg_data *tpg,
+                                          unsigned plane, unsigned bpl)
+{
+       unsigned w = 0;
+       unsigned p;
+
+       if (tpg->buffers > 1)
+               return bpl;
+       for (p = 0; p < tpg_g_planes(tpg); p++) {
+               unsigned plane_w = bpl * tpg->twopixelsize[p] / tpg->twopixelsize[0];
+
+               plane_w /= tpg->hdownsampling[p];
+               w += plane_w / tpg->vdownsampling[p];
+       }
+       return w;
+}
+
+static inline unsigned tpg_calc_plane_size(const struct tpg_data *tpg, unsigned plane)
+{
+       if (plane >= tpg_g_planes(tpg))
+               return 0;
+
+       return tpg_g_bytesperline(tpg, plane) * tpg->buf_height /
+              tpg->vdownsampling[plane];
 }
 
 static inline void tpg_s_buf_height(struct tpg_data *tpg, unsigned h)
@@ -348,9 +447,10 @@ static inline void tpg_s_buf_height(struct tpg_data *tpg, unsigned h)
        tpg->buf_height = h;
 }
 
-static inline void tpg_s_field(struct tpg_data *tpg, unsigned field)
+static inline void tpg_s_field(struct tpg_data *tpg, unsigned field, bool alternate)
 {
        tpg->field = field;
+       tpg->field_alternate = alternate;
 }
 
 static inline void tpg_s_perc_fill(struct tpg_data *tpg,
index 867a29a6d18f2fc1b8ef880659f788d309a38f52..dab5990f45a05f246a2a783e0d6b501ae78c9576 100644 (file)
@@ -42,20 +42,26 @@ static const struct vivid_fmt formats_ovl[] = {
        {
                .name     = "RGB565 (LE)",
                .fourcc   = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
-               .depth    = 16,
+               .vdownsampling = { 1 },
+               .bit_depth = { 16 },
                .planes   = 1,
+               .buffers = 1,
        },
        {
                .name     = "XRGB555 (LE)",
                .fourcc   = V4L2_PIX_FMT_XRGB555, /* gggbbbbb arrrrrgg */
-               .depth    = 16,
+               .vdownsampling = { 1 },
+               .bit_depth = { 16 },
                .planes   = 1,
+               .buffers = 1,
        },
        {
                .name     = "ARGB555 (LE)",
                .fourcc   = V4L2_PIX_FMT_ARGB555, /* gggbbbbb arrrrrgg */
-               .depth    = 16,
+               .vdownsampling = { 1 },
+               .bit_depth = { 16 },
                .planes   = 1,
+               .buffers = 1,
        },
 };
 
@@ -94,7 +100,7 @@ static int vid_cap_queue_setup(struct vb2_queue *vq, const struct v4l2_format *f
                       unsigned sizes[], void *alloc_ctxs[])
 {
        struct vivid_dev *dev = vb2_get_drv_priv(vq);
-       unsigned planes = tpg_g_planes(&dev->tpg);
+       unsigned buffers = tpg_g_buffers(&dev->tpg);
        unsigned h = dev->fmt_cap_rect.height;
        unsigned p;
 
@@ -127,39 +133,36 @@ static int vid_cap_queue_setup(struct vb2_queue *vq, const struct v4l2_format *f
                mp = &fmt->fmt.pix_mp;
                /*
                 * Check if the number of planes in the specified format match
-                * the number of planes in the current format. You can't mix that.
+                * the number of buffers in the current format. You can't mix that.
                 */
-               if (mp->num_planes != planes)
+               if (mp->num_planes != buffers)
                        return -EINVAL;
                vfmt = vivid_get_format(dev, mp->pixelformat);
-               for (p = 0; p < planes; p++) {
+               for (p = 0; p < buffers; p++) {
                        sizes[p] = mp->plane_fmt[p].sizeimage;
-                       if (sizes[0] < tpg_g_bytesperline(&dev->tpg, 0) * h +
+                       if (sizes[p] < tpg_g_line_width(&dev->tpg, p) * h +
                                                        vfmt->data_offset[p])
                                return -EINVAL;
                }
        } else {
-               for (p = 0; p < planes; p++)
-                       sizes[p] = tpg_g_bytesperline(&dev->tpg, p) * h +
+               for (p = 0; p < buffers; p++)
+                       sizes[p] = tpg_g_line_width(&dev->tpg, p) * h +
                                        dev->fmt_cap->data_offset[p];
        }
 
        if (vq->num_buffers + *nbuffers < 2)
                *nbuffers = 2 - vq->num_buffers;
 
-       *nplanes = planes;
+       *nplanes = buffers;
 
        /*
         * videobuf2-vmalloc allocator is context-less so no need to set
         * alloc_ctxs array.
         */
 
-       if (planes == 2)
-               dprintk(dev, 1, "%s, count=%d, sizes=%u, %u\n", __func__,
-                       *nbuffers, sizes[0], sizes[1]);
-       else
-               dprintk(dev, 1, "%s, count=%d, size=%u\n", __func__,
-                       *nbuffers, sizes[0]);
+       dprintk(dev, 1, "%s: count=%d\n", __func__, *nbuffers);
+       for (p = 0; p < buffers; p++)
+               dprintk(dev, 1, "%s: size[%u]=%u\n", __func__, p, sizes[p]);
 
        return 0;
 }
@@ -168,7 +171,7 @@ static int vid_cap_buf_prepare(struct vb2_buffer *vb)
 {
        struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
        unsigned long size;
-       unsigned planes = tpg_g_planes(&dev->tpg);
+       unsigned buffers = tpg_g_buffers(&dev->tpg);
        unsigned p;
 
        dprintk(dev, 1, "%s\n", __func__);
@@ -184,13 +187,13 @@ static int vid_cap_buf_prepare(struct vb2_buffer *vb)
                dev->buf_prepare_error = false;
                return -EINVAL;
        }
-       for (p = 0; p < planes; p++) {
-               size = tpg_g_bytesperline(&dev->tpg, p) * dev->fmt_cap_rect.height +
+       for (p = 0; p < buffers; p++) {
+               size = tpg_g_line_width(&dev->tpg, p) * dev->fmt_cap_rect.height +
                        dev->fmt_cap->data_offset[p];
 
-               if (vb2_plane_size(vb, 0) < size) {
+               if (vb2_plane_size(vb, p) < size) {
                        dprintk(dev, 1, "%s data will not fit into plane %u (%lu < %lu)\n",
-                                       __func__, p, vb2_plane_size(vb, 0), size);
+                                       __func__, p, vb2_plane_size(vb, p), size);
                        return -EINVAL;
                }
 
@@ -441,7 +444,7 @@ void vivid_update_format_cap(struct vivid_dev *dev, bool keep_controls)
                 */
                if (keep_controls || !dev->colorspace)
                        break;
-               if (bt->standards & V4L2_DV_BT_STD_CEA861) {
+               if (bt->flags & V4L2_DV_FL_IS_CE_VIDEO) {
                        if (bt->width == 720 && bt->height <= 576)
                                v4l2_ctrl_s_ctrl(dev->colorspace, VIVID_CS_170M);
                        else
@@ -526,11 +529,11 @@ int vivid_g_fmt_vid_cap(struct file *file, void *priv,
        mp->colorspace   = vivid_colorspace_cap(dev);
        mp->ycbcr_enc    = vivid_ycbcr_enc_cap(dev);
        mp->quantization = vivid_quantization_cap(dev);
-       mp->num_planes = dev->fmt_cap->planes;
+       mp->num_planes = dev->fmt_cap->buffers;
        for (p = 0; p < mp->num_planes; p++) {
                mp->plane_fmt[p].bytesperline = tpg_g_bytesperline(&dev->tpg, p);
                mp->plane_fmt[p].sizeimage =
-                       mp->plane_fmt[p].bytesperline * mp->height +
+                       tpg_g_line_width(&dev->tpg, p) * mp->height +
                        dev->fmt_cap->data_offset[p];
        }
        return 0;
@@ -596,18 +599,19 @@ int vivid_try_fmt_vid_cap(struct file *file, void *priv,
 
        /* This driver supports custom bytesperline values */
 
-       /* Calculate the minimum supported bytesperline value */
-       bytesperline = (mp->width * fmt->depth) >> 3;
-       /* Calculate the maximum supported bytesperline value */
-       max_bpl = (MAX_ZOOM * MAX_WIDTH * fmt->depth) >> 3;
-       mp->num_planes = fmt->planes;
+       mp->num_planes = fmt->buffers;
        for (p = 0; p < mp->num_planes; p++) {
+               /* Calculate the minimum supported bytesperline value */
+               bytesperline = (mp->width * fmt->bit_depth[p]) >> 3;
+               /* Calculate the maximum supported bytesperline value */
+               max_bpl = (MAX_ZOOM * MAX_WIDTH * fmt->bit_depth[p]) >> 3;
+
                if (pfmt[p].bytesperline > max_bpl)
                        pfmt[p].bytesperline = max_bpl;
                if (pfmt[p].bytesperline < bytesperline)
                        pfmt[p].bytesperline = bytesperline;
-               pfmt[p].sizeimage = pfmt[p].bytesperline * mp->height +
-                       fmt->data_offset[p];
+               pfmt[p].sizeimage = tpg_calc_line_width(&dev->tpg, p, pfmt[p].bytesperline) *
+                       mp->height + fmt->data_offset[p];
                memset(pfmt[p].reserved, 0, sizeof(pfmt[p].reserved));
        }
        mp->colorspace = vivid_colorspace_cap(dev);
@@ -627,6 +631,7 @@ int vivid_s_fmt_vid_cap(struct file *file, void *priv,
        struct vb2_queue *q = &dev->vb_vid_cap_q;
        int ret = vivid_try_fmt_vid_cap(file, priv, f);
        unsigned factor = 1;
+       unsigned p;
        unsigned i;
 
        if (ret < 0)
@@ -729,13 +734,15 @@ int vivid_s_fmt_vid_cap(struct file *file, void *priv,
        dev->fmt_cap_rect.width = mp->width;
        dev->fmt_cap_rect.height = mp->height;
        tpg_s_buf_height(&dev->tpg, mp->height);
-       tpg_s_bytesperline(&dev->tpg, 0, mp->plane_fmt[0].bytesperline);
-       if (tpg_g_planes(&dev->tpg) > 1)
-               tpg_s_bytesperline(&dev->tpg, 1, mp->plane_fmt[1].bytesperline);
+       tpg_s_fourcc(&dev->tpg, dev->fmt_cap->fourcc);
+       for (p = 0; p < tpg_g_buffers(&dev->tpg); p++)
+               tpg_s_bytesperline(&dev->tpg, p, mp->plane_fmt[p].bytesperline);
        dev->field_cap = mp->field;
-       tpg_s_field(&dev->tpg, dev->field_cap);
+       if (dev->field_cap == V4L2_FIELD_ALTERNATE)
+               tpg_s_field(&dev->tpg, V4L2_FIELD_TOP, true);
+       else
+               tpg_s_field(&dev->tpg, dev->field_cap, false);
        tpg_s_crop_compose(&dev->tpg, &dev->crop_cap, &dev->compose_cap);
-       tpg_s_fourcc(&dev->tpg, dev->fmt_cap->fourcc);
        if (vivid_is_sdtv_cap(dev))
                dev->tv_field_cap = mp->field;
        tpg_update_mv_step(&dev->tpg);
@@ -1012,8 +1019,12 @@ int vivid_vid_cap_cropcap(struct file *file, void *priv,
 int vidioc_enum_fmt_vid_overlay(struct file *file, void  *priv,
                                        struct v4l2_fmtdesc *f)
 {
+       struct vivid_dev *dev = video_drvdata(file);
        const struct vivid_fmt *fmt;
 
+       if (dev->multiplanar)
+               return -ENOTTY;
+
        if (f->index >= ARRAY_SIZE(formats_ovl))
                return -EINVAL;
 
@@ -1032,6 +1043,9 @@ int vidioc_g_fmt_vid_overlay(struct file *file, void *priv,
        struct v4l2_window *win = &f->fmt.win;
        unsigned clipcount = win->clipcount;
 
+       if (dev->multiplanar)
+               return -ENOTTY;
+
        win->w.top = dev->overlay_cap_top;
        win->w.left = dev->overlay_cap_left;
        win->w.width = compose->width;
@@ -1063,6 +1077,9 @@ int vidioc_try_fmt_vid_overlay(struct file *file, void *priv,
        struct v4l2_window *win = &f->fmt.win;
        int i, j;
 
+       if (dev->multiplanar)
+               return -ENOTTY;
+
        win->w.left = clamp_t(int, win->w.left,
                              -dev->fb_cap.fmt.width, dev->fb_cap.fmt.width);
        win->w.top = clamp_t(int, win->w.top,
@@ -1150,6 +1167,9 @@ int vivid_vid_cap_overlay(struct file *file, void *fh, unsigned i)
 {
        struct vivid_dev *dev = video_drvdata(file);
 
+       if (dev->multiplanar)
+               return -ENOTTY;
+
        if (i && dev->fb_vbase_cap == NULL)
                return -EINVAL;
 
@@ -1169,6 +1189,9 @@ int vivid_vid_cap_g_fbuf(struct file *file, void *fh,
 {
        struct vivid_dev *dev = video_drvdata(file);
 
+       if (dev->multiplanar)
+               return -ENOTTY;
+
        *a = dev->fb_cap;
        a->capability = V4L2_FBUF_CAP_BITMAP_CLIPPING |
                        V4L2_FBUF_CAP_LIST_CLIPPING;
@@ -1185,6 +1208,9 @@ int vivid_vid_cap_s_fbuf(struct file *file, void *fh,
        struct vivid_dev *dev = video_drvdata(file);
        const struct vivid_fmt *fmt;
 
+       if (dev->multiplanar)
+               return -ENOTTY;
+
        if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
                return -EPERM;
 
@@ -1202,7 +1228,7 @@ int vivid_vid_cap_s_fbuf(struct file *file, void *fh,
        fmt = vivid_get_format(dev, a->fmt.pixelformat);
        if (!fmt || !fmt->can_do_overlay)
                return -EINVAL;
-       if (a->fmt.bytesperline < (a->fmt.width * fmt->depth) / 8)
+       if (a->fmt.bytesperline < (a->fmt.width * fmt->bit_depth[0]) / 8)
                return -EINVAL;
        if (a->fmt.height * a->fmt.bytesperline < a->fmt.sizeimage)
                return -EINVAL;
@@ -1332,7 +1358,7 @@ int vidioc_s_input(struct file *file, void *priv, unsigned i)
                        v4l2_ctrl_s_ctrl(dev->colorspace, VIVID_CS_170M);
                        break;
                case HDMI:
-                       if (bt->standards & V4L2_DV_BT_STD_CEA861) {
+                       if (bt->flags & V4L2_DV_FL_IS_CE_VIDEO) {
                                if (dev->src_rect.width == 720 && dev->src_rect.height <= 576)
                                        v4l2_ctrl_s_ctrl(dev->colorspace, VIVID_CS_170M);
                                else
@@ -1552,6 +1578,65 @@ int vivid_vid_cap_s_std(struct file *file, void *priv, v4l2_std_id id)
        return 0;
 }
 
+static void find_aspect_ratio(u32 width, u32 height,
+                              u32 *num, u32 *denom)
+{
+       if (!(height % 3) && ((height * 4 / 3) == width)) {
+               *num = 4;
+               *denom = 3;
+       } else if (!(height % 9) && ((height * 16 / 9) == width)) {
+               *num = 16;
+               *denom = 9;
+       } else if (!(height % 10) && ((height * 16 / 10) == width)) {
+               *num = 16;
+               *denom = 10;
+       } else if (!(height % 4) && ((height * 5 / 4) == width)) {
+               *num = 5;
+               *denom = 4;
+       } else if (!(height % 9) && ((height * 15 / 9) == width)) {
+               *num = 15;
+               *denom = 9;
+       } else { /* default to 16:9 */
+               *num = 16;
+               *denom = 9;
+       }
+}
+
+static bool valid_cvt_gtf_timings(struct v4l2_dv_timings *timings)
+{
+       struct v4l2_bt_timings *bt = &timings->bt;
+       u32 total_h_pixel;
+       u32 total_v_lines;
+       u32 h_freq;
+
+       if (!v4l2_valid_dv_timings(timings, &vivid_dv_timings_cap,
+                               NULL, NULL))
+               return false;
+
+       total_h_pixel = V4L2_DV_BT_FRAME_WIDTH(bt);
+       total_v_lines = V4L2_DV_BT_FRAME_HEIGHT(bt);
+
+       h_freq = (u32)bt->pixelclock / total_h_pixel;
+
+       if (bt->standards == 0 || (bt->standards & V4L2_DV_BT_STD_CVT)) {
+               if (v4l2_detect_cvt(total_v_lines, h_freq, bt->vsync,
+                                   bt->polarities, timings))
+                       return true;
+       }
+
+       if (bt->standards == 0 || (bt->standards & V4L2_DV_BT_STD_GTF)) {
+               struct v4l2_fract aspect_ratio;
+
+               find_aspect_ratio(bt->width, bt->height,
+                                 &aspect_ratio.numerator,
+                                 &aspect_ratio.denominator);
+               if (v4l2_detect_gtf(total_v_lines, h_freq, bt->vsync,
+                                   bt->polarities, aspect_ratio, timings))
+                       return true;
+       }
+       return false;
+}
+
 int vivid_vid_cap_s_dv_timings(struct file *file, void *_fh,
                                    struct v4l2_dv_timings *timings)
 {
@@ -1559,13 +1644,16 @@ int vivid_vid_cap_s_dv_timings(struct file *file, void *_fh,
 
        if (!vivid_is_hdmi_cap(dev))
                return -ENODATA;
-       if (vb2_is_busy(&dev->vb_vid_cap_q))
-               return -EBUSY;
        if (!v4l2_find_dv_timings_cap(timings, &vivid_dv_timings_cap,
-                               0, NULL, NULL))
+                                     0, NULL, NULL) &&
+           !valid_cvt_gtf_timings(timings))
                return -EINVAL;
+
        if (v4l2_match_dv_timings(timings, &dev->dv_timings_cap, 0))
                return 0;
+       if (vb2_is_busy(&dev->vb_vid_cap_q))
+               return -EBUSY;
+
        dev->dv_timings_cap = *timings;
        vivid_update_format_cap(dev, false);
        return 0;
@@ -1663,18 +1751,14 @@ int vidioc_enum_frameintervals(struct file *file, void *priv,
                return -EINVAL;
 
        if (!vivid_is_webcam(dev)) {
-               static const struct v4l2_fract step = { 1, 1 };
-
                if (fival->index)
                        return -EINVAL;
                if (fival->width < MIN_WIDTH || fival->width > MAX_WIDTH * MAX_ZOOM)
                        return -EINVAL;
                if (fival->height < MIN_HEIGHT || fival->height > MAX_HEIGHT * MAX_ZOOM)
                        return -EINVAL;
-               fival->type = V4L2_FRMIVAL_TYPE_CONTINUOUS;
-               fival->stepwise.min = tpf_min;
-               fival->stepwise.max = tpf_max;
-               fival->stepwise.step = step;
+               fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+               fival->discrete = dev->timeperframe_vid_cap;
                return 0;
        }
 
index 6bef1e6d6788929b93059738636e938490f4535b..aa446271ad34ba57521adcf953d1a1c4e872d73a 100644 (file)
@@ -33,8 +33,9 @@ const struct v4l2_dv_timings_cap vivid_dv_timings_cap = {
        .type = V4L2_DV_BT_656_1120,
        /* keep this initialization for compatibility with GCC < 4.4.6 */
        .reserved = { 0 },
-       V4L2_INIT_BT_TIMINGS(0, MAX_WIDTH, 0, MAX_HEIGHT, 25000000, 600000000,
-               V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT,
+       V4L2_INIT_BT_TIMINGS(0, MAX_WIDTH, 0, MAX_HEIGHT, 14000000, 775000000,
+               V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
+               V4L2_DV_BT_STD_CVT | V4L2_DV_BT_STD_GTF,
                V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_INTERLACED)
 };
 
@@ -46,145 +47,435 @@ struct vivid_fmt vivid_formats[] = {
        {
                .name     = "4:2:2, packed, YUYV",
                .fourcc   = V4L2_PIX_FMT_YUYV,
-               .depth    = 16,
+               .vdownsampling = { 1 },
+               .bit_depth = { 16 },
                .is_yuv   = true,
                .planes   = 1,
-               .data_offset = { PLANE0_DATA_OFFSET, 0 },
+               .buffers = 1,
+               .data_offset = { PLANE0_DATA_OFFSET },
        },
        {
                .name     = "4:2:2, packed, UYVY",
                .fourcc   = V4L2_PIX_FMT_UYVY,
-               .depth    = 16,
+               .vdownsampling = { 1 },
+               .bit_depth = { 16 },
                .is_yuv   = true,
                .planes   = 1,
+               .buffers = 1,
        },
        {
                .name     = "4:2:2, packed, YVYU",
                .fourcc   = V4L2_PIX_FMT_YVYU,
-               .depth    = 16,
+               .vdownsampling = { 1 },
+               .bit_depth = { 16 },
                .is_yuv   = true,
                .planes   = 1,
+               .buffers = 1,
        },
        {
                .name     = "4:2:2, packed, VYUY",
                .fourcc   = V4L2_PIX_FMT_VYUY,
-               .depth    = 16,
+               .vdownsampling = { 1 },
+               .bit_depth = { 16 },
+               .is_yuv   = true,
+               .planes   = 1,
+               .buffers = 1,
+       },
+       {
+               .name     = "YUV 4:2:2 triplanar",
+               .fourcc   = V4L2_PIX_FMT_YUV422P,
+               .vdownsampling = { 1, 1, 1 },
+               .bit_depth = { 8, 4, 4 },
+               .is_yuv   = true,
+               .planes   = 3,
+               .buffers = 1,
+       },
+       {
+               .name     = "YUV 4:2:0 triplanar",
+               .fourcc   = V4L2_PIX_FMT_YUV420,
+               .vdownsampling = { 1, 2, 2 },
+               .bit_depth = { 8, 4, 4 },
+               .is_yuv   = true,
+               .planes   = 3,
+               .buffers = 1,
+       },
+       {
+               .name     = "YVU 4:2:0 triplanar",
+               .fourcc   = V4L2_PIX_FMT_YVU420,
+               .vdownsampling = { 1, 2, 2 },
+               .bit_depth = { 8, 4, 4 },
+               .is_yuv   = true,
+               .planes   = 3,
+               .buffers = 1,
+       },
+       {
+               .name     = "YUV 4:2:0 biplanar",
+               .fourcc   = V4L2_PIX_FMT_NV12,
+               .vdownsampling = { 1, 2 },
+               .bit_depth = { 8, 8 },
+               .is_yuv   = true,
+               .planes   = 2,
+               .buffers = 1,
+       },
+       {
+               .name     = "YVU 4:2:0 biplanar",
+               .fourcc   = V4L2_PIX_FMT_NV21,
+               .vdownsampling = { 1, 2 },
+               .bit_depth = { 8, 8 },
+               .is_yuv   = true,
+               .planes   = 2,
+               .buffers = 1,
+       },
+       {
+               .name     = "YUV 4:2:2 biplanar",
+               .fourcc   = V4L2_PIX_FMT_NV16,
+               .vdownsampling = { 1, 1 },
+               .bit_depth = { 8, 8 },
+               .is_yuv   = true,
+               .planes   = 2,
+               .buffers = 1,
+       },
+       {
+               .name     = "YVU 4:2:2 biplanar",
+               .fourcc   = V4L2_PIX_FMT_NV61,
+               .vdownsampling = { 1, 1 },
+               .bit_depth = { 8, 8 },
+               .is_yuv   = true,
+               .planes   = 2,
+               .buffers = 1,
+       },
+       {
+               .name     = "YUV 4:4:4 biplanar",
+               .fourcc   = V4L2_PIX_FMT_NV24,
+               .vdownsampling = { 1, 1 },
+               .bit_depth = { 8, 16 },
+               .is_yuv   = true,
+               .planes   = 2,
+               .buffers = 1,
+       },
+       {
+               .name     = "YVU 4:4:4 biplanar",
+               .fourcc   = V4L2_PIX_FMT_NV42,
+               .vdownsampling = { 1, 1 },
+               .bit_depth = { 8, 16 },
+               .is_yuv   = true,
+               .planes   = 2,
+               .buffers = 1,
+       },
+       {
+               .name     = "YUV555 (LE)",
+               .fourcc   = V4L2_PIX_FMT_YUV555, /* uuuvvvvv ayyyyyuu */
+               .vdownsampling = { 1 },
+               .bit_depth = { 16 },
+               .planes   = 1,
+               .buffers = 1,
+               .alpha_mask = 0x8000,
+       },
+       {
+               .name     = "YUV565 (LE)",
+               .fourcc   = V4L2_PIX_FMT_YUV565, /* uuuvvvvv yyyyyuuu */
+               .vdownsampling = { 1 },
+               .bit_depth = { 16 },
+               .planes   = 1,
+               .buffers = 1,
+       },
+       {
+               .name     = "YUV444",
+               .fourcc   = V4L2_PIX_FMT_YUV444, /* uuuuvvvv aaaayyyy */
+               .vdownsampling = { 1 },
+               .bit_depth = { 16 },
+               .planes   = 1,
+               .buffers = 1,
+               .alpha_mask = 0xf000,
+       },
+       {
+               .name     = "YUV32 (LE)",
+               .fourcc   = V4L2_PIX_FMT_YUV32, /* ayuv */
+               .vdownsampling = { 1 },
+               .bit_depth = { 32 },
+               .planes   = 1,
+               .buffers = 1,
+               .alpha_mask = 0x000000ff,
+       },
+       {
+               .name     = "Monochrome",
+               .fourcc   = V4L2_PIX_FMT_GREY,
+               .vdownsampling = { 1 },
+               .bit_depth = { 8 },
                .is_yuv   = true,
                .planes   = 1,
+               .buffers = 1,
+       },
+       {
+               .name     = "RGB332",
+               .fourcc   = V4L2_PIX_FMT_RGB332, /* rrrgggbb */
+               .vdownsampling = { 1 },
+               .bit_depth = { 8 },
+               .planes   = 1,
+               .buffers = 1,
        },
        {
                .name     = "RGB565 (LE)",
                .fourcc   = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
-               .depth    = 16,
+               .vdownsampling = { 1 },
+               .bit_depth = { 16 },
                .planes   = 1,
+               .buffers = 1,
                .can_do_overlay = true,
        },
        {
                .name     = "RGB565 (BE)",
                .fourcc   = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
-               .depth    = 16,
+               .vdownsampling = { 1 },
+               .bit_depth = { 16 },
                .planes   = 1,
+               .buffers = 1,
                .can_do_overlay = true,
        },
+       {
+               .name     = "RGB444",
+               .fourcc   = V4L2_PIX_FMT_RGB444, /* xxxxrrrr ggggbbbb */
+               .vdownsampling = { 1 },
+               .bit_depth = { 16 },
+               .planes   = 1,
+               .buffers = 1,
+       },
+       {
+               .name     = "XRGB444",
+               .fourcc   = V4L2_PIX_FMT_XRGB444, /* xxxxrrrr ggggbbbb */
+               .vdownsampling = { 1 },
+               .bit_depth = { 16 },
+               .planes   = 1,
+               .buffers = 1,
+       },
+       {
+               .name     = "ARGB444",
+               .fourcc   = V4L2_PIX_FMT_ARGB444, /* aaaarrrr ggggbbbb */
+               .vdownsampling = { 1 },
+               .bit_depth = { 16 },
+               .planes   = 1,
+               .buffers = 1,
+               .alpha_mask = 0x00f0,
+       },
        {
                .name     = "RGB555 (LE)",
-               .fourcc   = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */
-               .depth    = 16,
+               .fourcc   = V4L2_PIX_FMT_RGB555, /* gggbbbbb xrrrrrgg */
+               .vdownsampling = { 1 },
+               .bit_depth = { 16 },
                .planes   = 1,
+               .buffers = 1,
                .can_do_overlay = true,
        },
        {
                .name     = "XRGB555 (LE)",
-               .fourcc   = V4L2_PIX_FMT_XRGB555, /* gggbbbbb arrrrrgg */
-               .depth    = 16,
+               .fourcc   = V4L2_PIX_FMT_XRGB555, /* gggbbbbb xrrrrrgg */
+               .vdownsampling = { 1 },
+               .bit_depth = { 16 },
                .planes   = 1,
+               .buffers = 1,
                .can_do_overlay = true,
        },
        {
                .name     = "ARGB555 (LE)",
                .fourcc   = V4L2_PIX_FMT_ARGB555, /* gggbbbbb arrrrrgg */
-               .depth    = 16,
+               .vdownsampling = { 1 },
+               .bit_depth = { 16 },
                .planes   = 1,
+               .buffers = 1,
                .can_do_overlay = true,
                .alpha_mask = 0x8000,
        },
        {
                .name     = "RGB555 (BE)",
-               .fourcc   = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */
-               .depth    = 16,
+               .fourcc   = V4L2_PIX_FMT_RGB555X, /* xrrrrrgg gggbbbbb */
+               .vdownsampling = { 1 },
+               .bit_depth = { 16 },
                .planes   = 1,
-               .can_do_overlay = true,
+               .buffers = 1,
+       },
+       {
+               .name     = "XRGB555 (BE)",
+               .fourcc   = V4L2_PIX_FMT_XRGB555X, /* xrrrrrgg gggbbbbb */
+               .vdownsampling = { 1 },
+               .bit_depth = { 16 },
+               .planes   = 1,
+               .buffers = 1,
+       },
+       {
+               .name     = "ARGB555 (BE)",
+               .fourcc   = V4L2_PIX_FMT_ARGB555X, /* arrrrrgg gggbbbbb */
+               .vdownsampling = { 1 },
+               .bit_depth = { 16 },
+               .planes   = 1,
+               .buffers = 1,
+               .alpha_mask = 0x0080,
        },
        {
                .name     = "RGB24 (LE)",
                .fourcc   = V4L2_PIX_FMT_RGB24, /* rgb */
-               .depth    = 24,
+               .vdownsampling = { 1 },
+               .bit_depth = { 24 },
                .planes   = 1,
+               .buffers = 1,
        },
        {
                .name     = "RGB24 (BE)",
                .fourcc   = V4L2_PIX_FMT_BGR24, /* bgr */
-               .depth    = 24,
+               .vdownsampling = { 1 },
+               .bit_depth = { 24 },
                .planes   = 1,
+               .buffers = 1,
+       },
+       {
+               .name     = "BGR666",
+               .fourcc   = V4L2_PIX_FMT_BGR666, /* bbbbbbgg ggggrrrr rrxxxxxx */
+               .vdownsampling = { 1 },
+               .bit_depth = { 32 },
+               .planes   = 1,
+               .buffers = 1,
        },
        {
                .name     = "RGB32 (LE)",
-               .fourcc   = V4L2_PIX_FMT_RGB32, /* argb */
-               .depth    = 32,
+               .fourcc   = V4L2_PIX_FMT_RGB32, /* xrgb */
+               .vdownsampling = { 1 },
+               .bit_depth = { 32 },
                .planes   = 1,
+               .buffers = 1,
        },
        {
                .name     = "RGB32 (BE)",
-               .fourcc   = V4L2_PIX_FMT_BGR32, /* bgra */
-               .depth    = 32,
+               .fourcc   = V4L2_PIX_FMT_BGR32, /* bgrx */
+               .vdownsampling = { 1 },
+               .bit_depth = { 32 },
                .planes   = 1,
+               .buffers = 1,
        },
        {
                .name     = "XRGB32 (LE)",
-               .fourcc   = V4L2_PIX_FMT_XRGB32, /* argb */
-               .depth    = 32,
+               .fourcc   = V4L2_PIX_FMT_XRGB32, /* xrgb */
+               .vdownsampling = { 1 },
+               .bit_depth = { 32 },
                .planes   = 1,
+               .buffers = 1,
        },
        {
                .name     = "XRGB32 (BE)",
-               .fourcc   = V4L2_PIX_FMT_XBGR32, /* bgra */
-               .depth    = 32,
+               .fourcc   = V4L2_PIX_FMT_XBGR32, /* bgrx */
+               .vdownsampling = { 1 },
+               .bit_depth = { 32 },
                .planes   = 1,
+               .buffers = 1,
        },
        {
                .name     = "ARGB32 (LE)",
                .fourcc   = V4L2_PIX_FMT_ARGB32, /* argb */
-               .depth    = 32,
+               .vdownsampling = { 1 },
+               .bit_depth = { 32 },
                .planes   = 1,
+               .buffers = 1,
                .alpha_mask = 0x000000ff,
        },
        {
                .name     = "ARGB32 (BE)",
                .fourcc   = V4L2_PIX_FMT_ABGR32, /* bgra */
-               .depth    = 32,
+               .vdownsampling = { 1 },
+               .bit_depth = { 32 },
                .planes   = 1,
+               .buffers = 1,
                .alpha_mask = 0xff000000,
        },
        {
-               .name     = "4:2:2, planar, YUV",
+               .name     = "Bayer BG/GR",
+               .fourcc   = V4L2_PIX_FMT_SBGGR8, /* Bayer BG/GR */
+               .vdownsampling = { 1 },
+               .bit_depth = { 8 },
+               .planes   = 1,
+               .buffers = 1,
+       },
+       {
+               .name     = "Bayer GB/RG",
+               .fourcc   = V4L2_PIX_FMT_SGBRG8, /* Bayer GB/RG */
+               .vdownsampling = { 1 },
+               .bit_depth = { 8 },
+               .planes   = 1,
+               .buffers = 1,
+       },
+       {
+               .name     = "Bayer GR/BG",
+               .fourcc   = V4L2_PIX_FMT_SGRBG8, /* Bayer GR/BG */
+               .vdownsampling = { 1 },
+               .bit_depth = { 8 },
+               .planes   = 1,
+               .buffers = 1,
+       },
+       {
+               .name     = "Bayer RG/GB",
+               .fourcc   = V4L2_PIX_FMT_SRGGB8, /* Bayer RG/GB */
+               .vdownsampling = { 1 },
+               .bit_depth = { 8 },
+               .planes   = 1,
+               .buffers = 1,
+       },
+       {
+               .name     = "4:2:2, biplanar, YUV",
                .fourcc   = V4L2_PIX_FMT_NV16M,
-               .depth    = 8,
+               .vdownsampling = { 1, 1 },
+               .bit_depth = { 8, 8 },
                .is_yuv   = true,
                .planes   = 2,
+               .buffers = 2,
                .data_offset = { PLANE0_DATA_OFFSET, 0 },
        },
        {
-               .name     = "4:2:2, planar, YVU",
+               .name     = "4:2:2, biplanar, YVU",
                .fourcc   = V4L2_PIX_FMT_NV61M,
-               .depth    = 8,
+               .vdownsampling = { 1, 1 },
+               .bit_depth = { 8, 8 },
                .is_yuv   = true,
                .planes   = 2,
+               .buffers = 2,
                .data_offset = { 0, PLANE0_DATA_OFFSET },
        },
+       {
+               .name     = "4:2:0, triplanar, YUV",
+               .fourcc   = V4L2_PIX_FMT_YUV420M,
+               .vdownsampling = { 1, 2, 2 },
+               .bit_depth = { 8, 4, 4 },
+               .is_yuv   = true,
+               .planes   = 3,
+               .buffers = 3,
+       },
+       {
+               .name     = "4:2:0, triplanar, YVU",
+               .fourcc   = V4L2_PIX_FMT_YVU420M,
+               .vdownsampling = { 1, 2, 2 },
+               .bit_depth = { 8, 4, 4 },
+               .is_yuv   = true,
+               .planes   = 3,
+               .buffers = 3,
+       },
+       {
+               .name     = "4:2:0, biplanar, YUV",
+               .fourcc   = V4L2_PIX_FMT_NV12M,
+               .vdownsampling = { 1, 2 },
+               .bit_depth = { 8, 8 },
+               .is_yuv   = true,
+               .planes   = 2,
+               .buffers = 2,
+       },
+       {
+               .name     = "4:2:0, biplanar, YVU",
+               .fourcc   = V4L2_PIX_FMT_NV21M,
+               .vdownsampling = { 1, 2 },
+               .bit_depth = { 8, 8 },
+               .is_yuv   = true,
+               .planes   = 2,
+               .buffers = 2,
+       },
 };
 
-/* There are 2 multiplanar formats in the list */
-#define VIVID_MPLANAR_FORMATS 2
+/* There are 6 multiplanar formats in the list */
+#define VIVID_MPLANAR_FORMATS 6
 
 const struct vivid_fmt *vivid_get_format(struct vivid_dev *dev, u32 pixelformat)
 {
@@ -194,7 +485,7 @@ const struct vivid_fmt *vivid_get_format(struct vivid_dev *dev, u32 pixelformat)
        for (k = 0; k < ARRAY_SIZE(vivid_formats); k++) {
                fmt = &vivid_formats[k];
                if (fmt->fourcc == pixelformat)
-                       if (fmt->planes == 1 || dev->multiplanar)
+                       if (fmt->buffers == 1 || dev->multiplanar)
                                return fmt;
        }
 
@@ -210,6 +501,13 @@ bool vivid_vid_can_loop(struct vivid_dev *dev)
                return false;
        if (dev->field_cap != dev->field_out)
                return false;
+       /*
+        * While this can be supported, it is just too much work
+        * to actually implement.
+        */
+       if (dev->field_cap == V4L2_FIELD_SEQ_TB ||
+           dev->field_cap == V4L2_FIELD_SEQ_BT)
+               return false;
        if (vivid_is_svid_cap(dev) && vivid_is_svid_out(dev)) {
                if (!(dev->std_cap & V4L2_STD_525_60) !=
                    !(dev->std_out & V4L2_STD_525_60))
@@ -397,6 +695,9 @@ int vivid_vid_adjust_sel(unsigned flags, struct v4l2_rect *r)
        unsigned w = r->width;
        unsigned h = r->height;
 
+       /* sanitize w and h in case someone passes ~0 as the value */
+       w &= 0xffff;
+       h &= 0xffff;
        if (!(flags & V4L2_SEL_FLAG_LE)) {
                w++;
                h++;
@@ -421,8 +722,9 @@ int vivid_vid_adjust_sel(unsigned flags, struct v4l2_rect *r)
                r->top = 0;
        if (r->left < 0)
                r->left = 0;
-       r->left &= ~1;
-       r->top &= ~1;
+       /* sanitize left and top in case someone passes ~0 as the value */
+       r->left &= 0xfffe;
+       r->top &= 0xfffe;
        if (r->left + w > MAX_WIDTH)
                r->left = MAX_WIDTH - w;
        if (r->top + h > MAX_HEIGHT)
index 39ff79f6aa67da8453cba76321364ca857f16509..0af43dc7715c3fb7a1b0a4ba457571370f26c4e3 100644 (file)
@@ -36,9 +36,14 @@ static int vid_out_queue_setup(struct vb2_queue *vq, const struct v4l2_format *f
                       unsigned sizes[], void *alloc_ctxs[])
 {
        struct vivid_dev *dev = vb2_get_drv_priv(vq);
-       unsigned planes = dev->fmt_out->planes;
+       const struct vivid_fmt *vfmt = dev->fmt_out;
+       unsigned planes = vfmt->buffers;
        unsigned h = dev->fmt_out_rect.height;
        unsigned size = dev->bytesperline_out[0] * h;
+       unsigned p;
+
+       for (p = vfmt->buffers; p < vfmt->planes; p++)
+               size += dev->bytesperline_out[p] * h / vfmt->vdownsampling[p];
 
        if (dev->field_out == V4L2_FIELD_ALTERNATE) {
                /*
@@ -74,21 +79,16 @@ static int vid_out_queue_setup(struct vb2_queue *vq, const struct v4l2_format *f
                if (mp->num_planes != planes)
                        return -EINVAL;
                sizes[0] = mp->plane_fmt[0].sizeimage;
-               if (planes == 2) {
-                       sizes[1] = mp->plane_fmt[1].sizeimage;
-                       if (sizes[0] < dev->bytesperline_out[0] * h ||
-                           sizes[1] < dev->bytesperline_out[1] * h)
-                               return -EINVAL;
-               } else if (sizes[0] < size) {
+               if (sizes[0] < size)
                        return -EINVAL;
+               for (p = 1; p < planes; p++) {
+                       sizes[p] = mp->plane_fmt[p].sizeimage;
+                       if (sizes[p] < dev->bytesperline_out[p] * h)
+                               return -EINVAL;
                }
        } else {
-               if (planes == 2) {
-                       sizes[0] = dev->bytesperline_out[0] * h;
-                       sizes[1] = dev->bytesperline_out[1] * h;
-               } else {
-                       sizes[0] = size;
-               }
+               for (p = 0; p < planes; p++)
+                       sizes[p] = p ? dev->bytesperline_out[p] * h : size;
        }
 
        if (vq->num_buffers + *nbuffers < 2)
@@ -101,12 +101,9 @@ static int vid_out_queue_setup(struct vb2_queue *vq, const struct v4l2_format *f
         * alloc_ctxs array.
         */
 
-       if (planes == 2)
-               dprintk(dev, 1, "%s, count=%d, sizes=%u, %u\n", __func__,
-                       *nbuffers, sizes[0], sizes[1]);
-       else
-               dprintk(dev, 1, "%s, count=%d, size=%u\n", __func__,
-                       *nbuffers, sizes[0]);
+       dprintk(dev, 1, "%s: count=%d\n", __func__, *nbuffers);
+       for (p = 0; p < planes; p++)
+               dprintk(dev, 1, "%s: size[%u]=%u\n", __func__, p, sizes[p]);
        return 0;
 }
 
@@ -114,7 +111,7 @@ static int vid_out_buf_prepare(struct vb2_buffer *vb)
 {
        struct vivid_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
        unsigned long size;
-       unsigned planes = dev->fmt_out->planes;
+       unsigned planes;
        unsigned p;
 
        dprintk(dev, 1, "%s\n", __func__);
@@ -122,6 +119,8 @@ static int vid_out_buf_prepare(struct vb2_buffer *vb)
        if (WARN_ON(NULL == dev->fmt_out))
                return -EINVAL;
 
+       planes = dev->fmt_out->planes;
+
        if (dev->buf_prepare_error) {
                /*
                 * Error injection: test what happens if buf_prepare() returns
@@ -220,7 +219,7 @@ const struct vb2_ops vivid_vid_out_qops = {
 void vivid_update_format_out(struct vivid_dev *dev)
 {
        struct v4l2_bt_timings *bt = &dev->dv_timings_out.bt;
-       unsigned size;
+       unsigned size, p;
 
        switch (dev->output_type[dev->output]) {
        case SVID:
@@ -249,7 +248,7 @@ void vivid_update_format_out(struct vivid_dev *dev)
                        dev->field_out = V4L2_FIELD_ALTERNATE;
                else
                        dev->field_out = V4L2_FIELD_NONE;
-               if (!dev->dvi_d_out && (bt->standards & V4L2_DV_BT_STD_CEA861)) {
+               if (!dev->dvi_d_out && (bt->flags & V4L2_DV_FL_IS_CE_VIDEO)) {
                        if (bt->width == 720 && bt->height <= 576)
                                dev->colorspace_out = V4L2_COLORSPACE_SMPTE170M;
                        else
@@ -267,9 +266,9 @@ void vivid_update_format_out(struct vivid_dev *dev)
        if (V4L2_FIELD_HAS_T_OR_B(dev->field_out))
                dev->crop_out.height /= 2;
        dev->fmt_out_rect = dev->crop_out;
-       dev->bytesperline_out[0] = (dev->sink_rect.width * dev->fmt_out->depth) / 8;
-       if (dev->fmt_out->planes == 2)
-               dev->bytesperline_out[1] = (dev->sink_rect.width * dev->fmt_out->depth) / 8;
+       for (p = 0; p < dev->fmt_out->planes; p++)
+               dev->bytesperline_out[p] =
+                       (dev->sink_rect.width * dev->fmt_out->bit_depth[p]) / 8;
 }
 
 /* Map the field to something that is valid for the current output */
@@ -313,21 +312,28 @@ int vivid_g_fmt_vid_out(struct file *file, void *priv,
 {
        struct vivid_dev *dev = video_drvdata(file);
        struct v4l2_pix_format_mplane *mp = &f->fmt.pix_mp;
+       const struct vivid_fmt *fmt = dev->fmt_out;
        unsigned p;
 
        mp->width        = dev->fmt_out_rect.width;
        mp->height       = dev->fmt_out_rect.height;
        mp->field        = dev->field_out;
-       mp->pixelformat  = dev->fmt_out->fourcc;
+       mp->pixelformat  = fmt->fourcc;
        mp->colorspace   = dev->colorspace_out;
        mp->ycbcr_enc    = dev->ycbcr_enc_out;
        mp->quantization = dev->quantization_out;
-       mp->num_planes = dev->fmt_out->planes;
+       mp->num_planes = fmt->buffers;
        for (p = 0; p < mp->num_planes; p++) {
                mp->plane_fmt[p].bytesperline = dev->bytesperline_out[p];
                mp->plane_fmt[p].sizeimage =
                        mp->plane_fmt[p].bytesperline * mp->height;
        }
+       for (p = fmt->buffers; p < fmt->planes; p++) {
+               unsigned stride = dev->bytesperline_out[p];
+
+               mp->plane_fmt[0].sizeimage +=
+                       (stride * mp->height) / fmt->vdownsampling[p];
+       }
        return 0;
 }
 
@@ -386,10 +392,10 @@ int vivid_try_fmt_vid_out(struct file *file, void *priv,
        /* This driver supports custom bytesperline values */
 
        /* Calculate the minimum supported bytesperline value */
-       bytesperline = (mp->width * fmt->depth) >> 3;
+       bytesperline = (mp->width * fmt->bit_depth[0]) >> 3;
        /* Calculate the maximum supported bytesperline value */
-       max_bpl = (MAX_ZOOM * MAX_WIDTH * fmt->depth) >> 3;
-       mp->num_planes = fmt->planes;
+       max_bpl = (MAX_ZOOM * MAX_WIDTH * fmt->bit_depth[0]) >> 3;
+       mp->num_planes = fmt->buffers;
        for (p = 0; p < mp->num_planes; p++) {
                if (pfmt[p].bytesperline > max_bpl)
                        pfmt[p].bytesperline = max_bpl;
@@ -398,11 +404,14 @@ int vivid_try_fmt_vid_out(struct file *file, void *priv,
                pfmt[p].sizeimage = pfmt[p].bytesperline * mp->height;
                memset(pfmt[p].reserved, 0, sizeof(pfmt[p].reserved));
        }
+       for (p = fmt->buffers; p < fmt->planes; p++)
+               pfmt[0].sizeimage += (pfmt[0].bytesperline * fmt->bit_depth[p]) /
+                                    (fmt->bit_depth[0] * fmt->vdownsampling[p]);
        mp->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
        mp->quantization = V4L2_QUANTIZATION_DEFAULT;
        if (vivid_is_svid_out(dev)) {
                mp->colorspace = V4L2_COLORSPACE_SMPTE170M;
-       } else if (dev->dvi_d_out || !(bt->standards & V4L2_DV_BT_STD_CEA861)) {
+       } else if (dev->dvi_d_out || !(bt->flags & V4L2_DV_FL_IS_CE_VIDEO)) {
                mp->colorspace = V4L2_COLORSPACE_SRGB;
                if (dev->dvi_d_out)
                        mp->quantization = V4L2_QUANTIZATION_LIM_RANGE;
@@ -429,6 +438,7 @@ int vivid_s_fmt_vid_out(struct file *file, void *priv,
        struct vb2_queue *q = &dev->vb_vid_out_q;
        int ret = vivid_try_fmt_vid_out(file, priv, f);
        unsigned factor = 1;
+       unsigned p;
 
        if (ret < 0)
                return ret;
@@ -524,9 +534,12 @@ int vivid_s_fmt_vid_out(struct file *file, void *priv,
 
        dev->fmt_out_rect.width = mp->width;
        dev->fmt_out_rect.height = mp->height;
-       dev->bytesperline_out[0] = mp->plane_fmt[0].bytesperline;
-       if (mp->num_planes > 1)
-               dev->bytesperline_out[1] = mp->plane_fmt[1].bytesperline;
+       for (p = 0; p < mp->num_planes; p++)
+               dev->bytesperline_out[p] = mp->plane_fmt[p].bytesperline;
+       for (p = dev->fmt_out->buffers; p < dev->fmt_out->planes; p++)
+               dev->bytesperline_out[p] =
+                       (dev->bytesperline_out[0] * dev->fmt_out->bit_depth[p]) /
+                       dev->fmt_out->bit_depth[0];
        dev->field_out = mp->field;
        if (vivid_is_svid_out(dev))
                dev->tv_field_out = mp->field;
@@ -1114,13 +1127,13 @@ int vivid_vid_out_s_dv_timings(struct file *file, void *_fh,
 
        if (!vivid_is_hdmi_out(dev))
                return -ENODATA;
-       if (vb2_is_busy(&dev->vb_vid_out_q))
-               return -EBUSY;
        if (!v4l2_find_dv_timings_cap(timings, &vivid_dv_timings_cap,
                                0, NULL, NULL))
                return -EINVAL;
        if (v4l2_match_dv_timings(timings, &dev->dv_timings_out, 0))
                return 0;
+       if (vb2_is_busy(&dev->vb_vid_out_q))
+               return -EBUSY;
        dev->dv_timings_out = *timings;
        vivid_update_format_out(dev);
        return 0;
index 401e2b77a0b69f26bf78907c0fcd6eb11bcf355c..7dd763311c0f3974bd7fd43ddd790628723148b2 100644 (file)
@@ -183,13 +183,14 @@ static int bru_s_stream(struct v4l2_subdev *subdev, int enable)
  */
 
 static int bru_enum_mbus_code(struct v4l2_subdev *subdev,
-                             struct v4l2_subdev_fh *fh,
+                             struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_mbus_code_enum *code)
 {
        static const unsigned int codes[] = {
                MEDIA_BUS_FMT_ARGB8888_1X32,
                MEDIA_BUS_FMT_AYUV8_1X32,
        };
+       struct vsp1_bru *bru = to_bru(subdev);
        struct v4l2_mbus_framefmt *format;
 
        if (code->pad == BRU_PAD_SINK(0)) {
@@ -201,7 +202,8 @@ static int bru_enum_mbus_code(struct v4l2_subdev *subdev,
                if (code->index)
                        return -EINVAL;
 
-               format = v4l2_subdev_get_try_format(fh, BRU_PAD_SINK(0));
+               format = vsp1_entity_get_pad_format(&bru->entity, cfg,
+                                                   BRU_PAD_SINK(0), code->which);
                code->code = format->code;
        }
 
@@ -209,7 +211,7 @@ static int bru_enum_mbus_code(struct v4l2_subdev *subdev,
 }
 
 static int bru_enum_frame_size(struct v4l2_subdev *subdev,
-                              struct v4l2_subdev_fh *fh,
+                              struct v4l2_subdev_pad_config *cfg,
                               struct v4l2_subdev_frame_size_enum *fse)
 {
        if (fse->index)
@@ -228,12 +230,12 @@ static int bru_enum_frame_size(struct v4l2_subdev *subdev,
 }
 
 static struct v4l2_rect *bru_get_compose(struct vsp1_bru *bru,
-                                        struct v4l2_subdev_fh *fh,
+                                        struct v4l2_subdev_pad_config *cfg,
                                         unsigned int pad, u32 which)
 {
        switch (which) {
        case V4L2_SUBDEV_FORMAT_TRY:
-               return v4l2_subdev_get_try_crop(fh, pad);
+               return v4l2_subdev_get_try_crop(&bru->entity.subdev, cfg, pad);
        case V4L2_SUBDEV_FORMAT_ACTIVE:
                return &bru->inputs[pad].compose;
        default:
@@ -241,18 +243,18 @@ static struct v4l2_rect *bru_get_compose(struct vsp1_bru *bru,
        }
 }
 
-static int bru_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
+static int bru_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg,
                          struct v4l2_subdev_format *fmt)
 {
        struct vsp1_bru *bru = to_bru(subdev);
 
-       fmt->format = *vsp1_entity_get_pad_format(&bru->entity, fh, fmt->pad,
+       fmt->format = *vsp1_entity_get_pad_format(&bru->entity, cfg, fmt->pad,
                                                  fmt->which);
 
        return 0;
 }
 
-static void bru_try_format(struct vsp1_bru *bru, struct v4l2_subdev_fh *fh,
+static void bru_try_format(struct vsp1_bru *bru, struct v4l2_subdev_pad_config *cfg,
                           unsigned int pad, struct v4l2_mbus_framefmt *fmt,
                           enum v4l2_subdev_format_whence which)
 {
@@ -268,7 +270,7 @@ static void bru_try_format(struct vsp1_bru *bru, struct v4l2_subdev_fh *fh,
 
        default:
                /* The BRU can't perform format conversion. */
-               format = vsp1_entity_get_pad_format(&bru->entity, fh,
+               format = vsp1_entity_get_pad_format(&bru->entity, cfg,
                                                    BRU_PAD_SINK(0), which);
                fmt->code = format->code;
                break;
@@ -280,15 +282,15 @@ static void bru_try_format(struct vsp1_bru *bru, struct v4l2_subdev_fh *fh,
        fmt->colorspace = V4L2_COLORSPACE_SRGB;
 }
 
-static int bru_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
+static int bru_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg,
                          struct v4l2_subdev_format *fmt)
 {
        struct vsp1_bru *bru = to_bru(subdev);
        struct v4l2_mbus_framefmt *format;
 
-       bru_try_format(bru, fh, fmt->pad, &fmt->format, fmt->which);
+       bru_try_format(bru, cfg, fmt->pad, &fmt->format, fmt->which);
 
-       format = vsp1_entity_get_pad_format(&bru->entity, fh, fmt->pad,
+       format = vsp1_entity_get_pad_format(&bru->entity, cfg, fmt->pad,
                                            fmt->which);
        *format = fmt->format;
 
@@ -296,7 +298,7 @@ static int bru_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
        if (fmt->pad != BRU_PAD_SOURCE) {
                struct v4l2_rect *compose;
 
-               compose = bru_get_compose(bru, fh, fmt->pad, fmt->which);
+               compose = bru_get_compose(bru, cfg, fmt->pad, fmt->which);
                compose->left = 0;
                compose->top = 0;
                compose->width = format->width;
@@ -308,7 +310,7 @@ static int bru_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
                unsigned int i;
 
                for (i = 0; i <= BRU_PAD_SOURCE; ++i) {
-                       format = vsp1_entity_get_pad_format(&bru->entity, fh,
+                       format = vsp1_entity_get_pad_format(&bru->entity, cfg,
                                                            i, fmt->which);
                        format->code = fmt->format.code;
                }
@@ -318,7 +320,7 @@ static int bru_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
 }
 
 static int bru_get_selection(struct v4l2_subdev *subdev,
-                            struct v4l2_subdev_fh *fh,
+                            struct v4l2_subdev_pad_config *cfg,
                             struct v4l2_subdev_selection *sel)
 {
        struct vsp1_bru *bru = to_bru(subdev);
@@ -335,7 +337,7 @@ static int bru_get_selection(struct v4l2_subdev *subdev,
                return 0;
 
        case V4L2_SEL_TGT_COMPOSE:
-               sel->r = *bru_get_compose(bru, fh, sel->pad, sel->which);
+               sel->r = *bru_get_compose(bru, cfg, sel->pad, sel->which);
                return 0;
 
        default:
@@ -344,7 +346,7 @@ static int bru_get_selection(struct v4l2_subdev *subdev,
 }
 
 static int bru_set_selection(struct v4l2_subdev *subdev,
-                            struct v4l2_subdev_fh *fh,
+                            struct v4l2_subdev_pad_config *cfg,
                             struct v4l2_subdev_selection *sel)
 {
        struct vsp1_bru *bru = to_bru(subdev);
@@ -360,7 +362,7 @@ static int bru_set_selection(struct v4l2_subdev *subdev,
        /* The compose rectangle top left corner must be inside the output
         * frame.
         */
-       format = vsp1_entity_get_pad_format(&bru->entity, fh, BRU_PAD_SOURCE,
+       format = vsp1_entity_get_pad_format(&bru->entity, cfg, BRU_PAD_SOURCE,
                                            sel->which);
        sel->r.left = clamp_t(unsigned int, sel->r.left, 0, format->width - 1);
        sel->r.top = clamp_t(unsigned int, sel->r.top, 0, format->height - 1);
@@ -368,12 +370,12 @@ static int bru_set_selection(struct v4l2_subdev *subdev,
        /* Scaling isn't supported, the compose rectangle size must be identical
         * to the sink format size.
         */
-       format = vsp1_entity_get_pad_format(&bru->entity, fh, sel->pad,
+       format = vsp1_entity_get_pad_format(&bru->entity, cfg, sel->pad,
                                            sel->which);
        sel->r.width = format->width;
        sel->r.height = format->height;
 
-       compose = bru_get_compose(bru, fh, sel->pad, sel->which);
+       compose = bru_get_compose(bru, cfg, sel->pad, sel->which);
        *compose = sel->r;
 
        return 0;
index 79af71d5e2709bb4d00222a8ff90ec761f5b7e3c..a453bb4ddd37df65562bf98f571c332e239ca628 100644 (file)
@@ -63,12 +63,12 @@ int vsp1_entity_set_streaming(struct vsp1_entity *entity, bool streaming)
 
 struct v4l2_mbus_framefmt *
 vsp1_entity_get_pad_format(struct vsp1_entity *entity,
-                          struct v4l2_subdev_fh *fh,
+                          struct v4l2_subdev_pad_config *cfg,
                           unsigned int pad, u32 which)
 {
        switch (which) {
        case V4L2_SUBDEV_FORMAT_TRY:
-               return v4l2_subdev_get_try_format(fh, pad);
+               return v4l2_subdev_get_try_format(&entity->subdev, cfg, pad);
        case V4L2_SUBDEV_FORMAT_ACTIVE:
                return &entity->formats[pad];
        default:
@@ -79,14 +79,14 @@ vsp1_entity_get_pad_format(struct vsp1_entity *entity,
 /*
  * vsp1_entity_init_formats - Initialize formats on all pads
  * @subdev: V4L2 subdevice
- * @fh: V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad configuration
  *
- * Initialize all pad formats with default values. If fh is not NULL, try
+ * Initialize all pad formats with default values. If cfg is not NULL, try
  * formats are initialized on the file handle. Otherwise active formats are
  * initialized on the device.
  */
 void vsp1_entity_init_formats(struct v4l2_subdev *subdev,
-                           struct v4l2_subdev_fh *fh)
+                           struct v4l2_subdev_pad_config *cfg)
 {
        struct v4l2_subdev_format format;
        unsigned int pad;
@@ -95,17 +95,17 @@ void vsp1_entity_init_formats(struct v4l2_subdev *subdev,
                memset(&format, 0, sizeof(format));
 
                format.pad = pad;
-               format.which = fh ? V4L2_SUBDEV_FORMAT_TRY
+               format.which = cfg ? V4L2_SUBDEV_FORMAT_TRY
                             : V4L2_SUBDEV_FORMAT_ACTIVE;
 
-               v4l2_subdev_call(subdev, pad, set_fmt, fh, &format);
+               v4l2_subdev_call(subdev, pad, set_fmt, cfg, &format);
        }
 }
 
 static int vsp1_entity_open(struct v4l2_subdev *subdev,
                            struct v4l2_subdev_fh *fh)
 {
-       vsp1_entity_init_formats(subdev, fh);
+       vsp1_entity_init_formats(subdev, fh->pad);
 
        return 0;
 }
index aa20aaa58208e559ab96e976f04340d45014fa9b..62c768d1c6aa985a92f343514704fa20a054ab94 100644 (file)
@@ -91,10 +91,10 @@ extern const struct media_entity_operations vsp1_media_ops;
 
 struct v4l2_mbus_framefmt *
 vsp1_entity_get_pad_format(struct vsp1_entity *entity,
-                          struct v4l2_subdev_fh *fh,
+                          struct v4l2_subdev_pad_config *cfg,
                           unsigned int pad, u32 which);
 void vsp1_entity_init_formats(struct v4l2_subdev *subdev,
-                             struct v4l2_subdev_fh *fh);
+                             struct v4l2_subdev_pad_config *cfg);
 
 bool vsp1_entity_is_streaming(struct vsp1_entity *entity);
 int vsp1_entity_set_streaming(struct vsp1_entity *entity, bool streaming);
index 0bc0471746c922f644f5ccc8756335c67ff48013..8ffb817ae5255809498f0716a6d91604ad31880c 100644 (file)
@@ -55,7 +55,7 @@ static int hsit_s_stream(struct v4l2_subdev *subdev, int enable)
  */
 
 static int hsit_enum_mbus_code(struct v4l2_subdev *subdev,
-                              struct v4l2_subdev_fh *fh,
+                              struct v4l2_subdev_pad_config *cfg,
                               struct v4l2_subdev_mbus_code_enum *code)
 {
        struct vsp1_hsit *hsit = to_hsit(subdev);
@@ -73,12 +73,14 @@ static int hsit_enum_mbus_code(struct v4l2_subdev *subdev,
 }
 
 static int hsit_enum_frame_size(struct v4l2_subdev *subdev,
-                               struct v4l2_subdev_fh *fh,
+                               struct v4l2_subdev_pad_config *cfg,
                                struct v4l2_subdev_frame_size_enum *fse)
 {
+       struct vsp1_hsit *hsit = to_hsit(subdev);
        struct v4l2_mbus_framefmt *format;
 
-       format = v4l2_subdev_get_try_format(fh, fse->pad);
+       format = vsp1_entity_get_pad_format(&hsit->entity, cfg, fse->pad,
+                                           fse->which);
 
        if (fse->index || fse->code != format->code)
                return -EINVAL;
@@ -102,25 +104,25 @@ static int hsit_enum_frame_size(struct v4l2_subdev *subdev,
 }
 
 static int hsit_get_format(struct v4l2_subdev *subdev,
-                          struct v4l2_subdev_fh *fh,
+                          struct v4l2_subdev_pad_config *cfg,
                           struct v4l2_subdev_format *fmt)
 {
        struct vsp1_hsit *hsit = to_hsit(subdev);
 
-       fmt->format = *vsp1_entity_get_pad_format(&hsit->entity, fh, fmt->pad,
+       fmt->format = *vsp1_entity_get_pad_format(&hsit->entity, cfg, fmt->pad,
                                                  fmt->which);
 
        return 0;
 }
 
 static int hsit_set_format(struct v4l2_subdev *subdev,
-                          struct v4l2_subdev_fh *fh,
+                          struct v4l2_subdev_pad_config *cfg,
                           struct v4l2_subdev_format *fmt)
 {
        struct vsp1_hsit *hsit = to_hsit(subdev);
        struct v4l2_mbus_framefmt *format;
 
-       format = vsp1_entity_get_pad_format(&hsit->entity, fh, fmt->pad,
+       format = vsp1_entity_get_pad_format(&hsit->entity, cfg, fmt->pad,
                                            fmt->which);
 
        if (fmt->pad == HSIT_PAD_SOURCE) {
@@ -143,7 +145,7 @@ static int hsit_set_format(struct v4l2_subdev *subdev,
        fmt->format = *format;
 
        /* Propagate the format to the source pad. */
-       format = vsp1_entity_get_pad_format(&hsit->entity, fh, HSIT_PAD_SOURCE,
+       format = vsp1_entity_get_pad_format(&hsit->entity, cfg, HSIT_PAD_SOURCE,
                                            fmt->which);
        *format = fmt->format;
        format->code = hsit->inverse ? MEDIA_BUS_FMT_ARGB8888_1X32
index 17a6ca7dafe6c240c6af50a9ae9c24db8289dc7b..39fa5ef20fbb725d79f05d3b038dda706438dfe3 100644 (file)
@@ -74,13 +74,14 @@ static int lif_s_stream(struct v4l2_subdev *subdev, int enable)
  */
 
 static int lif_enum_mbus_code(struct v4l2_subdev *subdev,
-                             struct v4l2_subdev_fh *fh,
+                             struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_mbus_code_enum *code)
 {
        static const unsigned int codes[] = {
                MEDIA_BUS_FMT_ARGB8888_1X32,
                MEDIA_BUS_FMT_AYUV8_1X32,
        };
+       struct vsp1_lif *lif = to_lif(subdev);
 
        if (code->pad == LIF_PAD_SINK) {
                if (code->index >= ARRAY_SIZE(codes))
@@ -96,7 +97,8 @@ static int lif_enum_mbus_code(struct v4l2_subdev *subdev,
                if (code->index)
                        return -EINVAL;
 
-               format = v4l2_subdev_get_try_format(fh, LIF_PAD_SINK);
+               format = vsp1_entity_get_pad_format(&lif->entity, cfg,
+                                                   LIF_PAD_SINK, code->which);
                code->code = format->code;
        }
 
@@ -104,12 +106,14 @@ static int lif_enum_mbus_code(struct v4l2_subdev *subdev,
 }
 
 static int lif_enum_frame_size(struct v4l2_subdev *subdev,
-                              struct v4l2_subdev_fh *fh,
+                              struct v4l2_subdev_pad_config *cfg,
                               struct v4l2_subdev_frame_size_enum *fse)
 {
+       struct vsp1_lif *lif = to_lif(subdev);
        struct v4l2_mbus_framefmt *format;
 
-       format = v4l2_subdev_get_try_format(fh, LIF_PAD_SINK);
+       format = vsp1_entity_get_pad_format(&lif->entity, cfg, LIF_PAD_SINK,
+                                           fse->which);
 
        if (fse->index || fse->code != format->code)
                return -EINVAL;
@@ -129,18 +133,18 @@ static int lif_enum_frame_size(struct v4l2_subdev *subdev,
        return 0;
 }
 
-static int lif_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
+static int lif_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg,
                          struct v4l2_subdev_format *fmt)
 {
        struct vsp1_lif *lif = to_lif(subdev);
 
-       fmt->format = *vsp1_entity_get_pad_format(&lif->entity, fh, fmt->pad,
+       fmt->format = *vsp1_entity_get_pad_format(&lif->entity, cfg, fmt->pad,
                                                  fmt->which);
 
        return 0;
 }
 
-static int lif_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
+static int lif_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg,
                          struct v4l2_subdev_format *fmt)
 {
        struct vsp1_lif *lif = to_lif(subdev);
@@ -151,7 +155,7 @@ static int lif_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
            fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
                fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
 
-       format = vsp1_entity_get_pad_format(&lif->entity, fh, fmt->pad,
+       format = vsp1_entity_get_pad_format(&lif->entity, cfg, fmt->pad,
                                            fmt->which);
 
        if (fmt->pad == LIF_PAD_SOURCE) {
@@ -173,7 +177,7 @@ static int lif_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
        fmt->format = *format;
 
        /* Propagate the format to the source pad. */
-       format = vsp1_entity_get_pad_format(&lif->entity, fh, LIF_PAD_SOURCE,
+       format = vsp1_entity_get_pad_format(&lif->entity, cfg, LIF_PAD_SOURCE,
                                            fmt->which);
        *format = fmt->format;
 
index 6f185c3621feb15a27a8bc178a56c1039edaa669..656ec272a414b6c0bbfb00f5cd0409d4489368d5 100644 (file)
@@ -82,7 +82,7 @@ static int lut_s_stream(struct v4l2_subdev *subdev, int enable)
  */
 
 static int lut_enum_mbus_code(struct v4l2_subdev *subdev,
-                             struct v4l2_subdev_fh *fh,
+                             struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_mbus_code_enum *code)
 {
        static const unsigned int codes[] = {
@@ -90,6 +90,7 @@ static int lut_enum_mbus_code(struct v4l2_subdev *subdev,
                MEDIA_BUS_FMT_AHSV8888_1X32,
                MEDIA_BUS_FMT_AYUV8_1X32,
        };
+       struct vsp1_lut *lut = to_lut(subdev);
        struct v4l2_mbus_framefmt *format;
 
        if (code->pad == LUT_PAD_SINK) {
@@ -104,7 +105,8 @@ static int lut_enum_mbus_code(struct v4l2_subdev *subdev,
                if (code->index)
                        return -EINVAL;
 
-               format = v4l2_subdev_get_try_format(fh, LUT_PAD_SINK);
+               format = vsp1_entity_get_pad_format(&lut->entity, cfg,
+                                                   LUT_PAD_SINK, code->which);
                code->code = format->code;
        }
 
@@ -112,12 +114,14 @@ static int lut_enum_mbus_code(struct v4l2_subdev *subdev,
 }
 
 static int lut_enum_frame_size(struct v4l2_subdev *subdev,
-                              struct v4l2_subdev_fh *fh,
+                              struct v4l2_subdev_pad_config *cfg,
                               struct v4l2_subdev_frame_size_enum *fse)
 {
+       struct vsp1_lut *lut = to_lut(subdev);
        struct v4l2_mbus_framefmt *format;
 
-       format = v4l2_subdev_get_try_format(fh, fse->pad);
+       format = vsp1_entity_get_pad_format(&lut->entity, cfg,
+                                           fse->pad, fse->which);
 
        if (fse->index || fse->code != format->code)
                return -EINVAL;
@@ -140,18 +144,18 @@ static int lut_enum_frame_size(struct v4l2_subdev *subdev,
        return 0;
 }
 
-static int lut_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
+static int lut_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg,
                          struct v4l2_subdev_format *fmt)
 {
        struct vsp1_lut *lut = to_lut(subdev);
 
-       fmt->format = *vsp1_entity_get_pad_format(&lut->entity, fh, fmt->pad,
+       fmt->format = *vsp1_entity_get_pad_format(&lut->entity, cfg, fmt->pad,
                                                  fmt->which);
 
        return 0;
 }
 
-static int lut_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
+static int lut_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg,
                          struct v4l2_subdev_format *fmt)
 {
        struct vsp1_lut *lut = to_lut(subdev);
@@ -163,7 +167,7 @@ static int lut_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
            fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
                fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
 
-       format = vsp1_entity_get_pad_format(&lut->entity, fh, fmt->pad,
+       format = vsp1_entity_get_pad_format(&lut->entity, cfg, fmt->pad,
                                            fmt->which);
 
        if (fmt->pad == LUT_PAD_SOURCE) {
@@ -182,7 +186,7 @@ static int lut_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
        fmt->format = *format;
 
        /* Propagate the format to the source pad. */
-       format = vsp1_entity_get_pad_format(&lut->entity, fh, LUT_PAD_SOURCE,
+       format = vsp1_entity_get_pad_format(&lut->entity, cfg, LUT_PAD_SOURCE,
                                            fmt->which);
        *format = fmt->format;
 
index 1f1ba26a834a5019ede7bb3c429eedeaff6cf13b..fa71f4695e1684dc97d622da7d6899245c665332 100644 (file)
@@ -25,7 +25,7 @@
  */
 
 int vsp1_rwpf_enum_mbus_code(struct v4l2_subdev *subdev,
-                            struct v4l2_subdev_fh *fh,
+                            struct v4l2_subdev_pad_config *cfg,
                             struct v4l2_subdev_mbus_code_enum *code)
 {
        static const unsigned int codes[] = {
@@ -42,13 +42,14 @@ int vsp1_rwpf_enum_mbus_code(struct v4l2_subdev *subdev,
 }
 
 int vsp1_rwpf_enum_frame_size(struct v4l2_subdev *subdev,
-                             struct v4l2_subdev_fh *fh,
+                             struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_frame_size_enum *fse)
 {
        struct vsp1_rwpf *rwpf = to_rwpf(subdev);
        struct v4l2_mbus_framefmt *format;
 
-       format = v4l2_subdev_get_try_format(fh, fse->pad);
+       format = vsp1_entity_get_pad_format(&rwpf->entity, cfg, fse->pad,
+                                           fse->which);
 
        if (fse->index || fse->code != format->code)
                return -EINVAL;
@@ -72,11 +73,11 @@ int vsp1_rwpf_enum_frame_size(struct v4l2_subdev *subdev,
 }
 
 static struct v4l2_rect *
-vsp1_rwpf_get_crop(struct vsp1_rwpf *rwpf, struct v4l2_subdev_fh *fh, u32 which)
+vsp1_rwpf_get_crop(struct vsp1_rwpf *rwpf, struct v4l2_subdev_pad_config *cfg, u32 which)
 {
        switch (which) {
        case V4L2_SUBDEV_FORMAT_TRY:
-               return v4l2_subdev_get_try_crop(fh, RWPF_PAD_SINK);
+               return v4l2_subdev_get_try_crop(&rwpf->entity.subdev, cfg, RWPF_PAD_SINK);
        case V4L2_SUBDEV_FORMAT_ACTIVE:
                return &rwpf->crop;
        default:
@@ -84,18 +85,18 @@ vsp1_rwpf_get_crop(struct vsp1_rwpf *rwpf, struct v4l2_subdev_fh *fh, u32 which)
        }
 }
 
-int vsp1_rwpf_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
+int vsp1_rwpf_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg,
                         struct v4l2_subdev_format *fmt)
 {
        struct vsp1_rwpf *rwpf = to_rwpf(subdev);
 
-       fmt->format = *vsp1_entity_get_pad_format(&rwpf->entity, fh, fmt->pad,
+       fmt->format = *vsp1_entity_get_pad_format(&rwpf->entity, cfg, fmt->pad,
                                                  fmt->which);
 
        return 0;
 }
 
-int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
+int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg,
                         struct v4l2_subdev_format *fmt)
 {
        struct vsp1_rwpf *rwpf = to_rwpf(subdev);
@@ -107,7 +108,7 @@ int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
            fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
                fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
 
-       format = vsp1_entity_get_pad_format(&rwpf->entity, fh, fmt->pad,
+       format = vsp1_entity_get_pad_format(&rwpf->entity, cfg, fmt->pad,
                                            fmt->which);
 
        if (fmt->pad == RWPF_PAD_SOURCE) {
@@ -130,14 +131,14 @@ int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
        fmt->format = *format;
 
        /* Update the sink crop rectangle. */
-       crop = vsp1_rwpf_get_crop(rwpf, fh, fmt->which);
+       crop = vsp1_rwpf_get_crop(rwpf, cfg, fmt->which);
        crop->left = 0;
        crop->top = 0;
        crop->width = fmt->format.width;
        crop->height = fmt->format.height;
 
        /* Propagate the format to the source pad. */
-       format = vsp1_entity_get_pad_format(&rwpf->entity, fh, RWPF_PAD_SOURCE,
+       format = vsp1_entity_get_pad_format(&rwpf->entity, cfg, RWPF_PAD_SOURCE,
                                            fmt->which);
        *format = fmt->format;
 
@@ -145,7 +146,7 @@ int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
 }
 
 int vsp1_rwpf_get_selection(struct v4l2_subdev *subdev,
-                           struct v4l2_subdev_fh *fh,
+                           struct v4l2_subdev_pad_config *cfg,
                            struct v4l2_subdev_selection *sel)
 {
        struct vsp1_rwpf *rwpf = to_rwpf(subdev);
@@ -157,11 +158,11 @@ int vsp1_rwpf_get_selection(struct v4l2_subdev *subdev,
 
        switch (sel->target) {
        case V4L2_SEL_TGT_CROP:
-               sel->r = *vsp1_rwpf_get_crop(rwpf, fh, sel->which);
+               sel->r = *vsp1_rwpf_get_crop(rwpf, cfg, sel->which);
                break;
 
        case V4L2_SEL_TGT_CROP_BOUNDS:
-               format = vsp1_entity_get_pad_format(&rwpf->entity, fh,
+               format = vsp1_entity_get_pad_format(&rwpf->entity, cfg,
                                                    RWPF_PAD_SINK, sel->which);
                sel->r.left = 0;
                sel->r.top = 0;
@@ -177,7 +178,7 @@ int vsp1_rwpf_get_selection(struct v4l2_subdev *subdev,
 }
 
 int vsp1_rwpf_set_selection(struct v4l2_subdev *subdev,
-                           struct v4l2_subdev_fh *fh,
+                           struct v4l2_subdev_pad_config *cfg,
                            struct v4l2_subdev_selection *sel)
 {
        struct vsp1_rwpf *rwpf = to_rwpf(subdev);
@@ -194,7 +195,7 @@ int vsp1_rwpf_set_selection(struct v4l2_subdev *subdev,
        /* Make sure the crop rectangle is entirely contained in the image. The
         * WPF top and left offsets are limited to 255.
         */
-       format = vsp1_entity_get_pad_format(&rwpf->entity, fh, RWPF_PAD_SINK,
+       format = vsp1_entity_get_pad_format(&rwpf->entity, cfg, RWPF_PAD_SINK,
                                            sel->which);
        sel->r.left = min_t(unsigned int, sel->r.left, format->width - 2);
        sel->r.top = min_t(unsigned int, sel->r.top, format->height - 2);
@@ -207,11 +208,11 @@ int vsp1_rwpf_set_selection(struct v4l2_subdev *subdev,
        sel->r.height = min_t(unsigned int, sel->r.height,
                              format->height - sel->r.top);
 
-       crop = vsp1_rwpf_get_crop(rwpf, fh, sel->which);
+       crop = vsp1_rwpf_get_crop(rwpf, cfg, sel->which);
        *crop = sel->r;
 
        /* Propagate the format to the source pad. */
-       format = vsp1_entity_get_pad_format(&rwpf->entity, fh, RWPF_PAD_SOURCE,
+       format = vsp1_entity_get_pad_format(&rwpf->entity, cfg, RWPF_PAD_SOURCE,
                                            sel->which);
        format->width = crop->width;
        format->height = crop->height;
index 2cf1f13d3bf9c3fefaa42fad8803c54b949cf71a..f452dce1a931d6e082e5fe302afa3c3067a1c1be 100644 (file)
@@ -51,20 +51,20 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index);
 struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index);
 
 int vsp1_rwpf_enum_mbus_code(struct v4l2_subdev *subdev,
-                            struct v4l2_subdev_fh *fh,
+                            struct v4l2_subdev_pad_config *cfg,
                             struct v4l2_subdev_mbus_code_enum *code);
 int vsp1_rwpf_enum_frame_size(struct v4l2_subdev *subdev,
-                             struct v4l2_subdev_fh *fh,
+                             struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_frame_size_enum *fse);
-int vsp1_rwpf_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
+int vsp1_rwpf_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg,
                         struct v4l2_subdev_format *fmt);
-int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
+int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg,
                         struct v4l2_subdev_format *fmt);
 int vsp1_rwpf_get_selection(struct v4l2_subdev *subdev,
-                           struct v4l2_subdev_fh *fh,
+                           struct v4l2_subdev_pad_config *cfg,
                            struct v4l2_subdev_selection *sel);
 int vsp1_rwpf_set_selection(struct v4l2_subdev *subdev,
-                           struct v4l2_subdev_fh *fh,
+                           struct v4l2_subdev_pad_config *cfg,
                            struct v4l2_subdev_selection *sel);
 
 #endif /* __VSP1_RWPF_H__ */
index 1129494c7cfc774541b5fe8d4ec7385e0bcc22de..6310acab60e79b3d97978950ce97c3155fed2b29 100644 (file)
@@ -166,13 +166,14 @@ static int sru_s_stream(struct v4l2_subdev *subdev, int enable)
  */
 
 static int sru_enum_mbus_code(struct v4l2_subdev *subdev,
-                             struct v4l2_subdev_fh *fh,
+                             struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_mbus_code_enum *code)
 {
        static const unsigned int codes[] = {
                MEDIA_BUS_FMT_ARGB8888_1X32,
                MEDIA_BUS_FMT_AYUV8_1X32,
        };
+       struct vsp1_sru *sru = to_sru(subdev);
        struct v4l2_mbus_framefmt *format;
 
        if (code->pad == SRU_PAD_SINK) {
@@ -187,7 +188,8 @@ static int sru_enum_mbus_code(struct v4l2_subdev *subdev,
                if (code->index)
                        return -EINVAL;
 
-               format = v4l2_subdev_get_try_format(fh, SRU_PAD_SINK);
+               format = vsp1_entity_get_pad_format(&sru->entity, cfg,
+                                                   SRU_PAD_SINK, code->which);
                code->code = format->code;
        }
 
@@ -195,12 +197,14 @@ static int sru_enum_mbus_code(struct v4l2_subdev *subdev,
 }
 
 static int sru_enum_frame_size(struct v4l2_subdev *subdev,
-                              struct v4l2_subdev_fh *fh,
+                              struct v4l2_subdev_pad_config *cfg,
                               struct v4l2_subdev_frame_size_enum *fse)
 {
+       struct vsp1_sru *sru = to_sru(subdev);
        struct v4l2_mbus_framefmt *format;
 
-       format = v4l2_subdev_get_try_format(fh, SRU_PAD_SINK);
+       format = vsp1_entity_get_pad_format(&sru->entity, cfg,
+                                           SRU_PAD_SINK, fse->which);
 
        if (fse->index || fse->code != format->code)
                return -EINVAL;
@@ -226,18 +230,18 @@ static int sru_enum_frame_size(struct v4l2_subdev *subdev,
        return 0;
 }
 
-static int sru_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
+static int sru_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg,
                          struct v4l2_subdev_format *fmt)
 {
        struct vsp1_sru *sru = to_sru(subdev);
 
-       fmt->format = *vsp1_entity_get_pad_format(&sru->entity, fh, fmt->pad,
+       fmt->format = *vsp1_entity_get_pad_format(&sru->entity, cfg, fmt->pad,
                                                  fmt->which);
 
        return 0;
 }
 
-static void sru_try_format(struct vsp1_sru *sru, struct v4l2_subdev_fh *fh,
+static void sru_try_format(struct vsp1_sru *sru, struct v4l2_subdev_pad_config *cfg,
                           unsigned int pad, struct v4l2_mbus_framefmt *fmt,
                           enum v4l2_subdev_format_whence which)
 {
@@ -258,7 +262,7 @@ static void sru_try_format(struct vsp1_sru *sru, struct v4l2_subdev_fh *fh,
 
        case SRU_PAD_SOURCE:
                /* The SRU can't perform format conversion. */
-               format = vsp1_entity_get_pad_format(&sru->entity, fh,
+               format = vsp1_entity_get_pad_format(&sru->entity, cfg,
                                                    SRU_PAD_SINK, which);
                fmt->code = format->code;
 
@@ -288,25 +292,25 @@ static void sru_try_format(struct vsp1_sru *sru, struct v4l2_subdev_fh *fh,
        fmt->colorspace = V4L2_COLORSPACE_SRGB;
 }
 
-static int sru_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
+static int sru_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg,
                          struct v4l2_subdev_format *fmt)
 {
        struct vsp1_sru *sru = to_sru(subdev);
        struct v4l2_mbus_framefmt *format;
 
-       sru_try_format(sru, fh, fmt->pad, &fmt->format, fmt->which);
+       sru_try_format(sru, cfg, fmt->pad, &fmt->format, fmt->which);
 
-       format = vsp1_entity_get_pad_format(&sru->entity, fh, fmt->pad,
+       format = vsp1_entity_get_pad_format(&sru->entity, cfg, fmt->pad,
                                            fmt->which);
        *format = fmt->format;
 
        if (fmt->pad == SRU_PAD_SINK) {
                /* Propagate the format to the source pad. */
-               format = vsp1_entity_get_pad_format(&sru->entity, fh,
+               format = vsp1_entity_get_pad_format(&sru->entity, cfg,
                                                    SRU_PAD_SOURCE, fmt->which);
                *format = fmt->format;
 
-               sru_try_format(sru, fh, SRU_PAD_SOURCE, format, fmt->which);
+               sru_try_format(sru, cfg, SRU_PAD_SOURCE, format, fmt->which);
        }
 
        return 0;
index a4afec13380009d8b4383abbe7ee232cf4d48166..ccc8243e3493d7728167ade8486e32ebe3e48506 100644 (file)
@@ -169,13 +169,14 @@ static int uds_s_stream(struct v4l2_subdev *subdev, int enable)
  */
 
 static int uds_enum_mbus_code(struct v4l2_subdev *subdev,
-                             struct v4l2_subdev_fh *fh,
+                             struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_mbus_code_enum *code)
 {
        static const unsigned int codes[] = {
                MEDIA_BUS_FMT_ARGB8888_1X32,
                MEDIA_BUS_FMT_AYUV8_1X32,
        };
+       struct vsp1_uds *uds = to_uds(subdev);
 
        if (code->pad == UDS_PAD_SINK) {
                if (code->index >= ARRAY_SIZE(codes))
@@ -191,7 +192,8 @@ static int uds_enum_mbus_code(struct v4l2_subdev *subdev,
                if (code->index)
                        return -EINVAL;
 
-               format = v4l2_subdev_get_try_format(fh, UDS_PAD_SINK);
+               format = vsp1_entity_get_pad_format(&uds->entity, cfg,
+                                                   UDS_PAD_SINK, code->which);
                code->code = format->code;
        }
 
@@ -199,12 +201,14 @@ static int uds_enum_mbus_code(struct v4l2_subdev *subdev,
 }
 
 static int uds_enum_frame_size(struct v4l2_subdev *subdev,
-                              struct v4l2_subdev_fh *fh,
+                              struct v4l2_subdev_pad_config *cfg,
                               struct v4l2_subdev_frame_size_enum *fse)
 {
+       struct vsp1_uds *uds = to_uds(subdev);
        struct v4l2_mbus_framefmt *format;
 
-       format = v4l2_subdev_get_try_format(fh, UDS_PAD_SINK);
+       format = vsp1_entity_get_pad_format(&uds->entity, cfg,
+                                           UDS_PAD_SINK, fse->which);
 
        if (fse->index || fse->code != format->code)
                return -EINVAL;
@@ -224,18 +228,18 @@ static int uds_enum_frame_size(struct v4l2_subdev *subdev,
        return 0;
 }
 
-static int uds_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
+static int uds_get_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg,
                          struct v4l2_subdev_format *fmt)
 {
        struct vsp1_uds *uds = to_uds(subdev);
 
-       fmt->format = *vsp1_entity_get_pad_format(&uds->entity, fh, fmt->pad,
+       fmt->format = *vsp1_entity_get_pad_format(&uds->entity, cfg, fmt->pad,
                                                  fmt->which);
 
        return 0;
 }
 
-static void uds_try_format(struct vsp1_uds *uds, struct v4l2_subdev_fh *fh,
+static void uds_try_format(struct vsp1_uds *uds, struct v4l2_subdev_pad_config *cfg,
                           unsigned int pad, struct v4l2_mbus_framefmt *fmt,
                           enum v4l2_subdev_format_whence which)
 {
@@ -256,7 +260,7 @@ static void uds_try_format(struct vsp1_uds *uds, struct v4l2_subdev_fh *fh,
 
        case UDS_PAD_SOURCE:
                /* The UDS scales but can't perform format conversion. */
-               format = vsp1_entity_get_pad_format(&uds->entity, fh,
+               format = vsp1_entity_get_pad_format(&uds->entity, cfg,
                                                    UDS_PAD_SINK, which);
                fmt->code = format->code;
 
@@ -271,25 +275,25 @@ static void uds_try_format(struct vsp1_uds *uds, struct v4l2_subdev_fh *fh,
        fmt->colorspace = V4L2_COLORSPACE_SRGB;
 }
 
-static int uds_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
+static int uds_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_pad_config *cfg,
                          struct v4l2_subdev_format *fmt)
 {
        struct vsp1_uds *uds = to_uds(subdev);
        struct v4l2_mbus_framefmt *format;
 
-       uds_try_format(uds, fh, fmt->pad, &fmt->format, fmt->which);
+       uds_try_format(uds, cfg, fmt->pad, &fmt->format, fmt->which);
 
-       format = vsp1_entity_get_pad_format(&uds->entity, fh, fmt->pad,
+       format = vsp1_entity_get_pad_format(&uds->entity, cfg, fmt->pad,
                                            fmt->which);
        *format = fmt->format;
 
        if (fmt->pad == UDS_PAD_SINK) {
                /* Propagate the format to the source pad. */
-               format = vsp1_entity_get_pad_format(&uds->entity, fh,
+               format = vsp1_entity_get_pad_format(&uds->entity, cfg,
                                                    UDS_PAD_SOURCE, fmt->which);
                *format = fmt->format;
 
-               uds_try_format(uds, fh, UDS_PAD_SOURCE, format, fmt->which);
+               uds_try_format(uds, cfg, UDS_PAD_SOURCE, format, fmt->which);
        }
 
        return 0;
diff --git a/drivers/media/platform/xilinx/Kconfig b/drivers/media/platform/xilinx/Kconfig
new file mode 100644 (file)
index 0000000..d7324c7
--- /dev/null
@@ -0,0 +1,23 @@
+config VIDEO_XILINX
+       tristate "Xilinx Video IP (EXPERIMENTAL)"
+       depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && OF
+       select VIDEOBUF2_DMA_CONTIG
+       ---help---
+         Driver for Xilinx Video IP Pipelines
+
+if VIDEO_XILINX
+
+config VIDEO_XILINX_TPG
+       tristate "Xilinx Video Test Pattern Generator"
+       depends on VIDEO_XILINX
+       select VIDEO_XILINX_VTC
+       ---help---
+          Driver for the Xilinx Video Test Pattern Generator
+
+config VIDEO_XILINX_VTC
+       tristate "Xilinx Video Timing Controller"
+       depends on VIDEO_XILINX
+       ---help---
+          Driver for the Xilinx Video Timing Controller
+
+endif #VIDEO_XILINX
diff --git a/drivers/media/platform/xilinx/Makefile b/drivers/media/platform/xilinx/Makefile
new file mode 100644 (file)
index 0000000..e8a0f2a
--- /dev/null
@@ -0,0 +1,5 @@
+xilinx-video-objs += xilinx-dma.o xilinx-vip.o xilinx-vipp.o
+
+obj-$(CONFIG_VIDEO_XILINX) += xilinx-video.o
+obj-$(CONFIG_VIDEO_XILINX_TPG) += xilinx-tpg.o
+obj-$(CONFIG_VIDEO_XILINX_VTC) += xilinx-vtc.o
diff --git a/drivers/media/platform/xilinx/xilinx-dma.c b/drivers/media/platform/xilinx/xilinx-dma.c
new file mode 100644 (file)
index 0000000..efde88a
--- /dev/null
@@ -0,0 +1,766 @@
+/*
+ * Xilinx Video DMA
+ *
+ * Copyright (C) 2013-2015 Ideas on Board
+ * Copyright (C) 2013-2015 Xilinx, Inc.
+ *
+ * Contacts: Hyun Kwon <hyun.kwon@xilinx.com>
+ *           Laurent Pinchart <laurent.pinchart@ideasonboard.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/dma/xilinx_dma.h>
+#include <linux/lcm.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+
+#include <media/v4l2-dev.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "xilinx-dma.h"
+#include "xilinx-vip.h"
+#include "xilinx-vipp.h"
+
+#define XVIP_DMA_DEF_FORMAT            V4L2_PIX_FMT_YUYV
+#define XVIP_DMA_DEF_WIDTH             1920
+#define XVIP_DMA_DEF_HEIGHT            1080
+
+/* Minimum and maximum widths are expressed in bytes */
+#define XVIP_DMA_MIN_WIDTH             1U
+#define XVIP_DMA_MAX_WIDTH             65535U
+#define XVIP_DMA_MIN_HEIGHT            1U
+#define XVIP_DMA_MAX_HEIGHT            8191U
+
+/* -----------------------------------------------------------------------------
+ * Helper functions
+ */
+
+static struct v4l2_subdev *
+xvip_dma_remote_subdev(struct media_pad *local, u32 *pad)
+{
+       struct media_pad *remote;
+
+       remote = media_entity_remote_pad(local);
+       if (remote == NULL ||
+           media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+               return NULL;
+
+       if (pad)
+               *pad = remote->index;
+
+       return media_entity_to_v4l2_subdev(remote->entity);
+}
+
+static int xvip_dma_verify_format(struct xvip_dma *dma)
+{
+       struct v4l2_subdev_format fmt;
+       struct v4l2_subdev *subdev;
+       int ret;
+
+       subdev = xvip_dma_remote_subdev(&dma->pad, &fmt.pad);
+       if (subdev == NULL)
+               return -EPIPE;
+
+       fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+       ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
+       if (ret < 0)
+               return ret == -ENOIOCTLCMD ? -EINVAL : ret;
+
+       if (dma->fmtinfo->code != fmt.format.code ||
+           dma->format.height != fmt.format.height ||
+           dma->format.width != fmt.format.width ||
+           dma->format.colorspace != fmt.format.colorspace)
+               return -EINVAL;
+
+       return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Pipeline Stream Management
+ */
+
+/**
+ * xvip_pipeline_start_stop - Start ot stop streaming on a pipeline
+ * @pipe: The pipeline
+ * @start: Start (when true) or stop (when false) the pipeline
+ *
+ * Walk the entities chain starting at the pipeline output video node and start
+ * or stop all of them.
+ *
+ * Return: 0 if successful, or the return value of the failed video::s_stream
+ * operation otherwise.
+ */
+static int xvip_pipeline_start_stop(struct xvip_pipeline *pipe, bool start)
+{
+       struct xvip_dma *dma = pipe->output;
+       struct media_entity *entity;
+       struct media_pad *pad;
+       struct v4l2_subdev *subdev;
+       int ret;
+
+       entity = &dma->video.entity;
+       while (1) {
+               pad = &entity->pads[0];
+               if (!(pad->flags & MEDIA_PAD_FL_SINK))
+                       break;
+
+               pad = media_entity_remote_pad(pad);
+               if (pad == NULL ||
+                   media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+                       break;
+
+               entity = pad->entity;
+               subdev = media_entity_to_v4l2_subdev(entity);
+
+               ret = v4l2_subdev_call(subdev, video, s_stream, start);
+               if (start && ret < 0 && ret != -ENOIOCTLCMD)
+                       return ret;
+       }
+
+       return 0;
+}
+
+/**
+ * xvip_pipeline_set_stream - Enable/disable streaming on a pipeline
+ * @pipe: The pipeline
+ * @on: Turn the stream on when true or off when false
+ *
+ * The pipeline is shared between all DMA engines connect at its input and
+ * output. While the stream state of DMA engines can be controlled
+ * independently, pipelines have a shared stream state that enable or disable
+ * all entities in the pipeline. For this reason the pipeline uses a streaming
+ * counter that tracks the number of DMA engines that have requested the stream
+ * to be enabled.
+ *
+ * When called with the @on argument set to true, this function will increment
+ * the pipeline streaming count. If the streaming count reaches the number of
+ * DMA engines in the pipeline it will enable all entities that belong to the
+ * pipeline.
+ *
+ * Similarly, when called with the @on argument set to false, this function will
+ * decrement the pipeline streaming count and disable all entities in the
+ * pipeline when the streaming count reaches zero.
+ *
+ * Return: 0 if successful, or the return value of the failed video::s_stream
+ * operation otherwise. Stopping the pipeline never fails. The pipeline state is
+ * not updated when the operation fails.
+ */
+static int xvip_pipeline_set_stream(struct xvip_pipeline *pipe, bool on)
+{
+       int ret = 0;
+
+       mutex_lock(&pipe->lock);
+
+       if (on) {
+               if (pipe->stream_count == pipe->num_dmas - 1) {
+                       ret = xvip_pipeline_start_stop(pipe, true);
+                       if (ret < 0)
+                               goto done;
+               }
+               pipe->stream_count++;
+       } else {
+               if (--pipe->stream_count == 0)
+                       xvip_pipeline_start_stop(pipe, false);
+       }
+
+done:
+       mutex_unlock(&pipe->lock);
+       return ret;
+}
+
+static int xvip_pipeline_validate(struct xvip_pipeline *pipe,
+                                 struct xvip_dma *start)
+{
+       struct media_entity_graph graph;
+       struct media_entity *entity = &start->video.entity;
+       struct media_device *mdev = entity->parent;
+       unsigned int num_inputs = 0;
+       unsigned int num_outputs = 0;
+
+       mutex_lock(&mdev->graph_mutex);
+
+       /* Walk the graph to locate the video nodes. */
+       media_entity_graph_walk_start(&graph, entity);
+
+       while ((entity = media_entity_graph_walk_next(&graph))) {
+               struct xvip_dma *dma;
+
+               if (entity->type != MEDIA_ENT_T_DEVNODE_V4L)
+                       continue;
+
+               dma = to_xvip_dma(media_entity_to_video_device(entity));
+
+               if (dma->pad.flags & MEDIA_PAD_FL_SINK) {
+                       pipe->output = dma;
+                       num_outputs++;
+               } else {
+                       num_inputs++;
+               }
+       }
+
+       mutex_unlock(&mdev->graph_mutex);
+
+       /* We need exactly one output and zero or one input. */
+       if (num_outputs != 1 || num_inputs > 1)
+               return -EPIPE;
+
+       pipe->num_dmas = num_inputs + num_outputs;
+
+       return 0;
+}
+
+static void __xvip_pipeline_cleanup(struct xvip_pipeline *pipe)
+{
+       pipe->num_dmas = 0;
+       pipe->output = NULL;
+}
+
+/**
+ * xvip_pipeline_cleanup - Cleanup the pipeline after streaming
+ * @pipe: the pipeline
+ *
+ * Decrease the pipeline use count and clean it up if we were the last user.
+ */
+static void xvip_pipeline_cleanup(struct xvip_pipeline *pipe)
+{
+       mutex_lock(&pipe->lock);
+
+       /* If we're the last user clean up the pipeline. */
+       if (--pipe->use_count == 0)
+               __xvip_pipeline_cleanup(pipe);
+
+       mutex_unlock(&pipe->lock);
+}
+
+/**
+ * xvip_pipeline_prepare - Prepare the pipeline for streaming
+ * @pipe: the pipeline
+ * @dma: DMA engine at one end of the pipeline
+ *
+ * Validate the pipeline if no user exists yet, otherwise just increase the use
+ * count.
+ *
+ * Return: 0 if successful or -EPIPE if the pipeline is not valid.
+ */
+static int xvip_pipeline_prepare(struct xvip_pipeline *pipe,
+                                struct xvip_dma *dma)
+{
+       int ret;
+
+       mutex_lock(&pipe->lock);
+
+       /* If we're the first user validate and initialize the pipeline. */
+       if (pipe->use_count == 0) {
+               ret = xvip_pipeline_validate(pipe, dma);
+               if (ret < 0) {
+                       __xvip_pipeline_cleanup(pipe);
+                       goto done;
+               }
+       }
+
+       pipe->use_count++;
+       ret = 0;
+
+done:
+       mutex_unlock(&pipe->lock);
+       return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * videobuf2 queue operations
+ */
+
+/**
+ * struct xvip_dma_buffer - Video DMA buffer
+ * @buf: vb2 buffer base object
+ * @queue: buffer list entry in the DMA engine queued buffers list
+ * @dma: DMA channel that uses the buffer
+ */
+struct xvip_dma_buffer {
+       struct vb2_buffer buf;
+       struct list_head queue;
+       struct xvip_dma *dma;
+};
+
+#define to_xvip_dma_buffer(vb) container_of(vb, struct xvip_dma_buffer, buf)
+
+static void xvip_dma_complete(void *param)
+{
+       struct xvip_dma_buffer *buf = param;
+       struct xvip_dma *dma = buf->dma;
+
+       spin_lock(&dma->queued_lock);
+       list_del(&buf->queue);
+       spin_unlock(&dma->queued_lock);
+
+       buf->buf.v4l2_buf.field = V4L2_FIELD_NONE;
+       buf->buf.v4l2_buf.sequence = dma->sequence++;
+       v4l2_get_timestamp(&buf->buf.v4l2_buf.timestamp);
+       vb2_set_plane_payload(&buf->buf, 0, dma->format.sizeimage);
+       vb2_buffer_done(&buf->buf, VB2_BUF_STATE_DONE);
+}
+
+static int
+xvip_dma_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+                    unsigned int *nbuffers, unsigned int *nplanes,
+                    unsigned int sizes[], void *alloc_ctxs[])
+{
+       struct xvip_dma *dma = vb2_get_drv_priv(vq);
+
+       /* Make sure the image size is large enough. */
+       if (fmt && fmt->fmt.pix.sizeimage < dma->format.sizeimage)
+               return -EINVAL;
+
+       *nplanes = 1;
+
+       sizes[0] = fmt ? fmt->fmt.pix.sizeimage : dma->format.sizeimage;
+       alloc_ctxs[0] = dma->alloc_ctx;
+
+       return 0;
+}
+
+static int xvip_dma_buffer_prepare(struct vb2_buffer *vb)
+{
+       struct xvip_dma *dma = vb2_get_drv_priv(vb->vb2_queue);
+       struct xvip_dma_buffer *buf = to_xvip_dma_buffer(vb);
+
+       buf->dma = dma;
+
+       return 0;
+}
+
+static void xvip_dma_buffer_queue(struct vb2_buffer *vb)
+{
+       struct xvip_dma *dma = vb2_get_drv_priv(vb->vb2_queue);
+       struct xvip_dma_buffer *buf = to_xvip_dma_buffer(vb);
+       struct dma_async_tx_descriptor *desc;
+       dma_addr_t addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+       u32 flags;
+
+       if (dma->queue.type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK;
+               dma->xt.dir = DMA_DEV_TO_MEM;
+               dma->xt.src_sgl = false;
+               dma->xt.dst_sgl = true;
+               dma->xt.dst_start = addr;
+       } else {
+               flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK;
+               dma->xt.dir = DMA_MEM_TO_DEV;
+               dma->xt.src_sgl = true;
+               dma->xt.dst_sgl = false;
+               dma->xt.src_start = addr;
+       }
+
+       dma->xt.frame_size = 1;
+       dma->sgl[0].size = dma->format.width * dma->fmtinfo->bpp;
+       dma->sgl[0].icg = dma->format.bytesperline - dma->sgl[0].size;
+       dma->xt.numf = dma->format.height;
+
+       desc = dmaengine_prep_interleaved_dma(dma->dma, &dma->xt, flags);
+       if (!desc) {
+               dev_err(dma->xdev->dev, "Failed to prepare DMA transfer\n");
+               vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
+               return;
+       }
+       desc->callback = xvip_dma_complete;
+       desc->callback_param = buf;
+
+       spin_lock_irq(&dma->queued_lock);
+       list_add_tail(&buf->queue, &dma->queued_bufs);
+       spin_unlock_irq(&dma->queued_lock);
+
+       dmaengine_submit(desc);
+
+       if (vb2_is_streaming(&dma->queue))
+               dma_async_issue_pending(dma->dma);
+}
+
+static int xvip_dma_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+       struct xvip_dma *dma = vb2_get_drv_priv(vq);
+       struct xvip_dma_buffer *buf, *nbuf;
+       struct xvip_pipeline *pipe;
+       int ret;
+
+       dma->sequence = 0;
+
+       /*
+        * Start streaming on the pipeline. No link touching an entity in the
+        * pipeline can be activated or deactivated once streaming is started.
+        *
+        * Use the pipeline object embedded in the first DMA object that starts
+        * streaming.
+        */
+       pipe = dma->video.entity.pipe
+            ? to_xvip_pipeline(&dma->video.entity) : &dma->pipe;
+
+       ret = media_entity_pipeline_start(&dma->video.entity, &pipe->pipe);
+       if (ret < 0)
+               goto error;
+
+       /* Verify that the configured format matches the output of the
+        * connected subdev.
+        */
+       ret = xvip_dma_verify_format(dma);
+       if (ret < 0)
+               goto error_stop;
+
+       ret = xvip_pipeline_prepare(pipe, dma);
+       if (ret < 0)
+               goto error_stop;
+
+       /* Start the DMA engine. This must be done before starting the blocks
+        * in the pipeline to avoid DMA synchronization issues.
+        */
+       dma_async_issue_pending(dma->dma);
+
+       /* Start the pipeline. */
+       xvip_pipeline_set_stream(pipe, true);
+
+       return 0;
+
+error_stop:
+       media_entity_pipeline_stop(&dma->video.entity);
+
+error:
+       /* Give back all queued buffers to videobuf2. */
+       spin_lock_irq(&dma->queued_lock);
+       list_for_each_entry_safe(buf, nbuf, &dma->queued_bufs, queue) {
+               vb2_buffer_done(&buf->buf, VB2_BUF_STATE_QUEUED);
+               list_del(&buf->queue);
+       }
+       spin_unlock_irq(&dma->queued_lock);
+
+       return ret;
+}
+
+static void xvip_dma_stop_streaming(struct vb2_queue *vq)
+{
+       struct xvip_dma *dma = vb2_get_drv_priv(vq);
+       struct xvip_pipeline *pipe = to_xvip_pipeline(&dma->video.entity);
+       struct xvip_dma_buffer *buf, *nbuf;
+
+       /* Stop the pipeline. */
+       xvip_pipeline_set_stream(pipe, false);
+
+       /* Stop and reset the DMA engine. */
+       dmaengine_terminate_all(dma->dma);
+
+       /* Cleanup the pipeline and mark it as being stopped. */
+       xvip_pipeline_cleanup(pipe);
+       media_entity_pipeline_stop(&dma->video.entity);
+
+       /* Give back all queued buffers to videobuf2. */
+       spin_lock_irq(&dma->queued_lock);
+       list_for_each_entry_safe(buf, nbuf, &dma->queued_bufs, queue) {
+               vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
+               list_del(&buf->queue);
+       }
+       spin_unlock_irq(&dma->queued_lock);
+}
+
+static struct vb2_ops xvip_dma_queue_qops = {
+       .queue_setup = xvip_dma_queue_setup,
+       .buf_prepare = xvip_dma_buffer_prepare,
+       .buf_queue = xvip_dma_buffer_queue,
+       .wait_prepare = vb2_ops_wait_prepare,
+       .wait_finish = vb2_ops_wait_finish,
+       .start_streaming = xvip_dma_start_streaming,
+       .stop_streaming = xvip_dma_stop_streaming,
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 ioctls
+ */
+
+static int
+xvip_dma_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
+{
+       struct v4l2_fh *vfh = file->private_data;
+       struct xvip_dma *dma = to_xvip_dma(vfh->vdev);
+
+       cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING
+                         | dma->xdev->v4l2_caps;
+
+       if (dma->queue.type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+       else
+               cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
+
+       strlcpy(cap->driver, "xilinx-vipp", sizeof(cap->driver));
+       strlcpy(cap->card, dma->video.name, sizeof(cap->card));
+       snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s:%u",
+                dma->xdev->dev->of_node->name, dma->port);
+
+       return 0;
+}
+
+/* FIXME: without this callback function, some applications are not configured
+ * with correct formats, and it results in frames in wrong format. Whether this
+ * callback needs to be required is not clearly defined, so it should be
+ * clarified through the mailing list.
+ */
+static int
+xvip_dma_enum_format(struct file *file, void *fh, struct v4l2_fmtdesc *f)
+{
+       struct v4l2_fh *vfh = file->private_data;
+       struct xvip_dma *dma = to_xvip_dma(vfh->vdev);
+
+       if (f->index > 0)
+               return -EINVAL;
+
+       f->pixelformat = dma->format.pixelformat;
+       strlcpy(f->description, dma->fmtinfo->description,
+               sizeof(f->description));
+
+       return 0;
+}
+
+static int
+xvip_dma_get_format(struct file *file, void *fh, struct v4l2_format *format)
+{
+       struct v4l2_fh *vfh = file->private_data;
+       struct xvip_dma *dma = to_xvip_dma(vfh->vdev);
+
+       format->fmt.pix = dma->format;
+
+       return 0;
+}
+
+static void
+__xvip_dma_try_format(struct xvip_dma *dma, struct v4l2_pix_format *pix,
+                     const struct xvip_video_format **fmtinfo)
+{
+       const struct xvip_video_format *info;
+       unsigned int min_width;
+       unsigned int max_width;
+       unsigned int min_bpl;
+       unsigned int max_bpl;
+       unsigned int width;
+       unsigned int align;
+       unsigned int bpl;
+
+       /* Retrieve format information and select the default format if the
+        * requested format isn't supported.
+        */
+       info = xvip_get_format_by_fourcc(pix->pixelformat);
+       if (IS_ERR(info))
+               info = xvip_get_format_by_fourcc(XVIP_DMA_DEF_FORMAT);
+
+       pix->pixelformat = info->fourcc;
+       pix->field = V4L2_FIELD_NONE;
+
+       /* The transfer alignment requirements are expressed in bytes. Compute
+        * the minimum and maximum values, clamp the requested width and convert
+        * it back to pixels.
+        */
+       align = lcm(dma->align, info->bpp);
+       min_width = roundup(XVIP_DMA_MIN_WIDTH, align);
+       max_width = rounddown(XVIP_DMA_MAX_WIDTH, align);
+       width = rounddown(pix->width * info->bpp, align);
+
+       pix->width = clamp(width, min_width, max_width) / info->bpp;
+       pix->height = clamp(pix->height, XVIP_DMA_MIN_HEIGHT,
+                           XVIP_DMA_MAX_HEIGHT);
+
+       /* Clamp the requested bytes per line value. If the maximum bytes per
+        * line value is zero, the module doesn't support user configurable line
+        * sizes. Override the requested value with the minimum in that case.
+        */
+       min_bpl = pix->width * info->bpp;
+       max_bpl = rounddown(XVIP_DMA_MAX_WIDTH, dma->align);
+       bpl = rounddown(pix->bytesperline, dma->align);
+
+       pix->bytesperline = clamp(bpl, min_bpl, max_bpl);
+       pix->sizeimage = pix->bytesperline * pix->height;
+
+       if (fmtinfo)
+               *fmtinfo = info;
+}
+
+static int
+xvip_dma_try_format(struct file *file, void *fh, struct v4l2_format *format)
+{
+       struct v4l2_fh *vfh = file->private_data;
+       struct xvip_dma *dma = to_xvip_dma(vfh->vdev);
+
+       __xvip_dma_try_format(dma, &format->fmt.pix, NULL);
+       return 0;
+}
+
+static int
+xvip_dma_set_format(struct file *file, void *fh, struct v4l2_format *format)
+{
+       struct v4l2_fh *vfh = file->private_data;
+       struct xvip_dma *dma = to_xvip_dma(vfh->vdev);
+       const struct xvip_video_format *info;
+
+       __xvip_dma_try_format(dma, &format->fmt.pix, &info);
+
+       if (vb2_is_busy(&dma->queue))
+               return -EBUSY;
+
+       dma->format = format->fmt.pix;
+       dma->fmtinfo = info;
+
+       return 0;
+}
+
+static const struct v4l2_ioctl_ops xvip_dma_ioctl_ops = {
+       .vidioc_querycap                = xvip_dma_querycap,
+       .vidioc_enum_fmt_vid_cap        = xvip_dma_enum_format,
+       .vidioc_g_fmt_vid_cap           = xvip_dma_get_format,
+       .vidioc_g_fmt_vid_out           = xvip_dma_get_format,
+       .vidioc_s_fmt_vid_cap           = xvip_dma_set_format,
+       .vidioc_s_fmt_vid_out           = xvip_dma_set_format,
+       .vidioc_try_fmt_vid_cap         = xvip_dma_try_format,
+       .vidioc_try_fmt_vid_out         = xvip_dma_try_format,
+       .vidioc_reqbufs                 = vb2_ioctl_reqbufs,
+       .vidioc_querybuf                = vb2_ioctl_querybuf,
+       .vidioc_qbuf                    = vb2_ioctl_qbuf,
+       .vidioc_dqbuf                   = vb2_ioctl_dqbuf,
+       .vidioc_create_bufs             = vb2_ioctl_create_bufs,
+       .vidioc_expbuf                  = vb2_ioctl_expbuf,
+       .vidioc_streamon                = vb2_ioctl_streamon,
+       .vidioc_streamoff               = vb2_ioctl_streamoff,
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 file operations
+ */
+
+static const struct v4l2_file_operations xvip_dma_fops = {
+       .owner          = THIS_MODULE,
+       .unlocked_ioctl = video_ioctl2,
+       .open           = v4l2_fh_open,
+       .release        = vb2_fop_release,
+       .poll           = vb2_fop_poll,
+       .mmap           = vb2_fop_mmap,
+};
+
+/* -----------------------------------------------------------------------------
+ * Xilinx Video DMA Core
+ */
+
+int xvip_dma_init(struct xvip_composite_device *xdev, struct xvip_dma *dma,
+                 enum v4l2_buf_type type, unsigned int port)
+{
+       char name[14];
+       int ret;
+
+       dma->xdev = xdev;
+       dma->port = port;
+       mutex_init(&dma->lock);
+       mutex_init(&dma->pipe.lock);
+       INIT_LIST_HEAD(&dma->queued_bufs);
+       spin_lock_init(&dma->queued_lock);
+
+       dma->fmtinfo = xvip_get_format_by_fourcc(XVIP_DMA_DEF_FORMAT);
+       dma->format.pixelformat = dma->fmtinfo->fourcc;
+       dma->format.colorspace = V4L2_COLORSPACE_SRGB;
+       dma->format.field = V4L2_FIELD_NONE;
+       dma->format.width = XVIP_DMA_DEF_WIDTH;
+       dma->format.height = XVIP_DMA_DEF_HEIGHT;
+       dma->format.bytesperline = dma->format.width * dma->fmtinfo->bpp;
+       dma->format.sizeimage = dma->format.bytesperline * dma->format.height;
+
+       /* Initialize the media entity... */
+       dma->pad.flags = type == V4L2_BUF_TYPE_VIDEO_CAPTURE
+                      ? MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE;
+
+       ret = media_entity_init(&dma->video.entity, 1, &dma->pad, 0);
+       if (ret < 0)
+               goto error;
+
+       /* ... and the video node... */
+       dma->video.fops = &xvip_dma_fops;
+       dma->video.v4l2_dev = &xdev->v4l2_dev;
+       dma->video.queue = &dma->queue;
+       snprintf(dma->video.name, sizeof(dma->video.name), "%s %s %u",
+                xdev->dev->of_node->name,
+                type == V4L2_BUF_TYPE_VIDEO_CAPTURE ? "output" : "input",
+                port);
+       dma->video.vfl_type = VFL_TYPE_GRABBER;
+       dma->video.vfl_dir = type == V4L2_BUF_TYPE_VIDEO_CAPTURE
+                          ? VFL_DIR_RX : VFL_DIR_TX;
+       dma->video.release = video_device_release_empty;
+       dma->video.ioctl_ops = &xvip_dma_ioctl_ops;
+       dma->video.lock = &dma->lock;
+
+       video_set_drvdata(&dma->video, dma);
+
+       /* ... and the buffers queue... */
+       dma->alloc_ctx = vb2_dma_contig_init_ctx(dma->xdev->dev);
+       if (IS_ERR(dma->alloc_ctx))
+               goto error;
+
+       /* Don't enable VB2_READ and VB2_WRITE, as using the read() and write()
+        * V4L2 APIs would be inefficient. Testing on the command line with a
+        * 'cat /dev/video?' thus won't be possible, but given that the driver
+        * anyway requires a test tool to setup the pipeline before any video
+        * stream can be started, requiring a specific V4L2 test tool as well
+        * instead of 'cat' isn't really a drawback.
+        */
+       dma->queue.type = type;
+       dma->queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
+       dma->queue.lock = &dma->lock;
+       dma->queue.drv_priv = dma;
+       dma->queue.buf_struct_size = sizeof(struct xvip_dma_buffer);
+       dma->queue.ops = &xvip_dma_queue_qops;
+       dma->queue.mem_ops = &vb2_dma_contig_memops;
+       dma->queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC
+                                  | V4L2_BUF_FLAG_TSTAMP_SRC_EOF;
+       ret = vb2_queue_init(&dma->queue);
+       if (ret < 0) {
+               dev_err(dma->xdev->dev, "failed to initialize VB2 queue\n");
+               goto error;
+       }
+
+       /* ... and the DMA channel. */
+       sprintf(name, "port%u", port);
+       dma->dma = dma_request_slave_channel(dma->xdev->dev, name);
+       if (dma->dma == NULL) {
+               dev_err(dma->xdev->dev, "no VDMA channel found\n");
+               ret = -ENODEV;
+               goto error;
+       }
+
+       dma->align = 1 << dma->dma->device->copy_align;
+
+       ret = video_register_device(&dma->video, VFL_TYPE_GRABBER, -1);
+       if (ret < 0) {
+               dev_err(dma->xdev->dev, "failed to register video device\n");
+               goto error;
+       }
+
+       return 0;
+
+error:
+       xvip_dma_cleanup(dma);
+       return ret;
+}
+
+void xvip_dma_cleanup(struct xvip_dma *dma)
+{
+       if (video_is_registered(&dma->video))
+               video_unregister_device(&dma->video);
+
+       if (dma->dma)
+               dma_release_channel(dma->dma);
+
+       if (!IS_ERR_OR_NULL(dma->alloc_ctx))
+               vb2_dma_contig_cleanup_ctx(dma->alloc_ctx);
+
+       media_entity_cleanup(&dma->video.entity);
+
+       mutex_destroy(&dma->lock);
+       mutex_destroy(&dma->pipe.lock);
+}
diff --git a/drivers/media/platform/xilinx/xilinx-dma.h b/drivers/media/platform/xilinx/xilinx-dma.h
new file mode 100644 (file)
index 0000000..a540111
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Xilinx Video DMA
+ *
+ * Copyright (C) 2013-2015 Ideas on Board
+ * Copyright (C) 2013-2015 Xilinx, Inc.
+ *
+ * Contacts: Hyun Kwon <hyun.kwon@xilinx.com>
+ *           Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __XILINX_VIP_DMA_H__
+#define __XILINX_VIP_DMA_H__
+
+#include <linux/dmaengine.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/videodev2.h>
+
+#include <media/media-entity.h>
+#include <media/v4l2-dev.h>
+#include <media/videobuf2-core.h>
+
+struct dma_chan;
+struct xvip_composite_device;
+struct xvip_video_format;
+
+/**
+ * struct xvip_pipeline - Xilinx Video IP pipeline structure
+ * @pipe: media pipeline
+ * @lock: protects the pipeline @stream_count
+ * @use_count: number of DMA engines using the pipeline
+ * @stream_count: number of DMA engines currently streaming
+ * @num_dmas: number of DMA engines in the pipeline
+ * @output: DMA engine at the output of the pipeline
+ */
+struct xvip_pipeline {
+       struct media_pipeline pipe;
+
+       struct mutex lock;
+       unsigned int use_count;
+       unsigned int stream_count;
+
+       unsigned int num_dmas;
+       struct xvip_dma *output;
+};
+
+static inline struct xvip_pipeline *to_xvip_pipeline(struct media_entity *e)
+{
+       return container_of(e->pipe, struct xvip_pipeline, pipe);
+}
+
+/**
+ * struct xvip_dma - Video DMA channel
+ * @list: list entry in a composite device dmas list
+ * @video: V4L2 video device associated with the DMA channel
+ * @pad: media pad for the video device entity
+ * @xdev: composite device the DMA channel belongs to
+ * @pipe: pipeline belonging to the DMA channel
+ * @port: composite device DT node port number for the DMA channel
+ * @lock: protects the @format, @fmtinfo and @queue fields
+ * @format: active V4L2 pixel format
+ * @fmtinfo: format information corresponding to the active @format
+ * @queue: vb2 buffers queue
+ * @alloc_ctx: allocation context for the vb2 @queue
+ * @sequence: V4L2 buffers sequence number
+ * @queued_bufs: list of queued buffers
+ * @queued_lock: protects the buf_queued list
+ * @dma: DMA engine channel
+ * @align: transfer alignment required by the DMA channel (in bytes)
+ * @xt: dma interleaved template for dma configuration
+ * @sgl: data chunk structure for dma_interleaved_template
+ */
+struct xvip_dma {
+       struct list_head list;
+       struct video_device video;
+       struct media_pad pad;
+
+       struct xvip_composite_device *xdev;
+       struct xvip_pipeline pipe;
+       unsigned int port;
+
+       struct mutex lock;
+       struct v4l2_pix_format format;
+       const struct xvip_video_format *fmtinfo;
+
+       struct vb2_queue queue;
+       void *alloc_ctx;
+       unsigned int sequence;
+
+       struct list_head queued_bufs;
+       spinlock_t queued_lock;
+
+       struct dma_chan *dma;
+       unsigned int align;
+       struct dma_interleaved_template xt;
+       struct data_chunk sgl[1];
+};
+
+#define to_xvip_dma(vdev)      container_of(vdev, struct xvip_dma, video)
+
+int xvip_dma_init(struct xvip_composite_device *xdev, struct xvip_dma *dma,
+                 enum v4l2_buf_type type, unsigned int port);
+void xvip_dma_cleanup(struct xvip_dma *dma);
+
+#endif /* __XILINX_VIP_DMA_H__ */
diff --git a/drivers/media/platform/xilinx/xilinx-tpg.c b/drivers/media/platform/xilinx/xilinx-tpg.c
new file mode 100644 (file)
index 0000000..b5f7d5e
--- /dev/null
@@ -0,0 +1,931 @@
+/*
+ * Xilinx Test Pattern Generator
+ *
+ * Copyright (C) 2013-2015 Ideas on Board
+ * Copyright (C) 2013-2015 Xilinx, Inc.
+ *
+ * Contacts: Hyun Kwon <hyun.kwon@xilinx.com>
+ *           Laurent Pinchart <laurent.pinchart@ideasonboard.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/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/xilinx-v4l2-controls.h>
+
+#include <media/v4l2-async.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-subdev.h>
+
+#include "xilinx-vip.h"
+#include "xilinx-vtc.h"
+
+#define XTPG_CTRL_STATUS_SLAVE_ERROR           (1 << 16)
+#define XTPG_CTRL_IRQ_SLAVE_ERROR              (1 << 16)
+
+#define XTPG_PATTERN_CONTROL                   0x0100
+#define XTPG_PATTERN_MASK                      (0xf << 0)
+#define XTPG_PATTERN_CONTROL_CROSS_HAIRS       (1 << 4)
+#define XTPG_PATTERN_CONTROL_MOVING_BOX                (1 << 5)
+#define XTPG_PATTERN_CONTROL_COLOR_MASK_SHIFT  6
+#define XTPG_PATTERN_CONTROL_COLOR_MASK_MASK   (0xf << 6)
+#define XTPG_PATTERN_CONTROL_STUCK_PIXEL       (1 << 9)
+#define XTPG_PATTERN_CONTROL_NOISE             (1 << 10)
+#define XTPG_PATTERN_CONTROL_MOTION            (1 << 12)
+#define XTPG_MOTION_SPEED                      0x0104
+#define XTPG_CROSS_HAIRS                       0x0108
+#define XTPG_CROSS_HAIRS_ROW_SHIFT             0
+#define XTPG_CROSS_HAIRS_ROW_MASK              (0xfff << 0)
+#define XTPG_CROSS_HAIRS_COLUMN_SHIFT          16
+#define XTPG_CROSS_HAIRS_COLUMN_MASK           (0xfff << 16)
+#define XTPG_ZPLATE_HOR_CONTROL                        0x010c
+#define XTPG_ZPLATE_VER_CONTROL                        0x0110
+#define XTPG_ZPLATE_START_SHIFT                        0
+#define XTPG_ZPLATE_START_MASK                 (0xffff << 0)
+#define XTPG_ZPLATE_SPEED_SHIFT                        16
+#define XTPG_ZPLATE_SPEED_MASK                 (0xffff << 16)
+#define XTPG_BOX_SIZE                          0x0114
+#define XTPG_BOX_COLOR                         0x0118
+#define XTPG_STUCK_PIXEL_THRESH                        0x011c
+#define XTPG_NOISE_GAIN                                0x0120
+#define XTPG_BAYER_PHASE                       0x0124
+#define XTPG_BAYER_PHASE_RGGB                  0
+#define XTPG_BAYER_PHASE_GRBG                  1
+#define XTPG_BAYER_PHASE_GBRG                  2
+#define XTPG_BAYER_PHASE_BGGR                  3
+#define XTPG_BAYER_PHASE_OFF                   4
+
+/*
+ * The minimum blanking value is one clock cycle for the front porch, one clock
+ * cycle for the sync pulse and one clock cycle for the back porch.
+ */
+#define XTPG_MIN_HBLANK                        3
+#define XTPG_MAX_HBLANK                        (XVTC_MAX_HSIZE - XVIP_MIN_WIDTH)
+#define XTPG_MIN_VBLANK                        3
+#define XTPG_MAX_VBLANK                        (XVTC_MAX_VSIZE - XVIP_MIN_HEIGHT)
+
+/**
+ * struct xtpg_device - Xilinx Test Pattern Generator device structure
+ * @xvip: Xilinx Video IP device
+ * @pads: media pads
+ * @npads: number of pads (1 or 2)
+ * @has_input: whether an input is connected to the sink pad
+ * @formats: active V4L2 media bus format for each pad
+ * @default_format: default V4L2 media bus format
+ * @vip_format: format information corresponding to the active format
+ * @bayer: boolean flag if TPG is set to any bayer format
+ * @ctrl_handler: control handler
+ * @hblank: horizontal blanking control
+ * @vblank: vertical blanking control
+ * @pattern: test pattern control
+ * @streaming: is the video stream active
+ * @vtc: video timing controller
+ * @vtmux_gpio: video timing mux GPIO
+ */
+struct xtpg_device {
+       struct xvip_device xvip;
+
+       struct media_pad pads[2];
+       unsigned int npads;
+       bool has_input;
+
+       struct v4l2_mbus_framefmt formats[2];
+       struct v4l2_mbus_framefmt default_format;
+       const struct xvip_video_format *vip_format;
+       bool bayer;
+
+       struct v4l2_ctrl_handler ctrl_handler;
+       struct v4l2_ctrl *hblank;
+       struct v4l2_ctrl *vblank;
+       struct v4l2_ctrl *pattern;
+       bool streaming;
+
+       struct xvtc_device *vtc;
+       struct gpio_desc *vtmux_gpio;
+};
+
+static inline struct xtpg_device *to_tpg(struct v4l2_subdev *subdev)
+{
+       return container_of(subdev, struct xtpg_device, xvip.subdev);
+}
+
+static u32 xtpg_get_bayer_phase(unsigned int code)
+{
+       switch (code) {
+       case MEDIA_BUS_FMT_SRGGB8_1X8:
+               return XTPG_BAYER_PHASE_RGGB;
+       case MEDIA_BUS_FMT_SGRBG8_1X8:
+               return XTPG_BAYER_PHASE_GRBG;
+       case MEDIA_BUS_FMT_SGBRG8_1X8:
+               return XTPG_BAYER_PHASE_GBRG;
+       case MEDIA_BUS_FMT_SBGGR8_1X8:
+               return XTPG_BAYER_PHASE_BGGR;
+       default:
+               return XTPG_BAYER_PHASE_OFF;
+       }
+}
+
+static void __xtpg_update_pattern_control(struct xtpg_device *xtpg,
+                                         bool passthrough, bool pattern)
+{
+       u32 pattern_mask = (1 << (xtpg->pattern->maximum + 1)) - 1;
+
+       /*
+        * If the TPG has no sink pad or no input connected to its sink pad
+        * passthrough mode can't be enabled.
+        */
+       if (xtpg->npads == 1 || !xtpg->has_input)
+               passthrough = false;
+
+       /* If passthrough mode is allowed unmask bit 0. */
+       if (passthrough)
+               pattern_mask &= ~1;
+
+       /* If test pattern mode is allowed unmask all other bits. */
+       if (pattern)
+               pattern_mask &= 1;
+
+       __v4l2_ctrl_modify_range(xtpg->pattern, 0, xtpg->pattern->maximum,
+                                pattern_mask, pattern ? 9 : 0);
+}
+
+static void xtpg_update_pattern_control(struct xtpg_device *xtpg,
+                                       bool passthrough, bool pattern)
+{
+       mutex_lock(xtpg->ctrl_handler.lock);
+       __xtpg_update_pattern_control(xtpg, passthrough, pattern);
+       mutex_unlock(xtpg->ctrl_handler.lock);
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdevice Video Operations
+ */
+
+static int xtpg_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+       struct xtpg_device *xtpg = to_tpg(subdev);
+       unsigned int width = xtpg->formats[0].width;
+       unsigned int height = xtpg->formats[0].height;
+       bool passthrough;
+       u32 bayer_phase;
+
+       if (!enable) {
+               xvip_stop(&xtpg->xvip);
+               if (xtpg->vtc)
+                       xvtc_generator_stop(xtpg->vtc);
+
+               xtpg_update_pattern_control(xtpg, true, true);
+               xtpg->streaming = false;
+               return 0;
+       }
+
+       xvip_set_frame_size(&xtpg->xvip, &xtpg->formats[0]);
+
+       if (xtpg->vtc) {
+               struct xvtc_config config = {
+                       .hblank_start = width,
+                       .hsync_start = width + 1,
+                       .vblank_start = height,
+                       .vsync_start = height + 1,
+               };
+               unsigned int htotal;
+               unsigned int vtotal;
+
+               htotal = min_t(unsigned int, XVTC_MAX_HSIZE,
+                              v4l2_ctrl_g_ctrl(xtpg->hblank) + width);
+               vtotal = min_t(unsigned int, XVTC_MAX_VSIZE,
+                              v4l2_ctrl_g_ctrl(xtpg->vblank) + height);
+
+               config.hsync_end = htotal - 1;
+               config.hsize = htotal;
+               config.vsync_end = vtotal - 1;
+               config.vsize = vtotal;
+
+               xvtc_generator_start(xtpg->vtc, &config);
+       }
+
+       /*
+        * Configure the bayer phase and video timing mux based on the
+        * operation mode (passthrough or test pattern generation). The test
+        * pattern can be modified by the control set handler, we thus need to
+        * take the control lock here to avoid races.
+        */
+       mutex_lock(xtpg->ctrl_handler.lock);
+
+       xvip_clr_and_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
+                        XTPG_PATTERN_MASK, xtpg->pattern->cur.val);
+
+       /*
+        * Switching between passthrough and test pattern generation modes isn't
+        * allowed during streaming, update the control range accordingly.
+        */
+       passthrough = xtpg->pattern->cur.val == 0;
+       __xtpg_update_pattern_control(xtpg, passthrough, !passthrough);
+
+       xtpg->streaming = true;
+
+       mutex_unlock(xtpg->ctrl_handler.lock);
+
+       /*
+        * For TPG v5.0, the bayer phase needs to be off for the pass through
+        * mode, otherwise the external input would be subsampled.
+        */
+       bayer_phase = passthrough ? XTPG_BAYER_PHASE_OFF
+                   : xtpg_get_bayer_phase(xtpg->formats[0].code);
+       xvip_write(&xtpg->xvip, XTPG_BAYER_PHASE, bayer_phase);
+
+       if (xtpg->vtmux_gpio)
+               gpiod_set_value_cansleep(xtpg->vtmux_gpio, !passthrough);
+
+       xvip_start(&xtpg->xvip);
+
+       return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdevice Pad Operations
+ */
+
+static struct v4l2_mbus_framefmt *
+__xtpg_get_pad_format(struct xtpg_device *xtpg,
+                     struct v4l2_subdev_pad_config *cfg,
+                     unsigned int pad, u32 which)
+{
+       switch (which) {
+       case V4L2_SUBDEV_FORMAT_TRY:
+               return v4l2_subdev_get_try_format(&xtpg->xvip.subdev, cfg, pad);
+       case V4L2_SUBDEV_FORMAT_ACTIVE:
+               return &xtpg->formats[pad];
+       default:
+               return NULL;
+       }
+}
+
+static int xtpg_get_format(struct v4l2_subdev *subdev,
+                          struct v4l2_subdev_pad_config *cfg,
+                          struct v4l2_subdev_format *fmt)
+{
+       struct xtpg_device *xtpg = to_tpg(subdev);
+
+       fmt->format = *__xtpg_get_pad_format(xtpg, cfg, fmt->pad, fmt->which);
+
+       return 0;
+}
+
+static int xtpg_set_format(struct v4l2_subdev *subdev,
+                          struct v4l2_subdev_pad_config *cfg,
+                          struct v4l2_subdev_format *fmt)
+{
+       struct xtpg_device *xtpg = to_tpg(subdev);
+       struct v4l2_mbus_framefmt *__format;
+       u32 bayer_phase;
+
+       __format = __xtpg_get_pad_format(xtpg, cfg, fmt->pad, fmt->which);
+
+       /* In two pads mode the source pad format is always identical to the
+        * sink pad format.
+        */
+       if (xtpg->npads == 2 && fmt->pad == 1) {
+               fmt->format = *__format;
+               return 0;
+       }
+
+       /* Bayer phase is configurable at runtime */
+       if (xtpg->bayer) {
+               bayer_phase = xtpg_get_bayer_phase(fmt->format.code);
+               if (bayer_phase != XTPG_BAYER_PHASE_OFF)
+                       __format->code = fmt->format.code;
+       }
+
+       xvip_set_format_size(__format, fmt);
+
+       fmt->format = *__format;
+
+       /* Propagate the format to the source pad. */
+       if (xtpg->npads == 2) {
+               __format = __xtpg_get_pad_format(xtpg, cfg, 1, fmt->which);
+               *__format = fmt->format;
+       }
+
+       return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdevice Operations
+ */
+
+static int xtpg_enum_frame_size(struct v4l2_subdev *subdev,
+                               struct v4l2_subdev_pad_config *cfg,
+                               struct v4l2_subdev_frame_size_enum *fse)
+{
+       struct v4l2_mbus_framefmt *format;
+
+       format = v4l2_subdev_get_try_format(subdev, cfg, fse->pad);
+
+       if (fse->index || fse->code != format->code)
+               return -EINVAL;
+
+       /* Min / max values for pad 0 is always fixed in both one and two pads
+        * modes. In two pads mode, the source pad(= 1) size is identical to
+        * the sink pad size */
+       if (fse->pad == 0) {
+               fse->min_width = XVIP_MIN_WIDTH;
+               fse->max_width = XVIP_MAX_WIDTH;
+               fse->min_height = XVIP_MIN_HEIGHT;
+               fse->max_height = XVIP_MAX_HEIGHT;
+       } else {
+               fse->min_width = format->width;
+               fse->max_width = format->width;
+               fse->min_height = format->height;
+               fse->max_height = format->height;
+       }
+
+       return 0;
+}
+
+static int xtpg_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+       struct xtpg_device *xtpg = to_tpg(subdev);
+       struct v4l2_mbus_framefmt *format;
+
+       format = v4l2_subdev_get_try_format(subdev, fh->pad, 0);
+       *format = xtpg->default_format;
+
+       if (xtpg->npads == 2) {
+               format = v4l2_subdev_get_try_format(subdev, fh->pad, 1);
+               *format = xtpg->default_format;
+       }
+
+       return 0;
+}
+
+static int xtpg_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+       return 0;
+}
+
+static int xtpg_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct xtpg_device *xtpg = container_of(ctrl->handler,
+                                               struct xtpg_device,
+                                               ctrl_handler);
+       switch (ctrl->id) {
+       case V4L2_CID_TEST_PATTERN:
+               xvip_clr_and_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
+                                XTPG_PATTERN_MASK, ctrl->val);
+               return 0;
+       case V4L2_CID_XILINX_TPG_CROSS_HAIRS:
+               xvip_clr_or_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
+                               XTPG_PATTERN_CONTROL_CROSS_HAIRS, ctrl->val);
+               return 0;
+       case V4L2_CID_XILINX_TPG_MOVING_BOX:
+               xvip_clr_or_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
+                               XTPG_PATTERN_CONTROL_MOVING_BOX, ctrl->val);
+               return 0;
+       case V4L2_CID_XILINX_TPG_COLOR_MASK:
+               xvip_clr_and_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
+                                XTPG_PATTERN_CONTROL_COLOR_MASK_MASK,
+                                ctrl->val <<
+                                XTPG_PATTERN_CONTROL_COLOR_MASK_SHIFT);
+               return 0;
+       case V4L2_CID_XILINX_TPG_STUCK_PIXEL:
+               xvip_clr_or_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
+                               XTPG_PATTERN_CONTROL_STUCK_PIXEL, ctrl->val);
+               return 0;
+       case V4L2_CID_XILINX_TPG_NOISE:
+               xvip_clr_or_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
+                               XTPG_PATTERN_CONTROL_NOISE, ctrl->val);
+               return 0;
+       case V4L2_CID_XILINX_TPG_MOTION:
+               xvip_clr_or_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
+                               XTPG_PATTERN_CONTROL_MOTION, ctrl->val);
+               return 0;
+       case V4L2_CID_XILINX_TPG_MOTION_SPEED:
+               xvip_write(&xtpg->xvip, XTPG_MOTION_SPEED, ctrl->val);
+               return 0;
+       case V4L2_CID_XILINX_TPG_CROSS_HAIR_ROW:
+               xvip_clr_and_set(&xtpg->xvip, XTPG_CROSS_HAIRS,
+                                XTPG_CROSS_HAIRS_ROW_MASK,
+                                ctrl->val << XTPG_CROSS_HAIRS_ROW_SHIFT);
+               return 0;
+       case V4L2_CID_XILINX_TPG_CROSS_HAIR_COLUMN:
+               xvip_clr_and_set(&xtpg->xvip, XTPG_CROSS_HAIRS,
+                                XTPG_CROSS_HAIRS_COLUMN_MASK,
+                                ctrl->val << XTPG_CROSS_HAIRS_COLUMN_SHIFT);
+               return 0;
+       case V4L2_CID_XILINX_TPG_ZPLATE_HOR_START:
+               xvip_clr_and_set(&xtpg->xvip, XTPG_ZPLATE_HOR_CONTROL,
+                                XTPG_ZPLATE_START_MASK,
+                                ctrl->val << XTPG_ZPLATE_START_SHIFT);
+               return 0;
+       case V4L2_CID_XILINX_TPG_ZPLATE_HOR_SPEED:
+               xvip_clr_and_set(&xtpg->xvip, XTPG_ZPLATE_HOR_CONTROL,
+                                XTPG_ZPLATE_SPEED_MASK,
+                                ctrl->val << XTPG_ZPLATE_SPEED_SHIFT);
+               return 0;
+       case V4L2_CID_XILINX_TPG_ZPLATE_VER_START:
+               xvip_clr_and_set(&xtpg->xvip, XTPG_ZPLATE_VER_CONTROL,
+                                XTPG_ZPLATE_START_MASK,
+                                ctrl->val << XTPG_ZPLATE_START_SHIFT);
+               return 0;
+       case V4L2_CID_XILINX_TPG_ZPLATE_VER_SPEED:
+               xvip_clr_and_set(&xtpg->xvip, XTPG_ZPLATE_VER_CONTROL,
+                                XTPG_ZPLATE_SPEED_MASK,
+                                ctrl->val << XTPG_ZPLATE_SPEED_SHIFT);
+               return 0;
+       case V4L2_CID_XILINX_TPG_BOX_SIZE:
+               xvip_write(&xtpg->xvip, XTPG_BOX_SIZE, ctrl->val);
+               return 0;
+       case V4L2_CID_XILINX_TPG_BOX_COLOR:
+               xvip_write(&xtpg->xvip, XTPG_BOX_COLOR, ctrl->val);
+               return 0;
+       case V4L2_CID_XILINX_TPG_STUCK_PIXEL_THRESH:
+               xvip_write(&xtpg->xvip, XTPG_STUCK_PIXEL_THRESH, ctrl->val);
+               return 0;
+       case V4L2_CID_XILINX_TPG_NOISE_GAIN:
+               xvip_write(&xtpg->xvip, XTPG_NOISE_GAIN, ctrl->val);
+               return 0;
+       }
+
+       return 0;
+}
+
+static const struct v4l2_ctrl_ops xtpg_ctrl_ops = {
+       .s_ctrl = xtpg_s_ctrl,
+};
+
+static struct v4l2_subdev_core_ops xtpg_core_ops = {
+};
+
+static struct v4l2_subdev_video_ops xtpg_video_ops = {
+       .s_stream = xtpg_s_stream,
+};
+
+static struct v4l2_subdev_pad_ops xtpg_pad_ops = {
+       .enum_mbus_code         = xvip_enum_mbus_code,
+       .enum_frame_size        = xtpg_enum_frame_size,
+       .get_fmt                = xtpg_get_format,
+       .set_fmt                = xtpg_set_format,
+};
+
+static struct v4l2_subdev_ops xtpg_ops = {
+       .core   = &xtpg_core_ops,
+       .video  = &xtpg_video_ops,
+       .pad    = &xtpg_pad_ops,
+};
+
+static const struct v4l2_subdev_internal_ops xtpg_internal_ops = {
+       .open   = xtpg_open,
+       .close  = xtpg_close,
+};
+
+/*
+ * Control Config
+ */
+
+static const char *const xtpg_pattern_strings[] = {
+       "Passthrough",
+       "Horizontal Ramp",
+       "Vertical Ramp",
+       "Temporal Ramp",
+       "Solid Red",
+       "Solid Green",
+       "Solid Blue",
+       "Solid Black",
+       "Solid White",
+       "Color Bars",
+       "Zone Plate",
+       "Tartan Color Bars",
+       "Cross Hatch",
+       "None",
+       "Vertical/Horizontal Ramps",
+       "Black/White Checker Board",
+};
+
+static struct v4l2_ctrl_config xtpg_ctrls[] = {
+       {
+               .ops    = &xtpg_ctrl_ops,
+               .id     = V4L2_CID_XILINX_TPG_CROSS_HAIRS,
+               .name   = "Test Pattern: Cross Hairs",
+               .type   = V4L2_CTRL_TYPE_BOOLEAN,
+               .min    = false,
+               .max    = true,
+               .step   = 1,
+               .def    = 0,
+       }, {
+               .ops    = &xtpg_ctrl_ops,
+               .id     = V4L2_CID_XILINX_TPG_MOVING_BOX,
+               .name   = "Test Pattern: Moving Box",
+               .type   = V4L2_CTRL_TYPE_BOOLEAN,
+               .min    = false,
+               .max    = true,
+               .step   = 1,
+               .def    = 0,
+       }, {
+               .ops    = &xtpg_ctrl_ops,
+               .id     = V4L2_CID_XILINX_TPG_COLOR_MASK,
+               .name   = "Test Pattern: Color Mask",
+               .type   = V4L2_CTRL_TYPE_BITMASK,
+               .min    = 0,
+               .max    = 0xf,
+               .def    = 0,
+       }, {
+               .ops    = &xtpg_ctrl_ops,
+               .id     = V4L2_CID_XILINX_TPG_STUCK_PIXEL,
+               .name   = "Test Pattern: Stuck Pixel",
+               .type   = V4L2_CTRL_TYPE_BOOLEAN,
+               .min    = false,
+               .max    = true,
+               .step   = 1,
+               .def    = 0,
+       }, {
+               .ops    = &xtpg_ctrl_ops,
+               .id     = V4L2_CID_XILINX_TPG_NOISE,
+               .name   = "Test Pattern: Noise",
+               .type   = V4L2_CTRL_TYPE_BOOLEAN,
+               .min    = false,
+               .max    = true,
+               .step   = 1,
+               .def    = 0,
+       }, {
+               .ops    = &xtpg_ctrl_ops,
+               .id     = V4L2_CID_XILINX_TPG_MOTION,
+               .name   = "Test Pattern: Motion",
+               .type   = V4L2_CTRL_TYPE_BOOLEAN,
+               .min    = false,
+               .max    = true,
+               .step   = 1,
+               .def    = 0,
+       }, {
+               .ops    = &xtpg_ctrl_ops,
+               .id     = V4L2_CID_XILINX_TPG_MOTION_SPEED,
+               .name   = "Test Pattern: Motion Speed",
+               .type   = V4L2_CTRL_TYPE_INTEGER,
+               .min    = 0,
+               .max    = (1 << 8) - 1,
+               .step   = 1,
+               .def    = 4,
+               .flags  = V4L2_CTRL_FLAG_SLIDER,
+       }, {
+               .ops    = &xtpg_ctrl_ops,
+               .id     = V4L2_CID_XILINX_TPG_CROSS_HAIR_ROW,
+               .name   = "Test Pattern: Cross Hairs Row",
+               .type   = V4L2_CTRL_TYPE_INTEGER,
+               .min    = 0,
+               .max    = (1 << 12) - 1,
+               .step   = 1,
+               .def    = 0x64,
+               .flags  = V4L2_CTRL_FLAG_SLIDER,
+       }, {
+               .ops    = &xtpg_ctrl_ops,
+               .id     = V4L2_CID_XILINX_TPG_CROSS_HAIR_COLUMN,
+               .name   = "Test Pattern: Cross Hairs Column",
+               .type   = V4L2_CTRL_TYPE_INTEGER,
+               .min    = 0,
+               .max    = (1 << 12) - 1,
+               .step   = 1,
+               .def    = 0x64,
+               .flags  = V4L2_CTRL_FLAG_SLIDER,
+       }, {
+               .ops    = &xtpg_ctrl_ops,
+               .id     = V4L2_CID_XILINX_TPG_ZPLATE_HOR_START,
+               .name   = "Test Pattern: Zplate Horizontal Start Pos",
+               .type   = V4L2_CTRL_TYPE_INTEGER,
+               .min    = 0,
+               .max    = (1 << 16) - 1,
+               .step   = 1,
+               .def    = 0x1e,
+               .flags  = V4L2_CTRL_FLAG_SLIDER,
+       }, {
+               .ops    = &xtpg_ctrl_ops,
+               .id     = V4L2_CID_XILINX_TPG_ZPLATE_HOR_SPEED,
+               .name   = "Test Pattern: Zplate Horizontal Speed",
+               .type   = V4L2_CTRL_TYPE_INTEGER,
+               .min    = 0,
+               .max    = (1 << 16) - 1,
+               .step   = 1,
+               .def    = 0,
+               .flags  = V4L2_CTRL_FLAG_SLIDER,
+       }, {
+               .ops    = &xtpg_ctrl_ops,
+               .id     = V4L2_CID_XILINX_TPG_ZPLATE_VER_START,
+               .name   = "Test Pattern: Zplate Vertical Start Pos",
+               .type   = V4L2_CTRL_TYPE_INTEGER,
+               .min    = 0,
+               .max    = (1 << 16) - 1,
+               .step   = 1,
+               .def    = 1,
+               .flags  = V4L2_CTRL_FLAG_SLIDER,
+       }, {
+               .ops    = &xtpg_ctrl_ops,
+               .id     = V4L2_CID_XILINX_TPG_ZPLATE_VER_SPEED,
+               .name   = "Test Pattern: Zplate Vertical Speed",
+               .type   = V4L2_CTRL_TYPE_INTEGER,
+               .min    = 0,
+               .max    = (1 << 16) - 1,
+               .step   = 1,
+               .def    = 0,
+               .flags  = V4L2_CTRL_FLAG_SLIDER,
+       }, {
+               .ops    = &xtpg_ctrl_ops,
+               .id     = V4L2_CID_XILINX_TPG_BOX_SIZE,
+               .name   = "Test Pattern: Box Size",
+               .type   = V4L2_CTRL_TYPE_INTEGER,
+               .min    = 0,
+               .max    = (1 << 12) - 1,
+               .step   = 1,
+               .def    = 0x32,
+               .flags  = V4L2_CTRL_FLAG_SLIDER,
+       }, {
+               .ops    = &xtpg_ctrl_ops,
+               .id     = V4L2_CID_XILINX_TPG_BOX_COLOR,
+               .name   = "Test Pattern: Box Color(RGB)",
+               .type   = V4L2_CTRL_TYPE_INTEGER,
+               .min    = 0,
+               .max    = (1 << 24) - 1,
+               .step   = 1,
+               .def    = 0,
+       }, {
+               .ops    = &xtpg_ctrl_ops,
+               .id     = V4L2_CID_XILINX_TPG_STUCK_PIXEL_THRESH,
+               .name   = "Test Pattern: Stuck Pixel threshold",
+               .type   = V4L2_CTRL_TYPE_INTEGER,
+               .min    = 0,
+               .max    = (1 << 16) - 1,
+               .step   = 1,
+               .def    = 0,
+               .flags  = V4L2_CTRL_FLAG_SLIDER,
+       }, {
+               .ops    = &xtpg_ctrl_ops,
+               .id     = V4L2_CID_XILINX_TPG_NOISE_GAIN,
+               .name   = "Test Pattern: Noise Gain",
+               .type   = V4L2_CTRL_TYPE_INTEGER,
+               .min    = 0,
+               .max    = (1 << 8) - 1,
+               .step   = 1,
+               .def    = 0,
+               .flags  = V4L2_CTRL_FLAG_SLIDER,
+       },
+};
+
+/* -----------------------------------------------------------------------------
+ * Media Operations
+ */
+
+static const struct media_entity_operations xtpg_media_ops = {
+       .link_validate = v4l2_subdev_link_validate,
+};
+
+/* -----------------------------------------------------------------------------
+ * Power Management
+ */
+
+static int __maybe_unused xtpg_pm_suspend(struct device *dev)
+{
+       struct xtpg_device *xtpg = dev_get_drvdata(dev);
+
+       xvip_suspend(&xtpg->xvip);
+
+       return 0;
+}
+
+static int __maybe_unused xtpg_pm_resume(struct device *dev)
+{
+       struct xtpg_device *xtpg = dev_get_drvdata(dev);
+
+       xvip_resume(&xtpg->xvip);
+
+       return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Platform Device Driver
+ */
+
+static int xtpg_parse_of(struct xtpg_device *xtpg)
+{
+       struct device *dev = xtpg->xvip.dev;
+       struct device_node *node = xtpg->xvip.dev->of_node;
+       struct device_node *ports;
+       struct device_node *port;
+       unsigned int nports = 0;
+       bool has_endpoint = false;
+
+       ports = of_get_child_by_name(node, "ports");
+       if (ports == NULL)
+               ports = node;
+
+       for_each_child_of_node(ports, port) {
+               const struct xvip_video_format *format;
+               struct device_node *endpoint;
+
+               if (!port->name || of_node_cmp(port->name, "port"))
+                       continue;
+
+               format = xvip_of_get_format(port);
+               if (IS_ERR(format)) {
+                       dev_err(dev, "invalid format in DT");
+                       return PTR_ERR(format);
+               }
+
+               /* Get and check the format description */
+               if (!xtpg->vip_format) {
+                       xtpg->vip_format = format;
+               } else if (xtpg->vip_format != format) {
+                       dev_err(dev, "in/out format mismatch in DT");
+                       return -EINVAL;
+               }
+
+               if (nports == 0) {
+                       endpoint = of_get_next_child(port, NULL);
+                       if (endpoint)
+                               has_endpoint = true;
+                       of_node_put(endpoint);
+               }
+
+               /* Count the number of ports. */
+               nports++;
+       }
+
+       if (nports != 1 && nports != 2) {
+               dev_err(dev, "invalid number of ports %u\n", nports);
+               return -EINVAL;
+       }
+
+       xtpg->npads = nports;
+       if (nports == 2 && has_endpoint)
+               xtpg->has_input = true;
+
+       return 0;
+}
+
+static int xtpg_probe(struct platform_device *pdev)
+{
+       struct v4l2_subdev *subdev;
+       struct xtpg_device *xtpg;
+       u32 i, bayer_phase;
+       int ret;
+
+       xtpg = devm_kzalloc(&pdev->dev, sizeof(*xtpg), GFP_KERNEL);
+       if (!xtpg)
+               return -ENOMEM;
+
+       xtpg->xvip.dev = &pdev->dev;
+
+       ret = xtpg_parse_of(xtpg);
+       if (ret < 0)
+               return ret;
+
+       ret = xvip_init_resources(&xtpg->xvip);
+       if (ret < 0)
+               return ret;
+
+       xtpg->vtmux_gpio = devm_gpiod_get_optional(&pdev->dev, "timing",
+                                                  GPIOD_OUT_HIGH);
+       if (IS_ERR(xtpg->vtmux_gpio)) {
+               ret = PTR_ERR(xtpg->vtmux_gpio);
+               goto error_resource;
+       }
+
+       xtpg->vtc = xvtc_of_get(pdev->dev.of_node);
+       if (IS_ERR(xtpg->vtc)) {
+               ret = PTR_ERR(xtpg->vtc);
+               goto error_resource;
+       }
+
+       /* Reset and initialize the core */
+       xvip_reset(&xtpg->xvip);
+
+       /* Initialize V4L2 subdevice and media entity. Pad numbers depend on the
+        * number of pads.
+        */
+       if (xtpg->npads == 2) {
+               xtpg->pads[0].flags = MEDIA_PAD_FL_SINK;
+               xtpg->pads[1].flags = MEDIA_PAD_FL_SOURCE;
+       } else {
+               xtpg->pads[0].flags = MEDIA_PAD_FL_SOURCE;
+       }
+
+       /* Initialize the default format */
+       xtpg->default_format.code = xtpg->vip_format->code;
+       xtpg->default_format.field = V4L2_FIELD_NONE;
+       xtpg->default_format.colorspace = V4L2_COLORSPACE_SRGB;
+       xvip_get_frame_size(&xtpg->xvip, &xtpg->default_format);
+
+       bayer_phase = xtpg_get_bayer_phase(xtpg->vip_format->code);
+       if (bayer_phase != XTPG_BAYER_PHASE_OFF)
+               xtpg->bayer = true;
+
+       xtpg->formats[0] = xtpg->default_format;
+       if (xtpg->npads == 2)
+               xtpg->formats[1] = xtpg->default_format;
+
+       /* Initialize V4L2 subdevice and media entity */
+       subdev = &xtpg->xvip.subdev;
+       v4l2_subdev_init(subdev, &xtpg_ops);
+       subdev->dev = &pdev->dev;
+       subdev->internal_ops = &xtpg_internal_ops;
+       strlcpy(subdev->name, dev_name(&pdev->dev), sizeof(subdev->name));
+       v4l2_set_subdevdata(subdev, xtpg);
+       subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+       subdev->entity.ops = &xtpg_media_ops;
+
+       ret = media_entity_init(&subdev->entity, xtpg->npads, xtpg->pads, 0);
+       if (ret < 0)
+               goto error;
+
+       v4l2_ctrl_handler_init(&xtpg->ctrl_handler, 3 + ARRAY_SIZE(xtpg_ctrls));
+
+       xtpg->vblank = v4l2_ctrl_new_std(&xtpg->ctrl_handler, &xtpg_ctrl_ops,
+                                        V4L2_CID_VBLANK, XTPG_MIN_VBLANK,
+                                        XTPG_MAX_VBLANK, 1, 100);
+       xtpg->hblank = v4l2_ctrl_new_std(&xtpg->ctrl_handler, &xtpg_ctrl_ops,
+                                        V4L2_CID_HBLANK, XTPG_MIN_HBLANK,
+                                        XTPG_MAX_HBLANK, 1, 100);
+       xtpg->pattern = v4l2_ctrl_new_std_menu_items(&xtpg->ctrl_handler,
+                                       &xtpg_ctrl_ops, V4L2_CID_TEST_PATTERN,
+                                       ARRAY_SIZE(xtpg_pattern_strings) - 1,
+                                       1, 9, xtpg_pattern_strings);
+
+       for (i = 0; i < ARRAY_SIZE(xtpg_ctrls); i++)
+               v4l2_ctrl_new_custom(&xtpg->ctrl_handler, &xtpg_ctrls[i], NULL);
+
+       if (xtpg->ctrl_handler.error) {
+               dev_err(&pdev->dev, "failed to add controls\n");
+               ret = xtpg->ctrl_handler.error;
+               goto error;
+       }
+       subdev->ctrl_handler = &xtpg->ctrl_handler;
+
+       xtpg_update_pattern_control(xtpg, true, true);
+
+       ret = v4l2_ctrl_handler_setup(&xtpg->ctrl_handler);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "failed to set controls\n");
+               goto error;
+       }
+
+       platform_set_drvdata(pdev, xtpg);
+
+       xvip_print_version(&xtpg->xvip);
+
+       ret = v4l2_async_register_subdev(subdev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "failed to register subdev\n");
+               goto error;
+       }
+
+       return 0;
+
+error:
+       v4l2_ctrl_handler_free(&xtpg->ctrl_handler);
+       media_entity_cleanup(&subdev->entity);
+       xvtc_put(xtpg->vtc);
+error_resource:
+       xvip_cleanup_resources(&xtpg->xvip);
+       return ret;
+}
+
+static int xtpg_remove(struct platform_device *pdev)
+{
+       struct xtpg_device *xtpg = platform_get_drvdata(pdev);
+       struct v4l2_subdev *subdev = &xtpg->xvip.subdev;
+
+       v4l2_async_unregister_subdev(subdev);
+       v4l2_ctrl_handler_free(&xtpg->ctrl_handler);
+       media_entity_cleanup(&subdev->entity);
+
+       xvip_cleanup_resources(&xtpg->xvip);
+
+       return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(xtpg_pm_ops, xtpg_pm_suspend, xtpg_pm_resume);
+
+static const struct of_device_id xtpg_of_id_table[] = {
+       { .compatible = "xlnx,v-tpg-5.0" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, xtpg_of_id_table);
+
+static struct platform_driver xtpg_driver = {
+       .driver = {
+               .name           = "xilinx-tpg",
+               .pm             = &xtpg_pm_ops,
+               .of_match_table = xtpg_of_id_table,
+       },
+       .probe                  = xtpg_probe,
+       .remove                 = xtpg_remove,
+};
+
+module_platform_driver(xtpg_driver);
+
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_DESCRIPTION("Xilinx Test Pattern Generator Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/xilinx/xilinx-vip.c b/drivers/media/platform/xilinx/xilinx-vip.c
new file mode 100644 (file)
index 0000000..3112591
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+ * Xilinx Video IP Core
+ *
+ * Copyright (C) 2013-2015 Ideas on Board
+ * Copyright (C) 2013-2015 Xilinx, Inc.
+ *
+ * Contacts: Hyun Kwon <hyun.kwon@xilinx.com>
+ *           Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include <dt-bindings/media/xilinx-vip.h>
+
+#include "xilinx-vip.h"
+
+/* -----------------------------------------------------------------------------
+ * Helper functions
+ */
+
+static const struct xvip_video_format xvip_video_formats[] = {
+       { XVIP_VF_YUV_422, 8, NULL, MEDIA_BUS_FMT_UYVY8_1X16,
+         2, V4L2_PIX_FMT_YUYV, "4:2:2, packed, YUYV" },
+       { XVIP_VF_YUV_444, 8, NULL, MEDIA_BUS_FMT_VUY8_1X24,
+         3, V4L2_PIX_FMT_YUV444, "4:4:4, packed, YUYV" },
+       { XVIP_VF_RBG, 8, NULL, MEDIA_BUS_FMT_RBG888_1X24,
+         3, 0, NULL },
+       { XVIP_VF_MONO_SENSOR, 8, "mono", MEDIA_BUS_FMT_Y8_1X8,
+         1, V4L2_PIX_FMT_GREY, "Greyscale 8-bit" },
+       { XVIP_VF_MONO_SENSOR, 8, "rggb", MEDIA_BUS_FMT_SRGGB8_1X8,
+         1, V4L2_PIX_FMT_SGRBG8, "Bayer 8-bit RGGB" },
+       { XVIP_VF_MONO_SENSOR, 8, "grbg", MEDIA_BUS_FMT_SGRBG8_1X8,
+         1, V4L2_PIX_FMT_SGRBG8, "Bayer 8-bit GRBG" },
+       { XVIP_VF_MONO_SENSOR, 8, "gbrg", MEDIA_BUS_FMT_SGBRG8_1X8,
+         1, V4L2_PIX_FMT_SGBRG8, "Bayer 8-bit GBRG" },
+       { XVIP_VF_MONO_SENSOR, 8, "bggr", MEDIA_BUS_FMT_SBGGR8_1X8,
+         1, V4L2_PIX_FMT_SBGGR8, "Bayer 8-bit BGGR" },
+};
+
+/**
+ * xvip_get_format_by_code - Retrieve format information for a media bus code
+ * @code: the format media bus code
+ *
+ * Return: a pointer to the format information structure corresponding to the
+ * given V4L2 media bus format @code, or ERR_PTR if no corresponding format can
+ * be found.
+ */
+const struct xvip_video_format *xvip_get_format_by_code(unsigned int code)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(xvip_video_formats); ++i) {
+               const struct xvip_video_format *format = &xvip_video_formats[i];
+
+               if (format->code == code)
+                       return format;
+       }
+
+       return ERR_PTR(-EINVAL);
+}
+EXPORT_SYMBOL_GPL(xvip_get_format_by_code);
+
+/**
+ * xvip_get_format_by_fourcc - Retrieve format information for a 4CC
+ * @fourcc: the format 4CC
+ *
+ * Return: a pointer to the format information structure corresponding to the
+ * given V4L2 format @fourcc, or ERR_PTR if no corresponding format can be
+ * found.
+ */
+const struct xvip_video_format *xvip_get_format_by_fourcc(u32 fourcc)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(xvip_video_formats); ++i) {
+               const struct xvip_video_format *format = &xvip_video_formats[i];
+
+               if (format->fourcc == fourcc)
+                       return format;
+       }
+
+       return ERR_PTR(-EINVAL);
+}
+EXPORT_SYMBOL_GPL(xvip_get_format_by_fourcc);
+
+/**
+ * xvip_of_get_format - Parse a device tree node and return format information
+ * @node: the device tree node
+ *
+ * Read the xlnx,video-format, xlnx,video-width and xlnx,cfa-pattern properties
+ * from the device tree @node passed as an argument and return the corresponding
+ * format information.
+ *
+ * Return: a pointer to the format information structure corresponding to the
+ * format name and width, or ERR_PTR if no corresponding format can be found.
+ */
+const struct xvip_video_format *xvip_of_get_format(struct device_node *node)
+{
+       const char *pattern = "mono";
+       unsigned int vf_code;
+       unsigned int i;
+       u32 width;
+       int ret;
+
+       ret = of_property_read_u32(node, "xlnx,video-format", &vf_code);
+       if (ret < 0)
+               return ERR_PTR(ret);
+
+       ret = of_property_read_u32(node, "xlnx,video-width", &width);
+       if (ret < 0)
+               return ERR_PTR(ret);
+
+       if (vf_code == XVIP_VF_MONO_SENSOR)
+               of_property_read_string(node, "xlnx,cfa-pattern", &pattern);
+
+       for (i = 0; i < ARRAY_SIZE(xvip_video_formats); ++i) {
+               const struct xvip_video_format *format = &xvip_video_formats[i];
+
+               if (format->vf_code != vf_code || format->width != width)
+                       continue;
+
+               if (vf_code == XVIP_VF_MONO_SENSOR &&
+                   strcmp(pattern, format->pattern))
+                       continue;
+
+               return format;
+       }
+
+       return ERR_PTR(-EINVAL);
+}
+EXPORT_SYMBOL_GPL(xvip_of_get_format);
+
+/**
+ * xvip_set_format_size - Set the media bus frame format size
+ * @format: V4L2 frame format on media bus
+ * @fmt: media bus format
+ *
+ * Set the media bus frame format size. The width / height from the subdevice
+ * format are set to the given media bus format. The new format size is stored
+ * in @format. The width and height are clamped using default min / max values.
+ */
+void xvip_set_format_size(struct v4l2_mbus_framefmt *format,
+                         const struct v4l2_subdev_format *fmt)
+{
+       format->width = clamp_t(unsigned int, fmt->format.width,
+                               XVIP_MIN_WIDTH, XVIP_MAX_WIDTH);
+       format->height = clamp_t(unsigned int, fmt->format.height,
+                        XVIP_MIN_HEIGHT, XVIP_MAX_HEIGHT);
+}
+EXPORT_SYMBOL_GPL(xvip_set_format_size);
+
+/**
+ * xvip_clr_or_set - Clear or set the register with a bitmask
+ * @xvip: Xilinx Video IP device
+ * @addr: address of register
+ * @mask: bitmask to be set or cleared
+ * @set: boolean flag indicating whether to set or clear
+ *
+ * Clear or set the register at address @addr with a bitmask @mask depending on
+ * the boolean flag @set. When the flag @set is true, the bitmask is set in
+ * the register, otherwise the bitmask is cleared from the register
+ * when the flag @set is false.
+ *
+ * Fox eample, this function can be used to set a control with a boolean value
+ * requested by users. If the caller knows whether to set or clear in the first
+ * place, the caller should call xvip_clr() or xvip_set() directly instead of
+ * using this function.
+ */
+void xvip_clr_or_set(struct xvip_device *xvip, u32 addr, u32 mask, bool set)
+{
+       u32 reg;
+
+       reg = xvip_read(xvip, addr);
+       reg = set ? reg | mask : reg & ~mask;
+       xvip_write(xvip, addr, reg);
+}
+EXPORT_SYMBOL_GPL(xvip_clr_or_set);
+
+/**
+ * xvip_clr_and_set - Clear and set the register with a bitmask
+ * @xvip: Xilinx Video IP device
+ * @addr: address of register
+ * @clr: bitmask to be cleared
+ * @set: bitmask to be set
+ *
+ * Clear a bit(s) of mask @clr in the register at address @addr, then set
+ * a bit(s) of mask @set in the register after.
+ */
+void xvip_clr_and_set(struct xvip_device *xvip, u32 addr, u32 clr, u32 set)
+{
+       u32 reg;
+
+       reg = xvip_read(xvip, addr);
+       reg &= ~clr;
+       reg |= set;
+       xvip_write(xvip, addr, reg);
+}
+EXPORT_SYMBOL_GPL(xvip_clr_and_set);
+
+int xvip_init_resources(struct xvip_device *xvip)
+{
+       struct platform_device *pdev = to_platform_device(xvip->dev);
+       struct resource *res;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       xvip->iomem = devm_ioremap_resource(xvip->dev, res);
+       if (IS_ERR(xvip->iomem))
+               return PTR_ERR(xvip->iomem);
+
+       xvip->clk = devm_clk_get(xvip->dev, NULL);
+       if (IS_ERR(xvip->clk))
+               return PTR_ERR(xvip->clk);
+
+       clk_prepare_enable(xvip->clk);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(xvip_init_resources);
+
+void xvip_cleanup_resources(struct xvip_device *xvip)
+{
+       clk_disable_unprepare(xvip->clk);
+}
+EXPORT_SYMBOL_GPL(xvip_cleanup_resources);
+
+/* -----------------------------------------------------------------------------
+ * Subdev operations handlers
+ */
+
+/**
+ * xvip_enum_mbus_code - Enumerate the media format code
+ * @subdev: V4L2 subdevice
+ * @cfg: V4L2 subdev pad configuration
+ * @code: returning media bus code
+ *
+ * Enumerate the media bus code of the subdevice. Return the corresponding
+ * pad format code. This function only works for subdevices with fixed format
+ * on all pads. Subdevices with multiple format should have their own
+ * function to enumerate mbus codes.
+ *
+ * Return: 0 if the media bus code is found, or -EINVAL if the format index
+ * is not valid.
+ */
+int xvip_enum_mbus_code(struct v4l2_subdev *subdev,
+                       struct v4l2_subdev_pad_config *cfg,
+                       struct v4l2_subdev_mbus_code_enum *code)
+{
+       struct v4l2_mbus_framefmt *format;
+
+       /* Enumerating frame sizes based on the active configuration isn't
+        * supported yet.
+        */
+       if (code->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
+
+       if (code->index)
+               return -EINVAL;
+
+       format = v4l2_subdev_get_try_format(subdev, cfg, code->pad);
+
+       code->code = format->code;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(xvip_enum_mbus_code);
+
+/**
+ * xvip_enum_frame_size - Enumerate the media bus frame size
+ * @subdev: V4L2 subdevice
+ * @cfg: V4L2 subdev pad configuration
+ * @fse: returning media bus frame size
+ *
+ * This function is a drop-in implementation of the subdev enum_frame_size pad
+ * operation. It assumes that the subdevice has one sink pad and one source
+ * pad, and that the format on the source pad is always identical to the
+ * format on the sink pad. Entities with different requirements need to
+ * implement their own enum_frame_size handlers.
+ *
+ * Return: 0 if the media bus frame size is found, or -EINVAL
+ * if the index or the code is not valid.
+ */
+int xvip_enum_frame_size(struct v4l2_subdev *subdev,
+                        struct v4l2_subdev_pad_config *cfg,
+                        struct v4l2_subdev_frame_size_enum *fse)
+{
+       struct v4l2_mbus_framefmt *format;
+
+       /* Enumerating frame sizes based on the active configuration isn't
+        * supported yet.
+        */
+       if (fse->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
+
+       format = v4l2_subdev_get_try_format(subdev, cfg, fse->pad);
+
+       if (fse->index || fse->code != format->code)
+               return -EINVAL;
+
+       if (fse->pad == XVIP_PAD_SINK) {
+               fse->min_width = XVIP_MIN_WIDTH;
+               fse->max_width = XVIP_MAX_WIDTH;
+               fse->min_height = XVIP_MIN_HEIGHT;
+               fse->max_height = XVIP_MAX_HEIGHT;
+       } else {
+               /* The size on the source pad is fixed and always identical to
+                * the size on the sink pad.
+                */
+               fse->min_width = format->width;
+               fse->max_width = format->width;
+               fse->min_height = format->height;
+               fse->max_height = format->height;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(xvip_enum_frame_size);
diff --git a/drivers/media/platform/xilinx/xilinx-vip.h b/drivers/media/platform/xilinx/xilinx-vip.h
new file mode 100644 (file)
index 0000000..42fee20
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+ * Xilinx Video IP Core
+ *
+ * Copyright (C) 2013-2015 Ideas on Board
+ * Copyright (C) 2013-2015 Xilinx, Inc.
+ *
+ * Contacts: Hyun Kwon <hyun.kwon@xilinx.com>
+ *           Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __XILINX_VIP_H__
+#define __XILINX_VIP_H__
+
+#include <linux/io.h>
+#include <media/v4l2-subdev.h>
+
+struct clk;
+
+/*
+ * Minimum and maximum width and height common to most video IP cores. IP
+ * cores with different requirements must define their own values.
+ */
+#define XVIP_MIN_WIDTH                 32
+#define XVIP_MAX_WIDTH                 7680
+#define XVIP_MIN_HEIGHT                        32
+#define XVIP_MAX_HEIGHT                        7680
+
+/*
+ * Pad IDs. IP cores with with multiple inputs or outputs should define
+ * their own values.
+ */
+#define XVIP_PAD_SINK                  0
+#define XVIP_PAD_SOURCE                        1
+
+/* Xilinx Video IP Control Registers */
+#define XVIP_CTRL_CONTROL                      0x0000
+#define XVIP_CTRL_CONTROL_SW_ENABLE            (1 << 0)
+#define XVIP_CTRL_CONTROL_REG_UPDATE           (1 << 1)
+#define XVIP_CTRL_CONTROL_BYPASS               (1 << 4)
+#define XVIP_CTRL_CONTROL_TEST_PATTERN         (1 << 5)
+#define XVIP_CTRL_CONTROL_FRAME_SYNC_RESET     (1 << 30)
+#define XVIP_CTRL_CONTROL_SW_RESET             (1 << 31)
+#define XVIP_CTRL_STATUS                       0x0004
+#define XVIP_CTRL_STATUS_PROC_STARTED          (1 << 0)
+#define XVIP_CTRL_STATUS_EOF                   (1 << 1)
+#define XVIP_CTRL_ERROR                                0x0008
+#define XVIP_CTRL_ERROR_SLAVE_EOL_EARLY                (1 << 0)
+#define XVIP_CTRL_ERROR_SLAVE_EOL_LATE         (1 << 1)
+#define XVIP_CTRL_ERROR_SLAVE_SOF_EARLY                (1 << 2)
+#define XVIP_CTRL_ERROR_SLAVE_SOF_LATE         (1 << 3)
+#define XVIP_CTRL_IRQ_ENABLE                   0x000c
+#define XVIP_CTRL_IRQ_ENABLE_PROC_STARTED      (1 << 0)
+#define XVIP_CTRL_IRQ_EOF                      (1 << 1)
+#define XVIP_CTRL_VERSION                      0x0010
+#define XVIP_CTRL_VERSION_MAJOR_MASK           (0xff << 24)
+#define XVIP_CTRL_VERSION_MAJOR_SHIFT          24
+#define XVIP_CTRL_VERSION_MINOR_MASK           (0xff << 16)
+#define XVIP_CTRL_VERSION_MINOR_SHIFT          16
+#define XVIP_CTRL_VERSION_REVISION_MASK                (0xf << 12)
+#define XVIP_CTRL_VERSION_REVISION_SHIFT       12
+#define XVIP_CTRL_VERSION_PATCH_MASK           (0xf << 8)
+#define XVIP_CTRL_VERSION_PATCH_SHIFT          8
+#define XVIP_CTRL_VERSION_INTERNAL_MASK                (0xff << 0)
+#define XVIP_CTRL_VERSION_INTERNAL_SHIFT       0
+
+/* Xilinx Video IP Timing Registers */
+#define XVIP_ACTIVE_SIZE                       0x0020
+#define XVIP_ACTIVE_VSIZE_MASK                 (0x7ff << 16)
+#define XVIP_ACTIVE_VSIZE_SHIFT                        16
+#define XVIP_ACTIVE_HSIZE_MASK                 (0x7ff << 0)
+#define XVIP_ACTIVE_HSIZE_SHIFT                        0
+#define XVIP_ENCODING                          0x0028
+#define XVIP_ENCODING_NBITS_8                  (0 << 4)
+#define XVIP_ENCODING_NBITS_10                 (1 << 4)
+#define XVIP_ENCODING_NBITS_12                 (2 << 4)
+#define XVIP_ENCODING_NBITS_16                 (3 << 4)
+#define XVIP_ENCODING_NBITS_MASK               (3 << 4)
+#define XVIP_ENCODING_NBITS_SHIFT              4
+#define XVIP_ENCODING_VIDEO_FORMAT_YUV422      (0 << 0)
+#define XVIP_ENCODING_VIDEO_FORMAT_YUV444      (1 << 0)
+#define XVIP_ENCODING_VIDEO_FORMAT_RGB         (2 << 0)
+#define XVIP_ENCODING_VIDEO_FORMAT_YUV420      (3 << 0)
+#define XVIP_ENCODING_VIDEO_FORMAT_MASK                (3 << 0)
+#define XVIP_ENCODING_VIDEO_FORMAT_SHIFT       0
+
+/**
+ * struct xvip_device - Xilinx Video IP device structure
+ * @subdev: V4L2 subdevice
+ * @dev: (OF) device
+ * @iomem: device I/O register space remapped to kernel virtual memory
+ * @clk: video core clock
+ * @saved_ctrl: saved control register for resume / suspend
+ */
+struct xvip_device {
+       struct v4l2_subdev subdev;
+       struct device *dev;
+       void __iomem *iomem;
+       struct clk *clk;
+       u32 saved_ctrl;
+};
+
+/**
+ * struct xvip_video_format - Xilinx Video IP video format description
+ * @vf_code: AXI4 video format code
+ * @width: AXI4 format width in bits per component
+ * @pattern: CFA pattern for Mono/Sensor formats
+ * @code: media bus format code
+ * @bpp: bytes per pixel (when stored in memory)
+ * @fourcc: V4L2 pixel format FCC identifier
+ * @description: format description, suitable for userspace
+ */
+struct xvip_video_format {
+       unsigned int vf_code;
+       unsigned int width;
+       const char *pattern;
+       unsigned int code;
+       unsigned int bpp;
+       u32 fourcc;
+       const char *description;
+};
+
+const struct xvip_video_format *xvip_get_format_by_code(unsigned int code);
+const struct xvip_video_format *xvip_get_format_by_fourcc(u32 fourcc);
+const struct xvip_video_format *xvip_of_get_format(struct device_node *node);
+void xvip_set_format_size(struct v4l2_mbus_framefmt *format,
+                         const struct v4l2_subdev_format *fmt);
+int xvip_enum_mbus_code(struct v4l2_subdev *subdev,
+                       struct v4l2_subdev_pad_config *cfg,
+                       struct v4l2_subdev_mbus_code_enum *code);
+int xvip_enum_frame_size(struct v4l2_subdev *subdev,
+                        struct v4l2_subdev_pad_config *cfg,
+                        struct v4l2_subdev_frame_size_enum *fse);
+
+static inline u32 xvip_read(struct xvip_device *xvip, u32 addr)
+{
+       return ioread32(xvip->iomem + addr);
+}
+
+static inline void xvip_write(struct xvip_device *xvip, u32 addr, u32 value)
+{
+       iowrite32(value, xvip->iomem + addr);
+}
+
+static inline void xvip_clr(struct xvip_device *xvip, u32 addr, u32 clr)
+{
+       xvip_write(xvip, addr, xvip_read(xvip, addr) & ~clr);
+}
+
+static inline void xvip_set(struct xvip_device *xvip, u32 addr, u32 set)
+{
+       xvip_write(xvip, addr, xvip_read(xvip, addr) | set);
+}
+
+void xvip_clr_or_set(struct xvip_device *xvip, u32 addr, u32 mask, bool set);
+void xvip_clr_and_set(struct xvip_device *xvip, u32 addr, u32 clr, u32 set);
+
+int xvip_init_resources(struct xvip_device *xvip);
+void xvip_cleanup_resources(struct xvip_device *xvip);
+
+static inline void xvip_reset(struct xvip_device *xvip)
+{
+       xvip_write(xvip, XVIP_CTRL_CONTROL, XVIP_CTRL_CONTROL_SW_RESET);
+}
+
+static inline void xvip_start(struct xvip_device *xvip)
+{
+       xvip_set(xvip, XVIP_CTRL_CONTROL,
+                XVIP_CTRL_CONTROL_SW_ENABLE | XVIP_CTRL_CONTROL_REG_UPDATE);
+}
+
+static inline void xvip_stop(struct xvip_device *xvip)
+{
+       xvip_clr(xvip, XVIP_CTRL_CONTROL, XVIP_CTRL_CONTROL_SW_ENABLE);
+}
+
+static inline void xvip_resume(struct xvip_device *xvip)
+{
+       xvip_write(xvip, XVIP_CTRL_CONTROL,
+                  xvip->saved_ctrl | XVIP_CTRL_CONTROL_SW_ENABLE);
+}
+
+static inline void xvip_suspend(struct xvip_device *xvip)
+{
+       xvip->saved_ctrl = xvip_read(xvip, XVIP_CTRL_CONTROL);
+       xvip_write(xvip, XVIP_CTRL_CONTROL,
+                  xvip->saved_ctrl & ~XVIP_CTRL_CONTROL_SW_ENABLE);
+}
+
+static inline void xvip_set_frame_size(struct xvip_device *xvip,
+                                      const struct v4l2_mbus_framefmt *format)
+{
+       xvip_write(xvip, XVIP_ACTIVE_SIZE,
+                  (format->height << XVIP_ACTIVE_VSIZE_SHIFT) |
+                  (format->width << XVIP_ACTIVE_HSIZE_SHIFT));
+}
+
+static inline void xvip_get_frame_size(struct xvip_device *xvip,
+                                      struct v4l2_mbus_framefmt *format)
+{
+       u32 reg;
+
+       reg = xvip_read(xvip, XVIP_ACTIVE_SIZE);
+       format->width = (reg & XVIP_ACTIVE_HSIZE_MASK) >>
+                       XVIP_ACTIVE_HSIZE_SHIFT;
+       format->height = (reg & XVIP_ACTIVE_VSIZE_MASK) >>
+                        XVIP_ACTIVE_VSIZE_SHIFT;
+}
+
+static inline void xvip_enable_reg_update(struct xvip_device *xvip)
+{
+       xvip_set(xvip, XVIP_CTRL_CONTROL, XVIP_CTRL_CONTROL_REG_UPDATE);
+}
+
+static inline void xvip_disable_reg_update(struct xvip_device *xvip)
+{
+       xvip_clr(xvip, XVIP_CTRL_CONTROL, XVIP_CTRL_CONTROL_REG_UPDATE);
+}
+
+static inline void xvip_print_version(struct xvip_device *xvip)
+{
+       u32 version;
+
+       version = xvip_read(xvip, XVIP_CTRL_VERSION);
+
+       dev_info(xvip->dev, "device found, version %u.%02x%x\n",
+                ((version & XVIP_CTRL_VERSION_MAJOR_MASK) >>
+                 XVIP_CTRL_VERSION_MAJOR_SHIFT),
+                ((version & XVIP_CTRL_VERSION_MINOR_MASK) >>
+                 XVIP_CTRL_VERSION_MINOR_SHIFT),
+                ((version & XVIP_CTRL_VERSION_REVISION_MASK) >>
+                 XVIP_CTRL_VERSION_REVISION_SHIFT));
+}
+
+#endif /* __XILINX_VIP_H__ */
diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c
new file mode 100644 (file)
index 0000000..7b7cb9c
--- /dev/null
@@ -0,0 +1,669 @@
+/*
+ * Xilinx Video IP Composite Device
+ *
+ * Copyright (C) 2013-2015 Ideas on Board
+ * Copyright (C) 2013-2015 Xilinx, Inc.
+ *
+ * Contacts: Hyun Kwon <hyun.kwon@xilinx.com>
+ *           Laurent Pinchart <laurent.pinchart@ideasonboard.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/list.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_graph.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <media/v4l2-async.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-of.h>
+
+#include "xilinx-dma.h"
+#include "xilinx-vipp.h"
+
+#define XVIPP_DMA_S2MM                         0
+#define XVIPP_DMA_MM2S                         1
+
+/**
+ * struct xvip_graph_entity - Entity in the video graph
+ * @list: list entry in a graph entities list
+ * @node: the entity's DT node
+ * @entity: media entity, from the corresponding V4L2 subdev
+ * @asd: subdev asynchronous registration information
+ * @subdev: V4L2 subdev
+ */
+struct xvip_graph_entity {
+       struct list_head list;
+       struct device_node *node;
+       struct media_entity *entity;
+
+       struct v4l2_async_subdev asd;
+       struct v4l2_subdev *subdev;
+};
+
+/* -----------------------------------------------------------------------------
+ * Graph Management
+ */
+
+static struct xvip_graph_entity *
+xvip_graph_find_entity(struct xvip_composite_device *xdev,
+                      const struct device_node *node)
+{
+       struct xvip_graph_entity *entity;
+
+       list_for_each_entry(entity, &xdev->entities, list) {
+               if (entity->node == node)
+                       return entity;
+       }
+
+       return NULL;
+}
+
+static int xvip_graph_build_one(struct xvip_composite_device *xdev,
+                               struct xvip_graph_entity *entity)
+{
+       u32 link_flags = MEDIA_LNK_FL_ENABLED;
+       struct media_entity *local = entity->entity;
+       struct media_entity *remote;
+       struct media_pad *local_pad;
+       struct media_pad *remote_pad;
+       struct xvip_graph_entity *ent;
+       struct v4l2_of_link link;
+       struct device_node *ep = NULL;
+       struct device_node *next;
+       int ret = 0;
+
+       dev_dbg(xdev->dev, "creating links for entity %s\n", local->name);
+
+       while (1) {
+               /* Get the next endpoint and parse its link. */
+               next = of_graph_get_next_endpoint(entity->node, ep);
+               if (next == NULL)
+                       break;
+
+               of_node_put(ep);
+               ep = next;
+
+               dev_dbg(xdev->dev, "processing endpoint %s\n", ep->full_name);
+
+               ret = v4l2_of_parse_link(ep, &link);
+               if (ret < 0) {
+                       dev_err(xdev->dev, "failed to parse link for %s\n",
+                               ep->full_name);
+                       continue;
+               }
+
+               /* Skip sink ports, they will be processed from the other end of
+                * the link.
+                */
+               if (link.local_port >= local->num_pads) {
+                       dev_err(xdev->dev, "invalid port number %u on %s\n",
+                               link.local_port, link.local_node->full_name);
+                       v4l2_of_put_link(&link);
+                       ret = -EINVAL;
+                       break;
+               }
+
+               local_pad = &local->pads[link.local_port];
+
+               if (local_pad->flags & MEDIA_PAD_FL_SINK) {
+                       dev_dbg(xdev->dev, "skipping sink port %s:%u\n",
+                               link.local_node->full_name, link.local_port);
+                       v4l2_of_put_link(&link);
+                       continue;
+               }
+
+               /* Skip DMA engines, they will be processed separately. */
+               if (link.remote_node == xdev->dev->of_node) {
+                       dev_dbg(xdev->dev, "skipping DMA port %s:%u\n",
+                               link.local_node->full_name, link.local_port);
+                       v4l2_of_put_link(&link);
+                       continue;
+               }
+
+               /* Find the remote entity. */
+               ent = xvip_graph_find_entity(xdev, link.remote_node);
+               if (ent == NULL) {
+                       dev_err(xdev->dev, "no entity found for %s\n",
+                               link.remote_node->full_name);
+                       v4l2_of_put_link(&link);
+                       ret = -ENODEV;
+                       break;
+               }
+
+               remote = ent->entity;
+
+               if (link.remote_port >= remote->num_pads) {
+                       dev_err(xdev->dev, "invalid port number %u on %s\n",
+                               link.remote_port, link.remote_node->full_name);
+                       v4l2_of_put_link(&link);
+                       ret = -EINVAL;
+                       break;
+               }
+
+               remote_pad = &remote->pads[link.remote_port];
+
+               v4l2_of_put_link(&link);
+
+               /* Create the media link. */
+               dev_dbg(xdev->dev, "creating %s:%u -> %s:%u link\n",
+                       local->name, local_pad->index,
+                       remote->name, remote_pad->index);
+
+               ret = media_entity_create_link(local, local_pad->index,
+                                              remote, remote_pad->index,
+                                              link_flags);
+               if (ret < 0) {
+                       dev_err(xdev->dev,
+                               "failed to create %s:%u -> %s:%u link\n",
+                               local->name, local_pad->index,
+                               remote->name, remote_pad->index);
+                       break;
+               }
+       }
+
+       of_node_put(ep);
+       return ret;
+}
+
+static struct xvip_dma *
+xvip_graph_find_dma(struct xvip_composite_device *xdev, unsigned int port)
+{
+       struct xvip_dma *dma;
+
+       list_for_each_entry(dma, &xdev->dmas, list) {
+               if (dma->port == port)
+                       return dma;
+       }
+
+       return NULL;
+}
+
+static int xvip_graph_build_dma(struct xvip_composite_device *xdev)
+{
+       u32 link_flags = MEDIA_LNK_FL_ENABLED;
+       struct device_node *node = xdev->dev->of_node;
+       struct media_entity *source;
+       struct media_entity *sink;
+       struct media_pad *source_pad;
+       struct media_pad *sink_pad;
+       struct xvip_graph_entity *ent;
+       struct v4l2_of_link link;
+       struct device_node *ep = NULL;
+       struct device_node *next;
+       struct xvip_dma *dma;
+       int ret = 0;
+
+       dev_dbg(xdev->dev, "creating links for DMA engines\n");
+
+       while (1) {
+               /* Get the next endpoint and parse its link. */
+               next = of_graph_get_next_endpoint(node, ep);
+               if (next == NULL)
+                       break;
+
+               of_node_put(ep);
+               ep = next;
+
+               dev_dbg(xdev->dev, "processing endpoint %s\n", ep->full_name);
+
+               ret = v4l2_of_parse_link(ep, &link);
+               if (ret < 0) {
+                       dev_err(xdev->dev, "failed to parse link for %s\n",
+                               ep->full_name);
+                       continue;
+               }
+
+               /* Find the DMA engine. */
+               dma = xvip_graph_find_dma(xdev, link.local_port);
+               if (dma == NULL) {
+                       dev_err(xdev->dev, "no DMA engine found for port %u\n",
+                               link.local_port);
+                       v4l2_of_put_link(&link);
+                       ret = -EINVAL;
+                       break;
+               }
+
+               dev_dbg(xdev->dev, "creating link for DMA engine %s\n",
+                       dma->video.name);
+
+               /* Find the remote entity. */
+               ent = xvip_graph_find_entity(xdev, link.remote_node);
+               if (ent == NULL) {
+                       dev_err(xdev->dev, "no entity found for %s\n",
+                               link.remote_node->full_name);
+                       v4l2_of_put_link(&link);
+                       ret = -ENODEV;
+                       break;
+               }
+
+               if (link.remote_port >= ent->entity->num_pads) {
+                       dev_err(xdev->dev, "invalid port number %u on %s\n",
+                               link.remote_port, link.remote_node->full_name);
+                       v4l2_of_put_link(&link);
+                       ret = -EINVAL;
+                       break;
+               }
+
+               if (dma->pad.flags & MEDIA_PAD_FL_SOURCE) {
+                       source = &dma->video.entity;
+                       source_pad = &dma->pad;
+                       sink = ent->entity;
+                       sink_pad = &sink->pads[link.remote_port];
+               } else {
+                       source = ent->entity;
+                       source_pad = &source->pads[link.remote_port];
+                       sink = &dma->video.entity;
+                       sink_pad = &dma->pad;
+               }
+
+               v4l2_of_put_link(&link);
+
+               /* Create the media link. */
+               dev_dbg(xdev->dev, "creating %s:%u -> %s:%u link\n",
+                       source->name, source_pad->index,
+                       sink->name, sink_pad->index);
+
+               ret = media_entity_create_link(source, source_pad->index,
+                                              sink, sink_pad->index,
+                                              link_flags);
+               if (ret < 0) {
+                       dev_err(xdev->dev,
+                               "failed to create %s:%u -> %s:%u link\n",
+                               source->name, source_pad->index,
+                               sink->name, sink_pad->index);
+                       break;
+               }
+       }
+
+       of_node_put(ep);
+       return ret;
+}
+
+static int xvip_graph_notify_complete(struct v4l2_async_notifier *notifier)
+{
+       struct xvip_composite_device *xdev =
+               container_of(notifier, struct xvip_composite_device, notifier);
+       struct xvip_graph_entity *entity;
+       int ret;
+
+       dev_dbg(xdev->dev, "notify complete, all subdevs registered\n");
+
+       /* Create links for every entity. */
+       list_for_each_entry(entity, &xdev->entities, list) {
+               ret = xvip_graph_build_one(xdev, entity);
+               if (ret < 0)
+                       return ret;
+       }
+
+       /* Create links for DMA channels. */
+       ret = xvip_graph_build_dma(xdev);
+       if (ret < 0)
+               return ret;
+
+       ret = v4l2_device_register_subdev_nodes(&xdev->v4l2_dev);
+       if (ret < 0)
+               dev_err(xdev->dev, "failed to register subdev nodes\n");
+
+       return ret;
+}
+
+static int xvip_graph_notify_bound(struct v4l2_async_notifier *notifier,
+                                  struct v4l2_subdev *subdev,
+                                  struct v4l2_async_subdev *asd)
+{
+       struct xvip_composite_device *xdev =
+               container_of(notifier, struct xvip_composite_device, notifier);
+       struct xvip_graph_entity *entity;
+
+       /* Locate the entity corresponding to the bound subdev and store the
+        * subdev pointer.
+        */
+       list_for_each_entry(entity, &xdev->entities, list) {
+               if (entity->node != subdev->dev->of_node)
+                       continue;
+
+               if (entity->subdev) {
+                       dev_err(xdev->dev, "duplicate subdev for node %s\n",
+                               entity->node->full_name);
+                       return -EINVAL;
+               }
+
+               dev_dbg(xdev->dev, "subdev %s bound\n", subdev->name);
+               entity->entity = &subdev->entity;
+               entity->subdev = subdev;
+               return 0;
+       }
+
+       dev_err(xdev->dev, "no entity for subdev %s\n", subdev->name);
+       return -EINVAL;
+}
+
+static int xvip_graph_parse_one(struct xvip_composite_device *xdev,
+                               struct device_node *node)
+{
+       struct xvip_graph_entity *entity;
+       struct device_node *remote;
+       struct device_node *ep = NULL;
+       struct device_node *next;
+       int ret = 0;
+
+       dev_dbg(xdev->dev, "parsing node %s\n", node->full_name);
+
+       while (1) {
+               next = of_graph_get_next_endpoint(node, ep);
+               if (next == NULL)
+                       break;
+
+               of_node_put(ep);
+               ep = next;
+
+               dev_dbg(xdev->dev, "handling endpoint %s\n", ep->full_name);
+
+               remote = of_graph_get_remote_port_parent(ep);
+               if (remote == NULL) {
+                       ret = -EINVAL;
+                       break;
+               }
+
+               /* Skip entities that we have already processed. */
+               if (remote == xdev->dev->of_node ||
+                   xvip_graph_find_entity(xdev, remote)) {
+                       of_node_put(remote);
+                       continue;
+               }
+
+               entity = devm_kzalloc(xdev->dev, sizeof(*entity), GFP_KERNEL);
+               if (entity == NULL) {
+                       of_node_put(remote);
+                       ret = -ENOMEM;
+                       break;
+               }
+
+               entity->node = remote;
+               entity->asd.match_type = V4L2_ASYNC_MATCH_OF;
+               entity->asd.match.of.node = remote;
+               list_add_tail(&entity->list, &xdev->entities);
+               xdev->num_subdevs++;
+       }
+
+       of_node_put(ep);
+       return ret;
+}
+
+static int xvip_graph_parse(struct xvip_composite_device *xdev)
+{
+       struct xvip_graph_entity *entity;
+       int ret;
+
+       /*
+        * Walk the links to parse the full graph. Start by parsing the
+        * composite node and then parse entities in turn. The list_for_each
+        * loop will handle entities added at the end of the list while walking
+        * the links.
+        */
+       ret = xvip_graph_parse_one(xdev, xdev->dev->of_node);
+       if (ret < 0)
+               return 0;
+
+       list_for_each_entry(entity, &xdev->entities, list) {
+               ret = xvip_graph_parse_one(xdev, entity->node);
+               if (ret < 0)
+                       break;
+       }
+
+       return ret;
+}
+
+static int xvip_graph_dma_init_one(struct xvip_composite_device *xdev,
+                                  struct device_node *node)
+{
+       struct xvip_dma *dma;
+       enum v4l2_buf_type type;
+       const char *direction;
+       unsigned int index;
+       int ret;
+
+       ret = of_property_read_string(node, "direction", &direction);
+       if (ret < 0)
+               return ret;
+
+       if (strcmp(direction, "input") == 0)
+               type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       else if (strcmp(direction, "output") == 0)
+               type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+       else
+               return -EINVAL;
+
+       of_property_read_u32(node, "reg", &index);
+
+       dma = devm_kzalloc(xdev->dev, sizeof(*dma), GFP_KERNEL);
+       if (dma == NULL)
+               return -ENOMEM;
+
+       ret = xvip_dma_init(xdev, dma, type, index);
+       if (ret < 0) {
+               dev_err(xdev->dev, "%s initialization failed\n",
+                       node->full_name);
+               return ret;
+       }
+
+       list_add_tail(&dma->list, &xdev->dmas);
+
+       xdev->v4l2_caps |= type == V4L2_BUF_TYPE_VIDEO_CAPTURE
+                        ? V4L2_CAP_VIDEO_CAPTURE : V4L2_CAP_VIDEO_OUTPUT;
+
+       return 0;
+}
+
+static int xvip_graph_dma_init(struct xvip_composite_device *xdev)
+{
+       struct device_node *ports;
+       struct device_node *port;
+       int ret;
+
+       ports = of_get_child_by_name(xdev->dev->of_node, "ports");
+       if (ports == NULL) {
+               dev_err(xdev->dev, "ports node not present\n");
+               return -EINVAL;
+       }
+
+       for_each_child_of_node(ports, port) {
+               ret = xvip_graph_dma_init_one(xdev, port);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static void xvip_graph_cleanup(struct xvip_composite_device *xdev)
+{
+       struct xvip_graph_entity *entityp;
+       struct xvip_graph_entity *entity;
+       struct xvip_dma *dmap;
+       struct xvip_dma *dma;
+
+       v4l2_async_notifier_unregister(&xdev->notifier);
+
+       list_for_each_entry_safe(entity, entityp, &xdev->entities, list) {
+               of_node_put(entity->node);
+               list_del(&entity->list);
+       }
+
+       list_for_each_entry_safe(dma, dmap, &xdev->dmas, list) {
+               xvip_dma_cleanup(dma);
+               list_del(&dma->list);
+       }
+}
+
+static int xvip_graph_init(struct xvip_composite_device *xdev)
+{
+       struct xvip_graph_entity *entity;
+       struct v4l2_async_subdev **subdevs = NULL;
+       unsigned int num_subdevs;
+       unsigned int i;
+       int ret;
+
+       /* Init the DMA channels. */
+       ret = xvip_graph_dma_init(xdev);
+       if (ret < 0) {
+               dev_err(xdev->dev, "DMA initialization failed\n");
+               goto done;
+       }
+
+       /* Parse the graph to extract a list of subdevice DT nodes. */
+       ret = xvip_graph_parse(xdev);
+       if (ret < 0) {
+               dev_err(xdev->dev, "graph parsing failed\n");
+               goto done;
+       }
+
+       if (!xdev->num_subdevs) {
+               dev_err(xdev->dev, "no subdev found in graph\n");
+               goto done;
+       }
+
+       /* Register the subdevices notifier. */
+       num_subdevs = xdev->num_subdevs;
+       subdevs = devm_kzalloc(xdev->dev, sizeof(*subdevs) * num_subdevs,
+                              GFP_KERNEL);
+       if (subdevs == NULL) {
+               ret = -ENOMEM;
+               goto done;
+       }
+
+       i = 0;
+       list_for_each_entry(entity, &xdev->entities, list)
+               subdevs[i++] = &entity->asd;
+
+       xdev->notifier.subdevs = subdevs;
+       xdev->notifier.num_subdevs = num_subdevs;
+       xdev->notifier.bound = xvip_graph_notify_bound;
+       xdev->notifier.complete = xvip_graph_notify_complete;
+
+       ret = v4l2_async_notifier_register(&xdev->v4l2_dev, &xdev->notifier);
+       if (ret < 0) {
+               dev_err(xdev->dev, "notifier registration failed\n");
+               goto done;
+       }
+
+       ret = 0;
+
+done:
+       if (ret < 0)
+               xvip_graph_cleanup(xdev);
+
+       return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * Media Controller and V4L2
+ */
+
+static void xvip_composite_v4l2_cleanup(struct xvip_composite_device *xdev)
+{
+       v4l2_device_unregister(&xdev->v4l2_dev);
+       media_device_unregister(&xdev->media_dev);
+}
+
+static int xvip_composite_v4l2_init(struct xvip_composite_device *xdev)
+{
+       int ret;
+
+       xdev->media_dev.dev = xdev->dev;
+       strlcpy(xdev->media_dev.model, "Xilinx Video Composite Device",
+               sizeof(xdev->media_dev.model));
+       xdev->media_dev.hw_revision = 0;
+
+       ret = media_device_register(&xdev->media_dev);
+       if (ret < 0) {
+               dev_err(xdev->dev, "media device registration failed (%d)\n",
+                       ret);
+               return ret;
+       }
+
+       xdev->v4l2_dev.mdev = &xdev->media_dev;
+       ret = v4l2_device_register(xdev->dev, &xdev->v4l2_dev);
+       if (ret < 0) {
+               dev_err(xdev->dev, "V4L2 device registration failed (%d)\n",
+                       ret);
+               media_device_unregister(&xdev->media_dev);
+               return ret;
+       }
+
+       return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Platform Device Driver
+ */
+
+static int xvip_composite_probe(struct platform_device *pdev)
+{
+       struct xvip_composite_device *xdev;
+       int ret;
+
+       xdev = devm_kzalloc(&pdev->dev, sizeof(*xdev), GFP_KERNEL);
+       if (!xdev)
+               return -ENOMEM;
+
+       xdev->dev = &pdev->dev;
+       INIT_LIST_HEAD(&xdev->entities);
+       INIT_LIST_HEAD(&xdev->dmas);
+
+       ret = xvip_composite_v4l2_init(xdev);
+       if (ret < 0)
+               return ret;
+
+       ret = xvip_graph_init(xdev);
+       if (ret < 0)
+               goto error;
+
+       platform_set_drvdata(pdev, xdev);
+
+       dev_info(xdev->dev, "device registered\n");
+
+       return 0;
+
+error:
+       xvip_composite_v4l2_cleanup(xdev);
+       return ret;
+}
+
+static int xvip_composite_remove(struct platform_device *pdev)
+{
+       struct xvip_composite_device *xdev = platform_get_drvdata(pdev);
+
+       xvip_graph_cleanup(xdev);
+       xvip_composite_v4l2_cleanup(xdev);
+
+       return 0;
+}
+
+static const struct of_device_id xvip_composite_of_id_table[] = {
+       { .compatible = "xlnx,video" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, xvip_composite_of_id_table);
+
+static struct platform_driver xvip_composite_driver = {
+       .driver = {
+               .name = "xilinx-video",
+               .of_match_table = xvip_composite_of_id_table,
+       },
+       .probe = xvip_composite_probe,
+       .remove = xvip_composite_remove,
+};
+
+module_platform_driver(xvip_composite_driver);
+
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_DESCRIPTION("Xilinx Video IP Composite Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/xilinx/xilinx-vipp.h b/drivers/media/platform/xilinx/xilinx-vipp.h
new file mode 100644 (file)
index 0000000..faf6b6e
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Xilinx Video IP Composite Device
+ *
+ * Copyright (C) 2013-2015 Ideas on Board
+ * Copyright (C) 2013-2015 Xilinx, Inc.
+ *
+ * Contacts: Hyun Kwon <hyun.kwon@xilinx.com>
+ *           Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __XILINX_VIPP_H__
+#define __XILINX_VIPP_H__
+
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <media/media-device.h>
+#include <media/v4l2-async.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+
+/**
+ * struct xvip_composite_device - Xilinx Video IP device structure
+ * @v4l2_dev: V4L2 device
+ * @media_dev: media device
+ * @dev: (OF) device
+ * @notifier: V4L2 asynchronous subdevs notifier
+ * @entities: entities in the graph as a list of xvip_graph_entity
+ * @num_subdevs: number of subdevs in the pipeline
+ * @dmas: list of DMA channels at the pipeline output and input
+ * @v4l2_caps: V4L2 capabilities of the whole device (see VIDIOC_QUERYCAP)
+ */
+struct xvip_composite_device {
+       struct v4l2_device v4l2_dev;
+       struct media_device media_dev;
+       struct device *dev;
+
+       struct v4l2_async_notifier notifier;
+       struct list_head entities;
+       unsigned int num_subdevs;
+
+       struct list_head dmas;
+       u32 v4l2_caps;
+};
+
+#endif /* __XILINX_VIPP_H__ */
diff --git a/drivers/media/platform/xilinx/xilinx-vtc.c b/drivers/media/platform/xilinx/xilinx-vtc.c
new file mode 100644 (file)
index 0000000..01c750e
--- /dev/null
@@ -0,0 +1,380 @@
+/*
+ * Xilinx Video Timing Controller
+ *
+ * Copyright (C) 2013-2015 Ideas on Board
+ * Copyright (C) 2013-2015 Xilinx, Inc.
+ *
+ * Contacts: Hyun Kwon <hyun.kwon@xilinx.com>
+ *           Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "xilinx-vip.h"
+#include "xilinx-vtc.h"
+
+#define XVTC_CONTROL_FIELD_ID_POL_SRC          (1 << 26)
+#define XVTC_CONTROL_ACTIVE_CHROMA_POL_SRC     (1 << 25)
+#define XVTC_CONTROL_ACTIVE_VIDEO_POL_SRC      (1 << 24)
+#define XVTC_CONTROL_HSYNC_POL_SRC             (1 << 23)
+#define XVTC_CONTROL_VSYNC_POL_SRC             (1 << 22)
+#define XVTC_CONTROL_HBLANK_POL_SRC            (1 << 21)
+#define XVTC_CONTROL_VBLANK_POL_SRC            (1 << 20)
+#define XVTC_CONTROL_CHROMA_SRC                        (1 << 18)
+#define XVTC_CONTROL_VBLANK_HOFF_SRC           (1 << 17)
+#define XVTC_CONTROL_VSYNC_END_SRC             (1 << 16)
+#define XVTC_CONTROL_VSYNC_START_SRC           (1 << 15)
+#define XVTC_CONTROL_ACTIVE_VSIZE_SRC          (1 << 14)
+#define XVTC_CONTROL_FRAME_VSIZE_SRC           (1 << 13)
+#define XVTC_CONTROL_HSYNC_END_SRC             (1 << 11)
+#define XVTC_CONTROL_HSYNC_START_SRC           (1 << 10)
+#define XVTC_CONTROL_ACTIVE_HSIZE_SRC          (1 << 9)
+#define XVTC_CONTROL_FRAME_HSIZE_SRC           (1 << 8)
+#define XVTC_CONTROL_SYNC_ENABLE               (1 << 5)
+#define XVTC_CONTROL_DET_ENABLE                        (1 << 3)
+#define XVTC_CONTROL_GEN_ENABLE                        (1 << 2)
+
+#define XVTC_STATUS_FSYNC(n)                   ((n) << 16)
+#define XVTC_STATUS_GEN_ACTIVE_VIDEO           (1 << 13)
+#define XVTC_STATUS_GEN_VBLANK                 (1 << 12)
+#define XVTC_STATUS_DET_ACTIVE_VIDEO           (1 << 11)
+#define XVTC_STATUS_DET_VBLANK                 (1 << 10)
+#define XVTC_STATUS_LOCK_LOSS                  (1 << 9)
+#define XVTC_STATUS_LOCK                       (1 << 8)
+
+#define XVTC_ERROR_ACTIVE_CHROMA_LOCK          (1 << 21)
+#define XVTC_ERROR_ACTIVE_VIDEO_LOCK           (1 << 20)
+#define XVTC_ERROR_HSYNC_LOCK                  (1 << 19)
+#define XVTC_ERROR_VSYNC_LOCK                  (1 << 18)
+#define XVTC_ERROR_HBLANK_LOCK                 (1 << 17)
+#define XVTC_ERROR_VBLANK_LOCK                 (1 << 16)
+
+#define XVTC_IRQ_ENABLE_FSYNC(n)               ((n) << 16)
+#define XVTC_IRQ_ENABLE_GEN_ACTIVE_VIDEO       (1 << 13)
+#define XVTC_IRQ_ENABLE_GEN_VBLANK             (1 << 12)
+#define XVTC_IRQ_ENABLE_DET_ACTIVE_VIDEO       (1 << 11)
+#define XVTC_IRQ_ENABLE_DET_VBLANK             (1 << 10)
+#define XVTC_IRQ_ENABLE_LOCK_LOSS              (1 << 9)
+#define XVTC_IRQ_ENABLE_LOCK                   (1 << 8)
+
+/*
+ * The following registers exist in two blocks, one at 0x0020 for the detector
+ * and one at 0x0060 for the generator.
+ */
+
+#define XVTC_DETECTOR_OFFSET                   0x0020
+#define XVTC_GENERATOR_OFFSET                  0x0060
+
+#define XVTC_ACTIVE_SIZE                       0x0000
+#define XVTC_ACTIVE_VSIZE_SHIFT                        16
+#define XVTC_ACTIVE_VSIZE_MASK                 (0x1fff << 16)
+#define XVTC_ACTIVE_HSIZE_SHIFT                        0
+#define XVTC_ACTIVE_HSIZE_MASK                 (0x1fff << 0)
+
+#define XVTC_TIMING_STATUS                     0x0004
+#define XVTC_TIMING_STATUS_ACTIVE_VIDEO                (1 << 2)
+#define XVTC_TIMING_STATUS_VBLANK              (1 << 1)
+#define XVTC_TIMING_STATUS_LOCKED              (1 << 0)
+
+#define XVTC_ENCODING                          0x0008
+#define XVTC_ENCODING_CHROMA_PARITY_SHIFT      8
+#define XVTC_ENCODING_CHROMA_PARITY_MASK       (3 << 8)
+#define XVTC_ENCODING_CHROMA_PARITY_EVEN_ALL   (0 << 8)
+#define XVTC_ENCODING_CHROMA_PARITY_ODD_ALL    (1 << 8)
+#define XVTC_ENCODING_CHROMA_PARITY_EVEN_EVEN  (2 << 8)
+#define XVTC_ENCODING_CHROMA_PARITY_ODD_EVEN   (3 << 8)
+#define XVTC_ENCODING_VIDEO_FORMAT_SHIFT       0
+#define XVTC_ENCODING_VIDEO_FORMAT_MASK                (0xf << 0)
+#define XVTC_ENCODING_VIDEO_FORMAT_YUV422      (0 << 0)
+#define XVTC_ENCODING_VIDEO_FORMAT_YUV444      (1 << 0)
+#define XVTC_ENCODING_VIDEO_FORMAT_RGB         (2 << 0)
+#define XVTC_ENCODING_VIDEO_FORMAT_YUV420      (3 << 0)
+
+#define XVTC_POLARITY                          0x000c
+#define XVTC_POLARITY_ACTIVE_CHROMA_POL                (1 << 5)
+#define XVTC_POLARITY_ACTIVE_VIDEO_POL         (1 << 4)
+#define XVTC_POLARITY_HSYNC_POL                        (1 << 3)
+#define XVTC_POLARITY_VSYNC_POL                        (1 << 2)
+#define XVTC_POLARITY_HBLANK_POL               (1 << 1)
+#define XVTC_POLARITY_VBLANK_POL               (1 << 0)
+
+#define XVTC_HSIZE                             0x0010
+#define XVTC_HSIZE_MASK                                (0x1fff << 0)
+
+#define XVTC_VSIZE                             0x0014
+#define XVTC_VSIZE_MASK                                (0x1fff << 0)
+
+#define XVTC_HSYNC                             0x0018
+#define XVTC_HSYNC_END_SHIFT                   16
+#define XVTC_HSYNC_END_MASK                    (0x1fff << 16)
+#define XVTC_HSYNC_START_SHIFT                 0
+#define XVTC_HSYNC_START_MASK                  (0x1fff << 0)
+
+#define XVTC_F0_VBLANK_H                       0x001c
+#define XVTC_F0_VBLANK_HEND_SHIFT              16
+#define XVTC_F0_VBLANK_HEND_MASK               (0x1fff << 16)
+#define XVTC_F0_VBLANK_HSTART_SHIFT            0
+#define XVTC_F0_VBLANK_HSTART_MASK             (0x1fff << 0)
+
+#define XVTC_F0_VSYNC_V                                0x0020
+#define XVTC_F0_VSYNC_VEND_SHIFT               16
+#define XVTC_F0_VSYNC_VEND_MASK                        (0x1fff << 16)
+#define XVTC_F0_VSYNC_VSTART_SHIFT             0
+#define XVTC_F0_VSYNC_VSTART_MASK              (0x1fff << 0)
+
+#define XVTC_F0_VSYNC_H                                0x0024
+#define XVTC_F0_VSYNC_HEND_SHIFT               16
+#define XVTC_F0_VSYNC_HEND_MASK                        (0x1fff << 16)
+#define XVTC_F0_VSYNC_HSTART_SHIFT             0
+#define XVTC_F0_VSYNC_HSTART_MASK              (0x1fff << 0)
+
+#define XVTC_FRAME_SYNC_CONFIG(n)              (0x0100 + 4 * (n))
+#define XVTC_FRAME_SYNC_V_START_SHIFT          16
+#define XVTC_FRAME_SYNC_V_START_MASK           (0x1fff << 16)
+#define XVTC_FRAME_SYNC_H_START_SHIFT          0
+#define XVTC_FRAME_SYNC_H_START_MASK           (0x1fff << 0)
+
+#define XVTC_GENERATOR_GLOBAL_DELAY            0x0104
+
+/**
+ * struct xvtc_device - Xilinx Video Timing Controller device structure
+ * @xvip: Xilinx Video IP device
+ * @list: entry in the global VTC list
+ * @has_detector: the VTC has a timing detector
+ * @has_generator: the VTC has a timing generator
+ * @config: generator timings configuration
+ */
+struct xvtc_device {
+       struct xvip_device xvip;
+       struct list_head list;
+
+       bool has_detector;
+       bool has_generator;
+
+       struct xvtc_config config;
+};
+
+static LIST_HEAD(xvtc_list);
+static DEFINE_MUTEX(xvtc_lock);
+
+static inline void xvtc_gen_write(struct xvtc_device *xvtc, u32 addr, u32 value)
+{
+       xvip_write(&xvtc->xvip, XVTC_GENERATOR_OFFSET + addr, value);
+}
+
+/* -----------------------------------------------------------------------------
+ * Generator Operations
+ */
+
+int xvtc_generator_start(struct xvtc_device *xvtc,
+                        const struct xvtc_config *config)
+{
+       int ret;
+
+       if (!xvtc->has_generator)
+               return -ENXIO;
+
+       ret = clk_prepare_enable(xvtc->xvip.clk);
+       if (ret < 0)
+               return ret;
+
+       /* We don't care about the chroma active signal, encoding parameters are
+        * not important for now.
+        */
+       xvtc_gen_write(xvtc, XVTC_POLARITY,
+                      XVTC_POLARITY_ACTIVE_CHROMA_POL |
+                      XVTC_POLARITY_ACTIVE_VIDEO_POL |
+                      XVTC_POLARITY_HSYNC_POL | XVTC_POLARITY_VSYNC_POL |
+                      XVTC_POLARITY_HBLANK_POL | XVTC_POLARITY_VBLANK_POL);
+
+       /* Hardcode the polarity to active high, as required by the video in to
+        * AXI4-stream core.
+        */
+       xvtc_gen_write(xvtc, XVTC_ENCODING, 0);
+
+       /* Configure the timings. The VBLANK and VSYNC signals assertion and
+        * deassertion are hardcoded to the first pixel of the line.
+        */
+       xvtc_gen_write(xvtc, XVTC_ACTIVE_SIZE,
+                      (config->vblank_start << XVTC_ACTIVE_VSIZE_SHIFT) |
+                      (config->hblank_start << XVTC_ACTIVE_HSIZE_SHIFT));
+       xvtc_gen_write(xvtc, XVTC_HSIZE, config->hsize);
+       xvtc_gen_write(xvtc, XVTC_VSIZE, config->vsize);
+       xvtc_gen_write(xvtc, XVTC_HSYNC,
+                      (config->hsync_end << XVTC_HSYNC_END_SHIFT) |
+                      (config->hsync_start << XVTC_HSYNC_START_SHIFT));
+       xvtc_gen_write(xvtc, XVTC_F0_VBLANK_H, 0);
+       xvtc_gen_write(xvtc, XVTC_F0_VSYNC_V,
+                      (config->vsync_end << XVTC_F0_VSYNC_VEND_SHIFT) |
+                      (config->vsync_start << XVTC_F0_VSYNC_VSTART_SHIFT));
+       xvtc_gen_write(xvtc, XVTC_F0_VSYNC_H, 0);
+
+       /* Enable the generator. Set the source of all generator parameters to
+        * generator registers.
+        */
+       xvip_write(&xvtc->xvip, XVIP_CTRL_CONTROL,
+                  XVTC_CONTROL_ACTIVE_CHROMA_POL_SRC |
+                  XVTC_CONTROL_ACTIVE_VIDEO_POL_SRC |
+                  XVTC_CONTROL_HSYNC_POL_SRC | XVTC_CONTROL_VSYNC_POL_SRC |
+                  XVTC_CONTROL_HBLANK_POL_SRC | XVTC_CONTROL_VBLANK_POL_SRC |
+                  XVTC_CONTROL_CHROMA_SRC | XVTC_CONTROL_VBLANK_HOFF_SRC |
+                  XVTC_CONTROL_VSYNC_END_SRC | XVTC_CONTROL_VSYNC_START_SRC |
+                  XVTC_CONTROL_ACTIVE_VSIZE_SRC |
+                  XVTC_CONTROL_FRAME_VSIZE_SRC | XVTC_CONTROL_HSYNC_END_SRC |
+                  XVTC_CONTROL_HSYNC_START_SRC |
+                  XVTC_CONTROL_ACTIVE_HSIZE_SRC |
+                  XVTC_CONTROL_FRAME_HSIZE_SRC | XVTC_CONTROL_GEN_ENABLE |
+                  XVIP_CTRL_CONTROL_REG_UPDATE);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(xvtc_generator_start);
+
+int xvtc_generator_stop(struct xvtc_device *xvtc)
+{
+       if (!xvtc->has_generator)
+               return -ENXIO;
+
+       xvip_write(&xvtc->xvip, XVIP_CTRL_CONTROL, 0);
+
+       clk_disable_unprepare(xvtc->xvip.clk);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(xvtc_generator_stop);
+
+struct xvtc_device *xvtc_of_get(struct device_node *np)
+{
+       struct device_node *xvtc_node;
+       struct xvtc_device *found = NULL;
+       struct xvtc_device *xvtc;
+
+       if (!of_find_property(np, "xlnx,vtc", NULL))
+               return NULL;
+
+       xvtc_node = of_parse_phandle(np, "xlnx,vtc", 0);
+       if (xvtc_node == NULL)
+               return ERR_PTR(-EINVAL);
+
+       mutex_lock(&xvtc_lock);
+       list_for_each_entry(xvtc, &xvtc_list, list) {
+               if (xvtc->xvip.dev->of_node == xvtc_node) {
+                       found = xvtc;
+                       break;
+               }
+       }
+       mutex_unlock(&xvtc_lock);
+
+       of_node_put(xvtc_node);
+
+       if (!found)
+               return ERR_PTR(-EPROBE_DEFER);
+
+       return found;
+}
+EXPORT_SYMBOL_GPL(xvtc_of_get);
+
+void xvtc_put(struct xvtc_device *xvtc)
+{
+}
+EXPORT_SYMBOL_GPL(xvtc_put);
+
+/* -----------------------------------------------------------------------------
+ * Registration and Unregistration
+ */
+
+static void xvtc_register_device(struct xvtc_device *xvtc)
+{
+       mutex_lock(&xvtc_lock);
+       list_add_tail(&xvtc->list, &xvtc_list);
+       mutex_unlock(&xvtc_lock);
+}
+
+static void xvtc_unregister_device(struct xvtc_device *xvtc)
+{
+       mutex_lock(&xvtc_lock);
+       list_del(&xvtc->list);
+       mutex_unlock(&xvtc_lock);
+}
+
+/* -----------------------------------------------------------------------------
+ * Platform Device Driver
+ */
+
+static int xvtc_parse_of(struct xvtc_device *xvtc)
+{
+       struct device_node *node = xvtc->xvip.dev->of_node;
+
+       xvtc->has_detector = of_property_read_bool(node, "xlnx,detector");
+       xvtc->has_generator = of_property_read_bool(node, "xlnx,generator");
+
+       return 0;
+}
+
+static int xvtc_probe(struct platform_device *pdev)
+{
+       struct xvtc_device *xvtc;
+       int ret;
+
+       xvtc = devm_kzalloc(&pdev->dev, sizeof(*xvtc), GFP_KERNEL);
+       if (!xvtc)
+               return -ENOMEM;
+
+       xvtc->xvip.dev = &pdev->dev;
+
+       ret = xvtc_parse_of(xvtc);
+       if (ret < 0)
+               return ret;
+
+       ret = xvip_init_resources(&xvtc->xvip);
+       if (ret < 0)
+               return ret;
+
+       platform_set_drvdata(pdev, xvtc);
+
+       xvip_print_version(&xvtc->xvip);
+
+       xvtc_register_device(xvtc);
+
+       return 0;
+}
+
+static int xvtc_remove(struct platform_device *pdev)
+{
+       struct xvtc_device *xvtc = platform_get_drvdata(pdev);
+
+       xvtc_unregister_device(xvtc);
+
+       xvip_cleanup_resources(&xvtc->xvip);
+
+       return 0;
+}
+
+static const struct of_device_id xvtc_of_id_table[] = {
+       { .compatible = "xlnx,v-tc-6.1" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, xvtc_of_id_table);
+
+static struct platform_driver xvtc_driver = {
+       .driver = {
+               .name = "xilinx-vtc",
+               .of_match_table = xvtc_of_id_table,
+       },
+       .probe = xvtc_probe,
+       .remove = xvtc_remove,
+};
+
+module_platform_driver(xvtc_driver);
+
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_DESCRIPTION("Xilinx Video Timing Controller Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/xilinx/xilinx-vtc.h b/drivers/media/platform/xilinx/xilinx-vtc.h
new file mode 100644 (file)
index 0000000..e1bb2cf
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Xilinx Video Timing Controller
+ *
+ * Copyright (C) 2013-2015 Ideas on Board
+ * Copyright (C) 2013-2015 Xilinx, Inc.
+ *
+ * Contacts: Hyun Kwon <hyun.kwon@xilinx.com>
+ *           Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __XILINX_VTC_H__
+#define __XILINX_VTC_H__
+
+struct device_node;
+struct xvtc_device;
+
+#define XVTC_MAX_HSIZE                 8191
+#define XVTC_MAX_VSIZE                 8191
+
+struct xvtc_config {
+       unsigned int hblank_start;
+       unsigned int hsync_start;
+       unsigned int hsync_end;
+       unsigned int hsize;
+       unsigned int vblank_start;
+       unsigned int vsync_start;
+       unsigned int vsync_end;
+       unsigned int vsize;
+};
+
+struct xvtc_device *xvtc_of_get(struct device_node *np);
+void xvtc_put(struct xvtc_device *xvtc);
+
+int xvtc_generator_start(struct xvtc_device *xvtc,
+                        const struct xvtc_config *config);
+int xvtc_generator_stop(struct xvtc_device *xvtc);
+
+#endif /* __XILINX_VTC_H__ */
index b8f36445516b167d222103d58d22fa819df521a5..a93f681aa9d67c2f5dcb9bc6871f7239940960bd 100644 (file)
@@ -347,6 +347,7 @@ static int wl1273_fm_set_tx_freq(struct wl1273_device *radio, unsigned int freq)
 {
        struct wl1273_core *core = radio->core;
        int r = 0;
+       unsigned long t;
 
        if (freq < WL1273_BAND_TX_LOW) {
                dev_err(radio->dev,
@@ -378,11 +379,11 @@ static int wl1273_fm_set_tx_freq(struct wl1273_device *radio, unsigned int freq)
        reinit_completion(&radio->busy);
 
        /* wait for the FR IRQ */
-       r = wait_for_completion_timeout(&radio->busy, msecs_to_jiffies(2000));
-       if (!r)
+       t = wait_for_completion_timeout(&radio->busy, msecs_to_jiffies(2000));
+       if (!t)
                return -ETIMEDOUT;
 
-       dev_dbg(radio->dev, "WL1273_CHANL_SET: %d\n", r);
+       dev_dbg(radio->dev, "WL1273_CHANL_SET: %lu\n", t);
 
        /* Enable the output power */
        r = core->write(core, WL1273_POWER_ENB_SET, 1);
@@ -392,12 +393,12 @@ static int wl1273_fm_set_tx_freq(struct wl1273_device *radio, unsigned int freq)
        reinit_completion(&radio->busy);
 
        /* wait for the POWER_ENB IRQ */
-       r = wait_for_completion_timeout(&radio->busy, msecs_to_jiffies(1000));
-       if (!r)
+       t = wait_for_completion_timeout(&radio->busy, msecs_to_jiffies(1000));
+       if (!t)
                return -ETIMEDOUT;
 
        radio->tx_frequency = freq;
-       dev_dbg(radio->dev, "WL1273_POWER_ENB_SET: %d\n", r);
+       dev_dbg(radio->dev, "WL1273_POWER_ENB_SET: %lu\n", t);
 
        return  0;
 }
@@ -406,6 +407,7 @@ static int wl1273_fm_set_rx_freq(struct wl1273_device *radio, unsigned int freq)
 {
        struct wl1273_core *core = radio->core;
        int r, f;
+       unsigned long t;
 
        if (freq < radio->rangelow) {
                dev_err(radio->dev,
@@ -446,8 +448,8 @@ static int wl1273_fm_set_rx_freq(struct wl1273_device *radio, unsigned int freq)
 
        reinit_completion(&radio->busy);
 
-       r = wait_for_completion_timeout(&radio->busy, msecs_to_jiffies(2000));
-       if (!r) {
+       t = wait_for_completion_timeout(&radio->busy, msecs_to_jiffies(2000));
+       if (!t) {
                dev_err(radio->dev, "%s: TIMEOUT\n", __func__);
                return -ETIMEDOUT;
        }
@@ -826,9 +828,12 @@ static int wl1273_fm_set_seek(struct wl1273_device *radio,
        if (r)
                goto out;
 
+       /* wait for the FR IRQ */
        wait_for_completion_timeout(&radio->busy, msecs_to_jiffies(1000));
-       if (!(radio->irq_received & WL1273_BL_EVENT))
+       if (!(radio->irq_received & WL1273_BL_EVENT)) {
+               r = -ETIMEDOUT;
                goto out;
+       }
 
        radio->irq_received &= ~WL1273_BL_EVENT;
 
@@ -854,7 +859,9 @@ static int wl1273_fm_set_seek(struct wl1273_device *radio,
        if (r)
                goto out;
 
-       wait_for_completion_timeout(&radio->busy, msecs_to_jiffies(1000));
+       /* wait for the FR IRQ */
+       if (!wait_for_completion_timeout(&radio->busy, msecs_to_jiffies(1000)))
+               r = -ETIMEDOUT;
 out:
        dev_dbg(radio->dev, "%s: Err: %d\n", __func__, r);
        return r;
index 909c3f92d83920de0561d9dc59aa31171826d973..1d827adab7ebbbbf2ef9ed873fa55494344e4aa5 100644 (file)
@@ -208,6 +208,7 @@ static int si470x_set_band(struct si470x_device *radio, int band)
 static int si470x_set_chan(struct si470x_device *radio, unsigned short chan)
 {
        int retval;
+       unsigned long time_left;
        bool timed_out = false;
 
        /* start tuning */
@@ -219,9 +220,9 @@ static int si470x_set_chan(struct si470x_device *radio, unsigned short chan)
 
        /* wait till tune operation has completed */
        reinit_completion(&radio->completion);
-       retval = wait_for_completion_timeout(&radio->completion,
-                       msecs_to_jiffies(tune_timeout));
-       if (!retval)
+       time_left = wait_for_completion_timeout(&radio->completion,
+                                               msecs_to_jiffies(tune_timeout));
+       if (time_left == 0)
                timed_out = true;
 
        if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
@@ -301,6 +302,7 @@ static int si470x_set_seek(struct si470x_device *radio,
        int band, retval;
        unsigned int freq;
        bool timed_out = false;
+       unsigned long time_left;
 
        /* set band */
        if (seek->rangelow || seek->rangehigh) {
@@ -342,9 +344,9 @@ static int si470x_set_seek(struct si470x_device *radio,
 
        /* wait till tune operation has completed */
        reinit_completion(&radio->completion);
-       retval = wait_for_completion_timeout(&radio->completion,
-                       msecs_to_jiffies(seek_timeout));
-       if (!retval)
+       time_left = wait_for_completion_timeout(&radio->completion,
+                                               msecs_to_jiffies(seek_timeout));
+       if (time_left == 0)
                timed_out = true;
 
        if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
index c90004dac170c42c61b100a2b0750a62ddf59f77..e9d03ac69a27ff07bd50247a9d61f2a43721c18b 100644 (file)
@@ -383,7 +383,7 @@ static int si4713_powerup(struct si4713_device *sdev)
                }
        }
 
-       if (!IS_ERR(sdev->gpio_reset)) {
+       if (sdev->gpio_reset) {
                udelay(50);
                gpiod_set_value(sdev->gpio_reset, 1);
        }
@@ -407,8 +407,7 @@ static int si4713_powerup(struct si4713_device *sdev)
                                                SI4713_STC_INT | SI4713_CTS);
                return err;
        }
-       if (!IS_ERR(sdev->gpio_reset))
-               gpiod_set_value(sdev->gpio_reset, 0);
+       gpiod_set_value(sdev->gpio_reset, 0);
 
 
        if (sdev->vdd) {
@@ -447,7 +446,7 @@ static int si4713_powerdown(struct si4713_device *sdev)
                v4l2_dbg(1, debug, &sdev->sd, "Power down response: 0x%02x\n",
                                resp[0]);
                v4l2_dbg(1, debug, &sdev->sd, "Device in reset mode\n");
-               if (!IS_ERR(sdev->gpio_reset))
+               if (sdev->gpio_reset)
                        gpiod_set_value(sdev->gpio_reset, 0);
 
                if (sdev->vdd) {
@@ -1460,14 +1459,9 @@ static int si4713_probe(struct i2c_client *client,
                goto exit;
        }
 
-       sdev->gpio_reset = devm_gpiod_get(&client->dev, "reset");
-       if (!IS_ERR(sdev->gpio_reset)) {
-               gpiod_direction_output(sdev->gpio_reset, 0);
-       } else if (PTR_ERR(sdev->gpio_reset) == -ENOENT) {
-               dev_dbg(&client->dev, "No reset GPIO assigned\n");
-       } else if (PTR_ERR(sdev->gpio_reset) == -ENOSYS) {
-               dev_dbg(&client->dev, "No reset GPIO support\n");
-       } else {
+       sdev->gpio_reset = devm_gpiod_get_optional(&client->dev, "reset",
+                                                  GPIOD_OUT_LOW);
+       if (IS_ERR(sdev->gpio_reset)) {
                rval = PTR_ERR(sdev->gpio_reset);
                dev_err(&client->dev, "Failed to request gpio: %d\n", rval);
                goto exit;
index f359be7e9dd9a952aa4544e2bff211666d0cfa98..9d6574bebf78b4f6b215e2f546db53b0e08a9c45 100644 (file)
@@ -5,7 +5,7 @@ menu "Texas Instruments WL128x FM driver (ST based)"
 config RADIO_WL128X
        tristate "Texas Instruments WL128x FM Radio"
        depends on VIDEO_V4L2 && RFKILL && GPIOLIB && TTY
-       select TI_ST if NET
+       depends on TI_ST
        help
        Choose Y here if you have this FM radio chip.
 
index a5bd3f674bbdba19be2697c247c8276ed51f9d17..fb42f0fd0c1f0fbe65cd2b8401854411e387f2ef 100644 (file)
@@ -36,7 +36,7 @@
 #include "fmdrv_rx.h"
 #include "fmdrv_tx.h"
 
-static struct video_device *gradio_dev;
+static struct video_device gradio_dev;
 static u8 radio_disconnected;
 
 /* -- V4L2 RADIO (/dev/radioX) device file operation interfaces --- */
@@ -517,7 +517,7 @@ static struct video_device fm_viddev_template = {
        .fops = &fm_drv_fops,
        .ioctl_ops = &fm_drv_ioctl_ops,
        .name = FM_DRV_NAME,
-       .release = video_device_release,
+       .release = video_device_release_empty,
        /*
         * To ensure both the tuner and modulator ioctls are accessible we
         * set the vfl_dir to M2M to indicate this.
@@ -543,29 +543,21 @@ int fm_v4l2_init_video_device(struct fmdev *fmdev, int radio_nr)
        /* Init mutex for core locking */
        mutex_init(&fmdev->mutex);
 
-       /* Allocate new video device */
-       gradio_dev = video_device_alloc();
-       if (NULL == gradio_dev) {
-               fmerr("Can't allocate video device\n");
-               return -ENOMEM;
-       }
-
        /* Setup FM driver's V4L2 properties */
-       memcpy(gradio_dev, &fm_viddev_template, sizeof(fm_viddev_template));
+       gradio_dev = fm_viddev_template;
 
-       video_set_drvdata(gradio_dev, fmdev);
+       video_set_drvdata(&gradio_dev, fmdev);
 
-       gradio_dev->lock = &fmdev->mutex;
-       gradio_dev->v4l2_dev = &fmdev->v4l2_dev;
+       gradio_dev.lock = &fmdev->mutex;
+       gradio_dev.v4l2_dev = &fmdev->v4l2_dev;
 
        /* Register with V4L2 subsystem as RADIO device */
-       if (video_register_device(gradio_dev, VFL_TYPE_RADIO, radio_nr)) {
-               video_device_release(gradio_dev);
+       if (video_register_device(&gradio_dev, VFL_TYPE_RADIO, radio_nr)) {
                fmerr("Could not register video device\n");
                return -ENOMEM;
        }
 
-       fmdev->radio_dev = gradio_dev;
+       fmdev->radio_dev = &gradio_dev;
 
        /* Register to v4l2 ctrl handler framework */
        fmdev->radio_dev->ctrl_handler = &fmdev->ctrl_handler;
@@ -611,13 +603,13 @@ void *fm_v4l2_deinit_video_device(void)
        struct fmdev *fmdev;
 
 
-       fmdev = video_get_drvdata(gradio_dev);
+       fmdev = video_get_drvdata(&gradio_dev);
 
        /* Unregister to v4l2 ctrl handler framework*/
        v4l2_ctrl_handler_free(&fmdev->ctrl_handler);
 
        /* Unregister RADIO device from V4L2 subsystem */
-       video_unregister_device(gradio_dev);
+       video_unregister_device(&gradio_dev);
 
        v4l2_device_unregister(&fmdev->v4l2_dev);
 
index 77c78de4f5bf57ab4bb899357815d9d064c69272..03fe080278df3eab251c4eab71d3aa2e23368264 100644 (file)
@@ -110,16 +110,32 @@ static int img_ir_probe(struct platform_device *pdev)
        priv->clk = devm_clk_get(&pdev->dev, "core");
        if (IS_ERR(priv->clk))
                dev_warn(&pdev->dev, "cannot get core clock resource\n");
+
+       /* Get sys clock */
+       priv->sys_clk = devm_clk_get(&pdev->dev, "sys");
+       if (IS_ERR(priv->sys_clk))
+               dev_warn(&pdev->dev, "cannot get sys clock resource\n");
        /*
-        * The driver doesn't need to know about the system ("sys") or power
-        * modulation ("mod") clocks yet
+        * Enabling the system clock before the register interface is
+        * accessed. ISR shouldn't get called with Sys Clock disabled,
+        * hence exiting probe with an error.
         */
+       if (!IS_ERR(priv->sys_clk)) {
+               error = clk_prepare_enable(priv->sys_clk);
+               if (error) {
+                       dev_err(&pdev->dev, "cannot enable sys clock\n");
+                       return error;
+               }
+       }
 
        /* Set up raw & hw decoder */
        error = img_ir_probe_raw(priv);
        error2 = img_ir_probe_hw(priv);
-       if (error && error2)
-               return (error == -ENODEV) ? error2 : error;
+       if (error && error2) {
+               if (error == -ENODEV)
+                       error = error2;
+               goto err_probe;
+       }
 
        /* Get the IRQ */
        priv->irq = irq;
@@ -139,6 +155,9 @@ static int img_ir_probe(struct platform_device *pdev)
 err_irq:
        img_ir_remove_hw(priv);
        img_ir_remove_raw(priv);
+err_probe:
+       if (!IS_ERR(priv->sys_clk))
+               clk_disable_unprepare(priv->sys_clk);
        return error;
 }
 
@@ -146,12 +165,14 @@ static int img_ir_remove(struct platform_device *pdev)
 {
        struct img_ir_priv *priv = platform_get_drvdata(pdev);
 
-       free_irq(priv->irq, img_ir_isr);
+       free_irq(priv->irq, priv);
        img_ir_remove_hw(priv);
        img_ir_remove_raw(priv);
 
        if (!IS_ERR(priv->clk))
                clk_disable_unprepare(priv->clk);
+       if (!IS_ERR(priv->sys_clk))
+               clk_disable_unprepare(priv->sys_clk);
        return 0;
 }
 
index 2ddf560831825c98e4548d146ee15d36ad52f0b7..f1387c016d3d27c7969d3bcb345b0f661612bdaf 100644 (file)
@@ -138,6 +138,7 @@ struct clk;
  * @dev:               Platform device.
  * @irq:               IRQ number.
  * @clk:               Input clock.
+ * @sys_clk:           System clock.
  * @reg_base:          Iomem base address of IR register block.
  * @lock:              Protects IR registers and variables in this struct.
  * @raw:               Driver data for raw decoder.
@@ -147,6 +148,7 @@ struct img_ir_priv {
        struct device           *dev;
        int                     irq;
        struct clk              *clk;
+       struct clk              *sys_clk;
        void __iomem            *reg_base;
        spinlock_t              lock;
 
index b0df62961c1403c4acd439c46254a15b3981cac7..58ec5986274ed79b0191a440696912e38f940e0b 100644 (file)
 #include <linux/regmap.h>
 #include <media/rc-core.h>
 
-/* Allow the driver to compile on all architectures */
-#ifndef writel_relaxed
-# define writel_relaxed writel
-#endif
-#ifndef readl_relaxed
-# define readl_relaxed readl
-#endif
-
 #define IR_ENABLE              0x00
 #define IR_CONFIG              0x04
 #define CNT_LEADS              0x08
index 42e5a01b9192ace596ca4b893ea93676184ec8d7..983510d282f6e7ba18747f115a65927e760cbaf3 100644 (file)
@@ -224,14 +224,6 @@ config MEDIA_TUNER_FC2580
        help
          FCI FC2580 silicon tuner driver.
 
-config MEDIA_TUNER_M88TS2022
-       tristate "Montage M88TS2022 silicon tuner"
-       depends on MEDIA_SUPPORT && I2C
-       select REGMAP_I2C
-       default m if !MEDIA_SUBDRV_AUTOSELECT
-       help
-         Montage M88TS2022 silicon tuner driver.
-
 config MEDIA_TUNER_M88RS6000T
        tristate "Montage M88RS6000 internal tuner"
        depends on MEDIA_SUPPORT && I2C
index da4fe6ef73e74ce13031a45d01066c242be0802c..06a9ab65e5fa79ea61479841820900020ac5031c 100644 (file)
@@ -33,7 +33,6 @@ obj-$(CONFIG_MEDIA_TUNER_E4000) += e4000.o
 obj-$(CONFIG_MEDIA_TUNER_FC2580) += fc2580.o
 obj-$(CONFIG_MEDIA_TUNER_TUA9001) += tua9001.o
 obj-$(CONFIG_MEDIA_TUNER_SI2157) += si2157.o
-obj-$(CONFIG_MEDIA_TUNER_M88TS2022) += m88ts2022.o
 obj-$(CONFIG_MEDIA_TUNER_FC0011) += fc0011.o
 obj-$(CONFIG_MEDIA_TUNER_FC0012) += fc0012.o
 obj-$(CONFIG_MEDIA_TUNER_FC0013) += fc0013.o
index 43ec893a6877e000b55e0e7e74bf0add0f20550f..81bb568d694338f7f967fef7b3c799b39a6122d2 100644 (file)
@@ -23,7 +23,7 @@ enum fc0011_fe_callback_commands {
        FC0011_FE_CALLBACK_RESET,
 };
 
-#if IS_ENABLED(CONFIG_MEDIA_TUNER_FC0011)
+#if IS_REACHABLE(CONFIG_MEDIA_TUNER_FC0011)
 struct dvb_frontend *fc0011_attach(struct dvb_frontend *fe,
                                   struct i2c_adapter *i2c,
                                   const struct fc0011_config *config);
index 1d08057e32752ee7f48cda2a8c1734666ac85476..9ad32859bab0679264577a813d497f91ce4781cd 100644 (file)
@@ -49,7 +49,7 @@ struct fc0012_config {
        bool clock_out;
 };
 
-#if IS_ENABLED(CONFIG_MEDIA_TUNER_FC0012)
+#if IS_REACHABLE(CONFIG_MEDIA_TUNER_FC0012)
 extern struct dvb_frontend *fc0012_attach(struct dvb_frontend *fe,
                                        struct i2c_adapter *i2c,
                                        const struct fc0012_config *cfg);
index d65d5b37f56e0e9e04712915d2f26381f359a24a..e130bd7a32302477d1f3a8bec41e9ff2b98aa8ad 100644 (file)
@@ -26,7 +26,7 @@
 #include "dvb_frontend.h"
 #include "fc001x-common.h"
 
-#if IS_ENABLED(CONFIG_MEDIA_TUNER_FC0013)
+#if IS_REACHABLE(CONFIG_MEDIA_TUNER_FC0013)
 extern struct dvb_frontend *fc0013_attach(struct dvb_frontend *fe,
                                        struct i2c_adapter *i2c,
                                        u8 i2c_address, int dual_master,
index 9c43c1cc82d9b18ac460981202226db4d0cf1910..b1ce6770f88e94646eb76f9ca2bff4a853445754 100644 (file)
@@ -37,7 +37,7 @@ struct fc2580_config {
        u32 clock;
 };
 
-#if IS_ENABLED(CONFIG_MEDIA_TUNER_FC2580)
+#if IS_REACHABLE(CONFIG_MEDIA_TUNER_FC2580)
 extern struct dvb_frontend *fc2580_attach(struct dvb_frontend *fe,
        struct i2c_adapter *i2c, const struct fc2580_config *cfg);
 #else
diff --git a/drivers/media/tuners/m88ts2022.c b/drivers/media/tuners/m88ts2022.c
deleted file mode 100644 (file)
index 066e543..0000000
+++ /dev/null
@@ -1,579 +0,0 @@
-/*
- * Montage M88TS2022 silicon tuner driver
- *
- * Copyright (C) 2013 Antti Palosaari <crope@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 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.
- *
- * Some calculations are taken from existing TS2020 driver.
- */
-
-#include "m88ts2022_priv.h"
-
-static int m88ts2022_cmd(struct m88ts2022_dev *dev, int op, int sleep, u8 reg,
-               u8 mask, u8 val, u8 *reg_val)
-{
-       int ret, i;
-       unsigned int utmp;
-       struct m88ts2022_reg_val reg_vals[] = {
-               {0x51, 0x1f - op},
-               {0x51, 0x1f},
-               {0x50, 0x00 + op},
-               {0x50, 0x00},
-       };
-
-       for (i = 0; i < 2; i++) {
-               dev_dbg(&dev->client->dev,
-                               "i=%d op=%02x reg=%02x mask=%02x val=%02x\n",
-                               i, op, reg, mask, val);
-
-               for (i = 0; i < ARRAY_SIZE(reg_vals); i++) {
-                       ret = regmap_write(dev->regmap, reg_vals[i].reg,
-                                       reg_vals[i].val);
-                       if (ret)
-                               goto err;
-               }
-
-               usleep_range(sleep * 1000, sleep * 10000);
-
-               ret = regmap_read(dev->regmap, reg, &utmp);
-               if (ret)
-                       goto err;
-
-               if ((utmp & mask) != val)
-                       break;
-       }
-
-       if (reg_val)
-               *reg_val = utmp;
-err:
-       return ret;
-}
-
-static int m88ts2022_set_params(struct dvb_frontend *fe)
-{
-       struct m88ts2022_dev *dev = fe->tuner_priv;
-       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-       int ret;
-       unsigned int utmp, frequency_khz, frequency_offset_khz, f_3db_hz;
-       unsigned int f_ref_khz, f_vco_khz, div_ref, div_out, pll_n, gdiv28;
-       u8 buf[3], u8tmp, cap_code, lpf_gm, lpf_mxdiv, div_max, div_min;
-       u16 u16tmp;
-
-       dev_dbg(&dev->client->dev,
-                       "frequency=%d symbol_rate=%d rolloff=%d\n",
-                       c->frequency, c->symbol_rate, c->rolloff);
-       /*
-        * Integer-N PLL synthesizer
-        * kHz is used for all calculations to keep calculations within 32-bit
-        */
-       f_ref_khz = DIV_ROUND_CLOSEST(dev->cfg.clock, 1000);
-       div_ref = DIV_ROUND_CLOSEST(f_ref_khz, 2000);
-
-       if (c->symbol_rate < 5000000)
-               frequency_offset_khz = 3000; /* 3 MHz */
-       else
-               frequency_offset_khz = 0;
-
-       frequency_khz = c->frequency + frequency_offset_khz;
-
-       if (frequency_khz < 1103000) {
-               div_out = 4;
-               u8tmp = 0x1b;
-       } else {
-               div_out = 2;
-               u8tmp = 0x0b;
-       }
-
-       buf[0] = u8tmp;
-       buf[1] = 0x40;
-       ret = regmap_bulk_write(dev->regmap, 0x10, buf, 2);
-       if (ret)
-               goto err;
-
-       f_vco_khz = frequency_khz * div_out;
-       pll_n = f_vco_khz * div_ref / f_ref_khz;
-       pll_n += pll_n % 2;
-       dev->frequency_khz = pll_n * f_ref_khz / div_ref / div_out;
-
-       if (pll_n < 4095)
-               u16tmp = pll_n - 1024;
-       else if (pll_n < 6143)
-               u16tmp = pll_n + 1024;
-       else
-               u16tmp = pll_n + 3072;
-
-       buf[0] = (u16tmp >> 8) & 0x3f;
-       buf[1] = (u16tmp >> 0) & 0xff;
-       buf[2] = div_ref - 8;
-       ret = regmap_bulk_write(dev->regmap, 0x01, buf, 3);
-       if (ret)
-               goto err;
-
-       dev_dbg(&dev->client->dev,
-                       "frequency=%u offset=%d f_vco_khz=%u pll_n=%u div_ref=%u div_out=%u\n",
-                       dev->frequency_khz, dev->frequency_khz - c->frequency,
-                       f_vco_khz, pll_n, div_ref, div_out);
-
-       ret = m88ts2022_cmd(dev, 0x10, 5, 0x15, 0x40, 0x00, NULL);
-       if (ret)
-               goto err;
-
-       ret = regmap_read(dev->regmap, 0x14, &utmp);
-       if (ret)
-               goto err;
-
-       utmp &= 0x7f;
-       if (utmp < 64) {
-               ret = regmap_update_bits(dev->regmap, 0x10, 0x80, 0x80);
-               if (ret)
-                       goto err;
-
-               ret = regmap_write(dev->regmap, 0x11, 0x6f);
-               if (ret)
-                       goto err;
-
-               ret = m88ts2022_cmd(dev, 0x10, 5, 0x15, 0x40, 0x00, NULL);
-               if (ret)
-                       goto err;
-       }
-
-       ret = regmap_read(dev->regmap, 0x14, &utmp);
-       if (ret)
-               goto err;
-
-       utmp &= 0x1f;
-       if (utmp > 19) {
-               ret = regmap_update_bits(dev->regmap, 0x10, 0x02, 0x00);
-               if (ret)
-                       goto err;
-       }
-
-       ret = m88ts2022_cmd(dev, 0x08, 5, 0x3c, 0xff, 0x00, NULL);
-       if (ret)
-               goto err;
-
-       ret = regmap_write(dev->regmap, 0x25, 0x00);
-       if (ret)
-               goto err;
-
-       ret = regmap_write(dev->regmap, 0x27, 0x70);
-       if (ret)
-               goto err;
-
-       ret = regmap_write(dev->regmap, 0x41, 0x09);
-       if (ret)
-               goto err;
-
-       ret = regmap_write(dev->regmap, 0x08, 0x0b);
-       if (ret)
-               goto err;
-
-       /* filters */
-       gdiv28 = DIV_ROUND_CLOSEST(f_ref_khz * 1694U, 1000000U);
-
-       ret = regmap_write(dev->regmap, 0x04, gdiv28);
-       if (ret)
-               goto err;
-
-       ret = m88ts2022_cmd(dev, 0x04, 2, 0x26, 0xff, 0x00, &u8tmp);
-       if (ret)
-               goto err;
-
-       cap_code = u8tmp & 0x3f;
-
-       ret = regmap_write(dev->regmap, 0x41, 0x0d);
-       if (ret)
-               goto err;
-
-       ret = m88ts2022_cmd(dev, 0x04, 2, 0x26, 0xff, 0x00, &u8tmp);
-       if (ret)
-               goto err;
-
-       u8tmp &= 0x3f;
-       cap_code = (cap_code + u8tmp) / 2;
-       gdiv28 = gdiv28 * 207 / (cap_code * 2 + 151);
-       div_max = gdiv28 * 135 / 100;
-       div_min = gdiv28 * 78 / 100;
-       div_max = clamp_val(div_max, 0U, 63U);
-
-       f_3db_hz = mult_frac(c->symbol_rate, 135, 200);
-       f_3db_hz +=  2000000U + (frequency_offset_khz * 1000U);
-       f_3db_hz = clamp(f_3db_hz, 7000000U, 40000000U);
-
-#define LPF_COEFF 3200U
-       lpf_gm = DIV_ROUND_CLOSEST(f_3db_hz * gdiv28, LPF_COEFF * f_ref_khz);
-       lpf_gm = clamp_val(lpf_gm, 1U, 23U);
-
-       lpf_mxdiv = DIV_ROUND_CLOSEST(lpf_gm * LPF_COEFF * f_ref_khz, f_3db_hz);
-       if (lpf_mxdiv < div_min)
-               lpf_mxdiv = DIV_ROUND_CLOSEST(++lpf_gm * LPF_COEFF * f_ref_khz, f_3db_hz);
-       lpf_mxdiv = clamp_val(lpf_mxdiv, 0U, div_max);
-
-       ret = regmap_write(dev->regmap, 0x04, lpf_mxdiv);
-       if (ret)
-               goto err;
-
-       ret = regmap_write(dev->regmap, 0x06, lpf_gm);
-       if (ret)
-               goto err;
-
-       ret = m88ts2022_cmd(dev, 0x04, 2, 0x26, 0xff, 0x00, &u8tmp);
-       if (ret)
-               goto err;
-
-       cap_code = u8tmp & 0x3f;
-
-       ret = regmap_write(dev->regmap, 0x41, 0x09);
-       if (ret)
-               goto err;
-
-       ret = m88ts2022_cmd(dev, 0x04, 2, 0x26, 0xff, 0x00, &u8tmp);
-       if (ret)
-               goto err;
-
-       u8tmp &= 0x3f;
-       cap_code = (cap_code + u8tmp) / 2;
-
-       u8tmp = cap_code | 0x80;
-       ret = regmap_write(dev->regmap, 0x25, u8tmp);
-       if (ret)
-               goto err;
-
-       ret = regmap_write(dev->regmap, 0x27, 0x30);
-       if (ret)
-               goto err;
-
-       ret = regmap_write(dev->regmap, 0x08, 0x09);
-       if (ret)
-               goto err;
-
-       ret = m88ts2022_cmd(dev, 0x01, 20, 0x21, 0xff, 0x00, NULL);
-       if (ret)
-               goto err;
-err:
-       if (ret)
-               dev_dbg(&dev->client->dev, "failed=%d\n", ret);
-
-       return ret;
-}
-
-static int m88ts2022_init(struct dvb_frontend *fe)
-{
-       struct m88ts2022_dev *dev = fe->tuner_priv;
-       int ret, i;
-       u8 u8tmp;
-       static const struct m88ts2022_reg_val reg_vals[] = {
-               {0x7d, 0x9d},
-               {0x7c, 0x9a},
-               {0x7a, 0x76},
-               {0x3b, 0x01},
-               {0x63, 0x88},
-               {0x61, 0x85},
-               {0x22, 0x30},
-               {0x30, 0x40},
-               {0x20, 0x23},
-               {0x24, 0x02},
-               {0x12, 0xa0},
-       };
-
-       dev_dbg(&dev->client->dev, "\n");
-
-       ret = regmap_write(dev->regmap, 0x00, 0x01);
-       if (ret)
-               goto err;
-
-       ret = regmap_write(dev->regmap, 0x00, 0x03);
-       if (ret)
-               goto err;
-
-       switch (dev->cfg.clock_out) {
-       case M88TS2022_CLOCK_OUT_DISABLED:
-               u8tmp = 0x60;
-               break;
-       case M88TS2022_CLOCK_OUT_ENABLED:
-               u8tmp = 0x70;
-               ret = regmap_write(dev->regmap, 0x05, dev->cfg.clock_out_div);
-               if (ret)
-                       goto err;
-               break;
-       case M88TS2022_CLOCK_OUT_ENABLED_XTALOUT:
-               u8tmp = 0x6c;
-               break;
-       default:
-               goto err;
-       }
-
-       ret = regmap_write(dev->regmap, 0x42, u8tmp);
-       if (ret)
-               goto err;
-
-       if (dev->cfg.loop_through)
-               u8tmp = 0xec;
-       else
-               u8tmp = 0x6c;
-
-       ret = regmap_write(dev->regmap, 0x62, u8tmp);
-       if (ret)
-               goto err;
-
-       for (i = 0; i < ARRAY_SIZE(reg_vals); i++) {
-               ret = regmap_write(dev->regmap, reg_vals[i].reg, reg_vals[i].val);
-               if (ret)
-                       goto err;
-       }
-err:
-       if (ret)
-               dev_dbg(&dev->client->dev, "failed=%d\n", ret);
-       return ret;
-}
-
-static int m88ts2022_sleep(struct dvb_frontend *fe)
-{
-       struct m88ts2022_dev *dev = fe->tuner_priv;
-       int ret;
-
-       dev_dbg(&dev->client->dev, "\n");
-
-       ret = regmap_write(dev->regmap, 0x00, 0x00);
-       if (ret)
-               goto err;
-err:
-       if (ret)
-               dev_dbg(&dev->client->dev, "failed=%d\n", ret);
-       return ret;
-}
-
-static int m88ts2022_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-       struct m88ts2022_dev *dev = fe->tuner_priv;
-
-       dev_dbg(&dev->client->dev, "\n");
-
-       *frequency = dev->frequency_khz;
-       return 0;
-}
-
-static int m88ts2022_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-       struct m88ts2022_dev *dev = fe->tuner_priv;
-
-       dev_dbg(&dev->client->dev, "\n");
-
-       *frequency = 0; /* Zero-IF */
-       return 0;
-}
-
-static int m88ts2022_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
-{
-       struct m88ts2022_dev *dev = fe->tuner_priv;
-       int ret;
-       u16 gain, u16tmp;
-       unsigned int utmp, gain1, gain2, gain3;
-
-       ret = regmap_read(dev->regmap, 0x3d, &utmp);
-       if (ret)
-               goto err;
-
-       gain1 = (utmp >> 0) & 0x1f;
-       gain1 = clamp(gain1, 0U, 15U);
-
-       ret = regmap_read(dev->regmap, 0x21, &utmp);
-       if (ret)
-               goto err;
-
-       gain2 = (utmp >> 0) & 0x1f;
-       gain2 = clamp(gain2, 2U, 16U);
-
-       ret = regmap_read(dev->regmap, 0x66, &utmp);
-       if (ret)
-               goto err;
-
-       gain3 = (utmp >> 3) & 0x07;
-       gain3 = clamp(gain3, 0U, 6U);
-
-       gain = gain1 * 265 + gain2 * 338 + gain3 * 285;
-
-       /* scale value to 0x0000-0xffff */
-       u16tmp = (0xffff - gain);
-       u16tmp = clamp_val(u16tmp, 59000U, 61500U);
-
-       *strength = (u16tmp - 59000) * 0xffff / (61500 - 59000);
-err:
-       if (ret)
-               dev_dbg(&dev->client->dev, "failed=%d\n", ret);
-       return ret;
-}
-
-static const struct dvb_tuner_ops m88ts2022_tuner_ops = {
-       .info = {
-               .name          = "Montage M88TS2022",
-               .frequency_min = 950000,
-               .frequency_max = 2150000,
-       },
-
-       .init = m88ts2022_init,
-       .sleep = m88ts2022_sleep,
-       .set_params = m88ts2022_set_params,
-
-       .get_frequency = m88ts2022_get_frequency,
-       .get_if_frequency = m88ts2022_get_if_frequency,
-       .get_rf_strength = m88ts2022_get_rf_strength,
-};
-
-static int m88ts2022_probe(struct i2c_client *client,
-               const struct i2c_device_id *id)
-{
-       struct m88ts2022_config *cfg = client->dev.platform_data;
-       struct dvb_frontend *fe = cfg->fe;
-       struct m88ts2022_dev *dev;
-       int ret;
-       u8 u8tmp;
-       unsigned int utmp;
-       static const struct regmap_config regmap_config = {
-               .reg_bits = 8,
-               .val_bits = 8,
-       };
-
-       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-       if (!dev) {
-               ret = -ENOMEM;
-               dev_err(&client->dev, "kzalloc() failed\n");
-               goto err;
-       }
-
-       memcpy(&dev->cfg, cfg, sizeof(struct m88ts2022_config));
-       dev->client = client;
-       dev->regmap = devm_regmap_init_i2c(client, &regmap_config);
-       if (IS_ERR(dev->regmap)) {
-               ret = PTR_ERR(dev->regmap);
-               goto err;
-       }
-
-       /* check if the tuner is there */
-       ret = regmap_read(dev->regmap, 0x00, &utmp);
-       if (ret)
-               goto err;
-
-       if ((utmp & 0x03) == 0x00) {
-               ret = regmap_write(dev->regmap, 0x00, 0x01);
-               if (ret)
-                       goto err;
-
-               usleep_range(2000, 50000);
-       }
-
-       ret = regmap_write(dev->regmap, 0x00, 0x03);
-       if (ret)
-               goto err;
-
-       usleep_range(2000, 50000);
-
-       ret = regmap_read(dev->regmap, 0x00, &utmp);
-       if (ret)
-               goto err;
-
-       dev_dbg(&dev->client->dev, "chip_id=%02x\n", utmp);
-
-       switch (utmp) {
-       case 0xc3:
-       case 0x83:
-               break;
-       default:
-               ret = -ENODEV;
-               goto err;
-       }
-
-       switch (dev->cfg.clock_out) {
-       case M88TS2022_CLOCK_OUT_DISABLED:
-               u8tmp = 0x60;
-               break;
-       case M88TS2022_CLOCK_OUT_ENABLED:
-               u8tmp = 0x70;
-               ret = regmap_write(dev->regmap, 0x05, dev->cfg.clock_out_div);
-               if (ret)
-                       goto err;
-               break;
-       case M88TS2022_CLOCK_OUT_ENABLED_XTALOUT:
-               u8tmp = 0x6c;
-               break;
-       default:
-               ret = -EINVAL;
-               goto err;
-       }
-
-       ret = regmap_write(dev->regmap, 0x42, u8tmp);
-       if (ret)
-               goto err;
-
-       if (dev->cfg.loop_through)
-               u8tmp = 0xec;
-       else
-               u8tmp = 0x6c;
-
-       ret = regmap_write(dev->regmap, 0x62, u8tmp);
-       if (ret)
-               goto err;
-
-       /* sleep */
-       ret = regmap_write(dev->regmap, 0x00, 0x00);
-       if (ret)
-               goto err;
-
-       dev_info(&dev->client->dev, "Montage M88TS2022 successfully identified\n");
-
-       fe->tuner_priv = dev;
-       memcpy(&fe->ops.tuner_ops, &m88ts2022_tuner_ops,
-                       sizeof(struct dvb_tuner_ops));
-
-       i2c_set_clientdata(client, dev);
-       return 0;
-err:
-       dev_dbg(&client->dev, "failed=%d\n", ret);
-       kfree(dev);
-       return ret;
-}
-
-static int m88ts2022_remove(struct i2c_client *client)
-{
-       struct m88ts2022_dev *dev = i2c_get_clientdata(client);
-       struct dvb_frontend *fe = dev->cfg.fe;
-
-       dev_dbg(&client->dev, "\n");
-
-       memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));
-       fe->tuner_priv = NULL;
-       kfree(dev);
-
-       return 0;
-}
-
-static const struct i2c_device_id m88ts2022_id[] = {
-       {"m88ts2022", 0},
-       {}
-};
-MODULE_DEVICE_TABLE(i2c, m88ts2022_id);
-
-static struct i2c_driver m88ts2022_driver = {
-       .driver = {
-               .owner  = THIS_MODULE,
-               .name   = "m88ts2022",
-       },
-       .probe          = m88ts2022_probe,
-       .remove         = m88ts2022_remove,
-       .id_table       = m88ts2022_id,
-};
-
-module_i2c_driver(m88ts2022_driver);
-
-MODULE_DESCRIPTION("Montage M88TS2022 silicon tuner driver");
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/tuners/m88ts2022.h b/drivers/media/tuners/m88ts2022.h
deleted file mode 100644 (file)
index 659fa1b..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Montage M88TS2022 silicon tuner driver
- *
- * Copyright (C) 2013 Antti Palosaari <crope@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 Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- */
-
-#ifndef M88TS2022_H
-#define M88TS2022_H
-
-#include "dvb_frontend.h"
-
-struct m88ts2022_config {
-       /*
-        * clock
-        * 16000000 - 32000000
-        */
-       u32 clock;
-
-       /*
-        * RF loop-through
-        */
-       u8 loop_through:1;
-
-       /*
-        * clock output
-        */
-#define M88TS2022_CLOCK_OUT_DISABLED        0
-#define M88TS2022_CLOCK_OUT_ENABLED         1
-#define M88TS2022_CLOCK_OUT_ENABLED_XTALOUT 2
-       u8 clock_out:2;
-
-       /*
-        * clock output divider
-        * 1 - 31
-        */
-       u8 clock_out_div:5;
-
-       /*
-        * pointer to DVB frontend
-        */
-       struct dvb_frontend *fe;
-};
-
-#endif
diff --git a/drivers/media/tuners/m88ts2022_priv.h b/drivers/media/tuners/m88ts2022_priv.h
deleted file mode 100644 (file)
index feeb5ad..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Montage M88TS2022 silicon tuner driver
- *
- * Copyright (C) 2013 Antti Palosaari <crope@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 Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- */
-
-#ifndef M88TS2022_PRIV_H
-#define M88TS2022_PRIV_H
-
-#include "m88ts2022.h"
-#include <linux/regmap.h>
-
-struct m88ts2022_dev {
-       struct m88ts2022_config cfg;
-       struct i2c_client *client;
-       struct regmap *regmap;
-       u32 frequency_khz;
-};
-
-struct m88ts2022_reg_val {
-       u8 reg;
-       u8 val;
-};
-
-#endif
index 26e1dc64bb6777a2a400f8da62d906ced5c945ce..5054f01a78fbba435e587af3a404ae3f136bd81f 100644 (file)
@@ -32,7 +32,7 @@ struct max2165_config {
        u8 osc_clk; /* in MHz, selectable values: 4,16,18,20,22,24,26,28 */
 };
 
-#if IS_ENABLED(CONFIG_MEDIA_TUNER_MAX2165)
+#if IS_REACHABLE(CONFIG_MEDIA_TUNER_MAX2165)
 extern struct dvb_frontend *max2165_attach(struct dvb_frontend *fe,
        struct i2c_adapter *i2c,
        struct max2165_config *cfg);
index 9aae50aca2b7c502853a7a4ce5c1d610f4578b50..b3e614be657dbe32d8eef52d9278ca9e645f546c 100644 (file)
@@ -32,7 +32,7 @@ struct mc44s803_config {
        u8 dig_out;
 };
 
-#if IS_ENABLED(CONFIG_MEDIA_TUNER_MC44S803)
+#if IS_REACHABLE(CONFIG_MEDIA_TUNER_MC44S803)
 extern struct dvb_frontend *mc44s803_attach(struct dvb_frontend *fe,
         struct i2c_adapter *i2c, struct mc44s803_config *cfg);
 #else
index c64fc19cb27866a1af42cffba6bae94e7110270a..6efed359a24fd2cefadfffaf378294b4a112b535 100644 (file)
@@ -30,7 +30,7 @@ struct mt2060_config {
        u8 clock_out; /* 0 = off, 1 = CLK/4, 2 = CLK/2, 3 = CLK/1 */
 };
 
-#if IS_ENABLED(CONFIG_MEDIA_TUNER_MT2060)
+#if IS_REACHABLE(CONFIG_MEDIA_TUNER_MT2060)
 extern struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1);
 #else
 static inline struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1)
index e1acfc8e7ae3f20b6fa01d66554d629af9da6c9d..e55e0a6dd1be403d3859a54e45210b4d4f2e06c7 100644 (file)
@@ -8,7 +8,7 @@ struct mt2063_config {
        u32 refclock;
 };
 
-#if IS_ENABLED(CONFIG_MEDIA_TUNER_MT2063)
+#if IS_REACHABLE(CONFIG_MEDIA_TUNER_MT2063)
 struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
                                   struct mt2063_config *config,
                                   struct i2c_adapter *i2c);
index f56241ccaa00b85946fbb7d17bb8928b30e44fba..9912362b415ea646ed43b8c32ed90bd4ae479d39 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/i2c.h>
 #include "dvb_frontend.h"
 
-#if IS_ENABLED(CONFIG_MEDIA_TUNER_MT20XX)
+#if IS_REACHABLE(CONFIG_MEDIA_TUNER_MT20XX)
 extern struct dvb_frontend *microtune_attach(struct dvb_frontend *fe,
                                             struct i2c_adapter* i2c_adap,
                                             u8 i2c_addr);
index 837c854b9c656cab9a574467fdb39b3dc2c963f1..8267a6ae5d848bc12bb1bbb7e2f1fc5ab7ffd561 100644 (file)
@@ -30,7 +30,7 @@ struct mt2131_config {
        u8 clock_out; /* 0 = off, 1 = CLK/4, 2 = CLK/2, 3 = CLK/1 */
 };
 
-#if IS_ENABLED(CONFIG_MEDIA_TUNER_MT2131)
+#if IS_REACHABLE(CONFIG_MEDIA_TUNER_MT2131)
 extern struct dvb_frontend* mt2131_attach(struct dvb_frontend *fe,
                                          struct i2c_adapter *i2c,
                                          struct mt2131_config *cfg,
index fad6dd657d77016e27425264d6edd2fe0e26da5d..69abefa18c37c38699c541206d297f09e3cbcb90 100644 (file)
@@ -24,7 +24,7 @@ struct mt2266_config {
        u8 i2c_address;
 };
 
-#if IS_ENABLED(CONFIG_MEDIA_TUNER_MT2266)
+#if IS_REACHABLE(CONFIG_MEDIA_TUNER_MT2266)
 extern struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2266_config *cfg);
 #else
 static inline struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2266_config *cfg)
index ae8db885ad87a1cfb22603910bc2bc04e360717f..5764b12c5c7c6f45619763f90b0381889e8f00c7 100644 (file)
@@ -118,7 +118,7 @@ struct mxl5005s_config {
        u8 AgcMasterByte;
 };
 
-#if IS_ENABLED(CONFIG_MEDIA_TUNER_MXL5005S)
+#if IS_REACHABLE(CONFIG_MEDIA_TUNER_MXL5005S)
 extern struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe,
                                            struct i2c_adapter *i2c,
                                            struct mxl5005s_config *config);
index ae7037d681c5a0b050f3eb859491323df23871b0..e786d1f23ff1b7c0da087361903c576778fdd75c 100644 (file)
@@ -77,7 +77,7 @@ struct mxl5007t_config {
        unsigned int clk_out_enable:1;
 };
 
-#if IS_ENABLED(CONFIG_MEDIA_TUNER_MXL5007T)
+#if IS_REACHABLE(CONFIG_MEDIA_TUNER_MXL5007T)
 extern struct dvb_frontend *mxl5007t_attach(struct dvb_frontend *fe,
                                            struct i2c_adapter *i2c, u8 addr,
                                            struct mxl5007t_config *cfg);
index 8ab5d479749f4b6a82a8b75316c8247d1b643e51..e3198f23437c1af9d70b340415d567e970d24832 100644 (file)
@@ -36,7 +36,7 @@ struct qt1010_config {
  * @param cfg  tuner hw based configuration
  * @return fe  pointer on success, NULL on failure
  */
-#if IS_ENABLED(CONFIG_MEDIA_TUNER_QT1010)
+#if IS_REACHABLE(CONFIG_MEDIA_TUNER_QT1010)
 extern struct dvb_frontend *qt1010_attach(struct dvb_frontend *fe,
                                          struct i2c_adapter *i2c,
                                          struct qt1010_config *cfg);
index 8e040cf9cf1347e8fbe42a9d051bd2ac2def18d6..71159a58860fc973cf5354278bf270e7b22a6f31 100644 (file)
@@ -775,6 +775,19 @@ static int r820t_sysfreq_sel(struct r820t_priv *priv, u32 freq,
                div_buf_cur = 0x30;     /* 11, 150u */
                filter_cur = 0x40;      /* 10, low */
                break;
+       case SYS_DVBC_ANNEX_A:
+               mixer_top = 0x24;       /* mixer top:13 , top-1, low-discharge */
+               lna_top = 0xe5;
+               lna_vth_l = 0x62;
+               mixer_vth_l = 0x75;
+               air_cable1_in = 0x60;
+               cable2_in = 0x00;
+               pre_dect = 0x40;
+               lna_discharge = 14;
+               cp_cur = 0x38;          /* 111, auto */
+               div_buf_cur = 0x30;     /* 11, 150u */
+               filter_cur = 0x40;      /* 10, low */
+               break;
        default: /* DVB-T 8M */
                mixer_top = 0x24;       /* mixer top:13 , top-1, low-discharge */
                lna_top = 0xe5;         /* detect bw 3, lna top:4, predet top:2 */
@@ -957,7 +970,7 @@ static int r820t_set_tv_standard(struct r820t_priv *priv,
                ext_enable = 0x40;      /* r30[6], ext enable; r30[5]:0 ext at lna max */
                loop_through = 0x00;    /* r5[7], lt on */
                lt_att = 0x00;          /* r31[7], lt att enable */
-               flt_ext_widest = 0x00;  /* r15[7]: flt_ext_wide off */
+               flt_ext_widest = 0x80;  /* r15[7]: flt_ext_wide on */
                polyfil_cur = 0x60;     /* r25[6:5]:min */
        } else if (delsys == SYS_DVBC_ANNEX_A) {
                if_khz = 5070;
@@ -971,6 +984,18 @@ static int r820t_set_tv_standard(struct r820t_priv *priv,
                lt_att = 0x00;          /* r31[7], lt att enable */
                flt_ext_widest = 0x00;  /* r15[7]: flt_ext_wide off */
                polyfil_cur = 0x60;     /* r25[6:5]:min */
+       } else if (delsys == SYS_DVBC_ANNEX_C) {
+               if_khz = 4063;
+               filt_cal_lo = 55000;
+               filt_gain = 0x10;       /* +3db, 6mhz on */
+               img_r = 0x00;           /* image negative */
+               filt_q = 0x10;          /* r10[4]:low q(1'b1) */
+               hp_cor = 0x6a;          /* 1.7m disable, +0cap, 1.0mhz */
+               ext_enable = 0x40;      /* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */
+               loop_through = 0x00;    /* r5[7], lt on */
+               lt_att = 0x00;          /* r31[7], lt att enable */
+               flt_ext_widest = 0x80;  /* r15[7]: flt_ext_wide on */
+               polyfil_cur = 0x60;     /* r25[6:5]:min */
        } else {
                if (bw <= 6) {
                        if_khz = 3570;
@@ -1186,7 +1211,7 @@ static int r820t_read_gain(struct r820t_priv *priv)
        if (rc < 0)
                return rc;
 
-       return ((data[3] & 0x0f) << 1) + ((data[3] & 0xf0) >> 4);
+       return ((data[3] & 0x08) << 1) + ((data[3] & 0xf0) >> 4);
 }
 
 #if 0
index 48af3548027da19fa872fab0a0dff8a369a54ea5..b1e5661af1c7e03d7a0f9f1d850598eaa29b6e65 100644 (file)
@@ -42,7 +42,7 @@ struct r820t_config {
        bool use_predetect;
 };
 
-#if IS_ENABLED(CONFIG_MEDIA_TUNER_R820T)
+#if IS_REACHABLE(CONFIG_MEDIA_TUNER_R820T)
 struct dvb_frontend *r820t_attach(struct dvb_frontend *fe,
                                  struct i2c_adapter *i2c,
                                  const struct r820t_config *cfg);
index fcf139dfdec6bc99daa3c67be783c0c66da14c09..d74ae26621ca531d458649c487fb9b883a73e00a 100644 (file)
@@ -244,6 +244,7 @@ static int si2157_set_params(struct dvb_frontend *fe)
        int ret;
        struct si2157_cmd cmd;
        u8 bandwidth, delivery_system;
+       u32 if_frequency = 5000000;
 
        dev_dbg(&client->dev,
                        "delivery_system=%d frequency=%u bandwidth_hz=%u\n",
@@ -266,9 +267,11 @@ static int si2157_set_params(struct dvb_frontend *fe)
        switch (c->delivery_system) {
        case SYS_ATSC:
                        delivery_system = 0x00;
+                       if_frequency = 3250000;
                        break;
        case SYS_DVBC_ANNEX_B:
                        delivery_system = 0x10;
+                       if_frequency = 4000000;
                        break;
        case SYS_DVBT:
        case SYS_DVBT2: /* it seems DVB-T and DVB-T2 both are 0x20 here */
@@ -302,6 +305,20 @@ static int si2157_set_params(struct dvb_frontend *fe)
        if (ret)
                goto err;
 
+       /* set if frequency if needed */
+       if (if_frequency != dev->if_frequency) {
+               memcpy(cmd.args, "\x14\x00\x06\x07", 4);
+               cmd.args[4] = (if_frequency / 1000) & 0xff;
+               cmd.args[5] = ((if_frequency / 1000) >> 8) & 0xff;
+               cmd.wlen = 6;
+               cmd.rlen = 4;
+               ret = si2157_cmd_execute(client, &cmd);
+               if (ret)
+                       goto err;
+
+               dev->if_frequency = if_frequency;
+       }
+
        /* set frequency */
        memcpy(cmd.args, "\x41\x00\x00\x00\x00\x00\x00\x00", 8);
        cmd.args[4] = (c->frequency >>  0) & 0xff;
@@ -322,14 +339,17 @@ err:
 
 static int si2157_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
 {
-       *frequency = 5000000; /* default value of property 0x0706 */
+       struct i2c_client *client = fe->tuner_priv;
+       struct si2157_dev *dev = i2c_get_clientdata(client);
+
+       *frequency = dev->if_frequency;
        return 0;
 }
 
 static const struct dvb_tuner_ops si2157_ops = {
        .info = {
                .name           = "Silicon Labs Si2146/2147/2148/2157/2158",
-               .frequency_min  = 110000000,
+               .frequency_min  = 55000000,
                .frequency_max  = 862000000,
        },
 
@@ -360,6 +380,7 @@ static int si2157_probe(struct i2c_client *client,
        dev->inversion = cfg->inversion;
        dev->fw_loaded = false;
        dev->chiptype = (u8)id->driver_data;
+       dev->if_frequency = 5000000; /* default value of property 0x0706 */
        mutex_init(&dev->i2c_mutex);
 
        /* check if the tuner is there */
index 7aa53bce559335be9ff2a1180e6f84f5e3c9c264..cd8fa5b253047081d47b152cac551814e811ff76 100644 (file)
@@ -28,6 +28,7 @@ struct si2157_dev {
        bool fw_loaded;
        bool inversion;
        u8 chiptype;
+       u32 if_frequency;
 };
 
 #define SI2157_CHIPTYPE_SI2157 0
index 366410e0cc9a2dc5fdedc8ea584a30710b7c4346..1eacb4f84e937d5adbc819b28b794c9aa3b40540 100644 (file)
@@ -30,7 +30,7 @@ struct tda18218_config {
        u8 loop_through:1;
 };
 
-#if IS_ENABLED(CONFIG_MEDIA_TUNER_TDA18218)
+#if IS_REACHABLE(CONFIG_MEDIA_TUNER_TDA18218)
 extern struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe,
        struct i2c_adapter *i2c, struct tda18218_config *cfg);
 #else
index 4c418d63f540d539f049781be691d9388b7dcdea..0a846333ce57cd289c8bb7f62462c4c7949f7bed 100644 (file)
@@ -121,7 +121,7 @@ enum tda18271_mode {
        TDA18271_DIGITAL,
 };
 
-#if IS_ENABLED(CONFIG_MEDIA_TUNER_TDA18271)
+#if IS_REACHABLE(CONFIG_MEDIA_TUNER_TDA18271)
 extern struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
                                            struct i2c_adapter *i2c,
                                            struct tda18271_config *cfg);
index b64292152baf535831e0ce77902308f13a6dedb7..abf2e2fe53507b6fcff3d3435e305df8b244a2e0 100644 (file)
@@ -51,7 +51,7 @@ struct tda827x_config
  * @param cfg optional callback function pointers.
  * @return FE pointer on success, NULL on failure.
  */
-#if IS_ENABLED(CONFIG_MEDIA_TUNER_TDA827X)
+#if IS_REACHABLE(CONFIG_MEDIA_TUNER_TDA827X)
 extern struct dvb_frontend* tda827x_attach(struct dvb_frontend *fe, int addr,
                                           struct i2c_adapter *i2c,
                                           struct tda827x_config *cfg);
index cf96e585785e37bae9ebe15f5feecb75c240eb22..901b8cac7105e27eaa0e28a5ec6d6a35a1794999 100644 (file)
@@ -38,7 +38,7 @@ struct tda829x_config {
        struct tda18271_std_map *tda18271_std_map;
 };
 
-#if IS_ENABLED(CONFIG_MEDIA_TUNER_TDA8290)
+#if IS_REACHABLE(CONFIG_MEDIA_TUNER_TDA8290)
 extern int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr);
 
 extern struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
index 37a4a1123e0cfacae72b12456687d480ab65e343..95070eca02ca179432d93cfe725e0e97c597ef69 100644 (file)
@@ -21,7 +21,7 @@
 #include "dvb_frontend.h"
 
 /* ------------------------------------------------------------------------ */
-#if IS_ENABLED(CONFIG_MEDIA_TUNER_TDA9887)
+#if IS_REACHABLE(CONFIG_MEDIA_TUNER_TDA9887)
 extern struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
                                           struct i2c_adapter *i2c_adap,
                                           u8 i2c_addr);
index 933228ffb5095c95c39088c193d95d3d83b24c94..2d624d9919e3a263806a4b8eb3425592e7a22074 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/i2c.h>
 #include "dvb_frontend.h"
 
-#if IS_ENABLED(CONFIG_MEDIA_TUNER_TEA5761)
+#if IS_REACHABLE(CONFIG_MEDIA_TUNER_TEA5761)
 extern int tea5761_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr);
 
 extern struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe,
index c391011993831a79dc9393d7ff6c8609e3518944..4f6f6c92db78b6d76938a153f78a0d297478be5e 100644 (file)
@@ -39,7 +39,7 @@ struct tea5767_ctrl {
        enum tea5767_xtal       xtal_freq;
 };
 
-#if IS_ENABLED(CONFIG_MEDIA_TUNER_TEA5767)
+#if IS_REACHABLE(CONFIG_MEDIA_TUNER_TEA5767)
 extern int tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr);
 
 extern struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe,
index 26358da1c10016fcd6ae33ec1e7692ad7b9a0290..2c3375c7aeb9eaf8677b7fd9d81f28cfeb33aaf5 100644 (file)
@@ -51,7 +51,7 @@ struct tua9001_config {
 #define TUA9001_CMD_RESETN  1
 #define TUA9001_CMD_RXEN    2
 
-#if IS_ENABLED(CONFIG_MEDIA_TUNER_TUA9001)
+#if IS_REACHABLE(CONFIG_MEDIA_TUNER_TUA9001)
 extern struct dvb_frontend *tua9001_attach(struct dvb_frontend *fe,
                struct i2c_adapter *i2c, struct tua9001_config *cfg);
 #else
index ffd12cfe650b8e89d5560abe17d8e07185bf1a6e..6399b45b0590b80835b95fe350411d1a509332b4 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/i2c.h>
 #include "dvb_frontend.h"
 
-#if IS_ENABLED(CONFIG_MEDIA_TUNER_SIMPLE)
+#if IS_REACHABLE(CONFIG_MEDIA_TUNER_SIMPLE)
 extern struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
                                                struct i2c_adapter *i2c_adap,
                                                u8 i2c_addr,
index 181d087faec4a1795cf5ac7eabb8972a76400a7f..98e4effca8964e60b60b2fda82fcc8e8b45a7c40 100644 (file)
@@ -56,7 +56,7 @@ struct xc2028_config {
 #define XC2028_RESET_CLK       1
 #define XC2028_I2C_FLUSH       2
 
-#if IS_ENABLED(CONFIG_MEDIA_TUNER_XC2028)
+#if IS_REACHABLE(CONFIG_MEDIA_TUNER_XC2028)
 extern struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
                                          struct xc2028_config *cfg);
 #else
index 97c23de5296c635aa7db9e656fa6639e9aeab2a0..40517860cf67ff85b261dc3470c2343da27b1835 100644 (file)
@@ -50,7 +50,7 @@ struct xc4000_config {
  * it's passed back to a bridge during tuner_callback().
  */
 
-#if IS_ENABLED(CONFIG_MEDIA_TUNER_XC4000)
+#if IS_REACHABLE(CONFIG_MEDIA_TUNER_XC4000)
 extern struct dvb_frontend *xc4000_attach(struct dvb_frontend *fe,
                                          struct i2c_adapter *i2c,
                                          struct xc4000_config *cfg);
index 2a039de8ab9ae822917ac65c36b40002897b998e..e6e5e90d8d959cb7817a8ca65e63e80fb8031e93 100644 (file)
@@ -1336,7 +1336,10 @@ static int xc5000_release(struct dvb_frontend *fe)
 
        if (priv) {
                cancel_delayed_work(&priv->timer_sleep);
-               release_firmware(priv->firmware);
+               if (priv->firmware) {
+                       release_firmware(priv->firmware);
+                       priv->firmware = NULL;
+               }
                hybrid_tuner_release_state(priv);
        }
 
index 6aa534f17a3079333c9ace2725a71553536b0858..00ba29e21fb96ffa2d0aae6874b99273e87b769b 100644 (file)
@@ -58,7 +58,7 @@ struct xc5000_config {
  * it's passed back to a bridge during tuner_callback().
  */
 
-#if IS_ENABLED(CONFIG_MEDIA_TUNER_XC5000)
+#if IS_REACHABLE(CONFIG_MEDIA_TUNER_XC5000)
 extern struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
                                          struct i2c_adapter *i2c,
                                          const struct xc5000_config *cfg);
index a27cb5fcdef83b152ff0f7cea1e72031a204b88c..1a362a041ab3f33061be2113a4d984be6c577245 100644 (file)
@@ -299,29 +299,23 @@ static int au0828_init_isoc(struct au0828_dev *dev, int max_packets,
  * Announces that a buffer were filled and request the next
  */
 static inline void buffer_filled(struct au0828_dev *dev,
-                                 struct au0828_dmaqueue *dma_q,
-                                 struct au0828_buffer *buf)
+                                struct au0828_dmaqueue *dma_q,
+                                struct au0828_buffer *buf)
 {
-       /* Advice that buffer was filled */
-       au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->top_field);
+       struct vb2_buffer *vb = &buf->vb;
+       struct vb2_queue *q = vb->vb2_queue;
 
-       buf->vb.v4l2_buf.sequence = dev->frame_count++;
-       buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
-       v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
-       vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
-}
-
-static inline void vbi_buffer_filled(struct au0828_dev *dev,
-                                    struct au0828_dmaqueue *dma_q,
-                                    struct au0828_buffer *buf)
-{
        /* Advice that buffer was filled */
        au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->top_field);
 
-       buf->vb.v4l2_buf.sequence = dev->vbi_frame_count++;
-       buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
-       v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
-       vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+       if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               vb->v4l2_buf.sequence = dev->frame_count++;
+       else
+               vb->v4l2_buf.sequence = dev->vbi_frame_count++;
+
+       vb->v4l2_buf.field = V4L2_FIELD_INTERLACED;
+       v4l2_get_timestamp(&vb->v4l2_buf.timestamp);
+       vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
 }
 
 /*
@@ -574,9 +568,7 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
                        if (fbyte & 0x40) {
                                /* VBI */
                                if (vbi_buf != NULL)
-                                       vbi_buffer_filled(dev,
-                                                         vbi_dma_q,
-                                                         vbi_buf);
+                                       buffer_filled(dev, vbi_dma_q, vbi_buf);
                                vbi_get_next_buf(vbi_dma_q, &vbi_buf);
                                if (vbi_buf == NULL)
                                        vbioutp = NULL;
@@ -899,12 +891,8 @@ void au0828_analog_unregister(struct au0828_dev *dev)
 {
        dprintk(1, "au0828_analog_unregister called\n");
        mutex_lock(&au0828_sysfs_lock);
-
-       if (dev->vdev)
-               video_unregister_device(dev->vdev);
-       if (dev->vbi_dev)
-               video_unregister_device(dev->vbi_dev);
-
+       video_unregister_device(&dev->vdev);
+       video_unregister_device(&dev->vbi_dev);
        mutex_unlock(&au0828_sysfs_lock);
 }
 
@@ -949,7 +937,7 @@ static void au0828_vbi_buffer_timeout(unsigned long data)
        if (buf != NULL) {
                vbi_data = vb2_plane_vaddr(&buf->vb, 0);
                memset(vbi_data, 0x00, buf->length);
-               vbi_buffer_filled(dev, dma_q, buf);
+               buffer_filled(dev, dma_q, buf);
        }
        vbi_get_next_buf(dma_q, &buf);
 
@@ -1286,7 +1274,7 @@ static int vidioc_enum_input(struct file *file, void *priv,
                input->audioset = 2;
        }
 
-       input->std = dev->vdev->tvnorms;
+       input->std = dev->vdev.tvnorms;
 
        return 0;
 }
@@ -1704,7 +1692,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
 
 static const struct video_device au0828_video_template = {
        .fops                       = &au0828_v4l_fops,
-       .release                    = video_device_release,
+       .release                    = video_device_release_empty,
        .ioctl_ops                  = &video_ioctl_ops,
        .tvnorms                    = V4L2_STD_NTSC_M | V4L2_STD_PAL_M,
 };
@@ -1814,52 +1802,36 @@ int au0828_analog_register(struct au0828_dev *dev,
        dev->std = V4L2_STD_NTSC_M;
        au0828_s_input(dev, 0);
 
-       /* allocate and fill v4l2 video struct */
-       dev->vdev = video_device_alloc();
-       if (NULL == dev->vdev) {
-               dprintk(1, "Can't allocate video_device.\n");
-               return -ENOMEM;
-       }
-
-       /* allocate the VBI struct */
-       dev->vbi_dev = video_device_alloc();
-       if (NULL == dev->vbi_dev) {
-               dprintk(1, "Can't allocate vbi_device.\n");
-               ret = -ENOMEM;
-               goto err_vdev;
-       }
-
        mutex_init(&dev->vb_queue_lock);
        mutex_init(&dev->vb_vbi_queue_lock);
 
        /* Fill the video capture device struct */
-       *dev->vdev = au0828_video_template;
-       dev->vdev->v4l2_dev = &dev->v4l2_dev;
-       dev->vdev->lock = &dev->lock;
-       dev->vdev->queue = &dev->vb_vidq;
-       dev->vdev->queue->lock = &dev->vb_queue_lock;
-       strcpy(dev->vdev->name, "au0828a video");
+       dev->vdev = au0828_video_template;
+       dev->vdev.v4l2_dev = &dev->v4l2_dev;
+       dev->vdev.lock = &dev->lock;
+       dev->vdev.queue = &dev->vb_vidq;
+       dev->vdev.queue->lock = &dev->vb_queue_lock;
+       strcpy(dev->vdev.name, "au0828a video");
 
        /* Setup the VBI device */
-       *dev->vbi_dev = au0828_video_template;
-       dev->vbi_dev->v4l2_dev = &dev->v4l2_dev;
-       dev->vbi_dev->lock = &dev->lock;
-       dev->vbi_dev->queue = &dev->vb_vbiq;
-       dev->vbi_dev->queue->lock = &dev->vb_vbi_queue_lock;
-       strcpy(dev->vbi_dev->name, "au0828a vbi");
+       dev->vbi_dev = au0828_video_template;
+       dev->vbi_dev.v4l2_dev = &dev->v4l2_dev;
+       dev->vbi_dev.lock = &dev->lock;
+       dev->vbi_dev.queue = &dev->vb_vbiq;
+       dev->vbi_dev.queue->lock = &dev->vb_vbi_queue_lock;
+       strcpy(dev->vbi_dev.name, "au0828a vbi");
 
        /* initialize videobuf2 stuff */
        retval = au0828_vb2_setup(dev);
        if (retval != 0) {
                dprintk(1, "unable to setup videobuf2 queues (error = %d).\n",
                        retval);
-               ret = -ENODEV;
-               goto err_vbi_dev;
+               return -ENODEV;
        }
 
        /* Register the v4l2 device */
-       video_set_drvdata(dev->vdev, dev);
-       retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1);
+       video_set_drvdata(&dev->vdev, dev);
+       retval = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1);
        if (retval != 0) {
                dprintk(1, "unable to register video device (error = %d).\n",
                        retval);
@@ -1868,8 +1840,8 @@ int au0828_analog_register(struct au0828_dev *dev,
        }
 
        /* Register the vbi device */
-       video_set_drvdata(dev->vbi_dev, dev);
-       retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1);
+       video_set_drvdata(&dev->vbi_dev, dev);
+       retval = video_register_device(&dev->vbi_dev, VFL_TYPE_VBI, -1);
        if (retval != 0) {
                dprintk(1, "unable to register vbi device (error = %d).\n",
                        retval);
@@ -1882,14 +1854,10 @@ int au0828_analog_register(struct au0828_dev *dev,
        return 0;
 
 err_reg_vbi_dev:
-       video_unregister_device(dev->vdev);
+       video_unregister_device(&dev->vdev);
 err_reg_vdev:
        vb2_queue_release(&dev->vb_vidq);
        vb2_queue_release(&dev->vb_vbiq);
-err_vbi_dev:
-       video_device_release(dev->vbi_dev);
-err_vdev:
-       video_device_release(dev->vdev);
        return ret;
 }
 
index eb1518742ae627f9f192f618fd4bc648e373129b..3b480005ce3be6576fd83348e016af8688b990fc 100644 (file)
@@ -209,8 +209,8 @@ struct au0828_dev {
        struct au0828_rc *ir;
 #endif
 
-       struct video_device *vdev;
-       struct video_device *vbi_dev;
+       struct video_device vdev;
+       struct video_device vbi_dev;
 
        /* Videobuf2 */
        struct vb2_queue vb_vidq;
index 173c0e287a08d528c91f9a810b869f38619d4454..0cced3e5b040bfddc8696d030aa3752003108e9f 100644 (file)
@@ -47,6 +47,7 @@ config VIDEO_CX231XX_DVB
        select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT
        select DVB_MB86A20S if MEDIA_SUBDRV_AUTOSELECT
        select DVB_LGDT3305 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_LGDT3306A if MEDIA_SUBDRV_AUTOSELECT
        select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT
        select DVB_SI2165 if MEDIA_SUBDRV_AUTOSELECT
        select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT
index 3f295b4d1a3dc25c76f76adb670b00fd49c57cc3..983ea83391540a0600635a418d8c6f56a48092b0 100644 (file)
@@ -1868,13 +1868,9 @@ void cx231xx_417_unregister(struct cx231xx *dev)
        dprintk(1, "%s()\n", __func__);
        dprintk(3, "%s()\n", __func__);
 
-       if (dev->v4l_device) {
-               if (-1 != dev->v4l_device->minor)
-                       video_unregister_device(dev->v4l_device);
-               else
-                       video_device_release(dev->v4l_device);
+       if (video_is_registered(&dev->v4l_device)) {
+               video_unregister_device(&dev->v4l_device);
                v4l2_ctrl_handler_free(&dev->mpeg_ctrl_handler.hdl);
-               dev->v4l_device = NULL;
        }
 }
 
@@ -1911,25 +1907,21 @@ static struct cx2341x_handler_ops cx231xx_ops = {
        .s_video_encoding = cx231xx_s_video_encoding,
 };
 
-static struct video_device *cx231xx_video_dev_alloc(
+static void cx231xx_video_dev_init(
        struct cx231xx *dev,
        struct usb_device *usbdev,
-       struct video_device *template,
-       char *type)
+       struct video_device *vfd,
+       const struct video_device *template,
+       const char *type)
 {
-       struct video_device *vfd;
-
        dprintk(1, "%s()\n", __func__);
-       vfd = video_device_alloc();
-       if (NULL == vfd)
-               return NULL;
        *vfd = *template;
        snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name,
                type, cx231xx_boards[dev->model].name);
 
        vfd->v4l2_dev = &dev->v4l2_dev;
        vfd->lock = &dev->lock;
-       vfd->release = video_device_release;
+       vfd->release = video_device_release_empty;
        vfd->ctrl_handler = &dev->mpeg_ctrl_handler.hdl;
        video_set_drvdata(vfd, dev);
        if (dev->tuner_type == TUNER_ABSENT) {
@@ -1938,9 +1930,6 @@ static struct video_device *cx231xx_video_dev_alloc(
                v4l2_disable_ioctl(vfd, VIDIOC_G_TUNER);
                v4l2_disable_ioctl(vfd, VIDIOC_S_TUNER);
        }
-
-       return vfd;
-
 }
 
 int cx231xx_417_register(struct cx231xx *dev)
@@ -1983,9 +1972,9 @@ int cx231xx_417_register(struct cx231xx *dev)
        cx2341x_handler_set_50hz(&dev->mpeg_ctrl_handler, false);
 
        /* Allocate and initialize V4L video device */
-       dev->v4l_device = cx231xx_video_dev_alloc(dev,
-               dev->udev, &cx231xx_mpeg_template, "mpeg");
-       err = video_register_device(dev->v4l_device,
+       cx231xx_video_dev_init(dev, dev->udev,
+                       &dev->v4l_device, &cx231xx_mpeg_template, "mpeg");
+       err = video_register_device(&dev->v4l_device,
                VFL_TYPE_GRABBER, -1);
        if (err < 0) {
                dprintk(3, "%s: can't register mpeg device\n", dev->name);
@@ -1994,7 +1983,7 @@ int cx231xx_417_register(struct cx231xx *dev)
        }
 
        dprintk(3, "%s: registered device video%d [mpeg]\n",
-              dev->name, dev->v4l_device->num);
+              dev->name, dev->v4l_device.num);
 
        return 0;
 }
index da03733690bda74387832e89705493ec4f538304..fe00da105e77519bbf7c15684db8ae55593dac7e 100644 (file)
@@ -757,6 +757,45 @@ struct cx231xx_board cx231xx_boards[] = {
                .demod_addr = 0x0e,
                .norm = V4L2_STD_PAL,
 
+               .input = {{
+                       .type = CX231XX_VMUX_TELEVISION,
+                       .vmux = CX231XX_VIN_3_1,
+                       .amux = CX231XX_AMUX_VIDEO,
+                       .gpio = NULL,
+               }, {
+                       .type = CX231XX_VMUX_COMPOSITE1,
+                       .vmux = CX231XX_VIN_2_1,
+                       .amux = CX231XX_AMUX_LINE_IN,
+                       .gpio = NULL,
+               }, {
+                       .type = CX231XX_VMUX_SVIDEO,
+                       .vmux = CX231XX_VIN_1_1 |
+                               (CX231XX_VIN_1_2 << 8) |
+                               CX25840_SVIDEO_ON,
+                       .amux = CX231XX_AMUX_LINE_IN,
+                       .gpio = NULL,
+               } },
+       },
+       [CX231XX_BOARD_HAUPPAUGE_955Q] = {
+               .name = "Hauppauge WinTV-HVR-955Q (111401)",
+               .tuner_type = TUNER_ABSENT,
+               .tuner_addr = 0x60,
+               .tuner_gpio = RDE250_XCV_TUNER,
+               .tuner_sif_gpio = 0x05,
+               .tuner_scl_gpio = 0x1a,
+               .tuner_sda_gpio = 0x1b,
+               .decoder = CX231XX_AVDECODER,
+               .output_mode = OUT_MODE_VIP11,
+               .demod_xfer_mode = 0,
+               .ctl_pin_status_mask = 0xFFFFFFC4,
+               .agc_analog_digital_select_gpio = 0x0c,
+               .gpio_pin_status_mask = 0x4001000,
+               .tuner_i2c_master = I2C_1_MUX_3,
+               .demod_i2c_master = I2C_2,
+               .has_dvb = 1,
+               .demod_addr = 0x0e,
+               .norm = V4L2_STD_NTSC,
+
                .input = {{
                        .type = CX231XX_VMUX_TELEVISION,
                        .vmux = CX231XX_VIN_3_1,
@@ -805,6 +844,8 @@ struct usb_device_id cx231xx_id_table[] = {
         .driver_info = CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC},
        {USB_DEVICE(0x2040, 0xb120),
         .driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER},
+       {USB_DEVICE(0x2040, 0xb123),
+        .driver_info = CX231XX_BOARD_HAUPPAUGE_955Q},
        {USB_DEVICE(0x2040, 0xb130),
         .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx},
        {USB_DEVICE(0x2040, 0xb131),
@@ -912,9 +953,6 @@ static inline void cx231xx_set_model(struct cx231xx *dev)
  */
 void cx231xx_pre_card_setup(struct cx231xx *dev)
 {
-
-       cx231xx_set_model(dev);
-
        dev_info(dev->dev, "Identified as %s (card=%d)\n",
                dev->board.name, dev->model);
 
@@ -1052,6 +1090,7 @@ void cx231xx_card_setup(struct cx231xx *dev)
        switch (dev->model) {
        case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx:
        case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx:
+       case CX231XX_BOARD_HAUPPAUGE_955Q:
                {
                        struct tveeprom tvee;
                        static u8 eeprom[256];
@@ -1092,6 +1131,17 @@ void cx231xx_config_i2c(struct cx231xx *dev)
        call_all(dev, video, s_stream, 1);
 }
 
+static void cx231xx_unregister_media_device(struct cx231xx *dev)
+{
+#ifdef CONFIG_MEDIA_CONTROLLER
+       if (dev->media_dev) {
+               media_device_unregister(dev->media_dev);
+               kfree(dev->media_dev);
+               dev->media_dev = NULL;
+       }
+#endif
+}
+
 /*
  * cx231xx_realease_resources()
  * unregisters the v4l2,i2c and usb devices
@@ -1099,6 +1149,8 @@ void cx231xx_config_i2c(struct cx231xx *dev)
 */
 void cx231xx_release_resources(struct cx231xx *dev)
 {
+       cx231xx_unregister_media_device(dev);
+
        cx231xx_release_analog_resources(dev);
 
        cx231xx_remove_from_devlist(dev);
@@ -1117,6 +1169,74 @@ void cx231xx_release_resources(struct cx231xx *dev)
        clear_bit(dev->devno, &cx231xx_devused);
 }
 
+static void cx231xx_media_device_register(struct cx231xx *dev,
+                                         struct usb_device *udev)
+{
+#ifdef CONFIG_MEDIA_CONTROLLER
+       struct media_device *mdev;
+       int ret;
+
+       mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
+       if (!mdev)
+               return;
+
+       mdev->dev = dev->dev;
+       strlcpy(mdev->model, dev->board.name, sizeof(mdev->model));
+       if (udev->serial)
+               strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial));
+       strcpy(mdev->bus_info, udev->devpath);
+       mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
+       mdev->driver_version = LINUX_VERSION_CODE;
+
+       ret = media_device_register(mdev);
+       if (ret) {
+               dev_err(dev->dev,
+                       "Couldn't create a media device. Error: %d\n",
+                       ret);
+               kfree(mdev);
+               return;
+       }
+
+       dev->media_dev = mdev;
+#endif
+}
+
+static void cx231xx_create_media_graph(struct cx231xx *dev)
+{
+#ifdef CONFIG_MEDIA_CONTROLLER
+       struct media_device *mdev = dev->media_dev;
+       struct media_entity *entity;
+       struct media_entity *tuner = NULL, *decoder = NULL;
+
+       if (!mdev)
+               return;
+
+       media_device_for_each_entity(entity, mdev) {
+               switch (entity->type) {
+               case MEDIA_ENT_T_V4L2_SUBDEV_TUNER:
+                       tuner = entity;
+                       break;
+               case MEDIA_ENT_T_V4L2_SUBDEV_DECODER:
+                       decoder = entity;
+                       break;
+               }
+       }
+
+       /* Analog setup, using tuner as a link */
+
+       if (!decoder)
+               return;
+
+       if (tuner)
+               media_entity_create_link(tuner, 0, decoder, 0,
+                                        MEDIA_LNK_FL_ENABLED);
+       media_entity_create_link(decoder, 1, &dev->vdev.entity, 0,
+                                MEDIA_LNK_FL_ENABLED);
+       media_entity_create_link(decoder, 2, &dev->vbi_dev.entity, 0,
+                                MEDIA_LNK_FL_ENABLED);
+#endif
+}
+
 /*
  * cx231xx_init_dev()
  * allocates and inits the device structs, registers i2c bus and v4l device
@@ -1225,10 +1345,8 @@ static int cx231xx_init_dev(struct cx231xx *dev, struct usb_device *udev,
        }
 
        retval = cx231xx_register_analog_devices(dev);
-       if (retval) {
-               cx231xx_release_analog_resources(dev);
+       if (retval)
                goto err_analog;
-       }
 
        cx231xx_ir_init(dev);
 
@@ -1236,6 +1354,8 @@ static int cx231xx_init_dev(struct cx231xx *dev, struct usb_device *udev,
 
        return 0;
 err_analog:
+       cx231xx_unregister_media_device(dev);
+       cx231xx_release_analog_resources(dev);
        cx231xx_remove_from_devlist(dev);
 err_dev_init:
        cx231xx_dev_uninit(dev);
@@ -1438,6 +1558,8 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
        dev->video_mode.alt = -1;
        dev->dev = d;
 
+       cx231xx_set_model(dev);
+
        dev->interface_count++;
        /* reset gpio dir and value */
        dev->gpio_dir = 0;
@@ -1502,7 +1624,13 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
        /* save our data pointer in this interface device */
        usb_set_intfdata(interface, dev);
 
+       /* Register the media controller */
+       cx231xx_media_device_register(dev, udev);
+
        /* Create v4l2 device */
+#ifdef CONFIG_MEDIA_CONTROLLER
+       dev->v4l2_dev.mdev = dev->media_dev;
+#endif
        retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev);
        if (retval) {
                dev_err(d, "v4l2_device_register failed\n");
@@ -1568,6 +1696,8 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
        /* load other modules required */
        request_modules(dev);
 
+       cx231xx_create_media_graph(dev);
+
        return 0;
 err_video_alt:
        /* cx231xx_uninit_dev: */
@@ -1618,7 +1748,7 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface)
        if (dev->users) {
                dev_warn(dev->dev,
                         "device %s is open! Deregistration and memory deallocation are deferred on close.\n",
-                        video_device_node_name(dev->vdev));
+                        video_device_node_name(&dev->vdev));
 
                /* Even having users, it is safe to remove the RC i2c driver */
                cx231xx_ir_exit(dev);
index 4a3f28c4e8d341e4fb4a8ad64311ec3015eff9a4..e42bde081cd797c1fc8a27f700d166f75bba4715 100644 (file)
@@ -176,16 +176,9 @@ int cx231xx_send_usb_command(struct cx231xx_i2c *i2c_bus,
        saddr_len = req_data->saddr_len;
 
        /* Set wValue */
-       if (saddr_len == 1)     /* need check saddr_len == 0  */
-               ven_req.wValue =
-                   req_data->
-                   dev_addr << 9 | _i2c_period << 4 | saddr_len << 2 |
-                   _i2c_nostop << 1 | I2C_SYNC | _i2c_reserve << 6;
-       else
-               ven_req.wValue =
-                   req_data->
-                   dev_addr << 9 | _i2c_period << 4 | saddr_len << 2 |
-                   _i2c_nostop << 1 | I2C_SYNC | _i2c_reserve << 6;
+       ven_req.wValue = (req_data->dev_addr << 9 | _i2c_period << 4 |
+                         saddr_len << 2 | _i2c_nostop << 1 | I2C_SYNC |
+                         _i2c_reserve << 6);
 
        /* set channel number */
        if (req_data->direction & I2C_M_RD) {
index dd600b994e698ae1ec15a880d6373ad347167afe..610d5675bde66e5cabd2727f5c31f30a1ef82493 100644 (file)
@@ -34,6 +34,7 @@
 #include "si2165.h"
 #include "mb86a20s.h"
 #include "si2157.h"
+#include "lgdt3306a.h"
 
 MODULE_DESCRIPTION("driver for cx231xx based DVB cards");
 MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>");
@@ -160,6 +161,18 @@ static const struct si2165_config pctv_quatro_stick_1114xx_si2165_config = {
        .ref_freq_Hz    = 24000000,
 };
 
+static struct lgdt3306a_config hauppauge_955q_lgdt3306a_config = {
+       .i2c_addr           = 0x59,
+       .qam_if_khz         = 4000,
+       .vsb_if_khz         = 3250,
+       .deny_i2c_rptr      = 1,
+       .spectral_inversion = 1,
+       .mpeg_mode          = LGDT3306A_MPEG_SERIAL,
+       .tpclk_edge         = LGDT3306A_TPCLK_RISING_EDGE,
+       .tpvalid_polarity   = LGDT3306A_TP_VALID_HIGH,
+       .xtalMHz            = 25,
+};
+
 static inline void print_err_status(struct cx231xx *dev, int packet, int status)
 {
        char *errmsg = "Unknown";
@@ -455,6 +468,7 @@ static int register_dvb(struct cx231xx_dvb *dvb,
 
        mutex_init(&dvb->lock);
 
+
        /* register adapter */
        result = dvb_register_adapter(&dvb->adapter, dev->name, module, device,
                                      adapter_nr);
@@ -464,6 +478,7 @@ static int register_dvb(struct cx231xx_dvb *dvb,
                       dev->name, result);
                goto fail_adapter;
        }
+       dvb_register_media_controller(&dvb->adapter, dev->media_dev);
 
        /* Ensure all frontends negotiate bus access */
        dvb->frontend->ops.ts_bus_ctrl = cx231xx_dvb_bus_ctrl;
@@ -536,6 +551,8 @@ static int register_dvb(struct cx231xx_dvb *dvb,
 
        /* register network adapter */
        dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
+       dvb_create_media_graph(&dvb->adapter);
+
        return 0;
 
 fail_fe_conn:
@@ -807,7 +824,61 @@ static int dvb_init(struct cx231xx *dev)
                dev->dvb->i2c_client_tuner = client;
                break;
        }
+       case CX231XX_BOARD_HAUPPAUGE_955Q:
+       {
+               struct i2c_client *client;
+               struct i2c_board_info info;
+               struct si2157_config si2157_config;
+
+               memset(&info, 0, sizeof(struct i2c_board_info));
+
+               dev->dvb->frontend = dvb_attach(lgdt3306a_attach,
+                       &hauppauge_955q_lgdt3306a_config,
+                       tuner_i2c
+                       );
+
+               if (dev->dvb->frontend == NULL) {
+                       dev_err(dev->dev,
+                               "Failed to attach LGDT3306A frontend.\n");
+                       result = -EINVAL;
+                       goto out_free;
+               }
+
+               dev->dvb->frontend->ops.i2c_gate_ctrl = NULL;
+
+               /* define general-purpose callback pointer */
+               dvb->frontend->callback = cx231xx_tuner_callback;
+
+               /* attach tuner */
+               memset(&si2157_config, 0, sizeof(si2157_config));
+               si2157_config.fe = dev->dvb->frontend;
+               si2157_config.inversion = true;
+               strlcpy(info.type, "si2157", I2C_NAME_SIZE);
+               info.addr = 0x60;
+               info.platform_data = &si2157_config;
+               request_module("si2157");
 
+               client = i2c_new_device(
+                       tuner_i2c,
+                       &info);
+               if (client == NULL || client->dev.driver == NULL) {
+                       dvb_frontend_detach(dev->dvb->frontend);
+                       result = -ENODEV;
+                       goto out_free;
+               }
+
+               if (!try_module_get(client->dev.driver->owner)) {
+                       i2c_unregister_device(client);
+                       dvb_frontend_detach(dev->dvb->frontend);
+                       result = -ENODEV;
+                       goto out_free;
+               }
+
+               dev->cx231xx_reset_analog_tuner = NULL;
+
+               dev->dvb->i2c_client_tuner = client;
+               break;
+       }
        case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
        case CX231XX_BOARD_KWORLD_UB430_USB_HYBRID:
 
index ecea76fe07f6121c8a44fbdc7b34d9456d0a400f..c261e160c158f92800669399205d2217ca85d85e 100644 (file)
@@ -100,6 +100,75 @@ static struct cx231xx_fmt format[] = {
 };
 
 
+static int cx231xx_enable_analog_tuner(struct cx231xx *dev)
+{
+#ifdef CONFIG_MEDIA_CONTROLLER
+       struct media_device *mdev = dev->media_dev;
+       struct media_entity  *entity, *decoder = NULL, *source;
+       struct media_link *link, *found_link = NULL;
+       int i, ret, active_links = 0;
+
+       if (!mdev)
+               return 0;
+
+       /*
+        * This will find the tuner that is connected into the decoder.
+        * Technically, this is not 100% correct, as the device may be
+        * using an analog input instead of the tuner. However, as we can't
+        * do DVB streaming while the DMA engine is being used for V4L2,
+        * this should be enough for the actual needs.
+        */
+       media_device_for_each_entity(entity, mdev) {
+               if (entity->type == MEDIA_ENT_T_V4L2_SUBDEV_DECODER) {
+                       decoder = entity;
+                       break;
+               }
+       }
+       if (!decoder)
+               return 0;
+
+       for (i = 0; i < decoder->num_links; i++) {
+               link = &decoder->links[i];
+               if (link->sink->entity == decoder) {
+                       found_link = link;
+                       if (link->flags & MEDIA_LNK_FL_ENABLED)
+                               active_links++;
+                       break;
+               }
+       }
+
+       if (active_links == 1 || !found_link)
+               return 0;
+
+       source = found_link->source->entity;
+       for (i = 0; i < source->num_links; i++) {
+               struct media_entity *sink;
+               int flags = 0;
+
+               link = &source->links[i];
+               sink = link->sink->entity;
+
+               if (sink == entity)
+                       flags = MEDIA_LNK_FL_ENABLED;
+
+               ret = media_entity_setup_link(link, flags);
+               if (ret) {
+                       dev_err(dev->dev,
+                               "Couldn't change link %s->%s to %s. Error %d\n",
+                               source->name, sink->name,
+                               flags ? "enabled" : "disabled",
+                               ret);
+                       return ret;
+               } else
+                       dev_dbg(dev->dev,
+                               "link %s->%s was %s\n",
+                               source->name, sink->name,
+                               flags ? "ENABLED" : "disabled");
+       }
+#endif
+       return 0;
+}
+
 /* ------------------------------------------------------------------
        Video buffer and parser functions
    ------------------------------------------------------------------*/
@@ -667,6 +736,9 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
        if (*count < CX231XX_MIN_BUF)
                *count = CX231XX_MIN_BUF;
 
+
+       cx231xx_enable_analog_tuner(dev);
+
        return 0;
 }
 
@@ -756,6 +828,7 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
        }
 
        buf->vb.state = VIDEOBUF_PREPARED;
+
        return 0;
 
 fail:
@@ -1056,7 +1129,7 @@ int cx231xx_enum_input(struct file *file, void *priv,
            (CX231XX_VMUX_CABLE == INPUT(n)->type))
                i->type = V4L2_INPUT_TYPE_TUNER;
 
-       i->std = dev->vdev->tvnorms;
+       i->std = dev->vdev.tvnorms;
 
        /* If they are asking about the active input, read signal status */
        if (n == dev->video_input) {
@@ -1451,7 +1524,7 @@ int cx231xx_querycap(struct file *file, void *priv,
        cap->capabilities = cap->device_caps | V4L2_CAP_READWRITE |
                V4L2_CAP_VBI_CAPTURE | V4L2_CAP_VIDEO_CAPTURE |
                V4L2_CAP_STREAMING | V4L2_CAP_DEVICE_CAPS;
-       if (dev->radio_dev)
+       if (video_is_registered(&dev->radio_dev))
                cap->capabilities |= V4L2_CAP_RADIO;
 
        return 0;
@@ -1729,34 +1802,21 @@ void cx231xx_release_analog_resources(struct cx231xx *dev)
 
        /*FIXME: I2C IR should be disconnected */
 
-       if (dev->radio_dev) {
-               if (video_is_registered(dev->radio_dev))
-                       video_unregister_device(dev->radio_dev);
-               else
-                       video_device_release(dev->radio_dev);
-               dev->radio_dev = NULL;
-       }
-       if (dev->vbi_dev) {
+       if (video_is_registered(&dev->radio_dev))
+               video_unregister_device(&dev->radio_dev);
+       if (video_is_registered(&dev->vbi_dev)) {
                dev_info(dev->dev, "V4L2 device %s deregistered\n",
-                       video_device_node_name(dev->vbi_dev));
-               if (video_is_registered(dev->vbi_dev))
-                       video_unregister_device(dev->vbi_dev);
-               else
-                       video_device_release(dev->vbi_dev);
-               dev->vbi_dev = NULL;
+                       video_device_node_name(&dev->vbi_dev));
+               video_unregister_device(&dev->vbi_dev);
        }
-       if (dev->vdev) {
+       if (video_is_registered(&dev->vdev)) {
                dev_info(dev->dev, "V4L2 device %s deregistered\n",
-                       video_device_node_name(dev->vdev));
+                       video_device_node_name(&dev->vdev));
 
                if (dev->board.has_417)
                        cx231xx_417_unregister(dev);
 
-               if (video_is_registered(dev->vdev))
-                       video_unregister_device(dev->vdev);
-               else
-                       video_device_release(dev->vdev);
-               dev->vdev = NULL;
+               video_unregister_device(&dev->vdev);
        }
        v4l2_ctrl_handler_free(&dev->ctrl_handler);
        v4l2_ctrl_handler_free(&dev->radio_ctrl_handler);
@@ -2013,7 +2073,7 @@ static struct video_device cx231xx_vbi_template;
 
 static const struct video_device cx231xx_video_template = {
        .fops         = &cx231xx_v4l_fops,
-       .release      = video_device_release,
+       .release      = video_device_release_empty,
        .ioctl_ops    = &video_ioctl_ops,
        .tvnorms      = V4L2_STD_ALL,
 };
@@ -2049,19 +2109,14 @@ static struct video_device cx231xx_radio_template = {
 
 /******************************** usb interface ******************************/
 
-static struct video_device *cx231xx_vdev_init(struct cx231xx *dev,
-               const struct video_device
-               *template, const char *type_name)
+static void cx231xx_vdev_init(struct cx231xx *dev,
+               struct video_device *vfd,
+               const struct video_device *template,
+               const char *type_name)
 {
-       struct video_device *vfd;
-
-       vfd = video_device_alloc();
-       if (NULL == vfd)
-               return NULL;
-
        *vfd = *template;
        vfd->v4l2_dev = &dev->v4l2_dev;
-       vfd->release = video_device_release;
+       vfd->release = video_device_release_empty;
        vfd->lock = &dev->lock;
 
        snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name);
@@ -2073,7 +2128,6 @@ static struct video_device *cx231xx_vdev_init(struct cx231xx *dev,
                v4l2_disable_ioctl(vfd, VIDIOC_G_TUNER);
                v4l2_disable_ioctl(vfd, VIDIOC_S_TUNER);
        }
-       return vfd;
 }
 
 int cx231xx_register_analog_devices(struct cx231xx *dev)
@@ -2116,15 +2170,16 @@ int cx231xx_register_analog_devices(struct cx231xx *dev)
        /* write code here...  */
 
        /* allocate and fill video video_device struct */
-       dev->vdev = cx231xx_vdev_init(dev, &cx231xx_video_template, "video");
-       if (!dev->vdev) {
-               dev_err(dev->dev, "cannot allocate video_device.\n");
-               return -ENODEV;
-       }
-
-       dev->vdev->ctrl_handler = &dev->ctrl_handler;
+       cx231xx_vdev_init(dev, &dev->vdev, &cx231xx_video_template, "video");
+#if defined(CONFIG_MEDIA_CONTROLLER)
+       dev->video_pad.flags = MEDIA_PAD_FL_SINK;
+       ret = media_entity_init(&dev->vdev.entity, 1, &dev->video_pad, 0);
+       if (ret < 0)
+               dev_err(dev->dev, "failed to initialize video media entity!\n");
+#endif
+       dev->vdev.ctrl_handler = &dev->ctrl_handler;
        /* register v4l2 video video_device */
-       ret = video_register_device(dev->vdev, VFL_TYPE_GRABBER,
+       ret = video_register_device(&dev->vdev, VFL_TYPE_GRABBER,
                                    video_nr[dev->devno]);
        if (ret) {
                dev_err(dev->dev,
@@ -2134,22 +2189,24 @@ int cx231xx_register_analog_devices(struct cx231xx *dev)
        }
 
        dev_info(dev->dev, "Registered video device %s [v4l2]\n",
-               video_device_node_name(dev->vdev));
+               video_device_node_name(&dev->vdev));
 
        /* Initialize VBI template */
        cx231xx_vbi_template = cx231xx_video_template;
        strcpy(cx231xx_vbi_template.name, "cx231xx-vbi");
 
        /* Allocate and fill vbi video_device struct */
-       dev->vbi_dev = cx231xx_vdev_init(dev, &cx231xx_vbi_template, "vbi");
+       cx231xx_vdev_init(dev, &dev->vbi_dev, &cx231xx_vbi_template, "vbi");
 
-       if (!dev->vbi_dev) {
-               dev_err(dev->dev, "cannot allocate video_device.\n");
-               return -ENODEV;
-       }
-       dev->vbi_dev->ctrl_handler = &dev->ctrl_handler;
+#if defined(CONFIG_MEDIA_CONTROLLER)
+       dev->vbi_pad.flags = MEDIA_PAD_FL_SINK;
+       ret = media_entity_init(&dev->vbi_dev.entity, 1, &dev->vbi_pad, 0);
+       if (ret < 0)
+               dev_err(dev->dev, "failed to initialize vbi media entity!\n");
+#endif
+       dev->vbi_dev.ctrl_handler = &dev->ctrl_handler;
        /* register v4l2 vbi video_device */
-       ret = video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
+       ret = video_register_device(&dev->vbi_dev, VFL_TYPE_VBI,
                                    vbi_nr[dev->devno]);
        if (ret < 0) {
                dev_err(dev->dev, "unable to register vbi device\n");
@@ -2157,18 +2214,13 @@ int cx231xx_register_analog_devices(struct cx231xx *dev)
        }
 
        dev_info(dev->dev, "Registered VBI device %s\n",
-               video_device_node_name(dev->vbi_dev));
+               video_device_node_name(&dev->vbi_dev));
 
        if (cx231xx_boards[dev->model].radio.type == CX231XX_RADIO) {
-               dev->radio_dev = cx231xx_vdev_init(dev, &cx231xx_radio_template,
-                                                  "radio");
-               if (!dev->radio_dev) {
-                       dev_err(dev->dev,
-                               "cannot allocate video_device.\n");
-                       return -ENODEV;
-               }
-               dev->radio_dev->ctrl_handler = &dev->radio_ctrl_handler;
-               ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO,
+               cx231xx_vdev_init(dev, &dev->radio_dev,
+                               &cx231xx_radio_template, "radio");
+               dev->radio_dev.ctrl_handler = &dev->radio_ctrl_handler;
+               ret = video_register_device(&dev->radio_dev, VFL_TYPE_RADIO,
                                            radio_nr[dev->devno]);
                if (ret < 0) {
                        dev_err(dev->dev,
@@ -2176,7 +2228,7 @@ int cx231xx_register_analog_devices(struct cx231xx *dev)
                        return ret;
                }
                dev_info(dev->dev, "Registered radio device as %s\n",
-                       video_device_node_name(dev->radio_dev));
+                       video_device_node_name(&dev->radio_dev));
        }
 
        return 0;
index 6d6f3ee812f64f40dbbd7fa0ba1d3475875e8ab6..00d3bce9a690c53aa2da077d0db805aae6c43992 100644 (file)
@@ -76,6 +76,7 @@
 #define CX231XX_BOARD_KWORLD_UB445_USB_HYBRID 18
 #define CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx 19
 #define CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx 20
+#define CX231XX_BOARD_HAUPPAUGE_955Q 21
 
 /* Limits minimum and default number of buffers */
 #define CX231XX_MIN_BUF                 4
@@ -633,7 +634,7 @@ struct cx231xx {
 
        /* video for linux */
        int users;              /* user count for exclusive use */
-       struct video_device *vdev;      /* video for linux device struct */
+       struct video_device vdev;       /* video for linux device struct */
        v4l2_std_id norm;       /* selected tv norm */
        int ctl_freq;           /* selected frequency */
        unsigned int ctl_ainput;        /* selected audio input */
@@ -655,8 +656,13 @@ struct cx231xx {
        struct mutex ctrl_urb_lock;     /* protects urb_buf */
        struct list_head inqueue, outqueue;
        wait_queue_head_t open, wait_frame, wait_stream;
-       struct video_device *vbi_dev;
-       struct video_device *radio_dev;
+       struct video_device vbi_dev;
+       struct video_device radio_dev;
+
+#if defined(CONFIG_MEDIA_CONTROLLER)
+       struct media_device *media_dev;
+       struct media_pad video_pad, vbi_pad;
+#endif
 
        unsigned char eedata[256];
 
@@ -718,7 +724,7 @@ struct cx231xx {
        u8 USE_ISO;
        struct cx231xx_tvnorm      encodernorm;
        struct cx231xx_tsport      ts1, ts2;
-       struct video_device        *v4l_device;
+       struct video_device        v4l_device;
        atomic_t                   v4l_reader_count;
        u32                        freq;
        unsigned int               input;
@@ -972,8 +978,11 @@ extern void cx231xx_417_unregister(struct cx231xx *dev);
 int cx231xx_ir_init(struct cx231xx *dev);
 void cx231xx_ir_exit(struct cx231xx *dev);
 #else
-#define cx231xx_ir_init(dev)   (0)
-#define cx231xx_ir_exit(dev)   (0)
+static inline int cx231xx_ir_init(struct cx231xx *dev)
+{
+       return 0;
+}
+static inline void cx231xx_ir_exit(struct cx231xx *dev) {}
 #endif
 
 static inline unsigned int norm_maxw(struct cx231xx *dev)
index 0982e734fab53ffd80dde865fd21aafde9f34fd1..9facc92c8dea53da1c516120b849a10433a60f95 100644 (file)
@@ -146,7 +146,7 @@ config DVB_USB_DVBSKY
        depends on DVB_USB_V2
        select DVB_M88DS3103 if MEDIA_SUBDRV_AUTOSELECT
        select DVB_SI2168 if MEDIA_SUBDRV_AUTOSELECT
-       select MEDIA_TUNER_M88TS2022 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TS2020 if MEDIA_SUBDRV_AUTOSELECT
        select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT
        select DVB_SP2 if MEDIA_SUBDRV_AUTOSELECT
        help
index 41c6363dff0896786add58914637d92cacc87c8f..023d91f7e6542f0905af07964648988c252a5ad7 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/usb/input.h>
 #include <linux/firmware.h>
 #include <media/rc-core.h>
+#include <media/media-device.h>
 
 #include "dvb_frontend.h"
 #include "dvb_demux.h"
index 9913e0f59485ef5b120d3e7627878f8da06d186f..f5df9eaba04fb0843e40bb26555aec4eb8c0c641 100644 (file)
@@ -400,10 +400,61 @@ skip_feed_stop:
        return ret;
 }
 
+static void dvb_usbv2_media_device_register(struct dvb_usb_adapter *adap)
+{
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+       struct media_device *mdev;
+       struct dvb_usb_device *d = adap_to_d(adap);
+       struct usb_device *udev = d->udev;
+       int ret;
+
+       mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
+       if (!mdev)
+               return;
+
+       mdev->dev = &udev->dev;
+       strlcpy(mdev->model, d->name, sizeof(mdev->model));
+       if (udev->serial)
+               strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial));
+       strcpy(mdev->bus_info, udev->devpath);
+       mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
+       mdev->driver_version = LINUX_VERSION_CODE;
+
+       ret = media_device_register(mdev);
+       if (ret) {
+               dev_err(&d->udev->dev,
+                       "Couldn't create a media device. Error: %d\n",
+                       ret);
+               kfree(mdev);
+               return;
+       }
+
+       dvb_register_media_controller(&adap->dvb_adap, mdev);
+
+       dev_info(&d->udev->dev, "media controller created\n");
+
+#endif
+}
+
+static void dvb_usbv2_media_device_unregister(struct dvb_usb_adapter *adap)
+{
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+
+       if (!adap->dvb_adap.mdev)
+               return;
+
+       media_device_unregister(adap->dvb_adap.mdev);
+       kfree(adap->dvb_adap.mdev);
+       adap->dvb_adap.mdev = NULL;
+
+#endif
+}
+
 static int dvb_usbv2_adapter_dvb_init(struct dvb_usb_adapter *adap)
 {
        int ret;
        struct dvb_usb_device *d = adap_to_d(adap);
+
        dev_dbg(&d->udev->dev, "%s: adap=%d\n", __func__, adap->id);
 
        ret = dvb_register_adapter(&adap->dvb_adap, d->name, d->props->owner,
@@ -416,6 +467,8 @@ static int dvb_usbv2_adapter_dvb_init(struct dvb_usb_adapter *adap)
 
        adap->dvb_adap.priv = adap;
 
+       dvb_usbv2_media_device_register(adap);
+
        if (d->props->read_mac_address) {
                ret = d->props->read_mac_address(adap,
                                adap->dvb_adap.proposed_mac);
@@ -464,6 +517,7 @@ err_dvb_net_init:
 err_dvb_dmxdev_init:
        dvb_dmx_release(&adap->demux);
 err_dvb_dmx_init:
+       dvb_usbv2_media_device_unregister(adap);
        dvb_unregister_adapter(&adap->dvb_adap);
 err_dvb_register_adapter:
        adap->dvb_adap.priv = NULL;
@@ -480,6 +534,7 @@ static int dvb_usbv2_adapter_dvb_exit(struct dvb_usb_adapter *adap)
                adap->demux.dmx.close(&adap->demux.dmx);
                dvb_dmxdev_release(&adap->dmxdev);
                dvb_dmx_release(&adap->demux);
+               dvb_usbv2_media_device_unregister(adap);
                dvb_unregister_adapter(&adap->dvb_adap);
        }
 
@@ -643,6 +698,8 @@ static int dvb_usbv2_adapter_frontend_init(struct dvb_usb_adapter *adap)
                }
        }
 
+       dvb_create_media_graph(&adap->dvb_adap);
+
        return 0;
 
 err_dvb_unregister_frontend:
@@ -955,6 +1012,7 @@ void dvb_usbv2_disconnect(struct usb_interface *intf)
        struct dvb_usb_device *d = usb_get_intfdata(intf);
        const char *name = d->name;
        struct device dev = d->udev->dev;
+
        dev_dbg(&d->udev->dev, "%s: bInterfaceNumber=%d\n", __func__,
                        intf->cur_altsetting->desc.bInterfaceNumber);
 
index 9b5add4499e36fab1143aa2cb79c0c46fa479a89..cdf59bcd760c4576bf5fe086aecf495e6694405f 100644 (file)
@@ -20,7 +20,7 @@
 
 #include "dvb_usb.h"
 #include "m88ds3103.h"
-#include "m88ts2022.h"
+#include "ts2020.h"
 #include "sp2.h"
 #include "si2168.h"
 #include "si2157.h"
@@ -315,9 +315,7 @@ static int dvbsky_s960_attach(struct dvb_usb_adapter *adap)
        struct i2c_adapter *i2c_adapter;
        struct i2c_client *client;
        struct i2c_board_info info;
-       struct m88ts2022_config m88ts2022_config = {
-                       .clock = 27000000,
-               };
+       struct ts2020_config ts2020_config = {};
        memset(&info, 0, sizeof(struct i2c_board_info));
 
        /* attach demod */
@@ -332,11 +330,11 @@ static int dvbsky_s960_attach(struct dvb_usb_adapter *adap)
        }
 
        /* attach tuner */
-       m88ts2022_config.fe = adap->fe[0];
-       strlcpy(info.type, "m88ts2022", I2C_NAME_SIZE);
+       ts2020_config.fe = adap->fe[0];
+       strlcpy(info.type, "ts2020", I2C_NAME_SIZE);
        info.addr = 0x60;
-       info.platform_data = &m88ts2022_config;
-       request_module("m88ts2022");
+       info.platform_data = &ts2020_config;
+       request_module("ts2020");
        client = i2c_new_device(i2c_adapter, &info);
        if (client == NULL || client->dev.driver == NULL) {
                dvb_frontend_detach(adap->fe[0]);
@@ -439,9 +437,7 @@ static int dvbsky_s960c_attach(struct dvb_usb_adapter *adap)
        struct i2c_client *client_tuner, *client_ci;
        struct i2c_board_info info;
        struct sp2_config sp2_config;
-       struct m88ts2022_config m88ts2022_config = {
-                       .clock = 27000000,
-               };
+       struct ts2020_config ts2020_config = {};
        memset(&info, 0, sizeof(struct i2c_board_info));
 
        /* attach demod */
@@ -456,11 +452,11 @@ static int dvbsky_s960c_attach(struct dvb_usb_adapter *adap)
        }
 
        /* attach tuner */
-       m88ts2022_config.fe = adap->fe[0];
-       strlcpy(info.type, "m88ts2022", I2C_NAME_SIZE);
+       ts2020_config.fe = adap->fe[0];
+       strlcpy(info.type, "ts2020", I2C_NAME_SIZE);
        info.addr = 0x60;
-       info.platform_data = &m88ts2022_config;
-       request_module("m88ts2022");
+       info.platform_data = &ts2020_config;
+       request_module("ts2020");
        client_tuner = i2c_new_device(i2c_adapter, &info);
        if (client_tuner == NULL || client_tuner->dev.driver == NULL) {
                ret = -ENODEV;
index 87fc0fe29ebd30e91ee58488cf6398df111ece63..895441fe90f7cbbb4e41e6971f785d124cf54845 100644 (file)
@@ -866,6 +866,8 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
                        mn88472_config.i2c_wr_max = 22,
                        strlcpy(info.type, "mn88472", I2C_NAME_SIZE);
                        mn88472_config.xtal = 20500000;
+                       mn88472_config.ts_mode = SERIAL_TS_MODE;
+                       mn88472_config.ts_clock = VARIABLE_TS_CLOCK;
                        info.addr = 0x18;
                        info.platform_data = &mn88472_config;
                        request_module(info.type);
@@ -1609,7 +1611,7 @@ static int rtl2832u_get_rc_config(struct dvb_usb_device *d,
        rc->allowed_protos = RC_BIT_ALL;
        rc->driver_type = RC_DRIVER_IR_RAW;
        rc->query = rtl2832u_rc_query;
-       rc->interval = 400;
+       rc->interval = 200;
 
        return 0;
 }
@@ -1724,6 +1726,8 @@ static const struct usb_device_id rtl28xxu_id_table[] = {
                &rtl28xxu_props, "DigitalNow Quad DVB-T Receiver", NULL) },
        { DVB_USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_MINID,
                &rtl28xxu_props, "Leadtek Winfast DTV Dongle Mini D", NULL) },
+       { DVB_USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV2000DS_PLUS,
+               &rtl28xxu_props, "Leadtek WinFast DTV2000DS Plus", RC_MAP_LEADTEK_Y04G0051) },
        { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00d3,
                &rtl28xxu_props, "TerraTec Cinergy T Stick RC (Rev. 3)", NULL) },
        { DVB_USB_DEVICE(USB_VID_DEXATEK, 0x1102,
@@ -1754,6 +1758,8 @@ static const struct usb_device_id rtl28xxu_id_table[] = {
                &rtl28xxu_props, "Sveon STV21", NULL) },
        { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV27,
                &rtl28xxu_props, "Sveon STV27", NULL) },
+       { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_TURBOX_DTT_2000,
+               &rtl28xxu_props, "TURBO-X Pure TV Tuner DTT-2000", NULL) },
 
        /* RTL2832P devices: */
        { DVB_USB_DEVICE(USB_VID_HANFTEK, 0x0131,
index 3364200db093e3b73622e272bb2176953f4b101f..128eee61570d1bb53a7ace0a33dbde45fb2ce2ed 100644 (file)
@@ -278,9 +278,10 @@ config DVB_USB_DW2102
        select DVB_STV6110 if MEDIA_SUBDRV_AUTOSELECT
        select DVB_STV0900 if MEDIA_SUBDRV_AUTOSELECT
        select DVB_M88RS2000 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_M88DS3103 if MEDIA_SUBDRV_AUTOSELECT
        help
-         Say Y here to support the DvbWorld, TeVii, Prof DVB-S/S2 USB2.0
-         receivers.
+         Say Y here to support the DvbWorld, TeVii, Prof, TechnoTrend
+         DVB-S/S2 USB2.0 receivers.
 
 config DVB_USB_CINERGY_T2
        tristate "Terratec CinergyT2/qanu USB 2.0 DVB-T receiver"
index f327c49d7e0936baf1e529746e82166129423916..ffc3704abdedce344d3cf0ccc9cff8a7df6762df 100644 (file)
@@ -1516,28 +1516,95 @@ static void cxusb_disconnect(struct usb_interface *intf)
        dvb_usb_device_exit(intf);
 }
 
-static struct usb_device_id cxusb_table [] = {
-       { USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) },
-       { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD) },
-       { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_WARM) },
-       { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_COLD) },
-       { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM) },
-       { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_COLD) },
-       { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_WARM) },
-       { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_COLD) },
-       { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_WARM) },
-       { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD) },
-       { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM) },
-       { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD) },
-       { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM) },
-       { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4) },
-       { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2) },
-       { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM) },
-       { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_A868R) },
-       { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2) },
-       { USB_DEVICE(USB_VID_CONEXANT, USB_PID_CONEXANT_D680_DMB) },
-       { USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_D689) },
-       { USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230) },
+enum cxusb_table_index {
+       MEDION_MD95700,
+       DVICO_BLUEBIRD_LG064F_COLD,
+       DVICO_BLUEBIRD_LG064F_WARM,
+       DVICO_BLUEBIRD_DUAL_1_COLD,
+       DVICO_BLUEBIRD_DUAL_1_WARM,
+       DVICO_BLUEBIRD_LGZ201_COLD,
+       DVICO_BLUEBIRD_LGZ201_WARM,
+       DVICO_BLUEBIRD_TH7579_COLD,
+       DVICO_BLUEBIRD_TH7579_WARM,
+       DIGITALNOW_BLUEBIRD_DUAL_1_COLD,
+       DIGITALNOW_BLUEBIRD_DUAL_1_WARM,
+       DVICO_BLUEBIRD_DUAL_2_COLD,
+       DVICO_BLUEBIRD_DUAL_2_WARM,
+       DVICO_BLUEBIRD_DUAL_4,
+       DVICO_BLUEBIRD_DVB_T_NANO_2,
+       DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM,
+       AVERMEDIA_VOLAR_A868R,
+       DVICO_BLUEBIRD_DUAL_4_REV_2,
+       CONEXANT_D680_DMB,
+       MYGICA_D689,
+       MYGICA_T230,
+       NR__cxusb_table_index
+};
+
+static struct usb_device_id cxusb_table[NR__cxusb_table_index + 1] = {
+       [MEDION_MD95700] = {
+               USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700)
+       },
+       [DVICO_BLUEBIRD_LG064F_COLD] = {
+               USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD)
+       },
+       [DVICO_BLUEBIRD_LG064F_WARM] = {
+               USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_WARM)
+       },
+       [DVICO_BLUEBIRD_DUAL_1_COLD] = {
+               USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_COLD)
+       },
+       [DVICO_BLUEBIRD_DUAL_1_WARM] = {
+               USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM)
+       },
+       [DVICO_BLUEBIRD_LGZ201_COLD] = {
+               USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_COLD)
+       },
+       [DVICO_BLUEBIRD_LGZ201_WARM] = {
+               USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_WARM)
+       },
+       [DVICO_BLUEBIRD_TH7579_COLD] = {
+               USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_COLD)
+       },
+       [DVICO_BLUEBIRD_TH7579_WARM] = {
+               USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_WARM)
+       },
+       [DIGITALNOW_BLUEBIRD_DUAL_1_COLD] = {
+               USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD)
+       },
+       [DIGITALNOW_BLUEBIRD_DUAL_1_WARM] = {
+               USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM)
+       },
+       [DVICO_BLUEBIRD_DUAL_2_COLD] = {
+               USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD)
+       },
+       [DVICO_BLUEBIRD_DUAL_2_WARM] = {
+               USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM)
+       },
+       [DVICO_BLUEBIRD_DUAL_4] = {
+               USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4)
+       },
+       [DVICO_BLUEBIRD_DVB_T_NANO_2] = {
+               USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2)
+       },
+       [DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM] = {
+               USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM)
+       },
+       [AVERMEDIA_VOLAR_A868R] = {
+               USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_A868R)
+       },
+       [DVICO_BLUEBIRD_DUAL_4_REV_2] = {
+               USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2)
+       },
+       [CONEXANT_D680_DMB] = {
+               USB_DEVICE(USB_VID_CONEXANT, USB_PID_CONEXANT_D680_DMB)
+       },
+       [MYGICA_D689] = {
+               USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_D689)
+       },
+       [MYGICA_T230] = {
+               USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230)
+       },
        {}              /* Terminating entry */
 };
 MODULE_DEVICE_TABLE (usb, cxusb_table);
@@ -1581,7 +1648,7 @@ static struct dvb_usb_device_properties cxusb_medion_properties = {
        .devices = {
                {   "Medion MD95700 (MDUSBTV-HYBRID)",
                        { NULL },
-                       { &cxusb_table[0], NULL },
+                       { &cxusb_table[MEDION_MD95700], NULL },
                },
        }
 };
@@ -1637,8 +1704,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties = {
        .num_device_descs = 1,
        .devices = {
                {   "DViCO FusionHDTV5 USB Gold",
-                       { &cxusb_table[1], NULL },
-                       { &cxusb_table[2], NULL },
+                       { &cxusb_table[DVICO_BLUEBIRD_LG064F_COLD], NULL },
+                       { &cxusb_table[DVICO_BLUEBIRD_LG064F_WARM], NULL },
                },
        }
 };
@@ -1693,16 +1760,16 @@ static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties = {
        .num_device_descs = 3,
        .devices = {
                {   "DViCO FusionHDTV DVB-T Dual USB",
-                       { &cxusb_table[3], NULL },
-                       { &cxusb_table[4], NULL },
+                       { &cxusb_table[DVICO_BLUEBIRD_DUAL_1_COLD], NULL },
+                       { &cxusb_table[DVICO_BLUEBIRD_DUAL_1_WARM], NULL },
                },
                {   "DigitalNow DVB-T Dual USB",
-                       { &cxusb_table[9],  NULL },
-                       { &cxusb_table[10], NULL },
+                       { &cxusb_table[DIGITALNOW_BLUEBIRD_DUAL_1_COLD],  NULL },
+                       { &cxusb_table[DIGITALNOW_BLUEBIRD_DUAL_1_WARM], NULL },
                },
                {   "DViCO FusionHDTV DVB-T Dual Digital 2",
-                       { &cxusb_table[11], NULL },
-                       { &cxusb_table[12], NULL },
+                       { &cxusb_table[DVICO_BLUEBIRD_DUAL_2_COLD], NULL },
+                       { &cxusb_table[DVICO_BLUEBIRD_DUAL_2_WARM], NULL },
                },
        }
 };
@@ -1756,8 +1823,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties = {
        .num_device_descs = 1,
        .devices = {
                {   "DViCO FusionHDTV DVB-T USB (LGZ201)",
-                       { &cxusb_table[5], NULL },
-                       { &cxusb_table[6], NULL },
+                       { &cxusb_table[DVICO_BLUEBIRD_LGZ201_COLD], NULL },
+                       { &cxusb_table[DVICO_BLUEBIRD_LGZ201_WARM], NULL },
                },
        }
 };
@@ -1812,8 +1879,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = {
        .num_device_descs = 1,
        .devices = {
                {   "DViCO FusionHDTV DVB-T USB (TH7579)",
-                       { &cxusb_table[7], NULL },
-                       { &cxusb_table[8], NULL },
+                       { &cxusb_table[DVICO_BLUEBIRD_TH7579_COLD], NULL },
+                       { &cxusb_table[DVICO_BLUEBIRD_TH7579_WARM], NULL },
                },
        }
 };
@@ -1865,7 +1932,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties = {
        .devices = {
                {   "DViCO FusionHDTV DVB-T Dual Digital 4",
                        { NULL },
-                       { &cxusb_table[13], NULL },
+                       { &cxusb_table[DVICO_BLUEBIRD_DUAL_4], NULL },
                },
        }
 };
@@ -1918,7 +1985,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties = {
        .devices = {
                {   "DViCO FusionHDTV DVB-T NANO2",
                        { NULL },
-                       { &cxusb_table[14], NULL },
+                       { &cxusb_table[DVICO_BLUEBIRD_DVB_T_NANO_2], NULL },
                },
        }
 };
@@ -1972,8 +2039,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope
        .num_device_descs = 1,
        .devices = {
                {   "DViCO FusionHDTV DVB-T NANO2 w/o firmware",
-                       { &cxusb_table[14], NULL },
-                       { &cxusb_table[15], NULL },
+                       { &cxusb_table[DVICO_BLUEBIRD_DVB_T_NANO_2], NULL },
+                       { &cxusb_table[DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM], NULL },
                },
        }
 };
@@ -2017,7 +2084,7 @@ static struct dvb_usb_device_properties cxusb_aver_a868r_properties = {
        .devices = {
                {   "AVerMedia AVerTVHD Volar (A868R)",
                        { NULL },
-                       { &cxusb_table[16], NULL },
+                       { &cxusb_table[AVERMEDIA_VOLAR_A868R], NULL },
                },
        }
 };
@@ -2071,7 +2138,7 @@ struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties = {
        .devices = {
                {   "DViCO FusionHDTV DVB-T Dual Digital 4 (rev 2)",
                        { NULL },
-                       { &cxusb_table[17], NULL },
+                       { &cxusb_table[DVICO_BLUEBIRD_DUAL_4_REV_2], NULL },
                },
        }
 };
@@ -2125,7 +2192,7 @@ static struct dvb_usb_device_properties cxusb_d680_dmb_properties = {
                {
                        "Conexant DMB-TH Stick",
                        { NULL },
-                       { &cxusb_table[18], NULL },
+                       { &cxusb_table[CONEXANT_D680_DMB], NULL },
                },
        }
 };
@@ -2179,7 +2246,7 @@ static struct dvb_usb_device_properties cxusb_mygica_d689_properties = {
                {
                        "Mygica D689 DMB-TH",
                        { NULL },
-                       { &cxusb_table[19], NULL },
+                       { &cxusb_table[MYGICA_D689], NULL },
                },
        }
 };
@@ -2232,7 +2299,7 @@ static struct dvb_usb_device_properties cxusb_mygica_t230_properties = {
                {
                        "Mygica T230 DVB-T/T2/C",
                        { NULL },
-                       { &cxusb_table[20], NULL },
+                       { &cxusb_table[MYGICA_T230], NULL },
                },
        }
 };
index 50856dbf5496d5c76f56e8677ef5d8dff91a149b..2b40393836ffafa14c63c2a700bdd8072d8e0ed7 100644 (file)
@@ -651,9 +651,6 @@ out:
        return ret;
 }
 
-/* Number of keypresses to ignore before start repeating */
-#define RC_REPEAT_DELAY_V1_20 10
-
 /* This is the structure of the RC response packet starting in firmware 1.20 */
 struct dib0700_rc_response {
        u8 report_id;
index e1757b8f5f5d0e7775abbc91c40bba817fec9d3d..d7d55a20e959073f4519172c8948e5e416268f62 100644 (file)
@@ -510,9 +510,6 @@ static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap)
 
 static u8 rc_request[] = { REQUEST_POLL_RC, 0 };
 
-/* Number of keypresses to ignore before start repeating */
-#define RC_REPEAT_DELAY 6
-
 /*
  * This function is used only when firmware is < 1.20 version. Newer
  * firmwares use bulk mode, with functions implemented at dib0700_core,
index 719413b15f208b7ceb165422ff4d1111dfcfd6e1..8a260c854653d50d95a9529af459a21c9f0767bc 100644 (file)
@@ -84,14 +84,61 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
 
 static int dvb_usb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
 {
-       deb_ts("start pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid,dvbdmxfeed->type);
-       return dvb_usb_ctrl_feed(dvbdmxfeed,1);
+       deb_ts("start pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid,
+              dvbdmxfeed->type);
+       return dvb_usb_ctrl_feed(dvbdmxfeed, 1);
 }
 
 static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
 {
        deb_ts("stop pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid, dvbdmxfeed->type);
-       return dvb_usb_ctrl_feed(dvbdmxfeed,0);
+       return dvb_usb_ctrl_feed(dvbdmxfeed, 0);
+}
+
+static void dvb_usb_media_device_register(struct dvb_usb_adapter *adap)
+{
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+       struct media_device *mdev;
+       struct dvb_usb_device *d = adap->dev;
+       struct usb_device *udev = d->udev;
+       int ret;
+
+       mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
+       if (!mdev)
+               return;
+
+       mdev->dev = &udev->dev;
+       strlcpy(mdev->model, d->desc->name, sizeof(mdev->model));
+       if (udev->serial)
+               strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial));
+       strcpy(mdev->bus_info, udev->devpath);
+       mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
+       mdev->driver_version = LINUX_VERSION_CODE;
+
+       ret = media_device_register(mdev);
+       if (ret) {
+               dev_err(&d->udev->dev,
+                       "Couldn't create a media device. Error: %d\n",
+                       ret);
+               kfree(mdev);
+               return;
+       }
+       dvb_register_media_controller(&adap->dvb_adap, mdev);
+
+       dev_info(&d->udev->dev, "media controller created\n");
+#endif
+}
+
+static void dvb_usb_media_device_unregister(struct dvb_usb_adapter *adap)
+{
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+       if (!adap->dvb_adap.mdev)
+               return;
+
+       media_device_unregister(adap->dvb_adap.mdev);
+       kfree(adap->dvb_adap.mdev);
+       adap->dvb_adap.mdev = NULL;
+#endif
 }
 
 int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, short *adapter_nums)
@@ -107,9 +154,11 @@ int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, short *adapter_nums)
        }
        adap->dvb_adap.priv = adap;
 
+       dvb_usb_media_device_register(adap);
+
        if (adap->dev->props.read_mac_address) {
-               if (adap->dev->props.read_mac_address(adap->dev,adap->dvb_adap.proposed_mac) == 0)
-                       info("MAC address: %pM",adap->dvb_adap.proposed_mac);
+               if (adap->dev->props.read_mac_address(adap->dev, adap->dvb_adap.proposed_mac) == 0)
+                       info("MAC address: %pM", adap->dvb_adap.proposed_mac);
                else
                        err("MAC address reading failed.");
        }
@@ -128,7 +177,7 @@ int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, short *adapter_nums)
        adap->demux.stop_feed        = dvb_usb_stop_feed;
        adap->demux.write_to_decoder = NULL;
        if ((ret = dvb_dmx_init(&adap->demux)) < 0) {
-               err("dvb_dmx_init failed: error %d",ret);
+               err("dvb_dmx_init failed: error %d", ret);
                goto err_dmx;
        }
 
@@ -136,13 +185,13 @@ int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, short *adapter_nums)
        adap->dmxdev.demux           = &adap->demux.dmx;
        adap->dmxdev.capabilities    = 0;
        if ((ret = dvb_dmxdev_init(&adap->dmxdev, &adap->dvb_adap)) < 0) {
-               err("dvb_dmxdev_init failed: error %d",ret);
+               err("dvb_dmxdev_init failed: error %d", ret);
                goto err_dmx_dev;
        }
 
        if ((ret = dvb_net_init(&adap->dvb_adap, &adap->dvb_net,
                                                &adap->demux.dmx)) < 0) {
-               err("dvb_net_init failed: error %d",ret);
+               err("dvb_net_init failed: error %d", ret);
                goto err_net_init;
        }
 
@@ -154,6 +203,7 @@ err_net_init:
 err_dmx_dev:
        dvb_dmx_release(&adap->demux);
 err_dmx:
+       dvb_usb_media_device_unregister(adap);
        dvb_unregister_adapter(&adap->dvb_adap);
 err:
        return ret;
@@ -167,6 +217,7 @@ int dvb_usb_adapter_dvb_exit(struct dvb_usb_adapter *adap)
                adap->demux.dmx.close(&adap->demux.dmx);
                dvb_dmxdev_release(&adap->dmxdev);
                dvb_dmx_release(&adap->demux);
+               dvb_usb_media_device_unregister(adap);
                dvb_unregister_adapter(&adap->dvb_adap);
                adap->state &= ~DVB_USB_ADAP_STATE_DVB;
        }
@@ -268,6 +319,8 @@ int dvb_usb_adapter_frontend_init(struct dvb_usb_adapter *adap)
                adap->num_frontends_initialized++;
        }
 
+       dvb_create_media_graph(&adap->dvb_adap);
+
        return 0;
 }
 
index 1a3df10d6bad5e1c1354874c8d715a7f6e5629c0..f1f357f43ff03663b1d606502dbcd3c250bcd16b 100644 (file)
@@ -2,7 +2,8 @@
  *     DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101,
  *     TeVii S600, S630, S650, S660, S480, S421, S632
  *     Prof 1100, 7500,
- *     Geniatech SU3000, T220 Cards
+ *     Geniatech SU3000, T220,
+ *     TechnoTrend S2-4600 Cards
  * Copyright (C) 2008-2012 Igor M. Liplianin (liplianin@me.by)
  *
  *     This program is free software; you can redistribute it and/or modify it
@@ -31,6 +32,8 @@
 #include "m88rs2000.h"
 #include "tda18271.h"
 #include "cxd2820r.h"
+#include "m88ds3103.h"
+#include "ts2020.h"
 
 /* Max transfer size done by I2C transfer functions */
 #define MAX_XFER_SIZE  64
                "Please see linux/Documentation/dvb/ for more details " \
                "on firmware-problems."
 
-struct su3000_state {
+struct dw2102_state {
        u8 initialized;
-};
-
-struct s6x0_state {
+       struct i2c_client *i2c_client_tuner;
        int (*old_set_voltage)(struct dvb_frontend *f, fe_sec_voltage_t v);
 };
 
@@ -887,7 +888,7 @@ static int su3000_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
 
 static int su3000_power_ctrl(struct dvb_usb_device *d, int i)
 {
-       struct su3000_state *state = (struct su3000_state *)d->priv;
+       struct dw2102_state *state = (struct dw2102_state *)d->priv;
        u8 obuf[] = {0xde, 0};
 
        info("%s: %d, initialized %d\n", __func__, i, state->initialized);
@@ -973,7 +974,7 @@ static int s660_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
 {
        struct dvb_usb_adapter *d =
                (struct dvb_usb_adapter *)(fe->dvb->priv);
-       struct s6x0_state *st = (struct s6x0_state *)d->dev->priv;
+       struct dw2102_state *st = (struct dw2102_state *)d->dev->priv;
 
        dw210x_set_voltage(fe, voltage);
        if (st->old_set_voltage)
@@ -1117,6 +1118,22 @@ static struct tda18271_config tda18271_config = {
        .gate = TDA18271_GATE_DIGITAL,
 };
 
+static const struct m88ds3103_config tt_s2_4600_m88ds3103_config = {
+       .i2c_addr = 0x68,
+       .clock = 27000000,
+       .i2c_wr_max = 33,
+       .ts_mode = M88DS3103_TS_CI,
+       .ts_clk = 16000,
+       .ts_clk_pol = 0,
+       .spec_inv = 0,
+       .agc_inv = 0,
+       .clock_out = M88DS3103_CLOCK_OUT_ENABLED,
+       .envelope_mode = 0,
+       .agc = 0x99,
+       .lnb_hv_pol = 1,
+       .lnb_en_pol = 0,
+};
+
 static u8 m88rs2000_inittab[] = {
        DEMOD_WRITE, 0x9a, 0x30,
        DEMOD_WRITE, 0x00, 0x01,
@@ -1295,7 +1312,7 @@ static int stv0288_frontend_attach(struct dvb_usb_adapter *d)
 
 static int ds3000_frontend_attach(struct dvb_usb_adapter *d)
 {
-       struct s6x0_state *st = (struct s6x0_state *)d->dev->priv;
+       struct dw2102_state *st = d->dev->priv;
        u8 obuf[] = {7, 1};
 
        d->fe_adap[0].fe = dvb_attach(ds3000_attach, &s660_ds3000_config,
@@ -1461,6 +1478,84 @@ static int m88rs2000_frontend_attach(struct dvb_usb_adapter *d)
        return -EIO;
 }
 
+static int tt_s2_4600_frontend_attach(struct dvb_usb_adapter *adap)
+{
+       struct dvb_usb_device *d = adap->dev;
+       struct dw2102_state *state = d->priv;
+       u8 obuf[3] = { 0xe, 0x80, 0 };
+       u8 ibuf[] = { 0 };
+       struct i2c_adapter *i2c_adapter;
+       struct i2c_client *client;
+       struct i2c_board_info info;
+       struct ts2020_config ts2020_config = {};
+
+       if (dvb_usb_generic_rw(d, obuf, 3, ibuf, 1, 0) < 0)
+               err("command 0x0e transfer failed.");
+
+       obuf[0] = 0xe;
+       obuf[1] = 0x02;
+       obuf[2] = 1;
+
+       if (dvb_usb_generic_rw(d, obuf, 3, ibuf, 1, 0) < 0)
+               err("command 0x0e transfer failed.");
+       msleep(300);
+
+       obuf[0] = 0xe;
+       obuf[1] = 0x83;
+       obuf[2] = 0;
+
+       if (dvb_usb_generic_rw(d, obuf, 3, ibuf, 1, 0) < 0)
+               err("command 0x0e transfer failed.");
+
+       obuf[0] = 0xe;
+       obuf[1] = 0x83;
+       obuf[2] = 1;
+
+       if (dvb_usb_generic_rw(d, obuf, 3, ibuf, 1, 0) < 0)
+               err("command 0x0e transfer failed.");
+
+       obuf[0] = 0x51;
+
+       if (dvb_usb_generic_rw(d, obuf, 1, ibuf, 1, 0) < 0)
+               err("command 0x51 transfer failed.");
+
+       memset(&info, 0, sizeof(struct i2c_board_info));
+
+       adap->fe_adap[0].fe = dvb_attach(m88ds3103_attach,
+                                       &tt_s2_4600_m88ds3103_config,
+                                       &d->i2c_adap,
+                                       &i2c_adapter);
+       if (adap->fe_adap[0].fe == NULL)
+               return -ENODEV;
+
+       /* attach tuner */
+       ts2020_config.fe = adap->fe_adap[0].fe;
+       strlcpy(info.type, "ts2022", I2C_NAME_SIZE);
+       info.addr = 0x60;
+       info.platform_data = &ts2020_config;
+       request_module("ts2020");
+       client = i2c_new_device(i2c_adapter, &info);
+
+       if (client == NULL || client->dev.driver == NULL) {
+               dvb_frontend_detach(adap->fe_adap[0].fe);
+               return -ENODEV;
+       }
+
+       if (!try_module_get(client->dev.driver->owner)) {
+               i2c_unregister_device(client);
+               dvb_frontend_detach(adap->fe_adap[0].fe);
+               return -ENODEV;
+       }
+
+       /* delegate signal strength measurement to tuner */
+       adap->fe_adap[0].fe->ops.read_signal_strength =
+                       adap->fe_adap[0].fe->ops.tuner_ops.get_rf_strength;
+
+       state->i2c_client_tuner = client;
+
+       return 0;
+}
+
 static int dw2102_tuner_attach(struct dvb_usb_adapter *adap)
 {
        dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60,
@@ -1561,6 +1656,7 @@ enum dw2102_table_entry {
        TERRATEC_CINERGY_S2_R2,
        GOTVIEW_SAT_HD,
        GENIATECH_T220,
+       TECHNOTREND_S2_4600,
 };
 
 static struct usb_device_id dw2102_table[] = {
@@ -1584,6 +1680,8 @@ static struct usb_device_id dw2102_table[] = {
        [TERRATEC_CINERGY_S2_R2] = {USB_DEVICE(USB_VID_TERRATEC, 0x00b0)},
        [GOTVIEW_SAT_HD] = {USB_DEVICE(0x1FE1, USB_PID_GOTVIEW_SAT_HD)},
        [GENIATECH_T220] = {USB_DEVICE(0x1f4d, 0xD220)},
+       [TECHNOTREND_S2_4600] = {USB_DEVICE(USB_VID_TECHNOTREND,
+               USB_PID_TECHNOTREND_CONNECT_S2_4600)},
        { }
 };
 
@@ -1857,7 +1955,7 @@ static struct dvb_usb_device_properties dw3101_properties = {
 static struct dvb_usb_device_properties s6x0_properties = {
        .caps = DVB_USB_IS_AN_I2C_ADAPTER,
        .usb_ctrl = DEVICE_SPECIFIC,
-       .size_of_priv = sizeof(struct s6x0_state),
+       .size_of_priv = sizeof(struct dw2102_state),
        .firmware = S630_FIRMWARE,
        .no_reconnect = 1,
 
@@ -1950,7 +2048,7 @@ static struct dvb_usb_device_description d632 = {
 static struct dvb_usb_device_properties su3000_properties = {
        .caps = DVB_USB_IS_AN_I2C_ADAPTER,
        .usb_ctrl = DEVICE_SPECIFIC,
-       .size_of_priv = sizeof(struct su3000_state),
+       .size_of_priv = sizeof(struct dw2102_state),
        .power_ctrl = su3000_power_ctrl,
        .num_adapters = 1,
        .identify_state = su3000_identify_state,
@@ -2015,7 +2113,7 @@ static struct dvb_usb_device_properties su3000_properties = {
 static struct dvb_usb_device_properties t220_properties = {
        .caps = DVB_USB_IS_AN_I2C_ADAPTER,
        .usb_ctrl = DEVICE_SPECIFIC,
-       .size_of_priv = sizeof(struct su3000_state),
+       .size_of_priv = sizeof(struct dw2102_state),
        .power_ctrl = su3000_power_ctrl,
        .num_adapters = 1,
        .identify_state = su3000_identify_state,
@@ -2061,6 +2159,55 @@ static struct dvb_usb_device_properties t220_properties = {
        }
 };
 
+static struct dvb_usb_device_properties tt_s2_4600_properties = {
+       .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+       .usb_ctrl = DEVICE_SPECIFIC,
+       .size_of_priv = sizeof(struct dw2102_state),
+       .power_ctrl = su3000_power_ctrl,
+       .num_adapters = 1,
+       .identify_state = su3000_identify_state,
+       .i2c_algo = &su3000_i2c_algo,
+
+       .rc.core = {
+               .rc_interval = 250,
+               .rc_codes = RC_MAP_TT_1500,
+               .module_name = "dw2102",
+               .allowed_protos   = RC_BIT_RC5,
+               .rc_query = su3000_rc_query,
+       },
+
+       .read_mac_address = su3000_read_mac_address,
+
+       .generic_bulk_ctrl_endpoint = 0x01,
+
+       .adapter = {
+               {
+               .num_frontends = 1,
+               .fe = {{
+                       .streaming_ctrl   = su3000_streaming_ctrl,
+                       .frontend_attach  = tt_s2_4600_frontend_attach,
+                       .stream = {
+                               .type = USB_BULK,
+                               .count = 8,
+                               .endpoint = 0x82,
+                               .u = {
+                                       .bulk = {
+                                               .buffersize = 4096,
+                                       }
+                               }
+                       }
+               } },
+               }
+       },
+       .num_device_descs = 1,
+       .devices = {
+               { "TechnoTrend TT-connect S2-4600",
+                       { &dw2102_table[TECHNOTREND_S2_4600], NULL },
+                       { NULL },
+               },
+       }
+};
+
 static int dw2102_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
@@ -2135,16 +2282,34 @@ static int dw2102_probe(struct usb_interface *intf,
            0 == dvb_usb_device_init(intf, &su3000_properties,
                         THIS_MODULE, NULL, adapter_nr) ||
            0 == dvb_usb_device_init(intf, &t220_properties,
+                        THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &tt_s2_4600_properties,
                         THIS_MODULE, NULL, adapter_nr))
                return 0;
 
        return -ENODEV;
 }
 
+static void dw2102_disconnect(struct usb_interface *intf)
+{
+       struct dvb_usb_device *d = usb_get_intfdata(intf);
+       struct dw2102_state *st = (struct dw2102_state *)d->priv;
+       struct i2c_client *client;
+
+       /* remove I2C client for tuner */
+       client = st->i2c_client_tuner;
+       if (client) {
+               module_put(client->dev.driver->owner);
+               i2c_unregister_device(client);
+       }
+
+       dvb_usb_device_exit(intf);
+}
+
 static struct usb_driver dw2102_driver = {
        .name = "dw2102",
        .probe = dw2102_probe,
-       .disconnect = dvb_usb_device_exit,
+       .disconnect = dw2102_disconnect,
        .id_table = dw2102_table,
 };
 
@@ -2155,7 +2320,8 @@ MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104,"
                        " DVB-C 3101 USB2.0,"
                        " TeVii S600, S630, S650, S660, S480, S421, S632"
                        " Prof 1100, 7500 USB2.0,"
-                       " Geniatech SU3000, T220 devices");
+                       " Geniatech SU3000, T220,"
+                       " TechnoTrend S2-4600 devices");
 MODULE_VERSION("0.1");
 MODULE_LICENSE("GPL");
 MODULE_FIRMWARE(DW2101_FIRMWARE);
index f5d7198753c76883b644da2d4b543b959b0991b1..e382210c4adaba001a8e939cb737a8c3aaa057a2 100644 (file)
@@ -55,7 +55,7 @@ config VIDEO_EM28XX_DVB
        select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT
        select MEDIA_TUNER_TDA18212 if MEDIA_SUBDRV_AUTOSELECT
        select DVB_M88DS3103 if MEDIA_SUBDRV_AUTOSELECT
-       select MEDIA_TUNER_M88TS2022 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TS2020 if MEDIA_SUBDRV_AUTOSELECT
        select DVB_DRX39XYJ if MEDIA_SUBDRV_AUTOSELECT
        select DVB_SI2168 if MEDIA_SUBDRV_AUTOSELECT
        select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT
index 7be661f739302b2a2648449ab235aa7eedb7e1ef..a4b22c2c3ba7f9afa520719bdee8b8c2a613c74c 100644 (file)
@@ -330,7 +330,7 @@ int em28xx_init_camera(struct em28xx *dev)
 
        v4l2_clk_name_i2c(clk_name, sizeof(clk_name),
                          i2c_adapter_id(adap), client->addr);
-       v4l2->clk = v4l2_clk_register_fixed(clk_name, "mclk", -EINVAL);
+       v4l2->clk = v4l2_clk_register_fixed(clk_name, -EINVAL);
        if (IS_ERR(v4l2->clk))
                return PTR_ERR(v4l2->clk);
 
index d9704e66b8c911f00911c3c605c53af3bac3ed06..394004607059bffaa28c62dbd84a5cc1e649b26b 100644 (file)
@@ -1157,6 +1157,15 @@ struct em28xx_board em28xx_boards[] = {
                .i2c_speed    = EM28XX_I2C_CLK_WAIT_ENABLE |
                                EM28XX_I2C_FREQ_400_KHZ,
        },
+       [EM2884_BOARD_ELGATO_EYETV_HYBRID_2008] = {
+               .name         = "Elgato EyeTV Hybrid 2008 INT",
+               .has_dvb      = 1,
+               .ir_codes     = RC_MAP_NEC_TERRATEC_CINERGY_XS,
+               .tuner_type   = TUNER_ABSENT,
+               .def_i2c_bus  = 1,
+               .i2c_speed    = EM28XX_I2C_CLK_WAIT_ENABLE |
+                               EM28XX_I2C_FREQ_400_KHZ,
+       },
        [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900] = {
                .name         = "Hauppauge WinTV HVR 900",
                .tda9887_conf = TDA9887_PRESENT,
@@ -2378,8 +2387,10 @@ struct usb_device_id em28xx_id_table[] = {
                        .driver_info = EM2860_BOARD_TERRATEC_GRABBY },
        { USB_DEVICE(0x0ccd, 0x00b2),
                        .driver_info = EM2884_BOARD_CINERGY_HTC_STICK },
+       { USB_DEVICE(0x0fd9, 0x0018),
+                       .driver_info = EM2884_BOARD_ELGATO_EYETV_HYBRID_2008 },
        { USB_DEVICE(0x0fd9, 0x0033),
-                       .driver_info = EM2860_BOARD_ELGATO_VIDEO_CAPTURE},
+                       .driver_info = EM2860_BOARD_ELGATO_VIDEO_CAPTURE },
        { USB_DEVICE(0x185b, 0x2870),
                        .driver_info = EM2870_BOARD_COMPRO_VIDEOMATE },
        { USB_DEVICE(0x185b, 0x2041),
index aee70d4832649e6231c6496b9a867afb2354c25f..a5b22c5a240ced569dd83128b6d237838af0b2ef 100644 (file)
@@ -54,7 +54,7 @@
 #include "qt1010.h"
 #include "mb86a20s.h"
 #include "m88ds3103.h"
-#include "m88ts2022.h"
+#include "ts2020.h"
 #include "si2168.h"
 #include "si2157.h"
 
@@ -1380,6 +1380,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
                        }
                }
                break;
+       case EM2884_BOARD_ELGATO_EYETV_HYBRID_2008:
        case EM2884_BOARD_CINERGY_HTC_STICK:
                terratec_htc_stick_init(dev);
 
@@ -1491,8 +1492,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
                        struct i2c_adapter *i2c_adapter;
                        struct i2c_client *client;
                        struct i2c_board_info info;
-                       struct m88ts2022_config m88ts2022_config = {
-                               .clock = 27000000,
+                       struct ts2020_config ts2020_config = {
                        };
                        memset(&info, 0, sizeof(struct i2c_board_info));
 
@@ -1507,11 +1507,11 @@ static int em28xx_dvb_init(struct em28xx *dev)
                        }
 
                        /* attach tuner */
-                       m88ts2022_config.fe = dvb->fe[0];
-                       strlcpy(info.type, "m88ts2022", I2C_NAME_SIZE);
+                       ts2020_config.fe = dvb->fe[0];
+                       strlcpy(info.type, "ts2022", I2C_NAME_SIZE);
                        info.addr = 0x60;
-                       info.platform_data = &m88ts2022_config;
-                       request_module("m88ts2022");
+                       info.platform_data = &ts2020_config;
+                       request_module("ts2020");
                        client = i2c_new_device(i2c_adapter, &info);
                        if (client == NULL || client->dev.driver == NULL) {
                                dvb_frontend_detach(dvb->fe[0]);
index 9ecf65629b3d219cb6b1a33d5380c24f69cf0c9a..14eba9c65de39687941a23c99b33c3c8ad336c76 100644 (file)
@@ -1472,7 +1472,7 @@ static int vidioc_enum_input(struct file *file, void *priv,
            (EM28XX_VMUX_CABLE == INPUT(n)->type))
                i->type = V4L2_INPUT_TYPE_TUNER;
 
-       i->std = dev->v4l2->vdev->tvnorms;
+       i->std = dev->v4l2->vdev.tvnorms;
        /* webcams do not have the STD API */
        if (dev->board.is_webcam)
                i->capabilities = 0;
@@ -1730,9 +1730,9 @@ static int vidioc_querycap(struct file *file, void  *priv,
 
        cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS |
                V4L2_CAP_READWRITE | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
-       if (v4l2->vbi_dev)
+       if (video_is_registered(&v4l2->vbi_dev))
                cap->capabilities |= V4L2_CAP_VBI_CAPTURE;
-       if (v4l2->radio_dev)
+       if (video_is_registered(&v4l2->radio_dev))
                cap->capabilities |= V4L2_CAP_RADIO;
        return 0;
 }
@@ -1966,20 +1966,20 @@ static int em28xx_v4l2_fini(struct em28xx *dev)
 
        em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
 
-       if (v4l2->radio_dev) {
+       if (video_is_registered(&v4l2->radio_dev)) {
                em28xx_info("V4L2 device %s deregistered\n",
-                           video_device_node_name(v4l2->radio_dev));
-               video_unregister_device(v4l2->radio_dev);
+                           video_device_node_name(&v4l2->radio_dev));
+               video_unregister_device(&v4l2->radio_dev);
        }
-       if (v4l2->vbi_dev) {
+       if (video_is_registered(&v4l2->vbi_dev)) {
                em28xx_info("V4L2 device %s deregistered\n",
-                           video_device_node_name(v4l2->vbi_dev));
-               video_unregister_device(v4l2->vbi_dev);
+                           video_device_node_name(&v4l2->vbi_dev));
+               video_unregister_device(&v4l2->vbi_dev);
        }
-       if (v4l2->vdev) {
+       if (video_is_registered(&v4l2->vdev)) {
                em28xx_info("V4L2 device %s deregistered\n",
-                           video_device_node_name(v4l2->vdev));
-               video_unregister_device(v4l2->vdev);
+                           video_device_node_name(&v4l2->vdev));
+               video_unregister_device(&v4l2->vdev);
        }
 
        v4l2_ctrl_handler_free(&v4l2->ctrl_handler);
@@ -2127,7 +2127,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
 static const struct video_device em28xx_video_template = {
        .fops           = &em28xx_v4l_fops,
        .ioctl_ops      = &video_ioctl_ops,
-       .release        = video_device_release,
+       .release        = video_device_release_empty,
        .tvnorms        = V4L2_STD_ALL,
 };
 
@@ -2156,7 +2156,7 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = {
 static struct video_device em28xx_radio_template = {
        .fops           = &radio_fops,
        .ioctl_ops      = &radio_ioctl_ops,
-       .release        = video_device_release,
+       .release        = video_device_release_empty,
 };
 
 /* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */
@@ -2179,17 +2179,11 @@ static unsigned short msp3400_addrs[] = {
 
 /******************************** usb interface ******************************/
 
-static struct video_device
-*em28xx_vdev_init(struct em28xx *dev,
-                 const struct video_device *template,
-                 const char *type_name)
+static void em28xx_vdev_init(struct em28xx *dev,
+                            struct video_device *vfd,
+                            const struct video_device *template,
+                            const char *type_name)
 {
-       struct video_device *vfd;
-
-       vfd = video_device_alloc();
-       if (NULL == vfd)
-               return NULL;
-
        *vfd            = *template;
        vfd->v4l2_dev   = &dev->v4l2->v4l2_dev;
        vfd->lock       = &dev->lock;
@@ -2200,7 +2194,6 @@ static struct video_device
                 dev->name, type_name);
 
        video_set_drvdata(vfd, dev);
-       return vfd;
 }
 
 static void em28xx_tuner_setup(struct em28xx *dev, unsigned short tuner_addr)
@@ -2491,38 +2484,33 @@ static int em28xx_v4l2_init(struct em28xx *dev)
                goto unregister_dev;
 
        /* allocate and fill video video_device struct */
-       v4l2->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video");
-       if (!v4l2->vdev) {
-               em28xx_errdev("cannot allocate video_device.\n");
-               ret = -ENODEV;
-               goto unregister_dev;
-       }
+       em28xx_vdev_init(dev, &v4l2->vdev, &em28xx_video_template, "video");
        mutex_init(&v4l2->vb_queue_lock);
        mutex_init(&v4l2->vb_vbi_queue_lock);
-       v4l2->vdev->queue = &v4l2->vb_vidq;
-       v4l2->vdev->queue->lock = &v4l2->vb_queue_lock;
+       v4l2->vdev.queue = &v4l2->vb_vidq;
+       v4l2->vdev.queue->lock = &v4l2->vb_queue_lock;
 
        /* disable inapplicable ioctls */
        if (dev->board.is_webcam) {
-               v4l2_disable_ioctl(v4l2->vdev, VIDIOC_QUERYSTD);
-               v4l2_disable_ioctl(v4l2->vdev, VIDIOC_G_STD);
-               v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_STD);
+               v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_QUERYSTD);
+               v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_G_STD);
+               v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_S_STD);
        } else {
-               v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_PARM);
+               v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_S_PARM);
        }
        if (dev->tuner_type == TUNER_ABSENT) {
-               v4l2_disable_ioctl(v4l2->vdev, VIDIOC_G_TUNER);
-               v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_TUNER);
-               v4l2_disable_ioctl(v4l2->vdev, VIDIOC_G_FREQUENCY);
-               v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_FREQUENCY);
+               v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_G_TUNER);
+               v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_S_TUNER);
+               v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_G_FREQUENCY);
+               v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_S_FREQUENCY);
        }
        if (dev->int_audio_type == EM28XX_INT_AUDIO_NONE) {
-               v4l2_disable_ioctl(v4l2->vdev, VIDIOC_G_AUDIO);
-               v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_AUDIO);
+               v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_G_AUDIO);
+               v4l2_disable_ioctl(&v4l2->vdev, VIDIOC_S_AUDIO);
        }
 
        /* register v4l2 video video_device */
-       ret = video_register_device(v4l2->vdev, VFL_TYPE_GRABBER,
+       ret = video_register_device(&v4l2->vdev, VFL_TYPE_GRABBER,
                                    video_nr[dev->devno]);
        if (ret) {
                em28xx_errdev("unable to register video device (error=%i).\n",
@@ -2532,27 +2520,27 @@ static int em28xx_v4l2_init(struct em28xx *dev)
 
        /* Allocate and fill vbi video_device struct */
        if (em28xx_vbi_supported(dev) == 1) {
-               v4l2->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template,
-                                               "vbi");
+               em28xx_vdev_init(dev, &v4l2->vbi_dev, &em28xx_video_template,
+                               "vbi");
 
-               v4l2->vbi_dev->queue = &v4l2->vb_vbiq;
-               v4l2->vbi_dev->queue->lock = &v4l2->vb_vbi_queue_lock;
+               v4l2->vbi_dev.queue = &v4l2->vb_vbiq;
+               v4l2->vbi_dev.queue->lock = &v4l2->vb_vbi_queue_lock;
 
                /* disable inapplicable ioctls */
-               v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_PARM);
+               v4l2_disable_ioctl(&v4l2->vbi_dev, VIDIOC_S_PARM);
                if (dev->tuner_type == TUNER_ABSENT) {
-                       v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_G_TUNER);
-                       v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_TUNER);
-                       v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_G_FREQUENCY);
-                       v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_FREQUENCY);
+                       v4l2_disable_ioctl(&v4l2->vbi_dev, VIDIOC_G_TUNER);
+                       v4l2_disable_ioctl(&v4l2->vbi_dev, VIDIOC_S_TUNER);
+                       v4l2_disable_ioctl(&v4l2->vbi_dev, VIDIOC_G_FREQUENCY);
+                       v4l2_disable_ioctl(&v4l2->vbi_dev, VIDIOC_S_FREQUENCY);
                }
                if (dev->int_audio_type == EM28XX_INT_AUDIO_NONE) {
-                       v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_G_AUDIO);
-                       v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_AUDIO);
+                       v4l2_disable_ioctl(&v4l2->vbi_dev, VIDIOC_G_AUDIO);
+                       v4l2_disable_ioctl(&v4l2->vbi_dev, VIDIOC_S_AUDIO);
                }
 
                /* register v4l2 vbi video_device */
-               ret = video_register_device(v4l2->vbi_dev, VFL_TYPE_VBI,
+               ret = video_register_device(&v4l2->vbi_dev, VFL_TYPE_VBI,
                                            vbi_nr[dev->devno]);
                if (ret < 0) {
                        em28xx_errdev("unable to register vbi device\n");
@@ -2561,29 +2549,24 @@ static int em28xx_v4l2_init(struct em28xx *dev)
        }
 
        if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) {
-               v4l2->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template,
-                                                  "radio");
-               if (!v4l2->radio_dev) {
-                       em28xx_errdev("cannot allocate video_device.\n");
-                       ret = -ENODEV;
-                       goto unregister_dev;
-               }
-               ret = video_register_device(v4l2->radio_dev, VFL_TYPE_RADIO,
+               em28xx_vdev_init(dev, &v4l2->radio_dev, &em28xx_radio_template,
+                                  "radio");
+               ret = video_register_device(&v4l2->radio_dev, VFL_TYPE_RADIO,
                                            radio_nr[dev->devno]);
                if (ret < 0) {
                        em28xx_errdev("can't register radio device\n");
                        goto unregister_dev;
                }
                em28xx_info("Registered radio device as %s\n",
-                           video_device_node_name(v4l2->radio_dev));
+                           video_device_node_name(&v4l2->radio_dev));
        }
 
        em28xx_info("V4L2 video device registered as %s\n",
-                   video_device_node_name(v4l2->vdev));
+                   video_device_node_name(&v4l2->vdev));
 
-       if (v4l2->vbi_dev)
+       if (video_is_registered(&v4l2->vbi_dev))
                em28xx_info("V4L2 VBI device registered as %s\n",
-                           video_device_node_name(v4l2->vbi_dev));
+                           video_device_node_name(&v4l2->vbi_dev));
 
        /* Save some power by putting tuner to sleep */
        v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_power, 0);
index 9c7075344109b0ef0e3f1a11e33521cce36e6a7b..e6559c6f143c663b3cdf2bf23d9c643e72f5a4c6 100644 (file)
 #define EM28178_BOARD_PCTV_292E                   94
 #define EM2861_BOARD_LEADTEK_VC100                95
 #define EM28178_BOARD_TERRATEC_T2_STICK_HD        96
+#define EM2884_BOARD_ELGATO_EYETV_HYBRID_2008     97
 
 /* Limits minimum and default number of buffers */
 #define EM28XX_MIN_BUF 4
@@ -512,9 +513,9 @@ struct em28xx_v4l2 {
        struct v4l2_ctrl_handler ctrl_handler;
        struct v4l2_clk *clk;
 
-       struct video_device *vdev;
-       struct video_device *vbi_dev;
-       struct video_device *radio_dev;
+       struct video_device vdev;
+       struct video_device vbi_dev;
+       struct video_device radio_dev;
 
        /* Videobuf2 */
        struct vb2_queue vb_vidq;
index a9c866d6d82ddda715f4275937572847e8bbb4be..146071b8e11618a12b480db88ee946c5af11e87b 100644 (file)
@@ -816,21 +816,16 @@ static void sethue(struct gspca_dev *gspca_dev, s32 val)
                s16 huesin;
                s16 huecos;
 
-               /* fixp_sin and fixp_cos accept only positive values, while
-                * our val is between -90 and 90
-                */
-               val += 360;
-
                /* According to the datasheet the registers expect HUESIN and
                 * HUECOS to be the result of the trigonometric functions,
                 * scaled by 0x80.
                 *
-                * The 0x100 here represents the maximun absolute value
+                * The 0x7fff here represents the maximum absolute value
                 * returned byt fixp_sin and fixp_cos, so the scaling will
                 * consider the result like in the interval [-1.0, 1.0].
                 */
-               huesin = fixp_sin(val) * 0x80 / 0x100;
-               huecos = fixp_cos(val) * 0x80 / 0x100;
+               huesin = fixp_sin16(val) * 0x80 / 0x7fff;
+               huecos = fixp_cos16(val) * 0x80 / 0x7fff;
 
                if (huesin < 0) {
                        sccb_reg_write(gspca_dev, 0xab,
index 5fcd1eec2004ae97b1ed61df808cf3e97bc1adf4..c70ff406b07ac55cf6f48b2741930b39afa2ca2d 100644 (file)
@@ -969,7 +969,9 @@ static void jpeg_set_qual(u8 *jpeg_hdr,
 {
        int i, sc;
 
-       if (quality < 50)
+       if (quality <= 0)
+               sc = 5000;
+       else if (quality < 50)
                sc = 5000 / quality;
        else
                sc = 200 - quality * 2;
index 42b4cdf28cfd9d24e89e38a7ca3eb84a0354b57e..3fc64197b4e6a6475c89b61d580bf3a4317e4b35 100644 (file)
@@ -69,10 +69,6 @@ MODULE_DEVICE_TABLE(usb, hdpvr_table);
 void hdpvr_delete(struct hdpvr_device *dev)
 {
        hdpvr_free_buffers(dev);
-
-       if (dev->video_dev)
-               video_device_release(dev->video_dev);
-
        usb_put_dev(dev->udev);
 }
 
@@ -397,7 +393,7 @@ static int hdpvr_probe(struct usb_interface *interface,
 
        /* let the user know what node this device is now attached to */
        v4l2_info(&dev->v4l2_dev, "device now attached to %s\n",
-                 video_device_node_name(dev->video_dev));
+                 video_device_node_name(&dev->video_dev));
        return 0;
 
 reg_fail:
@@ -420,7 +416,7 @@ static void hdpvr_disconnect(struct usb_interface *interface)
        struct hdpvr_device *dev = to_hdpvr_dev(usb_get_intfdata(interface));
 
        v4l2_info(&dev->v4l2_dev, "device %s disconnected\n",
-                 video_device_node_name(dev->video_dev));
+                 video_device_node_name(&dev->video_dev));
        /* prevent more I/O from starting and stop any ongoing */
        mutex_lock(&dev->io_mutex);
        dev->status = STATUS_DISCONNECTED;
@@ -436,7 +432,7 @@ static void hdpvr_disconnect(struct usb_interface *interface)
 #if IS_ENABLED(CONFIG_I2C)
        i2c_del_adapter(&dev->i2c_adapter);
 #endif
-       video_unregister_device(dev->video_dev);
+       video_unregister_device(&dev->video_dev);
        atomic_dec(&dev_nr);
 }
 
index 59d15fd242ba04b8c38147225c538907b9cab4cc..d8d8c0f519fc2484edc04a4aa07f29154957ad9b 100644 (file)
@@ -797,7 +797,7 @@ static int vidioc_s_input(struct file *file, void *_fh,
                 * Comment this out for now, but if the legacy mode can be
                 * removed in the future, then this code should be enabled
                 * again.
-               dev->video_dev->tvnorms =
+               dev->video_dev.tvnorms =
                        (index != HDPVR_COMPONENT) ? V4L2_STD_ALL : 0;
                 */
        }
@@ -1228,19 +1228,12 @@ int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent,
        }
 
        /* setup and register video device */
-       dev->video_dev = video_device_alloc();
-       if (!dev->video_dev) {
-               v4l2_err(&dev->v4l2_dev, "video_device_alloc() failed\n");
-               res = -ENOMEM;
-               goto error;
-       }
-
-       *dev->video_dev = hdpvr_video_template;
-       strcpy(dev->video_dev->name, "Hauppauge HD PVR");
-       dev->video_dev->v4l2_dev = &dev->v4l2_dev;
-       video_set_drvdata(dev->video_dev, dev);
+       dev->video_dev = hdpvr_video_template;
+       strcpy(dev->video_dev.name, "Hauppauge HD PVR");
+       dev->video_dev.v4l2_dev = &dev->v4l2_dev;
+       video_set_drvdata(&dev->video_dev, dev);
 
-       res = video_register_device(dev->video_dev, VFL_TYPE_GRABBER, devnum);
+       res = video_register_device(&dev->video_dev, VFL_TYPE_GRABBER, devnum);
        if (res < 0) {
                v4l2_err(&dev->v4l2_dev, "video_device registration failed\n");
                goto error;
index dc685d44cb3e4ef24284f9807c966af7e85a35a8..a3194304182d03b453959d4c068d3ecdc422afac 100644 (file)
@@ -66,7 +66,7 @@ struct hdpvr_options {
 /* Structure to hold all of our device specific stuff */
 struct hdpvr_device {
        /* the v4l device for this device */
-       struct video_device     *video_dev;
+       struct video_device     video_dev;
        /* the control handler for this device */
        struct v4l2_ctrl_handler hdl;
        /* the usb device for this device */
index 35e4ea530494ffe2dea15d4786f003a66f68b9ac..1c5f85bf7ed4b49c8c13d0bbae3869928892e698 100644 (file)
@@ -21,7 +21,6 @@
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/version.h>
 #include "pvrusb2-context.h"
 #include "pvrusb2-hdw.h"
 #include "pvrusb2.h"
@@ -32,6 +31,7 @@
 #include <linux/module.h>
 #include <media/v4l2-dev.h>
 #include <media/v4l2-device.h>
+#include <media/v4l2-fh.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
 
@@ -50,14 +50,11 @@ struct pvr2_v4l2_dev {
 };
 
 struct pvr2_v4l2_fh {
+       struct v4l2_fh fh;
        struct pvr2_channel channel;
        struct pvr2_v4l2_dev *pdi;
-       enum v4l2_priority prio;
        struct pvr2_ioread *rhp;
        struct file *file;
-       struct pvr2_v4l2 *vhead;
-       struct pvr2_v4l2_fh *vnext;
-       struct pvr2_v4l2_fh *vprev;
        wait_queue_head_t wait_data;
        int fw_mode_flag;
        /* Map contiguous ordinal value to input id */
@@ -67,10 +64,6 @@ struct pvr2_v4l2_fh {
 
 struct pvr2_v4l2 {
        struct pvr2_channel channel;
-       struct pvr2_v4l2_fh *vfirst;
-       struct pvr2_v4l2_fh *vlast;
-
-       struct v4l2_prio_state prio;
 
        /* streams - Note that these must be separately, individually,
         * allocated pointers.  This is because the v4l core is going to
@@ -169,23 +162,6 @@ static int pvr2_querycap(struct file *file, void *priv, struct v4l2_capability *
        return 0;
 }
 
-static int pvr2_g_priority(struct file *file, void *priv, enum v4l2_priority *p)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_v4l2 *vp = fh->vhead;
-
-       *p = v4l2_prio_max(&vp->prio);
-       return 0;
-}
-
-static int pvr2_s_priority(struct file *file, void *priv, enum v4l2_priority prio)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_v4l2 *vp = fh->vhead;
-
-       return v4l2_prio_change(&vp->prio, &fh->prio, prio);
-}
-
 static int pvr2_g_std(struct file *file, void *priv, v4l2_std_id *std)
 {
        struct pvr2_v4l2_fh *fh = file->private_data;
@@ -805,8 +781,6 @@ static int pvr2_log_status(struct file *file, void *priv)
 
 static const struct v4l2_ioctl_ops pvr2_ioctl_ops = {
        .vidioc_querycap                    = pvr2_querycap,
-       .vidioc_g_priority                  = pvr2_g_priority,
-       .vidioc_s_priority                  = pvr2_s_priority,
        .vidioc_s_audio                     = pvr2_s_audio,
        .vidioc_g_audio                     = pvr2_g_audio,
        .vidioc_enumaudio                   = pvr2_enumaudio,
@@ -911,7 +885,9 @@ static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
        if (!vp->channel.mc_head->disconnect_flag) return;
        pvr2_v4l2_dev_disassociate_parent(vp->dev_video);
        pvr2_v4l2_dev_disassociate_parent(vp->dev_radio);
-       if (vp->vfirst) return;
+       if (!list_empty(&vp->dev_video->devbase.fh_list) ||
+           !list_empty(&vp->dev_radio->devbase.fh_list))
+               return;
        pvr2_v4l2_destroy_no_lock(vp);
 }
 
@@ -921,7 +897,6 @@ static long pvr2_v4l2_ioctl(struct file *file,
 {
 
        struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_v4l2 *vp = fh->vhead;
        struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
        long ret = -EINVAL;
 
@@ -934,18 +909,6 @@ static long pvr2_v4l2_ioctl(struct file *file,
                return -EFAULT;
        }
 
-       /* check priority */
-       switch (cmd) {
-       case VIDIOC_S_CTRL:
-       case VIDIOC_S_STD:
-       case VIDIOC_S_INPUT:
-       case VIDIOC_S_TUNER:
-       case VIDIOC_S_FREQUENCY:
-               ret = v4l2_prio_check(&vp->prio, fh->prio);
-               if (ret)
-                       return ret;
-       }
-
        ret = video_ioctl2(file, cmd, arg);
 
        pvr2_hdw_commit_ctl(hdw);
@@ -970,7 +933,7 @@ static long pvr2_v4l2_ioctl(struct file *file,
 static int pvr2_v4l2_release(struct file *file)
 {
        struct pvr2_v4l2_fh *fhp = file->private_data;
-       struct pvr2_v4l2 *vp = fhp->vhead;
+       struct pvr2_v4l2 *vp = fhp->pdi->v4lp;
        struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
 
        pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
@@ -984,22 +947,10 @@ static int pvr2_v4l2_release(struct file *file)
                fhp->rhp = NULL;
        }
 
-       v4l2_prio_close(&vp->prio, fhp->prio);
+       v4l2_fh_del(&fhp->fh);
+       v4l2_fh_exit(&fhp->fh);
        file->private_data = NULL;
 
-       if (fhp->vnext) {
-               fhp->vnext->vprev = fhp->vprev;
-       } else {
-               vp->vlast = fhp->vprev;
-       }
-       if (fhp->vprev) {
-               fhp->vprev->vnext = fhp->vnext;
-       } else {
-               vp->vfirst = fhp->vnext;
-       }
-       fhp->vnext = NULL;
-       fhp->vprev = NULL;
-       fhp->vhead = NULL;
        pvr2_channel_done(&fhp->channel);
        pvr2_trace(PVR2_TRACE_STRUCT,
                   "Destroying pvr_v4l2_fh id=%p",fhp);
@@ -1008,7 +959,9 @@ static int pvr2_v4l2_release(struct file *file)
                fhp->input_map = NULL;
        }
        kfree(fhp);
-       if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
+       if (vp->channel.mc_head->disconnect_flag &&
+           list_empty(&vp->dev_video->devbase.fh_list) &&
+           list_empty(&vp->dev_radio->devbase.fh_list)) {
                pvr2_v4l2_destroy_no_lock(vp);
        }
        return 0;
@@ -1043,6 +996,7 @@ static int pvr2_v4l2_open(struct file *file)
                return -ENOMEM;
        }
 
+       v4l2_fh_init(&fhp->fh, &dip->devbase);
        init_waitqueue_head(&fhp->wait_data);
        fhp->pdi = dip;
 
@@ -1093,21 +1047,11 @@ static int pvr2_v4l2_open(struct file *file)
                fhp->input_map[input_cnt++] = idx;
        }
 
-       fhp->vnext = NULL;
-       fhp->vprev = vp->vlast;
-       if (vp->vlast) {
-               vp->vlast->vnext = fhp;
-       } else {
-               vp->vfirst = fhp;
-       }
-       vp->vlast = fhp;
-       fhp->vhead = vp;
-
        fhp->file = file;
        file->private_data = fhp;
-       v4l2_prio_open(&vp->prio, &fhp->prio);
 
        fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
+       v4l2_fh_add(&fhp->fh);
 
        return 0;
 }
@@ -1247,7 +1191,7 @@ static const struct v4l2_file_operations vdev_fops = {
        .open       = pvr2_v4l2_open,
        .release    = pvr2_v4l2_release,
        .read       = pvr2_v4l2_read,
-       .ioctl      = pvr2_v4l2_ioctl,
+       .unlocked_ioctl = pvr2_v4l2_ioctl,
        .poll       = pvr2_v4l2_poll,
 };
 
index 94e10b10b66e8c41c95672a702bcb84c91f5b05b..c945e4c2fbd49cdb0ffab93a53cd72ee37e81db7 100644 (file)
@@ -19,6 +19,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 ****************************************************************/
 
+#include "smscoreapi.h"
+
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/usb.h>
@@ -26,14 +28,9 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include <linux/slab.h>
 #include <linux/module.h>
 
-#include "smscoreapi.h"
 #include "sms-cards.h"
 #include "smsendian.h"
 
-static int sms_dbg;
-module_param_named(debug, sms_dbg, int, 0644);
-MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
-
 #define USB1_BUFFER_SIZE               0x1000
 #define USB2_BUFFER_SIZE               0x2000
 
@@ -87,7 +84,7 @@ static void smsusb_onresponse(struct urb *urb)
        struct smsusb_device_t *dev = surb->dev;
 
        if (urb->status == -ESHUTDOWN) {
-               sms_err("error, urb status %d (-ESHUTDOWN), %d bytes",
+               pr_err("error, urb status %d (-ESHUTDOWN), %d bytes\n",
                        urb->status, urb->actual_length);
                return;
        }
@@ -109,9 +106,7 @@ static void smsusb_onresponse(struct urb *urb)
                                /* sanity check */
                                if (((int) phdr->msg_length +
                                     surb->cb->offset) > urb->actual_length) {
-                                       sms_err("invalid response "
-                                               "msglen %d offset %d "
-                                               "size %d",
+                                       pr_err("invalid response msglen %d offset %d size %d\n",
                                                phdr->msg_length,
                                                surb->cb->offset,
                                                urb->actual_length);
@@ -125,7 +120,7 @@ static void smsusb_onresponse(struct urb *urb)
                        } else
                                surb->cb->offset = 0;
 
-                       sms_debug("received %s(%d) size: %d",
+                       pr_debug("received %s(%d) size: %d\n",
                                  smscore_translate_msg(phdr->msg_type),
                                  phdr->msg_type, phdr->msg_length);
 
@@ -134,12 +129,11 @@ static void smsusb_onresponse(struct urb *urb)
                        smscore_onresponse(dev->coredev, surb->cb);
                        surb->cb = NULL;
                } else {
-                       sms_err("invalid response "
-                               "msglen %d actual %d",
+                       pr_err("invalid response msglen %d actual %d\n",
                                phdr->msg_length, urb->actual_length);
                }
        } else
-               sms_err("error, urb status %d, %d bytes",
+               pr_err("error, urb status %d, %d bytes\n",
                        urb->status, urb->actual_length);
 
 
@@ -153,7 +147,7 @@ static int smsusb_submit_urb(struct smsusb_device_t *dev,
        if (!surb->cb) {
                surb->cb = smscore_getbuffer(dev->coredev);
                if (!surb->cb) {
-                       sms_err("smscore_getbuffer(...) returned NULL");
+                       pr_err("smscore_getbuffer(...) returned NULL\n");
                        return -ENOMEM;
                }
        }
@@ -194,7 +188,7 @@ static int smsusb_start_streaming(struct smsusb_device_t *dev)
        for (i = 0; i < MAX_URBS; i++) {
                rc = smsusb_submit_urb(dev, &dev->surbs[i]);
                if (rc < 0) {
-                       sms_err("smsusb_submit_urb(...) failed");
+                       pr_err("smsusb_submit_urb(...) failed\n");
                        smsusb_stop_streaming(dev);
                        break;
                }
@@ -210,11 +204,11 @@ static int smsusb_sendrequest(void *context, void *buffer, size_t size)
        int dummy;
 
        if (dev->state != SMSUSB_ACTIVE) {
-               sms_debug("Device not active yet");
+               pr_debug("Device not active yet\n");
                return -ENOENT;
        }
 
-       sms_debug("sending %s(%d) size: %d",
+       pr_debug("sending %s(%d) size: %d\n",
                  smscore_translate_msg(phdr->msg_type), phdr->msg_type,
                  phdr->msg_length);
 
@@ -249,7 +243,7 @@ static int smsusb1_load_firmware(struct usb_device *udev, int id, int board_id)
                id = sms_get_board(board_id)->default_mode;
 
        if (id < DEVICE_MODE_DVBT || id > DEVICE_MODE_DVBT_BDA) {
-               sms_err("invalid firmware id specified %d", id);
+               pr_err("invalid firmware id specified %d\n", id);
                return -EINVAL;
        }
 
@@ -257,13 +251,13 @@ static int smsusb1_load_firmware(struct usb_device *udev, int id, int board_id)
 
        rc = request_firmware(&fw, fw_filename, &udev->dev);
        if (rc < 0) {
-               sms_warn("failed to open \"%s\" mode %d, "
-                        "trying again with default firmware", fw_filename, id);
+               pr_warn("failed to open '%s' mode %d, trying again with default firmware\n",
+                       fw_filename, id);
 
                fw_filename = smsusb1_fw_lkup[id];
                rc = request_firmware(&fw, fw_filename, &udev->dev);
                if (rc < 0) {
-                       sms_warn("failed to open \"%s\" mode %d",
+                       pr_warn("failed to open '%s' mode %d\n",
                                 fw_filename, id);
 
                        return rc;
@@ -277,14 +271,14 @@ static int smsusb1_load_firmware(struct usb_device *udev, int id, int board_id)
                rc = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 2),
                                  fw_buffer, fw->size, &dummy, 1000);
 
-               sms_info("sent %zu(%d) bytes, rc %d", fw->size, dummy, rc);
+               pr_debug("sent %zu(%d) bytes, rc %d\n", fw->size, dummy, rc);
 
                kfree(fw_buffer);
        } else {
-               sms_err("failed to allocate firmware buffer");
+               pr_err("failed to allocate firmware buffer\n");
                rc = -ENOMEM;
        }
-       sms_info("read FW %s, size=%zu", fw_filename, fw->size);
+       pr_debug("read FW %s, size=%zu\n", fw_filename, fw->size);
 
        release_firmware(fw);
 
@@ -300,7 +294,7 @@ static void smsusb1_detectmode(void *context, int *mode)
 
        if (!product_string) {
                product_string = "none";
-               sms_err("product string not found");
+               pr_err("product string not found\n");
        } else if (strstr(product_string, "DVBH"))
                *mode = 1;
        else if (strstr(product_string, "BDA"))
@@ -310,7 +304,7 @@ static void smsusb1_detectmode(void *context, int *mode)
        else if (strstr(product_string, "TDMB"))
                *mode = 2;
 
-       sms_info("%d \"%s\"", *mode, product_string);
+       pr_debug("%d \"%s\"\n", *mode, product_string);
 }
 
 static int smsusb1_setmode(void *context, int mode)
@@ -319,7 +313,7 @@ static int smsusb1_setmode(void *context, int mode)
                             sizeof(struct sms_msg_hdr), 0 };
 
        if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_DVBT_BDA) {
-               sms_err("invalid firmware id specified %d", mode);
+               pr_err("invalid firmware id specified %d\n", mode);
                return -EINVAL;
        }
 
@@ -339,25 +333,61 @@ static void smsusb_term_device(struct usb_interface *intf)
                if (dev->coredev)
                        smscore_unregister_device(dev->coredev);
 
-               sms_info("device 0x%p destroyed", dev);
+               pr_debug("device 0x%p destroyed\n", dev);
                kfree(dev);
        }
 
        usb_set_intfdata(intf, NULL);
 }
 
+static void *siano_media_device_register(struct smsusb_device_t *dev,
+                                       int board_id)
+{
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+       struct media_device *mdev;
+       struct usb_device *udev = dev->udev;
+       struct sms_board *board = sms_get_board(board_id);
+       int ret;
+
+       mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
+       if (!mdev)
+               return NULL;
+
+       mdev->dev = &udev->dev;
+       strlcpy(mdev->model, board->name, sizeof(mdev->model));
+       if (udev->serial)
+               strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial));
+       strcpy(mdev->bus_info, udev->devpath);
+       mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
+       mdev->driver_version = LINUX_VERSION_CODE;
+
+       ret = media_device_register(mdev);
+       if (ret) {
+               pr_err("Couldn't create a media device. Error: %d\n",
+                       ret);
+               kfree(mdev);
+               return NULL;
+       }
+
+       pr_info("media controller created\n");
+
+       return mdev;
+#else
+       return NULL;
+#endif
+}
+
 static int smsusb_init_device(struct usb_interface *intf, int board_id)
 {
        struct smsdevice_params_t params;
        struct smsusb_device_t *dev;
+       void *mdev;
        int i, rc;
 
        /* create device object */
        dev = kzalloc(sizeof(struct smsusb_device_t), GFP_KERNEL);
-       if (!dev) {
-               sms_err("kzalloc(sizeof(struct smsusb_device_t) failed");
+       if (!dev)
                return -ENOMEM;
-       }
 
        memset(&params, 0, sizeof(params));
        usb_set_intfdata(intf, dev);
@@ -374,7 +404,7 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
                params.detectmode_handler = smsusb1_detectmode;
                break;
        case SMS_UNKNOWN_TYPE:
-               sms_err("Unspecified sms device type!");
+               pr_err("Unspecified sms device type!\n");
                /* fall-thru */
        default:
                dev->buffer_size = USB2_BUFFER_SIZE;
@@ -393,7 +423,7 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
                        dev->out_ep = intf->cur_altsetting->endpoint[i].desc.bEndpointAddress;
        }
 
-       sms_info("in_ep = %02x, out_ep = %02x",
+       pr_debug("in_ep = %02x, out_ep = %02x\n",
                dev->in_ep, dev->out_ep);
 
        params.device = &dev->udev->dev;
@@ -403,11 +433,17 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
        params.context = dev;
        usb_make_path(dev->udev, params.devpath, sizeof(params.devpath));
 
+       mdev = siano_media_device_register(dev, board_id);
+
        /* register in smscore */
-       rc = smscore_register_device(&params, &dev->coredev);
+       rc = smscore_register_device(&params, &dev->coredev, mdev);
        if (rc < 0) {
-               sms_err("smscore_register_device(...) failed, rc %d", rc);
+               pr_err("smscore_register_device(...) failed, rc %d\n", rc);
                smsusb_term_device(intf);
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+               media_device_unregister(mdev);
+#endif
+               kfree(mdev);
                return rc;
        }
 
@@ -421,10 +457,10 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
                usb_init_urb(&dev->surbs[i].urb);
        }
 
-       sms_info("smsusb_start_streaming(...).");
+       pr_debug("smsusb_start_streaming(...).\n");
        rc = smsusb_start_streaming(dev);
        if (rc < 0) {
-               sms_err("smsusb_start_streaming(...) failed");
+               pr_err("smsusb_start_streaming(...) failed\n");
                smsusb_term_device(intf);
                return rc;
        }
@@ -433,12 +469,12 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
 
        rc = smscore_start_device(dev->coredev);
        if (rc < 0) {
-               sms_err("smscore_start_device(...) failed");
+               pr_err("smscore_start_device(...) failed\n");
                smsusb_term_device(intf);
                return rc;
        }
 
-       sms_info("device 0x%p created", dev);
+       pr_debug("device 0x%p created\n", dev);
 
        return rc;
 }
@@ -450,13 +486,13 @@ static int smsusb_probe(struct usb_interface *intf,
        char devpath[32];
        int i, rc;
 
-       sms_info("board id=%lu, interface number %d",
+       pr_info("board id=%lu, interface number %d\n",
                 id->driver_info,
                 intf->cur_altsetting->desc.bInterfaceNumber);
 
        if (sms_get_board(id->driver_info)->intf_num !=
            intf->cur_altsetting->desc.bInterfaceNumber) {
-               sms_debug("interface %d won't be used. Expecting interface %d to popup",
+               pr_debug("interface %d won't be used. Expecting interface %d to popup\n",
                        intf->cur_altsetting->desc.bInterfaceNumber,
                        sms_get_board(id->driver_info)->intf_num);
                return -ENODEV;
@@ -467,15 +503,15 @@ static int smsusb_probe(struct usb_interface *intf,
                                       intf->cur_altsetting->desc.bInterfaceNumber,
                                       0);
                if (rc < 0) {
-                       sms_err("usb_set_interface failed, rc %d", rc);
+                       pr_err("usb_set_interface failed, rc %d\n", rc);
                        return rc;
                }
        }
 
-       sms_info("smsusb_probe %d",
+       pr_debug("smsusb_probe %d\n",
               intf->cur_altsetting->desc.bInterfaceNumber);
        for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
-               sms_info("endpoint %d %02x %02x %d", i,
+               pr_debug("endpoint %d %02x %02x %d\n", i,
                       intf->cur_altsetting->endpoint[i].desc.bEndpointAddress,
                       intf->cur_altsetting->endpoint[i].desc.bmAttributes,
                       intf->cur_altsetting->endpoint[i].desc.wMaxPacketSize);
@@ -489,7 +525,7 @@ static int smsusb_probe(struct usb_interface *intf,
        }
        if ((udev->actconfig->desc.bNumInterfaces == 2) &&
            (intf->cur_altsetting->desc.bInterfaceNumber == 0)) {
-               sms_debug("rom interface 0 is not used");
+               pr_debug("rom interface 0 is not used\n");
                return -ENODEV;
        }
 
@@ -498,23 +534,25 @@ static int smsusb_probe(struct usb_interface *intf,
 
                snprintf(devpath, sizeof(devpath), "usb\\%d-%s",
                         udev->bus->busnum, udev->devpath);
-               sms_info("stellar device in cold state was found at %s.", devpath);
+               pr_info("stellar device in cold state was found at %s.\n",
+                       devpath);
                rc = smsusb1_load_firmware(
                                udev, smscore_registry_getmode(devpath),
                                id->driver_info);
 
                /* This device will reset and gain another USB ID */
                if (!rc)
-                       sms_info("stellar device now in warm state");
+                       pr_info("stellar device now in warm state\n");
                else
-                       sms_err("Failed to put stellar in warm state. Error: %d", rc);
+                       pr_err("Failed to put stellar in warm state. Error: %d\n",
+                              rc);
 
                return rc;
        } else {
                rc = smsusb_init_device(intf, id->driver_info);
        }
 
-       sms_info("Device initialized with return code %d", rc);
+       pr_info("Device initialized with return code %d\n", rc);
        sms_board_load_modules(id->driver_info);
        return rc;
 }
index 65a326c5128fda082e1b9ac0e8ca176f86b44a62..749ad5603c9e93488adec2c4347d531a807c0cf5 100644 (file)
@@ -240,6 +240,11 @@ static int stk1160_stop_streaming(struct stk1160 *dev)
        if (mutex_lock_interruptible(&dev->v4l_lock))
                return -ERESTARTSYS;
 
+       /*
+        * Once URBs are cancelled, the URB complete handler
+        * won't be running. This is required to safely release the
+        * current buffer (dev->isoc_ctl.buf).
+        */
        stk1160_cancel_isoc(dev);
 
        /*
@@ -620,8 +625,16 @@ void stk1160_clear_queue(struct stk1160 *dev)
                stk1160_info("buffer [%p/%d] aborted\n",
                                buf, buf->vb.v4l2_buf.index);
        }
-       /* It's important to clear current buffer */
-       dev->isoc_ctl.buf = NULL;
+
+       /* It's important to release the current buffer */
+       if (dev->isoc_ctl.buf) {
+               buf = dev->isoc_ctl.buf;
+               dev->isoc_ctl.buf = NULL;
+
+               vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+               stk1160_info("buffer [%p/%d] aborted\n",
+                               buf, buf->vb.v4l2_buf.index);
+       }
        spin_unlock_irqrestore(&dev->buf_lock, flags);
 }
 
index e08fa587332f88028d2f762d8191c589e6403b1b..c21c4c004f9778a50809c27d0cba39ca9596d7f7 100644 (file)
@@ -556,10 +556,8 @@ static int stk_free_sio_buffers(struct stk_camera *dev)
        nbufs = dev->n_sbufs;
        dev->n_sbufs = 0;
        spin_unlock_irqrestore(&dev->spinlock, flags);
-       for (i = 0; i < nbufs; i++) {
-               if (dev->sio_bufs[i].buffer != NULL)
-                       vfree(dev->sio_bufs[i].buffer);
-       }
+       for (i = 0; i < nbufs; i++)
+               vfree(dev->sio_bufs[i].buffer);
        kfree(dev->sio_bufs);
        dev->sio_bufs = NULL;
        return 0;
index 0f14d3ccc7b4454a7b16bf810e9467410eaa7a49..77ce9efe1f2477050b665bde13a24868370f1383 100644 (file)
@@ -1576,7 +1576,7 @@ static struct video_device tm6000_template = {
        .name           = "tm6000",
        .fops           = &tm6000_fops,
        .ioctl_ops      = &video_ioctl_ops,
-       .release        = video_device_release,
+       .release        = video_device_release_empty,
        .tvnorms        = TM6000_STD,
 };
 
@@ -1609,25 +1609,19 @@ static struct video_device tm6000_radio_template = {
  * ------------------------------------------------------------------
  */
 
-static struct video_device *vdev_init(struct tm6000_core *dev,
+static void vdev_init(struct tm6000_core *dev,
+               struct video_device *vfd,
                const struct video_device
                *template, const char *type_name)
 {
-       struct video_device *vfd;
-
-       vfd = video_device_alloc();
-       if (NULL == vfd)
-               return NULL;
-
        *vfd = *template;
        vfd->v4l2_dev = &dev->v4l2_dev;
-       vfd->release = video_device_release;
+       vfd->release = video_device_release_empty;
        vfd->lock = &dev->lock;
 
        snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name);
 
        video_set_drvdata(vfd, dev);
-       return vfd;
 }
 
 int tm6000_v4l2_register(struct tm6000_core *dev)
@@ -1658,62 +1652,46 @@ int tm6000_v4l2_register(struct tm6000_core *dev)
        if (ret)
                goto free_ctrl;
 
-       dev->vfd = vdev_init(dev, &tm6000_template, "video");
+       vdev_init(dev, &dev->vfd, &tm6000_template, "video");
 
-       if (!dev->vfd) {
-               printk(KERN_INFO "%s: can't register video device\n",
-                      dev->name);
-               ret = -ENOMEM;
-               goto free_ctrl;
-       }
-       dev->vfd->ctrl_handler = &dev->ctrl_handler;
+       dev->vfd.ctrl_handler = &dev->ctrl_handler;
 
        /* init video dma queues */
        INIT_LIST_HEAD(&dev->vidq.active);
        INIT_LIST_HEAD(&dev->vidq.queued);
 
-       ret = video_register_device(dev->vfd, VFL_TYPE_GRABBER, video_nr);
+       ret = video_register_device(&dev->vfd, VFL_TYPE_GRABBER, video_nr);
 
        if (ret < 0) {
                printk(KERN_INFO "%s: can't register video device\n",
                       dev->name);
-               video_device_release(dev->vfd);
-               dev->vfd = NULL;
                goto free_ctrl;
        }
 
        printk(KERN_INFO "%s: registered device %s\n",
-              dev->name, video_device_node_name(dev->vfd));
+              dev->name, video_device_node_name(&dev->vfd));
 
        if (dev->caps.has_radio) {
-               dev->radio_dev = vdev_init(dev, &tm6000_radio_template,
+               vdev_init(dev, &dev->radio_dev, &tm6000_radio_template,
                                                           "radio");
-               if (!dev->radio_dev) {
-                       printk(KERN_INFO "%s: can't register radio device\n",
-                              dev->name);
-                       ret = -ENXIO;
-                       goto unreg_video;
-               }
-
-               dev->radio_dev->ctrl_handler = &dev->radio_ctrl_handler;
-               ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO,
+               dev->radio_dev.ctrl_handler = &dev->radio_ctrl_handler;
+               ret = video_register_device(&dev->radio_dev, VFL_TYPE_RADIO,
                                            radio_nr);
                if (ret < 0) {
                        printk(KERN_INFO "%s: can't register radio device\n",
                               dev->name);
-                       video_device_release(dev->radio_dev);
                        goto unreg_video;
                }
 
                printk(KERN_INFO "%s: registered device %s\n",
-                      dev->name, video_device_node_name(dev->radio_dev));
+                      dev->name, video_device_node_name(&dev->radio_dev));
        }
 
        printk(KERN_INFO "Trident TVMaster TM5600/TM6000/TM6010 USB2 board (Load status: %d)\n", ret);
        return ret;
 
 unreg_video:
-       video_unregister_device(dev->vfd);
+       video_unregister_device(&dev->vfd);
 free_ctrl:
        v4l2_ctrl_handler_free(&dev->ctrl_handler);
        v4l2_ctrl_handler_free(&dev->radio_ctrl_handler);
@@ -1722,19 +1700,12 @@ free_ctrl:
 
 int tm6000_v4l2_unregister(struct tm6000_core *dev)
 {
-       video_unregister_device(dev->vfd);
+       video_unregister_device(&dev->vfd);
 
        /* if URB buffers are still allocated free them now */
        tm6000_free_urb_buffers(dev);
 
-       if (dev->radio_dev) {
-               if (video_is_registered(dev->radio_dev))
-                       video_unregister_device(dev->radio_dev);
-               else
-                       video_device_release(dev->radio_dev);
-               dev->radio_dev = NULL;
-       }
-
+       video_unregister_device(&dev->radio_dev);
        return 0;
 }
 
index 08bd0740dd2368ddaaa23dcaea687f8de57e086c..f2127944776fb2a4fc91458599d4738d1804c620 100644 (file)
@@ -220,8 +220,8 @@ struct tm6000_core {
        struct tm6000_fh                *resources;     /* Points to fh that is streaming */
        bool                            is_res_read;
 
-       struct video_device             *vfd;
-       struct video_device             *radio_dev;
+       struct video_device             vfd;
+       struct video_device             radio_dev;
        struct tm6000_dmaqueue          vidq;
        struct v4l2_device              v4l2_dev;
        struct v4l2_ctrl_handler        ctrl_handler;
index cd2fbf11e3b4a07f53da903792d61f301f899af5..12b403e78d5212b9d1710c6b9dd3bdca30dfaccb 100644 (file)
@@ -471,7 +471,7 @@ static int vidioc_g_register(struct file *file, void *priv,
        /* NT100x has a 8-bit register space */
        err_code = usbvision_read_reg(usbvision, reg->reg&0xff);
        if (err_code < 0) {
-               dev_err(&usbvision->vdev->dev,
+               dev_err(&usbvision->vdev.dev,
                        "%s: VIDIOC_DBG_G_REGISTER failed: error %d\n",
                                __func__, err_code);
                return err_code;
@@ -490,7 +490,7 @@ static int vidioc_s_register(struct file *file, void *priv,
        /* NT100x has a 8-bit register space */
        err_code = usbvision_write_reg(usbvision, reg->reg & 0xff, reg->val);
        if (err_code < 0) {
-               dev_err(&usbvision->vdev->dev,
+               dev_err(&usbvision->vdev.dev,
                        "%s: VIDIOC_DBG_S_REGISTER failed: error %d\n",
                                __func__, err_code);
                return err_code;
@@ -1157,7 +1157,7 @@ static int usbvision_radio_open(struct file *file)
        if (mutex_lock_interruptible(&usbvision->v4l2_lock))
                return -ERESTARTSYS;
        if (usbvision->user) {
-               dev_err(&usbvision->rdev->dev,
+               dev_err(&usbvision->rdev.dev,
                        "%s: Someone tried to open an already opened USBVision Radio!\n",
                                __func__);
                err_code = -EBUSY;
@@ -1280,7 +1280,7 @@ static struct video_device usbvision_video_template = {
        .fops           = &usbvision_fops,
        .ioctl_ops      = &usbvision_ioctl_ops,
        .name           = "usbvision-video",
-       .release        = video_device_release,
+       .release        = video_device_release_empty,
        .tvnorms        = USBVISION_NORMS,
 };
 
@@ -1312,58 +1312,46 @@ static const struct v4l2_ioctl_ops usbvision_radio_ioctl_ops = {
 static struct video_device usbvision_radio_template = {
        .fops           = &usbvision_radio_fops,
        .name           = "usbvision-radio",
-       .release        = video_device_release,
+       .release        = video_device_release_empty,
        .ioctl_ops      = &usbvision_radio_ioctl_ops,
 };
 
 
-static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision,
-                                       struct video_device *vdev_template,
-                                       char *name)
+static void usbvision_vdev_init(struct usb_usbvision *usbvision,
+                               struct video_device *vdev,
+                               const struct video_device *vdev_template,
+                               const char *name)
 {
        struct usb_device *usb_dev = usbvision->dev;
-       struct video_device *vdev;
 
        if (usb_dev == NULL) {
                dev_err(&usbvision->dev->dev,
                        "%s: usbvision->dev is not set\n", __func__);
-               return NULL;
+               return;
        }
 
-       vdev = video_device_alloc();
-       if (NULL == vdev)
-               return NULL;
        *vdev = *vdev_template;
        vdev->lock = &usbvision->v4l2_lock;
        vdev->v4l2_dev = &usbvision->v4l2_dev;
        snprintf(vdev->name, sizeof(vdev->name), "%s", name);
        video_set_drvdata(vdev, usbvision);
-       return vdev;
 }
 
 /* unregister video4linux devices */
 static void usbvision_unregister_video(struct usb_usbvision *usbvision)
 {
        /* Radio Device: */
-       if (usbvision->rdev) {
+       if (video_is_registered(&usbvision->rdev)) {
                PDEBUG(DBG_PROBE, "unregister %s [v4l2]",
-                      video_device_node_name(usbvision->rdev));
-               if (video_is_registered(usbvision->rdev))
-                       video_unregister_device(usbvision->rdev);
-               else
-                       video_device_release(usbvision->rdev);
-               usbvision->rdev = NULL;
+                      video_device_node_name(&usbvision->rdev));
+               video_unregister_device(&usbvision->rdev);
        }
 
        /* Video Device: */
-       if (usbvision->vdev) {
+       if (video_is_registered(&usbvision->vdev)) {
                PDEBUG(DBG_PROBE, "unregister %s [v4l2]",
-                      video_device_node_name(usbvision->vdev));
-               if (video_is_registered(usbvision->vdev))
-                       video_unregister_device(usbvision->vdev);
-               else
-                       video_device_release(usbvision->vdev);
-               usbvision->vdev = NULL;
+                      video_device_node_name(&usbvision->vdev));
+               video_unregister_device(&usbvision->vdev);
        }
 }
 
@@ -1371,28 +1359,22 @@ static void usbvision_unregister_video(struct usb_usbvision *usbvision)
 static int usbvision_register_video(struct usb_usbvision *usbvision)
 {
        /* Video Device: */
-       usbvision->vdev = usbvision_vdev_init(usbvision,
-                                             &usbvision_video_template,
-                                             "USBVision Video");
-       if (usbvision->vdev == NULL)
-               goto err_exit;
-       if (video_register_device(usbvision->vdev, VFL_TYPE_GRABBER, video_nr) < 0)
+       usbvision_vdev_init(usbvision, &usbvision->vdev,
+                             &usbvision_video_template, "USBVision Video");
+       if (video_register_device(&usbvision->vdev, VFL_TYPE_GRABBER, video_nr) < 0)
                goto err_exit;
        printk(KERN_INFO "USBVision[%d]: registered USBVision Video device %s [v4l2]\n",
-              usbvision->nr, video_device_node_name(usbvision->vdev));
+              usbvision->nr, video_device_node_name(&usbvision->vdev));
 
        /* Radio Device: */
        if (usbvision_device_data[usbvision->dev_model].radio) {
                /* usbvision has radio */
-               usbvision->rdev = usbvision_vdev_init(usbvision,
-                                                     &usbvision_radio_template,
-                                                     "USBVision Radio");
-               if (usbvision->rdev == NULL)
-                       goto err_exit;
-               if (video_register_device(usbvision->rdev, VFL_TYPE_RADIO, radio_nr) < 0)
+               usbvision_vdev_init(usbvision, &usbvision->rdev,
+                             &usbvision_radio_template, "USBVision Radio");
+               if (video_register_device(&usbvision->rdev, VFL_TYPE_RADIO, radio_nr) < 0)
                        goto err_exit;
                printk(KERN_INFO "USBVision[%d]: registered USBVision Radio device %s [v4l2]\n",
-                      usbvision->nr, video_device_node_name(usbvision->rdev));
+                      usbvision->nr, video_device_node_name(&usbvision->rdev));
        }
        /* all done */
        return 0;
@@ -1461,7 +1443,7 @@ static void usbvision_release(struct usb_usbvision *usbvision)
 
        usbvision->initialized = 0;
 
-       usbvision_remove_sysfs(usbvision->vdev);
+       usbvision_remove_sysfs(&usbvision->vdev);
        usbvision_unregister_video(usbvision);
        kfree(usbvision->alt_max_pkt_size);
 
@@ -1525,7 +1507,7 @@ static int usbvision_probe(struct usb_interface *intf,
        const struct usb_host_interface *interface;
        struct usb_usbvision *usbvision = NULL;
        const struct usb_endpoint_descriptor *endpoint;
-       int model, i;
+       int model, i, ret;
 
        PDEBUG(DBG_PROBE, "VID=%#04x, PID=%#04x, ifnum=%u",
                                dev->descriptor.idVendor,
@@ -1534,7 +1516,8 @@ static int usbvision_probe(struct usb_interface *intf,
        model = devid->driver_info;
        if (model < 0 || model >= usbvision_device_data_size) {
                PDEBUG(DBG_PROBE, "model out of bounds %d", model);
-               return -ENODEV;
+               ret = -ENODEV;
+               goto err_usb;
        }
        printk(KERN_INFO "%s: %s found\n", __func__,
                                usbvision_device_data[model].model_string);
@@ -1549,18 +1532,21 @@ static int usbvision_probe(struct usb_interface *intf,
                    __func__, ifnum);
                dev_err(&intf->dev, "%s: Endpoint attributes %d",
                    __func__, endpoint->bmAttributes);
-               return -ENODEV;
+               ret = -ENODEV;
+               goto err_usb;
        }
        if (usb_endpoint_dir_out(endpoint)) {
                dev_err(&intf->dev, "%s: interface %d. has ISO OUT endpoint!\n",
                    __func__, ifnum);
-               return -ENODEV;
+               ret = -ENODEV;
+               goto err_usb;
        }
 
        usbvision = usbvision_alloc(dev, intf);
        if (usbvision == NULL) {
                dev_err(&intf->dev, "%s: couldn't allocate USBVision struct\n", __func__);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto err_usb;
        }
 
        if (dev->descriptor.bNumConfigurations > 1)
@@ -1579,8 +1565,8 @@ static int usbvision_probe(struct usb_interface *intf,
        usbvision->alt_max_pkt_size = kmalloc(32 * usbvision->num_alt, GFP_KERNEL);
        if (usbvision->alt_max_pkt_size == NULL) {
                dev_err(&intf->dev, "usbvision: out of memory!\n");
-               usbvision_release(usbvision);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto err_pkt;
        }
 
        for (i = 0; i < usbvision->num_alt; i++) {
@@ -1611,10 +1597,16 @@ static int usbvision_probe(struct usb_interface *intf,
        usbvision_configure_video(usbvision);
        usbvision_register_video(usbvision);
 
-       usbvision_create_sysfs(usbvision->vdev);
+       usbvision_create_sysfs(&usbvision->vdev);
 
        PDEBUG(DBG_PROBE, "success");
        return 0;
+
+err_pkt:
+       usbvision_release(usbvision);
+err_usb:
+       usb_put_dev(dev);
+       return ret;
 }
 
 
index 77aeb1ed9a81e314ecd1f495adfce5499634b05c..140a1f67566eb022d4cf8d1db6835bebbe6899eb 100644 (file)
@@ -357,8 +357,8 @@ extern struct usb_device_id usbvision_table[];
 
 struct usb_usbvision {
        struct v4l2_device v4l2_dev;
-       struct video_device *vdev;                                      /* Video Device */
-       struct video_device *rdev;                                      /* Radio Device */
+       struct video_device vdev;                                       /* Video Device */
+       struct video_device rdev;                                       /* Radio Device */
 
        /* i2c Declaration Section*/
        struct i2c_adapter i2c_adap;
index cf27006c29dc334e106b5c031bb15b2a4153a162..5970dd6a1c1cf491fe7ff64dbc6aedcfb957c55f 100644 (file)
@@ -1669,10 +1669,6 @@ static void uvc_delete(struct uvc_device *dev)
 #ifdef CONFIG_MEDIA_CONTROLLER
                uvc_mc_cleanup_entity(entity);
 #endif
-               if (entity->vdev) {
-                       video_device_release(entity->vdev);
-                       entity->vdev = NULL;
-               }
                kfree(entity);
        }
 
@@ -1717,11 +1713,10 @@ static void uvc_unregister_video(struct uvc_device *dev)
        atomic_inc(&dev->nstreams);
 
        list_for_each_entry(stream, &dev->streams, list) {
-               if (stream->vdev == NULL)
+               if (!video_is_registered(&stream->vdev))
                        continue;
 
-               video_unregister_device(stream->vdev);
-               stream->vdev = NULL;
+               video_unregister_device(&stream->vdev);
 
                uvc_debugfs_cleanup_stream(stream);
        }
@@ -1736,7 +1731,7 @@ static void uvc_unregister_video(struct uvc_device *dev)
 static int uvc_register_video(struct uvc_device *dev,
                struct uvc_streaming *stream)
 {
-       struct video_device *vdev;
+       struct video_device *vdev = &stream->vdev;
        int ret;
 
        /* Initialize the video buffers queue. */
@@ -1757,12 +1752,6 @@ static int uvc_register_video(struct uvc_device *dev,
        uvc_debugfs_init_stream(stream);
 
        /* Register the device with V4L. */
-       vdev = video_device_alloc();
-       if (vdev == NULL) {
-               uvc_printk(KERN_ERR, "Failed to allocate video device (%d).\n",
-                          ret);
-               return -ENOMEM;
-       }
 
        /* We already hold a reference to dev->udev. The video device will be
         * unregistered before the reference is released, so we don't need to
@@ -1780,15 +1769,12 @@ static int uvc_register_video(struct uvc_device *dev,
        /* Set the driver data before calling video_register_device, otherwise
         * uvc_v4l2_open might race us.
         */
-       stream->vdev = vdev;
        video_set_drvdata(vdev, stream);
 
        ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
        if (ret < 0) {
                uvc_printk(KERN_ERR, "Failed to register video device (%d).\n",
                           ret);
-               stream->vdev = NULL;
-               video_device_release(vdev);
                return ret;
        }
 
@@ -1827,7 +1813,7 @@ static int uvc_register_terms(struct uvc_device *dev,
                if (ret < 0)
                        return ret;
 
-               term->vdev = stream->vdev;
+               term->vdev = &stream->vdev;
        }
 
        return 0;
@@ -2461,6 +2447,14 @@ static struct usb_device_id uvc_ids[] = {
          .bInterfaceProtocol   = 0,
          .driver_info          = UVC_QUIRK_PROBE_MINMAX
                                | UVC_QUIRK_PROBE_EXTRAFIELDS },
+       /* Aveo Technology USB 2.0 Camera (Tasco USB Microscope) */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x1871,
+         .idProduct            = 0x0516,
+         .bInterfaceClass      = USB_CLASS_VENDOR_SPEC,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0 },
        /* Ecamm Pico iMage */
        { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
                                | USB_DEVICE_ID_MATCH_INT_INFO,
index 10c554e7655c6648bdc622c2095bce7fbca59158..87a19f33e4605de8d7d5fc2f6cf6b2e3c1d4eb70 100644 (file)
@@ -306,25 +306,14 @@ int uvc_queue_streamoff(struct uvc_video_queue *queue, enum v4l2_buf_type type)
 
 int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
 {
-       int ret;
-
-       mutex_lock(&queue->mutex);
-       ret = vb2_mmap(&queue->queue, vma);
-       mutex_unlock(&queue->mutex);
-
-       return ret;
+       return vb2_mmap(&queue->queue, vma);
 }
 
 #ifndef CONFIG_MMU
 unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue,
                unsigned long pgoff)
 {
-       unsigned long ret;
-
-       mutex_lock(&queue->mutex);
-       ret = vb2_get_unmapped_area(&queue->queue, 0, 0, pgoff, 0);
-       mutex_unlock(&queue->mutex);
-       return ret;
+       return vb2_get_unmapped_area(&queue->queue, 0, 0, pgoff, 0);
 }
 #endif
 
index 43e953f73e020ace3ba15567a0778e728ce5bb80..c4b1ac6750d8d6fb8516ce2f8dcdd06ff629b311 100644 (file)
@@ -511,7 +511,7 @@ static int uvc_v4l2_open(struct file *file)
        stream->dev->users++;
        mutex_unlock(&stream->dev->lock);
 
-       v4l2_fh_init(&handle->vfh, stream->vdev);
+       v4l2_fh_init(&handle->vfh, &stream->vdev);
        v4l2_fh_add(&handle->vfh);
        handle->chain = stream->chain;
        handle->stream = stream;
@@ -882,6 +882,35 @@ static int uvc_ioctl_queryctrl(struct file *file, void *fh,
        return uvc_query_v4l2_ctrl(chain, qc);
 }
 
+static int uvc_ioctl_query_ext_ctrl(struct file *file, void *fh,
+                                   struct v4l2_query_ext_ctrl *qec)
+{
+       struct uvc_fh *handle = fh;
+       struct uvc_video_chain *chain = handle->chain;
+       struct v4l2_queryctrl qc = { qec->id };
+       int ret;
+
+       ret = uvc_query_v4l2_ctrl(chain, &qc);
+       if (ret)
+               return ret;
+
+       qec->id = qc.id;
+       qec->type = qc.type;
+       strlcpy(qec->name, qc.name, sizeof(qec->name));
+       qec->minimum = qc.minimum;
+       qec->maximum = qc.maximum;
+       qec->step = qc.step;
+       qec->default_value = qc.default_value;
+       qec->flags = qc.flags;
+       qec->elem_size = 4;
+       qec->elems = 1;
+       qec->nr_of_dims = 0;
+       memset(qec->dims, 0, sizeof(qec->dims));
+       memset(qec->reserved, 0, sizeof(qec->reserved));
+
+       return 0;
+}
+
 static int uvc_ioctl_g_ctrl(struct file *file, void *fh,
                            struct v4l2_control *ctrl)
 {
@@ -1018,26 +1047,37 @@ static int uvc_ioctl_querymenu(struct file *file, void *fh,
        return uvc_query_v4l2_menu(chain, qm);
 }
 
-static int uvc_ioctl_cropcap(struct file *file, void *fh,
-                            struct v4l2_cropcap *ccap)
+static int uvc_ioctl_g_selection(struct file *file, void *fh,
+                                struct v4l2_selection *sel)
 {
        struct uvc_fh *handle = fh;
        struct uvc_streaming *stream = handle->stream;
 
-       if (ccap->type != stream->type)
+       if (sel->type != stream->type)
                return -EINVAL;
 
-       ccap->bounds.left = 0;
-       ccap->bounds.top = 0;
+       switch (sel->target) {
+       case V4L2_SEL_TGT_CROP_DEFAULT:
+       case V4L2_SEL_TGT_CROP_BOUNDS:
+               if (stream->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+                       return -EINVAL;
+               break;
+       case V4L2_SEL_TGT_COMPOSE_DEFAULT:
+       case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+               if (stream->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+                       return -EINVAL;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       sel->r.left = 0;
+       sel->r.top = 0;
        mutex_lock(&stream->mutex);
-       ccap->bounds.width = stream->cur_frame->wWidth;
-       ccap->bounds.height = stream->cur_frame->wHeight;
+       sel->r.width = stream->cur_frame->wWidth;
+       sel->r.height = stream->cur_frame->wHeight;
        mutex_unlock(&stream->mutex);
 
-       ccap->defrect = ccap->bounds;
-
-       ccap->pixelaspect.numerator = 1;
-       ccap->pixelaspect.denominator = 1;
        return 0;
 }
 
@@ -1133,6 +1173,9 @@ static int uvc_ioctl_enum_frameintervals(struct file *file, void *fh,
                uvc_simplify_fraction(&fival->discrete.numerator,
                        &fival->discrete.denominator, 8, 333);
        } else {
+               if (fival->index)
+                       return -EINVAL;
+
                fival->type = V4L2_FRMIVAL_TYPE_STEPWISE;
                fival->stepwise.min.numerator = frame->dwFrameInterval[0];
                fival->stepwise.min.denominator = 10000000;
@@ -1443,13 +1486,14 @@ const struct v4l2_ioctl_ops uvc_ioctl_ops = {
        .vidioc_g_input = uvc_ioctl_g_input,
        .vidioc_s_input = uvc_ioctl_s_input,
        .vidioc_queryctrl = uvc_ioctl_queryctrl,
+       .vidioc_query_ext_ctrl = uvc_ioctl_query_ext_ctrl,
        .vidioc_g_ctrl = uvc_ioctl_g_ctrl,
        .vidioc_s_ctrl = uvc_ioctl_s_ctrl,
        .vidioc_g_ext_ctrls = uvc_ioctl_g_ext_ctrls,
        .vidioc_s_ext_ctrls = uvc_ioctl_s_ext_ctrls,
        .vidioc_try_ext_ctrls = uvc_ioctl_try_ext_ctrls,
        .vidioc_querymenu = uvc_ioctl_querymenu,
-       .vidioc_cropcap = uvc_ioctl_cropcap,
+       .vidioc_g_selection = uvc_ioctl_g_selection,
        .vidioc_g_parm = uvc_ioctl_g_parm,
        .vidioc_s_parm = uvc_ioctl_s_parm,
        .vidioc_enum_framesizes = uvc_ioctl_enum_framesizes,
index c63e5b55e1431b3eeffa954e32c7eb273e6845a5..1b594c2039927e9815ab26c5a047c2265c35fa59 100644 (file)
@@ -443,7 +443,7 @@ struct uvc_stats_stream {
 struct uvc_streaming {
        struct list_head list;
        struct uvc_device *dev;
-       struct video_device *vdev;
+       struct video_device vdev;
        struct uvc_video_chain *chain;
        atomic_t active;
 
index 559f8372e2eb3d9bfc021da1196582d3f438ba21..abdcffabcb5977ed6fd789b1fcdfa891affb4355 100644 (file)
@@ -134,6 +134,9 @@ struct tuner {
        unsigned int        type; /* chip type id */
        void                *config;
        const char          *name;
+#if defined(CONFIG_MEDIA_CONTROLLER)
+       struct media_pad        pad;
+#endif
 };
 
 /*
@@ -434,6 +437,10 @@ static void set_type(struct i2c_client *c, unsigned int type,
                t->name = analog_ops->info.name;
        }
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+       t->sd.entity.name = t->name;
+#endif
+
        tuner_dbg("type set to %s\n", t->name);
 
        t->mode_mask = new_mode_mask;
@@ -592,6 +599,9 @@ static int tuner_probe(struct i2c_client *client,
        struct tuner *t;
        struct tuner *radio;
        struct tuner *tv;
+#ifdef CONFIG_MEDIA_CONTROLLER
+       int ret;
+#endif
 
        t = kzalloc(sizeof(struct tuner), GFP_KERNEL);
        if (NULL == t)
@@ -684,6 +694,18 @@ static int tuner_probe(struct i2c_client *client,
 
        /* Should be just before return */
 register_client:
+#if defined(CONFIG_MEDIA_CONTROLLER)
+       t->pad.flags = MEDIA_PAD_FL_SOURCE;
+       t->sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV_TUNER;
+       t->sd.entity.name = t->name;
+
+       ret = media_entity_init(&t->sd.entity, 1, &t->pad, 0);
+       if (ret < 0) {
+               tuner_err("failed to initialize media entity!\n");
+               kfree(t);
+               return -ENODEV;
+       }
+#endif
        /* Sets a default mode */
        if (t->mode_mask & T_ANALOG_TV)
                t->mode = V4L2_TUNER_ANALOG_TV;
index e18cc0469cf8271fcaccae98a4cb676cfa12c200..34e416a554f64294e31c5e8c3f967cf94672b7ac 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <linux/atomic.h>
+#include <linux/clk.h>
 #include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/list.h>
 static DEFINE_MUTEX(clk_lock);
 static LIST_HEAD(clk_list);
 
-static struct v4l2_clk *v4l2_clk_find(const char *dev_id, const char *id)
+static struct v4l2_clk *v4l2_clk_find(const char *dev_id)
 {
        struct v4l2_clk *clk;
 
-       list_for_each_entry(clk, &clk_list, list) {
-               if (strcmp(dev_id, clk->dev_id))
-                       continue;
-
-               if (!id || !clk->id || !strcmp(clk->id, id))
+       list_for_each_entry(clk, &clk_list, list)
+               if (!strcmp(dev_id, clk->dev_id))
                        return clk;
-       }
 
        return ERR_PTR(-ENODEV);
 }
@@ -41,9 +38,24 @@ static struct v4l2_clk *v4l2_clk_find(const char *dev_id, const char *id)
 struct v4l2_clk *v4l2_clk_get(struct device *dev, const char *id)
 {
        struct v4l2_clk *clk;
+       struct clk *ccf_clk = clk_get(dev, id);
+
+       if (PTR_ERR(ccf_clk) == -EPROBE_DEFER)
+               return ERR_PTR(-EPROBE_DEFER);
+
+       if (!IS_ERR_OR_NULL(ccf_clk)) {
+               clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+               if (!clk) {
+                       clk_put(ccf_clk);
+                       return ERR_PTR(-ENOMEM);
+               }
+               clk->clk = ccf_clk;
+
+               return clk;
+       }
 
        mutex_lock(&clk_lock);
-       clk = v4l2_clk_find(dev_name(dev), id);
+       clk = v4l2_clk_find(dev_name(dev));
 
        if (!IS_ERR(clk))
                atomic_inc(&clk->use_count);
@@ -60,6 +72,12 @@ void v4l2_clk_put(struct v4l2_clk *clk)
        if (IS_ERR(clk))
                return;
 
+       if (clk->clk) {
+               clk_put(clk->clk);
+               kfree(clk);
+               return;
+       }
+
        mutex_lock(&clk_lock);
 
        list_for_each_entry(tmp, &clk_list, list)
@@ -97,8 +115,12 @@ static void v4l2_clk_unlock_driver(struct v4l2_clk *clk)
 
 int v4l2_clk_enable(struct v4l2_clk *clk)
 {
-       int ret = v4l2_clk_lock_driver(clk);
+       int ret;
+
+       if (clk->clk)
+               return clk_prepare_enable(clk->clk);
 
+       ret = v4l2_clk_lock_driver(clk);
        if (ret < 0)
                return ret;
 
@@ -124,11 +146,14 @@ void v4l2_clk_disable(struct v4l2_clk *clk)
 {
        int enable;
 
+       if (clk->clk)
+               return clk_disable_unprepare(clk->clk);
+
        mutex_lock(&clk->lock);
 
        enable = --clk->enable;
-       if (WARN(enable < 0, "Unbalanced %s() on %s:%s!\n", __func__,
-                clk->dev_id, clk->id))
+       if (WARN(enable < 0, "Unbalanced %s() on %s!\n", __func__,
+                clk->dev_id))
                clk->enable++;
        else if (!enable && clk->ops->disable)
                clk->ops->disable(clk);
@@ -141,8 +166,12 @@ EXPORT_SYMBOL(v4l2_clk_disable);
 
 unsigned long v4l2_clk_get_rate(struct v4l2_clk *clk)
 {
-       int ret = v4l2_clk_lock_driver(clk);
+       int ret;
+
+       if (clk->clk)
+               return clk_get_rate(clk->clk);
 
+       ret = v4l2_clk_lock_driver(clk);
        if (ret < 0)
                return ret;
 
@@ -161,7 +190,16 @@ EXPORT_SYMBOL(v4l2_clk_get_rate);
 
 int v4l2_clk_set_rate(struct v4l2_clk *clk, unsigned long rate)
 {
-       int ret = v4l2_clk_lock_driver(clk);
+       int ret;
+
+       if (clk->clk) {
+               long r = clk_round_rate(clk->clk, rate);
+               if (r < 0)
+                       return r;
+               return clk_set_rate(clk->clk, r);
+       }
+
+       ret = v4l2_clk_lock_driver(clk);
 
        if (ret < 0)
                return ret;
@@ -181,7 +219,7 @@ EXPORT_SYMBOL(v4l2_clk_set_rate);
 
 struct v4l2_clk *v4l2_clk_register(const struct v4l2_clk_ops *ops,
                                   const char *dev_id,
-                                  const char *id, void *priv)
+                                  void *priv)
 {
        struct v4l2_clk *clk;
        int ret;
@@ -193,9 +231,8 @@ struct v4l2_clk *v4l2_clk_register(const struct v4l2_clk_ops *ops,
        if (!clk)
                return ERR_PTR(-ENOMEM);
 
-       clk->id = kstrdup(id, GFP_KERNEL);
        clk->dev_id = kstrdup(dev_id, GFP_KERNEL);
-       if ((id && !clk->id) || !clk->dev_id) {
+       if (!clk->dev_id) {
                ret = -ENOMEM;
                goto ealloc;
        }
@@ -205,7 +242,7 @@ struct v4l2_clk *v4l2_clk_register(const struct v4l2_clk_ops *ops,
        mutex_init(&clk->lock);
 
        mutex_lock(&clk_lock);
-       if (!IS_ERR(v4l2_clk_find(dev_id, id))) {
+       if (!IS_ERR(v4l2_clk_find(dev_id))) {
                mutex_unlock(&clk_lock);
                ret = -EEXIST;
                goto eexist;
@@ -217,7 +254,6 @@ struct v4l2_clk *v4l2_clk_register(const struct v4l2_clk_ops *ops,
 
 eexist:
 ealloc:
-       kfree(clk->id);
        kfree(clk->dev_id);
        kfree(clk);
        return ERR_PTR(ret);
@@ -227,15 +263,14 @@ EXPORT_SYMBOL(v4l2_clk_register);
 void v4l2_clk_unregister(struct v4l2_clk *clk)
 {
        if (WARN(atomic_read(&clk->use_count),
-                "%s(): Refusing to unregister ref-counted %s:%s clock!\n",
-                __func__, clk->dev_id, clk->id))
+                "%s(): Refusing to unregister ref-counted %s clock!\n",
+                __func__, clk->dev_id))
                return;
 
        mutex_lock(&clk_lock);
        list_del(&clk->list);
        mutex_unlock(&clk_lock);
 
-       kfree(clk->id);
        kfree(clk->dev_id);
        kfree(clk);
 }
@@ -253,7 +288,7 @@ static unsigned long fixed_get_rate(struct v4l2_clk *clk)
 }
 
 struct v4l2_clk *__v4l2_clk_register_fixed(const char *dev_id,
-               const char *id, unsigned long rate, struct module *owner)
+                               unsigned long rate, struct module *owner)
 {
        struct v4l2_clk *clk;
        struct v4l2_clk_fixed *priv = kzalloc(sizeof(*priv), GFP_KERNEL);
@@ -265,7 +300,7 @@ struct v4l2_clk *__v4l2_clk_register_fixed(const char *dev_id,
        priv->ops.get_rate = fixed_get_rate;
        priv->ops.owner = owner;
 
-       clk = v4l2_clk_register(&priv->ops, dev_id, id, priv);
+       clk = v4l2_clk_register(&priv->ops, dev_id, priv);
        if (IS_ERR(clk))
                kfree(priv);
 
index 45c5b47106012db96ca667fd74303fdd677dafe1..e3a3468002e6950798eaac3a9a978d5cd39c6903 100644 (file)
@@ -991,7 +991,8 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
        case V4L2_CID_AUTO_FOCUS_START:
        case V4L2_CID_AUTO_FOCUS_STOP:
                *type = V4L2_CTRL_TYPE_BUTTON;
-               *flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
+               *flags |= V4L2_CTRL_FLAG_WRITE_ONLY |
+                         V4L2_CTRL_FLAG_EXECUTE_ON_WRITE;
                *min = *max = *step = *def = 0;
                break;
        case V4L2_CID_POWER_LINE_FREQUENCY:
@@ -1172,7 +1173,8 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
        case V4L2_CID_FOCUS_RELATIVE:
        case V4L2_CID_IRIS_RELATIVE:
        case V4L2_CID_ZOOM_RELATIVE:
-               *flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
+               *flags |= V4L2_CTRL_FLAG_WRITE_ONLY |
+                         V4L2_CTRL_FLAG_EXECUTE_ON_WRITE;
                break;
        case V4L2_CID_FLASH_STROBE_STATUS:
        case V4L2_CID_AUTO_FOCUS_STATUS:
@@ -1609,6 +1611,19 @@ static int cluster_changed(struct v4l2_ctrl *master)
 
                if (ctrl == NULL)
                        continue;
+
+               if (ctrl->flags & V4L2_CTRL_FLAG_EXECUTE_ON_WRITE)
+                       changed = ctrl_changed = true;
+
+               /*
+                * Set has_changed to false to avoid generating
+                * the event V4L2_EVENT_CTRL_CH_VALUE
+                */
+               if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE) {
+                       ctrl->has_changed = false;
+                       continue;
+               }
+
                for (idx = 0; !ctrl_changed && idx < ctrl->elems; idx++)
                        ctrl_changed = !ctrl->type_ops->equal(ctrl, idx,
                                ctrl->p_cur, ctrl->p_new);
@@ -1974,7 +1989,8 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
 
        sz_extra = 0;
        if (type == V4L2_CTRL_TYPE_BUTTON)
-               flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
+               flags |= V4L2_CTRL_FLAG_WRITE_ONLY |
+                       V4L2_CTRL_FLAG_EXECUTE_ON_WRITE;
        else if (type == V4L2_CTRL_TYPE_CTRL_CLASS)
                flags |= V4L2_CTRL_FLAG_READ_ONLY;
        else if (type == V4L2_CTRL_TYPE_INTEGER64 ||
index 86bb93fd7db8bd3bd08a630fe379ffe5543abef0..71a1b93b079071b560370bca7cbcf9cdd1d3c820 100644 (file)
@@ -357,34 +357,6 @@ static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                        ret = vdev->fops->unlocked_ioctl(filp, cmd, arg);
                if (lock)
                        mutex_unlock(lock);
-       } else if (vdev->fops->ioctl) {
-               /* This code path is a replacement for the BKL. It is a major
-                * hack but it will have to do for those drivers that are not
-                * yet converted to use unlocked_ioctl.
-                *
-                * All drivers implement struct v4l2_device, so we use the
-                * lock defined there to serialize the ioctls.
-                *
-                * However, if the driver sleeps, then it blocks all ioctls
-                * since the lock is still held. This is very common for
-                * VIDIOC_DQBUF since that normally waits for a frame to arrive.
-                * As a result any other ioctl calls will proceed very, very
-                * slowly since each call will have to wait for the VIDIOC_QBUF
-                * to finish. Things that should take 0.01s may now take 10-20
-                * seconds.
-                *
-                * The workaround is to *not* take the lock for VIDIOC_DQBUF.
-                * This actually works OK for videobuf-based drivers, since
-                * videobuf will take its own internal lock.
-                */
-               struct mutex *m = &vdev->v4l2_dev->ioctl_lock;
-
-               if (cmd != VIDIOC_DQBUF && mutex_lock_interruptible(m))
-                       return -ERESTARTSYS;
-               if (video_is_registered(vdev))
-                       ret = vdev->fops->ioctl(filp, cmd, arg);
-               if (cmd != VIDIOC_DQBUF)
-                       mutex_unlock(m);
        } else
                ret = -ENOTTY;
 
@@ -560,10 +532,9 @@ static void determine_valid_ioctls(struct video_device *vdev)
        /* vfl_type and vfl_dir independent ioctls */
 
        SET_VALID_IOCTL(ops, VIDIOC_QUERYCAP, vidioc_querycap);
-       if (ops->vidioc_g_priority)
-               set_bit(_IOC_NR(VIDIOC_G_PRIORITY), valid_ioctls);
-       if (ops->vidioc_s_priority)
-               set_bit(_IOC_NR(VIDIOC_S_PRIORITY), valid_ioctls);
+       set_bit(_IOC_NR(VIDIOC_G_PRIORITY), valid_ioctls);
+       set_bit(_IOC_NR(VIDIOC_S_PRIORITY), valid_ioctls);
+
        /* Note: the control handler can also be passed through the filehandle,
           and that can't be tested here. If the bit for these control ioctls
           is set, then the ioctl is valid. But if it is 0, then it can still
@@ -640,6 +611,14 @@ static void determine_valid_ioctls(struct video_device *vdev)
                SET_VALID_IOCTL(ops, VIDIOC_TRY_DECODER_CMD, vidioc_try_decoder_cmd);
                SET_VALID_IOCTL(ops, VIDIOC_ENUM_FRAMESIZES, vidioc_enum_framesizes);
                SET_VALID_IOCTL(ops, VIDIOC_ENUM_FRAMEINTERVALS, vidioc_enum_frameintervals);
+               if (ops->vidioc_g_crop || ops->vidioc_g_selection)
+                       set_bit(_IOC_NR(VIDIOC_G_CROP), valid_ioctls);
+               if (ops->vidioc_s_crop || ops->vidioc_s_selection)
+                       set_bit(_IOC_NR(VIDIOC_S_CROP), valid_ioctls);
+               SET_VALID_IOCTL(ops, VIDIOC_G_SELECTION, vidioc_g_selection);
+               SET_VALID_IOCTL(ops, VIDIOC_S_SELECTION, vidioc_s_selection);
+               if (ops->vidioc_cropcap || ops->vidioc_g_selection)
+                       set_bit(_IOC_NR(VIDIOC_CROPCAP), valid_ioctls);
        } else if (is_vbi) {
                /* vbi specific ioctls */
                if ((is_rx && (ops->vidioc_g_fmt_vbi_cap ||
@@ -708,14 +687,6 @@ static void determine_valid_ioctls(struct video_device *vdev)
                        SET_VALID_IOCTL(ops, VIDIOC_G_AUDOUT, vidioc_g_audout);
                        SET_VALID_IOCTL(ops, VIDIOC_S_AUDOUT, vidioc_s_audout);
                }
-               if (ops->vidioc_g_crop || ops->vidioc_g_selection)
-                       set_bit(_IOC_NR(VIDIOC_G_CROP), valid_ioctls);
-               if (ops->vidioc_s_crop || ops->vidioc_s_selection)
-                       set_bit(_IOC_NR(VIDIOC_S_CROP), valid_ioctls);
-               SET_VALID_IOCTL(ops, VIDIOC_G_SELECTION, vidioc_g_selection);
-               SET_VALID_IOCTL(ops, VIDIOC_S_SELECTION, vidioc_s_selection);
-               if (ops->vidioc_cropcap || ops->vidioc_g_selection)
-                       set_bit(_IOC_NR(VIDIOC_CROPCAP), valid_ioctls);
                if (ops->vidioc_g_parm || (vdev->vfl_type == VFL_TYPE_GRABBER &&
                                        ops->vidioc_g_std))
                        set_bit(_IOC_NR(VIDIOC_G_PARM), valid_ioctls);
@@ -943,8 +914,8 @@ int __video_register_device(struct video_device *vdev, int type, int nr,
            vdev->vfl_type != VFL_TYPE_SUBDEV) {
                vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L;
                vdev->entity.name = vdev->name;
-               vdev->entity.info.v4l.major = VIDEO_MAJOR;
-               vdev->entity.info.v4l.minor = vdev->minor;
+               vdev->entity.info.dev.major = VIDEO_MAJOR;
+               vdev->entity.info.dev.minor = vdev->minor;
                ret = media_device_register_entity(vdev->v4l2_dev->mdev,
                        &vdev->entity);
                if (ret < 0)
index 015f92aab44a85b602c0ae58b3632fe7661015cf..5b0a30b9252be2a205fcef2feecaf6fd1f3e57f6 100644 (file)
@@ -37,7 +37,6 @@ int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev)
 
        INIT_LIST_HEAD(&v4l2_dev->subdevs);
        spin_lock_init(&v4l2_dev->lock);
-       mutex_init(&v4l2_dev->ioctl_lock);
        v4l2_prio_init(&v4l2_dev->prio);
        kref_init(&v4l2_dev->ref);
        get_device(dev);
@@ -248,8 +247,8 @@ int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev)
                        goto clean_up;
                }
 #if defined(CONFIG_MEDIA_CONTROLLER)
-               sd->entity.info.v4l.major = VIDEO_MAJOR;
-               sd->entity.info.v4l.minor = vdev->minor;
+               sd->entity.info.dev.major = VIDEO_MAJOR;
+               sd->entity.info.dev.minor = vdev->minor;
 #endif
                sd->devnode = vdev;
        }
index b1d8dbb39665eab512f8dd59abdfac63fbed43e2..c0e96382feba11ec0f982b7fd8861e3581c35120 100644 (file)
@@ -282,7 +282,7 @@ void v4l2_print_dv_timings(const char *dev_prefix, const char *prefix,
                        (bt->polarities & V4L2_DV_VSYNC_POS_POL) ? "+" : "-",
                        bt->vsync, bt->vbackporch);
        pr_info("%s: pixelclock: %llu\n", dev_prefix, bt->pixelclock);
-       pr_info("%s: flags (0x%x):%s%s%s%s\n", dev_prefix, bt->flags,
+       pr_info("%s: flags (0x%x):%s%s%s%s%s\n", dev_prefix, bt->flags,
                        (bt->flags & V4L2_DV_FL_REDUCED_BLANKING) ?
                        " REDUCED_BLANKING" : "",
                        (bt->flags & V4L2_DV_FL_CAN_REDUCE_FPS) ?
@@ -290,7 +290,9 @@ void v4l2_print_dv_timings(const char *dev_prefix, const char *prefix,
                        (bt->flags & V4L2_DV_FL_REDUCED_FPS) ?
                        " REDUCED_FPS" : "",
                        (bt->flags & V4L2_DV_FL_HALF_LINE) ?
-                       " HALF_LINE" : "");
+                       " HALF_LINE" : "",
+                       (bt->flags & V4L2_DV_FL_IS_CE_VIDEO) ?
+                       " CE_VIDEO" : "");
        pr_info("%s: standards (0x%x):%s%s%s%s\n", dev_prefix, bt->standards,
                        (bt->standards & V4L2_DV_BT_STD_CEA861) ?  " CEA" : "",
                        (bt->standards & V4L2_DV_BT_STD_DMT) ?  " DMT" : "",
index b08407225db14ec7723f89dcecbb4bea722de6f1..aa407cb5f830c03965ca1a26e3850813e0767858 100644 (file)
@@ -257,7 +257,7 @@ static void v4l_print_format(const void *arg, bool write_only)
                pr_cont(", width=%u, height=%u, "
                        "pixelformat=%c%c%c%c, field=%s, "
                        "bytesperline=%u, sizeimage=%u, colorspace=%d, "
-                       "flags %x, ycbcr_enc=%u, quantization=%u\n",
+                       "flags=0x%x, ycbcr_enc=%u, quantization=%u\n",
                        pix->width, pix->height,
                        (pix->pixelformat & 0xff),
                        (pix->pixelformat >>  8) & 0xff,
@@ -273,7 +273,7 @@ static void v4l_print_format(const void *arg, bool write_only)
                mp = &p->fmt.pix_mp;
                pr_cont(", width=%u, height=%u, "
                        "format=%c%c%c%c, field=%s, "
-                       "colorspace=%d, num_planes=%u, flags=%x, "
+                       "colorspace=%d, num_planes=%u, flags=0x%x, "
                        "ycbcr_enc=%u, quantization=%u\n",
                        mp->width, mp->height,
                        (mp->pixelformat & 0xff),
@@ -901,6 +901,8 @@ static int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv)
         */
        if (!allow_priv && c->ctrl_class == V4L2_CID_PRIVATE_BASE)
                return 0;
+       if (c->ctrl_class == 0)
+               return 1;
        /* Check that all controls are from the same control class. */
        for (i = 0; i < c->count; i++) {
                if (V4L2_CTRL_ID2CLASS(c->controls[i].id) != c->ctrl_class) {
@@ -1046,8 +1048,6 @@ static int v4l_g_priority(const struct v4l2_ioctl_ops *ops,
        struct video_device *vfd;
        u32 *p = arg;
 
-       if (ops->vidioc_g_priority)
-               return ops->vidioc_g_priority(file, fh, arg);
        vfd = video_devdata(file);
        *p = v4l2_prio_max(vfd->prio);
        return 0;
@@ -1060,9 +1060,9 @@ static int v4l_s_priority(const struct v4l2_ioctl_ops *ops,
        struct v4l2_fh *vfh;
        u32 *p = arg;
 
-       if (ops->vidioc_s_priority)
-               return ops->vidioc_s_priority(file, fh, *p);
        vfd = video_devdata(file);
+       if (!test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags))
+               return -ENOTTY;
        vfh = file->private_data;
        return v4l2_prio_change(vfd->prio, &vfh->prio, *p);
 }
index 80c588f4e4290643b98674de129e31d0c164f257..73824a5ada83788fff9b143b36cf0eff5cec24bc 100644 (file)
@@ -97,7 +97,7 @@ EXPORT_SYMBOL(v4l2_m2m_get_vq);
  */
 void *v4l2_m2m_next_buf(struct v4l2_m2m_queue_ctx *q_ctx)
 {
-       struct v4l2_m2m_buffer *b = NULL;
+       struct v4l2_m2m_buffer *b;
        unsigned long flags;
 
        spin_lock_irqsave(&q_ctx->rdy_spinlock, flags);
@@ -119,7 +119,7 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_next_buf);
  */
 void *v4l2_m2m_buf_remove(struct v4l2_m2m_queue_ctx *q_ctx)
 {
-       struct v4l2_m2m_buffer *b = NULL;
+       struct v4l2_m2m_buffer *b;
        unsigned long flags;
 
        spin_lock_irqsave(&q_ctx->rdy_spinlock, flags);
index b4ed9a955fbe0d779ad44b92a2780ff5d9808826..83143d39dea760d1120f6bf7d2fa309a147a2189 100644 (file)
 
 #include <media/v4l2-of.h>
 
-static void v4l2_of_parse_csi_bus(const struct device_node *node,
-                                 struct v4l2_of_endpoint *endpoint)
+static int v4l2_of_parse_csi_bus(const struct device_node *node,
+                                struct v4l2_of_endpoint *endpoint)
 {
        struct v4l2_of_bus_mipi_csi2 *bus = &endpoint->bus.mipi_csi2;
-       u32 data_lanes[ARRAY_SIZE(bus->data_lanes)];
        struct property *prop;
        bool have_clk_lane = false;
        unsigned int flags = 0;
@@ -32,16 +31,34 @@ static void v4l2_of_parse_csi_bus(const struct device_node *node,
        prop = of_find_property(node, "data-lanes", NULL);
        if (prop) {
                const __be32 *lane = NULL;
-               int i;
+               unsigned int i;
 
-               for (i = 0; i < ARRAY_SIZE(data_lanes); i++) {
-                       lane = of_prop_next_u32(prop, lane, &data_lanes[i]);
+               for (i = 0; i < ARRAY_SIZE(bus->data_lanes); i++) {
+                       lane = of_prop_next_u32(prop, lane, &v);
                        if (!lane)
                                break;
+                       bus->data_lanes[i] = v;
                }
                bus->num_data_lanes = i;
-               while (i--)
-                       bus->data_lanes[i] = data_lanes[i];
+       }
+
+       prop = of_find_property(node, "lane-polarities", NULL);
+       if (prop) {
+               const __be32 *polarity = NULL;
+               unsigned int i;
+
+               for (i = 0; i < ARRAY_SIZE(bus->lane_polarities); i++) {
+                       polarity = of_prop_next_u32(prop, polarity, &v);
+                       if (!polarity)
+                               break;
+                       bus->lane_polarities[i] = v;
+               }
+
+               if (i < 1 + bus->num_data_lanes /* clock + data */) {
+                       pr_warn("%s: too few lane-polarities entries (need %u, got %u)\n",
+                               node->full_name, 1 + bus->num_data_lanes, i);
+                       return -EINVAL;
+               }
        }
 
        if (!of_property_read_u32(node, "clock-lanes", &v)) {
@@ -56,6 +73,8 @@ static void v4l2_of_parse_csi_bus(const struct device_node *node,
 
        bus->flags = flags;
        endpoint->bus_type = V4L2_MBUS_CSI2;
+
+       return 0;
 }
 
 static void v4l2_of_parse_parallel_bus(const struct device_node *node,
@@ -127,11 +146,15 @@ static void v4l2_of_parse_parallel_bus(const struct device_node *node,
 int v4l2_of_parse_endpoint(const struct device_node *node,
                           struct v4l2_of_endpoint *endpoint)
 {
+       int rval;
+
        of_graph_parse_endpoint(node, &endpoint->base);
        endpoint->bus_type = 0;
        memset(&endpoint->bus, 0, sizeof(endpoint->bus));
 
-       v4l2_of_parse_csi_bus(node, endpoint);
+       rval = v4l2_of_parse_csi_bus(node, endpoint);
+       if (rval)
+               return rval;
        /*
         * Parse the parallel video bus properties only if none
         * of the MIPI CSI-2 specific properties were found.
@@ -142,3 +165,64 @@ int v4l2_of_parse_endpoint(const struct device_node *node,
        return 0;
 }
 EXPORT_SYMBOL(v4l2_of_parse_endpoint);
+
+/**
+ * v4l2_of_parse_link() - parse a link between two endpoints
+ * @node: pointer to the endpoint at the local end of the link
+ * @link: pointer to the V4L2 OF link data structure
+ *
+ * Fill the link structure with the local and remote nodes and port numbers.
+ * The local_node and remote_node fields are set to point to the local and
+ * remote port's parent nodes respectively (the port parent node being the
+ * parent node of the port node if that node isn't a 'ports' node, or the
+ * grand-parent node of the port node otherwise).
+ *
+ * A reference is taken to both the local and remote nodes, the caller must use
+ * v4l2_of_put_link() to drop the references when done with the link.
+ *
+ * Return: 0 on success, or -ENOLINK if the remote endpoint can't be found.
+ */
+int v4l2_of_parse_link(const struct device_node *node,
+                      struct v4l2_of_link *link)
+{
+       struct device_node *np;
+
+       memset(link, 0, sizeof(*link));
+
+       np = of_get_parent(node);
+       of_property_read_u32(np, "reg", &link->local_port);
+       np = of_get_next_parent(np);
+       if (of_node_cmp(np->name, "ports") == 0)
+               np = of_get_next_parent(np);
+       link->local_node = np;
+
+       np = of_parse_phandle(node, "remote-endpoint", 0);
+       if (!np) {
+               of_node_put(link->local_node);
+               return -ENOLINK;
+       }
+
+       np = of_get_parent(np);
+       of_property_read_u32(np, "reg", &link->remote_port);
+       np = of_get_next_parent(np);
+       if (of_node_cmp(np->name, "ports") == 0)
+               np = of_get_next_parent(np);
+       link->remote_node = np;
+
+       return 0;
+}
+EXPORT_SYMBOL(v4l2_of_parse_link);
+
+/**
+ * v4l2_of_put_link() - drop references to nodes in a link
+ * @link: pointer to the V4L2 OF link data structure
+ *
+ * Drop references to the local and remote nodes in the link. This function must
+ * be called on every link parsed with v4l2_of_parse_link().
+ */
+void v4l2_of_put_link(struct v4l2_of_link *link)
+{
+       of_node_put(link->local_node);
+       of_node_put(link->remote_node);
+}
+EXPORT_SYMBOL(v4l2_of_put_link);
index 19a034e79be4d15fdfd3a1104aff1dadc902849f..63596063b21362fe82f51a37c0c91b5f860d926d 100644 (file)
@@ -93,8 +93,7 @@ static int subdev_open(struct file *file)
 
 err:
 #if defined(CONFIG_MEDIA_CONTROLLER)
-       if (entity)
-               media_entity_put(entity);
+       media_entity_put(entity);
 #endif
        v4l2_fh_del(&subdev_fh->vfh);
        v4l2_fh_exit(&subdev_fh->vfh);
@@ -262,7 +261,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                if (rval)
                        return rval;
 
-               return v4l2_subdev_call(sd, pad, get_fmt, subdev_fh, format);
+               return v4l2_subdev_call(sd, pad, get_fmt, subdev_fh->pad, format);
        }
 
        case VIDIOC_SUBDEV_S_FMT: {
@@ -272,7 +271,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                if (rval)
                        return rval;
 
-               return v4l2_subdev_call(sd, pad, set_fmt, subdev_fh, format);
+               return v4l2_subdev_call(sd, pad, set_fmt, subdev_fh->pad, format);
        }
 
        case VIDIOC_SUBDEV_G_CROP: {
@@ -289,7 +288,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                sel.target = V4L2_SEL_TGT_CROP;
 
                rval = v4l2_subdev_call(
-                       sd, pad, get_selection, subdev_fh, &sel);
+                       sd, pad, get_selection, subdev_fh->pad, &sel);
 
                crop->rect = sel.r;
 
@@ -311,7 +310,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                sel.r = crop->rect;
 
                rval = v4l2_subdev_call(
-                       sd, pad, set_selection, subdev_fh, &sel);
+                       sd, pad, set_selection, subdev_fh->pad, &sel);
 
                crop->rect = sel.r;
 
@@ -321,20 +320,28 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        case VIDIOC_SUBDEV_ENUM_MBUS_CODE: {
                struct v4l2_subdev_mbus_code_enum *code = arg;
 
+               if (code->which != V4L2_SUBDEV_FORMAT_TRY &&
+                   code->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+                       return -EINVAL;
+
                if (code->pad >= sd->entity.num_pads)
                        return -EINVAL;
 
-               return v4l2_subdev_call(sd, pad, enum_mbus_code, subdev_fh,
+               return v4l2_subdev_call(sd, pad, enum_mbus_code, subdev_fh->pad,
                                        code);
        }
 
        case VIDIOC_SUBDEV_ENUM_FRAME_SIZE: {
                struct v4l2_subdev_frame_size_enum *fse = arg;
 
+               if (fse->which != V4L2_SUBDEV_FORMAT_TRY &&
+                   fse->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+                       return -EINVAL;
+
                if (fse->pad >= sd->entity.num_pads)
                        return -EINVAL;
 
-               return v4l2_subdev_call(sd, pad, enum_frame_size, subdev_fh,
+               return v4l2_subdev_call(sd, pad, enum_frame_size, subdev_fh->pad,
                                        fse);
        }
 
@@ -359,10 +366,14 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        case VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL: {
                struct v4l2_subdev_frame_interval_enum *fie = arg;
 
+               if (fie->which != V4L2_SUBDEV_FORMAT_TRY &&
+                   fie->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+                       return -EINVAL;
+
                if (fie->pad >= sd->entity.num_pads)
                        return -EINVAL;
 
-               return v4l2_subdev_call(sd, pad, enum_frame_interval, subdev_fh,
+               return v4l2_subdev_call(sd, pad, enum_frame_interval, subdev_fh->pad,
                                        fie);
        }
 
@@ -374,7 +385,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                        return rval;
 
                return v4l2_subdev_call(
-                       sd, pad, get_selection, subdev_fh, sel);
+                       sd, pad, get_selection, subdev_fh->pad, sel);
        }
 
        case VIDIOC_SUBDEV_S_SELECTION: {
@@ -385,7 +396,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                        return rval;
 
                return v4l2_subdev_call(
-                       sd, pad, set_selection, subdev_fh, sel);
+                       sd, pad, set_selection, subdev_fh->pad, sel);
        }
 
        case VIDIOC_G_EDID: {
index cc16e76a24933c41a9cc81ddb5b2beb0193fcbe2..66ada01c796ca934527321fe67406667c2927c9a 100644 (file)
@@ -1247,6 +1247,16 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
 {
        unsigned int plane;
 
+       if (V4L2_TYPE_IS_OUTPUT(b->type)) {
+               if (WARN_ON_ONCE(b->bytesused == 0)) {
+                       pr_warn_once("use of bytesused == 0 is deprecated and will be removed in the future,\n");
+                       if (vb->vb2_queue->allow_zero_bytesused)
+                               pr_warn_once("use VIDIOC_DECODER_CMD(V4L2_DEC_CMD_STOP) instead.\n");
+                       else
+                               pr_warn_once("use the actual size instead.\n");
+               }
+       }
+
        if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
                if (b->memory == V4L2_MEMORY_USERPTR) {
                        for (plane = 0; plane < vb->num_planes; ++plane) {
@@ -1276,13 +1286,22 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
                         * userspace clearly never bothered to set it and
                         * it's a safe assumption that they really meant to
                         * use the full plane sizes.
+                        *
+                        * Some drivers, e.g. old codec drivers, use bytesused == 0
+                        * as a way to indicate that streaming is finished.
+                        * In that case, the driver should use the
+                        * allow_zero_bytesused flag to keep old userspace
+                        * applications working.
                         */
                        for (plane = 0; plane < vb->num_planes; ++plane) {
                                struct v4l2_plane *pdst = &v4l2_planes[plane];
                                struct v4l2_plane *psrc = &b->m.planes[plane];
 
-                               pdst->bytesused = psrc->bytesused ?
-                                       psrc->bytesused : pdst->length;
+                               if (vb->vb2_queue->allow_zero_bytesused)
+                                       pdst->bytesused = psrc->bytesused;
+                               else
+                                       pdst->bytesused = psrc->bytesused ?
+                                               psrc->bytesused : pdst->length;
                                pdst->data_offset = psrc->data_offset;
                        }
                }
@@ -1295,6 +1314,11 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
                 *
                 * If bytesused == 0 for the output buffer, then fall back
                 * to the full buffer size as that's a sensible default.
+                *
+                * Some drivers, e.g. old codec drivers, use bytesused == 0 as
+                * a way to indicate that streaming is finished. In that case,
+                * the driver should use the allow_zero_bytesused flag to keep
+                * old userspace applications working.
                 */
                if (b->memory == V4L2_MEMORY_USERPTR) {
                        v4l2_planes[0].m.userptr = b->m.userptr;
@@ -1306,10 +1330,13 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
                        v4l2_planes[0].length = b->length;
                }
 
-               if (V4L2_TYPE_IS_OUTPUT(b->type))
-                       v4l2_planes[0].bytesused = b->bytesused ?
-                               b->bytesused : v4l2_planes[0].length;
-               else
+               if (V4L2_TYPE_IS_OUTPUT(b->type)) {
+                       if (vb->vb2_queue->allow_zero_bytesused)
+                               v4l2_planes[0].bytesused = b->bytesused;
+                       else
+                               v4l2_planes[0].bytesused = b->bytesused ?
+                                       b->bytesused : v4l2_planes[0].length;
+               } else
                        v4l2_planes[0].bytesused = 0;
 
        }
@@ -2760,7 +2787,8 @@ struct vb2_fileio_data {
        unsigned int initial_index;
        unsigned int q_count;
        unsigned int dq_count;
-       unsigned int flags;
+       unsigned read_once:1;
+       unsigned write_immediately:1;
 };
 
 /**
@@ -2798,14 +2826,16 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
         */
        count = 1;
 
-       dprintk(3, "setting up file io: mode %s, count %d, flags %08x\n",
-               (read) ? "read" : "write", count, q->io_flags);
+       dprintk(3, "setting up file io: mode %s, count %d, read_once %d, write_immediately %d\n",
+               (read) ? "read" : "write", count, q->fileio_read_once,
+               q->fileio_write_immediately);
 
        fileio = kzalloc(sizeof(struct vb2_fileio_data), GFP_KERNEL);
        if (fileio == NULL)
                return -ENOMEM;
 
-       fileio->flags = q->io_flags;
+       fileio->read_once = q->fileio_read_once;
+       fileio->write_immediately = q->fileio_write_immediately;
 
        /*
         * Request buffers and use MMAP type to force driver
@@ -3028,13 +3058,11 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
        /*
         * Queue next buffer if required.
         */
-       if (buf->pos == buf->size ||
-          (!read && (fileio->flags & VB2_FILEIO_WRITE_IMMEDIATELY))) {
+       if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
                /*
                 * Check if this is the last buffer to read.
                 */
-               if (read && (fileio->flags & VB2_FILEIO_READ_ONCE) &&
-                   fileio->dq_count == 1) {
+               if (read && fileio->read_once && fileio->dq_count == 1) {
                        dprintk(3, "read limit reached\n");
                        return __vb2_cleanup_fileio(q);
                }
@@ -3225,7 +3253,6 @@ EXPORT_SYMBOL_GPL(vb2_thread_start);
 int vb2_thread_stop(struct vb2_queue *q)
 {
        struct vb2_threadio_data *threadio = q->threadio;
-       struct vb2_fileio_data *fileio = q->fileio;
        int err;
 
        if (threadio == NULL)
@@ -3411,6 +3438,8 @@ ssize_t vb2_fop_write(struct file *file, const char __user *buf,
        struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
        int err = -EBUSY;
 
+       if (!(vdev->queue->io_modes & VB2_WRITE))
+               return -EINVAL;
        if (lock && mutex_lock_interruptible(lock))
                return -ERESTARTSYS;
        if (vb2_queue_is_busy(vdev, file))
@@ -3433,6 +3462,8 @@ ssize_t vb2_fop_read(struct file *file, char __user *buf,
        struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
        int err = -EBUSY;
 
+       if (!(vdev->queue->io_modes & VB2_READ))
+               return -EINVAL;
        if (lock && mutex_lock_interruptible(lock))
                return -ERESTARTSYS;
        if (vb2_queue_is_busy(vdev, file))
index 69e0483adfee02e569f89ece65a31f73c0a96f35..644dec73d2203fdffa67a035231f6fe7450278d2 100644 (file)
@@ -402,6 +402,12 @@ static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv, unsigned long flags)
 {
        struct vb2_dc_buf *buf = buf_priv;
        struct dma_buf *dbuf;
+       DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+
+       exp_info.ops = &vb2_dc_dmabuf_ops;
+       exp_info.size = buf->size;
+       exp_info.flags = flags;
+       exp_info.priv = buf;
 
        if (!buf->sgt_base)
                buf->sgt_base = vb2_dc_get_base_sgt(buf);
@@ -409,7 +415,7 @@ static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv, unsigned long flags)
        if (WARN_ON(!buf->sgt_base))
                return NULL;
 
-       dbuf = dma_buf_export(buf, &vb2_dc_dmabuf_ops, buf->size, flags, NULL);
+       dbuf = dma_buf_export(&exp_info);
        if (IS_ERR(dbuf))
                return NULL;
 
index b1838abb6d0056c38d7fefbce57b3bf2a154328b..45c708e463b93e84721e0c3a65a7a3f52aa33f92 100644 (file)
@@ -583,11 +583,17 @@ static struct dma_buf *vb2_dma_sg_get_dmabuf(void *buf_priv, unsigned long flags
 {
        struct vb2_dma_sg_buf *buf = buf_priv;
        struct dma_buf *dbuf;
+       DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+
+       exp_info.ops = &vb2_dma_sg_dmabuf_ops;
+       exp_info.size = buf->size;
+       exp_info.flags = flags;
+       exp_info.priv = buf;
 
        if (WARN_ON(!buf->dma_sgt))
                return NULL;
 
-       dbuf = dma_buf_export(buf, &vb2_dma_sg_dmabuf_ops, buf->size, flags, NULL);
+       dbuf = dma_buf_export(&exp_info);
        if (IS_ERR(dbuf))
                return NULL;
 
index bcde88572429fe1e2a5b113183cad15d8077971b..657ab302a5cf457549e151e603b3cc60e5f90be1 100644 (file)
@@ -368,11 +368,17 @@ static struct dma_buf *vb2_vmalloc_get_dmabuf(void *buf_priv, unsigned long flag
 {
        struct vb2_vmalloc_buf *buf = buf_priv;
        struct dma_buf *dbuf;
+       DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+
+       exp_info.ops = &vb2_vmalloc_dmabuf_ops;
+       exp_info.size = buf->size;
+       exp_info.flags = flags;
+       exp_info.priv = buf;
 
        if (WARN_ON(!buf->vaddr))
                return NULL;
 
-       dbuf = dma_buf_export(buf, &vb2_vmalloc_dmabuf_ops, buf->size, flags, NULL);
+       dbuf = dma_buf_export(&exp_info);
        if (IS_ERR(dbuf))
                return NULL;
 
index 191383d8c94d6e1d8e6d67bfc3e0ec5494b1d323..868036f70f8f126c0e81e16fe8bd4af63319909a 100644 (file)
@@ -83,6 +83,15 @@ config FSL_IFC
        bool
        depends on FSL_SOC
 
+config JZ4780_NEMC
+       bool "Ingenic JZ4780 SoC NEMC driver"
+       default y
+       depends on MACH_JZ4780
+       help
+         This driver is for the NAND/External Memory Controller (NEMC) in
+         the Ingenic JZ4780. This controller is used to handle external
+         memory devices such as NAND and SRAM.
+
 source "drivers/memory/tegra/Kconfig"
 
 endif
index 6b6548124473350a453b8982e341e4bb27264458..b670441e3cdf9a2f6816741797722e03b9d72466 100644 (file)
@@ -13,5 +13,6 @@ obj-$(CONFIG_FSL_CORENET_CF)  += fsl-corenet-cf.o
 obj-$(CONFIG_FSL_IFC)          += fsl_ifc.o
 obj-$(CONFIG_MVEBU_DEVBUS)     += mvebu-devbus.o
 obj-$(CONFIG_TEGRA20_MC)       += tegra20-mc.o
+obj-$(CONFIG_JZ4780_NEMC)      += jz4780-nemc.o
 
 obj-$(CONFIG_TEGRA_MC)         += tegra/
diff --git a/drivers/memory/jz4780-nemc.c b/drivers/memory/jz4780-nemc.c
new file mode 100644 (file)
index 0000000..919d192
--- /dev/null
@@ -0,0 +1,391 @@
+/*
+ * JZ4780 NAND/external memory controller (NEMC)
+ *
+ * Copyright (c) 2015 Imagination Technologies
+ * Author: Alex Smith <alex@alex-smith.me.uk>
+ *
+ * This program is free software; you can 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/init.h>
+#include <linux/math64.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include <linux/jz4780-nemc.h>
+
+#define NEMC_SMCRn(n)          (0x14 + (((n) - 1) * 4))
+#define NEMC_NFCSR             0x50
+
+#define NEMC_SMCR_SMT          BIT(0)
+#define NEMC_SMCR_BW_SHIFT     6
+#define NEMC_SMCR_BW_MASK      (0x3 << NEMC_SMCR_BW_SHIFT)
+#define NEMC_SMCR_BW_8         (0 << 6)
+#define NEMC_SMCR_TAS_SHIFT    8
+#define NEMC_SMCR_TAS_MASK     (0xf << NEMC_SMCR_TAS_SHIFT)
+#define NEMC_SMCR_TAH_SHIFT    12
+#define NEMC_SMCR_TAH_MASK     (0xf << NEMC_SMCR_TAH_SHIFT)
+#define NEMC_SMCR_TBP_SHIFT    16
+#define NEMC_SMCR_TBP_MASK     (0xf << NEMC_SMCR_TBP_SHIFT)
+#define NEMC_SMCR_TAW_SHIFT    20
+#define NEMC_SMCR_TAW_MASK     (0xf << NEMC_SMCR_TAW_SHIFT)
+#define NEMC_SMCR_TSTRV_SHIFT  24
+#define NEMC_SMCR_TSTRV_MASK   (0x3f << NEMC_SMCR_TSTRV_SHIFT)
+
+#define NEMC_NFCSR_NFEn(n)     BIT(((n) - 1) << 1)
+#define NEMC_NFCSR_NFCEn(n)    BIT((((n) - 1) << 1) + 1)
+#define NEMC_NFCSR_TNFEn(n)    BIT(16 + (n) - 1)
+
+struct jz4780_nemc {
+       spinlock_t lock;
+       struct device *dev;
+       void __iomem *base;
+       struct clk *clk;
+       uint32_t clk_period;
+       unsigned long banks_present;
+};
+
+/**
+ * jz4780_nemc_num_banks() - count the number of banks referenced by a device
+ * @dev: device to count banks for, must be a child of the NEMC.
+ *
+ * Return: The number of unique NEMC banks referred to by the specified NEMC
+ * child device. Unique here means that a device that references the same bank
+ * multiple times in the its "reg" property will only count once.
+ */
+unsigned int jz4780_nemc_num_banks(struct device *dev)
+{
+       const __be32 *prop;
+       unsigned int bank, count = 0;
+       unsigned long referenced = 0;
+       int i = 0;
+
+       while ((prop = of_get_address(dev->of_node, i++, NULL, NULL))) {
+               bank = of_read_number(prop, 1);
+               if (!(referenced & BIT(bank))) {
+                       referenced |= BIT(bank);
+                       count++;
+               }
+       }
+
+       return count;
+}
+EXPORT_SYMBOL(jz4780_nemc_num_banks);
+
+/**
+ * jz4780_nemc_set_type() - set the type of device connected to a bank
+ * @dev: child device of the NEMC.
+ * @bank: bank number to configure.
+ * @type: type of device connected to the bank.
+ */
+void jz4780_nemc_set_type(struct device *dev, unsigned int bank,
+                         enum jz4780_nemc_bank_type type)
+{
+       struct jz4780_nemc *nemc = dev_get_drvdata(dev->parent);
+       uint32_t nfcsr;
+
+       nfcsr = readl(nemc->base + NEMC_NFCSR);
+
+       /* TODO: Support toggle NAND devices. */
+       switch (type) {
+       case JZ4780_NEMC_BANK_SRAM:
+               nfcsr &= ~(NEMC_NFCSR_TNFEn(bank) | NEMC_NFCSR_NFEn(bank));
+               break;
+       case JZ4780_NEMC_BANK_NAND:
+               nfcsr &= ~NEMC_NFCSR_TNFEn(bank);
+               nfcsr |= NEMC_NFCSR_NFEn(bank);
+               break;
+       }
+
+       writel(nfcsr, nemc->base + NEMC_NFCSR);
+}
+EXPORT_SYMBOL(jz4780_nemc_set_type);
+
+/**
+ * jz4780_nemc_assert() - (de-)assert a NAND device's chip enable pin
+ * @dev: child device of the NEMC.
+ * @bank: bank number of device.
+ * @assert: whether the chip enable pin should be asserted.
+ *
+ * (De-)asserts the chip enable pin for the NAND device connected to the
+ * specified bank.
+ */
+void jz4780_nemc_assert(struct device *dev, unsigned int bank, bool assert)
+{
+       struct jz4780_nemc *nemc = dev_get_drvdata(dev->parent);
+       uint32_t nfcsr;
+
+       nfcsr = readl(nemc->base + NEMC_NFCSR);
+
+       if (assert)
+               nfcsr |= NEMC_NFCSR_NFCEn(bank);
+       else
+               nfcsr &= ~NEMC_NFCSR_NFCEn(bank);
+
+       writel(nfcsr, nemc->base + NEMC_NFCSR);
+}
+EXPORT_SYMBOL(jz4780_nemc_assert);
+
+static uint32_t jz4780_nemc_clk_period(struct jz4780_nemc *nemc)
+{
+       unsigned long rate;
+
+       rate = clk_get_rate(nemc->clk);
+       if (!rate)
+               return 0;
+
+       /* Return in picoseconds. */
+       return div64_ul(1000000000000ull, rate);
+}
+
+static uint32_t jz4780_nemc_ns_to_cycles(struct jz4780_nemc *nemc, uint32_t ns)
+{
+       return ((ns * 1000) + nemc->clk_period - 1) / nemc->clk_period;
+}
+
+static bool jz4780_nemc_configure_bank(struct jz4780_nemc *nemc,
+                                      unsigned int bank,
+                                      struct device_node *node)
+{
+       uint32_t smcr, val, cycles;
+
+       /*
+        * Conversion of tBP and tAW cycle counts to values supported by the
+        * hardware (round up to the next supported value).
+        */
+       static const uint32_t convert_tBP_tAW[] = {
+               0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+
+               /* 11 - 12 -> 12 cycles */
+               11, 11,
+
+               /* 13 - 15 -> 15 cycles */
+               12, 12, 12,
+
+               /* 16 - 20 -> 20 cycles */
+               13, 13, 13, 13, 13,
+
+               /* 21 - 25 -> 25 cycles */
+               14, 14, 14, 14, 14,
+
+               /* 26 - 31 -> 31 cycles */
+               15, 15, 15, 15, 15, 15
+       };
+
+       smcr = readl(nemc->base + NEMC_SMCRn(bank));
+       smcr &= ~NEMC_SMCR_SMT;
+
+       if (!of_property_read_u32(node, "ingenic,nemc-bus-width", &val)) {
+               smcr &= ~NEMC_SMCR_BW_MASK;
+               switch (val) {
+               case 8:
+                       smcr |= NEMC_SMCR_BW_8;
+                       break;
+               default:
+                       /*
+                        * Earlier SoCs support a 16 bit bus width (the 4780
+                        * does not), until those are properly supported, error.
+                        */
+                       dev_err(nemc->dev, "unsupported bus width: %u\n", val);
+                       return false;
+               }
+       }
+
+       if (of_property_read_u32(node, "ingenic,nemc-tAS", &val) == 0) {
+               smcr &= ~NEMC_SMCR_TAS_MASK;
+               cycles = jz4780_nemc_ns_to_cycles(nemc, val);
+               if (cycles > 15) {
+                       dev_err(nemc->dev, "tAS %u is too high (%u cycles)\n",
+                               val, cycles);
+                       return false;
+               }
+
+               smcr |= cycles << NEMC_SMCR_TAS_SHIFT;
+       }
+
+       if (of_property_read_u32(node, "ingenic,nemc-tAH", &val) == 0) {
+               smcr &= ~NEMC_SMCR_TAH_MASK;
+               cycles = jz4780_nemc_ns_to_cycles(nemc, val);
+               if (cycles > 15) {
+                       dev_err(nemc->dev, "tAH %u is too high (%u cycles)\n",
+                               val, cycles);
+                       return false;
+               }
+
+               smcr |= cycles << NEMC_SMCR_TAH_SHIFT;
+       }
+
+       if (of_property_read_u32(node, "ingenic,nemc-tBP", &val) == 0) {
+               smcr &= ~NEMC_SMCR_TBP_MASK;
+               cycles = jz4780_nemc_ns_to_cycles(nemc, val);
+               if (cycles > 31) {
+                       dev_err(nemc->dev, "tBP %u is too high (%u cycles)\n",
+                               val, cycles);
+                       return false;
+               }
+
+               smcr |= convert_tBP_tAW[cycles] << NEMC_SMCR_TBP_SHIFT;
+       }
+
+       if (of_property_read_u32(node, "ingenic,nemc-tAW", &val) == 0) {
+               smcr &= ~NEMC_SMCR_TAW_MASK;
+               cycles = jz4780_nemc_ns_to_cycles(nemc, val);
+               if (cycles > 31) {
+                       dev_err(nemc->dev, "tAW %u is too high (%u cycles)\n",
+                               val, cycles);
+                       return false;
+               }
+
+               smcr |= convert_tBP_tAW[cycles] << NEMC_SMCR_TAW_SHIFT;
+       }
+
+       if (of_property_read_u32(node, "ingenic,nemc-tSTRV", &val) == 0) {
+               smcr &= ~NEMC_SMCR_TSTRV_MASK;
+               cycles = jz4780_nemc_ns_to_cycles(nemc, val);
+               if (cycles > 63) {
+                       dev_err(nemc->dev, "tSTRV %u is too high (%u cycles)\n",
+                               val, cycles);
+                       return false;
+               }
+
+               smcr |= cycles << NEMC_SMCR_TSTRV_SHIFT;
+       }
+
+       writel(smcr, nemc->base + NEMC_SMCRn(bank));
+       return true;
+}
+
+static int jz4780_nemc_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct jz4780_nemc *nemc;
+       struct resource *res;
+       struct device_node *child;
+       const __be32 *prop;
+       unsigned int bank;
+       unsigned long referenced;
+       int i, ret;
+
+       nemc = devm_kzalloc(dev, sizeof(*nemc), GFP_KERNEL);
+       if (!nemc)
+               return -ENOMEM;
+
+       spin_lock_init(&nemc->lock);
+       nemc->dev = dev;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       nemc->base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(nemc->base)) {
+               dev_err(dev, "failed to get I/O memory\n");
+               return PTR_ERR(nemc->base);
+       }
+
+       writel(0, nemc->base + NEMC_NFCSR);
+
+       nemc->clk = devm_clk_get(dev, NULL);
+       if (IS_ERR(nemc->clk)) {
+               dev_err(dev, "failed to get clock\n");
+               return PTR_ERR(nemc->clk);
+       }
+
+       ret = clk_prepare_enable(nemc->clk);
+       if (ret) {
+               dev_err(dev, "failed to enable clock: %d\n", ret);
+               return ret;
+       }
+
+       nemc->clk_period = jz4780_nemc_clk_period(nemc);
+       if (!nemc->clk_period) {
+               dev_err(dev, "failed to calculate clock period\n");
+               clk_disable_unprepare(nemc->clk);
+               return -EINVAL;
+       }
+
+       /*
+        * Iterate over child devices, check that they do not conflict with
+        * each other, and register child devices for them. If a child device
+        * has invalid properties, it is ignored and no platform device is
+        * registered for it.
+        */
+       for_each_child_of_node(nemc->dev->of_node, child) {
+               referenced = 0;
+               i = 0;
+               while ((prop = of_get_address(child, i++, NULL, NULL))) {
+                       bank = of_read_number(prop, 1);
+                       if (bank < 1 || bank >= JZ4780_NEMC_NUM_BANKS) {
+                               dev_err(nemc->dev,
+                                       "%s requests invalid bank %u\n",
+                                       child->full_name, bank);
+
+                               /* Will continue the outer loop below. */
+                               referenced = 0;
+                               break;
+                       }
+
+                       referenced |= BIT(bank);
+               }
+
+               if (!referenced) {
+                       dev_err(nemc->dev, "%s has no addresses\n",
+                               child->full_name);
+                       continue;
+               } else if (nemc->banks_present & referenced) {
+                       dev_err(nemc->dev, "%s conflicts with another node\n",
+                               child->full_name);
+                       continue;
+               }
+
+               /* Configure bank parameters. */
+               for_each_set_bit(bank, &referenced, JZ4780_NEMC_NUM_BANKS) {
+                       if (!jz4780_nemc_configure_bank(nemc, bank, child)) {
+                               referenced = 0;
+                               break;
+                       }
+               }
+
+               if (referenced) {
+                       if (of_platform_device_create(child, NULL, nemc->dev))
+                               nemc->banks_present |= referenced;
+               }
+       }
+
+       platform_set_drvdata(pdev, nemc);
+       dev_info(dev, "JZ4780 NEMC initialised\n");
+       return 0;
+}
+
+static int jz4780_nemc_remove(struct platform_device *pdev)
+{
+       struct jz4780_nemc *nemc = platform_get_drvdata(pdev);
+
+       clk_disable_unprepare(nemc->clk);
+       return 0;
+}
+
+static const struct of_device_id jz4780_nemc_dt_match[] = {
+       { .compatible = "ingenic,jz4780-nemc" },
+       {},
+};
+
+static struct platform_driver jz4780_nemc_driver = {
+       .probe          = jz4780_nemc_probe,
+       .remove         = jz4780_nemc_remove,
+       .driver = {
+               .name   = "jz4780-nemc",
+               .of_match_table = of_match_ptr(jz4780_nemc_dt_match),
+       },
+};
+
+static int __init jz4780_nemc_init(void)
+{
+       return platform_driver_register(&jz4780_nemc_driver);
+}
+subsys_initcall(jz4780_nemc_init);
index 24696f59215b6b819b44b92719c86afa381fec2e..c94ea0d687467f176e19d44dae06ebe0efaef899 100644 (file)
@@ -12,8 +12,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#undef DEBUG
-
 #include <linux/irq.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -29,6 +27,7 @@
 #include <linux/of_address.h>
 #include <linux/of_mtd.h>
 #include <linux/of_device.h>
+#include <linux/of_platform.h>
 #include <linux/omap-gpmc.h>
 #include <linux/mtd/nand.h>
 #include <linux/pm_runtime.h>
 #define GPMC_CONFIG1_WRITETYPE_ASYNC    (0 << 27)
 #define GPMC_CONFIG1_WRITETYPE_SYNC     (1 << 27)
 #define GPMC_CONFIG1_CLKACTIVATIONTIME(val) ((val & 3) << 25)
+/** CLKACTIVATIONTIME Max Ticks */
+#define GPMC_CONFIG1_CLKACTIVATIONTIME_MAX 2
 #define GPMC_CONFIG1_PAGE_LEN(val)      ((val & 3) << 23)
+/** ATTACHEDDEVICEPAGELENGTH Max Value */
+#define GPMC_CONFIG1_ATTACHEDDEVICEPAGELENGTH_MAX 2
 #define GPMC_CONFIG1_WAIT_READ_MON      (1 << 22)
 #define GPMC_CONFIG1_WAIT_WRITE_MON     (1 << 21)
-#define GPMC_CONFIG1_WAIT_MON_IIME(val) ((val & 3) << 18)
+#define GPMC_CONFIG1_WAIT_MON_TIME(val) ((val & 3) << 18)
+/** WAITMONITORINGTIME Max Ticks */
+#define GPMC_CONFIG1_WAITMONITORINGTIME_MAX  2
 #define GPMC_CONFIG1_WAIT_PIN_SEL(val)  ((val & 3) << 16)
 #define GPMC_CONFIG1_DEVICESIZE(val)    ((val & 3) << 12)
 #define GPMC_CONFIG1_DEVICESIZE_16      GPMC_CONFIG1_DEVICESIZE(1)
+/** DEVICESIZE Max Value */
+#define GPMC_CONFIG1_DEVICESIZE_MAX     1
 #define GPMC_CONFIG1_DEVICETYPE(val)    ((val & 3) << 10)
 #define GPMC_CONFIG1_DEVICETYPE_NOR     GPMC_CONFIG1_DEVICETYPE(0)
 #define GPMC_CONFIG1_MUXTYPE(val)       ((val & 3) << 8)
 #define GPMC_CONFIG1_FCLK_DIV4          (GPMC_CONFIG1_FCLK_DIV(3))
 #define GPMC_CONFIG7_CSVALID           (1 << 6)
 
+#define GPMC_CONFIG7_BASEADDRESS_MASK  0x3f
+#define GPMC_CONFIG7_CSVALID_MASK      BIT(6)
+#define GPMC_CONFIG7_MASKADDRESS_OFFSET        8
+#define GPMC_CONFIG7_MASKADDRESS_MASK  (0xf << GPMC_CONFIG7_MASKADDRESS_OFFSET)
+/* All CONFIG7 bits except reserved bits */
+#define GPMC_CONFIG7_MASK              (GPMC_CONFIG7_BASEADDRESS_MASK | \
+                                        GPMC_CONFIG7_CSVALID_MASK |     \
+                                        GPMC_CONFIG7_MASKADDRESS_MASK)
+
 #define GPMC_DEVICETYPE_NOR            0
 #define GPMC_DEVICETYPE_NAND           2
 #define GPMC_CONFIG_WRITEPROTECT       0x00000010
  */
 #define        GPMC_NR_IRQ             2
 
+enum gpmc_clk_domain {
+       GPMC_CD_FCLK,
+       GPMC_CD_CLK
+};
+
 struct gpmc_cs_data {
        const char *name;
 
@@ -267,16 +288,55 @@ static unsigned long gpmc_get_fclk_period(void)
        return rate;
 }
 
-static unsigned int gpmc_ns_to_ticks(unsigned int time_ns)
+/**
+ * gpmc_get_clk_period - get period of selected clock domain in ps
+ * @cs Chip Select Region.
+ * @cd Clock Domain.
+ *
+ * GPMC_CS_CONFIG1 GPMCFCLKDIVIDER for cs has to be setup
+ * prior to calling this function with GPMC_CD_CLK.
+ */
+static unsigned long gpmc_get_clk_period(int cs, enum gpmc_clk_domain cd)
+{
+
+       unsigned long tick_ps = gpmc_get_fclk_period();
+       u32 l;
+       int div;
+
+       switch (cd) {
+       case GPMC_CD_CLK:
+               /* get current clk divider */
+               l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+               div = (l & 0x03) + 1;
+               /* get GPMC_CLK period */
+               tick_ps *= div;
+               break;
+       case GPMC_CD_FCLK:
+               /* FALL-THROUGH */
+       default:
+               break;
+       }
+
+       return tick_ps;
+
+}
+
+static unsigned int gpmc_ns_to_clk_ticks(unsigned int time_ns, int cs,
+                                        enum gpmc_clk_domain cd)
 {
        unsigned long tick_ps;
 
        /* Calculate in picosecs to yield more exact results */
-       tick_ps = gpmc_get_fclk_period();
+       tick_ps = gpmc_get_clk_period(cs, cd);
 
        return (time_ns * 1000 + tick_ps - 1) / tick_ps;
 }
 
+static unsigned int gpmc_ns_to_ticks(unsigned int time_ns)
+{
+       return gpmc_ns_to_clk_ticks(time_ns, /* any CS */ 0, GPMC_CD_FCLK);
+}
+
 static unsigned int gpmc_ps_to_ticks(unsigned int time_ps)
 {
        unsigned long tick_ps;
@@ -287,9 +347,15 @@ static unsigned int gpmc_ps_to_ticks(unsigned int time_ps)
        return (time_ps + tick_ps - 1) / tick_ps;
 }
 
+unsigned int gpmc_clk_ticks_to_ns(unsigned ticks, int cs,
+                                 enum gpmc_clk_domain cd)
+{
+       return ticks * gpmc_get_clk_period(cs, cd) / 1000;
+}
+
 unsigned int gpmc_ticks_to_ns(unsigned int ticks)
 {
-       return ticks * gpmc_get_fclk_period() / 1000;
+       return gpmc_clk_ticks_to_ns(ticks, /* any CS */ 0, GPMC_CD_FCLK);
 }
 
 static unsigned int gpmc_ticks_to_ps(unsigned int ticks)
@@ -338,33 +404,66 @@ static void gpmc_cs_bool_timings(int cs, const struct gpmc_bool_timings *p)
 }
 
 #ifdef DEBUG
-static int get_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
-                              bool raw, bool noval, int shift,
-                              const char *name)
+/**
+ * get_gpmc_timing_reg - read a timing parameter and print DTS settings for it.
+ * @cs:      Chip Select Region
+ * @reg:     GPMC_CS_CONFIGn register offset.
+ * @st_bit:  Start Bit
+ * @end_bit: End Bit. Must be >= @st_bit.
+ * @ma:x     Maximum parameter value (before optional @shift).
+ *           If 0, maximum is as high as @st_bit and @end_bit allow.
+ * @name:    DTS node name, w/o "gpmc,"
+ * @cd:      Clock Domain of timing parameter.
+ * @shift:   Parameter value left shifts @shift, which is then printed instead of value.
+ * @raw:     Raw Format Option.
+ *           raw format:  gpmc,name = <value>
+ *           tick format: gpmc,name = <value> /&zwj;* x ns -- y ns; x ticks *&zwj;/
+ *           Where x ns -- y ns result in the same tick value.
+ *           When @max is exceeded, "invalid" is printed inside comment.
+ * @noval:   Parameter values equal to 0 are not printed.
+ * @return:  Specified timing parameter (after optional @shift).
+ *
+ */
+static int get_gpmc_timing_reg(
+       /* timing specifiers */
+       int cs, int reg, int st_bit, int end_bit, int max,
+       const char *name, const enum gpmc_clk_domain cd,
+       /* value transform */
+       int shift,
+       /* format specifiers */
+       bool raw, bool noval)
 {
        u32 l;
-       int nr_bits, max_value, mask;
+       int nr_bits;
+       int mask;
+       bool invalid;
 
        l = gpmc_cs_read_reg(cs, reg);
        nr_bits = end_bit - st_bit + 1;
-       max_value = (1 << nr_bits) - 1;
-       mask = max_value << st_bit;
-       l = (l & mask) >> st_bit;
+       mask = (1 << nr_bits) - 1;
+       l = (l >> st_bit) & mask;
+       if (!max)
+               max = mask;
+       invalid = l > max;
        if (shift)
                l = (shift << l);
        if (noval && (l == 0))
                return 0;
        if (!raw) {
-               unsigned int time_ns_min, time_ns, time_ns_max;
-
-               time_ns_min = gpmc_ticks_to_ns(l ? l - 1 : 0);
-               time_ns = gpmc_ticks_to_ns(l);
-               time_ns_max = gpmc_ticks_to_ns(l + 1 > max_value ?
-                                              max_value : l + 1);
-               pr_info("gpmc,%s = <%u> (%u - %u ns, %i ticks)\n",
-                       name, time_ns, time_ns_min, time_ns_max, l);
+               /* DTS tick format for timings in ns */
+               unsigned int time_ns;
+               unsigned int time_ns_min = 0;
+
+               if (l)
+                       time_ns_min = gpmc_clk_ticks_to_ns(l - 1, cs, cd) + 1;
+               time_ns = gpmc_clk_ticks_to_ns(l, cs, cd);
+               pr_info("gpmc,%s = <%u> /* %u ns - %u ns; %i ticks%s*/\n",
+                       name, time_ns, time_ns_min, time_ns, l,
+                       invalid ? "; invalid " : " ");
        } else {
-               pr_info("gpmc,%s = <%u>\n", name, l);
+               /* raw format */
+               pr_info("gpmc,%s = <%u>%s\n", name, l,
+                       invalid ? " /* invalid */" : "");
        }
 
        return l;
@@ -374,13 +473,19 @@ static int get_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
        pr_info("cs%i %s: 0x%08x\n", cs, #config, \
                gpmc_cs_read_reg(cs, config))
 #define GPMC_GET_RAW(reg, st, end, field) \
-       get_gpmc_timing_reg(cs, (reg), (st), (end), 1, 0, 0, field)
+       get_gpmc_timing_reg(cs, (reg), (st), (end), 0, field, GPMC_CD_FCLK, 0, 1, 0)
+#define GPMC_GET_RAW_MAX(reg, st, end, max, field) \
+       get_gpmc_timing_reg(cs, (reg), (st), (end), (max), field, GPMC_CD_FCLK, 0, 1, 0)
 #define GPMC_GET_RAW_BOOL(reg, st, end, field) \
-       get_gpmc_timing_reg(cs, (reg), (st), (end), 1, 1, 0, field)
-#define GPMC_GET_RAW_SHIFT(reg, st, end, shift, field) \
-       get_gpmc_timing_reg(cs, (reg), (st), (end), 1, 1, (shift), field)
+       get_gpmc_timing_reg(cs, (reg), (st), (end), 0, field, GPMC_CD_FCLK, 0, 1, 1)
+#define GPMC_GET_RAW_SHIFT_MAX(reg, st, end, shift, max, field) \
+       get_gpmc_timing_reg(cs, (reg), (st), (end), (max), field, GPMC_CD_FCLK, (shift), 1, 1)
 #define GPMC_GET_TICKS(reg, st, end, field) \
-       get_gpmc_timing_reg(cs, (reg), (st), (end), 0, 0, 0, field)
+       get_gpmc_timing_reg(cs, (reg), (st), (end), 0, field, GPMC_CD_FCLK, 0, 0, 0)
+#define GPMC_GET_TICKS_CD(reg, st, end, field, cd) \
+       get_gpmc_timing_reg(cs, (reg), (st), (end), 0, field, (cd), 0, 0, 0)
+#define GPMC_GET_TICKS_CD_MAX(reg, st, end, max, field, cd) \
+       get_gpmc_timing_reg(cs, (reg), (st), (end), (max), field, (cd), 0, 0, 0)
 
 static void gpmc_show_regs(int cs, const char *desc)
 {
@@ -404,11 +509,14 @@ static void gpmc_cs_show_timings(int cs, const char *desc)
        pr_info("gpmc cs%i access configuration:\n", cs);
        GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1,  4,  4, "time-para-granularity");
        GPMC_GET_RAW(GPMC_CS_CONFIG1,  8,  9, "mux-add-data");
-       GPMC_GET_RAW(GPMC_CS_CONFIG1, 12, 13, "device-width");
+       GPMC_GET_RAW_MAX(GPMC_CS_CONFIG1, 12, 13,
+                        GPMC_CONFIG1_DEVICESIZE_MAX, "device-width");
        GPMC_GET_RAW(GPMC_CS_CONFIG1, 16, 17, "wait-pin");
        GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 21, 21, "wait-on-write");
        GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 22, 22, "wait-on-read");
-       GPMC_GET_RAW_SHIFT(GPMC_CS_CONFIG1, 23, 24, 4, "burst-length");
+       GPMC_GET_RAW_SHIFT_MAX(GPMC_CS_CONFIG1, 23, 24, 4,
+                              GPMC_CONFIG1_ATTACHEDDEVICEPAGELENGTH_MAX,
+                              "burst-length");
        GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 27, 27, "sync-write");
        GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 28, 28, "burst-write");
        GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 29, 29, "gpmc,sync-read");
@@ -448,8 +556,12 @@ static void gpmc_cs_show_timings(int cs, const char *desc)
        GPMC_GET_TICKS(GPMC_CS_CONFIG6, 0, 3, "bus-turnaround-ns");
        GPMC_GET_TICKS(GPMC_CS_CONFIG6, 8, 11, "cycle2cycle-delay-ns");
 
-       GPMC_GET_TICKS(GPMC_CS_CONFIG1, 18, 19, "wait-monitoring-ns");
-       GPMC_GET_TICKS(GPMC_CS_CONFIG1, 25, 26, "clk-activation-ns");
+       GPMC_GET_TICKS_CD_MAX(GPMC_CS_CONFIG1, 18, 19,
+                             GPMC_CONFIG1_WAITMONITORINGTIME_MAX,
+                             "wait-monitoring-ns", GPMC_CD_CLK);
+       GPMC_GET_TICKS_CD_MAX(GPMC_CS_CONFIG1, 25, 26,
+                             GPMC_CONFIG1_CLKACTIVATIONTIME_MAX,
+                             "clk-activation-ns", GPMC_CD_FCLK);
 
        GPMC_GET_TICKS(GPMC_CS_CONFIG6, 16, 19, "wr-data-mux-bus-ns");
        GPMC_GET_TICKS(GPMC_CS_CONFIG6, 24, 28, "wr-access-ns");
@@ -460,8 +572,24 @@ static inline void gpmc_cs_show_timings(int cs, const char *desc)
 }
 #endif
 
-static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
-                              int time, const char *name)
+/**
+ * set_gpmc_timing_reg - set a single timing parameter for Chip Select Region.
+ * Caller is expected to have initialized CONFIG1 GPMCFCLKDIVIDER
+ * prior to calling this function with @cd equal to GPMC_CD_CLK.
+ *
+ * @cs:      Chip Select Region.
+ * @reg:     GPMC_CS_CONFIGn register offset.
+ * @st_bit:  Start Bit
+ * @end_bit: End Bit. Must be >= @st_bit.
+ * @max:     Maximum parameter value.
+ *           If 0, maximum is as high as @st_bit and @end_bit allow.
+ * @time:    Timing parameter in ns.
+ * @cd:      Timing parameter clock domain.
+ * @name:    Timing parameter name.
+ * @return:  0 on success, -1 on error.
+ */
+static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, int max,
+                              int time, enum gpmc_clk_domain cd, const char *name)
 {
        u32 l;
        int ticks, mask, nr_bits;
@@ -469,22 +597,25 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
        if (time == 0)
                ticks = 0;
        else
-               ticks = gpmc_ns_to_ticks(time);
+               ticks = gpmc_ns_to_clk_ticks(time, cs, cd);
        nr_bits = end_bit - st_bit + 1;
        mask = (1 << nr_bits) - 1;
 
-       if (ticks > mask) {
-               pr_err("%s: GPMC error! CS%d: %s: %d ns, %d ticks > %d\n",
-                      __func__, cs, name, time, ticks, mask);
+       if (!max)
+               max = mask;
+
+       if (ticks > max) {
+               pr_err("%s: GPMC CS%d: %s %d ns, %d ticks > %d ticks\n",
+                      __func__, cs, name, time, ticks, max);
 
                return -1;
        }
 
        l = gpmc_cs_read_reg(cs, reg);
 #ifdef DEBUG
-       printk(KERN_INFO
-               "GPMC CS%d: %-10s: %3d ticks, %3lu ns (was %3i ticks) %3d ns\n",
-              cs, name, ticks, gpmc_get_fclk_period() * ticks / 1000,
+       pr_info(
+               "GPMC CS%d: %-17s: %3d ticks, %3lu ns (was %3i ticks) %3d ns\n",
+              cs, name, ticks, gpmc_get_clk_period(cs, cd) * ticks / 1000,
                        (l >> st_bit) & mask, time);
 #endif
        l &= ~(mask << st_bit);
@@ -494,18 +625,56 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
        return 0;
 }
 
-#define GPMC_SET_ONE(reg, st, end, field) \
-       if (set_gpmc_timing_reg(cs, (reg), (st), (end),         \
-                       t->field, #field) < 0)                  \
+#define GPMC_SET_ONE_CD_MAX(reg, st, end, max, field, cd)  \
+       if (set_gpmc_timing_reg(cs, (reg), (st), (end), (max), \
+           t->field, (cd), #field) < 0)                       \
                return -1
 
+#define GPMC_SET_ONE(reg, st, end, field) \
+       GPMC_SET_ONE_CD_MAX(reg, st, end, 0, field, GPMC_CD_FCLK)
+
+/**
+ * gpmc_calc_waitmonitoring_divider - calculate proper GPMCFCLKDIVIDER based on WAITMONITORINGTIME
+ * WAITMONITORINGTIME will be _at least_ as long as desired, i.e.
+ * read  --> don't sample bus too early
+ * write --> data is longer on bus
+ *
+ * Formula:
+ * gpmc_clk_div + 1 = ceil(ceil(waitmonitoringtime_ns / gpmc_fclk_ns)
+ *                    / waitmonitoring_ticks)
+ * WAITMONITORINGTIME resulting in 0 or 1 tick with div = 1 are caught by
+ * div <= 0 check.
+ *
+ * @wait_monitoring: WAITMONITORINGTIME in ns.
+ * @return:          -1 on failure to scale, else proper divider > 0.
+ */
+static int gpmc_calc_waitmonitoring_divider(unsigned int wait_monitoring)
+{
+
+       int div = gpmc_ns_to_ticks(wait_monitoring);
+
+       div += GPMC_CONFIG1_WAITMONITORINGTIME_MAX - 1;
+       div /= GPMC_CONFIG1_WAITMONITORINGTIME_MAX;
+
+       if (div > 4)
+               return -1;
+       if (div <= 0)
+               div = 1;
+
+       return div;
+
+}
+
+/**
+ * gpmc_calc_divider - calculate GPMC_FCLK divider for sync_clk GPMC_CLK period.
+ * @sync_clk: GPMC_CLK period in ps.
+ * @return:   Returns at least 1 if GPMC_FCLK can be divided to GPMC_CLK.
+ *            Else, returns -1.
+ */
 int gpmc_calc_divider(unsigned int sync_clk)
 {
-       int div;
-       u32 l;
+       int div = gpmc_ps_to_ticks(sync_clk);
 
-       l = sync_clk + (gpmc_get_fclk_period() - 1);
-       div = l / gpmc_get_fclk_period();
        if (div > 4)
                return -1;
        if (div <= 0)
@@ -514,7 +683,15 @@ int gpmc_calc_divider(unsigned int sync_clk)
        return div;
 }
 
-int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
+/**
+ * gpmc_cs_set_timings - program timing parameters for Chip Select Region.
+ * @cs:     Chip Select Region.
+ * @t:      GPMC timing parameters.
+ * @s:      GPMC timing settings.
+ * @return: 0 on success, -1 on error.
+ */
+int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t,
+                       const struct gpmc_settings *s)
 {
        int div;
        u32 l;
@@ -524,6 +701,33 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
        if (div < 0)
                return div;
 
+       /*
+        * See if we need to change the divider for waitmonitoringtime.
+        *
+        * Calculate GPMCFCLKDIVIDER independent of gpmc,sync-clk-ps in DT for
+        * pure asynchronous accesses, i.e. both read and write asynchronous.
+        * However, only do so if WAITMONITORINGTIME is actually used, i.e.
+        * either WAITREADMONITORING or WAITWRITEMONITORING is set.
+        *
+        * This statement must not change div to scale async WAITMONITORINGTIME
+        * to protect mixed synchronous and asynchronous accesses.
+        *
+        * We raise an error later if WAITMONITORINGTIME does not fit.
+        */
+       if (!s->sync_read && !s->sync_write &&
+           (s->wait_on_read || s->wait_on_write)
+          ) {
+
+               div = gpmc_calc_waitmonitoring_divider(t->wait_monitoring);
+               if (div < 0) {
+                       pr_err("%s: waitmonitoringtime %3d ns too large for greatest gpmcfclkdivider.\n",
+                              __func__,
+                              t->wait_monitoring
+                              );
+                       return -1;
+               }
+       }
+
        GPMC_SET_ONE(GPMC_CS_CONFIG2,  0,  3, cs_on);
        GPMC_SET_ONE(GPMC_CS_CONFIG2,  8, 12, cs_rd_off);
        GPMC_SET_ONE(GPMC_CS_CONFIG2, 16, 20, cs_wr_off);
@@ -546,27 +750,27 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
        GPMC_SET_ONE(GPMC_CS_CONFIG6, 0, 3, bus_turnaround);
        GPMC_SET_ONE(GPMC_CS_CONFIG6, 8, 11, cycle2cycle_delay);
 
-       GPMC_SET_ONE(GPMC_CS_CONFIG1, 18, 19, wait_monitoring);
-       GPMC_SET_ONE(GPMC_CS_CONFIG1, 25, 26, clk_activation);
-
        if (gpmc_capability & GPMC_HAS_WR_DATA_MUX_BUS)
                GPMC_SET_ONE(GPMC_CS_CONFIG6, 16, 19, wr_data_mux_bus);
        if (gpmc_capability & GPMC_HAS_WR_ACCESS)
                GPMC_SET_ONE(GPMC_CS_CONFIG6, 24, 28, wr_access);
 
-       /* caller is expected to have initialized CONFIG1 to cover
-        * at least sync vs async
-        */
        l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
-       if (l & (GPMC_CONFIG1_READTYPE_SYNC | GPMC_CONFIG1_WRITETYPE_SYNC)) {
+       l &= ~0x03;
+       l |= (div - 1);
+       gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
+
+       GPMC_SET_ONE_CD_MAX(GPMC_CS_CONFIG1, 18, 19,
+                           GPMC_CONFIG1_WAITMONITORINGTIME_MAX,
+                           wait_monitoring, GPMC_CD_CLK);
+       GPMC_SET_ONE_CD_MAX(GPMC_CS_CONFIG1, 25, 26,
+                           GPMC_CONFIG1_CLKACTIVATIONTIME_MAX,
+                           clk_activation, GPMC_CD_FCLK);
+
 #ifdef DEBUG
-               printk(KERN_INFO "GPMC CS%d CLK period is %lu ns (div %d)\n",
-                               cs, (div * gpmc_get_fclk_period()) / 1000, div);
+       pr_info("GPMC CS%d CLK period is %lu ns (div %d)\n",
+                       cs, (div * gpmc_get_fclk_period()) / 1000, div);
 #endif
-               l &= ~0x03;
-               l |= (div - 1);
-               gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
-       }
 
        gpmc_cs_bool_timings(cs, &t->bool_timings);
        gpmc_cs_show_timings(cs, "after gpmc_cs_set_timings");
@@ -586,12 +790,15 @@ static int gpmc_cs_set_memconf(int cs, u32 base, u32 size)
        if (base & (size - 1))
                return -EINVAL;
 
+       base >>= GPMC_CHUNK_SHIFT;
        mask = (1 << GPMC_SECTION_SHIFT) - size;
+       mask >>= GPMC_CHUNK_SHIFT;
+       mask <<= GPMC_CONFIG7_MASKADDRESS_OFFSET;
+
        l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
-       l &= ~0x3f;
-       l = (base >> GPMC_CHUNK_SHIFT) & 0x3f;
-       l &= ~(0x0f << 8);
-       l |= ((mask >> GPMC_CHUNK_SHIFT) & 0x0f) << 8;
+       l &= ~GPMC_CONFIG7_MASK;
+       l |= base & GPMC_CONFIG7_BASEADDRESS_MASK;
+       l |= mask & GPMC_CONFIG7_MASKADDRESS_MASK;
        l |= GPMC_CONFIG7_CSVALID;
        gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l);
 
@@ -656,7 +863,7 @@ static void gpmc_cs_set_name(int cs, const char *name)
        gpmc->name = name;
 }
 
-const char *gpmc_cs_get_name(int cs)
+static const char *gpmc_cs_get_name(int cs)
 {
        struct gpmc_cs_data *gpmc = &gpmc_cs[cs];
 
@@ -1786,7 +1993,7 @@ static int gpmc_probe_generic_child(struct platform_device *pdev,
        if (ret < 0)
                goto err;
 
-       ret = gpmc_cs_set_timings(cs, &gpmc_t);
+       ret = gpmc_cs_set_timings(cs, &gpmc_t, &gpmc_s);
        if (ret) {
                dev_err(&pdev->dev, "failed to set gpmc timings for: %s\n",
                        child->name);
@@ -1802,8 +2009,21 @@ static int gpmc_probe_generic_child(struct platform_device *pdev,
        gpmc_cs_enable_mem(cs);
 
 no_timings:
-       if (of_platform_device_create(child, NULL, &pdev->dev))
-               return 0;
+
+       /* create platform device, NULL on error or when disabled */
+       if (!of_platform_device_create(child, NULL, &pdev->dev))
+               goto err_child_fail;
+
+       /* is child a common bus? */
+       if (of_match_node(of_default_bus_match_table, child))
+               /* create children and other common bus children */
+               if (of_platform_populate(child, of_default_bus_match_table,
+                                        NULL, &pdev->dev))
+                       goto err_child_fail;
+
+       return 0;
+
+err_child_fail:
 
        dev_err(&pdev->dev, "failed to create gpmc child %s\n", child->name);
        ret = -ENODEV;
index fc0c81ef04ff08df4de9feae9e19add3b56c6379..c4aecc6f83739779880f85ae6b5ac659a153c095 100644 (file)
@@ -74,15 +74,11 @@ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
        ret = ec_dev->cmd_xfer(ec_dev, msg);
        if (msg->result == EC_RES_IN_PROGRESS) {
                int i;
-               struct cros_ec_command status_msg;
-               struct ec_response_get_comms_status status;
+               struct cros_ec_command status_msg = { };
+               struct ec_response_get_comms_status *status;
 
-               status_msg.version = 0;
                status_msg.command = EC_CMD_GET_COMMS_STATUS;
-               status_msg.outdata = NULL;
-               status_msg.outsize = 0;
-               status_msg.indata = (uint8_t *)&status;
-               status_msg.insize = sizeof(status);
+               status_msg.insize = sizeof(*status);
 
                /*
                 * Query the EC's status until it's no longer busy or
@@ -98,7 +94,10 @@ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
                        msg->result = status_msg.result;
                        if (status_msg.result != EC_RES_SUCCESS)
                                break;
-                       if (!(status.flags & EC_COMMS_STATUS_PROCESSING))
+
+                       status = (struct ec_response_get_comms_status *)
+                                status_msg.indata;
+                       if (!(status->flags & EC_COMMS_STATUS_PROCESSING))
                                break;
                }
        }
@@ -119,6 +118,10 @@ static const struct mfd_cell cros_devs[] = {
                .id = 2,
                .of_compatible = "google,cros-ec-i2c-tunnel",
        },
+       {
+               .name = "cros-ec-ctl",
+               .id = 3,
+       },
 };
 
 int cros_ec_register(struct cros_ec_device *ec_dev)
index 4c4a59b2553797b52cde8c4465da82d979eee1ed..7f90ce5a569a434e68da725d3a71b59bd86b5453 100644 (file)
@@ -230,6 +230,8 @@ static const struct i2c_device_id bh1780_id[] = {
        { },
 };
 
+MODULE_DEVICE_TABLE(i2c, bh1780_id);
+
 #ifdef CONFIG_OF
 static const struct of_device_id of_bh1780_match[] = {
        { .compatible = "rohm,bh1780gli", },
index 06166ac000e08c8788725916b5a3a68469ac7e3a..0b1bd85e4ae677f115c1b60b45f156c8ddd67327 100644 (file)
@@ -479,6 +479,7 @@ static int fpga_program_block(struct fpga_dev *priv, void *buf, size_t count)
 static noinline int fpga_program_cpu(struct fpga_dev *priv)
 {
        int ret;
+       unsigned long timeout;
 
        /* Disable the programmer */
        fpga_programmer_disable(priv);
@@ -497,8 +498,8 @@ static noinline int fpga_program_cpu(struct fpga_dev *priv)
                goto out_disable_controller;
 
        /* Wait for the interrupt handler to signal that programming finished */
-       ret = wait_for_completion_timeout(&priv->completion, 2 * HZ);
-       if (!ret) {
+       timeout = wait_for_completion_timeout(&priv->completion, 2 * HZ);
+       if (!timeout) {
                dev_err(priv->dev, "Timed out waiting for completion\n");
                ret = -ETIMEDOUT;
                goto out_disable_controller;
@@ -536,6 +537,7 @@ static noinline int fpga_program_dma(struct fpga_dev *priv)
        struct sg_table table;
        dma_cookie_t cookie;
        int ret, i;
+       unsigned long timeout;
 
        /* Disable the programmer */
        fpga_programmer_disable(priv);
@@ -623,8 +625,8 @@ static noinline int fpga_program_dma(struct fpga_dev *priv)
        dev_dbg(priv->dev, "enabled the controller\n");
 
        /* Wait for the interrupt handler to signal that programming finished */
-       ret = wait_for_completion_timeout(&priv->completion, 2 * HZ);
-       if (!ret) {
+       timeout = wait_for_completion_timeout(&priv->completion, 2 * HZ);
+       if (!timeout) {
                dev_err(priv->dev, "Timed out waiting for completion\n");
                ret = -ETIMEDOUT;
                goto out_disable_controller;
@@ -1142,7 +1144,7 @@ out_return:
        return ret;
 }
 
-static struct of_device_id fpga_of_match[] = {
+static const struct of_device_id fpga_of_match[] = {
        { .compatible = "carma,fpga-programmer", },
        {},
 };
index 68cdfe151bdb8481f964e6a12039e95dd85a8399..5aba3fd789deb25ddced039dab80bf4ae0489692 100644 (file)
@@ -1486,7 +1486,7 @@ static int data_of_remove(struct platform_device *op)
        return 0;
 }
 
-static struct of_device_id data_of_match[] = {
+static const struct of_device_id data_of_match[] = {
        { .compatible = "carma,carma-fpga", },
        {},
 };
index 3ef4627f9cb1552a7585787f6da81cb880c4b784..4739689d23ad08aec40c4478d57e3fae3a118adb 100644 (file)
@@ -950,6 +950,7 @@ int lis3lv02d_init_dt(struct lis3lv02d *lis3)
        struct lis3lv02d_platform_data *pdata;
        struct device_node *np = lis3->of_node;
        u32 val;
+       s32 sval;
 
        if (!lis3->of_node)
                return 0;
@@ -1031,6 +1032,23 @@ int lis3lv02d_init_dt(struct lis3lv02d *lis3)
                pdata->wakeup_flags |= LIS3_WAKEUP_Z_LO;
        if (of_get_property(np, "st,wakeup-z-hi", NULL))
                pdata->wakeup_flags |= LIS3_WAKEUP_Z_HI;
+       if (of_get_property(np, "st,wakeup-threshold", &val))
+               pdata->wakeup_thresh = val;
+
+       if (of_get_property(np, "st,wakeup2-x-lo", NULL))
+               pdata->wakeup_flags2 |= LIS3_WAKEUP_X_LO;
+       if (of_get_property(np, "st,wakeup2-x-hi", NULL))
+               pdata->wakeup_flags2 |= LIS3_WAKEUP_X_HI;
+       if (of_get_property(np, "st,wakeup2-y-lo", NULL))
+               pdata->wakeup_flags2 |= LIS3_WAKEUP_Y_LO;
+       if (of_get_property(np, "st,wakeup2-y-hi", NULL))
+               pdata->wakeup_flags2 |= LIS3_WAKEUP_Y_HI;
+       if (of_get_property(np, "st,wakeup2-z-lo", NULL))
+               pdata->wakeup_flags2 |= LIS3_WAKEUP_Z_LO;
+       if (of_get_property(np, "st,wakeup2-z-hi", NULL))
+               pdata->wakeup_flags2 |= LIS3_WAKEUP_Z_HI;
+       if (of_get_property(np, "st,wakeup2-threshold", &val))
+               pdata->wakeup_thresh2 = val;
 
        if (!of_property_read_u32(np, "st,highpass-cutoff-hz", &val)) {
                switch (val) {
@@ -1054,29 +1072,29 @@ int lis3lv02d_init_dt(struct lis3lv02d *lis3)
        if (of_get_property(np, "st,hipass2-disable", NULL))
                pdata->hipass_ctrl |= LIS3_HIPASS2_DISABLE;
 
-       if (of_get_property(np, "st,axis-x", &val))
-               pdata->axis_x = val;
-       if (of_get_property(np, "st,axis-y", &val))
-               pdata->axis_y = val;
-       if (of_get_property(np, "st,axis-z", &val))
-               pdata->axis_z = val;
+       if (of_property_read_s32(np, "st,axis-x", &sval) == 0)
+               pdata->axis_x = sval;
+       if (of_property_read_s32(np, "st,axis-y", &sval) == 0)
+               pdata->axis_y = sval;
+       if (of_property_read_s32(np, "st,axis-z", &sval) == 0)
+               pdata->axis_z = sval;
 
        if (of_get_property(np, "st,default-rate", NULL))
                pdata->default_rate = val;
 
-       if (of_get_property(np, "st,min-limit-x", &val))
-               pdata->st_min_limits[0] = val;
-       if (of_get_property(np, "st,min-limit-y", &val))
-               pdata->st_min_limits[1] = val;
-       if (of_get_property(np, "st,min-limit-z", &val))
-               pdata->st_min_limits[2] = val;
-
-       if (of_get_property(np, "st,max-limit-x", &val))
-               pdata->st_max_limits[0] = val;
-       if (of_get_property(np, "st,max-limit-y", &val))
-               pdata->st_max_limits[1] = val;
-       if (of_get_property(np, "st,max-limit-z", &val))
-               pdata->st_max_limits[2] = val;
+       if (of_property_read_s32(np, "st,min-limit-x", &sval) == 0)
+               pdata->st_min_limits[0] = sval;
+       if (of_property_read_s32(np, "st,min-limit-y", &sval) == 0)
+               pdata->st_min_limits[1] = sval;
+       if (of_property_read_s32(np, "st,min-limit-z", &sval) == 0)
+               pdata->st_min_limits[2] = sval;
+
+       if (of_property_read_s32(np, "st,max-limit-x", &sval) == 0)
+               pdata->st_max_limits[0] = sval;
+       if (of_property_read_s32(np, "st,max-limit-y", &sval) == 0)
+               pdata->st_max_limits[1] = sval;
+       if (of_property_read_s32(np, "st,max-limit-z", &sval) == 0)
+               pdata->st_max_limits[2] = sval;
 
 
        lis3->pdata = pdata;
index 63fe096d44621a3c771b500452240e234da6357b..e3e7f1dc27ba5df5daf8ad647953c10d92a69caa 100644 (file)
@@ -106,7 +106,7 @@ static union axis_conversion lis3lv02d_axis_map =
        { .as_array = { LIS3_DEV_X, LIS3_DEV_Y, LIS3_DEV_Z } };
 
 #ifdef CONFIG_OF
-static struct of_device_id lis3lv02d_i2c_dt_ids[] = {
+static const struct of_device_id lis3lv02d_i2c_dt_ids[] = {
        { .compatible = "st,lis3lv02d" },
        {}
 };
index bd06d0cfac45e15a2f1ee21f1e4ab856867e0e98..b2f6e1651ac941a37d5ff57bfde8ab0b286442da 100644 (file)
@@ -61,7 +61,7 @@ static union axis_conversion lis3lv02d_axis_normal =
        { .as_array = { 1, 2, 3 } };
 
 #ifdef CONFIG_OF
-static struct of_device_id lis302dl_spi_dt_ids[] = {
+static const struct of_device_id lis302dl_spi_dt_ids[] = {
        { .compatible = "st,lis302dl-spi" },
        {}
 };
index 8ebc6cda1373d6c7e543d785064559720bbf0391..518914a82b83755ba05d6bdb214aabcf2c05d563 100644 (file)
@@ -21,3 +21,6 @@ mei-me-objs += hw-me.o
 obj-$(CONFIG_INTEL_MEI_TXE) += mei-txe.o
 mei-txe-objs := pci-txe.o
 mei-txe-objs += hw-txe.o
+
+mei-$(CONFIG_EVENT_TRACING) += mei-trace.o
+CFLAGS_mei-trace.o = -I$(src)
index 40ea639fa413a92f0239e1835894e73d36ddc1c1..d2cd53e3fac378b27e0694e04ea8cee0438d784d 100644 (file)
@@ -48,10 +48,7 @@ void mei_amthif_reset_params(struct mei_device *dev)
 {
        /* reset iamthif parameters. */
        dev->iamthif_current_cb = NULL;
-       dev->iamthif_msg_buf_size = 0;
-       dev->iamthif_msg_buf_index = 0;
        dev->iamthif_canceled = false;
-       dev->iamthif_ioctl = false;
        dev->iamthif_state = MEI_IAMTHIF_IDLE;
        dev->iamthif_timer = 0;
        dev->iamthif_stall_timer = 0;
@@ -69,7 +66,6 @@ int mei_amthif_host_init(struct mei_device *dev)
 {
        struct mei_cl *cl = &dev->iamthif_cl;
        struct mei_me_client *me_cl;
-       unsigned char *msg_buf;
        int ret;
 
        dev->iamthif_state = MEI_IAMTHIF_IDLE;
@@ -90,18 +86,6 @@ int mei_amthif_host_init(struct mei_device *dev)
        dev->iamthif_mtu = me_cl->props.max_msg_length;
        dev_dbg(dev->dev, "IAMTHIF_MTU = %d\n", dev->iamthif_mtu);
 
-       kfree(dev->iamthif_msg_buf);
-       dev->iamthif_msg_buf = NULL;
-
-       /* allocate storage for ME message buffer */
-       msg_buf = kcalloc(dev->iamthif_mtu,
-                       sizeof(unsigned char), GFP_KERNEL);
-       if (!msg_buf) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       dev->iamthif_msg_buf = msg_buf;
 
        ret = mei_cl_link(cl, MEI_IAMTHIF_HOST_CLIENT_ID);
        if (ret < 0) {
@@ -194,30 +178,33 @@ int mei_amthif_read(struct mei_device *dev, struct file *file,
                dev_dbg(dev->dev, "woke up from sleep\n");
        }
 
+       if (cb->status) {
+               rets = cb->status;
+               dev_dbg(dev->dev, "read operation failed %d\n", rets);
+               goto free;
+       }
 
        dev_dbg(dev->dev, "Got amthif data\n");
        dev->iamthif_timer = 0;
 
-       if (cb) {
-               timeout = cb->read_time +
-                       mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
-               dev_dbg(dev->dev, "amthif timeout = %lud\n",
-                               timeout);
-
-               if  (time_after(jiffies, timeout)) {
-                       dev_dbg(dev->dev, "amthif Time out\n");
-                       /* 15 sec for the message has expired */
-                       list_del(&cb->list);
-                       rets = -ETIME;
-                       goto free;
-               }
+       timeout = cb->read_time +
+               mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
+       dev_dbg(dev->dev, "amthif timeout = %lud\n",
+                       timeout);
+
+       if  (time_after(jiffies, timeout)) {
+               dev_dbg(dev->dev, "amthif Time out\n");
+               /* 15 sec for the message has expired */
+               list_del_init(&cb->list);
+               rets = -ETIME;
+               goto free;
        }
        /* if the whole message will fit remove it from the list */
        if (cb->buf_idx >= *offset && length >= (cb->buf_idx - *offset))
-               list_del(&cb->list);
+               list_del_init(&cb->list);
        else if (cb->buf_idx > 0 && cb->buf_idx <= *offset) {
                /* end of the message has been reached */
-               list_del(&cb->list);
+               list_del_init(&cb->list);
                rets = 0;
                goto free;
        }
@@ -225,15 +212,15 @@ int mei_amthif_read(struct mei_device *dev, struct file *file,
                 * remove message from deletion list
                 */
 
-       dev_dbg(dev->dev, "amthif cb->response_buffer size - %d\n",
-           cb->response_buffer.size);
+       dev_dbg(dev->dev, "amthif cb->buf size - %d\n",
+           cb->buf.size);
        dev_dbg(dev->dev, "amthif cb->buf_idx - %lu\n", cb->buf_idx);
 
        /* length is being truncated to PAGE_SIZE, however,
         * the buf_idx may point beyond */
        length = min_t(size_t, length, (cb->buf_idx - *offset));
 
-       if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length)) {
+       if (copy_to_user(ubuf, cb->buf.data + *offset, length)) {
                dev_dbg(dev->dev, "failed to copy data to userland\n");
                rets = -EFAULT;
        } else {
@@ -252,126 +239,88 @@ out:
 }
 
 /**
- * mei_amthif_send_cmd - send amthif command to the ME
+ * mei_amthif_read_start - queue message for sending read credential
  *
- * @dev: the device structure
- * @cb: mei call back struct
+ * @cl: host client
+ * @file: file pointer of message recipient
  *
  * Return: 0 on success, <0 on failure.
- *
  */
-static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
+static int mei_amthif_read_start(struct mei_cl *cl, struct file *file)
 {
-       struct mei_msg_hdr mei_hdr;
-       struct mei_cl *cl;
-       int ret;
-
-       if (!dev || !cb)
-               return -ENODEV;
+       struct mei_device *dev = cl->dev;
+       struct mei_cl_cb *cb;
+       size_t length = dev->iamthif_mtu;
+       int rets;
 
-       dev_dbg(dev->dev, "write data to amthif client.\n");
+       cb = mei_io_cb_init(cl, MEI_FOP_READ, file);
+       if (!cb) {
+               rets = -ENOMEM;
+               goto err;
+       }
 
-       dev->iamthif_state = MEI_IAMTHIF_WRITING;
-       dev->iamthif_current_cb = cb;
-       dev->iamthif_file_object = cb->file_object;
-       dev->iamthif_canceled = false;
-       dev->iamthif_ioctl = true;
-       dev->iamthif_msg_buf_size = cb->request_buffer.size;
-       memcpy(dev->iamthif_msg_buf, cb->request_buffer.data,
-              cb->request_buffer.size);
-       cl = &dev->iamthif_cl;
+       rets = mei_io_cb_alloc_buf(cb, length);
+       if (rets)
+               goto err;
 
-       ret = mei_cl_flow_ctrl_creds(cl);
-       if (ret < 0)
-               return ret;
+       list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
 
-       if (ret && mei_hbuf_acquire(dev)) {
-               ret = 0;
-               if (cb->request_buffer.size > mei_hbuf_max_len(dev)) {
-                       mei_hdr.length = mei_hbuf_max_len(dev);
-                       mei_hdr.msg_complete = 0;
-               } else {
-                       mei_hdr.length = cb->request_buffer.size;
-                       mei_hdr.msg_complete = 1;
-               }
+       dev->iamthif_state = MEI_IAMTHIF_READING;
+       dev->iamthif_file_object = cb->file_object;
+       dev->iamthif_current_cb = cb;
 
-               mei_hdr.host_addr = cl->host_client_id;
-               mei_hdr.me_addr = cl->me_client_id;
-               mei_hdr.reserved = 0;
-               mei_hdr.internal = 0;
-               dev->iamthif_msg_buf_index += mei_hdr.length;
-               ret = mei_write_message(dev, &mei_hdr, dev->iamthif_msg_buf);
-               if (ret)
-                       return ret;
-
-               if (mei_hdr.msg_complete) {
-                       if (mei_cl_flow_ctrl_reduce(cl))
-                               return -EIO;
-                       dev->iamthif_flow_control_pending = true;
-                       dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
-                       dev_dbg(dev->dev, "add amthif cb to write waiting list\n");
-                       dev->iamthif_current_cb = cb;
-                       dev->iamthif_file_object = cb->file_object;
-                       list_add_tail(&cb->list, &dev->write_waiting_list.list);
-               } else {
-                       dev_dbg(dev->dev, "message does not complete, so add amthif cb to write list.\n");
-                       list_add_tail(&cb->list, &dev->write_list.list);
-               }
-       } else {
-               list_add_tail(&cb->list, &dev->write_list.list);
-       }
        return 0;
+err:
+       mei_io_cb_free(cb);
+       return rets;
 }
 
 /**
- * mei_amthif_write - write amthif data to amthif client
+ * mei_amthif_send_cmd - send amthif command to the ME
  *
- * @dev: the device structure
+ * @cl: the host client
  * @cb: mei call back struct
  *
  * Return: 0 on success, <0 on failure.
- *
  */
-int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *cb)
+static int mei_amthif_send_cmd(struct mei_cl *cl, struct mei_cl_cb *cb)
 {
+       struct mei_device *dev;
        int ret;
 
-       if (!dev || !cb)
+       if (!cl->dev || !cb)
                return -ENODEV;
 
-       ret = mei_io_cb_alloc_resp_buf(cb, dev->iamthif_mtu);
-       if (ret)
+       dev = cl->dev;
+
+       dev->iamthif_state = MEI_IAMTHIF_WRITING;
+       dev->iamthif_current_cb = cb;
+       dev->iamthif_file_object = cb->file_object;
+       dev->iamthif_canceled = false;
+
+       ret = mei_cl_write(cl, cb, false);
+       if (ret < 0)
                return ret;
 
-       cb->fop_type = MEI_FOP_WRITE;
+       if (cb->completed)
+               cb->status = mei_amthif_read_start(cl, cb->file_object);
 
-       if (!list_empty(&dev->amthif_cmd_list.list) ||
-           dev->iamthif_state != MEI_IAMTHIF_IDLE) {
-               dev_dbg(dev->dev,
-                       "amthif state = %d\n", dev->iamthif_state);
-               dev_dbg(dev->dev, "AMTHIF: add cb to the wait list\n");
-               list_add_tail(&cb->list, &dev->amthif_cmd_list.list);
-               return 0;
-       }
-       return mei_amthif_send_cmd(dev, cb);
+       return 0;
 }
+
 /**
  * mei_amthif_run_next_cmd - send next amt command from queue
  *
  * @dev: the device structure
+ *
+ * Return: 0 on success, <0 on failure.
  */
-void mei_amthif_run_next_cmd(struct mei_device *dev)
+int mei_amthif_run_next_cmd(struct mei_device *dev)
 {
+       struct mei_cl *cl = &dev->iamthif_cl;
        struct mei_cl_cb *cb;
-       int ret;
-
-       if (!dev)
-               return;
 
-       dev->iamthif_msg_buf_size = 0;
-       dev->iamthif_msg_buf_index = 0;
        dev->iamthif_canceled = false;
-       dev->iamthif_ioctl = true;
        dev->iamthif_state = MEI_IAMTHIF_IDLE;
        dev->iamthif_timer = 0;
        dev->iamthif_file_object = NULL;
@@ -381,13 +330,48 @@ void mei_amthif_run_next_cmd(struct mei_device *dev)
        cb = list_first_entry_or_null(&dev->amthif_cmd_list.list,
                                        typeof(*cb), list);
        if (!cb)
-               return;
-       list_del(&cb->list);
-       ret =  mei_amthif_send_cmd(dev, cb);
-       if (ret)
-               dev_warn(dev->dev, "amthif write failed status = %d\n", ret);
+               return 0;
+
+       list_del_init(&cb->list);
+       return mei_amthif_send_cmd(cl, cb);
 }
 
+/**
+ * mei_amthif_write - write amthif data to amthif client
+ *
+ * @cl: host client
+ * @cb: mei call back struct
+ *
+ * Return: 0 on success, <0 on failure.
+ */
+int mei_amthif_write(struct mei_cl *cl, struct mei_cl_cb *cb)
+{
+
+       struct mei_device *dev;
+
+       if (WARN_ON(!cl || !cl->dev))
+               return -ENODEV;
+
+       if (WARN_ON(!cb))
+               return -EINVAL;
+
+       dev = cl->dev;
+
+       list_add_tail(&cb->list, &dev->amthif_cmd_list.list);
+       return mei_amthif_run_next_cmd(dev);
+}
+
+/**
+ * mei_amthif_poll - the amthif poll function
+ *
+ * @dev: the device structure
+ * @file: pointer to file structure
+ * @wait: pointer to poll_table structure
+ *
+ * Return: poll mask
+ *
+ * Locking: called under "dev->device_lock" lock
+ */
 
 unsigned int mei_amthif_poll(struct mei_device *dev,
                struct file *file, poll_table *wait)
@@ -396,19 +380,12 @@ unsigned int mei_amthif_poll(struct mei_device *dev,
 
        poll_wait(file, &dev->iamthif_cl.wait, wait);
 
-       mutex_lock(&dev->device_lock);
-       if (!mei_cl_is_connected(&dev->iamthif_cl)) {
-
-               mask = POLLERR;
-
-       } else if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE &&
-                  dev->iamthif_file_object == file) {
+       if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE &&
+           dev->iamthif_file_object == file) {
 
-               mask |= (POLLIN | POLLRDNORM);
-               dev_dbg(dev->dev, "run next amthif cb\n");
+               mask |= POLLIN | POLLRDNORM;
                mei_amthif_run_next_cmd(dev);
        }
-       mutex_unlock(&dev->device_lock);
 
        return mask;
 }
@@ -427,71 +404,14 @@ unsigned int mei_amthif_poll(struct mei_device *dev,
 int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
                         struct mei_cl_cb *cmpl_list)
 {
-       struct mei_device *dev = cl->dev;
-       struct mei_msg_hdr mei_hdr;
-       size_t len = dev->iamthif_msg_buf_size - dev->iamthif_msg_buf_index;
-       u32 msg_slots = mei_data2slots(len);
-       int slots;
-       int rets;
-
-       rets = mei_cl_flow_ctrl_creds(cl);
-       if (rets < 0)
-               return rets;
-
-       if (rets == 0) {
-               cl_dbg(dev, cl, "No flow control credentials: not sending.\n");
-               return 0;
-       }
-
-       mei_hdr.host_addr = cl->host_client_id;
-       mei_hdr.me_addr = cl->me_client_id;
-       mei_hdr.reserved = 0;
-       mei_hdr.internal = 0;
-
-       slots = mei_hbuf_empty_slots(dev);
-
-       if (slots >= msg_slots) {
-               mei_hdr.length = len;
-               mei_hdr.msg_complete = 1;
-       /* Split the message only if we can write the whole host buffer */
-       } else if (slots == dev->hbuf_depth) {
-               msg_slots = slots;
-               len = (slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
-               mei_hdr.length = len;
-               mei_hdr.msg_complete = 0;
-       } else {
-               /* wait for next time the host buffer is empty */
-               return 0;
-       }
-
-       dev_dbg(dev->dev, MEI_HDR_FMT,  MEI_HDR_PRM(&mei_hdr));
-
-       rets = mei_write_message(dev, &mei_hdr,
-                       dev->iamthif_msg_buf + dev->iamthif_msg_buf_index);
-       if (rets) {
-               dev->iamthif_state = MEI_IAMTHIF_IDLE;
-               cl->status = rets;
-               list_del(&cb->list);
-               return rets;
-       }
-
-       if (mei_cl_flow_ctrl_reduce(cl))
-               return -EIO;
-
-       dev->iamthif_msg_buf_index += mei_hdr.length;
-       cl->status = 0;
-
-       if (mei_hdr.msg_complete) {
-               dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
-               dev->iamthif_flow_control_pending = true;
-
-               /* save iamthif cb sent to amthif client */
-               cb->buf_idx = dev->iamthif_msg_buf_index;
-               dev->iamthif_current_cb = cb;
+       int ret;
 
-               list_move_tail(&cb->list, &dev->write_waiting_list.list);
-       }
+       ret = mei_cl_irq_write(cl, cb, cmpl_list);
+       if (ret)
+               return ret;
 
+       if (cb->completed)
+               cb->status = mei_amthif_read_start(cl, cb->file_object);
 
        return 0;
 }
@@ -500,83 +420,35 @@ int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
  * mei_amthif_irq_read_msg - read routine after ISR to
  *                     handle the read amthif message
  *
- * @dev: the device structure
+ * @cl: mei client
  * @mei_hdr: header of amthif message
- * @complete_list: An instance of our list structure
+ * @cmpl_list: completed callbacks list
  *
- * Return: 0 on success, <0 on failure.
+ * Return: -ENODEV if cb is NULL 0 otherwise; error message is in cb->status
  */
-int mei_amthif_irq_read_msg(struct mei_device *dev,
+int mei_amthif_irq_read_msg(struct mei_cl *cl,
                            struct mei_msg_hdr *mei_hdr,
-                           struct mei_cl_cb *complete_list)
+                           struct mei_cl_cb *cmpl_list)
 {
-       struct mei_cl_cb *cb;
-       unsigned char *buffer;
-
-       BUG_ON(mei_hdr->me_addr != dev->iamthif_cl.me_client_id);
-       BUG_ON(dev->iamthif_state != MEI_IAMTHIF_READING);
+       struct mei_device *dev;
+       int ret;
 
-       buffer = dev->iamthif_msg_buf + dev->iamthif_msg_buf_index;
-       BUG_ON(dev->iamthif_mtu < dev->iamthif_msg_buf_index + mei_hdr->length);
+       dev = cl->dev;
 
-       mei_read_slots(dev, buffer, mei_hdr->length);
+       if (dev->iamthif_state != MEI_IAMTHIF_READING)
+               return 0;
 
-       dev->iamthif_msg_buf_index += mei_hdr->length;
+       ret = mei_cl_irq_read_msg(cl, mei_hdr, cmpl_list);
+       if (ret)
+               return ret;
 
        if (!mei_hdr->msg_complete)
                return 0;
 
-       dev_dbg(dev->dev, "amthif_message_buffer_index =%d\n",
-                       mei_hdr->length);
-
        dev_dbg(dev->dev, "completed amthif read.\n ");
-       if (!dev->iamthif_current_cb)
-               return -ENODEV;
-
-       cb = dev->iamthif_current_cb;
        dev->iamthif_current_cb = NULL;
-
        dev->iamthif_stall_timer = 0;
-       cb->buf_idx = dev->iamthif_msg_buf_index;
-       cb->read_time = jiffies;
-       if (dev->iamthif_ioctl) {
-               /* found the iamthif cb */
-               dev_dbg(dev->dev, "complete the amthif read cb.\n ");
-               dev_dbg(dev->dev, "add the amthif read cb to complete.\n ");
-               list_add_tail(&cb->list, &complete_list->list);
-       }
-       return 0;
-}
-
-/**
- * mei_amthif_irq_read - prepares to read amthif data.
- *
- * @dev: the device structure.
- * @slots: free slots.
- *
- * Return: 0, OK; otherwise, error.
- */
-int mei_amthif_irq_read(struct mei_device *dev, s32 *slots)
-{
-       u32 msg_slots = mei_data2slots(sizeof(struct hbm_flow_control));
-
-       if (*slots < msg_slots)
-               return -EMSGSIZE;
-
-       *slots -= msg_slots;
-
-       if (mei_hbm_cl_flow_control_req(dev, &dev->iamthif_cl)) {
-               dev_dbg(dev->dev, "iamthif flow control failed\n");
-               return -EIO;
-       }
 
-       dev_dbg(dev->dev, "iamthif flow control success\n");
-       dev->iamthif_state = MEI_IAMTHIF_READING;
-       dev->iamthif_flow_control_pending = false;
-       dev->iamthif_msg_buf_index = 0;
-       dev->iamthif_msg_buf_size = 0;
-       dev->iamthif_stall_timer = MEI_IAMTHIF_STALL_TIMER;
-       dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
        return 0;
 }
 
@@ -588,17 +460,30 @@ int mei_amthif_irq_read(struct mei_device *dev, s32 *slots)
  */
 void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb)
 {
+
+       if (cb->fop_type == MEI_FOP_WRITE) {
+               if (!cb->status) {
+                       dev->iamthif_stall_timer = MEI_IAMTHIF_STALL_TIMER;
+                       mei_io_cb_free(cb);
+                       return;
+               }
+               /*
+                * in case of error enqueue the write cb to complete read list
+                * so it can be propagated to the reader
+                */
+               list_add_tail(&cb->list, &dev->amthif_rd_complete_list.list);
+               wake_up_interruptible(&dev->iamthif_cl.wait);
+               return;
+       }
+
        if (dev->iamthif_canceled != 1) {
                dev->iamthif_state = MEI_IAMTHIF_READ_COMPLETE;
                dev->iamthif_stall_timer = 0;
-               memcpy(cb->response_buffer.data,
-                               dev->iamthif_msg_buf,
-                               dev->iamthif_msg_buf_index);
                list_add_tail(&cb->list, &dev->amthif_rd_complete_list.list);
                dev_dbg(dev->dev, "amthif read completed\n");
                dev->iamthif_timer = jiffies;
                dev_dbg(dev->dev, "dev->iamthif_timer = %ld\n",
-                               dev->iamthif_timer);
+                       dev->iamthif_timer);
        } else {
                mei_amthif_run_next_cmd(dev);
        }
@@ -623,26 +508,22 @@ void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb)
 static bool mei_clear_list(struct mei_device *dev,
                const struct file *file, struct list_head *mei_cb_list)
 {
-       struct mei_cl_cb *cb_pos = NULL;
-       struct mei_cl_cb *cb_next = NULL;
+       struct mei_cl *cl = &dev->iamthif_cl;
+       struct mei_cl_cb *cb, *next;
        bool removed = false;
 
        /* list all list member */
-       list_for_each_entry_safe(cb_pos, cb_next, mei_cb_list, list) {
+       list_for_each_entry_safe(cbnext, mei_cb_list, list) {
                /* check if list member associated with a file */
-               if (file == cb_pos->file_object) {
-                       /* remove member from the list */
-                       list_del(&cb_pos->list);
+               if (file == cb->file_object) {
                        /* check if cb equal to current iamthif cb */
-                       if (dev->iamthif_current_cb == cb_pos) {
+                       if (dev->iamthif_current_cb == cb) {
                                dev->iamthif_current_cb = NULL;
                                /* send flow control to iamthif client */
-                               mei_hbm_cl_flow_control_req(dev,
-                                                       &dev->iamthif_cl);
+                               mei_hbm_cl_flow_control_req(dev, cl);
                        }
                        /* free all allocated buffers */
-                       mei_io_cb_free(cb_pos);
-                       cb_pos = NULL;
+                       mei_io_cb_free(cb);
                        removed = true;
                }
        }
index be767f4db26a137bb93043bf448891031428e9fe..4cf38c39878aa1787de6cb36cf2a5c045f01b875 100644 (file)
@@ -238,7 +238,7 @@ static ssize_t ___mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
        dev = cl->dev;
 
        mutex_lock(&dev->device_lock);
-       if (cl->state != MEI_FILE_CONNECTED) {
+       if (!mei_cl_is_connected(cl)) {
                rets = -ENODEV;
                goto out;
        }
@@ -255,17 +255,13 @@ static ssize_t ___mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
                goto out;
        }
 
-       cb = mei_io_cb_init(cl, NULL);
+       cb = mei_cl_alloc_cb(cl, length, MEI_FOP_WRITE, NULL);
        if (!cb) {
                rets = -ENOMEM;
                goto out;
        }
 
-       rets = mei_io_cb_alloc_req_buf(cb, length);
-       if (rets < 0)
-               goto out;
-
-       memcpy(cb->request_buffer.data, buf, length);
+       memcpy(cb->buf.data, buf, length);
 
        rets = mei_cl_write(cl, cb, blocking);
 
@@ -292,20 +288,21 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
 
        mutex_lock(&dev->device_lock);
 
-       if (!cl->read_cb) {
-               rets = mei_cl_read_start(cl, length);
-               if (rets < 0)
-                       goto out;
-       }
+       cb = mei_cl_read_cb(cl, NULL);
+       if (cb)
+               goto copy;
 
-       if (cl->reading_state != MEI_READ_COMPLETE &&
-           !waitqueue_active(&cl->rx_wait)) {
+       rets = mei_cl_read_start(cl, length, NULL);
+       if (rets && rets != -EBUSY)
+               goto out;
+
+       if (list_empty(&cl->rd_completed) && !waitqueue_active(&cl->rx_wait)) {
 
                mutex_unlock(&dev->device_lock);
 
                if (wait_event_interruptible(cl->rx_wait,
-                               cl->reading_state == MEI_READ_COMPLETE  ||
-                               mei_cl_is_transitioning(cl))) {
+                               (!list_empty(&cl->rd_completed)) ||
+                               (!mei_cl_is_connected(cl)))) {
 
                        if (signal_pending(current))
                                return -EINTR;
@@ -313,23 +310,31 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
                }
 
                mutex_lock(&dev->device_lock);
-       }
 
-       cb = cl->read_cb;
+               if (!mei_cl_is_connected(cl)) {
+                       rets = -EBUSY;
+                       goto out;
+               }
+       }
 
-       if (cl->reading_state != MEI_READ_COMPLETE) {
+       cb = mei_cl_read_cb(cl, NULL);
+       if (!cb) {
                rets = 0;
                goto out;
        }
 
+copy:
+       if (cb->status) {
+               rets = cb->status;
+               goto free;
+       }
+
        r_length = min_t(size_t, length, cb->buf_idx);
-       memcpy(buf, cb->response_buffer.data, r_length);
+       memcpy(buf, cb->buf.data, r_length);
        rets = r_length;
 
+free:
        mei_io_cb_free(cb);
-       cl->reading_state = MEI_IDLE;
-       cl->read_cb = NULL;
-
 out:
        mutex_unlock(&dev->device_lock);
 
@@ -386,7 +391,7 @@ static void mei_bus_event_work(struct work_struct *work)
        device->events = 0;
 
        /* Prepare for the next read */
-       mei_cl_read_start(device->cl, 0);
+       mei_cl_read_start(device->cl, 0, NULL);
 }
 
 int mei_cl_register_event_cb(struct mei_cl_device *device,
@@ -400,7 +405,7 @@ int mei_cl_register_event_cb(struct mei_cl_device *device,
        device->event_context = context;
        INIT_WORK(&device->event_work, mei_bus_event_work);
 
-       mei_cl_read_start(device->cl, 0);
+       mei_cl_read_start(device->cl, 0, NULL);
 
        return 0;
 }
@@ -441,8 +446,8 @@ int mei_cl_enable_device(struct mei_cl_device *device)
 
        mutex_unlock(&dev->device_lock);
 
-       if (device->event_cb && !cl->read_cb)
-               mei_cl_read_start(device->cl, 0);
+       if (device->event_cb)
+               mei_cl_read_start(device->cl, 0, NULL);
 
        if (!device->ops || !device->ops->enable)
                return 0;
@@ -462,54 +467,34 @@ int mei_cl_disable_device(struct mei_cl_device *device)
 
        dev = cl->dev;
 
+       if (device->ops && device->ops->disable)
+               device->ops->disable(device);
+
+       device->event_cb = NULL;
+
        mutex_lock(&dev->device_lock);
 
-       if (cl->state != MEI_FILE_CONNECTED) {
-               mutex_unlock(&dev->device_lock);
+       if (!mei_cl_is_connected(cl)) {
                dev_err(dev->dev, "Already disconnected");
-
-               return 0;
+               err = 0;
+               goto out;
        }
 
        cl->state = MEI_FILE_DISCONNECTING;
 
        err = mei_cl_disconnect(cl);
        if (err < 0) {
-               mutex_unlock(&dev->device_lock);
-               dev_err(dev->dev,
-                       "Could not disconnect from the ME client");
-
-               return err;
+               dev_err(dev->dev, "Could not disconnect from the ME client");
+               goto out;
        }
 
        /* Flush queues and remove any pending read */
-       mei_cl_flush_queues(cl);
-
-       if (cl->read_cb) {
-               struct mei_cl_cb *cb = NULL;
-
-               cb = mei_cl_find_read_cb(cl);
-               /* Remove entry from read list */
-               if (cb)
-                       list_del(&cb->list);
-
-               cb = cl->read_cb;
-               cl->read_cb = NULL;
-
-               if (cb) {
-                       mei_io_cb_free(cb);
-                       cb = NULL;
-               }
-       }
-
-       device->event_cb = NULL;
+       mei_cl_flush_queues(cl, NULL);
 
+out:
        mutex_unlock(&dev->device_lock);
+       return err;
 
-       if (!device->ops || !device->ops->disable)
-               return 0;
-
-       return device->ops->disable(device);
 }
 EXPORT_SYMBOL_GPL(mei_cl_disable_device);
 
index dfbddfe1c7a06f9e1ea435ffac42ab31b7a9511c..1e99ef6a54a2b83153e6e6053e45a9a5df85bee9 100644 (file)
@@ -48,14 +48,14 @@ void mei_me_cl_init(struct mei_me_client *me_cl)
  */
 struct mei_me_client *mei_me_cl_get(struct mei_me_client *me_cl)
 {
-       if (me_cl)
-               kref_get(&me_cl->refcnt);
+       if (me_cl && kref_get_unless_zero(&me_cl->refcnt))
+               return me_cl;
 
-       return me_cl;
+       return NULL;
 }
 
 /**
- * mei_me_cl_release - unlink and free me client
+ * mei_me_cl_release - free me client
  *
  * Locking: called under "dev->device_lock" lock
  *
@@ -65,9 +65,10 @@ static void mei_me_cl_release(struct kref *ref)
 {
        struct mei_me_client *me_cl =
                container_of(ref, struct mei_me_client, refcnt);
-       list_del(&me_cl->list);
+
        kfree(me_cl);
 }
+
 /**
  * mei_me_cl_put - decrease me client refcount and free client if necessary
  *
@@ -82,28 +83,87 @@ void mei_me_cl_put(struct mei_me_client *me_cl)
 }
 
 /**
- * mei_me_cl_by_uuid - locate me client by uuid
+ * __mei_me_cl_del  - delete me client form the list and decrease
+ *     reference counter
+ *
+ * @dev: mei device
+ * @me_cl: me client
+ *
+ * Locking: dev->me_clients_rwsem
+ */
+static void __mei_me_cl_del(struct mei_device *dev, struct mei_me_client *me_cl)
+{
+       if (!me_cl)
+               return;
+
+       list_del(&me_cl->list);
+       mei_me_cl_put(me_cl);
+}
+
+/**
+ * mei_me_cl_add - add me client to the list
+ *
+ * @dev: mei device
+ * @me_cl: me client
+ */
+void mei_me_cl_add(struct mei_device *dev, struct mei_me_client *me_cl)
+{
+       down_write(&dev->me_clients_rwsem);
+       list_add(&me_cl->list, &dev->me_clients);
+       up_write(&dev->me_clients_rwsem);
+}
+
+/**
+ * __mei_me_cl_by_uuid - locate me client by uuid
  *     increases ref count
  *
  * @dev: mei device
  * @uuid: me client uuid
  *
- * Locking: called under "dev->device_lock" lock
- *
  * Return: me client or NULL if not found
+ *
+ * Locking: dev->me_clients_rwsem
  */
-struct mei_me_client *mei_me_cl_by_uuid(const struct mei_device *dev,
+static struct mei_me_client *__mei_me_cl_by_uuid(struct mei_device *dev,
                                        const uuid_le *uuid)
 {
        struct mei_me_client *me_cl;
+       const uuid_le *pn;
 
-       list_for_each_entry(me_cl, &dev->me_clients, list)
-               if (uuid_le_cmp(*uuid, me_cl->props.protocol_name) == 0)
+       WARN_ON(!rwsem_is_locked(&dev->me_clients_rwsem));
+
+       list_for_each_entry(me_cl, &dev->me_clients, list) {
+               pn = &me_cl->props.protocol_name;
+               if (uuid_le_cmp(*uuid, *pn) == 0)
                        return mei_me_cl_get(me_cl);
+       }
 
        return NULL;
 }
 
+/**
+ * mei_me_cl_by_uuid - locate me client by uuid
+ *     increases ref count
+ *
+ * @dev: mei device
+ * @uuid: me client uuid
+ *
+ * Return: me client or NULL if not found
+ *
+ * Locking: dev->me_clients_rwsem
+ */
+struct mei_me_client *mei_me_cl_by_uuid(struct mei_device *dev,
+                                       const uuid_le *uuid)
+{
+       struct mei_me_client *me_cl;
+
+       down_read(&dev->me_clients_rwsem);
+       me_cl = __mei_me_cl_by_uuid(dev, uuid);
+       up_read(&dev->me_clients_rwsem);
+
+       return me_cl;
+}
+
 /**
  * mei_me_cl_by_id - locate me client by client id
  *     increases ref count
@@ -111,22 +171,58 @@ struct mei_me_client *mei_me_cl_by_uuid(const struct mei_device *dev,
  * @dev: the device structure
  * @client_id: me client id
  *
- * Locking: called under "dev->device_lock" lock
- *
  * Return: me client or NULL if not found
+ *
+ * Locking: dev->me_clients_rwsem
  */
 struct mei_me_client *mei_me_cl_by_id(struct mei_device *dev, u8 client_id)
 {
 
+       struct mei_me_client *__me_cl, *me_cl = NULL;
+
+       down_read(&dev->me_clients_rwsem);
+       list_for_each_entry(__me_cl, &dev->me_clients, list) {
+               if (__me_cl->client_id == client_id) {
+                       me_cl = mei_me_cl_get(__me_cl);
+                       break;
+               }
+       }
+       up_read(&dev->me_clients_rwsem);
+
+       return me_cl;
+}
+
+/**
+ * __mei_me_cl_by_uuid_id - locate me client by client id and uuid
+ *     increases ref count
+ *
+ * @dev: the device structure
+ * @uuid: me client uuid
+ * @client_id: me client id
+ *
+ * Return: me client or null if not found
+ *
+ * Locking: dev->me_clients_rwsem
+ */
+static struct mei_me_client *__mei_me_cl_by_uuid_id(struct mei_device *dev,
+                                          const uuid_le *uuid, u8 client_id)
+{
        struct mei_me_client *me_cl;
+       const uuid_le *pn;
+
+       WARN_ON(!rwsem_is_locked(&dev->me_clients_rwsem));
 
-       list_for_each_entry(me_cl, &dev->me_clients, list)
-               if (me_cl->client_id == client_id)
+       list_for_each_entry(me_cl, &dev->me_clients, list) {
+               pn = &me_cl->props.protocol_name;
+               if (uuid_le_cmp(*uuid, *pn) == 0 &&
+                   me_cl->client_id == client_id)
                        return mei_me_cl_get(me_cl);
+       }
 
        return NULL;
 }
 
+
 /**
  * mei_me_cl_by_uuid_id - locate me client by client id and uuid
  *     increases ref count
@@ -135,21 +231,18 @@ struct mei_me_client *mei_me_cl_by_id(struct mei_device *dev, u8 client_id)
  * @uuid: me client uuid
  * @client_id: me client id
  *
- * Locking: called under "dev->device_lock" lock
- *
- * Return: me client or NULL if not found
+ * Return: me client or null if not found
  */
 struct mei_me_client *mei_me_cl_by_uuid_id(struct mei_device *dev,
                                           const uuid_le *uuid, u8 client_id)
 {
        struct mei_me_client *me_cl;
 
-       list_for_each_entry(me_cl, &dev->me_clients, list)
-               if (uuid_le_cmp(*uuid, me_cl->props.protocol_name) == 0 &&
-                   me_cl->client_id == client_id)
-                       return mei_me_cl_get(me_cl);
+       down_read(&dev->me_clients_rwsem);
+       me_cl = __mei_me_cl_by_uuid_id(dev, uuid, client_id);
+       up_read(&dev->me_clients_rwsem);
 
-       return NULL;
+       return me_cl;
 }
 
 /**
@@ -162,12 +255,14 @@ struct mei_me_client *mei_me_cl_by_uuid_id(struct mei_device *dev,
  */
 void mei_me_cl_rm_by_uuid(struct mei_device *dev, const uuid_le *uuid)
 {
-       struct mei_me_client *me_cl, *next;
+       struct mei_me_client *me_cl;
 
        dev_dbg(dev->dev, "remove %pUl\n", uuid);
-       list_for_each_entry_safe(me_cl, next, &dev->me_clients, list)
-               if (uuid_le_cmp(*uuid, me_cl->props.protocol_name) == 0)
-                       mei_me_cl_put(me_cl);
+
+       down_write(&dev->me_clients_rwsem);
+       me_cl = __mei_me_cl_by_uuid(dev, uuid);
+       __mei_me_cl_del(dev, me_cl);
+       up_write(&dev->me_clients_rwsem);
 }
 
 /**
@@ -181,15 +276,14 @@ void mei_me_cl_rm_by_uuid(struct mei_device *dev, const uuid_le *uuid)
  */
 void mei_me_cl_rm_by_uuid_id(struct mei_device *dev, const uuid_le *uuid, u8 id)
 {
-       struct mei_me_client *me_cl, *next;
-       const uuid_le *pn;
+       struct mei_me_client *me_cl;
 
        dev_dbg(dev->dev, "remove %pUl %d\n", uuid, id);
-       list_for_each_entry_safe(me_cl, next, &dev->me_clients, list) {
-               pn =  &me_cl->props.protocol_name;
-               if (me_cl->client_id == id && uuid_le_cmp(*uuid, *pn) == 0)
-                       mei_me_cl_put(me_cl);
-       }
+
+       down_write(&dev->me_clients_rwsem);
+       me_cl = __mei_me_cl_by_uuid_id(dev, uuid, id);
+       __mei_me_cl_del(dev, me_cl);
+       up_write(&dev->me_clients_rwsem);
 }
 
 /**
@@ -203,12 +297,12 @@ void mei_me_cl_rm_all(struct mei_device *dev)
 {
        struct mei_me_client *me_cl, *next;
 
+       down_write(&dev->me_clients_rwsem);
        list_for_each_entry_safe(me_cl, next, &dev->me_clients, list)
-                       mei_me_cl_put(me_cl);
+               __mei_me_cl_del(dev, me_cl);
+       up_write(&dev->me_clients_rwsem);
 }
 
-
-
 /**
  * mei_cl_cmp_id - tells if the clients are the same
  *
@@ -227,7 +321,48 @@ static inline bool mei_cl_cmp_id(const struct mei_cl *cl1,
 }
 
 /**
- * mei_io_list_flush - removes cbs belonging to cl.
+ * mei_io_cb_free - free mei_cb_private related memory
+ *
+ * @cb: mei callback struct
+ */
+void mei_io_cb_free(struct mei_cl_cb *cb)
+{
+       if (cb == NULL)
+               return;
+
+       list_del(&cb->list);
+       kfree(cb->buf.data);
+       kfree(cb);
+}
+
+/**
+ * mei_io_cb_init - allocate and initialize io callback
+ *
+ * @cl: mei client
+ * @type: operation type
+ * @fp: pointer to file structure
+ *
+ * Return: mei_cl_cb pointer or NULL;
+ */
+struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, enum mei_cb_file_ops type,
+                                struct file *fp)
+{
+       struct mei_cl_cb *cb;
+
+       cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
+       if (!cb)
+               return NULL;
+
+       INIT_LIST_HEAD(&cb->list);
+       cb->file_object = fp;
+       cb->cl = cl;
+       cb->buf_idx = 0;
+       cb->fop_type = type;
+       return cb;
+}
+
+/**
+ * __mei_io_list_flush - removes and frees cbs belonging to cl.
  *
  * @list:  an instance of our list structure
  * @cl:    host client, can be NULL for flushing the whole list
@@ -236,13 +371,12 @@ static inline bool mei_cl_cmp_id(const struct mei_cl *cl1,
 static void __mei_io_list_flush(struct mei_cl_cb *list,
                                struct mei_cl *cl, bool free)
 {
-       struct mei_cl_cb *cb;
-       struct mei_cl_cb *next;
+       struct mei_cl_cb *cb, *next;
 
        /* enable removing everything if no cl is specified */
        list_for_each_entry_safe(cb, next, &list->list, list) {
                if (!cl || mei_cl_cmp_id(cl, cb->cl)) {
-                       list_del(&cb->list);
+                       list_del_init(&cb->list);
                        if (free)
                                mei_io_cb_free(cb);
                }
@@ -260,7 +394,6 @@ void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl)
        __mei_io_list_flush(list, cl, false);
 }
 
-
 /**
  * mei_io_list_free - removes cb belonging to cl and free them
  *
@@ -273,103 +406,107 @@ static inline void mei_io_list_free(struct mei_cl_cb *list, struct mei_cl *cl)
 }
 
 /**
- * mei_io_cb_free - free mei_cb_private related memory
+ * mei_io_cb_alloc_buf - allocate callback buffer
  *
- * @cb: mei callback struct
+ * @cb: io callback structure
+ * @length: size of the buffer
+ *
+ * Return: 0 on success
+ *         -EINVAL if cb is NULL
+ *         -ENOMEM if allocation failed
  */
-void mei_io_cb_free(struct mei_cl_cb *cb)
+int mei_io_cb_alloc_buf(struct mei_cl_cb *cb, size_t length)
 {
-       if (cb == NULL)
-               return;
+       if (!cb)
+               return -EINVAL;
 
-       kfree(cb->request_buffer.data);
-       kfree(cb->response_buffer.data);
-       kfree(cb);
+       if (length == 0)
+               return 0;
+
+       cb->buf.data = kmalloc(length, GFP_KERNEL);
+       if (!cb->buf.data)
+               return -ENOMEM;
+       cb->buf.size = length;
+       return 0;
 }
 
 /**
- * mei_io_cb_init - allocate and initialize io callback
+ * mei_cl_alloc_cb - a convenient wrapper for allocating read cb
  *
- * @cl: mei client
- * @fp: pointer to file structure
+ * @cl: host client
+ * @length: size of the buffer
+ * @type: operation type
+ * @fp: associated file pointer (might be NULL)
  *
- * Return: mei_cl_cb pointer or NULL;
+ * Return: cb on success and NULL on failure
  */
-struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, struct file *fp)
+struct mei_cl_cb *mei_cl_alloc_cb(struct mei_cl *cl, size_t length,
+                                 enum mei_cb_file_ops type, struct file *fp)
 {
        struct mei_cl_cb *cb;
 
-       cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
+       cb = mei_io_cb_init(cl, type, fp);
        if (!cb)
                return NULL;
 
-       mei_io_list_init(cb);
+       if (mei_io_cb_alloc_buf(cb, length)) {
+               mei_io_cb_free(cb);
+               return NULL;
+       }
 
-       cb->file_object = fp;
-       cb->cl = cl;
-       cb->buf_idx = 0;
        return cb;
 }
 
 /**
- * mei_io_cb_alloc_req_buf - allocate request buffer
+ * mei_cl_read_cb - find this cl's callback in the read list
+ *     for a specific file
  *
- * @cb: io callback structure
- * @length: size of the buffer
+ * @cl: host client
+ * @fp: file pointer (matching cb file object), may be NULL
  *
- * Return: 0 on success
- *         -EINVAL if cb is NULL
- *         -ENOMEM if allocation failed
+ * Return: cb on success, NULL if cb is not found
  */
-int mei_io_cb_alloc_req_buf(struct mei_cl_cb *cb, size_t length)
+struct mei_cl_cb *mei_cl_read_cb(const struct mei_cl *cl, const struct file *fp)
 {
-       if (!cb)
-               return -EINVAL;
+       struct mei_cl_cb *cb;
 
-       if (length == 0)
-               return 0;
+       list_for_each_entry(cb, &cl->rd_completed, list)
+               if (!fp || fp == cb->file_object)
+                       return cb;
 
-       cb->request_buffer.data = kmalloc(length, GFP_KERNEL);
-       if (!cb->request_buffer.data)
-               return -ENOMEM;
-       cb->request_buffer.size = length;
-       return 0;
+       return NULL;
 }
+
 /**
- * mei_io_cb_alloc_resp_buf - allocate response buffer
- *
- * @cb: io callback structure
- * @length: size of the buffer
+ * mei_cl_read_cb_flush - free client's read pending and completed cbs
+ *   for a specific file
  *
- * Return: 0 on success
- *         -EINVAL if cb is NULL
- *         -ENOMEM if allocation failed
+ * @cl: host client
+ * @fp: file pointer (matching cb file object), may be NULL
  */
-int mei_io_cb_alloc_resp_buf(struct mei_cl_cb *cb, size_t length)
+void mei_cl_read_cb_flush(const struct mei_cl *cl, const struct file *fp)
 {
-       if (!cb)
-               return -EINVAL;
+       struct mei_cl_cb *cb, *next;
 
-       if (length == 0)
-               return 0;
-
-       cb->response_buffer.data = kmalloc(length, GFP_KERNEL);
-       if (!cb->response_buffer.data)
-               return -ENOMEM;
-       cb->response_buffer.size = length;
-       return 0;
-}
+       list_for_each_entry_safe(cb, next, &cl->rd_completed, list)
+               if (!fp || fp == cb->file_object)
+                       mei_io_cb_free(cb);
 
 
+       list_for_each_entry_safe(cb, next, &cl->rd_pending, list)
+               if (!fp || fp == cb->file_object)
+                       mei_io_cb_free(cb);
+}
 
 /**
  * mei_cl_flush_queues - flushes queue lists belonging to cl.
  *
  * @cl: host client
+ * @fp: file pointer (matching cb file object), may be NULL
  *
  * Return: 0 on success, -EINVAL if cl or cl->dev is NULL.
  */
-int mei_cl_flush_queues(struct mei_cl *cl)
+int mei_cl_flush_queues(struct mei_cl *cl, const struct file *fp)
 {
        struct mei_device *dev;
 
@@ -379,13 +516,15 @@ int mei_cl_flush_queues(struct mei_cl *cl)
        dev = cl->dev;
 
        cl_dbg(dev, cl, "remove list entry belonging to cl\n");
-       mei_io_list_flush(&cl->dev->read_list, cl);
        mei_io_list_free(&cl->dev->write_list, cl);
        mei_io_list_free(&cl->dev->write_waiting_list, cl);
        mei_io_list_flush(&cl->dev->ctrl_wr_list, cl);
        mei_io_list_flush(&cl->dev->ctrl_rd_list, cl);
        mei_io_list_flush(&cl->dev->amthif_cmd_list, cl);
        mei_io_list_flush(&cl->dev->amthif_rd_complete_list, cl);
+
+       mei_cl_read_cb_flush(cl, fp);
+
        return 0;
 }
 
@@ -402,9 +541,10 @@ void mei_cl_init(struct mei_cl *cl, struct mei_device *dev)
        init_waitqueue_head(&cl->wait);
        init_waitqueue_head(&cl->rx_wait);
        init_waitqueue_head(&cl->tx_wait);
+       INIT_LIST_HEAD(&cl->rd_completed);
+       INIT_LIST_HEAD(&cl->rd_pending);
        INIT_LIST_HEAD(&cl->link);
        INIT_LIST_HEAD(&cl->device_link);
-       cl->reading_state = MEI_IDLE;
        cl->writing_state = MEI_IDLE;
        cl->dev = dev;
 }
@@ -429,31 +569,14 @@ struct mei_cl *mei_cl_allocate(struct mei_device *dev)
 }
 
 /**
- * mei_cl_find_read_cb - find this cl's callback in the read list
+ * mei_cl_link - allocate host id in the host map
  *
  * @cl: host client
- *
- * Return: cb on success, NULL on error
- */
-struct mei_cl_cb *mei_cl_find_read_cb(struct mei_cl *cl)
-{
-       struct mei_device *dev = cl->dev;
-       struct mei_cl_cb *cb;
-
-       list_for_each_entry(cb, &dev->read_list.list, list)
-               if (mei_cl_cmp_id(cl, cb->cl))
-                       return cb;
-       return NULL;
-}
-
-/** mei_cl_link: allocate host id in the host map
- *
- * @cl - host client
- * @id - fixed host id or -1 for generic one
+ * @id: fixed host id or MEI_HOST_CLIENT_ID_ANY (-1) for generic one
  *
  * Return: 0 on success
  *     -EINVAL on incorrect values
- *     -ENONET if client not found
+ *     -EMFILE if open count exceeded.
  */
 int mei_cl_link(struct mei_cl *cl, int id)
 {
@@ -535,28 +658,31 @@ int mei_cl_unlink(struct mei_cl *cl)
 
 void mei_host_client_init(struct work_struct *work)
 {
-       struct mei_device *dev = container_of(work,
-                                             struct mei_device, init_work);
+       struct mei_device *dev =
+               container_of(work, struct mei_device, init_work);
        struct mei_me_client *me_cl;
-       struct mei_client_properties *props;
 
        mutex_lock(&dev->device_lock);
 
-       list_for_each_entry(me_cl, &dev->me_clients, list) {
-               props = &me_cl->props;
 
-               if (!uuid_le_cmp(props->protocol_name, mei_amthif_guid))
-                       mei_amthif_host_init(dev);
-               else if (!uuid_le_cmp(props->protocol_name, mei_wd_guid))
-                       mei_wd_host_init(dev);
-               else if (!uuid_le_cmp(props->protocol_name, mei_nfc_guid))
-                       mei_nfc_host_init(dev);
+       me_cl = mei_me_cl_by_uuid(dev, &mei_amthif_guid);
+       if (me_cl)
+               mei_amthif_host_init(dev);
+       mei_me_cl_put(me_cl);
+
+       me_cl = mei_me_cl_by_uuid(dev, &mei_wd_guid);
+       if (me_cl)
+               mei_wd_host_init(dev);
+       mei_me_cl_put(me_cl);
+
+       me_cl = mei_me_cl_by_uuid(dev, &mei_nfc_guid);
+       if (me_cl)
+               mei_nfc_host_init(dev);
+       mei_me_cl_put(me_cl);
 
-       }
 
        dev->dev_state = MEI_DEV_ENABLED;
        dev->reset_count = 0;
-
        mutex_unlock(&dev->device_lock);
 
        pm_runtime_mark_last_busy(dev->dev);
@@ -620,13 +746,10 @@ int mei_cl_disconnect(struct mei_cl *cl)
                return rets;
        }
 
-       cb = mei_io_cb_init(cl, NULL);
-       if (!cb) {
-               rets = -ENOMEM;
+       cb = mei_io_cb_init(cl, MEI_FOP_DISCONNECT, NULL);
+       rets = cb ? 0 : -ENOMEM;
+       if (rets)
                goto free;
-       }
-
-       cb->fop_type = MEI_FOP_DISCONNECT;
 
        if (mei_hbuf_acquire(dev)) {
                if (mei_hbm_cl_disconnect_req(dev, cl)) {
@@ -727,13 +850,10 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file)
                return rets;
        }
 
-       cb = mei_io_cb_init(cl, file);
-       if (!cb) {
-               rets = -ENOMEM;
+       cb = mei_io_cb_init(cl, MEI_FOP_CONNECT, file);
+       rets = cb ? 0 : -ENOMEM;
+       if (rets)
                goto out;
-       }
-
-       cb->fop_type = MEI_FOP_CONNECT;
 
        /* run hbuf acquire last so we don't have to undo */
        if (!mei_cl_is_other_connecting(cl) && mei_hbuf_acquire(dev)) {
@@ -756,7 +876,7 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file)
                        mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
        mutex_lock(&dev->device_lock);
 
-       if (cl->state != MEI_FILE_CONNECTED) {
+       if (!mei_cl_is_connected(cl)) {
                cl->state = MEI_FILE_DISCONNECTED;
                /* something went really wrong */
                if (!cl->status)
@@ -777,6 +897,37 @@ out:
        return rets;
 }
 
+/**
+ * mei_cl_alloc_linked - allocate and link host client
+ *
+ * @dev: the device structure
+ * @id: fixed host id or MEI_HOST_CLIENT_ID_ANY (-1) for generic one
+ *
+ * Return: cl on success ERR_PTR on failure
+ */
+struct mei_cl *mei_cl_alloc_linked(struct mei_device *dev, int id)
+{
+       struct mei_cl *cl;
+       int ret;
+
+       cl = mei_cl_allocate(dev);
+       if (!cl) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       ret = mei_cl_link(cl, id);
+       if (ret)
+               goto err;
+
+       return cl;
+err:
+       kfree(cl);
+       return ERR_PTR(ret);
+}
+
+
+
 /**
  * mei_cl_flow_ctrl_creds - checks flow_control credits for cl.
  *
@@ -866,10 +1017,11 @@ out:
  *
  * @cl: host client
  * @length: number of bytes to read
+ * @fp: pointer to file structure
  *
  * Return: 0 on success, <0 on failure.
  */
-int mei_cl_read_start(struct mei_cl *cl, size_t length)
+int mei_cl_read_start(struct mei_cl *cl, size_t length, struct file *fp)
 {
        struct mei_device *dev;
        struct mei_cl_cb *cb;
@@ -884,10 +1036,10 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length)
        if (!mei_cl_is_connected(cl))
                return -ENODEV;
 
-       if (cl->read_cb) {
-               cl_dbg(dev, cl, "read is pending.\n");
+       /* HW currently supports only one pending read */
+       if (!list_empty(&cl->rd_pending))
                return -EBUSY;
-       }
+
        me_cl = mei_me_cl_by_uuid_id(dev, &cl->cl_uuid, cl->me_client_id);
        if (!me_cl) {
                cl_err(dev, cl, "no such me client %d\n", cl->me_client_id);
@@ -904,29 +1056,21 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length)
                return rets;
        }
 
-       cb = mei_io_cb_init(cl, NULL);
-       if (!cb) {
-               rets = -ENOMEM;
-               goto out;
-       }
-
-       rets = mei_io_cb_alloc_resp_buf(cb, length);
+       cb = mei_cl_alloc_cb(cl, length, MEI_FOP_READ, fp);
+       rets = cb ? 0 : -ENOMEM;
        if (rets)
                goto out;
 
-       cb->fop_type = MEI_FOP_READ;
        if (mei_hbuf_acquire(dev)) {
                rets = mei_hbm_cl_flow_control_req(dev, cl);
                if (rets < 0)
                        goto out;
 
-               list_add_tail(&cb->list, &dev->read_list.list);
+               list_add_tail(&cb->list, &cl->rd_pending);
        } else {
                list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
        }
 
-       cl->read_cb = cb;
-
 out:
        cl_dbg(dev, cl, "rpm: autosuspend\n");
        pm_runtime_mark_last_busy(dev->dev);
@@ -964,7 +1108,7 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
 
        dev = cl->dev;
 
-       buf = &cb->request_buffer;
+       buf = &cb->buf;
 
        rets = mei_cl_flow_ctrl_creds(cl);
        if (rets < 0)
@@ -999,7 +1143,7 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
        }
 
        cl_dbg(dev, cl, "buf: size = %d idx = %lu\n",
-                       cb->request_buffer.size, cb->buf_idx);
+                       cb->buf.size, cb->buf_idx);
 
        rets = mei_write_message(dev, &mei_hdr, buf->data + cb->buf_idx);
        if (rets) {
@@ -1011,6 +1155,7 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
        cl->status = 0;
        cl->writing_state = MEI_WRITING;
        cb->buf_idx += mei_hdr.length;
+       cb->completed = mei_hdr.msg_complete == 1;
 
        if (mei_hdr.msg_complete) {
                if (mei_cl_flow_ctrl_reduce(cl))
@@ -1048,7 +1193,7 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
        dev = cl->dev;
 
 
-       buf = &cb->request_buffer;
+       buf = &cb->buf;
 
        cl_dbg(dev, cl, "size=%d\n", buf->size);
 
@@ -1059,7 +1204,6 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
                return rets;
        }
 
-       cb->fop_type = MEI_FOP_WRITE;
        cb->buf_idx = 0;
        cl->writing_state = MEI_IDLE;
 
@@ -1099,6 +1243,7 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
 
        cl->writing_state = MEI_WRITING;
        cb->buf_idx = mei_hdr.length;
+       cb->completed = mei_hdr.msg_complete == 1;
 
 out:
        if (mei_hdr.msg_complete) {
@@ -1151,11 +1296,10 @@ void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb)
                if (waitqueue_active(&cl->tx_wait))
                        wake_up_interruptible(&cl->tx_wait);
 
-       } else if (cb->fop_type == MEI_FOP_READ &&
-                       MEI_READING == cl->reading_state) {
-               cl->reading_state = MEI_READ_COMPLETE;
+       } else if (cb->fop_type == MEI_FOP_READ) {
+               list_add_tail(&cb->list, &cl->rd_completed);
                if (waitqueue_active(&cl->rx_wait))
-                       wake_up_interruptible(&cl->rx_wait);
+                       wake_up_interruptible_all(&cl->rx_wait);
                else
                        mei_cl_bus_rx_event(cl);
 
index cfcde8e97fc489a3e0ba966d06def8f1fde2c0c4..0a39e5d45171855a642c2bca7d550a223fe94cd7 100644 (file)
@@ -31,7 +31,10 @@ void mei_me_cl_init(struct mei_me_client *me_cl);
 void mei_me_cl_put(struct mei_me_client *me_cl);
 struct mei_me_client *mei_me_cl_get(struct mei_me_client *me_cl);
 
-struct mei_me_client *mei_me_cl_by_uuid(const struct mei_device *dev,
+void mei_me_cl_add(struct mei_device *dev, struct mei_me_client *me_cl);
+void mei_me_cl_del(struct mei_device *dev, struct mei_me_client *me_cl);
+
+struct mei_me_client *mei_me_cl_by_uuid(struct mei_device *dev,
                                        const uuid_le *uuid);
 struct mei_me_client *mei_me_cl_by_id(struct mei_device *dev, u8 client_id);
 struct mei_me_client *mei_me_cl_by_uuid_id(struct mei_device *dev,
@@ -44,10 +47,10 @@ void mei_me_cl_rm_all(struct mei_device *dev);
 /*
  * MEI IO Functions
  */
-struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, struct file *fp);
+struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, enum mei_cb_file_ops type,
+                                struct file *fp);
 void mei_io_cb_free(struct mei_cl_cb *priv_cb);
-int mei_io_cb_alloc_req_buf(struct mei_cl_cb *cb, size_t length);
-int mei_io_cb_alloc_resp_buf(struct mei_cl_cb *cb, size_t length);
+int mei_io_cb_alloc_buf(struct mei_cl_cb *cb, size_t length);
 
 
 /**
@@ -72,9 +75,14 @@ void mei_cl_init(struct mei_cl *cl, struct mei_device *dev);
 int mei_cl_link(struct mei_cl *cl, int id);
 int mei_cl_unlink(struct mei_cl *cl);
 
-int mei_cl_flush_queues(struct mei_cl *cl);
-struct mei_cl_cb *mei_cl_find_read_cb(struct mei_cl *cl);
+struct mei_cl *mei_cl_alloc_linked(struct mei_device *dev, int id);
 
+struct mei_cl_cb *mei_cl_read_cb(const struct mei_cl *cl,
+                                const struct file *fp);
+void mei_cl_read_cb_flush(const struct mei_cl *cl, const struct file *fp);
+struct mei_cl_cb *mei_cl_alloc_cb(struct mei_cl *cl, size_t length,
+                                 enum mei_cb_file_ops type, struct file *fp);
+int mei_cl_flush_queues(struct mei_cl *cl, const struct file *fp);
 
 int mei_cl_flow_ctrl_creds(struct mei_cl *cl);
 
@@ -82,23 +90,25 @@ int mei_cl_flow_ctrl_reduce(struct mei_cl *cl);
 /*
  *  MEI input output function prototype
  */
+
+/**
+ * mei_cl_is_connected - host client is connected
+ *
+ * @cl: host clinet
+ *
+ * Return: true if the host clinet is connected
+ */
 static inline bool mei_cl_is_connected(struct mei_cl *cl)
 {
-       return  cl->dev &&
-               cl->dev->dev_state == MEI_DEV_ENABLED &&
-               cl->state == MEI_FILE_CONNECTED;
-}
-static inline bool mei_cl_is_transitioning(struct mei_cl *cl)
-{
-       return  MEI_FILE_INITIALIZING == cl->state ||
-               MEI_FILE_DISCONNECTED == cl->state ||
-               MEI_FILE_DISCONNECTING == cl->state;
+       return  cl->state == MEI_FILE_CONNECTED;
 }
 
 bool mei_cl_is_other_connecting(struct mei_cl *cl);
 int mei_cl_disconnect(struct mei_cl *cl);
 int mei_cl_connect(struct mei_cl *cl, struct file *file);
-int mei_cl_read_start(struct mei_cl *cl, size_t length);
+int mei_cl_read_start(struct mei_cl *cl, size_t length, struct file *fp);
+int mei_cl_irq_read_msg(struct mei_cl *cl, struct mei_msg_hdr *hdr,
+                       struct mei_cl_cb *cmpl_list);
 int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking);
 int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
                     struct mei_cl_cb *cmpl_list);
index b125380ee8710162923bc246e0712bfca6d92690..d9cd7e6ee48466acf4afcbbb19b2655ca3eb3439 100644 (file)
@@ -28,7 +28,7 @@ static ssize_t mei_dbgfs_read_meclients(struct file *fp, char __user *ubuf,
                                        size_t cnt, loff_t *ppos)
 {
        struct mei_device *dev = fp->private_data;
-       struct mei_me_client *me_cl, *n;
+       struct mei_me_client *me_cl;
        size_t bufsz = 1;
        char *buf;
        int i = 0;
@@ -38,15 +38,14 @@ static ssize_t mei_dbgfs_read_meclients(struct file *fp, char __user *ubuf,
 #define HDR \
 "  |id|fix|         UUID                       |con|msg len|sb|refc|\n"
 
-       mutex_lock(&dev->device_lock);
-
+       down_read(&dev->me_clients_rwsem);
        list_for_each_entry(me_cl, &dev->me_clients, list)
                bufsz++;
 
        bufsz *= sizeof(HDR) + 1;
        buf = kzalloc(bufsz, GFP_KERNEL);
        if (!buf) {
-               mutex_unlock(&dev->device_lock);
+               up_read(&dev->me_clients_rwsem);
                return -ENOMEM;
        }
 
@@ -56,10 +55,9 @@ static ssize_t mei_dbgfs_read_meclients(struct file *fp, char __user *ubuf,
        if (dev->dev_state != MEI_DEV_ENABLED)
                goto out;
 
-       list_for_each_entry_safe(me_cl, n, &dev->me_clients, list) {
+       list_for_each_entry(me_cl, &dev->me_clients, list) {
 
-               me_cl = mei_me_cl_get(me_cl);
-               if (me_cl) {
+               if (mei_me_cl_get(me_cl)) {
                        pos += scnprintf(buf + pos, bufsz - pos,
                                "%2d|%2d|%3d|%pUl|%3d|%7d|%2d|%4d|\n",
                                i++, me_cl->client_id,
@@ -69,12 +67,13 @@ static ssize_t mei_dbgfs_read_meclients(struct file *fp, char __user *ubuf,
                                me_cl->props.max_msg_length,
                                me_cl->props.single_recv_buf,
                                atomic_read(&me_cl->refcnt.refcount));
-               }
 
-               mei_me_cl_put(me_cl);
+                       mei_me_cl_put(me_cl);
+               }
        }
+
 out:
-       mutex_unlock(&dev->device_lock);
+       up_read(&dev->me_clients_rwsem);
        ret = simple_read_from_buffer(ubuf, cnt, ppos, buf, pos);
        kfree(buf);
        return ret;
@@ -118,7 +117,7 @@ static ssize_t mei_dbgfs_read_active(struct file *fp, char __user *ubuf,
                pos += scnprintf(buf + pos, bufsz - pos,
                        "%2d|%2d|%4d|%5d|%2d|%2d|\n",
                        i, cl->me_client_id, cl->host_client_id, cl->state,
-                       cl->reading_state, cl->writing_state);
+                       !list_empty(&cl->rd_completed), cl->writing_state);
                i++;
        }
 out:
index c8412d41e4f163410b771dfcdd7126f201f3e937..58da92565c5ed332aca5101d7930722a759f4f31 100644 (file)
@@ -338,7 +338,8 @@ static int mei_hbm_me_cl_add(struct mei_device *dev,
        me_cl->client_id = res->me_addr;
        me_cl->mei_flow_ctrl_creds = 0;
 
-       list_add(&me_cl->list, &dev->me_clients);
+       mei_me_cl_add(dev, me_cl);
+
        return 0;
 }
 
@@ -638,7 +639,7 @@ static void mei_hbm_cl_res(struct mei_device *dev,
                        continue;
 
                if (mei_hbm_cl_addr_equal(cl, rs)) {
-                       list_del(&cb->list);
+                       list_del_init(&cb->list);
                        break;
                }
        }
@@ -683,10 +684,9 @@ static int mei_hbm_fw_disconnect_req(struct mei_device *dev,
                cl->state = MEI_FILE_DISCONNECTED;
                cl->timer_count = 0;
 
-               cb = mei_io_cb_init(cl, NULL);
+               cb = mei_io_cb_init(cl, MEI_FOP_DISCONNECT_RSP, NULL);
                if (!cb)
                        return -ENOMEM;
-               cb->fop_type = MEI_FOP_DISCONNECT_RSP;
                cl_dbg(dev, cl, "add disconnect response as first\n");
                list_add(&cb->list, &dev->ctrl_wr_list.list);
        }
index f8fd503dfbd69b09cc192c655127cf9aeb950e77..6fb75e62a764c5af4f57fbbe79340d91d6e1e8ed 100644 (file)
@@ -25,6 +25,8 @@
 #include "hw-me.h"
 #include "hw-me-regs.h"
 
+#include "mei-trace.h"
+
 /**
  * mei_me_reg_read - Reads 32bit data from the mei device
  *
@@ -61,45 +63,79 @@ static inline void mei_me_reg_write(const struct mei_me_hw *hw,
  *
  * Return: ME_CB_RW register value (u32)
  */
-static u32 mei_me_mecbrw_read(const struct mei_device *dev)
+static inline u32 mei_me_mecbrw_read(const struct mei_device *dev)
 {
        return mei_me_reg_read(to_me_hw(dev), ME_CB_RW);
 }
+
+/**
+ * mei_me_hcbww_write - write 32bit data to the host circular buffer
+ *
+ * @dev: the device structure
+ * @data: 32bit data to be written to the host circular buffer
+ */
+static inline void mei_me_hcbww_write(struct mei_device *dev, u32 data)
+{
+       mei_me_reg_write(to_me_hw(dev), H_CB_WW, data);
+}
+
 /**
  * mei_me_mecsr_read - Reads 32bit data from the ME CSR
  *
- * @hw: the me hardware structure
+ * @dev: the device structure
  *
  * Return: ME_CSR_HA register value (u32)
  */
-static inline u32 mei_me_mecsr_read(const struct mei_me_hw *hw)
+static inline u32 mei_me_mecsr_read(const struct mei_device *dev)
 {
-       return mei_me_reg_read(hw, ME_CSR_HA);
+       u32 reg;
+
+       reg = mei_me_reg_read(to_me_hw(dev), ME_CSR_HA);
+       trace_mei_reg_read(dev->dev, "ME_CSR_HA", ME_CSR_HA, reg);
+
+       return reg;
 }
 
 /**
  * mei_hcsr_read - Reads 32bit data from the host CSR
  *
- * @hw: the me hardware structure
+ * @dev: the device structure
  *
  * Return: H_CSR register value (u32)
  */
-static inline u32 mei_hcsr_read(const struct mei_me_hw *hw)
+static inline u32 mei_hcsr_read(const struct mei_device *dev)
+{
+       u32 reg;
+
+       reg = mei_me_reg_read(to_me_hw(dev), H_CSR);
+       trace_mei_reg_read(dev->dev, "H_CSR", H_CSR, reg);
+
+       return reg;
+}
+
+/**
+ * mei_hcsr_write - writes H_CSR register to the mei device
+ *
+ * @dev: the device structure
+ * @reg: new register value
+ */
+static inline void mei_hcsr_write(struct mei_device *dev, u32 reg)
 {
-       return mei_me_reg_read(hw, H_CSR);
+       trace_mei_reg_write(dev->dev, "H_CSR", H_CSR, reg);
+       mei_me_reg_write(to_me_hw(dev), H_CSR, reg);
 }
 
 /**
  * mei_hcsr_set - writes H_CSR register to the mei device,
  * and ignores the H_IS bit for it is write-one-to-zero.
  *
- * @hw: the me hardware structure
- * @hcsr: new register value
+ * @dev: the device structure
+ * @reg: new register value
  */
-static inline void mei_hcsr_set(struct mei_me_hw *hw, u32 hcsr)
+static inline void mei_hcsr_set(struct mei_device *dev, u32 reg)
 {
-       hcsr &= ~H_IS;
-       mei_me_reg_write(hw, H_CSR, hcsr);
+       reg &= ~H_IS;
+       mei_hcsr_write(dev, reg);
 }
 
 /**
@@ -141,7 +177,7 @@ static int mei_me_fw_status(struct mei_device *dev,
 static void mei_me_hw_config(struct mei_device *dev)
 {
        struct mei_me_hw *hw = to_me_hw(dev);
-       u32 hcsr = mei_hcsr_read(to_me_hw(dev));
+       u32 hcsr = mei_hcsr_read(dev);
        /* Doesn't change in runtime */
        dev->hbuf_depth = (hcsr & H_CBD) >> 24;
 
@@ -170,11 +206,10 @@ static inline enum mei_pg_state mei_me_pg_state(struct mei_device *dev)
  */
 static void mei_me_intr_clear(struct mei_device *dev)
 {
-       struct mei_me_hw *hw = to_me_hw(dev);
-       u32 hcsr = mei_hcsr_read(hw);
+       u32 hcsr = mei_hcsr_read(dev);
 
        if ((hcsr & H_IS) == H_IS)
-               mei_me_reg_write(hw, H_CSR, hcsr);
+               mei_hcsr_write(dev, hcsr);
 }
 /**
  * mei_me_intr_enable - enables mei device interrupts
@@ -183,11 +218,10 @@ static void mei_me_intr_clear(struct mei_device *dev)
  */
 static void mei_me_intr_enable(struct mei_device *dev)
 {
-       struct mei_me_hw *hw = to_me_hw(dev);
-       u32 hcsr = mei_hcsr_read(hw);
+       u32 hcsr = mei_hcsr_read(dev);
 
        hcsr |= H_IE;
-       mei_hcsr_set(hw, hcsr);
+       mei_hcsr_set(dev, hcsr);
 }
 
 /**
@@ -197,11 +231,10 @@ static void mei_me_intr_enable(struct mei_device *dev)
  */
 static void mei_me_intr_disable(struct mei_device *dev)
 {
-       struct mei_me_hw *hw = to_me_hw(dev);
-       u32 hcsr = mei_hcsr_read(hw);
+       u32 hcsr = mei_hcsr_read(dev);
 
        hcsr  &= ~H_IE;
-       mei_hcsr_set(hw, hcsr);
+       mei_hcsr_set(dev, hcsr);
 }
 
 /**
@@ -211,12 +244,11 @@ static void mei_me_intr_disable(struct mei_device *dev)
  */
 static void mei_me_hw_reset_release(struct mei_device *dev)
 {
-       struct mei_me_hw *hw = to_me_hw(dev);
-       u32 hcsr = mei_hcsr_read(hw);
+       u32 hcsr = mei_hcsr_read(dev);
 
        hcsr |= H_IG;
        hcsr &= ~H_RST;
-       mei_hcsr_set(hw, hcsr);
+       mei_hcsr_set(dev, hcsr);
 
        /* complete this write before we set host ready on another CPU */
        mmiowb();
@@ -231,8 +263,7 @@ static void mei_me_hw_reset_release(struct mei_device *dev)
  */
 static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
 {
-       struct mei_me_hw *hw = to_me_hw(dev);
-       u32 hcsr = mei_hcsr_read(hw);
+       u32 hcsr = mei_hcsr_read(dev);
 
        /* H_RST may be found lit before reset is started,
         * for example if preceding reset flow hasn't completed.
@@ -242,8 +273,8 @@ static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
        if ((hcsr & H_RST) == H_RST) {
                dev_warn(dev->dev, "H_RST is set = 0x%08X", hcsr);
                hcsr &= ~H_RST;
-               mei_hcsr_set(hw, hcsr);
-               hcsr = mei_hcsr_read(hw);
+               mei_hcsr_set(dev, hcsr);
+               hcsr = mei_hcsr_read(dev);
        }
 
        hcsr |= H_RST | H_IG | H_IS;
@@ -254,13 +285,13 @@ static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
                hcsr &= ~H_IE;
 
        dev->recvd_hw_ready = false;
-       mei_me_reg_write(hw, H_CSR, hcsr);
+       mei_hcsr_write(dev, hcsr);
 
        /*
         * Host reads the H_CSR once to ensure that the
         * posted write to H_CSR completes.
         */
-       hcsr = mei_hcsr_read(hw);
+       hcsr = mei_hcsr_read(dev);
 
        if ((hcsr & H_RST) == 0)
                dev_warn(dev->dev, "H_RST is not set = 0x%08X", hcsr);
@@ -281,11 +312,10 @@ static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
  */
 static void mei_me_host_set_ready(struct mei_device *dev)
 {
-       struct mei_me_hw *hw = to_me_hw(dev);
-       u32 hcsr = mei_hcsr_read(hw);
+       u32 hcsr = mei_hcsr_read(dev);
 
        hcsr |= H_IE | H_IG | H_RDY;
-       mei_hcsr_set(hw, hcsr);
+       mei_hcsr_set(dev, hcsr);
 }
 
 /**
@@ -296,8 +326,7 @@ static void mei_me_host_set_ready(struct mei_device *dev)
  */
 static bool mei_me_host_is_ready(struct mei_device *dev)
 {
-       struct mei_me_hw *hw = to_me_hw(dev);
-       u32 hcsr = mei_hcsr_read(hw);
+       u32 hcsr = mei_hcsr_read(dev);
 
        return (hcsr & H_RDY) == H_RDY;
 }
@@ -310,8 +339,7 @@ static bool mei_me_host_is_ready(struct mei_device *dev)
  */
 static bool mei_me_hw_is_ready(struct mei_device *dev)
 {
-       struct mei_me_hw *hw = to_me_hw(dev);
-       u32 mecsr = mei_me_mecsr_read(hw);
+       u32 mecsr = mei_me_mecsr_read(dev);
 
        return (mecsr & ME_RDY_HRA) == ME_RDY_HRA;
 }
@@ -368,11 +396,10 @@ static int mei_me_hw_start(struct mei_device *dev)
  */
 static unsigned char mei_hbuf_filled_slots(struct mei_device *dev)
 {
-       struct mei_me_hw *hw = to_me_hw(dev);
        u32 hcsr;
        char read_ptr, write_ptr;
 
-       hcsr = mei_hcsr_read(hw);
+       hcsr = mei_hcsr_read(dev);
 
        read_ptr = (char) ((hcsr & H_CBRP) >> 8);
        write_ptr = (char) ((hcsr & H_CBWP) >> 16);
@@ -439,7 +466,6 @@ static int mei_me_write_message(struct mei_device *dev,
                        struct mei_msg_hdr *header,
                        unsigned char *buf)
 {
-       struct mei_me_hw *hw = to_me_hw(dev);
        unsigned long rem;
        unsigned long length = header->length;
        u32 *reg_buf = (u32 *)buf;
@@ -457,21 +483,21 @@ static int mei_me_write_message(struct mei_device *dev,
        if (empty_slots < 0 || dw_cnt > empty_slots)
                return -EMSGSIZE;
 
-       mei_me_reg_write(hw, H_CB_WW, *((u32 *) header));
+       mei_me_hcbww_write(dev, *((u32 *) header));
 
        for (i = 0; i < length / 4; i++)
-               mei_me_reg_write(hw, H_CB_WW, reg_buf[i]);
+               mei_me_hcbww_write(dev, reg_buf[i]);
 
        rem = length & 0x3;
        if (rem > 0) {
                u32 reg = 0;
 
                memcpy(&reg, &buf[length - rem], rem);
-               mei_me_reg_write(hw, H_CB_WW, reg);
+               mei_me_hcbww_write(dev, reg);
        }
 
-       hcsr = mei_hcsr_read(hw) | H_IG;
-       mei_hcsr_set(hw, hcsr);
+       hcsr = mei_hcsr_read(dev) | H_IG;
+       mei_hcsr_set(dev, hcsr);
        if (!mei_me_hw_is_ready(dev))
                return -EIO;
 
@@ -487,12 +513,11 @@ static int mei_me_write_message(struct mei_device *dev,
  */
 static int mei_me_count_full_read_slots(struct mei_device *dev)
 {
-       struct mei_me_hw *hw = to_me_hw(dev);
        u32 me_csr;
        char read_ptr, write_ptr;
        unsigned char buffer_depth, filled_slots;
 
-       me_csr = mei_me_mecsr_read(hw);
+       me_csr = mei_me_mecsr_read(dev);
        buffer_depth = (unsigned char)((me_csr & ME_CBD_HRA) >> 24);
        read_ptr = (char) ((me_csr & ME_CBRP_HRA) >> 8);
        write_ptr = (char) ((me_csr & ME_CBWP_HRA) >> 16);
@@ -518,7 +543,6 @@ static int mei_me_count_full_read_slots(struct mei_device *dev)
 static int mei_me_read_slots(struct mei_device *dev, unsigned char *buffer,
                    unsigned long buffer_length)
 {
-       struct mei_me_hw *hw = to_me_hw(dev);
        u32 *reg_buf = (u32 *)buffer;
        u32 hcsr;
 
@@ -531,49 +555,59 @@ static int mei_me_read_slots(struct mei_device *dev, unsigned char *buffer,
                memcpy(reg_buf, &reg, buffer_length);
        }
 
-       hcsr = mei_hcsr_read(hw) | H_IG;
-       mei_hcsr_set(hw, hcsr);
+       hcsr = mei_hcsr_read(dev) | H_IG;
+       mei_hcsr_set(dev, hcsr);
        return 0;
 }
 
 /**
- * mei_me_pg_enter - write pg enter register
+ * mei_me_pg_set - write pg enter register
  *
  * @dev: the device structure
  */
-static void mei_me_pg_enter(struct mei_device *dev)
+static void mei_me_pg_set(struct mei_device *dev)
 {
        struct mei_me_hw *hw = to_me_hw(dev);
-       u32 reg = mei_me_reg_read(hw, H_HPG_CSR);
+       u32 reg;
+
+       reg = mei_me_reg_read(hw, H_HPG_CSR);
+       trace_mei_reg_read(dev->dev, "H_HPG_CSR", H_HPG_CSR, reg);
 
        reg |= H_HPG_CSR_PGI;
+
+       trace_mei_reg_write(dev->dev, "H_HPG_CSR", H_HPG_CSR, reg);
        mei_me_reg_write(hw, H_HPG_CSR, reg);
 }
 
 /**
- * mei_me_pg_exit - write pg exit register
+ * mei_me_pg_unset - write pg exit register
  *
  * @dev: the device structure
  */
-static void mei_me_pg_exit(struct mei_device *dev)
+static void mei_me_pg_unset(struct mei_device *dev)
 {
        struct mei_me_hw *hw = to_me_hw(dev);
-       u32 reg = mei_me_reg_read(hw, H_HPG_CSR);
+       u32 reg;
+
+       reg = mei_me_reg_read(hw, H_HPG_CSR);
+       trace_mei_reg_read(dev->dev, "H_HPG_CSR", H_HPG_CSR, reg);
 
        WARN(!(reg & H_HPG_CSR_PGI), "PGI is not set\n");
 
        reg |= H_HPG_CSR_PGIHEXR;
+
+       trace_mei_reg_write(dev->dev, "H_HPG_CSR", H_HPG_CSR, reg);
        mei_me_reg_write(hw, H_HPG_CSR, reg);
 }
 
 /**
- * mei_me_pg_set_sync - perform pg entry procedure
+ * mei_me_pg_enter_sync - perform pg entry procedure
  *
  * @dev: the device structure
  *
  * Return: 0 on success an error code otherwise
  */
-int mei_me_pg_set_sync(struct mei_device *dev)
+int mei_me_pg_enter_sync(struct mei_device *dev)
 {
        struct mei_me_hw *hw = to_me_hw(dev);
        unsigned long timeout = mei_secs_to_jiffies(MEI_PGI_TIMEOUT);
@@ -591,7 +625,7 @@ int mei_me_pg_set_sync(struct mei_device *dev)
        mutex_lock(&dev->device_lock);
 
        if (dev->pg_event == MEI_PG_EVENT_RECEIVED) {
-               mei_me_pg_enter(dev);
+               mei_me_pg_set(dev);
                ret = 0;
        } else {
                ret = -ETIME;
@@ -604,13 +638,13 @@ int mei_me_pg_set_sync(struct mei_device *dev)
 }
 
 /**
- * mei_me_pg_unset_sync - perform pg exit procedure
+ * mei_me_pg_exit_sync - perform pg exit procedure
  *
  * @dev: the device structure
  *
  * Return: 0 on success an error code otherwise
  */
-int mei_me_pg_unset_sync(struct mei_device *dev)
+int mei_me_pg_exit_sync(struct mei_device *dev)
 {
        struct mei_me_hw *hw = to_me_hw(dev);
        unsigned long timeout = mei_secs_to_jiffies(MEI_PGI_TIMEOUT);
@@ -621,7 +655,7 @@ int mei_me_pg_unset_sync(struct mei_device *dev)
 
        dev->pg_event = MEI_PG_EVENT_WAIT;
 
-       mei_me_pg_exit(dev);
+       mei_me_pg_unset(dev);
 
        mutex_unlock(&dev->device_lock);
        wait_event_timeout(dev->wait_pg,
@@ -649,8 +683,7 @@ reply:
  */
 static bool mei_me_pg_is_enabled(struct mei_device *dev)
 {
-       struct mei_me_hw *hw = to_me_hw(dev);
-       u32 reg = mei_me_reg_read(hw, ME_CSR_HA);
+       u32 reg = mei_me_mecsr_read(dev);
 
        if ((reg & ME_PGIC_HRA) == 0)
                goto notsupported;
@@ -683,14 +716,13 @@ notsupported:
 irqreturn_t mei_me_irq_quick_handler(int irq, void *dev_id)
 {
        struct mei_device *dev = (struct mei_device *) dev_id;
-       struct mei_me_hw *hw = to_me_hw(dev);
-       u32 csr_reg = mei_hcsr_read(hw);
+       u32 hcsr = mei_hcsr_read(dev);
 
-       if ((csr_reg & H_IS) != H_IS)
+       if ((hcsr & H_IS) != H_IS)
                return IRQ_NONE;
 
        /* clear H_IS bit in H_CSR */
-       mei_me_reg_write(hw, H_CSR, csr_reg);
+       mei_hcsr_write(dev, hcsr);
 
        return IRQ_WAKE_THREAD;
 }
index d6567af44377e8deaf33a5a60888f58a128a7588..6022d52af6f6fb8ad57e6339b38f9c4c3cc133ba 100644 (file)
@@ -71,8 +71,8 @@ extern const struct mei_cfg mei_me_pch8_sps_cfg;
 struct mei_device *mei_me_dev_init(struct pci_dev *pdev,
                                   const struct mei_cfg *cfg);
 
-int mei_me_pg_set_sync(struct mei_device *dev);
-int mei_me_pg_unset_sync(struct mei_device *dev);
+int mei_me_pg_enter_sync(struct mei_device *dev);
+int mei_me_pg_exit_sync(struct mei_device *dev);
 
 irqreturn_t mei_me_irq_quick_handler(int irq, void *dev_id);
 irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id);
index 618ea721aca8845dec1049cfa164d0fe4e3cedfa..7abafe7d120d8b085511b2c6f31021ffa6522d2a 100644 (file)
@@ -412,7 +412,7 @@ static void mei_txe_intr_disable(struct mei_device *dev)
        mei_txe_br_reg_write(hw, HIER_REG, 0);
 }
 /**
- * mei_txe_intr_disable - enable all interrupts
+ * mei_txe_intr_enable - enable all interrupts
  *
  * @dev: the device structure
  */
index 6ad049a08e4d9d27880e62b69a8d249207fa5a13..97353cf8d9b6b7186ae13485382da2cb0da59e4f 100644 (file)
@@ -389,6 +389,7 @@ void mei_device_init(struct mei_device *dev,
        INIT_LIST_HEAD(&dev->device_list);
        INIT_LIST_HEAD(&dev->me_clients);
        mutex_init(&dev->device_lock);
+       init_rwsem(&dev->me_clients_rwsem);
        init_waitqueue_head(&dev->wait_hw_ready);
        init_waitqueue_head(&dev->wait_pg);
        init_waitqueue_head(&dev->wait_hbm_start);
@@ -396,7 +397,6 @@ void mei_device_init(struct mei_device *dev,
        dev->dev_state = MEI_DEV_INITIALIZING;
        dev->reset_count = 0;
 
-       mei_io_list_init(&dev->read_list);
        mei_io_list_init(&dev->write_list);
        mei_io_list_init(&dev->write_waiting_list);
        mei_io_list_init(&dev->ctrl_wr_list);
index 711cddfa9c997b1a0986c8b94433327bdb21229a..3f84d2edcde44f1f7a06377abe903a6ca2f86fd1 100644 (file)
@@ -43,7 +43,7 @@ void mei_irq_compl_handler(struct mei_device *dev, struct mei_cl_cb *compl_list)
 
        list_for_each_entry_safe(cb, next, &compl_list->list, list) {
                cl = cb->cl;
-               list_del(&cb->list);
+               list_del_init(&cb->list);
 
                dev_dbg(dev->dev, "completing call back.\n");
                if (cl == &dev->iamthif_cl)
@@ -68,91 +68,91 @@ static inline int mei_cl_hbm_equal(struct mei_cl *cl,
        return cl->host_client_id == mei_hdr->host_addr &&
                cl->me_client_id == mei_hdr->me_addr;
 }
+
 /**
- * mei_cl_is_reading - checks if the client
- *             is the one to read this message
- *
- * @cl: mei client
- * @mei_hdr: header of mei message
+ * mei_irq_discard_msg  - discard received message
  *
- * Return: true on match and false otherwise
+ * @dev: mei device
+ * @hdr: message header
  */
-static bool mei_cl_is_reading(struct mei_cl *cl, struct mei_msg_hdr *mei_hdr)
+static inline
+void mei_irq_discard_msg(struct mei_device *dev, struct mei_msg_hdr *hdr)
 {
-       return mei_cl_hbm_equal(cl, mei_hdr) &&
-               cl->state == MEI_FILE_CONNECTED &&
-               cl->reading_state != MEI_READ_COMPLETE;
+       /*
+        * no need to check for size as it is guarantied
+        * that length fits into rd_msg_buf
+        */
+       mei_read_slots(dev, dev->rd_msg_buf, hdr->length);
+       dev_dbg(dev->dev, "discarding message " MEI_HDR_FMT "\n",
+               MEI_HDR_PRM(hdr));
 }
 
 /**
  * mei_cl_irq_read_msg - process client message
  *
- * @dev: the device structure
+ * @cl: reading client
  * @mei_hdr: header of mei client message
- * @complete_list: An instance of our list structure
+ * @complete_list: completion list
  *
- * Return: 0 on success, <0 on failure.
+ * Return: always 0
  */
-static int mei_cl_irq_read_msg(struct mei_device *dev,
-                              struct mei_msg_hdr *mei_hdr,
-                              struct mei_cl_cb *complete_list)
+int mei_cl_irq_read_msg(struct mei_cl *cl,
+                      struct mei_msg_hdr *mei_hdr,
+                      struct mei_cl_cb *complete_list)
 {
-       struct mei_cl *cl;
-       struct mei_cl_cb *cb, *next;
+       struct mei_device *dev = cl->dev;
+       struct mei_cl_cb *cb;
        unsigned char *buffer = NULL;
 
-       list_for_each_entry_safe(cb, next, &dev->read_list.list, list) {
-               cl = cb->cl;
-               if (!mei_cl_is_reading(cl, mei_hdr))
-                       continue;
-
-               cl->reading_state = MEI_READING;
+       cb = list_first_entry_or_null(&cl->rd_pending, struct mei_cl_cb, list);
+       if (!cb) {
+               cl_err(dev, cl, "pending read cb not found\n");
+               goto out;
+       }
 
-               if (cb->response_buffer.size == 0 ||
-                   cb->response_buffer.data == NULL) {
-                       cl_err(dev, cl, "response buffer is not allocated.\n");
-                       list_del(&cb->list);
-                       return -ENOMEM;
-               }
+       if (!mei_cl_is_connected(cl)) {
+               cl_dbg(dev, cl, "not connected\n");
+               cb->status = -ENODEV;
+               goto out;
+       }
 
-               if (cb->response_buffer.size < mei_hdr->length + cb->buf_idx) {
-                       cl_dbg(dev, cl, "message overflow. size %d len %d idx %ld\n",
-                               cb->response_buffer.size,
-                               mei_hdr->length, cb->buf_idx);
-                       buffer = krealloc(cb->response_buffer.data,
-                                         mei_hdr->length + cb->buf_idx,
-                                         GFP_KERNEL);
-
-                       if (!buffer) {
-                               list_del(&cb->list);
-                               return -ENOMEM;
-                       }
-                       cb->response_buffer.data = buffer;
-                       cb->response_buffer.size =
-                               mei_hdr->length + cb->buf_idx;
-               }
+       if (cb->buf.size == 0 || cb->buf.data == NULL) {
+               cl_err(dev, cl, "response buffer is not allocated.\n");
+               list_move_tail(&cb->list, &complete_list->list);
+               cb->status = -ENOMEM;
+               goto out;
+       }
 
-               buffer = cb->response_buffer.data + cb->buf_idx;
-               mei_read_slots(dev, buffer, mei_hdr->length);
+       if (cb->buf.size < mei_hdr->length + cb->buf_idx) {
+               cl_dbg(dev, cl, "message overflow. size %d len %d idx %ld\n",
+                       cb->buf.size, mei_hdr->length, cb->buf_idx);
+               buffer = krealloc(cb->buf.data, mei_hdr->length + cb->buf_idx,
+                                 GFP_KERNEL);
 
-               cb->buf_idx += mei_hdr->length;
-               if (mei_hdr->msg_complete) {
-                       cl->status = 0;
-                       list_del(&cb->list);
-                       cl_dbg(dev, cl, "completed read length = %lu\n",
-                               cb->buf_idx);
-                       list_add_tail(&cb->list, &complete_list->list);
+               if (!buffer) {
+                       cb->status = -ENOMEM;
+                       list_move_tail(&cb->list, &complete_list->list);
+                       goto out;
                }
-               break;
+               cb->buf.data = buffer;
+               cb->buf.size = mei_hdr->length + cb->buf_idx;
        }
 
-       dev_dbg(dev->dev, "message read\n");
-       if (!buffer) {
-               mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length);
-               dev_dbg(dev->dev, "discarding message " MEI_HDR_FMT "\n",
-                               MEI_HDR_PRM(mei_hdr));
+       buffer = cb->buf.data + cb->buf_idx;
+       mei_read_slots(dev, buffer, mei_hdr->length);
+
+       cb->buf_idx += mei_hdr->length;
+
+       if (mei_hdr->msg_complete) {
+               cb->read_time = jiffies;
+               cl_dbg(dev, cl, "completed read length = %lu\n", cb->buf_idx);
+               list_move_tail(&cb->list, &complete_list->list);
        }
 
+out:
+       if (!buffer)
+               mei_irq_discard_msg(dev, mei_hdr);
+
        return 0;
 }
 
@@ -183,7 +183,6 @@ static int mei_cl_irq_disconnect_rsp(struct mei_cl *cl, struct mei_cl_cb *cb,
 
        cl->state = MEI_FILE_DISCONNECTED;
        cl->status = 0;
-       list_del(&cb->list);
        mei_io_cb_free(cb);
 
        return ret;
@@ -263,7 +262,7 @@ static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb,
                return ret;
        }
 
-       list_move_tail(&cb->list, &dev->read_list.list);
+       list_move_tail(&cb->list, &cl->rd_pending);
 
        return 0;
 }
@@ -301,7 +300,7 @@ static int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb,
        if (ret) {
                cl->status = ret;
                cb->buf_idx = 0;
-               list_del(&cb->list);
+               list_del_init(&cb->list);
                return ret;
        }
 
@@ -378,25 +377,13 @@ int mei_irq_read_handler(struct mei_device *dev,
                goto end;
        }
 
-       if (mei_hdr->host_addr == dev->iamthif_cl.host_client_id &&
-           MEI_FILE_CONNECTED == dev->iamthif_cl.state &&
-           dev->iamthif_state == MEI_IAMTHIF_READING) {
-
-               ret = mei_amthif_irq_read_msg(dev, mei_hdr, cmpl_list);
-               if (ret) {
-                       dev_err(dev->dev, "mei_amthif_irq_read_msg failed = %d\n",
-                                       ret);
-                       goto end;
-               }
+       if (cl == &dev->iamthif_cl) {
+               ret = mei_amthif_irq_read_msg(cl, mei_hdr, cmpl_list);
        } else {
-               ret = mei_cl_irq_read_msg(dev, mei_hdr, cmpl_list);
-               if (ret) {
-                       dev_err(dev->dev, "mei_cl_irq_read_msg failed = %d\n",
-                                       ret);
-                       goto end;
-               }
+               ret = mei_cl_irq_read_msg(cl, mei_hdr, cmpl_list);
        }
 
+
 reset_slots:
        /* reset the number of slots and header */
        *slots = mei_count_full_read_slots(dev);
@@ -449,21 +436,9 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
                cl = cb->cl;
 
                cl->status = 0;
-               list_del(&cb->list);
-               if (cb->fop_type == MEI_FOP_WRITE &&
-                   cl != &dev->iamthif_cl) {
-                       cl_dbg(dev, cl, "MEI WRITE COMPLETE\n");
-                       cl->writing_state = MEI_WRITE_COMPLETE;
-                       list_add_tail(&cb->list, &cmpl_list->list);
-               }
-               if (cl == &dev->iamthif_cl) {
-                       cl_dbg(dev, cl, "check iamthif flow control.\n");
-                       if (dev->iamthif_flow_control_pending) {
-                               ret = mei_amthif_irq_read(dev, &slots);
-                               if (ret)
-                                       return ret;
-                       }
-               }
+               cl_dbg(dev, cl, "MEI WRITE COMPLETE\n");
+               cl->writing_state = MEI_WRITE_COMPLETE;
+               list_move_tail(&cb->list, &cmpl_list->list);
        }
 
        if (dev->wd_state == MEI_WD_STOPPING) {
@@ -587,10 +562,7 @@ void mei_timer(struct work_struct *work)
                if (--dev->iamthif_stall_timer == 0) {
                        dev_err(dev->dev, "timer: amthif  hanged.\n");
                        mei_reset(dev);
-                       dev->iamthif_msg_buf_size = 0;
-                       dev->iamthif_msg_buf_index = 0;
                        dev->iamthif_canceled = false;
-                       dev->iamthif_ioctl = true;
                        dev->iamthif_state = MEI_IAMTHIF_IDLE;
                        dev->iamthif_timer = 0;
 
@@ -636,4 +608,3 @@ out:
                schedule_delayed_work(&dev->timer_work, 2 * HZ);
        mutex_unlock(&dev->device_lock);
 }
-
index 47680c84801c766f158bf65c2e2dd3893fdff300..3e29681595064a74de8c856f782402d82aa08fe0 100644 (file)
@@ -58,24 +58,18 @@ static int mei_open(struct inode *inode, struct file *file)
 
        mutex_lock(&dev->device_lock);
 
-       cl = NULL;
-
-       err = -ENODEV;
        if (dev->dev_state != MEI_DEV_ENABLED) {
                dev_dbg(dev->dev, "dev_state != MEI_ENABLED  dev_state = %s\n",
                    mei_dev_state_str(dev->dev_state));
+               err = -ENODEV;
                goto err_unlock;
        }
 
-       err = -ENOMEM;
-       cl = mei_cl_allocate(dev);
-       if (!cl)
-               goto err_unlock;
-
-       /* open_handle_count check is handled in the mei_cl_link */
-       err = mei_cl_link(cl, MEI_HOST_CLIENT_ID_ANY);
-       if (err)
+       cl = mei_cl_alloc_linked(dev, MEI_HOST_CLIENT_ID_ANY);
+       if (IS_ERR(cl)) {
+               err = PTR_ERR(cl);
                goto err_unlock;
+       }
 
        file->private_data = cl;
 
@@ -85,7 +79,6 @@ static int mei_open(struct inode *inode, struct file *file)
 
 err_unlock:
        mutex_unlock(&dev->device_lock);
-       kfree(cl);
        return err;
 }
 
@@ -100,7 +93,6 @@ err_unlock:
 static int mei_release(struct inode *inode, struct file *file)
 {
        struct mei_cl *cl = file->private_data;
-       struct mei_cl_cb *cb;
        struct mei_device *dev;
        int rets = 0;
 
@@ -114,33 +106,18 @@ static int mei_release(struct inode *inode, struct file *file)
                rets = mei_amthif_release(dev, file);
                goto out;
        }
-       if (cl->state == MEI_FILE_CONNECTED) {
+       if (mei_cl_is_connected(cl)) {
                cl->state = MEI_FILE_DISCONNECTING;
                cl_dbg(dev, cl, "disconnecting\n");
                rets = mei_cl_disconnect(cl);
        }
-       mei_cl_flush_queues(cl);
+       mei_cl_flush_queues(cl, file);
        cl_dbg(dev, cl, "removing\n");
 
        mei_cl_unlink(cl);
 
-
-       /* free read cb */
-       cb = NULL;
-       if (cl->read_cb) {
-               cb = mei_cl_find_read_cb(cl);
-               /* Remove entry from read list */
-               if (cb)
-                       list_del(&cb->list);
-
-               cb = cl->read_cb;
-               cl->read_cb = NULL;
-       }
-
        file->private_data = NULL;
 
-       mei_io_cb_free(cb);
-
        kfree(cl);
 out:
        mutex_unlock(&dev->device_lock);
@@ -162,9 +139,8 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
                        size_t length, loff_t *offset)
 {
        struct mei_cl *cl = file->private_data;
-       struct mei_cl_cb *cb_pos = NULL;
-       struct mei_cl_cb *cb = NULL;
        struct mei_device *dev;
+       struct mei_cl_cb *cb = NULL;
        int rets;
        int err;
 
@@ -191,8 +167,8 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
                goto out;
        }
 
-       if (cl->read_cb) {
-               cb = cl->read_cb;
+       cb = mei_cl_read_cb(cl, file);
+       if (cb) {
                /* read what left */
                if (cb->buf_idx > *offset)
                        goto copy_buffer;
@@ -208,7 +184,7 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
                *offset = 0;
        }
 
-       err = mei_cl_read_start(cl, length);
+       err = mei_cl_read_start(cl, length, file);
        if (err && err != -EBUSY) {
                dev_dbg(dev->dev,
                        "mei start read failure with status = %d\n", err);
@@ -216,8 +192,7 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
                goto out;
        }
 
-       if (MEI_READ_COMPLETE != cl->reading_state &&
-                       !waitqueue_active(&cl->rx_wait)) {
+       if (list_empty(&cl->rd_completed) && !waitqueue_active(&cl->rx_wait)) {
                if (file->f_flags & O_NONBLOCK) {
                        rets = -EAGAIN;
                        goto out;
@@ -226,8 +201,8 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
                mutex_unlock(&dev->device_lock);
 
                if (wait_event_interruptible(cl->rx_wait,
-                               MEI_READ_COMPLETE == cl->reading_state ||
-                               mei_cl_is_transitioning(cl))) {
+                               (!list_empty(&cl->rd_completed)) ||
+                               (!mei_cl_is_connected(cl)))) {
 
                        if (signal_pending(current))
                                return -EINTR;
@@ -235,26 +210,28 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
                }
 
                mutex_lock(&dev->device_lock);
-               if (mei_cl_is_transitioning(cl)) {
+               if (!mei_cl_is_connected(cl)) {
                        rets = -EBUSY;
                        goto out;
                }
        }
 
-       cb = cl->read_cb;
-
+       cb = mei_cl_read_cb(cl, file);
        if (!cb) {
-               rets = -ENODEV;
-               goto out;
-       }
-       if (cl->reading_state != MEI_READ_COMPLETE) {
                rets = 0;
                goto out;
        }
-       /* now copy the data to user space */
+
 copy_buffer:
+       /* now copy the data to user space */
+       if (cb->status) {
+               rets = cb->status;
+               dev_dbg(dev->dev, "read operation failed %d\n", rets);
+               goto free;
+       }
+
        dev_dbg(dev->dev, "buf.size = %d buf.idx= %ld\n",
-           cb->response_buffer.size, cb->buf_idx);
+           cb->buf.size, cb->buf_idx);
        if (length == 0 || ubuf == NULL || *offset > cb->buf_idx) {
                rets = -EMSGSIZE;
                goto free;
@@ -264,7 +241,7 @@ copy_buffer:
         * however buf_idx may point beyond that */
        length = min_t(size_t, length, cb->buf_idx - *offset);
 
-       if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length)) {
+       if (copy_to_user(ubuf, cb->buf.data + *offset, length)) {
                dev_dbg(dev->dev, "failed to copy data to userland\n");
                rets = -EFAULT;
                goto free;
@@ -276,13 +253,8 @@ copy_buffer:
                goto out;
 
 free:
-       cb_pos = mei_cl_find_read_cb(cl);
-       /* Remove entry from read list */
-       if (cb_pos)
-               list_del(&cb_pos->list);
        mei_io_cb_free(cb);
-       cl->reading_state = MEI_IDLE;
-       cl->read_cb = NULL;
+
 out:
        dev_dbg(dev->dev, "end mei read rets= %d\n", rets);
        mutex_unlock(&dev->device_lock);
@@ -336,9 +308,8 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
                goto out;
        }
 
-       if (cl->state != MEI_FILE_CONNECTED) {
-               dev_err(dev->dev, "host client = %d,  is not connected to ME client = %d",
-                       cl->host_client_id, cl->me_client_id);
+       if (!mei_cl_is_connected(cl)) {
+               cl_err(dev, cl, "is not connected");
                rets = -ENODEV;
                goto out;
        }
@@ -349,41 +320,22 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
                        timeout = write_cb->read_time +
                                mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
 
-                       if (time_after(jiffies, timeout) ||
-                           cl->reading_state == MEI_READ_COMPLETE) {
+                       if (time_after(jiffies, timeout)) {
                                *offset = 0;
-                               list_del(&write_cb->list);
                                mei_io_cb_free(write_cb);
                                write_cb = NULL;
                        }
                }
        }
 
-       /* free entry used in read */
-       if (cl->reading_state == MEI_READ_COMPLETE) {
-               *offset = 0;
-               write_cb = mei_cl_find_read_cb(cl);
-               if (write_cb) {
-                       list_del(&write_cb->list);
-                       mei_io_cb_free(write_cb);
-                       write_cb = NULL;
-                       cl->reading_state = MEI_IDLE;
-                       cl->read_cb = NULL;
-               }
-       } else if (cl->reading_state == MEI_IDLE)
-               *offset = 0;
-
-
-       write_cb = mei_io_cb_init(cl, file);
+       *offset = 0;
+       write_cb = mei_cl_alloc_cb(cl, length, MEI_FOP_WRITE, file);
        if (!write_cb) {
                rets = -ENOMEM;
                goto out;
        }
-       rets = mei_io_cb_alloc_req_buf(write_cb, length);
-       if (rets)
-               goto out;
 
-       rets = copy_from_user(write_cb->request_buffer.data, ubuf, length);
+       rets = copy_from_user(write_cb->buf.data, ubuf, length);
        if (rets) {
                dev_dbg(dev->dev, "failed to copy data from userland\n");
                rets = -EFAULT;
@@ -391,7 +343,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
        }
 
        if (cl == &dev->iamthif_cl) {
-               rets = mei_amthif_write(dev, write_cb);
+               rets = mei_amthif_write(cl, write_cb);
 
                if (rets) {
                        dev_err(dev->dev,
@@ -464,7 +416,7 @@ static int mei_ioctl_connect_client(struct file *file,
         */
        if (uuid_le_cmp(data->in_client_uuid, mei_amthif_guid) == 0) {
                dev_dbg(dev->dev, "FW Client is amthi\n");
-               if (dev->iamthif_cl.state != MEI_FILE_CONNECTED) {
+               if (!mei_cl_is_connected(&dev->iamthif_cl)) {
                        rets = -ENODEV;
                        goto end;
                }
@@ -588,6 +540,7 @@ static long mei_compat_ioctl(struct file *file,
  */
 static unsigned int mei_poll(struct file *file, poll_table *wait)
 {
+       unsigned long req_events = poll_requested_events(wait);
        struct mei_cl *cl = file->private_data;
        struct mei_device *dev;
        unsigned int mask = 0;
@@ -599,27 +552,26 @@ static unsigned int mei_poll(struct file *file, poll_table *wait)
 
        mutex_lock(&dev->device_lock);
 
-       if (!mei_cl_is_connected(cl)) {
+
+       if (dev->dev_state != MEI_DEV_ENABLED ||
+           !mei_cl_is_connected(cl)) {
                mask = POLLERR;
                goto out;
        }
 
-       mutex_unlock(&dev->device_lock);
-
-
-       if (cl == &dev->iamthif_cl)
-               return mei_amthif_poll(dev, file, wait);
-
-       poll_wait(file, &cl->tx_wait, wait);
-
-       mutex_lock(&dev->device_lock);
-
-       if (!mei_cl_is_connected(cl)) {
-               mask = POLLERR;
+       if (cl == &dev->iamthif_cl) {
+               mask = mei_amthif_poll(dev, file, wait);
                goto out;
        }
 
-       mask |= (POLLIN | POLLRDNORM);
+       if (req_events & (POLLIN | POLLRDNORM)) {
+               poll_wait(file, &cl->rx_wait, wait);
+
+               if (!list_empty(&cl->rd_completed))
+                       mask |= POLLIN | POLLRDNORM;
+               else
+                       mei_cl_read_start(cl, 0, file);
+       }
 
 out:
        mutex_unlock(&dev->device_lock);
diff --git a/drivers/misc/mei/mei-trace.c b/drivers/misc/mei/mei-trace.c
new file mode 100644 (file)
index 0000000..388efb5
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ *
+ * Intel Management Engine Interface (Intel MEI) Linux driver
+ * Copyright (c) 2015, 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/module.h>
+
+/* sparse doesn't like tracepoint macros */
+#ifndef __CHECKER__
+#define CREATE_TRACE_POINTS
+#include "mei-trace.h"
+
+EXPORT_TRACEPOINT_SYMBOL(mei_reg_read);
+EXPORT_TRACEPOINT_SYMBOL(mei_reg_write);
+#endif /* __CHECKER__ */
diff --git a/drivers/misc/mei/mei-trace.h b/drivers/misc/mei/mei-trace.h
new file mode 100644 (file)
index 0000000..47e1bc6
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ *
+ * Intel Management Engine Interface (Intel MEI) Linux driver
+ * Copyright (c) 2015, 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.
+ *
+ */
+
+#if !defined(_MEI_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
+#define _MEI_TRACE_H_
+
+#include <linux/stringify.h>
+#include <linux/types.h>
+#include <linux/tracepoint.h>
+
+#include <linux/device.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM mei
+
+TRACE_EVENT(mei_reg_read,
+       TP_PROTO(const struct device *dev, const char *reg, u32 offs, u32 val),
+       TP_ARGS(dev, reg, offs, val),
+       TP_STRUCT__entry(
+               __string(dev, dev_name(dev))
+               __field(const char *, reg)
+               __field(u32, offs)
+               __field(u32, val)
+       ),
+       TP_fast_assign(
+               __assign_str(dev, dev_name(dev))
+               __entry->reg  = reg;
+               __entry->offs = offs;
+               __entry->val = val;
+       ),
+       TP_printk("[%s] read %s:[%#x] = %#x",
+                 __get_str(dev), __entry->reg, __entry->offs, __entry->val)
+);
+
+TRACE_EVENT(mei_reg_write,
+       TP_PROTO(const struct device *dev, const char *reg, u32 offs, u32 val),
+       TP_ARGS(dev, reg, offs, val),
+       TP_STRUCT__entry(
+               __string(dev, dev_name(dev))
+               __field(const char *, reg)
+               __field(u32, offs)
+               __field(u32, val)
+       ),
+       TP_fast_assign(
+               __assign_str(dev, dev_name(dev))
+               __entry->reg = reg;
+               __entry->offs = offs;
+               __entry->val = val;
+       ),
+       TP_printk("[%s] write %s[%#x] = %#x)",
+                 __get_str(dev), __entry->reg,  __entry->offs, __entry->val)
+);
+
+#endif /* _MEI_TRACE_H_ */
+
+/* This part must be outside protection */
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE mei-trace
+#include <trace/define_trace.h>
index 6c6ce9381535151a437612ad83bae65b08dfed2e..f066ecd719393aaa8f52a165d5d0b8b13416bf8e 100644 (file)
@@ -194,23 +194,25 @@ struct mei_cl;
  * @list: link in callback queue
  * @cl: file client who is running this operation
  * @fop_type: file operation type
- * @request_buffer: buffer to store request data
- * @response_buffer: buffer to store response data
+ * @buf: buffer for data associated with the callback
  * @buf_idx: last read index
  * @read_time: last read operation time stamp (iamthif)
  * @file_object: pointer to file structure
+ * @status: io status of the cb
  * @internal: communication between driver and FW flag
+ * @completed: the transfer or reception has completed
  */
 struct mei_cl_cb {
        struct list_head list;
        struct mei_cl *cl;
        enum mei_cb_file_ops fop_type;
-       struct mei_msg_data request_buffer;
-       struct mei_msg_data response_buffer;
+       struct mei_msg_data buf;
        unsigned long buf_idx;
        unsigned long read_time;
        struct file *file_object;
+       int status;
        u32 internal:1;
+       u32 completed:1;
 };
 
 /**
@@ -229,9 +231,9 @@ struct mei_cl_cb {
  * @me_client_id: me/fw id
  * @mei_flow_ctrl_creds: transmit flow credentials
  * @timer_count:  watchdog timer for operation completion
- * @reading_state: state of the rx
  * @writing_state: state of the tx
- * @read_cb: current pending reading callback
+ * @rd_pending: pending read credits
+ * @rd_completed: completed read
  *
  * @device: device on the mei client bus
  * @device_link:  link to bus clients
@@ -249,9 +251,9 @@ struct mei_cl {
        u8 me_client_id;
        u8 mei_flow_ctrl_creds;
        u8 timer_count;
-       enum mei_file_transaction_states reading_state;
        enum mei_file_transaction_states writing_state;
-       struct mei_cl_cb *read_cb;
+       struct list_head rd_pending;
+       struct list_head rd_completed;
 
        /* MEI CL bus data */
        struct mei_cl_device *device;
@@ -423,7 +425,6 @@ const char *mei_pg_state_str(enum mei_pg_state state);
  * @cdev        : character device
  * @minor       : minor number allocated for device
  *
- * @read_list   : read completion list
  * @write_list  : write pending list
  * @write_waiting_list : write completion list
  * @ctrl_wr_list : pending control write list
@@ -460,6 +461,7 @@ const char *mei_pg_state_str(enum mei_pg_state state);
  * @version     : HBM protocol version in use
  * @hbm_f_pg_supported : hbm feature pgi protocol
  *
+ * @me_clients_rwsem: rw lock over me_clients list
  * @me_clients  : list of FW clients
  * @me_clients_map : FW clients bit map
  * @host_clients_map : host clients id pool
@@ -480,12 +482,7 @@ const char *mei_pg_state_str(enum mei_pg_state state);
  * @iamthif_mtu : amthif client max message length
  * @iamthif_timer : time stamp of current amthif command completion
  * @iamthif_stall_timer : timer to detect amthif hang
- * @iamthif_msg_buf : amthif current message buffer
- * @iamthif_msg_buf_size : size of current amthif message request buffer
- * @iamthif_msg_buf_index : current index in amthif message request buffer
  * @iamthif_state : amthif processor state
- * @iamthif_flow_control_pending: amthif waits for flow control
- * @iamthif_ioctl : wait for completion if amthif control message
  * @iamthif_canceled : current amthif command is canceled
  *
  * @init_work   : work item for the device init
@@ -503,7 +500,6 @@ struct mei_device {
        struct cdev cdev;
        int minor;
 
-       struct mei_cl_cb read_list;
        struct mei_cl_cb write_list;
        struct mei_cl_cb write_waiting_list;
        struct mei_cl_cb ctrl_wr_list;
@@ -556,6 +552,7 @@ struct mei_device {
        struct hbm_version version;
        unsigned int hbm_f_pg_supported:1;
 
+       struct rw_semaphore me_clients_rwsem;
        struct list_head me_clients;
        DECLARE_BITMAP(me_clients_map, MEI_CLIENTS_MAX);
        DECLARE_BITMAP(host_clients_map, MEI_CLIENTS_MAX);
@@ -579,12 +576,7 @@ struct mei_device {
        int iamthif_mtu;
        unsigned long iamthif_timer;
        u32 iamthif_stall_timer;
-       unsigned char *iamthif_msg_buf; /* Note: memory has to be allocated */
-       u32 iamthif_msg_buf_size;
-       u32 iamthif_msg_buf_index;
        enum iamthif_states iamthif_state;
-       bool iamthif_flow_control_pending;
-       bool iamthif_ioctl;
        bool iamthif_canceled;
 
        struct work_struct init_work;
@@ -662,8 +654,6 @@ void mei_amthif_reset_params(struct mei_device *dev);
 
 int mei_amthif_host_init(struct mei_device *dev);
 
-int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *priv_cb);
-
 int mei_amthif_read(struct mei_device *dev, struct file *file,
                char __user *ubuf, size_t length, loff_t *offset);
 
@@ -675,13 +665,13 @@ int mei_amthif_release(struct mei_device *dev, struct file *file);
 struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev,
                                                struct file *file);
 
-void mei_amthif_run_next_cmd(struct mei_device *dev);
-
+int mei_amthif_write(struct mei_cl *cl, struct mei_cl_cb *cb);
+int mei_amthif_run_next_cmd(struct mei_device *dev);
 int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
                        struct mei_cl_cb *cmpl_list);
 
 void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb);
-int mei_amthif_irq_read_msg(struct mei_device *dev,
+int mei_amthif_irq_read_msg(struct mei_cl *cl,
                            struct mei_msg_hdr *mei_hdr,
                            struct mei_cl_cb *complete_list);
 int mei_amthif_irq_read(struct mei_device *dev, s32 *slots);
index bb61a119b8bbb4fdd8ee7d09da5fb520bab72573..c3bcb63686d7279dc29792ff62eb5dd8c7e7b15b 100644 (file)
@@ -482,8 +482,8 @@ err:
 int mei_nfc_host_init(struct mei_device *dev)
 {
        struct mei_nfc_dev *ndev;
-       struct mei_cl *cl_info, *cl = NULL;
-       struct mei_me_client *me_cl;
+       struct mei_cl *cl_info, *cl;
+       struct mei_me_client *me_cl = NULL;
        int ret;
 
 
@@ -500,17 +500,6 @@ int mei_nfc_host_init(struct mei_device *dev)
                goto err;
        }
 
-       ndev->cl_info = mei_cl_allocate(dev);
-       ndev->cl = mei_cl_allocate(dev);
-
-       cl = ndev->cl;
-       cl_info = ndev->cl_info;
-
-       if (!cl || !cl_info) {
-               ret = -ENOMEM;
-               goto err;
-       }
-
        /* check for valid client id */
        me_cl = mei_me_cl_by_uuid(dev, &mei_nfc_info_guid);
        if (!me_cl) {
@@ -519,17 +508,21 @@ int mei_nfc_host_init(struct mei_device *dev)
                goto err;
        }
 
+       cl_info = mei_cl_alloc_linked(dev, MEI_HOST_CLIENT_ID_ANY);
+       if (IS_ERR(cl_info)) {
+               ret = PTR_ERR(cl_info);
+               goto err;
+       }
+
        cl_info->me_client_id = me_cl->client_id;
        cl_info->cl_uuid = me_cl->props.protocol_name;
        mei_me_cl_put(me_cl);
-
-       ret = mei_cl_link(cl_info, MEI_HOST_CLIENT_ID_ANY);
-       if (ret)
-               goto err;
-
+       me_cl = NULL;
 
        list_add_tail(&cl_info->device_link, &dev->device_list);
 
+       ndev->cl_info = cl_info;
+
        /* check for valid client id */
        me_cl = mei_me_cl_by_uuid(dev, &mei_nfc_guid);
        if (!me_cl) {
@@ -538,16 +531,21 @@ int mei_nfc_host_init(struct mei_device *dev)
                goto err;
        }
 
+       cl = mei_cl_alloc_linked(dev, MEI_HOST_CLIENT_ID_ANY);
+       if (IS_ERR(cl)) {
+               ret = PTR_ERR(cl);
+               goto err;
+       }
+
        cl->me_client_id = me_cl->client_id;
        cl->cl_uuid = me_cl->props.protocol_name;
        mei_me_cl_put(me_cl);
-
-       ret = mei_cl_link(cl, MEI_HOST_CLIENT_ID_ANY);
-       if (ret)
-               goto err;
+       me_cl = NULL;
 
        list_add_tail(&cl->device_link, &dev->device_list);
 
+       ndev->cl = cl;
+
        ndev->req_id = 1;
 
        INIT_WORK(&ndev->init_work, mei_nfc_init);
@@ -557,6 +555,7 @@ int mei_nfc_host_init(struct mei_device *dev)
        return 0;
 
 err:
+       mei_me_cl_put(me_cl);
        mei_nfc_free(ndev);
 
        return ret;
index af44ee26075d8b520401a2cc52150b74d45157f0..23f71f5ce4fb07be4bb9c32021bf3babef6b938d 100644 (file)
@@ -388,7 +388,7 @@ static int mei_me_pm_runtime_suspend(struct device *device)
        mutex_lock(&dev->device_lock);
 
        if (mei_write_is_idle(dev))
-               ret = mei_me_pg_set_sync(dev);
+               ret = mei_me_pg_enter_sync(dev);
        else
                ret = -EAGAIN;
 
@@ -413,7 +413,7 @@ static int mei_me_pm_runtime_resume(struct device *device)
 
        mutex_lock(&dev->device_lock);
 
-       ret = mei_me_pg_unset_sync(dev);
+       ret = mei_me_pg_exit_sync(dev);
 
        mutex_unlock(&dev->device_lock);
 
index c86e2ddbe30af004ce38f4fe7f9ee5f0d5475209..dcfcba44b6f7c2fe2f54a67e0ccb5cde2c11b652 100644 (file)
@@ -63,7 +63,7 @@ static void mei_txe_pci_iounmap(struct pci_dev *pdev, struct mei_txe_hw *hw)
        }
 }
 /**
- * mei_probe - Device Initialization Routine
+ * mei_txe_probe - Device Initialization Routine
  *
  * @pdev: PCI device structure
  * @ent: entry in mei_txe_pci_tbl
@@ -193,7 +193,7 @@ end:
 }
 
 /**
- * mei_remove - Device Removal Routine
+ * mei_txe_remove - Device Removal Routine
  *
  * @pdev: PCI device structure
  *
index 475f1dea45bfd06c5ecfa9e2fdb40da2da32b34f..2725f865c3d6b814ef7b532069f42c6902572e8f 100644 (file)
@@ -160,9 +160,10 @@ int mei_wd_send(struct mei_device *dev)
  */
 int mei_wd_stop(struct mei_device *dev)
 {
+       struct mei_cl *cl = &dev->wd_cl;
        int ret;
 
-       if (dev->wd_cl.state != MEI_FILE_CONNECTED ||
+       if (!mei_cl_is_connected(cl) ||
            dev->wd_state != MEI_WD_RUNNING)
                return 0;
 
@@ -170,7 +171,7 @@ int mei_wd_stop(struct mei_device *dev)
 
        dev->wd_state = MEI_WD_STOPPING;
 
-       ret = mei_cl_flow_ctrl_creds(&dev->wd_cl);
+       ret = mei_cl_flow_ctrl_creds(cl);
        if (ret < 0)
                goto err;
 
@@ -202,22 +203,25 @@ err:
        return ret;
 }
 
-/*
+/**
  * mei_wd_ops_start - wd start command from the watchdog core.
  *
- * @wd_dev - watchdog device struct
+ * @wd_dev: watchdog device struct
  *
  * Return: 0 if success, negative errno code for failure
  */
 static int mei_wd_ops_start(struct watchdog_device *wd_dev)
 {
-       int err = -ENODEV;
        struct mei_device *dev;
+       struct mei_cl *cl;
+       int err = -ENODEV;
 
        dev = watchdog_get_drvdata(wd_dev);
        if (!dev)
                return -ENODEV;
 
+       cl = &dev->wd_cl;
+
        mutex_lock(&dev->device_lock);
 
        if (dev->dev_state != MEI_DEV_ENABLED) {
@@ -226,8 +230,8 @@ static int mei_wd_ops_start(struct watchdog_device *wd_dev)
                goto end_unlock;
        }
 
-       if (dev->wd_cl.state != MEI_FILE_CONNECTED)     {
-               dev_dbg(dev->dev, "MEI Driver is not connected to Watchdog Client\n");
+       if (!mei_cl_is_connected(cl)) {
+               cl_dbg(dev, cl, "MEI Driver is not connected to Watchdog Client\n");
                goto end_unlock;
        }
 
@@ -239,10 +243,10 @@ end_unlock:
        return err;
 }
 
-/*
+/**
  * mei_wd_ops_stop -  wd stop command from the watchdog core.
  *
- * @wd_dev - watchdog device struct
+ * @wd_dev: watchdog device struct
  *
  * Return: 0 if success, negative errno code for failure
  */
@@ -261,10 +265,10 @@ static int mei_wd_ops_stop(struct watchdog_device *wd_dev)
        return 0;
 }
 
-/*
+/**
  * mei_wd_ops_ping - wd ping command from the watchdog core.
  *
- * @wd_dev - watchdog device struct
+ * @wd_dev: watchdog device struct
  *
  * Return: 0 if success, negative errno code for failure
  */
@@ -282,8 +286,8 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
 
        mutex_lock(&dev->device_lock);
 
-       if (cl->state != MEI_FILE_CONNECTED) {
-               dev_err(dev->dev, "wd: not connected.\n");
+       if (!mei_cl_is_connected(cl)) {
+               cl_err(dev, cl, "wd: not connected.\n");
                ret = -ENODEV;
                goto end;
        }
@@ -311,11 +315,11 @@ end:
        return ret;
 }
 
-/*
+/**
  * mei_wd_ops_set_timeout - wd set timeout command from the watchdog core.
  *
- * @wd_dev - watchdog device struct
- * @timeout - timeout value to set
+ * @wd_dev: watchdog device struct
+ * @timeout: timeout value to set
  *
  * Return: 0 if success, negative errno code for failure
  */
index ff2b0fb1a6be03c3d94169670e4fd5c83b79a9dc..d9fa609da061433f3ae6d2e6133abf9921b7b1a4 100644 (file)
@@ -309,7 +309,7 @@ void mic_complete_resume(struct mic_device *mdev)
  */
 void mic_prepare_suspend(struct mic_device *mdev)
 {
-       int rc;
+       unsigned long timeout;
 
 #define MIC_SUSPEND_TIMEOUT (60 * HZ)
 
@@ -331,10 +331,10 @@ void mic_prepare_suspend(struct mic_device *mdev)
                 */
                mic_set_state(mdev, MIC_SUSPENDING);
                mutex_unlock(&mdev->mic_mutex);
-               rc = wait_for_completion_timeout(&mdev->reset_wait,
-                                               MIC_SUSPEND_TIMEOUT);
+               timeout = wait_for_completion_timeout(&mdev->reset_wait,
+                                                     MIC_SUSPEND_TIMEOUT);
                /* Force reset the card if the shutdown completion timed out */
-               if (!rc) {
+               if (!timeout) {
                        mutex_lock(&mdev->mic_mutex);
                        mic_set_state(mdev, MIC_SUSPENDED);
                        mutex_unlock(&mdev->mic_mutex);
@@ -348,10 +348,10 @@ void mic_prepare_suspend(struct mic_device *mdev)
                 */
                mic_set_state(mdev, MIC_SUSPENDED);
                mutex_unlock(&mdev->mic_mutex);
-               rc = wait_for_completion_timeout(&mdev->reset_wait,
-                                               MIC_SUSPEND_TIMEOUT);
+               timeout = wait_for_completion_timeout(&mdev->reset_wait,
+                                                     MIC_SUSPEND_TIMEOUT);
                /* Force reset the card if the shutdown completion timed out */
-               if (!rc)
+               if (!timeout)
                        mic_stop(mdev, true);
                break;
        default:
index d686f2846ac7ba7ba8b0508d56c76ac0f950b3a8..b4ca6c884d198d68dcee378083db37decfa907e8 100644 (file)
@@ -363,8 +363,6 @@ static int mic_setup_intx(struct mic_device *mdev, struct pci_dev *pdev)
 {
        int rc;
 
-       pci_msi_off(pdev);
-
        /* Enable intx */
        pci_intx(pdev, 1);
        rc = mic_setup_callbacks(mdev);
index 21181fa243dfd8705f10e113f4293c990b231c37..eeaaf5fca105d9aeed160fbd13c73ba0bbee539d 100644 (file)
@@ -69,12 +69,23 @@ static int sram_probe(struct platform_device *pdev)
        INIT_LIST_HEAD(&reserve_list);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       virt_base = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(virt_base))
-               return PTR_ERR(virt_base);
+       if (!res) {
+               dev_err(&pdev->dev, "found no memory resource\n");
+               return -EINVAL;
+       }
 
        size = resource_size(res);
 
+       if (!devm_request_mem_region(&pdev->dev,
+                       res->start, size, pdev->name)) {
+               dev_err(&pdev->dev, "could not request region for resource\n");
+               return -EBUSY;
+       }
+
+       virt_base = devm_ioremap_wc(&pdev->dev, res->start, size);
+       if (IS_ERR(virt_base))
+               return PTR_ERR(virt_base);
+
        sram = devm_kzalloc(&pdev->dev, sizeof(*sram), GFP_KERNEL);
        if (!sram)
                return -ENOMEM;
@@ -205,7 +216,7 @@ static int sram_remove(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_OF
-static struct of_device_id sram_dt_ids[] = {
+static const struct of_device_id sram_dt_ids[] = {
        { .compatible = "mmio-sram" },
        {}
 };
index a606c8901e1859099bf387e8a7d1f8b07b0f3cd0..a37a42f67088fada76104cf3d988d98f34aca3b7 100644 (file)
@@ -236,6 +236,7 @@ static int tifm_7xx1_resume(struct pci_dev *dev)
 {
        struct tifm_adapter *fm = pci_get_drvdata(dev);
        int rc;
+       unsigned long timeout;
        unsigned int good_sockets = 0, bad_sockets = 0;
        unsigned long flags;
        unsigned char new_ids[fm->num_sockets];
@@ -272,8 +273,8 @@ static int tifm_7xx1_resume(struct pci_dev *dev)
        if (good_sockets) {
                fm->finish_me = &finish_resume;
                spin_unlock_irqrestore(&fm->lock, flags);
-               rc = wait_for_completion_timeout(&finish_resume, HZ);
-               dev_dbg(&dev->dev, "wait returned %d\n", rc);
+               timeout = wait_for_completion_timeout(&finish_resume, HZ);
+               dev_dbg(&dev->dev, "wait returned %lu\n", timeout);
                writel(TIFM_IRQ_FIFOMASK(good_sockets)
                       | TIFM_IRQ_CARDMASK(good_sockets),
                       fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
index 032d35cf93ca97dfaed554e6e77832672cfbca29..b823f9a6e4641c69af5cc9f7e5c9c438433ffa01 100644 (file)
@@ -113,5 +113,5 @@ module_exit(vmci_drv_exit);
 
 MODULE_AUTHOR("VMware, Inc.");
 MODULE_DESCRIPTION("VMware Virtual Machine Communication Interface.");
-MODULE_VERSION("1.1.1.0-k");
+MODULE_VERSION("1.1.3.0-k");
 MODULE_LICENSE("GPL v2");
index 66fc9921fc85d22b927ea2b297fde5ca199866ee..a721b5d8a9dacdafe85257c64ea7c1f545e6f743 100644 (file)
@@ -395,6 +395,12 @@ static int vmci_host_do_send_datagram(struct vmci_host_dev *vmci_host_dev,
                return -EFAULT;
        }
 
+       if (VMCI_DG_SIZE(dg) != send_info.len) {
+               vmci_ioctl_err("datagram size mismatch\n");
+               kfree(dg);
+               return -EINVAL;
+       }
+
        pr_devel("Datagram dst (handle=0x%x:0x%x) src (handle=0x%x:0x%x), payload (size=%llu bytes)\n",
                 dg->dst.context, dg->dst.resource,
                 dg->src.context, dg->src.resource,
index 35f19a6838222e411e3ab4e427488915a9a841f8..f42d9c4e45619ae5f15cbf7cc270ad1f57b2c3f7 100644 (file)
@@ -295,12 +295,20 @@ static void *qp_alloc_queue(u64 size, u32 flags)
 {
        u64 i;
        struct vmci_queue *queue;
-       const size_t num_pages = DIV_ROUND_UP(size, PAGE_SIZE) + 1;
-       const size_t pas_size = num_pages * sizeof(*queue->kernel_if->u.g.pas);
-       const size_t vas_size = num_pages * sizeof(*queue->kernel_if->u.g.vas);
-       const size_t queue_size =
-               sizeof(*queue) + sizeof(*queue->kernel_if) +
-               pas_size + vas_size;
+       size_t pas_size;
+       size_t vas_size;
+       size_t queue_size = sizeof(*queue) + sizeof(*queue->kernel_if);
+       const u64 num_pages = DIV_ROUND_UP(size, PAGE_SIZE) + 1;
+
+       if (num_pages >
+                (SIZE_MAX - queue_size) /
+                (sizeof(*queue->kernel_if->u.g.pas) +
+                 sizeof(*queue->kernel_if->u.g.vas)))
+               return NULL;
+
+       pas_size = num_pages * sizeof(*queue->kernel_if->u.g.pas);
+       vas_size = num_pages * sizeof(*queue->kernel_if->u.g.vas);
+       queue_size += pas_size + vas_size;
 
        queue = vmalloc(queue_size);
        if (!queue)
@@ -615,10 +623,15 @@ static int qp_memcpy_from_queue_iov(void *dest,
 static struct vmci_queue *qp_host_alloc_queue(u64 size)
 {
        struct vmci_queue *queue;
-       const size_t num_pages = DIV_ROUND_UP(size, PAGE_SIZE) + 1;
+       size_t queue_page_size;
+       const u64 num_pages = DIV_ROUND_UP(size, PAGE_SIZE) + 1;
        const size_t queue_size = sizeof(*queue) + sizeof(*(queue->kernel_if));
-       const size_t queue_page_size =
-           num_pages * sizeof(*queue->kernel_if->u.h.page);
+
+       if (num_pages > (SIZE_MAX - queue_size) /
+                sizeof(*queue->kernel_if->u.h.page))
+               return NULL;
+
+       queue_page_size = num_pages * sizeof(*queue->kernel_if->u.h.page);
 
        queue = kzalloc(queue_size + queue_page_size, GFP_KERNEL);
        if (queue) {
@@ -737,7 +750,8 @@ static int qp_host_get_user_memory(u64 produce_uva,
                                     produce_q->kernel_if->num_pages, 1,
                                     produce_q->kernel_if->u.h.header_page);
        if (retval < produce_q->kernel_if->num_pages) {
-               pr_warn("get_user_pages(produce) failed (retval=%d)", retval);
+               pr_debug("get_user_pages_fast(produce) failed (retval=%d)",
+                       retval);
                qp_release_pages(produce_q->kernel_if->u.h.header_page,
                                 retval, false);
                err = VMCI_ERROR_NO_MEM;
@@ -748,7 +762,8 @@ static int qp_host_get_user_memory(u64 produce_uva,
                                     consume_q->kernel_if->num_pages, 1,
                                     consume_q->kernel_if->u.h.header_page);
        if (retval < consume_q->kernel_if->num_pages) {
-               pr_warn("get_user_pages(consume) failed (retval=%d)", retval);
+               pr_debug("get_user_pages_fast(consume) failed (retval=%d)",
+                       retval);
                qp_release_pages(consume_q->kernel_if->u.h.header_page,
                                 retval, false);
                qp_release_pages(produce_q->kernel_if->u.h.header_page,
index 2fc426926574ec0b092485313b852158272d96ae..2c25271f8c417e21982e43b2d163e65556e6aca1 100644 (file)
@@ -2418,9 +2418,8 @@ static const struct mmc_fixup blk_fixups[] =
        END_FIXUP
 };
 
-static int mmc_blk_probe(struct device *dev)
+static int mmc_blk_probe(struct mmc_card *card)
 {
-       struct mmc_card *card = mmc_dev_to_card(dev);
        struct mmc_blk_data *md, *part_md;
        char cap_str[10];
 
@@ -2445,7 +2444,7 @@ static int mmc_blk_probe(struct device *dev)
        if (mmc_blk_alloc_parts(card, md))
                goto out;
 
-       dev_set_drvdata(dev, md);
+       dev_set_drvdata(&card->dev, md);
 
        if (mmc_add_disk(md))
                goto out;
@@ -2475,10 +2474,9 @@ static int mmc_blk_probe(struct device *dev)
        return 0;
 }
 
-static int mmc_blk_remove(struct device *dev)
+static void mmc_blk_remove(struct mmc_card *card)
 {
-       struct mmc_card *card = mmc_dev_to_card(dev);
-       struct mmc_blk_data *md = dev_get_drvdata(dev);
+       struct mmc_blk_data *md = dev_get_drvdata(&card->dev);
 
        mmc_blk_remove_parts(card, md);
        pm_runtime_get_sync(&card->dev);
@@ -2489,15 +2487,13 @@ static int mmc_blk_remove(struct device *dev)
                pm_runtime_disable(&card->dev);
        pm_runtime_put_noidle(&card->dev);
        mmc_blk_remove_req(md);
-       dev_set_drvdata(dev, NULL);
-
-       return 0;
+       dev_set_drvdata(&card->dev, NULL);
 }
 
-static int _mmc_blk_suspend(struct device *dev)
+static int _mmc_blk_suspend(struct mmc_card *card)
 {
        struct mmc_blk_data *part_md;
-       struct mmc_blk_data *md = dev_get_drvdata(dev);
+       struct mmc_blk_data *md = dev_get_drvdata(&card->dev);
 
        if (md) {
                mmc_queue_suspend(&md->queue);
@@ -2508,15 +2504,17 @@ static int _mmc_blk_suspend(struct device *dev)
        return 0;
 }
 
-static void mmc_blk_shutdown(struct device *dev)
+static void mmc_blk_shutdown(struct mmc_card *card)
 {
-       _mmc_blk_suspend(dev);
+       _mmc_blk_suspend(card);
 }
 
 #ifdef CONFIG_PM_SLEEP
 static int mmc_blk_suspend(struct device *dev)
 {
-       return _mmc_blk_suspend(dev);
+       struct mmc_card *card = mmc_dev_to_card(dev);
+
+       return _mmc_blk_suspend(card);
 }
 
 static int mmc_blk_resume(struct device *dev)
@@ -2541,9 +2539,11 @@ static int mmc_blk_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(mmc_blk_pm_ops, mmc_blk_suspend, mmc_blk_resume);
 
-static struct device_driver mmc_driver = {
-       .name           = "mmcblk",
-       .pm             = &mmc_blk_pm_ops,
+static struct mmc_driver mmc_driver = {
+       .drv            = {
+               .name   = "mmcblk",
+               .pm     = &mmc_blk_pm_ops,
+       },
        .probe          = mmc_blk_probe,
        .remove         = mmc_blk_remove,
        .shutdown       = mmc_blk_shutdown,
index 7dac4695163beadb5add4817c9a13fd3abe00d4e..53b741398b9330e33136cc4b6e0b8eddae69cf96 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/mmc.h>
 #include <linux/slab.h>
-#include <linux/device.h>
 
 #include <linux/scatterlist.h>
 #include <linux/swap.h>                /* For nr_free_buffer_pages() */
@@ -2996,9 +2995,8 @@ err:
        return ret;
 }
 
-static int mmc_test_probe(struct device *dev)
+static int mmc_test_probe(struct mmc_card *card)
 {
-       struct mmc_card *card = mmc_dev_to_card(dev);
        int ret;
 
        if (!mmc_card_mmc(card) && !mmc_card_sd(card))
@@ -3013,22 +3011,20 @@ static int mmc_test_probe(struct device *dev)
        return 0;
 }
 
-static int mmc_test_remove(struct device *dev)
+static void mmc_test_remove(struct mmc_card *card)
 {
-       struct mmc_card *card = mmc_dev_to_card(dev);
-
        mmc_test_free_result(card);
        mmc_test_free_dbgfs_file(card);
-
-       return 0;
 }
 
-static void mmc_test_shutdown(struct device *dev)
+static void mmc_test_shutdown(struct mmc_card *card)
 {
 }
 
-static struct device_driver mmc_driver = {
-       .name   = "mmc_test",
+static struct mmc_driver mmc_driver = {
+       .drv            = {
+               .name   = "mmc_test",
+       },
        .probe          = mmc_test_probe,
        .remove         = mmc_test_remove,
        .shutdown       = mmc_test_shutdown,
index c5ef10065a4ae5785047381ee44597f6f5b43b4e..972ff844cf5a3ef6ff0c7cd9fe8914beb5d021b2 100644 (file)
@@ -26,6 +26,8 @@
 #include "sdio_cis.h"
 #include "bus.h"
 
+#define to_mmc_driver(d)       container_of(d, struct mmc_driver, drv)
+
 static ssize_t type_show(struct device *dev,
        struct device_attribute *attr, char *buf)
 {
@@ -105,14 +107,33 @@ mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
        return retval;
 }
 
+static int mmc_bus_probe(struct device *dev)
+{
+       struct mmc_driver *drv = to_mmc_driver(dev->driver);
+       struct mmc_card *card = mmc_dev_to_card(dev);
+
+       return drv->probe(card);
+}
+
+static int mmc_bus_remove(struct device *dev)
+{
+       struct mmc_driver *drv = to_mmc_driver(dev->driver);
+       struct mmc_card *card = mmc_dev_to_card(dev);
+
+       drv->remove(card);
+
+       return 0;
+}
+
 static void mmc_bus_shutdown(struct device *dev)
 {
+       struct mmc_driver *drv = to_mmc_driver(dev->driver);
        struct mmc_card *card = mmc_dev_to_card(dev);
        struct mmc_host *host = card->host;
        int ret;
 
-       if (dev->driver && dev->driver->shutdown)
-               dev->driver->shutdown(dev);
+       if (dev->driver && drv->shutdown)
+               drv->shutdown(card);
 
        if (host->bus_ops->shutdown) {
                ret = host->bus_ops->shutdown(host);
@@ -181,6 +202,8 @@ static struct bus_type mmc_bus_type = {
        .dev_groups     = mmc_dev_groups,
        .match          = mmc_bus_match,
        .uevent         = mmc_bus_uevent,
+       .probe          = mmc_bus_probe,
+       .remove         = mmc_bus_remove,
        .shutdown       = mmc_bus_shutdown,
        .pm             = &mmc_bus_pm_ops,
 };
@@ -199,22 +222,24 @@ void mmc_unregister_bus(void)
  *     mmc_register_driver - register a media driver
  *     @drv: MMC media driver
  */
-int mmc_register_driver(struct device_driver *drv)
+int mmc_register_driver(struct mmc_driver *drv)
 {
-       drv->bus = &mmc_bus_type;
-       return driver_register(drv);
+       drv->drv.bus = &mmc_bus_type;
+       return driver_register(&drv->drv);
 }
+
 EXPORT_SYMBOL(mmc_register_driver);
 
 /**
  *     mmc_unregister_driver - unregister a media driver
  *     @drv: MMC media driver
  */
-void mmc_unregister_driver(struct device_driver *drv)
+void mmc_unregister_driver(struct mmc_driver *drv)
 {
-       drv->bus = &mmc_bus_type;
-       driver_unregister(drv);
+       drv->drv.bus = &mmc_bus_type;
+       driver_unregister(&drv->drv);
 }
+
 EXPORT_SYMBOL(mmc_unregister_driver);
 
 static void mmc_release_card(struct device *dev)
index ab21297811610089bc79f11c413be479a0114fe0..4c1d1757dbf977f2dbe3a653cfcadbcc02e30cb6 100644 (file)
@@ -73,7 +73,7 @@ int mmc_pwrseq_alloc(struct mmc_host *host)
 
        pwrseq = match->alloc(host, &pdev->dev);
        if (IS_ERR(pwrseq)) {
-               ret = PTR_ERR(host->pwrseq);
+               ret = PTR_ERR(pwrseq);
                goto err;
        }
 
index 7f4db908f89b1a03e2f572b91e2331fa2fc44563..b1f837e749fe83d51fa4ec1410081ac44d97fb33 100644 (file)
@@ -408,14 +408,6 @@ config MMC_SDHCI_MSM
 
          If unsure, say N.
 
-config MMC_MSM
-       tristate "Qualcomm SDCC Controller Support"
-       depends on MMC && (ARCH_MSM7X00A || ARCH_MSM7X30 || ARCH_QSD8X50)
-       help
-         This provides support for the SD/MMC cell found in the
-         MSM and QSD SOCs from Qualcomm. The controller also has
-         support for SDIO devices.
-
 config MMC_MXC
        tristate "Freescale i.MX21/27/31 or MPC512x Multimedia Card support"
        depends on ARCH_MXC || PPC_MPC512x
index 711e913450f5be77d3aa0690931d827697f706c1..e3ab5b968651f53e6479b64dc7385261428e9bbf 100644 (file)
@@ -24,7 +24,6 @@ obj-$(CONFIG_MMC_OMAP)                += omap.o
 obj-$(CONFIG_MMC_OMAP_HS)      += omap_hsmmc.o
 obj-$(CONFIG_MMC_ATMELMCI)     += atmel-mci.o
 obj-$(CONFIG_MMC_TIFM_SD)      += tifm_sd.o
-obj-$(CONFIG_MMC_MSM)          += msm_sdcc.o
 obj-$(CONFIG_MMC_MVSDIO)       += mvsdio.o
 obj-$(CONFIG_MMC_DAVINCI)       += davinci_mmc.o
 obj-$(CONFIG_MMC_GOLDFISH)     += android-goldfish.o
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
deleted file mode 100644 (file)
index 90c60fd..0000000
+++ /dev/null
@@ -1,1474 +0,0 @@
-/*
- *  linux/drivers/mmc/host/msm_sdcc.c - Qualcomm MSM 7X00A SDCC Driver
- *
- *  Copyright (C) 2007 Google Inc,
- *  Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved.
- *  Copyright (C) 2009, Code Aurora Forum. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Based on mmci.c
- *
- * Author: San Mehat (san@android.com)
- *
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/highmem.h>
-#include <linux/log2.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/card.h>
-#include <linux/mmc/sdio.h>
-#include <linux/clk.h>
-#include <linux/scatterlist.h>
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/debugfs.h>
-#include <linux/io.h>
-#include <linux/memory.h>
-#include <linux/gfp.h>
-#include <linux/gpio.h>
-
-#include <asm/cacheflush.h>
-#include <asm/div64.h>
-#include <asm/sizes.h>
-
-#include <linux/platform_data/mmc-msm_sdcc.h>
-#include <mach/dma.h>
-#include <mach/clk.h>
-
-#include "msm_sdcc.h"
-
-#define DRIVER_NAME "msm-sdcc"
-
-#define BUSCLK_PWRSAVE 1
-#define BUSCLK_TIMEOUT (HZ)
-static unsigned int msmsdcc_fmin = 144000;
-static unsigned int msmsdcc_fmax = 50000000;
-static unsigned int msmsdcc_4bit = 1;
-static unsigned int msmsdcc_pwrsave = 1;
-static unsigned int msmsdcc_piopoll = 1;
-static unsigned int msmsdcc_sdioirq;
-
-#define PIO_SPINMAX 30
-#define CMD_SPINMAX 20
-
-
-static inline void
-msmsdcc_disable_clocks(struct msmsdcc_host *host, int deferr)
-{
-       WARN_ON(!host->clks_on);
-
-       BUG_ON(host->curr.mrq);
-
-       if (deferr) {
-               mod_timer(&host->busclk_timer, jiffies + BUSCLK_TIMEOUT);
-       } else {
-               del_timer_sync(&host->busclk_timer);
-               /* Need to check clks_on again in case the busclk
-                * timer fired
-                */
-               if (host->clks_on) {
-                       clk_disable(host->clk);
-                       clk_disable(host->pclk);
-                       host->clks_on = 0;
-               }
-       }
-}
-
-static inline int
-msmsdcc_enable_clocks(struct msmsdcc_host *host)
-{
-       int rc;
-
-       del_timer_sync(&host->busclk_timer);
-
-       if (!host->clks_on) {
-               rc = clk_enable(host->pclk);
-               if (rc)
-                       return rc;
-               rc = clk_enable(host->clk);
-               if (rc) {
-                       clk_disable(host->pclk);
-                       return rc;
-               }
-               udelay(1 + ((3 * USEC_PER_SEC) /
-                      (host->clk_rate ? host->clk_rate : msmsdcc_fmin)));
-               host->clks_on = 1;
-       }
-       return 0;
-}
-
-static inline unsigned int
-msmsdcc_readl(struct msmsdcc_host *host, unsigned int reg)
-{
-       return readl(host->base + reg);
-}
-
-static inline void
-msmsdcc_writel(struct msmsdcc_host *host, u32 data, unsigned int reg)
-{
-       writel(data, host->base + reg);
-       /* 3 clk delay required! */
-       udelay(1 + ((3 * USEC_PER_SEC) /
-              (host->clk_rate ? host->clk_rate : msmsdcc_fmin)));
-}
-
-static void
-msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd,
-                     u32 c);
-
-static void msmsdcc_reset_and_restore(struct msmsdcc_host *host)
-{
-       u32     mci_clk = 0;
-       u32     mci_mask0 = 0;
-       int     ret = 0;
-
-       /* Save the controller state */
-       mci_clk = readl(host->base + MMCICLOCK);
-       mci_mask0 = readl(host->base + MMCIMASK0);
-
-       /* Reset the controller */
-       ret = clk_reset(host->clk, CLK_RESET_ASSERT);
-       if (ret)
-               pr_err("%s: Clock assert failed at %u Hz with err %d\n",
-                               mmc_hostname(host->mmc), host->clk_rate, ret);
-
-       ret = clk_reset(host->clk, CLK_RESET_DEASSERT);
-       if (ret)
-               pr_err("%s: Clock deassert failed at %u Hz with err %d\n",
-                               mmc_hostname(host->mmc), host->clk_rate, ret);
-
-       pr_info("%s: Controller has been re-initialiazed\n",
-                       mmc_hostname(host->mmc));
-
-       /* Restore the contoller state */
-       writel(host->pwr, host->base + MMCIPOWER);
-       writel(mci_clk, host->base + MMCICLOCK);
-       writel(mci_mask0, host->base + MMCIMASK0);
-       ret = clk_set_rate(host->clk, host->clk_rate);
-       if (ret)
-               pr_err("%s: Failed to set clk rate %u Hz (%d)\n",
-                               mmc_hostname(host->mmc), host->clk_rate, ret);
-}
-
-static void
-msmsdcc_request_end(struct msmsdcc_host *host, struct mmc_request *mrq)
-{
-       BUG_ON(host->curr.data);
-
-       host->curr.mrq = NULL;
-       host->curr.cmd = NULL;
-
-       if (mrq->data)
-               mrq->data->bytes_xfered = host->curr.data_xfered;
-       if (mrq->cmd->error == -ETIMEDOUT)
-               mdelay(5);
-
-#if BUSCLK_PWRSAVE
-       msmsdcc_disable_clocks(host, 1);
-#endif
-       /*
-        * Need to drop the host lock here; mmc_request_done may call
-        * back into the driver...
-        */
-       spin_unlock(&host->lock);
-       mmc_request_done(host->mmc, mrq);
-       spin_lock(&host->lock);
-}
-
-static void
-msmsdcc_stop_data(struct msmsdcc_host *host)
-{
-       host->curr.data = NULL;
-       host->curr.got_dataend = 0;
-}
-
-uint32_t msmsdcc_fifo_addr(struct msmsdcc_host *host)
-{
-       return host->memres->start + MMCIFIFO;
-}
-
-static inline void
-msmsdcc_start_command_exec(struct msmsdcc_host *host, u32 arg, u32 c) {
-       msmsdcc_writel(host, arg, MMCIARGUMENT);
-       msmsdcc_writel(host, c, MMCICOMMAND);
-}
-
-static void
-msmsdcc_dma_exec_func(struct msm_dmov_cmd *cmd)
-{
-       struct msmsdcc_host *host = (struct msmsdcc_host *)cmd->data;
-
-       msmsdcc_writel(host, host->cmd_timeout, MMCIDATATIMER);
-       msmsdcc_writel(host, (unsigned int)host->curr.xfer_size,
-                      MMCIDATALENGTH);
-       msmsdcc_writel(host, (msmsdcc_readl(host, MMCIMASK0) &
-                       (~MCI_IRQ_PIO)) | host->cmd_pio_irqmask, MMCIMASK0);
-       msmsdcc_writel(host, host->cmd_datactrl, MMCIDATACTRL);
-
-       if (host->cmd_cmd) {
-               msmsdcc_start_command_exec(host,
-                                          (u32) host->cmd_cmd->arg,
-                                          (u32) host->cmd_c);
-       }
-       host->dma.active = 1;
-}
-
-static void
-msmsdcc_dma_complete_tlet(unsigned long data)
-{
-       struct msmsdcc_host *host = (struct msmsdcc_host *)data;
-       unsigned long           flags;
-       struct mmc_request      *mrq;
-       struct msm_dmov_errdata err;
-
-       spin_lock_irqsave(&host->lock, flags);
-       host->dma.active = 0;
-
-       err = host->dma.err;
-       mrq = host->curr.mrq;
-       BUG_ON(!mrq);
-       WARN_ON(!mrq->data);
-
-       if (!(host->dma.result & DMOV_RSLT_VALID)) {
-               pr_err("msmsdcc: Invalid DataMover result\n");
-               goto out;
-       }
-
-       if (host->dma.result & DMOV_RSLT_DONE) {
-               host->curr.data_xfered = host->curr.xfer_size;
-       } else {
-               /* Error or flush  */
-               if (host->dma.result & DMOV_RSLT_ERROR)
-                       pr_err("%s: DMA error (0x%.8x)\n",
-                              mmc_hostname(host->mmc), host->dma.result);
-               if (host->dma.result & DMOV_RSLT_FLUSH)
-                       pr_err("%s: DMA channel flushed (0x%.8x)\n",
-                              mmc_hostname(host->mmc), host->dma.result);
-
-               pr_err("Flush data: %.8x %.8x %.8x %.8x %.8x %.8x\n",
-                      err.flush[0], err.flush[1], err.flush[2],
-                      err.flush[3], err.flush[4], err.flush[5]);
-
-               msmsdcc_reset_and_restore(host);
-               if (!mrq->data->error)
-                       mrq->data->error = -EIO;
-       }
-       dma_unmap_sg(mmc_dev(host->mmc), host->dma.sg, host->dma.num_ents,
-                    host->dma.dir);
-
-       host->dma.sg = NULL;
-       host->dma.busy = 0;
-
-       if (host->curr.got_dataend || mrq->data->error) {
-
-               /*
-                * If we've already gotten our DATAEND / DATABLKEND
-                * for this request, then complete it through here.
-                */
-               msmsdcc_stop_data(host);
-
-               if (!mrq->data->error)
-                       host->curr.data_xfered = host->curr.xfer_size;
-               if (!mrq->data->stop || mrq->cmd->error) {
-                       host->curr.mrq = NULL;
-                       host->curr.cmd = NULL;
-                       mrq->data->bytes_xfered = host->curr.data_xfered;
-
-                       spin_unlock_irqrestore(&host->lock, flags);
-#if BUSCLK_PWRSAVE
-                       msmsdcc_disable_clocks(host, 1);
-#endif
-                       mmc_request_done(host->mmc, mrq);
-                       return;
-               } else
-                       msmsdcc_start_command(host, mrq->data->stop, 0);
-       }
-
-out:
-       spin_unlock_irqrestore(&host->lock, flags);
-       return;
-}
-
-static void
-msmsdcc_dma_complete_func(struct msm_dmov_cmd *cmd,
-                         unsigned int result,
-                         struct msm_dmov_errdata *err)
-{
-       struct msmsdcc_dma_data *dma_data =
-               container_of(cmd, struct msmsdcc_dma_data, hdr);
-       struct msmsdcc_host *host = dma_data->host;
-
-       dma_data->result = result;
-       if (err)
-               memcpy(&dma_data->err, err, sizeof(struct msm_dmov_errdata));
-
-       tasklet_schedule(&host->dma_tlet);
-}
-
-static int validate_dma(struct msmsdcc_host *host, struct mmc_data *data)
-{
-       if (host->dma.channel == -1)
-               return -ENOENT;
-
-       if ((data->blksz * data->blocks) < MCI_FIFOSIZE)
-               return -EINVAL;
-       if ((data->blksz * data->blocks) % MCI_FIFOSIZE)
-               return -EINVAL;
-       return 0;
-}
-
-static int msmsdcc_config_dma(struct msmsdcc_host *host, struct mmc_data *data)
-{
-       struct msmsdcc_nc_dmadata *nc;
-       dmov_box *box;
-       uint32_t rows;
-       uint32_t crci;
-       unsigned int n;
-       int i, rc;
-       struct scatterlist *sg = data->sg;
-
-       rc = validate_dma(host, data);
-       if (rc)
-               return rc;
-
-       host->dma.sg = data->sg;
-       host->dma.num_ents = data->sg_len;
-
-       BUG_ON(host->dma.num_ents > NR_SG); /* Prevent memory corruption */
-
-       nc = host->dma.nc;
-
-       switch (host->pdev_id) {
-       case 1:
-               crci = MSMSDCC_CRCI_SDC1;
-               break;
-       case 2:
-               crci = MSMSDCC_CRCI_SDC2;
-               break;
-       case 3:
-               crci = MSMSDCC_CRCI_SDC3;
-               break;
-       case 4:
-               crci = MSMSDCC_CRCI_SDC4;
-               break;
-       default:
-               host->dma.sg = NULL;
-               host->dma.num_ents = 0;
-               return -ENOENT;
-       }
-
-       if (data->flags & MMC_DATA_READ)
-               host->dma.dir = DMA_FROM_DEVICE;
-       else
-               host->dma.dir = DMA_TO_DEVICE;
-
-       host->curr.user_pages = 0;
-
-       box = &nc->cmd[0];
-
-       /* location of command block must be 64 bit aligned */
-       BUG_ON(host->dma.cmd_busaddr & 0x07);
-
-       nc->cmdptr = (host->dma.cmd_busaddr >> 3) | CMD_PTR_LP;
-       host->dma.hdr.cmdptr = DMOV_CMD_PTR_LIST |
-                              DMOV_CMD_ADDR(host->dma.cmdptr_busaddr);
-       host->dma.hdr.complete_func = msmsdcc_dma_complete_func;
-
-       n = dma_map_sg(mmc_dev(host->mmc), host->dma.sg,
-                       host->dma.num_ents, host->dma.dir);
-       if (n == 0) {
-               pr_err("%s: Unable to map in all sg elements\n",
-                       mmc_hostname(host->mmc));
-               host->dma.sg = NULL;
-               host->dma.num_ents = 0;
-               return -ENOMEM;
-       }
-
-       for_each_sg(host->dma.sg, sg, n, i) {
-
-               box->cmd = CMD_MODE_BOX;
-
-               if (i == n - 1)
-                       box->cmd |= CMD_LC;
-               rows = (sg_dma_len(sg) % MCI_FIFOSIZE) ?
-                       (sg_dma_len(sg) / MCI_FIFOSIZE) + 1 :
-                       (sg_dma_len(sg) / MCI_FIFOSIZE) ;
-
-               if (data->flags & MMC_DATA_READ) {
-                       box->src_row_addr = msmsdcc_fifo_addr(host);
-                       box->dst_row_addr = sg_dma_address(sg);
-
-                       box->src_dst_len = (MCI_FIFOSIZE << 16) |
-                                          (MCI_FIFOSIZE);
-                       box->row_offset = MCI_FIFOSIZE;
-
-                       box->num_rows = rows * ((1 << 16) + 1);
-                       box->cmd |= CMD_SRC_CRCI(crci);
-               } else {
-                       box->src_row_addr = sg_dma_address(sg);
-                       box->dst_row_addr = msmsdcc_fifo_addr(host);
-
-                       box->src_dst_len = (MCI_FIFOSIZE << 16) |
-                                          (MCI_FIFOSIZE);
-                       box->row_offset = (MCI_FIFOSIZE << 16);
-
-                       box->num_rows = rows * ((1 << 16) + 1);
-                       box->cmd |= CMD_DST_CRCI(crci);
-               }
-               box++;
-       }
-
-       return 0;
-}
-
-static int
-snoop_cccr_abort(struct mmc_command *cmd)
-{
-       if ((cmd->opcode == 52) &&
-           (cmd->arg & 0x80000000) &&
-           (((cmd->arg >> 9) & 0x1ffff) == SDIO_CCCR_ABORT))
-               return 1;
-       return 0;
-}
-
-static void
-msmsdcc_start_command_deferred(struct msmsdcc_host *host,
-                               struct mmc_command *cmd, u32 *c)
-{
-       *c |= (cmd->opcode | MCI_CPSM_ENABLE);
-
-       if (cmd->flags & MMC_RSP_PRESENT) {
-               if (cmd->flags & MMC_RSP_136)
-                       *c |= MCI_CPSM_LONGRSP;
-               *c |= MCI_CPSM_RESPONSE;
-       }
-
-       if (/*interrupt*/0)
-               *c |= MCI_CPSM_INTERRUPT;
-
-       if ((((cmd->opcode == 17) || (cmd->opcode == 18))  ||
-            ((cmd->opcode == 24) || (cmd->opcode == 25))) ||
-             (cmd->opcode == 53))
-               *c |= MCI_CSPM_DATCMD;
-
-       if (host->prog_scan && (cmd->opcode == 12)) {
-               *c |= MCI_CPSM_PROGENA;
-               host->prog_enable = true;
-       }
-
-       if (cmd == cmd->mrq->stop)
-               *c |= MCI_CSPM_MCIABORT;
-
-       if (snoop_cccr_abort(cmd))
-               *c |= MCI_CSPM_MCIABORT;
-
-       if (host->curr.cmd != NULL) {
-               pr_err("%s: Overlapping command requests\n",
-                       mmc_hostname(host->mmc));
-       }
-       host->curr.cmd = cmd;
-}
-
-static void
-msmsdcc_start_data(struct msmsdcc_host *host, struct mmc_data *data,
-                       struct mmc_command *cmd, u32 c)
-{
-       unsigned int datactrl, timeout;
-       unsigned long long clks;
-       unsigned int pio_irqmask = 0;
-
-       host->curr.data = data;
-       host->curr.xfer_size = data->blksz * data->blocks;
-       host->curr.xfer_remain = host->curr.xfer_size;
-       host->curr.data_xfered = 0;
-       host->curr.got_dataend = 0;
-
-       memset(&host->pio, 0, sizeof(host->pio));
-
-       datactrl = MCI_DPSM_ENABLE | (data->blksz << 4);
-
-       if (!msmsdcc_config_dma(host, data))
-               datactrl |= MCI_DPSM_DMAENABLE;
-       else {
-               host->pio.sg = data->sg;
-               host->pio.sg_len = data->sg_len;
-               host->pio.sg_off = 0;
-
-               if (data->flags & MMC_DATA_READ) {
-                       pio_irqmask = MCI_RXFIFOHALFFULLMASK;
-                       if (host->curr.xfer_remain < MCI_FIFOSIZE)
-                               pio_irqmask |= MCI_RXDATAAVLBLMASK;
-               } else
-                       pio_irqmask = MCI_TXFIFOHALFEMPTYMASK;
-       }
-
-       if (data->flags & MMC_DATA_READ)
-               datactrl |= MCI_DPSM_DIRECTION;
-
-       clks = (unsigned long long)data->timeout_ns * host->clk_rate;
-       do_div(clks, NSEC_PER_SEC);
-       timeout = data->timeout_clks + (unsigned int)clks*2 ;
-
-       if (datactrl & MCI_DPSM_DMAENABLE) {
-               /* Save parameters for the exec function */
-               host->cmd_timeout = timeout;
-               host->cmd_pio_irqmask = pio_irqmask;
-               host->cmd_datactrl = datactrl;
-               host->cmd_cmd = cmd;
-
-               host->dma.hdr.execute_func = msmsdcc_dma_exec_func;
-               host->dma.hdr.data = (void *)host;
-               host->dma.busy = 1;
-
-               if (cmd) {
-                       msmsdcc_start_command_deferred(host, cmd, &c);
-                       host->cmd_c = c;
-               }
-               msm_dmov_enqueue_cmd(host->dma.channel, &host->dma.hdr);
-               if (data->flags & MMC_DATA_WRITE)
-                       host->prog_scan = true;
-       } else {
-               msmsdcc_writel(host, timeout, MMCIDATATIMER);
-
-               msmsdcc_writel(host, host->curr.xfer_size, MMCIDATALENGTH);
-
-               msmsdcc_writel(host, (msmsdcc_readl(host, MMCIMASK0) &
-                               (~MCI_IRQ_PIO)) | pio_irqmask, MMCIMASK0);
-
-               msmsdcc_writel(host, datactrl, MMCIDATACTRL);
-
-               if (cmd) {
-                       /* Daisy-chain the command if requested */
-                       msmsdcc_start_command(host, cmd, c);
-               }
-       }
-}
-
-static void
-msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd, u32 c)
-{
-       if (cmd == cmd->mrq->stop)
-               c |= MCI_CSPM_MCIABORT;
-
-       host->stats.cmds++;
-
-       msmsdcc_start_command_deferred(host, cmd, &c);
-       msmsdcc_start_command_exec(host, cmd->arg, c);
-}
-
-static void
-msmsdcc_data_err(struct msmsdcc_host *host, struct mmc_data *data,
-                unsigned int status)
-{
-       if (status & MCI_DATACRCFAIL) {
-               pr_err("%s: Data CRC error\n", mmc_hostname(host->mmc));
-               pr_err("%s: opcode 0x%.8x\n", __func__,
-                      data->mrq->cmd->opcode);
-               pr_err("%s: blksz %d, blocks %d\n", __func__,
-                      data->blksz, data->blocks);
-               data->error = -EILSEQ;
-       } else if (status & MCI_DATATIMEOUT) {
-               pr_err("%s: Data timeout\n", mmc_hostname(host->mmc));
-               data->error = -ETIMEDOUT;
-       } else if (status & MCI_RXOVERRUN) {
-               pr_err("%s: RX overrun\n", mmc_hostname(host->mmc));
-               data->error = -EIO;
-       } else if (status & MCI_TXUNDERRUN) {
-               pr_err("%s: TX underrun\n", mmc_hostname(host->mmc));
-               data->error = -EIO;
-       } else {
-               pr_err("%s: Unknown error (0x%.8x)\n",
-                      mmc_hostname(host->mmc), status);
-               data->error = -EIO;
-       }
-}
-
-
-static int
-msmsdcc_pio_read(struct msmsdcc_host *host, char *buffer, unsigned int remain)
-{
-       uint32_t        *ptr = (uint32_t *) buffer;
-       int             count = 0;
-
-       if (remain % 4)
-               remain = ((remain >> 2) + 1) << 2;
-
-       while (msmsdcc_readl(host, MMCISTATUS) & MCI_RXDATAAVLBL) {
-               *ptr = msmsdcc_readl(host, MMCIFIFO + (count % MCI_FIFOSIZE));
-               ptr++;
-               count += sizeof(uint32_t);
-
-               remain -=  sizeof(uint32_t);
-               if (remain == 0)
-                       break;
-       }
-       return count;
-}
-
-static int
-msmsdcc_pio_write(struct msmsdcc_host *host, char *buffer,
-                 unsigned int remain, u32 status)
-{
-       void __iomem *base = host->base;
-       char *ptr = buffer;
-
-       do {
-               unsigned int count, maxcnt, sz;
-
-               maxcnt = status & MCI_TXFIFOEMPTY ? MCI_FIFOSIZE :
-                                                   MCI_FIFOHALFSIZE;
-               count = min(remain, maxcnt);
-
-               sz = count % 4 ? (count >> 2) + 1 : (count >> 2);
-               writesl(base + MMCIFIFO, ptr, sz);
-               ptr += count;
-               remain -= count;
-
-               if (remain == 0)
-                       break;
-
-               status = msmsdcc_readl(host, MMCISTATUS);
-       } while (status & MCI_TXFIFOHALFEMPTY);
-
-       return ptr - buffer;
-}
-
-static int
-msmsdcc_spin_on_status(struct msmsdcc_host *host, uint32_t mask, int maxspin)
-{
-       while (maxspin) {
-               if ((msmsdcc_readl(host, MMCISTATUS) & mask))
-                       return 0;
-               udelay(1);
-               --maxspin;
-       }
-       return -ETIMEDOUT;
-}
-
-static irqreturn_t
-msmsdcc_pio_irq(int irq, void *dev_id)
-{
-       struct msmsdcc_host     *host = dev_id;
-       uint32_t                status;
-       u32 mci_mask0;
-
-       status = msmsdcc_readl(host, MMCISTATUS);
-       mci_mask0 = msmsdcc_readl(host, MMCIMASK0);
-
-       if (((mci_mask0 & status) & MCI_IRQ_PIO) == 0)
-               return IRQ_NONE;
-
-       do {
-               unsigned long flags;
-               unsigned int remain, len;
-               char *buffer;
-
-               if (!(status & (MCI_TXFIFOHALFEMPTY | MCI_RXDATAAVLBL))) {
-                       if (host->curr.xfer_remain == 0 || !msmsdcc_piopoll)
-                               break;
-
-                       if (msmsdcc_spin_on_status(host,
-                                                  (MCI_TXFIFOHALFEMPTY |
-                                                  MCI_RXDATAAVLBL),
-                                                  PIO_SPINMAX)) {
-                               break;
-                       }
-               }
-
-               /* Map the current scatter buffer */
-               local_irq_save(flags);
-               buffer = kmap_atomic(sg_page(host->pio.sg))
-                                    + host->pio.sg->offset;
-               buffer += host->pio.sg_off;
-               remain = host->pio.sg->length - host->pio.sg_off;
-               len = 0;
-               if (status & MCI_RXACTIVE)
-                       len = msmsdcc_pio_read(host, buffer, remain);
-               if (status & MCI_TXACTIVE)
-                       len = msmsdcc_pio_write(host, buffer, remain, status);
-
-               /* Unmap the buffer */
-               kunmap_atomic(buffer);
-               local_irq_restore(flags);
-
-               host->pio.sg_off += len;
-               host->curr.xfer_remain -= len;
-               host->curr.data_xfered += len;
-               remain -= len;
-
-               if (remain == 0) {
-                       /* This sg page is full - do some housekeeping */
-                       if (status & MCI_RXACTIVE && host->curr.user_pages)
-                               flush_dcache_page(sg_page(host->pio.sg));
-
-                       if (!--host->pio.sg_len) {
-                               memset(&host->pio, 0, sizeof(host->pio));
-                               break;
-                       }
-
-                       /* Advance to next sg */
-                       host->pio.sg++;
-                       host->pio.sg_off = 0;
-               }
-
-               status = msmsdcc_readl(host, MMCISTATUS);
-       } while (1);
-
-       if (status & MCI_RXACTIVE && host->curr.xfer_remain < MCI_FIFOSIZE)
-               msmsdcc_writel(host, (mci_mask0 & (~MCI_IRQ_PIO)) |
-                                       MCI_RXDATAAVLBLMASK, MMCIMASK0);
-
-       if (!host->curr.xfer_remain)
-               msmsdcc_writel(host, (mci_mask0 & (~MCI_IRQ_PIO)) | 0,
-                                       MMCIMASK0);
-
-       return IRQ_HANDLED;
-}
-
-static void msmsdcc_do_cmdirq(struct msmsdcc_host *host, uint32_t status)
-{
-       struct mmc_command *cmd = host->curr.cmd;
-
-       host->curr.cmd = NULL;
-       cmd->resp[0] = msmsdcc_readl(host, MMCIRESPONSE0);
-       cmd->resp[1] = msmsdcc_readl(host, MMCIRESPONSE1);
-       cmd->resp[2] = msmsdcc_readl(host, MMCIRESPONSE2);
-       cmd->resp[3] = msmsdcc_readl(host, MMCIRESPONSE3);
-
-       if (status & MCI_CMDTIMEOUT) {
-               cmd->error = -ETIMEDOUT;
-       } else if (status & MCI_CMDCRCFAIL &&
-                  cmd->flags & MMC_RSP_CRC) {
-               pr_err("%s: Command CRC error\n", mmc_hostname(host->mmc));
-               cmd->error = -EILSEQ;
-       }
-
-       if (!cmd->data || cmd->error) {
-               if (host->curr.data && host->dma.sg)
-                       msm_dmov_stop_cmd(host->dma.channel,
-                                         &host->dma.hdr, 0);
-               else if (host->curr.data) { /* Non DMA */
-                       msmsdcc_reset_and_restore(host);
-                       msmsdcc_stop_data(host);
-                       msmsdcc_request_end(host, cmd->mrq);
-               } else { /* host->data == NULL */
-                       if (!cmd->error && host->prog_enable) {
-                               if (status & MCI_PROGDONE) {
-                                       host->prog_scan = false;
-                                       host->prog_enable = false;
-                                       msmsdcc_request_end(host, cmd->mrq);
-                               } else {
-                                       host->curr.cmd = cmd;
-                               }
-                       } else {
-                               if (host->prog_enable) {
-                                       host->prog_scan = false;
-                                       host->prog_enable = false;
-                               }
-                               msmsdcc_request_end(host, cmd->mrq);
-                       }
-               }
-       } else if (cmd->data)
-               if (!(cmd->data->flags & MMC_DATA_READ))
-                       msmsdcc_start_data(host, cmd->data,
-                                               NULL, 0);
-}
-
-static void
-msmsdcc_handle_irq_data(struct msmsdcc_host *host, u32 status,
-                       void __iomem *base)
-{
-       struct mmc_data *data = host->curr.data;
-
-       if (status & (MCI_CMDSENT | MCI_CMDRESPEND | MCI_CMDCRCFAIL |
-                       MCI_CMDTIMEOUT | MCI_PROGDONE) && host->curr.cmd) {
-               msmsdcc_do_cmdirq(host, status);
-       }
-
-       if (!data)
-               return;
-
-       /* Check for data errors */
-       if (status & (MCI_DATACRCFAIL | MCI_DATATIMEOUT |
-                     MCI_TXUNDERRUN | MCI_RXOVERRUN)) {
-               msmsdcc_data_err(host, data, status);
-               host->curr.data_xfered = 0;
-               if (host->dma.sg)
-                       msm_dmov_stop_cmd(host->dma.channel,
-                                         &host->dma.hdr, 0);
-               else {
-                       msmsdcc_reset_and_restore(host);
-                       if (host->curr.data)
-                               msmsdcc_stop_data(host);
-                       if (!data->stop)
-                               msmsdcc_request_end(host, data->mrq);
-                       else
-                               msmsdcc_start_command(host, data->stop, 0);
-               }
-       }
-
-       /* Check for data done */
-       if (!host->curr.got_dataend && (status & MCI_DATAEND))
-               host->curr.got_dataend = 1;
-
-       /*
-        * If DMA is still in progress, we complete via the completion handler
-        */
-       if (host->curr.got_dataend && !host->dma.busy) {
-               /*
-                * There appears to be an issue in the controller where
-                * if you request a small block transfer (< fifo size),
-                * you may get your DATAEND/DATABLKEND irq without the
-                * PIO data irq.
-                *
-                * Check to see if there is still data to be read,
-                * and simulate a PIO irq.
-                */
-               if (readl(base + MMCISTATUS) & MCI_RXDATAAVLBL)
-                       msmsdcc_pio_irq(1, host);
-
-               msmsdcc_stop_data(host);
-               if (!data->error)
-                       host->curr.data_xfered = host->curr.xfer_size;
-
-               if (!data->stop)
-                       msmsdcc_request_end(host, data->mrq);
-               else
-                       msmsdcc_start_command(host, data->stop, 0);
-       }
-}
-
-static irqreturn_t
-msmsdcc_irq(int irq, void *dev_id)
-{
-       struct msmsdcc_host     *host = dev_id;
-       void __iomem            *base = host->base;
-       u32                     status;
-       int                     ret = 0;
-       int                     cardint = 0;
-
-       spin_lock(&host->lock);
-
-       do {
-               status = msmsdcc_readl(host, MMCISTATUS);
-               status &= msmsdcc_readl(host, MMCIMASK0);
-               if ((status & (~MCI_IRQ_PIO)) == 0)
-                       break;
-               msmsdcc_writel(host, status, MMCICLEAR);
-
-               if (status & MCI_SDIOINTR)
-                       status &= ~MCI_SDIOINTR;
-
-               if (!status)
-                       break;
-
-               msmsdcc_handle_irq_data(host, status, base);
-
-               if (status & MCI_SDIOINTOPER) {
-                       cardint = 1;
-                       status &= ~MCI_SDIOINTOPER;
-               }
-               ret = 1;
-       } while (status);
-
-       spin_unlock(&host->lock);
-
-       /*
-        * We have to delay handling the card interrupt as it calls
-        * back into the driver.
-        */
-       if (cardint)
-               mmc_signal_sdio_irq(host->mmc);
-
-       return IRQ_RETVAL(ret);
-}
-
-static void
-msmsdcc_request(struct mmc_host *mmc, struct mmc_request *mrq)
-{
-       struct msmsdcc_host *host = mmc_priv(mmc);
-       unsigned long flags;
-
-       WARN_ON(host->curr.mrq != NULL);
-       WARN_ON(host->pwr == 0);
-
-       spin_lock_irqsave(&host->lock, flags);
-
-       host->stats.reqs++;
-
-       if (host->eject) {
-               if (mrq->data && !(mrq->data->flags & MMC_DATA_READ)) {
-                       mrq->cmd->error = 0;
-                       mrq->data->bytes_xfered = mrq->data->blksz *
-                                                 mrq->data->blocks;
-               } else
-                       mrq->cmd->error = -ENOMEDIUM;
-
-               spin_unlock_irqrestore(&host->lock, flags);
-               mmc_request_done(mmc, mrq);
-               return;
-       }
-
-       msmsdcc_enable_clocks(host);
-
-       host->curr.mrq = mrq;
-
-       if (mrq->data && mrq->data->flags & MMC_DATA_READ)
-               /* Queue/read data, daisy-chain command when data starts */
-               msmsdcc_start_data(host, mrq->data, mrq->cmd, 0);
-       else
-               msmsdcc_start_command(host, mrq->cmd, 0);
-
-       if (host->cmdpoll && !msmsdcc_spin_on_status(host,
-                               MCI_CMDRESPEND|MCI_CMDCRCFAIL|MCI_CMDTIMEOUT,
-                               CMD_SPINMAX)) {
-               uint32_t status = msmsdcc_readl(host, MMCISTATUS);
-               msmsdcc_do_cmdirq(host, status);
-               msmsdcc_writel(host,
-                              MCI_CMDRESPEND | MCI_CMDCRCFAIL | MCI_CMDTIMEOUT,
-                              MMCICLEAR);
-               host->stats.cmdpoll_hits++;
-       } else {
-               host->stats.cmdpoll_misses++;
-       }
-       spin_unlock_irqrestore(&host->lock, flags);
-}
-
-static void msmsdcc_setup_gpio(struct msmsdcc_host *host, bool enable)
-{
-       struct msm_mmc_gpio_data *curr;
-       int i, rc = 0;
-
-       if (!host->plat->gpio_data || host->gpio_config_status == enable)
-               return;
-
-       curr = host->plat->gpio_data;
-       for (i = 0; i < curr->size; i++) {
-               if (enable) {
-                       rc = gpio_request(curr->gpio[i].no,
-                                               curr->gpio[i].name);
-                       if (rc) {
-                               pr_err("%s: gpio_request(%d, %s) failed %d\n",
-                                       mmc_hostname(host->mmc),
-                                       curr->gpio[i].no,
-                                       curr->gpio[i].name, rc);
-                               goto free_gpios;
-                       }
-               } else {
-                       gpio_free(curr->gpio[i].no);
-               }
-       }
-       host->gpio_config_status = enable;
-       return;
-
-free_gpios:
-       for (; i >= 0; i--)
-               gpio_free(curr->gpio[i].no);
-}
-
-static void
-msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
-{
-       struct msmsdcc_host *host = mmc_priv(mmc);
-       u32 clk = 0, pwr = 0;
-       int rc;
-       unsigned long flags;
-
-       spin_lock_irqsave(&host->lock, flags);
-
-       msmsdcc_enable_clocks(host);
-
-       spin_unlock_irqrestore(&host->lock, flags);
-
-       if (ios->clock) {
-               if (ios->clock != host->clk_rate) {
-                       rc = clk_set_rate(host->clk, ios->clock);
-                       if (rc < 0)
-                               pr_err("%s: Error setting clock rate (%d)\n",
-                                      mmc_hostname(host->mmc), rc);
-                       else
-                               host->clk_rate = ios->clock;
-               }
-               clk |= MCI_CLK_ENABLE;
-       }
-
-       if (ios->bus_width == MMC_BUS_WIDTH_4)
-               clk |= (2 << 10); /* Set WIDEBUS */
-
-       if (ios->clock > 400000 && msmsdcc_pwrsave)
-               clk |= (1 << 9); /* PWRSAVE */
-
-       clk |= (1 << 12); /* FLOW_ENA */
-       clk |= (1 << 15); /* feedback clock */
-
-       if (host->plat->translate_vdd)
-               pwr |= host->plat->translate_vdd(mmc_dev(mmc), ios->vdd);
-
-       switch (ios->power_mode) {
-       case MMC_POWER_OFF:
-               msmsdcc_setup_gpio(host, false);
-               break;
-       case MMC_POWER_UP:
-               pwr |= MCI_PWR_UP;
-               msmsdcc_setup_gpio(host, true);
-               break;
-       case MMC_POWER_ON:
-               pwr |= MCI_PWR_ON;
-               break;
-       }
-
-       if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
-               pwr |= MCI_OD;
-
-       msmsdcc_writel(host, clk, MMCICLOCK);
-
-       if (host->pwr != pwr) {
-               host->pwr = pwr;
-               msmsdcc_writel(host, pwr, MMCIPOWER);
-       }
-#if BUSCLK_PWRSAVE
-       spin_lock_irqsave(&host->lock, flags);
-       msmsdcc_disable_clocks(host, 1);
-       spin_unlock_irqrestore(&host->lock, flags);
-#endif
-}
-
-static void msmsdcc_enable_sdio_irq(struct mmc_host *mmc, int enable)
-{
-       struct msmsdcc_host *host = mmc_priv(mmc);
-       unsigned long flags;
-       u32 status;
-
-       spin_lock_irqsave(&host->lock, flags);
-       if (msmsdcc_sdioirq == 1) {
-               status = msmsdcc_readl(host, MMCIMASK0);
-               if (enable)
-                       status |= MCI_SDIOINTOPERMASK;
-               else
-                       status &= ~MCI_SDIOINTOPERMASK;
-               host->saved_irq0mask = status;
-               msmsdcc_writel(host, status, MMCIMASK0);
-       }
-       spin_unlock_irqrestore(&host->lock, flags);
-}
-
-static void msmsdcc_init_card(struct mmc_host *mmc, struct mmc_card *card)
-{
-       struct msmsdcc_host *host = mmc_priv(mmc);
-
-       if (host->plat->init_card)
-               host->plat->init_card(card);
-}
-
-static const struct mmc_host_ops msmsdcc_ops = {
-       .request        = msmsdcc_request,
-       .set_ios        = msmsdcc_set_ios,
-       .enable_sdio_irq = msmsdcc_enable_sdio_irq,
-       .init_card      = msmsdcc_init_card,
-};
-
-static void
-msmsdcc_check_status(unsigned long data)
-{
-       struct msmsdcc_host *host = (struct msmsdcc_host *)data;
-       unsigned int status;
-
-       if (!host->plat->status) {
-               mmc_detect_change(host->mmc, 0);
-               goto out;
-       }
-
-       status = host->plat->status(mmc_dev(host->mmc));
-       host->eject = !status;
-       if (status ^ host->oldstat) {
-               pr_info("%s: Slot status change detected (%d -> %d)\n",
-                       mmc_hostname(host->mmc), host->oldstat, status);
-               if (status)
-                       mmc_detect_change(host->mmc, (5 * HZ) / 2);
-               else
-                       mmc_detect_change(host->mmc, 0);
-       }
-
-       host->oldstat = status;
-
-out:
-       if (host->timer.function)
-               mod_timer(&host->timer, jiffies + HZ);
-}
-
-static irqreturn_t
-msmsdcc_platform_status_irq(int irq, void *dev_id)
-{
-       struct msmsdcc_host *host = dev_id;
-
-       pr_debug("%s: %d\n", __func__, irq);
-       msmsdcc_check_status((unsigned long) host);
-       return IRQ_HANDLED;
-}
-
-static void
-msmsdcc_status_notify_cb(int card_present, void *dev_id)
-{
-       struct msmsdcc_host *host = dev_id;
-
-       pr_debug("%s: card_present %d\n", mmc_hostname(host->mmc),
-              card_present);
-       msmsdcc_check_status((unsigned long) host);
-}
-
-static void
-msmsdcc_busclk_expired(unsigned long _data)
-{
-       struct msmsdcc_host     *host = (struct msmsdcc_host *) _data;
-
-       if (host->clks_on)
-               msmsdcc_disable_clocks(host, 0);
-}
-
-static int
-msmsdcc_init_dma(struct msmsdcc_host *host)
-{
-       memset(&host->dma, 0, sizeof(struct msmsdcc_dma_data));
-       host->dma.host = host;
-       host->dma.channel = -1;
-
-       if (!host->dmares)
-               return -ENODEV;
-
-       host->dma.nc = dma_alloc_coherent(NULL,
-                                         sizeof(struct msmsdcc_nc_dmadata),
-                                         &host->dma.nc_busaddr,
-                                         GFP_KERNEL);
-       if (host->dma.nc == NULL) {
-               pr_err("Unable to allocate DMA buffer\n");
-               return -ENOMEM;
-       }
-       memset(host->dma.nc, 0x00, sizeof(struct msmsdcc_nc_dmadata));
-       host->dma.cmd_busaddr = host->dma.nc_busaddr;
-       host->dma.cmdptr_busaddr = host->dma.nc_busaddr +
-                               offsetof(struct msmsdcc_nc_dmadata, cmdptr);
-       host->dma.channel = host->dmares->start;
-
-       return 0;
-}
-
-static int
-msmsdcc_probe(struct platform_device *pdev)
-{
-       struct msm_mmc_platform_data *plat = pdev->dev.platform_data;
-       struct msmsdcc_host *host;
-       struct mmc_host *mmc;
-       struct resource *cmd_irqres = NULL;
-       struct resource *stat_irqres = NULL;
-       struct resource *memres = NULL;
-       struct resource *dmares = NULL;
-       int ret;
-
-       /* must have platform data */
-       if (!plat) {
-               pr_err("%s: Platform data not available\n", __func__);
-               ret = -EINVAL;
-               goto out;
-       }
-
-       if (pdev->id < 1 || pdev->id > 4)
-               return -EINVAL;
-
-       if (pdev->resource == NULL || pdev->num_resources < 2) {
-               pr_err("%s: Invalid resource\n", __func__);
-               return -ENXIO;
-       }
-
-       memres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-       cmd_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
-                                                 "cmd_irq");
-       stat_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
-                                                  "status_irq");
-
-       if (!cmd_irqres || !memres) {
-               pr_err("%s: Invalid resource\n", __func__);
-               return -ENXIO;
-       }
-
-       /*
-        * Setup our host structure
-        */
-
-       mmc = mmc_alloc_host(sizeof(struct msmsdcc_host), &pdev->dev);
-       if (!mmc) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       host = mmc_priv(mmc);
-       host->pdev_id = pdev->id;
-       host->plat = plat;
-       host->mmc = mmc;
-       host->curr.cmd = NULL;
-       init_timer(&host->busclk_timer);
-       host->busclk_timer.data = (unsigned long) host;
-       host->busclk_timer.function = msmsdcc_busclk_expired;
-
-
-       host->cmdpoll = 1;
-
-       host->base = ioremap(memres->start, PAGE_SIZE);
-       if (!host->base) {
-               ret = -ENOMEM;
-               goto host_free;
-       }
-
-       host->cmd_irqres = cmd_irqres;
-       host->memres = memres;
-       host->dmares = dmares;
-       spin_lock_init(&host->lock);
-
-       tasklet_init(&host->dma_tlet, msmsdcc_dma_complete_tlet,
-                       (unsigned long)host);
-
-       /*
-        * Setup DMA
-        */
-       if (host->dmares) {
-               ret = msmsdcc_init_dma(host);
-               if (ret)
-                       goto ioremap_free;
-       } else {
-               host->dma.channel = -1;
-       }
-
-       /* Get our clocks */
-       host->pclk = clk_get(&pdev->dev, "sdc_pclk");
-       if (IS_ERR(host->pclk)) {
-               ret = PTR_ERR(host->pclk);
-               goto dma_free;
-       }
-
-       host->clk = clk_get(&pdev->dev, "sdc_clk");
-       if (IS_ERR(host->clk)) {
-               ret = PTR_ERR(host->clk);
-               goto pclk_put;
-       }
-
-       ret = clk_set_rate(host->clk, msmsdcc_fmin);
-       if (ret) {
-               pr_err("%s: Clock rate set failed (%d)\n", __func__, ret);
-               goto clk_put;
-       }
-
-       ret = clk_prepare(host->pclk);
-       if (ret)
-               goto clk_put;
-
-       ret = clk_prepare(host->clk);
-       if (ret)
-               goto clk_unprepare_p;
-
-       /* Enable clocks */
-       ret = msmsdcc_enable_clocks(host);
-       if (ret)
-               goto clk_unprepare;
-
-       host->pclk_rate = clk_get_rate(host->pclk);
-       host->clk_rate = clk_get_rate(host->clk);
-
-       /*
-        * Setup MMC host structure
-        */
-       mmc->ops = &msmsdcc_ops;
-       mmc->f_min = msmsdcc_fmin;
-       mmc->f_max = msmsdcc_fmax;
-       mmc->ocr_avail = plat->ocr_mask;
-
-       if (msmsdcc_4bit)
-               mmc->caps |= MMC_CAP_4_BIT_DATA;
-       if (msmsdcc_sdioirq)
-               mmc->caps |= MMC_CAP_SDIO_IRQ;
-       mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
-
-       mmc->max_segs = NR_SG;
-       mmc->max_blk_size = 4096;       /* MCI_DATA_CTL BLOCKSIZE up to 4096 */
-       mmc->max_blk_count = 65536;
-
-       mmc->max_req_size = 33554432;   /* MCI_DATA_LENGTH is 25 bits */
-       mmc->max_seg_size = mmc->max_req_size;
-
-       msmsdcc_writel(host, 0, MMCIMASK0);
-       msmsdcc_writel(host, 0x5e007ff, MMCICLEAR);
-
-       msmsdcc_writel(host, MCI_IRQENABLE, MMCIMASK0);
-       host->saved_irq0mask = MCI_IRQENABLE;
-
-       /*
-        * Setup card detect change
-        */
-
-       memset(&host->timer, 0, sizeof(host->timer));
-
-       if (stat_irqres && !(stat_irqres->flags & IORESOURCE_DISABLED)) {
-               unsigned long irqflags = IRQF_SHARED |
-                       (stat_irqres->flags & IRQF_TRIGGER_MASK);
-
-               host->stat_irq = stat_irqres->start;
-               ret = request_irq(host->stat_irq,
-                                 msmsdcc_platform_status_irq,
-                                 irqflags,
-                                 DRIVER_NAME " (slot)",
-                                 host);
-               if (ret) {
-                       pr_err("%s: Unable to get slot IRQ %d (%d)\n",
-                              mmc_hostname(mmc), host->stat_irq, ret);
-                       goto clk_disable;
-               }
-       } else if (plat->register_status_notify) {
-               plat->register_status_notify(msmsdcc_status_notify_cb, host);
-       } else if (!plat->status)
-               pr_err("%s: No card detect facilities available\n",
-                      mmc_hostname(mmc));
-       else {
-               init_timer(&host->timer);
-               host->timer.data = (unsigned long)host;
-               host->timer.function = msmsdcc_check_status;
-               host->timer.expires = jiffies + HZ;
-               add_timer(&host->timer);
-       }
-
-       if (plat->status) {
-               host->oldstat = host->plat->status(mmc_dev(host->mmc));
-               host->eject = !host->oldstat;
-       }
-
-       ret = request_irq(cmd_irqres->start, msmsdcc_irq, IRQF_SHARED,
-                         DRIVER_NAME " (cmd)", host);
-       if (ret)
-               goto stat_irq_free;
-
-       ret = request_irq(cmd_irqres->start, msmsdcc_pio_irq, IRQF_SHARED,
-                         DRIVER_NAME " (pio)", host);
-       if (ret)
-               goto cmd_irq_free;
-
-       platform_set_drvdata(pdev, mmc);
-       mmc_add_host(mmc);
-
-       pr_info("%s: Qualcomm MSM SDCC at 0x%016llx irq %d,%d dma %d\n",
-               mmc_hostname(mmc), (unsigned long long)memres->start,
-               (unsigned int) cmd_irqres->start,
-               (unsigned int) host->stat_irq, host->dma.channel);
-       pr_info("%s: 4 bit data mode %s\n", mmc_hostname(mmc),
-               (mmc->caps & MMC_CAP_4_BIT_DATA ? "enabled" : "disabled"));
-       pr_info("%s: MMC clock %u -> %u Hz, PCLK %u Hz\n",
-               mmc_hostname(mmc), msmsdcc_fmin, msmsdcc_fmax, host->pclk_rate);
-       pr_info("%s: Slot eject status = %d\n", mmc_hostname(mmc), host->eject);
-       pr_info("%s: Power save feature enable = %d\n",
-               mmc_hostname(mmc), msmsdcc_pwrsave);
-
-       if (host->dma.channel != -1) {
-               pr_info("%s: DM non-cached buffer at %p, dma_addr 0x%.8x\n",
-                       mmc_hostname(mmc), host->dma.nc, host->dma.nc_busaddr);
-               pr_info("%s: DM cmd busaddr 0x%.8x, cmdptr busaddr 0x%.8x\n",
-                       mmc_hostname(mmc), host->dma.cmd_busaddr,
-                       host->dma.cmdptr_busaddr);
-       } else
-               pr_info("%s: PIO transfer enabled\n", mmc_hostname(mmc));
-       if (host->timer.function)
-               pr_info("%s: Polling status mode enabled\n", mmc_hostname(mmc));
-
-       return 0;
- cmd_irq_free:
-       free_irq(cmd_irqres->start, host);
- stat_irq_free:
-       if (host->stat_irq)
-               free_irq(host->stat_irq, host);
- clk_disable:
-       msmsdcc_disable_clocks(host, 0);
- clk_unprepare:
-       clk_unprepare(host->clk);
- clk_unprepare_p:
-       clk_unprepare(host->pclk);
- clk_put:
-       clk_put(host->clk);
- pclk_put:
-       clk_put(host->pclk);
-dma_free:
-       if (host->dmares)
-               dma_free_coherent(NULL, sizeof(struct msmsdcc_nc_dmadata),
-                                       host->dma.nc, host->dma.nc_busaddr);
-ioremap_free:
-       tasklet_kill(&host->dma_tlet);
-       iounmap(host->base);
- host_free:
-       mmc_free_host(mmc);
- out:
-       return ret;
-}
-
-#ifdef CONFIG_PM
-static int
-msmsdcc_suspend(struct platform_device *dev, pm_message_t state)
-{
-       struct mmc_host *mmc = platform_get_drvdata(dev);
-
-       if (mmc) {
-               struct msmsdcc_host *host = mmc_priv(mmc);
-
-               if (host->stat_irq)
-                       disable_irq(host->stat_irq);
-
-               msmsdcc_writel(host, 0, MMCIMASK0);
-               if (host->clks_on)
-                       msmsdcc_disable_clocks(host, 0);
-       }
-       return 0;
-}
-
-static int
-msmsdcc_resume(struct platform_device *dev)
-{
-       struct mmc_host *mmc = platform_get_drvdata(dev);
-
-       if (mmc) {
-               struct msmsdcc_host *host = mmc_priv(mmc);
-
-               msmsdcc_enable_clocks(host);
-
-               msmsdcc_writel(host, host->saved_irq0mask, MMCIMASK0);
-
-               if (host->stat_irq)
-                       enable_irq(host->stat_irq);
-#if BUSCLK_PWRSAVE
-               msmsdcc_disable_clocks(host, 1);
-#endif
-       }
-       return 0;
-}
-#else
-#define msmsdcc_suspend        0
-#define msmsdcc_resume 0
-#endif
-
-static struct platform_driver msmsdcc_driver = {
-       .probe          = msmsdcc_probe,
-       .suspend        = msmsdcc_suspend,
-       .resume         = msmsdcc_resume,
-       .driver         = {
-               .name   = "msm_sdcc",
-       },
-};
-
-module_platform_driver(msmsdcc_driver);
-
-MODULE_DESCRIPTION("Qualcomm MSM 7X00A Multimedia Card Interface driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
deleted file mode 100644 (file)
index 402028d..0000000
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- *  linux/drivers/mmc/host/msmsdcc.h - QCT MSM7K SDC Controller
- *
- *  Copyright (C) 2008 Google, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * - Based on mmci.h
- */
-
-#ifndef _MSM_SDCC_H
-#define _MSM_SDCC_H
-
-#define MSMSDCC_CRCI_SDC1      6
-#define MSMSDCC_CRCI_SDC2      7
-#define MSMSDCC_CRCI_SDC3      12
-#define MSMSDCC_CRCI_SDC4      13
-
-#define MMCIPOWER              0x000
-#define MCI_PWR_OFF            0x00
-#define MCI_PWR_UP             0x02
-#define MCI_PWR_ON             0x03
-#define MCI_OD                 (1 << 6)
-
-#define MMCICLOCK              0x004
-#define MCI_CLK_ENABLE         (1 << 8)
-#define MCI_CLK_PWRSAVE                (1 << 9)
-#define MCI_CLK_WIDEBUS                (1 << 10)
-#define MCI_CLK_FLOWENA                (1 << 12)
-#define MCI_CLK_INVERTOUT      (1 << 13)
-#define MCI_CLK_SELECTIN       (1 << 14)
-
-#define MMCIARGUMENT           0x008
-#define MMCICOMMAND            0x00c
-#define MCI_CPSM_RESPONSE      (1 << 6)
-#define MCI_CPSM_LONGRSP       (1 << 7)
-#define MCI_CPSM_INTERRUPT     (1 << 8)
-#define MCI_CPSM_PENDING       (1 << 9)
-#define MCI_CPSM_ENABLE                (1 << 10)
-#define MCI_CPSM_PROGENA       (1 << 11)
-#define MCI_CSPM_DATCMD                (1 << 12)
-#define MCI_CSPM_MCIABORT      (1 << 13)
-#define MCI_CSPM_CCSENABLE     (1 << 14)
-#define MCI_CSPM_CCSDISABLE    (1 << 15)
-
-
-#define MMCIRESPCMD            0x010
-#define MMCIRESPONSE0          0x014
-#define MMCIRESPONSE1          0x018
-#define MMCIRESPONSE2          0x01c
-#define MMCIRESPONSE3          0x020
-#define MMCIDATATIMER          0x024
-#define MMCIDATALENGTH         0x028
-
-#define MMCIDATACTRL           0x02c
-#define MCI_DPSM_ENABLE                (1 << 0)
-#define MCI_DPSM_DIRECTION     (1 << 1)
-#define MCI_DPSM_MODE          (1 << 2)
-#define MCI_DPSM_DMAENABLE     (1 << 3)
-
-#define MMCIDATACNT            0x030
-#define MMCISTATUS             0x034
-#define MCI_CMDCRCFAIL         (1 << 0)
-#define MCI_DATACRCFAIL                (1 << 1)
-#define MCI_CMDTIMEOUT         (1 << 2)
-#define MCI_DATATIMEOUT                (1 << 3)
-#define MCI_TXUNDERRUN         (1 << 4)
-#define MCI_RXOVERRUN          (1 << 5)
-#define MCI_CMDRESPEND         (1 << 6)
-#define MCI_CMDSENT            (1 << 7)
-#define MCI_DATAEND            (1 << 8)
-#define MCI_DATABLOCKEND       (1 << 10)
-#define MCI_CMDACTIVE          (1 << 11)
-#define MCI_TXACTIVE           (1 << 12)
-#define MCI_RXACTIVE           (1 << 13)
-#define MCI_TXFIFOHALFEMPTY    (1 << 14)
-#define MCI_RXFIFOHALFFULL     (1 << 15)
-#define MCI_TXFIFOFULL         (1 << 16)
-#define MCI_RXFIFOFULL         (1 << 17)
-#define MCI_TXFIFOEMPTY                (1 << 18)
-#define MCI_RXFIFOEMPTY                (1 << 19)
-#define MCI_TXDATAAVLBL                (1 << 20)
-#define MCI_RXDATAAVLBL                (1 << 21)
-#define MCI_SDIOINTR           (1 << 22)
-#define MCI_PROGDONE           (1 << 23)
-#define MCI_ATACMDCOMPL                (1 << 24)
-#define MCI_SDIOINTOPER                (1 << 25)
-#define MCI_CCSTIMEOUT         (1 << 26)
-
-#define MMCICLEAR              0x038
-#define MCI_CMDCRCFAILCLR      (1 << 0)
-#define MCI_DATACRCFAILCLR     (1 << 1)
-#define MCI_CMDTIMEOUTCLR      (1 << 2)
-#define MCI_DATATIMEOUTCLR     (1 << 3)
-#define MCI_TXUNDERRUNCLR      (1 << 4)
-#define MCI_RXOVERRUNCLR       (1 << 5)
-#define MCI_CMDRESPENDCLR      (1 << 6)
-#define MCI_CMDSENTCLR         (1 << 7)
-#define MCI_DATAENDCLR         (1 << 8)
-#define MCI_DATABLOCKENDCLR    (1 << 10)
-
-#define MMCIMASK0              0x03c
-#define MCI_CMDCRCFAILMASK     (1 << 0)
-#define MCI_DATACRCFAILMASK    (1 << 1)
-#define MCI_CMDTIMEOUTMASK     (1 << 2)
-#define MCI_DATATIMEOUTMASK    (1 << 3)
-#define MCI_TXUNDERRUNMASK     (1 << 4)
-#define MCI_RXOVERRUNMASK      (1 << 5)
-#define MCI_CMDRESPENDMASK     (1 << 6)
-#define MCI_CMDSENTMASK                (1 << 7)
-#define MCI_DATAENDMASK                (1 << 8)
-#define MCI_DATABLOCKENDMASK   (1 << 10)
-#define MCI_CMDACTIVEMASK      (1 << 11)
-#define MCI_TXACTIVEMASK       (1 << 12)
-#define MCI_RXACTIVEMASK       (1 << 13)
-#define MCI_TXFIFOHALFEMPTYMASK        (1 << 14)
-#define MCI_RXFIFOHALFFULLMASK (1 << 15)
-#define MCI_TXFIFOFULLMASK     (1 << 16)
-#define MCI_RXFIFOFULLMASK     (1 << 17)
-#define MCI_TXFIFOEMPTYMASK    (1 << 18)
-#define MCI_RXFIFOEMPTYMASK    (1 << 19)
-#define MCI_TXDATAAVLBLMASK    (1 << 20)
-#define MCI_RXDATAAVLBLMASK    (1 << 21)
-#define MCI_SDIOINTMASK                (1 << 22)
-#define MCI_PROGDONEMASK       (1 << 23)
-#define MCI_ATACMDCOMPLMASK    (1 << 24)
-#define MCI_SDIOINTOPERMASK    (1 << 25)
-#define MCI_CCSTIMEOUTMASK     (1 << 26)
-
-#define MMCIMASK1              0x040
-#define MMCIFIFOCNT            0x044
-#define MCICCSTIMER            0x058
-
-#define MMCIFIFO               0x080 /* to 0x0bc */
-
-#define MCI_IRQENABLE  \
-       (MCI_CMDCRCFAILMASK|MCI_DATACRCFAILMASK|MCI_CMDTIMEOUTMASK|     \
-       MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK|       \
-       MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATAENDMASK|MCI_PROGDONEMASK)
-
-#define MCI_IRQ_PIO \
-       (MCI_RXDATAAVLBLMASK | MCI_TXDATAAVLBLMASK | MCI_RXFIFOEMPTYMASK | \
-        MCI_TXFIFOEMPTYMASK | MCI_RXFIFOFULLMASK | MCI_TXFIFOFULLMASK | \
-        MCI_RXFIFOHALFFULLMASK | MCI_TXFIFOHALFEMPTYMASK | \
-        MCI_RXACTIVEMASK | MCI_TXACTIVEMASK)
-/*
- * The size of the FIFO in bytes.
- */
-#define MCI_FIFOSIZE   (16*4)
-
-#define MCI_FIFOHALFSIZE (MCI_FIFOSIZE / 2)
-
-#define NR_SG          32
-
-struct clk;
-
-struct msmsdcc_nc_dmadata {
-       dmov_box        cmd[NR_SG];
-       uint32_t        cmdptr;
-};
-
-struct msmsdcc_dma_data {
-       struct msmsdcc_nc_dmadata       *nc;
-       dma_addr_t                      nc_busaddr;
-       dma_addr_t                      cmd_busaddr;
-       dma_addr_t                      cmdptr_busaddr;
-
-       struct msm_dmov_cmd             hdr;
-       enum dma_data_direction         dir;
-
-       struct scatterlist              *sg;
-       int                             num_ents;
-
-       int                             channel;
-       struct msmsdcc_host             *host;
-       int                             busy; /* Set if DM is busy */
-       int                             active;
-       unsigned int                    result;
-       struct msm_dmov_errdata         err;
-};
-
-struct msmsdcc_pio_data {
-       struct scatterlist      *sg;
-       unsigned int            sg_len;
-       unsigned int            sg_off;
-};
-
-struct msmsdcc_curr_req {
-       struct mmc_request      *mrq;
-       struct mmc_command      *cmd;
-       struct mmc_data         *data;
-       unsigned int            xfer_size;      /* Total data size */
-       unsigned int            xfer_remain;    /* Bytes remaining to send */
-       unsigned int            data_xfered;    /* Bytes acked by BLKEND irq */
-       int                     got_dataend;
-       int                     user_pages;
-};
-
-struct msmsdcc_stats {
-       unsigned int reqs;
-       unsigned int cmds;
-       unsigned int cmdpoll_hits;
-       unsigned int cmdpoll_misses;
-};
-
-struct msmsdcc_host {
-       struct resource         *cmd_irqres;
-       struct resource         *memres;
-       struct resource         *dmares;
-       void __iomem            *base;
-       int                     pdev_id;
-       unsigned int            stat_irq;
-
-       struct msmsdcc_curr_req curr;
-
-       struct mmc_host         *mmc;
-       struct clk              *clk;           /* main MMC bus clock */
-       struct clk              *pclk;          /* SDCC peripheral bus clock */
-       unsigned int            clks_on;        /* set if clocks are enabled */
-       struct timer_list       busclk_timer;
-
-       unsigned int            eject;          /* eject state */
-
-       spinlock_t              lock;
-
-       unsigned int            clk_rate;       /* Current clock rate */
-       unsigned int            pclk_rate;
-
-       u32                     pwr;
-       u32                     saved_irq0mask; /* MMCIMASK0 reg value */
-       struct msm_mmc_platform_data *plat;
-
-       struct timer_list       timer;
-       unsigned int            oldstat;
-
-       struct msmsdcc_dma_data dma;
-       struct msmsdcc_pio_data pio;
-       int                     cmdpoll;
-       struct msmsdcc_stats    stats;
-
-       struct tasklet_struct   dma_tlet;
-       /* Command parameters */
-       unsigned int            cmd_timeout;
-       unsigned int            cmd_pio_irqmask;
-       unsigned int            cmd_datactrl;
-       struct mmc_command      *cmd_cmd;
-       u32                     cmd_c;
-       bool                    gpio_config_status;
-
-       bool prog_scan;
-       bool prog_enable;
-};
-
-#endif
index 072f67066df38e8d60d4eb0d1f5bc656947fa1fa..2b6ef6bd5d5fee1c3277c4970549da294b4706da 100644 (file)
@@ -388,7 +388,7 @@ sh_mmcif_request_dma_one(struct sh_mmcif_host *host,
 {
        struct dma_slave_config cfg = { 0, };
        struct dma_chan *chan;
-       unsigned int slave_id;
+       void *slave_data = NULL;
        struct resource *res;
        dma_cap_mask_t mask;
        int ret;
@@ -397,13 +397,12 @@ sh_mmcif_request_dma_one(struct sh_mmcif_host *host,
        dma_cap_set(DMA_SLAVE, mask);
 
        if (pdata)
-               slave_id = direction == DMA_MEM_TO_DEV
-                        ? pdata->slave_id_tx : pdata->slave_id_rx;
-       else
-               slave_id = 0;
+               slave_data = direction == DMA_MEM_TO_DEV ?
+                       (void *)pdata->slave_id_tx :
+                       (void *)pdata->slave_id_rx;
 
        chan = dma_request_slave_channel_compat(mask, shdma_chan_filter,
-                               (void *)(unsigned long)slave_id, &host->pd->dev,
+                               slave_data, &host->pd->dev,
                                direction == DMA_MEM_TO_DEV ? "tx" : "rx");
 
        dev_dbg(&host->pd->dev, "%s: %s: got channel %p\n", __func__,
@@ -414,8 +413,6 @@ sh_mmcif_request_dma_one(struct sh_mmcif_host *host,
 
        res = platform_get_resource(host->pd, IORESOURCE_MEM, 0);
 
-       /* In the OF case the driver will get the slave ID from the DT */
-       cfg.slave_id = slave_id;
        cfg.direction = direction;
 
        if (direction == DMA_DEV_TO_MEM) {
index 6906a905cd543f9d34058cbab8b4bbf7b64bb051..354f4f335ed57ab7abed082700264beb11d804b9 100644 (file)
@@ -201,7 +201,7 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev)
                of_match_device(sh_mobile_sdhi_of_match, &pdev->dev);
        struct sh_mobile_sdhi *priv;
        struct tmio_mmc_data *mmc_data;
-       struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
+       struct tmio_mmc_data *mmd = pdev->dev.platform_data;
        struct tmio_mmc_host *host;
        struct resource *res;
        int irq, ret, i = 0;
@@ -245,30 +245,14 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev)
        else
                host->bus_shift = 0;
 
-       mmc_data->capabilities = MMC_CAP_MMC_HIGHSPEED;
-       if (p) {
-               mmc_data->flags = p->tmio_flags;
-               mmc_data->ocr_mask = p->tmio_ocr_mask;
-               mmc_data->capabilities |= p->tmio_caps;
-               mmc_data->capabilities2 |= p->tmio_caps2;
-               mmc_data->cd_gpio = p->cd_gpio;
-
-               if (p->dma_slave_tx > 0 && p->dma_slave_rx > 0) {
-                       /*
-                        * Yes, we have to provide slave IDs twice to TMIO:
-                        * once as a filter parameter and once for channel
-                        * configuration as an explicit slave ID
-                        */
-                       dma_priv->chan_priv_tx = (void *)p->dma_slave_tx;
-                       dma_priv->chan_priv_rx = (void *)p->dma_slave_rx;
-                       dma_priv->slave_id_tx = p->dma_slave_tx;
-                       dma_priv->slave_id_rx = p->dma_slave_rx;
-               }
-       }
+       if (mmd)
+               *mmc_data = *mmd;
+
        dma_priv->filter = shdma_chan_filter;
        dma_priv->enable = sh_mobile_sdhi_enable_dma;
 
        mmc_data->alignment_shift = 1; /* 2-byte alignment */
+       mmc_data->capabilities |= MMC_CAP_MMC_HIGHSPEED;
 
        /*
         * All SDHI blocks support 2-byte and larger block sizes in 4-bit
index fc3805ed69d18d8e88919d06221fb9129359e91f..4a597f5a53e20ff6e0d7ef5b69b6009a879cc83f 100644 (file)
@@ -43,10 +43,6 @@ struct tmio_mmc_data;
 struct tmio_mmc_host;
 
 struct tmio_mmc_dma {
-       void *chan_priv_tx;
-       void *chan_priv_rx;
-       int slave_id_tx;
-       int slave_id_rx;
        enum dma_slave_buswidth dma_buswidth;
        bool (*filter)(struct dma_chan *chan, void *arg);
        void (*enable)(struct tmio_mmc_host *host, bool enable);
index 331bb618e3987a6bb8283a2102f7ccfb5639a38e..e4b05dbb9ca822f003f566d07a60c508721bc68c 100644 (file)
@@ -261,7 +261,7 @@ void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdat
 {
        /* We can only either use DMA for both Tx and Rx or not use it at all */
        if (!host->dma || (!host->pdev->dev.of_node &&
-               (!host->dma->chan_priv_tx || !host->dma->chan_priv_rx)))
+               (!pdata->chan_priv_tx || !pdata->chan_priv_rx)))
                return;
 
        if (!host->chan_tx && !host->chan_rx) {
@@ -278,7 +278,7 @@ void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdat
                dma_cap_set(DMA_SLAVE, mask);
 
                host->chan_tx = dma_request_slave_channel_compat(mask,
-                                       host->dma->filter, host->dma->chan_priv_tx,
+                                       host->dma->filter, pdata->chan_priv_tx,
                                        &host->pdev->dev, "tx");
                dev_dbg(&host->pdev->dev, "%s: TX: got channel %p\n", __func__,
                        host->chan_tx);
@@ -286,8 +286,6 @@ void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdat
                if (!host->chan_tx)
                        return;
 
-               if (host->dma->chan_priv_tx)
-                       cfg.slave_id = host->dma->slave_id_tx;
                cfg.direction = DMA_MEM_TO_DEV;
                cfg.dst_addr = res->start + (CTL_SD_DATA_PORT << host->bus_shift);
                cfg.dst_addr_width = host->dma->dma_buswidth;
@@ -299,7 +297,7 @@ void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdat
                        goto ecfgtx;
 
                host->chan_rx = dma_request_slave_channel_compat(mask,
-                                       host->dma->filter, host->dma->chan_priv_rx,
+                                       host->dma->filter, pdata->chan_priv_rx,
                                        &host->pdev->dev, "rx");
                dev_dbg(&host->pdev->dev, "%s: RX: got channel %p\n", __func__,
                        host->chan_rx);
@@ -307,8 +305,6 @@ void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdat
                if (!host->chan_rx)
                        goto ereqrx;
 
-               if (host->dma->chan_priv_rx)
-                       cfg.slave_id = host->dma->slave_id_rx;
                cfg.direction = DMA_DEV_TO_MEM;
                cfg.src_addr = cfg.dst_addr + host->pdata->dma_rx_offset;
                cfg.src_addr_width = host->dma->dma_buswidth;
index 71fea895ce38d34c20beee385182277241525431..a03ad2951c7b423975c566dfce20902b7fd074f0 100644 (file)
@@ -309,6 +309,19 @@ config MTD_SWAP
          The driver provides wear leveling by storing erase counter into the
          OOB.
 
+config MTD_PARTITIONED_MASTER
+       bool "Retain master device when partitioned"
+       default n
+       depends on MTD
+       help
+         For historical reasons, by default, either a master is present or
+         several partitions are present, but not both. The concern was that
+         data listed in multiple partitions was dangerous; however, SCSI does
+         this and it is frequently useful for applications. This config option
+         leaves the master in even if the device is partitioned. It also makes
+         the parent of the partition device be the master device, rather than
+         what lies behind the master.
+
 source "drivers/mtd/chips/Kconfig"
 
 source "drivers/mtd/maps/Kconfig"
index 423666b51efb990fab17827c0a850784cc887779..9a1a6ffd16b87902d9ee9caf02efab300a014ef5 100644 (file)
@@ -206,23 +206,23 @@ static struct mtd_info *cfi_staa_setup(struct map_info *map)
                        mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].numblocks = ernum;
                }
                offset += (ersize * ernum);
-               }
+       }
 
-               if (offset != devsize) {
-                       /* Argh */
-                       printk(KERN_WARNING "Sum of regions (%lx) != total size of set of interleaved chips (%lx)\n", offset, devsize);
-                       kfree(mtd->eraseregions);
-                       kfree(cfi->cmdset_priv);
-                       kfree(mtd);
-                       return NULL;
-               }
+       if (offset != devsize) {
+               /* Argh */
+               printk(KERN_WARNING "Sum of regions (%lx) != total size of set of interleaved chips (%lx)\n", offset, devsize);
+               kfree(mtd->eraseregions);
+               kfree(cfi->cmdset_priv);
+               kfree(mtd);
+               return NULL;
+       }
 
-               for (i=0; i<mtd->numeraseregions;i++){
-                       printk(KERN_DEBUG "%d: offset=0x%llx,size=0x%x,blocks=%d\n",
-                              i, (unsigned long long)mtd->eraseregions[i].offset,
-                              mtd->eraseregions[i].erasesize,
-                              mtd->eraseregions[i].numblocks);
-               }
+       for (i=0; i<mtd->numeraseregions;i++){
+               printk(KERN_DEBUG "%d: offset=0x%llx,size=0x%x,blocks=%d\n",
+                      i, (unsigned long long)mtd->eraseregions[i].offset,
+                      mtd->eraseregions[i].erasesize,
+                      mtd->eraseregions[i].numblocks);
+       }
 
        /* Also select the correct geometry setup too */
        mtd->_erase = cfi_staa_erase_varsize;
index 66f0405f7e535b33f02f71586ffe4bc13b5f1ee0..b16f3cda97ff0a6c12fb9ef3d8830603f5e5dc39 100644 (file)
@@ -9,7 +9,15 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+/*
+ * When the first attempt at device initialization fails, we may need to
+ * wait a little bit and retry. This timeout, by default 3 seconds, gives
+ * device time to start up. Required on BCM2708 and a few other chipsets.
+ */
+#define MTD_DEFAULT_TIMEOUT    3
+
 #include <linux/module.h>
+#include <linux/delay.h>
 #include <linux/fs.h>
 #include <linux/blkdev.h>
 #include <linux/bio.h>
@@ -209,10 +217,14 @@ static void block2mtd_free_device(struct block2mtd_dev *dev)
 }
 
 
-static struct block2mtd_dev *add_device(char *devname, int erase_size)
+static struct block2mtd_dev *add_device(char *devname, int erase_size,
+               int timeout)
 {
+#ifndef MODULE
+       int i;
+#endif
        const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL;
-       struct block_device *bdev;
+       struct block_device *bdev = ERR_PTR(-ENODEV);
        struct block2mtd_dev *dev;
        char *name;
 
@@ -225,15 +237,28 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
 
        /* Get a handle on the device */
        bdev = blkdev_get_by_path(devname, mode, dev);
-#ifndef MODULE
-       if (IS_ERR(bdev)) {
-
-               /* We might not have rootfs mounted at this point. Try
-                  to resolve the device name by other means. */
 
-               dev_t devt = name_to_dev_t(devname);
-               if (devt)
-                       bdev = blkdev_get_by_dev(devt, mode, dev);
+#ifndef MODULE
+       /*
+        * We might not have the root device mounted at this point.
+        * Try to resolve the device name by other means.
+        */
+       for (i = 0; IS_ERR(bdev) && i <= timeout; i++) {
+               dev_t devt;
+
+               if (i)
+                       /*
+                        * Calling wait_for_device_probe in the first loop
+                        * was not enough, sleep for a bit in subsequent
+                        * go-arounds.
+                        */
+                       msleep(1000);
+               wait_for_device_probe();
+
+               devt = name_to_dev_t(devname);
+               if (!devt)
+                       continue;
+               bdev = blkdev_get_by_dev(devt, mode, dev);
        }
 #endif
 
@@ -280,6 +305,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
                /* Device didn't get added, so free the entry */
                goto err_destroy_mutex;
        }
+
        list_add(&dev->list, &blkmtd_device_list);
        pr_info("mtd%d: [%s] erase_size = %dKiB [%d]\n",
                dev->mtd.index,
@@ -348,16 +374,19 @@ static inline void kill_final_newline(char *str)
 
 #ifndef MODULE
 static int block2mtd_init_called = 0;
-static char block2mtd_paramline[80 + 12]; /* 80 for device, 12 for erase size */
+/* 80 for device, 12 for erase size */
+static char block2mtd_paramline[80 + 12];
 #endif
 
 static int block2mtd_setup2(const char *val)
 {
-       char buf[80 + 12]; /* 80 for device, 12 for erase size */
+       /* 80 for device, 12 for erase size, 80 for name, 8 for timeout */
+       char buf[80 + 12 + 80 + 8];
        char *str = buf;
        char *token[2];
        char *name;
        size_t erase_size = PAGE_SIZE;
+       unsigned long timeout = MTD_DEFAULT_TIMEOUT;
        int i, ret;
 
        if (strnlen(val, sizeof(buf)) >= sizeof(buf)) {
@@ -395,7 +424,7 @@ static int block2mtd_setup2(const char *val)
                }
        }
 
-       add_device(name, erase_size);
+       add_device(name, erase_size, timeout);
 
        return 0;
 }
@@ -463,8 +492,7 @@ static void block2mtd_exit(void)
        }
 }
 
-
-module_init(block2mtd_init);
+late_initcall(block2mtd_init);
 module_exit(block2mtd_exit);
 
 MODULE_LICENSE("GPL");
index 448ce42f951e4fc99c72e2296a09825f88aae4d4..866d319044750bda27e5679d36ff4b0e5d9d26aa 100644 (file)
@@ -1805,7 +1805,7 @@ static int __init doc_dbg_register(struct docg3 *docg3)
        }
 }
 
-static void __exit doc_dbg_unregister(struct docg3 *docg3)
+static void doc_dbg_unregister(struct docg3 *docg3)
 {
        debugfs_remove_recursive(docg3->debugfs_root);
 }
@@ -2033,7 +2033,7 @@ static int __init docg3_probe(struct platform_device *pdev)
        struct mtd_info *mtd;
        struct resource *ress;
        void __iomem *base;
-       int ret, floor, found = 0;
+       int ret, floor;
        struct docg3_cascade *cascade;
 
        ret = -ENXIO;
@@ -2073,14 +2073,11 @@ static int __init docg3_probe(struct platform_device *pdev)
                                                0);
                if (ret)
                        goto err_probe;
-               found++;
        }
 
        ret = doc_register_sysfs(pdev, cascade);
        if (ret)
                goto err_probe;
-       if (!found)
-               goto notfound;
 
        platform_set_drvdata(pdev, cascade);
        doc_dbg_register(cascade->floors[0]->priv);
@@ -2103,7 +2100,7 @@ err_probe:
  *
  * Returns 0
  */
-static int __exit docg3_release(struct platform_device *pdev)
+static int docg3_release(struct platform_device *pdev)
 {
        struct docg3_cascade *cascade = platform_get_drvdata(pdev);
        struct docg3 *docg3 = cascade->floors[0]->priv;
@@ -2134,7 +2131,7 @@ static struct platform_driver g3_driver = {
        },
        .suspend        = docg3_suspend,
        .resume         = docg3_resume,
-       .remove         = __exit_p(docg3_release),
+       .remove         = docg3_release,
 };
 
 module_platform_driver_probe(g3_driver, docg3_probe);
index 85e35467fba6f2d0990115a463f43aaf2ef4b396..7c8b1694a134da91cbeb5b4764922c8e7d8d06c2 100644 (file)
@@ -223,6 +223,8 @@ static int m25p_probe(struct spi_device *spi)
         */
        if (data && data->type)
                flash_name = data->type;
+       else if (!strcmp(spi->modalias, "nor-jedec"))
+               flash_name = NULL; /* auto-detect */
        else
                flash_name = spi->modalias;
 
@@ -247,9 +249,16 @@ static int m25p_remove(struct spi_device *spi)
 }
 
 /*
- * XXX This needs to be kept in sync with spi_nor_ids.  We can't share
- * it with spi-nor, because if this is built as a module then modpost
- * won't be able to read it and add appropriate aliases.
+ * Do NOT add to this array without reading the following:
+ *
+ * Historically, many flash devices are bound to this driver by their name. But
+ * since most of these flash are compatible to some extent, and their
+ * differences can often be differentiated by the JEDEC read-ID command, we
+ * encourage new users to add support to the spi-nor library, and simply bind
+ * against a generic string here (e.g., "nor-jedec").
+ *
+ * Many flash names are kept here in this list (as well as in spi-nor.c) to
+ * keep them available as module aliases for existing platforms.
  */
 static const struct spi_device_id m25p_ids[] = {
        {"at25fs010"},  {"at25fs040"},  {"at25df041a"}, {"at25df321a"},
@@ -291,6 +300,12 @@ static const struct spi_device_id m25p_ids[] = {
        {"w25x64"},     {"w25q64"},     {"w25q80"},     {"w25q80bl"},
        {"w25q128"},    {"w25q256"},    {"cat25c11"},
        {"cat25c03"},   {"cat25c09"},   {"cat25c17"},   {"cat25128"},
+
+       /*
+        * Generic support for SPI NOR that can be identified by the JEDEC READ
+        * ID opcode (0x9F). Use this, if possible.
+        */
+       {"nor-jedec"},
        { },
 };
 MODULE_DEVICE_TABLE(spi, m25p_ids);
index ba801d2c6dcc2c54a72b8a7962130a8784c39296..e715ae90632f82e69991bdc7704cc5dbd35ab0f9 100644 (file)
@@ -242,7 +242,7 @@ config MTD_L440GX
 
 config MTD_CFI_FLAGADM
        tristate "CFI Flash device mapping on FlagaDM"
-       depends on 8xx && MTD_CFI
+       depends on PPC_8xx && MTD_CFI
        help
          Mapping for the Flaga digital module. If you don't have one, ignore
          this setting.
index ea697202935a12a420a12f58f42f770ce2915e03..892ad6ac63f2936a12ecd52c256b07c5dbd395e1 100644 (file)
@@ -274,7 +274,7 @@ static int sa1100_mtd_probe(struct platform_device *pdev)
        return err;
 }
 
-static int __exit sa1100_mtd_remove(struct platform_device *pdev)
+static int sa1100_mtd_remove(struct platform_device *pdev)
 {
        struct sa_info *info = platform_get_drvdata(pdev);
        struct flash_platform_data *plat = dev_get_platdata(&pdev->dev);
@@ -286,7 +286,7 @@ static int __exit sa1100_mtd_remove(struct platform_device *pdev)
 
 static struct platform_driver sa1100_mtd_driver = {
        .probe          = sa1100_mtd_probe,
-       .remove         = __exit_p(sa1100_mtd_remove),
+       .remove         = sa1100_mtd_remove,
        .driver         = {
                .name   = "sa1100-mtd",
        },
index d1d671daf2356862374691b5a5977754d6828384..9969fedb1f13c2be53859df396823260bd1b9740 100644 (file)
@@ -117,5 +117,5 @@ module_exit(cleanup_ts5500_map);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Sean Young <sean@mess.org>");
-MODULE_DESCRIPTION("MTD map driver for Techology Systems TS-5500 board");
+MODULE_DESCRIPTION("MTD map driver for Technology Systems TS-5500 board");
 
index d08229eb44d8a8911dc49c6cbdba51ec99cdbdf0..2b0c528709997a618d672e55c50bb44336a8cd69 100644 (file)
@@ -171,9 +171,6 @@ static void mtd_blktrans_work(struct work_struct *work)
                background_done = 0;
        }
 
-       if (req)
-               __blk_end_request_all(req, -EIO);
-
        spin_unlock_irq(rq->queue_lock);
 }
 
index 11883bd26d9d35e8234cc7dc74f51b7ed57d7566..d172195fbd15fcbd947a2bc0780d0f9044cba2fd 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/gfp.h>
 #include <linux/slab.h>
 #include <linux/reboot.h>
+#include <linux/kconfig.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -501,6 +502,29 @@ out_error:
        return ret;
 }
 
+static int mtd_add_device_partitions(struct mtd_info *mtd,
+                                    struct mtd_partition *real_parts,
+                                    int nbparts)
+{
+       int ret;
+
+       if (nbparts == 0 || IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) {
+               ret = add_mtd_device(mtd);
+               if (ret == 1)
+                       return -ENODEV;
+       }
+
+       if (nbparts > 0) {
+               ret = add_mtd_partitions(mtd, real_parts, nbparts);
+               if (ret && IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER))
+                       del_mtd_device(mtd);
+               return ret;
+       }
+
+       return 0;
+}
+
+
 /**
  * mtd_device_parse_register - parse partitions and register an MTD device.
  *
@@ -523,7 +547,8 @@ out_error:
  *   found this functions tries to fallback to information specified in
  *   @parts/@nr_parts.
  * * If any partitioning info was found, this function registers the found
- *   partitions.
+ *   partitions. If the MTD_PARTITIONED_MASTER option is set, then the device
+ *   as a whole is registered first.
  * * If no partitions were found this function just registers the MTD device
  *   @mtd and exits.
  *
@@ -534,27 +559,21 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
                              const struct mtd_partition *parts,
                              int nr_parts)
 {
-       int err;
-       struct mtd_partition *real_parts;
+       int ret;
+       struct mtd_partition *real_parts = NULL;
 
-       err = parse_mtd_partitions(mtd, types, &real_parts, parser_data);
-       if (err <= 0 && nr_parts && parts) {
+       ret = parse_mtd_partitions(mtd, types, &real_parts, parser_data);
+       if (ret <= 0 && nr_parts && parts) {
                real_parts = kmemdup(parts, sizeof(*parts) * nr_parts,
                                     GFP_KERNEL);
                if (!real_parts)
-                       err = -ENOMEM;
+                       ret = -ENOMEM;
                else
-                       err = nr_parts;
+                       ret = nr_parts;
        }
 
-       if (err > 0) {
-               err = add_mtd_partitions(mtd, real_parts, err);
-               kfree(real_parts);
-       } else if (err == 0) {
-               err = add_mtd_device(mtd);
-               if (err == 1)
-                       err = -ENODEV;
-       }
+       if (ret >= 0)
+               ret = mtd_add_device_partitions(mtd, real_parts, ret);
 
        /*
         * FIXME: some drivers unfortunately call this function more than once.
@@ -569,7 +588,8 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
                register_reboot_notifier(&mtd->reboot_notifier);
        }
 
-       return err;
+       kfree(real_parts);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_device_parse_register);
 
index e779de315ade505f1a508edefc541f7a4223af97..cafdb8855a794f93f2adf56ca917fcb7a283e9df 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/err.h>
+#include <linux/kconfig.h>
 
 #include "mtdcore.h"
 
@@ -379,10 +380,17 @@ static struct mtd_part *allocate_partition(struct mtd_info *master,
        slave->mtd.name = name;
        slave->mtd.owner = master->owner;
 
-       /* NOTE:  we don't arrange MTDs as a tree; it'd be error-prone
-        * to have the same data be in two different partitions.
+       /* NOTE: Historically, we didn't arrange MTDs as a tree out of
+        * concern for showing the same data in multiple partitions.
+        * However, it is very useful to have the master node present,
+        * so the MTD_PARTITIONED_MASTER option allows that. The master
+        * will have device nodes etc only if this is set, so make the
+        * parent conditional on that option. Note, this is a way to
+        * distinguish between the master and the partition in sysfs.
         */
-       slave->mtd.dev.parent = master->dev.parent;
+       slave->mtd.dev.parent = IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER) ?
+                               &master->dev :
+                               master->dev.parent;
 
        slave->mtd._read = part_read;
        slave->mtd._write = part_write;
@@ -546,12 +554,35 @@ out_register:
        return slave;
 }
 
+static ssize_t mtd_partition_offset_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct mtd_info *mtd = dev_get_drvdata(dev);
+       struct mtd_part *part = PART(mtd);
+       return snprintf(buf, PAGE_SIZE, "%lld\n", part->offset);
+}
+
+static DEVICE_ATTR(offset, S_IRUGO, mtd_partition_offset_show, NULL);
+
+static const struct attribute *mtd_partition_attrs[] = {
+       &dev_attr_offset.attr,
+       NULL
+};
+
+static int mtd_add_partition_attrs(struct mtd_part *new)
+{
+       int ret = sysfs_create_files(&new->mtd.dev.kobj, mtd_partition_attrs);
+       if (ret)
+               printk(KERN_WARNING
+                      "mtd: failed to create partition attrs, err=%d\n", ret);
+       return ret;
+}
+
 int mtd_add_partition(struct mtd_info *master, const char *name,
                      long long offset, long long length)
 {
        struct mtd_partition part;
-       struct mtd_part *p, *new;
-       uint64_t start, end;
+       struct mtd_part *new;
        int ret = 0;
 
        /* the direct offset is expected */
@@ -575,31 +606,15 @@ int mtd_add_partition(struct mtd_info *master, const char *name,
        if (IS_ERR(new))
                return PTR_ERR(new);
 
-       start = offset;
-       end = offset + length;
-
        mutex_lock(&mtd_partitions_mutex);
-       list_for_each_entry(p, &mtd_partitions, list)
-               if (p->master == master) {
-                       if ((start >= p->offset) &&
-                           (start < (p->offset + p->mtd.size)))
-                               goto err_inv;
-
-                       if ((end >= p->offset) &&
-                           (end < (p->offset + p->mtd.size)))
-                               goto err_inv;
-               }
-
        list_add(&new->list, &mtd_partitions);
        mutex_unlock(&mtd_partitions_mutex);
 
        add_mtd_device(&new->mtd);
 
+       mtd_add_partition_attrs(new);
+
        return ret;
-err_inv:
-       mutex_unlock(&mtd_partitions_mutex);
-       free_partition(new);
-       return -EINVAL;
 }
 EXPORT_SYMBOL_GPL(mtd_add_partition);
 
@@ -612,6 +627,8 @@ int mtd_del_partition(struct mtd_info *master, int partno)
        list_for_each_entry_safe(slave, next, &mtd_partitions, list)
                if ((slave->master == master) &&
                    (slave->mtd.index == partno)) {
+                       sysfs_remove_files(&slave->mtd.dev.kobj,
+                                          mtd_partition_attrs);
                        ret = del_mtd_device(&slave->mtd);
                        if (ret < 0)
                                break;
@@ -631,8 +648,8 @@ EXPORT_SYMBOL_GPL(mtd_del_partition);
  * and registers slave MTD objects which are bound to the master according to
  * the partition definitions.
  *
- * We don't register the master, or expect the caller to have done so,
- * for reasons of data integrity.
+ * For historical reasons, this function's caller only registers the master
+ * if the MTD_PARTITIONED_MASTER config option is set.
  */
 
 int add_mtd_partitions(struct mtd_info *master,
@@ -655,6 +672,7 @@ int add_mtd_partitions(struct mtd_info *master,
                mutex_unlock(&mtd_partitions_mutex);
 
                add_mtd_device(&slave->mtd);
+               mtd_add_partition_attrs(slave);
 
                cur_offset = slave->offset + slave->mtd.size;
        }
index d93c849b70b5cf299864a356e955a792e35bd802..46010bd895b152598d44b9a47004c42de374a678 100644 (file)
@@ -485,7 +485,7 @@ static void pmecc_config_ecc_layout(struct nand_ecclayout *layout,
        for (i = 0; i < ecc_len; i++)
                layout->eccpos[i] = oobsize - ecc_len + i;
 
-       layout->oobfree[0].offset = 2;
+       layout->oobfree[0].offset = PMECC_OOB_RESERVED_BYTES;
        layout->oobfree[0].length =
                oobsize - ecc_len - layout->oobfree[0].offset;
 }
@@ -1204,14 +1204,14 @@ static int atmel_pmecc_nand_init_params(struct platform_device *pdev,
                goto err;
        }
 
-       regs_rom = platform_get_resource(pdev, IORESOURCE_MEM, 3);
-       host->pmecc_rom_base = devm_ioremap_resource(&pdev->dev, regs_rom);
-       if (IS_ERR(host->pmecc_rom_base)) {
-               if (!host->has_no_lookup_table)
-                       /* Don't display the information again */
+       if (!host->has_no_lookup_table) {
+               regs_rom = platform_get_resource(pdev, IORESOURCE_MEM, 3);
+               host->pmecc_rom_base = devm_ioremap_resource(&pdev->dev,
+                                                               regs_rom);
+               if (IS_ERR(host->pmecc_rom_base)) {
                        dev_err(host->dev, "Can not get I/O resource for ROM, will build a lookup table in runtime!\n");
-
-               host->has_no_lookup_table = true;
+                       host->has_no_lookup_table = true;
+               }
        }
 
        if (host->has_no_lookup_table) {
@@ -1254,7 +1254,8 @@ static int atmel_pmecc_nand_init_params(struct platform_device *pdev,
                nand_chip->ecc.steps = mtd->writesize / sector_size;
                nand_chip->ecc.total = nand_chip->ecc.bytes *
                        nand_chip->ecc.steps;
-               if (nand_chip->ecc.total > mtd->oobsize - 2) {
+               if (nand_chip->ecc.total >
+                               mtd->oobsize - PMECC_OOB_RESERVED_BYTES) {
                        dev_err(host->dev, "No room for ECC bytes\n");
                        err_no = -EINVAL;
                        goto err;
@@ -1719,7 +1720,7 @@ static int nfc_wait_interrupt(struct atmel_nand_host *host, u32 flag)
                comp[index++] = &host->nfc->comp_cmd_done;
 
        if (index == 0) {
-               dev_err(host->dev, "Unkown interrupt flag: 0x%08x\n", flag);
+               dev_err(host->dev, "Unknown interrupt flag: 0x%08x\n", flag);
                return -EINVAL;
        }
 
@@ -1752,11 +1753,10 @@ static int nfc_send_command(struct atmel_nand_host *host,
                cmd, addr, cycle0);
 
        timeout = jiffies + msecs_to_jiffies(NFC_TIME_OUT_MS);
-       while (nfc_cmd_readl(NFCADDR_CMD_NFCBUSY, host->nfc->base_cmd_regs)
-                       & NFCADDR_CMD_NFCBUSY) {
+       while (nfc_readl(host->nfc->hsmc_regs, SR) & NFC_SR_BUSY) {
                if (time_after(jiffies, timeout)) {
                        dev_err(host->dev,
-                               "Time out to wait CMD_NFCBUSY ready!\n");
+                               "Time out to wait for NFC ready!\n");
                        return -ETIMEDOUT;
                }
        }
index d4035e335ad8fbe75d8cb435b44d8b94e5260cc7..668e7358f19b76e94dc577c8e89cc7297f419b9a 100644 (file)
 /* Time out value for reading PMECC status register */
 #define PMECC_MAX_TIMEOUT_MS                   100
 
+/* Reserved bytes in oob area */
+#define PMECC_OOB_RESERVED_BYTES               2
+
 #endif
index 85b8ca6af7d2d5d9e1e804cb4b575733e0fc38a5..4d5d26221a7ee512d3d16e02441f0619d81ad900 100644 (file)
@@ -35,6 +35,7 @@
 #define                NFC_CTRL_DISABLE        (1 << 1)
 
 #define ATMEL_HSMC_NFC_SR      0x08            /* NFC Status Register */
+#define                NFC_SR_BUSY             (1 << 8)
 #define                NFC_SR_XFR_DONE         (1 << 16)
 #define                NFC_SR_CMD_DONE         (1 << 17)
 #define                NFC_SR_DTOE             (1 << 20)
index f44c6061536a830e66fa7f50b139e6bd0fbf0050..870c7fc0f759dc515539c170f2befeae2d2be872 100644 (file)
@@ -225,7 +225,6 @@ static void nand_onfi_timing_set(struct denali_nand_info *denali,
        uint16_t Twhr[6] = {120, 80, 80, 60, 60, 60};
        uint16_t Tcs[6] = {70, 35, 25, 25, 20, 15};
 
-       uint16_t TclsRising = 1;
        uint16_t data_invalid_rhoh, data_invalid_rloh, data_invalid;
        uint16_t dv_window = 0;
        uint16_t en_lo, en_hi;
@@ -276,8 +275,6 @@ static void nand_onfi_timing_set(struct denali_nand_info *denali,
        re_2_re = CEIL_DIV(Trhz[mode], CLK_X);
        we_2_re = CEIL_DIV(Twhr[mode], CLK_X);
        cs_cnt = CEIL_DIV((Tcs[mode] - Trp[mode]), CLK_X);
-       if (!TclsRising)
-               cs_cnt = CEIL_DIV(Tcs[mode], CLK_X);
        if (cs_cnt == 0)
                cs_cnt = 1;
 
@@ -1536,6 +1533,9 @@ int denali_init(struct denali_nand_info *denali)
        denali->nand.options |= NAND_SKIP_BBTSCAN;
        denali->nand.ecc.mode = NAND_ECC_HW_SYNDROME;
 
+       /* no subpage writes on denali */
+       denali->nand.options |= NAND_NO_SUBPAGE_WRITE;
+
        /*
         * Denali Controller only support 15bit and 8bit ECC in MRST,
         * so just let controller do 15bit ECC for MLC and 8bit ECC for
index 4c05f4f6a5c6a9a65040b3c4adc8f46cddc3d912..51394e59901bbc11704b3bb9c6d9c978247ee01f 100644 (file)
@@ -317,7 +317,7 @@ static void fsl_ifc_run_command(struct mtd_info *mtd)
 
        /* wait for command complete flag or timeout */
        wait_event_timeout(ctrl->nand_wait, ctrl->nand_stat,
-                          IFC_TIMEOUT_MSECS * HZ/1000);
+                          msecs_to_jiffies(IFC_TIMEOUT_MSECS));
 
        /* ctrl->nand_stat will be updated from IRQ context */
        if (!ctrl->nand_stat)
@@ -860,7 +860,7 @@ static void fsl_ifc_sram_init(struct fsl_ifc_mtd *priv)
 
        /* wait for command complete flag or timeout */
        wait_event_timeout(ctrl->nand_wait, ctrl->nand_stat,
-                          IFC_TIMEOUT_MSECS * HZ/1000);
+                          msecs_to_jiffies(IFC_TIMEOUT_MSECS));
 
        if (ctrl->nand_stat != IFC_NAND_EVTER_STAT_OPC)
                printk(KERN_ERR "fsl-ifc: Failed to Initialise SRAM\n");
index edfaa21b1817b533f1272e99708592d98daaa719..e58af4bfa8c81d1752151adc8a8b86175351057e 100644 (file)
@@ -873,6 +873,7 @@ static int fsmc_nand_probe_config_dt(struct platform_device *pdev,
 {
        struct fsmc_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
        u32 val;
+       int ret;
 
        /* Set default NAND width to 8 bits */
        pdata->width = 8;
@@ -891,8 +892,12 @@ static int fsmc_nand_probe_config_dt(struct platform_device *pdev,
                                sizeof(*pdata->nand_timings), GFP_KERNEL);
        if (!pdata->nand_timings)
                return -ENOMEM;
-       of_property_read_u8_array(np, "timings", (u8 *)pdata->nand_timings,
+       ret = of_property_read_u8_array(np, "timings", (u8 *)pdata->nand_timings,
                                                sizeof(*pdata->nand_timings));
+       if (ret) {
+               dev_info(&pdev->dev, "No timings in dts specified, using default timings!\n");
+               pdata->nand_timings = NULL;
+       }
 
        /* Set default NAND bank to 0 */
        pdata->bank = 0;
index 33f3c3c54dbc769f1259335722461d742556e3e9..1b8f3500e6d22613b7046e71af5ddb5c64717f65 100644 (file)
@@ -446,7 +446,7 @@ int start_dma_without_bch_irq(struct gpmi_nand_data *this,
                                struct dma_async_tx_descriptor *desc)
 {
        struct completion *dma_c = &this->dma_done;
-       int err;
+       unsigned long timeout;
 
        init_completion(dma_c);
 
@@ -456,8 +456,8 @@ int start_dma_without_bch_irq(struct gpmi_nand_data *this,
        dma_async_issue_pending(get_dma_chan(this));
 
        /* Wait for the interrupt from the DMA block. */
-       err = wait_for_completion_timeout(dma_c, msecs_to_jiffies(1000));
-       if (!err) {
+       timeout = wait_for_completion_timeout(dma_c, msecs_to_jiffies(1000));
+       if (!timeout) {
                dev_err(this->dev, "DMA timeout, last DMA :%d\n",
                        this->last_dma_type);
                gpmi_dump_info(this);
@@ -477,7 +477,7 @@ int start_dma_with_bch_irq(struct gpmi_nand_data *this,
                        struct dma_async_tx_descriptor *desc)
 {
        struct completion *bch_c = &this->bch_done;
-       int err;
+       unsigned long timeout;
 
        /* Prepare to receive an interrupt from the BCH block. */
        init_completion(bch_c);
@@ -486,8 +486,8 @@ int start_dma_with_bch_irq(struct gpmi_nand_data *this,
        start_dma_without_bch_irq(this, desc);
 
        /* Wait for the interrupt from the BCH block. */
-       err = wait_for_completion_timeout(bch_c, msecs_to_jiffies(1000));
-       if (!err) {
+       timeout = wait_for_completion_timeout(bch_c, msecs_to_jiffies(1000));
+       if (!timeout) {
                dev_err(this->dev, "BCH timeout, last DMA :%d\n",
                        this->last_dma_type);
                gpmi_dump_info(this);
@@ -1950,7 +1950,9 @@ static int gpmi_nand_init(struct gpmi_nand_data *this)
        ret = nand_boot_init(this);
        if (ret)
                goto err_out;
-       chip->scan_bbt(mtd);
+       ret = chip->scan_bbt(mtd);
+       if (ret)
+               goto err_out;
 
        ppdata.of_node = this->pdev->dev.of_node;
        ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
index a8f550fec35e009932f4cb5d5cff9e0df17fd2b4..372e0e38f59b323f4388c6d96416ea5ea35f3c69 100644 (file)
@@ -386,26 +386,51 @@ static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
 /* This function polls the NANDFC to wait for the basic operation to
  * complete by checking the INT bit of config2 register.
  */
-static void wait_op_done(struct mxc_nand_host *host, int useirq)
+static int wait_op_done(struct mxc_nand_host *host, int useirq)
 {
-       int max_retries = 8000;
+       int ret = 0;
+
+       /*
+        * If operation is already complete, don't bother to setup an irq or a
+        * loop.
+        */
+       if (host->devtype_data->check_int(host))
+               return 0;
 
        if (useirq) {
-               if (!host->devtype_data->check_int(host)) {
-                       reinit_completion(&host->op_completion);
-                       irq_control(host, 1);
-                       wait_for_completion(&host->op_completion);
+               unsigned long timeout;
+
+               reinit_completion(&host->op_completion);
+
+               irq_control(host, 1);
+
+               timeout = wait_for_completion_timeout(&host->op_completion, HZ);
+               if (!timeout && !host->devtype_data->check_int(host)) {
+                       dev_dbg(host->dev, "timeout waiting for irq\n");
+                       ret = -ETIMEDOUT;
                }
        } else {
-               while (max_retries-- > 0) {
-                       if (host->devtype_data->check_int(host))
-                               break;
+               int max_retries = 8000;
+               int done;
 
+               do {
                        udelay(1);
+
+                       done = host->devtype_data->check_int(host);
+                       if (done)
+                               break;
+
+               } while (--max_retries);
+
+               if (!done) {
+                       dev_dbg(host->dev, "timeout polling for completion\n");
+                       ret = -ETIMEDOUT;
                }
-               if (max_retries < 0)
-                       pr_debug("%s: INT not set\n", __func__);
        }
+
+       WARN_ONCE(ret < 0, "timeout! useirq=%d\n", useirq);
+
+       return ret;
 }
 
 static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq)
@@ -527,30 +552,17 @@ static void send_page_v1(struct mtd_info *mtd, unsigned int ops)
 
 static void send_read_id_v3(struct mxc_nand_host *host)
 {
-       struct nand_chip *this = &host->nand;
-
        /* Read ID into main buffer */
        writel(NFC_ID, NFC_V3_LAUNCH);
 
        wait_op_done(host, true);
 
        memcpy32_fromio(host->data_buf, host->main_area0, 16);
-
-       if (this->options & NAND_BUSWIDTH_16) {
-               /* compress the ID info */
-               host->data_buf[1] = host->data_buf[2];
-               host->data_buf[2] = host->data_buf[4];
-               host->data_buf[3] = host->data_buf[6];
-               host->data_buf[4] = host->data_buf[8];
-               host->data_buf[5] = host->data_buf[10];
-       }
 }
 
 /* Request the NANDFC to perform a read of the NAND device ID. */
 static void send_read_id_v1_v2(struct mxc_nand_host *host)
 {
-       struct nand_chip *this = &host->nand;
-
        /* NANDFC buffer 0 is used for device ID output */
        writew(host->active_cs << 4, NFC_V1_V2_BUF_ADDR);
 
@@ -560,15 +572,6 @@ static void send_read_id_v1_v2(struct mxc_nand_host *host)
        wait_op_done(host, true);
 
        memcpy32_fromio(host->data_buf, host->main_area0, 16);
-
-       if (this->options & NAND_BUSWIDTH_16) {
-               /* compress the ID info */
-               host->data_buf[1] = host->data_buf[2];
-               host->data_buf[2] = host->data_buf[4];
-               host->data_buf[3] = host->data_buf[6];
-               host->data_buf[4] = host->data_buf[8];
-               host->data_buf[5] = host->data_buf[10];
-       }
 }
 
 static uint16_t get_dev_status_v3(struct mxc_nand_host *host)
@@ -694,9 +697,17 @@ static u_char mxc_nand_read_byte(struct mtd_info *mtd)
        if (host->status_request)
                return host->devtype_data->get_dev_status(host) & 0xFF;
 
-       ret = *(uint8_t *)(host->data_buf + host->buf_start);
-       host->buf_start++;
+       if (nand_chip->options & NAND_BUSWIDTH_16) {
+               /* only take the lower byte of each word */
+               ret = *(uint16_t *)(host->data_buf + host->buf_start);
+
+               host->buf_start += 2;
+       } else {
+               ret = *(uint8_t *)(host->data_buf + host->buf_start);
+               host->buf_start++;
+       }
 
+       pr_debug("%s: ret=0x%hhx (start=%u)\n", __func__, ret, host->buf_start);
        return ret;
 }
 
@@ -825,6 +836,12 @@ static void copy_spare(struct mtd_info *mtd, bool bfrom)
        }
 }
 
+/*
+ * MXC NANDFC can only perform full page+spare or spare-only read/write.  When
+ * the upper layers perform a read/write buf operation, the saved column address
+ * is used to index into the full page. So usually this function is called with
+ * column == 0 (unless no column cycle is needed indicated by column == -1)
+ */
 static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
 {
        struct nand_chip *nand_chip = mtd->priv;
@@ -832,16 +849,13 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
 
        /* Write out column address, if necessary */
        if (column != -1) {
-               /*
-                * MXC NANDFC can only perform full page+spare or
-                * spare-only read/write.  When the upper layers
-                * perform a read/write buf operation, the saved column
-                 * address is used to index into the full page.
-                */
-               host->devtype_data->send_addr(host, 0, page_addr == -1);
+               host->devtype_data->send_addr(host, column & 0xff,
+                                             page_addr == -1);
                if (mtd->writesize > 512)
                        /* another col addr cycle for 2k page */
-                       host->devtype_data->send_addr(host, 0, false);
+                       host->devtype_data->send_addr(host,
+                                                     (column >> 8) & 0xff,
+                                                     false);
        }
 
        /* Write out page address, if necessary */
@@ -903,7 +917,7 @@ static void preset_v1(struct mtd_info *mtd)
        struct mxc_nand_host *host = nand_chip->priv;
        uint16_t config1 = 0;
 
-       if (nand_chip->ecc.mode == NAND_ECC_HW)
+       if (nand_chip->ecc.mode == NAND_ECC_HW && mtd->writesize)
                config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
 
        if (!host->devtype_data->irqpending_quirk)
@@ -931,9 +945,6 @@ static void preset_v2(struct mtd_info *mtd)
        struct mxc_nand_host *host = nand_chip->priv;
        uint16_t config1 = 0;
 
-       if (nand_chip->ecc.mode == NAND_ECC_HW)
-               config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
-
        config1 |= NFC_V2_CONFIG1_FP_INT;
 
        if (!host->devtype_data->irqpending_quirk)
@@ -942,6 +953,9 @@ static void preset_v2(struct mtd_info *mtd)
        if (mtd->writesize) {
                uint16_t pages_per_block = mtd->erasesize / mtd->writesize;
 
+               if (nand_chip->ecc.mode == NAND_ECC_HW)
+                       config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
+
                host->eccsize = get_eccsize(mtd);
                if (host->eccsize == 4)
                        config1 |= NFC_V2_CONFIG1_ECC_MODE_4;
@@ -999,9 +1013,6 @@ static void preset_v3(struct mtd_info *mtd)
                NFC_V3_CONFIG2_INT_MSK |
                NFC_V3_CONFIG2_NUM_ADDR_PHASE0;
 
-       if (chip->ecc.mode == NAND_ECC_HW)
-               config2 |= NFC_V3_CONFIG2_ECC_EN;
-
        addr_phases = fls(chip->pagemask) >> 3;
 
        if (mtd->writesize == 2048) {
@@ -1016,6 +1027,9 @@ static void preset_v3(struct mtd_info *mtd)
        }
 
        if (mtd->writesize) {
+               if (chip->ecc.mode == NAND_ECC_HW)
+                       config2 |= NFC_V3_CONFIG2_ECC_EN;
+
                config2 |= NFC_V3_CONFIG2_PPB(
                                ffs(mtd->erasesize / mtd->writesize) - 6,
                                host->devtype_data->ppb_shift);
@@ -1066,6 +1080,9 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
                host->status_request = true;
 
                host->devtype_data->send_cmd(host, command, true);
+               WARN_ONCE(column != -1 || page_addr != -1,
+                         "Unexpected column/row value (cmd=%u, col=%d, row=%d)\n",
+                         command, column, page_addr);
                mxc_do_addr_cycle(mtd, column, page_addr);
                break;
 
@@ -1079,7 +1096,10 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
                command = NAND_CMD_READ0; /* only READ0 is valid */
 
                host->devtype_data->send_cmd(host, command, false);
-               mxc_do_addr_cycle(mtd, column, page_addr);
+               WARN_ONCE(column < 0,
+                         "Unexpected column/row value (cmd=%u, col=%d, row=%d)\n",
+                         command, column, page_addr);
+               mxc_do_addr_cycle(mtd, 0, page_addr);
 
                if (mtd->writesize > 512)
                        host->devtype_data->send_cmd(host,
@@ -1100,7 +1120,10 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
                host->buf_start = column;
 
                host->devtype_data->send_cmd(host, command, false);
-               mxc_do_addr_cycle(mtd, column, page_addr);
+               WARN_ONCE(column < -1,
+                         "Unexpected column/row value (cmd=%u, col=%d, row=%d)\n",
+                         command, column, page_addr);
+               mxc_do_addr_cycle(mtd, 0, page_addr);
                break;
 
        case NAND_CMD_PAGEPROG:
@@ -1108,6 +1131,9 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
                copy_spare(mtd, false);
                host->devtype_data->send_page(mtd, NFC_INPUT);
                host->devtype_data->send_cmd(host, command, true);
+               WARN_ONCE(column != -1 || page_addr != -1,
+                         "Unexpected column/row value (cmd=%u, col=%d, row=%d)\n",
+                         command, column, page_addr);
                mxc_do_addr_cycle(mtd, column, page_addr);
                break;
 
@@ -1115,15 +1141,29 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
                host->devtype_data->send_cmd(host, command, true);
                mxc_do_addr_cycle(mtd, column, page_addr);
                host->devtype_data->send_read_id(host);
-               host->buf_start = column;
+               host->buf_start = 0;
                break;
 
        case NAND_CMD_ERASE1:
        case NAND_CMD_ERASE2:
                host->devtype_data->send_cmd(host, command, false);
+               WARN_ONCE(column != -1,
+                         "Unexpected column value (cmd=%u, col=%d)\n",
+                         command, column);
                mxc_do_addr_cycle(mtd, column, page_addr);
 
                break;
+       case NAND_CMD_PARAM:
+               host->devtype_data->send_cmd(host, command, false);
+               mxc_do_addr_cycle(mtd, column, page_addr);
+               host->devtype_data->send_page(mtd, NFC_OUTPUT);
+               memcpy32_fromio(host->data_buf, host->main_area0, 512);
+               host->buf_start = 0;
+               break;
+       default:
+               WARN_ONCE(1, "Unimplemented command (cmd=%u)\n",
+                         command);
+               break;
        }
 }
 
index df7eb4ff07d156ec213b3656f9840f6e99a35710..c2e1232cd45cc847197c3960ddbd3cd38584dd55 100644 (file)
@@ -386,7 +386,7 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
        uint8_t buf[2] = { 0, 0 };
        int ret = 0, res, i = 0;
 
-       ops.datbuf = NULL;
+       memset(&ops, 0, sizeof(ops));
        ops.oobbuf = buf;
        ops.ooboffs = chip->badblockpos;
        if (chip->options & NAND_BUSWIDTH_16) {
@@ -565,6 +565,25 @@ void nand_wait_ready(struct mtd_info *mtd)
 }
 EXPORT_SYMBOL_GPL(nand_wait_ready);
 
+/**
+ * nand_wait_status_ready - [GENERIC] Wait for the ready status after commands.
+ * @mtd: MTD device structure
+ * @timeo: Timeout in ms
+ *
+ * Wait for status ready (i.e. command done) or timeout.
+ */
+static void nand_wait_status_ready(struct mtd_info *mtd, unsigned long timeo)
+{
+       register struct nand_chip *chip = mtd->priv;
+
+       timeo = jiffies + msecs_to_jiffies(timeo);
+       do {
+               if ((chip->read_byte(mtd) & NAND_STATUS_READY))
+                       break;
+               touch_softlockup_watchdog();
+       } while (time_before(jiffies, timeo));
+};
+
 /**
  * nand_command - [DEFAULT] Send command to NAND device
  * @mtd: MTD device structure
@@ -643,8 +662,8 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,
                               NAND_CTRL_CLE | NAND_CTRL_CHANGE);
                chip->cmd_ctrl(mtd,
                               NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
-               while (!(chip->read_byte(mtd) & NAND_STATUS_READY))
-                               ;
+               /* EZ-NAND can take upto 250ms as per ONFi v4.0 */
+               nand_wait_status_ready(mtd, 250);
                return;
 
                /* This applies to read commands */
@@ -740,8 +759,8 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
                               NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
                chip->cmd_ctrl(mtd, NAND_CMD_NONE,
                               NAND_NCE | NAND_CTRL_CHANGE);
-               while (!(chip->read_byte(mtd) & NAND_STATUS_READY))
-                               ;
+               /* EZ-NAND can take upto 250ms as per ONFi v4.0 */
+               nand_wait_status_ready(mtd, 250);
                return;
 
        case NAND_CMD_RNDOUT:
@@ -968,7 +987,7 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
                        __func__, (unsigned long long)ofs, len);
 
        if (check_offs_len(mtd, ofs, len))
-               ret = -EINVAL;
+               return -EINVAL;
 
        /* Align to last block address if size addresses end of the device */
        if (ofs + len == mtd->size)
@@ -1031,7 +1050,7 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
                        __func__, (unsigned long long)ofs, len);
 
        if (check_offs_len(mtd, ofs, len))
-               ret = -EINVAL;
+               return -EINVAL;
 
        nand_get_device(mtd, FL_LOCKING);
 
@@ -1716,9 +1735,9 @@ static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
        int ret;
 
        nand_get_device(mtd, FL_READING);
+       memset(&ops, 0, sizeof(ops));
        ops.len = len;
        ops.datbuf = buf;
-       ops.oobbuf = NULL;
        ops.mode = MTD_OPS_PLACE_OOB;
        ret = nand_do_read_ops(mtd, from, &ops);
        *retlen = ops.retlen;
@@ -2124,7 +2143,7 @@ static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
 
 
 /**
- * nand_write_subpage_hwecc - [REPLACABLE] hardware ECC based subpage write
+ * nand_write_subpage_hwecc - [REPLACEABLE] hardware ECC based subpage write
  * @mtd:       mtd info structure
  * @chip:      nand chip info structure
  * @offset:    column address of subpage within the page
@@ -2508,9 +2527,9 @@ static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
        /* Grab the device */
        panic_nand_get_device(chip, mtd, FL_WRITING);
 
+       memset(&ops, 0, sizeof(ops));
        ops.len = len;
        ops.datbuf = (uint8_t *)buf;
-       ops.oobbuf = NULL;
        ops.mode = MTD_OPS_PLACE_OOB;
 
        ret = nand_do_write_ops(mtd, to, &ops);
@@ -2536,9 +2555,9 @@ static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
        int ret;
 
        nand_get_device(mtd, FL_WRITING);
+       memset(&ops, 0, sizeof(ops));
        ops.len = len;
        ops.datbuf = (uint8_t *)buf;
-       ops.oobbuf = NULL;
        ops.mode = MTD_OPS_PLACE_OOB;
        ret = nand_do_write_ops(mtd, to, &ops);
        *retlen = ops.retlen;
index 10b1f7a4fe50511e9fdac06242343f14df9cf71f..a4615fcc3d001f6a0efba58ddfc5b5573ad91069 100644 (file)
@@ -38,8 +38,8 @@
 
 #include <linux/platform_data/mtd-nand-pxa3xx.h>
 
-#define        CHIP_DELAY_TIMEOUT      (2 * HZ/10)
-#define NAND_STOP_DELAY                (2 * HZ/50)
+#define        CHIP_DELAY_TIMEOUT      msecs_to_jiffies(200)
+#define NAND_STOP_DELAY                msecs_to_jiffies(40)
 #define PAGE_CHUNK_SIZE                (2048)
 
 /*
@@ -605,11 +605,24 @@ static void start_data_dma(struct pxa3xx_nand_info *info)
 {}
 #endif
 
+static irqreturn_t pxa3xx_nand_irq_thread(int irq, void *data)
+{
+       struct pxa3xx_nand_info *info = data;
+
+       handle_data_pio(info);
+
+       info->state = STATE_CMD_DONE;
+       nand_writel(info, NDSR, NDSR_WRDREQ | NDSR_RDDREQ);
+
+       return IRQ_HANDLED;
+}
+
 static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 {
        struct pxa3xx_nand_info *info = devid;
        unsigned int status, is_completed = 0, is_ready = 0;
        unsigned int ready, cmd_done;
+       irqreturn_t ret = IRQ_HANDLED;
 
        if (info->cs == 0) {
                ready           = NDSR_FLASH_RDY;
@@ -651,7 +664,8 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
                } else {
                        info->state = (status & NDSR_RDDREQ) ?
                                      STATE_PIO_READING : STATE_PIO_WRITING;
-                       handle_data_pio(info);
+                       ret = IRQ_WAKE_THREAD;
+                       goto NORMAL_IRQ_EXIT;
                }
        }
        if (status & cmd_done) {
@@ -692,7 +706,7 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
        if (is_ready)
                complete(&info->dev_ready);
 NORMAL_IRQ_EXIT:
-       return IRQ_HANDLED;
+       return ret;
 }
 
 static inline int is_buf_blank(uint8_t *buf, size_t len)
@@ -951,7 +965,7 @@ static void nand_cmdfunc(struct mtd_info *mtd, unsigned command,
 {
        struct pxa3xx_nand_host *host = mtd->priv;
        struct pxa3xx_nand_info *info = host->info_data;
-       int ret, exec_cmd;
+       int exec_cmd;
 
        /*
         * if this is a x16 device ,then convert the input
@@ -983,9 +997,8 @@ static void nand_cmdfunc(struct mtd_info *mtd, unsigned command,
                info->need_wait = 1;
                pxa3xx_nand_start(info);
 
-               ret = wait_for_completion_timeout(&info->cmd_complete,
-                               CHIP_DELAY_TIMEOUT);
-               if (!ret) {
+               if (!wait_for_completion_timeout(&info->cmd_complete,
+                   CHIP_DELAY_TIMEOUT)) {
                        dev_err(&info->pdev->dev, "Wait time out!!!\n");
                        /* Stop State Machine for next command cycle */
                        pxa3xx_nand_stop(info);
@@ -1000,7 +1013,7 @@ static void nand_cmdfunc_extended(struct mtd_info *mtd,
 {
        struct pxa3xx_nand_host *host = mtd->priv;
        struct pxa3xx_nand_info *info = host->info_data;
-       int ret, exec_cmd, ext_cmd_type;
+       int exec_cmd, ext_cmd_type;
 
        /*
         * if this is a x16 device then convert the input
@@ -1063,9 +1076,8 @@ static void nand_cmdfunc_extended(struct mtd_info *mtd,
                init_completion(&info->cmd_complete);
                pxa3xx_nand_start(info);
 
-               ret = wait_for_completion_timeout(&info->cmd_complete,
-                               CHIP_DELAY_TIMEOUT);
-               if (!ret) {
+               if (!wait_for_completion_timeout(&info->cmd_complete,
+                   CHIP_DELAY_TIMEOUT)) {
                        dev_err(&info->pdev->dev, "Wait time out!!!\n");
                        /* Stop State Machine for next command cycle */
                        pxa3xx_nand_stop(info);
@@ -1198,13 +1210,11 @@ static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
 {
        struct pxa3xx_nand_host *host = mtd->priv;
        struct pxa3xx_nand_info *info = host->info_data;
-       int ret;
 
        if (info->need_wait) {
-               ret = wait_for_completion_timeout(&info->dev_ready,
-                               CHIP_DELAY_TIMEOUT);
                info->need_wait = 0;
-               if (!ret) {
+               if (!wait_for_completion_timeout(&info->dev_ready,
+                   CHIP_DELAY_TIMEOUT)) {
                        dev_err(&info->pdev->dev, "Ready time out!!!\n");
                        return NAND_STATUS_FAIL;
                }
@@ -1508,6 +1518,8 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
                return ret;
        }
 
+       memset(pxa3xx_flash_ids, 0, sizeof(pxa3xx_flash_ids));
+
        pxa3xx_flash_ids[0].name = f->name;
        pxa3xx_flash_ids[0].dev_id = (f->chip_id >> 8) & 0xffff;
        pxa3xx_flash_ids[0].pagesize = f->page_size;
@@ -1710,7 +1722,9 @@ static int alloc_nand_resource(struct platform_device *pdev)
        /* initialize all interrupts to be disabled */
        disable_int(info, NDSR_MASK);
 
-       ret = request_irq(irq, pxa3xx_nand_irq, 0, pdev->name, info);
+       ret = request_threaded_irq(irq, pxa3xx_nand_irq,
+                                  pxa3xx_nand_irq_thread, IRQF_ONESHOT,
+                                  pdev->name, info);
        if (ret < 0) {
                dev_err(&pdev->dev, "failed to request IRQ\n");
                goto fail_free_buf;
index 35aef5edb5887f8f8c1f1053e6a7873a887b4077..0e02be47ce1d4dbc959e7037a5bb08edc8e91b98 100644 (file)
@@ -948,8 +948,6 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
 
        cpu_type = platform_get_device_id(pdev)->driver_data;
 
-       pr_debug("s3c2410_nand_probe(%p)\n", pdev);
-
        info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
        if (info == NULL) {
                err = -ENOMEM;
@@ -1045,7 +1043,6 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
                s3c2410_nand_clk_set_state(info, CLOCK_SUSPEND);
        }
 
-       pr_debug("initialised ok\n");
        return 0;
 
  exit_error:
index a21c378f096acd79b23851cc6fe2c054b48ab835..c3ce81c1a7163a71d3ceee81ea248e11f45925dc 100644 (file)
@@ -159,7 +159,6 @@ static void flctl_setup_dma(struct sh_flctl *flctl)
                return;
 
        memset(&cfg, 0, sizeof(cfg));
-       cfg.slave_id = pdata->slave_id_fifo0_tx;
        cfg.direction = DMA_MEM_TO_DEV;
        cfg.dst_addr = (dma_addr_t)FLDTFIFO(flctl);
        cfg.src_addr = 0;
@@ -175,7 +174,6 @@ static void flctl_setup_dma(struct sh_flctl *flctl)
        if (!flctl->chan_fifo0_rx)
                goto err;
 
-       cfg.slave_id = pdata->slave_id_fifo0_rx;
        cfg.direction = DMA_DEV_TO_MEM;
        cfg.dst_addr = 0;
        cfg.src_addr = (dma_addr_t)FLDTFIFO(flctl);
index 635ee0027691eb771bc31eac771209b48987d8e2..43b3392ffee7e255555d88948e4dbe2aa47867d2 100644 (file)
@@ -1743,7 +1743,6 @@ static int onenand_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
        struct onenand_chip *this = mtd->priv;
        int column, subpage;
        int written = 0;
-       int ret = 0;
 
        if (this->state == FL_PM_SUSPENDED)
                return -EBUSY;
@@ -1786,15 +1785,10 @@ static int onenand_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
                onenand_panic_wait(mtd);
 
                /* In partial page write we don't update bufferram */
-               onenand_update_bufferram(mtd, to, !ret && !subpage);
+               onenand_update_bufferram(mtd, to, !subpage);
                if (ONENAND_IS_2PLANE(this)) {
                        ONENAND_SET_BUFFERRAM1(this);
-                       onenand_update_bufferram(mtd, to + this->writesize, !ret && !subpage);
-               }
-
-               if (ret) {
-                       printk(KERN_ERR "%s: write failed %d\n", __func__, ret);
-                       break;
+                       onenand_update_bufferram(mtd, to + this->writesize, !subpage);
                }
 
                written += thislen;
@@ -1808,7 +1802,7 @@ static int onenand_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
        }
 
        *retlen = written;
-       return ret;
+       return 0;
 }
 
 /**
index 1c7308c2c77d9b54beb22ad626a0b9d813052a48..5d5d36272bb5b3b5d50074e89515e683cb7f6084 100644 (file)
@@ -460,8 +460,7 @@ fsl_qspi_runcmd(struct fsl_qspi *q, u8 cmd, unsigned int addr, int len)
        writel((seqid << QUADSPI_IPCR_SEQID_SHIFT) | len, base + QUADSPI_IPCR);
 
        /* Wait for the interrupt. */
-       err = wait_for_completion_timeout(&q->c, msecs_to_jiffies(1000));
-       if (!err) {
+       if (!wait_for_completion_timeout(&q->c, msecs_to_jiffies(1000))) {
                dev_err(q->dev,
                        "cmd 0x%.2x timeout, addr@%.8x, FR:0x%.8x, SR:0x%.8x\n",
                        cmd, addr, readl(base + QUADSPI_FR),
@@ -830,27 +829,27 @@ static int fsl_qspi_probe(struct platform_device *pdev)
 
        ret = clk_prepare_enable(q->clk_en);
        if (ret) {
-               dev_err(dev, "can not enable the qspi_en clock\n");
+               dev_err(dev, "cannot enable the qspi_en clock: %d\n", ret);
                return ret;
        }
 
        ret = clk_prepare_enable(q->clk);
        if (ret) {
-               dev_err(dev, "can not enable the qspi clock\n");
+               dev_err(dev, "cannot enable the qspi clock: %d\n", ret);
                goto clk_failed;
        }
 
        /* find the irq */
        ret = platform_get_irq(pdev, 0);
        if (ret < 0) {
-               dev_err(dev, "failed to get the irq\n");
+               dev_err(dev, "failed to get the irq: %d\n", ret);
                goto irq_failed;
        }
 
        ret = devm_request_irq(dev, ret,
                        fsl_qspi_irq_handler, 0, pdev->name, q);
        if (ret) {
-               dev_err(dev, "failed to request irq.\n");
+               dev_err(dev, "failed to request irq: %d\n", ret);
                goto irq_failed;
        }
 
index b6a5a0c269e1d29f2dbf46f2ab2f2117dbe96417..14a5d2325dac0cdf0558d881a99fee2727b7a7bb 100644 (file)
@@ -369,17 +369,13 @@ erase_err:
        return ret;
 }
 
-static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len)
 {
-       struct spi_nor *nor = mtd_to_spi_nor(mtd);
+       struct mtd_info *mtd = nor->mtd;
        uint32_t offset = ofs;
        uint8_t status_old, status_new;
        int ret = 0;
 
-       ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_LOCK);
-       if (ret)
-               return ret;
-
        status_old = read_sr(nor);
 
        if (offset < mtd->size - (mtd->size / 2))
@@ -402,26 +398,18 @@ static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
                                (status_old & (SR_BP2 | SR_BP1 | SR_BP0))) {
                write_enable(nor);
                ret = write_sr(nor, status_new);
-               if (ret)
-                       goto err;
        }
 
-err:
-       spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK);
        return ret;
 }
 
-static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len)
 {
-       struct spi_nor *nor = mtd_to_spi_nor(mtd);
+       struct mtd_info *mtd = nor->mtd;
        uint32_t offset = ofs;
        uint8_t status_old, status_new;
        int ret = 0;
 
-       ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_UNLOCK);
-       if (ret)
-               return ret;
-
        status_old = read_sr(nor);
 
        if (offset+len > mtd->size - (mtd->size / 64))
@@ -444,15 +432,41 @@ static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
                                (status_old & (SR_BP2 | SR_BP1 | SR_BP0))) {
                write_enable(nor);
                ret = write_sr(nor, status_new);
-               if (ret)
-                       goto err;
        }
 
-err:
+       return ret;
+}
+
+static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+{
+       struct spi_nor *nor = mtd_to_spi_nor(mtd);
+       int ret;
+
+       ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_LOCK);
+       if (ret)
+               return ret;
+
+       ret = nor->flash_lock(nor, ofs, len);
+
        spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_UNLOCK);
        return ret;
 }
 
+static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+{
+       struct spi_nor *nor = mtd_to_spi_nor(mtd);
+       int ret;
+
+       ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_UNLOCK);
+       if (ret)
+               return ret;
+
+       ret = nor->flash_unlock(nor, ofs, len);
+
+       spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK);
+       return ret;
+}
+
 /* Used when the "_ext_id" is two bytes at most */
 #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags)     \
        ((kernel_ulong_t)&(struct flash_info) {                         \
@@ -524,6 +538,7 @@ static const struct spi_device_id spi_nor_ids[] = {
        { "en25q64",    INFO(0x1c3017, 0, 64 * 1024,  128, SECT_4K) },
        { "en25qh128",  INFO(0x1c7018, 0, 64 * 1024,  256, 0) },
        { "en25qh256",  INFO(0x1c7019, 0, 64 * 1024,  512, 0) },
+       { "en25s64",    INFO(0x1c3817, 0, 64 * 1024,  128, 0) },
 
        /* ESMT */
        { "f25l32pa", INFO(0x8c2016, 0, 64 * 1024, 64, SECT_4K) },
@@ -553,6 +568,7 @@ static const struct spi_device_id spi_nor_ids[] = {
        { "mx25l3205d",  INFO(0xc22016, 0, 64 * 1024,  64, 0) },
        { "mx25l3255e",  INFO(0xc29e16, 0, 64 * 1024,  64, SECT_4K) },
        { "mx25l6405d",  INFO(0xc22017, 0, 64 * 1024, 128, 0) },
+       { "mx25u6435f",  INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) },
        { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
        { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
        { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) },
@@ -648,6 +664,7 @@ static const struct spi_device_id spi_nor_ids[] = {
        { "m25px80",    INFO(0x207114,  0, 64 * 1024, 16, 0) },
 
        /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
+       { "w25x05", INFO(0xef3010, 0, 64 * 1024,  1,  SECT_4K) },
        { "w25x10", INFO(0xef3011, 0, 64 * 1024,  2,  SECT_4K) },
        { "w25x20", INFO(0xef3012, 0, 64 * 1024,  4,  SECT_4K) },
        { "w25x40", INFO(0xef3013, 0, 64 * 1024,  8,  SECT_4K) },
@@ -658,6 +675,7 @@ static const struct spi_device_id spi_nor_ids[] = {
        { "w25q32dw", INFO(0xef6016, 0, 64 * 1024,  64, SECT_4K) },
        { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) },
        { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
+       { "w25q64dw", INFO(0xef6017, 0, 64 * 1024, 128, SECT_4K) },
        { "w25q80", INFO(0xef5014, 0, 64 * 1024,  16, SECT_4K) },
        { "w25q80bl", INFO(0xef4014, 0, 64 * 1024,  16, SECT_4K) },
        { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) },
@@ -1045,6 +1063,11 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
 
        /* nor protection support for STmicro chips */
        if (JEDEC_MFR(info) == CFI_MFR_ST) {
+               nor->flash_lock = stm_lock;
+               nor->flash_unlock = stm_unlock;
+       }
+
+       if (nor->flash_lock && nor->flash_unlock) {
                mtd->_lock = spi_nor_lock;
                mtd->_unlock = spi_nor_unlock;
        }
index e579f9027c47d82bb1e4d577ddd13128324a0075..79316159eec63cbca36aa06d27bfaab561b62dc0 100644 (file)
@@ -9,6 +9,8 @@
 #include <linux/slab.h>
 #include <linux/mtd/nand_ecc.h>
 
+#include "mtd_test.h"
+
 /*
  * Test the implementation for software ECC
  *
@@ -274,6 +276,10 @@ static int nand_ecc_test_run(const size_t size)
                }
                pr_info("ok - %s-%zd\n",
                        nand_ecc_test[i].name, size);
+
+               err = mtdtest_relax();
+               if (err)
+                       break;
        }
 error:
        kfree(error_data);
index f437c776c54f499614746b78492d0d38139049af..4b7bee17c924bb0f29c007812568bdadb3226924 100644 (file)
@@ -1,4 +1,16 @@
 #include <linux/mtd/mtd.h>
+#include <linux/sched.h>
+
+static inline int mtdtest_relax(void)
+{
+       cond_resched();
+       if (signal_pending(current)) {
+               pr_info("aborting test due to pending signal!\n");
+               return -EINTR;
+       }
+
+       return 0;
+}
 
 int mtdtest_erase_eraseblock(struct mtd_info *mtd, unsigned int ebnum);
 int mtdtest_scan_for_bad_eraseblocks(struct mtd_info *mtd, unsigned char *bbt,
index 273f7e5539541ee7fa2bdd7bed0eb659dc2bebca..09a4ccac53a2e74dd29aae1c9e8d41baad505609 100644 (file)
@@ -320,6 +320,10 @@ static int overwrite_test(void)
                        break;
                }
 
+               err = mtdtest_relax();
+               if (err)
+                       break;
+
                opno++;
        }
 
index 5e061186eab181c927d41568dd73b7cd9e486b25..8e8525f0202f60b2349cc0fcff0357b038d6417e 100644 (file)
@@ -70,7 +70,7 @@ static int write_eraseblock(int ebnum)
        int i;
        struct mtd_oob_ops ops;
        int err = 0;
-       loff_t addr = ebnum * mtd->erasesize;
+       loff_t addr = (loff_t)ebnum * mtd->erasesize;
 
        prandom_bytes_state(&rnd_state, writebuf, use_len_max * pgcnt);
        for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
@@ -112,7 +112,10 @@ static int write_whole_device(void)
                        return err;
                if (i % 256 == 0)
                        pr_info("written up to eraseblock %u\n", i);
-               cond_resched();
+
+               err = mtdtest_relax();
+               if (err)
+                       return err;
        }
        pr_info("written %u eraseblocks\n", i);
        return 0;
@@ -141,6 +144,31 @@ static size_t memcmpshow(loff_t addr, const void *cs, const void *ct, size_t cou
        return bitflips;
 }
 
+/*
+ * Compare with 0xff and show the address, offset and data bytes at
+ * comparison failure. Return number of bitflips encountered.
+ */
+static size_t memffshow(loff_t addr, loff_t offset, const void *cs,
+                       size_t count)
+{
+       const unsigned char *su1;
+       int res;
+       size_t i = 0;
+       size_t bitflips = 0;
+
+       for (su1 = cs; 0 < count; ++su1, count--, i++) {
+               res = *su1 ^ 0xff;
+               if (res) {
+                       pr_info("error @addr[0x%lx:0x%lx] 0x%x -> 0xff diff 0x%x\n",
+                               (unsigned long)addr, (unsigned long)offset + i,
+                               *su1, res);
+                       bitflips += hweight8(res);
+               }
+       }
+
+       return bitflips;
+}
+
 static int verify_eraseblock(int ebnum)
 {
        int i;
@@ -203,6 +231,15 @@ static int verify_eraseblock(int ebnum)
                        bitflips = memcmpshow(addr, readbuf + use_offset,
                                              writebuf + (use_len_max * i) + use_offset,
                                              use_len);
+
+                       /* verify pre-offset area for 0xff */
+                       bitflips += memffshow(addr, 0, readbuf, use_offset);
+
+                       /* verify post-(use_offset + use_len) area for 0xff */
+                       k = use_offset + use_len;
+                       bitflips += memffshow(addr, k, readbuf + k,
+                                             mtd->ecclayout->oobavail - k);
+
                        if (bitflips > bitflip_limit) {
                                pr_err("error: verify failed at %#llx\n",
                                                (long long)addr);
@@ -212,34 +249,8 @@ static int verify_eraseblock(int ebnum)
                                        return -1;
                                }
                        } else if (bitflips) {
-                               pr_info("ignoring error as within bitflip_limit\n");
+                               pr_info("ignoring errors as within bitflip limit\n");
                        }
-
-                       for (k = 0; k < use_offset; ++k)
-                               if (readbuf[k] != 0xff) {
-                                       pr_err("error: verify 0xff "
-                                              "failed at %#llx\n",
-                                              (long long)addr);
-                                       errcnt += 1;
-                                       if (errcnt > 1000) {
-                                               pr_err("error: too "
-                                                      "many errors\n");
-                                               return -1;
-                                       }
-                               }
-                       for (k = use_offset + use_len;
-                            k < mtd->ecclayout->oobavail; ++k)
-                               if (readbuf[k] != 0xff) {
-                                       pr_err("error: verify 0xff "
-                                              "failed at %#llx\n",
-                                              (long long)addr);
-                                       errcnt += 1;
-                                       if (errcnt > 1000) {
-                                               pr_err("error: too "
-                                                      "many errors\n");
-                                               return -1;
-                                       }
-                               }
                }
                if (vary_offset)
                        do_vary_offset();
@@ -310,7 +321,10 @@ static int verify_all_eraseblocks(void)
                        return err;
                if (i % 256 == 0)
                        pr_info("verified up to eraseblock %u\n", i);
-               cond_resched();
+
+               err = mtdtest_relax();
+               if (err)
+                       return err;
        }
        pr_info("verified %u eraseblocks\n", i);
        return 0;
@@ -421,7 +435,10 @@ static int __init mtd_oobtest_init(void)
                        goto out;
                if (i % 256 == 0)
                        pr_info("verified up to eraseblock %u\n", i);
-               cond_resched();
+
+               err = mtdtest_relax();
+               if (err)
+                       goto out;
        }
        pr_info("verified %u eraseblocks\n", i);
 
@@ -634,7 +651,11 @@ static int __init mtd_oobtest_init(void)
                                goto out;
                        if (i % 256 == 0)
                                pr_info("written up to eraseblock %u\n", i);
-                       cond_resched();
+
+                       err = mtdtest_relax();
+                       if (err)
+                               goto out;
+
                        addr += mtd->writesize;
                }
        }
@@ -672,7 +693,10 @@ static int __init mtd_oobtest_init(void)
                }
                if (i % 256 == 0)
                        pr_info("verified up to eraseblock %u\n", i);
-               cond_resched();
+
+               err = mtdtest_relax();
+               if (err)
+                       goto out;
        }
        pr_info("verified %u eraseblocks\n", i);
 
index 88296e888e9d6518a398384d26c68a0d7744bcb9..ba1890d5632ce1607d5ce8371c3ff962f8b8cc41 100644 (file)
@@ -407,7 +407,10 @@ static int __init mtd_pagetest_init(void)
                        goto out;
                if (i % 256 == 0)
                        pr_info("written up to eraseblock %u\n", i);
-               cond_resched();
+
+               err = mtdtest_relax();
+               if (err)
+                       goto out;
        }
        pr_info("written %u eraseblocks\n", i);
 
@@ -422,7 +425,10 @@ static int __init mtd_pagetest_init(void)
                        goto out;
                if (i % 256 == 0)
                        pr_info("verified up to eraseblock %u\n", i);
-               cond_resched();
+
+               err = mtdtest_relax();
+               if (err)
+                       goto out;
        }
        pr_info("verified %u eraseblocks\n", i);
 
index a54cf1511114c31ed5d52a59a7d9814d792a334f..a3196b750a220663b22f866fbf8173ca6fe81d4a 100644 (file)
@@ -190,7 +190,10 @@ static int __init mtd_readtest_init(void)
                        if (!err)
                                err = ret;
                }
-               cond_resched();
+
+               err = mtdtest_relax();
+               if (err)
+                       goto out;
        }
 
        if (err)
index 5ee9f7021020dae7a45a90e646a7afa12deeeb7d..5a6f31af06f90c3337ae1316310e50af070d4f17 100644 (file)
@@ -185,7 +185,7 @@ static long calc_speed(void)
             (finish.tv_usec - start.tv_usec) / 1000;
        if (ms == 0)
                return 0;
-       k = goodebcnt * (mtd->erasesize / 1024) * 1000;
+       k = (uint64_t)goodebcnt * (mtd->erasesize / 1024) * 1000;
        do_div(k, ms);
        return k;
 }
@@ -269,7 +269,10 @@ static int __init mtd_speedtest_init(void)
                err = write_eraseblock(i);
                if (err)
                        goto out;
-               cond_resched();
+
+               err = mtdtest_relax();
+               if (err)
+                       goto out;
        }
        stop_timing();
        speed = calc_speed();
@@ -284,7 +287,10 @@ static int __init mtd_speedtest_init(void)
                err = read_eraseblock(i);
                if (err)
                        goto out;
-               cond_resched();
+
+               err = mtdtest_relax();
+               if (err)
+                       goto out;
        }
        stop_timing();
        speed = calc_speed();
@@ -303,7 +309,10 @@ static int __init mtd_speedtest_init(void)
                err = write_eraseblock_by_page(i);
                if (err)
                        goto out;
-               cond_resched();
+
+               err = mtdtest_relax();
+               if (err)
+                       goto out;
        }
        stop_timing();
        speed = calc_speed();
@@ -318,7 +327,10 @@ static int __init mtd_speedtest_init(void)
                err = read_eraseblock_by_page(i);
                if (err)
                        goto out;
-               cond_resched();
+
+               err = mtdtest_relax();
+               if (err)
+                       goto out;
        }
        stop_timing();
        speed = calc_speed();
@@ -337,7 +349,10 @@ static int __init mtd_speedtest_init(void)
                err = write_eraseblock_by_2pages(i);
                if (err)
                        goto out;
-               cond_resched();
+
+               err = mtdtest_relax();
+               if (err)
+                       goto out;
        }
        stop_timing();
        speed = calc_speed();
@@ -352,7 +367,10 @@ static int __init mtd_speedtest_init(void)
                err = read_eraseblock_by_2pages(i);
                if (err)
                        goto out;
-               cond_resched();
+
+               err = mtdtest_relax();
+               if (err)
+                       goto out;
        }
        stop_timing();
        speed = calc_speed();
@@ -385,7 +403,11 @@ static int __init mtd_speedtest_init(void)
                        err = multiblock_erase(i, j);
                        if (err)
                                goto out;
-                       cond_resched();
+
+                       err = mtdtest_relax();
+                       if (err)
+                               goto out;
+
                        i += j;
                }
                stop_timing();
index c9d42cc2df1b5303804217f7621af9539cffc28f..e509f8aa9a7eea21db08004a8eca1608880ac7d1 100644 (file)
@@ -96,7 +96,7 @@ static int do_read(void)
                if (offs + len > mtd->erasesize)
                        len = mtd->erasesize - offs;
        }
-       addr = eb * mtd->erasesize + offs;
+       addr = (loff_t)eb * mtd->erasesize + offs;
        return mtdtest_read(mtd, addr, len, readbuf);
 }
 
@@ -124,7 +124,7 @@ static int do_write(void)
                        offsets[eb + 1] = 0;
                }
        }
-       addr = eb * mtd->erasesize + offs;
+       addr = (loff_t)eb * mtd->erasesize + offs;
        err = mtdtest_write(mtd, addr, len, writebuf);
        if (unlikely(err))
                return err;
@@ -221,7 +221,10 @@ static int __init mtd_stresstest_init(void)
                err = do_operation();
                if (err)
                        goto out;
-               cond_resched();
+
+               err = mtdtest_relax();
+               if (err)
+                       goto out;
        }
        pr_info("finished, %d operations done\n", op);
 
index 7b59ef522d5ea9b98431d376b4095451ba9b7f8b..aecc6ce5a9e1c131a38d657325356ab590de845c 100644 (file)
@@ -95,7 +95,7 @@ static int write_eraseblock2(int ebnum)
        loff_t addr = (loff_t)ebnum * mtd->erasesize;
 
        for (k = 1; k < 33; ++k) {
-               if (addr + (subpgsize * k) > (ebnum + 1) * mtd->erasesize)
+               if (addr + (subpgsize * k) > (loff_t)(ebnum + 1) * mtd->erasesize)
                        break;
                prandom_bytes_state(&rnd_state, writebuf, subpgsize * k);
                err = mtd_write(mtd, addr, subpgsize * k, &written, writebuf);
@@ -195,7 +195,7 @@ static int verify_eraseblock2(int ebnum)
        loff_t addr = (loff_t)ebnum * mtd->erasesize;
 
        for (k = 1; k < 33; ++k) {
-               if (addr + (subpgsize * k) > (ebnum + 1) * mtd->erasesize)
+               if (addr + (subpgsize * k) > (loff_t)(ebnum + 1) * mtd->erasesize)
                        break;
                prandom_bytes_state(&rnd_state, writebuf, subpgsize * k);
                clear_data(readbuf, subpgsize * k);
@@ -269,7 +269,10 @@ static int verify_all_eraseblocks_ff(void)
                        return err;
                if (i % 256 == 0)
                        pr_info("verified up to eraseblock %u\n", i);
-               cond_resched();
+
+               err = mtdtest_relax();
+               if (err)
+                       return err;
        }
        pr_info("verified %u eraseblocks\n", i);
        return 0;
@@ -346,7 +349,10 @@ static int __init mtd_subpagetest_init(void)
                        goto out;
                if (i % 256 == 0)
                        pr_info("written up to eraseblock %u\n", i);
-               cond_resched();
+
+               err = mtdtest_relax();
+               if (err)
+                       goto out;
        }
        pr_info("written %u eraseblocks\n", i);
 
@@ -360,7 +366,10 @@ static int __init mtd_subpagetest_init(void)
                        goto out;
                if (i % 256 == 0)
                        pr_info("verified up to eraseblock %u\n", i);
-               cond_resched();
+
+               err = mtdtest_relax();
+               if (err)
+                       goto out;
        }
        pr_info("verified %u eraseblocks\n", i);
 
@@ -383,7 +392,10 @@ static int __init mtd_subpagetest_init(void)
                        goto out;
                if (i % 256 == 0)
                        pr_info("written up to eraseblock %u\n", i);
-               cond_resched();
+
+               err = mtdtest_relax();
+               if (err)
+                       goto out;
        }
        pr_info("written %u eraseblocks\n", i);
 
@@ -398,7 +410,10 @@ static int __init mtd_subpagetest_init(void)
                        goto out;
                if (i % 256 == 0)
                        pr_info("verified up to eraseblock %u\n", i);
-               cond_resched();
+
+               err = mtdtest_relax();
+               if (err)
+                       goto out;
        }
        pr_info("verified %u eraseblocks\n", i);
 
index b55bc52a134084759b5dd61d22554faa1f0bc032..e5d6e6d9532fa5f12961ae9aae72d0766e296370 100644 (file)
@@ -101,11 +101,11 @@ static inline int check_eraseblock(int ebnum, unsigned char *buf)
 {
        int err, retries = 0;
        size_t read;
-       loff_t addr = ebnum * mtd->erasesize;
+       loff_t addr = (loff_t)ebnum * mtd->erasesize;
        size_t len = mtd->erasesize;
 
        if (pgcnt) {
-               addr = (ebnum + 1) * mtd->erasesize - pgcnt * pgsize;
+               addr = (loff_t)(ebnum + 1) * mtd->erasesize - pgcnt * pgsize;
                len = pgcnt * pgsize;
        }
 
@@ -155,11 +155,11 @@ static inline int write_pattern(int ebnum, void *buf)
 {
        int err;
        size_t written;
-       loff_t addr = ebnum * mtd->erasesize;
+       loff_t addr = (loff_t)ebnum * mtd->erasesize;
        size_t len = mtd->erasesize;
 
        if (pgcnt) {
-               addr = (ebnum + 1) * mtd->erasesize - pgcnt * pgsize;
+               addr = (loff_t)(ebnum + 1) * mtd->erasesize - pgcnt * pgsize;
                len = pgcnt * pgsize;
        }
        err = mtd_write(mtd, addr, len, &written, buf);
@@ -279,7 +279,10 @@ static int __init tort_init(void)
                                               " for 0xFF... pattern\n");
                                        goto out;
                                }
-                               cond_resched();
+
+                               err = mtdtest_relax();
+                               if (err)
+                                       goto out;
                        }
                }
 
@@ -294,7 +297,10 @@ static int __init tort_init(void)
                        err = write_pattern(i, patt);
                        if (err)
                                goto out;
-                       cond_resched();
+
+                       err = mtdtest_relax();
+                       if (err)
+                               goto out;
                }
 
                /* Verify what we wrote */
@@ -314,7 +320,10 @@ static int __init tort_init(void)
                                               "0x55AA55..." : "0xAA55AA...");
                                        goto out;
                                }
-                               cond_resched();
+
+                               err = mtdtest_relax();
+                               if (err)
+                                       goto out;
                        }
                }
 
index 9690cf9aaef557d922a9423b15db5e8761ccd993..b7f824d5ee8884eb1268ae3b0fb7501c4f3fe811 100644 (file)
@@ -1169,9 +1169,9 @@ static struct mtd_info * __init open_mtd_by_chdev(const char *mtd_dev)
                return ERR_PTR(err);
 
        /* MTD device number is defined by the major / minor numbers */
-       major = imajor(path.dentry->d_inode);
-       minor = iminor(path.dentry->d_inode);
-       mode = path.dentry->d_inode->i_mode;
+       major = imajor(d_backing_inode(path.dentry));
+       minor = iminor(d_backing_inode(path.dentry));
+       mode = d_backing_inode(path.dentry)->i_mode;
        path_put(&path);
        if (major != MTD_CHAR_MAJOR || !S_ISCHR(mode))
                return ERR_PTR(-EINVAL);
index 478e00cf2d9e51b41af0ace4ea496c2ff31f0a79..e844887732fbd062481cc60a3a34a13dd7c25468 100644 (file)
@@ -314,7 +314,7 @@ struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode)
        if (error)
                return ERR_PTR(error);
 
-       inode = path.dentry->d_inode;
+       inode = d_backing_inode(path.dentry);
        mod = inode->i_mode;
        ubi_num = ubi_major2num(imajor(inode));
        vol_id = iminor(inode) - 1;
index 78dde56ae6e6fa9dd7d04e64ae1969023d285238..d5fe5d5f490f3efa70e022fdac9b64bd89311e22 100644 (file)
@@ -82,6 +82,8 @@
 #include <net/bond_3ad.h>
 #include <net/bond_alb.h>
 
+#include "bonding_priv.h"
+
 /*---------------------------- Module parameters ----------------------------*/
 
 /* monitor all links that often (in milliseconds). <=0 disables monitoring */
@@ -4542,6 +4544,8 @@ unsigned int bond_get_num_tx_queues(void)
 int bond_create(struct net *net, const char *name)
 {
        struct net_device *bond_dev;
+       struct bonding *bond;
+       struct alb_bond_info *bond_info;
        int res;
 
        rtnl_lock();
@@ -4555,6 +4559,14 @@ int bond_create(struct net *net, const char *name)
                return -ENOMEM;
        }
 
+       /*
+        * Initialize rx_hashtbl_used_head to RLB_NULL_INDEX.
+        * It is set to 0 by default which is wrong.
+        */
+       bond = netdev_priv(bond_dev);
+       bond_info = &(BOND_ALB_INFO(bond));
+       bond_info->rx_hashtbl_used_head = RLB_NULL_INDEX;
+
        dev_net_set(bond_dev, net);
        bond_dev->rtnl_link_ops = &bond_link_ops;
 
index 62694cfc05b6548aff5c4f7186021f8c2a4ee570..b20b35acb47d3465063cdde30a1018321b344b56 100644 (file)
@@ -4,6 +4,7 @@
 #include <net/netns/generic.h>
 #include <net/bonding.h>
 
+#include "bonding_priv.h"
 
 static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos)
        __acquires(RCU)
diff --git a/drivers/net/bonding/bonding_priv.h b/drivers/net/bonding/bonding_priv.h
new file mode 100644 (file)
index 0000000..5a4d81a
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Bond several ethernet interfaces into a Cisco, running 'Etherchannel'.
+ *
+ * Portions are (c) Copyright 1995 Simon "Guru Aleph-Null" Janes
+ * NCM: Network and Communications Management, Inc.
+ *
+ * BUT, I'm the one who modified it for ethernet, so:
+ * (c) Copyright 1999, Thomas Davis, tadavis@lbl.gov
+ *
+ *     This software may be used and distributed according to the terms
+ *     of the GNU Public License, incorporated herein by reference.
+ *
+ */
+
+#ifndef _BONDING_PRIV_H
+#define _BONDING_PRIV_H
+
+#define DRV_VERSION    "3.7.1"
+#define DRV_RELDATE    "April 27, 2011"
+#define DRV_NAME       "bonding"
+#define DRV_DESCRIPTION        "Ethernet Channel Bonding Driver"
+
+#define bond_version DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n"
+
+#endif
index 58808f6514520c869631b356d6476f8cbc060a14..e8c96b8e86f48e66e68b2cd5285c0766865f067e 100644 (file)
@@ -112,7 +112,7 @@ config PCH_CAN
 
 config CAN_GRCAN
        tristate "Aeroflex Gaisler GRCAN and GRHCAN CAN devices"
-       depends on OF
+       depends on OF && HAS_DMA
        ---help---
          Say Y here if you want to use Aeroflex Gaisler GRCAN or GRHCAN.
          Note that the driver supports little endian, even though little
index 4643914859b2c7894f7556cfe023e1903eeb9cc6..8b17a9065b0b193a0c5e5a93048c637f0f7fbad3 100644 (file)
@@ -1102,7 +1102,7 @@ static void kvaser_usb_rx_can_err(const struct kvaser_usb_net_priv *priv,
 
        if (msg->u.rx_can_header.flag & (MSG_FLAG_ERROR_FRAME |
                                         MSG_FLAG_NERR)) {
-               netdev_err(priv->netdev, "Unknow error (flags: 0x%02x)\n",
+               netdev_err(priv->netdev, "Unknown error (flags: 0x%02x)\n",
                           msg->u.rx_can_header.flag);
 
                stats->rx_errors++;
index 9f0c2b9d58aed868968045ebdb24603e8b81e01e..af639ab4c55b64fd886df0413d090afd2fe618ba 100644 (file)
@@ -1251,8 +1251,7 @@ int mv88e6xxx_setup_port_common(struct dsa_switch *ds, int port)
        /* Port Control 1: disable trunking, disable sending
         * learning messages to this port.
         */
-       ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_DEFAULT_VLAN,
-                                  0x0000);
+       ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_CONTROL_1, 0x0000);
        if (ret)
                goto abort;
 
@@ -1275,7 +1274,8 @@ int mv88e6xxx_setup_port_common(struct dsa_switch *ds, int port)
        /* Default VLAN ID and priority: don't set a default VLAN
         * ID, and set the default packet priority to zero.
         */
-       ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), 0x07, 0x0000);
+       ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_DEFAULT_VLAN,
+                                  0x0000);
 abort:
        mutex_unlock(&ps->smi_mutex);
        return ret;
index b36ee9e0d220c0f03e0b62e5fc3a6d9014411fab..d686b9cac29f0b4ac2805455b6ba8f1f99017a74 100644 (file)
@@ -523,7 +523,7 @@ static int etherh_addr(char *addr, struct expansion_card *ec)
        char *s;
        
        if (!ecard_readchunk(&cd, ec, 0xf5, 0)) {
-               printk(KERN_ERR "%s: unable to read podule description string\n",
+               printk(KERN_ERR "%s: unable to read module description string\n",
                       dev_name(&ec->dev));
                goto no_addr;
        }
index e335626e1b6b5288c4f3d4cc8f45d79dcd56655d..89cd11d866420475ae9fd9bc2fa295afa08d4a36 100644 (file)
@@ -58,21 +58,17 @@ struct msgdma_extended_desc {
 /* Tx buffer control flags
  */
 #define MSGDMA_DESC_CTL_TX_FIRST       (MSGDMA_DESC_CTL_GEN_SOP |      \
-                                        MSGDMA_DESC_CTL_TR_ERR_IRQ |   \
                                         MSGDMA_DESC_CTL_GO)
 
-#define MSGDMA_DESC_CTL_TX_MIDDLE      (MSGDMA_DESC_CTL_TR_ERR_IRQ |   \
-                                        MSGDMA_DESC_CTL_GO)
+#define MSGDMA_DESC_CTL_TX_MIDDLE      (MSGDMA_DESC_CTL_GO)
 
 #define MSGDMA_DESC_CTL_TX_LAST                (MSGDMA_DESC_CTL_GEN_EOP |      \
                                         MSGDMA_DESC_CTL_TR_COMP_IRQ |  \
-                                        MSGDMA_DESC_CTL_TR_ERR_IRQ |   \
                                         MSGDMA_DESC_CTL_GO)
 
 #define MSGDMA_DESC_CTL_TX_SINGLE      (MSGDMA_DESC_CTL_GEN_SOP |      \
                                         MSGDMA_DESC_CTL_GEN_EOP |      \
                                         MSGDMA_DESC_CTL_TR_COMP_IRQ |  \
-                                        MSGDMA_DESC_CTL_TR_ERR_IRQ |   \
                                         MSGDMA_DESC_CTL_GO)
 
 #define MSGDMA_DESC_CTL_RX_SINGLE      (MSGDMA_DESC_CTL_END_ON_EOP |   \
index 90a76306ad0fafd441376fb524f1e00e1d202163..da48e66377b5ff42dc497a5ac4685ca1e16a1eb9 100644 (file)
@@ -391,6 +391,12 @@ static int tse_rx(struct altera_tse_private *priv, int limit)
                                   "RCV pktstatus %08X pktlength %08X\n",
                                   pktstatus, pktlength);
 
+               /* DMA trasfer from TSE starts with 2 aditional bytes for
+                * IP payload alignment. Status returned by get_rx_status()
+                * contains DMA transfer length. Packet is 2 bytes shorter.
+                */
+               pktlength -= 2;
+
                count++;
                next_entry = (++priv->rx_cons) % priv->rx_ring_size;
 
@@ -777,6 +783,8 @@ static int init_phy(struct net_device *dev)
        struct altera_tse_private *priv = netdev_priv(dev);
        struct phy_device *phydev;
        struct device_node *phynode;
+       bool fixed_link = false;
+       int rc = 0;
 
        /* Avoid init phy in case of no phy present */
        if (!priv->phy_iface)
@@ -789,13 +797,32 @@ static int init_phy(struct net_device *dev)
        phynode = of_parse_phandle(priv->device->of_node, "phy-handle", 0);
 
        if (!phynode) {
-               netdev_dbg(dev, "no phy-handle found\n");
-               if (!priv->mdio) {
-                       netdev_err(dev,
-                                  "No phy-handle nor local mdio specified\n");
-                       return -ENODEV;
+               /* check if a fixed-link is defined in device-tree */
+               if (of_phy_is_fixed_link(priv->device->of_node)) {
+                       rc = of_phy_register_fixed_link(priv->device->of_node);
+                       if (rc < 0) {
+                               netdev_err(dev, "cannot register fixed PHY\n");
+                               return rc;
+                       }
+
+                       /* In the case of a fixed PHY, the DT node associated
+                        * to the PHY is the Ethernet MAC DT node.
+                        */
+                       phynode = of_node_get(priv->device->of_node);
+                       fixed_link = true;
+
+                       netdev_dbg(dev, "fixed-link detected\n");
+                       phydev = of_phy_connect(dev, phynode,
+                                               &altera_tse_adjust_link,
+                                               0, priv->phy_iface);
+               } else {
+                       netdev_dbg(dev, "no phy-handle found\n");
+                       if (!priv->mdio) {
+                               netdev_err(dev, "No phy-handle nor local mdio specified\n");
+                               return -ENODEV;
+                       }
+                       phydev = connect_local_phy(dev);
                }
-               phydev = connect_local_phy(dev);
        } else {
                netdev_dbg(dev, "phy-handle found\n");
                phydev = of_phy_connect(dev, phynode,
@@ -819,10 +846,10 @@ static int init_phy(struct net_device *dev)
        /* Broken HW is sometimes missing the pull-up resistor on the
         * MDIO line, which results in reads to non-existent devices returning
         * 0 rather than 0xffff. Catch this here and treat 0 as a non-existent
-        * device as well.
+        * device as well. If a fixed-link is used the phy_id is always 0.
         * Note: phydev->phy_id is the result of reading the UID PHY registers.
         */
-       if (phydev->phy_id == 0) {
+       if ((phydev->phy_id == 0) && !fixed_link) {
                netdev_err(dev, "Bad PHY UID 0x%08x\n", phydev->phy_id);
                phy_disconnect(phydev);
                return -ENODEV;
index c638c85f3954bc685db3ccd9ac338d1375b8de02..089c269637b725da7876db7e4988baa77b5ec171 100644 (file)
@@ -179,7 +179,7 @@ config SUNLANCE
 
 config AMD_XGBE
        tristate "AMD 10GbE Ethernet driver"
-       depends on (OF_NET || ACPI) && HAS_IOMEM
+       depends on (OF_NET || ACPI) && HAS_IOMEM && HAS_DMA
        select PHYLIB
        select AMD_XGBE_PHY
        select BITREVERSE
index 8e262e2b39b63fc5b1e26cca09c66c08b76169c9..dea29ee24da4a28ce1effc2a9c72a77b516021cc 100644 (file)
@@ -25,8 +25,7 @@ config ARC_EMAC_CORE
 config ARC_EMAC
        tristate "ARC EMAC support"
        select ARC_EMAC_CORE
-       depends on OF_IRQ
-       depends on OF_NET
+       depends on OF_IRQ && OF_NET && HAS_DMA
        ---help---
          On some legacy ARC (Synopsys) FPGA boards such as ARCAngel4/ML50x
          non-standard on-chip ethernet device ARC EMAC 10/100 is used.
@@ -35,7 +34,7 @@ config ARC_EMAC
 config EMAC_ROCKCHIP
        tristate "Rockchip EMAC support"
        select ARC_EMAC_CORE
-       depends on OF_IRQ && OF_NET && REGULATOR
+       depends on OF_IRQ && OF_NET && REGULATOR && HAS_DMA
        ---help---
          Support for Rockchip RK3066/RK3188 EMAC ethernet controllers.
          This selects Rockchip SoC glue layer support for the
index 74df16aef7933871fb87c29a511ddc5b19182a01..88a6271de5bc96fde0993f6d9096a7904aa78c7b 100644 (file)
@@ -129,7 +129,7 @@ s32 atl1e_restart_autoneg(struct atl1e_hw *hw);
 #define     TWSI_CTRL_LD_SLV_ADDR_SHIFT     8
 #define     TWSI_CTRL_SW_LDSTART            0x800
 #define     TWSI_CTRL_HW_LDSTART            0x1000
-#define     TWSI_CTRL_SMB_SLV_ADDR_MASK     0x0x7F
+#define     TWSI_CTRL_SMB_SLV_ADDR_MASK     0x7F
 #define     TWSI_CTRL_SMB_SLV_ADDR_SHIFT    15
 #define     TWSI_CTRL_LD_EXIST              0x400000
 #define     TWSI_CTRL_READ_FREQ_SEL_MASK    0x3
index 7e3d87a88c76a81e2c36b65559d8b2b0bcf34217..e2c043eabbf39d165644312aba5bbecb4f07fcf8 100644 (file)
@@ -543,7 +543,7 @@ struct bcm_sysport_tx_counters {
        u32     jbr;            /* RO # of xmited jabber count*/
        u32     bytes;          /* RO # of xmited byte count */
        u32     pok;            /* RO # of xmited good pkt */
-       u32     uc;             /* RO (0x0x4f0)# of xmited unitcast pkt */
+       u32     uc;             /* RO (0x4f0) # of xmited unicast pkt */
 };
 
 struct bcm_sysport_mib {
index de77d3a74abc82f0c8b77dff3200799e70634674..21e3c38c7c752dd75674a62aeb8211bc78477808 100644 (file)
@@ -1260,7 +1260,7 @@ static int bgmac_poll(struct napi_struct *napi, int weight)
 
        /* Poll again if more events arrived in the meantime */
        if (bgmac_read(bgmac, BGMAC_INT_STATUS) & (BGMAC_IS_TX0 | BGMAC_IS_RX))
-               return handled;
+               return weight;
 
        if (handled < weight) {
                napi_complete(napi);
index 355d5fea5be9c3847597371fe86092956929bf02..a3b0f7a0c61e0d6ffeefcd88ae81ab751554e085 100644 (file)
@@ -521,6 +521,7 @@ struct bnx2x_fp_txdata {
 };
 
 enum bnx2x_tpa_mode_t {
+       TPA_MODE_DISABLED,
        TPA_MODE_LRO,
        TPA_MODE_GRO
 };
@@ -589,7 +590,6 @@ struct bnx2x_fastpath {
 
        /* TPA related */
        struct bnx2x_agg_info   *tpa_info;
-       u8                      disable_tpa;
 #ifdef BNX2X_STOP_ON_ERROR
        u64                     tpa_queue_used;
 #endif
@@ -1545,9 +1545,7 @@ struct bnx2x {
 #define USING_MSIX_FLAG                        (1 << 5)
 #define USING_MSI_FLAG                 (1 << 6)
 #define DISABLE_MSI_FLAG               (1 << 7)
-#define TPA_ENABLE_FLAG                        (1 << 8)
 #define NO_MCP_FLAG                    (1 << 9)
-#define GRO_ENABLE_FLAG                        (1 << 10)
 #define MF_FUNC_DIS                    (1 << 11)
 #define OWN_CNIC_IRQ                   (1 << 12)
 #define NO_ISCSI_OOO_FLAG              (1 << 13)
index 2f63467bce465ff9e8a5f50bf04be86b5150d77d..a8bb8f664d3d7f9a031158d5cac82820fbed7d6d 100644 (file)
@@ -947,10 +947,10 @@ static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
                        u16 frag_size, pages;
 #ifdef BNX2X_STOP_ON_ERROR
                        /* sanity check */
-                       if (fp->disable_tpa &&
+                       if (fp->mode == TPA_MODE_DISABLED &&
                            (CQE_TYPE_START(cqe_fp_type) ||
                             CQE_TYPE_STOP(cqe_fp_type)))
-                               BNX2X_ERR("START/STOP packet while disable_tpa type %x\n",
+                               BNX2X_ERR("START/STOP packet while TPA disabled, type %x\n",
                                          CQE_TYPE(cqe_fp_type));
 #endif
 
@@ -1396,7 +1396,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
                DP(NETIF_MSG_IFUP,
                   "mtu %d  rx_buf_size %d\n", bp->dev->mtu, fp->rx_buf_size);
 
-               if (!fp->disable_tpa) {
+               if (fp->mode != TPA_MODE_DISABLED) {
                        /* Fill the per-aggregation pool */
                        for (i = 0; i < MAX_AGG_QS(bp); i++) {
                                struct bnx2x_agg_info *tpa_info =
@@ -1410,7 +1410,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
                                        BNX2X_ERR("Failed to allocate TPA skb pool for queue[%d] - disabling TPA on this queue!\n",
                                                  j);
                                        bnx2x_free_tpa_pool(bp, fp, i);
-                                       fp->disable_tpa = 1;
+                                       fp->mode = TPA_MODE_DISABLED;
                                        break;
                                }
                                dma_unmap_addr_set(first_buf, mapping, 0);
@@ -1438,7 +1438,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
                                                                ring_prod);
                                        bnx2x_free_tpa_pool(bp, fp,
                                                            MAX_AGG_QS(bp));
-                                       fp->disable_tpa = 1;
+                                       fp->mode = TPA_MODE_DISABLED;
                                        ring_prod = 0;
                                        break;
                                }
@@ -1560,7 +1560,7 @@ static void bnx2x_free_rx_skbs(struct bnx2x *bp)
 
                bnx2x_free_rx_bds(fp);
 
-               if (!fp->disable_tpa)
+               if (fp->mode != TPA_MODE_DISABLED)
                        bnx2x_free_tpa_pool(bp, fp, MAX_AGG_QS(bp));
        }
 }
@@ -2477,17 +2477,19 @@ static void bnx2x_bz_fp(struct bnx2x *bp, int index)
        /* set the tpa flag for each queue. The tpa flag determines the queue
         * minimal size so it must be set prior to queue memory allocation
         */
-       fp->disable_tpa = !(bp->flags & TPA_ENABLE_FLAG ||
-                                 (bp->flags & GRO_ENABLE_FLAG &&
-                                  bnx2x_mtu_allows_gro(bp->dev->mtu)));
-       if (bp->flags & TPA_ENABLE_FLAG)
+       if (bp->dev->features & NETIF_F_LRO)
                fp->mode = TPA_MODE_LRO;
-       else if (bp->flags & GRO_ENABLE_FLAG)
+       else if (bp->dev->features & NETIF_F_GRO &&
+                bnx2x_mtu_allows_gro(bp->dev->mtu))
                fp->mode = TPA_MODE_GRO;
+       else
+               fp->mode = TPA_MODE_DISABLED;
 
-       /* We don't want TPA on an FCoE L2 ring */
-       if (IS_FCOE_FP(fp))
-               fp->disable_tpa = 1;
+       /* We don't want TPA if it's disabled in bp
+        * or if this is an FCoE L2 ring.
+        */
+       if (bp->disable_tpa || IS_FCOE_FP(fp))
+               fp->mode = TPA_MODE_DISABLED;
 }
 
 int bnx2x_load_cnic(struct bnx2x *bp)
@@ -2608,7 +2610,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
        /*
         * Zero fastpath structures preserving invariants like napi, which are
         * allocated only once, fp index, max_cos, bp pointer.
-        * Also set fp->disable_tpa and txdata_ptr.
+        * Also set fp->mode and txdata_ptr.
         */
        DP(NETIF_MSG_IFUP, "num queues: %d", bp->num_queues);
        for_each_queue(bp, i)
@@ -3247,7 +3249,7 @@ int bnx2x_low_latency_recv(struct napi_struct *napi)
 
        if ((bp->state == BNX2X_STATE_CLOSED) ||
            (bp->state == BNX2X_STATE_ERROR) ||
-           (bp->flags & (TPA_ENABLE_FLAG | GRO_ENABLE_FLAG)))
+           (bp->dev->features & (NETIF_F_LRO | NETIF_F_GRO)))
                return LL_FLUSH_FAILED;
 
        if (!bnx2x_fp_lock_poll(fp))
@@ -4543,7 +4545,7 @@ alloc_mem_err:
         * In these cases we disable the queue
         * Min size is different for OOO, TPA and non-TPA queues
         */
-       if (ring_size < (fp->disable_tpa ?
+       if (ring_size < (fp->mode == TPA_MODE_DISABLED ?
                                MIN_RX_SIZE_NONTPA : MIN_RX_SIZE_TPA)) {
                        /* release memory allocated for this queue */
                        bnx2x_free_fp_mem_at(bp, index);
@@ -4809,66 +4811,71 @@ netdev_features_t bnx2x_fix_features(struct net_device *dev,
 {
        struct bnx2x *bp = netdev_priv(dev);
 
+       if (pci_num_vf(bp->pdev)) {
+               netdev_features_t changed = dev->features ^ features;
+
+               /* Revert the requested changes in features if they
+                * would require internal reload of PF in bnx2x_set_features().
+                */
+               if (!(features & NETIF_F_RXCSUM) && !bp->disable_tpa) {
+                       features &= ~NETIF_F_RXCSUM;
+                       features |= dev->features & NETIF_F_RXCSUM;
+               }
+
+               if (changed & NETIF_F_LOOPBACK) {
+                       features &= ~NETIF_F_LOOPBACK;
+                       features |= dev->features & NETIF_F_LOOPBACK;
+               }
+       }
+
        /* TPA requires Rx CSUM offloading */
        if (!(features & NETIF_F_RXCSUM)) {
                features &= ~NETIF_F_LRO;
                features &= ~NETIF_F_GRO;
        }
 
-       /* Note: do not disable SW GRO in kernel when HW GRO is off */
-       if (bp->disable_tpa)
-               features &= ~NETIF_F_LRO;
-
        return features;
 }
 
 int bnx2x_set_features(struct net_device *dev, netdev_features_t features)
 {
        struct bnx2x *bp = netdev_priv(dev);
-       u32 flags = bp->flags;
-       u32 changes;
+       netdev_features_t changes = features ^ dev->features;
        bool bnx2x_reload = false;
+       int rc;
 
-       if (features & NETIF_F_LRO)
-               flags |= TPA_ENABLE_FLAG;
-       else
-               flags &= ~TPA_ENABLE_FLAG;
-
-       if (features & NETIF_F_GRO)
-               flags |= GRO_ENABLE_FLAG;
-       else
-               flags &= ~GRO_ENABLE_FLAG;
-
-       if (features & NETIF_F_LOOPBACK) {
-               if (bp->link_params.loopback_mode != LOOPBACK_BMAC) {
-                       bp->link_params.loopback_mode = LOOPBACK_BMAC;
-                       bnx2x_reload = true;
-               }
-       } else {
-               if (bp->link_params.loopback_mode != LOOPBACK_NONE) {
-                       bp->link_params.loopback_mode = LOOPBACK_NONE;
-                       bnx2x_reload = true;
+       /* VFs or non SRIOV PFs should be able to change loopback feature */
+       if (!pci_num_vf(bp->pdev)) {
+               if (features & NETIF_F_LOOPBACK) {
+                       if (bp->link_params.loopback_mode != LOOPBACK_BMAC) {
+                               bp->link_params.loopback_mode = LOOPBACK_BMAC;
+                               bnx2x_reload = true;
+                       }
+               } else {
+                       if (bp->link_params.loopback_mode != LOOPBACK_NONE) {
+                               bp->link_params.loopback_mode = LOOPBACK_NONE;
+                               bnx2x_reload = true;
+                       }
                }
        }
 
-       changes = flags ^ bp->flags;
-
        /* if GRO is changed while LRO is enabled, don't force a reload */
-       if ((changes & GRO_ENABLE_FLAG) && (flags & TPA_ENABLE_FLAG))
-               changes &= ~GRO_ENABLE_FLAG;
+       if ((changes & NETIF_F_GRO) && (features & NETIF_F_LRO))
+               changes &= ~NETIF_F_GRO;
 
        /* if GRO is changed while HW TPA is off, don't force a reload */
-       if ((changes & GRO_ENABLE_FLAG) && bp->disable_tpa)
-               changes &= ~GRO_ENABLE_FLAG;
+       if ((changes & NETIF_F_GRO) && bp->disable_tpa)
+               changes &= ~NETIF_F_GRO;
 
        if (changes)
                bnx2x_reload = true;
 
-       bp->flags = flags;
-
        if (bnx2x_reload) {
-               if (bp->recovery_state == BNX2X_RECOVERY_DONE)
-                       return bnx2x_reload_if_running(dev);
+               if (bp->recovery_state == BNX2X_RECOVERY_DONE) {
+                       dev->features = features;
+                       rc = bnx2x_reload_if_running(dev);
+                       return rc ? rc : 1;
+               }
                /* else: bnx2x_nic_load() will be called at end of recovery */
        }
 
@@ -4931,6 +4938,11 @@ int bnx2x_resume(struct pci_dev *pdev)
        }
        bp = netdev_priv(dev);
 
+       if (pci_num_vf(bp->pdev)) {
+               DP(BNX2X_MSG_IOV, "VFs are enabled, can not change MTU\n");
+               return -EPERM;
+       }
+
        if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
                BNX2X_ERR("Handling parity error recovery. Try again later\n");
                return -EAGAIN;
index adcacda7af7b10e70b053821acc1e2dfe722732a..d7a71758e87615de36fe06664a914291bdb3cfa3 100644 (file)
@@ -969,7 +969,7 @@ static inline void bnx2x_free_rx_sge_range(struct bnx2x *bp,
 {
        int i;
 
-       if (fp->disable_tpa)
+       if (fp->mode == TPA_MODE_DISABLED)
                return;
 
        for (i = 0; i < last; i++)
index e3d853cab7c9644c241cd42ba1a2844b82e55176..48ed005ba73fd3a9d9aa550871b647fdd0b59350 100644 (file)
@@ -1843,6 +1843,12 @@ static int bnx2x_set_ringparam(struct net_device *dev,
           "set ring params command parameters: rx_pending = %d, tx_pending = %d\n",
           ering->rx_pending, ering->tx_pending);
 
+       if (pci_num_vf(bp->pdev)) {
+               DP(BNX2X_MSG_IOV,
+                  "VFs are enabled, can not change ring parameters\n");
+               return -EPERM;
+       }
+
        if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
                DP(BNX2X_MSG_ETHTOOL,
                   "Handling parity error recovery. Try again later\n");
@@ -2899,6 +2905,12 @@ static void bnx2x_self_test(struct net_device *dev,
        u8 is_serdes, link_up;
        int rc, cnt = 0;
 
+       if (pci_num_vf(bp->pdev)) {
+               DP(BNX2X_MSG_IOV,
+                  "VFs are enabled, can not perform self test\n");
+               return;
+       }
+
        if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
                netdev_err(bp->dev,
                           "Handling parity error recovery. Try again later\n");
@@ -3468,6 +3480,11 @@ static int bnx2x_set_channels(struct net_device *dev,
           channels->rx_count, channels->tx_count, channels->other_count,
           channels->combined_count);
 
+       if (pci_num_vf(bp->pdev)) {
+               DP(BNX2X_MSG_IOV, "VFs are enabled, can not set channels\n");
+               return -EPERM;
+       }
+
        /* We don't support separate rx / tx channels.
         * We don't allow setting 'other' channels.
         */
index b9f85fccb419be528ae328efc3af4303f0498103..556dcc162a6252a36fe550110b4abbb3d1bbcf60 100644 (file)
@@ -3128,7 +3128,7 @@ static unsigned long bnx2x_get_q_flags(struct bnx2x *bp,
                __set_bit(BNX2X_Q_FLG_FORCE_DEFAULT_PRI, &flags);
        }
 
-       if (!fp->disable_tpa) {
+       if (fp->mode != TPA_MODE_DISABLED) {
                __set_bit(BNX2X_Q_FLG_TPA, &flags);
                __set_bit(BNX2X_Q_FLG_TPA_IPV6, &flags);
                if (fp->mode == TPA_MODE_GRO)
@@ -3176,7 +3176,7 @@ static void bnx2x_pf_rx_q_prep(struct bnx2x *bp,
        u16 sge_sz = 0;
        u16 tpa_agg_size = 0;
 
-       if (!fp->disable_tpa) {
+       if (fp->mode != TPA_MODE_DISABLED) {
                pause->sge_th_lo = SGE_TH_LO(bp);
                pause->sge_th_hi = SGE_TH_HI(bp);
 
@@ -3304,7 +3304,7 @@ static void bnx2x_pf_init(struct bnx2x *bp)
        /* This flag is relevant for E1x only.
         * E2 doesn't have a TPA configuration in a function level.
         */
-       flags |= (bp->flags & TPA_ENABLE_FLAG) ? FUNC_FLG_TPA : 0;
+       flags |= (bp->dev->features & NETIF_F_LRO) ? FUNC_FLG_TPA : 0;
 
        func_init.func_flgs = flags;
        func_init.pf_id = BP_FUNC(bp);
@@ -12107,11 +12107,8 @@ static int bnx2x_init_bp(struct bnx2x *bp)
 
        /* Set TPA flags */
        if (bp->disable_tpa) {
-               bp->flags &= ~(TPA_ENABLE_FLAG | GRO_ENABLE_FLAG);
+               bp->dev->hw_features &= ~NETIF_F_LRO;
                bp->dev->features &= ~NETIF_F_LRO;
-       } else {
-               bp->flags |= (TPA_ENABLE_FLAG | GRO_ENABLE_FLAG);
-               bp->dev->features |= NETIF_F_LRO;
        }
 
        if (CHIP_IS_E1(bp))
@@ -13371,6 +13368,12 @@ static int bnx2x_init_one(struct pci_dev *pdev,
        bool is_vf;
        int cnic_cnt;
 
+       /* Management FW 'remembers' living interfaces. Allow it some time
+        * to forget previously living interfaces, allowing a proper re-load.
+        */
+       if (is_kdump_kernel())
+               msleep(5000);
+
        /* An estimated maximum supported CoS number according to the chip
         * version.
         * We will try to roughly estimate the maximum number of CoSes this chip
index 15b2d164756058c6c5fb154bdc128f52aa3148c3..06b8c0d8fd3b12ab4e864c8c0971cc52380c007c 100644 (file)
@@ -594,7 +594,7 @@ int bnx2x_vfpf_setup_q(struct bnx2x *bp, struct bnx2x_fastpath *fp,
        bnx2x_vfpf_prep(bp, &req->first_tlv, CHANNEL_TLV_SETUP_Q, sizeof(*req));
 
        /* select tpa mode to request */
-       if (!fp->disable_tpa) {
+       if (fp->mode != TPA_MODE_DISABLED) {
                flags |= VFPF_QUEUE_FLG_TPA;
                flags |= VFPF_QUEUE_FLG_TPA_IPV6;
                if (fp->mode == TPA_MODE_GRO)
index 1270b189a9a2ffd7776985f8e0a96fada80f8de8..069952fa5d644b62b7d1a04fdb8b615a4ed3d69a 100644 (file)
@@ -18129,7 +18129,9 @@ static pci_ers_result_t tg3_io_error_detected(struct pci_dev *pdev,
 
        rtnl_lock();
 
-       tp->pcierr_recovery = true;
+       /* We needn't recover from permanent error */
+       if (state == pci_channel_io_frozen)
+               tp->pcierr_recovery = true;
 
        /* We probably don't have netdev yet */
        if (!netdev || !netif_running(netdev))
index 9f5387249f242374437581e6c2df7c037917f83a..4104d49f005d4a825eb14b99efeb5f158ab456d5 100644 (file)
@@ -707,6 +707,9 @@ static void gem_rx_refill(struct macb *bp)
 
                        /* properly align Ethernet header */
                        skb_reserve(skb, NET_IP_ALIGN);
+               } else {
+                       bp->rx_ring[entry].addr &= ~MACB_BIT(RX_USED);
+                       bp->rx_ring[entry].ctrl = 0;
                }
        }
 
@@ -1473,9 +1476,9 @@ static void macb_init_rings(struct macb *bp)
        for (i = 0; i < TX_RING_SIZE; i++) {
                bp->queues[0].tx_ring[i].addr = 0;
                bp->queues[0].tx_ring[i].ctrl = MACB_BIT(TX_USED);
-               bp->queues[0].tx_head = 0;
-               bp->queues[0].tx_tail = 0;
        }
+       bp->queues[0].tx_head = 0;
+       bp->queues[0].tx_tail = 0;
        bp->queues[0].tx_ring[TX_RING_SIZE - 1].ctrl |= MACB_BIT(TX_WRAP);
 
        bp->rx_tail = 0;
index f0285bcbe5981e1202071d536080d774566cb20e..371f75e782e5eb76fd22205d9aedfed30850aa19 100644 (file)
@@ -538,7 +538,7 @@ static ssize_t tp_la_write(struct file *file, const char __user *buf,
        char s[32];
        unsigned long val;
        size_t size = min(sizeof(s) - 1, count);
-       struct adapter *adap = FILE_DATA(file)->i_private;
+       struct adapter *adap = file_inode(file)->i_private;
 
        if (copy_from_user(s, buf, size))
                return -EFAULT;
@@ -647,7 +647,7 @@ static int pm_stats_open(struct inode *inode, struct file *file)
 static ssize_t pm_stats_clear(struct file *file, const char __user *buf,
                              size_t count, loff_t *pos)
 {
-       struct adapter *adap = FILE_DATA(file)->i_private;
+       struct adapter *adap = file_inode(file)->i_private;
 
        t4_write_reg(adap, PM_RX_STAT_CONFIG_A, 0);
        t4_write_reg(adap, PM_TX_STAT_CONFIG_A, 0);
@@ -1005,7 +1005,7 @@ static ssize_t mbox_write(struct file *file, const char __user *buf,
                   &data[7], &c) < 8 || c != '\n')
                return -EINVAL;
 
-       ino = FILE_DATA(file);
+       ino = file_inode(file);
        mbox = (uintptr_t)ino->i_private & 7;
        adap = ino->i_private - mbox;
        addr = adap->regs + PF_REG(mbox, CIM_PF_MAILBOX_DATA_A);
@@ -1034,7 +1034,7 @@ static ssize_t flash_read(struct file *file, char __user *buf, size_t count,
                          loff_t *ppos)
 {
        loff_t pos = *ppos;
-       loff_t avail = FILE_DATA(file)->i_size;
+       loff_t avail = file_inode(file)->i_size;
        struct adapter *adap = file->private_data;
 
        if (pos < 0)
@@ -1479,7 +1479,7 @@ static ssize_t rss_key_write(struct file *file, const char __user *buf,
        int i, j;
        u32 key[10];
        char s[100], *p;
-       struct adapter *adap = FILE_DATA(file)->i_private;
+       struct adapter *adap = file_inode(file)->i_private;
 
        if (count > sizeof(s) - 1)
                return -EINVAL;
@@ -1951,12 +1951,6 @@ static const struct file_operations mem_debugfs_fops = {
        .llseek  = default_llseek,
 };
 
-static void set_debugfs_file_size(struct dentry *de, loff_t size)
-{
-       if (!IS_ERR(de) && de->d_inode)
-               de->d_inode->i_size = size;
-}
-
 static void add_debugfs_mem(struct adapter *adap, const char *name,
                            unsigned int idx, unsigned int size_mb)
 {
@@ -2072,9 +2066,8 @@ int t4_setup_debugfs(struct adapter *adap)
                }
        }
 
-       de = debugfs_create_file("flash", S_IRUSR, adap->debugfs_root, adap,
-                                &flash_debugfs_fops);
-       set_debugfs_file_size(de, adap->params.sf_size);
+       de = debugfs_create_file_size("flash", S_IRUSR, adap->debugfs_root, adap,
+                                     &flash_debugfs_fops, adap->params.sf_size);
 
        return 0;
 }
index 8f418ba868bd4887f97a56f48c243dd93fd14b4f..23f43a0f8950d250577afcc45b22eb50288bc6a8 100644 (file)
@@ -37,8 +37,6 @@
 
 #include <linux/export.h>
 
-#define FILE_DATA(_file) ((_file)->f_path.dentry->d_inode)
-
 #define DEFINE_SIMPLE_DEBUGFS_FILE(name) \
 static int name##_open(struct inode *inode, struct file *file) \
 { \
index 5959e3ae72da213e11587e8cd27a2bc9759755d0..e8578a742f2a29b14a2eaec01216a8e47a68e12a 100644 (file)
@@ -492,7 +492,7 @@ int t4_memory_rw(struct adapter *adap, int win, int mtype, u32 addr,
                memoffset = (mtype * (edc_size * 1024 * 1024));
        else {
                mc_size = EXT_MEM0_SIZE_G(t4_read_reg(adap,
-                                                     MA_EXT_MEMORY1_BAR_A));
+                                                     MA_EXT_MEMORY0_BAR_A));
                memoffset = (MEM_MC0 * edc_size + mc_size) * 1024 * 1024;
        }
 
index fb0bc3c3620e9cf87983b1c425e0f24d431bffc9..a6dcbf850c1fd4e09462d40f5f0e7cc08cfb2088 100644 (file)
@@ -4846,7 +4846,8 @@ err:
 }
 
 static int be_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
-                                struct net_device *dev, u32 filter_mask)
+                                struct net_device *dev, u32 filter_mask,
+                                int nlflags)
 {
        struct be_adapter *adapter = netdev_priv(dev);
        int status = 0;
@@ -4868,7 +4869,7 @@ static int be_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
        return ndo_dflt_bridge_getlink(skb, pid, seq, dev,
                                       hsw_mode == PORT_FWD_TYPE_VEPA ?
                                       BRIDGE_MODE_VEPA : BRIDGE_MODE_VEB,
-                                      0, 0);
+                                      0, 0, nlflags);
 }
 
 #ifdef CONFIG_BE2NET_VXLAN
index f6a3a7abd468e1f25fd4c33e874a38f0c85bc4dd..66d47e448e4d175aeefecddacc53f8f858f0085b 100644 (file)
@@ -988,7 +988,10 @@ fec_restart(struct net_device *ndev)
                rcntl |= 0x40000000 | 0x00000020;
 
                /* RGMII, RMII or MII */
-               if (fep->phy_interface == PHY_INTERFACE_MODE_RGMII)
+               if (fep->phy_interface == PHY_INTERFACE_MODE_RGMII ||
+                   fep->phy_interface == PHY_INTERFACE_MODE_RGMII_ID ||
+                   fep->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID ||
+                   fep->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID)
                        rcntl |= (1 << 6);
                else if (fep->phy_interface == PHY_INTERFACE_MODE_RMII)
                        rcntl |= (1 << 8);
index 291c87036e173c792a1b26234e2b99e8cd67bf65..2a0dc127df3f4e099e273a77715ad87358385aff 100644 (file)
@@ -3347,7 +3347,7 @@ static int ehea_register_memory_hooks(void)
 {
        int ret = 0;
 
-       if (atomic_inc_and_test(&ehea_memory_hooks_registered))
+       if (atomic_inc_return(&ehea_memory_hooks_registered) > 1)
                return 0;
 
        ret = ehea_create_busmap();
@@ -3381,12 +3381,14 @@ out3:
 out2:
        unregister_reboot_notifier(&ehea_reboot_nb);
 out:
+       atomic_dec(&ehea_memory_hooks_registered);
        return ret;
 }
 
 static void ehea_unregister_memory_hooks(void)
 {
-       if (atomic_read(&ehea_memory_hooks_registered))
+       /* Only remove the hooks if we've registered them */
+       if (atomic_read(&ehea_memory_hooks_registered) == 0)
                return;
 
        unregister_reboot_notifier(&ehea_reboot_nb);
index cd7675ac5bf9ed8b8658996d2d27190c6b20245f..18134766a11409c6c976f00ac0431de748c03073 100644 (file)
@@ -1238,7 +1238,7 @@ static int ibmveth_change_mtu(struct net_device *dev, int new_mtu)
                return -EINVAL;
 
        for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++)
-               if (new_mtu_oh < adapter->rx_buff_pool[i].buff_size)
+               if (new_mtu_oh <= adapter->rx_buff_pool[i].buff_size)
                        break;
 
        if (i == IBMVETH_NUM_BUFF_POOLS)
@@ -1257,7 +1257,7 @@ static int ibmveth_change_mtu(struct net_device *dev, int new_mtu)
        for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) {
                adapter->rx_buff_pool[i].active = 1;
 
-               if (new_mtu_oh < adapter->rx_buff_pool[i].buff_size) {
+               if (new_mtu_oh <= adapter->rx_buff_pool[i].buff_size) {
                        dev->mtu = new_mtu;
                        vio_cmo_set_dev_desired(viodev,
                                                ibmveth_get_desired_dma
index 24481cd7e59ac94e3e4ec14528938338aeaf4000..a54c14491e3b6a4dbc168980dd44d399b6766487 100644 (file)
@@ -8053,10 +8053,10 @@ static int i40e_ndo_bridge_setlink(struct net_device *dev,
 #ifdef HAVE_BRIDGE_FILTER
 static int i40e_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
                                   struct net_device *dev,
-                                  u32 __always_unused filter_mask)
+                                  u32 __always_unused filter_mask, int nlflags)
 #else
 static int i40e_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
-                                  struct net_device *dev)
+                                  struct net_device *dev, int nlflags)
 #endif /* HAVE_BRIDGE_FILTER */
 {
        struct i40e_netdev_priv *np = netdev_priv(dev);
@@ -8078,7 +8078,8 @@ static int i40e_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
        if (!veb)
                return 0;
 
-       return ndo_dflt_bridge_getlink(skb, pid, seq, dev, veb->bridge_mode);
+       return ndo_dflt_bridge_getlink(skb, pid, seq, dev, veb->bridge_mode,
+                                      nlflags);
 }
 #endif /* HAVE_BRIDGE_ATTRIBS */
 
index d3f4b0ceb3f781216599408248b351cd4854bc92..5be12a00e1f447744f2497131cea1a70e313fd1f 100644 (file)
@@ -8044,7 +8044,7 @@ static int ixgbe_ndo_bridge_setlink(struct net_device *dev,
 
 static int ixgbe_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
                                    struct net_device *dev,
-                                   u32 filter_mask)
+                                   u32 filter_mask, int nlflags)
 {
        struct ixgbe_adapter *adapter = netdev_priv(dev);
 
@@ -8052,7 +8052,7 @@ static int ixgbe_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
                return 0;
 
        return ndo_dflt_bridge_getlink(skb, pid, seq, dev,
-                                      adapter->bridge_mode, 0, 0);
+                                      adapter->bridge_mode, 0, 0, nlflags);
 }
 
 static void *ixgbe_fwd_add(struct net_device *pdev, struct net_device *vdev)
index af829c57840039e54e853bd5c4230ab0c6f17699..7ace07dad6a31d4b18ab5aa1e5335c0727cff596 100644 (file)
@@ -1508,7 +1508,8 @@ static int pxa168_eth_probe(struct platform_device *pdev)
                np = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0);
                if (!np) {
                        dev_err(&pdev->dev, "missing phy-handle\n");
-                       return -EINVAL;
+                       err = -EINVAL;
+                       goto err_netdev;
                }
                of_property_read_u32(np, "reg", &pep->phy_addr);
                pep->phy_intf = of_get_phy_mode(pdev->dev.of_node);
@@ -1526,7 +1527,7 @@ static int pxa168_eth_probe(struct platform_device *pdev)
        pep->smi_bus = mdiobus_alloc();
        if (pep->smi_bus == NULL) {
                err = -ENOMEM;
-               goto err_base;
+               goto err_netdev;
        }
        pep->smi_bus->priv = pep;
        pep->smi_bus->name = "pxa168_eth smi";
@@ -1551,13 +1552,10 @@ err_mdiobus:
        mdiobus_unregister(pep->smi_bus);
 err_free_mdio:
        mdiobus_free(pep->smi_bus);
-err_base:
-       iounmap(pep->base);
 err_netdev:
        free_netdev(dev);
 err_clk:
-       clk_disable(clk);
-       clk_put(clk);
+       clk_disable_unprepare(clk);
        return err;
 }
 
@@ -1574,13 +1572,9 @@ static int pxa168_eth_remove(struct platform_device *pdev)
        if (pep->phy)
                phy_disconnect(pep->phy);
        if (pep->clk) {
-               clk_disable(pep->clk);
-               clk_put(pep->clk);
-               pep->clk = NULL;
+               clk_disable_unprepare(pep->clk);
        }
 
-       iounmap(pep->base);
-       pep->base = NULL;
        mdiobus_unregister(pep->smi_bus);
        mdiobus_free(pep->smi_bus);
        unregister_netdev(dev);
index f0fbb4ade85db9b3db5ce049eff76cd978d08353..4f7dc044601e2751ad625e4c011aa3a1c328e62f 100644 (file)
@@ -939,21 +939,34 @@ static int mlx4_MAD_IFC_wrapper(struct mlx4_dev *dev, int slave,
                                return err;
                        }
                        if (smp->attr_id == IB_SMP_ATTR_GUID_INFO) {
-                               /* compute slave's gid block */
-                               smp->attr_mod = cpu_to_be32(slave / 8);
-                               /* execute cmd */
-                               err = mlx4_cmd_box(dev, inbox->dma, outbox->dma,
-                                            vhcr->in_modifier, opcode_modifier,
-                                            vhcr->op, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE);
-                               if (!err) {
-                                       /* if needed, move slave gid to index 0 */
-                                       if (slave % 8)
-                                               memcpy(outsmp->data,
-                                                      outsmp->data + (slave % 8) * 8, 8);
-                                       /* delete all other gids */
-                                       memset(outsmp->data + 8, 0, 56);
+                               __be64 guid = mlx4_get_admin_guid(dev, slave,
+                                                                 port);
+
+                               /* set the PF admin guid to the FW/HW burned
+                                * GUID, if it wasn't yet set
+                                */
+                               if (slave == 0 && guid == 0) {
+                                       smp->attr_mod = 0;
+                                       err = mlx4_cmd_box(dev,
+                                                          inbox->dma,
+                                                          outbox->dma,
+                                                          vhcr->in_modifier,
+                                                          opcode_modifier,
+                                                          vhcr->op,
+                                                          MLX4_CMD_TIME_CLASS_C,
+                                                          MLX4_CMD_NATIVE);
+                                       if (err)
+                                               return err;
+                                       mlx4_set_admin_guid(dev,
+                                                           *(__be64 *)outsmp->
+                                                           data, slave, port);
+                               } else {
+                                       memcpy(outsmp->data, &guid, 8);
                                }
-                               return err;
+
+                               /* clean all other gids */
+                               memset(outsmp->data + 8, 0, 56);
+                               return 0;
                        }
                        if (smp->attr_id == IB_SMP_ATTR_NODE_INFO) {
                                err = mlx4_cmd_box(dev, inbox->dma, outbox->dma,
@@ -2350,6 +2363,7 @@ int mlx4_multi_func_init(struct mlx4_dev *dev)
                                oper_vport->qos_vport = MLX4_VPP_DEFAULT_VPORT;
                                vf_oper->vport[port].vlan_idx = NO_INDX;
                                vf_oper->vport[port].mac_idx = NO_INDX;
+                               mlx4_set_random_admin_guid(dev, i, port);
                        }
                        spin_lock_init(&s_state->lock);
                }
index 3f44e2bbb9824caad9068e7ce6f03e1a2df382f2..a2ddf3d75ff8ff8956763b924bc2fda8b156c222 100644 (file)
@@ -1102,20 +1102,21 @@ static int mlx4_en_check_rxfh_func(struct net_device *dev, u8 hfunc)
        struct mlx4_en_priv *priv = netdev_priv(dev);
 
        /* check if requested function is supported by the device */
-       if ((hfunc == ETH_RSS_HASH_TOP &&
-            !(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RSS_TOP)) ||
-           (hfunc == ETH_RSS_HASH_XOR &&
-            !(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RSS_XOR)))
-               return -EINVAL;
+       if (hfunc == ETH_RSS_HASH_TOP) {
+               if (!(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RSS_TOP))
+                       return -EINVAL;
+               if (!(dev->features & NETIF_F_RXHASH))
+                       en_warn(priv, "Toeplitz hash function should be used in conjunction with RX hashing for optimal performance\n");
+               return 0;
+       } else if (hfunc == ETH_RSS_HASH_XOR) {
+               if (!(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RSS_XOR))
+                       return -EINVAL;
+               if (dev->features & NETIF_F_RXHASH)
+                       en_warn(priv, "Enabling both XOR Hash function and RX Hashing can limit RPS functionality\n");
+               return 0;
+       }
 
-       priv->rss_hash_fn = hfunc;
-       if (hfunc == ETH_RSS_HASH_TOP && !(dev->features & NETIF_F_RXHASH))
-               en_warn(priv,
-                       "Toeplitz hash function should be used in conjunction with RX hashing for optimal performance\n");
-       if (hfunc == ETH_RSS_HASH_XOR && (dev->features & NETIF_F_RXHASH))
-               en_warn(priv,
-                       "Enabling both XOR Hash function and RX Hashing can limit RPS functionality\n");
-       return 0;
+       return -EINVAL;
 }
 
 static int mlx4_en_get_rxfh(struct net_device *dev, u32 *ring_index, u8 *key,
@@ -1189,6 +1190,8 @@ static int mlx4_en_set_rxfh(struct net_device *dev, const u32 *ring_index,
                priv->prof->rss_rings = rss_rings;
        if (key)
                memcpy(priv->rss_key, key, MLX4_EN_RSS_KEY_SIZE);
+       if (hfunc !=  ETH_RSS_HASH_NO_CHANGE)
+               priv->rss_hash_fn = hfunc;
 
        if (port_up) {
                err = mlx4_en_start_port(dev);
index 0f1afc085d580b34e0eda1eaa4b1cdc1737c71be..32f5ec7374723d1315f4234f77b12ffbe5adcfe0 100644 (file)
@@ -1467,6 +1467,7 @@ static void mlx4_en_service_task(struct work_struct *work)
                if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS)
                        mlx4_en_ptp_overflow_check(mdev);
 
+               mlx4_en_recover_from_oom(priv);
                queue_delayed_work(mdev->workqueue, &priv->service_task,
                                   SERVICE_TASK_DELAY);
        }
@@ -1721,7 +1722,7 @@ mac_err:
 cq_err:
        while (rx_index--) {
                mlx4_en_deactivate_cq(priv, priv->rx_cq[rx_index]);
-               mlx4_en_free_affinity_hint(priv, i);
+               mlx4_en_free_affinity_hint(priv, rx_index);
        }
        for (i = 0; i < priv->rx_ring_num; i++)
                mlx4_en_deactivate_rx_ring(priv, priv->rx_ring[i]);
index 4fdd3c37e47bf7c7862b9edf569be6f7f38e8dae..2a77a6b191216b19059c89fa8ad386252684806c 100644 (file)
@@ -244,6 +244,12 @@ static int mlx4_en_prepare_rx_desc(struct mlx4_en_priv *priv,
        return mlx4_en_alloc_frags(priv, rx_desc, frags, ring->page_alloc, gfp);
 }
 
+static inline bool mlx4_en_is_ring_empty(struct mlx4_en_rx_ring *ring)
+{
+       BUG_ON((u32)(ring->prod - ring->cons) > ring->actual_size);
+       return ring->prod == ring->cons;
+}
+
 static inline void mlx4_en_update_rx_prod_db(struct mlx4_en_rx_ring *ring)
 {
        *ring->wqres.db.db = cpu_to_be32(ring->prod & 0xffff);
@@ -315,8 +321,7 @@ static void mlx4_en_free_rx_buf(struct mlx4_en_priv *priv,
               ring->cons, ring->prod);
 
        /* Unmap and free Rx buffers */
-       BUG_ON((u32) (ring->prod - ring->cons) > ring->actual_size);
-       while (ring->cons != ring->prod) {
+       while (!mlx4_en_is_ring_empty(ring)) {
                index = ring->cons & ring->size_mask;
                en_dbg(DRV, priv, "Processing descriptor:%d\n", index);
                mlx4_en_free_rx_desc(priv, ring, index);
@@ -491,6 +496,23 @@ err_allocator:
        return err;
 }
 
+/* We recover from out of memory by scheduling our napi poll
+ * function (mlx4_en_process_cq), which tries to allocate
+ * all missing RX buffers (call to mlx4_en_refill_rx_buffers).
+ */
+void mlx4_en_recover_from_oom(struct mlx4_en_priv *priv)
+{
+       int ring;
+
+       if (!priv->port_up)
+               return;
+
+       for (ring = 0; ring < priv->rx_ring_num; ring++) {
+               if (mlx4_en_is_ring_empty(priv->rx_ring[ring]))
+                       napi_reschedule(&priv->rx_cq[ring]->napi);
+       }
+}
+
 void mlx4_en_destroy_rx_ring(struct mlx4_en_priv *priv,
                             struct mlx4_en_rx_ring **pring,
                             u32 size, u16 stride)
index 1783705273d89773c0a462cb28684f2969e55ac4..f7bf312fb44311b1c436c4eb3706341db92c1db0 100644 (file)
@@ -143,8 +143,10 @@ int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
        ring->hwtstamp_tx_type = priv->hwtstamp_config.tx_type;
        ring->queue_index = queue_index;
 
-       if (queue_index < priv->num_tx_rings_p_up && cpu_online(queue_index))
-               cpumask_set_cpu(queue_index, &ring->affinity_mask);
+       if (queue_index < priv->num_tx_rings_p_up)
+               cpumask_set_cpu_local_first(queue_index,
+                                           priv->mdev->dev->numa_node,
+                                           &ring->affinity_mask);
 
        *pring = ring;
        return 0;
@@ -213,7 +215,7 @@ int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv,
 
        err = mlx4_qp_to_ready(mdev->dev, &ring->wqres.mtt, &ring->context,
                               &ring->qp, &ring->qp_state);
-       if (!user_prio && cpu_online(ring->queue_index))
+       if (!cpumask_empty(&ring->affinity_mask))
                netif_set_xps_queue(priv->dev, &ring->affinity_mask,
                                    ring->queue_index);
 
index 190fd624bdfebd6e7b5b9e83f8470b840f8d09cb..2619c9fbf42dfb952473e4779a2ee8d6ebfd2c65 100644 (file)
@@ -702,6 +702,8 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
                                priv->mfunc.master.slave_state[flr_slave].is_slave_going_down = 1;
                        }
                        spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags);
+                       mlx4_dispatch_event(dev, MLX4_DEV_EVENT_SLAVE_SHUTDOWN,
+                                           flr_slave);
                        queue_work(priv->mfunc.master.comm_wq,
                                   &priv->mfunc.master.slave_flr_event_work);
                        break;
index b9881fc1252fab863cb184a633113ac7307a4467..e30bf57ad7a18ff559eb4bba122252eaf0308964 100644 (file)
@@ -56,11 +56,13 @@ MODULE_PARM_DESC(enable_qos, "Enable Enhanced QoS support (default: on)");
 #define MLX4_GET(dest, source, offset)                               \
        do {                                                          \
                void *__p = (char *) (source) + (offset);             \
+               u64 val;                                              \
                switch (sizeof (dest)) {                              \
                case 1: (dest) = *(u8 *) __p;       break;            \
                case 2: (dest) = be16_to_cpup(__p); break;            \
                case 4: (dest) = be32_to_cpup(__p); break;            \
-               case 8: (dest) = be64_to_cpup(__p); break;            \
+               case 8: val = get_unaligned((u64 *)__p);              \
+                       (dest) = be64_to_cpu(val);  break;            \
                default: __buggy_use_of_MLX4_GET();                   \
                }                                                     \
        } while (0)
@@ -781,10 +783,10 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
        MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET);
        dev_cap->num_ports = field & 0xf;
        MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MSG_SZ_OFFSET);
+       dev_cap->max_msg_sz = 1 << (field & 0x1f);
        MLX4_GET(field, outbox, QUERY_DEV_CAP_PORT_FLOWSTATS_COUNTERS_OFFSET);
        if (field & 0x10)
                dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_FLOWSTATS_EN;
-       dev_cap->max_msg_sz = 1 << (field & 0x1f);
        MLX4_GET(field, outbox, QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET);
        if (field & 0x80)
                dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_FS_EN;
@@ -1605,9 +1607,17 @@ static void get_board_id(void *vsd, char *board_id)
                 * swaps each 4-byte word before passing it back to
                 * us.  Therefore we need to swab it before printing.
                 */
-               for (i = 0; i < 4; ++i)
-                       ((u32 *) board_id)[i] =
-                               swab32(*(u32 *) (vsd + VSD_OFFSET_MLX_BOARD_ID + i * 4));
+               u32 *bid_u32 = (u32 *)board_id;
+
+               for (i = 0; i < 4; ++i) {
+                       u32 *addr;
+                       u32 val;
+
+                       addr = (u32 *) (vsd + VSD_OFFSET_MLX_BOARD_ID + i * 4);
+                       val = get_unaligned(addr);
+                       val = swab32(val);
+                       put_unaligned(val, &bid_u32[i]);
+               }
        }
 }
 
index acceb75e8c440c6aab8061cc1cdec7c0d420f4b1..ced5ecab5aa754ad44ae055464608bba66d6b137 100644 (file)
@@ -2260,6 +2260,37 @@ void mlx4_counter_free(struct mlx4_dev *dev, u32 idx)
 }
 EXPORT_SYMBOL_GPL(mlx4_counter_free);
 
+void mlx4_set_admin_guid(struct mlx4_dev *dev, __be64 guid, int entry, int port)
+{
+       struct mlx4_priv *priv = mlx4_priv(dev);
+
+       priv->mfunc.master.vf_admin[entry].vport[port].guid = guid;
+}
+EXPORT_SYMBOL_GPL(mlx4_set_admin_guid);
+
+__be64 mlx4_get_admin_guid(struct mlx4_dev *dev, int entry, int port)
+{
+       struct mlx4_priv *priv = mlx4_priv(dev);
+
+       return priv->mfunc.master.vf_admin[entry].vport[port].guid;
+}
+EXPORT_SYMBOL_GPL(mlx4_get_admin_guid);
+
+void mlx4_set_random_admin_guid(struct mlx4_dev *dev, int entry, int port)
+{
+       struct mlx4_priv *priv = mlx4_priv(dev);
+       __be64 guid;
+
+       /* hw GUID */
+       if (entry == 0)
+               return;
+
+       get_random_bytes((char *)&guid, sizeof(guid));
+       guid &= ~(cpu_to_be64(1ULL << 56));
+       guid |= cpu_to_be64(1ULL << 57);
+       priv->mfunc.master.vf_admin[entry].vport[port].guid = guid;
+}
+
 static int mlx4_setup_hca(struct mlx4_dev *dev)
 {
        struct mlx4_priv *priv = mlx4_priv(dev);
index f30eeb730a8667d44bead81f19c606d6770d2bb9..502d3dd2c888528e71af1cbf1ed276b10d058c81 100644 (file)
@@ -499,6 +499,7 @@ struct mlx4_vport_state {
        bool spoofchk;
        u32 link_state;
        u8 qos_vport;
+       __be64 guid;
 };
 
 struct mlx4_vf_admin_state {
index 9de30216b146bb09188a6867307b5bbcf7aa9dd0..d021f079f181b06bb6ec73250ea8493ad87d1cee 100644 (file)
@@ -774,6 +774,7 @@ int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv,
 void mlx4_en_deactivate_tx_ring(struct mlx4_en_priv *priv,
                                struct mlx4_en_tx_ring *ring);
 void mlx4_en_set_num_rx_rings(struct mlx4_en_dev *mdev);
+void mlx4_en_recover_from_oom(struct mlx4_en_priv *priv);
 int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
                           struct mlx4_en_rx_ring **pring,
                           u32 size, u16 stride, int node);
index df2238372ea73a0d71b39450cd816810bbcdd1ad..8a64542abc16127627374cf4cb065eea017d135f 100644 (file)
@@ -211,26 +211,28 @@ static int alloc_4k(struct mlx5_core_dev *dev, u64 *addr)
        return 0;
 }
 
+#define MLX5_U64_4K_PAGE_MASK ((~(u64)0U) << PAGE_SHIFT)
+
 static void free_4k(struct mlx5_core_dev *dev, u64 addr)
 {
        struct fw_page *fwp;
        int n;
 
-       fwp = find_fw_page(dev, addr & PAGE_MASK);
+       fwp = find_fw_page(dev, addr & MLX5_U64_4K_PAGE_MASK);
        if (!fwp) {
                mlx5_core_warn(dev, "page not found\n");
                return;
        }
 
-       n = (addr & ~PAGE_MASK) >> MLX5_ADAPTER_PAGE_SHIFT;
+       n = (addr & ~MLX5_U64_4K_PAGE_MASK) >> MLX5_ADAPTER_PAGE_SHIFT;
        fwp->free_count++;
        set_bit(n, &fwp->bitmask);
        if (fwp->free_count == MLX5_NUM_4K_IN_PAGE) {
                rb_erase(&fwp->rb_node, &dev->priv.page_root);
                if (fwp->free_count != 1)
                        list_del(&fwp->list);
-               dma_unmap_page(&dev->pdev->dev, addr & PAGE_MASK, PAGE_SIZE,
-                              DMA_BIDIRECTIONAL);
+               dma_unmap_page(&dev->pdev->dev, addr & MLX5_U64_4K_PAGE_MASK,
+                              PAGE_SIZE, DMA_BIDIRECTIONAL);
                __free_page(fwp->page);
                kfree(fwp);
        } else if (fwp->free_count == 1) {
index 1412f5af05ecf521e41ff109dc1a24e7621090ce..2bae50292dcd814a2b8cb338da1bb0a6beac82f0 100644 (file)
 #include <net/ip.h>
 #include <net/tcp.h>
 #include <asm/byteorder.h>
-#include <asm/io.h>
 #include <asm/processor.h>
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
 #include <net/busy_poll.h>
 
 #include "myri10ge_mcp.h"
@@ -242,8 +238,7 @@ struct myri10ge_priv {
        unsigned int rdma_tags_available;
        int intr_coal_delay;
        __be32 __iomem *intr_coal_delay_ptr;
-       int mtrr;
-       int wc_enabled;
+       int wc_cookie;
        int down_cnt;
        wait_queue_head_t down_wq;
        struct work_struct watchdog_work;
@@ -1905,7 +1900,7 @@ static const char myri10ge_gstrings_main_stats[][ETH_GSTRING_LEN] = {
        "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors",
        "tx_heartbeat_errors", "tx_window_errors",
        /* device-specific stats */
-       "tx_boundary", "WC", "irq", "MSI", "MSIX",
+       "tx_boundary", "irq", "MSI", "MSIX",
        "read_dma_bw_MBs", "write_dma_bw_MBs", "read_write_dma_bw_MBs",
        "serial_number", "watchdog_resets",
 #ifdef CONFIG_MYRI10GE_DCA
@@ -1984,7 +1979,6 @@ myri10ge_get_ethtool_stats(struct net_device *netdev,
                data[i] = ((u64 *)&link_stats)[i];
 
        data[i++] = (unsigned int)mgp->tx_boundary;
-       data[i++] = (unsigned int)mgp->wc_enabled;
        data[i++] = (unsigned int)mgp->pdev->irq;
        data[i++] = (unsigned int)mgp->msi_enabled;
        data[i++] = (unsigned int)mgp->msix_enabled;
@@ -4040,14 +4034,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        mgp->board_span = pci_resource_len(pdev, 0);
        mgp->iomem_base = pci_resource_start(pdev, 0);
-       mgp->mtrr = -1;
-       mgp->wc_enabled = 0;
-#ifdef CONFIG_MTRR
-       mgp->mtrr = mtrr_add(mgp->iomem_base, mgp->board_span,
-                            MTRR_TYPE_WRCOMB, 1);
-       if (mgp->mtrr >= 0)
-               mgp->wc_enabled = 1;
-#endif
+       mgp->wc_cookie = arch_phys_wc_add(mgp->iomem_base, mgp->board_span);
        mgp->sram = ioremap_wc(mgp->iomem_base, mgp->board_span);
        if (mgp->sram == NULL) {
                dev_err(&pdev->dev, "ioremap failed for %ld bytes at 0x%lx\n",
@@ -4146,14 +4133,14 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto abort_with_state;
        }
        if (mgp->msix_enabled)
-               dev_info(dev, "%d MSI-X IRQs, tx bndry %d, fw %s, WC %s\n",
+               dev_info(dev, "%d MSI-X IRQs, tx bndry %d, fw %s, MTRR %s, WC Enabled\n",
                         mgp->num_slices, mgp->tx_boundary, mgp->fw_name,
-                        (mgp->wc_enabled ? "Enabled" : "Disabled"));
+                        (mgp->wc_cookie > 0 ? "Enabled" : "Disabled"));
        else
-               dev_info(dev, "%s IRQ %d, tx bndry %d, fw %s, WC %s\n",
+               dev_info(dev, "%s IRQ %d, tx bndry %d, fw %s, MTRR %s, WC Enabled\n",
                         mgp->msi_enabled ? "MSI" : "xPIC",
                         pdev->irq, mgp->tx_boundary, mgp->fw_name,
-                        (mgp->wc_enabled ? "Enabled" : "Disabled"));
+                        (mgp->wc_cookie > 0 ? "Enabled" : "Disabled"));
 
        board_number++;
        return 0;
@@ -4175,10 +4162,7 @@ abort_with_ioremap:
        iounmap(mgp->sram);
 
 abort_with_mtrr:
-#ifdef CONFIG_MTRR
-       if (mgp->mtrr >= 0)
-               mtrr_del(mgp->mtrr, mgp->iomem_base, mgp->board_span);
-#endif
+       arch_phys_wc_del(mgp->wc_cookie);
        dma_free_coherent(&pdev->dev, sizeof(*mgp->cmd),
                          mgp->cmd, mgp->cmd_bus);
 
@@ -4220,11 +4204,7 @@ static void myri10ge_remove(struct pci_dev *pdev)
        pci_restore_state(pdev);
 
        iounmap(mgp->sram);
-
-#ifdef CONFIG_MTRR
-       if (mgp->mtrr >= 0)
-               mtrr_del(mgp->mtrr, mgp->iomem_base, mgp->board_span);
-#endif
+       arch_phys_wc_del(mgp->wc_cookie);
        myri10ge_free_slices(mgp);
        kfree(mgp->msix_vectors);
        dma_free_coherent(&pdev->dev, sizeof(*mgp->cmd),
index 5c4068353f664e8924f832c3d681ec41f53465c6..8da7c3faf8178c05576c74833fc828f197104f52 100644 (file)
@@ -135,7 +135,7 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter)
        int i, j;
        struct nx_host_tx_ring *tx_ring = adapter->tx_ring;
 
-       spin_lock(&adapter->tx_clean_lock);
+       spin_lock_bh(&adapter->tx_clean_lock);
        cmd_buf = tx_ring->cmd_buf_arr;
        for (i = 0; i < tx_ring->num_desc; i++) {
                buffrag = cmd_buf->frag_array;
@@ -159,7 +159,7 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter)
                }
                cmd_buf++;
        }
-       spin_unlock(&adapter->tx_clean_lock);
+       spin_unlock_bh(&adapter->tx_clean_lock);
 }
 
 void netxen_free_sw_resources(struct netxen_adapter *adapter)
index a570a60533be5531c5881ace3683e69e9d80ece5..ec251531bd9f8ecd1e64295b4f1f5c35fe475b79 100644 (file)
@@ -4176,14 +4176,15 @@ static int rocker_port_bridge_setlink(struct net_device *dev,
 
 static int rocker_port_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
                                      struct net_device *dev,
-                                     u32 filter_mask)
+                                     u32 filter_mask, int nlflags)
 {
        struct rocker_port *rocker_port = netdev_priv(dev);
        u16 mode = BRIDGE_MODE_UNDEF;
        u32 mask = BR_LEARNING | BR_LEARNING_SYNC;
 
        return ndo_dflt_bridge_getlink(skb, pid, seq, dev, mode,
-                                      rocker_port->brport_flags, mask);
+                                      rocker_port->brport_flags, mask,
+                                      nlflags);
 }
 
 static int rocker_port_get_phys_port_name(struct net_device *dev,
index 2bef655279f32a4ffb6097b295362e2da22867c0..9b7e0a34c98b10aca5eed610c47f33b2eedbbd00 100644 (file)
@@ -1765,7 +1765,9 @@ static void netcp_ethss_link_state_action(struct gbe_priv *gbe_dev,
                                     ALE_PORT_STATE,
                                     ALE_PORT_STATE_FORWARD);
 
-               if (ndev && slave->open)
+               if (ndev && slave->open &&
+                   slave->link_interface != SGMII_LINK_MAC_PHY &&
+                   slave->link_interface != XGMII_LINK_MAC_PHY)
                        netif_carrier_on(ndev);
        } else {
                writel(mac_control, GBE_REG_ADDR(slave, emac_regs,
@@ -1773,7 +1775,9 @@ static void netcp_ethss_link_state_action(struct gbe_priv *gbe_dev,
                cpsw_ale_control_set(gbe_dev->ale, slave->port_num,
                                     ALE_PORT_STATE,
                                     ALE_PORT_STATE_DISABLE);
-               if (ndev)
+               if (ndev &&
+                   slave->link_interface != SGMII_LINK_MAC_PHY &&
+                   slave->link_interface != XGMII_LINK_MAC_PHY)
                        netif_carrier_off(ndev);
        }
 
index a10b31664709f51215435d94a9439c65d311221b..41071d32bc8e0e1259726aa647bc8a77324ffdd9 100644 (file)
@@ -128,7 +128,6 @@ struct ndis_tcp_ip_checksum_info;
 struct hv_netvsc_packet {
        /* Bookkeeping stuff */
        u32 status;
-       bool part_of_skb;
 
        bool is_data_pkt;
        bool xmit_more; /* from skb */
@@ -612,6 +611,15 @@ struct multi_send_data {
        u32 count; /* counter of batched packets */
 };
 
+/* The context of the netvsc device  */
+struct net_device_context {
+       /* point back to our device context */
+       struct hv_device *device_ctx;
+       struct delayed_work dwork;
+       struct work_struct work;
+       u32 msg_enable; /* debug level */
+};
+
 /* Per netvsc device */
 struct netvsc_device {
        struct hv_device *dev;
@@ -667,6 +675,9 @@ struct netvsc_device {
        struct multi_send_data msd[NR_CPUS];
        u32 max_pkt; /* max number of pkt in one send, e.g. 8 */
        u32 pkt_align; /* alignment bytes, e.g. 8 */
+
+       /* The net device context */
+       struct net_device_context *nd_ctx;
 };
 
 /* NdisInitialize message */
index 2e8ad0636b466668e8939e4eabe442160e6c2402..2d9ef533cc4837c5bd7b46c96958f9f1b9eda323 100644 (file)
@@ -889,11 +889,6 @@ int netvsc_send(struct hv_device *device,
                } else {
                        packet->page_buf_cnt = 0;
                        packet->total_data_buflen += msd_len;
-                       if (!packet->part_of_skb) {
-                               skb = (struct sk_buff *)(unsigned long)packet->
-                                      send_completion_tid;
-                               packet->send_completion_tid = 0;
-                       }
                }
 
                if (msdp->pkt)
@@ -1197,6 +1192,9 @@ int netvsc_device_add(struct hv_device *device, void *additional_info)
         */
        ndev = net_device->ndev;
 
+       /* Add netvsc_device context to netvsc_device */
+       net_device->nd_ctx = netdev_priv(ndev);
+
        /* Initialize the NetVSC channel extension */
        init_completion(&net_device->channel_init_wait);
 
index a3a9d3898a6e8a80ddb21cb11864c09006e47554..5993c7e2d723a7e42d6022c90cb8e495420a49ad 100644 (file)
 
 #include "hyperv_net.h"
 
-struct net_device_context {
-       /* point back to our device context */
-       struct hv_device *device_ctx;
-       struct delayed_work dwork;
-       struct work_struct work;
-};
 
 #define RING_SIZE_MIN 64
 static int ring_size = 128;
 module_param(ring_size, int, S_IRUGO);
 MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)");
 
+static const u32 default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE |
+                               NETIF_MSG_LINK | NETIF_MSG_IFUP |
+                               NETIF_MSG_IFDOWN | NETIF_MSG_RX_ERR |
+                               NETIF_MSG_TX_ERR;
+
+static int debug = -1;
+module_param(debug, int, S_IRUGO);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+
 static void do_set_multicast(struct work_struct *w)
 {
        struct net_device_context *ndevctx =
@@ -235,9 +238,6 @@ void netvsc_xmit_completion(void *context)
        struct sk_buff *skb = (struct sk_buff *)
                (unsigned long)packet->send_completion_tid;
 
-       if (!packet->part_of_skb)
-               kfree(packet);
-
        if (skb)
                dev_kfree_skb_any(skb);
 }
@@ -389,7 +389,6 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
        u32 net_trans_info;
        u32 hash;
        u32 skb_length;
-       u32 head_room;
        u32 pkt_sz;
        struct hv_page_buffer page_buf[MAX_PAGE_BUFFER_COUNT];
 
@@ -402,7 +401,6 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
 
 check_size:
        skb_length = skb->len;
-       head_room = skb_headroom(skb);
        num_data_pgs = netvsc_get_slots(skb) + 2;
        if (num_data_pgs > MAX_PAGE_BUFFER_COUNT && linear) {
                net_alert_ratelimited("packet too big: %u pages (%u bytes)\n",
@@ -421,20 +419,14 @@ check_size:
 
        pkt_sz = sizeof(struct hv_netvsc_packet) + RNDIS_AND_PPI_SIZE;
 
-       if (head_room < pkt_sz) {
-               packet = kmalloc(pkt_sz, GFP_ATOMIC);
-               if (!packet) {
-                       /* out of memory, drop packet */
-                       netdev_err(net, "unable to alloc hv_netvsc_packet\n");
-                       ret = -ENOMEM;
-                       goto drop;
-               }
-               packet->part_of_skb = false;
-       } else {
-               /* Use the headroom for building up the packet */
-               packet = (struct hv_netvsc_packet *)skb->head;
-               packet->part_of_skb = true;
+       ret = skb_cow_head(skb, pkt_sz);
+       if (ret) {
+               netdev_err(net, "unable to alloc hv_netvsc_packet\n");
+               ret = -ENOMEM;
+               goto drop;
        }
+       /* Use the headroom for building up the packet */
+       packet = (struct hv_netvsc_packet *)skb->head;
 
        packet->status = 0;
        packet->xmit_more = skb->xmit_more;
@@ -591,8 +583,6 @@ drop:
                net->stats.tx_bytes += skb_length;
                net->stats.tx_packets++;
        } else {
-               if (packet && !packet->part_of_skb)
-                       kfree(packet);
                if (ret != -EAGAIN) {
                        dev_kfree_skb_any(skb);
                        net->stats.tx_dropped++;
@@ -888,6 +878,11 @@ static int netvsc_probe(struct hv_device *dev,
 
        net_device_ctx = netdev_priv(net);
        net_device_ctx->device_ctx = dev;
+       net_device_ctx->msg_enable = netif_msg_init(debug, default_msg);
+       if (netif_msg_probe(net_device_ctx))
+               netdev_dbg(net, "netvsc msg_enable: %d\n",
+                          net_device_ctx->msg_enable);
+
        hv_set_drvdata(dev, net);
        INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_link_change);
        INIT_WORK(&net_device_ctx->work, do_set_multicast);
index 0d92efefd796c9b631beeca1b35ad9979cb36d2f..9118cea918821cb6bbe83a2f97a71134a58fd5dd 100644 (file)
@@ -429,7 +429,8 @@ int rndis_filter_receive(struct hv_device *dev,
 
        rndis_msg = pkt->data;
 
-       dump_rndis_message(dev, rndis_msg);
+       if (netif_msg_rx_err(net_dev->nd_ctx))
+               dump_rndis_message(dev, rndis_msg);
 
        switch (rndis_msg->ndis_msg_type) {
        case RNDIS_MSG_PACKET:
index 49ce7ece5af30c04c3e632a1719ba45d9b47f3b5..c9cb486c753d053c8b6da529a0c078d89f9c2a2f 100644 (file)
@@ -80,7 +80,8 @@ static void mdio_dir(struct mdiobb_ctrl *ctrl, int dir)
                 * assume the pin serves as pull-up. If direction is
                 * output, the default value is high.
                 */
-               gpio_set_value(bitbang->mdo, 1 ^ bitbang->mdo_active_low);
+               gpio_set_value_cansleep(bitbang->mdo,
+                                       1 ^ bitbang->mdo_active_low);
                return;
        }
 
@@ -96,7 +97,8 @@ static int mdio_get(struct mdiobb_ctrl *ctrl)
        struct mdio_gpio_info *bitbang =
                container_of(ctrl, struct mdio_gpio_info, ctrl);
 
-       return gpio_get_value(bitbang->mdio) ^ bitbang->mdio_active_low;
+       return gpio_get_value_cansleep(bitbang->mdio) ^
+               bitbang->mdio_active_low;
 }
 
 static void mdio_set(struct mdiobb_ctrl *ctrl, int what)
@@ -105,9 +107,11 @@ static void mdio_set(struct mdiobb_ctrl *ctrl, int what)
                container_of(ctrl, struct mdio_gpio_info, ctrl);
 
        if (bitbang->mdo)
-               gpio_set_value(bitbang->mdo, what ^ bitbang->mdo_active_low);
+               gpio_set_value_cansleep(bitbang->mdo,
+                                       what ^ bitbang->mdo_active_low);
        else
-               gpio_set_value(bitbang->mdio, what ^ bitbang->mdio_active_low);
+               gpio_set_value_cansleep(bitbang->mdio,
+                                       what ^ bitbang->mdio_active_low);
 }
 
 static void mdc_set(struct mdiobb_ctrl *ctrl, int what)
@@ -115,7 +119,7 @@ static void mdc_set(struct mdiobb_ctrl *ctrl, int what)
        struct mdio_gpio_info *bitbang =
                container_of(ctrl, struct mdio_gpio_info, ctrl);
 
-       gpio_set_value(bitbang->mdc, what ^ bitbang->mdc_active_low);
+       gpio_set_value_cansleep(bitbang->mdc, what ^ bitbang->mdc_active_low);
 }
 
 static struct mdiobb_ops mdio_gpio_ops = {
index 1a87a585e74df9abac74d5a60c8715917b179ff9..66edd99bc302ddc5c5bdd0d0757acd7923adf8f4 100644 (file)
 #include <linux/module.h>
 #include <linux/phy.h>
 #include <linux/mdio-mux.h>
-#include <linux/of_gpio.h>
+#include <linux/gpio/consumer.h>
 
 #define DRV_VERSION "1.1"
 #define DRV_DESCRIPTION "GPIO controlled MDIO bus multiplexer driver"
 
-#define MDIO_MUX_GPIO_MAX_BITS 8
-
 struct mdio_mux_gpio_state {
-       struct gpio_desc *gpio[MDIO_MUX_GPIO_MAX_BITS];
-       unsigned int num_gpios;
+       struct gpio_descs *gpios;
        void *mux_handle;
 };
 
 static int mdio_mux_gpio_switch_fn(int current_child, int desired_child,
                                   void *data)
 {
-       int values[MDIO_MUX_GPIO_MAX_BITS];
-       unsigned int n;
        struct mdio_mux_gpio_state *s = data;
+       int values[s->gpios->ndescs];
+       unsigned int n;
 
        if (current_child == desired_child)
                return 0;
 
-       for (n = 0; n < s->num_gpios; n++) {
+       for (n = 0; n < s->gpios->ndescs; n++)
                values[n] = (desired_child >> n) & 1;
-       }
-       gpiod_set_array_cansleep(s->num_gpios, s->gpio, values);
+
+       gpiod_set_array_cansleep(s->gpios->ndescs, s->gpios->desc, values);
 
        return 0;
 }
@@ -46,56 +43,33 @@ static int mdio_mux_gpio_switch_fn(int current_child, int desired_child,
 static int mdio_mux_gpio_probe(struct platform_device *pdev)
 {
        struct mdio_mux_gpio_state *s;
-       int num_gpios;
-       unsigned int n;
        int r;
 
-       if (!pdev->dev.of_node)
-               return -ENODEV;
-
-       num_gpios = of_gpio_count(pdev->dev.of_node);
-       if (num_gpios <= 0 || num_gpios > MDIO_MUX_GPIO_MAX_BITS)
-               return -ENODEV;
-
        s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL);
        if (!s)
                return -ENOMEM;
 
-       s->num_gpios = num_gpios;
-
-       for (n = 0; n < num_gpios; ) {
-               struct gpio_desc *gpio = gpiod_get_index(&pdev->dev, NULL, n,
-                                                        GPIOD_OUT_LOW);
-               if (IS_ERR(gpio)) {
-                       r = PTR_ERR(gpio);
-                       goto err;
-               }
-               s->gpio[n] = gpio;
-               n++;
-       }
+       s->gpios = gpiod_get_array(&pdev->dev, NULL, GPIOD_OUT_LOW);
+       if (IS_ERR(s->gpios))
+               return PTR_ERR(s->gpios);
 
        r = mdio_mux_init(&pdev->dev,
                          mdio_mux_gpio_switch_fn, &s->mux_handle, s);
 
-       if (r == 0) {
-               pdev->dev.platform_data = s;
-               return 0;
-       }
-err:
-       while (n) {
-               n--;
-               gpiod_put(s->gpio[n]);
+       if (r != 0) {
+               gpiod_put_array(s->gpios);
+               return r;
        }
-       return r;
+
+       pdev->dev.platform_data = s;
+       return 0;
 }
 
 static int mdio_mux_gpio_remove(struct platform_device *pdev)
 {
-       unsigned int n;
        struct mdio_mux_gpio_state *s = dev_get_platdata(&pdev->dev);
        mdio_mux_uninit(s->mux_handle);
-       for (n = 0; n < s->num_gpios; n++)
-               gpiod_put(s->gpio[n]);
+       gpiod_put_array(s->gpios);
        return 0;
 }
 
index af034dba9bd62a693ba81dd04479cd11ffc7f10e..9d15566521a719b525a28a009f1d999c91a00da2 100644 (file)
@@ -1716,6 +1716,7 @@ ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
 {
        /* note: a 0-length skb is used as an error indication */
        if (skb->len > 0) {
+               skb_checksum_complete_unset(skb);
 #ifdef CONFIG_PPP_MULTILINK
                /* XXX do channel-level decompression here */
                if (PPP_PROTO(skb) == PPP_MP)
index 911b21602ff271885c2dbfb4c5c04f69fb028e7e..05005c660d4d954527d278130824f232383c2d49 100644 (file)
@@ -478,7 +478,6 @@ mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf,
        struct blkcipher_desc desc = { .tfm = state->arc4 };
        unsigned ccount;
        int flushed = MPPE_BITS(ibuf) & MPPE_BIT_FLUSHED;
-       int sanity = 0;
        struct scatterlist sg_in[1], sg_out[1];
 
        if (isize <= PPP_HDRLEN + MPPE_OVHD) {
@@ -514,31 +513,19 @@ mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf,
                       "mppe_decompress[%d]: ENCRYPTED bit not set!\n",
                       state->unit);
                state->sanity_errors += 100;
-               sanity = 1;
+               goto sanity_error;
        }
        if (!state->stateful && !flushed) {
                printk(KERN_DEBUG "mppe_decompress[%d]: FLUSHED bit not set in "
                       "stateless mode!\n", state->unit);
                state->sanity_errors += 100;
-               sanity = 1;
+               goto sanity_error;
        }
        if (state->stateful && ((ccount & 0xff) == 0xff) && !flushed) {
                printk(KERN_DEBUG "mppe_decompress[%d]: FLUSHED bit not set on "
                       "flag packet!\n", state->unit);
                state->sanity_errors += 100;
-               sanity = 1;
-       }
-
-       if (sanity) {
-               if (state->sanity_errors < SANITY_MAX)
-                       return DECOMP_ERROR;
-               else
-                       /*
-                        * Take LCP down if the peer is sending too many bogons.
-                        * We don't want to do this for a single or just a few
-                        * instances since it could just be due to packet corruption.
-                        */
-                       return DECOMP_FATALERROR;
+               goto sanity_error;
        }
 
        /*
@@ -546,6 +533,13 @@ mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf,
         */
 
        if (!state->stateful) {
+               /* Discard late packet */
+               if ((ccount - state->ccount) % MPPE_CCOUNT_SPACE
+                                               > MPPE_CCOUNT_SPACE / 2) {
+                       state->sanity_errors++;
+                       goto sanity_error;
+               }
+
                /* RFC 3078, sec 8.1.  Rekey for every packet. */
                while (state->ccount != ccount) {
                        mppe_rekey(state, 0);
@@ -649,6 +643,16 @@ mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf,
        state->sanity_errors >>= 1;
 
        return osize;
+
+sanity_error:
+       if (state->sanity_errors < SANITY_MAX)
+               return DECOMP_ERROR;
+       else
+               /* Take LCP down if the peer is sending too many bogons.
+                * We don't want to do this for a single or just a few
+                * instances since it could just be due to packet corruption.
+                */
+               return DECOMP_FATALERROR;
 }
 
 /*
index ff059e1d8ac6c8c478625a55e54c4c41c945ad9a..aa1dd926623ad622e3a15f905733e3d585aca871 100644 (file)
@@ -380,6 +380,9 @@ static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb)
         * can't change.
         */
 
+       if (skb->pkt_type == PACKET_OTHERHOST)
+               goto abort_kfree;
+
        if (sk->sk_state & PPPOX_BOUND) {
                ppp_input(&po->chan, skb);
        } else if (sk->sk_state & PPPOX_RELAY) {
index 154116aafd0d8c5cb6caab9056a2245cbc3c783b..27a5f954f8e999cc809dc5ed0bad08d2e06e0f18 100644 (file)
@@ -730,12 +730,8 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan,
                        /* Only change unicasts */
                        if (!(is_multicast_ether_addr(f->eth_addr) ||
                             is_zero_ether_addr(f->eth_addr))) {
-                               int rc = vxlan_fdb_replace(f, ip, port, vni,
+                               notify |= vxlan_fdb_replace(f, ip, port, vni,
                                                           ifindex);
-
-                               if (rc < 0)
-                                       return rc;
-                               notify |= rc;
                        } else
                                return -EOPNOTSUPP;
                }
index a92bd3e89796b181902bc387f49ff8eafaf31d04..ea0e359bdb43b5e98d437b468d3e331e0f865d42 100644 (file)
 #include <linux/err.h>
 #include <linux/wl12xx.h>
 
-static struct wl12xx_platform_data *wl12xx_platform_data;
-
-int __init wl12xx_set_platform_data(const struct wl12xx_platform_data *data)
-{
-       if (wl12xx_platform_data)
-               return -EBUSY;
-       if (!data)
-               return -EINVAL;
-
-       wl12xx_platform_data = kmemdup(data, sizeof(*data), GFP_KERNEL);
-       if (!wl12xx_platform_data)
-               return -ENOMEM;
-
-       return 0;
-}
-
-struct wl12xx_platform_data *wl12xx_get_platform_data(void)
-{
-       if (!wl12xx_platform_data)
-               return ERR_PTR(-ENODEV);
-
-       return wl12xx_platform_data;
-}
-EXPORT_SYMBOL(wl12xx_get_platform_data);
-
 static struct wl1251_platform_data *wl1251_platform_data;
 
 int __init wl1251_set_platform_data(const struct wl1251_platform_data *data)
index 144d1f8ba473463ce204de1188b8971cff3a841f..af0fe2e1715105c6ce2823bff0eb1ea99b22c8c7 100644 (file)
@@ -24,8 +24,6 @@
 
 #include <linux/err.h>
 
-#include <linux/wl12xx.h>
-
 #include "../wlcore/wlcore.h"
 #include "../wlcore/debug.h"
 #include "../wlcore/io.h"
@@ -1770,11 +1768,44 @@ wl12xx_iface_combinations[] = {
        },
 };
 
+static const struct wl12xx_clock wl12xx_refclock_table[] = {
+       { 19200000,     false,  WL12XX_REFCLOCK_19      },
+       { 26000000,     false,  WL12XX_REFCLOCK_26      },
+       { 26000000,     true,   WL12XX_REFCLOCK_26_XTAL },
+       { 38400000,     false,  WL12XX_REFCLOCK_38      },
+       { 38400000,     true,   WL12XX_REFCLOCK_38_XTAL },
+       { 52000000,     false,  WL12XX_REFCLOCK_52      },
+       { 0,            false,  0 }
+};
+
+static const struct wl12xx_clock wl12xx_tcxoclock_table[] = {
+       { 16368000,     true,   WL12XX_TCXOCLOCK_16_368 },
+       { 16800000,     true,   WL12XX_TCXOCLOCK_16_8   },
+       { 19200000,     true,   WL12XX_TCXOCLOCK_19_2   },
+       { 26000000,     true,   WL12XX_TCXOCLOCK_26     },
+       { 32736000,     true,   WL12XX_TCXOCLOCK_32_736 },
+       { 33600000,     true,   WL12XX_TCXOCLOCK_33_6   },
+       { 38400000,     true,   WL12XX_TCXOCLOCK_38_4   },
+       { 52000000,     true,   WL12XX_TCXOCLOCK_52     },
+       { 0,            false,  0 }
+};
+
+static int wl12xx_get_clock_idx(const struct wl12xx_clock *table,
+                               u32 freq, bool xtal)
+{
+       int i;
+
+       for (i = 0; table[i].freq != 0; i++)
+               if ((table[i].freq == freq) && (table[i].xtal == xtal))
+                       return table[i].hw_idx;
+
+       return -EINVAL;
+}
+
 static int wl12xx_setup(struct wl1271 *wl)
 {
        struct wl12xx_priv *priv = wl->priv;
        struct wlcore_platdev_data *pdev_data = dev_get_platdata(&wl->pdev->dev);
-       struct wl12xx_platform_data *pdata = pdev_data->pdata;
 
        BUILD_BUG_ON(WL12XX_MAX_LINKS > WLCORE_MAX_LINKS);
        BUILD_BUG_ON(WL12XX_MAX_AP_STATIONS > WL12XX_MAX_LINKS);
@@ -1799,7 +1830,17 @@ static int wl12xx_setup(struct wl1271 *wl)
        wl12xx_conf_init(wl);
 
        if (!fref_param) {
-               priv->ref_clock = pdata->board_ref_clock;
+               priv->ref_clock = wl12xx_get_clock_idx(wl12xx_refclock_table,
+                                               pdev_data->ref_clock_freq,
+                                               pdev_data->ref_clock_xtal);
+               if (priv->ref_clock < 0) {
+                       wl1271_error("Invalid ref_clock frequency (%d Hz, %s)",
+                                    pdev_data->ref_clock_freq,
+                                    pdev_data->ref_clock_xtal ?
+                                    "XTAL" : "not XTAL");
+
+                       return priv->ref_clock;
+               }
        } else {
                if (!strcmp(fref_param, "19.2"))
                        priv->ref_clock = WL12XX_REFCLOCK_19;
@@ -1817,9 +1858,17 @@ static int wl12xx_setup(struct wl1271 *wl)
                        wl1271_error("Invalid fref parameter %s", fref_param);
        }
 
-       if (!tcxo_param) {
-               priv->tcxo_clock = pdata->board_tcxo_clock;
-       } else {
+       if (!tcxo_param && pdev_data->tcxo_clock_freq) {
+               priv->tcxo_clock = wl12xx_get_clock_idx(wl12xx_tcxoclock_table,
+                                               pdev_data->tcxo_clock_freq,
+                                               true);
+               if (priv->tcxo_clock < 0) {
+                       wl1271_error("Invalid tcxo_clock frequency (%d Hz)",
+                                    pdev_data->tcxo_clock_freq);
+
+                       return priv->tcxo_clock;
+               }
+       } else if (tcxo_param) {
                if (!strcmp(tcxo_param, "19.2"))
                        priv->tcxo_clock = WL12XX_TCXOCLOCK_19_2;
                else if (!strcmp(tcxo_param, "26"))
index 75c92658bfeaecb3ccd356303fde6dc17efc92c4..5952e99ace1bb2fa752d0827c78159ae0287fb45 100644 (file)
@@ -82,6 +82,34 @@ struct wl12xx_priv {
        struct wl127x_rx_mem_pool_addr *rx_mem_addr;
 };
 
+/* Reference clock values */
+enum {
+       WL12XX_REFCLOCK_19      = 0, /* 19.2 MHz */
+       WL12XX_REFCLOCK_26      = 1, /* 26 MHz */
+       WL12XX_REFCLOCK_38      = 2, /* 38.4 MHz */
+       WL12XX_REFCLOCK_52      = 3, /* 52 MHz */
+       WL12XX_REFCLOCK_38_XTAL = 4, /* 38.4 MHz, XTAL */
+       WL12XX_REFCLOCK_26_XTAL = 5, /* 26 MHz, XTAL */
+};
+
+/* TCXO clock values */
+enum {
+       WL12XX_TCXOCLOCK_19_2   = 0, /* 19.2MHz */
+       WL12XX_TCXOCLOCK_26     = 1, /* 26 MHz */
+       WL12XX_TCXOCLOCK_38_4   = 2, /* 38.4MHz */
+       WL12XX_TCXOCLOCK_52     = 3, /* 52 MHz */
+       WL12XX_TCXOCLOCK_16_368 = 4, /* 16.368 MHz */
+       WL12XX_TCXOCLOCK_32_736 = 5, /* 32.736 MHz */
+       WL12XX_TCXOCLOCK_16_8   = 6, /* 16.8 MHz */
+       WL12XX_TCXOCLOCK_33_6   = 7, /* 33.6 MHz */
+};
+
+struct wl12xx_clock {
+       u32     freq;
+       bool    xtal;
+       u8      hw_idx;
+};
+
 struct wl12xx_fw_packet_counters {
        /* Cumulative counter of released packets per AC */
        u8 tx_released_pkts[NUM_TX_QUEUES];
index 77752b03f1892184f0275172f41ef15721c4cd1c..19b7ec7b69c21dd12f2355d7fba8c8f8d69b2c8f 100644 (file)
@@ -22,7 +22,6 @@
  */
 
 #include <linux/slab.h>
-#include <linux/wl12xx.h>
 #include <linux/export.h>
 
 #include "debug.h"
index 68f3bf229b5a5029d57d06638ea5b27144a76e33..eb43f94a15973fec04cba41af965fac4e9065715 100644 (file)
@@ -502,7 +502,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
        DRIVER_STATE_PRINT_HEX(irq);
        /* TODO: ref_clock and tcxo_clock were moved to wl12xx priv */
        DRIVER_STATE_PRINT_HEX(hw_pg_ver);
-       DRIVER_STATE_PRINT_HEX(platform_quirks);
+       DRIVER_STATE_PRINT_HEX(irq_flags);
        DRIVER_STATE_PRINT_HEX(chip.id);
        DRIVER_STATE_PRINT_STR(chip.fw_ver_str);
        DRIVER_STATE_PRINT_STR(chip.phy_fw_ver_str);
index 1e136993580f104a156fd3c72494dee9b3845a9b..0be807951afe3bbcca6db42ea98855ff8536254a 100644 (file)
@@ -25,8 +25,8 @@
 #include <linux/firmware.h>
 #include <linux/etherdevice.h>
 #include <linux/vmalloc.h>
-#include <linux/wl12xx.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 
 #include "wlcore.h"
 #include "debug.h"
@@ -538,7 +538,7 @@ static int wlcore_irq_locked(struct wl1271 *wl)
         * In case edge triggered interrupt must be used, we cannot iterate
         * more than once without introducing race conditions with the hardirq.
         */
-       if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ)
+       if (wl->irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING))
                loopcount = 1;
 
        wl1271_debug(DEBUG_IRQ, "IRQ work");
@@ -6249,7 +6249,6 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size,
        wl->ap_ps_map = 0;
        wl->ap_fw_ps_map = 0;
        wl->quirks = 0;
-       wl->platform_quirks = 0;
        wl->system_hlid = WL12XX_SYSTEM_HLID;
        wl->active_sta_count = 0;
        wl->active_link_count = 0;
@@ -6390,8 +6389,8 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context)
        struct wl1271 *wl = context;
        struct platform_device *pdev = wl->pdev;
        struct wlcore_platdev_data *pdev_data = dev_get_platdata(&pdev->dev);
-       struct wl12xx_platform_data *pdata = pdev_data->pdata;
-       unsigned long irqflags;
+       struct resource *res;
+
        int ret;
        irq_handler_t hardirq_fn = NULL;
 
@@ -6418,19 +6417,23 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context)
        /* adjust some runtime configuration parameters */
        wlcore_adjust_conf(wl);
 
-       wl->irq = platform_get_irq(pdev, 0);
-       wl->platform_quirks = pdata->platform_quirks;
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!res) {
+               wl1271_error("Could not get IRQ resource");
+               goto out_free_nvs;
+       }
+
+       wl->irq = res->start;
+       wl->irq_flags = res->flags & IRQF_TRIGGER_MASK;
        wl->if_ops = pdev_data->if_ops;
 
-       if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) {
-               irqflags = IRQF_TRIGGER_RISING;
+       if (wl->irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING))
                hardirq_fn = wlcore_hardirq;
-       } else {
-               irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT;
-       }
+       else
+               wl->irq_flags |= IRQF_ONESHOT;
 
        ret = request_threaded_irq(wl->irq, hardirq_fn, wlcore_irq,
-                                  irqflags, pdev->name, wl);
+                                  wl->irq_flags, pdev->name, wl);
        if (ret < 0) {
                wl1271_error("request_irq() failed: %d", ret);
                goto out_free_nvs;
@@ -6441,7 +6444,7 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context)
        if (!ret) {
                wl->irq_wake_enabled = true;
                device_init_wakeup(wl->dev, 1);
-               if (pdata->pwr_in_suspend)
+               if (pdev_data->pwr_in_suspend)
                        wl->hw->wiphy->wowlan = &wlcore_wowlan_support;
        }
 #endif
index d3dd7bfdf3f1f33efbfbd9e0be762f664c892926..ea7e07abca4ebaccd37eaa1aac75567453b3e0a0 100644 (file)
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
 #include <linux/gpio.h>
-#include <linux/wl12xx.h>
 #include <linux/pm_runtime.h>
 #include <linux/printk.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
 
 #include "wlcore.h"
 #include "wl12xx_80211.h"
@@ -214,6 +215,52 @@ static struct wl1271_if_operations sdio_ops = {
        .set_block_size = wl1271_sdio_set_block_size,
 };
 
+#ifdef CONFIG_OF
+static const struct of_device_id wlcore_sdio_of_match_table[] = {
+       { .compatible = "ti,wl1271" },
+       { .compatible = "ti,wl1273" },
+       { .compatible = "ti,wl1281" },
+       { .compatible = "ti,wl1283" },
+       { .compatible = "ti,wl1801" },
+       { .compatible = "ti,wl1805" },
+       { .compatible = "ti,wl1807" },
+       { .compatible = "ti,wl1831" },
+       { .compatible = "ti,wl1835" },
+       { .compatible = "ti,wl1837" },
+       { }
+};
+
+static int wlcore_probe_of(struct device *dev, int *irq,
+                          struct wlcore_platdev_data *pdev_data)
+{
+       struct device_node *np = dev->of_node;
+
+       if (!np || !of_match_node(wlcore_sdio_of_match_table, np))
+               return -ENODATA;
+
+       *irq = irq_of_parse_and_map(np, 0);
+       if (!*irq) {
+               dev_err(dev, "No irq in platform data\n");
+               kfree(pdev_data);
+               return -EINVAL;
+       }
+
+       /* optional clock frequency params */
+       of_property_read_u32(np, "ref-clock-frequency",
+                            &pdev_data->ref_clock_freq);
+       of_property_read_u32(np, "tcxo-clock-frequency",
+                            &pdev_data->tcxo_clock_freq);
+
+       return 0;
+}
+#else
+static int wlcore_probe_of(struct device *dev, int *irq,
+                          struct wlcore_platdev_data *pdev_data)
+{
+       return -ENODATA;
+}
+#endif
+
 static int wl1271_probe(struct sdio_func *func,
                                  const struct sdio_device_id *id)
 {
@@ -222,6 +269,7 @@ static int wl1271_probe(struct sdio_func *func,
        struct resource res[1];
        mmc_pm_flag_t mmcflags;
        int ret = -ENOMEM;
+       int irq;
        const char *chip_family;
 
        /* We are only able to handle the wlan function */
@@ -245,19 +293,15 @@ static int wl1271_probe(struct sdio_func *func,
        /* Use block mode for transferring over one block size of data */
        func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
 
-       pdev_data.pdata = wl12xx_get_platform_data();
-       if (IS_ERR(pdev_data.pdata)) {
-               ret = PTR_ERR(pdev_data.pdata);
-               dev_err(glue->dev, "missing wlan platform data: %d\n", ret);
+       if (wlcore_probe_of(&func->dev, &irq, &pdev_data))
                goto out_free_glue;
-       }
 
        /* if sdio can keep power while host is suspended, enable wow */
        mmcflags = sdio_get_host_pm_caps(func);
        dev_dbg(glue->dev, "sdio PM caps = 0x%x\n", mmcflags);
 
        if (mmcflags & MMC_PM_KEEP_POWER)
-               pdev_data.pdata->pwr_in_suspend = true;
+               pdev_data.pwr_in_suspend = true;
 
        sdio_set_drvdata(func, glue);
 
@@ -286,8 +330,9 @@ static int wl1271_probe(struct sdio_func *func,
 
        memset(res, 0x00, sizeof(res));
 
-       res[0].start = pdev_data.pdata->irq;
-       res[0].flags = IORESOURCE_IRQ;
+       res[0].start = irq;
+       res[0].flags = IORESOURCE_IRQ |
+                      irqd_get_trigger_type(irq_get_irq_data(irq));
        res[0].name = "irq";
 
        ret = platform_device_add_resources(glue->core, res, ARRAY_SIZE(res));
index 69601f6741d9dde900df6162fc4c7ee485123c3a..f1ac2839d97cb22fc20a96f9a8fe07e70eda9012 100644 (file)
@@ -331,11 +331,7 @@ static int wl1271_probe(struct spi_device *spi)
 
        memset(&pdev_data, 0x00, sizeof(pdev_data));
 
-       pdev_data.pdata = dev_get_platdata(&spi->dev);
-       if (!pdev_data.pdata) {
-               dev_err(&spi->dev, "no platform data\n");
-               return -ENODEV;
-       }
+       /* TODO: add DT parsing when needed */
 
        pdev_data.if_ops = &spi_ops;
 
index d599c869e6e881af451c7ea56ef3a718137b9a25..7f363fa566a3478b24e354abd3dadacb19275e6a 100644 (file)
@@ -197,6 +197,8 @@ struct wl1271 {
 
        int irq;
 
+       int irq_flags;
+
        spinlock_t wl_lock;
 
        enum wlcore_state state;
@@ -404,9 +406,6 @@ struct wl1271 {
        /* Quirks of specific hardware revisions */
        unsigned int quirks;
 
-       /* Platform limitations */
-       unsigned int platform_quirks;
-
        /* number of currently active RX BA sessions */
        int ba_rx_session_count;
 
index 3396ce5a934d1d815206d0c9fe639cb7f2f2b697..39efc6d78b10dd743f65c0b96dfe72f86747afe3 100644 (file)
@@ -201,8 +201,12 @@ struct wl1271_if_operations {
 };
 
 struct wlcore_platdev_data {
-       struct wl12xx_platform_data *pdata;
        struct wl1271_if_operations *if_ops;
+
+       bool ref_clock_xtal;    /* specify whether the clock is XTAL or not */
+       u32 ref_clock_freq;     /* in Hertz */
+       u32 tcxo_clock_freq;    /* in Hertz, tcxo is always XTAL */
+       bool pwr_in_suspend;
 };
 
 #define MAX_NUM_KEYS 14
index 1470b52278341a79ab1e0304cdd915888045cfb6..07bb3c8f191bed56c6c2293d68cefb3a6aa678ac 100644 (file)
@@ -50,7 +50,7 @@ config OF_ADDRESS_PCI
 
 config OF_IRQ
        def_bool y
-       depends on !SPARC
+       depends on !SPARC && IRQ_DOMAIN
 
 config OF_NET
        depends on NETDEVICES
index a1aa0c7dee50c59d51bcf6a672b34f10107be27d..99764db0875aa0e1b34ca348ca1606c2a8990258 100644 (file)
@@ -567,6 +567,29 @@ bool of_device_is_available(const struct device_node *device)
 }
 EXPORT_SYMBOL(of_device_is_available);
 
+/**
+ *  of_device_is_big_endian - check if a device has BE registers
+ *
+ *  @device: Node to check for endianness
+ *
+ *  Returns true if the device has a "big-endian" property, or if the kernel
+ *  was compiled for BE *and* the device has a "native-endian" property.
+ *  Returns false otherwise.
+ *
+ *  Callers would nominally use ioread32be/iowrite32be if
+ *  of_device_is_big_endian() == true, or readl/writel otherwise.
+ */
+bool of_device_is_big_endian(const struct device_node *device)
+{
+       if (of_property_read_bool(device, "big-endian"))
+               return true;
+       if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) &&
+           of_property_read_bool(device, "native-endian"))
+               return true;
+       return false;
+}
+EXPORT_SYMBOL(of_device_is_big_endian);
+
 /**
  *     of_get_parent - Get a node's parent if any
  *     @node:  Node to get parent
@@ -640,8 +663,9 @@ static struct device_node *__of_get_next_child(const struct device_node *node,
  *     @node:  parent node
  *     @prev:  previous child of the parent node, or NULL to get first
  *
- *     Returns a node pointer with refcount incremented, use
- *     of_node_put() on it when done.
+ *     Returns a node pointer with refcount incremented, use of_node_put() on
+ *     it when done. Returns NULL when prev is the last child. Decrements the
+ *     refcount of prev.
  */
 struct device_node *of_get_next_child(const struct device_node *node,
        struct device_node *prev)
index 3a896c9aeb7464ccf9ba067e27d601316fc1c879..cde35c5d0191bd5950c7953d5b8e88a2d139306f 100644 (file)
@@ -108,6 +108,25 @@ int of_fdt_is_compatible(const void *blob,
        return 0;
 }
 
+/**
+ * of_fdt_is_big_endian - Return true if given node needs BE MMIO accesses
+ * @blob: A device tree blob
+ * @node: node to test
+ *
+ * Returns true if the node has a "big-endian" property, or if the kernel
+ * was compiled for BE *and* the node has a "native-endian" property.
+ * Returns false otherwise.
+ */
+bool of_fdt_is_big_endian(const void *blob, unsigned long node)
+{
+       if (fdt_getprop(blob, node, "big-endian", NULL))
+               return true;
+       if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) &&
+           fdt_getprop(blob, node, "native-endian", NULL))
+               return true;
+       return false;
+}
+
 /**
  * of_fdt_match - Return true if node matches a list of compatible values
  */
@@ -172,7 +191,7 @@ static void * unflatten_dt_node(void *blob,
        if (!pathp)
                return mem;
 
-       allocl = l++;
+       allocl = ++l;
 
        /* version 0x10 has a more compact unit name here instead of the full
         * path. we accumulate the full path size using "fpsize", we'll rebuild
@@ -879,8 +898,7 @@ int __init early_init_dt_scan_memory(unsigned long node, const char *uname,
 
        endp = reg + (l / sizeof(__be32));
 
-       pr_debug("memory scan node %s, reg size %d, data: %x %x %x %x,\n",
-           uname, l, reg[0], reg[1], reg[2], reg[3]);
+       pr_debug("memory scan node %s, reg size %d,\n", uname, l);
 
        while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
                u64 base, size;
index e844907c9efa5edeb9f9a98babace1c70a9e1833..18016341d5a91656b29220b414faddae48188648 100644 (file)
@@ -23,6 +23,8 @@
 #include <linux/i2c.h>
 #include <linux/i2c-mux.h>
 
+#include <linux/bitops.h>
+
 #include "of_private.h"
 
 static struct unittest_results {
@@ -1109,6 +1111,59 @@ static const char *overlay_path(int nr)
 
 static const char *bus_path = "/testcase-data/overlay-node/test-bus";
 
+/* it is guaranteed that overlay ids are assigned in sequence */
+#define MAX_UNITTEST_OVERLAYS  256
+static unsigned long overlay_id_bits[BITS_TO_LONGS(MAX_UNITTEST_OVERLAYS)];
+static int overlay_first_id = -1;
+
+static void of_unittest_track_overlay(int id)
+{
+       if (overlay_first_id < 0)
+               overlay_first_id = id;
+       id -= overlay_first_id;
+
+       /* we shouldn't need that many */
+       BUG_ON(id >= MAX_UNITTEST_OVERLAYS);
+       overlay_id_bits[BIT_WORD(id)] |= BIT_MASK(id);
+}
+
+static void of_unittest_untrack_overlay(int id)
+{
+       if (overlay_first_id < 0)
+               return;
+       id -= overlay_first_id;
+       BUG_ON(id >= MAX_UNITTEST_OVERLAYS);
+       overlay_id_bits[BIT_WORD(id)] &= ~BIT_MASK(id);
+}
+
+static void of_unittest_destroy_tracked_overlays(void)
+{
+       int id, ret, defers;
+
+       if (overlay_first_id < 0)
+               return;
+
+       /* try until no defers */
+       do {
+               defers = 0;
+               /* remove in reverse order */
+               for (id = MAX_UNITTEST_OVERLAYS - 1; id >= 0; id--) {
+                       if (!(overlay_id_bits[BIT_WORD(id)] & BIT_MASK(id)))
+                               continue;
+
+                       ret = of_overlay_destroy(id + overlay_first_id);
+                       if (ret != 0) {
+                               defers++;
+                               pr_warn("%s: overlay destroy failed for #%d\n",
+                                       __func__, id + overlay_first_id);
+                               continue;
+                       }
+
+                       overlay_id_bits[BIT_WORD(id)] &= ~BIT_MASK(id);
+               }
+       } while (defers > 0);
+}
+
 static int of_unittest_apply_overlay(int unittest_nr, int overlay_nr,
                int *overlay_id)
 {
@@ -1130,6 +1185,7 @@ static int of_unittest_apply_overlay(int unittest_nr, int overlay_nr,
                goto out;
        }
        id = ret;
+       of_unittest_track_overlay(id);
 
        ret = 0;
 
@@ -1343,6 +1399,7 @@ static void of_unittest_overlay_6(void)
                        return;
                }
                ov_id[i] = ret;
+               of_unittest_track_overlay(ov_id[i]);
        }
 
        for (i = 0; i < 2; i++) {
@@ -1367,6 +1424,7 @@ static void of_unittest_overlay_6(void)
                                                PDEV_OVERLAY));
                        return;
                }
+               of_unittest_untrack_overlay(ov_id[i]);
        }
 
        for (i = 0; i < 2; i++) {
@@ -1411,6 +1469,7 @@ static void of_unittest_overlay_8(void)
                        return;
                }
                ov_id[i] = ret;
+               of_unittest_track_overlay(ov_id[i]);
        }
 
        /* now try to remove first overlay (it should fail) */
@@ -1433,6 +1492,7 @@ static void of_unittest_overlay_8(void)
                                                PDEV_OVERLAY));
                        return;
                }
+               of_unittest_untrack_overlay(ov_id[i]);
        }
 
        unittest(1, "overlay test %d passed\n", 8);
@@ -1855,6 +1915,8 @@ static void __init of_unittest_overlay(void)
        of_unittest_overlay_i2c_cleanup();
 #endif
 
+       of_unittest_destroy_tracked_overlays();
+
 out:
        of_node_put(bus_np);
 }
index 3f493459378faa15d4cfe872af18b0970b19d98c..dd92c5edf219453aac0bb98d161fc1136395f1c7 100644 (file)
@@ -138,22 +138,22 @@ static int __oprofilefs_create_file(struct dentry *root, char const *name,
        struct dentry *dentry;
        struct inode *inode;
 
-       mutex_lock(&root->d_inode->i_mutex);
+       mutex_lock(&d_inode(root)->i_mutex);
        dentry = d_alloc_name(root, name);
        if (!dentry) {
-               mutex_unlock(&root->d_inode->i_mutex);
+               mutex_unlock(&d_inode(root)->i_mutex);
                return -ENOMEM;
        }
        inode = oprofilefs_get_inode(root->d_sb, S_IFREG | perm);
        if (!inode) {
                dput(dentry);
-               mutex_unlock(&root->d_inode->i_mutex);
+               mutex_unlock(&d_inode(root)->i_mutex);
                return -ENOMEM;
        }
        inode->i_fop = fops;
        inode->i_private = priv;
        d_add(dentry, inode);
-       mutex_unlock(&root->d_inode->i_mutex);
+       mutex_unlock(&d_inode(root)->i_mutex);
        return 0;
 }
 
@@ -215,22 +215,22 @@ struct dentry *oprofilefs_mkdir(struct dentry *parent, char const *name)
        struct dentry *dentry;
        struct inode *inode;
 
-       mutex_lock(&parent->d_inode->i_mutex);
+       mutex_lock(&d_inode(parent)->i_mutex);
        dentry = d_alloc_name(parent, name);
        if (!dentry) {
-               mutex_unlock(&parent->d_inode->i_mutex);
+               mutex_unlock(&d_inode(parent)->i_mutex);
                return NULL;
        }
        inode = oprofilefs_get_inode(parent->d_sb, S_IFDIR | 0755);
        if (!inode) {
                dput(dentry);
-               mutex_unlock(&parent->d_inode->i_mutex);
+               mutex_unlock(&d_inode(parent)->i_mutex);
                return NULL;
        }
        inode->i_op = &simple_dir_inode_operations;
        inode->i_fop = &simple_dir_operations;
        d_add(dentry, inode);
-       mutex_unlock(&parent->d_inode->i_mutex);
+       mutex_unlock(&d_inode(parent)->i_mutex);
        return dentry;
 }
 
index 6bc16809c504e57e39df0dfc8fee05945cd55e4f..02ff84fcfa61289f33d7a53f8f1eb16c6b871082 100644 (file)
@@ -916,7 +916,7 @@ ccio_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
        /* Fast path single entry scatterlists. */
        if (nents == 1) {
                sg_dma_address(sglist) = ccio_map_single(dev,
-                               (void *)sg_virt_addr(sglist), sglist->length,
+                               sg_virt(sglist), sglist->length,
                                direction);
                sg_dma_len(sglist) = sglist->length;
                return 1;
@@ -983,8 +983,8 @@ ccio_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents,
        BUG_ON(!dev);
        ioc = GET_IOC(dev);
 
-       DBG_RUN_SG("%s() START %d entries,  %08lx,%x\n",
-               __func__, nents, sg_virt_addr(sglist), sglist->length);
+       DBG_RUN_SG("%s() START %d entries, %p,%x\n",
+               __func__, nents, sg_virt(sglist), sglist->length);
 
 #ifdef CCIO_COLLECT_STATS
        ioc->usg_calls++;
index 8c33491b21fe75b7b38fddcab4022676d274db43..761e77bfce5d2f43f251ebb74f82245d52c5f5f3 100644 (file)
@@ -30,9 +30,9 @@ iommu_fill_pdir(struct ioc *ioc, struct scatterlist *startsg, int nents,
                unsigned long vaddr;
                long size;
 
-               DBG_RUN_SG(" %d : %08lx/%05x %08lx/%05x\n", nents,
+               DBG_RUN_SG(" %d : %08lx/%05x %p/%05x\n", nents,
                           (unsigned long)sg_dma_address(startsg), cnt,
-                          sg_virt_addr(startsg), startsg->length
+                          sg_virt(startsg), startsg->length
                );
 
 
@@ -66,7 +66,7 @@ iommu_fill_pdir(struct ioc *ioc, struct scatterlist *startsg, int nents,
                
                BUG_ON(pdirp == NULL);
                
-               vaddr = sg_virt_addr(startsg);
+               vaddr = (unsigned long)sg_virt(startsg);
                sg_dma_len(dma_sg) += startsg->length;
                size = startsg->length + dma_offset;
                dma_offset = 0;
@@ -113,7 +113,7 @@ iommu_coalesce_chunks(struct ioc *ioc, struct device *dev,
                */
                contig_sg = startsg;
                dma_len = startsg->length;
-               dma_offset = sg_virt_addr(startsg) & ~IOVP_MASK;
+               dma_offset = startsg->offset;
 
                /* PARANOID: clear entries */
                sg_dma_address(startsg) = 0;
@@ -124,14 +124,13 @@ iommu_coalesce_chunks(struct ioc *ioc, struct device *dev,
                ** it's always looking one "ahead".
                */
                while(--nents > 0) {
-                       unsigned long prevstartsg_end, startsg_end;
+                       unsigned long prev_end, sg_start;
 
-                       prevstartsg_end = sg_virt_addr(startsg) +
-                               startsg->length;
+                       prev_end = (unsigned long)sg_virt(startsg) +
+                                                       startsg->length;
 
                        startsg++;
-                       startsg_end = sg_virt_addr(startsg) + 
-                               startsg->length;
+                       sg_start = (unsigned long)sg_virt(startsg);
 
                        /* PARANOID: clear entries */
                        sg_dma_address(startsg) = 0;
@@ -150,10 +149,13 @@ iommu_coalesce_chunks(struct ioc *ioc, struct device *dev,
                                break;
 
                        /*
-                       ** Next see if we can append the next chunk (i.e.
-                       ** it must end on one page and begin on another
+                       * Next see if we can append the next chunk (i.e.
+                       * it must end on one page and begin on another, or
+                       * it must start on the same address as the previous
+                       * entry ended.
                        */
-                       if (unlikely(((prevstartsg_end | sg_virt_addr(startsg)) & ~PAGE_MASK) != 0))
+                       if (unlikely((prev_end != sg_start) ||
+                               ((prev_end | sg_start) & ~PAGE_MASK)))
                                break;
                        
                        dma_len += startsg->length;
index f074712646891beb529bced0219551e62030bf58..f1441e466c06cd12218d01f6f527c5485a78cdac 100644 (file)
@@ -278,7 +278,7 @@ sba_dump_sg( struct ioc *ioc, struct scatterlist *startsg, int nents)
                                nents,
                                (unsigned long) sg_dma_address(startsg),
                                sg_dma_len(startsg),
-                               sg_virt_addr(startsg), startsg->length);
+                               sg_virt(startsg), startsg->length);
                startsg++;
        }
 }
@@ -945,8 +945,7 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
 
        /* Fast path single entry scatterlists. */
        if (nents == 1) {
-               sg_dma_address(sglist) = sba_map_single(dev,
-                                               (void *)sg_virt_addr(sglist),
+               sg_dma_address(sglist) = sba_map_single(dev, sg_virt(sglist),
                                                sglist->length, direction);
                sg_dma_len(sglist)     = sglist->length;
                return 1;
@@ -1025,7 +1024,7 @@ sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents,
 #endif
 
        DBG_RUN_SG("%s() START %d entries,  %p,%x\n",
-               __func__, nents, sg_virt_addr(sglist), sglist->length);
+               __func__, nents, sg_virt(sglist), sglist->length);
 
        ioc = GET_IOC(dev);
 
index 45f67c63d38539a091fde716bb0c5aa8a18b2b8b..a65f821f52eb2ab882754cb16e9af9ae5b3ea06b 100644 (file)
@@ -275,6 +275,7 @@ config BFIN_CFPCMCIA
 
 config AT91_CF
        tristate "AT91 CompactFlash Controller"
+       depends on PCI
        depends on PCMCIA && ARCH_AT91
        depends on !ARCH_MULTIPLATFORM
        help
index bfb799c7b343a055edd97b621c1f85f8ed79e873..e7775a41ae5d11f397012194e20daa1ebf05d9b9 100644 (file)
@@ -317,13 +317,14 @@ static int at91_cf_probe(struct platform_device *pdev)
        } else
                cf->socket.pci_irq = nr_irqs + 1;
 
-       /* pcmcia layer only remaps "real" memory not iospace */
-       cf->socket.io_offset = (unsigned long) devm_ioremap(&pdev->dev,
-                                       cf->phys_baseaddr + CF_IO_PHYS, SZ_2K);
-       if (!cf->socket.io_offset) {
-               status = -ENXIO;
+       /*
+        * pcmcia layer only remaps "real" memory not iospace
+        * io_offset is set to 0x10000 to avoid the check in static_find_io().
+        * */
+       cf->socket.io_offset = 0x10000;
+       status = pci_ioremap_io(0x10000, cf->phys_baseaddr + CF_IO_PHYS);
+       if (status)
                goto fail0a;
-       }
 
        /* reserve chip-select regions */
        if (!devm_request_mem_region(&pdev->dev, io->start, resource_size(io), "at91_cf")) {
index 8170102d1e9389d166396b5699ea480f2ec2e099..4e2f501e55486dbee297865f03148e5b46d09d91 100644 (file)
@@ -220,9 +220,7 @@ static int __init omap_cf_probe(struct platform_device *pdev)
        cf = kzalloc(sizeof *cf, GFP_KERNEL);
        if (!cf)
                return -ENOMEM;
-       init_timer(&cf->timer);
-       cf->timer.function = omap_cf_timer;
-       cf->timer.data = (unsigned long) cf;
+       setup_timer(&cf->timer, omap_cf_timer, (unsigned long)cf);
 
        cf->pdev = pdev;
        platform_set_drvdata(pdev, cf);
index 34ace4854dc242513730582b5a51bbcdaf730cce..0f70b4d58f9e7c2d8bb2b9b6c0dc00d2dca3f308 100644 (file)
@@ -707,11 +707,9 @@ static int pd6729_pci_probe(struct pci_dev *dev,
                }
        } else {
                /* poll Card status change */
-               init_timer(&socket->poll_timer);
-               socket->poll_timer.function = pd6729_interrupt_wrapper;
-               socket->poll_timer.data = (unsigned long)socket;
-               socket->poll_timer.expires = jiffies + HZ;
-               add_timer(&socket->poll_timer);
+               setup_timer(&socket->poll_timer, pd6729_interrupt_wrapper,
+                           (unsigned long)socket);
+               mod_timer(&socket->poll_timer, jiffies + HZ);
        }
 
        for (i = 0; i < MAX_SOCKETS; i++) {
index 933f4657515b56f170bdda60558a2bc9e9a1222c..eed5e9c05353c2fafb30b4b0cc8745472b44aff8 100644 (file)
@@ -726,9 +726,8 @@ int soc_pcmcia_add_one(struct soc_pcmcia_socket *skt)
 {
        int ret;
 
-       init_timer(&skt->poll_timer);
-       skt->poll_timer.function = soc_common_pcmcia_poll_event;
-       skt->poll_timer.data = (unsigned long)skt;
+       setup_timer(&skt->poll_timer, soc_common_pcmcia_poll_event,
+                   (unsigned long)skt);
        skt->poll_timer.expires = jiffies + SOC_PCMCIA_POLL_PERIOD;
 
        ret = request_resource(&iomem_resource, &skt->res_skt);
index 8a23ccb41213762317216a8cd10e7be0138638be..965bd84912335868ad92f995bcbe6b553b65da37 100644 (file)
@@ -1236,11 +1236,9 @@ static int yenta_probe(struct pci_dev *dev, const struct pci_device_id *id)
        if (!socket->cb_irq || request_irq(socket->cb_irq, yenta_interrupt, IRQF_SHARED, "yenta", socket)) {
                /* No IRQ or request_irq failed. Poll */
                socket->cb_irq = 0; /* But zero is a valid IRQ number. */
-               init_timer(&socket->poll_timer);
-               socket->poll_timer.function = yenta_interrupt_wrapper;
-               socket->poll_timer.data = (unsigned long)socket;
-               socket->poll_timer.expires = jiffies + HZ;
-               add_timer(&socket->poll_timer);
+               setup_timer(&socket->poll_timer, yenta_interrupt_wrapper,
+                           (unsigned long)socket);
+               mod_timer(&socket->poll_timer, jiffies + HZ);
                dev_printk(KERN_INFO, &dev->dev,
                           "no PCI IRQ, CardBus support disabled for this "
                           "socket.\n");
index c6f299ba25cb6c9d610507e138c7eb57dc535268..aeb5729fbda61976de6501ec75ca26c2628c623c 100644 (file)
@@ -95,9 +95,11 @@ config PINCTRL_FALCON
 
 config PINCTRL_MESON
        bool
+       depends on OF
        select PINMUX
        select PINCONF
        select GENERIC_PINCONF
+       select GPIOLIB
        select OF_GPIO
        select REGMAP_MMIO
 
@@ -229,7 +231,8 @@ config PINCTRL_XWAY
 
 config PINCTRL_TB10X
        bool
-       depends on ARC_PLAT_TB10X
+       depends on OF && ARC_PLAT_TB10X
+       select GPIOLIB
 
 endmenu
 
index 89dca77ca0382e93909188cad63ccd9ef6bff41b..18ee2089df4ae84e7edb6f665146be84ca43b83f 100644 (file)
@@ -1110,7 +1110,7 @@ void devm_pinctrl_put(struct pinctrl *p)
 EXPORT_SYMBOL_GPL(devm_pinctrl_put);
 
 int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps,
-                        bool dup, bool locked)
+                        bool dup)
 {
        int i, ret;
        struct pinctrl_maps *maps_node;
@@ -1178,11 +1178,9 @@ int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps,
                maps_node->maps = maps;
        }
 
-       if (!locked)
-               mutex_lock(&pinctrl_maps_mutex);
+       mutex_lock(&pinctrl_maps_mutex);
        list_add_tail(&maps_node->node, &pinctrl_maps);
-       if (!locked)
-               mutex_unlock(&pinctrl_maps_mutex);
+       mutex_unlock(&pinctrl_maps_mutex);
 
        return 0;
 }
@@ -1197,7 +1195,7 @@ int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps,
 int pinctrl_register_mappings(struct pinctrl_map const *maps,
                              unsigned num_maps)
 {
-       return pinctrl_register_map(maps, num_maps, true, false);
+       return pinctrl_register_map(maps, num_maps, true);
 }
 
 void pinctrl_unregister_map(struct pinctrl_map const *map)
index 75476b3d87dafe00c6273931a4e3a137f1509dfa..b24ea846c8677ebea49ffd435c04c3de40f226b9 100644 (file)
@@ -183,7 +183,7 @@ static inline struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev,
 }
 
 int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps,
-                        bool dup, bool locked);
+                        bool dup);
 void pinctrl_unregister_map(struct pinctrl_map const *map);
 
 extern int pinctrl_force_sleep(struct pinctrl_dev *pctldev);
index eda13de2e7c0d110f5e105a84b5b19da93cadc36..0bbf7d71b2811242a5a69db9fe97389c1acde5e8 100644 (file)
@@ -92,7 +92,7 @@ static int dt_remember_or_free_map(struct pinctrl *p, const char *statename,
        dt_map->num_maps = num_maps;
        list_add_tail(&dt_map->node, &p->dt_maps);
 
-       return pinctrl_register_map(map, num_maps, false, true);
+       return pinctrl_register_map(map, num_maps, false);
 }
 
 struct pinctrl_dev *of_pinctrl_get(struct device_node *np)
index 5983cf5b2c463f28f8b52c3095a942cde6aad02d..6b3551cad111ccf4068116083ce5c06d71b14d17 100644 (file)
@@ -2,6 +2,7 @@ if ARCH_MEDIATEK || COMPILE_TEST
 
 config PINCTRL_MTK_COMMON
        bool
+       depends on OF
        select PINMUX
        select GENERIC_PINCONF
        select GPIOLIB
@@ -10,12 +11,14 @@ config PINCTRL_MTK_COMMON
 # For ARMv7 SoCs
 config PINCTRL_MT8135
        bool "Mediatek MT8135 pin control" if COMPILE_TEST && !MACH_MT8135
+       depends on OF
        default MACH_MT8135
        select PINCTRL_MTK_COMMON
 
 # For ARMv8 SoCs
 config PINCTRL_MT8173
        bool "Mediatek MT8173 pin control"
+       depends on OF
        depends on ARM64 || COMPILE_TEST
        default ARM64 && ARCH_MEDIATEK
        select PINCTRL_MTK_COMMON
index 493294c0ebe6faccf0dc8c0e5f15b98ddf9d76b0..474812e2b0cb97c806402fda486ab2e883398c06 100644 (file)
@@ -881,6 +881,8 @@ static int mtk_gpio_set_debounce(struct gpio_chip *chip, unsigned offset,
        if (!mtk_eint_get_mask(pctl, eint_num)) {
                mtk_eint_mask(d);
                unmask = 1;
+       } else {
+               unmask = 0;
        }
 
        clr_bit = 0xff << eint_offset;
index 42f930f70de31e9086d4d7f7fec78a47d83cbfcc..03aa58c4cb85bd04cb4b043f09a1e9aec5f19cc1 100644 (file)
@@ -364,7 +364,7 @@ static struct mvebu_mpp_mode mv88f6710_mpp_modes[] = {
           MPP_FUNCTION(0x5, "audio", "mclk"),
           MPP_FUNCTION(0x6, "uart0", "cts")),
        MPP_MODE(63,
-          MPP_FUNCTION(0x0, "gpo", NULL),
+          MPP_FUNCTION(0x0, "gpio", NULL),
           MPP_FUNCTION(0x1, "spi0", "sck"),
           MPP_FUNCTION(0x2, "tclk", NULL)),
        MPP_MODE(64,
index d48a5aa24a29500dbd81c7030fce988ea163f4e0..f4fcebfce68c46808045a288d34bf7d16d8c8539 100644 (file)
@@ -30,9 +30,9 @@ if (ARCH_U8500 || ARCH_NOMADIK)
 config PINCTRL_NOMADIK
        bool "Nomadik pin controller driver"
        depends on ARCH_U8500 || ARCH_NOMADIK
+       depends on OF && GPIOLIB
        select PINMUX
        select PINCONF
-       select GPIOLIB
        select OF_GPIO
        select GPIOLIB_IRQCHIP
 
index b2d22218a2582f94b2c5d0274843fa0c2d3d7162..de684ca93b5af59910077a27fb1d13e3b6d06224 100644 (file)
@@ -260,6 +260,7 @@ static int pmic_gpio_set_mux(struct pinctrl_dev *pctldev, unsigned function,
                        val = 1;
        }
 
+       val = val << PMIC_GPIO_REG_MODE_DIR_SHIFT;
        val |= pad->function << PMIC_GPIO_REG_MODE_FUNCTION_SHIFT;
        val |= pad->out_value & PMIC_GPIO_REG_MODE_VALUE_SHIFT;
 
index 8f36c5f9194903fd8433736499a03a61afbfb2ac..211b942ad6d544ade10ea2fa91c54e5210efa290 100644 (file)
@@ -370,6 +370,7 @@ static int pmic_mpp_set_mux(struct pinctrl_dev *pctldev, unsigned function,
                }
        }
 
+       val = val << PMIC_MPP_REG_MODE_DIR_SHIFT;
        val |= pad->function << PMIC_MPP_REG_MODE_FUNCTION_SHIFT;
        val |= pad->out_value & PMIC_MPP_REG_MODE_VALUE_MASK;
 
@@ -576,10 +577,11 @@ static void pmic_mpp_config_dbg_show(struct pinctrl_dev *pctldev,
 
                if (pad->input_enabled) {
                        ret = pmic_mpp_read(state, pad, PMIC_MPP_REG_RT_STS);
-                       if (!ret) {
-                               ret &= PMIC_MPP_REG_RT_STS_VAL_MASK;
-                               pad->out_value = ret;
-                       }
+                       if (ret < 0)
+                               return;
+
+                       ret &= PMIC_MPP_REG_RT_STS_VAL_MASK;
+                       pad->out_value = ret;
                }
 
                seq_printf(s, " %-4s", pad->output_enabled ? "out" : "in");
index 440ed776efd4c97d015cd1ebef066d2a2f528719..2a6531a5fde818fdfe5cdd7679434636f967e659 100644 (file)
@@ -4,7 +4,7 @@
 
 menuconfig CHROME_PLATFORMS
        bool "Platform support for Chrome hardware"
-       depends on X86
+       depends on X86 || ARM
        ---help---
          Say Y here to get to see options for platform support for
          various Chromebooks and Chromeboxes. This option alone does
@@ -16,8 +16,7 @@ if CHROME_PLATFORMS
 
 config CHROMEOS_LAPTOP
        tristate "Chrome OS Laptop"
-       depends on I2C
-       depends on DMI
+       depends on I2C && DMI && X86
        ---help---
          This driver instantiates i2c and smbus devices such as
          light sensors and touchpads.
@@ -27,6 +26,7 @@ config CHROMEOS_LAPTOP
 
 config CHROMEOS_PSTORE
        tristate "Chrome OS pstore support"
+       depends on X86
        ---help---
          This module instantiates the persistent storage on x86 ChromeOS
          devices. It can be used to store away console logs and crash
@@ -38,5 +38,25 @@ config CHROMEOS_PSTORE
          If you have a supported Chromebook, choose Y or M here.
          The module will be called chromeos_pstore.
 
+config CROS_EC_CHARDEV
+        tristate "Chrome OS Embedded Controller userspace device interface"
+        depends on MFD_CROS_EC
+        ---help---
+          This driver adds support to talk with the ChromeOS EC from userspace.
+
+          If you have a supported Chromebook, choose Y or M here.
+          The module will be called cros_ec_dev.
+
+config CROS_EC_LPC
+        tristate "ChromeOS Embedded Controller (LPC)"
+        depends on MFD_CROS_EC && (X86 || COMPILE_TEST)
+        help
+          If you say Y here, you get support for talking to the ChromeOS EC
+          over an LPC bus. This uses a simple byte-level protocol with a
+          checksum. This is used for userspace access only. The kernel
+          typically has its own communication methods.
+
+          To compile this driver as a module, choose M here: the
+          module will be called cros_ec_lpc.
 
 endif # CHROMEOS_PLATFORMS
index 2b860ca7450fd57bee3c70c82de4a24d53c480f0..bd8d8601e87516e851389debd281ac3e0d67b7f1 100644 (file)
@@ -1,3 +1,6 @@
 
 obj-$(CONFIG_CHROMEOS_LAPTOP)  += chromeos_laptop.o
 obj-$(CONFIG_CHROMEOS_PSTORE)  += chromeos_pstore.o
+cros_ec_devs-objs               := cros_ec_dev.o cros_ec_sysfs.o cros_ec_lightbar.o
+obj-$(CONFIG_CROS_EC_CHARDEV)   += cros_ec_devs.o
+obj-$(CONFIG_CROS_EC_LPC)       += cros_ec_lpc.o
index b84fdd6b629bc678281076df59586e460d0fc850..a04019ab9feb3636dd74d3cf7e1a09764513a5fd 100644 (file)
@@ -133,12 +133,13 @@ static struct i2c_client *__add_probed_i2c_device(
                const char *name,
                int bus,
                struct i2c_board_info *info,
-               const unsigned short *addrs)
+               const unsigned short *alt_addr_list)
 {
        const struct dmi_device *dmi_dev;
        const struct dmi_dev_onboard *dev_data;
        struct i2c_adapter *adapter;
-       struct i2c_client *client;
+       struct i2c_client *client = NULL;
+       const unsigned short addr_list[] = { info->addr, I2C_CLIENT_END };
 
        if (bus < 0)
                return NULL;
@@ -169,8 +170,28 @@ static struct i2c_client *__add_probed_i2c_device(
                return NULL;
        }
 
-       /* add the i2c device */
-       client = i2c_new_probed_device(adapter, info, addrs, NULL);
+       /*
+        * Add the i2c device. If we can't detect it at the primary
+        * address we scan secondary addresses. In any case the client
+        * structure gets assigned primary address.
+        */
+       client = i2c_new_probed_device(adapter, info, addr_list, NULL);
+       if (!client && alt_addr_list) {
+               struct i2c_board_info dummy_info = {
+                       I2C_BOARD_INFO("dummy", info->addr),
+               };
+               struct i2c_client *dummy;
+
+               dummy = i2c_new_probed_device(adapter, &dummy_info,
+                                             alt_addr_list, NULL);
+               if (dummy) {
+                       pr_debug("%s %d-%02x is probed at %02x\n",
+                                 __func__, bus, info->addr, dummy->addr);
+                       i2c_unregister_device(dummy);
+                       client = i2c_new_device(adapter, info);
+               }
+       }
+
        if (!client)
                pr_notice("%s failed to register device %d-%02x\n",
                          __func__, bus, info->addr);
@@ -254,12 +275,10 @@ static struct i2c_client *add_i2c_device(const char *name,
                                                enum i2c_adapter_type type,
                                                struct i2c_board_info *info)
 {
-       const unsigned short addr_list[] = { info->addr, I2C_CLIENT_END };
-
        return __add_probed_i2c_device(name,
                                       find_i2c_adapter_num(type),
                                       info,
-                                      addr_list);
+                                      NULL);
 }
 
 static int setup_cyapa_tp(enum i2c_adapter_type type)
@@ -275,7 +294,6 @@ static int setup_cyapa_tp(enum i2c_adapter_type type)
 static int setup_atmel_224s_tp(enum i2c_adapter_type type)
 {
        const unsigned short addr_list[] = { ATMEL_TP_I2C_BL_ADDR,
-                                            ATMEL_TP_I2C_ADDR,
                                             I2C_CLIENT_END };
        if (tp)
                return 0;
@@ -289,7 +307,6 @@ static int setup_atmel_224s_tp(enum i2c_adapter_type type)
 static int setup_atmel_1664s_ts(enum i2c_adapter_type type)
 {
        const unsigned short addr_list[] = { ATMEL_TS_I2C_BL_ADDR,
-                                            ATMEL_TS_I2C_ADDR,
                                             I2C_CLIENT_END };
        if (ts)
                return 0;
diff --git a/drivers/platform/chrome/cros_ec_dev.c b/drivers/platform/chrome/cros_ec_dev.c
new file mode 100644 (file)
index 0000000..6090d0b
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+ * cros_ec_dev - expose the Chrome OS Embedded Controller to user-space
+ *
+ * Copyright (C) 2014 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+
+#include "cros_ec_dev.h"
+
+/* Device variables */
+#define CROS_MAX_DEV 128
+static struct class *cros_class;
+static int ec_major;
+
+/* Basic communication */
+static int ec_get_version(struct cros_ec_device *ec, char *str, int maxlen)
+{
+       struct ec_response_get_version *resp;
+       static const char * const current_image_name[] = {
+               "unknown", "read-only", "read-write", "invalid",
+       };
+       struct cros_ec_command msg = {
+               .version = 0,
+               .command = EC_CMD_GET_VERSION,
+               .outdata = { 0 },
+               .outsize = 0,
+               .indata = { 0 },
+               .insize = sizeof(*resp),
+       };
+       int ret;
+
+       ret = cros_ec_cmd_xfer(ec, &msg);
+       if (ret < 0)
+               return ret;
+
+       if (msg.result != EC_RES_SUCCESS) {
+               snprintf(str, maxlen,
+                        "%s\nUnknown EC version: EC returned %d\n",
+                        CROS_EC_DEV_VERSION, msg.result);
+               return 0;
+       }
+
+       resp = (struct ec_response_get_version *)msg.indata;
+       if (resp->current_image >= ARRAY_SIZE(current_image_name))
+               resp->current_image = 3; /* invalid */
+
+       snprintf(str, maxlen, "%s\n%s\n%s\n%s\n", CROS_EC_DEV_VERSION,
+                resp->version_string_ro, resp->version_string_rw,
+                current_image_name[resp->current_image]);
+
+       return 0;
+}
+
+/* Device file ops */
+static int ec_device_open(struct inode *inode, struct file *filp)
+{
+       filp->private_data = container_of(inode->i_cdev,
+                                         struct cros_ec_device, cdev);
+       return 0;
+}
+
+static int ec_device_release(struct inode *inode, struct file *filp)
+{
+       return 0;
+}
+
+static ssize_t ec_device_read(struct file *filp, char __user *buffer,
+                             size_t length, loff_t *offset)
+{
+       struct cros_ec_device *ec = filp->private_data;
+       char msg[sizeof(struct ec_response_get_version) +
+                sizeof(CROS_EC_DEV_VERSION)];
+       size_t count;
+       int ret;
+
+       if (*offset != 0)
+               return 0;
+
+       ret = ec_get_version(ec, msg, sizeof(msg));
+       if (ret)
+               return ret;
+
+       count = min(length, strlen(msg));
+
+       if (copy_to_user(buffer, msg, count))
+               return -EFAULT;
+
+       *offset = count;
+       return count;
+}
+
+/* Ioctls */
+static long ec_device_ioctl_xcmd(struct cros_ec_device *ec, void __user *arg)
+{
+       long ret;
+       struct cros_ec_command s_cmd = { };
+
+       if (copy_from_user(&s_cmd, arg, sizeof(s_cmd)))
+               return -EFAULT;
+
+       ret = cros_ec_cmd_xfer(ec, &s_cmd);
+       /* Only copy data to userland if data was received. */
+       if (ret < 0)
+               return ret;
+
+       if (copy_to_user(arg, &s_cmd, sizeof(s_cmd)))
+               return -EFAULT;
+
+       return 0;
+}
+
+static long ec_device_ioctl_readmem(struct cros_ec_device *ec, void __user *arg)
+{
+       struct cros_ec_readmem s_mem = { };
+       long num;
+
+       /* Not every platform supports direct reads */
+       if (!ec->cmd_readmem)
+               return -ENOTTY;
+
+       if (copy_from_user(&s_mem, arg, sizeof(s_mem)))
+               return -EFAULT;
+
+       num = ec->cmd_readmem(ec, s_mem.offset, s_mem.bytes, s_mem.buffer);
+       if (num <= 0)
+               return num;
+
+       if (copy_to_user((void __user *)arg, &s_mem, sizeof(s_mem)))
+               return -EFAULT;
+
+       return 0;
+}
+
+static long ec_device_ioctl(struct file *filp, unsigned int cmd,
+                           unsigned long arg)
+{
+       struct cros_ec_device *ec = filp->private_data;
+
+       if (_IOC_TYPE(cmd) != CROS_EC_DEV_IOC)
+               return -ENOTTY;
+
+       switch (cmd) {
+       case CROS_EC_DEV_IOCXCMD:
+               return ec_device_ioctl_xcmd(ec, (void __user *)arg);
+       case CROS_EC_DEV_IOCRDMEM:
+               return ec_device_ioctl_readmem(ec, (void __user *)arg);
+       }
+
+       return -ENOTTY;
+}
+
+/* Module initialization */
+static const struct file_operations fops = {
+       .open = ec_device_open,
+       .release = ec_device_release,
+       .read = ec_device_read,
+       .unlocked_ioctl = ec_device_ioctl,
+};
+
+static int ec_device_probe(struct platform_device *pdev)
+{
+       struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent);
+       int retval = -ENOTTY;
+       dev_t devno = MKDEV(ec_major, 0);
+
+       /* Instantiate it (and remember the EC) */
+       cdev_init(&ec->cdev, &fops);
+
+       retval = cdev_add(&ec->cdev, devno, 1);
+       if (retval) {
+               dev_err(&pdev->dev, ": failed to add character device\n");
+               return retval;
+       }
+
+       ec->vdev = device_create(cros_class, NULL, devno, ec,
+                                CROS_EC_DEV_NAME);
+       if (IS_ERR(ec->vdev)) {
+               retval = PTR_ERR(ec->vdev);
+               dev_err(&pdev->dev, ": failed to create device\n");
+               cdev_del(&ec->cdev);
+               return retval;
+       }
+
+       /* Initialize extra interfaces */
+       ec_dev_sysfs_init(ec);
+       ec_dev_lightbar_init(ec);
+
+       return 0;
+}
+
+static int ec_device_remove(struct platform_device *pdev)
+{
+       struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent);
+
+       ec_dev_lightbar_remove(ec);
+       ec_dev_sysfs_remove(ec);
+       device_destroy(cros_class, MKDEV(ec_major, 0));
+       cdev_del(&ec->cdev);
+       return 0;
+}
+
+static struct platform_driver cros_ec_dev_driver = {
+       .driver = {
+               .name = "cros-ec-ctl",
+       },
+       .probe = ec_device_probe,
+       .remove = ec_device_remove,
+};
+
+static int __init cros_ec_dev_init(void)
+{
+       int ret;
+       dev_t dev = 0;
+
+       cros_class = class_create(THIS_MODULE, "chromeos");
+       if (IS_ERR(cros_class)) {
+               pr_err(CROS_EC_DEV_NAME ": failed to register device class\n");
+               return PTR_ERR(cros_class);
+       }
+
+       /* Get a range of minor numbers (starting with 0) to work with */
+       ret = alloc_chrdev_region(&dev, 0, CROS_MAX_DEV, CROS_EC_DEV_NAME);
+       if (ret < 0) {
+               pr_err(CROS_EC_DEV_NAME ": alloc_chrdev_region() failed\n");
+               goto failed_chrdevreg;
+       }
+       ec_major = MAJOR(dev);
+
+       /* Register the driver */
+       ret = platform_driver_register(&cros_ec_dev_driver);
+       if (ret < 0) {
+               pr_warn(CROS_EC_DEV_NAME ": can't register driver: %d\n", ret);
+               goto failed_devreg;
+       }
+       return 0;
+
+failed_devreg:
+       unregister_chrdev_region(MKDEV(ec_major, 0), CROS_MAX_DEV);
+failed_chrdevreg:
+       class_destroy(cros_class);
+       return ret;
+}
+
+static void __exit cros_ec_dev_exit(void)
+{
+       platform_driver_unregister(&cros_ec_dev_driver);
+       unregister_chrdev(ec_major, CROS_EC_DEV_NAME);
+       class_destroy(cros_class);
+}
+
+module_init(cros_ec_dev_init);
+module_exit(cros_ec_dev_exit);
+
+MODULE_AUTHOR("Bill Richardson <wfrichar@chromium.org>");
+MODULE_DESCRIPTION("Userspace interface to the Chrome OS Embedded Controller");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/platform/chrome/cros_ec_dev.h b/drivers/platform/chrome/cros_ec_dev.h
new file mode 100644 (file)
index 0000000..45d67f7
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * cros_ec_dev - expose the Chrome OS Embedded Controller to userspace
+ *
+ * Copyright (C) 2014 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.
+ *
+ * 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 _CROS_EC_DEV_H_
+#define _CROS_EC_DEV_H_
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+#include <linux/mfd/cros_ec.h>
+
+#define CROS_EC_DEV_NAME "cros_ec"
+#define CROS_EC_DEV_VERSION "1.0.0"
+
+/*
+ * @offset: within EC_LPC_ADDR_MEMMAP region
+ * @bytes: number of bytes to read. zero means "read a string" (including '\0')
+ *         (at most only EC_MEMMAP_SIZE bytes can be read)
+ * @buffer: where to store the result
+ * ioctl returns the number of bytes read, negative on error
+ */
+struct cros_ec_readmem {
+       uint32_t offset;
+       uint32_t bytes;
+       uint8_t buffer[EC_MEMMAP_SIZE];
+};
+
+#define CROS_EC_DEV_IOC       0xEC
+#define CROS_EC_DEV_IOCXCMD   _IOWR(CROS_EC_DEV_IOC, 0, struct cros_ec_command)
+#define CROS_EC_DEV_IOCRDMEM  _IOWR(CROS_EC_DEV_IOC, 1, struct cros_ec_readmem)
+
+void ec_dev_sysfs_init(struct cros_ec_device *);
+void ec_dev_sysfs_remove(struct cros_ec_device *);
+
+void ec_dev_lightbar_init(struct cros_ec_device *);
+void ec_dev_lightbar_remove(struct cros_ec_device *);
+
+#endif /* _CROS_EC_DEV_H_ */
diff --git a/drivers/platform/chrome/cros_ec_lightbar.c b/drivers/platform/chrome/cros_ec_lightbar.c
new file mode 100644 (file)
index 0000000..b4ff47a
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+ * cros_ec_lightbar - expose the Chromebook Pixel lightbar to userspace
+ *
+ * Copyright (C) 2014 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define pr_fmt(fmt) "cros_ec_lightbar: " fmt
+
+#include <linux/ctype.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/kobject.h>
+#include <linux/mfd/cros_ec.h>
+#include <linux/mfd/cros_ec_commands.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+
+#include "cros_ec_dev.h"
+
+/* Rate-limit the lightbar interface to prevent DoS. */
+static unsigned long lb_interval_jiffies = 50 * HZ / 1000;
+
+static ssize_t interval_msec_show(struct device *dev,
+                                 struct device_attribute *attr, char *buf)
+{
+       unsigned long msec = lb_interval_jiffies * 1000 / HZ;
+
+       return scnprintf(buf, PAGE_SIZE, "%lu\n", msec);
+}
+
+static ssize_t interval_msec_store(struct device *dev,
+                                  struct device_attribute *attr,
+                                  const char *buf, size_t count)
+{
+       unsigned long msec;
+
+       if (kstrtoul(buf, 0, &msec))
+               return -EINVAL;
+
+       lb_interval_jiffies = msec * HZ / 1000;
+
+       return count;
+}
+
+static DEFINE_MUTEX(lb_mutex);
+/* Return 0 if able to throttle correctly, error otherwise */
+static int lb_throttle(void)
+{
+       static unsigned long last_access;
+       unsigned long now, next_timeslot;
+       long delay;
+       int ret = 0;
+
+       mutex_lock(&lb_mutex);
+
+       now = jiffies;
+       next_timeslot = last_access + lb_interval_jiffies;
+
+       if (time_before(now, next_timeslot)) {
+               delay = (long)(next_timeslot) - (long)now;
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (schedule_timeout(delay) > 0) {
+                       /* interrupted - just abort */
+                       ret = -EINTR;
+                       goto out;
+               }
+               now = jiffies;
+       }
+
+       last_access = now;
+out:
+       mutex_unlock(&lb_mutex);
+
+       return ret;
+}
+
+#define INIT_MSG(P, R) { \
+               .command = EC_CMD_LIGHTBAR_CMD, \
+               .outsize = sizeof(*P), \
+               .insize = sizeof(*R), \
+       }
+
+static int get_lightbar_version(struct cros_ec_device *ec,
+                               uint32_t *ver_ptr, uint32_t *flg_ptr)
+{
+       struct ec_params_lightbar *param;
+       struct ec_response_lightbar *resp;
+       struct cros_ec_command msg = INIT_MSG(param, resp);
+       int ret;
+
+       param = (struct ec_params_lightbar *)msg.outdata;
+       param->cmd = LIGHTBAR_CMD_VERSION;
+       ret = cros_ec_cmd_xfer(ec, &msg);
+       if (ret < 0)
+               return 0;
+
+       switch (msg.result) {
+       case EC_RES_INVALID_PARAM:
+               /* Pixel had no version command. */
+               if (ver_ptr)
+                       *ver_ptr = 0;
+               if (flg_ptr)
+                       *flg_ptr = 0;
+               return 1;
+
+       case EC_RES_SUCCESS:
+               resp = (struct ec_response_lightbar *)msg.indata;
+
+               /* Future devices w/lightbars should implement this command */
+               if (ver_ptr)
+                       *ver_ptr = resp->version.num;
+               if (flg_ptr)
+                       *flg_ptr = resp->version.flags;
+               return 1;
+       }
+
+       /* Anything else (ie, EC_RES_INVALID_COMMAND) - no lightbar */
+       return 0;
+}
+
+static ssize_t version_show(struct device *dev,
+                           struct device_attribute *attr, char *buf)
+{
+       uint32_t version, flags;
+       struct cros_ec_device *ec = dev_get_drvdata(dev);
+       int ret;
+
+       ret = lb_throttle();
+       if (ret)
+               return ret;
+
+       /* This should always succeed, because we check during init. */
+       if (!get_lightbar_version(ec, &version, &flags))
+               return -EIO;
+
+       return scnprintf(buf, PAGE_SIZE, "%d %d\n", version, flags);
+}
+
+static ssize_t brightness_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count)
+{
+       struct ec_params_lightbar *param;
+       struct ec_response_lightbar *resp;
+       struct cros_ec_command msg = INIT_MSG(param, resp);
+       int ret;
+       unsigned int val;
+       struct cros_ec_device *ec = dev_get_drvdata(dev);
+
+       if (kstrtouint(buf, 0, &val))
+               return -EINVAL;
+
+       param = (struct ec_params_lightbar *)msg.outdata;
+       param->cmd = LIGHTBAR_CMD_BRIGHTNESS;
+       param->brightness.num = val;
+       ret = lb_throttle();
+       if (ret)
+               return ret;
+
+       ret = cros_ec_cmd_xfer(ec, &msg);
+       if (ret < 0)
+               return ret;
+
+       if (msg.result != EC_RES_SUCCESS)
+               return -EINVAL;
+
+       return count;
+}
+
+
+/*
+ * We expect numbers, and we'll keep reading until we find them, skipping over
+ * any whitespace (sysfs guarantees that the input is null-terminated). Every
+ * four numbers are sent to the lightbar as <LED,R,G,B>. We fail at the first
+ * parsing error, if we don't parse any numbers, or if we have numbers left
+ * over.
+ */
+static ssize_t led_rgb_store(struct device *dev, struct device_attribute *attr,
+                            const char *buf, size_t count)
+{
+       struct ec_params_lightbar *param;
+       struct ec_response_lightbar *resp;
+       struct cros_ec_command msg = INIT_MSG(param, resp);
+       struct cros_ec_device *ec = dev_get_drvdata(dev);
+       unsigned int val[4];
+       int ret, i = 0, j = 0, ok = 0;
+
+       do {
+               /* Skip any whitespace */
+               while (*buf && isspace(*buf))
+                       buf++;
+
+               if (!*buf)
+                       break;
+
+               ret = sscanf(buf, "%i", &val[i++]);
+               if (ret == 0)
+                       return -EINVAL;
+
+               if (i == 4) {
+                       param = (struct ec_params_lightbar *)msg.outdata;
+                       param->cmd = LIGHTBAR_CMD_RGB;
+                       param->rgb.led = val[0];
+                       param->rgb.red = val[1];
+                       param->rgb.green = val[2];
+                       param->rgb.blue = val[3];
+                       /*
+                        * Throttle only the first of every four transactions,
+                        * so that the user can update all four LEDs at once.
+                        */
+                       if ((j++ % 4) == 0) {
+                               ret = lb_throttle();
+                               if (ret)
+                                       return ret;
+                       }
+
+                       ret = cros_ec_cmd_xfer(ec, &msg);
+                       if (ret < 0)
+                               return ret;
+
+                       if (msg.result != EC_RES_SUCCESS)
+                               return -EINVAL;
+
+                       i = 0;
+                       ok = 1;
+               }
+
+               /* Skip over the number we just read */
+               while (*buf && !isspace(*buf))
+                       buf++;
+
+       } while (*buf);
+
+       return (ok && i == 0) ? count : -EINVAL;
+}
+
+static char const *seqname[] = {
+       "ERROR", "S5", "S3", "S0", "S5S3", "S3S0",
+       "S0S3", "S3S5", "STOP", "RUN", "PULSE", "TEST", "KONAMI",
+};
+
+static ssize_t sequence_show(struct device *dev,
+                            struct device_attribute *attr, char *buf)
+{
+       struct ec_params_lightbar *param;
+       struct ec_response_lightbar *resp;
+       struct cros_ec_command msg = INIT_MSG(param, resp);
+       int ret;
+       struct cros_ec_device *ec = dev_get_drvdata(dev);
+
+       param = (struct ec_params_lightbar *)msg.outdata;
+       param->cmd = LIGHTBAR_CMD_GET_SEQ;
+       ret = lb_throttle();
+       if (ret)
+               return ret;
+
+       ret = cros_ec_cmd_xfer(ec, &msg);
+       if (ret < 0)
+               return ret;
+
+       if (msg.result != EC_RES_SUCCESS)
+               return scnprintf(buf, PAGE_SIZE,
+                                "ERROR: EC returned %d\n", msg.result);
+
+       resp = (struct ec_response_lightbar *)msg.indata;
+       if (resp->get_seq.num >= ARRAY_SIZE(seqname))
+               return scnprintf(buf, PAGE_SIZE, "%d\n", resp->get_seq.num);
+       else
+               return scnprintf(buf, PAGE_SIZE, "%s\n",
+                                seqname[resp->get_seq.num]);
+}
+
+static ssize_t sequence_store(struct device *dev, struct device_attribute *attr,
+                             const char *buf, size_t count)
+{
+       struct ec_params_lightbar *param;
+       struct ec_response_lightbar *resp;
+       struct cros_ec_command msg = INIT_MSG(param, resp);
+       unsigned int num;
+       int ret, len;
+       struct cros_ec_device *ec = dev_get_drvdata(dev);
+
+       for (len = 0; len < count; len++)
+               if (!isalnum(buf[len]))
+                       break;
+
+       for (num = 0; num < ARRAY_SIZE(seqname); num++)
+               if (!strncasecmp(seqname[num], buf, len))
+                       break;
+
+       if (num >= ARRAY_SIZE(seqname)) {
+               ret = kstrtouint(buf, 0, &num);
+               if (ret)
+                       return ret;
+       }
+
+       param = (struct ec_params_lightbar *)msg.outdata;
+       param->cmd = LIGHTBAR_CMD_SEQ;
+       param->seq.num = num;
+       ret = lb_throttle();
+       if (ret)
+               return ret;
+
+       ret = cros_ec_cmd_xfer(ec, &msg);
+       if (ret < 0)
+               return ret;
+
+       if (msg.result != EC_RES_SUCCESS)
+               return -EINVAL;
+
+       return count;
+}
+
+/* Module initialization */
+
+static DEVICE_ATTR_RW(interval_msec);
+static DEVICE_ATTR_RO(version);
+static DEVICE_ATTR_WO(brightness);
+static DEVICE_ATTR_WO(led_rgb);
+static DEVICE_ATTR_RW(sequence);
+static struct attribute *__lb_cmds_attrs[] = {
+       &dev_attr_interval_msec.attr,
+       &dev_attr_version.attr,
+       &dev_attr_brightness.attr,
+       &dev_attr_led_rgb.attr,
+       &dev_attr_sequence.attr,
+       NULL,
+};
+static struct attribute_group lb_cmds_attr_group = {
+       .name = "lightbar",
+       .attrs = __lb_cmds_attrs,
+};
+
+void ec_dev_lightbar_init(struct cros_ec_device *ec)
+{
+       int ret = 0;
+
+       /* Only instantiate this stuff if the EC has a lightbar */
+       if (!get_lightbar_version(ec, NULL, NULL))
+               return;
+
+       ret = sysfs_create_group(&ec->vdev->kobj, &lb_cmds_attr_group);
+       if (ret)
+               pr_warn("sysfs_create_group() failed: %d\n", ret);
+}
+
+void ec_dev_lightbar_remove(struct cros_ec_device *ec)
+{
+       sysfs_remove_group(&ec->vdev->kobj, &lb_cmds_attr_group);
+}
diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c
new file mode 100644 (file)
index 0000000..8f9ac4d
--- /dev/null
@@ -0,0 +1,319 @@
+/*
+ * cros_ec_lpc - LPC access to the Chrome OS Embedded Controller
+ *
+ * Copyright (C) 2012-2015 Google, Inc
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This driver uses the Chrome OS EC byte-level message-based protocol for
+ * communicating the keyboard state (which keys are pressed) from a keyboard EC
+ * to the AP over some bus (such as i2c, lpc, spi).  The EC does debouncing,
+ * but everything else (including deghosting) is done here.  The main
+ * motivation for this is to keep the EC firmware as simple as possible, since
+ * it cannot be easily upgraded and EC flash/IRAM space is relatively
+ * expensive.
+ */
+
+#include <linux/dmi.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/mfd/cros_ec.h>
+#include <linux/mfd/cros_ec_commands.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+
+#define DRV_NAME "cros_ec_lpc"
+
+static int ec_response_timed_out(void)
+{
+       unsigned long one_second = jiffies + HZ;
+
+       usleep_range(200, 300);
+       do {
+               if (!(inb(EC_LPC_ADDR_HOST_CMD) & EC_LPC_STATUS_BUSY_MASK))
+                       return 0;
+               usleep_range(100, 200);
+       } while (time_before(jiffies, one_second));
+
+       return 1;
+}
+
+static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
+                               struct cros_ec_command *msg)
+{
+       struct ec_lpc_host_args args;
+       int csum;
+       int i;
+       int ret = 0;
+
+       if (msg->outsize > EC_PROTO2_MAX_PARAM_SIZE ||
+           msg->insize > EC_PROTO2_MAX_PARAM_SIZE) {
+               dev_err(ec->dev,
+                       "invalid buffer sizes (out %d, in %d)\n",
+                       msg->outsize, msg->insize);
+               return -EINVAL;
+       }
+
+       /* Now actually send the command to the EC and get the result */
+       args.flags = EC_HOST_ARGS_FLAG_FROM_HOST;
+       args.command_version = msg->version;
+       args.data_size = msg->outsize;
+
+       /* Initialize checksum */
+       csum = msg->command + args.flags +
+               args.command_version + args.data_size;
+
+       /* Copy data and update checksum */
+       for (i = 0; i < msg->outsize; i++) {
+               outb(msg->outdata[i], EC_LPC_ADDR_HOST_PARAM + i);
+               csum += msg->outdata[i];
+       }
+
+       /* Finalize checksum and write args */
+       args.checksum = csum & 0xFF;
+       outb(args.flags, EC_LPC_ADDR_HOST_ARGS);
+       outb(args.command_version, EC_LPC_ADDR_HOST_ARGS + 1);
+       outb(args.data_size, EC_LPC_ADDR_HOST_ARGS + 2);
+       outb(args.checksum, EC_LPC_ADDR_HOST_ARGS + 3);
+
+       /* Here we go */
+       outb(msg->command, EC_LPC_ADDR_HOST_CMD);
+
+       if (ec_response_timed_out()) {
+               dev_warn(ec->dev, "EC responsed timed out\n");
+               ret = -EIO;
+               goto done;
+       }
+
+       /* Check result */
+       msg->result = inb(EC_LPC_ADDR_HOST_DATA);
+
+       switch (msg->result) {
+       case EC_RES_SUCCESS:
+               break;
+       case EC_RES_IN_PROGRESS:
+               ret = -EAGAIN;
+               dev_dbg(ec->dev, "command 0x%02x in progress\n",
+                       msg->command);
+               goto done;
+       default:
+               dev_dbg(ec->dev, "command 0x%02x returned %d\n",
+                       msg->command, msg->result);
+       }
+
+       /* Read back args */
+       args.flags = inb(EC_LPC_ADDR_HOST_ARGS);
+       args.command_version = inb(EC_LPC_ADDR_HOST_ARGS + 1);
+       args.data_size = inb(EC_LPC_ADDR_HOST_ARGS + 2);
+       args.checksum = inb(EC_LPC_ADDR_HOST_ARGS + 3);
+
+       if (args.data_size > msg->insize) {
+               dev_err(ec->dev,
+                       "packet too long (%d bytes, expected %d)",
+                       args.data_size, msg->insize);
+               ret = -ENOSPC;
+               goto done;
+       }
+
+       /* Start calculating response checksum */
+       csum = msg->command + args.flags +
+               args.command_version + args.data_size;
+
+       /* Read response and update checksum */
+       for (i = 0; i < args.data_size; i++) {
+               msg->indata[i] = inb(EC_LPC_ADDR_HOST_PARAM + i);
+               csum += msg->indata[i];
+       }
+
+       /* Verify checksum */
+       if (args.checksum != (csum & 0xFF)) {
+               dev_err(ec->dev,
+                       "bad packet checksum, expected %02x, got %02x\n",
+                       args.checksum, csum & 0xFF);
+               ret = -EBADMSG;
+               goto done;
+       }
+
+       /* Return actual amount of data received */
+       ret = args.data_size;
+done:
+       return ret;
+}
+
+/* Returns num bytes read, or negative on error. Doesn't need locking. */
+static int cros_ec_lpc_readmem(struct cros_ec_device *ec, unsigned int offset,
+                              unsigned int bytes, void *dest)
+{
+       int i = offset;
+       char *s = dest;
+       int cnt = 0;
+
+       if (offset >= EC_MEMMAP_SIZE - bytes)
+               return -EINVAL;
+
+       /* fixed length */
+       if (bytes) {
+               for (; cnt < bytes; i++, s++, cnt++)
+                       *s = inb(EC_LPC_ADDR_MEMMAP + i);
+               return cnt;
+       }
+
+       /* string */
+       for (; i < EC_MEMMAP_SIZE; i++, s++) {
+               *s = inb(EC_LPC_ADDR_MEMMAP + i);
+               cnt++;
+               if (!*s)
+                       break;
+       }
+
+       return cnt;
+}
+
+static int cros_ec_lpc_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct cros_ec_device *ec_dev;
+       int ret;
+
+       if (!devm_request_region(dev, EC_LPC_ADDR_MEMMAP, EC_MEMMAP_SIZE,
+                                dev_name(dev))) {
+               dev_err(dev, "couldn't reserve memmap region\n");
+               return -EBUSY;
+       }
+
+       if ((inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID) != 'E') ||
+           (inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID + 1) != 'C')) {
+               dev_err(dev, "EC ID not detected\n");
+               return -ENODEV;
+       }
+
+       if (!devm_request_region(dev, EC_HOST_CMD_REGION0,
+                                EC_HOST_CMD_REGION_SIZE, dev_name(dev))) {
+               dev_err(dev, "couldn't reserve region0\n");
+               return -EBUSY;
+       }
+       if (!devm_request_region(dev, EC_HOST_CMD_REGION1,
+                                EC_HOST_CMD_REGION_SIZE, dev_name(dev))) {
+               dev_err(dev, "couldn't reserve region1\n");
+               return -EBUSY;
+       }
+
+       ec_dev = devm_kzalloc(dev, sizeof(*ec_dev), GFP_KERNEL);
+       if (!ec_dev)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, ec_dev);
+       ec_dev->dev = dev;
+       ec_dev->ec_name = pdev->name;
+       ec_dev->phys_name = dev_name(dev);
+       ec_dev->parent = dev;
+       ec_dev->cmd_xfer = cros_ec_cmd_xfer_lpc;
+       ec_dev->cmd_readmem = cros_ec_lpc_readmem;
+
+       ret = cros_ec_register(ec_dev);
+       if (ret) {
+               dev_err(dev, "couldn't register ec_dev (%d)\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int cros_ec_lpc_remove(struct platform_device *pdev)
+{
+       struct cros_ec_device *ec_dev;
+
+       ec_dev = platform_get_drvdata(pdev);
+       cros_ec_remove(ec_dev);
+
+       return 0;
+}
+
+static struct dmi_system_id cros_ec_lpc_dmi_table[] __initdata = {
+       {
+               /*
+                * Today all Chromebooks/boxes ship with Google_* as version and
+                * coreboot as bios vendor. No other systems with this
+                * combination are known to date.
+                */
+               .matches = {
+                       DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"),
+                       DMI_MATCH(DMI_BIOS_VERSION, "Google_"),
+               },
+       },
+       {
+               /* x86-link, the Chromebook Pixel. */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Link"),
+               },
+       },
+       {
+               /* x86-peppy, the Acer C720 Chromebook. */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Peppy"),
+               },
+       },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(dmi, cros_ec_lpc_dmi_table);
+
+static struct platform_driver cros_ec_lpc_driver = {
+       .driver = {
+               .name = DRV_NAME,
+       },
+       .probe = cros_ec_lpc_probe,
+       .remove = cros_ec_lpc_remove,
+};
+
+static struct platform_device cros_ec_lpc_device = {
+       .name = DRV_NAME
+};
+
+static int __init cros_ec_lpc_init(void)
+{
+       int ret;
+
+       if (!dmi_check_system(cros_ec_lpc_dmi_table)) {
+               pr_err(DRV_NAME ": unsupported system.\n");
+               return -ENODEV;
+       }
+
+       /* Register the driver */
+       ret = platform_driver_register(&cros_ec_lpc_driver);
+       if (ret) {
+               pr_err(DRV_NAME ": can't register driver: %d\n", ret);
+               return ret;
+       }
+
+       /* Register the device, and it'll get hooked up automatically */
+       ret = platform_device_register(&cros_ec_lpc_device);
+       if (ret) {
+               pr_err(DRV_NAME ": can't register device: %d\n", ret);
+               platform_driver_unregister(&cros_ec_lpc_driver);
+               return ret;
+       }
+
+       return 0;
+}
+
+static void __exit cros_ec_lpc_exit(void)
+{
+       platform_device_unregister(&cros_ec_lpc_device);
+       platform_driver_unregister(&cros_ec_lpc_driver);
+}
+
+module_init(cros_ec_lpc_init);
+module_exit(cros_ec_lpc_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ChromeOS EC LPC driver");
diff --git a/drivers/platform/chrome/cros_ec_sysfs.c b/drivers/platform/chrome/cros_ec_sysfs.c
new file mode 100644 (file)
index 0000000..fb62ab6
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ * cros_ec_sysfs - expose the Chrome OS EC through sysfs
+ *
+ * Copyright (C) 2014 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define pr_fmt(fmt) "cros_ec_sysfs: " fmt
+
+#include <linux/ctype.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/kobject.h>
+#include <linux/mfd/cros_ec.h>
+#include <linux/mfd/cros_ec_commands.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+#include <linux/stat.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+
+#include "cros_ec_dev.h"
+
+/* Accessor functions */
+
+static ssize_t show_ec_reboot(struct device *dev,
+                             struct device_attribute *attr, char *buf)
+{
+       int count = 0;
+
+       count += scnprintf(buf + count, PAGE_SIZE - count,
+                          "ro|rw|cancel|cold|disable-jump|hibernate");
+       count += scnprintf(buf + count, PAGE_SIZE - count,
+                          " [at-shutdown]\n");
+       return count;
+}
+
+static ssize_t store_ec_reboot(struct device *dev,
+                              struct device_attribute *attr,
+                              const char *buf, size_t count)
+{
+       static const struct {
+               const char * const str;
+               uint8_t cmd;
+               uint8_t flags;
+       } words[] = {
+               {"cancel",       EC_REBOOT_CANCEL, 0},
+               {"ro",           EC_REBOOT_JUMP_RO, 0},
+               {"rw",           EC_REBOOT_JUMP_RW, 0},
+               {"cold",         EC_REBOOT_COLD, 0},
+               {"disable-jump", EC_REBOOT_DISABLE_JUMP, 0},
+               {"hibernate",    EC_REBOOT_HIBERNATE, 0},
+               {"at-shutdown",  -1, EC_REBOOT_FLAG_ON_AP_SHUTDOWN},
+       };
+       struct cros_ec_command msg = { 0 };
+       struct ec_params_reboot_ec *param =
+               (struct ec_params_reboot_ec *)msg.outdata;
+       int got_cmd = 0, offset = 0;
+       int i;
+       int ret;
+       struct cros_ec_device *ec = dev_get_drvdata(dev);
+
+       param->flags = 0;
+       while (1) {
+               /* Find word to start scanning */
+               while (buf[offset] && isspace(buf[offset]))
+                       offset++;
+               if (!buf[offset])
+                       break;
+
+               for (i = 0; i < ARRAY_SIZE(words); i++) {
+                       if (!strncasecmp(words[i].str, buf+offset,
+                                        strlen(words[i].str))) {
+                               if (words[i].flags) {
+                                       param->flags |= words[i].flags;
+                               } else {
+                                       param->cmd = words[i].cmd;
+                                       got_cmd = 1;
+                               }
+                               break;
+                       }
+               }
+
+               /* On to the next word, if any */
+               while (buf[offset] && !isspace(buf[offset]))
+                       offset++;
+       }
+
+       if (!got_cmd)
+               return -EINVAL;
+
+       msg.command = EC_CMD_REBOOT_EC;
+       msg.outsize = sizeof(param);
+       ret = cros_ec_cmd_xfer(ec, &msg);
+       if (ret < 0)
+               return ret;
+       if (msg.result != EC_RES_SUCCESS) {
+               dev_dbg(ec->dev, "EC result %d\n", msg.result);
+               return -EINVAL;
+       }
+
+       return count;
+}
+
+static ssize_t show_ec_version(struct device *dev,
+                              struct device_attribute *attr, char *buf)
+{
+       static const char * const image_names[] = {"unknown", "RO", "RW"};
+       struct ec_response_get_version *r_ver;
+       struct ec_response_get_chip_info *r_chip;
+       struct ec_response_board_version *r_board;
+       struct cros_ec_command msg = { 0 };
+       int ret;
+       int count = 0;
+       struct cros_ec_device *ec = dev_get_drvdata(dev);
+
+       /* Get versions. RW may change. */
+       msg.command = EC_CMD_GET_VERSION;
+       msg.insize = sizeof(*r_ver);
+       ret = cros_ec_cmd_xfer(ec, &msg);
+       if (ret < 0)
+               return ret;
+       if (msg.result != EC_RES_SUCCESS)
+               return scnprintf(buf, PAGE_SIZE,
+                                "ERROR: EC returned %d\n", msg.result);
+
+       r_ver = (struct ec_response_get_version *)msg.indata;
+       /* Strings should be null-terminated, but let's be sure. */
+       r_ver->version_string_ro[sizeof(r_ver->version_string_ro) - 1] = '\0';
+       r_ver->version_string_rw[sizeof(r_ver->version_string_rw) - 1] = '\0';
+       count += scnprintf(buf + count, PAGE_SIZE - count,
+                          "RO version:    %s\n", r_ver->version_string_ro);
+       count += scnprintf(buf + count, PAGE_SIZE - count,
+                          "RW version:    %s\n", r_ver->version_string_rw);
+       count += scnprintf(buf + count, PAGE_SIZE - count,
+                          "Firmware copy: %s\n",
+                          (r_ver->current_image < ARRAY_SIZE(image_names) ?
+                           image_names[r_ver->current_image] : "?"));
+
+       /* Get build info. */
+       msg.command = EC_CMD_GET_BUILD_INFO;
+       msg.insize = sizeof(msg.indata);
+       ret = cros_ec_cmd_xfer(ec, &msg);
+       if (ret < 0)
+               count += scnprintf(buf + count, PAGE_SIZE - count,
+                                  "Build info:    XFER ERROR %d\n", ret);
+       else if (msg.result != EC_RES_SUCCESS)
+               count += scnprintf(buf + count, PAGE_SIZE - count,
+                                  "Build info:    EC error %d\n", msg.result);
+       else {
+               msg.indata[sizeof(msg.indata) - 1] = '\0';
+               count += scnprintf(buf + count, PAGE_SIZE - count,
+                                  "Build info:    %s\n", msg.indata);
+       }
+
+       /* Get chip info. */
+       msg.command = EC_CMD_GET_CHIP_INFO;
+       msg.insize = sizeof(*r_chip);
+       ret = cros_ec_cmd_xfer(ec, &msg);
+       if (ret < 0)
+               count += scnprintf(buf + count, PAGE_SIZE - count,
+                                  "Chip info:     XFER ERROR %d\n", ret);
+       else if (msg.result != EC_RES_SUCCESS)
+               count += scnprintf(buf + count, PAGE_SIZE - count,
+                                  "Chip info:     EC error %d\n", msg.result);
+       else {
+               r_chip = (struct ec_response_get_chip_info *)msg.indata;
+
+               r_chip->vendor[sizeof(r_chip->vendor) - 1] = '\0';
+               r_chip->name[sizeof(r_chip->name) - 1] = '\0';
+               r_chip->revision[sizeof(r_chip->revision) - 1] = '\0';
+               count += scnprintf(buf + count, PAGE_SIZE - count,
+                                  "Chip vendor:   %s\n", r_chip->vendor);
+               count += scnprintf(buf + count, PAGE_SIZE - count,
+                                  "Chip name:     %s\n", r_chip->name);
+               count += scnprintf(buf + count, PAGE_SIZE - count,
+                                  "Chip revision: %s\n", r_chip->revision);
+       }
+
+       /* Get board version */
+       msg.command = EC_CMD_GET_BOARD_VERSION;
+       msg.insize = sizeof(*r_board);
+       ret = cros_ec_cmd_xfer(ec, &msg);
+       if (ret < 0)
+               count += scnprintf(buf + count, PAGE_SIZE - count,
+                                  "Board version: XFER ERROR %d\n", ret);
+       else if (msg.result != EC_RES_SUCCESS)
+               count += scnprintf(buf + count, PAGE_SIZE - count,
+                                  "Board version: EC error %d\n", msg.result);
+       else {
+               r_board = (struct ec_response_board_version *)msg.indata;
+
+               count += scnprintf(buf + count, PAGE_SIZE - count,
+                                  "Board version: %d\n",
+                                  r_board->board_version);
+       }
+
+       return count;
+}
+
+static ssize_t show_ec_flashinfo(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       struct ec_response_flash_info *resp;
+       struct cros_ec_command msg = { 0 };
+       int ret;
+       struct cros_ec_device *ec = dev_get_drvdata(dev);
+
+       /* The flash info shouldn't ever change, but ask each time anyway. */
+       msg.command = EC_CMD_FLASH_INFO;
+       msg.insize = sizeof(*resp);
+       ret = cros_ec_cmd_xfer(ec, &msg);
+       if (ret < 0)
+               return ret;
+       if (msg.result != EC_RES_SUCCESS)
+               return scnprintf(buf, PAGE_SIZE,
+                                "ERROR: EC returned %d\n", msg.result);
+
+       resp = (struct ec_response_flash_info *)msg.indata;
+
+       return scnprintf(buf, PAGE_SIZE,
+                        "FlashSize %d\nWriteSize %d\n"
+                        "EraseSize %d\nProtectSize %d\n",
+                        resp->flash_size, resp->write_block_size,
+                        resp->erase_block_size, resp->protect_block_size);
+}
+
+/* Module initialization */
+
+static DEVICE_ATTR(reboot, S_IWUSR | S_IRUGO, show_ec_reboot, store_ec_reboot);
+static DEVICE_ATTR(version, S_IRUGO, show_ec_version, NULL);
+static DEVICE_ATTR(flashinfo, S_IRUGO, show_ec_flashinfo, NULL);
+
+static struct attribute *__ec_attrs[] = {
+       &dev_attr_reboot.attr,
+       &dev_attr_version.attr,
+       &dev_attr_flashinfo.attr,
+       NULL,
+};
+
+static struct attribute_group ec_attr_group = {
+       .attrs = __ec_attrs,
+};
+
+void ec_dev_sysfs_init(struct cros_ec_device *ec)
+{
+       int error;
+
+       error = sysfs_create_group(&ec->vdev->kobj, &ec_attr_group);
+       if (error)
+               pr_warn("failed to create group: %d\n", error);
+}
+
+void ec_dev_sysfs_remove(struct cros_ec_device *ec)
+{
+       sysfs_remove_group(&ec->vdev->kobj, &ec_attr_group);
+}
index 97527614141bf4a406528503d404ad8efd64695f..f9f205cb1f115a92617fca64002f028d1856faab 100644 (file)
@@ -614,6 +614,7 @@ config ACPI_TOSHIBA
        depends on INPUT
        depends on RFKILL || RFKILL = n
        depends on SERIO_I8042 || SERIO_I8042 = n
+       depends on ACPI_VIDEO || ACPI_VIDEO = n
        select INPUT_POLLDEV
        select INPUT_SPARSEKMAP
        ---help---
index 66d6d22c239c2b2231ca6837bc36d4cd89a9edb7..6808715003f6e7e40d6b5bb9d60c6533efff2c26 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/vga_switcheroo.h>
+#include <linux/vgaarb.h>
 #include <acpi/video.h>
 #include <asm/io.h>
 
@@ -31,6 +32,7 @@ struct apple_gmux_data {
        bool indexed;
        struct mutex index_lock;
 
+       struct pci_dev *pdev;
        struct backlight_device *bdev;
 
        /* switcheroo data */
@@ -415,6 +417,23 @@ static int gmux_resume(struct device *dev)
        return 0;
 }
 
+static struct pci_dev *gmux_get_io_pdev(void)
+{
+       struct pci_dev *pdev = NULL;
+
+       while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev))) {
+               u16 cmd;
+
+               pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+               if (!(cmd & PCI_COMMAND_IO))
+                       continue;
+
+               return pdev;
+       }
+
+       return NULL;
+}
+
 static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
 {
        struct apple_gmux_data *gmux_data;
@@ -425,6 +444,7 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
        int ret = -ENXIO;
        acpi_status status;
        unsigned long long gpe;
+       struct pci_dev *pdev = NULL;
 
        if (apple_gmux_data)
                return -EBUSY;
@@ -475,7 +495,7 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
                        ver_minor = (version >> 16) & 0xff;
                        ver_release = (version >> 8) & 0xff;
                } else {
-                       pr_info("gmux device not present\n");
+                       pr_info("gmux device not present or IO disabled\n");
                        ret = -ENODEV;
                        goto err_release;
                }
@@ -483,6 +503,23 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
        pr_info("Found gmux version %d.%d.%d [%s]\n", ver_major, ver_minor,
                ver_release, (gmux_data->indexed ? "indexed" : "classic"));
 
+       /*
+        * Apple systems with gmux are EFI based and normally don't use
+        * VGA. In addition changing IO+MEM ownership between IGP and dGPU
+        * disables IO/MEM used for backlight control on some systems.
+        * Lock IO+MEM to GPU with active IO to prevent switch.
+        */
+       pdev = gmux_get_io_pdev();
+       if (pdev && vga_tryget(pdev,
+                              VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM)) {
+               pr_err("IO+MEM vgaarb-locking for PCI:%s failed\n",
+                       pci_name(pdev));
+               ret = -EBUSY;
+               goto err_release;
+       } else if (pdev)
+               pr_info("locked IO for PCI:%s\n", pci_name(pdev));
+       gmux_data->pdev = pdev;
+
        memset(&props, 0, sizeof(props));
        props.type = BACKLIGHT_PLATFORM;
        props.max_brightness = gmux_read32(gmux_data, GMUX_PORT_MAX_BRIGHTNESS);
@@ -574,6 +611,10 @@ err_enable_gpe:
 err_notify:
        backlight_device_unregister(bdev);
 err_release:
+       if (gmux_data->pdev)
+               vga_put(gmux_data->pdev,
+                       VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM);
+       pci_dev_put(pdev);
        release_region(gmux_data->iostart, gmux_data->iolen);
 err_free:
        kfree(gmux_data);
@@ -593,6 +634,11 @@ static void gmux_remove(struct pnp_dev *pnp)
                                           &gmux_notify_handler);
        }
 
+       if (gmux_data->pdev) {
+               vga_put(gmux_data->pdev,
+                       VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM);
+               pci_dev_put(gmux_data->pdev);
+       }
        backlight_device_unregister(gmux_data->bdev);
 
        release_region(gmux_data->iostart, gmux_data->iolen);
index 3d21efe11d7b77c511ff651201ca9a14c467e058..d688d806a8a51d9845ab9c5c5bc3322e748738f3 100644 (file)
@@ -2,9 +2,11 @@
  *  Driver for Dell laptop extras
  *
  *  Copyright (c) Red Hat <mjg@redhat.com>
+ *  Copyright (c) 2014 Gabriele Mazzotta <gabriele.mzt@gmail.com>
+ *  Copyright (c) 2014 Pali Rohár <pali.rohar@gmail.com>
  *
- *  Based on documentation in the libsmbios package, Copyright (C) 2005 Dell
- *  Inc.
+ *  Based on documentation in the libsmbios package:
+ *  Copyright (C) 2005-2014 Dell 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
 #include "../../firmware/dcdbas.h"
 
 #define BRIGHTNESS_TOKEN 0x7d
+#define KBD_LED_OFF_TOKEN 0x01E1
+#define KBD_LED_ON_TOKEN 0x01E2
+#define KBD_LED_AUTO_TOKEN 0x01E3
+#define KBD_LED_AUTO_25_TOKEN 0x02EA
+#define KBD_LED_AUTO_50_TOKEN 0x02EB
+#define KBD_LED_AUTO_75_TOKEN 0x02EC
+#define KBD_LED_AUTO_100_TOKEN 0x02F6
 
 /* This structure will be modified by the firmware when we enter
  * system management mode, hence the volatiles */
@@ -62,6 +71,13 @@ struct calling_interface_structure {
 
 struct quirk_entry {
        u8 touchpad_led;
+
+       int needs_kbd_timeouts;
+       /*
+        * Ordered list of timeouts expressed in seconds.
+        * The list must end with -1
+        */
+       int kbd_timeouts[];
 };
 
 static struct quirk_entry *quirks;
@@ -76,6 +92,15 @@ static int __init dmi_matched(const struct dmi_system_id *dmi)
        return 1;
 }
 
+/*
+ * These values come from Windows utility provided by Dell. If any other value
+ * is used then BIOS silently set timeout to 0 without any error message.
+ */
+static struct quirk_entry quirk_dell_xps13_9333 = {
+       .needs_kbd_timeouts = 1,
+       .kbd_timeouts = { 0, 5, 15, 60, 5 * 60, 15 * 60, -1 },
+};
+
 static int da_command_address;
 static int da_command_code;
 static int da_num_tokens;
@@ -267,6 +292,15 @@ static const struct dmi_system_id dell_quirks[] __initconst = {
                },
                .driver_data = &quirk_dell_vostro_v130,
        },
+       {
+               .callback = dmi_matched,
+               .ident = "Dell XPS13 9333",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "XPS13 9333"),
+               },
+               .driver_data = &quirk_dell_xps13_9333,
+       },
        { }
 };
 
@@ -331,17 +365,29 @@ static void __init find_tokens(const struct dmi_header *dm, void *dummy)
        }
 }
 
-static int find_token_location(int tokenid)
+static int find_token_id(int tokenid)
 {
        int i;
+
        for (i = 0; i < da_num_tokens; i++) {
                if (da_tokens[i].tokenID == tokenid)
-                       return da_tokens[i].location;
+                       return i;
        }
 
        return -1;
 }
 
+static int find_token_location(int tokenid)
+{
+       int id;
+
+       id = find_token_id(tokenid);
+       if (id == -1)
+               return -1;
+
+       return da_tokens[id].location;
+}
+
 static struct calling_interface_buffer *
 dell_send_request(struct calling_interface_buffer *buffer, int class,
                  int select)
@@ -362,6 +408,20 @@ dell_send_request(struct calling_interface_buffer *buffer, int class,
        return buffer;
 }
 
+static inline int dell_smi_error(int value)
+{
+       switch (value) {
+       case 0: /* Completed successfully */
+               return 0;
+       case -1: /* Completed with error */
+               return -EIO;
+       case -2: /* Function not supported */
+               return -ENXIO;
+       default: /* Unknown error */
+               return -EINVAL;
+       }
+}
+
 /* Derived from information in DellWirelessCtl.cpp:
    Class 17, select 11 is radio control. It returns an array of 32-bit values.
 
@@ -716,7 +776,7 @@ static int dell_send_intensity(struct backlight_device *bd)
        else
                dell_send_request(buffer, 1, 1);
 
-out:
+ out:
        release_buffer();
        return ret;
 }
@@ -740,7 +800,7 @@ static int dell_get_intensity(struct backlight_device *bd)
 
        ret = buffer->output[1];
 
-out:
+ out:
        release_buffer();
        return ret;
 }
@@ -789,6 +849,1018 @@ static void touchpad_led_exit(void)
        led_classdev_unregister(&touchpad_led);
 }
 
+/*
+ * Derived from information in smbios-keyboard-ctl:
+ *
+ * cbClass 4
+ * cbSelect 11
+ * Keyboard illumination
+ * cbArg1 determines the function to be performed
+ *
+ * cbArg1 0x0 = Get Feature Information
+ *  cbRES1         Standard return codes (0, -1, -2)
+ *  cbRES2, word0  Bitmap of user-selectable modes
+ *     bit 0     Always off (All systems)
+ *     bit 1     Always on (Travis ATG, Siberia)
+ *     bit 2     Auto: ALS-based On; ALS-based Off (Travis ATG)
+ *     bit 3     Auto: ALS- and input-activity-based On; input-activity based Off
+ *     bit 4     Auto: Input-activity-based On; input-activity based Off
+ *     bit 5     Auto: Input-activity-based On (illumination level 25%); input-activity based Off
+ *     bit 6     Auto: Input-activity-based On (illumination level 50%); input-activity based Off
+ *     bit 7     Auto: Input-activity-based On (illumination level 75%); input-activity based Off
+ *     bit 8     Auto: Input-activity-based On (illumination level 100%); input-activity based Off
+ *     bits 9-15 Reserved for future use
+ *  cbRES2, byte2  Reserved for future use
+ *  cbRES2, byte3  Keyboard illumination type
+ *     0         Reserved
+ *     1         Tasklight
+ *     2         Backlight
+ *     3-255     Reserved for future use
+ *  cbRES3, byte0  Supported auto keyboard illumination trigger bitmap.
+ *     bit 0     Any keystroke
+ *     bit 1     Touchpad activity
+ *     bit 2     Pointing stick
+ *     bit 3     Any mouse
+ *     bits 4-7  Reserved for future use
+ *  cbRES3, byte1  Supported timeout unit bitmap
+ *     bit 0     Seconds
+ *     bit 1     Minutes
+ *     bit 2     Hours
+ *     bit 3     Days
+ *     bits 4-7  Reserved for future use
+ *  cbRES3, byte2  Number of keyboard light brightness levels
+ *  cbRES4, byte0  Maximum acceptable seconds value (0 if seconds not supported).
+ *  cbRES4, byte1  Maximum acceptable minutes value (0 if minutes not supported).
+ *  cbRES4, byte2  Maximum acceptable hours value (0 if hours not supported).
+ *  cbRES4, byte3  Maximum acceptable days value (0 if days not supported)
+ *
+ * cbArg1 0x1 = Get Current State
+ *  cbRES1         Standard return codes (0, -1, -2)
+ *  cbRES2, word0  Bitmap of current mode state
+ *     bit 0     Always off (All systems)
+ *     bit 1     Always on (Travis ATG, Siberia)
+ *     bit 2     Auto: ALS-based On; ALS-based Off (Travis ATG)
+ *     bit 3     Auto: ALS- and input-activity-based On; input-activity based Off
+ *     bit 4     Auto: Input-activity-based On; input-activity based Off
+ *     bit 5     Auto: Input-activity-based On (illumination level 25%); input-activity based Off
+ *     bit 6     Auto: Input-activity-based On (illumination level 50%); input-activity based Off
+ *     bit 7     Auto: Input-activity-based On (illumination level 75%); input-activity based Off
+ *     bit 8     Auto: Input-activity-based On (illumination level 100%); input-activity based Off
+ *     bits 9-15 Reserved for future use
+ *     Note: Only One bit can be set
+ *  cbRES2, byte2  Currently active auto keyboard illumination triggers.
+ *     bit 0     Any keystroke
+ *     bit 1     Touchpad activity
+ *     bit 2     Pointing stick
+ *     bit 3     Any mouse
+ *     bits 4-7  Reserved for future use
+ *  cbRES2, byte3  Current Timeout
+ *     bits 7:6  Timeout units indicator:
+ *     00b       Seconds
+ *     01b       Minutes
+ *     10b       Hours
+ *     11b       Days
+ *     bits 5:0  Timeout value (0-63) in sec/min/hr/day
+ *     NOTE: A value of 0 means always on (no timeout) if any bits of RES3 byte
+ *     are set upon return from the [Get feature information] call.
+ *  cbRES3, byte0  Current setting of ALS value that turns the light on or off.
+ *  cbRES3, byte1  Current ALS reading
+ *  cbRES3, byte2  Current keyboard light level.
+ *
+ * cbArg1 0x2 = Set New State
+ *  cbRES1         Standard return codes (0, -1, -2)
+ *  cbArg2, word0  Bitmap of current mode state
+ *     bit 0     Always off (All systems)
+ *     bit 1     Always on (Travis ATG, Siberia)
+ *     bit 2     Auto: ALS-based On; ALS-based Off (Travis ATG)
+ *     bit 3     Auto: ALS- and input-activity-based On; input-activity based Off
+ *     bit 4     Auto: Input-activity-based On; input-activity based Off
+ *     bit 5     Auto: Input-activity-based On (illumination level 25%); input-activity based Off
+ *     bit 6     Auto: Input-activity-based On (illumination level 50%); input-activity based Off
+ *     bit 7     Auto: Input-activity-based On (illumination level 75%); input-activity based Off
+ *     bit 8     Auto: Input-activity-based On (illumination level 100%); input-activity based Off
+ *     bits 9-15 Reserved for future use
+ *     Note: Only One bit can be set
+ *  cbArg2, byte2  Desired auto keyboard illumination triggers. Must remain inactive to allow
+ *                 keyboard to turn off automatically.
+ *     bit 0     Any keystroke
+ *     bit 1     Touchpad activity
+ *     bit 2     Pointing stick
+ *     bit 3     Any mouse
+ *     bits 4-7  Reserved for future use
+ *  cbArg2, byte3  Desired Timeout
+ *     bits 7:6  Timeout units indicator:
+ *     00b       Seconds
+ *     01b       Minutes
+ *     10b       Hours
+ *     11b       Days
+ *     bits 5:0  Timeout value (0-63) in sec/min/hr/day
+ *  cbArg3, byte0  Desired setting of ALS value that turns the light on or off.
+ *  cbArg3, byte2  Desired keyboard light level.
+ */
+
+
+enum kbd_timeout_unit {
+       KBD_TIMEOUT_SECONDS = 0,
+       KBD_TIMEOUT_MINUTES,
+       KBD_TIMEOUT_HOURS,
+       KBD_TIMEOUT_DAYS,
+};
+
+enum kbd_mode_bit {
+       KBD_MODE_BIT_OFF = 0,
+       KBD_MODE_BIT_ON,
+       KBD_MODE_BIT_ALS,
+       KBD_MODE_BIT_TRIGGER_ALS,
+       KBD_MODE_BIT_TRIGGER,
+       KBD_MODE_BIT_TRIGGER_25,
+       KBD_MODE_BIT_TRIGGER_50,
+       KBD_MODE_BIT_TRIGGER_75,
+       KBD_MODE_BIT_TRIGGER_100,
+};
+
+#define kbd_is_als_mode_bit(bit) \
+       ((bit) == KBD_MODE_BIT_ALS || (bit) == KBD_MODE_BIT_TRIGGER_ALS)
+#define kbd_is_trigger_mode_bit(bit) \
+       ((bit) >= KBD_MODE_BIT_TRIGGER_ALS && (bit) <= KBD_MODE_BIT_TRIGGER_100)
+#define kbd_is_level_mode_bit(bit) \
+       ((bit) >= KBD_MODE_BIT_TRIGGER_25 && (bit) <= KBD_MODE_BIT_TRIGGER_100)
+
+struct kbd_info {
+       u16 modes;
+       u8 type;
+       u8 triggers;
+       u8 levels;
+       u8 seconds;
+       u8 minutes;
+       u8 hours;
+       u8 days;
+};
+
+struct kbd_state {
+       u8 mode_bit;
+       u8 triggers;
+       u8 timeout_value;
+       u8 timeout_unit;
+       u8 als_setting;
+       u8 als_value;
+       u8 level;
+};
+
+static const int kbd_tokens[] = {
+       KBD_LED_OFF_TOKEN,
+       KBD_LED_AUTO_25_TOKEN,
+       KBD_LED_AUTO_50_TOKEN,
+       KBD_LED_AUTO_75_TOKEN,
+       KBD_LED_AUTO_100_TOKEN,
+       KBD_LED_ON_TOKEN,
+};
+
+static u16 kbd_token_bits;
+
+static struct kbd_info kbd_info;
+static bool kbd_als_supported;
+static bool kbd_triggers_supported;
+
+static u8 kbd_mode_levels[16];
+static int kbd_mode_levels_count;
+
+static u8 kbd_previous_level;
+static u8 kbd_previous_mode_bit;
+
+static bool kbd_led_present;
+
+/*
+ * NOTE: there are three ways to set the keyboard backlight level.
+ * First, via kbd_state.mode_bit (assigning KBD_MODE_BIT_TRIGGER_* value).
+ * Second, via kbd_state.level (assigning numerical value <= kbd_info.levels).
+ * Third, via SMBIOS tokens (KBD_LED_* in kbd_tokens)
+ *
+ * There are laptops which support only one of these methods. If we want to
+ * support as many machines as possible we need to implement all three methods.
+ * The first two methods use the kbd_state structure. The third uses SMBIOS
+ * tokens. If kbd_info.levels == 0, the machine does not support setting the
+ * keyboard backlight level via kbd_state.level.
+ */
+
+static int kbd_get_info(struct kbd_info *info)
+{
+       u8 units;
+       int ret;
+
+       get_buffer();
+
+       buffer->input[0] = 0x0;
+       dell_send_request(buffer, 4, 11);
+       ret = buffer->output[0];
+
+       if (ret) {
+               ret = dell_smi_error(ret);
+               goto out;
+       }
+
+       info->modes = buffer->output[1] & 0xFFFF;
+       info->type = (buffer->output[1] >> 24) & 0xFF;
+       info->triggers = buffer->output[2] & 0xFF;
+       units = (buffer->output[2] >> 8) & 0xFF;
+       info->levels = (buffer->output[2] >> 16) & 0xFF;
+
+       if (units & BIT(0))
+               info->seconds = (buffer->output[3] >> 0) & 0xFF;
+       if (units & BIT(1))
+               info->minutes = (buffer->output[3] >> 8) & 0xFF;
+       if (units & BIT(2))
+               info->hours = (buffer->output[3] >> 16) & 0xFF;
+       if (units & BIT(3))
+               info->days = (buffer->output[3] >> 24) & 0xFF;
+
+ out:
+       release_buffer();
+       return ret;
+}
+
+static unsigned int kbd_get_max_level(void)
+{
+       if (kbd_info.levels != 0)
+               return kbd_info.levels;
+       if (kbd_mode_levels_count > 0)
+               return kbd_mode_levels_count - 1;
+       return 0;
+}
+
+static int kbd_get_level(struct kbd_state *state)
+{
+       int i;
+
+       if (kbd_info.levels != 0)
+               return state->level;
+
+       if (kbd_mode_levels_count > 0) {
+               for (i = 0; i < kbd_mode_levels_count; ++i)
+                       if (kbd_mode_levels[i] == state->mode_bit)
+                               return i;
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static int kbd_set_level(struct kbd_state *state, u8 level)
+{
+       if (kbd_info.levels != 0) {
+               if (level != 0)
+                       kbd_previous_level = level;
+               if (state->level == level)
+                       return 0;
+               state->level = level;
+               if (level != 0 && state->mode_bit == KBD_MODE_BIT_OFF)
+                       state->mode_bit = kbd_previous_mode_bit;
+               else if (level == 0 && state->mode_bit != KBD_MODE_BIT_OFF) {
+                       kbd_previous_mode_bit = state->mode_bit;
+                       state->mode_bit = KBD_MODE_BIT_OFF;
+               }
+               return 0;
+       }
+
+       if (kbd_mode_levels_count > 0 && level < kbd_mode_levels_count) {
+               if (level != 0)
+                       kbd_previous_level = level;
+               state->mode_bit = kbd_mode_levels[level];
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static int kbd_get_state(struct kbd_state *state)
+{
+       int ret;
+
+       get_buffer();
+
+       buffer->input[0] = 0x1;
+       dell_send_request(buffer, 4, 11);
+       ret = buffer->output[0];
+
+       if (ret) {
+               ret = dell_smi_error(ret);
+               goto out;
+       }
+
+       state->mode_bit = ffs(buffer->output[1] & 0xFFFF);
+       if (state->mode_bit != 0)
+               state->mode_bit--;
+
+       state->triggers = (buffer->output[1] >> 16) & 0xFF;
+       state->timeout_value = (buffer->output[1] >> 24) & 0x3F;
+       state->timeout_unit = (buffer->output[1] >> 30) & 0x3;
+       state->als_setting = buffer->output[2] & 0xFF;
+       state->als_value = (buffer->output[2] >> 8) & 0xFF;
+       state->level = (buffer->output[2] >> 16) & 0xFF;
+
+ out:
+       release_buffer();
+       return ret;
+}
+
+static int kbd_set_state(struct kbd_state *state)
+{
+       int ret;
+
+       get_buffer();
+       buffer->input[0] = 0x2;
+       buffer->input[1] = BIT(state->mode_bit) & 0xFFFF;
+       buffer->input[1] |= (state->triggers & 0xFF) << 16;
+       buffer->input[1] |= (state->timeout_value & 0x3F) << 24;
+       buffer->input[1] |= (state->timeout_unit & 0x3) << 30;
+       buffer->input[2] = state->als_setting & 0xFF;
+       buffer->input[2] |= (state->level & 0xFF) << 16;
+       dell_send_request(buffer, 4, 11);
+       ret = buffer->output[0];
+       release_buffer();
+
+       return dell_smi_error(ret);
+}
+
+static int kbd_set_state_safe(struct kbd_state *state, struct kbd_state *old)
+{
+       int ret;
+
+       ret = kbd_set_state(state);
+       if (ret == 0)
+               return 0;
+
+       /*
+        * When setting the new state fails,try to restore the previous one.
+        * This is needed on some machines where BIOS sets a default state when
+        * setting a new state fails. This default state could be all off.
+        */
+
+       if (kbd_set_state(old))
+               pr_err("Setting old previous keyboard state failed\n");
+
+       return ret;
+}
+
+static int kbd_set_token_bit(u8 bit)
+{
+       int id;
+       int ret;
+
+       if (bit >= ARRAY_SIZE(kbd_tokens))
+               return -EINVAL;
+
+       id = find_token_id(kbd_tokens[bit]);
+       if (id == -1)
+               return -EINVAL;
+
+       get_buffer();
+       buffer->input[0] = da_tokens[id].location;
+       buffer->input[1] = da_tokens[id].value;
+       dell_send_request(buffer, 1, 0);
+       ret = buffer->output[0];
+       release_buffer();
+
+       return dell_smi_error(ret);
+}
+
+static int kbd_get_token_bit(u8 bit)
+{
+       int id;
+       int ret;
+       int val;
+
+       if (bit >= ARRAY_SIZE(kbd_tokens))
+               return -EINVAL;
+
+       id = find_token_id(kbd_tokens[bit]);
+       if (id == -1)
+               return -EINVAL;
+
+       get_buffer();
+       buffer->input[0] = da_tokens[id].location;
+       dell_send_request(buffer, 0, 0);
+       ret = buffer->output[0];
+       val = buffer->output[1];
+       release_buffer();
+
+       if (ret)
+               return dell_smi_error(ret);
+
+       return (val == da_tokens[id].value);
+}
+
+static int kbd_get_first_active_token_bit(void)
+{
+       int i;
+       int ret;
+
+       for (i = 0; i < ARRAY_SIZE(kbd_tokens); ++i) {
+               ret = kbd_get_token_bit(i);
+               if (ret == 1)
+                       return i;
+       }
+
+       return ret;
+}
+
+static int kbd_get_valid_token_counts(void)
+{
+       return hweight16(kbd_token_bits);
+}
+
+static inline int kbd_init_info(void)
+{
+       struct kbd_state state;
+       int ret;
+       int i;
+
+       ret = kbd_get_info(&kbd_info);
+       if (ret)
+               return ret;
+
+       kbd_get_state(&state);
+
+       /* NOTE: timeout value is stored in 6 bits so max value is 63 */
+       if (kbd_info.seconds > 63)
+               kbd_info.seconds = 63;
+       if (kbd_info.minutes > 63)
+               kbd_info.minutes = 63;
+       if (kbd_info.hours > 63)
+               kbd_info.hours = 63;
+       if (kbd_info.days > 63)
+               kbd_info.days = 63;
+
+       /* NOTE: On tested machines ON mode did not work and caused
+        *       problems (turned backlight off) so do not use it
+        */
+       kbd_info.modes &= ~BIT(KBD_MODE_BIT_ON);
+
+       kbd_previous_level = kbd_get_level(&state);
+       kbd_previous_mode_bit = state.mode_bit;
+
+       if (kbd_previous_level == 0 && kbd_get_max_level() != 0)
+               kbd_previous_level = 1;
+
+       if (kbd_previous_mode_bit == KBD_MODE_BIT_OFF) {
+               kbd_previous_mode_bit =
+                       ffs(kbd_info.modes & ~BIT(KBD_MODE_BIT_OFF));
+               if (kbd_previous_mode_bit != 0)
+                       kbd_previous_mode_bit--;
+       }
+
+       if (kbd_info.modes & (BIT(KBD_MODE_BIT_ALS) |
+                             BIT(KBD_MODE_BIT_TRIGGER_ALS)))
+               kbd_als_supported = true;
+
+       if (kbd_info.modes & (
+           BIT(KBD_MODE_BIT_TRIGGER_ALS) | BIT(KBD_MODE_BIT_TRIGGER) |
+           BIT(KBD_MODE_BIT_TRIGGER_25) | BIT(KBD_MODE_BIT_TRIGGER_50) |
+           BIT(KBD_MODE_BIT_TRIGGER_75) | BIT(KBD_MODE_BIT_TRIGGER_100)
+          ))
+               kbd_triggers_supported = true;
+
+       /* kbd_mode_levels[0] is reserved, see below */
+       for (i = 0; i < 16; ++i)
+               if (kbd_is_level_mode_bit(i) && (BIT(i) & kbd_info.modes))
+                       kbd_mode_levels[1 + kbd_mode_levels_count++] = i;
+
+       /*
+        * Find the first supported mode and assign to kbd_mode_levels[0].
+        * This should be 0 (off), but we cannot depend on the BIOS to
+        * support 0.
+        */
+       if (kbd_mode_levels_count > 0) {
+               for (i = 0; i < 16; ++i) {
+                       if (BIT(i) & kbd_info.modes) {
+                               kbd_mode_levels[0] = i;
+                               break;
+                       }
+               }
+               kbd_mode_levels_count++;
+       }
+
+       return 0;
+
+}
+
+static inline void kbd_init_tokens(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(kbd_tokens); ++i)
+               if (find_token_id(kbd_tokens[i]) != -1)
+                       kbd_token_bits |= BIT(i);
+}
+
+static void kbd_init(void)
+{
+       int ret;
+
+       ret = kbd_init_info();
+       kbd_init_tokens();
+
+       if (kbd_token_bits != 0 || ret == 0)
+               kbd_led_present = true;
+}
+
+static ssize_t kbd_led_timeout_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       struct kbd_state new_state;
+       struct kbd_state state;
+       bool convert;
+       int value;
+       int ret;
+       char ch;
+       u8 unit;
+       int i;
+
+       ret = sscanf(buf, "%d %c", &value, &ch);
+       if (ret < 1)
+               return -EINVAL;
+       else if (ret == 1)
+               ch = 's';
+
+       if (value < 0)
+               return -EINVAL;
+
+       convert = false;
+
+       switch (ch) {
+       case 's':
+               if (value > kbd_info.seconds)
+                       convert = true;
+               unit = KBD_TIMEOUT_SECONDS;
+               break;
+       case 'm':
+               if (value > kbd_info.minutes)
+                       convert = true;
+               unit = KBD_TIMEOUT_MINUTES;
+               break;
+       case 'h':
+               if (value > kbd_info.hours)
+                       convert = true;
+               unit = KBD_TIMEOUT_HOURS;
+               break;
+       case 'd':
+               if (value > kbd_info.days)
+                       convert = true;
+               unit = KBD_TIMEOUT_DAYS;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (quirks && quirks->needs_kbd_timeouts)
+               convert = true;
+
+       if (convert) {
+               /* Convert value from current units to seconds */
+               switch (unit) {
+               case KBD_TIMEOUT_DAYS:
+                       value *= 24;
+               case KBD_TIMEOUT_HOURS:
+                       value *= 60;
+               case KBD_TIMEOUT_MINUTES:
+                       value *= 60;
+                       unit = KBD_TIMEOUT_SECONDS;
+               }
+
+               if (quirks && quirks->needs_kbd_timeouts) {
+                       for (i = 0; quirks->kbd_timeouts[i] != -1; i++) {
+                               if (value <= quirks->kbd_timeouts[i]) {
+                                       value = quirks->kbd_timeouts[i];
+                                       break;
+                               }
+                       }
+               }
+
+               if (value <= kbd_info.seconds && kbd_info.seconds) {
+                       unit = KBD_TIMEOUT_SECONDS;
+               } else if (value / 60 <= kbd_info.minutes && kbd_info.minutes) {
+                       value /= 60;
+                       unit = KBD_TIMEOUT_MINUTES;
+               } else if (value / (60 * 60) <= kbd_info.hours && kbd_info.hours) {
+                       value /= (60 * 60);
+                       unit = KBD_TIMEOUT_HOURS;
+               } else if (value / (60 * 60 * 24) <= kbd_info.days && kbd_info.days) {
+                       value /= (60 * 60 * 24);
+                       unit = KBD_TIMEOUT_DAYS;
+               } else {
+                       return -EINVAL;
+               }
+       }
+
+       ret = kbd_get_state(&state);
+       if (ret)
+               return ret;
+
+       new_state = state;
+       new_state.timeout_value = value;
+       new_state.timeout_unit = unit;
+
+       ret = kbd_set_state_safe(&new_state, &state);
+       if (ret)
+               return ret;
+
+       return count;
+}
+
+static ssize_t kbd_led_timeout_show(struct device *dev,
+                                   struct device_attribute *attr, char *buf)
+{
+       struct kbd_state state;
+       int ret;
+       int len;
+
+       ret = kbd_get_state(&state);
+       if (ret)
+               return ret;
+
+       len = sprintf(buf, "%d", state.timeout_value);
+
+       switch (state.timeout_unit) {
+       case KBD_TIMEOUT_SECONDS:
+               return len + sprintf(buf+len, "s\n");
+       case KBD_TIMEOUT_MINUTES:
+               return len + sprintf(buf+len, "m\n");
+       case KBD_TIMEOUT_HOURS:
+               return len + sprintf(buf+len, "h\n");
+       case KBD_TIMEOUT_DAYS:
+               return len + sprintf(buf+len, "d\n");
+       default:
+               return -EINVAL;
+       }
+
+       return len;
+}
+
+static DEVICE_ATTR(stop_timeout, S_IRUGO | S_IWUSR,
+                  kbd_led_timeout_show, kbd_led_timeout_store);
+
+static const char * const kbd_led_triggers[] = {
+       "keyboard",
+       "touchpad",
+       /*"trackstick"*/ NULL, /* NOTE: trackstick is just alias for touchpad */
+       "mouse",
+};
+
+static ssize_t kbd_led_triggers_store(struct device *dev,
+                                     struct device_attribute *attr,
+                                     const char *buf, size_t count)
+{
+       struct kbd_state new_state;
+       struct kbd_state state;
+       bool triggers_enabled = false;
+       int trigger_bit = -1;
+       char trigger[21];
+       int i, ret;
+
+       ret = sscanf(buf, "%20s", trigger);
+       if (ret != 1)
+               return -EINVAL;
+
+       if (trigger[0] != '+' && trigger[0] != '-')
+               return -EINVAL;
+
+       ret = kbd_get_state(&state);
+       if (ret)
+               return ret;
+
+       if (kbd_triggers_supported)
+               triggers_enabled = kbd_is_trigger_mode_bit(state.mode_bit);
+
+       if (kbd_triggers_supported) {
+               for (i = 0; i < ARRAY_SIZE(kbd_led_triggers); ++i) {
+                       if (!(kbd_info.triggers & BIT(i)))
+                               continue;
+                       if (!kbd_led_triggers[i])
+                               continue;
+                       if (strcmp(trigger+1, kbd_led_triggers[i]) != 0)
+                               continue;
+                       if (trigger[0] == '+' &&
+                           triggers_enabled && (state.triggers & BIT(i)))
+                               return count;
+                       if (trigger[0] == '-' &&
+                           (!triggers_enabled || !(state.triggers & BIT(i))))
+                               return count;
+                       trigger_bit = i;
+                       break;
+               }
+       }
+
+       if (trigger_bit != -1) {
+               new_state = state;
+               if (trigger[0] == '+')
+                       new_state.triggers |= BIT(trigger_bit);
+               else {
+                       new_state.triggers &= ~BIT(trigger_bit);
+                       /* NOTE: trackstick bit (2) must be disabled when
+                        *       disabling touchpad bit (1), otherwise touchpad
+                        *       bit (1) will not be disabled */
+                       if (trigger_bit == 1)
+                               new_state.triggers &= ~BIT(2);
+               }
+               if ((kbd_info.triggers & new_state.triggers) !=
+                   new_state.triggers)
+                       return -EINVAL;
+               if (new_state.triggers && !triggers_enabled) {
+                       new_state.mode_bit = KBD_MODE_BIT_TRIGGER;
+                       kbd_set_level(&new_state, kbd_previous_level);
+               } else if (new_state.triggers == 0) {
+                       kbd_set_level(&new_state, 0);
+               }
+               if (!(kbd_info.modes & BIT(new_state.mode_bit)))
+                       return -EINVAL;
+               ret = kbd_set_state_safe(&new_state, &state);
+               if (ret)
+                       return ret;
+               if (new_state.mode_bit != KBD_MODE_BIT_OFF)
+                       kbd_previous_mode_bit = new_state.mode_bit;
+               return count;
+       }
+
+       return -EINVAL;
+}
+
+static ssize_t kbd_led_triggers_show(struct device *dev,
+                                    struct device_attribute *attr, char *buf)
+{
+       struct kbd_state state;
+       bool triggers_enabled;
+       int level, i, ret;
+       int len = 0;
+
+       ret = kbd_get_state(&state);
+       if (ret)
+               return ret;
+
+       len = 0;
+
+       if (kbd_triggers_supported) {
+               triggers_enabled = kbd_is_trigger_mode_bit(state.mode_bit);
+               level = kbd_get_level(&state);
+               for (i = 0; i < ARRAY_SIZE(kbd_led_triggers); ++i) {
+                       if (!(kbd_info.triggers & BIT(i)))
+                               continue;
+                       if (!kbd_led_triggers[i])
+                               continue;
+                       if ((triggers_enabled || level <= 0) &&
+                           (state.triggers & BIT(i)))
+                               buf[len++] = '+';
+                       else
+                               buf[len++] = '-';
+                       len += sprintf(buf+len, "%s ", kbd_led_triggers[i]);
+               }
+       }
+
+       if (len)
+               buf[len - 1] = '\n';
+
+       return len;
+}
+
+static DEVICE_ATTR(start_triggers, S_IRUGO | S_IWUSR,
+                  kbd_led_triggers_show, kbd_led_triggers_store);
+
+static ssize_t kbd_led_als_enabled_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count)
+{
+       struct kbd_state new_state;
+       struct kbd_state state;
+       bool triggers_enabled = false;
+       int enable;
+       int ret;
+
+       ret = kstrtoint(buf, 0, &enable);
+       if (ret)
+               return ret;
+
+       ret = kbd_get_state(&state);
+       if (ret)
+               return ret;
+
+       if (enable == kbd_is_als_mode_bit(state.mode_bit))
+               return count;
+
+       new_state = state;
+
+       if (kbd_triggers_supported)
+               triggers_enabled = kbd_is_trigger_mode_bit(state.mode_bit);
+
+       if (enable) {
+               if (triggers_enabled)
+                       new_state.mode_bit = KBD_MODE_BIT_TRIGGER_ALS;
+               else
+                       new_state.mode_bit = KBD_MODE_BIT_ALS;
+       } else {
+               if (triggers_enabled) {
+                       new_state.mode_bit = KBD_MODE_BIT_TRIGGER;
+                       kbd_set_level(&new_state, kbd_previous_level);
+               } else {
+                       new_state.mode_bit = KBD_MODE_BIT_ON;
+               }
+       }
+       if (!(kbd_info.modes & BIT(new_state.mode_bit)))
+               return -EINVAL;
+
+       ret = kbd_set_state_safe(&new_state, &state);
+       if (ret)
+               return ret;
+       kbd_previous_mode_bit = new_state.mode_bit;
+
+       return count;
+}
+
+static ssize_t kbd_led_als_enabled_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct kbd_state state;
+       bool enabled = false;
+       int ret;
+
+       ret = kbd_get_state(&state);
+       if (ret)
+               return ret;
+       enabled = kbd_is_als_mode_bit(state.mode_bit);
+
+       return sprintf(buf, "%d\n", enabled ? 1 : 0);
+}
+
+static DEVICE_ATTR(als_enabled, S_IRUGO | S_IWUSR,
+                  kbd_led_als_enabled_show, kbd_led_als_enabled_store);
+
+static ssize_t kbd_led_als_setting_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count)
+{
+       struct kbd_state state;
+       struct kbd_state new_state;
+       u8 setting;
+       int ret;
+
+       ret = kstrtou8(buf, 10, &setting);
+       if (ret)
+               return ret;
+
+       ret = kbd_get_state(&state);
+       if (ret)
+               return ret;
+
+       new_state = state;
+       new_state.als_setting = setting;
+
+       ret = kbd_set_state_safe(&new_state, &state);
+       if (ret)
+               return ret;
+
+       return count;
+}
+
+static ssize_t kbd_led_als_setting_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct kbd_state state;
+       int ret;
+
+       ret = kbd_get_state(&state);
+       if (ret)
+               return ret;
+
+       return sprintf(buf, "%d\n", state.als_setting);
+}
+
+static DEVICE_ATTR(als_setting, S_IRUGO | S_IWUSR,
+                  kbd_led_als_setting_show, kbd_led_als_setting_store);
+
+static struct attribute *kbd_led_attrs[] = {
+       &dev_attr_stop_timeout.attr,
+       &dev_attr_start_triggers.attr,
+       NULL,
+};
+
+static const struct attribute_group kbd_led_group = {
+       .attrs = kbd_led_attrs,
+};
+
+static struct attribute *kbd_led_als_attrs[] = {
+       &dev_attr_als_enabled.attr,
+       &dev_attr_als_setting.attr,
+       NULL,
+};
+
+static const struct attribute_group kbd_led_als_group = {
+       .attrs = kbd_led_als_attrs,
+};
+
+static const struct attribute_group *kbd_led_groups[] = {
+       &kbd_led_group,
+       &kbd_led_als_group,
+       NULL,
+};
+
+static enum led_brightness kbd_led_level_get(struct led_classdev *led_cdev)
+{
+       int ret;
+       u16 num;
+       struct kbd_state state;
+
+       if (kbd_get_max_level()) {
+               ret = kbd_get_state(&state);
+               if (ret)
+                       return 0;
+               ret = kbd_get_level(&state);
+               if (ret < 0)
+                       return 0;
+               return ret;
+       }
+
+       if (kbd_get_valid_token_counts()) {
+               ret = kbd_get_first_active_token_bit();
+               if (ret < 0)
+                       return 0;
+               for (num = kbd_token_bits; num != 0 && ret > 0; --ret)
+                       num &= num - 1; /* clear the first bit set */
+               if (num == 0)
+                       return 0;
+               return ffs(num) - 1;
+       }
+
+       pr_warn("Keyboard brightness level control not supported\n");
+       return 0;
+}
+
+static void kbd_led_level_set(struct led_classdev *led_cdev,
+                             enum led_brightness value)
+{
+       struct kbd_state state;
+       struct kbd_state new_state;
+       u16 num;
+
+       if (kbd_get_max_level()) {
+               if (kbd_get_state(&state))
+                       return;
+               new_state = state;
+               if (kbd_set_level(&new_state, value))
+                       return;
+               kbd_set_state_safe(&new_state, &state);
+               return;
+       }
+
+       if (kbd_get_valid_token_counts()) {
+               for (num = kbd_token_bits; num != 0 && value > 0; --value)
+                       num &= num - 1; /* clear the first bit set */
+               if (num == 0)
+                       return;
+               kbd_set_token_bit(ffs(num) - 1);
+               return;
+       }
+
+       pr_warn("Keyboard brightness level control not supported\n");
+}
+
+static struct led_classdev kbd_led = {
+       .name           = "dell::kbd_backlight",
+       .brightness_set = kbd_led_level_set,
+       .brightness_get = kbd_led_level_get,
+       .groups         = kbd_led_groups,
+};
+
+static int __init kbd_led_init(struct device *dev)
+{
+       kbd_init();
+       if (!kbd_led_present)
+               return -ENODEV;
+       if (!kbd_als_supported)
+               kbd_led_groups[1] = NULL;
+       kbd_led.max_brightness = kbd_get_max_level();
+       if (!kbd_led.max_brightness) {
+               kbd_led.max_brightness = kbd_get_valid_token_counts();
+               if (kbd_led.max_brightness)
+                       kbd_led.max_brightness--;
+       }
+       return led_classdev_register(dev, &kbd_led);
+}
+
+static void brightness_set_exit(struct led_classdev *led_cdev,
+                               enum led_brightness value)
+{
+       /* Don't change backlight level on exit */
+};
+
+static void kbd_led_exit(void)
+{
+       if (!kbd_led_present)
+               return;
+       kbd_led.brightness_set = brightness_set_exit;
+       led_classdev_unregister(&kbd_led);
+}
+
 static int __init dell_init(void)
 {
        int max_intensity = 0;
@@ -841,6 +1913,8 @@ static int __init dell_init(void)
        if (quirks && quirks->touchpad_led)
                touchpad_led_init(&platform_device->dev);
 
+       kbd_led_init(&platform_device->dev);
+
        dell_laptop_dir = debugfs_create_dir("dell_laptop", NULL);
        if (dell_laptop_dir != NULL)
                debugfs_create_file("rfkill", 0444, dell_laptop_dir, NULL,
@@ -908,6 +1982,7 @@ static void __exit dell_exit(void)
        debugfs_remove_recursive(dell_laptop_dir);
        if (quirks && quirks->touchpad_led)
                touchpad_led_exit();
+       kbd_led_exit();
        i8042_remove_filter(dell_laptop_i8042_filter);
        cancel_delayed_work_sync(&dell_rfkill_work);
        backlight_device_unregister(dell_backlight_device);
@@ -924,5 +1999,7 @@ module_init(dell_init);
 module_exit(dell_exit);
 
 MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
+MODULE_AUTHOR("Gabriele Mazzotta <gabriele.mzt@gmail.com>");
+MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>");
 MODULE_DESCRIPTION("Dell laptop driver");
 MODULE_LICENSE("GPL");
index b3d419a8472341dabee36c3cb40765157be443a9..b496db87bc0505368fe4501b6199f653f7a257e0 100644 (file)
@@ -829,6 +829,13 @@ static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data)
  * report all radios as hardware-blocked.
  */
 static const struct dmi_system_id no_hw_rfkill_list[] = {
+       {
+               .ident = "Lenovo G40-30",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo G40-30"),
+               },
+       },
        {
                .ident = "Lenovo Yoga 2 11 / 13 / Pro",
                .matches = {
index a4a4258f613447a83bd90bfcb9408aa5c557c39d..8037c8b46241e12e615e1f634774d053877ae673 100644 (file)
@@ -62,7 +62,7 @@
  * (1 << 1):   Bluetooth enable/disable, RW.
  * (1 << 2):   GPS enable/disable, RW.
  * (1 << 3):   WiFi enable/disable, RW.
- * (1 << 4):   WWAN (3G) enable/disalbe, RW.
+ * (1 << 4):   WWAN (3G) enable/disable, RW.
  * (1 << 5):   Touchscreen enable/disable, Read Only.
  */
 #define OT_EC_DEVICE_STATE_ADDRESS     0xD6
index 3b8ceee7c5cbfd891c87a5fd58c59017db5f34e8..9bb9ad6d4a1b1b1c3600cd283f240d2479a80841 100644 (file)
@@ -319,6 +319,7 @@ static struct {
        u32 sensors_pdrv_attrs_registered:1;
        u32 sensors_pdev_attrs_registered:1;
        u32 hotkey_poll_active:1;
+       u32 has_adaptive_kbd:1;
 } tp_features;
 
 static struct {
@@ -1911,6 +1912,27 @@ enum {   /* hot key scan codes (derived from ACPI DSDT) */
        TP_ACPI_HOTKEYSCAN_UNK7,
        TP_ACPI_HOTKEYSCAN_UNK8,
 
+       TP_ACPI_HOTKEYSCAN_MUTE2,
+       TP_ACPI_HOTKEYSCAN_BRIGHTNESS_ZERO,
+       TP_ACPI_HOTKEYSCAN_CLIPPING_TOOL,
+       TP_ACPI_HOTKEYSCAN_CLOUD,
+       TP_ACPI_HOTKEYSCAN_UNK9,
+       TP_ACPI_HOTKEYSCAN_VOICE,
+       TP_ACPI_HOTKEYSCAN_UNK10,
+       TP_ACPI_HOTKEYSCAN_GESTURES,
+       TP_ACPI_HOTKEYSCAN_UNK11,
+       TP_ACPI_HOTKEYSCAN_UNK12,
+       TP_ACPI_HOTKEYSCAN_UNK13,
+       TP_ACPI_HOTKEYSCAN_CONFIG,
+       TP_ACPI_HOTKEYSCAN_NEW_TAB,
+       TP_ACPI_HOTKEYSCAN_RELOAD,
+       TP_ACPI_HOTKEYSCAN_BACK,
+       TP_ACPI_HOTKEYSCAN_MIC_DOWN,
+       TP_ACPI_HOTKEYSCAN_MIC_UP,
+       TP_ACPI_HOTKEYSCAN_MIC_CANCELLATION,
+       TP_ACPI_HOTKEYSCAN_CAMERA_MODE,
+       TP_ACPI_HOTKEYSCAN_ROTATE_DISPLAY,
+
        /* Hotkey keymap size */
        TPACPI_HOTKEY_MAP_LEN
 };
@@ -2093,7 +2115,7 @@ static int hotkey_mask_get(void)
        return 0;
 }
 
-void static hotkey_mask_warn_incomplete_mask(void)
+static void hotkey_mask_warn_incomplete_mask(void)
 {
        /* log only what the user can fix... */
        const u32 wantedmask = hotkey_driver_mask &
@@ -2647,9 +2669,7 @@ static ssize_t hotkey_enable_store(struct device *dev,
        return count;
 }
 
-static struct device_attribute dev_attr_hotkey_enable =
-       __ATTR(hotkey_enable, S_IWUSR | S_IRUGO,
-               hotkey_enable_show, hotkey_enable_store);
+static DEVICE_ATTR_RW(hotkey_enable);
 
 /* sysfs hotkey mask --------------------------------------------------- */
 static ssize_t hotkey_mask_show(struct device *dev,
@@ -2685,9 +2705,7 @@ static ssize_t hotkey_mask_store(struct device *dev,
        return (res) ? res : count;
 }
 
-static struct device_attribute dev_attr_hotkey_mask =
-       __ATTR(hotkey_mask, S_IWUSR | S_IRUGO,
-               hotkey_mask_show, hotkey_mask_store);
+static DEVICE_ATTR_RW(hotkey_mask);
 
 /* sysfs hotkey bios_enabled ------------------------------------------- */
 static ssize_t hotkey_bios_enabled_show(struct device *dev,
@@ -2697,8 +2715,7 @@ static ssize_t hotkey_bios_enabled_show(struct device *dev,
        return sprintf(buf, "0\n");
 }
 
-static struct device_attribute dev_attr_hotkey_bios_enabled =
-       __ATTR(hotkey_bios_enabled, S_IRUGO, hotkey_bios_enabled_show, NULL);
+static DEVICE_ATTR_RO(hotkey_bios_enabled);
 
 /* sysfs hotkey bios_mask ---------------------------------------------- */
 static ssize_t hotkey_bios_mask_show(struct device *dev,
@@ -2710,8 +2727,7 @@ static ssize_t hotkey_bios_mask_show(struct device *dev,
        return snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_orig_mask);
 }
 
-static struct device_attribute dev_attr_hotkey_bios_mask =
-       __ATTR(hotkey_bios_mask, S_IRUGO, hotkey_bios_mask_show, NULL);
+static DEVICE_ATTR_RO(hotkey_bios_mask);
 
 /* sysfs hotkey all_mask ----------------------------------------------- */
 static ssize_t hotkey_all_mask_show(struct device *dev,
@@ -2722,8 +2738,7 @@ static ssize_t hotkey_all_mask_show(struct device *dev,
                                hotkey_all_mask | hotkey_source_mask);
 }
 
-static struct device_attribute dev_attr_hotkey_all_mask =
-       __ATTR(hotkey_all_mask, S_IRUGO, hotkey_all_mask_show, NULL);
+static DEVICE_ATTR_RO(hotkey_all_mask);
 
 /* sysfs hotkey recommended_mask --------------------------------------- */
 static ssize_t hotkey_recommended_mask_show(struct device *dev,
@@ -2735,9 +2750,7 @@ static ssize_t hotkey_recommended_mask_show(struct device *dev,
                        & ~hotkey_reserved_mask);
 }
 
-static struct device_attribute dev_attr_hotkey_recommended_mask =
-       __ATTR(hotkey_recommended_mask, S_IRUGO,
-               hotkey_recommended_mask_show, NULL);
+static DEVICE_ATTR_RO(hotkey_recommended_mask);
 
 #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
 
@@ -2792,9 +2805,7 @@ static ssize_t hotkey_source_mask_store(struct device *dev,
        return (rc < 0) ? rc : count;
 }
 
-static struct device_attribute dev_attr_hotkey_source_mask =
-       __ATTR(hotkey_source_mask, S_IWUSR | S_IRUGO,
-               hotkey_source_mask_show, hotkey_source_mask_store);
+static DEVICE_ATTR_RW(hotkey_source_mask);
 
 /* sysfs hotkey hotkey_poll_freq --------------------------------------- */
 static ssize_t hotkey_poll_freq_show(struct device *dev,
@@ -2826,9 +2837,7 @@ static ssize_t hotkey_poll_freq_store(struct device *dev,
        return count;
 }
 
-static struct device_attribute dev_attr_hotkey_poll_freq =
-       __ATTR(hotkey_poll_freq, S_IWUSR | S_IRUGO,
-               hotkey_poll_freq_show, hotkey_poll_freq_store);
+static DEVICE_ATTR_RW(hotkey_poll_freq);
 
 #endif /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */
 
@@ -2849,8 +2858,7 @@ static ssize_t hotkey_radio_sw_show(struct device *dev,
                        (res == TPACPI_RFK_RADIO_OFF) ? 0 : 1);
 }
 
-static struct device_attribute dev_attr_hotkey_radio_sw =
-       __ATTR(hotkey_radio_sw, S_IRUGO, hotkey_radio_sw_show, NULL);
+static DEVICE_ATTR_RO(hotkey_radio_sw);
 
 static void hotkey_radio_sw_notify_change(void)
 {
@@ -2872,8 +2880,7 @@ static ssize_t hotkey_tablet_mode_show(struct device *dev,
        return snprintf(buf, PAGE_SIZE, "%d\n", !!s);
 }
 
-static struct device_attribute dev_attr_hotkey_tablet_mode =
-       __ATTR(hotkey_tablet_mode, S_IRUGO, hotkey_tablet_mode_show, NULL);
+static DEVICE_ATTR_RO(hotkey_tablet_mode);
 
 static void hotkey_tablet_mode_notify_change(void)
 {
@@ -2890,8 +2897,7 @@ static ssize_t hotkey_wakeup_reason_show(struct device *dev,
        return snprintf(buf, PAGE_SIZE, "%d\n", hotkey_wakeup_reason);
 }
 
-static struct device_attribute dev_attr_hotkey_wakeup_reason =
-       __ATTR(wakeup_reason, S_IRUGO, hotkey_wakeup_reason_show, NULL);
+static DEVICE_ATTR_RO(hotkey_wakeup_reason);
 
 static void hotkey_wakeup_reason_notify_change(void)
 {
@@ -2907,9 +2913,7 @@ static ssize_t hotkey_wakeup_hotunplug_complete_show(struct device *dev,
        return snprintf(buf, PAGE_SIZE, "%d\n", hotkey_autosleep_ack);
 }
 
-static struct device_attribute dev_attr_hotkey_wakeup_hotunplug_complete =
-       __ATTR(wakeup_hotunplug_complete, S_IRUGO,
-              hotkey_wakeup_hotunplug_complete_show, NULL);
+static DEVICE_ATTR_RO(hotkey_wakeup_hotunplug_complete);
 
 static void hotkey_wakeup_hotunplug_complete_notify_change(void)
 {
@@ -2917,6 +2921,57 @@ static void hotkey_wakeup_hotunplug_complete_notify_change(void)
                     "wakeup_hotunplug_complete");
 }
 
+/* sysfs adaptive kbd mode --------------------------------------------- */
+
+static int adaptive_keyboard_get_mode(void);
+static int adaptive_keyboard_set_mode(int new_mode);
+
+enum ADAPTIVE_KEY_MODE {
+       HOME_MODE,
+       WEB_BROWSER_MODE,
+       WEB_CONFERENCE_MODE,
+       FUNCTION_MODE,
+       LAYFLAT_MODE
+};
+
+static ssize_t adaptive_kbd_mode_show(struct device *dev,
+                          struct device_attribute *attr,
+                          char *buf)
+{
+       int current_mode;
+
+       current_mode = adaptive_keyboard_get_mode();
+       if (current_mode < 0)
+               return current_mode;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", current_mode);
+}
+
+static ssize_t adaptive_kbd_mode_store(struct device *dev,
+                           struct device_attribute *attr,
+                           const char *buf, size_t count)
+{
+       unsigned long t;
+       int res;
+
+       if (parse_strtoul(buf, LAYFLAT_MODE, &t))
+               return -EINVAL;
+
+       res = adaptive_keyboard_set_mode(t);
+       return (res < 0) ? res : count;
+}
+
+static DEVICE_ATTR_RW(adaptive_kbd_mode);
+
+static struct attribute *adaptive_kbd_attributes[] = {
+       &dev_attr_adaptive_kbd_mode.attr,
+       NULL
+};
+
+static const struct attribute_group adaptive_kbd_attr_group = {
+       .attrs = adaptive_kbd_attributes,
+};
+
 /* --------------------------------------------------------------------- */
 
 static struct attribute *hotkey_attributes[] __initdata = {
@@ -3118,6 +3173,13 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
                /* (assignments unknown, please report if found) */
                KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
                KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
+
+               /* No assignments, only used for Adaptive keyboards. */
+               KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
+               KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
+               KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
+               KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
+               KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
                },
 
        /* Generic keymap for Lenovo ThinkPads */
@@ -3174,6 +3236,35 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
 
                /* Extra keys in use since the X240 / T440 / T540 */
                KEY_CONFIG, KEY_SEARCH, KEY_SCALE, KEY_FILE,
+
+               /*
+                * These are the adaptive keyboard keycodes for Carbon X1 2014.
+                * The first item in this list is the Mute button which is
+                * emitted with 0x103 through
+                * adaptive_keyboard_hotkey_notify_hotkey() when the sound
+                * symbol is held.
+                * We'll need to offset those by 0x20.
+                */
+               KEY_RESERVED,        /* Mute held, 0x103 */
+               KEY_BRIGHTNESS_MIN,  /* Backlight off */
+               KEY_RESERVED,        /* Clipping tool */
+               KEY_RESERVED,        /* Cloud */
+               KEY_RESERVED,
+               KEY_VOICECOMMAND,    /* Voice */
+               KEY_RESERVED,
+               KEY_RESERVED,        /* Gestures */
+               KEY_RESERVED,
+               KEY_RESERVED,
+               KEY_RESERVED,
+               KEY_CONFIG,          /* Settings */
+               KEY_RESERVED,        /* New tab */
+               KEY_REFRESH,         /* Reload */
+               KEY_BACK,            /* Back */
+               KEY_RESERVED,        /* Microphone down */
+               KEY_RESERVED,        /* Microphone up */
+               KEY_RESERVED,        /* Microphone cancellation */
+               KEY_RESERVED,        /* Camera mode */
+               KEY_RESERVED,        /* Rotate display, 0x116 */
                },
        };
 
@@ -3227,6 +3318,20 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
        if (!tp_features.hotkey)
                return 1;
 
+       /*
+        * Check if we have an adaptive keyboard, like on the
+        * Lenovo Carbon X1 2014 (2nd Gen).
+        */
+       if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) {
+               if ((hkeyv >> 8) == 2) {
+                       tp_features.has_adaptive_kbd = true;
+                       res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
+                                       &adaptive_kbd_attr_group);
+                       if (res)
+                               goto err_exit;
+               }
+       }
+
        quirks = tpacpi_check_quirks(tpacpi_hotkey_qtable,
                                     ARRAY_SIZE(tpacpi_hotkey_qtable));
 
@@ -3437,6 +3542,9 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
 
 err_exit:
        delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj);
+       sysfs_remove_group(&tpacpi_pdev->dev.kobj,
+                       &adaptive_kbd_attr_group);
+
        hotkey_dev_attributes = NULL;
 
        return (res < 0) ? res : 1;
@@ -3449,14 +3557,6 @@ err_exit:
  * Will consider support rest of modes in future.
  *
  */
-enum ADAPTIVE_KEY_MODE {
-       HOME_MODE,
-       WEB_BROWSER_MODE,
-       WEB_CONFERENCE_MODE,
-       FUNCTION_MODE,
-       LAYFLAT_MODE
-};
-
 static const int adaptive_keyboard_modes[] = {
        HOME_MODE,
 /*     WEB_BROWSER_MODE = 2,
@@ -3466,6 +3566,8 @@ static const int adaptive_keyboard_modes[] = {
 
 #define DFR_CHANGE_ROW                 0x101
 #define DFR_SHOW_QUICKVIEW_ROW         0x102
+#define FIRST_ADAPTIVE_KEY             0x103
+#define ADAPTIVE_KEY_OFFSET            0x020
 
 /* press Fn key a while second, it will switch to Function Mode. Then
  * release Fn key, previous mode be restored.
@@ -3473,6 +3575,32 @@ static const int adaptive_keyboard_modes[] = {
 static bool adaptive_keyboard_mode_is_saved;
 static int adaptive_keyboard_prev_mode;
 
+static int adaptive_keyboard_get_mode(void)
+{
+       int mode = 0;
+
+       if (!acpi_evalf(hkey_handle, &mode, "GTRW", "dd", 0)) {
+               pr_err("Cannot read adaptive keyboard mode\n");
+               return -EIO;
+       }
+
+       return mode;
+}
+
+static int adaptive_keyboard_set_mode(int new_mode)
+{
+       if (new_mode < 0 ||
+               new_mode > LAYFLAT_MODE)
+               return -EINVAL;
+
+       if (!acpi_evalf(hkey_handle, NULL, "STRW", "vd", new_mode)) {
+               pr_err("Cannot set adaptive keyboard mode\n");
+               return -EIO;
+       }
+
+       return 0;
+}
+
 static int adaptive_keyboard_get_next_mode(int mode)
 {
        size_t i;
@@ -3493,8 +3621,9 @@ static int adaptive_keyboard_get_next_mode(int mode)
 
 static bool adaptive_keyboard_hotkey_notify_hotkey(unsigned int scancode)
 {
-       u32 current_mode = 0;
+       int current_mode = 0;
        int new_mode = 0;
+       int keycode;
 
        switch (scancode) {
        case DFR_CHANGE_ROW:
@@ -3502,43 +3631,51 @@ static bool adaptive_keyboard_hotkey_notify_hotkey(unsigned int scancode)
                        new_mode = adaptive_keyboard_prev_mode;
                        adaptive_keyboard_mode_is_saved = false;
                } else {
-                       if (!acpi_evalf(
-                                       hkey_handle, &current_mode,
-                                       "GTRW", "dd", 0)) {
-                               pr_err("Cannot read adaptive keyboard mode\n");
+                       current_mode = adaptive_keyboard_get_mode();
+                       if (current_mode < 0)
                                return false;
-                       } else {
-                               new_mode = adaptive_keyboard_get_next_mode(
-                                               current_mode);
-                       }
+                       new_mode = adaptive_keyboard_get_next_mode(
+                                       current_mode);
                }
 
-               if (!acpi_evalf(hkey_handle, NULL, "STRW", "vd", new_mode)) {
-                       pr_err("Cannot set adaptive keyboard mode\n");
+               if (adaptive_keyboard_set_mode(new_mode) < 0)
                        return false;
-               }
 
                return true;
 
        case DFR_SHOW_QUICKVIEW_ROW:
-               if (!acpi_evalf(hkey_handle,
-                               &adaptive_keyboard_prev_mode,
-                               "GTRW", "dd", 0)) {
-                       pr_err("Cannot read adaptive keyboard mode\n");
+               current_mode = adaptive_keyboard_get_mode();
+               if (current_mode < 0)
                        return false;
-               } else {
-                       adaptive_keyboard_mode_is_saved = true;
 
-                       if (!acpi_evalf(hkey_handle,
-                                       NULL, "STRW", "vd", FUNCTION_MODE)) {
-                               pr_err("Cannot set adaptive keyboard mode\n");
-                               return false;
-                       }
-               }
+               adaptive_keyboard_prev_mode = current_mode;
+               adaptive_keyboard_mode_is_saved = true;
+
+               if (adaptive_keyboard_set_mode (FUNCTION_MODE) < 0)
+                       return false;
                return true;
 
        default:
-               return false;
+               if (scancode < FIRST_ADAPTIVE_KEY ||
+                   scancode >= FIRST_ADAPTIVE_KEY + TPACPI_HOTKEY_MAP_LEN -
+                               ADAPTIVE_KEY_OFFSET) {
+                       pr_info("Unhandled adaptive keyboard key: 0x%x\n",
+                                       scancode);
+                       return false;
+               }
+               keycode = hotkey_keycode_map[scancode - FIRST_ADAPTIVE_KEY + ADAPTIVE_KEY_OFFSET];
+               if (keycode != KEY_RESERVED) {
+                       mutex_lock(&tpacpi_inputdev_send_mutex);
+
+                       input_report_key(tpacpi_inputdev, keycode, 1);
+                       input_sync(tpacpi_inputdev);
+
+                       input_report_key(tpacpi_inputdev, keycode, 0);
+                       input_sync(tpacpi_inputdev);
+
+                       mutex_unlock(&tpacpi_inputdev_send_mutex);
+               }
+               return true;
        }
 }
 
@@ -3836,28 +3973,21 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
 
 static void hotkey_suspend(void)
 {
-       int hkeyv;
-
        /* Do these on suspend, we get the events on early resume! */
        hotkey_wakeup_reason = TP_ACPI_WAKEUP_NONE;
        hotkey_autosleep_ack = 0;
 
        /* save previous mode of adaptive keyboard of X1 Carbon */
-       if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) {
-               if ((hkeyv >> 8) == 2) {
-                       if (!acpi_evalf(hkey_handle,
-                                               &adaptive_keyboard_prev_mode,
-                                               "GTRW", "dd", 0)) {
-                               pr_err("Cannot read adaptive keyboard mode.\n");
-                       }
+       if (tp_features.has_adaptive_kbd) {
+               if (!acpi_evalf(hkey_handle, &adaptive_keyboard_prev_mode,
+                                       "GTRW", "dd", 0)) {
+                       pr_err("Cannot read adaptive keyboard mode.\n");
                }
        }
 }
 
 static void hotkey_resume(void)
 {
-       int hkeyv;
-
        tpacpi_disable_brightness_delay();
 
        if (hotkey_status_set(true) < 0 ||
@@ -3872,14 +4002,10 @@ static void hotkey_resume(void)
        hotkey_poll_setup_safe(false);
 
        /* restore previous mode of adapive keyboard of X1 Carbon */
-       if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) {
-               if ((hkeyv >> 8) == 2) {
-                       if (!acpi_evalf(hkey_handle,
-                                               NULL,
-                                               "STRW", "vd",
-                                               adaptive_keyboard_prev_mode)) {
-                               pr_err("Cannot set adaptive keyboard mode.\n");
-                       }
+       if (tp_features.has_adaptive_kbd) {
+               if (!acpi_evalf(hkey_handle, NULL, "STRW", "vd",
+                                       adaptive_keyboard_prev_mode)) {
+                       pr_err("Cannot set adaptive keyboard mode.\n");
                }
        }
 }
@@ -4079,9 +4205,7 @@ static ssize_t bluetooth_enable_store(struct device *dev,
                                attr, buf, count);
 }
 
-static struct device_attribute dev_attr_bluetooth_enable =
-       __ATTR(bluetooth_enable, S_IWUSR | S_IRUGO,
-               bluetooth_enable_show, bluetooth_enable_store);
+static DEVICE_ATTR_RW(bluetooth_enable);
 
 /* --------------------------------------------------------------------- */
 
@@ -4269,9 +4393,7 @@ static ssize_t wan_enable_store(struct device *dev,
                        attr, buf, count);
 }
 
-static struct device_attribute dev_attr_wan_enable =
-       __ATTR(wwan_enable, S_IWUSR | S_IRUGO,
-               wan_enable_show, wan_enable_store);
+static DEVICE_ATTR_RW(wan_enable);
 
 /* --------------------------------------------------------------------- */
 
@@ -5048,8 +5170,7 @@ static ssize_t cmos_command_store(struct device *dev,
        return (res) ? res : count;
 }
 
-static struct device_attribute dev_attr_cmos_command =
-       __ATTR(cmos_command, S_IWUSR, NULL, cmos_command_store);
+static DEVICE_ATTR_WO(cmos_command);
 
 /* --------------------------------------------------------------------- */
 
@@ -8017,9 +8138,7 @@ static ssize_t fan_pwm1_enable_store(struct device *dev,
        return count;
 }
 
-static struct device_attribute dev_attr_fan_pwm1_enable =
-       __ATTR(pwm1_enable, S_IWUSR | S_IRUGO,
-               fan_pwm1_enable_show, fan_pwm1_enable_store);
+static DEVICE_ATTR_RW(fan_pwm1_enable);
 
 /* sysfs fan pwm1 ------------------------------------------------------ */
 static ssize_t fan_pwm1_show(struct device *dev,
@@ -8079,9 +8198,7 @@ static ssize_t fan_pwm1_store(struct device *dev,
        return (rc) ? rc : count;
 }
 
-static struct device_attribute dev_attr_fan_pwm1 =
-       __ATTR(pwm1, S_IWUSR | S_IRUGO,
-               fan_pwm1_show, fan_pwm1_store);
+static DEVICE_ATTR_RW(fan_pwm1);
 
 /* sysfs fan fan1_input ------------------------------------------------ */
 static ssize_t fan_fan1_input_show(struct device *dev,
@@ -8098,9 +8215,7 @@ static ssize_t fan_fan1_input_show(struct device *dev,
        return snprintf(buf, PAGE_SIZE, "%u\n", speed);
 }
 
-static struct device_attribute dev_attr_fan_fan1_input =
-       __ATTR(fan1_input, S_IRUGO,
-               fan_fan1_input_show, NULL);
+static DEVICE_ATTR_RO(fan_fan1_input);
 
 /* sysfs fan fan2_input ------------------------------------------------ */
 static ssize_t fan_fan2_input_show(struct device *dev,
@@ -8117,9 +8232,7 @@ static ssize_t fan_fan2_input_show(struct device *dev,
        return snprintf(buf, PAGE_SIZE, "%u\n", speed);
 }
 
-static struct device_attribute dev_attr_fan_fan2_input =
-       __ATTR(fan2_input, S_IRUGO,
-               fan_fan2_input_show, NULL);
+static DEVICE_ATTR_RO(fan_fan2_input);
 
 /* sysfs fan fan_watchdog (hwmon driver) ------------------------------- */
 static ssize_t fan_fan_watchdog_show(struct device_driver *drv,
@@ -8735,8 +8848,7 @@ static ssize_t thinkpad_acpi_pdev_name_show(struct device *dev,
        return snprintf(buf, PAGE_SIZE, "%s\n", TPACPI_NAME);
 }
 
-static struct device_attribute dev_attr_thinkpad_acpi_pdev_name =
-       __ATTR(name, S_IRUGO, thinkpad_acpi_pdev_name_show, NULL);
+static DEVICE_ATTR_RO(thinkpad_acpi_pdev_name);
 
 /* --------------------------------------------------------------------- */
 
index dbcb7a8915b84fb8794fd4daea15825e55a49cdd..9956b9902bb40aaeb59e724b60579e56a495795e 100644 (file)
@@ -51,6 +51,7 @@
 #include <linux/acpi.h>
 #include <linux/dmi.h>
 #include <linux/uaccess.h>
+#include <acpi/video.h>
 
 MODULE_AUTHOR("John Belmonte");
 MODULE_DESCRIPTION("Toshiba Laptop ACPI Extras Driver");
@@ -116,6 +117,7 @@ MODULE_LICENSE("GPL");
 #define HCI_KBD_ILLUMINATION           0x0095
 #define HCI_ECO_MODE                   0x0097
 #define HCI_ACCELEROMETER2             0x00a6
+#define HCI_SYSTEM_INFO                        0xc000
 #define SCI_PANEL_POWER_ON             0x010d
 #define SCI_ILLUMINATION               0x014e
 #define SCI_USB_SLEEP_CHARGE           0x0150
@@ -129,10 +131,13 @@ MODULE_LICENSE("GPL");
 #define HCI_ACCEL_MASK                 0x7fff
 #define HCI_HOTKEY_DISABLE             0x0b
 #define HCI_HOTKEY_ENABLE              0x09
+#define HCI_HOTKEY_SPECIAL_FUNCTIONS   0x10
 #define HCI_LCD_BRIGHTNESS_BITS                3
 #define HCI_LCD_BRIGHTNESS_SHIFT       (16-HCI_LCD_BRIGHTNESS_BITS)
 #define HCI_LCD_BRIGHTNESS_LEVELS      (1 << HCI_LCD_BRIGHTNESS_BITS)
 #define HCI_MISC_SHIFT                 0x10
+#define HCI_SYSTEM_TYPE1               0x10
+#define HCI_SYSTEM_TYPE2               0x11
 #define HCI_VIDEO_OUT_LCD              0x1
 #define HCI_VIDEO_OUT_CRT              0x2
 #define HCI_VIDEO_OUT_TV               0x4
@@ -147,9 +152,10 @@ MODULE_LICENSE("GPL");
 #define SCI_KBD_MODE_OFF               0x10
 #define SCI_KBD_TIME_MAX               0x3c001a
 #define SCI_USB_CHARGE_MODE_MASK       0xff
-#define SCI_USB_CHARGE_DISABLED                0x30000
-#define SCI_USB_CHARGE_ALTERNATE       0x30009
-#define SCI_USB_CHARGE_AUTO            0x30021
+#define SCI_USB_CHARGE_DISABLED                0x00
+#define SCI_USB_CHARGE_ALTERNATE       0x09
+#define SCI_USB_CHARGE_TYPICAL         0x11
+#define SCI_USB_CHARGE_AUTO            0x21
 #define SCI_USB_CHARGE_BAT_MASK                0x7
 #define SCI_USB_CHARGE_BAT_LVL_OFF     0x1
 #define SCI_USB_CHARGE_BAT_LVL_ON      0x4
@@ -174,6 +180,8 @@ struct toshiba_acpi_dev {
        int kbd_mode;
        int kbd_time;
        int usbsc_bat_level;
+       int usbsc_mode_base;
+       int hotkey_event_type;
 
        unsigned int illumination_supported:1;
        unsigned int video_supported:1;
@@ -243,29 +251,6 @@ static const struct key_entry toshiba_acpi_keymap[] = {
        { KE_END, 0 },
 };
 
-/* alternative keymap */
-static const struct dmi_system_id toshiba_alt_keymap_dmi[] = {
-       {
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M840"),
-               },
-       },
-       {
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "Qosmio X75-A"),
-               },
-       },
-       {
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "TECRA A50-A"),
-               },
-       },
-       {}
-};
-
 static const struct key_entry toshiba_acpi_alt_keymap[] = {
        { KE_KEY, 0x157, { KEY_MUTE } },
        { KE_KEY, 0x102, { KEY_ZOOMOUT } },
@@ -280,6 +265,14 @@ static const struct key_entry toshiba_acpi_alt_keymap[] = {
        { KE_END, 0 },
 };
 
+/*
+ * List of models which have a broken acpi-video backlight interface and thus
+ * need to use the toshiba (vendor) interface instead.
+ */
+static const struct dmi_system_id toshiba_vendor_backlight_dmi[] = {
+       {}
+};
+
 /*
  * Utility
  */
@@ -819,6 +812,54 @@ static int toshiba_accelerometer_get(struct toshiba_acpi_dev *dev,
 }
 
 /* Sleep (Charge and Music) utilities support */
+static void toshiba_usb_sleep_charge_available(struct toshiba_acpi_dev *dev)
+{
+       u32 in[TCI_WORDS] = { SCI_GET, SCI_USB_SLEEP_CHARGE, 0, 0, 0, 0 };
+       u32 out[TCI_WORDS];
+       acpi_status status;
+
+       /* Set the feature to "not supported" in case of error */
+       dev->usb_sleep_charge_supported = 0;
+
+       if (!sci_open(dev))
+               return;
+
+       status = tci_raw(dev, in, out);
+       if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) {
+               pr_err("ACPI call to get USB Sleep and Charge mode failed\n");
+               sci_close(dev);
+               return;
+       } else if (out[0] == TOS_NOT_SUPPORTED) {
+               pr_info("USB Sleep and Charge not supported\n");
+               sci_close(dev);
+               return;
+       } else if (out[0] == TOS_SUCCESS) {
+               dev->usbsc_mode_base = out[4];
+       }
+
+       in[5] = SCI_USB_CHARGE_BAT_LVL;
+       status = tci_raw(dev, in, out);
+       if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) {
+               pr_err("ACPI call to get USB Sleep and Charge mode failed\n");
+               sci_close(dev);
+               return;
+       } else if (out[0] == TOS_NOT_SUPPORTED) {
+               pr_info("USB Sleep and Charge not supported\n");
+               sci_close(dev);
+               return;
+       } else if (out[0] == TOS_SUCCESS) {
+               dev->usbsc_bat_level = out[2];
+               /*
+                * If we reach this point, it means that the laptop has support
+                * for this feature and all values are initialized.
+                * Set it as supported.
+                */
+               dev->usb_sleep_charge_supported = 1;
+       }
+
+       sci_close(dev);
+}
+
 static int toshiba_usb_sleep_charge_get(struct toshiba_acpi_dev *dev,
                                        u32 *mode)
 {
@@ -934,11 +975,11 @@ static int toshiba_usb_rapid_charge_get(struct toshiba_acpi_dev *dev,
        status = tci_raw(dev, in, out);
        sci_close(dev);
        if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) {
-               pr_err("ACPI call to get USB S&C battery level failed\n");
+               pr_err("ACPI call to get USB Rapid Charge failed\n");
                return -EIO;
        } else if (out[0] == TOS_NOT_SUPPORTED ||
                   out[0] == TOS_INPUT_DATA_ERROR) {
-               pr_info("USB Sleep and Charge not supported\n");
+               pr_info("USB Rapid Charge not supported\n");
                return -ENODEV;
        }
 
@@ -962,10 +1003,10 @@ static int toshiba_usb_rapid_charge_set(struct toshiba_acpi_dev *dev,
        status = tci_raw(dev, in, out);
        sci_close(dev);
        if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) {
-               pr_err("ACPI call to set USB S&C battery level failed\n");
+               pr_err("ACPI call to set USB Rapid Charge failed\n");
                return -EIO;
        } else if (out[0] == TOS_NOT_SUPPORTED) {
-               pr_info("USB Sleep and Charge not supported\n");
+               pr_info("USB Rapid Charge not supported\n");
                return -ENODEV;
        } else if (out[0] == TOS_INPUT_DATA_ERROR) {
                return -EIO;
@@ -984,10 +1025,10 @@ static int toshiba_usb_sleep_music_get(struct toshiba_acpi_dev *dev, u32 *state)
        result = sci_read(dev, SCI_USB_SLEEP_MUSIC, state);
        sci_close(dev);
        if (result == TOS_FAILURE) {
-               pr_err("ACPI call to set USB S&C mode failed\n");
+               pr_err("ACPI call to get Sleep and Music failed\n");
                return -EIO;
        } else if (result == TOS_NOT_SUPPORTED) {
-               pr_info("USB Sleep and Charge not supported\n");
+               pr_info("Sleep and Music not supported\n");
                return -ENODEV;
        } else if (result == TOS_INPUT_DATA_ERROR) {
                return -EIO;
@@ -1006,10 +1047,10 @@ static int toshiba_usb_sleep_music_set(struct toshiba_acpi_dev *dev, u32 state)
        result = sci_write(dev, SCI_USB_SLEEP_MUSIC, state);
        sci_close(dev);
        if (result == TOS_FAILURE) {
-               pr_err("ACPI call to set USB S&C mode failed\n");
+               pr_err("ACPI call to set Sleep and Music failed\n");
                return -EIO;
        } else if (result == TOS_NOT_SUPPORTED) {
-               pr_info("USB Sleep and Charge not supported\n");
+               pr_info("Sleep and Music not supported\n");
                return -ENODEV;
        } else if (result == TOS_INPUT_DATA_ERROR) {
                return -EIO;
@@ -1149,6 +1190,28 @@ static int toshiba_usb_three_set(struct toshiba_acpi_dev *dev, u32 state)
        return 0;
 }
 
+/* Hotkey Event type */
+static int toshiba_hotkey_event_type_get(struct toshiba_acpi_dev *dev,
+                                        u32 *type)
+{
+       u32 val1 = 0x03;
+       u32 val2 = 0;
+       u32 result;
+
+       result = hci_read2(dev, HCI_SYSTEM_INFO, &val1, &val2);
+       if (result == TOS_FAILURE) {
+               pr_err("ACPI call to get System type failed\n");
+               return -EIO;
+       } else if (result == TOS_NOT_SUPPORTED) {
+               pr_info("System type not supported\n");
+               return -ENODEV;
+       }
+
+       *type = val2;
+
+       return 0;
+}
+
 /* Bluetooth rfkill handlers */
 
 static u32 hci_get_bt_present(struct toshiba_acpi_dev *dev, bool *present)
@@ -1973,17 +2036,21 @@ static ssize_t usb_sleep_charge_store(struct device *dev,
         * 0 - Disabled
         * 1 - Alternate (Non USB conformant devices that require more power)
         * 2 - Auto (USB conformant devices)
+        * 3 - Typical
         */
-       if (state != 0 && state != 1 && state != 2)
+       if (state != 0 && state != 1 && state != 2 && state != 3)
                return -EINVAL;
 
        /* Set the USB charging mode to internal value */
+       mode = toshiba->usbsc_mode_base;
        if (state == 0)
-               mode = SCI_USB_CHARGE_DISABLED;
+               mode |= SCI_USB_CHARGE_DISABLED;
        else if (state == 1)
-               mode = SCI_USB_CHARGE_ALTERNATE;
+               mode |= SCI_USB_CHARGE_ALTERNATE;
        else if (state == 2)
-               mode = SCI_USB_CHARGE_AUTO;
+               mode |= SCI_USB_CHARGE_AUTO;
+       else if (state == 3)
+               mode |= SCI_USB_CHARGE_TYPICAL;
 
        ret = toshiba_usb_sleep_charge_set(toshiba, mode);
        if (ret)
@@ -2333,6 +2400,20 @@ static int toshiba_acpi_enable_hotkeys(struct toshiba_acpi_dev *dev)
        return 0;
 }
 
+static void toshiba_acpi_enable_special_functions(struct toshiba_acpi_dev *dev)
+{
+       u32 result;
+
+       /*
+        * Re-activate the hotkeys, but this time, we are using the
+        * "Special Functions" mode.
+        */
+       result = hci_write1(dev, HCI_HOTKEY_EVENT,
+                           HCI_HOTKEY_SPECIAL_FUNCTIONS);
+       if (result != TOS_SUCCESS)
+               pr_err("Could not enable the Special Function mode\n");
+}
+
 static bool toshiba_acpi_i8042_filter(unsigned char data, unsigned char str,
                                      struct serio *port)
 {
@@ -2434,10 +2515,22 @@ static void toshiba_acpi_process_hotkeys(struct toshiba_acpi_dev *dev)
 
 static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
 {
+       const struct key_entry *keymap = toshiba_acpi_keymap;
        acpi_handle ec_handle;
-       int error;
+       u32 events_type;
        u32 hci_result;
-       const struct key_entry *keymap = toshiba_acpi_keymap;
+       int error;
+
+       error = toshiba_acpi_enable_hotkeys(dev);
+       if (error)
+               return error;
+
+       error = toshiba_hotkey_event_type_get(dev, &events_type);
+       if (error) {
+               pr_err("Unable to query Hotkey Event Type\n");
+               return error;
+       }
+       dev->hotkey_event_type = events_type;
 
        dev->hotkey_dev = input_allocate_device();
        if (!dev->hotkey_dev)
@@ -2447,8 +2540,14 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
        dev->hotkey_dev->phys = "toshiba_acpi/input0";
        dev->hotkey_dev->id.bustype = BUS_HOST;
 
-       if (dmi_check_system(toshiba_alt_keymap_dmi))
+       if (events_type == HCI_SYSTEM_TYPE1 ||
+           !dev->kbd_function_keys_supported)
+               keymap = toshiba_acpi_keymap;
+       else if (events_type == HCI_SYSTEM_TYPE2 ||
+                dev->kbd_function_keys_supported)
                keymap = toshiba_acpi_alt_keymap;
+       else
+               pr_info("Unknown event type received %x\n", events_type);
        error = sparse_keymap_setup(dev->hotkey_dev, keymap, NULL);
        if (error)
                goto err_free_dev;
@@ -2490,12 +2589,6 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
                goto err_remove_filter;
        }
 
-       error = toshiba_acpi_enable_hotkeys(dev);
-       if (error) {
-               pr_info("Unable to enable hotkeys\n");
-               goto err_remove_filter;
-       }
-
        error = input_register_device(dev->hotkey_dev);
        if (error) {
                pr_info("Unable to register input device\n");
@@ -2541,6 +2634,20 @@ static int toshiba_acpi_setup_backlight(struct toshiba_acpi_dev *dev)
        ret = get_tr_backlight_status(dev, &enabled);
        dev->tr_backlight_supported = !ret;
 
+       /*
+        * Tell acpi-video-detect code to prefer vendor backlight on all
+        * systems with transflective backlight and on dmi matched systems.
+        */
+       if (dev->tr_backlight_supported ||
+           dmi_check_system(toshiba_vendor_backlight_dmi))
+               acpi_video_dmi_promote_vendor();
+
+       if (acpi_video_backlight_support())
+               return 0;
+
+       /* acpi-video may have loaded before we called dmi_promote_vendor() */
+       acpi_video_unregister_backlight();
+
        memset(&props, 0, sizeof(props));
        props.type = BACKLIGHT_PLATFORM;
        props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
@@ -2624,6 +2731,7 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
 {
        struct toshiba_acpi_dev *dev;
        const char *hci_method;
+       u32 special_functions;
        u32 dummy;
        bool bt_present;
        int ret = 0;
@@ -2648,6 +2756,16 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
        acpi_dev->driver_data = dev;
        dev_set_drvdata(&acpi_dev->dev, dev);
 
+       /* Query the BIOS for supported features */
+
+       /*
+        * The "Special Functions" are always supported by the laptops
+        * with the new keyboard layout, query for its presence to help
+        * determine the keymap layout to use.
+        */
+       ret = toshiba_function_keys_get(dev, &special_functions);
+       dev->kbd_function_keys_supported = !ret;
+
        if (toshiba_acpi_setup_keyboard(dev))
                pr_info("Unable to activate hotkeys\n");
 
@@ -2716,8 +2834,7 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
        ret = toshiba_accelerometer_supported(dev);
        dev->accelerometer_supported = !ret;
 
-       ret = toshiba_usb_sleep_charge_get(dev, &dummy);
-       dev->usb_sleep_charge_supported = !ret;
+       toshiba_usb_sleep_charge_available(dev);
 
        ret = toshiba_usb_rapid_charge_get(dev, &dummy);
        dev->usb_rapid_charge_supported = !ret;
@@ -2725,23 +2842,25 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
        ret = toshiba_usb_sleep_music_get(dev, &dummy);
        dev->usb_sleep_music_supported = !ret;
 
-       ret = toshiba_function_keys_get(dev, &dummy);
-       dev->kbd_function_keys_supported = !ret;
-
        ret = toshiba_panel_power_on_get(dev, &dummy);
        dev->panel_power_on_supported = !ret;
 
        ret = toshiba_usb_three_get(dev, &dummy);
        dev->usb_three_supported = !ret;
 
-       /* Determine whether or not BIOS supports fan and video interfaces */
-
        ret = get_video_status(dev, &dummy);
        dev->video_supported = !ret;
 
        ret = get_fan_status(dev, &dummy);
        dev->fan_supported = !ret;
 
+       /*
+        * Enable the "Special Functions" mode only if they are
+        * supported and if they are activated.
+        */
+       if (dev->kbd_function_keys_supported && special_functions)
+               toshiba_acpi_enable_special_functions(dev);
+
        ret = sysfs_create_group(&dev->acpi_dev->dev.kobj,
                                 &toshiba_attr_group);
        if (ret) {
@@ -2770,6 +2889,21 @@ static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event)
        case 0x80: /* Hotkeys and some system events */
                toshiba_acpi_process_hotkeys(dev);
                break;
+       case 0x81: /* Dock events */
+       case 0x82:
+       case 0x83:
+               pr_info("Dock event received %x\n", event);
+               break;
+       case 0x88: /* Thermal events */
+               pr_info("Thermal event received\n");
+               break;
+       case 0x8f: /* LID closed */
+       case 0x90: /* LID is closed and Dock has been ejected */
+               break;
+       case 0x8c: /* SATA power events */
+       case 0x8b:
+               pr_info("SATA power event received %x\n", event);
+               break;
        case 0x92: /* Keyboard backlight mode changed */
                /* Update sysfs entries */
                ret = sysfs_update_group(&acpi_dev->dev.kobj,
@@ -2777,17 +2911,19 @@ static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event)
                if (ret)
                        pr_err("Unable to update sysfs entries\n");
                break;
-       case 0x81: /* Unknown */
-       case 0x82: /* Unknown */
-       case 0x83: /* Unknown */
-       case 0x8c: /* Unknown */
+       case 0x85: /* Unknown */
+       case 0x8d: /* Unknown */
        case 0x8e: /* Unknown */
-       case 0x8f: /* Unknown */
-       case 0x90: /* Unknown */
+       case 0x94: /* Unknown */
+       case 0x95: /* Unknown */
        default:
                pr_info("Unknown event received %x\n", event);
                break;
        }
+
+       acpi_bus_generate_netlink_event(acpi_dev->pnp.device_class,
+                                       dev_name(&acpi_dev->dev),
+                                       event, 0);
 }
 
 #ifdef CONFIG_PM_SLEEP
index 2cb1ea62b4a7f9ac7b268adadb251105be279923..24980076336223147fb179979256be03b6c1e99a 100644 (file)
@@ -2,6 +2,7 @@
  * Toshiba Bluetooth Enable Driver
  *
  * Copyright (C) 2009 Jes Sorensen <Jes.Sorensen@gmail.com>
+ * Copyright (C) 2015 Azael Avalos <coproscefalo@gmail.com>
  *
  * Thanks to Matthew Garrett for background info on ACPI innards which
  * normal people aren't meant to understand :-)
 #include <linux/types.h>
 #include <linux/acpi.h>
 
+#define BT_KILLSWITCH_MASK     0x01
+#define BT_PLUGGED_MASK                0x40
+#define BT_POWER_MASK          0x80
+
 MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@gmail.com>");
 MODULE_DESCRIPTION("Toshiba Laptop ACPI Bluetooth Enable Driver");
 MODULE_LICENSE("GPL");
@@ -57,32 +62,107 @@ static struct acpi_driver toshiba_bt_rfkill_driver = {
        .drv.pm =       &toshiba_bt_pm,
 };
 
+static int toshiba_bluetooth_present(acpi_handle handle)
+{
+       acpi_status result;
+       u64 bt_present;
+
+       /*
+        * Some Toshiba laptops may have a fake TOS6205 device in
+        * their ACPI BIOS, so query the _STA method to see if there
+        * is really anything there.
+        */
+       result = acpi_evaluate_integer(handle, "_STA", NULL, &bt_present);
+       if (ACPI_FAILURE(result)) {
+               pr_err("ACPI call to query Bluetooth presence failed");
+               return -ENXIO;
+       } else if (!bt_present) {
+               pr_info("Bluetooth device not present\n");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static int toshiba_bluetooth_status(acpi_handle handle)
+{
+       acpi_status result;
+       u64 status;
+
+       result = acpi_evaluate_integer(handle, "BTST", NULL, &status);
+       if (ACPI_FAILURE(result)) {
+               pr_err("Could not get Bluetooth device status\n");
+               return -ENXIO;
+       }
+
+       pr_info("Bluetooth status %llu\n", status);
+
+       return status;
+}
 
 static int toshiba_bluetooth_enable(acpi_handle handle)
 {
-       acpi_status res1, res2;
-       u64 result;
+       acpi_status result;
+       bool killswitch;
+       bool powered;
+       bool plugged;
+       int status;
 
        /*
         * Query ACPI to verify RFKill switch is set to 'on'.
         * If not, we return silently, no need to report it as
         * an error.
         */
-       res1 = acpi_evaluate_integer(handle, "BTST", NULL, &result);
-       if (ACPI_FAILURE(res1))
-               return res1;
-       if (!(result & 0x01))
-               return 0;
+       status = toshiba_bluetooth_status(handle);
+       if (status < 0)
+               return status;
+
+       killswitch = (status & BT_KILLSWITCH_MASK) ? true : false;
+       powered = (status & BT_POWER_MASK) ? true : false;
+       plugged = (status & BT_PLUGGED_MASK) ? true : false;
 
-       pr_info("Re-enabling Toshiba Bluetooth\n");
-       res1 = acpi_evaluate_object(handle, "AUSB", NULL, NULL);
-       res2 = acpi_evaluate_object(handle, "BTPO", NULL, NULL);
-       if (!ACPI_FAILURE(res1) || !ACPI_FAILURE(res2))
+       if (!killswitch)
                return 0;
+       /*
+        * This check ensures to only enable the device if it is powered
+        * off or detached, as some recent devices somehow pass the killswitch
+        * test, causing a loop enabling/disabling the device, see bug 93911.
+        */
+       if (powered || plugged)
+               return 0;
+
+       result = acpi_evaluate_object(handle, "AUSB", NULL, NULL);
+       if (ACPI_FAILURE(result)) {
+               pr_err("Could not attach USB Bluetooth device\n");
+               return -ENXIO;
+       }
+
+       result = acpi_evaluate_object(handle, "BTPO", NULL, NULL);
+       if (ACPI_FAILURE(result)) {
+               pr_err("Could not power ON Bluetooth device\n");
+               return -ENXIO;
+       }
+
+       return 0;
+}
+
+static int toshiba_bluetooth_disable(acpi_handle handle)
+{
+       acpi_status result;
+
+       result = acpi_evaluate_object(handle, "BTPF", NULL, NULL);
+       if (ACPI_FAILURE(result)) {
+               pr_err("Could not power OFF Bluetooth device\n");
+               return -ENXIO;
+       }
 
-       pr_warn("Failed to re-enable Toshiba Bluetooth\n");
+       result = acpi_evaluate_object(handle, "DUSB", NULL, NULL);
+       if (ACPI_FAILURE(result)) {
+               pr_err("Could not detach USB Bluetooth device\n");
+               return -ENXIO;
+       }
 
-       return -ENODEV;
+       return 0;
 }
 
 static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event)
@@ -99,23 +179,18 @@ static int toshiba_bt_resume(struct device *dev)
 
 static int toshiba_bt_rfkill_add(struct acpi_device *device)
 {
-       acpi_status status;
-       u64 bt_present;
-       int result = -ENODEV;
+       int result;
 
-       /*
-        * Some Toshiba laptops may have a fake TOS6205 device in
-        * their ACPI BIOS, so query the _STA method to see if there
-        * is really anything there, before trying to enable it.
-        */
-       status = acpi_evaluate_integer(device->handle, "_STA", NULL,
-                                      &bt_present);
+       result = toshiba_bluetooth_present(device->handle);
+       if (result)
+               return result;
 
-       if (!ACPI_FAILURE(status) && bt_present) {
-               pr_info("Detected Toshiba ACPI Bluetooth device - "
-                       "installing RFKill handler\n");
-               result = toshiba_bluetooth_enable(device->handle);
-       }
+       pr_info("Toshiba ACPI Bluetooth device driver\n");
+
+       /* Enable the BT device */
+       result = toshiba_bluetooth_enable(device->handle);
+       if (result)
+               return result;
 
        return result;
 }
@@ -123,7 +198,7 @@ static int toshiba_bt_rfkill_add(struct acpi_device *device)
 static int toshiba_bt_rfkill_remove(struct acpi_device *device)
 {
        /* clean up */
-       return 0;
+       return toshiba_bluetooth_disable(device->handle);
 }
 
 module_acpi_driver(toshiba_bt_rfkill_driver);
index 737e56d46f61950826419bbef2d9fb66d69abcc1..aac47573f9ed83e4c42ea84aef9c3940644e4db1 100644 (file)
@@ -45,7 +45,6 @@ MODULE_LICENSE("GPL");
 
 #define ACPI_WMI_CLASS "wmi"
 
-static DEFINE_MUTEX(wmi_data_lock);
 static LIST_HEAD(wmi_block_list);
 
 struct guid_block {
@@ -240,10 +239,10 @@ static bool find_guid(const char *guid_string, struct wmi_block **out)
                if (memcmp(block->guid, guid_input, 16) == 0) {
                        if (out)
                                *out = wblock;
-                       return 1;
+                       return true;
                }
        }
-       return 0;
+       return false;
 }
 
 static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable)
index e03877c4b1958c853563705087faf52a918193b6..fd243231620ac10554b0b2616792c00e189d970d 100644 (file)
@@ -1064,6 +1064,7 @@ static const struct x86_cpu_id rapl_ids[] __initconst = {
        RAPL_CPU(0x3f, rapl_defaults_hsw_server),/* Haswell servers */
        RAPL_CPU(0x4f, rapl_defaults_hsw_server),/* Broadwell servers */
        RAPL_CPU(0x45, rapl_defaults_core),/* Haswell ULT */
+       RAPL_CPU(0x4E, rapl_defaults_core),/* Skylake */
        RAPL_CPU(0x4C, rapl_defaults_atom),/* Braswell */
        RAPL_CPU(0x4A, rapl_defaults_atom),/* Tangier */
        RAPL_CPU(0x56, rapl_defaults_core),/* Future Xeon */
index 810aef3f4c3e84586d5dd5719ea5d9c74dcfdcfe..ba34c7d8904232de070b78d4565377c1fab75740 100644 (file)
@@ -573,7 +573,7 @@ EXPORT_SYMBOL_GPL(of_pwm_get);
  * @table: array of consumers to register
  * @num: number of consumers in table
  */
-void __init pwm_add_table(struct pwm_lookup *table, size_t num)
+void pwm_add_table(struct pwm_lookup *table, size_t num)
 {
        mutex_lock(&pwm_lookup_lock);
 
index 522f7075bb1a42b14d699d5ee6548fe375fcdd53..fa5feaba25a5d768d47aa100f4a9e55c634aabce 100644 (file)
@@ -225,6 +225,10 @@ static const struct of_device_id atmel_hlcdc_dt_ids[] = {
                .compatible = "atmel,sama5d3-hlcdc",
                .data = &atmel_hlcdc_pwm_sama5d3_errata,
        },
+       {
+               .compatible = "atmel,sama5d4-hlcdc",
+               .data = &atmel_hlcdc_pwm_sama5d3_errata,
+       },
        { /* sentinel */ },
 };
 
index f75ecb09d97de3e9a80e7b0fac46f2369fc288b7..b430811e14f582a9ad66e4cad3f86fbe4569a073 100644 (file)
 #define  PERIOD_CDIV(div)      (((div) & 0x7) << 20)
 #define  PERIOD_CDIV_MAX       8
 
+static const unsigned int cdiv[PERIOD_CDIV_MAX] = {
+       1, 2, 4, 8, 16, 64, 256, 1024
+};
+
 struct mxs_pwm_chip {
        struct pwm_chip chip;
        struct clk *clk;
@@ -54,13 +58,13 @@ static int mxs_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
 
        rate = clk_get_rate(mxs->clk);
        while (1) {
-               c = rate / (1 << div);
+               c = rate / cdiv[div];
                c = c * period_ns;
                do_div(c, 1000000000);
                if (c < PERIOD_PERIOD_MAX)
                        break;
                div++;
-               if (div > PERIOD_CDIV_MAX)
+               if (div >= PERIOD_CDIV_MAX)
                        return -EINVAL;
        }
 
index 3fb775ded0dff062e07f6d34e2f37f7e8bb93d1a..34b5c275a92a3ca592c5fee09b8ca45634caea49 100644 (file)
@@ -202,7 +202,7 @@ static const struct pwm_ops pca9685_pwm_ops = {
        .owner = THIS_MODULE,
 };
 
-static struct regmap_config pca9685_regmap_i2c_config = {
+static const struct regmap_config pca9685_regmap_i2c_config = {
        .reg_bits = 8,
        .val_bits = 8,
        .max_register = PCA9685_NUMREGS,
index 3e9b5835a4af80c6a4e510e93f9f79934b96a1b4..ff201e1b92197e1d354cacc3239a045b7b88e77c 100644 (file)
@@ -269,12 +269,31 @@ static void pwm_samsung_disable(struct pwm_chip *chip, struct pwm_device *pwm)
        spin_unlock_irqrestore(&samsung_pwm_lock, flags);
 }
 
+static void pwm_samsung_manual_update(struct samsung_pwm_chip *chip,
+                                     struct pwm_device *pwm)
+{
+       unsigned int tcon_chan = to_tcon_channel(pwm->hwpwm);
+       u32 tcon;
+       unsigned long flags;
+
+       spin_lock_irqsave(&samsung_pwm_lock, flags);
+
+       tcon = readl(chip->base + REG_TCON);
+       tcon |= TCON_MANUALUPDATE(tcon_chan);
+       writel(tcon, chip->base + REG_TCON);
+
+       tcon &= ~TCON_MANUALUPDATE(tcon_chan);
+       writel(tcon, chip->base + REG_TCON);
+
+       spin_unlock_irqrestore(&samsung_pwm_lock, flags);
+}
+
 static int pwm_samsung_config(struct pwm_chip *chip, struct pwm_device *pwm,
                              int duty_ns, int period_ns)
 {
        struct samsung_pwm_chip *our_chip = to_samsung_pwm_chip(chip);
        struct samsung_pwm_channel *chan = pwm_get_chip_data(pwm);
-       u32 tin_ns = chan->tin_ns, tcnt, tcmp;
+       u32 tin_ns = chan->tin_ns, tcnt, tcmp, oldtcmp;
 
        /*
         * We currently avoid using 64bit arithmetic by using the
@@ -288,6 +307,7 @@ static int pwm_samsung_config(struct pwm_chip *chip, struct pwm_device *pwm,
                return 0;
 
        tcnt = readl(our_chip->base + REG_TCNTB(pwm->hwpwm));
+       oldtcmp = readl(our_chip->base + REG_TCMPB(pwm->hwpwm));
 
        /* We need tick count for calculation, not last tick. */
        ++tcnt;
@@ -335,6 +355,16 @@ static int pwm_samsung_config(struct pwm_chip *chip, struct pwm_device *pwm,
        writel(tcnt, our_chip->base + REG_TCNTB(pwm->hwpwm));
        writel(tcmp, our_chip->base + REG_TCMPB(pwm->hwpwm));
 
+       /*
+        * In case the PWM is currently at 100% duty cycle, force a manual
+        * update to prevent the signal staying high if the PWM is disabled
+        * shortly afer this update (before it autoreloaded the new values).
+        */
+       if (oldtcmp == (u32) -1) {
+               dev_dbg(our_chip->chip.dev, "Forcing manual update");
+               pwm_samsung_manual_update(our_chip, pwm);
+       }
+
        chan->period_ns = period_ns;
        chan->tin_ns = tin_ns;
        chan->duty_ns = duty_ns;
index 6149ae01e11f9dfc2441efb49d1a04c2915cc3d4..0fe4ad8826b2cda45044d8699696486cbd4bd1eb 100644 (file)
@@ -164,6 +164,16 @@ config RTC_DRV_ABB5ZES3
          This driver can also be built as a module. If so, the module
          will be called rtc-ab-b5ze-s3.
 
+config RTC_DRV_ABX80X
+       tristate "Abracon ABx80x"
+       help
+         If you say yes here you get support for Abracon AB080X and AB180X
+         families of ultra-low-power  battery- and capacitor-backed real-time
+         clock chips.
+
+         This driver can also be built as a module. If so, the module
+         will be called rtc-abx80x.
+
 config RTC_DRV_AS3722
        tristate "ams AS3722 RTC driver"
        depends on MFD_AS3722
index c31731c297624096e5526be906dd3f8bea0a2f7a..2b82e2b0311bd9da719b037e5d217fdee9efc652 100644 (file)
@@ -25,6 +25,7 @@ obj-$(CONFIG_RTC_DRV_88PM80X) += rtc-88pm80x.o
 obj-$(CONFIG_RTC_DRV_AB3100)   += rtc-ab3100.o
 obj-$(CONFIG_RTC_DRV_AB8500)   += rtc-ab8500.o
 obj-$(CONFIG_RTC_DRV_ABB5ZES3) += rtc-ab-b5ze-s3.o
+obj-$(CONFIG_RTC_DRV_ABX80X)   += rtc-abx80x.o
 obj-$(CONFIG_RTC_DRV_ARMADA38X)        += rtc-armada38x.o
 obj-$(CONFIG_RTC_DRV_AS3722)   += rtc-as3722.o
 obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o
diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c
new file mode 100644 (file)
index 0000000..4337c3b
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * A driver for the I2C members of the Abracon AB x8xx RTC family,
+ * and compatible: AB 1805 and AB 0805
+ *
+ * Copyright 2014-2015 Macq S.A.
+ *
+ * Author: Philippe De Muyter <phdm@macqel.be>
+ * Author: Alexandre Belloni <alexandre.belloni@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/bcd.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/rtc.h>
+
+#define ABX8XX_REG_HTH         0x00
+#define ABX8XX_REG_SC          0x01
+#define ABX8XX_REG_MN          0x02
+#define ABX8XX_REG_HR          0x03
+#define ABX8XX_REG_DA          0x04
+#define ABX8XX_REG_MO          0x05
+#define ABX8XX_REG_YR          0x06
+#define ABX8XX_REG_WD          0x07
+
+#define ABX8XX_REG_CTRL1       0x10
+#define ABX8XX_CTRL_WRITE      BIT(1)
+#define ABX8XX_CTRL_12_24      BIT(6)
+
+#define ABX8XX_REG_CFG_KEY     0x1f
+#define ABX8XX_CFG_KEY_MISC    0x9d
+
+#define ABX8XX_REG_ID0         0x28
+
+#define ABX8XX_REG_TRICKLE     0x20
+#define ABX8XX_TRICKLE_CHARGE_ENABLE   0xa0
+#define ABX8XX_TRICKLE_STANDARD_DIODE  0x8
+#define ABX8XX_TRICKLE_SCHOTTKY_DIODE  0x4
+
+static u8 trickle_resistors[] = {0, 3, 6, 11};
+
+enum abx80x_chip {AB0801, AB0803, AB0804, AB0805,
+       AB1801, AB1803, AB1804, AB1805, ABX80X};
+
+struct abx80x_cap {
+       u16 pn;
+       bool has_tc;
+};
+
+static struct abx80x_cap abx80x_caps[] = {
+       [AB0801] = {.pn = 0x0801},
+       [AB0803] = {.pn = 0x0803},
+       [AB0804] = {.pn = 0x0804, .has_tc = true},
+       [AB0805] = {.pn = 0x0805, .has_tc = true},
+       [AB1801] = {.pn = 0x1801},
+       [AB1803] = {.pn = 0x1803},
+       [AB1804] = {.pn = 0x1804, .has_tc = true},
+       [AB1805] = {.pn = 0x1805, .has_tc = true},
+       [ABX80X] = {.pn = 0}
+};
+
+static struct i2c_driver abx80x_driver;
+
+static int abx80x_enable_trickle_charger(struct i2c_client *client,
+                                        u8 trickle_cfg)
+{
+       int err;
+
+       /*
+        * Write the configuration key register to enable access to the Trickle
+        * register
+        */
+       err = i2c_smbus_write_byte_data(client, ABX8XX_REG_CFG_KEY,
+                                       ABX8XX_CFG_KEY_MISC);
+       if (err < 0) {
+               dev_err(&client->dev, "Unable to write configuration key\n");
+               return -EIO;
+       }
+
+       err = i2c_smbus_write_byte_data(client, ABX8XX_REG_TRICKLE,
+                                       ABX8XX_TRICKLE_CHARGE_ENABLE |
+                                       trickle_cfg);
+       if (err < 0) {
+               dev_err(&client->dev, "Unable to write trickle register\n");
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int abx80x_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       unsigned char buf[8];
+       int err;
+
+       err = i2c_smbus_read_i2c_block_data(client, ABX8XX_REG_HTH,
+                                           sizeof(buf), buf);
+       if (err < 0) {
+               dev_err(&client->dev, "Unable to read date\n");
+               return -EIO;
+       }
+
+       tm->tm_sec = bcd2bin(buf[ABX8XX_REG_SC] & 0x7F);
+       tm->tm_min = bcd2bin(buf[ABX8XX_REG_MN] & 0x7F);
+       tm->tm_hour = bcd2bin(buf[ABX8XX_REG_HR] & 0x3F);
+       tm->tm_wday = buf[ABX8XX_REG_WD] & 0x7;
+       tm->tm_mday = bcd2bin(buf[ABX8XX_REG_DA] & 0x3F);
+       tm->tm_mon = bcd2bin(buf[ABX8XX_REG_MO] & 0x1F) - 1;
+       tm->tm_year = bcd2bin(buf[ABX8XX_REG_YR]) + 100;
+
+       err = rtc_valid_tm(tm);
+       if (err < 0)
+               dev_err(&client->dev, "retrieved date/time is not valid.\n");
+
+       return err;
+}
+
+static int abx80x_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       unsigned char buf[8];
+       int err;
+
+       if (tm->tm_year < 100)
+               return -EINVAL;
+
+       buf[ABX8XX_REG_HTH] = 0;
+       buf[ABX8XX_REG_SC] = bin2bcd(tm->tm_sec);
+       buf[ABX8XX_REG_MN] = bin2bcd(tm->tm_min);
+       buf[ABX8XX_REG_HR] = bin2bcd(tm->tm_hour);
+       buf[ABX8XX_REG_DA] = bin2bcd(tm->tm_mday);
+       buf[ABX8XX_REG_MO] = bin2bcd(tm->tm_mon + 1);
+       buf[ABX8XX_REG_YR] = bin2bcd(tm->tm_year - 100);
+       buf[ABX8XX_REG_WD] = tm->tm_wday;
+
+       err = i2c_smbus_write_i2c_block_data(client, ABX8XX_REG_HTH,
+                                            sizeof(buf), buf);
+       if (err < 0) {
+               dev_err(&client->dev, "Unable to write to date registers\n");
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static const struct rtc_class_ops abx80x_rtc_ops = {
+       .read_time      = abx80x_rtc_read_time,
+       .set_time       = abx80x_rtc_set_time,
+};
+
+static int abx80x_dt_trickle_cfg(struct device_node *np)
+{
+       const char *diode;
+       int trickle_cfg = 0;
+       int i, ret;
+       u32 tmp;
+
+       ret = of_property_read_string(np, "abracon,tc-diode", &diode);
+       if (ret)
+               return ret;
+
+       if (!strcmp(diode, "standard"))
+               trickle_cfg |= ABX8XX_TRICKLE_STANDARD_DIODE;
+       else if (!strcmp(diode, "schottky"))
+               trickle_cfg |= ABX8XX_TRICKLE_SCHOTTKY_DIODE;
+       else
+               return -EINVAL;
+
+       ret = of_property_read_u32(np, "abracon,tc-resistor", &tmp);
+       if (ret)
+               return ret;
+
+       for (i = 0; i < sizeof(trickle_resistors); i++)
+               if (trickle_resistors[i] == tmp)
+                       break;
+
+       if (i == sizeof(trickle_resistors))
+               return -EINVAL;
+
+       return (trickle_cfg | i);
+}
+
+static int abx80x_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
+{
+       struct device_node *np = client->dev.of_node;
+       struct rtc_device *rtc;
+       int i, data, err, trickle_cfg = -EINVAL;
+       char buf[7];
+       unsigned int part = id->driver_data;
+       unsigned int partnumber;
+       unsigned int majrev, minrev;
+       unsigned int lot;
+       unsigned int wafer;
+       unsigned int uid;
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+               return -ENODEV;
+
+       err = i2c_smbus_read_i2c_block_data(client, ABX8XX_REG_ID0,
+                                           sizeof(buf), buf);
+       if (err < 0) {
+               dev_err(&client->dev, "Unable to read partnumber\n");
+               return -EIO;
+       }
+
+       partnumber = (buf[0] << 8) | buf[1];
+       majrev = buf[2] >> 3;
+       minrev = buf[2] & 0x7;
+       lot = ((buf[4] & 0x80) << 2) | ((buf[6] & 0x80) << 1) | buf[3];
+       uid = ((buf[4] & 0x7f) << 8) | buf[5];
+       wafer = (buf[6] & 0x7c) >> 2;
+       dev_info(&client->dev, "model %04x, revision %u.%u, lot %x, wafer %x, uid %x\n",
+                partnumber, majrev, minrev, lot, wafer, uid);
+
+       data = i2c_smbus_read_byte_data(client, ABX8XX_REG_CTRL1);
+       if (data < 0) {
+               dev_err(&client->dev, "Unable to read control register\n");
+               return -EIO;
+       }
+
+       err = i2c_smbus_write_byte_data(client, ABX8XX_REG_CTRL1,
+                                       ((data & ~ABX8XX_CTRL_12_24) |
+                                        ABX8XX_CTRL_WRITE));
+       if (err < 0) {
+               dev_err(&client->dev, "Unable to write control register\n");
+               return -EIO;
+       }
+
+       /* part autodetection */
+       if (part == ABX80X) {
+               for (i = 0; abx80x_caps[i].pn; i++)
+                       if (partnumber == abx80x_caps[i].pn)
+                               break;
+               if (abx80x_caps[i].pn == 0) {
+                       dev_err(&client->dev, "Unknown part: %04x\n",
+                               partnumber);
+                       return -EINVAL;
+               }
+               part = i;
+       }
+
+       if (partnumber != abx80x_caps[part].pn) {
+               dev_err(&client->dev, "partnumber mismatch %04x != %04x\n",
+                       partnumber, abx80x_caps[part].pn);
+               return -EINVAL;
+       }
+
+       if (np && abx80x_caps[part].has_tc)
+               trickle_cfg = abx80x_dt_trickle_cfg(np);
+
+       if (trickle_cfg > 0) {
+               dev_info(&client->dev, "Enabling trickle charger: %02x\n",
+                        trickle_cfg);
+               abx80x_enable_trickle_charger(client, trickle_cfg);
+       }
+
+       rtc = devm_rtc_device_register(&client->dev, abx80x_driver.driver.name,
+                                      &abx80x_rtc_ops, THIS_MODULE);
+
+       if (IS_ERR(rtc))
+               return PTR_ERR(rtc);
+
+       i2c_set_clientdata(client, rtc);
+
+       return 0;
+}
+
+static int abx80x_remove(struct i2c_client *client)
+{
+       return 0;
+}
+
+static const struct i2c_device_id abx80x_id[] = {
+       { "abx80x", ABX80X },
+       { "ab0801", AB0801 },
+       { "ab0803", AB0803 },
+       { "ab0804", AB0804 },
+       { "ab0805", AB0805 },
+       { "ab1801", AB1801 },
+       { "ab1803", AB1803 },
+       { "ab1804", AB1804 },
+       { "ab1805", AB1805 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, abx80x_id);
+
+static struct i2c_driver abx80x_driver = {
+       .driver         = {
+               .name   = "rtc-abx80x",
+       },
+       .probe          = abx80x_probe,
+       .remove         = abx80x_remove,
+       .id_table       = abx80x_id,
+};
+
+module_i2c_driver(abx80x_driver);
+
+MODULE_AUTHOR("Philippe De Muyter <phdm@macqel.be>");
+MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@free-electrons.com>");
+MODULE_DESCRIPTION("Abracon ABX80X RTC driver");
+MODULE_LICENSE("GPL v2");
index 43e04af39e0964e3dccd24e251f484d04a680bc9..cb70ced7e0db19771699a7b362d63b7c49e06d31 100644 (file)
@@ -40,6 +40,13 @@ struct armada38x_rtc {
        void __iomem        *regs;
        void __iomem        *regs_soc;
        spinlock_t          lock;
+       /*
+        * While setting the time, the RTC TIME register should not be
+        * accessed. Setting the RTC time involves sleeping during
+        * 100ms, so a mutex instead of a spinlock is used to protect
+        * it
+        */
+       struct mutex        mutex_time;
        int                 irq;
 };
 
@@ -59,8 +66,7 @@ static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm)
        struct armada38x_rtc *rtc = dev_get_drvdata(dev);
        unsigned long time, time_check, flags;
 
-       spin_lock_irqsave(&rtc->lock, flags);
-
+       mutex_lock(&rtc->mutex_time);
        time = readl(rtc->regs + RTC_TIME);
        /*
         * WA for failing time set attempts. As stated in HW ERRATA if
@@ -71,7 +77,7 @@ static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm)
        if ((time_check - time) > 1)
                time_check = readl(rtc->regs + RTC_TIME);
 
-       spin_unlock_irqrestore(&rtc->lock, flags);
+       mutex_unlock(&rtc->mutex_time);
 
        rtc_time_to_tm(time_check, tm);
 
@@ -94,19 +100,12 @@ static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm)
         * then wait for 100ms before writing to the time register to be
         * sure that the data will be taken into account.
         */
-       spin_lock_irqsave(&rtc->lock, flags);
-
+       mutex_lock(&rtc->mutex_time);
        rtc_delayed_write(0, rtc, RTC_STATUS);
-
-       spin_unlock_irqrestore(&rtc->lock, flags);
-
        msleep(100);
-
-       spin_lock_irqsave(&rtc->lock, flags);
-
        rtc_delayed_write(time, rtc, RTC_TIME);
+       mutex_unlock(&rtc->mutex_time);
 
-       spin_unlock_irqrestore(&rtc->lock, flags);
 out:
        return ret;
 }
@@ -230,6 +229,7 @@ static __init int armada38x_rtc_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        spin_lock_init(&rtc->lock);
+       mutex_init(&rtc->mutex_time);
 
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rtc");
        rtc->regs = devm_ioremap_resource(&pdev->dev, res);
index c43aca69fb30dffed727c210b725b46a365440dd..0fc3fe5fd5b810c77fd24bc99e269414151e3405 100644 (file)
@@ -667,6 +667,8 @@ static struct raw3215_info *raw3215_alloc_info(void)
        info->buffer = kzalloc(RAW3215_BUFFER_SIZE, GFP_KERNEL | GFP_DMA);
        info->inbuf = kzalloc(RAW3215_INBUF_SIZE, GFP_KERNEL | GFP_DMA);
        if (!info->buffer || !info->inbuf) {
+               kfree(info->inbuf);
+               kfree(info->buffer);
                kfree(info);
                return NULL;
        }
index 71d7802aa8b48b75aee89ea2aae167436c746d65..6f1fa1773e76418ef3d55917fb3146875dd4f5b7 100644 (file)
@@ -1201,13 +1201,9 @@ static int virtio_ccw_online(struct ccw_device *cdev)
        vcdev->vdev.id.vendor = cdev->id.cu_type;
        vcdev->vdev.id.device = cdev->id.cu_model;
 
-       if (virtio_device_is_legacy_only(vcdev->vdev.id)) {
-               vcdev->revision = 0;
-       } else {
-               ret = virtio_ccw_set_transport_rev(vcdev);
-               if (ret)
-                       goto out_free;
-       }
+       ret = virtio_ccw_set_transport_rev(vcdev);
+       if (ret)
+               goto out_free;
 
        ret = register_virtio_device(&vcdev->vdev);
        if (ret) {
index 7600639db4c46fb642e0b86a9e638ab94392538d..add419d6ff34996ed4aab8a145aee637ee987dbf 100644 (file)
@@ -149,7 +149,6 @@ static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset);
 static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry *sglistarg);
 static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id);
 static char *twa_string_lookup(twa_message_type *table, unsigned int aen_code);
-static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id);
 
 /* Functions */
 
@@ -1340,11 +1339,11 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance)
                                }
 
                                /* Now complete the io */
+                               scsi_dma_unmap(cmd);
+                               cmd->scsi_done(cmd);
                                tw_dev->state[request_id] = TW_S_COMPLETED;
                                twa_free_request_id(tw_dev, request_id);
                                tw_dev->posted_request_count--;
-                               tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
-                               twa_unmap_scsi_data(tw_dev, request_id);
                        }
 
                        /* Check for valid status after each drain */
@@ -1402,26 +1401,6 @@ static void twa_load_sgl(TW_Device_Extension *tw_dev, TW_Command_Full *full_comm
        }
 } /* End twa_load_sgl() */
 
-/* This function will perform a pci-dma mapping for a scatter gather list */
-static int twa_map_scsi_sg_data(TW_Device_Extension *tw_dev, int request_id)
-{
-       int use_sg;
-       struct scsi_cmnd *cmd = tw_dev->srb[request_id];
-
-       use_sg = scsi_dma_map(cmd);
-       if (!use_sg)
-               return 0;
-       else if (use_sg < 0) {
-               TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1c, "Failed to map scatter gather list");
-               return 0;
-       }
-
-       cmd->SCp.phase = TW_PHASE_SGLIST;
-       cmd->SCp.have_data_in = use_sg;
-
-       return use_sg;
-} /* End twa_map_scsi_sg_data() */
-
 /* This function will poll for a response interrupt of a request */
 static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds)
 {
@@ -1600,9 +1579,11 @@ static int twa_reset_device_extension(TW_Device_Extension *tw_dev)
                    (tw_dev->state[i] != TW_S_INITIAL) &&
                    (tw_dev->state[i] != TW_S_COMPLETED)) {
                        if (tw_dev->srb[i]) {
-                               tw_dev->srb[i]->result = (DID_RESET << 16);
-                               tw_dev->srb[i]->scsi_done(tw_dev->srb[i]);
-                               twa_unmap_scsi_data(tw_dev, i);
+                               struct scsi_cmnd *cmd = tw_dev->srb[i];
+
+                               cmd->result = (DID_RESET << 16);
+                               scsi_dma_unmap(cmd);
+                               cmd->scsi_done(cmd);
                        }
                }
        }
@@ -1781,21 +1762,18 @@ static int twa_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
        /* Save the scsi command for use by the ISR */
        tw_dev->srb[request_id] = SCpnt;
 
-       /* Initialize phase to zero */
-       SCpnt->SCp.phase = TW_PHASE_INITIAL;
-
        retval = twa_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL);
        switch (retval) {
        case SCSI_MLQUEUE_HOST_BUSY:
+               scsi_dma_unmap(SCpnt);
                twa_free_request_id(tw_dev, request_id);
-               twa_unmap_scsi_data(tw_dev, request_id);
                break;
        case 1:
-               tw_dev->state[request_id] = TW_S_COMPLETED;
-               twa_free_request_id(tw_dev, request_id);
-               twa_unmap_scsi_data(tw_dev, request_id);
                SCpnt->result = (DID_ERROR << 16);
+               scsi_dma_unmap(SCpnt);
                done(SCpnt);
+               tw_dev->state[request_id] = TW_S_COMPLETED;
+               twa_free_request_id(tw_dev, request_id);
                retval = 0;
        }
 out:
@@ -1863,8 +1841,8 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
                                command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
                                command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH);
                        } else {
-                               sg_count = twa_map_scsi_sg_data(tw_dev, request_id);
-                               if (sg_count == 0)
+                               sg_count = scsi_dma_map(srb);
+                               if (sg_count < 0)
                                        goto out;
 
                                scsi_for_each_sg(srb, sg, sg_count, i) {
@@ -1979,15 +1957,6 @@ static char *twa_string_lookup(twa_message_type *table, unsigned int code)
        return(table[index].text);
 } /* End twa_string_lookup() */
 
-/* This function will perform a pci-dma unmap */
-static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id)
-{
-       struct scsi_cmnd *cmd = tw_dev->srb[request_id];
-
-       if (cmd->SCp.phase == TW_PHASE_SGLIST)
-               scsi_dma_unmap(cmd);
-} /* End twa_unmap_scsi_data() */
-
 /* This function gets called when a disk is coming on-line */
 static int twa_slave_configure(struct scsi_device *sdev)
 {
index 040f7214e5b7a5c3782743a4a66a456aea79df81..0fdc83cfa0e1a28a42757ae52f434523238075b3 100644 (file)
@@ -324,11 +324,6 @@ static twa_message_type twa_error_table[] = {
 #define TW_CURRENT_DRIVER_BUILD 0
 #define TW_CURRENT_DRIVER_BRANCH 0
 
-/* Phase defines */
-#define TW_PHASE_INITIAL 0
-#define TW_PHASE_SINGLE  1
-#define TW_PHASE_SGLIST  2
-
 /* Misc defines */
 #define TW_9550SX_DRAIN_COMPLETED            0xFFFF
 #define TW_SECTOR_SIZE                        512
index 2361772d590966abf6f618d2e1228b0f3d424ebc..f8374850f714dd09c53aa1eb25a38bbcb7d0ee8d 100644 (file)
@@ -290,26 +290,6 @@ static int twl_post_command_packet(TW_Device_Extension *tw_dev, int request_id)
        return 0;
 } /* End twl_post_command_packet() */
 
-/* This function will perform a pci-dma mapping for a scatter gather list */
-static int twl_map_scsi_sg_data(TW_Device_Extension *tw_dev, int request_id)
-{
-       int use_sg;
-       struct scsi_cmnd *cmd = tw_dev->srb[request_id];
-
-       use_sg = scsi_dma_map(cmd);
-       if (!use_sg)
-               return 0;
-       else if (use_sg < 0) {
-               TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1, "Failed to map scatter gather list");
-               return 0;
-       }
-
-       cmd->SCp.phase = TW_PHASE_SGLIST;
-       cmd->SCp.have_data_in = use_sg;
-
-       return use_sg;
-} /* End twl_map_scsi_sg_data() */
-
 /* This function hands scsi cdb's to the firmware */
 static int twl_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry_ISO *sglistarg)
 {
@@ -357,8 +337,8 @@ static int twl_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
        if (!sglistarg) {
                /* Map sglist from scsi layer to cmd packet */
                if (scsi_sg_count(srb)) {
-                       sg_count = twl_map_scsi_sg_data(tw_dev, request_id);
-                       if (sg_count == 0)
+                       sg_count = scsi_dma_map(srb);
+                       if (sg_count <= 0)
                                goto out;
 
                        scsi_for_each_sg(srb, sg, sg_count, i) {
@@ -1102,15 +1082,6 @@ out:
        return retval;
 } /* End twl_initialize_device_extension() */
 
-/* This function will perform a pci-dma unmap */
-static void twl_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id)
-{
-       struct scsi_cmnd *cmd = tw_dev->srb[request_id];
-
-       if (cmd->SCp.phase == TW_PHASE_SGLIST)
-               scsi_dma_unmap(cmd);
-} /* End twl_unmap_scsi_data() */
-
 /* This function will handle attention interrupts */
 static int twl_handle_attention_interrupt(TW_Device_Extension *tw_dev)
 {
@@ -1251,11 +1222,11 @@ static irqreturn_t twl_interrupt(int irq, void *dev_instance)
                        }
 
                        /* Now complete the io */
+                       scsi_dma_unmap(cmd);
+                       cmd->scsi_done(cmd);
                        tw_dev->state[request_id] = TW_S_COMPLETED;
                        twl_free_request_id(tw_dev, request_id);
                        tw_dev->posted_request_count--;
-                       tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
-                       twl_unmap_scsi_data(tw_dev, request_id);
                }
 
                /* Check for another response interrupt */
@@ -1400,10 +1371,12 @@ static int twl_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_res
                if ((tw_dev->state[i] != TW_S_FINISHED) &&
                    (tw_dev->state[i] != TW_S_INITIAL) &&
                    (tw_dev->state[i] != TW_S_COMPLETED)) {
-                       if (tw_dev->srb[i]) {
-                               tw_dev->srb[i]->result = (DID_RESET << 16);
-                               tw_dev->srb[i]->scsi_done(tw_dev->srb[i]);
-                               twl_unmap_scsi_data(tw_dev, i);
+                       struct scsi_cmnd *cmd = tw_dev->srb[i];
+
+                       if (cmd) {
+                               cmd->result = (DID_RESET << 16);
+                               scsi_dma_unmap(cmd);
+                               cmd->scsi_done(cmd);
                        }
                }
        }
@@ -1507,9 +1480,6 @@ static int twl_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
        /* Save the scsi command for use by the ISR */
        tw_dev->srb[request_id] = SCpnt;
 
-       /* Initialize phase to zero */
-       SCpnt->SCp.phase = TW_PHASE_INITIAL;
-
        retval = twl_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL);
        if (retval) {
                tw_dev->state[request_id] = TW_S_COMPLETED;
index d474892701d4540658a36b48edb7b903a8b9ba76..fec6449c7595132f706439277cd396b4dc66c0a8 100644 (file)
@@ -103,10 +103,6 @@ static char *twl_aen_severity_table[] =
 #define TW_CURRENT_DRIVER_BUILD 0
 #define TW_CURRENT_DRIVER_BRANCH 0
 
-/* Phase defines */
-#define TW_PHASE_INITIAL 0
-#define TW_PHASE_SGLIST  2
-
 /* Misc defines */
 #define TW_SECTOR_SIZE                        512
 #define TW_MAX_UNITS                         32
index c75f2048319f7ced2ba9f9956a2a56f41b181a24..2940bd769936cd7f75d2d20adc324914b0df4b84 100644 (file)
@@ -1271,32 +1271,6 @@ static int tw_initialize_device_extension(TW_Device_Extension *tw_dev)
        return 0;
 } /* End tw_initialize_device_extension() */
 
-static int tw_map_scsi_sg_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
-{
-       int use_sg;
-
-       dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data()\n");
-
-       use_sg = scsi_dma_map(cmd);
-       if (use_sg < 0) {
-               printk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data(): pci_map_sg() failed.\n");
-               return 0;
-       }
-
-       cmd->SCp.phase = TW_PHASE_SGLIST;
-       cmd->SCp.have_data_in = use_sg;
-
-       return use_sg;
-} /* End tw_map_scsi_sg_data() */
-
-static void tw_unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
-{
-       dprintk(KERN_WARNING "3w-xxxx: tw_unmap_scsi_data()\n");
-
-       if (cmd->SCp.phase == TW_PHASE_SGLIST)
-               scsi_dma_unmap(cmd);
-} /* End tw_unmap_scsi_data() */
-
 /* This function will reset a device extension */
 static int tw_reset_device_extension(TW_Device_Extension *tw_dev)
 {
@@ -1319,8 +1293,8 @@ static int tw_reset_device_extension(TW_Device_Extension *tw_dev)
                        srb = tw_dev->srb[i];
                        if (srb != NULL) {
                                srb->result = (DID_RESET << 16);
-                               tw_dev->srb[i]->scsi_done(tw_dev->srb[i]);
-                               tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[i]);
+                               scsi_dma_unmap(srb);
+                               srb->scsi_done(srb);
                        }
                }
        }
@@ -1767,8 +1741,8 @@ static int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id)
        command_packet->byte8.io.lba = lba;
        command_packet->byte6.block_count = num_sectors;
 
-       use_sg = tw_map_scsi_sg_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
-       if (!use_sg)
+       use_sg = scsi_dma_map(srb);
+       if (use_sg <= 0)
                return 1;
 
        scsi_for_each_sg(tw_dev->srb[request_id], sg, use_sg, i) {
@@ -1955,9 +1929,6 @@ static int tw_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_c
        /* Save the scsi command for use by the ISR */
        tw_dev->srb[request_id] = SCpnt;
 
-       /* Initialize phase to zero */
-       SCpnt->SCp.phase = TW_PHASE_INITIAL;
-
        switch (*command) {
                case READ_10:
                case READ_6:
@@ -2185,12 +2156,11 @@ static irqreturn_t tw_interrupt(int irq, void *dev_instance)
 
                                /* Now complete the io */
                                if ((error != TW_ISR_DONT_COMPLETE)) {
+                                       scsi_dma_unmap(tw_dev->srb[request_id]);
+                                       tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
                                        tw_dev->state[request_id] = TW_S_COMPLETED;
                                        tw_state_request_finish(tw_dev, request_id);
                                        tw_dev->posted_request_count--;
-                                       tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
-                                       
-                                       tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
                                }
                        }
                                
index 29b0b84ed69e888b1939c57dde7e60589506e992..6f65e663d3932108edaed6b75eba328d469f4fce 100644 (file)
@@ -195,11 +195,6 @@ static unsigned char tw_sense_table[][4] =
 #define TW_AEN_SMART_FAIL        0x000F
 #define TW_AEN_SBUF_FAIL         0x0024
 
-/* Phase defines */
-#define TW_PHASE_INITIAL 0
-#define TW_PHASE_SINGLE 1
-#define TW_PHASE_SGLIST 2
-
 /* Misc defines */
 #define TW_ALIGNMENT_6000                    64 /* 64 bytes */
 #define TW_ALIGNMENT_7000                     4  /* 4 bytes */
index ec432763a29a3c3472a53952e017b1d831cd214e..b95d2779f4679cba20908b86a92502b32ec33a06 100644 (file)
@@ -375,9 +375,10 @@ static int aha1542_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
        u8 lun = cmd->device->lun;
        unsigned long flags;
        int bufflen = scsi_bufflen(cmd);
-       int mbo;
+       int mbo, sg_count;
        struct mailbox *mb = aha1542->mb;
        struct ccb *ccb = aha1542->ccb;
+       struct chain *cptr;
 
        if (*cmd->cmnd == REQUEST_SENSE) {
                /* Don't do the command - we have the sense data already */
@@ -397,6 +398,13 @@ static int aha1542_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
                print_hex_dump_bytes("command: ", DUMP_PREFIX_NONE, cmd->cmnd, cmd->cmd_len);
        }
 #endif
+       if (bufflen) {  /* allocate memory before taking host_lock */
+               sg_count = scsi_sg_count(cmd);
+               cptr = kmalloc(sizeof(*cptr) * sg_count, GFP_KERNEL | GFP_DMA);
+               if (!cptr)
+                       return SCSI_MLQUEUE_HOST_BUSY;
+       }
+
        /* Use the outgoing mailboxes in a round-robin fashion, because this
           is how the host adapter will scan for them */
 
@@ -441,19 +449,10 @@ static int aha1542_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
 
        if (bufflen) {
                struct scatterlist *sg;
-               struct chain *cptr;
-               int i, sg_count = scsi_sg_count(cmd);
+               int i;
 
                ccb[mbo].op = 2;        /* SCSI Initiator Command  w/scatter-gather */
-               cmd->host_scribble = kmalloc(sizeof(*cptr)*sg_count,
-                                                        GFP_KERNEL | GFP_DMA);
-               cptr = (struct chain *) cmd->host_scribble;
-               if (cptr == NULL) {
-                       /* free the claimed mailbox slot */
-                       aha1542->int_cmds[mbo] = NULL;
-                       spin_unlock_irqrestore(sh->host_lock, flags);
-                       return SCSI_MLQUEUE_HOST_BUSY;
-               }
+               cmd->host_scribble = (void *)cptr;
                scsi_for_each_sg(cmd, sg, sg_count, i) {
                        any2scsi(cptr[i].dataptr, isa_page_to_bus(sg_page(sg))
                                                                + sg->offset);
index 57418258c1017631798b73d78bf73e2367ae8917..fe8a8d157e225df6018f101ec0f3a0be3d3e786f 100644 (file)
@@ -3065,7 +3065,7 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle,
 {
        struct qla_hw_data *ha = vha->hw;
        struct se_cmd *se_cmd;
-       struct target_core_fabric_ops *tfo;
+       const struct target_core_fabric_ops *tfo;
        struct qla_tgt_cmd *cmd;
 
        if (handle & CTIO_INTERMEDIATE_HANDLE_MARK) {
index ab4879e12ea7fd0b2745327400b2166451519483..68c2002e78bf80d3b383b92f76519901459059da 100644 (file)
@@ -53,9 +53,8 @@
 static struct workqueue_struct *tcm_qla2xxx_free_wq;
 static struct workqueue_struct *tcm_qla2xxx_cmd_wq;
 
-/* Local pointer to allocated TCM configfs fabric module */
-static struct target_fabric_configfs *tcm_qla2xxx_fabric_configfs;
-static struct target_fabric_configfs *tcm_qla2xxx_npiv_fabric_configfs;
+static const struct target_core_fabric_ops tcm_qla2xxx_ops;
+static const struct target_core_fabric_ops tcm_qla2xxx_npiv_ops;
 
 /*
  * Parse WWN.
@@ -336,6 +335,14 @@ static int tcm_qla2xxx_check_demo_mode_login_only(struct se_portal_group *se_tpg
        return tpg->tpg_attrib.demo_mode_login_only;
 }
 
+static int tcm_qla2xxx_check_prot_fabric_only(struct se_portal_group *se_tpg)
+{
+       struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
+                               struct tcm_qla2xxx_tpg, se_tpg);
+
+       return tpg->tpg_attrib.fabric_prot_type;
+}
+
 static struct se_node_acl *tcm_qla2xxx_alloc_fabric_acl(
        struct se_portal_group *se_tpg)
 {
@@ -1082,8 +1089,53 @@ static ssize_t tcm_qla2xxx_tpg_store_enable(
 
 TF_TPG_BASE_ATTR(tcm_qla2xxx, enable, S_IRUGO | S_IWUSR);
 
+static ssize_t tcm_qla2xxx_tpg_show_dynamic_sessions(
+       struct se_portal_group *se_tpg,
+       char *page)
+{
+       return target_show_dynamic_sessions(se_tpg, page);
+}
+
+TF_TPG_BASE_ATTR_RO(tcm_qla2xxx, dynamic_sessions);
+
+static ssize_t tcm_qla2xxx_tpg_store_fabric_prot_type(
+       struct se_portal_group *se_tpg,
+       const char *page,
+       size_t count)
+{
+       struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
+                               struct tcm_qla2xxx_tpg, se_tpg);
+       unsigned long val;
+       int ret = kstrtoul(page, 0, &val);
+
+       if (ret) {
+               pr_err("kstrtoul() returned %d for fabric_prot_type\n", ret);
+               return ret;
+       }
+       if (val != 0 && val != 1 && val != 3) {
+               pr_err("Invalid qla2xxx fabric_prot_type: %lu\n", val);
+               return -EINVAL;
+       }
+       tpg->tpg_attrib.fabric_prot_type = val;
+
+       return count;
+}
+
+static ssize_t tcm_qla2xxx_tpg_show_fabric_prot_type(
+       struct se_portal_group *se_tpg,
+       char *page)
+{
+       struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
+                               struct tcm_qla2xxx_tpg, se_tpg);
+
+       return sprintf(page, "%d\n", tpg->tpg_attrib.fabric_prot_type);
+}
+TF_TPG_BASE_ATTR(tcm_qla2xxx, fabric_prot_type, S_IRUGO | S_IWUSR);
+
 static struct configfs_attribute *tcm_qla2xxx_tpg_attrs[] = {
        &tcm_qla2xxx_tpg_enable.attr,
+       &tcm_qla2xxx_tpg_dynamic_sessions.attr,
+       &tcm_qla2xxx_tpg_fabric_prot_type.attr,
        NULL,
 };
 
@@ -1124,7 +1176,7 @@ static struct se_portal_group *tcm_qla2xxx_make_tpg(
        tpg->tpg_attrib.cache_dynamic_acls = 1;
        tpg->tpg_attrib.demo_mode_login_only = 1;
 
-       ret = core_tpg_register(&tcm_qla2xxx_fabric_configfs->tf_ops, wwn,
+       ret = core_tpg_register(&tcm_qla2xxx_ops, wwn,
                                &tpg->se_tpg, tpg, TRANSPORT_TPG_TYPE_NORMAL);
        if (ret < 0) {
                kfree(tpg);
@@ -1244,7 +1296,7 @@ static struct se_portal_group *tcm_qla2xxx_npiv_make_tpg(
        tpg->tpg_attrib.cache_dynamic_acls = 1;
        tpg->tpg_attrib.demo_mode_login_only = 1;
 
-       ret = core_tpg_register(&tcm_qla2xxx_npiv_fabric_configfs->tf_ops, wwn,
+       ret = core_tpg_register(&tcm_qla2xxx_npiv_ops, wwn,
                                &tpg->se_tpg, tpg, TRANSPORT_TPG_TYPE_NORMAL);
        if (ret < 0) {
                kfree(tpg);
@@ -1560,7 +1612,7 @@ static int tcm_qla2xxx_check_initiator_node_acl(
 
        se_sess = transport_init_session_tags(num_tags,
                                              sizeof(struct qla_tgt_cmd),
-                                             TARGET_PROT_NORMAL);
+                                             TARGET_PROT_ALL);
        if (IS_ERR(se_sess)) {
                pr_err("Unable to initialize struct se_session\n");
                return PTR_ERR(se_sess);
@@ -1934,7 +1986,9 @@ static struct configfs_attribute *tcm_qla2xxx_wwn_attrs[] = {
        NULL,
 };
 
-static struct target_core_fabric_ops tcm_qla2xxx_ops = {
+static const struct target_core_fabric_ops tcm_qla2xxx_ops = {
+       .module                         = THIS_MODULE,
+       .name                           = "qla2xxx",
        .get_fabric_name                = tcm_qla2xxx_get_fabric_name,
        .get_fabric_proto_ident         = tcm_qla2xxx_get_fabric_proto_ident,
        .tpg_get_wwn                    = tcm_qla2xxx_get_fabric_wwn,
@@ -1949,6 +2003,7 @@ static struct target_core_fabric_ops tcm_qla2xxx_ops = {
                                        tcm_qla2xxx_check_demo_write_protect,
        .tpg_check_prod_mode_write_protect =
                                        tcm_qla2xxx_check_prod_write_protect,
+       .tpg_check_prot_fabric_only     = tcm_qla2xxx_check_prot_fabric_only,
        .tpg_check_demo_mode_login_only = tcm_qla2xxx_check_demo_mode_login_only,
        .tpg_alloc_fabric_acl           = tcm_qla2xxx_alloc_fabric_acl,
        .tpg_release_fabric_acl         = tcm_qla2xxx_release_fabric_acl,
@@ -1983,9 +2038,15 @@ static struct target_core_fabric_ops tcm_qla2xxx_ops = {
        .fabric_drop_np                 = NULL,
        .fabric_make_nodeacl            = tcm_qla2xxx_make_nodeacl,
        .fabric_drop_nodeacl            = tcm_qla2xxx_drop_nodeacl,
+
+       .tfc_wwn_attrs                  = tcm_qla2xxx_wwn_attrs,
+       .tfc_tpg_base_attrs             = tcm_qla2xxx_tpg_attrs,
+       .tfc_tpg_attrib_attrs           = tcm_qla2xxx_tpg_attrib_attrs,
 };
 
-static struct target_core_fabric_ops tcm_qla2xxx_npiv_ops = {
+static const struct target_core_fabric_ops tcm_qla2xxx_npiv_ops = {
+       .module                         = THIS_MODULE,
+       .name                           = "qla2xxx_npiv",
        .get_fabric_name                = tcm_qla2xxx_npiv_get_fabric_name,
        .get_fabric_proto_ident         = tcm_qla2xxx_get_fabric_proto_ident,
        .tpg_get_wwn                    = tcm_qla2xxx_get_fabric_wwn,
@@ -2033,94 +2094,26 @@ static struct target_core_fabric_ops tcm_qla2xxx_npiv_ops = {
        .fabric_drop_np                 = NULL,
        .fabric_make_nodeacl            = tcm_qla2xxx_make_nodeacl,
        .fabric_drop_nodeacl            = tcm_qla2xxx_drop_nodeacl,
+
+       .tfc_wwn_attrs                  = tcm_qla2xxx_wwn_attrs,
+       .tfc_tpg_base_attrs             = tcm_qla2xxx_npiv_tpg_attrs,
 };
 
 static int tcm_qla2xxx_register_configfs(void)
 {
-       struct target_fabric_configfs *fabric, *npiv_fabric;
        int ret;
 
        pr_debug("TCM QLOGIC QLA2XXX fabric module %s on %s/%s on "
            UTS_RELEASE"\n", TCM_QLA2XXX_VERSION, utsname()->sysname,
            utsname()->machine);
-       /*
-        * Register the top level struct config_item_type with TCM core
-        */
-       fabric = target_fabric_configfs_init(THIS_MODULE, "qla2xxx");
-       if (IS_ERR(fabric)) {
-               pr_err("target_fabric_configfs_init() failed\n");
-               return PTR_ERR(fabric);
-       }
-       /*
-        * Setup fabric->tf_ops from our local tcm_qla2xxx_ops
-        */
-       fabric->tf_ops = tcm_qla2xxx_ops;
-       /*
-        * Setup default attribute lists for various fabric->tf_cit_tmpl
-        */
-       fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = tcm_qla2xxx_wwn_attrs;
-       fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = tcm_qla2xxx_tpg_attrs;
-       fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs =
-                                               tcm_qla2xxx_tpg_attrib_attrs;
-       fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_nacl_base_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_nacl_auth_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_nacl_param_cit.ct_attrs = NULL;
-       /*
-        * Register the fabric for use within TCM
-        */
-       ret = target_fabric_configfs_register(fabric);
-       if (ret < 0) {
-               pr_err("target_fabric_configfs_register() failed for TCM_QLA2XXX\n");
+
+       ret = target_register_template(&tcm_qla2xxx_ops);
+       if (ret)
                return ret;
-       }
-       /*
-        * Setup our local pointer to *fabric
-        */
-       tcm_qla2xxx_fabric_configfs = fabric;
-       pr_debug("TCM_QLA2XXX[0] - Set fabric -> tcm_qla2xxx_fabric_configfs\n");
 
-       /*
-        * Register the top level struct config_item_type for NPIV with TCM core
-        */
-       npiv_fabric = target_fabric_configfs_init(THIS_MODULE, "qla2xxx_npiv");
-       if (IS_ERR(npiv_fabric)) {
-               pr_err("target_fabric_configfs_init() failed\n");
-               ret = PTR_ERR(npiv_fabric);
-               goto out_fabric;
-       }
-       /*
-        * Setup fabric->tf_ops from our local tcm_qla2xxx_npiv_ops
-        */
-       npiv_fabric->tf_ops = tcm_qla2xxx_npiv_ops;
-       /*
-        * Setup default attribute lists for various npiv_fabric->tf_cit_tmpl
-        */
-       npiv_fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = tcm_qla2xxx_wwn_attrs;
-       npiv_fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs =
-           tcm_qla2xxx_npiv_tpg_attrs;
-       npiv_fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = NULL;
-       npiv_fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL;
-       npiv_fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;
-       npiv_fabric->tf_cit_tmpl.tfc_tpg_nacl_base_cit.ct_attrs = NULL;
-       npiv_fabric->tf_cit_tmpl.tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;
-       npiv_fabric->tf_cit_tmpl.tfc_tpg_nacl_auth_cit.ct_attrs = NULL;
-       npiv_fabric->tf_cit_tmpl.tfc_tpg_nacl_param_cit.ct_attrs = NULL;
-       /*
-        * Register the npiv_fabric for use within TCM
-        */
-       ret = target_fabric_configfs_register(npiv_fabric);
-       if (ret < 0) {
-               pr_err("target_fabric_configfs_register() failed for TCM_QLA2XXX\n");
+       ret = target_register_template(&tcm_qla2xxx_npiv_ops);
+       if (ret)
                goto out_fabric;
-       }
-       /*
-        * Setup our local pointer to *npiv_fabric
-        */
-       tcm_qla2xxx_npiv_fabric_configfs = npiv_fabric;
-       pr_debug("TCM_QLA2XXX[0] - Set fabric -> tcm_qla2xxx_npiv_fabric_configfs\n");
 
        tcm_qla2xxx_free_wq = alloc_workqueue("tcm_qla2xxx_free",
                                                WQ_MEM_RECLAIM, 0);
@@ -2140,9 +2133,9 @@ static int tcm_qla2xxx_register_configfs(void)
 out_free_wq:
        destroy_workqueue(tcm_qla2xxx_free_wq);
 out_fabric_npiv:
-       target_fabric_configfs_deregister(tcm_qla2xxx_npiv_fabric_configfs);
+       target_unregister_template(&tcm_qla2xxx_npiv_ops);
 out_fabric:
-       target_fabric_configfs_deregister(tcm_qla2xxx_fabric_configfs);
+       target_unregister_template(&tcm_qla2xxx_ops);
        return ret;
 }
 
@@ -2151,13 +2144,8 @@ static void tcm_qla2xxx_deregister_configfs(void)
        destroy_workqueue(tcm_qla2xxx_cmd_wq);
        destroy_workqueue(tcm_qla2xxx_free_wq);
 
-       target_fabric_configfs_deregister(tcm_qla2xxx_fabric_configfs);
-       tcm_qla2xxx_fabric_configfs = NULL;
-       pr_debug("TCM_QLA2XXX[0] - Cleared tcm_qla2xxx_fabric_configfs\n");
-
-       target_fabric_configfs_deregister(tcm_qla2xxx_npiv_fabric_configfs);
-       tcm_qla2xxx_npiv_fabric_configfs = NULL;
-       pr_debug("TCM_QLA2XXX[0] - Cleared tcm_qla2xxx_npiv_fabric_configfs\n");
+       target_unregister_template(&tcm_qla2xxx_ops);
+       target_unregister_template(&tcm_qla2xxx_npiv_ops);
 }
 
 static int __init tcm_qla2xxx_init(void)
index 10c002145648cfb2deeda14c0d83568025ec5bef..23295115c9fc60d7ece0b7448e99fe31c2acf6cc 100644 (file)
@@ -33,6 +33,7 @@ struct tcm_qla2xxx_tpg_attrib {
        int demo_mode_write_protect;
        int prod_mode_write_protect;
        int demo_mode_login_only;
+       int fabric_prot_type;
 };
 
 struct tcm_qla2xxx_tpg {
index 262ab837a7040d5586e4212b59e569aa55a2df0c..9f77d23239a264d85a2331ea50737cbfdc88ee36 100644 (file)
@@ -226,6 +226,7 @@ static struct {
        {"PIONEER", "CD-ROM DRM-624X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
        {"Promise", "VTrak E610f", NULL, BLIST_SPARSELUN | BLIST_NO_RSOC},
        {"Promise", "", NULL, BLIST_SPARSELUN},
+       {"QNAP", "iSCSI Storage", NULL, BLIST_MAX_1024},
        {"QUANTUM", "XP34301", "1071", BLIST_NOTQ},
        {"REGAL", "CDC-4X", NULL, BLIST_MAX5LUN | BLIST_SINGLELUN},
        {"SanDisk", "ImageMate CF-SD1", NULL, BLIST_FORCELUN},
index 60aae01caa89d96cd8c78681a8f0a97b44cae8ec..6efab1c455e158a71a2792c07d9b6d3fadc7595c 100644 (file)
@@ -897,6 +897,12 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
         */
        if (*bflags & BLIST_MAX_512)
                blk_queue_max_hw_sectors(sdev->request_queue, 512);
+       /*
+        * Max 1024 sector transfer length for targets that report incorrect
+        * max/optimal lengths and relied on the old block layer safe default
+        */
+       else if (*bflags & BLIST_MAX_1024)
+               blk_queue_max_hw_sectors(sdev->request_queue, 1024);
 
        /*
         * Some devices may not want to have a start command automatically
index cd4c293f0dd0d375be6d6d815108aeb588304fec..fe8875f0d7be1155883655150ec57c3115356bbe 100644 (file)
@@ -80,9 +80,10 @@ static int __init sh_pm_runtime_init(void)
        if (IS_ENABLED(CONFIG_ARCH_SHMOBILE_MULTI)) {
                if (!of_machine_is_compatible("renesas,emev2") &&
                    !of_machine_is_compatible("renesas,r7s72100") &&
-                   !of_machine_is_compatible("renesas,r8a73a4") &&
 #ifndef CONFIG_PM_GENERIC_DOMAINS_OF
+                   !of_machine_is_compatible("renesas,r8a73a4") &&
                    !of_machine_is_compatible("renesas,r8a7740") &&
+                   !of_machine_is_compatible("renesas,sh73a0") &&
 #endif
                    !of_machine_is_compatible("renesas,r8a7778") &&
                    !of_machine_is_compatible("renesas,r8a7779") &&
@@ -90,9 +91,7 @@ static int __init sh_pm_runtime_init(void)
                    !of_machine_is_compatible("renesas,r8a7791") &&
                    !of_machine_is_compatible("renesas,r8a7792") &&
                    !of_machine_is_compatible("renesas,r8a7793") &&
-                   !of_machine_is_compatible("renesas,r8a7794") &&
-                   !of_machine_is_compatible("renesas,sh7372") &&
-                   !of_machine_is_compatible("renesas,sh73a0"))
+                   !of_machine_is_compatible("renesas,r8a7794"))
                        return 0;
        }
 
index 76d6bd4da138f1162fc8a7dcc516b54d4f26b26b..d8bde82f03708bf96f7c3fbd86cdbcdd20b9689b 100644 (file)
@@ -1,5 +1,6 @@
 menu "SOC (System On Chip) specific Drivers"
 
+source "drivers/soc/mediatek/Kconfig"
 source "drivers/soc/qcom/Kconfig"
 source "drivers/soc/ti/Kconfig"
 source "drivers/soc/versatile/Kconfig"
index 063113d0bd3871b131caec6ea902cef2f283209e..70042b259744eab805dea6e65aff46e03a74da25 100644 (file)
@@ -2,6 +2,7 @@
 # Makefile for the Linux Kernel SOC specific device drivers.
 #
 
+obj-$(CONFIG_ARCH_MEDIATEK)    += mediatek/
 obj-$(CONFIG_ARCH_QCOM)                += qcom/
 obj-$(CONFIG_ARCH_TEGRA)       += tegra/
 obj-$(CONFIG_SOC_TI)           += ti/
diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
new file mode 100644 (file)
index 0000000..bcdb22d
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# MediaTek SoC drivers
+#
+config MTK_PMIC_WRAP
+       tristate "MediaTek PMIC Wrapper Support"
+       depends on ARCH_MEDIATEK
+       select REGMAP
+       help
+         Say yes here to add support for MediaTek PMIC Wrapper found
+         on different MediaTek SoCs. The PMIC wrapper is a proprietary
+         hardware to connect the PMIC.
diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
new file mode 100644 (file)
index 0000000..ecaf4de
--- /dev/null
@@ -0,0 +1 @@
+obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c
new file mode 100644 (file)
index 0000000..db5be1e
--- /dev/null
@@ -0,0 +1,975 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu, MediaTek
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#define PWRAP_MT8135_BRIDGE_IORD_ARB_EN                0x4
+#define PWRAP_MT8135_BRIDGE_WACS3_EN           0x10
+#define PWRAP_MT8135_BRIDGE_INIT_DONE3         0x14
+#define PWRAP_MT8135_BRIDGE_WACS4_EN           0x24
+#define PWRAP_MT8135_BRIDGE_INIT_DONE4         0x28
+#define PWRAP_MT8135_BRIDGE_INT_EN             0x38
+#define PWRAP_MT8135_BRIDGE_TIMER_EN           0x48
+#define PWRAP_MT8135_BRIDGE_WDT_UNIT           0x50
+#define PWRAP_MT8135_BRIDGE_WDT_SRC_EN         0x54
+
+/* macro for wrapper status */
+#define PWRAP_GET_WACS_RDATA(x)                (((x) >> 0) & 0x0000ffff)
+#define PWRAP_GET_WACS_FSM(x)          (((x) >> 16) & 0x00000007)
+#define PWRAP_GET_WACS_REQ(x)          (((x) >> 19) & 0x00000001)
+#define PWRAP_STATE_SYNC_IDLE0         (1 << 20)
+#define PWRAP_STATE_INIT_DONE0         (1 << 21)
+
+/* macro for WACS FSM */
+#define PWRAP_WACS_FSM_IDLE            0x00
+#define PWRAP_WACS_FSM_REQ             0x02
+#define PWRAP_WACS_FSM_WFDLE           0x04
+#define PWRAP_WACS_FSM_WFVLDCLR                0x06
+#define PWRAP_WACS_INIT_DONE           0x01
+#define PWRAP_WACS_WACS_SYNC_IDLE      0x01
+#define PWRAP_WACS_SYNC_BUSY           0x00
+
+/* macro for device wrapper default value */
+#define PWRAP_DEW_READ_TEST_VAL                0x5aa5
+#define PWRAP_DEW_WRITE_TEST_VAL       0xa55a
+
+/* macro for manual command */
+#define PWRAP_MAN_CMD_SPI_WRITE                (1 << 13)
+#define PWRAP_MAN_CMD_OP_CSH           (0x0 << 8)
+#define PWRAP_MAN_CMD_OP_CSL           (0x1 << 8)
+#define PWRAP_MAN_CMD_OP_CK            (0x2 << 8)
+#define PWRAP_MAN_CMD_OP_OUTS          (0x8 << 8)
+#define PWRAP_MAN_CMD_OP_OUTD          (0x9 << 8)
+#define PWRAP_MAN_CMD_OP_OUTQ          (0xa << 8)
+
+/* macro for slave device wrapper registers */
+#define PWRAP_DEW_BASE                 0xbc00
+#define PWRAP_DEW_EVENT_OUT_EN         (PWRAP_DEW_BASE + 0x0)
+#define PWRAP_DEW_DIO_EN               (PWRAP_DEW_BASE + 0x2)
+#define PWRAP_DEW_EVENT_SRC_EN         (PWRAP_DEW_BASE + 0x4)
+#define PWRAP_DEW_EVENT_SRC            (PWRAP_DEW_BASE + 0x6)
+#define PWRAP_DEW_EVENT_FLAG           (PWRAP_DEW_BASE + 0x8)
+#define PWRAP_DEW_READ_TEST            (PWRAP_DEW_BASE + 0xa)
+#define PWRAP_DEW_WRITE_TEST           (PWRAP_DEW_BASE + 0xc)
+#define PWRAP_DEW_CRC_EN               (PWRAP_DEW_BASE + 0xe)
+#define PWRAP_DEW_CRC_VAL              (PWRAP_DEW_BASE + 0x10)
+#define PWRAP_DEW_MON_GRP_SEL          (PWRAP_DEW_BASE + 0x12)
+#define PWRAP_DEW_MON_FLAG_SEL         (PWRAP_DEW_BASE + 0x14)
+#define PWRAP_DEW_EVENT_TEST           (PWRAP_DEW_BASE + 0x16)
+#define PWRAP_DEW_CIPHER_KEY_SEL       (PWRAP_DEW_BASE + 0x18)
+#define PWRAP_DEW_CIPHER_IV_SEL                (PWRAP_DEW_BASE + 0x1a)
+#define PWRAP_DEW_CIPHER_LOAD          (PWRAP_DEW_BASE + 0x1c)
+#define PWRAP_DEW_CIPHER_START         (PWRAP_DEW_BASE + 0x1e)
+#define PWRAP_DEW_CIPHER_RDY           (PWRAP_DEW_BASE + 0x20)
+#define PWRAP_DEW_CIPHER_MODE          (PWRAP_DEW_BASE + 0x22)
+#define PWRAP_DEW_CIPHER_SWRST         (PWRAP_DEW_BASE + 0x24)
+#define PWRAP_MT8173_DEW_CIPHER_IV0    (PWRAP_DEW_BASE + 0x26)
+#define PWRAP_MT8173_DEW_CIPHER_IV1    (PWRAP_DEW_BASE + 0x28)
+#define PWRAP_MT8173_DEW_CIPHER_IV2    (PWRAP_DEW_BASE + 0x2a)
+#define PWRAP_MT8173_DEW_CIPHER_IV3    (PWRAP_DEW_BASE + 0x2c)
+#define PWRAP_MT8173_DEW_CIPHER_IV4    (PWRAP_DEW_BASE + 0x2e)
+#define PWRAP_MT8173_DEW_CIPHER_IV5    (PWRAP_DEW_BASE + 0x30)
+
+enum pwrap_regs {
+       PWRAP_MUX_SEL,
+       PWRAP_WRAP_EN,
+       PWRAP_DIO_EN,
+       PWRAP_SIDLY,
+       PWRAP_CSHEXT_WRITE,
+       PWRAP_CSHEXT_READ,
+       PWRAP_CSLEXT_START,
+       PWRAP_CSLEXT_END,
+       PWRAP_STAUPD_PRD,
+       PWRAP_STAUPD_GRPEN,
+       PWRAP_STAUPD_MAN_TRIG,
+       PWRAP_STAUPD_STA,
+       PWRAP_WRAP_STA,
+       PWRAP_HARB_INIT,
+       PWRAP_HARB_HPRIO,
+       PWRAP_HIPRIO_ARB_EN,
+       PWRAP_HARB_STA0,
+       PWRAP_HARB_STA1,
+       PWRAP_MAN_EN,
+       PWRAP_MAN_CMD,
+       PWRAP_MAN_RDATA,
+       PWRAP_MAN_VLDCLR,
+       PWRAP_WACS0_EN,
+       PWRAP_INIT_DONE0,
+       PWRAP_WACS0_CMD,
+       PWRAP_WACS0_RDATA,
+       PWRAP_WACS0_VLDCLR,
+       PWRAP_WACS1_EN,
+       PWRAP_INIT_DONE1,
+       PWRAP_WACS1_CMD,
+       PWRAP_WACS1_RDATA,
+       PWRAP_WACS1_VLDCLR,
+       PWRAP_WACS2_EN,
+       PWRAP_INIT_DONE2,
+       PWRAP_WACS2_CMD,
+       PWRAP_WACS2_RDATA,
+       PWRAP_WACS2_VLDCLR,
+       PWRAP_INT_EN,
+       PWRAP_INT_FLG_RAW,
+       PWRAP_INT_FLG,
+       PWRAP_INT_CLR,
+       PWRAP_SIG_ADR,
+       PWRAP_SIG_MODE,
+       PWRAP_SIG_VALUE,
+       PWRAP_SIG_ERRVAL,
+       PWRAP_CRC_EN,
+       PWRAP_TIMER_EN,
+       PWRAP_TIMER_STA,
+       PWRAP_WDT_UNIT,
+       PWRAP_WDT_SRC_EN,
+       PWRAP_WDT_FLG,
+       PWRAP_DEBUG_INT_SEL,
+       PWRAP_CIPHER_KEY_SEL,
+       PWRAP_CIPHER_IV_SEL,
+       PWRAP_CIPHER_RDY,
+       PWRAP_CIPHER_MODE,
+       PWRAP_CIPHER_SWRST,
+       PWRAP_DCM_EN,
+       PWRAP_DCM_DBC_PRD,
+
+       /* MT8135 only regs */
+       PWRAP_CSHEXT,
+       PWRAP_EVENT_IN_EN,
+       PWRAP_EVENT_DST_EN,
+       PWRAP_RRARB_INIT,
+       PWRAP_RRARB_EN,
+       PWRAP_RRARB_STA0,
+       PWRAP_RRARB_STA1,
+       PWRAP_EVENT_STA,
+       PWRAP_EVENT_STACLR,
+       PWRAP_CIPHER_LOAD,
+       PWRAP_CIPHER_START,
+
+       /* MT8173 only regs */
+       PWRAP_RDDMY,
+       PWRAP_SI_CK_CON,
+       PWRAP_DVFS_ADR0,
+       PWRAP_DVFS_WDATA0,
+       PWRAP_DVFS_ADR1,
+       PWRAP_DVFS_WDATA1,
+       PWRAP_DVFS_ADR2,
+       PWRAP_DVFS_WDATA2,
+       PWRAP_DVFS_ADR3,
+       PWRAP_DVFS_WDATA3,
+       PWRAP_DVFS_ADR4,
+       PWRAP_DVFS_WDATA4,
+       PWRAP_DVFS_ADR5,
+       PWRAP_DVFS_WDATA5,
+       PWRAP_DVFS_ADR6,
+       PWRAP_DVFS_WDATA6,
+       PWRAP_DVFS_ADR7,
+       PWRAP_DVFS_WDATA7,
+       PWRAP_SPMINF_STA,
+       PWRAP_CIPHER_EN,
+};
+
+static int mt8173_regs[] = {
+       [PWRAP_MUX_SEL] =               0x0,
+       [PWRAP_WRAP_EN] =               0x4,
+       [PWRAP_DIO_EN] =                0x8,
+       [PWRAP_SIDLY] =                 0xc,
+       [PWRAP_RDDMY] =                 0x10,
+       [PWRAP_SI_CK_CON] =             0x14,
+       [PWRAP_CSHEXT_WRITE] =          0x18,
+       [PWRAP_CSHEXT_READ] =           0x1c,
+       [PWRAP_CSLEXT_START] =          0x20,
+       [PWRAP_CSLEXT_END] =            0x24,
+       [PWRAP_STAUPD_PRD] =            0x28,
+       [PWRAP_STAUPD_GRPEN] =          0x2c,
+       [PWRAP_STAUPD_MAN_TRIG] =       0x40,
+       [PWRAP_STAUPD_STA] =            0x44,
+       [PWRAP_WRAP_STA] =              0x48,
+       [PWRAP_HARB_INIT] =             0x4c,
+       [PWRAP_HARB_HPRIO] =            0x50,
+       [PWRAP_HIPRIO_ARB_EN] =         0x54,
+       [PWRAP_HARB_STA0] =             0x58,
+       [PWRAP_HARB_STA1] =             0x5c,
+       [PWRAP_MAN_EN] =                0x60,
+       [PWRAP_MAN_CMD] =               0x64,
+       [PWRAP_MAN_RDATA] =             0x68,
+       [PWRAP_MAN_VLDCLR] =            0x6c,
+       [PWRAP_WACS0_EN] =              0x70,
+       [PWRAP_INIT_DONE0] =            0x74,
+       [PWRAP_WACS0_CMD] =             0x78,
+       [PWRAP_WACS0_RDATA] =           0x7c,
+       [PWRAP_WACS0_VLDCLR] =          0x80,
+       [PWRAP_WACS1_EN] =              0x84,
+       [PWRAP_INIT_DONE1] =            0x88,
+       [PWRAP_WACS1_CMD] =             0x8c,
+       [PWRAP_WACS1_RDATA] =           0x90,
+       [PWRAP_WACS1_VLDCLR] =          0x94,
+       [PWRAP_WACS2_EN] =              0x98,
+       [PWRAP_INIT_DONE2] =            0x9c,
+       [PWRAP_WACS2_CMD] =             0xa0,
+       [PWRAP_WACS2_RDATA] =           0xa4,
+       [PWRAP_WACS2_VLDCLR] =          0xa8,
+       [PWRAP_INT_EN] =                0xac,
+       [PWRAP_INT_FLG_RAW] =           0xb0,
+       [PWRAP_INT_FLG] =               0xb4,
+       [PWRAP_INT_CLR] =               0xb8,
+       [PWRAP_SIG_ADR] =               0xbc,
+       [PWRAP_SIG_MODE] =              0xc0,
+       [PWRAP_SIG_VALUE] =             0xc4,
+       [PWRAP_SIG_ERRVAL] =            0xc8,
+       [PWRAP_CRC_EN] =                0xcc,
+       [PWRAP_TIMER_EN] =              0xd0,
+       [PWRAP_TIMER_STA] =             0xd4,
+       [PWRAP_WDT_UNIT] =              0xd8,
+       [PWRAP_WDT_SRC_EN] =            0xdc,
+       [PWRAP_WDT_FLG] =               0xe0,
+       [PWRAP_DEBUG_INT_SEL] =         0xe4,
+       [PWRAP_DVFS_ADR0] =             0xe8,
+       [PWRAP_DVFS_WDATA0] =           0xec,
+       [PWRAP_DVFS_ADR1] =             0xf0,
+       [PWRAP_DVFS_WDATA1] =           0xf4,
+       [PWRAP_DVFS_ADR2] =             0xf8,
+       [PWRAP_DVFS_WDATA2] =           0xfc,
+       [PWRAP_DVFS_ADR3] =             0x100,
+       [PWRAP_DVFS_WDATA3] =           0x104,
+       [PWRAP_DVFS_ADR4] =             0x108,
+       [PWRAP_DVFS_WDATA4] =           0x10c,
+       [PWRAP_DVFS_ADR5] =             0x110,
+       [PWRAP_DVFS_WDATA5] =           0x114,
+       [PWRAP_DVFS_ADR6] =             0x118,
+       [PWRAP_DVFS_WDATA6] =           0x11c,
+       [PWRAP_DVFS_ADR7] =             0x120,
+       [PWRAP_DVFS_WDATA7] =           0x124,
+       [PWRAP_SPMINF_STA] =            0x128,
+       [PWRAP_CIPHER_KEY_SEL] =        0x12c,
+       [PWRAP_CIPHER_IV_SEL] =         0x130,
+       [PWRAP_CIPHER_EN] =             0x134,
+       [PWRAP_CIPHER_RDY] =            0x138,
+       [PWRAP_CIPHER_MODE] =           0x13c,
+       [PWRAP_CIPHER_SWRST] =          0x140,
+       [PWRAP_DCM_EN] =                0x144,
+       [PWRAP_DCM_DBC_PRD] =           0x148,
+};
+
+static int mt8135_regs[] = {
+       [PWRAP_MUX_SEL] =               0x0,
+       [PWRAP_WRAP_EN] =               0x4,
+       [PWRAP_DIO_EN] =                0x8,
+       [PWRAP_SIDLY] =                 0xc,
+       [PWRAP_CSHEXT] =                0x10,
+       [PWRAP_CSHEXT_WRITE] =          0x14,
+       [PWRAP_CSHEXT_READ] =           0x18,
+       [PWRAP_CSLEXT_START] =          0x1c,
+       [PWRAP_CSLEXT_END] =            0x20,
+       [PWRAP_STAUPD_PRD] =            0x24,
+       [PWRAP_STAUPD_GRPEN] =          0x28,
+       [PWRAP_STAUPD_MAN_TRIG] =       0x2c,
+       [PWRAP_STAUPD_STA] =            0x30,
+       [PWRAP_EVENT_IN_EN] =           0x34,
+       [PWRAP_EVENT_DST_EN] =          0x38,
+       [PWRAP_WRAP_STA] =              0x3c,
+       [PWRAP_RRARB_INIT] =            0x40,
+       [PWRAP_RRARB_EN] =              0x44,
+       [PWRAP_RRARB_STA0] =            0x48,
+       [PWRAP_RRARB_STA1] =            0x4c,
+       [PWRAP_HARB_INIT] =             0x50,
+       [PWRAP_HARB_HPRIO] =            0x54,
+       [PWRAP_HIPRIO_ARB_EN] =         0x58,
+       [PWRAP_HARB_STA0] =             0x5c,
+       [PWRAP_HARB_STA1] =             0x60,
+       [PWRAP_MAN_EN] =                0x64,
+       [PWRAP_MAN_CMD] =               0x68,
+       [PWRAP_MAN_RDATA] =             0x6c,
+       [PWRAP_MAN_VLDCLR] =            0x70,
+       [PWRAP_WACS0_EN] =              0x74,
+       [PWRAP_INIT_DONE0] =            0x78,
+       [PWRAP_WACS0_CMD] =             0x7c,
+       [PWRAP_WACS0_RDATA] =           0x80,
+       [PWRAP_WACS0_VLDCLR] =          0x84,
+       [PWRAP_WACS1_EN] =              0x88,
+       [PWRAP_INIT_DONE1] =            0x8c,
+       [PWRAP_WACS1_CMD] =             0x90,
+       [PWRAP_WACS1_RDATA] =           0x94,
+       [PWRAP_WACS1_VLDCLR] =          0x98,
+       [PWRAP_WACS2_EN] =              0x9c,
+       [PWRAP_INIT_DONE2] =            0xa0,
+       [PWRAP_WACS2_CMD] =             0xa4,
+       [PWRAP_WACS2_RDATA] =           0xa8,
+       [PWRAP_WACS2_VLDCLR] =          0xac,
+       [PWRAP_INT_EN] =                0xb0,
+       [PWRAP_INT_FLG_RAW] =           0xb4,
+       [PWRAP_INT_FLG] =               0xb8,
+       [PWRAP_INT_CLR] =               0xbc,
+       [PWRAP_SIG_ADR] =               0xc0,
+       [PWRAP_SIG_MODE] =              0xc4,
+       [PWRAP_SIG_VALUE] =             0xc8,
+       [PWRAP_SIG_ERRVAL] =            0xcc,
+       [PWRAP_CRC_EN] =                0xd0,
+       [PWRAP_EVENT_STA] =             0xd4,
+       [PWRAP_EVENT_STACLR] =          0xd8,
+       [PWRAP_TIMER_EN] =              0xdc,
+       [PWRAP_TIMER_STA] =             0xe0,
+       [PWRAP_WDT_UNIT] =              0xe4,
+       [PWRAP_WDT_SRC_EN] =            0xe8,
+       [PWRAP_WDT_FLG] =               0xec,
+       [PWRAP_DEBUG_INT_SEL] =         0xf0,
+       [PWRAP_CIPHER_KEY_SEL] =        0x134,
+       [PWRAP_CIPHER_IV_SEL] =         0x138,
+       [PWRAP_CIPHER_LOAD] =           0x13c,
+       [PWRAP_CIPHER_START] =          0x140,
+       [PWRAP_CIPHER_RDY] =            0x144,
+       [PWRAP_CIPHER_MODE] =           0x148,
+       [PWRAP_CIPHER_SWRST] =          0x14c,
+       [PWRAP_DCM_EN] =                0x15c,
+       [PWRAP_DCM_DBC_PRD] =           0x160,
+};
+
+enum pwrap_type {
+       PWRAP_MT8135,
+       PWRAP_MT8173,
+};
+
+struct pmic_wrapper_type {
+       int *regs;
+       enum pwrap_type type;
+       u32 arb_en_all;
+};
+
+static struct pmic_wrapper_type pwrap_mt8135 = {
+       .regs = mt8135_regs,
+       .type = PWRAP_MT8135,
+       .arb_en_all = 0x1ff,
+};
+
+static struct pmic_wrapper_type pwrap_mt8173 = {
+       .regs = mt8173_regs,
+       .type = PWRAP_MT8173,
+       .arb_en_all = 0x3f,
+};
+
+struct pmic_wrapper {
+       struct device *dev;
+       void __iomem *base;
+       struct regmap *regmap;
+       int *regs;
+       enum pwrap_type type;
+       u32 arb_en_all;
+       struct clk *clk_spi;
+       struct clk *clk_wrap;
+       struct reset_control *rstc;
+
+       struct reset_control *rstc_bridge;
+       void __iomem *bridge_base;
+};
+
+static inline int pwrap_is_mt8135(struct pmic_wrapper *wrp)
+{
+       return wrp->type == PWRAP_MT8135;
+}
+
+static inline int pwrap_is_mt8173(struct pmic_wrapper *wrp)
+{
+       return wrp->type == PWRAP_MT8173;
+}
+
+static u32 pwrap_readl(struct pmic_wrapper *wrp, enum pwrap_regs reg)
+{
+       return readl(wrp->base + wrp->regs[reg]);
+}
+
+static void pwrap_writel(struct pmic_wrapper *wrp, u32 val, enum pwrap_regs reg)
+{
+       writel(val, wrp->base + wrp->regs[reg]);
+}
+
+static bool pwrap_is_fsm_idle(struct pmic_wrapper *wrp)
+{
+       u32 val = pwrap_readl(wrp, PWRAP_WACS2_RDATA);
+
+       return PWRAP_GET_WACS_FSM(val) == PWRAP_WACS_FSM_IDLE;
+}
+
+static bool pwrap_is_fsm_vldclr(struct pmic_wrapper *wrp)
+{
+       u32 val = pwrap_readl(wrp, PWRAP_WACS2_RDATA);
+
+       return PWRAP_GET_WACS_FSM(val) == PWRAP_WACS_FSM_WFVLDCLR;
+}
+
+static bool pwrap_is_sync_idle(struct pmic_wrapper *wrp)
+{
+       return pwrap_readl(wrp, PWRAP_WACS2_RDATA) & PWRAP_STATE_SYNC_IDLE0;
+}
+
+static bool pwrap_is_fsm_idle_and_sync_idle(struct pmic_wrapper *wrp)
+{
+       u32 val = pwrap_readl(wrp, PWRAP_WACS2_RDATA);
+
+       return (PWRAP_GET_WACS_FSM(val) == PWRAP_WACS_FSM_IDLE) &&
+               (val & PWRAP_STATE_SYNC_IDLE0);
+}
+
+static int pwrap_wait_for_state(struct pmic_wrapper *wrp,
+               bool (*fp)(struct pmic_wrapper *))
+{
+       unsigned long timeout;
+
+       timeout = jiffies + usecs_to_jiffies(255);
+
+       do {
+               if (time_after(jiffies, timeout))
+                       return fp(wrp) ? 0 : -ETIMEDOUT;
+               if (fp(wrp))
+                       return 0;
+       } while (1);
+}
+
+static int pwrap_write(struct pmic_wrapper *wrp, u32 adr, u32 wdata)
+{
+       int ret;
+       u32 val;
+
+       val = pwrap_readl(wrp, PWRAP_WACS2_RDATA);
+       if (PWRAP_GET_WACS_FSM(val) == PWRAP_WACS_FSM_WFVLDCLR)
+               pwrap_writel(wrp, 1, PWRAP_WACS2_VLDCLR);
+
+       ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle);
+       if (ret)
+               return ret;
+
+       pwrap_writel(wrp, (1 << 31) | ((adr >> 1) << 16) | wdata,
+                       PWRAP_WACS2_CMD);
+
+       return 0;
+}
+
+static int pwrap_read(struct pmic_wrapper *wrp, u32 adr, u32 *rdata)
+{
+       int ret;
+       u32 val;
+
+       val = pwrap_readl(wrp, PWRAP_WACS2_RDATA);
+       if (PWRAP_GET_WACS_FSM(val) == PWRAP_WACS_FSM_WFVLDCLR)
+               pwrap_writel(wrp, 1, PWRAP_WACS2_VLDCLR);
+
+       ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle);
+       if (ret)
+               return ret;
+
+       pwrap_writel(wrp, (adr >> 1) << 16, PWRAP_WACS2_CMD);
+
+       ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_vldclr);
+       if (ret)
+               return ret;
+
+       *rdata = PWRAP_GET_WACS_RDATA(pwrap_readl(wrp, PWRAP_WACS2_RDATA));
+
+       return 0;
+}
+
+static int pwrap_regmap_read(void *context, u32 adr, u32 *rdata)
+{
+       return pwrap_read(context, adr, rdata);
+}
+
+static int pwrap_regmap_write(void *context, u32 adr, u32 wdata)
+{
+       return pwrap_write(context, adr, wdata);
+}
+
+static int pwrap_reset_spislave(struct pmic_wrapper *wrp)
+{
+       int ret, i;
+
+       pwrap_writel(wrp, 0, PWRAP_HIPRIO_ARB_EN);
+       pwrap_writel(wrp, 0, PWRAP_WRAP_EN);
+       pwrap_writel(wrp, 1, PWRAP_MUX_SEL);
+       pwrap_writel(wrp, 1, PWRAP_MAN_EN);
+       pwrap_writel(wrp, 0, PWRAP_DIO_EN);
+
+       pwrap_writel(wrp, PWRAP_MAN_CMD_SPI_WRITE | PWRAP_MAN_CMD_OP_CSL,
+                       PWRAP_MAN_CMD);
+       pwrap_writel(wrp, PWRAP_MAN_CMD_SPI_WRITE | PWRAP_MAN_CMD_OP_OUTS,
+                       PWRAP_MAN_CMD);
+       pwrap_writel(wrp, PWRAP_MAN_CMD_SPI_WRITE | PWRAP_MAN_CMD_OP_CSH,
+                       PWRAP_MAN_CMD);
+
+       for (i = 0; i < 4; i++)
+               pwrap_writel(wrp, PWRAP_MAN_CMD_SPI_WRITE | PWRAP_MAN_CMD_OP_OUTS,
+                               PWRAP_MAN_CMD);
+
+       ret = pwrap_wait_for_state(wrp, pwrap_is_sync_idle);
+       if (ret) {
+               dev_err(wrp->dev, "%s fail, ret=%d\n", __func__, ret);
+               return ret;
+       }
+
+       pwrap_writel(wrp, 0, PWRAP_MAN_EN);
+       pwrap_writel(wrp, 0, PWRAP_MUX_SEL);
+
+       return 0;
+}
+
+/*
+ * pwrap_init_sidly - configure serial input delay
+ *
+ * This configures the serial input delay. We can configure 0, 2, 4 or 6ns
+ * delay. Do a read test with all possible values and chose the best delay.
+ */
+static int pwrap_init_sidly(struct pmic_wrapper *wrp)
+{
+       u32 rdata;
+       u32 i;
+       u32 pass = 0;
+       signed char dly[16] = {
+               -1, 0, 1, 0, 2, -1, 1, 1, 3, -1, -1, -1, 3, -1, 2, 1
+       };
+
+       for (i = 0; i < 4; i++) {
+               pwrap_writel(wrp, i, PWRAP_SIDLY);
+               pwrap_read(wrp, PWRAP_DEW_READ_TEST, &rdata);
+               if (rdata == PWRAP_DEW_READ_TEST_VAL) {
+                       dev_dbg(wrp->dev, "[Read Test] pass, SIDLY=%x\n", i);
+                       pass |= 1 << i;
+               }
+       }
+
+       if (dly[pass] < 0) {
+               dev_err(wrp->dev, "sidly pass range 0x%x not continuous\n",
+                               pass);
+               return -EIO;
+       }
+
+       pwrap_writel(wrp, dly[pass], PWRAP_SIDLY);
+
+       return 0;
+}
+
+static int pwrap_init_reg_clock(struct pmic_wrapper *wrp)
+{
+       unsigned long rate_spi;
+       int ck_mhz;
+
+       rate_spi = clk_get_rate(wrp->clk_spi);
+
+       if (rate_spi > 26000000)
+               ck_mhz = 26;
+       else if (rate_spi > 18000000)
+               ck_mhz = 18;
+       else
+               ck_mhz = 0;
+
+       switch (ck_mhz) {
+       case 18:
+               if (pwrap_is_mt8135(wrp))
+                       pwrap_writel(wrp, 0xc, PWRAP_CSHEXT);
+               pwrap_writel(wrp, 0x4, PWRAP_CSHEXT_WRITE);
+               pwrap_writel(wrp, 0xc, PWRAP_CSHEXT_READ);
+               pwrap_writel(wrp, 0x0, PWRAP_CSLEXT_START);
+               pwrap_writel(wrp, 0x0, PWRAP_CSLEXT_END);
+               break;
+       case 26:
+               if (pwrap_is_mt8135(wrp))
+                       pwrap_writel(wrp, 0x4, PWRAP_CSHEXT);
+               pwrap_writel(wrp, 0x0, PWRAP_CSHEXT_WRITE);
+               pwrap_writel(wrp, 0x4, PWRAP_CSHEXT_READ);
+               pwrap_writel(wrp, 0x0, PWRAP_CSLEXT_START);
+               pwrap_writel(wrp, 0x0, PWRAP_CSLEXT_END);
+               break;
+       case 0:
+               if (pwrap_is_mt8135(wrp))
+                       pwrap_writel(wrp, 0xf, PWRAP_CSHEXT);
+               pwrap_writel(wrp, 0xf, PWRAP_CSHEXT_WRITE);
+               pwrap_writel(wrp, 0xf, PWRAP_CSHEXT_READ);
+               pwrap_writel(wrp, 0xf, PWRAP_CSLEXT_START);
+               pwrap_writel(wrp, 0xf, PWRAP_CSLEXT_END);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static bool pwrap_is_cipher_ready(struct pmic_wrapper *wrp)
+{
+       return pwrap_readl(wrp, PWRAP_CIPHER_RDY) & 1;
+}
+
+static bool pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp)
+{
+       u32 rdata;
+       int ret;
+
+       ret = pwrap_read(wrp, PWRAP_DEW_CIPHER_RDY, &rdata);
+       if (ret)
+               return 0;
+
+       return rdata == 1;
+}
+
+static int pwrap_init_cipher(struct pmic_wrapper *wrp)
+{
+       int ret;
+       u32 rdata;
+
+       pwrap_writel(wrp, 0x1, PWRAP_CIPHER_SWRST);
+       pwrap_writel(wrp, 0x0, PWRAP_CIPHER_SWRST);
+       pwrap_writel(wrp, 0x1, PWRAP_CIPHER_KEY_SEL);
+       pwrap_writel(wrp, 0x2, PWRAP_CIPHER_IV_SEL);
+
+       if (pwrap_is_mt8135(wrp)) {
+               pwrap_writel(wrp, 1, PWRAP_CIPHER_LOAD);
+               pwrap_writel(wrp, 1, PWRAP_CIPHER_START);
+       } else {
+               pwrap_writel(wrp, 1, PWRAP_CIPHER_EN);
+       }
+
+       /* Config cipher mode @PMIC */
+       pwrap_write(wrp, PWRAP_DEW_CIPHER_SWRST, 0x1);
+       pwrap_write(wrp, PWRAP_DEW_CIPHER_SWRST, 0x0);
+       pwrap_write(wrp, PWRAP_DEW_CIPHER_KEY_SEL, 0x1);
+       pwrap_write(wrp, PWRAP_DEW_CIPHER_IV_SEL, 0x2);
+       pwrap_write(wrp, PWRAP_DEW_CIPHER_LOAD, 0x1);
+       pwrap_write(wrp, PWRAP_DEW_CIPHER_START, 0x1);
+
+       /* wait for cipher data ready@AP */
+       ret = pwrap_wait_for_state(wrp, pwrap_is_cipher_ready);
+       if (ret) {
+               dev_err(wrp->dev, "cipher data ready@AP fail, ret=%d\n", ret);
+               return ret;
+       }
+
+       /* wait for cipher data ready@PMIC */
+       ret = pwrap_wait_for_state(wrp, pwrap_is_pmic_cipher_ready);
+       if (ret) {
+               dev_err(wrp->dev, "timeout waiting for cipher data ready@PMIC\n");
+               return ret;
+       }
+
+       /* wait for cipher mode idle */
+       pwrap_write(wrp, PWRAP_DEW_CIPHER_MODE, 0x1);
+       ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle_and_sync_idle);
+       if (ret) {
+               dev_err(wrp->dev, "cipher mode idle fail, ret=%d\n", ret);
+               return ret;
+       }
+
+       pwrap_writel(wrp, 1, PWRAP_CIPHER_MODE);
+
+       /* Write Test */
+       if (pwrap_write(wrp, PWRAP_DEW_WRITE_TEST, PWRAP_DEW_WRITE_TEST_VAL) ||
+           pwrap_read(wrp, PWRAP_DEW_WRITE_TEST, &rdata) ||
+                       (rdata != PWRAP_DEW_WRITE_TEST_VAL)) {
+               dev_err(wrp->dev, "rdata=0x%04X\n", rdata);
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+static int pwrap_init(struct pmic_wrapper *wrp)
+{
+       int ret;
+       u32 rdata;
+
+       reset_control_reset(wrp->rstc);
+       if (wrp->rstc_bridge)
+               reset_control_reset(wrp->rstc_bridge);
+
+       if (pwrap_is_mt8173(wrp)) {
+               /* Enable DCM */
+               pwrap_writel(wrp, 3, PWRAP_DCM_EN);
+               pwrap_writel(wrp, 0, PWRAP_DCM_DBC_PRD);
+       }
+
+       /* Reset SPI slave */
+       ret = pwrap_reset_spislave(wrp);
+       if (ret)
+               return ret;
+
+       pwrap_writel(wrp, 1, PWRAP_WRAP_EN);
+
+       pwrap_writel(wrp, wrp->arb_en_all, PWRAP_HIPRIO_ARB_EN);
+
+       pwrap_writel(wrp, 1, PWRAP_WACS2_EN);
+
+       ret = pwrap_init_reg_clock(wrp);
+       if (ret)
+               return ret;
+
+       /* Setup serial input delay */
+       ret = pwrap_init_sidly(wrp);
+       if (ret)
+               return ret;
+
+       /* Enable dual IO mode */
+       pwrap_write(wrp, PWRAP_DEW_DIO_EN, 1);
+
+       /* Check IDLE & INIT_DONE in advance */
+       ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle_and_sync_idle);
+       if (ret) {
+               dev_err(wrp->dev, "%s fail, ret=%d\n", __func__, ret);
+               return ret;
+       }
+
+       pwrap_writel(wrp, 1, PWRAP_DIO_EN);
+
+       /* Read Test */
+       pwrap_read(wrp, PWRAP_DEW_READ_TEST, &rdata);
+       if (rdata != PWRAP_DEW_READ_TEST_VAL) {
+               dev_err(wrp->dev, "Read test failed after switch to DIO mode: 0x%04x != 0x%04x\n",
+                               PWRAP_DEW_READ_TEST_VAL, rdata);
+               return -EFAULT;
+       }
+
+       /* Enable encryption */
+       ret = pwrap_init_cipher(wrp);
+       if (ret)
+               return ret;
+
+       /* Signature checking - using CRC */
+       if (pwrap_write(wrp, PWRAP_DEW_CRC_EN, 0x1))
+               return -EFAULT;
+
+       pwrap_writel(wrp, 0x1, PWRAP_CRC_EN);
+       pwrap_writel(wrp, 0x0, PWRAP_SIG_MODE);
+       pwrap_writel(wrp, PWRAP_DEW_CRC_VAL, PWRAP_SIG_ADR);
+       pwrap_writel(wrp, wrp->arb_en_all, PWRAP_HIPRIO_ARB_EN);
+
+       if (pwrap_is_mt8135(wrp))
+               pwrap_writel(wrp, 0x7, PWRAP_RRARB_EN);
+
+       pwrap_writel(wrp, 0x1, PWRAP_WACS0_EN);
+       pwrap_writel(wrp, 0x1, PWRAP_WACS1_EN);
+       pwrap_writel(wrp, 0x1, PWRAP_WACS2_EN);
+       pwrap_writel(wrp, 0x5, PWRAP_STAUPD_PRD);
+       pwrap_writel(wrp, 0xff, PWRAP_STAUPD_GRPEN);
+       pwrap_writel(wrp, 0xf, PWRAP_WDT_UNIT);
+       pwrap_writel(wrp, 0xffffffff, PWRAP_WDT_SRC_EN);
+       pwrap_writel(wrp, 0x1, PWRAP_TIMER_EN);
+       pwrap_writel(wrp, ~((1 << 31) | (1 << 1)), PWRAP_INT_EN);
+
+       if (pwrap_is_mt8135(wrp)) {
+               /* enable pwrap events and pwrap bridge in AP side */
+               pwrap_writel(wrp, 0x1, PWRAP_EVENT_IN_EN);
+               pwrap_writel(wrp, 0xffff, PWRAP_EVENT_DST_EN);
+               writel(0x7f, wrp->bridge_base + PWRAP_MT8135_BRIDGE_IORD_ARB_EN);
+               writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WACS3_EN);
+               writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WACS4_EN);
+               writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WDT_UNIT);
+               writel(0xffff, wrp->bridge_base + PWRAP_MT8135_BRIDGE_WDT_SRC_EN);
+               writel(0x1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_TIMER_EN);
+               writel(0x7ff, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INT_EN);
+
+               /* enable PMIC event out and sources */
+               if (pwrap_write(wrp, PWRAP_DEW_EVENT_OUT_EN, 0x1) ||
+                               pwrap_write(wrp, PWRAP_DEW_EVENT_SRC_EN, 0xffff)) {
+                       dev_err(wrp->dev, "enable dewrap fail\n");
+                       return -EFAULT;
+               }
+       } else {
+               /* PMIC_DEWRAP enables */
+               if (pwrap_write(wrp, PWRAP_DEW_EVENT_OUT_EN, 0x1) ||
+                               pwrap_write(wrp, PWRAP_DEW_EVENT_SRC_EN, 0xffff)) {
+                       dev_err(wrp->dev, "enable dewrap fail\n");
+                       return -EFAULT;
+               }
+       }
+
+       /* Setup the init done registers */
+       pwrap_writel(wrp, 1, PWRAP_INIT_DONE2);
+       pwrap_writel(wrp, 1, PWRAP_INIT_DONE0);
+       pwrap_writel(wrp, 1, PWRAP_INIT_DONE1);
+
+       if (pwrap_is_mt8135(wrp)) {
+               writel(1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INIT_DONE3);
+               writel(1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INIT_DONE4);
+       }
+
+       return 0;
+}
+
+static irqreturn_t pwrap_interrupt(int irqno, void *dev_id)
+{
+       u32 rdata;
+       struct pmic_wrapper *wrp = dev_id;
+
+       rdata = pwrap_readl(wrp, PWRAP_INT_FLG);
+
+       dev_err(wrp->dev, "unexpected interrupt int=0x%x\n", rdata);
+
+       pwrap_writel(wrp, 0xffffffff, PWRAP_INT_CLR);
+
+       return IRQ_HANDLED;
+}
+
+static const struct regmap_config pwrap_regmap_config = {
+       .reg_bits = 16,
+       .val_bits = 16,
+       .reg_stride = 2,
+       .reg_read = pwrap_regmap_read,
+       .reg_write = pwrap_regmap_write,
+       .max_register = 0xffff,
+};
+
+static struct of_device_id of_pwrap_match_tbl[] = {
+       {
+               .compatible = "mediatek,mt8135-pwrap",
+               .data = &pwrap_mt8135,
+       }, {
+               .compatible = "mediatek,mt8173-pwrap",
+               .data = &pwrap_mt8173,
+       }, {
+               /* sentinel */
+       }
+};
+MODULE_DEVICE_TABLE(of, of_pwrap_match_tbl);
+
+static int pwrap_probe(struct platform_device *pdev)
+{
+       int ret, irq;
+       struct pmic_wrapper *wrp;
+       struct device_node *np = pdev->dev.of_node;
+       const struct of_device_id *of_id =
+               of_match_device(of_pwrap_match_tbl, &pdev->dev);
+       const struct pmic_wrapper_type *type;
+       struct resource *res;
+
+       wrp = devm_kzalloc(&pdev->dev, sizeof(*wrp), GFP_KERNEL);
+       if (!wrp)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, wrp);
+
+       type = of_id->data;
+       wrp->regs = type->regs;
+       wrp->type = type->type;
+       wrp->arb_en_all = type->arb_en_all;
+       wrp->dev = &pdev->dev;
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pwrap");
+       wrp->base = devm_ioremap_resource(wrp->dev, res);
+       if (IS_ERR(wrp->base))
+               return PTR_ERR(wrp->base);
+
+       wrp->rstc = devm_reset_control_get(wrp->dev, "pwrap");
+       if (IS_ERR(wrp->rstc)) {
+               ret = PTR_ERR(wrp->rstc);
+               dev_dbg(wrp->dev, "cannot get pwrap reset: %d\n", ret);
+               return ret;
+       }
+
+       if (pwrap_is_mt8135(wrp)) {
+               res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+                               "pwrap-bridge");
+               wrp->bridge_base = devm_ioremap_resource(wrp->dev, res);
+               if (IS_ERR(wrp->bridge_base))
+                       return PTR_ERR(wrp->bridge_base);
+
+               wrp->rstc_bridge = devm_reset_control_get(wrp->dev, "pwrap-bridge");
+               if (IS_ERR(wrp->rstc_bridge)) {
+                       ret = PTR_ERR(wrp->rstc_bridge);
+                       dev_dbg(wrp->dev, "cannot get pwrap-bridge reset: %d\n", ret);
+                       return ret;
+               }
+       }
+
+       wrp->clk_spi = devm_clk_get(wrp->dev, "spi");
+       if (IS_ERR(wrp->clk_spi)) {
+               dev_dbg(wrp->dev, "failed to get clock: %ld\n", PTR_ERR(wrp->clk_spi));
+               return PTR_ERR(wrp->clk_spi);
+       }
+
+       wrp->clk_wrap = devm_clk_get(wrp->dev, "wrap");
+       if (IS_ERR(wrp->clk_wrap)) {
+               dev_dbg(wrp->dev, "failed to get clock: %ld\n", PTR_ERR(wrp->clk_wrap));
+               return PTR_ERR(wrp->clk_wrap);
+       }
+
+       ret = clk_prepare_enable(wrp->clk_spi);
+       if (ret)
+               return ret;
+
+       ret = clk_prepare_enable(wrp->clk_wrap);
+       if (ret)
+               goto err_out1;
+
+       /* Enable internal dynamic clock */
+       pwrap_writel(wrp, 1, PWRAP_DCM_EN);
+       pwrap_writel(wrp, 0, PWRAP_DCM_DBC_PRD);
+
+       /*
+        * The PMIC could already be initialized by the bootloader.
+        * Skip initialization here in this case.
+        */
+       if (!pwrap_readl(wrp, PWRAP_INIT_DONE2)) {
+               ret = pwrap_init(wrp);
+               if (ret) {
+                       dev_dbg(wrp->dev, "init failed with %d\n", ret);
+                       goto err_out2;
+               }
+       }
+
+       if (!(pwrap_readl(wrp, PWRAP_WACS2_RDATA) & PWRAP_STATE_INIT_DONE0)) {
+               dev_dbg(wrp->dev, "initialization isn't finished\n");
+               return -ENODEV;
+       }
+
+       irq = platform_get_irq(pdev, 0);
+       ret = devm_request_irq(wrp->dev, irq, pwrap_interrupt, IRQF_TRIGGER_HIGH,
+                       "mt-pmic-pwrap", wrp);
+       if (ret)
+               goto err_out2;
+
+       wrp->regmap = devm_regmap_init(wrp->dev, NULL, wrp, &pwrap_regmap_config);
+       if (IS_ERR(wrp->regmap))
+               return PTR_ERR(wrp->regmap);
+
+       ret = of_platform_populate(np, NULL, NULL, wrp->dev);
+       if (ret) {
+               dev_dbg(wrp->dev, "failed to create child devices at %s\n",
+                               np->full_name);
+               goto err_out2;
+       }
+
+       return 0;
+
+err_out2:
+       clk_disable_unprepare(wrp->clk_wrap);
+err_out1:
+       clk_disable_unprepare(wrp->clk_spi);
+
+       return ret;
+}
+
+static struct platform_driver pwrap_drv = {
+       .driver = {
+               .name = "mt-pmic-pwrap",
+               .owner = THIS_MODULE,
+               .of_match_table = of_match_ptr(of_pwrap_match_tbl),
+       },
+       .probe = pwrap_probe,
+};
+
+module_platform_driver(pwrap_drv);
+
+MODULE_AUTHOR("Flora Fu, MediaTek");
+MODULE_DESCRIPTION("MediaTek MT8135 PMIC Wrapper Driver");
+MODULE_LICENSE("GPL v2");
index 7bd2c94f54a4e923f473db63e512b99bffa3a9ba..460b2dba109c8dac48eb3acdb493dc2b535d62c7 100644 (file)
@@ -4,6 +4,7 @@
 config QCOM_GSBI
         tristate "QCOM General Serial Bus Interface"
         depends on ARCH_QCOM
+        select MFD_SYSCON
         help
           Say y here to enable GSBI support.  The GSBI provides control
           functions for connecting the underlying serial UART, SPI, and I2C
index 729425ddfd3e371d04978cdda0871209e2f24885..09c669e70d636861df12f9670dcdf339cf4021ee 100644 (file)
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <dt-bindings/soc/qcom,gsbi.h>
 
 #define GSBI_CTRL_REG          0x0000
 #define GSBI_PROTOCOL_SHIFT    4
+#define MAX_GSBI               12
+
+#define TCSR_ADM_CRCI_BASE     0x70
+
+struct crci_config {
+       u32 num_rows;
+       const u32 (*array)[MAX_GSBI];
+};
+
+static const u32 crci_ipq8064[][MAX_GSBI] = {
+       {
+               0x000003, 0x00000c, 0x000030, 0x0000c0,
+               0x000300, 0x000c00, 0x003000, 0x00c000,
+               0x030000, 0x0c0000, 0x300000, 0xc00000
+       },
+       {
+               0x000003, 0x00000c, 0x000030, 0x0000c0,
+               0x000300, 0x000c00, 0x003000, 0x00c000,
+               0x030000, 0x0c0000, 0x300000, 0xc00000
+       },
+};
+
+static const struct crci_config config_ipq8064 = {
+       .num_rows = ARRAY_SIZE(crci_ipq8064),
+       .array = crci_ipq8064,
+};
+
+static const unsigned int crci_apq8064[][MAX_GSBI] = {
+       {
+               0x001800, 0x006000, 0x000030, 0x0000c0,
+               0x000300, 0x000400, 0x000000, 0x000000,
+               0x000000, 0x000000, 0x000000, 0x000000
+       },
+       {
+               0x000000, 0x000000, 0x000000, 0x000000,
+               0x000000, 0x000020, 0x0000c0, 0x000000,
+               0x000000, 0x000000, 0x000000, 0x000000
+       },
+};
+
+static const struct crci_config config_apq8064 = {
+       .num_rows = ARRAY_SIZE(crci_apq8064),
+       .array = crci_apq8064,
+};
+
+static const unsigned int crci_msm8960[][MAX_GSBI] = {
+       {
+               0x000003, 0x00000c, 0x000030, 0x0000c0,
+               0x000300, 0x000400, 0x000000, 0x000000,
+               0x000000, 0x000000, 0x000000, 0x000000
+       },
+       {
+               0x000000, 0x000000, 0x000000, 0x000000,
+               0x000000, 0x000020, 0x0000c0, 0x000300,
+               0x001800, 0x006000, 0x000000, 0x000000
+       },
+};
+
+static const struct crci_config config_msm8960 = {
+       .num_rows = ARRAY_SIZE(crci_msm8960),
+       .array = crci_msm8960,
+};
+
+static const unsigned int crci_msm8660[][MAX_GSBI] = {
+       {       /* ADM 0 - B */
+               0x000003, 0x00000c, 0x000030, 0x0000c0,
+               0x000300, 0x000c00, 0x003000, 0x00c000,
+               0x030000, 0x0c0000, 0x300000, 0xc00000
+       },
+       {       /* ADM 0 - B */
+               0x000003, 0x00000c, 0x000030, 0x0000c0,
+               0x000300, 0x000c00, 0x003000, 0x00c000,
+               0x030000, 0x0c0000, 0x300000, 0xc00000
+       },
+       {       /* ADM 1 - A */
+               0x000003, 0x00000c, 0x000030, 0x0000c0,
+               0x000300, 0x000c00, 0x003000, 0x00c000,
+               0x030000, 0x0c0000, 0x300000, 0xc00000
+       },
+       {       /* ADM 1 - B */
+               0x000003, 0x00000c, 0x000030, 0x0000c0,
+               0x000300, 0x000c00, 0x003000, 0x00c000,
+               0x030000, 0x0c0000, 0x300000, 0xc00000
+       },
+};
+
+static const struct crci_config config_msm8660 = {
+       .num_rows = ARRAY_SIZE(crci_msm8660),
+       .array = crci_msm8660,
+};
 
 struct gsbi_info {
        struct clk *hclk;
        u32 mode;
        u32 crci;
+       struct regmap *tcsr;
+};
+
+static const struct of_device_id tcsr_dt_match[] = {
+       { .compatible = "qcom,tcsr-ipq8064", .data = &config_ipq8064},
+       { .compatible = "qcom,tcsr-apq8064", .data = &config_apq8064},
+       { .compatible = "qcom,tcsr-msm8960", .data = &config_msm8960},
+       { .compatible = "qcom,tcsr-msm8660", .data = &config_msm8660},
+       { },
 };
 
 static int gsbi_probe(struct platform_device *pdev)
 {
        struct device_node *node = pdev->dev.of_node;
+       struct device_node *tcsr_node;
+       const struct of_device_id *match;
        struct resource *res;
        void __iomem *base;
        struct gsbi_info *gsbi;
+       int i;
+       u32 mask, gsbi_num;
+       const struct crci_config *config = NULL;
 
        gsbi = devm_kzalloc(&pdev->dev, sizeof(*gsbi), GFP_KERNEL);
 
@@ -45,6 +152,32 @@ static int gsbi_probe(struct platform_device *pdev)
        if (IS_ERR(base))
                return PTR_ERR(base);
 
+       /* get the tcsr node and setup the config and regmap */
+       gsbi->tcsr = syscon_regmap_lookup_by_phandle(node, "syscon-tcsr");
+
+       if (!IS_ERR(gsbi->tcsr)) {
+               tcsr_node = of_parse_phandle(node, "syscon-tcsr", 0);
+               if (tcsr_node) {
+                       match = of_match_node(tcsr_dt_match, tcsr_node);
+                       if (match)
+                               config = match->data;
+                       else
+                               dev_warn(&pdev->dev, "no matching TCSR\n");
+
+                       of_node_put(tcsr_node);
+               }
+       }
+
+       if (of_property_read_u32(node, "cell-index", &gsbi_num)) {
+               dev_err(&pdev->dev, "missing cell-index\n");
+               return -EINVAL;
+       }
+
+       if (gsbi_num < 1 || gsbi_num > MAX_GSBI) {
+               dev_err(&pdev->dev, "invalid cell-index\n");
+               return -EINVAL;
+       }
+
        if (of_property_read_u32(node, "qcom,mode", &gsbi->mode)) {
                dev_err(&pdev->dev, "missing mode configuration\n");
                return -EINVAL;
@@ -64,6 +197,25 @@ static int gsbi_probe(struct platform_device *pdev)
        writel_relaxed((gsbi->mode << GSBI_PROTOCOL_SHIFT) | gsbi->crci,
                                base + GSBI_CTRL_REG);
 
+       /*
+        * modify tcsr to reflect mode and ADM CRCI mux
+        * Each gsbi contains a pair of bits, one for RX and one for TX
+        * SPI mode requires both bits cleared, otherwise they are set
+        */
+       if (config) {
+               for (i = 0; i < config->num_rows; i++) {
+                       mask = config->array[i][gsbi_num - 1];
+
+                       if (gsbi->mode == GSBI_PROT_SPI)
+                               regmap_update_bits(gsbi->tcsr,
+                                       TCSR_ADM_CRCI_BASE + 4 * i, mask, 0);
+                       else
+                               regmap_update_bits(gsbi->tcsr,
+                                       TCSR_ADM_CRCI_BASE + 4 * i, mask, mask);
+
+               }
+       }
+
        /* make sure the gsbi control write is not reordered */
        wmb();
 
index 186924aa4740e758af2075f417745487825b6163..f6bac9e77d067390f29584595b2a219b69e749e4 100644 (file)
@@ -1023,7 +1023,6 @@ static struct dma_chan *rspi_request_dma_chan(struct device *dev,
        }
 
        memset(&cfg, 0, sizeof(cfg));
-       cfg.slave_id = id;
        cfg.direction = dir;
        if (dir == DMA_MEM_TO_DEV) {
                cfg.dst_addr = port_addr;
index e57eec0b2f46a64f99ad104251baa505396b0555..bcc7c635d8e7dfe628d4ad5a4cf5fce80c6e4f09 100644 (file)
@@ -1030,7 +1030,6 @@ static struct dma_chan *sh_msiof_request_dma_chan(struct device *dev,
        }
 
        memset(&cfg, 0, sizeof(cfg));
-       cfg.slave_id = id;
        cfg.direction = dir;
        if (dir == DMA_MEM_TO_DEV) {
                cfg.dst_addr = port_addr;
index bf1295e19f892526f03c9fa3fbc28b8a7a8b20bd..c8d99563d2454fe686aaa69b3b7854e34adbb4ce 100644 (file)
@@ -12,7 +12,6 @@ if SPMI
 
 config SPMI_MSM_PMIC_ARB
        tristate "Qualcomm MSM SPMI Controller (PMIC Arbiter)"
-       depends on ARM
        depends on IRQ_DOMAIN
        depends on ARCH_QCOM || COMPILE_TEST
        default ARCH_QCOM
index 20559ab3466da6f87e96283cb917b06f75b3bb29..d7119db49cfe561b5cd534ccf5c0c1bf45ac0ce0 100644 (file)
@@ -1,4 +1,5 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/*
+ * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
 
 /* PMIC Arbiter configuration registers */
 #define PMIC_ARB_VERSION               0x0000
+#define PMIC_ARB_VERSION_V2_MIN                0x20010000
 #define PMIC_ARB_INT_EN                        0x0004
 
-/* PMIC Arbiter channel registers */
-#define PMIC_ARB_CMD(N)                        (0x0800 + (0x80 * (N)))
-#define PMIC_ARB_CONFIG(N)             (0x0804 + (0x80 * (N)))
-#define PMIC_ARB_STATUS(N)             (0x0808 + (0x80 * (N)))
-#define PMIC_ARB_WDATA0(N)             (0x0810 + (0x80 * (N)))
-#define PMIC_ARB_WDATA1(N)             (0x0814 + (0x80 * (N)))
-#define PMIC_ARB_RDATA0(N)             (0x0818 + (0x80 * (N)))
-#define PMIC_ARB_RDATA1(N)             (0x081C + (0x80 * (N)))
-
-/* Interrupt Controller */
-#define SPMI_PIC_OWNER_ACC_STATUS(M, N)        (0x0000 + ((32 * (M)) + (4 * (N))))
-#define SPMI_PIC_ACC_ENABLE(N)         (0x0200 + (4 * (N)))
-#define SPMI_PIC_IRQ_STATUS(N)         (0x0600 + (4 * (N)))
-#define SPMI_PIC_IRQ_CLEAR(N)          (0x0A00 + (4 * (N)))
+/* PMIC Arbiter channel registers offsets */
+#define PMIC_ARB_CMD                   0x00
+#define PMIC_ARB_CONFIG                        0x04
+#define PMIC_ARB_STATUS                        0x08
+#define PMIC_ARB_WDATA0                        0x10
+#define PMIC_ARB_WDATA1                        0x14
+#define PMIC_ARB_RDATA0                        0x18
+#define PMIC_ARB_RDATA1                        0x1C
+#define PMIC_ARB_REG_CHNL(N)           (0x800 + 0x4 * (N))
 
 /* Mapping Table */
 #define SPMI_MAPPING_TABLE_REG(N)      (0x0B00 + (4 * (N)))
@@ -52,6 +49,7 @@
 
 #define SPMI_MAPPING_TABLE_LEN         255
 #define SPMI_MAPPING_TABLE_TREE_DEPTH  16      /* Maximum of 16-bits */
+#define PPID_TO_CHAN_TABLE_SZ          BIT(12) /* PPID is 12bit chan is 1byte*/
 
 /* Ownership Table */
 #define SPMI_OWNERSHIP_TABLE_REG(N)    (0x0700 + (4 * (N)))
@@ -88,6 +86,7 @@ enum pmic_arb_cmd_op_code {
 
 /* Maximum number of support PMIC peripherals */
 #define PMIC_ARB_MAX_PERIPHS           256
+#define PMIC_ARB_MAX_CHNL              128
 #define PMIC_ARB_PERIPH_ID_VALID       (1 << 15)
 #define PMIC_ARB_TIMEOUT_US            100
 #define PMIC_ARB_MAX_TRANS_BYTES       (8)
@@ -98,14 +97,17 @@ enum pmic_arb_cmd_op_code {
 /* interrupt enable bit */
 #define SPMI_PIC_ACC_ENABLE_BIT                BIT(0)
 
+struct pmic_arb_ver_ops;
+
 /**
  * spmi_pmic_arb_dev - SPMI PMIC Arbiter object
  *
- * @base:              address of the PMIC Arbiter core registers.
+ * @rd_base:           on v1 "core", on v2 "observer" register base off DT.
+ * @wr_base:           on v1 "core", on v2 "chnls"    register base off DT.
  * @intr:              address of the SPMI interrupt control registers.
  * @cnfg:              address of the PMIC Arbiter configuration registers.
  * @lock:              lock to synchronize accesses.
- * @channel:           which channel to use for accesses.
+ * @channel:           execution environment channel to use for accesses.
  * @irq:               PMIC ARB interrupt.
  * @ee:                        the current Execution Environment
  * @min_apid:          minimum APID (used for bounding IRQ search)
@@ -113,10 +115,14 @@ enum pmic_arb_cmd_op_code {
  * @mapping_table:     in-memory copy of PPID -> APID mapping table.
  * @domain:            irq domain object for PMIC IRQ domain
  * @spmic:             SPMI controller object
- * @apid_to_ppid:      cached mapping from APID to PPID
+ * @apid_to_ppid:      in-memory copy of APID -> PPID mapping table.
+ * @ver_ops:           version dependent operations.
+ * @ppid_to_chan       in-memory copy of PPID -> channel (APID) mapping table.
+ *                     v2 only.
  */
 struct spmi_pmic_arb_dev {
-       void __iomem            *base;
+       void __iomem            *rd_base;
+       void __iomem            *wr_base;
        void __iomem            *intr;
        void __iomem            *cnfg;
        raw_spinlock_t          lock;
@@ -129,17 +135,54 @@ struct spmi_pmic_arb_dev {
        struct irq_domain       *domain;
        struct spmi_controller  *spmic;
        u16                     apid_to_ppid[256];
+       const struct pmic_arb_ver_ops *ver_ops;
+       u8                      *ppid_to_chan;
+};
+
+/**
+ * pmic_arb_ver: version dependent functionality.
+ *
+ * @non_data_cmd:      on v1 issues an spmi non-data command.
+ *                     on v2 no HW support, returns -EOPNOTSUPP.
+ * @offset:            on v1 offset of per-ee channel.
+ *                     on v2 offset of per-ee and per-ppid channel.
+ * @fmt_cmd:           formats a GENI/SPMI command.
+ * @owner_acc_status:  on v1 offset of PMIC_ARB_SPMI_PIC_OWNERm_ACC_STATUSn
+ *                     on v2 offset of SPMI_PIC_OWNERm_ACC_STATUSn.
+ * @acc_enable:                on v1 offset of PMIC_ARB_SPMI_PIC_ACC_ENABLEn
+ *                     on v2 offset of SPMI_PIC_ACC_ENABLEn.
+ * @irq_status:                on v1 offset of PMIC_ARB_SPMI_PIC_IRQ_STATUSn
+ *                     on v2 offset of SPMI_PIC_IRQ_STATUSn.
+ * @irq_clear:         on v1 offset of PMIC_ARB_SPMI_PIC_IRQ_CLEARn
+ *                     on v2 offset of SPMI_PIC_IRQ_CLEARn.
+ */
+struct pmic_arb_ver_ops {
+       /* spmi commands (read_cmd, write_cmd, cmd) functionality */
+       u32 (*offset)(struct spmi_pmic_arb_dev *dev, u8 sid, u16 addr);
+       u32 (*fmt_cmd)(u8 opc, u8 sid, u16 addr, u8 bc);
+       int (*non_data_cmd)(struct spmi_controller *ctrl, u8 opc, u8 sid);
+       /* Interrupts controller functionality (offset of PIC registers) */
+       u32 (*owner_acc_status)(u8 m, u8 n);
+       u32 (*acc_enable)(u8 n);
+       u32 (*irq_status)(u8 n);
+       u32 (*irq_clear)(u8 n);
 };
 
 static inline u32 pmic_arb_base_read(struct spmi_pmic_arb_dev *dev, u32 offset)
 {
-       return readl_relaxed(dev->base + offset);
+       return readl_relaxed(dev->rd_base + offset);
 }
 
 static inline void pmic_arb_base_write(struct spmi_pmic_arb_dev *dev,
                                       u32 offset, u32 val)
 {
-       writel_relaxed(val, dev->base + offset);
+       writel_relaxed(val, dev->wr_base + offset);
+}
+
+static inline void pmic_arb_set_rd_cmd(struct spmi_pmic_arb_dev *dev,
+                                      u32 offset, u32 val)
+{
+       writel_relaxed(val, dev->rd_base + offset);
 }
 
 /**
@@ -168,15 +211,16 @@ pa_write_data(struct spmi_pmic_arb_dev *dev, const u8 *buf, u32 reg, u8 bc)
        pmic_arb_base_write(dev, reg, data);
 }
 
-static int pmic_arb_wait_for_done(struct spmi_controller *ctrl)
+static int pmic_arb_wait_for_done(struct spmi_controller *ctrl,
+                                 void __iomem *base, u8 sid, u16 addr)
 {
        struct spmi_pmic_arb_dev *dev = spmi_controller_get_drvdata(ctrl);
        u32 status = 0;
        u32 timeout = PMIC_ARB_TIMEOUT_US;
-       u32 offset = PMIC_ARB_STATUS(dev->channel);
+       u32 offset = dev->ver_ops->offset(dev, sid, addr) + PMIC_ARB_STATUS;
 
        while (timeout--) {
-               status = pmic_arb_base_read(dev, offset);
+               status = readl_relaxed(base + offset);
 
                if (status & PMIC_ARB_STATUS_DONE) {
                        if (status & PMIC_ARB_STATUS_DENIED) {
@@ -211,28 +255,45 @@ static int pmic_arb_wait_for_done(struct spmi_controller *ctrl)
        return -ETIMEDOUT;
 }
 
-/* Non-data command */
-static int pmic_arb_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid)
+static int
+pmic_arb_non_data_cmd_v1(struct spmi_controller *ctrl, u8 opc, u8 sid)
 {
        struct spmi_pmic_arb_dev *pmic_arb = spmi_controller_get_drvdata(ctrl);
        unsigned long flags;
        u32 cmd;
        int rc;
-
-       /* Check for valid non-data command */
-       if (opc < SPMI_CMD_RESET || opc > SPMI_CMD_WAKEUP)
-               return -EINVAL;
+       u32 offset = pmic_arb->ver_ops->offset(pmic_arb, sid, 0);
 
        cmd = ((opc | 0x40) << 27) | ((sid & 0xf) << 20);
 
        raw_spin_lock_irqsave(&pmic_arb->lock, flags);
-       pmic_arb_base_write(pmic_arb, PMIC_ARB_CMD(pmic_arb->channel), cmd);
-       rc = pmic_arb_wait_for_done(ctrl);
+       pmic_arb_base_write(pmic_arb, offset + PMIC_ARB_CMD, cmd);
+       rc = pmic_arb_wait_for_done(ctrl, pmic_arb->wr_base, sid, 0);
        raw_spin_unlock_irqrestore(&pmic_arb->lock, flags);
 
        return rc;
 }
 
+static int
+pmic_arb_non_data_cmd_v2(struct spmi_controller *ctrl, u8 opc, u8 sid)
+{
+       return -EOPNOTSUPP;
+}
+
+/* Non-data command */
+static int pmic_arb_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid)
+{
+       struct spmi_pmic_arb_dev *pmic_arb = spmi_controller_get_drvdata(ctrl);
+
+       dev_dbg(&ctrl->dev, "cmd op:0x%x sid:%d\n", opc, sid);
+
+       /* Check for valid non-data command */
+       if (opc < SPMI_CMD_RESET || opc > SPMI_CMD_WAKEUP)
+               return -EINVAL;
+
+       return pmic_arb->ver_ops->non_data_cmd(ctrl, opc, sid);
+}
+
 static int pmic_arb_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
                             u16 addr, u8 *buf, size_t len)
 {
@@ -241,10 +302,11 @@ static int pmic_arb_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
        u8 bc = len - 1;
        u32 cmd;
        int rc;
+       u32 offset = pmic_arb->ver_ops->offset(pmic_arb, sid, addr);
 
        if (bc >= PMIC_ARB_MAX_TRANS_BYTES) {
                dev_err(&ctrl->dev,
-                       "pmic-arb supports 1..%d bytes per trans, but %d requested",
+                       "pmic-arb supports 1..%d bytes per trans, but:%zu requested",
                        PMIC_ARB_MAX_TRANS_BYTES, len);
                return  -EINVAL;
        }
@@ -259,20 +321,20 @@ static int pmic_arb_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
        else
                return -EINVAL;
 
-       cmd = (opc << 27) | ((sid & 0xf) << 20) | (addr << 4) | (bc & 0x7);
+       cmd = pmic_arb->ver_ops->fmt_cmd(opc, sid, addr, bc);
 
        raw_spin_lock_irqsave(&pmic_arb->lock, flags);
-       pmic_arb_base_write(pmic_arb, PMIC_ARB_CMD(pmic_arb->channel), cmd);
-       rc = pmic_arb_wait_for_done(ctrl);
+       pmic_arb_set_rd_cmd(pmic_arb, offset + PMIC_ARB_CMD, cmd);
+       rc = pmic_arb_wait_for_done(ctrl, pmic_arb->rd_base, sid, addr);
        if (rc)
                goto done;
 
-       pa_read_data(pmic_arb, buf, PMIC_ARB_RDATA0(pmic_arb->channel),
+       pa_read_data(pmic_arb, buf, offset + PMIC_ARB_RDATA0,
                     min_t(u8, bc, 3));
 
        if (bc > 3)
                pa_read_data(pmic_arb, buf + 4,
-                               PMIC_ARB_RDATA1(pmic_arb->channel), bc - 4);
+                               offset + PMIC_ARB_RDATA1, bc - 4);
 
 done:
        raw_spin_unlock_irqrestore(&pmic_arb->lock, flags);
@@ -287,10 +349,11 @@ static int pmic_arb_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
        u8 bc = len - 1;
        u32 cmd;
        int rc;
+       u32 offset = pmic_arb->ver_ops->offset(pmic_arb, sid, addr);
 
        if (bc >= PMIC_ARB_MAX_TRANS_BYTES) {
                dev_err(&ctrl->dev,
-                       "pmic-arb supports 1..%d bytes per trans, but:%d requested",
+                       "pmic-arb supports 1..%d bytes per trans, but:%zu requested",
                        PMIC_ARB_MAX_TRANS_BYTES, len);
                return  -EINVAL;
        }
@@ -307,19 +370,19 @@ static int pmic_arb_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
        else
                return -EINVAL;
 
-       cmd = (opc << 27) | ((sid & 0xf) << 20) | (addr << 4) | (bc & 0x7);
+       cmd = pmic_arb->ver_ops->fmt_cmd(opc, sid, addr, bc);
 
        /* Write data to FIFOs */
        raw_spin_lock_irqsave(&pmic_arb->lock, flags);
-       pa_write_data(pmic_arb, buf, PMIC_ARB_WDATA0(pmic_arb->channel)
-                                                       , min_t(u8, bc, 3));
+       pa_write_data(pmic_arb, buf, offset + PMIC_ARB_WDATA0,
+                     min_t(u8, bc, 3));
        if (bc > 3)
                pa_write_data(pmic_arb, buf + 4,
-                               PMIC_ARB_WDATA1(pmic_arb->channel), bc - 4);
+                               offset + PMIC_ARB_WDATA1, bc - 4);
 
        /* Start the transaction */
-       pmic_arb_base_write(pmic_arb, PMIC_ARB_CMD(pmic_arb->channel), cmd);
-       rc = pmic_arb_wait_for_done(ctrl);
+       pmic_arb_base_write(pmic_arb, offset + PMIC_ARB_CMD, cmd);
+       rc = pmic_arb_wait_for_done(ctrl, pmic_arb->wr_base, sid, addr);
        raw_spin_unlock_irqrestore(&pmic_arb->lock, flags);
 
        return rc;
@@ -376,7 +439,7 @@ static void periph_interrupt(struct spmi_pmic_arb_dev *pa, u8 apid)
        u32 status;
        int id;
 
-       status = readl_relaxed(pa->intr + SPMI_PIC_IRQ_STATUS(apid));
+       status = readl_relaxed(pa->intr + pa->ver_ops->irq_status(apid));
        while (status) {
                id = ffs(status) - 1;
                status &= ~(1 << id);
@@ -402,7 +465,7 @@ static void pmic_arb_chained_irq(unsigned int irq, struct irq_desc *desc)
 
        for (i = first; i <= last; ++i) {
                status = readl_relaxed(intr +
-                                      SPMI_PIC_OWNER_ACC_STATUS(pa->ee, i));
+                                     pa->ver_ops->owner_acc_status(pa->ee, i));
                while (status) {
                        id = ffs(status) - 1;
                        status &= ~(1 << id);
@@ -422,7 +485,7 @@ static void qpnpint_irq_ack(struct irq_data *d)
        u8 data;
 
        raw_spin_lock_irqsave(&pa->lock, flags);
-       writel_relaxed(1 << irq, pa->intr + SPMI_PIC_IRQ_CLEAR(apid));
+       writel_relaxed(1 << irq, pa->intr + pa->ver_ops->irq_clear(apid));
        raw_spin_unlock_irqrestore(&pa->lock, flags);
 
        data = 1 << irq;
@@ -439,10 +502,11 @@ static void qpnpint_irq_mask(struct irq_data *d)
        u8 data;
 
        raw_spin_lock_irqsave(&pa->lock, flags);
-       status = readl_relaxed(pa->intr + SPMI_PIC_ACC_ENABLE(apid));
+       status = readl_relaxed(pa->intr + pa->ver_ops->acc_enable(apid));
        if (status & SPMI_PIC_ACC_ENABLE_BIT) {
                status = status & ~SPMI_PIC_ACC_ENABLE_BIT;
-               writel_relaxed(status, pa->intr + SPMI_PIC_ACC_ENABLE(apid));
+               writel_relaxed(status, pa->intr +
+                              pa->ver_ops->acc_enable(apid));
        }
        raw_spin_unlock_irqrestore(&pa->lock, flags);
 
@@ -460,10 +524,10 @@ static void qpnpint_irq_unmask(struct irq_data *d)
        u8 data;
 
        raw_spin_lock_irqsave(&pa->lock, flags);
-       status = readl_relaxed(pa->intr + SPMI_PIC_ACC_ENABLE(apid));
+       status = readl_relaxed(pa->intr + pa->ver_ops->acc_enable(apid));
        if (!(status & SPMI_PIC_ACC_ENABLE_BIT)) {
                writel_relaxed(status | SPMI_PIC_ACC_ENABLE_BIT,
-                               pa->intr + SPMI_PIC_ACC_ENABLE(apid));
+                               pa->intr + pa->ver_ops->acc_enable(apid));
        }
        raw_spin_unlock_irqrestore(&pa->lock, flags);
 
@@ -624,6 +688,91 @@ static int qpnpint_irq_domain_map(struct irq_domain *d,
        return 0;
 }
 
+/* v1 offset per ee */
+static u32 pmic_arb_offset_v1(struct spmi_pmic_arb_dev *pa, u8 sid, u16 addr)
+{
+       return 0x800 + 0x80 * pa->channel;
+}
+
+/* v2 offset per ppid (chan) and per ee */
+static u32 pmic_arb_offset_v2(struct spmi_pmic_arb_dev *pa, u8 sid, u16 addr)
+{
+       u16 ppid = (sid << 8) | (addr >> 8);
+       u8  chan = pa->ppid_to_chan[ppid];
+
+       return 0x1000 * pa->ee + 0x8000 * chan;
+}
+
+static u32 pmic_arb_fmt_cmd_v1(u8 opc, u8 sid, u16 addr, u8 bc)
+{
+       return (opc << 27) | ((sid & 0xf) << 20) | (addr << 4) | (bc & 0x7);
+}
+
+static u32 pmic_arb_fmt_cmd_v2(u8 opc, u8 sid, u16 addr, u8 bc)
+{
+       return (opc << 27) | ((addr & 0xff) << 4) | (bc & 0x7);
+}
+
+static u32 pmic_arb_owner_acc_status_v1(u8 m, u8 n)
+{
+       return 0x20 * m + 0x4 * n;
+}
+
+static u32 pmic_arb_owner_acc_status_v2(u8 m, u8 n)
+{
+       return 0x100000 + 0x1000 * m + 0x4 * n;
+}
+
+static u32 pmic_arb_acc_enable_v1(u8 n)
+{
+       return 0x200 + 0x4 * n;
+}
+
+static u32 pmic_arb_acc_enable_v2(u8 n)
+{
+       return 0x1000 * n;
+}
+
+static u32 pmic_arb_irq_status_v1(u8 n)
+{
+       return 0x600 + 0x4 * n;
+}
+
+static u32 pmic_arb_irq_status_v2(u8 n)
+{
+       return 0x4 + 0x1000 * n;
+}
+
+static u32 pmic_arb_irq_clear_v1(u8 n)
+{
+       return 0xA00 + 0x4 * n;
+}
+
+static u32 pmic_arb_irq_clear_v2(u8 n)
+{
+       return 0x8 + 0x1000 * n;
+}
+
+static const struct pmic_arb_ver_ops pmic_arb_v1 = {
+       .non_data_cmd           = pmic_arb_non_data_cmd_v1,
+       .offset                 = pmic_arb_offset_v1,
+       .fmt_cmd                = pmic_arb_fmt_cmd_v1,
+       .owner_acc_status       = pmic_arb_owner_acc_status_v1,
+       .acc_enable             = pmic_arb_acc_enable_v1,
+       .irq_status             = pmic_arb_irq_status_v1,
+       .irq_clear              = pmic_arb_irq_clear_v1,
+};
+
+static const struct pmic_arb_ver_ops pmic_arb_v2 = {
+       .non_data_cmd           = pmic_arb_non_data_cmd_v2,
+       .offset                 = pmic_arb_offset_v2,
+       .fmt_cmd                = pmic_arb_fmt_cmd_v2,
+       .owner_acc_status       = pmic_arb_owner_acc_status_v2,
+       .acc_enable             = pmic_arb_acc_enable_v2,
+       .irq_status             = pmic_arb_irq_status_v2,
+       .irq_clear              = pmic_arb_irq_clear_v2,
+};
+
 static const struct irq_domain_ops pmic_arb_irq_domain_ops = {
        .map    = qpnpint_irq_domain_map,
        .xlate  = qpnpint_irq_domain_dt_translate,
@@ -634,8 +783,10 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
        struct spmi_pmic_arb_dev *pa;
        struct spmi_controller *ctrl;
        struct resource *res;
-       u32 channel, ee;
+       void __iomem *core;
+       u32 channel, ee, hw_ver;
        int err, i;
+       bool is_v1;
 
        ctrl = spmi_controller_alloc(&pdev->dev, sizeof(*pa));
        if (!ctrl)
@@ -645,12 +796,65 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
        pa->spmic = ctrl;
 
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core");
-       pa->base = devm_ioremap_resource(&ctrl->dev, res);
-       if (IS_ERR(pa->base)) {
-               err = PTR_ERR(pa->base);
+       core = devm_ioremap_resource(&ctrl->dev, res);
+       if (IS_ERR(core)) {
+               err = PTR_ERR(core);
                goto err_put_ctrl;
        }
 
+       hw_ver = readl_relaxed(core + PMIC_ARB_VERSION);
+       is_v1  = (hw_ver < PMIC_ARB_VERSION_V2_MIN);
+
+       dev_info(&ctrl->dev, "PMIC Arb Version-%d (0x%x)\n", (is_v1 ? 1 : 2),
+               hw_ver);
+
+       if (is_v1) {
+               pa->ver_ops = &pmic_arb_v1;
+               pa->wr_base = core;
+               pa->rd_base = core;
+       } else {
+               u8  chan;
+               u16 ppid;
+               u32 regval;
+
+               pa->ver_ops = &pmic_arb_v2;
+
+               res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+                                                  "obsrvr");
+               pa->rd_base = devm_ioremap_resource(&ctrl->dev, res);
+               if (IS_ERR(pa->rd_base)) {
+                       err = PTR_ERR(pa->rd_base);
+                       goto err_put_ctrl;
+               }
+
+               res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+                                                  "chnls");
+               pa->wr_base = devm_ioremap_resource(&ctrl->dev, res);
+               if (IS_ERR(pa->wr_base)) {
+                       err = PTR_ERR(pa->wr_base);
+                       goto err_put_ctrl;
+               }
+
+               pa->ppid_to_chan = devm_kzalloc(&ctrl->dev,
+                                       PPID_TO_CHAN_TABLE_SZ, GFP_KERNEL);
+               if (!pa->ppid_to_chan) {
+                       err = -ENOMEM;
+                       goto err_put_ctrl;
+               }
+               /*
+                * PMIC_ARB_REG_CHNL is a table in HW mapping channel to ppid.
+                * ppid_to_chan is an in-memory invert of that table.
+                */
+               for (chan = 0; chan < PMIC_ARB_MAX_CHNL; ++chan) {
+                       regval = readl_relaxed(core + PMIC_ARB_REG_CHNL(chan));
+                       if (!regval)
+                               continue;
+
+                       ppid = (regval >> 8) & 0xFFF;
+                       pa->ppid_to_chan[ppid] = chan;
+               }
+       }
+
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "intr");
        pa->intr = devm_ioremap_resource(&ctrl->dev, res);
        if (IS_ERR(pa->intr)) {
@@ -731,9 +935,6 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
        if (err)
                goto err_domain_remove;
 
-       dev_dbg(&ctrl->dev, "PMIC Arb Version 0x%x\n",
-               pmic_arb_base_read(pa, PMIC_ARB_VERSION));
-
        return 0;
 
 err_domain_remove:
index 1d92f5103ebfe885028a28b93aa9fcef87921d39..94938436aef9c7313403882141a8fc1858413190 100644 (file)
@@ -1,4 +1,5 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/*
+ * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -316,11 +317,6 @@ static int spmi_drv_probe(struct device *dev)
        struct spmi_device *sdev = to_spmi_device(dev);
        int err;
 
-       /* Ensure the slave is in ACTIVE state */
-       err = spmi_command_wakeup(sdev);
-       if (err)
-               goto fail_wakeup;
-
        pm_runtime_get_noresume(dev);
        pm_runtime_set_active(dev);
        pm_runtime_enable(dev);
@@ -335,7 +331,6 @@ fail_probe:
        pm_runtime_disable(dev);
        pm_runtime_set_suspended(dev);
        pm_runtime_put_noidle(dev);
-fail_wakeup:
        return err;
 }
 
index 0e3d8c7add24e1955e2bd480075df0caf09b1a94..b0b96ab31954a98718d1af05121656abc1533e17 100644 (file)
@@ -1106,6 +1106,7 @@ struct dma_buf *ion_share_dma_buf(struct ion_client *client,
        struct ion_buffer *buffer;
        struct dma_buf *dmabuf;
        bool valid_handle;
+       DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
 
        mutex_lock(&client->lock);
        valid_handle = ion_handle_validate(client, handle);
@@ -1118,8 +1119,12 @@ struct dma_buf *ion_share_dma_buf(struct ion_client *client,
        ion_buffer_get(buffer);
        mutex_unlock(&client->lock);
 
-       dmabuf = dma_buf_export(buffer, &dma_buf_ops, buffer->size, O_RDWR,
-                               NULL);
+       exp_info.ops = &dma_buf_ops;
+       exp_info.size = buffer->size;
+       exp_info.flags = O_RDWR;
+       exp_info.priv = buffer;
+
+       dmabuf = dma_buf_export(&exp_info);
        if (IS_ERR(dmabuf)) {
                ion_buffer_put(buffer);
                return dmabuf;
index fe1fd05423e9b6aec1d1cd55e38937a3d1f32d73..5af01351306d3debe68863ae9444629024ac4e83 100644 (file)
@@ -153,7 +153,7 @@ static int ll_ddelete(const struct dentry *de)
 
        CDEBUG(D_DENTRY, "%s dentry %pd (%p, parent %p, inode %p) %s%s\n",
               d_lustre_invalid((struct dentry *)de) ? "deleting" : "keeping",
-              de, de, de->d_parent, de->d_inode,
+              de, de, de->d_parent, d_inode(de),
               d_unhashed(de) ? "" : "hashed,",
               list_empty(&de->d_subdirs) ? "" : "subdirs");
 
@@ -167,8 +167,8 @@ static int ll_ddelete(const struct dentry *de)
 #if 0
        /* if not ldlm lock for this inode, set i_nlink to 0 so that
         * this inode can be recycled later b=20433 */
-       if (de->d_inode && !find_cbdata(de->d_inode))
-               clear_nlink(de->d_inode);
+       if (d_really_is_positive(de) && !find_cbdata(d_inode(de)))
+               clear_nlink(d_inode(de));
 #endif
 
        if (d_lustre_invalid((struct dentry *)de))
@@ -181,7 +181,7 @@ int ll_d_init(struct dentry *de)
        LASSERT(de != NULL);
 
        CDEBUG(D_DENTRY, "ldd on dentry %pd (%p) parent %p inode %p refc %d\n",
-               de, de, de->d_parent, de->d_inode,
+               de, de, de->d_parent, d_inode(de),
                d_count(de));
 
        if (de->d_fsdata == NULL) {
@@ -261,7 +261,7 @@ void ll_invalidate_aliases(struct inode *inode)
        ll_d_hlist_for_each_entry(dentry, p, &inode->i_dentry, d_u.d_alias) {
                CDEBUG(D_DENTRY, "dentry in drop %pd (%p) parent %p inode %p flags %d\n",
                       dentry, dentry, dentry->d_parent,
-                      dentry->d_inode, dentry->d_flags);
+                      d_inode(dentry), dentry->d_flags);
 
                d_lustre_invalidate(dentry, 0);
        }
@@ -309,7 +309,7 @@ void ll_lookup_finish_locks(struct lookup_intent *it, struct inode *inode)
 static int ll_revalidate_dentry(struct dentry *dentry,
                                unsigned int lookup_flags)
 {
-       struct inode *dir = dentry->d_parent->d_inode;
+       struct inode *dir = d_inode(dentry->d_parent);
 
        /*
         * if open&create is set, talk to MDS to make sure file is created if
@@ -329,7 +329,7 @@ static int ll_revalidate_dentry(struct dentry *dentry,
        if (lookup_flags & LOOKUP_RCU)
                return -ECHILD;
 
-       do_statahead_enter(dir, &dentry, dentry->d_inode == NULL);
+       do_statahead_enter(dir, &dentry, d_inode(dentry) == NULL);
        ll_statahead_mark(dir, dentry);
        return 1;
 }
index 529062ea112b63ca99a604b7c0686b6d459d172a..4b44c634fcc3de6159c89671826c8762a21dd582 100644 (file)
@@ -388,7 +388,7 @@ int ll_file_release(struct inode *inode, struct file *file)
 static int ll_intent_file_open(struct dentry *dentry, void *lmm,
                               int lmmsize, struct lookup_intent *itp)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct ll_sb_info *sbi = ll_i2sbi(inode);
        struct dentry *parent = dentry->d_parent;
        const char *name = dentry->d_name.name;
@@ -413,7 +413,7 @@ static int ll_intent_file_open(struct dentry *dentry, void *lmm,
                        opc = LUSTRE_OPC_CREATE;
        }
 
-       op_data  = ll_prep_md_op_data(NULL, parent->d_inode,
+       op_data  = ll_prep_md_op_data(NULL, d_inode(parent),
                                      inode, name, len,
                                      O_RDWR, opc, NULL);
        if (IS_ERR(op_data))
@@ -2896,7 +2896,7 @@ static int ll_inode_revalidate_fini(struct inode *inode, int rc)
 
 static int __ll_inode_revalidate(struct dentry *dentry, __u64 ibits)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct ptlrpc_request *req = NULL;
        struct obd_export *exp;
        int rc = 0;
@@ -2948,12 +2948,12 @@ static int __ll_inode_revalidate(struct dentry *dentry, __u64 ibits)
                   do_lookup() -> ll_revalidate_it(). We cannot use d_drop
                   here to preserve get_cwd functionality on 2.6.
                   Bug 10503 */
-               if (!dentry->d_inode->i_nlink)
+               if (!d_inode(dentry)->i_nlink)
                        d_lustre_invalidate(dentry, 0);
 
                ll_lookup_finish_locks(&oit, inode);
-       } else if (!ll_have_md_lock(dentry->d_inode, &ibits, LCK_MINMODE)) {
-               struct ll_sb_info *sbi = ll_i2sbi(dentry->d_inode);
+       } else if (!ll_have_md_lock(d_inode(dentry), &ibits, LCK_MINMODE)) {
+               struct ll_sb_info *sbi = ll_i2sbi(d_inode(dentry));
                u64 valid = OBD_MD_FLGETATTR;
                struct md_op_data *op_data;
                int ealen = 0;
@@ -2991,7 +2991,7 @@ out:
 
 static int ll_inode_revalidate(struct dentry *dentry, __u64 ibits)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int rc;
 
        rc = __ll_inode_revalidate(dentry, ibits);
@@ -3019,7 +3019,7 @@ static int ll_inode_revalidate(struct dentry *dentry, __u64 ibits)
 
 int ll_getattr(struct vfsmount *mnt, struct dentry *de, struct kstat *stat)
 {
-       struct inode *inode = de->d_inode;
+       struct inode *inode = d_inode(de);
        struct ll_sb_info *sbi = ll_i2sbi(inode);
        struct ll_inode_info *lli = ll_i2info(inode);
        int res = 0;
index e7422f5c9c6f408deb97d93583a52fe30ebc20c9..5f918e3c4683ddac82c864d1d45f7c5700d20282 100644 (file)
@@ -1488,7 +1488,7 @@ static inline void d_lustre_invalidate(struct dentry *dentry, int nested)
 {
        CDEBUG(D_DENTRY, "invalidate dentry %pd (%p) parent %p inode %p refc %d\n",
               dentry, dentry,
-              dentry->d_parent, dentry->d_inode, d_count(dentry));
+              dentry->d_parent, d_inode(dentry), d_count(dentry));
 
        spin_lock_nested(&dentry->d_lock,
                         nested ? DENTRY_D_LOCK_NESTED : DENTRY_D_LOCK_NORMAL);
index bf1ec277a1dc72072592551563e4b534f1ef7532..a27af7882170f42924aed9d0685dde3cf24f8211 100644 (file)
@@ -1166,7 +1166,7 @@ static int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data,
                  struct md_open_data **mod)
 {
        struct lustre_md md;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct ll_sb_info *sbi = ll_i2sbi(inode);
        struct ptlrpc_request *request = NULL;
        int rc, ia_valid;
@@ -1290,7 +1290,7 @@ static int ll_setattr_ost(struct inode *inode, struct iattr *attr)
  */
 int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct ll_inode_info *lli = ll_i2info(inode);
        struct md_op_data *op_data = NULL;
        struct md_open_data *mod = NULL;
@@ -1465,7 +1465,7 @@ out:
 
 int ll_setattr(struct dentry *de, struct iattr *attr)
 {
-       int mode = de->d_inode->i_mode;
+       int mode = d_inode(de)->i_mode;
 
        if ((attr->ia_valid & (ATTR_CTIME|ATTR_SIZE|ATTR_MODE)) ==
                              (ATTR_CTIME|ATTR_SIZE|ATTR_MODE))
index 243a7840457f17457a32d86a039eacedcbceeaa1..db43b81386f7aedfdf634488d4b6634329dc67f1 100644 (file)
@@ -230,11 +230,11 @@ static int ll_nfs_get_name_filldir(struct dir_context *ctx, const char *name,
 static int ll_get_name(struct dentry *dentry, char *name,
                       struct dentry *child)
 {
-       struct inode *dir = dentry->d_inode;
+       struct inode *dir = d_inode(dentry);
        int rc;
        struct ll_getname_data lgd = {
                .lgd_name = name,
-               .lgd_fid = ll_i2info(child->d_inode)->lli_fid,
+               .lgd_fid = ll_i2info(d_inode(child))->lli_fid,
                .ctx.actor = ll_nfs_get_name_filldir,
        };
 
@@ -282,7 +282,7 @@ static struct dentry *ll_fh_to_parent(struct super_block *sb, struct fid *fid,
 static struct dentry *ll_get_parent(struct dentry *dchild)
 {
        struct ptlrpc_request *req = NULL;
-       struct inode      *dir = dchild->d_inode;
+       struct inode      *dir = d_inode(dchild);
        struct ll_sb_info     *sbi;
        struct dentry    *result = NULL;
        struct mdt_body       *body;
index 49f1cb067ea2d8514e977ccfc8add30095dd51fc..5a25dcd10126c153deea7859a7896d2d5f43ba0d 100644 (file)
@@ -155,7 +155,7 @@ static void ll_invalidate_negative_children(struct inode *dir)
                        list_for_each_entry_safe(child, tmp_subdir,
                                                 &dentry->d_subdirs,
                                                 d_child) {
-                               if (child->d_inode == NULL)
+                               if (d_really_is_negative(child))
                                        d_lustre_invalidate(child, 1);
                        }
                }
@@ -392,7 +392,7 @@ struct dentry *ll_splice_alias(struct inode *inode, struct dentry *de)
                        iput(inode);
                        CDEBUG(D_DENTRY,
                               "Reuse dentry %p inode %p refc %d flags %#x\n",
-                             new, new->d_inode, d_count(new), new->d_flags);
+                             new, d_inode(new), d_count(new), new->d_flags);
                        return new;
                }
        }
@@ -401,7 +401,7 @@ struct dentry *ll_splice_alias(struct inode *inode, struct dentry *de)
                return ERR_PTR(rc);
        d_add(de, inode);
        CDEBUG(D_DENTRY, "Add dentry %p inode %p refc %d flags %#x\n",
-              de, de->d_inode, d_count(de), de->d_flags);
+              de, d_inode(de), d_count(de), de->d_flags);
        return de;
 }
 
@@ -448,7 +448,7 @@ static int ll_lookup_it_finish(struct ptlrpc_request *request,
                   !it_disposition(it, DISP_OPEN_CREATE)) {
                /* With DISP_OPEN_CREATE dentry will
                   instantiated in ll_create_it. */
-               LASSERT((*de)->d_inode == NULL);
+               LASSERT(d_inode(*de) == NULL);
                d_instantiate(*de, inode);
        }
 
@@ -541,7 +541,7 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
                goto out;
        }
 
-       inode = dentry->d_inode;
+       inode = d_inode(dentry);
        if ((it->it_op & IT_OPEN) && inode &&
            !S_ISREG(inode->i_mode) &&
            !S_ISDIR(inode->i_mode)) {
@@ -638,9 +638,9 @@ static int ll_atomic_open(struct inode *dir, struct dentry *dentry,
 
                        *opened |= FILE_CREATED;
                }
-               if (dentry->d_inode && it_disposition(it, DISP_OPEN_OPEN)) {
+               if (d_really_is_positive(dentry) && it_disposition(it, DISP_OPEN_OPEN)) {
                        /* Open dentry. */
-                       if (S_ISFIFO(dentry->d_inode->i_mode)) {
+                       if (S_ISFIFO(d_inode(dentry)->i_mode)) {
                                /* We cannot call open here as it would
                                 * deadlock.
                                 */
@@ -862,8 +862,8 @@ static int ll_create_nd(struct inode *dir, struct dentry *dentry,
 
 static inline void ll_get_child_fid(struct dentry *child, struct lu_fid *fid)
 {
-       if (child->d_inode)
-               *fid = *ll_inode2fid(child->d_inode);
+       if (d_really_is_positive(child))
+               *fid = *ll_inode2fid(d_inode(child));
 }
 
 /**
@@ -1076,7 +1076,7 @@ static int ll_symlink(struct inode *dir, struct dentry *dentry,
 static int ll_link(struct dentry *old_dentry, struct inode *dir,
                   struct dentry *new_dentry)
 {
-       struct inode *src = old_dentry->d_inode;
+       struct inode *src = d_inode(old_dentry);
        struct ll_sb_info *sbi = ll_i2sbi(dir);
        struct ptlrpc_request *request = NULL;
        struct md_op_data *op_data;
index b75562c6b5de95700b6ee1ee8eeae6e6e54931a6..7f8071242f23446b48d2e5d81df205302454f005 100644 (file)
@@ -880,7 +880,7 @@ static int do_sa_lookup(struct inode *dir, struct ll_sa_entry *entry)
 static int do_sa_revalidate(struct inode *dir, struct ll_sa_entry *entry,
                            struct dentry *dentry)
 {
-       struct inode         *inode = dentry->d_inode;
+       struct inode         *inode = d_inode(dentry);
        struct lookup_intent      it = { .it_op = IT_GETATTR,
                                         .d.lustre.it_lock_handle = 0 };
        struct md_enqueue_info   *minfo;
@@ -926,7 +926,7 @@ static int do_sa_revalidate(struct inode *dir, struct ll_sa_entry *entry,
 static void ll_statahead_one(struct dentry *parent, const char *entry_name,
                             int entry_name_len)
 {
-       struct inode         *dir    = parent->d_inode;
+       struct inode         *dir    = d_inode(parent);
        struct ll_inode_info     *lli    = ll_i2info(dir);
        struct ll_statahead_info *sai    = lli->lli_sai;
        struct dentry       *dentry = NULL;
@@ -944,8 +944,8 @@ static void ll_statahead_one(struct dentry *parent, const char *entry_name,
                rc = do_sa_lookup(dir, entry);
        } else {
                rc = do_sa_revalidate(dir, entry, dentry);
-               if (rc == 1 && agl_should_run(sai, dentry->d_inode))
-                       ll_agl_add(sai, dentry->d_inode, entry->se_index);
+               if (rc == 1 && agl_should_run(sai, d_inode(dentry)))
+                       ll_agl_add(sai, d_inode(dentry), entry->se_index);
        }
 
        if (dentry != NULL)
@@ -968,7 +968,7 @@ static void ll_statahead_one(struct dentry *parent, const char *entry_name,
 static int ll_agl_thread(void *arg)
 {
        struct dentry       *parent = (struct dentry *)arg;
-       struct inode         *dir    = parent->d_inode;
+       struct inode         *dir    = d_inode(parent);
        struct ll_inode_info     *plli   = ll_i2info(dir);
        struct ll_inode_info     *clli;
        struct ll_sb_info       *sbi    = ll_i2sbi(dir);
@@ -1042,7 +1042,7 @@ static void ll_start_agl(struct dentry *parent, struct ll_statahead_info *sai)
        CDEBUG(D_READA, "start agl thread: sai %p, parent %pd\n",
               sai, parent);
 
-       plli = ll_i2info(parent->d_inode);
+       plli = ll_i2info(d_inode(parent));
        task = kthread_run(ll_agl_thread, parent,
                               "ll_agl_%u", plli->lli_opendir_pid);
        if (IS_ERR(task)) {
@@ -1059,7 +1059,7 @@ static void ll_start_agl(struct dentry *parent, struct ll_statahead_info *sai)
 static int ll_statahead_thread(void *arg)
 {
        struct dentry       *parent = (struct dentry *)arg;
-       struct inode         *dir    = parent->d_inode;
+       struct inode         *dir    = d_inode(parent);
        struct ll_inode_info     *plli   = ll_i2info(dir);
        struct ll_inode_info     *clli;
        struct ll_sb_info       *sbi    = ll_i2sbi(dir);
@@ -1604,7 +1604,7 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp,
                        rc = md_revalidate_lock(ll_i2mdexp(dir), &it,
                                                ll_inode2fid(inode), &bits);
                        if (rc == 1) {
-                               if ((*dentryp)->d_inode == NULL) {
+                               if (d_inode(*dentryp) == NULL) {
                                        struct dentry *alias;
 
                                        alias = ll_splice_alias(inode,
@@ -1614,13 +1614,13 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp,
                                                return PTR_ERR(alias);
                                        }
                                        *dentryp = alias;
-                               } else if ((*dentryp)->d_inode != inode) {
+                               } else if (d_inode(*dentryp) != inode) {
                                        /* revalidate, but inode is recreated */
                                        CDEBUG(D_READA,
                                              "stale dentry %pd inode %lu/%u, statahead inode %lu/%u\n",
                                              *dentryp,
-                                             (*dentryp)->d_inode->i_ino,
-                                             (*dentryp)->d_inode->i_generation,
+                                             d_inode(*dentryp)->i_ino,
+                                             d_inode(*dentryp)->i_generation,
                                              inode->i_ino,
                                              inode->i_generation);
                                        ll_sai_unplug(sai, entry);
@@ -1666,8 +1666,8 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp,
 
        /* get parent reference count here, and put it in ll_statahead_thread */
        parent = dget((*dentryp)->d_parent);
-       if (unlikely(sai->sai_inode != parent->d_inode)) {
-               struct ll_inode_info *nlli = ll_i2info(parent->d_inode);
+       if (unlikely(sai->sai_inode != d_inode(parent))) {
+               struct ll_inode_info *nlli = ll_i2info(d_inode(parent));
 
                CWARN("Race condition, someone changed %pd just now: old parent "DFID", new parent "DFID"\n",
                      *dentryp,
@@ -1689,7 +1689,7 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp,
        ll_sai_get(sai);
        lli->lli_sai = sai;
 
-       plli = ll_i2info(parent->d_inode);
+       plli = ll_i2info(d_inode(parent));
        rc = PTR_ERR(kthread_run(ll_statahead_thread, parent,
                                 "ll_sa_%u", plli->lli_opendir_pid));
        thread = &sai->sai_thread;
index 686b6a574cc585610641da696728a1acc12b746b..3711e671a4dfaa21af87d19857416f8f0f631734 100644 (file)
@@ -120,7 +120,7 @@ failed:
 
 static void *ll_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct ptlrpc_request *request = NULL;
        int rc;
        char *symname = NULL;
index b439936b4524e5d8032f451cd6fd1a710bc400b4..e0fcbe1395fd31cfec2319f9a61768961a813be5 100644 (file)
@@ -214,7 +214,7 @@ int ll_setxattr_common(struct inode *inode, const char *name,
 int ll_setxattr(struct dentry *dentry, const char *name,
                const void *value, size_t size, int flags)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
 
        LASSERT(inode);
        LASSERT(name);
@@ -267,7 +267,7 @@ int ll_setxattr(struct dentry *dentry, const char *name,
 
 int ll_removexattr(struct dentry *dentry, const char *name)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
 
        LASSERT(inode);
        LASSERT(name);
@@ -457,7 +457,7 @@ out:
 ssize_t ll_getxattr(struct dentry *dentry, const char *name,
                    void *buffer, size_t size)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
 
        LASSERT(inode);
        LASSERT(name);
@@ -545,7 +545,7 @@ out:
 
 ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int rc = 0, rc2 = 0;
        struct lov_mds_md *lmm = NULL;
        struct ptlrpc_request *request = NULL;
index f28ffef0d1f0caada0f02d5e2d6ed7ea07aea3bf..e9d0691b21d3aa2f7119c32127dac919fcfecb5d 100644 (file)
@@ -279,7 +279,7 @@ struct region_info {
 
 struct bcm2048_device {
        struct i2c_client *client;
-       struct video_device *videodev;
+       struct video_device videodev;
        struct work_struct work;
        struct completion compl;
        struct mutex mutex;
@@ -1579,7 +1579,7 @@ static void bcm2048_parse_rt_match_d(struct bcm2048_device *bdev, int i,
                bcm2048_parse_rds_rt_block(bdev, i, index+2, crc);
 }
 
-static int bcm2048_parse_rds_rt(struct bcm2048_device *bdev)
+static void bcm2048_parse_rds_rt(struct bcm2048_device *bdev)
 {
        int i, index = 0, crc, match_b = 0, match_c = 0, match_d = 0;
 
@@ -1615,8 +1615,6 @@ static int bcm2048_parse_rds_rt(struct bcm2048_device *bdev)
                                        match_b = 1;
                }
        }
-
-       return 0;
 }
 
 static void bcm2048_parse_rds_ps_block(struct bcm2048_device *bdev, int i,
@@ -2273,7 +2271,7 @@ done:
  */
 static const struct v4l2_file_operations bcm2048_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        /* for RDS read support */
        .open           = bcm2048_fops_open,
        .release        = bcm2048_fops_release,
@@ -2584,7 +2582,7 @@ static struct v4l2_ioctl_ops bcm2048_ioctl_ops = {
 static struct video_device bcm2048_viddev_template = {
        .fops                   = &bcm2048_fops,
        .name                   = BCM2048_DRIVER_NAME,
-       .release                = video_device_release,
+       .release                = video_device_release_empty,
        .ioctl_ops              = &bcm2048_ioctl_ops,
 };
 
@@ -2603,13 +2601,6 @@ static int bcm2048_i2c_driver_probe(struct i2c_client *client,
                goto exit;
        }
 
-       bdev->videodev = video_device_alloc();
-       if (!bdev->videodev) {
-               dev_dbg(&client->dev, "Failed to alloc video device.\n");
-               err = -ENOMEM;
-               goto free_bdev;
-       }
-
        bdev->client = client;
        i2c_set_clientdata(client, bdev);
        mutex_init(&bdev->mutex);
@@ -2622,16 +2613,16 @@ static int bcm2048_i2c_driver_probe(struct i2c_client *client,
                        client->name, bdev);
                if (err < 0) {
                        dev_err(&client->dev, "Could not request IRQ\n");
-                       goto free_vdev;
+                       goto free_bdev;
                }
                dev_dbg(&client->dev, "IRQ requested.\n");
        } else {
                dev_dbg(&client->dev, "IRQ not configured. Using timeouts.\n");
        }
 
-       *bdev->videodev = bcm2048_viddev_template;
-       video_set_drvdata(bdev->videodev, bdev);
-       if (video_register_device(bdev->videodev, VFL_TYPE_RADIO, radio_nr)) {
+       bdev->videodev = bcm2048_viddev_template;
+       video_set_drvdata(&bdev->videodev, bdev);
+       if (video_register_device(&bdev->videodev, VFL_TYPE_RADIO, radio_nr)) {
                dev_dbg(&client->dev, "Could not register video device.\n");
                err = -EIO;
                goto free_irq;
@@ -2654,18 +2645,13 @@ static int bcm2048_i2c_driver_probe(struct i2c_client *client,
 free_sysfs:
        bcm2048_sysfs_unregister_properties(bdev, ARRAY_SIZE(attrs));
 free_registration:
-       video_unregister_device(bdev->videodev);
-       /* video_unregister_device frees bdev->videodev */
-       bdev->videodev = NULL;
+       video_unregister_device(&bdev->videodev);
        skip_release = 1;
 free_irq:
        if (client->irq)
                free_irq(client->irq, bdev);
-free_vdev:
-       if (!skip_release)
-               video_device_release(bdev->videodev);
-       i2c_set_clientdata(client, NULL);
 free_bdev:
+       i2c_set_clientdata(client, NULL);
        kfree(bdev);
 exit:
        return err;
@@ -2674,16 +2660,13 @@ exit:
 static int __exit bcm2048_i2c_driver_remove(struct i2c_client *client)
 {
        struct bcm2048_device *bdev = i2c_get_clientdata(client);
-       struct video_device *vd;
 
        if (!client->adapter)
                return -ENODEV;
 
        if (bdev) {
-               vd = bdev->videodev;
-
                bcm2048_sysfs_unregister_properties(bdev, ARRAY_SIZE(attrs));
-               video_unregister_device(vd);
+               video_unregister_device(&bdev->videodev);
 
                if (bdev->power_state)
                        bcm2048_set_power_state(bdev, BCM2048_POWER_OFF);
index a425f71dfb974f2b455c36e3e2e732dbcf5b9a95..1bbb90ce00867793dc49e8622f4e4c17c94da29d 100644 (file)
@@ -1414,17 +1414,17 @@ static int ipipe_set_stream(struct v4l2_subdev *sd, int enable)
  * __ipipe_get_format() - helper function for getting ipipe format
  * @ipipe: pointer to ipipe private structure.
  * @pad: pad number.
- * @fh: V4L2 subdev file handle.
+ * @cfg: V4L2 subdev pad config
  * @which: wanted subdev format.
  *
  */
 static struct v4l2_mbus_framefmt *
 __ipipe_get_format(struct vpfe_ipipe_device *ipipe,
-                      struct v4l2_subdev_fh *fh, unsigned int pad,
+                      struct v4l2_subdev_pad_config *cfg, unsigned int pad,
                       enum v4l2_subdev_format_whence which)
 {
        if (which == V4L2_SUBDEV_FORMAT_TRY)
-               return v4l2_subdev_get_try_format(fh, pad);
+               return v4l2_subdev_get_try_format(&ipipe->subdev, cfg, pad);
 
        return &ipipe->formats[pad];
 }
@@ -1432,14 +1432,14 @@ __ipipe_get_format(struct vpfe_ipipe_device *ipipe,
 /*
  * ipipe_try_format() - Handle try format by pad subdev method
  * @ipipe: VPFE ipipe device.
- * @fh: V4L2 subdev file handle.
+ * @cfg: V4L2 subdev pad config
  * @pad: pad num.
  * @fmt: pointer to v4l2 format structure.
  * @which : wanted subdev format
  */
 static void
 ipipe_try_format(struct vpfe_ipipe_device *ipipe,
-                  struct v4l2_subdev_fh *fh, unsigned int pad,
+                  struct v4l2_subdev_pad_config *cfg, unsigned int pad,
                   struct v4l2_mbus_framefmt *fmt,
                   enum v4l2_subdev_format_whence which)
 {
@@ -1475,22 +1475,22 @@ ipipe_try_format(struct vpfe_ipipe_device *ipipe,
 /*
  * ipipe_set_format() - Handle set format by pads subdev method
  * @sd: pointer to v4l2 subdev structure
- * @fh: V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad config
  * @fmt: pointer to v4l2 subdev format structure
  * return -EINVAL or zero on success
  */
 static int
-ipipe_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+ipipe_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                     struct v4l2_subdev_format *fmt)
 {
        struct vpfe_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
        struct v4l2_mbus_framefmt *format;
 
-       format = __ipipe_get_format(ipipe, fh, fmt->pad, fmt->which);
+       format = __ipipe_get_format(ipipe, cfg, fmt->pad, fmt->which);
        if (format == NULL)
                return -EINVAL;
 
-       ipipe_try_format(ipipe, fh, fmt->pad, &fmt->format, fmt->which);
+       ipipe_try_format(ipipe, cfg, fmt->pad, &fmt->format, fmt->which);
        *format = fmt->format;
 
        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
@@ -1512,11 +1512,11 @@ ipipe_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 /*
  * ipipe_get_format() - Handle get format by pads subdev method.
  * @sd: pointer to v4l2 subdev structure.
- * @fh: V4L2 subdev file handle.
+ * @cfg: V4L2 subdev pad config
  * @fmt: pointer to v4l2 subdev format structure.
  */
 static int
-ipipe_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+ipipe_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                     struct v4l2_subdev_format *fmt)
 {
        struct vpfe_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
@@ -1524,7 +1524,7 @@ ipipe_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
                fmt->format = ipipe->formats[fmt->pad];
        else
-               fmt->format = *(v4l2_subdev_get_try_format(fh, fmt->pad));
+               fmt->format = *(v4l2_subdev_get_try_format(sd, cfg, fmt->pad));
 
        return 0;
 }
@@ -1532,11 +1532,11 @@ ipipe_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 /*
  * ipipe_enum_frame_size() - enum frame sizes on pads
  * @sd: pointer to v4l2 subdev structure.
- * @fh: V4L2 subdev file handle.
+ * @cfg: V4L2 subdev pad config
  * @fse: pointer to v4l2_subdev_frame_size_enum structure.
  */
 static int
-ipipe_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+ipipe_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                          struct v4l2_subdev_frame_size_enum *fse)
 {
        struct vpfe_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
@@ -1548,8 +1548,7 @@ ipipe_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        format.code = fse->code;
        format.width = 1;
        format.height = 1;
-       ipipe_try_format(ipipe, fh, fse->pad, &format,
-                          V4L2_SUBDEV_FORMAT_TRY);
+       ipipe_try_format(ipipe, cfg, fse->pad, &format, fse->which);
        fse->min_width = format.width;
        fse->min_height = format.height;
 
@@ -1559,8 +1558,7 @@ ipipe_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        format.code = fse->code;
        format.width = -1;
        format.height = -1;
-       ipipe_try_format(ipipe, fh, fse->pad, &format,
-                          V4L2_SUBDEV_FORMAT_TRY);
+       ipipe_try_format(ipipe, cfg, fse->pad, &format, fse->which);
        fse->max_width = format.width;
        fse->max_height = format.height;
 
@@ -1570,11 +1568,11 @@ ipipe_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 /*
  * ipipe_enum_mbus_code() - enum mbus codes for pads
  * @sd: pointer to v4l2 subdev structure.
- * @fh: V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad config
  * @code: pointer to v4l2_subdev_mbus_code_enum structure
  */
 static int
-ipipe_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+ipipe_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                     struct v4l2_subdev_mbus_code_enum *code)
 {
        switch (code->pad) {
@@ -1630,9 +1628,8 @@ static int ipipe_s_ctrl(struct v4l2_ctrl *ctrl)
  * @sd: pointer to v4l2 subdev structure.
  * @fh: V4L2 subdev file handle
  *
- * Initialize all pad formats with default values. If fh is not NULL, try
- * formats are initialized on the file handle. Otherwise active formats are
- * initialized on the device.
+ * Initialize all pad formats with default values. Try formats are initialized
+ * on the file handle.
  */
 static int
 ipipe_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
@@ -1641,19 +1638,19 @@ ipipe_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 
        memset(&format, 0, sizeof(format));
        format.pad = IPIPE_PAD_SINK;
-       format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+       format.which = V4L2_SUBDEV_FORMAT_TRY;
        format.format.code = MEDIA_BUS_FMT_SGRBG12_1X12;
        format.format.width = IPIPE_MAX_OUTPUT_WIDTH_A;
        format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_A;
-       ipipe_set_format(sd, fh, &format);
+       ipipe_set_format(sd, fh->pad, &format);
 
        memset(&format, 0, sizeof(format));
        format.pad = IPIPE_PAD_SOURCE;
-       format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+       format.which = V4L2_SUBDEV_FORMAT_TRY;
        format.format.code = MEDIA_BUS_FMT_UYVY8_2X8;
        format.format.width = IPIPE_MAX_OUTPUT_WIDTH_A;
        format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_A;
-       ipipe_set_format(sd, fh, &format);
+       ipipe_set_format(sd, fh->pad, &format);
 
        return 0;
 }
index 17e105e7d892db8c02945f5db4c66926e0f0dbff..8b230541b1d16a5fb0d14c3c0bf614a7923f92c4 100644 (file)
@@ -544,12 +544,12 @@ static int ipipeif_set_stream(struct v4l2_subdev *sd, int enable)
 /*
  * ipipeif_enum_mbus_code() - Handle pixel format enumeration
  * @sd: pointer to v4l2 subdev structure
- * @fh: V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad config
  * @code: pointer to v4l2_subdev_mbus_code_enum structure
  * return -EINVAL or zero on success
  */
 static int ipipeif_enum_mbus_code(struct v4l2_subdev *sd,
-                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_pad_config *cfg,
                        struct v4l2_subdev_mbus_code_enum *code)
 {
        switch (code->pad) {
@@ -577,11 +577,11 @@ static int ipipeif_enum_mbus_code(struct v4l2_subdev *sd,
 /*
  * ipipeif_get_format() - Handle get format by pads subdev method
  * @sd: pointer to v4l2 subdev structure
- * @fh: V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad config
  * @fmt: pointer to v4l2 subdev format structure
  */
 static int
-ipipeif_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+ipipeif_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                struct v4l2_subdev_format *fmt)
 {
        struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
@@ -589,7 +589,7 @@ ipipeif_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
                fmt->format = ipipeif->formats[fmt->pad];
        else
-               fmt->format = *(v4l2_subdev_get_try_format(fh, fmt->pad));
+               fmt->format = *(v4l2_subdev_get_try_format(sd, cfg, fmt->pad));
 
        return 0;
 }
@@ -600,14 +600,14 @@ ipipeif_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 /*
  * ipipeif_try_format() - Handle try format by pad subdev method
  * @ipipeif: VPFE ipipeif device.
- * @fh: V4L2 subdev file handle.
+ * @cfg: V4L2 subdev pad config
  * @pad: pad num.
  * @fmt: pointer to v4l2 format structure.
  * @which : wanted subdev format
  */
 static void
 ipipeif_try_format(struct vpfe_ipipeif_device *ipipeif,
-                  struct v4l2_subdev_fh *fh, unsigned int pad,
+                  struct v4l2_subdev_pad_config *cfg, unsigned int pad,
                   struct v4l2_mbus_framefmt *fmt,
                   enum v4l2_subdev_format_whence which)
 {
@@ -641,7 +641,7 @@ ipipeif_try_format(struct vpfe_ipipeif_device *ipipeif,
 }
 
 static int
-ipipeif_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+ipipeif_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                     struct v4l2_subdev_frame_size_enum *fse)
 {
        struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
@@ -653,8 +653,7 @@ ipipeif_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        format.code = fse->code;
        format.width = 1;
        format.height = 1;
-       ipipeif_try_format(ipipeif, fh, fse->pad, &format,
-                          V4L2_SUBDEV_FORMAT_TRY);
+       ipipeif_try_format(ipipeif, cfg, fse->pad, &format, fse->which);
        fse->min_width = format.width;
        fse->min_height = format.height;
 
@@ -664,8 +663,7 @@ ipipeif_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        format.code = fse->code;
        format.width = -1;
        format.height = -1;
-       ipipeif_try_format(ipipeif, fh, fse->pad, &format,
-                          V4L2_SUBDEV_FORMAT_TRY);
+       ipipeif_try_format(ipipeif, cfg, fse->pad, &format, fse->which);
        fse->max_width = format.width;
        fse->max_height = format.height;
 
@@ -675,18 +673,18 @@ ipipeif_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 /*
  * __ipipeif_get_format() - helper function for getting ipipeif format
  * @ipipeif: pointer to ipipeif private structure.
+ * @cfg: V4L2 subdev pad config
  * @pad: pad number.
- * @fh: V4L2 subdev file handle.
  * @which: wanted subdev format.
  *
  */
 static struct v4l2_mbus_framefmt *
 __ipipeif_get_format(struct vpfe_ipipeif_device *ipipeif,
-                      struct v4l2_subdev_fh *fh, unsigned int pad,
+                      struct v4l2_subdev_pad_config *cfg, unsigned int pad,
                       enum v4l2_subdev_format_whence which)
 {
        if (which == V4L2_SUBDEV_FORMAT_TRY)
-               return v4l2_subdev_get_try_format(fh, pad);
+               return v4l2_subdev_get_try_format(&ipipeif->subdev, cfg, pad);
 
        return &ipipeif->formats[pad];
 }
@@ -694,22 +692,22 @@ __ipipeif_get_format(struct vpfe_ipipeif_device *ipipeif,
 /*
  * ipipeif_set_format() - Handle set format by pads subdev method
  * @sd: pointer to v4l2 subdev structure
- * @fh: V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad config
  * @fmt: pointer to v4l2 subdev format structure
  * return -EINVAL or zero on success
  */
 static int
-ipipeif_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+ipipeif_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                struct v4l2_subdev_format *fmt)
 {
        struct vpfe_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
        struct v4l2_mbus_framefmt *format;
 
-       format = __ipipeif_get_format(ipipeif, fh, fmt->pad, fmt->which);
+       format = __ipipeif_get_format(ipipeif, cfg, fmt->pad, fmt->which);
        if (format == NULL)
                return -EINVAL;
 
-       ipipeif_try_format(ipipeif, fh, fmt->pad, &fmt->format, fmt->which);
+       ipipeif_try_format(ipipeif, cfg, fmt->pad, &fmt->format, fmt->which);
        *format = fmt->format;
 
        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
@@ -756,9 +754,8 @@ static void ipipeif_set_default_config(struct vpfe_ipipeif_device *ipipeif)
  * @sd: VPFE ipipeif V4L2 subdevice
  * @fh: V4L2 subdev file handle
  *
- * Initialize all pad formats with default values. If fh is not NULL, try
- * formats are initialized on the file handle. Otherwise active formats are
- * initialized on the device.
+ * Initialize all pad formats with default values. Try formats are initialized
+ * on the file handle.
  */
 static int
 ipipeif_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
@@ -768,19 +765,19 @@ ipipeif_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 
        memset(&format, 0, sizeof(format));
        format.pad = IPIPEIF_PAD_SINK;
-       format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+       format.which = V4L2_SUBDEV_FORMAT_TRY;
        format.format.code = MEDIA_BUS_FMT_SGRBG12_1X12;
        format.format.width = IPIPE_MAX_OUTPUT_WIDTH_A;
        format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_A;
-       ipipeif_set_format(sd, fh, &format);
+       ipipeif_set_format(sd, fh->pad, &format);
 
        memset(&format, 0, sizeof(format));
        format.pad = IPIPEIF_PAD_SOURCE;
-       format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+       format.which = V4L2_SUBDEV_FORMAT_TRY;
        format.format.code = MEDIA_BUS_FMT_UYVY8_2X8;
        format.format.width = IPIPE_MAX_OUTPUT_WIDTH_A;
        format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_A;
-       ipipeif_set_format(sd, fh, &format);
+       ipipeif_set_format(sd, fh->pad, &format);
 
        ipipeif_set_default_config(ipipeif);
 
index bcf762bc233d3a813cd6613b9d9efdcfe0943514..80907b46441294989db1a4ae4659efd49c2266fa 100644 (file)
@@ -278,11 +278,11 @@ isif_config_format(struct vpfe_device *vpfe_dev, unsigned int pad)
 /*
  * isif_try_format() - Try video format on a pad
  * @isif: VPFE isif device
- * @fh: V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad config
  * @fmt: pointer to v4l2 subdev format structure
  */
 static void
-isif_try_format(struct vpfe_isif_device *isif, struct v4l2_subdev_fh *fh,
+isif_try_format(struct vpfe_isif_device *isif, struct v4l2_subdev_pad_config *cfg,
                struct v4l2_subdev_format *fmt)
 {
        unsigned int width = fmt->format.width;
@@ -1394,11 +1394,11 @@ static int isif_set_stream(struct v4l2_subdev *sd, int enable)
  * __isif_get_format() - helper function for getting isif format
  * @isif: pointer to isif private structure.
  * @pad: pad number.
- * @fh: V4L2 subdev file handle.
+ * @cfg: V4L2 subdev pad config
  * @which: wanted subdev format.
  */
 static struct v4l2_mbus_framefmt *
-__isif_get_format(struct vpfe_isif_device *isif, struct v4l2_subdev_fh *fh,
+__isif_get_format(struct vpfe_isif_device *isif, struct v4l2_subdev_pad_config *cfg,
                  unsigned int pad, enum v4l2_subdev_format_whence which)
 {
        if (which == V4L2_SUBDEV_FORMAT_TRY) {
@@ -1407,32 +1407,32 @@ __isif_get_format(struct vpfe_isif_device *isif, struct v4l2_subdev_fh *fh,
                fmt.pad = pad;
                fmt.which = which;
 
-               return v4l2_subdev_get_try_format(fh, pad);
+               return v4l2_subdev_get_try_format(&isif->subdev, cfg, pad);
        }
        return &isif->formats[pad];
 }
 
 /*
-* isif_set_format() - set format on pad
-* @sd    : VPFE ISIF device
-* @fh    : V4L2 subdev file handle
-* @fmt   : pointer to v4l2 subdev format structure
-*
-* Return 0 on success or -EINVAL if format or pad is invalid
-*/
+ * isif_set_format() - set format on pad
+ * @sd    : VPFE ISIF device
+ * @cfg   : V4L2 subdev pad config
+ * @fmt   : pointer to v4l2 subdev format structure
+ *
+ * Return 0 on success or -EINVAL if format or pad is invalid
+ */
 static int
-isif_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+isif_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                struct v4l2_subdev_format *fmt)
 {
        struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd);
        struct vpfe_device *vpfe_dev = to_vpfe_device(isif);
        struct v4l2_mbus_framefmt *format;
 
-       format = __isif_get_format(isif, fh, fmt->pad, fmt->which);
+       format = __isif_get_format(isif, cfg, fmt->pad, fmt->which);
        if (format == NULL)
                return -EINVAL;
 
-       isif_try_format(isif, fh, fmt);
+       isif_try_format(isif, cfg, fmt);
        memcpy(format, &fmt->format, sizeof(*format));
 
        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
@@ -1447,20 +1447,20 @@ isif_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 /*
  * isif_get_format() - Retrieve the video format on a pad
  * @sd: VPFE ISIF V4L2 subdevice
- * @fh: V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad config
  * @fmt: pointer to v4l2 subdev format structure
  *
  * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
  * to the format type.
  */
 static int
-isif_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+isif_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                struct v4l2_subdev_format *fmt)
 {
        struct vpfe_isif_device *vpfe_isif = v4l2_get_subdevdata(sd);
        struct v4l2_mbus_framefmt *format;
 
-       format = __isif_get_format(vpfe_isif, fh, fmt->pad, fmt->which);
+       format = __isif_get_format(vpfe_isif, cfg, fmt->pad, fmt->which);
        if (format == NULL)
                return -EINVAL;
 
@@ -1472,11 +1472,11 @@ isif_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 /*
  * isif_enum_frame_size() - enum frame sizes on pads
  * @sd: VPFE isif V4L2 subdevice
- * @fh: V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad config
  * @code: pointer to v4l2_subdev_frame_size_enum structure
  */
 static int
-isif_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+isif_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                     struct v4l2_subdev_frame_size_enum *fse)
 {
        struct vpfe_isif_device *isif = v4l2_get_subdevdata(sd);
@@ -1489,8 +1489,8 @@ isif_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        format.format.code = fse->code;
        format.format.width = 1;
        format.format.height = 1;
-       format.which = V4L2_SUBDEV_FORMAT_TRY;
-       isif_try_format(isif, fh, &format);
+       format.which = fse->which;
+       isif_try_format(isif, cfg, &format);
        fse->min_width = format.format.width;
        fse->min_height = format.format.height;
 
@@ -1501,8 +1501,8 @@ isif_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        format.format.code = fse->code;
        format.format.width = -1;
        format.format.height = -1;
-       format.which = V4L2_SUBDEV_FORMAT_TRY;
-       isif_try_format(isif, fh, &format);
+       format.which = fse->which;
+       isif_try_format(isif, cfg, &format);
        fse->max_width = format.format.width;
        fse->max_height = format.format.height;
 
@@ -1512,11 +1512,11 @@ isif_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 /*
  * isif_enum_mbus_code() - enum mbus codes for pads
  * @sd: VPFE isif V4L2 subdevice
- * @fh: V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad config
  * @code: pointer to v4l2_subdev_mbus_code_enum structure
  */
 static int
-isif_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+isif_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                    struct v4l2_subdev_mbus_code_enum *code)
 {
        switch (code->pad) {
@@ -1537,14 +1537,14 @@ isif_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 /*
  * isif_pad_set_selection() - set crop rectangle on pad
  * @sd: VPFE isif V4L2 subdevice
- * @fh: V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad config
  * @code: pointer to v4l2_subdev_mbus_code_enum structure
  *
  * Return 0 on success, -EINVAL if pad is invalid
  */
 static int
 isif_pad_set_selection(struct v4l2_subdev *sd,
-                      struct v4l2_subdev_fh *fh,
+                      struct v4l2_subdev_pad_config *cfg,
                       struct v4l2_subdev_selection *sel)
 {
        struct vpfe_isif_device *vpfe_isif = v4l2_get_subdevdata(sd);
@@ -1554,7 +1554,7 @@ isif_pad_set_selection(struct v4l2_subdev *sd,
        if (sel->pad != ISIF_PAD_SINK || sel->target != V4L2_SEL_TGT_CROP)
                return -EINVAL;
 
-       format = __isif_get_format(vpfe_isif, fh, sel->pad, sel->which);
+       format = __isif_get_format(vpfe_isif, cfg, sel->pad, sel->which);
        if (format == NULL)
                return -EINVAL;
 
@@ -1577,7 +1577,7 @@ isif_pad_set_selection(struct v4l2_subdev *sd,
        } else {
                struct v4l2_rect *rect;
 
-               rect = v4l2_subdev_get_try_crop(fh, ISIF_PAD_SINK);
+               rect = v4l2_subdev_get_try_crop(sd, cfg, ISIF_PAD_SINK);
                memcpy(rect, &vpfe_isif->crop, sizeof(*rect));
        }
        return 0;
@@ -1586,14 +1586,14 @@ isif_pad_set_selection(struct v4l2_subdev *sd,
 /*
  * isif_pad_get_selection() - get crop rectangle on pad
  * @sd: VPFE isif V4L2 subdevice
- * @fh: V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad config
  * @code: pointer to v4l2_subdev_mbus_code_enum structure
  *
  * Return 0 on success, -EINVAL if pad is invalid
  */
 static int
 isif_pad_get_selection(struct v4l2_subdev *sd,
-                      struct v4l2_subdev_fh *fh,
+                      struct v4l2_subdev_pad_config *cfg,
                       struct v4l2_subdev_selection *sel)
 {
        struct vpfe_isif_device *vpfe_isif = v4l2_get_subdevdata(sd);
@@ -1605,7 +1605,7 @@ isif_pad_get_selection(struct v4l2_subdev *sd,
        if (sel->which == V4L2_SUBDEV_FORMAT_TRY) {
                struct v4l2_rect *rect;
 
-               rect = v4l2_subdev_get_try_crop(fh, ISIF_PAD_SINK);
+               rect = v4l2_subdev_get_try_crop(sd, cfg, ISIF_PAD_SINK);
                memcpy(&sel->r, rect, sizeof(*rect));
        } else {
                sel->r = vpfe_isif->crop;
@@ -1619,9 +1619,8 @@ isif_pad_get_selection(struct v4l2_subdev *sd,
  * @sd: VPFE isif V4L2 subdevice
  * @fh: V4L2 subdev file handle
  *
- * Initialize all pad formats with default values. If fh is not NULL, try
- * formats are initialized on the file handle. Otherwise active formats are
- * initialized on the device.
+ * Initialize all pad formats with default values. Try formats are initialized
+ * on the file handle.
  */
 static int
 isif_init_formats(struct v4l2_subdev *sd,
@@ -1632,27 +1631,27 @@ isif_init_formats(struct v4l2_subdev *sd,
 
        memset(&format, 0, sizeof(format));
        format.pad = ISIF_PAD_SINK;
-       format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+       format.which = V4L2_SUBDEV_FORMAT_TRY;
        format.format.code = MEDIA_BUS_FMT_SGRBG12_1X12;
        format.format.width = MAX_WIDTH;
        format.format.height = MAX_HEIGHT;
-       isif_set_format(sd, fh, &format);
+       isif_set_format(sd, fh->pad, &format);
 
        memset(&format, 0, sizeof(format));
        format.pad = ISIF_PAD_SOURCE;
-       format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+       format.which = V4L2_SUBDEV_FORMAT_TRY;
        format.format.code = MEDIA_BUS_FMT_SGRBG12_1X12;
        format.format.width = MAX_WIDTH;
        format.format.height = MAX_HEIGHT;
-       isif_set_format(sd, fh, &format);
+       isif_set_format(sd, fh->pad, &format);
 
        memset(&sel, 0, sizeof(sel));
        sel.pad = ISIF_PAD_SINK;
-       sel.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+       sel.which = V4L2_SUBDEV_FORMAT_TRY;
        sel.target = V4L2_SEL_TGT_CROP;
        sel.r.width = MAX_WIDTH;
        sel.r.height = MAX_HEIGHT;
-       isif_pad_set_selection(sd, fh, &sel);
+       isif_pad_set_selection(sd, fh->pad, &sel);
 
        return 0;
 }
index 7cc8d1b4d737c4d03718862a0145568ec0a1a842..b6498137de56b5ad5dd4477197880df6961490ff 100644 (file)
@@ -1288,19 +1288,19 @@ static int resizer_set_stream(struct v4l2_subdev *sd, int enable)
 /*
  * __resizer_get_format() - helper function for getting resizer format
  * @sd: pointer to subdev.
- * @fh: V4L2 subdev file handle.
+ * @cfg: V4L2 subdev pad config
  * @pad: pad number.
  * @which: wanted subdev format.
  * Retun wanted mbus frame format.
  */
 static struct v4l2_mbus_framefmt *
-__resizer_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+__resizer_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                     unsigned int pad, enum v4l2_subdev_format_whence which)
 {
        struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd);
 
        if (which == V4L2_SUBDEV_FORMAT_TRY)
-               return v4l2_subdev_get_try_format(fh, pad);
+               return v4l2_subdev_get_try_format(sd, cfg, pad);
        if (&resizer->crop_resizer.subdev == sd)
                return &resizer->crop_resizer.formats[pad];
        if (&resizer->resizer_a.subdev == sd)
@@ -1313,13 +1313,13 @@ __resizer_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 /*
  * resizer_try_format() - Handle try format by pad subdev method
  * @sd: pointer to subdev.
- * @fh: V4L2 subdev file handle.
+ * @cfg: V4L2 subdev pad config
  * @pad: pad num.
  * @fmt: pointer to v4l2 format structure.
  * @which: wanted subdev format.
  */
 static void
-resizer_try_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+resizer_try_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
        unsigned int pad, struct v4l2_mbus_framefmt *fmt,
        enum v4l2_subdev_format_whence which)
 {
@@ -1387,21 +1387,21 @@ resizer_try_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 /*
  * resizer_set_format() - Handle set format by pads subdev method
  * @sd: pointer to v4l2 subdev structure
- * @fh: V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad config
  * @fmt: pointer to v4l2 subdev format structure
  * return -EINVAL or zero on success
  */
-static int resizer_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int resizer_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                           struct v4l2_subdev_format *fmt)
 {
        struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd);
        struct v4l2_mbus_framefmt *format;
 
-       format = __resizer_get_format(sd, fh, fmt->pad, fmt->which);
+       format = __resizer_get_format(sd, cfg, fmt->pad, fmt->which);
        if (format == NULL)
                return -EINVAL;
 
-       resizer_try_format(sd, fh, fmt->pad, &fmt->format, fmt->which);
+       resizer_try_format(sd, cfg, fmt->pad, &fmt->format, fmt->which);
        *format = fmt->format;
 
        if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
@@ -1447,16 +1447,16 @@ static int resizer_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 /*
  * resizer_get_format() - Retrieve the video format on a pad
  * @sd: pointer to v4l2 subdev structure.
- * @fh: V4L2 subdev file handle.
+ * @cfg: V4L2 subdev pad config
  * @fmt: pointer to v4l2 subdev format structure
  * return -EINVAL or zero on success
  */
-static int resizer_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int resizer_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                           struct v4l2_subdev_format *fmt)
 {
        struct v4l2_mbus_framefmt *format;
 
-       format = __resizer_get_format(sd, fh, fmt->pad, fmt->which);
+       format = __resizer_get_format(sd, cfg, fmt->pad, fmt->which);
        if (format == NULL)
                return -EINVAL;
 
@@ -1468,11 +1468,11 @@ static int resizer_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 /*
  * resizer_enum_frame_size() - enum frame sizes on pads
  * @sd: Pointer to subdevice.
- * @fh: V4L2 subdev file handle.
+ * @cfg: V4L2 subdev pad config
  * @code: pointer to v4l2_subdev_frame_size_enum structure.
  */
 static int resizer_enum_frame_size(struct v4l2_subdev *sd,
-                                  struct v4l2_subdev_fh *fh,
+                                  struct v4l2_subdev_pad_config *cfg,
                                   struct v4l2_subdev_frame_size_enum *fse)
 {
        struct v4l2_mbus_framefmt format;
@@ -1483,8 +1483,7 @@ static int resizer_enum_frame_size(struct v4l2_subdev *sd,
        format.code = fse->code;
        format.width = 1;
        format.height = 1;
-       resizer_try_format(sd, fh, fse->pad, &format,
-                           V4L2_SUBDEV_FORMAT_TRY);
+       resizer_try_format(sd, cfg, fse->pad, &format, fse->which);
        fse->min_width = format.width;
        fse->min_height = format.height;
 
@@ -1494,8 +1493,7 @@ static int resizer_enum_frame_size(struct v4l2_subdev *sd,
        format.code = fse->code;
        format.width = -1;
        format.height = -1;
-       resizer_try_format(sd, fh, fse->pad, &format,
-                          V4L2_SUBDEV_FORMAT_TRY);
+       resizer_try_format(sd, cfg, fse->pad, &format, fse->which);
        fse->max_width = format.width;
        fse->max_height = format.height;
 
@@ -1505,11 +1503,11 @@ static int resizer_enum_frame_size(struct v4l2_subdev *sd,
 /*
  * resizer_enum_mbus_code() - enum mbus codes for pads
  * @sd: Pointer to subdevice.
- * @fh: V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad config
  * @code: pointer to v4l2_subdev_mbus_code_enum structure
  */
 static int resizer_enum_mbus_code(struct v4l2_subdev *sd,
-                                 struct v4l2_subdev_fh *fh,
+                                 struct v4l2_subdev_pad_config *cfg,
                                  struct v4l2_subdev_mbus_code_enum *code)
 {
        if (code->pad == RESIZER_PAD_SINK) {
@@ -1532,14 +1530,13 @@ static int resizer_enum_mbus_code(struct v4l2_subdev *sd,
  * @sd: Pointer to subdevice.
  * @fh: V4L2 subdev file handle.
  *
- * Initialize all pad formats with default values. If fh is not NULL, try
- * formats are initialized on the file handle. Otherwise active formats are
- * initialized on the device.
+ * Initialize all pad formats with default values. Try formats are
+ * initialized on the file handle.
  */
 static int resizer_init_formats(struct v4l2_subdev *sd,
                                struct v4l2_subdev_fh *fh)
 {
-       __u32 which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+       __u32 which = V4L2_SUBDEV_FORMAT_TRY;
        struct vpfe_resizer_device *resizer = v4l2_get_subdevdata(sd);
        struct v4l2_subdev_format format;
 
@@ -1550,7 +1547,7 @@ static int resizer_init_formats(struct v4l2_subdev *sd,
                format.format.code = MEDIA_BUS_FMT_YUYV8_2X8;
                format.format.width = MAX_IN_WIDTH;
                format.format.height = MAX_IN_HEIGHT;
-               resizer_set_format(sd, fh, &format);
+               resizer_set_format(sd, fh->pad, &format);
 
                memset(&format, 0, sizeof(format));
                format.pad = RESIZER_CROP_PAD_SOURCE;
@@ -1558,7 +1555,7 @@ static int resizer_init_formats(struct v4l2_subdev *sd,
                format.format.code = MEDIA_BUS_FMT_UYVY8_2X8;
                format.format.width = MAX_IN_WIDTH;
                format.format.height = MAX_IN_WIDTH;
-               resizer_set_format(sd, fh, &format);
+               resizer_set_format(sd, fh->pad, &format);
 
                memset(&format, 0, sizeof(format));
                format.pad = RESIZER_CROP_PAD_SOURCE2;
@@ -1566,7 +1563,7 @@ static int resizer_init_formats(struct v4l2_subdev *sd,
                format.format.code = MEDIA_BUS_FMT_UYVY8_2X8;
                format.format.width = MAX_IN_WIDTH;
                format.format.height = MAX_IN_WIDTH;
-               resizer_set_format(sd, fh, &format);
+               resizer_set_format(sd, fh->pad, &format);
        } else if (&resizer->resizer_a.subdev == sd) {
                memset(&format, 0, sizeof(format));
                format.pad = RESIZER_PAD_SINK;
@@ -1574,7 +1571,7 @@ static int resizer_init_formats(struct v4l2_subdev *sd,
                format.format.code = MEDIA_BUS_FMT_YUYV8_2X8;
                format.format.width = MAX_IN_WIDTH;
                format.format.height = MAX_IN_HEIGHT;
-               resizer_set_format(sd, fh, &format);
+               resizer_set_format(sd, fh->pad, &format);
 
                memset(&format, 0, sizeof(format));
                format.pad = RESIZER_PAD_SOURCE;
@@ -1582,7 +1579,7 @@ static int resizer_init_formats(struct v4l2_subdev *sd,
                format.format.code = MEDIA_BUS_FMT_UYVY8_2X8;
                format.format.width = IPIPE_MAX_OUTPUT_WIDTH_A;
                format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_A;
-               resizer_set_format(sd, fh, &format);
+               resizer_set_format(sd, fh->pad, &format);
        } else if (&resizer->resizer_b.subdev == sd) {
                memset(&format, 0, sizeof(format));
                format.pad = RESIZER_PAD_SINK;
@@ -1590,7 +1587,7 @@ static int resizer_init_formats(struct v4l2_subdev *sd,
                format.format.code = MEDIA_BUS_FMT_YUYV8_2X8;
                format.format.width = MAX_IN_WIDTH;
                format.format.height = MAX_IN_HEIGHT;
-               resizer_set_format(sd, fh, &format);
+               resizer_set_format(sd, fh->pad, &format);
 
                memset(&format, 0, sizeof(format));
                format.pad = RESIZER_PAD_SOURCE;
@@ -1598,7 +1595,7 @@ static int resizer_init_formats(struct v4l2_subdev *sd,
                format.format.code = MEDIA_BUS_FMT_UYVY8_2X8;
                format.format.width = IPIPE_MAX_OUTPUT_WIDTH_B;
                format.format.height = IPIPE_MAX_OUTPUT_HEIGHT_B;
-               resizer_set_format(sd, fh, &format);
+               resizer_set_format(sd, fh->pad, &format);
        }
 
        return 0;
index 293ffda503e06be82bf4bf6697f29e238fef86ed..52a8ffe560b1bda6311e259df9263e56ec3cdea7 100644 (file)
@@ -244,7 +244,7 @@ dt3155_wait_prepare(struct vb2_queue *q)
 {
        struct dt3155_priv *pd = vb2_get_drv_priv(q);
 
-       mutex_unlock(pd->vdev->lock);
+       mutex_unlock(pd->vdev.lock);
 }
 
 static void
@@ -252,7 +252,7 @@ dt3155_wait_finish(struct vb2_queue *q)
 {
        struct dt3155_priv *pd = vb2_get_drv_priv(q);
 
-       mutex_lock(pd->vdev->lock);
+       mutex_lock(pd->vdev.lock);
 }
 
 static int
@@ -824,7 +824,7 @@ static struct video_device dt3155_vdev = {
        .fops = &dt3155_fops,
        .ioctl_ops = &dt3155_ioctl_ops,
        .minor = -1,
-       .release = video_device_release,
+       .release = video_device_release_empty,
        .tvnorms = DT3155_CURRENT_NORM,
 };
 
@@ -901,28 +901,24 @@ dt3155_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
        if (err)
                return -ENODEV;
-       pd = kzalloc(sizeof(*pd), GFP_KERNEL);
+       pd = devm_kzalloc(&pdev->dev, sizeof(*pd), GFP_KERNEL);
        if (!pd)
                return -ENOMEM;
-       pd->vdev = video_device_alloc();
-       if (!pd->vdev) {
-               err = -ENOMEM;
-               goto err_video_device_alloc;
-       }
-       *pd->vdev = dt3155_vdev;
+
+       pd->vdev = dt3155_vdev;
        pci_set_drvdata(pdev, pd);    /* for use in dt3155_remove() */
-       video_set_drvdata(pd->vdev, pd);  /* for use in video_fops */
+       video_set_drvdata(&pd->vdev, pd);  /* for use in video_fops */
        pd->users = 0;
        pd->pdev = pdev;
        INIT_LIST_HEAD(&pd->dmaq);
        mutex_init(&pd->mux);
-       pd->vdev->lock = &pd->mux; /* for locking v4l2_file_operations */
+       pd->vdev.lock = &pd->mux; /* for locking v4l2_file_operations */
        spin_lock_init(&pd->lock);
        pd->csr2 = csr2_init;
        pd->config = config_init;
        err = pci_enable_device(pdev);
        if (err)
-               goto err_enable_dev;
+               return err;
        err = pci_request_region(pdev, 0, pci_name(pdev));
        if (err)
                goto err_req_region;
@@ -934,13 +930,13 @@ dt3155_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        err = dt3155_init_board(pdev);
        if (err)
                goto err_init_board;
-       err = video_register_device(pd->vdev, VFL_TYPE_GRABBER, -1);
+       err = video_register_device(&pd->vdev, VFL_TYPE_GRABBER, -1);
        if (err)
                goto err_init_board;
        if (dt3155_alloc_coherent(&pdev->dev, DT3155_CHUNK_SIZE,
                                                        DMA_MEMORY_MAP))
                dev_info(&pdev->dev, "preallocated 8 buffers\n");
-       dev_info(&pdev->dev, "/dev/video%i is ready\n", pd->vdev->minor);
+       dev_info(&pdev->dev, "/dev/video%i is ready\n", pd->vdev.minor);
        return 0;  /*   success   */
 
 err_init_board:
@@ -949,10 +945,6 @@ err_pci_iomap:
        pci_release_region(pdev, 0);
 err_req_region:
        pci_disable_device(pdev);
-err_enable_dev:
-       video_device_release(pd->vdev);
-err_video_device_alloc:
-       kfree(pd);
        return err;
 }
 
@@ -962,15 +954,10 @@ dt3155_remove(struct pci_dev *pdev)
        struct dt3155_priv *pd = pci_get_drvdata(pdev);
 
        dt3155_free_coherent(&pdev->dev);
-       video_unregister_device(pd->vdev);
+       video_unregister_device(&pd->vdev);
        pci_iounmap(pdev, pd->regs);
        pci_release_region(pdev, 0);
        pci_disable_device(pdev);
-       /*
-        * video_device_release() is invoked automatically
-        * see: struct video_device dt3155_vdev
-        */
-       kfree(pd);
 }
 
 static const struct pci_device_id pci_ids[] = {
index 2e4f89d402e4f93986fca3a3ab27cd442bab7567..96f01a0c75810cfd48e0fff9e5d539d49ddb2e47 100644 (file)
@@ -178,7 +178,7 @@ struct dt3155_stats {
 /**
  * struct dt3155_priv - private data structure
  *
- * @vdev:              pointer to video_device structure
+ * @vdev:              video_device structure
  * @pdev:              pointer to pci_dev structure
  * @q                  pointer to vb2_queue structure
  * @curr_buf:          pointer to curren buffer
@@ -193,7 +193,7 @@ struct dt3155_stats {
  * @config:            local copy of config register
  */
 struct dt3155_priv {
-       struct video_device *vdev;
+       struct video_device vdev;
        struct pci_dev *pdev;
        struct vb2_queue *q;
        struct vb2_buffer *curr_buf;
index 2a68582e7f71abc9d5c658147e1add98925d1384..a4cfcf57c99c0d37d6fcd7b100f4b1f25d8d5ec2 100644 (file)
@@ -19,7 +19,7 @@
 static int mn88472_get_tune_settings(struct dvb_frontend *fe,
        struct dvb_frontend_tune_settings *s)
 {
-       s->min_delay_ms = 400;
+       s->min_delay_ms = 800;
        return 0;
 }
 
@@ -178,8 +178,32 @@ static int mn88472_set_frontend(struct dvb_frontend *fe)
 
        ret = regmap_write(dev->regmap[0], 0x46, 0x00);
        ret = regmap_write(dev->regmap[0], 0xae, 0x00);
-       ret = regmap_write(dev->regmap[2], 0x08, 0x1d);
-       ret = regmap_write(dev->regmap[0], 0xd9, 0xe3);
+
+       switch (dev->ts_mode) {
+       case SERIAL_TS_MODE:
+               ret = regmap_write(dev->regmap[2], 0x08, 0x1d);
+               break;
+       case PARALLEL_TS_MODE:
+               ret = regmap_write(dev->regmap[2], 0x08, 0x00);
+               break;
+       default:
+               dev_dbg(&client->dev, "ts_mode error: %d\n", dev->ts_mode);
+               ret = -EINVAL;
+               goto err;
+       }
+
+       switch (dev->ts_clock) {
+       case VARIABLE_TS_CLOCK:
+               ret = regmap_write(dev->regmap[0], 0xd9, 0xe3);
+               break;
+       case FIXED_TS_CLOCK:
+               ret = regmap_write(dev->regmap[0], 0xd9, 0xe1);
+               break;
+       default:
+               dev_dbg(&client->dev, "ts_clock error: %d\n", dev->ts_clock);
+               ret = -EINVAL;
+               goto err;
+       }
 
        /* Reset demod */
        ret = regmap_write(dev->regmap[2], 0xf8, 0x9f);
@@ -201,6 +225,7 @@ static int mn88472_read_status(struct dvb_frontend *fe, fe_status_t *status)
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        int ret;
        unsigned int utmp;
+       int lock = 0;
 
        *status = 0;
 
@@ -211,21 +236,36 @@ static int mn88472_read_status(struct dvb_frontend *fe, fe_status_t *status)
 
        switch (c->delivery_system) {
        case SYS_DVBT:
+               ret = regmap_read(dev->regmap[0], 0x7F, &utmp);
+               if (ret)
+                       goto err;
+               if ((utmp & 0xF) >= 0x09)
+                       lock = 1;
+               break;
        case SYS_DVBT2:
-               /* FIXME: implement me */
-               utmp = 0x08; /* DVB-C lock value */
+               ret = regmap_read(dev->regmap[2], 0x92, &utmp);
+               if (ret)
+                       goto err;
+               if ((utmp & 0xF) >= 0x07)
+                       *status |= FE_HAS_SIGNAL;
+               if ((utmp & 0xF) >= 0x0a)
+                       *status |= FE_HAS_CARRIER;
+               if ((utmp & 0xF) >= 0x0d)
+                       *status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
                break;
        case SYS_DVBC_ANNEX_A:
                ret = regmap_read(dev->regmap[1], 0x84, &utmp);
                if (ret)
                        goto err;
+               if ((utmp & 0xF) >= 0x08)
+                       lock = 1;
                break;
        default:
                ret = -EINVAL;
                goto err;
        }
 
-       if (utmp == 0x08)
+       if (lock)
                *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
                                FE_HAS_SYNC | FE_HAS_LOCK;
 
@@ -242,6 +282,7 @@ static int mn88472_init(struct dvb_frontend *fe)
        int ret, len, remaining;
        const struct firmware *fw = NULL;
        u8 *fw_file = MN88472_FIRMWARE;
+       unsigned int tmp;
 
        dev_dbg(&client->dev, "\n");
 
@@ -257,6 +298,17 @@ static int mn88472_init(struct dvb_frontend *fe)
        if (ret)
                goto err;
 
+       /* check if firmware is already running */
+       ret = regmap_read(dev->regmap[0], 0xf5, &tmp);
+       if (ret)
+               goto err;
+
+       if (!(tmp & 0x1)) {
+               dev_info(&client->dev, "firmware already running\n");
+               dev->warm = true;
+               return 0;
+       }
+
        /* request the firmware, this will block and timeout */
        ret = request_firmware(&fw, fw_file, &client->dev);
        if (ret) {
@@ -270,7 +322,7 @@ static int mn88472_init(struct dvb_frontend *fe)
 
        ret = regmap_write(dev->regmap[0], 0xf5, 0x03);
        if (ret)
-               goto err;
+               goto firmware_release;
 
        for (remaining = fw->size; remaining > 0;
                        remaining -= (dev->i2c_wr_max - 1)) {
@@ -283,13 +335,27 @@ static int mn88472_init(struct dvb_frontend *fe)
                if (ret) {
                        dev_err(&client->dev,
                                        "firmware download failed=%d\n", ret);
-                       goto err;
+                       goto firmware_release;
                }
        }
 
+       /* parity check of firmware */
+       ret = regmap_read(dev->regmap[0], 0xf8, &tmp);
+       if (ret) {
+               dev_err(&client->dev,
+                               "parity reg read failed=%d\n", ret);
+               goto err;
+       }
+       if (tmp & 0x10) {
+               dev_err(&client->dev,
+                               "firmware parity check failed=0x%x\n", tmp);
+               goto err;
+       }
+       dev_err(&client->dev, "firmware parity check succeeded=0x%x\n", tmp);
+
        ret = regmap_write(dev->regmap[0], 0xf5, 0x00);
        if (ret)
-               goto err;
+               goto firmware_release;
 
        release_firmware(fw);
        fw = NULL;
@@ -298,10 +364,9 @@ static int mn88472_init(struct dvb_frontend *fe)
        dev->warm = true;
 
        return 0;
+firmware_release:
+       release_firmware(fw);
 err:
-       if (fw)
-               release_firmware(fw);
-
        dev_dbg(&client->dev, "failed=%d\n", ret);
        return ret;
 }
@@ -336,6 +401,8 @@ static struct dvb_frontend_ops mn88472_ops = {
        .delsys = {SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A},
        .info = {
                .name = "Panasonic MN88472",
+               .symbol_rate_min = 1000000,
+               .symbol_rate_max = 7200000,
                .caps = FE_CAN_FEC_1_2                 |
                        FE_CAN_FEC_2_3                 |
                        FE_CAN_FEC_3_4                 |
@@ -396,6 +463,8 @@ static int mn88472_probe(struct i2c_client *client,
 
        dev->i2c_wr_max = config->i2c_wr_max;
        dev->xtal = config->xtal;
+       dev->ts_mode = config->ts_mode;
+       dev->ts_clock = config->ts_clock;
        dev->client[0] = client;
        dev->regmap[0] = regmap_init_i2c(dev->client[0], &regmap_config);
        if (IS_ERR(dev->regmap[0])) {
index b12b731e2d4e0f3a2b4d80798ba9f45dbd38193d..9ba8c8b3823e7bac9161fe0fc444aaf0647ea643 100644 (file)
@@ -32,6 +32,8 @@ struct mn88472_dev {
        fe_delivery_system_t delivery_system;
        bool warm; /* FW running */
        u32 xtal;
+       int ts_mode;
+       int ts_clock;
 };
 
 #endif
index 5baeb03ab3d12d220db8f97b23d72e29b0575b3b..8b6736c700579643f32e4c7b26cfe6be85770612 100644 (file)
@@ -30,6 +30,7 @@ static int mn88473_set_frontend(struct dvb_frontend *fe)
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        int ret, i;
        u32 if_frequency;
+       u64 tmp;
        u8 delivery_system_val, if_val[3], bw_val[7];
 
        dev_dbg(&client->dev,
@@ -62,32 +63,13 @@ static int mn88473_set_frontend(struct dvb_frontend *fe)
                goto err;
        }
 
-       switch (c->delivery_system) {
-       case SYS_DVBT:
-       case SYS_DVBT2:
-               if (c->bandwidth_hz <= 6000000) {
-                       /* IF 3570000 Hz, BW 6000000 Hz */
-                       memcpy(if_val, "\x24\x8e\x8a", 3);
-                       memcpy(bw_val, "\xe9\x55\x55\x1c\x29\x1c\x29", 7);
-               } else if (c->bandwidth_hz <= 7000000) {
-                       /* IF 4570000 Hz, BW 7000000 Hz */
-                       memcpy(if_val, "\x2e\xcb\xfb", 3);
-                       memcpy(bw_val, "\xc8\x00\x00\x17\x0a\x17\x0a", 7);
-               } else if (c->bandwidth_hz <= 8000000) {
-                       /* IF 4570000 Hz, BW 8000000 Hz */
-                       memcpy(if_val, "\x2e\xcb\xfb", 3);
-                       memcpy(bw_val, "\xaf\x00\x00\x11\xec\x11\xec", 7);
-               } else {
-                       ret = -EINVAL;
-                       goto err;
-               }
-               break;
-       case SYS_DVBC_ANNEX_A:
-               /* IF 5070000 Hz, BW 8000000 Hz */
-               memcpy(if_val, "\x33\xea\xb3", 3);
+       if (c->bandwidth_hz <= 6000000) {
+               memcpy(bw_val, "\xe9\x55\x55\x1c\x29\x1c\x29", 7);
+       } else if (c->bandwidth_hz <= 7000000) {
+               memcpy(bw_val, "\xc8\x00\x00\x17\x0a\x17\x0a", 7);
+       } else if (c->bandwidth_hz <= 8000000) {
                memcpy(bw_val, "\xaf\x00\x00\x11\xec\x11\xec", 7);
-               break;
-       default:
+       } else {
                ret = -EINVAL;
                goto err;
        }
@@ -109,17 +91,12 @@ static int mn88473_set_frontend(struct dvb_frontend *fe)
                if_frequency = 0;
        }
 
-       switch (if_frequency) {
-       case 3570000:
-       case 4570000:
-       case 5070000:
-               break;
-       default:
-               dev_err(&client->dev, "IF frequency %d not supported\n",
-                       if_frequency);
-               ret = -EINVAL;
-               goto err;
-       }
+       /* Calculate IF registers ( (1<<24)*IF / Xtal ) */
+       tmp =  div_u64(if_frequency * (u64)(1<<24) + (dev->xtal / 2),
+                                  dev->xtal);
+       if_val[0] = ((tmp >> 16) & 0xff);
+       if_val[1] = ((tmp >>  8) & 0xff);
+       if_val[2] = ((tmp >>  0) & 0xff);
 
        ret = regmap_write(dev->regmap[2], 0x05, 0x00);
        ret = regmap_write(dev->regmap[2], 0xfb, 0x13);
@@ -194,7 +171,10 @@ static int mn88473_read_status(struct dvb_frontend *fe, fe_status_t *status)
 {
        struct i2c_client *client = fe->demodulator_priv;
        struct mn88473_dev *dev = i2c_get_clientdata(client);
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        int ret;
+       unsigned int utmp;
+       int lock = 0;
 
        *status = 0;
 
@@ -203,8 +183,51 @@ static int mn88473_read_status(struct dvb_frontend *fe, fe_status_t *status)
                goto err;
        }
 
-       *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
-                       FE_HAS_SYNC | FE_HAS_LOCK;
+       switch (c->delivery_system) {
+       case SYS_DVBT:
+               ret = regmap_read(dev->regmap[0], 0x62, &utmp);
+               if (ret)
+                       goto err;
+               if (!(utmp & 0xA0)) {
+                       if ((utmp & 0xF) >= 0x03)
+                               *status |= FE_HAS_SIGNAL;
+                       if ((utmp & 0xF) >= 0x09)
+                               lock = 1;
+               }
+               break;
+       case SYS_DVBT2:
+               ret = regmap_read(dev->regmap[2], 0x8B, &utmp);
+               if (ret)
+                       goto err;
+               if (!(utmp & 0x40)) {
+                       if ((utmp & 0xF) >= 0x07)
+                               *status |= FE_HAS_SIGNAL;
+                       if ((utmp & 0xF) >= 0x0a)
+                               *status |= FE_HAS_CARRIER;
+                       if ((utmp & 0xF) >= 0x0d)
+                               *status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+               }
+               break;
+       case SYS_DVBC_ANNEX_A:
+               ret = regmap_read(dev->regmap[1], 0x85, &utmp);
+               if (ret)
+                       goto err;
+               if (!(utmp & 0x40)) {
+                       ret = regmap_read(dev->regmap[1], 0x89, &utmp);
+                       if (ret)
+                               goto err;
+                       if (utmp & 0x01)
+                               lock = 1;
+               }
+               break;
+       default:
+               ret = -EINVAL;
+               goto err;
+       }
+
+       if (lock)
+               *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
+                               FE_HAS_SYNC | FE_HAS_LOCK;
 
        return 0;
 err:
@@ -219,11 +242,23 @@ static int mn88473_init(struct dvb_frontend *fe)
        int ret, len, remaining;
        const struct firmware *fw = NULL;
        u8 *fw_file = MN88473_FIRMWARE;
+       unsigned int tmp;
 
        dev_dbg(&client->dev, "\n");
 
-       if (dev->warm)
+       /* set cold state by default */
+       dev->warm = false;
+
+       /* check if firmware is already running */
+       ret = regmap_read(dev->regmap[0], 0xf5, &tmp);
+       if (ret)
+               goto err;
+
+       if (!(tmp & 0x1)) {
+               dev_info(&client->dev, "firmware already running\n");
+               dev->warm = true;
                return 0;
+       }
 
        /* request the firmware, this will block and timeout */
        ret = request_firmware(&fw, fw_file, &client->dev);
@@ -254,6 +289,20 @@ static int mn88473_init(struct dvb_frontend *fe)
                }
        }
 
+       /* parity check of firmware */
+       ret = regmap_read(dev->regmap[0], 0xf8, &tmp);
+       if (ret) {
+               dev_err(&client->dev,
+                               "parity reg read failed=%d\n", ret);
+               goto err;
+       }
+       if (tmp & 0x10) {
+               dev_err(&client->dev,
+                               "firmware parity check failed=0x%x\n", tmp);
+               goto err;
+       }
+       dev_err(&client->dev, "firmware parity check succeeded=0x%x\n", tmp);
+
        ret = regmap_write(dev->regmap[0], 0xf5, 0x00);
        if (ret)
                goto err;
@@ -297,6 +346,8 @@ static struct dvb_frontend_ops mn88473_ops = {
        .delsys = {SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_AC},
        .info = {
                .name = "Panasonic MN88473",
+               .symbol_rate_min = 1000000,
+               .symbol_rate_max = 7200000,
                .caps = FE_CAN_FEC_1_2                 |
                        FE_CAN_FEC_2_3                 |
                        FE_CAN_FEC_3_4                 |
@@ -356,6 +407,10 @@ static int mn88473_probe(struct i2c_client *client,
        }
 
        dev->i2c_wr_max = config->i2c_wr_max;
+       if (!config->xtal)
+               dev->xtal = 25000000;
+       else
+               dev->xtal = config->xtal;
        dev->client[0] = client;
        dev->regmap[0] = regmap_init_i2c(dev->client[0], &regmap_config);
        if (IS_ERR(dev->regmap[0])) {
index 78af112fb41d271d424ebc4f76841ae4b643e174..ef6f01323ac990fc45d53bc2636a4508cb6c37c8 100644 (file)
@@ -31,6 +31,7 @@ struct mn88473_dev {
        u16 i2c_wr_max;
        fe_delivery_system_t delivery_system;
        bool warm; /* FW running */
+       u32 xtal;
 };
 
 #endif
index b78643f907e7a4e7cd4974a877c3ddd98a19a77e..072dac04a75007cd8dd5ad1f1769b791a14d216a 100644 (file)
@@ -2,6 +2,7 @@ config VIDEO_OMAP4
        bool "OMAP 4 Camera support"
        depends on VIDEO_V4L2=y && VIDEO_V4L2_SUBDEV_API && I2C=y && ARCH_OMAP4
        depends on HAS_DMA
+       select MFD_SYSCON
        select VIDEOBUF2_DMA_CONTIG
        ---help---
          Driver for an OMAP 4 ISS controller.
index e0ad5e520e2d26705f43d1862de128ea428f20a6..7ced940bd8073dd6b3e3f4299e656ff3cf48146b 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
+#include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
@@ -1386,6 +1387,16 @@ static int iss_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, iss);
 
+       /*
+        * TODO: When implementing DT support switch to syscon regmap lookup by
+        * phandle.
+        */
+       iss->syscon = syscon_regmap_lookup_by_compatible("syscon");
+       if (IS_ERR(iss->syscon)) {
+               ret = PTR_ERR(iss->syscon);
+               goto error;
+       }
+
        /* Clocks */
        ret = iss_map_mem_resource(pdev, iss, OMAP4_ISS_MEM_TOP);
        if (ret < 0)
index 734cfeeb03148abed151ff76c1009c9d3df8994a..35df8b4709e6089d44f15d81fa989e9a4a6840cc 100644 (file)
@@ -29,6 +29,8 @@
 #include "iss_ipipe.h"
 #include "iss_resizer.h"
 
+struct regmap;
+
 #define to_iss_device(ptr_module)                              \
        container_of(ptr_module, struct iss_device, ptr_module)
 #define to_device(ptr_module)                                          \
@@ -79,6 +81,7 @@ struct iss_reg {
 
 /*
  * struct iss_device - ISS device structure.
+ * @syscon: Regmap for the syscon register space
  * @crashed: Bitmask of crashed entities (indexed by entity ID)
  */
 struct iss_device {
@@ -93,6 +96,7 @@ struct iss_device {
 
        struct resource *res[OMAP4_ISS_MEM_LAST];
        void __iomem *regs[OMAP4_ISS_MEM_LAST];
+       struct regmap *syscon;
 
        u64 raw_dmamask;
 
index 2d96fb3eca53795b9c7642db68411f1e5a38110a..d7ff7698a067a0f98d55a015d193c1e166eb5ba6 100644 (file)
@@ -828,17 +828,17 @@ static const struct iss_video_operations csi2_issvideo_ops = {
  */
 
 static struct v4l2_mbus_framefmt *
-__csi2_get_format(struct iss_csi2_device *csi2, struct v4l2_subdev_fh *fh,
+__csi2_get_format(struct iss_csi2_device *csi2, struct v4l2_subdev_pad_config *cfg,
                  unsigned int pad, enum v4l2_subdev_format_whence which)
 {
        if (which == V4L2_SUBDEV_FORMAT_TRY)
-               return v4l2_subdev_get_try_format(fh, pad);
+               return v4l2_subdev_get_try_format(&csi2->subdev, cfg, pad);
 
        return &csi2->formats[pad];
 }
 
 static void
-csi2_try_format(struct iss_csi2_device *csi2, struct v4l2_subdev_fh *fh,
+csi2_try_format(struct iss_csi2_device *csi2, struct v4l2_subdev_pad_config *cfg,
                unsigned int pad, struct v4l2_mbus_framefmt *fmt,
                enum v4l2_subdev_format_whence which)
 {
@@ -868,7 +868,7 @@ csi2_try_format(struct iss_csi2_device *csi2, struct v4l2_subdev_fh *fh,
                 * compression.
                 */
                pixelcode = fmt->code;
-               format = __csi2_get_format(csi2, fh, CSI2_PAD_SINK, which);
+               format = __csi2_get_format(csi2, cfg, CSI2_PAD_SINK, which);
                memcpy(fmt, format, sizeof(*fmt));
 
                /*
@@ -889,12 +889,12 @@ csi2_try_format(struct iss_csi2_device *csi2, struct v4l2_subdev_fh *fh,
 /*
  * csi2_enum_mbus_code - Handle pixel format enumeration
  * @sd     : pointer to v4l2 subdev structure
- * @fh     : V4L2 subdev file handle
+ * @cfg    : V4L2 subdev pad config
  * @code   : pointer to v4l2_subdev_mbus_code_enum structure
  * return -EINVAL or zero on success
  */
 static int csi2_enum_mbus_code(struct v4l2_subdev *sd,
-                              struct v4l2_subdev_fh *fh,
+                              struct v4l2_subdev_pad_config *cfg,
                               struct v4l2_subdev_mbus_code_enum *code)
 {
        struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd);
@@ -907,8 +907,8 @@ static int csi2_enum_mbus_code(struct v4l2_subdev *sd,
 
                code->code = csi2_input_fmts[code->index];
        } else {
-               format = __csi2_get_format(csi2, fh, CSI2_PAD_SINK,
-                                          V4L2_SUBDEV_FORMAT_TRY);
+               format = __csi2_get_format(csi2, cfg, CSI2_PAD_SINK,
+                                          code->which);
                switch (code->index) {
                case 0:
                        /* Passthrough sink pad code */
@@ -931,7 +931,7 @@ static int csi2_enum_mbus_code(struct v4l2_subdev *sd,
 }
 
 static int csi2_enum_frame_size(struct v4l2_subdev *sd,
-                               struct v4l2_subdev_fh *fh,
+                               struct v4l2_subdev_pad_config *cfg,
                                struct v4l2_subdev_frame_size_enum *fse)
 {
        struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd);
@@ -943,7 +943,7 @@ static int csi2_enum_frame_size(struct v4l2_subdev *sd,
        format.code = fse->code;
        format.width = 1;
        format.height = 1;
-       csi2_try_format(csi2, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+       csi2_try_format(csi2, cfg, fse->pad, &format, fse->which);
        fse->min_width = format.width;
        fse->min_height = format.height;
 
@@ -953,7 +953,7 @@ static int csi2_enum_frame_size(struct v4l2_subdev *sd,
        format.code = fse->code;
        format.width = -1;
        format.height = -1;
-       csi2_try_format(csi2, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+       csi2_try_format(csi2, cfg, fse->pad, &format, fse->which);
        fse->max_width = format.width;
        fse->max_height = format.height;
 
@@ -963,17 +963,17 @@ static int csi2_enum_frame_size(struct v4l2_subdev *sd,
 /*
  * csi2_get_format - Handle get format by pads subdev method
  * @sd : pointer to v4l2 subdev structure
- * @fh : V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad config
  * @fmt: pointer to v4l2 subdev format structure
  * return -EINVAL or zero on success
  */
-static int csi2_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int csi2_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                           struct v4l2_subdev_format *fmt)
 {
        struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd);
        struct v4l2_mbus_framefmt *format;
 
-       format = __csi2_get_format(csi2, fh, fmt->pad, fmt->which);
+       format = __csi2_get_format(csi2, cfg, fmt->pad, fmt->which);
        if (format == NULL)
                return -EINVAL;
 
@@ -984,29 +984,29 @@ static int csi2_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 /*
  * csi2_set_format - Handle set format by pads subdev method
  * @sd : pointer to v4l2 subdev structure
- * @fh : V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad config
  * @fmt: pointer to v4l2 subdev format structure
  * return -EINVAL or zero on success
  */
-static int csi2_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int csi2_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                           struct v4l2_subdev_format *fmt)
 {
        struct iss_csi2_device *csi2 = v4l2_get_subdevdata(sd);
        struct v4l2_mbus_framefmt *format;
 
-       format = __csi2_get_format(csi2, fh, fmt->pad, fmt->which);
+       format = __csi2_get_format(csi2, cfg, fmt->pad, fmt->which);
        if (format == NULL)
                return -EINVAL;
 
-       csi2_try_format(csi2, fh, fmt->pad, &fmt->format, fmt->which);
+       csi2_try_format(csi2, cfg, fmt->pad, &fmt->format, fmt->which);
        *format = fmt->format;
 
        /* Propagate the format from sink to source */
        if (fmt->pad == CSI2_PAD_SINK) {
-               format = __csi2_get_format(csi2, fh, CSI2_PAD_SOURCE,
+               format = __csi2_get_format(csi2, cfg, CSI2_PAD_SOURCE,
                                           fmt->which);
                *format = fmt->format;
-               csi2_try_format(csi2, fh, CSI2_PAD_SOURCE, format, fmt->which);
+               csi2_try_format(csi2, cfg, CSI2_PAD_SOURCE, format, fmt->which);
        }
 
        return 0;
@@ -1048,7 +1048,7 @@ static int csi2_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
        format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
        format.format.width = 4096;
        format.format.height = 4096;
-       csi2_set_format(sd, fh, &format);
+       csi2_set_format(sd, fh ? fh->pad : NULL, &format);
 
        return 0;
 }
index 7c3d55d811ef66d2597a5ef6fa4ceff087eab6b0..748607f8918f7021a2319ec21d05b6e18533f895 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/delay.h>
 #include <linux/device.h>
+#include <linux/regmap.h>
 
 #include "../../../../arch/arm/mach-omap2/control.h"
 
@@ -140,9 +141,11 @@ int omap4iss_csiphy_config(struct iss_device *iss,
         * - bit [18] : CSIPHY1 CTRLCLK enable
         * - bit [17:16] : CSIPHY1 config: 00 d-phy, 01/10 ccp2
         */
-       cam_rx_ctrl = omap4_ctrl_pad_readl(
-                       OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_CAMERA_RX);
-
+       /*
+        * TODO: When implementing DT support specify the CONTROL_CAMERA_RX
+        * register offset in the syscon property instead of hardcoding it.
+        */
+       regmap_read(iss->syscon, 0x68, &cam_rx_ctrl);
 
        if (subdevs->interface == ISS_INTERFACE_CSI2A_PHY1) {
                cam_rx_ctrl &= ~(OMAP4_CAMERARX_CSI21_LANEENABLE_MASK |
@@ -166,8 +169,7 @@ int omap4iss_csiphy_config(struct iss_device *iss,
                cam_rx_ctrl |= OMAP4_CAMERARX_CSI22_CTRLCLKEN_MASK;
        }
 
-       omap4_ctrl_pad_writel(cam_rx_ctrl,
-                OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_CAMERA_RX);
+       regmap_write(iss->syscon, 0x68, cam_rx_ctrl);
 
        /* Reset used lane count */
        csi2->phy->used_data_lanes = 0;
index a1a46ef8319bdc204ff6f1570e010108fc925ea1..eaa82da30f503a9f63ce17b0664b521dc88f31c2 100644 (file)
@@ -24,7 +24,7 @@
 #include "iss_ipipe.h"
 
 static struct v4l2_mbus_framefmt *
-__ipipe_get_format(struct iss_ipipe_device *ipipe, struct v4l2_subdev_fh *fh,
+__ipipe_get_format(struct iss_ipipe_device *ipipe, struct v4l2_subdev_pad_config *cfg,
                  unsigned int pad, enum v4l2_subdev_format_whence which);
 
 static const unsigned int ipipe_fmts[] = {
@@ -176,11 +176,11 @@ static int ipipe_set_stream(struct v4l2_subdev *sd, int enable)
 }
 
 static struct v4l2_mbus_framefmt *
-__ipipe_get_format(struct iss_ipipe_device *ipipe, struct v4l2_subdev_fh *fh,
+__ipipe_get_format(struct iss_ipipe_device *ipipe, struct v4l2_subdev_pad_config *cfg,
                  unsigned int pad, enum v4l2_subdev_format_whence which)
 {
        if (which == V4L2_SUBDEV_FORMAT_TRY)
-               return v4l2_subdev_get_try_format(fh, pad);
+               return v4l2_subdev_get_try_format(&ipipe->subdev, cfg, pad);
 
        return &ipipe->formats[pad];
 }
@@ -188,12 +188,12 @@ __ipipe_get_format(struct iss_ipipe_device *ipipe, struct v4l2_subdev_fh *fh,
 /*
  * ipipe_try_format - Try video format on a pad
  * @ipipe: ISS IPIPE device
- * @fh : V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad config
  * @pad: Pad number
  * @fmt: Format
  */
 static void
-ipipe_try_format(struct iss_ipipe_device *ipipe, struct v4l2_subdev_fh *fh,
+ipipe_try_format(struct iss_ipipe_device *ipipe, struct v4l2_subdev_pad_config *cfg,
                unsigned int pad, struct v4l2_mbus_framefmt *fmt,
                enum v4l2_subdev_format_whence which)
 {
@@ -220,7 +220,7 @@ ipipe_try_format(struct iss_ipipe_device *ipipe, struct v4l2_subdev_fh *fh,
                break;
 
        case IPIPE_PAD_SOURCE_VP:
-               format = __ipipe_get_format(ipipe, fh, IPIPE_PAD_SINK, which);
+               format = __ipipe_get_format(ipipe, cfg, IPIPE_PAD_SINK, which);
                memcpy(fmt, format, sizeof(*fmt));
 
                fmt->code = MEDIA_BUS_FMT_UYVY8_1X16;
@@ -236,12 +236,12 @@ ipipe_try_format(struct iss_ipipe_device *ipipe, struct v4l2_subdev_fh *fh,
 /*
  * ipipe_enum_mbus_code - Handle pixel format enumeration
  * @sd     : pointer to v4l2 subdev structure
- * @fh : V4L2 subdev file handle
+ * @cfg    : V4L2 subdev pad config
  * @code   : pointer to v4l2_subdev_mbus_code_enum structure
  * return -EINVAL or zero on success
  */
 static int ipipe_enum_mbus_code(struct v4l2_subdev *sd,
-                              struct v4l2_subdev_fh *fh,
+                              struct v4l2_subdev_pad_config *cfg,
                               struct v4l2_subdev_mbus_code_enum *code)
 {
        switch (code->pad) {
@@ -268,7 +268,7 @@ static int ipipe_enum_mbus_code(struct v4l2_subdev *sd,
 }
 
 static int ipipe_enum_frame_size(struct v4l2_subdev *sd,
-                               struct v4l2_subdev_fh *fh,
+                               struct v4l2_subdev_pad_config *cfg,
                                struct v4l2_subdev_frame_size_enum *fse)
 {
        struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
@@ -280,7 +280,7 @@ static int ipipe_enum_frame_size(struct v4l2_subdev *sd,
        format.code = fse->code;
        format.width = 1;
        format.height = 1;
-       ipipe_try_format(ipipe, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+       ipipe_try_format(ipipe, cfg, fse->pad, &format, fse->which);
        fse->min_width = format.width;
        fse->min_height = format.height;
 
@@ -290,7 +290,7 @@ static int ipipe_enum_frame_size(struct v4l2_subdev *sd,
        format.code = fse->code;
        format.width = -1;
        format.height = -1;
-       ipipe_try_format(ipipe, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+       ipipe_try_format(ipipe, cfg, fse->pad, &format, fse->which);
        fse->max_width = format.width;
        fse->max_height = format.height;
 
@@ -300,19 +300,19 @@ static int ipipe_enum_frame_size(struct v4l2_subdev *sd,
 /*
  * ipipe_get_format - Retrieve the video format on a pad
  * @sd : ISP IPIPE V4L2 subdevice
- * @fh : V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad config
  * @fmt: Format
  *
  * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
  * to the format type.
  */
-static int ipipe_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int ipipe_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                           struct v4l2_subdev_format *fmt)
 {
        struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
        struct v4l2_mbus_framefmt *format;
 
-       format = __ipipe_get_format(ipipe, fh, fmt->pad, fmt->which);
+       format = __ipipe_get_format(ipipe, cfg, fmt->pad, fmt->which);
        if (format == NULL)
                return -EINVAL;
 
@@ -323,31 +323,31 @@ static int ipipe_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 /*
  * ipipe_set_format - Set the video format on a pad
  * @sd : ISP IPIPE V4L2 subdevice
- * @fh : V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad config
  * @fmt: Format
  *
  * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
  * to the format type.
  */
-static int ipipe_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int ipipe_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                           struct v4l2_subdev_format *fmt)
 {
        struct iss_ipipe_device *ipipe = v4l2_get_subdevdata(sd);
        struct v4l2_mbus_framefmt *format;
 
-       format = __ipipe_get_format(ipipe, fh, fmt->pad, fmt->which);
+       format = __ipipe_get_format(ipipe, cfg, fmt->pad, fmt->which);
        if (format == NULL)
                return -EINVAL;
 
-       ipipe_try_format(ipipe, fh, fmt->pad, &fmt->format, fmt->which);
+       ipipe_try_format(ipipe, cfg, fmt->pad, &fmt->format, fmt->which);
        *format = fmt->format;
 
        /* Propagate the format from sink to source */
        if (fmt->pad == IPIPE_PAD_SINK) {
-               format = __ipipe_get_format(ipipe, fh, IPIPE_PAD_SOURCE_VP,
+               format = __ipipe_get_format(ipipe, cfg, IPIPE_PAD_SOURCE_VP,
                                           fmt->which);
                *format = fmt->format;
-               ipipe_try_format(ipipe, fh, IPIPE_PAD_SOURCE_VP, format,
+               ipipe_try_format(ipipe, cfg, IPIPE_PAD_SOURCE_VP, format,
                                fmt->which);
        }
 
@@ -388,7 +388,7 @@ static int ipipe_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
        format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
        format.format.width = 4096;
        format.format.height = 4096;
-       ipipe_set_format(sd, fh, &format);
+       ipipe_set_format(sd, fh ? fh->pad : NULL, &format);
 
        return 0;
 }
@@ -516,8 +516,6 @@ static int ipipe_init_entities(struct iss_ipipe_device *ipipe)
 
 void omap4iss_ipipe_unregister_entities(struct iss_ipipe_device *ipipe)
 {
-       media_entity_cleanup(&ipipe->subdev.entity);
-
        v4l2_device_unregister_subdev(&ipipe->subdev);
 }
 
@@ -566,5 +564,7 @@ int omap4iss_ipipe_init(struct iss_device *iss)
  */
 void omap4iss_ipipe_cleanup(struct iss_device *iss)
 {
-       /* FIXME: are you sure there's nothing to do? */
+       struct iss_ipipe_device *ipipe = &iss->ipipe;
+
+       media_entity_cleanup(&ipipe->subdev.entity);
 }
index 3943fae699ee7f1bdb4c850552c0a3544afa738c..530ac8426b5bf5c931ace3f677271cf994055cd4 100644 (file)
@@ -361,24 +361,24 @@ static int ipipeif_set_stream(struct v4l2_subdev *sd, int enable)
 
 static struct v4l2_mbus_framefmt *
 __ipipeif_get_format(struct iss_ipipeif_device *ipipeif,
-                    struct v4l2_subdev_fh *fh, unsigned int pad,
+                    struct v4l2_subdev_pad_config *cfg, unsigned int pad,
                     enum v4l2_subdev_format_whence which)
 {
        if (which == V4L2_SUBDEV_FORMAT_TRY)
-               return v4l2_subdev_get_try_format(fh, pad);
+               return v4l2_subdev_get_try_format(&ipipeif->subdev, cfg, pad);
        return &ipipeif->formats[pad];
 }
 
 /*
  * ipipeif_try_format - Try video format on a pad
  * @ipipeif: ISS IPIPEIF device
- * @fh : V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad config
  * @pad: Pad number
  * @fmt: Format
  */
 static void
 ipipeif_try_format(struct iss_ipipeif_device *ipipeif,
-                  struct v4l2_subdev_fh *fh, unsigned int pad,
+                  struct v4l2_subdev_pad_config *cfg, unsigned int pad,
                   struct v4l2_mbus_framefmt *fmt,
                   enum v4l2_subdev_format_whence which)
 {
@@ -407,7 +407,7 @@ ipipeif_try_format(struct iss_ipipeif_device *ipipeif,
                break;
 
        case IPIPEIF_PAD_SOURCE_ISIF_SF:
-               format = __ipipeif_get_format(ipipeif, fh, IPIPEIF_PAD_SINK,
+               format = __ipipeif_get_format(ipipeif, cfg, IPIPEIF_PAD_SINK,
                                              which);
                memcpy(fmt, format, sizeof(*fmt));
 
@@ -422,7 +422,7 @@ ipipeif_try_format(struct iss_ipipeif_device *ipipeif,
                break;
 
        case IPIPEIF_PAD_SOURCE_VP:
-               format = __ipipeif_get_format(ipipeif, fh, IPIPEIF_PAD_SINK,
+               format = __ipipeif_get_format(ipipeif, cfg, IPIPEIF_PAD_SINK,
                                              which);
                memcpy(fmt, format, sizeof(*fmt));
 
@@ -441,12 +441,12 @@ ipipeif_try_format(struct iss_ipipeif_device *ipipeif,
 /*
  * ipipeif_enum_mbus_code - Handle pixel format enumeration
  * @sd     : pointer to v4l2 subdev structure
- * @fh : V4L2 subdev file handle
+ * @cfg    : V4L2 subdev pad config
  * @code   : pointer to v4l2_subdev_mbus_code_enum structure
  * return -EINVAL or zero on success
  */
 static int ipipeif_enum_mbus_code(struct v4l2_subdev *sd,
-                              struct v4l2_subdev_fh *fh,
+                              struct v4l2_subdev_pad_config *cfg,
                               struct v4l2_subdev_mbus_code_enum *code)
 {
        struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
@@ -466,8 +466,8 @@ static int ipipeif_enum_mbus_code(struct v4l2_subdev *sd,
                if (code->index != 0)
                        return -EINVAL;
 
-               format = __ipipeif_get_format(ipipeif, fh, IPIPEIF_PAD_SINK,
-                                             V4L2_SUBDEV_FORMAT_TRY);
+               format = __ipipeif_get_format(ipipeif, cfg, IPIPEIF_PAD_SINK,
+                                             code->which);
 
                code->code = format->code;
                break;
@@ -480,7 +480,7 @@ static int ipipeif_enum_mbus_code(struct v4l2_subdev *sd,
 }
 
 static int ipipeif_enum_frame_size(struct v4l2_subdev *sd,
-                               struct v4l2_subdev_fh *fh,
+                               struct v4l2_subdev_pad_config *cfg,
                                struct v4l2_subdev_frame_size_enum *fse)
 {
        struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
@@ -492,8 +492,7 @@ static int ipipeif_enum_frame_size(struct v4l2_subdev *sd,
        format.code = fse->code;
        format.width = 1;
        format.height = 1;
-       ipipeif_try_format(ipipeif, fh, fse->pad, &format,
-                          V4L2_SUBDEV_FORMAT_TRY);
+       ipipeif_try_format(ipipeif, cfg, fse->pad, &format, fse->which);
        fse->min_width = format.width;
        fse->min_height = format.height;
 
@@ -503,8 +502,7 @@ static int ipipeif_enum_frame_size(struct v4l2_subdev *sd,
        format.code = fse->code;
        format.width = -1;
        format.height = -1;
-       ipipeif_try_format(ipipeif, fh, fse->pad, &format,
-                          V4L2_SUBDEV_FORMAT_TRY);
+       ipipeif_try_format(ipipeif, cfg, fse->pad, &format, fse->which);
        fse->max_width = format.width;
        fse->max_height = format.height;
 
@@ -514,19 +512,19 @@ static int ipipeif_enum_frame_size(struct v4l2_subdev *sd,
 /*
  * ipipeif_get_format - Retrieve the video format on a pad
  * @sd : ISP IPIPEIF V4L2 subdevice
- * @fh : V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad config
  * @fmt: Format
  *
  * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
  * to the format type.
  */
-static int ipipeif_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int ipipeif_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                           struct v4l2_subdev_format *fmt)
 {
        struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
        struct v4l2_mbus_framefmt *format;
 
-       format = __ipipeif_get_format(ipipeif, fh, fmt->pad, fmt->which);
+       format = __ipipeif_get_format(ipipeif, cfg, fmt->pad, fmt->which);
        if (format == NULL)
                return -EINVAL;
 
@@ -537,39 +535,39 @@ static int ipipeif_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 /*
  * ipipeif_set_format - Set the video format on a pad
  * @sd : ISP IPIPEIF V4L2 subdevice
- * @fh : V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad config
  * @fmt: Format
  *
  * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
  * to the format type.
  */
-static int ipipeif_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int ipipeif_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                           struct v4l2_subdev_format *fmt)
 {
        struct iss_ipipeif_device *ipipeif = v4l2_get_subdevdata(sd);
        struct v4l2_mbus_framefmt *format;
 
-       format = __ipipeif_get_format(ipipeif, fh, fmt->pad, fmt->which);
+       format = __ipipeif_get_format(ipipeif, cfg, fmt->pad, fmt->which);
        if (format == NULL)
                return -EINVAL;
 
-       ipipeif_try_format(ipipeif, fh, fmt->pad, &fmt->format, fmt->which);
+       ipipeif_try_format(ipipeif, cfg, fmt->pad, &fmt->format, fmt->which);
        *format = fmt->format;
 
        /* Propagate the format from sink to source */
        if (fmt->pad == IPIPEIF_PAD_SINK) {
-               format = __ipipeif_get_format(ipipeif, fh,
+               format = __ipipeif_get_format(ipipeif, cfg,
                                              IPIPEIF_PAD_SOURCE_ISIF_SF,
                                              fmt->which);
                *format = fmt->format;
-               ipipeif_try_format(ipipeif, fh, IPIPEIF_PAD_SOURCE_ISIF_SF,
+               ipipeif_try_format(ipipeif, cfg, IPIPEIF_PAD_SOURCE_ISIF_SF,
                                   format, fmt->which);
 
-               format = __ipipeif_get_format(ipipeif, fh,
+               format = __ipipeif_get_format(ipipeif, cfg,
                                              IPIPEIF_PAD_SOURCE_VP,
                                              fmt->which);
                *format = fmt->format;
-               ipipeif_try_format(ipipeif, fh, IPIPEIF_PAD_SOURCE_VP, format,
+               ipipeif_try_format(ipipeif, cfg, IPIPEIF_PAD_SOURCE_VP, format,
                                fmt->which);
        }
 
@@ -612,7 +610,7 @@ static int ipipeif_init_formats(struct v4l2_subdev *sd,
        format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
        format.format.width = 4096;
        format.format.height = 4096;
-       ipipeif_set_format(sd, fh, &format);
+       ipipeif_set_format(sd, fh ? fh->pad : NULL, &format);
 
        return 0;
 }
@@ -773,8 +771,6 @@ static int ipipeif_init_entities(struct iss_ipipeif_device *ipipeif)
 
 void omap4iss_ipipeif_unregister_entities(struct iss_ipipeif_device *ipipeif)
 {
-       media_entity_cleanup(&ipipeif->subdev.entity);
-
        v4l2_device_unregister_subdev(&ipipeif->subdev);
        omap4iss_video_unregister(&ipipeif->video_out);
 }
@@ -828,5 +824,7 @@ int omap4iss_ipipeif_init(struct iss_device *iss)
  */
 void omap4iss_ipipeif_cleanup(struct iss_device *iss)
 {
-       /* FIXME: are you sure there's nothing to do? */
+       struct iss_ipipeif_device *ipipeif = &iss->ipipeif;
+
+       media_entity_cleanup(&ipipeif->subdev.entity);
 }
index 3ab972818f1bf279e7063776519f3ebc8a50ad5f..5f69012c4debdda7b178a67e936b0bea6f59087d 100644 (file)
@@ -420,24 +420,24 @@ static int resizer_set_stream(struct v4l2_subdev *sd, int enable)
 
 static struct v4l2_mbus_framefmt *
 __resizer_get_format(struct iss_resizer_device *resizer,
-                    struct v4l2_subdev_fh *fh, unsigned int pad,
+                    struct v4l2_subdev_pad_config *cfg, unsigned int pad,
                     enum v4l2_subdev_format_whence which)
 {
        if (which == V4L2_SUBDEV_FORMAT_TRY)
-               return v4l2_subdev_get_try_format(fh, pad);
+               return v4l2_subdev_get_try_format(&resizer->subdev, cfg, pad);
        return &resizer->formats[pad];
 }
 
 /*
  * resizer_try_format - Try video format on a pad
  * @resizer: ISS RESIZER device
- * @fh : V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad config
  * @pad: Pad number
  * @fmt: Format
  */
 static void
 resizer_try_format(struct iss_resizer_device *resizer,
-                  struct v4l2_subdev_fh *fh, unsigned int pad,
+                  struct v4l2_subdev_pad_config *cfg, unsigned int pad,
                   struct v4l2_mbus_framefmt *fmt,
                   enum v4l2_subdev_format_whence which)
 {
@@ -465,7 +465,7 @@ resizer_try_format(struct iss_resizer_device *resizer,
 
        case RESIZER_PAD_SOURCE_MEM:
                pixelcode = fmt->code;
-               format = __resizer_get_format(resizer, fh, RESIZER_PAD_SINK,
+               format = __resizer_get_format(resizer, cfg, RESIZER_PAD_SINK,
                                              which);
                memcpy(fmt, format, sizeof(*fmt));
 
@@ -492,12 +492,12 @@ resizer_try_format(struct iss_resizer_device *resizer,
 /*
  * resizer_enum_mbus_code - Handle pixel format enumeration
  * @sd     : pointer to v4l2 subdev structure
- * @fh : V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad config
  * @code   : pointer to v4l2_subdev_mbus_code_enum structure
  * return -EINVAL or zero on success
  */
 static int resizer_enum_mbus_code(struct v4l2_subdev *sd,
-                              struct v4l2_subdev_fh *fh,
+                              struct v4l2_subdev_pad_config *cfg,
                               struct v4l2_subdev_mbus_code_enum *code)
 {
        struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd);
@@ -512,8 +512,8 @@ static int resizer_enum_mbus_code(struct v4l2_subdev *sd,
                break;
 
        case RESIZER_PAD_SOURCE_MEM:
-               format = __resizer_get_format(resizer, fh, RESIZER_PAD_SINK,
-                                             V4L2_SUBDEV_FORMAT_TRY);
+               format = __resizer_get_format(resizer, cfg, RESIZER_PAD_SINK,
+                                             code->which);
 
                if (code->index == 0) {
                        code->code = format->code;
@@ -542,7 +542,7 @@ static int resizer_enum_mbus_code(struct v4l2_subdev *sd,
 }
 
 static int resizer_enum_frame_size(struct v4l2_subdev *sd,
-                               struct v4l2_subdev_fh *fh,
+                               struct v4l2_subdev_pad_config *cfg,
                                struct v4l2_subdev_frame_size_enum *fse)
 {
        struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd);
@@ -554,8 +554,7 @@ static int resizer_enum_frame_size(struct v4l2_subdev *sd,
        format.code = fse->code;
        format.width = 1;
        format.height = 1;
-       resizer_try_format(resizer, fh, fse->pad, &format,
-                          V4L2_SUBDEV_FORMAT_TRY);
+       resizer_try_format(resizer, cfg, fse->pad, &format, fse->which);
        fse->min_width = format.width;
        fse->min_height = format.height;
 
@@ -565,8 +564,7 @@ static int resizer_enum_frame_size(struct v4l2_subdev *sd,
        format.code = fse->code;
        format.width = -1;
        format.height = -1;
-       resizer_try_format(resizer, fh, fse->pad, &format,
-                          V4L2_SUBDEV_FORMAT_TRY);
+       resizer_try_format(resizer, cfg, fse->pad, &format, fse->which);
        fse->max_width = format.width;
        fse->max_height = format.height;
 
@@ -576,19 +574,19 @@ static int resizer_enum_frame_size(struct v4l2_subdev *sd,
 /*
  * resizer_get_format - Retrieve the video format on a pad
  * @sd : ISP RESIZER V4L2 subdevice
- * @fh : V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad config
  * @fmt: Format
  *
  * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
  * to the format type.
  */
-static int resizer_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int resizer_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                           struct v4l2_subdev_format *fmt)
 {
        struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd);
        struct v4l2_mbus_framefmt *format;
 
-       format = __resizer_get_format(resizer, fh, fmt->pad, fmt->which);
+       format = __resizer_get_format(resizer, cfg, fmt->pad, fmt->which);
        if (format == NULL)
                return -EINVAL;
 
@@ -599,32 +597,32 @@ static int resizer_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 /*
  * resizer_set_format - Set the video format on a pad
  * @sd : ISP RESIZER V4L2 subdevice
- * @fh : V4L2 subdev file handle
+ * @cfg: V4L2 subdev pad config
  * @fmt: Format
  *
  * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
  * to the format type.
  */
-static int resizer_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+static int resizer_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_format *fmt)
 {
        struct iss_resizer_device *resizer = v4l2_get_subdevdata(sd);
        struct v4l2_mbus_framefmt *format;
 
-       format = __resizer_get_format(resizer, fh, fmt->pad, fmt->which);
+       format = __resizer_get_format(resizer, cfg, fmt->pad, fmt->which);
        if (format == NULL)
                return -EINVAL;
 
-       resizer_try_format(resizer, fh, fmt->pad, &fmt->format, fmt->which);
+       resizer_try_format(resizer, cfg, fmt->pad, &fmt->format, fmt->which);
        *format = fmt->format;
 
        /* Propagate the format from sink to source */
        if (fmt->pad == RESIZER_PAD_SINK) {
-               format = __resizer_get_format(resizer, fh,
+               format = __resizer_get_format(resizer, cfg,
                                              RESIZER_PAD_SOURCE_MEM,
                                              fmt->which);
                *format = fmt->format;
-               resizer_try_format(resizer, fh, RESIZER_PAD_SOURCE_MEM, format,
+               resizer_try_format(resizer, cfg, RESIZER_PAD_SOURCE_MEM, format,
                                fmt->which);
        }
 
@@ -667,7 +665,7 @@ static int resizer_init_formats(struct v4l2_subdev *sd,
        format.format.code = MEDIA_BUS_FMT_UYVY8_1X16;
        format.format.width = 4096;
        format.format.height = 4096;
-       resizer_set_format(sd, fh, &format);
+       resizer_set_format(sd, fh ? fh->pad : NULL, &format);
 
        return 0;
 }
@@ -817,8 +815,6 @@ static int resizer_init_entities(struct iss_resizer_device *resizer)
 
 void omap4iss_resizer_unregister_entities(struct iss_resizer_device *resizer)
 {
-       media_entity_cleanup(&resizer->subdev.entity);
-
        v4l2_device_unregister_subdev(&resizer->subdev);
        omap4iss_video_unregister(&resizer->video_out);
 }
@@ -872,5 +868,7 @@ int omap4iss_resizer_init(struct iss_device *iss)
  */
 void omap4iss_resizer_cleanup(struct iss_device *iss)
 {
-       /* FIXME: are you sure there's nothing to do? */
+       struct iss_resizer_device *resizer = &iss->resizer;
+
+       media_entity_cleanup(&resizer->subdev.entity);
 }
index 55938cccde7f0114c395e03e8d39ddc060a9de56..85c54fedddda27eb53c81d4023720bd8510e7dbf 100644 (file)
@@ -171,14 +171,14 @@ static void iss_video_pix_to_mbus(const struct v4l2_pix_format *pix,
        mbus->width = pix->width;
        mbus->height = pix->height;
 
-       for (i = 0; i < ARRAY_SIZE(formats); ++i) {
+       /* Skip the last format in the loop so that it will be selected if no
+        * match is found.
+        */
+       for (i = 0; i < ARRAY_SIZE(formats) - 1; ++i) {
                if (formats[i].pixelformat == pix->pixelformat)
                        break;
        }
 
-       if (WARN_ON(i == ARRAY_SIZE(formats)))
-               return;
-
        mbus->code = formats[i].code;
        mbus->colorspace = pix->colorspace;
        mbus->field = pix->field;
index 81d44c477a5bf11431e37659adf62acf94a8b5bf..257361280510b5b69532ec890941a9fde79e45d6 100644 (file)
@@ -31,12 +31,13 @@ config TCM_PSCSI
        Say Y here to enable the TCM/pSCSI subsystem plugin for non-buffered
        passthrough access to Linux/SCSI device
 
-config TCM_USER
+config TCM_USER2
        tristate "TCM/USER Subsystem Plugin for Linux"
        depends on UIO && NET
        help
        Say Y here to enable the TCM/USER subsystem plugin for a userspace
-       process to handle requests
+       process to handle requests. This is version 2 of the ABI; version 1
+       is obsolete.
 
 source "drivers/target/loopback/Kconfig"
 source "drivers/target/tcm_fc/Kconfig"
index bbb4a7d638efeb4309120b4275cd0415befd9a05..e619c0266a7939bdae8f52ff1da8390e90de6b6b 100644 (file)
@@ -22,7 +22,7 @@ obj-$(CONFIG_TARGET_CORE)     += target_core_mod.o
 obj-$(CONFIG_TCM_IBLOCK)       += target_core_iblock.o
 obj-$(CONFIG_TCM_FILEIO)       += target_core_file.o
 obj-$(CONFIG_TCM_PSCSI)                += target_core_pscsi.o
-obj-$(CONFIG_TCM_USER)         += target_core_user.o
+obj-$(CONFIG_TCM_USER2)                += target_core_user.o
 
 # Fabric modules
 obj-$(CONFIG_LOOPBACK_TARGET)  += loopback/
index 13a92403fe3e1fbba372746c3551c943c05576a4..0f43be9c34532f48e0e681138bdb00c4ed918b0b 100644 (file)
@@ -1,6 +1,5 @@
 iscsi_target_mod-y +=          iscsi_target_parameters.o \
                                iscsi_target_seq_pdu_list.o \
-                               iscsi_target_tq.o \
                                iscsi_target_auth.o \
                                iscsi_target_datain_values.o \
                                iscsi_target_device.o \
index 77d64251af40451f8e897eac1813599e3ba499d0..34871a628b11124e093231694b0b0fb14b62de80 100644 (file)
@@ -33,8 +33,6 @@
 #include <target/iscsi/iscsi_target_core.h>
 #include "iscsi_target_parameters.h"
 #include "iscsi_target_seq_pdu_list.h"
-#include "iscsi_target_tq.h"
-#include "iscsi_target_configfs.h"
 #include "iscsi_target_datain_values.h"
 #include "iscsi_target_erl0.h"
 #include "iscsi_target_erl1.h"
@@ -537,7 +535,7 @@ static struct iscsit_transport iscsi_target_transport = {
 
 static int __init iscsi_target_init_module(void)
 {
-       int ret = 0;
+       int ret = 0, size;
 
        pr_debug("iSCSI-Target "ISCSIT_VERSION"\n");
 
@@ -546,24 +544,21 @@ static int __init iscsi_target_init_module(void)
                pr_err("Unable to allocate memory for iscsit_global\n");
                return -1;
        }
+       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 = iscsi_target_register_configfs();
-       if (ret < 0)
+       ret = target_register_template(&iscsi_ops);
+       if (ret)
                goto out;
 
-       ret = iscsi_thread_set_init();
-       if (ret < 0)
+       size = BITS_TO_LONGS(ISCSIT_BITMAP_BITS) * sizeof(long);
+       iscsit_global->ts_bitmap = vzalloc(size);
+       if (!iscsit_global->ts_bitmap) {
+               pr_err("Unable to allocate iscsit_global->ts_bitmap\n");
                goto configfs_out;
-
-       if (iscsi_allocate_thread_sets(TARGET_THREAD_SET_COUNT) !=
-                       TARGET_THREAD_SET_COUNT) {
-               pr_err("iscsi_allocate_thread_sets() returned"
-                       " unexpected value!\n");
-               goto ts_out1;
        }
 
        lio_qr_cache = kmem_cache_create("lio_qr_cache",
@@ -572,7 +567,7 @@ static int __init iscsi_target_init_module(void)
        if (!lio_qr_cache) {
                pr_err("nable to kmem_cache_create() for"
                                " lio_qr_cache\n");
-               goto ts_out2;
+               goto bitmap_out;
        }
 
        lio_dr_cache = kmem_cache_create("lio_dr_cache",
@@ -617,12 +612,13 @@ dr_out:
        kmem_cache_destroy(lio_dr_cache);
 qr_out:
        kmem_cache_destroy(lio_qr_cache);
-ts_out2:
-       iscsi_deallocate_thread_sets();
-ts_out1:
-       iscsi_thread_set_free();
+bitmap_out:
+       vfree(iscsit_global->ts_bitmap);
 configfs_out:
-       iscsi_target_deregister_configfs();
+       /* XXX: this probably wants it to be it's own unwind step.. */
+       if (iscsit_global->discovery_tpg)
+               iscsit_tpg_disable_portal_group(iscsit_global->discovery_tpg, 1);
+       target_unregister_template(&iscsi_ops);
 out:
        kfree(iscsit_global);
        return -ENOMEM;
@@ -630,8 +626,6 @@ out:
 
 static void __exit iscsi_target_cleanup_module(void)
 {
-       iscsi_deallocate_thread_sets();
-       iscsi_thread_set_free();
        iscsit_release_discovery_tpg();
        iscsit_unregister_transport(&iscsi_target_transport);
        kmem_cache_destroy(lio_qr_cache);
@@ -639,8 +633,15 @@ static void __exit iscsi_target_cleanup_module(void)
        kmem_cache_destroy(lio_ooo_cache);
        kmem_cache_destroy(lio_r2t_cache);
 
-       iscsi_target_deregister_configfs();
+       /*
+        * Shutdown discovery sessions and disable discovery TPG
+        */
+       if (iscsit_global->discovery_tpg)
+               iscsit_tpg_disable_portal_group(iscsit_global->discovery_tpg, 1);
 
+       target_unregister_template(&iscsi_ops);
+
+       vfree(iscsit_global->ts_bitmap);
        kfree(iscsit_global);
 }
 
@@ -990,7 +991,7 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
        /*
         * Initialize struct se_cmd descriptor from target_core_mod infrastructure
         */
-       transport_init_se_cmd(&cmd->se_cmd, &lio_target_fabric_configfs->tf_ops,
+       transport_init_se_cmd(&cmd->se_cmd, &iscsi_ops,
                        conn->sess->se_sess, be32_to_cpu(hdr->data_length),
                        cmd->data_direction, sam_task_attr,
                        cmd->sense_buffer + 2);
@@ -1805,8 +1806,7 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
                u8 tcm_function;
                int ret;
 
-               transport_init_se_cmd(&cmd->se_cmd,
-                                     &lio_target_fabric_configfs->tf_ops,
+               transport_init_se_cmd(&cmd->se_cmd, &iscsi_ops,
                                      conn->sess->se_sess, 0, DMA_NONE,
                                      TCM_SIMPLE_TAG, cmd->sense_buffer + 2);
 
@@ -2155,7 +2155,6 @@ reject:
        cmd->text_in_ptr = NULL;
        return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, buf);
 }
-EXPORT_SYMBOL(iscsit_handle_text_cmd);
 
 int iscsit_logout_closesession(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
 {
@@ -3715,17 +3714,16 @@ static int iscsit_send_reject(
 
 void iscsit_thread_get_cpumask(struct iscsi_conn *conn)
 {
-       struct iscsi_thread_set *ts = conn->thread_set;
        int ord, cpu;
        /*
-        * thread_id is assigned from iscsit_global->ts_bitmap from
-        * within iscsi_thread_set.c:iscsi_allocate_thread_sets()
+        * bitmap_id is assigned from iscsit_global->ts_bitmap from
+        * within iscsit_start_kthreads()
         *
-        * Here we use thread_id to determine which CPU that this
-        * iSCSI connection's iscsi_thread_set will be scheduled to
+        * Here we use bitmap_id to determine which CPU that this
+        * iSCSI connection's RX/TX threads will be scheduled to
         * execute upon.
         */
-       ord = ts->thread_id % cpumask_weight(cpu_online_mask);
+       ord = conn->bitmap_id % cpumask_weight(cpu_online_mask);
        for_each_online_cpu(cpu) {
                if (ord-- == 0) {
                        cpumask_set_cpu(cpu, conn->conn_cpumask);
@@ -3914,7 +3912,7 @@ check_rsp_state:
        switch (state) {
        case ISTATE_SEND_LOGOUTRSP:
                if (!iscsit_logout_post_handler(cmd, conn))
-                       goto restart;
+                       return -ECONNRESET;
                /* fall through */
        case ISTATE_SEND_STATUS:
        case ISTATE_SEND_ASYNCMSG:
@@ -3942,8 +3940,6 @@ check_rsp_state:
 
 err:
        return -1;
-restart:
-       return -EAGAIN;
 }
 
 static int iscsit_handle_response_queue(struct iscsi_conn *conn)
@@ -3970,21 +3966,13 @@ static int iscsit_handle_response_queue(struct iscsi_conn *conn)
 int iscsi_target_tx_thread(void *arg)
 {
        int ret = 0;
-       struct iscsi_conn *conn;
-       struct iscsi_thread_set *ts = arg;
+       struct iscsi_conn *conn = arg;
        /*
         * Allow ourselves to be interrupted by SIGINT so that a
         * connection recovery / failure event can be triggered externally.
         */
        allow_signal(SIGINT);
 
-restart:
-       conn = iscsi_tx_thread_pre_handler(ts);
-       if (!conn)
-               goto out;
-
-       ret = 0;
-
        while (!kthread_should_stop()) {
                /*
                 * Ensure that both TX and RX per connection kthreads
@@ -3993,11 +3981,9 @@ restart:
                iscsit_thread_check_cpumask(conn, current, 1);
 
                wait_event_interruptible(conn->queues_wq,
-                                        !iscsit_conn_all_queues_empty(conn) ||
-                                        ts->status == ISCSI_THREAD_SET_RESET);
+                                        !iscsit_conn_all_queues_empty(conn));
 
-               if ((ts->status == ISCSI_THREAD_SET_RESET) ||
-                    signal_pending(current))
+               if (signal_pending(current))
                        goto transport_err;
 
 get_immediate:
@@ -4008,15 +3994,14 @@ get_immediate:
                ret = iscsit_handle_response_queue(conn);
                if (ret == 1)
                        goto get_immediate;
-               else if (ret == -EAGAIN)
-                       goto restart;
+               else if (ret == -ECONNRESET)
+                       goto out;
                else if (ret < 0)
                        goto transport_err;
        }
 
 transport_err:
        iscsit_take_action_for_connection_exit(conn);
-       goto restart;
 out:
        return 0;
 }
@@ -4111,8 +4096,7 @@ int iscsi_target_rx_thread(void *arg)
        int ret;
        u8 buffer[ISCSI_HDR_LEN], opcode;
        u32 checksum = 0, digest = 0;
-       struct iscsi_conn *conn = NULL;
-       struct iscsi_thread_set *ts = arg;
+       struct iscsi_conn *conn = arg;
        struct kvec iov;
        /*
         * Allow ourselves to be interrupted by SIGINT so that a
@@ -4120,11 +4104,6 @@ int iscsi_target_rx_thread(void *arg)
         */
        allow_signal(SIGINT);
 
-restart:
-       conn = iscsi_rx_thread_pre_handler(ts);
-       if (!conn)
-               goto out;
-
        if (conn->conn_transport->transport_type == ISCSI_INFINIBAND) {
                struct completion comp;
                int rc;
@@ -4134,7 +4113,7 @@ restart:
                if (rc < 0)
                        goto transport_err;
 
-               goto out;
+               goto transport_err;
        }
 
        while (!kthread_should_stop()) {
@@ -4210,8 +4189,6 @@ transport_err:
        if (!signal_pending(current))
                atomic_set(&conn->transport_failed, 1);
        iscsit_take_action_for_connection_exit(conn);
-       goto restart;
-out:
        return 0;
 }
 
@@ -4273,7 +4250,24 @@ int iscsit_close_connection(
        if (conn->conn_transport->transport_type == ISCSI_TCP)
                complete(&conn->conn_logout_comp);
 
-       iscsi_release_thread_set(conn);
+       if (!strcmp(current->comm, ISCSI_RX_THREAD_NAME)) {
+               if (conn->tx_thread &&
+                   cmpxchg(&conn->tx_thread_active, true, false)) {
+                       send_sig(SIGINT, conn->tx_thread, 1);
+                       kthread_stop(conn->tx_thread);
+               }
+       } else if (!strcmp(current->comm, ISCSI_TX_THREAD_NAME)) {
+               if (conn->rx_thread &&
+                   cmpxchg(&conn->rx_thread_active, true, false)) {
+                       send_sig(SIGINT, conn->rx_thread, 1);
+                       kthread_stop(conn->rx_thread);
+               }
+       }
+
+       spin_lock(&iscsit_global->ts_bitmap_lock);
+       bitmap_release_region(iscsit_global->ts_bitmap, conn->bitmap_id,
+                             get_order(1));
+       spin_unlock(&iscsit_global->ts_bitmap_lock);
 
        iscsit_stop_timers_for_cmds(conn);
        iscsit_stop_nopin_response_timer(conn);
@@ -4383,8 +4377,6 @@ int iscsit_close_connection(
 
        iscsit_put_transport(conn->conn_transport);
 
-       conn->thread_set = NULL;
-
        pr_debug("Moving to TARG_CONN_STATE_FREE.\n");
        conn->conn_state = TARG_CONN_STATE_FREE;
        kfree(conn);
@@ -4551,15 +4543,13 @@ static void iscsit_logout_post_handler_closesession(
        struct iscsi_conn *conn)
 {
        struct iscsi_session *sess = conn->sess;
-
-       iscsi_set_thread_clear(conn, ISCSI_CLEAR_TX_THREAD);
-       iscsi_set_thread_set_signal(conn, ISCSI_SIGNAL_TX_THREAD);
+       int sleep = cmpxchg(&conn->tx_thread_active, true, false);
 
        atomic_set(&conn->conn_logout_remove, 0);
        complete(&conn->conn_logout_comp);
 
        iscsit_dec_conn_usage_count(conn);
-       iscsit_stop_session(sess, 1, 1);
+       iscsit_stop_session(sess, sleep, sleep);
        iscsit_dec_session_usage_count(sess);
        target_put_session(sess->se_sess);
 }
@@ -4567,13 +4557,12 @@ static void iscsit_logout_post_handler_closesession(
 static void iscsit_logout_post_handler_samecid(
        struct iscsi_conn *conn)
 {
-       iscsi_set_thread_clear(conn, ISCSI_CLEAR_TX_THREAD);
-       iscsi_set_thread_set_signal(conn, ISCSI_SIGNAL_TX_THREAD);
+       int sleep = cmpxchg(&conn->tx_thread_active, true, false);
 
        atomic_set(&conn->conn_logout_remove, 0);
        complete(&conn->conn_logout_comp);
 
-       iscsit_cause_connection_reinstatement(conn, 1);
+       iscsit_cause_connection_reinstatement(conn, sleep);
        iscsit_dec_conn_usage_count(conn);
 }
 
index e936d56fb523988cf29e0a66c2ea097c5b05a7e0..7d0f9c00d9c255bb6f32856ba2dd19e8390457c0 100644 (file)
@@ -35,7 +35,7 @@ extern void iscsit_stop_session(struct iscsi_session *, int, int);
 extern int iscsit_release_sessions_for_tpg(struct iscsi_portal_group *, int);
 
 extern struct iscsit_global *iscsit_global;
-extern struct target_fabric_configfs *lio_target_fabric_configfs;
+extern const struct target_core_fabric_ops iscsi_ops;
 
 extern struct kmem_cache *lio_dr_cache;
 extern struct kmem_cache *lio_ooo_cache;
index 48384b675e624b9b04011fe03750c11170961ef1..469fce44ebad50a9efda5345fa6135af733d74ca 100644 (file)
@@ -37,9 +37,6 @@
 #include "iscsi_target_util.h"
 #include "iscsi_target.h"
 #include <target/iscsi/iscsi_target_stat.h>
-#include "iscsi_target_configfs.h"
-
-struct target_fabric_configfs *lio_target_fabric_configfs;
 
 struct lio_target_configfs_attribute {
        struct configfs_attribute attr;
@@ -1052,6 +1049,11 @@ TPG_ATTR(default_erl, S_IRUGO | S_IWUSR);
  */
 DEF_TPG_ATTRIB(t10_pi);
 TPG_ATTR(t10_pi, S_IRUGO | S_IWUSR);
+/*
+ * Define iscsi_tpg_attrib_s_fabric_prot_type
+ */
+DEF_TPG_ATTRIB(fabric_prot_type);
+TPG_ATTR(fabric_prot_type, S_IRUGO | S_IWUSR);
 
 static struct configfs_attribute *lio_target_tpg_attrib_attrs[] = {
        &iscsi_tpg_attrib_authentication.attr,
@@ -1065,6 +1067,7 @@ static struct configfs_attribute *lio_target_tpg_attrib_attrs[] = {
        &iscsi_tpg_attrib_demo_mode_discovery.attr,
        &iscsi_tpg_attrib_default_erl.attr,
        &iscsi_tpg_attrib_t10_pi.attr,
+       &iscsi_tpg_attrib_fabric_prot_type.attr,
        NULL,
 };
 
@@ -1410,8 +1413,18 @@ out:
 
 TF_TPG_BASE_ATTR(lio_target, enable, S_IRUGO | S_IWUSR);
 
+static ssize_t lio_target_tpg_show_dynamic_sessions(
+       struct se_portal_group *se_tpg,
+       char *page)
+{
+       return target_show_dynamic_sessions(se_tpg, page);
+}
+
+TF_TPG_BASE_ATTR_RO(lio_target, dynamic_sessions);
+
 static struct configfs_attribute *lio_target_tpg_attrs[] = {
        &lio_target_tpg_enable.attr,
+       &lio_target_tpg_dynamic_sessions.attr,
        NULL,
 };
 
@@ -1450,10 +1463,8 @@ static struct se_portal_group *lio_target_tiqn_addtpg(
        if (!tpg)
                return NULL;
 
-       ret = core_tpg_register(
-                       &lio_target_fabric_configfs->tf_ops,
-                       wwn, &tpg->tpg_se_tpg, tpg,
-                       TRANSPORT_TPG_TYPE_NORMAL);
+       ret = core_tpg_register(&iscsi_ops, wwn, &tpg->tpg_se_tpg,
+                               tpg, TRANSPORT_TPG_TYPE_NORMAL);
        if (ret < 0)
                return NULL;
 
@@ -1872,6 +1883,20 @@ static int lio_tpg_check_prod_mode_write_protect(
        return tpg->tpg_attrib.prod_mode_write_protect;
 }
 
+static int lio_tpg_check_prot_fabric_only(
+       struct se_portal_group *se_tpg)
+{
+       struct iscsi_portal_group *tpg = se_tpg->se_tpg_fabric_ptr;
+       /*
+        * Only report fabric_prot_type if t10_pi has also been enabled
+        * for incoming ib_isert sessions.
+        */
+       if (!tpg->tpg_attrib.t10_pi)
+               return 0;
+
+       return tpg->tpg_attrib.fabric_prot_type;
+}
+
 static void lio_tpg_release_fabric_acl(
        struct se_portal_group *se_tpg,
        struct se_node_acl *se_acl)
@@ -1953,115 +1978,60 @@ static void lio_release_cmd(struct se_cmd *se_cmd)
        iscsit_release_cmd(cmd);
 }
 
-/* End functions for target_core_fabric_ops */
-
-int iscsi_target_register_configfs(void)
-{
-       struct target_fabric_configfs *fabric;
-       int ret;
-
-       lio_target_fabric_configfs = NULL;
-       fabric = target_fabric_configfs_init(THIS_MODULE, "iscsi");
-       if (IS_ERR(fabric)) {
-               pr_err("target_fabric_configfs_init() for"
-                               " LIO-Target failed!\n");
-               return PTR_ERR(fabric);
-       }
-       /*
-        * Setup the fabric API of function pointers used by target_core_mod..
-        */
-       fabric->tf_ops.get_fabric_name = &iscsi_get_fabric_name;
-       fabric->tf_ops.get_fabric_proto_ident = &iscsi_get_fabric_proto_ident;
-       fabric->tf_ops.tpg_get_wwn = &lio_tpg_get_endpoint_wwn;
-       fabric->tf_ops.tpg_get_tag = &lio_tpg_get_tag;
-       fabric->tf_ops.tpg_get_default_depth = &lio_tpg_get_default_depth;
-       fabric->tf_ops.tpg_get_pr_transport_id = &iscsi_get_pr_transport_id;
-       fabric->tf_ops.tpg_get_pr_transport_id_len =
-                               &iscsi_get_pr_transport_id_len;
-       fabric->tf_ops.tpg_parse_pr_out_transport_id =
-                               &iscsi_parse_pr_out_transport_id;
-       fabric->tf_ops.tpg_check_demo_mode = &lio_tpg_check_demo_mode;
-       fabric->tf_ops.tpg_check_demo_mode_cache =
-                               &lio_tpg_check_demo_mode_cache;
-       fabric->tf_ops.tpg_check_demo_mode_write_protect =
-                               &lio_tpg_check_demo_mode_write_protect;
-       fabric->tf_ops.tpg_check_prod_mode_write_protect =
-                               &lio_tpg_check_prod_mode_write_protect;
-       fabric->tf_ops.tpg_alloc_fabric_acl = &lio_tpg_alloc_fabric_acl;
-       fabric->tf_ops.tpg_release_fabric_acl = &lio_tpg_release_fabric_acl;
-       fabric->tf_ops.tpg_get_inst_index = &lio_tpg_get_inst_index;
-       fabric->tf_ops.check_stop_free = &lio_check_stop_free,
-       fabric->tf_ops.release_cmd = &lio_release_cmd;
-       fabric->tf_ops.shutdown_session = &lio_tpg_shutdown_session;
-       fabric->tf_ops.close_session = &lio_tpg_close_session;
-       fabric->tf_ops.sess_get_index = &lio_sess_get_index;
-       fabric->tf_ops.sess_get_initiator_sid = &lio_sess_get_initiator_sid;
-       fabric->tf_ops.write_pending = &lio_write_pending;
-       fabric->tf_ops.write_pending_status = &lio_write_pending_status;
-       fabric->tf_ops.set_default_node_attributes =
-                               &lio_set_default_node_attributes;
-       fabric->tf_ops.get_task_tag = &iscsi_get_task_tag;
-       fabric->tf_ops.get_cmd_state = &iscsi_get_cmd_state;
-       fabric->tf_ops.queue_data_in = &lio_queue_data_in;
-       fabric->tf_ops.queue_status = &lio_queue_status;
-       fabric->tf_ops.queue_tm_rsp = &lio_queue_tm_rsp;
-       fabric->tf_ops.aborted_task = &lio_aborted_task;
-       /*
-        * Setup function pointers for generic logic in target_core_fabric_configfs.c
-        */
-       fabric->tf_ops.fabric_make_wwn = &lio_target_call_coreaddtiqn;
-       fabric->tf_ops.fabric_drop_wwn = &lio_target_call_coredeltiqn;
-       fabric->tf_ops.fabric_make_tpg = &lio_target_tiqn_addtpg;
-       fabric->tf_ops.fabric_drop_tpg = &lio_target_tiqn_deltpg;
-       fabric->tf_ops.fabric_post_link = NULL;
-       fabric->tf_ops.fabric_pre_unlink = NULL;
-       fabric->tf_ops.fabric_make_np = &lio_target_call_addnptotpg;
-       fabric->tf_ops.fabric_drop_np = &lio_target_call_delnpfromtpg;
-       fabric->tf_ops.fabric_make_nodeacl = &lio_target_make_nodeacl;
-       fabric->tf_ops.fabric_drop_nodeacl = &lio_target_drop_nodeacl;
-       /*
-        * Setup default attribute lists for various fabric->tf_cit_tmpl
-        * sturct config_item_type's
-        */
-       fabric->tf_cit_tmpl.tfc_discovery_cit.ct_attrs = lio_target_discovery_auth_attrs;
-       fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = lio_target_wwn_attrs;
-       fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = lio_target_tpg_attrs;
-       fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = lio_target_tpg_attrib_attrs;
-       fabric->tf_cit_tmpl.tfc_tpg_auth_cit.ct_attrs = lio_target_tpg_auth_attrs;
-       fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = lio_target_tpg_param_attrs;
-       fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = lio_target_portal_attrs;
-       fabric->tf_cit_tmpl.tfc_tpg_nacl_base_cit.ct_attrs = lio_target_initiator_attrs;
-       fabric->tf_cit_tmpl.tfc_tpg_nacl_attrib_cit.ct_attrs = lio_target_nacl_attrib_attrs;
-       fabric->tf_cit_tmpl.tfc_tpg_nacl_auth_cit.ct_attrs = lio_target_nacl_auth_attrs;
-       fabric->tf_cit_tmpl.tfc_tpg_nacl_param_cit.ct_attrs = lio_target_nacl_param_attrs;
-
-       ret = target_fabric_configfs_register(fabric);
-       if (ret < 0) {
-               pr_err("target_fabric_configfs_register() for"
-                               " LIO-Target failed!\n");
-               target_fabric_configfs_free(fabric);
-               return ret;
-       }
-
-       lio_target_fabric_configfs = fabric;
-       pr_debug("LIO_TARGET[0] - Set fabric ->"
-                       " lio_target_fabric_configfs\n");
-       return 0;
-}
-
-
-void iscsi_target_deregister_configfs(void)
-{
-       if (!lio_target_fabric_configfs)
-               return;
-       /*
-        * Shutdown discovery sessions and disable discovery TPG
-        */
-       if (iscsit_global->discovery_tpg)
-               iscsit_tpg_disable_portal_group(iscsit_global->discovery_tpg, 1);
-
-       target_fabric_configfs_deregister(lio_target_fabric_configfs);
-       lio_target_fabric_configfs = NULL;
-       pr_debug("LIO_TARGET[0] - Cleared"
-                               " lio_target_fabric_configfs\n");
-}
+const struct target_core_fabric_ops iscsi_ops = {
+       .module                         = THIS_MODULE,
+       .name                           = "iscsi",
+       .get_fabric_name                = iscsi_get_fabric_name,
+       .get_fabric_proto_ident         = iscsi_get_fabric_proto_ident,
+       .tpg_get_wwn                    = lio_tpg_get_endpoint_wwn,
+       .tpg_get_tag                    = lio_tpg_get_tag,
+       .tpg_get_default_depth          = lio_tpg_get_default_depth,
+       .tpg_get_pr_transport_id        = iscsi_get_pr_transport_id,
+       .tpg_get_pr_transport_id_len    = iscsi_get_pr_transport_id_len,
+       .tpg_parse_pr_out_transport_id  = iscsi_parse_pr_out_transport_id,
+       .tpg_check_demo_mode            = lio_tpg_check_demo_mode,
+       .tpg_check_demo_mode_cache      = lio_tpg_check_demo_mode_cache,
+       .tpg_check_demo_mode_write_protect =
+                       lio_tpg_check_demo_mode_write_protect,
+       .tpg_check_prod_mode_write_protect =
+                       lio_tpg_check_prod_mode_write_protect,
+       .tpg_check_prot_fabric_only     = &lio_tpg_check_prot_fabric_only,
+       .tpg_alloc_fabric_acl           = lio_tpg_alloc_fabric_acl,
+       .tpg_release_fabric_acl         = lio_tpg_release_fabric_acl,
+       .tpg_get_inst_index             = lio_tpg_get_inst_index,
+       .check_stop_free                = lio_check_stop_free,
+       .release_cmd                    = lio_release_cmd,
+       .shutdown_session               = lio_tpg_shutdown_session,
+       .close_session                  = lio_tpg_close_session,
+       .sess_get_index                 = lio_sess_get_index,
+       .sess_get_initiator_sid         = lio_sess_get_initiator_sid,
+       .write_pending                  = lio_write_pending,
+       .write_pending_status           = lio_write_pending_status,
+       .set_default_node_attributes    = lio_set_default_node_attributes,
+       .get_task_tag                   = iscsi_get_task_tag,
+       .get_cmd_state                  = iscsi_get_cmd_state,
+       .queue_data_in                  = lio_queue_data_in,
+       .queue_status                   = lio_queue_status,
+       .queue_tm_rsp                   = lio_queue_tm_rsp,
+       .aborted_task                   = lio_aborted_task,
+       .fabric_make_wwn                = lio_target_call_coreaddtiqn,
+       .fabric_drop_wwn                = lio_target_call_coredeltiqn,
+       .fabric_make_tpg                = lio_target_tiqn_addtpg,
+       .fabric_drop_tpg                = lio_target_tiqn_deltpg,
+       .fabric_make_np                 = lio_target_call_addnptotpg,
+       .fabric_drop_np                 = lio_target_call_delnpfromtpg,
+       .fabric_make_nodeacl            = lio_target_make_nodeacl,
+       .fabric_drop_nodeacl            = lio_target_drop_nodeacl,
+
+       .tfc_discovery_attrs            = lio_target_discovery_auth_attrs,
+       .tfc_wwn_attrs                  = lio_target_wwn_attrs,
+       .tfc_tpg_base_attrs             = lio_target_tpg_attrs,
+       .tfc_tpg_attrib_attrs           = lio_target_tpg_attrib_attrs,
+       .tfc_tpg_auth_attrs             = lio_target_tpg_auth_attrs,
+       .tfc_tpg_param_attrs            = lio_target_tpg_param_attrs,
+       .tfc_tpg_np_base_attrs          = lio_target_portal_attrs,
+       .tfc_tpg_nacl_base_attrs        = lio_target_initiator_attrs,
+       .tfc_tpg_nacl_attrib_attrs      = lio_target_nacl_attrib_attrs,
+       .tfc_tpg_nacl_auth_attrs        = lio_target_nacl_auth_attrs,
+       .tfc_tpg_nacl_param_attrs       = lio_target_nacl_param_attrs,
+};
diff --git a/drivers/target/iscsi/iscsi_target_configfs.h b/drivers/target/iscsi/iscsi_target_configfs.h
deleted file mode 100644 (file)
index 8cd5a63..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef ISCSI_TARGET_CONFIGFS_H
-#define ISCSI_TARGET_CONFIGFS_H
-
-extern int iscsi_target_register_configfs(void);
-extern void iscsi_target_deregister_configfs(void);
-
-#endif /* ISCSI_TARGET_CONFIGFS_H */
index bdd8731a4daa677083d829333fc651591ebca046..959a14c9dd5d65f1cbd3ff4e37a8d3480ee9f177 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <target/iscsi/iscsi_target_core.h>
 #include "iscsi_target_seq_pdu_list.h"
-#include "iscsi_target_tq.h"
 #include "iscsi_target_erl0.h"
 #include "iscsi_target_erl1.h"
 #include "iscsi_target_erl2.h"
@@ -860,7 +859,10 @@ void iscsit_connection_reinstatement_rcfr(struct iscsi_conn *conn)
        }
        spin_unlock_bh(&conn->state_lock);
 
-       iscsi_thread_set_force_reinstatement(conn);
+       if (conn->tx_thread && conn->tx_thread_active)
+               send_sig(SIGINT, conn->tx_thread, 1);
+       if (conn->rx_thread && conn->rx_thread_active)
+               send_sig(SIGINT, conn->rx_thread, 1);
 
 sleep:
        wait_for_completion(&conn->conn_wait_rcfr_comp);
@@ -885,10 +887,10 @@ void iscsit_cause_connection_reinstatement(struct iscsi_conn *conn, int sleep)
                return;
        }
 
-       if (iscsi_thread_set_force_reinstatement(conn) < 0) {
-               spin_unlock_bh(&conn->state_lock);
-               return;
-       }
+       if (conn->tx_thread && conn->tx_thread_active)
+               send_sig(SIGINT, conn->tx_thread, 1);
+       if (conn->rx_thread && conn->rx_thread_active)
+               send_sig(SIGINT, conn->rx_thread, 1);
 
        atomic_set(&conn->connection_reinstatement, 1);
        if (!sleep) {
index 153fb66ac1b83693b2a7ea18580ddd4c94f9b5a9..8ce94ff744e6ba1dfd131e5e59a3b18a75639bcb 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <target/iscsi/iscsi_target_core.h>
 #include <target/iscsi/iscsi_target_stat.h>
-#include "iscsi_target_tq.h"
 #include "iscsi_target_device.h"
 #include "iscsi_target_nego.h"
 #include "iscsi_target_erl0.h"
@@ -699,6 +698,51 @@ static void iscsi_post_login_start_timers(struct iscsi_conn *conn)
                iscsit_start_nopin_timer(conn);
 }
 
+static int iscsit_start_kthreads(struct iscsi_conn *conn)
+{
+       int ret = 0;
+
+       spin_lock(&iscsit_global->ts_bitmap_lock);
+       conn->bitmap_id = bitmap_find_free_region(iscsit_global->ts_bitmap,
+                                       ISCSIT_BITMAP_BITS, get_order(1));
+       spin_unlock(&iscsit_global->ts_bitmap_lock);
+
+       if (conn->bitmap_id < 0) {
+               pr_err("bitmap_find_free_region() failed for"
+                      " iscsit_start_kthreads()\n");
+               return -ENOMEM;
+       }
+
+       conn->tx_thread = kthread_run(iscsi_target_tx_thread, conn,
+                                     "%s", ISCSI_TX_THREAD_NAME);
+       if (IS_ERR(conn->tx_thread)) {
+               pr_err("Unable to start iscsi_target_tx_thread\n");
+               ret = PTR_ERR(conn->tx_thread);
+               goto out_bitmap;
+       }
+       conn->tx_thread_active = true;
+
+       conn->rx_thread = kthread_run(iscsi_target_rx_thread, conn,
+                                     "%s", ISCSI_RX_THREAD_NAME);
+       if (IS_ERR(conn->rx_thread)) {
+               pr_err("Unable to start iscsi_target_rx_thread\n");
+               ret = PTR_ERR(conn->rx_thread);
+               goto out_tx;
+       }
+       conn->rx_thread_active = true;
+
+       return 0;
+out_tx:
+       kthread_stop(conn->tx_thread);
+       conn->tx_thread_active = false;
+out_bitmap:
+       spin_lock(&iscsit_global->ts_bitmap_lock);
+       bitmap_release_region(iscsit_global->ts_bitmap, conn->bitmap_id,
+                             get_order(1));
+       spin_unlock(&iscsit_global->ts_bitmap_lock);
+       return ret;
+}
+
 int iscsi_post_login_handler(
        struct iscsi_np *np,
        struct iscsi_conn *conn,
@@ -709,7 +753,7 @@ int iscsi_post_login_handler(
        struct se_session *se_sess = sess->se_sess;
        struct iscsi_portal_group *tpg = sess->tpg;
        struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
-       struct iscsi_thread_set *ts;
+       int rc;
 
        iscsit_inc_conn_usage_count(conn);
 
@@ -724,7 +768,6 @@ int iscsi_post_login_handler(
        /*
         * SCSI Initiator -> SCSI Target Port Mapping
         */
-       ts = iscsi_get_thread_set();
        if (!zero_tsih) {
                iscsi_set_session_parameters(sess->sess_ops,
                                conn->param_list, 0);
@@ -751,9 +794,11 @@ int iscsi_post_login_handler(
                        sess->sess_ops->InitiatorName);
                spin_unlock_bh(&sess->conn_lock);
 
-               iscsi_post_login_start_timers(conn);
+               rc = iscsit_start_kthreads(conn);
+               if (rc)
+                       return rc;
 
-               iscsi_activate_thread_set(conn, ts);
+               iscsi_post_login_start_timers(conn);
                /*
                 * Determine CPU mask to ensure connection's RX and TX kthreads
                 * are scheduled on the same CPU.
@@ -810,8 +855,11 @@ int iscsi_post_login_handler(
                " iSCSI Target Portal Group: %hu\n", tpg->nsessions, tpg->tpgt);
        spin_unlock_bh(&se_tpg->session_lock);
 
+       rc = iscsit_start_kthreads(conn);
+       if (rc)
+               return rc;
+
        iscsi_post_login_start_timers(conn);
-       iscsi_activate_thread_set(conn, ts);
        /*
         * Determine CPU mask to ensure connection's RX and TX kthreads
         * are scheduled on the same CPU.
index bdd127c0e3aed1c718f0bd8b7d656a2c3aefcb71..e8a240818353bb54e2fdf9bb14cb194081c519c2 100644 (file)
@@ -68,10 +68,8 @@ int iscsit_load_discovery_tpg(void)
                return -1;
        }
 
-       ret = core_tpg_register(
-                       &lio_target_fabric_configfs->tf_ops,
-                       NULL, &tpg->tpg_se_tpg, tpg,
-                       TRANSPORT_TPG_TYPE_DISCOVERY);
+       ret = core_tpg_register(&iscsi_ops, NULL, &tpg->tpg_se_tpg,
+                               tpg, TRANSPORT_TPG_TYPE_DISCOVERY);
        if (ret < 0) {
                kfree(tpg);
                return -1;
@@ -228,6 +226,7 @@ static void iscsit_set_default_tpg_attribs(struct iscsi_portal_group *tpg)
        a->demo_mode_discovery = TA_DEMO_MODE_DISCOVERY;
        a->default_erl = TA_DEFAULT_ERL;
        a->t10_pi = TA_DEFAULT_T10_PI;
+       a->fabric_prot_type = TA_DEFAULT_FABRIC_PROT_TYPE;
 }
 
 int iscsit_tpg_add_portal_group(struct iscsi_tiqn *tiqn, struct iscsi_portal_group *tpg)
@@ -878,3 +877,21 @@ int iscsit_ta_t10_pi(
 
        return 0;
 }
+
+int iscsit_ta_fabric_prot_type(
+       struct iscsi_portal_group *tpg,
+       u32 prot_type)
+{
+       struct iscsi_tpg_attrib *a = &tpg->tpg_attrib;
+
+       if ((prot_type != 0) && (prot_type != 1) && (prot_type != 3)) {
+               pr_err("Illegal value for fabric_prot_type: %u\n", prot_type);
+               return -EINVAL;
+       }
+
+       a->fabric_prot_type = prot_type;
+       pr_debug("iSCSI_TPG[%hu] - T10 Fabric Protection Type: %u\n",
+                tpg->tpgt, prot_type);
+
+       return 0;
+}
index e7265337bc43c1f4cf789d4e4c980d8fdbd6add6..95ff5bdecd719d601826feed61abb97b3eac13d4 100644 (file)
@@ -39,5 +39,6 @@ extern int iscsit_ta_prod_mode_write_protect(struct iscsi_portal_group *, u32);
 extern int iscsit_ta_demo_mode_discovery(struct iscsi_portal_group *, u32);
 extern int iscsit_ta_default_erl(struct iscsi_portal_group *, u32);
 extern int iscsit_ta_t10_pi(struct iscsi_portal_group *, u32);
+extern int iscsit_ta_fabric_prot_type(struct iscsi_portal_group *, u32);
 
 #endif /* ISCSI_TARGET_TPG_H */
diff --git a/drivers/target/iscsi/iscsi_target_tq.c b/drivers/target/iscsi/iscsi_target_tq.c
deleted file mode 100644 (file)
index 26aa509..0000000
+++ /dev/null
@@ -1,495 +0,0 @@
-/*******************************************************************************
- * This file contains the iSCSI Login Thread and Thread Queue functions.
- *
- * (c) Copyright 2007-2013 Datera, Inc.
- *
- * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU 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/kthread.h>
-#include <linux/list.h>
-#include <linux/bitmap.h>
-
-#include <target/iscsi/iscsi_target_core.h>
-#include "iscsi_target_tq.h"
-#include "iscsi_target.h"
-
-static LIST_HEAD(inactive_ts_list);
-static DEFINE_SPINLOCK(inactive_ts_lock);
-static DEFINE_SPINLOCK(ts_bitmap_lock);
-
-static void iscsi_add_ts_to_inactive_list(struct iscsi_thread_set *ts)
-{
-       if (!list_empty(&ts->ts_list)) {
-               WARN_ON(1);
-               return;
-       }
-       spin_lock(&inactive_ts_lock);
-       list_add_tail(&ts->ts_list, &inactive_ts_list);
-       iscsit_global->inactive_ts++;
-       spin_unlock(&inactive_ts_lock);
-}
-
-static struct iscsi_thread_set *iscsi_get_ts_from_inactive_list(void)
-{
-       struct iscsi_thread_set *ts;
-
-       spin_lock(&inactive_ts_lock);
-       if (list_empty(&inactive_ts_list)) {
-               spin_unlock(&inactive_ts_lock);
-               return NULL;
-       }
-
-       ts = list_first_entry(&inactive_ts_list, struct iscsi_thread_set, ts_list);
-
-       list_del_init(&ts->ts_list);
-       iscsit_global->inactive_ts--;
-       spin_unlock(&inactive_ts_lock);
-
-       return ts;
-}
-
-int iscsi_allocate_thread_sets(u32 thread_pair_count)
-{
-       int allocated_thread_pair_count = 0, i, thread_id;
-       struct iscsi_thread_set *ts = NULL;
-
-       for (i = 0; i < thread_pair_count; i++) {
-               ts = kzalloc(sizeof(struct iscsi_thread_set), GFP_KERNEL);
-               if (!ts) {
-                       pr_err("Unable to allocate memory for"
-                                       " thread set.\n");
-                       return allocated_thread_pair_count;
-               }
-               /*
-                * Locate the next available regision in the thread_set_bitmap
-                */
-               spin_lock(&ts_bitmap_lock);
-               thread_id = bitmap_find_free_region(iscsit_global->ts_bitmap,
-                               iscsit_global->ts_bitmap_count, get_order(1));
-               spin_unlock(&ts_bitmap_lock);
-               if (thread_id < 0) {
-                       pr_err("bitmap_find_free_region() failed for"
-                               " thread_set_bitmap\n");
-                       kfree(ts);
-                       return allocated_thread_pair_count;
-               }
-
-               ts->thread_id = thread_id;
-               ts->status = ISCSI_THREAD_SET_FREE;
-               INIT_LIST_HEAD(&ts->ts_list);
-               spin_lock_init(&ts->ts_state_lock);
-               init_completion(&ts->rx_restart_comp);
-               init_completion(&ts->tx_restart_comp);
-               init_completion(&ts->rx_start_comp);
-               init_completion(&ts->tx_start_comp);
-               sema_init(&ts->ts_activate_sem, 0);
-
-               ts->create_threads = 1;
-               ts->tx_thread = kthread_run(iscsi_target_tx_thread, ts, "%s",
-                                       ISCSI_TX_THREAD_NAME);
-               if (IS_ERR(ts->tx_thread)) {
-                       dump_stack();
-                       pr_err("Unable to start iscsi_target_tx_thread\n");
-                       break;
-               }
-
-               ts->rx_thread = kthread_run(iscsi_target_rx_thread, ts, "%s",
-                                       ISCSI_RX_THREAD_NAME);
-               if (IS_ERR(ts->rx_thread)) {
-                       kthread_stop(ts->tx_thread);
-                       pr_err("Unable to start iscsi_target_rx_thread\n");
-                       break;
-               }
-               ts->create_threads = 0;
-
-               iscsi_add_ts_to_inactive_list(ts);
-               allocated_thread_pair_count++;
-       }
-
-       pr_debug("Spawned %d thread set(s) (%d total threads).\n",
-               allocated_thread_pair_count, allocated_thread_pair_count * 2);
-       return allocated_thread_pair_count;
-}
-
-static void iscsi_deallocate_thread_one(struct iscsi_thread_set *ts)
-{
-       spin_lock_bh(&ts->ts_state_lock);
-       ts->status = ISCSI_THREAD_SET_DIE;
-
-       if (ts->rx_thread) {
-               complete(&ts->rx_start_comp);
-               spin_unlock_bh(&ts->ts_state_lock);
-               kthread_stop(ts->rx_thread);
-               spin_lock_bh(&ts->ts_state_lock);
-       }
-       if (ts->tx_thread) {
-               complete(&ts->tx_start_comp);
-               spin_unlock_bh(&ts->ts_state_lock);
-               kthread_stop(ts->tx_thread);
-               spin_lock_bh(&ts->ts_state_lock);
-       }
-       spin_unlock_bh(&ts->ts_state_lock);
-       /*
-        * Release this thread_id in the thread_set_bitmap
-        */
-       spin_lock(&ts_bitmap_lock);
-       bitmap_release_region(iscsit_global->ts_bitmap,
-                       ts->thread_id, get_order(1));
-       spin_unlock(&ts_bitmap_lock);
-
-       kfree(ts);
-}
-
-void iscsi_deallocate_thread_sets(void)
-{
-       struct iscsi_thread_set *ts = NULL;
-       u32 released_count = 0;
-
-       while ((ts = iscsi_get_ts_from_inactive_list())) {
-
-               iscsi_deallocate_thread_one(ts);
-               released_count++;
-       }
-
-       if (released_count)
-               pr_debug("Stopped %d thread set(s) (%d total threads)."
-                       "\n", released_count, released_count * 2);
-}
-
-static void iscsi_deallocate_extra_thread_sets(void)
-{
-       u32 orig_count, released_count = 0;
-       struct iscsi_thread_set *ts = NULL;
-
-       orig_count = TARGET_THREAD_SET_COUNT;
-
-       while ((iscsit_global->inactive_ts + 1) > orig_count) {
-               ts = iscsi_get_ts_from_inactive_list();
-               if (!ts)
-                       break;
-
-               iscsi_deallocate_thread_one(ts);
-               released_count++;
-       }
-
-       if (released_count)
-               pr_debug("Stopped %d thread set(s) (%d total threads)."
-                       "\n", released_count, released_count * 2);
-}
-
-void iscsi_activate_thread_set(struct iscsi_conn *conn, struct iscsi_thread_set *ts)
-{
-       spin_lock_bh(&ts->ts_state_lock);
-       conn->thread_set = ts;
-       ts->conn = conn;
-       ts->status = ISCSI_THREAD_SET_ACTIVE;
-       spin_unlock_bh(&ts->ts_state_lock);
-
-       complete(&ts->rx_start_comp);
-       complete(&ts->tx_start_comp);
-
-       down(&ts->ts_activate_sem);
-}
-
-struct iscsi_thread_set *iscsi_get_thread_set(void)
-{
-       struct iscsi_thread_set *ts;
-
-get_set:
-       ts = iscsi_get_ts_from_inactive_list();
-       if (!ts) {
-               iscsi_allocate_thread_sets(1);
-               goto get_set;
-       }
-
-       ts->delay_inactive = 1;
-       ts->signal_sent = 0;
-       ts->thread_count = 2;
-       init_completion(&ts->rx_restart_comp);
-       init_completion(&ts->tx_restart_comp);
-       sema_init(&ts->ts_activate_sem, 0);
-
-       return ts;
-}
-
-void iscsi_set_thread_clear(struct iscsi_conn *conn, u8 thread_clear)
-{
-       struct iscsi_thread_set *ts = NULL;
-
-       if (!conn->thread_set) {
-               pr_err("struct iscsi_conn->thread_set is NULL\n");
-               return;
-       }
-       ts = conn->thread_set;
-
-       spin_lock_bh(&ts->ts_state_lock);
-       ts->thread_clear &= ~thread_clear;
-
-       if ((thread_clear & ISCSI_CLEAR_RX_THREAD) &&
-           (ts->blocked_threads & ISCSI_BLOCK_RX_THREAD))
-               complete(&ts->rx_restart_comp);
-       else if ((thread_clear & ISCSI_CLEAR_TX_THREAD) &&
-                (ts->blocked_threads & ISCSI_BLOCK_TX_THREAD))
-               complete(&ts->tx_restart_comp);
-       spin_unlock_bh(&ts->ts_state_lock);
-}
-
-void iscsi_set_thread_set_signal(struct iscsi_conn *conn, u8 signal_sent)
-{
-       struct iscsi_thread_set *ts = NULL;
-
-       if (!conn->thread_set) {
-               pr_err("struct iscsi_conn->thread_set is NULL\n");
-               return;
-       }
-       ts = conn->thread_set;
-
-       spin_lock_bh(&ts->ts_state_lock);
-       ts->signal_sent |= signal_sent;
-       spin_unlock_bh(&ts->ts_state_lock);
-}
-
-int iscsi_release_thread_set(struct iscsi_conn *conn)
-{
-       int thread_called = 0;
-       struct iscsi_thread_set *ts = NULL;
-
-       if (!conn || !conn->thread_set) {
-               pr_err("connection or thread set pointer is NULL\n");
-               BUG();
-       }
-       ts = conn->thread_set;
-
-       spin_lock_bh(&ts->ts_state_lock);
-       ts->status = ISCSI_THREAD_SET_RESET;
-
-       if (!strncmp(current->comm, ISCSI_RX_THREAD_NAME,
-                       strlen(ISCSI_RX_THREAD_NAME)))
-               thread_called = ISCSI_RX_THREAD;
-       else if (!strncmp(current->comm, ISCSI_TX_THREAD_NAME,
-                       strlen(ISCSI_TX_THREAD_NAME)))
-               thread_called = ISCSI_TX_THREAD;
-
-       if (ts->rx_thread && (thread_called == ISCSI_TX_THREAD) &&
-          (ts->thread_clear & ISCSI_CLEAR_RX_THREAD)) {
-
-               if (!(ts->signal_sent & ISCSI_SIGNAL_RX_THREAD)) {
-                       send_sig(SIGINT, ts->rx_thread, 1);
-                       ts->signal_sent |= ISCSI_SIGNAL_RX_THREAD;
-               }
-               ts->blocked_threads |= ISCSI_BLOCK_RX_THREAD;
-               spin_unlock_bh(&ts->ts_state_lock);
-               wait_for_completion(&ts->rx_restart_comp);
-               spin_lock_bh(&ts->ts_state_lock);
-               ts->blocked_threads &= ~ISCSI_BLOCK_RX_THREAD;
-       }
-       if (ts->tx_thread && (thread_called == ISCSI_RX_THREAD) &&
-          (ts->thread_clear & ISCSI_CLEAR_TX_THREAD)) {
-
-               if (!(ts->signal_sent & ISCSI_SIGNAL_TX_THREAD)) {
-                       send_sig(SIGINT, ts->tx_thread, 1);
-                       ts->signal_sent |= ISCSI_SIGNAL_TX_THREAD;
-               }
-               ts->blocked_threads |= ISCSI_BLOCK_TX_THREAD;
-               spin_unlock_bh(&ts->ts_state_lock);
-               wait_for_completion(&ts->tx_restart_comp);
-               spin_lock_bh(&ts->ts_state_lock);
-               ts->blocked_threads &= ~ISCSI_BLOCK_TX_THREAD;
-       }
-
-       ts->conn = NULL;
-       ts->status = ISCSI_THREAD_SET_FREE;
-       spin_unlock_bh(&ts->ts_state_lock);
-
-       return 0;
-}
-
-int iscsi_thread_set_force_reinstatement(struct iscsi_conn *conn)
-{
-       struct iscsi_thread_set *ts;
-
-       if (!conn->thread_set)
-               return -1;
-       ts = conn->thread_set;
-
-       spin_lock_bh(&ts->ts_state_lock);
-       if (ts->status != ISCSI_THREAD_SET_ACTIVE) {
-               spin_unlock_bh(&ts->ts_state_lock);
-               return -1;
-       }
-
-       if (ts->tx_thread && (!(ts->signal_sent & ISCSI_SIGNAL_TX_THREAD))) {
-               send_sig(SIGINT, ts->tx_thread, 1);
-               ts->signal_sent |= ISCSI_SIGNAL_TX_THREAD;
-       }
-       if (ts->rx_thread && (!(ts->signal_sent & ISCSI_SIGNAL_RX_THREAD))) {
-               send_sig(SIGINT, ts->rx_thread, 1);
-               ts->signal_sent |= ISCSI_SIGNAL_RX_THREAD;
-       }
-       spin_unlock_bh(&ts->ts_state_lock);
-
-       return 0;
-}
-
-static void iscsi_check_to_add_additional_sets(void)
-{
-       int thread_sets_add;
-
-       spin_lock(&inactive_ts_lock);
-       thread_sets_add = iscsit_global->inactive_ts;
-       spin_unlock(&inactive_ts_lock);
-       if (thread_sets_add == 1)
-               iscsi_allocate_thread_sets(1);
-}
-
-static int iscsi_signal_thread_pre_handler(struct iscsi_thread_set *ts)
-{
-       spin_lock_bh(&ts->ts_state_lock);
-       if (ts->status == ISCSI_THREAD_SET_DIE || kthread_should_stop() ||
-           signal_pending(current)) {
-               spin_unlock_bh(&ts->ts_state_lock);
-               return -1;
-       }
-       spin_unlock_bh(&ts->ts_state_lock);
-
-       return 0;
-}
-
-struct iscsi_conn *iscsi_rx_thread_pre_handler(struct iscsi_thread_set *ts)
-{
-       int ret;
-
-       spin_lock_bh(&ts->ts_state_lock);
-       if (ts->create_threads) {
-               spin_unlock_bh(&ts->ts_state_lock);
-               goto sleep;
-       }
-
-       if (ts->status != ISCSI_THREAD_SET_DIE)
-               flush_signals(current);
-
-       if (ts->delay_inactive && (--ts->thread_count == 0)) {
-               spin_unlock_bh(&ts->ts_state_lock);
-
-               if (!iscsit_global->in_shutdown)
-                       iscsi_deallocate_extra_thread_sets();
-
-               iscsi_add_ts_to_inactive_list(ts);
-               spin_lock_bh(&ts->ts_state_lock);
-       }
-
-       if ((ts->status == ISCSI_THREAD_SET_RESET) &&
-           (ts->thread_clear & ISCSI_CLEAR_RX_THREAD))
-               complete(&ts->rx_restart_comp);
-
-       ts->thread_clear &= ~ISCSI_CLEAR_RX_THREAD;
-       spin_unlock_bh(&ts->ts_state_lock);
-sleep:
-       ret = wait_for_completion_interruptible(&ts->rx_start_comp);
-       if (ret != 0)
-               return NULL;
-
-       if (iscsi_signal_thread_pre_handler(ts) < 0)
-               return NULL;
-
-       iscsi_check_to_add_additional_sets();
-
-       spin_lock_bh(&ts->ts_state_lock);
-       if (!ts->conn) {
-               pr_err("struct iscsi_thread_set->conn is NULL for"
-                       " RX thread_id: %s/%d\n", current->comm, current->pid);
-               spin_unlock_bh(&ts->ts_state_lock);
-               return NULL;
-       }
-       ts->thread_clear |= ISCSI_CLEAR_RX_THREAD;
-       spin_unlock_bh(&ts->ts_state_lock);
-
-       up(&ts->ts_activate_sem);
-
-       return ts->conn;
-}
-
-struct iscsi_conn *iscsi_tx_thread_pre_handler(struct iscsi_thread_set *ts)
-{
-       int ret;
-
-       spin_lock_bh(&ts->ts_state_lock);
-       if (ts->create_threads) {
-               spin_unlock_bh(&ts->ts_state_lock);
-               goto sleep;
-       }
-
-       if (ts->status != ISCSI_THREAD_SET_DIE)
-               flush_signals(current);
-
-       if (ts->delay_inactive && (--ts->thread_count == 0)) {
-               spin_unlock_bh(&ts->ts_state_lock);
-
-               if (!iscsit_global->in_shutdown)
-                       iscsi_deallocate_extra_thread_sets();
-
-               iscsi_add_ts_to_inactive_list(ts);
-               spin_lock_bh(&ts->ts_state_lock);
-       }
-       if ((ts->status == ISCSI_THREAD_SET_RESET) &&
-           (ts->thread_clear & ISCSI_CLEAR_TX_THREAD))
-               complete(&ts->tx_restart_comp);
-
-       ts->thread_clear &= ~ISCSI_CLEAR_TX_THREAD;
-       spin_unlock_bh(&ts->ts_state_lock);
-sleep:
-       ret = wait_for_completion_interruptible(&ts->tx_start_comp);
-       if (ret != 0)
-               return NULL;
-
-       if (iscsi_signal_thread_pre_handler(ts) < 0)
-               return NULL;
-
-       iscsi_check_to_add_additional_sets();
-
-       spin_lock_bh(&ts->ts_state_lock);
-       if (!ts->conn) {
-               pr_err("struct iscsi_thread_set->conn is NULL for"
-                       " TX thread_id: %s/%d\n", current->comm, current->pid);
-               spin_unlock_bh(&ts->ts_state_lock);
-               return NULL;
-       }
-       ts->thread_clear |= ISCSI_CLEAR_TX_THREAD;
-       spin_unlock_bh(&ts->ts_state_lock);
-
-       up(&ts->ts_activate_sem);
-
-       return ts->conn;
-}
-
-int iscsi_thread_set_init(void)
-{
-       int size;
-
-       iscsit_global->ts_bitmap_count = ISCSI_TS_BITMAP_BITS;
-
-       size = BITS_TO_LONGS(iscsit_global->ts_bitmap_count) * sizeof(long);
-       iscsit_global->ts_bitmap = kzalloc(size, GFP_KERNEL);
-       if (!iscsit_global->ts_bitmap) {
-               pr_err("Unable to allocate iscsit_global->ts_bitmap\n");
-               return -ENOMEM;
-       }
-
-       return 0;
-}
-
-void iscsi_thread_set_free(void)
-{
-       kfree(iscsit_global->ts_bitmap);
-}
diff --git a/drivers/target/iscsi/iscsi_target_tq.h b/drivers/target/iscsi/iscsi_target_tq.h
deleted file mode 100644 (file)
index cc1eede..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-#ifndef ISCSI_THREAD_QUEUE_H
-#define ISCSI_THREAD_QUEUE_H
-
-/*
- * Defines for thread sets.
- */
-extern int iscsi_thread_set_force_reinstatement(struct iscsi_conn *);
-extern int iscsi_allocate_thread_sets(u32);
-extern void iscsi_deallocate_thread_sets(void);
-extern void iscsi_activate_thread_set(struct iscsi_conn *, struct iscsi_thread_set *);
-extern struct iscsi_thread_set *iscsi_get_thread_set(void);
-extern void iscsi_set_thread_clear(struct iscsi_conn *, u8);
-extern void iscsi_set_thread_set_signal(struct iscsi_conn *, u8);
-extern int iscsi_release_thread_set(struct iscsi_conn *);
-extern struct iscsi_conn *iscsi_rx_thread_pre_handler(struct iscsi_thread_set *);
-extern struct iscsi_conn *iscsi_tx_thread_pre_handler(struct iscsi_thread_set *);
-extern int iscsi_thread_set_init(void);
-extern void iscsi_thread_set_free(void);
-
-extern int iscsi_target_tx_thread(void *);
-extern int iscsi_target_rx_thread(void *);
-
-#define TARGET_THREAD_SET_COUNT                        4
-
-#define ISCSI_RX_THREAD                         1
-#define ISCSI_TX_THREAD                         2
-#define ISCSI_RX_THREAD_NAME                   "iscsi_trx"
-#define ISCSI_TX_THREAD_NAME                   "iscsi_ttx"
-#define ISCSI_BLOCK_RX_THREAD                  0x1
-#define ISCSI_BLOCK_TX_THREAD                  0x2
-#define ISCSI_CLEAR_RX_THREAD                  0x1
-#define ISCSI_CLEAR_TX_THREAD                  0x2
-#define ISCSI_SIGNAL_RX_THREAD                 0x1
-#define ISCSI_SIGNAL_TX_THREAD                 0x2
-
-/* struct iscsi_thread_set->status */
-#define ISCSI_THREAD_SET_FREE                  1
-#define ISCSI_THREAD_SET_ACTIVE                        2
-#define ISCSI_THREAD_SET_DIE                   3
-#define ISCSI_THREAD_SET_RESET                 4
-#define ISCSI_THREAD_SET_DEALLOCATE_THREADS    5
-
-/* By default allow a maximum of 32K iSCSI connections */
-#define ISCSI_TS_BITMAP_BITS                   32768
-
-struct iscsi_thread_set {
-       /* flags used for blocking and restarting sets */
-       int     blocked_threads;
-       /* flag for creating threads */
-       int     create_threads;
-       /* flag for delaying readding to inactive list */
-       int     delay_inactive;
-       /* status for thread set */
-       int     status;
-       /* which threads have had signals sent */
-       int     signal_sent;
-       /* flag for which threads exited first */
-       int     thread_clear;
-       /* Active threads in the thread set */
-       int     thread_count;
-       /* Unique thread ID */
-       u32     thread_id;
-       /* pointer to connection if set is active */
-       struct iscsi_conn       *conn;
-       /* used for controlling ts state accesses */
-       spinlock_t      ts_state_lock;
-       /* used for restarting thread queue */
-       struct completion       rx_restart_comp;
-       /* used for restarting thread queue */
-       struct completion       tx_restart_comp;
-       /* used for normal unused blocking */
-       struct completion       rx_start_comp;
-       /* used for normal unused blocking */
-       struct completion       tx_start_comp;
-       /* OS descriptor for rx thread */
-       struct task_struct      *rx_thread;
-       /* OS descriptor for tx thread */
-       struct task_struct      *tx_thread;
-       /* struct iscsi_thread_set in list list head*/
-       struct list_head        ts_list;
-       struct semaphore        ts_activate_sem;
-};
-
-#endif   /*** ISCSI_THREAD_QUEUE_H ***/
index 390df8ed72b26738c53073180063c42847850585..b18edda3e8af8a6f4b6edba747dbf725bf36a21a 100644 (file)
@@ -33,7 +33,6 @@
 #include "iscsi_target_erl1.h"
 #include "iscsi_target_erl2.h"
 #include "iscsi_target_tpg.h"
-#include "iscsi_target_tq.h"
 #include "iscsi_target_util.h"
 #include "iscsi_target.h"
 
index c36bd7c29136aba1ea42afbc28cae34c6c7ad6a8..51f0c895c6a58fd1e93badf13a52e5eae4b64877 100644 (file)
@@ -41,8 +41,7 @@
 
 #define to_tcm_loop_hba(hba)   container_of(hba, struct tcm_loop_hba, dev)
 
-/* Local pointer to allocated TCM configfs fabric module */
-static struct target_fabric_configfs *tcm_loop_fabric_configfs;
+static const struct target_core_fabric_ops loop_ops;
 
 static struct workqueue_struct *tcm_loop_workqueue;
 static struct kmem_cache *tcm_loop_cmd_cache;
@@ -108,7 +107,7 @@ static struct device_driver tcm_loop_driverfs = {
 /*
  * Used with root_device_register() in tcm_loop_alloc_core_bus() below
  */
-struct device *tcm_loop_primary;
+static struct device *tcm_loop_primary;
 
 static void tcm_loop_submission_work(struct work_struct *work)
 {
@@ -697,6 +696,13 @@ static int tcm_loop_check_prod_mode_write_protect(struct se_portal_group *se_tpg
        return 0;
 }
 
+static int tcm_loop_check_prot_fabric_only(struct se_portal_group *se_tpg)
+{
+       struct tcm_loop_tpg *tl_tpg = container_of(se_tpg, struct tcm_loop_tpg,
+                                                  tl_se_tpg);
+       return tl_tpg->tl_fabric_prot_type;
+}
+
 static struct se_node_acl *tcm_loop_tpg_alloc_fabric_acl(
        struct se_portal_group *se_tpg)
 {
@@ -912,6 +918,46 @@ static void tcm_loop_port_unlink(
 
 /* End items for tcm_loop_port_cit */
 
+static ssize_t tcm_loop_tpg_attrib_show_fabric_prot_type(
+       struct se_portal_group *se_tpg,
+       char *page)
+{
+       struct tcm_loop_tpg *tl_tpg = container_of(se_tpg, struct tcm_loop_tpg,
+                                                  tl_se_tpg);
+
+       return sprintf(page, "%d\n", tl_tpg->tl_fabric_prot_type);
+}
+
+static ssize_t tcm_loop_tpg_attrib_store_fabric_prot_type(
+       struct se_portal_group *se_tpg,
+       const char *page,
+       size_t count)
+{
+       struct tcm_loop_tpg *tl_tpg = container_of(se_tpg, struct tcm_loop_tpg,
+                                                  tl_se_tpg);
+       unsigned long val;
+       int ret = kstrtoul(page, 0, &val);
+
+       if (ret) {
+               pr_err("kstrtoul() returned %d for fabric_prot_type\n", ret);
+               return ret;
+       }
+       if (val != 0 && val != 1 && val != 3) {
+               pr_err("Invalid qla2xxx fabric_prot_type: %lu\n", val);
+               return -EINVAL;
+       }
+       tl_tpg->tl_fabric_prot_type = val;
+
+       return count;
+}
+
+TF_TPG_ATTRIB_ATTR(tcm_loop, fabric_prot_type, S_IRUGO | S_IWUSR);
+
+static struct configfs_attribute *tcm_loop_tpg_attrib_attrs[] = {
+       &tcm_loop_tpg_attrib_fabric_prot_type.attr,
+       NULL,
+};
+
 /* Start items for tcm_loop_nexus_cit */
 
 static int tcm_loop_make_nexus(
@@ -937,7 +983,8 @@ static int tcm_loop_make_nexus(
        /*
         * Initialize the struct se_session pointer
         */
-       tl_nexus->se_sess = transport_init_session(TARGET_PROT_ALL);
+       tl_nexus->se_sess = transport_init_session(
+                               TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS);
        if (IS_ERR(tl_nexus->se_sess)) {
                ret = PTR_ERR(tl_nexus->se_sess);
                goto out;
@@ -1165,21 +1212,19 @@ static struct se_portal_group *tcm_loop_make_naa_tpg(
        struct tcm_loop_hba *tl_hba = container_of(wwn,
                        struct tcm_loop_hba, tl_hba_wwn);
        struct tcm_loop_tpg *tl_tpg;
-       char *tpgt_str, *end_ptr;
        int ret;
-       unsigned short int tpgt;
+       unsigned long tpgt;
 
-       tpgt_str = strstr(name, "tpgt_");
-       if (!tpgt_str) {
+       if (strstr(name, "tpgt_") != name) {
                pr_err("Unable to locate \"tpgt_#\" directory"
                                " group\n");
                return ERR_PTR(-EINVAL);
        }
-       tpgt_str += 5; /* Skip ahead of "tpgt_" */
-       tpgt = (unsigned short int) simple_strtoul(tpgt_str, &end_ptr, 0);
+       if (kstrtoul(name+5, 10, &tpgt))
+               return ERR_PTR(-EINVAL);
 
        if (tpgt >= TL_TPGS_PER_HBA) {
-               pr_err("Passed tpgt: %hu exceeds TL_TPGS_PER_HBA:"
+               pr_err("Passed tpgt: %lu exceeds TL_TPGS_PER_HBA:"
                                " %u\n", tpgt, TL_TPGS_PER_HBA);
                return ERR_PTR(-EINVAL);
        }
@@ -1189,14 +1234,13 @@ static struct se_portal_group *tcm_loop_make_naa_tpg(
        /*
         * Register the tl_tpg as a emulated SAS TCM Target Endpoint
         */
-       ret = core_tpg_register(&tcm_loop_fabric_configfs->tf_ops,
-                       wwn, &tl_tpg->tl_se_tpg, tl_tpg,
+       ret = core_tpg_register(&loop_ops, wwn, &tl_tpg->tl_se_tpg, tl_tpg,
                        TRANSPORT_TPG_TYPE_NORMAL);
        if (ret < 0)
                return ERR_PTR(-ENOMEM);
 
        pr_debug("TCM_Loop_ConfigFS: Allocated Emulated %s"
-               " Target Port %s,t,0x%04x\n", tcm_loop_dump_proto_id(tl_hba),
+               " Target Port %s,t,0x%04lx\n", tcm_loop_dump_proto_id(tl_hba),
                config_item_name(&wwn->wwn_group.cg_item), tpgt);
 
        return &tl_tpg->tl_se_tpg;
@@ -1338,127 +1382,51 @@ static struct configfs_attribute *tcm_loop_wwn_attrs[] = {
 
 /* End items for tcm_loop_cit */
 
-static int tcm_loop_register_configfs(void)
-{
-       struct target_fabric_configfs *fabric;
-       int ret;
-       /*
-        * Set the TCM Loop HBA counter to zero
-        */
-       tcm_loop_hba_no_cnt = 0;
-       /*
-        * Register the top level struct config_item_type with TCM core
-        */
-       fabric = target_fabric_configfs_init(THIS_MODULE, "loopback");
-       if (IS_ERR(fabric)) {
-               pr_err("tcm_loop_register_configfs() failed!\n");
-               return PTR_ERR(fabric);
-       }
-       /*
-        * Setup the fabric API of function pointers used by target_core_mod
-        */
-       fabric->tf_ops.get_fabric_name = &tcm_loop_get_fabric_name;
-       fabric->tf_ops.get_fabric_proto_ident = &tcm_loop_get_fabric_proto_ident;
-       fabric->tf_ops.tpg_get_wwn = &tcm_loop_get_endpoint_wwn;
-       fabric->tf_ops.tpg_get_tag = &tcm_loop_get_tag;
-       fabric->tf_ops.tpg_get_default_depth = &tcm_loop_get_default_depth;
-       fabric->tf_ops.tpg_get_pr_transport_id = &tcm_loop_get_pr_transport_id;
-       fabric->tf_ops.tpg_get_pr_transport_id_len =
-                                       &tcm_loop_get_pr_transport_id_len;
-       fabric->tf_ops.tpg_parse_pr_out_transport_id =
-                                       &tcm_loop_parse_pr_out_transport_id;
-       fabric->tf_ops.tpg_check_demo_mode = &tcm_loop_check_demo_mode;
-       fabric->tf_ops.tpg_check_demo_mode_cache =
-                                       &tcm_loop_check_demo_mode_cache;
-       fabric->tf_ops.tpg_check_demo_mode_write_protect =
-                                       &tcm_loop_check_demo_mode_write_protect;
-       fabric->tf_ops.tpg_check_prod_mode_write_protect =
-                                       &tcm_loop_check_prod_mode_write_protect;
-       /*
-        * The TCM loopback fabric module runs in demo-mode to a local
-        * virtual SCSI device, so fabric dependent initator ACLs are
-        * not required.
-        */
-       fabric->tf_ops.tpg_alloc_fabric_acl = &tcm_loop_tpg_alloc_fabric_acl;
-       fabric->tf_ops.tpg_release_fabric_acl =
-                                       &tcm_loop_tpg_release_fabric_acl;
-       fabric->tf_ops.tpg_get_inst_index = &tcm_loop_get_inst_index;
-       /*
-        * Used for setting up remaining TCM resources in process context
-        */
-       fabric->tf_ops.check_stop_free = &tcm_loop_check_stop_free;
-       fabric->tf_ops.release_cmd = &tcm_loop_release_cmd;
-       fabric->tf_ops.shutdown_session = &tcm_loop_shutdown_session;
-       fabric->tf_ops.close_session = &tcm_loop_close_session;
-       fabric->tf_ops.sess_get_index = &tcm_loop_sess_get_index;
-       fabric->tf_ops.sess_get_initiator_sid = NULL;
-       fabric->tf_ops.write_pending = &tcm_loop_write_pending;
-       fabric->tf_ops.write_pending_status = &tcm_loop_write_pending_status;
-       /*
-        * Not used for TCM loopback
-        */
-       fabric->tf_ops.set_default_node_attributes =
-                                       &tcm_loop_set_default_node_attributes;
-       fabric->tf_ops.get_task_tag = &tcm_loop_get_task_tag;
-       fabric->tf_ops.get_cmd_state = &tcm_loop_get_cmd_state;
-       fabric->tf_ops.queue_data_in = &tcm_loop_queue_data_in;
-       fabric->tf_ops.queue_status = &tcm_loop_queue_status;
-       fabric->tf_ops.queue_tm_rsp = &tcm_loop_queue_tm_rsp;
-       fabric->tf_ops.aborted_task = &tcm_loop_aborted_task;
-
-       /*
-        * Setup function pointers for generic logic in target_core_fabric_configfs.c
-        */
-       fabric->tf_ops.fabric_make_wwn = &tcm_loop_make_scsi_hba;
-       fabric->tf_ops.fabric_drop_wwn = &tcm_loop_drop_scsi_hba;
-       fabric->tf_ops.fabric_make_tpg = &tcm_loop_make_naa_tpg;
-       fabric->tf_ops.fabric_drop_tpg = &tcm_loop_drop_naa_tpg;
-       /*
-        * fabric_post_link() and fabric_pre_unlink() are used for
-        * registration and release of TCM Loop Virtual SCSI LUNs.
-        */
-       fabric->tf_ops.fabric_post_link = &tcm_loop_port_link;
-       fabric->tf_ops.fabric_pre_unlink = &tcm_loop_port_unlink;
-       fabric->tf_ops.fabric_make_np = NULL;
-       fabric->tf_ops.fabric_drop_np = NULL;
-       /*
-        * Setup default attribute lists for various fabric->tf_cit_tmpl
-        */
-       fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = tcm_loop_wwn_attrs;
-       fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = tcm_loop_tpg_attrs;
-       fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;
-       /*
-        * Once fabric->tf_ops has been setup, now register the fabric for
-        * use within TCM
-        */
-       ret = target_fabric_configfs_register(fabric);
-       if (ret < 0) {
-               pr_err("target_fabric_configfs_register() for"
-                               " TCM_Loop failed!\n");
-               target_fabric_configfs_free(fabric);
-               return -1;
-       }
-       /*
-        * Setup our local pointer to *fabric.
-        */
-       tcm_loop_fabric_configfs = fabric;
-       pr_debug("TCM_LOOP[0] - Set fabric ->"
-                       " tcm_loop_fabric_configfs\n");
-       return 0;
-}
-
-static void tcm_loop_deregister_configfs(void)
-{
-       if (!tcm_loop_fabric_configfs)
-               return;
-
-       target_fabric_configfs_deregister(tcm_loop_fabric_configfs);
-       tcm_loop_fabric_configfs = NULL;
-       pr_debug("TCM_LOOP[0] - Cleared"
-                               " tcm_loop_fabric_configfs\n");
-}
+static const struct target_core_fabric_ops loop_ops = {
+       .module                         = THIS_MODULE,
+       .name                           = "loopback",
+       .get_fabric_name                = tcm_loop_get_fabric_name,
+       .get_fabric_proto_ident         = tcm_loop_get_fabric_proto_ident,
+       .tpg_get_wwn                    = tcm_loop_get_endpoint_wwn,
+       .tpg_get_tag                    = tcm_loop_get_tag,
+       .tpg_get_default_depth          = tcm_loop_get_default_depth,
+       .tpg_get_pr_transport_id        = tcm_loop_get_pr_transport_id,
+       .tpg_get_pr_transport_id_len    = tcm_loop_get_pr_transport_id_len,
+       .tpg_parse_pr_out_transport_id  = tcm_loop_parse_pr_out_transport_id,
+       .tpg_check_demo_mode            = tcm_loop_check_demo_mode,
+       .tpg_check_demo_mode_cache      = tcm_loop_check_demo_mode_cache,
+       .tpg_check_demo_mode_write_protect =
+                               tcm_loop_check_demo_mode_write_protect,
+       .tpg_check_prod_mode_write_protect =
+                               tcm_loop_check_prod_mode_write_protect,
+       .tpg_check_prot_fabric_only     = tcm_loop_check_prot_fabric_only,
+       .tpg_alloc_fabric_acl           = tcm_loop_tpg_alloc_fabric_acl,
+       .tpg_release_fabric_acl         = tcm_loop_tpg_release_fabric_acl,
+       .tpg_get_inst_index             = tcm_loop_get_inst_index,
+       .check_stop_free                = tcm_loop_check_stop_free,
+       .release_cmd                    = tcm_loop_release_cmd,
+       .shutdown_session               = tcm_loop_shutdown_session,
+       .close_session                  = tcm_loop_close_session,
+       .sess_get_index                 = tcm_loop_sess_get_index,
+       .write_pending                  = tcm_loop_write_pending,
+       .write_pending_status           = tcm_loop_write_pending_status,
+       .set_default_node_attributes    = tcm_loop_set_default_node_attributes,
+       .get_task_tag                   = tcm_loop_get_task_tag,
+       .get_cmd_state                  = tcm_loop_get_cmd_state,
+       .queue_data_in                  = tcm_loop_queue_data_in,
+       .queue_status                   = tcm_loop_queue_status,
+       .queue_tm_rsp                   = tcm_loop_queue_tm_rsp,
+       .aborted_task                   = tcm_loop_aborted_task,
+       .fabric_make_wwn                = tcm_loop_make_scsi_hba,
+       .fabric_drop_wwn                = tcm_loop_drop_scsi_hba,
+       .fabric_make_tpg                = tcm_loop_make_naa_tpg,
+       .fabric_drop_tpg                = tcm_loop_drop_naa_tpg,
+       .fabric_post_link               = tcm_loop_port_link,
+       .fabric_pre_unlink              = tcm_loop_port_unlink,
+       .tfc_wwn_attrs                  = tcm_loop_wwn_attrs,
+       .tfc_tpg_base_attrs             = tcm_loop_tpg_attrs,
+       .tfc_tpg_attrib_attrs           = tcm_loop_tpg_attrib_attrs,
+};
 
 static int __init tcm_loop_fabric_init(void)
 {
@@ -1482,7 +1450,7 @@ static int __init tcm_loop_fabric_init(void)
        if (ret)
                goto out_destroy_cache;
 
-       ret = tcm_loop_register_configfs();
+       ret = target_register_template(&loop_ops);
        if (ret)
                goto out_release_core_bus;
 
@@ -1500,7 +1468,7 @@ out:
 
 static void __exit tcm_loop_fabric_exit(void)
 {
-       tcm_loop_deregister_configfs();
+       target_unregister_template(&loop_ops);
        tcm_loop_release_core_bus();
        kmem_cache_destroy(tcm_loop_cmd_cache);
        destroy_workqueue(tcm_loop_workqueue);
index 6ae49f272ba6f72d1cd425d30c66227d5d696f31..1e72ff77cac9c3eab83e933d2c5d675edfea483b 100644 (file)
@@ -43,6 +43,7 @@ struct tcm_loop_nacl {
 struct tcm_loop_tpg {
        unsigned short tl_tpgt;
        unsigned short tl_transport_status;
+       enum target_prot_type tl_fabric_prot_type;
        atomic_t tl_tpg_port_count;
        struct se_portal_group tl_se_tpg;
        struct tcm_loop_hba *tl_hba;
index 9512af6a811408f169b7a6c5084dda5ce98d8dfa..18b0f9703ff282a7c63229e822b6f2b8a01b26e2 100644 (file)
@@ -42,8 +42,7 @@
 
 #include "sbp_target.h"
 
-/* Local pointer to allocated TCM configfs fabric module */
-static struct target_fabric_configfs *sbp_fabric_configfs;
+static const struct target_core_fabric_ops sbp_ops;
 
 /* FireWire address region for management and command block address handlers */
 static const struct fw_address_region sbp_register_region = {
@@ -2215,8 +2214,7 @@ static struct se_portal_group *sbp_make_tpg(
                goto out_free_tpg;
        }
 
-       ret = core_tpg_register(&sbp_fabric_configfs->tf_ops, wwn,
-                       &tpg->se_tpg, (void *)tpg,
+       ret = core_tpg_register(&sbp_ops, wwn, &tpg->se_tpg, tpg,
                        TRANSPORT_TPG_TYPE_NORMAL);
        if (ret < 0)
                goto out_unreg_mgt_agt;
@@ -2503,7 +2501,9 @@ static struct configfs_attribute *sbp_tpg_attrib_attrs[] = {
        NULL,
 };
 
-static struct target_core_fabric_ops sbp_ops = {
+static const struct target_core_fabric_ops sbp_ops = {
+       .module                         = THIS_MODULE,
+       .name                           = "sbp",
        .get_fabric_name                = sbp_get_fabric_name,
        .get_fabric_proto_ident         = sbp_get_fabric_proto_ident,
        .tpg_get_wwn                    = sbp_get_fabric_wwn,
@@ -2544,68 +2544,20 @@ static struct target_core_fabric_ops sbp_ops = {
        .fabric_drop_np                 = NULL,
        .fabric_make_nodeacl            = sbp_make_nodeacl,
        .fabric_drop_nodeacl            = sbp_drop_nodeacl,
-};
-
-static int sbp_register_configfs(void)
-{
-       struct target_fabric_configfs *fabric;
-       int ret;
-
-       fabric = target_fabric_configfs_init(THIS_MODULE, "sbp");
-       if (IS_ERR(fabric)) {
-               pr_err("target_fabric_configfs_init() failed\n");
-               return PTR_ERR(fabric);
-       }
-
-       fabric->tf_ops = sbp_ops;
-
-       /*
-        * Setup default attribute lists for various fabric->tf_cit_tmpl
-        */
-       fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = sbp_wwn_attrs;
-       fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = sbp_tpg_base_attrs;
-       fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = sbp_tpg_attrib_attrs;
-       fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_nacl_base_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_nacl_auth_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_nacl_param_cit.ct_attrs = NULL;
-
-       ret = target_fabric_configfs_register(fabric);
-       if (ret < 0) {
-               pr_err("target_fabric_configfs_register() failed for SBP\n");
-               return ret;
-       }
 
-       sbp_fabric_configfs = fabric;
-
-       return 0;
-};
-
-static void sbp_deregister_configfs(void)
-{
-       if (!sbp_fabric_configfs)
-               return;
-
-       target_fabric_configfs_deregister(sbp_fabric_configfs);
-       sbp_fabric_configfs = NULL;
+       .tfc_wwn_attrs                  = sbp_wwn_attrs,
+       .tfc_tpg_base_attrs             = sbp_tpg_base_attrs,
+       .tfc_tpg_attrib_attrs           = sbp_tpg_attrib_attrs,
 };
 
 static int __init sbp_init(void)
 {
-       int ret;
-
-       ret = sbp_register_configfs();
-       if (ret < 0)
-               return ret;
-
-       return 0;
+       return target_register_template(&sbp_ops);
 };
 
 static void __exit sbp_exit(void)
 {
-       sbp_deregister_configfs();
+       target_unregister_template(&sbp_ops);
 };
 
 MODULE_DESCRIPTION("FireWire SBP fabric driver");
index 75d89adfccc025f7fa862c5c7aba157113b001ea..ddaf76a4ac2aab3c00e70607a76c90a6cb308389 100644 (file)
@@ -142,8 +142,8 @@ static struct config_group *target_core_register_fabric(
 
        tf = target_core_get_fabric(name);
        if (!tf) {
-               pr_err("target_core_register_fabric() trying autoload for %s\n",
-                       name);
+               pr_debug("target_core_register_fabric() trying autoload for %s\n",
+                        name);
 
                /*
                 * Below are some hardcoded request_module() calls to automatically
@@ -165,8 +165,8 @@ static struct config_group *target_core_register_fabric(
                         */
                        ret = request_module("iscsi_target_mod");
                        if (ret < 0) {
-                               pr_err("request_module() failed for"
-                                      " iscsi_target_mod.ko: %d\n", ret);
+                               pr_debug("request_module() failed for"
+                                        " iscsi_target_mod.ko: %d\n", ret);
                                return ERR_PTR(-EINVAL);
                        }
                } else if (!strncmp(name, "loopback", 8)) {
@@ -178,8 +178,8 @@ static struct config_group *target_core_register_fabric(
                         */
                        ret = request_module("tcm_loop");
                        if (ret < 0) {
-                               pr_err("request_module() failed for"
-                                      " tcm_loop.ko: %d\n", ret);
+                               pr_debug("request_module() failed for"
+                                        " tcm_loop.ko: %d\n", ret);
                                return ERR_PTR(-EINVAL);
                        }
                }
@@ -188,8 +188,8 @@ static struct config_group *target_core_register_fabric(
        }
 
        if (!tf) {
-               pr_err("target_core_get_fabric() failed for %s\n",
-                      name);
+               pr_debug("target_core_get_fabric() failed for %s\n",
+                        name);
                return ERR_PTR(-EINVAL);
        }
        pr_debug("Target_Core_ConfigFS: REGISTER -> Located fabric:"
@@ -300,81 +300,17 @@ struct configfs_subsystem *target_core_subsystem[] = {
 // Start functions called by external Target Fabrics Modules
 //############################################################################*/
 
-/*
- * First function called by fabric modules to:
- *
- * 1) Allocate a struct target_fabric_configfs and save the *fabric_cit pointer.
- * 2) Add struct target_fabric_configfs to g_tf_list
- * 3) Return struct target_fabric_configfs to fabric module to be passed
- *    into target_fabric_configfs_register().
- */
-struct target_fabric_configfs *target_fabric_configfs_init(
-       struct module *fabric_mod,
-       const char *name)
+static int target_fabric_tf_ops_check(const struct target_core_fabric_ops *tfo)
 {
-       struct target_fabric_configfs *tf;
-
-       if (!(name)) {
-               pr_err("Unable to locate passed fabric name\n");
-               return ERR_PTR(-EINVAL);
+       if (!tfo->name) {
+               pr_err("Missing tfo->name\n");
+               return -EINVAL;
        }
-       if (strlen(name) >= TARGET_FABRIC_NAME_SIZE) {
+       if (strlen(tfo->name) >= TARGET_FABRIC_NAME_SIZE) {
                pr_err("Passed name: %s exceeds TARGET_FABRIC"
-                       "_NAME_SIZE\n", name);
-               return ERR_PTR(-EINVAL);
+                       "_NAME_SIZE\n", tfo->name);
+               return -EINVAL;
        }
-
-       tf = kzalloc(sizeof(struct target_fabric_configfs), GFP_KERNEL);
-       if (!tf)
-               return ERR_PTR(-ENOMEM);
-
-       INIT_LIST_HEAD(&tf->tf_list);
-       atomic_set(&tf->tf_access_cnt, 0);
-       /*
-        * Setup the default generic struct config_item_type's (cits) in
-        * struct target_fabric_configfs->tf_cit_tmpl
-        */
-       tf->tf_module = fabric_mod;
-       target_fabric_setup_cits(tf);
-
-       tf->tf_subsys = target_core_subsystem[0];
-       snprintf(tf->tf_name, TARGET_FABRIC_NAME_SIZE, "%s", name);
-
-       mutex_lock(&g_tf_lock);
-       list_add_tail(&tf->tf_list, &g_tf_list);
-       mutex_unlock(&g_tf_lock);
-
-       pr_debug("<<<<<<<<<<<<<<<<<<<<<< BEGIN FABRIC API >>>>>>>>"
-                       ">>>>>>>>>>>>>>\n");
-       pr_debug("Initialized struct target_fabric_configfs: %p for"
-                       " %s\n", tf, tf->tf_name);
-       return tf;
-}
-EXPORT_SYMBOL(target_fabric_configfs_init);
-
-/*
- * Called by fabric plugins after FAILED target_fabric_configfs_register() call.
- */
-void target_fabric_configfs_free(
-       struct target_fabric_configfs *tf)
-{
-       mutex_lock(&g_tf_lock);
-       list_del(&tf->tf_list);
-       mutex_unlock(&g_tf_lock);
-
-       kfree(tf);
-}
-EXPORT_SYMBOL(target_fabric_configfs_free);
-
-/*
- * Perform a sanity check of the passed tf->tf_ops before completing
- * TCM fabric module registration.
- */
-static int target_fabric_tf_ops_check(
-       struct target_fabric_configfs *tf)
-{
-       struct target_core_fabric_ops *tfo = &tf->tf_ops;
-
        if (!tfo->get_fabric_name) {
                pr_err("Missing tfo->get_fabric_name()\n");
                return -EINVAL;
@@ -508,77 +444,59 @@ static int target_fabric_tf_ops_check(
        return 0;
 }
 
-/*
- * Called 2nd from fabric module with returned parameter of
- * struct target_fabric_configfs * from target_fabric_configfs_init().
- *
- * Upon a successful registration, the new fabric's struct config_item is
- * return.  Also, a pointer to this struct is set in the passed
- * struct target_fabric_configfs.
- */
-int target_fabric_configfs_register(
-       struct target_fabric_configfs *tf)
+int target_register_template(const struct target_core_fabric_ops *fo)
 {
+       struct target_fabric_configfs *tf;
        int ret;
 
+       ret = target_fabric_tf_ops_check(fo);
+       if (ret)
+               return ret;
+
+       tf = kzalloc(sizeof(struct target_fabric_configfs), GFP_KERNEL);
        if (!tf) {
-               pr_err("Unable to locate target_fabric_configfs"
-                       " pointer\n");
-               return -EINVAL;
-       }
-       if (!tf->tf_subsys) {
-               pr_err("Unable to target struct config_subsystem"
-                       " pointer\n");
-               return -EINVAL;
+               pr_err("%s: could not allocate memory!\n", __func__);
+               return -ENOMEM;
        }
-       ret = target_fabric_tf_ops_check(tf);
-       if (ret < 0)
-               return ret;
 
-       pr_debug("<<<<<<<<<<<<<<<<<<<<<< END FABRIC API >>>>>>>>>>>>"
-               ">>>>>>>>>>\n");
+       INIT_LIST_HEAD(&tf->tf_list);
+       atomic_set(&tf->tf_access_cnt, 0);
+
+       /*
+        * Setup the default generic struct config_item_type's (cits) in
+        * struct target_fabric_configfs->tf_cit_tmpl
+        */
+       tf->tf_module = fo->module;
+       tf->tf_subsys = target_core_subsystem[0];
+       snprintf(tf->tf_name, TARGET_FABRIC_NAME_SIZE, "%s", fo->name);
+
+       tf->tf_ops = *fo;
+       target_fabric_setup_cits(tf);
+
+       mutex_lock(&g_tf_lock);
+       list_add_tail(&tf->tf_list, &g_tf_list);
+       mutex_unlock(&g_tf_lock);
+
        return 0;
 }
-EXPORT_SYMBOL(target_fabric_configfs_register);
+EXPORT_SYMBOL(target_register_template);
 
-void target_fabric_configfs_deregister(
-       struct target_fabric_configfs *tf)
+void target_unregister_template(const struct target_core_fabric_ops *fo)
 {
-       struct configfs_subsystem *su;
+       struct target_fabric_configfs *t;
 
-       if (!tf) {
-               pr_err("Unable to locate passed target_fabric_"
-                       "configfs\n");
-               return;
-       }
-       su = tf->tf_subsys;
-       if (!su) {
-               pr_err("Unable to locate passed tf->tf_subsys"
-                       " pointer\n");
-               return;
-       }
-       pr_debug("<<<<<<<<<<<<<<<<<<<<<< BEGIN FABRIC API >>>>>>>>>>"
-                       ">>>>>>>>>>>>\n");
        mutex_lock(&g_tf_lock);
-       if (atomic_read(&tf->tf_access_cnt)) {
-               mutex_unlock(&g_tf_lock);
-               pr_err("Non zero tf->tf_access_cnt for fabric %s\n",
-                       tf->tf_name);
-               BUG();
+       list_for_each_entry(t, &g_tf_list, tf_list) {
+               if (!strcmp(t->tf_name, fo->name)) {
+                       BUG_ON(atomic_read(&t->tf_access_cnt));
+                       list_del(&t->tf_list);
+                       kfree(t);
+                       break;
+               }
        }
-       list_del(&tf->tf_list);
        mutex_unlock(&g_tf_lock);
-
-       pr_debug("Target_Core_ConfigFS: DEREGISTER -> Releasing tf:"
-                       " %s\n", tf->tf_name);
-       tf->tf_module = NULL;
-       tf->tf_subsys = NULL;
-       kfree(tf);
-
-       pr_debug("<<<<<<<<<<<<<<<<<<<<<< END FABRIC API >>>>>>>>>>>>>>>>>"
-                       ">>>>>\n");
 }
-EXPORT_SYMBOL(target_fabric_configfs_deregister);
+EXPORT_SYMBOL(target_unregister_template);
 
 /*##############################################################################
 // Stop functions called by external Target Fabrics Modules
@@ -945,7 +863,7 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_holder_tg_port(
        struct se_lun *lun;
        struct se_portal_group *se_tpg;
        struct t10_pr_registration *pr_reg;
-       struct target_core_fabric_ops *tfo;
+       const struct target_core_fabric_ops *tfo;
        ssize_t len = 0;
 
        spin_lock(&dev->dev_reservation_lock);
@@ -979,7 +897,7 @@ SE_DEV_PR_ATTR_RO(res_pr_holder_tg_port);
 static ssize_t target_core_dev_pr_show_attr_res_pr_registered_i_pts(
                struct se_device *dev, char *page)
 {
-       struct target_core_fabric_ops *tfo;
+       const struct target_core_fabric_ops *tfo;
        struct t10_pr_registration *pr_reg;
        unsigned char buf[384];
        char i_buf[PR_REG_ISID_ID_LEN];
index 0c3f90130b7d398c8670509834d3fe3a59f0de98..1f7886bb16bfc213bad718ac45c2aff3a8ee5f97 100644 (file)
@@ -56,6 +56,20 @@ static void target_fabric_setup_##_name##_cit(struct target_fabric_configfs *tf)
        pr_debug("Setup generic %s\n", __stringify(_name));             \
 }
 
+#define TF_CIT_SETUP_DRV(_name, _item_ops, _group_ops)         \
+static void target_fabric_setup_##_name##_cit(struct target_fabric_configfs *tf) \
+{                                                                      \
+       struct target_fabric_configfs_template *tfc = &tf->tf_cit_tmpl; \
+       struct config_item_type *cit = &tfc->tfc_##_name##_cit;         \
+       struct configfs_attribute **attrs = tf->tf_ops.tfc_##_name##_attrs; \
+                                                                       \
+       cit->ct_item_ops = _item_ops;                                   \
+       cit->ct_group_ops = _group_ops;                                 \
+       cit->ct_attrs = attrs;                                          \
+       cit->ct_owner = tf->tf_module;                                  \
+       pr_debug("Setup generic %s\n", __stringify(_name));             \
+}
+
 /* Start of tfc_tpg_mappedlun_cit */
 
 static int target_fabric_mappedlun_link(
@@ -278,7 +292,7 @@ static struct configfs_item_operations target_fabric_nacl_attrib_item_ops = {
        .store_attribute        = target_fabric_nacl_attrib_attr_store,
 };
 
-TF_CIT_SETUP(tpg_nacl_attrib, &target_fabric_nacl_attrib_item_ops, NULL, NULL);
+TF_CIT_SETUP_DRV(tpg_nacl_attrib, &target_fabric_nacl_attrib_item_ops, NULL);
 
 /* End of tfc_tpg_nacl_attrib_cit */
 
@@ -291,7 +305,7 @@ static struct configfs_item_operations target_fabric_nacl_auth_item_ops = {
        .store_attribute        = target_fabric_nacl_auth_attr_store,
 };
 
-TF_CIT_SETUP(tpg_nacl_auth, &target_fabric_nacl_auth_item_ops, NULL, NULL);
+TF_CIT_SETUP_DRV(tpg_nacl_auth, &target_fabric_nacl_auth_item_ops, NULL);
 
 /* End of tfc_tpg_nacl_auth_cit */
 
@@ -304,7 +318,7 @@ static struct configfs_item_operations target_fabric_nacl_param_item_ops = {
        .store_attribute        = target_fabric_nacl_param_attr_store,
 };
 
-TF_CIT_SETUP(tpg_nacl_param, &target_fabric_nacl_param_item_ops, NULL, NULL);
+TF_CIT_SETUP_DRV(tpg_nacl_param, &target_fabric_nacl_param_item_ops, NULL);
 
 /* End of tfc_tpg_nacl_param_cit */
 
@@ -461,8 +475,8 @@ static struct configfs_group_operations target_fabric_nacl_base_group_ops = {
        .drop_item              = target_fabric_drop_mappedlun,
 };
 
-TF_CIT_SETUP(tpg_nacl_base, &target_fabric_nacl_base_item_ops,
-               &target_fabric_nacl_base_group_ops, NULL);
+TF_CIT_SETUP_DRV(tpg_nacl_base, &target_fabric_nacl_base_item_ops,
+               &target_fabric_nacl_base_group_ops);
 
 /* End of tfc_tpg_nacl_base_cit */
 
@@ -570,7 +584,7 @@ static struct configfs_item_operations target_fabric_np_base_item_ops = {
        .store_attribute        = target_fabric_np_base_attr_store,
 };
 
-TF_CIT_SETUP(tpg_np_base, &target_fabric_np_base_item_ops, NULL, NULL);
+TF_CIT_SETUP_DRV(tpg_np_base, &target_fabric_np_base_item_ops, NULL);
 
 /* End of tfc_tpg_np_base_cit */
 
@@ -966,7 +980,7 @@ static struct configfs_item_operations target_fabric_tpg_attrib_item_ops = {
        .store_attribute        = target_fabric_tpg_attrib_attr_store,
 };
 
-TF_CIT_SETUP(tpg_attrib, &target_fabric_tpg_attrib_item_ops, NULL, NULL);
+TF_CIT_SETUP_DRV(tpg_attrib, &target_fabric_tpg_attrib_item_ops, NULL);
 
 /* End of tfc_tpg_attrib_cit */
 
@@ -979,7 +993,7 @@ static struct configfs_item_operations target_fabric_tpg_auth_item_ops = {
        .store_attribute        = target_fabric_tpg_auth_attr_store,
 };
 
-TF_CIT_SETUP(tpg_auth, &target_fabric_tpg_auth_item_ops, NULL, NULL);
+TF_CIT_SETUP_DRV(tpg_auth, &target_fabric_tpg_auth_item_ops, NULL);
 
 /* End of tfc_tpg_attrib_cit */
 
@@ -992,7 +1006,7 @@ static struct configfs_item_operations target_fabric_tpg_param_item_ops = {
        .store_attribute        = target_fabric_tpg_param_attr_store,
 };
 
-TF_CIT_SETUP(tpg_param, &target_fabric_tpg_param_item_ops, NULL, NULL);
+TF_CIT_SETUP_DRV(tpg_param, &target_fabric_tpg_param_item_ops, NULL);
 
 /* End of tfc_tpg_param_cit */
 
@@ -1018,7 +1032,7 @@ static struct configfs_item_operations target_fabric_tpg_base_item_ops = {
        .store_attribute        = target_fabric_tpg_attr_store,
 };
 
-TF_CIT_SETUP(tpg_base, &target_fabric_tpg_base_item_ops, NULL, NULL);
+TF_CIT_SETUP_DRV(tpg_base, &target_fabric_tpg_base_item_ops, NULL);
 
 /* End of tfc_tpg_base_cit */
 
@@ -1192,7 +1206,7 @@ static struct configfs_item_operations target_fabric_wwn_item_ops = {
        .store_attribute        = target_fabric_wwn_attr_store,
 };
 
-TF_CIT_SETUP(wwn, &target_fabric_wwn_item_ops, &target_fabric_wwn_group_ops, NULL);
+TF_CIT_SETUP_DRV(wwn, &target_fabric_wwn_item_ops, &target_fabric_wwn_group_ops);
 
 /* End of tfc_wwn_cit */
 
@@ -1206,7 +1220,7 @@ static struct configfs_item_operations target_fabric_discovery_item_ops = {
        .store_attribute        = target_fabric_discovery_attr_store,
 };
 
-TF_CIT_SETUP(discovery, &target_fabric_discovery_item_ops, NULL, NULL);
+TF_CIT_SETUP_DRV(discovery, &target_fabric_discovery_item_ops, NULL);
 
 /* End of tfc_discovery_cit */
 
index 44620fb6bd45e96eae5b13dac4b9582a0d86c85e..f7e6e51aed3614aa35e8a58c0bb1d2cfcc462141 100644 (file)
@@ -264,40 +264,32 @@ static int fd_do_prot_rw(struct se_cmd *cmd, struct fd_prot *fd_prot,
        struct se_device *se_dev = cmd->se_dev;
        struct fd_dev *dev = FD_DEV(se_dev);
        struct file *prot_fd = dev->fd_prot_file;
-       struct scatterlist *sg;
        loff_t pos = (cmd->t_task_lba * se_dev->prot_length);
        unsigned char *buf;
-       u32 prot_size, len, size;
-       int rc, ret = 1, i;
+       u32 prot_size;
+       int rc, ret = 1;
 
        prot_size = (cmd->data_length / se_dev->dev_attrib.block_size) *
                     se_dev->prot_length;
 
        if (!is_write) {
-               fd_prot->prot_buf = vzalloc(prot_size);
+               fd_prot->prot_buf = kzalloc(prot_size, GFP_KERNEL);
                if (!fd_prot->prot_buf) {
                        pr_err("Unable to allocate fd_prot->prot_buf\n");
                        return -ENOMEM;
                }
                buf = fd_prot->prot_buf;
 
-               fd_prot->prot_sg_nents = cmd->t_prot_nents;
-               fd_prot->prot_sg = kzalloc(sizeof(struct scatterlist) *
-                                          fd_prot->prot_sg_nents, GFP_KERNEL);
+               fd_prot->prot_sg_nents = 1;
+               fd_prot->prot_sg = kzalloc(sizeof(struct scatterlist),
+                                          GFP_KERNEL);
                if (!fd_prot->prot_sg) {
                        pr_err("Unable to allocate fd_prot->prot_sg\n");
-                       vfree(fd_prot->prot_buf);
+                       kfree(fd_prot->prot_buf);
                        return -ENOMEM;
                }
-               size = prot_size;
-
-               for_each_sg(fd_prot->prot_sg, sg, fd_prot->prot_sg_nents, i) {
-
-                       len = min_t(u32, PAGE_SIZE, size);
-                       sg_set_buf(sg, buf, len);
-                       size -= len;
-                       buf += len;
-               }
+               sg_init_table(fd_prot->prot_sg, fd_prot->prot_sg_nents);
+               sg_set_buf(fd_prot->prot_sg, buf, prot_size);
        }
 
        if (is_write) {
@@ -318,7 +310,7 @@ static int fd_do_prot_rw(struct se_cmd *cmd, struct fd_prot *fd_prot,
 
        if (is_write || ret < 0) {
                kfree(fd_prot->prot_sg);
-               vfree(fd_prot->prot_buf);
+               kfree(fd_prot->prot_buf);
        }
 
        return ret;
@@ -331,36 +323,33 @@ static int fd_do_rw(struct se_cmd *cmd, struct scatterlist *sgl,
        struct fd_dev *dev = FD_DEV(se_dev);
        struct file *fd = dev->fd_file;
        struct scatterlist *sg;
-       struct iovec *iov;
-       mm_segment_t old_fs;
+       struct iov_iter iter;
+       struct bio_vec *bvec;
+       ssize_t len = 0;
        loff_t pos = (cmd->t_task_lba * se_dev->dev_attrib.block_size);
        int ret = 0, i;
 
-       iov = kzalloc(sizeof(struct iovec) * sgl_nents, GFP_KERNEL);
-       if (!iov) {
+       bvec = kcalloc(sgl_nents, sizeof(struct bio_vec), GFP_KERNEL);
+       if (!bvec) {
                pr_err("Unable to allocate fd_do_readv iov[]\n");
                return -ENOMEM;
        }
 
        for_each_sg(sgl, sg, sgl_nents, i) {
-               iov[i].iov_len = sg->length;
-               iov[i].iov_base = kmap(sg_page(sg)) + sg->offset;
-       }
+               bvec[i].bv_page = sg_page(sg);
+               bvec[i].bv_len = sg->length;
+               bvec[i].bv_offset = sg->offset;
 
-       old_fs = get_fs();
-       set_fs(get_ds());
+               len += sg->length;
+       }
 
+       iov_iter_bvec(&iter, ITER_BVEC, bvec, sgl_nents, len);
        if (is_write)
-               ret = vfs_writev(fd, &iov[0], sgl_nents, &pos);
+               ret = vfs_iter_write(fd, &iter, &pos);
        else
-               ret = vfs_readv(fd, &iov[0], sgl_nents, &pos);
-
-       set_fs(old_fs);
-
-       for_each_sg(sgl, sg, sgl_nents, i)
-               kunmap(sg_page(sg));
+               ret = vfs_iter_read(fd, &iter, &pos);
 
-       kfree(iov);
+       kfree(bvec);
 
        if (is_write) {
                if (ret < 0 || ret != cmd->data_length) {
@@ -436,59 +425,17 @@ fd_execute_sync_cache(struct se_cmd *cmd)
        return 0;
 }
 
-static unsigned char *
-fd_setup_write_same_buf(struct se_cmd *cmd, struct scatterlist *sg,
-                   unsigned int len)
-{
-       struct se_device *se_dev = cmd->se_dev;
-       unsigned int block_size = se_dev->dev_attrib.block_size;
-       unsigned int i = 0, end;
-       unsigned char *buf, *p, *kmap_buf;
-
-       buf = kzalloc(min_t(unsigned int, len, PAGE_SIZE), GFP_KERNEL);
-       if (!buf) {
-               pr_err("Unable to allocate fd_execute_write_same buf\n");
-               return NULL;
-       }
-
-       kmap_buf = kmap(sg_page(sg)) + sg->offset;
-       if (!kmap_buf) {
-               pr_err("kmap() failed in fd_setup_write_same\n");
-               kfree(buf);
-               return NULL;
-       }
-       /*
-        * Fill local *buf to contain multiple WRITE_SAME blocks up to
-        * min(len, PAGE_SIZE)
-        */
-       p = buf;
-       end = min_t(unsigned int, len, PAGE_SIZE);
-
-       while (i < end) {
-               memcpy(p, kmap_buf, block_size);
-
-               i += block_size;
-               p += block_size;
-       }
-       kunmap(sg_page(sg));
-
-       return buf;
-}
-
 static sense_reason_t
 fd_execute_write_same(struct se_cmd *cmd)
 {
        struct se_device *se_dev = cmd->se_dev;
        struct fd_dev *fd_dev = FD_DEV(se_dev);
-       struct file *f = fd_dev->fd_file;
-       struct scatterlist *sg;
-       struct iovec *iov;
-       mm_segment_t old_fs;
-       sector_t nolb = sbc_get_write_same_sectors(cmd);
        loff_t pos = cmd->t_task_lba * se_dev->dev_attrib.block_size;
-       unsigned int len, len_tmp, iov_num;
-       int i, rc;
-       unsigned char *buf;
+       sector_t nolb = sbc_get_write_same_sectors(cmd);
+       struct iov_iter iter;
+       struct bio_vec *bvec;
+       unsigned int len = 0, i;
+       ssize_t ret;
 
        if (!nolb) {
                target_complete_cmd(cmd, SAM_STAT_GOOD);
@@ -499,56 +446,92 @@ fd_execute_write_same(struct se_cmd *cmd)
                       " backends not supported\n");
                return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
        }
-       sg = &cmd->t_data_sg[0];
 
        if (cmd->t_data_nents > 1 ||
-           sg->length != cmd->se_dev->dev_attrib.block_size) {
+           cmd->t_data_sg[0].length != cmd->se_dev->dev_attrib.block_size) {
                pr_err("WRITE_SAME: Illegal SGL t_data_nents: %u length: %u"
-                       " block_size: %u\n", cmd->t_data_nents, sg->length,
+                       " block_size: %u\n",
+                       cmd->t_data_nents,
+                       cmd->t_data_sg[0].length,
                        cmd->se_dev->dev_attrib.block_size);
                return TCM_INVALID_CDB_FIELD;
        }
 
-       len = len_tmp = nolb * se_dev->dev_attrib.block_size;
-       iov_num = DIV_ROUND_UP(len, PAGE_SIZE);
-
-       buf = fd_setup_write_same_buf(cmd, sg, len);
-       if (!buf)
+       bvec = kcalloc(nolb, sizeof(struct bio_vec), GFP_KERNEL);
+       if (!bvec)
                return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 
-       iov = vzalloc(sizeof(struct iovec) * iov_num);
-       if (!iov) {
-               pr_err("Unable to allocate fd_execute_write_same iovecs\n");
-               kfree(buf);
+       for (i = 0; i < nolb; i++) {
+               bvec[i].bv_page = sg_page(&cmd->t_data_sg[0]);
+               bvec[i].bv_len = cmd->t_data_sg[0].length;
+               bvec[i].bv_offset = cmd->t_data_sg[0].offset;
+
+               len += se_dev->dev_attrib.block_size;
+       }
+
+       iov_iter_bvec(&iter, ITER_BVEC, bvec, nolb, len);
+       ret = vfs_iter_write(fd_dev->fd_file, &iter, &pos);
+
+       kfree(bvec);
+       if (ret < 0 || ret != len) {
+               pr_err("vfs_iter_write() returned %zd for write same\n", ret);
                return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
        }
-       /*
-        * Map the single fabric received scatterlist block now populated
-        * in *buf into each iovec for I/O submission.
-        */
-       for (i = 0; i < iov_num; i++) {
-               iov[i].iov_base = buf;
-               iov[i].iov_len = min_t(unsigned int, len_tmp, PAGE_SIZE);
-               len_tmp -= iov[i].iov_len;
+
+       target_complete_cmd(cmd, SAM_STAT_GOOD);
+       return 0;
+}
+
+static int
+fd_do_prot_fill(struct se_device *se_dev, sector_t lba, sector_t nolb,
+               void *buf, size_t bufsize)
+{
+       struct fd_dev *fd_dev = FD_DEV(se_dev);
+       struct file *prot_fd = fd_dev->fd_prot_file;
+       sector_t prot_length, prot;
+       loff_t pos = lba * se_dev->prot_length;
+
+       if (!prot_fd) {
+               pr_err("Unable to locate fd_dev->fd_prot_file\n");
+               return -ENODEV;
        }
 
-       old_fs = get_fs();
-       set_fs(get_ds());
-       rc = vfs_writev(f, &iov[0], iov_num, &pos);
-       set_fs(old_fs);
+       prot_length = nolb * se_dev->prot_length;
 
-       vfree(iov);
-       kfree(buf);
+       for (prot = 0; prot < prot_length;) {
+               sector_t len = min_t(sector_t, bufsize, prot_length - prot);
+               ssize_t ret = kernel_write(prot_fd, buf, len, pos + prot);
 
-       if (rc < 0 || rc != len) {
-               pr_err("vfs_writev() returned %d for write same\n", rc);
-               return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+               if (ret != len) {
+                       pr_err("vfs_write to prot file failed: %zd\n", ret);
+                       return ret < 0 ? ret : -ENODEV;
+               }
+               prot += ret;
        }
 
-       target_complete_cmd(cmd, SAM_STAT_GOOD);
        return 0;
 }
 
+static int
+fd_do_prot_unmap(struct se_cmd *cmd, sector_t lba, sector_t nolb)
+{
+       void *buf;
+       int rc;
+
+       buf = (void *)__get_free_page(GFP_KERNEL);
+       if (!buf) {
+               pr_err("Unable to allocate FILEIO prot buf\n");
+               return -ENOMEM;
+       }
+       memset(buf, 0xff, PAGE_SIZE);
+
+       rc = fd_do_prot_fill(cmd->se_dev, lba, nolb, buf, PAGE_SIZE);
+
+       free_page((unsigned long)buf);
+
+       return rc;
+}
+
 static sense_reason_t
 fd_do_unmap(struct se_cmd *cmd, void *priv, sector_t lba, sector_t nolb)
 {
@@ -556,6 +539,12 @@ fd_do_unmap(struct se_cmd *cmd, void *priv, sector_t lba, sector_t nolb)
        struct inode *inode = file->f_mapping->host;
        int ret;
 
+       if (cmd->se_dev->dev_attrib.pi_prot_type) {
+               ret = fd_do_prot_unmap(cmd, lba, nolb);
+               if (ret)
+                       return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+       }
+
        if (S_ISBLK(inode->i_mode)) {
                /* The backend is block device, use discard */
                struct block_device *bdev = inode->i_bdev;
@@ -595,7 +584,7 @@ fd_execute_write_same_unmap(struct se_cmd *cmd)
        struct file *file = fd_dev->fd_file;
        sector_t lba = cmd->t_task_lba;
        sector_t nolb = sbc_get_write_same_sectors(cmd);
-       int ret;
+       sense_reason_t ret;
 
        if (!nolb) {
                target_complete_cmd(cmd, SAM_STAT_GOOD);
@@ -643,7 +632,7 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
        if (data_direction == DMA_FROM_DEVICE) {
                memset(&fd_prot, 0, sizeof(struct fd_prot));
 
-               if (cmd->prot_type) {
+               if (cmd->prot_type && dev->dev_attrib.pi_prot_type) {
                        ret = fd_do_prot_rw(cmd, &fd_prot, false);
                        if (ret < 0)
                                return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
@@ -651,23 +640,23 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
 
                ret = fd_do_rw(cmd, sgl, sgl_nents, 0);
 
-               if (ret > 0 && cmd->prot_type) {
+               if (ret > 0 && cmd->prot_type && dev->dev_attrib.pi_prot_type) {
                        u32 sectors = cmd->data_length / dev->dev_attrib.block_size;
 
                        rc = sbc_dif_verify_read(cmd, cmd->t_task_lba, sectors,
                                                 0, fd_prot.prot_sg, 0);
                        if (rc) {
                                kfree(fd_prot.prot_sg);
-                               vfree(fd_prot.prot_buf);
+                               kfree(fd_prot.prot_buf);
                                return rc;
                        }
                        kfree(fd_prot.prot_sg);
-                       vfree(fd_prot.prot_buf);
+                       kfree(fd_prot.prot_buf);
                }
        } else {
                memset(&fd_prot, 0, sizeof(struct fd_prot));
 
-               if (cmd->prot_type) {
+               if (cmd->prot_type && dev->dev_attrib.pi_prot_type) {
                        u32 sectors = cmd->data_length / dev->dev_attrib.block_size;
 
                        ret = fd_do_prot_rw(cmd, &fd_prot, false);
@@ -678,7 +667,7 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
                                                  0, fd_prot.prot_sg, 0);
                        if (rc) {
                                kfree(fd_prot.prot_sg);
-                               vfree(fd_prot.prot_buf);
+                               kfree(fd_prot.prot_buf);
                                return rc;
                        }
                }
@@ -705,7 +694,7 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
                        vfs_fsync_range(fd_dev->fd_file, start, end, 1);
                }
 
-               if (ret > 0 && cmd->prot_type) {
+               if (ret > 0 && cmd->prot_type && dev->dev_attrib.pi_prot_type) {
                        ret = fd_do_prot_rw(cmd, &fd_prot, true);
                        if (ret < 0)
                                return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
@@ -714,7 +703,7 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
 
        if (ret < 0) {
                kfree(fd_prot.prot_sg);
-               vfree(fd_prot.prot_buf);
+               kfree(fd_prot.prot_buf);
                return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
        }
 
@@ -878,48 +867,28 @@ static int fd_init_prot(struct se_device *dev)
 
 static int fd_format_prot(struct se_device *dev)
 {
-       struct fd_dev *fd_dev = FD_DEV(dev);
-       struct file *prot_fd = fd_dev->fd_prot_file;
-       sector_t prot_length, prot;
        unsigned char *buf;
-       loff_t pos = 0;
        int unit_size = FDBD_FORMAT_UNIT_SIZE * dev->dev_attrib.block_size;
-       int rc, ret = 0, size, len;
+       int ret;
 
        if (!dev->dev_attrib.pi_prot_type) {
                pr_err("Unable to format_prot while pi_prot_type == 0\n");
                return -ENODEV;
        }
-       if (!prot_fd) {
-               pr_err("Unable to locate fd_dev->fd_prot_file\n");
-               return -ENODEV;
-       }
 
        buf = vzalloc(unit_size);
        if (!buf) {
                pr_err("Unable to allocate FILEIO prot buf\n");
                return -ENOMEM;
        }
-       prot_length = (dev->transport->get_blocks(dev) + 1) * dev->prot_length;
-       size = prot_length;
 
        pr_debug("Using FILEIO prot_length: %llu\n",
-                (unsigned long long)prot_length);
+                (unsigned long long)(dev->transport->get_blocks(dev) + 1) *
+                                       dev->prot_length);
 
        memset(buf, 0xff, unit_size);
-       for (prot = 0; prot < prot_length; prot += unit_size) {
-               len = min(unit_size, size);
-               rc = kernel_write(prot_fd, buf, len, pos);
-               if (rc != len) {
-                       pr_err("vfs_write to prot file failed: %d\n", rc);
-                       ret = -ENODEV;
-                       goto out;
-               }
-               pos += len;
-               size -= len;
-       }
-
-out:
+       ret = fd_do_prot_fill(dev, 0, dev->transport->get_blocks(dev) + 1,
+                             buf, unit_size);
        vfree(buf);
        return ret;
 }
index d4a4b0fb444a12907fac835f6a3db03600b722fa..1b7947c2510fc8c65872127738c83ccbb34cf6a3 100644 (file)
@@ -444,7 +444,7 @@ iblock_execute_write_same_unmap(struct se_cmd *cmd)
        struct block_device *bdev = IBLOCK_DEV(cmd->se_dev)->ibd_bd;
        sector_t lba = cmd->t_task_lba;
        sector_t nolb = sbc_get_write_same_sectors(cmd);
-       int ret;
+       sense_reason_t ret;
 
        ret = iblock_do_unmap(cmd, bdev, lba, nolb);
        if (ret)
@@ -774,7 +774,7 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
                sg_num--;
        }
 
-       if (cmd->prot_type) {
+       if (cmd->prot_type && dev->dev_attrib.pi_prot_type) {
                int rc = iblock_alloc_bip(cmd, bio_start);
                if (rc)
                        goto fail_put_bios;
index 60381db9002622bd1c11e68ded07f78648e1fec2..874a9bc988d807a615a9ed7516041bfe54176c4b 100644 (file)
@@ -4,7 +4,13 @@
 /* target_core_alua.c */
 extern struct t10_alua_lu_gp *default_lu_gp;
 
+/* target_core_configfs.c */
+extern struct configfs_subsystem *target_core_subsystem[];
+
 /* target_core_device.c */
+extern struct mutex g_device_mutex;
+extern struct list_head g_device_list;
+
 struct se_dev_entry *core_get_se_deve_from_rtpi(struct se_node_acl *, u16);
 int    core_free_device_list_for_node(struct se_node_acl *,
                struct se_portal_group *);
index 2de6fb8cee8d83b8338472ee2a51dd02c078e833..c1aa9655e96ec13881bdee2040254887fde0e903 100644 (file)
@@ -78,6 +78,22 @@ enum preempt_type {
 static void __core_scsi3_complete_pro_release(struct se_device *, struct se_node_acl *,
                                              struct t10_pr_registration *, int, int);
 
+static int is_reservation_holder(
+       struct t10_pr_registration *pr_res_holder,
+       struct t10_pr_registration *pr_reg)
+{
+       int pr_res_type;
+
+       if (pr_res_holder) {
+               pr_res_type = pr_res_holder->pr_res_type;
+
+               return pr_res_holder == pr_reg ||
+                      pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG ||
+                      pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_ALLREG;
+       }
+       return 0;
+}
+
 static sense_reason_t
 target_scsi2_reservation_check(struct se_cmd *cmd)
 {
@@ -664,7 +680,7 @@ static struct t10_pr_registration *__core_scsi3_alloc_registration(
        struct se_dev_entry *deve_tmp;
        struct se_node_acl *nacl_tmp;
        struct se_port *port, *port_tmp;
-       struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo;
+       const struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo;
        struct t10_pr_registration *pr_reg, *pr_reg_atp, *pr_reg_tmp, *pr_reg_tmp_safe;
        int ret;
        /*
@@ -963,7 +979,7 @@ int core_scsi3_check_aptpl_registration(
 }
 
 static void __core_scsi3_dump_registration(
-       struct target_core_fabric_ops *tfo,
+       const struct target_core_fabric_ops *tfo,
        struct se_device *dev,
        struct se_node_acl *nacl,
        struct t10_pr_registration *pr_reg,
@@ -1004,7 +1020,7 @@ static void __core_scsi3_add_registration(
        enum register_type register_type,
        int register_move)
 {
-       struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo;
+       const struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo;
        struct t10_pr_registration *pr_reg_tmp, *pr_reg_tmp_safe;
        struct t10_reservation *pr_tmpl = &dev->t10_pr;
 
@@ -1220,8 +1236,10 @@ static void __core_scsi3_free_registration(
        struct t10_pr_registration *pr_reg,
        struct list_head *preempt_and_abort_list,
        int dec_holders)
+       __releases(&pr_tmpl->registration_lock)
+       __acquires(&pr_tmpl->registration_lock)
 {
-       struct target_core_fabric_ops *tfo =
+       const struct target_core_fabric_ops *tfo =
                        pr_reg->pr_reg_nacl->se_tpg->se_tpg_tfo;
        struct t10_reservation *pr_tmpl = &dev->t10_pr;
        char i_buf[PR_REG_ISID_ID_LEN];
@@ -1445,7 +1463,7 @@ core_scsi3_decode_spec_i_port(
        struct t10_pr_registration *pr_reg_tmp, *pr_reg_tmp_safe;
        LIST_HEAD(tid_dest_list);
        struct pr_transport_id_holder *tidh_new, *tidh, *tidh_tmp;
-       struct target_core_fabric_ops *tmp_tf_ops;
+       const struct target_core_fabric_ops *tmp_tf_ops;
        unsigned char *buf;
        unsigned char *ptr, *i_str = NULL, proto_ident, tmp_proto_ident;
        char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN];
@@ -2287,7 +2305,6 @@ core_scsi3_pro_reserve(struct se_cmd *cmd, int type, int scope, u64 res_key)
        spin_lock(&dev->dev_reservation_lock);
        pr_res_holder = dev->dev_pr_res_holder;
        if (pr_res_holder) {
-               int pr_res_type = pr_res_holder->pr_res_type;
                /*
                 * From spc4r17 Section 5.7.9: Reserving:
                 *
@@ -2298,9 +2315,7 @@ core_scsi3_pro_reserve(struct se_cmd *cmd, int type, int scope, u64 res_key)
                 * the logical unit, then the command shall be completed with
                 * RESERVATION CONFLICT status.
                 */
-               if ((pr_res_holder != pr_reg) &&
-                   (pr_res_type != PR_TYPE_WRITE_EXCLUSIVE_ALLREG) &&
-                   (pr_res_type != PR_TYPE_EXCLUSIVE_ACCESS_ALLREG)) {
+               if (!is_reservation_holder(pr_res_holder, pr_reg)) {
                        struct se_node_acl *pr_res_nacl = pr_res_holder->pr_reg_nacl;
                        pr_err("SPC-3 PR: Attempted RESERVE from"
                                " [%s]: %s while reservation already held by"
@@ -2409,7 +2424,7 @@ static void __core_scsi3_complete_pro_release(
        int explicit,
        int unreg)
 {
-       struct target_core_fabric_ops *tfo = se_nacl->se_tpg->se_tpg_tfo;
+       const struct target_core_fabric_ops *tfo = se_nacl->se_tpg->se_tpg_tfo;
        char i_buf[PR_REG_ISID_ID_LEN];
        int pr_res_type = 0, pr_res_scope = 0;
 
@@ -2477,7 +2492,6 @@ core_scsi3_emulate_pro_release(struct se_cmd *cmd, int type, int scope,
        struct se_lun *se_lun = cmd->se_lun;
        struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_res_holder;
        struct t10_reservation *pr_tmpl = &dev->t10_pr;
-       int all_reg = 0;
        sense_reason_t ret = 0;
 
        if (!se_sess || !se_lun) {
@@ -2514,13 +2528,9 @@ core_scsi3_emulate_pro_release(struct se_cmd *cmd, int type, int scope,
                spin_unlock(&dev->dev_reservation_lock);
                goto out_put_pr_reg;
        }
-       if ((pr_res_holder->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG) ||
-           (pr_res_holder->pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_ALLREG))
-               all_reg = 1;
 
-       if ((all_reg == 0) && (pr_res_holder != pr_reg)) {
+       if (!is_reservation_holder(pr_res_holder, pr_reg)) {
                /*
-                * Non 'All Registrants' PR Type cases..
                 * Release request from a registered I_T nexus that is not a
                 * persistent reservation holder. return GOOD status.
                 */
@@ -2726,7 +2736,7 @@ static void __core_scsi3_complete_pro_preempt(
        enum preempt_type preempt_type)
 {
        struct se_node_acl *nacl = pr_reg->pr_reg_nacl;
-       struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo;
+       const struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo;
        char i_buf[PR_REG_ISID_ID_LEN];
 
        memset(i_buf, 0, PR_REG_ISID_ID_LEN);
@@ -3111,7 +3121,7 @@ core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key,
        struct se_node_acl *pr_res_nacl, *pr_reg_nacl, *dest_node_acl = NULL;
        struct se_port *se_port;
        struct se_portal_group *se_tpg, *dest_se_tpg = NULL;
-       struct target_core_fabric_ops *dest_tf_ops = NULL, *tf_ops;
+       const struct target_core_fabric_ops *dest_tf_ops = NULL, *tf_ops;
        struct t10_pr_registration *pr_reg, *pr_res_holder, *dest_pr_reg;
        struct t10_reservation *pr_tmpl = &dev->t10_pr;
        unsigned char *buf;
@@ -3375,7 +3385,7 @@ after_iport_check:
         * From spc4r17 section 5.7.8  Table 50 --
         *      Register behaviors for a REGISTER AND MOVE service action
         */
-       if (pr_res_holder != pr_reg) {
+       if (!is_reservation_holder(pr_res_holder, pr_reg)) {
                pr_warn("SPC-3 PR REGISTER_AND_MOVE: Calling I_T"
                        " Nexus is not reservation holder\n");
                spin_unlock(&dev->dev_reservation_lock);
index 98e83ac5661bcfe5b3b7b98d6c9fbf21bb27c14e..a263bf5fab8d4538384f557aef1a3df7df3d9792 100644 (file)
@@ -139,10 +139,22 @@ static int rd_allocate_sgl_table(struct rd_dev *rd_dev, struct rd_dev_sg_table *
        unsigned char *p;
 
        while (total_sg_needed) {
+               unsigned int chain_entry = 0;
+
                sg_per_table = (total_sg_needed > max_sg_per_table) ?
                        max_sg_per_table : total_sg_needed;
 
-               sg = kzalloc(sg_per_table * sizeof(struct scatterlist),
+#ifdef CONFIG_ARCH_HAS_SG_CHAIN
+
+               /*
+                * Reserve extra element for chain entry
+                */
+               if (sg_per_table < total_sg_needed)
+                       chain_entry = 1;
+
+#endif /* CONFIG_ARCH_HAS_SG_CHAIN */
+
+               sg = kcalloc(sg_per_table + chain_entry, sizeof(*sg),
                                GFP_KERNEL);
                if (!sg) {
                        pr_err("Unable to allocate scatterlist array"
@@ -150,7 +162,16 @@ static int rd_allocate_sgl_table(struct rd_dev *rd_dev, struct rd_dev_sg_table *
                        return -ENOMEM;
                }
 
-               sg_init_table(sg, sg_per_table);
+               sg_init_table(sg, sg_per_table + chain_entry);
+
+#ifdef CONFIG_ARCH_HAS_SG_CHAIN
+
+               if (i > 0) {
+                       sg_chain(sg_table[i - 1].sg_table,
+                                max_sg_per_table + 1, sg);
+               }
+
+#endif /* CONFIG_ARCH_HAS_SG_CHAIN */
 
                sg_table[i].sg_table = sg;
                sg_table[i].rd_sg_count = sg_per_table;
@@ -382,6 +403,76 @@ static struct rd_dev_sg_table *rd_get_prot_table(struct rd_dev *rd_dev, u32 page
        return NULL;
 }
 
+typedef sense_reason_t (*dif_verify)(struct se_cmd *, sector_t, unsigned int,
+                                    unsigned int, struct scatterlist *, int);
+
+static sense_reason_t rd_do_prot_rw(struct se_cmd *cmd, dif_verify dif_verify)
+{
+       struct se_device *se_dev = cmd->se_dev;
+       struct rd_dev *dev = RD_DEV(se_dev);
+       struct rd_dev_sg_table *prot_table;
+       bool need_to_release = false;
+       struct scatterlist *prot_sg;
+       u32 sectors = cmd->data_length / se_dev->dev_attrib.block_size;
+       u32 prot_offset, prot_page;
+       u32 prot_npages __maybe_unused;
+       u64 tmp;
+       sense_reason_t rc = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+
+       tmp = cmd->t_task_lba * se_dev->prot_length;
+       prot_offset = do_div(tmp, PAGE_SIZE);
+       prot_page = tmp;
+
+       prot_table = rd_get_prot_table(dev, prot_page);
+       if (!prot_table)
+               return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+
+       prot_sg = &prot_table->sg_table[prot_page -
+                                       prot_table->page_start_offset];
+
+#ifndef CONFIG_ARCH_HAS_SG_CHAIN
+
+       prot_npages = DIV_ROUND_UP(prot_offset + sectors * se_dev->prot_length,
+                                  PAGE_SIZE);
+
+       /*
+        * Allocate temporaly contiguous scatterlist entries if prot pages
+        * straddles multiple scatterlist tables.
+        */
+       if (prot_table->page_end_offset < prot_page + prot_npages - 1) {
+               int i;
+
+               prot_sg = kcalloc(prot_npages, sizeof(*prot_sg), GFP_KERNEL);
+               if (!prot_sg)
+                       return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+
+               need_to_release = true;
+               sg_init_table(prot_sg, prot_npages);
+
+               for (i = 0; i < prot_npages; i++) {
+                       if (prot_page + i > prot_table->page_end_offset) {
+                               prot_table = rd_get_prot_table(dev,
+                                                               prot_page + i);
+                               if (!prot_table) {
+                                       kfree(prot_sg);
+                                       return rc;
+                               }
+                               sg_unmark_end(&prot_sg[i - 1]);
+                       }
+                       prot_sg[i] = prot_table->sg_table[prot_page + i -
+                                               prot_table->page_start_offset];
+               }
+       }
+
+#endif /* !CONFIG_ARCH_HAS_SG_CHAIN */
+
+       rc = dif_verify(cmd, cmd->t_task_lba, sectors, 0, prot_sg, prot_offset);
+       if (need_to_release)
+               kfree(prot_sg);
+
+       return rc;
+}
+
 static sense_reason_t
 rd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
              enum dma_data_direction data_direction)
@@ -419,24 +510,9 @@ rd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
                        data_direction == DMA_FROM_DEVICE ? "Read" : "Write",
                        cmd->t_task_lba, rd_size, rd_page, rd_offset);
 
-       if (cmd->prot_type && data_direction == DMA_TO_DEVICE) {
-               struct rd_dev_sg_table *prot_table;
-               struct scatterlist *prot_sg;
-               u32 sectors = cmd->data_length / se_dev->dev_attrib.block_size;
-               u32 prot_offset, prot_page;
-
-               tmp = cmd->t_task_lba * se_dev->prot_length;
-               prot_offset = do_div(tmp, PAGE_SIZE);
-               prot_page = tmp;
-
-               prot_table = rd_get_prot_table(dev, prot_page);
-               if (!prot_table)
-                       return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-
-               prot_sg = &prot_table->sg_table[prot_page - prot_table->page_start_offset];
-
-               rc = sbc_dif_verify_write(cmd, cmd->t_task_lba, sectors, 0,
-                                         prot_sg, prot_offset);
+       if (cmd->prot_type && se_dev->dev_attrib.pi_prot_type &&
+           data_direction == DMA_TO_DEVICE) {
+               rc = rd_do_prot_rw(cmd, sbc_dif_verify_write);
                if (rc)
                        return rc;
        }
@@ -502,24 +578,9 @@ rd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
        }
        sg_miter_stop(&m);
 
-       if (cmd->prot_type && data_direction == DMA_FROM_DEVICE) {
-               struct rd_dev_sg_table *prot_table;
-               struct scatterlist *prot_sg;
-               u32 sectors = cmd->data_length / se_dev->dev_attrib.block_size;
-               u32 prot_offset, prot_page;
-
-               tmp = cmd->t_task_lba * se_dev->prot_length;
-               prot_offset = do_div(tmp, PAGE_SIZE);
-               prot_page = tmp;
-
-               prot_table = rd_get_prot_table(dev, prot_page);
-               if (!prot_table)
-                       return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-
-               prot_sg = &prot_table->sg_table[prot_page - prot_table->page_start_offset];
-
-               rc = sbc_dif_verify_read(cmd, cmd->t_task_lba, sectors, 0,
-                                        prot_sg, prot_offset);
+       if (cmd->prot_type && se_dev->dev_attrib.pi_prot_type &&
+           data_direction == DMA_FROM_DEVICE) {
+               rc = rd_do_prot_rw(cmd, sbc_dif_verify_read);
                if (rc)
                        return rc;
        }
index 3e729741111075cf4828a46ac2f434414e70faf1..8855781ac653026aa0b513340b150e5f33f05f28 100644 (file)
@@ -93,6 +93,8 @@ sbc_emulate_readcapacity_16(struct se_cmd *cmd)
 {
        struct se_device *dev = cmd->se_dev;
        struct se_session *sess = cmd->se_sess;
+       int pi_prot_type = dev->dev_attrib.pi_prot_type;
+
        unsigned char *rbuf;
        unsigned char buf[32];
        unsigned long long blocks = dev->transport->get_blocks(dev);
@@ -114,8 +116,15 @@ sbc_emulate_readcapacity_16(struct se_cmd *cmd)
         * Set P_TYPE and PROT_EN bits for DIF support
         */
        if (sess->sup_prot_ops & (TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS)) {
-               if (dev->dev_attrib.pi_prot_type)
-                       buf[12] = (dev->dev_attrib.pi_prot_type - 1) << 1 | 0x1;
+               /*
+                * Only override a device's pi_prot_type if no T10-PI is
+                * available, and sess_prot_type has been explicitly enabled.
+                */
+               if (!pi_prot_type)
+                       pi_prot_type = sess->sess_prot_type;
+
+               if (pi_prot_type)
+                       buf[12] = (pi_prot_type - 1) << 1 | 0x1;
        }
 
        if (dev->transport->get_lbppbe)
@@ -312,7 +321,7 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *o
        return 0;
 }
 
-static sense_reason_t xdreadwrite_callback(struct se_cmd *cmd)
+static sense_reason_t xdreadwrite_callback(struct se_cmd *cmd, bool success)
 {
        unsigned char *buf, *addr;
        struct scatterlist *sg;
@@ -376,7 +385,7 @@ sbc_execute_rw(struct se_cmd *cmd)
                               cmd->data_direction);
 }
 
-static sense_reason_t compare_and_write_post(struct se_cmd *cmd)
+static sense_reason_t compare_and_write_post(struct se_cmd *cmd, bool success)
 {
        struct se_device *dev = cmd->se_dev;
 
@@ -399,7 +408,7 @@ static sense_reason_t compare_and_write_post(struct se_cmd *cmd)
        return TCM_NO_SENSE;
 }
 
-static sense_reason_t compare_and_write_callback(struct se_cmd *cmd)
+static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool success)
 {
        struct se_device *dev = cmd->se_dev;
        struct scatterlist *write_sg = NULL, *sg;
@@ -414,10 +423,15 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd)
 
        /*
         * Handle early failure in transport_generic_request_failure(),
-        * which will not have taken ->caw_mutex yet..
+        * which will not have taken ->caw_sem yet..
         */
-       if (!cmd->t_data_sg || !cmd->t_bidi_data_sg)
+       if (!success && (!cmd->t_data_sg || !cmd->t_bidi_data_sg))
                return TCM_NO_SENSE;
+       /*
+        * Handle special case for zero-length COMPARE_AND_WRITE
+        */
+       if (!cmd->data_length)
+               goto out;
        /*
         * Immediately exit + release dev->caw_sem if command has already
         * been failed with a non-zero SCSI status.
@@ -581,12 +595,13 @@ sbc_compare_and_write(struct se_cmd *cmd)
 }
 
 static int
-sbc_set_prot_op_checks(u8 protect, enum target_prot_type prot_type,
+sbc_set_prot_op_checks(u8 protect, bool fabric_prot, enum target_prot_type prot_type,
                       bool is_write, struct se_cmd *cmd)
 {
        if (is_write) {
-               cmd->prot_op = protect ? TARGET_PROT_DOUT_PASS :
-                                        TARGET_PROT_DOUT_INSERT;
+               cmd->prot_op = fabric_prot ? TARGET_PROT_DOUT_STRIP :
+                              protect ? TARGET_PROT_DOUT_PASS :
+                              TARGET_PROT_DOUT_INSERT;
                switch (protect) {
                case 0x0:
                case 0x3:
@@ -610,8 +625,9 @@ sbc_set_prot_op_checks(u8 protect, enum target_prot_type prot_type,
                        return -EINVAL;
                }
        } else {
-               cmd->prot_op = protect ? TARGET_PROT_DIN_PASS :
-                                        TARGET_PROT_DIN_STRIP;
+               cmd->prot_op = fabric_prot ? TARGET_PROT_DIN_INSERT :
+                              protect ? TARGET_PROT_DIN_PASS :
+                              TARGET_PROT_DIN_STRIP;
                switch (protect) {
                case 0x0:
                case 0x1:
@@ -644,11 +660,15 @@ sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb,
               u32 sectors, bool is_write)
 {
        u8 protect = cdb[1] >> 5;
+       int sp_ops = cmd->se_sess->sup_prot_ops;
+       int pi_prot_type = dev->dev_attrib.pi_prot_type;
+       bool fabric_prot = false;
 
        if (!cmd->t_prot_sg || !cmd->t_prot_nents) {
-               if (protect && !dev->dev_attrib.pi_prot_type) {
-                       pr_err("CDB contains protect bit, but device does not"
-                              " advertise PROTECT=1 feature bit\n");
+               if (unlikely(protect &&
+                   !dev->dev_attrib.pi_prot_type && !cmd->se_sess->sess_prot_type)) {
+                       pr_err("CDB contains protect bit, but device + fabric does"
+                              " not advertise PROTECT=1 feature bit\n");
                        return TCM_INVALID_CDB_FIELD;
                }
                if (cmd->prot_pto)
@@ -669,15 +689,32 @@ sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb,
                cmd->reftag_seed = cmd->t_task_lba;
                break;
        case TARGET_DIF_TYPE0_PROT:
+               /*
+                * See if the fabric supports T10-PI, and the session has been
+                * configured to allow export PROTECT=1 feature bit with backend
+                * devices that don't support T10-PI.
+                */
+               fabric_prot = is_write ?
+                             !!(sp_ops & (TARGET_PROT_DOUT_PASS | TARGET_PROT_DOUT_STRIP)) :
+                             !!(sp_ops & (TARGET_PROT_DIN_PASS | TARGET_PROT_DIN_INSERT));
+
+               if (fabric_prot && cmd->se_sess->sess_prot_type) {
+                       pi_prot_type = cmd->se_sess->sess_prot_type;
+                       break;
+               }
+               if (!protect)
+                       return TCM_NO_SENSE;
+               /* Fallthrough */
        default:
-               return TCM_NO_SENSE;
+               pr_err("Unable to determine pi_prot_type for CDB: 0x%02x "
+                      "PROTECT: 0x%02x\n", cdb[0], protect);
+               return TCM_INVALID_CDB_FIELD;
        }
 
-       if (sbc_set_prot_op_checks(protect, dev->dev_attrib.pi_prot_type,
-                                  is_write, cmd))
+       if (sbc_set_prot_op_checks(protect, fabric_prot, pi_prot_type, is_write, cmd))
                return TCM_INVALID_CDB_FIELD;
 
-       cmd->prot_type = dev->dev_attrib.pi_prot_type;
+       cmd->prot_type = pi_prot_type;
        cmd->prot_length = dev->prot_length * sectors;
 
        /**
@@ -1166,14 +1203,16 @@ sbc_dif_generate(struct se_cmd *cmd)
                        sdt = paddr + offset;
                        sdt->guard_tag = cpu_to_be16(crc_t10dif(daddr + j,
                                                dev->dev_attrib.block_size));
-                       if (dev->dev_attrib.pi_prot_type == TARGET_DIF_TYPE1_PROT)
+                       if (cmd->prot_type == TARGET_DIF_TYPE1_PROT)
                                sdt->ref_tag = cpu_to_be32(sector & 0xffffffff);
                        sdt->app_tag = 0;
 
-                       pr_debug("DIF WRITE INSERT sector: %llu guard_tag: 0x%04x"
+                       pr_debug("DIF %s INSERT sector: %llu guard_tag: 0x%04x"
                                 " app_tag: 0x%04x ref_tag: %u\n",
-                                (unsigned long long)sector, sdt->guard_tag,
-                                sdt->app_tag, be32_to_cpu(sdt->ref_tag));
+                                (cmd->data_direction == DMA_TO_DEVICE) ?
+                                "WRITE" : "READ", (unsigned long long)sector,
+                                sdt->guard_tag, sdt->app_tag,
+                                be32_to_cpu(sdt->ref_tag));
 
                        sector++;
                        offset += sizeof(struct se_dif_v1_tuple);
@@ -1185,12 +1224,16 @@ sbc_dif_generate(struct se_cmd *cmd)
 }
 
 static sense_reason_t
-sbc_dif_v1_verify(struct se_device *dev, struct se_dif_v1_tuple *sdt,
+sbc_dif_v1_verify(struct se_cmd *cmd, struct se_dif_v1_tuple *sdt,
                  const void *p, sector_t sector, unsigned int ei_lba)
 {
+       struct se_device *dev = cmd->se_dev;
        int block_size = dev->dev_attrib.block_size;
        __be16 csum;
 
+       if (!(cmd->prot_checks & TARGET_DIF_CHECK_GUARD))
+               goto check_ref;
+
        csum = cpu_to_be16(crc_t10dif(p, block_size));
 
        if (sdt->guard_tag != csum) {
@@ -1200,7 +1243,11 @@ sbc_dif_v1_verify(struct se_device *dev, struct se_dif_v1_tuple *sdt,
                return TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED;
        }
 
-       if (dev->dev_attrib.pi_prot_type == TARGET_DIF_TYPE1_PROT &&
+check_ref:
+       if (!(cmd->prot_checks & TARGET_DIF_CHECK_REFTAG))
+               return 0;
+
+       if (cmd->prot_type == TARGET_DIF_TYPE1_PROT &&
            be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) {
                pr_err("DIFv1 Type 1 reference failed on sector: %llu tag: 0x%08x"
                       " sector MSB: 0x%08x\n", (unsigned long long)sector,
@@ -1208,7 +1255,7 @@ sbc_dif_v1_verify(struct se_device *dev, struct se_dif_v1_tuple *sdt,
                return TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED;
        }
 
-       if (dev->dev_attrib.pi_prot_type == TARGET_DIF_TYPE2_PROT &&
+       if (cmd->prot_type == TARGET_DIF_TYPE2_PROT &&
            be32_to_cpu(sdt->ref_tag) != ei_lba) {
                pr_err("DIFv1 Type 2 reference failed on sector: %llu tag: 0x%08x"
                       " ei_lba: 0x%08x\n", (unsigned long long)sector,
@@ -1229,6 +1276,9 @@ sbc_dif_copy_prot(struct se_cmd *cmd, unsigned int sectors, bool read,
        unsigned int i, len, left;
        unsigned int offset = sg_off;
 
+       if (!sg)
+               return;
+
        left = sectors * dev->prot_length;
 
        for_each_sg(cmd->t_prot_sg, psg, cmd->t_prot_nents, i) {
@@ -1292,7 +1342,7 @@ sbc_dif_verify_write(struct se_cmd *cmd, sector_t start, unsigned int sectors,
                                 (unsigned long long)sector, sdt->guard_tag,
                                 sdt->app_tag, be32_to_cpu(sdt->ref_tag));
 
-                       rc = sbc_dif_v1_verify(dev, sdt, daddr + j, sector,
+                       rc = sbc_dif_v1_verify(cmd, sdt, daddr + j, sector,
                                               ei_lba);
                        if (rc) {
                                kunmap_atomic(paddr);
@@ -1309,6 +1359,9 @@ sbc_dif_verify_write(struct se_cmd *cmd, sector_t start, unsigned int sectors,
                kunmap_atomic(paddr);
                kunmap_atomic(daddr);
        }
+       if (!sg)
+               return 0;
+
        sbc_dif_copy_prot(cmd, sectors, false, sg, sg_off);
 
        return 0;
@@ -1353,7 +1406,7 @@ __sbc_dif_verify_read(struct se_cmd *cmd, sector_t start, unsigned int sectors,
                                continue;
                        }
 
-                       rc = sbc_dif_v1_verify(dev, sdt, daddr + j, sector,
+                       rc = sbc_dif_v1_verify(cmd, sdt, daddr + j, sector,
                                               ei_lba);
                        if (rc) {
                                kunmap_atomic(paddr);
index 6c8bd6bc175ca48fb9d33063dc3f3b8185d19876..7912aa1243857a8968dcff5fa0f643b8e249dd6e 100644 (file)
@@ -103,10 +103,12 @@ spc_emulate_inquiry_std(struct se_cmd *cmd, unsigned char *buf)
                buf[5] |= 0x8;
        /*
         * Set Protection (PROTECT) bit when DIF has been enabled on the
-        * device, and the transport supports VERIFY + PASS.
+        * device, and the fabric supports VERIFY + PASS.  Also report
+        * PROTECT=1 if sess_prot_type has been configured to allow T10-PI
+        * to unprotected devices.
         */
        if (sess->sup_prot_ops & (TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS)) {
-               if (dev->dev_attrib.pi_prot_type)
+               if (dev->dev_attrib.pi_prot_type || cmd->se_sess->sess_prot_type)
                        buf[5] |= 0x1;
        }
 
@@ -467,9 +469,11 @@ spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf)
         * only for TYPE3 protection.
         */
        if (sess->sup_prot_ops & (TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS)) {
-               if (dev->dev_attrib.pi_prot_type == TARGET_DIF_TYPE1_PROT)
+               if (dev->dev_attrib.pi_prot_type == TARGET_DIF_TYPE1_PROT ||
+                   cmd->se_sess->sess_prot_type == TARGET_DIF_TYPE1_PROT)
                        buf[4] = 0x5;
-               else if (dev->dev_attrib.pi_prot_type == TARGET_DIF_TYPE3_PROT)
+               else if (dev->dev_attrib.pi_prot_type == TARGET_DIF_TYPE3_PROT ||
+                       cmd->se_sess->sess_prot_type == TARGET_DIF_TYPE3_PROT)
                        buf[4] = 0x4;
        }
 
@@ -861,7 +865,7 @@ static int spc_modesense_control(struct se_cmd *cmd, u8 pc, u8 *p)
         * TAG field.
         */
        if (sess->sup_prot_ops & (TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS)) {
-               if (dev->dev_attrib.pi_prot_type)
+               if (dev->dev_attrib.pi_prot_type || sess->sess_prot_type)
                        p[5] |= 0x80;
        }
 
@@ -1099,7 +1103,7 @@ static sense_reason_t spc_emulate_modeselect(struct se_cmd *cmd)
        unsigned char *buf;
        unsigned char tbuf[SE_MODE_PAGE_BUF];
        int length;
-       int ret = 0;
+       sense_reason_t ret = 0;
        int i;
 
        if (!cmd->data_length) {
index fa5e157db47be242f855a9c1a209ea9e08e60c3d..315ec3458eebc03a15a1715a065eee3dd72b9a2d 100644 (file)
@@ -125,8 +125,8 @@ void core_tmr_abort_task(
                if (dev != se_cmd->se_dev)
                        continue;
 
-               /* skip se_cmd associated with tmr */
-               if (tmr->task_cmd == se_cmd)
+               /* skip task management functions, including tmr->task_cmd */
+               if (se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)
                        continue;
 
                ref_tag = se_cmd->se_tfo->get_task_tag(se_cmd);
index 0696de9553d3d7dea5b8e0f1f874f5f5b91ab821..47f064415bf661fc2bb39b27762f870c4acabc56 100644 (file)
@@ -672,7 +672,7 @@ static int core_tpg_setup_virtual_lun0(struct se_portal_group *se_tpg)
 }
 
 int core_tpg_register(
-       struct target_core_fabric_ops *tfo,
+       const struct target_core_fabric_ops *tfo,
        struct se_wwn *se_wwn,
        struct se_portal_group *se_tpg,
        void *tpg_fabric_ptr,
index ac3cbabdbdf0243ecbfd91c01e331ee3e0013a1a..3fe5cb240b6f6a5b4c8a3fb42396b77dd5701f74 100644 (file)
@@ -322,6 +322,7 @@ void __transport_register_session(
        struct se_session *se_sess,
        void *fabric_sess_ptr)
 {
+       const struct target_core_fabric_ops *tfo = se_tpg->se_tpg_tfo;
        unsigned char buf[PR_REG_ISID_LEN];
 
        se_sess->se_tpg = se_tpg;
@@ -333,6 +334,21 @@ void __transport_register_session(
         * eg: *NOT* discovery sessions.
         */
        if (se_nacl) {
+               /*
+                *
+                * Determine if fabric allows for T10-PI feature bits exposed to
+                * initiators for device backends with !dev->dev_attrib.pi_prot_type.
+                *
+                * If so, then always save prot_type on a per se_node_acl node
+                * basis and re-instate the previous sess_prot_type to avoid
+                * disabling PI from below any previously initiator side
+                * registered LUNs.
+                */
+               if (se_nacl->saved_prot_type)
+                       se_sess->sess_prot_type = se_nacl->saved_prot_type;
+               else if (tfo->tpg_check_prot_fabric_only)
+                       se_sess->sess_prot_type = se_nacl->saved_prot_type =
+                                       tfo->tpg_check_prot_fabric_only(se_tpg);
                /*
                 * If the fabric module supports an ISID based TransportID,
                 * save this value in binary from the fabric I_T Nexus now.
@@ -404,6 +420,30 @@ void target_put_session(struct se_session *se_sess)
 }
 EXPORT_SYMBOL(target_put_session);
 
+ssize_t target_show_dynamic_sessions(struct se_portal_group *se_tpg, char *page)
+{
+       struct se_session *se_sess;
+       ssize_t len = 0;
+
+       spin_lock_bh(&se_tpg->session_lock);
+       list_for_each_entry(se_sess, &se_tpg->tpg_sess_list, sess_list) {
+               if (!se_sess->se_node_acl)
+                       continue;
+               if (!se_sess->se_node_acl->dynamic_node_acl)
+                       continue;
+               if (strlen(se_sess->se_node_acl->initiatorname) + 1 + len > PAGE_SIZE)
+                       break;
+
+               len += snprintf(page + len, PAGE_SIZE - len, "%s\n",
+                               se_sess->se_node_acl->initiatorname);
+               len += 1; /* Include NULL terminator */
+       }
+       spin_unlock_bh(&se_tpg->session_lock);
+
+       return len;
+}
+EXPORT_SYMBOL(target_show_dynamic_sessions);
+
 static void target_complete_nacl(struct kref *kref)
 {
        struct se_node_acl *nacl = container_of(kref,
@@ -462,7 +502,7 @@ EXPORT_SYMBOL(transport_free_session);
 void transport_deregister_session(struct se_session *se_sess)
 {
        struct se_portal_group *se_tpg = se_sess->se_tpg;
-       struct target_core_fabric_ops *se_tfo;
+       const struct target_core_fabric_ops *se_tfo;
        struct se_node_acl *se_nacl;
        unsigned long flags;
        bool comp_nacl = true;
@@ -1118,7 +1158,7 @@ target_cmd_size_check(struct se_cmd *cmd, unsigned int size)
  */
 void transport_init_se_cmd(
        struct se_cmd *cmd,
-       struct target_core_fabric_ops *tfo,
+       const struct target_core_fabric_ops *tfo,
        struct se_session *se_sess,
        u32 data_length,
        int data_direction,
@@ -1570,6 +1610,8 @@ EXPORT_SYMBOL(target_submit_tmr);
  * has completed.
  */
 bool target_stop_cmd(struct se_cmd *cmd, unsigned long *flags)
+       __releases(&cmd->t_state_lock)
+       __acquires(&cmd->t_state_lock)
 {
        bool was_active = false;
 
@@ -1615,11 +1657,11 @@ void transport_generic_request_failure(struct se_cmd *cmd,
        transport_complete_task_attr(cmd);
        /*
         * Handle special case for COMPARE_AND_WRITE failure, where the
-        * callback is expected to drop the per device ->caw_mutex.
+        * callback is expected to drop the per device ->caw_sem.
         */
        if ((cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) &&
             cmd->transport_complete_callback)
-               cmd->transport_complete_callback(cmd);
+               cmd->transport_complete_callback(cmd, false);
 
        switch (sense_reason) {
        case TCM_NON_EXISTENT_LUN:
@@ -1706,6 +1748,41 @@ void __target_execute_cmd(struct se_cmd *cmd)
        }
 }
 
+static int target_write_prot_action(struct se_cmd *cmd)
+{
+       u32 sectors;
+       /*
+        * Perform WRITE_INSERT of PI using software emulation when backend
+        * device has PI enabled, if the transport has not already generated
+        * PI using hardware WRITE_INSERT offload.
+        */
+       switch (cmd->prot_op) {
+       case TARGET_PROT_DOUT_INSERT:
+               if (!(cmd->se_sess->sup_prot_ops & TARGET_PROT_DOUT_INSERT))
+                       sbc_dif_generate(cmd);
+               break;
+       case TARGET_PROT_DOUT_STRIP:
+               if (cmd->se_sess->sup_prot_ops & TARGET_PROT_DOUT_STRIP)
+                       break;
+
+               sectors = cmd->data_length >> ilog2(cmd->se_dev->dev_attrib.block_size);
+               cmd->pi_err = sbc_dif_verify_write(cmd, cmd->t_task_lba,
+                                                  sectors, 0, NULL, 0);
+               if (unlikely(cmd->pi_err)) {
+                       spin_lock_irq(&cmd->t_state_lock);
+                       cmd->transport_state &= ~CMD_T_BUSY|CMD_T_SENT;
+                       spin_unlock_irq(&cmd->t_state_lock);
+                       transport_generic_request_failure(cmd, cmd->pi_err);
+                       return -1;
+               }
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
 static bool target_handle_task_attr(struct se_cmd *cmd)
 {
        struct se_device *dev = cmd->se_dev;
@@ -1785,15 +1862,9 @@ void target_execute_cmd(struct se_cmd *cmd)
        cmd->t_state = TRANSPORT_PROCESSING;
        cmd->transport_state |= CMD_T_ACTIVE|CMD_T_BUSY|CMD_T_SENT;
        spin_unlock_irq(&cmd->t_state_lock);
-       /*
-        * Perform WRITE_INSERT of PI using software emulation when backend
-        * device has PI enabled, if the transport has not already generated
-        * PI using hardware WRITE_INSERT offload.
-        */
-       if (cmd->prot_op == TARGET_PROT_DOUT_INSERT) {
-               if (!(cmd->se_sess->sup_prot_ops & TARGET_PROT_DOUT_INSERT))
-                       sbc_dif_generate(cmd);
-       }
+
+       if (target_write_prot_action(cmd))
+               return;
 
        if (target_handle_task_attr(cmd)) {
                spin_lock_irq(&cmd->t_state_lock);
@@ -1919,16 +1990,28 @@ static void transport_handle_queue_full(
        schedule_work(&cmd->se_dev->qf_work_queue);
 }
 
-static bool target_check_read_strip(struct se_cmd *cmd)
+static bool target_read_prot_action(struct se_cmd *cmd)
 {
        sense_reason_t rc;
 
-       if (!(cmd->se_sess->sup_prot_ops & TARGET_PROT_DIN_STRIP)) {
-               rc = sbc_dif_read_strip(cmd);
-               if (rc) {
-                       cmd->pi_err = rc;
-                       return true;
+       switch (cmd->prot_op) {
+       case TARGET_PROT_DIN_STRIP:
+               if (!(cmd->se_sess->sup_prot_ops & TARGET_PROT_DIN_STRIP)) {
+                       rc = sbc_dif_read_strip(cmd);
+                       if (rc) {
+                               cmd->pi_err = rc;
+                               return true;
+                       }
                }
+               break;
+       case TARGET_PROT_DIN_INSERT:
+               if (cmd->se_sess->sup_prot_ops & TARGET_PROT_DIN_INSERT)
+                       break;
+
+               sbc_dif_generate(cmd);
+               break;
+       default:
+               break;
        }
 
        return false;
@@ -1975,8 +2058,12 @@ static void target_complete_ok_work(struct work_struct *work)
        if (cmd->transport_complete_callback) {
                sense_reason_t rc;
 
-               rc = cmd->transport_complete_callback(cmd);
+               rc = cmd->transport_complete_callback(cmd, true);
                if (!rc && !(cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE_POST)) {
+                       if ((cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) &&
+                           !cmd->data_length)
+                               goto queue_rsp;
+
                        return;
                } else if (rc) {
                        ret = transport_send_check_condition_and_sense(cmd,
@@ -1990,6 +2077,7 @@ static void target_complete_ok_work(struct work_struct *work)
                }
        }
 
+queue_rsp:
        switch (cmd->data_direction) {
        case DMA_FROM_DEVICE:
                spin_lock(&cmd->se_lun->lun_sep_lock);
@@ -2003,8 +2091,7 @@ static void target_complete_ok_work(struct work_struct *work)
                 * backend had PI enabled, if the transport will not be
                 * performing hardware READ_STRIP offload.
                 */
-               if (cmd->prot_op == TARGET_PROT_DIN_STRIP &&
-                   target_check_read_strip(cmd)) {
+               if (target_read_prot_action(cmd)) {
                        ret = transport_send_check_condition_and_sense(cmd,
                                                cmd->pi_err, 0);
                        if (ret == -EAGAIN || ret == -ENOMEM)
@@ -2094,6 +2181,16 @@ static inline void transport_reset_sgl_orig(struct se_cmd *cmd)
 static inline void transport_free_pages(struct se_cmd *cmd)
 {
        if (cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC) {
+               /*
+                * Release special case READ buffer payload required for
+                * SG_TO_MEM_NOALLOC to function with COMPARE_AND_WRITE
+                */
+               if (cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) {
+                       transport_free_sgl(cmd->t_bidi_data_sg,
+                                          cmd->t_bidi_data_nents);
+                       cmd->t_bidi_data_sg = NULL;
+                       cmd->t_bidi_data_nents = 0;
+               }
                transport_reset_sgl_orig(cmd);
                return;
        }
@@ -2246,6 +2343,7 @@ sense_reason_t
 transport_generic_new_cmd(struct se_cmd *cmd)
 {
        int ret = 0;
+       bool zero_flag = !(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB);
 
        /*
         * Determine is the TCM fabric module has already allocated physical
@@ -2254,7 +2352,6 @@ transport_generic_new_cmd(struct se_cmd *cmd)
         */
        if (!(cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC) &&
            cmd->data_length) {
-               bool zero_flag = !(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB);
 
                if ((cmd->se_cmd_flags & SCF_BIDI) ||
                    (cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE)) {
@@ -2285,6 +2382,20 @@ transport_generic_new_cmd(struct se_cmd *cmd)
                                       cmd->data_length, zero_flag);
                if (ret < 0)
                        return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+       } else if ((cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) &&
+                   cmd->data_length) {
+               /*
+                * Special case for COMPARE_AND_WRITE with fabrics
+                * using SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC.
+                */
+               u32 caw_length = cmd->t_task_nolb *
+                                cmd->se_dev->dev_attrib.block_size;
+
+               ret = target_alloc_sgl(&cmd->t_bidi_data_sg,
+                                      &cmd->t_bidi_data_nents,
+                                      caw_length, zero_flag);
+               if (ret < 0)
+                       return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
        }
        /*
         * If this command is not a write we can execute it right here,
@@ -2376,10 +2487,8 @@ int target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd,
         * fabric acknowledgement that requires two target_put_sess_cmd()
         * invocations before se_cmd descriptor release.
         */
-       if (ack_kref) {
+       if (ack_kref)
                kref_get(&se_cmd->cmd_kref);
-               se_cmd->se_cmd_flags |= SCF_ACK_KREF;
-       }
 
        spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
        if (se_sess->sess_tearing_down) {
@@ -2398,6 +2507,7 @@ out:
 EXPORT_SYMBOL(target_get_sess_cmd);
 
 static void target_release_cmd_kref(struct kref *kref)
+               __releases(&se_cmd->se_sess->sess_cmd_lock)
 {
        struct se_cmd *se_cmd = container_of(kref, struct se_cmd, cmd_kref);
        struct se_session *se_sess = se_cmd->se_sess;
index 1a1bcf71ec9dbf3ed5ae05cbfadcf71a29a33f87..dbc872a6c9816e95211f5b93bb9f623233d249ba 100644 (file)
@@ -344,8 +344,11 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
 
                entry = (void *) mb + CMDR_OFF + cmd_head;
                tcmu_flush_dcache_range(entry, sizeof(*entry));
-               tcmu_hdr_set_op(&entry->hdr, TCMU_OP_PAD);
-               tcmu_hdr_set_len(&entry->hdr, pad_size);
+               tcmu_hdr_set_op(&entry->hdr.len_op, TCMU_OP_PAD);
+               tcmu_hdr_set_len(&entry->hdr.len_op, pad_size);
+               entry->hdr.cmd_id = 0; /* not used for PAD */
+               entry->hdr.kflags = 0;
+               entry->hdr.uflags = 0;
 
                UPDATE_HEAD(mb->cmd_head, pad_size, udev->cmdr_size);
 
@@ -355,9 +358,11 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
 
        entry = (void *) mb + CMDR_OFF + cmd_head;
        tcmu_flush_dcache_range(entry, sizeof(*entry));
-       tcmu_hdr_set_op(&entry->hdr, TCMU_OP_CMD);
-       tcmu_hdr_set_len(&entry->hdr, command_size);
-       entry->cmd_id = tcmu_cmd->cmd_id;
+       tcmu_hdr_set_op(&entry->hdr.len_op, TCMU_OP_CMD);
+       tcmu_hdr_set_len(&entry->hdr.len_op, command_size);
+       entry->hdr.cmd_id = tcmu_cmd->cmd_id;
+       entry->hdr.kflags = 0;
+       entry->hdr.uflags = 0;
 
        /*
         * Fix up iovecs, and handle if allocation in data ring wrapped.
@@ -376,7 +381,8 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
 
                /* Even iov_base is relative to mb_addr */
                iov->iov_len = copy_bytes;
-               iov->iov_base = (void *) udev->data_off + udev->data_head;
+               iov->iov_base = (void __user *) udev->data_off +
+                                               udev->data_head;
                iov_cnt++;
                iov++;
 
@@ -388,7 +394,8 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
                        copy_bytes = sg->length - copy_bytes;
 
                        iov->iov_len = copy_bytes;
-                       iov->iov_base = (void *) udev->data_off + udev->data_head;
+                       iov->iov_base = (void __user *) udev->data_off +
+                                                       udev->data_head;
 
                        if (se_cmd->data_direction == DMA_TO_DEVICE) {
                                to = (void *) mb + udev->data_off + udev->data_head;
@@ -405,6 +412,8 @@ static int tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
                kunmap_atomic(from);
        }
        entry->req.iov_cnt = iov_cnt;
+       entry->req.iov_bidi_cnt = 0;
+       entry->req.iov_dif_cnt = 0;
 
        /* All offsets relative to mb_addr, not start of entry! */
        cdb_off = CMDR_OFF + cmd_head + base_command_size;
@@ -462,6 +471,17 @@ static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry *
                return;
        }
 
+       if (entry->hdr.uflags & TCMU_UFLAG_UNKNOWN_OP) {
+               UPDATE_HEAD(udev->data_tail, cmd->data_length, udev->data_size);
+               pr_warn("TCMU: Userspace set UNKNOWN_OP flag on se_cmd %p\n",
+                       cmd->se_cmd);
+               transport_generic_request_failure(cmd->se_cmd,
+                       TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE);
+               cmd->se_cmd = NULL;
+               kmem_cache_free(tcmu_cmd_cache, cmd);
+               return;
+       }
+
        if (entry->rsp.scsi_status == SAM_STAT_CHECK_CONDITION) {
                memcpy(se_cmd->sense_buffer, entry->rsp.sense_buffer,
                               se_cmd->scsi_sense_length);
@@ -540,14 +560,16 @@ static unsigned int tcmu_handle_completions(struct tcmu_dev *udev)
 
                tcmu_flush_dcache_range(entry, sizeof(*entry));
 
-               if (tcmu_hdr_get_op(&entry->hdr) == TCMU_OP_PAD) {
-                       UPDATE_HEAD(udev->cmdr_last_cleaned, tcmu_hdr_get_len(&entry->hdr), udev->cmdr_size);
+               if (tcmu_hdr_get_op(entry->hdr.len_op) == TCMU_OP_PAD) {
+                       UPDATE_HEAD(udev->cmdr_last_cleaned,
+                                   tcmu_hdr_get_len(entry->hdr.len_op),
+                                   udev->cmdr_size);
                        continue;
                }
-               WARN_ON(tcmu_hdr_get_op(&entry->hdr) != TCMU_OP_CMD);
+               WARN_ON(tcmu_hdr_get_op(entry->hdr.len_op) != TCMU_OP_CMD);
 
                spin_lock(&udev->commands_lock);
-               cmd = idr_find(&udev->commands, entry->cmd_id);
+               cmd = idr_find(&udev->commands, entry->hdr.cmd_id);
                if (cmd)
                        idr_remove(&udev->commands, cmd->cmd_id);
                spin_unlock(&udev->commands_lock);
@@ -560,7 +582,9 @@ static unsigned int tcmu_handle_completions(struct tcmu_dev *udev)
 
                tcmu_handle_completion(cmd, entry);
 
-               UPDATE_HEAD(udev->cmdr_last_cleaned, tcmu_hdr_get_len(&entry->hdr), udev->cmdr_size);
+               UPDATE_HEAD(udev->cmdr_last_cleaned,
+                           tcmu_hdr_get_len(entry->hdr.len_op),
+                           udev->cmdr_size);
 
                handled++;
        }
@@ -838,14 +862,14 @@ static int tcmu_configure_device(struct se_device *dev)
        udev->data_size = TCMU_RING_SIZE - CMDR_SIZE;
 
        mb = udev->mb_addr;
-       mb->version = 1;
+       mb->version = TCMU_MAILBOX_VERSION;
        mb->cmdr_off = CMDR_OFF;
        mb->cmdr_size = udev->cmdr_size;
 
        WARN_ON(!PAGE_ALIGNED(udev->data_off));
        WARN_ON(udev->data_size % PAGE_SIZE);
 
-       info->version = "1";
+       info->version = xstr(TCMU_MAILBOX_VERSION);
 
        info->mem[0].name = "tcm-user command & data buffer";
        info->mem[0].addr = (phys_addr_t) udev->mb_addr;
index 33ac39bf75e5e25e58145260718568ff01dac88b..a600ff15dcfd1674140170b0808d494db64333ea 100644 (file)
 #include <target/target_core_fabric.h>
 #include <target/target_core_configfs.h>
 
+#include "target_core_internal.h"
 #include "target_core_pr.h"
 #include "target_core_ua.h"
 #include "target_core_xcopy.h"
 
 static struct workqueue_struct *xcopy_wq = NULL;
-/*
- * From target_core_device.c
- */
-extern struct mutex g_device_mutex;
-extern struct list_head g_device_list;
-/*
- * From target_core_configfs.c
- */
-extern struct configfs_subsystem *target_core_subsystem[];
 
 static int target_xcopy_gen_naa_ieee(struct se_device *dev, unsigned char *buf)
 {
@@ -433,7 +425,7 @@ static int xcopy_pt_queue_status(struct se_cmd *se_cmd)
        return 0;
 }
 
-static struct target_core_fabric_ops xcopy_pt_tfo = {
+static const struct target_core_fabric_ops xcopy_pt_tfo = {
        .get_fabric_name        = xcopy_pt_get_fabric_name,
        .get_task_tag           = xcopy_pt_get_tag,
        .get_cmd_state          = xcopy_pt_get_cmd_state,
@@ -548,33 +540,22 @@ static void target_xcopy_setup_pt_port(
        }
 }
 
-static int target_xcopy_init_pt_lun(
-       struct xcopy_pt_cmd *xpt_cmd,
-       struct xcopy_op *xop,
-       struct se_device *se_dev,
-       struct se_cmd *pt_cmd,
-       bool remote_port)
+static void target_xcopy_init_pt_lun(struct se_device *se_dev,
+               struct se_cmd *pt_cmd, bool remote_port)
 {
        /*
         * Don't allocate + init an pt_cmd->se_lun if honoring local port for
         * reservations.  The pt_cmd->se_lun pointer will be setup from within
         * target_xcopy_setup_pt_port()
         */
-       if (!remote_port) {
-               pt_cmd->se_cmd_flags |= SCF_SE_LUN_CMD | SCF_CMD_XCOPY_PASSTHROUGH;
-               return 0;
+       if (remote_port) {
+               pr_debug("Setup emulated se_dev: %p from se_dev\n",
+                       pt_cmd->se_dev);
+               pt_cmd->se_lun = &se_dev->xcopy_lun;
+               pt_cmd->se_dev = se_dev;
        }
 
-       pt_cmd->se_lun = &se_dev->xcopy_lun;
-       pt_cmd->se_dev = se_dev;
-
-       pr_debug("Setup emulated se_dev: %p from se_dev\n", pt_cmd->se_dev);
-       pt_cmd->se_cmd_flags |= SCF_SE_LUN_CMD | SCF_CMD_XCOPY_PASSTHROUGH;
-
-       pr_debug("Setup emulated se_dev: %p to pt_cmd->se_lun->lun_se_dev\n",
-               pt_cmd->se_lun->lun_se_dev);
-
-       return 0;
+       pt_cmd->se_cmd_flags |= SCF_SE_LUN_CMD;
 }
 
 static int target_xcopy_setup_pt_cmd(
@@ -592,11 +573,8 @@ static int target_xcopy_setup_pt_cmd(
         * Setup LUN+port to honor reservations based upon xop->op_origin for
         * X-COPY PUSH or X-COPY PULL based upon where the CDB was received.
         */
-       rc = target_xcopy_init_pt_lun(xpt_cmd, xop, se_dev, cmd, remote_port);
-       if (rc < 0) {
-               ret = rc;
-               goto out;
-       }
+       target_xcopy_init_pt_lun(se_dev, cmd, remote_port);
+
        xpt_cmd->xcopy_op = xop;
        target_xcopy_setup_pt_port(xpt_cmd, xop, remote_port);
 
index a0bcfd3e7e7d5924b06c56928d8c51989c6c66da..881deb3d499adc57e578ce9af9890953f9281f2a 100644 (file)
@@ -129,7 +129,6 @@ struct ft_cmd {
 
 extern struct mutex ft_lport_lock;
 extern struct fc4_prov ft_prov;
-extern struct target_fabric_configfs *ft_configfs;
 extern unsigned int ft_debug_logging;
 
 /*
index efdcb9663a1a699520d3543b544ebac5c34ad860..65dce1345966e392fe57c6bf7eadd80dc86351cd 100644 (file)
@@ -48,7 +48,7 @@
 
 #include "tcm_fc.h"
 
-struct target_fabric_configfs *ft_configfs;
+static const struct target_core_fabric_ops ft_fabric_ops;
 
 static LIST_HEAD(ft_wwn_list);
 DEFINE_MUTEX(ft_lport_lock);
@@ -337,7 +337,7 @@ static struct se_portal_group *ft_add_tpg(
                return NULL;
        }
 
-       ret = core_tpg_register(&ft_configfs->tf_ops, wwn, &tpg->se_tpg,
+       ret = core_tpg_register(&ft_fabric_ops, wwn, &tpg->se_tpg,
                                tpg, TRANSPORT_TPG_TYPE_NORMAL);
        if (ret < 0) {
                destroy_workqueue(wq);
@@ -507,7 +507,9 @@ static u32 ft_tpg_get_inst_index(struct se_portal_group *se_tpg)
        return tpg->index;
 }
 
-static struct target_core_fabric_ops ft_fabric_ops = {
+static const struct target_core_fabric_ops ft_fabric_ops = {
+       .module =                       THIS_MODULE,
+       .name =                         "fc",
        .get_fabric_name =              ft_get_fabric_name,
        .get_fabric_proto_ident =       fc_get_fabric_proto_ident,
        .tpg_get_wwn =                  ft_get_fabric_wwn,
@@ -552,62 +554,10 @@ static struct target_core_fabric_ops ft_fabric_ops = {
        .fabric_drop_np =               NULL,
        .fabric_make_nodeacl =          &ft_add_acl,
        .fabric_drop_nodeacl =          &ft_del_acl,
-};
-
-static int ft_register_configfs(void)
-{
-       struct target_fabric_configfs *fabric;
-       int ret;
-
-       /*
-        * Register the top level struct config_item_type with TCM core
-        */
-       fabric = target_fabric_configfs_init(THIS_MODULE, "fc");
-       if (IS_ERR(fabric)) {
-               pr_err("%s: target_fabric_configfs_init() failed!\n",
-                      __func__);
-               return PTR_ERR(fabric);
-       }
-       fabric->tf_ops = ft_fabric_ops;
-
-       /*
-        * Setup default attribute lists for various fabric->tf_cit_tmpl
-        */
-       fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = ft_wwn_attrs;
-       fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_nacl_base_cit.ct_attrs =
-                                                   ft_nacl_base_attrs;
-       fabric->tf_cit_tmpl.tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_nacl_auth_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_nacl_param_cit.ct_attrs = NULL;
-       /*
-        * register the fabric for use within TCM
-        */
-       ret = target_fabric_configfs_register(fabric);
-       if (ret < 0) {
-               pr_debug("target_fabric_configfs_register() for"
-                           " FC Target failed!\n");
-               target_fabric_configfs_free(fabric);
-               return -1;
-       }
-
-       /*
-        * Setup our local pointer to *fabric.
-        */
-       ft_configfs = fabric;
-       return 0;
-}
 
-static void ft_deregister_configfs(void)
-{
-       if (!ft_configfs)
-               return;
-       target_fabric_configfs_deregister(ft_configfs);
-       ft_configfs = NULL;
-}
+       .tfc_wwn_attrs                  = ft_wwn_attrs,
+       .tfc_tpg_nacl_base_attrs        = ft_nacl_base_attrs,
+};
 
 static struct notifier_block ft_notifier = {
        .notifier_call = ft_lport_notify
@@ -615,15 +565,24 @@ static struct notifier_block ft_notifier = {
 
 static int __init ft_init(void)
 {
-       if (ft_register_configfs())
-               return -1;
-       if (fc_fc4_register_provider(FC_TYPE_FCP, &ft_prov)) {
-               ft_deregister_configfs();
-               return -1;
-       }
+       int ret;
+
+       ret = target_register_template(&ft_fabric_ops);
+       if (ret)
+               goto out;
+
+       ret = fc_fc4_register_provider(FC_TYPE_FCP, &ft_prov);
+       if (ret)
+               goto out_unregister_template;
+
        blocking_notifier_chain_register(&fc_lport_notifier_head, &ft_notifier);
        fc_lport_iterate(ft_lport_add, NULL);
        return 0;
+
+out_unregister_template:
+       target_unregister_template(&ft_fabric_ops);
+out:
+       return ret;
 }
 
 static void __exit ft_exit(void)
@@ -632,7 +591,7 @@ static void __exit ft_exit(void)
                                           &ft_notifier);
        fc_fc4_deregister_provider(FC_TYPE_FCP, &ft_prov);
        fc_lport_iterate(ft_lport_del, NULL);
-       ft_deregister_configfs();
+       target_unregister_template(&ft_fabric_ops);
        synchronize_rcu();
 }
 
index 071551bf3e9a559ae6ac1177f482ade55067eb42..543b234e70fc33bf728f6b30b66e0ef3048e4e1d 100644 (file)
@@ -41,7 +41,7 @@
 
 static const char hvc_opal_name[] = "hvc_opal";
 
-static struct of_device_id hvc_opal_match[] = {
+static const struct of_device_id hvc_opal_match[] = {
        { .name = "serial", .compatible = "ibm,opal-console-raw" },
        { .name = "serial", .compatible = "ibm,opal-console-hvsi" },
        { },
index f1e57425e39ff00b1a929500f4ea297aba5ae095..5bab1c684bb11024c2e5a7ee143c18aefc54349b 100644 (file)
@@ -299,11 +299,27 @@ static int xen_initial_domain_console_init(void)
        return 0;
 }
 
+static void xen_console_update_evtchn(struct xencons_info *info)
+{
+       if (xen_hvm_domain()) {
+               uint64_t v;
+               int err;
+
+               err = hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN, &v);
+               if (!err && v)
+                       info->evtchn = v;
+       } else
+               info->evtchn = xen_start_info->console.domU.evtchn;
+}
+
 void xen_console_resume(void)
 {
        struct xencons_info *info = vtermno_to_xencons(HVC_COOKIE);
-       if (info != NULL && info->irq)
+       if (info != NULL && info->irq) {
+               if (!xen_initial_domain())
+                       xen_console_update_evtchn(info);
                rebind_evtchn_irq(info->evtchn, info->irq);
+       }
 }
 
 static void xencons_disconnect_backend(struct xencons_info *info)
index c4343764cc5b7c527b85278013c3cbbb62f1cbd8..91abc00aa833b8493fe721e05024cd8368e23aa6 100644 (file)
@@ -2669,7 +2669,7 @@ static inline void muxnet_put(struct gsm_mux_net *mux_net)
 static int gsm_mux_net_start_xmit(struct sk_buff *skb,
                                      struct net_device *net)
 {
-       struct gsm_mux_net *mux_net = (struct gsm_mux_net *)netdev_priv(net);
+       struct gsm_mux_net *mux_net = netdev_priv(net);
        struct gsm_dlci *dlci = mux_net->dlci;
        muxnet_get(mux_net);
 
@@ -2698,7 +2698,7 @@ static void gsm_mux_rx_netchar(struct gsm_dlci *dlci,
 {
        struct net_device *net = dlci->net;
        struct sk_buff *skb;
-       struct gsm_mux_net *mux_net = (struct gsm_mux_net *)netdev_priv(net);
+       struct gsm_mux_net *mux_net = netdev_priv(net);
        muxnet_get(mux_net);
 
        /* Allocate an sk_buff */
@@ -2727,7 +2727,7 @@ static void gsm_mux_rx_netchar(struct gsm_dlci *dlci,
 
 static int gsm_change_mtu(struct net_device *net, int new_mtu)
 {
-       struct gsm_mux_net *mux_net = (struct gsm_mux_net *)netdev_priv(net);
+       struct gsm_mux_net *mux_net = netdev_priv(net);
        if ((new_mtu < 8) || (new_mtu > mux_net->dlci->gsm->mtu))
                return -EINVAL;
        net->mtu = new_mtu;
@@ -2763,7 +2763,7 @@ static void gsm_destroy_network(struct gsm_dlci *dlci)
        pr_debug("destroy network interface");
        if (!dlci->net)
                return;
-       mux_net = (struct gsm_mux_net *)netdev_priv(dlci->net);
+       mux_net = netdev_priv(dlci->net);
        muxnet_put(mux_net);
 }
 
@@ -2801,7 +2801,7 @@ static int gsm_create_network(struct gsm_dlci *dlci, struct gsm_netconfig *nc)
                return -ENOMEM;
        }
        net->mtu = dlci->gsm->mtu;
-       mux_net = (struct gsm_mux_net *)netdev_priv(net);
+       mux_net = netdev_priv(net);
        mux_net->dlci = dlci;
        kref_init(&mux_net->ref);
        strncpy(nc->if_name, net->name, IFNAMSIZ); /* return net name */
@@ -2824,7 +2824,7 @@ static int gsm_create_network(struct gsm_dlci *dlci, struct gsm_netconfig *nc)
 }
 
 /* Line discipline for real tty */
-struct tty_ldisc_ops tty_ldisc_packet = {
+static struct tty_ldisc_ops tty_ldisc_packet = {
        .owner           = THIS_MODULE,
        .magic           = TTY_LDISC_MAGIC,
        .name            = "n_gsm",
index b00836851061e099d517a3600b838b572ef8743d..c43f74c53cd98259056400cc86b9ff355c4993ca 100644 (file)
@@ -21,7 +21,6 @@ struct uart_8250_dma {
 
        /* Filter function */
        dma_filter_fn           fn;
-
        /* Parameter to the filter function */
        void                    *rx_param;
        void                    *tx_param;
@@ -53,7 +52,7 @@ struct old_serial_port {
        unsigned int baud_base;
        unsigned int port;
        unsigned int irq;
-       unsigned int flags;
+       upf_t        flags;
        unsigned char hub6;
        unsigned char io_type;
        unsigned char __iomem *iomem_base;
@@ -85,9 +84,6 @@ struct serial8250_config {
 #define UART_BUG_THRE  (1 << 3)        /* UART has buggy THRE reassertion */
 #define UART_BUG_PARITY        (1 << 4)        /* UART mishandles parity if FIFO enabled */
 
-#define PROBE_RSA      (1 << 0)
-#define PROBE_ANY      (~0)
-
 #define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
 
 #ifdef CONFIG_SERIAL_8250_SHARE_IRQ
@@ -198,3 +194,20 @@ static inline int serial8250_request_dma(struct uart_8250_port *p)
 }
 static inline void serial8250_release_dma(struct uart_8250_port *p) { }
 #endif
+
+static inline int ns16550a_goto_highspeed(struct uart_8250_port *up)
+{
+       unsigned char status;
+
+       status = serial_in(up, 0x04); /* EXCR2 */
+#define PRESL(x) ((x) & 0x30)
+       if (PRESL(status) == 0x10) {
+               /* already in high speed mode */
+               return 0;
+       } else {
+               status &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
+               status |= 0x10;  /* 1.625 divisor for baud_base --> 921600 */
+               serial_out(up, 0x04, status);
+       }
+       return 1;
+}
index deae122c9c4bac6a2bb28d6bbc191bfc18d16747..4506e405c8f3986cb83235dbaf766ed4cc09f0c1 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/tty.h>
 #include <linux/ratelimit.h>
 #include <linux/tty_flip.h>
-#include <linux/serial_core.h>
 #include <linux/serial.h>
 #include <linux/serial_8250.h>
 #include <linux/nmi.h>
@@ -61,7 +60,7 @@ static struct uart_driver serial8250_reg;
 
 static int serial_index(struct uart_port *port)
 {
-       return (serial8250_reg.minor - 64) + port->line;
+       return port->minor - 64;
 }
 
 static unsigned int skip_txen_test; /* force skip of txen test at init time */
@@ -358,34 +357,46 @@ static void default_serial_dl_write(struct uart_8250_port *up, int value)
 #if defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_SERIAL_8250_RT288X)
 
 /* Au1x00/RT288x UART hardware has a weird register layout */
-static const u8 au_io_in_map[] = {
-       [UART_RX]  = 0,
-       [UART_IER] = 2,
-       [UART_IIR] = 3,
-       [UART_LCR] = 5,
-       [UART_MCR] = 6,
-       [UART_LSR] = 7,
-       [UART_MSR] = 8,
+static const s8 au_io_in_map[8] = {
+        0,     /* UART_RX  */
+        2,     /* UART_IER */
+        3,     /* UART_IIR */
+        5,     /* UART_LCR */
+        6,     /* UART_MCR */
+        7,     /* UART_LSR */
+        8,     /* UART_MSR */
+       -1,     /* UART_SCR (unmapped) */
 };
 
-static const u8 au_io_out_map[] = {
-       [UART_TX]  = 1,
-       [UART_IER] = 2,
-       [UART_FCR] = 4,
-       [UART_LCR] = 5,
-       [UART_MCR] = 6,
+static const s8 au_io_out_map[8] = {
+        1,     /* UART_TX  */
+        2,     /* UART_IER */
+        4,     /* UART_FCR */
+        5,     /* UART_LCR */
+        6,     /* UART_MCR */
+       -1,     /* UART_LSR (unmapped) */
+       -1,     /* UART_MSR (unmapped) */
+       -1,     /* UART_SCR (unmapped) */
 };
 
 static unsigned int au_serial_in(struct uart_port *p, int offset)
 {
-       offset = au_io_in_map[offset] << p->regshift;
-       return __raw_readl(p->membase + offset);
+       if (offset >= ARRAY_SIZE(au_io_in_map))
+               return UINT_MAX;
+       offset = au_io_in_map[offset];
+       if (offset < 0)
+               return UINT_MAX;
+       return __raw_readl(p->membase + (offset << p->regshift));
 }
 
 static void au_serial_out(struct uart_port *p, int offset, int value)
 {
-       offset = au_io_out_map[offset] << p->regshift;
-       __raw_writel(value, p->membase + offset);
+       if (offset >= ARRAY_SIZE(au_io_out_map))
+               return;
+       offset = au_io_out_map[offset];
+       if (offset < 0)
+               return;
+       __raw_writel(value, p->membase + (offset << p->regshift));
 }
 
 /* Au1x00 haven't got a standard divisor latch */
@@ -439,6 +450,18 @@ static unsigned int mem32_serial_in(struct uart_port *p, int offset)
        return readl(p->membase + offset);
 }
 
+static void mem32be_serial_out(struct uart_port *p, int offset, int value)
+{
+       offset = offset << p->regshift;
+       iowrite32be(value, p->membase + offset);
+}
+
+static unsigned int mem32be_serial_in(struct uart_port *p, int offset)
+{
+       offset = offset << p->regshift;
+       return ioread32be(p->membase + offset);
+}
+
 static unsigned int io_serial_in(struct uart_port *p, int offset)
 {
        offset = offset << p->regshift;
@@ -477,6 +500,11 @@ static void set_io_from_upio(struct uart_port *p)
                p->serial_out = mem32_serial_out;
                break;
 
+       case UPIO_MEM32BE:
+               p->serial_in = mem32be_serial_in;
+               p->serial_out = mem32be_serial_out;
+               break;
+
 #if defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_SERIAL_8250_RT288X)
        case UPIO_AU:
                p->serial_in = au_serial_in;
@@ -502,6 +530,7 @@ serial_port_out_sync(struct uart_port *p, int offset, int value)
        switch (p->iotype) {
        case UPIO_MEM:
        case UPIO_MEM32:
+       case UPIO_MEM32BE:
        case UPIO_AU:
                p->serial_out(p, offset, value);
                p->serial_in(p, UART_LCR);      /* safe, no side-effects */
@@ -895,7 +924,7 @@ static int broken_efr(struct uart_8250_port *up)
        /*
         * Exar ST16C2550 "A2" devices incorrectly detect as
         * having an EFR, and report an ID of 0x0201.  See
-        * http://linux.derkeiler.com/Mailing-Lists/Kernel/2004-11/4812.html 
+        * http://linux.derkeiler.com/Mailing-Lists/Kernel/2004-11/4812.html
         */
        if (autoconfig_read_divisor_id(up) == 0x0201 && size_fifo(up) == 16)
                return 1;
@@ -903,23 +932,6 @@ static int broken_efr(struct uart_8250_port *up)
        return 0;
 }
 
-static inline int ns16550a_goto_highspeed(struct uart_8250_port *up)
-{
-       unsigned char status;
-
-       status = serial_in(up, 0x04); /* EXCR2 */
-#define PRESL(x) ((x) & 0x30)
-       if (PRESL(status) == 0x10) {
-               /* already in high speed mode */
-               return 0;
-       } else {
-               status &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
-               status |= 0x10;  /* 1.625 divisor for baud_base --> 921600 */
-               serial_out(up, 0x04, status);
-       }
-       return 1;
-}
-
 /*
  * We know that the chip has FIFOs.  Does it have an EFR?  The
  * EFR is located in the same register position as the IIR and
@@ -1122,7 +1134,7 @@ static void autoconfig_16550a(struct uart_8250_port *up)
  * whether or not this UART is a 16550A or not, since this will
  * determine whether or not we can use its FIFO features or not.
  */
-static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
+static void autoconfig(struct uart_8250_port *up)
 {
        unsigned char status1, scratch, scratch2, scratch3;
        unsigned char save_lcr, save_mcr;
@@ -1245,22 +1257,15 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
        /*
         * Only probe for RSA ports if we got the region.
         */
-       if (port->type == PORT_16550A && probeflags & PROBE_RSA) {
-               int i;
-
-               for (i = 0 ; i < probe_rsa_count; ++i) {
-                       if (probe_rsa[i] == port->iobase && __enable_rsa(up)) {
-                               port->type = PORT_RSA;
-                               break;
-                       }
-               }
-       }
+       if (port->type == PORT_16550A && up->probe & UART_PROBE_RSA &&
+           __enable_rsa(up))
+               port->type = PORT_RSA;
 #endif
 
        serial_out(up, UART_LCR, save_lcr);
 
        port->fifosize = uart_config[up->port.type].fifo_size;
-       old_capabilities = up->capabilities; 
+       old_capabilities = up->capabilities;
        up->capabilities = uart_config[port->type].flags;
        up->tx_loadsz = uart_config[port->type].tx_loadsz;
 
@@ -1907,6 +1912,48 @@ static void serial8250_backup_timeout(unsigned long data)
                jiffies + uart_poll_timeout(&up->port) + HZ / 5);
 }
 
+static int univ8250_setup_irq(struct uart_8250_port *up)
+{
+       struct uart_port *port = &up->port;
+       int retval = 0;
+
+       /*
+        * The above check will only give an accurate result the first time
+        * the port is opened so this value needs to be preserved.
+        */
+       if (up->bugs & UART_BUG_THRE) {
+               pr_debug("ttyS%d - using backup timer\n", serial_index(port));
+
+               up->timer.function = serial8250_backup_timeout;
+               up->timer.data = (unsigned long)up;
+               mod_timer(&up->timer, jiffies +
+                         uart_poll_timeout(port) + HZ / 5);
+       }
+
+       /*
+        * If the "interrupt" for this port doesn't correspond with any
+        * hardware interrupt, we use a timer-based system.  The original
+        * driver used to do this with IRQ0.
+        */
+       if (!port->irq) {
+               up->timer.data = (unsigned long)up;
+               mod_timer(&up->timer, jiffies + uart_poll_timeout(port));
+       } else
+               retval = serial_link_irq_chain(up);
+
+       return retval;
+}
+
+static void univ8250_release_irq(struct uart_8250_port *up)
+{
+       struct uart_port *port = &up->port;
+
+       del_timer_sync(&up->timer);
+       up->timer.function = serial8250_timeout;
+       if (port->irq)
+               serial_unlink_irq_chain(up);
+}
+
 static unsigned int serial8250_tx_empty(struct uart_port *port)
 {
        struct uart_8250_port *up = up_to_u8250p(port);
@@ -2211,35 +2258,12 @@ int serial8250_do_startup(struct uart_port *port)
                if ((!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) ||
                    up->port.flags & UPF_BUG_THRE) {
                        up->bugs |= UART_BUG_THRE;
-                       pr_debug("ttyS%d - using backup timer\n",
-                                serial_index(port));
                }
        }
 
-       /*
-        * The above check will only give an accurate result the first time
-        * the port is opened so this value needs to be preserved.
-        */
-       if (up->bugs & UART_BUG_THRE) {
-               up->timer.function = serial8250_backup_timeout;
-               up->timer.data = (unsigned long)up;
-               mod_timer(&up->timer, jiffies +
-                       uart_poll_timeout(port) + HZ / 5);
-       }
-
-       /*
-        * If the "interrupt" for this port doesn't correspond with any
-        * hardware interrupt, we use a timer-based system.  The original
-        * driver used to do this with IRQ0.
-        */
-       if (!port->irq) {
-               up->timer.data = (unsigned long)up;
-               mod_timer(&up->timer, jiffies + uart_poll_timeout(port));
-       } else {
-               retval = serial_link_irq_chain(up);
-               if (retval)
-                       goto out;
-       }
+       retval = up->ops->setup_irq(up);
+       if (retval)
+               goto out;
 
        /*
         * Now, initialize the UART
@@ -2270,7 +2294,7 @@ int serial8250_do_startup(struct uart_port *port)
           is variable. So, let's just don't test if we receive
           TX irq. This way, we'll never enable UART_BUG_TXEN.
         */
-       if (skip_txen_test || up->port.flags & UPF_NO_TXEN_TEST)
+       if (up->port.flags & UPF_NO_TXEN_TEST)
                goto dont_test_tx_en;
 
        /*
@@ -2397,10 +2421,7 @@ void serial8250_do_shutdown(struct uart_port *port)
        serial_port_in(port, UART_RX);
        serial8250_rpm_put(up);
 
-       del_timer_sync(&up->timer);
-       up->timer.function = serial8250_timeout;
-       if (port->irq)
-               serial_unlink_irq_chain(up);
+       up->ops->release_irq(up);
 }
 EXPORT_SYMBOL_GPL(serial8250_do_shutdown);
 
@@ -2719,6 +2740,8 @@ serial8250_pm(struct uart_port *port, unsigned int state,
 
 static unsigned int serial8250_port_size(struct uart_8250_port *pt)
 {
+       if (pt->port.mapsize)
+               return pt->port.mapsize;
        if (pt->port.iotype == UPIO_AU) {
                if (pt->port.type == PORT_RT2880)
                        return 0x100;
@@ -2743,6 +2766,7 @@ static int serial8250_request_std_resource(struct uart_8250_port *up)
        case UPIO_AU:
        case UPIO_TSI:
        case UPIO_MEM32:
+       case UPIO_MEM32BE:
        case UPIO_MEM:
                if (!port->mapbase)
                        break;
@@ -2779,6 +2803,7 @@ static void serial8250_release_std_resource(struct uart_8250_port *up)
        case UPIO_AU:
        case UPIO_TSI:
        case UPIO_MEM32:
+       case UPIO_MEM32BE:
        case UPIO_MEM:
                if (!port->mapbase)
                        break;
@@ -2798,6 +2823,7 @@ static void serial8250_release_std_resource(struct uart_8250_port *up)
        }
 }
 
+#ifdef CONFIG_SERIAL_8250_RSA
 static int serial8250_request_rsa_resource(struct uart_8250_port *up)
 {
        unsigned long start = UART_RSA_BASE << up->port.regshift;
@@ -2832,14 +2858,13 @@ static void serial8250_release_rsa_resource(struct uart_8250_port *up)
                break;
        }
 }
+#endif
 
 static void serial8250_release_port(struct uart_port *port)
 {
        struct uart_8250_port *up = up_to_u8250p(port);
 
        serial8250_release_std_resource(up);
-       if (port->type == PORT_RSA)
-               serial8250_release_rsa_resource(up);
 }
 
 static int serial8250_request_port(struct uart_port *port)
@@ -2851,11 +2876,6 @@ static int serial8250_request_port(struct uart_port *port)
                return -ENODEV;
 
        ret = serial8250_request_std_resource(up);
-       if (ret == 0 && port->type == PORT_RSA) {
-               ret = serial8250_request_rsa_resource(up);
-               if (ret < 0)
-                       serial8250_release_std_resource(up);
-       }
 
        return ret;
 }
@@ -3003,7 +3023,6 @@ static void register_dev_spec_attr_grp(struct uart_8250_port *up)
 static void serial8250_config_port(struct uart_port *port, int flags)
 {
        struct uart_8250_port *up = up_to_u8250p(port);
-       int probeflags = PROBE_ANY;
        int ret;
 
        if (port->type == PORT_8250_CIR)
@@ -3017,15 +3036,11 @@ static void serial8250_config_port(struct uart_port *port, int flags)
        if (ret < 0)
                return;
 
-       ret = serial8250_request_rsa_resource(up);
-       if (ret < 0)
-               probeflags &= ~PROBE_RSA;
-
        if (port->iotype != up->cur_iotype)
                set_io_from_upio(port);
 
        if (flags & UART_CONFIG_TYPE)
-               autoconfig(up, probeflags);
+               autoconfig(up);
 
        /* if access method is AU, it is a 16550 with a quirk */
        if (port->type == PORT_16550A && port->iotype == UPIO_AU)
@@ -3038,8 +3053,6 @@ static void serial8250_config_port(struct uart_port *port, int flags)
        if (port->type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)
                autoconfig_irq(up);
 
-       if (port->type != PORT_RSA && probeflags & PROBE_RSA)
-               serial8250_release_rsa_resource(up);
        if (port->type == PORT_UNKNOWN)
                serial8250_release_std_resource(up);
 
@@ -3073,7 +3086,7 @@ serial8250_type(struct uart_port *port)
        return uart_config[type].name;
 }
 
-static struct uart_ops serial8250_pops = {
+static const struct uart_ops serial8250_pops = {
        .tx_empty       = serial8250_tx_empty,
        .set_mctrl      = serial8250_set_mctrl,
        .get_mctrl      = serial8250_get_mctrl,
@@ -3100,6 +3113,14 @@ static struct uart_ops serial8250_pops = {
 #endif
 };
 
+static const struct uart_ops *base_ops;
+static struct uart_ops univ8250_port_ops;
+
+static const struct uart_8250_ops univ8250_driver_ops = {
+       .setup_irq      = univ8250_setup_irq,
+       .release_irq    = univ8250_release_irq,
+};
+
 static struct uart_8250_port serial8250_ports[UART_NR];
 
 /**
@@ -3130,6 +3151,105 @@ void serial8250_set_isa_configurator(
 }
 EXPORT_SYMBOL(serial8250_set_isa_configurator);
 
+static void serial8250_init_port(struct uart_8250_port *up)
+{
+       struct uart_port *port = &up->port;
+
+       spin_lock_init(&port->lock);
+       port->ops = &serial8250_pops;
+
+       up->cur_iotype = 0xFF;
+}
+
+static void serial8250_set_defaults(struct uart_8250_port *up)
+{
+       struct uart_port *port = &up->port;
+
+       if (up->port.flags & UPF_FIXED_TYPE) {
+               unsigned int type = up->port.type;
+
+               if (!up->port.fifosize)
+                       up->port.fifosize = uart_config[type].fifo_size;
+               if (!up->tx_loadsz)
+                       up->tx_loadsz = uart_config[type].tx_loadsz;
+               if (!up->capabilities)
+                       up->capabilities = uart_config[type].flags;
+       }
+
+       set_io_from_upio(port);
+
+       /* default dma handlers */
+       if (up->dma) {
+               if (!up->dma->tx_dma)
+                       up->dma->tx_dma = serial8250_tx_dma;
+               if (!up->dma->rx_dma)
+                       up->dma->rx_dma = serial8250_rx_dma;
+       }
+}
+
+#ifdef CONFIG_SERIAL_8250_RSA
+
+static void univ8250_config_port(struct uart_port *port, int flags)
+{
+       struct uart_8250_port *up = up_to_u8250p(port);
+
+       up->probe &= ~UART_PROBE_RSA;
+       if (port->type == PORT_RSA) {
+               if (serial8250_request_rsa_resource(up) == 0)
+                       up->probe |= UART_PROBE_RSA;
+       } else if (flags & UART_CONFIG_TYPE) {
+               int i;
+
+               for (i = 0; i < probe_rsa_count; i++) {
+                       if (probe_rsa[i] == up->port.iobase) {
+                               if (serial8250_request_rsa_resource(up) == 0)
+                                       up->probe |= UART_PROBE_RSA;
+                               break;
+                       }
+               }
+       }
+
+       base_ops->config_port(port, flags);
+
+       if (port->type != PORT_RSA && up->probe & UART_PROBE_RSA)
+               serial8250_release_rsa_resource(up);
+}
+
+static int univ8250_request_port(struct uart_port *port)
+{
+       struct uart_8250_port *up = up_to_u8250p(port);
+       int ret;
+
+       ret = base_ops->request_port(port);
+       if (ret == 0 && port->type == PORT_RSA) {
+               ret = serial8250_request_rsa_resource(up);
+               if (ret < 0)
+                       base_ops->release_port(port);
+       }
+
+       return ret;
+}
+
+static void univ8250_release_port(struct uart_port *port)
+{
+       struct uart_8250_port *up = up_to_u8250p(port);
+
+       if (port->type == PORT_RSA)
+               serial8250_release_rsa_resource(up);
+       base_ops->release_port(port);
+}
+
+static void univ8250_rsa_support(struct uart_ops *ops)
+{
+       ops->config_port  = univ8250_config_port;
+       ops->request_port = univ8250_request_port;
+       ops->release_port = univ8250_release_port;
+}
+
+#else
+#define univ8250_rsa_support(x)                do { } while (0)
+#endif /* CONFIG_SERIAL_8250_RSA */
+
 static void __init serial8250_isa_init_ports(void)
 {
        struct uart_8250_port *up;
@@ -3148,21 +3268,27 @@ static void __init serial8250_isa_init_ports(void)
                struct uart_port *port = &up->port;
 
                port->line = i;
-               spin_lock_init(&port->lock);
+               serial8250_init_port(up);
+               if (!base_ops)
+                       base_ops = port->ops;
+               port->ops = &univ8250_port_ops;
 
                init_timer(&up->timer);
                up->timer.function = serial8250_timeout;
-               up->cur_iotype = 0xFF;
+
+               up->ops = &univ8250_driver_ops;
 
                /*
                 * ALPHA_KLUDGE_MCR needs to be killed.
                 */
                up->mcr_mask = ~ALPHA_KLUDGE_MCR;
                up->mcr_force = ALPHA_KLUDGE_MCR;
-
-               port->ops = &serial8250_pops;
        }
 
+       /* chain base port ops to support Remote Supervisor Adapter */
+       univ8250_port_ops = *base_ops;
+       univ8250_rsa_support(&univ8250_port_ops);
+
        if (share_irqs)
                irqflag = IRQF_SHARED;
 
@@ -3180,26 +3306,14 @@ static void __init serial8250_isa_init_ports(void)
                port->membase  = old_serial_port[i].iomem_base;
                port->iotype   = old_serial_port[i].io_type;
                port->regshift = old_serial_port[i].iomem_reg_shift;
-               set_io_from_upio(port);
+               serial8250_set_defaults(up);
+
                port->irqflags |= irqflag;
                if (serial8250_isa_config != NULL)
                        serial8250_isa_config(i, &up->port, &up->capabilities);
-
        }
 }
 
-static void
-serial8250_init_fixed_type_port(struct uart_8250_port *up, unsigned int type)
-{
-       up->port.type = type;
-       if (!up->port.fifosize)
-               up->port.fifosize = uart_config[type].fifo_size;
-       if (!up->tx_loadsz)
-               up->tx_loadsz = uart_config[type].tx_loadsz;
-       if (!up->capabilities)
-               up->capabilities = uart_config[type].flags;
-}
-
 static void __init
 serial8250_register_ports(struct uart_driver *drv, struct device *dev)
 {
@@ -3213,8 +3327,8 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev)
 
                up->port.dev = dev;
 
-               if (up->port.flags & UPF_FIXED_TYPE)
-                       serial8250_init_fixed_type_port(up, up->port.type);
+               if (skip_txen_test)
+                       up->port.flags |= UPF_NO_TXEN_TEST;
 
                uart_add_one_port(drv, &up->port);
        }
@@ -3236,10 +3350,9 @@ static void serial8250_console_putchar(struct uart_port *port, int ch)
  *
  *     The console_lock must be held when we get here.
  */
-static void
-serial8250_console_write(struct console *co, const char *s, unsigned int count)
+static void serial8250_console_write(struct uart_8250_port *up, const char *s,
+                                    unsigned int count)
 {
-       struct uart_8250_port *up = &serial8250_ports[co->index];
        struct uart_port *port = &up->port;
        unsigned long flags;
        unsigned int ier;
@@ -3311,14 +3424,51 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
        serial8250_rpm_put(up);
 }
 
-static int serial8250_console_setup(struct console *co, char *options)
+static void univ8250_console_write(struct console *co, const char *s,
+                                  unsigned int count)
+{
+       struct uart_8250_port *up = &serial8250_ports[co->index];
+
+       serial8250_console_write(up, s, count);
+}
+
+static unsigned int probe_baud(struct uart_port *port)
+{
+       unsigned char lcr, dll, dlm;
+       unsigned int quot;
+
+       lcr = serial_port_in(port, UART_LCR);
+       serial_port_out(port, UART_LCR, lcr | UART_LCR_DLAB);
+       dll = serial_port_in(port, UART_DLL);
+       dlm = serial_port_in(port, UART_DLM);
+       serial_port_out(port, UART_LCR, lcr);
+
+       quot = (dlm << 8) | dll;
+       return (port->uartclk / 16) / quot;
+}
+
+static int serial8250_console_setup(struct uart_port *port, char *options, bool probe)
 {
-       struct uart_port *port;
        int baud = 9600;
        int bits = 8;
        int parity = 'n';
        int flow = 'n';
 
+       if (!port->iobase && !port->membase)
+               return -ENODEV;
+
+       if (options)
+               uart_parse_options(options, &baud, &parity, &bits, &flow);
+       else if (probe)
+               baud = probe_baud(port);
+
+       return uart_set_options(port, port->cons, baud, parity, bits, flow);
+}
+
+static int univ8250_console_setup(struct console *co, char *options)
+{
+       struct uart_port *port;
+
        /*
         * Check whether an invalid uart number has been specified, and
         * if so, search for the first available port that does have
@@ -3327,53 +3477,84 @@ static int serial8250_console_setup(struct console *co, char *options)
        if (co->index >= nr_uarts)
                co->index = 0;
        port = &serial8250_ports[co->index].port;
-       if (!port->iobase && !port->membase)
-               return -ENODEV;
-
-       if (options)
-               uart_parse_options(options, &baud, &parity, &bits, &flow);
+       /* link port to console */
+       port->cons = co;
 
-       return uart_set_options(port, co, baud, parity, bits, flow);
+       return serial8250_console_setup(port, options, false);
 }
 
-static int serial8250_console_early_setup(void)
+/**
+ *     univ8250_console_match - non-standard console matching
+ *     @co:      registering console
+ *     @name:    name from console command line
+ *     @idx:     index from console command line
+ *     @options: ptr to option string from console command line
+ *
+ *     Only attempts to match console command lines of the form:
+ *         console=uart[8250],io|mmio|mmio32,<addr>[,<options>]
+ *         console=uart[8250],0x<addr>[,<options>]
+ *     This form is used to register an initial earlycon boot console and
+ *     replace it with the serial8250_console at 8250 driver init.
+ *
+ *     Performs console setup for a match (as required by interface)
+ *     If no <options> are specified, then assume the h/w is already setup.
+ *
+ *     Returns 0 if console matches; otherwise non-zero to use default matching
+ */
+static int univ8250_console_match(struct console *co, char *name, int idx,
+                                 char *options)
 {
-       return serial8250_find_port_for_earlycon();
+       char match[] = "uart";  /* 8250-specific earlycon name */
+       unsigned char iotype;
+       unsigned long addr;
+       int i;
+
+       if (strncmp(name, match, 4) != 0)
+               return -ENODEV;
+
+       if (uart_parse_earlycon(options, &iotype, &addr, &options))
+               return -ENODEV;
+
+       /* try to match the port specified on the command line */
+       for (i = 0; i < nr_uarts; i++) {
+               struct uart_port *port = &serial8250_ports[i].port;
+
+               if (port->iotype != iotype)
+                       continue;
+               if ((iotype == UPIO_MEM || iotype == UPIO_MEM32) &&
+                   (port->mapbase != addr))
+                       continue;
+               if (iotype == UPIO_PORT && port->iobase != addr)
+                       continue;
+
+               co->index = i;
+               port->cons = co;
+               return serial8250_console_setup(port, options, true);
+       }
+
+       return -ENODEV;
 }
 
-static struct console serial8250_console = {
+static struct console univ8250_console = {
        .name           = "ttyS",
-       .write          = serial8250_console_write,
+       .write          = univ8250_console_write,
        .device         = uart_console_device,
-       .setup          = serial8250_console_setup,
-       .early_setup    = serial8250_console_early_setup,
+       .setup          = univ8250_console_setup,
+       .match          = univ8250_console_match,
        .flags          = CON_PRINTBUFFER | CON_ANYTIME,
        .index          = -1,
        .data           = &serial8250_reg,
 };
 
-static int __init serial8250_console_init(void)
+static int __init univ8250_console_init(void)
 {
        serial8250_isa_init_ports();
-       register_console(&serial8250_console);
+       register_console(&univ8250_console);
        return 0;
 }
-console_initcall(serial8250_console_init);
-
-int serial8250_find_port(struct uart_port *p)
-{
-       int line;
-       struct uart_port *port;
-
-       for (line = 0; line < nr_uarts; line++) {
-               port = &serial8250_ports[line].port;
-               if (uart_match_port(p, port))
-                       return line;
-       }
-       return -ENODEV;
-}
+console_initcall(univ8250_console_init);
 
-#define SERIAL8250_CONSOLE     &serial8250_console
+#define SERIAL8250_CONSOLE     &univ8250_console
 #else
 #define SERIAL8250_CONSOLE     NULL
 #endif
@@ -3412,19 +3593,19 @@ int __init early_serial_setup(struct uart_port *port)
        p->iotype       = port->iotype;
        p->flags        = port->flags;
        p->mapbase      = port->mapbase;
+       p->mapsize      = port->mapsize;
        p->private_data = port->private_data;
        p->type         = port->type;
        p->line         = port->line;
 
-       set_io_from_upio(p);
+       serial8250_set_defaults(up_to_u8250p(p));
+
        if (port->serial_in)
                p->serial_in = port->serial_in;
        if (port->serial_out)
                p->serial_out = port->serial_out;
        if (port->handle_irq)
                p->handle_irq = port->handle_irq;
-       else
-               p->handle_irq = serial8250_default_handle_irq;
 
        return 0;
 }
@@ -3444,7 +3625,8 @@ void serial8250_suspend_port(int line)
            port->type != PORT_8250) {
                unsigned char canary = 0xa5;
                serial_out(up, UART_SCR, canary);
-               up->canary = canary;
+               if (serial_in(up, UART_SCR) == canary)
+                       up->canary = canary;
        }
 
        uart_suspend_port(&serial8250_reg, port);
@@ -3666,6 +3848,7 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
                uart->port.flags        = up->port.flags | UPF_BOOT_AUTOCONF;
                uart->bugs              = up->bugs;
                uart->port.mapbase      = up->port.mapbase;
+               uart->port.mapsize      = up->port.mapsize;
                uart->port.private_data = up->port.private_data;
                uart->port.fifosize     = up->port.fifosize;
                uart->tx_loadsz         = up->tx_loadsz;
@@ -3674,6 +3857,7 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
                uart->port.unthrottle   = up->port.unthrottle;
                uart->port.rs485_config = up->port.rs485_config;
                uart->port.rs485        = up->port.rs485;
+               uart->dma               = up->dma;
 
                /* Take tx_loadsz from fifosize if it wasn't set separately */
                if (uart->port.fifosize && !uart->tx_loadsz)
@@ -3682,10 +3866,14 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
                if (up->port.dev)
                        uart->port.dev = up->port.dev;
 
+               if (skip_txen_test)
+                       uart->port.flags |= UPF_NO_TXEN_TEST;
+
                if (up->port.flags & UPF_FIXED_TYPE)
-                       serial8250_init_fixed_type_port(uart, up->port.type);
+                       uart->port.type = up->port.type;
+
+               serial8250_set_defaults(uart);
 
-               set_io_from_upio(&uart->port);
                /* Possibly override default I/O functions.  */
                if (up->port.serial_in)
                        uart->port.serial_in = up->port.serial_in;
@@ -3710,13 +3898,6 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
                        uart->dl_read = up->dl_read;
                if (up->dl_write)
                        uart->dl_write = up->dl_write;
-               if (up->dma) {
-                       uart->dma = up->dma;
-                       if (!uart->dma->tx_dma)
-                               uart->dma->tx_dma = serial8250_tx_dma;
-                       if (!uart->dma->rx_dma)
-                               uart->dma->rx_dma = serial8250_rx_dma;
-               }
 
                if (serial8250_isa_config != NULL)
                        serial8250_isa_config(0, &uart->port,
@@ -3747,9 +3928,11 @@ void serial8250_unregister_port(int line)
        uart_remove_one_port(&serial8250_reg, &uart->port);
        if (serial8250_isa_devs) {
                uart->port.flags &= ~UPF_BOOT_AUTOCONF;
+               if (skip_txen_test)
+                       uart->port.flags |= UPF_NO_TXEN_TEST;
                uart->port.type = PORT_UNKNOWN;
                uart->port.dev = &serial8250_isa_devs->dev;
-               uart->capabilities = uart_config[uart->port.type].flags;
+               uart->capabilities = 0;
                uart_add_one_port(&serial8250_reg, &uart->port);
        } else {
                uart->port.dev = NULL;
index 6ae5b8560e4d764cafb8143a8a4654a81bf21f83..176f18f2e3ab5e16013ebcf7a71e7db2e85cd7db 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/serial_8250.h>
-#include <linux/serial_core.h>
 #include <linux/serial_reg.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
@@ -364,9 +363,9 @@ static int dw8250_probe_of(struct uart_port *p,
        }
 
        if (of_property_read_bool(np, "cts-override")) {
-               /* Always report DSR as active */
-               data->msr_mask_on |= UART_MSR_DSR;
-               data->msr_mask_off |= UART_MSR_DDSR;
+               /* Always report CTS as active */
+               data->msr_mask_on |= UART_MSR_CTS;
+               data->msr_mask_off |= UART_MSR_DCTS;
        }
 
        if (of_property_read_bool(np, "ri-override")) {
@@ -375,37 +374,16 @@ static int dw8250_probe_of(struct uart_port *p,
                data->msr_mask_off |= UART_MSR_TERI;
        }
 
-       /* clock got configured through clk api, all done */
-       if (p->uartclk)
-               return 0;
-
-       /* try to find out clock frequency from DT as fallback */
-       if (of_property_read_u32(np, "clock-frequency", &val)) {
-               dev_err(p->dev, "clk or clock-frequency not defined\n");
-               return -EINVAL;
-       }
-       p->uartclk = val;
-
        return 0;
 }
 
 static int dw8250_probe_acpi(struct uart_8250_port *up,
                             struct dw8250_data *data)
 {
-       const struct acpi_device_id *id;
        struct uart_port *p = &up->port;
 
        dw8250_setup_port(up);
 
-       id = acpi_match_device(p->dev->driver->acpi_match_table, p->dev);
-       if (!id)
-               return -ENODEV;
-
-       if (!p->uartclk)
-               if (device_property_read_u32(p->dev, "clock-frequency",
-                                            &p->uartclk))
-                       return -EINVAL;
-
        p->iotype = UPIO_MEM32;
        p->serial_in = dw8250_serial_in32;
        p->serial_out = dw8250_serial_out32;
@@ -425,18 +403,24 @@ static int dw8250_probe(struct platform_device *pdev)
 {
        struct uart_8250_port uart = {};
        struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       int irq = platform_get_irq(pdev, 0);
        struct dw8250_data *data;
        int err;
 
-       if (!regs || !irq) {
-               dev_err(&pdev->dev, "no registers/irq defined\n");
+       if (!regs) {
+               dev_err(&pdev->dev, "no registers defined\n");
                return -EINVAL;
        }
 
+       if (irq < 0) {
+               if (irq != -EPROBE_DEFER)
+                       dev_err(&pdev->dev, "cannot get irq\n");
+               return irq;
+       }
+
        spin_lock_init(&uart.port.lock);
        uart.port.mapbase = regs->start;
-       uart.port.irq = irq->start;
+       uart.port.irq = irq;
        uart.port.handle_irq = dw8250_handle_irq;
        uart.port.pm = dw8250_do_pm;
        uart.port.type = PORT_8250;
@@ -453,12 +437,18 @@ static int dw8250_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        data->usr_reg = DW_UART_USR;
+
+       /* Always ask for fixed clock rate from a property. */
+       device_property_read_u32(&pdev->dev, "clock-frequency",
+                                &uart.port.uartclk);
+
+       /* If there is separate baudclk, get the rate from it. */
        data->clk = devm_clk_get(&pdev->dev, "baudclk");
        if (IS_ERR(data->clk) && PTR_ERR(data->clk) != -EPROBE_DEFER)
                data->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(data->clk) && PTR_ERR(data->clk) == -EPROBE_DEFER)
                return -EPROBE_DEFER;
-       if (!IS_ERR(data->clk)) {
+       if (!IS_ERR_OR_NULL(data->clk)) {
                err = clk_prepare_enable(data->clk);
                if (err)
                        dev_warn(&pdev->dev, "could not enable optional baudclk: %d\n",
@@ -467,6 +457,12 @@ static int dw8250_probe(struct platform_device *pdev)
                        uart.port.uartclk = clk_get_rate(data->clk);
        }
 
+       /* If no clock rate is defined, fail. */
+       if (!uart.port.uartclk) {
+               dev_err(&pdev->dev, "clock rate not defined\n");
+               return -EINVAL;
+       }
+
        data->pclk = devm_clk_get(&pdev->dev, "apb_pclk");
        if (IS_ERR(data->clk) && PTR_ERR(data->clk) == -EPROBE_DEFER) {
                err = -EPROBE_DEFER;
@@ -629,6 +625,7 @@ static const struct acpi_device_id dw8250_acpi_match[] = {
        { "80860F0A", 0 },
        { "8086228A", 0 },
        { "APMC0D08", 0},
+       { "AMD0020", 0 },
        { },
 };
 MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match);
@@ -649,3 +646,4 @@ module_platform_driver(dw8250_platform_driver);
 MODULE_AUTHOR("Jamie Iles");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Synopsys DesignWare 8250 serial port driver");
+MODULE_ALIAS("platform:dw-apb-uart");
index c31a22b4f84524a0226343cab01532da884d1bac..6c0fd8b9d1c35b38b6019afd8a0fb293f0c117bc 100644 (file)
 #include <linux/tty.h>
 #include <linux/init.h>
 #include <linux/console.h>
-#include <linux/serial_core.h>
 #include <linux/serial_reg.h>
 #include <linux/serial.h>
 #include <linux/serial_8250.h>
 #include <asm/io.h>
 #include <asm/serial.h>
 
-static struct earlycon_device *early_device;
-
 unsigned int __weak __init serial8250_early_in(struct uart_port *port, int offset)
 {
        switch (port->iotype) {
@@ -45,6 +42,8 @@ unsigned int __weak __init serial8250_early_in(struct uart_port *port, int offse
                return readb(port->membase + offset);
        case UPIO_MEM32:
                return readl(port->membase + (offset << 2));
+       case UPIO_MEM32BE:
+               return ioread32be(port->membase + (offset << 2));
        case UPIO_PORT:
                return inb(port->iobase + offset);
        default:
@@ -61,6 +60,9 @@ void __weak __init serial8250_early_out(struct uart_port *port, int offset, int
        case UPIO_MEM32:
                writel(value, port->membase + (offset << 2));
                break;
+       case UPIO_MEM32BE:
+               iowrite32be(value, port->membase + (offset << 2));
+               break;
        case UPIO_PORT:
                outb(value, port->iobase + offset);
                break;
@@ -90,7 +92,8 @@ static void __init serial_putc(struct uart_port *port, int c)
 static void __init early_serial8250_write(struct console *console,
                                        const char *s, unsigned int count)
 {
-       struct uart_port *port = &early_device->port;
+       struct earlycon_device *device = console->data;
+       struct uart_port *port = &device->port;
        unsigned int ier;
 
        /* Save the IER and disable interrupts preserving the UUE bit */
@@ -107,21 +110,6 @@ static void __init early_serial8250_write(struct console *console,
                serial8250_early_out(port, UART_IER, ier);
 }
 
-static unsigned int __init probe_baud(struct uart_port *port)
-{
-       unsigned char lcr, dll, dlm;
-       unsigned int quot;
-
-       lcr = serial8250_early_in(port, UART_LCR);
-       serial8250_early_out(port, UART_LCR, lcr | UART_LCR_DLAB);
-       dll = serial8250_early_in(port, UART_DLL);
-       dlm = serial8250_early_in(port, UART_DLM);
-       serial8250_early_out(port, UART_LCR, lcr);
-
-       quot = (dlm << 8) | dll;
-       return (port->uartclk / 16) / quot;
-}
-
 static void __init init_port(struct earlycon_device *device)
 {
        struct uart_port *port = &device->port;
@@ -147,52 +135,20 @@ static int __init early_serial8250_setup(struct earlycon_device *device,
                                         const char *options)
 {
        if (!(device->port.membase || device->port.iobase))
-               return 0;
+               return -ENODEV;
 
        if (!device->baud) {
-               device->baud = probe_baud(&device->port);
-               snprintf(device->options, sizeof(device->options), "%u",
-                        device->baud);
-       }
+               struct uart_port *port = &device->port;
+               unsigned int ier;
 
-       init_port(device);
+               /* assume the device was initialized, only mask interrupts */
+               ier = serial8250_early_in(port, UART_IER);
+               serial8250_early_out(port, UART_IER, ier & UART_IER_UUE);
+       } else
+               init_port(device);
 
-       early_device = device;
        device->con->write = early_serial8250_write;
        return 0;
 }
 EARLYCON_DECLARE(uart8250, early_serial8250_setup);
 EARLYCON_DECLARE(uart, early_serial8250_setup);
-
-int __init setup_early_serial8250_console(char *cmdline)
-{
-       char match[] = "uart8250";
-
-       if (cmdline && cmdline[4] == ',')
-               match[4] = '\0';
-
-       return setup_earlycon(cmdline, match, early_serial8250_setup);
-}
-
-int serial8250_find_port_for_earlycon(void)
-{
-       struct earlycon_device *device = early_device;
-       struct uart_port *port = device ? &device->port : NULL;
-       int line;
-       int ret;
-
-       if (!port || (!port->membase && !port->iobase))
-               return -ENODEV;
-
-       line = serial8250_find_port(port);
-       if (line < 0)
-               return -ENODEV;
-
-       ret = update_console_cmdline("uart", 8250,
-                            "ttyS", line, device->options);
-       if (ret < 0)
-               ret = update_console_cmdline("uart", 0,
-                                    "ttyS", line, device->options);
-
-       return ret;
-}
index ae5eaed6aa85e7131c598c9f507e6e2ed673b60f..0b63812149176a7a9c6655f04112d9347ca007da 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/serial_8250.h>
-#include <linux/serial_core.h>
 #include <linux/serial_reg.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
index b4882082b2470d38acc1f61947b823850d711b60..2891958cd8420303a5e11cac8c72f359b7c2c229 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/serial.h>
-#include <linux/serial_core.h>
 #include <linux/serial_8250.h>
 #include <linux/delay.h>
 #include <linux/dio.h>
index fe6d2e51da09266324d0ac93af72da3578280c85..9289999cb7c62bb05b2a4b758fa76d5ce9413316 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/serial_8250.h>
-#include <linux/serial_core.h>
 #include <linux/serial_reg.h>
 #include <linux/tty_flip.h>
 #include <linux/platform_device.h>
index 892eb32cdef4bd98586d02e2e432c38aea512797..46bcebba54b2ff44fc32de373dfc8b09fc58687a 100644 (file)
 #include <linux/serial_core.h>
 #include <linux/8250_pci.h>
 #include <linux/bitops.h>
+#include <linux/rational.h>
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
 
 #include <linux/dmaengine.h>
 #include <linux/platform_data/dma-dw.h>
+#include <linux/platform_data/dma-hsu.h>
 
 #include "8250.h"
 
@@ -1392,45 +1394,22 @@ byt_set_termios(struct uart_port *p, struct ktermios *termios,
                struct ktermios *old)
 {
        unsigned int baud = tty_termios_baud_rate(termios);
-       unsigned int m, n;
+       unsigned long fref = 100000000, fuart = baud * 16;
+       unsigned long w = BIT(15) - 1;
+       unsigned long m, n;
        u32 reg;
 
+       /* Get Fuart closer to Fref */
+       fuart *= rounddown_pow_of_two(fref / fuart);
+
        /*
         * For baud rates 0.5M, 1M, 1.5M, 2M, 2.5M, 3M, 3.5M and 4M the
         * dividers must be adjusted.
         *
         * uartclk = (m / n) * 100 MHz, where m <= n
         */
-       switch (baud) {
-       case 500000:
-       case 1000000:
-       case 2000000:
-       case 4000000:
-               m = 64;
-               n = 100;
-               p->uartclk = 64000000;
-               break;
-       case 3500000:
-               m = 56;
-               n = 100;
-               p->uartclk = 56000000;
-               break;
-       case 1500000:
-       case 3000000:
-               m = 48;
-               n = 100;
-               p->uartclk = 48000000;
-               break;
-       case 2500000:
-               m = 40;
-               n = 100;
-               p->uartclk = 40000000;
-               break;
-       default:
-               m = 2304;
-               n = 3125;
-               p->uartclk = 73728000;
-       }
+       rational_best_approximation(fuart, fref, w, w, &m, &n);
+       p->uartclk = fuart;
 
        /* Reset the clock */
        reg = (m << BYT_PRV_CLK_M_VAL_SHIFT) | (n << BYT_PRV_CLK_N_VAL_SHIFT);
@@ -1525,6 +1504,167 @@ byt_serial_setup(struct serial_private *priv,
        return ret;
 }
 
+#define INTEL_MID_UART_PS              0x30
+#define INTEL_MID_UART_MUL             0x34
+#define INTEL_MID_UART_DIV             0x38
+
+static void intel_mid_set_termios(struct uart_port *p,
+                                 struct ktermios *termios,
+                                 struct ktermios *old,
+                                 unsigned long fref)
+{
+       unsigned int baud = tty_termios_baud_rate(termios);
+       unsigned short ps = 16;
+       unsigned long fuart = baud * ps;
+       unsigned long w = BIT(24) - 1;
+       unsigned long mul, div;
+
+       if (fref < fuart) {
+               /* Find prescaler value that satisfies Fuart < Fref */
+               if (fref > baud)
+                       ps = fref / baud;       /* baud rate too high */
+               else
+                       ps = 1;                 /* PLL case */
+               fuart = baud * ps;
+       } else {
+               /* Get Fuart closer to Fref */
+               fuart *= rounddown_pow_of_two(fref / fuart);
+       }
+
+       rational_best_approximation(fuart, fref, w, w, &mul, &div);
+       p->uartclk = fuart * 16 / ps;           /* core uses ps = 16 always */
+
+       writel(ps, p->membase + INTEL_MID_UART_PS);             /* set PS */
+       writel(mul, p->membase + INTEL_MID_UART_MUL);           /* set MUL */
+       writel(div, p->membase + INTEL_MID_UART_DIV);
+
+       serial8250_do_set_termios(p, termios, old);
+}
+
+static void intel_mid_set_termios_38_4M(struct uart_port *p,
+                                       struct ktermios *termios,
+                                       struct ktermios *old)
+{
+       intel_mid_set_termios(p, termios, old, 38400000);
+}
+
+static void intel_mid_set_termios_50M(struct uart_port *p,
+                                     struct ktermios *termios,
+                                     struct ktermios *old)
+{
+       /*
+        * The uart clk is 50Mhz, and the baud rate come from:
+        *      baud = 50M * MUL / (DIV * PS * DLAB)
+        */
+       intel_mid_set_termios(p, termios, old, 50000000);
+}
+
+static bool intel_mid_dma_filter(struct dma_chan *chan, void *param)
+{
+       struct hsu_dma_slave *s = param;
+
+       if (s->dma_dev != chan->device->dev || s->chan_id != chan->chan_id)
+               return false;
+
+       chan->private = s;
+       return true;
+}
+
+static int intel_mid_serial_setup(struct serial_private *priv,
+                                 const struct pciserial_board *board,
+                                 struct uart_8250_port *port, int idx,
+                                 int index, struct pci_dev *dma_dev)
+{
+       struct device *dev = port->port.dev;
+       struct uart_8250_dma *dma;
+       struct hsu_dma_slave *tx_param, *rx_param;
+
+       dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
+       if (!dma)
+               return -ENOMEM;
+
+       tx_param = devm_kzalloc(dev, sizeof(*tx_param), GFP_KERNEL);
+       if (!tx_param)
+               return -ENOMEM;
+
+       rx_param = devm_kzalloc(dev, sizeof(*rx_param), GFP_KERNEL);
+       if (!rx_param)
+               return -ENOMEM;
+
+       rx_param->chan_id = index * 2 + 1;
+       tx_param->chan_id = index * 2;
+
+       dma->rxconf.src_maxburst = 64;
+       dma->txconf.dst_maxburst = 64;
+
+       rx_param->dma_dev = &dma_dev->dev;
+       tx_param->dma_dev = &dma_dev->dev;
+
+       dma->fn = intel_mid_dma_filter;
+       dma->rx_param = rx_param;
+       dma->tx_param = tx_param;
+
+       port->port.type = PORT_16750;
+       port->port.flags |= UPF_FIXED_PORT | UPF_FIXED_TYPE;
+       port->dma = dma;
+
+       return pci_default_setup(priv, board, port, idx);
+}
+
+#define PCI_DEVICE_ID_INTEL_PNW_UART1  0x081b
+#define PCI_DEVICE_ID_INTEL_PNW_UART2  0x081c
+#define PCI_DEVICE_ID_INTEL_PNW_UART3  0x081d
+
+static int pnw_serial_setup(struct serial_private *priv,
+                           const struct pciserial_board *board,
+                           struct uart_8250_port *port, int idx)
+{
+       struct pci_dev *pdev = priv->dev;
+       struct pci_dev *dma_dev;
+       int index;
+
+       switch (pdev->device) {
+       case PCI_DEVICE_ID_INTEL_PNW_UART1:
+               index = 0;
+               break;
+       case PCI_DEVICE_ID_INTEL_PNW_UART2:
+               index = 1;
+               break;
+       case PCI_DEVICE_ID_INTEL_PNW_UART3:
+               index = 2;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       dma_dev = pci_get_slot(pdev->bus, PCI_DEVFN(PCI_SLOT(pdev->devfn), 3));
+
+       port->port.set_termios = intel_mid_set_termios_50M;
+
+       return intel_mid_serial_setup(priv, board, port, idx, index, dma_dev);
+}
+
+#define PCI_DEVICE_ID_INTEL_TNG_UART   0x1191
+
+static int tng_serial_setup(struct serial_private *priv,
+                           const struct pciserial_board *board,
+                           struct uart_8250_port *port, int idx)
+{
+       struct pci_dev *pdev = priv->dev;
+       struct pci_dev *dma_dev;
+       int index = PCI_FUNC(pdev->devfn);
+
+       /* Currently no support for HSU port0 */
+       if (index-- == 0)
+               return -ENODEV;
+
+       dma_dev = pci_get_slot(pdev->bus, PCI_DEVFN(5, 0));
+
+       port->port.set_termios = intel_mid_set_termios_38_4M;
+
+       return intel_mid_serial_setup(priv, board, port, idx, index, dma_dev);
+}
+
 static int
 pci_omegapci_setup(struct serial_private *priv,
                      const struct pciserial_board *board,
@@ -1550,95 +1690,71 @@ static int pci_fintek_setup(struct serial_private *priv,
                            struct uart_8250_port *port, int idx)
 {
        struct pci_dev *pdev = priv->dev;
-       unsigned long base;
-       unsigned long iobase;
-       unsigned long ciobase = 0;
        u8 config_base;
+       u16 iobase;
+
+       config_base = 0x40 + 0x08 * idx;
+
+       /* Get the io address from configuration space */
+       pci_read_config_word(pdev, config_base + 4, &iobase);
+
+       dev_dbg(&pdev->dev, "%s: idx=%d iobase=0x%x", __func__, idx, iobase);
+
+       port->port.iotype = UPIO_PORT;
+       port->port.iobase = iobase;
+
+       return 0;
+}
+
+static int pci_fintek_init(struct pci_dev *dev)
+{
+       unsigned long iobase;
+       u32 max_port, i;
        u32 bar_data[3];
+       u8 config_base;
 
-       /*
-        * Find each UARTs offset in PCI configuraion space
-        */
-       switch (idx) {
-       case 0:
-               config_base = 0x40;
-               break;
-       case 1:
-               config_base = 0x48;
-               break;
-       case 2:
-               config_base = 0x50;
-               break;
-       case 3:
-               config_base = 0x58;
-               break;
-       case 4:
-               config_base = 0x60;
-               break;
-       case 5:
-               config_base = 0x68;
-               break;
-       case 6:
-               config_base = 0x70;
-               break;
-       case 7:
-               config_base = 0x78;
-               break;
-       case 8:
-               config_base = 0x80;
+       switch (dev->device) {
+       case 0x1104: /* 4 ports */
+       case 0x1108: /* 8 ports */
+               max_port = dev->device & 0xff;
                break;
-       case 9:
-               config_base = 0x88;
-               break;
-       case 10:
-               config_base = 0x90;
-               break;
-       case 11:
-               config_base = 0x98;
+       case 0x1112: /* 12 ports */
+               max_port = 12;
                break;
        default:
-               /* Unknown number of ports, get out of here */
                return -EINVAL;
        }
 
-       if (idx < 4) {
-               base = pci_resource_start(priv->dev, 3);
-               ciobase = (int)(base + (0x8 * idx));
-       }
-
        /* Get the io address dispatch from the BIOS */
-       pci_read_config_dword(pdev, 0x24, &bar_data[0]);
-       pci_read_config_dword(pdev, 0x20, &bar_data[1]);
-       pci_read_config_dword(pdev, 0x1c, &bar_data[2]);
-
-       /* Calculate Real IO Port */
-       iobase = (bar_data[idx/4] & 0xffffffe0) + (idx % 4) * 8;
+       pci_read_config_dword(dev, 0x24, &bar_data[0]);
+       pci_read_config_dword(dev, 0x20, &bar_data[1]);
+       pci_read_config_dword(dev, 0x1c, &bar_data[2]);
 
-       dev_dbg(&pdev->dev, "%s: idx=%d iobase=0x%lx ciobase=0x%lx config_base=0x%2x\n",
-               __func__, idx, iobase, ciobase, config_base);
+       for (i = 0; i < max_port; ++i) {
+               /* UART0 configuration offset start from 0x40 */
+               config_base = 0x40 + 0x08 * i;
 
-       /* Enable UART I/O port */
-       pci_write_config_byte(pdev, config_base + 0x00, 0x01);
+               /* Calculate Real IO Port */
+               iobase = (bar_data[i / 4] & 0xffffffe0) + (i % 4) * 8;
 
-       /* Select 128-byte FIFO and 8x FIFO threshold */
-       pci_write_config_byte(pdev, config_base + 0x01, 0x33);
+               /* Enable UART I/O port */
+               pci_write_config_byte(dev, config_base + 0x00, 0x01);
 
-       /* LSB UART */
-       pci_write_config_byte(pdev, config_base + 0x04, (u8)(iobase & 0xff));
+               /* Select 128-byte FIFO and 8x FIFO threshold */
+               pci_write_config_byte(dev, config_base + 0x01, 0x33);
 
-       /* MSB UART */
-       pci_write_config_byte(pdev, config_base + 0x05, (u8)((iobase & 0xff00) >> 8));
+               /* LSB UART */
+               pci_write_config_byte(dev, config_base + 0x04,
+                               (u8)(iobase & 0xff));
 
-       /* irq number, this usually fails, but the spec says to do it anyway. */
-       pci_write_config_byte(pdev, config_base + 0x06, pdev->irq);
+               /* MSB UART */
+               pci_write_config_byte(dev, config_base + 0x05,
+                               (u8)((iobase & 0xff00) >> 8));
 
-       port->port.iotype = UPIO_PORT;
-       port->port.iobase = iobase;
-       port->port.mapbase = 0;
-       port->port.membase = NULL;
-       port->port.regshift = 0;
+               pci_write_config_byte(dev, config_base + 0x06, dev->irq);
+       }
 
-       return 0;
+       return max_port;
 }
 
 static int skip_tx_en_setup(struct serial_private *priv,
@@ -1882,6 +1998,8 @@ pci_wch_ch38x_setup(struct serial_private *priv,
 #define PCIE_DEVICE_ID_WCH_CH382_2S1P  0x3250
 #define PCIE_DEVICE_ID_WCH_CH384_4S    0x3470
 
+#define PCI_DEVICE_ID_EXAR_XR17V8358   0x8358
+
 /* Unknown vendors/cards - this should not be in linux/pci_ids.h */
 #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584        0x1584
 #define PCI_SUBDEVICE_ID_UNKNOWN_0x1588        0x1588
@@ -1987,6 +2105,34 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
                .subdevice      = PCI_ANY_ID,
                .setup          = byt_serial_setup,
        },
+       {
+               .vendor         = PCI_VENDOR_ID_INTEL,
+               .device         = PCI_DEVICE_ID_INTEL_PNW_UART1,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = pnw_serial_setup,
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_INTEL,
+               .device         = PCI_DEVICE_ID_INTEL_PNW_UART2,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = pnw_serial_setup,
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_INTEL,
+               .device         = PCI_DEVICE_ID_INTEL_PNW_UART3,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = pnw_serial_setup,
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_INTEL,
+               .device         = PCI_DEVICE_ID_INTEL_TNG_UART,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = tng_serial_setup,
+       },
        {
                .vendor         = PCI_VENDOR_ID_INTEL,
                .device         = PCI_DEVICE_ID_INTEL_BSW_UART1,
@@ -2376,6 +2522,13 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
                .subdevice      = PCI_ANY_ID,
                .setup          = pci_xr17v35x_setup,
        },
+       {
+               .vendor = PCI_VENDOR_ID_EXAR,
+               .device = PCI_DEVICE_ID_EXAR_XR17V8358,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = pci_xr17v35x_setup,
+       },
        /*
         * Xircom cards
         */
@@ -2653,6 +2806,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
                .subvendor      = PCI_ANY_ID,
                .subdevice      = PCI_ANY_ID,
                .setup          = pci_fintek_setup,
+               .init           = pci_fintek_init,
        },
        {
                .vendor         = 0x1c29,
@@ -2660,6 +2814,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
                .subvendor      = PCI_ANY_ID,
                .subdevice      = PCI_ANY_ID,
                .setup          = pci_fintek_setup,
+               .init           = pci_fintek_init,
        },
        {
                .vendor         = 0x1c29,
@@ -2667,6 +2822,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
                .subvendor      = PCI_ANY_ID,
                .subdevice      = PCI_ANY_ID,
                .setup          = pci_fintek_setup,
+               .init           = pci_fintek_init,
        },
 
        /*
@@ -2852,6 +3008,7 @@ enum pci_board_num_t {
        pbn_exar_XR17V352,
        pbn_exar_XR17V354,
        pbn_exar_XR17V358,
+       pbn_exar_XR17V8358,
        pbn_exar_ibm_saturn,
        pbn_pasemi_1682M,
        pbn_ni8430_2,
@@ -2864,6 +3021,8 @@ enum pci_board_num_t {
        pbn_ADDIDATA_PCIe_8_3906250,
        pbn_ce4100_1_115200,
        pbn_byt,
+       pbn_pnw,
+       pbn_tng,
        pbn_qrk,
        pbn_omegapci,
        pbn_NETMOS9900_2s_115200,
@@ -3536,6 +3695,14 @@ static struct pciserial_board pci_boards[] = {
                .reg_shift      = 0,
                .first_offset   = 0,
        },
+       [pbn_exar_XR17V8358] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 16,
+               .base_baud      = 7812500,
+               .uart_offset    = 0x400,
+               .reg_shift      = 0,
+               .first_offset   = 0,
+       },
        [pbn_exar_ibm_saturn] = {
                .flags          = FL_BASE0,
                .num_ports      = 1,
@@ -3630,6 +3797,16 @@ static struct pciserial_board pci_boards[] = {
                .uart_offset    = 0x80,
                .reg_shift      = 2,
        },
+       [pbn_pnw] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 1,
+               .base_baud      = 115200,
+       },
+       [pbn_tng] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 1,
+               .base_baud      = 1843200,
+       },
        [pbn_qrk] = {
                .flags          = FL_BASE0,
                .num_ports      = 1,
@@ -4006,41 +4183,41 @@ static void pciserial_remove_one(struct pci_dev *dev)
        pci_disable_device(dev);
 }
 
-#ifdef CONFIG_PM
-static int pciserial_suspend_one(struct pci_dev *dev, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int pciserial_suspend_one(struct device *dev)
 {
-       struct serial_private *priv = pci_get_drvdata(dev);
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct serial_private *priv = pci_get_drvdata(pdev);
 
        if (priv)
                pciserial_suspend_ports(priv);
 
-       pci_save_state(dev);
-       pci_set_power_state(dev, pci_choose_state(dev, state));
        return 0;
 }
 
-static int pciserial_resume_one(struct pci_dev *dev)
+static int pciserial_resume_one(struct device *dev)
 {
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct serial_private *priv = pci_get_drvdata(pdev);
        int err;
-       struct serial_private *priv = pci_get_drvdata(dev);
-
-       pci_set_power_state(dev, PCI_D0);
-       pci_restore_state(dev);
 
        if (priv) {
                /*
                 * The device may have been disabled.  Re-enable it.
                 */
-               err = pci_enable_device(dev);
+               err = pci_enable_device(pdev);
                /* FIXME: We cannot simply error out here */
                if (err)
-                       dev_err(&dev->dev, "Unable to re-enable ports, trying to continue.\n");
+                       dev_err(dev, "Unable to re-enable ports, trying to continue.\n");
                pciserial_resume_ports(priv);
        }
        return 0;
 }
 #endif
 
+static SIMPLE_DEV_PM_OPS(pciserial_pm_ops, pciserial_suspend_one,
+                        pciserial_resume_one);
+
 static struct pci_device_id serial_pci_tbl[] = {
        /* Advantech use PCI_DEVICE_ID_ADVANTECH_PCI3620 (0x3620) as 'PCI_SUBVENDOR_ID' */
        {       PCI_VENDOR_ID_ADVANTECH, PCI_DEVICE_ID_ADVANTECH_PCI3620,
@@ -4921,7 +5098,7 @@ static struct pci_device_id serial_pci_tbl[] = {
                0,
                0, pbn_exar_XR17C158 },
        /*
-        * Exar Corp. XR17V35[248] Dual/Quad/Octal PCIe UARTs
+        * Exar Corp. XR17V[48]35[248] Dual/Quad/Octal/Hexa PCIe UARTs
         */
        {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V352,
                PCI_ANY_ID, PCI_ANY_ID,
@@ -4935,7 +5112,10 @@ static struct pci_device_id serial_pci_tbl[] = {
                PCI_ANY_ID, PCI_ANY_ID,
                0,
                0, pbn_exar_XR17V358 },
-
+       {       PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V8358,
+               PCI_ANY_ID, PCI_ANY_ID,
+               0,
+               0, pbn_exar_XR17V8358 },
        /*
         * Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke)
         */
@@ -5362,6 +5542,26 @@ static struct pci_device_id serial_pci_tbl[] = {
                PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
                pbn_byt },
 
+       /*
+        * Intel Penwell
+        */
+       {       PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PNW_UART1,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_pnw},
+       {       PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PNW_UART2,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_pnw},
+       {       PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PNW_UART3,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_pnw},
+
+       /*
+        * Intel Tangier
+        */
+       {       PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TNG_UART,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_tng},
+
        /*
         * Intel Quark x1000
         */
@@ -5510,10 +5710,9 @@ static struct pci_driver serial_pci_driver = {
        .name           = "serial",
        .probe          = pciserial_init_one,
        .remove         = pciserial_remove_one,
-#ifdef CONFIG_PM
-       .suspend        = pciserial_suspend_one,
-       .resume         = pciserial_resume_one,
-#endif
+       .driver         = {
+               .pm     = &pciserial_pm_ops,
+       },
        .id_table       = serial_pci_tbl,
        .err_handler    = &serial8250_err_handler,
 };
index 6f7f2d753defe9695925ea9aaa0f503066858e55..c3507035652891e4e25070c6f7fa79c94cd549f8 100644 (file)
@@ -108,6 +108,7 @@ config SERIAL_8250_PCI
        tristate "8250/16550 PCI device support" if EXPERT
        depends on SERIAL_8250 && PCI
        default SERIAL_8250
+       select RATIONAL
        help
          This builds standard PCI serial support. You may be able to
          disable this feature if you only need legacy serial support.
index d2501f01cd03483b3f83a384027275abb5b5c089..f8120c1bde14760f306e425d4d0de2d23f26d0e2 100644 (file)
@@ -20,7 +20,7 @@ comment "Non-8250 serial port support"
 
 config SERIAL_AMBA_PL010
        tristate "ARM AMBA PL010 serial port support"
-       depends on ARM_AMBA && (BROKEN || !ARCH_VERSATILE)
+       depends on ARM_AMBA
        select SERIAL_CORE
        help
          This selects the ARM(R) AMBA(R) PrimeCell PL010 UART.  If you have
@@ -483,16 +483,6 @@ config SERIAL_SA1100_CONSOLE
          your boot loader (lilo or loadlin) about how to pass options to the
          kernel at boot time.)
 
-config SERIAL_MFD_HSU
-       tristate "Medfield High Speed UART support"
-       depends on PCI
-       select SERIAL_CORE
-
-config SERIAL_MFD_HSU_CONSOLE
-       bool "Medfile HSU serial console support"
-       depends on SERIAL_MFD_HSU=y
-       select SERIAL_CORE_CONSOLE
-
 config SERIAL_BFIN
        tristate "Blackfin serial port support"
        depends on BLACKFIN
@@ -835,7 +825,7 @@ config SERIAL_MCF_CONSOLE
 
 config SERIAL_PMACZILOG
        tristate "Mac or PowerMac z85c30 ESCC support"
-       depends on (M68K && MAC) || (PPC_OF && PPC_PMAC)
+       depends on (M68K && MAC) || PPC_PMAC
        select SERIAL_CORE
        help
          This driver supports the Zilog z85C30 serial ports found on
@@ -878,7 +868,7 @@ config SERIAL_PMACZILOG_CONSOLE
 
 config SERIAL_CPM
        tristate "CPM SCC/SMC serial port support"
-       depends on CPM2 || 8xx
+       depends on CPM2 || CPM1
        select SERIAL_CORE
        help
          This driver supports the SCC and SMC serial ports on Motorola 
@@ -1054,7 +1044,7 @@ config SERIAL_SGI_IOC3
 
 config SERIAL_MSM
        bool "MSM on-chip serial port support"
-       depends on ARCH_MSM || ARCH_QCOM
+       depends on ARCH_QCOM
        select SERIAL_CORE
 
 config SERIAL_MSM_CONSOLE
@@ -1063,18 +1053,6 @@ config SERIAL_MSM_CONSOLE
        select SERIAL_CORE_CONSOLE
        select SERIAL_EARLYCON
 
-config SERIAL_MSM_HS
-       tristate "MSM UART High Speed: Serial Driver"
-       depends on ARCH_MSM7X00A || ARCH_MSM7X30 || ARCH_QSD8X50
-       select SERIAL_CORE
-       help
-         If you have a machine based on MSM family of SoCs, you
-         can enable its onboard high speed serial port by enabling
-         this option.
-
-         Choose M here to compile it as a module. The module will be
-         called msm_serial_hs.
-
 config SERIAL_VT8500
        bool "VIA VT8500 on-chip serial port support"
        depends on ARCH_VT8500
@@ -1153,7 +1131,7 @@ config SERIAL_OMAP_CONSOLE
 
 config SERIAL_OF_PLATFORM_NWPSERIAL
        tristate "NWP serial port driver"
-       depends on PPC_OF && PPC_DCR
+       depends on PPC_DCR
        select SERIAL_OF_PLATFORM
        select SERIAL_CORE_CONSOLE
        select SERIAL_CORE
index 599be4b05a268801d31d94b6fb539e45f95af665..c3ac3d930b33809d7eccb43f9e8b7753d46ae45b 100644 (file)
@@ -62,7 +62,6 @@ obj-$(CONFIG_SERIAL_SGI_IOC3) += ioc3_serial.o
 obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o
 obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o
 obj-$(CONFIG_SERIAL_MSM) += msm_serial.o
-obj-$(CONFIG_SERIAL_MSM_HS) += msm_serial_hs.o
 obj-$(CONFIG_SERIAL_NETX) += netx-serial.o
 obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o
 obj-$(CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL) += nwpserial.o
@@ -78,7 +77,6 @@ obj-$(CONFIG_SERIAL_TIMBERDALE)       += timbuart.o
 obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o
 obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o
 obj-$(CONFIG_SERIAL_VT8500) += vt8500_serial.o
-obj-$(CONFIG_SERIAL_MFD_HSU)   += mfd.o
 obj-$(CONFIG_SERIAL_IFX6X60)   += ifx6x60.o
 obj-$(CONFIG_SERIAL_PCH_UART)  += pch_uart.o
 obj-$(CONFIG_SERIAL_MSM_SMD)   += msm_smd_tty.o
index 8d94c194f090b8ed16ae1e9a418502f224041e36..5a4e9d579585f9c5165839db0fec8e368dfb8133 100644 (file)
@@ -58,6 +58,7 @@
 #include <linux/pinctrl/consumer.h>
 #include <linux/sizes.h>
 #include <linux/io.h>
+#include <linux/workqueue.h>
 
 #define UART_NR                        14
 
@@ -156,7 +157,9 @@ struct uart_amba_port {
        unsigned int            lcrh_tx;        /* vendor-specific */
        unsigned int            lcrh_rx;        /* vendor-specific */
        unsigned int            old_cr;         /* state during shutdown */
+       struct delayed_work     tx_softirq_work;
        bool                    autorts;
+       unsigned int            tx_irq_seen;    /* 0=none, 1=1, 2=2 or more */
        char                    type[12];
 #ifdef CONFIG_DMA_ENGINE
        /* DMA stuff */
@@ -164,6 +167,7 @@ struct uart_amba_port {
        bool                    using_rx_dma;
        struct pl011_dmarx_data dmarx;
        struct pl011_dmatx_data dmatx;
+       bool                    dma_probed;
 #endif
 };
 
@@ -261,10 +265,11 @@ static void pl011_sgbuf_free(struct dma_chan *chan, struct pl011_sgbuf *sg,
        }
 }
 
-static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port *uap)
+static void pl011_dma_probe(struct uart_amba_port *uap)
 {
        /* DMA is the sole user of the platform data right now */
        struct amba_pl011_data *plat = dev_get_platdata(uap->port.dev);
+       struct device *dev = uap->port.dev;
        struct dma_slave_config tx_conf = {
                .dst_addr = uap->port.mapbase + UART01x_DR,
                .dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
@@ -275,9 +280,14 @@ static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port *
        struct dma_chan *chan;
        dma_cap_mask_t mask;
 
-       chan = dma_request_slave_channel(dev, "tx");
+       uap->dma_probed = true;
+       chan = dma_request_slave_channel_reason(dev, "tx");
+       if (IS_ERR(chan)) {
+               if (PTR_ERR(chan) == -EPROBE_DEFER) {
+                       uap->dma_probed = false;
+                       return;
+               }
 
-       if (!chan) {
                /* We need platform data */
                if (!plat || !plat->dma_filter) {
                        dev_info(uap->port.dev, "no DMA platform data\n");
@@ -385,63 +395,17 @@ static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port *
        }
 }
 
-#ifndef MODULE
-/*
- * Stack up the UARTs and let the above initcall be done at device
- * initcall time, because the serial driver is called as an arch
- * initcall, and at this time the DMA subsystem is not yet registered.
- * At this point the driver will switch over to using DMA where desired.
- */
-struct dma_uap {
-       struct list_head node;
-       struct uart_amba_port *uap;
-       struct device *dev;
-};
-
-static LIST_HEAD(pl011_dma_uarts);
-
-static int __init pl011_dma_initcall(void)
-{
-       struct list_head *node, *tmp;
-
-       list_for_each_safe(node, tmp, &pl011_dma_uarts) {
-               struct dma_uap *dmau = list_entry(node, struct dma_uap, node);
-               pl011_dma_probe_initcall(dmau->dev, dmau->uap);
-               list_del(node);
-               kfree(dmau);
-       }
-       return 0;
-}
-
-device_initcall(pl011_dma_initcall);
-
-static void pl011_dma_probe(struct device *dev, struct uart_amba_port *uap)
-{
-       struct dma_uap *dmau = kzalloc(sizeof(struct dma_uap), GFP_KERNEL);
-       if (dmau) {
-               dmau->uap = uap;
-               dmau->dev = dev;
-               list_add_tail(&dmau->node, &pl011_dma_uarts);
-       }
-}
-#else
-static void pl011_dma_probe(struct device *dev, struct uart_amba_port *uap)
-{
-       pl011_dma_probe_initcall(dev, uap);
-}
-#endif
-
 static void pl011_dma_remove(struct uart_amba_port *uap)
 {
-       /* TODO: remove the initcall if it has not yet executed */
        if (uap->dmatx.chan)
                dma_release_channel(uap->dmatx.chan);
        if (uap->dmarx.chan)
                dma_release_channel(uap->dmarx.chan);
 }
 
-/* Forward declare this for the refill routine */
+/* Forward declare these for the refill routine */
 static int pl011_dma_tx_refill(struct uart_amba_port *uap);
+static void pl011_start_tx_pio(struct uart_amba_port *uap);
 
 /*
  * The current DMA TX buffer has been sent.
@@ -479,14 +443,13 @@ static void pl011_dma_tx_callback(void *data)
                return;
        }
 
-       if (pl011_dma_tx_refill(uap) <= 0) {
+       if (pl011_dma_tx_refill(uap) <= 0)
                /*
                 * We didn't queue a DMA buffer for some reason, but we
                 * have data pending to be sent.  Re-enable the TX IRQ.
                 */
-               uap->im |= UART011_TXIM;
-               writew(uap->im, uap->port.membase + UART011_IMSC);
-       }
+               pl011_start_tx_pio(uap);
+
        spin_unlock_irqrestore(&uap->port.lock, flags);
 }
 
@@ -664,12 +627,10 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
                if (!uap->dmatx.queued) {
                        if (pl011_dma_tx_refill(uap) > 0) {
                                uap->im &= ~UART011_TXIM;
-                               ret = true;
-                       } else {
-                               uap->im |= UART011_TXIM;
+                               writew(uap->im, uap->port.membase +
+                                      UART011_IMSC);
+                       } else
                                ret = false;
-                       }
-                       writew(uap->im, uap->port.membase + UART011_IMSC);
                } else if (!(uap->dmacr & UART011_TXDMAE)) {
                        uap->dmacr |= UART011_TXDMAE;
                        writew(uap->dmacr,
@@ -1021,6 +982,9 @@ static void pl011_dma_startup(struct uart_amba_port *uap)
 {
        int ret;
 
+       if (!uap->dma_probed)
+               pl011_dma_probe(uap);
+
        if (!uap->dmatx.chan)
                return;
 
@@ -1142,7 +1106,7 @@ static inline bool pl011_dma_rx_running(struct uart_amba_port *uap)
 
 #else
 /* Blank functions if the DMA engine is not available */
-static inline void pl011_dma_probe(struct device *dev, struct uart_amba_port *uap)
+static inline void pl011_dma_probe(struct uart_amba_port *uap)
 {
 }
 
@@ -1208,15 +1172,24 @@ static void pl011_stop_tx(struct uart_port *port)
        pl011_dma_tx_stop(uap);
 }
 
+static bool pl011_tx_chars(struct uart_amba_port *uap);
+
+/* Start TX with programmed I/O only (no DMA) */
+static void pl011_start_tx_pio(struct uart_amba_port *uap)
+{
+       uap->im |= UART011_TXIM;
+       writew(uap->im, uap->port.membase + UART011_IMSC);
+       if (!uap->tx_irq_seen)
+               pl011_tx_chars(uap);
+}
+
 static void pl011_start_tx(struct uart_port *port)
 {
        struct uart_amba_port *uap =
            container_of(port, struct uart_amba_port, port);
 
-       if (!pl011_dma_tx_start(uap)) {
-               uap->im |= UART011_TXIM;
-               writew(uap->im, uap->port.membase + UART011_IMSC);
-       }
+       if (!pl011_dma_tx_start(uap))
+               pl011_start_tx_pio(uap);
 }
 
 static void pl011_stop_rx(struct uart_port *port)
@@ -1274,40 +1247,87 @@ __acquires(&uap->port.lock)
        spin_lock(&uap->port.lock);
 }
 
-static void pl011_tx_chars(struct uart_amba_port *uap)
+/*
+ * Transmit a character
+ * There must be at least one free entry in the TX FIFO to accept the char.
+ *
+ * Returns true if the FIFO might have space in it afterwards;
+ * returns false if the FIFO definitely became full.
+ */
+static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c)
+{
+       writew(c, uap->port.membase + UART01x_DR);
+       uap->port.icount.tx++;
+
+       if (likely(uap->tx_irq_seen > 1))
+               return true;
+
+       return !(readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF);
+}
+
+static bool pl011_tx_chars(struct uart_amba_port *uap)
 {
        struct circ_buf *xmit = &uap->port.state->xmit;
        int count;
 
+       if (unlikely(uap->tx_irq_seen < 2))
+               /*
+                * Initial FIFO fill level unknown: we must check TXFF
+                * after each write, so just try to fill up the FIFO.
+                */
+               count = uap->fifosize;
+       else /* tx_irq_seen >= 2 */
+               /*
+                * FIFO initially at least half-empty, so we can simply
+                * write half the FIFO without polling TXFF.
+
+                * Note: the *first* TX IRQ can still race with
+                * pl011_start_tx_pio(), which can result in the FIFO
+                * being fuller than expected in that case.
+                */
+               count = uap->fifosize >> 1;
+
+       /*
+        * If the FIFO is full we're guaranteed a TX IRQ at some later point,
+        * and can't transmit immediately in any case:
+        */
+       if (unlikely(uap->tx_irq_seen < 2 &&
+                    readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF))
+               return false;
+
        if (uap->port.x_char) {
-               writew(uap->port.x_char, uap->port.membase + UART01x_DR);
-               uap->port.icount.tx++;
+               pl011_tx_char(uap, uap->port.x_char);
                uap->port.x_char = 0;
-               return;
+               --count;
        }
        if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) {
                pl011_stop_tx(&uap->port);
-               return;
+               goto done;
        }
 
        /* If we are using DMA mode, try to send some characters. */
        if (pl011_dma_tx_irq(uap))
-               return;
+               goto done;
 
-       count = uap->fifosize >> 1;
-       do {
-               writew(xmit->buf[xmit->tail], uap->port.membase + UART01x_DR);
+       while (count-- > 0 && pl011_tx_char(uap, xmit->buf[xmit->tail])) {
                xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-               uap->port.icount.tx++;
                if (uart_circ_empty(xmit))
                        break;
-       } while (--count > 0);
+       }
 
        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
                uart_write_wakeup(&uap->port);
 
-       if (uart_circ_empty(xmit))
+       if (uart_circ_empty(xmit)) {
                pl011_stop_tx(&uap->port);
+               goto done;
+       }
+
+       if (unlikely(!uap->tx_irq_seen))
+               schedule_delayed_work(&uap->tx_softirq_work, uap->port.timeout);
+
+done:
+       return false;
 }
 
 static void pl011_modem_status(struct uart_amba_port *uap)
@@ -1334,6 +1354,28 @@ static void pl011_modem_status(struct uart_amba_port *uap)
        wake_up_interruptible(&uap->port.state->port.delta_msr_wait);
 }
 
+static void pl011_tx_softirq(struct work_struct *work)
+{
+       struct delayed_work *dwork = to_delayed_work(work);
+       struct uart_amba_port *uap =
+               container_of(dwork, struct uart_amba_port, tx_softirq_work);
+
+       spin_lock(&uap->port.lock);
+       while (pl011_tx_chars(uap)) ;
+       spin_unlock(&uap->port.lock);
+}
+
+static void pl011_tx_irq_seen(struct uart_amba_port *uap)
+{
+       if (likely(uap->tx_irq_seen > 1))
+               return;
+
+       uap->tx_irq_seen++;
+       if (uap->tx_irq_seen < 2)
+               /* first TX IRQ */
+               cancel_delayed_work(&uap->tx_softirq_work);
+}
+
 static irqreturn_t pl011_int(int irq, void *dev_id)
 {
        struct uart_amba_port *uap = dev_id;
@@ -1372,8 +1414,10 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
                        if (status & (UART011_DSRMIS|UART011_DCDMIS|
                                      UART011_CTSMIS|UART011_RIMIS))
                                pl011_modem_status(uap);
-                       if (status & UART011_TXIS)
+                       if (status & UART011_TXIS) {
+                               pl011_tx_irq_seen(uap);
                                pl011_tx_chars(uap);
+                       }
 
                        if (pass_counter-- == 0)
                                break;
@@ -1577,7 +1621,7 @@ static int pl011_startup(struct uart_port *port)
 {
        struct uart_amba_port *uap =
            container_of(port, struct uart_amba_port, port);
-       unsigned int cr, lcr_h, fbrd, ibrd;
+       unsigned int cr;
        int retval;
 
        retval = pl011_hwinit(port);
@@ -1595,30 +1639,8 @@ static int pl011_startup(struct uart_port *port)
 
        writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS);
 
-       /*
-        * Provoke TX FIFO interrupt into asserting. Taking care to preserve
-        * baud rate and data format specified by FBRD, IBRD and LCRH as the
-        * UART may already be in use as a console.
-        */
        spin_lock_irq(&uap->port.lock);
 
-       fbrd = readw(uap->port.membase + UART011_FBRD);
-       ibrd = readw(uap->port.membase + UART011_IBRD);
-       lcr_h = readw(uap->port.membase + uap->lcrh_rx);
-
-       cr = UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_LBE;
-       writew(cr, uap->port.membase + UART011_CR);
-       writew(0, uap->port.membase + UART011_FBRD);
-       writew(1, uap->port.membase + UART011_IBRD);
-       pl011_write_lcr_h(uap, 0);
-       writew(0, uap->port.membase + UART01x_DR);
-       while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY)
-               barrier();
-
-       writew(fbrd, uap->port.membase + UART011_FBRD);
-       writew(ibrd, uap->port.membase + UART011_IBRD);
-       pl011_write_lcr_h(uap, lcr_h);
-
        /* restore RTS and DTR */
        cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR);
        cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
@@ -1672,13 +1694,15 @@ static void pl011_shutdown(struct uart_port *port)
            container_of(port, struct uart_amba_port, port);
        unsigned int cr;
 
+       cancel_delayed_work_sync(&uap->tx_softirq_work);
+
        /*
         * disable all interrupts
         */
        spin_lock_irq(&uap->port.lock);
        uap->im = 0;
        writew(uap->im, uap->port.membase + UART011_IMSC);
-       writew(0xffff, uap->port.membase + UART011_ICR);
+       writew(0xffff & ~UART011_TXIS, uap->port.membase + UART011_ICR);
        spin_unlock_irq(&uap->port.lock);
 
        pl011_dma_shutdown(uap);
@@ -2218,7 +2242,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
        uap->port.ops = &amba_pl011_pops;
        uap->port.flags = UPF_BOOT_AUTOCONF;
        uap->port.line = i;
-       pl011_dma_probe(&dev->dev, uap);
+       INIT_DELAYED_WORK(&uap->tx_softirq_work, pl011_tx_softirq);
 
        /* Ensure interrupts from this UART are masked and cleared */
        writew(0, uap->port.membase + UART011_IMSC);
@@ -2233,7 +2257,8 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
        if (!amba_reg.state) {
                ret = uart_register_driver(&amba_reg);
                if (ret < 0) {
-                       pr_err("Failed to register AMBA-PL011 driver\n");
+                       dev_err(&dev->dev,
+                               "Failed to register AMBA-PL011 driver\n");
                        return ret;
                }
        }
@@ -2242,7 +2267,6 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
        if (ret) {
                amba_ports[i] = NULL;
                uart_unregister_driver(&amba_reg);
-               pl011_dma_remove(uap);
        }
 
        return ret;
index 4f0f95e358e8300aed111f4bab22f7abec8d6c9a..f3af317131acb022616739800cca755c29ebf404 100644 (file)
@@ -572,7 +572,7 @@ static int apbuart_probe(struct platform_device *op)
        return 0;
 }
 
-static struct of_device_id apbuart_match[] = {
+static const struct of_device_id apbuart_match[] = {
        {
         .name = "GAISLER_APBUART",
         },
index 77fc9faa74a41f508414440e2c41fc155058d1ce..1519d2ca7705f23eb785b083ed8364b0d46e1de3 100644 (file)
@@ -649,7 +649,7 @@ static int ar933x_uart_probe(struct platform_device *pdev)
                        id = 0;
        }
 
-       if (id > CONFIG_SERIAL_AR933X_NR_UARTS)
+       if (id >= CONFIG_SERIAL_AR933X_NR_UARTS)
                return -EINVAL;
 
        irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
index 4e959c43f6804d12f8677d916e1f050bdc740457..27dade29646b7c8d962494cf37daee398c774514 100644 (file)
@@ -855,7 +855,7 @@ static int atmel_prepare_tx_dma(struct uart_port *port)
        spin_lock_init(&atmel_port->lock_tx);
        sg_init_table(&atmel_port->sg_tx, 1);
        /* UART circular tx buffer is an aligned page. */
-       BUG_ON((int)port->state->xmit.buf & ~PAGE_MASK);
+       BUG_ON(!PAGE_ALIGNED(port->state->xmit.buf));
        sg_set_page(&atmel_port->sg_tx,
                        virt_to_page(port->state->xmit.buf),
                        UART_XMIT_SIZE,
@@ -880,6 +880,7 @@ static int atmel_prepare_tx_dma(struct uart_port *port)
        config.direction = DMA_MEM_TO_DEV;
        config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
        config.dst_addr = port->mapbase + ATMEL_US_THR;
+       config.dst_maxburst = 1;
 
        ret = dmaengine_slave_config(atmel_port->chan_tx,
                                     &config);
@@ -1034,10 +1035,10 @@ static int atmel_prepare_rx_dma(struct uart_port *port)
        spin_lock_init(&atmel_port->lock_rx);
        sg_init_table(&atmel_port->sg_rx, 1);
        /* UART circular rx buffer is an aligned page. */
-       BUG_ON((int)port->state->xmit.buf & ~PAGE_MASK);
+       BUG_ON(!PAGE_ALIGNED(ring->buf));
        sg_set_page(&atmel_port->sg_rx,
                    virt_to_page(ring->buf),
-                   ATMEL_SERIAL_RINGSIZE,
+                   sizeof(struct atmel_uart_char) * ATMEL_SERIAL_RINGSIZE,
                    (int)ring->buf & ~PAGE_MASK);
        nent = dma_map_sg(port->dev,
                          &atmel_port->sg_rx,
@@ -1059,6 +1060,7 @@ static int atmel_prepare_rx_dma(struct uart_port *port)
        config.direction = DMA_DEV_TO_MEM;
        config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
        config.src_addr = port->mapbase + ATMEL_US_RHR;
+       config.src_maxburst = 1;
 
        ret = dmaengine_slave_config(atmel_port->chan_rx,
                                     &config);
@@ -1554,7 +1556,7 @@ static void atmel_tasklet_func(unsigned long data)
        spin_unlock(&port->lock);
 }
 
-static int atmel_init_property(struct atmel_uart_port *atmel_port,
+static void atmel_init_property(struct atmel_uart_port *atmel_port,
                                struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
@@ -1595,7 +1597,6 @@ static int atmel_init_property(struct atmel_uart_port *atmel_port,
                atmel_port->use_dma_tx  = false;
        }
 
-       return 0;
 }
 
 static void atmel_init_rs485(struct uart_port *port,
@@ -1777,10 +1778,13 @@ static int atmel_startup(struct uart_port *port)
        if (retval)
                goto free_irq;
 
+       tasklet_enable(&atmel_port->tasklet);
+
        /*
         * Initialize DMA (if necessary)
         */
        atmel_init_property(atmel_port, pdev);
+       atmel_set_ops(port);
 
        if (atmel_port->prepare_rx) {
                retval = atmel_port->prepare_rx(port);
@@ -1879,6 +1883,7 @@ static void atmel_shutdown(struct uart_port *port)
         * Clear out any scheduled tasklets before
         * we destroy the buffers
         */
+       tasklet_disable(&atmel_port->tasklet);
        tasklet_kill(&atmel_port->tasklet);
 
        /*
@@ -2256,8 +2261,8 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port,
        struct uart_port *port = &atmel_port->uart;
        struct atmel_uart_data *pdata = dev_get_platdata(&pdev->dev);
 
-       if (!atmel_init_property(atmel_port, pdev))
-               atmel_set_ops(port);
+       atmel_init_property(atmel_port, pdev);
+       atmel_set_ops(port);
 
        atmel_init_rs485(port, pdev);
 
@@ -2272,6 +2277,7 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port,
 
        tasklet_init(&atmel_port->tasklet, atmel_tasklet_func,
                        (unsigned long)port);
+       tasklet_disable(&atmel_port->tasklet);
 
        memset(&atmel_port->rx_ring, 0, sizeof(atmel_port->rx_ring));
 
@@ -2581,8 +2587,8 @@ static int atmel_init_gpios(struct atmel_uart_port *p, struct device *dev)
        struct gpio_desc *gpiod;
 
        p->gpios = mctrl_gpio_init(dev, 0);
-       if (IS_ERR_OR_NULL(p->gpios))
-               return -1;
+       if (IS_ERR(p->gpios))
+               return PTR_ERR(p->gpios);
 
        for (i = 0; i < UART_GPIO_MAX; i++) {
                gpiod = mctrl_gpio_to_gpiod(p->gpios, i);
@@ -2635,9 +2641,10 @@ static int atmel_serial_probe(struct platform_device *pdev)
        spin_lock_init(&port->lock_suspended);
 
        ret = atmel_init_gpios(port, &pdev->dev);
-       if (ret < 0)
-               dev_err(&pdev->dev, "%s",
-                       "Failed to initialize GPIOs. The serial port may not work as expected");
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to initialize GPIOs.");
+               goto err;
+       }
 
        ret = atmel_init_port(port, pdev);
        if (ret)
index 01d83df08e3d394f7a028ca1e37fa2429eab2644..681e0f3d5e0ef895b0f618a24a40cf138f8f0eca 100644 (file)
@@ -854,7 +854,7 @@ static int bcm_uart_probe(struct platform_device *pdev)
 
        ret = uart_add_one_port(&bcm_uart_driver, port);
        if (ret) {
-               ports[pdev->id].membase = 0;
+               ports[pdev->id].membase = NULL;
                return ret;
        }
        platform_set_drvdata(pdev, port);
@@ -868,7 +868,7 @@ static int bcm_uart_remove(struct platform_device *pdev)
        port = platform_get_drvdata(pdev);
        uart_remove_one_port(&bcm_uart_driver, port);
        /* mark port as free */
-       ports[pdev->id].membase = 0;
+       ports[pdev->id].membase = NULL;
        return 0;
 }
 
index 43b3e2c233ff0f73928193c3c7dc032abfaf9df3..155781ece050a0718676e5a2f805b0b75a0a1745 100644 (file)
@@ -464,6 +464,7 @@ void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
        int x_pos, pos;
        unsigned long flags;
 
+       dma_disable_irq_nosync(uart->rx_dma_channel);
        spin_lock_irqsave(&uart->rx_lock, flags);
 
        /* 2D DMA RX buffer ring is used. Because curr_y_count and
@@ -496,6 +497,7 @@ void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
        }
 
        spin_unlock_irqrestore(&uart->rx_lock, flags);
+       dma_enable_irq(uart->rx_dma_channel);
 
        mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES);
 }
index 6e11c275f2ab70d4fe326cf55c8177839408b03d..d5d2dd7c79174820432363d4a7076566eafc2204 100644 (file)
@@ -501,6 +501,8 @@ static int uart_clps711x_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, s);
 
        s->gpios = mctrl_gpio_init(&pdev->dev, 0);
+       if (IS_ERR(s->gpios))
+           return PTR_ERR(s->gpios);
 
        ret = uart_add_one_port(&clps711x_uart, &s->port);
        if (ret)
index e072724ea754fe718cfc5d414f2973a7380243dd..896a5d57881c181fc025087f5488ec6a8746e23e 100644 (file)
@@ -6,6 +6,6 @@ obj-$(CONFIG_SERIAL_CPM) += cpm_uart.o
 
 # Select the correct platform objects.
 cpm_uart-objs-$(CONFIG_CPM2)   += cpm_uart_cpm2.o
-cpm_uart-objs-$(CONFIG_8xx)    += cpm_uart_cpm1.o
+cpm_uart-objs-$(CONFIG_CPM1)   += cpm_uart_cpm1.o
 
 cpm_uart-objs  := cpm_uart_core.o $(cpm_uart-objs-y)
index cf34d26ff6cdd642849fe61ae0f60af71ed04f94..0ad027b958732cbc1234290cf99fe49e1bb34896 100644 (file)
@@ -19,7 +19,7 @@
 
 #if defined(CONFIG_CPM2)
 #include "cpm_uart_cpm2.h"
-#elif defined(CONFIG_8xx)
+#elif defined(CONFIG_CPM1)
 #include "cpm_uart_cpm1.h"
 #endif
 
index fddb1fd4d9d3347d2ef790e1e796d7338ba1b385..08431adeacd5dcd4f24e4ba395a228eab1060457 100644 (file)
@@ -1435,7 +1435,7 @@ static int cpm_uart_remove(struct platform_device *ofdev)
        return uart_remove_one_port(&cpm_reg, &pinfo->port);
 }
 
-static struct of_device_id cpm_uart_match[] = {
+static const struct of_device_id cpm_uart_match[] = {
        {
                .compatible = "fsl,cpm1-smc-uart",
        },
index 64fe25a4285c2d1fe0f13c9ea9c91880fdd40ad9..5fdc9f3ecd644d9b58a0f9a10f150296b68282d7 100644 (file)
@@ -10,6 +10,9 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+
+#define pr_fmt(fmt)    KBUILD_MODNAME ": " fmt
+
 #include <linux/console.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -34,6 +37,10 @@ static struct earlycon_device early_console_dev = {
        .con = &early_con,
 };
 
+extern struct earlycon_id __earlycon_table[];
+static const struct earlycon_id __earlycon_table_sentinel
+       __used __section(__earlycon_table_end);
+
 static const struct of_device_id __earlycon_of_table_sentinel
        __used __section(__earlycon_of_table_end);
 
@@ -54,44 +61,29 @@ static void __iomem * __init earlycon_map(unsigned long paddr, size_t size)
        return base;
 }
 
-static int __init parse_options(struct earlycon_device *device,
-                               char *options)
+static int __init parse_options(struct earlycon_device *device, char *options)
 {
        struct uart_port *port = &device->port;
-       int mmio, mmio32, length;
+       int length;
        unsigned long addr;
 
-       if (!options)
-               return -ENODEV;
+       if (uart_parse_earlycon(options, &port->iotype, &addr, &options))
+               return -EINVAL;
 
-       mmio = !strncmp(options, "mmio,", 5);
-       mmio32 = !strncmp(options, "mmio32,", 7);
-       if (mmio || mmio32) {
-               port->iotype = (mmio ? UPIO_MEM : UPIO_MEM32);
-               options += mmio ? 5 : 7;
-               addr = simple_strtoul(options, NULL, 0);
+       switch (port->iotype) {
+       case UPIO_MEM32:
+               port->regshift = 2;     /* fall-through */
+       case UPIO_MEM:
                port->mapbase = addr;
-               if (mmio32)
-                       port->regshift = 2;
-       } else if (!strncmp(options, "io,", 3)) {
-               port->iotype = UPIO_PORT;
-               options += 3;
-               addr = simple_strtoul(options, NULL, 0);
+               break;
+       case UPIO_PORT:
                port->iobase = addr;
-               mmio = 0;
-       } else if (!strncmp(options, "0x", 2)) {
-               port->iotype = UPIO_MEM;
-               addr = simple_strtoul(options, NULL, 0);
-               port->mapbase = addr;
-       } else {
+               break;
+       default:
                return -EINVAL;
        }
 
-       port->uartclk = BASE_BAUD * 16;
-
-       options = strchr(options, ',');
        if (options) {
-               options++;
                device->baud = simple_strtoul(options, NULL, 0);
                length = min(strcspn(options, " ") + 1,
                             (size_t)(sizeof(device->options)));
@@ -100,7 +92,7 @@ static int __init parse_options(struct earlycon_device *device,
 
        if (port->iotype == UPIO_MEM || port->iotype == UPIO_MEM32)
                pr_info("Early serial console at MMIO%s 0x%llx (options '%s')\n",
-                       mmio32 ? "32" : "",
+                       (port->iotype == UPIO_MEM32) ? "32" : "",
                        (unsigned long long)port->mapbase,
                        device->options);
        else
@@ -111,34 +103,21 @@ static int __init parse_options(struct earlycon_device *device,
        return 0;
 }
 
-int __init setup_earlycon(char *buf, const char *match,
-                         int (*setup)(struct earlycon_device *, const char *))
+static int __init register_earlycon(char *buf, const struct earlycon_id *match)
 {
        int err;
-       size_t len;
        struct uart_port *port = &early_console_dev.port;
 
-       if (!buf || !match || !setup)
-               return 0;
-
-       len = strlen(match);
-       if (strncmp(buf, match, len))
-               return 0;
-       if (buf[len] && (buf[len] != ','))
-               return 0;
-
-       buf += len + 1;
-
-       err = parse_options(&early_console_dev, buf);
        /* On parsing error, pass the options buf to the setup function */
-       if (!err)
+       if (buf && !parse_options(&early_console_dev, buf))
                buf = NULL;
 
+       port->uartclk = BASE_BAUD * 16;
        if (port->mapbase)
                port->membase = earlycon_map(port->mapbase, 64);
 
        early_console_dev.con->data = &early_console_dev;
-       err = setup(&early_console_dev, buf);
+       err = match->setup(&early_console_dev, buf);
        if (err < 0)
                return err;
        if (!early_console_dev.con->write)
@@ -148,6 +127,77 @@ int __init setup_earlycon(char *buf, const char *match,
        return 0;
 }
 
+/**
+ *     setup_earlycon - match and register earlycon console
+ *     @buf:   earlycon param string
+ *
+ *     Registers the earlycon console matching the earlycon specified
+ *     in the param string @buf. Acceptable param strings are of the form
+ *        <name>,io|mmio|mmio32,<addr>,<options>
+ *        <name>,0x<addr>,<options>
+ *        <name>,<options>
+ *        <name>
+ *
+ *     Only for the third form does the earlycon setup() method receive the
+ *     <options> string in the 'options' parameter; all other forms set
+ *     the parameter to NULL.
+ *
+ *     Returns 0 if an attempt to register the earlycon was made,
+ *     otherwise negative error code
+ */
+int __init setup_earlycon(char *buf)
+{
+       const struct earlycon_id *match;
+
+       if (!buf || !buf[0])
+               return -EINVAL;
+
+       if (early_con.flags & CON_ENABLED)
+               return -EALREADY;
+
+       for (match = __earlycon_table; match->name[0]; match++) {
+               size_t len = strlen(match->name);
+
+               if (strncmp(buf, match->name, len))
+                       continue;
+
+               if (buf[len]) {
+                       if (buf[len] != ',')
+                               continue;
+                       buf += len + 1;
+               } else
+                       buf = NULL;
+
+               return register_earlycon(buf, match);
+       }
+
+       return -ENOENT;
+}
+
+/* early_param wrapper for setup_earlycon() */
+static int __init param_setup_earlycon(char *buf)
+{
+       int err;
+
+       /*
+        * Just 'earlycon' is a valid param for devicetree earlycons;
+        * don't generate a warning from parse_early_params() in that case
+        */
+       if (!buf || !buf[0])
+               return 0;
+
+       err = setup_earlycon(buf);
+       if (err == -ENOENT) {
+               pr_warn("no match for %s\n", buf);
+               err = 0;
+       } else if (err == -EALREADY) {
+               pr_warn("already registered\n");
+               err = 0;
+       }
+       return err;
+}
+early_param("earlycon", param_setup_earlycon);
+
 int __init of_setup_earlycon(unsigned long addr,
                             int (*setup)(struct earlycon_device *, const char *))
 {
index 3ad1458bfeb0fc32afe790b2aa0f3e36961b7b45..08ce76f4f261043c20d843c88c8d4dfe8167ce64 100644 (file)
@@ -257,7 +257,7 @@ struct lpuart_port {
        struct timer_list       lpuart_timer;
 };
 
-static struct of_device_id lpuart_dt_ids[] = {
+static const struct of_device_id lpuart_dt_ids[] = {
        {
                .compatible = "fsl,vf610-lpuart",
        },
index 0eb29b1c47ac8ea313456df38a45f6720e62246b..c8cfa06371280af6abfd63bd379ee5c121523ad7 100644 (file)
@@ -1,13 +1,10 @@
 /*
- *  Driver for Motorola IMX serial ports
+ * Driver for Motorola/Freescale IMX serial ports
  *
- *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
  *
- *  Author: Sascha Hauer <sascha@saschahauer.de>
- *  Copyright (C) 2004 Pengutronix
- *
- *  Copyright (C) 2009 emlix GmbH
- *  Author: Fabian Godehardt (added IrDA support for iMX)
+ * Author: Sascha Hauer <sascha@saschahauer.de>
+ * Copyright (C) 2004 Pengutronix
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * but WITHOUT 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
- *
- * [29-Mar-2005] Mike Lee
- * Added hardware handshake
  */
 
 #if defined(CONFIG_SERIAL_IMX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 
 #define UART_NR 8
 
-/* i.mx21 type uart runs on all i.mx except i.mx1 */
+/* i.MX21 type uart runs on all i.mx except i.MX1 and i.MX6q */
 enum imx_uart_type {
        IMX1_UART,
        IMX21_UART,
@@ -206,10 +196,8 @@ struct imx_port {
        struct uart_port        port;
        struct timer_list       timer;
        unsigned int            old_status;
-       int                     txirq, rxirq, rtsirq;
        unsigned int            have_rtscts:1;
        unsigned int            dte_mode:1;
-       unsigned int            use_irda:1;
        unsigned int            irda_inv_rx:1;
        unsigned int            irda_inv_tx:1;
        unsigned short          trcv_delay; /* transceiver delay */
@@ -236,12 +224,6 @@ struct imx_port_ucrs {
        unsigned int    ucr3;
 };
 
-#ifdef CONFIG_IRDA
-#define USE_IRDA(sport)        ((sport)->use_irda)
-#else
-#define USE_IRDA(sport)        (0)
-#endif
-
 static struct imx_uart_data imx_uart_devdata[] = {
        [IMX1_UART] = {
                .uts_reg = IMX1_UTS,
@@ -273,7 +255,7 @@ static struct platform_device_id imx_uart_devtype[] = {
 };
 MODULE_DEVICE_TABLE(platform, imx_uart_devtype);
 
-static struct of_device_id imx_uart_dt_ids[] = {
+static const struct of_device_id imx_uart_dt_ids[] = {
        { .compatible = "fsl,imx6q-uart", .data = &imx_uart_devdata[IMX6Q_UART], },
        { .compatible = "fsl,imx1-uart", .data = &imx_uart_devdata[IMX1_UART], },
        { .compatible = "fsl,imx21-uart", .data = &imx_uart_devdata[IMX21_UART], },
@@ -376,48 +358,6 @@ static void imx_stop_tx(struct uart_port *port)
        struct imx_port *sport = (struct imx_port *)port;
        unsigned long temp;
 
-       if (USE_IRDA(sport)) {
-               /* half duplex - wait for end of transmission */
-               int n = 256;
-               while ((--n > 0) &&
-                     !(readl(sport->port.membase + USR2) & USR2_TXDC)) {
-                       udelay(5);
-                       barrier();
-               }
-               /*
-                * irda transceiver - wait a bit more to avoid
-                * cutoff, hardware dependent
-                */
-               udelay(sport->trcv_delay);
-
-               /*
-                * half duplex - reactivate receive mode,
-                * flush receive pipe echo crap
-                */
-               if (readl(sport->port.membase + USR2) & USR2_TXDC) {
-                       temp = readl(sport->port.membase + UCR1);
-                       temp &= ~(UCR1_TXMPTYEN | UCR1_TRDYEN);
-                       writel(temp, sport->port.membase + UCR1);
-
-                       temp = readl(sport->port.membase + UCR4);
-                       temp &= ~(UCR4_TCEN);
-                       writel(temp, sport->port.membase + UCR4);
-
-                       while (readl(sport->port.membase + URXD0) &
-                              URXD_CHARRDY)
-                               barrier();
-
-                       temp = readl(sport->port.membase + UCR1);
-                       temp |= UCR1_RRDYEN;
-                       writel(temp, sport->port.membase + UCR1);
-
-                       temp = readl(sport->port.membase + UCR4);
-                       temp |= UCR4_DREN;
-                       writel(temp, sport->port.membase + UCR4);
-               }
-               return;
-       }
-
        /*
         * We are maybe in the SMP context, so if the DMA TX thread is running
         * on other cpu, we have to wait for it to finish.
@@ -425,8 +365,23 @@ static void imx_stop_tx(struct uart_port *port)
        if (sport->dma_is_enabled && sport->dma_is_txing)
                return;
 
-       temp = readl(sport->port.membase + UCR1);
-       writel(temp & ~UCR1_TXMPTYEN, sport->port.membase + UCR1);
+       temp = readl(port->membase + UCR1);
+       writel(temp & ~UCR1_TXMPTYEN, port->membase + UCR1);
+
+       /* in rs485 mode disable transmitter if shifter is empty */
+       if (port->rs485.flags & SER_RS485_ENABLED &&
+           readl(port->membase + USR2) & USR2_TXDC) {
+               temp = readl(port->membase + UCR2);
+               if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
+                       temp &= ~UCR2_CTS;
+               else
+                       temp |= UCR2_CTS;
+               writel(temp, port->membase + UCR2);
+
+               temp = readl(port->membase + UCR4);
+               temp &= ~UCR4_TCEN;
+               writel(temp, port->membase + UCR4);
+       }
 }
 
 /*
@@ -620,15 +575,18 @@ static void imx_start_tx(struct uart_port *port)
        struct imx_port *sport = (struct imx_port *)port;
        unsigned long temp;
 
-       if (USE_IRDA(sport)) {
-               /* half duplex in IrDA mode; have to disable receive mode */
-               temp = readl(sport->port.membase + UCR4);
-               temp &= ~(UCR4_DREN);
-               writel(temp, sport->port.membase + UCR4);
+       if (port->rs485.flags & SER_RS485_ENABLED) {
+               /* enable transmitter and shifter empty irq */
+               temp = readl(port->membase + UCR2);
+               if (port->rs485.flags & SER_RS485_RTS_ON_SEND)
+                       temp &= ~UCR2_CTS;
+               else
+                       temp |= UCR2_CTS;
+               writel(temp, port->membase + UCR2);
 
-               temp = readl(sport->port.membase + UCR1);
-               temp &= ~(UCR1_RRDYEN);
-               writel(temp, sport->port.membase + UCR1);
+               temp = readl(port->membase + UCR4);
+               temp |= UCR4_TCEN;
+               writel(temp, port->membase + UCR4);
        }
 
        if (!sport->dma_is_enabled) {
@@ -636,16 +594,6 @@ static void imx_start_tx(struct uart_port *port)
                writel(temp | UCR1_TXMPTYEN, sport->port.membase + UCR1);
        }
 
-       if (USE_IRDA(sport)) {
-               temp = readl(sport->port.membase + UCR1);
-               temp |= UCR1_TRDYEN;
-               writel(temp, sport->port.membase + UCR1);
-
-               temp = readl(sport->port.membase + UCR4);
-               temp |= UCR4_TCEN;
-               writel(temp, sport->port.membase + UCR4);
-       }
-
        if (sport->dma_is_enabled) {
                if (sport->port.x_char) {
                        /* We have X-char to send, so enable TX IRQ and
@@ -796,6 +744,7 @@ static irqreturn_t imx_int(int irq, void *dev_id)
        unsigned int sts2;
 
        sts = readl(sport->port.membase + USR1);
+       sts2 = readl(sport->port.membase + USR2);
 
        if (sts & USR1_RRDY) {
                if (sport->dma_is_enabled)
@@ -804,8 +753,10 @@ static irqreturn_t imx_int(int irq, void *dev_id)
                        imx_rxint(irq, dev_id);
        }
 
-       if (sts & USR1_TRDY &&
-                       readl(sport->port.membase + UCR1) & UCR1_TXMPTYEN)
+       if ((sts & USR1_TRDY &&
+            readl(sport->port.membase + UCR1) & UCR1_TXMPTYEN) ||
+           (sts2 & USR2_TXDC &&
+            readl(sport->port.membase + UCR4) & UCR4_TCEN))
                imx_txint(irq, dev_id);
 
        if (sts & USR1_RTSD)
@@ -814,11 +765,10 @@ static irqreturn_t imx_int(int irq, void *dev_id)
        if (sts & USR1_AWAKE)
                writel(USR1_AWAKE, sport->port.membase + USR1);
 
-       sts2 = readl(sport->port.membase + USR2);
        if (sts2 & USR2_ORE) {
                dev_err(sport->port.dev, "Rx FIFO overrun\n");
                sport->port.icount.overrun++;
-               writel(sts2 | USR2_ORE, sport->port.membase + USR2);
+               writel(USR2_ORE, sport->port.membase + USR2);
        }
 
        return IRQ_HANDLED;
@@ -866,11 +816,13 @@ static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl)
        struct imx_port *sport = (struct imx_port *)port;
        unsigned long temp;
 
-       temp = readl(sport->port.membase + UCR2) & ~(UCR2_CTS | UCR2_CTSC);
-       if (mctrl & TIOCM_RTS)
-               temp |= UCR2_CTS | UCR2_CTSC;
-
-       writel(temp, sport->port.membase + UCR2);
+       if (!(port->rs485.flags & SER_RS485_ENABLED)) {
+               temp = readl(sport->port.membase + UCR2);
+               temp &= ~(UCR2_CTS | UCR2_CTSC);
+               if (mctrl & TIOCM_RTS)
+                       temp |= UCR2_CTS | UCR2_CTSC;
+               writel(temp, sport->port.membase + UCR2);
+       }
 
        temp = readl(sport->port.membase + uts_reg(sport)) & ~UTS_LOOP;
        if (mctrl & TIOCM_LOOP)
@@ -1156,9 +1108,6 @@ static int imx_startup(struct uart_port *port)
         */
        temp = readl(sport->port.membase + UCR4);
 
-       if (USE_IRDA(sport))
-               temp |= UCR4_IRSC;
-
        /* set the trigger level for CTS */
        temp &= ~(UCR4_CTSTL_MASK << UCR4_CTSTL_SHF);
        temp |= CTSTL << UCR4_CTSTL_SHF;
@@ -1181,10 +1130,12 @@ static int imx_startup(struct uart_port *port)
                imx_uart_dma_init(sport);
 
        spin_lock_irqsave(&sport->port.lock, flags);
+
        /*
         * Finally, clear and enable interrupts
         */
        writel(USR1_RTSD, sport->port.membase + USR1);
+       writel(USR2_ORE, sport->port.membase + USR2);
 
        if (sport->dma_is_inited && !sport->dma_is_enabled)
                imx_enable_dma(sport);
@@ -1192,17 +1143,8 @@ static int imx_startup(struct uart_port *port)
        temp = readl(sport->port.membase + UCR1);
        temp |= UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN;
 
-       if (USE_IRDA(sport)) {
-               temp |= UCR1_IREN;
-               temp &= ~(UCR1_RTSDEN);
-       }
-
        writel(temp, sport->port.membase + UCR1);
 
-       /* Clear any pending ORE flag before enabling interrupt */
-       temp = readl(sport->port.membase + USR2);
-       writel(temp | USR2_ORE, sport->port.membase + USR2);
-
        temp = readl(sport->port.membase + UCR4);
        temp |= UCR4_OREN;
        writel(temp, sport->port.membase + UCR4);
@@ -1219,38 +1161,12 @@ static int imx_startup(struct uart_port *port)
                writel(temp, sport->port.membase + UCR3);
        }
 
-       if (USE_IRDA(sport)) {
-               temp = readl(sport->port.membase + UCR4);
-               if (sport->irda_inv_rx)
-                       temp |= UCR4_INVR;
-               else
-                       temp &= ~(UCR4_INVR);
-               writel(temp | UCR4_DREN, sport->port.membase + UCR4);
-
-               temp = readl(sport->port.membase + UCR3);
-               if (sport->irda_inv_tx)
-                       temp |= UCR3_INVT;
-               else
-                       temp &= ~(UCR3_INVT);
-               writel(temp, sport->port.membase + UCR3);
-       }
-
        /*
         * Enable modem status interrupts
         */
        imx_enable_ms(&sport->port);
        spin_unlock_irqrestore(&sport->port.lock, flags);
 
-       if (USE_IRDA(sport)) {
-               struct imxuart_platform_data *pdata;
-               pdata = dev_get_platdata(sport->port.dev);
-               sport->irda_inv_rx = pdata->irda_inv_rx;
-               sport->irda_inv_tx = pdata->irda_inv_tx;
-               sport->trcv_delay = pdata->transceiver_delay;
-               if (pdata->irda_enable)
-                       pdata->irda_enable(1);
-       }
-
        return 0;
 }
 
@@ -1286,13 +1202,6 @@ static void imx_shutdown(struct uart_port *port)
        writel(temp, sport->port.membase + UCR2);
        spin_unlock_irqrestore(&sport->port.lock, flags);
 
-       if (USE_IRDA(sport)) {
-               struct imxuart_platform_data *pdata;
-               pdata = dev_get_platdata(sport->port.dev);
-               if (pdata->irda_enable)
-                       pdata->irda_enable(0);
-       }
-
        /*
         * Stop our timer.
         */
@@ -1305,8 +1214,6 @@ static void imx_shutdown(struct uart_port *port)
        spin_lock_irqsave(&sport->port.lock, flags);
        temp = readl(sport->port.membase + UCR1);
        temp &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN);
-       if (USE_IRDA(sport))
-               temp &= ~(UCR1_IREN);
 
        writel(temp, sport->port.membase + UCR1);
        spin_unlock_irqrestore(&sport->port.lock, flags);
@@ -1320,7 +1227,7 @@ static void imx_flush_buffer(struct uart_port *port)
        struct imx_port *sport = (struct imx_port *)port;
        struct scatterlist *sgl = &sport->tx_sgl[0];
        unsigned long temp;
-       int i = 100, ubir, ubmr, ubrc, uts;
+       int i = 100, ubir, ubmr, uts;
 
        if (!sport->dma_chan_tx)
                return;
@@ -1345,7 +1252,6 @@ static void imx_flush_buffer(struct uart_port *port)
         */
        ubir = readl(sport->port.membase + UBIR);
        ubmr = readl(sport->port.membase + UBMR);
-       ubrc = readl(sport->port.membase + UBRC);
        uts = readl(sport->port.membase + IMX21_UTS);
 
        temp = readl(sport->port.membase + UCR2);
@@ -1358,7 +1264,6 @@ static void imx_flush_buffer(struct uart_port *port)
        /* Restore the registers */
        writel(ubir, sport->port.membase + UBIR);
        writel(ubmr, sport->port.membase + UBMR);
-       writel(ubrc, sport->port.membase + UBRC);
        writel(uts, sport->port.membase + IMX21_UTS);
 }
 
@@ -1374,15 +1279,6 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
        unsigned long num, denom;
        uint64_t tdiv64;
 
-       /*
-        * If we don't support modem control lines, don't allow
-        * these to be set.
-        */
-       if (0) {
-               termios->c_cflag &= ~(HUPCL | CRTSCTS | CMSPAR);
-               termios->c_cflag |= CLOCAL;
-       }
-
        /*
         * We only support CS7 and CS8.
         */
@@ -1401,11 +1297,26 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
        if (termios->c_cflag & CRTSCTS) {
                if (sport->have_rtscts) {
                        ucr2 &= ~UCR2_IRTS;
-                       ucr2 |= UCR2_CTSC;
+
+                       if (port->rs485.flags & SER_RS485_ENABLED) {
+                               /*
+                                * RTS is mandatory for rs485 operation, so keep
+                                * it under manual control and keep transmitter
+                                * disabled.
+                                */
+                               if (!(port->rs485.flags &
+                                     SER_RS485_RTS_AFTER_SEND))
+                                       ucr2 |= UCR2_CTS;
+                       } else {
+                               ucr2 |= UCR2_CTSC;
+                       }
                } else {
                        termios->c_cflag &= ~CRTSCTS;
                }
-       }
+       } else if (port->rs485.flags & SER_RS485_ENABLED)
+               /* disable transmitter */
+               if (!(port->rs485.flags & SER_RS485_RTS_AFTER_SEND))
+                       ucr2 |= UCR2_CTS;
 
        if (termios->c_cflag & CSTOPB)
                ucr2 |= UCR2_STPB;
@@ -1471,24 +1382,16 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
                        sport->port.membase + UCR2);
        old_txrxen &= (UCR2_TXEN | UCR2_RXEN);
 
-       if (USE_IRDA(sport)) {
-               /*
-                * use maximum available submodule frequency to
-                * avoid missing short pulses due to low sampling rate
-                */
+       /* custom-baudrate handling */
+       div = sport->port.uartclk / (baud * 16);
+       if (baud == 38400 && quot != div)
+               baud = sport->port.uartclk / (quot * 16);
+
+       div = sport->port.uartclk / (baud * 16);
+       if (div > 7)
+               div = 7;
+       if (!div)
                div = 1;
-       } else {
-               /* custom-baudrate handling */
-               div = sport->port.uartclk / (baud * 16);
-               if (baud == 38400 && quot != div)
-                       baud = sport->port.uartclk / (quot * 16);
-
-               div = sport->port.uartclk / (baud * 16);
-               if (div > 7)
-                       div = 7;
-               if (!div)
-                       div = 1;
-       }
 
        rational_best_approximation(16 * div * baud, sport->port.uartclk,
                1 << 16, 1 << 16, &num, &denom);
@@ -1635,6 +1538,38 @@ static void imx_poll_put_char(struct uart_port *port, unsigned char c)
 }
 #endif
 
+static int imx_rs485_config(struct uart_port *port,
+                           struct serial_rs485 *rs485conf)
+{
+       struct imx_port *sport = (struct imx_port *)port;
+
+       /* unimplemented */
+       rs485conf->delay_rts_before_send = 0;
+       rs485conf->delay_rts_after_send = 0;
+       rs485conf->flags |= SER_RS485_RX_DURING_TX;
+
+       /* RTS is required to control the transmitter */
+       if (!sport->have_rtscts)
+               rs485conf->flags &= ~SER_RS485_ENABLED;
+
+       if (rs485conf->flags & SER_RS485_ENABLED) {
+               unsigned long temp;
+
+               /* disable transmitter */
+               temp = readl(sport->port.membase + UCR2);
+               temp &= ~UCR2_CTSC;
+               if (rs485conf->flags & SER_RS485_RTS_AFTER_SEND)
+                       temp &= ~UCR2_CTS;
+               else
+                       temp |= UCR2_CTS;
+               writel(temp, sport->port.membase + UCR2);
+       }
+
+       port->rs485 = *rs485conf;
+
+       return 0;
+}
+
 static struct uart_ops imx_pops = {
        .tx_empty       = imx_tx_empty,
        .set_mctrl      = imx_set_mctrl,
@@ -1927,9 +1862,6 @@ static int serial_imx_probe_dt(struct imx_port *sport,
        if (of_get_property(np, "fsl,uart-has-rtscts", NULL))
                sport->have_rtscts = 1;
 
-       if (of_get_property(np, "fsl,irda-mode", NULL))
-               sport->use_irda = 1;
-
        if (of_get_property(np, "fsl,dte-mode", NULL))
                sport->dte_mode = 1;
 
@@ -1958,9 +1890,6 @@ static void serial_imx_probe_pdata(struct imx_port *sport,
 
        if (pdata->flags & IMXUART_HAVE_RTSCTS)
                sport->have_rtscts = 1;
-
-       if (pdata->flags & IMXUART_IRDA)
-               sport->use_irda = 1;
 }
 
 static int serial_imx_probe(struct platform_device *pdev)
@@ -1969,6 +1898,7 @@ static int serial_imx_probe(struct platform_device *pdev)
        void __iomem *base;
        int ret = 0;
        struct resource *res;
+       int txirq, rxirq, rtsirq;
 
        sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL);
        if (!sport)
@@ -1985,17 +1915,21 @@ static int serial_imx_probe(struct platform_device *pdev)
        if (IS_ERR(base))
                return PTR_ERR(base);
 
+       rxirq = platform_get_irq(pdev, 0);
+       txirq = platform_get_irq(pdev, 1);
+       rtsirq = platform_get_irq(pdev, 2);
+
        sport->port.dev = &pdev->dev;
        sport->port.mapbase = res->start;
        sport->port.membase = base;
        sport->port.type = PORT_IMX,
        sport->port.iotype = UPIO_MEM;
-       sport->port.irq = platform_get_irq(pdev, 0);
-       sport->rxirq = platform_get_irq(pdev, 0);
-       sport->txirq = platform_get_irq(pdev, 1);
-       sport->rtsirq = platform_get_irq(pdev, 2);
+       sport->port.irq = rxirq;
        sport->port.fifosize = 32;
        sport->port.ops = &imx_pops;
+       sport->port.rs485_config = imx_rs485_config;
+       sport->port.rs485.flags =
+               SER_RS485_RTS_ON_SEND | SER_RS485_RX_DURING_TX;
        sport->port.flags = UPF_BOOT_AUTOCONF;
        init_timer(&sport->timer);
        sport->timer.function = imx_timeout;
@@ -2021,27 +1955,18 @@ static int serial_imx_probe(struct platform_device *pdev)
         * Allocate the IRQ(s) i.MX1 has three interrupts whereas later
         * chips only have one interrupt.
         */
-       if (sport->txirq > 0) {
-               ret = devm_request_irq(&pdev->dev, sport->rxirq, imx_rxint, 0,
+       if (txirq > 0) {
+               ret = devm_request_irq(&pdev->dev, rxirq, imx_rxint, 0,
                                       dev_name(&pdev->dev), sport);
                if (ret)
                        return ret;
 
-               ret = devm_request_irq(&pdev->dev, sport->txirq, imx_txint, 0,
+               ret = devm_request_irq(&pdev->dev, txirq, imx_txint, 0,
                                       dev_name(&pdev->dev), sport);
                if (ret)
                        return ret;
-
-               /* do not use RTS IRQ on IrDA */
-               if (!USE_IRDA(sport)) {
-                       ret = devm_request_irq(&pdev->dev, sport->rtsirq,
-                                              imx_rtsint, 0,
-                                              dev_name(&pdev->dev), sport);
-                       if (ret)
-                               return ret;
-               }
        } else {
-               ret = devm_request_irq(&pdev->dev, sport->port.irq, imx_int, 0,
+               ret = devm_request_irq(&pdev->dev, rxirq, imx_int, 0,
                                       dev_name(&pdev->dev), sport);
                if (ret)
                        return ret;
index bfb0681195b600354babc4fcc923473ecbaf44b3..4eb12a9cae76ce71e59745c4f4acde5b9d928bd5 100644 (file)
@@ -570,7 +570,7 @@ static inline void cls_parse_isr(struct jsm_board *brd, uint port)
         * verified in the interrupt routine.
         */
 
-       if (port > brd->nasync)
+       if (port >= brd->nasync)
                return;
 
        ch = brd->channels[port];
index 7291c2117daaf180f54b314003366e235410d5bd..932b2accd06f7099e58adc04ff0fb4d028e81a18 100644 (file)
@@ -724,7 +724,7 @@ static inline void neo_parse_isr(struct jsm_board *brd, u32 port)
        if (!brd)
                return;
 
-       if (port > brd->maxports)
+       if (port >= brd->maxports)
                return;
 
        ch = brd->channels[port];
@@ -840,7 +840,7 @@ static inline void neo_parse_lsr(struct jsm_board *brd, u32 port)
        if (!brd)
                return;
 
-       if (port > brd->maxports)
+       if (port >= brd->maxports)
                return;
 
        ch = brd->channels[port];
@@ -1180,7 +1180,7 @@ static irqreturn_t neo_intr(int irq, void *voidbrd)
                         */
 
                        /* Verify the port is in range. */
-                       if (port > brd->nasync)
+                       if (port >= brd->nasync)
                                continue;
 
                        ch = brd->channels[port];
index 79f9a9eff5455e561d3cdb98e57d0aee16281d38..077377259a2ce459f515c41da7f4e016d2804459 100644 (file)
@@ -782,7 +782,7 @@ static int max3100_probe(struct spi_device *spi)
        pdata = dev_get_platdata(&spi->dev);
        max3100s[i]->crystal = pdata->crystal;
        max3100s[i]->loopback = pdata->loopback;
-       max3100s[i]->poll_time = pdata->poll_time * HZ / 1000;
+       max3100s[i]->poll_time = msecs_to_jiffies(pdata->poll_time);
        if (pdata->poll_time > 0 && max3100s[i]->poll_time == 0)
                max3100s[i]->poll_time = 1;
        max3100s[i]->max3100_hw_suspend = pdata->max3100_hw_suspend;
diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c
deleted file mode 100644 (file)
index 8fe4501..0000000
+++ /dev/null
@@ -1,1505 +0,0 @@
-/*
- * mfd.c: driver for High Speed UART device of Intel Medfield platform
- *
- * Refer pxa.c, 8250.c and some other drivers in drivers/serial/
- *
- * (C) Copyright 2010 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; version 2
- * of the License.
- */
-
-/* Notes:
- * 1. DMA channel allocation: 0/1 channel are assigned to port 0,
- *    2/3 chan to port 1, 4/5 chan to port 3. Even number chans
- *    are used for RX, odd chans for TX
- *
- * 2. The RI/DSR/DCD/DTR are not pinned out, DCD & DSR are always
- *    asserted, only when the HW is reset the DDCD and DDSR will
- *    be triggered
- */
-
-#if defined(CONFIG_SERIAL_MFD_HSU_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/slab.h>
-#include <linux/serial_reg.h>
-#include <linux/circ_buf.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/serial_mfd.h>
-#include <linux/dma-mapping.h>
-#include <linux/pci.h>
-#include <linux/nmi.h>
-#include <linux/io.h>
-#include <linux/debugfs.h>
-#include <linux/pm_runtime.h>
-
-#define HSU_DMA_BUF_SIZE       2048
-
-#define chan_readl(chan, offset)       readl(chan->reg + offset)
-#define chan_writel(chan, offset, val) writel(val, chan->reg + offset)
-
-#define mfd_readl(obj, offset)         readl(obj->reg + offset)
-#define mfd_writel(obj, offset, val)   writel(val, obj->reg + offset)
-
-static int hsu_dma_enable;
-module_param(hsu_dma_enable, int, 0);
-MODULE_PARM_DESC(hsu_dma_enable,
-                "It is a bitmap to set working mode, if bit[x] is 1, then port[x] will work in DMA mode, otherwise in PIO mode.");
-
-struct hsu_dma_buffer {
-       u8              *buf;
-       dma_addr_t      dma_addr;
-       u32             dma_size;
-       u32             ofs;
-};
-
-struct hsu_dma_chan {
-       u32     id;
-       enum dma_data_direction dirt;
-       struct uart_hsu_port    *uport;
-       void __iomem            *reg;
-};
-
-struct uart_hsu_port {
-       struct uart_port        port;
-       unsigned char           ier;
-       unsigned char           lcr;
-       unsigned char           mcr;
-       unsigned int            lsr_break_flag;
-       char                    name[12];
-       int                     index;
-       struct device           *dev;
-
-       struct hsu_dma_chan     *txc;
-       struct hsu_dma_chan     *rxc;
-       struct hsu_dma_buffer   txbuf;
-       struct hsu_dma_buffer   rxbuf;
-       int                     use_dma;        /* flag for DMA/PIO */
-       int                     running;
-       int                     dma_tx_on;
-};
-
-/* Top level data structure of HSU */
-struct hsu_port {
-       void __iomem    *reg;
-       unsigned long   paddr;
-       unsigned long   iolen;
-       u32             irq;
-
-       struct uart_hsu_port    port[3];
-       struct hsu_dma_chan     chans[10];
-
-       struct dentry *debugfs;
-};
-
-static inline unsigned int serial_in(struct uart_hsu_port *up, int offset)
-{
-       unsigned int val;
-
-       if (offset > UART_MSR) {
-               offset <<= 2;
-               val = readl(up->port.membase + offset);
-       } else
-               val = (unsigned int)readb(up->port.membase + offset);
-
-       return val;
-}
-
-static inline void serial_out(struct uart_hsu_port *up, int offset, int value)
-{
-       if (offset > UART_MSR) {
-               offset <<= 2;
-               writel(value, up->port.membase + offset);
-       } else {
-               unsigned char val = value & 0xff;
-               writeb(val, up->port.membase + offset);
-       }
-}
-
-#ifdef CONFIG_DEBUG_FS
-
-#define HSU_REGS_BUFSIZE       1024
-
-
-static ssize_t port_show_regs(struct file *file, char __user *user_buf,
-                               size_t count, loff_t *ppos)
-{
-       struct uart_hsu_port *up = file->private_data;
-       char *buf;
-       u32 len = 0;
-       ssize_t ret;
-
-       buf = kzalloc(HSU_REGS_BUFSIZE, GFP_KERNEL);
-       if (!buf)
-               return 0;
-
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "MFD HSU port[%d] regs:\n", up->index);
-
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "=================================\n");
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "IER: \t\t0x%08x\n", serial_in(up, UART_IER));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "IIR: \t\t0x%08x\n", serial_in(up, UART_IIR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "LCR: \t\t0x%08x\n", serial_in(up, UART_LCR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "MCR: \t\t0x%08x\n", serial_in(up, UART_MCR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "LSR: \t\t0x%08x\n", serial_in(up, UART_LSR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "MSR: \t\t0x%08x\n", serial_in(up, UART_MSR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "FOR: \t\t0x%08x\n", serial_in(up, UART_FOR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "PS: \t\t0x%08x\n", serial_in(up, UART_PS));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "MUL: \t\t0x%08x\n", serial_in(up, UART_MUL));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "DIV: \t\t0x%08x\n", serial_in(up, UART_DIV));
-
-       if (len > HSU_REGS_BUFSIZE)
-               len = HSU_REGS_BUFSIZE;
-
-       ret =  simple_read_from_buffer(user_buf, count, ppos, buf, len);
-       kfree(buf);
-       return ret;
-}
-
-static ssize_t dma_show_regs(struct file *file, char __user *user_buf,
-                               size_t count, loff_t *ppos)
-{
-       struct hsu_dma_chan *chan = file->private_data;
-       char *buf;
-       u32 len = 0;
-       ssize_t ret;
-
-       buf = kzalloc(HSU_REGS_BUFSIZE, GFP_KERNEL);
-       if (!buf)
-               return 0;
-
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "MFD HSU DMA channel [%d] regs:\n", chan->id);
-
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "=================================\n");
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "CR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_CR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "DCR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_DCR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "BSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_BSR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "MOTSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_MOTSR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D0SAR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D0TSR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D1SAR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D1TSR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D2SAR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D2TSR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D3SAR));
-       len += snprintf(buf + len, HSU_REGS_BUFSIZE - len,
-                       "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D3TSR));
-
-       if (len > HSU_REGS_BUFSIZE)
-               len = HSU_REGS_BUFSIZE;
-
-       ret =  simple_read_from_buffer(user_buf, count, ppos, buf, len);
-       kfree(buf);
-       return ret;
-}
-
-static const struct file_operations port_regs_ops = {
-       .owner          = THIS_MODULE,
-       .open           = simple_open,
-       .read           = port_show_regs,
-       .llseek         = default_llseek,
-};
-
-static const struct file_operations dma_regs_ops = {
-       .owner          = THIS_MODULE,
-       .open           = simple_open,
-       .read           = dma_show_regs,
-       .llseek         = default_llseek,
-};
-
-static int hsu_debugfs_init(struct hsu_port *hsu)
-{
-       int i;
-       char name[32];
-
-       hsu->debugfs = debugfs_create_dir("hsu", NULL);
-       if (!hsu->debugfs)
-               return -ENOMEM;
-
-       for (i = 0; i < 3; i++) {
-               snprintf(name, sizeof(name), "port_%d_regs", i);
-               debugfs_create_file(name, S_IFREG | S_IRUGO,
-                       hsu->debugfs, (void *)(&hsu->port[i]), &port_regs_ops);
-       }
-
-       for (i = 0; i < 6; i++) {
-               snprintf(name, sizeof(name), "dma_chan_%d_regs", i);
-               debugfs_create_file(name, S_IFREG | S_IRUGO,
-                       hsu->debugfs, (void *)&hsu->chans[i], &dma_regs_ops);
-       }
-
-       return 0;
-}
-
-static void hsu_debugfs_remove(struct hsu_port *hsu)
-{
-       if (hsu->debugfs)
-               debugfs_remove_recursive(hsu->debugfs);
-}
-
-#else
-static inline int hsu_debugfs_init(struct hsu_port *hsu)
-{
-       return 0;
-}
-
-static inline void hsu_debugfs_remove(struct hsu_port *hsu)
-{
-}
-#endif /* CONFIG_DEBUG_FS */
-
-static void serial_hsu_enable_ms(struct uart_port *port)
-{
-       struct uart_hsu_port *up =
-               container_of(port, struct uart_hsu_port, port);
-
-       up->ier |= UART_IER_MSI;
-       serial_out(up, UART_IER, up->ier);
-}
-
-static void hsu_dma_tx(struct uart_hsu_port *up)
-{
-       struct circ_buf *xmit = &up->port.state->xmit;
-       struct hsu_dma_buffer *dbuf = &up->txbuf;
-       int count;
-
-       /* test_and_set_bit may be better, but anyway it's in lock protected mode */
-       if (up->dma_tx_on)
-               return;
-
-       /* Update the circ buf info */
-       xmit->tail += dbuf->ofs;
-       xmit->tail &= UART_XMIT_SIZE - 1;
-
-       up->port.icount.tx += dbuf->ofs;
-       dbuf->ofs = 0;
-
-       /* Disable the channel */
-       chan_writel(up->txc, HSU_CH_CR, 0x0);
-
-       if (!uart_circ_empty(xmit) && !uart_tx_stopped(&up->port)) {
-               dma_sync_single_for_device(up->port.dev,
-                                          dbuf->dma_addr,
-                                          dbuf->dma_size,
-                                          DMA_TO_DEVICE);
-
-               count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
-               dbuf->ofs = count;
-
-               /* Reprogram the channel */
-               chan_writel(up->txc, HSU_CH_D0SAR, dbuf->dma_addr + xmit->tail);
-               chan_writel(up->txc, HSU_CH_D0TSR, count);
-
-               /* Reenable the channel */
-               chan_writel(up->txc, HSU_CH_DCR, 0x1
-                                                | (0x1 << 8)
-                                                | (0x1 << 16)
-                                                | (0x1 << 24));
-               up->dma_tx_on = 1;
-               chan_writel(up->txc, HSU_CH_CR, 0x1);
-       }
-
-       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-               uart_write_wakeup(&up->port);
-}
-
-/* The buffer is already cache coherent */
-static void hsu_dma_start_rx_chan(struct hsu_dma_chan *rxc,
-                                       struct hsu_dma_buffer *dbuf)
-{
-       dbuf->ofs = 0;
-
-       chan_writel(rxc, HSU_CH_BSR, 32);
-       chan_writel(rxc, HSU_CH_MOTSR, 4);
-
-       chan_writel(rxc, HSU_CH_D0SAR, dbuf->dma_addr);
-       chan_writel(rxc, HSU_CH_D0TSR, dbuf->dma_size);
-       chan_writel(rxc, HSU_CH_DCR, 0x1 | (0x1 << 8)
-                                        | (0x1 << 16)
-                                        | (0x1 << 24)  /* timeout bit, see HSU Errata 1 */
-                                        );
-       chan_writel(rxc, HSU_CH_CR, 0x3);
-}
-
-/* Protected by spin_lock_irqsave(port->lock) */
-static void serial_hsu_start_tx(struct uart_port *port)
-{
-       struct uart_hsu_port *up =
-               container_of(port, struct uart_hsu_port, port);
-
-       if (up->use_dma) {
-               hsu_dma_tx(up);
-       } else if (!(up->ier & UART_IER_THRI)) {
-               up->ier |= UART_IER_THRI;
-               serial_out(up, UART_IER, up->ier);
-       }
-}
-
-static void serial_hsu_stop_tx(struct uart_port *port)
-{
-       struct uart_hsu_port *up =
-               container_of(port, struct uart_hsu_port, port);
-       struct hsu_dma_chan *txc = up->txc;
-
-       if (up->use_dma)
-               chan_writel(txc, HSU_CH_CR, 0x0);
-       else if (up->ier & UART_IER_THRI) {
-               up->ier &= ~UART_IER_THRI;
-               serial_out(up, UART_IER, up->ier);
-       }
-}
-
-/* This is always called in spinlock protected mode, so
- * modify timeout timer is safe here */
-static void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts,
-                       unsigned long *flags)
-{
-       struct hsu_dma_buffer *dbuf = &up->rxbuf;
-       struct hsu_dma_chan *chan = up->rxc;
-       struct uart_port *port = &up->port;
-       struct tty_port *tport = &port->state->port;
-       int count;
-
-       /*
-        * First need to know how many is already transferred,
-        * then check if its a timeout DMA irq, and return
-        * the trail bytes out, push them up and reenable the
-        * channel
-        */
-
-       /* Timeout IRQ, need wait some time, see Errata 2 */
-       if (int_sts & 0xf00)
-               udelay(2);
-
-       /* Stop the channel */
-       chan_writel(chan, HSU_CH_CR, 0x0);
-
-       count = chan_readl(chan, HSU_CH_D0SAR) - dbuf->dma_addr;
-       if (!count) {
-               /* Restart the channel before we leave */
-               chan_writel(chan, HSU_CH_CR, 0x3);
-               return;
-       }
-
-       dma_sync_single_for_cpu(port->dev, dbuf->dma_addr,
-                       dbuf->dma_size, DMA_FROM_DEVICE);
-
-       /*
-        * Head will only wrap around when we recycle
-        * the DMA buffer, and when that happens, we
-        * explicitly set tail to 0. So head will
-        * always be greater than tail.
-        */
-       tty_insert_flip_string(tport, dbuf->buf, count);
-       port->icount.rx += count;
-
-       dma_sync_single_for_device(up->port.dev, dbuf->dma_addr,
-                       dbuf->dma_size, DMA_FROM_DEVICE);
-
-       /* Reprogram the channel */
-       chan_writel(chan, HSU_CH_D0SAR, dbuf->dma_addr);
-       chan_writel(chan, HSU_CH_D0TSR, dbuf->dma_size);
-       chan_writel(chan, HSU_CH_DCR, 0x1
-                                        | (0x1 << 8)
-                                        | (0x1 << 16)
-                                        | (0x1 << 24)  /* timeout bit, see HSU Errata 1 */
-                                        );
-       spin_unlock_irqrestore(&up->port.lock, *flags);
-       tty_flip_buffer_push(tport);
-       spin_lock_irqsave(&up->port.lock, *flags);
-
-       chan_writel(chan, HSU_CH_CR, 0x3);
-
-}
-
-static void serial_hsu_stop_rx(struct uart_port *port)
-{
-       struct uart_hsu_port *up =
-               container_of(port, struct uart_hsu_port, port);
-       struct hsu_dma_chan *chan = up->rxc;
-
-       if (up->use_dma)
-               chan_writel(chan, HSU_CH_CR, 0x2);
-       else {
-               up->ier &= ~UART_IER_RLSI;
-               up->port.read_status_mask &= ~UART_LSR_DR;
-               serial_out(up, UART_IER, up->ier);
-       }
-}
-
-static inline void receive_chars(struct uart_hsu_port *up, int *status,
-               unsigned long *flags)
-{
-       unsigned int ch, flag;
-       unsigned int max_count = 256;
-
-       do {
-               ch = serial_in(up, UART_RX);
-               flag = TTY_NORMAL;
-               up->port.icount.rx++;
-
-               if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
-                                      UART_LSR_FE | UART_LSR_OE))) {
-
-                       dev_warn(up->dev, "We really rush into ERR/BI case"
-                               "status = 0x%02x", *status);
-                       /* For statistics only */
-                       if (*status & UART_LSR_BI) {
-                               *status &= ~(UART_LSR_FE | UART_LSR_PE);
-                               up->port.icount.brk++;
-                               /*
-                                * We do the SysRQ and SAK checking
-                                * here because otherwise the break
-                                * may get masked by ignore_status_mask
-                                * or read_status_mask.
-                                */
-                               if (uart_handle_break(&up->port))
-                                       goto ignore_char;
-                       } else if (*status & UART_LSR_PE)
-                               up->port.icount.parity++;
-                       else if (*status & UART_LSR_FE)
-                               up->port.icount.frame++;
-                       if (*status & UART_LSR_OE)
-                               up->port.icount.overrun++;
-
-                       /* Mask off conditions which should be ignored. */
-                       *status &= up->port.read_status_mask;
-
-#ifdef CONFIG_SERIAL_MFD_HSU_CONSOLE
-                       if (up->port.cons &&
-                               up->port.cons->index == up->port.line) {
-                               /* Recover the break flag from console xmit */
-                               *status |= up->lsr_break_flag;
-                               up->lsr_break_flag = 0;
-                       }
-#endif
-                       if (*status & UART_LSR_BI) {
-                               flag = TTY_BREAK;
-                       } else if (*status & UART_LSR_PE)
-                               flag = TTY_PARITY;
-                       else if (*status & UART_LSR_FE)
-                               flag = TTY_FRAME;
-               }
-
-               if (uart_handle_sysrq_char(&up->port, ch))
-                       goto ignore_char;
-
-               uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag);
-       ignore_char:
-               *status = serial_in(up, UART_LSR);
-       } while ((*status & UART_LSR_DR) && max_count--);
-
-       spin_unlock_irqrestore(&up->port.lock, *flags);
-       tty_flip_buffer_push(&up->port.state->port);
-       spin_lock_irqsave(&up->port.lock, *flags);
-}
-
-static void transmit_chars(struct uart_hsu_port *up)
-{
-       struct circ_buf *xmit = &up->port.state->xmit;
-       int count;
-
-       if (up->port.x_char) {
-               serial_out(up, UART_TX, up->port.x_char);
-               up->port.icount.tx++;
-               up->port.x_char = 0;
-               return;
-       }
-       if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
-               serial_hsu_stop_tx(&up->port);
-               return;
-       }
-
-       /* The IRQ is for TX FIFO half-empty */
-       count = up->port.fifosize / 2;
-
-       do {
-               serial_out(up, UART_TX, xmit->buf[xmit->tail]);
-               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-
-               up->port.icount.tx++;
-               if (uart_circ_empty(xmit))
-                       break;
-       } while (--count > 0);
-
-       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-               uart_write_wakeup(&up->port);
-
-       if (uart_circ_empty(xmit))
-               serial_hsu_stop_tx(&up->port);
-}
-
-static inline void check_modem_status(struct uart_hsu_port *up)
-{
-       int status;
-
-       status = serial_in(up, UART_MSR);
-
-       if ((status & UART_MSR_ANY_DELTA) == 0)
-               return;
-
-       if (status & UART_MSR_TERI)
-               up->port.icount.rng++;
-       if (status & UART_MSR_DDSR)
-               up->port.icount.dsr++;
-       /* We may only get DDCD when HW init and reset */
-       if (status & UART_MSR_DDCD)
-               uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
-       /* Will start/stop_tx accordingly */
-       if (status & UART_MSR_DCTS)
-               uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
-
-       wake_up_interruptible(&up->port.state->port.delta_msr_wait);
-}
-
-/*
- * This handles the interrupt from one port.
- */
-static irqreturn_t port_irq(int irq, void *dev_id)
-{
-       struct uart_hsu_port *up = dev_id;
-       unsigned int iir, lsr;
-       unsigned long flags;
-
-       if (unlikely(!up->running))
-               return IRQ_NONE;
-
-       spin_lock_irqsave(&up->port.lock, flags);
-       if (up->use_dma) {
-               lsr = serial_in(up, UART_LSR);
-               if (unlikely(lsr & (UART_LSR_BI | UART_LSR_PE |
-                                      UART_LSR_FE | UART_LSR_OE)))
-                       dev_warn(up->dev,
-                               "Got lsr irq while using DMA, lsr = 0x%2x\n",
-                               lsr);
-               check_modem_status(up);
-               spin_unlock_irqrestore(&up->port.lock, flags);
-               return IRQ_HANDLED;
-       }
-
-       iir = serial_in(up, UART_IIR);
-       if (iir & UART_IIR_NO_INT) {
-               spin_unlock_irqrestore(&up->port.lock, flags);
-               return IRQ_NONE;
-       }
-
-       lsr = serial_in(up, UART_LSR);
-       if (lsr & UART_LSR_DR)
-               receive_chars(up, &lsr, &flags);
-       check_modem_status(up);
-
-       /* lsr will be renewed during the receive_chars */
-       if (lsr & UART_LSR_THRE)
-               transmit_chars(up);
-
-       spin_unlock_irqrestore(&up->port.lock, flags);
-       return IRQ_HANDLED;
-}
-
-static inline void dma_chan_irq(struct hsu_dma_chan *chan)
-{
-       struct uart_hsu_port *up = chan->uport;
-       unsigned long flags;
-       u32 int_sts;
-
-       spin_lock_irqsave(&up->port.lock, flags);
-
-       if (!up->use_dma || !up->running)
-               goto exit;
-
-       /*
-        * No matter what situation, need read clear the IRQ status
-        * There is a bug, see Errata 5, HSD 2900918
-        */
-       int_sts = chan_readl(chan, HSU_CH_SR);
-
-       /* Rx channel */
-       if (chan->dirt == DMA_FROM_DEVICE)
-               hsu_dma_rx(up, int_sts, &flags);
-
-       /* Tx channel */
-       if (chan->dirt == DMA_TO_DEVICE) {
-               chan_writel(chan, HSU_CH_CR, 0x0);
-               up->dma_tx_on = 0;
-               hsu_dma_tx(up);
-       }
-
-exit:
-       spin_unlock_irqrestore(&up->port.lock, flags);
-       return;
-}
-
-static irqreturn_t dma_irq(int irq, void *dev_id)
-{
-       struct hsu_port *hsu = dev_id;
-       u32 int_sts, i;
-
-       int_sts = mfd_readl(hsu, HSU_GBL_DMAISR);
-
-       /* Currently we only have 6 channels may be used */
-       for (i = 0; i < 6; i++) {
-               if (int_sts & 0x1)
-                       dma_chan_irq(&hsu->chans[i]);
-               int_sts >>= 1;
-       }
-
-       return IRQ_HANDLED;
-}
-
-static unsigned int serial_hsu_tx_empty(struct uart_port *port)
-{
-       struct uart_hsu_port *up =
-               container_of(port, struct uart_hsu_port, port);
-       unsigned long flags;
-       unsigned int ret;
-
-       spin_lock_irqsave(&up->port.lock, flags);
-       ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
-       spin_unlock_irqrestore(&up->port.lock, flags);
-
-       return ret;
-}
-
-static unsigned int serial_hsu_get_mctrl(struct uart_port *port)
-{
-       struct uart_hsu_port *up =
-               container_of(port, struct uart_hsu_port, port);
-       unsigned char status;
-       unsigned int ret;
-
-       status = serial_in(up, UART_MSR);
-
-       ret = 0;
-       if (status & UART_MSR_DCD)
-               ret |= TIOCM_CAR;
-       if (status & UART_MSR_RI)
-               ret |= TIOCM_RNG;
-       if (status & UART_MSR_DSR)
-               ret |= TIOCM_DSR;
-       if (status & UART_MSR_CTS)
-               ret |= TIOCM_CTS;
-       return ret;
-}
-
-static void serial_hsu_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
-       struct uart_hsu_port *up =
-               container_of(port, struct uart_hsu_port, port);
-       unsigned char mcr = 0;
-
-       if (mctrl & TIOCM_RTS)
-               mcr |= UART_MCR_RTS;
-       if (mctrl & TIOCM_DTR)
-               mcr |= UART_MCR_DTR;
-       if (mctrl & TIOCM_OUT1)
-               mcr |= UART_MCR_OUT1;
-       if (mctrl & TIOCM_OUT2)
-               mcr |= UART_MCR_OUT2;
-       if (mctrl & TIOCM_LOOP)
-               mcr |= UART_MCR_LOOP;
-
-       mcr |= up->mcr;
-
-       serial_out(up, UART_MCR, mcr);
-}
-
-static void serial_hsu_break_ctl(struct uart_port *port, int break_state)
-{
-       struct uart_hsu_port *up =
-               container_of(port, struct uart_hsu_port, port);
-       unsigned long flags;
-
-       spin_lock_irqsave(&up->port.lock, flags);
-       if (break_state == -1)
-               up->lcr |= UART_LCR_SBC;
-       else
-               up->lcr &= ~UART_LCR_SBC;
-       serial_out(up, UART_LCR, up->lcr);
-       spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-/*
- * What special to do:
- * 1. chose the 64B fifo mode
- * 2. start dma or pio depends on configuration
- * 3. we only allocate dma memory when needed
- */
-static int serial_hsu_startup(struct uart_port *port)
-{
-       struct uart_hsu_port *up =
-               container_of(port, struct uart_hsu_port, port);
-       unsigned long flags;
-
-       pm_runtime_get_sync(up->dev);
-
-       /*
-        * Clear the FIFO buffers and disable them.
-        * (they will be reenabled in set_termios())
-        */
-       serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-       serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-                       UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-       serial_out(up, UART_FCR, 0);
-
-       /* Clear the interrupt registers. */
-       (void) serial_in(up, UART_LSR);
-       (void) serial_in(up, UART_RX);
-       (void) serial_in(up, UART_IIR);
-       (void) serial_in(up, UART_MSR);
-
-       /* Now, initialize the UART, default is 8n1 */
-       serial_out(up, UART_LCR, UART_LCR_WLEN8);
-
-       spin_lock_irqsave(&up->port.lock, flags);
-
-       up->port.mctrl |= TIOCM_OUT2;
-       serial_hsu_set_mctrl(&up->port, up->port.mctrl);
-
-       /*
-        * Finally, enable interrupts.  Note: Modem status interrupts
-        * are set via set_termios(), which will be occurring imminently
-        * anyway, so we don't enable them here.
-        */
-       if (!up->use_dma)
-               up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE;
-       else
-               up->ier = 0;
-       serial_out(up, UART_IER, up->ier);
-
-       spin_unlock_irqrestore(&up->port.lock, flags);
-
-       /* DMA init */
-       if (up->use_dma) {
-               struct hsu_dma_buffer *dbuf;
-               struct circ_buf *xmit = &port->state->xmit;
-
-               up->dma_tx_on = 0;
-
-               /* First allocate the RX buffer */
-               dbuf = &up->rxbuf;
-               dbuf->buf = kzalloc(HSU_DMA_BUF_SIZE, GFP_KERNEL);
-               if (!dbuf->buf) {
-                       up->use_dma = 0;
-                       goto exit;
-               }
-               dbuf->dma_addr = dma_map_single(port->dev,
-                                               dbuf->buf,
-                                               HSU_DMA_BUF_SIZE,
-                                               DMA_FROM_DEVICE);
-               dbuf->dma_size = HSU_DMA_BUF_SIZE;
-
-               /* Start the RX channel right now */
-               hsu_dma_start_rx_chan(up->rxc, dbuf);
-
-               /* Next init the TX DMA */
-               dbuf = &up->txbuf;
-               dbuf->buf = xmit->buf;
-               dbuf->dma_addr = dma_map_single(port->dev,
-                                              dbuf->buf,
-                                              UART_XMIT_SIZE,
-                                              DMA_TO_DEVICE);
-               dbuf->dma_size = UART_XMIT_SIZE;
-
-               /* This should not be changed all around */
-               chan_writel(up->txc, HSU_CH_BSR, 32);
-               chan_writel(up->txc, HSU_CH_MOTSR, 4);
-               dbuf->ofs = 0;
-       }
-
-exit:
-        /* And clear the interrupt registers again for luck. */
-       (void) serial_in(up, UART_LSR);
-       (void) serial_in(up, UART_RX);
-       (void) serial_in(up, UART_IIR);
-       (void) serial_in(up, UART_MSR);
-
-       up->running = 1;
-       return 0;
-}
-
-static void serial_hsu_shutdown(struct uart_port *port)
-{
-       struct uart_hsu_port *up =
-               container_of(port, struct uart_hsu_port, port);
-       unsigned long flags;
-
-       /* Disable interrupts from this port */
-       up->ier = 0;
-       serial_out(up, UART_IER, 0);
-       up->running = 0;
-
-       spin_lock_irqsave(&up->port.lock, flags);
-       up->port.mctrl &= ~TIOCM_OUT2;
-       serial_hsu_set_mctrl(&up->port, up->port.mctrl);
-       spin_unlock_irqrestore(&up->port.lock, flags);
-
-       /* Disable break condition and FIFOs */
-       serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
-       serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-                                 UART_FCR_CLEAR_RCVR |
-                                 UART_FCR_CLEAR_XMIT);
-       serial_out(up, UART_FCR, 0);
-
-       pm_runtime_put(up->dev);
-}
-
-static void
-serial_hsu_set_termios(struct uart_port *port, struct ktermios *termios,
-                      struct ktermios *old)
-{
-       struct uart_hsu_port *up =
-                       container_of(port, struct uart_hsu_port, port);
-       unsigned char cval, fcr = 0;
-       unsigned long flags;
-       unsigned int baud, quot;
-       u32 ps, mul;
-
-       switch (termios->c_cflag & CSIZE) {
-       case CS5:
-               cval = UART_LCR_WLEN5;
-               break;
-       case CS6:
-               cval = UART_LCR_WLEN6;
-               break;
-       case CS7:
-               cval = UART_LCR_WLEN7;
-               break;
-       default:
-       case CS8:
-               cval = UART_LCR_WLEN8;
-               break;
-       }
-
-       /* CMSPAR isn't supported by this driver */
-       termios->c_cflag &= ~CMSPAR;
-
-       if (termios->c_cflag & CSTOPB)
-               cval |= UART_LCR_STOP;
-       if (termios->c_cflag & PARENB)
-               cval |= UART_LCR_PARITY;
-       if (!(termios->c_cflag & PARODD))
-               cval |= UART_LCR_EPAR;
-
-       /*
-        * The base clk is 50Mhz, and the baud rate come from:
-        *      baud = 50M * MUL / (DIV * PS * DLAB)
-        *
-        * For those basic low baud rate we can get the direct
-        * scalar from 2746800, like 115200 = 2746800/24. For those
-        * higher baud rate, we handle them case by case, mainly by
-        * adjusting the MUL/PS registers, and DIV register is kept
-        * as default value 0x3d09 to make things simple
-        */
-       baud = uart_get_baud_rate(port, termios, old, 0, 4000000);
-
-       quot = 1;
-       ps = 0x10;
-       mul = 0x3600;
-       switch (baud) {
-       case 3500000:
-               mul = 0x3345;
-               ps = 0xC;
-               break;
-       case 1843200:
-               mul = 0x2400;
-               break;
-       case 3000000:
-       case 2500000:
-       case 2000000:
-       case 1500000:
-       case 1000000:
-       case 500000:
-               /* mul/ps/quot = 0x9C4/0x10/0x1 will make a 500000 bps */
-               mul = baud / 500000 * 0x9C4;
-               break;
-       default:
-               /* Use uart_get_divisor to get quot for other baud rates */
-               quot = 0;
-       }
-
-       if (!quot)
-               quot = uart_get_divisor(port, baud);
-
-       if ((up->port.uartclk / quot) < (2400 * 16))
-               fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_1B;
-       else if ((up->port.uartclk / quot) < (230400 * 16))
-               fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_16B;
-       else
-               fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_32B;
-
-       fcr |= UART_FCR_HSU_64B_FIFO;
-
-       /*
-        * Ok, we're now changing the port state.  Do it with
-        * interrupts disabled.
-        */
-       spin_lock_irqsave(&up->port.lock, flags);
-
-       /* Update the per-port timeout */
-       uart_update_timeout(port, termios->c_cflag, baud);
-
-       up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-       if (termios->c_iflag & INPCK)
-               up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-       if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
-               up->port.read_status_mask |= UART_LSR_BI;
-
-       /* Characters to ignore */
-       up->port.ignore_status_mask = 0;
-       if (termios->c_iflag & IGNPAR)
-               up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
-       if (termios->c_iflag & IGNBRK) {
-               up->port.ignore_status_mask |= UART_LSR_BI;
-               /*
-                * If we're ignoring parity and break indicators,
-                * ignore overruns too (for real raw support).
-                */
-               if (termios->c_iflag & IGNPAR)
-                       up->port.ignore_status_mask |= UART_LSR_OE;
-       }
-
-       /* Ignore all characters if CREAD is not set */
-       if ((termios->c_cflag & CREAD) == 0)
-               up->port.ignore_status_mask |= UART_LSR_DR;
-
-       /*
-        * CTS flow control flag and modem status interrupts, disable
-        * MSI by default
-        */
-       up->ier &= ~UART_IER_MSI;
-       if (UART_ENABLE_MS(&up->port, termios->c_cflag))
-               up->ier |= UART_IER_MSI;
-
-       serial_out(up, UART_IER, up->ier);
-
-       if (termios->c_cflag & CRTSCTS)
-               up->mcr |= UART_MCR_AFE | UART_MCR_RTS;
-       else
-               up->mcr &= ~UART_MCR_AFE;
-
-       serial_out(up, UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */
-       serial_out(up, UART_DLL, quot & 0xff);          /* LS of divisor */
-       serial_out(up, UART_DLM, quot >> 8);            /* MS of divisor */
-       serial_out(up, UART_LCR, cval);                 /* reset DLAB */
-       serial_out(up, UART_MUL, mul);                  /* set MUL */
-       serial_out(up, UART_PS, ps);                    /* set PS */
-       up->lcr = cval;                                 /* Save LCR */
-       serial_hsu_set_mctrl(&up->port, up->port.mctrl);
-       serial_out(up, UART_FCR, fcr);
-       spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
-static void
-serial_hsu_pm(struct uart_port *port, unsigned int state,
-             unsigned int oldstate)
-{
-}
-
-static void serial_hsu_release_port(struct uart_port *port)
-{
-}
-
-static int serial_hsu_request_port(struct uart_port *port)
-{
-       return 0;
-}
-
-static void serial_hsu_config_port(struct uart_port *port, int flags)
-{
-       struct uart_hsu_port *up =
-               container_of(port, struct uart_hsu_port, port);
-       up->port.type = PORT_MFD;
-}
-
-static int
-serial_hsu_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
-       /* We don't want the core code to modify any port params */
-       return -EINVAL;
-}
-
-static const char *
-serial_hsu_type(struct uart_port *port)
-{
-       struct uart_hsu_port *up =
-               container_of(port, struct uart_hsu_port, port);
-       return up->name;
-}
-
-/* Mainly for uart console use */
-static struct uart_hsu_port *serial_hsu_ports[3];
-static struct uart_driver serial_hsu_reg;
-
-#ifdef CONFIG_SERIAL_MFD_HSU_CONSOLE
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/* Wait for transmitter & holding register to empty */
-static inline void wait_for_xmitr(struct uart_hsu_port *up)
-{
-       unsigned int status, tmout = 1000;
-
-       /* Wait up to 1ms for the character to be sent. */
-       do {
-               status = serial_in(up, UART_LSR);
-
-               if (status & UART_LSR_BI)
-                       up->lsr_break_flag = UART_LSR_BI;
-
-               if (--tmout == 0)
-                       break;
-               udelay(1);
-       } while (!(status & BOTH_EMPTY));
-
-       /* Wait up to 1s for flow control if necessary */
-       if (up->port.flags & UPF_CONS_FLOW) {
-               tmout = 1000000;
-               while (--tmout &&
-                      ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
-                       udelay(1);
-       }
-}
-
-static void serial_hsu_console_putchar(struct uart_port *port, int ch)
-{
-       struct uart_hsu_port *up =
-               container_of(port, struct uart_hsu_port, port);
-
-       wait_for_xmitr(up);
-       serial_out(up, UART_TX, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- *     The console_lock must be held when we get here.
- */
-static void
-serial_hsu_console_write(struct console *co, const char *s, unsigned int count)
-{
-       struct uart_hsu_port *up = serial_hsu_ports[co->index];
-       unsigned long flags;
-       unsigned int ier;
-       int locked = 1;
-
-       touch_nmi_watchdog();
-
-       local_irq_save(flags);
-       if (up->port.sysrq)
-               locked = 0;
-       else if (oops_in_progress) {
-               locked = spin_trylock(&up->port.lock);
-       } else
-               spin_lock(&up->port.lock);
-
-       /* First save the IER then disable the interrupts */
-       ier = serial_in(up, UART_IER);
-       serial_out(up, UART_IER, 0);
-
-       uart_console_write(&up->port, s, count, serial_hsu_console_putchar);
-
-       /*
-        * Finally, wait for transmitter to become empty
-        * and restore the IER
-        */
-       wait_for_xmitr(up);
-       serial_out(up, UART_IER, ier);
-
-       if (locked)
-               spin_unlock(&up->port.lock);
-       local_irq_restore(flags);
-}
-
-static struct console serial_hsu_console;
-
-static int __init
-serial_hsu_console_setup(struct console *co, char *options)
-{
-       struct uart_hsu_port *up;
-       int baud = 115200;
-       int bits = 8;
-       int parity = 'n';
-       int flow = 'n';
-
-       if (co->index == -1 || co->index >= serial_hsu_reg.nr)
-               co->index = 0;
-       up = serial_hsu_ports[co->index];
-       if (!up)
-               return -ENODEV;
-
-       if (options)
-               uart_parse_options(options, &baud, &parity, &bits, &flow);
-
-       return uart_set_options(&up->port, co, baud, parity, bits, flow);
-}
-
-static struct console serial_hsu_console = {
-       .name           = "ttyMFD",
-       .write          = serial_hsu_console_write,
-       .device         = uart_console_device,
-       .setup          = serial_hsu_console_setup,
-       .flags          = CON_PRINTBUFFER,
-       .index          = -1,
-       .data           = &serial_hsu_reg,
-};
-
-#define SERIAL_HSU_CONSOLE     (&serial_hsu_console)
-#else
-#define SERIAL_HSU_CONSOLE     NULL
-#endif
-
-static struct uart_ops serial_hsu_pops = {
-       .tx_empty       = serial_hsu_tx_empty,
-       .set_mctrl      = serial_hsu_set_mctrl,
-       .get_mctrl      = serial_hsu_get_mctrl,
-       .stop_tx        = serial_hsu_stop_tx,
-       .start_tx       = serial_hsu_start_tx,
-       .stop_rx        = serial_hsu_stop_rx,
-       .enable_ms      = serial_hsu_enable_ms,
-       .break_ctl      = serial_hsu_break_ctl,
-       .startup        = serial_hsu_startup,
-       .shutdown       = serial_hsu_shutdown,
-       .set_termios    = serial_hsu_set_termios,
-       .pm             = serial_hsu_pm,
-       .type           = serial_hsu_type,
-       .release_port   = serial_hsu_release_port,
-       .request_port   = serial_hsu_request_port,
-       .config_port    = serial_hsu_config_port,
-       .verify_port    = serial_hsu_verify_port,
-};
-
-static struct uart_driver serial_hsu_reg = {
-       .owner          = THIS_MODULE,
-       .driver_name    = "MFD serial",
-       .dev_name       = "ttyMFD",
-       .major          = TTY_MAJOR,
-       .minor          = 128,
-       .nr             = 3,
-       .cons           = SERIAL_HSU_CONSOLE,
-};
-
-#ifdef CONFIG_PM
-static int serial_hsu_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-       void *priv = pci_get_drvdata(pdev);
-       struct uart_hsu_port *up;
-
-       /* Make sure this is not the internal dma controller */
-       if (priv && (pdev->device != 0x081E)) {
-               up = priv;
-               uart_suspend_port(&serial_hsu_reg, &up->port);
-       }
-
-       pci_save_state(pdev);
-       pci_set_power_state(pdev, pci_choose_state(pdev, state));
-        return 0;
-}
-
-static int serial_hsu_resume(struct pci_dev *pdev)
-{
-       void *priv = pci_get_drvdata(pdev);
-       struct uart_hsu_port *up;
-       int ret;
-
-       pci_set_power_state(pdev, PCI_D0);
-       pci_restore_state(pdev);
-
-       ret = pci_enable_device(pdev);
-       if (ret)
-               dev_warn(&pdev->dev,
-                       "HSU: can't re-enable device, try to continue\n");
-
-       if (priv && (pdev->device != 0x081E)) {
-               up = priv;
-               uart_resume_port(&serial_hsu_reg, &up->port);
-       }
-       return 0;
-}
-
-static int serial_hsu_runtime_idle(struct device *dev)
-{
-       pm_schedule_suspend(dev, 500);
-       return -EBUSY;
-}
-
-static int serial_hsu_runtime_suspend(struct device *dev)
-{
-       return 0;
-}
-
-static int serial_hsu_runtime_resume(struct device *dev)
-{
-       return 0;
-}
-#else
-#define serial_hsu_suspend             NULL
-#define serial_hsu_resume              NULL
-#define serial_hsu_runtime_idle                NULL
-#define serial_hsu_runtime_suspend     NULL
-#define serial_hsu_runtime_resume      NULL
-#endif
-
-static const struct dev_pm_ops serial_hsu_pm_ops = {
-       .runtime_suspend = serial_hsu_runtime_suspend,
-       .runtime_resume = serial_hsu_runtime_resume,
-       .runtime_idle = serial_hsu_runtime_idle,
-};
-
-/* temp global pointer before we settle down on using one or four PCI dev */
-static struct hsu_port *phsu;
-
-static int serial_hsu_probe(struct pci_dev *pdev,
-                               const struct pci_device_id *ent)
-{
-       struct uart_hsu_port *uport;
-       int index, ret;
-
-       printk(KERN_INFO "HSU: found PCI Serial controller(ID: %04x:%04x)\n",
-               pdev->vendor, pdev->device);
-
-       switch (pdev->device) {
-       case 0x081B:
-               index = 0;
-               break;
-       case 0x081C:
-               index = 1;
-               break;
-       case 0x081D:
-               index = 2;
-               break;
-       case 0x081E:
-               /* internal DMA controller */
-               index = 3;
-               break;
-       default:
-               dev_err(&pdev->dev, "HSU: out of index!");
-               return -ENODEV;
-       }
-
-       ret = pci_enable_device(pdev);
-       if (ret)
-               return ret;
-
-       if (index == 3) {
-               /* DMA controller */
-               ret = request_irq(pdev->irq, dma_irq, 0, "hsu_dma", phsu);
-               if (ret) {
-                       dev_err(&pdev->dev, "can not get IRQ\n");
-                       goto err_disable;
-               }
-               pci_set_drvdata(pdev, phsu);
-       } else {
-               /* UART port 0~2 */
-               uport = &phsu->port[index];
-               uport->port.irq = pdev->irq;
-               uport->port.dev = &pdev->dev;
-               uport->dev = &pdev->dev;
-
-               ret = request_irq(pdev->irq, port_irq, 0, uport->name, uport);
-               if (ret) {
-                       dev_err(&pdev->dev, "can not get IRQ\n");
-                       goto err_disable;
-               }
-               uart_add_one_port(&serial_hsu_reg, &uport->port);
-
-               pci_set_drvdata(pdev, uport);
-       }
-
-       pm_runtime_put_noidle(&pdev->dev);
-       pm_runtime_allow(&pdev->dev);
-
-       return 0;
-
-err_disable:
-       pci_disable_device(pdev);
-       return ret;
-}
-
-static void hsu_global_init(void)
-{
-       struct hsu_port *hsu;
-       struct uart_hsu_port *uport;
-       struct hsu_dma_chan *dchan;
-       int i, ret;
-
-       hsu = kzalloc(sizeof(struct hsu_port), GFP_KERNEL);
-       if (!hsu)
-               return;
-
-       /* Get basic io resource and map it */
-       hsu->paddr = 0xffa28000;
-       hsu->iolen = 0x1000;
-
-       if (!(request_mem_region(hsu->paddr, hsu->iolen, "HSU global")))
-               pr_warn("HSU: error in request mem region\n");
-
-       hsu->reg = ioremap_nocache((unsigned long)hsu->paddr, hsu->iolen);
-       if (!hsu->reg) {
-               pr_err("HSU: error in ioremap\n");
-               ret = -ENOMEM;
-               goto err_free_region;
-       }
-
-       /* Initialise the 3 UART ports */
-       uport = hsu->port;
-       for (i = 0; i < 3; i++) {
-               uport->port.type = PORT_MFD;
-               uport->port.iotype = UPIO_MEM;
-               uport->port.mapbase = (resource_size_t)hsu->paddr
-                                       + HSU_PORT_REG_OFFSET
-                                       + i * HSU_PORT_REG_LENGTH;
-               uport->port.membase = hsu->reg + HSU_PORT_REG_OFFSET
-                                       + i * HSU_PORT_REG_LENGTH;
-
-               sprintf(uport->name, "hsu_port%d", i);
-               uport->port.fifosize = 64;
-               uport->port.ops = &serial_hsu_pops;
-               uport->port.line = i;
-               uport->port.flags = UPF_IOREMAP;
-               /* set the scalable maxim support rate to 2746800 bps */
-               uport->port.uartclk = 115200 * 24 * 16;
-
-               uport->running = 0;
-               uport->txc = &hsu->chans[i * 2];
-               uport->rxc = &hsu->chans[i * 2 + 1];
-
-               serial_hsu_ports[i] = uport;
-               uport->index = i;
-
-               if (hsu_dma_enable & (1<<i))
-                       uport->use_dma = 1;
-               else
-                       uport->use_dma = 0;
-
-               uport++;
-       }
-
-       /* Initialise 6 dma channels */
-       dchan = hsu->chans;
-       for (i = 0; i < 6; i++) {
-               dchan->id = i;
-               dchan->dirt = (i & 0x1) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-               dchan->uport = &hsu->port[i/2];
-               dchan->reg = hsu->reg + HSU_DMA_CHANS_REG_OFFSET +
-                               i * HSU_DMA_CHANS_REG_LENGTH;
-
-               dchan++;
-       }
-
-       phsu = hsu;
-       hsu_debugfs_init(hsu);
-       return;
-
-err_free_region:
-       release_mem_region(hsu->paddr, hsu->iolen);
-       kfree(hsu);
-       return;
-}
-
-static void serial_hsu_remove(struct pci_dev *pdev)
-{
-       void *priv = pci_get_drvdata(pdev);
-       struct uart_hsu_port *up;
-
-       if (!priv)
-               return;
-
-       pm_runtime_forbid(&pdev->dev);
-       pm_runtime_get_noresume(&pdev->dev);
-
-       /* For port 0/1/2, priv is the address of uart_hsu_port */
-       if (pdev->device != 0x081E) {
-               up = priv;
-               uart_remove_one_port(&serial_hsu_reg, &up->port);
-       }
-
-       free_irq(pdev->irq, priv);
-       pci_disable_device(pdev);
-}
-
-/* First 3 are UART ports, and the 4th is the DMA */
-static const struct pci_device_id pci_ids[] = {
-       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081B) },
-       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081C) },
-       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081D) },
-       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081E) },
-       {},
-};
-
-static struct pci_driver hsu_pci_driver = {
-       .name =         "HSU serial",
-       .id_table =     pci_ids,
-       .probe =        serial_hsu_probe,
-       .remove =       serial_hsu_remove,
-       .suspend =      serial_hsu_suspend,
-       .resume =       serial_hsu_resume,
-       .driver = {
-               .pm = &serial_hsu_pm_ops,
-       },
-};
-
-static int __init hsu_pci_init(void)
-{
-       int ret;
-
-       hsu_global_init();
-
-       ret = uart_register_driver(&serial_hsu_reg);
-       if (ret)
-               return ret;
-
-       return pci_register_driver(&hsu_pci_driver);
-}
-
-static void __exit hsu_pci_exit(void)
-{
-       pci_unregister_driver(&hsu_pci_driver);
-       uart_unregister_driver(&serial_hsu_reg);
-
-       hsu_debugfs_remove(phsu);
-
-       kfree(phsu);
-}
-
-module_init(hsu_pci_init);
-module_exit(hsu_pci_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DEVICE_TABLE(pci, pci_ids);
index 3308ef243dc31ab03a88d2dbdc41d8faa057cb9d..1589f17c1fca61dd63682041bba0d9f7e2330e35 100644 (file)
@@ -1717,7 +1717,7 @@ static struct uart_driver mpc52xx_uart_driver = {
 /* OF Platform Driver                                                       */
 /* ======================================================================== */
 
-static struct of_device_id mpc52xx_uart_of_match[] = {
+static const struct of_device_id mpc52xx_uart_of_match[] = {
 #ifdef CONFIG_PPC_MPC52xx
        { .compatible = "fsl,mpc5200b-psc-uart", .data = &mpc5200b_psc_ops, },
        { .compatible = "fsl,mpc5200-psc-uart", .data = &mpc52xx_psc_ops, },
index 3e1c7138d8cd22bd64830e005b1c9ed77cedeee3..737f69fe7113a93410652cd84030a08bc6697335 100644 (file)
@@ -170,15 +170,6 @@ void msm_serial_set_mnd_regs_from_uartclk(struct uart_port *port)
                msm_serial_set_mnd_regs_tcxoby4(port);
 }
 
-/*
- * TROUT has a specific defect that makes it report it's uartclk
- * as 19.2Mhz (TCXO) when it's actually 4.8Mhz (TCXO/4). This special
- * cases TROUT to use the right clock.
- */
-#ifdef CONFIG_MACH_TROUT
-#define msm_serial_set_mnd_regs msm_serial_set_mnd_regs_tcxoby4
-#else
 #define msm_serial_set_mnd_regs msm_serial_set_mnd_regs_from_uartclk
-#endif
 
 #endif /* __DRIVERS_SERIAL_MSM_SERIAL_H */
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
deleted file mode 100644 (file)
index 62da853..0000000
+++ /dev/null
@@ -1,1874 +0,0 @@
-/*
- * MSM 7k/8k High speed uart driver
- *
- * Copyright (c) 2007-2011, Code Aurora Forum. All rights reserved.
- * Copyright (c) 2008 Google Inc.
- * Modified: Nick Pelly <npelly@google.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.
- *
- * Has optional support for uart power management independent of linux
- * suspend/resume:
- *
- * RX wakeup.
- * UART wakeup can be triggered by RX activity (using a wakeup GPIO on the
- * UART RX pin). This should only be used if there is not a wakeup
- * GPIO on the UART CTS, and the first RX byte is known (for example, with the
- * Bluetooth Texas Instruments HCILL protocol), since the first RX byte will
- * always be lost. RTS will be asserted even while the UART is off in this mode
- * of operation. See msm_serial_hs_platform_data.rx_wakeup_irq.
- */
-
-#include <linux/module.h>
-
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/dma-mapping.h>
-#include <linux/dmapool.h>
-#include <linux/wait.h>
-#include <linux/workqueue.h>
-
-#include <linux/atomic.h>
-#include <asm/irq.h>
-
-#include <mach/hardware.h>
-#include <mach/dma.h>
-#include <linux/platform_data/msm_serial_hs.h>
-
-/* HSUART Registers */
-#define UARTDM_MR1_ADDR 0x0
-#define UARTDM_MR2_ADDR 0x4
-
-/* Data Mover result codes */
-#define RSLT_FIFO_CNTR_BMSK (0xE << 28)
-#define RSLT_VLD            BIT(1)
-
-/* write only register */
-#define UARTDM_CSR_ADDR 0x8
-#define UARTDM_CSR_115200 0xFF
-#define UARTDM_CSR_57600  0xEE
-#define UARTDM_CSR_38400  0xDD
-#define UARTDM_CSR_28800  0xCC
-#define UARTDM_CSR_19200  0xBB
-#define UARTDM_CSR_14400  0xAA
-#define UARTDM_CSR_9600   0x99
-#define UARTDM_CSR_7200   0x88
-#define UARTDM_CSR_4800   0x77
-#define UARTDM_CSR_3600   0x66
-#define UARTDM_CSR_2400   0x55
-#define UARTDM_CSR_1200   0x44
-#define UARTDM_CSR_600    0x33
-#define UARTDM_CSR_300    0x22
-#define UARTDM_CSR_150    0x11
-#define UARTDM_CSR_75     0x00
-
-/* write only register */
-#define UARTDM_TF_ADDR 0x70
-#define UARTDM_TF2_ADDR 0x74
-#define UARTDM_TF3_ADDR 0x78
-#define UARTDM_TF4_ADDR 0x7C
-
-/* write only register */
-#define UARTDM_CR_ADDR 0x10
-#define UARTDM_IMR_ADDR 0x14
-
-#define UARTDM_IPR_ADDR 0x18
-#define UARTDM_TFWR_ADDR 0x1c
-#define UARTDM_RFWR_ADDR 0x20
-#define UARTDM_HCR_ADDR 0x24
-#define UARTDM_DMRX_ADDR 0x34
-#define UARTDM_IRDA_ADDR 0x38
-#define UARTDM_DMEN_ADDR 0x3c
-
-/* UART_DM_NO_CHARS_FOR_TX */
-#define UARTDM_NCF_TX_ADDR 0x40
-
-#define UARTDM_BADR_ADDR 0x44
-
-#define UARTDM_SIM_CFG_ADDR 0x80
-/* Read Only register */
-#define UARTDM_SR_ADDR 0x8
-
-/* Read Only register */
-#define UARTDM_RF_ADDR  0x70
-#define UARTDM_RF2_ADDR 0x74
-#define UARTDM_RF3_ADDR 0x78
-#define UARTDM_RF4_ADDR 0x7C
-
-/* Read Only register */
-#define UARTDM_MISR_ADDR 0x10
-
-/* Read Only register */
-#define UARTDM_ISR_ADDR 0x14
-#define UARTDM_RX_TOTAL_SNAP_ADDR 0x38
-
-#define UARTDM_RXFS_ADDR 0x50
-
-/* Register field Mask Mapping */
-#define UARTDM_SR_PAR_FRAME_BMSK        BIT(5)
-#define UARTDM_SR_OVERRUN_BMSK          BIT(4)
-#define UARTDM_SR_TXEMT_BMSK            BIT(3)
-#define UARTDM_SR_TXRDY_BMSK            BIT(2)
-#define UARTDM_SR_RXRDY_BMSK            BIT(0)
-
-#define UARTDM_CR_TX_DISABLE_BMSK       BIT(3)
-#define UARTDM_CR_RX_DISABLE_BMSK       BIT(1)
-#define UARTDM_CR_TX_EN_BMSK            BIT(2)
-#define UARTDM_CR_RX_EN_BMSK            BIT(0)
-
-/* UARTDM_CR channel_comman bit value (register field is bits 8:4) */
-#define RESET_RX                0x10
-#define RESET_TX                0x20
-#define RESET_ERROR_STATUS      0x30
-#define RESET_BREAK_INT         0x40
-#define START_BREAK             0x50
-#define STOP_BREAK              0x60
-#define RESET_CTS               0x70
-#define RESET_STALE_INT         0x80
-#define RFR_LOW                 0xD0
-#define RFR_HIGH                0xE0
-#define CR_PROTECTION_EN        0x100
-#define STALE_EVENT_ENABLE      0x500
-#define STALE_EVENT_DISABLE     0x600
-#define FORCE_STALE_EVENT       0x400
-#define CLEAR_TX_READY          0x300
-#define RESET_TX_ERROR          0x800
-#define RESET_TX_DONE           0x810
-
-#define UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK 0xffffff00
-#define UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK 0x3f
-#define UARTDM_MR1_CTS_CTL_BMSK 0x40
-#define UARTDM_MR1_RX_RDY_CTL_BMSK 0x80
-
-#define UARTDM_MR2_ERROR_MODE_BMSK 0x40
-#define UARTDM_MR2_BITS_PER_CHAR_BMSK 0x30
-
-/* bits per character configuration */
-#define FIVE_BPC  (0 << 4)
-#define SIX_BPC   (1 << 4)
-#define SEVEN_BPC (2 << 4)
-#define EIGHT_BPC (3 << 4)
-
-#define UARTDM_MR2_STOP_BIT_LEN_BMSK 0xc
-#define STOP_BIT_ONE (1 << 2)
-#define STOP_BIT_TWO (3 << 2)
-
-#define UARTDM_MR2_PARITY_MODE_BMSK 0x3
-
-/* Parity configuration */
-#define NO_PARITY 0x0
-#define EVEN_PARITY 0x1
-#define ODD_PARITY 0x2
-#define SPACE_PARITY 0x3
-
-#define UARTDM_IPR_STALE_TIMEOUT_MSB_BMSK 0xffffff80
-#define UARTDM_IPR_STALE_LSB_BMSK 0x1f
-
-/* These can be used for both ISR and IMR register */
-#define UARTDM_ISR_TX_READY_BMSK        BIT(7)
-#define UARTDM_ISR_CURRENT_CTS_BMSK     BIT(6)
-#define UARTDM_ISR_DELTA_CTS_BMSK       BIT(5)
-#define UARTDM_ISR_RXLEV_BMSK           BIT(4)
-#define UARTDM_ISR_RXSTALE_BMSK         BIT(3)
-#define UARTDM_ISR_RXBREAK_BMSK         BIT(2)
-#define UARTDM_ISR_RXHUNT_BMSK          BIT(1)
-#define UARTDM_ISR_TXLEV_BMSK           BIT(0)
-
-/* Field definitions for UART_DM_DMEN*/
-#define UARTDM_TX_DM_EN_BMSK 0x1
-#define UARTDM_RX_DM_EN_BMSK 0x2
-
-#define UART_FIFOSIZE 64
-#define UARTCLK 7372800
-
-/* Rx DMA request states */
-enum flush_reason {
-       FLUSH_NONE,
-       FLUSH_DATA_READY,
-       FLUSH_DATA_INVALID,  /* values after this indicate invalid data */
-       FLUSH_IGNORE = FLUSH_DATA_INVALID,
-       FLUSH_STOP,
-       FLUSH_SHUTDOWN,
-};
-
-/* UART clock states */
-enum msm_hs_clk_states_e {
-       MSM_HS_CLK_PORT_OFF,     /* port not in use */
-       MSM_HS_CLK_OFF,          /* clock disabled */
-       MSM_HS_CLK_REQUEST_OFF,  /* disable after TX and RX flushed */
-       MSM_HS_CLK_ON,           /* clock enabled */
-};
-
-/* Track the forced RXSTALE flush during clock off sequence.
- * These states are only valid during MSM_HS_CLK_REQUEST_OFF */
-enum msm_hs_clk_req_off_state_e {
-       CLK_REQ_OFF_START,
-       CLK_REQ_OFF_RXSTALE_ISSUED,
-       CLK_REQ_OFF_FLUSH_ISSUED,
-       CLK_REQ_OFF_RXSTALE_FLUSHED,
-};
-
-/**
- * struct msm_hs_tx
- * @tx_ready_int_en: ok to dma more tx?
- * @dma_in_flight: tx dma in progress
- * @xfer: top level DMA command pointer structure
- * @command_ptr: third level command struct pointer
- * @command_ptr_ptr: second level command list struct pointer
- * @mapped_cmd_ptr: DMA view of third level command struct
- * @mapped_cmd_ptr_ptr: DMA view of second level command list struct
- * @tx_count: number of bytes to transfer in DMA transfer
- * @dma_base: DMA view of UART xmit buffer
- *
- * This structure describes a single Tx DMA transaction. MSM DMA
- * commands have two levels of indirection. The top level command
- * ptr points to a list of command ptr which in turn points to a
- * single DMA 'command'. In our case each Tx transaction consists
- * of a single second level pointer pointing to a 'box type' command.
- */
-struct msm_hs_tx {
-       unsigned int tx_ready_int_en;
-       unsigned int dma_in_flight;
-       struct msm_dmov_cmd xfer;
-       dmov_box *command_ptr;
-       u32 *command_ptr_ptr;
-       dma_addr_t mapped_cmd_ptr;
-       dma_addr_t mapped_cmd_ptr_ptr;
-       int tx_count;
-       dma_addr_t dma_base;
-};
-
-/**
- * struct msm_hs_rx
- * @flush: Rx DMA request state
- * @xfer: top level DMA command pointer structure
- * @cmdptr_dmaaddr: DMA view of second level command structure
- * @command_ptr: third level DMA command pointer structure
- * @command_ptr_ptr: second level DMA command list pointer
- * @mapped_cmd_ptr: DMA view of the third level command structure
- * @wait: wait for DMA completion before shutdown
- * @buffer: destination buffer for RX DMA
- * @rbuffer: DMA view of buffer
- * @pool: dma pool out of which coherent rx buffer is allocated
- * @tty_work: private work-queue for tty flip buffer push task
- *
- * This structure describes a single Rx DMA transaction. Rx DMA
- * transactions use box mode DMA commands.
- */
-struct msm_hs_rx {
-       enum flush_reason flush;
-       struct msm_dmov_cmd xfer;
-       dma_addr_t cmdptr_dmaaddr;
-       dmov_box *command_ptr;
-       u32 *command_ptr_ptr;
-       dma_addr_t mapped_cmd_ptr;
-       wait_queue_head_t wait;
-       dma_addr_t rbuffer;
-       unsigned char *buffer;
-       struct dma_pool *pool;
-       struct work_struct tty_work;
-};
-
-/**
- * struct msm_hs_rx_wakeup
- * @irq: IRQ line to be configured as interrupt source on Rx activity
- * @ignore: boolean value. 1 = ignore the wakeup interrupt
- * @rx_to_inject: extra character to be inserted to Rx tty on wakeup
- * @inject_rx: 1 = insert rx_to_inject. 0 = do not insert extra character
- *
- * This is an optional structure required for UART Rx GPIO IRQ based
- * wakeup from low power state. UART wakeup can be triggered by RX activity
- * (using a wakeup GPIO on the UART RX pin). This should only be used if
- * there is not a wakeup GPIO on the UART CTS, and the first RX byte is
- * known (eg., with the Bluetooth Texas Instruments HCILL protocol),
- * since the first RX byte will always be lost. RTS will be asserted even
- * while the UART is clocked off in this mode of operation.
- */
-struct msm_hs_rx_wakeup {
-       int irq;  /* < 0 indicates low power wakeup disabled */
-       unsigned char ignore;
-       unsigned char inject_rx;
-       char rx_to_inject;
-};
-
-/**
- * struct msm_hs_port
- * @uport: embedded uart port structure
- * @imr_reg: shadow value of UARTDM_IMR
- * @clk: uart input clock handle
- * @tx: Tx transaction related data structure
- * @rx: Rx transaction related data structure
- * @dma_tx_channel: Tx DMA command channel
- * @dma_rx_channel Rx DMA command channel
- * @dma_tx_crci: Tx channel rate control interface number
- * @dma_rx_crci: Rx channel rate control interface number
- * @clk_off_timer: Timer to poll DMA event completion before clock off
- * @clk_off_delay: clk_off_timer poll interval
- * @clk_state: overall clock state
- * @clk_req_off_state: post flush clock states
- * @rx_wakeup: optional rx_wakeup feature related data
- * @exit_lpm_cb: optional callback to exit low power mode
- *
- * Low level serial port structure.
- */
-struct msm_hs_port {
-       struct uart_port uport;
-       unsigned long imr_reg;
-       struct clk *clk;
-       struct msm_hs_tx tx;
-       struct msm_hs_rx rx;
-
-       int dma_tx_channel;
-       int dma_rx_channel;
-       int dma_tx_crci;
-       int dma_rx_crci;
-
-       struct hrtimer clk_off_timer;
-       ktime_t clk_off_delay;
-       enum msm_hs_clk_states_e clk_state;
-       enum msm_hs_clk_req_off_state_e clk_req_off_state;
-
-       struct msm_hs_rx_wakeup rx_wakeup;
-       void (*exit_lpm_cb)(struct uart_port *);
-};
-
-#define MSM_UARTDM_BURST_SIZE 16   /* DM burst size (in bytes) */
-#define UARTDM_TX_BUF_SIZE UART_XMIT_SIZE
-#define UARTDM_RX_BUF_SIZE 512
-
-#define UARTDM_NR 2
-
-static struct msm_hs_port q_uart_port[UARTDM_NR];
-static struct platform_driver msm_serial_hs_platform_driver;
-static struct uart_driver msm_hs_driver;
-static struct uart_ops msm_hs_ops;
-static struct workqueue_struct *msm_hs_workqueue;
-
-#define UARTDM_TO_MSM(uart_port) \
-       container_of((uart_port), struct msm_hs_port, uport)
-
-static unsigned int use_low_power_rx_wakeup(struct msm_hs_port
-                                                  *msm_uport)
-{
-       return (msm_uport->rx_wakeup.irq >= 0);
-}
-
-static unsigned int msm_hs_read(struct uart_port *uport,
-                                      unsigned int offset)
-{
-       return ioread32(uport->membase + offset);
-}
-
-static void msm_hs_write(struct uart_port *uport, unsigned int offset,
-                                unsigned int value)
-{
-       iowrite32(value, uport->membase + offset);
-}
-
-static void msm_hs_release_port(struct uart_port *port)
-{
-       iounmap(port->membase);
-}
-
-static int msm_hs_request_port(struct uart_port *port)
-{
-       port->membase = ioremap(port->mapbase, PAGE_SIZE);
-       if (unlikely(!port->membase))
-               return -ENOMEM;
-
-       /* configure the CR Protection to Enable */
-       msm_hs_write(port, UARTDM_CR_ADDR, CR_PROTECTION_EN);
-       return 0;
-}
-
-static int msm_hs_remove(struct platform_device *pdev)
-{
-
-       struct msm_hs_port *msm_uport;
-       struct device *dev;
-
-       if (pdev->id < 0 || pdev->id >= UARTDM_NR) {
-               printk(KERN_ERR "Invalid plaform device ID = %d\n", pdev->id);
-               return -EINVAL;
-       }
-
-       msm_uport = &q_uart_port[pdev->id];
-       dev = msm_uport->uport.dev;
-
-       dma_unmap_single(dev, msm_uport->rx.mapped_cmd_ptr, sizeof(dmov_box),
-                        DMA_TO_DEVICE);
-       dma_pool_free(msm_uport->rx.pool, msm_uport->rx.buffer,
-                     msm_uport->rx.rbuffer);
-       dma_pool_destroy(msm_uport->rx.pool);
-
-       dma_unmap_single(dev, msm_uport->rx.cmdptr_dmaaddr, sizeof(u32),
-                        DMA_TO_DEVICE);
-       dma_unmap_single(dev, msm_uport->tx.mapped_cmd_ptr_ptr, sizeof(u32),
-                        DMA_TO_DEVICE);
-       dma_unmap_single(dev, msm_uport->tx.mapped_cmd_ptr, sizeof(dmov_box),
-                        DMA_TO_DEVICE);
-
-       uart_remove_one_port(&msm_hs_driver, &msm_uport->uport);
-       clk_put(msm_uport->clk);
-
-       /* Free the tx resources */
-       kfree(msm_uport->tx.command_ptr);
-       kfree(msm_uport->tx.command_ptr_ptr);
-
-       /* Free the rx resources */
-       kfree(msm_uport->rx.command_ptr);
-       kfree(msm_uport->rx.command_ptr_ptr);
-
-       iounmap(msm_uport->uport.membase);
-
-       return 0;
-}
-
-static int msm_hs_init_clk_locked(struct uart_port *uport)
-{
-       int ret;
-       struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
-
-       ret = clk_enable(msm_uport->clk);
-       if (ret) {
-               printk(KERN_ERR "Error could not turn on UART clk\n");
-               return ret;
-       }
-
-       /* Set up the MREG/NREG/DREG/MNDREG */
-       ret = clk_set_rate(msm_uport->clk, uport->uartclk);
-       if (ret) {
-               printk(KERN_WARNING "Error setting clock rate on UART\n");
-               clk_disable(msm_uport->clk);
-               return ret;
-       }
-
-       msm_uport->clk_state = MSM_HS_CLK_ON;
-       return 0;
-}
-
-/* Enable and Disable clocks  (Used for power management) */
-static void msm_hs_pm(struct uart_port *uport, unsigned int state,
-                     unsigned int oldstate)
-{
-       struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
-
-       if (use_low_power_rx_wakeup(msm_uport) ||
-           msm_uport->exit_lpm_cb)
-               return;  /* ignore linux PM states,
-                           use msm_hs_request_clock API */
-
-       switch (state) {
-       case 0:
-               clk_enable(msm_uport->clk);
-               break;
-       case 3:
-               clk_disable(msm_uport->clk);
-               break;
-       default:
-               dev_err(uport->dev, "msm_serial: Unknown PM state %d\n",
-                       state);
-       }
-}
-
-/*
- * programs the UARTDM_CSR register with correct bit rates
- *
- * Interrupts should be disabled before we are called, as
- * we modify Set Baud rate
- * Set receive stale interrupt level, dependent on Bit Rate
- * Goal is to have around 8 ms before indicate stale.
- * roundup (((Bit Rate * .008) / 10) + 1
- */
-static void msm_hs_set_bps_locked(struct uart_port *uport,
-                                 unsigned int bps)
-{
-       unsigned long rxstale;
-       unsigned long data;
-       struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
-
-       switch (bps) {
-       case 300:
-               msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_75);
-               rxstale = 1;
-               break;
-       case 600:
-               msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_150);
-               rxstale = 1;
-               break;
-       case 1200:
-               msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_300);
-               rxstale = 1;
-               break;
-       case 2400:
-               msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_600);
-               rxstale = 1;
-               break;
-       case 4800:
-               msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_1200);
-               rxstale = 1;
-               break;
-       case 9600:
-               msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_2400);
-               rxstale = 2;
-               break;
-       case 14400:
-               msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_3600);
-               rxstale = 3;
-               break;
-       case 19200:
-               msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_4800);
-               rxstale = 4;
-               break;
-       case 28800:
-               msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_7200);
-               rxstale = 6;
-               break;
-       case 38400:
-               msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_9600);
-               rxstale = 8;
-               break;
-       case 57600:
-               msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_14400);
-               rxstale = 16;
-               break;
-       case 76800:
-               msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_19200);
-               rxstale = 16;
-               break;
-       case 115200:
-               msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_28800);
-               rxstale = 31;
-               break;
-       case 230400:
-               msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_57600);
-               rxstale = 31;
-               break;
-       case 460800:
-               msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_115200);
-               rxstale = 31;
-               break;
-       case 4000000:
-       case 3686400:
-       case 3200000:
-       case 3500000:
-       case 3000000:
-       case 2500000:
-       case 1500000:
-       case 1152000:
-       case 1000000:
-       case 921600:
-               msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_115200);
-               rxstale = 31;
-               break;
-       default:
-               msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_2400);
-               /* default to 9600 */
-               bps = 9600;
-               rxstale = 2;
-               break;
-       }
-       if (bps > 460800)
-               uport->uartclk = bps * 16;
-       else
-               uport->uartclk = UARTCLK;
-
-       if (clk_set_rate(msm_uport->clk, uport->uartclk)) {
-               printk(KERN_WARNING "Error setting clock rate on UART\n");
-               return;
-       }
-
-       data = rxstale & UARTDM_IPR_STALE_LSB_BMSK;
-       data |= UARTDM_IPR_STALE_TIMEOUT_MSB_BMSK & (rxstale << 2);
-
-       msm_hs_write(uport, UARTDM_IPR_ADDR, data);
-}
-
-/*
- * termios :  new ktermios
- * oldtermios:  old ktermios previous setting
- *
- * Configure the serial port
- */
-static void msm_hs_set_termios(struct uart_port *uport,
-                              struct ktermios *termios,
-                              struct ktermios *oldtermios)
-{
-       unsigned int bps;
-       unsigned long data;
-       unsigned long flags;
-       unsigned int c_cflag = termios->c_cflag;
-       struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
-
-       spin_lock_irqsave(&uport->lock, flags);
-       clk_enable(msm_uport->clk);
-
-       /* 300 is the minimum baud support by the driver  */
-       bps = uart_get_baud_rate(uport, termios, oldtermios, 200, 4000000);
-
-       /* Temporary remapping  200 BAUD to 3.2 mbps */
-       if (bps == 200)
-               bps = 3200000;
-
-       msm_hs_set_bps_locked(uport, bps);
-
-       data = msm_hs_read(uport, UARTDM_MR2_ADDR);
-       data &= ~UARTDM_MR2_PARITY_MODE_BMSK;
-       /* set parity */
-       if (PARENB == (c_cflag & PARENB)) {
-               if (PARODD == (c_cflag & PARODD))
-                       data |= ODD_PARITY;
-               else if (CMSPAR == (c_cflag & CMSPAR))
-                       data |= SPACE_PARITY;
-               else
-                       data |= EVEN_PARITY;
-       }
-
-       /* Set bits per char */
-       data &= ~UARTDM_MR2_BITS_PER_CHAR_BMSK;
-
-       switch (c_cflag & CSIZE) {
-       case CS5:
-               data |= FIVE_BPC;
-               break;
-       case CS6:
-               data |= SIX_BPC;
-               break;
-       case CS7:
-               data |= SEVEN_BPC;
-               break;
-       default:
-               data |= EIGHT_BPC;
-               break;
-       }
-       /* stop bits */
-       if (c_cflag & CSTOPB) {
-               data |= STOP_BIT_TWO;
-       } else {
-               /* otherwise 1 stop bit */
-               data |= STOP_BIT_ONE;
-       }
-       data |= UARTDM_MR2_ERROR_MODE_BMSK;
-       /* write parity/bits per char/stop bit configuration */
-       msm_hs_write(uport, UARTDM_MR2_ADDR, data);
-
-       /* Configure HW flow control */
-       data = msm_hs_read(uport, UARTDM_MR1_ADDR);
-
-       data &= ~(UARTDM_MR1_CTS_CTL_BMSK | UARTDM_MR1_RX_RDY_CTL_BMSK);
-
-       if (c_cflag & CRTSCTS) {
-               data |= UARTDM_MR1_CTS_CTL_BMSK;
-               data |= UARTDM_MR1_RX_RDY_CTL_BMSK;
-       }
-
-       msm_hs_write(uport, UARTDM_MR1_ADDR, data);
-
-       uport->ignore_status_mask = termios->c_iflag & INPCK;
-       uport->ignore_status_mask |= termios->c_iflag & IGNPAR;
-       uport->read_status_mask = (termios->c_cflag & CREAD);
-
-       msm_hs_write(uport, UARTDM_IMR_ADDR, 0);
-
-       /* Set Transmit software time out */
-       uart_update_timeout(uport, c_cflag, bps);
-
-       msm_hs_write(uport, UARTDM_CR_ADDR, RESET_RX);
-       msm_hs_write(uport, UARTDM_CR_ADDR, RESET_TX);
-
-       if (msm_uport->rx.flush == FLUSH_NONE) {
-               msm_uport->rx.flush = FLUSH_IGNORE;
-               msm_dmov_stop_cmd(msm_uport->dma_rx_channel, NULL, 1);
-       }
-
-       msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
-
-       clk_disable(msm_uport->clk);
-       spin_unlock_irqrestore(&uport->lock, flags);
-}
-
-/*
- *  Standard API, Transmitter
- *  Any character in the transmit shift register is sent
- */
-static unsigned int msm_hs_tx_empty(struct uart_port *uport)
-{
-       unsigned int data;
-       unsigned int ret = 0;
-       struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
-
-       clk_enable(msm_uport->clk);
-
-       data = msm_hs_read(uport, UARTDM_SR_ADDR);
-       if (data & UARTDM_SR_TXEMT_BMSK)
-               ret = TIOCSER_TEMT;
-
-       clk_disable(msm_uport->clk);
-
-       return ret;
-}
-
-/*
- *  Standard API, Stop transmitter.
- *  Any character in the transmit shift register is sent as
- *  well as the current data mover transfer .
- */
-static void msm_hs_stop_tx_locked(struct uart_port *uport)
-{
-       struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
-
-       msm_uport->tx.tx_ready_int_en = 0;
-}
-
-/*
- *  Standard API, Stop receiver as soon as possible.
- *
- *  Function immediately terminates the operation of the
- *  channel receiver and any incoming characters are lost. None
- *  of the receiver status bits are affected by this command and
- *  characters that are already in the receive FIFO there.
- */
-static void msm_hs_stop_rx_locked(struct uart_port *uport)
-{
-       struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
-       unsigned int data;
-
-       clk_enable(msm_uport->clk);
-
-       /* disable dlink */
-       data = msm_hs_read(uport, UARTDM_DMEN_ADDR);
-       data &= ~UARTDM_RX_DM_EN_BMSK;
-       msm_hs_write(uport, UARTDM_DMEN_ADDR, data);
-
-       /* Disable the receiver */
-       if (msm_uport->rx.flush == FLUSH_NONE)
-               msm_dmov_stop_cmd(msm_uport->dma_rx_channel, NULL, 1);
-
-       if (msm_uport->rx.flush != FLUSH_SHUTDOWN)
-               msm_uport->rx.flush = FLUSH_STOP;
-
-       clk_disable(msm_uport->clk);
-}
-
-/*  Transmit the next chunk of data */
-static void msm_hs_submit_tx_locked(struct uart_port *uport)
-{
-       int left;
-       int tx_count;
-       dma_addr_t src_addr;
-       struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
-       struct msm_hs_tx *tx = &msm_uport->tx;
-       struct circ_buf *tx_buf = &msm_uport->uport.state->xmit;
-
-       if (uart_circ_empty(tx_buf) || uport->state->port.tty->stopped) {
-               msm_hs_stop_tx_locked(uport);
-               return;
-       }
-
-       tx->dma_in_flight = 1;
-
-       tx_count = uart_circ_chars_pending(tx_buf);
-
-       if (UARTDM_TX_BUF_SIZE < tx_count)
-               tx_count = UARTDM_TX_BUF_SIZE;
-
-       left = UART_XMIT_SIZE - tx_buf->tail;
-
-       if (tx_count > left)
-               tx_count = left;
-
-       src_addr = tx->dma_base + tx_buf->tail;
-       dma_sync_single_for_device(uport->dev, src_addr, tx_count,
-                                  DMA_TO_DEVICE);
-
-       tx->command_ptr->num_rows = (((tx_count + 15) >> 4) << 16) |
-                                    ((tx_count + 15) >> 4);
-       tx->command_ptr->src_row_addr = src_addr;
-
-       dma_sync_single_for_device(uport->dev, tx->mapped_cmd_ptr,
-                                  sizeof(dmov_box), DMA_TO_DEVICE);
-
-       *tx->command_ptr_ptr = CMD_PTR_LP | DMOV_CMD_ADDR(tx->mapped_cmd_ptr);
-
-       dma_sync_single_for_device(uport->dev, tx->mapped_cmd_ptr_ptr,
-                                  sizeof(u32), DMA_TO_DEVICE);
-
-       /* Save tx_count to use in Callback */
-       tx->tx_count = tx_count;
-       msm_hs_write(uport, UARTDM_NCF_TX_ADDR, tx_count);
-
-       /* Disable the tx_ready interrupt */
-       msm_uport->imr_reg &= ~UARTDM_ISR_TX_READY_BMSK;
-       msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
-       msm_dmov_enqueue_cmd(msm_uport->dma_tx_channel, &tx->xfer);
-}
-
-/* Start to receive the next chunk of data */
-static void msm_hs_start_rx_locked(struct uart_port *uport)
-{
-       struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
-
-       msm_hs_write(uport, UARTDM_CR_ADDR, RESET_STALE_INT);
-       msm_hs_write(uport, UARTDM_DMRX_ADDR, UARTDM_RX_BUF_SIZE);
-       msm_hs_write(uport, UARTDM_CR_ADDR, STALE_EVENT_ENABLE);
-       msm_uport->imr_reg |= UARTDM_ISR_RXLEV_BMSK;
-       msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
-
-       msm_uport->rx.flush = FLUSH_NONE;
-       msm_dmov_enqueue_cmd(msm_uport->dma_rx_channel, &msm_uport->rx.xfer);
-
-       /* might have finished RX and be ready to clock off */
-       hrtimer_start(&msm_uport->clk_off_timer, msm_uport->clk_off_delay,
-                       HRTIMER_MODE_REL);
-}
-
-/* Enable the transmitter Interrupt */
-static void msm_hs_start_tx_locked(struct uart_port *uport)
-{
-       struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
-
-       clk_enable(msm_uport->clk);
-
-       if (msm_uport->exit_lpm_cb)
-               msm_uport->exit_lpm_cb(uport);
-
-       if (msm_uport->tx.tx_ready_int_en == 0) {
-               msm_uport->tx.tx_ready_int_en = 1;
-               msm_hs_submit_tx_locked(uport);
-       }
-
-       clk_disable(msm_uport->clk);
-}
-
-/*
- *  This routine is called when we are done with a DMA transfer
- *
- *  This routine is registered with Data mover when we set
- *  up a Data Mover transfer. It is called from Data mover ISR
- *  when the DMA transfer is done.
- */
-static void msm_hs_dmov_tx_callback(struct msm_dmov_cmd *cmd_ptr,
-                                       unsigned int result,
-                                       struct msm_dmov_errdata *err)
-{
-       unsigned long flags;
-       struct msm_hs_port *msm_uport;
-
-       /* DMA did not finish properly */
-       WARN_ON((((result & RSLT_FIFO_CNTR_BMSK) >> 28) == 1) &&
-               !(result & RSLT_VLD));
-
-       msm_uport = container_of(cmd_ptr, struct msm_hs_port, tx.xfer);
-
-       spin_lock_irqsave(&msm_uport->uport.lock, flags);
-       clk_enable(msm_uport->clk);
-
-       msm_uport->imr_reg |= UARTDM_ISR_TX_READY_BMSK;
-       msm_hs_write(&msm_uport->uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
-
-       clk_disable(msm_uport->clk);
-       spin_unlock_irqrestore(&msm_uport->uport.lock, flags);
-}
-
-/*
- * This routine is called when we are done with a DMA transfer or the
- * a flush has been sent to the data mover driver.
- *
- * This routine is registered with Data mover when we set up a Data Mover
- *  transfer. It is called from Data mover ISR when the DMA transfer is done.
- */
-static void msm_hs_dmov_rx_callback(struct msm_dmov_cmd *cmd_ptr,
-                                       unsigned int result,
-                                       struct msm_dmov_errdata *err)
-{
-       int retval;
-       int rx_count;
-       unsigned long status;
-       unsigned int error_f = 0;
-       unsigned long flags;
-       unsigned int flush;
-       struct tty_port *port;
-       struct uart_port *uport;
-       struct msm_hs_port *msm_uport;
-
-       msm_uport = container_of(cmd_ptr, struct msm_hs_port, rx.xfer);
-       uport = &msm_uport->uport;
-
-       spin_lock_irqsave(&uport->lock, flags);
-       clk_enable(msm_uport->clk);
-
-       port = &uport->state->port;
-
-       msm_hs_write(uport, UARTDM_CR_ADDR, STALE_EVENT_DISABLE);
-
-       status = msm_hs_read(uport, UARTDM_SR_ADDR);
-
-       /* overflow is not connect to data in a FIFO */
-       if (unlikely((status & UARTDM_SR_OVERRUN_BMSK) &&
-                    (uport->read_status_mask & CREAD))) {
-               tty_insert_flip_char(port, 0, TTY_OVERRUN);
-               uport->icount.buf_overrun++;
-               error_f = 1;
-       }
-
-       if (!(uport->ignore_status_mask & INPCK))
-               status = status & ~(UARTDM_SR_PAR_FRAME_BMSK);
-
-       if (unlikely(status & UARTDM_SR_PAR_FRAME_BMSK)) {
-               /* Can not tell difference between parity & frame error */
-               uport->icount.parity++;
-               error_f = 1;
-               if (uport->ignore_status_mask & IGNPAR)
-                       tty_insert_flip_char(port, 0, TTY_PARITY);
-       }
-
-       if (error_f)
-               msm_hs_write(uport, UARTDM_CR_ADDR, RESET_ERROR_STATUS);
-
-       if (msm_uport->clk_req_off_state == CLK_REQ_OFF_FLUSH_ISSUED)
-               msm_uport->clk_req_off_state = CLK_REQ_OFF_RXSTALE_FLUSHED;
-
-       flush = msm_uport->rx.flush;
-       if (flush == FLUSH_IGNORE)
-               msm_hs_start_rx_locked(uport);
-       if (flush == FLUSH_STOP)
-               msm_uport->rx.flush = FLUSH_SHUTDOWN;
-       if (flush >= FLUSH_DATA_INVALID)
-               goto out;
-
-       rx_count = msm_hs_read(uport, UARTDM_RX_TOTAL_SNAP_ADDR);
-
-       if (0 != (uport->read_status_mask & CREAD)) {
-               retval = tty_insert_flip_string(port, msm_uport->rx.buffer,
-                                               rx_count);
-               BUG_ON(retval != rx_count);
-       }
-
-       msm_hs_start_rx_locked(uport);
-
-out:
-       clk_disable(msm_uport->clk);
-
-       spin_unlock_irqrestore(&uport->lock, flags);
-
-       if (flush < FLUSH_DATA_INVALID)
-               queue_work(msm_hs_workqueue, &msm_uport->rx.tty_work);
-}
-
-static void msm_hs_tty_flip_buffer_work(struct work_struct *work)
-{
-       struct msm_hs_port *msm_uport =
-                       container_of(work, struct msm_hs_port, rx.tty_work);
-
-       tty_flip_buffer_push(&msm_uport->uport.state->port);
-}
-
-/*
- *  Standard API, Current states of modem control inputs
- *
- * Since CTS can be handled entirely by HARDWARE we always
- * indicate clear to send and count on the TX FIFO to block when
- * it fills up.
- *
- * - TIOCM_DCD
- * - TIOCM_CTS
- * - TIOCM_DSR
- * - TIOCM_RI
- *  (Unsupported) DCD and DSR will return them high. RI will return low.
- */
-static unsigned int msm_hs_get_mctrl_locked(struct uart_port *uport)
-{
-       return TIOCM_DSR | TIOCM_CAR | TIOCM_CTS;
-}
-
-/*
- * True enables UART auto RFR, which indicates we are ready for data if the RX
- * buffer is not full. False disables auto RFR, and deasserts RFR to indicate
- * we are not ready for data. Must be called with UART clock on.
- */
-static void set_rfr_locked(struct uart_port *uport, int auto_rfr)
-{
-       unsigned int data;
-
-       data = msm_hs_read(uport, UARTDM_MR1_ADDR);
-
-       if (auto_rfr) {
-               /* enable auto ready-for-receiving */
-               data |= UARTDM_MR1_RX_RDY_CTL_BMSK;
-               msm_hs_write(uport, UARTDM_MR1_ADDR, data);
-       } else {
-               /* disable auto ready-for-receiving */
-               data &= ~UARTDM_MR1_RX_RDY_CTL_BMSK;
-               msm_hs_write(uport, UARTDM_MR1_ADDR, data);
-               /* RFR is active low, set high */
-               msm_hs_write(uport, UARTDM_CR_ADDR, RFR_HIGH);
-       }
-}
-
-/*
- *  Standard API, used to set or clear RFR
- */
-static void msm_hs_set_mctrl_locked(struct uart_port *uport,
-                                   unsigned int mctrl)
-{
-       unsigned int auto_rfr;
-       struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
-
-       clk_enable(msm_uport->clk);
-
-       auto_rfr = TIOCM_RTS & mctrl ? 1 : 0;
-       set_rfr_locked(uport, auto_rfr);
-
-       clk_disable(msm_uport->clk);
-}
-
-/* Standard API, Enable modem status (CTS) interrupt  */
-static void msm_hs_enable_ms_locked(struct uart_port *uport)
-{
-       struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
-
-       clk_enable(msm_uport->clk);
-
-       /* Enable DELTA_CTS Interrupt */
-       msm_uport->imr_reg |= UARTDM_ISR_DELTA_CTS_BMSK;
-       msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
-
-       clk_disable(msm_uport->clk);
-
-}
-
-/*
- *  Standard API, Break Signal
- *
- * Control the transmission of a break signal. ctl eq 0 => break
- * signal terminate ctl ne 0 => start break signal
- */
-static void msm_hs_break_ctl(struct uart_port *uport, int ctl)
-{
-       struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
-
-       clk_enable(msm_uport->clk);
-       msm_hs_write(uport, UARTDM_CR_ADDR, ctl ? START_BREAK : STOP_BREAK);
-       clk_disable(msm_uport->clk);
-}
-
-static void msm_hs_config_port(struct uart_port *uport, int cfg_flags)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&uport->lock, flags);
-       if (cfg_flags & UART_CONFIG_TYPE) {
-               uport->type = PORT_MSM;
-               msm_hs_request_port(uport);
-       }
-       spin_unlock_irqrestore(&uport->lock, flags);
-}
-
-/*  Handle CTS changes (Called from interrupt handler) */
-static void msm_hs_handle_delta_cts_locked(struct uart_port *uport)
-{
-       struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
-
-       clk_enable(msm_uport->clk);
-
-       /* clear interrupt */
-       msm_hs_write(uport, UARTDM_CR_ADDR, RESET_CTS);
-       uport->icount.cts++;
-
-       clk_disable(msm_uport->clk);
-
-       /* clear the IOCTL TIOCMIWAIT if called */
-       wake_up_interruptible(&uport->state->port.delta_msr_wait);
-}
-
-/* check if the TX path is flushed, and if so clock off
- * returns 0 did not clock off, need to retry (still sending final byte)
- *        -1 did not clock off, do not retry
- *         1 if we clocked off
- */
-static int msm_hs_check_clock_off_locked(struct uart_port *uport)
-{
-       unsigned long sr_status;
-       struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
-       struct circ_buf *tx_buf = &uport->state->xmit;
-
-       /* Cancel if tx tty buffer is not empty, dma is in flight,
-        * or tx fifo is not empty, or rx fifo is not empty */
-       if (msm_uport->clk_state != MSM_HS_CLK_REQUEST_OFF ||
-           !uart_circ_empty(tx_buf) || msm_uport->tx.dma_in_flight ||
-           (msm_uport->imr_reg & UARTDM_ISR_TXLEV_BMSK) ||
-           !(msm_uport->imr_reg & UARTDM_ISR_RXLEV_BMSK))  {
-               return -1;
-       }
-
-       /* Make sure the uart is finished with the last byte */
-       sr_status = msm_hs_read(uport, UARTDM_SR_ADDR);
-       if (!(sr_status & UARTDM_SR_TXEMT_BMSK))
-               return 0;  /* retry */
-
-       /* Make sure forced RXSTALE flush complete */
-       switch (msm_uport->clk_req_off_state) {
-       case CLK_REQ_OFF_START:
-               msm_uport->clk_req_off_state = CLK_REQ_OFF_RXSTALE_ISSUED;
-               msm_hs_write(uport, UARTDM_CR_ADDR, FORCE_STALE_EVENT);
-               return 0;  /* RXSTALE flush not complete - retry */
-       case CLK_REQ_OFF_RXSTALE_ISSUED:
-       case CLK_REQ_OFF_FLUSH_ISSUED:
-               return 0;  /* RXSTALE flush not complete - retry */
-       case CLK_REQ_OFF_RXSTALE_FLUSHED:
-               break;  /* continue */
-       }
-
-       if (msm_uport->rx.flush != FLUSH_SHUTDOWN) {
-               if (msm_uport->rx.flush == FLUSH_NONE)
-                       msm_hs_stop_rx_locked(uport);
-               return 0;  /* come back later to really clock off */
-       }
-
-       /* we really want to clock off */
-       clk_disable(msm_uport->clk);
-       msm_uport->clk_state = MSM_HS_CLK_OFF;
-
-       if (use_low_power_rx_wakeup(msm_uport)) {
-               msm_uport->rx_wakeup.ignore = 1;
-               enable_irq(msm_uport->rx_wakeup.irq);
-       }
-       return 1;
-}
-
-static enum hrtimer_restart msm_hs_clk_off_retry(struct hrtimer *timer)
-{
-       unsigned long flags;
-       int ret = HRTIMER_NORESTART;
-       struct msm_hs_port *msm_uport = container_of(timer, struct msm_hs_port,
-                                                    clk_off_timer);
-       struct uart_port *uport = &msm_uport->uport;
-
-       spin_lock_irqsave(&uport->lock, flags);
-
-       if (!msm_hs_check_clock_off_locked(uport)) {
-               hrtimer_forward_now(timer, msm_uport->clk_off_delay);
-               ret = HRTIMER_RESTART;
-       }
-
-       spin_unlock_irqrestore(&uport->lock, flags);
-
-       return ret;
-}
-
-static irqreturn_t msm_hs_isr(int irq, void *dev)
-{
-       unsigned long flags;
-       unsigned long isr_status;
-       struct msm_hs_port *msm_uport = dev;
-       struct uart_port *uport = &msm_uport->uport;
-       struct circ_buf *tx_buf = &uport->state->xmit;
-       struct msm_hs_tx *tx = &msm_uport->tx;
-       struct msm_hs_rx *rx = &msm_uport->rx;
-
-       spin_lock_irqsave(&uport->lock, flags);
-
-       isr_status = msm_hs_read(uport, UARTDM_MISR_ADDR);
-
-       /* Uart RX starting */
-       if (isr_status & UARTDM_ISR_RXLEV_BMSK) {
-               msm_uport->imr_reg &= ~UARTDM_ISR_RXLEV_BMSK;
-               msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
-       }
-       /* Stale rx interrupt */
-       if (isr_status & UARTDM_ISR_RXSTALE_BMSK) {
-               msm_hs_write(uport, UARTDM_CR_ADDR, STALE_EVENT_DISABLE);
-               msm_hs_write(uport, UARTDM_CR_ADDR, RESET_STALE_INT);
-
-               if (msm_uport->clk_req_off_state == CLK_REQ_OFF_RXSTALE_ISSUED)
-                       msm_uport->clk_req_off_state =
-                                       CLK_REQ_OFF_FLUSH_ISSUED;
-               if (rx->flush == FLUSH_NONE) {
-                       rx->flush = FLUSH_DATA_READY;
-                       msm_dmov_stop_cmd(msm_uport->dma_rx_channel, NULL, 1);
-               }
-       }
-       /* tx ready interrupt */
-       if (isr_status & UARTDM_ISR_TX_READY_BMSK) {
-               /* Clear  TX Ready */
-               msm_hs_write(uport, UARTDM_CR_ADDR, CLEAR_TX_READY);
-
-               if (msm_uport->clk_state == MSM_HS_CLK_REQUEST_OFF) {
-                       msm_uport->imr_reg |= UARTDM_ISR_TXLEV_BMSK;
-                       msm_hs_write(uport, UARTDM_IMR_ADDR,
-                                    msm_uport->imr_reg);
-               }
-
-               /* Complete DMA TX transactions and submit new transactions */
-               tx_buf->tail = (tx_buf->tail + tx->tx_count) & ~UART_XMIT_SIZE;
-
-               tx->dma_in_flight = 0;
-
-               uport->icount.tx += tx->tx_count;
-               if (tx->tx_ready_int_en)
-                       msm_hs_submit_tx_locked(uport);
-
-               if (uart_circ_chars_pending(tx_buf) < WAKEUP_CHARS)
-                       uart_write_wakeup(uport);
-       }
-       if (isr_status & UARTDM_ISR_TXLEV_BMSK) {
-               /* TX FIFO is empty */
-               msm_uport->imr_reg &= ~UARTDM_ISR_TXLEV_BMSK;
-               msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
-               if (!msm_hs_check_clock_off_locked(uport))
-                       hrtimer_start(&msm_uport->clk_off_timer,
-                                     msm_uport->clk_off_delay,
-                                     HRTIMER_MODE_REL);
-       }
-
-       /* Change in CTS interrupt */
-       if (isr_status & UARTDM_ISR_DELTA_CTS_BMSK)
-               msm_hs_handle_delta_cts_locked(uport);
-
-       spin_unlock_irqrestore(&uport->lock, flags);
-
-       return IRQ_HANDLED;
-}
-
-void msm_hs_request_clock_off_locked(struct uart_port *uport)
-{
-       struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
-
-       if (msm_uport->clk_state == MSM_HS_CLK_ON) {
-               msm_uport->clk_state = MSM_HS_CLK_REQUEST_OFF;
-               msm_uport->clk_req_off_state = CLK_REQ_OFF_START;
-               if (!use_low_power_rx_wakeup(msm_uport))
-                       set_rfr_locked(uport, 0);
-               msm_uport->imr_reg |= UARTDM_ISR_TXLEV_BMSK;
-               msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
-       }
-}
-
-/**
- * msm_hs_request_clock_off - request to (i.e. asynchronously) turn off uart
- * clock once pending TX is flushed and Rx DMA command is terminated.
- * @uport: uart_port structure for the device instance.
- *
- * This functions puts the device into a partially active low power mode. It
- * waits to complete all pending tx transactions, flushes ongoing Rx DMA
- * command and terminates UART side Rx transaction, puts UART HW in non DMA
- * mode and then clocks off the device. A client calls this when no UART
- * data is expected. msm_request_clock_on() must be called before any further
- * UART can be sent or received.
- */
-void msm_hs_request_clock_off(struct uart_port *uport)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&uport->lock, flags);
-       msm_hs_request_clock_off_locked(uport);
-       spin_unlock_irqrestore(&uport->lock, flags);
-}
-
-void msm_hs_request_clock_on_locked(struct uart_port *uport)
-{
-       struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
-       unsigned int data;
-
-       switch (msm_uport->clk_state) {
-       case MSM_HS_CLK_OFF:
-               clk_enable(msm_uport->clk);
-               disable_irq_nosync(msm_uport->rx_wakeup.irq);
-               /* fall-through */
-       case MSM_HS_CLK_REQUEST_OFF:
-               if (msm_uport->rx.flush == FLUSH_STOP ||
-                   msm_uport->rx.flush == FLUSH_SHUTDOWN) {
-                       msm_hs_write(uport, UARTDM_CR_ADDR, RESET_RX);
-                       data = msm_hs_read(uport, UARTDM_DMEN_ADDR);
-                       data |= UARTDM_RX_DM_EN_BMSK;
-                       msm_hs_write(uport, UARTDM_DMEN_ADDR, data);
-               }
-               hrtimer_try_to_cancel(&msm_uport->clk_off_timer);
-               if (msm_uport->rx.flush == FLUSH_SHUTDOWN)
-                       msm_hs_start_rx_locked(uport);
-               if (!use_low_power_rx_wakeup(msm_uport))
-                       set_rfr_locked(uport, 1);
-               if (msm_uport->rx.flush == FLUSH_STOP)
-                       msm_uport->rx.flush = FLUSH_IGNORE;
-               msm_uport->clk_state = MSM_HS_CLK_ON;
-               break;
-       case MSM_HS_CLK_ON:
-               break;
-       case MSM_HS_CLK_PORT_OFF:
-               break;
-       }
-}
-
-/**
- * msm_hs_request_clock_on - Switch the device from partially active low
- * power mode to fully active (i.e. clock on) mode.
- * @uport: uart_port structure for the device.
- *
- * This function switches on the input clock, puts UART HW into DMA mode
- * and enqueues an Rx DMA command if the device was in partially active
- * mode. It has no effect if called with the device in inactive state.
- */
-void msm_hs_request_clock_on(struct uart_port *uport)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&uport->lock, flags);
-       msm_hs_request_clock_on_locked(uport);
-       spin_unlock_irqrestore(&uport->lock, flags);
-}
-
-static irqreturn_t msm_hs_rx_wakeup_isr(int irq, void *dev)
-{
-       unsigned int wakeup = 0;
-       unsigned long flags;
-       struct msm_hs_port *msm_uport = dev;
-       struct uart_port *uport = &msm_uport->uport;
-
-       spin_lock_irqsave(&uport->lock, flags);
-       if (msm_uport->clk_state == MSM_HS_CLK_OFF) {
-               /* ignore the first irq - it is a pending irq that occurred
-                * before enable_irq() */
-               if (msm_uport->rx_wakeup.ignore)
-                       msm_uport->rx_wakeup.ignore = 0;
-               else
-                       wakeup = 1;
-       }
-
-       if (wakeup) {
-               /* the uart was clocked off during an rx, wake up and
-                * optionally inject char into tty rx */
-               msm_hs_request_clock_on_locked(uport);
-               if (msm_uport->rx_wakeup.inject_rx) {
-                       tty_insert_flip_char(&uport->state->port,
-                                            msm_uport->rx_wakeup.rx_to_inject,
-                                            TTY_NORMAL);
-                       queue_work(msm_hs_workqueue, &msm_uport->rx.tty_work);
-               }
-       }
-
-       spin_unlock_irqrestore(&uport->lock, flags);
-
-       return IRQ_HANDLED;
-}
-
-static const char *msm_hs_type(struct uart_port *port)
-{
-       return (port->type == PORT_MSM) ? "MSM_HS_UART" : NULL;
-}
-
-/* Called when port is opened */
-static int msm_hs_startup(struct uart_port *uport)
-{
-       int ret;
-       int rfr_level;
-       unsigned long flags;
-       unsigned int data;
-       struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
-       struct circ_buf *tx_buf = &uport->state->xmit;
-       struct msm_hs_tx *tx = &msm_uport->tx;
-       struct msm_hs_rx *rx = &msm_uport->rx;
-
-       rfr_level = uport->fifosize;
-       if (rfr_level > 16)
-               rfr_level -= 16;
-
-       tx->dma_base = dma_map_single(uport->dev, tx_buf->buf, UART_XMIT_SIZE,
-                                     DMA_TO_DEVICE);
-
-       /* do not let tty layer execute RX in global workqueue, use a
-        * dedicated workqueue managed by this driver */
-       uport->state->port.low_latency = 1;
-
-       /* turn on uart clk */
-       ret = msm_hs_init_clk_locked(uport);
-       if (unlikely(ret)) {
-               printk(KERN_ERR "Turning uartclk failed!\n");
-               goto err_msm_hs_init_clk;
-       }
-
-       /* Set auto RFR Level */
-       data = msm_hs_read(uport, UARTDM_MR1_ADDR);
-       data &= ~UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK;
-       data &= ~UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK;
-       data |= (UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK & (rfr_level << 2));
-       data |= (UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK & rfr_level);
-       msm_hs_write(uport, UARTDM_MR1_ADDR, data);
-
-       /* Make sure RXSTALE count is non-zero */
-       data = msm_hs_read(uport, UARTDM_IPR_ADDR);
-       if (!data) {
-               data |= 0x1f & UARTDM_IPR_STALE_LSB_BMSK;
-               msm_hs_write(uport, UARTDM_IPR_ADDR, data);
-       }
-
-       /* Enable Data Mover Mode */
-       data = UARTDM_TX_DM_EN_BMSK | UARTDM_RX_DM_EN_BMSK;
-       msm_hs_write(uport, UARTDM_DMEN_ADDR, data);
-
-       /* Reset TX */
-       msm_hs_write(uport, UARTDM_CR_ADDR, RESET_TX);
-       msm_hs_write(uport, UARTDM_CR_ADDR, RESET_RX);
-       msm_hs_write(uport, UARTDM_CR_ADDR, RESET_ERROR_STATUS);
-       msm_hs_write(uport, UARTDM_CR_ADDR, RESET_BREAK_INT);
-       msm_hs_write(uport, UARTDM_CR_ADDR, RESET_STALE_INT);
-       msm_hs_write(uport, UARTDM_CR_ADDR, RESET_CTS);
-       msm_hs_write(uport, UARTDM_CR_ADDR, RFR_LOW);
-       /* Turn on Uart Receiver */
-       msm_hs_write(uport, UARTDM_CR_ADDR, UARTDM_CR_RX_EN_BMSK);
-
-       /* Turn on Uart Transmitter */
-       msm_hs_write(uport, UARTDM_CR_ADDR, UARTDM_CR_TX_EN_BMSK);
-
-       /* Initialize the tx */
-       tx->tx_ready_int_en = 0;
-       tx->dma_in_flight = 0;
-
-       tx->xfer.complete_func = msm_hs_dmov_tx_callback;
-       tx->xfer.execute_func = NULL;
-
-       tx->command_ptr->cmd = CMD_LC |
-           CMD_DST_CRCI(msm_uport->dma_tx_crci) | CMD_MODE_BOX;
-
-       tx->command_ptr->src_dst_len = (MSM_UARTDM_BURST_SIZE << 16)
-                                          | (MSM_UARTDM_BURST_SIZE);
-
-       tx->command_ptr->row_offset = (MSM_UARTDM_BURST_SIZE << 16);
-
-       tx->command_ptr->dst_row_addr =
-           msm_uport->uport.mapbase + UARTDM_TF_ADDR;
-
-
-       /* Turn on Uart Receive */
-       rx->xfer.complete_func = msm_hs_dmov_rx_callback;
-       rx->xfer.execute_func = NULL;
-
-       rx->command_ptr->cmd = CMD_LC |
-           CMD_SRC_CRCI(msm_uport->dma_rx_crci) | CMD_MODE_BOX;
-
-       rx->command_ptr->src_dst_len = (MSM_UARTDM_BURST_SIZE << 16)
-                                          | (MSM_UARTDM_BURST_SIZE);
-       rx->command_ptr->row_offset =  MSM_UARTDM_BURST_SIZE;
-       rx->command_ptr->src_row_addr = uport->mapbase + UARTDM_RF_ADDR;
-
-
-       msm_uport->imr_reg |= UARTDM_ISR_RXSTALE_BMSK;
-       /* Enable reading the current CTS, no harm even if CTS is ignored */
-       msm_uport->imr_reg |= UARTDM_ISR_CURRENT_CTS_BMSK;
-
-       msm_hs_write(uport, UARTDM_TFWR_ADDR, 0);  /* TXLEV on empty TX fifo */
-
-
-       ret = request_irq(uport->irq, msm_hs_isr, IRQF_TRIGGER_HIGH,
-                         "msm_hs_uart", msm_uport);
-       if (unlikely(ret)) {
-               printk(KERN_ERR "Request msm_hs_uart IRQ failed!\n");
-               goto err_request_irq;
-       }
-       if (use_low_power_rx_wakeup(msm_uport)) {
-               ret = request_irq(msm_uport->rx_wakeup.irq,
-                                 msm_hs_rx_wakeup_isr,
-                                 IRQF_TRIGGER_FALLING,
-                                 "msm_hs_rx_wakeup", msm_uport);
-               if (unlikely(ret)) {
-                       printk(KERN_ERR "Request msm_hs_rx_wakeup IRQ failed!\n");
-                       free_irq(uport->irq, msm_uport);
-                       goto err_request_irq;
-               }
-               disable_irq(msm_uport->rx_wakeup.irq);
-       }
-
-       spin_lock_irqsave(&uport->lock, flags);
-
-       msm_hs_write(uport, UARTDM_RFWR_ADDR, 0);
-       msm_hs_start_rx_locked(uport);
-
-       spin_unlock_irqrestore(&uport->lock, flags);
-       ret = pm_runtime_set_active(uport->dev);
-       if (ret)
-               dev_err(uport->dev, "set active error:%d\n", ret);
-       pm_runtime_enable(uport->dev);
-
-       return 0;
-
-err_request_irq:
-err_msm_hs_init_clk:
-       dma_unmap_single(uport->dev, tx->dma_base,
-                               UART_XMIT_SIZE, DMA_TO_DEVICE);
-       return ret;
-}
-
-/* Initialize tx and rx data structures */
-static int uartdm_init_port(struct uart_port *uport)
-{
-       int ret = 0;
-       struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
-       struct msm_hs_tx *tx = &msm_uport->tx;
-       struct msm_hs_rx *rx = &msm_uport->rx;
-
-       /* Allocate the command pointer. Needs to be 64 bit aligned */
-       tx->command_ptr = kmalloc(sizeof(dmov_box), GFP_KERNEL | __GFP_DMA);
-       if (!tx->command_ptr)
-               return -ENOMEM;
-
-       tx->command_ptr_ptr = kmalloc(sizeof(u32), GFP_KERNEL | __GFP_DMA);
-       if (!tx->command_ptr_ptr) {
-               ret = -ENOMEM;
-               goto err_tx_command_ptr_ptr;
-       }
-
-       tx->mapped_cmd_ptr = dma_map_single(uport->dev, tx->command_ptr,
-                                           sizeof(dmov_box), DMA_TO_DEVICE);
-       tx->mapped_cmd_ptr_ptr = dma_map_single(uport->dev,
-                                               tx->command_ptr_ptr,
-                                               sizeof(u32), DMA_TO_DEVICE);
-       tx->xfer.cmdptr = DMOV_CMD_ADDR(tx->mapped_cmd_ptr_ptr);
-
-       init_waitqueue_head(&rx->wait);
-
-       rx->pool = dma_pool_create("rx_buffer_pool", uport->dev,
-                                  UARTDM_RX_BUF_SIZE, 16, 0);
-       if (!rx->pool) {
-               pr_err("%s(): cannot allocate rx_buffer_pool", __func__);
-               ret = -ENOMEM;
-               goto err_dma_pool_create;
-       }
-
-       rx->buffer = dma_pool_alloc(rx->pool, GFP_KERNEL, &rx->rbuffer);
-       if (!rx->buffer) {
-               pr_err("%s(): cannot allocate rx->buffer", __func__);
-               ret = -ENOMEM;
-               goto err_dma_pool_alloc;
-       }
-
-       /* Allocate the command pointer. Needs to be 64 bit aligned */
-       rx->command_ptr = kmalloc(sizeof(dmov_box), GFP_KERNEL | __GFP_DMA);
-       if (!rx->command_ptr) {
-               pr_err("%s(): cannot allocate rx->command_ptr", __func__);
-               ret = -ENOMEM;
-               goto err_rx_command_ptr;
-       }
-
-       rx->command_ptr_ptr = kmalloc(sizeof(u32), GFP_KERNEL | __GFP_DMA);
-       if (!rx->command_ptr_ptr) {
-               pr_err("%s(): cannot allocate rx->command_ptr_ptr", __func__);
-               ret = -ENOMEM;
-               goto err_rx_command_ptr_ptr;
-       }
-
-       rx->command_ptr->num_rows = ((UARTDM_RX_BUF_SIZE >> 4) << 16) |
-                                        (UARTDM_RX_BUF_SIZE >> 4);
-
-       rx->command_ptr->dst_row_addr = rx->rbuffer;
-
-       rx->mapped_cmd_ptr = dma_map_single(uport->dev, rx->command_ptr,
-                                           sizeof(dmov_box), DMA_TO_DEVICE);
-
-       *rx->command_ptr_ptr = CMD_PTR_LP | DMOV_CMD_ADDR(rx->mapped_cmd_ptr);
-
-       rx->cmdptr_dmaaddr = dma_map_single(uport->dev, rx->command_ptr_ptr,
-                                           sizeof(u32), DMA_TO_DEVICE);
-       rx->xfer.cmdptr = DMOV_CMD_ADDR(rx->cmdptr_dmaaddr);
-
-       INIT_WORK(&rx->tty_work, msm_hs_tty_flip_buffer_work);
-
-       return ret;
-
-err_rx_command_ptr_ptr:
-       kfree(rx->command_ptr);
-err_rx_command_ptr:
-       dma_pool_free(msm_uport->rx.pool, msm_uport->rx.buffer,
-                                               msm_uport->rx.rbuffer);
-err_dma_pool_alloc:
-       dma_pool_destroy(msm_uport->rx.pool);
-err_dma_pool_create:
-       dma_unmap_single(uport->dev, msm_uport->tx.mapped_cmd_ptr_ptr,
-                               sizeof(u32), DMA_TO_DEVICE);
-       dma_unmap_single(uport->dev, msm_uport->tx.mapped_cmd_ptr,
-                               sizeof(dmov_box), DMA_TO_DEVICE);
-       kfree(msm_uport->tx.command_ptr_ptr);
-err_tx_command_ptr_ptr:
-       kfree(msm_uport->tx.command_ptr);
-       return ret;
-}
-
-static int msm_hs_probe(struct platform_device *pdev)
-{
-       int ret;
-       struct uart_port *uport;
-       struct msm_hs_port *msm_uport;
-       struct resource *resource;
-       const struct msm_serial_hs_platform_data *pdata =
-                                               dev_get_platdata(&pdev->dev);
-
-       if (pdev->id < 0 || pdev->id >= UARTDM_NR) {
-               printk(KERN_ERR "Invalid plaform device ID = %d\n", pdev->id);
-               return -EINVAL;
-       }
-
-       msm_uport = &q_uart_port[pdev->id];
-       uport = &msm_uport->uport;
-
-       uport->dev = &pdev->dev;
-
-       resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (unlikely(!resource))
-               return -ENXIO;
-
-       uport->mapbase = resource->start;
-       uport->irq = platform_get_irq(pdev, 0);
-       if (unlikely(uport->irq < 0))
-               return -ENXIO;
-
-       if (unlikely(irq_set_irq_wake(uport->irq, 1)))
-               return -ENXIO;
-
-       if (pdata == NULL || pdata->rx_wakeup_irq < 0)
-               msm_uport->rx_wakeup.irq = -1;
-       else {
-               msm_uport->rx_wakeup.irq = pdata->rx_wakeup_irq;
-               msm_uport->rx_wakeup.ignore = 1;
-               msm_uport->rx_wakeup.inject_rx = pdata->inject_rx_on_wakeup;
-               msm_uport->rx_wakeup.rx_to_inject = pdata->rx_to_inject;
-
-               if (unlikely(msm_uport->rx_wakeup.irq < 0))
-                       return -ENXIO;
-
-               if (unlikely(irq_set_irq_wake(msm_uport->rx_wakeup.irq, 1)))
-                       return -ENXIO;
-       }
-
-       if (pdata == NULL)
-               msm_uport->exit_lpm_cb = NULL;
-       else
-               msm_uport->exit_lpm_cb = pdata->exit_lpm_cb;
-
-       resource = platform_get_resource_byname(pdev, IORESOURCE_DMA,
-                                               "uartdm_channels");
-       if (unlikely(!resource))
-               return -ENXIO;
-
-       msm_uport->dma_tx_channel = resource->start;
-       msm_uport->dma_rx_channel = resource->end;
-
-       resource = platform_get_resource_byname(pdev, IORESOURCE_DMA,
-                                               "uartdm_crci");
-       if (unlikely(!resource))
-               return -ENXIO;
-
-       msm_uport->dma_tx_crci = resource->start;
-       msm_uport->dma_rx_crci = resource->end;
-
-       uport->iotype = UPIO_MEM;
-       uport->fifosize = UART_FIFOSIZE;
-       uport->ops = &msm_hs_ops;
-       uport->flags = UPF_BOOT_AUTOCONF;
-       uport->uartclk = UARTCLK;
-       msm_uport->imr_reg = 0x0;
-       msm_uport->clk = clk_get(&pdev->dev, "uartdm_clk");
-       if (IS_ERR(msm_uport->clk))
-               return PTR_ERR(msm_uport->clk);
-
-       ret = uartdm_init_port(uport);
-       if (unlikely(ret))
-               return ret;
-
-       msm_uport->clk_state = MSM_HS_CLK_PORT_OFF;
-       hrtimer_init(&msm_uport->clk_off_timer, CLOCK_MONOTONIC,
-                    HRTIMER_MODE_REL);
-       msm_uport->clk_off_timer.function = msm_hs_clk_off_retry;
-       msm_uport->clk_off_delay = ktime_set(0, 1000000);  /* 1ms */
-
-       uport->line = pdev->id;
-       return uart_add_one_port(&msm_hs_driver, uport);
-}
-
-static int __init msm_serial_hs_init(void)
-{
-       int ret, i;
-
-       /* Init all UARTS as non-configured */
-       for (i = 0; i < UARTDM_NR; i++)
-               q_uart_port[i].uport.type = PORT_UNKNOWN;
-
-       msm_hs_workqueue = create_singlethread_workqueue("msm_serial_hs");
-       if (unlikely(!msm_hs_workqueue))
-               return -ENOMEM;
-
-       ret = uart_register_driver(&msm_hs_driver);
-       if (unlikely(ret)) {
-               printk(KERN_ERR "%s failed to load\n", __func__);
-               goto err_uart_register_driver;
-       }
-
-       ret = platform_driver_register(&msm_serial_hs_platform_driver);
-       if (ret) {
-               printk(KERN_ERR "%s failed to load\n", __func__);
-               goto err_platform_driver_register;
-       }
-
-       return ret;
-
-err_platform_driver_register:
-       uart_unregister_driver(&msm_hs_driver);
-err_uart_register_driver:
-       destroy_workqueue(msm_hs_workqueue);
-       return ret;
-}
-module_init(msm_serial_hs_init);
-
-/*
- *  Called by the upper layer when port is closed.
- *     - Disables the port
- *     - Unhook the ISR
- */
-static void msm_hs_shutdown(struct uart_port *uport)
-{
-       unsigned long flags;
-       struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
-
-       BUG_ON(msm_uport->rx.flush < FLUSH_STOP);
-
-       spin_lock_irqsave(&uport->lock, flags);
-       clk_enable(msm_uport->clk);
-
-       /* Disable the transmitter */
-       msm_hs_write(uport, UARTDM_CR_ADDR, UARTDM_CR_TX_DISABLE_BMSK);
-       /* Disable the receiver */
-       msm_hs_write(uport, UARTDM_CR_ADDR, UARTDM_CR_RX_DISABLE_BMSK);
-
-       pm_runtime_disable(uport->dev);
-       pm_runtime_set_suspended(uport->dev);
-
-       /* Free the interrupt */
-       free_irq(uport->irq, msm_uport);
-       if (use_low_power_rx_wakeup(msm_uport))
-               free_irq(msm_uport->rx_wakeup.irq, msm_uport);
-
-       msm_uport->imr_reg = 0;
-       msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
-
-       wait_event(msm_uport->rx.wait, msm_uport->rx.flush == FLUSH_SHUTDOWN);
-
-       clk_disable(msm_uport->clk);  /* to balance local clk_enable() */
-       if (msm_uport->clk_state != MSM_HS_CLK_OFF)
-               clk_disable(msm_uport->clk);  /* to balance clk_state */
-       msm_uport->clk_state = MSM_HS_CLK_PORT_OFF;
-
-       dma_unmap_single(uport->dev, msm_uport->tx.dma_base,
-                        UART_XMIT_SIZE, DMA_TO_DEVICE);
-
-       spin_unlock_irqrestore(&uport->lock, flags);
-
-       if (cancel_work_sync(&msm_uport->rx.tty_work))
-               msm_hs_tty_flip_buffer_work(&msm_uport->rx.tty_work);
-}
-
-static void __exit msm_serial_hs_exit(void)
-{
-       flush_workqueue(msm_hs_workqueue);
-       destroy_workqueue(msm_hs_workqueue);
-       platform_driver_unregister(&msm_serial_hs_platform_driver);
-       uart_unregister_driver(&msm_hs_driver);
-}
-module_exit(msm_serial_hs_exit);
-
-#ifdef CONFIG_PM
-static int msm_hs_runtime_idle(struct device *dev)
-{
-       /*
-        * returning success from idle results in runtime suspend to be
-        * called
-        */
-       return 0;
-}
-
-static int msm_hs_runtime_resume(struct device *dev)
-{
-       struct platform_device *pdev = container_of(dev, struct
-                                                   platform_device, dev);
-       struct msm_hs_port *msm_uport = &q_uart_port[pdev->id];
-
-       msm_hs_request_clock_on(&msm_uport->uport);
-       return 0;
-}
-
-static int msm_hs_runtime_suspend(struct device *dev)
-{
-       struct platform_device *pdev = container_of(dev, struct
-                                                   platform_device, dev);
-       struct msm_hs_port *msm_uport = &q_uart_port[pdev->id];
-
-       msm_hs_request_clock_off(&msm_uport->uport);
-       return 0;
-}
-#else
-#define msm_hs_runtime_idle NULL
-#define msm_hs_runtime_resume NULL
-#define msm_hs_runtime_suspend NULL
-#endif
-
-static const struct dev_pm_ops msm_hs_dev_pm_ops = {
-       .runtime_suspend = msm_hs_runtime_suspend,
-       .runtime_resume  = msm_hs_runtime_resume,
-       .runtime_idle    = msm_hs_runtime_idle,
-};
-
-static struct platform_driver msm_serial_hs_platform_driver = {
-       .probe = msm_hs_probe,
-       .remove = msm_hs_remove,
-       .driver = {
-               .name = "msm_serial_hs",
-               .pm   = &msm_hs_dev_pm_ops,
-       },
-};
-
-static struct uart_driver msm_hs_driver = {
-       .owner = THIS_MODULE,
-       .driver_name = "msm_serial_hs",
-       .dev_name = "ttyHS",
-       .nr = UARTDM_NR,
-       .cons = 0,
-};
-
-static struct uart_ops msm_hs_ops = {
-       .tx_empty = msm_hs_tx_empty,
-       .set_mctrl = msm_hs_set_mctrl_locked,
-       .get_mctrl = msm_hs_get_mctrl_locked,
-       .stop_tx = msm_hs_stop_tx_locked,
-       .start_tx = msm_hs_start_tx_locked,
-       .stop_rx = msm_hs_stop_rx_locked,
-       .enable_ms = msm_hs_enable_ms_locked,
-       .break_ctl = msm_hs_break_ctl,
-       .startup = msm_hs_startup,
-       .shutdown = msm_hs_shutdown,
-       .set_termios = msm_hs_set_termios,
-       .pm = msm_hs_pm,
-       .type = msm_hs_type,
-       .config_port = msm_hs_config_port,
-       .release_port = msm_hs_release_port,
-       .request_port = msm_hs_request_port,
-};
-
-MODULE_DESCRIPTION("High Speed UART Driver for the MSM chipset");
-MODULE_VERSION("1.2");
-MODULE_LICENSE("GPL v2");
index d1298b6cc68e4e6f1f610959f57f94cf350650fd..f7e5825b55ab32f339ee7e7d4d430cc3468cb571 100644 (file)
@@ -176,7 +176,7 @@ static struct platform_device_id mxs_auart_devtype[] = {
 };
 MODULE_DEVICE_TABLE(platform, mxs_auart_devtype);
 
-static struct of_device_id mxs_auart_dt_ids[] = {
+static const struct of_device_id mxs_auart_dt_ids[] = {
        {
                .compatible = "fsl,imx28-auart",
                .data = &mxs_auart_devtype[IMX28_AUART]
@@ -1155,14 +1155,14 @@ static int serial_mxs_probe_dt(struct mxs_auart_port *s,
        return 0;
 }
 
-static bool mxs_auart_init_gpios(struct mxs_auart_port *s, struct device *dev)
+static int mxs_auart_init_gpios(struct mxs_auart_port *s, struct device *dev)
 {
        enum mctrl_gpio_idx i;
        struct gpio_desc *gpiod;
 
        s->gpios = mctrl_gpio_init(dev, 0);
-       if (IS_ERR_OR_NULL(s->gpios))
-               return false;
+       if (IS_ERR(s->gpios))
+               return PTR_ERR(s->gpios);
 
        /* Block (enabled before) DMA option if RTS or CTS is GPIO line */
        if (!RTS_AT_AUART() || !CTS_AT_AUART()) {
@@ -1180,7 +1180,7 @@ static bool mxs_auart_init_gpios(struct mxs_auart_port *s, struct device *dev)
                        s->gpio_irq[i] = -EINVAL;
        }
 
-       return true;
+       return 0;
 }
 
 static void mxs_auart_free_gpio_irq(struct mxs_auart_port *s)
@@ -1276,9 +1276,11 @@ static int mxs_auart_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, s);
 
-       if (!mxs_auart_init_gpios(s, &pdev->dev))
-               dev_err(&pdev->dev,
-                       "Failed to initialize GPIOs. The serial port may not work as expected\n");
+       ret = mxs_auart_init_gpios(s, &pdev->dev);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to initialize GPIOs.\n");
+               return ret;
+       }
 
        /*
         * Get the GPIO lines IRQ
index 33fb94f7896773c53141ec283f15a3a18be96f1a..137381e649e5bec1c2ac5bf616bc9da6e813772a 100644 (file)
@@ -89,6 +89,7 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
 
        spin_lock_init(&port->lock);
        port->mapbase = resource.start;
+       port->mapsize = resource_size(&resource);
 
        /* Check for shifted address mapping */
        if (of_property_read_u32(np, "reg-offset", &prop) == 0)
@@ -115,7 +116,8 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
                        port->iotype = UPIO_MEM;
                        break;
                case 4:
-                       port->iotype = UPIO_MEM32;
+                       port->iotype = of_device_is_big_endian(np) ?
+                                      UPIO_MEM32BE : UPIO_MEM32;
                        break;
                default:
                        dev_warn(&ofdev->dev, "unsupported reg-io-width (%d)\n",
@@ -155,7 +157,7 @@ out:
 /*
  * Try to register a serial port
  */
-static struct of_device_id of_platform_serial_table[];
+static const struct of_device_id of_platform_serial_table[];
 static int of_platform_serial_probe(struct platform_device *ofdev)
 {
        const struct of_device_id *match;
@@ -320,7 +322,7 @@ static SIMPLE_DEV_PM_OPS(of_serial_pm_ops, of_serial_suspend, of_serial_resume);
 /*
  * A few common types, add more as needed.
  */
-static struct of_device_id of_platform_serial_table[] = {
+static const struct of_device_id of_platform_serial_table[] = {
        { .compatible = "ns8250",   .data = (void *)PORT_8250, },
        { .compatible = "ns16450",  .data = (void *)PORT_16450, },
        { .compatible = "ns16550a", .data = (void *)PORT_16550A, },
@@ -344,7 +346,6 @@ static struct of_device_id of_platform_serial_table[] = {
        { .compatible = "ibm,qpace-nwp-serial",
                .data = (void *)PORT_NWPSERIAL, },
 #endif
-       { .type = "serial",         .data = (void *)PORT_UNKNOWN, },
        { /* end of list */ },
 };
 
index 10256fa04b40abf0bd07f6ed5b8d5d721df1eb3f..211479aa34bb20d5375078afb103829faa5bfd84 100644 (file)
@@ -1654,11 +1654,6 @@ static int serial_omap_probe(struct platform_device *pdev)
        up->port.type = PORT_OMAP;
        up->port.iotype = UPIO_MEM;
        up->port.irq = uartirq;
-       up->wakeirq = wakeirq;
-       if (!up->wakeirq)
-               dev_info(up->port.dev, "no wakeirq for uart%d\n",
-                        up->port.line);
-
        up->port.regshift = 2;
        up->port.fifosize = 64;
        up->port.ops = &serial_omap_pops;
@@ -1682,6 +1677,11 @@ static int serial_omap_probe(struct platform_device *pdev)
                goto err_port_line;
        }
 
+       up->wakeirq = wakeirq;
+       if (!up->wakeirq)
+               dev_info(up->port.dev, "no wakeirq for uart%d\n",
+                        up->port.line);
+
        ret = serial_omap_probe_rs485(up, pdev->dev.of_node);
        if (ret < 0)
                goto err_rs485;
index 8f515799c9c10a27add45b156425bf98ae920deb..e156e39d620cebd2ee48304ed80223fd7c96a2c2 100644 (file)
@@ -1846,7 +1846,7 @@ static int __init pmz_register(void)
 
 #ifdef CONFIG_PPC_PMAC
 
-static struct of_device_id pmz_match[] = 
+static const struct of_device_id pmz_match[] =
 {
        {
        .name           = "ch-a",
index d5d062694bd399e8d82e9811a9667f3b439e372f..9becba6548921116adae390af002290cb31e883a 100644 (file)
@@ -824,7 +824,7 @@ static const struct dev_pm_ops serial_pxa_pm_ops = {
 };
 #endif
 
-static struct of_device_id serial_pxa_dt_ids[] = {
+static const struct of_device_id serial_pxa_dt_ids[] = {
        { .compatible = "mrvl,pxa-uart", },
        { .compatible = "mrvl,mmp-uart", },
        {}
index cf08876922f1446e55a2d8ca79bf87e0d4e24fed..a0ae942d9562d818c3e35a30c71d1bd1cb12e426 100644 (file)
@@ -1068,8 +1068,9 @@ static int s3c64xx_serial_startup(struct uart_port *port)
        spin_lock_irqsave(&port->lock, flags);
 
        ufcon = rd_regl(port, S3C2410_UFCON);
-       ufcon |= S3C2410_UFCON_RESETRX | S3C2410_UFCON_RESETTX |
-                       S5PV210_UFCON_RXTRIG8;
+       ufcon |= S3C2410_UFCON_RESETRX | S5PV210_UFCON_RXTRIG8;
+       if (!uart_console(port))
+               ufcon |= S3C2410_UFCON_RESETTX;
        wr_regl(port, S3C2410_UFCON, ufcon);
 
        enable_rx_pio(ourport);
index df9a384dfbdaab9a6d953b1c36a50ba0c30989ae..468354ef7baa2f8f9fb160e4b0ef06e407c6e270 100644 (file)
@@ -829,16 +829,32 @@ static void sc16is7xx_set_termios(struct uart_port *port,
 }
 
 static int sc16is7xx_config_rs485(struct uart_port *port,
-                                  struct serial_rs485 *rs485)
+                                 struct serial_rs485 *rs485)
 {
-       if (port->rs485.flags & SER_RS485_ENABLED)
-               sc16is7xx_port_update(port, SC16IS7XX_EFCR_REG,
-                                     SC16IS7XX_EFCR_AUTO_RS485_BIT,
-                                     SC16IS7XX_EFCR_AUTO_RS485_BIT);
-       else
-               sc16is7xx_port_update(port, SC16IS7XX_EFCR_REG,
-                                     SC16IS7XX_EFCR_AUTO_RS485_BIT,
-                                     0);
+       const u32 mask = SC16IS7XX_EFCR_AUTO_RS485_BIT |
+                        SC16IS7XX_EFCR_RTS_INVERT_BIT;
+       u32 efcr = 0;
+
+       if (rs485->flags & SER_RS485_ENABLED) {
+               bool rts_during_rx, rts_during_tx;
+
+               rts_during_rx = rs485->flags & SER_RS485_RTS_AFTER_SEND;
+               rts_during_tx = rs485->flags & SER_RS485_RTS_ON_SEND;
+
+               efcr |= SC16IS7XX_EFCR_AUTO_RS485_BIT;
+
+               if (!rts_during_rx && rts_during_tx)
+                       /* default */;
+               else if (rts_during_rx && !rts_during_tx)
+                       efcr |= SC16IS7XX_EFCR_RTS_INVERT_BIT;
+               else
+                       dev_err(port->dev,
+                               "unsupported RTS signalling on_send:%d after_send:%d - exactly one of RS485 RTS flags should be set\n",
+                               rts_during_tx, rts_during_rx);
+       }
+
+       sc16is7xx_port_update(port, SC16IS7XX_EFCR_REG, mask, efcr);
+
        port->rs485 = *rs485;
 
        return 0;
@@ -903,9 +919,11 @@ static void sc16is7xx_shutdown(struct uart_port *port)
        /* Disable all interrupts */
        sc16is7xx_port_write(port, SC16IS7XX_IER_REG, 0);
        /* Disable TX/RX */
-       sc16is7xx_port_write(port, SC16IS7XX_EFCR_REG,
-                            SC16IS7XX_EFCR_RXDISABLE_BIT |
-                            SC16IS7XX_EFCR_TXDISABLE_BIT);
+       sc16is7xx_port_update(port, SC16IS7XX_EFCR_REG,
+                             SC16IS7XX_EFCR_RXDISABLE_BIT |
+                             SC16IS7XX_EFCR_TXDISABLE_BIT,
+                             SC16IS7XX_EFCR_RXDISABLE_BIT |
+                             SC16IS7XX_EFCR_TXDISABLE_BIT);
 
        sc16is7xx_power(port, 0);
 }
@@ -1048,6 +1066,7 @@ static int sc16is7xx_probe(struct device *dev,
                else
                        return PTR_ERR(s->clk);
        } else {
+               clk_prepare_enable(s->clk);
                freq = clk_get_rate(s->clk);
        }
 
@@ -1120,6 +1139,9 @@ static int sc16is7xx_probe(struct device *dev,
        if (!ret)
                return 0;
 
+       for (i = 0; i < s->uart.nr; i++)
+               uart_remove_one_port(&s->uart, &s->p[i].port);
+
        mutex_destroy(&s->mutex);
 
 #ifdef CONFIG_GPIOLIB
index 48e6e41636b2040c9a02a3f610d6d4610ae13fe3..1d5ea3964ee59d61d882ad23e35f63e367e86af5 100644 (file)
@@ -1251,7 +1251,7 @@ static struct tegra_uart_chip_data tegra30_uart_chip_data = {
        .support_clk_src_div            = true,
 };
 
-static struct of_device_id tegra_uart_of_match[] = {
+static const struct of_device_id tegra_uart_of_match[] = {
        {
                .compatible     = "nvidia,tegra30-hsuart",
                .data           = &tegra30_uart_chip_data,
index 6a1055ae343727e964cbb6af44909b42cd526afb..0b7bb12dfc68bc7edc45f7274a4e75acb9238a59 100644 (file)
@@ -1118,8 +1118,7 @@ uart_wait_modem_status(struct uart_state *state, unsigned long arg)
 
                cprev = cnow;
        }
-
-       current->state = TASK_RUNNING;
+       __set_current_state(TASK_RUNNING);
        remove_wait_queue(&port->delta_msr_wait, &wait);
 
        return ret;
@@ -1766,12 +1765,12 @@ static const struct file_operations uart_proc_fops = {
 #endif
 
 #if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(CONFIG_CONSOLE_POLL)
-/*
+/**
  *     uart_console_write - write a console message to a serial port
  *     @port: the port to write the message
  *     @s: array of characters
  *     @count: number of characters in string to write
- *     @write: function to write character to port
+ *     @putchar: function to write character to port
  */
 void uart_console_write(struct uart_port *port, const char *s,
                        unsigned int count,
@@ -1809,6 +1808,52 @@ uart_get_console(struct uart_port *ports, int nr, struct console *co)
        return ports + idx;
 }
 
+/**
+ *     uart_parse_earlycon - Parse earlycon options
+ *     @p:       ptr to 2nd field (ie., just beyond '<name>,')
+ *     @iotype:  ptr for decoded iotype (out)
+ *     @addr:    ptr for decoded mapbase/iobase (out)
+ *     @options: ptr for <options> field; NULL if not present (out)
+ *
+ *     Decodes earlycon kernel command line parameters of the form
+ *        earlycon=<name>,io|mmio|mmio32,<addr>,<options>
+ *        console=<name>,io|mmio|mmio32,<addr>,<options>
+ *
+ *     The optional form
+ *        earlycon=<name>,0x<addr>,<options>
+ *        console=<name>,0x<addr>,<options>
+ *     is also accepted; the returned @iotype will be UPIO_MEM.
+ *
+ *     Returns 0 on success or -EINVAL on failure
+ */
+int uart_parse_earlycon(char *p, unsigned char *iotype, unsigned long *addr,
+                       char **options)
+{
+       if (strncmp(p, "mmio,", 5) == 0) {
+               *iotype = UPIO_MEM;
+               p += 5;
+       } else if (strncmp(p, "mmio32,", 7) == 0) {
+               *iotype = UPIO_MEM32;
+               p += 7;
+       } else if (strncmp(p, "io,", 3) == 0) {
+               *iotype = UPIO_PORT;
+               p += 3;
+       } else if (strncmp(p, "0x", 2) == 0) {
+               *iotype = UPIO_MEM;
+       } else {
+               return -EINVAL;
+       }
+
+       *addr = simple_strtoul(p, NULL, 0);
+       p = strchr(p, ',');
+       if (p)
+               p++;
+
+       *options = p;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(uart_parse_earlycon);
+
 /**
  *     uart_parse_options - Parse serial port baud/parity/bits/flow control.
  *     @options: pointer to option string
@@ -2637,6 +2682,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
 
        state->pm_state = UART_PM_STATE_UNDEFINED;
        uport->cons = drv->cons;
+       uport->minor = drv->tty_driver->minor_start + uport->line;
 
        /*
         * If this port is a console, then the spinlock is already
index a38596c5194e4b6f6a1feb26183e4b9cd8366f2f..0ec756c62bcf1f859a7692c9cf2fe580cff8b56f 100644 (file)
@@ -48,9 +48,6 @@ void mctrl_gpio_set(struct mctrl_gpios *gpios, unsigned int mctrl)
        int value_array[UART_GPIO_MAX];
        unsigned int count = 0;
 
-       if (IS_ERR_OR_NULL(gpios))
-               return;
-
        for (i = 0; i < UART_GPIO_MAX; i++)
                if (!IS_ERR_OR_NULL(gpios->gpio[i]) &&
                    mctrl_gpios_desc[i].dir_out) {
@@ -65,10 +62,7 @@ EXPORT_SYMBOL_GPL(mctrl_gpio_set);
 struct gpio_desc *mctrl_gpio_to_gpiod(struct mctrl_gpios *gpios,
                                      enum mctrl_gpio_idx gidx)
 {
-       if (!IS_ERR_OR_NULL(gpios) && !IS_ERR_OR_NULL(gpios->gpio[gidx]))
-               return gpios->gpio[gidx];
-       else
-               return NULL;
+       return gpios->gpio[gidx];
 }
 EXPORT_SYMBOL_GPL(mctrl_gpio_to_gpiod);
 
@@ -76,15 +70,8 @@ unsigned int mctrl_gpio_get(struct mctrl_gpios *gpios, unsigned int *mctrl)
 {
        enum mctrl_gpio_idx i;
 
-       /*
-        * return it unchanged if the structure is not allocated
-        */
-       if (IS_ERR_OR_NULL(gpios))
-               return *mctrl;
-
        for (i = 0; i < UART_GPIO_MAX; i++) {
-               if (!IS_ERR_OR_NULL(gpios->gpio[i]) &&
-                   !mctrl_gpios_desc[i].dir_out) {
+               if (gpios->gpio[i] && !mctrl_gpios_desc[i].dir_out) {
                        if (gpiod_get_value(gpios->gpio[i]))
                                *mctrl |= mctrl_gpios_desc[i].mctrl;
                        else
@@ -100,34 +87,26 @@ struct mctrl_gpios *mctrl_gpio_init(struct device *dev, unsigned int idx)
 {
        struct mctrl_gpios *gpios;
        enum mctrl_gpio_idx i;
-       int err;
 
        gpios = devm_kzalloc(dev, sizeof(*gpios), GFP_KERNEL);
        if (!gpios)
                return ERR_PTR(-ENOMEM);
 
        for (i = 0; i < UART_GPIO_MAX; i++) {
-               gpios->gpio[i] = devm_gpiod_get_index(dev,
-                                                     mctrl_gpios_desc[i].name,
-                                                     idx);
-
-               /*
-                * The GPIOs are maybe not all filled,
-                * this is not an error.
-                */
-               if (IS_ERR_OR_NULL(gpios->gpio[i]))
-                       continue;
+               enum gpiod_flags flags;
 
                if (mctrl_gpios_desc[i].dir_out)
-                       err = gpiod_direction_output(gpios->gpio[i], 0);
+                       flags = GPIOD_OUT_LOW;
                else
-                       err = gpiod_direction_input(gpios->gpio[i]);
-               if (err) {
-                       dev_dbg(dev, "Unable to set direction for %s GPIO",
-                               mctrl_gpios_desc[i].name);
-                       devm_gpiod_put(dev, gpios->gpio[i]);
-                       gpios->gpio[i] = NULL;
-               }
+                       flags = GPIOD_IN;
+
+               gpios->gpio[i] =
+                       devm_gpiod_get_index_optional(dev,
+                                                     mctrl_gpios_desc[i].name,
+                                                     idx, flags);
+
+               if (IS_ERR(gpios->gpio[i]))
+                       return ERR_CAST(gpios->gpio[i]);
        }
 
        return gpios;
@@ -138,9 +117,6 @@ void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios)
 {
        enum mctrl_gpio_idx i;
 
-       if (IS_ERR_OR_NULL(gpios))
-               return;
-
        for (i = 0; i < UART_GPIO_MAX; i++)
                if (!IS_ERR_OR_NULL(gpios->gpio[i]))
                        devm_gpiod_put(dev, gpios->gpio[i]);
index 5b50c792ad5fd00e72ef86ed95a196d20e9ae06c..e7d6566fafaf3da538788ef34260c6dd220dba5b 100644 (file)
@@ -844,14 +844,32 @@ static int sci_handle_fifo_overrun(struct uart_port *port)
        struct tty_port *tport = &port->state->port;
        struct sci_port *s = to_sci_port(port);
        struct plat_sci_reg *reg;
-       int copied = 0;
+       int copied = 0, offset;
+       u16 status, bit;
+
+       switch (port->type) {
+       case PORT_SCIF:
+       case PORT_HSCIF:
+               offset = SCLSR;
+               break;
+       case PORT_SCIFA:
+       case PORT_SCIFB:
+               offset = SCxSR;
+               break;
+       default:
+               return 0;
+       }
 
-       reg = sci_getreg(port, SCLSR);
+       reg = sci_getreg(port, offset);
        if (!reg->size)
                return 0;
 
-       if ((serial_port_in(port, SCLSR) & (1 << s->overrun_bit))) {
-               serial_port_out(port, SCLSR, 0);
+       status = serial_port_in(port, offset);
+       bit = 1 << s->overrun_bit;
+
+       if (status & bit) {
+               status &= ~bit;
+               serial_port_out(port, offset, status);
 
                port->icount.overrun++;
 
@@ -996,16 +1014,24 @@ static inline unsigned long port_rx_irq_mask(struct uart_port *port)
 
 static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
 {
-       unsigned short ssr_status, scr_status, err_enabled;
-       unsigned short slr_status = 0;
+       unsigned short ssr_status, scr_status, err_enabled, orer_status = 0;
        struct uart_port *port = ptr;
        struct sci_port *s = to_sci_port(port);
        irqreturn_t ret = IRQ_NONE;
 
        ssr_status = serial_port_in(port, SCxSR);
        scr_status = serial_port_in(port, SCSCR);
-       if (port->type == PORT_SCIF || port->type == PORT_HSCIF)
-               slr_status = serial_port_in(port, SCLSR);
+       switch (port->type) {
+       case PORT_SCIF:
+       case PORT_HSCIF:
+               orer_status = serial_port_in(port, SCLSR);
+               break;
+       case PORT_SCIFA:
+       case PORT_SCIFB:
+               orer_status = ssr_status;
+               break;
+       }
+
        err_enabled = scr_status & port_rx_irq_mask(port);
 
        /* Tx Interrupt */
@@ -1033,10 +1059,8 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
                ret = sci_br_interrupt(irq, ptr);
 
        /* Overrun Interrupt */
-       if (port->type == PORT_SCIF || port->type == PORT_HSCIF) {
-               if (slr_status & 0x01)
-                       sci_handle_fifo_overrun(port);
-       }
+       if (orer_status & (1 << s->overrun_bit))
+               sci_handle_fifo_overrun(port);
 
        return ret;
 }
@@ -1967,18 +1991,40 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 
 #ifdef CONFIG_SERIAL_SH_SCI_DMA
        /*
-        * Calculate delay for 1.5 DMA buffers: see
-        * drivers/serial/serial_core.c::uart_update_timeout(). With 10 bits
-        * (CS8), 250Hz, 115200 baud and 64 bytes FIFO, the above function
+        * Calculate delay for 2 DMA buffers (4 FIFO).
+        * See drivers/serial/serial_core.c::uart_update_timeout(). With 10
+        * bits (CS8), 250Hz, 115200 baud and 64 bytes FIFO, the above function
         * calculates 1 jiffie for the data plus 5 jiffies for the "slop(e)."
-        * Then below we calculate 3 jiffies (12ms) for 1.5 DMA buffers (3 FIFO
-        * sizes), but it has been found out experimentally, that this is not
-        * enough: the driver too often needlessly runs on a DMA timeout. 20ms
-        * as a minimum seem to work perfectly.
+        * Then below we calculate 5 jiffies (20ms) for 2 DMA buffers (4 FIFO
+        * sizes), but when performing a faster transfer, value obtained by
+        * this formula is may not enough. Therefore, if value is smaller than
+        * 20msec, this sets 20msec as timeout of DMA.
         */
        if (s->chan_rx) {
-               s->rx_timeout = (port->timeout - HZ / 50) * s->buf_len_rx * 3 /
-                       port->fifosize / 2;
+               unsigned int bits;
+
+               /* byte size and parity */
+               switch (termios->c_cflag & CSIZE) {
+               case CS5:
+                       bits = 7;
+                       break;
+               case CS6:
+                       bits = 8;
+                       break;
+               case CS7:
+                       bits = 9;
+                       break;
+               default:
+                       bits = 10;
+                       break;
+               }
+
+               if (termios->c_cflag & CSTOPB)
+                       bits++;
+               if (termios->c_cflag & PARENB)
+                       bits++;
+               s->rx_timeout = DIV_ROUND_UP((s->buf_len_rx * 2 * bits * HZ) /
+                                            (baud / 10), 10);
                dev_dbg(port->dev, "DMA Rx t-out %ums, tty t-out %u jiffies\n",
                        s->rx_timeout * 1000 / HZ, port->timeout);
                if (s->rx_timeout < msecs_to_jiffies(20))
index 27ed0e960880990c810fe4190e28f03dd455db4f..9de3eabe57372c49322e45034c99a3de99b59ae9 100644 (file)
@@ -1269,7 +1269,7 @@ static struct uart_driver sirfsoc_uart_drv = {
 #endif
 };
 
-static struct of_device_id sirfsoc_uart_ids[] = {
+static const struct of_device_id sirfsoc_uart_ids[] = {
        { .compatible = "sirf,prima2-uart", .data = &sirfsoc_uart,},
        { .compatible = "sirf,atlas7-uart", .data = &sirfsoc_uart},
        { .compatible = "sirf,prima2-usp-uart", .data = &sirfsoc_usp},
index bca975f5093b73fd5ebf3e0f4ec8c42e97dfea35..582d2729f7008078064da5ddec8bc456b5102003 100644 (file)
@@ -493,6 +493,8 @@ static int sprd_verify_port(struct uart_port *port,
                return -EINVAL;
        if (port->irq != ser->irq)
                return -EINVAL;
+       if (port->iotype != ser->io_type)
+               return -EINVAL;
        return 0;
 }
 
@@ -707,7 +709,7 @@ static int sprd_probe(struct platform_device *pdev)
        up->dev = &pdev->dev;
        up->line = index;
        up->type = PORT_SPRD;
-       up->iotype = SERIAL_IO_PORT;
+       up->iotype = UPIO_MEM;
        up->uartclk = SPRD_DEF_RATE;
        up->fifosize = SPRD_FIFO_SIZE;
        up->ops = &serial_sprd_ops;
@@ -754,6 +756,7 @@ static int sprd_probe(struct platform_device *pdev)
        return ret;
 }
 
+#ifdef CONFIG_PM_SLEEP
 static int sprd_suspend(struct device *dev)
 {
        struct sprd_uart_port *sup = dev_get_drvdata(dev);
@@ -771,6 +774,7 @@ static int sprd_resume(struct device *dev)
 
        return 0;
 }
+#endif
 
 static SIMPLE_DEV_PM_OPS(sprd_pm_ops, sprd_suspend, sprd_resume);
 
index 712b03a076b8c1ca5ee9e2bdfad3752eccdd7155..d625664ce1b51eea836775d800eded58140fb5ee 100644 (file)
@@ -720,7 +720,7 @@ static struct asc_port *asc_of_get_asc_port(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_OF
-static struct of_device_id asc_match[] = {
+static const struct of_device_id asc_match[] = {
        { .compatible = "st,asc", },
        {},
 };
index 189f52e3111ff71feef99741f1ad52e680c42f4b..b1c6bd3d483fa87a0372928ebd59cbdf9173d17d 100644 (file)
@@ -622,7 +622,7 @@ static int ulite_release(struct device *dev)
 
 #if defined(CONFIG_OF)
 /* Match table for of_platform binding */
-static struct of_device_id ulite_of_match[] = {
+static const struct of_device_id ulite_of_match[] = {
        { .compatible = "xlnx,opb-uartlite-1.00.b", },
        { .compatible = "xlnx,xps-uartlite-1.00.a", },
        {}
@@ -632,7 +632,8 @@ MODULE_DEVICE_TABLE(of, ulite_of_match);
 
 static int ulite_probe(struct platform_device *pdev)
 {
-       struct resource *res, *res2;
+       struct resource *res;
+       int irq;
        int id = pdev->id;
 #ifdef CONFIG_OF
        const __be32 *prop;
@@ -646,11 +647,11 @@ static int ulite_probe(struct platform_device *pdev)
        if (!res)
                return -ENODEV;
 
-       res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (!res2)
-               return -ENODEV;
+       irq = platform_get_irq(pdev, 0);
+       if (irq <= 0)
+               return -ENXIO;
 
-       return ulite_assign(&pdev->dev, id, res->start, res2->start);
+       return ulite_assign(&pdev->dev, id, res->start, irq);
 }
 
 static int ulite_remove(struct platform_device *pdev)
index 14d10fcfd21052798e73a2ee5746b2ff347d1bbb..7d2532b23969e738cc63f9c952ff737a18b2abea 100644 (file)
@@ -1473,7 +1473,7 @@ static int ucc_uart_remove(struct platform_device *ofdev)
        return 0;
 }
 
-static struct of_device_id ucc_uart_match[] = {
+static const struct of_device_id ucc_uart_match[] = {
        {
                .type = "serial",
                .compatible = "ucc_uart",
index cff531a51a783f8501bae180fd5788ce45a00c34..3ddbac767db3c43e3f5e3afd1e5dd482af86f88a 100644 (file)
 #define CDNS_UART_MINOR                0       /* works best with devtmpfs */
 #define CDNS_UART_NR_PORTS     2
 #define CDNS_UART_FIFO_SIZE    64      /* FIFO size */
-#define CDNS_UART_REGISTER_SPACE       0xFFF
-
-#define cdns_uart_readl(offset)                ioread32(port->membase + offset)
-#define cdns_uart_writel(val, offset)  iowrite32(val, port->membase + offset)
+#define CDNS_UART_REGISTER_SPACE       0x1000
 
 /* Rx Trigger level */
 static int rx_trigger_level = 56;
@@ -195,7 +192,7 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id)
        /* Read the interrupt status register to determine which
         * interrupt(s) is/are active.
         */
-       isrstatus = cdns_uart_readl(CDNS_UART_ISR_OFFSET);
+       isrstatus = readl(port->membase + CDNS_UART_ISR_OFFSET);
 
        /*
         * There is no hardware break detection, so we interpret framing
@@ -203,14 +200,15 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id)
         * there's another non-zero byte at the end of the sequence.
         */
        if (isrstatus & CDNS_UART_IXR_FRAMING) {
-               while (!(cdns_uart_readl(CDNS_UART_SR_OFFSET) &
+               while (!(readl(port->membase + CDNS_UART_SR_OFFSET) &
                                        CDNS_UART_SR_RXEMPTY)) {
-                       if (!cdns_uart_readl(CDNS_UART_FIFO_OFFSET)) {
+                       if (!readl(port->membase + CDNS_UART_FIFO_OFFSET)) {
                                port->read_status_mask |= CDNS_UART_IXR_BRK;
                                isrstatus &= ~CDNS_UART_IXR_FRAMING;
                        }
                }
-               cdns_uart_writel(CDNS_UART_IXR_FRAMING, CDNS_UART_ISR_OFFSET);
+               writel(CDNS_UART_IXR_FRAMING,
+                               port->membase + CDNS_UART_ISR_OFFSET);
        }
 
        /* drop byte with parity error if IGNPAR specified */
@@ -223,9 +221,9 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id)
        if ((isrstatus & CDNS_UART_IXR_TOUT) ||
                (isrstatus & CDNS_UART_IXR_RXTRIG)) {
                /* Receive Timeout Interrupt */
-               while ((cdns_uart_readl(CDNS_UART_SR_OFFSET) &
-                       CDNS_UART_SR_RXEMPTY) != CDNS_UART_SR_RXEMPTY) {
-                       data = cdns_uart_readl(CDNS_UART_FIFO_OFFSET);
+               while (!(readl(port->membase + CDNS_UART_SR_OFFSET) &
+                                       CDNS_UART_SR_RXEMPTY)) {
+                       data = readl(port->membase + CDNS_UART_FIFO_OFFSET);
 
                        /* Non-NULL byte after BREAK is garbage (99%) */
                        if (data && (port->read_status_mask &
@@ -275,8 +273,8 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id)
        /* Dispatch an appropriate handler */
        if ((isrstatus & CDNS_UART_IXR_TXEMPTY) == CDNS_UART_IXR_TXEMPTY) {
                if (uart_circ_empty(&port->state->xmit)) {
-                       cdns_uart_writel(CDNS_UART_IXR_TXEMPTY,
-                                               CDNS_UART_IDR_OFFSET);
+                       writel(CDNS_UART_IXR_TXEMPTY,
+                                       port->membase + CDNS_UART_IDR_OFFSET);
                } else {
                        numbytes = port->fifosize;
                        /* Break if no more data available in the UART buffer */
@@ -287,9 +285,9 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id)
                                 * and write it to the cdns_uart's TX_FIFO
                                 * register.
                                 */
-                               cdns_uart_writel(
-                                       port->state->xmit.buf[port->state->xmit.
-                                       tail], CDNS_UART_FIFO_OFFSET);
+                               writel(port->state->xmit.buf[
+                                               port->state->xmit.tail],
+                                       port->membase + CDNS_UART_FIFO_OFFSET);
 
                                port->icount.tx++;
 
@@ -307,7 +305,7 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id)
                }
        }
 
-       cdns_uart_writel(isrstatus, CDNS_UART_ISR_OFFSET);
+       writel(isrstatus, port->membase + CDNS_UART_ISR_OFFSET);
 
        /* be sure to release the lock and tty before leaving */
        spin_unlock_irqrestore(&port->lock, flags);
@@ -397,14 +395,14 @@ static unsigned int cdns_uart_set_baud_rate(struct uart_port *port,
                        &div8);
 
        /* Write new divisors to hardware */
-       mreg = cdns_uart_readl(CDNS_UART_MR_OFFSET);
+       mreg = readl(port->membase + CDNS_UART_MR_OFFSET);
        if (div8)
                mreg |= CDNS_UART_MR_CLKSEL;
        else
                mreg &= ~CDNS_UART_MR_CLKSEL;
-       cdns_uart_writel(mreg, CDNS_UART_MR_OFFSET);
-       cdns_uart_writel(cd, CDNS_UART_BAUDGEN_OFFSET);
-       cdns_uart_writel(bdiv, CDNS_UART_BAUDDIV_OFFSET);
+       writel(mreg, port->membase + CDNS_UART_MR_OFFSET);
+       writel(cd, port->membase + CDNS_UART_BAUDGEN_OFFSET);
+       writel(bdiv, port->membase + CDNS_UART_BAUDDIV_OFFSET);
        cdns_uart->baud = baud;
 
        return calc_baud;
@@ -451,9 +449,9 @@ static int cdns_uart_clk_notifier_cb(struct notifier_block *nb,
                spin_lock_irqsave(&cdns_uart->port->lock, flags);
 
                /* Disable the TX and RX to set baud rate */
-               ctrl_reg = cdns_uart_readl(CDNS_UART_CR_OFFSET);
+               ctrl_reg = readl(port->membase + CDNS_UART_CR_OFFSET);
                ctrl_reg |= CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS;
-               cdns_uart_writel(ctrl_reg, CDNS_UART_CR_OFFSET);
+               writel(ctrl_reg, port->membase + CDNS_UART_CR_OFFSET);
 
                spin_unlock_irqrestore(&cdns_uart->port->lock, flags);
 
@@ -478,11 +476,11 @@ static int cdns_uart_clk_notifier_cb(struct notifier_block *nb,
                        spin_lock_irqsave(&cdns_uart->port->lock, flags);
 
                /* Set TX/RX Reset */
-               ctrl_reg = cdns_uart_readl(CDNS_UART_CR_OFFSET);
+               ctrl_reg = readl(port->membase + CDNS_UART_CR_OFFSET);
                ctrl_reg |= CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST;
-               cdns_uart_writel(ctrl_reg, CDNS_UART_CR_OFFSET);
+               writel(ctrl_reg, port->membase + CDNS_UART_CR_OFFSET);
 
-               while (cdns_uart_readl(CDNS_UART_CR_OFFSET) &
+               while (readl(port->membase + CDNS_UART_CR_OFFSET) &
                                (CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST))
                        cpu_relax();
 
@@ -491,11 +489,11 @@ static int cdns_uart_clk_notifier_cb(struct notifier_block *nb,
                 * enable bit and RX enable bit to enable the transmitter and
                 * receiver.
                 */
-               cdns_uart_writel(rx_timeout, CDNS_UART_RXTOUT_OFFSET);
-               ctrl_reg = cdns_uart_readl(CDNS_UART_CR_OFFSET);
+               writel(rx_timeout, port->membase + CDNS_UART_RXTOUT_OFFSET);
+               ctrl_reg = readl(port->membase + CDNS_UART_CR_OFFSET);
                ctrl_reg &= ~(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS);
                ctrl_reg |= CDNS_UART_CR_TX_EN | CDNS_UART_CR_RX_EN;
-               cdns_uart_writel(ctrl_reg, CDNS_UART_CR_OFFSET);
+               writel(ctrl_reg, port->membase + CDNS_UART_CR_OFFSET);
 
                spin_unlock_irqrestore(&cdns_uart->port->lock, flags);
 
@@ -517,14 +515,14 @@ static void cdns_uart_start_tx(struct uart_port *port)
        if (uart_circ_empty(&port->state->xmit) || uart_tx_stopped(port))
                return;
 
-       status = cdns_uart_readl(CDNS_UART_CR_OFFSET);
+       status = readl(port->membase + CDNS_UART_CR_OFFSET);
        /* Set the TX enable bit and clear the TX disable bit to enable the
         * transmitter.
         */
-       cdns_uart_writel((status & ~CDNS_UART_CR_TX_DIS) | CDNS_UART_CR_TX_EN,
-               CDNS_UART_CR_OFFSET);
+       writel((status & ~CDNS_UART_CR_TX_DIS) | CDNS_UART_CR_TX_EN,
+                       port->membase + CDNS_UART_CR_OFFSET);
 
-       while (numbytes-- && ((cdns_uart_readl(CDNS_UART_SR_OFFSET) &
+       while (numbytes-- && ((readl(port->membase + CDNS_UART_SR_OFFSET) &
                                CDNS_UART_SR_TXFULL)) != CDNS_UART_SR_TXFULL) {
                /* Break if no more data available in the UART buffer */
                if (uart_circ_empty(&port->state->xmit))
@@ -533,9 +531,8 @@ static void cdns_uart_start_tx(struct uart_port *port)
                /* Get the data from the UART circular buffer and
                 * write it to the cdns_uart's TX_FIFO register.
                 */
-               cdns_uart_writel(
-                       port->state->xmit.buf[port->state->xmit.tail],
-                       CDNS_UART_FIFO_OFFSET);
+               writel(port->state->xmit.buf[port->state->xmit.tail],
+                               port->membase + CDNS_UART_FIFO_OFFSET);
                port->icount.tx++;
 
                /* Adjust the tail of the UART buffer and wrap
@@ -544,9 +541,9 @@ static void cdns_uart_start_tx(struct uart_port *port)
                port->state->xmit.tail = (port->state->xmit.tail + 1) &
                                        (UART_XMIT_SIZE - 1);
        }
-       cdns_uart_writel(CDNS_UART_IXR_TXEMPTY, CDNS_UART_ISR_OFFSET);
+       writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_ISR_OFFSET);
        /* Enable the TX Empty interrupt */
-       cdns_uart_writel(CDNS_UART_IXR_TXEMPTY, CDNS_UART_IER_OFFSET);
+       writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_IER_OFFSET);
 
        if (uart_circ_chars_pending(&port->state->xmit) < WAKEUP_CHARS)
                uart_write_wakeup(port);
@@ -560,10 +557,10 @@ static void cdns_uart_stop_tx(struct uart_port *port)
 {
        unsigned int regval;
 
-       regval = cdns_uart_readl(CDNS_UART_CR_OFFSET);
+       regval = readl(port->membase + CDNS_UART_CR_OFFSET);
        regval |= CDNS_UART_CR_TX_DIS;
        /* Disable the transmitter */
-       cdns_uart_writel(regval, CDNS_UART_CR_OFFSET);
+       writel(regval, port->membase + CDNS_UART_CR_OFFSET);
 }
 
 /**
@@ -574,10 +571,10 @@ static void cdns_uart_stop_rx(struct uart_port *port)
 {
        unsigned int regval;
 
-       regval = cdns_uart_readl(CDNS_UART_CR_OFFSET);
+       regval = readl(port->membase + CDNS_UART_CR_OFFSET);
        regval |= CDNS_UART_CR_RX_DIS;
        /* Disable the receiver */
-       cdns_uart_writel(regval, CDNS_UART_CR_OFFSET);
+       writel(regval, port->membase + CDNS_UART_CR_OFFSET);
 }
 
 /**
@@ -590,7 +587,8 @@ static unsigned int cdns_uart_tx_empty(struct uart_port *port)
 {
        unsigned int status;
 
-       status = cdns_uart_readl(CDNS_UART_SR_OFFSET) & CDNS_UART_SR_TXEMPTY;
+       status = readl(port->membase + CDNS_UART_SR_OFFSET) &
+                               CDNS_UART_SR_TXEMPTY;
        return status ? TIOCSER_TEMT : 0;
 }
 
@@ -607,15 +605,15 @@ static void cdns_uart_break_ctl(struct uart_port *port, int ctl)
 
        spin_lock_irqsave(&port->lock, flags);
 
-       status = cdns_uart_readl(CDNS_UART_CR_OFFSET);
+       status = readl(port->membase + CDNS_UART_CR_OFFSET);
 
        if (ctl == -1)
-               cdns_uart_writel(CDNS_UART_CR_STARTBRK | status,
-                                       CDNS_UART_CR_OFFSET);
+               writel(CDNS_UART_CR_STARTBRK | status,
+                               port->membase + CDNS_UART_CR_OFFSET);
        else {
                if ((status & CDNS_UART_CR_STOPBRK) == 0)
-                       cdns_uart_writel(CDNS_UART_CR_STOPBRK | status,
-                                        CDNS_UART_CR_OFFSET);
+                       writel(CDNS_UART_CR_STOPBRK | status,
+                                       port->membase + CDNS_UART_CR_OFFSET);
        }
        spin_unlock_irqrestore(&port->lock, flags);
 }
@@ -638,17 +636,18 @@ static void cdns_uart_set_termios(struct uart_port *port,
        spin_lock_irqsave(&port->lock, flags);
 
        /* Wait for the transmit FIFO to empty before making changes */
-       if (!(cdns_uart_readl(CDNS_UART_CR_OFFSET) & CDNS_UART_CR_TX_DIS)) {
-               while (!(cdns_uart_readl(CDNS_UART_SR_OFFSET) &
+       if (!(readl(port->membase + CDNS_UART_CR_OFFSET) &
+                               CDNS_UART_CR_TX_DIS)) {
+               while (!(readl(port->membase + CDNS_UART_SR_OFFSET) &
                                CDNS_UART_SR_TXEMPTY)) {
                        cpu_relax();
                }
        }
 
        /* Disable the TX and RX to set baud rate */
-       ctrl_reg = cdns_uart_readl(CDNS_UART_CR_OFFSET);
+       ctrl_reg = readl(port->membase + CDNS_UART_CR_OFFSET);
        ctrl_reg |= CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS;
-       cdns_uart_writel(ctrl_reg, CDNS_UART_CR_OFFSET);
+       writel(ctrl_reg, port->membase + CDNS_UART_CR_OFFSET);
 
        /*
         * Min baud rate = 6bps and Max Baud Rate is 10Mbps for 100Mhz clk
@@ -667,20 +666,20 @@ static void cdns_uart_set_termios(struct uart_port *port,
        uart_update_timeout(port, termios->c_cflag, baud);
 
        /* Set TX/RX Reset */
-       ctrl_reg = cdns_uart_readl(CDNS_UART_CR_OFFSET);
+       ctrl_reg = readl(port->membase + CDNS_UART_CR_OFFSET);
        ctrl_reg |= CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST;
-       cdns_uart_writel(ctrl_reg, CDNS_UART_CR_OFFSET);
+       writel(ctrl_reg, port->membase + CDNS_UART_CR_OFFSET);
 
        /*
         * Clear the RX disable and TX disable bits and then set the TX enable
         * bit and RX enable bit to enable the transmitter and receiver.
         */
-       ctrl_reg = cdns_uart_readl(CDNS_UART_CR_OFFSET);
+       ctrl_reg = readl(port->membase + CDNS_UART_CR_OFFSET);
        ctrl_reg &= ~(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS);
        ctrl_reg |= CDNS_UART_CR_TX_EN | CDNS_UART_CR_RX_EN;
-       cdns_uart_writel(ctrl_reg, CDNS_UART_CR_OFFSET);
+       writel(ctrl_reg, port->membase + CDNS_UART_CR_OFFSET);
 
-       cdns_uart_writel(rx_timeout, CDNS_UART_RXTOUT_OFFSET);
+       writel(rx_timeout, port->membase + CDNS_UART_RXTOUT_OFFSET);
 
        port->read_status_mask = CDNS_UART_IXR_TXEMPTY | CDNS_UART_IXR_RXTRIG |
                        CDNS_UART_IXR_OVERRUN | CDNS_UART_IXR_TOUT;
@@ -700,7 +699,7 @@ static void cdns_uart_set_termios(struct uart_port *port,
                        CDNS_UART_IXR_TOUT | CDNS_UART_IXR_PARITY |
                        CDNS_UART_IXR_FRAMING | CDNS_UART_IXR_OVERRUN;
 
-       mode_reg = cdns_uart_readl(CDNS_UART_MR_OFFSET);
+       mode_reg = readl(port->membase + CDNS_UART_MR_OFFSET);
 
        /* Handling Data Size */
        switch (termios->c_cflag & CSIZE) {
@@ -741,7 +740,7 @@ static void cdns_uart_set_termios(struct uart_port *port,
                cval |= CDNS_UART_MR_PARITY_NONE;
        }
        cval |= mode_reg & 1;
-       cdns_uart_writel(cval, CDNS_UART_MR_OFFSET);
+       writel(cval, port->membase + CDNS_UART_MR_OFFSET);
 
        spin_unlock_irqrestore(&port->lock, flags);
 }
@@ -762,52 +761,53 @@ static int cdns_uart_startup(struct uart_port *port)
                return retval;
 
        /* Disable the TX and RX */
-       cdns_uart_writel(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS,
-                                               CDNS_UART_CR_OFFSET);
+       writel(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS,
+                       port->membase + CDNS_UART_CR_OFFSET);
 
        /* Set the Control Register with TX/RX Enable, TX/RX Reset,
         * no break chars.
         */
-       cdns_uart_writel(CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST,
-                               CDNS_UART_CR_OFFSET);
+       writel(CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST,
+                       port->membase + CDNS_UART_CR_OFFSET);
 
-       status = cdns_uart_readl(CDNS_UART_CR_OFFSET);
+       status = readl(port->membase + CDNS_UART_CR_OFFSET);
 
        /* Clear the RX disable and TX disable bits and then set the TX enable
         * bit and RX enable bit to enable the transmitter and receiver.
         */
-       cdns_uart_writel((status & ~(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS))
+       writel((status & ~(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS))
                        | (CDNS_UART_CR_TX_EN | CDNS_UART_CR_RX_EN |
-                       CDNS_UART_CR_STOPBRK), CDNS_UART_CR_OFFSET);
+                       CDNS_UART_CR_STOPBRK),
+                       port->membase + CDNS_UART_CR_OFFSET);
 
        /* Set the Mode Register with normal mode,8 data bits,1 stop bit,
         * no parity.
         */
-       cdns_uart_writel(CDNS_UART_MR_CHMODE_NORM | CDNS_UART_MR_STOPMODE_1_BIT
+       writel(CDNS_UART_MR_CHMODE_NORM | CDNS_UART_MR_STOPMODE_1_BIT
                | CDNS_UART_MR_PARITY_NONE | CDNS_UART_MR_CHARLEN_8_BIT,
-                CDNS_UART_MR_OFFSET);
+               port->membase + CDNS_UART_MR_OFFSET);
 
        /*
         * Set the RX FIFO Trigger level to use most of the FIFO, but it
         * can be tuned with a module parameter
         */
-       cdns_uart_writel(rx_trigger_level, CDNS_UART_RXWM_OFFSET);
+       writel(rx_trigger_level, port->membase + CDNS_UART_RXWM_OFFSET);
 
        /*
         * Receive Timeout register is enabled but it
         * can be tuned with a module parameter
         */
-       cdns_uart_writel(rx_timeout, CDNS_UART_RXTOUT_OFFSET);
+       writel(rx_timeout, port->membase + CDNS_UART_RXTOUT_OFFSET);
 
        /* Clear out any pending interrupts before enabling them */
-       cdns_uart_writel(cdns_uart_readl(CDNS_UART_ISR_OFFSET),
-                       CDNS_UART_ISR_OFFSET);
+       writel(readl(port->membase + CDNS_UART_ISR_OFFSET),
+                       port->membase + CDNS_UART_ISR_OFFSET);
 
        /* Set the Interrupt Registers with desired interrupts */
-       cdns_uart_writel(CDNS_UART_IXR_TXEMPTY | CDNS_UART_IXR_PARITY |
+       writel(CDNS_UART_IXR_TXEMPTY | CDNS_UART_IXR_PARITY |
                CDNS_UART_IXR_FRAMING | CDNS_UART_IXR_OVERRUN |
                CDNS_UART_IXR_RXTRIG | CDNS_UART_IXR_TOUT,
-               CDNS_UART_IER_OFFSET);
+               port->membase + CDNS_UART_IER_OFFSET);
 
        return retval;
 }
@@ -821,12 +821,12 @@ static void cdns_uart_shutdown(struct uart_port *port)
        int status;
 
        /* Disable interrupts */
-       status = cdns_uart_readl(CDNS_UART_IMR_OFFSET);
-       cdns_uart_writel(status, CDNS_UART_IDR_OFFSET);
+       status = readl(port->membase + CDNS_UART_IMR_OFFSET);
+       writel(status, port->membase + CDNS_UART_IDR_OFFSET);
 
        /* Disable the TX and RX */
-       cdns_uart_writel(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS,
-                                CDNS_UART_CR_OFFSET);
+       writel(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS,
+                       port->membase + CDNS_UART_CR_OFFSET);
        free_irq(port->irq, port);
 }
 
@@ -928,7 +928,7 @@ static void cdns_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
        u32 val;
 
-       val = cdns_uart_readl(CDNS_UART_MODEMCR_OFFSET);
+       val = readl(port->membase + CDNS_UART_MODEMCR_OFFSET);
 
        val &= ~(CDNS_UART_MODEMCR_RTS | CDNS_UART_MODEMCR_DTR);
 
@@ -937,7 +937,7 @@ static void cdns_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
        if (mctrl & TIOCM_DTR)
                val |= CDNS_UART_MODEMCR_DTR;
 
-       cdns_uart_writel(val, CDNS_UART_MODEMCR_OFFSET);
+       writel(val, port->membase + CDNS_UART_MODEMCR_OFFSET);
 }
 
 #ifdef CONFIG_CONSOLE_POLL
@@ -947,17 +947,18 @@ static int cdns_uart_poll_get_char(struct uart_port *port)
        int c;
 
        /* Disable all interrupts */
-       imr = cdns_uart_readl(CDNS_UART_IMR_OFFSET);
-       cdns_uart_writel(imr, CDNS_UART_IDR_OFFSET);
+       imr = readl(port->membase + CDNS_UART_IMR_OFFSET);
+       writel(imr, port->membase + CDNS_UART_IDR_OFFSET);
 
        /* Check if FIFO is empty */
-       if (cdns_uart_readl(CDNS_UART_SR_OFFSET) & CDNS_UART_SR_RXEMPTY)
+       if (readl(port->membase + CDNS_UART_SR_OFFSET) & CDNS_UART_SR_RXEMPTY)
                c = NO_POLL_CHAR;
        else /* Read a character */
-               c = (unsigned char) cdns_uart_readl(CDNS_UART_FIFO_OFFSET);
+               c = (unsigned char) readl(
+                                       port->membase + CDNS_UART_FIFO_OFFSET);
 
        /* Enable interrupts */
-       cdns_uart_writel(imr, CDNS_UART_IER_OFFSET);
+       writel(imr, port->membase + CDNS_UART_IER_OFFSET);
 
        return c;
 }
@@ -967,22 +968,24 @@ static void cdns_uart_poll_put_char(struct uart_port *port, unsigned char c)
        u32 imr;
 
        /* Disable all interrupts */
-       imr = cdns_uart_readl(CDNS_UART_IMR_OFFSET);
-       cdns_uart_writel(imr, CDNS_UART_IDR_OFFSET);
+       imr = readl(port->membase + CDNS_UART_IMR_OFFSET);
+       writel(imr, port->membase + CDNS_UART_IDR_OFFSET);
 
        /* Wait until FIFO is empty */
-       while (!(cdns_uart_readl(CDNS_UART_SR_OFFSET) & CDNS_UART_SR_TXEMPTY))
+       while (!(readl(port->membase + CDNS_UART_SR_OFFSET) &
+                               CDNS_UART_SR_TXEMPTY))
                cpu_relax();
 
        /* Write a character */
-       cdns_uart_writel(c, CDNS_UART_FIFO_OFFSET);
+       writel(c, port->membase + CDNS_UART_FIFO_OFFSET);
 
        /* Wait until FIFO is empty */
-       while (!(cdns_uart_readl(CDNS_UART_SR_OFFSET) & CDNS_UART_SR_TXEMPTY))
+       while (!(readl(port->membase + CDNS_UART_SR_OFFSET) &
+                               CDNS_UART_SR_TXEMPTY))
                cpu_relax();
 
        /* Enable interrupts */
-       cdns_uart_writel(imr, CDNS_UART_IER_OFFSET);
+       writel(imr, port->membase + CDNS_UART_IER_OFFSET);
 
        return;
 }
@@ -1010,7 +1013,7 @@ static struct uart_ops cdns_uart_ops = {
 #endif
 };
 
-static struct uart_port cdns_uart_port[2];
+static struct uart_port cdns_uart_port[CDNS_UART_NR_PORTS];
 
 /**
  * cdns_uart_get_port - Configure the port from platform device resource info
@@ -1038,7 +1041,6 @@ static struct uart_port *cdns_uart_get_port(int id)
        /* At this point, we've got an empty uart_port struct, initialize it */
        spin_lock_init(&port->lock);
        port->membase   = NULL;
-       port->iobase    = 1; /* mark port in use */
        port->irq       = 0;
        port->type      = PORT_UNKNOWN;
        port->iotype    = UPIO_MEM32;
@@ -1057,8 +1059,8 @@ static struct uart_port *cdns_uart_get_port(int id)
  */
 static void cdns_uart_console_wait_tx(struct uart_port *port)
 {
-       while ((cdns_uart_readl(CDNS_UART_SR_OFFSET) & CDNS_UART_SR_TXEMPTY)
-                               != CDNS_UART_SR_TXEMPTY)
+       while (!(readl(port->membase + CDNS_UART_SR_OFFSET) &
+                               CDNS_UART_SR_TXEMPTY))
                barrier();
 }
 
@@ -1070,7 +1072,7 @@ static void cdns_uart_console_wait_tx(struct uart_port *port)
 static void cdns_uart_console_putchar(struct uart_port *port, int ch)
 {
        cdns_uart_console_wait_tx(port);
-       cdns_uart_writel(ch, CDNS_UART_FIFO_OFFSET);
+       writel(ch, port->membase + CDNS_UART_FIFO_OFFSET);
 }
 
 static void cdns_early_write(struct console *con, const char *s, unsigned n)
@@ -1112,24 +1114,24 @@ static void cdns_uart_console_write(struct console *co, const char *s,
                spin_lock_irqsave(&port->lock, flags);
 
        /* save and disable interrupt */
-       imr = cdns_uart_readl(CDNS_UART_IMR_OFFSET);
-       cdns_uart_writel(imr, CDNS_UART_IDR_OFFSET);
+       imr = readl(port->membase + CDNS_UART_IMR_OFFSET);
+       writel(imr, port->membase + CDNS_UART_IDR_OFFSET);
 
        /*
         * Make sure that the tx part is enabled. Set the TX enable bit and
         * clear the TX disable bit to enable the transmitter.
         */
-       ctrl = cdns_uart_readl(CDNS_UART_CR_OFFSET);
-       cdns_uart_writel((ctrl & ~CDNS_UART_CR_TX_DIS) | CDNS_UART_CR_TX_EN,
-               CDNS_UART_CR_OFFSET);
+       ctrl = readl(port->membase + CDNS_UART_CR_OFFSET);
+       writel((ctrl & ~CDNS_UART_CR_TX_DIS) | CDNS_UART_CR_TX_EN,
+                       port->membase + CDNS_UART_CR_OFFSET);
 
        uart_console_write(port, s, count, cdns_uart_console_putchar);
        cdns_uart_console_wait_tx(port);
 
-       cdns_uart_writel(ctrl, CDNS_UART_CR_OFFSET);
+       writel(ctrl, port->membase + CDNS_UART_CR_OFFSET);
 
        /* restore interrupt state */
-       cdns_uart_writel(imr, CDNS_UART_IER_OFFSET);
+       writel(imr, port->membase + CDNS_UART_IER_OFFSET);
 
        if (locked)
                spin_unlock_irqrestore(&port->lock, flags);
@@ -1153,8 +1155,9 @@ static int __init cdns_uart_console_setup(struct console *co, char *options)
        if (co->index < 0 || co->index >= CDNS_UART_NR_PORTS)
                return -EINVAL;
 
-       if (!port->mapbase) {
-               pr_debug("console on ttyPS%i not present\n", co->index);
+       if (!port->membase) {
+               pr_debug("console on " CDNS_UART_TTY_NAME "%i not present\n",
+                        co->index);
                return -ENODEV;
        }
 
@@ -1240,13 +1243,14 @@ static int cdns_uart_suspend(struct device *device)
 
                spin_lock_irqsave(&port->lock, flags);
                /* Empty the receive FIFO 1st before making changes */
-               while (!(cdns_uart_readl(CDNS_UART_SR_OFFSET) &
+               while (!(readl(port->membase + CDNS_UART_SR_OFFSET) &
                                        CDNS_UART_SR_RXEMPTY))
-                       cdns_uart_readl(CDNS_UART_FIFO_OFFSET);
+                       readl(port->membase + CDNS_UART_FIFO_OFFSET);
                /* set RX trigger level to 1 */
-               cdns_uart_writel(1, CDNS_UART_RXWM_OFFSET);
+               writel(1, port->membase + CDNS_UART_RXWM_OFFSET);
                /* disable RX timeout interrups */
-               cdns_uart_writel(CDNS_UART_IXR_TOUT, CDNS_UART_IDR_OFFSET);
+               writel(CDNS_UART_IXR_TOUT,
+                               port->membase + CDNS_UART_IDR_OFFSET);
                spin_unlock_irqrestore(&port->lock, flags);
        }
 
@@ -1285,28 +1289,30 @@ static int cdns_uart_resume(struct device *device)
                spin_lock_irqsave(&port->lock, flags);
 
                /* Set TX/RX Reset */
-               ctrl_reg = cdns_uart_readl(CDNS_UART_CR_OFFSET);
+               ctrl_reg = readl(port->membase + CDNS_UART_CR_OFFSET);
                ctrl_reg |= CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST;
-               cdns_uart_writel(ctrl_reg, CDNS_UART_CR_OFFSET);
-               while (cdns_uart_readl(CDNS_UART_CR_OFFSET) &
+               writel(ctrl_reg, port->membase + CDNS_UART_CR_OFFSET);
+               while (readl(port->membase + CDNS_UART_CR_OFFSET) &
                                (CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST))
                        cpu_relax();
 
                /* restore rx timeout value */
-               cdns_uart_writel(rx_timeout, CDNS_UART_RXTOUT_OFFSET);
+               writel(rx_timeout, port->membase + CDNS_UART_RXTOUT_OFFSET);
                /* Enable Tx/Rx */
-               ctrl_reg = cdns_uart_readl(CDNS_UART_CR_OFFSET);
+               ctrl_reg = readl(port->membase + CDNS_UART_CR_OFFSET);
                ctrl_reg &= ~(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS);
                ctrl_reg |= CDNS_UART_CR_TX_EN | CDNS_UART_CR_RX_EN;
-               cdns_uart_writel(ctrl_reg, CDNS_UART_CR_OFFSET);
+               writel(ctrl_reg, port->membase + CDNS_UART_CR_OFFSET);
 
                spin_unlock_irqrestore(&port->lock, flags);
        } else {
                spin_lock_irqsave(&port->lock, flags);
                /* restore original rx trigger level */
-               cdns_uart_writel(rx_trigger_level, CDNS_UART_RXWM_OFFSET);
+               writel(rx_trigger_level,
+                               port->membase + CDNS_UART_RXWM_OFFSET);
                /* enable RX timeout interrupt */
-               cdns_uart_writel(CDNS_UART_IXR_TOUT, CDNS_UART_IER_OFFSET);
+               writel(CDNS_UART_IXR_TOUT,
+                               port->membase + CDNS_UART_IER_OFFSET);
                spin_unlock_irqrestore(&port->lock, flags);
        }
 
@@ -1325,9 +1331,9 @@ static SIMPLE_DEV_PM_OPS(cdns_uart_dev_pm_ops, cdns_uart_suspend,
  */
 static int cdns_uart_probe(struct platform_device *pdev)
 {
-       int rc, id;
+       int rc, id, irq;
        struct uart_port *port;
-       struct resource *res, *res2;
+       struct resource *res;
        struct cdns_uart *cdns_uart_data;
 
        cdns_uart_data = devm_kzalloc(&pdev->dev, sizeof(*cdns_uart_data),
@@ -1374,9 +1380,9 @@ static int cdns_uart_probe(struct platform_device *pdev)
                goto err_out_clk_disable;
        }
 
-       res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (!res2) {
-               rc = -ENODEV;
+       irq = platform_get_irq(pdev, 0);
+       if (irq <= 0) {
+               rc = -ENXIO;
                goto err_out_clk_disable;
        }
 
@@ -1405,7 +1411,7 @@ static int cdns_uart_probe(struct platform_device *pdev)
                 * and triggers invocation of the config_port() entry point.
                 */
                port->mapbase = res->start;
-               port->irq = res2->start;
+               port->irq = irq;
                port->dev = &pdev->dev;
                port->uartclk = clk_get_rate(cdns_uart_data->uartclk);
                port->private_data = cdns_uart_data;
@@ -1458,7 +1464,7 @@ static int cdns_uart_remove(struct platform_device *pdev)
 }
 
 /* Match table for of_platform binding */
-static struct of_device_id cdns_uart_of_match[] = {
+static const struct of_device_id cdns_uart_of_match[] = {
        { .compatible = "xlnx,xuartps", },
        { .compatible = "cdns,uart-r1p8", },
        {}
index 2bb4dfc028734079f29a89bfb779bfdc7e0079eb..e5695467598f9b68629738586c5ed9285d8384ae 100644 (file)
@@ -1025,11 +1025,17 @@ void start_tty(struct tty_struct *tty)
 }
 EXPORT_SYMBOL(start_tty);
 
-/* We limit tty time update visibility to every 8 seconds or so. */
 static void tty_update_time(struct timespec *time)
 {
        unsigned long sec = get_seconds();
-       if (abs(sec - time->tv_sec) & ~7)
+
+       /*
+        * We only care if the two values differ in anything other than the
+        * lower three bits (i.e every 8 seconds).  If so, then we can update
+        * the time of the tty device, otherwise it could be construded as a
+        * security leak to let userspace know the exact timing of the tty.
+        */
+       if ((sec ^ time->tv_sec) & ~7)
                time->tv_sec = sec;
 }
 
@@ -3593,6 +3599,13 @@ static ssize_t show_cons_active(struct device *dev,
 }
 static DEVICE_ATTR(active, S_IRUGO, show_cons_active, NULL);
 
+static struct attribute *cons_dev_attrs[] = {
+       &dev_attr_active.attr,
+       NULL
+};
+
+ATTRIBUTE_GROUPS(cons_dev);
+
 static struct device *consdev;
 
 void console_sysfs_notify(void)
@@ -3617,12 +3630,11 @@ int __init tty_init(void)
        if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||
            register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)
                panic("Couldn't register /dev/console driver\n");
-       consdev = device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL,
-                             "console");
+       consdev = device_create_with_groups(tty_class, NULL,
+                                           MKDEV(TTYAUX_MAJOR, 1), NULL,
+                                           cons_dev_groups, "console");
        if (IS_ERR(consdev))
                consdev = NULL;
-       else
-               WARN_ON(device_create_file(consdev, &dev_attr_active) < 0);
 
 #ifdef CONFIG_VT
        vty_init(&console_fops);
index 632fc815206169281af9aa13f6ca345eb846eabe..8e53fe4696647e6bbfd8951e3a96a0d070ce28af 100644 (file)
@@ -536,7 +536,7 @@ EXPORT_SYMBOL(tty_termios_hw_change);
  *     Locking: termios_rwsem
  */
 
-static int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios)
+int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios)
 {
        struct ktermios old_termios;
        struct tty_ldisc *ld;
@@ -569,6 +569,7 @@ static int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios)
        up_write(&tty->termios_rwsem);
        return 0;
 }
+EXPORT_SYMBOL_GPL(tty_set_termios);
 
 /**
  *     set_termios             -       set termios values for a tty
index 6e00572cbeb9386bd357a5ec466e5c2eb259fc4c..4a24eb2b0ede20c2968d0566f488daf07e33b250 100644 (file)
@@ -1237,7 +1237,7 @@ static void default_attr(struct vc_data *vc)
 
 struct rgb { u8 r; u8 g; u8 b; };
 
-struct rgb rgb_from_256(int i)
+static struct rgb rgb_from_256(int i)
 {
        struct rgb c;
        if (i < 8) {            /* Standard colours. */
@@ -1573,7 +1573,7 @@ static void setterm_command(struct vc_data *vc)
                case 11: /* set bell duration in msec */
                        if (vc->vc_npar >= 1)
                                vc->vc_bell_duration = (vc->vc_par[1] < 2000) ?
-                                       vc->vc_par[1] * HZ / 1000 : 0;
+                                       msecs_to_jiffies(vc->vc_par[1]) : 0;
                        else
                                vc->vc_bell_duration = DEFAULT_BELL_DURATION;
                        break;
@@ -3041,17 +3041,24 @@ static ssize_t show_tty_active(struct device *dev,
 }
 static DEVICE_ATTR(active, S_IRUGO, show_tty_active, NULL);
 
+static struct attribute *vt_dev_attrs[] = {
+       &dev_attr_active.attr,
+       NULL
+};
+
+ATTRIBUTE_GROUPS(vt_dev);
+
 int __init vty_init(const struct file_operations *console_fops)
 {
        cdev_init(&vc0_cdev, console_fops);
        if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) ||
            register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
                panic("Couldn't register /dev/tty0 driver\n");
-       tty0dev = device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
+       tty0dev = device_create_with_groups(tty_class, NULL,
+                                           MKDEV(TTY_MAJOR, 0), NULL,
+                                           vt_dev_groups, "tty0");
        if (IS_ERR(tty0dev))
                tty0dev = NULL;
-       else
-               WARN_ON(device_create_file(tty0dev, &dev_attr_active) < 0);
 
        vcs_init();
 
@@ -3423,42 +3430,26 @@ static ssize_t show_name(struct device *dev, struct device_attribute *attr,
 
 }
 
-static struct device_attribute device_attrs[] = {
-       __ATTR(bind, S_IRUGO|S_IWUSR, show_bind, store_bind),
-       __ATTR(name, S_IRUGO, show_name, NULL),
+static DEVICE_ATTR(bind, S_IRUGO|S_IWUSR, show_bind, store_bind);
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+static struct attribute *con_dev_attrs[] = {
+       &dev_attr_bind.attr,
+       &dev_attr_name.attr,
+       NULL
 };
 
+ATTRIBUTE_GROUPS(con_dev);
+
 static int vtconsole_init_device(struct con_driver *con)
 {
-       int i;
-       int error = 0;
-
        con->flag |= CON_DRIVER_FLAG_ATTR;
-       dev_set_drvdata(con->dev, con);
-       for (i = 0; i < ARRAY_SIZE(device_attrs); i++) {
-               error = device_create_file(con->dev, &device_attrs[i]);
-               if (error)
-                       break;
-       }
-
-       if (error) {
-               while (--i >= 0)
-                       device_remove_file(con->dev, &device_attrs[i]);
-               con->flag &= ~CON_DRIVER_FLAG_ATTR;
-       }
-
-       return error;
+       return 0;
 }
 
 static void vtconsole_deinit_device(struct con_driver *con)
 {
-       int i;
-
-       if (con->flag & CON_DRIVER_FLAG_ATTR) {
-               for (i = 0; i < ARRAY_SIZE(device_attrs); i++)
-                       device_remove_file(con->dev, &device_attrs[i]);
-               con->flag &= ~CON_DRIVER_FLAG_ATTR;
-       }
+       con->flag &= ~CON_DRIVER_FLAG_ATTR;
 }
 
 /**
@@ -3621,11 +3612,11 @@ static int do_register_con_driver(const struct consw *csw, int first, int last)
        if (retval)
                goto err;
 
-       con_driver->dev = device_create(vtconsole_class, NULL,
-                                               MKDEV(0, con_driver->node),
-                                               NULL, "vtcon%i",
-                                               con_driver->node);
-
+       con_driver->dev =
+               device_create_with_groups(vtconsole_class, NULL,
+                                         MKDEV(0, con_driver->node),
+                                         con_driver, con_dev_groups,
+                                         "vtcon%i", con_driver->node);
        if (IS_ERR(con_driver->dev)) {
                printk(KERN_WARNING "Unable to create device for %s; "
                       "errno = %ld\n", con_driver->desc,
@@ -3739,10 +3730,11 @@ static int __init vtconsole_class_init(void)
                struct con_driver *con = &registered_con_driver[i];
 
                if (con->con && !con->dev) {
-                       con->dev = device_create(vtconsole_class, NULL,
-                                                        MKDEV(0, con->node),
-                                                        NULL, "vtcon%i",
-                                                        con->node);
+                       con->dev =
+                               device_create_with_groups(vtconsole_class, NULL,
+                                                         MKDEV(0, con->node),
+                                                         con, con_dev_groups,
+                                                         "vtcon%i", con->node);
 
                        if (IS_ERR(con->dev)) {
                                printk(KERN_WARNING "Unable to create "
index 2bd78e2ac8ecba07dbf42788b6c61506ee8b2b20..97d5a74558a3a4477e3c5cfb29dd88591fefbe92 100644 (file)
@@ -388,7 +388,7 @@ int vt_ioctl(struct tty_struct *tty,
                 * Generate the tone for the appropriate number of ticks.
                 * If the time is zero, turn off sound ourselves.
                 */
-               ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
+               ticks = msecs_to_jiffies((arg >> 16) & 0xffff);
                count = ticks ? (arg & 0xffff) : 0;
                if (count)
                        count = PIT_TICK_RATE / count;
index 6276f13e9e126f8085fdc8949d0d8b784e4df14e..65bf0676d54afc785107822f51a696ae373a2702 100644 (file)
@@ -835,7 +835,15 @@ int __uio_register_device(struct module *owner,
        info->uio_dev = idev;
 
        if (info->irq && (info->irq != UIO_IRQ_CUSTOM)) {
-               ret = devm_request_irq(idev->dev, info->irq, uio_interrupt,
+               /*
+                * Note that we deliberately don't use devm_request_irq
+                * here. The parent module can unregister the UIO device
+                * and call pci_disable_msi, which requires that this
+                * irq has been freed. However, the device may have open
+                * FDs at the time of unregister and therefore may not be
+                * freed until they are released.
+                */
+               ret = request_irq(info->irq, uio_interrupt,
                                  info->irq_flags, info->name, idev);
                if (ret)
                        goto err_request_irq;
@@ -871,6 +879,8 @@ void uio_unregister_device(struct uio_info *info)
 
        uio_dev_del_attributes(idev);
 
+       free_irq(idev->info->irq, idev);
+
        device_destroy(&uio_class, MKDEV(uio_major, idev->minor));
 
        return;
index 083acf45ad5aba6cc9e0fe6c9c7d94b3e0fcd85c..19d655a743b55eb8e17f4308bc722a40bfe4e505 100644 (file)
@@ -520,7 +520,6 @@ static int ci_otg_start_host(struct otg_fsm *fsm, int on)
 {
        struct ci_hdrc  *ci = container_of(fsm, struct ci_hdrc, fsm);
 
-       mutex_unlock(&fsm->lock);
        if (on) {
                ci_role_stop(ci);
                ci_role_start(ci, CI_ROLE_HOST);
@@ -529,7 +528,6 @@ static int ci_otg_start_host(struct otg_fsm *fsm, int on)
                hw_device_reset(ci);
                ci_role_start(ci, CI_ROLE_GADGET);
        }
-       mutex_lock(&fsm->lock);
        return 0;
 }
 
@@ -537,12 +535,10 @@ static int ci_otg_start_gadget(struct otg_fsm *fsm, int on)
 {
        struct ci_hdrc  *ci = container_of(fsm, struct ci_hdrc, fsm);
 
-       mutex_unlock(&fsm->lock);
        if (on)
                usb_gadget_vbus_connect(&ci->gadget);
        else
                usb_gadget_vbus_disconnect(&ci->gadget);
-       mutex_lock(&fsm->lock);
 
        return 0;
 }
index 3e15add665e236f2ef15bd1a9858dd9eabcb0c96..5c8f58114677daa1c65d5bd46255b71e8fd7fe72 100644 (file)
@@ -1142,11 +1142,16 @@ static int acm_probe(struct usb_interface *intf,
        }
 
        while (buflen > 0) {
+               elength = buffer[0];
+               if (!elength) {
+                       dev_err(&intf->dev, "skipping garbage byte\n");
+                       elength = 1;
+                       goto next_desc;
+               }
                if (buffer[1] != USB_DT_CS_INTERFACE) {
                        dev_err(&intf->dev, "skipping garbage\n");
                        goto next_desc;
                }
-               elength = buffer[0];
 
                switch (buffer[2]) {
                case USB_CDC_UNION_TYPE: /* we've found it */
index 76891adfba7a414b87e5fd03252928e32492f7eb..cf0df8fbba890130f427e748a98736a4eee3a6aa 100644 (file)
@@ -222,7 +222,7 @@ uvc_function_ep0_complete(struct usb_ep *ep, struct usb_request *req)
                v4l2_event.type = UVC_EVENT_DATA;
                uvc_event->data.length = req->actual;
                memcpy(&uvc_event->data.data, req->buf, req->actual);
-               v4l2_event_queue(uvc->vdev, &v4l2_event);
+               v4l2_event_queue(&uvc->vdev, &v4l2_event);
        }
 }
 
@@ -256,7 +256,7 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
        memset(&v4l2_event, 0, sizeof(v4l2_event));
        v4l2_event.type = UVC_EVENT_SETUP;
        memcpy(&uvc_event->req, ctrl, sizeof(uvc_event->req));
-       v4l2_event_queue(uvc->vdev, &v4l2_event);
+       v4l2_event_queue(&uvc->vdev, &v4l2_event);
 
        return 0;
 }
@@ -315,7 +315,7 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
                        memset(&v4l2_event, 0, sizeof(v4l2_event));
                        v4l2_event.type = UVC_EVENT_CONNECT;
                        uvc_event->speed = cdev->gadget->speed;
-                       v4l2_event_queue(uvc->vdev, &v4l2_event);
+                       v4l2_event_queue(&uvc->vdev, &v4l2_event);
 
                        uvc->state = UVC_STATE_CONNECTED;
                }
@@ -343,7 +343,7 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
 
                memset(&v4l2_event, 0, sizeof(v4l2_event));
                v4l2_event.type = UVC_EVENT_STREAMOFF;
-               v4l2_event_queue(uvc->vdev, &v4l2_event);
+               v4l2_event_queue(&uvc->vdev, &v4l2_event);
 
                uvc->state = UVC_STATE_CONNECTED;
                return 0;
@@ -370,7 +370,7 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
 
                memset(&v4l2_event, 0, sizeof(v4l2_event));
                v4l2_event.type = UVC_EVENT_STREAMON;
-               v4l2_event_queue(uvc->vdev, &v4l2_event);
+               v4l2_event_queue(&uvc->vdev, &v4l2_event);
                return USB_GADGET_DELAYED_STATUS;
 
        default:
@@ -388,7 +388,7 @@ uvc_function_disable(struct usb_function *f)
 
        memset(&v4l2_event, 0, sizeof(v4l2_event));
        v4l2_event.type = UVC_EVENT_DISCONNECT;
-       v4l2_event_queue(uvc->vdev, &v4l2_event);
+       v4l2_event_queue(&uvc->vdev, &v4l2_event);
 
        uvc->state = UVC_STATE_DISCONNECTED;
 
@@ -435,24 +435,19 @@ static int
 uvc_register_video(struct uvc_device *uvc)
 {
        struct usb_composite_dev *cdev = uvc->func.config->cdev;
-       struct video_device *video;
 
        /* TODO reference counting. */
-       video = video_device_alloc();
-       if (video == NULL)
-               return -ENOMEM;
+       uvc->vdev.v4l2_dev = &uvc->v4l2_dev;
+       uvc->vdev.fops = &uvc_v4l2_fops;
+       uvc->vdev.ioctl_ops = &uvc_v4l2_ioctl_ops;
+       uvc->vdev.release = video_device_release_empty;
+       uvc->vdev.vfl_dir = VFL_DIR_TX;
+       uvc->vdev.lock = &uvc->video.mutex;
+       strlcpy(uvc->vdev.name, cdev->gadget->name, sizeof(uvc->vdev.name));
 
-       video->v4l2_dev = &uvc->v4l2_dev;
-       video->fops = &uvc_v4l2_fops;
-       video->ioctl_ops = &uvc_v4l2_ioctl_ops;
-       video->release = video_device_release;
-       video->vfl_dir = VFL_DIR_TX;
-       strlcpy(video->name, cdev->gadget->name, sizeof(video->name));
+       video_set_drvdata(&uvc->vdev, uvc);
 
-       uvc->vdev = video;
-       video_set_drvdata(video, uvc);
-
-       return video_register_device(video, VFL_TYPE_GRABBER, -1);
+       return video_register_device(&uvc->vdev, VFL_TYPE_GRABBER, -1);
 }
 
 #define UVC_COPY_DESCRIPTOR(mem, dst, desc) \
@@ -765,8 +760,6 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
 
 error:
        v4l2_device_unregister(&uvc->v4l2_dev);
-       if (uvc->vdev)
-               video_device_release(uvc->vdev);
 
        if (uvc->control_ep)
                uvc->control_ep->driver_data = NULL;
@@ -897,7 +890,7 @@ static void uvc_unbind(struct usb_configuration *c, struct usb_function *f)
 
        INFO(cdev, "%s\n", __func__);
 
-       video_unregister_device(uvc->vdev);
+       video_unregister_device(&uvc->vdev);
        v4l2_device_unregister(&uvc->v4l2_dev);
        uvc->control_ep->driver_data = NULL;
        uvc->video.ep->driver_data = NULL;
@@ -918,6 +911,7 @@ static struct usb_function *uvc_alloc(struct usb_function_instance *fi)
        if (uvc == NULL)
                return ERR_PTR(-ENOMEM);
 
+       mutex_init(&uvc->video.mutex);
        uvc->state = UVC_STATE_DISCONNECTED;
        opts = fi_to_f_uvc_opts(fi);
 
index f67695cb28f8a8429987beffd8aaf44a3bd0303c..ebe409b9e41992321bf026f14e2a37a240e4d524 100644 (file)
@@ -115,6 +115,7 @@ struct uvc_video
        unsigned int width;
        unsigned int height;
        unsigned int imagesize;
+       struct mutex mutex;     /* protects frame parameters */
 
        /* Requests */
        unsigned int req_size;
@@ -143,7 +144,7 @@ enum uvc_state
 
 struct uvc_device
 {
-       struct video_device *vdev;
+       struct video_device vdev;
        struct v4l2_device v4l2_dev;
        enum uvc_state state;
        struct usb_function func;
index 8ea8b3b227b497108815118a9f38f297f81b6df3..d617c39a00527414ea2561c3332a7c508f7b7815 100644 (file)
@@ -104,29 +104,16 @@ static void uvc_buffer_queue(struct vb2_buffer *vb)
        spin_unlock_irqrestore(&queue->irqlock, flags);
 }
 
-static void uvc_wait_prepare(struct vb2_queue *vq)
-{
-       struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
-
-       mutex_unlock(&queue->mutex);
-}
-
-static void uvc_wait_finish(struct vb2_queue *vq)
-{
-       struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
-
-       mutex_lock(&queue->mutex);
-}
-
 static struct vb2_ops uvc_queue_qops = {
        .queue_setup = uvc_queue_setup,
        .buf_prepare = uvc_buffer_prepare,
        .buf_queue = uvc_buffer_queue,
-       .wait_prepare = uvc_wait_prepare,
-       .wait_finish = uvc_wait_finish,
+       .wait_prepare = vb2_ops_wait_prepare,
+       .wait_finish = vb2_ops_wait_finish,
 };
 
-int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)
+int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
+                   struct mutex *lock)
 {
        int ret;
 
@@ -135,6 +122,7 @@ int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)
        queue->queue.drv_priv = queue;
        queue->queue.buf_struct_size = sizeof(struct uvc_buffer);
        queue->queue.ops = &uvc_queue_qops;
+       queue->queue.lock = lock;
        queue->queue.mem_ops = &vb2_vmalloc_memops;
        queue->queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC
                                     | V4L2_BUF_FLAG_TSTAMP_SRC_EOF;
@@ -142,7 +130,6 @@ int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)
        if (ret)
                return ret;
 
-       mutex_init(&queue->mutex);
        spin_lock_init(&queue->irqlock);
        INIT_LIST_HEAD(&queue->irqqueue);
        queue->flags = 0;
@@ -155,9 +142,7 @@ int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)
  */
 void uvcg_free_buffers(struct uvc_video_queue *queue)
 {
-       mutex_lock(&queue->mutex);
        vb2_queue_release(&queue->queue);
-       mutex_unlock(&queue->mutex);
 }
 
 /*
@@ -168,22 +153,14 @@ int uvcg_alloc_buffers(struct uvc_video_queue *queue,
 {
        int ret;
 
-       mutex_lock(&queue->mutex);
        ret = vb2_reqbufs(&queue->queue, rb);
-       mutex_unlock(&queue->mutex);
 
        return ret ? ret : rb->count;
 }
 
 int uvcg_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf)
 {
-       int ret;
-
-       mutex_lock(&queue->mutex);
-       ret = vb2_querybuf(&queue->queue, buf);
-       mutex_unlock(&queue->mutex);
-
-       return ret;
+       return vb2_querybuf(&queue->queue, buf);
 }
 
 int uvcg_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf)
@@ -191,18 +168,14 @@ int uvcg_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf)
        unsigned long flags;
        int ret;
 
-       mutex_lock(&queue->mutex);
        ret = vb2_qbuf(&queue->queue, buf);
        if (ret < 0)
-               goto done;
+               return ret;
 
        spin_lock_irqsave(&queue->irqlock, flags);
        ret = (queue->flags & UVC_QUEUE_PAUSED) != 0;
        queue->flags &= ~UVC_QUEUE_PAUSED;
        spin_unlock_irqrestore(&queue->irqlock, flags);
-
-done:
-       mutex_unlock(&queue->mutex);
        return ret;
 }
 
@@ -213,13 +186,7 @@ done:
 int uvcg_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf,
                        int nonblocking)
 {
-       int ret;
-
-       mutex_lock(&queue->mutex);
-       ret = vb2_dqbuf(&queue->queue, buf, nonblocking);
-       mutex_unlock(&queue->mutex);
-
-       return ret;
+       return vb2_dqbuf(&queue->queue, buf, nonblocking);
 }
 
 /*
@@ -231,24 +198,12 @@ int uvcg_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf,
 unsigned int uvcg_queue_poll(struct uvc_video_queue *queue, struct file *file,
                             poll_table *wait)
 {
-       unsigned int ret;
-
-       mutex_lock(&queue->mutex);
-       ret = vb2_poll(&queue->queue, file, wait);
-       mutex_unlock(&queue->mutex);
-
-       return ret;
+       return vb2_poll(&queue->queue, file, wait);
 }
 
 int uvcg_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
 {
-       int ret;
-
-       mutex_lock(&queue->mutex);
-       ret = vb2_mmap(&queue->queue, vma);
-       mutex_unlock(&queue->mutex);
-
-       return ret;
+       return vb2_mmap(&queue->queue, vma);
 }
 
 #ifndef CONFIG_MMU
@@ -260,12 +215,7 @@ int uvcg_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
 unsigned long uvcg_queue_get_unmapped_area(struct uvc_video_queue *queue,
                                           unsigned long pgoff)
 {
-       unsigned long ret;
-
-       mutex_lock(&queue->mutex);
-       ret = vb2_get_unmapped_area(&queue->queue, 0, 0, pgoff, 0);
-       mutex_unlock(&queue->mutex);
-       return ret;
+       return vb2_get_unmapped_area(&queue->queue, 0, 0, pgoff, 0);
 }
 #endif
 
@@ -327,18 +277,17 @@ int uvcg_queue_enable(struct uvc_video_queue *queue, int enable)
        unsigned long flags;
        int ret = 0;
 
-       mutex_lock(&queue->mutex);
        if (enable) {
                ret = vb2_streamon(&queue->queue, queue->queue.type);
                if (ret < 0)
-                       goto done;
+                       return ret;
 
                queue->sequence = 0;
                queue->buf_used = 0;
        } else {
                ret = vb2_streamoff(&queue->queue, queue->queue.type);
                if (ret < 0)
-                       goto done;
+                       return ret;
 
                spin_lock_irqsave(&queue->irqlock, flags);
                INIT_LIST_HEAD(&queue->irqqueue);
@@ -353,8 +302,6 @@ int uvcg_queue_enable(struct uvc_video_queue *queue, int enable)
                spin_unlock_irqrestore(&queue->irqlock, flags);
        }
 
-done:
-       mutex_unlock(&queue->mutex);
        return ret;
 }
 
index 03919c7249615adec90485ab42dd81f1fe5abd38..01ca9eab3481d4550f3d2a1fc99eafd547327a5c 100644 (file)
@@ -41,7 +41,6 @@ struct uvc_buffer {
 
 struct uvc_video_queue {
        struct vb2_queue queue;
-       struct mutex mutex;     /* Protects queue */
 
        unsigned int flags;
        __u32 sequence;
@@ -57,7 +56,8 @@ static inline int uvc_queue_streaming(struct uvc_video_queue *queue)
        return vb2_is_streaming(&queue->queue);
 }
 
-int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type);
+int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
+                   struct mutex *lock);
 
 void uvcg_free_buffers(struct uvc_video_queue *queue);
 
index 8b818fd027b3380772030c2a650c67df830a4e56..f4ccbd56f4d254c42112f3ae89949aefe6d5c8d1 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/list.h>
-#include <linux/mutex.h>
 #include <linux/videodev2.h>
 #include <linux/vmalloc.h>
 #include <linux/wait.h>
@@ -77,7 +76,8 @@ uvc_v4l2_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
        strlcpy(cap->bus_info, dev_name(&cdev->gadget->dev),
                sizeof(cap->bus_info));
 
-       cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
+       cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
+       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
 
        return 0;
 }
@@ -312,8 +312,10 @@ uvc_v4l2_release(struct file *file)
 
        uvc_function_disconnect(uvc);
 
+       mutex_lock(&video->mutex);
        uvcg_video_enable(video, 0);
        uvcg_free_buffers(&video->queue);
+       mutex_unlock(&video->mutex);
 
        file->private_data = NULL;
        v4l2_fh_del(&handle->vfh);
@@ -357,7 +359,7 @@ struct v4l2_file_operations uvc_v4l2_fops = {
        .owner          = THIS_MODULE,
        .open           = uvc_v4l2_open,
        .release        = uvc_v4l2_release,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .mmap           = uvc_v4l2_mmap,
        .poll           = uvc_v4l2_poll,
 #ifndef CONFIG_MMU
index 50a5e637ca35ad804925112675e54b2ee115b80f..3d0d5d94a62f2fe6927983ba6979784eb20eceeb 100644 (file)
@@ -391,7 +391,8 @@ int uvcg_video_init(struct uvc_video *video)
        video->imagesize = 320 * 240 * 2;
 
        /* Initialize the video buffers queue. */
-       uvcg_queue_init(&video->queue, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+       uvcg_queue_init(&video->queue, V4L2_BUF_TYPE_VIDEO_OUTPUT,
+                       &video->mutex);
        return 0;
 }
 
index 6af58c6dba5ebe7ea134197537864b95c8bfe002..2030565c6789031af2a903df9e6e12b5053a293a 100644 (file)
@@ -1505,7 +1505,7 @@ static void destroy_ep_files (struct dev_data *dev)
                list_del_init (&ep->epfiles);
                dentry = ep->dentry;
                ep->dentry = NULL;
-               parent = dentry->d_parent->d_inode;
+               parent = d_inode(dentry->d_parent);
 
                /* break link to controller */
                if (ep->state == STATE_EP_ENABLED)
index 6e0a019aad54ae7a209f03355ae50d7c1e0cdb29..8b80addc4ce6a5aaae4a330f4e27abd3ea67c5f8 100644 (file)
@@ -29,7 +29,7 @@
 
 USB_GADGET_COMPOSITE_OPTIONS();
 
-static struct target_fabric_configfs *usbg_fabric_configfs;
+static const struct target_core_fabric_ops usbg_ops;
 
 static inline struct f_uas *to_f_uas(struct usb_function *f)
 {
@@ -1572,8 +1572,7 @@ static struct se_portal_group *usbg_make_tpg(
        tpg->tport = tport;
        tpg->tport_tpgt = tpgt;
 
-       ret = core_tpg_register(&usbg_fabric_configfs->tf_ops, wwn,
-                               &tpg->se_tpg, tpg,
+       ret = core_tpg_register(&usbg_ops, wwn, &tpg->se_tpg, tpg,
                                TRANSPORT_TPG_TYPE_NORMAL);
        if (ret < 0) {
                destroy_workqueue(tpg->workqueue);
@@ -1864,7 +1863,9 @@ static int usbg_check_stop_free(struct se_cmd *se_cmd)
        return 1;
 }
 
-static struct target_core_fabric_ops usbg_ops = {
+static const struct target_core_fabric_ops usbg_ops = {
+       .module                         = THIS_MODULE,
+       .name                           = "usb_gadget",
        .get_fabric_name                = usbg_get_fabric_name,
        .get_fabric_proto_ident         = usbg_get_fabric_proto_ident,
        .tpg_get_wwn                    = usbg_get_fabric_wwn,
@@ -1906,46 +1907,9 @@ static struct target_core_fabric_ops usbg_ops = {
        .fabric_drop_np                 = NULL,
        .fabric_make_nodeacl            = usbg_make_nodeacl,
        .fabric_drop_nodeacl            = usbg_drop_nodeacl,
-};
-
-static int usbg_register_configfs(void)
-{
-       struct target_fabric_configfs *fabric;
-       int ret;
-
-       fabric = target_fabric_configfs_init(THIS_MODULE, "usb_gadget");
-       if (IS_ERR(fabric)) {
-               printk(KERN_ERR "target_fabric_configfs_init() failed\n");
-               return PTR_ERR(fabric);
-       }
-
-       fabric->tf_ops = usbg_ops;
-       fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = usbg_wwn_attrs;
-       fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = usbg_base_attrs;
-       fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_nacl_base_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_nacl_auth_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_nacl_param_cit.ct_attrs = NULL;
-       ret = target_fabric_configfs_register(fabric);
-       if (ret < 0) {
-               printk(KERN_ERR "target_fabric_configfs_register() failed"
-                               " for usb-gadget\n");
-               return ret;
-       }
-       usbg_fabric_configfs = fabric;
-       return 0;
-};
 
-static void usbg_deregister_configfs(void)
-{
-       if (!(usbg_fabric_configfs))
-               return;
-
-       target_fabric_configfs_deregister(usbg_fabric_configfs);
-       usbg_fabric_configfs = NULL;
+       .tfc_wwn_attrs                  = usbg_wwn_attrs,
+       .tfc_tpg_base_attrs             = usbg_base_attrs,
 };
 
 /* Start gadget.c code */
@@ -2454,16 +2418,13 @@ static void usbg_detach(struct usbg_tpg *tpg)
 
 static int __init usb_target_gadget_init(void)
 {
-       int ret;
-
-       ret = usbg_register_configfs();
-       return ret;
+       return target_register_template(&usbg_ops);
 }
 module_init(usb_target_gadget_init);
 
 static void __exit usb_target_gadget_exit(void)
 {
-       usbg_deregister_configfs();
+       target_unregister_template(&usbg_ops);
 }
 module_exit(usb_target_gadget_exit);
 
index 9db74ca7e5b98224dd9889a3a09e3a8e4941668c..275c92e53a5972615166310742b63af0a8d61cf5 100644 (file)
@@ -88,13 +88,20 @@ static int ehci_msm_probe(struct platform_device *pdev)
        }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       hcd->regs = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(hcd->regs)) {
-               ret = PTR_ERR(hcd->regs);
+       if (!res) {
+               dev_err(&pdev->dev, "Unable to get memory resource\n");
+               ret = -ENODEV;
                goto put_hcd;
        }
+
        hcd->rsrc_start = res->start;
        hcd->rsrc_len = resource_size(res);
+       hcd->regs = devm_ioremap(&pdev->dev, hcd->rsrc_start, hcd->rsrc_len);
+       if (!hcd->regs) {
+               dev_err(&pdev->dev, "ioremap failed\n");
+               ret = -ENOMEM;
+               goto put_hcd;
+       }
 
        /*
         * OTG driver takes care of PHY initialization, clock management,
index 9893d696fc973e9e4183b57b56b3ceb22570942f..f58caa9e6a27e6e1a7161a66e5e9a97698cc1e1a 100644 (file)
@@ -51,7 +51,8 @@ static int uas_find_endpoints(struct usb_host_interface *alt,
 }
 
 static int uas_use_uas_driver(struct usb_interface *intf,
-                             const struct usb_device_id *id)
+                             const struct usb_device_id *id,
+                             unsigned long *flags_ret)
 {
        struct usb_host_endpoint *eps[4] = { };
        struct usb_device *udev = interface_to_usbdev(intf);
@@ -73,7 +74,7 @@ static int uas_use_uas_driver(struct usb_interface *intf,
         * this writing the following versions exist:
         * ASM1051 - no uas support version
         * ASM1051 - with broken (*) uas support
-        * ASM1053 - with working uas support
+        * ASM1053 - with working uas support, but problems with large xfers
         * ASM1153 - with working uas support
         *
         * Devices with these chips re-use a number of device-ids over the
@@ -103,6 +104,9 @@ static int uas_use_uas_driver(struct usb_interface *intf,
                } else if (usb_ss_max_streams(&eps[1]->ss_ep_comp) == 32) {
                        /* Possibly an ASM1051, disable uas */
                        flags |= US_FL_IGNORE_UAS;
+               } else {
+                       /* ASM1053, these have issues with large transfers */
+                       flags |= US_FL_MAX_SECTORS_240;
                }
        }
 
@@ -132,5 +136,8 @@ static int uas_use_uas_driver(struct usb_interface *intf,
                return 0;
        }
 
+       if (flags_ret)
+               *flags_ret = flags;
+
        return 1;
 }
index 6cdabdc119a73bc172d5b2e52f024113bde09d3b..6d3122afeed33e9cfe1b571c3acaf19dac967da4 100644 (file)
@@ -759,7 +759,10 @@ static int uas_eh_bus_reset_handler(struct scsi_cmnd *cmnd)
 
 static int uas_slave_alloc(struct scsi_device *sdev)
 {
-       sdev->hostdata = (void *)sdev->host->hostdata;
+       struct uas_dev_info *devinfo =
+               (struct uas_dev_info *)sdev->host->hostdata;
+
+       sdev->hostdata = devinfo;
 
        /* USB has unusual DMA-alignment requirements: Although the
         * starting address of each scatter-gather element doesn't matter,
@@ -778,6 +781,11 @@ static int uas_slave_alloc(struct scsi_device *sdev)
         */
        blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1));
 
+       if (devinfo->flags & US_FL_MAX_SECTORS_64)
+               blk_queue_max_hw_sectors(sdev->request_queue, 64);
+       else if (devinfo->flags & US_FL_MAX_SECTORS_240)
+               blk_queue_max_hw_sectors(sdev->request_queue, 240);
+
        return 0;
 }
 
@@ -887,8 +895,9 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
        struct Scsi_Host *shost = NULL;
        struct uas_dev_info *devinfo;
        struct usb_device *udev = interface_to_usbdev(intf);
+       unsigned long dev_flags;
 
-       if (!uas_use_uas_driver(intf, id))
+       if (!uas_use_uas_driver(intf, id, &dev_flags))
                return -ENODEV;
 
        if (uas_switch_interface(udev, intf))
@@ -910,8 +919,7 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
        devinfo->udev = udev;
        devinfo->resetting = 0;
        devinfo->shutdown = 0;
-       devinfo->flags = id->driver_info;
-       usb_stor_adjust_quirks(udev, &devinfo->flags);
+       devinfo->flags = dev_flags;
        init_usb_anchor(&devinfo->cmd_urbs);
        init_usb_anchor(&devinfo->sense_urbs);
        init_usb_anchor(&devinfo->data_urbs);
index 5600c33fcadb219e52e8f985bf692c6ff3a1025e..6c10c888f35fb976b94b1ea3fddd61c4bcabe520 100644 (file)
@@ -479,7 +479,8 @@ void usb_stor_adjust_quirks(struct usb_device *udev, unsigned long *fflags)
                        US_FL_SINGLE_LUN | US_FL_NO_WP_DETECT |
                        US_FL_NO_READ_DISC_INFO | US_FL_NO_READ_CAPACITY_16 |
                        US_FL_INITIAL_READ10 | US_FL_WRITE_CACHE |
-                       US_FL_NO_ATA_1X | US_FL_NO_REPORT_OPCODES);
+                       US_FL_NO_ATA_1X | US_FL_NO_REPORT_OPCODES |
+                       US_FL_MAX_SECTORS_240);
 
        p = quirks;
        while (*p) {
@@ -520,6 +521,9 @@ void usb_stor_adjust_quirks(struct usb_device *udev, unsigned long *fflags)
                case 'f':
                        f |= US_FL_NO_REPORT_OPCODES;
                        break;
+               case 'g':
+                       f |= US_FL_MAX_SECTORS_240;
+                       break;
                case 'h':
                        f |= US_FL_CAPACITY_HEURISTICS;
                        break;
@@ -1080,7 +1084,7 @@ static int storage_probe(struct usb_interface *intf,
 
        /* If uas is enabled and this device can do uas then ignore it. */
 #if IS_ENABLED(CONFIG_USB_UAS)
-       if (uas_use_uas_driver(intf, id))
+       if (uas_use_uas_driver(intf, id, NULL))
                return -ENXIO;
 #endif
 
index 69fab0fd15aec4a5cb05c870984dc7e4bc9dcad4..e9851add6f4ef251defba65a3bab9af359b60b3a 100644 (file)
@@ -907,8 +907,14 @@ static void vfio_pci_request(void *device_data, unsigned int count)
        mutex_lock(&vdev->igate);
 
        if (vdev->req_trigger) {
-               dev_dbg(&vdev->pdev->dev, "Requesting device from user\n");
+               if (!(count % 10))
+                       dev_notice_ratelimited(&vdev->pdev->dev,
+                               "Relaying device request to user (#%u)\n",
+                               count);
                eventfd_signal(vdev->req_trigger, 1);
+       } else if (count == 0) {
+               dev_warn(&vdev->pdev->dev,
+                       "No device request channel registered, blocked until released by user\n");
        }
 
        mutex_unlock(&vdev->igate);
index 0d336625ac7113b0e0cc10d4a9d00283cc673766..e1278fe04b1e7ba16eddbece247c21620b6e8fb7 100644 (file)
@@ -710,6 +710,8 @@ void *vfio_del_group_dev(struct device *dev)
        void *device_data = device->device_data;
        struct vfio_unbound_dev *unbound;
        unsigned int i = 0;
+       long ret;
+       bool interrupted = false;
 
        /*
         * The group exists so long as we have a device reference.  Get
@@ -755,9 +757,22 @@ void *vfio_del_group_dev(struct device *dev)
 
                vfio_device_put(device);
 
-       } while (wait_event_interruptible_timeout(vfio.release_q,
-                                                 !vfio_dev_present(group, dev),
-                                                 HZ * 10) <= 0);
+               if (interrupted) {
+                       ret = wait_event_timeout(vfio.release_q,
+                                       !vfio_dev_present(group, dev), HZ * 10);
+               } else {
+                       ret = wait_event_interruptible_timeout(vfio.release_q,
+                                       !vfio_dev_present(group, dev), HZ * 10);
+                       if (ret == -ERESTARTSYS) {
+                               interrupted = true;
+                               dev_warn(dev,
+                                        "Device is currently in use, task"
+                                        " \"%s\" (%d) "
+                                        "blocked until device is released",
+                                        current->comm, task_pid_nr(current));
+                       }
+               }
+       } while (ret <= 0);
 
        vfio_group_put(group);
 
index 71df240a467a10bef98c6314ba8d6031fa8e3bf6..5e19bb53b3a99a4ccc93696bf9792a4f4f1ad7c4 100644 (file)
@@ -131,6 +131,8 @@ struct vhost_scsi_tpg {
        int tv_tpg_port_count;
        /* Used for vhost_scsi device reference to tpg_nexus, protected by tv_tpg_mutex */
        int tv_tpg_vhost_count;
+       /* Used for enabling T10-PI with legacy devices */
+       int tv_fabric_prot_type;
        /* list for vhost_scsi_list */
        struct list_head tv_tpg_list;
        /* Used to protect access for tpg_nexus */
@@ -214,9 +216,7 @@ struct vhost_scsi {
        int vs_events_nr; /* num of pending events, protected by vq->mutex */
 };
 
-/* Local pointer to allocated TCM configfs fabric module */
-static struct target_fabric_configfs *vhost_scsi_fabric_configfs;
-
+static struct target_core_fabric_ops vhost_scsi_ops;
 static struct workqueue_struct *vhost_scsi_workqueue;
 
 /* Global spinlock to protect vhost_scsi TPG list for vhost IOCTL access */
@@ -431,6 +431,14 @@ vhost_scsi_parse_pr_out_transport_id(struct se_portal_group *se_tpg,
                        port_nexus_ptr);
 }
 
+static int vhost_scsi_check_prot_fabric_only(struct se_portal_group *se_tpg)
+{
+       struct vhost_scsi_tpg *tpg = container_of(se_tpg,
+                               struct vhost_scsi_tpg, se_tpg);
+
+       return tpg->tv_fabric_prot_type;
+}
+
 static struct se_node_acl *
 vhost_scsi_alloc_fabric_acl(struct se_portal_group *se_tpg)
 {
@@ -1878,6 +1886,45 @@ static void vhost_scsi_free_cmd_map_res(struct vhost_scsi_nexus *nexus,
        }
 }
 
+static ssize_t vhost_scsi_tpg_attrib_store_fabric_prot_type(
+       struct se_portal_group *se_tpg,
+       const char *page,
+       size_t count)
+{
+       struct vhost_scsi_tpg *tpg = container_of(se_tpg,
+                               struct vhost_scsi_tpg, se_tpg);
+       unsigned long val;
+       int ret = kstrtoul(page, 0, &val);
+
+       if (ret) {
+               pr_err("kstrtoul() returned %d for fabric_prot_type\n", ret);
+               return ret;
+       }
+       if (val != 0 && val != 1 && val != 3) {
+               pr_err("Invalid vhost_scsi fabric_prot_type: %lu\n", val);
+               return -EINVAL;
+       }
+       tpg->tv_fabric_prot_type = val;
+
+       return count;
+}
+
+static ssize_t vhost_scsi_tpg_attrib_show_fabric_prot_type(
+       struct se_portal_group *se_tpg,
+       char *page)
+{
+       struct vhost_scsi_tpg *tpg = container_of(se_tpg,
+                               struct vhost_scsi_tpg, se_tpg);
+
+       return sprintf(page, "%d\n", tpg->tv_fabric_prot_type);
+}
+TF_TPG_ATTRIB_ATTR(vhost_scsi, fabric_prot_type, S_IRUGO | S_IWUSR);
+
+static struct configfs_attribute *vhost_scsi_tpg_attrib_attrs[] = {
+       &vhost_scsi_tpg_attrib_fabric_prot_type.attr,
+       NULL,
+};
+
 static int vhost_scsi_make_nexus(struct vhost_scsi_tpg *tpg,
                                const char *name)
 {
@@ -2155,7 +2202,7 @@ vhost_scsi_make_tpg(struct se_wwn *wwn,
        tpg->tport = tport;
        tpg->tport_tpgt = tpgt;
 
-       ret = core_tpg_register(&vhost_scsi_fabric_configfs->tf_ops, wwn,
+       ret = core_tpg_register(&vhost_scsi_ops, wwn,
                                &tpg->se_tpg, tpg, TRANSPORT_TPG_TYPE_NORMAL);
        if (ret < 0) {
                kfree(tpg);
@@ -2277,6 +2324,8 @@ static struct configfs_attribute *vhost_scsi_wwn_attrs[] = {
 };
 
 static struct target_core_fabric_ops vhost_scsi_ops = {
+       .module                         = THIS_MODULE,
+       .name                           = "vhost",
        .get_fabric_name                = vhost_scsi_get_fabric_name,
        .get_fabric_proto_ident         = vhost_scsi_get_fabric_proto_ident,
        .tpg_get_wwn                    = vhost_scsi_get_fabric_wwn,
@@ -2289,6 +2338,7 @@ static struct target_core_fabric_ops vhost_scsi_ops = {
        .tpg_check_demo_mode_cache      = vhost_scsi_check_true,
        .tpg_check_demo_mode_write_protect = vhost_scsi_check_false,
        .tpg_check_prod_mode_write_protect = vhost_scsi_check_false,
+       .tpg_check_prot_fabric_only     = vhost_scsi_check_prot_fabric_only,
        .tpg_alloc_fabric_acl           = vhost_scsi_alloc_fabric_acl,
        .tpg_release_fabric_acl         = vhost_scsi_release_fabric_acl,
        .tpg_get_inst_index             = vhost_scsi_tpg_get_inst_index,
@@ -2320,70 +2370,20 @@ static struct target_core_fabric_ops vhost_scsi_ops = {
        .fabric_drop_np                 = NULL,
        .fabric_make_nodeacl            = vhost_scsi_make_nodeacl,
        .fabric_drop_nodeacl            = vhost_scsi_drop_nodeacl,
+
+       .tfc_wwn_attrs                  = vhost_scsi_wwn_attrs,
+       .tfc_tpg_base_attrs             = vhost_scsi_tpg_attrs,
+       .tfc_tpg_attrib_attrs           = vhost_scsi_tpg_attrib_attrs,
 };
 
-static int vhost_scsi_register_configfs(void)
+static int __init vhost_scsi_init(void)
 {
-       struct target_fabric_configfs *fabric;
-       int ret;
+       int ret = -ENOMEM;
 
-       pr_debug("vhost-scsi fabric module %s on %s/%s"
+       pr_debug("TCM_VHOST fabric module %s on %s/%s"
                " on "UTS_RELEASE"\n", VHOST_SCSI_VERSION, utsname()->sysname,
                utsname()->machine);
-       /*
-        * Register the top level struct config_item_type with TCM core
-        */
-       fabric = target_fabric_configfs_init(THIS_MODULE, "vhost");
-       if (IS_ERR(fabric)) {
-               pr_err("target_fabric_configfs_init() failed\n");
-               return PTR_ERR(fabric);
-       }
-       /*
-        * Setup fabric->tf_ops from our local vhost_scsi_ops
-        */
-       fabric->tf_ops = vhost_scsi_ops;
-       /*
-        * Setup default attribute lists for various fabric->tf_cit_tmpl
-        */
-       fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = vhost_scsi_wwn_attrs;
-       fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = vhost_scsi_tpg_attrs;
-       fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_nacl_base_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_nacl_auth_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_nacl_param_cit.ct_attrs = NULL;
-       /*
-        * Register the fabric for use within TCM
-        */
-       ret = target_fabric_configfs_register(fabric);
-       if (ret < 0) {
-               pr_err("target_fabric_configfs_register() failed"
-                               " for TCM_VHOST\n");
-               return ret;
-       }
-       /*
-        * Setup our local pointer to *fabric
-        */
-       vhost_scsi_fabric_configfs = fabric;
-       pr_debug("TCM_VHOST[0] - Set fabric -> vhost_scsi_fabric_configfs\n");
-       return 0;
-};
-
-static void vhost_scsi_deregister_configfs(void)
-{
-       if (!vhost_scsi_fabric_configfs)
-               return;
-
-       target_fabric_configfs_deregister(vhost_scsi_fabric_configfs);
-       vhost_scsi_fabric_configfs = NULL;
-       pr_debug("TCM_VHOST[0] - Cleared vhost_scsi_fabric_configfs\n");
-};
 
-static int __init vhost_scsi_init(void)
-{
-       int ret = -ENOMEM;
        /*
         * Use our own dedicated workqueue for submitting I/O into
         * target core to avoid contention within system_wq.
@@ -2396,7 +2396,7 @@ static int __init vhost_scsi_init(void)
        if (ret < 0)
                goto out_destroy_workqueue;
 
-       ret = vhost_scsi_register_configfs();
+       ret = target_register_template(&vhost_scsi_ops);
        if (ret < 0)
                goto out_vhost_scsi_deregister;
 
@@ -2412,7 +2412,7 @@ out:
 
 static void vhost_scsi_exit(void)
 {
-       vhost_scsi_deregister_configfs();
+       target_unregister_template(&vhost_scsi_ops);
        vhost_scsi_deregister();
        destroy_workqueue(vhost_scsi_workqueue);
 };
index b546da5d8ea32312cf1c93a4164ffb37c34e7272..cab9f3f63a38929b0634ae05fc3bc7d2ce4a3dd4 100644 (file)
@@ -48,6 +48,16 @@ config VIRTIO_BALLOON
 
         If unsure, say M.
 
+config VIRTIO_INPUT
+       tristate "Virtio input driver"
+       depends on VIRTIO
+       depends on INPUT
+       ---help---
+        This driver supports virtio input devices such as
+        keyboards, mice and tablets.
+
+        If unsure, say M.
+
  config VIRTIO_MMIO
        tristate "Platform bus driver for memory mapped virtio devices"
        depends on HAS_IOMEM
index d85565b8ea46dd3f0ccfb6a0ed8c33418483a9f3..41e30e3dc842835aae20aa41596ad2edc40ae27e 100644 (file)
@@ -4,3 +4,4 @@ obj-$(CONFIG_VIRTIO_PCI) += virtio_pci.o
 virtio_pci-y := virtio_pci_modern.o virtio_pci_common.o
 virtio_pci-$(CONFIG_VIRTIO_PCI_LEGACY) += virtio_pci_legacy.o
 obj-$(CONFIG_VIRTIO_BALLOON) += virtio_balloon.o
+obj-$(CONFIG_VIRTIO_INPUT) += virtio_input.o
index 5ce2aa48fc6e0943031f28c2a51d639e71b52f36..b1877d73fa563d6d48f2d55b7958f02daa8d9ad7 100644 (file)
@@ -278,12 +278,6 @@ static struct bus_type virtio_bus = {
        .remove = virtio_dev_remove,
 };
 
-bool virtio_device_is_legacy_only(struct virtio_device_id id)
-{
-       return id.device == VIRTIO_ID_BALLOON;
-}
-EXPORT_SYMBOL_GPL(virtio_device_is_legacy_only);
-
 int register_virtio_driver(struct virtio_driver *driver)
 {
        /* Catch this early. */
index 6a356e344f82c3d5b594abeeb47c453e868c4f9f..82e80e034f250b88993af25bb27434c2a78f8204 100644 (file)
@@ -214,8 +214,8 @@ static inline void update_stat(struct virtio_balloon *vb, int idx,
                               u16 tag, u64 val)
 {
        BUG_ON(idx >= VIRTIO_BALLOON_S_NR);
-       vb->stats[idx].tag = tag;
-       vb->stats[idx].val = val;
+       vb->stats[idx].tag = cpu_to_virtio16(vb->vdev, tag);
+       vb->stats[idx].val = cpu_to_virtio64(vb->vdev, val);
 }
 
 #define pages_to_bytes(x) ((u64)(x) << PAGE_SHIFT)
@@ -283,18 +283,27 @@ static void virtballoon_changed(struct virtio_device *vdev)
 
 static inline s64 towards_target(struct virtio_balloon *vb)
 {
-       __le32 v;
        s64 target;
+       u32 num_pages;
 
-       virtio_cread(vb->vdev, struct virtio_balloon_config, num_pages, &v);
+       virtio_cread(vb->vdev, struct virtio_balloon_config, num_pages,
+                    &num_pages);
 
-       target = le32_to_cpu(v);
+       /* Legacy balloon config space is LE, unlike all other devices. */
+       if (!virtio_has_feature(vb->vdev, VIRTIO_F_VERSION_1))
+               num_pages = le32_to_cpu((__force __le32)num_pages);
+
+       target = num_pages;
        return target - vb->num_pages;
 }
 
 static void update_balloon_size(struct virtio_balloon *vb)
 {
-       __le32 actual = cpu_to_le32(vb->num_pages);
+       u32 actual = vb->num_pages;
+
+       /* Legacy balloon config space is LE, unlike all other devices. */
+       if (!virtio_has_feature(vb->vdev, VIRTIO_F_VERSION_1))
+               actual = (__force u32)cpu_to_le32(actual);
 
        virtio_cwrite(vb->vdev, struct virtio_balloon_config, actual,
                      &actual);
diff --git a/drivers/virtio/virtio_input.c b/drivers/virtio/virtio_input.c
new file mode 100644 (file)
index 0000000..60e2a16
--- /dev/null
@@ -0,0 +1,384 @@
+#include <linux/module.h>
+#include <linux/virtio.h>
+#include <linux/virtio_config.h>
+#include <linux/input.h>
+
+#include <uapi/linux/virtio_ids.h>
+#include <uapi/linux/virtio_input.h>
+
+struct virtio_input {
+       struct virtio_device       *vdev;
+       struct input_dev           *idev;
+       char                       name[64];
+       char                       serial[64];
+       char                       phys[64];
+       struct virtqueue           *evt, *sts;
+       struct virtio_input_event  evts[64];
+       spinlock_t                 lock;
+       bool                       ready;
+};
+
+static void virtinput_queue_evtbuf(struct virtio_input *vi,
+                                  struct virtio_input_event *evtbuf)
+{
+       struct scatterlist sg[1];
+
+       sg_init_one(sg, evtbuf, sizeof(*evtbuf));
+       virtqueue_add_inbuf(vi->evt, sg, 1, evtbuf, GFP_ATOMIC);
+}
+
+static void virtinput_recv_events(struct virtqueue *vq)
+{
+       struct virtio_input *vi = vq->vdev->priv;
+       struct virtio_input_event *event;
+       unsigned long flags;
+       unsigned int len;
+
+       spin_lock_irqsave(&vi->lock, flags);
+       if (vi->ready) {
+               while ((event = virtqueue_get_buf(vi->evt, &len)) != NULL) {
+                       spin_unlock_irqrestore(&vi->lock, flags);
+                       input_event(vi->idev,
+                                   le16_to_cpu(event->type),
+                                   le16_to_cpu(event->code),
+                                   le32_to_cpu(event->value));
+                       spin_lock_irqsave(&vi->lock, flags);
+                       virtinput_queue_evtbuf(vi, event);
+               }
+               virtqueue_kick(vq);
+       }
+       spin_unlock_irqrestore(&vi->lock, flags);
+}
+
+/*
+ * On error we are losing the status update, which isn't critical as
+ * this is typically used for stuff like keyboard leds.
+ */
+static int virtinput_send_status(struct virtio_input *vi,
+                                u16 type, u16 code, s32 value)
+{
+       struct virtio_input_event *stsbuf;
+       struct scatterlist sg[1];
+       unsigned long flags;
+       int rc;
+
+       stsbuf = kzalloc(sizeof(*stsbuf), GFP_ATOMIC);
+       if (!stsbuf)
+               return -ENOMEM;
+
+       stsbuf->type  = cpu_to_le16(type);
+       stsbuf->code  = cpu_to_le16(code);
+       stsbuf->value = cpu_to_le32(value);
+       sg_init_one(sg, stsbuf, sizeof(*stsbuf));
+
+       spin_lock_irqsave(&vi->lock, flags);
+       if (vi->ready) {
+               rc = virtqueue_add_outbuf(vi->sts, sg, 1, stsbuf, GFP_ATOMIC);
+               virtqueue_kick(vi->sts);
+       } else {
+               rc = -ENODEV;
+       }
+       spin_unlock_irqrestore(&vi->lock, flags);
+
+       if (rc != 0)
+               kfree(stsbuf);
+       return rc;
+}
+
+static void virtinput_recv_status(struct virtqueue *vq)
+{
+       struct virtio_input *vi = vq->vdev->priv;
+       struct virtio_input_event *stsbuf;
+       unsigned long flags;
+       unsigned int len;
+
+       spin_lock_irqsave(&vi->lock, flags);
+       while ((stsbuf = virtqueue_get_buf(vi->sts, &len)) != NULL)
+               kfree(stsbuf);
+       spin_unlock_irqrestore(&vi->lock, flags);
+}
+
+static int virtinput_status(struct input_dev *idev, unsigned int type,
+                           unsigned int code, int value)
+{
+       struct virtio_input *vi = input_get_drvdata(idev);
+
+       return virtinput_send_status(vi, type, code, value);
+}
+
+static u8 virtinput_cfg_select(struct virtio_input *vi,
+                              u8 select, u8 subsel)
+{
+       u8 size;
+
+       virtio_cwrite(vi->vdev, struct virtio_input_config, select, &select);
+       virtio_cwrite(vi->vdev, struct virtio_input_config, subsel, &subsel);
+       virtio_cread(vi->vdev, struct virtio_input_config, size, &size);
+       return size;
+}
+
+static void virtinput_cfg_bits(struct virtio_input *vi, int select, int subsel,
+                              unsigned long *bits, unsigned int bitcount)
+{
+       unsigned int bit;
+       u8 *virtio_bits;
+       u8 bytes;
+
+       bytes = virtinput_cfg_select(vi, select, subsel);
+       if (!bytes)
+               return;
+       if (bitcount > bytes * 8)
+               bitcount = bytes * 8;
+
+       /*
+        * Bitmap in virtio config space is a simple stream of bytes,
+        * with the first byte carrying bits 0-7, second bits 8-15 and
+        * so on.
+        */
+       virtio_bits = kzalloc(bytes, GFP_KERNEL);
+       if (!virtio_bits)
+               return;
+       virtio_cread_bytes(vi->vdev, offsetof(struct virtio_input_config,
+                                             u.bitmap),
+                          virtio_bits, bytes);
+       for (bit = 0; bit < bitcount; bit++) {
+               if (virtio_bits[bit / 8] & (1 << (bit % 8)))
+                       __set_bit(bit, bits);
+       }
+       kfree(virtio_bits);
+
+       if (select == VIRTIO_INPUT_CFG_EV_BITS)
+               __set_bit(subsel, vi->idev->evbit);
+}
+
+static void virtinput_cfg_abs(struct virtio_input *vi, int abs)
+{
+       u32 mi, ma, re, fu, fl;
+
+       virtinput_cfg_select(vi, VIRTIO_INPUT_CFG_ABS_INFO, abs);
+       virtio_cread(vi->vdev, struct virtio_input_config, u.abs.min, &mi);
+       virtio_cread(vi->vdev, struct virtio_input_config, u.abs.max, &ma);
+       virtio_cread(vi->vdev, struct virtio_input_config, u.abs.res, &re);
+       virtio_cread(vi->vdev, struct virtio_input_config, u.abs.fuzz, &fu);
+       virtio_cread(vi->vdev, struct virtio_input_config, u.abs.flat, &fl);
+       input_set_abs_params(vi->idev, abs, mi, ma, fu, fl);
+       input_abs_set_res(vi->idev, abs, re);
+}
+
+static int virtinput_init_vqs(struct virtio_input *vi)
+{
+       struct virtqueue *vqs[2];
+       vq_callback_t *cbs[] = { virtinput_recv_events,
+                                virtinput_recv_status };
+       static const char *names[] = { "events", "status" };
+       int err;
+
+       err = vi->vdev->config->find_vqs(vi->vdev, 2, vqs, cbs, names);
+       if (err)
+               return err;
+       vi->evt = vqs[0];
+       vi->sts = vqs[1];
+
+       return 0;
+}
+
+static void virtinput_fill_evt(struct virtio_input *vi)
+{
+       unsigned long flags;
+       int i, size;
+
+       spin_lock_irqsave(&vi->lock, flags);
+       size = virtqueue_get_vring_size(vi->evt);
+       if (size > ARRAY_SIZE(vi->evts))
+               size = ARRAY_SIZE(vi->evts);
+       for (i = 0; i < size; i++)
+               virtinput_queue_evtbuf(vi, &vi->evts[i]);
+       virtqueue_kick(vi->evt);
+       spin_unlock_irqrestore(&vi->lock, flags);
+}
+
+static int virtinput_probe(struct virtio_device *vdev)
+{
+       struct virtio_input *vi;
+       unsigned long flags;
+       size_t size;
+       int abs, err;
+
+       if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1))
+               return -ENODEV;
+
+       vi = kzalloc(sizeof(*vi), GFP_KERNEL);
+       if (!vi)
+               return -ENOMEM;
+
+       vdev->priv = vi;
+       vi->vdev = vdev;
+       spin_lock_init(&vi->lock);
+
+       err = virtinput_init_vqs(vi);
+       if (err)
+               goto err_init_vq;
+
+       vi->idev = input_allocate_device();
+       if (!vi->idev) {
+               err = -ENOMEM;
+               goto err_input_alloc;
+       }
+       input_set_drvdata(vi->idev, vi);
+
+       size = virtinput_cfg_select(vi, VIRTIO_INPUT_CFG_ID_NAME, 0);
+       virtio_cread_bytes(vi->vdev, offsetof(struct virtio_input_config,
+                                             u.string),
+                          vi->name, min(size, sizeof(vi->name)));
+       size = virtinput_cfg_select(vi, VIRTIO_INPUT_CFG_ID_SERIAL, 0);
+       virtio_cread_bytes(vi->vdev, offsetof(struct virtio_input_config,
+                                             u.string),
+                          vi->serial, min(size, sizeof(vi->serial)));
+       snprintf(vi->phys, sizeof(vi->phys),
+                "virtio%d/input0", vdev->index);
+       vi->idev->name = vi->name;
+       vi->idev->phys = vi->phys;
+       vi->idev->uniq = vi->serial;
+
+       size = virtinput_cfg_select(vi, VIRTIO_INPUT_CFG_ID_DEVIDS, 0);
+       if (size >= sizeof(struct virtio_input_devids)) {
+               virtio_cread(vi->vdev, struct virtio_input_config,
+                            u.ids.bustype, &vi->idev->id.bustype);
+               virtio_cread(vi->vdev, struct virtio_input_config,
+                            u.ids.vendor, &vi->idev->id.vendor);
+               virtio_cread(vi->vdev, struct virtio_input_config,
+                            u.ids.product, &vi->idev->id.product);
+               virtio_cread(vi->vdev, struct virtio_input_config,
+                            u.ids.version, &vi->idev->id.version);
+       } else {
+               vi->idev->id.bustype = BUS_VIRTUAL;
+       }
+
+       virtinput_cfg_bits(vi, VIRTIO_INPUT_CFG_PROP_BITS, 0,
+                          vi->idev->propbit, INPUT_PROP_CNT);
+       size = virtinput_cfg_select(vi, VIRTIO_INPUT_CFG_EV_BITS, EV_REP);
+       if (size)
+               __set_bit(EV_REP, vi->idev->evbit);
+
+       vi->idev->dev.parent = &vdev->dev;
+       vi->idev->event = virtinput_status;
+
+       /* device -> kernel */
+       virtinput_cfg_bits(vi, VIRTIO_INPUT_CFG_EV_BITS, EV_KEY,
+                          vi->idev->keybit, KEY_CNT);
+       virtinput_cfg_bits(vi, VIRTIO_INPUT_CFG_EV_BITS, EV_REL,
+                          vi->idev->relbit, REL_CNT);
+       virtinput_cfg_bits(vi, VIRTIO_INPUT_CFG_EV_BITS, EV_ABS,
+                          vi->idev->absbit, ABS_CNT);
+       virtinput_cfg_bits(vi, VIRTIO_INPUT_CFG_EV_BITS, EV_MSC,
+                          vi->idev->mscbit, MSC_CNT);
+       virtinput_cfg_bits(vi, VIRTIO_INPUT_CFG_EV_BITS, EV_SW,
+                          vi->idev->swbit,  SW_CNT);
+
+       /* kernel -> device */
+       virtinput_cfg_bits(vi, VIRTIO_INPUT_CFG_EV_BITS, EV_LED,
+                          vi->idev->ledbit, LED_CNT);
+       virtinput_cfg_bits(vi, VIRTIO_INPUT_CFG_EV_BITS, EV_SND,
+                          vi->idev->sndbit, SND_CNT);
+
+       if (test_bit(EV_ABS, vi->idev->evbit)) {
+               for (abs = 0; abs < ABS_CNT; abs++) {
+                       if (!test_bit(abs, vi->idev->absbit))
+                               continue;
+                       virtinput_cfg_abs(vi, abs);
+               }
+       }
+
+       virtio_device_ready(vdev);
+       vi->ready = true;
+       err = input_register_device(vi->idev);
+       if (err)
+               goto err_input_register;
+
+       virtinput_fill_evt(vi);
+       return 0;
+
+err_input_register:
+       spin_lock_irqsave(&vi->lock, flags);
+       vi->ready = false;
+       spin_unlock_irqrestore(&vi->lock, flags);
+       input_free_device(vi->idev);
+err_input_alloc:
+       vdev->config->del_vqs(vdev);
+err_init_vq:
+       kfree(vi);
+       return err;
+}
+
+static void virtinput_remove(struct virtio_device *vdev)
+{
+       struct virtio_input *vi = vdev->priv;
+       unsigned long flags;
+
+       spin_lock_irqsave(&vi->lock, flags);
+       vi->ready = false;
+       spin_unlock_irqrestore(&vi->lock, flags);
+
+       input_unregister_device(vi->idev);
+       vdev->config->del_vqs(vdev);
+       kfree(vi);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int virtinput_freeze(struct virtio_device *vdev)
+{
+       struct virtio_input *vi = vdev->priv;
+       unsigned long flags;
+
+       spin_lock_irqsave(&vi->lock, flags);
+       vi->ready = false;
+       spin_unlock_irqrestore(&vi->lock, flags);
+
+       vdev->config->del_vqs(vdev);
+       return 0;
+}
+
+static int virtinput_restore(struct virtio_device *vdev)
+{
+       struct virtio_input *vi = vdev->priv;
+       int err;
+
+       err = virtinput_init_vqs(vi);
+       if (err)
+               return err;
+
+       virtio_device_ready(vdev);
+       vi->ready = true;
+       virtinput_fill_evt(vi);
+       return 0;
+}
+#endif
+
+static unsigned int features[] = {
+       /* none */
+};
+static struct virtio_device_id id_table[] = {
+       { VIRTIO_ID_INPUT, VIRTIO_DEV_ANY_ID },
+       { 0 },
+};
+
+static struct virtio_driver virtio_input_driver = {
+       .driver.name         = KBUILD_MODNAME,
+       .driver.owner        = THIS_MODULE,
+       .feature_table       = features,
+       .feature_table_size  = ARRAY_SIZE(features),
+       .id_table            = id_table,
+       .probe               = virtinput_probe,
+       .remove              = virtinput_remove,
+#ifdef CONFIG_PM_SLEEP
+       .freeze              = virtinput_freeze,
+       .restore             = virtinput_restore,
+#endif
+};
+
+module_virtio_driver(virtio_input_driver);
+MODULE_DEVICE_TABLE(virtio, id_table);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Virtio input device driver");
+MODULE_AUTHOR("Gerd Hoffmann <kraxel@redhat.com>");
index 6010d7ec0a0f899b7b7690d202e9b57c6dbc7193..7a5e60dea6c59267ef48efa42ac2091346616b57 100644 (file)
@@ -581,14 +581,6 @@ static int virtio_mmio_probe(struct platform_device *pdev)
        }
        vm_dev->vdev.id.vendor = readl(vm_dev->base + VIRTIO_MMIO_VENDOR_ID);
 
-       /* Reject legacy-only IDs for version 2 devices */
-       if (vm_dev->version == 2 &&
-                       virtio_device_is_legacy_only(vm_dev->vdev.id)) {
-               dev_err(&pdev->dev, "Version 2 not supported for devices %u!\n",
-                               vm_dev->vdev.id.device);
-               return -ENODEV;
-       }
-
        if (vm_dev->version == 1)
                writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_GUEST_PAGE_SIZE);
 
index 2aa38e59db2e0849a7cba101358d970a389b7f80..e88e0997a8897e2ceaa25891f3ae080048d6e259 100644 (file)
 #define VIRTIO_PCI_NO_LEGACY
 #include "virtio_pci_common.h"
 
+/*
+ * Type-safe wrappers for io accesses.
+ * Use these to enforce at compile time the following spec requirement:
+ *
+ * The driver MUST access each field using the “natural” access
+ * method, i.e. 32-bit accesses for 32-bit fields, 16-bit accesses
+ * for 16-bit fields and 8-bit accesses for 8-bit fields.
+ */
+static inline u8 vp_ioread8(u8 __iomem *addr)
+{
+       return ioread8(addr);
+}
+static inline u16 vp_ioread16 (u16 __iomem *addr)
+{
+       return ioread16(addr);
+}
+
+static inline u32 vp_ioread32(u32 __iomem *addr)
+{
+       return ioread32(addr);
+}
+
+static inline void vp_iowrite8(u8 value, u8 __iomem *addr)
+{
+       iowrite8(value, addr);
+}
+
+static inline void vp_iowrite16(u16 value, u16 __iomem *addr)
+{
+       iowrite16(value, addr);
+}
+
+static inline void vp_iowrite32(u32 value, u32 __iomem *addr)
+{
+       iowrite32(value, addr);
+}
+
+static void vp_iowrite64_twopart(u64 val,
+                                __le32 __iomem *lo, __le32 __iomem *hi)
+{
+       vp_iowrite32((u32)val, lo);
+       vp_iowrite32(val >> 32, hi);
+}
+
 static void __iomem *map_capability(struct pci_dev *dev, int off,
                                    size_t minlen,
                                    u32 align,
@@ -94,22 +138,16 @@ static void __iomem *map_capability(struct pci_dev *dev, int off,
        return p;
 }
 
-static void iowrite64_twopart(u64 val, __le32 __iomem *lo, __le32 __iomem *hi)
-{
-       iowrite32((u32)val, lo);
-       iowrite32(val >> 32, hi);
-}
-
 /* virtio config->get_features() implementation */
 static u64 vp_get_features(struct virtio_device *vdev)
 {
        struct virtio_pci_device *vp_dev = to_vp_device(vdev);
        u64 features;
 
-       iowrite32(0, &vp_dev->common->device_feature_select);
-       features = ioread32(&vp_dev->common->device_feature);
-       iowrite32(1, &vp_dev->common->device_feature_select);
-       features |= ((u64)ioread32(&vp_dev->common->device_feature) << 32);
+       vp_iowrite32(0, &vp_dev->common->device_feature_select);
+       features = vp_ioread32(&vp_dev->common->device_feature);
+       vp_iowrite32(1, &vp_dev->common->device_feature_select);
+       features |= ((u64)vp_ioread32(&vp_dev->common->device_feature) << 32);
 
        return features;
 }
@@ -128,10 +166,10 @@ static int vp_finalize_features(struct virtio_device *vdev)
                return -EINVAL;
        }
 
-       iowrite32(0, &vp_dev->common->guest_feature_select);
-       iowrite32((u32)vdev->features, &vp_dev->common->guest_feature);
-       iowrite32(1, &vp_dev->common->guest_feature_select);
-       iowrite32(vdev->features >> 32, &vp_dev->common->guest_feature);
+       vp_iowrite32(0, &vp_dev->common->guest_feature_select);
+       vp_iowrite32((u32)vdev->features, &vp_dev->common->guest_feature);
+       vp_iowrite32(1, &vp_dev->common->guest_feature_select);
+       vp_iowrite32(vdev->features >> 32, &vp_dev->common->guest_feature);
 
        return 0;
 }
@@ -210,14 +248,14 @@ static void vp_set(struct virtio_device *vdev, unsigned offset,
 static u32 vp_generation(struct virtio_device *vdev)
 {
        struct virtio_pci_device *vp_dev = to_vp_device(vdev);
-       return ioread8(&vp_dev->common->config_generation);
+       return vp_ioread8(&vp_dev->common->config_generation);
 }
 
 /* config->{get,set}_status() implementations */
 static u8 vp_get_status(struct virtio_device *vdev)
 {
        struct virtio_pci_device *vp_dev = to_vp_device(vdev);
-       return ioread8(&vp_dev->common->device_status);
+       return vp_ioread8(&vp_dev->common->device_status);
 }
 
 static void vp_set_status(struct virtio_device *vdev, u8 status)
@@ -225,17 +263,17 @@ static void vp_set_status(struct virtio_device *vdev, u8 status)
        struct virtio_pci_device *vp_dev = to_vp_device(vdev);
        /* We should never be setting status to 0. */
        BUG_ON(status == 0);
-       iowrite8(status, &vp_dev->common->device_status);
+       vp_iowrite8(status, &vp_dev->common->device_status);
 }
 
 static void vp_reset(struct virtio_device *vdev)
 {
        struct virtio_pci_device *vp_dev = to_vp_device(vdev);
        /* 0 status means a reset. */
-       iowrite8(0, &vp_dev->common->device_status);
+       vp_iowrite8(0, &vp_dev->common->device_status);
        /* Flush out the status write, and flush in device writes,
         * including MSI-X interrupts, if any. */
-       ioread8(&vp_dev->common->device_status);
+       vp_ioread8(&vp_dev->common->device_status);
        /* Flush pending VQ/configuration callbacks. */
        vp_synchronize_vectors(vdev);
 }
@@ -243,10 +281,10 @@ static void vp_reset(struct virtio_device *vdev)
 static u16 vp_config_vector(struct virtio_pci_device *vp_dev, u16 vector)
 {
        /* Setup the vector used for configuration events */
-       iowrite16(vector, &vp_dev->common->msix_config);
+       vp_iowrite16(vector, &vp_dev->common->msix_config);
        /* Verify we had enough resources to assign the vector */
        /* Will also flush the write out to device */
-       return ioread16(&vp_dev->common->msix_config);
+       return vp_ioread16(&vp_dev->common->msix_config);
 }
 
 static size_t vring_pci_size(u16 num)
@@ -286,15 +324,15 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
        u16 num, off;
        int err;
 
-       if (index >= ioread16(&cfg->num_queues))
+       if (index >= vp_ioread16(&cfg->num_queues))
                return ERR_PTR(-ENOENT);
 
        /* Select the queue we're interested in */
-       iowrite16(index, &cfg->queue_select);
+       vp_iowrite16(index, &cfg->queue_select);
 
        /* Check if queue is either not available or already active. */
-       num = ioread16(&cfg->queue_size);
-       if (!num || ioread16(&cfg->queue_enable))
+       num = vp_ioread16(&cfg->queue_size);
+       if (!num || vp_ioread16(&cfg->queue_enable))
                return ERR_PTR(-ENOENT);
 
        if (num & (num - 1)) {
@@ -303,7 +341,7 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
        }
 
        /* get offset of notification word for this vq */
-       off = ioread16(&cfg->queue_notify_off);
+       off = vp_ioread16(&cfg->queue_notify_off);
 
        info->num = num;
        info->msix_vector = msix_vec;
@@ -322,13 +360,13 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
        }
 
        /* activate the queue */
-       iowrite16(num, &cfg->queue_size);
-       iowrite64_twopart(virt_to_phys(info->queue),
-                         &cfg->queue_desc_lo, &cfg->queue_desc_hi);
-       iowrite64_twopart(virt_to_phys(virtqueue_get_avail(vq)),
-                         &cfg->queue_avail_lo, &cfg->queue_avail_hi);
-       iowrite64_twopart(virt_to_phys(virtqueue_get_used(vq)),
-                         &cfg->queue_used_lo, &cfg->queue_used_hi);
+       vp_iowrite16(num, &cfg->queue_size);
+       vp_iowrite64_twopart(virt_to_phys(info->queue),
+                            &cfg->queue_desc_lo, &cfg->queue_desc_hi);
+       vp_iowrite64_twopart(virt_to_phys(virtqueue_get_avail(vq)),
+                            &cfg->queue_avail_lo, &cfg->queue_avail_hi);
+       vp_iowrite64_twopart(virt_to_phys(virtqueue_get_used(vq)),
+                            &cfg->queue_used_lo, &cfg->queue_used_hi);
 
        if (vp_dev->notify_base) {
                /* offset should not wrap */
@@ -357,8 +395,8 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
        }
 
        if (msix_vec != VIRTIO_MSI_NO_VECTOR) {
-               iowrite16(msix_vec, &cfg->queue_msix_vector);
-               msix_vec = ioread16(&cfg->queue_msix_vector);
+               vp_iowrite16(msix_vec, &cfg->queue_msix_vector);
+               msix_vec = vp_ioread16(&cfg->queue_msix_vector);
                if (msix_vec == VIRTIO_MSI_NO_VECTOR) {
                        err = -EBUSY;
                        goto err_assign_vector;
@@ -393,8 +431,8 @@ static int vp_modern_find_vqs(struct virtio_device *vdev, unsigned nvqs,
         * this, there's no way to go back except reset.
         */
        list_for_each_entry(vq, &vdev->vqs, list) {
-               iowrite16(vq->index, &vp_dev->common->queue_select);
-               iowrite16(1, &vp_dev->common->queue_enable);
+               vp_iowrite16(vq->index, &vp_dev->common->queue_select);
+               vp_iowrite16(1, &vp_dev->common->queue_enable);
        }
 
        return 0;
@@ -405,13 +443,13 @@ static void del_vq(struct virtio_pci_vq_info *info)
        struct virtqueue *vq = info->vq;
        struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
 
-       iowrite16(vq->index, &vp_dev->common->queue_select);
+       vp_iowrite16(vq->index, &vp_dev->common->queue_select);
 
        if (vp_dev->msix_enabled) {
-               iowrite16(VIRTIO_MSI_NO_VECTOR,
-                         &vp_dev->common->queue_msix_vector);
+               vp_iowrite16(VIRTIO_MSI_NO_VECTOR,
+                            &vp_dev->common->queue_msix_vector);
                /* Flush the write out to device */
-               ioread16(&vp_dev->common->queue_msix_vector);
+               vp_ioread16(&vp_dev->common->queue_msix_vector);
        }
 
        if (!vp_dev->notify_base)
@@ -577,9 +615,6 @@ int virtio_pci_modern_probe(struct virtio_pci_device *vp_dev)
        }
        vp_dev->vdev.id.vendor = pci_dev->subsystem_vendor;
 
-       if (virtio_device_is_legacy_only(vp_dev->vdev.id))
-               return -ENODEV;
-
        /* check for a common config: if not, use legacy mode (bar 0). */
        common = virtio_pci_find_capability(pci_dev, VIRTIO_PCI_CAP_COMMON_CFG,
                                            IORESOURCE_IO | IORESOURCE_MEM);
index 53bf2c860ad3503a497b0f656ff5306a21ceb5ff..a4621757a47f5184d96b99fda56c20f11562425d 100644 (file)
@@ -166,7 +166,7 @@ static int mxc_w1_remove(struct platform_device *pdev)
        return 0;
 }
 
-static struct of_device_id mxc_w1_dt_ids[] = {
+static const struct of_device_id mxc_w1_dt_ids[] = {
        { .compatible = "fsl,imx21-owire" },
        { /* sentinel */ }
 };
index 03321d6a268465a7f9c19754ea84f299dda9c95d..e7d448963a24355551b008495f7193d3e2c97da9 100644 (file)
@@ -72,7 +72,7 @@ struct hdq_data {
 static int omap_hdq_probe(struct platform_device *pdev);
 static int omap_hdq_remove(struct platform_device *pdev);
 
-static struct of_device_id omap_hdq_dt_ids[] = {
+static const struct of_device_id omap_hdq_dt_ids[] = {
        { .compatible = "ti,omap3-1w" },
        {}
 };
index b99a932ad901ff5b81e458349e0100be564fd37f..8f7848c62811aff90bf273b14c1e8146a2f07d32 100644 (file)
@@ -68,7 +68,7 @@ static u8 w1_gpio_read_bit(void *data)
 }
 
 #if defined(CONFIG_OF)
-static struct of_device_id w1_gpio_dt_ids[] = {
+static const struct of_device_id w1_gpio_dt_ids[] = {
        { .compatible = "w1-gpio" },
        {}
 };
index 16f20235099768d91f10931841e25176af59ef7e..e5e7c5505de7dc8f289f3891013b0eac25399747 100644 (file)
@@ -154,7 +154,7 @@ config ARM_SP805_WATCHDOG
 
 config AT91RM9200_WATCHDOG
        tristate "AT91RM9200 watchdog"
-       depends on SOC_AT91RM9200
+       depends on SOC_AT91RM9200 && MFD_SYSCON
        help
          Watchdog timer embedded into AT91RM9200 chips. This will reboot your
          system when the timeout is reached.
@@ -169,7 +169,6 @@ config AT91SAM9X_WATCHDOG
 
 config CADENCE_WATCHDOG
        tristate "Cadence Watchdog Timer"
-       depends on ARM
        select WATCHDOG_CORE
        help
          Say Y here if you want to include support for the watchdog
@@ -1190,6 +1189,7 @@ config OCTEON_WDT
        tristate "Cavium OCTEON SOC family Watchdog Timer"
        depends on CAVIUM_OCTEON_SOC
        default y
+       select WATCHDOG_CORE
        select EXPORT_UASM if OCTEON_WDT = m
        help
          Hardware driver for OCTEON's on chip watchdog timer.
index d244112d5b6f0541da038f5366091c0e592d3e8a..41cecb55766c049b600834d6ee021ef45f15332e 100644 (file)
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/bitops.h>
+#include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/atmel-st.h>
 #include <linux/miscdevice.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/platform_device.h>
+#include <linux/reboot.h>
+#include <linux/regmap.h>
 #include <linux/types.h>
 #include <linux/watchdog.h>
 #include <linux/uaccess.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
-#include <mach/at91_st.h>
 
 #define WDT_DEFAULT_TIME       5       /* seconds */
 #define WDT_MAX_TIME           256     /* seconds */
 
 static int wdt_time = WDT_DEFAULT_TIME;
 static bool nowayout = WATCHDOG_NOWAYOUT;
+static struct regmap *regmap_st;
 
 module_param(wdt_time, int, 0);
 MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="
@@ -50,12 +55,33 @@ static unsigned long at91wdt_busy;
 
 /* ......................................................................... */
 
+static int at91rm9200_restart(struct notifier_block *this,
+                                       unsigned long mode, void *cmd)
+{
+       /*
+        * Perform a hardware reset with the use of the Watchdog timer.
+        */
+       regmap_write(regmap_st, AT91_ST_WDMR,
+                    AT91_ST_RSTEN | AT91_ST_EXTEN | 1);
+       regmap_write(regmap_st, AT91_ST_CR, AT91_ST_WDRST);
+
+       mdelay(2000);
+
+       pr_emerg("Unable to restart system\n");
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block at91rm9200_restart_nb = {
+       .notifier_call = at91rm9200_restart,
+       .priority = 192,
+};
+
 /*
  * Disable the watchdog.
  */
 static inline void at91_wdt_stop(void)
 {
-       at91_st_write(AT91_ST_WDMR, AT91_ST_EXTEN);
+       regmap_write(regmap_st, AT91_ST_WDMR, AT91_ST_EXTEN);
 }
 
 /*
@@ -63,9 +89,9 @@ static inline void at91_wdt_stop(void)
  */
 static inline void at91_wdt_start(void)
 {
-       at91_st_write(AT91_ST_WDMR, AT91_ST_EXTEN | AT91_ST_RSTEN |
+       regmap_write(regmap_st, AT91_ST_WDMR, AT91_ST_EXTEN | AT91_ST_RSTEN |
                                (((65536 * wdt_time) >> 8) & AT91_ST_WDV));
-       at91_st_write(AT91_ST_CR, AT91_ST_WDRST);
+       regmap_write(regmap_st, AT91_ST_CR, AT91_ST_WDRST);
 }
 
 /*
@@ -73,7 +99,7 @@ static inline void at91_wdt_start(void)
  */
 static inline void at91_wdt_reload(void)
 {
-       at91_st_write(AT91_ST_CR, AT91_ST_WDRST);
+       regmap_write(regmap_st, AT91_ST_CR, AT91_ST_WDRST);
 }
 
 /* ......................................................................... */
@@ -203,16 +229,32 @@ static struct miscdevice at91wdt_miscdev = {
 
 static int at91wdt_probe(struct platform_device *pdev)
 {
+       struct device *dev = &pdev->dev;
+       struct device *parent;
        int res;
 
        if (at91wdt_miscdev.parent)
                return -EBUSY;
        at91wdt_miscdev.parent = &pdev->dev;
 
+       parent = dev->parent;
+       if (!parent) {
+               dev_err(dev, "no parent\n");
+               return -ENODEV;
+       }
+
+       regmap_st = syscon_node_to_regmap(parent->of_node);
+       if (!regmap_st)
+               return -ENODEV;
+
        res = misc_register(&at91wdt_miscdev);
        if (res)
                return res;
 
+       res = register_restart_handler(&at91rm9200_restart_nb);
+       if (res)
+               dev_warn(dev, "failed to register restart handler\n");
+
        pr_info("AT91 Watchdog Timer enabled (%d seconds%s)\n",
                wdt_time, nowayout ? ", nowayout" : "");
        return 0;
@@ -220,8 +262,13 @@ static int at91wdt_probe(struct platform_device *pdev)
 
 static int at91wdt_remove(struct platform_device *pdev)
 {
+       struct device *dev = &pdev->dev;
        int res;
 
+       res = unregister_restart_handler(&at91rm9200_restart_nb);
+       if (res)
+               dev_warn(dev, "failed to unregister restart handler\n");
+
        res = misc_deregister(&at91wdt_miscdev);
        if (!res)
                at91wdt_miscdev.parent = NULL;
@@ -267,7 +314,7 @@ static struct platform_driver at91wdt_driver = {
        .suspend        = at91wdt_suspend,
        .resume         = at91wdt_resume,
        .driver         = {
-               .name   = "at91_wdt",
+               .name   = "atmel_st_watchdog",
                .of_match_table = at91_wdt_dt_ids,
        },
 };
@@ -296,4 +343,4 @@ module_exit(at91_wdt_exit);
 MODULE_AUTHOR("Andrew Victor");
 MODULE_DESCRIPTION("Watchdog driver for Atmel AT91RM9200");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:at91_wdt");
+MODULE_ALIAS("platform:atmel_st_watchdog");
index 4e37db3539a48551853c931e317571dc2642fd21..22d8ae65772a508ecb28592b3d59f7304da9a8d0 100644 (file)
@@ -99,12 +99,14 @@ static int secure_register_read(struct bcm_kona_wdt *wdt, uint32_t offset)
 
 static int bcm_kona_wdt_dbg_show(struct seq_file *s, void *data)
 {
-       int ctl_val, cur_val, ret;
+       int ctl_val, cur_val;
        unsigned long flags;
        struct bcm_kona_wdt *wdt = s->private;
 
-       if (!wdt)
-               return seq_puts(s, "No device pointer\n");
+       if (!wdt) {
+               seq_puts(s, "No device pointer\n");
+               return 0;
+       }
 
        spin_lock_irqsave(&wdt->lock, flags);
        ctl_val = secure_register_read(wdt, SECWDOG_CTRL_REG);
@@ -112,7 +114,7 @@ static int bcm_kona_wdt_dbg_show(struct seq_file *s, void *data)
        spin_unlock_irqrestore(&wdt->lock, flags);
 
        if (ctl_val < 0 || cur_val < 0) {
-               ret = seq_puts(s, "Error accessing hardware\n");
+               seq_puts(s, "Error accessing hardware\n");
        } else {
                int ctl, cur, ctl_sec, cur_sec, res;
 
@@ -121,15 +123,18 @@ static int bcm_kona_wdt_dbg_show(struct seq_file *s, void *data)
                cur = cur_val & SECWDOG_COUNT_MASK;
                ctl_sec = TICKS_TO_SECS(ctl, wdt);
                cur_sec = TICKS_TO_SECS(cur, wdt);
-               ret = seq_printf(s, "Resolution: %d / %d\n"
-                               "Control: %d s / %d (%#x) ticks\n"
-                               "Current: %d s / %d (%#x) ticks\n"
-                               "Busy count: %lu\n", res,
-                               wdt->resolution, ctl_sec, ctl, ctl, cur_sec,
-                               cur, cur, wdt->busy_count);
+               seq_printf(s,
+                          "Resolution: %d / %d\n"
+                          "Control: %d s / %d (%#x) ticks\n"
+                          "Current: %d s / %d (%#x) ticks\n"
+                          "Busy count: %lu\n",
+                          res, wdt->resolution,
+                          ctl_sec, ctl, ctl,
+                          cur_sec, cur, cur,
+                          wdt->busy_count);
        }
 
-       return ret;
+       return 0;
 }
 
 static int bcm_kona_dbg_open(struct inode *inode, struct file *file)
index 8453531545dfee189ee28077d55e6b37e807df2f..14521c8b3d5a81916cc04d9b6e7d242837c2e678 100644 (file)
@@ -3,6 +3,8 @@
  *
  * Copyright (C) 2007, 2008, 2009, 2010 Cavium Networks
  *
+ * Converted to use WATCHDOG_CORE by Aaro Koskinen <aaro.koskinen@iki.fi>.
+ *
  * Some parts derived from wdt.c
  *
  *     (c) Copyright 1996-1997 Alan Cox <alan@lxorguk.ukuu.org.uk>,
@@ -103,13 +105,10 @@ MODULE_PARM_DESC(nowayout,
        "Watchdog cannot be stopped once started (default="
                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
-static unsigned long octeon_wdt_is_open;
-static char expect_close;
-
-static u32 __initdata nmi_stage1_insns[64];
+static u32 nmi_stage1_insns[64] __initdata;
 /* We need one branch and therefore one relocation per target label. */
-static struct uasm_label __initdata labels[5];
-static struct uasm_reloc __initdata relocs[5];
+static struct uasm_label labels[5] __initdata;
+static struct uasm_reloc relocs[5] __initdata;
 
 enum lable_id {
        label_enter_bootloader = 1
@@ -218,7 +217,8 @@ static void __init octeon_wdt_build_stage1(void)
        pr_debug("\t.set pop\n");
 
        if (len > 32)
-               panic("NMI stage 1 handler exceeds 32 instructions, was %d\n", len);
+               panic("NMI stage 1 handler exceeds 32 instructions, was %d\n",
+                     len);
 }
 
 static int cpu2core(int cpu)
@@ -294,6 +294,7 @@ static void octeon_wdt_write_hex(u64 value, int digits)
 {
        int d;
        int v;
+
        for (d = 0; d < digits; d++) {
                v = (value >> ((digits - d - 1) * 4)) & 0xf;
                if (v >= 10)
@@ -303,7 +304,7 @@ static void octeon_wdt_write_hex(u64 value, int digits)
        }
 }
 
-const char *reg_name[] = {
+static const char reg_name[][3] = {
        "$0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
        "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
        "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
@@ -444,7 +445,7 @@ static int octeon_wdt_cpu_callback(struct notifier_block *nfb,
        return NOTIFY_OK;
 }
 
-static void octeon_wdt_ping(void)
+static int octeon_wdt_ping(struct watchdog_device __always_unused *wdog)
 {
        int cpu;
        int coreid;
@@ -457,10 +458,12 @@ static void octeon_wdt_ping(void)
                    !cpumask_test_cpu(cpu, &irq_enabled_cpus)) {
                        /* We have to enable the irq */
                        int irq = OCTEON_IRQ_WDOG0 + coreid;
+
                        enable_irq(irq);
                        cpumask_set_cpu(cpu, &irq_enabled_cpus);
                }
        }
+       return 0;
 }
 
 static void octeon_wdt_calc_parameters(int t)
@@ -489,7 +492,8 @@ static void octeon_wdt_calc_parameters(int t)
        timeout_cnt = ((octeon_get_io_clock_rate() >> 8) * timeout_sec) >> 8;
 }
 
-static int octeon_wdt_set_heartbeat(int t)
+static int octeon_wdt_set_timeout(struct watchdog_device *wdog,
+                                 unsigned int t)
 {
        int cpu;
        int coreid;
@@ -509,158 +513,45 @@ static int octeon_wdt_set_heartbeat(int t)
                cvmx_write_csr(CVMX_CIU_WDOGX(coreid), ciu_wdog.u64);
                cvmx_write_csr(CVMX_CIU_PP_POKEX(coreid), 1);
        }
-       octeon_wdt_ping(); /* Get the irqs back on. */
+       octeon_wdt_ping(wdog); /* Get the irqs back on. */
        return 0;
 }
 
-/**
- *     octeon_wdt_write:
- *     @file: file handle to the watchdog
- *     @buf: buffer to write (unused as data does not matter here
- *     @count: count of bytes
- *     @ppos: pointer to the position to write. No seeks allowed
- *
- *     A write to a watchdog device is defined as a keepalive signal. Any
- *     write of data will do, as we we don't define content meaning.
- */
-
-static ssize_t octeon_wdt_write(struct file *file, const char __user *buf,
-                               size_t count, loff_t *ppos)
-{
-       if (count) {
-               if (!nowayout) {
-                       size_t i;
-
-                       /* In case it was set long ago */
-                       expect_close = 0;
-
-                       for (i = 0; i != count; i++) {
-                               char c;
-                               if (get_user(c, buf + i))
-                                       return -EFAULT;
-                               if (c == 'V')
-                                       expect_close = 1;
-                       }
-               }
-               octeon_wdt_ping();
-       }
-       return count;
-}
-
-/**
- *     octeon_wdt_ioctl:
- *     @file: file handle to the device
- *     @cmd: watchdog command
- *     @arg: argument pointer
- *
- *     The watchdog API defines a common set of functions for all
- *     watchdogs according to their available features. We only
- *     actually usefully support querying capabilities and setting
- *     the timeout.
- */
-
-static long octeon_wdt_ioctl(struct file *file, unsigned int cmd,
-                            unsigned long arg)
-{
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       int new_heartbeat;
-
-       static struct watchdog_info ident = {
-               .options =              WDIOF_SETTIMEOUT|
-                                       WDIOF_MAGICCLOSE|
-                                       WDIOF_KEEPALIVEPING,
-               .firmware_version =     1,
-               .identity =             "OCTEON",
-       };
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
-       case WDIOC_GETSTATUS:
-       case WDIOC_GETBOOTSTATUS:
-               return put_user(0, p);
-       case WDIOC_KEEPALIVE:
-               octeon_wdt_ping();
-               return 0;
-       case WDIOC_SETTIMEOUT:
-               if (get_user(new_heartbeat, p))
-                       return -EFAULT;
-               if (octeon_wdt_set_heartbeat(new_heartbeat))
-                       return -EINVAL;
-               /* Fall through. */
-       case WDIOC_GETTIMEOUT:
-               return put_user(heartbeat, p);
-       default:
-               return -ENOTTY;
-       }
-}
-
-/**
- *     octeon_wdt_open:
- *     @inode: inode of device
- *     @file: file handle to device
- *
- *     The watchdog device has been opened. The watchdog device is single
- *     open and on opening we do a ping to reset the counters.
- */
-
-static int octeon_wdt_open(struct inode *inode, struct file *file)
+static int octeon_wdt_start(struct watchdog_device *wdog)
 {
-       if (test_and_set_bit(0, &octeon_wdt_is_open))
-               return -EBUSY;
-       /*
-        *      Activate
-        */
-       octeon_wdt_ping();
+       octeon_wdt_ping(wdog);
        do_coundown = 1;
-       return nonseekable_open(inode, file);
+       return 0;
 }
 
-/**
- *     octeon_wdt_release:
- *     @inode: inode to board
- *     @file: file handle to board
- *
- *     The watchdog has a configurable API. There is a religious dispute
- *     between people who want their watchdog to be able to shut down and
- *     those who want to be sure if the watchdog manager dies the machine
- *     reboots. In the former case we disable the counters, in the latter
- *     case you have to open it again very soon.
- */
-
-static int octeon_wdt_release(struct inode *inode, struct file *file)
+static int octeon_wdt_stop(struct watchdog_device *wdog)
 {
-       if (expect_close) {
-               do_coundown = 0;
-               octeon_wdt_ping();
-       } else {
-               pr_crit("WDT device closed unexpectedly.  WDT will not stop!\n");
-       }
-       clear_bit(0, &octeon_wdt_is_open);
-       expect_close = 0;
+       do_coundown = 0;
+       octeon_wdt_ping(wdog);
        return 0;
 }
 
-static const struct file_operations octeon_wdt_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .write          = octeon_wdt_write,
-       .unlocked_ioctl = octeon_wdt_ioctl,
-       .open           = octeon_wdt_open,
-       .release        = octeon_wdt_release,
+static struct notifier_block octeon_wdt_cpu_notifier = {
+       .notifier_call = octeon_wdt_cpu_callback,
 };
 
-static struct miscdevice octeon_wdt_miscdev = {
-       .minor  = WATCHDOG_MINOR,
-       .name   = "watchdog",
-       .fops   = &octeon_wdt_fops,
+static const struct watchdog_info octeon_wdt_info = {
+       .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
+       .identity = "OCTEON",
 };
 
-static struct notifier_block octeon_wdt_cpu_notifier = {
-       .notifier_call = octeon_wdt_cpu_callback,
+static const struct watchdog_ops octeon_wdt_ops = {
+       .owner          = THIS_MODULE,
+       .start          = octeon_wdt_start,
+       .stop           = octeon_wdt_stop,
+       .ping           = octeon_wdt_ping,
+       .set_timeout    = octeon_wdt_set_timeout,
 };
 
+static struct watchdog_device octeon_wdt = {
+       .info   = &octeon_wdt_info,
+       .ops    = &octeon_wdt_ops,
+};
 
 /**
  * Module/ driver initialization.
@@ -685,7 +576,8 @@ static int __init octeon_wdt_init(void)
        max_timeout_sec = 6;
        do {
                max_timeout_sec--;
-               timeout_cnt = ((octeon_get_io_clock_rate() >> 8) * max_timeout_sec) >> 8;
+               timeout_cnt = ((octeon_get_io_clock_rate() >> 8) *
+                             max_timeout_sec) >> 8;
        } while (timeout_cnt > 65535);
 
        BUG_ON(timeout_cnt == 0);
@@ -694,11 +586,15 @@ static int __init octeon_wdt_init(void)
 
        pr_info("Initial granularity %d Sec\n", timeout_sec);
 
-       ret = misc_register(&octeon_wdt_miscdev);
+       octeon_wdt.timeout      = timeout_sec;
+       octeon_wdt.max_timeout  = UINT_MAX;
+
+       watchdog_set_nowayout(&octeon_wdt, nowayout);
+
+       ret = watchdog_register_device(&octeon_wdt);
        if (ret) {
-               pr_err("cannot register miscdev on minor=%d (err=%d)\n",
-                      WATCHDOG_MINOR, ret);
-               goto out;
+               pr_err("watchdog_register_device() failed: %d\n", ret);
+               return ret;
        }
 
        /* Build the NMI handler ... */
@@ -721,8 +617,7 @@ static int __init octeon_wdt_init(void)
        __register_hotcpu_notifier(&octeon_wdt_cpu_notifier);
        cpu_notifier_register_done();
 
-out:
-       return ret;
+       return 0;
 }
 
 /**
@@ -732,7 +627,7 @@ static void __exit octeon_wdt_cleanup(void)
 {
        int cpu;
 
-       misc_deregister(&octeon_wdt_miscdev);
+       watchdog_unregister_device(&octeon_wdt);
 
        cpu_notifier_register_begin();
        __unregister_hotcpu_notifier(&octeon_wdt_cpu_notifier);
index 55e220150103067ae7544b7046cfe39783a14e20..b9c6049c3e78601151218508c67e54b363d69be5 100644 (file)
@@ -216,7 +216,7 @@ static struct platform_driver platform_wdt_driver = {
 module_platform_driver(platform_wdt_driver);
 
 MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
-MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>");
+MODULE_AUTHOR("Wolfram Sang <kernel@pengutronix.de>");
 MODULE_DESCRIPTION("PNX4008 Watchdog Driver");
 
 module_param(heartbeat, uint, 0);
index aa85618c4d0328bf42e8ca43157f9c67451ceee9..aa03ca8f2d9b0a0f08f85cab9d928fdc0a594388 100644 (file)
@@ -20,9 +20,9 @@
 #include <linux/reboot.h>
 #include <linux/watchdog.h>
 
-#define WDT_RST                0x0
-#define WDT_EN         0x8
-#define WDT_BITE_TIME  0x24
+#define WDT_RST                0x38
+#define WDT_EN         0x40
+#define WDT_BITE_TIME  0x5C
 
 struct qcom_wdt {
        struct watchdog_device  wdd;
@@ -117,6 +117,8 @@ static int qcom_wdt_probe(struct platform_device *pdev)
 {
        struct qcom_wdt *wdt;
        struct resource *res;
+       struct device_node *np = pdev->dev.of_node;
+       u32 percpu_offset;
        int ret;
 
        wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
@@ -124,6 +126,14 @@ static int qcom_wdt_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+       /* We use CPU0's DGT for the watchdog */
+       if (of_property_read_u32(np, "cpu-offset", &percpu_offset))
+               percpu_offset = 0;
+
+       res->start += percpu_offset;
+       res->end += percpu_offset;
+
        wdt->base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(wdt->base))
                return PTR_ERR(wdt->base);
@@ -203,9 +213,8 @@ static int qcom_wdt_remove(struct platform_device *pdev)
 }
 
 static const struct of_device_id qcom_wdt_of_table[] = {
-       { .compatible = "qcom,kpss-wdt-msm8960", },
-       { .compatible = "qcom,kpss-wdt-apq8064", },
-       { .compatible = "qcom,kpss-wdt-ipq8064", },
+       { .compatible = "qcom,kpss-timer" },
+       { .compatible = "qcom,scss-timer" },
        { },
 };
 MODULE_DEVICE_TABLE(of, qcom_wdt_of_table);
index a62b1b6decf472ac2b35cf7e663da7e704f9e005..e7f0d5b60d3d4febb20759ea893dc0432d4963ee 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Watchdog driver for the RTC based watchdog in STMP3xxx and i.MX23/28
  *
- * Author: Wolfram Sang <w.sang@pengutronix.de>
+ * Author: Wolfram Sang <kernel@pengutronix.de>
  *
  * Copyright (C) 2011-12 Wolfram Sang, Pengutronix
  *
@@ -129,4 +129,4 @@ module_platform_driver(stmp3xxx_wdt_driver);
 
 MODULE_DESCRIPTION("STMP3XXX RTC Watchdog Driver");
 MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>");
+MODULE_AUTHOR("Wolfram Sang <kernel@pengutronix.de>");
index a270004c96058baf353435ac0dd0c7d1deaa9314..7cd226da15fea2d6985b6203d696a6fe8e0c400f 100644 (file)
@@ -276,4 +276,8 @@ config XEN_AUTO_XLATE
        help
          Support for auto-translated physmap guests.
 
+config XEN_ACPI
+       def_bool y
+       depends on X86 && ACPI
+
 endmenu
index 40edd1cbb60d9abebdc0c372543f516a73caf478..e293bc507cbcb20edbcdc0d3a0807c403de530b3 100644 (file)
@@ -13,7 +13,7 @@ CFLAGS_efi.o                          += -fshort-wchar
 
 dom0-$(CONFIG_PCI) += pci.o
 dom0-$(CONFIG_USB_SUPPORT) += dbgp.o
-dom0-$(CONFIG_ACPI) += acpi.o $(xen-pad-y)
+dom0-$(CONFIG_XEN_ACPI) += acpi.o $(xen-pad-y)
 xen-pad-$(CONFIG_X86) += xen-acpi-pad.o
 dom0-$(CONFIG_X86) += pcpu.o
 obj-$(CONFIG_XEN_DOM0)                 += $(dom0-y)
index 5db43fc100a413bf0ee55676d2b359e4db94e7ec..7dd46312c18023c6e9ca6db16fba107c79a9bb84 100644 (file)
@@ -345,6 +345,15 @@ irqreturn_t xen_debug_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
+static void evtchn_2l_resume(void)
+{
+       int i;
+
+       for_each_online_cpu(i)
+               memset(per_cpu(cpu_evtchn_mask, i), 0, sizeof(xen_ulong_t) *
+                               EVTCHN_2L_NR_CHANNELS/BITS_PER_EVTCHN_WORD);
+}
+
 static const struct evtchn_ops evtchn_ops_2l = {
        .max_channels      = evtchn_2l_max_channels,
        .nr_channels       = evtchn_2l_max_channels,
@@ -356,6 +365,7 @@ static const struct evtchn_ops evtchn_ops_2l = {
        .mask              = evtchn_2l_mask,
        .unmask            = evtchn_2l_unmask,
        .handle_events     = evtchn_2l_handle_events,
+       .resume            = evtchn_2l_resume,
 };
 
 void __init xen_evtchn_2l_init(void)
index 70fba973a107165c2c29b2104d8f4d438faddc2b..2b8553bd871514db8bfbd4877838c66d30f6598b 100644 (file)
@@ -529,8 +529,8 @@ static unsigned int __startup_pirq(unsigned int irq)
        if (rc)
                goto err;
 
-       bind_evtchn_to_cpu(evtchn, 0);
        info->evtchn = evtchn;
+       bind_evtchn_to_cpu(evtchn, 0);
 
        rc = xen_evtchn_port_setup(info);
        if (rc)
@@ -1279,8 +1279,9 @@ void rebind_evtchn_irq(int evtchn, int irq)
 
        mutex_unlock(&irq_mapping_update_lock);
 
-       /* new event channels are always bound to cpu 0 */
-       irq_set_affinity(irq, cpumask_of(0));
+        bind_evtchn_to_cpu(evtchn, info->cpu);
+       /* This will be deferred until interrupt is processed */
+       irq_set_affinity(irq, cpumask_of(info->cpu));
 
        /* Unmask the event channel. */
        enable_irq(irq);
index d5bb1a33d0a3fc7337975734f4305038c1959723..89274850741b5e3ee457fa2bd19d6efaf16d1f5d 100644 (file)
@@ -327,30 +327,10 @@ static int map_grant_pages(struct grant_map *map)
        return err;
 }
 
-struct unmap_grant_pages_callback_data
-{
-       struct completion completion;
-       int result;
-};
-
-static void unmap_grant_callback(int result,
-                                struct gntab_unmap_queue_data *data)
-{
-       struct unmap_grant_pages_callback_data* d = data->data;
-
-       d->result = result;
-       complete(&d->completion);
-}
-
 static int __unmap_grant_pages(struct grant_map *map, int offset, int pages)
 {
        int i, err = 0;
        struct gntab_unmap_queue_data unmap_data;
-       struct unmap_grant_pages_callback_data data;
-
-       init_completion(&data.completion);
-       unmap_data.data = &data;
-       unmap_data.done= &unmap_grant_callback;
 
        if (map->notify.flags & UNMAP_NOTIFY_CLEAR_BYTE) {
                int pgno = (map->notify.addr >> PAGE_SHIFT);
@@ -367,11 +347,9 @@ static int __unmap_grant_pages(struct grant_map *map, int offset, int pages)
        unmap_data.pages = map->pages + offset;
        unmap_data.count = pages;
 
-       gnttab_unmap_refs_async(&unmap_data);
-
-       wait_for_completion(&data.completion);
-       if (data.result)
-               return data.result;
+       err = gnttab_unmap_refs_sync(&unmap_data);
+       if (err)
+               return err;
 
        for (i = 0; i < pages; i++) {
                if (map->unmap_ops[offset+i].status)
index 17972fbacddc41d34122c5af816461bd6b99effd..b1c7170e5c9e1edf85049c4d43fc4d1b9f2b18f8 100644 (file)
@@ -123,6 +123,11 @@ struct gnttab_ops {
        int (*query_foreign_access)(grant_ref_t ref);
 };
 
+struct unmap_refs_callback_data {
+       struct completion completion;
+       int result;
+};
+
 static struct gnttab_ops *gnttab_interface;
 
 static int grant_table_version;
@@ -863,6 +868,29 @@ void gnttab_unmap_refs_async(struct gntab_unmap_queue_data* item)
 }
 EXPORT_SYMBOL_GPL(gnttab_unmap_refs_async);
 
+static void unmap_refs_callback(int result,
+               struct gntab_unmap_queue_data *data)
+{
+       struct unmap_refs_callback_data *d = data->data;
+
+       d->result = result;
+       complete(&d->completion);
+}
+
+int gnttab_unmap_refs_sync(struct gntab_unmap_queue_data *item)
+{
+       struct unmap_refs_callback_data data;
+
+       init_completion(&data.completion);
+       item->data = &data;
+       item->done = &unmap_refs_callback;
+       gnttab_unmap_refs_async(item);
+       wait_for_completion(&data.completion);
+
+       return data.result;
+}
+EXPORT_SYMBOL_GPL(gnttab_unmap_refs_sync);
+
 static int gnttab_map_frames_v1(xen_pfn_t *frames, unsigned int nr_gframes)
 {
        int rc;
index bf1940706422fe1c2dd334cf28096294ab74e542..9e6a85104a20820ff16ef748804eb8c6a98b4201 100644 (file)
@@ -131,6 +131,8 @@ static void do_suspend(void)
                goto out_resume;
        }
 
+       xen_arch_suspend();
+
        si.cancelled = 1;
 
        err = stop_machine(xen_suspend, &si, cpumask_of(0));
@@ -148,11 +150,12 @@ static void do_suspend(void)
                si.cancelled = 1;
        }
 
+       xen_arch_resume();
+
 out_resume:
-       if (!si.cancelled) {
-               xen_arch_resume();
+       if (!si.cancelled)
                xs_resume();
-       else
+       else
                xs_suspend_cancel();
 
        dpm_resume_end(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
index 810ad419e34ca76ef3f2d0444e789d579dea1b9e..4c549323c605d97591224050b00add55e3a833a0 100644 (file)
@@ -235,7 +235,7 @@ retry:
 #define SLABS_PER_PAGE (1 << (PAGE_SHIFT - IO_TLB_SHIFT))
 #define IO_TLB_MIN_SLABS ((1<<20) >> IO_TLB_SHIFT)
                while ((SLABS_PER_PAGE << order) > IO_TLB_MIN_SLABS) {
-                       xen_io_tlb_start = (void *)__get_free_pages(__GFP_NOWARN, order);
+                       xen_io_tlb_start = (void *)xen_get_swiotlb_free_pages(order);
                        if (xen_io_tlb_start)
                                break;
                        order--;
index 75fe3d466515a08cf8ec8da7eebafd8c5b903895..9c234209d8b52d44d6483397f33a190fa2899c90 100644 (file)
@@ -16,8 +16,8 @@
 #include "conf_space.h"
 #include "conf_space_quirks.h"
 
-bool permissive;
-module_param(permissive, bool, 0644);
+bool xen_pcibk_permissive;
+module_param_named(permissive, xen_pcibk_permissive, bool, 0644);
 
 /* This is where xen_pcibk_read_config_byte, xen_pcibk_read_config_word,
  * xen_pcibk_write_config_word, and xen_pcibk_write_config_byte are created. */
@@ -262,7 +262,7 @@ int xen_pcibk_config_write(struct pci_dev *dev, int offset, int size, u32 value)
                 * This means that some fields may still be read-only because
                 * they have entries in the config_field list that intercept
                 * the write and do nothing. */
-               if (dev_data->permissive || permissive) {
+               if (dev_data->permissive || xen_pcibk_permissive) {
                        switch (size) {
                        case 1:
                                err = pci_write_config_byte(dev, offset,
index 2e1d73d1d5d09393ebf7e2ab21a026b709e5bb5f..62461a8ba1d6bbfbf9e6de2e98a8230ebc67ff3e 100644 (file)
@@ -64,7 +64,7 @@ struct config_field_entry {
        void *data;
 };
 
-extern bool permissive;
+extern bool xen_pcibk_permissive;
 
 #define OFFSET(cfg_entry) ((cfg_entry)->base_offset+(cfg_entry)->field->offset)
 
index c2260a0456c94fa1f73b6ef96777b4565aaef61e..ad3d17d29c81171838d01a2f1a081c769407f02d 100644 (file)
@@ -118,7 +118,7 @@ static int command_write(struct pci_dev *dev, int offset, u16 value, void *data)
 
        cmd->val = value;
 
-       if (!permissive && (!dev_data || !dev_data->permissive))
+       if (!xen_pcibk_permissive && (!dev_data || !dev_data->permissive))
                return 0;
 
        /* Only allow the guest to control certain bits. */
index 07ef383252237a2a0fad0bda86994a12a941446e..b7f51504f85adc1b5d19d33e48d066bdd60684c5 100644 (file)
@@ -204,8 +204,7 @@ static LIST_HEAD(scsiback_free_pages);
 static DEFINE_MUTEX(scsiback_mutex);
 static LIST_HEAD(scsiback_list);
 
-/* Local pointer to allocated TCM configfs fabric module */
-static struct target_fabric_configfs *scsiback_fabric_configfs;
+static const struct target_core_fabric_ops scsiback_ops;
 
 static void scsiback_get(struct vscsibk_info *info)
 {
@@ -1902,7 +1901,7 @@ scsiback_make_tpg(struct se_wwn *wwn,
        tpg->tport = tport;
        tpg->tport_tpgt = tpgt;
 
-       ret = core_tpg_register(&scsiback_fabric_configfs->tf_ops, wwn,
+       ret = core_tpg_register(&scsiback_ops, wwn,
                                &tpg->se_tpg, tpg, TRANSPORT_TPG_TYPE_NORMAL);
        if (ret < 0) {
                kfree(tpg);
@@ -1944,7 +1943,9 @@ static int scsiback_check_false(struct se_portal_group *se_tpg)
        return 0;
 }
 
-static struct target_core_fabric_ops scsiback_ops = {
+static const struct target_core_fabric_ops scsiback_ops = {
+       .module                         = THIS_MODULE,
+       .name                           = "xen-pvscsi",
        .get_fabric_name                = scsiback_get_fabric_name,
        .get_fabric_proto_ident         = scsiback_get_fabric_proto_ident,
        .tpg_get_wwn                    = scsiback_get_fabric_wwn,
@@ -1991,62 +1992,10 @@ static struct target_core_fabric_ops scsiback_ops = {
        .fabric_make_nodeacl            = scsiback_make_nodeacl,
        .fabric_drop_nodeacl            = scsiback_drop_nodeacl,
 #endif
-};
-
-static int scsiback_register_configfs(void)
-{
-       struct target_fabric_configfs *fabric;
-       int ret;
-
-       pr_debug("fabric module %s on %s/%s on "UTS_RELEASE"\n",
-                VSCSI_VERSION, utsname()->sysname, utsname()->machine);
-       /*
-        * Register the top level struct config_item_type with TCM core
-        */
-       fabric = target_fabric_configfs_init(THIS_MODULE, "xen-pvscsi");
-       if (IS_ERR(fabric))
-               return PTR_ERR(fabric);
 
-       /*
-        * Setup fabric->tf_ops from our local scsiback_ops
-        */
-       fabric->tf_ops = scsiback_ops;
-       /*
-        * Setup default attribute lists for various fabric->tf_cit_tmpl
-        */
-       fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = scsiback_wwn_attrs;
-       fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = scsiback_tpg_attrs;
-       fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = scsiback_param_attrs;
-       fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_nacl_base_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_nacl_auth_cit.ct_attrs = NULL;
-       fabric->tf_cit_tmpl.tfc_tpg_nacl_param_cit.ct_attrs = NULL;
-       /*
-        * Register the fabric for use within TCM
-        */
-       ret = target_fabric_configfs_register(fabric);
-       if (ret < 0) {
-               target_fabric_configfs_free(fabric);
-               return ret;
-       }
-       /*
-        * Setup our local pointer to *fabric
-        */
-       scsiback_fabric_configfs = fabric;
-       pr_debug("Set fabric -> scsiback_fabric_configfs\n");
-       return 0;
-};
-
-static void scsiback_deregister_configfs(void)
-{
-       if (!scsiback_fabric_configfs)
-               return;
-
-       target_fabric_configfs_deregister(scsiback_fabric_configfs);
-       scsiback_fabric_configfs = NULL;
-       pr_debug("Cleared scsiback_fabric_configfs\n");
+       .tfc_wwn_attrs                  = scsiback_wwn_attrs,
+       .tfc_tpg_base_attrs             = scsiback_tpg_attrs,
+       .tfc_tpg_param_attrs            = scsiback_param_attrs,
 };
 
 static const struct xenbus_device_id scsiback_ids[] = {
@@ -2078,6 +2027,9 @@ static int __init scsiback_init(void)
        if (!xen_domain())
                return -ENODEV;
 
+       pr_debug("xen-pvscsi: fabric module %s on %s/%s on "UTS_RELEASE"\n",
+                VSCSI_VERSION, utsname()->sysname, utsname()->machine);
+
        scsiback_cachep = kmem_cache_create("vscsiif_cache",
                sizeof(struct vscsibk_pend), 0, 0, scsiback_init_pend);
        if (!scsiback_cachep)
@@ -2087,7 +2039,7 @@ static int __init scsiback_init(void)
        if (ret)
                goto out_cache_destroy;
 
-       ret = scsiback_register_configfs();
+       ret = target_register_template(&scsiback_ops);
        if (ret)
                goto out_unregister_xenbus;
 
@@ -2110,7 +2062,7 @@ static void __exit scsiback_exit(void)
                        BUG();
                gnttab_free_pages(1, &page);
        }
-       scsiback_deregister_configfs();
+       target_unregister_template(&scsiback_ops);
        xenbus_unregister_driver(&scsiback_driver);
        kmem_cache_destroy(scsiback_cachep);
 }
index 564b31584860432634a898a8fce9c7dc155a6662..5390a674b5e3a8d8ea62112343be83a34be58547 100644 (file)
@@ -57,6 +57,7 @@
 #include <xen/xen.h>
 #include <xen/xenbus.h>
 #include <xen/events.h>
+#include <xen/xen-ops.h>
 #include <xen/page.h>
 
 #include <xen/hvm.h>
@@ -735,6 +736,30 @@ static int __init xenstored_local_init(void)
        return err;
 }
 
+static int xenbus_resume_cb(struct notifier_block *nb,
+                           unsigned long action, void *data)
+{
+       int err = 0;
+
+       if (xen_hvm_domain()) {
+               uint64_t v;
+
+               err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v);
+               if (!err && v)
+                       xen_store_evtchn = v;
+               else
+                       pr_warn("Cannot update xenstore event channel: %d\n",
+                               err);
+       } else
+               xen_store_evtchn = xen_start_info->store_evtchn;
+
+       return err;
+}
+
+static struct notifier_block xenbus_resume_nb = {
+       .notifier_call = xenbus_resume_cb,
+};
+
 static int __init xenbus_init(void)
 {
        int err = 0;
@@ -793,6 +818,10 @@ static int __init xenbus_init(void)
                goto out_error;
        }
 
+       if ((xen_store_domain_type != XS_LOCAL) &&
+           (xen_store_domain_type != XS_UNKNOWN))
+               xen_resume_notifier_register(&xenbus_resume_nb);
+
 #ifdef CONFIG_XEN_COMPAT_XENFS
        /*
         * Create xenfs mountpoint in /proc for compatibility with
index 8482f2d1160667ba1255ee5b48434287bc51da65..31c010372660154f6665782e89cea669b8457d29 100644 (file)
@@ -247,7 +247,7 @@ static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name,
        if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT)
                return v9fs_remote_get_acl(dentry, name, buffer, size, type);
 
-       acl = v9fs_get_cached_acl(dentry->d_inode, type);
+       acl = v9fs_get_cached_acl(d_inode(dentry), type);
        if (IS_ERR(acl))
                return PTR_ERR(acl);
        if (acl == NULL)
@@ -285,7 +285,7 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
        int retval;
        struct posix_acl *acl;
        struct v9fs_session_info *v9ses;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
 
        if (strcmp(name, "") != 0)
                return -EINVAL;
index a345b2d659cc8ac638ddb8dbd2d39535e442ec4b..bd456c668d3997959220eaacd5aebf1b1da19309 100644 (file)
@@ -53,7 +53,7 @@ static int v9fs_cached_dentry_delete(const struct dentry *dentry)
                 dentry, dentry);
 
        /* Don't cache negative dentries */
-       if (!dentry->d_inode)
+       if (d_really_is_negative(dentry))
                return 1;
        return 0;
 }
@@ -83,7 +83,7 @@ static int v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
        if (flags & LOOKUP_RCU)
                return -ECHILD;
 
-       inode = dentry->d_inode;
+       inode = d_inode(dentry);
        if (!inode)
                goto out_valid;
 
index 76c3b1ab6361d69b12f069ed7e9d68b48751eb82..5cc00e56206e339cb6077db514a6ac6a2bffcfd9 100644 (file)
@@ -138,6 +138,8 @@ static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx)
                                           &err);
                        if (err)
                                return err;
+                       if (n == 0)
+                               return 0;
 
                        rdir->head = 0;
                        rdir->tail = n;
index 3662f1d1d9cf0fc2f73c44fa4c34fb6e14c0af5f..703342e309f57af329085db6d8f0b1b4814793dd 100644 (file)
@@ -595,7 +595,7 @@ static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags)
                 dir, dentry, flags);
 
        v9ses = v9fs_inode2v9ses(dir);
-       inode = dentry->d_inode;
+       inode = d_inode(dentry);
        dfid = v9fs_fid_lookup(dentry->d_parent);
        if (IS_ERR(dfid)) {
                retval = PTR_ERR(dfid);
@@ -864,7 +864,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
        }
 
        /* Only creates */
-       if (!(flags & O_CREAT) || dentry->d_inode)
+       if (!(flags & O_CREAT) || d_really_is_positive(dentry))
                return finish_no_open(file, res);
 
        err = 0;
@@ -881,7 +881,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
        }
 
        v9fs_invalidate_inode_attr(dir);
-       v9inode = V9FS_I(dentry->d_inode);
+       v9inode = V9FS_I(d_inode(dentry));
        mutex_lock(&v9inode->v_mutex);
        if ((v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) &&
            !v9inode->writeback_fid &&
@@ -908,7 +908,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
 
        file->private_data = fid;
        if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
-               v9fs_cache_inode_set_cookie(dentry->d_inode, file);
+               v9fs_cache_inode_set_cookie(d_inode(dentry), file);
 
        *opened |= FILE_CREATED;
 out:
@@ -969,8 +969,8 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 
        p9_debug(P9_DEBUG_VFS, "\n");
        retval = 0;
-       old_inode = old_dentry->d_inode;
-       new_inode = new_dentry->d_inode;
+       old_inode = d_inode(old_dentry);
+       new_inode = d_inode(new_dentry);
        v9ses = v9fs_inode2v9ses(old_inode);
        oldfid = v9fs_fid_lookup(old_dentry);
        if (IS_ERR(oldfid))
@@ -1061,7 +1061,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
        p9_debug(P9_DEBUG_VFS, "dentry: %p\n", dentry);
        v9ses = v9fs_dentry2v9ses(dentry);
        if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
-               generic_fillattr(dentry->d_inode, stat);
+               generic_fillattr(d_inode(dentry), stat);
                return 0;
        }
        fid = v9fs_fid_lookup(dentry);
@@ -1072,8 +1072,8 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
        if (IS_ERR(st))
                return PTR_ERR(st);
 
-       v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb);
-       generic_fillattr(dentry->d_inode, stat);
+       v9fs_stat2inode(st, d_inode(dentry), d_inode(dentry)->i_sb);
+       generic_fillattr(d_inode(dentry), stat);
 
        p9stat_free(st);
        kfree(st);
@@ -1095,7 +1095,7 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
        struct p9_wstat wstat;
 
        p9_debug(P9_DEBUG_VFS, "\n");
-       retval = inode_change_ok(dentry->d_inode, iattr);
+       retval = inode_change_ok(d_inode(dentry), iattr);
        if (retval)
                return retval;
 
@@ -1128,20 +1128,20 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
 
        /* Write all dirty data */
        if (d_is_reg(dentry))
-               filemap_write_and_wait(dentry->d_inode->i_mapping);
+               filemap_write_and_wait(d_inode(dentry)->i_mapping);
 
        retval = p9_client_wstat(fid, &wstat);
        if (retval < 0)
                return retval;
 
        if ((iattr->ia_valid & ATTR_SIZE) &&
-           iattr->ia_size != i_size_read(dentry->d_inode))
-               truncate_setsize(dentry->d_inode, iattr->ia_size);
+           iattr->ia_size != i_size_read(d_inode(dentry)))
+               truncate_setsize(d_inode(dentry), iattr->ia_size);
 
-       v9fs_invalidate_inode_attr(dentry->d_inode);
+       v9fs_invalidate_inode_attr(d_inode(dentry));
 
-       setattr_copy(dentry->d_inode, iattr);
-       mark_inode_dirty(dentry->d_inode);
+       setattr_copy(d_inode(dentry), iattr);
+       mark_inode_dirty(d_inode(dentry));
        return 0;
 }
 
@@ -1403,7 +1403,7 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
        retval = v9fs_vfs_mkspecial(dir, dentry, P9_DMLINK, name);
        __putname(name);
        if (!retval) {
-               v9fs_refresh_inode(oldfid, old_dentry->d_inode);
+               v9fs_refresh_inode(oldfid, d_inode(old_dentry));
                v9fs_invalidate_inode_attr(dir);
        }
 clunk_fid:
index 6054c16b8faed41d0e80771a5a711f7c06a79fe8..9861c7c951a6dbd293e78d84e190f0908b4a1921 100644 (file)
@@ -265,7 +265,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
        }
 
        /* Only creates */
-       if (!(flags & O_CREAT) || dentry->d_inode)
+       if (!(flags & O_CREAT) || d_really_is_positive(dentry))
                return  finish_no_open(file, res);
 
        v9ses = v9fs_inode2v9ses(dir);
@@ -481,7 +481,7 @@ v9fs_vfs_getattr_dotl(struct vfsmount *mnt, struct dentry *dentry,
        p9_debug(P9_DEBUG_VFS, "dentry: %p\n", dentry);
        v9ses = v9fs_dentry2v9ses(dentry);
        if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
-               generic_fillattr(dentry->d_inode, stat);
+               generic_fillattr(d_inode(dentry), stat);
                return 0;
        }
        fid = v9fs_fid_lookup(dentry);
@@ -496,8 +496,8 @@ v9fs_vfs_getattr_dotl(struct vfsmount *mnt, struct dentry *dentry,
        if (IS_ERR(st))
                return PTR_ERR(st);
 
-       v9fs_stat2inode_dotl(st, dentry->d_inode);
-       generic_fillattr(dentry->d_inode, stat);
+       v9fs_stat2inode_dotl(st, d_inode(dentry));
+       generic_fillattr(d_inode(dentry), stat);
        /* Change block size to what the server returned */
        stat->blksize = st->st_blksize;
 
@@ -557,7 +557,7 @@ int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr)
        int retval;
        struct p9_fid *fid;
        struct p9_iattr_dotl p9attr;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
 
        p9_debug(P9_DEBUG_VFS, "\n");
 
@@ -795,10 +795,10 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir,
                if (IS_ERR(fid))
                        return PTR_ERR(fid);
 
-               v9fs_refresh_inode_dotl(fid, old_dentry->d_inode);
+               v9fs_refresh_inode_dotl(fid, d_inode(old_dentry));
        }
-       ihold(old_dentry->d_inode);
-       d_instantiate(dentry, old_dentry->d_inode);
+       ihold(d_inode(old_dentry));
+       d_instantiate(dentry, d_inode(old_dentry));
 
        return err;
 }
index 0afd0382822bca65bb87f10bffc1716f6944cefe..e99a338a46384128f32d6a32af8e549319f5121a 100644 (file)
@@ -168,8 +168,8 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
                        retval = PTR_ERR(st);
                        goto release_sb;
                }
-               root->d_inode->i_ino = v9fs_qid2ino(&st->qid);
-               v9fs_stat2inode_dotl(st, root->d_inode);
+               d_inode(root)->i_ino = v9fs_qid2ino(&st->qid);
+               v9fs_stat2inode_dotl(st, d_inode(root));
                kfree(st);
        } else {
                struct p9_wstat *st = NULL;
@@ -179,8 +179,8 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
                        goto release_sb;
                }
 
-               root->d_inode->i_ino = v9fs_qid2ino(&st->qid);
-               v9fs_stat2inode(st, root->d_inode, sb);
+               d_inode(root)->i_ino = v9fs_qid2ino(&st->qid);
+               v9fs_stat2inode(st, d_inode(root), sb);
 
                p9stat_free(st);
                kfree(st);
index b9acadafa4a10780d92c6d520008406fce4d5ddc..335055d828e45d082f24558ac5b1c155dac1fefb 100644 (file)
@@ -298,7 +298,7 @@ out:
 int
 adfs_notify_change(struct dentry *dentry, struct iattr *attr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct super_block *sb = inode->i_sb;
        unsigned int ia_valid = attr->ia_valid;
        int error;
index 5022ac96aa40f0ef1a05bd5f75e2d93de92cee77..a8f463c028ce9e9c52862e01a21de82a5b7e2f09 100644 (file)
@@ -138,7 +138,7 @@ affs_fix_dcache(struct inode *inode, u32 entry_ino)
 static int
 affs_remove_link(struct dentry *dentry)
 {
-       struct inode *dir, *inode = dentry->d_inode;
+       struct inode *dir, *inode = d_inode(dentry);
        struct super_block *sb = inode->i_sb;
        struct buffer_head *bh = NULL, *link_bh = NULL;
        u32 link_ino, ino;
@@ -268,11 +268,11 @@ affs_remove_header(struct dentry *dentry)
        struct buffer_head *bh = NULL;
        int retval;
 
-       dir = dentry->d_parent->d_inode;
+       dir = d_inode(dentry->d_parent);
        sb = dir->i_sb;
 
        retval = -ENOENT;
-       inode = dentry->d_inode;
+       inode = d_inode(dentry);
        if (!inode)
                goto done;
 
@@ -471,10 +471,9 @@ affs_warning(struct super_block *sb, const char *function, const char *fmt, ...)
 bool
 affs_nofilenametruncate(const struct dentry *dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
 
        return affs_test_opt(AFFS_SB(inode->i_sb)->s_flags, SF_NO_TRUNCATE);
-
 }
 
 /* Check if the name is valid for a affs object. */
index 9628003ccd2f676bdc0a0b673e210806a5d76982..a022f4accd76b801566564b7c6de2d38f2e1cdfb 100644 (file)
@@ -213,7 +213,7 @@ affs_write_inode(struct inode *inode, struct writeback_control *wbc)
 int
 affs_notify_change(struct dentry *dentry, struct iattr *attr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int error;
 
        pr_debug("notify_change(%lu,0x%x)\n", inode->i_ino, attr->ia_valid);
index ec8ca0efb960720402ab724125a39cdba9a9f198..181e05b46e7261d32ab9390daf7007b017af1e84 100644 (file)
@@ -251,7 +251,7 @@ int
 affs_unlink(struct inode *dir, struct dentry *dentry)
 {
        pr_debug("%s(dir=%lu, %lu \"%pd\")\n", __func__, dir->i_ino,
-                dentry->d_inode->i_ino, dentry);
+                d_inode(dentry)->i_ino, dentry);
 
        return affs_remove_header(dentry);
 }
@@ -320,7 +320,7 @@ int
 affs_rmdir(struct inode *dir, struct dentry *dentry)
 {
        pr_debug("%s(dir=%lu, %lu \"%pd\")\n", __func__, dir->i_ino,
-                dentry->d_inode->i_ino, dentry);
+                d_inode(dentry)->i_ino, dentry);
 
        return affs_remove_header(dentry);
 }
@@ -403,7 +403,7 @@ err:
 int
 affs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
 {
-       struct inode *inode = old_dentry->d_inode;
+       struct inode *inode = d_inode(old_dentry);
 
        pr_debug("%s(%lu, %lu, \"%pd\")\n", __func__, inode->i_ino, dir->i_ino,
                 dentry);
@@ -430,13 +430,13 @@ affs_rename(struct inode *old_dir, struct dentry *old_dentry,
                return retval;
 
        /* Unlink destination if it already exists */
-       if (new_dentry->d_inode) {
+       if (d_really_is_positive(new_dentry)) {
                retval = affs_remove_header(new_dentry);
                if (retval)
                        return retval;
        }
 
-       bh = affs_bread(sb, old_dentry->d_inode->i_ino);
+       bh = affs_bread(sb, d_inode(old_dentry)->i_ino);
        if (!bh)
                return -EIO;
 
index 4ec35e9130e1d7d2731ca381edbcc119b13da5a4..e10e17788f06073b2cd80204bf09343918654111 100644 (file)
@@ -505,7 +505,7 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
        _enter("{%x:%u},%p{%pd},",
               vnode->fid.vid, vnode->fid.vnode, dentry, dentry);
 
-       ASSERTCMP(dentry->d_inode, ==, NULL);
+       ASSERTCMP(d_inode(dentry), ==, NULL);
 
        if (dentry->d_name.len >= AFSNAMEMAX) {
                _leave(" = -ENAMETOOLONG");
@@ -563,8 +563,8 @@ success:
        _leave(" = 0 { vn=%u u=%u } -> { ino=%lu v=%u }",
               fid.vnode,
               fid.unique,
-              dentry->d_inode->i_ino,
-              dentry->d_inode->i_generation);
+              d_inode(dentry)->i_ino,
+              d_inode(dentry)->i_generation);
 
        return NULL;
 }
@@ -586,9 +586,9 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
        if (flags & LOOKUP_RCU)
                return -ECHILD;
 
-       vnode = AFS_FS_I(dentry->d_inode);
+       vnode = AFS_FS_I(d_inode(dentry));
 
-       if (dentry->d_inode)
+       if (d_really_is_positive(dentry))
                _enter("{v={%x:%u} n=%pd fl=%lx},",
                       vnode->fid.vid, vnode->fid.vnode, dentry,
                       vnode->flags);
@@ -601,7 +601,7 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
 
        /* lock down the parent dentry so we can peer at it */
        parent = dget_parent(dentry);
-       dir = AFS_FS_I(parent->d_inode);
+       dir = AFS_FS_I(d_inode(parent));
 
        /* validate the parent directory */
        if (test_bit(AFS_VNODE_MODIFIED, &dir->flags))
@@ -623,9 +623,9 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
        switch (ret) {
        case 0:
                /* the filename maps to something */
-               if (!dentry->d_inode)
+               if (d_really_is_negative(dentry))
                        goto out_bad;
-               if (is_bad_inode(dentry->d_inode)) {
+               if (is_bad_inode(d_inode(dentry))) {
                        printk("kAFS: afs_d_revalidate: %pd2 has bad inode\n",
                               dentry);
                        goto out_bad;
@@ -647,7 +647,7 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
                        _debug("%pd: file deleted (uq %u -> %u I:%u)",
                               dentry, fid.unique,
                               vnode->fid.unique,
-                              dentry->d_inode->i_generation);
+                              d_inode(dentry)->i_generation);
                        spin_lock(&vnode->lock);
                        set_bit(AFS_VNODE_DELETED, &vnode->flags);
                        spin_unlock(&vnode->lock);
@@ -658,7 +658,7 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
        case -ENOENT:
                /* the filename is unknown */
                _debug("%pd: dirent not found", dentry);
-               if (dentry->d_inode)
+               if (d_really_is_positive(dentry))
                        goto not_found;
                goto out_valid;
 
@@ -703,9 +703,9 @@ static int afs_d_delete(const struct dentry *dentry)
        if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
                goto zap;
 
-       if (dentry->d_inode &&
-           (test_bit(AFS_VNODE_DELETED,   &AFS_FS_I(dentry->d_inode)->flags) ||
-            test_bit(AFS_VNODE_PSEUDODIR, &AFS_FS_I(dentry->d_inode)->flags)))
+       if (d_really_is_positive(dentry) &&
+           (test_bit(AFS_VNODE_DELETED,   &AFS_FS_I(d_inode(dentry))->flags) ||
+            test_bit(AFS_VNODE_PSEUDODIR, &AFS_FS_I(d_inode(dentry))->flags)))
                goto zap;
 
        _leave(" = 0 [keep]");
@@ -814,8 +814,8 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
        if (ret < 0)
                goto rmdir_error;
 
-       if (dentry->d_inode) {
-               vnode = AFS_FS_I(dentry->d_inode);
+       if (d_really_is_positive(dentry)) {
+               vnode = AFS_FS_I(d_inode(dentry));
                clear_nlink(&vnode->vfs_inode);
                set_bit(AFS_VNODE_DELETED, &vnode->flags);
                afs_discard_callback_on_delete(vnode);
@@ -856,8 +856,8 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
                goto error;
        }
 
-       if (dentry->d_inode) {
-               vnode = AFS_FS_I(dentry->d_inode);
+       if (d_really_is_positive(dentry)) {
+               vnode = AFS_FS_I(d_inode(dentry));
 
                /* make sure we have a callback promise on the victim */
                ret = afs_validate(vnode, key);
@@ -869,7 +869,7 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
        if (ret < 0)
                goto remove_error;
 
-       if (dentry->d_inode) {
+       if (d_really_is_positive(dentry)) {
                /* if the file wasn't deleted due to excess hard links, the
                 * fileserver will break the callback promise on the file - if
                 * it had one - before it returns to us, and if it was deleted,
@@ -879,7 +879,7 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
                 * or it was outstanding on a different server, then it won't
                 * break it either...
                 */
-               vnode = AFS_FS_I(dentry->d_inode);
+               vnode = AFS_FS_I(d_inode(dentry));
                if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
                        _debug("AFS_VNODE_DELETED");
                if (test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags))
@@ -977,7 +977,7 @@ static int afs_link(struct dentry *from, struct inode *dir,
        struct key *key;
        int ret;
 
-       vnode = AFS_FS_I(from->d_inode);
+       vnode = AFS_FS_I(d_inode(from));
        dvnode = AFS_FS_I(dir);
 
        _enter("{%x:%u},{%x:%u},{%pd}",
@@ -1089,7 +1089,7 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
        struct key *key;
        int ret;
 
-       vnode = AFS_FS_I(old_dentry->d_inode);
+       vnode = AFS_FS_I(d_inode(old_dentry));
        orig_dvnode = AFS_FS_I(old_dir);
        new_dvnode = AFS_FS_I(new_dir);
 
index 8a1d38ef0fc203678883493a672c0f638f94a107..e06f5a23352ac65415f8bcb54450af2620588e95 100644 (file)
@@ -379,7 +379,7 @@ int afs_getattr(struct vfsmount *mnt, struct dentry *dentry,
 {
        struct inode *inode;
 
-       inode = dentry->d_inode;
+       inode = d_inode(dentry);
 
        _enter("{ ino=%lu v=%u }", inode->i_ino, inode->i_generation);
 
@@ -458,7 +458,7 @@ void afs_evict_inode(struct inode *inode)
  */
 int afs_setattr(struct dentry *dentry, struct iattr *attr)
 {
-       struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode);
+       struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry));
        struct key *key;
        int ret;
 
index 938c5ab06d5a2d875f22963a267b7e976ef5f339..ccd0b212e82a703b6ea1792339f7bf4603e5015f 100644 (file)
@@ -134,7 +134,7 @@ static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt)
 
        _enter("{%pd}", mntpt);
 
-       BUG_ON(!mntpt->d_inode);
+       BUG_ON(!d_inode(mntpt));
 
        ret = -ENOMEM;
        devname = (char *) get_zeroed_page(GFP_KERNEL);
@@ -145,7 +145,7 @@ static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt)
        if (!options)
                goto error_no_options;
 
-       vnode = AFS_FS_I(mntpt->d_inode);
+       vnode = AFS_FS_I(d_inode(mntpt));
        if (test_bit(AFS_VNODE_PSEUDODIR, &vnode->flags)) {
                /* if the directory is a pseudo directory, use the d_name */
                static const char afs_root_cell[] = ":root.cell.";
@@ -169,14 +169,14 @@ static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt)
                }
        } else {
                /* read the contents of the AFS special symlink */
-               loff_t size = i_size_read(mntpt->d_inode);
+               loff_t size = i_size_read(d_inode(mntpt));
                char *buf;
 
                ret = -EINVAL;
                if (size > PAGE_SIZE - 1)
                        goto error_no_page;
 
-               page = read_mapping_page(mntpt->d_inode->i_mapping, 0, NULL);
+               page = read_mapping_page(d_inode(mntpt)->i_mapping, 0, NULL);
                if (IS_ERR(page)) {
                        ret = PTR_ERR(page);
                        goto error_no_page;
index c4861557e38573796dd20237ff90938ee5f1429e..1fb4a5129f7dfc0007dfa52f287ca03766feeff0 100644 (file)
@@ -529,7 +529,7 @@ static void afs_destroy_inode(struct inode *inode)
 static int afs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
        struct afs_volume_status vs;
-       struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode);
+       struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry));
        struct key *key;
        int ret;
 
index d10e619632ab48b30390062455eef4b543b7c183..5b700ef1e59db31c9d8d71e9386566eb1c488774 100644 (file)
@@ -235,12 +235,12 @@ static inline u32 autofs4_get_dev(struct autofs_sb_info *sbi)
 
 static inline u64 autofs4_get_ino(struct autofs_sb_info *sbi)
 {
-       return sbi->sb->s_root->d_inode->i_ino;
+       return d_inode(sbi->sb->s_root)->i_ino;
 }
 
 static inline int simple_positive(struct dentry *dentry)
 {
-       return dentry->d_inode && !d_unhashed(dentry);
+       return d_really_is_positive(dentry) && !d_unhashed(dentry);
 }
 
 static inline void __autofs4_add_expiring(struct dentry *dentry)
index 11dd118f75e25e6a8f25f2143724901fb64c72a0..1cebc3c52fa5792242144c939908be50040b9e0b 100644 (file)
@@ -374,7 +374,7 @@ static struct dentry *should_expire(struct dentry *dentry,
                return NULL;
        }
 
-       if (dentry->d_inode && d_is_symlink(dentry)) {
+       if (d_really_is_positive(dentry) && d_is_symlink(dentry)) {
                DPRINTK("checking symlink %p %pd", dentry, dentry);
                /*
                 * A symlink can't be "busy" in the usual sense so
index 1c55388ae633c9908ab31934de070cbee08ae06f..a3ae0b2aeb5a0feeaeb43d5c3016bc13a0ca1d19 100644 (file)
@@ -71,7 +71,7 @@ void autofs4_kill_sb(struct super_block *sb)
 static int autofs4_show_options(struct seq_file *m, struct dentry *root)
 {
        struct autofs_sb_info *sbi = autofs4_sbi(root->d_sb);
-       struct inode *root_inode = root->d_sb->s_root->d_inode;
+       struct inode *root_inode = d_inode(root->d_sb->s_root);
 
        if (!sbi)
                return 0;
@@ -352,8 +352,8 @@ struct inode *autofs4_get_inode(struct super_block *sb, umode_t mode)
 
        inode->i_mode = mode;
        if (sb->s_root) {
-               inode->i_uid = sb->s_root->d_inode->i_uid;
-               inode->i_gid = sb->s_root->d_inode->i_gid;
+               inode->i_uid = d_inode(sb->s_root)->i_uid;
+               inode->i_gid = d_inode(sb->s_root)->i_gid;
        }
        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
        inode->i_ino = get_next_ino();
index 7e44fdd03e2dd0a684036be49e7c2152c192ee63..c6d7d3dbd52abfa9af11ea0fb7aab955e355bbc9 100644 (file)
@@ -240,7 +240,7 @@ static struct dentry *autofs4_lookup_expiring(struct dentry *dentry,
                spin_lock(&expiring->d_lock);
 
                /* We've already been dentry_iput or unlinked */
-               if (!expiring->d_inode)
+               if (d_really_is_negative(expiring))
                        goto next;
 
                qstr = &expiring->d_name;
@@ -371,7 +371,7 @@ static struct vfsmount *autofs4_d_automount(struct path *path)
         * having d_mountpoint() true, so there's no need to call back
         * to the daemon.
         */
-       if (dentry->d_inode && d_is_symlink(dentry)) {
+       if (d_really_is_positive(dentry) && d_is_symlink(dentry)) {
                spin_unlock(&sbi->fs_lock);
                goto done;
        }
@@ -459,7 +459,7 @@ static int autofs4_d_manage(struct dentry *dentry, bool rcu_walk)
                        return 0;
                if (d_mountpoint(dentry))
                        return 0;
-               inode = ACCESS_ONCE(dentry->d_inode);
+               inode = d_inode_rcu(dentry);
                if (inode && S_ISLNK(inode->i_mode))
                        return -EISDIR;
                if (list_empty(&dentry->d_subdirs))
@@ -485,7 +485,7 @@ static int autofs4_d_manage(struct dentry *dentry, bool rcu_walk)
                 * an incorrect ELOOP error return.
                 */
                if ((!d_mountpoint(dentry) && !simple_empty(dentry)) ||
-                   (dentry->d_inode && d_is_symlink(dentry)))
+                   (d_really_is_positive(dentry) && d_is_symlink(dentry)))
                        status = -EISDIR;
        }
        spin_unlock(&sbi->fs_lock);
@@ -625,8 +625,8 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry)
        }
        dput(ino->dentry);
 
-       dentry->d_inode->i_size = 0;
-       clear_nlink(dentry->d_inode);
+       d_inode(dentry)->i_size = 0;
+       clear_nlink(d_inode(dentry));
 
        dir->i_mtime = CURRENT_TIME;
 
@@ -719,8 +719,8 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
                        atomic_dec(&p_ino->count);
        }
        dput(ino->dentry);
-       dentry->d_inode->i_size = 0;
-       clear_nlink(dentry->d_inode);
+       d_inode(dentry)->i_size = 0;
+       clear_nlink(d_inode(dentry));
 
        if (dir->i_nlink)
                drop_nlink(dir);
@@ -839,7 +839,7 @@ static inline int autofs4_ask_umount(struct vfsmount *mnt, int __user *p)
 */
 int is_autofs4_dentry(struct dentry *dentry)
 {
-       return dentry && dentry->d_inode &&
+       return dentry && d_really_is_positive(dentry) &&
                dentry->d_op == &autofs4_dentry_operations &&
                dentry->d_fsdata != NULL;
 }
index 1e8ea192be2b13612e9702c4296f57611e50ba09..de58cc7b8076178605cea8f776031945d7d6da62 100644 (file)
@@ -18,7 +18,7 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
        struct autofs_info *ino = autofs4_dentry_ino(dentry);
        if (ino && !autofs4_oz_mode(sbi))
                ino->last_used = jiffies;
-       nd_set_link(nd, dentry->d_inode->i_private);
+       nd_set_link(nd, d_inode(dentry)->i_private);
        return NULL;
 }
 
index 2ad05ab93db86efe0e4d0432b7ed8f1f37a0dd52..35b755e79c2d9b311d0eb899dd749580cb42b209 100644 (file)
@@ -322,7 +322,7 @@ static int validate_request(struct autofs_wait_queue **wait,
                 * continue on and create a new request.
                 */
                if (!IS_ROOT(dentry)) {
-                       if (dentry->d_inode && d_unhashed(dentry)) {
+                       if (d_really_is_positive(dentry) && d_unhashed(dentry)) {
                                struct dentry *parent = dentry->d_parent;
                                new = d_lookup(parent, &dentry->d_name);
                                if (new)
@@ -364,7 +364,7 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
        if (pid == 0 || tgid == 0)
                return -ENOENT;
 
-       if (!dentry->d_inode) {
+       if (d_really_is_negative(dentry)) {
                /*
                 * A wait for a negative dentry is invalid for certain
                 * cases. A direct or offset mount "always" has its mount
index 16e0a48bfccd41e904a8044beced4d84af1bdbe7..7943533c386802dc880051cc7ac2b078cf5d3ccb 100644 (file)
@@ -471,7 +471,7 @@ static void *
 befs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        struct super_block *sb = dentry->d_sb;
-       struct befs_inode_info *befs_ino = BEFS_I(dentry->d_inode);
+       struct befs_inode_info *befs_ino = BEFS_I(d_inode(dentry));
        befs_data_stream *data = &befs_ino->i_data.ds;
        befs_off_t len = data->size;
        char *link;
@@ -501,7 +501,7 @@ befs_follow_link(struct dentry *dentry, struct nameidata *nd)
 static void *
 befs_fast_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-       struct befs_inode_info *befs_ino = BEFS_I(dentry->d_inode);
+       struct befs_inode_info *befs_ino = BEFS_I(d_inode(dentry));
 
        nd_set_link(nd, befs_ino->i_data.symlink);
        return NULL;
index 7a8182770649dd48b3a35a1b28dfa1ff13252e6b..3ec6113146c0b6de610d507f85704f2d7187ad7e 100644 (file)
@@ -153,7 +153,7 @@ static struct dentry *bfs_lookup(struct inode *dir, struct dentry *dentry,
 static int bfs_link(struct dentry *old, struct inode *dir,
                                                struct dentry *new)
 {
-       struct inode *inode = old->d_inode;
+       struct inode *inode = d_inode(old);
        struct bfs_sb_info *info = BFS_SB(inode->i_sb);
        int err;
 
@@ -176,7 +176,7 @@ static int bfs_link(struct dentry *old, struct inode *dir,
 static int bfs_unlink(struct inode *dir, struct dentry *dentry)
 {
        int error = -ENOENT;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct buffer_head *bh;
        struct bfs_dirent *de;
        struct bfs_sb_info *info = BFS_SB(inode->i_sb);
@@ -216,7 +216,7 @@ static int bfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        int error = -ENOENT;
 
        old_bh = new_bh = NULL;
-       old_inode = old_dentry->d_inode;
+       old_inode = d_inode(old_dentry);
        if (S_ISDIR(old_inode->i_mode))
                return -EINVAL;
 
@@ -231,7 +231,7 @@ static int bfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                goto end_rename;
 
        error = -EPERM;
-       new_inode = new_dentry->d_inode;
+       new_inode = d_inode(new_dentry);
        new_bh = bfs_find_entry(new_dir, 
                                new_dentry->d_name.name, 
                                new_dentry->d_name.len, &new_de);
index 9dcb05409ba7e7aadf43a1e46ad52eac24828f6f..78f005f378476011a43c41e7d0eaa8d99ac1af21 100644 (file)
@@ -591,7 +591,7 @@ static void kill_node(Node *e)
        write_unlock(&entries_lock);
 
        if (dentry) {
-               drop_nlink(dentry->d_inode);
+               drop_nlink(d_inode(dentry));
                d_drop(dentry);
                dput(dentry);
                simple_release_fs(&bm_mnt, &entry_count);
@@ -638,11 +638,11 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer,
        case 3:
                /* Delete this handler. */
                root = dget(file->f_path.dentry->d_sb->s_root);
-               mutex_lock(&root->d_inode->i_mutex);
+               mutex_lock(&d_inode(root)->i_mutex);
 
                kill_node(e);
 
-               mutex_unlock(&root->d_inode->i_mutex);
+               mutex_unlock(&d_inode(root)->i_mutex);
                dput(root);
                break;
        default:
@@ -675,14 +675,14 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer,
                return PTR_ERR(e);
 
        root = dget(sb->s_root);
-       mutex_lock(&root->d_inode->i_mutex);
+       mutex_lock(&d_inode(root)->i_mutex);
        dentry = lookup_one_len(e->name, root, strlen(e->name));
        err = PTR_ERR(dentry);
        if (IS_ERR(dentry))
                goto out;
 
        err = -EEXIST;
-       if (dentry->d_inode)
+       if (d_really_is_positive(dentry))
                goto out2;
 
        inode = bm_get_inode(sb, S_IFREG | 0644);
@@ -711,7 +711,7 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer,
 out2:
        dput(dentry);
 out:
-       mutex_unlock(&root->d_inode->i_mutex);
+       mutex_unlock(&d_inode(root)->i_mutex);
        dput(root);
 
        if (err) {
@@ -754,12 +754,12 @@ static ssize_t bm_status_write(struct file *file, const char __user *buffer,
        case 3:
                /* Delete all handlers. */
                root = dget(file->f_path.dentry->d_sb->s_root);
-               mutex_lock(&root->d_inode->i_mutex);
+               mutex_lock(&d_inode(root)->i_mutex);
 
                while (!list_empty(&entries))
                        kill_node(list_entry(entries.next, Node, list));
 
-               mutex_unlock(&root->d_inode->i_mutex);
+               mutex_unlock(&d_inode(root)->i_mutex);
                dput(root);
                break;
        default:
index 897ee0503932fbbf7adc88b0fd27591576696160..c7e4163ede87f3370a235bdb929cf26e5cd487e8 100644 (file)
@@ -152,7 +152,8 @@ blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, loff_t offset)
        struct inode *inode = file->f_mapping->host;
 
        return __blockdev_direct_IO(iocb, inode, I_BDEV(inode), iter, offset,
-                                   blkdev_get_block, NULL, NULL, 0);
+                                   blkdev_get_block, NULL, NULL,
+                                   DIO_SKIP_DIO_COUNT);
 }
 
 int __sync_blockdev(struct block_device *bdev, int wait)
@@ -1716,7 +1717,7 @@ struct block_device *lookup_bdev(const char *pathname)
        if (error)
                return ERR_PTR(error);
 
-       inode = path.dentry->d_inode;
+       inode = d_backing_inode(path.dentry);
        error = -ENOTBLK;
        if (!S_ISBLK(inode->i_mode))
                goto fail;
index 4dabeb893b7c18cced67230fd8fbcc36c677983b..df9932b00d08fdc666f63c84014fbd08889cf624 100644 (file)
@@ -87,7 +87,7 @@ BTRFS_WORK_HELPER(scrubwrc_helper);
 BTRFS_WORK_HELPER(scrubnc_helper);
 
 static struct __btrfs_workqueue *
-__btrfs_alloc_workqueue(const char *name, int flags, int max_active,
+__btrfs_alloc_workqueue(const char *name, unsigned int flags, int max_active,
                         int thresh)
 {
        struct __btrfs_workqueue *ret = kzalloc(sizeof(*ret), GFP_NOFS);
@@ -132,7 +132,7 @@ static inline void
 __btrfs_destroy_workqueue(struct __btrfs_workqueue *wq);
 
 struct btrfs_workqueue *btrfs_alloc_workqueue(const char *name,
-                                             int flags,
+                                             unsigned int flags,
                                              int max_active,
                                              int thresh)
 {
index e386c29ef1f62c559a184e4ae31884c2bcc425ba..ec2ee477f8ba003ee7af4030da1b976891073dcf 100644 (file)
@@ -66,7 +66,7 @@ BTRFS_WORK_HELPER_PROTO(scrubwrc_helper);
 BTRFS_WORK_HELPER_PROTO(scrubnc_helper);
 
 struct btrfs_workqueue *btrfs_alloc_workqueue(const char *name,
-                                             int flags,
+                                             unsigned int flags,
                                              int max_active,
                                              int thresh);
 void btrfs_init_work(struct btrfs_work *work, btrfs_work_func_t helper,
index f55721ff938544c1b73d0d8cb057a52dba5b7884..9de772ee0031707c59292ac7849520ef8d6e9e47 100644 (file)
@@ -1206,7 +1206,7 @@ int btrfs_check_shared(struct btrfs_trans_handle *trans,
        struct ulist *roots = NULL;
        struct ulist_iterator uiter;
        struct ulist_node *node;
-       struct seq_list elem = {};
+       struct seq_list elem = SEQ_LIST_INIT(elem);
        int ret = 0;
 
        tmp = ulist_alloc(GFP_NOFS);
@@ -1610,7 +1610,7 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info,
        struct ulist *roots = NULL;
        struct ulist_node *ref_node = NULL;
        struct ulist_node *root_node = NULL;
-       struct seq_list tree_mod_seq_elem = {};
+       struct seq_list tree_mod_seq_elem = SEQ_LIST_INIT(tree_mod_seq_elem);
        struct ulist_iterator ref_uiter;
        struct ulist_iterator root_uiter;
 
index de5e4f2adfeac9d07ba2539a8098b44cc9781580..0ef5cc13fae26f8899cad7ed30b59344c79120d4 100644 (file)
@@ -66,7 +66,11 @@ struct btrfs_inode {
         */
        struct btrfs_key location;
 
-       /* Lock for counters */
+       /*
+        * Lock for counters and all fields used to determine if the inode is in
+        * the log or not (last_trans, last_sub_trans, last_log_commit,
+        * logged_trans).
+        */
        spinlock_t lock;
 
        /* the extent_tree has caches of all the extent mappings to disk */
@@ -250,6 +254,9 @@ static inline bool btrfs_is_free_space_inode(struct inode *inode)
 
 static inline int btrfs_inode_in_log(struct inode *inode, u64 generation)
 {
+       int ret = 0;
+
+       spin_lock(&BTRFS_I(inode)->lock);
        if (BTRFS_I(inode)->logged_trans == generation &&
            BTRFS_I(inode)->last_sub_trans <=
            BTRFS_I(inode)->last_log_commit &&
@@ -263,9 +270,10 @@ static inline int btrfs_inode_in_log(struct inode *inode, u64 generation)
                 */
                smp_mb();
                if (list_empty(&BTRFS_I(inode)->extent_tree.modified_extents))
-                       return 1;
+                       ret = 1;
        }
-       return 0;
+       spin_unlock(&BTRFS_I(inode)->lock);
+       return ret;
 }
 
 #define BTRFS_DIO_ORIG_BIO_SUBMITTED   0x1
index d897ef803b3b6f3efcb0e8fc3d05bbeff994da35..ce7dec88f4b82c63ddefdc9398adcbda767d6c99 100644 (file)
@@ -2990,8 +2990,8 @@ static void __btrfsic_submit_bio(int rw, struct bio *bio)
                               (unsigned long long)bio->bi_iter.bi_sector,
                               dev_bytenr, bio->bi_bdev);
 
-               mapped_datav = kmalloc(sizeof(*mapped_datav) * bio->bi_vcnt,
-                                      GFP_NOFS);
+               mapped_datav = kmalloc_array(bio->bi_vcnt,
+                                            sizeof(*mapped_datav), GFP_NOFS);
                if (!mapped_datav)
                        goto leave;
                cur_bytenr = dev_bytenr;
@@ -3241,8 +3241,5 @@ void btrfsic_unmount(struct btrfs_root *root,
 
        mutex_unlock(&btrfsic_mutex);
 
-       if (is_vmalloc_addr(state))
-               vfree(state);
-       else
-               kfree(state);
+       kvfree(state);
 }
index e9df8862012c6291be4ff802918ba15a6dda6744..ce62324c78e7dbc734a2793c39a89de38238e27b 100644 (file)
@@ -622,7 +622,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
        cb->orig_bio = bio;
 
        nr_pages = DIV_ROUND_UP(compressed_len, PAGE_CACHE_SIZE);
-       cb->compressed_pages = kzalloc(sizeof(struct page *) * nr_pages,
+       cb->compressed_pages = kcalloc(nr_pages, sizeof(struct page *),
                                       GFP_NOFS);
        if (!cb->compressed_pages)
                goto fail1;
@@ -750,7 +750,7 @@ static int comp_num_workspace[BTRFS_COMPRESS_TYPES];
 static atomic_t comp_alloc_workspace[BTRFS_COMPRESS_TYPES];
 static wait_queue_head_t comp_workspace_wait[BTRFS_COMPRESS_TYPES];
 
-static struct btrfs_compress_op *btrfs_compress_op[] = {
+static const struct btrfs_compress_op * const btrfs_compress_op[] = {
        &btrfs_zlib_compress,
        &btrfs_lzo_compress,
 };
index d181f70caae01471ca80e181818a833b41f057de..13a4dc0436c9d3072b401312b3d3bf82a789ae4e 100644 (file)
@@ -77,7 +77,7 @@ struct btrfs_compress_op {
                          size_t srclen, size_t destlen);
 };
 
-extern struct btrfs_compress_op btrfs_zlib_compress;
-extern struct btrfs_compress_op btrfs_lzo_compress;
+extern const struct btrfs_compress_op btrfs_zlib_compress;
+extern const struct btrfs_compress_op btrfs_lzo_compress;
 
 #endif
index 6d67f32e648df72bc5f5b5d707ff39ce8fa4302b..0f11ebc92f02ac69ffe3302624852cf9e467656a 100644 (file)
@@ -578,7 +578,7 @@ tree_mod_log_insert_move(struct btrfs_fs_info *fs_info,
        if (!tree_mod_need_log(fs_info, eb))
                return 0;
 
-       tm_list = kzalloc(nr_items * sizeof(struct tree_mod_elem *), flags);
+       tm_list = kcalloc(nr_items, sizeof(struct tree_mod_elem *), flags);
        if (!tm_list)
                return -ENOMEM;
 
@@ -677,7 +677,7 @@ tree_mod_log_insert_root(struct btrfs_fs_info *fs_info,
 
        if (log_removal && btrfs_header_level(old_root) > 0) {
                nritems = btrfs_header_nritems(old_root);
-               tm_list = kzalloc(nritems * sizeof(struct tree_mod_elem *),
+               tm_list = kcalloc(nritems, sizeof(struct tree_mod_elem *),
                                  flags);
                if (!tm_list) {
                        ret = -ENOMEM;
@@ -814,7 +814,7 @@ tree_mod_log_eb_copy(struct btrfs_fs_info *fs_info, struct extent_buffer *dst,
        if (btrfs_header_level(dst) == 0 && btrfs_header_level(src) == 0)
                return 0;
 
-       tm_list = kzalloc(nr_items * 2 * sizeof(struct tree_mod_elem *),
+       tm_list = kcalloc(nr_items * 2, sizeof(struct tree_mod_elem *),
                          GFP_NOFS);
        if (!tm_list)
                return -ENOMEM;
@@ -905,8 +905,7 @@ tree_mod_log_free_eb(struct btrfs_fs_info *fs_info, struct extent_buffer *eb)
                return 0;
 
        nritems = btrfs_header_nritems(eb);
-       tm_list = kzalloc(nritems * sizeof(struct tree_mod_elem *),
-                         GFP_NOFS);
+       tm_list = kcalloc(nritems, sizeof(struct tree_mod_elem *), GFP_NOFS);
        if (!tm_list)
                return -ENOMEM;
 
@@ -1073,7 +1072,7 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
                        ret = btrfs_dec_ref(trans, root, buf, 1);
                        BUG_ON(ret); /* -ENOMEM */
                }
-               clean_tree_block(trans, root, buf);
+               clean_tree_block(trans, root->fs_info, buf);
                *last_ref = 1;
        }
        return 0;
@@ -1678,7 +1677,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
                        continue;
                }
 
-               cur = btrfs_find_tree_block(root, blocknr);
+               cur = btrfs_find_tree_block(root->fs_info, blocknr);
                if (cur)
                        uptodate = btrfs_buffer_uptodate(cur, gen, 0);
                else
@@ -1943,7 +1942,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
 
                path->locks[level] = 0;
                path->nodes[level] = NULL;
-               clean_tree_block(trans, root, mid);
+               clean_tree_block(trans, root->fs_info, mid);
                btrfs_tree_unlock(mid);
                /* once for the path */
                free_extent_buffer(mid);
@@ -1997,7 +1996,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
                if (wret < 0 && wret != -ENOSPC)
                        ret = wret;
                if (btrfs_header_nritems(right) == 0) {
-                       clean_tree_block(trans, root, right);
+                       clean_tree_block(trans, root->fs_info, right);
                        btrfs_tree_unlock(right);
                        del_ptr(root, path, level + 1, pslot + 1);
                        root_sub_used(root, right->len);
@@ -2041,7 +2040,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
                BUG_ON(wret == 1);
        }
        if (btrfs_header_nritems(mid) == 0) {
-               clean_tree_block(trans, root, mid);
+               clean_tree_block(trans, root->fs_info, mid);
                btrfs_tree_unlock(mid);
                del_ptr(root, path, level + 1, pslot);
                root_sub_used(root, mid->len);
@@ -2259,7 +2258,7 @@ static void reada_for_search(struct btrfs_root *root,
 
        search = btrfs_node_blockptr(node, slot);
        blocksize = root->nodesize;
-       eb = btrfs_find_tree_block(root, search);
+       eb = btrfs_find_tree_block(root->fs_info, search);
        if (eb) {
                free_extent_buffer(eb);
                return;
@@ -2319,7 +2318,7 @@ static noinline void reada_for_balance(struct btrfs_root *root,
        if (slot > 0) {
                block1 = btrfs_node_blockptr(parent, slot - 1);
                gen = btrfs_node_ptr_generation(parent, slot - 1);
-               eb = btrfs_find_tree_block(root, block1);
+               eb = btrfs_find_tree_block(root->fs_info, block1);
                /*
                 * if we get -eagain from btrfs_buffer_uptodate, we
                 * don't want to return eagain here.  That will loop
@@ -2332,7 +2331,7 @@ static noinline void reada_for_balance(struct btrfs_root *root,
        if (slot + 1 < nritems) {
                block2 = btrfs_node_blockptr(parent, slot + 1);
                gen = btrfs_node_ptr_generation(parent, slot + 1);
-               eb = btrfs_find_tree_block(root, block2);
+               eb = btrfs_find_tree_block(root->fs_info, block2);
                if (eb && btrfs_buffer_uptodate(eb, gen, 1) != 0)
                        block2 = 0;
                free_extent_buffer(eb);
@@ -2450,7 +2449,7 @@ read_block_for_search(struct btrfs_trans_handle *trans,
        blocknr = btrfs_node_blockptr(b, slot);
        gen = btrfs_node_ptr_generation(b, slot);
 
-       tmp = btrfs_find_tree_block(root, blocknr);
+       tmp = btrfs_find_tree_block(root->fs_info, blocknr);
        if (tmp) {
                /* first we do an atomic uptodate check */
                if (btrfs_buffer_uptodate(tmp, gen, 1) > 0) {
@@ -3126,7 +3125,8 @@ again:
  * higher levels
  *
  */
-static void fixup_low_keys(struct btrfs_root *root, struct btrfs_path *path,
+static void fixup_low_keys(struct btrfs_fs_info *fs_info,
+                          struct btrfs_path *path,
                           struct btrfs_disk_key *key, int level)
 {
        int i;
@@ -3137,7 +3137,7 @@ static void fixup_low_keys(struct btrfs_root *root, struct btrfs_path *path,
                if (!path->nodes[i])
                        break;
                t = path->nodes[i];
-               tree_mod_log_set_node_key(root->fs_info, t, tslot, 1);
+               tree_mod_log_set_node_key(fs_info, t, tslot, 1);
                btrfs_set_node_key(t, key, tslot);
                btrfs_mark_buffer_dirty(path->nodes[i]);
                if (tslot != 0)
@@ -3151,7 +3151,8 @@ static void fixup_low_keys(struct btrfs_root *root, struct btrfs_path *path,
  * This function isn't completely safe. It's the caller's responsibility
  * that the new key won't break the order
  */
-void btrfs_set_item_key_safe(struct btrfs_root *root, struct btrfs_path *path,
+void btrfs_set_item_key_safe(struct btrfs_fs_info *fs_info,
+                            struct btrfs_path *path,
                             struct btrfs_key *new_key)
 {
        struct btrfs_disk_key disk_key;
@@ -3173,7 +3174,7 @@ void btrfs_set_item_key_safe(struct btrfs_root *root, struct btrfs_path *path,
        btrfs_set_item_key(eb, &disk_key, slot);
        btrfs_mark_buffer_dirty(eb);
        if (slot == 0)
-               fixup_low_keys(root, path, &disk_key, 1);
+               fixup_low_keys(fs_info, path, &disk_key, 1);
 }
 
 /*
@@ -3692,7 +3693,7 @@ static noinline int __push_leaf_right(struct btrfs_trans_handle *trans,
        if (left_nritems)
                btrfs_mark_buffer_dirty(left);
        else
-               clean_tree_block(trans, root, left);
+               clean_tree_block(trans, root->fs_info, left);
 
        btrfs_mark_buffer_dirty(right);
 
@@ -3704,7 +3705,7 @@ static noinline int __push_leaf_right(struct btrfs_trans_handle *trans,
        if (path->slots[0] >= left_nritems) {
                path->slots[0] -= left_nritems;
                if (btrfs_header_nritems(path->nodes[0]) == 0)
-                       clean_tree_block(trans, root, path->nodes[0]);
+                       clean_tree_block(trans, root->fs_info, path->nodes[0]);
                btrfs_tree_unlock(path->nodes[0]);
                free_extent_buffer(path->nodes[0]);
                path->nodes[0] = right;
@@ -3928,10 +3929,10 @@ static noinline int __push_leaf_left(struct btrfs_trans_handle *trans,
        if (right_nritems)
                btrfs_mark_buffer_dirty(right);
        else
-               clean_tree_block(trans, root, right);
+               clean_tree_block(trans, root->fs_info, right);
 
        btrfs_item_key(right, &disk_key, 0);
-       fixup_low_keys(root, path, &disk_key, 1);
+       fixup_low_keys(root->fs_info, path, &disk_key, 1);
 
        /* then fixup the leaf pointer in the path */
        if (path->slots[0] < push_items) {
@@ -4168,6 +4169,7 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans,
        int mid;
        int slot;
        struct extent_buffer *right;
+       struct btrfs_fs_info *fs_info = root->fs_info;
        int ret = 0;
        int wret;
        int split;
@@ -4271,10 +4273,10 @@ again:
        btrfs_set_header_backref_rev(right, BTRFS_MIXED_BACKREF_REV);
        btrfs_set_header_owner(right, root->root_key.objectid);
        btrfs_set_header_level(right, 0);
-       write_extent_buffer(right, root->fs_info->fsid,
+       write_extent_buffer(right, fs_info->fsid,
                            btrfs_header_fsid(), BTRFS_FSID_SIZE);
 
-       write_extent_buffer(right, root->fs_info->chunk_tree_uuid,
+       write_extent_buffer(right, fs_info->chunk_tree_uuid,
                            btrfs_header_chunk_tree_uuid(right),
                            BTRFS_UUID_SIZE);
 
@@ -4297,7 +4299,7 @@ again:
                        path->nodes[0] = right;
                        path->slots[0] = 0;
                        if (path->slots[1] == 0)
-                               fixup_low_keys(root, path, &disk_key, 1);
+                               fixup_low_keys(fs_info, path, &disk_key, 1);
                }
                btrfs_mark_buffer_dirty(right);
                return ret;
@@ -4615,7 +4617,7 @@ void btrfs_truncate_item(struct btrfs_root *root, struct btrfs_path *path,
                btrfs_set_disk_key_offset(&disk_key, offset + size_diff);
                btrfs_set_item_key(leaf, &disk_key, slot);
                if (slot == 0)
-                       fixup_low_keys(root, path, &disk_key, 1);
+                       fixup_low_keys(root->fs_info, path, &disk_key, 1);
        }
 
        item = btrfs_item_nr(slot);
@@ -4716,7 +4718,7 @@ void setup_items_for_insert(struct btrfs_root *root, struct btrfs_path *path,
 
        if (path->slots[0] == 0) {
                btrfs_cpu_key_to_disk(&disk_key, cpu_key);
-               fixup_low_keys(root, path, &disk_key, 1);
+               fixup_low_keys(root->fs_info, path, &disk_key, 1);
        }
        btrfs_unlock_up_safe(path, 1);
 
@@ -4888,7 +4890,7 @@ static void del_ptr(struct btrfs_root *root, struct btrfs_path *path,
                struct btrfs_disk_key disk_key;
 
                btrfs_node_key(parent, &disk_key, 0);
-               fixup_low_keys(root, path, &disk_key, level + 1);
+               fixup_low_keys(root->fs_info, path, &disk_key, level + 1);
        }
        btrfs_mark_buffer_dirty(parent);
 }
@@ -4981,7 +4983,7 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
                        btrfs_set_header_level(leaf, 0);
                } else {
                        btrfs_set_path_blocking(path);
-                       clean_tree_block(trans, root, leaf);
+                       clean_tree_block(trans, root->fs_info, leaf);
                        btrfs_del_leaf(trans, root, path, leaf);
                }
        } else {
@@ -4990,7 +4992,7 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
                        struct btrfs_disk_key disk_key;
 
                        btrfs_item_key(leaf, &disk_key, 0);
-                       fixup_low_keys(root, path, &disk_key, 1);
+                       fixup_low_keys(root->fs_info, path, &disk_key, 1);
                }
 
                /* delete the leaf if it is mostly empty */
index f9c89cae39ee41fd6ae37bbc36178f8eb9093044..6f364e1d8d3d1e9c08e246dbc1df443be49c33fd 100644 (file)
@@ -1061,6 +1061,12 @@ struct btrfs_block_group_item {
        __le64 flags;
 } __attribute__ ((__packed__));
 
+#define BTRFS_QGROUP_LEVEL_SHIFT               48
+static inline u64 btrfs_qgroup_level(u64 qgroupid)
+{
+       return qgroupid >> BTRFS_QGROUP_LEVEL_SHIFT;
+}
+
 /*
  * is subvolume quota turned on?
  */
@@ -1256,6 +1262,20 @@ struct btrfs_caching_control {
        atomic_t count;
 };
 
+struct btrfs_io_ctl {
+       void *cur, *orig;
+       struct page *page;
+       struct page **pages;
+       struct btrfs_root *root;
+       struct inode *inode;
+       unsigned long size;
+       int index;
+       int num_pages;
+       int entries;
+       int bitmaps;
+       unsigned check_crcs:1;
+};
+
 struct btrfs_block_group_cache {
        struct btrfs_key key;
        struct btrfs_block_group_item item;
@@ -1321,6 +1341,9 @@ struct btrfs_block_group_cache {
 
        /* For dirty block groups */
        struct list_head dirty_list;
+       struct list_head io_list;
+
+       struct btrfs_io_ctl io_ctl;
 };
 
 /* delayed seq elem */
@@ -1329,6 +1352,8 @@ struct seq_list {
        u64 seq;
 };
 
+#define SEQ_LIST_INIT(name)    { .list = LIST_HEAD_INIT((name).list), .seq = 0 }
+
 enum btrfs_orphan_cleanup_state {
        ORPHAN_CLEANUP_STARTED  = 1,
        ORPHAN_CLEANUP_DONE     = 2,
@@ -1472,6 +1497,12 @@ struct btrfs_fs_info {
        struct mutex chunk_mutex;
        struct mutex volume_mutex;
 
+       /*
+        * this is taken to make sure we don't set block groups ro after
+        * the free space cache has been allocated on them
+        */
+       struct mutex ro_block_group_mutex;
+
        /* this is used during read/modify/write to make sure
         * no two ios are trying to mod the same stripe at the same
         * time
@@ -1513,6 +1544,7 @@ struct btrfs_fs_info {
 
        spinlock_t delayed_iput_lock;
        struct list_head delayed_iputs;
+       struct rw_semaphore delayed_iput_sem;
 
        /* this protects tree_mod_seq_list */
        spinlock_t tree_mod_seq_lock;
@@ -3295,6 +3327,9 @@ static inline gfp_t btrfs_alloc_write_mask(struct address_space *mapping)
 }
 
 /* extent-tree.c */
+
+u64 btrfs_csum_bytes_to_leaves(struct btrfs_root *root, u64 csum_bytes);
+
 static inline u64 btrfs_calc_trans_metadata_size(struct btrfs_root *root,
                                                 unsigned num_items)
 {
@@ -3385,6 +3420,8 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
                         u64 bytenr, u64 num_bytes, u64 parent,
                         u64 root_objectid, u64 owner, u64 offset, int no_quota);
 
+int btrfs_start_dirty_block_groups(struct btrfs_trans_handle *trans,
+                                  struct btrfs_root *root);
 int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
                                    struct btrfs_root *root);
 int btrfs_setup_space_cache(struct btrfs_trans_handle *trans,
@@ -3417,7 +3454,7 @@ enum btrfs_reserve_flush_enum {
        BTRFS_RESERVE_FLUSH_ALL,
 };
 
-int btrfs_check_data_free_space(struct inode *inode, u64 bytes);
+int btrfs_check_data_free_space(struct inode *inode, u64 bytes, u64 write_bytes);
 void btrfs_free_reserved_data_space(struct inode *inode, u64 bytes);
 void btrfs_trans_release_metadata(struct btrfs_trans_handle *trans,
                                struct btrfs_root *root);
@@ -3440,6 +3477,7 @@ struct btrfs_block_rsv *btrfs_alloc_block_rsv(struct btrfs_root *root,
                                              unsigned short type);
 void btrfs_free_block_rsv(struct btrfs_root *root,
                          struct btrfs_block_rsv *rsv);
+void __btrfs_free_block_rsv(struct btrfs_block_rsv *rsv);
 int btrfs_block_rsv_add(struct btrfs_root *root,
                        struct btrfs_block_rsv *block_rsv, u64 num_bytes,
                        enum btrfs_reserve_flush_enum flush);
@@ -3486,7 +3524,8 @@ int btrfs_previous_item(struct btrfs_root *root,
                        int type);
 int btrfs_previous_extent_item(struct btrfs_root *root,
                        struct btrfs_path *path, u64 min_objectid);
-void btrfs_set_item_key_safe(struct btrfs_root *root, struct btrfs_path *path,
+void btrfs_set_item_key_safe(struct btrfs_fs_info *fs_info,
+                            struct btrfs_path *path,
                             struct btrfs_key *new_key);
 struct extent_buffer *btrfs_root_node(struct btrfs_root *root);
 struct extent_buffer *btrfs_lock_root_node(struct btrfs_root *root);
@@ -4180,7 +4219,8 @@ int btree_readahead_hook(struct btrfs_root *root, struct extent_buffer *eb,
 static inline int is_fstree(u64 rootid)
 {
        if (rootid == BTRFS_FS_TREE_OBJECTID ||
-           (s64)rootid >= (s64)BTRFS_FIRST_FREE_OBJECTID)
+           ((s64)rootid >= (s64)BTRFS_FIRST_FREE_OBJECTID &&
+             !btrfs_qgroup_level(rootid)))
                return 1;
        return 0;
 }
index 82f0c7c954747363859fff768917f34ec67765ab..a2ae42720a6afe92701de402b837d56dd66d03b4 100644 (file)
@@ -1383,7 +1383,7 @@ out:
 
 
 static int btrfs_wq_run_delayed_node(struct btrfs_delayed_root *delayed_root,
-                                    struct btrfs_root *root, int nr)
+                                    struct btrfs_fs_info *fs_info, int nr)
 {
        struct btrfs_async_delayed_work *async_work;
 
@@ -1399,7 +1399,7 @@ static int btrfs_wq_run_delayed_node(struct btrfs_delayed_root *delayed_root,
                        btrfs_async_run_delayed_root, NULL, NULL);
        async_work->nr = nr;
 
-       btrfs_queue_work(root->fs_info->delayed_workers, &async_work->work);
+       btrfs_queue_work(fs_info->delayed_workers, &async_work->work);
        return 0;
 }
 
@@ -1426,6 +1426,7 @@ static int could_end_wait(struct btrfs_delayed_root *delayed_root, int seq)
 void btrfs_balance_delayed_items(struct btrfs_root *root)
 {
        struct btrfs_delayed_root *delayed_root;
+       struct btrfs_fs_info *fs_info = root->fs_info;
 
        delayed_root = btrfs_get_delayed_root(root);
 
@@ -1438,7 +1439,7 @@ void btrfs_balance_delayed_items(struct btrfs_root *root)
 
                seq = atomic_read(&delayed_root->items_seq);
 
-               ret = btrfs_wq_run_delayed_node(delayed_root, root, 0);
+               ret = btrfs_wq_run_delayed_node(delayed_root, fs_info, 0);
                if (ret)
                        return;
 
@@ -1447,7 +1448,7 @@ void btrfs_balance_delayed_items(struct btrfs_root *root)
                return;
        }
 
-       btrfs_wq_run_delayed_node(delayed_root, root, BTRFS_DELAYED_BATCH);
+       btrfs_wq_run_delayed_node(delayed_root, fs_info, BTRFS_DELAYED_BATCH);
 }
 
 /* Will return 0 or -ENOMEM */
@@ -1801,6 +1802,8 @@ int btrfs_fill_inode(struct inode *inode, u32 *rdev)
        set_nlink(inode, btrfs_stack_inode_nlink(inode_item));
        inode_set_bytes(inode, btrfs_stack_inode_nbytes(inode_item));
        BTRFS_I(inode)->generation = btrfs_stack_inode_generation(inode_item);
+        BTRFS_I(inode)->last_trans = btrfs_stack_inode_transid(inode_item);
+
        inode->i_version = btrfs_stack_inode_sequence(inode_item);
        inode->i_rdev = 0;
        *rdev = btrfs_stack_inode_rdev(inode_item);
index 6d16bea94e1cd1cac5c102efa8b50290c2b4e218..8f8ed7d20bac5f4e058fc693d0fdc24fde7abeda 100644 (file)
@@ -489,11 +489,13 @@ update_existing_ref(struct btrfs_trans_handle *trans,
  * existing and update must have the same bytenr
  */
 static noinline void
-update_existing_head_ref(struct btrfs_delayed_ref_node *existing,
+update_existing_head_ref(struct btrfs_delayed_ref_root *delayed_refs,
+                        struct btrfs_delayed_ref_node *existing,
                         struct btrfs_delayed_ref_node *update)
 {
        struct btrfs_delayed_ref_head *existing_ref;
        struct btrfs_delayed_ref_head *ref;
+       int old_ref_mod;
 
        existing_ref = btrfs_delayed_node_to_head(existing);
        ref = btrfs_delayed_node_to_head(update);
@@ -541,7 +543,20 @@ update_existing_head_ref(struct btrfs_delayed_ref_node *existing,
         * only need the lock for this case cause we could be processing it
         * currently, for refs we just added we know we're a-ok.
         */
+       old_ref_mod = existing_ref->total_ref_mod;
        existing->ref_mod += update->ref_mod;
+       existing_ref->total_ref_mod += update->ref_mod;
+
+       /*
+        * If we are going to from a positive ref mod to a negative or vice
+        * versa we need to make sure to adjust pending_csums accordingly.
+        */
+       if (existing_ref->is_data) {
+               if (existing_ref->total_ref_mod >= 0 && old_ref_mod < 0)
+                       delayed_refs->pending_csums -= existing->num_bytes;
+               if (existing_ref->total_ref_mod < 0 && old_ref_mod >= 0)
+                       delayed_refs->pending_csums += existing->num_bytes;
+       }
        spin_unlock(&existing_ref->lock);
 }
 
@@ -605,6 +620,7 @@ add_delayed_ref_head(struct btrfs_fs_info *fs_info,
        head_ref->is_data = is_data;
        head_ref->ref_root = RB_ROOT;
        head_ref->processing = 0;
+       head_ref->total_ref_mod = count_mod;
 
        spin_lock_init(&head_ref->lock);
        mutex_init(&head_ref->mutex);
@@ -614,7 +630,7 @@ add_delayed_ref_head(struct btrfs_fs_info *fs_info,
        existing = htree_insert(&delayed_refs->href_root,
                                &head_ref->href_node);
        if (existing) {
-               update_existing_head_ref(&existing->node, ref);
+               update_existing_head_ref(delayed_refs, &existing->node, ref);
                /*
                 * we've updated the existing ref, free the newly
                 * allocated ref
@@ -622,6 +638,8 @@ add_delayed_ref_head(struct btrfs_fs_info *fs_info,
                kmem_cache_free(btrfs_delayed_ref_head_cachep, head_ref);
                head_ref = existing;
        } else {
+               if (is_data && count_mod < 0)
+                       delayed_refs->pending_csums += num_bytes;
                delayed_refs->num_heads++;
                delayed_refs->num_heads_ready++;
                atomic_inc(&delayed_refs->num_entries);
index a764e2340d484fd7539cf514081cecc594d740a5..5eb0892396d017ba95645f7ab179a1c8a3696253 100644 (file)
@@ -88,6 +88,14 @@ struct btrfs_delayed_ref_head {
        struct rb_node href_node;
 
        struct btrfs_delayed_extent_op *extent_op;
+
+       /*
+        * This is used to track the final ref_mod from all the refs associated
+        * with this head ref, this is not adjusted as delayed refs are run,
+        * this is meant to track if we need to do the csum accounting or not.
+        */
+       int total_ref_mod;
+
        /*
         * when a new extent is allocated, it is just reserved in memory
         * The actual extent isn't inserted into the extent allocation tree
@@ -138,6 +146,8 @@ struct btrfs_delayed_ref_root {
        /* total number of head nodes ready for processing */
        unsigned long num_heads_ready;
 
+       u64 pending_csums;
+
        /*
         * set when the tree is flushing before a transaction commit,
         * used by the throttling code to decide if new updates need
index 5ec03d999c37bfb3e48d937abd79b6dc57cd5257..0573848c73337f2f7848dfdd2fd05e31d5f26a56 100644 (file)
@@ -670,8 +670,8 @@ void btrfs_dev_replace_status(struct btrfs_fs_info *fs_info,
        case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED:
        case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED:
                srcdev = dev_replace->srcdev;
-               args->status.progress_1000 = div64_u64(dev_replace->cursor_left,
-                       div64_u64(btrfs_device_get_total_bytes(srcdev), 1000));
+               args->status.progress_1000 = div_u64(dev_replace->cursor_left,
+                       div_u64(btrfs_device_get_total_bytes(srcdev), 1000));
                break;
        }
        btrfs_dev_replace_unlock(dev_replace);
@@ -806,7 +806,7 @@ static int btrfs_dev_replace_kthread(void *data)
                btrfs_dev_replace_status(fs_info, status_args);
                progress = status_args->status.progress_1000;
                kfree(status_args);
-               do_div(progress, 10);
+               progress = div_u64(progress, 10);
                printk_in_rcu(KERN_INFO
                        "BTRFS: continuing dev_replace from %s (devid %llu) to %s @%u%%\n",
                        dev_replace->srcdev->missing ? "<missing disk>" :
index 639f2663ed3f8f40dc925451618702632e8b9109..2ef9a4b72d06e46d4f3a19c73e94796cb8397347 100644 (file)
@@ -54,7 +54,7 @@
 #include <asm/cpufeature.h>
 #endif
 
-static struct extent_io_ops btree_extent_io_ops;
+static const struct extent_io_ops btree_extent_io_ops;
 static void end_workqueue_fn(struct btrfs_work *work);
 static void free_fs_root(struct btrfs_root *root);
 static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info,
@@ -274,10 +274,11 @@ void btrfs_csum_final(u32 crc, char *result)
  * compute the csum for a btree block, and either verify it or write it
  * into the csum field of the block.
  */
-static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
+static int csum_tree_block(struct btrfs_fs_info *fs_info,
+                          struct extent_buffer *buf,
                           int verify)
 {
-       u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
+       u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
        char *result = NULL;
        unsigned long len;
        unsigned long cur_len;
@@ -302,7 +303,7 @@ static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
                offset += cur_len;
        }
        if (csum_size > sizeof(inline_result)) {
-               result = kzalloc(csum_size * sizeof(char), GFP_NOFS);
+               result = kzalloc(csum_size, GFP_NOFS);
                if (!result)
                        return 1;
        } else {
@@ -321,7 +322,7 @@ static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
                        printk_ratelimited(KERN_WARNING
                                "BTRFS: %s checksum verify failed on %llu wanted %X found %X "
                                "level %d\n",
-                               root->fs_info->sb->s_id, buf->start,
+                               fs_info->sb->s_id, buf->start,
                                val, found, btrfs_header_level(buf));
                        if (result != (char *)&inline_result)
                                kfree(result);
@@ -418,12 +419,6 @@ static int btrfs_check_super_csum(char *raw_disk_sb)
 
                if (memcmp(raw_disk_sb, result, csum_size))
                        ret = 1;
-
-               if (ret && btrfs_super_generation(disk_sb) < 10) {
-                       printk(KERN_WARNING
-                               "BTRFS: super block crcs don't match, older mkfs detected\n");
-                       ret = 0;
-               }
        }
 
        if (csum_type >= ARRAY_SIZE(btrfs_csum_sizes)) {
@@ -501,7 +496,7 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root,
  * we only fill in the checksum field in the first page of a multi-page block
  */
 
-static int csum_dirty_buffer(struct btrfs_root *root, struct page *page)
+static int csum_dirty_buffer(struct btrfs_fs_info *fs_info, struct page *page)
 {
        u64 start = page_offset(page);
        u64 found_start;
@@ -513,14 +508,14 @@ static int csum_dirty_buffer(struct btrfs_root *root, struct page *page)
        found_start = btrfs_header_bytenr(eb);
        if (WARN_ON(found_start != start || !PageUptodate(page)))
                return 0;
-       csum_tree_block(root, eb, 0);
+       csum_tree_block(fs_info, eb, 0);
        return 0;
 }
 
-static int check_tree_block_fsid(struct btrfs_root *root,
+static int check_tree_block_fsid(struct btrfs_fs_info *fs_info,
                                 struct extent_buffer *eb)
 {
-       struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices;
+       struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
        u8 fsid[BTRFS_UUID_SIZE];
        int ret = 1;
 
@@ -640,7 +635,7 @@ static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio,
                ret = -EIO;
                goto err;
        }
-       if (check_tree_block_fsid(root, eb)) {
+       if (check_tree_block_fsid(root->fs_info, eb)) {
                printk_ratelimited(KERN_ERR "BTRFS (device %s): bad fsid on block %llu\n",
                               eb->fs_info->sb->s_id, eb->start);
                ret = -EIO;
@@ -657,7 +652,7 @@ static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio,
        btrfs_set_buffer_lockdep_class(btrfs_header_owner(eb),
                                       eb, found_level);
 
-       ret = csum_tree_block(root, eb, 1);
+       ret = csum_tree_block(root->fs_info, eb, 1);
        if (ret) {
                ret = -EIO;
                goto err;
@@ -882,7 +877,7 @@ static int btree_csum_one_bio(struct bio *bio)
 
        bio_for_each_segment_all(bvec, bio, i) {
                root = BTRFS_I(bvec->bv_page->mapping->host)->root;
-               ret = csum_dirty_buffer(root, bvec->bv_page);
+               ret = csum_dirty_buffer(root->fs_info, bvec->bv_page);
                if (ret)
                        break;
        }
@@ -1119,10 +1114,10 @@ int reada_tree_block_flagged(struct btrfs_root *root, u64 bytenr,
        return 0;
 }
 
-struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root,
+struct extent_buffer *btrfs_find_tree_block(struct btrfs_fs_info *fs_info,
                                            u64 bytenr)
 {
-       return find_extent_buffer(root->fs_info, bytenr);
+       return find_extent_buffer(fs_info, bytenr);
 }
 
 struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root,
@@ -1165,11 +1160,10 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
 
 }
 
-void clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
+void clean_tree_block(struct btrfs_trans_handle *trans,
+                     struct btrfs_fs_info *fs_info,
                      struct extent_buffer *buf)
 {
-       struct btrfs_fs_info *fs_info = root->fs_info;
-
        if (btrfs_header_generation(buf) ==
            fs_info->running_transaction->transid) {
                btrfs_assert_tree_locked(buf);
@@ -2146,6 +2140,267 @@ void btrfs_free_fs_roots(struct btrfs_fs_info *fs_info)
        }
 }
 
+static void btrfs_init_scrub(struct btrfs_fs_info *fs_info)
+{
+       mutex_init(&fs_info->scrub_lock);
+       atomic_set(&fs_info->scrubs_running, 0);
+       atomic_set(&fs_info->scrub_pause_req, 0);
+       atomic_set(&fs_info->scrubs_paused, 0);
+       atomic_set(&fs_info->scrub_cancel_req, 0);
+       init_waitqueue_head(&fs_info->scrub_pause_wait);
+       fs_info->scrub_workers_refcnt = 0;
+}
+
+static void btrfs_init_balance(struct btrfs_fs_info *fs_info)
+{
+       spin_lock_init(&fs_info->balance_lock);
+       mutex_init(&fs_info->balance_mutex);
+       atomic_set(&fs_info->balance_running, 0);
+       atomic_set(&fs_info->balance_pause_req, 0);
+       atomic_set(&fs_info->balance_cancel_req, 0);
+       fs_info->balance_ctl = NULL;
+       init_waitqueue_head(&fs_info->balance_wait_q);
+}
+
+static void btrfs_init_btree_inode(struct btrfs_fs_info *fs_info,
+                                  struct btrfs_root *tree_root)
+{
+       fs_info->btree_inode->i_ino = BTRFS_BTREE_INODE_OBJECTID;
+       set_nlink(fs_info->btree_inode, 1);
+       /*
+        * we set the i_size on the btree inode to the max possible int.
+        * the real end of the address space is determined by all of
+        * the devices in the system
+        */
+       fs_info->btree_inode->i_size = OFFSET_MAX;
+       fs_info->btree_inode->i_mapping->a_ops = &btree_aops;
+
+       RB_CLEAR_NODE(&BTRFS_I(fs_info->btree_inode)->rb_node);
+       extent_io_tree_init(&BTRFS_I(fs_info->btree_inode)->io_tree,
+                            fs_info->btree_inode->i_mapping);
+       BTRFS_I(fs_info->btree_inode)->io_tree.track_uptodate = 0;
+       extent_map_tree_init(&BTRFS_I(fs_info->btree_inode)->extent_tree);
+
+       BTRFS_I(fs_info->btree_inode)->io_tree.ops = &btree_extent_io_ops;
+
+       BTRFS_I(fs_info->btree_inode)->root = tree_root;
+       memset(&BTRFS_I(fs_info->btree_inode)->location, 0,
+              sizeof(struct btrfs_key));
+       set_bit(BTRFS_INODE_DUMMY,
+               &BTRFS_I(fs_info->btree_inode)->runtime_flags);
+       btrfs_insert_inode_hash(fs_info->btree_inode);
+}
+
+static void btrfs_init_dev_replace_locks(struct btrfs_fs_info *fs_info)
+{
+       fs_info->dev_replace.lock_owner = 0;
+       atomic_set(&fs_info->dev_replace.nesting_level, 0);
+       mutex_init(&fs_info->dev_replace.lock_finishing_cancel_unmount);
+       mutex_init(&fs_info->dev_replace.lock_management_lock);
+       mutex_init(&fs_info->dev_replace.lock);
+       init_waitqueue_head(&fs_info->replace_wait);
+}
+
+static void btrfs_init_qgroup(struct btrfs_fs_info *fs_info)
+{
+       spin_lock_init(&fs_info->qgroup_lock);
+       mutex_init(&fs_info->qgroup_ioctl_lock);
+       fs_info->qgroup_tree = RB_ROOT;
+       fs_info->qgroup_op_tree = RB_ROOT;
+       INIT_LIST_HEAD(&fs_info->dirty_qgroups);
+       fs_info->qgroup_seq = 1;
+       fs_info->quota_enabled = 0;
+       fs_info->pending_quota_state = 0;
+       fs_info->qgroup_ulist = NULL;
+       mutex_init(&fs_info->qgroup_rescan_lock);
+}
+
+static int btrfs_init_workqueues(struct btrfs_fs_info *fs_info,
+               struct btrfs_fs_devices *fs_devices)
+{
+       int max_active = fs_info->thread_pool_size;
+       unsigned int flags = WQ_MEM_RECLAIM | WQ_FREEZABLE | WQ_UNBOUND;
+
+       fs_info->workers =
+               btrfs_alloc_workqueue("worker", flags | WQ_HIGHPRI,
+                                     max_active, 16);
+
+       fs_info->delalloc_workers =
+               btrfs_alloc_workqueue("delalloc", flags, max_active, 2);
+
+       fs_info->flush_workers =
+               btrfs_alloc_workqueue("flush_delalloc", flags, max_active, 0);
+
+       fs_info->caching_workers =
+               btrfs_alloc_workqueue("cache", flags, max_active, 0);
+
+       /*
+        * a higher idle thresh on the submit workers makes it much more
+        * likely that bios will be send down in a sane order to the
+        * devices
+        */
+       fs_info->submit_workers =
+               btrfs_alloc_workqueue("submit", flags,
+                                     min_t(u64, fs_devices->num_devices,
+                                           max_active), 64);
+
+       fs_info->fixup_workers =
+               btrfs_alloc_workqueue("fixup", flags, 1, 0);
+
+       /*
+        * endios are largely parallel and should have a very
+        * low idle thresh
+        */
+       fs_info->endio_workers =
+               btrfs_alloc_workqueue("endio", flags, max_active, 4);
+       fs_info->endio_meta_workers =
+               btrfs_alloc_workqueue("endio-meta", flags, max_active, 4);
+       fs_info->endio_meta_write_workers =
+               btrfs_alloc_workqueue("endio-meta-write", flags, max_active, 2);
+       fs_info->endio_raid56_workers =
+               btrfs_alloc_workqueue("endio-raid56", flags, max_active, 4);
+       fs_info->endio_repair_workers =
+               btrfs_alloc_workqueue("endio-repair", flags, 1, 0);
+       fs_info->rmw_workers =
+               btrfs_alloc_workqueue("rmw", flags, max_active, 2);
+       fs_info->endio_write_workers =
+               btrfs_alloc_workqueue("endio-write", flags, max_active, 2);
+       fs_info->endio_freespace_worker =
+               btrfs_alloc_workqueue("freespace-write", flags, max_active, 0);
+       fs_info->delayed_workers =
+               btrfs_alloc_workqueue("delayed-meta", flags, max_active, 0);
+       fs_info->readahead_workers =
+               btrfs_alloc_workqueue("readahead", flags, max_active, 2);
+       fs_info->qgroup_rescan_workers =
+               btrfs_alloc_workqueue("qgroup-rescan", flags, 1, 0);
+       fs_info->extent_workers =
+               btrfs_alloc_workqueue("extent-refs", flags,
+                                     min_t(u64, fs_devices->num_devices,
+                                           max_active), 8);
+
+       if (!(fs_info->workers && fs_info->delalloc_workers &&
+             fs_info->submit_workers && fs_info->flush_workers &&
+             fs_info->endio_workers && fs_info->endio_meta_workers &&
+             fs_info->endio_meta_write_workers &&
+             fs_info->endio_repair_workers &&
+             fs_info->endio_write_workers && fs_info->endio_raid56_workers &&
+             fs_info->endio_freespace_worker && fs_info->rmw_workers &&
+             fs_info->caching_workers && fs_info->readahead_workers &&
+             fs_info->fixup_workers && fs_info->delayed_workers &&
+             fs_info->extent_workers &&
+             fs_info->qgroup_rescan_workers)) {
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+static int btrfs_replay_log(struct btrfs_fs_info *fs_info,
+                           struct btrfs_fs_devices *fs_devices)
+{
+       int ret;
+       struct btrfs_root *tree_root = fs_info->tree_root;
+       struct btrfs_root *log_tree_root;
+       struct btrfs_super_block *disk_super = fs_info->super_copy;
+       u64 bytenr = btrfs_super_log_root(disk_super);
+
+       if (fs_devices->rw_devices == 0) {
+               printk(KERN_WARNING "BTRFS: log replay required "
+                      "on RO media\n");
+               return -EIO;
+       }
+
+       log_tree_root = btrfs_alloc_root(fs_info);
+       if (!log_tree_root)
+               return -ENOMEM;
+
+       __setup_root(tree_root->nodesize, tree_root->sectorsize,
+                       tree_root->stripesize, log_tree_root, fs_info,
+                       BTRFS_TREE_LOG_OBJECTID);
+
+       log_tree_root->node = read_tree_block(tree_root, bytenr,
+                       fs_info->generation + 1);
+       if (!log_tree_root->node ||
+           !extent_buffer_uptodate(log_tree_root->node)) {
+               printk(KERN_ERR "BTRFS: failed to read log tree\n");
+               free_extent_buffer(log_tree_root->node);
+               kfree(log_tree_root);
+               return -EIO;
+       }
+       /* returns with log_tree_root freed on success */
+       ret = btrfs_recover_log_trees(log_tree_root);
+       if (ret) {
+               btrfs_error(tree_root->fs_info, ret,
+                           "Failed to recover log tree");
+               free_extent_buffer(log_tree_root->node);
+               kfree(log_tree_root);
+               return ret;
+       }
+
+       if (fs_info->sb->s_flags & MS_RDONLY) {
+               ret = btrfs_commit_super(tree_root);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int btrfs_read_roots(struct btrfs_fs_info *fs_info,
+                           struct btrfs_root *tree_root)
+{
+       struct btrfs_root *root;
+       struct btrfs_key location;
+       int ret;
+
+       location.objectid = BTRFS_EXTENT_TREE_OBJECTID;
+       location.type = BTRFS_ROOT_ITEM_KEY;
+       location.offset = 0;
+
+       root = btrfs_read_tree_root(tree_root, &location);
+       if (IS_ERR(root))
+               return PTR_ERR(root);
+       set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state);
+       fs_info->extent_root = root;
+
+       location.objectid = BTRFS_DEV_TREE_OBJECTID;
+       root = btrfs_read_tree_root(tree_root, &location);
+       if (IS_ERR(root))
+               return PTR_ERR(root);
+       set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state);
+       fs_info->dev_root = root;
+       btrfs_init_devices_late(fs_info);
+
+       location.objectid = BTRFS_CSUM_TREE_OBJECTID;
+       root = btrfs_read_tree_root(tree_root, &location);
+       if (IS_ERR(root))
+               return PTR_ERR(root);
+       set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state);
+       fs_info->csum_root = root;
+
+       location.objectid = BTRFS_QUOTA_TREE_OBJECTID;
+       root = btrfs_read_tree_root(tree_root, &location);
+       if (!IS_ERR(root)) {
+               set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state);
+               fs_info->quota_enabled = 1;
+               fs_info->pending_quota_state = 1;
+               fs_info->quota_root = root;
+       }
+
+       location.objectid = BTRFS_UUID_TREE_OBJECTID;
+       root = btrfs_read_tree_root(tree_root, &location);
+       if (IS_ERR(root)) {
+               ret = PTR_ERR(root);
+               if (ret != -ENOENT)
+                       return ret;
+       } else {
+               set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state);
+               fs_info->uuid_root = root;
+       }
+
+       return 0;
+}
+
 int open_ctree(struct super_block *sb,
               struct btrfs_fs_devices *fs_devices,
               char *options)
@@ -2160,21 +2415,12 @@ int open_ctree(struct super_block *sb,
        struct btrfs_super_block *disk_super;
        struct btrfs_fs_info *fs_info = btrfs_sb(sb);
        struct btrfs_root *tree_root;
-       struct btrfs_root *extent_root;
-       struct btrfs_root *csum_root;
        struct btrfs_root *chunk_root;
-       struct btrfs_root *dev_root;
-       struct btrfs_root *quota_root;
-       struct btrfs_root *uuid_root;
-       struct btrfs_root *log_tree_root;
        int ret;
        int err = -EINVAL;
        int num_backups_tried = 0;
        int backup_index = 0;
        int max_active;
-       int flags = WQ_MEM_RECLAIM | WQ_FREEZABLE | WQ_UNBOUND;
-       bool create_uuid_tree;
-       bool check_uuid_tree;
 
        tree_root = fs_info->tree_root = btrfs_alloc_root(fs_info);
        chunk_root = fs_info->chunk_root = btrfs_alloc_root(fs_info);
@@ -2241,11 +2487,12 @@ int open_ctree(struct super_block *sb,
        spin_lock_init(&fs_info->qgroup_op_lock);
        spin_lock_init(&fs_info->buffer_lock);
        spin_lock_init(&fs_info->unused_bgs_lock);
-       mutex_init(&fs_info->unused_bg_unpin_mutex);
        rwlock_init(&fs_info->tree_mod_log_lock);
+       mutex_init(&fs_info->unused_bg_unpin_mutex);
        mutex_init(&fs_info->reloc_mutex);
        mutex_init(&fs_info->delalloc_root_mutex);
        seqlock_init(&fs_info->profiles_lock);
+       init_rwsem(&fs_info->delayed_iput_sem);
 
        init_completion(&fs_info->kobj_unregister);
        INIT_LIST_HEAD(&fs_info->dirty_cowonly_roots);
@@ -2276,7 +2523,7 @@ int open_ctree(struct super_block *sb,
        fs_info->free_chunk_space = 0;
        fs_info->tree_mod_log = RB_ROOT;
        fs_info->commit_interval = BTRFS_DEFAULT_COMMIT_INTERVAL;
-       fs_info->avg_delayed_ref_runtime = div64_u64(NSEC_PER_SEC, 64);
+       fs_info->avg_delayed_ref_runtime = NSEC_PER_SEC >> 6; /* div by 64 */
        /* readahead state */
        INIT_RADIX_TREE(&fs_info->reada_tree, GFP_NOFS & ~__GFP_WAIT);
        spin_lock_init(&fs_info->reada_lock);
@@ -2294,55 +2541,18 @@ int open_ctree(struct super_block *sb,
        }
        btrfs_init_delayed_root(fs_info->delayed_root);
 
-       mutex_init(&fs_info->scrub_lock);
-       atomic_set(&fs_info->scrubs_running, 0);
-       atomic_set(&fs_info->scrub_pause_req, 0);
-       atomic_set(&fs_info->scrubs_paused, 0);
-       atomic_set(&fs_info->scrub_cancel_req, 0);
-       init_waitqueue_head(&fs_info->replace_wait);
-       init_waitqueue_head(&fs_info->scrub_pause_wait);
-       fs_info->scrub_workers_refcnt = 0;
+       btrfs_init_scrub(fs_info);
 #ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
        fs_info->check_integrity_print_mask = 0;
 #endif
-
-       spin_lock_init(&fs_info->balance_lock);
-       mutex_init(&fs_info->balance_mutex);
-       atomic_set(&fs_info->balance_running, 0);
-       atomic_set(&fs_info->balance_pause_req, 0);
-       atomic_set(&fs_info->balance_cancel_req, 0);
-       fs_info->balance_ctl = NULL;
-       init_waitqueue_head(&fs_info->balance_wait_q);
+       btrfs_init_balance(fs_info);
        btrfs_init_async_reclaim_work(&fs_info->async_reclaim_work);
 
        sb->s_blocksize = 4096;
        sb->s_blocksize_bits = blksize_bits(4096);
        sb->s_bdi = &fs_info->bdi;
 
-       fs_info->btree_inode->i_ino = BTRFS_BTREE_INODE_OBJECTID;
-       set_nlink(fs_info->btree_inode, 1);
-       /*
-        * we set the i_size on the btree inode to the max possible int.
-        * the real end of the address space is determined by all of
-        * the devices in the system
-        */
-       fs_info->btree_inode->i_size = OFFSET_MAX;
-       fs_info->btree_inode->i_mapping->a_ops = &btree_aops;
-
-       RB_CLEAR_NODE(&BTRFS_I(fs_info->btree_inode)->rb_node);
-       extent_io_tree_init(&BTRFS_I(fs_info->btree_inode)->io_tree,
-                            fs_info->btree_inode->i_mapping);
-       BTRFS_I(fs_info->btree_inode)->io_tree.track_uptodate = 0;
-       extent_map_tree_init(&BTRFS_I(fs_info->btree_inode)->extent_tree);
-
-       BTRFS_I(fs_info->btree_inode)->io_tree.ops = &btree_extent_io_ops;
-
-       BTRFS_I(fs_info->btree_inode)->root = tree_root;
-       memset(&BTRFS_I(fs_info->btree_inode)->location, 0,
-              sizeof(struct btrfs_key));
-       set_bit(BTRFS_INODE_DUMMY,
-               &BTRFS_I(fs_info->btree_inode)->runtime_flags);
-       btrfs_insert_inode_hash(fs_info->btree_inode);
+       btrfs_init_btree_inode(fs_info, tree_root);
 
        spin_lock_init(&fs_info->block_group_cache_lock);
        fs_info->block_group_cache_tree = RB_ROOT;
@@ -2363,26 +2573,14 @@ int open_ctree(struct super_block *sb,
        mutex_init(&fs_info->transaction_kthread_mutex);
        mutex_init(&fs_info->cleaner_mutex);
        mutex_init(&fs_info->volume_mutex);
+       mutex_init(&fs_info->ro_block_group_mutex);
        init_rwsem(&fs_info->commit_root_sem);
        init_rwsem(&fs_info->cleanup_work_sem);
        init_rwsem(&fs_info->subvol_sem);
        sema_init(&fs_info->uuid_tree_rescan_sem, 1);
-       fs_info->dev_replace.lock_owner = 0;
-       atomic_set(&fs_info->dev_replace.nesting_level, 0);
-       mutex_init(&fs_info->dev_replace.lock_finishing_cancel_unmount);
-       mutex_init(&fs_info->dev_replace.lock_management_lock);
-       mutex_init(&fs_info->dev_replace.lock);
 
-       spin_lock_init(&fs_info->qgroup_lock);
-       mutex_init(&fs_info->qgroup_ioctl_lock);
-       fs_info->qgroup_tree = RB_ROOT;
-       fs_info->qgroup_op_tree = RB_ROOT;
-       INIT_LIST_HEAD(&fs_info->dirty_qgroups);
-       fs_info->qgroup_seq = 1;
-       fs_info->quota_enabled = 0;
-       fs_info->pending_quota_state = 0;
-       fs_info->qgroup_ulist = NULL;
-       mutex_init(&fs_info->qgroup_rescan_lock);
+       btrfs_init_dev_replace_locks(fs_info);
+       btrfs_init_qgroup(fs_info);
 
        btrfs_init_free_cluster(&fs_info->meta_alloc_cluster);
        btrfs_init_free_cluster(&fs_info->data_alloc_cluster);
@@ -2554,75 +2752,9 @@ int open_ctree(struct super_block *sb,
 
        max_active = fs_info->thread_pool_size;
 
-       fs_info->workers =
-               btrfs_alloc_workqueue("worker", flags | WQ_HIGHPRI,
-                                     max_active, 16);
-
-       fs_info->delalloc_workers =
-               btrfs_alloc_workqueue("delalloc", flags, max_active, 2);
-
-       fs_info->flush_workers =
-               btrfs_alloc_workqueue("flush_delalloc", flags, max_active, 0);
-
-       fs_info->caching_workers =
-               btrfs_alloc_workqueue("cache", flags, max_active, 0);
-
-       /*
-        * a higher idle thresh on the submit workers makes it much more
-        * likely that bios will be send down in a sane order to the
-        * devices
-        */
-       fs_info->submit_workers =
-               btrfs_alloc_workqueue("submit", flags,
-                                     min_t(u64, fs_devices->num_devices,
-                                           max_active), 64);
-
-       fs_info->fixup_workers =
-               btrfs_alloc_workqueue("fixup", flags, 1, 0);
-
-       /*
-        * endios are largely parallel and should have a very
-        * low idle thresh
-        */
-       fs_info->endio_workers =
-               btrfs_alloc_workqueue("endio", flags, max_active, 4);
-       fs_info->endio_meta_workers =
-               btrfs_alloc_workqueue("endio-meta", flags, max_active, 4);
-       fs_info->endio_meta_write_workers =
-               btrfs_alloc_workqueue("endio-meta-write", flags, max_active, 2);
-       fs_info->endio_raid56_workers =
-               btrfs_alloc_workqueue("endio-raid56", flags, max_active, 4);
-       fs_info->endio_repair_workers =
-               btrfs_alloc_workqueue("endio-repair", flags, 1, 0);
-       fs_info->rmw_workers =
-               btrfs_alloc_workqueue("rmw", flags, max_active, 2);
-       fs_info->endio_write_workers =
-               btrfs_alloc_workqueue("endio-write", flags, max_active, 2);
-       fs_info->endio_freespace_worker =
-               btrfs_alloc_workqueue("freespace-write", flags, max_active, 0);
-       fs_info->delayed_workers =
-               btrfs_alloc_workqueue("delayed-meta", flags, max_active, 0);
-       fs_info->readahead_workers =
-               btrfs_alloc_workqueue("readahead", flags, max_active, 2);
-       fs_info->qgroup_rescan_workers =
-               btrfs_alloc_workqueue("qgroup-rescan", flags, 1, 0);
-       fs_info->extent_workers =
-               btrfs_alloc_workqueue("extent-refs", flags,
-                                     min_t(u64, fs_devices->num_devices,
-                                           max_active), 8);
-
-       if (!(fs_info->workers && fs_info->delalloc_workers &&
-             fs_info->submit_workers && fs_info->flush_workers &&
-             fs_info->endio_workers && fs_info->endio_meta_workers &&
-             fs_info->endio_meta_write_workers &&
-             fs_info->endio_repair_workers &&
-             fs_info->endio_write_workers && fs_info->endio_raid56_workers &&
-             fs_info->endio_freespace_worker && fs_info->rmw_workers &&
-             fs_info->caching_workers && fs_info->readahead_workers &&
-             fs_info->fixup_workers && fs_info->delayed_workers &&
-             fs_info->extent_workers &&
-             fs_info->qgroup_rescan_workers)) {
-               err = -ENOMEM;
+       ret = btrfs_init_workqueues(fs_info, fs_devices);
+       if (ret) {
+               err = ret;
                goto fail_sb_buffer;
        }
 
@@ -2688,7 +2820,7 @@ int open_ctree(struct super_block *sb,
         * keep the device that is marked to be the target device for the
         * dev_replace procedure
         */
-       btrfs_close_extra_devices(fs_info, fs_devices, 0);
+       btrfs_close_extra_devices(fs_devices, 0);
 
        if (!fs_devices->latest_bdev) {
                printk(KERN_ERR "BTRFS: failed to read devices on %s\n",
@@ -2714,61 +2846,9 @@ retry_root_backup:
        tree_root->commit_root = btrfs_root_node(tree_root);
        btrfs_set_root_refs(&tree_root->root_item, 1);
 
-       location.objectid = BTRFS_EXTENT_TREE_OBJECTID;
-       location.type = BTRFS_ROOT_ITEM_KEY;
-       location.offset = 0;
-
-       extent_root = btrfs_read_tree_root(tree_root, &location);
-       if (IS_ERR(extent_root)) {
-               ret = PTR_ERR(extent_root);
-               goto recovery_tree_root;
-       }
-       set_bit(BTRFS_ROOT_TRACK_DIRTY, &extent_root->state);
-       fs_info->extent_root = extent_root;
-
-       location.objectid = BTRFS_DEV_TREE_OBJECTID;
-       dev_root = btrfs_read_tree_root(tree_root, &location);
-       if (IS_ERR(dev_root)) {
-               ret = PTR_ERR(dev_root);
-               goto recovery_tree_root;
-       }
-       set_bit(BTRFS_ROOT_TRACK_DIRTY, &dev_root->state);
-       fs_info->dev_root = dev_root;
-       btrfs_init_devices_late(fs_info);
-
-       location.objectid = BTRFS_CSUM_TREE_OBJECTID;
-       csum_root = btrfs_read_tree_root(tree_root, &location);
-       if (IS_ERR(csum_root)) {
-               ret = PTR_ERR(csum_root);
+       ret = btrfs_read_roots(fs_info, tree_root);
+       if (ret)
                goto recovery_tree_root;
-       }
-       set_bit(BTRFS_ROOT_TRACK_DIRTY, &csum_root->state);
-       fs_info->csum_root = csum_root;
-
-       location.objectid = BTRFS_QUOTA_TREE_OBJECTID;
-       quota_root = btrfs_read_tree_root(tree_root, &location);
-       if (!IS_ERR(quota_root)) {
-               set_bit(BTRFS_ROOT_TRACK_DIRTY, &quota_root->state);
-               fs_info->quota_enabled = 1;
-               fs_info->pending_quota_state = 1;
-               fs_info->quota_root = quota_root;
-       }
-
-       location.objectid = BTRFS_UUID_TREE_OBJECTID;
-       uuid_root = btrfs_read_tree_root(tree_root, &location);
-       if (IS_ERR(uuid_root)) {
-               ret = PTR_ERR(uuid_root);
-               if (ret != -ENOENT)
-                       goto recovery_tree_root;
-               create_uuid_tree = true;
-               check_uuid_tree = false;
-       } else {
-               set_bit(BTRFS_ROOT_TRACK_DIRTY, &uuid_root->state);
-               fs_info->uuid_root = uuid_root;
-               create_uuid_tree = false;
-               check_uuid_tree =
-                   generation != btrfs_super_uuid_tree_generation(disk_super);
-       }
 
        fs_info->generation = generation;
        fs_info->last_trans_committed = generation;
@@ -2792,7 +2872,7 @@ retry_root_backup:
                goto fail_block_groups;
        }
 
-       btrfs_close_extra_devices(fs_info, fs_devices, 1);
+       btrfs_close_extra_devices(fs_devices, 1);
 
        ret = btrfs_sysfs_add_one(fs_info);
        if (ret) {
@@ -2806,7 +2886,7 @@ retry_root_backup:
                goto fail_sysfs;
        }
 
-       ret = btrfs_read_block_groups(extent_root);
+       ret = btrfs_read_block_groups(fs_info->extent_root);
        if (ret) {
                printk(KERN_ERR "BTRFS: Failed to read block groups: %d\n", ret);
                goto fail_sysfs;
@@ -2864,48 +2944,11 @@ retry_root_backup:
 
        /* do not make disk changes in broken FS */
        if (btrfs_super_log_root(disk_super) != 0) {
-               u64 bytenr = btrfs_super_log_root(disk_super);
-
-               if (fs_devices->rw_devices == 0) {
-                       printk(KERN_WARNING "BTRFS: log replay required "
-                              "on RO media\n");
-                       err = -EIO;
-                       goto fail_qgroup;
-               }
-
-               log_tree_root = btrfs_alloc_root(fs_info);
-               if (!log_tree_root) {
-                       err = -ENOMEM;
-                       goto fail_qgroup;
-               }
-
-               __setup_root(nodesize, sectorsize, stripesize,
-                            log_tree_root, fs_info, BTRFS_TREE_LOG_OBJECTID);
-
-               log_tree_root->node = read_tree_block(tree_root, bytenr,
-                                                     generation + 1);
-               if (!log_tree_root->node ||
-                   !extent_buffer_uptodate(log_tree_root->node)) {
-                       printk(KERN_ERR "BTRFS: failed to read log tree\n");
-                       free_extent_buffer(log_tree_root->node);
-                       kfree(log_tree_root);
-                       goto fail_qgroup;
-               }
-               /* returns with log_tree_root freed on success */
-               ret = btrfs_recover_log_trees(log_tree_root);
+               ret = btrfs_replay_log(fs_info, fs_devices);
                if (ret) {
-                       btrfs_error(tree_root->fs_info, ret,
-                                   "Failed to recover log tree");
-                       free_extent_buffer(log_tree_root->node);
-                       kfree(log_tree_root);
+                       err = ret;
                        goto fail_qgroup;
                }
-
-               if (sb->s_flags & MS_RDONLY) {
-                       ret = btrfs_commit_super(tree_root);
-                       if (ret)
-                               goto fail_qgroup;
-               }
        }
 
        ret = btrfs_find_orphan_roots(tree_root);
@@ -2966,7 +3009,7 @@ retry_root_backup:
 
        btrfs_qgroup_rescan_resume(fs_info);
 
-       if (create_uuid_tree) {
+       if (!fs_info->uuid_root) {
                pr_info("BTRFS: creating UUID tree\n");
                ret = btrfs_create_uuid_tree(fs_info);
                if (ret) {
@@ -2975,8 +3018,9 @@ retry_root_backup:
                        close_ctree(tree_root);
                        return ret;
                }
-       } else if (check_uuid_tree ||
-                  btrfs_test_opt(tree_root, RESCAN_UUID_TREE)) {
+       } else if (btrfs_test_opt(tree_root, RESCAN_UUID_TREE) ||
+                  fs_info->generation !=
+                               btrfs_super_uuid_tree_generation(disk_super)) {
                pr_info("BTRFS: checking UUID tree\n");
                ret = btrfs_check_uuid_tree(fs_info);
                if (ret) {
@@ -3668,7 +3712,7 @@ void close_ctree(struct btrfs_root *root)
        if (!(fs_info->sb->s_flags & MS_RDONLY)) {
                ret = btrfs_commit_super(root);
                if (ret)
-                       btrfs_err(root->fs_info, "commit super ret %d", ret);
+                       btrfs_err(fs_info, "commit super ret %d", ret);
        }
 
        if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state))
@@ -3680,10 +3724,10 @@ void close_ctree(struct btrfs_root *root)
        fs_info->closing = 2;
        smp_mb();
 
-       btrfs_free_qgroup_config(root->fs_info);
+       btrfs_free_qgroup_config(fs_info);
 
        if (percpu_counter_sum(&fs_info->delalloc_bytes)) {
-               btrfs_info(root->fs_info, "at unmount delalloc count %lld",
+               btrfs_info(fs_info, "at unmount delalloc count %lld",
                       percpu_counter_sum(&fs_info->delalloc_bytes));
        }
 
@@ -3723,7 +3767,7 @@ void close_ctree(struct btrfs_root *root)
 
        btrfs_free_stripe_hash_table(fs_info);
 
-       btrfs_free_block_rsv(root, root->orphan_block_rsv);
+       __btrfs_free_block_rsv(root->orphan_block_rsv);
        root->orphan_block_rsv = NULL;
 
        lock_chunks(root);
@@ -4134,7 +4178,7 @@ static int btrfs_destroy_marked_extents(struct btrfs_root *root,
 
                clear_extent_bits(dirty_pages, start, end, mark, GFP_NOFS);
                while (start <= end) {
-                       eb = btrfs_find_tree_block(root, start);
+                       eb = btrfs_find_tree_block(root->fs_info, start);
                        start += root->nodesize;
                        if (!eb)
                                continue;
@@ -4285,7 +4329,7 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root)
        return 0;
 }
 
-static struct extent_io_ops btree_extent_io_ops = {
+static const struct extent_io_ops btree_extent_io_ops = {
        .readpage_end_io_hook = btree_readpage_end_io_hook,
        .readpage_io_failed_hook = btree_io_failed_hook,
        .submit_bio_hook = btree_submit_bio_hook,
index 27d44c0fd2364df69eafd15f61bd6a215696f91f..d4cbfeeeedd42050d3b2cd61707f80781d258328 100644 (file)
@@ -52,7 +52,7 @@ int reada_tree_block_flagged(struct btrfs_root *root, u64 bytenr,
 struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root,
                                                   u64 bytenr);
 void clean_tree_block(struct btrfs_trans_handle *trans,
-                     struct btrfs_root *root, struct extent_buffer *buf);
+                     struct btrfs_fs_info *fs_info, struct extent_buffer *buf);
 int open_ctree(struct super_block *sb,
               struct btrfs_fs_devices *fs_devices,
               char *options);
@@ -61,7 +61,7 @@ int write_ctree_super(struct btrfs_trans_handle *trans,
                      struct btrfs_root *root, int max_mirrors);
 struct buffer_head *btrfs_read_dev_super(struct block_device *bdev);
 int btrfs_commit_super(struct btrfs_root *root);
-struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root,
+struct extent_buffer *btrfs_find_tree_block(struct btrfs_fs_info *fs_info,
                                            u64 bytenr);
 struct btrfs_root *btrfs_read_fs_root(struct btrfs_root *tree_root,
                                      struct btrfs_key *location);
index 37d164540c3a25c469d831899e05f9cc5eccb9d1..8d052209f473be1d0959b6e65bded71b92c05584 100644 (file)
@@ -152,7 +152,7 @@ static struct dentry *btrfs_fh_to_dentry(struct super_block *sb, struct fid *fh,
 
 static struct dentry *btrfs_get_parent(struct dentry *child)
 {
-       struct inode *dir = child->d_inode;
+       struct inode *dir = d_inode(child);
        struct btrfs_root *root = BTRFS_I(dir)->root;
        struct btrfs_path *path;
        struct extent_buffer *leaf;
@@ -220,8 +220,8 @@ fail:
 static int btrfs_get_name(struct dentry *parent, char *name,
                          struct dentry *child)
 {
-       struct inode *inode = child->d_inode;
-       struct inode *dir = parent->d_inode;
+       struct inode *inode = d_inode(child);
+       struct inode *dir = d_inode(parent);
        struct btrfs_path *path;
        struct btrfs_root *root = BTRFS_I(dir)->root;
        struct btrfs_inode_ref *iref;
index 8b353ad02f034a9307e1da5d8923aff6b43a0dcb..0ec8e228b89f42505cc0c9c8ffef96e1a2f3f9a4 100644 (file)
@@ -2538,6 +2538,12 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
                 * list before we release it.
                 */
                if (btrfs_delayed_ref_is_head(ref)) {
+                       if (locked_ref->is_data &&
+                           locked_ref->total_ref_mod < 0) {
+                               spin_lock(&delayed_refs->lock);
+                               delayed_refs->pending_csums -= ref->num_bytes;
+                               spin_unlock(&delayed_refs->lock);
+                       }
                        btrfs_delayed_ref_unlock(locked_ref);
                        locked_ref = NULL;
                }
@@ -2561,8 +2567,7 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
                 */
                spin_lock(&delayed_refs->lock);
                avg = fs_info->avg_delayed_ref_runtime * 3 + runtime;
-               avg = div64_u64(avg, 4);
-               fs_info->avg_delayed_ref_runtime = avg;
+               fs_info->avg_delayed_ref_runtime = avg >> 2;    /* div by 4 */
                spin_unlock(&delayed_refs->lock);
        }
        return 0;
@@ -2624,7 +2629,26 @@ static inline u64 heads_to_leaves(struct btrfs_root *root, u64 heads)
         * We don't ever fill up leaves all the way so multiply by 2 just to be
         * closer to what we're really going to want to ouse.
         */
-       return div64_u64(num_bytes, BTRFS_LEAF_DATA_SIZE(root));
+       return div_u64(num_bytes, BTRFS_LEAF_DATA_SIZE(root));
+}
+
+/*
+ * Takes the number of bytes to be csumm'ed and figures out how many leaves it
+ * would require to store the csums for that many bytes.
+ */
+u64 btrfs_csum_bytes_to_leaves(struct btrfs_root *root, u64 csum_bytes)
+{
+       u64 csum_size;
+       u64 num_csums_per_leaf;
+       u64 num_csums;
+
+       csum_size = BTRFS_LEAF_DATA_SIZE(root) - sizeof(struct btrfs_item);
+       num_csums_per_leaf = div64_u64(csum_size,
+                       (u64)btrfs_super_csum_size(root->fs_info->super_copy));
+       num_csums = div64_u64(csum_bytes, root->sectorsize);
+       num_csums += num_csums_per_leaf - 1;
+       num_csums = div64_u64(num_csums, num_csums_per_leaf);
+       return num_csums;
 }
 
 int btrfs_check_space_for_delayed_refs(struct btrfs_trans_handle *trans,
@@ -2632,7 +2656,9 @@ int btrfs_check_space_for_delayed_refs(struct btrfs_trans_handle *trans,
 {
        struct btrfs_block_rsv *global_rsv;
        u64 num_heads = trans->transaction->delayed_refs.num_heads_ready;
-       u64 num_bytes;
+       u64 csum_bytes = trans->transaction->delayed_refs.pending_csums;
+       u64 num_dirty_bgs = trans->transaction->num_dirty_bgs;
+       u64 num_bytes, num_dirty_bgs_bytes;
        int ret = 0;
 
        num_bytes = btrfs_calc_trans_metadata_size(root, 1);
@@ -2640,17 +2666,22 @@ int btrfs_check_space_for_delayed_refs(struct btrfs_trans_handle *trans,
        if (num_heads > 1)
                num_bytes += (num_heads - 1) * root->nodesize;
        num_bytes <<= 1;
+       num_bytes += btrfs_csum_bytes_to_leaves(root, csum_bytes) * root->nodesize;
+       num_dirty_bgs_bytes = btrfs_calc_trans_metadata_size(root,
+                                                            num_dirty_bgs);
        global_rsv = &root->fs_info->global_block_rsv;
 
        /*
         * If we can't allocate any more chunks lets make sure we have _lots_ of
         * wiggle room since running delayed refs can create more delayed refs.
         */
-       if (global_rsv->space_info->full)
+       if (global_rsv->space_info->full) {
+               num_dirty_bgs_bytes <<= 1;
                num_bytes <<= 1;
+       }
 
        spin_lock(&global_rsv->lock);
-       if (global_rsv->reserved <= num_bytes)
+       if (global_rsv->reserved <= num_bytes + num_dirty_bgs_bytes)
                ret = 1;
        spin_unlock(&global_rsv->lock);
        return ret;
@@ -3147,8 +3178,8 @@ static int write_one_cache_group(struct btrfs_trans_handle *trans,
        bi = btrfs_item_ptr_offset(leaf, path->slots[0]);
        write_extent_buffer(leaf, &cache->item, bi, sizeof(cache->item));
        btrfs_mark_buffer_dirty(leaf);
-       btrfs_release_path(path);
 fail:
+       btrfs_release_path(path);
        if (ret)
                btrfs_abort_transaction(trans, root, ret);
        return ret;
@@ -3193,7 +3224,7 @@ static int cache_save_setup(struct btrfs_block_group_cache *block_group,
        struct inode *inode = NULL;
        u64 alloc_hint = 0;
        int dcs = BTRFS_DC_ERROR;
-       int num_pages = 0;
+       u64 num_pages = 0;
        int retries = 0;
        int ret = 0;
 
@@ -3267,15 +3298,14 @@ again:
                if (ret)
                        goto out_put;
 
-               ret = btrfs_truncate_free_space_cache(root, trans, inode);
+               ret = btrfs_truncate_free_space_cache(root, trans, NULL, inode);
                if (ret)
                        goto out_put;
        }
 
        spin_lock(&block_group->lock);
        if (block_group->cached != BTRFS_CACHE_FINISHED ||
-           !btrfs_test_opt(root, SPACE_CACHE) ||
-           block_group->delalloc_bytes) {
+           !btrfs_test_opt(root, SPACE_CACHE)) {
                /*
                 * don't bother trying to write stuff out _if_
                 * a) we're not cached,
@@ -3293,14 +3323,14 @@ again:
         * taking up quite a bit since it's not folded into the other space
         * cache.
         */
-       num_pages = (int)div64_u64(block_group->key.offset, 256 * 1024 * 1024);
+       num_pages = div_u64(block_group->key.offset, 256 * 1024 * 1024);
        if (!num_pages)
                num_pages = 1;
 
        num_pages *= 16;
        num_pages *= PAGE_CACHE_SIZE;
 
-       ret = btrfs_check_data_free_space(inode, num_pages);
+       ret = btrfs_check_data_free_space(inode, num_pages, num_pages);
        if (ret)
                goto out_put;
 
@@ -3351,16 +3381,166 @@ int btrfs_setup_space_cache(struct btrfs_trans_handle *trans,
        return 0;
 }
 
+/*
+ * transaction commit does final block group cache writeback during a
+ * critical section where nothing is allowed to change the FS.  This is
+ * required in order for the cache to actually match the block group,
+ * but can introduce a lot of latency into the commit.
+ *
+ * So, btrfs_start_dirty_block_groups is here to kick off block group
+ * cache IO.  There's a chance we'll have to redo some of it if the
+ * block group changes again during the commit, but it greatly reduces
+ * the commit latency by getting rid of the easy block groups while
+ * we're still allowing others to join the commit.
+ */
+int btrfs_start_dirty_block_groups(struct btrfs_trans_handle *trans,
+                                  struct btrfs_root *root)
+{
+       struct btrfs_block_group_cache *cache;
+       struct btrfs_transaction *cur_trans = trans->transaction;
+       int ret = 0;
+       int should_put;
+       struct btrfs_path *path = NULL;
+       LIST_HEAD(dirty);
+       struct list_head *io = &cur_trans->io_bgs;
+       int num_started = 0;
+       int loops = 0;
+
+       spin_lock(&cur_trans->dirty_bgs_lock);
+       if (list_empty(&cur_trans->dirty_bgs)) {
+               spin_unlock(&cur_trans->dirty_bgs_lock);
+               return 0;
+       }
+       list_splice_init(&cur_trans->dirty_bgs, &dirty);
+       spin_unlock(&cur_trans->dirty_bgs_lock);
+
+again:
+       /*
+        * make sure all the block groups on our dirty list actually
+        * exist
+        */
+       btrfs_create_pending_block_groups(trans, root);
+
+       if (!path) {
+               path = btrfs_alloc_path();
+               if (!path)
+                       return -ENOMEM;
+       }
+
+       /*
+        * cache_write_mutex is here only to save us from balance or automatic
+        * removal of empty block groups deleting this block group while we are
+        * writing out the cache
+        */
+       mutex_lock(&trans->transaction->cache_write_mutex);
+       while (!list_empty(&dirty)) {
+               cache = list_first_entry(&dirty,
+                                        struct btrfs_block_group_cache,
+                                        dirty_list);
+               /*
+                * this can happen if something re-dirties a block
+                * group that is already under IO.  Just wait for it to
+                * finish and then do it all again
+                */
+               if (!list_empty(&cache->io_list)) {
+                       list_del_init(&cache->io_list);
+                       btrfs_wait_cache_io(root, trans, cache,
+                                           &cache->io_ctl, path,
+                                           cache->key.objectid);
+                       btrfs_put_block_group(cache);
+               }
+
+
+               /*
+                * btrfs_wait_cache_io uses the cache->dirty_list to decide
+                * if it should update the cache_state.  Don't delete
+                * until after we wait.
+                *
+                * Since we're not running in the commit critical section
+                * we need the dirty_bgs_lock to protect from update_block_group
+                */
+               spin_lock(&cur_trans->dirty_bgs_lock);
+               list_del_init(&cache->dirty_list);
+               spin_unlock(&cur_trans->dirty_bgs_lock);
+
+               should_put = 1;
+
+               cache_save_setup(cache, trans, path);
+
+               if (cache->disk_cache_state == BTRFS_DC_SETUP) {
+                       cache->io_ctl.inode = NULL;
+                       ret = btrfs_write_out_cache(root, trans, cache, path);
+                       if (ret == 0 && cache->io_ctl.inode) {
+                               num_started++;
+                               should_put = 0;
+
+                               /*
+                                * the cache_write_mutex is protecting
+                                * the io_list
+                                */
+                               list_add_tail(&cache->io_list, io);
+                       } else {
+                               /*
+                                * if we failed to write the cache, the
+                                * generation will be bad and life goes on
+                                */
+                               ret = 0;
+                       }
+               }
+               if (!ret)
+                       ret = write_one_cache_group(trans, root, path, cache);
+
+               /* if its not on the io list, we need to put the block group */
+               if (should_put)
+                       btrfs_put_block_group(cache);
+
+               if (ret)
+                       break;
+
+               /*
+                * Avoid blocking other tasks for too long. It might even save
+                * us from writing caches for block groups that are going to be
+                * removed.
+                */
+               mutex_unlock(&trans->transaction->cache_write_mutex);
+               mutex_lock(&trans->transaction->cache_write_mutex);
+       }
+       mutex_unlock(&trans->transaction->cache_write_mutex);
+
+       /*
+        * go through delayed refs for all the stuff we've just kicked off
+        * and then loop back (just once)
+        */
+       ret = btrfs_run_delayed_refs(trans, root, 0);
+       if (!ret && loops == 0) {
+               loops++;
+               spin_lock(&cur_trans->dirty_bgs_lock);
+               list_splice_init(&cur_trans->dirty_bgs, &dirty);
+               /*
+                * dirty_bgs_lock protects us from concurrent block group
+                * deletes too (not just cache_write_mutex).
+                */
+               if (!list_empty(&dirty)) {
+                       spin_unlock(&cur_trans->dirty_bgs_lock);
+                       goto again;
+               }
+               spin_unlock(&cur_trans->dirty_bgs_lock);
+       }
+
+       btrfs_free_path(path);
+       return ret;
+}
+
 int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
                                   struct btrfs_root *root)
 {
        struct btrfs_block_group_cache *cache;
        struct btrfs_transaction *cur_trans = trans->transaction;
        int ret = 0;
+       int should_put;
        struct btrfs_path *path;
-
-       if (list_empty(&cur_trans->dirty_bgs))
-               return 0;
+       struct list_head *io = &cur_trans->io_bgs;
+       int num_started = 0;
 
        path = btrfs_alloc_path();
        if (!path)
@@ -3376,16 +3556,61 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
                cache = list_first_entry(&cur_trans->dirty_bgs,
                                         struct btrfs_block_group_cache,
                                         dirty_list);
+
+               /*
+                * this can happen if cache_save_setup re-dirties a block
+                * group that is already under IO.  Just wait for it to
+                * finish and then do it all again
+                */
+               if (!list_empty(&cache->io_list)) {
+                       list_del_init(&cache->io_list);
+                       btrfs_wait_cache_io(root, trans, cache,
+                                           &cache->io_ctl, path,
+                                           cache->key.objectid);
+                       btrfs_put_block_group(cache);
+               }
+
+               /*
+                * don't remove from the dirty list until after we've waited
+                * on any pending IO
+                */
                list_del_init(&cache->dirty_list);
-               if (cache->disk_cache_state == BTRFS_DC_CLEAR)
-                       cache_save_setup(cache, trans, path);
+               should_put = 1;
+
+               cache_save_setup(cache, trans, path);
+
                if (!ret)
-                       ret = btrfs_run_delayed_refs(trans, root,
-                                                    (unsigned long) -1);
-               if (!ret && cache->disk_cache_state == BTRFS_DC_SETUP)
-                       btrfs_write_out_cache(root, trans, cache, path);
+                       ret = btrfs_run_delayed_refs(trans, root, (unsigned long) -1);
+
+               if (!ret && cache->disk_cache_state == BTRFS_DC_SETUP) {
+                       cache->io_ctl.inode = NULL;
+                       ret = btrfs_write_out_cache(root, trans, cache, path);
+                       if (ret == 0 && cache->io_ctl.inode) {
+                               num_started++;
+                               should_put = 0;
+                               list_add_tail(&cache->io_list, io);
+                       } else {
+                               /*
+                                * if we failed to write the cache, the
+                                * generation will be bad and life goes on
+                                */
+                               ret = 0;
+                       }
+               }
                if (!ret)
                        ret = write_one_cache_group(trans, root, path, cache);
+
+               /* if its not on the io list, we need to put the block group */
+               if (should_put)
+                       btrfs_put_block_group(cache);
+       }
+
+       while (!list_empty(io)) {
+               cache = list_first_entry(io, struct btrfs_block_group_cache,
+                                        io_list);
+               list_del_init(&cache->io_list);
+               btrfs_wait_cache_io(root, trans, cache,
+                                   &cache->io_ctl, path, cache->key.objectid);
                btrfs_put_block_group(cache);
        }
 
@@ -3635,19 +3860,21 @@ u64 btrfs_get_alloc_profile(struct btrfs_root *root, int data)
  * This will check the space that the inode allocates from to make sure we have
  * enough space for bytes.
  */
-int btrfs_check_data_free_space(struct inode *inode, u64 bytes)
+int btrfs_check_data_free_space(struct inode *inode, u64 bytes, u64 write_bytes)
 {
        struct btrfs_space_info *data_sinfo;
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct btrfs_fs_info *fs_info = root->fs_info;
        u64 used;
-       int ret = 0, committed = 0, alloc_chunk = 1;
+       int ret = 0;
+       int need_commit = 2;
+       int have_pinned_space;
 
        /* make sure bytes are sectorsize aligned */
        bytes = ALIGN(bytes, root->sectorsize);
 
        if (btrfs_is_free_space_inode(inode)) {
-               committed = 1;
+               need_commit = 0;
                ASSERT(current->journal_info);
        }
 
@@ -3669,7 +3896,7 @@ again:
                 * if we don't have enough free bytes in this space then we need
                 * to alloc a new chunk.
                 */
-               if (!data_sinfo->full && alloc_chunk) {
+               if (!data_sinfo->full) {
                        u64 alloc_target;
 
                        data_sinfo->force_alloc = CHUNK_ALLOC_FORCE;
@@ -3697,8 +3924,10 @@ alloc:
                        if (ret < 0) {
                                if (ret != -ENOSPC)
                                        return ret;
-                               else
+                               else {
+                                       have_pinned_space = 1;
                                        goto commit_trans;
+                               }
                        }
 
                        if (!data_sinfo)
@@ -3709,26 +3938,39 @@ alloc:
 
                /*
                 * If we don't have enough pinned space to deal with this
-                * allocation don't bother committing the transaction.
+                * allocation, and no removed chunk in current transaction,
+                * don't bother committing the transaction.
                 */
-               if (percpu_counter_compare(&data_sinfo->total_bytes_pinned,
-                                          bytes) < 0)
-                       committed = 1;
+               have_pinned_space = percpu_counter_compare(
+                       &data_sinfo->total_bytes_pinned,
+                       used + bytes - data_sinfo->total_bytes);
                spin_unlock(&data_sinfo->lock);
 
                /* commit the current transaction and try again */
 commit_trans:
-               if (!committed &&
+               if (need_commit &&
                    !atomic_read(&root->fs_info->open_ioctl_trans)) {
-                       committed = 1;
+                       need_commit--;
 
                        trans = btrfs_join_transaction(root);
                        if (IS_ERR(trans))
                                return PTR_ERR(trans);
-                       ret = btrfs_commit_transaction(trans, root);
-                       if (ret)
-                               return ret;
-                       goto again;
+                       if (have_pinned_space >= 0 ||
+                           trans->transaction->have_free_bgs ||
+                           need_commit > 0) {
+                               ret = btrfs_commit_transaction(trans, root);
+                               if (ret)
+                                       return ret;
+                               /*
+                                * make sure that all running delayed iput are
+                                * done
+                                */
+                               down_write(&root->fs_info->delayed_iput_sem);
+                               up_write(&root->fs_info->delayed_iput_sem);
+                               goto again;
+                       } else {
+                               btrfs_end_transaction(trans, root);
+                       }
                }
 
                trace_btrfs_space_reservation(root->fs_info,
@@ -3736,12 +3978,16 @@ commit_trans:
                                              data_sinfo->flags, bytes, 1);
                return -ENOSPC;
        }
+       ret = btrfs_qgroup_reserve(root, write_bytes);
+       if (ret)
+               goto out;
        data_sinfo->bytes_may_use += bytes;
        trace_btrfs_space_reservation(root->fs_info, "space_info",
                                      data_sinfo->flags, bytes, 1);
+out:
        spin_unlock(&data_sinfo->lock);
 
-       return 0;
+       return ret;
 }
 
 /*
@@ -4298,8 +4544,13 @@ out:
 static inline int need_do_async_reclaim(struct btrfs_space_info *space_info,
                                        struct btrfs_fs_info *fs_info, u64 used)
 {
-       return (used >= div_factor_fine(space_info->total_bytes, 98) &&
-               !btrfs_fs_closing(fs_info) &&
+       u64 thresh = div_factor_fine(space_info->total_bytes, 98);
+
+       /* If we're just plain full then async reclaim just slows us down. */
+       if (space_info->bytes_used >= thresh)
+               return 0;
+
+       return (used >= thresh && !btrfs_fs_closing(fs_info) &&
                !test_bit(BTRFS_FS_STATE_REMOUNTING, &fs_info->fs_state));
 }
 
@@ -4354,10 +4605,7 @@ static void btrfs_async_reclaim_metadata_space(struct work_struct *work)
                if (!btrfs_need_do_async_reclaim(space_info, fs_info,
                                                 flush_state))
                        return;
-       } while (flush_state <= COMMIT_TRANS);
-
-       if (btrfs_need_do_async_reclaim(space_info, fs_info, flush_state))
-               queue_work(system_unbound_wq, work);
+       } while (flush_state < COMMIT_TRANS);
 }
 
 void btrfs_init_async_reclaim_work(struct work_struct *work)
@@ -4700,6 +4948,11 @@ void btrfs_free_block_rsv(struct btrfs_root *root,
        kfree(rsv);
 }
 
+void __btrfs_free_block_rsv(struct btrfs_block_rsv *rsv)
+{
+       kfree(rsv);
+}
+
 int btrfs_block_rsv_add(struct btrfs_root *root,
                        struct btrfs_block_rsv *block_rsv, u64 num_bytes,
                        enum btrfs_reserve_flush_enum flush)
@@ -4812,10 +5065,10 @@ static u64 calc_global_metadata_size(struct btrfs_fs_info *fs_info)
 
        num_bytes = (data_used >> fs_info->sb->s_blocksize_bits) *
                    csum_size * 2;
-       num_bytes += div64_u64(data_used + meta_used, 50);
+       num_bytes += div_u64(data_used + meta_used, 50);
 
        if (num_bytes * 3 > meta_used)
-               num_bytes = div64_u64(meta_used, 3);
+               num_bytes = div_u64(meta_used, 3);
 
        return ALIGN(num_bytes, fs_info->extent_root->nodesize << 10);
 }
@@ -4998,8 +5251,6 @@ void btrfs_subvolume_release_metadata(struct btrfs_root *root,
                                      u64 qgroup_reserved)
 {
        btrfs_block_rsv_release(root, rsv, (u64)-1);
-       if (qgroup_reserved)
-               btrfs_qgroup_free(root, qgroup_reserved);
 }
 
 /**
@@ -5066,30 +5317,18 @@ static u64 calc_csum_metadata_size(struct inode *inode, u64 num_bytes,
                                   int reserve)
 {
        struct btrfs_root *root = BTRFS_I(inode)->root;
-       u64 csum_size;
-       int num_csums_per_leaf;
-       int num_csums;
-       int old_csums;
+       u64 old_csums, num_csums;
 
        if (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM &&
            BTRFS_I(inode)->csum_bytes == 0)
                return 0;
 
-       old_csums = (int)div64_u64(BTRFS_I(inode)->csum_bytes, root->sectorsize);
+       old_csums = btrfs_csum_bytes_to_leaves(root, BTRFS_I(inode)->csum_bytes);
        if (reserve)
                BTRFS_I(inode)->csum_bytes += num_bytes;
        else
                BTRFS_I(inode)->csum_bytes -= num_bytes;
-       csum_size = BTRFS_LEAF_DATA_SIZE(root) - sizeof(struct btrfs_item);
-       num_csums_per_leaf = (int)div64_u64(csum_size,
-                                           sizeof(struct btrfs_csum_item) +
-                                           sizeof(struct btrfs_disk_key));
-       num_csums = (int)div64_u64(BTRFS_I(inode)->csum_bytes, root->sectorsize);
-       num_csums = num_csums + num_csums_per_leaf - 1;
-       num_csums = num_csums / num_csums_per_leaf;
-
-       old_csums = old_csums + num_csums_per_leaf - 1;
-       old_csums = old_csums / num_csums_per_leaf;
+       num_csums = btrfs_csum_bytes_to_leaves(root, BTRFS_I(inode)->csum_bytes);
 
        /* No change, no need to reserve more */
        if (old_csums == num_csums)
@@ -5163,8 +5402,7 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
        spin_unlock(&BTRFS_I(inode)->lock);
 
        if (root->fs_info->quota_enabled) {
-               ret = btrfs_qgroup_reserve(root, num_bytes +
-                                          nr_extents * root->nodesize);
+               ret = btrfs_qgroup_reserve(root, nr_extents * root->nodesize);
                if (ret)
                        goto out_fail;
        }
@@ -5172,8 +5410,7 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
        ret = reserve_metadata_bytes(root, block_rsv, to_reserve, flush);
        if (unlikely(ret)) {
                if (root->fs_info->quota_enabled)
-                       btrfs_qgroup_free(root, num_bytes +
-                                               nr_extents * root->nodesize);
+                       btrfs_qgroup_free(root, nr_extents * root->nodesize);
                goto out_fail;
        }
 
@@ -5290,10 +5527,6 @@ void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes)
 
        trace_btrfs_space_reservation(root->fs_info, "delalloc",
                                      btrfs_ino(inode), to_free, 0);
-       if (root->fs_info->quota_enabled) {
-               btrfs_qgroup_free(root, num_bytes +
-                                       dropped * root->nodesize);
-       }
 
        btrfs_block_rsv_release(root, &root->fs_info->delalloc_block_rsv,
                                to_free);
@@ -5318,7 +5551,7 @@ int btrfs_delalloc_reserve_space(struct inode *inode, u64 num_bytes)
 {
        int ret;
 
-       ret = btrfs_check_data_free_space(inode, num_bytes);
+       ret = btrfs_check_data_free_space(inode, num_bytes, num_bytes);
        if (ret)
                return ret;
 
@@ -5390,14 +5623,6 @@ static int update_block_group(struct btrfs_trans_handle *trans,
                if (!alloc && cache->cached == BTRFS_CACHE_NO)
                        cache_block_group(cache, 1);
 
-               spin_lock(&trans->transaction->dirty_bgs_lock);
-               if (list_empty(&cache->dirty_list)) {
-                       list_add_tail(&cache->dirty_list,
-                                     &trans->transaction->dirty_bgs);
-                       btrfs_get_block_group(cache);
-               }
-               spin_unlock(&trans->transaction->dirty_bgs_lock);
-
                byte_in_group = bytenr - cache->key.objectid;
                WARN_ON(byte_in_group > cache->key.offset);
 
@@ -5446,6 +5671,16 @@ static int update_block_group(struct btrfs_trans_handle *trans,
                                spin_unlock(&info->unused_bgs_lock);
                        }
                }
+
+               spin_lock(&trans->transaction->dirty_bgs_lock);
+               if (list_empty(&cache->dirty_list)) {
+                       list_add_tail(&cache->dirty_list,
+                                     &trans->transaction->dirty_bgs);
+                               trans->transaction->num_dirty_bgs++;
+                       btrfs_get_block_group(cache);
+               }
+               spin_unlock(&trans->transaction->dirty_bgs_lock);
+
                btrfs_put_block_group(cache);
                total -= num_bytes;
                bytenr += num_bytes;
@@ -6956,15 +7191,15 @@ static int __btrfs_free_reserved_extent(struct btrfs_root *root,
                return -ENOSPC;
        }
 
-       if (btrfs_test_opt(root, DISCARD))
-               ret = btrfs_discard_extent(root, start, len, NULL);
-
        if (pin)
                pin_down_extent(root, cache, start, len, 1);
        else {
+               if (btrfs_test_opt(root, DISCARD))
+                       ret = btrfs_discard_extent(root, start, len, NULL);
                btrfs_add_free_space(cache, start, len);
                btrfs_update_reserved_bytes(cache, len, RESERVE_FREE, delalloc);
        }
+
        btrfs_put_block_group(cache);
 
        trace_btrfs_reserved_extent_free(root, start, len);
@@ -7095,9 +7330,9 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
        ret = btrfs_insert_empty_item(trans, fs_info->extent_root, path,
                                      ins, size);
        if (ret) {
+               btrfs_free_path(path);
                btrfs_free_and_pin_reserved_extent(root, ins->objectid,
                                                   root->nodesize);
-               btrfs_free_path(path);
                return ret;
        }
 
@@ -7217,7 +7452,7 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root,
        btrfs_set_header_generation(buf, trans->transid);
        btrfs_set_buffer_lockdep_class(root->root_key.objectid, buf, level);
        btrfs_tree_lock(buf);
-       clean_tree_block(trans, root, buf);
+       clean_tree_block(trans, root->fs_info, buf);
        clear_bit(EXTENT_BUFFER_STALE, &buf->bflags);
 
        btrfs_set_lock_blocking(buf);
@@ -7311,7 +7546,7 @@ static void unuse_block_rsv(struct btrfs_fs_info *fs_info,
  * returns the key for the extent through ins, and a tree buffer for
  * the first block of the extent through buf.
  *
- * returns the tree buffer or NULL.
+ * returns the tree buffer or an ERR_PTR on error.
  */
 struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans,
                                        struct btrfs_root *root,
@@ -7322,6 +7557,7 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans,
        struct btrfs_key ins;
        struct btrfs_block_rsv *block_rsv;
        struct extent_buffer *buf;
+       struct btrfs_delayed_extent_op *extent_op;
        u64 flags = 0;
        int ret;
        u32 blocksize = root->nodesize;
@@ -7342,13 +7578,14 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans,
 
        ret = btrfs_reserve_extent(root, blocksize, blocksize,
                                   empty_size, hint, &ins, 0, 0);
-       if (ret) {
-               unuse_block_rsv(root->fs_info, block_rsv, blocksize);
-               return ERR_PTR(ret);
-       }
+       if (ret)
+               goto out_unuse;
 
        buf = btrfs_init_new_buffer(trans, root, ins.objectid, level);
-       BUG_ON(IS_ERR(buf)); /* -ENOMEM */
+       if (IS_ERR(buf)) {
+               ret = PTR_ERR(buf);
+               goto out_free_reserved;
+       }
 
        if (root_objectid == BTRFS_TREE_RELOC_OBJECTID) {
                if (parent == 0)
@@ -7358,9 +7595,11 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans,
                BUG_ON(parent > 0);
 
        if (root_objectid != BTRFS_TREE_LOG_OBJECTID) {
-               struct btrfs_delayed_extent_op *extent_op;
                extent_op = btrfs_alloc_delayed_extent_op();
-               BUG_ON(!extent_op); /* -ENOMEM */
+               if (!extent_op) {
+                       ret = -ENOMEM;
+                       goto out_free_buf;
+               }
                if (key)
                        memcpy(&extent_op->key, key, sizeof(extent_op->key));
                else
@@ -7375,13 +7614,24 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans,
                extent_op->level = level;
 
                ret = btrfs_add_delayed_tree_ref(root->fs_info, trans,
-                                       ins.objectid,
-                                       ins.offset, parent, root_objectid,
-                                       level, BTRFS_ADD_DELAYED_EXTENT,
-                                       extent_op, 0);
-               BUG_ON(ret); /* -ENOMEM */
+                                                ins.objectid, ins.offset,
+                                                parent, root_objectid, level,
+                                                BTRFS_ADD_DELAYED_EXTENT,
+                                                extent_op, 0);
+               if (ret)
+                       goto out_free_delayed;
        }
        return buf;
+
+out_free_delayed:
+       btrfs_free_delayed_extent_op(extent_op);
+out_free_buf:
+       free_extent_buffer(buf);
+out_free_reserved:
+       btrfs_free_reserved_extent(root, ins.objectid, ins.offset, 0);
+out_unuse:
+       unuse_block_rsv(root->fs_info, block_rsv, blocksize);
+       return ERR_PTR(ret);
 }
 
 struct walk_control {
@@ -7815,7 +8065,7 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
        bytenr = btrfs_node_blockptr(path->nodes[level], path->slots[level]);
        blocksize = root->nodesize;
 
-       next = btrfs_find_tree_block(root, bytenr);
+       next = btrfs_find_tree_block(root->fs_info, bytenr);
        if (!next) {
                next = btrfs_find_create_tree_block(root, bytenr);
                if (!next)
@@ -8016,7 +8266,7 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans,
                        btrfs_set_lock_blocking(eb);
                        path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING;
                }
-               clean_tree_block(trans, root, eb);
+               clean_tree_block(trans, root->fs_info, eb);
        }
 
        if (eb == root->node) {
@@ -8533,10 +8783,30 @@ int btrfs_set_block_group_ro(struct btrfs_root *root,
 
        BUG_ON(cache->ro);
 
+again:
        trans = btrfs_join_transaction(root);
        if (IS_ERR(trans))
                return PTR_ERR(trans);
 
+       /*
+        * we're not allowed to set block groups readonly after the dirty
+        * block groups cache has started writing.  If it already started,
+        * back off and let this transaction commit
+        */
+       mutex_lock(&root->fs_info->ro_block_group_mutex);
+       if (trans->transaction->dirty_bg_run) {
+               u64 transid = trans->transid;
+
+               mutex_unlock(&root->fs_info->ro_block_group_mutex);
+               btrfs_end_transaction(trans, root);
+
+               ret = btrfs_wait_for_commit(root, transid);
+               if (ret)
+                       return ret;
+               goto again;
+       }
+
+
        ret = set_block_group_ro(cache, 0);
        if (!ret)
                goto out;
@@ -8551,6 +8821,7 @@ out:
                alloc_flags = update_block_group_flags(root, cache->flags);
                check_system_chunk(trans, root, alloc_flags);
        }
+       mutex_unlock(&root->fs_info->ro_block_group_mutex);
 
        btrfs_end_transaction(trans, root);
        return ret;
@@ -8720,7 +8991,7 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr)
                min_free <<= 1;
        } else if (index == BTRFS_RAID_RAID0) {
                dev_min = fs_devices->rw_devices;
-               do_div(min_free, dev_min);
+               min_free = div64_u64(min_free, dev_min);
        }
 
        /* We need to do this so that we can look at pending chunks */
@@ -8992,6 +9263,7 @@ btrfs_create_block_group_cache(struct btrfs_root *root, u64 start, u64 size)
        INIT_LIST_HEAD(&cache->bg_list);
        INIT_LIST_HEAD(&cache->ro_list);
        INIT_LIST_HEAD(&cache->dirty_list);
+       INIT_LIST_HEAD(&cache->io_list);
        btrfs_init_free_space_ctl(cache);
        atomic_set(&cache->trimming, 0);
 
@@ -9355,7 +9627,38 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
                goto out;
        }
 
+       /*
+        * get the inode first so any iput calls done for the io_list
+        * aren't the final iput (no unlinks allowed now)
+        */
        inode = lookup_free_space_inode(tree_root, block_group, path);
+
+       mutex_lock(&trans->transaction->cache_write_mutex);
+       /*
+        * make sure our free spache cache IO is done before remove the
+        * free space inode
+        */
+       spin_lock(&trans->transaction->dirty_bgs_lock);
+       if (!list_empty(&block_group->io_list)) {
+               list_del_init(&block_group->io_list);
+
+               WARN_ON(!IS_ERR(inode) && inode != block_group->io_ctl.inode);
+
+               spin_unlock(&trans->transaction->dirty_bgs_lock);
+               btrfs_wait_cache_io(root, trans, block_group,
+                                   &block_group->io_ctl, path,
+                                   block_group->key.objectid);
+               btrfs_put_block_group(block_group);
+               spin_lock(&trans->transaction->dirty_bgs_lock);
+       }
+
+       if (!list_empty(&block_group->dirty_list)) {
+               list_del_init(&block_group->dirty_list);
+               btrfs_put_block_group(block_group);
+       }
+       spin_unlock(&trans->transaction->dirty_bgs_lock);
+       mutex_unlock(&trans->transaction->cache_write_mutex);
+
        if (!IS_ERR(inode)) {
                ret = btrfs_orphan_add(trans, inode);
                if (ret) {
@@ -9448,18 +9751,29 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
 
        spin_lock(&trans->transaction->dirty_bgs_lock);
        if (!list_empty(&block_group->dirty_list)) {
-               list_del_init(&block_group->dirty_list);
-               btrfs_put_block_group(block_group);
+               WARN_ON(1);
+       }
+       if (!list_empty(&block_group->io_list)) {
+               WARN_ON(1);
        }
        spin_unlock(&trans->transaction->dirty_bgs_lock);
-
        btrfs_remove_free_space_cache(block_group);
 
        spin_lock(&block_group->space_info->lock);
        list_del_init(&block_group->ro_list);
+
+       if (btrfs_test_opt(root, ENOSPC_DEBUG)) {
+               WARN_ON(block_group->space_info->total_bytes
+                       < block_group->key.offset);
+               WARN_ON(block_group->space_info->bytes_readonly
+                       < block_group->key.offset);
+               WARN_ON(block_group->space_info->disk_total
+                       < block_group->key.offset * factor);
+       }
        block_group->space_info->total_bytes -= block_group->key.offset;
        block_group->space_info->bytes_readonly -= block_group->key.offset;
        block_group->space_info->disk_total -= block_group->key.offset * factor;
+
        spin_unlock(&block_group->space_info->lock);
 
        memcpy(&key, &block_group->key, sizeof(key));
@@ -9647,8 +9961,18 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info)
                mutex_unlock(&fs_info->unused_bg_unpin_mutex);
 
                /* Reset pinned so btrfs_put_block_group doesn't complain */
+               spin_lock(&space_info->lock);
+               spin_lock(&block_group->lock);
+
+               space_info->bytes_pinned -= block_group->pinned;
+               space_info->bytes_readonly += block_group->pinned;
+               percpu_counter_add(&space_info->total_bytes_pinned,
+                                  -block_group->pinned);
                block_group->pinned = 0;
 
+               spin_unlock(&block_group->lock);
+               spin_unlock(&space_info->lock);
+
                /*
                 * Btrfs_remove_chunk will abort the transaction if things go
                 * horribly wrong.
index d688cfe5d4962ddf626e97a36fc8136edd7922b9..43af5a61ad25b4dbb3f4c0f2cb89160c120d1ac7 100644 (file)
@@ -4514,8 +4514,11 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
                }
                ret = fiemap_fill_next_extent(fieinfo, em_start, disko,
                                              em_len, flags);
-               if (ret)
+               if (ret) {
+                       if (ret == 1)
+                               ret = 0;
                        goto out_free;
+               }
        }
 out_free:
        free_extent_map(em);
@@ -4557,36 +4560,37 @@ static void btrfs_release_extent_buffer_page(struct extent_buffer *eb)
        do {
                index--;
                page = eb->pages[index];
-               if (page && mapped) {
+               if (!page)
+                       continue;
+               if (mapped)
                        spin_lock(&page->mapping->private_lock);
+               /*
+                * We do this since we'll remove the pages after we've
+                * removed the eb from the radix tree, so we could race
+                * and have this page now attached to the new eb.  So
+                * only clear page_private if it's still connected to
+                * this eb.
+                */
+               if (PagePrivate(page) &&
+                   page->private == (unsigned long)eb) {
+                       BUG_ON(test_bit(EXTENT_BUFFER_DIRTY, &eb->bflags));
+                       BUG_ON(PageDirty(page));
+                       BUG_ON(PageWriteback(page));
                        /*
-                        * We do this since we'll remove the pages after we've
-                        * removed the eb from the radix tree, so we could race
-                        * and have this page now attached to the new eb.  So
-                        * only clear page_private if it's still connected to
-                        * this eb.
+                        * We need to make sure we haven't be attached
+                        * to a new eb.
                         */
-                       if (PagePrivate(page) &&
-                           page->private == (unsigned long)eb) {
-                               BUG_ON(test_bit(EXTENT_BUFFER_DIRTY, &eb->bflags));
-                               BUG_ON(PageDirty(page));
-                               BUG_ON(PageWriteback(page));
-                               /*
-                                * We need to make sure we haven't be attached
-                                * to a new eb.
-                                */
-                               ClearPagePrivate(page);
-                               set_page_private(page, 0);
-                               /* One for the page private */
-                               page_cache_release(page);
-                       }
-                       spin_unlock(&page->mapping->private_lock);
-
-               }
-               if (page) {
-                       /* One for when we alloced the page */
+                       ClearPagePrivate(page);
+                       set_page_private(page, 0);
+                       /* One for the page private */
                        page_cache_release(page);
                }
+
+               if (mapped)
+                       spin_unlock(&page->mapping->private_lock);
+
+               /* One for when we alloced the page */
+               page_cache_release(page);
        } while (index != 0);
 }
 
@@ -4867,6 +4871,7 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info,
                                mark_extent_buffer_accessed(exists, p);
                                goto free_eb;
                        }
+                       exists = NULL;
 
                        /*
                         * Do this so attach doesn't complain and we need to
@@ -4930,12 +4935,12 @@ again:
        return eb;
 
 free_eb:
+       WARN_ON(!atomic_dec_and_test(&eb->refs));
        for (i = 0; i < num_pages; i++) {
                if (eb->pages[i])
                        unlock_page(eb->pages[i]);
        }
 
-       WARN_ON(!atomic_dec_and_test(&eb->refs));
        btrfs_release_extent_buffer(eb);
        return exists;
 }
index 695b0ccfb7553e786f4c9634d3a86c0263c86321..c668f36898d3a4c2dd2e0e18456dd2cfa6c55747 100644 (file)
@@ -97,7 +97,7 @@ struct extent_io_tree {
        u64 dirty_bytes;
        int track_uptodate;
        spinlock_t lock;
-       struct extent_io_ops *ops;
+       const struct extent_io_ops *ops;
 };
 
 struct extent_state {
index 84a2d1868271b86b1f6a771bf5cf734a8e45c3dc..58ece6558430094969d7dcea7e477f6949c2eac6 100644 (file)
@@ -185,8 +185,8 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
        nblocks = bio->bi_iter.bi_size >> inode->i_sb->s_blocksize_bits;
        if (!dst) {
                if (nblocks * csum_size > BTRFS_BIO_INLINE_CSUM_SIZE) {
-                       btrfs_bio->csum_allocated = kmalloc(nblocks * csum_size,
-                                                           GFP_NOFS);
+                       btrfs_bio->csum_allocated = kmalloc_array(nblocks,
+                                       csum_size, GFP_NOFS);
                        if (!btrfs_bio->csum_allocated) {
                                btrfs_free_path(path);
                                return -ENOMEM;
@@ -553,7 +553,7 @@ static noinline void truncate_one_csum(struct btrfs_root *root,
                btrfs_truncate_item(root, path, new_size, 0);
 
                key->offset = end_byte;
-               btrfs_set_item_key_safe(root, path, key);
+               btrfs_set_item_key_safe(root->fs_info, path, key);
        } else {
                BUG();
        }
index faa7d390841b9a245a95ffb4944d515c3c486cbf..b072e17479aa8e26a32ede03fa8b5315ca1f9a7e 100644 (file)
@@ -273,11 +273,7 @@ void btrfs_cleanup_defrag_inodes(struct btrfs_fs_info *fs_info)
                defrag = rb_entry(node, struct inode_defrag, rb_node);
                kmem_cache_free(btrfs_inode_defrag_cachep, defrag);
 
-               if (need_resched()) {
-                       spin_unlock(&fs_info->defrag_inodes_lock);
-                       cond_resched();
-                       spin_lock(&fs_info->defrag_inodes_lock);
-               }
+               cond_resched_lock(&fs_info->defrag_inodes_lock);
 
                node = rb_first(&fs_info->defrag_inodes);
        }
@@ -868,7 +864,7 @@ next_slot:
 
                        memcpy(&new_key, &key, sizeof(new_key));
                        new_key.offset = end;
-                       btrfs_set_item_key_safe(root, path, &new_key);
+                       btrfs_set_item_key_safe(root->fs_info, path, &new_key);
 
                        extent_offset += end - key.offset;
                        btrfs_set_file_extent_offset(leaf, fi, extent_offset);
@@ -1126,7 +1122,7 @@ again:
                                     ino, bytenr, orig_offset,
                                     &other_start, &other_end)) {
                        new_key.offset = end;
-                       btrfs_set_item_key_safe(root, path, &new_key);
+                       btrfs_set_item_key_safe(root->fs_info, path, &new_key);
                        fi = btrfs_item_ptr(leaf, path->slots[0],
                                            struct btrfs_file_extent_item);
                        btrfs_set_file_extent_generation(leaf, fi,
@@ -1160,7 +1156,7 @@ again:
                                                         trans->transid);
                        path->slots[0]++;
                        new_key.offset = start;
-                       btrfs_set_item_key_safe(root, path, &new_key);
+                       btrfs_set_item_key_safe(root->fs_info, path, &new_key);
 
                        fi = btrfs_item_ptr(leaf, path->slots[0],
                                            struct btrfs_file_extent_item);
@@ -1485,7 +1481,7 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,
                        PAGE_CACHE_SIZE / (sizeof(struct page *)));
        nrptrs = min(nrptrs, current->nr_dirtied_pause - current->nr_dirtied);
        nrptrs = max(nrptrs, 8);
-       pages = kmalloc(nrptrs * sizeof(struct page *), GFP_KERNEL);
+       pages = kmalloc_array(nrptrs, sizeof(struct page *), GFP_KERNEL);
        if (!pages)
                return -ENOMEM;
 
@@ -1514,7 +1510,7 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,
                }
 
                reserve_bytes = num_pages << PAGE_CACHE_SHIFT;
-               ret = btrfs_check_data_free_space(inode, reserve_bytes);
+               ret = btrfs_check_data_free_space(inode, reserve_bytes, write_bytes);
                if (ret == -ENOSPC &&
                    (BTRFS_I(inode)->flags & (BTRFS_INODE_NODATACOW |
                                              BTRFS_INODE_PREALLOC))) {
@@ -1635,8 +1631,8 @@ again:
                        btrfs_end_write_no_snapshoting(root);
 
                if (only_release_metadata && copied > 0) {
-                       u64 lockstart = round_down(pos, root->sectorsize);
-                       u64 lockend = lockstart +
+                       lockstart = round_down(pos, root->sectorsize);
+                       lockend = lockstart +
                                (dirty_pages << PAGE_CACHE_SHIFT) - 1;
 
                        set_extent_bit(&BTRFS_I(inode)->io_tree, lockstart,
@@ -1809,7 +1805,9 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb,
         * otherwise subsequent syncs to a file that's been synced in this
         * transaction will appear to have already occured.
         */
+       spin_lock(&BTRFS_I(inode)->lock);
        BTRFS_I(inode)->last_sub_trans = root->log_transid;
+       spin_unlock(&BTRFS_I(inode)->lock);
        if (num_written > 0) {
                err = generic_write_sync(file, pos, num_written);
                if (err < 0)
@@ -1864,7 +1862,7 @@ static int start_ordered_ops(struct inode *inode, loff_t start, loff_t end)
 int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 {
        struct dentry *dentry = file->f_path.dentry;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct btrfs_trans_handle *trans;
        struct btrfs_log_ctx ctx;
@@ -2162,7 +2160,7 @@ static int fill_holes(struct btrfs_trans_handle *trans, struct inode *inode,
                u64 num_bytes;
 
                key.offset = offset;
-               btrfs_set_item_key_safe(root, path, &key);
+               btrfs_set_item_key_safe(root->fs_info, path, &key);
                fi = btrfs_item_ptr(leaf, path->slots[0],
                                    struct btrfs_file_extent_item);
                num_bytes = btrfs_file_extent_num_bytes(leaf, fi) + end -
@@ -2545,7 +2543,6 @@ static long btrfs_fallocate(struct file *file, int mode,
 {
        struct inode *inode = file_inode(file);
        struct extent_state *cached_state = NULL;
-       struct btrfs_root *root = BTRFS_I(inode)->root;
        u64 cur_offset;
        u64 last_byte;
        u64 alloc_start;
@@ -2570,14 +2567,9 @@ static long btrfs_fallocate(struct file *file, int mode,
         * Make sure we have enough space before we do the
         * allocation.
         */
-       ret = btrfs_check_data_free_space(inode, alloc_end - alloc_start);
+       ret = btrfs_check_data_free_space(inode, alloc_end - alloc_start, alloc_end - alloc_start);
        if (ret)
                return ret;
-       if (root->fs_info->quota_enabled) {
-               ret = btrfs_qgroup_reserve(root, alloc_end - alloc_start);
-               if (ret)
-                       goto out_reserve_fail;
-       }
 
        mutex_lock(&inode->i_mutex);
        ret = inode_newsize_ok(inode, alloc_end);
@@ -2667,23 +2659,35 @@ static long btrfs_fallocate(struct file *file, int mode,
                                                        1 << inode->i_blkbits,
                                                        offset + len,
                                                        &alloc_hint);
-
-                       if (ret < 0) {
-                               free_extent_map(em);
-                               break;
-                       }
                } else if (actual_end > inode->i_size &&
                           !(mode & FALLOC_FL_KEEP_SIZE)) {
+                       struct btrfs_trans_handle *trans;
+                       struct btrfs_root *root = BTRFS_I(inode)->root;
+
                        /*
                         * We didn't need to allocate any more space, but we
                         * still extended the size of the file so we need to
-                        * update i_size.
+                        * update i_size and the inode item.
                         */
-                       inode->i_ctime = CURRENT_TIME;
-                       i_size_write(inode, actual_end);
-                       btrfs_ordered_update_i_size(inode, actual_end, NULL);
+                       trans = btrfs_start_transaction(root, 1);
+                       if (IS_ERR(trans)) {
+                               ret = PTR_ERR(trans);
+                       } else {
+                               inode->i_ctime = CURRENT_TIME;
+                               i_size_write(inode, actual_end);
+                               btrfs_ordered_update_i_size(inode, actual_end,
+                                                           NULL);
+                               ret = btrfs_update_inode(trans, root, inode);
+                               if (ret)
+                                       btrfs_end_transaction(trans, root);
+                               else
+                                       ret = btrfs_end_transaction(trans,
+                                                                   root);
+                       }
                }
                free_extent_map(em);
+               if (ret < 0)
+                       break;
 
                cur_offset = last_byte;
                if (cur_offset >= alloc_end) {
@@ -2695,9 +2699,6 @@ static long btrfs_fallocate(struct file *file, int mode,
                             &cached_state, GFP_NOFS);
 out:
        mutex_unlock(&inode->i_mutex);
-       if (root->fs_info->quota_enabled)
-               btrfs_qgroup_free(root, alloc_end - alloc_start);
-out_reserve_fail:
        /* Let go of our reservation. */
        btrfs_free_reserved_data_space(inode, alloc_end - alloc_start);
        return ret;
index a71978578fa71a11d83f8c435541b807eedc2b51..41c510b7cc110891bbc3818638137e3e516d5800 100644 (file)
@@ -85,7 +85,8 @@ static struct inode *__lookup_free_space_inode(struct btrfs_root *root,
        }
 
        mapping_set_gfp_mask(inode->i_mapping,
-                       mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
+                       mapping_gfp_mask(inode->i_mapping) &
+                       ~(GFP_NOFS & ~__GFP_HIGHMEM));
 
        return inode;
 }
@@ -170,13 +171,13 @@ static int __create_free_space_inode(struct btrfs_root *root,
        key.objectid = BTRFS_FREE_SPACE_OBJECTID;
        key.offset = offset;
        key.type = 0;
-
        ret = btrfs_insert_empty_item(trans, root, path, &key,
                                      sizeof(struct btrfs_free_space_header));
        if (ret < 0) {
                btrfs_release_path(path);
                return ret;
        }
+
        leaf = path->nodes[0];
        header = btrfs_item_ptr(leaf, path->slots[0],
                                struct btrfs_free_space_header);
@@ -225,9 +226,37 @@ int btrfs_check_trunc_cache_free_space(struct btrfs_root *root,
 
 int btrfs_truncate_free_space_cache(struct btrfs_root *root,
                                    struct btrfs_trans_handle *trans,
+                                   struct btrfs_block_group_cache *block_group,
                                    struct inode *inode)
 {
        int ret = 0;
+       struct btrfs_path *path = btrfs_alloc_path();
+
+       if (!path) {
+               ret = -ENOMEM;
+               goto fail;
+       }
+
+       if (block_group) {
+               mutex_lock(&trans->transaction->cache_write_mutex);
+               if (!list_empty(&block_group->io_list)) {
+                       list_del_init(&block_group->io_list);
+
+                       btrfs_wait_cache_io(root, trans, block_group,
+                                           &block_group->io_ctl, path,
+                                           block_group->key.objectid);
+                       btrfs_put_block_group(block_group);
+               }
+
+               /*
+                * now that we've truncated the cache away, its no longer
+                * setup or written
+                */
+               spin_lock(&block_group->lock);
+               block_group->disk_cache_state = BTRFS_DC_CLEAR;
+               spin_unlock(&block_group->lock);
+       }
+       btrfs_free_path(path);
 
        btrfs_i_size_write(inode, 0);
        truncate_pagecache(inode, 0);
@@ -235,15 +264,23 @@ int btrfs_truncate_free_space_cache(struct btrfs_root *root,
        /*
         * We don't need an orphan item because truncating the free space cache
         * will never be split across transactions.
+        * We don't need to check for -EAGAIN because we're a free space
+        * cache inode
         */
        ret = btrfs_truncate_inode_items(trans, root, inode,
                                         0, BTRFS_EXTENT_DATA_KEY);
        if (ret) {
+               mutex_unlock(&trans->transaction->cache_write_mutex);
                btrfs_abort_transaction(trans, root, ret);
                return ret;
        }
 
        ret = btrfs_update_inode(trans, root, inode);
+
+       if (block_group)
+               mutex_unlock(&trans->transaction->cache_write_mutex);
+
+fail:
        if (ret)
                btrfs_abort_transaction(trans, root, ret);
 
@@ -269,18 +306,7 @@ static int readahead_cache(struct inode *inode)
        return 0;
 }
 
-struct io_ctl {
-       void *cur, *orig;
-       struct page *page;
-       struct page **pages;
-       struct btrfs_root *root;
-       unsigned long size;
-       int index;
-       int num_pages;
-       unsigned check_crcs:1;
-};
-
-static int io_ctl_init(struct io_ctl *io_ctl, struct inode *inode,
+static int io_ctl_init(struct btrfs_io_ctl *io_ctl, struct inode *inode,
                       struct btrfs_root *root, int write)
 {
        int num_pages;
@@ -296,45 +322,46 @@ static int io_ctl_init(struct io_ctl *io_ctl, struct inode *inode,
            (num_pages * sizeof(u32)) >= PAGE_CACHE_SIZE)
                return -ENOSPC;
 
-       memset(io_ctl, 0, sizeof(struct io_ctl));
+       memset(io_ctl, 0, sizeof(struct btrfs_io_ctl));
 
-       io_ctl->pages = kzalloc(sizeof(struct page *) * num_pages, GFP_NOFS);
+       io_ctl->pages = kcalloc(num_pages, sizeof(struct page *), GFP_NOFS);
        if (!io_ctl->pages)
                return -ENOMEM;
 
        io_ctl->num_pages = num_pages;
        io_ctl->root = root;
        io_ctl->check_crcs = check_crcs;
+       io_ctl->inode = inode;
 
        return 0;
 }
 
-static void io_ctl_free(struct io_ctl *io_ctl)
+static void io_ctl_free(struct btrfs_io_ctl *io_ctl)
 {
        kfree(io_ctl->pages);
+       io_ctl->pages = NULL;
 }
 
-static void io_ctl_unmap_page(struct io_ctl *io_ctl)
+static void io_ctl_unmap_page(struct btrfs_io_ctl *io_ctl)
 {
        if (io_ctl->cur) {
-               kunmap(io_ctl->page);
                io_ctl->cur = NULL;
                io_ctl->orig = NULL;
        }
 }
 
-static void io_ctl_map_page(struct io_ctl *io_ctl, int clear)
+static void io_ctl_map_page(struct btrfs_io_ctl *io_ctl, int clear)
 {
        ASSERT(io_ctl->index < io_ctl->num_pages);
        io_ctl->page = io_ctl->pages[io_ctl->index++];
-       io_ctl->cur = kmap(io_ctl->page);
+       io_ctl->cur = page_address(io_ctl->page);
        io_ctl->orig = io_ctl->cur;
        io_ctl->size = PAGE_CACHE_SIZE;
        if (clear)
                memset(io_ctl->cur, 0, PAGE_CACHE_SIZE);
 }
 
-static void io_ctl_drop_pages(struct io_ctl *io_ctl)
+static void io_ctl_drop_pages(struct btrfs_io_ctl *io_ctl)
 {
        int i;
 
@@ -349,7 +376,7 @@ static void io_ctl_drop_pages(struct io_ctl *io_ctl)
        }
 }
 
-static int io_ctl_prepare_pages(struct io_ctl *io_ctl, struct inode *inode,
+static int io_ctl_prepare_pages(struct btrfs_io_ctl *io_ctl, struct inode *inode,
                                int uptodate)
 {
        struct page *page;
@@ -383,7 +410,7 @@ static int io_ctl_prepare_pages(struct io_ctl *io_ctl, struct inode *inode,
        return 0;
 }
 
-static void io_ctl_set_generation(struct io_ctl *io_ctl, u64 generation)
+static void io_ctl_set_generation(struct btrfs_io_ctl *io_ctl, u64 generation)
 {
        __le64 *val;
 
@@ -406,7 +433,7 @@ static void io_ctl_set_generation(struct io_ctl *io_ctl, u64 generation)
        io_ctl->cur += sizeof(u64);
 }
 
-static int io_ctl_check_generation(struct io_ctl *io_ctl, u64 generation)
+static int io_ctl_check_generation(struct btrfs_io_ctl *io_ctl, u64 generation)
 {
        __le64 *gen;
 
@@ -435,7 +462,7 @@ static int io_ctl_check_generation(struct io_ctl *io_ctl, u64 generation)
        return 0;
 }
 
-static void io_ctl_set_crc(struct io_ctl *io_ctl, int index)
+static void io_ctl_set_crc(struct btrfs_io_ctl *io_ctl, int index)
 {
        u32 *tmp;
        u32 crc = ~(u32)0;
@@ -453,13 +480,12 @@ static void io_ctl_set_crc(struct io_ctl *io_ctl, int index)
                              PAGE_CACHE_SIZE - offset);
        btrfs_csum_final(crc, (char *)&crc);
        io_ctl_unmap_page(io_ctl);
-       tmp = kmap(io_ctl->pages[0]);
+       tmp = page_address(io_ctl->pages[0]);
        tmp += index;
        *tmp = crc;
-       kunmap(io_ctl->pages[0]);
 }
 
-static int io_ctl_check_crc(struct io_ctl *io_ctl, int index)
+static int io_ctl_check_crc(struct btrfs_io_ctl *io_ctl, int index)
 {
        u32 *tmp, val;
        u32 crc = ~(u32)0;
@@ -473,10 +499,9 @@ static int io_ctl_check_crc(struct io_ctl *io_ctl, int index)
        if (index == 0)
                offset = sizeof(u32) * io_ctl->num_pages;
 
-       tmp = kmap(io_ctl->pages[0]);
+       tmp = page_address(io_ctl->pages[0]);
        tmp += index;
        val = *tmp;
-       kunmap(io_ctl->pages[0]);
 
        io_ctl_map_page(io_ctl, 0);
        crc = btrfs_csum_data(io_ctl->orig + offset, crc,
@@ -492,7 +517,7 @@ static int io_ctl_check_crc(struct io_ctl *io_ctl, int index)
        return 0;
 }
 
-static int io_ctl_add_entry(struct io_ctl *io_ctl, u64 offset, u64 bytes,
+static int io_ctl_add_entry(struct btrfs_io_ctl *io_ctl, u64 offset, u64 bytes,
                            void *bitmap)
 {
        struct btrfs_free_space_entry *entry;
@@ -522,7 +547,7 @@ static int io_ctl_add_entry(struct io_ctl *io_ctl, u64 offset, u64 bytes,
        return 0;
 }
 
-static int io_ctl_add_bitmap(struct io_ctl *io_ctl, void *bitmap)
+static int io_ctl_add_bitmap(struct btrfs_io_ctl *io_ctl, void *bitmap)
 {
        if (!io_ctl->cur)
                return -ENOSPC;
@@ -545,7 +570,7 @@ static int io_ctl_add_bitmap(struct io_ctl *io_ctl, void *bitmap)
        return 0;
 }
 
-static void io_ctl_zero_remaining_pages(struct io_ctl *io_ctl)
+static void io_ctl_zero_remaining_pages(struct btrfs_io_ctl *io_ctl)
 {
        /*
         * If we're not on the boundary we know we've modified the page and we
@@ -562,7 +587,7 @@ static void io_ctl_zero_remaining_pages(struct io_ctl *io_ctl)
        }
 }
 
-static int io_ctl_read_entry(struct io_ctl *io_ctl,
+static int io_ctl_read_entry(struct btrfs_io_ctl *io_ctl,
                            struct btrfs_free_space *entry, u8 *type)
 {
        struct btrfs_free_space_entry *e;
@@ -589,7 +614,7 @@ static int io_ctl_read_entry(struct io_ctl *io_ctl,
        return 0;
 }
 
-static int io_ctl_read_bitmap(struct io_ctl *io_ctl,
+static int io_ctl_read_bitmap(struct btrfs_io_ctl *io_ctl,
                              struct btrfs_free_space *entry)
 {
        int ret;
@@ -648,7 +673,7 @@ static int __load_free_space_cache(struct btrfs_root *root, struct inode *inode,
 {
        struct btrfs_free_space_header *header;
        struct extent_buffer *leaf;
-       struct io_ctl io_ctl;
+       struct btrfs_io_ctl io_ctl;
        struct btrfs_key key;
        struct btrfs_free_space *e, *n;
        LIST_HEAD(bitmaps);
@@ -877,7 +902,7 @@ out:
 }
 
 static noinline_for_stack
-int write_cache_extent_entries(struct io_ctl *io_ctl,
+int write_cache_extent_entries(struct btrfs_io_ctl *io_ctl,
                              struct btrfs_free_space_ctl *ctl,
                              struct btrfs_block_group_cache *block_group,
                              int *entries, int *bitmaps,
@@ -885,6 +910,7 @@ int write_cache_extent_entries(struct io_ctl *io_ctl,
 {
        int ret;
        struct btrfs_free_cluster *cluster = NULL;
+       struct btrfs_free_cluster *cluster_locked = NULL;
        struct rb_node *node = rb_first(&ctl->free_space_offset);
        struct btrfs_trim_range *trim_entry;
 
@@ -896,6 +922,8 @@ int write_cache_extent_entries(struct io_ctl *io_ctl,
        }
 
        if (!node && cluster) {
+               cluster_locked = cluster;
+               spin_lock(&cluster_locked->lock);
                node = rb_first(&cluster->root);
                cluster = NULL;
        }
@@ -919,9 +947,15 @@ int write_cache_extent_entries(struct io_ctl *io_ctl,
                node = rb_next(node);
                if (!node && cluster) {
                        node = rb_first(&cluster->root);
+                       cluster_locked = cluster;
+                       spin_lock(&cluster_locked->lock);
                        cluster = NULL;
                }
        }
+       if (cluster_locked) {
+               spin_unlock(&cluster_locked->lock);
+               cluster_locked = NULL;
+       }
 
        /*
         * Make sure we don't miss any range that was removed from our rbtree
@@ -939,6 +973,8 @@ int write_cache_extent_entries(struct io_ctl *io_ctl,
 
        return 0;
 fail:
+       if (cluster_locked)
+               spin_unlock(&cluster_locked->lock);
        return -ENOSPC;
 }
 
@@ -1000,7 +1036,7 @@ fail:
 static noinline_for_stack int
 write_pinned_extent_entries(struct btrfs_root *root,
                            struct btrfs_block_group_cache *block_group,
-                           struct io_ctl *io_ctl,
+                           struct btrfs_io_ctl *io_ctl,
                            int *entries)
 {
        u64 start, extent_start, extent_end, len;
@@ -1050,7 +1086,7 @@ write_pinned_extent_entries(struct btrfs_root *root,
 }
 
 static noinline_for_stack int
-write_bitmap_entries(struct io_ctl *io_ctl, struct list_head *bitmap_list)
+write_bitmap_entries(struct btrfs_io_ctl *io_ctl, struct list_head *bitmap_list)
 {
        struct list_head *pos, *n;
        int ret;
@@ -1083,10 +1119,7 @@ static int flush_dirty_cache(struct inode *inode)
 }
 
 static void noinline_for_stack
-cleanup_write_cache_enospc(struct inode *inode,
-                          struct io_ctl *io_ctl,
-                          struct extent_state **cached_state,
-                          struct list_head *bitmap_list)
+cleanup_bitmap_list(struct list_head *bitmap_list)
 {
        struct list_head *pos, *n;
 
@@ -1095,12 +1128,85 @@ cleanup_write_cache_enospc(struct inode *inode,
                        list_entry(pos, struct btrfs_free_space, list);
                list_del_init(&entry->list);
        }
+}
+
+static void noinline_for_stack
+cleanup_write_cache_enospc(struct inode *inode,
+                          struct btrfs_io_ctl *io_ctl,
+                          struct extent_state **cached_state,
+                          struct list_head *bitmap_list)
+{
        io_ctl_drop_pages(io_ctl);
        unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0,
                             i_size_read(inode) - 1, cached_state,
                             GFP_NOFS);
 }
 
+int btrfs_wait_cache_io(struct btrfs_root *root,
+                       struct btrfs_trans_handle *trans,
+                       struct btrfs_block_group_cache *block_group,
+                       struct btrfs_io_ctl *io_ctl,
+                       struct btrfs_path *path, u64 offset)
+{
+       int ret;
+       struct inode *inode = io_ctl->inode;
+
+       if (!inode)
+               return 0;
+
+       if (block_group)
+               root = root->fs_info->tree_root;
+
+       /* Flush the dirty pages in the cache file. */
+       ret = flush_dirty_cache(inode);
+       if (ret)
+               goto out;
+
+       /* Update the cache item to tell everyone this cache file is valid. */
+       ret = update_cache_item(trans, root, inode, path, offset,
+                               io_ctl->entries, io_ctl->bitmaps);
+out:
+       io_ctl_free(io_ctl);
+       if (ret) {
+               invalidate_inode_pages2(inode->i_mapping);
+               BTRFS_I(inode)->generation = 0;
+               if (block_group) {
+#ifdef DEBUG
+                       btrfs_err(root->fs_info,
+                               "failed to write free space cache for block group %llu",
+                               block_group->key.objectid);
+#endif
+               }
+       }
+       btrfs_update_inode(trans, root, inode);
+
+       if (block_group) {
+               /* the dirty list is protected by the dirty_bgs_lock */
+               spin_lock(&trans->transaction->dirty_bgs_lock);
+
+               /* the disk_cache_state is protected by the block group lock */
+               spin_lock(&block_group->lock);
+
+               /*
+                * only mark this as written if we didn't get put back on
+                * the dirty list while waiting for IO.   Otherwise our
+                * cache state won't be right, and we won't get written again
+                */
+               if (!ret && list_empty(&block_group->dirty_list))
+                       block_group->disk_cache_state = BTRFS_DC_WRITTEN;
+               else if (ret)
+                       block_group->disk_cache_state = BTRFS_DC_ERROR;
+
+               spin_unlock(&block_group->lock);
+               spin_unlock(&trans->transaction->dirty_bgs_lock);
+               io_ctl->inode = NULL;
+               iput(inode);
+       }
+
+       return ret;
+
+}
+
 /**
  * __btrfs_write_out_cache - write out cached info to an inode
  * @root - the root the inode belongs to
@@ -1112,27 +1218,29 @@ cleanup_write_cache_enospc(struct inode *inode,
  *
  * This function writes out a free space cache struct to disk for quick recovery
  * on mount.  This will return 0 if it was successfull in writing the cache out,
- * and -1 if it was not.
+ * or an errno if it was not.
  */
 static int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
                                   struct btrfs_free_space_ctl *ctl,
                                   struct btrfs_block_group_cache *block_group,
+                                  struct btrfs_io_ctl *io_ctl,
                                   struct btrfs_trans_handle *trans,
                                   struct btrfs_path *path, u64 offset)
 {
        struct extent_state *cached_state = NULL;
-       struct io_ctl io_ctl;
        LIST_HEAD(bitmap_list);
        int entries = 0;
        int bitmaps = 0;
        int ret;
+       int must_iput = 0;
 
        if (!i_size_read(inode))
-               return -1;
+               return -EIO;
 
-       ret = io_ctl_init(&io_ctl, inode, root, 1);
+       WARN_ON(io_ctl->pages);
+       ret = io_ctl_init(io_ctl, inode, root, 1);
        if (ret)
-               return -1;
+               return ret;
 
        if (block_group && (block_group->flags & BTRFS_BLOCK_GROUP_DATA)) {
                down_write(&block_group->data_rwsem);
@@ -1143,55 +1251,59 @@ static int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
                        up_write(&block_group->data_rwsem);
                        BTRFS_I(inode)->generation = 0;
                        ret = 0;
+                       must_iput = 1;
                        goto out;
                }
                spin_unlock(&block_group->lock);
        }
 
        /* Lock all pages first so we can lock the extent safely. */
-       io_ctl_prepare_pages(&io_ctl, inode, 0);
+       ret = io_ctl_prepare_pages(io_ctl, inode, 0);
+       if (ret)
+               goto out;
 
        lock_extent_bits(&BTRFS_I(inode)->io_tree, 0, i_size_read(inode) - 1,
                         0, &cached_state);
 
-       io_ctl_set_generation(&io_ctl, trans->transid);
+       io_ctl_set_generation(io_ctl, trans->transid);
 
        mutex_lock(&ctl->cache_writeout_mutex);
        /* Write out the extent entries in the free space cache */
-       ret = write_cache_extent_entries(&io_ctl, ctl,
+       spin_lock(&ctl->tree_lock);
+       ret = write_cache_extent_entries(io_ctl, ctl,
                                         block_group, &entries, &bitmaps,
                                         &bitmap_list);
-       if (ret) {
-               mutex_unlock(&ctl->cache_writeout_mutex);
-               goto out_nospc;
-       }
+       if (ret)
+               goto out_nospc_locked;
 
        /*
         * Some spaces that are freed in the current transaction are pinned,
         * they will be added into free space cache after the transaction is
         * committed, we shouldn't lose them.
+        *
+        * If this changes while we are working we'll get added back to
+        * the dirty list and redo it.  No locking needed
         */
-       ret = write_pinned_extent_entries(root, block_group, &io_ctl, &entries);
-       if (ret) {
-               mutex_unlock(&ctl->cache_writeout_mutex);
-               goto out_nospc;
-       }
+       ret = write_pinned_extent_entries(root, block_group, io_ctl, &entries);
+       if (ret)
+               goto out_nospc_locked;
 
        /*
         * At last, we write out all the bitmaps and keep cache_writeout_mutex
         * locked while doing it because a concurrent trim can be manipulating
         * or freeing the bitmap.
         */
-       ret = write_bitmap_entries(&io_ctl, &bitmap_list);
+       ret = write_bitmap_entries(io_ctl, &bitmap_list);
+       spin_unlock(&ctl->tree_lock);
        mutex_unlock(&ctl->cache_writeout_mutex);
        if (ret)
                goto out_nospc;
 
        /* Zero out the rest of the pages just to make sure */
-       io_ctl_zero_remaining_pages(&io_ctl);
+       io_ctl_zero_remaining_pages(io_ctl);
 
        /* Everything is written out, now we dirty the pages in the file. */
-       ret = btrfs_dirty_pages(root, inode, io_ctl.pages, io_ctl.num_pages,
+       ret = btrfs_dirty_pages(root, inode, io_ctl->pages, io_ctl->num_pages,
                                0, i_size_read(inode), &cached_state);
        if (ret)
                goto out_nospc;
@@ -1202,30 +1314,44 @@ static int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
         * Release the pages and unlock the extent, we will flush
         * them out later
         */
-       io_ctl_drop_pages(&io_ctl);
+       io_ctl_drop_pages(io_ctl);
 
        unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0,
                             i_size_read(inode) - 1, &cached_state, GFP_NOFS);
 
-       /* Flush the dirty pages in the cache file. */
-       ret = flush_dirty_cache(inode);
+       /*
+        * at this point the pages are under IO and we're happy,
+        * The caller is responsible for waiting on them and updating the
+        * the cache and the inode
+        */
+       io_ctl->entries = entries;
+       io_ctl->bitmaps = bitmaps;
+
+       ret = btrfs_fdatawrite_range(inode, 0, (u64)-1);
        if (ret)
                goto out;
 
-       /* Update the cache item to tell everyone this cache file is valid. */
-       ret = update_cache_item(trans, root, inode, path, offset,
-                               entries, bitmaps);
+       return 0;
+
 out:
-       io_ctl_free(&io_ctl);
+       io_ctl->inode = NULL;
+       io_ctl_free(io_ctl);
        if (ret) {
                invalidate_inode_pages2(inode->i_mapping);
                BTRFS_I(inode)->generation = 0;
        }
        btrfs_update_inode(trans, root, inode);
+       if (must_iput)
+               iput(inode);
        return ret;
 
+out_nospc_locked:
+       cleanup_bitmap_list(&bitmap_list);
+       spin_unlock(&ctl->tree_lock);
+       mutex_unlock(&ctl->cache_writeout_mutex);
+
 out_nospc:
-       cleanup_write_cache_enospc(inode, &io_ctl, &cached_state, &bitmap_list);
+       cleanup_write_cache_enospc(inode, io_ctl, &cached_state, &bitmap_list);
 
        if (block_group && (block_group->flags & BTRFS_BLOCK_GROUP_DATA))
                up_write(&block_group->data_rwsem);
@@ -1241,7 +1367,6 @@ int btrfs_write_out_cache(struct btrfs_root *root,
        struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
        struct inode *inode;
        int ret = 0;
-       enum btrfs_disk_cache_state dcs = BTRFS_DC_WRITTEN;
 
        root = root->fs_info->tree_root;
 
@@ -1250,34 +1375,34 @@ int btrfs_write_out_cache(struct btrfs_root *root,
                spin_unlock(&block_group->lock);
                return 0;
        }
-
-       if (block_group->delalloc_bytes) {
-               block_group->disk_cache_state = BTRFS_DC_WRITTEN;
-               spin_unlock(&block_group->lock);
-               return 0;
-       }
        spin_unlock(&block_group->lock);
 
        inode = lookup_free_space_inode(root, block_group, path);
        if (IS_ERR(inode))
                return 0;
 
-       ret = __btrfs_write_out_cache(root, inode, ctl, block_group, trans,
+       ret = __btrfs_write_out_cache(root, inode, ctl, block_group,
+                                     &block_group->io_ctl, trans,
                                      path, block_group->key.objectid);
        if (ret) {
-               dcs = BTRFS_DC_ERROR;
-               ret = 0;
 #ifdef DEBUG
                btrfs_err(root->fs_info,
                        "failed to write free space cache for block group %llu",
                        block_group->key.objectid);
 #endif
+               spin_lock(&block_group->lock);
+               block_group->disk_cache_state = BTRFS_DC_ERROR;
+               spin_unlock(&block_group->lock);
+
+               block_group->io_ctl.inode = NULL;
+               iput(inode);
        }
 
-       spin_lock(&block_group->lock);
-       block_group->disk_cache_state = dcs;
-       spin_unlock(&block_group->lock);
-       iput(inode);
+       /*
+        * if ret == 0 the caller is expected to call btrfs_wait_cache_io
+        * to wait for IO and put the inode
+        */
+
        return ret;
 }
 
@@ -1298,11 +1423,11 @@ static inline u64 offset_to_bitmap(struct btrfs_free_space_ctl *ctl,
                                   u64 offset)
 {
        u64 bitmap_start;
-       u64 bytes_per_bitmap;
+       u32 bytes_per_bitmap;
 
        bytes_per_bitmap = BITS_PER_BITMAP * ctl->unit;
        bitmap_start = offset - ctl->start;
-       bitmap_start = div64_u64(bitmap_start, bytes_per_bitmap);
+       bitmap_start = div_u64(bitmap_start, bytes_per_bitmap);
        bitmap_start *= bytes_per_bitmap;
        bitmap_start += ctl->start;
 
@@ -1521,10 +1646,10 @@ static void recalculate_thresholds(struct btrfs_free_space_ctl *ctl)
        u64 bitmap_bytes;
        u64 extent_bytes;
        u64 size = block_group->key.offset;
-       u64 bytes_per_bg = BITS_PER_BITMAP * ctl->unit;
-       int max_bitmaps = div64_u64(size + bytes_per_bg - 1, bytes_per_bg);
+       u32 bytes_per_bg = BITS_PER_BITMAP * ctl->unit;
+       u32 max_bitmaps = div_u64(size + bytes_per_bg - 1, bytes_per_bg);
 
-       max_bitmaps = max(max_bitmaps, 1);
+       max_bitmaps = max_t(u32, max_bitmaps, 1);
 
        ASSERT(ctl->total_bitmaps <= max_bitmaps);
 
@@ -1537,7 +1662,7 @@ static void recalculate_thresholds(struct btrfs_free_space_ctl *ctl)
                max_bytes = MAX_CACHE_BYTES_PER_GIG;
        else
                max_bytes = MAX_CACHE_BYTES_PER_GIG *
-                       div64_u64(size, 1024 * 1024 * 1024);
+                       div_u64(size, 1024 * 1024 * 1024);
 
        /*
         * we want to account for 1 more bitmap than what we have so we can make
@@ -1552,14 +1677,14 @@ static void recalculate_thresholds(struct btrfs_free_space_ctl *ctl)
        }
 
        /*
-        * we want the extent entry threshold to always be at most 1/2 the maxw
+        * we want the extent entry threshold to always be at most 1/2 the max
         * bytes we can have, or whatever is less than that.
         */
        extent_bytes = max_bytes - bitmap_bytes;
-       extent_bytes = min_t(u64, extent_bytes, div64_u64(max_bytes, 2));
+       extent_bytes = min_t(u64, extent_bytes, max_bytes >> 1);
 
        ctl->extents_thresh =
-               div64_u64(extent_bytes, (sizeof(struct btrfs_free_space)));
+               div_u64(extent_bytes, sizeof(struct btrfs_free_space));
 }
 
 static inline void __bitmap_clear_bits(struct btrfs_free_space_ctl *ctl,
@@ -1673,7 +1798,7 @@ find_free_space(struct btrfs_free_space_ctl *ctl, u64 *offset, u64 *bytes,
                 */
                if (*bytes >= align) {
                        tmp = entry->offset - ctl->start + align - 1;
-                       do_div(tmp, align);
+                       tmp = div64_u64(tmp, align);
                        tmp = tmp * align + ctl->start;
                        align_off = tmp - entry->offset;
                } else {
@@ -2402,11 +2527,8 @@ static void __btrfs_remove_free_space_cache_locked(
                } else {
                        free_bitmap(ctl, info);
                }
-               if (need_resched()) {
-                       spin_unlock(&ctl->tree_lock);
-                       cond_resched();
-                       spin_lock(&ctl->tree_lock);
-               }
+
+               cond_resched_lock(&ctl->tree_lock);
        }
 }
 
@@ -2431,11 +2553,8 @@ void btrfs_remove_free_space_cache(struct btrfs_block_group_cache *block_group)
 
                WARN_ON(cluster->block_group != block_group);
                __btrfs_return_cluster_to_free_space(block_group, cluster);
-               if (need_resched()) {
-                       spin_unlock(&ctl->tree_lock);
-                       cond_resched();
-                       spin_lock(&ctl->tree_lock);
-               }
+
+               cond_resched_lock(&ctl->tree_lock);
        }
        __btrfs_remove_free_space_cache_locked(ctl);
        spin_unlock(&ctl->tree_lock);
@@ -3346,11 +3465,17 @@ int btrfs_write_out_ino_cache(struct btrfs_root *root,
 {
        struct btrfs_free_space_ctl *ctl = root->free_ino_ctl;
        int ret;
+       struct btrfs_io_ctl io_ctl;
 
        if (!btrfs_test_opt(root, INODE_MAP_CACHE))
                return 0;
 
-       ret = __btrfs_write_out_cache(root, inode, ctl, NULL, trans, path, 0);
+       memset(&io_ctl, 0, sizeof(io_ctl));
+       ret = __btrfs_write_out_cache(root, inode, ctl, NULL, &io_ctl,
+                                     trans, path, 0);
+       if (!ret)
+               ret = btrfs_wait_cache_io(root, trans, NULL, &io_ctl, path, 0);
+
        if (ret) {
                btrfs_delalloc_release_metadata(inode, inode->i_size);
 #ifdef DEBUG
index 88b2238a0aeda1cf4c91f7a0d32de09b19c2174c..a16a029ad3b128dcd7723e6d657f43a66a26ed34 100644 (file)
@@ -48,6 +48,8 @@ struct btrfs_free_space_op {
                           struct btrfs_free_space *info);
 };
 
+struct btrfs_io_ctl;
+
 struct inode *lookup_free_space_inode(struct btrfs_root *root,
                                      struct btrfs_block_group_cache
                                      *block_group, struct btrfs_path *path);
@@ -60,14 +62,19 @@ int btrfs_check_trunc_cache_free_space(struct btrfs_root *root,
                                       struct btrfs_block_rsv *rsv);
 int btrfs_truncate_free_space_cache(struct btrfs_root *root,
                                    struct btrfs_trans_handle *trans,
+                                   struct btrfs_block_group_cache *block_group,
                                    struct inode *inode);
 int load_free_space_cache(struct btrfs_fs_info *fs_info,
                          struct btrfs_block_group_cache *block_group);
+int btrfs_wait_cache_io(struct btrfs_root *root,
+                       struct btrfs_trans_handle *trans,
+                       struct btrfs_block_group_cache *block_group,
+                       struct btrfs_io_ctl *io_ctl,
+                       struct btrfs_path *path, u64 offset);
 int btrfs_write_out_cache(struct btrfs_root *root,
                          struct btrfs_trans_handle *trans,
                          struct btrfs_block_group_cache *block_group,
                          struct btrfs_path *path);
-
 struct inode *lookup_free_ino_inode(struct btrfs_root *root,
                                    struct btrfs_path *path);
 int create_free_ino_inode(struct btrfs_root *root,
index 74faea3a516ee710f7b099e4bc0e06eb2c3d001d..f6a596d5a6374f1dbf66279e24ef17aed9ff399d 100644 (file)
@@ -456,7 +456,7 @@ again:
        }
 
        if (i_size_read(inode) > 0) {
-               ret = btrfs_truncate_free_space_cache(root, trans, inode);
+               ret = btrfs_truncate_free_space_cache(root, trans, NULL, inode);
                if (ret) {
                        if (ret != -ENOSPC)
                                btrfs_abort_transaction(trans, root, ret);
index 43192e10cc4331f9f533c61f10f21c602bdee806..8bb013672aee061e81eb03fcba6d51db9cd169af 100644 (file)
@@ -59,6 +59,7 @@
 #include "backref.h"
 #include "hash.h"
 #include "props.h"
+#include "qgroup.h"
 
 struct btrfs_iget_args {
        struct btrfs_key *location;
@@ -470,7 +471,7 @@ again:
         */
        if (inode_need_compress(inode)) {
                WARN_ON(pages);
-               pages = kzalloc(sizeof(struct page *) * nr_pages, GFP_NOFS);
+               pages = kcalloc(nr_pages, sizeof(struct page *), GFP_NOFS);
                if (!pages) {
                        /* just bail out to the uncompressed code */
                        goto cont;
@@ -752,7 +753,6 @@ retry:
                        }
                        goto out_free;
                }
-
                /*
                 * here we're doing allocation and writeback of the
                 * compressed pages
@@ -3110,6 +3110,8 @@ void btrfs_run_delayed_iputs(struct btrfs_root *root)
        if (empty)
                return;
 
+       down_read(&fs_info->delayed_iput_sem);
+
        spin_lock(&fs_info->delayed_iput_lock);
        list_splice_init(&fs_info->delayed_iputs, &list);
        spin_unlock(&fs_info->delayed_iput_lock);
@@ -3120,6 +3122,8 @@ void btrfs_run_delayed_iputs(struct btrfs_root *root)
                iput(delayed->inode);
                kfree(delayed);
        }
+
+       up_read(&root->fs_info->delayed_iput_sem);
 }
 
 /*
@@ -3628,25 +3632,28 @@ static void btrfs_read_locked_inode(struct inode *inode)
        BTRFS_I(inode)->generation = btrfs_inode_generation(leaf, inode_item);
        BTRFS_I(inode)->last_trans = btrfs_inode_transid(leaf, inode_item);
 
+       inode->i_version = btrfs_inode_sequence(leaf, inode_item);
+       inode->i_generation = BTRFS_I(inode)->generation;
+       inode->i_rdev = 0;
+       rdev = btrfs_inode_rdev(leaf, inode_item);
+
+       BTRFS_I(inode)->index_cnt = (u64)-1;
+       BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item);
+
+cache_index:
        /*
         * If we were modified in the current generation and evicted from memory
         * and then re-read we need to do a full sync since we don't have any
         * idea about which extents were modified before we were evicted from
         * cache.
+        *
+        * This is required for both inode re-read from disk and delayed inode
+        * in delayed_nodes_tree.
         */
        if (BTRFS_I(inode)->last_trans == root->fs_info->generation)
                set_bit(BTRFS_INODE_NEEDS_FULL_SYNC,
                        &BTRFS_I(inode)->runtime_flags);
 
-       inode->i_version = btrfs_inode_sequence(leaf, inode_item);
-       inode->i_generation = BTRFS_I(inode)->generation;
-       inode->i_rdev = 0;
-       rdev = btrfs_inode_rdev(leaf, inode_item);
-
-       BTRFS_I(inode)->index_cnt = (u64)-1;
-       BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item);
-
-cache_index:
        path->slots[0]++;
        if (inode->i_nlink != 1 ||
            path->slots[0] >= btrfs_header_nritems(leaf))
@@ -4016,16 +4023,16 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry)
 {
        struct btrfs_root *root = BTRFS_I(dir)->root;
        struct btrfs_trans_handle *trans;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int ret;
 
        trans = __unlink_start_trans(dir);
        if (IS_ERR(trans))
                return PTR_ERR(trans);
 
-       btrfs_record_unlink_dir(trans, dir, dentry->d_inode, 0);
+       btrfs_record_unlink_dir(trans, dir, d_inode(dentry), 0);
 
-       ret = btrfs_unlink_inode(trans, root, dir, dentry->d_inode,
+       ret = btrfs_unlink_inode(trans, root, dir, d_inode(dentry),
                                 dentry->d_name.name, dentry->d_name.len);
        if (ret)
                goto out;
@@ -4124,7 +4131,7 @@ out:
 
 static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int err = 0;
        struct btrfs_root *root = BTRFS_I(dir)->root;
        struct btrfs_trans_handle *trans;
@@ -4151,7 +4158,7 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
                goto out;
 
        /* now the directory is empty */
-       err = btrfs_unlink_inode(trans, root, dir, dentry->d_inode,
+       err = btrfs_unlink_inode(trans, root, dir, d_inode(dentry),
                                 dentry->d_name.name, dentry->d_name.len);
        if (!err)
                btrfs_i_size_write(inode, 0);
@@ -4162,6 +4169,21 @@ out:
        return err;
 }
 
+static int truncate_space_check(struct btrfs_trans_handle *trans,
+                               struct btrfs_root *root,
+                               u64 bytes_deleted)
+{
+       int ret;
+
+       bytes_deleted = btrfs_csum_bytes_to_leaves(root, bytes_deleted);
+       ret = btrfs_block_rsv_add(root, &root->fs_info->trans_block_rsv,
+                                 bytes_deleted, BTRFS_RESERVE_NO_FLUSH);
+       if (!ret)
+               trans->bytes_reserved += bytes_deleted;
+       return ret;
+
+}
+
 /*
  * this can truncate away extent items, csum items and directory items.
  * It starts at a high offset and removes keys until it can't find
@@ -4197,9 +4219,21 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
        int ret;
        int err = 0;
        u64 ino = btrfs_ino(inode);
+       u64 bytes_deleted = 0;
+       bool be_nice = 0;
+       bool should_throttle = 0;
+       bool should_end = 0;
 
        BUG_ON(new_size > 0 && min_type != BTRFS_EXTENT_DATA_KEY);
 
+       /*
+        * for non-free space inodes and ref cows, we want to back off from
+        * time to time
+        */
+       if (!btrfs_is_free_space_inode(inode) &&
+           test_bit(BTRFS_ROOT_REF_COWS, &root->state))
+               be_nice = 1;
+
        path = btrfs_alloc_path();
        if (!path)
                return -ENOMEM;
@@ -4229,6 +4263,19 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
        key.type = (u8)-1;
 
 search_again:
+       /*
+        * with a 16K leaf size and 128MB extents, you can actually queue
+        * up a huge file in a single leaf.  Most of the time that
+        * bytes_deleted is > 0, it will be huge by the time we get here
+        */
+       if (be_nice && bytes_deleted > 32 * 1024 * 1024) {
+               if (btrfs_should_end_transaction(trans, root)) {
+                       err = -EAGAIN;
+                       goto error;
+               }
+       }
+
+
        path->leave_spinning = 1;
        ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
        if (ret < 0) {
@@ -4371,22 +4418,39 @@ delete:
                } else {
                        break;
                }
+               should_throttle = 0;
+
                if (found_extent &&
                    (test_bit(BTRFS_ROOT_REF_COWS, &root->state) ||
                     root == root->fs_info->tree_root)) {
                        btrfs_set_path_blocking(path);
+                       bytes_deleted += extent_num_bytes;
                        ret = btrfs_free_extent(trans, root, extent_start,
                                                extent_num_bytes, 0,
                                                btrfs_header_owner(leaf),
                                                ino, extent_offset, 0);
                        BUG_ON(ret);
+                       if (btrfs_should_throttle_delayed_refs(trans, root))
+                               btrfs_async_run_delayed_refs(root,
+                                       trans->delayed_ref_updates * 2, 0);
+                       if (be_nice) {
+                               if (truncate_space_check(trans, root,
+                                                        extent_num_bytes)) {
+                                       should_end = 1;
+                               }
+                               if (btrfs_should_throttle_delayed_refs(trans,
+                                                                      root)) {
+                                       should_throttle = 1;
+                               }
+                       }
                }
 
                if (found_type == BTRFS_INODE_ITEM_KEY)
                        break;
 
                if (path->slots[0] == 0 ||
-                   path->slots[0] != pending_del_slot) {
+                   path->slots[0] != pending_del_slot ||
+                   should_throttle || should_end) {
                        if (pending_del_nr) {
                                ret = btrfs_del_items(trans, root, path,
                                                pending_del_slot,
@@ -4399,6 +4463,23 @@ delete:
                                pending_del_nr = 0;
                        }
                        btrfs_release_path(path);
+                       if (should_throttle) {
+                               unsigned long updates = trans->delayed_ref_updates;
+                               if (updates) {
+                                       trans->delayed_ref_updates = 0;
+                                       ret = btrfs_run_delayed_refs(trans, root, updates * 2);
+                                       if (ret && !err)
+                                               err = ret;
+                               }
+                       }
+                       /*
+                        * if we failed to refill our space rsv, bail out
+                        * and let the transaction restart
+                        */
+                       if (should_end) {
+                               err = -EAGAIN;
+                               goto error;
+                       }
                        goto search_again;
                } else {
                        path->slots[0]--;
@@ -4415,7 +4496,18 @@ error:
        if (last_size != (u64)-1 &&
            root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID)
                btrfs_ordered_update_i_size(inode, last_size, NULL);
+
        btrfs_free_path(path);
+
+       if (be_nice && bytes_deleted > 32 * 1024 * 1024) {
+               unsigned long updates = trans->delayed_ref_updates;
+               if (updates) {
+                       trans->delayed_ref_updates = 0;
+                       ret = btrfs_run_delayed_refs(trans, root, updates * 2);
+                       if (ret && !err)
+                               err = ret;
+               }
+       }
        return err;
 }
 
@@ -4826,7 +4918,7 @@ static int btrfs_setsize(struct inode *inode, struct iattr *attr)
 
 static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct btrfs_root *root = BTRFS_I(inode)->root;
        int err;
 
@@ -4924,6 +5016,7 @@ void btrfs_evict_inode(struct inode *inode)
        struct btrfs_trans_handle *trans;
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct btrfs_block_rsv *rsv, *global_rsv;
+       int steal_from_global = 0;
        u64 min_size = btrfs_calc_trunc_metadata_size(root, 1);
        int ret;
 
@@ -4991,9 +5084,20 @@ void btrfs_evict_inode(struct inode *inode)
                 * hard as possible to get this to work.
                 */
                if (ret)
-                       ret = btrfs_block_rsv_migrate(global_rsv, rsv, min_size);
+                       steal_from_global++;
+               else
+                       steal_from_global = 0;
+               ret = 0;
 
-               if (ret) {
+               /*
+                * steal_from_global == 0: we reserved stuff, hooray!
+                * steal_from_global == 1: we didn't reserve stuff, boo!
+                * steal_from_global == 2: we've committed, still not a lot of
+                * room but maybe we'll have room in the global reserve this
+                * time.
+                * steal_from_global == 3: abandon all hope!
+                */
+               if (steal_from_global > 2) {
                        btrfs_warn(root->fs_info,
                                "Could not get space for a delete, will truncate on mount %d",
                                ret);
@@ -5009,10 +5113,40 @@ void btrfs_evict_inode(struct inode *inode)
                        goto no_delete;
                }
 
+               /*
+                * We can't just steal from the global reserve, we need tomake
+                * sure there is room to do it, if not we need to commit and try
+                * again.
+                */
+               if (steal_from_global) {
+                       if (!btrfs_check_space_for_delayed_refs(trans, root))
+                               ret = btrfs_block_rsv_migrate(global_rsv, rsv,
+                                                             min_size);
+                       else
+                               ret = -ENOSPC;
+               }
+
+               /*
+                * Couldn't steal from the global reserve, we have too much
+                * pending stuff built up, commit the transaction and try it
+                * again.
+                */
+               if (ret) {
+                       ret = btrfs_commit_transaction(trans, root);
+                       if (ret) {
+                               btrfs_orphan_del(NULL, inode);
+                               btrfs_free_block_rsv(root, rsv);
+                               goto no_delete;
+                       }
+                       continue;
+               } else {
+                       steal_from_global = 0;
+               }
+
                trans->block_rsv = rsv;
 
                ret = btrfs_truncate_inode_items(trans, root, inode, 0, 0);
-               if (ret != -ENOSPC)
+               if (ret != -ENOSPC && ret != -EAGAIN)
                        break;
 
                trans->block_rsv = &root->fs_info->trans_block_rsv;
@@ -5416,10 +5550,10 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)
 static int btrfs_dentry_delete(const struct dentry *dentry)
 {
        struct btrfs_root *root;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
 
        if (!inode && !IS_ROOT(dentry))
-               inode = dentry->d_parent->d_inode;
+               inode = d_inode(dentry->d_parent);
 
        if (inode) {
                root = BTRFS_I(inode)->root;
@@ -6226,7 +6360,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
 {
        struct btrfs_trans_handle *trans;
        struct btrfs_root *root = BTRFS_I(dir)->root;
-       struct inode *inode = old_dentry->d_inode;
+       struct inode *inode = d_inode(old_dentry);
        u64 index;
        int err;
        int drop_inode = 0;
@@ -8129,7 +8263,7 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
        if (check_direct_IO(BTRFS_I(inode)->root, iocb, iter, offset))
                return 0;
 
-       atomic_inc(&inode->i_dio_count);
+       inode_dio_begin(inode);
        smp_mb__after_atomic();
 
        /*
@@ -8169,7 +8303,7 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
                current->journal_info = &outstanding_extents;
        } else if (test_bit(BTRFS_INODE_READDIO_NEED_LOCK,
                                     &BTRFS_I(inode)->runtime_flags)) {
-               inode_dio_done(inode);
+               inode_dio_end(inode);
                flags = DIO_LOCKING | DIO_SKIP_HOLES;
                wakeup = false;
        }
@@ -8188,7 +8322,7 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
        }
 out:
        if (wakeup)
-               inode_dio_done(inode);
+               inode_dio_end(inode);
        if (relock)
                mutex_lock(&inode->i_mutex);
 
@@ -8581,7 +8715,7 @@ static int btrfs_truncate(struct inode *inode)
                ret = btrfs_truncate_inode_items(trans, root, inode,
                                                 inode->i_size,
                                                 BTRFS_EXTENT_DATA_KEY);
-               if (ret != -ENOSPC) {
+               if (ret != -ENOSPC && ret != -EAGAIN) {
                        err = ret;
                        break;
                }
@@ -8875,7 +9009,7 @@ static int btrfs_getattr(struct vfsmount *mnt,
                         struct dentry *dentry, struct kstat *stat)
 {
        u64 delalloc_bytes;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        u32 blocksize = inode->i_sb->s_blocksize;
 
        generic_fillattr(inode, stat);
@@ -8896,8 +9030,8 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        struct btrfs_trans_handle *trans;
        struct btrfs_root *root = BTRFS_I(old_dir)->root;
        struct btrfs_root *dest = BTRFS_I(new_dir)->root;
-       struct inode *new_inode = new_dentry->d_inode;
-       struct inode *old_inode = old_dentry->d_inode;
+       struct inode *new_inode = d_inode(new_dentry);
+       struct inode *old_inode = d_inode(old_dentry);
        struct timespec ctime = CURRENT_TIME;
        u64 index = 0;
        u64 root_objectid;
@@ -9009,7 +9143,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                                        old_dentry->d_name.len);
        } else {
                ret = __btrfs_unlink_inode(trans, root, old_dir,
-                                       old_dentry->d_inode,
+                                       d_inode(old_dentry),
                                        old_dentry->d_name.name,
                                        old_dentry->d_name.len);
                if (!ret)
@@ -9033,12 +9167,12 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                        BUG_ON(new_inode->i_nlink == 0);
                } else {
                        ret = btrfs_unlink_inode(trans, dest, new_dir,
-                                                new_dentry->d_inode,
+                                                d_inode(new_dentry),
                                                 new_dentry->d_name.name,
                                                 new_dentry->d_name.len);
                }
                if (!ret && new_inode->i_nlink == 0)
-                       ret = btrfs_orphan_add(trans, new_dentry->d_inode);
+                       ret = btrfs_orphan_add(trans, d_inode(new_dentry));
                if (ret) {
                        btrfs_abort_transaction(trans, root, ret);
                        goto out_fail;
@@ -9451,6 +9585,7 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode,
                                btrfs_end_transaction(trans, root);
                        break;
                }
+
                btrfs_drop_extent_cache(inode, cur_offset,
                                        cur_offset + ins.offset -1, 0);
 
index 74609b931ba5564da01de0955b8aa1d3142512d7..1c22c65185045c61b170db3f1db8f2c3627bbd84 100644 (file)
@@ -456,6 +456,13 @@ static noinline int create_subvol(struct inode *dir,
        if (ret)
                return ret;
 
+       /*
+        * Don't create subvolume whose level is not zero. Or qgroup will be
+        * screwed up since it assume subvolme qgroup's level to be 0.
+        */
+       if (btrfs_qgroup_level(objectid))
+               return -ENOSPC;
+
        btrfs_init_block_rsv(&block_rsv, BTRFS_BLOCK_RSV_TEMP);
        /*
         * The same as the snapshot creation, please see the comment
@@ -717,7 +724,7 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
        if (ret)
                goto fail;
 
-       inode = btrfs_lookup_dentry(dentry->d_parent->d_inode, dentry);
+       inode = btrfs_lookup_dentry(d_inode(dentry->d_parent), dentry);
        if (IS_ERR(inode)) {
                ret = PTR_ERR(inode);
                goto fail;
@@ -761,10 +768,10 @@ static int btrfs_may_delete(struct inode *dir, struct dentry *victim, int isdir)
 {
        int error;
 
-       if (!victim->d_inode)
+       if (d_really_is_negative(victim))
                return -ENOENT;
 
-       BUG_ON(victim->d_parent->d_inode != dir);
+       BUG_ON(d_inode(victim->d_parent) != dir);
        audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE);
 
        error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
@@ -772,8 +779,8 @@ static int btrfs_may_delete(struct inode *dir, struct dentry *victim, int isdir)
                return error;
        if (IS_APPEND(dir))
                return -EPERM;
-       if (check_sticky(dir, victim->d_inode) || IS_APPEND(victim->d_inode) ||
-           IS_IMMUTABLE(victim->d_inode) || IS_SWAPFILE(victim->d_inode))
+       if (check_sticky(dir, d_inode(victim)) || IS_APPEND(d_inode(victim)) ||
+           IS_IMMUTABLE(d_inode(victim)) || IS_SWAPFILE(d_inode(victim)))
                return -EPERM;
        if (isdir) {
                if (!d_is_dir(victim))
@@ -792,7 +799,7 @@ static int btrfs_may_delete(struct inode *dir, struct dentry *victim, int isdir)
 /* copy of may_create in fs/namei.c() */
 static inline int btrfs_may_create(struct inode *dir, struct dentry *child)
 {
-       if (child->d_inode)
+       if (d_really_is_positive(child))
                return -EEXIST;
        if (IS_DEADDIR(dir))
                return -ENOENT;
@@ -810,7 +817,7 @@ static noinline int btrfs_mksubvol(struct path *parent,
                                   u64 *async_transid, bool readonly,
                                   struct btrfs_qgroup_inherit *inherit)
 {
-       struct inode *dir  = parent->dentry->d_inode;
+       struct inode *dir  = d_inode(parent->dentry);
        struct dentry *dentry;
        int error;
 
@@ -824,7 +831,7 @@ static noinline int btrfs_mksubvol(struct path *parent,
                goto out_unlock;
 
        error = -EEXIST;
-       if (dentry->d_inode)
+       if (d_really_is_positive(dentry))
                goto out_dput;
 
        error = btrfs_may_create(dir, dentry);
@@ -1564,7 +1571,7 @@ static noinline int btrfs_ioctl_resize(struct file *file,
                goto out_free;
        }
 
-       do_div(new_size, root->sectorsize);
+       new_size = div_u64(new_size, root->sectorsize);
        new_size *= root->sectorsize;
 
        printk_in_rcu(KERN_INFO "BTRFS: new size for %s is %llu\n",
@@ -2294,7 +2301,7 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
 {
        struct dentry *parent = file->f_path.dentry;
        struct dentry *dentry;
-       struct inode *dir = parent->d_inode;
+       struct inode *dir = d_inode(parent);
        struct inode *inode;
        struct btrfs_root *root = BTRFS_I(dir)->root;
        struct btrfs_root *dest = NULL;
@@ -2333,12 +2340,12 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
                goto out_unlock_dir;
        }
 
-       if (!dentry->d_inode) {
+       if (d_really_is_negative(dentry)) {
                err = -ENOENT;
                goto out_dput;
        }
 
-       inode = dentry->d_inode;
+       inode = d_inode(dentry);
        dest = BTRFS_I(inode)->root;
        if (!capable(CAP_SYS_ADMIN)) {
                /*
@@ -2403,7 +2410,7 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
                        "Attempt to delete subvolume %llu during send",
                        dest->root_key.objectid);
                err = -EPERM;
-               goto out_dput;
+               goto out_unlock_inode;
        }
 
        d_invalidate(dentry);
@@ -2498,6 +2505,7 @@ out_up_write:
                                root_flags & ~BTRFS_ROOT_SUBVOL_DEAD);
                spin_unlock(&dest->root_item_lock);
        }
+out_unlock_inode:
        mutex_unlock(&inode->i_mutex);
        if (!err) {
                shrink_dcache_sb(root->fs_info->sb);
@@ -2897,6 +2905,9 @@ static int btrfs_extent_same(struct inode *src, u64 loff, u64 len,
        if (src == dst)
                return -EINVAL;
 
+       if (len == 0)
+               return 0;
+
        btrfs_double_lock(src, loff, dst, dst_loff, len);
 
        ret = extent_same_check_offsets(src, loff, len);
@@ -3039,7 +3050,7 @@ out:
 static int check_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
                     u64 disko)
 {
-       struct seq_list tree_mod_seq_elem = {};
+       struct seq_list tree_mod_seq_elem = SEQ_LIST_INIT(tree_mod_seq_elem);
        struct ulist *roots;
        struct ulist_iterator uiter;
        struct ulist_node *root_node = NULL;
@@ -3202,6 +3213,8 @@ static int btrfs_clone(struct inode *src, struct inode *inode,
        key.offset = off;
 
        while (1) {
+               u64 next_key_min_offset = key.offset + 1;
+
                /*
                 * note the key will change type as we walk through the
                 * tree.
@@ -3282,7 +3295,7 @@ process_slot:
                        } else if (key.offset >= off + len) {
                                break;
                        }
-
+                       next_key_min_offset = key.offset + datal;
                        size = btrfs_item_size_nr(leaf, slot);
                        read_extent_buffer(leaf, buf,
                                           btrfs_item_ptr_offset(leaf, slot),
@@ -3497,7 +3510,7 @@ process_slot:
                                break;
                }
                btrfs_release_path(path);
-               key.offset++;
+               key.offset = next_key_min_offset;
        }
        ret = 0;
 
@@ -3626,6 +3639,11 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
        if (off + len == src->i_size)
                len = ALIGN(src->i_size, bs) - off;
 
+       if (len == 0) {
+               ret = 0;
+               goto out_unlock;
+       }
+
        /* verify the end result is block aligned */
        if (!IS_ALIGNED(off, bs) || !IS_ALIGNED(off + len, bs) ||
            !IS_ALIGNED(destoff, bs))
@@ -4624,6 +4642,11 @@ static long btrfs_ioctl_qgroup_assign(struct file *file, void __user *arg)
                                                sa->src, sa->dst);
        }
 
+       /* update qgroup status and info */
+       err = btrfs_run_qgroups(trans, root->fs_info);
+       if (err < 0)
+               btrfs_error(root->fs_info, ret,
+                           "failed to update qgroup status and info\n");
        err = btrfs_end_transaction(trans, root);
        if (err && !ret)
                ret = err;
@@ -4669,8 +4692,7 @@ static long btrfs_ioctl_qgroup_create(struct file *file, void __user *arg)
 
        /* FIXME: check if the IDs really exist */
        if (sa->create) {
-               ret = btrfs_create_qgroup(trans, root->fs_info, sa->qgroupid,
-                                         NULL);
+               ret = btrfs_create_qgroup(trans, root->fs_info, sa->qgroupid);
        } else {
                ret = btrfs_remove_qgroup(trans, root->fs_info, sa->qgroupid);
        }
index 617553cdb7d3b36b1b8ca6a87b28526c5a060b4d..a2f0513477313fb6edbc4f898df70262eda96aef 100644 (file)
@@ -434,7 +434,7 @@ out:
        return ret;
 }
 
-struct btrfs_compress_op btrfs_lzo_compress = {
+const struct btrfs_compress_op btrfs_lzo_compress = {
        .alloc_workspace        = lzo_alloc_workspace,
        .free_workspace         = lzo_free_workspace,
        .compress_pages         = lzo_compress_pages,
index b7816cefbd1312247104821e3e2932569dea66a3..1b10a3cd1195eae7401eb46ba4c9d9bb9b5bb4de 100644 (file)
@@ -28,8 +28,7 @@ static inline u64 div_factor(u64 num, int factor)
        if (factor == 10)
                return num;
        num *= factor;
-       do_div(num, 10);
-       return num;
+       return div_u64(num, 10);
 }
 
 static inline u64 div_factor_fine(u64 num, int factor)
@@ -37,8 +36,7 @@ static inline u64 div_factor_fine(u64 num, int factor)
        if (factor == 100)
                return num;
        num *= factor;
-       do_div(num, 100);
-       return num;
+       return div_u64(num, 100);
 }
 
 #endif
index 129b1dd28527135f2d3e33f0f3441d246f4b9235..dca137b04095fc509390b2c02d4ca6ad1752ee74 100644 (file)
@@ -425,3 +425,5 @@ static const char *prop_compression_extract(struct inode *inode)
 
        return NULL;
 }
+
+
index 058c79eecbfb96825918a370e3f78d926b49b098..3d6546581bb9fd4f778f2c7536c54f7367717f53 100644 (file)
@@ -644,9 +644,8 @@ out:
 }
 
 static int update_qgroup_limit_item(struct btrfs_trans_handle *trans,
-                                   struct btrfs_root *root, u64 qgroupid,
-                                   u64 flags, u64 max_rfer, u64 max_excl,
-                                   u64 rsv_rfer, u64 rsv_excl)
+                                   struct btrfs_root *root,
+                                   struct btrfs_qgroup *qgroup)
 {
        struct btrfs_path *path;
        struct btrfs_key key;
@@ -657,7 +656,7 @@ static int update_qgroup_limit_item(struct btrfs_trans_handle *trans,
 
        key.objectid = 0;
        key.type = BTRFS_QGROUP_LIMIT_KEY;
-       key.offset = qgroupid;
+       key.offset = qgroup->qgroupid;
 
        path = btrfs_alloc_path();
        if (!path)
@@ -673,11 +672,11 @@ static int update_qgroup_limit_item(struct btrfs_trans_handle *trans,
        l = path->nodes[0];
        slot = path->slots[0];
        qgroup_limit = btrfs_item_ptr(l, slot, struct btrfs_qgroup_limit_item);
-       btrfs_set_qgroup_limit_flags(l, qgroup_limit, flags);
-       btrfs_set_qgroup_limit_max_rfer(l, qgroup_limit, max_rfer);
-       btrfs_set_qgroup_limit_max_excl(l, qgroup_limit, max_excl);
-       btrfs_set_qgroup_limit_rsv_rfer(l, qgroup_limit, rsv_rfer);
-       btrfs_set_qgroup_limit_rsv_excl(l, qgroup_limit, rsv_excl);
+       btrfs_set_qgroup_limit_flags(l, qgroup_limit, qgroup->lim_flags);
+       btrfs_set_qgroup_limit_max_rfer(l, qgroup_limit, qgroup->max_rfer);
+       btrfs_set_qgroup_limit_max_excl(l, qgroup_limit, qgroup->max_excl);
+       btrfs_set_qgroup_limit_rsv_rfer(l, qgroup_limit, qgroup->rsv_rfer);
+       btrfs_set_qgroup_limit_rsv_excl(l, qgroup_limit, qgroup->rsv_excl);
 
        btrfs_mark_buffer_dirty(l);
 
@@ -967,6 +966,7 @@ int btrfs_quota_disable(struct btrfs_trans_handle *trans,
        fs_info->pending_quota_state = 0;
        quota_root = fs_info->quota_root;
        fs_info->quota_root = NULL;
+       fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_ON;
        spin_unlock(&fs_info->qgroup_lock);
 
        btrfs_free_qgroup_config(fs_info);
@@ -982,7 +982,7 @@ int btrfs_quota_disable(struct btrfs_trans_handle *trans,
        list_del(&quota_root->dirty_list);
 
        btrfs_tree_lock(quota_root->node);
-       clean_tree_block(trans, tree_root, quota_root->node);
+       clean_tree_block(trans, tree_root->fs_info, quota_root->node);
        btrfs_tree_unlock(quota_root->node);
        btrfs_free_tree_block(trans, quota_root, quota_root->node, 0, 1);
 
@@ -1001,6 +1001,110 @@ static void qgroup_dirty(struct btrfs_fs_info *fs_info,
                list_add(&qgroup->dirty, &fs_info->dirty_qgroups);
 }
 
+/*
+ * The easy accounting, if we are adding/removing the only ref for an extent
+ * then this qgroup and all of the parent qgroups get their refrence and
+ * exclusive counts adjusted.
+ *
+ * Caller should hold fs_info->qgroup_lock.
+ */
+static int __qgroup_excl_accounting(struct btrfs_fs_info *fs_info,
+                                   struct ulist *tmp, u64 ref_root,
+                                   u64 num_bytes, int sign)
+{
+       struct btrfs_qgroup *qgroup;
+       struct btrfs_qgroup_list *glist;
+       struct ulist_node *unode;
+       struct ulist_iterator uiter;
+       int ret = 0;
+
+       qgroup = find_qgroup_rb(fs_info, ref_root);
+       if (!qgroup)
+               goto out;
+
+       qgroup->rfer += sign * num_bytes;
+       qgroup->rfer_cmpr += sign * num_bytes;
+
+       WARN_ON(sign < 0 && qgroup->excl < num_bytes);
+       qgroup->excl += sign * num_bytes;
+       qgroup->excl_cmpr += sign * num_bytes;
+       if (sign > 0)
+               qgroup->reserved -= num_bytes;
+
+       qgroup_dirty(fs_info, qgroup);
+
+       /* Get all of the parent groups that contain this qgroup */
+       list_for_each_entry(glist, &qgroup->groups, next_group) {
+               ret = ulist_add(tmp, glist->group->qgroupid,
+                               ptr_to_u64(glist->group), GFP_ATOMIC);
+               if (ret < 0)
+                       goto out;
+       }
+
+       /* Iterate all of the parents and adjust their reference counts */
+       ULIST_ITER_INIT(&uiter);
+       while ((unode = ulist_next(tmp, &uiter))) {
+               qgroup = u64_to_ptr(unode->aux);
+               qgroup->rfer += sign * num_bytes;
+               qgroup->rfer_cmpr += sign * num_bytes;
+               WARN_ON(sign < 0 && qgroup->excl < num_bytes);
+               qgroup->excl += sign * num_bytes;
+               if (sign > 0)
+                       qgroup->reserved -= num_bytes;
+               qgroup->excl_cmpr += sign * num_bytes;
+               qgroup_dirty(fs_info, qgroup);
+
+               /* Add any parents of the parents */
+               list_for_each_entry(glist, &qgroup->groups, next_group) {
+                       ret = ulist_add(tmp, glist->group->qgroupid,
+                                       ptr_to_u64(glist->group), GFP_ATOMIC);
+                       if (ret < 0)
+                               goto out;
+               }
+       }
+       ret = 0;
+out:
+       return ret;
+}
+
+
+/*
+ * Quick path for updating qgroup with only excl refs.
+ *
+ * In that case, just update all parent will be enough.
+ * Or we needs to do a full rescan.
+ * Caller should also hold fs_info->qgroup_lock.
+ *
+ * Return 0 for quick update, return >0 for need to full rescan
+ * and mark INCONSISTENT flag.
+ * Return < 0 for other error.
+ */
+static int quick_update_accounting(struct btrfs_fs_info *fs_info,
+                                  struct ulist *tmp, u64 src, u64 dst,
+                                  int sign)
+{
+       struct btrfs_qgroup *qgroup;
+       int ret = 1;
+       int err = 0;
+
+       qgroup = find_qgroup_rb(fs_info, src);
+       if (!qgroup)
+               goto out;
+       if (qgroup->excl == qgroup->rfer) {
+               ret = 0;
+               err = __qgroup_excl_accounting(fs_info, tmp, dst,
+                                              qgroup->excl, sign);
+               if (err < 0) {
+                       ret = err;
+                       goto out;
+               }
+       }
+out:
+       if (ret)
+               fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
+       return ret;
+}
+
 int btrfs_add_qgroup_relation(struct btrfs_trans_handle *trans,
                              struct btrfs_fs_info *fs_info, u64 src, u64 dst)
 {
@@ -1008,8 +1112,17 @@ int btrfs_add_qgroup_relation(struct btrfs_trans_handle *trans,
        struct btrfs_qgroup *parent;
        struct btrfs_qgroup *member;
        struct btrfs_qgroup_list *list;
+       struct ulist *tmp;
        int ret = 0;
 
+       tmp = ulist_alloc(GFP_NOFS);
+       if (!tmp)
+               return -ENOMEM;
+
+       /* Check the level of src and dst first */
+       if (btrfs_qgroup_level(src) >= btrfs_qgroup_level(dst))
+               return -EINVAL;
+
        mutex_lock(&fs_info->qgroup_ioctl_lock);
        quota_root = fs_info->quota_root;
        if (!quota_root) {
@@ -1043,23 +1156,33 @@ int btrfs_add_qgroup_relation(struct btrfs_trans_handle *trans,
 
        spin_lock(&fs_info->qgroup_lock);
        ret = add_relation_rb(quota_root->fs_info, src, dst);
+       if (ret < 0) {
+               spin_unlock(&fs_info->qgroup_lock);
+               goto out;
+       }
+       ret = quick_update_accounting(fs_info, tmp, src, dst, 1);
        spin_unlock(&fs_info->qgroup_lock);
 out:
        mutex_unlock(&fs_info->qgroup_ioctl_lock);
+       ulist_free(tmp);
        return ret;
 }
 
-int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans,
+int __del_qgroup_relation(struct btrfs_trans_handle *trans,
                              struct btrfs_fs_info *fs_info, u64 src, u64 dst)
 {
        struct btrfs_root *quota_root;
        struct btrfs_qgroup *parent;
        struct btrfs_qgroup *member;
        struct btrfs_qgroup_list *list;
+       struct ulist *tmp;
        int ret = 0;
        int err;
 
-       mutex_lock(&fs_info->qgroup_ioctl_lock);
+       tmp = ulist_alloc(GFP_NOFS);
+       if (!tmp)
+               return -ENOMEM;
+
        quota_root = fs_info->quota_root;
        if (!quota_root) {
                ret = -EINVAL;
@@ -1088,14 +1211,27 @@ exist:
 
        spin_lock(&fs_info->qgroup_lock);
        del_relation_rb(fs_info, src, dst);
+       ret = quick_update_accounting(fs_info, tmp, src, dst, -1);
        spin_unlock(&fs_info->qgroup_lock);
 out:
+       ulist_free(tmp);
+       return ret;
+}
+
+int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans,
+                             struct btrfs_fs_info *fs_info, u64 src, u64 dst)
+{
+       int ret = 0;
+
+       mutex_lock(&fs_info->qgroup_ioctl_lock);
+       ret = __del_qgroup_relation(trans, fs_info, src, dst);
        mutex_unlock(&fs_info->qgroup_ioctl_lock);
+
        return ret;
 }
 
 int btrfs_create_qgroup(struct btrfs_trans_handle *trans,
-                       struct btrfs_fs_info *fs_info, u64 qgroupid, char *name)
+                       struct btrfs_fs_info *fs_info, u64 qgroupid)
 {
        struct btrfs_root *quota_root;
        struct btrfs_qgroup *qgroup;
@@ -1133,6 +1269,7 @@ int btrfs_remove_qgroup(struct btrfs_trans_handle *trans,
 {
        struct btrfs_root *quota_root;
        struct btrfs_qgroup *qgroup;
+       struct btrfs_qgroup_list *list;
        int ret = 0;
 
        mutex_lock(&fs_info->qgroup_ioctl_lock);
@@ -1147,15 +1284,24 @@ int btrfs_remove_qgroup(struct btrfs_trans_handle *trans,
                ret = -ENOENT;
                goto out;
        } else {
-               /* check if there are no relations to this qgroup */
-               if (!list_empty(&qgroup->groups) ||
-                   !list_empty(&qgroup->members)) {
+               /* check if there are no children of this qgroup */
+               if (!list_empty(&qgroup->members)) {
                        ret = -EBUSY;
                        goto out;
                }
        }
        ret = del_qgroup_item(trans, quota_root, qgroupid);
 
+       while (!list_empty(&qgroup->groups)) {
+               list = list_first_entry(&qgroup->groups,
+                                       struct btrfs_qgroup_list, next_group);
+               ret = __del_qgroup_relation(trans, fs_info,
+                                          qgroupid,
+                                          list->group->qgroupid);
+               if (ret)
+                       goto out;
+       }
+
        spin_lock(&fs_info->qgroup_lock);
        del_qgroup_rb(quota_root->fs_info, qgroupid);
        spin_unlock(&fs_info->qgroup_lock);
@@ -1184,23 +1330,27 @@ int btrfs_limit_qgroup(struct btrfs_trans_handle *trans,
                ret = -ENOENT;
                goto out;
        }
-       ret = update_qgroup_limit_item(trans, quota_root, qgroupid,
-                                      limit->flags, limit->max_rfer,
-                                      limit->max_excl, limit->rsv_rfer,
-                                      limit->rsv_excl);
+
+       spin_lock(&fs_info->qgroup_lock);
+       if (limit->flags & BTRFS_QGROUP_LIMIT_MAX_RFER)
+               qgroup->max_rfer = limit->max_rfer;
+       if (limit->flags & BTRFS_QGROUP_LIMIT_MAX_EXCL)
+               qgroup->max_excl = limit->max_excl;
+       if (limit->flags & BTRFS_QGROUP_LIMIT_RSV_RFER)
+               qgroup->rsv_rfer = limit->rsv_rfer;
+       if (limit->flags & BTRFS_QGROUP_LIMIT_RSV_EXCL)
+               qgroup->rsv_excl = limit->rsv_excl;
+       qgroup->lim_flags |= limit->flags;
+
+       spin_unlock(&fs_info->qgroup_lock);
+
+       ret = update_qgroup_limit_item(trans, quota_root, qgroup);
        if (ret) {
                fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
                btrfs_info(fs_info, "unable to update quota limit for %llu",
                       qgroupid);
        }
 
-       spin_lock(&fs_info->qgroup_lock);
-       qgroup->lim_flags = limit->flags;
-       qgroup->max_rfer = limit->max_rfer;
-       qgroup->max_excl = limit->max_excl;
-       qgroup->rsv_rfer = limit->rsv_rfer;
-       qgroup->rsv_excl = limit->rsv_excl;
-       spin_unlock(&fs_info->qgroup_lock);
 out:
        mutex_unlock(&fs_info->qgroup_ioctl_lock);
        return ret;
@@ -1256,14 +1406,14 @@ static int comp_oper(struct btrfs_qgroup_operation *oper1,
                return -1;
        if (oper1->bytenr > oper2->bytenr)
                return 1;
-       if (oper1->seq < oper2->seq)
-               return -1;
-       if (oper1->seq > oper2->seq)
-               return 1;
        if (oper1->ref_root < oper2->ref_root)
                return -1;
        if (oper1->ref_root > oper2->ref_root)
                return 1;
+       if (oper1->seq < oper2->seq)
+               return -1;
+       if (oper1->seq > oper2->seq)
+               return 1;
        if (oper1->type < oper2->type)
                return -1;
        if (oper1->type > oper2->type)
@@ -1372,19 +1522,10 @@ int btrfs_qgroup_record_ref(struct btrfs_trans_handle *trans,
        return 0;
 }
 
-/*
- * The easy accounting, if we are adding/removing the only ref for an extent
- * then this qgroup and all of the parent qgroups get their refrence and
- * exclusive counts adjusted.
- */
 static int qgroup_excl_accounting(struct btrfs_fs_info *fs_info,
                                  struct btrfs_qgroup_operation *oper)
 {
-       struct btrfs_qgroup *qgroup;
        struct ulist *tmp;
-       struct btrfs_qgroup_list *glist;
-       struct ulist_node *unode;
-       struct ulist_iterator uiter;
        int sign = 0;
        int ret = 0;
 
@@ -1395,9 +1536,7 @@ static int qgroup_excl_accounting(struct btrfs_fs_info *fs_info,
        spin_lock(&fs_info->qgroup_lock);
        if (!fs_info->quota_root)
                goto out;
-       qgroup = find_qgroup_rb(fs_info, oper->ref_root);
-       if (!qgroup)
-               goto out;
+
        switch (oper->type) {
        case BTRFS_QGROUP_OPER_ADD_EXCL:
                sign = 1;
@@ -1408,43 +1547,8 @@ static int qgroup_excl_accounting(struct btrfs_fs_info *fs_info,
        default:
                ASSERT(0);
        }
-       qgroup->rfer += sign * oper->num_bytes;
-       qgroup->rfer_cmpr += sign * oper->num_bytes;
-
-       WARN_ON(sign < 0 && qgroup->excl < oper->num_bytes);
-       qgroup->excl += sign * oper->num_bytes;
-       qgroup->excl_cmpr += sign * oper->num_bytes;
-
-       qgroup_dirty(fs_info, qgroup);
-
-       /* Get all of the parent groups that contain this qgroup */
-       list_for_each_entry(glist, &qgroup->groups, next_group) {
-               ret = ulist_add(tmp, glist->group->qgroupid,
-                               ptr_to_u64(glist->group), GFP_ATOMIC);
-               if (ret < 0)
-                       goto out;
-       }
-
-       /* Iterate all of the parents and adjust their reference counts */
-       ULIST_ITER_INIT(&uiter);
-       while ((unode = ulist_next(tmp, &uiter))) {
-               qgroup = u64_to_ptr(unode->aux);
-               qgroup->rfer += sign * oper->num_bytes;
-               qgroup->rfer_cmpr += sign * oper->num_bytes;
-               WARN_ON(sign < 0 && qgroup->excl < oper->num_bytes);
-               qgroup->excl += sign * oper->num_bytes;
-               qgroup->excl_cmpr += sign * oper->num_bytes;
-               qgroup_dirty(fs_info, qgroup);
-
-               /* Add any parents of the parents */
-               list_for_each_entry(glist, &qgroup->groups, next_group) {
-                       ret = ulist_add(tmp, glist->group->qgroupid,
-                                       ptr_to_u64(glist->group), GFP_ATOMIC);
-                       if (ret < 0)
-                               goto out;
-               }
-       }
-       ret = 0;
+       ret = __qgroup_excl_accounting(fs_info, tmp, oper->ref_root,
+                                      oper->num_bytes, sign);
 out:
        spin_unlock(&fs_info->qgroup_lock);
        ulist_free(tmp);
@@ -1845,7 +1949,7 @@ static int qgroup_shared_accounting(struct btrfs_trans_handle *trans,
        struct ulist *roots = NULL;
        struct ulist *qgroups, *tmp;
        struct btrfs_qgroup *qgroup;
-       struct seq_list elem = {};
+       struct seq_list elem = SEQ_LIST_INIT(elem);
        u64 seq;
        int old_roots = 0;
        int new_roots = 0;
@@ -1967,7 +2071,7 @@ static int qgroup_subtree_accounting(struct btrfs_trans_handle *trans,
        int err;
        struct btrfs_qgroup *qg;
        u64 root_obj = 0;
-       struct seq_list elem = {};
+       struct seq_list elem = SEQ_LIST_INIT(elem);
 
        parents = ulist_alloc(GFP_NOFS);
        if (!parents)
@@ -2153,6 +2257,10 @@ int btrfs_run_qgroups(struct btrfs_trans_handle *trans,
                list_del_init(&qgroup->dirty);
                spin_unlock(&fs_info->qgroup_lock);
                ret = update_qgroup_info_item(trans, quota_root, qgroup);
+               if (ret)
+                       fs_info->qgroup_flags |=
+                                       BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
+               ret = update_qgroup_limit_item(trans, quota_root, qgroup);
                if (ret)
                        fs_info->qgroup_flags |=
                                        BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
@@ -2219,6 +2327,11 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans,
                                ret = -EINVAL;
                                goto out;
                        }
+
+                       if ((srcgroup->qgroupid >> 48) <= (objectid >> 48)) {
+                               ret = -EINVAL;
+                               goto out;
+                       }
                        ++i_qgroups;
                }
        }
@@ -2230,17 +2343,6 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans,
        if (ret)
                goto out;
 
-       if (inherit && inherit->flags & BTRFS_QGROUP_INHERIT_SET_LIMITS) {
-               ret = update_qgroup_limit_item(trans, quota_root, objectid,
-                                              inherit->lim.flags,
-                                              inherit->lim.max_rfer,
-                                              inherit->lim.max_excl,
-                                              inherit->lim.rsv_rfer,
-                                              inherit->lim.rsv_excl);
-               if (ret)
-                       goto out;
-       }
-
        if (srcid) {
                struct btrfs_root *srcroot;
                struct btrfs_key srckey;
@@ -2286,6 +2388,22 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans,
                goto unlock;
        }
 
+       if (inherit && inherit->flags & BTRFS_QGROUP_INHERIT_SET_LIMITS) {
+               dstgroup->lim_flags = inherit->lim.flags;
+               dstgroup->max_rfer = inherit->lim.max_rfer;
+               dstgroup->max_excl = inherit->lim.max_excl;
+               dstgroup->rsv_rfer = inherit->lim.rsv_rfer;
+               dstgroup->rsv_excl = inherit->lim.rsv_excl;
+
+               ret = update_qgroup_limit_item(trans, quota_root, dstgroup);
+               if (ret) {
+                       fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
+                       btrfs_info(fs_info, "unable to update quota limit for %llu",
+                              dstgroup->qgroupid);
+                       goto unlock;
+               }
+       }
+
        if (srcid) {
                srcgroup = find_qgroup_rb(fs_info, srcid);
                if (!srcgroup)
@@ -2302,6 +2420,14 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans,
                dstgroup->excl_cmpr = level_size;
                srcgroup->excl = level_size;
                srcgroup->excl_cmpr = level_size;
+
+               /* inherit the limit info */
+               dstgroup->lim_flags = srcgroup->lim_flags;
+               dstgroup->max_rfer = srcgroup->max_rfer;
+               dstgroup->max_excl = srcgroup->max_excl;
+               dstgroup->rsv_rfer = srcgroup->rsv_rfer;
+               dstgroup->rsv_excl = srcgroup->rsv_excl;
+
                qgroup_dirty(fs_info, dstgroup);
                qgroup_dirty(fs_info, srcgroup);
        }
@@ -2358,12 +2484,6 @@ out:
        return ret;
 }
 
-/*
- * reserve some space for a qgroup and all its parents. The reservation takes
- * place with start_transaction or dealloc_reserve, similar to ENOSPC
- * accounting. If not enough space is available, EDQUOT is returned.
- * We assume that the requested space is new for all qgroups.
- */
 int btrfs_qgroup_reserve(struct btrfs_root *root, u64 num_bytes)
 {
        struct btrfs_root *quota_root;
@@ -2513,7 +2633,7 @@ void assert_qgroups_uptodate(struct btrfs_trans_handle *trans)
 
 /*
  * returns < 0 on error, 0 when more leafs are to be scanned.
- * returns 1 when done, 2 when done and FLAG_INCONSISTENT was cleared.
+ * returns 1 when done.
  */
 static int
 qgroup_rescan_leaf(struct btrfs_fs_info *fs_info, struct btrfs_path *path,
@@ -2522,7 +2642,7 @@ qgroup_rescan_leaf(struct btrfs_fs_info *fs_info, struct btrfs_path *path,
 {
        struct btrfs_key found;
        struct ulist *roots = NULL;
-       struct seq_list tree_mod_seq_elem = {};
+       struct seq_list tree_mod_seq_elem = SEQ_LIST_INIT(tree_mod_seq_elem);
        u64 num_bytes;
        u64 seq;
        int new_roots;
@@ -2618,6 +2738,7 @@ static void btrfs_qgroup_rescan_worker(struct btrfs_work *work)
        struct ulist *tmp = NULL, *qgroups = NULL;
        struct extent_buffer *scratch_leaf = NULL;
        int err = -ENOMEM;
+       int ret = 0;
 
        path = btrfs_alloc_path();
        if (!path)
@@ -2660,7 +2781,7 @@ out:
        mutex_lock(&fs_info->qgroup_rescan_lock);
        fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_RESCAN;
 
-       if (err == 2 &&
+       if (err > 0 &&
            fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT) {
                fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
        } else if (err < 0) {
@@ -2668,13 +2789,33 @@ out:
        }
        mutex_unlock(&fs_info->qgroup_rescan_lock);
 
+       /*
+        * only update status, since the previous part has alreay updated the
+        * qgroup info.
+        */
+       trans = btrfs_start_transaction(fs_info->quota_root, 1);
+       if (IS_ERR(trans)) {
+               err = PTR_ERR(trans);
+               btrfs_err(fs_info,
+                         "fail to start transaction for status update: %d\n",
+                         err);
+               goto done;
+       }
+       ret = update_qgroup_status_item(trans, fs_info, fs_info->quota_root);
+       if (ret < 0) {
+               err = ret;
+               btrfs_err(fs_info, "fail to update qgroup status: %d\n", err);
+       }
+       btrfs_end_transaction(trans, fs_info->quota_root);
+
        if (err >= 0) {
                btrfs_info(fs_info, "qgroup scan completed%s",
-                       err == 2 ? " (inconsistency flag cleared)" : "");
+                       err > 0 ? " (inconsistency flag cleared)" : "");
        } else {
                btrfs_err(fs_info, "qgroup scan failed with %d", err);
        }
 
+done:
        complete_all(&fs_info->qgroup_rescan_completion);
 }
 
@@ -2709,7 +2850,6 @@ qgroup_rescan_init(struct btrfs_fs_info *fs_info, u64 progress_objectid,
                        mutex_unlock(&fs_info->qgroup_rescan_lock);
                        goto err;
                }
-
                fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_RESCAN;
        }
 
index 18cc68ca309054e84ce8248d78059fe3170be3ac..c5242aa9a4b2a1cc7237bd42487c063a0790d87f 100644 (file)
@@ -70,8 +70,7 @@ int btrfs_add_qgroup_relation(struct btrfs_trans_handle *trans,
 int btrfs_del_qgroup_relation(struct btrfs_trans_handle *trans,
                              struct btrfs_fs_info *fs_info, u64 src, u64 dst);
 int btrfs_create_qgroup(struct btrfs_trans_handle *trans,
-                       struct btrfs_fs_info *fs_info, u64 qgroupid,
-                       char *name);
+                       struct btrfs_fs_info *fs_info, u64 qgroupid);
 int btrfs_remove_qgroup(struct btrfs_trans_handle *trans,
                              struct btrfs_fs_info *fs_info, u64 qgroupid);
 int btrfs_limit_qgroup(struct btrfs_trans_handle *trans,
index 5264858ed7683f2306ccba372bf510c4509862fa..fa72068bd256018e27a13fbc8326b82ce49b207b 100644 (file)
@@ -237,12 +237,8 @@ int btrfs_alloc_stripe_hash_table(struct btrfs_fs_info *info)
        }
 
        x = cmpxchg(&info->stripe_hash_table, NULL, table);
-       if (x) {
-               if (is_vmalloc_addr(x))
-                       vfree(x);
-               else
-                       kfree(x);
-       }
+       if (x)
+               kvfree(x);
        return 0;
 }
 
@@ -453,10 +449,7 @@ void btrfs_free_stripe_hash_table(struct btrfs_fs_info *info)
        if (!info->stripe_hash_table)
                return;
        btrfs_clear_rbio_cache(info);
-       if (is_vmalloc_addr(info->stripe_hash_table))
-               vfree(info->stripe_hash_table);
-       else
-               kfree(info->stripe_hash_table);
+       kvfree(info->stripe_hash_table);
        info->stripe_hash_table = NULL;
 }
 
@@ -1807,8 +1800,7 @@ static void __raid_recover_end_io(struct btrfs_raid_bio *rbio)
        int err;
        int i;
 
-       pointers = kzalloc(rbio->real_stripes * sizeof(void *),
-                          GFP_NOFS);
+       pointers = kcalloc(rbio->real_stripes, sizeof(void *), GFP_NOFS);
        if (!pointers) {
                err = -ENOMEM;
                goto cleanup_io;
index d83085381bccfa745ee0258b8cab5558afbcd639..74b24b01d5740041a69aab1d083391c2e03ade8b 100644 (file)
@@ -3027,7 +3027,7 @@ int prealloc_file_extent_cluster(struct inode *inode,
        mutex_lock(&inode->i_mutex);
 
        ret = btrfs_check_data_free_space(inode, cluster->end +
-                                         1 - cluster->start);
+                                         1 - cluster->start, 0);
        if (ret)
                goto out;
 
@@ -3430,7 +3430,9 @@ static int block_use_full_backref(struct reloc_control *rc,
 }
 
 static int delete_block_group_cache(struct btrfs_fs_info *fs_info,
-                                   struct inode *inode, u64 ino)
+                                   struct btrfs_block_group_cache *block_group,
+                                   struct inode *inode,
+                                   u64 ino)
 {
        struct btrfs_key key;
        struct btrfs_root *root = fs_info->tree_root;
@@ -3463,7 +3465,7 @@ truncate:
                goto out;
        }
 
-       ret = btrfs_truncate_free_space_cache(root, trans, inode);
+       ret = btrfs_truncate_free_space_cache(root, trans, block_group, inode);
 
        btrfs_end_transaction(trans, root);
        btrfs_btree_balance_dirty(root);
@@ -3509,6 +3511,7 @@ static int find_data_references(struct reloc_control *rc,
         */
        if (ref_root == BTRFS_ROOT_TREE_OBJECTID) {
                ret = delete_block_group_cache(rc->extent_root->fs_info,
+                                              rc->block_group,
                                               NULL, ref_objectid);
                if (ret != -ENOENT)
                        return ret;
@@ -4223,7 +4226,7 @@ int btrfs_relocate_block_group(struct btrfs_root *extent_root, u64 group_start)
        btrfs_free_path(path);
 
        if (!IS_ERR(inode))
-               ret = delete_block_group_cache(fs_info, inode, 0);
+               ret = delete_block_group_cache(fs_info, rc->block_group, inode, 0);
        else
                ret = PTR_ERR(inode);
 
index ec57687c9a4d8a079466d6e9f95724188ec03bc7..ab5811545a988edf685ef4acce607cbff1ac7b81 100644 (file)
@@ -964,9 +964,8 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check)
         * the statistics.
         */
 
-       sblocks_for_recheck = kzalloc(BTRFS_MAX_MIRRORS *
-                                    sizeof(*sblocks_for_recheck),
-                                    GFP_NOFS);
+       sblocks_for_recheck = kcalloc(BTRFS_MAX_MIRRORS,
+                                     sizeof(*sblocks_for_recheck), GFP_NOFS);
        if (!sblocks_for_recheck) {
                spin_lock(&sctx->stat_lock);
                sctx->stat.malloc_errors++;
@@ -2319,7 +2318,7 @@ static inline void __scrub_mark_bitmap(struct scrub_parity *sparity,
                                       unsigned long *bitmap,
                                       u64 start, u64 len)
 {
-       int offset;
+       u32 offset;
        int nsectors;
        int sectorsize = sparity->sctx->dev_root->sectorsize;
 
@@ -2329,7 +2328,7 @@ static inline void __scrub_mark_bitmap(struct scrub_parity *sparity,
        }
 
        start -= sparity->logic_start;
-       offset = (int)do_div(start, sparity->stripe_len);
+       start = div_u64_rem(start, sparity->stripe_len, &offset);
        offset /= sectorsize;
        nsectors = (int)len / sectorsize;
 
@@ -2612,8 +2611,8 @@ static int get_raid56_logic_offset(u64 physical, int num,
        int j = 0;
        u64 stripe_nr;
        u64 last_offset;
-       int stripe_index;
-       int rot;
+       u32 stripe_index;
+       u32 rot;
 
        last_offset = (physical - map->stripes[num].physical) *
                      nr_data_stripes(map);
@@ -2624,12 +2623,11 @@ static int get_raid56_logic_offset(u64 physical, int num,
        for (i = 0; i < nr_data_stripes(map); i++) {
                *offset = last_offset + i * map->stripe_len;
 
-               stripe_nr = *offset;
-               do_div(stripe_nr, map->stripe_len);
-               do_div(stripe_nr, nr_data_stripes(map));
+               stripe_nr = div_u64(*offset, map->stripe_len);
+               stripe_nr = div_u64(stripe_nr, nr_data_stripes(map));
 
                /* Work out the disk rotation on this stripe-set */
-               rot = do_div(stripe_nr, map->num_stripes);
+               stripe_nr = div_u64_rem(stripe_nr, map->num_stripes, &rot);
                /* calculate which stripe this data locates */
                rot += i;
                stripe_index = rot % map->num_stripes;
@@ -2995,10 +2993,9 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
        int extent_mirror_num;
        int stop_loop = 0;
 
-       nstripes = length;
        physical = map->stripes[num].physical;
        offset = 0;
-       do_div(nstripes, map->stripe_len);
+       nstripes = div_u64(length, map->stripe_len);
        if (map->type & BTRFS_BLOCK_GROUP_RAID0) {
                offset = map->stripe_len * num;
                increment = map->stripe_len * map->num_stripes;
@@ -3563,7 +3560,7 @@ static noinline_for_stack int scrub_workers_get(struct btrfs_fs_info *fs_info,
                                                int is_dev_replace)
 {
        int ret = 0;
-       int flags = WQ_FREEZABLE | WQ_UNBOUND;
+       unsigned int flags = WQ_FREEZABLE | WQ_UNBOUND;
        int max_active = fs_info->thread_pool_size;
 
        if (fs_info->scrub_workers_refcnt == 0) {
index d6033f540cc75cfb49ddbe5f07689d67fdefc492..a1216f9b49171510194109c7594c61b4277298ea 100644 (file)
@@ -3067,48 +3067,6 @@ static struct pending_dir_move *get_pending_dir_moves(struct send_ctx *sctx,
        return NULL;
 }
 
-static int path_loop(struct send_ctx *sctx, struct fs_path *name,
-                    u64 ino, u64 gen, u64 *ancestor_ino)
-{
-       int ret = 0;
-       u64 parent_inode = 0;
-       u64 parent_gen = 0;
-       u64 start_ino = ino;
-
-       *ancestor_ino = 0;
-       while (ino != BTRFS_FIRST_FREE_OBJECTID) {
-               fs_path_reset(name);
-
-               if (is_waiting_for_rm(sctx, ino))
-                       break;
-               if (is_waiting_for_move(sctx, ino)) {
-                       if (*ancestor_ino == 0)
-                               *ancestor_ino = ino;
-                       ret = get_first_ref(sctx->parent_root, ino,
-                                           &parent_inode, &parent_gen, name);
-               } else {
-                       ret = __get_cur_name_and_parent(sctx, ino, gen,
-                                                       &parent_inode,
-                                                       &parent_gen, name);
-                       if (ret > 0) {
-                               ret = 0;
-                               break;
-                       }
-               }
-               if (ret < 0)
-                       break;
-               if (parent_inode == start_ino) {
-                       ret = 1;
-                       if (*ancestor_ino == 0)
-                               *ancestor_ino = ino;
-                       break;
-               }
-               ino = parent_inode;
-               gen = parent_gen;
-       }
-       return ret;
-}
-
 static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm)
 {
        struct fs_path *from_path = NULL;
@@ -3120,7 +3078,6 @@ static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm)
        struct waiting_dir_move *dm = NULL;
        u64 rmdir_ino = 0;
        int ret;
-       u64 ancestor = 0;
 
        name = fs_path_alloc();
        from_path = fs_path_alloc();
@@ -3152,22 +3109,6 @@ static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm)
                goto out;
 
        sctx->send_progress = sctx->cur_ino + 1;
-       ret = path_loop(sctx, name, pm->ino, pm->gen, &ancestor);
-       if (ret) {
-               LIST_HEAD(deleted_refs);
-               ASSERT(ancestor > BTRFS_FIRST_FREE_OBJECTID);
-               ret = add_pending_dir_move(sctx, pm->ino, pm->gen, ancestor,
-                                          &pm->update_refs, &deleted_refs,
-                                          pm->is_orphan);
-               if (ret < 0)
-                       goto out;
-               if (rmdir_ino) {
-                       dm = get_waiting_dir_move(sctx, pm->ino);
-                       ASSERT(dm);
-                       dm->rmdir_ino = rmdir_ino;
-               }
-               goto out;
-       }
        fs_path_reset(name);
        to_path = name;
        name = NULL;
@@ -3610,10 +3551,27 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
                        if (ret < 0)
                                goto out;
                        if (ret) {
+                               struct name_cache_entry *nce;
+
                                ret = orphanize_inode(sctx, ow_inode, ow_gen,
                                                cur->full_path);
                                if (ret < 0)
                                        goto out;
+                               /*
+                                * Make sure we clear our orphanized inode's
+                                * name from the name cache. This is because the
+                                * inode ow_inode might be an ancestor of some
+                                * other inode that will be orphanized as well
+                                * later and has an inode number greater than
+                                * sctx->send_progress. We need to prevent
+                                * future name lookups from using the old name
+                                * and get instead the orphan name.
+                                */
+                               nce = name_cache_search(sctx, ow_inode, ow_gen);
+                               if (nce) {
+                                       name_cache_delete(sctx, nce);
+                                       kfree(nce);
+                               }
                        } else {
                                ret = send_unlink(sctx, cur->full_path);
                                if (ret < 0)
@@ -5852,19 +5810,20 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_)
                                ret = PTR_ERR(clone_root);
                                goto out;
                        }
-                       clone_sources_to_rollback = i + 1;
                        spin_lock(&clone_root->root_item_lock);
-                       clone_root->send_in_progress++;
-                       if (!btrfs_root_readonly(clone_root)) {
+                       if (!btrfs_root_readonly(clone_root) ||
+                           btrfs_root_dead(clone_root)) {
                                spin_unlock(&clone_root->root_item_lock);
                                srcu_read_unlock(&fs_info->subvol_srcu, index);
                                ret = -EPERM;
                                goto out;
                        }
+                       clone_root->send_in_progress++;
                        spin_unlock(&clone_root->root_item_lock);
                        srcu_read_unlock(&fs_info->subvol_srcu, index);
 
                        sctx->clone_roots[i].root = clone_root;
+                       clone_sources_to_rollback = i + 1;
                }
                vfree(clone_sources_tmp);
                clone_sources_tmp = NULL;
index 05fef198ff94fc8df4eb126a62195af8452fb18d..9e66f5e724db1e307f19f74df7862550c170f069 100644 (file)
@@ -901,6 +901,15 @@ find_root:
        if (IS_ERR(new_root))
                return ERR_CAST(new_root);
 
+       if (!(sb->s_flags & MS_RDONLY)) {
+               int ret;
+               down_read(&fs_info->cleanup_work_sem);
+               ret = btrfs_orphan_cleanup(new_root);
+               up_read(&fs_info->cleanup_work_sem);
+               if (ret)
+                       return ERR_PTR(ret);
+       }
+
        dir_id = btrfs_root_dirid(&new_root->root_item);
 setup_root:
        location.objectid = dir_id;
@@ -916,7 +925,7 @@ setup_root:
         * a reference to the dentry.  We will have already gotten a reference
         * to the inode in btrfs_fill_super so we're good to go.
         */
-       if (!new && sb->s_root->d_inode == inode) {
+       if (!new && d_inode(sb->s_root) == inode) {
                iput(inode);
                return dget(sb->s_root);
        }
@@ -1221,7 +1230,7 @@ static struct dentry *mount_subvol(const char *subvol_name, int flags,
 
        root = mount_subtree(mnt, subvol_name);
 
-       if (!IS_ERR(root) && !is_subvolume_inode(root->d_inode)) {
+       if (!IS_ERR(root) && !is_subvolume_inode(d_inode(root))) {
                struct super_block *s = root->d_sb;
                dput(root);
                root = ERR_PTR(-EINVAL);
@@ -1714,7 +1723,7 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes)
                avail_space = device->total_bytes - device->bytes_used;
 
                /* align with stripe_len */
-               do_div(avail_space, BTRFS_STRIPE_LEN);
+               avail_space = div_u64(avail_space, BTRFS_STRIPE_LEN);
                avail_space *= BTRFS_STRIPE_LEN;
 
                /*
@@ -1886,8 +1895,8 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
        buf->f_fsid.val[0] = be32_to_cpu(fsid[0]) ^ be32_to_cpu(fsid[2]);
        buf->f_fsid.val[1] = be32_to_cpu(fsid[1]) ^ be32_to_cpu(fsid[3]);
        /* Mask in the root object ID too, to disambiguate subvols */
-       buf->f_fsid.val[0] ^= BTRFS_I(dentry->d_inode)->root->objectid >> 32;
-       buf->f_fsid.val[1] ^= BTRFS_I(dentry->d_inode)->root->objectid;
+       buf->f_fsid.val[0] ^= BTRFS_I(d_inode(dentry))->root->objectid >> 32;
+       buf->f_fsid.val[1] ^= BTRFS_I(d_inode(dentry))->root->objectid;
 
        return 0;
 }
@@ -1908,6 +1917,17 @@ static struct file_system_type btrfs_fs_type = {
 };
 MODULE_ALIAS_FS("btrfs");
 
+static int btrfs_control_open(struct inode *inode, struct file *file)
+{
+       /*
+        * The control file's private_data is used to hold the
+        * transaction when it is started and is used to keep
+        * track of whether a transaction is already in progress.
+        */
+       file->private_data = NULL;
+       return 0;
+}
+
 /*
  * used by btrfsctl to scan devices when no FS is mounted
  */
@@ -2009,6 +2029,7 @@ static const struct super_operations btrfs_super_ops = {
 };
 
 static const struct file_operations btrfs_ctl_fops = {
+       .open = btrfs_control_open,
        .unlocked_ioctl  = btrfs_control_ioctl,
        .compat_ioctl = btrfs_control_ioctl,
        .owner   = THIS_MODULE,
index 94edb0a2a026652b6cb017f45cc5e1ef9d521277..e8a4c86d274d5c82cda9fc7ac40c6974f429ece8 100644 (file)
@@ -459,7 +459,7 @@ static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj)
 static char btrfs_unknown_feature_names[3][NUM_FEATURE_BITS][13];
 static struct btrfs_feature_attr btrfs_feature_attrs[3][NUM_FEATURE_BITS];
 
-static u64 supported_feature_masks[3] = {
+static const u64 supported_feature_masks[3] = {
        [FEAT_COMPAT]    = BTRFS_FEATURE_COMPAT_SUPP,
        [FEAT_COMPAT_RO] = BTRFS_FEATURE_COMPAT_RO_SUPP,
        [FEAT_INCOMPAT]  = BTRFS_FEATURE_INCOMPAT_SUPP,
index f7dd298b3cf6ecbb080924ffd083af7bb68a4e1f..3a4bbed723fde53e05228ace7dea9e49165f246a 100644 (file)
@@ -61,11 +61,23 @@ static struct btrfs_feature_attr btrfs_attr_##_name = {                          \
        BTRFS_FEAT_ATTR(name, FEAT_INCOMPAT, BTRFS_FEATURE_INCOMPAT, feature)
 
 /* convert from attribute */
-#define to_btrfs_feature_attr(a) \
-                       container_of(a, struct btrfs_feature_attr, kobj_attr)
-#define attr_to_btrfs_attr(a) container_of(a, struct kobj_attribute, attr)
-#define attr_to_btrfs_feature_attr(a) \
-                       to_btrfs_feature_attr(attr_to_btrfs_attr(a))
+static inline struct btrfs_feature_attr *
+to_btrfs_feature_attr(struct kobj_attribute *a)
+{
+       return container_of(a, struct btrfs_feature_attr, kobj_attr);
+}
+
+static inline struct kobj_attribute *attr_to_btrfs_attr(struct attribute *attr)
+{
+       return container_of(attr, struct kobj_attribute, attr);
+}
+
+static inline struct btrfs_feature_attr *
+attr_to_btrfs_feature_attr(struct attribute *attr)
+{
+       return to_btrfs_feature_attr(attr_to_btrfs_attr(attr));
+}
+
 char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags);
 extern const char * const btrfs_feature_set_names[3];
 extern struct kobj_type space_info_ktype;
index 73f299ebdabb4389964fafeb7506bdd9716dea67..c32a7ba76bcaed1262dffff1c2b8a6a8db63ce29 100644 (file)
@@ -232,7 +232,7 @@ static int test_no_shared_qgroup(struct btrfs_root *root)
        init_dummy_trans(&trans);
 
        test_msg("Qgroup basic add\n");
-       ret = btrfs_create_qgroup(NULL, fs_info, 5, NULL);
+       ret = btrfs_create_qgroup(NULL, fs_info, 5);
        if (ret) {
                test_msg("Couldn't create a qgroup %d\n", ret);
                return ret;
@@ -301,7 +301,7 @@ static int test_multiple_refs(struct btrfs_root *root)
        test_msg("Qgroup multiple refs test\n");
 
        /* We have 5 created already from the previous test */
-       ret = btrfs_create_qgroup(NULL, fs_info, 256, NULL);
+       ret = btrfs_create_qgroup(NULL, fs_info, 256);
        if (ret) {
                test_msg("Couldn't create a qgroup %d\n", ret);
                return ret;
index 8be4278e25e8e06e32d52b5ac412201d7b20a53c..5628e25250c0d2cca318f03d41f4e6d64b4d40e0 100644 (file)
@@ -35,7 +35,7 @@
 
 #define BTRFS_ROOT_TRANS_TAG 0
 
-static unsigned int btrfs_blocked_trans_types[TRANS_STATE_MAX] = {
+static const unsigned int btrfs_blocked_trans_types[TRANS_STATE_MAX] = {
        [TRANS_STATE_RUNNING]           = 0U,
        [TRANS_STATE_BLOCKED]           = (__TRANS_USERSPACE |
                                           __TRANS_START),
@@ -64,6 +64,9 @@ void btrfs_put_transaction(struct btrfs_transaction *transaction)
        if (atomic_dec_and_test(&transaction->use_count)) {
                BUG_ON(!list_empty(&transaction->list));
                WARN_ON(!RB_EMPTY_ROOT(&transaction->delayed_refs.href_root));
+               if (transaction->delayed_refs.pending_csums)
+                       printk(KERN_ERR "pending csums is %llu\n",
+                              transaction->delayed_refs.pending_csums);
                while (!list_empty(&transaction->pending_chunks)) {
                        struct extent_map *em;
 
@@ -93,11 +96,8 @@ static void clear_btree_io_tree(struct extent_io_tree *tree)
                 */
                ASSERT(!waitqueue_active(&state->wq));
                free_extent_state(state);
-               if (need_resched()) {
-                       spin_unlock(&tree->lock);
-                       cond_resched();
-                       spin_lock(&tree->lock);
-               }
+
+               cond_resched_lock(&tree->lock);
        }
        spin_unlock(&tree->lock);
 }
@@ -222,10 +222,12 @@ loop:
        atomic_set(&cur_trans->use_count, 2);
        cur_trans->have_free_bgs = 0;
        cur_trans->start_time = get_seconds();
+       cur_trans->dirty_bg_run = 0;
 
        cur_trans->delayed_refs.href_root = RB_ROOT;
        atomic_set(&cur_trans->delayed_refs.num_entries, 0);
        cur_trans->delayed_refs.num_heads_ready = 0;
+       cur_trans->delayed_refs.pending_csums = 0;
        cur_trans->delayed_refs.num_heads = 0;
        cur_trans->delayed_refs.flushing = 0;
        cur_trans->delayed_refs.run_delayed_start = 0;
@@ -250,6 +252,9 @@ loop:
        INIT_LIST_HEAD(&cur_trans->switch_commits);
        INIT_LIST_HEAD(&cur_trans->pending_ordered);
        INIT_LIST_HEAD(&cur_trans->dirty_bgs);
+       INIT_LIST_HEAD(&cur_trans->io_bgs);
+       mutex_init(&cur_trans->cache_write_mutex);
+       cur_trans->num_dirty_bgs = 0;
        spin_lock_init(&cur_trans->dirty_bgs_lock);
        list_add_tail(&cur_trans->list, &fs_info->trans_list);
        extent_io_tree_init(&cur_trans->dirty_pages,
@@ -721,7 +726,7 @@ int btrfs_should_end_transaction(struct btrfs_trans_handle *trans,
        updates = trans->delayed_ref_updates;
        trans->delayed_ref_updates = 0;
        if (updates) {
-               err = btrfs_run_delayed_refs(trans, root, updates);
+               err = btrfs_run_delayed_refs(trans, root, updates * 2);
                if (err) /* Error code will also eval true */
                        return err;
        }
@@ -1057,6 +1062,7 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans,
 {
        struct btrfs_fs_info *fs_info = root->fs_info;
        struct list_head *dirty_bgs = &trans->transaction->dirty_bgs;
+       struct list_head *io_bgs = &trans->transaction->io_bgs;
        struct list_head *next;
        struct extent_buffer *eb;
        int ret;
@@ -1110,7 +1116,7 @@ again:
                        return ret;
        }
 
-       while (!list_empty(dirty_bgs)) {
+       while (!list_empty(dirty_bgs) || !list_empty(io_bgs)) {
                ret = btrfs_write_dirty_block_groups(trans, root);
                if (ret)
                        return ret;
@@ -1810,6 +1816,37 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
                return ret;
        }
 
+       if (!cur_trans->dirty_bg_run) {
+               int run_it = 0;
+
+               /* this mutex is also taken before trying to set
+                * block groups readonly.  We need to make sure
+                * that nobody has set a block group readonly
+                * after a extents from that block group have been
+                * allocated for cache files.  btrfs_set_block_group_ro
+                * will wait for the transaction to commit if it
+                * finds dirty_bg_run = 1
+                *
+                * The dirty_bg_run flag is also used to make sure only
+                * one process starts all the block group IO.  It wouldn't
+                * hurt to have more than one go through, but there's no
+                * real advantage to it either.
+                */
+               mutex_lock(&root->fs_info->ro_block_group_mutex);
+               if (!cur_trans->dirty_bg_run) {
+                       run_it = 1;
+                       cur_trans->dirty_bg_run = 1;
+               }
+               mutex_unlock(&root->fs_info->ro_block_group_mutex);
+
+               if (run_it)
+                       ret = btrfs_start_dirty_block_groups(trans, root);
+       }
+       if (ret) {
+               btrfs_end_transaction(trans, root);
+               return ret;
+       }
+
        spin_lock(&root->fs_info->trans_lock);
        list_splice(&trans->ordered, &cur_trans->pending_ordered);
        if (cur_trans->state >= TRANS_STATE_COMMIT_START) {
@@ -2003,6 +2040,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
 
        assert_qgroups_uptodate(trans);
        ASSERT(list_empty(&cur_trans->dirty_bgs));
+       ASSERT(list_empty(&cur_trans->io_bgs));
        update_super_roots(root);
 
        btrfs_set_super_log_root(root->fs_info->super_copy, 0);
index 937050a2b68edaf6bdd6027f23c6c6d37b8257d5..0b24755596bab2fe4c5ba0c60511db33aff51254 100644 (file)
@@ -64,9 +64,19 @@ struct btrfs_transaction {
        struct list_head pending_ordered;
        struct list_head switch_commits;
        struct list_head dirty_bgs;
+       struct list_head io_bgs;
+       u64 num_dirty_bgs;
+
+       /*
+        * we need to make sure block group deletion doesn't race with
+        * free space cache writeout.  This mutex keeps them from stomping
+        * on each other
+        */
+       struct mutex cache_write_mutex;
        spinlock_t dirty_bgs_lock;
        struct btrfs_delayed_ref_root delayed_refs;
        int aborted;
+       int dirty_bg_run;
 };
 
 #define __TRANS_FREEZABLE      (1U << 0)
@@ -136,9 +146,11 @@ struct btrfs_pending_snapshot {
 static inline void btrfs_set_inode_last_trans(struct btrfs_trans_handle *trans,
                                              struct inode *inode)
 {
+       spin_lock(&BTRFS_I(inode)->lock);
        BTRFS_I(inode)->last_trans = trans->transaction->transid;
        BTRFS_I(inode)->last_sub_trans = BTRFS_I(inode)->root->log_transid;
        BTRFS_I(inode)->last_log_commit = BTRFS_I(inode)->root->last_log_commit;
+       spin_unlock(&BTRFS_I(inode)->lock);
 }
 
 int btrfs_end_transaction(struct btrfs_trans_handle *trans,
index c5b8ba37f88e31fa188258af9c6e13036c2df18f..d04968374e9d8bd5b118024d53ea0a5bfa6d0bd2 100644 (file)
@@ -492,11 +492,19 @@ insert:
 
                if (btrfs_inode_generation(eb, src_item) == 0) {
                        struct extent_buffer *dst_eb = path->nodes[0];
+                       const u64 ino_size = btrfs_inode_size(eb, src_item);
 
+                       /*
+                        * For regular files an ino_size == 0 is used only when
+                        * logging that an inode exists, as part of a directory
+                        * fsync, and the inode wasn't fsynced before. In this
+                        * case don't set the size of the inode in the fs/subvol
+                        * tree, otherwise we would be throwing valid data away.
+                        */
                        if (S_ISREG(btrfs_inode_mode(eb, src_item)) &&
-                           S_ISREG(btrfs_inode_mode(dst_eb, dst_item))) {
+                           S_ISREG(btrfs_inode_mode(dst_eb, dst_item)) &&
+                           ino_size != 0) {
                                struct btrfs_map_token token;
-                               u64 ino_size = btrfs_inode_size(eb, src_item);
 
                                btrfs_init_map_token(&token);
                                btrfs_set_token_inode_size(dst_eb, dst_item,
@@ -1951,6 +1959,104 @@ out:
        return ret;
 }
 
+static int replay_xattr_deletes(struct btrfs_trans_handle *trans,
+                             struct btrfs_root *root,
+                             struct btrfs_root *log,
+                             struct btrfs_path *path,
+                             const u64 ino)
+{
+       struct btrfs_key search_key;
+       struct btrfs_path *log_path;
+       int i;
+       int nritems;
+       int ret;
+
+       log_path = btrfs_alloc_path();
+       if (!log_path)
+               return -ENOMEM;
+
+       search_key.objectid = ino;
+       search_key.type = BTRFS_XATTR_ITEM_KEY;
+       search_key.offset = 0;
+again:
+       ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0);
+       if (ret < 0)
+               goto out;
+process_leaf:
+       nritems = btrfs_header_nritems(path->nodes[0]);
+       for (i = path->slots[0]; i < nritems; i++) {
+               struct btrfs_key key;
+               struct btrfs_dir_item *di;
+               struct btrfs_dir_item *log_di;
+               u32 total_size;
+               u32 cur;
+
+               btrfs_item_key_to_cpu(path->nodes[0], &key, i);
+               if (key.objectid != ino || key.type != BTRFS_XATTR_ITEM_KEY) {
+                       ret = 0;
+                       goto out;
+               }
+
+               di = btrfs_item_ptr(path->nodes[0], i, struct btrfs_dir_item);
+               total_size = btrfs_item_size_nr(path->nodes[0], i);
+               cur = 0;
+               while (cur < total_size) {
+                       u16 name_len = btrfs_dir_name_len(path->nodes[0], di);
+                       u16 data_len = btrfs_dir_data_len(path->nodes[0], di);
+                       u32 this_len = sizeof(*di) + name_len + data_len;
+                       char *name;
+
+                       name = kmalloc(name_len, GFP_NOFS);
+                       if (!name) {
+                               ret = -ENOMEM;
+                               goto out;
+                       }
+                       read_extent_buffer(path->nodes[0], name,
+                                          (unsigned long)(di + 1), name_len);
+
+                       log_di = btrfs_lookup_xattr(NULL, log, log_path, ino,
+                                                   name, name_len, 0);
+                       btrfs_release_path(log_path);
+                       if (!log_di) {
+                               /* Doesn't exist in log tree, so delete it. */
+                               btrfs_release_path(path);
+                               di = btrfs_lookup_xattr(trans, root, path, ino,
+                                                       name, name_len, -1);
+                               kfree(name);
+                               if (IS_ERR(di)) {
+                                       ret = PTR_ERR(di);
+                                       goto out;
+                               }
+                               ASSERT(di);
+                               ret = btrfs_delete_one_dir_name(trans, root,
+                                                               path, di);
+                               if (ret)
+                                       goto out;
+                               btrfs_release_path(path);
+                               search_key = key;
+                               goto again;
+                       }
+                       kfree(name);
+                       if (IS_ERR(log_di)) {
+                               ret = PTR_ERR(log_di);
+                               goto out;
+                       }
+                       cur += this_len;
+                       di = (struct btrfs_dir_item *)((char *)di + this_len);
+               }
+       }
+       ret = btrfs_next_leaf(root, path);
+       if (ret > 0)
+               ret = 0;
+       else if (ret == 0)
+               goto process_leaf;
+out:
+       btrfs_free_path(log_path);
+       btrfs_release_path(path);
+       return ret;
+}
+
+
 /*
  * deletion replay happens before we copy any new directory items
  * out of the log or out of backreferences from inodes.  It
@@ -2104,6 +2210,10 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb,
 
                        inode_item = btrfs_item_ptr(eb, i,
                                            struct btrfs_inode_item);
+                       ret = replay_xattr_deletes(wc->trans, root, log,
+                                                  path, key.objectid);
+                       if (ret)
+                               break;
                        mode = btrfs_inode_mode(eb, inode_item);
                        if (S_ISDIR(mode)) {
                                ret = replay_dir_deletes(wc->trans,
@@ -2230,7 +2340,8 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
                                if (trans) {
                                        btrfs_tree_lock(next);
                                        btrfs_set_lock_blocking(next);
-                                       clean_tree_block(trans, root, next);
+                                       clean_tree_block(trans, root->fs_info,
+                                                       next);
                                        btrfs_wait_tree_block_writeback(next);
                                        btrfs_tree_unlock(next);
                                }
@@ -2308,7 +2419,8 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans,
                                if (trans) {
                                        btrfs_tree_lock(next);
                                        btrfs_set_lock_blocking(next);
-                                       clean_tree_block(trans, root, next);
+                                       clean_tree_block(trans, root->fs_info,
+                                                       next);
                                        btrfs_wait_tree_block_writeback(next);
                                        btrfs_tree_unlock(next);
                                }
@@ -2384,7 +2496,7 @@ static int walk_log_tree(struct btrfs_trans_handle *trans,
                        if (trans) {
                                btrfs_tree_lock(next);
                                btrfs_set_lock_blocking(next);
-                               clean_tree_block(trans, log, next);
+                               clean_tree_block(trans, log->fs_info, next);
                                btrfs_wait_tree_block_writeback(next);
                                btrfs_tree_unlock(next);
                        }
@@ -3020,6 +3132,7 @@ static noinline int log_dir_items(struct btrfs_trans_handle *trans,
                          struct btrfs_root *root, struct inode *inode,
                          struct btrfs_path *path,
                          struct btrfs_path *dst_path, int key_type,
+                         struct btrfs_log_ctx *ctx,
                          u64 min_offset, u64 *last_offset_ret)
 {
        struct btrfs_key min_key;
@@ -3104,6 +3217,8 @@ static noinline int log_dir_items(struct btrfs_trans_handle *trans,
                src = path->nodes[0];
                nritems = btrfs_header_nritems(src);
                for (i = path->slots[0]; i < nritems; i++) {
+                       struct btrfs_dir_item *di;
+
                        btrfs_item_key_to_cpu(src, &min_key, i);
 
                        if (min_key.objectid != ino || min_key.type != key_type)
@@ -3114,6 +3229,37 @@ static noinline int log_dir_items(struct btrfs_trans_handle *trans,
                                err = ret;
                                goto done;
                        }
+
+                       /*
+                        * We must make sure that when we log a directory entry,
+                        * the corresponding inode, after log replay, has a
+                        * matching link count. For example:
+                        *
+                        * touch foo
+                        * mkdir mydir
+                        * sync
+                        * ln foo mydir/bar
+                        * xfs_io -c "fsync" mydir
+                        * <crash>
+                        * <mount fs and log replay>
+                        *
+                        * Would result in a fsync log that when replayed, our
+                        * file inode would have a link count of 1, but we get
+                        * two directory entries pointing to the same inode.
+                        * After removing one of the names, it would not be
+                        * possible to remove the other name, which resulted
+                        * always in stale file handle errors, and would not
+                        * be possible to rmdir the parent directory, since
+                        * its i_size could never decrement to the value
+                        * BTRFS_EMPTY_DIR_SIZE, resulting in -ENOTEMPTY errors.
+                        */
+                       di = btrfs_item_ptr(src, i, struct btrfs_dir_item);
+                       btrfs_dir_item_key_to_cpu(src, di, &tmp);
+                       if (ctx &&
+                           (btrfs_dir_transid(src, di) == trans->transid ||
+                            btrfs_dir_type(src, di) == BTRFS_FT_DIR) &&
+                           tmp.type != BTRFS_ROOT_ITEM_KEY)
+                               ctx->log_new_dentries = true;
                }
                path->slots[0] = nritems;
 
@@ -3175,7 +3321,8 @@ done:
 static noinline int log_directory_changes(struct btrfs_trans_handle *trans,
                          struct btrfs_root *root, struct inode *inode,
                          struct btrfs_path *path,
-                         struct btrfs_path *dst_path)
+                         struct btrfs_path *dst_path,
+                         struct btrfs_log_ctx *ctx)
 {
        u64 min_key;
        u64 max_key;
@@ -3187,7 +3334,7 @@ again:
        max_key = 0;
        while (1) {
                ret = log_dir_items(trans, root, inode, path,
-                                   dst_path, key_type, min_key,
+                                   dst_path, key_type, ctx, min_key,
                                    &max_key);
                if (ret)
                        return ret;
@@ -3963,7 +4110,7 @@ static int logged_inode_size(struct btrfs_root *log, struct inode *inode,
        if (ret < 0) {
                return ret;
        } else if (ret > 0) {
-               *size_ret = i_size_read(inode);
+               *size_ret = 0;
        } else {
                struct btrfs_inode_item *item;
 
@@ -4070,10 +4217,8 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
        if (S_ISDIR(inode->i_mode)) {
                int max_key_type = BTRFS_DIR_LOG_INDEX_KEY;
 
-               if (inode_only == LOG_INODE_EXISTS) {
-                       max_key_type = BTRFS_INODE_EXTREF_KEY;
-                       max_key.type = max_key_type;
-               }
+               if (inode_only == LOG_INODE_EXISTS)
+                       max_key_type = BTRFS_XATTR_ITEM_KEY;
                ret = drop_objectid_items(trans, log, path, ino, max_key_type);
        } else {
                if (inode_only == LOG_INODE_EXISTS) {
@@ -4098,7 +4243,7 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
                if (test_bit(BTRFS_INODE_NEEDS_FULL_SYNC,
                             &BTRFS_I(inode)->runtime_flags)) {
                        if (inode_only == LOG_INODE_EXISTS) {
-                               max_key.type = BTRFS_INODE_EXTREF_KEY;
+                               max_key.type = BTRFS_XATTR_ITEM_KEY;
                                ret = drop_objectid_items(trans, log, path, ino,
                                                          max_key.type);
                        } else {
@@ -4106,20 +4251,19 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
                                          &BTRFS_I(inode)->runtime_flags);
                                clear_bit(BTRFS_INODE_COPY_EVERYTHING,
                                          &BTRFS_I(inode)->runtime_flags);
-                               ret = btrfs_truncate_inode_items(trans, log,
-                                                                inode, 0, 0);
+                               while(1) {
+                                       ret = btrfs_truncate_inode_items(trans,
+                                                        log, inode, 0, 0);
+                                       if (ret != -EAGAIN)
+                                               break;
+                               }
                        }
-               } else if (test_bit(BTRFS_INODE_COPY_EVERYTHING,
-                                   &BTRFS_I(inode)->runtime_flags) ||
+               } else if (test_and_clear_bit(BTRFS_INODE_COPY_EVERYTHING,
+                                             &BTRFS_I(inode)->runtime_flags) ||
                           inode_only == LOG_INODE_EXISTS) {
-                       if (inode_only == LOG_INODE_ALL) {
-                               clear_bit(BTRFS_INODE_COPY_EVERYTHING,
-                                         &BTRFS_I(inode)->runtime_flags);
+                       if (inode_only == LOG_INODE_ALL)
                                fast_search = true;
-                               max_key.type = BTRFS_XATTR_ITEM_KEY;
-                       } else {
-                               max_key.type = BTRFS_INODE_EXTREF_KEY;
-                       }
+                       max_key.type = BTRFS_XATTR_ITEM_KEY;
                        ret = drop_objectid_items(trans, log, path, ino,
                                                  max_key.type);
                } else {
@@ -4277,15 +4421,18 @@ log_extents:
        }
 
        if (inode_only == LOG_INODE_ALL && S_ISDIR(inode->i_mode)) {
-               ret = log_directory_changes(trans, root, inode, path, dst_path);
+               ret = log_directory_changes(trans, root, inode, path, dst_path,
+                                           ctx);
                if (ret) {
                        err = ret;
                        goto out_unlock;
                }
        }
 
+       spin_lock(&BTRFS_I(inode)->lock);
        BTRFS_I(inode)->logged_trans = trans->transid;
        BTRFS_I(inode)->last_log_commit = BTRFS_I(inode)->last_sub_trans;
+       spin_unlock(&BTRFS_I(inode)->lock);
 out_unlock:
        if (unlikely(err))
                btrfs_put_logged_extents(&logged_list);
@@ -4327,9 +4474,9 @@ static noinline int check_parent_dirs_for_sync(struct btrfs_trans_handle *trans,
                        goto out;
 
        if (!S_ISDIR(inode->i_mode)) {
-               if (!parent || !parent->d_inode || sb != parent->d_inode->i_sb)
+               if (!parent || d_really_is_negative(parent) || sb != d_inode(parent)->i_sb)
                        goto out;
-               inode = parent->d_inode;
+               inode = d_inode(parent);
        }
 
        while (1) {
@@ -4355,7 +4502,7 @@ static noinline int check_parent_dirs_for_sync(struct btrfs_trans_handle *trans,
                        break;
                }
 
-               if (!parent || !parent->d_inode || sb != parent->d_inode->i_sb)
+               if (!parent || d_really_is_negative(parent) || sb != d_inode(parent)->i_sb)
                        break;
 
                if (IS_ROOT(parent))
@@ -4364,7 +4511,7 @@ static noinline int check_parent_dirs_for_sync(struct btrfs_trans_handle *trans,
                parent = dget_parent(parent);
                dput(old_parent);
                old_parent = parent;
-               inode = parent->d_inode;
+               inode = d_inode(parent);
 
        }
        dput(old_parent);
@@ -4372,6 +4519,181 @@ out:
        return ret;
 }
 
+struct btrfs_dir_list {
+       u64 ino;
+       struct list_head list;
+};
+
+/*
+ * Log the inodes of the new dentries of a directory. See log_dir_items() for
+ * details about the why it is needed.
+ * This is a recursive operation - if an existing dentry corresponds to a
+ * directory, that directory's new entries are logged too (same behaviour as
+ * ext3/4, xfs, f2fs, reiserfs, nilfs2). Note that when logging the inodes
+ * the dentries point to we do not lock their i_mutex, otherwise lockdep
+ * complains about the following circular lock dependency / possible deadlock:
+ *
+ *        CPU0                                        CPU1
+ *        ----                                        ----
+ * lock(&type->i_mutex_dir_key#3/2);
+ *                                            lock(sb_internal#2);
+ *                                            lock(&type->i_mutex_dir_key#3/2);
+ * lock(&sb->s_type->i_mutex_key#14);
+ *
+ * Where sb_internal is the lock (a counter that works as a lock) acquired by
+ * sb_start_intwrite() in btrfs_start_transaction().
+ * Not locking i_mutex of the inodes is still safe because:
+ *
+ * 1) For regular files we log with a mode of LOG_INODE_EXISTS. It's possible
+ *    that while logging the inode new references (names) are added or removed
+ *    from the inode, leaving the logged inode item with a link count that does
+ *    not match the number of logged inode reference items. This is fine because
+ *    at log replay time we compute the real number of links and correct the
+ *    link count in the inode item (see replay_one_buffer() and
+ *    link_to_fixup_dir());
+ *
+ * 2) For directories we log with a mode of LOG_INODE_ALL. It's possible that
+ *    while logging the inode's items new items with keys BTRFS_DIR_ITEM_KEY and
+ *    BTRFS_DIR_INDEX_KEY are added to fs/subvol tree and the logged inode item
+ *    has a size that doesn't match the sum of the lengths of all the logged
+ *    names. This does not result in a problem because if a dir_item key is
+ *    logged but its matching dir_index key is not logged, at log replay time we
+ *    don't use it to replay the respective name (see replay_one_name()). On the
+ *    other hand if only the dir_index key ends up being logged, the respective
+ *    name is added to the fs/subvol tree with both the dir_item and dir_index
+ *    keys created (see replay_one_name()).
+ *    The directory's inode item with a wrong i_size is not a problem as well,
+ *    since we don't use it at log replay time to set the i_size in the inode
+ *    item of the fs/subvol tree (see overwrite_item()).
+ */
+static int log_new_dir_dentries(struct btrfs_trans_handle *trans,
+                               struct btrfs_root *root,
+                               struct inode *start_inode,
+                               struct btrfs_log_ctx *ctx)
+{
+       struct btrfs_root *log = root->log_root;
+       struct btrfs_path *path;
+       LIST_HEAD(dir_list);
+       struct btrfs_dir_list *dir_elem;
+       int ret = 0;
+
+       path = btrfs_alloc_path();
+       if (!path)
+               return -ENOMEM;
+
+       dir_elem = kmalloc(sizeof(*dir_elem), GFP_NOFS);
+       if (!dir_elem) {
+               btrfs_free_path(path);
+               return -ENOMEM;
+       }
+       dir_elem->ino = btrfs_ino(start_inode);
+       list_add_tail(&dir_elem->list, &dir_list);
+
+       while (!list_empty(&dir_list)) {
+               struct extent_buffer *leaf;
+               struct btrfs_key min_key;
+               int nritems;
+               int i;
+
+               dir_elem = list_first_entry(&dir_list, struct btrfs_dir_list,
+                                           list);
+               if (ret)
+                       goto next_dir_inode;
+
+               min_key.objectid = dir_elem->ino;
+               min_key.type = BTRFS_DIR_ITEM_KEY;
+               min_key.offset = 0;
+again:
+               btrfs_release_path(path);
+               ret = btrfs_search_forward(log, &min_key, path, trans->transid);
+               if (ret < 0) {
+                       goto next_dir_inode;
+               } else if (ret > 0) {
+                       ret = 0;
+                       goto next_dir_inode;
+               }
+
+process_leaf:
+               leaf = path->nodes[0];
+               nritems = btrfs_header_nritems(leaf);
+               for (i = path->slots[0]; i < nritems; i++) {
+                       struct btrfs_dir_item *di;
+                       struct btrfs_key di_key;
+                       struct inode *di_inode;
+                       struct btrfs_dir_list *new_dir_elem;
+                       int log_mode = LOG_INODE_EXISTS;
+                       int type;
+
+                       btrfs_item_key_to_cpu(leaf, &min_key, i);
+                       if (min_key.objectid != dir_elem->ino ||
+                           min_key.type != BTRFS_DIR_ITEM_KEY)
+                               goto next_dir_inode;
+
+                       di = btrfs_item_ptr(leaf, i, struct btrfs_dir_item);
+                       type = btrfs_dir_type(leaf, di);
+                       if (btrfs_dir_transid(leaf, di) < trans->transid &&
+                           type != BTRFS_FT_DIR)
+                               continue;
+                       btrfs_dir_item_key_to_cpu(leaf, di, &di_key);
+                       if (di_key.type == BTRFS_ROOT_ITEM_KEY)
+                               continue;
+
+                       di_inode = btrfs_iget(root->fs_info->sb, &di_key,
+                                             root, NULL);
+                       if (IS_ERR(di_inode)) {
+                               ret = PTR_ERR(di_inode);
+                               goto next_dir_inode;
+                       }
+
+                       if (btrfs_inode_in_log(di_inode, trans->transid)) {
+                               iput(di_inode);
+                               continue;
+                       }
+
+                       ctx->log_new_dentries = false;
+                       if (type == BTRFS_FT_DIR)
+                               log_mode = LOG_INODE_ALL;
+                       btrfs_release_path(path);
+                       ret = btrfs_log_inode(trans, root, di_inode,
+                                             log_mode, 0, LLONG_MAX, ctx);
+                       iput(di_inode);
+                       if (ret)
+                               goto next_dir_inode;
+                       if (ctx->log_new_dentries) {
+                               new_dir_elem = kmalloc(sizeof(*new_dir_elem),
+                                                      GFP_NOFS);
+                               if (!new_dir_elem) {
+                                       ret = -ENOMEM;
+                                       goto next_dir_inode;
+                               }
+                               new_dir_elem->ino = di_key.objectid;
+                               list_add_tail(&new_dir_elem->list, &dir_list);
+                       }
+                       break;
+               }
+               if (i == nritems) {
+                       ret = btrfs_next_leaf(log, path);
+                       if (ret < 0) {
+                               goto next_dir_inode;
+                       } else if (ret > 0) {
+                               ret = 0;
+                               goto next_dir_inode;
+                       }
+                       goto process_leaf;
+               }
+               if (min_key.offset < (u64)-1) {
+                       min_key.offset++;
+                       goto again;
+               }
+next_dir_inode:
+               list_del(&dir_elem->list);
+               kfree(dir_elem);
+       }
+
+       btrfs_free_path(path);
+       return ret;
+}
+
 /*
  * helper function around btrfs_log_inode to make sure newly created
  * parent directories also end up in the log.  A minimal inode and backref
@@ -4394,6 +4716,8 @@ static int btrfs_log_inode_parent(struct btrfs_trans_handle *trans,
        const struct dentry * const first_parent = parent;
        const bool did_unlink = (BTRFS_I(inode)->last_unlink_trans >
                                 last_committed);
+       bool log_dentries = false;
+       struct inode *orig_inode = inode;
 
        sb = inode->i_sb;
 
@@ -4449,11 +4773,14 @@ static int btrfs_log_inode_parent(struct btrfs_trans_handle *trans,
                goto end_trans;
        }
 
+       if (S_ISDIR(inode->i_mode) && ctx && ctx->log_new_dentries)
+               log_dentries = true;
+
        while (1) {
-               if (!parent || !parent->d_inode || sb != parent->d_inode->i_sb)
+               if (!parent || d_really_is_negative(parent) || sb != d_inode(parent)->i_sb)
                        break;
 
-               inode = parent->d_inode;
+               inode = d_inode(parent);
                if (root != BTRFS_I(inode)->root)
                        break;
 
@@ -4485,7 +4812,10 @@ static int btrfs_log_inode_parent(struct btrfs_trans_handle *trans,
                dput(old_parent);
                old_parent = parent;
        }
-       ret = 0;
+       if (log_dentries)
+               ret = log_new_dir_dentries(trans, root, orig_inode, ctx);
+       else
+               ret = 0;
 end_trans:
        dput(old_parent);
        if (ret < 0) {
@@ -4515,7 +4845,7 @@ int btrfs_log_dentry_safe(struct btrfs_trans_handle *trans,
        struct dentry *parent = dget_parent(dentry);
        int ret;
 
-       ret = btrfs_log_inode_parent(trans, root, dentry->d_inode, parent,
+       ret = btrfs_log_inode_parent(trans, root, d_inode(dentry), parent,
                                     start, end, 0, ctx);
        dput(parent);
 
index 154990c26dcbc9d63508228b9125182b7168b80e..6916a781ea02cbdff331b002949369f41113d2d1 100644 (file)
@@ -29,6 +29,7 @@ struct btrfs_log_ctx {
        int log_ret;
        int log_transid;
        int io_err;
+       bool log_new_dentries;
        struct list_head list;
 };
 
@@ -37,6 +38,7 @@ static inline void btrfs_init_log_ctx(struct btrfs_log_ctx *ctx)
        ctx->log_ret = 0;
        ctx->log_transid = 0;
        ctx->io_err = 0;
+       ctx->log_new_dentries = false;
        INIT_LIST_HEAD(&ctx->list);
 }
 
index 8222f6f74147972ba1b654c12b013c55a3b60825..96aebf3bcd5b37d35604c76ec584d29686ad34e2 100644 (file)
@@ -366,8 +366,8 @@ loop_lock:
                btrfsic_submit_bio(cur->bi_rw, cur);
                num_run++;
                batch_run++;
-               if (need_resched())
-                       cond_resched();
+
+               cond_resched();
 
                /*
                 * we made progress, there is more work to do and the bdi
@@ -400,8 +400,7 @@ loop_lock:
                                 * against it before looping
                                 */
                                last_waited = ioc->last_waited;
-                               if (need_resched())
-                                       cond_resched();
+                               cond_resched();
                                continue;
                        }
                        spin_lock(&device->io_lock);
@@ -609,8 +608,7 @@ error:
        return ERR_PTR(-ENOMEM);
 }
 
-void btrfs_close_extra_devices(struct btrfs_fs_info *fs_info,
-                              struct btrfs_fs_devices *fs_devices, int step)
+void btrfs_close_extra_devices(struct btrfs_fs_devices *fs_devices, int step)
 {
        struct btrfs_device *device, *next;
        struct btrfs_device *latest_dev = NULL;
@@ -1060,6 +1058,7 @@ static int contains_pending_extent(struct btrfs_trans_handle *trans,
        struct extent_map *em;
        struct list_head *search_list = &trans->transaction->pending_chunks;
        int ret = 0;
+       u64 physical_start = *start;
 
 again:
        list_for_each_entry(em, search_list, list) {
@@ -1070,9 +1069,9 @@ again:
                for (i = 0; i < map->num_stripes; i++) {
                        if (map->stripes[i].dev != device)
                                continue;
-                       if (map->stripes[i].physical >= *start + len ||
+                       if (map->stripes[i].physical >= physical_start + len ||
                            map->stripes[i].physical + em->orig_block_len <=
-                           *start)
+                           physical_start)
                                continue;
                        *start = map->stripes[i].physical +
                                em->orig_block_len;
@@ -1136,11 +1135,11 @@ int find_free_dev_extent(struct btrfs_trans_handle *trans,
        path = btrfs_alloc_path();
        if (!path)
                return -ENOMEM;
-again:
+
        max_hole_start = search_start;
        max_hole_size = 0;
-       hole_size = 0;
 
+again:
        if (search_start >= search_end || device->is_tgtdev_for_dev_replace) {
                ret = -ENOSPC;
                goto out;
@@ -1195,8 +1194,14 @@ again:
                         */
                        if (contains_pending_extent(trans, device,
                                                    &search_start,
-                                                   hole_size))
-                               hole_size = 0;
+                                                   hole_size)) {
+                               if (key.offset >= search_start) {
+                                       hole_size = key.offset - search_start;
+                               } else {
+                                       WARN_ON_ONCE(1);
+                                       hole_size = 0;
+                               }
+                       }
 
                        if (hole_size > max_hole_size) {
                                max_hole_start = search_start;
@@ -1233,21 +1238,23 @@ next:
         * allocated dev extents, and when shrinking the device,
         * search_end may be smaller than search_start.
         */
-       if (search_end > search_start)
+       if (search_end > search_start) {
                hole_size = search_end - search_start;
 
-       if (hole_size > max_hole_size) {
-               max_hole_start = search_start;
-               max_hole_size = hole_size;
-       }
+               if (contains_pending_extent(trans, device, &search_start,
+                                           hole_size)) {
+                       btrfs_release_path(path);
+                       goto again;
+               }
 
-       if (contains_pending_extent(trans, device, &search_start, hole_size)) {
-               btrfs_release_path(path);
-               goto again;
+               if (hole_size > max_hole_size) {
+                       max_hole_start = search_start;
+                       max_hole_size = hole_size;
+               }
        }
 
        /* See above. */
-       if (hole_size < num_bytes)
+       if (max_hole_size < num_bytes)
                ret = -ENOSPC;
        else
                ret = 0;
@@ -2487,8 +2494,7 @@ int btrfs_grow_device(struct btrfs_trans_handle *trans,
 }
 
 static int btrfs_free_chunk(struct btrfs_trans_handle *trans,
-                           struct btrfs_root *root,
-                           u64 chunk_tree, u64 chunk_objectid,
+                           struct btrfs_root *root, u64 chunk_objectid,
                            u64 chunk_offset)
 {
        int ret;
@@ -2580,7 +2586,6 @@ int btrfs_remove_chunk(struct btrfs_trans_handle *trans,
        struct map_lookup *map;
        u64 dev_extent_len = 0;
        u64 chunk_objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID;
-       u64 chunk_tree = root->fs_info->chunk_root->objectid;
        int i, ret = 0;
 
        /* Just in case */
@@ -2634,8 +2639,7 @@ int btrfs_remove_chunk(struct btrfs_trans_handle *trans,
                        }
                }
        }
-       ret = btrfs_free_chunk(trans, root, chunk_tree, chunk_objectid,
-                              chunk_offset);
+       ret = btrfs_free_chunk(trans, root, chunk_objectid, chunk_offset);
        if (ret) {
                btrfs_abort_transaction(trans, root, ret);
                goto out;
@@ -2664,8 +2668,8 @@ out:
 }
 
 static int btrfs_relocate_chunk(struct btrfs_root *root,
-                        u64 chunk_tree, u64 chunk_objectid,
-                        u64 chunk_offset)
+                               u64 chunk_objectid,
+                               u64 chunk_offset)
 {
        struct btrfs_root *extent_root;
        struct btrfs_trans_handle *trans;
@@ -2707,7 +2711,6 @@ static int btrfs_relocate_sys_chunks(struct btrfs_root *root)
        struct btrfs_chunk *chunk;
        struct btrfs_key key;
        struct btrfs_key found_key;
-       u64 chunk_tree = chunk_root->root_key.objectid;
        u64 chunk_type;
        bool retried = false;
        int failed = 0;
@@ -2744,7 +2747,7 @@ again:
                btrfs_release_path(path);
 
                if (chunk_type & BTRFS_BLOCK_GROUP_SYSTEM) {
-                       ret = btrfs_relocate_chunk(chunk_root, chunk_tree,
+                       ret = btrfs_relocate_chunk(chunk_root,
                                                   found_key.objectid,
                                                   found_key.offset);
                        if (ret == -ENOSPC)
@@ -3022,7 +3025,7 @@ static int chunk_drange_filter(struct extent_buffer *leaf,
 
                stripe_offset = btrfs_stripe_offset(leaf, stripe);
                stripe_length = btrfs_chunk_length(leaf, chunk);
-               do_div(stripe_length, factor);
+               stripe_length = div_u64(stripe_length, factor);
 
                if (stripe_offset < bargs->pend &&
                    stripe_offset + stripe_length > bargs->pstart)
@@ -3255,7 +3258,6 @@ again:
                }
 
                ret = btrfs_relocate_chunk(chunk_root,
-                                          chunk_root->root_key.objectid,
                                           found_key.objectid,
                                           found_key.offset);
                if (ret && ret != -ENOSPC)
@@ -3957,7 +3959,6 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size)
        struct btrfs_dev_extent *dev_extent = NULL;
        struct btrfs_path *path;
        u64 length;
-       u64 chunk_tree;
        u64 chunk_objectid;
        u64 chunk_offset;
        int ret;
@@ -4027,13 +4028,11 @@ again:
                        break;
                }
 
-               chunk_tree = btrfs_dev_extent_chunk_tree(l, dev_extent);
                chunk_objectid = btrfs_dev_extent_chunk_objectid(l, dev_extent);
                chunk_offset = btrfs_dev_extent_chunk_offset(l, dev_extent);
                btrfs_release_path(path);
 
-               ret = btrfs_relocate_chunk(root, chunk_tree, chunk_objectid,
-                                          chunk_offset);
+               ret = btrfs_relocate_chunk(root, chunk_objectid, chunk_offset);
                if (ret && ret != -ENOSPC)
                        goto done;
                if (ret == -ENOSPC)
@@ -4131,7 +4130,7 @@ static int btrfs_cmp_device_info(const void *a, const void *b)
        return 0;
 }
 
-static struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = {
+static const struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = {
        [BTRFS_RAID_RAID10] = {
                .sub_stripes    = 2,
                .dev_stripes    = 1,
@@ -4289,7 +4288,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
        max_chunk_size = min(div_factor(fs_devices->total_rw_bytes, 1),
                             max_chunk_size);
 
-       devices_info = kzalloc(sizeof(*devices_info) * fs_devices->rw_devices,
+       devices_info = kcalloc(fs_devices->rw_devices, sizeof(*devices_info),
                               GFP_NOFS);
        if (!devices_info)
                return -ENOMEM;
@@ -4400,8 +4399,8 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
         */
        if (stripe_size * data_stripes > max_chunk_size) {
                u64 mask = (1ULL << 24) - 1;
-               stripe_size = max_chunk_size;
-               do_div(stripe_size, data_stripes);
+
+               stripe_size = div_u64(max_chunk_size, data_stripes);
 
                /* bump the answer up to a 16MB boundary */
                stripe_size = (stripe_size + mask) & ~mask;
@@ -4413,10 +4412,10 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
                        stripe_size = devices_info[ndevs-1].max_avail;
        }
 
-       do_div(stripe_size, dev_stripes);
+       stripe_size = div_u64(stripe_size, dev_stripes);
 
        /* align to BTRFS_STRIPE_LEN */
-       do_div(stripe_size, raid_stripe_len);
+       stripe_size = div_u64(stripe_size, raid_stripe_len);
        stripe_size *= raid_stripe_len;
 
        map = kmalloc(map_lookup_size(num_stripes), GFP_NOFS);
@@ -4954,7 +4953,7 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
        u64 stripe_nr_orig;
        u64 stripe_nr_end;
        u64 stripe_len;
-       int stripe_index;
+       u32 stripe_index;
        int i;
        int ret = 0;
        int num_stripes;
@@ -4995,7 +4994,7 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
         * stripe_nr counts the total number of stripes we have to stride
         * to get to this block
         */
-       do_div(stripe_nr, stripe_len);
+       stripe_nr = div64_u64(stripe_nr, stripe_len);
 
        stripe_offset = stripe_nr * stripe_len;
        BUG_ON(offset < stripe_offset);
@@ -5011,7 +5010,8 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
                /* allow a write of a full stripe, but make sure we don't
                 * allow straddling of stripes
                 */
-               do_div(raid56_full_stripe_start, full_stripe_len);
+               raid56_full_stripe_start = div64_u64(raid56_full_stripe_start,
+                               full_stripe_len);
                raid56_full_stripe_start *= full_stripe_len;
        }
 
@@ -5136,7 +5136,7 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
        stripe_index = 0;
        stripe_nr_orig = stripe_nr;
        stripe_nr_end = ALIGN(offset + *length, map->stripe_len);
-       do_div(stripe_nr_end, map->stripe_len);
+       stripe_nr_end = div_u64(stripe_nr_end, map->stripe_len);
        stripe_end_offset = stripe_nr_end * map->stripe_len -
                            (offset + *length);
 
@@ -5144,7 +5144,8 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
                if (rw & REQ_DISCARD)
                        num_stripes = min_t(u64, map->num_stripes,
                                            stripe_nr_end - stripe_nr_orig);
-               stripe_index = do_div(stripe_nr, map->num_stripes);
+               stripe_nr = div_u64_rem(stripe_nr, map->num_stripes,
+                               &stripe_index);
                if (!(rw & (REQ_WRITE | REQ_DISCARD | REQ_GET_READ_MIRRORS)))
                        mirror_num = 1;
        } else if (map->type & BTRFS_BLOCK_GROUP_RAID1) {
@@ -5170,9 +5171,9 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
                }
 
        } else if (map->type & BTRFS_BLOCK_GROUP_RAID10) {
-               int factor = map->num_stripes / map->sub_stripes;
+               u32 factor = map->num_stripes / map->sub_stripes;
 
-               stripe_index = do_div(stripe_nr, factor);
+               stripe_nr = div_u64_rem(stripe_nr, factor, &stripe_index);
                stripe_index *= map->sub_stripes;
 
                if (rw & (REQ_WRITE | REQ_GET_READ_MIRRORS))
@@ -5198,8 +5199,8 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
                    ((rw & (REQ_WRITE | REQ_GET_READ_MIRRORS)) ||
                     mirror_num > 1)) {
                        /* push stripe_nr back to the start of the full stripe */
-                       stripe_nr = raid56_full_stripe_start;
-                       do_div(stripe_nr, stripe_len * nr_data_stripes(map));
+                       stripe_nr = div_u64(raid56_full_stripe_start,
+                                       stripe_len * nr_data_stripes(map));
 
                        /* RAID[56] write or recovery. Return all stripes */
                        num_stripes = map->num_stripes;
@@ -5209,32 +5210,32 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
                        stripe_index = 0;
                        stripe_offset = 0;
                } else {
-                       u64 tmp;
-
                        /*
                         * Mirror #0 or #1 means the original data block.
                         * Mirror #2 is RAID5 parity block.
                         * Mirror #3 is RAID6 Q block.
                         */
-                       stripe_index = do_div(stripe_nr, nr_data_stripes(map));
+                       stripe_nr = div_u64_rem(stripe_nr,
+                                       nr_data_stripes(map), &stripe_index);
                        if (mirror_num > 1)
                                stripe_index = nr_data_stripes(map) +
                                                mirror_num - 2;
 
                        /* We distribute the parity blocks across stripes */
-                       tmp = stripe_nr + stripe_index;
-                       stripe_index = do_div(tmp, map->num_stripes);
+                       div_u64_rem(stripe_nr + stripe_index, map->num_stripes,
+                                       &stripe_index);
                        if (!(rw & (REQ_WRITE | REQ_DISCARD |
                                    REQ_GET_READ_MIRRORS)) && mirror_num <= 1)
                                mirror_num = 1;
                }
        } else {
                /*
-                * after this do_div call, stripe_nr is the number of stripes
-                * on this device we have to walk to find the data, and
-                * stripe_index is the number of our device in the stripe array
+                * after this, stripe_nr is the number of stripes on this
+                * device we have to walk to find the data, and stripe_index is
+                * the number of our device in the stripe array
                 */
-               stripe_index = do_div(stripe_nr, map->num_stripes);
+               stripe_nr = div_u64_rem(stripe_nr, map->num_stripes,
+                               &stripe_index);
                mirror_num = stripe_index + 1;
        }
        BUG_ON(stripe_index >= map->num_stripes);
@@ -5261,7 +5262,7 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
            need_raid_map && ((rw & (REQ_WRITE | REQ_GET_READ_MIRRORS)) ||
            mirror_num > 1)) {
                u64 tmp;
-               int i, rot;
+               unsigned rot;
 
                bbio->raid_map = (u64 *)((void *)bbio->stripes +
                                 sizeof(struct btrfs_bio_stripe) *
@@ -5269,8 +5270,7 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
                                 sizeof(int) * tgtdev_indexes);
 
                /* Work out the disk rotation on this stripe-set */
-               tmp = stripe_nr;
-               rot = do_div(tmp, num_stripes);
+               div_u64_rem(stripe_nr, num_stripes, &rot);
 
                /* Fill in the logical address of each stripe */
                tmp = stripe_nr * nr_data_stripes(map);
@@ -5285,8 +5285,8 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
        }
 
        if (rw & REQ_DISCARD) {
-               int factor = 0;
-               int sub_stripes = 0;
+               u32 factor = 0;
+               u32 sub_stripes = 0;
                u64 stripes_per_dev = 0;
                u32 remaining_stripes = 0;
                u32 last_stripe = 0;
@@ -5437,9 +5437,7 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
                        }
                }
                if (found) {
-                       u64 length = map->stripe_len;
-
-                       if (physical_of_found + length <=
+                       if (physical_of_found + map->stripe_len <=
                            dev_replace->cursor_left) {
                                struct btrfs_bio_stripe *tgtdev_stripe =
                                        bbio->stripes + num_stripes;
@@ -5535,15 +5533,15 @@ int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree,
        rmap_len = map->stripe_len;
 
        if (map->type & BTRFS_BLOCK_GROUP_RAID10)
-               do_div(length, map->num_stripes / map->sub_stripes);
+               length = div_u64(length, map->num_stripes / map->sub_stripes);
        else if (map->type & BTRFS_BLOCK_GROUP_RAID0)
-               do_div(length, map->num_stripes);
+               length = div_u64(length, map->num_stripes);
        else if (map->type & BTRFS_BLOCK_GROUP_RAID56_MASK) {
-               do_div(length, nr_data_stripes(map));
+               length = div_u64(length, nr_data_stripes(map));
                rmap_len = map->stripe_len * nr_data_stripes(map);
        }
 
-       buf = kzalloc(sizeof(u64) * map->num_stripes, GFP_NOFS);
+       buf = kcalloc(map->num_stripes, sizeof(u64), GFP_NOFS);
        BUG_ON(!buf); /* -ENOMEM */
 
        for (i = 0; i < map->num_stripes; i++) {
@@ -5554,11 +5552,11 @@ int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree,
                        continue;
 
                stripe_nr = physical - map->stripes[i].physical;
-               do_div(stripe_nr, map->stripe_len);
+               stripe_nr = div_u64(stripe_nr, map->stripe_len);
 
                if (map->type & BTRFS_BLOCK_GROUP_RAID10) {
                        stripe_nr = stripe_nr * map->num_stripes + i;
-                       do_div(stripe_nr, map->sub_stripes);
+                       stripe_nr = div_u64(stripe_nr, map->sub_stripes);
                } else if (map->type & BTRFS_BLOCK_GROUP_RAID0) {
                        stripe_nr = stripe_nr * map->num_stripes + i;
                } /* else if RAID[56], multiply by nr_data_stripes().
@@ -5835,8 +5833,8 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,
        u64 length = 0;
        u64 map_length;
        int ret;
-       int dev_nr = 0;
-       int total_devs = 1;
+       int dev_nr;
+       int total_devs;
        struct btrfs_bio *bbio = NULL;
 
        length = bio->bi_iter.bi_size;
@@ -5877,11 +5875,10 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,
                BUG();
        }
 
-       while (dev_nr < total_devs) {
+       for (dev_nr = 0; dev_nr < total_devs; dev_nr++) {
                dev = bbio->stripes[dev_nr].dev;
                if (!dev || !dev->bdev || (rw & WRITE && !dev->writeable)) {
                        bbio_error(bbio, first_bio, logical);
-                       dev_nr++;
                        continue;
                }
 
@@ -5894,7 +5891,6 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,
                        ret = breakup_stripe_bio(root, bbio, first_bio, dev,
                                                 dev_nr, rw, async_submit);
                        BUG_ON(ret);
-                       dev_nr++;
                        continue;
                }
 
@@ -5909,7 +5905,6 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,
                submit_stripe_bio(root, bbio, bio,
                                  bbio->stripes[dev_nr].physical, dev_nr, rw,
                                  async_submit);
-               dev_nr++;
        }
        btrfs_bio_counter_dec(root->fs_info);
        return 0;
index 83069dec6898a1a024baa28b98dca3174a3959c0..ebc31331a83746b23b4e99ac146b25fc03b31cc3 100644 (file)
@@ -421,8 +421,7 @@ int btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
 int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
                          struct btrfs_fs_devices **fs_devices_ret);
 int btrfs_close_devices(struct btrfs_fs_devices *fs_devices);
-void btrfs_close_extra_devices(struct btrfs_fs_info *fs_info,
-                              struct btrfs_fs_devices *fs_devices, int step);
+void btrfs_close_extra_devices(struct btrfs_fs_devices *fs_devices, int step);
 int btrfs_find_device_missing_or_by_path(struct btrfs_root *root,
                                         char *device_path,
                                         struct btrfs_device **device);
index 883b93623bc5682ecde2684bfe936bb98fd9e51d..6f518c90e1c14b6966d80ab9202c0bff0e399686 100644 (file)
@@ -261,7 +261,7 @@ out:
 ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
 {
        struct btrfs_key key, found_key;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct btrfs_path *path;
        struct extent_buffer *leaf;
@@ -364,22 +364,42 @@ const struct xattr_handler *btrfs_xattr_handlers[] = {
 /*
  * Check if the attribute is in a supported namespace.
  *
- * This applied after the check for the synthetic attributes in the system
+ * This is applied after the check for the synthetic attributes in the system
  * namespace.
  */
-static bool btrfs_is_valid_xattr(const char *name)
+static int btrfs_is_valid_xattr(const char *name)
 {
-       return !strncmp(name, XATTR_SECURITY_PREFIX,
-                       XATTR_SECURITY_PREFIX_LEN) ||
-              !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) ||
-              !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) ||
-              !strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) ||
-               !strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN);
+       int len = strlen(name);
+       int prefixlen = 0;
+
+       if (!strncmp(name, XATTR_SECURITY_PREFIX,
+                       XATTR_SECURITY_PREFIX_LEN))
+               prefixlen = XATTR_SECURITY_PREFIX_LEN;
+       else if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
+               prefixlen = XATTR_SYSTEM_PREFIX_LEN;
+       else if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN))
+               prefixlen = XATTR_TRUSTED_PREFIX_LEN;
+       else if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
+               prefixlen = XATTR_USER_PREFIX_LEN;
+       else if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN))
+               prefixlen = XATTR_BTRFS_PREFIX_LEN;
+       else
+               return -EOPNOTSUPP;
+
+       /*
+        * The name cannot consist of just prefix
+        */
+       if (len <= prefixlen)
+               return -EINVAL;
+
+       return 0;
 }
 
 ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
                       void *buffer, size_t size)
 {
+       int ret;
+
        /*
         * If this is a request for a synthetic attribute in the system.*
         * namespace use the generic infrastructure to resolve a handler
@@ -388,15 +408,17 @@ ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
        if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
                return generic_getxattr(dentry, name, buffer, size);
 
-       if (!btrfs_is_valid_xattr(name))
-               return -EOPNOTSUPP;
-       return __btrfs_getxattr(dentry->d_inode, name, buffer, size);
+       ret = btrfs_is_valid_xattr(name);
+       if (ret)
+               return ret;
+       return __btrfs_getxattr(d_inode(dentry), name, buffer, size);
 }
 
 int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
                   size_t size, int flags)
 {
-       struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root;
+       struct btrfs_root *root = BTRFS_I(d_inode(dentry))->root;
+       int ret;
 
        /*
         * The permission on security.* and system.* is not checked
@@ -413,23 +435,25 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
        if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
                return generic_setxattr(dentry, name, value, size, flags);
 
-       if (!btrfs_is_valid_xattr(name))
-               return -EOPNOTSUPP;
+       ret = btrfs_is_valid_xattr(name);
+       if (ret)
+               return ret;
 
        if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN))
-               return btrfs_set_prop(dentry->d_inode, name,
+               return btrfs_set_prop(d_inode(dentry), name,
                                      value, size, flags);
 
        if (size == 0)
                value = "";  /* empty EA, do not remove */
 
-       return __btrfs_setxattr(NULL, dentry->d_inode, name, value, size,
+       return __btrfs_setxattr(NULL, d_inode(dentry), name, value, size,
                                flags);
 }
 
 int btrfs_removexattr(struct dentry *dentry, const char *name)
 {
-       struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root;
+       struct btrfs_root *root = BTRFS_I(d_inode(dentry))->root;
+       int ret;
 
        /*
         * The permission on security.* and system.* is not checked
@@ -446,14 +470,15 @@ int btrfs_removexattr(struct dentry *dentry, const char *name)
        if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
                return generic_removexattr(dentry, name);
 
-       if (!btrfs_is_valid_xattr(name))
-               return -EOPNOTSUPP;
+       ret = btrfs_is_valid_xattr(name);
+       if (ret)
+               return ret;
 
        if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN))
-               return btrfs_set_prop(dentry->d_inode, name,
+               return btrfs_set_prop(d_inode(dentry), name,
                                      NULL, 0, XATTR_REPLACE);
 
-       return __btrfs_setxattr(NULL, dentry->d_inode, name, NULL, 0,
+       return __btrfs_setxattr(NULL, d_inode(dentry), name, NULL, 0,
                                XATTR_REPLACE);
 }
 
index fb22fd8d8fb8fad73cb4d2b63d4d525da3eea876..82990b8f872b6d455be25196ee88a97eb82bd932 100644 (file)
@@ -403,7 +403,7 @@ next:
        return ret;
 }
 
-struct btrfs_compress_op btrfs_zlib_compress = {
+const struct btrfs_compress_op btrfs_zlib_compress = {
        .alloc_workspace        = zlib_alloc_workspace,
        .free_workspace         = zlib_free_workspace,
        .compress_pages         = zlib_compress_pages,
index fbb08e97438d36eb0bc783386bf68d1521fb9a81..6af790fc3df8a163249b7863d443fc7ab2ae4e9d 100644 (file)
@@ -123,11 +123,11 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
 
        /* check parameters */
        ret = -EOPNOTSUPP;
-       if (!root->d_inode ||
-           !root->d_inode->i_op->lookup ||
-           !root->d_inode->i_op->mkdir ||
-           !root->d_inode->i_op->setxattr ||
-           !root->d_inode->i_op->getxattr ||
+       if (d_is_negative(root) ||
+           !d_backing_inode(root)->i_op->lookup ||
+           !d_backing_inode(root)->i_op->mkdir ||
+           !d_backing_inode(root)->i_op->setxattr ||
+           !d_backing_inode(root)->i_op->getxattr ||
            !root->d_sb->s_op->statfs ||
            !root->d_sb->s_op->sync_fs)
                goto error_unsupported;
index 232426214fdd1849b21a4e3c080563e2132e8bd2..afa023dded5be937ddd713847b37f2d165f586be 100644 (file)
@@ -441,12 +441,12 @@ static int cachefiles_attr_changed(struct fscache_object *_object)
 
        fscache_set_store_limit(&object->fscache, ni_size);
 
-       oi_size = i_size_read(object->backer->d_inode);
+       oi_size = i_size_read(d_backing_inode(object->backer));
        if (oi_size == ni_size)
                return 0;
 
        cachefiles_begin_secure(cache, &saved_cred);
-       mutex_lock(&object->backer->d_inode->i_mutex);
+       mutex_lock(&d_inode(object->backer)->i_mutex);
 
        /* if there's an extension to a partial page at the end of the backing
         * file, we need to discard the partial page so that we pick up new
@@ -465,7 +465,7 @@ static int cachefiles_attr_changed(struct fscache_object *_object)
        ret = notify_change(object->backer, &newattrs, NULL);
 
 truncate_failed:
-       mutex_unlock(&object->backer->d_inode->i_mutex);
+       mutex_unlock(&d_inode(object->backer)->i_mutex);
        cachefiles_end_secure(cache, saved_cred);
 
        if (ret == -EIO) {
index 1e51714eb33e15f5e6624699021d26d95e1c16aa..ab857ab9f40d91a375a31030e1872f9ebd704837 100644 (file)
@@ -286,13 +286,13 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
                if (ret < 0) {
                        cachefiles_io_error(cache, "Unlink security error");
                } else {
-                       ret = vfs_unlink(dir->d_inode, rep, NULL);
+                       ret = vfs_unlink(d_inode(dir), rep, NULL);
 
                        if (preemptive)
                                cachefiles_mark_object_buried(cache, rep);
                }
 
-               mutex_unlock(&dir->d_inode->i_mutex);
+               mutex_unlock(&d_inode(dir)->i_mutex);
 
                if (ret == -EIO)
                        cachefiles_io_error(cache, "Unlink failed");
@@ -303,7 +303,7 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
 
        /* directories have to be moved to the graveyard */
        _debug("move stale object to graveyard");
-       mutex_unlock(&dir->d_inode->i_mutex);
+       mutex_unlock(&d_inode(dir)->i_mutex);
 
 try_again:
        /* first step is to make up a grave dentry in the graveyard */
@@ -355,7 +355,7 @@ try_again:
                return -EIO;
        }
 
-       if (grave->d_inode) {
+       if (d_is_positive(grave)) {
                unlock_rename(cache->graveyard, dir);
                dput(grave);
                grave = NULL;
@@ -387,8 +387,8 @@ try_again:
        if (ret < 0) {
                cachefiles_io_error(cache, "Rename security error %d", ret);
        } else {
-               ret = vfs_rename(dir->d_inode, rep,
-                                cache->graveyard->d_inode, grave, NULL, 0);
+               ret = vfs_rename(d_inode(dir), rep,
+                                d_inode(cache->graveyard), grave, NULL, 0);
                if (ret != 0 && ret != -ENOMEM)
                        cachefiles_io_error(cache,
                                            "Rename failed with error %d", ret);
@@ -415,18 +415,18 @@ int cachefiles_delete_object(struct cachefiles_cache *cache,
        _enter(",OBJ%x{%p}", object->fscache.debug_id, object->dentry);
 
        ASSERT(object->dentry);
-       ASSERT(object->dentry->d_inode);
+       ASSERT(d_backing_inode(object->dentry));
        ASSERT(object->dentry->d_parent);
 
        dir = dget_parent(object->dentry);
 
-       mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
+       mutex_lock_nested(&d_inode(dir)->i_mutex, I_MUTEX_PARENT);
 
        if (test_bit(CACHEFILES_OBJECT_BURIED, &object->flags)) {
                /* object allocation for the same key preemptively deleted this
                 * object's file so that it could create its own file */
                _debug("object preemptively buried");
-               mutex_unlock(&dir->d_inode->i_mutex);
+               mutex_unlock(&d_inode(dir)->i_mutex);
                ret = 0;
        } else {
                /* we need to check that our parent is _still_ our parent - it
@@ -438,7 +438,7 @@ int cachefiles_delete_object(struct cachefiles_cache *cache,
                        /* it got moved, presumably by cachefilesd culling it,
                         * so it's no longer in the key path and we can ignore
                         * it */
-                       mutex_unlock(&dir->d_inode->i_mutex);
+                       mutex_unlock(&d_inode(dir)->i_mutex);
                        ret = 0;
                }
        }
@@ -473,7 +473,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,
        path.mnt = cache->mnt;
 
        ASSERT(parent->dentry);
-       ASSERT(parent->dentry->d_inode);
+       ASSERT(d_backing_inode(parent->dentry));
 
        if (!(d_is_dir(parent->dentry))) {
                // TODO: convert file to dir
@@ -497,7 +497,7 @@ lookup_again:
        /* search the current directory for the element name */
        _debug("lookup '%s'", name);
 
-       mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
+       mutex_lock_nested(&d_inode(dir)->i_mutex, I_MUTEX_PARENT);
 
        start = jiffies;
        next = lookup_one_len(name, dir, nlen);
@@ -505,21 +505,21 @@ lookup_again:
        if (IS_ERR(next))
                goto lookup_error;
 
-       _debug("next -> %p %s", next, next->d_inode ? "positive" : "negative");
+       _debug("next -> %p %s", next, d_backing_inode(next) ? "positive" : "negative");
 
        if (!key)
-               object->new = !next->d_inode;
+               object->new = !d_backing_inode(next);
 
        /* if this element of the path doesn't exist, then the lookup phase
         * failed, and we can release any readers in the certain knowledge that
         * there's nothing for them to actually read */
-       if (!next->d_inode)
+       if (d_is_negative(next))
                fscache_object_lookup_negative(&object->fscache);
 
        /* we need to create the object if it's negative */
        if (key || object->type == FSCACHE_COOKIE_TYPE_INDEX) {
                /* index objects and intervening tree levels must be subdirs */
-               if (!next->d_inode) {
+               if (d_is_negative(next)) {
                        ret = cachefiles_has_space(cache, 1, 0);
                        if (ret < 0)
                                goto create_error;
@@ -529,26 +529,26 @@ lookup_again:
                        if (ret < 0)
                                goto create_error;
                        start = jiffies;
-                       ret = vfs_mkdir(dir->d_inode, next, 0);
+                       ret = vfs_mkdir(d_inode(dir), next, 0);
                        cachefiles_hist(cachefiles_mkdir_histogram, start);
                        if (ret < 0)
                                goto create_error;
 
-                       ASSERT(next->d_inode);
+                       ASSERT(d_backing_inode(next));
 
                        _debug("mkdir -> %p{%p{ino=%lu}}",
-                              next, next->d_inode, next->d_inode->i_ino);
+                              next, d_backing_inode(next), d_backing_inode(next)->i_ino);
 
                } else if (!d_can_lookup(next)) {
                        pr_err("inode %lu is not a directory\n",
-                              next->d_inode->i_ino);
+                              d_backing_inode(next)->i_ino);
                        ret = -ENOBUFS;
                        goto error;
                }
 
        } else {
                /* non-index objects start out life as files */
-               if (!next->d_inode) {
+               if (d_is_negative(next)) {
                        ret = cachefiles_has_space(cache, 1, 0);
                        if (ret < 0)
                                goto create_error;
@@ -558,21 +558,21 @@ lookup_again:
                        if (ret < 0)
                                goto create_error;
                        start = jiffies;
-                       ret = vfs_create(dir->d_inode, next, S_IFREG, true);
+                       ret = vfs_create(d_inode(dir), next, S_IFREG, true);
                        cachefiles_hist(cachefiles_create_histogram, start);
                        if (ret < 0)
                                goto create_error;
 
-                       ASSERT(next->d_inode);
+                       ASSERT(d_backing_inode(next));
 
                        _debug("create -> %p{%p{ino=%lu}}",
-                              next, next->d_inode, next->d_inode->i_ino);
+                              next, d_backing_inode(next), d_backing_inode(next)->i_ino);
 
                } else if (!d_can_lookup(next) &&
                           !d_is_reg(next)
                           ) {
                        pr_err("inode %lu is not a file or directory\n",
-                              next->d_inode->i_ino);
+                              d_backing_inode(next)->i_ino);
                        ret = -ENOBUFS;
                        goto error;
                }
@@ -581,7 +581,7 @@ lookup_again:
        /* process the next component */
        if (key) {
                _debug("advance");
-               mutex_unlock(&dir->d_inode->i_mutex);
+               mutex_unlock(&d_inode(dir)->i_mutex);
                dput(dir);
                dir = next;
                next = NULL;
@@ -617,7 +617,7 @@ lookup_again:
        /* note that we're now using this object */
        ret = cachefiles_mark_object_active(cache, object);
 
-       mutex_unlock(&dir->d_inode->i_mutex);
+       mutex_unlock(&d_inode(dir)->i_mutex);
        dput(dir);
        dir = NULL;
 
@@ -646,7 +646,7 @@ lookup_again:
                        const struct address_space_operations *aops;
 
                        ret = -EPERM;
-                       aops = object->dentry->d_inode->i_mapping->a_ops;
+                       aops = d_backing_inode(object->dentry)->i_mapping->a_ops;
                        if (!aops->bmap)
                                goto check_error;
 
@@ -659,7 +659,7 @@ lookup_again:
        object->new = 0;
        fscache_obtained_object(&object->fscache);
 
-       _leave(" = 0 [%lu]", object->dentry->d_inode->i_ino);
+       _leave(" = 0 [%lu]", d_backing_inode(object->dentry)->i_ino);
        return 0;
 
 create_error:
@@ -695,7 +695,7 @@ lookup_error:
                cachefiles_io_error(cache, "Lookup failed");
        next = NULL;
 error:
-       mutex_unlock(&dir->d_inode->i_mutex);
+       mutex_unlock(&d_inode(dir)->i_mutex);
        dput(next);
 error_out2:
        dput(dir);
@@ -719,7 +719,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
        _enter(",,%s", dirname);
 
        /* search the current directory for the element name */
-       mutex_lock(&dir->d_inode->i_mutex);
+       mutex_lock(&d_inode(dir)->i_mutex);
 
        start = jiffies;
        subdir = lookup_one_len(dirname, dir, strlen(dirname));
@@ -731,10 +731,10 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
        }
 
        _debug("subdir -> %p %s",
-              subdir, subdir->d_inode ? "positive" : "negative");
+              subdir, d_backing_inode(subdir) ? "positive" : "negative");
 
        /* we need to create the subdir if it doesn't exist yet */
-       if (!subdir->d_inode) {
+       if (d_is_negative(subdir)) {
                ret = cachefiles_has_space(cache, 1, 0);
                if (ret < 0)
                        goto mkdir_error;
@@ -746,22 +746,22 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
                ret = security_path_mkdir(&path, subdir, 0700);
                if (ret < 0)
                        goto mkdir_error;
-               ret = vfs_mkdir(dir->d_inode, subdir, 0700);
+               ret = vfs_mkdir(d_inode(dir), subdir, 0700);
                if (ret < 0)
                        goto mkdir_error;
 
-               ASSERT(subdir->d_inode);
+               ASSERT(d_backing_inode(subdir));
 
                _debug("mkdir -> %p{%p{ino=%lu}}",
                       subdir,
-                      subdir->d_inode,
-                      subdir->d_inode->i_ino);
+                      d_backing_inode(subdir),
+                      d_backing_inode(subdir)->i_ino);
        }
 
-       mutex_unlock(&dir->d_inode->i_mutex);
+       mutex_unlock(&d_inode(dir)->i_mutex);
 
        /* we need to make sure the subdir is a directory */
-       ASSERT(subdir->d_inode);
+       ASSERT(d_backing_inode(subdir));
 
        if (!d_can_lookup(subdir)) {
                pr_err("%s is not a directory\n", dirname);
@@ -770,18 +770,18 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
        }
 
        ret = -EPERM;
-       if (!subdir->d_inode->i_op->setxattr ||
-           !subdir->d_inode->i_op->getxattr ||
-           !subdir->d_inode->i_op->lookup ||
-           !subdir->d_inode->i_op->mkdir ||
-           !subdir->d_inode->i_op->create ||
-           (!subdir->d_inode->i_op->rename &&
-            !subdir->d_inode->i_op->rename2) ||
-           !subdir->d_inode->i_op->rmdir ||
-           !subdir->d_inode->i_op->unlink)
+       if (!d_backing_inode(subdir)->i_op->setxattr ||
+           !d_backing_inode(subdir)->i_op->getxattr ||
+           !d_backing_inode(subdir)->i_op->lookup ||
+           !d_backing_inode(subdir)->i_op->mkdir ||
+           !d_backing_inode(subdir)->i_op->create ||
+           (!d_backing_inode(subdir)->i_op->rename &&
+            !d_backing_inode(subdir)->i_op->rename2) ||
+           !d_backing_inode(subdir)->i_op->rmdir ||
+           !d_backing_inode(subdir)->i_op->unlink)
                goto check_error;
 
-       _leave(" = [%lu]", subdir->d_inode->i_ino);
+       _leave(" = [%lu]", d_backing_inode(subdir)->i_ino);
        return subdir;
 
 check_error:
@@ -790,19 +790,19 @@ check_error:
        return ERR_PTR(ret);
 
 mkdir_error:
-       mutex_unlock(&dir->d_inode->i_mutex);
+       mutex_unlock(&d_inode(dir)->i_mutex);
        dput(subdir);
        pr_err("mkdir %s failed with error %d\n", dirname, ret);
        return ERR_PTR(ret);
 
 lookup_error:
-       mutex_unlock(&dir->d_inode->i_mutex);
+       mutex_unlock(&d_inode(dir)->i_mutex);
        ret = PTR_ERR(subdir);
        pr_err("Lookup %s failed with error %d\n", dirname, ret);
        return ERR_PTR(ret);
 
 nomem_d_alloc:
-       mutex_unlock(&dir->d_inode->i_mutex);
+       mutex_unlock(&d_inode(dir)->i_mutex);
        _leave(" = -ENOMEM");
        return ERR_PTR(-ENOMEM);
 }
@@ -827,7 +827,7 @@ static struct dentry *cachefiles_check_active(struct cachefiles_cache *cache,
        //       dir, filename);
 
        /* look up the victim */
-       mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
+       mutex_lock_nested(&d_inode(dir)->i_mutex, I_MUTEX_PARENT);
 
        start = jiffies;
        victim = lookup_one_len(filename, dir, strlen(filename));
@@ -836,13 +836,13 @@ static struct dentry *cachefiles_check_active(struct cachefiles_cache *cache,
                goto lookup_error;
 
        //_debug("victim -> %p %s",
-       //       victim, victim->d_inode ? "positive" : "negative");
+       //       victim, d_backing_inode(victim) ? "positive" : "negative");
 
        /* if the object is no longer there then we probably retired the object
         * at the netfs's request whilst the cull was in progress
         */
-       if (!victim->d_inode) {
-               mutex_unlock(&dir->d_inode->i_mutex);
+       if (d_is_negative(victim)) {
+               mutex_unlock(&d_inode(dir)->i_mutex);
                dput(victim);
                _leave(" = -ENOENT [absent]");
                return ERR_PTR(-ENOENT);
@@ -871,13 +871,13 @@ static struct dentry *cachefiles_check_active(struct cachefiles_cache *cache,
 
 object_in_use:
        read_unlock(&cache->active_lock);
-       mutex_unlock(&dir->d_inode->i_mutex);
+       mutex_unlock(&d_inode(dir)->i_mutex);
        dput(victim);
        //_leave(" = -EBUSY [in use]");
        return ERR_PTR(-EBUSY);
 
 lookup_error:
-       mutex_unlock(&dir->d_inode->i_mutex);
+       mutex_unlock(&d_inode(dir)->i_mutex);
        ret = PTR_ERR(victim);
        if (ret == -ENOENT) {
                /* file or dir now absent - probably retired by netfs */
@@ -913,7 +913,7 @@ int cachefiles_cull(struct cachefiles_cache *cache, struct dentry *dir,
                return PTR_ERR(victim);
 
        _debug("victim -> %p %s",
-              victim, victim->d_inode ? "positive" : "negative");
+              victim, d_backing_inode(victim) ? "positive" : "negative");
 
        /* okay... the victim is not being used so we can cull it
         * - start by marking it as stale
@@ -936,7 +936,7 @@ int cachefiles_cull(struct cachefiles_cache *cache, struct dentry *dir,
        return 0;
 
 error_unlock:
-       mutex_unlock(&dir->d_inode->i_mutex);
+       mutex_unlock(&d_inode(dir)->i_mutex);
 error:
        dput(victim);
        if (ret == -ENOENT) {
@@ -971,7 +971,7 @@ int cachefiles_check_in_use(struct cachefiles_cache *cache, struct dentry *dir,
        if (IS_ERR(victim))
                return PTR_ERR(victim);
 
-       mutex_unlock(&dir->d_inode->i_mutex);
+       mutex_unlock(&d_inode(dir)->i_mutex);
        dput(victim);
        //_leave(" = 0");
        return 0;
index c6cd8d7a4eef91b379efc75888a94eba6345ac33..3cbb0e834694131d461c927fddb2340b72755415 100644 (file)
@@ -74,12 +74,12 @@ static int cachefiles_read_waiter(wait_queue_t *wait, unsigned mode,
 static int cachefiles_read_reissue(struct cachefiles_object *object,
                                   struct cachefiles_one_read *monitor)
 {
-       struct address_space *bmapping = object->backer->d_inode->i_mapping;
+       struct address_space *bmapping = d_backing_inode(object->backer)->i_mapping;
        struct page *backpage = monitor->back_page, *backpage2;
        int ret;
 
        _enter("{ino=%lx},{%lx,%lx}",
-              object->backer->d_inode->i_ino,
+              d_backing_inode(object->backer)->i_ino,
               backpage->index, backpage->flags);
 
        /* skip if the page was truncated away completely */
@@ -157,7 +157,7 @@ static void cachefiles_read_copier(struct fscache_operation *_op)
        object = container_of(op->op.object,
                              struct cachefiles_object, fscache);
 
-       _enter("{ino=%lu}", object->backer->d_inode->i_ino);
+       _enter("{ino=%lu}", d_backing_inode(object->backer)->i_ino);
 
        max = 8;
        spin_lock_irq(&object->work_lock);
@@ -247,7 +247,7 @@ static int cachefiles_read_backing_file_one(struct cachefiles_object *object,
        init_waitqueue_func_entry(&monitor->monitor, cachefiles_read_waiter);
 
        /* attempt to get hold of the backing page */
-       bmapping = object->backer->d_inode->i_mapping;
+       bmapping = d_backing_inode(object->backer)->i_mapping;
        newpage = NULL;
 
        for (;;) {
@@ -408,7 +408,7 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op,
        if (!object->backer)
                goto enobufs;
 
-       inode = object->backer->d_inode;
+       inode = d_backing_inode(object->backer);
        ASSERT(S_ISREG(inode->i_mode));
        ASSERT(inode->i_mapping->a_ops->bmap);
        ASSERT(inode->i_mapping->a_ops->readpages);
@@ -468,7 +468,7 @@ static int cachefiles_read_backing_file(struct cachefiles_object *object,
                                        struct list_head *list)
 {
        struct cachefiles_one_read *monitor = NULL;
-       struct address_space *bmapping = object->backer->d_inode->i_mapping;
+       struct address_space *bmapping = d_backing_inode(object->backer)->i_mapping;
        struct page *newpage = NULL, *netpage, *_n, *backpage = NULL;
        int ret = 0;
 
@@ -705,7 +705,7 @@ int cachefiles_read_or_alloc_pages(struct fscache_retrieval *op,
        if (cachefiles_has_space(cache, 0, *nr_pages) < 0)
                space = 0;
 
-       inode = object->backer->d_inode;
+       inode = d_backing_inode(object->backer);
        ASSERT(S_ISREG(inode->i_mode));
        ASSERT(inode->i_mapping->a_ops->bmap);
        ASSERT(inode->i_mapping->a_ops->readpages);
index 396c18ea2764116cd9aade503f11348b16c59b11..31bbc0528b1173fcc56cd4e74863d8eb106d1f8a 100644 (file)
@@ -55,14 +55,14 @@ static int cachefiles_check_cache_dir(struct cachefiles_cache *cache,
 {
        int ret;
 
-       ret = security_inode_mkdir(root->d_inode, root, 0);
+       ret = security_inode_mkdir(d_backing_inode(root), root, 0);
        if (ret < 0) {
                pr_err("Security denies permission to make dirs: error %d",
                       ret);
                return ret;
        }
 
-       ret = security_inode_create(root->d_inode, root, 0);
+       ret = security_inode_create(d_backing_inode(root), root, 0);
        if (ret < 0)
                pr_err("Security denies permission to create files: error %d",
                       ret);
@@ -95,7 +95,7 @@ int cachefiles_determine_cache_security(struct cachefiles_cache *cache,
 
        /* use the cache root dir's security context as the basis with
         * which create files */
-       ret = set_create_files_as(new, root->d_inode);
+       ret = set_create_files_as(new, d_backing_inode(root));
        if (ret < 0) {
                abort_creds(new);
                cachefiles_begin_secure(cache, _saved_cred);
index a8a68745e11d45b0c093501e359d1190546f788b..d31c1a72d8a5ba90255ff7537a824b9c8036b749 100644 (file)
@@ -33,7 +33,7 @@ int cachefiles_check_object_type(struct cachefiles_object *object)
        int ret;
 
        ASSERT(dentry);
-       ASSERT(dentry->d_inode);
+       ASSERT(d_backing_inode(dentry));
 
        if (!object->fscache.cookie)
                strcpy(type, "C3");
@@ -52,7 +52,7 @@ int cachefiles_check_object_type(struct cachefiles_object *object)
 
        if (ret != -EEXIST) {
                pr_err("Can't set xattr on %pd [%lu] (err %d)\n",
-                      dentry, dentry->d_inode->i_ino,
+                      dentry, d_backing_inode(dentry)->i_ino,
                       -ret);
                goto error;
        }
@@ -64,7 +64,7 @@ int cachefiles_check_object_type(struct cachefiles_object *object)
                        goto bad_type_length;
 
                pr_err("Can't read xattr on %pd [%lu] (err %d)\n",
-                      dentry, dentry->d_inode->i_ino,
+                      dentry, d_backing_inode(dentry)->i_ino,
                       -ret);
                goto error;
        }
@@ -84,14 +84,14 @@ error:
 
 bad_type_length:
        pr_err("Cache object %lu type xattr length incorrect\n",
-              dentry->d_inode->i_ino);
+              d_backing_inode(dentry)->i_ino);
        ret = -EIO;
        goto error;
 
 bad_type:
        xtype[2] = 0;
        pr_err("Cache object %pd [%lu] type %s not %s\n",
-              dentry, dentry->d_inode->i_ino,
+              dentry, d_backing_inode(dentry)->i_ino,
               xtype, type);
        ret = -EIO;
        goto error;
@@ -165,7 +165,7 @@ int cachefiles_check_auxdata(struct cachefiles_object *object)
        int ret;
 
        ASSERT(dentry);
-       ASSERT(dentry->d_inode);
+       ASSERT(d_backing_inode(dentry));
        ASSERT(object->fscache.cookie->def->check_aux);
 
        auxbuf = kmalloc(sizeof(struct cachefiles_xattr) + 512, GFP_KERNEL);
@@ -204,7 +204,7 @@ int cachefiles_check_object_xattr(struct cachefiles_object *object,
        _enter("%p,#%d", object, auxdata->len);
 
        ASSERT(dentry);
-       ASSERT(dentry->d_inode);
+       ASSERT(d_backing_inode(dentry));
 
        auxbuf = kmalloc(sizeof(struct cachefiles_xattr) + 512, cachefiles_gfp);
        if (!auxbuf) {
@@ -225,7 +225,7 @@ int cachefiles_check_object_xattr(struct cachefiles_object *object,
 
                cachefiles_io_error_obj(object,
                                        "Can't read xattr on %lu (err %d)",
-                                       dentry->d_inode->i_ino, -ret);
+                                       d_backing_inode(dentry)->i_ino, -ret);
                goto error;
        }
 
@@ -276,7 +276,7 @@ int cachefiles_check_object_xattr(struct cachefiles_object *object,
                        cachefiles_io_error_obj(object,
                                                "Can't update xattr on %lu"
                                                " (error %d)",
-                                               dentry->d_inode->i_ino, -ret);
+                                               d_backing_inode(dentry)->i_ino, -ret);
                        goto error;
                }
        }
@@ -291,7 +291,7 @@ error:
 
 bad_type_length:
        pr_err("Cache object %lu xattr length incorrect\n",
-              dentry->d_inode->i_ino);
+              d_backing_inode(dentry)->i_ino);
        ret = -EIO;
        goto error;
 
@@ -316,7 +316,7 @@ int cachefiles_remove_object_xattr(struct cachefiles_cache *cache,
                        cachefiles_io_error(cache,
                                            "Can't remove xattr from %lu"
                                            " (error %d)",
-                                           dentry->d_inode->i_ino, -ret);
+                                           d_backing_inode(dentry)->i_ino, -ret);
        }
 
        _leave(" = %d", ret);
index 155ab9c0246b202aed75e3db02313369fab52976..e162bcd105ee2d98c2dcd12e80c75ee729a7a951 100644 (file)
@@ -1146,6 +1146,10 @@ static int ceph_write_begin(struct file *file, struct address_space *mapping,
                     inode, page, (int)pos, (int)len);
 
                r = ceph_update_writeable_page(file, pos, len, page);
+               if (r < 0)
+                       page_cache_release(page);
+               else
+                       *pagep = page;
        } while (r == -EAGAIN);
 
        return r;
@@ -1534,19 +1538,27 @@ int ceph_uninline_data(struct file *filp, struct page *locked_page)
 
        osd_req_op_extent_osd_data_pages(req, 1, &page, len, 0, false, false);
 
-       err = osd_req_op_xattr_init(req, 0, CEPH_OSD_OP_CMPXATTR,
-                                   "inline_version", &inline_version,
-                                   sizeof(inline_version),
-                                   CEPH_OSD_CMPXATTR_OP_GT,
-                                   CEPH_OSD_CMPXATTR_MODE_U64);
-       if (err)
-               goto out_put;
-
-       err = osd_req_op_xattr_init(req, 2, CEPH_OSD_OP_SETXATTR,
-                                   "inline_version", &inline_version,
-                                   sizeof(inline_version), 0, 0);
-       if (err)
-               goto out_put;
+       {
+               __le64 xattr_buf = cpu_to_le64(inline_version);
+               err = osd_req_op_xattr_init(req, 0, CEPH_OSD_OP_CMPXATTR,
+                                           "inline_version", &xattr_buf,
+                                           sizeof(xattr_buf),
+                                           CEPH_OSD_CMPXATTR_OP_GT,
+                                           CEPH_OSD_CMPXATTR_MODE_U64);
+               if (err)
+                       goto out_put;
+       }
+
+       {
+               char xattr_buf[32];
+               int xattr_len = snprintf(xattr_buf, sizeof(xattr_buf),
+                                        "%llu", inline_version);
+               err = osd_req_op_xattr_init(req, 2, CEPH_OSD_OP_SETXATTR,
+                                           "inline_version",
+                                           xattr_buf, xattr_len, 0, 0);
+               if (err)
+                       goto out_put;
+       }
 
        ceph_osdc_build_request(req, 0, NULL, CEPH_NOSNAP, &inode->i_mtime);
        err = ceph_osdc_start_request(&fsc->client->osdc, req, false);
index 8172775428a0b9165e68d293d23812a3f2be1593..be5ea6af8366479b675e81e1d13e96139abed2c4 100644 (file)
@@ -896,6 +896,18 @@ int ceph_is_any_caps(struct inode *inode)
        return ret;
 }
 
+static void drop_inode_snap_realm(struct ceph_inode_info *ci)
+{
+       struct ceph_snap_realm *realm = ci->i_snap_realm;
+       spin_lock(&realm->inodes_with_caps_lock);
+       list_del_init(&ci->i_snap_realm_item);
+       ci->i_snap_realm_counter++;
+       ci->i_snap_realm = NULL;
+       spin_unlock(&realm->inodes_with_caps_lock);
+       ceph_put_snap_realm(ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc,
+                           realm);
+}
+
 /*
  * Remove a cap.  Take steps to deal with a racing iterate_session_caps.
  *
@@ -946,15 +958,13 @@ void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release)
        if (removed)
                ceph_put_cap(mdsc, cap);
 
-       if (!__ceph_is_any_caps(ci) && ci->i_snap_realm) {
-               struct ceph_snap_realm *realm = ci->i_snap_realm;
-               spin_lock(&realm->inodes_with_caps_lock);
-               list_del_init(&ci->i_snap_realm_item);
-               ci->i_snap_realm_counter++;
-               ci->i_snap_realm = NULL;
-               spin_unlock(&realm->inodes_with_caps_lock);
-               ceph_put_snap_realm(mdsc, realm);
-       }
+       /* when reconnect denied, we remove session caps forcibly,
+        * i_wr_ref can be non-zero. If there are ongoing write,
+        * keep i_snap_realm.
+        */
+       if (!__ceph_is_any_caps(ci) && ci->i_wr_ref == 0 && ci->i_snap_realm)
+               drop_inode_snap_realm(ci);
+
        if (!__ceph_is_any_real_caps(ci))
                __cap_delay_cancel(mdsc, ci);
 }
@@ -1394,6 +1404,13 @@ int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask)
        int was = ci->i_dirty_caps;
        int dirty = 0;
 
+       if (!ci->i_auth_cap) {
+               pr_warn("__mark_dirty_caps %p %llx mask %s, "
+                       "but no auth cap (session was closed?)\n",
+                       inode, ceph_ino(inode), ceph_cap_string(mask));
+               return 0;
+       }
+
        dout("__mark_dirty_caps %p %s dirty %s -> %s\n", &ci->vfs_inode,
             ceph_cap_string(mask), ceph_cap_string(was),
             ceph_cap_string(was | mask));
@@ -1404,7 +1421,6 @@ int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask)
                                ci->i_snap_realm->cached_context);
                dout(" inode %p now dirty snapc %p auth cap %p\n",
                     &ci->vfs_inode, ci->i_head_snapc, ci->i_auth_cap);
-               WARN_ON(!ci->i_auth_cap);
                BUG_ON(!list_empty(&ci->i_dirty_item));
                spin_lock(&mdsc->cap_dirty_lock);
                list_add(&ci->i_dirty_item, &mdsc->cap_dirty);
@@ -1545,7 +1561,19 @@ retry_locked:
        if (!mdsc->stopping && inode->i_nlink > 0) {
                if (want) {
                        retain |= CEPH_CAP_ANY;       /* be greedy */
+               } else if (S_ISDIR(inode->i_mode) &&
+                          (issued & CEPH_CAP_FILE_SHARED) &&
+                           __ceph_dir_is_complete(ci)) {
+                       /*
+                        * If a directory is complete, we want to keep
+                        * the exclusive cap. So that MDS does not end up
+                        * revoking the shared cap on every create/unlink
+                        * operation.
+                        */
+                       want = CEPH_CAP_ANY_SHARED | CEPH_CAP_FILE_EXCL;
+                       retain |= want;
                } else {
+
                        retain |= CEPH_CAP_ANY_SHARED;
                        /*
                         * keep RD only if we didn't have the file open RW,
@@ -2309,6 +2337,9 @@ void ceph_put_cap_refs(struct ceph_inode_info *ci, int had)
                                        wake = 1;
                                }
                        }
+                       /* see comment in __ceph_remove_cap() */
+                       if (!__ceph_is_any_caps(ci) && ci->i_snap_realm)
+                               drop_inode_snap_realm(ci);
                }
        spin_unlock(&ci->i_ceph_lock);
 
@@ -3391,7 +3422,7 @@ int ceph_encode_inode_release(void **p, struct inode *inode,
 int ceph_encode_dentry_release(void **p, struct dentry *dentry,
                               int mds, int drop, int unless)
 {
-       struct inode *dir = dentry->d_parent->d_inode;
+       struct inode *dir = d_inode(dentry->d_parent);
        struct ceph_mds_request_release *rel = *p;
        struct ceph_dentry_info *di = ceph_dentry(dentry);
        int force = 0;
index 1b2355109b9fd13faa3141ecc1cd75bbe28881c1..31f831471ed287e470bc38fc8632b19d6aed61d2 100644 (file)
@@ -84,7 +84,7 @@ static int mdsc_show(struct seq_file *s, void *p)
                                path = NULL;
                        spin_lock(&req->r_dentry->d_lock);
                        seq_printf(s, " #%llx/%pd (%s)",
-                                  ceph_ino(req->r_dentry->d_parent->d_inode),
+                                  ceph_ino(d_inode(req->r_dentry->d_parent)),
                                   req->r_dentry,
                                   path ? path : "");
                        spin_unlock(&req->r_dentry->d_lock);
index 83e9976f718983ccfb5d95c56893e81c7d01caa9..4248307fea909c6f1555758e536a3f733ad5f95d 100644 (file)
@@ -49,9 +49,9 @@ int ceph_init_dentry(struct dentry *dentry)
                goto out_unlock;
        }
 
-       if (ceph_snap(dentry->d_parent->d_inode) == CEPH_NOSNAP)
+       if (ceph_snap(d_inode(dentry->d_parent)) == CEPH_NOSNAP)
                d_set_d_op(dentry, &ceph_dentry_ops);
-       else if (ceph_snap(dentry->d_parent->d_inode) == CEPH_SNAPDIR)
+       else if (ceph_snap(d_inode(dentry->d_parent)) == CEPH_SNAPDIR)
                d_set_d_op(dentry, &ceph_snapdir_dentry_ops);
        else
                d_set_d_op(dentry, &ceph_snap_dentry_ops);
@@ -77,7 +77,7 @@ struct inode *ceph_get_dentry_parent_inode(struct dentry *dentry)
 
        spin_lock(&dentry->d_lock);
        if (!IS_ROOT(dentry)) {
-               inode = dentry->d_parent->d_inode;
+               inode = d_inode(dentry->d_parent);
                ihold(inode);
        }
        spin_unlock(&dentry->d_lock);
@@ -122,7 +122,7 @@ static int __dcache_readdir(struct file *file,  struct dir_context *ctx,
 {
        struct ceph_file_info *fi = file->private_data;
        struct dentry *parent = file->f_path.dentry;
-       struct inode *dir = parent->d_inode;
+       struct inode *dir = d_inode(parent);
        struct list_head *p;
        struct dentry *dentry, *last;
        struct ceph_dentry_info *di;
@@ -161,15 +161,15 @@ more:
                }
                spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
                if (di->lease_shared_gen == shared_gen &&
-                   !d_unhashed(dentry) && dentry->d_inode &&
-                   ceph_snap(dentry->d_inode) != CEPH_SNAPDIR &&
-                   ceph_ino(dentry->d_inode) != CEPH_INO_CEPH &&
+                   !d_unhashed(dentry) && d_really_is_positive(dentry) &&
+                   ceph_snap(d_inode(dentry)) != CEPH_SNAPDIR &&
+                   ceph_ino(d_inode(dentry)) != CEPH_INO_CEPH &&
                    fpos_cmp(ctx->pos, di->offset) <= 0)
                        break;
                dout(" skipping %p %pd at %llu (%llu)%s%s\n", dentry,
                     dentry, di->offset,
                     ctx->pos, d_unhashed(dentry) ? " unhashed" : "",
-                    !dentry->d_inode ? " null" : "");
+                    !d_inode(dentry) ? " null" : "");
                spin_unlock(&dentry->d_lock);
                p = p->prev;
                dentry = list_entry(p, struct dentry, d_child);
@@ -189,11 +189,11 @@ more:
        }
 
        dout(" %llu (%llu) dentry %p %pd %p\n", di->offset, ctx->pos,
-            dentry, dentry, dentry->d_inode);
+            dentry, dentry, d_inode(dentry));
        if (!dir_emit(ctx, dentry->d_name.name,
                      dentry->d_name.len,
-                     ceph_translate_ino(dentry->d_sb, dentry->d_inode->i_ino),
-                     dentry->d_inode->i_mode >> 12)) {
+                     ceph_translate_ino(dentry->d_sb, d_inode(dentry)->i_ino),
+                     d_inode(dentry)->i_mode >> 12)) {
                if (last) {
                        /* remember our position */
                        fi->dentry = last;
@@ -281,6 +281,7 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
        /* can we use the dcache? */
        spin_lock(&ci->i_ceph_lock);
        if ((ctx->pos == 2 || fi->dentry) &&
+           ceph_test_mount_opt(fsc, DCACHE) &&
            !ceph_test_mount_opt(fsc, NOASYNCREADDIR) &&
            ceph_snap(inode) != CEPH_SNAPDIR &&
            __ceph_dir_is_complete_ordered(ci) &&
@@ -336,16 +337,23 @@ more:
                        ceph_mdsc_put_request(req);
                        return err;
                }
-               req->r_inode = inode;
-               ihold(inode);
-               req->r_dentry = dget(file->f_path.dentry);
                /* hints to request -> mds selection code */
                req->r_direct_mode = USE_AUTH_MDS;
                req->r_direct_hash = ceph_frag_value(frag);
                req->r_direct_is_hash = true;
-               req->r_path2 = kstrdup(fi->last_name, GFP_NOFS);
+               if (fi->last_name) {
+                       req->r_path2 = kstrdup(fi->last_name, GFP_NOFS);
+                       if (!req->r_path2) {
+                               ceph_mdsc_put_request(req);
+                               return -ENOMEM;
+                       }
+               }
                req->r_readdir_offset = fi->next_offset;
                req->r_args.readdir.frag = cpu_to_le32(frag);
+
+               req->r_inode = inode;
+               ihold(inode);
+               req->r_dentry = dget(file->f_path.dentry);
                err = ceph_mdsc_do_request(mdsc, NULL, req);
                if (err < 0) {
                        ceph_mdsc_put_request(req);
@@ -535,7 +543,7 @@ int ceph_handle_snapdir(struct ceph_mds_request *req,
                        struct dentry *dentry, int err)
 {
        struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb);
-       struct inode *parent = dentry->d_parent->d_inode; /* we hold i_mutex */
+       struct inode *parent = d_inode(dentry->d_parent); /* we hold i_mutex */
 
        /* .snap dir? */
        if (err == -ENOENT &&
@@ -571,8 +579,8 @@ struct dentry *ceph_finish_lookup(struct ceph_mds_request *req,
                err = 0;
                if (!req->r_reply_info.head->is_dentry) {
                        dout("ENOENT and no trace, dentry %p inode %p\n",
-                            dentry, dentry->d_inode);
-                       if (dentry->d_inode) {
+                            dentry, d_inode(dentry));
+                       if (d_really_is_positive(dentry)) {
                                d_drop(dentry);
                                err = -ENOENT;
                        } else {
@@ -619,7 +627,7 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
                return ERR_PTR(err);
 
        /* can we conclude ENOENT locally? */
-       if (dentry->d_inode == NULL) {
+       if (d_really_is_negative(dentry)) {
                struct ceph_inode_info *ci = ceph_inode(dir);
                struct ceph_dentry_info *di = ceph_dentry(dentry);
 
@@ -629,6 +637,7 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
                            fsc->mount_options->snapdir_name,
                            dentry->d_name.len) &&
                    !is_root_ceph_dentry(dir, dentry) &&
+                   ceph_test_mount_opt(fsc, DCACHE) &&
                    __ceph_dir_is_complete(ci) &&
                    (__ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1))) {
                        spin_unlock(&ci->i_ceph_lock);
@@ -725,7 +734,7 @@ static int ceph_mknod(struct inode *dir, struct dentry *dentry,
        ceph_mdsc_put_request(req);
 out:
        if (!err)
-               ceph_init_inode_acls(dentry->d_inode, &acls);
+               ceph_init_inode_acls(d_inode(dentry), &acls);
        else
                d_drop(dentry);
        ceph_release_acls_info(&acls);
@@ -755,10 +764,15 @@ static int ceph_symlink(struct inode *dir, struct dentry *dentry,
                err = PTR_ERR(req);
                goto out;
        }
-       req->r_dentry = dget(dentry);
-       req->r_num_caps = 2;
        req->r_path2 = kstrdup(dest, GFP_NOFS);
+       if (!req->r_path2) {
+               err = -ENOMEM;
+               ceph_mdsc_put_request(req);
+               goto out;
+       }
        req->r_locked_dir = dir;
+       req->r_dentry = dget(dentry);
+       req->r_num_caps = 2;
        req->r_dentry_drop = CEPH_CAP_FILE_SHARED;
        req->r_dentry_unless = CEPH_CAP_FILE_EXCL;
        err = ceph_mdsc_do_request(mdsc, dir, req);
@@ -821,7 +835,7 @@ static int ceph_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
        ceph_mdsc_put_request(req);
 out:
        if (!err)
-               ceph_init_inode_acls(dentry->d_inode, &acls);
+               ceph_init_inode_acls(d_inode(dentry), &acls);
        else
                d_drop(dentry);
        ceph_release_acls_info(&acls);
@@ -858,8 +872,8 @@ static int ceph_link(struct dentry *old_dentry, struct inode *dir,
        if (err) {
                d_drop(dentry);
        } else if (!req->r_reply_info.head->is_dentry) {
-               ihold(old_dentry->d_inode);
-               d_instantiate(dentry, old_dentry->d_inode);
+               ihold(d_inode(old_dentry));
+               d_instantiate(dentry, d_inode(old_dentry));
        }
        ceph_mdsc_put_request(req);
        return err;
@@ -892,7 +906,7 @@ static int ceph_unlink(struct inode *dir, struct dentry *dentry)
 {
        struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
        struct ceph_mds_client *mdsc = fsc->mdsc;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct ceph_mds_request *req;
        int err = -EROFS;
        int op;
@@ -933,16 +947,20 @@ static int ceph_rename(struct inode *old_dir, struct dentry *old_dentry,
        struct ceph_fs_client *fsc = ceph_sb_to_client(old_dir->i_sb);
        struct ceph_mds_client *mdsc = fsc->mdsc;
        struct ceph_mds_request *req;
+       int op = CEPH_MDS_OP_RENAME;
        int err;
 
        if (ceph_snap(old_dir) != ceph_snap(new_dir))
                return -EXDEV;
-       if (ceph_snap(old_dir) != CEPH_NOSNAP ||
-           ceph_snap(new_dir) != CEPH_NOSNAP)
-               return -EROFS;
+       if (ceph_snap(old_dir) != CEPH_NOSNAP) {
+               if (old_dir == new_dir && ceph_snap(old_dir) == CEPH_SNAPDIR)
+                       op = CEPH_MDS_OP_RENAMESNAP;
+               else
+                       return -EROFS;
+       }
        dout("rename dir %p dentry %p to dir %p dentry %p\n",
             old_dir, old_dentry, new_dir, new_dentry);
-       req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_RENAME, USE_AUTH_MDS);
+       req = ceph_mdsc_create_request(mdsc, op, USE_AUTH_MDS);
        if (IS_ERR(req))
                return PTR_ERR(req);
        ihold(old_dir);
@@ -957,8 +975,8 @@ static int ceph_rename(struct inode *old_dir, struct dentry *old_dentry,
        req->r_dentry_unless = CEPH_CAP_FILE_EXCL;
        /* release LINK_RDCACHE on source inode (mds will lock it) */
        req->r_old_inode_drop = CEPH_CAP_LINK_SHARED;
-       if (new_dentry->d_inode)
-               req->r_inode_drop = drop_caps_for_unlink(new_dentry->d_inode);
+       if (d_really_is_positive(new_dentry))
+               req->r_inode_drop = drop_caps_for_unlink(d_inode(new_dentry));
        err = ceph_mdsc_do_request(mdsc, old_dir, req);
        if (!err && !req->r_reply_info.head->is_dentry) {
                /*
@@ -1024,7 +1042,7 @@ static int dentry_lease_is_valid(struct dentry *dentry)
                        if (di->lease_renew_after &&
                            time_after(jiffies, di->lease_renew_after)) {
                                /* we should renew */
-                               dir = dentry->d_parent->d_inode;
+                               dir = d_inode(dentry->d_parent);
                                session = ceph_get_mds_session(s);
                                seq = di->lease_seq;
                                di->lease_renew_after = 0;
@@ -1074,22 +1092,22 @@ static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags)
                return -ECHILD;
 
        dout("d_revalidate %p '%pd' inode %p offset %lld\n", dentry,
-            dentry, dentry->d_inode, ceph_dentry(dentry)->offset);
+            dentry, d_inode(dentry), ceph_dentry(dentry)->offset);
 
        dir = ceph_get_dentry_parent_inode(dentry);
 
        /* always trust cached snapped dentries, snapdir dentry */
        if (ceph_snap(dir) != CEPH_NOSNAP) {
                dout("d_revalidate %p '%pd' inode %p is SNAPPED\n", dentry,
-                    dentry, dentry->d_inode);
+                    dentry, d_inode(dentry));
                valid = 1;
-       } else if (dentry->d_inode &&
-                  ceph_snap(dentry->d_inode) == CEPH_SNAPDIR) {
+       } else if (d_really_is_positive(dentry) &&
+                  ceph_snap(d_inode(dentry)) == CEPH_SNAPDIR) {
                valid = 1;
        } else if (dentry_lease_is_valid(dentry) ||
                   dir_lease_is_valid(dir, dentry)) {
-               if (dentry->d_inode)
-                       valid = ceph_is_any_caps(dentry->d_inode);
+               if (d_really_is_positive(dentry))
+                       valid = ceph_is_any_caps(d_inode(dentry));
                else
                        valid = 1;
        }
@@ -1151,7 +1169,7 @@ static void ceph_d_prune(struct dentry *dentry)
         * we hold d_lock, so d_parent is stable, and d_fsdata is never
         * cleared until d_release
         */
-       ceph_dir_clear_complete(dentry->d_parent->d_inode);
+       ceph_dir_clear_complete(d_inode(dentry->d_parent));
 }
 
 /*
@@ -1240,11 +1258,12 @@ static int ceph_dir_fsync(struct file *file, loff_t start, loff_t end,
                dout("dir_fsync %p wait on tid %llu (until %llu)\n",
                     inode, req->r_tid, last_tid);
                if (req->r_timeout) {
-                       ret = wait_for_completion_timeout(
-                               &req->r_safe_completion, req->r_timeout);
-                       if (ret > 0)
+                       unsigned long time_left = wait_for_completion_timeout(
+                                                       &req->r_safe_completion,
+                                                       req->r_timeout);
+                       if (time_left > 0)
                                ret = 0;
-                       else if (ret == 0)
+                       else
                                ret = -EIO;  /* timed out */
                } else {
                        wait_for_completion(&req->r_safe_completion);
@@ -1372,6 +1391,7 @@ const struct inode_operations ceph_snapdir_iops = {
        .getattr = ceph_getattr,
        .mkdir = ceph_mkdir,
        .rmdir = ceph_unlink,
+       .rename = ceph_rename,
 };
 
 const struct dentry_operations ceph_dentry_ops = {
index 8d7d782f43822d2fd29b1f6fe941093ff7e247d3..fe02ae7f056a332220929ce653e822a0a39e2605 100644 (file)
@@ -136,8 +136,8 @@ static struct dentry *__get_parent(struct super_block *sb,
                return ERR_CAST(req);
 
        if (child) {
-               req->r_inode = child->d_inode;
-               ihold(child->d_inode);
+               req->r_inode = d_inode(child);
+               ihold(d_inode(child));
        } else {
                req->r_ino1 = (struct ceph_vino) {
                        .ino = ino,
@@ -164,7 +164,7 @@ static struct dentry *__get_parent(struct super_block *sb,
                return ERR_PTR(err);
        }
        dout("__get_parent ino %llx parent %p ino %llx.%llx\n",
-            child ? ceph_ino(child->d_inode) : ino,
+            child ? ceph_ino(d_inode(child)) : ino,
             dentry, ceph_vinop(inode));
        return dentry;
 }
@@ -172,11 +172,11 @@ static struct dentry *__get_parent(struct super_block *sb,
 static struct dentry *ceph_get_parent(struct dentry *child)
 {
        /* don't re-export snaps */
-       if (ceph_snap(child->d_inode) != CEPH_NOSNAP)
+       if (ceph_snap(d_inode(child)) != CEPH_NOSNAP)
                return ERR_PTR(-EINVAL);
 
        dout("get_parent %p ino %llx.%llx\n",
-            child, ceph_vinop(child->d_inode));
+            child, ceph_vinop(d_inode(child)));
        return __get_parent(child->d_sb, child, 0);
 }
 
@@ -209,32 +209,32 @@ static int ceph_get_name(struct dentry *parent, char *name,
        struct ceph_mds_request *req;
        int err;
 
-       mdsc = ceph_inode_to_client(child->d_inode)->mdsc;
+       mdsc = ceph_inode_to_client(d_inode(child))->mdsc;
        req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_LOOKUPNAME,
                                       USE_ANY_MDS);
        if (IS_ERR(req))
                return PTR_ERR(req);
 
-       mutex_lock(&parent->d_inode->i_mutex);
+       mutex_lock(&d_inode(parent)->i_mutex);
 
-       req->r_inode = child->d_inode;
-       ihold(child->d_inode);
-       req->r_ino2 = ceph_vino(parent->d_inode);
-       req->r_locked_dir = parent->d_inode;
+       req->r_inode = d_inode(child);
+       ihold(d_inode(child));
+       req->r_ino2 = ceph_vino(d_inode(parent));
+       req->r_locked_dir = d_inode(parent);
        req->r_num_caps = 2;
        err = ceph_mdsc_do_request(mdsc, NULL, req);
 
-       mutex_unlock(&parent->d_inode->i_mutex);
+       mutex_unlock(&d_inode(parent)->i_mutex);
 
        if (!err) {
                struct ceph_mds_reply_info_parsed *rinfo = &req->r_reply_info;
                memcpy(name, rinfo->dname, rinfo->dname_len);
                name[rinfo->dname_len] = 0;
                dout("get_name %p ino %llx.%llx name %s\n",
-                    child, ceph_vinop(child->d_inode), name);
+                    child, ceph_vinop(d_inode(child)), name);
        } else {
                dout("get_name %p ino %llx.%llx err %d\n",
-                    child, ceph_vinop(child->d_inode), err);
+                    child, ceph_vinop(d_inode(child)), err);
        }
 
        ceph_mdsc_put_request(req);
index b9b8eb225f66ead124f4a1484cfc5b76dbb8d2fb..3b6b522b4b31ed9e2f7193c661894787bfe63627 100644 (file)
@@ -291,14 +291,14 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
        }
        if (err)
                goto out_req;
-       if (dn || dentry->d_inode == NULL || d_is_symlink(dentry)) {
+       if (dn || d_really_is_negative(dentry) || d_is_symlink(dentry)) {
                /* make vfs retry on splice, ENOENT, or symlink */
                dout("atomic_open finish_no_open on dn %p\n", dn);
                err = finish_no_open(file, dn);
        } else {
                dout("atomic_open finish_open on dn %p\n", dn);
                if (req->r_op == CEPH_MDS_OP_CREATE && req->r_reply_info.has_create_ino) {
-                       ceph_init_inode_acls(dentry->d_inode, &acls);
+                       ceph_init_inode_acls(d_inode(dentry), &acls);
                        *opened |= FILE_CREATED;
                }
                err = finish_open(file, dentry, ceph_open, opened);
index 119c43c80638788f648272fbd1593e6e6bdbfd94..e876e1944519a330a2cc1f44e33a031139a35438 100644 (file)
@@ -940,7 +940,7 @@ static void update_dentry_lease(struct dentry *dentry,
             dentry, duration, ttl);
 
        /* make lease_rdcache_gen match directory */
-       dir = dentry->d_parent->d_inode;
+       dir = d_inode(dentry->d_parent);
        di->lease_shared_gen = ceph_inode(dir)->i_shared_gen;
 
        if (duration == 0)
@@ -980,7 +980,7 @@ static struct dentry *splice_dentry(struct dentry *dn, struct inode *in,
 {
        struct dentry *realdn;
 
-       BUG_ON(dn->d_inode);
+       BUG_ON(d_inode(dn));
 
        /* dn must be unhashed */
        if (!d_unhashed(dn))
@@ -998,13 +998,13 @@ static struct dentry *splice_dentry(struct dentry *dn, struct inode *in,
                     "inode %p ino %llx.%llx\n",
                     dn, d_count(dn),
                     realdn, d_count(realdn),
-                    realdn->d_inode, ceph_vinop(realdn->d_inode));
+                    d_inode(realdn), ceph_vinop(d_inode(realdn)));
                dput(dn);
                dn = realdn;
        } else {
                BUG_ON(!ceph_dentry(dn));
                dout("dn %p attached to %p ino %llx.%llx\n",
-                    dn, dn->d_inode, ceph_vinop(dn->d_inode));
+                    dn, d_inode(dn), ceph_vinop(d_inode(dn)));
        }
        if ((!prehash || *prehash) && d_unhashed(dn))
                d_rehash(dn);
@@ -1125,11 +1125,11 @@ retry_lookup:
                                        dput(parent);
                                        goto done;
                                }
-                       } else if (dn->d_inode &&
-                                  (ceph_ino(dn->d_inode) != vino.ino ||
-                                   ceph_snap(dn->d_inode) != vino.snap)) {
+                       } else if (d_really_is_positive(dn) &&
+                                  (ceph_ino(d_inode(dn)) != vino.ino ||
+                                   ceph_snap(d_inode(dn)) != vino.snap)) {
                                dout(" dn %p points to wrong inode %p\n",
-                                    dn, dn->d_inode);
+                                    dn, d_inode(dn));
                                d_delete(dn);
                                dput(dn);
                                goto retry_lookup;
@@ -1183,7 +1183,7 @@ retry_lookup:
 
                BUG_ON(!dn);
                BUG_ON(!dir);
-               BUG_ON(dn->d_parent->d_inode != dir);
+               BUG_ON(d_inode(dn->d_parent) != dir);
                BUG_ON(ceph_ino(dir) !=
                       le64_to_cpu(rinfo->diri.in->ino));
                BUG_ON(ceph_snap(dir) !=
@@ -1235,7 +1235,7 @@ retry_lookup:
                /* null dentry? */
                if (!rinfo->head->is_target) {
                        dout("fill_trace null dentry\n");
-                       if (dn->d_inode) {
+                       if (d_really_is_positive(dn)) {
                                ceph_dir_clear_ordered(dir);
                                dout("d_delete %p\n", dn);
                                d_delete(dn);
@@ -1252,7 +1252,7 @@ retry_lookup:
                }
 
                /* attach proper inode */
-               if (!dn->d_inode) {
+               if (d_really_is_negative(dn)) {
                        ceph_dir_clear_ordered(dir);
                        ihold(in);
                        dn = splice_dentry(dn, in, &have_lease);
@@ -1261,9 +1261,9 @@ retry_lookup:
                                goto done;
                        }
                        req->r_dentry = dn;  /* may have spliced */
-               } else if (dn->d_inode && dn->d_inode != in) {
+               } else if (d_really_is_positive(dn) && d_inode(dn) != in) {
                        dout(" %p links to %p %llx.%llx, not %llx.%llx\n",
-                            dn, dn->d_inode, ceph_vinop(dn->d_inode),
+                            dn, d_inode(dn), ceph_vinop(d_inode(dn)),
                             ceph_vinop(in));
                        have_lease = false;
                }
@@ -1363,7 +1363,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
                return readdir_prepopulate_inodes_only(req, session);
 
        if (le32_to_cpu(rinfo->head->op) == CEPH_MDS_OP_LSSNAP) {
-               snapdir = ceph_get_snapdir(parent->d_inode);
+               snapdir = ceph_get_snapdir(d_inode(parent));
                parent = d_find_alias(snapdir);
                dout("readdir_prepopulate %d items under SNAPDIR dn %p\n",
                     rinfo->dir_nr, parent);
@@ -1371,7 +1371,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
                dout("readdir_prepopulate %d items under dn %p\n",
                     rinfo->dir_nr, parent);
                if (rinfo->dir_dir)
-                       ceph_fill_dirfrag(parent->d_inode, rinfo->dir_dir);
+                       ceph_fill_dirfrag(d_inode(parent), rinfo->dir_dir);
        }
 
        /* FIXME: release caps/leases if error occurs */
@@ -1405,11 +1405,11 @@ retry_lookup:
                                err = ret;
                                goto out;
                        }
-               } else if (dn->d_inode &&
-                          (ceph_ino(dn->d_inode) != vino.ino ||
-                           ceph_snap(dn->d_inode) != vino.snap)) {
+               } else if (d_really_is_positive(dn) &&
+                          (ceph_ino(d_inode(dn)) != vino.ino ||
+                           ceph_snap(d_inode(dn)) != vino.snap)) {
                        dout(" dn %p points to wrong inode %p\n",
-                            dn, dn->d_inode);
+                            dn, d_inode(dn));
                        d_delete(dn);
                        dput(dn);
                        goto retry_lookup;
@@ -1423,8 +1423,8 @@ retry_lookup:
                }
 
                /* inode */
-               if (dn->d_inode) {
-                       in = dn->d_inode;
+               if (d_really_is_positive(dn)) {
+                       in = d_inode(dn);
                } else {
                        in = ceph_get_inode(parent->d_sb, vino);
                        if (IS_ERR(in)) {
@@ -1440,13 +1440,13 @@ retry_lookup:
                               req->r_request_started, -1,
                               &req->r_caps_reservation) < 0) {
                        pr_err("fill_inode badness on %p\n", in);
-                       if (!dn->d_inode)
+                       if (d_really_is_negative(dn))
                                iput(in);
                        d_drop(dn);
                        goto next_item;
                }
 
-               if (!dn->d_inode) {
+               if (d_really_is_negative(dn)) {
                        struct dentry *realdn = splice_dentry(dn, in, NULL);
                        if (IS_ERR(realdn)) {
                                err = PTR_ERR(realdn);
@@ -1693,7 +1693,7 @@ retry:
  */
 static void *ceph_sym_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-       struct ceph_inode_info *ci = ceph_inode(dentry->d_inode);
+       struct ceph_inode_info *ci = ceph_inode(d_inode(dentry));
        nd_set_link(nd, ci->i_symlink);
        return NULL;
 }
@@ -1714,7 +1714,7 @@ static const struct inode_operations ceph_symlink_iops = {
  */
 int ceph_setattr(struct dentry *dentry, struct iattr *attr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct ceph_inode_info *ci = ceph_inode(inode);
        const unsigned int ia_valid = attr->ia_valid;
        struct ceph_mds_request *req;
@@ -1990,7 +1990,7 @@ int ceph_permission(struct inode *inode, int mask)
 int ceph_getattr(struct vfsmount *mnt, struct dentry *dentry,
                 struct kstat *stat)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct ceph_inode_info *ci = ceph_inode(inode);
        int err;
 
index 71c073f38e547522c81fa335fcae85c5d8c7ef58..84f37f34f9aa663952a60e8a3440a81934c083b0 100644 (file)
@@ -679,7 +679,7 @@ static struct dentry *get_nonsnap_parent(struct dentry *dentry)
         * except to resplice to another snapdir, and either the old or new
         * result is a valid result.
         */
-       while (!IS_ROOT(dentry) && ceph_snap(dentry->d_inode) != CEPH_NOSNAP)
+       while (!IS_ROOT(dentry) && ceph_snap(d_inode(dentry)) != CEPH_NOSNAP)
                dentry = dentry->d_parent;
        return dentry;
 }
@@ -716,20 +716,20 @@ static int __choose_mds(struct ceph_mds_client *mdsc,
        } else if (req->r_dentry) {
                /* ignore race with rename; old or new d_parent is okay */
                struct dentry *parent = req->r_dentry->d_parent;
-               struct inode *dir = parent->d_inode;
+               struct inode *dir = d_inode(parent);
 
                if (dir->i_sb != mdsc->fsc->sb) {
                        /* not this fs! */
-                       inode = req->r_dentry->d_inode;
+                       inode = d_inode(req->r_dentry);
                } else if (ceph_snap(dir) != CEPH_NOSNAP) {
                        /* direct snapped/virtual snapdir requests
                         * based on parent dir inode */
                        struct dentry *dn = get_nonsnap_parent(parent);
-                       inode = dn->d_inode;
+                       inode = d_inode(dn);
                        dout("__choose_mds using nonsnap parent %p\n", inode);
                } else {
                        /* dentry target */
-                       inode = req->r_dentry->d_inode;
+                       inode = d_inode(req->r_dentry);
                        if (!inode || mode == USE_AUTH_MDS) {
                                /* dir + name */
                                inode = dir;
@@ -1021,6 +1021,33 @@ static void cleanup_cap_releases(struct ceph_mds_session *session)
        spin_unlock(&session->s_cap_lock);
 }
 
+static void cleanup_session_requests(struct ceph_mds_client *mdsc,
+                                    struct ceph_mds_session *session)
+{
+       struct ceph_mds_request *req;
+       struct rb_node *p;
+
+       dout("cleanup_session_requests mds%d\n", session->s_mds);
+       mutex_lock(&mdsc->mutex);
+       while (!list_empty(&session->s_unsafe)) {
+               req = list_first_entry(&session->s_unsafe,
+                                      struct ceph_mds_request, r_unsafe_item);
+               list_del_init(&req->r_unsafe_item);
+               pr_info(" dropping unsafe request %llu\n", req->r_tid);
+               __unregister_request(mdsc, req);
+       }
+       /* zero r_attempts, so kick_requests() will re-send requests */
+       p = rb_first(&mdsc->request_tree);
+       while (p) {
+               req = rb_entry(p, struct ceph_mds_request, r_node);
+               p = rb_next(p);
+               if (req->r_session &&
+                   req->r_session->s_mds == session->s_mds)
+                       req->r_attempts = 0;
+       }
+       mutex_unlock(&mdsc->mutex);
+}
+
 /*
  * Helper to safely iterate over all caps associated with a session, with
  * special care taken to handle a racing __ceph_remove_cap().
@@ -1098,7 +1125,7 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap,
             cap, ci, &ci->vfs_inode);
        spin_lock(&ci->i_ceph_lock);
        __ceph_remove_cap(cap, false);
-       if (!__ceph_is_any_real_caps(ci)) {
+       if (!ci->i_auth_cap) {
                struct ceph_mds_client *mdsc =
                        ceph_sb_to_client(inode->i_sb)->mdsc;
 
@@ -1120,13 +1147,6 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap,
                        mdsc->num_cap_flushing--;
                        drop = 1;
                }
-               if (drop && ci->i_wrbuffer_ref) {
-                       pr_info(" dropping dirty data for %p %lld\n",
-                               inode, ceph_ino(inode));
-                       ci->i_wrbuffer_ref = 0;
-                       ci->i_wrbuffer_ref_head = 0;
-                       drop++;
-               }
                spin_unlock(&mdsc->cap_dirty_lock);
        }
        spin_unlock(&ci->i_ceph_lock);
@@ -1712,7 +1732,7 @@ retry:
        seq = read_seqbegin(&rename_lock);
        rcu_read_lock();
        for (temp = dentry; !IS_ROOT(temp);) {
-               struct inode *inode = temp->d_inode;
+               struct inode *inode = d_inode(temp);
                if (inode && ceph_snap(inode) == CEPH_SNAPDIR)
                        len++;  /* slash only */
                else if (stop_on_nosnap && inode &&
@@ -1736,7 +1756,7 @@ retry:
                struct inode *inode;
 
                spin_lock(&temp->d_lock);
-               inode = temp->d_inode;
+               inode = d_inode(temp);
                if (inode && ceph_snap(inode) == CEPH_SNAPDIR) {
                        dout("build_path path+%d: %p SNAPDIR\n",
                             pos, temp);
@@ -1770,7 +1790,7 @@ retry:
                goto retry;
        }
 
-       *base = ceph_ino(temp->d_inode);
+       *base = ceph_ino(d_inode(temp));
        *plen = len;
        dout("build_path on %p %d built %llx '%.*s'\n",
             dentry, d_count(dentry), *base, len, path);
@@ -1783,8 +1803,8 @@ static int build_dentry_path(struct dentry *dentry,
 {
        char *path;
 
-       if (ceph_snap(dentry->d_parent->d_inode) == CEPH_NOSNAP) {
-               *pino = ceph_ino(dentry->d_parent->d_inode);
+       if (ceph_snap(d_inode(dentry->d_parent)) == CEPH_NOSNAP) {
+               *pino = ceph_ino(d_inode(dentry->d_parent));
                *ppath = dentry->d_name.name;
                *ppathlen = dentry->d_name.len;
                return 0;
@@ -1853,7 +1873,7 @@ static int set_request_path_attr(struct inode *rinode, struct dentry *rdentry,
  */
 static struct ceph_msg *create_request_message(struct ceph_mds_client *mdsc,
                                               struct ceph_mds_request *req,
-                                              int mds)
+                                              int mds, bool drop_cap_releases)
 {
        struct ceph_msg *msg;
        struct ceph_mds_request_head *head;
@@ -1925,7 +1945,7 @@ static struct ceph_msg *create_request_message(struct ceph_mds_client *mdsc,
        releases = 0;
        if (req->r_inode_drop)
                releases += ceph_encode_inode_release(&p,
-                     req->r_inode ? req->r_inode : req->r_dentry->d_inode,
+                     req->r_inode ? req->r_inode : d_inode(req->r_dentry),
                      mds, req->r_inode_drop, req->r_inode_unless, 0);
        if (req->r_dentry_drop)
                releases += ceph_encode_dentry_release(&p, req->r_dentry,
@@ -1935,8 +1955,14 @@ static struct ceph_msg *create_request_message(struct ceph_mds_client *mdsc,
                       mds, req->r_old_dentry_drop, req->r_old_dentry_unless);
        if (req->r_old_inode_drop)
                releases += ceph_encode_inode_release(&p,
-                     req->r_old_dentry->d_inode,
+                     d_inode(req->r_old_dentry),
                      mds, req->r_old_inode_drop, req->r_old_inode_unless, 0);
+
+       if (drop_cap_releases) {
+               releases = 0;
+               p = msg->front.iov_base + req->r_request_release_offset;
+       }
+
        head->num_releases = cpu_to_le16(releases);
 
        /* time stamp */
@@ -1989,7 +2015,7 @@ static void complete_request(struct ceph_mds_client *mdsc,
  */
 static int __prepare_send_request(struct ceph_mds_client *mdsc,
                                  struct ceph_mds_request *req,
-                                 int mds)
+                                 int mds, bool drop_cap_releases)
 {
        struct ceph_mds_request_head *rhead;
        struct ceph_msg *msg;
@@ -2048,7 +2074,7 @@ static int __prepare_send_request(struct ceph_mds_client *mdsc,
                ceph_msg_put(req->r_request);
                req->r_request = NULL;
        }
-       msg = create_request_message(mdsc, req, mds);
+       msg = create_request_message(mdsc, req, mds, drop_cap_releases);
        if (IS_ERR(msg)) {
                req->r_err = PTR_ERR(msg);
                complete_request(mdsc, req);
@@ -2132,7 +2158,7 @@ static int __do_request(struct ceph_mds_client *mdsc,
        if (req->r_request_started == 0)   /* note request start time */
                req->r_request_started = jiffies;
 
-       err = __prepare_send_request(mdsc, req, mds);
+       err = __prepare_send_request(mdsc, req, mds, false);
        if (!err) {
                ceph_msg_get(req->r_request);
                ceph_con_send(&session->s_con, req->r_request);
@@ -2590,6 +2616,7 @@ static void handle_session(struct ceph_mds_session *session,
        case CEPH_SESSION_CLOSE:
                if (session->s_state == CEPH_MDS_SESSION_RECONNECTING)
                        pr_info("mds%d reconnect denied\n", session->s_mds);
+               cleanup_session_requests(mdsc, session);
                remove_session_caps(session);
                wake = 2; /* for good measure */
                wake_up_all(&mdsc->session_close_wq);
@@ -2658,7 +2685,7 @@ static void replay_unsafe_requests(struct ceph_mds_client *mdsc,
 
        mutex_lock(&mdsc->mutex);
        list_for_each_entry_safe(req, nreq, &session->s_unsafe, r_unsafe_item) {
-               err = __prepare_send_request(mdsc, req, session->s_mds);
+               err = __prepare_send_request(mdsc, req, session->s_mds, true);
                if (!err) {
                        ceph_msg_get(req->r_request);
                        ceph_con_send(&session->s_con, req->r_request);
@@ -2679,7 +2706,8 @@ static void replay_unsafe_requests(struct ceph_mds_client *mdsc,
                        continue; /* only old requests */
                if (req->r_session &&
                    req->r_session->s_mds == session->s_mds) {
-                       err = __prepare_send_request(mdsc, req, session->s_mds);
+                       err = __prepare_send_request(mdsc, req,
+                                                    session->s_mds, true);
                        if (!err) {
                                ceph_msg_get(req->r_request);
                                ceph_con_send(&session->s_con, req->r_request);
@@ -2864,7 +2892,8 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc,
        spin_unlock(&session->s_cap_lock);
 
        /* trim unused caps to reduce MDS's cache rejoin time */
-       shrink_dcache_parent(mdsc->fsc->sb->s_root);
+       if (mdsc->fsc->sb->s_root)
+               shrink_dcache_parent(mdsc->fsc->sb->s_root);
 
        ceph_con_close(&session->s_con);
        ceph_con_open(&session->s_con,
@@ -3133,7 +3162,7 @@ static void handle_lease(struct ceph_mds_client *mdsc,
                    di->lease_renew_from &&
                    di->lease_renew_after == 0) {
                        unsigned long duration =
-                               le32_to_cpu(h->duration_ms) * HZ / 1000;
+                               msecs_to_jiffies(le32_to_cpu(h->duration_ms));
 
                        di->lease_seq = seq;
                        dentry->d_time = di->lease_renew_from + duration;
index 51cc23e4811147ad537fdc0d49ffb2f07bcc9dcf..89e6bc321df30fba6ef2555d4c376cd474d50366 100644 (file)
@@ -75,6 +75,7 @@ const char *ceph_mds_op_name(int op)
        case CEPH_MDS_OP_LSSNAP: return "lssnap";
        case CEPH_MDS_OP_MKSNAP: return "mksnap";
        case CEPH_MDS_OP_RMSNAP: return "rmsnap";
+       case CEPH_MDS_OP_RENAMESNAP: return "renamesnap";
        case CEPH_MDS_OP_SETFILELOCK: return "setfilelock";
        case CEPH_MDS_OP_GETFILELOCK: return "getfilelock";
        }
index a63997b8bcff8ac6d5967361700d79f1b6e35c3f..4e9905374078a228d18762a46a782a925f8f1675 100644 (file)
@@ -44,7 +44,7 @@ static void ceph_put_super(struct super_block *s)
 
 static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
-       struct ceph_fs_client *fsc = ceph_inode_to_client(dentry->d_inode);
+       struct ceph_fs_client *fsc = ceph_inode_to_client(d_inode(dentry));
        struct ceph_monmap *monmap = fsc->client->monc.monmap;
        struct ceph_statfs st;
        u64 fsid;
@@ -345,6 +345,11 @@ static int parse_mount_options(struct ceph_mount_options **pfsopt,
        fsopt->rsize = CEPH_RSIZE_DEFAULT;
        fsopt->rasize = CEPH_RASIZE_DEFAULT;
        fsopt->snapdir_name = kstrdup(CEPH_SNAPDIRNAME_DEFAULT, GFP_KERNEL);
+       if (!fsopt->snapdir_name) {
+               err = -ENOMEM;
+               goto out;
+       }
+
        fsopt->caps_wanted_delay_min = CEPH_CAPS_WANTED_DELAY_MIN_DEFAULT;
        fsopt->caps_wanted_delay_max = CEPH_CAPS_WANTED_DELAY_MAX_DEFAULT;
        fsopt->cap_release_safety = CEPH_CAP_RELEASE_SAFETY_DEFAULT;
@@ -406,31 +411,20 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root)
 {
        struct ceph_fs_client *fsc = ceph_sb_to_client(root->d_sb);
        struct ceph_mount_options *fsopt = fsc->mount_options;
-       struct ceph_options *opt = fsc->client->options;
-
-       if (opt->flags & CEPH_OPT_FSID)
-               seq_printf(m, ",fsid=%pU", &opt->fsid);
-       if (opt->flags & CEPH_OPT_NOSHARE)
-               seq_puts(m, ",noshare");
-       if (opt->flags & CEPH_OPT_NOCRC)
-               seq_puts(m, ",nocrc");
-       if (opt->flags & CEPH_OPT_NOMSGAUTH)
-               seq_puts(m, ",nocephx_require_signatures");
-       if ((opt->flags & CEPH_OPT_TCP_NODELAY) == 0)
-               seq_puts(m, ",notcp_nodelay");
-
-       if (opt->name)
-               seq_printf(m, ",name=%s", opt->name);
-       if (opt->key)
-               seq_puts(m, ",secret=<hidden>");
-
-       if (opt->mount_timeout != CEPH_MOUNT_TIMEOUT_DEFAULT)
-               seq_printf(m, ",mount_timeout=%d", opt->mount_timeout);
-       if (opt->osd_idle_ttl != CEPH_OSD_IDLE_TTL_DEFAULT)
-               seq_printf(m, ",osd_idle_ttl=%d", opt->osd_idle_ttl);
-       if (opt->osd_keepalive_timeout != CEPH_OSD_KEEPALIVE_DEFAULT)
-               seq_printf(m, ",osdkeepalivetimeout=%d",
-                          opt->osd_keepalive_timeout);
+       size_t pos;
+       int ret;
+
+       /* a comma between MNT/MS and client options */
+       seq_putc(m, ',');
+       pos = m->count;
+
+       ret = ceph_print_client_options(m, fsc->client);
+       if (ret)
+               return ret;
+
+       /* retract our comma if no client options */
+       if (m->count == pos)
+               m->count--;
 
        if (fsopt->flags & CEPH_MOUNT_OPT_DIRSTAT)
                seq_puts(m, ",dirstat");
@@ -438,14 +432,10 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root)
                seq_puts(m, ",norbytes");
        if (fsopt->flags & CEPH_MOUNT_OPT_NOASYNCREADDIR)
                seq_puts(m, ",noasyncreaddir");
-       if (fsopt->flags & CEPH_MOUNT_OPT_DCACHE)
-               seq_puts(m, ",dcache");
-       else
+       if ((fsopt->flags & CEPH_MOUNT_OPT_DCACHE) == 0)
                seq_puts(m, ",nodcache");
        if (fsopt->flags & CEPH_MOUNT_OPT_FSCACHE)
                seq_puts(m, ",fsc");
-       else
-               seq_puts(m, ",nofsc");
 
 #ifdef CONFIG_CEPH_FS_POSIX_ACL
        if (fsopt->sb_flags & MS_POSIXACL)
@@ -477,6 +467,7 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root)
                seq_printf(m, ",readdir_max_bytes=%d", fsopt->max_readdir_bytes);
        if (strcmp(fsopt->snapdir_name, CEPH_SNAPDIRNAME_DEFAULT))
                seq_printf(m, ",snapdirname=%s", fsopt->snapdir_name);
+
        return 0;
 }
 
@@ -730,6 +721,11 @@ static struct dentry *open_root_dentry(struct ceph_fs_client *fsc,
        if (IS_ERR(req))
                return ERR_CAST(req);
        req->r_path1 = kstrdup(path, GFP_NOFS);
+       if (!req->r_path1) {
+               root = ERR_PTR(-ENOMEM);
+               goto out;
+       }
+
        req->r_ino1.ino = CEPH_INO_ROOT;
        req->r_ino1.snap = CEPH_NOSNAP;
        req->r_started = started;
@@ -976,7 +972,7 @@ static struct dentry *ceph_mount(struct file_system_type *fs_type,
        if (IS_ERR(res))
                goto out_splat;
        dout("root %p inode %p ino %llx.%llx\n", res,
-            res->d_inode, ceph_vinop(res->d_inode));
+            d_inode(res), ceph_vinop(d_inode(res)));
        return res;
 
 out_splat:
index 04c8124ed30ecae65bf7344c96f7c984ed5a1d03..fa20e131893956a5360b2f6c37cd1aa7fce7542e 100644 (file)
@@ -36,7 +36,8 @@
 #define CEPH_MOUNT_OPT_DCACHE          (1<<9) /* use dcache for readdir etc */
 #define CEPH_MOUNT_OPT_FSCACHE         (1<<10) /* use fscache */
 
-#define CEPH_MOUNT_OPT_DEFAULT    (CEPH_MOUNT_OPT_RBYTES)
+#define CEPH_MOUNT_OPT_DEFAULT    (CEPH_MOUNT_OPT_RBYTES | \
+                                  CEPH_MOUNT_OPT_DCACHE)
 
 #define ceph_set_mount_opt(fsc, opt) \
        (fsc)->mount_options->flags |= CEPH_MOUNT_OPT_##opt;
@@ -881,7 +882,6 @@ extern int ceph_mmap(struct file *file, struct vm_area_struct *vma);
 
 /* file.c */
 extern const struct file_operations ceph_file_fops;
-extern const struct address_space_operations ceph_aops;
 
 extern int ceph_open(struct inode *inode, struct file *file);
 extern int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
index 5a492caf34cbbdbede390a00ecf534fdc7826a62..cd7ffad4041d81b605bdfbc97a4bc0072c19ca99 100644 (file)
@@ -776,12 +776,12 @@ ssize_t ceph_getxattr(struct dentry *dentry, const char *name, void *value,
        if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
                return generic_getxattr(dentry, name, value, size);
 
-       return __ceph_getxattr(dentry->d_inode, name, value, size);
+       return __ceph_getxattr(d_inode(dentry), name, value, size);
 }
 
 ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct ceph_inode_info *ci = ceph_inode(inode);
        struct ceph_vxattr *vxattrs = ceph_inode_vxattrs(inode);
        u32 vir_namelen = 0;
@@ -847,7 +847,7 @@ static int ceph_sync_setxattr(struct dentry *dentry, const char *name,
                              const char *value, size_t size, int flags)
 {
        struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb);
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct ceph_inode_info *ci = ceph_inode(inode);
        struct ceph_mds_request *req;
        struct ceph_mds_client *mdsc = fsc->mdsc;
@@ -877,16 +877,23 @@ static int ceph_sync_setxattr(struct dentry *dentry, const char *name,
                err = PTR_ERR(req);
                goto out;
        }
-       req->r_inode = inode;
-       ihold(inode);
-       req->r_inode_drop = CEPH_CAP_XATTR_SHARED;
-       req->r_num_caps = 1;
+
        req->r_args.setxattr.flags = cpu_to_le32(flags);
        req->r_path2 = kstrdup(name, GFP_NOFS);
+       if (!req->r_path2) {
+               ceph_mdsc_put_request(req);
+               err = -ENOMEM;
+               goto out;
+       }
 
        req->r_pagelist = pagelist;
        pagelist = NULL;
 
+       req->r_inode = inode;
+       ihold(inode);
+       req->r_num_caps = 1;
+       req->r_inode_drop = CEPH_CAP_XATTR_SHARED;
+
        dout("xattr.ver (before): %lld\n", ci->i_xattrs.version);
        err = ceph_mdsc_do_request(mdsc, NULL, req);
        ceph_mdsc_put_request(req);
@@ -901,7 +908,7 @@ out:
 int __ceph_setxattr(struct dentry *dentry, const char *name,
                        const void *value, size_t size, int flags)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct ceph_vxattr *vxattr;
        struct ceph_inode_info *ci = ceph_inode(inode);
        int issued;
@@ -995,7 +1002,7 @@ out:
 int ceph_setxattr(struct dentry *dentry, const char *name,
                  const void *value, size_t size, int flags)
 {
-       if (ceph_snap(dentry->d_inode) != CEPH_NOSNAP)
+       if (ceph_snap(d_inode(dentry)) != CEPH_NOSNAP)
                return -EROFS;
 
        if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
@@ -1011,7 +1018,7 @@ static int ceph_send_removexattr(struct dentry *dentry, const char *name)
 {
        struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb);
        struct ceph_mds_client *mdsc = fsc->mdsc;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct ceph_mds_request *req;
        int err;
 
@@ -1019,12 +1026,14 @@ static int ceph_send_removexattr(struct dentry *dentry, const char *name)
                                       USE_AUTH_MDS);
        if (IS_ERR(req))
                return PTR_ERR(req);
+       req->r_path2 = kstrdup(name, GFP_NOFS);
+       if (!req->r_path2)
+               return -ENOMEM;
+
        req->r_inode = inode;
        ihold(inode);
-       req->r_inode_drop = CEPH_CAP_XATTR_SHARED;
        req->r_num_caps = 1;
-       req->r_path2 = kstrdup(name, GFP_NOFS);
-
+       req->r_inode_drop = CEPH_CAP_XATTR_SHARED;
        err = ceph_mdsc_do_request(mdsc, NULL, req);
        ceph_mdsc_put_request(req);
        return err;
@@ -1032,7 +1041,7 @@ static int ceph_send_removexattr(struct dentry *dentry, const char *name)
 
 int __ceph_removexattr(struct dentry *dentry, const char *name)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct ceph_vxattr *vxattr;
        struct ceph_inode_info *ci = ceph_inode(inode);
        int issued;
@@ -1098,7 +1107,7 @@ out:
 
 int ceph_removexattr(struct dentry *dentry, const char *name)
 {
-       if (ceph_snap(dentry->d_inode) != CEPH_NOSNAP)
+       if (ceph_snap(d_inode(dentry)) != CEPH_NOSNAP)
                return -EROFS;
 
        if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
index b8602f19981560bc51fe9123689d75eed24f8e0c..430e0348c99ebb9b86c65ccd957a1b5e69ed6a2a 100644 (file)
@@ -301,7 +301,7 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
        if (full_path == NULL)
                goto cdda_exit;
 
-       cifs_sb = CIFS_SB(mntpt->d_inode->i_sb);
+       cifs_sb = CIFS_SB(d_inode(mntpt)->i_sb);
        tlink = cifs_sb_tlink(cifs_sb);
        if (IS_ERR(tlink)) {
                mnt = ERR_CAST(tlink);
index eaab4b2a05953225ea92075c95dd2e0174d3d75b..f5089bde363576dcab6a35887f3c539a8a7e6247 100644 (file)
@@ -607,7 +607,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
        p = s = full_path;
 
        do {
-               struct inode *dir = dentry->d_inode;
+               struct inode *dir = d_inode(dentry);
                struct dentry *child;
 
                if (!dir) {
index fa13d5e79f643afb4fcfdb92333a68786e5dff32..84650a51c7c4064357eab083868cc613a75f7f18 100644 (file)
@@ -1898,7 +1898,7 @@ static void
 cifs_writev_requeue(struct cifs_writedata *wdata)
 {
        int i, rc = 0;
-       struct inode *inode = wdata->cfile->dentry->d_inode;
+       struct inode *inode = d_inode(wdata->cfile->dentry);
        struct TCP_Server_Info *server;
        unsigned int rest_len;
 
@@ -1981,7 +1981,7 @@ cifs_writev_complete(struct work_struct *work)
 {
        struct cifs_writedata *wdata = container_of(work,
                                                struct cifs_writedata, work);
-       struct inode *inode = wdata->cfile->dentry->d_inode;
+       struct inode *inode = d_inode(wdata->cfile->dentry);
        int i = 0;
 
        if (wdata->result == 0) {
index b72bc29cba23e7f29b4acfc5f1309150f0711aaf..338d56936f6af694b7085284a38e7b751ba7eb66 100644 (file)
@@ -745,13 +745,13 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
                goto lookup_out;
        }
 
-       if (direntry->d_inode != NULL) {
+       if (d_really_is_positive(direntry)) {
                cifs_dbg(FYI, "non-NULL inode in lookup\n");
        } else {
                cifs_dbg(FYI, "NULL inode in lookup\n");
        }
        cifs_dbg(FYI, "Full path: %s inode = 0x%p\n",
-                full_path, direntry->d_inode);
+                full_path, d_inode(direntry));
 
        if (pTcon->unix_ext) {
                rc = cifs_get_inode_info_unix(&newInode, full_path,
@@ -792,7 +792,7 @@ cifs_d_revalidate(struct dentry *direntry, unsigned int flags)
        if (flags & LOOKUP_RCU)
                return -ECHILD;
 
-       if (direntry->d_inode) {
+       if (d_really_is_positive(direntry)) {
                if (cifs_revalidate_dentry(direntry))
                        return 0;
                else {
@@ -803,7 +803,7 @@ cifs_d_revalidate(struct dentry *direntry, unsigned int flags)
                         * attributes will have been updated by
                         * cifs_revalidate_dentry().
                         */
-                       if (IS_AUTOMOUNT(direntry->d_inode) &&
+                       if (IS_AUTOMOUNT(d_inode(direntry)) &&
                           !(direntry->d_flags & DCACHE_NEED_AUTOMOUNT)) {
                                spin_lock(&direntry->d_lock);
                                direntry->d_flags |= DCACHE_NEED_AUTOMOUNT;
index ca2bc5406306e57fb0d9620ffeec3488ed7d4414..cafbf10521d5017074196e02ad37218939d0ab70 100644 (file)
@@ -273,7 +273,7 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
                  struct tcon_link *tlink, __u32 oplock)
 {
        struct dentry *dentry = file->f_path.dentry;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct cifsInodeInfo *cinode = CIFS_I(inode);
        struct cifsFileInfo *cfile;
        struct cifs_fid_locks *fdlocks;
@@ -357,7 +357,7 @@ cifsFileInfo_get(struct cifsFileInfo *cifs_file)
  */
 void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
 {
-       struct inode *inode = cifs_file->dentry->d_inode;
+       struct inode *inode = d_inode(cifs_file->dentry);
        struct cifs_tcon *tcon = tlink_tcon(cifs_file->tlink);
        struct TCP_Server_Info *server = tcon->ses->server;
        struct cifsInodeInfo *cifsi = CIFS_I(inode);
@@ -386,7 +386,7 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
 
        if (list_empty(&cifsi->openFileList)) {
                cifs_dbg(FYI, "closing last open instance for inode %p\n",
-                        cifs_file->dentry->d_inode);
+                        d_inode(cifs_file->dentry));
                /*
                 * In strict cache mode we need invalidate mapping on the last
                 * close  because it may cause a error when we open this file
@@ -572,7 +572,7 @@ static int
 cifs_relock_file(struct cifsFileInfo *cfile)
 {
        struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
-       struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
+       struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
        struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
        int rc = 0;
 
@@ -620,7 +620,7 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
                return rc;
        }
 
-       inode = cfile->dentry->d_inode;
+       inode = d_inode(cfile->dentry);
        cifs_sb = CIFS_SB(inode->i_sb);
        tcon = tlink_tcon(cfile->tlink);
        server = tcon->ses->server;
@@ -874,7 +874,7 @@ cifs_find_lock_conflict(struct cifsFileInfo *cfile, __u64 offset, __u64 length,
 {
        bool rc = false;
        struct cifs_fid_locks *cur;
-       struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
+       struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
 
        list_for_each_entry(cur, &cinode->llist, llist) {
                rc = cifs_find_fid_lock_conflict(cur, offset, length, type,
@@ -899,7 +899,7 @@ cifs_lock_test(struct cifsFileInfo *cfile, __u64 offset, __u64 length,
 {
        int rc = 0;
        struct cifsLockInfo *conf_lock;
-       struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
+       struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
        struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
        bool exist;
 
@@ -927,7 +927,7 @@ cifs_lock_test(struct cifsFileInfo *cfile, __u64 offset, __u64 length,
 static void
 cifs_lock_add(struct cifsFileInfo *cfile, struct cifsLockInfo *lock)
 {
-       struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
+       struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
        down_write(&cinode->lock_sem);
        list_add_tail(&lock->llist, &cfile->llist->locks);
        up_write(&cinode->lock_sem);
@@ -944,7 +944,7 @@ cifs_lock_add_if(struct cifsFileInfo *cfile, struct cifsLockInfo *lock,
                 bool wait)
 {
        struct cifsLockInfo *conf_lock;
-       struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
+       struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
        bool exist;
        int rc = 0;
 
@@ -1125,7 +1125,7 @@ struct lock_to_push {
 static int
 cifs_push_posix_locks(struct cifsFileInfo *cfile)
 {
-       struct inode *inode = cfile->dentry->d_inode;
+       struct inode *inode = d_inode(cfile->dentry);
        struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
        struct file_lock *flock;
        struct file_lock_context *flctx = inode->i_flctx;
@@ -1214,7 +1214,7 @@ static int
 cifs_push_locks(struct cifsFileInfo *cfile)
 {
        struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
-       struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
+       struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
        struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
        int rc = 0;
 
@@ -1382,7 +1382,7 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
        unsigned int max_num, num, max_buf;
        LOCKING_ANDX_RANGE *buf, *cur;
        struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
-       struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
+       struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
        struct cifsLockInfo *li, *tmp;
        __u64 length = 1 + flock->fl_end - flock->fl_start;
        struct list_head tmp_llist;
@@ -1488,7 +1488,7 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
        struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data;
        struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
        struct TCP_Server_Info *server = tcon->ses->server;
-       struct inode *inode = cfile->dentry->d_inode;
+       struct inode *inode = d_inode(cfile->dentry);
 
        if (posix_lck) {
                int posix_lock_type;
@@ -1643,7 +1643,7 @@ cifs_write(struct cifsFileInfo *open_file, __u32 pid, const char *write_data,
        struct TCP_Server_Info *server;
        unsigned int xid;
        struct dentry *dentry = open_file->dentry;
-       struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode);
+       struct cifsInodeInfo *cifsi = CIFS_I(d_inode(dentry));
        struct cifs_io_parms io_parms;
 
        cifs_sb = CIFS_SB(dentry->d_sb);
@@ -1676,7 +1676,7 @@ cifs_write(struct cifsFileInfo *open_file, __u32 pid, const char *write_data,
                                        break;
                        }
 
-                       len = min(server->ops->wp_retry_size(dentry->d_inode),
+                       len = min(server->ops->wp_retry_size(d_inode(dentry)),
                                  (unsigned int)write_size - total_written);
                        /* iov[0] is reserved for smb header */
                        iov[1].iov_base = (char *)write_data + total_written;
@@ -1696,9 +1696,9 @@ cifs_write(struct cifsFileInfo *open_file, __u32 pid, const char *write_data,
                                return rc;
                        }
                } else {
-                       spin_lock(&dentry->d_inode->i_lock);
+                       spin_lock(&d_inode(dentry)->i_lock);
                        cifs_update_eof(cifsi, *offset, bytes_written);
-                       spin_unlock(&dentry->d_inode->i_lock);
+                       spin_unlock(&d_inode(dentry)->i_lock);
                        *offset += bytes_written;
                }
        }
@@ -1706,12 +1706,12 @@ cifs_write(struct cifsFileInfo *open_file, __u32 pid, const char *write_data,
        cifs_stats_bytes_written(tcon, total_written);
 
        if (total_written > 0) {
-               spin_lock(&dentry->d_inode->i_lock);
-               if (*offset > dentry->d_inode->i_size)
-                       i_size_write(dentry->d_inode, *offset);
-               spin_unlock(&dentry->d_inode->i_lock);
+               spin_lock(&d_inode(dentry)->i_lock);
+               if (*offset > d_inode(dentry)->i_size)
+                       i_size_write(d_inode(dentry), *offset);
+               spin_unlock(&d_inode(dentry)->i_lock);
        }
-       mark_inode_dirty_sync(dentry->d_inode);
+       mark_inode_dirty_sync(d_inode(dentry));
        free_xid(xid);
        return total_written;
 }
@@ -2406,7 +2406,7 @@ cifs_uncached_writev_complete(struct work_struct *work)
 {
        struct cifs_writedata *wdata = container_of(work,
                                        struct cifs_writedata, work);
-       struct inode *inode = wdata->cfile->dentry->d_inode;
+       struct inode *inode = d_inode(wdata->cfile->dentry);
        struct cifsInodeInfo *cifsi = CIFS_I(inode);
 
        spin_lock(&inode->i_lock);
@@ -3794,7 +3794,7 @@ void cifs_oplock_break(struct work_struct *work)
 {
        struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
                                                  oplock_break);
-       struct inode *inode = cfile->dentry->d_inode;
+       struct inode *inode = d_inode(cfile->dentry);
        struct cifsInodeInfo *cinode = CIFS_I(inode);
        struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
        struct TCP_Server_Info *server = tcon->ses->server;
index 3e126d7bb2ea5bec97c9d6e02973a49886261580..55b58112d122248b92305ea00eb66c6715a40b03 100644 (file)
@@ -1067,7 +1067,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
        int rc;
        struct cifs_fid fid;
        struct cifs_open_parms oparms;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct cifsInodeInfo *cifsInode = CIFS_I(inode);
        struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
        struct tcon_link *tlink;
@@ -1196,7 +1196,7 @@ cifs_drop_nlink(struct inode *inode)
 }
 
 /*
- * If dentry->d_inode is null (usually meaning the cached dentry
+ * If d_inode(dentry) is null (usually meaning the cached dentry
  * is a negative dentry) then we would attempt a standard SMB delete, but
  * if that fails we can not attempt the fall back mechanisms on EACCESS
  * but will return the EACCESS to the caller. Note that the VFS does not call
@@ -1207,7 +1207,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
        int rc = 0;
        unsigned int xid;
        char *full_path = NULL;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct cifsInodeInfo *cifs_inode;
        struct super_block *sb = dir->i_sb;
        struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
@@ -1551,13 +1551,13 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
        cifs_put_tlink(tlink);
 
        if (!rc) {
-               spin_lock(&direntry->d_inode->i_lock);
-               i_size_write(direntry->d_inode, 0);
-               clear_nlink(direntry->d_inode);
-               spin_unlock(&direntry->d_inode->i_lock);
+               spin_lock(&d_inode(direntry)->i_lock);
+               i_size_write(d_inode(direntry), 0);
+               clear_nlink(d_inode(direntry));
+               spin_unlock(&d_inode(direntry)->i_lock);
        }
 
-       cifsInode = CIFS_I(direntry->d_inode);
+       cifsInode = CIFS_I(d_inode(direntry));
        /* force revalidate to go get info when needed */
        cifsInode->time = 0;
 
@@ -1568,7 +1568,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
         */
        cifsInode->time = 0;
 
-       direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
+       d_inode(direntry)->i_ctime = inode->i_ctime = inode->i_mtime =
                current_fs_time(inode->i_sb);
 
 rmdir_exit:
@@ -1727,7 +1727,7 @@ cifs_rename2(struct inode *source_dir, struct dentry *source_dentry,
 
 unlink_target:
        /* Try unlinking the target dentry if it's not negative */
-       if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) {
+       if (d_really_is_positive(target_dentry) && (rc == -EACCES || rc == -EEXIST)) {
                if (d_is_dir(target_dentry))
                        tmprc = cifs_rmdir(target_dir, target_dentry);
                else
@@ -1867,7 +1867,7 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry)
 {
        unsigned int xid;
        int rc = 0;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct super_block *sb = dentry->d_sb;
        char *full_path = NULL;
 
@@ -1919,7 +1919,7 @@ int cifs_revalidate_file(struct file *filp)
 int cifs_revalidate_dentry(struct dentry *dentry)
 {
        int rc;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
 
        rc = cifs_revalidate_dentry_attr(dentry);
        if (rc)
@@ -1933,7 +1933,7 @@ int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
 {
        struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
        struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int rc;
 
        /*
@@ -2110,7 +2110,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
        int rc;
        unsigned int xid;
        char *full_path = NULL;
-       struct inode *inode = direntry->d_inode;
+       struct inode *inode = d_inode(direntry);
        struct cifsInodeInfo *cifsInode = CIFS_I(inode);
        struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
        struct tcon_link *tlink;
@@ -2251,7 +2251,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
        unsigned int xid;
        kuid_t uid = INVALID_UID;
        kgid_t gid = INVALID_GID;
-       struct inode *inode = direntry->d_inode;
+       struct inode *inode = d_inode(direntry);
        struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
        struct cifsInodeInfo *cifsInode = CIFS_I(inode);
        char *full_path = NULL;
@@ -2409,7 +2409,7 @@ cifs_setattr_exit:
 int
 cifs_setattr(struct dentry *direntry, struct iattr *attrs)
 {
-       struct inode *inode = direntry->d_inode;
+       struct inode *inode = d_inode(direntry);
        struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
        struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
 
index 2ec6037f61c758e11f7e1238e0e3c17c9a65af12..252e672d56043468fb8f906ce371acef27d74db0 100644 (file)
@@ -586,12 +586,12 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
         * if source file is cached (oplocked) revalidate will not go to server
         * until the file is closed or oplock broken so update nlinks locally
         */
-       if (old_file->d_inode) {
-               cifsInode = CIFS_I(old_file->d_inode);
+       if (d_really_is_positive(old_file)) {
+               cifsInode = CIFS_I(d_inode(old_file));
                if (rc == 0) {
-                       spin_lock(&old_file->d_inode->i_lock);
-                       inc_nlink(old_file->d_inode);
-                       spin_unlock(&old_file->d_inode->i_lock);
+                       spin_lock(&d_inode(old_file)->i_lock);
+                       inc_nlink(d_inode(old_file));
+                       spin_unlock(&d_inode(old_file)->i_lock);
 
                        /*
                         * parent dir timestamps will update from srv within a
@@ -629,7 +629,7 @@ cifs_hl_exit:
 void *
 cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
 {
-       struct inode *inode = direntry->d_inode;
+       struct inode *inode = d_inode(direntry);
        int rc = -ENOMEM;
        unsigned int xid;
        char *full_path = NULL;
index 337946355b29db5c71632f66a354295311e9f3e3..8442b8b8e0be145e7f68055e0025f1909442d156 100644 (file)
@@ -473,7 +473,7 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
                                        continue;
 
                                cifs_dbg(FYI, "file id match, oplock break\n");
-                               pCifsInode = CIFS_I(netfile->dentry->d_inode);
+                               pCifsInode = CIFS_I(d_inode(netfile->dentry));
 
                                set_bit(CIFS_INODE_PENDING_OPLOCK_BREAK,
                                        &pCifsInode->flags);
index c295338e0a98ce95a71c60afedc87ad9bd5267b5..b4a47237486b883851e889e78505bd1179c7842d 100644 (file)
@@ -78,7 +78,7 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *name,
 {
        struct dentry *dentry, *alias;
        struct inode *inode;
-       struct super_block *sb = parent->d_inode->i_sb;
+       struct super_block *sb = d_inode(parent)->i_sb;
        struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
 
        cifs_dbg(FYI, "%s: for %s\n", __func__, name->name);
@@ -88,7 +88,7 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *name,
                return;
 
        if (dentry) {
-               inode = dentry->d_inode;
+               inode = d_inode(dentry);
                if (inode) {
                        /*
                         * If we're generating inode numbers, then we don't
index d2979036a4c72756e91f9fa6c454337585c06800..7bfdd6066276256fc03855cd809f63c167d3991b 100644 (file)
@@ -722,7 +722,7 @@ cifs_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
 static void
 cifs_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock)
 {
-       struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
+       struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
        cfile->fid.netfid = fid->netfid;
        cifs_set_oplock_level(cinode, oplock);
        cinode->can_cache_brlcks = CIFS_CACHE_WRITE(cinode);
index 7198eac5dddd2ab5746a8d7778f7fdfd5e9bd5bb..2ab297dae5a7b2b4e544e3f35abc5f09b9fa7b1d 100644 (file)
@@ -95,7 +95,7 @@ smb2_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
        unsigned int max_num, num = 0, max_buf;
        struct smb2_lock_element *buf, *cur;
        struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
-       struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
+       struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
        struct cifsLockInfo *li, *tmp;
        __u64 length = 1 + flock->fl_end - flock->fl_start;
        struct list_head tmp_llist;
@@ -231,7 +231,7 @@ smb2_push_mandatory_locks(struct cifsFileInfo *cfile)
        unsigned int xid;
        unsigned int max_num, max_buf;
        struct smb2_lock_element *buf;
-       struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
+       struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
        struct cifs_fid_locks *fdlocks;
 
        xid = get_xid();
index 22dfdf17d06547f3d1b3abbc302bb03abf1b047b..1c5907019045517ac302daf4c04e8caea21f1fda 100644 (file)
@@ -453,7 +453,7 @@ smb2_tcon_has_lease(struct cifs_tcon *tcon, struct smb2_lease_break *rsp,
 
        list_for_each(tmp, &tcon->openFileList) {
                cfile = list_entry(tmp, struct cifsFileInfo, tlist);
-               cinode = CIFS_I(cfile->dentry->d_inode);
+               cinode = CIFS_I(d_inode(cfile->dentry));
 
                if (memcmp(cinode->lease_key, rsp->LeaseKey,
                                                        SMB2_LEASE_KEY_SIZE))
@@ -590,7 +590,7 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
                                        continue;
 
                                cifs_dbg(FYI, "file id match, oplock break\n");
-                               cinode = CIFS_I(cfile->dentry->d_inode);
+                               cinode = CIFS_I(d_inode(cfile->dentry));
 
                                if (!CIFS_CACHE_WRITE(cinode) &&
                                    rsp->OplockLevel == SMB2_OPLOCK_LEVEL_NONE)
index eab05e1aa587424863d6914eb351da9fdcf17437..54daee5ad4c102b71b3617317a58d15375f4e755 100644 (file)
@@ -524,7 +524,7 @@ smb2_print_stats(struct seq_file *m, struct cifs_tcon *tcon)
 static void
 smb2_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock)
 {
-       struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
+       struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
        struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
 
        cfile->fid.persistent_fid = fid->persistent_fid;
@@ -793,7 +793,7 @@ smb2_set_file_size(const unsigned int xid, struct cifs_tcon *tcon,
         * If extending file more than one page make sparse. Many Linux fs
         * make files sparse by default when extending via ftruncate
         */
-       inode = cfile->dentry->d_inode;
+       inode = d_inode(cfile->dentry);
 
        if (!set_alloc && (size > inode->i_size + 8192)) {
                __u8 set_sparse = 1;
@@ -1032,7 +1032,7 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
 
        xid = get_xid();
 
-       inode = cfile->dentry->d_inode;
+       inode = d_inode(cfile->dentry);
        cifsi = CIFS_I(inode);
 
        /* if file not oplocked can't be sure whether asking to extend size */
@@ -1083,7 +1083,7 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
 
        xid = get_xid();
 
-       inode = cfile->dentry->d_inode;
+       inode = d_inode(cfile->dentry);
        cifsi = CIFS_I(inode);
 
        /* Need to make file sparse, if not already, before freeing range. */
@@ -1115,7 +1115,7 @@ static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon,
 
        xid = get_xid();
 
-       inode = cfile->dentry->d_inode;
+       inode = d_inode(cfile->dentry);
        cifsi = CIFS_I(inode);
 
        /* if file not oplocked can't be sure whether asking to extend size */
index 72a4d10653d6e746919bae66d9fe46316cdaa812..ff9e1f8b16a4872158c05f688a9761a9a7a8781d 100644 (file)
@@ -50,9 +50,9 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name)
 
        if (direntry == NULL)
                return -EIO;
-       if (direntry->d_inode == NULL)
+       if (d_really_is_negative(direntry))
                return -EIO;
-       sb = direntry->d_inode->i_sb;
+       sb = d_inode(direntry)->i_sb;
        if (sb == NULL)
                return -EIO;
 
@@ -111,9 +111,9 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
 
        if (direntry == NULL)
                return -EIO;
-       if (direntry->d_inode == NULL)
+       if (d_really_is_negative(direntry))
                return -EIO;
-       sb = direntry->d_inode->i_sb;
+       sb = d_inode(direntry)->i_sb;
        if (sb == NULL)
                return -EIO;
 
@@ -177,12 +177,12 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
                        memcpy(pacl, ea_value, value_size);
                        if (pTcon->ses->server->ops->set_acl)
                                rc = pTcon->ses->server->ops->set_acl(pacl,
-                                               value_size, direntry->d_inode,
+                                               value_size, d_inode(direntry),
                                                full_path, CIFS_ACL_DACL);
                        else
                                rc = -EOPNOTSUPP;
                        if (rc == 0) /* force revalidate of the inode */
-                               CIFS_I(direntry->d_inode)->time = 0;
+                               CIFS_I(d_inode(direntry))->time = 0;
                        kfree(pacl);
                }
 #else
@@ -246,9 +246,9 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
 
        if (direntry == NULL)
                return -EIO;
-       if (direntry->d_inode == NULL)
+       if (d_really_is_negative(direntry))
                return -EIO;
-       sb = direntry->d_inode->i_sb;
+       sb = d_inode(direntry)->i_sb;
        if (sb == NULL)
                return -EIO;
 
@@ -324,7 +324,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
                                goto get_ea_exit; /* rc already EOPNOTSUPP */
 
                        pacl = pTcon->ses->server->ops->get_acl(cifs_sb,
-                                       direntry->d_inode, full_path, &acllen);
+                                       d_inode(direntry), full_path, &acllen);
                        if (IS_ERR(pacl)) {
                                rc = PTR_ERR(pacl);
                                cifs_dbg(VFS, "%s: error %zd getting sec desc\n",
@@ -382,9 +382,9 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
 
        if (direntry == NULL)
                return -EIO;
-       if (direntry->d_inode == NULL)
+       if (d_really_is_negative(direntry))
                return -EIO;
-       sb = direntry->d_inode->i_sb;
+       sb = d_inode(direntry)->i_sb;
        if (sb == NULL)
                return -EIO;
 
index 46ee6f238985a86186493cd22a245f4baa7638e0..5bb630a769e044942fcfa3e5910ffd841141ee47 100644 (file)
@@ -94,8 +94,8 @@ static void coda_flag_children(struct dentry *parent, int flag)
        spin_lock(&parent->d_lock);
        list_for_each_entry(de, &parent->d_subdirs, d_child) {
                /* don't know what to do with negative dentries */
-               if (de->d_inode ) 
-                       coda_flag_inode(de->d_inode, flag);
+               if (d_inode(de) ) 
+                       coda_flag_inode(d_inode(de), flag);
        }
        spin_unlock(&parent->d_lock);
        return; 
index 60cb88c1dd2bf88bb12f3e5451e33ed51d5ac1ff..fda9f4311212fe4a6d3b884d43dfdb7b5ff51e7e 100644 (file)
@@ -201,7 +201,7 @@ err_out:
 static int coda_link(struct dentry *source_de, struct inode *dir_inode, 
          struct dentry *de)
 {
-       struct inode *inode = source_de->d_inode;
+       struct inode *inode = d_inode(source_de);
         const char * name = de->d_name.name;
        int len = de->d_name.len;
        int error;
@@ -266,7 +266,7 @@ static int coda_unlink(struct inode *dir, struct dentry *de)
                return error;
 
        coda_dir_update_mtime(dir);
-       drop_nlink(de->d_inode);
+       drop_nlink(d_inode(de));
        return 0;
 }
 
@@ -279,8 +279,8 @@ static int coda_rmdir(struct inode *dir, struct dentry *de)
        error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len);
        if (!error) {
                /* VFS may delete the child */
-               if (de->d_inode)
-                       clear_nlink(de->d_inode);
+               if (d_really_is_positive(de))
+                       clear_nlink(d_inode(de));
 
                /* fix the link count of the parent */
                coda_dir_drop_nlink(dir);
@@ -303,14 +303,14 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
                             coda_i2f(new_dir), old_length, new_length,
                             (const char *) old_name, (const char *)new_name);
        if (!error) {
-               if (new_dentry->d_inode) {
+               if (d_really_is_positive(new_dentry)) {
                        if (d_is_dir(new_dentry)) {
                                coda_dir_drop_nlink(old_dir);
                                coda_dir_inc_nlink(new_dir);
                        }
                        coda_dir_update_mtime(old_dir);
                        coda_dir_update_mtime(new_dir);
-                       coda_flag_inode(new_dentry->d_inode, C_VATTR);
+                       coda_flag_inode(d_inode(new_dentry), C_VATTR);
                } else {
                        coda_flag_inode(old_dir, C_VATTR);
                        coda_flag_inode(new_dir, C_VATTR);
@@ -449,13 +449,13 @@ static int coda_dentry_revalidate(struct dentry *de, unsigned int flags)
        if (flags & LOOKUP_RCU)
                return -ECHILD;
 
-       inode = de->d_inode;
+       inode = d_inode(de);
        if (!inode || is_root_inode(inode))
                goto out;
        if (is_bad_inode(inode))
                goto bad;
 
-       cii = ITOC(de->d_inode);
+       cii = ITOC(d_inode(de));
        if (!(cii->c_flags & (C_PURGE | C_FLUSH)))
                goto out;
 
@@ -487,11 +487,11 @@ static int coda_dentry_delete(const struct dentry * dentry)
 {
        int flags;
 
-       if (!dentry->d_inode
+       if (d_really_is_negative(dentry)
                return 0;
 
-       flags = (ITOC(dentry->d_inode)->c_flags) & C_PURGE;
-       if (is_bad_inode(dentry->d_inode) || flags) {
+       flags = (ITOC(d_inode(dentry))->c_flags) & C_PURGE;
+       if (is_bad_inode(d_inode(dentry)) || flags) {
                return 1;
        }
        return 0;
index 82ec68b59208282f49ece9fb06e0fdb5135c3749..cac1390b87a35a92b7089aaa574f683369088da7 100644 (file)
@@ -257,15 +257,15 @@ static void coda_evict_inode(struct inode *inode)
 
 int coda_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 {
-       int err = coda_revalidate_inode(dentry->d_inode);
+       int err = coda_revalidate_inode(d_inode(dentry));
        if (!err)
-               generic_fillattr(dentry->d_inode, stat);
+               generic_fillattr(d_inode(dentry), stat);
        return err;
 }
 
 int coda_setattr(struct dentry *de, struct iattr *iattr)
 {
-       struct inode *inode = de->d_inode;
+       struct inode *inode = d_inode(de);
        struct coda_vattr vattr;
        int error;
 
index 4326d172fc27fb697d5c94baf110f68b721401d4..f36a4040afb8019ee689bc3058957af1c75b758a 100644 (file)
@@ -72,7 +72,7 @@ static long coda_pioctl(struct file *filp, unsigned int cmd,
        if (error)
                return error;
 
-       target_inode = path.dentry->d_inode;
+       target_inode = d_inode(path.dentry);
 
        /* return if it is not a Coda inode */
        if (target_inode->i_sb != inode->i_sb) {
index 5bb6e27298a469d3a20bf3e54ef37e79d3435f76..9b1ffaa0572e5825d8c617880bfbc19be166313b 100644 (file)
@@ -820,8 +820,8 @@ int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out)
        case CODA_FLUSH:
                coda_cache_clear_all(sb);
                shrink_dcache_sb(sb);
-               if (sb->s_root->d_inode)
-                       coda_flag_inode(sb->s_root->d_inode, C_FLUSH);
+               if (d_really_is_positive(sb->s_root))
+                       coda_flag_inode(d_inode(sb->s_root), C_FLUSH);
                break;
 
        case CODA_PURGEUSER:
index acb3d63bc9dc763cf8e3518cfe66a233ee9ee63f..c81ce7f200a6d9944b4670de2729f909048e773c 100644 (file)
@@ -289,7 +289,7 @@ static int configfs_create_dir(struct config_item *item, struct dentry *dentry)
        configfs_set_dir_dirent_depth(p->d_fsdata, dentry->d_fsdata);
        error = configfs_create(dentry, mode, init_dir);
        if (!error) {
-               inc_nlink(p->d_inode);
+               inc_nlink(d_inode(p));
                item->ci_dentry = dentry;
        } else {
                struct configfs_dirent *sd = dentry->d_fsdata;
@@ -375,8 +375,8 @@ static void remove_dir(struct dentry * d)
        list_del_init(&sd->s_sibling);
        spin_unlock(&configfs_dirent_lock);
        configfs_put(sd);
-       if (d->d_inode)
-               simple_rmdir(parent->d_inode,d);
+       if (d_really_is_positive(d))
+               simple_rmdir(d_inode(parent),d);
 
        pr_debug(" o %pd removing done (%d)\n", d, d_count(d));
 
@@ -513,7 +513,7 @@ static int configfs_detach_prep(struct dentry *dentry, struct mutex **wait_mutex
                        /* Abort if racing with mkdir() */
                        if (sd->s_type & CONFIGFS_USET_IN_MKDIR) {
                                if (wait_mutex)
-                                       *wait_mutex = &sd->s_dentry->d_inode->i_mutex;
+                                       *wait_mutex = &d_inode(sd->s_dentry)->i_mutex;
                                return -EAGAIN;
                        }
 
@@ -624,13 +624,13 @@ static void detach_groups(struct config_group *group)
 
                child = sd->s_dentry;
 
-               mutex_lock(&child->d_inode->i_mutex);
+               mutex_lock(&d_inode(child)->i_mutex);
 
                configfs_detach_group(sd->s_element);
-               child->d_inode->i_flags |= S_DEAD;
+               d_inode(child)->i_flags |= S_DEAD;
                dont_mount(child);
 
-               mutex_unlock(&child->d_inode->i_mutex);
+               mutex_unlock(&d_inode(child)->i_mutex);
 
                d_delete(child);
                dput(child);
@@ -672,7 +672,7 @@ static int create_default_group(struct config_group *parent_group,
                        sd = child->d_fsdata;
                        sd->s_type |= CONFIGFS_USET_DEFAULT;
                } else {
-                       BUG_ON(child->d_inode);
+                       BUG_ON(d_inode(child));
                        d_drop(child);
                        dput(child);
                }
@@ -818,11 +818,11 @@ static int configfs_attach_item(struct config_item *parent_item,
                         * the VFS may already have hit and used them. Thus,
                         * we must lock them as rmdir() would.
                         */
-                       mutex_lock(&dentry->d_inode->i_mutex);
+                       mutex_lock(&d_inode(dentry)->i_mutex);
                        configfs_remove_dir(item);
-                       dentry->d_inode->i_flags |= S_DEAD;
+                       d_inode(dentry)->i_flags |= S_DEAD;
                        dont_mount(dentry);
-                       mutex_unlock(&dentry->d_inode->i_mutex);
+                       mutex_unlock(&d_inode(dentry)->i_mutex);
                        d_delete(dentry);
                }
        }
@@ -858,16 +858,16 @@ static int configfs_attach_group(struct config_item *parent_item,
                 * We must also lock the inode to remove it safely in case of
                 * error, as rmdir() would.
                 */
-               mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD);
+               mutex_lock_nested(&d_inode(dentry)->i_mutex, I_MUTEX_CHILD);
                configfs_adjust_dir_dirent_depth_before_populate(sd);
                ret = populate_groups(to_config_group(item));
                if (ret) {
                        configfs_detach_item(item);
-                       dentry->d_inode->i_flags |= S_DEAD;
+                       d_inode(dentry)->i_flags |= S_DEAD;
                        dont_mount(dentry);
                }
                configfs_adjust_dir_dirent_depth_after_populate(sd);
-               mutex_unlock(&dentry->d_inode->i_mutex);
+               mutex_unlock(&d_inode(dentry)->i_mutex);
                if (ret)
                        d_delete(dentry);
        }
@@ -1075,7 +1075,7 @@ int configfs_depend_item(struct configfs_subsystem *subsys,
         * subsystem is really registered, and so we need to lock out
         * configfs_[un]register_subsystem().
         */
-       mutex_lock(&root->d_inode->i_mutex);
+       mutex_lock(&d_inode(root)->i_mutex);
 
        root_sd = root->d_fsdata;
 
@@ -1111,7 +1111,7 @@ int configfs_depend_item(struct configfs_subsystem *subsys,
 out_unlock_dirent_lock:
        spin_unlock(&configfs_dirent_lock);
 out_unlock_fs:
-       mutex_unlock(&root->d_inode->i_mutex);
+       mutex_unlock(&d_inode(root)->i_mutex);
 
        /*
         * If we succeeded, the fs is pinned via other methods.  If not,
@@ -1453,11 +1453,11 @@ int configfs_rename_dir(struct config_item * item, const char *new_name)
        down_write(&configfs_rename_sem);
        parent = item->parent->dentry;
 
-       mutex_lock(&parent->d_inode->i_mutex);
+       mutex_lock(&d_inode(parent)->i_mutex);
 
        new_dentry = lookup_one_len(new_name, parent, strlen(new_name));
        if (!IS_ERR(new_dentry)) {
-               if (!new_dentry->d_inode) {
+               if (d_really_is_negative(new_dentry)) {
                        error = config_item_set_name(item, "%s", new_name);
                        if (!error) {
                                d_add(new_dentry, NULL);
@@ -1469,7 +1469,7 @@ int configfs_rename_dir(struct config_item * item, const char *new_name)
                        error = -EEXIST;
                dput(new_dentry);
        }
-       mutex_unlock(&parent->d_inode->i_mutex);
+       mutex_unlock(&d_inode(parent)->i_mutex);
        up_write(&configfs_rename_sem);
 
        return error;
@@ -1482,7 +1482,7 @@ static int configfs_dir_open(struct inode *inode, struct file *file)
        struct configfs_dirent * parent_sd = dentry->d_fsdata;
        int err;
 
-       mutex_lock(&dentry->d_inode->i_mutex);
+       mutex_lock(&d_inode(dentry)->i_mutex);
        /*
         * Fake invisibility if dir belongs to a group/default groups hierarchy
         * being attached
@@ -1495,7 +1495,7 @@ static int configfs_dir_open(struct inode *inode, struct file *file)
                else
                        err = 0;
        }
-       mutex_unlock(&dentry->d_inode->i_mutex);
+       mutex_unlock(&d_inode(dentry)->i_mutex);
 
        return err;
 }
@@ -1505,11 +1505,11 @@ static int configfs_dir_close(struct inode *inode, struct file *file)
        struct dentry * dentry = file->f_path.dentry;
        struct configfs_dirent * cursor = file->private_data;
 
-       mutex_lock(&dentry->d_inode->i_mutex);
+       mutex_lock(&d_inode(dentry)->i_mutex);
        spin_lock(&configfs_dirent_lock);
        list_del_init(&cursor->s_sibling);
        spin_unlock(&configfs_dirent_lock);
-       mutex_unlock(&dentry->d_inode->i_mutex);
+       mutex_unlock(&d_inode(dentry)->i_mutex);
 
        release_configfs_dirent(cursor);
 
@@ -1567,7 +1567,7 @@ static int configfs_readdir(struct file *file, struct dir_context *ctx)
                spin_lock(&configfs_dirent_lock);
                dentry = next->s_dentry;
                if (dentry)
-                       inode = dentry->d_inode;
+                       inode = d_inode(dentry);
                if (inode)
                        ino = inode->i_ino;
                spin_unlock(&configfs_dirent_lock);
@@ -1590,7 +1590,7 @@ static loff_t configfs_dir_lseek(struct file *file, loff_t offset, int whence)
 {
        struct dentry * dentry = file->f_path.dentry;
 
-       mutex_lock(&dentry->d_inode->i_mutex);
+       mutex_lock(&d_inode(dentry)->i_mutex);
        switch (whence) {
                case 1:
                        offset += file->f_pos;
@@ -1598,7 +1598,7 @@ static loff_t configfs_dir_lseek(struct file *file, loff_t offset, int whence)
                        if (offset >= 0)
                                break;
                default:
-                       mutex_unlock(&dentry->d_inode->i_mutex);
+                       mutex_unlock(&d_inode(dentry)->i_mutex);
                        return -EINVAL;
        }
        if (offset != file->f_pos) {
@@ -1624,7 +1624,7 @@ static loff_t configfs_dir_lseek(struct file *file, loff_t offset, int whence)
                        spin_unlock(&configfs_dirent_lock);
                }
        }
-       mutex_unlock(&dentry->d_inode->i_mutex);
+       mutex_unlock(&d_inode(dentry)->i_mutex);
        return offset;
 }
 
@@ -1654,7 +1654,7 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys)
        sd = root->d_fsdata;
        link_group(to_config_group(sd->s_element), group);
 
-       mutex_lock_nested(&root->d_inode->i_mutex, I_MUTEX_PARENT);
+       mutex_lock_nested(&d_inode(root)->i_mutex, I_MUTEX_PARENT);
 
        err = -ENOMEM;
        dentry = d_alloc_name(root, group->cg_item.ci_name);
@@ -1664,7 +1664,7 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys)
                err = configfs_attach_group(sd->s_element, &group->cg_item,
                                            dentry);
                if (err) {
-                       BUG_ON(dentry->d_inode);
+                       BUG_ON(d_inode(dentry));
                        d_drop(dentry);
                        dput(dentry);
                } else {
@@ -1674,7 +1674,7 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys)
                }
        }
 
-       mutex_unlock(&root->d_inode->i_mutex);
+       mutex_unlock(&d_inode(root)->i_mutex);
 
        if (err) {
                unlink_group(group);
@@ -1695,9 +1695,9 @@ void configfs_unregister_subsystem(struct configfs_subsystem *subsys)
                return;
        }
 
-       mutex_lock_nested(&root->d_inode->i_mutex,
+       mutex_lock_nested(&d_inode(root)->i_mutex,
                          I_MUTEX_PARENT);
-       mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD);
+       mutex_lock_nested(&d_inode(dentry)->i_mutex, I_MUTEX_CHILD);
        mutex_lock(&configfs_symlink_mutex);
        spin_lock(&configfs_dirent_lock);
        if (configfs_detach_prep(dentry, NULL)) {
@@ -1706,13 +1706,13 @@ void configfs_unregister_subsystem(struct configfs_subsystem *subsys)
        spin_unlock(&configfs_dirent_lock);
        mutex_unlock(&configfs_symlink_mutex);
        configfs_detach_group(&group->cg_item);
-       dentry->d_inode->i_flags |= S_DEAD;
+       d_inode(dentry)->i_flags |= S_DEAD;
        dont_mount(dentry);
-       mutex_unlock(&dentry->d_inode->i_mutex);
+       mutex_unlock(&d_inode(dentry)->i_mutex);
 
        d_delete(dentry);
 
-       mutex_unlock(&root->d_inode->i_mutex);
+       mutex_unlock(&d_inode(root)->i_mutex);
 
        dput(dentry);
 
index 56d2cdc9ae0a7213f91bb5e332b1513fda887b79..403269ffcdf3518b45f878166270c12e3365c17e 100644 (file)
@@ -326,10 +326,10 @@ int configfs_create_file(struct config_item * item, const struct configfs_attrib
        umode_t mode = (attr->ca_mode & S_IALLUGO) | S_IFREG;
        int error = 0;
 
-       mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_NORMAL);
+       mutex_lock_nested(&d_inode(dir)->i_mutex, I_MUTEX_NORMAL);
        error = configfs_make_dirent(parent_sd, NULL, (void *) attr, mode,
                                     CONFIGFS_ITEM_ATTR);
-       mutex_unlock(&dir->d_inode->i_mutex);
+       mutex_unlock(&d_inode(dir)->i_mutex);
 
        return error;
 }
index 5423a6a6ecc8350c0284d307ac47cf6afad9238a..8d89f5fd0331c6a8b0ff9648251199248995aa50 100644 (file)
@@ -56,7 +56,7 @@ static const struct inode_operations configfs_inode_operations ={
 
 int configfs_setattr(struct dentry * dentry, struct iattr * iattr)
 {
-       struct inode * inode = dentry->d_inode;
+       struct inode * inode = d_inode(dentry);
        struct configfs_dirent * sd = dentry->d_fsdata;
        struct iattr * sd_iattr;
        unsigned int ia_valid = iattr->ia_valid;
@@ -186,7 +186,7 @@ int configfs_create(struct dentry * dentry, umode_t mode, void (*init)(struct in
        if (!dentry)
                return -ENOENT;
 
-       if (dentry->d_inode)
+       if (d_really_is_positive(dentry))
                return -EEXIST;
 
        sd = dentry->d_fsdata;
@@ -194,7 +194,7 @@ int configfs_create(struct dentry * dentry, umode_t mode, void (*init)(struct in
        if (!inode)
                return -ENOMEM;
 
-       p_inode = dentry->d_parent->d_inode;
+       p_inode = d_inode(dentry->d_parent);
        p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME;
        configfs_set_inode_lock_class(sd, inode);
 
@@ -236,11 +236,11 @@ void configfs_drop_dentry(struct configfs_dirent * sd, struct dentry * parent)
 
        if (dentry) {
                spin_lock(&dentry->d_lock);
-               if (!d_unhashed(dentry) && dentry->d_inode) {
+               if (!d_unhashed(dentry) && d_really_is_positive(dentry)) {
                        dget_dlock(dentry);
                        __d_drop(dentry);
                        spin_unlock(&dentry->d_lock);
-                       simple_unlink(parent->d_inode, dentry);
+                       simple_unlink(d_inode(parent), dentry);
                } else
                        spin_unlock(&dentry->d_lock);
        }
@@ -251,11 +251,11 @@ void configfs_hash_and_remove(struct dentry * dir, const char * name)
        struct configfs_dirent * sd;
        struct configfs_dirent * parent_sd = dir->d_fsdata;
 
-       if (dir->d_inode == NULL)
+       if (d_really_is_negative(dir))
                /* no inode means this hasn't been made visible yet */
                return;
 
-       mutex_lock(&dir->d_inode->i_mutex);
+       mutex_lock(&d_inode(dir)->i_mutex);
        list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
                if (!sd->s_element)
                        continue;
@@ -268,5 +268,5 @@ void configfs_hash_and_remove(struct dentry * dir, const char * name)
                        break;
                }
        }
-       mutex_unlock(&dir->d_inode->i_mutex);
+       mutex_unlock(&d_inode(dir)->i_mutex);
 }
index da94e41bdbf685b02b567e95e3c0f37db33c2795..5373567420912c87b1d82f3c605e308bda94c68b 100644 (file)
@@ -173,5 +173,5 @@ MODULE_LICENSE("GPL");
 MODULE_VERSION("0.0.2");
 MODULE_DESCRIPTION("Simple RAM filesystem for user driven kernel subsystem configuration.");
 
-module_init(configfs_init);
+core_initcall(configfs_init);
 module_exit(configfs_exit);
index 0bb0aecb556cd15be7c902b3b315345a1017588f..6f65f00e58ecdc695284de68b832f3822247f594 100644 (file)
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -209,7 +209,7 @@ ssize_t dax_do_io(struct kiocb *iocb, struct inode *inode,
        }
 
        /* Protects against truncate */
-       atomic_inc(&inode->i_dio_count);
+       inode_dio_begin(inode);
 
        retval = dax_io(inode, iter, pos, end, get_block, &bh);
 
@@ -219,7 +219,7 @@ ssize_t dax_do_io(struct kiocb *iocb, struct inode *inode,
        if ((retval > 0) && end_io)
                end_io(iocb, pos, retval, bh.b_private);
 
-       inode_dio_done(inode);
+       inode_dio_end(inode);
  out:
        return retval;
 }
index 517e6493843824f716b721845075b28d8e7d229d..830a7e76f5c64067e46fad8fd368e9112ddae7a9 100644 (file)
@@ -45,7 +45,7 @@ const struct file_operations debugfs_file_operations = {
 
 static void *debugfs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-       nd_set_link(nd, dentry->d_inode->i_private);
+       nd_set_link(nd, d_inode(dentry)->i_private);
        return NULL;
 }
 
index c9ee0dfe90b5cfaa0f90c486812439b0f7a84b0e..c1e7ffb0dab658ecd21c449bf36467b14e0b75d6 100644 (file)
@@ -46,7 +46,7 @@ static struct inode *debugfs_get_inode(struct super_block *sb)
 
 static inline int debugfs_positive(struct dentry *dentry)
 {
-       return dentry->d_inode && !d_unhashed(dentry);
+       return d_really_is_positive(dentry) && !d_unhashed(dentry);
 }
 
 struct debugfs_mount_opts {
@@ -124,7 +124,7 @@ static int debugfs_parse_options(char *data, struct debugfs_mount_opts *opts)
 static int debugfs_apply_options(struct super_block *sb)
 {
        struct debugfs_fs_info *fsi = sb->s_fs_info;
-       struct inode *inode = sb->s_root->d_inode;
+       struct inode *inode = d_inode(sb->s_root);
        struct debugfs_mount_opts *opts = &fsi->mount_opts;
 
        inode->i_mode &= ~S_IALLUGO;
@@ -188,7 +188,7 @@ static struct vfsmount *debugfs_automount(struct path *path)
 {
        struct vfsmount *(*f)(void *);
        f = (struct vfsmount *(*)(void *))path->dentry->d_fsdata;
-       return f(path->dentry->d_inode->i_private);
+       return f(d_inode(path->dentry)->i_private);
 }
 
 static const struct dentry_operations debugfs_dops = {
@@ -270,20 +270,20 @@ static struct dentry *start_creating(const char *name, struct dentry *parent)
        if (!parent)
                parent = debugfs_mount->mnt_root;
 
-       mutex_lock(&parent->d_inode->i_mutex);
+       mutex_lock(&d_inode(parent)->i_mutex);
        dentry = lookup_one_len(name, parent, strlen(name));
-       if (!IS_ERR(dentry) && dentry->d_inode) {
+       if (!IS_ERR(dentry) && d_really_is_positive(dentry)) {
                dput(dentry);
                dentry = ERR_PTR(-EEXIST);
        }
        if (IS_ERR(dentry))
-               mutex_unlock(&parent->d_inode->i_mutex);
+               mutex_unlock(&d_inode(parent)->i_mutex);
        return dentry;
 }
 
 static struct dentry *failed_creating(struct dentry *dentry)
 {
-       mutex_unlock(&dentry->d_parent->d_inode->i_mutex);
+       mutex_unlock(&d_inode(dentry->d_parent)->i_mutex);
        dput(dentry);
        simple_release_fs(&debugfs_mount, &debugfs_mount_count);
        return NULL;
@@ -291,7 +291,7 @@ static struct dentry *failed_creating(struct dentry *dentry)
 
 static struct dentry *end_creating(struct dentry *dentry)
 {
-       mutex_unlock(&dentry->d_parent->d_inode->i_mutex);
+       mutex_unlock(&d_inode(dentry->d_parent)->i_mutex);
        return dentry;
 }
 
@@ -344,7 +344,7 @@ struct dentry *debugfs_create_file(const char *name, umode_t mode,
        inode->i_fop = fops ? fops : &debugfs_file_operations;
        inode->i_private = data;
        d_instantiate(dentry, inode);
-       fsnotify_create(dentry->d_parent->d_inode, dentry);
+       fsnotify_create(d_inode(dentry->d_parent), dentry);
        return end_creating(dentry);
 }
 EXPORT_SYMBOL_GPL(debugfs_create_file);
@@ -384,7 +384,7 @@ struct dentry *debugfs_create_file_size(const char *name, umode_t mode,
        struct dentry *de = debugfs_create_file(name, mode, parent, data, fops);
 
        if (de)
-               de->d_inode->i_size = file_size;
+               d_inode(de)->i_size = file_size;
        return de;
 }
 EXPORT_SYMBOL_GPL(debugfs_create_file_size);
@@ -426,8 +426,8 @@ struct dentry *debugfs_create_dir(const char *name, struct dentry *parent)
        /* directory inodes start off with i_nlink == 2 (for "." entry) */
        inc_nlink(inode);
        d_instantiate(dentry, inode);
-       inc_nlink(dentry->d_parent->d_inode);
-       fsnotify_mkdir(dentry->d_parent->d_inode, dentry);
+       inc_nlink(d_inode(dentry->d_parent));
+       fsnotify_mkdir(d_inode(dentry->d_parent), dentry);
        return end_creating(dentry);
 }
 EXPORT_SYMBOL_GPL(debugfs_create_dir);
@@ -525,9 +525,9 @@ static int __debugfs_remove(struct dentry *dentry, struct dentry *parent)
        if (debugfs_positive(dentry)) {
                dget(dentry);
                if (d_is_dir(dentry))
-                       ret = simple_rmdir(parent->d_inode, dentry);
+                       ret = simple_rmdir(d_inode(parent), dentry);
                else
-                       simple_unlink(parent->d_inode, dentry);
+                       simple_unlink(d_inode(parent), dentry);
                if (!ret)
                        d_delete(dentry);
                dput(dentry);
@@ -557,12 +557,12 @@ void debugfs_remove(struct dentry *dentry)
                return;
 
        parent = dentry->d_parent;
-       if (!parent || !parent->d_inode)
+       if (!parent || d_really_is_negative(parent))
                return;
 
-       mutex_lock(&parent->d_inode->i_mutex);
+       mutex_lock(&d_inode(parent)->i_mutex);
        ret = __debugfs_remove(dentry, parent);
-       mutex_unlock(&parent->d_inode->i_mutex);
+       mutex_unlock(&d_inode(parent)->i_mutex);
        if (!ret)
                simple_release_fs(&debugfs_mount, &debugfs_mount_count);
 }
@@ -588,12 +588,12 @@ void debugfs_remove_recursive(struct dentry *dentry)
                return;
 
        parent = dentry->d_parent;
-       if (!parent || !parent->d_inode)
+       if (!parent || d_really_is_negative(parent))
                return;
 
        parent = dentry;
  down:
-       mutex_lock(&parent->d_inode->i_mutex);
+       mutex_lock(&d_inode(parent)->i_mutex);
  loop:
        /*
         * The parent->d_subdirs is protected by the d_lock. Outside that
@@ -608,7 +608,7 @@ void debugfs_remove_recursive(struct dentry *dentry)
                /* perhaps simple_empty(child) makes more sense */
                if (!list_empty(&child->d_subdirs)) {
                        spin_unlock(&parent->d_lock);
-                       mutex_unlock(&parent->d_inode->i_mutex);
+                       mutex_unlock(&d_inode(parent)->i_mutex);
                        parent = child;
                        goto down;
                }
@@ -629,10 +629,10 @@ void debugfs_remove_recursive(struct dentry *dentry)
        }
        spin_unlock(&parent->d_lock);
 
-       mutex_unlock(&parent->d_inode->i_mutex);
+       mutex_unlock(&d_inode(parent)->i_mutex);
        child = parent;
        parent = parent->d_parent;
-       mutex_lock(&parent->d_inode->i_mutex);
+       mutex_lock(&d_inode(parent)->i_mutex);
 
        if (child != dentry)
                /* go up */
@@ -640,7 +640,7 @@ void debugfs_remove_recursive(struct dentry *dentry)
 
        if (!__debugfs_remove(child, parent))
                simple_release_fs(&debugfs_mount, &debugfs_mount_count);
-       mutex_unlock(&parent->d_inode->i_mutex);
+       mutex_unlock(&d_inode(parent)->i_mutex);
 }
 EXPORT_SYMBOL_GPL(debugfs_remove_recursive);
 
@@ -672,27 +672,27 @@ struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
 
        trap = lock_rename(new_dir, old_dir);
        /* Source or destination directories don't exist? */
-       if (!old_dir->d_inode || !new_dir->d_inode)
+       if (d_really_is_negative(old_dir) || d_really_is_negative(new_dir))
                goto exit;
        /* Source does not exist, cyclic rename, or mountpoint? */
-       if (!old_dentry->d_inode || old_dentry == trap ||
+       if (d_really_is_negative(old_dentry) || old_dentry == trap ||
            d_mountpoint(old_dentry))
                goto exit;
        dentry = lookup_one_len(new_name, new_dir, strlen(new_name));
        /* Lookup failed, cyclic rename or target exists? */
-       if (IS_ERR(dentry) || dentry == trap || dentry->d_inode)
+       if (IS_ERR(dentry) || dentry == trap || d_really_is_positive(dentry))
                goto exit;
 
        old_name = fsnotify_oldname_init(old_dentry->d_name.name);
 
-       error = simple_rename(old_dir->d_inode, old_dentry, new_dir->d_inode,
+       error = simple_rename(d_inode(old_dir), old_dentry, d_inode(new_dir),
                dentry);
        if (error) {
                fsnotify_oldname_free(old_name);
                goto exit;
        }
        d_move(old_dentry, dentry);
-       fsnotify_move(old_dir->d_inode, new_dir->d_inode, old_name,
+       fsnotify_move(d_inode(old_dir), d_inode(new_dir), old_name,
                d_is_dir(old_dentry),
                NULL, old_dentry);
        fsnotify_oldname_free(old_name);
index cfe8466f7fef51d6ecdf338f0d71b6cc00aa19ca..add566303c684336cce3d8f9c4fa0f98678adafc 100644 (file)
@@ -253,7 +253,7 @@ static int mknod_ptmx(struct super_block *sb)
        if (!uid_valid(root_uid) || !gid_valid(root_gid))
                return -EINVAL;
 
-       mutex_lock(&root->d_inode->i_mutex);
+       mutex_lock(&d_inode(root)->i_mutex);
 
        /* If we have already created ptmx node, return */
        if (fsi->ptmx_dentry) {
@@ -290,7 +290,7 @@ static int mknod_ptmx(struct super_block *sb)
        fsi->ptmx_dentry = dentry;
        rc = 0;
 out:
-       mutex_unlock(&root->d_inode->i_mutex);
+       mutex_unlock(&d_inode(root)->i_mutex);
        return rc;
 }
 
@@ -298,7 +298,7 @@ static void update_ptmx_mode(struct pts_fs_info *fsi)
 {
        struct inode *inode;
        if (fsi->ptmx_dentry) {
-               inode = fsi->ptmx_dentry->d_inode;
+               inode = d_inode(fsi->ptmx_dentry);
                inode->i_mode = S_IFCHR|fsi->mount_opts.ptmxmode;
        }
 }
@@ -602,18 +602,18 @@ struct inode *devpts_pty_new(struct inode *ptmx_inode, dev_t device, int index,
 
        sprintf(s, "%d", index);
 
-       mutex_lock(&root->d_inode->i_mutex);
+       mutex_lock(&d_inode(root)->i_mutex);
 
        dentry = d_alloc_name(root, s);
        if (dentry) {
                d_add(dentry, inode);
-               fsnotify_create(root->d_inode, dentry);
+               fsnotify_create(d_inode(root), dentry);
        } else {
                iput(inode);
                inode = ERR_PTR(-ENOMEM);
        }
 
-       mutex_unlock(&root->d_inode->i_mutex);
+       mutex_unlock(&d_inode(root)->i_mutex);
 
        return inode;
 }
@@ -658,7 +658,7 @@ void devpts_pty_kill(struct inode *inode)
 
        BUG_ON(inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR));
 
-       mutex_lock(&root->d_inode->i_mutex);
+       mutex_lock(&d_inode(root)->i_mutex);
 
        dentry = d_find_alias(inode);
 
@@ -667,7 +667,7 @@ void devpts_pty_kill(struct inode *inode)
        dput(dentry);   /* d_alloc_name() in devpts_pty_new() */
        dput(dentry);           /* d_find_alias above */
 
-       mutex_unlock(&root->d_inode->i_mutex);
+       mutex_unlock(&d_inode(root)->i_mutex);
 }
 
 static int __init init_devpts_fs(void)
index c3b560b24a463c50569a2a37c5d04f8d5af92c4d..745d2342651a0b87fcb9dd5b5b50e95b9129e117 100644 (file)
@@ -253,7 +253,9 @@ static ssize_t dio_complete(struct dio *dio, loff_t offset, ssize_t ret,
        if (dio->end_io && dio->result)
                dio->end_io(dio->iocb, offset, transferred, dio->private);
 
-       inode_dio_done(dio->inode);
+       if (!(dio->flags & DIO_SKIP_DIO_COUNT))
+               inode_dio_end(dio->inode);
+
        if (is_async) {
                if (dio->rw & WRITE) {
                        int err;
@@ -1195,7 +1197,8 @@ do_blockdev_direct_IO(struct kiocb *iocb, struct inode *inode,
        /*
         * Will be decremented at I/O completion time.
         */
-       atomic_inc(&inode->i_dio_count);
+       if (!(dio->flags & DIO_SKIP_DIO_COUNT))
+               inode_dio_begin(inode);
 
        retval = 0;
        sdio.blkbits = blkbits;
index 719e1ce1c60930ec8e2c316631d21ec2bac03cc3..97315f2f68164f45f41176abeb1d0317467280f4 100644 (file)
@@ -1326,7 +1326,7 @@ static int ecryptfs_read_headers_virt(char *page_virt,
        if (rc)
                goto out;
        if (!(crypt_stat->flags & ECRYPTFS_I_SIZE_INITIALIZED))
-               ecryptfs_i_size_init(page_virt, ecryptfs_dentry->d_inode);
+               ecryptfs_i_size_init(page_virt, d_inode(ecryptfs_dentry));
        offset += MAGIC_ECRYPTFS_MARKER_SIZE_BYTES;
        rc = ecryptfs_process_flags(crypt_stat, (page_virt + offset),
                                    &bytes_read);
@@ -1425,7 +1425,7 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)
 {
        int rc;
        char *page_virt;
-       struct inode *ecryptfs_inode = ecryptfs_dentry->d_inode;
+       struct inode *ecryptfs_inode = d_inode(ecryptfs_dentry);
        struct ecryptfs_crypt_stat *crypt_stat =
            &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
        struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
index 4000f6b3a7504505bb46d3d5ef2946b53e3d5cc9..8db0b464483f9b028f78e779a8337c3d33ca1c64 100644 (file)
@@ -54,11 +54,11 @@ static int ecryptfs_d_revalidate(struct dentry *dentry, unsigned int flags)
                return -ECHILD;
 
        rc = lower_dentry->d_op->d_revalidate(lower_dentry, flags);
-       if (dentry->d_inode) {
+       if (d_really_is_positive(dentry)) {
                struct inode *lower_inode =
-                       ecryptfs_inode_to_lower(dentry->d_inode);
+                       ecryptfs_inode_to_lower(d_inode(dentry));
 
-               fsstack_copy_attr_all(dentry->d_inode, lower_inode);
+               fsstack_copy_attr_all(d_inode(dentry), lower_inode);
        }
        return rc;
 }
index a65786e26b05ac97dbaab6a6258e533aa842cece..72afcc629d7b1fee2963fb90e1691a221eb77d8e 100644 (file)
@@ -130,7 +130,7 @@ struct kmem_cache *ecryptfs_file_info_cache;
 
 static int read_or_initialize_metadata(struct dentry *dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
        struct ecryptfs_crypt_stat *crypt_stat;
        int rc;
index b08b5187f6622cb6c7934d6dba9fcdfdbb0aefb6..fc850b55db67a27a99663596e1e8c711c8d71237 100644 (file)
@@ -41,13 +41,13 @@ static struct dentry *lock_parent(struct dentry *dentry)
        struct dentry *dir;
 
        dir = dget_parent(dentry);
-       mutex_lock_nested(&(dir->d_inode->i_mutex), I_MUTEX_PARENT);
+       mutex_lock_nested(&(d_inode(dir)->i_mutex), I_MUTEX_PARENT);
        return dir;
 }
 
 static void unlock_dir(struct dentry *dir)
 {
-       mutex_unlock(&dir->d_inode->i_mutex);
+       mutex_unlock(&d_inode(dir)->i_mutex);
        dput(dir);
 }
 
@@ -131,7 +131,7 @@ struct inode *ecryptfs_get_inode(struct inode *lower_inode,
 static int ecryptfs_interpose(struct dentry *lower_dentry,
                              struct dentry *dentry, struct super_block *sb)
 {
-       struct inode *inode = ecryptfs_get_inode(lower_dentry->d_inode, sb);
+       struct inode *inode = ecryptfs_get_inode(d_inode(lower_dentry), sb);
 
        if (IS_ERR(inode))
                return PTR_ERR(inode);
@@ -189,21 +189,21 @@ ecryptfs_do_create(struct inode *directory_inode,
 
        lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
        lower_dir_dentry = lock_parent(lower_dentry);
-       rc = vfs_create(lower_dir_dentry->d_inode, lower_dentry, mode, true);
+       rc = vfs_create(d_inode(lower_dir_dentry), lower_dentry, mode, true);
        if (rc) {
                printk(KERN_ERR "%s: Failure to create dentry in lower fs; "
                       "rc = [%d]\n", __func__, rc);
                inode = ERR_PTR(rc);
                goto out_lock;
        }
-       inode = __ecryptfs_get_inode(lower_dentry->d_inode,
+       inode = __ecryptfs_get_inode(d_inode(lower_dentry),
                                     directory_inode->i_sb);
        if (IS_ERR(inode)) {
-               vfs_unlink(lower_dir_dentry->d_inode, lower_dentry, NULL);
+               vfs_unlink(d_inode(lower_dir_dentry), lower_dentry, NULL);
                goto out_lock;
        }
-       fsstack_copy_attr_times(directory_inode, lower_dir_dentry->d_inode);
-       fsstack_copy_inode_size(directory_inode, lower_dir_dentry->d_inode);
+       fsstack_copy_attr_times(directory_inode, d_inode(lower_dir_dentry));
+       fsstack_copy_inode_size(directory_inode, d_inode(lower_dir_dentry));
 out_lock:
        unlock_dir(lower_dir_dentry);
        return inode;
@@ -332,7 +332,7 @@ static int ecryptfs_lookup_interpose(struct dentry *dentry,
                                     struct dentry *lower_dentry,
                                     struct inode *dir_inode)
 {
-       struct inode *inode, *lower_inode = lower_dentry->d_inode;
+       struct inode *inode, *lower_inode = d_inode(lower_dentry);
        struct ecryptfs_dentry_info *dentry_info;
        struct vfsmount *lower_mnt;
        int rc = 0;
@@ -347,14 +347,14 @@ static int ecryptfs_lookup_interpose(struct dentry *dentry,
        }
 
        lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(dentry->d_parent));
-       fsstack_copy_attr_atime(dir_inode, lower_dentry->d_parent->d_inode);
+       fsstack_copy_attr_atime(dir_inode, d_inode(lower_dentry->d_parent));
        BUG_ON(!d_count(lower_dentry));
 
        ecryptfs_set_dentry_private(dentry, dentry_info);
        dentry_info->lower_path.mnt = lower_mnt;
        dentry_info->lower_path.dentry = lower_dentry;
 
-       if (!lower_dentry->d_inode) {
+       if (d_really_is_negative(lower_dentry)) {
                /* We want to add because we couldn't find in lower */
                d_add(dentry, NULL);
                return 0;
@@ -400,11 +400,11 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
        int rc = 0;
 
        lower_dir_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry->d_parent);
-       mutex_lock(&lower_dir_dentry->d_inode->i_mutex);
+       mutex_lock(&d_inode(lower_dir_dentry)->i_mutex);
        lower_dentry = lookup_one_len(ecryptfs_dentry->d_name.name,
                                      lower_dir_dentry,
                                      ecryptfs_dentry->d_name.len);
-       mutex_unlock(&lower_dir_dentry->d_inode->i_mutex);
+       mutex_unlock(&d_inode(lower_dir_dentry)->i_mutex);
        if (IS_ERR(lower_dentry)) {
                rc = PTR_ERR(lower_dentry);
                ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned "
@@ -412,7 +412,7 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
                                ecryptfs_dentry);
                goto out;
        }
-       if (lower_dentry->d_inode)
+       if (d_really_is_positive(lower_dentry))
                goto interpose;
        mount_crypt_stat = &ecryptfs_superblock_to_private(
                                ecryptfs_dentry->d_sb)->mount_crypt_stat;
@@ -429,11 +429,11 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
                       "filename; rc = [%d]\n", __func__, rc);
                goto out;
        }
-       mutex_lock(&lower_dir_dentry->d_inode->i_mutex);
+       mutex_lock(&d_inode(lower_dir_dentry)->i_mutex);
        lower_dentry = lookup_one_len(encrypted_and_encoded_name,
                                      lower_dir_dentry,
                                      encrypted_and_encoded_name_size);
-       mutex_unlock(&lower_dir_dentry->d_inode->i_mutex);
+       mutex_unlock(&d_inode(lower_dir_dentry)->i_mutex);
        if (IS_ERR(lower_dentry)) {
                rc = PTR_ERR(lower_dentry);
                ecryptfs_printk(KERN_DEBUG, "%s: lookup_one_len() returned "
@@ -458,24 +458,24 @@ static int ecryptfs_link(struct dentry *old_dentry, struct inode *dir,
        u64 file_size_save;
        int rc;
 
-       file_size_save = i_size_read(old_dentry->d_inode);
+       file_size_save = i_size_read(d_inode(old_dentry));
        lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
        lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
        dget(lower_old_dentry);
        dget(lower_new_dentry);
        lower_dir_dentry = lock_parent(lower_new_dentry);
-       rc = vfs_link(lower_old_dentry, lower_dir_dentry->d_inode,
+       rc = vfs_link(lower_old_dentry, d_inode(lower_dir_dentry),
                      lower_new_dentry, NULL);
-       if (rc || !lower_new_dentry->d_inode)
+       if (rc || d_really_is_negative(lower_new_dentry))
                goto out_lock;
        rc = ecryptfs_interpose(lower_new_dentry, new_dentry, dir->i_sb);
        if (rc)
                goto out_lock;
-       fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
-       fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode);
-       set_nlink(old_dentry->d_inode,
-                 ecryptfs_inode_to_lower(old_dentry->d_inode)->i_nlink);
-       i_size_write(new_dentry->d_inode, file_size_save);
+       fsstack_copy_attr_times(dir, d_inode(lower_dir_dentry));
+       fsstack_copy_inode_size(dir, d_inode(lower_dir_dentry));
+       set_nlink(d_inode(old_dentry),
+                 ecryptfs_inode_to_lower(d_inode(old_dentry))->i_nlink);
+       i_size_write(d_inode(new_dentry), file_size_save);
 out_lock:
        unlock_dir(lower_dir_dentry);
        dput(lower_new_dentry);
@@ -485,7 +485,7 @@ out_lock:
 
 static int ecryptfs_unlink(struct inode *dir, struct dentry *dentry)
 {
-       return ecryptfs_do_unlink(dir, dentry, dentry->d_inode);
+       return ecryptfs_do_unlink(dir, dentry, d_inode(dentry));
 }
 
 static int ecryptfs_symlink(struct inode *dir, struct dentry *dentry,
@@ -510,20 +510,20 @@ static int ecryptfs_symlink(struct inode *dir, struct dentry *dentry,
                                                  strlen(symname));
        if (rc)
                goto out_lock;
-       rc = vfs_symlink(lower_dir_dentry->d_inode, lower_dentry,
+       rc = vfs_symlink(d_inode(lower_dir_dentry), lower_dentry,
                         encoded_symname);
        kfree(encoded_symname);
-       if (rc || !lower_dentry->d_inode)
+       if (rc || d_really_is_negative(lower_dentry))
                goto out_lock;
        rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb);
        if (rc)
                goto out_lock;
-       fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
-       fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode);
+       fsstack_copy_attr_times(dir, d_inode(lower_dir_dentry));
+       fsstack_copy_inode_size(dir, d_inode(lower_dir_dentry));
 out_lock:
        unlock_dir(lower_dir_dentry);
        dput(lower_dentry);
-       if (!dentry->d_inode)
+       if (d_really_is_negative(dentry))
                d_drop(dentry);
        return rc;
 }
@@ -536,18 +536,18 @@ static int ecryptfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
 
        lower_dentry = ecryptfs_dentry_to_lower(dentry);
        lower_dir_dentry = lock_parent(lower_dentry);
-       rc = vfs_mkdir(lower_dir_dentry->d_inode, lower_dentry, mode);
-       if (rc || !lower_dentry->d_inode)
+       rc = vfs_mkdir(d_inode(lower_dir_dentry), lower_dentry, mode);
+       if (rc || d_really_is_negative(lower_dentry))
                goto out;
        rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb);
        if (rc)
                goto out;
-       fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
-       fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode);
-       set_nlink(dir, lower_dir_dentry->d_inode->i_nlink);
+       fsstack_copy_attr_times(dir, d_inode(lower_dir_dentry));
+       fsstack_copy_inode_size(dir, d_inode(lower_dir_dentry));
+       set_nlink(dir, d_inode(lower_dir_dentry)->i_nlink);
 out:
        unlock_dir(lower_dir_dentry);
-       if (!dentry->d_inode)
+       if (d_really_is_negative(dentry))
                d_drop(dentry);
        return rc;
 }
@@ -562,12 +562,12 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry)
        dget(dentry);
        lower_dir_dentry = lock_parent(lower_dentry);
        dget(lower_dentry);
-       rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry);
+       rc = vfs_rmdir(d_inode(lower_dir_dentry), lower_dentry);
        dput(lower_dentry);
-       if (!rc && dentry->d_inode)
-               clear_nlink(dentry->d_inode);
-       fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
-       set_nlink(dir, lower_dir_dentry->d_inode->i_nlink);
+       if (!rc && d_really_is_positive(dentry))
+               clear_nlink(d_inode(dentry));
+       fsstack_copy_attr_times(dir, d_inode(lower_dir_dentry));
+       set_nlink(dir, d_inode(lower_dir_dentry)->i_nlink);
        unlock_dir(lower_dir_dentry);
        if (!rc)
                d_drop(dentry);
@@ -584,17 +584,17 @@ ecryptfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev
 
        lower_dentry = ecryptfs_dentry_to_lower(dentry);
        lower_dir_dentry = lock_parent(lower_dentry);
-       rc = vfs_mknod(lower_dir_dentry->d_inode, lower_dentry, mode, dev);
-       if (rc || !lower_dentry->d_inode)
+       rc = vfs_mknod(d_inode(lower_dir_dentry), lower_dentry, mode, dev);
+       if (rc || d_really_is_negative(lower_dentry))
                goto out;
        rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb);
        if (rc)
                goto out;
-       fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
-       fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode);
+       fsstack_copy_attr_times(dir, d_inode(lower_dir_dentry));
+       fsstack_copy_inode_size(dir, d_inode(lower_dir_dentry));
 out:
        unlock_dir(lower_dir_dentry);
-       if (!dentry->d_inode)
+       if (d_really_is_negative(dentry))
                d_drop(dentry);
        return rc;
 }
@@ -617,7 +617,7 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        dget(lower_new_dentry);
        lower_old_dir_dentry = dget_parent(lower_old_dentry);
        lower_new_dir_dentry = dget_parent(lower_new_dentry);
-       target_inode = new_dentry->d_inode;
+       target_inode = d_inode(new_dentry);
        trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
        /* source should not be ancestor of target */
        if (trap == lower_old_dentry) {
@@ -629,17 +629,17 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                rc = -ENOTEMPTY;
                goto out_lock;
        }
-       rc = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
-                       lower_new_dir_dentry->d_inode, lower_new_dentry,
+       rc = vfs_rename(d_inode(lower_old_dir_dentry), lower_old_dentry,
+                       d_inode(lower_new_dir_dentry), lower_new_dentry,
                        NULL, 0);
        if (rc)
                goto out_lock;
        if (target_inode)
                fsstack_copy_attr_all(target_inode,
                                      ecryptfs_inode_to_lower(target_inode));
-       fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);
+       fsstack_copy_attr_all(new_dir, d_inode(lower_new_dir_dentry));
        if (new_dir != old_dir)
-               fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode);
+               fsstack_copy_attr_all(old_dir, d_inode(lower_old_dir_dentry));
 out_lock:
        unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
        dput(lower_new_dir_dentry);
@@ -662,7 +662,7 @@ static char *ecryptfs_readlink_lower(struct dentry *dentry, size_t *bufsiz)
                return ERR_PTR(-ENOMEM);
        old_fs = get_fs();
        set_fs(get_ds());
-       rc = lower_dentry->d_inode->i_op->readlink(lower_dentry,
+       rc = d_inode(lower_dentry)->i_op->readlink(lower_dentry,
                                                   (char __user *)lower_buf,
                                                   PATH_MAX);
        set_fs(old_fs);
@@ -681,8 +681,8 @@ static void *ecryptfs_follow_link(struct dentry *dentry, struct nameidata *nd)
        char *buf = ecryptfs_readlink_lower(dentry, &len);
        if (IS_ERR(buf))
                goto out;
-       fsstack_copy_attr_atime(dentry->d_inode,
-                               ecryptfs_dentry_to_lower(dentry)->d_inode);
+       fsstack_copy_attr_atime(d_inode(dentry),
+                               d_inode(ecryptfs_dentry_to_lower(dentry)));
        buf[len] = '\0';
 out:
        nd_set_link(nd, buf);
@@ -738,7 +738,7 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia,
                          struct iattr *lower_ia)
 {
        int rc = 0;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct ecryptfs_crypt_stat *crypt_stat;
        loff_t i_size = i_size_read(inode);
        loff_t lower_size_before_truncate;
@@ -751,7 +751,7 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia,
        rc = ecryptfs_get_lower_file(dentry, inode);
        if (rc)
                return rc;
-       crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat;
+       crypt_stat = &ecryptfs_inode_to_private(d_inode(dentry))->crypt_stat;
        /* Switch on growing or shrinking file */
        if (ia->ia_size > i_size) {
                char zero[] = { 0x00 };
@@ -858,7 +858,7 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
        struct iattr lower_ia = { .ia_valid = 0 };
        int rc;
 
-       rc = ecryptfs_inode_newsize_ok(dentry->d_inode, new_length);
+       rc = ecryptfs_inode_newsize_ok(d_inode(dentry), new_length);
        if (rc)
                return rc;
 
@@ -866,9 +866,9 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
        if (!rc && lower_ia.ia_valid & ATTR_SIZE) {
                struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
 
-               mutex_lock(&lower_dentry->d_inode->i_mutex);
+               mutex_lock(&d_inode(lower_dentry)->i_mutex);
                rc = notify_change(lower_dentry, &lower_ia, NULL);
-               mutex_unlock(&lower_dentry->d_inode->i_mutex);
+               mutex_unlock(&d_inode(lower_dentry)->i_mutex);
        }
        return rc;
 }
@@ -900,10 +900,10 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
        struct inode *lower_inode;
        struct ecryptfs_crypt_stat *crypt_stat;
 
-       crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat;
+       crypt_stat = &ecryptfs_inode_to_private(d_inode(dentry))->crypt_stat;
        if (!(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED))
                ecryptfs_init_crypt_stat(crypt_stat);
-       inode = dentry->d_inode;
+       inode = d_inode(dentry);
        lower_inode = ecryptfs_inode_to_lower(inode);
        lower_dentry = ecryptfs_dentry_to_lower(dentry);
        mutex_lock(&crypt_stat->cs_mutex);
@@ -967,9 +967,9 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
        if (lower_ia.ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
                lower_ia.ia_valid &= ~ATTR_MODE;
 
-       mutex_lock(&lower_dentry->d_inode->i_mutex);
+       mutex_lock(&d_inode(lower_dentry)->i_mutex);
        rc = notify_change(lower_dentry, &lower_ia, NULL);
-       mutex_unlock(&lower_dentry->d_inode->i_mutex);
+       mutex_unlock(&d_inode(lower_dentry)->i_mutex);
 out:
        fsstack_copy_attr_all(inode, lower_inode);
        return rc;
@@ -983,7 +983,7 @@ static int ecryptfs_getattr_link(struct vfsmount *mnt, struct dentry *dentry,
 
        mount_crypt_stat = &ecryptfs_superblock_to_private(
                                                dentry->d_sb)->mount_crypt_stat;
-       generic_fillattr(dentry->d_inode, stat);
+       generic_fillattr(d_inode(dentry), stat);
        if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) {
                char *target;
                size_t targetsiz;
@@ -1007,9 +1007,9 @@ static int ecryptfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
 
        rc = vfs_getattr(ecryptfs_dentry_to_lower_path(dentry), &lower_stat);
        if (!rc) {
-               fsstack_copy_attr_all(dentry->d_inode,
-                                     ecryptfs_inode_to_lower(dentry->d_inode));
-               generic_fillattr(dentry->d_inode, stat);
+               fsstack_copy_attr_all(d_inode(dentry),
+                                     ecryptfs_inode_to_lower(d_inode(dentry)));
+               generic_fillattr(d_inode(dentry), stat);
                stat->blocks = lower_stat.blocks;
        }
        return rc;
@@ -1023,14 +1023,14 @@ ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,
        struct dentry *lower_dentry;
 
        lower_dentry = ecryptfs_dentry_to_lower(dentry);
-       if (!lower_dentry->d_inode->i_op->setxattr) {
+       if (!d_inode(lower_dentry)->i_op->setxattr) {
                rc = -EOPNOTSUPP;
                goto out;
        }
 
        rc = vfs_setxattr(lower_dentry, name, value, size, flags);
-       if (!rc && dentry->d_inode)
-               fsstack_copy_attr_all(dentry->d_inode, lower_dentry->d_inode);
+       if (!rc && d_really_is_positive(dentry))
+               fsstack_copy_attr_all(d_inode(dentry), d_inode(lower_dentry));
 out:
        return rc;
 }
@@ -1041,14 +1041,14 @@ ecryptfs_getxattr_lower(struct dentry *lower_dentry, const char *name,
 {
        int rc = 0;
 
-       if (!lower_dentry->d_inode->i_op->getxattr) {
+       if (!d_inode(lower_dentry)->i_op->getxattr) {
                rc = -EOPNOTSUPP;
                goto out;
        }
-       mutex_lock(&lower_dentry->d_inode->i_mutex);
-       rc = lower_dentry->d_inode->i_op->getxattr(lower_dentry, name, value,
+       mutex_lock(&d_inode(lower_dentry)->i_mutex);
+       rc = d_inode(lower_dentry)->i_op->getxattr(lower_dentry, name, value,
                                                   size);
-       mutex_unlock(&lower_dentry->d_inode->i_mutex);
+       mutex_unlock(&d_inode(lower_dentry)->i_mutex);
 out:
        return rc;
 }
@@ -1068,13 +1068,13 @@ ecryptfs_listxattr(struct dentry *dentry, char *list, size_t size)
        struct dentry *lower_dentry;
 
        lower_dentry = ecryptfs_dentry_to_lower(dentry);
-       if (!lower_dentry->d_inode->i_op->listxattr) {
+       if (!d_inode(lower_dentry)->i_op->listxattr) {
                rc = -EOPNOTSUPP;
                goto out;
        }
-       mutex_lock(&lower_dentry->d_inode->i_mutex);
-       rc = lower_dentry->d_inode->i_op->listxattr(lower_dentry, list, size);
-       mutex_unlock(&lower_dentry->d_inode->i_mutex);
+       mutex_lock(&d_inode(lower_dentry)->i_mutex);
+       rc = d_inode(lower_dentry)->i_op->listxattr(lower_dentry, list, size);
+       mutex_unlock(&d_inode(lower_dentry)->i_mutex);
 out:
        return rc;
 }
@@ -1085,13 +1085,13 @@ static int ecryptfs_removexattr(struct dentry *dentry, const char *name)
        struct dentry *lower_dentry;
 
        lower_dentry = ecryptfs_dentry_to_lower(dentry);
-       if (!lower_dentry->d_inode->i_op->removexattr) {
+       if (!d_inode(lower_dentry)->i_op->removexattr) {
                rc = -EOPNOTSUPP;
                goto out;
        }
-       mutex_lock(&lower_dentry->d_inode->i_mutex);
-       rc = lower_dentry->d_inode->i_op->removexattr(lower_dentry, name);
-       mutex_unlock(&lower_dentry->d_inode->i_mutex);
+       mutex_lock(&d_inode(lower_dentry)->i_mutex);
+       rc = d_inode(lower_dentry)->i_op->removexattr(lower_dentry, name);
+       mutex_unlock(&d_inode(lower_dentry)->i_mutex);
 out:
        return rc;
 }
index f1ea610362c6c160a9d955c6a8e946da03b83ccb..866bb18efefea9953250ba1cbdc145e7d4be49af 100644 (file)
@@ -144,7 +144,7 @@ int ecryptfs_privileged_open(struct file **lower_file,
        /* Corresponding dput() and mntput() are done when the
         * lower file is fput() when all eCryptfs files for the inode are
         * released. */
-       flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR;
+       flags |= IS_RDONLY(d_inode(lower_dentry)) ? O_RDONLY : O_RDWR;
        (*lower_file) = dentry_open(&req.path, flags, cred);
        if (!IS_ERR(*lower_file))
                goto out;
index c095d32642599f90cf68a9437b9a10674d5cd3d9..4f4d0474bee961e456d015a08f5891b686b9033c 100644 (file)
@@ -546,11 +546,11 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags
                goto out_free;
        }
 
-       if (check_ruid && !uid_eq(path.dentry->d_inode->i_uid, current_uid())) {
+       if (check_ruid && !uid_eq(d_inode(path.dentry)->i_uid, current_uid())) {
                rc = -EPERM;
                printk(KERN_ERR "Mount of device (uid: %d) not owned by "
                       "requested user (uid: %d)\n",
-                       i_uid_read(path.dentry->d_inode),
+                       i_uid_read(d_inode(path.dentry)),
                        from_kuid(&init_user_ns, current_uid()));
                goto out_free;
        }
@@ -584,7 +584,7 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags
                goto out_free;
        }
 
-       inode = ecryptfs_get_inode(path.dentry->d_inode, s);
+       inode = ecryptfs_get_inode(d_inode(path.dentry), s);
        rc = PTR_ERR(inode);
        if (IS_ERR(inode))
                goto out_free;
index 4626976794e75284b2665cfdb99b38092fecfd93..cf208522998ed9366fa981a79c8ea35af13b3123 100644 (file)
@@ -420,7 +420,7 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode)
        void *xattr_virt;
        struct dentry *lower_dentry =
                ecryptfs_inode_to_private(ecryptfs_inode)->lower_file->f_path.dentry;
-       struct inode *lower_inode = lower_dentry->d_inode;
+       struct inode *lower_inode = d_inode(lower_dentry);
        int rc;
 
        if (!lower_inode->i_op->getxattr || !lower_inode->i_op->setxattr) {
index 07ab49745e31c4c7ff945bbeb5b4cd67848ea3d3..3381b9da9ee6080881720f0500b71c74ecdf6058 100644 (file)
@@ -145,12 +145,12 @@ out:
 
 static int efivarfs_unlink(struct inode *dir, struct dentry *dentry)
 {
-       struct efivar_entry *var = dentry->d_inode->i_private;
+       struct efivar_entry *var = d_inode(dentry)->i_private;
 
        if (efivar_entry_delete(var))
                return -EINVAL;
 
-       drop_nlink(dentry->d_inode);
+       drop_nlink(d_inode(dentry));
        dput(dentry);
        return 0;
 };
index ddbce42548c9fb6c6e496b609c1fb05beb98c944..86a2121828c312e53d64aedee9506319bbadf6c1 100644 (file)
@@ -121,7 +121,7 @@ static int efivarfs_callback(efi_char16_t *name16, efi_guid_t vendor,
        int len, i;
        int err = -ENOMEM;
 
-       entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+       entry = kzalloc(sizeof(*entry), GFP_KERNEL);
        if (!entry)
                return err;
 
@@ -144,7 +144,7 @@ static int efivarfs_callback(efi_char16_t *name16, efi_guid_t vendor,
 
        name[len + EFI_VARIABLE_GUID_LEN+1] = '\0';
 
-       inode = efivarfs_get_inode(sb, root->d_inode, S_IFREG | 0644, 0);
+       inode = efivarfs_get_inode(sb, d_inode(root), S_IFREG | 0644, 0);
        if (!inode)
                goto fail_name;
 
index bbee8f063dfab1bba67b34fc07424a79c51ff47c..40ba9cc41bf74d322c563c9db1ec66a2633a1020 100644 (file)
@@ -111,9 +111,9 @@ struct dentry *efs_get_parent(struct dentry *child)
        struct dentry *parent = ERR_PTR(-ENOENT);
        efs_ino_t ino;
 
-       ino = efs_find_entry(child->d_inode, "..", 2);
+       ino = efs_find_entry(d_inode(child), "..", 2);
        if (ino)
-               parent = d_obtain_alias(efs_iget(child->d_inode->i_sb, ino));
+               parent = d_obtain_alias(efs_iget(d_inode(child)->i_sb, ino));
 
        return parent;
 }
index d7defd557601e6049ecb69fec954ea3b9d8e4ef0..4deb0b05b011266f344d7647a9cd004e085e4266 100644 (file)
@@ -379,7 +379,7 @@ ino_t exofs_parent_ino(struct dentry *child)
        struct exofs_dir_entry *de;
        ino_t ino;
 
-       de = exofs_dotdot(child->d_inode, &page);
+       de = exofs_dotdot(d_inode(child), &page);
        if (!de)
                return 0;
 
@@ -429,7 +429,7 @@ int exofs_set_link(struct inode *dir, struct exofs_dir_entry *de,
 
 int exofs_add_link(struct dentry *dentry, struct inode *inode)
 {
-       struct inode *dir = dentry->d_parent->d_inode;
+       struct inode *dir = d_inode(dentry->d_parent);
        const unsigned char *name = dentry->d_name.name;
        int namelen = dentry->d_name.len;
        unsigned chunk_size = exofs_chunk_size(dir);
index 35073aaec6e08895f06ce3f7db86820d7dc982ec..786e4cc8c889cc8903f7d734ee3e255c0aeb24f8 100644 (file)
@@ -1028,7 +1028,7 @@ static int _do_truncate(struct inode *inode, loff_t newsize)
  */
 int exofs_setattr(struct dentry *dentry, struct iattr *iattr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int error;
 
        /* if we are about to modify an object, and it hasn't been
index 28907460e8fadaafb4975d9ea0c4903b497e28cb..5ae25e43119185e04d19a287e534921cc61bbc1c 100644 (file)
@@ -141,7 +141,7 @@ out_fail:
 static int exofs_link(struct dentry *old_dentry, struct inode *dir,
                struct dentry *dentry)
 {
-       struct inode *inode = old_dentry->d_inode;
+       struct inode *inode = d_inode(old_dentry);
 
        inode->i_ctime = CURRENT_TIME;
        inode_inc_link_count(inode);
@@ -191,7 +191,7 @@ out_dir:
 
 static int exofs_unlink(struct inode *dir, struct dentry *dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct exofs_dir_entry *de;
        struct page *page;
        int err = -ENOENT;
@@ -213,7 +213,7 @@ out:
 
 static int exofs_rmdir(struct inode *dir, struct dentry *dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int err = -ENOTEMPTY;
 
        if (exofs_empty_dir(inode)) {
@@ -230,8 +230,8 @@ static int exofs_rmdir(struct inode *dir, struct dentry *dentry)
 static int exofs_rename(struct inode *old_dir, struct dentry *old_dentry,
                struct inode *new_dir, struct dentry *new_dentry)
 {
-       struct inode *old_inode = old_dentry->d_inode;
-       struct inode *new_inode = new_dentry->d_inode;
+       struct inode *old_inode = d_inode(old_dentry);
+       struct inode *new_inode = d_inode(new_dentry);
        struct page *dir_page = NULL;
        struct exofs_dir_entry *dir_de = NULL;
        struct page *old_page;
index fcc2e565f540c3d126997c181ee7c03340b075f3..b795c567b5e1df6e89a6531fabb1a493b9e541b4 100644 (file)
@@ -958,7 +958,7 @@ static struct dentry *exofs_get_parent(struct dentry *child)
        if (!ino)
                return ERR_PTR(-ESTALE);
 
-       return d_obtain_alias(exofs_iget(child->d_inode->i_sb, ino));
+       return d_obtain_alias(exofs_iget(d_inode(child)->i_sb, ino));
 }
 
 static struct inode *exofs_nfs_get_inode(struct super_block *sb,
index 832e2624b80bab95bd1440c5c8295ab13ec7859a..6f6f3a4c1365f730747e74d9c30dd83cb796b99c 100644 (file)
@@ -37,7 +37,7 @@
 
 static void *exofs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-       struct exofs_i_info *oi = exofs_i(dentry->d_inode);
+       struct exofs_i_info *oi = exofs_i(d_inode(dentry));
 
        nd_set_link(nd, (char *)oi->i_data);
        return NULL;
index 6e1d4ab09d7226e4e519ea00a2e1941dd793ca39..796b491e69785e4b703b7c3a0cbc7e97d3510a40 100644 (file)
@@ -486,7 +486,7 @@ void ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de,
  */
 int ext2_add_link (struct dentry *dentry, struct inode *inode)
 {
-       struct inode *dir = dentry->d_parent->d_inode;
+       struct inode *dir = d_inode(dentry->d_parent);
        const char *name = dentry->d_name.name;
        int namelen = dentry->d_name.len;
        unsigned chunk_size = ext2_chunk_size(dir);
index 6c14bb8322fabefa14cf6f59e51e179f66a8c71d..5c04a0ddea804e25b0548ef56272a33f48ea3318 100644 (file)
@@ -278,7 +278,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)
        avefreeb = free_blocks / ngroups;
        ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter);
 
-       if ((parent == sb->s_root->d_inode) ||
+       if ((parent == d_inode(sb->s_root)) ||
            (EXT2_I(parent)->i_flags & EXT2_TOPDIR_FL)) {
                struct ext2_group_desc *best_desc = NULL;
                int best_ndir = inodes_per_group;
index 5d9213963faee582c2520cede532f045e629c5d3..f460ae36d5b78addfd9cc1a6eb6c4287887a946e 100644 (file)
@@ -1544,7 +1544,7 @@ int ext2_write_inode(struct inode *inode, struct writeback_control *wbc)
 
 int ext2_setattr(struct dentry *dentry, struct iattr *iattr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int error;
 
        error = inode_change_ok(inode, iattr);
index ce422931f4114fff48d23a4887679a11c5341595..3e074a9ccbe6dd048c288ae8162229b0af26d176 100644 (file)
@@ -79,10 +79,10 @@ static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, uns
 struct dentry *ext2_get_parent(struct dentry *child)
 {
        struct qstr dotdot = QSTR_INIT("..", 2);
-       unsigned long ino = ext2_inode_by_name(child->d_inode, &dotdot);
+       unsigned long ino = ext2_inode_by_name(d_inode(child), &dotdot);
        if (!ino)
                return ERR_PTR(-ENOENT);
-       return d_obtain_alias(ext2_iget(child->d_inode->i_sb, ino));
+       return d_obtain_alias(ext2_iget(d_inode(child)->i_sb, ino));
 } 
 
 /*
@@ -208,7 +208,7 @@ out_fail:
 static int ext2_link (struct dentry * old_dentry, struct inode * dir,
        struct dentry *dentry)
 {
-       struct inode *inode = old_dentry->d_inode;
+       struct inode *inode = d_inode(old_dentry);
        int err;
 
        dquot_initialize(dir);
@@ -275,7 +275,7 @@ out_dir:
 
 static int ext2_unlink(struct inode * dir, struct dentry *dentry)
 {
-       struct inode * inode = dentry->d_inode;
+       struct inode * inode = d_inode(dentry);
        struct ext2_dir_entry_2 * de;
        struct page * page;
        int err = -ENOENT;
@@ -299,7 +299,7 @@ out:
 
 static int ext2_rmdir (struct inode * dir, struct dentry *dentry)
 {
-       struct inode * inode = dentry->d_inode;
+       struct inode * inode = d_inode(dentry);
        int err = -ENOTEMPTY;
 
        if (ext2_empty_dir(inode)) {
@@ -316,8 +316,8 @@ static int ext2_rmdir (struct inode * dir, struct dentry *dentry)
 static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry,
        struct inode * new_dir, struct dentry * new_dentry )
 {
-       struct inode * old_inode = old_dentry->d_inode;
-       struct inode * new_inode = new_dentry->d_inode;
+       struct inode * old_inode = d_inode(old_dentry);
+       struct inode * new_inode = d_inode(new_dentry);
        struct page * dir_page = NULL;
        struct ext2_dir_entry_2 * dir_de = NULL;
        struct page * old_page;
index 565cf817bbf15d4660003f31889e51060a7044ef..20608f17c2e5144ed6283e6afe7f23dae6f51031 100644 (file)
@@ -23,7 +23,7 @@
 
 static void *ext2_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-       struct ext2_inode_info *ei = EXT2_I(dentry->d_inode);
+       struct ext2_inode_info *ei = EXT2_I(d_inode(dentry));
        nd_set_link(nd, (char *)ei->i_data);
        return NULL;
 }
index 91426141c33a32a1bd37bb95fa2414da5bcbad92..0b6bfd3a398bd320cf8bbbbe81745f364decd765 100644 (file)
@@ -243,7 +243,7 @@ cleanup:
 static int
 ext2_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct buffer_head *bh = NULL;
        struct ext2_xattr_entry *entry;
        char *end;
@@ -319,7 +319,7 @@ cleanup:
 /*
  * Inode operation listxattr()
  *
- * dentry->d_inode->i_mutex: don't care
+ * d_inode(dentry)->i_mutex: don't care
  */
 ssize_t
 ext2_listxattr(struct dentry *dentry, char *buffer, size_t size)
index c0ebc4db88492e343a4e4f37d8e26e2b9f4480b3..702fc6840246e7484e5cc3d4c553c9dd2fa5d37e 100644 (file)
@@ -28,7 +28,7 @@ ext2_xattr_security_get(struct dentry *dentry, const char *name,
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return ext2_xattr_get(dentry->d_inode, EXT2_XATTR_INDEX_SECURITY, name,
+       return ext2_xattr_get(d_inode(dentry), EXT2_XATTR_INDEX_SECURITY, name,
                              buffer, size);
 }
 
@@ -38,7 +38,7 @@ ext2_xattr_security_set(struct dentry *dentry, const char *name,
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return ext2_xattr_set(dentry->d_inode, EXT2_XATTR_INDEX_SECURITY, name,
+       return ext2_xattr_set(d_inode(dentry), EXT2_XATTR_INDEX_SECURITY, name,
                              value, size, flags);
 }
 
index 7e192574c0013e6dbdfc591dc0395d4ac12f4886..42b6e9874bccf5501737ac53e62228ce22a6e3dd 100644 (file)
@@ -32,7 +32,7 @@ ext2_xattr_trusted_get(struct dentry *dentry, const char *name,
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return ext2_xattr_get(dentry->d_inode, EXT2_XATTR_INDEX_TRUSTED, name,
+       return ext2_xattr_get(d_inode(dentry), EXT2_XATTR_INDEX_TRUSTED, name,
                              buffer, size);
 }
 
@@ -42,7 +42,7 @@ ext2_xattr_trusted_set(struct dentry *dentry, const char *name,
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return ext2_xattr_set(dentry->d_inode, EXT2_XATTR_INDEX_TRUSTED, name,
+       return ext2_xattr_set(d_inode(dentry), EXT2_XATTR_INDEX_TRUSTED, name,
                              value, size, flags);
 }
 
index f470e44c4b8dbd1baefa82c4bbc9e53df15ca5cf..ecdc4605192cef4d502e6633e5537b5d06117a45 100644 (file)
@@ -36,7 +36,7 @@ ext2_xattr_user_get(struct dentry *dentry, const char *name,
                return -EINVAL;
        if (!test_opt(dentry->d_sb, XATTR_USER))
                return -EOPNOTSUPP;
-       return ext2_xattr_get(dentry->d_inode, EXT2_XATTR_INDEX_USER,
+       return ext2_xattr_get(d_inode(dentry), EXT2_XATTR_INDEX_USER,
                              name, buffer, size);
 }
 
@@ -49,7 +49,7 @@ ext2_xattr_user_set(struct dentry *dentry, const char *name,
        if (!test_opt(dentry->d_sb, XATTR_USER))
                return -EOPNOTSUPP;
 
-       return ext2_xattr_set(dentry->d_inode, EXT2_XATTR_INDEX_USER,
+       return ext2_xattr_set(d_inode(dentry), EXT2_XATTR_INDEX_USER,
                              name, value, size, flags);
 }
 
index a1b810230cc503708fa5cb2a91598684a0c3ca41..3ad242e5840e0bf0b2bec595039273e1e671afa0 100644 (file)
@@ -210,7 +210,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)
        avefreeb = freeb / ngroups;
        ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter);
 
-       if ((parent == sb->s_root->d_inode) ||
+       if ((parent == d_inode(sb->s_root)) ||
            (EXT3_I(parent)->i_flags & EXT3_TOPDIR_FL)) {
                int best_ndir = inodes_per_group;
                int best_group = -1;
index 13c0868c7160ee572f30601939fcd6f421a01f11..2ee2dc4351d1630b375da3b9aaa062840ce1afc9 100644 (file)
@@ -3240,7 +3240,7 @@ int ext3_write_inode(struct inode *inode, struct writeback_control *wbc)
  */
 int ext3_setattr(struct dentry *dentry, struct iattr *attr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int error, rc = 0;
        const unsigned int ia_valid = attr->ia_valid;
 
index f197736dccfa16cca207fecb81e6445a18e96973..4264b9bd0002f199593308feaf7906292311e42f 100644 (file)
@@ -1049,19 +1049,19 @@ struct dentry *ext3_get_parent(struct dentry *child)
        struct ext3_dir_entry_2 * de;
        struct buffer_head *bh;
 
-       bh = ext3_find_entry(child->d_inode, &dotdot, &de);
+       bh = ext3_find_entry(d_inode(child), &dotdot, &de);
        if (!bh)
                return ERR_PTR(-ENOENT);
        ino = le32_to_cpu(de->inode);
        brelse(bh);
 
-       if (!ext3_valid_inum(child->d_inode->i_sb, ino)) {
-               ext3_error(child->d_inode->i_sb, "ext3_get_parent",
+       if (!ext3_valid_inum(d_inode(child)->i_sb, ino)) {
+               ext3_error(d_inode(child)->i_sb, "ext3_get_parent",
                           "bad inode number: %lu", ino);
                return ERR_PTR(-EIO);
        }
 
-       return d_obtain_alias(ext3_iget(child->d_inode->i_sb, ino));
+       return d_obtain_alias(ext3_iget(d_inode(child)->i_sb, ino));
 }
 
 #define S_SHIFT 12
@@ -1243,7 +1243,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
                             struct inode *inode, struct ext3_dir_entry_2 *de,
                             struct buffer_head * bh)
 {
-       struct inode    *dir = dentry->d_parent->d_inode;
+       struct inode    *dir = d_inode(dentry->d_parent);
        const char      *name = dentry->d_name.name;
        int             namelen = dentry->d_name.len;
        unsigned long   offset = 0;
@@ -1330,7 +1330,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
 static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
                            struct inode *inode, struct buffer_head *bh)
 {
-       struct inode    *dir = dentry->d_parent->d_inode;
+       struct inode    *dir = d_inode(dentry->d_parent);
        const char      *name = dentry->d_name.name;
        int             namelen = dentry->d_name.len;
        struct buffer_head *bh2;
@@ -1435,7 +1435,7 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
 static int ext3_add_entry (handle_t *handle, struct dentry *dentry,
        struct inode *inode)
 {
-       struct inode *dir = dentry->d_parent->d_inode;
+       struct inode *dir = d_inode(dentry->d_parent);
        struct buffer_head * bh;
        struct ext3_dir_entry_2 *de;
        struct super_block * sb;
@@ -1489,7 +1489,7 @@ static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry,
        struct dx_entry *entries, *at;
        struct dx_hash_info hinfo;
        struct buffer_head * bh;
-       struct inode *dir = dentry->d_parent->d_inode;
+       struct inode *dir = d_inode(dentry->d_parent);
        struct super_block * sb = dir->i_sb;
        struct ext3_dir_entry_2 *de;
        int err;
@@ -2111,7 +2111,7 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry)
        /* Initialize quotas before so that eventual writes go in
         * separate transaction */
        dquot_initialize(dir);
-       dquot_initialize(dentry->d_inode);
+       dquot_initialize(d_inode(dentry));
 
        handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS(dir->i_sb));
        if (IS_ERR(handle))
@@ -2125,7 +2125,7 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry)
        if (IS_DIRSYNC(dir))
                handle->h_sync = 1;
 
-       inode = dentry->d_inode;
+       inode = d_inode(dentry);
 
        retval = -EIO;
        if (le32_to_cpu(de->inode) != inode->i_ino)
@@ -2173,7 +2173,7 @@ static int ext3_unlink(struct inode * dir, struct dentry *dentry)
        /* Initialize quotas before so that eventual writes go
         * in separate transaction */
        dquot_initialize(dir);
-       dquot_initialize(dentry->d_inode);
+       dquot_initialize(d_inode(dentry));
 
        handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS(dir->i_sb));
        if (IS_ERR(handle))
@@ -2187,7 +2187,7 @@ static int ext3_unlink(struct inode * dir, struct dentry *dentry)
        if (!bh)
                goto end_unlink;
 
-       inode = dentry->d_inode;
+       inode = d_inode(dentry);
 
        retval = -EIO;
        if (le32_to_cpu(de->inode) != inode->i_ino)
@@ -2328,7 +2328,7 @@ static int ext3_link (struct dentry * old_dentry,
                struct inode * dir, struct dentry *dentry)
 {
        handle_t *handle;
-       struct inode *inode = old_dentry->d_inode;
+       struct inode *inode = d_inode(old_dentry);
        int err, retries = 0;
 
        if (inode->i_nlink >= EXT3_LINK_MAX)
@@ -2391,8 +2391,8 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
 
        /* Initialize quotas before so that eventual writes go
         * in separate transaction */
-       if (new_dentry->d_inode)
-               dquot_initialize(new_dentry->d_inode);
+       if (d_really_is_positive(new_dentry))
+               dquot_initialize(d_inode(new_dentry));
        handle = ext3_journal_start(old_dir, 2 *
                                        EXT3_DATA_TRANS_BLOCKS(old_dir->i_sb) +
                                        EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2);
@@ -2409,12 +2409,12 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
         *  and merrily kill the link to whatever was created under the
         *  same name. Goodbye sticky bit ;-<
         */
-       old_inode = old_dentry->d_inode;
+       old_inode = d_inode(old_dentry);
        retval = -ENOENT;
        if (!old_bh || le32_to_cpu(old_de->inode) != old_inode->i_ino)
                goto end_rename;
 
-       new_inode = new_dentry->d_inode;
+       new_inode = d_inode(new_dentry);
        new_bh = ext3_find_entry(new_dir, &new_dentry->d_name, &new_de);
        if (new_bh) {
                if (!new_inode) {
index f037b4b273002f5a6815da593cad35f59b81b890..a9312f0a54e5b9125cf7a262402516a7b6cc13df 100644 (file)
@@ -1170,7 +1170,7 @@ static int parse_options (char *options, struct super_block *sb,
                                return 0;
                        }
 
-                       journal_inode = path.dentry->d_inode;
+                       journal_inode = d_inode(path.dentry);
                        if (!S_ISBLK(journal_inode->i_mode)) {
                                ext3_msg(sb, KERN_ERR, "error: journal path %s "
                                        "is not a block device", journal_path);
@@ -2947,7 +2947,7 @@ static int ext3_write_info(struct super_block *sb, int type)
        handle_t *handle;
 
        /* Data block + inode block */
-       handle = ext3_journal_start(sb->s_root->d_inode, 2);
+       handle = ext3_journal_start(d_inode(sb->s_root), 2);
        if (IS_ERR(handle))
                return PTR_ERR(handle);
        ret = dquot_commit_info(sb, type);
@@ -2994,7 +2994,7 @@ static int ext3_quota_on(struct super_block *sb, int type, int format_id,
         * When we journal data on quota file, we have to flush journal to see
         * all updates to the file when we bypass pagecache...
         */
-       if (ext3_should_journal_data(path->dentry->d_inode)) {
+       if (ext3_should_journal_data(d_inode(path->dentry))) {
                /*
                 * We don't need to lock updates but journal_flush() could
                 * otherwise be livelocked...
index 6b01c3eab1f3729fdd3293675aebabd65dcb95a1..ea96df3c58db199915e6e9b60b1d7beb9b931150 100644 (file)
@@ -23,7 +23,7 @@
 
 static void * ext3_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-       struct ext3_inode_info *ei = EXT3_I(dentry->d_inode);
+       struct ext3_inode_info *ei = EXT3_I(d_inode(dentry));
        nd_set_link(nd, (char*)ei->i_data);
        return NULL;
 }
index 24215dc09a18f5ac876a6adfe4465b6e20ea6009..7cf36501ccf46c21f5a5ed979c86eec6ef7906df 100644 (file)
@@ -137,7 +137,7 @@ ext3_xattr_handler(int name_index)
 /*
  * Inode operation listxattr()
  *
- * dentry->d_inode->i_mutex: don't care
+ * d_inode(dentry)->i_mutex: don't care
  */
 ssize_t
 ext3_listxattr(struct dentry *dentry, char *buffer, size_t size)
@@ -355,7 +355,7 @@ ext3_xattr_list_entries(struct dentry *dentry, struct ext3_xattr_entry *entry,
 static int
 ext3_xattr_block_list(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct buffer_head *bh = NULL;
        int error;
 
@@ -391,7 +391,7 @@ cleanup:
 static int
 ext3_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct ext3_xattr_ibody_header *header;
        struct ext3_inode *raw_inode;
        struct ext3_iloc iloc;
@@ -432,7 +432,7 @@ ext3_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
        int i_error, b_error;
 
-       down_read(&EXT3_I(dentry->d_inode)->xattr_sem);
+       down_read(&EXT3_I(d_inode(dentry))->xattr_sem);
        i_error = ext3_xattr_ibody_list(dentry, buffer, buffer_size);
        if (i_error < 0) {
                b_error = 0;
@@ -445,7 +445,7 @@ ext3_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
                if (b_error < 0)
                        i_error = 0;
        }
-       up_read(&EXT3_I(dentry->d_inode)->xattr_sem);
+       up_read(&EXT3_I(d_inode(dentry))->xattr_sem);
        return i_error + b_error;
 }
 
index 722c2bf9645dc50e60267b9280f441cfc4b38d5b..c9506d5e3b13b523d70e66c2b8b5133452532731 100644 (file)
@@ -29,7 +29,7 @@ ext3_xattr_security_get(struct dentry *dentry, const char *name,
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return ext3_xattr_get(dentry->d_inode, EXT3_XATTR_INDEX_SECURITY,
+       return ext3_xattr_get(d_inode(dentry), EXT3_XATTR_INDEX_SECURITY,
                              name, buffer, size);
 }
 
@@ -39,7 +39,7 @@ ext3_xattr_security_set(struct dentry *dentry, const char *name,
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return ext3_xattr_set(dentry->d_inode, EXT3_XATTR_INDEX_SECURITY,
+       return ext3_xattr_set(d_inode(dentry), EXT3_XATTR_INDEX_SECURITY,
                              name, value, size, flags);
 }
 
index d75727cc67fab83175136e3bf0fbf35e2f878903..206cc66dc2852a59b1cc760995b87a1a9d35361b 100644 (file)
@@ -32,7 +32,7 @@ ext3_xattr_trusted_get(struct dentry *dentry, const char *name,
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return ext3_xattr_get(dentry->d_inode, EXT3_XATTR_INDEX_TRUSTED,
+       return ext3_xattr_get(d_inode(dentry), EXT3_XATTR_INDEX_TRUSTED,
                              name, buffer, size);
 }
 
@@ -42,7 +42,7 @@ ext3_xattr_trusted_set(struct dentry *dentry, const char *name,
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return ext3_xattr_set(dentry->d_inode, EXT3_XATTR_INDEX_TRUSTED, name,
+       return ext3_xattr_set(d_inode(dentry), EXT3_XATTR_INDEX_TRUSTED, name,
                              value, size, flags);
 }
 
index 5612af3567e0c942a389b455ed36eed91a886e89..021508ad16168c465c12324459c798837606f3e0 100644 (file)
@@ -34,7 +34,7 @@ ext3_xattr_user_get(struct dentry *dentry, const char *name, void *buffer,
                return -EINVAL;
        if (!test_opt(dentry->d_sb, XATTR_USER))
                return -EOPNOTSUPP;
-       return ext3_xattr_get(dentry->d_inode, EXT3_XATTR_INDEX_USER,
+       return ext3_xattr_get(d_inode(dentry), EXT3_XATTR_INDEX_USER,
                              name, buffer, size);
 }
 
@@ -46,7 +46,7 @@ ext3_xattr_user_set(struct dentry *dentry, const char *name,
                return -EINVAL;
        if (!test_opt(dentry->d_sb, XATTR_USER))
                return -EOPNOTSUPP;
-       return ext3_xattr_set(dentry->d_inode, EXT3_XATTR_INDEX_USER,
+       return ext3_xattr_set(d_inode(dentry), EXT3_XATTR_INDEX_USER,
                              name, value, size, flags);
 }
 
index 18228c201f7f4c226f74c15d548ff35e63ff86c6..024f2284d3f6c03ec3a0b4697bc71cbe9d9b9e2e 100644 (file)
@@ -64,8 +64,8 @@ config EXT4_FS_SECURITY
          If you are not using a security module that requires using
          extended attributes for file security labels, say N.
 
-config EXT4_FS_ENCRYPTION
-       bool "Ext4 Encryption"
+config EXT4_ENCRYPTION
+       tristate "Ext4 Encryption"
        depends on EXT4_FS
        select CRYPTO_AES
        select CRYPTO_CBC
@@ -81,6 +81,11 @@ config EXT4_FS_ENCRYPTION
          efficient since it avoids caching the encrypted and
          decrypted pages in the page cache.
 
+config EXT4_FS_ENCRYPTION
+       bool
+       default y
+       depends on EXT4_ENCRYPTION
+
 config EXT4_DEBUG
        bool "EXT4 debugging support"
        depends on EXT4_FS
index ca2f5948c1ac52111259441ff0ee5e3405e0502a..fded02f7229921a8693909ade14c2e7b16095f5e 100644 (file)
@@ -66,6 +66,7 @@ static int ext4_fname_encrypt(struct ext4_fname_crypto_ctx *ctx,
        int res = 0;
        char iv[EXT4_CRYPTO_BLOCK_SIZE];
        struct scatterlist sg[1];
+       int padding = 4 << (ctx->flags & EXT4_POLICY_FLAGS_PAD_MASK);
        char *workbuf;
 
        if (iname->len <= 0 || iname->len > ctx->lim)
@@ -73,6 +74,7 @@ static int ext4_fname_encrypt(struct ext4_fname_crypto_ctx *ctx,
 
        ciphertext_len = (iname->len < EXT4_CRYPTO_BLOCK_SIZE) ?
                EXT4_CRYPTO_BLOCK_SIZE : iname->len;
+       ciphertext_len = ext4_fname_crypto_round_up(ciphertext_len, padding);
        ciphertext_len = (ciphertext_len > ctx->lim)
                        ? ctx->lim : ciphertext_len;
 
@@ -101,7 +103,7 @@ static int ext4_fname_encrypt(struct ext4_fname_crypto_ctx *ctx,
        /* Create encryption request */
        sg_init_table(sg, 1);
        sg_set_page(sg, ctx->workpage, PAGE_SIZE, 0);
-       ablkcipher_request_set_crypt(req, sg, sg, iname->len, iv);
+       ablkcipher_request_set_crypt(req, sg, sg, ciphertext_len, iv);
        res = crypto_ablkcipher_encrypt(req);
        if (res == -EINPROGRESS || res == -EBUSY) {
                BUG_ON(req->base.data != &ecr);
@@ -198,106 +200,57 @@ static int ext4_fname_decrypt(struct ext4_fname_crypto_ctx *ctx,
        return oname->len;
 }
 
+static const char *lookup_table =
+       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";
+
 /**
  * ext4_fname_encode_digest() -
  *
  * Encodes the input digest using characters from the set [a-zA-Z0-9_+].
  * The encoded string is roughly 4/3 times the size of the input string.
  */
-int ext4_fname_encode_digest(char *dst, char *src, u32 len)
+static int digest_encode(const char *src, int len, char *dst)
 {
-       static const char *lookup_table =
-               "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_+";
-       u32 current_chunk, num_chunks, i;
-       char tmp_buf[3];
-       u32 c0, c1, c2, c3;
-
-       current_chunk = 0;
-       num_chunks = len/3;
-       for (i = 0; i < num_chunks; i++) {
-               c0 = src[3*i] & 0x3f;
-               c1 = (((src[3*i]>>6)&0x3) | ((src[3*i+1] & 0xf)<<2)) & 0x3f;
-               c2 = (((src[3*i+1]>>4)&0xf) | ((src[3*i+2] & 0x3)<<4)) & 0x3f;
-               c3 = (src[3*i+2]>>2) & 0x3f;
-               dst[4*i] = lookup_table[c0];
-               dst[4*i+1] = lookup_table[c1];
-               dst[4*i+2] = lookup_table[c2];
-               dst[4*i+3] = lookup_table[c3];
-       }
-       if (i*3 < len) {
-               memset(tmp_buf, 0, 3);
-               memcpy(tmp_buf, &src[3*i], len-3*i);
-               c0 = tmp_buf[0] & 0x3f;
-               c1 = (((tmp_buf[0]>>6)&0x3) | ((tmp_buf[1] & 0xf)<<2)) & 0x3f;
-               c2 = (((tmp_buf[1]>>4)&0xf) | ((tmp_buf[2] & 0x3)<<4)) & 0x3f;
-               c3 = (tmp_buf[2]>>2) & 0x3f;
-               dst[4*i] = lookup_table[c0];
-               dst[4*i+1] = lookup_table[c1];
-               dst[4*i+2] = lookup_table[c2];
-               dst[4*i+3] = lookup_table[c3];
+       int i = 0, bits = 0, ac = 0;
+       char *cp = dst;
+
+       while (i < len) {
+               ac += (((unsigned char) src[i]) << bits);
+               bits += 8;
+               do {
+                       *cp++ = lookup_table[ac & 0x3f];
+                       ac >>= 6;
+                       bits -= 6;
+               } while (bits >= 6);
                i++;
        }
-       return (i * 4);
+       if (bits)
+               *cp++ = lookup_table[ac & 0x3f];
+       return cp - dst;
 }
 
-/**
- * ext4_fname_hash() -
- *
- * This function computes the hash of the input filename, and sets the output
- * buffer to the *encoded* digest.  It returns the length of the digest as its
- * return value.  Errors are returned as negative numbers.  We trust the caller
- * to allocate sufficient memory to oname string.
- */
-static int ext4_fname_hash(struct ext4_fname_crypto_ctx *ctx,
-                          const struct ext4_str *iname,
-                          struct ext4_str *oname)
+static int digest_decode(const char *src, int len, char *dst)
 {
-       struct scatterlist sg;
-       struct hash_desc desc = {
-               .tfm = (struct crypto_hash *)ctx->htfm,
-               .flags = CRYPTO_TFM_REQ_MAY_SLEEP
-       };
-       int res = 0;
-
-       if (iname->len <= EXT4_FNAME_CRYPTO_DIGEST_SIZE) {
-               res = ext4_fname_encode_digest(oname->name, iname->name,
-                                              iname->len);
-               oname->len = res;
-               return res;
-       }
-
-       sg_init_one(&sg, iname->name, iname->len);
-       res = crypto_hash_init(&desc);
-       if (res) {
-               printk(KERN_ERR
-                      "%s: Error initializing crypto hash; res = [%d]\n",
-                      __func__, res);
-               goto out;
-       }
-       res = crypto_hash_update(&desc, &sg, iname->len);
-       if (res) {
-               printk(KERN_ERR
-                      "%s: Error updating crypto hash; res = [%d]\n",
-                      __func__, res);
-               goto out;
-       }
-       res = crypto_hash_final(&desc,
-               &oname->name[EXT4_FNAME_CRYPTO_DIGEST_SIZE]);
-       if (res) {
-               printk(KERN_ERR
-                      "%s: Error finalizing crypto hash; res = [%d]\n",
-                      __func__, res);
-               goto out;
+       int i = 0, bits = 0, ac = 0;
+       const char *p;
+       char *cp = dst;
+
+       while (i < len) {
+               p = strchr(lookup_table, src[i]);
+               if (p == NULL || src[i] == 0)
+                       return -2;
+               ac += (p - lookup_table) << bits;
+               bits += 6;
+               if (bits >= 8) {
+                       *cp++ = ac & 0xff;
+                       ac >>= 8;
+                       bits -= 8;
+               }
+               i++;
        }
-       /* Encode the digest as a printable string--this will increase the
-        * size of the digest */
-       oname->name[0] = 'I';
-       res = ext4_fname_encode_digest(oname->name+1,
-               &oname->name[EXT4_FNAME_CRYPTO_DIGEST_SIZE],
-               EXT4_FNAME_CRYPTO_DIGEST_SIZE) + 1;
-       oname->len = res;
-out:
-       return res;
+       if (ac)
+               return -1;
+       return cp - dst;
 }
 
 /**
@@ -405,6 +358,7 @@ struct ext4_fname_crypto_ctx *ext4_get_fname_crypto_ctx(
        if (IS_ERR(ctx))
                return ctx;
 
+       ctx->flags = ei->i_crypt_policy_flags;
        if (ctx->has_valid_key) {
                if (ctx->key.mode != EXT4_ENCRYPTION_MODE_AES_256_CTS) {
                        printk_once(KERN_WARNING
@@ -517,6 +471,7 @@ int ext4_fname_crypto_namelen_on_disk(struct ext4_fname_crypto_ctx *ctx,
                                      u32 namelen)
 {
        u32 ciphertext_len;
+       int padding = 4 << (ctx->flags & EXT4_POLICY_FLAGS_PAD_MASK);
 
        if (ctx == NULL)
                return -EIO;
@@ -524,6 +479,7 @@ int ext4_fname_crypto_namelen_on_disk(struct ext4_fname_crypto_ctx *ctx,
                return -EACCES;
        ciphertext_len = (namelen < EXT4_CRYPTO_BLOCK_SIZE) ?
                EXT4_CRYPTO_BLOCK_SIZE : namelen;
+       ciphertext_len = ext4_fname_crypto_round_up(ciphertext_len, padding);
        ciphertext_len = (ciphertext_len > ctx->lim)
                        ? ctx->lim : ciphertext_len;
        return (int) ciphertext_len;
@@ -539,10 +495,13 @@ int ext4_fname_crypto_alloc_buffer(struct ext4_fname_crypto_ctx *ctx,
                                   u32 ilen, struct ext4_str *crypto_str)
 {
        unsigned int olen;
+       int padding = 4 << (ctx->flags & EXT4_POLICY_FLAGS_PAD_MASK);
 
        if (!ctx)
                return -EIO;
-       olen = ext4_fname_crypto_round_up(ilen, EXT4_CRYPTO_BLOCK_SIZE);
+       if (padding < EXT4_CRYPTO_BLOCK_SIZE)
+               padding = EXT4_CRYPTO_BLOCK_SIZE;
+       olen = ext4_fname_crypto_round_up(ilen, padding);
        crypto_str->len = olen;
        if (olen < EXT4_FNAME_CRYPTO_DIGEST_SIZE*2)
                olen = EXT4_FNAME_CRYPTO_DIGEST_SIZE*2;
@@ -571,9 +530,13 @@ void ext4_fname_crypto_free_buffer(struct ext4_str *crypto_str)
  * ext4_fname_disk_to_usr() - converts a filename from disk space to user space
  */
 int _ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx,
-                          const struct ext4_str *iname,
-                          struct ext4_str *oname)
+                           struct dx_hash_info *hinfo,
+                           const struct ext4_str *iname,
+                           struct ext4_str *oname)
 {
+       char buf[24];
+       int ret;
+
        if (ctx == NULL)
                return -EIO;
        if (iname->len < 3) {
@@ -587,18 +550,33 @@ int _ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx,
        }
        if (ctx->has_valid_key)
                return ext4_fname_decrypt(ctx, iname, oname);
-       else
-               return ext4_fname_hash(ctx, iname, oname);
+
+       if (iname->len <= EXT4_FNAME_CRYPTO_DIGEST_SIZE) {
+               ret = digest_encode(iname->name, iname->len, oname->name);
+               oname->len = ret;
+               return ret;
+       }
+       if (hinfo) {
+               memcpy(buf, &hinfo->hash, 4);
+               memcpy(buf+4, &hinfo->minor_hash, 4);
+       } else
+               memset(buf, 0, 8);
+       memcpy(buf + 8, iname->name + iname->len - 16, 16);
+       oname->name[0] = '_';
+       ret = digest_encode(buf, 24, oname->name+1);
+       oname->len = ret + 1;
+       return ret + 1;
 }
 
 int ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx,
+                          struct dx_hash_info *hinfo,
                           const struct ext4_dir_entry_2 *de,
                           struct ext4_str *oname)
 {
        struct ext4_str iname = {.name = (unsigned char *) de->name,
                                 .len = de->name_len };
 
-       return _ext4_fname_disk_to_usr(ctx, &iname, oname);
+       return _ext4_fname_disk_to_usr(ctx, hinfo, &iname, oname);
 }
 
 
@@ -640,10 +618,11 @@ int ext4_fname_usr_to_hash(struct ext4_fname_crypto_ctx *ctx,
                            const struct qstr *iname,
                            struct dx_hash_info *hinfo)
 {
-       struct ext4_str tmp, tmp2;
+       struct ext4_str tmp;
        int ret = 0;
+       char buf[EXT4_FNAME_CRYPTO_DIGEST_SIZE+1];
 
-       if (!ctx || !ctx->has_valid_key ||
+       if (!ctx ||
            ((iname->name[0] == '.') &&
             ((iname->len == 1) ||
              ((iname->name[1] == '.') && (iname->len == 2))))) {
@@ -651,59 +630,90 @@ int ext4_fname_usr_to_hash(struct ext4_fname_crypto_ctx *ctx,
                return 0;
        }
 
+       if (!ctx->has_valid_key && iname->name[0] == '_') {
+               if (iname->len != 33)
+                       return -ENOENT;
+               ret = digest_decode(iname->name+1, iname->len, buf);
+               if (ret != 24)
+                       return -ENOENT;
+               memcpy(&hinfo->hash, buf, 4);
+               memcpy(&hinfo->minor_hash, buf + 4, 4);
+               return 0;
+       }
+
+       if (!ctx->has_valid_key && iname->name[0] != '_') {
+               if (iname->len > 43)
+                       return -ENOENT;
+               ret = digest_decode(iname->name, iname->len, buf);
+               ext4fs_dirhash(buf, ret, hinfo);
+               return 0;
+       }
+
        /* First encrypt the plaintext name */
        ret = ext4_fname_crypto_alloc_buffer(ctx, iname->len, &tmp);
        if (ret < 0)
                return ret;
 
        ret = ext4_fname_encrypt(ctx, iname, &tmp);
-       if (ret < 0)
-               goto out;
-
-       tmp2.len = (4 * ((EXT4_FNAME_CRYPTO_DIGEST_SIZE + 2) / 3)) + 1;
-       tmp2.name = kmalloc(tmp2.len + 1, GFP_KERNEL);
-       if (tmp2.name == NULL) {
-               ret = -ENOMEM;
-               goto out;
+       if (ret >= 0) {
+               ext4fs_dirhash(tmp.name, tmp.len, hinfo);
+               ret = 0;
        }
 
-       ret = ext4_fname_hash(ctx, &tmp, &tmp2);
-       if (ret > 0)
-               ext4fs_dirhash(tmp2.name, tmp2.len, hinfo);
-       ext4_fname_crypto_free_buffer(&tmp2);
-out:
        ext4_fname_crypto_free_buffer(&tmp);
        return ret;
 }
 
-/**
- * ext4_fname_disk_to_htree() - converts a filename from disk space to htree-access string
- */
-int ext4_fname_disk_to_hash(struct ext4_fname_crypto_ctx *ctx,
-                           const struct ext4_dir_entry_2 *de,
-                           struct dx_hash_info *hinfo)
+int ext4_fname_match(struct ext4_fname_crypto_ctx *ctx, struct ext4_str *cstr,
+                    int len, const char * const name,
+                    struct ext4_dir_entry_2 *de)
 {
-       struct ext4_str iname = {.name = (unsigned char *) de->name,
-                                .len = de->name_len};
-       struct ext4_str tmp;
-       int ret;
+       int ret = -ENOENT;
+       int bigname = (*name == '_');
 
-       if (!ctx ||
-           ((iname.name[0] == '.') &&
-            ((iname.len == 1) ||
-             ((iname.name[1] == '.') && (iname.len == 2))))) {
-               ext4fs_dirhash(iname.name, iname.len, hinfo);
-               return 0;
+       if (ctx->has_valid_key) {
+               if (cstr->name == NULL) {
+                       struct qstr istr;
+
+                       ret = ext4_fname_crypto_alloc_buffer(ctx, len, cstr);
+                       if (ret < 0)
+                               goto errout;
+                       istr.name = name;
+                       istr.len = len;
+                       ret = ext4_fname_encrypt(ctx, &istr, cstr);
+                       if (ret < 0)
+                               goto errout;
+               }
+       } else {
+               if (cstr->name == NULL) {
+                       cstr->name = kmalloc(32, GFP_KERNEL);
+                       if (cstr->name == NULL)
+                               return -ENOMEM;
+                       if ((bigname && (len != 33)) ||
+                           (!bigname && (len > 43)))
+                               goto errout;
+                       ret = digest_decode(name+bigname, len-bigname,
+                                           cstr->name);
+                       if (ret < 0) {
+                               ret = -ENOENT;
+                               goto errout;
+                       }
+                       cstr->len = ret;
+               }
+               if (bigname) {
+                       if (de->name_len < 16)
+                               return 0;
+                       ret = memcmp(de->name + de->name_len - 16,
+                                    cstr->name + 8, 16);
+                       return (ret == 0) ? 1 : 0;
+               }
        }
-
-       tmp.len = (4 * ((EXT4_FNAME_CRYPTO_DIGEST_SIZE + 2) / 3)) + 1;
-       tmp.name = kmalloc(tmp.len + 1, GFP_KERNEL);
-       if (tmp.name == NULL)
-               return -ENOMEM;
-
-       ret = ext4_fname_hash(ctx, &iname, &tmp);
-       if (ret > 0)
-               ext4fs_dirhash(tmp.name, tmp.len, hinfo);
-       ext4_fname_crypto_free_buffer(&tmp);
+       if (de->name_len != cstr->len)
+               return 0;
+       ret = memcmp(de->name, cstr->name, cstr->len);
+       return (ret == 0) ? 1 : 0;
+errout:
+       kfree(cstr->name);
+       cstr->name = NULL;
        return ret;
 }
index c8392af8abbbbd8fffb0a1027d5cf5c74dbb6b81..52170d0b7c4036d03bec92d8bd0ec95981105040 100644 (file)
@@ -110,6 +110,7 @@ int ext4_generate_encryption_key(struct inode *inode)
        }
        res = 0;
 
+       ei->i_crypt_policy_flags = ctx.flags;
        if (S_ISREG(inode->i_mode))
                crypt_key->mode = ctx.contents_encryption_mode;
        else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
index 30eaf9e9864a967db328bbebc18211ff4796961e..a6d6291aea163e74efad0760b7b21b308d2a49f4 100644 (file)
@@ -37,6 +37,8 @@ static int ext4_is_encryption_context_consistent_with_policy(
                return 0;
        return (memcmp(ctx.master_key_descriptor, policy->master_key_descriptor,
                        EXT4_KEY_DESCRIPTOR_SIZE) == 0 &&
+               (ctx.flags ==
+                policy->flags) &&
                (ctx.contents_encryption_mode ==
                 policy->contents_encryption_mode) &&
                (ctx.filenames_encryption_mode ==
@@ -56,25 +58,25 @@ static int ext4_create_encryption_context_from_policy(
                printk(KERN_WARNING
                       "%s: Invalid contents encryption mode %d\n", __func__,
                        policy->contents_encryption_mode);
-               res = -EINVAL;
-               goto out;
+               return -EINVAL;
        }
        if (!ext4_valid_filenames_enc_mode(policy->filenames_encryption_mode)) {
                printk(KERN_WARNING
                       "%s: Invalid filenames encryption mode %d\n", __func__,
                        policy->filenames_encryption_mode);
-               res = -EINVAL;
-               goto out;
+               return -EINVAL;
        }
+       if (policy->flags & ~EXT4_POLICY_FLAGS_VALID)
+               return -EINVAL;
        ctx.contents_encryption_mode = policy->contents_encryption_mode;
        ctx.filenames_encryption_mode = policy->filenames_encryption_mode;
+       ctx.flags = policy->flags;
        BUILD_BUG_ON(sizeof(ctx.nonce) != EXT4_KEY_DERIVATION_NONCE_SIZE);
        get_random_bytes(ctx.nonce, EXT4_KEY_DERIVATION_NONCE_SIZE);
 
        res = ext4_xattr_set(inode, EXT4_XATTR_INDEX_ENCRYPTION,
                             EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, &ctx,
                             sizeof(ctx), 0);
-out:
        if (!res)
                ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);
        return res;
@@ -115,6 +117,7 @@ int ext4_get_policy(struct inode *inode, struct ext4_encryption_policy *policy)
        policy->version = 0;
        policy->contents_encryption_mode = ctx.contents_encryption_mode;
        policy->filenames_encryption_mode = ctx.filenames_encryption_mode;
+       policy->flags = ctx.flags;
        memcpy(&policy->master_key_descriptor, ctx.master_key_descriptor,
               EXT4_KEY_DESCRIPTOR_SIZE);
        return 0;
@@ -176,6 +179,7 @@ int ext4_inherit_context(struct inode *parent, struct inode *child)
                                EXT4_ENCRYPTION_MODE_AES_256_XTS;
                        ctx.filenames_encryption_mode =
                                EXT4_ENCRYPTION_MODE_AES_256_CTS;
+                       ctx.flags = 0;
                        memset(ctx.master_key_descriptor, 0x42,
                               EXT4_KEY_DESCRIPTOR_SIZE);
                        res = 0;
index 61db51a5ce4c2feb3a3fb28a4c1a900ebf7ec958..5665d82d233216f48097de22359fd0188fc7d4bc 100644 (file)
@@ -249,7 +249,7 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
                                } else {
                                        /* Directory is encrypted */
                                        err = ext4_fname_disk_to_usr(enc_ctx,
-                                                       de, &fname_crypto_str);
+                                               NULL, de, &fname_crypto_str);
                                        if (err < 0)
                                                goto errout;
                                        if (!dir_emit(ctx,
index ef267adce19a563d87f5708fa006db6dd3e6e393..009a0590b20fb328c5829573ee77440dabb8e83e 100644 (file)
@@ -911,6 +911,7 @@ struct ext4_inode_info {
 
        /* on-disk additional length */
        __u16 i_extra_isize;
+       char i_crypt_policy_flags;
 
        /* Indicate the inline data space. */
        u16 i_inline_off;
@@ -1066,12 +1067,6 @@ extern void ext4_set_bits(void *bm, int cur, int len);
 /* Metadata checksum algorithm codes */
 #define EXT4_CRC32C_CHKSUM             1
 
-/* Encryption algorithms */
-#define EXT4_ENCRYPTION_MODE_INVALID           0
-#define EXT4_ENCRYPTION_MODE_AES_256_XTS       1
-#define EXT4_ENCRYPTION_MODE_AES_256_GCM       2
-#define EXT4_ENCRYPTION_MODE_AES_256_CBC       3
-
 /*
  * Structure of the super block
  */
@@ -2093,9 +2088,11 @@ u32 ext4_fname_crypto_round_up(u32 size, u32 blksize);
 int ext4_fname_crypto_alloc_buffer(struct ext4_fname_crypto_ctx *ctx,
                                   u32 ilen, struct ext4_str *crypto_str);
 int _ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx,
+                           struct dx_hash_info *hinfo,
                            const struct ext4_str *iname,
                            struct ext4_str *oname);
 int ext4_fname_disk_to_usr(struct ext4_fname_crypto_ctx *ctx,
+                          struct dx_hash_info *hinfo,
                           const struct ext4_dir_entry_2 *de,
                           struct ext4_str *oname);
 int ext4_fname_usr_to_disk(struct ext4_fname_crypto_ctx *ctx,
@@ -2104,11 +2101,12 @@ int ext4_fname_usr_to_disk(struct ext4_fname_crypto_ctx *ctx,
 int ext4_fname_usr_to_hash(struct ext4_fname_crypto_ctx *ctx,
                           const struct qstr *iname,
                           struct dx_hash_info *hinfo);
-int ext4_fname_disk_to_hash(struct ext4_fname_crypto_ctx *ctx,
-                           const struct ext4_dir_entry_2 *de,
-                           struct dx_hash_info *hinfo);
 int ext4_fname_crypto_namelen_on_disk(struct ext4_fname_crypto_ctx *ctx,
                                      u32 namelen);
+int ext4_fname_match(struct ext4_fname_crypto_ctx *ctx, struct ext4_str *cstr,
+                    int len, const char * const name,
+                    struct ext4_dir_entry_2 *de);
+
 
 #ifdef CONFIG_EXT4_FS_ENCRYPTION
 void ext4_put_fname_crypto_ctx(struct ext4_fname_crypto_ctx **ctx);
index c2ba35a914b65f5b6ec4497e05ef37bd10b1bea8..d75159c101ce333c2dcef8b3ff3e76f60ee0f259 100644 (file)
@@ -20,12 +20,20 @@ struct ext4_encryption_policy {
        char version;
        char contents_encryption_mode;
        char filenames_encryption_mode;
+       char flags;
        char master_key_descriptor[EXT4_KEY_DESCRIPTOR_SIZE];
 } __attribute__((__packed__));
 
 #define EXT4_ENCRYPTION_CONTEXT_FORMAT_V1 1
 #define EXT4_KEY_DERIVATION_NONCE_SIZE 16
 
+#define EXT4_POLICY_FLAGS_PAD_4                0x00
+#define EXT4_POLICY_FLAGS_PAD_8                0x01
+#define EXT4_POLICY_FLAGS_PAD_16       0x02
+#define EXT4_POLICY_FLAGS_PAD_32       0x03
+#define EXT4_POLICY_FLAGS_PAD_MASK     0x03
+#define EXT4_POLICY_FLAGS_VALID                0x03
+
 /**
  * Encryption context for inode
  *
@@ -41,7 +49,7 @@ struct ext4_encryption_context {
        char format;
        char contents_encryption_mode;
        char filenames_encryption_mode;
-       char reserved;
+       char flags;
        char master_key_descriptor[EXT4_KEY_DESCRIPTOR_SIZE];
        char nonce[EXT4_KEY_DERIVATION_NONCE_SIZE];
 } __attribute__((__packed__));
@@ -120,6 +128,7 @@ struct ext4_fname_crypto_ctx {
        struct crypto_hash *htfm;
        struct page *workpage;
        struct ext4_encryption_key key;
+       unsigned flags : 8;
        unsigned has_valid_key : 1;
        unsigned ctfm_key_is_ready : 1;
 };
index 973816bfe4a9d115a11270a1689a1cecd6fd1dec..d74e08029643d3e5eeb1f8a14d9a78c290549863 100644 (file)
@@ -4927,13 +4927,6 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
        if (ret)
                return ret;
 
-       /*
-        * currently supporting (pre)allocate mode for extent-based
-        * files _only_
-        */
-       if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
-               return -EOPNOTSUPP;
-
        if (mode & FALLOC_FL_COLLAPSE_RANGE)
                return ext4_collapse_range(inode, offset, len);
 
@@ -4955,6 +4948,14 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
 
        mutex_lock(&inode->i_mutex);
 
+       /*
+        * We only support preallocation for extent-based files only
+        */
+       if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) {
+               ret = -EOPNOTSUPP;
+               goto out;
+       }
+
        if (!(mode & FALLOC_FL_KEEP_SIZE) &&
             offset + len > i_size_read(inode)) {
                new_size = offset + len;
index d33d5a6852b9b97610a0bd365f014bc0a8094876..26724aeece7396a7b55e20c22e586b1776a5b190 100644 (file)
@@ -703,6 +703,14 @@ int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
 
        BUG_ON(end < lblk);
 
+       if ((status & EXTENT_STATUS_DELAYED) &&
+           (status & EXTENT_STATUS_WRITTEN)) {
+               ext4_warning(inode->i_sb, "Inserting extent [%u/%u] as "
+                               " delayed and written which can potentially "
+                               " cause data loss.\n", lblk, len);
+               WARN_ON(1);
+       }
+
        newes.es_lblk = lblk;
        newes.es_len = len;
        ext4_es_store_pblock_status(&newes, pblk, status);
index e9d632e9aa4b4e3cac9391d0cbf9fb2279d9285d..8850254136ae31fea8c4398a43a21fcb0d21f9cd 100644 (file)
@@ -55,7 +55,7 @@ static int ext4_sync_parent(struct inode *inode)
                dentry = d_find_any_alias(inode);
                if (!dentry)
                        break;
-               next = igrab(dentry->d_parent->d_inode);
+               next = igrab(d_inode(dentry->d_parent));
                dput(dentry);
                if (!next)
                        break;
index 2cf18a2d5c72b233d52da1c22ed8047ad8cff40c..1eaa6cb96cd086f0274c2af014fa8c6e75d7ec80 100644 (file)
@@ -443,7 +443,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent,
        ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter);
 
        if (S_ISDIR(mode) &&
-           ((parent == sb->s_root->d_inode) ||
+           ((parent == d_inode(sb->s_root)) ||
             (ext4_test_inode_flag(parent, EXT4_INODE_TOPDIR)))) {
                int best_ndir = inodes_per_group;
                int ret = -1;
index 3580629e42d32aadaff81effd01fddb2aaa41484..9588240195090ce4216e87f07379121b4ffe6cfb 100644 (file)
@@ -682,11 +682,11 @@ retry:
                 * via ext4_inode_block_unlocked_dio(). Check inode's state
                 * while holding extra i_dio_count ref.
                 */
-               atomic_inc(&inode->i_dio_count);
+               inode_dio_begin(inode);
                smp_mb();
                if (unlikely(ext4_test_inode_state(inode,
                                                    EXT4_STATE_DIOREAD_LOCK))) {
-                       inode_dio_done(inode);
+                       inode_dio_end(inode);
                        goto locked;
                }
                if (IS_DAX(inode))
@@ -697,7 +697,7 @@ retry:
                                                   inode->i_sb->s_bdev, iter,
                                                   offset, ext4_get_block, NULL,
                                                   NULL, 0);
-               inode_dio_done(inode);
+               inode_dio_end(inode);
        } else {
 locked:
                if (IS_DAX(inode))
index feb2cafbeacec52b93617e500016a7224653cf23..095c7a258d97d0bf05b26de9bf42c99fc01b143d 100644 (file)
@@ -1000,7 +1000,7 @@ static int ext4_add_dirent_to_inline(handle_t *handle,
                                     struct ext4_iloc *iloc,
                                     void *inline_start, int inline_size)
 {
-       struct inode    *dir = dentry->d_parent->d_inode;
+       struct inode    *dir = d_inode(dentry->d_parent);
        const char      *name = dentry->d_name.name;
        int             namelen = dentry->d_name.len;
        int             err;
@@ -1254,7 +1254,7 @@ int ext4_try_add_inline_entry(handle_t *handle, struct dentry *dentry,
        int ret, inline_size;
        void *inline_start;
        struct ext4_iloc iloc;
-       struct inode *dir = dentry->d_parent->d_inode;
+       struct inode *dir = d_inode(dentry->d_parent);
 
        ret = ext4_get_inode_loc(dir, &iloc);
        if (ret)
index 366476e71e103aad678334577b38d64631f930ed..55b187c3bac1f1626cf0267734aa805b6f9a1263 100644 (file)
@@ -531,6 +531,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
                status = map->m_flags & EXT4_MAP_UNWRITTEN ?
                                EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN;
                if (!(flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) &&
+                   !(status & EXTENT_STATUS_WRITTEN) &&
                    ext4_find_delalloc_range(inode, map->m_lblk,
                                             map->m_lblk + map->m_len - 1))
                        status |= EXTENT_STATUS_DELAYED;
@@ -635,6 +636,7 @@ found:
                status = map->m_flags & EXT4_MAP_UNWRITTEN ?
                                EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN;
                if (!(flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) &&
+                   !(status & EXTENT_STATUS_WRITTEN) &&
                    ext4_find_delalloc_range(inode, map->m_lblk,
                                             map->m_lblk + map->m_len - 1))
                        status |= EXTENT_STATUS_DELAYED;
@@ -3077,7 +3079,7 @@ static ssize_t ext4_ext_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
         * overwrite DIO as i_dio_count needs to be incremented under i_mutex.
         */
        if (iov_iter_rw(iter) == WRITE)
-               atomic_inc(&inode->i_dio_count);
+               inode_dio_begin(inode);
 
        /* If we do a overwrite dio, i_mutex locking can be released */
        overwrite = *((int *)iocb->private);
@@ -3182,7 +3184,7 @@ static ssize_t ext4_ext_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
 
 retake_lock:
        if (iov_iter_rw(iter) == WRITE)
-               inode_dio_done(inode);
+               inode_dio_end(inode);
        /* take i_mutex locking again if we do a ovewrite dio */
        if (overwrite) {
                up_read(&EXT4_I(inode)->i_data_sem);
@@ -4637,7 +4639,7 @@ static void ext4_wait_for_tail_page_commit(struct inode *inode)
  */
 int ext4_setattr(struct dentry *dentry, struct iattr *attr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int error, rc = 0;
        int orphan = 0;
        const unsigned int ia_valid = attr->ia_valid;
@@ -4785,7 +4787,7 @@ int ext4_getattr(struct vfsmount *mnt, struct dentry *dentry,
        struct inode *inode;
        unsigned long long delalloc_blocks;
 
-       inode = dentry->d_inode;
+       inode = d_inode(dentry);
        generic_fillattr(inode, stat);
 
        /*
index 3cb267aee8021a0bfaf3c46fb66efd655739e540..b52374e4210221bc02c9cb3ad23f8027f21e77ad 100644 (file)
@@ -475,7 +475,7 @@ int ext4_ext_migrate(struct inode *inode)
                EXT4_INODES_PER_GROUP(inode->i_sb)) + 1;
        owner[0] = i_uid_read(inode);
        owner[1] = i_gid_read(inode);
-       tmp_inode = ext4_new_inode(handle, inode->i_sb->s_root->d_inode,
+       tmp_inode = ext4_new_inode(handle, d_inode(inode->i_sb->s_root),
                                   S_IFREG, NULL, goal, owner);
        if (IS_ERR(tmp_inode)) {
                retval = PTR_ERR(tmp_inode);
index ef22cd951c0c31cb58b10f368753f8c08f5af98a..814f3beb436965f116b7555ee8cf9ac30c3f0165 100644 (file)
@@ -640,7 +640,7 @@ static struct stats dx_show_leaf(struct inode *dir,
                                                ext4_put_fname_crypto_ctx(&ctx);
                                                ctx = NULL;
                                        }
-                                       res = ext4_fname_disk_to_usr(ctx, de,
+                                       res = ext4_fname_disk_to_usr(ctx, NULL, de,
                                                        &fname_crypto_str);
                                        if (res < 0) {
                                                printk(KERN_WARNING "Error "
@@ -653,15 +653,8 @@ static struct stats dx_show_leaf(struct inode *dir,
                                                name = fname_crypto_str.name;
                                                len = fname_crypto_str.len;
                                        }
-                                       res = ext4_fname_disk_to_hash(ctx, de,
-                                                                     &h);
-                                       if (res < 0) {
-                                               printk(KERN_WARNING "Error "
-                                                       "converting filename "
-                                                       "from disk to htree"
-                                                       "\n");
-                                               h.hash = 0xDEADBEEF;
-                                       }
+                                       ext4fs_dirhash(de->name, de->name_len,
+                                                      &h);
                                        printk("%*.s:(E)%x.%u ", len, name,
                                               h.hash, (unsigned) ((char *) de
                                                                   - base));
@@ -1008,15 +1001,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
                        /* silently ignore the rest of the block */
                        break;
                }
-#ifdef CONFIG_EXT4_FS_ENCRYPTION
-               err = ext4_fname_disk_to_hash(ctx, de, hinfo);
-               if (err < 0) {
-                       count = err;
-                       goto errout;
-               }
-#else
                ext4fs_dirhash(de->name, de->name_len, hinfo);
-#endif
                if ((hinfo->hash < start_hash) ||
                    ((hinfo->hash == start_hash) &&
                     (hinfo->minor_hash < start_minor_hash)))
@@ -1032,7 +1017,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
                                   &tmp_str);
                } else {
                        /* Directory is encrypted */
-                       err = ext4_fname_disk_to_usr(ctx, de,
+                       err = ext4_fname_disk_to_usr(ctx, hinfo, de,
                                                     &fname_crypto_str);
                        if (err < 0) {
                                count = err;
@@ -1193,26 +1178,10 @@ static int dx_make_map(struct inode *dir, struct ext4_dir_entry_2 *de,
        int count = 0;
        char *base = (char *) de;
        struct dx_hash_info h = *hinfo;
-#ifdef CONFIG_EXT4_FS_ENCRYPTION
-       struct ext4_fname_crypto_ctx *ctx = NULL;
-       int err;
-
-       ctx = ext4_get_fname_crypto_ctx(dir, EXT4_NAME_LEN);
-       if (IS_ERR(ctx))
-               return PTR_ERR(ctx);
-#endif
 
        while ((char *) de < base + blocksize) {
                if (de->name_len && de->inode) {
-#ifdef CONFIG_EXT4_FS_ENCRYPTION
-                       err = ext4_fname_disk_to_hash(ctx, de, &h);
-                       if (err < 0) {
-                               ext4_put_fname_crypto_ctx(&ctx);
-                               return err;
-                       }
-#else
                        ext4fs_dirhash(de->name, de->name_len, &h);
-#endif
                        map_tail--;
                        map_tail->hash = h.hash;
                        map_tail->offs = ((char *) de - base)>>2;
@@ -1223,9 +1192,6 @@ static int dx_make_map(struct inode *dir, struct ext4_dir_entry_2 *de,
                /* XXX: do we need to check rec_len == 0 case? -Chris */
                de = ext4_next_entry(de, blocksize);
        }
-#ifdef CONFIG_EXT4_FS_ENCRYPTION
-       ext4_put_fname_crypto_ctx(&ctx);
-#endif
        return count;
 }
 
@@ -1287,16 +1253,8 @@ static inline int ext4_match(struct ext4_fname_crypto_ctx *ctx,
                return 0;
 
 #ifdef CONFIG_EXT4_FS_ENCRYPTION
-       if (ctx) {
-               /* Directory is encrypted */
-               res = ext4_fname_disk_to_usr(ctx, de, fname_crypto_str);
-               if (res < 0)
-                       return res;
-               if (len != res)
-                       return 0;
-               res = memcmp(name, fname_crypto_str->name, len);
-               return (res == 0) ? 1 : 0;
-       }
+       if (ctx)
+               return ext4_fname_match(ctx, fname_crypto_str, len, name, de);
 #endif
        if (len != de->name_len)
                return 0;
@@ -1324,16 +1282,6 @@ int search_dir(struct buffer_head *bh, char *search_buf, int buf_size,
        if (IS_ERR(ctx))
                return -1;
 
-       if (ctx != NULL) {
-               /* Allocate buffer to hold maximum name length */
-               res = ext4_fname_crypto_alloc_buffer(ctx, EXT4_NAME_LEN,
-                                                    &fname_crypto_str);
-               if (res < 0) {
-                       ext4_put_fname_crypto_ctx(&ctx);
-                       return -1;
-               }
-       }
-
        de = (struct ext4_dir_entry_2 *)search_buf;
        dlimit = search_buf + buf_size;
        while ((char *) de < dlimit) {
@@ -1664,7 +1612,7 @@ struct dentry *ext4_get_parent(struct dentry *child)
        struct ext4_dir_entry_2 * de;
        struct buffer_head *bh;
 
-       bh = ext4_find_entry(child->d_inode, &dotdot, &de, NULL);
+       bh = ext4_find_entry(d_inode(child), &dotdot, &de, NULL);
        if (IS_ERR(bh))
                return (struct dentry *) bh;
        if (!bh)
@@ -1672,13 +1620,13 @@ struct dentry *ext4_get_parent(struct dentry *child)
        ino = le32_to_cpu(de->inode);
        brelse(bh);
 
-       if (!ext4_valid_inum(child->d_inode->i_sb, ino)) {
-               EXT4_ERROR_INODE(child->d_inode,
+       if (!ext4_valid_inum(d_inode(child)->i_sb, ino)) {
+               EXT4_ERROR_INODE(d_inode(child),
                                 "bad parent inode number: %u", ino);
                return ERR_PTR(-EIO);
        }
 
-       return d_obtain_alias(ext4_iget_normal(child->d_inode->i_sb, ino));
+       return d_obtain_alias(ext4_iget_normal(d_inode(child)->i_sb, ino));
 }
 
 /*
@@ -1872,14 +1820,6 @@ int ext4_find_dest_de(struct inode *dir, struct inode *inode,
                        return res;
                }
                reclen = EXT4_DIR_REC_LEN(res);
-
-               /* Allocate buffer to hold maximum name length */
-               res = ext4_fname_crypto_alloc_buffer(ctx, EXT4_NAME_LEN,
-                                                    &fname_crypto_str);
-               if (res < 0) {
-                       ext4_put_fname_crypto_ctx(&ctx);
-                       return -1;
-               }
        }
 
        de = (struct ext4_dir_entry_2 *)buf;
@@ -1988,7 +1928,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
                             struct inode *inode, struct ext4_dir_entry_2 *de,
                             struct buffer_head *bh)
 {
-       struct inode    *dir = dentry->d_parent->d_inode;
+       struct inode    *dir = d_inode(dentry->d_parent);
        const char      *name = dentry->d_name.name;
        int             namelen = dentry->d_name.len;
        unsigned int    blocksize = dir->i_sb->s_blocksize;
@@ -2048,7 +1988,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
 static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
                            struct inode *inode, struct buffer_head *bh)
 {
-       struct inode    *dir = dentry->d_parent->d_inode;
+       struct inode    *dir = d_inode(dentry->d_parent);
 #ifdef CONFIG_EXT4_FS_ENCRYPTION
        struct ext4_fname_crypto_ctx *ctx = NULL;
        int res;
@@ -2202,7 +2142,7 @@ out_frames:
 static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
                          struct inode *inode)
 {
-       struct inode *dir = dentry->d_parent->d_inode;
+       struct inode *dir = d_inode(dentry->d_parent);
        struct buffer_head *bh = NULL;
        struct ext4_dir_entry_2 *de;
        struct ext4_dir_entry_tail *t;
@@ -2287,7 +2227,7 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
        struct dx_entry *entries, *at;
        struct dx_hash_info hinfo;
        struct buffer_head *bh;
-       struct inode *dir = dentry->d_parent->d_inode;
+       struct inode *dir = d_inode(dentry->d_parent);
        struct super_block *sb = dir->i_sb;
        struct ext4_dir_entry_2 *de;
        int err;
@@ -3063,7 +3003,7 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
        /* Initialize quotas before so that eventual writes go in
         * separate transaction */
        dquot_initialize(dir);
-       dquot_initialize(dentry->d_inode);
+       dquot_initialize(d_inode(dentry));
 
        retval = -ENOENT;
        bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL);
@@ -3072,7 +3012,7 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
        if (!bh)
                goto end_rmdir;
 
-       inode = dentry->d_inode;
+       inode = d_inode(dentry);
 
        retval = -EIO;
        if (le32_to_cpu(de->inode) != inode->i_ino)
@@ -3132,7 +3072,7 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
        /* Initialize quotas before so that eventual writes go
         * in separate transaction */
        dquot_initialize(dir);
-       dquot_initialize(dentry->d_inode);
+       dquot_initialize(d_inode(dentry));
 
        retval = -ENOENT;
        bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL);
@@ -3141,7 +3081,7 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
        if (!bh)
                goto end_unlink;
 
-       inode = dentry->d_inode;
+       inode = d_inode(dentry);
 
        retval = -EIO;
        if (le32_to_cpu(de->inode) != inode->i_ino)
@@ -3339,7 +3279,7 @@ static int ext4_link(struct dentry *old_dentry,
                     struct inode *dir, struct dentry *dentry)
 {
        handle_t *handle;
-       struct inode *inode = old_dentry->d_inode;
+       struct inode *inode = d_inode(old_dentry);
        int err, retries = 0;
 
        if (inode->i_nlink >= EXT4_LINK_MAX)
@@ -3613,12 +3553,12 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
        struct ext4_renament old = {
                .dir = old_dir,
                .dentry = old_dentry,
-               .inode = old_dentry->d_inode,
+               .inode = d_inode(old_dentry),
        };
        struct ext4_renament new = {
                .dir = new_dir,
                .dentry = new_dentry,
-               .inode = new_dentry->d_inode,
+               .inode = d_inode(new_dentry),
        };
        int force_reread;
        int retval;
@@ -3809,12 +3749,12 @@ static int ext4_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
        struct ext4_renament old = {
                .dir = old_dir,
                .dentry = old_dentry,
-               .inode = old_dentry->d_inode,
+               .inode = d_inode(old_dentry),
        };
        struct ext4_renament new = {
                .dir = new_dir,
                .dentry = new_dentry,
-               .inode = new_dentry->d_inode,
+               .inode = d_inode(new_dentry),
        };
        u8 new_file_type;
        int retval;
index 8a8ec6293b195f16623e716342463979427b3156..cf0c472047e3a89a84e262c7eeddd7ca72fd1b8c 100644 (file)
@@ -1432,12 +1432,15 @@ static int ext4_flex_group_add(struct super_block *sb,
                goto exit;
        /*
         * We will always be modifying at least the superblock and  GDT
-        * block.  If we are adding a group past the last current GDT block,
+        * blocks.  If we are adding a group past the last current GDT block,
         * we will also modify the inode and the dindirect block.  If we
         * are adding a group with superblock/GDT backups  we will also
         * modify each of the reserved GDT dindirect blocks.
         */
-       credit = flex_gd->count * 4 + reserved_gdb;
+       credit = 3;     /* sb, resize inode, resize inode dindirect */
+       /* GDT blocks */
+       credit += 1 + DIV_ROUND_UP(flex_gd->count, EXT4_DESC_PER_BLOCK(sb));
+       credit += reserved_gdb; /* Reserved GDT dindirect blocks */
        handle = ext4_journal_start_sb(sb, EXT4_HT_RESIZE, credit);
        if (IS_ERR(handle)) {
                err = PTR_ERR(handle);
index 821f22dbe82565b11c30c4eaa35a6d379e4e3d98..f06d0589ddba5db7226a38a6e0de3ef2cdee48d9 100644 (file)
@@ -1556,7 +1556,7 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
                        return -1;
                }
 
-               journal_inode = path.dentry->d_inode;
+               journal_inode = d_inode(path.dentry);
                if (!S_ISBLK(journal_inode->i_mode)) {
                        ext4_msg(sb, KERN_ERR, "error: journal path %s "
                                "is not a block device", journal_path);
@@ -5217,7 +5217,7 @@ static int ext4_write_info(struct super_block *sb, int type)
        handle_t *handle;
 
        /* Data block + inode block */
-       handle = ext4_journal_start(sb->s_root->d_inode, EXT4_HT_QUOTA, 2);
+       handle = ext4_journal_start(d_inode(sb->s_root), EXT4_HT_QUOTA, 2);
        if (IS_ERR(handle))
                return PTR_ERR(handle);
        ret = dquot_commit_info(sb, type);
@@ -5265,7 +5265,7 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id,
         * all updates to the file when we bypass pagecache...
         */
        if (EXT4_SB(sb)->s_journal &&
-           ext4_should_journal_data(path->dentry->d_inode)) {
+           ext4_should_journal_data(d_inode(path->dentry))) {
                /*
                 * We don't need to lock updates but journal_flush() could
                 * otherwise be livelocked...
index 136ca0e911fd71efa681746c72da1a99cae1d949..187b789203142d6b444b264acd44798427626b41 100644 (file)
@@ -28,7 +28,7 @@ static void *ext4_follow_link(struct dentry *dentry, struct nameidata *nd)
        struct page *cpage = NULL;
        char *caddr, *paddr = NULL;
        struct ext4_str cstr, pstr;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct ext4_fname_crypto_ctx *ctx = NULL;
        struct ext4_encrypted_symlink_data *sd;
        loff_t size = min_t(loff_t, i_size_read(inode), PAGE_SIZE - 1);
@@ -43,8 +43,8 @@ static void *ext4_follow_link(struct dentry *dentry, struct nameidata *nd)
                return ctx;
 
        if (ext4_inode_is_fast_symlink(inode)) {
-               caddr = (char *) EXT4_I(dentry->d_inode)->i_data;
-               max_size = sizeof(EXT4_I(dentry->d_inode)->i_data);
+               caddr = (char *) EXT4_I(inode)->i_data;
+               max_size = sizeof(EXT4_I(inode)->i_data);
        } else {
                cpage = read_mapping_page(inode->i_mapping, 0, NULL);
                if (IS_ERR(cpage)) {
@@ -74,7 +74,7 @@ static void *ext4_follow_link(struct dentry *dentry, struct nameidata *nd)
                goto errout;
        }
        pstr.name = paddr;
-       res = _ext4_fname_disk_to_usr(ctx, &cstr, &pstr);
+       res = _ext4_fname_disk_to_usr(ctx, NULL, &cstr, &pstr);
        if (res < 0)
                goto errout;
        /* Null-terminate the name */
@@ -113,7 +113,7 @@ static void ext4_put_link(struct dentry *dentry, struct nameidata *nd,
 
 static void *ext4_follow_fast_link(struct dentry *dentry, struct nameidata *nd)
 {
-       struct ext4_inode_info *ei = EXT4_I(dentry->d_inode);
+       struct ext4_inode_info *ei = EXT4_I(d_inode(dentry));
        nd_set_link(nd, (char *) ei->i_data);
        return NULL;
 }
index 759842ff8af050be473ce3cab3b754d7f413a67d..16e28c08d1e8cf54eb0c05d15611a6416185b119 100644 (file)
@@ -178,7 +178,7 @@ ext4_xattr_handler(int name_index)
 /*
  * Inode operation listxattr()
  *
- * dentry->d_inode->i_mutex: don't care
+ * d_inode(dentry)->i_mutex: don't care
  */
 ssize_t
 ext4_listxattr(struct dentry *dentry, char *buffer, size_t size)
@@ -423,7 +423,7 @@ ext4_xattr_list_entries(struct dentry *dentry, struct ext4_xattr_entry *entry,
 static int
 ext4_xattr_block_list(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct buffer_head *bh = NULL;
        int error;
        struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode);
@@ -460,7 +460,7 @@ cleanup:
 static int
 ext4_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct ext4_xattr_ibody_header *header;
        struct ext4_inode *raw_inode;
        struct ext4_iloc iloc;
@@ -501,7 +501,7 @@ ext4_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
        int ret, ret2;
 
-       down_read(&EXT4_I(dentry->d_inode)->xattr_sem);
+       down_read(&EXT4_I(d_inode(dentry))->xattr_sem);
        ret = ret2 = ext4_xattr_ibody_list(dentry, buffer, buffer_size);
        if (ret < 0)
                goto errout;
@@ -514,7 +514,7 @@ ext4_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
                goto errout;
        ret += ret2;
 errout:
-       up_read(&EXT4_I(dentry->d_inode)->xattr_sem);
+       up_read(&EXT4_I(d_inode(dentry))->xattr_sem);
        return ret;
 }
 
index d2a200624af59a61ef29b88e4320609ddf2c02d0..95d90e0560f05677279db254936a4fa086ad67d2 100644 (file)
@@ -33,7 +33,7 @@ ext4_xattr_security_get(struct dentry *dentry, const char *name,
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return ext4_xattr_get(dentry->d_inode, EXT4_XATTR_INDEX_SECURITY,
+       return ext4_xattr_get(d_inode(dentry), EXT4_XATTR_INDEX_SECURITY,
                              name, buffer, size);
 }
 
@@ -43,7 +43,7 @@ ext4_xattr_security_set(struct dentry *dentry, const char *name,
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return ext4_xattr_set(dentry->d_inode, EXT4_XATTR_INDEX_SECURITY,
+       return ext4_xattr_set(d_inode(dentry), EXT4_XATTR_INDEX_SECURITY,
                              name, value, size, flags);
 }
 
index 95f1f4ab59a4a663fa8cc7fbdc3051fd8a9e8944..891ee2ddfbd64a7b5f5201f6252edaafb3550b97 100644 (file)
@@ -36,7 +36,7 @@ ext4_xattr_trusted_get(struct dentry *dentry, const char *name, void *buffer,
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return ext4_xattr_get(dentry->d_inode, EXT4_XATTR_INDEX_TRUSTED,
+       return ext4_xattr_get(d_inode(dentry), EXT4_XATTR_INDEX_TRUSTED,
                              name, buffer, size);
 }
 
@@ -46,7 +46,7 @@ ext4_xattr_trusted_set(struct dentry *dentry, const char *name,
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return ext4_xattr_set(dentry->d_inode, EXT4_XATTR_INDEX_TRUSTED,
+       return ext4_xattr_set(d_inode(dentry), EXT4_XATTR_INDEX_TRUSTED,
                              name, value, size, flags);
 }
 
index 0edb7611ffbeffbba85872625a3b456e4b955650..6ed932b3c04359b0817698ebcfcaf4a2d007b03f 100644 (file)
@@ -37,7 +37,7 @@ ext4_xattr_user_get(struct dentry *dentry, const char *name,
                return -EINVAL;
        if (!test_opt(dentry->d_sb, XATTR_USER))
                return -EOPNOTSUPP;
-       return ext4_xattr_get(dentry->d_inode, EXT4_XATTR_INDEX_USER,
+       return ext4_xattr_get(d_inode(dentry), EXT4_XATTR_INDEX_USER,
                              name, buffer, size);
 }
 
@@ -49,7 +49,7 @@ ext4_xattr_user_set(struct dentry *dentry, const char *name,
                return -EINVAL;
        if (!test_opt(dentry->d_sb, XATTR_USER))
                return -EOPNOTSUPP;
-       return ext4_xattr_set(dentry->d_inode, EXT4_XATTR_INDEX_USER,
+       return ext4_xattr_set(d_inode(dentry), EXT4_XATTR_INDEX_USER,
                              name, value, size, flags);
 }
 
index b91b0e10678eb1adcb87e45628f7794caa0dcc9b..1e1aae669fa86275d7b6c932aeda89ded129ce17 100644 (file)
@@ -1513,6 +1513,7 @@ static int f2fs_write_data_pages(struct address_space *mapping,
 {
        struct inode *inode = mapping->host;
        struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+       bool locked = false;
        int ret;
        long diff;
 
@@ -1533,7 +1534,13 @@ static int f2fs_write_data_pages(struct address_space *mapping,
 
        diff = nr_pages_to_write(sbi, DATA, wbc);
 
+       if (!S_ISDIR(inode->i_mode)) {
+               mutex_lock(&sbi->writepages);
+               locked = true;
+       }
        ret = write_cache_pages(mapping, wbc, __f2fs_writepage, mapping);
+       if (locked)
+               mutex_unlock(&sbi->writepages);
 
        f2fs_submit_merged_bio(sbi, DATA, WRITE);
 
index c06a25e5cec335d8195cf027623fc8021bca1f38..8de34ab6d5b1c5340276a5780bac1c133ac582fb 100644 (file)
@@ -625,6 +625,7 @@ struct f2fs_sb_info {
        struct mutex cp_mutex;                  /* checkpoint procedure lock */
        struct rw_semaphore cp_rwsem;           /* blocking FS operations */
        struct rw_semaphore node_write;         /* locking node writes */
+       struct mutex writepages;                /* mutex for writepages() */
        wait_queue_head_t cp_wait;
 
        struct inode_management im[MAX_INO_ENTRY];      /* manage inode cache */
@@ -1482,7 +1483,7 @@ bool f2fs_empty_dir(struct inode *);
 
 static inline int f2fs_add_link(struct dentry *dentry, struct inode *inode)
 {
-       return __f2fs_add_link(dentry->d_parent->d_inode, &dentry->d_name,
+       return __f2fs_add_link(d_inode(dentry->d_parent), &dentry->d_name,
                                inode, inode->i_ino, inode->i_mode);
 }
 
index a6f3f618658851943af35ee46e03dd7570d9b47a..2b52e48d74824dd67cfb8975a09b246a701a870f 100644 (file)
@@ -574,7 +574,7 @@ void f2fs_truncate(struct inode *inode)
 int f2fs_getattr(struct vfsmount *mnt,
                         struct dentry *dentry, struct kstat *stat)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        generic_fillattr(inode, stat);
        stat->blocks <<= 3;
        return 0;
@@ -613,7 +613,7 @@ static void __setattr_copy(struct inode *inode, const struct iattr *attr)
 
 int f2fs_setattr(struct dentry *dentry, struct iattr *attr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct f2fs_inode_info *fi = F2FS_I(inode);
        int err;
 
index 407dde3d7a92273a790aefb2ace267f3be0ece74..658e8079aaf9b9020068bd30aad723d168899309 100644 (file)
@@ -151,7 +151,7 @@ out:
 static int f2fs_link(struct dentry *old_dentry, struct inode *dir,
                struct dentry *dentry)
 {
-       struct inode *inode = old_dentry->d_inode;
+       struct inode *inode = d_inode(old_dentry);
        struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
        int err;
 
@@ -182,10 +182,10 @@ out:
 struct dentry *f2fs_get_parent(struct dentry *child)
 {
        struct qstr dotdot = QSTR_INIT("..", 2);
-       unsigned long ino = f2fs_inode_by_name(child->d_inode, &dotdot);
+       unsigned long ino = f2fs_inode_by_name(d_inode(child), &dotdot);
        if (!ino)
                return ERR_PTR(-ENOENT);
-       return d_obtain_alias(f2fs_iget(child->d_inode->i_sb, ino));
+       return d_obtain_alias(f2fs_iget(d_inode(child)->i_sb, ino));
 }
 
 static int __recover_dot_dentries(struct inode *dir, nid_t pino)
@@ -263,7 +263,7 @@ static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry,
 static int f2fs_unlink(struct inode *dir, struct dentry *dentry)
 {
        struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct f2fs_dir_entry *de;
        struct page *page;
        int err = -ENOENT;
@@ -298,16 +298,14 @@ fail:
 
 static void *f2fs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-       struct page *page;
+       struct page *page = page_follow_link_light(dentry, nd);
 
-       page = page_follow_link_light(dentry, nd);
-       if (IS_ERR(page))
+       if (IS_ERR_OR_NULL(page))
                return page;
 
        /* this is broken symlink case */
        if (*nd_get_link(nd) == 0) {
-               kunmap(page);
-               page_cache_release(page);
+               page_put_link(dentry, nd, page);
                return ERR_PTR(-ENOENT);
        }
        return page;
@@ -403,7 +401,7 @@ out_fail:
 
 static int f2fs_rmdir(struct inode *dir, struct dentry *dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        if (f2fs_empty_dir(inode))
                return f2fs_unlink(dir, dentry);
        return -ENOTEMPTY;
@@ -451,8 +449,8 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
                        struct inode *new_dir, struct dentry *new_dentry)
 {
        struct f2fs_sb_info *sbi = F2FS_I_SB(old_dir);
-       struct inode *old_inode = old_dentry->d_inode;
-       struct inode *new_inode = new_dentry->d_inode;
+       struct inode *old_inode = d_inode(old_dentry);
+       struct inode *new_inode = d_inode(new_dentry);
        struct page *old_dir_page;
        struct page *old_page, *new_page;
        struct f2fs_dir_entry *old_dir_entry = NULL;
@@ -578,8 +576,8 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
                             struct inode *new_dir, struct dentry *new_dentry)
 {
        struct f2fs_sb_info *sbi = F2FS_I_SB(old_dir);
-       struct inode *old_inode = old_dentry->d_inode;
-       struct inode *new_inode = new_dentry->d_inode;
+       struct inode *old_inode = d_inode(old_dentry);
+       struct inode *new_inode = d_inode(new_dentry);
        struct page *old_dir_page, *new_dir_page;
        struct page *old_page, *new_page;
        struct f2fs_dir_entry *old_dir_entry = NULL, *new_dir_entry = NULL;
index 160b88346b2477466f3ed34d4d2dff2509742d7e..b2dd1b01f07634e27f42fc09e8fd627a70395e3e 100644 (file)
@@ -1035,6 +1035,7 @@ try_onemore:
        sbi->raw_super = raw_super;
        sbi->raw_super_buf = raw_super_buf;
        mutex_init(&sbi->gc_mutex);
+       mutex_init(&sbi->writepages);
        mutex_init(&sbi->cp_mutex);
        init_rwsem(&sbi->node_write);
        clear_sbi_flag(sbi, SBI_POR_DOING);
index b0fd2f2d0716c487ff703a7b3a1f2759f0b4fd06..9757f65a05bc97dbb0ae2e42cc88e85c9d3e5d54 100644 (file)
@@ -83,7 +83,7 @@ static int f2fs_xattr_generic_get(struct dentry *dentry, const char *name,
        }
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return f2fs_getxattr(dentry->d_inode, type, name, buffer, size, NULL);
+       return f2fs_getxattr(d_inode(dentry), type, name, buffer, size, NULL);
 }
 
 static int f2fs_xattr_generic_set(struct dentry *dentry, const char *name,
@@ -108,7 +108,7 @@ static int f2fs_xattr_generic_set(struct dentry *dentry, const char *name,
        if (strcmp(name, "") == 0)
                return -EINVAL;
 
-       return f2fs_setxattr(dentry->d_inode, type, name,
+       return f2fs_setxattr(d_inode(dentry), type, name,
                                        value, size, NULL, flags);
 }
 
@@ -130,7 +130,7 @@ static size_t f2fs_xattr_advise_list(struct dentry *dentry, char *list,
 static int f2fs_xattr_advise_get(struct dentry *dentry, const char *name,
                void *buffer, size_t size, int type)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
 
        if (strcmp(name, "") != 0)
                return -EINVAL;
@@ -143,7 +143,7 @@ static int f2fs_xattr_advise_get(struct dentry *dentry, const char *name,
 static int f2fs_xattr_advise_set(struct dentry *dentry, const char *name,
                const void *value, size_t size, int flags, int type)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
 
        if (strcmp(name, "") != 0)
                return -EINVAL;
@@ -444,7 +444,7 @@ cleanup:
 
 ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct f2fs_xattr_entry *entry;
        void *base_addr;
        int error = 0;
index cf50d93565a2434b3a5416657a2d507d17640116..442d50a0e33e6a37daf2c315a2a424f43ddfcdaa 100644 (file)
@@ -305,7 +305,7 @@ void fat_truncate_blocks(struct inode *inode, loff_t offset)
 
 int fat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        generic_fillattr(inode, stat);
        stat->blksize = MSDOS_SB(inode->i_sb)->cluster_size;
 
@@ -377,7 +377,7 @@ static int fat_allow_set_time(struct msdos_sb_info *sbi, struct inode *inode)
 int fat_setattr(struct dentry *dentry, struct iattr *attr)
 {
        struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb);
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        unsigned int ia_valid;
        int error;
 
index cc6a8541b668f039f46721a8afb58b472d1ff9a5..b7e2b33aa79356b7762512dbe5940b5fca7de1d7 100644 (file)
@@ -308,7 +308,7 @@ out:
 static int msdos_rmdir(struct inode *dir, struct dentry *dentry)
 {
        struct super_block *sb = dir->i_sb;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct fat_slot_info sinfo;
        int err;
 
@@ -402,7 +402,7 @@ out:
 /***** Unlink a file */
 static int msdos_unlink(struct inode *dir, struct dentry *dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct super_block *sb = inode->i_sb;
        struct fat_slot_info sinfo;
        int err;
@@ -440,8 +440,8 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
        int err, old_attrs, is_dir, update_dotdot, corrupt = 0;
 
        old_sinfo.bh = sinfo.bh = dotdot_bh = NULL;
-       old_inode = old_dentry->d_inode;
-       new_inode = new_dentry->d_inode;
+       old_inode = d_inode(old_dentry);
+       new_inode = d_inode(new_dentry);
 
        err = fat_scan(old_dir, old_name, &old_sinfo);
        if (err) {
index 7e0974eebd8e3df91ea3a2ae2c40885818ee085e..7092584f424af63e66e43cf8ad365343fc18daa9 100644 (file)
@@ -33,7 +33,7 @@ static int vfat_revalidate_shortname(struct dentry *dentry)
 {
        int ret = 1;
        spin_lock(&dentry->d_lock);
-       if (dentry->d_time != dentry->d_parent->d_inode->i_version)
+       if (dentry->d_time != d_inode(dentry->d_parent)->i_version)
                ret = 0;
        spin_unlock(&dentry->d_lock);
        return ret;
@@ -45,7 +45,7 @@ static int vfat_revalidate(struct dentry *dentry, unsigned int flags)
                return -ECHILD;
 
        /* This is not negative dentry. Always valid. */
-       if (dentry->d_inode)
+       if (d_really_is_positive(dentry))
                return 1;
        return vfat_revalidate_shortname(dentry);
 }
@@ -65,7 +65,7 @@ static int vfat_revalidate_ci(struct dentry *dentry, unsigned int flags)
         * positive dentry isn't good idea. So it's unsupported like
         * rename("filename", "FILENAME") for now.
         */
-       if (dentry->d_inode)
+       if (d_really_is_positive(dentry))
                return 1;
 
        /*
@@ -801,7 +801,7 @@ out:
 
 static int vfat_rmdir(struct inode *dir, struct dentry *dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct super_block *sb = dir->i_sb;
        struct fat_slot_info sinfo;
        int err;
@@ -832,7 +832,7 @@ out:
 
 static int vfat_unlink(struct inode *dir, struct dentry *dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct super_block *sb = dir->i_sb;
        struct fat_slot_info sinfo;
        int err;
@@ -915,8 +915,8 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
        struct super_block *sb = old_dir->i_sb;
 
        old_sinfo.bh = sinfo.bh = dotdot_bh = NULL;
-       old_inode = old_dentry->d_inode;
-       new_inode = new_dentry->d_inode;
+       old_inode = d_inode(old_dentry);
+       new_inode = d_inode(new_dentry);
        mutex_lock(&MSDOS_SB(sb)->s_lock);
        err = vfat_find(old_dir, &old_dentry->d_name, &old_sinfo);
        if (err)
index 93e14933dcb6fc2abc24462fe9965a070e6d234d..eb192656fba2787a682acefbc9c6d9bed5c1fa2c 100644 (file)
@@ -266,7 +266,7 @@ struct inode *fat_rebuild_parent(struct super_block *sb, int parent_logstart)
  * Find the parent for a directory that is not currently connected to
  * the filesystem root.
  *
- * On entry, the caller holds child_dir->d_inode->i_mutex.
+ * On entry, the caller holds d_inode(child_dir)->i_mutex.
  */
 static struct dentry *fat_get_parent(struct dentry *child_dir)
 {
@@ -276,7 +276,7 @@ static struct dentry *fat_get_parent(struct dentry *child_dir)
        struct inode *parent_inode = NULL;
        struct msdos_sb_info *sbi = MSDOS_SB(sb);
 
-       if (!fat_get_dotdot_entry(child_dir->d_inode, &bh, &de)) {
+       if (!fat_get_dotdot_entry(d_inode(child_dir), &bh, &de)) {
                int parent_logstart = fat_get_start(sbi, de);
                parent_inode = fat_dget(sb, parent_logstart);
                if (!parent_inode && sbi->options.nfs == FAT_NFS_NOSTALE_RO)
index c36aeaf92e41070cb905d57ffb1b6df8ce2dac4d..8b9229e2ca5cb572976a839ca20f58e0514b6726 100644 (file)
@@ -76,7 +76,7 @@ const struct address_space_operations vxfs_immed_aops = {
 static void *
 vxfs_immed_follow_link(struct dentry *dp, struct nameidata *np)
 {
-       struct vxfs_inode_info          *vip = VXFS_INO(dp->d_inode);
+       struct vxfs_inode_info          *vip = VXFS_INO(d_inode(dp));
        nd_set_link(np, vip->vii_immed.vi_immed);
        return NULL;
 }
index 205e0d5d530752532bcb045b4630ddee0ded7ffd..f863ac6647ac35506681b3a68923f09e5492b5ea 100644 (file)
@@ -244,7 +244,7 @@ int fuse_ctl_add_conn(struct fuse_conn *fc)
                return 0;
 
        parent = fuse_control_sb->s_root;
-       inc_nlink(parent->d_inode);
+       inc_nlink(d_inode(parent));
        sprintf(name, "%u", fc->dev);
        parent = fuse_ctl_add_dentry(parent, fc, name, S_IFDIR | 0500, 2,
                                     &simple_dir_inode_operations,
@@ -283,11 +283,11 @@ void fuse_ctl_remove_conn(struct fuse_conn *fc)
 
        for (i = fc->ctl_ndents - 1; i >= 0; i--) {
                struct dentry *dentry = fc->ctl_dentry[i];
-               dentry->d_inode->i_private = NULL;
+               d_inode(dentry)->i_private = NULL;
                d_drop(dentry);
                dput(dentry);
        }
-       drop_nlink(fuse_control_sb->s_root->d_inode);
+       drop_nlink(d_inode(fuse_control_sb->s_root));
 }
 
 static int fuse_ctl_fill_super(struct super_block *sb, void *data, int silent)
index 1545b711ddcfdc925410b3b553b6597b93c71a25..0572bca49f1546b3d9cd3b00fb7fc21f0369308b 100644 (file)
@@ -192,7 +192,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
        struct fuse_inode *fi;
        int ret;
 
-       inode = ACCESS_ONCE(entry->d_inode);
+       inode = d_inode_rcu(entry);
        if (inode && is_bad_inode(inode))
                goto invalid;
        else if (time_before64(fuse_dentry_time(entry), get_jiffies_64()) ||
@@ -220,7 +220,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
                attr_version = fuse_get_attr_version(fc);
 
                parent = dget_parent(entry);
-               fuse_lookup_init(fc, &args, get_node_id(parent->d_inode),
+               fuse_lookup_init(fc, &args, get_node_id(d_inode(parent)),
                                 &entry->d_name, &outarg);
                ret = fuse_simple_request(fc, &args);
                dput(parent);
@@ -254,7 +254,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
                                return -ECHILD;
                } else if (test_and_clear_bit(FUSE_I_INIT_RDPLUS, &fi->state)) {
                        parent = dget_parent(entry);
-                       fuse_advise_use_readdirplus(parent->d_inode);
+                       fuse_advise_use_readdirplus(d_inode(parent));
                        dput(parent);
                }
        }
@@ -487,7 +487,7 @@ static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
                        entry = res;
        }
 
-       if (!(flags & O_CREAT) || entry->d_inode)
+       if (!(flags & O_CREAT) || d_really_is_positive(entry))
                goto no_open;
 
        /* Only creates */
@@ -653,7 +653,7 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry)
        args.in.args[0].value = entry->d_name.name;
        err = fuse_simple_request(fc, &args);
        if (!err) {
-               struct inode *inode = entry->d_inode;
+               struct inode *inode = d_inode(entry);
                struct fuse_inode *fi = get_fuse_inode(inode);
 
                spin_lock(&fc->lock);
@@ -689,7 +689,7 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry)
        args.in.args[0].value = entry->d_name.name;
        err = fuse_simple_request(fc, &args);
        if (!err) {
-               clear_nlink(entry->d_inode);
+               clear_nlink(d_inode(entry));
                fuse_invalidate_attr(dir);
                fuse_invalidate_entry_cache(entry);
        } else if (err == -EINTR)
@@ -721,12 +721,12 @@ static int fuse_rename_common(struct inode *olddir, struct dentry *oldent,
        err = fuse_simple_request(fc, &args);
        if (!err) {
                /* ctime changes */
-               fuse_invalidate_attr(oldent->d_inode);
-               fuse_update_ctime(oldent->d_inode);
+               fuse_invalidate_attr(d_inode(oldent));
+               fuse_update_ctime(d_inode(oldent));
 
                if (flags & RENAME_EXCHANGE) {
-                       fuse_invalidate_attr(newent->d_inode);
-                       fuse_update_ctime(newent->d_inode);
+                       fuse_invalidate_attr(d_inode(newent));
+                       fuse_update_ctime(d_inode(newent));
                }
 
                fuse_invalidate_attr(olddir);
@@ -734,10 +734,10 @@ static int fuse_rename_common(struct inode *olddir, struct dentry *oldent,
                        fuse_invalidate_attr(newdir);
 
                /* newent will end up negative */
-               if (!(flags & RENAME_EXCHANGE) && newent->d_inode) {
-                       fuse_invalidate_attr(newent->d_inode);
+               if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent)) {
+                       fuse_invalidate_attr(d_inode(newent));
                        fuse_invalidate_entry_cache(newent);
-                       fuse_update_ctime(newent->d_inode);
+                       fuse_update_ctime(d_inode(newent));
                }
        } else if (err == -EINTR) {
                /* If request was interrupted, DEITY only knows if the
@@ -746,7 +746,7 @@ static int fuse_rename_common(struct inode *olddir, struct dentry *oldent,
                   directory), then there can be inconsistency between
                   the dcache and the real filesystem.  Tough luck. */
                fuse_invalidate_entry(oldent);
-               if (newent->d_inode)
+               if (d_really_is_positive(newent))
                        fuse_invalidate_entry(newent);
        }
 
@@ -788,7 +788,7 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
 {
        int err;
        struct fuse_link_in inarg;
-       struct inode *inode = entry->d_inode;
+       struct inode *inode = d_inode(entry);
        struct fuse_conn *fc = get_fuse_conn(inode);
        FUSE_ARGS(args);
 
@@ -961,9 +961,9 @@ int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
        fuse_invalidate_attr(parent);
        fuse_invalidate_entry(entry);
 
-       if (child_nodeid != 0 && entry->d_inode) {
-               mutex_lock(&entry->d_inode->i_mutex);
-               if (get_node_id(entry->d_inode) != child_nodeid) {
+       if (child_nodeid != 0 && d_really_is_positive(entry)) {
+               mutex_lock(&d_inode(entry)->i_mutex);
+               if (get_node_id(d_inode(entry)) != child_nodeid) {
                        err = -ENOENT;
                        goto badentry;
                }
@@ -977,13 +977,13 @@ int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
                                err = -ENOTEMPTY;
                                goto badentry;
                        }
-                       entry->d_inode->i_flags |= S_DEAD;
+                       d_inode(entry)->i_flags |= S_DEAD;
                }
                dont_mount(entry);
-               clear_nlink(entry->d_inode);
+               clear_nlink(d_inode(entry));
                err = 0;
  badentry:
-               mutex_unlock(&entry->d_inode->i_mutex);
+               mutex_unlock(&d_inode(entry)->i_mutex);
                if (!err)
                        d_delete(entry);
        } else {
@@ -1169,7 +1169,7 @@ static int fuse_direntplus_link(struct file *file,
        struct qstr name = QSTR_INIT(dirent->name, dirent->namelen);
        struct dentry *dentry;
        struct dentry *alias;
-       struct inode *dir = parent->d_inode;
+       struct inode *dir = d_inode(parent);
        struct fuse_conn *fc;
        struct inode *inode;
 
@@ -1205,7 +1205,7 @@ static int fuse_direntplus_link(struct file *file,
        name.hash = full_name_hash(name.name, name.len);
        dentry = d_lookup(parent, &name);
        if (dentry) {
-               inode = dentry->d_inode;
+               inode = d_inode(dentry);
                if (!inode) {
                        d_drop(dentry);
                } else if (get_node_id(inode) != o->nodeid ||
@@ -1367,7 +1367,7 @@ static int fuse_readdir(struct file *file, struct dir_context *ctx)
 
 static char *read_link(struct dentry *dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct fuse_conn *fc = get_fuse_conn(inode);
        FUSE_ARGS(args);
        char *link;
@@ -1712,7 +1712,7 @@ error:
 
 static int fuse_setattr(struct dentry *entry, struct iattr *attr)
 {
-       struct inode *inode = entry->d_inode;
+       struct inode *inode = d_inode(entry);
 
        if (!fuse_allow_current_process(get_fuse_conn(inode)))
                return -EACCES;
@@ -1726,7 +1726,7 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr)
 static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
                        struct kstat *stat)
 {
-       struct inode *inode = entry->d_inode;
+       struct inode *inode = d_inode(entry);
        struct fuse_conn *fc = get_fuse_conn(inode);
 
        if (!fuse_allow_current_process(fc))
@@ -1738,7 +1738,7 @@ static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
 static int fuse_setxattr(struct dentry *entry, const char *name,
                         const void *value, size_t size, int flags)
 {
-       struct inode *inode = entry->d_inode;
+       struct inode *inode = d_inode(entry);
        struct fuse_conn *fc = get_fuse_conn(inode);
        FUSE_ARGS(args);
        struct fuse_setxattr_in inarg;
@@ -1774,7 +1774,7 @@ static int fuse_setxattr(struct dentry *entry, const char *name,
 static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
                             void *value, size_t size)
 {
-       struct inode *inode = entry->d_inode;
+       struct inode *inode = d_inode(entry);
        struct fuse_conn *fc = get_fuse_conn(inode);
        FUSE_ARGS(args);
        struct fuse_getxattr_in inarg;
@@ -1815,7 +1815,7 @@ static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
 
 static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
 {
-       struct inode *inode = entry->d_inode;
+       struct inode *inode = d_inode(entry);
        struct fuse_conn *fc = get_fuse_conn(inode);
        FUSE_ARGS(args);
        struct fuse_getxattr_in inarg;
@@ -1857,7 +1857,7 @@ static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
 
 static int fuse_removexattr(struct dentry *entry, const char *name)
 {
-       struct inode *inode = entry->d_inode;
+       struct inode *inode = d_inode(entry);
        struct fuse_conn *fc = get_fuse_conn(inode);
        FUSE_ARGS(args);
        int err;
index e8799c11424b93f0581497c5774db2122780b40b..082ac1c97f397f7f8014c7896123f8c7a5eebe8f 100644 (file)
@@ -421,7 +421,7 @@ static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf)
        memset(&outarg, 0, sizeof(outarg));
        args.in.numargs = 0;
        args.in.h.opcode = FUSE_STATFS;
-       args.in.h.nodeid = get_node_id(dentry->d_inode);
+       args.in.h.nodeid = get_node_id(d_inode(dentry));
        args.out.numargs = 1;
        args.out.args[0].size = sizeof(outarg);
        args.out.args[0].value = &outarg;
@@ -740,7 +740,7 @@ static struct dentry *fuse_fh_to_parent(struct super_block *sb,
 
 static struct dentry *fuse_get_parent(struct dentry *child)
 {
-       struct inode *child_inode = child->d_inode;
+       struct inode *child_inode = d_inode(child);
        struct fuse_conn *fc = get_fuse_conn(child_inode);
        struct inode *inode;
        struct dentry *parent;
index 589f4ea9381c4518de238d786f56433512c57565..30822b148f3e607b97678a2e3b1224b3f30d422f 100644 (file)
@@ -48,9 +48,9 @@ static int gfs2_drevalidate(struct dentry *dentry, unsigned int flags)
                return -ECHILD;
 
        parent = dget_parent(dentry);
-       sdp = GFS2_SB(parent->d_inode);
-       dip = GFS2_I(parent->d_inode);
-       inode = dentry->d_inode;
+       sdp = GFS2_SB(d_inode(parent));
+       dip = GFS2_I(d_inode(parent));
+       inode = d_inode(dentry);
 
        if (inode) {
                if (is_bad_inode(inode))
@@ -68,7 +68,7 @@ static int gfs2_drevalidate(struct dentry *dentry, unsigned int flags)
                        goto fail;
        } 
 
-       error = gfs2_dir_check(parent->d_inode, &dentry->d_name, ip);
+       error = gfs2_dir_check(d_inode(parent), &dentry->d_name, ip);
        switch (error) {
        case 0:
                if (!inode)
@@ -113,10 +113,10 @@ static int gfs2_dentry_delete(const struct dentry *dentry)
 {
        struct gfs2_inode *ginode;
 
-       if (!dentry->d_inode)
+       if (d_really_is_negative(dentry))
                return 0;
 
-       ginode = GFS2_I(dentry->d_inode);
+       ginode = GFS2_I(d_inode(dentry));
        if (!ginode->i_iopen_gh.gh_gl)
                return 0;
 
index c41d255b6a7b58808d60b205c81ce44f2b0bc75f..5d15e9498b48364a516f7063bb41c2aee4a85a62 100644 (file)
@@ -49,7 +49,7 @@ static int gfs2_encode_fh(struct inode *inode, __u32 *p, int *len,
        fh[3] = cpu_to_be32(ip->i_no_addr & 0xFFFFFFFF);
        *len = GFS2_SMALL_FH_SIZE;
 
-       if (!parent || inode == sb->s_root->d_inode)
+       if (!parent || inode == d_inode(sb->s_root))
                return *len;
 
        ip = GFS2_I(parent);
@@ -88,8 +88,8 @@ static int get_name_filldir(struct dir_context *ctx, const char *name,
 static int gfs2_get_name(struct dentry *parent, char *name,
                         struct dentry *child)
 {
-       struct inode *dir = parent->d_inode;
-       struct inode *inode = child->d_inode;
+       struct inode *dir = d_inode(parent);
+       struct inode *inode = d_inode(child);
        struct gfs2_inode *dip, *ip;
        struct get_name_filldir gnfd = {
                .ctx.actor = get_name_filldir,
@@ -128,7 +128,7 @@ static int gfs2_get_name(struct dentry *parent, char *name,
 
 static struct dentry *gfs2_get_parent(struct dentry *child)
 {
-       return d_obtain_alias(gfs2_lookupi(child->d_inode, &gfs2_qdotdot, 1));
+       return d_obtain_alias(gfs2_lookupi(d_inode(child), &gfs2_qdotdot, 1));
 }
 
 static struct dentry *gfs2_get_dentry(struct super_block *sb,
index 08bc84d7e768e7fb46ab7bae03c8f18597cb59fc..1b3ca7a2e3fcfb807d4505d81bace6b698272bff 100644 (file)
@@ -295,7 +295,7 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name,
 
        if ((name->len == 1 && memcmp(name->name, ".", 1) == 0) ||
            (name->len == 2 && memcmp(name->name, "..", 2) == 0 &&
-            dir == sb->s_root->d_inode)) {
+            dir == d_inode(sb->s_root))) {
                igrab(dir);
                return dir;
        }
@@ -687,7 +687,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
        }
        gfs2_set_inode_flags(inode);
 
-       if ((GFS2_I(sdp->sd_root_dir->d_inode) == dip) ||
+       if ((GFS2_I(d_inode(sdp->sd_root_dir)) == dip) ||
            (dip->i_diskflags & GFS2_DIF_TOPDIR))
                aflags |= GFS2_AF_ORLOV;
 
@@ -888,7 +888,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
 {
        struct gfs2_inode *dip = GFS2_I(dir);
        struct gfs2_sbd *sdp = GFS2_SB(dir);
-       struct inode *inode = old_dentry->d_inode;
+       struct inode *inode = d_inode(old_dentry);
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_holder ghs[2];
        struct buffer_head *dibh;
@@ -1055,7 +1055,7 @@ static int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
 static int gfs2_unlink_inode(struct gfs2_inode *dip,
                             const struct dentry *dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct gfs2_inode *ip = GFS2_I(inode);
        int error;
 
@@ -1091,7 +1091,7 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry)
 {
        struct gfs2_inode *dip = GFS2_I(dir);
        struct gfs2_sbd *sdp = GFS2_SB(dir);
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_holder ghs[3];
        struct gfs2_rgrpd *rgd;
@@ -1241,7 +1241,7 @@ static int gfs2_atomic_open(struct inode *dir, struct dentry *dentry,
                return PTR_ERR(d);
        if (d != NULL)
                dentry = d;
-       if (dentry->d_inode) {
+       if (d_really_is_positive(dentry)) {
                if (!(*opened & FILE_OPENED))
                        return finish_no_open(file, d);
                dput(d);
@@ -1282,7 +1282,7 @@ static int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to)
                        error = -EINVAL;
                        break;
                }
-               if (dir == sb->s_root->d_inode) {
+               if (dir == d_inode(sb->s_root)) {
                        error = 0;
                        break;
                }
@@ -1321,7 +1321,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
 {
        struct gfs2_inode *odip = GFS2_I(odir);
        struct gfs2_inode *ndip = GFS2_I(ndir);
-       struct gfs2_inode *ip = GFS2_I(odentry->d_inode);
+       struct gfs2_inode *ip = GFS2_I(d_inode(odentry));
        struct gfs2_inode *nip = NULL;
        struct gfs2_sbd *sdp = GFS2_SB(odir);
        struct gfs2_holder ghs[5], r_gh = { .gh_gl = NULL, };
@@ -1332,8 +1332,8 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
        unsigned int x;
        int error;
 
-       if (ndentry->d_inode) {
-               nip = GFS2_I(ndentry->d_inode);
+       if (d_really_is_positive(ndentry)) {
+               nip = GFS2_I(d_inode(ndentry));
                if (ip == nip)
                        return 0;
        }
@@ -1457,7 +1457,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
        /* Check out the dir to be renamed */
 
        if (dir_rename) {
-               error = gfs2_permission(odentry->d_inode, MAY_WRITE);
+               error = gfs2_permission(d_inode(odentry), MAY_WRITE);
                if (error)
                        goto out_gunlock;
        }
@@ -1550,7 +1550,7 @@ out:
 
 static void *gfs2_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-       struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
+       struct gfs2_inode *ip = GFS2_I(d_inode(dentry));
        struct gfs2_holder i_gh;
        struct buffer_head *dibh;
        unsigned int size;
@@ -1742,7 +1742,7 @@ out:
 
 static int gfs2_setattr(struct dentry *dentry, struct iattr *attr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_holder i_gh;
        int error;
@@ -1798,7 +1798,7 @@ out:
 static int gfs2_getattr(struct vfsmount *mnt, struct dentry *dentry,
                        struct kstat *stat)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_holder gh;
        int error;
@@ -1821,7 +1821,7 @@ static int gfs2_getattr(struct vfsmount *mnt, struct dentry *dentry,
 static int gfs2_setxattr(struct dentry *dentry, const char *name,
                         const void *data, size_t size, int flags)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_holder gh;
        int ret;
@@ -1841,7 +1841,7 @@ static int gfs2_setxattr(struct dentry *dentry, const char *name,
 static ssize_t gfs2_getxattr(struct dentry *dentry, const char *name,
                             void *data, size_t size)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_holder gh;
        int ret;
@@ -1862,7 +1862,7 @@ static ssize_t gfs2_getxattr(struct dentry *dentry, const char *name,
 
 static int gfs2_removexattr(struct dentry *dentry, const char *name)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_holder gh;
        int ret;
index efc8e254787cb3ca61b059cc1e35ce5f494d2641..35b49f44c72f03f03351d397cbabb6a027ee8c23 100644 (file)
@@ -647,7 +647,7 @@ out_unlock:
 
 static int init_journal(struct gfs2_sbd *sdp, int undo)
 {
-       struct inode *master = sdp->sd_master_dir->d_inode;
+       struct inode *master = d_inode(sdp->sd_master_dir);
        struct gfs2_holder ji_gh;
        struct gfs2_inode *ip;
        int jindex = 1;
@@ -782,7 +782,7 @@ static struct lock_class_key gfs2_quota_imutex_key;
 static int init_inodes(struct gfs2_sbd *sdp, int undo)
 {
        int error = 0;
-       struct inode *master = sdp->sd_master_dir->d_inode;
+       struct inode *master = d_inode(sdp->sd_master_dir);
 
        if (undo)
                goto fail_qinode;
@@ -848,7 +848,7 @@ static int init_per_node(struct gfs2_sbd *sdp, int undo)
        char buf[30];
        int error = 0;
        struct gfs2_inode *ip;
-       struct inode *master = sdp->sd_master_dir->d_inode;
+       struct inode *master = d_inode(sdp->sd_master_dir);
 
        if (sdp->sd_args.ar_spectator)
                return 0;
@@ -1357,7 +1357,7 @@ static struct dentry *gfs2_mount_meta(struct file_system_type *fs_type,
                return ERR_PTR(error);
        }
        s = sget(&gfs2_fs_type, test_gfs2_super, set_meta_super, flags,
-                path.dentry->d_inode->i_sb->s_bdev);
+                d_inode(path.dentry)->i_sb->s_bdev);
        path_put(&path);
        if (IS_ERR(s)) {
                pr_warn("gfs2 mount does not exist\n");
index 1666382b198db6463a75446578a7ee358ef66933..859c6edbf81a07cc0bfa5f688928301ac4f676ca 100644 (file)
@@ -1171,7 +1171,7 @@ static int gfs2_statfs_i(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host *s
 
 static int gfs2_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
-       struct super_block *sb = dentry->d_inode->i_sb;
+       struct super_block *sb = d_inode(dentry)->i_sb;
        struct gfs2_sbd *sdp = sb->s_fs_info;
        struct gfs2_statfs_change_host sc;
        int error;
index fd260ce8869a86ca532f2138900bfc7eb7a70a06..4c096fa9e2a18c4c52ef528c96198d9a08ef9b6a 100644 (file)
@@ -420,7 +420,7 @@ static int ea_list_i(struct gfs2_inode *ip, struct buffer_head *bh,
 
 ssize_t gfs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
 {
-       struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
+       struct gfs2_inode *ip = GFS2_I(d_inode(dentry));
        struct gfs2_ea_request er;
        struct gfs2_holder i_gh;
        int error;
@@ -586,7 +586,7 @@ out:
 static int gfs2_xattr_get(struct dentry *dentry, const char *name,
                void *buffer, size_t size, int type)
 {
-       struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
+       struct gfs2_inode *ip = GFS2_I(d_inode(dentry));
        struct gfs2_ea_location el;
        int error;
 
@@ -1230,7 +1230,7 @@ int __gfs2_xattr_set(struct inode *inode, const char *name,
 static int gfs2_xattr_set(struct dentry *dentry, const char *name,
                const void *value, size_t size, int flags, int type)
 {
-       return __gfs2_xattr_set(dentry->d_inode, name, value,
+       return __gfs2_xattr_set(d_inode(dentry), name, value,
                                size, flags, type);
 }
 
index e057ec542a6ad3634d6dd240f2dfcadc3fff7a43..8d931b157bbef8bfd382d9c6878fbdb8d53da481 100644 (file)
@@ -16,7 +16,7 @@
 int hfs_setxattr(struct dentry *dentry, const char *name,
                 const void *value, size_t size, int flags)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct hfs_find_data fd;
        hfs_cat_rec rec;
        struct hfs_cat_file *file;
@@ -59,7 +59,7 @@ out:
 ssize_t hfs_getxattr(struct dentry *dentry, const char *name,
                         void *value, size_t size)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct hfs_find_data fd;
        hfs_cat_rec rec;
        struct hfs_cat_file *file;
@@ -105,7 +105,7 @@ out:
 
 ssize_t hfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
 
        if (!S_ISREG(inode->i_mode) || HFS_IS_RSRC(inode))
                return -EOPNOTSUPP;
index 36d1a6ae765590cf0d442d5c688d201b0e781525..70788e03820ae3e1c34689c95493798c20781928 100644 (file)
@@ -253,7 +253,7 @@ static int hfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
  */
 static int hfs_remove(struct inode *dir, struct dentry *dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int res;
 
        if (S_ISDIR(inode->i_mode) && inode->i_size != 2)
@@ -285,18 +285,18 @@ static int hfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        int res;
 
        /* Unlink destination if it already exists */
-       if (new_dentry->d_inode) {
+       if (d_really_is_positive(new_dentry)) {
                res = hfs_remove(new_dir, new_dentry);
                if (res)
                        return res;
        }
 
-       res = hfs_cat_move(old_dentry->d_inode->i_ino,
+       res = hfs_cat_move(d_inode(old_dentry)->i_ino,
                           old_dir, &old_dentry->d_name,
                           new_dir, &new_dentry->d_name);
        if (!res)
                hfs_cat_build_key(old_dir->i_sb,
-                                 (btree_key *)&HFS_I(old_dentry->d_inode)->cat_key,
+                                 (btree_key *)&HFS_I(d_inode(old_dentry))->cat_key,
                                  new_dir->i_ino, &new_dentry->d_name);
        return res;
 }
index 75fd5d873c196dfd76006e77ef25405c9359c224..b99ebddb10cb5b5e2d422c0f2151fc926455d26b 100644 (file)
@@ -600,7 +600,7 @@ static int hfs_file_release(struct inode *inode, struct file *file)
 
 int hfs_inode_setattr(struct dentry *dentry, struct iattr * attr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct hfs_sb_info *hsb = HFS_SB(inode->i_sb);
        int error;
 
index 91b91fd3a9013a08cc7d12d5e3934b09931b1a1e..2875961fdc106fa543e25e3f9cc276b46ace35ed 100644 (file)
@@ -21,7 +21,7 @@ static int hfs_revalidate_dentry(struct dentry *dentry, unsigned int flags)
        if (flags & LOOKUP_RCU)
                return -ECHILD;
 
-       inode = dentry->d_inode;
+       inode = d_inode(dentry);
        if(!inode)
                return 1;
 
index 3074609befc312443a705a14b4d7486872dcef33..d0f39dcbb58e86057c91c2e32a9d538178da39c5 100644 (file)
@@ -81,7 +81,7 @@ again:
                                        HFSPLUS_I(HFSPLUS_SB(sb)->hidden_dir)->
                                                create_date ||
                                entry.file.create_date ==
-                                       HFSPLUS_I(sb->s_root->d_inode)->
+                                       HFSPLUS_I(d_inode(sb->s_root))->
                                                create_date) &&
                                HFSPLUS_SB(sb)->hidden_dir) {
                        struct qstr str;
@@ -296,8 +296,8 @@ static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir,
                        struct dentry *dst_dentry)
 {
        struct hfsplus_sb_info *sbi = HFSPLUS_SB(dst_dir->i_sb);
-       struct inode *inode = src_dentry->d_inode;
-       struct inode *src_dir = src_dentry->d_parent->d_inode;
+       struct inode *inode = d_inode(src_dentry);
+       struct inode *src_dir = d_inode(src_dentry->d_parent);
        struct qstr str;
        char name[32];
        u32 cnid, id;
@@ -353,7 +353,7 @@ out:
 static int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
 {
        struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb);
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct qstr str;
        char name[32];
        u32 cnid;
@@ -410,7 +410,7 @@ out:
 static int hfsplus_rmdir(struct inode *dir, struct dentry *dentry)
 {
        struct hfsplus_sb_info *sbi = HFSPLUS_SB(dir->i_sb);
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int res;
 
        if (inode->i_size != 2)
@@ -529,7 +529,7 @@ static int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry,
        int res;
 
        /* Unlink destination if it already exists */
-       if (new_dentry->d_inode) {
+       if (d_really_is_positive(new_dentry)) {
                if (d_is_dir(new_dentry))
                        res = hfsplus_rmdir(new_dir, new_dentry);
                else
index b0afedbef12b6a2d39bd6db290375e089af51ed4..6dd107d7421ec05368845846d6a9cd9f558e9d23 100644 (file)
@@ -243,7 +243,7 @@ static int hfsplus_file_release(struct inode *inode, struct file *file)
 
 static int hfsplus_setattr(struct dentry *dentry, struct iattr *attr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int error;
 
        error = inode_change_ok(inode, attr);
index 8e98f5db6ad685d0eae15e5da74fe62d57c75cdf..0624ce4e07022e3f047683a70cbbf1cdad6ff174 100644 (file)
@@ -26,7 +26,7 @@
 static int hfsplus_ioctl_bless(struct file *file, int __user *user_flags)
 {
        struct dentry *dentry = file->f_path.dentry;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
        struct hfsplus_vh *vh = sbi->s_vhdr;
        struct hfsplus_vh *bvh = sbi->s_backup_vhdr;
index 89f262d8fcd87bd0bdc6fbf42e4338f581093658..416b1dbafe516583b22efad4a851e7f6cf2abb25 100644 (file)
@@ -440,7 +440,7 @@ int hfsplus_setxattr(struct dentry *dentry, const char *name,
                return -ENOMEM;
        strcpy(xattr_name, prefix);
        strcpy(xattr_name + prefixlen, name);
-       res = __hfsplus_setxattr(dentry->d_inode, xattr_name, value, size,
+       res = __hfsplus_setxattr(d_inode(dentry), xattr_name, value, size,
                                 flags);
        kfree(xattr_name);
        return res;
@@ -600,7 +600,7 @@ ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
        strcpy(xattr_name, prefix);
        strcpy(xattr_name + prefixlen, name);
 
-       res = __hfsplus_getxattr(dentry->d_inode, xattr_name, value, size);
+       res = __hfsplus_getxattr(d_inode(dentry), xattr_name, value, size);
        kfree(xattr_name);
        return res;
 
@@ -620,7 +620,7 @@ static ssize_t hfsplus_listxattr_finder_info(struct dentry *dentry,
                                                char *buffer, size_t size)
 {
        ssize_t res = 0;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct hfs_find_data fd;
        u16 entry_type;
        u8 folder_finder_info[sizeof(struct DInfo) + sizeof(struct DXInfo)];
@@ -688,7 +688,7 @@ ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size)
 {
        ssize_t err;
        ssize_t res = 0;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct hfs_find_data fd;
        u16 key_len = 0;
        struct hfsplus_attr_key attr_key;
@@ -868,7 +868,7 @@ static int hfsplus_osx_getxattr(struct dentry *dentry, const char *name,
         * creates), so we pass the name through unmodified (after
         * ensuring it doesn't conflict with another namespace).
         */
-       return __hfsplus_getxattr(dentry->d_inode, name, buffer, size);
+       return __hfsplus_getxattr(d_inode(dentry), name, buffer, size);
 }
 
 static int hfsplus_osx_setxattr(struct dentry *dentry, const char *name,
@@ -890,7 +890,7 @@ static int hfsplus_osx_setxattr(struct dentry *dentry, const char *name,
         * creates), so we pass the name through unmodified (after
         * ensuring it doesn't conflict with another namespace).
         */
-       return __hfsplus_setxattr(dentry->d_inode, name, buffer, size, flags);
+       return __hfsplus_setxattr(d_inode(dentry), name, buffer, size, flags);
 }
 
 static size_t hfsplus_osx_listxattr(struct dentry *dentry, char *list,
index b83a0343378bd2b1aa2623d3f55f838c359457f5..ef263174acd23a88f2a110b80a67afc2fab2ddc0 100644 (file)
@@ -807,7 +807,7 @@ static int hostfs_permission(struct inode *ino, int desired)
 
 static int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct hostfs_iattr attrs;
        char *name;
        int err;
index 7ce4b74234a12011140fb32594bde7bac6450173..933c73780813198b8953376eaa1e595d786e36e1 100644 (file)
@@ -257,7 +257,7 @@ void hpfs_write_inode_nolock(struct inode *i)
 
 int hpfs_setattr(struct dentry *dentry, struct iattr *attr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int error = -EINVAL;
 
        hpfs_lock(inode->i_sb);
index bdbc2c3080a457210c5bec65bd166e573d7889e6..a0872f239f04ff0292fe6dcd6d272673f892417a 100644 (file)
@@ -359,7 +359,7 @@ static int hpfs_unlink(struct inode *dir, struct dentry *dentry)
        unsigned len = dentry->d_name.len;
        struct quad_buffer_head qbh;
        struct hpfs_dirent *de;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        dnode_secno dno;
        int r;
        int rep = 0;
@@ -433,7 +433,7 @@ static int hpfs_rmdir(struct inode *dir, struct dentry *dentry)
        unsigned len = dentry->d_name.len;
        struct quad_buffer_head qbh;
        struct hpfs_dirent *de;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        dnode_secno dno;
        int n_items = 0;
        int err;
@@ -522,8 +522,8 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        unsigned old_len = old_dentry->d_name.len;
        const unsigned char *new_name = new_dentry->d_name.name;
        unsigned new_len = new_dentry->d_name.len;
-       struct inode *i = old_dentry->d_inode;
-       struct inode *new_inode = new_dentry->d_inode;
+       struct inode *i = d_inode(old_dentry);
+       struct inode *new_inode = d_inode(new_dentry);
        struct quad_buffer_head qbh, qbh1;
        struct hpfs_dirent *dep, *nde;
        struct hpfs_dirent de;
index 043ac9d77262a858464adad185969109902c9479..fa2bd5366ecf1f4c3d9b81c2d80336a621831dcf 100644 (file)
@@ -153,9 +153,9 @@ static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry,
                return ERR_PTR(-ENOENT);
 
        parent = HPPFS_I(ino)->proc_dentry;
-       mutex_lock(&parent->d_inode->i_mutex);
+       mutex_lock(&d_inode(parent)->i_mutex);
        proc_dentry = lookup_one_len(name->name, parent, name->len);
-       mutex_unlock(&parent->d_inode->i_mutex);
+       mutex_unlock(&d_inode(parent)->i_mutex);
 
        if (IS_ERR(proc_dentry))
                return proc_dentry;
@@ -637,25 +637,25 @@ static const struct super_operations hppfs_sbops = {
 static int hppfs_readlink(struct dentry *dentry, char __user *buffer,
                          int buflen)
 {
-       struct dentry *proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry;
-       return proc_dentry->d_inode->i_op->readlink(proc_dentry, buffer,
+       struct dentry *proc_dentry = HPPFS_I(d_inode(dentry))->proc_dentry;
+       return d_inode(proc_dentry)->i_op->readlink(proc_dentry, buffer,
                                                    buflen);
 }
 
 static void *hppfs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-       struct dentry *proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry;
+       struct dentry *proc_dentry = HPPFS_I(d_inode(dentry))->proc_dentry;
 
-       return proc_dentry->d_inode->i_op->follow_link(proc_dentry, nd);
+       return d_inode(proc_dentry)->i_op->follow_link(proc_dentry, nd);
 }
 
 static void hppfs_put_link(struct dentry *dentry, struct nameidata *nd,
                           void *cookie)
 {
-       struct dentry *proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry;
+       struct dentry *proc_dentry = HPPFS_I(d_inode(dentry))->proc_dentry;
 
-       if (proc_dentry->d_inode->i_op->put_link)
-               proc_dentry->d_inode->i_op->put_link(proc_dentry, nd, cookie);
+       if (d_inode(proc_dentry)->i_op->put_link)
+               d_inode(proc_dentry)->i_op->put_link(proc_dentry, nd, cookie);
 }
 
 static const struct inode_operations hppfs_dir_iops = {
@@ -670,7 +670,7 @@ static const struct inode_operations hppfs_link_iops = {
 
 static struct inode *get_inode(struct super_block *sb, struct dentry *dentry)
 {
-       struct inode *proc_ino = dentry->d_inode;
+       struct inode *proc_ino = d_inode(dentry);
        struct inode *inode = new_inode(sb);
 
        if (!inode) {
index 2640d88b0e638c4085941180762ca6979ff11f1b..87724c1d7be66361a4b36fc5365818f02bd6b60b 100644 (file)
@@ -393,7 +393,7 @@ static int hugetlb_vmtruncate(struct inode *inode, loff_t offset)
 
 static int hugetlbfs_setattr(struct dentry *dentry, struct iattr *attr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct hstate *h = hstate_inode(inode);
        int error;
        unsigned int ia_valid = attr->ia_valid;
@@ -587,7 +587,7 @@ static int hugetlbfs_migrate_page(struct address_space *mapping,
 static int hugetlbfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
        struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(dentry->d_sb);
-       struct hstate *h = hstate_inode(dentry->d_inode);
+       struct hstate *h = hstate_inode(d_inode(dentry));
 
        buf->f_type = HUGETLBFS_MAGIC;
        buf->f_bsize = huge_page_size(h);
index f00b16f4550781f3e658ebf2f9d8d00e3fd36f64..ea37cd17b53f0c98b47e2e626b9ff2a9b6e5699b 100644 (file)
@@ -1587,7 +1587,7 @@ static int update_time(struct inode *inode, struct timespec *time, int flags)
 void touch_atime(const struct path *path)
 {
        struct vfsmount *mnt = path->mnt;
-       struct inode *inode = path->dentry->d_inode;
+       struct inode *inode = d_inode(path->dentry);
        struct timespec now;
 
        if (inode->i_flags & S_NOATIME)
@@ -1639,7 +1639,7 @@ EXPORT_SYMBOL(touch_atime);
  */
 int should_remove_suid(struct dentry *dentry)
 {
-       umode_t mode = dentry->d_inode->i_mode;
+       umode_t mode = d_inode(dentry)->i_mode;
        int kill = 0;
 
        /* suid always must be killed */
@@ -1675,7 +1675,7 @@ static int __remove_suid(struct dentry *dentry, int kill)
 int file_remove_suid(struct file *file)
 {
        struct dentry *dentry = file->f_path.dentry;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int killsuid;
        int killpriv;
        int error = 0;
@@ -1945,20 +1945,6 @@ void inode_dio_wait(struct inode *inode)
 }
 EXPORT_SYMBOL(inode_dio_wait);
 
-/*
- * inode_dio_done - signal finish of a direct I/O requests
- * @inode: inode the direct I/O happens on
- *
- * This is called once we've finished processing a direct I/O request,
- * and is used to wake up callers waiting for direct I/O to be quiesced.
- */
-void inode_dio_done(struct inode *inode)
-{
-       if (atomic_dec_and_test(&inode->i_dio_count))
-               wake_up_bit(&inode->i_state, __I_DIO_WAKEUP);
-}
-EXPORT_SYMBOL(inode_dio_done);
-
 /*
  * inode_set_flags - atomically set some inode flags
  *
index 12088d8de3faa1984fa88db3228dfcf669bb1539..0c5f721b4e91d019d8b25a756b40dacaff0f4463 100644 (file)
@@ -44,7 +44,7 @@ static struct dentry *isofs_export_get_parent(struct dentry *child)
 {
        unsigned long parent_block = 0;
        unsigned long parent_offset = 0;
-       struct inode *child_inode = child->d_inode;
+       struct inode *child_inode = d_inode(child);
        struct iso_inode_info *e_child_inode = ISOFS_I(child_inode);
        struct iso_directory_record *de = NULL;
        struct buffer_head * bh = NULL;
index f21b6fb5e4c42f219022edb51c84a0d0674bd4d2..1ba5c97943b8751f0210870a7bb51636dd4e5ecd 100644 (file)
@@ -224,14 +224,14 @@ static int jffs2_unlink(struct inode *dir_i, struct dentry *dentry)
 {
        struct jffs2_sb_info *c = JFFS2_SB_INFO(dir_i->i_sb);
        struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i);
-       struct jffs2_inode_info *dead_f = JFFS2_INODE_INFO(dentry->d_inode);
+       struct jffs2_inode_info *dead_f = JFFS2_INODE_INFO(d_inode(dentry));
        int ret;
        uint32_t now = get_seconds();
 
        ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name,
                              dentry->d_name.len, dead_f, now);
        if (dead_f->inocache)
-               set_nlink(dentry->d_inode, dead_f->inocache->pino_nlink);
+               set_nlink(d_inode(dentry), dead_f->inocache->pino_nlink);
        if (!ret)
                dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
        return ret;
@@ -241,8 +241,8 @@ static int jffs2_unlink(struct inode *dir_i, struct dentry *dentry)
 
 static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct dentry *dentry)
 {
-       struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dentry->d_inode->i_sb);
-       struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode);
+       struct jffs2_sb_info *c = JFFS2_SB_INFO(d_inode(old_dentry)->i_sb);
+       struct jffs2_inode_info *f = JFFS2_INODE_INFO(d_inode(old_dentry));
        struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i);
        int ret;
        uint8_t type;
@@ -256,7 +256,7 @@ static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct de
                return -EPERM;
 
        /* XXX: This is ugly */
-       type = (old_dentry->d_inode->i_mode & S_IFMT) >> 12;
+       type = (d_inode(old_dentry)->i_mode & S_IFMT) >> 12;
        if (!type) type = DT_REG;
 
        now = get_seconds();
@@ -264,11 +264,11 @@ static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct de
 
        if (!ret) {
                mutex_lock(&f->sem);
-               set_nlink(old_dentry->d_inode, ++f->inocache->pino_nlink);
+               set_nlink(d_inode(old_dentry), ++f->inocache->pino_nlink);
                mutex_unlock(&f->sem);
-               d_instantiate(dentry, old_dentry->d_inode);
+               d_instantiate(dentry, d_inode(old_dentry));
                dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
-               ihold(old_dentry->d_inode);
+               ihold(d_inode(old_dentry));
        }
        return ret;
 }
@@ -585,7 +585,7 @@ static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry)
 {
        struct jffs2_sb_info *c = JFFS2_SB_INFO(dir_i->i_sb);
        struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i);
-       struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode);
+       struct jffs2_inode_info *f = JFFS2_INODE_INFO(d_inode(dentry));
        struct jffs2_full_dirent *fd;
        int ret;
        uint32_t now = get_seconds();
@@ -599,7 +599,7 @@ static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry)
                              dentry->d_name.len, f, now);
        if (!ret) {
                dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
-               clear_nlink(dentry->d_inode);
+               clear_nlink(d_inode(dentry));
                drop_nlink(dir_i);
        }
        return ret;
@@ -770,8 +770,8 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
         * the VFS can't check whether the victim is empty. The filesystem
         * needs to do that for itself.
         */
-       if (new_dentry->d_inode) {
-               victim_f = JFFS2_INODE_INFO(new_dentry->d_inode);
+       if (d_really_is_positive(new_dentry)) {
+               victim_f = JFFS2_INODE_INFO(d_inode(new_dentry));
                if (d_is_dir(new_dentry)) {
                        struct jffs2_full_dirent *fd;
 
@@ -794,12 +794,12 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
        /* Make a hard link */
 
        /* XXX: This is ugly */
-       type = (old_dentry->d_inode->i_mode & S_IFMT) >> 12;
+       type = (d_inode(old_dentry)->i_mode & S_IFMT) >> 12;
        if (!type) type = DT_REG;
 
        now = get_seconds();
        ret = jffs2_do_link(c, JFFS2_INODE_INFO(new_dir_i),
-                           old_dentry->d_inode->i_ino, type,
+                           d_inode(old_dentry)->i_ino, type,
                            new_dentry->d_name.name, new_dentry->d_name.len, now);
 
        if (ret)
@@ -808,9 +808,9 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
        if (victim_f) {
                /* There was a victim. Kill it off nicely */
                if (d_is_dir(new_dentry))
-                       clear_nlink(new_dentry->d_inode);
+                       clear_nlink(d_inode(new_dentry));
                else
-                       drop_nlink(new_dentry->d_inode);
+                       drop_nlink(d_inode(new_dentry));
                /* Don't oops if the victim was a dirent pointing to an
                   inode which didn't exist. */
                if (victim_f->inocache) {
@@ -836,9 +836,9 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
 
        if (ret) {
                /* Oh shit. We really ought to make a single node which can do both atomically */
-               struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode);
+               struct jffs2_inode_info *f = JFFS2_INODE_INFO(d_inode(old_dentry));
                mutex_lock(&f->sem);
-               inc_nlink(old_dentry->d_inode);
+               inc_nlink(d_inode(old_dentry));
                if (f->inocache && !d_is_dir(old_dentry))
                        f->inocache->pino_nlink++;
                mutex_unlock(&f->sem);
@@ -846,8 +846,8 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
                pr_notice("%s(): Link succeeded, unlink failed (err %d). You now have a hard link\n",
                          __func__, ret);
                /* Might as well let the VFS know */
-               d_instantiate(new_dentry, old_dentry->d_inode);
-               ihold(old_dentry->d_inode);
+               d_instantiate(new_dentry, d_inode(old_dentry));
+               ihold(d_inode(old_dentry));
                new_dir_i->i_mtime = new_dir_i->i_ctime = ITIME(now);
                return ret;
        }
index 601afd1afddf5bca94fb35f993e61919b6bbdcd4..fe5ea080b4ec810f29589b257f605389067dadf4 100644 (file)
@@ -190,7 +190,7 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
 
 int jffs2_setattr(struct dentry *dentry, struct iattr *iattr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int rc;
 
        rc = inode_change_ok(inode, iattr);
index aca97f35b292f71be6a1a01007780c25a990551c..d4b43fb7adb18db678fc6bacf9cf9a0f3432af19 100644 (file)
@@ -54,7 +54,7 @@ static int jffs2_security_getxattr(struct dentry *dentry, const char *name,
        if (!strcmp(name, ""))
                return -EINVAL;
 
-       return do_jffs2_getxattr(dentry->d_inode, JFFS2_XPREFIX_SECURITY,
+       return do_jffs2_getxattr(d_inode(dentry), JFFS2_XPREFIX_SECURITY,
                                 name, buffer, size);
 }
 
@@ -64,7 +64,7 @@ static int jffs2_security_setxattr(struct dentry *dentry, const char *name,
        if (!strcmp(name, ""))
                return -EINVAL;
 
-       return do_jffs2_setxattr(dentry->d_inode, JFFS2_XPREFIX_SECURITY,
+       return do_jffs2_setxattr(d_inode(dentry), JFFS2_XPREFIX_SECURITY,
                                 name, buffer, size, flags);
 }
 
index 3d76f28a2ba9dc1d9e4b1d5b9dfde57af1b983e6..d86c5e3176a133cd898a62ff8a587010da845385 100644 (file)
@@ -140,14 +140,14 @@ static struct dentry *jffs2_get_parent(struct dentry *child)
 
        BUG_ON(!d_is_dir(child));
 
-       f = JFFS2_INODE_INFO(child->d_inode);
+       f = JFFS2_INODE_INFO(d_inode(child));
 
        pino = f->inocache->pino_nlink;
 
        JFFS2_DEBUG("Parent of directory ino #%u is #%u\n",
                    f->inocache->ino, pino);
 
-       return d_obtain_alias(jffs2_iget(child->d_inode->i_sb, pino));
+       return d_obtain_alias(jffs2_iget(d_inode(child)->i_sb, pino));
 }
 
 static const struct export_operations jffs2_export_ops = {
index c7c77b0dfccde2fe5dedb619500fb8f4f4a1f866..1fefa25d0fa586a14caae06efea7363794be38fc 100644 (file)
@@ -31,7 +31,7 @@ const struct inode_operations jffs2_symlink_inode_operations =
 
 static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-       struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode);
+       struct jffs2_inode_info *f = JFFS2_INODE_INFO(d_inode(dentry));
        char *p = (char *)f->target;
 
        /*
index 762c7a3cf43d1b650757d25e2d38830b2b567f37..f092fee5be50511f643e9fac79c03d393cef18f2 100644 (file)
@@ -960,7 +960,7 @@ static const struct xattr_handler *xprefix_to_handler(int xprefix) {
 
 ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
        struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
        struct jffs2_inode_cache *ic = f->inocache;
@@ -1266,7 +1266,6 @@ int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_
        if (rc) {
                JFFS2_WARNING("%s: jffs2_reserve_space_gc() = %d, request = %u\n",
                              __func__, rc, totlen);
-               rc = rc ? rc : -EBADFD;
                goto out;
        }
        rc = save_xattr_ref(c, ref);
index 1c868194c5045b7ef2399ba89206038ddf534419..ceaf9c693225b44edeb5bb3bddea534c1b62ad51 100644 (file)
@@ -21,7 +21,7 @@ static int jffs2_trusted_getxattr(struct dentry *dentry, const char *name,
 {
        if (!strcmp(name, ""))
                return -EINVAL;
-       return do_jffs2_getxattr(dentry->d_inode, JFFS2_XPREFIX_TRUSTED,
+       return do_jffs2_getxattr(d_inode(dentry), JFFS2_XPREFIX_TRUSTED,
                                 name, buffer, size);
 }
 
@@ -30,7 +30,7 @@ static int jffs2_trusted_setxattr(struct dentry *dentry, const char *name,
 {
        if (!strcmp(name, ""))
                return -EINVAL;
-       return do_jffs2_setxattr(dentry->d_inode, JFFS2_XPREFIX_TRUSTED,
+       return do_jffs2_setxattr(d_inode(dentry), JFFS2_XPREFIX_TRUSTED,
                                 name, buffer, size, flags);
 }
 
index 916b5c96603942b718759dbda4b54b72223679a1..a71391eba51497bf7902f10ee44955e67b623e5e 100644 (file)
@@ -21,7 +21,7 @@ static int jffs2_user_getxattr(struct dentry *dentry, const char *name,
 {
        if (!strcmp(name, ""))
                return -EINVAL;
-       return do_jffs2_getxattr(dentry->d_inode, JFFS2_XPREFIX_USER,
+       return do_jffs2_getxattr(d_inode(dentry), JFFS2_XPREFIX_USER,
                                 name, buffer, size);
 }
 
@@ -30,7 +30,7 @@ static int jffs2_user_setxattr(struct dentry *dentry, const char *name,
 {
        if (!strcmp(name, ""))
                return -EINVAL;
-       return do_jffs2_setxattr(dentry->d_inode, JFFS2_XPREFIX_USER,
+       return do_jffs2_setxattr(d_inode(dentry), JFFS2_XPREFIX_USER,
                                 name, buffer, size, flags);
 }
 
index ae46788b97231efecb7eaf7d7c0a0b9c779349ef..e98d39d75cf41a3f63c889958f87804dbb6aacf2 100644 (file)
@@ -100,7 +100,7 @@ static int jfs_release(struct inode *inode, struct file *file)
 
 int jfs_setattr(struct dentry *dentry, struct iattr *iattr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int rc;
 
        rc = inode_change_ok(inode, iattr);
index 38fdc533f4ecba5042f3473d0efe0454b2d52ef3..66db7bc0ed1096050c2b2f93c3aa9e16a0ba4726 100644 (file)
@@ -346,7 +346,7 @@ static int jfs_rmdir(struct inode *dip, struct dentry *dentry)
 {
        int rc;
        tid_t tid;              /* transaction id */
-       struct inode *ip = dentry->d_inode;
+       struct inode *ip = d_inode(dentry);
        ino_t ino;
        struct component_name dname;
        struct inode *iplist[2];
@@ -472,7 +472,7 @@ static int jfs_unlink(struct inode *dip, struct dentry *dentry)
 {
        int rc;
        tid_t tid;              /* transaction id */
-       struct inode *ip = dentry->d_inode;
+       struct inode *ip = d_inode(dentry);
        ino_t ino;
        struct component_name dname;    /* object name */
        struct inode *iplist[2];
@@ -791,7 +791,7 @@ static int jfs_link(struct dentry *old_dentry,
 {
        int rc;
        tid_t tid;
-       struct inode *ip = old_dentry->d_inode;
+       struct inode *ip = d_inode(old_dentry);
        ino_t ino;
        struct component_name dname;
        struct btstack btstack;
@@ -879,7 +879,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
        struct component_name dname;
        int ssize;              /* source pathname size */
        struct btstack btstack;
-       struct inode *ip = dentry->d_inode;
+       struct inode *ip = d_inode(dentry);
        unchar *i_fastsymlink;
        s64 xlen = 0;
        int bmask = 0, xsize;
@@ -1086,8 +1086,8 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        dquot_initialize(old_dir);
        dquot_initialize(new_dir);
 
-       old_ip = old_dentry->d_inode;
-       new_ip = new_dentry->d_inode;
+       old_ip = d_inode(old_dentry);
+       new_ip = d_inode(new_dentry);
 
        if ((rc = get_UCSname(&old_dname, old_dentry)))
                goto out1;
@@ -1500,9 +1500,9 @@ struct dentry *jfs_get_parent(struct dentry *dentry)
        unsigned long parent_ino;
 
        parent_ino =
-               le32_to_cpu(JFS_IP(dentry->d_inode)->i_dtroot.header.idotdot);
+               le32_to_cpu(JFS_IP(d_inode(dentry))->i_dtroot.header.idotdot);
 
-       return d_obtain_alias(jfs_iget(dentry->d_inode->i_sb, parent_ino));
+       return d_obtain_alias(jfs_iget(d_inode(dentry)->i_sb, parent_ino));
 }
 
 const struct inode_operations jfs_dir_inode_operations = {
@@ -1578,7 +1578,7 @@ static int jfs_ci_revalidate(struct dentry *dentry, unsigned int flags)
         * positive dentry isn't good idea. So it's unsupported like
         * rename("filename", "FILENAME") for now.
         */
-       if (dentry->d_inode)
+       if (d_really_is_positive(dentry))
                return 1;
 
        /*
index 205b946d8e0d3a2abd805896b93536dfc1193e39..80f42bcc4ef1295669de10ea1087384f1c98c95b 100644 (file)
@@ -24,7 +24,7 @@
 
 static void *jfs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-       char *s = JFS_IP(dentry->d_inode)->i_inline;
+       char *s = JFS_IP(d_inode(dentry))->i_inline;
        nd_set_link(nd, s);
        return NULL;
 }
index 46325d5c34fc37f1e2861c959e875886bfef124c..48b15a6e55586588a853018c92ce71acf329c9ba 100644 (file)
@@ -849,7 +849,7 @@ int __jfs_setxattr(tid_t tid, struct inode *inode, const char *name,
 int jfs_setxattr(struct dentry *dentry, const char *name, const void *value,
                 size_t value_len, int flags)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct jfs_inode_info *ji = JFS_IP(inode);
        int rc;
        tid_t tid;
@@ -872,7 +872,7 @@ int jfs_setxattr(struct dentry *dentry, const char *name, const void *value,
 
        tid = txBegin(inode->i_sb, 0);
        mutex_lock(&ji->commit_mutex);
-       rc = __jfs_setxattr(tid, dentry->d_inode, name, value, value_len,
+       rc = __jfs_setxattr(tid, d_inode(dentry), name, value, value_len,
                            flags);
        if (!rc)
                rc = txCommit(tid, 1, &inode, 0);
@@ -959,7 +959,7 @@ ssize_t jfs_getxattr(struct dentry *dentry, const char *name, void *data,
                        return -EOPNOTSUPP;
        }
 
-       err = __jfs_getxattr(dentry->d_inode, name, data, buf_size);
+       err = __jfs_getxattr(d_inode(dentry), name, data, buf_size);
 
        return err;
 }
@@ -976,7 +976,7 @@ static inline int can_list(struct jfs_ea *ea)
 
 ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        char *buffer;
        ssize_t size = 0;
        int xattr_size;
@@ -1029,7 +1029,7 @@ ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size)
 
 int jfs_removexattr(struct dentry *dentry, const char *name)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct jfs_inode_info *ji = JFS_IP(inode);
        int rc;
        tid_t tid;
@@ -1047,7 +1047,7 @@ int jfs_removexattr(struct dentry *dentry, const char *name)
 
        tid = txBegin(inode->i_sb, 0);
        mutex_lock(&ji->commit_mutex);
-       rc = __jfs_setxattr(tid, dentry->d_inode, name, NULL, 0, XATTR_REPLACE);
+       rc = __jfs_setxattr(tid, d_inode(dentry), name, NULL, 0, XATTR_REPLACE);
        if (!rc)
                rc = txCommit(tid, 1, &inode, 0);
        txEnd(tid);
index 6acc9648f9869727dc9fb030d281d37bffdf3277..f131fc23ffc4c18f03a9764973fa998bf0e5f79e 100644 (file)
@@ -444,7 +444,7 @@ static int kernfs_dop_revalidate(struct dentry *dentry, unsigned int flags)
                return -ECHILD;
 
        /* Always perform fresh lookup for negatives */
-       if (!dentry->d_inode)
+       if (d_really_is_negative(dentry))
                goto out_bad_unlocked;
 
        kn = dentry->d_fsdata;
index 9000874a945b62bf4f4fded166133d5f90159823..2da8493a380b8a43a8eca65c04f4de245c4b0219 100644 (file)
@@ -111,7 +111,7 @@ int kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr)
 
 int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct kernfs_node *kn = dentry->d_fsdata;
        int error;
 
@@ -172,11 +172,11 @@ int kernfs_iop_setxattr(struct dentry *dentry, const char *name,
 
        if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)) {
                const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
-               error = security_inode_setsecurity(dentry->d_inode, suffix,
+               error = security_inode_setsecurity(d_inode(dentry), suffix,
                                                value, size, flags);
                if (error)
                        return error;
-               error = security_inode_getsecctx(dentry->d_inode,
+               error = security_inode_getsecctx(d_inode(dentry),
                                                &secdata, &secdata_len);
                if (error)
                        return error;
@@ -271,7 +271,7 @@ int kernfs_iop_getattr(struct vfsmount *mnt, struct dentry *dentry,
                   struct kstat *stat)
 {
        struct kernfs_node *kn = dentry->d_fsdata;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
 
        mutex_lock(&kernfs_mutex);
        kernfs_refresh_inode(kn, inode);
index 0ab65122ee45405bfcc96463a3de2b228b36e283..cb1fb4b9b6377b09b669b833cc3437b259b622f6 100644 (file)
 
 static inline int simple_positive(struct dentry *dentry)
 {
-       return dentry->d_inode && !d_unhashed(dentry);
+       return d_really_is_positive(dentry) && !d_unhashed(dentry);
 }
 
 int simple_getattr(struct vfsmount *mnt, struct dentry *dentry,
                   struct kstat *stat)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        generic_fillattr(inode, stat);
        stat->blocks = inode->i_mapping->nrpages << (PAGE_CACHE_SHIFT - 9);
        return 0;
@@ -94,7 +94,7 @@ EXPORT_SYMBOL(dcache_dir_close);
 loff_t dcache_dir_lseek(struct file *file, loff_t offset, int whence)
 {
        struct dentry *dentry = file->f_path.dentry;
-       mutex_lock(&dentry->d_inode->i_mutex);
+       mutex_lock(&d_inode(dentry)->i_mutex);
        switch (whence) {
                case 1:
                        offset += file->f_pos;
@@ -102,7 +102,7 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int whence)
                        if (offset >= 0)
                                break;
                default:
-                       mutex_unlock(&dentry->d_inode->i_mutex);
+                       mutex_unlock(&d_inode(dentry)->i_mutex);
                        return -EINVAL;
        }
        if (offset != file->f_pos) {
@@ -129,7 +129,7 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int whence)
                        spin_unlock(&dentry->d_lock);
                }
        }
-       mutex_unlock(&dentry->d_inode->i_mutex);
+       mutex_unlock(&d_inode(dentry)->i_mutex);
        return offset;
 }
 EXPORT_SYMBOL(dcache_dir_lseek);
@@ -169,7 +169,7 @@ int dcache_readdir(struct file *file, struct dir_context *ctx)
                spin_unlock(&next->d_lock);
                spin_unlock(&dentry->d_lock);
                if (!dir_emit(ctx, next->d_name.name, next->d_name.len,
-                             next->d_inode->i_ino, dt_type(next->d_inode)))
+                             d_inode(next)->i_ino, dt_type(d_inode(next))))
                        return 0;
                spin_lock(&dentry->d_lock);
                spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
@@ -270,7 +270,7 @@ EXPORT_SYMBOL(simple_open);
 
 int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
 {
-       struct inode *inode = old_dentry->d_inode;
+       struct inode *inode = d_inode(old_dentry);
 
        inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
        inc_nlink(inode);
@@ -304,7 +304,7 @@ EXPORT_SYMBOL(simple_empty);
 
 int simple_unlink(struct inode *dir, struct dentry *dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
 
        inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
        drop_nlink(inode);
@@ -318,7 +318,7 @@ int simple_rmdir(struct inode *dir, struct dentry *dentry)
        if (!simple_empty(dentry))
                return -ENOTEMPTY;
 
-       drop_nlink(dentry->d_inode);
+       drop_nlink(d_inode(dentry));
        simple_unlink(dir, dentry);
        drop_nlink(dir);
        return 0;
@@ -328,16 +328,16 @@ EXPORT_SYMBOL(simple_rmdir);
 int simple_rename(struct inode *old_dir, struct dentry *old_dentry,
                struct inode *new_dir, struct dentry *new_dentry)
 {
-       struct inode *inode = old_dentry->d_inode;
+       struct inode *inode = d_inode(old_dentry);
        int they_are_dirs = d_is_dir(old_dentry);
 
        if (!simple_empty(new_dentry))
                return -ENOTEMPTY;
 
-       if (new_dentry->d_inode) {
+       if (d_really_is_positive(new_dentry)) {
                simple_unlink(new_dir, new_dentry);
                if (they_are_dirs) {
-                       drop_nlink(new_dentry->d_inode);
+                       drop_nlink(d_inode(new_dentry));
                        drop_nlink(old_dir);
                }
        } else if (they_are_dirs) {
@@ -368,7 +368,7 @@ EXPORT_SYMBOL(simple_rename);
  */
 int simple_setattr(struct dentry *dentry, struct iattr *iattr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int error;
 
        error = inode_change_ok(inode, iattr);
index 665ef5a05183557fe7cee2fdb4ff535faece7778..a563ddbc19e6935e91fe42a6946ee937efab482c 100644 (file)
@@ -31,7 +31,7 @@
 static struct hlist_head       nlm_files[FILE_NRHASH];
 static DEFINE_MUTEX(nlm_file_mutex);
 
-#ifdef NFSD_DEBUG
+#ifdef CONFIG_SUNRPC_DEBUG
 static inline void nlm_debug_print_fh(char *msg, struct nfs_fh *f)
 {
        u32 *fhp = (u32*)f->data;
index 6bdc347008f5eb15d2d60ea9750202e72d380f18..4cf38f1185494115c0dcb8625f07b6593ae15fd5 100644 (file)
@@ -213,7 +213,7 @@ static void abort_transaction(struct inode *inode, struct logfs_transaction *ta)
 static int logfs_unlink(struct inode *dir, struct dentry *dentry)
 {
        struct logfs_super *super = logfs_super(dir->i_sb);
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct logfs_transaction *ta;
        struct page *page;
        pgoff_t index;
@@ -271,7 +271,7 @@ static inline int logfs_empty_dir(struct inode *dir)
 
 static int logfs_rmdir(struct inode *dir, struct dentry *dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
 
        if (!logfs_empty_dir(inode))
                return -ENOTEMPTY;
@@ -537,7 +537,7 @@ static int logfs_symlink(struct inode *dir, struct dentry *dentry,
 static int logfs_link(struct dentry *old_dentry, struct inode *dir,
                struct dentry *dentry)
 {
-       struct inode *inode = old_dentry->d_inode;
+       struct inode *inode = d_inode(old_dentry);
 
        inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
        ihold(inode);
@@ -607,7 +607,7 @@ static int logfs_rename_cross(struct inode *old_dir, struct dentry *old_dentry,
        /* 2. write target dd */
        mutex_lock(&super->s_dirop_mutex);
        logfs_add_transaction(new_dir, ta);
-       err = logfs_write_dir(new_dir, new_dentry, old_dentry->d_inode);
+       err = logfs_write_dir(new_dir, new_dentry, d_inode(old_dentry));
        if (!err)
                err = write_inode(new_dir);
 
@@ -658,8 +658,8 @@ static int logfs_rename_target(struct inode *old_dir, struct dentry *old_dentry,
                               struct inode *new_dir, struct dentry *new_dentry)
 {
        struct logfs_super *super = logfs_super(old_dir->i_sb);
-       struct inode *old_inode = old_dentry->d_inode;
-       struct inode *new_inode = new_dentry->d_inode;
+       struct inode *old_inode = d_inode(old_dentry);
+       struct inode *new_inode = d_inode(new_dentry);
        int isdir = S_ISDIR(old_inode->i_mode);
        struct logfs_disk_dentry dd;
        struct logfs_transaction *ta;
@@ -719,7 +719,7 @@ out:
 static int logfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                        struct inode *new_dir, struct dentry *new_dentry)
 {
-       if (new_dentry->d_inode)
+       if (d_really_is_positive(new_dentry))
                return logfs_rename_target(old_dir, old_dentry,
                                           new_dir, new_dentry);
        return logfs_rename_cross(old_dir, old_dentry, new_dir, new_dentry);
index b2c13f739ffa27b8b8a249cadcd025737a512ce6..1a6f0167b16a7a4b657138ed7c366e8fe3151dfd 100644 (file)
@@ -241,7 +241,7 @@ int logfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 
 static int logfs_setattr(struct dentry *dentry, struct iattr *attr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int err = 0;
 
        err = inode_change_ok(inode, attr);
index dfaf6fa9b7b52a28bcb00ce3c4cd3df817158814..118e4e7bc9351cb3563a0ce85798301c83f0213e 100644 (file)
@@ -156,7 +156,7 @@ minix_dirent *minix_find_entry(struct dentry *dentry, struct page **res_page)
 {
        const char * name = dentry->d_name.name;
        int namelen = dentry->d_name.len;
-       struct inode * dir = dentry->d_parent->d_inode;
+       struct inode * dir = d_inode(dentry->d_parent);
        struct super_block * sb = dir->i_sb;
        struct minix_sb_info * sbi = minix_sb(sb);
        unsigned long n;
@@ -203,7 +203,7 @@ found:
 
 int minix_add_link(struct dentry *dentry, struct inode *inode)
 {
-       struct inode *dir = dentry->d_parent->d_inode;
+       struct inode *dir = d_inode(dentry->d_parent);
        const char * name = dentry->d_name.name;
        int namelen = dentry->d_name.len;
        struct super_block * sb = dir->i_sb;
index 6d63e27ec961c6ed03b9bbcd46414d4436e065dd..94f0eb9a6e2c1f77db3b3d5095092cf47c655976 100644 (file)
@@ -23,7 +23,7 @@ const struct file_operations minix_file_operations = {
 
 static int minix_setattr(struct dentry *dentry, struct iattr *attr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int error;
 
        error = inode_change_ok(inode, attr);
index 3f57af196a7de36343be9249d2e883a9b162310b..1182d1e26a9ca4e1b83b76903d16e23ef7494183 100644 (file)
@@ -626,8 +626,8 @@ static int minix_write_inode(struct inode *inode, struct writeback_control *wbc)
 int minix_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 {
        struct super_block *sb = dentry->d_sb;
-       generic_fillattr(dentry->d_inode, stat);
-       if (INODE_VERSION(dentry->d_inode) == MINIX_V1)
+       generic_fillattr(d_inode(dentry), stat);
+       if (INODE_VERSION(d_inode(dentry)) == MINIX_V1)
                stat->blocks = (BLOCK_SIZE / 512) * V1_minix_blocks(stat->size, sb);
        else
                stat->blocks = (sb->s_blocksize / 512) * V2_minix_blocks(stat->size, sb);
index cd950e2331b6c3164376e1b2205b3563f5703525..a795a11e50c728a9d31511fbc2849e8fb6fbeb8c 100644 (file)
@@ -104,7 +104,7 @@ out_fail:
 static int minix_link(struct dentry * old_dentry, struct inode * dir,
        struct dentry *dentry)
 {
-       struct inode *inode = old_dentry->d_inode;
+       struct inode *inode = d_inode(old_dentry);
 
        inode->i_ctime = CURRENT_TIME_SEC;
        inode_inc_link_count(inode);
@@ -151,7 +151,7 @@ out_dir:
 static int minix_unlink(struct inode * dir, struct dentry *dentry)
 {
        int err = -ENOENT;
-       struct inode * inode = dentry->d_inode;
+       struct inode * inode = d_inode(dentry);
        struct page * page;
        struct minix_dir_entry * de;
 
@@ -171,7 +171,7 @@ end_unlink:
 
 static int minix_rmdir(struct inode * dir, struct dentry *dentry)
 {
-       struct inode * inode = dentry->d_inode;
+       struct inode * inode = d_inode(dentry);
        int err = -ENOTEMPTY;
 
        if (minix_empty_dir(inode)) {
@@ -187,8 +187,8 @@ static int minix_rmdir(struct inode * dir, struct dentry *dentry)
 static int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
                           struct inode * new_dir, struct dentry *new_dentry)
 {
-       struct inode * old_inode = old_dentry->d_inode;
-       struct inode * new_inode = new_dentry->d_inode;
+       struct inode * old_inode = d_inode(old_dentry);
+       struct inode * new_inode = d_inode(new_dentry);
        struct page * dir_page = NULL;
        struct minix_dir_entry * dir_de = NULL;
        struct page * old_page;
index ffab2e06e1472eca41449cbe5d8fe22baa219d29..4a8d998b7274b3406532cc012d05ee18aa9b5bba 100644 (file)
@@ -1590,7 +1590,8 @@ static inline int walk_component(struct nameidata *nd, struct path *path,
 
        if (should_follow_link(path->dentry, follow)) {
                if (nd->flags & LOOKUP_RCU) {
-                       if (unlikely(unlazy_walk(nd, path->dentry))) {
+                       if (unlikely(nd->path.mnt != path->mnt ||
+                                    unlazy_walk(nd, path->dentry))) {
                                err = -ECHILD;
                                goto out_err;
                        }
@@ -3045,7 +3046,8 @@ finish_lookup:
 
        if (should_follow_link(path->dentry, !symlink_ok)) {
                if (nd->flags & LOOKUP_RCU) {
-                       if (unlikely(unlazy_walk(nd, path->dentry))) {
+                       if (unlikely(nd->path.mnt != path->mnt ||
+                                    unlazy_walk(nd, path->dentry))) {
                                error = -ECHILD;
                                goto out;
                        }
index e7ca827d7694c130e0be25b85fa6e6aed7217ab5..80021c709af9cc02dc2d3a41a0f14fd7b6409e89 100644 (file)
@@ -127,7 +127,7 @@ static inline int ncp_case_sensitive(const struct inode *i)
 static int 
 ncp_hash_dentry(const struct dentry *dentry, struct qstr *this)
 {
-       struct inode *inode = ACCESS_ONCE(dentry->d_inode);
+       struct inode *inode = d_inode_rcu(dentry);
 
        if (!inode)
                return 0;
@@ -162,7 +162,7 @@ ncp_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
        if (len != name->len)
                return 1;
 
-       pinode = ACCESS_ONCE(parent->d_inode);
+       pinode = d_inode_rcu(parent);
        if (!pinode)
                return 1;
 
@@ -180,7 +180,7 @@ ncp_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
 static int
 ncp_delete_dentry(const struct dentry * dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
 
        if (inode) {
                if (is_bad_inode(inode))
@@ -224,7 +224,7 @@ ncp_force_unlink(struct inode *dir, struct dentry* dentry)
        memset(&info, 0, sizeof(info));
        
         /* remove the Read-Only flag on the NW server */
-       inode = dentry->d_inode;
+       inode = d_inode(dentry);
 
        old_nwattr = NCP_FINFO(inode)->nwattr;
        info.attributes = old_nwattr & ~(aRONLY|aDELETEINHIBIT|aRENAMEINHIBIT);
@@ -254,7 +254,7 @@ ncp_force_rename(struct inode *old_dir, struct dentry* old_dentry, char *_old_na
 {
        struct nw_modify_dos_info info;
         int res=0x90,res2;
-       struct inode *old_inode = old_dentry->d_inode;
+       struct inode *old_inode = d_inode(old_dentry);
        __le32 old_nwattr = NCP_FINFO(old_inode)->nwattr;
        __le32 new_nwattr = 0; /* shut compiler warning */
        int old_nwattr_changed = 0;
@@ -268,8 +268,8 @@ ncp_force_rename(struct inode *old_dir, struct dentry* old_dentry, char *_old_na
        res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);
        if (!res2)
                old_nwattr_changed = 1;
-       if (new_dentry && new_dentry->d_inode) {
-               new_nwattr = NCP_FINFO(new_dentry->d_inode)->nwattr;
+       if (new_dentry && d_really_is_positive(new_dentry)) {
+               new_nwattr = NCP_FINFO(d_inode(new_dentry))->nwattr;
                info.attributes = new_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
                res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);
                if (!res2)
@@ -324,9 +324,9 @@ ncp_lookup_validate(struct dentry *dentry, unsigned int flags)
                return -ECHILD;
 
        parent = dget_parent(dentry);
-       dir = parent->d_inode;
+       dir = d_inode(parent);
 
-       if (!dentry->d_inode)
+       if (d_really_is_negative(dentry))
                goto finished;
 
        server = NCP_SERVER(dir);
@@ -367,7 +367,7 @@ ncp_lookup_validate(struct dentry *dentry, unsigned int flags)
         * what we remember, it's not valid any more.
         */
        if (!res) {
-               struct inode *inode = dentry->d_inode;
+               struct inode *inode = d_inode(dentry);
 
                mutex_lock(&inode->i_mutex);
                if (finfo.i.dirEntNum == NCP_FINFO(inode)->dirEntNum) {
@@ -388,7 +388,7 @@ finished:
 
 static time_t ncp_obtain_mtime(struct dentry *dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct ncp_server *server = NCP_SERVER(inode);
        struct nw_info_struct i;
 
@@ -404,7 +404,7 @@ static time_t ncp_obtain_mtime(struct dentry *dentry)
 static inline void
 ncp_invalidate_dircache_entries(struct dentry *parent)
 {
-       struct ncp_server *server = NCP_SERVER(parent->d_inode);
+       struct ncp_server *server = NCP_SERVER(d_inode(parent));
        struct dentry *dentry;
 
        spin_lock(&parent->d_lock);
@@ -418,7 +418,7 @@ ncp_invalidate_dircache_entries(struct dentry *parent)
 static int ncp_readdir(struct file *file, struct dir_context *ctx)
 {
        struct dentry *dentry = file->f_path.dentry;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct page *page = NULL;
        struct ncp_server *server = NCP_SERVER(inode);
        union  ncp_dir_cache *cache = NULL;
@@ -491,13 +491,13 @@ static int ncp_readdir(struct file *file, struct dir_context *ctx)
                                goto invalid_cache;
                        }
                        spin_unlock(&dentry->d_lock);
-                       if (!dent->d_inode) {
+                       if (d_really_is_negative(dent)) {
                                dput(dent);
                                goto invalid_cache;
                        }
                        over = !dir_emit(ctx, dent->d_name.name,
                                        dent->d_name.len,
-                                       dent->d_inode->i_ino, DT_UNKNOWN);
+                                       d_inode(dent)->i_ino, DT_UNKNOWN);
                        dput(dent);
                        if (over)
                                goto finished;
@@ -571,7 +571,7 @@ static void ncp_d_prune(struct dentry *dentry)
 {
        if (!dentry->d_fsdata)  /* not referenced from page cache */
                return;
-       NCP_FINFO(dentry->d_parent->d_inode)->flags &= ~NCPI_DIR_CACHE;
+       NCP_FINFO(d_inode(dentry->d_parent))->flags &= ~NCPI_DIR_CACHE;
 }
 
 static int
@@ -580,7 +580,7 @@ ncp_fill_cache(struct file *file, struct dir_context *ctx,
                int inval_childs)
 {
        struct dentry *newdent, *dentry = file->f_path.dentry;
-       struct inode *dir = dentry->d_inode;
+       struct inode *dir = d_inode(dentry);
        struct ncp_cache_control ctl = *ctrl;
        struct qstr qname;
        int valid = 0;
@@ -621,7 +621,7 @@ ncp_fill_cache(struct file *file, struct dir_context *ctx,
                dentry_update_name_case(newdent, &qname);
        }
 
-       if (!newdent->d_inode) {
+       if (d_really_is_negative(newdent)) {
                struct inode *inode;
 
                entry->opened = 0;
@@ -637,7 +637,7 @@ ncp_fill_cache(struct file *file, struct dir_context *ctx,
                        spin_unlock(&dentry->d_lock);
                }
        } else {
-               struct inode *inode = newdent->d_inode;
+               struct inode *inode = d_inode(newdent);
 
                mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD);
                ncp_update_inode2(inode, entry);
@@ -659,10 +659,10 @@ ncp_fill_cache(struct file *file, struct dir_context *ctx,
                        ctl.cache = kmap(ctl.page);
        }
        if (ctl.cache) {
-               if (newdent->d_inode) {
+               if (d_really_is_positive(newdent)) {
                        newdent->d_fsdata = newdent;
                        ctl.cache->dentry[ctl.idx] = newdent;
-                       ino = newdent->d_inode->i_ino;
+                       ino = d_inode(newdent)->i_ino;
                        ncp_new_dentry(newdent);
                }
                valid = 1;
@@ -807,7 +807,7 @@ int ncp_conn_logged_in(struct super_block *sb)
                }
                dent = sb->s_root;
                if (dent) {
-                       struct inode* ino = dent->d_inode;
+                       struct inode* ino = d_inode(dent);
                        if (ino) {
                                ncp_update_known_namespace(server, volNumber, NULL);
                                NCP_FINFO(ino)->volNumber = volNumber;
@@ -815,7 +815,7 @@ int ncp_conn_logged_in(struct super_block *sb)
                                NCP_FINFO(ino)->DosDirNum = DosDirNum;
                                result = 0;
                        } else {
-                               ncp_dbg(1, "sb->s_root->d_inode == NULL!\n");
+                               ncp_dbg(1, "d_inode(sb->s_root) == NULL!\n");
                        }
                } else {
                        ncp_dbg(1, "sb->s_root == NULL!\n");
@@ -1055,7 +1055,7 @@ out:
 
 static int ncp_unlink(struct inode *dir, struct dentry *dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct ncp_server *server;
        int error;
 
index 01a9e16e97825eb67a7c761c6b7cc969bd8077d0..9605a2f635490ddf498c72049d7b40d84e7f977b 100644 (file)
@@ -812,7 +812,7 @@ static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
        if (!d) {
                goto dflt;
        }
-       i = d->d_inode;
+       i = d_inode(d);
        if (!i) {
                goto dflt;
        }
@@ -865,7 +865,7 @@ dflt:;
 
 int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int result = 0;
        __le32 info_mask;
        struct nw_modify_dos_info info;
@@ -878,7 +878,7 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
                goto out;
 
        result = -EPERM;
-       if (IS_DEADDIR(dentry->d_inode))
+       if (IS_DEADDIR(d_inode(dentry)))
                goto out;
 
        /* ageing the dentry to force validation */
index cf7e043a944770a4c8e48b0b109a115a09c62023..79b113048eacdc645fb67994cb0dcb25aad84dd0 100644 (file)
@@ -376,7 +376,7 @@ static long __ncp_ioctl(struct inode *inode, unsigned int cmd, unsigned long arg
                                struct dentry* dentry = inode->i_sb->s_root;
 
                                if (dentry) {
-                                       struct inode* s_inode = dentry->d_inode;
+                                       struct inode* s_inode = d_inode(dentry);
 
                                        if (s_inode) {
                                                sr.volNumber = NCP_FINFO(s_inode)->volNumber;
@@ -384,7 +384,7 @@ static long __ncp_ioctl(struct inode *inode, unsigned int cmd, unsigned long arg
                                                sr.namespace = server->name_space[sr.volNumber];
                                                result = 0;
                                        } else
-                                               ncp_dbg(1, "s_root->d_inode==NULL\n");
+                                               ncp_dbg(1, "d_inode(s_root)==NULL\n");
                                } else
                                        ncp_dbg(1, "s_root==NULL\n");
                        } else {
@@ -431,7 +431,7 @@ static long __ncp_ioctl(struct inode *inode, unsigned int cmd, unsigned long arg
                                if (result == 0) {
                                        dentry = inode->i_sb->s_root;
                                        if (dentry) {
-                                               struct inode* s_inode = dentry->d_inode;
+                                               struct inode* s_inode = d_inode(dentry);
 
                                                if (s_inode) {
                                                        NCP_FINFO(s_inode)->volNumber = vnum;
@@ -439,7 +439,7 @@ static long __ncp_ioctl(struct inode *inode, unsigned int cmd, unsigned long arg
                                                        NCP_FINFO(s_inode)->DosDirNum = dosde;
                                                        server->root_setuped = 1;
                                                } else {
-                                                       ncp_dbg(1, "s_root->d_inode==NULL\n");
+                                                       ncp_dbg(1, "d_inode(s_root)==NULL\n");
                                                        result = -EIO;
                                                }
                                        } else {
index 2b502a0d79413ef2c01069b8dd228da14ecc354c..88dbbc9fcf4d6a5eb76a95f162481c7b88190a9b 100644 (file)
@@ -727,7 +727,7 @@ int
 ncp_del_file_or_subdir2(struct ncp_server *server,
                        struct dentry *dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        __u8  volnum;
        __le32 dirent;
 
index 1a63bfdb4a6584eb10d6744aabeec27e940513d7..421b6f91e8ecadc3b8105d380f84de38687194e4 100644 (file)
@@ -156,7 +156,7 @@ int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) {
                goto failfree;
        }
 
-       inode=dentry->d_inode;
+       inode=d_inode(dentry);
 
        if (ncp_make_open(inode, O_WRONLY))
                goto failfree;
index 1e987acf20c941312d31cd22bd153222f92e8d71..8664417955a2730b0813a2984b2fe4689a38e3ce 100644 (file)
@@ -22,7 +22,7 @@ nfsv3-$(CONFIG_NFS_V3_ACL) += nfs3acl.o
 obj-$(CONFIG_NFS_V4) += nfsv4.o
 CFLAGS_nfs4trace.o += -I$(src)
 nfsv4-y := nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o nfs4super.o nfs4file.o \
-         delegation.o idmap.o callback.o callback_xdr.o callback_proc.o \
+         delegation.o nfs4idmap.o callback.o callback_xdr.o callback_proc.o \
          nfs4namespace.o nfs4getroot.o nfs4client.o nfs4session.o \
          dns_resolve.o nfs4trace.o
 nfsv4-$(CONFIG_NFS_USE_LEGACY_DNS) += cache_lib.o
index 1cac3c175d1870e63126c37ba4e1c377b5ffe5ca..d2554fe140a3e106fa93bf8d2f048fcad66a2730 100644 (file)
@@ -890,6 +890,7 @@ static struct pnfs_layoutdriver_type blocklayout_type = {
        .free_deviceid_node             = bl_free_deviceid_node,
        .pg_read_ops                    = &bl_pg_read_ops,
        .pg_write_ops                   = &bl_pg_write_ops,
+       .sync                           = pnfs_generic_sync,
 };
 
 static int __init nfs4blocklayout_init(void)
index 5aed4f98df411be1d7612f566f5929d1db28c97a..e535599a07191619c28eba93342388a59267114e 100644 (file)
@@ -33,7 +33,7 @@ bl_free_deviceid_node(struct nfs4_deviceid_node *d)
                container_of(d, struct pnfs_block_dev, node);
 
        bl_free_device(dev);
-       kfree(dev);
+       kfree_rcu(dev, node.rcu);
 }
 
 static int
index 351be9205bf889bd48bf6b1f39b195899e5ab141..8d129bb7355afbb2ca7f1904ff0263f604e86dd6 100644 (file)
@@ -128,7 +128,7 @@ nfs41_callback_svc(void *vrqstp)
                if (try_to_freeze())
                        continue;
 
-               prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_UNINTERRUPTIBLE);
+               prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_INTERRUPTIBLE);
                spin_lock_bh(&serv->sv_cb_lock);
                if (!list_empty(&serv->sv_cb_list)) {
                        req = list_first_entry(&serv->sv_cb_list,
@@ -142,10 +142,10 @@ nfs41_callback_svc(void *vrqstp)
                                error);
                } else {
                        spin_unlock_bh(&serv->sv_cb_lock);
-                       /* schedule_timeout to game the hung task watchdog */
-                       schedule_timeout(60 * HZ);
+                       schedule();
                        finish_wait(&serv->sv_cb_waitq, &wq);
                }
+               flush_signals(current);
        }
        return 0;
 }
index 19874151e95c9908660132e6a3e2e6d7d2d3c8e4..892aefff36300a0861f9bf5d43cb7a4b5069d873 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/lockd/bind.h>
 #include <linux/seq_file.h>
 #include <linux/mount.h>
-#include <linux/nfs_idmap.h>
 #include <linux/vfs.h>
 #include <linux/inet.h>
 #include <linux/in6.h>
index a6ad688658803424d726afae85597ad2ace80044..029d688a969f4427e57ccf6f19b0dca9035c3d71 100644 (file)
@@ -378,7 +378,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
                if (freeme == NULL)
                        goto out;
        }
-       list_add_rcu(&delegation->super_list, &server->delegations);
+       list_add_tail_rcu(&delegation->super_list, &server->delegations);
        rcu_assign_pointer(nfsi->delegation, delegation);
        delegation = NULL;
 
@@ -514,7 +514,7 @@ void nfs_inode_return_delegation_noreclaim(struct inode *inode)
 
        delegation = nfs_inode_detach_delegation(inode);
        if (delegation != NULL)
-               nfs_do_return_delegation(inode, delegation, 0);
+               nfs_do_return_delegation(inode, delegation, 1);
 }
 
 /**
index c19e16f0b2d049f972acee413a287d9f73759ba3..b2c8b31b2be77d9a1d524b230ed2b66e479ad3fe 100644 (file)
@@ -416,15 +416,14 @@ int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry)
 {
        struct nfs_inode *nfsi;
 
-       if (dentry->d_inode == NULL)
-               goto different;
+       if (d_really_is_negative(dentry))
+               return 0;
 
-       nfsi = NFS_I(dentry->d_inode);
+       nfsi = NFS_I(d_inode(dentry));
        if (entry->fattr->fileid == nfsi->fileid)
                return 1;
        if (nfs_compare_fh(entry->fh, &nfsi->fh) == 0)
                return 1;
-different:
        return 0;
 }
 
@@ -473,7 +472,7 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry)
        struct qstr filename = QSTR_INIT(entry->name, entry->len);
        struct dentry *dentry;
        struct dentry *alias;
-       struct inode *dir = parent->d_inode;
+       struct inode *dir = d_inode(parent);
        struct inode *inode;
        int status;
 
@@ -497,9 +496,9 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry)
                        goto out;
                if (nfs_same_file(dentry, entry)) {
                        nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
-                       status = nfs_refresh_inode(dentry->d_inode, entry->fattr);
+                       status = nfs_refresh_inode(d_inode(dentry), entry->fattr);
                        if (!status)
-                               nfs_setsecurity(dentry->d_inode, entry->fattr, entry->label);
+                               nfs_setsecurity(d_inode(dentry), entry->fattr, entry->label);
                        goto out;
                } else {
                        d_invalidate(dentry);
@@ -544,6 +543,9 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
        if (scratch == NULL)
                return -ENOMEM;
 
+       if (buflen == 0)
+               goto out_nopages;
+
        xdr_init_decode_pages(&stream, &buf, xdr_pages, buflen);
        xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE);
 
@@ -565,6 +567,7 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
                        break;
        } while (!entry->eof);
 
+out_nopages:
        if (count == 0 || (status == -EBADCOOKIE && entry->eof != 0)) {
                array = nfs_readdir_get_array(page);
                if (!IS_ERR(array)) {
@@ -870,7 +873,7 @@ static bool nfs_dir_mapping_need_revalidate(struct inode *dir)
 static int nfs_readdir(struct file *file, struct dir_context *ctx)
 {
        struct dentry   *dentry = file->f_path.dentry;
-       struct inode    *inode = dentry->d_inode;
+       struct inode    *inode = d_inode(dentry);
        nfs_readdir_descriptor_t my_desc,
                        *desc = &my_desc;
        struct nfs_open_dir_context *dir_ctx = file->private_data;
@@ -1118,15 +1121,15 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
 
        if (flags & LOOKUP_RCU) {
                parent = ACCESS_ONCE(dentry->d_parent);
-               dir = ACCESS_ONCE(parent->d_inode);
+               dir = d_inode_rcu(parent);
                if (!dir)
                        return -ECHILD;
        } else {
                parent = dget_parent(dentry);
-               dir = parent->d_inode;
+               dir = d_inode(parent);
        }
        nfs_inc_stats(dir, NFSIOS_DENTRYREVALIDATE);
-       inode = dentry->d_inode;
+       inode = d_inode(dentry);
 
        if (!inode) {
                if (nfs_neg_need_reval(dir, dentry, flags)) {
@@ -1242,7 +1245,7 @@ out_error:
 }
 
 /*
- * A weaker form of d_revalidate for revalidating just the dentry->d_inode
+ * A weaker form of d_revalidate for revalidating just the d_inode(dentry)
  * when we don't really care about the dentry name. This is called when a
  * pathwalk ends on a dentry that was not found via a normal lookup in the
  * parent dir (e.g.: ".", "..", procfs symlinks or mountpoint traversals).
@@ -1253,7 +1256,7 @@ out_error:
 static int nfs_weak_revalidate(struct dentry *dentry, unsigned int flags)
 {
        int error;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
 
        /*
         * I believe we can only get a negative dentry here in the case of a
@@ -1287,7 +1290,7 @@ static int nfs_dentry_delete(const struct dentry *dentry)
                dentry, dentry->d_flags);
 
        /* Unhash any dentry with a stale inode */
-       if (dentry->d_inode != NULL && NFS_STALE(dentry->d_inode))
+       if (d_really_is_positive(dentry) && NFS_STALE(d_inode(dentry)))
                return 1;
 
        if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
@@ -1491,7 +1494,7 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
        int err;
 
        /* Expect a negative dentry */
-       BUG_ON(dentry->d_inode);
+       BUG_ON(d_inode(dentry));
 
        dfprintk(VFS, "NFS: atomic_open(%s/%lu), %pd\n",
                        dir->i_sb->s_id, dir->i_ino, dentry);
@@ -1587,7 +1590,7 @@ static int nfs4_lookup_revalidate(struct dentry *dentry, unsigned int flags)
        if (NFS_SB(dentry->d_sb)->caps & NFS_CAP_ATOMIC_OPEN_V1)
                goto no_open;
 
-       inode = dentry->d_inode;
+       inode = d_inode(dentry);
 
        /* We can't create new files in nfs_open_revalidate(), so we
         * optimize away revalidation of negative dentries.
@@ -1598,12 +1601,12 @@ static int nfs4_lookup_revalidate(struct dentry *dentry, unsigned int flags)
 
                if (flags & LOOKUP_RCU) {
                        parent = ACCESS_ONCE(dentry->d_parent);
-                       dir = ACCESS_ONCE(parent->d_inode);
+                       dir = d_inode_rcu(parent);
                        if (!dir)
                                return -ECHILD;
                } else {
                        parent = dget_parent(dentry);
-                       dir = parent->d_inode;
+                       dir = d_inode(parent);
                }
                if (!nfs_neg_need_reval(dir, dentry, flags))
                        ret = 1;
@@ -1643,14 +1646,14 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
                                struct nfs4_label *label)
 {
        struct dentry *parent = dget_parent(dentry);
-       struct inode *dir = parent->d_inode;
+       struct inode *dir = d_inode(parent);
        struct inode *inode;
        int error = -EACCES;
 
        d_drop(dentry);
 
        /* We may have been initialized further down */
-       if (dentry->d_inode)
+       if (d_really_is_positive(dentry))
                goto out;
        if (fhandle->size == 0) {
                error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, NULL);
@@ -1768,7 +1771,7 @@ EXPORT_SYMBOL_GPL(nfs_mkdir);
 
 static void nfs_dentry_handle_enoent(struct dentry *dentry)
 {
-       if (dentry->d_inode != NULL && !d_unhashed(dentry))
+       if (d_really_is_positive(dentry) && !d_unhashed(dentry))
                d_delete(dentry);
 }
 
@@ -1780,13 +1783,13 @@ int nfs_rmdir(struct inode *dir, struct dentry *dentry)
                        dir->i_sb->s_id, dir->i_ino, dentry);
 
        trace_nfs_rmdir_enter(dir, dentry);
-       if (dentry->d_inode) {
+       if (d_really_is_positive(dentry)) {
                nfs_wait_on_sillyrename(dentry);
                error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name);
                /* Ensure the VFS deletes this inode */
                switch (error) {
                case 0:
-                       clear_nlink(dentry->d_inode);
+                       clear_nlink(d_inode(dentry));
                        break;
                case -ENOENT:
                        nfs_dentry_handle_enoent(dentry);
@@ -1808,8 +1811,8 @@ EXPORT_SYMBOL_GPL(nfs_rmdir);
  */
 static int nfs_safe_remove(struct dentry *dentry)
 {
-       struct inode *dir = dentry->d_parent->d_inode;
-       struct inode *inode = dentry->d_inode;
+       struct inode *dir = d_inode(dentry->d_parent);
+       struct inode *inode = d_inode(dentry);
        int error = -EBUSY;
                
        dfprintk(VFS, "NFS: safe_remove(%pd2)\n", dentry);
@@ -1853,7 +1856,7 @@ int nfs_unlink(struct inode *dir, struct dentry *dentry)
        if (d_count(dentry) > 1) {
                spin_unlock(&dentry->d_lock);
                /* Start asynchronous writeout of the inode */
-               write_inode_now(dentry->d_inode, 0);
+               write_inode_now(d_inode(dentry), 0);
                error = nfs_sillyrename(dir, dentry);
                goto out;
        }
@@ -1931,7 +1934,7 @@ int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
         * No big deal if we can't add this page to the page cache here.
         * READLINK will get the missing page from the server if needed.
         */
-       if (!add_to_page_cache_lru(page, dentry->d_inode->i_mapping, 0,
+       if (!add_to_page_cache_lru(page, d_inode(dentry)->i_mapping, 0,
                                                        GFP_KERNEL)) {
                SetPageUptodate(page);
                unlock_page(page);
@@ -1950,7 +1953,7 @@ EXPORT_SYMBOL_GPL(nfs_symlink);
 int
 nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
 {
-       struct inode *inode = old_dentry->d_inode;
+       struct inode *inode = d_inode(old_dentry);
        int error;
 
        dfprintk(VFS, "NFS: link(%pd2 -> %pd2)\n",
@@ -1997,8 +2000,8 @@ EXPORT_SYMBOL_GPL(nfs_link);
 int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                      struct inode *new_dir, struct dentry *new_dentry)
 {
-       struct inode *old_inode = old_dentry->d_inode;
-       struct inode *new_inode = new_dentry->d_inode;
+       struct inode *old_inode = d_inode(old_dentry);
+       struct inode *new_inode = d_inode(new_dentry);
        struct dentry *dentry = NULL, *rehash = NULL;
        struct rpc_task *task;
        int error = -EBUSY;
index 682f65fe09b5177dcd64bcd2970bbfcef9824ac3..38678d9a5cc4a64838e70ff3c915107b828bb65d 100644 (file)
@@ -129,22 +129,25 @@ nfs_direct_good_bytes(struct nfs_direct_req *dreq, struct nfs_pgio_header *hdr)
        int i;
        ssize_t count;
 
-       WARN_ON_ONCE(hdr->pgio_mirror_idx >= dreq->mirror_count);
-
-       count = dreq->mirrors[hdr->pgio_mirror_idx].count;
-       if (count + dreq->io_start < hdr->io_start + hdr->good_bytes) {
-               count = hdr->io_start + hdr->good_bytes - dreq->io_start;
-               dreq->mirrors[hdr->pgio_mirror_idx].count = count;
-       }
-
-       /* update the dreq->count by finding the minimum agreed count from all
-        * mirrors */
-       count = dreq->mirrors[0].count;
+       if (dreq->mirror_count == 1) {
+               dreq->mirrors[hdr->pgio_mirror_idx].count += hdr->good_bytes;
+               dreq->count += hdr->good_bytes;
+       } else {
+               /* mirrored writes */
+               count = dreq->mirrors[hdr->pgio_mirror_idx].count;
+               if (count + dreq->io_start < hdr->io_start + hdr->good_bytes) {
+                       count = hdr->io_start + hdr->good_bytes - dreq->io_start;
+                       dreq->mirrors[hdr->pgio_mirror_idx].count = count;
+               }
+               /* update the dreq->count by finding the minimum agreed count from all
+                * mirrors */
+               count = dreq->mirrors[0].count;
 
-       for (i = 1; i < dreq->mirror_count; i++)
-               count = min(count, dreq->mirrors[i].count);
+               for (i = 1; i < dreq->mirror_count; i++)
+                       count = min(count, dreq->mirrors[i].count);
 
-       dreq->count = count;
+               dreq->count = count;
+       }
 }
 
 /*
@@ -258,18 +261,11 @@ ssize_t nfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter, loff_t pos)
        if (!IS_SWAPFILE(inode))
                return 0;
 
-#ifndef CONFIG_NFS_SWAP
-       dprintk("NFS: nfs_direct_IO (%pD) off/no(%Ld/%lu) EINVAL\n",
-                       iocb->ki_filp, (long long) pos, iter->nr_segs);
-
-       return -EINVAL;
-#else
        VM_BUG_ON(iov_iter_count(iter) != PAGE_SIZE);
 
        if (iov_iter_rw(iter) == READ)
                return nfs_file_direct_read(iocb, iter, pos);
        return nfs_file_direct_write(iocb, iter);
-#endif /* CONFIG_NFS_SWAP */
 }
 
 static void nfs_direct_release_pages(struct page **pages, unsigned int npages)
@@ -386,7 +382,7 @@ static void nfs_direct_complete(struct nfs_direct_req *dreq, bool write)
        if (write)
                nfs_zap_mapping(inode, inode->i_mapping);
 
-       inode_dio_done(inode);
+       inode_dio_end(inode);
 
        if (dreq->iocb) {
                long res = (long) dreq->error;
@@ -403,8 +399,8 @@ static void nfs_direct_complete(struct nfs_direct_req *dreq, bool write)
 static void nfs_direct_readpage_release(struct nfs_page *req)
 {
        dprintk("NFS: direct read done (%s/%llu %d@%lld)\n",
-               req->wb_context->dentry->d_inode->i_sb->s_id,
-               (unsigned long long)NFS_FILEID(req->wb_context->dentry->d_inode),
+               d_inode(req->wb_context->dentry)->i_sb->s_id,
+               (unsigned long long)NFS_FILEID(d_inode(req->wb_context->dentry)),
                req->wb_bytes,
                (long long)req_offset(req));
        nfs_release_request(req);
@@ -486,7 +482,7 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq,
                             &nfs_direct_read_completion_ops);
        get_dreq(dreq);
        desc.pg_dreq = dreq;
-       atomic_inc(&inode->i_dio_count);
+       inode_dio_begin(inode);
 
        while (iov_iter_count(iter)) {
                struct page **pagevec;
@@ -538,7 +534,7 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq,
         * generic layer handle the completion.
         */
        if (requested_bytes == 0) {
-               inode_dio_done(inode);
+               inode_dio_end(inode);
                nfs_direct_req_release(dreq);
                return result < 0 ? result : -EIO;
        }
@@ -872,7 +868,7 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
                              &nfs_direct_write_completion_ops);
        desc.pg_dreq = dreq;
        get_dreq(dreq);
-       atomic_inc(&inode->i_dio_count);
+       inode_dio_begin(inode);
 
        NFS_I(inode)->write_io += iov_iter_count(iter);
        while (iov_iter_count(iter)) {
@@ -928,7 +924,7 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
         * generic layer handle the completion.
         */
        if (requested_bytes == 0) {
-               inode_dio_done(inode);
+               inode_dio_end(inode);
                nfs_direct_req_release(dreq);
                return result < 0 ? result : -EIO;
        }
@@ -1030,6 +1026,7 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter)
                        if (i_size_read(inode) < iocb->ki_pos)
                                i_size_write(inode, iocb->ki_pos);
                        spin_unlock(&inode->i_lock);
+                       generic_write_sync(file, pos, result);
                }
        }
        nfs_direct_req_release(dreq);
index c40e4363e746eab4014991f326005aa27721b460..8b8d83a526ce2366ae974a87761c9c62c22da7f5 100644 (file)
@@ -280,6 +280,7 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 
        trace_nfs_fsync_enter(inode);
 
+       nfs_inode_dio_wait(inode);
        do {
                ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
                if (ret != 0)
@@ -782,7 +783,7 @@ do_unlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
         * Flush all pending writes before doing anything
         * with locks..
         */
-       nfs_sync_mapping(filp->f_mapping);
+       vfs_fsync(filp, 0);
 
        l_ctx = nfs_get_lock_context(nfs_file_open_context(filp));
        if (!IS_ERR(l_ctx)) {
index 91e88a7ecef0c64354b0278fc01381e0970d2086..a46bf6de9ce455a97ef18275efe4906ac10e12ed 100644 (file)
@@ -258,7 +258,8 @@ filelayout_set_layoutcommit(struct nfs_pgio_header *hdr)
            hdr->res.verf->committed != NFS_DATA_SYNC)
                return;
 
-       pnfs_set_layoutcommit(hdr);
+       pnfs_set_layoutcommit(hdr->inode, hdr->lseg,
+                       hdr->mds_offset + hdr->res.count);
        dprintk("%s inode %lu pls_end_pos %lu\n", __func__, hdr->inode->i_ino,
                (unsigned long) NFS_I(hdr->inode)->layout->plh_lwb);
 }
@@ -373,7 +374,7 @@ static int filelayout_commit_done_cb(struct rpc_task *task,
        }
 
        if (data->verf.committed == NFS_UNSTABLE)
-               pnfs_commit_set_layoutcommit(data);
+               pnfs_set_layoutcommit(data->inode, data->lseg, data->lwb);
 
        return 0;
 }
@@ -1086,7 +1087,7 @@ filelayout_alloc_deviceid_node(struct nfs_server *server,
 }
 
 static void
-filelayout_free_deveiceid_node(struct nfs4_deviceid_node *d)
+filelayout_free_deviceid_node(struct nfs4_deviceid_node *d)
 {
        nfs4_fl_free_deviceid(container_of(d, struct nfs4_file_layout_dsaddr, id_node));
 }
@@ -1137,7 +1138,8 @@ static struct pnfs_layoutdriver_type filelayout_type = {
        .read_pagelist          = filelayout_read_pagelist,
        .write_pagelist         = filelayout_write_pagelist,
        .alloc_deviceid_node    = filelayout_alloc_deviceid_node,
-       .free_deviceid_node     = filelayout_free_deveiceid_node,
+       .free_deviceid_node     = filelayout_free_deviceid_node,
+       .sync                   = pnfs_nfs_generic_sync,
 };
 
 static int __init nfs4filelayout_init(void)
index 4f372e2246034415583485aa680bd43a0a83a04f..4946ef40ba875e6255857ca3c27b6df352c7a46a 100644 (file)
@@ -55,7 +55,7 @@ nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr)
                        nfs4_pnfs_ds_put(ds);
        }
        kfree(dsaddr->stripe_indices);
-       kfree(dsaddr);
+       kfree_rcu(dsaddr, id_node.rcu);
 }
 
 /* Decode opaque device data and return the result */
index 315cc68945b9d1d3ad00b04e2597e38d7b7c4cab..7d05089e52d6c8b7a29e92e80011bdee0e06a32c 100644 (file)
 #include <linux/module.h>
 
 #include <linux/sunrpc/metrics.h>
-#include <linux/nfs_idmap.h>
 
 #include "flexfilelayout.h"
 #include "../nfs4session.h"
+#include "../nfs4idmap.h"
 #include "../internal.h"
 #include "../delegation.h"
 #include "../nfs4trace.h"
@@ -891,7 +891,8 @@ static int ff_layout_read_done_cb(struct rpc_task *task,
 static void
 ff_layout_set_layoutcommit(struct nfs_pgio_header *hdr)
 {
-       pnfs_set_layoutcommit(hdr);
+       pnfs_set_layoutcommit(hdr->inode, hdr->lseg,
+                       hdr->mds_offset + hdr->res.count);
        dprintk("%s inode %lu pls_end_pos %lu\n", __func__, hdr->inode->i_ino,
                (unsigned long) NFS_I(hdr->inode)->layout->plh_lwb);
 }
@@ -1074,7 +1075,7 @@ static int ff_layout_commit_done_cb(struct rpc_task *task,
        }
 
        if (data->verf.committed == NFS_UNSTABLE)
-               pnfs_commit_set_layoutcommit(data);
+               pnfs_set_layoutcommit(data->inode, data->lseg, data->lwb);
 
        return 0;
 }
@@ -1414,7 +1415,7 @@ ff_layout_get_ds_info(struct inode *inode)
 }
 
 static void
-ff_layout_free_deveiceid_node(struct nfs4_deviceid_node *d)
+ff_layout_free_deviceid_node(struct nfs4_deviceid_node *d)
 {
        nfs4_ff_layout_free_deviceid(container_of(d, struct nfs4_ff_layout_ds,
                                                  id_node));
@@ -1498,7 +1499,7 @@ static struct pnfs_layoutdriver_type flexfilelayout_type = {
        .pg_read_ops            = &ff_layout_pg_read_ops,
        .pg_write_ops           = &ff_layout_pg_write_ops,
        .get_ds_info            = ff_layout_get_ds_info,
-       .free_deviceid_node     = ff_layout_free_deveiceid_node,
+       .free_deviceid_node     = ff_layout_free_deviceid_node,
        .mark_request_commit    = pnfs_layout_mark_request_commit,
        .clear_request_commit   = pnfs_generic_clear_request_commit,
        .scan_commit_lists      = pnfs_generic_scan_commit_lists,
@@ -1508,6 +1509,7 @@ static struct pnfs_layoutdriver_type flexfilelayout_type = {
        .write_pagelist         = ff_layout_write_pagelist,
        .alloc_deviceid_node    = ff_layout_alloc_deviceid_node,
        .encode_layoutreturn    = ff_layout_encode_layoutreturn,
+       .sync                   = pnfs_nfs_generic_sync,
 };
 
 static int __init nfs4flexfilelayout_init(void)
index e2c01f204a956b584725d1d187d1ea1fc22d6ab0..77a2d026aa12b62bdc29dac2345cff0b3237e9c4 100644 (file)
@@ -30,7 +30,7 @@ void nfs4_ff_layout_free_deviceid(struct nfs4_ff_layout_ds *mirror_ds)
 {
        nfs4_print_deviceid(&mirror_ds->id_node.deviceid);
        nfs4_pnfs_ds_put(mirror_ds->ds);
-       kfree(mirror_ds);
+       kfree_rcu(mirror_ds, id_node.rcu);
 }
 
 /* Decode opaque device data and construct new_ds using it */
index 9ac3846cb59e4d90d9979e46f198b8bd23f0e1c5..a608ffd28accd68a9c0db14bb02da23a5067db78 100644 (file)
@@ -56,11 +56,11 @@ static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *i
                 * This again causes shrink_dcache_for_umount_subtree() to
                 * Oops, since the test for IS_ROOT() will fail.
                 */
-               spin_lock(&sb->s_root->d_inode->i_lock);
+               spin_lock(&d_inode(sb->s_root)->i_lock);
                spin_lock(&sb->s_root->d_lock);
                hlist_del_init(&sb->s_root->d_u.d_alias);
                spin_unlock(&sb->s_root->d_lock);
-               spin_unlock(&sb->s_root->d_inode->i_lock);
+               spin_unlock(&d_inode(sb->s_root)->i_lock);
        }
        return 0;
 }
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c
deleted file mode 100644 (file)
index 857e2a9..0000000
+++ /dev/null
@@ -1,792 +0,0 @@
-/*
- * fs/nfs/idmap.c
- *
- *  UID and GID to name mapping for clients.
- *
- *  Copyright (c) 2002 The Regents of the University of Michigan.
- *  All rights reserved.
- *
- *  Marius Aamodt Eriksen <marius@umich.edu>
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions
- *  are met:
- *
- *  1. Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *  2. Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *  3. Neither the name of the University nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <linux/types.h>
-#include <linux/parser.h>
-#include <linux/fs.h>
-#include <linux/nfs_idmap.h>
-#include <net/net_namespace.h>
-#include <linux/sunrpc/rpc_pipe_fs.h>
-#include <linux/nfs_fs.h>
-#include <linux/nfs_fs_sb.h>
-#include <linux/key.h>
-#include <linux/keyctl.h>
-#include <linux/key-type.h>
-#include <keys/user-type.h>
-#include <linux/module.h>
-
-#include "internal.h"
-#include "netns.h"
-#include "nfs4trace.h"
-
-#define NFS_UINT_MAXLEN 11
-
-static const struct cred *id_resolver_cache;
-static struct key_type key_type_id_resolver_legacy;
-
-struct idmap_legacy_upcalldata {
-       struct rpc_pipe_msg pipe_msg;
-       struct idmap_msg idmap_msg;
-       struct key_construction *key_cons;
-       struct idmap *idmap;
-};
-
-struct idmap {
-       struct rpc_pipe_dir_object idmap_pdo;
-       struct rpc_pipe         *idmap_pipe;
-       struct idmap_legacy_upcalldata *idmap_upcall_data;
-       struct mutex            idmap_mutex;
-};
-
-/**
- * nfs_fattr_init_names - initialise the nfs_fattr owner_name/group_name fields
- * @fattr: fully initialised struct nfs_fattr
- * @owner_name: owner name string cache
- * @group_name: group name string cache
- */
-void nfs_fattr_init_names(struct nfs_fattr *fattr,
-               struct nfs4_string *owner_name,
-               struct nfs4_string *group_name)
-{
-       fattr->owner_name = owner_name;
-       fattr->group_name = group_name;
-}
-
-static void nfs_fattr_free_owner_name(struct nfs_fattr *fattr)
-{
-       fattr->valid &= ~NFS_ATTR_FATTR_OWNER_NAME;
-       kfree(fattr->owner_name->data);
-}
-
-static void nfs_fattr_free_group_name(struct nfs_fattr *fattr)
-{
-       fattr->valid &= ~NFS_ATTR_FATTR_GROUP_NAME;
-       kfree(fattr->group_name->data);
-}
-
-static bool nfs_fattr_map_owner_name(struct nfs_server *server, struct nfs_fattr *fattr)
-{
-       struct nfs4_string *owner = fattr->owner_name;
-       kuid_t uid;
-
-       if (!(fattr->valid & NFS_ATTR_FATTR_OWNER_NAME))
-               return false;
-       if (nfs_map_name_to_uid(server, owner->data, owner->len, &uid) == 0) {
-               fattr->uid = uid;
-               fattr->valid |= NFS_ATTR_FATTR_OWNER;
-       }
-       return true;
-}
-
-static bool nfs_fattr_map_group_name(struct nfs_server *server, struct nfs_fattr *fattr)
-{
-       struct nfs4_string *group = fattr->group_name;
-       kgid_t gid;
-
-       if (!(fattr->valid & NFS_ATTR_FATTR_GROUP_NAME))
-               return false;
-       if (nfs_map_group_to_gid(server, group->data, group->len, &gid) == 0) {
-               fattr->gid = gid;
-               fattr->valid |= NFS_ATTR_FATTR_GROUP;
-       }
-       return true;
-}
-
-/**
- * nfs_fattr_free_names - free up the NFSv4 owner and group strings
- * @fattr: a fully initialised nfs_fattr structure
- */
-void nfs_fattr_free_names(struct nfs_fattr *fattr)
-{
-       if (fattr->valid & NFS_ATTR_FATTR_OWNER_NAME)
-               nfs_fattr_free_owner_name(fattr);
-       if (fattr->valid & NFS_ATTR_FATTR_GROUP_NAME)
-               nfs_fattr_free_group_name(fattr);
-}
-
-/**
- * nfs_fattr_map_and_free_names - map owner/group strings into uid/gid and free
- * @server: pointer to the filesystem nfs_server structure
- * @fattr: a fully initialised nfs_fattr structure
- *
- * This helper maps the cached NFSv4 owner/group strings in fattr into
- * their numeric uid/gid equivalents, and then frees the cached strings.
- */
-void nfs_fattr_map_and_free_names(struct nfs_server *server, struct nfs_fattr *fattr)
-{
-       if (nfs_fattr_map_owner_name(server, fattr))
-               nfs_fattr_free_owner_name(fattr);
-       if (nfs_fattr_map_group_name(server, fattr))
-               nfs_fattr_free_group_name(fattr);
-}
-
-int nfs_map_string_to_numeric(const char *name, size_t namelen, __u32 *res)
-{
-       unsigned long val;
-       char buf[16];
-
-       if (memchr(name, '@', namelen) != NULL || namelen >= sizeof(buf))
-               return 0;
-       memcpy(buf, name, namelen);
-       buf[namelen] = '\0';
-       if (kstrtoul(buf, 0, &val) != 0)
-               return 0;
-       *res = val;
-       return 1;
-}
-EXPORT_SYMBOL_GPL(nfs_map_string_to_numeric);
-
-static int nfs_map_numeric_to_string(__u32 id, char *buf, size_t buflen)
-{
-       return snprintf(buf, buflen, "%u", id);
-}
-
-static struct key_type key_type_id_resolver = {
-       .name           = "id_resolver",
-       .preparse       = user_preparse,
-       .free_preparse  = user_free_preparse,
-       .instantiate    = generic_key_instantiate,
-       .revoke         = user_revoke,
-       .destroy        = user_destroy,
-       .describe       = user_describe,
-       .read           = user_read,
-};
-
-static int nfs_idmap_init_keyring(void)
-{
-       struct cred *cred;
-       struct key *keyring;
-       int ret = 0;
-
-       printk(KERN_NOTICE "NFS: Registering the %s key type\n",
-               key_type_id_resolver.name);
-
-       cred = prepare_kernel_cred(NULL);
-       if (!cred)
-               return -ENOMEM;
-
-       keyring = keyring_alloc(".id_resolver",
-                               GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
-                               (KEY_POS_ALL & ~KEY_POS_SETATTR) |
-                               KEY_USR_VIEW | KEY_USR_READ,
-                               KEY_ALLOC_NOT_IN_QUOTA, NULL);
-       if (IS_ERR(keyring)) {
-               ret = PTR_ERR(keyring);
-               goto failed_put_cred;
-       }
-
-       ret = register_key_type(&key_type_id_resolver);
-       if (ret < 0)
-               goto failed_put_key;
-
-       ret = register_key_type(&key_type_id_resolver_legacy);
-       if (ret < 0)
-               goto failed_reg_legacy;
-
-       set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
-       cred->thread_keyring = keyring;
-       cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
-       id_resolver_cache = cred;
-       return 0;
-
-failed_reg_legacy:
-       unregister_key_type(&key_type_id_resolver);
-failed_put_key:
-       key_put(keyring);
-failed_put_cred:
-       put_cred(cred);
-       return ret;
-}
-
-static void nfs_idmap_quit_keyring(void)
-{
-       key_revoke(id_resolver_cache->thread_keyring);
-       unregister_key_type(&key_type_id_resolver);
-       unregister_key_type(&key_type_id_resolver_legacy);
-       put_cred(id_resolver_cache);
-}
-
-/*
- * Assemble the description to pass to request_key()
- * This function will allocate a new string and update dest to point
- * at it.  The caller is responsible for freeing dest.
- *
- * On error 0 is returned.  Otherwise, the length of dest is returned.
- */
-static ssize_t nfs_idmap_get_desc(const char *name, size_t namelen,
-                               const char *type, size_t typelen, char **desc)
-{
-       char *cp;
-       size_t desclen = typelen + namelen + 2;
-
-       *desc = kmalloc(desclen, GFP_KERNEL);
-       if (!*desc)
-               return -ENOMEM;
-
-       cp = *desc;
-       memcpy(cp, type, typelen);
-       cp += typelen;
-       *cp++ = ':';
-
-       memcpy(cp, name, namelen);
-       cp += namelen;
-       *cp = '\0';
-       return desclen;
-}
-
-static struct key *nfs_idmap_request_key(const char *name, size_t namelen,
-                                        const char *type, struct idmap *idmap)
-{
-       char *desc;
-       struct key *rkey;
-       ssize_t ret;
-
-       ret = nfs_idmap_get_desc(name, namelen, type, strlen(type), &desc);
-       if (ret <= 0)
-               return ERR_PTR(ret);
-
-       rkey = request_key(&key_type_id_resolver, desc, "");
-       if (IS_ERR(rkey)) {
-               mutex_lock(&idmap->idmap_mutex);
-               rkey = request_key_with_auxdata(&key_type_id_resolver_legacy,
-                                               desc, "", 0, idmap);
-               mutex_unlock(&idmap->idmap_mutex);
-       }
-       if (!IS_ERR(rkey))
-               set_bit(KEY_FLAG_ROOT_CAN_INVAL, &rkey->flags);
-
-       kfree(desc);
-       return rkey;
-}
-
-static ssize_t nfs_idmap_get_key(const char *name, size_t namelen,
-                                const char *type, void *data,
-                                size_t data_size, struct idmap *idmap)
-{
-       const struct cred *saved_cred;
-       struct key *rkey;
-       struct user_key_payload *payload;
-       ssize_t ret;
-
-       saved_cred = override_creds(id_resolver_cache);
-       rkey = nfs_idmap_request_key(name, namelen, type, idmap);
-       revert_creds(saved_cred);
-
-       if (IS_ERR(rkey)) {
-               ret = PTR_ERR(rkey);
-               goto out;
-       }
-
-       rcu_read_lock();
-       rkey->perm |= KEY_USR_VIEW;
-
-       ret = key_validate(rkey);
-       if (ret < 0)
-               goto out_up;
-
-       payload = rcu_dereference(rkey->payload.rcudata);
-       if (IS_ERR_OR_NULL(payload)) {
-               ret = PTR_ERR(payload);
-               goto out_up;
-       }
-
-       ret = payload->datalen;
-       if (ret > 0 && ret <= data_size)
-               memcpy(data, payload->data, ret);
-       else
-               ret = -EINVAL;
-
-out_up:
-       rcu_read_unlock();
-       key_put(rkey);
-out:
-       return ret;
-}
-
-/* ID -> Name */
-static ssize_t nfs_idmap_lookup_name(__u32 id, const char *type, char *buf,
-                                    size_t buflen, struct idmap *idmap)
-{
-       char id_str[NFS_UINT_MAXLEN];
-       int id_len;
-       ssize_t ret;
-
-       id_len = snprintf(id_str, sizeof(id_str), "%u", id);
-       ret = nfs_idmap_get_key(id_str, id_len, type, buf, buflen, idmap);
-       if (ret < 0)
-               return -EINVAL;
-       return ret;
-}
-
-/* Name -> ID */
-static int nfs_idmap_lookup_id(const char *name, size_t namelen, const char *type,
-                              __u32 *id, struct idmap *idmap)
-{
-       char id_str[NFS_UINT_MAXLEN];
-       long id_long;
-       ssize_t data_size;
-       int ret = 0;
-
-       data_size = nfs_idmap_get_key(name, namelen, type, id_str, NFS_UINT_MAXLEN, idmap);
-       if (data_size <= 0) {
-               ret = -EINVAL;
-       } else {
-               ret = kstrtol(id_str, 10, &id_long);
-               *id = (__u32)id_long;
-       }
-       return ret;
-}
-
-/* idmap classic begins here */
-
-enum {
-       Opt_find_uid, Opt_find_gid, Opt_find_user, Opt_find_group, Opt_find_err
-};
-
-static const match_table_t nfs_idmap_tokens = {
-       { Opt_find_uid, "uid:%s" },
-       { Opt_find_gid, "gid:%s" },
-       { Opt_find_user, "user:%s" },
-       { Opt_find_group, "group:%s" },
-       { Opt_find_err, NULL }
-};
-
-static int nfs_idmap_legacy_upcall(struct key_construction *, const char *, void *);
-static ssize_t idmap_pipe_downcall(struct file *, const char __user *,
-                                  size_t);
-static void idmap_release_pipe(struct inode *);
-static void idmap_pipe_destroy_msg(struct rpc_pipe_msg *);
-
-static const struct rpc_pipe_ops idmap_upcall_ops = {
-       .upcall         = rpc_pipe_generic_upcall,
-       .downcall       = idmap_pipe_downcall,
-       .release_pipe   = idmap_release_pipe,
-       .destroy_msg    = idmap_pipe_destroy_msg,
-};
-
-static struct key_type key_type_id_resolver_legacy = {
-       .name           = "id_legacy",
-       .preparse       = user_preparse,
-       .free_preparse  = user_free_preparse,
-       .instantiate    = generic_key_instantiate,
-       .revoke         = user_revoke,
-       .destroy        = user_destroy,
-       .describe       = user_describe,
-       .read           = user_read,
-       .request_key    = nfs_idmap_legacy_upcall,
-};
-
-static void nfs_idmap_pipe_destroy(struct dentry *dir,
-               struct rpc_pipe_dir_object *pdo)
-{
-       struct idmap *idmap = pdo->pdo_data;
-       struct rpc_pipe *pipe = idmap->idmap_pipe;
-
-       if (pipe->dentry) {
-               rpc_unlink(pipe->dentry);
-               pipe->dentry = NULL;
-       }
-}
-
-static int nfs_idmap_pipe_create(struct dentry *dir,
-               struct rpc_pipe_dir_object *pdo)
-{
-       struct idmap *idmap = pdo->pdo_data;
-       struct rpc_pipe *pipe = idmap->idmap_pipe;
-       struct dentry *dentry;
-
-       dentry = rpc_mkpipe_dentry(dir, "idmap", idmap, pipe);
-       if (IS_ERR(dentry))
-               return PTR_ERR(dentry);
-       pipe->dentry = dentry;
-       return 0;
-}
-
-static const struct rpc_pipe_dir_object_ops nfs_idmap_pipe_dir_object_ops = {
-       .create = nfs_idmap_pipe_create,
-       .destroy = nfs_idmap_pipe_destroy,
-};
-
-int
-nfs_idmap_new(struct nfs_client *clp)
-{
-       struct idmap *idmap;
-       struct rpc_pipe *pipe;
-       int error;
-
-       idmap = kzalloc(sizeof(*idmap), GFP_KERNEL);
-       if (idmap == NULL)
-               return -ENOMEM;
-
-       rpc_init_pipe_dir_object(&idmap->idmap_pdo,
-                       &nfs_idmap_pipe_dir_object_ops,
-                       idmap);
-
-       pipe = rpc_mkpipe_data(&idmap_upcall_ops, 0);
-       if (IS_ERR(pipe)) {
-               error = PTR_ERR(pipe);
-               goto err;
-       }
-       idmap->idmap_pipe = pipe;
-       mutex_init(&idmap->idmap_mutex);
-
-       error = rpc_add_pipe_dir_object(clp->cl_net,
-                       &clp->cl_rpcclient->cl_pipedir_objects,
-                       &idmap->idmap_pdo);
-       if (error)
-               goto err_destroy_pipe;
-
-       clp->cl_idmap = idmap;
-       return 0;
-err_destroy_pipe:
-       rpc_destroy_pipe_data(idmap->idmap_pipe);
-err:
-       kfree(idmap);
-       return error;
-}
-
-void
-nfs_idmap_delete(struct nfs_client *clp)
-{
-       struct idmap *idmap = clp->cl_idmap;
-
-       if (!idmap)
-               return;
-       clp->cl_idmap = NULL;
-       rpc_remove_pipe_dir_object(clp->cl_net,
-                       &clp->cl_rpcclient->cl_pipedir_objects,
-                       &idmap->idmap_pdo);
-       rpc_destroy_pipe_data(idmap->idmap_pipe);
-       kfree(idmap);
-}
-
-int nfs_idmap_init(void)
-{
-       int ret;
-       ret = nfs_idmap_init_keyring();
-       if (ret != 0)
-               goto out;
-out:
-       return ret;
-}
-
-void nfs_idmap_quit(void)
-{
-       nfs_idmap_quit_keyring();
-}
-
-static int nfs_idmap_prepare_message(char *desc, struct idmap *idmap,
-                                    struct idmap_msg *im,
-                                    struct rpc_pipe_msg *msg)
-{
-       substring_t substr;
-       int token, ret;
-
-       im->im_type = IDMAP_TYPE_GROUP;
-       token = match_token(desc, nfs_idmap_tokens, &substr);
-
-       switch (token) {
-       case Opt_find_uid:
-               im->im_type = IDMAP_TYPE_USER;
-       case Opt_find_gid:
-               im->im_conv = IDMAP_CONV_NAMETOID;
-               ret = match_strlcpy(im->im_name, &substr, IDMAP_NAMESZ);
-               break;
-
-       case Opt_find_user:
-               im->im_type = IDMAP_TYPE_USER;
-       case Opt_find_group:
-               im->im_conv = IDMAP_CONV_IDTONAME;
-               ret = match_int(&substr, &im->im_id);
-               break;
-
-       default:
-               ret = -EINVAL;
-               goto out;
-       }
-
-       msg->data = im;
-       msg->len  = sizeof(struct idmap_msg);
-
-out:
-       return ret;
-}
-
-static bool
-nfs_idmap_prepare_pipe_upcall(struct idmap *idmap,
-               struct idmap_legacy_upcalldata *data)
-{
-       if (idmap->idmap_upcall_data != NULL) {
-               WARN_ON_ONCE(1);
-               return false;
-       }
-       idmap->idmap_upcall_data = data;
-       return true;
-}
-
-static void
-nfs_idmap_complete_pipe_upcall_locked(struct idmap *idmap, int ret)
-{
-       struct key_construction *cons = idmap->idmap_upcall_data->key_cons;
-
-       kfree(idmap->idmap_upcall_data);
-       idmap->idmap_upcall_data = NULL;
-       complete_request_key(cons, ret);
-}
-
-static void
-nfs_idmap_abort_pipe_upcall(struct idmap *idmap, int ret)
-{
-       if (idmap->idmap_upcall_data != NULL)
-               nfs_idmap_complete_pipe_upcall_locked(idmap, ret);
-}
-
-static int nfs_idmap_legacy_upcall(struct key_construction *cons,
-                                  const char *op,
-                                  void *aux)
-{
-       struct idmap_legacy_upcalldata *data;
-       struct rpc_pipe_msg *msg;
-       struct idmap_msg *im;
-       struct idmap *idmap = (struct idmap *)aux;
-       struct key *key = cons->key;
-       int ret = -ENOMEM;
-
-       /* msg and im are freed in idmap_pipe_destroy_msg */
-       data = kzalloc(sizeof(*data), GFP_KERNEL);
-       if (!data)
-               goto out1;
-
-       msg = &data->pipe_msg;
-       im = &data->idmap_msg;
-       data->idmap = idmap;
-       data->key_cons = cons;
-
-       ret = nfs_idmap_prepare_message(key->description, idmap, im, msg);
-       if (ret < 0)
-               goto out2;
-
-       ret = -EAGAIN;
-       if (!nfs_idmap_prepare_pipe_upcall(idmap, data))
-               goto out2;
-
-       ret = rpc_queue_upcall(idmap->idmap_pipe, msg);
-       if (ret < 0)
-               nfs_idmap_abort_pipe_upcall(idmap, ret);
-
-       return ret;
-out2:
-       kfree(data);
-out1:
-       complete_request_key(cons, ret);
-       return ret;
-}
-
-static int nfs_idmap_instantiate(struct key *key, struct key *authkey, char *data, size_t datalen)
-{
-       return key_instantiate_and_link(key, data, datalen,
-                                       id_resolver_cache->thread_keyring,
-                                       authkey);
-}
-
-static int nfs_idmap_read_and_verify_message(struct idmap_msg *im,
-               struct idmap_msg *upcall,
-               struct key *key, struct key *authkey)
-{
-       char id_str[NFS_UINT_MAXLEN];
-       size_t len;
-       int ret = -ENOKEY;
-
-       /* ret = -ENOKEY */
-       if (upcall->im_type != im->im_type || upcall->im_conv != im->im_conv)
-               goto out;
-       switch (im->im_conv) {
-       case IDMAP_CONV_NAMETOID:
-               if (strcmp(upcall->im_name, im->im_name) != 0)
-                       break;
-               /* Note: here we store the NUL terminator too */
-               len = sprintf(id_str, "%d", im->im_id) + 1;
-               ret = nfs_idmap_instantiate(key, authkey, id_str, len);
-               break;
-       case IDMAP_CONV_IDTONAME:
-               if (upcall->im_id != im->im_id)
-                       break;
-               len = strlen(im->im_name);
-               ret = nfs_idmap_instantiate(key, authkey, im->im_name, len);
-               break;
-       default:
-               ret = -EINVAL;
-       }
-out:
-       return ret;
-}
-
-static ssize_t
-idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
-{
-       struct rpc_inode *rpci = RPC_I(file_inode(filp));
-       struct idmap *idmap = (struct idmap *)rpci->private;
-       struct key_construction *cons;
-       struct idmap_msg im;
-       size_t namelen_in;
-       int ret = -ENOKEY;
-
-       /* If instantiation is successful, anyone waiting for key construction
-        * will have been woken up and someone else may now have used
-        * idmap_key_cons - so after this point we may no longer touch it.
-        */
-       if (idmap->idmap_upcall_data == NULL)
-               goto out_noupcall;
-
-       cons = idmap->idmap_upcall_data->key_cons;
-
-       if (mlen != sizeof(im)) {
-               ret = -ENOSPC;
-               goto out;
-       }
-
-       if (copy_from_user(&im, src, mlen) != 0) {
-               ret = -EFAULT;
-               goto out;
-       }
-
-       if (!(im.im_status & IDMAP_STATUS_SUCCESS)) {
-               ret = -ENOKEY;
-               goto out;
-       }
-
-       namelen_in = strnlen(im.im_name, IDMAP_NAMESZ);
-       if (namelen_in == 0 || namelen_in == IDMAP_NAMESZ) {
-               ret = -EINVAL;
-               goto out;
-}
-
-       ret = nfs_idmap_read_and_verify_message(&im,
-                       &idmap->idmap_upcall_data->idmap_msg,
-                       cons->key, cons->authkey);
-       if (ret >= 0) {
-               key_set_timeout(cons->key, nfs_idmap_cache_timeout);
-               ret = mlen;
-       }
-
-out:
-       nfs_idmap_complete_pipe_upcall_locked(idmap, ret);
-out_noupcall:
-       return ret;
-}
-
-static void
-idmap_pipe_destroy_msg(struct rpc_pipe_msg *msg)
-{
-       struct idmap_legacy_upcalldata *data = container_of(msg,
-                       struct idmap_legacy_upcalldata,
-                       pipe_msg);
-       struct idmap *idmap = data->idmap;
-
-       if (msg->errno)
-               nfs_idmap_abort_pipe_upcall(idmap, msg->errno);
-}
-
-static void
-idmap_release_pipe(struct inode *inode)
-{
-       struct rpc_inode *rpci = RPC_I(inode);
-       struct idmap *idmap = (struct idmap *)rpci->private;
-
-       nfs_idmap_abort_pipe_upcall(idmap, -EPIPE);
-}
-
-int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, kuid_t *uid)
-{
-       struct idmap *idmap = server->nfs_client->cl_idmap;
-       __u32 id = -1;
-       int ret = 0;
-
-       if (!nfs_map_string_to_numeric(name, namelen, &id))
-               ret = nfs_idmap_lookup_id(name, namelen, "uid", &id, idmap);
-       if (ret == 0) {
-               *uid = make_kuid(&init_user_ns, id);
-               if (!uid_valid(*uid))
-                       ret = -ERANGE;
-       }
-       trace_nfs4_map_name_to_uid(name, namelen, id, ret);
-       return ret;
-}
-
-int nfs_map_group_to_gid(const struct nfs_server *server, const char *name, size_t namelen, kgid_t *gid)
-{
-       struct idmap *idmap = server->nfs_client->cl_idmap;
-       __u32 id = -1;
-       int ret = 0;
-
-       if (!nfs_map_string_to_numeric(name, namelen, &id))
-               ret = nfs_idmap_lookup_id(name, namelen, "gid", &id, idmap);
-       if (ret == 0) {
-               *gid = make_kgid(&init_user_ns, id);
-               if (!gid_valid(*gid))
-                       ret = -ERANGE;
-       }
-       trace_nfs4_map_group_to_gid(name, namelen, id, ret);
-       return ret;
-}
-
-int nfs_map_uid_to_name(const struct nfs_server *server, kuid_t uid, char *buf, size_t buflen)
-{
-       struct idmap *idmap = server->nfs_client->cl_idmap;
-       int ret = -EINVAL;
-       __u32 id;
-
-       id = from_kuid(&init_user_ns, uid);
-       if (!(server->caps & NFS_CAP_UIDGID_NOMAP))
-               ret = nfs_idmap_lookup_name(id, "user", buf, buflen, idmap);
-       if (ret < 0)
-               ret = nfs_map_numeric_to_string(id, buf, buflen);
-       trace_nfs4_map_uid_to_name(buf, ret, id, ret);
-       return ret;
-}
-int nfs_map_gid_to_group(const struct nfs_server *server, kgid_t gid, char *buf, size_t buflen)
-{
-       struct idmap *idmap = server->nfs_client->cl_idmap;
-       int ret = -EINVAL;
-       __u32 id;
-
-       id = from_kgid(&init_user_ns, gid);
-       if (!(server->caps & NFS_CAP_UIDGID_NOMAP))
-               ret = nfs_idmap_lookup_name(id, "group", buf, buflen, idmap);
-       if (ret < 0)
-               ret = nfs_map_numeric_to_string(id, buf, buflen);
-       trace_nfs4_map_gid_to_group(buf, ret, id, ret);
-       return ret;
-}
index d42dff6d5e983f65c2e2f299e12d5353f54236c7..f734562c6d244034cb5036fee8ab0b7d69cc90c5 100644 (file)
@@ -133,6 +133,13 @@ void nfs_evict_inode(struct inode *inode)
        nfs_clear_inode(inode);
 }
 
+int nfs_sync_inode(struct inode *inode)
+{
+       nfs_inode_dio_wait(inode);
+       return nfs_wb_all(inode);
+}
+EXPORT_SYMBOL_GPL(nfs_sync_inode);
+
 /**
  * nfs_sync_mapping - helper to flush all mmapped dirty data to disk
  */
@@ -192,7 +199,6 @@ void nfs_zap_caches(struct inode *inode)
        nfs_zap_caches_locked(inode);
        spin_unlock(&inode->i_lock);
 }
-EXPORT_SYMBOL_GPL(nfs_zap_caches);
 
 void nfs_zap_mapping(struct inode *inode, struct address_space *mapping)
 {
@@ -495,7 +501,7 @@ EXPORT_SYMBOL_GPL(nfs_fhget);
 int
 nfs_setattr(struct dentry *dentry, struct iattr *attr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct nfs_fattr *fattr;
        int error = -ENOMEM;
 
@@ -525,10 +531,8 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
        trace_nfs_setattr_enter(inode);
 
        /* Write all dirty data */
-       if (S_ISREG(inode->i_mode)) {
-               nfs_inode_dio_wait(inode);
-               nfs_wb_all(inode);
-       }
+       if (S_ISREG(inode->i_mode))
+               nfs_sync_inode(inode);
 
        fattr = nfs_alloc_fattr();
        if (fattr == NULL)
@@ -621,7 +625,7 @@ static void nfs_request_parent_use_readdirplus(struct dentry *dentry)
        struct dentry *parent;
 
        parent = dget_parent(dentry);
-       nfs_force_use_readdirplus(parent->d_inode);
+       nfs_force_use_readdirplus(d_inode(parent));
        dput(parent);
 }
 
@@ -637,15 +641,16 @@ static bool nfs_need_revalidate_inode(struct inode *inode)
 
 int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME;
        int err = 0;
 
        trace_nfs_getattr_enter(inode);
        /* Flush out writes to the server in order to update c/mtime.  */
        if (S_ISREG(inode->i_mode)) {
-               nfs_inode_dio_wait(inode);
-               err = filemap_write_and_wait(inode->i_mapping);
+               mutex_lock(&inode->i_mutex);
+               err = nfs_sync_inode(inode);
+               mutex_unlock(&inode->i_mutex);
                if (err)
                        goto out;
        }
@@ -708,7 +713,7 @@ static struct nfs_lock_context *__nfs_find_lock_context(struct nfs_open_context
 struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx)
 {
        struct nfs_lock_context *res, *new = NULL;
-       struct inode *inode = ctx->dentry->d_inode;
+       struct inode *inode = d_inode(ctx->dentry);
 
        spin_lock(&inode->i_lock);
        res = __nfs_find_lock_context(ctx);
@@ -736,7 +741,7 @@ EXPORT_SYMBOL_GPL(nfs_get_lock_context);
 void nfs_put_lock_context(struct nfs_lock_context *l_ctx)
 {
        struct nfs_open_context *ctx = l_ctx->open_context;
-       struct inode *inode = ctx->dentry->d_inode;
+       struct inode *inode = d_inode(ctx->dentry);
 
        if (!atomic_dec_and_lock(&l_ctx->count, &inode->i_lock))
                return;
@@ -763,7 +768,7 @@ void nfs_close_context(struct nfs_open_context *ctx, int is_sync)
                return;
        if (!is_sync)
                return;
-       inode = ctx->dentry->d_inode;
+       inode = d_inode(ctx->dentry);
        if (!list_empty(&NFS_I(inode)->open_files))
                return;
        server = NFS_SERVER(inode);
@@ -810,7 +815,7 @@ EXPORT_SYMBOL_GPL(get_nfs_open_context);
 
 static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync)
 {
-       struct inode *inode = ctx->dentry->d_inode;
+       struct inode *inode = d_inode(ctx->dentry);
        struct super_block *sb = ctx->dentry->d_sb;
 
        if (!list_empty(&ctx->list)) {
@@ -842,7 +847,7 @@ EXPORT_SYMBOL_GPL(put_nfs_open_context);
  */
 void nfs_inode_attach_open_context(struct nfs_open_context *ctx)
 {
-       struct inode *inode = ctx->dentry->d_inode;
+       struct inode *inode = d_inode(ctx->dentry);
        struct nfs_inode *nfsi = NFS_I(inode);
 
        spin_lock(&inode->i_lock);
@@ -885,7 +890,7 @@ static void nfs_file_clear_open_context(struct file *filp)
        struct nfs_open_context *ctx = nfs_file_open_context(filp);
 
        if (ctx) {
-               struct inode *inode = ctx->dentry->d_inode;
+               struct inode *inode = d_inode(ctx->dentry);
 
                filp->private_data = NULL;
                spin_lock(&inode->i_lock);
@@ -1588,6 +1593,19 @@ int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fa
 }
 EXPORT_SYMBOL_GPL(nfs_post_op_update_inode_force_wcc);
 
+
+static inline bool nfs_fileid_valid(struct nfs_inode *nfsi,
+                                   struct nfs_fattr *fattr)
+{
+       bool ret1 = true, ret2 = true;
+
+       if (fattr->valid & NFS_ATTR_FATTR_FILEID)
+               ret1 = (nfsi->fileid == fattr->fileid);
+       if (fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID)
+               ret2 = (nfsi->fileid == fattr->mounted_on_fileid);
+       return ret1 || ret2;
+}
+
 /*
  * Many nfs protocol calls return the new file attributes after
  * an operation.  Here we update the inode to reflect the state
@@ -1614,7 +1632,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
                        nfs_display_fhandle_hash(NFS_FH(inode)),
                        atomic_read(&inode->i_count), fattr->valid);
 
-       if ((fattr->valid & NFS_ATTR_FATTR_FILEID) && nfsi->fileid != fattr->fileid) {
+       if (!nfs_fileid_valid(nfsi, fattr)) {
                printk(KERN_ERR "NFS: server %s error: fileid changed\n"
                        "fsid %s: expected fileid 0x%Lx, got 0x%Lx\n",
                        NFS_SERVER(inode)->nfs_client->cl_hostname,
@@ -1819,7 +1837,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
 struct inode *nfs_alloc_inode(struct super_block *sb)
 {
        struct nfs_inode *nfsi;
-       nfsi = (struct nfs_inode *)kmem_cache_alloc(nfs_inode_cachep, GFP_KERNEL);
+       nfsi = kmem_cache_alloc(nfs_inode_cachep, GFP_KERNEL);
        if (!nfsi)
                return NULL;
        nfsi->flags = 0UL;
index b5a0afc3ee101b988fc18df2b009c20e56812534..c8162c660c440bb28eb7e31fbd33ce1b4c3b1438 100644 (file)
@@ -139,7 +139,7 @@ EXPORT_SYMBOL_GPL(nfs_path);
 struct vfsmount *nfs_d_automount(struct path *path)
 {
        struct vfsmount *mnt;
-       struct nfs_server *server = NFS_SERVER(path->dentry->d_inode);
+       struct nfs_server *server = NFS_SERVER(d_inode(path->dentry));
        struct nfs_fh *fh = NULL;
        struct nfs_fattr *fattr = NULL;
 
@@ -180,16 +180,16 @@ out_nofree:
 static int
 nfs_namespace_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 {
-       if (NFS_FH(dentry->d_inode)->size != 0)
+       if (NFS_FH(d_inode(dentry))->size != 0)
                return nfs_getattr(mnt, dentry, stat);
-       generic_fillattr(dentry->d_inode, stat);
+       generic_fillattr(d_inode(dentry), stat);
        return 0;
 }
 
 static int
 nfs_namespace_setattr(struct dentry *dentry, struct iattr *attr)
 {
-       if (NFS_FH(dentry->d_inode)->size != 0)
+       if (NFS_FH(d_inode(dentry))->size != 0)
                return nfs_setattr(dentry, attr);
        return -EACCES;
 }
@@ -279,7 +279,7 @@ struct vfsmount *nfs_submount(struct nfs_server *server, struct dentry *dentry,
        struct dentry *parent = dget_parent(dentry);
 
        /* Look it up again to get its attributes */
-       err = server->nfs_client->rpc_ops->lookup(parent->d_inode, &dentry->d_name, fh, fattr, NULL);
+       err = server->nfs_client->rpc_ops->lookup(d_inode(parent), &dentry->d_name, fh, fattr, NULL);
        dput(parent);
        if (err != 0)
                return ERR_PTR(err);
index 658e586ca438bc2964c0edc75242a373c2239f50..1ebe2fc7cda2778edfb968da2c8f079dd2870431 100644 (file)
@@ -279,7 +279,7 @@ nfs3_list_one_acl(struct inode *inode, int type, const char *name, void *data,
 ssize_t
 nfs3_listxattr(struct dentry *dentry, char *data, size_t size)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        ssize_t result = 0;
        int error;
 
index 1f11d2533ee4107bd9ae3f8de460b38ecdbaae74..cb28cceefebe01462adbff860e52c43630d0dca2 100644 (file)
@@ -120,7 +120,7 @@ static int
 nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
                        struct iattr *sattr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct nfs3_sattrargs   arg = {
                .fh             = NFS_FH(inode),
                .sattr          = sattr,
@@ -386,13 +386,13 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
                 * not sure this buys us anything (and I'd have
                 * to revamp the NFSv3 XDR code) */
                status = nfs3_proc_setattr(dentry, data->res.fattr, sattr);
-               nfs_post_op_update_inode(dentry->d_inode, data->res.fattr);
+               nfs_post_op_update_inode(d_inode(dentry), data->res.fattr);
                dprintk("NFS reply setattr (post-create): %d\n", status);
                if (status != 0)
                        goto out_release_acls;
        }
 
-       status = nfs3_proc_setacls(dentry->d_inode, acl, default_acl);
+       status = nfs3_proc_setacls(d_inode(dentry), acl, default_acl);
 
 out_release_acls:
        posix_acl_release(acl);
@@ -570,7 +570,7 @@ nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
        if (status != 0)
                goto out_release_acls;
 
-       status = nfs3_proc_setacls(dentry->d_inode, acl, default_acl);
+       status = nfs3_proc_setacls(d_inode(dentry), acl, default_acl);
 
 out_release_acls:
        posix_acl_release(acl);
@@ -623,7 +623,7 @@ static int
 nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
                  u64 cookie, struct page **pages, unsigned int count, int plus)
 {
-       struct inode            *dir = dentry->d_inode;
+       struct inode            *dir = d_inode(dentry);
        __be32                  *verf = NFS_I(dir)->cookieverf;
        struct nfs3_readdirargs arg = {
                .fh             = NFS_FH(dir),
@@ -715,7 +715,7 @@ nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
        if (status != 0)
                goto out_release_acls;
 
-       status = nfs3_proc_setacls(dentry->d_inode, acl, default_acl);
+       status = nfs3_proc_setacls(d_inode(dentry), acl, default_acl);
 
 out_release_acls:
        posix_acl_release(acl);
index cb170722769cd807990177274bc5a70e64bf806a..3a9e75235f30e60e5a4ae974864c63fb003b969d 100644 (file)
@@ -36,13 +36,16 @@ static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
                                 loff_t offset, loff_t len)
 {
        struct inode *inode = file_inode(filep);
+       struct nfs_server *server = NFS_SERVER(inode);
        struct nfs42_falloc_args args = {
                .falloc_fh      = NFS_FH(inode),
                .falloc_offset  = offset,
                .falloc_length  = len,
+               .falloc_bitmask = server->cache_consistency_bitmask,
+       };
+       struct nfs42_falloc_res res = {
+               .falloc_server  = server,
        };
-       struct nfs42_falloc_res res;
-       struct nfs_server *server = NFS_SERVER(inode);
        int status;
 
        msg->rpc_argp = &args;
@@ -52,8 +55,17 @@ static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
        if (status)
                return status;
 
-       return nfs4_call_sync(server->client, server, msg,
-                             &args.seq_args, &res.seq_res, 0);
+       res.falloc_fattr = nfs_alloc_fattr();
+       if (!res.falloc_fattr)
+               return -ENOMEM;
+
+       status = nfs4_call_sync(server->client, server, msg,
+                               &args.seq_args, &res.seq_res, 0);
+       if (status == 0)
+               status = nfs_post_op_update_inode(inode, res.falloc_fattr);
+
+       kfree(res.falloc_fattr);
+       return status;
 }
 
 static int nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
@@ -84,9 +96,13 @@ int nfs42_proc_allocate(struct file *filep, loff_t offset, loff_t len)
        if (!nfs_server_capable(inode, NFS_CAP_ALLOCATE))
                return -EOPNOTSUPP;
 
+       mutex_lock(&inode->i_mutex);
+
        err = nfs42_proc_fallocate(&msg, filep, offset, len);
        if (err == -EOPNOTSUPP)
                NFS_SERVER(inode)->caps &= ~NFS_CAP_ALLOCATE;
+
+       mutex_unlock(&inode->i_mutex);
        return err;
 }
 
@@ -101,9 +117,16 @@ int nfs42_proc_deallocate(struct file *filep, loff_t offset, loff_t len)
        if (!nfs_server_capable(inode, NFS_CAP_DEALLOCATE))
                return -EOPNOTSUPP;
 
+       nfs_wb_all(inode);
+       mutex_lock(&inode->i_mutex);
+
        err = nfs42_proc_fallocate(&msg, filep, offset, len);
+       if (err == 0)
+               truncate_pagecache_range(inode, offset, (offset + len) -1);
        if (err == -EOPNOTSUPP)
                NFS_SERVER(inode)->caps &= ~NFS_CAP_DEALLOCATE;
+
+       mutex_unlock(&inode->i_mutex);
        return err;
 }
 
index 038a7e1521fa8f0d157aaebdd6d39a78ff9a7eab..1a25b27248f2ff5fd0026b00a3032589ee8cdff5 100644 (file)
 
 #define NFS4_enc_allocate_sz           (compound_encode_hdr_maxsz + \
                                         encode_putfh_maxsz + \
-                                        encode_allocate_maxsz)
+                                        encode_allocate_maxsz + \
+                                        encode_getattr_maxsz)
 #define NFS4_dec_allocate_sz           (compound_decode_hdr_maxsz + \
                                         decode_putfh_maxsz + \
-                                        decode_allocate_maxsz)
+                                        decode_allocate_maxsz + \
+                                        decode_getattr_maxsz)
 #define NFS4_enc_deallocate_sz         (compound_encode_hdr_maxsz + \
                                         encode_putfh_maxsz + \
-                                        encode_deallocate_maxsz)
+                                        encode_deallocate_maxsz + \
+                                        encode_getattr_maxsz)
 #define NFS4_dec_deallocate_sz         (compound_decode_hdr_maxsz + \
                                         decode_putfh_maxsz + \
-                                        decode_deallocate_maxsz)
+                                        decode_deallocate_maxsz + \
+                                        decode_getattr_maxsz)
 #define NFS4_enc_seek_sz               (compound_encode_hdr_maxsz + \
                                         encode_putfh_maxsz + \
                                         encode_seek_maxsz)
@@ -92,6 +96,7 @@ static void nfs4_xdr_enc_allocate(struct rpc_rqst *req,
        encode_sequence(xdr, &args->seq_args, &hdr);
        encode_putfh(xdr, args->falloc_fh, &hdr);
        encode_allocate(xdr, args, &hdr);
+       encode_getfattr(xdr, args->falloc_bitmask, &hdr);
        encode_nops(&hdr);
 }
 
@@ -110,6 +115,7 @@ static void nfs4_xdr_enc_deallocate(struct rpc_rqst *req,
        encode_sequence(xdr, &args->seq_args, &hdr);
        encode_putfh(xdr, args->falloc_fh, &hdr);
        encode_deallocate(xdr, args, &hdr);
+       encode_getfattr(xdr, args->falloc_bitmask, &hdr);
        encode_nops(&hdr);
 }
 
@@ -183,6 +189,9 @@ static int nfs4_xdr_dec_allocate(struct rpc_rqst *rqstp,
        if (status)
                goto out;
        status = decode_allocate(xdr, res);
+       if (status)
+               goto out;
+       decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
 out:
        return status;
 }
@@ -207,6 +216,9 @@ static int nfs4_xdr_dec_deallocate(struct rpc_rqst *rqstp,
        if (status)
                goto out;
        status = decode_deallocate(xdr, res);
+       if (status)
+               goto out;
+       decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
 out:
        return status;
 }
index 86d6214ea022fee66f16f976a17451590edde7b8..e42be52a8c18d8121c934a5ac79483e77166206c 100644 (file)
@@ -4,7 +4,6 @@
  */
 #include <linux/module.h>
 #include <linux/nfs_fs.h>
-#include <linux/nfs_idmap.h>
 #include <linux/nfs_mount.h>
 #include <linux/sunrpc/addr.h>
 #include <linux/sunrpc/auth.h>
@@ -15,6 +14,7 @@
 #include "callback.h"
 #include "delegation.h"
 #include "nfs4session.h"
+#include "nfs4idmap.h"
 #include "pnfs.h"
 #include "netns.h"
 
@@ -1130,7 +1130,7 @@ error:
  */
 static int nfs_probe_destination(struct nfs_server *server)
 {
-       struct inode *inode = server->super->s_root->d_inode;
+       struct inode *inode = d_inode(server->super->s_root);
        struct nfs_fattr *fattr;
        int error;
 
index 0181cde1d102ab5340ef7be230dc2e3ca036993c..f58c17b3b480367c6322359ae7ca4b33b3695348 100644 (file)
@@ -10,6 +10,8 @@
 #include "fscache.h"
 #include "pnfs.h"
 
+#include "nfstrace.h"
+
 #ifdef CONFIG_NFS_V4_2
 #include "nfs42.h"
 #endif
@@ -46,7 +48,7 @@ nfs4_file_open(struct inode *inode, struct file *filp)
        openflags &= ~(O_CREAT|O_EXCL);
 
        parent = dget_parent(dentry);
-       dir = parent->d_inode;
+       dir = d_inode(parent);
 
        ctx = alloc_nfs_open_context(filp->f_path.dentry, filp->f_mode);
        err = PTR_ERR(ctx);
@@ -57,7 +59,7 @@ nfs4_file_open(struct inode *inode, struct file *filp)
        if (openflags & O_TRUNC) {
                attr.ia_valid |= ATTR_SIZE;
                attr.ia_size = 0;
-               nfs_wb_all(inode);
+               nfs_sync_inode(inode);
        }
 
        inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr, &opened);
@@ -74,7 +76,7 @@ nfs4_file_open(struct inode *inode, struct file *filp)
                        goto out_drop;
                }
        }
-       if (inode != dentry->d_inode)
+       if (inode != d_inode(dentry))
                goto out_drop;
 
        nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
@@ -100,6 +102,9 @@ nfs4_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
        int ret;
        struct inode *inode = file_inode(file);
 
+       trace_nfs_fsync_enter(inode);
+
+       nfs_inode_dio_wait(inode);
        do {
                ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
                if (ret != 0)
@@ -107,7 +112,7 @@ nfs4_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
                mutex_lock(&inode->i_mutex);
                ret = nfs_file_fsync_commit(file, start, end, datasync);
                if (!ret)
-                       ret = pnfs_layoutcommit_inode(inode, true);
+                       ret = pnfs_sync_inode(inode, !!datasync);
                mutex_unlock(&inode->i_mutex);
                /*
                 * If nfs_file_fsync_commit detected a server reboot, then
@@ -118,6 +123,7 @@ nfs4_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
                end = LLONG_MAX;
        } while (ret == -EAGAIN);
 
+       trace_nfs_fsync_exit(inode, ret);
        return ret;
 }
 
@@ -152,15 +158,9 @@ static long nfs42_fallocate(struct file *filep, int mode, loff_t offset, loff_t
        if (ret < 0)
                return ret;
 
-       mutex_lock(&inode->i_mutex);
        if (mode & FALLOC_FL_PUNCH_HOLE)
-               ret = nfs42_proc_deallocate(filep, offset, len);
-       else
-               ret = nfs42_proc_allocate(filep, offset, len);
-       mutex_unlock(&inode->i_mutex);
-
-       nfs_zap_caches(inode);
-       return ret;
+               return nfs42_proc_deallocate(filep, offset, len);
+       return nfs42_proc_allocate(filep, offset, len);
 }
 #endif /* CONFIG_NFS_V4_2 */
 
diff --git a/fs/nfs/nfs4idmap.c b/fs/nfs/nfs4idmap.c
new file mode 100644 (file)
index 0000000..2e1737c
--- /dev/null
@@ -0,0 +1,792 @@
+/*
+ * fs/nfs/idmap.c
+ *
+ *  UID and GID to name mapping for clients.
+ *
+ *  Copyright (c) 2002 The Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+ *  Marius Aamodt Eriksen <marius@umich.edu>
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the University nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <linux/types.h>
+#include <linux/parser.h>
+#include <linux/fs.h>
+#include <net/net_namespace.h>
+#include <linux/sunrpc/rpc_pipe_fs.h>
+#include <linux/nfs_fs.h>
+#include <linux/nfs_fs_sb.h>
+#include <linux/key.h>
+#include <linux/keyctl.h>
+#include <linux/key-type.h>
+#include <keys/user-type.h>
+#include <linux/module.h>
+
+#include "internal.h"
+#include "netns.h"
+#include "nfs4idmap.h"
+#include "nfs4trace.h"
+
+#define NFS_UINT_MAXLEN 11
+
+static const struct cred *id_resolver_cache;
+static struct key_type key_type_id_resolver_legacy;
+
+struct idmap_legacy_upcalldata {
+       struct rpc_pipe_msg pipe_msg;
+       struct idmap_msg idmap_msg;
+       struct key_construction *key_cons;
+       struct idmap *idmap;
+};
+
+struct idmap {
+       struct rpc_pipe_dir_object idmap_pdo;
+       struct rpc_pipe         *idmap_pipe;
+       struct idmap_legacy_upcalldata *idmap_upcall_data;
+       struct mutex            idmap_mutex;
+};
+
+/**
+ * nfs_fattr_init_names - initialise the nfs_fattr owner_name/group_name fields
+ * @fattr: fully initialised struct nfs_fattr
+ * @owner_name: owner name string cache
+ * @group_name: group name string cache
+ */
+void nfs_fattr_init_names(struct nfs_fattr *fattr,
+               struct nfs4_string *owner_name,
+               struct nfs4_string *group_name)
+{
+       fattr->owner_name = owner_name;
+       fattr->group_name = group_name;
+}
+
+static void nfs_fattr_free_owner_name(struct nfs_fattr *fattr)
+{
+       fattr->valid &= ~NFS_ATTR_FATTR_OWNER_NAME;
+       kfree(fattr->owner_name->data);
+}
+
+static void nfs_fattr_free_group_name(struct nfs_fattr *fattr)
+{
+       fattr->valid &= ~NFS_ATTR_FATTR_GROUP_NAME;
+       kfree(fattr->group_name->data);
+}
+
+static bool nfs_fattr_map_owner_name(struct nfs_server *server, struct nfs_fattr *fattr)
+{
+       struct nfs4_string *owner = fattr->owner_name;
+       kuid_t uid;
+
+       if (!(fattr->valid & NFS_ATTR_FATTR_OWNER_NAME))
+               return false;
+       if (nfs_map_name_to_uid(server, owner->data, owner->len, &uid) == 0) {
+               fattr->uid = uid;
+               fattr->valid |= NFS_ATTR_FATTR_OWNER;
+       }
+       return true;
+}
+
+static bool nfs_fattr_map_group_name(struct nfs_server *server, struct nfs_fattr *fattr)
+{
+       struct nfs4_string *group = fattr->group_name;
+       kgid_t gid;
+
+       if (!(fattr->valid & NFS_ATTR_FATTR_GROUP_NAME))
+               return false;
+       if (nfs_map_group_to_gid(server, group->data, group->len, &gid) == 0) {
+               fattr->gid = gid;
+               fattr->valid |= NFS_ATTR_FATTR_GROUP;
+       }
+       return true;
+}
+
+/**
+ * nfs_fattr_free_names - free up the NFSv4 owner and group strings
+ * @fattr: a fully initialised nfs_fattr structure
+ */
+void nfs_fattr_free_names(struct nfs_fattr *fattr)
+{
+       if (fattr->valid & NFS_ATTR_FATTR_OWNER_NAME)
+               nfs_fattr_free_owner_name(fattr);
+       if (fattr->valid & NFS_ATTR_FATTR_GROUP_NAME)
+               nfs_fattr_free_group_name(fattr);
+}
+
+/**
+ * nfs_fattr_map_and_free_names - map owner/group strings into uid/gid and free
+ * @server: pointer to the filesystem nfs_server structure
+ * @fattr: a fully initialised nfs_fattr structure
+ *
+ * This helper maps the cached NFSv4 owner/group strings in fattr into
+ * their numeric uid/gid equivalents, and then frees the cached strings.
+ */
+void nfs_fattr_map_and_free_names(struct nfs_server *server, struct nfs_fattr *fattr)
+{
+       if (nfs_fattr_map_owner_name(server, fattr))
+               nfs_fattr_free_owner_name(fattr);
+       if (nfs_fattr_map_group_name(server, fattr))
+               nfs_fattr_free_group_name(fattr);
+}
+
+int nfs_map_string_to_numeric(const char *name, size_t namelen, __u32 *res)
+{
+       unsigned long val;
+       char buf[16];
+
+       if (memchr(name, '@', namelen) != NULL || namelen >= sizeof(buf))
+               return 0;
+       memcpy(buf, name, namelen);
+       buf[namelen] = '\0';
+       if (kstrtoul(buf, 0, &val) != 0)
+               return 0;
+       *res = val;
+       return 1;
+}
+EXPORT_SYMBOL_GPL(nfs_map_string_to_numeric);
+
+static int nfs_map_numeric_to_string(__u32 id, char *buf, size_t buflen)
+{
+       return snprintf(buf, buflen, "%u", id);
+}
+
+static struct key_type key_type_id_resolver = {
+       .name           = "id_resolver",
+       .preparse       = user_preparse,
+       .free_preparse  = user_free_preparse,
+       .instantiate    = generic_key_instantiate,
+       .revoke         = user_revoke,
+       .destroy        = user_destroy,
+       .describe       = user_describe,
+       .read           = user_read,
+};
+
+static int nfs_idmap_init_keyring(void)
+{
+       struct cred *cred;
+       struct key *keyring;
+       int ret = 0;
+
+       printk(KERN_NOTICE "NFS: Registering the %s key type\n",
+               key_type_id_resolver.name);
+
+       cred = prepare_kernel_cred(NULL);
+       if (!cred)
+               return -ENOMEM;
+
+       keyring = keyring_alloc(".id_resolver",
+                               GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
+                               (KEY_POS_ALL & ~KEY_POS_SETATTR) |
+                               KEY_USR_VIEW | KEY_USR_READ,
+                               KEY_ALLOC_NOT_IN_QUOTA, NULL);
+       if (IS_ERR(keyring)) {
+               ret = PTR_ERR(keyring);
+               goto failed_put_cred;
+       }
+
+       ret = register_key_type(&key_type_id_resolver);
+       if (ret < 0)
+               goto failed_put_key;
+
+       ret = register_key_type(&key_type_id_resolver_legacy);
+       if (ret < 0)
+               goto failed_reg_legacy;
+
+       set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
+       cred->thread_keyring = keyring;
+       cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
+       id_resolver_cache = cred;
+       return 0;
+
+failed_reg_legacy:
+       unregister_key_type(&key_type_id_resolver);
+failed_put_key:
+       key_put(keyring);
+failed_put_cred:
+       put_cred(cred);
+       return ret;
+}
+
+static void nfs_idmap_quit_keyring(void)
+{
+       key_revoke(id_resolver_cache->thread_keyring);
+       unregister_key_type(&key_type_id_resolver);
+       unregister_key_type(&key_type_id_resolver_legacy);
+       put_cred(id_resolver_cache);
+}
+
+/*
+ * Assemble the description to pass to request_key()
+ * This function will allocate a new string and update dest to point
+ * at it.  The caller is responsible for freeing dest.
+ *
+ * On error 0 is returned.  Otherwise, the length of dest is returned.
+ */
+static ssize_t nfs_idmap_get_desc(const char *name, size_t namelen,
+                               const char *type, size_t typelen, char **desc)
+{
+       char *cp;
+       size_t desclen = typelen + namelen + 2;
+
+       *desc = kmalloc(desclen, GFP_KERNEL);
+       if (!*desc)
+               return -ENOMEM;
+
+       cp = *desc;
+       memcpy(cp, type, typelen);
+       cp += typelen;
+       *cp++ = ':';
+
+       memcpy(cp, name, namelen);
+       cp += namelen;
+       *cp = '\0';
+       return desclen;
+}
+
+static struct key *nfs_idmap_request_key(const char *name, size_t namelen,
+                                        const char *type, struct idmap *idmap)
+{
+       char *desc;
+       struct key *rkey;
+       ssize_t ret;
+
+       ret = nfs_idmap_get_desc(name, namelen, type, strlen(type), &desc);
+       if (ret <= 0)
+               return ERR_PTR(ret);
+
+       rkey = request_key(&key_type_id_resolver, desc, "");
+       if (IS_ERR(rkey)) {
+               mutex_lock(&idmap->idmap_mutex);
+               rkey = request_key_with_auxdata(&key_type_id_resolver_legacy,
+                                               desc, "", 0, idmap);
+               mutex_unlock(&idmap->idmap_mutex);
+       }
+       if (!IS_ERR(rkey))
+               set_bit(KEY_FLAG_ROOT_CAN_INVAL, &rkey->flags);
+
+       kfree(desc);
+       return rkey;
+}
+
+static ssize_t nfs_idmap_get_key(const char *name, size_t namelen,
+                                const char *type, void *data,
+                                size_t data_size, struct idmap *idmap)
+{
+       const struct cred *saved_cred;
+       struct key *rkey;
+       struct user_key_payload *payload;
+       ssize_t ret;
+
+       saved_cred = override_creds(id_resolver_cache);
+       rkey = nfs_idmap_request_key(name, namelen, type, idmap);
+       revert_creds(saved_cred);
+
+       if (IS_ERR(rkey)) {
+               ret = PTR_ERR(rkey);
+               goto out;
+       }
+
+       rcu_read_lock();
+       rkey->perm |= KEY_USR_VIEW;
+
+       ret = key_validate(rkey);
+       if (ret < 0)
+               goto out_up;
+
+       payload = rcu_dereference(rkey->payload.rcudata);
+       if (IS_ERR_OR_NULL(payload)) {
+               ret = PTR_ERR(payload);
+               goto out_up;
+       }
+
+       ret = payload->datalen;
+       if (ret > 0 && ret <= data_size)
+               memcpy(data, payload->data, ret);
+       else
+               ret = -EINVAL;
+
+out_up:
+       rcu_read_unlock();
+       key_put(rkey);
+out:
+       return ret;
+}
+
+/* ID -> Name */
+static ssize_t nfs_idmap_lookup_name(__u32 id, const char *type, char *buf,
+                                    size_t buflen, struct idmap *idmap)
+{
+       char id_str[NFS_UINT_MAXLEN];
+       int id_len;
+       ssize_t ret;
+
+       id_len = snprintf(id_str, sizeof(id_str), "%u", id);
+       ret = nfs_idmap_get_key(id_str, id_len, type, buf, buflen, idmap);
+       if (ret < 0)
+               return -EINVAL;
+       return ret;
+}
+
+/* Name -> ID */
+static int nfs_idmap_lookup_id(const char *name, size_t namelen, const char *type,
+                              __u32 *id, struct idmap *idmap)
+{
+       char id_str[NFS_UINT_MAXLEN];
+       long id_long;
+       ssize_t data_size;
+       int ret = 0;
+
+       data_size = nfs_idmap_get_key(name, namelen, type, id_str, NFS_UINT_MAXLEN, idmap);
+       if (data_size <= 0) {
+               ret = -EINVAL;
+       } else {
+               ret = kstrtol(id_str, 10, &id_long);
+               *id = (__u32)id_long;
+       }
+       return ret;
+}
+
+/* idmap classic begins here */
+
+enum {
+       Opt_find_uid, Opt_find_gid, Opt_find_user, Opt_find_group, Opt_find_err
+};
+
+static const match_table_t nfs_idmap_tokens = {
+       { Opt_find_uid, "uid:%s" },
+       { Opt_find_gid, "gid:%s" },
+       { Opt_find_user, "user:%s" },
+       { Opt_find_group, "group:%s" },
+       { Opt_find_err, NULL }
+};
+
+static int nfs_idmap_legacy_upcall(struct key_construction *, const char *, void *);
+static ssize_t idmap_pipe_downcall(struct file *, const char __user *,
+                                  size_t);
+static void idmap_release_pipe(struct inode *);
+static void idmap_pipe_destroy_msg(struct rpc_pipe_msg *);
+
+static const struct rpc_pipe_ops idmap_upcall_ops = {
+       .upcall         = rpc_pipe_generic_upcall,
+       .downcall       = idmap_pipe_downcall,
+       .release_pipe   = idmap_release_pipe,
+       .destroy_msg    = idmap_pipe_destroy_msg,
+};
+
+static struct key_type key_type_id_resolver_legacy = {
+       .name           = "id_legacy",
+       .preparse       = user_preparse,
+       .free_preparse  = user_free_preparse,
+       .instantiate    = generic_key_instantiate,
+       .revoke         = user_revoke,
+       .destroy        = user_destroy,
+       .describe       = user_describe,
+       .read           = user_read,
+       .request_key    = nfs_idmap_legacy_upcall,
+};
+
+static void nfs_idmap_pipe_destroy(struct dentry *dir,
+               struct rpc_pipe_dir_object *pdo)
+{
+       struct idmap *idmap = pdo->pdo_data;
+       struct rpc_pipe *pipe = idmap->idmap_pipe;
+
+       if (pipe->dentry) {
+               rpc_unlink(pipe->dentry);
+               pipe->dentry = NULL;
+       }
+}
+
+static int nfs_idmap_pipe_create(struct dentry *dir,
+               struct rpc_pipe_dir_object *pdo)
+{
+       struct idmap *idmap = pdo->pdo_data;
+       struct rpc_pipe *pipe = idmap->idmap_pipe;
+       struct dentry *dentry;
+
+       dentry = rpc_mkpipe_dentry(dir, "idmap", idmap, pipe);
+       if (IS_ERR(dentry))
+               return PTR_ERR(dentry);
+       pipe->dentry = dentry;
+       return 0;
+}
+
+static const struct rpc_pipe_dir_object_ops nfs_idmap_pipe_dir_object_ops = {
+       .create = nfs_idmap_pipe_create,
+       .destroy = nfs_idmap_pipe_destroy,
+};
+
+int
+nfs_idmap_new(struct nfs_client *clp)
+{
+       struct idmap *idmap;
+       struct rpc_pipe *pipe;
+       int error;
+
+       idmap = kzalloc(sizeof(*idmap), GFP_KERNEL);
+       if (idmap == NULL)
+               return -ENOMEM;
+
+       rpc_init_pipe_dir_object(&idmap->idmap_pdo,
+                       &nfs_idmap_pipe_dir_object_ops,
+                       idmap);
+
+       pipe = rpc_mkpipe_data(&idmap_upcall_ops, 0);
+       if (IS_ERR(pipe)) {
+               error = PTR_ERR(pipe);
+               goto err;
+       }
+       idmap->idmap_pipe = pipe;
+       mutex_init(&idmap->idmap_mutex);
+
+       error = rpc_add_pipe_dir_object(clp->cl_net,
+                       &clp->cl_rpcclient->cl_pipedir_objects,
+                       &idmap->idmap_pdo);
+       if (error)
+               goto err_destroy_pipe;
+
+       clp->cl_idmap = idmap;
+       return 0;
+err_destroy_pipe:
+       rpc_destroy_pipe_data(idmap->idmap_pipe);
+err:
+       kfree(idmap);
+       return error;
+}
+
+void
+nfs_idmap_delete(struct nfs_client *clp)
+{
+       struct idmap *idmap = clp->cl_idmap;
+
+       if (!idmap)
+               return;
+       clp->cl_idmap = NULL;
+       rpc_remove_pipe_dir_object(clp->cl_net,
+                       &clp->cl_rpcclient->cl_pipedir_objects,
+                       &idmap->idmap_pdo);
+       rpc_destroy_pipe_data(idmap->idmap_pipe);
+       kfree(idmap);
+}
+
+int nfs_idmap_init(void)
+{
+       int ret;
+       ret = nfs_idmap_init_keyring();
+       if (ret != 0)
+               goto out;
+out:
+       return ret;
+}
+
+void nfs_idmap_quit(void)
+{
+       nfs_idmap_quit_keyring();
+}
+
+static int nfs_idmap_prepare_message(char *desc, struct idmap *idmap,
+                                    struct idmap_msg *im,
+                                    struct rpc_pipe_msg *msg)
+{
+       substring_t substr;
+       int token, ret;
+
+       im->im_type = IDMAP_TYPE_GROUP;
+       token = match_token(desc, nfs_idmap_tokens, &substr);
+
+       switch (token) {
+       case Opt_find_uid:
+               im->im_type = IDMAP_TYPE_USER;
+       case Opt_find_gid:
+               im->im_conv = IDMAP_CONV_NAMETOID;
+               ret = match_strlcpy(im->im_name, &substr, IDMAP_NAMESZ);
+               break;
+
+       case Opt_find_user:
+               im->im_type = IDMAP_TYPE_USER;
+       case Opt_find_group:
+               im->im_conv = IDMAP_CONV_IDTONAME;
+               ret = match_int(&substr, &im->im_id);
+               break;
+
+       default:
+               ret = -EINVAL;
+               goto out;
+       }
+
+       msg->data = im;
+       msg->len  = sizeof(struct idmap_msg);
+
+out:
+       return ret;
+}
+
+static bool
+nfs_idmap_prepare_pipe_upcall(struct idmap *idmap,
+               struct idmap_legacy_upcalldata *data)
+{
+       if (idmap->idmap_upcall_data != NULL) {
+               WARN_ON_ONCE(1);
+               return false;
+       }
+       idmap->idmap_upcall_data = data;
+       return true;
+}
+
+static void
+nfs_idmap_complete_pipe_upcall_locked(struct idmap *idmap, int ret)
+{
+       struct key_construction *cons = idmap->idmap_upcall_data->key_cons;
+
+       kfree(idmap->idmap_upcall_data);
+       idmap->idmap_upcall_data = NULL;
+       complete_request_key(cons, ret);
+}
+
+static void
+nfs_idmap_abort_pipe_upcall(struct idmap *idmap, int ret)
+{
+       if (idmap->idmap_upcall_data != NULL)
+               nfs_idmap_complete_pipe_upcall_locked(idmap, ret);
+}
+
+static int nfs_idmap_legacy_upcall(struct key_construction *cons,
+                                  const char *op,
+                                  void *aux)
+{
+       struct idmap_legacy_upcalldata *data;
+       struct rpc_pipe_msg *msg;
+       struct idmap_msg *im;
+       struct idmap *idmap = (struct idmap *)aux;
+       struct key *key = cons->key;
+       int ret = -ENOMEM;
+
+       /* msg and im are freed in idmap_pipe_destroy_msg */
+       data = kzalloc(sizeof(*data), GFP_KERNEL);
+       if (!data)
+               goto out1;
+
+       msg = &data->pipe_msg;
+       im = &data->idmap_msg;
+       data->idmap = idmap;
+       data->key_cons = cons;
+
+       ret = nfs_idmap_prepare_message(key->description, idmap, im, msg);
+       if (ret < 0)
+               goto out2;
+
+       ret = -EAGAIN;
+       if (!nfs_idmap_prepare_pipe_upcall(idmap, data))
+               goto out2;
+
+       ret = rpc_queue_upcall(idmap->idmap_pipe, msg);
+       if (ret < 0)
+               nfs_idmap_abort_pipe_upcall(idmap, ret);
+
+       return ret;
+out2:
+       kfree(data);
+out1:
+       complete_request_key(cons, ret);
+       return ret;
+}
+
+static int nfs_idmap_instantiate(struct key *key, struct key *authkey, char *data, size_t datalen)
+{
+       return key_instantiate_and_link(key, data, datalen,
+                                       id_resolver_cache->thread_keyring,
+                                       authkey);
+}
+
+static int nfs_idmap_read_and_verify_message(struct idmap_msg *im,
+               struct idmap_msg *upcall,
+               struct key *key, struct key *authkey)
+{
+       char id_str[NFS_UINT_MAXLEN];
+       size_t len;
+       int ret = -ENOKEY;
+
+       /* ret = -ENOKEY */
+       if (upcall->im_type != im->im_type || upcall->im_conv != im->im_conv)
+               goto out;
+       switch (im->im_conv) {
+       case IDMAP_CONV_NAMETOID:
+               if (strcmp(upcall->im_name, im->im_name) != 0)
+                       break;
+               /* Note: here we store the NUL terminator too */
+               len = sprintf(id_str, "%d", im->im_id) + 1;
+               ret = nfs_idmap_instantiate(key, authkey, id_str, len);
+               break;
+       case IDMAP_CONV_IDTONAME:
+               if (upcall->im_id != im->im_id)
+                       break;
+               len = strlen(im->im_name);
+               ret = nfs_idmap_instantiate(key, authkey, im->im_name, len);
+               break;
+       default:
+               ret = -EINVAL;
+       }
+out:
+       return ret;
+}
+
+static ssize_t
+idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
+{
+       struct rpc_inode *rpci = RPC_I(file_inode(filp));
+       struct idmap *idmap = (struct idmap *)rpci->private;
+       struct key_construction *cons;
+       struct idmap_msg im;
+       size_t namelen_in;
+       int ret = -ENOKEY;
+
+       /* If instantiation is successful, anyone waiting for key construction
+        * will have been woken up and someone else may now have used
+        * idmap_key_cons - so after this point we may no longer touch it.
+        */
+       if (idmap->idmap_upcall_data == NULL)
+               goto out_noupcall;
+
+       cons = idmap->idmap_upcall_data->key_cons;
+
+       if (mlen != sizeof(im)) {
+               ret = -ENOSPC;
+               goto out;
+       }
+
+       if (copy_from_user(&im, src, mlen) != 0) {
+               ret = -EFAULT;
+               goto out;
+       }
+
+       if (!(im.im_status & IDMAP_STATUS_SUCCESS)) {
+               ret = -ENOKEY;
+               goto out;
+       }
+
+       namelen_in = strnlen(im.im_name, IDMAP_NAMESZ);
+       if (namelen_in == 0 || namelen_in == IDMAP_NAMESZ) {
+               ret = -EINVAL;
+               goto out;
+}
+
+       ret = nfs_idmap_read_and_verify_message(&im,
+                       &idmap->idmap_upcall_data->idmap_msg,
+                       cons->key, cons->authkey);
+       if (ret >= 0) {
+               key_set_timeout(cons->key, nfs_idmap_cache_timeout);
+               ret = mlen;
+       }
+
+out:
+       nfs_idmap_complete_pipe_upcall_locked(idmap, ret);
+out_noupcall:
+       return ret;
+}
+
+static void
+idmap_pipe_destroy_msg(struct rpc_pipe_msg *msg)
+{
+       struct idmap_legacy_upcalldata *data = container_of(msg,
+                       struct idmap_legacy_upcalldata,
+                       pipe_msg);
+       struct idmap *idmap = data->idmap;
+
+       if (msg->errno)
+               nfs_idmap_abort_pipe_upcall(idmap, msg->errno);
+}
+
+static void
+idmap_release_pipe(struct inode *inode)
+{
+       struct rpc_inode *rpci = RPC_I(inode);
+       struct idmap *idmap = (struct idmap *)rpci->private;
+
+       nfs_idmap_abort_pipe_upcall(idmap, -EPIPE);
+}
+
+int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, kuid_t *uid)
+{
+       struct idmap *idmap = server->nfs_client->cl_idmap;
+       __u32 id = -1;
+       int ret = 0;
+
+       if (!nfs_map_string_to_numeric(name, namelen, &id))
+               ret = nfs_idmap_lookup_id(name, namelen, "uid", &id, idmap);
+       if (ret == 0) {
+               *uid = make_kuid(&init_user_ns, id);
+               if (!uid_valid(*uid))
+                       ret = -ERANGE;
+       }
+       trace_nfs4_map_name_to_uid(name, namelen, id, ret);
+       return ret;
+}
+
+int nfs_map_group_to_gid(const struct nfs_server *server, const char *name, size_t namelen, kgid_t *gid)
+{
+       struct idmap *idmap = server->nfs_client->cl_idmap;
+       __u32 id = -1;
+       int ret = 0;
+
+       if (!nfs_map_string_to_numeric(name, namelen, &id))
+               ret = nfs_idmap_lookup_id(name, namelen, "gid", &id, idmap);
+       if (ret == 0) {
+               *gid = make_kgid(&init_user_ns, id);
+               if (!gid_valid(*gid))
+                       ret = -ERANGE;
+       }
+       trace_nfs4_map_group_to_gid(name, namelen, id, ret);
+       return ret;
+}
+
+int nfs_map_uid_to_name(const struct nfs_server *server, kuid_t uid, char *buf, size_t buflen)
+{
+       struct idmap *idmap = server->nfs_client->cl_idmap;
+       int ret = -EINVAL;
+       __u32 id;
+
+       id = from_kuid(&init_user_ns, uid);
+       if (!(server->caps & NFS_CAP_UIDGID_NOMAP))
+               ret = nfs_idmap_lookup_name(id, "user", buf, buflen, idmap);
+       if (ret < 0)
+               ret = nfs_map_numeric_to_string(id, buf, buflen);
+       trace_nfs4_map_uid_to_name(buf, ret, id, ret);
+       return ret;
+}
+int nfs_map_gid_to_group(const struct nfs_server *server, kgid_t gid, char *buf, size_t buflen)
+{
+       struct idmap *idmap = server->nfs_client->cl_idmap;
+       int ret = -EINVAL;
+       __u32 id;
+
+       id = from_kgid(&init_user_ns, gid);
+       if (!(server->caps & NFS_CAP_UIDGID_NOMAP))
+               ret = nfs_idmap_lookup_name(id, "group", buf, buflen, idmap);
+       if (ret < 0)
+               ret = nfs_map_numeric_to_string(id, buf, buflen);
+       trace_nfs4_map_gid_to_group(buf, ret, id, ret);
+       return ret;
+}
diff --git a/fs/nfs/nfs4idmap.h b/fs/nfs/nfs4idmap.h
new file mode 100644 (file)
index 0000000..de44d73
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * fs/nfs/nfs4idmap.h
+ *
+ *  UID and GID to name mapping for clients.
+ *
+ *  Copyright (c) 2002 The Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+ *  Marius Aamodt Eriksen <marius@umich.edu>
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the University nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef NFS_IDMAP_H
+#define NFS_IDMAP_H
+
+#include <linux/uidgid.h>
+#include <uapi/linux/nfs_idmap.h>
+
+
+/* Forward declaration to make this header independent of others */
+struct nfs_client;
+struct nfs_server;
+struct nfs_fattr;
+struct nfs4_string;
+
+int nfs_idmap_init(void);
+void nfs_idmap_quit(void);
+int nfs_idmap_new(struct nfs_client *);
+void nfs_idmap_delete(struct nfs_client *);
+
+void nfs_fattr_init_names(struct nfs_fattr *fattr,
+               struct nfs4_string *owner_name,
+               struct nfs4_string *group_name);
+void nfs_fattr_free_names(struct nfs_fattr *);
+void nfs_fattr_map_and_free_names(struct nfs_server *, struct nfs_fattr *);
+
+int nfs_map_name_to_uid(const struct nfs_server *, const char *, size_t, kuid_t *);
+int nfs_map_group_to_gid(const struct nfs_server *, const char *, size_t, kgid_t *);
+int nfs_map_uid_to_name(const struct nfs_server *, kuid_t, char *, size_t);
+int nfs_map_gid_to_group(const struct nfs_server *, kgid_t, char *, size_t);
+
+int nfs_map_string_to_numeric(const char *name, size_t namelen, __u32 *res);
+
+extern unsigned int nfs_idmap_cache_timeout;
+#endif /* NFS_IDMAP_H */
index 3d83cb1fdc700ee95f120eee7286ff63f17e17e2..f592672373cbb09c1ba18a0a7aedc1267dbd69b2 100644 (file)
@@ -375,7 +375,7 @@ static struct vfsmount *nfs_do_refmount(struct rpc_clnt *client, struct dentry *
        dprintk("%s: getting locations for %pd2\n",
                __func__, dentry);
 
-       err = nfs4_proc_fs_locations(client, parent->d_inode, &dentry->d_name, fs_locations, page);
+       err = nfs4_proc_fs_locations(client, d_inode(parent), &dentry->d_name, fs_locations, page);
        dput(parent);
        if (err != 0 ||
            fs_locations->nlocations <= 0 ||
@@ -396,7 +396,7 @@ struct vfsmount *nfs4_submount(struct nfs_server *server, struct dentry *dentry,
 {
        rpc_authflavor_t flavor = server->client->cl_auth->au_flavor;
        struct dentry *parent = dget_parent(dentry);
-       struct inode *dir = parent->d_inode;
+       struct inode *dir = d_inode(parent);
        struct qstr *name = &dentry->d_name;
        struct rpc_clnt *client;
        struct vfsmount *mnt;
index 627f37c44456752d6bd90a8882ae373ec6d70718..45b35b9b1e36a1213a2c2736e4ae551dcd0d8848 100644 (file)
@@ -51,7 +51,6 @@
 #include <linux/namei.h>
 #include <linux/mount.h>
 #include <linux/module.h>
-#include <linux/nfs_idmap.h>
 #include <linux/xattr.h>
 #include <linux/utsname.h>
 #include <linux/freezer.h>
@@ -63,6 +62,7 @@
 #include "callback.h"
 #include "pnfs.h"
 #include "netns.h"
+#include "nfs4idmap.h"
 #include "nfs4session.h"
 #include "fscache.h"
 
@@ -185,7 +185,8 @@ const u32 nfs4_fattr_bitmap[3] = {
        | FATTR4_WORD1_SPACE_USED
        | FATTR4_WORD1_TIME_ACCESS
        | FATTR4_WORD1_TIME_METADATA
-       | FATTR4_WORD1_TIME_MODIFY,
+       | FATTR4_WORD1_TIME_MODIFY
+       | FATTR4_WORD1_MOUNTED_ON_FILEID,
 #ifdef CONFIG_NFS_V4_SECURITY_LABEL
        FATTR4_WORD2_SECURITY_LABEL
 #endif
@@ -293,7 +294,7 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent
                *p++ = xdr_one;                         /* bitmap length */
                *p++ = htonl(FATTR4_WORD0_FILEID);             /* bitmap */
                *p++ = htonl(8);              /* attribute buffer length */
-               p = xdr_encode_hyper(p, NFS_FILEID(dentry->d_inode));
+               p = xdr_encode_hyper(p, NFS_FILEID(d_inode(dentry)));
        }
        
        *p++ = xdr_one;                                  /* next */
@@ -305,7 +306,7 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent
        *p++ = xdr_one;                         /* bitmap length */
        *p++ = htonl(FATTR4_WORD0_FILEID);             /* bitmap */
        *p++ = htonl(8);              /* attribute buffer length */
-       p = xdr_encode_hyper(p, NFS_FILEID(dentry->d_parent->d_inode));
+       p = xdr_encode_hyper(p, NFS_FILEID(d_inode(dentry->d_parent)));
 
        readdir->pgbase = (char *)p - (char *)start;
        readdir->count -= readdir->pgbase;
@@ -1004,7 +1005,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
                gfp_t gfp_mask)
 {
        struct dentry *parent = dget_parent(dentry);
-       struct inode *dir = parent->d_inode;
+       struct inode *dir = d_inode(parent);
        struct nfs_server *server = NFS_SERVER(dir);
        struct nfs_seqid *(*alloc_seqid)(struct nfs_seqid_counter *, gfp_t);
        struct nfs4_opendata *p;
@@ -1057,7 +1058,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
        case NFS4_OPEN_CLAIM_FH:
        case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
        case NFS4_OPEN_CLAIM_DELEG_PREV_FH:
-               p->o_arg.fh = NFS_FH(dentry->d_inode);
+               p->o_arg.fh = NFS_FH(d_inode(dentry));
        }
        if (attrs != NULL && attrs->ia_valid != 0) {
                __u32 verf[2];
@@ -1794,7 +1795,7 @@ static const struct rpc_call_ops nfs4_open_confirm_ops = {
  */
 static int _nfs4_proc_open_confirm(struct nfs4_opendata *data)
 {
-       struct nfs_server *server = NFS_SERVER(data->dir->d_inode);
+       struct nfs_server *server = NFS_SERVER(d_inode(data->dir));
        struct rpc_task *task;
        struct  rpc_message msg = {
                .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_CONFIRM],
@@ -1951,7 +1952,7 @@ static const struct rpc_call_ops nfs4_open_ops = {
 
 static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover)
 {
-       struct inode *dir = data->dir->d_inode;
+       struct inode *dir = d_inode(data->dir);
        struct nfs_server *server = NFS_SERVER(dir);
        struct nfs_openargs *o_arg = &data->o_arg;
        struct nfs_openres *o_res = &data->o_res;
@@ -1998,7 +1999,7 @@ static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover)
 
 static int _nfs4_recover_proc_open(struct nfs4_opendata *data)
 {
-       struct inode *dir = data->dir->d_inode;
+       struct inode *dir = d_inode(data->dir);
        struct nfs_openres *o_res = &data->o_res;
         int status;
 
@@ -2067,7 +2068,7 @@ static int nfs4_opendata_access(struct rpc_cred *cred,
  */
 static int _nfs4_proc_open(struct nfs4_opendata *data)
 {
-       struct inode *dir = data->dir->d_inode;
+       struct inode *dir = d_inode(data->dir);
        struct nfs_server *server = NFS_SERVER(dir);
        struct nfs_openargs *o_arg = &data->o_arg;
        struct nfs_openres *o_res = &data->o_res;
@@ -2314,7 +2315,7 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
                set_bit(NFS_STATE_POSIX_LOCKS, &state->flags);
 
        dentry = opendata->dentry;
-       if (dentry->d_inode == NULL) {
+       if (d_really_is_negative(dentry)) {
                /* FIXME: Is this d_drop() ever needed? */
                d_drop(dentry);
                dentry = d_add_unique(dentry, igrab(state->inode));
@@ -2325,7 +2326,7 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
                        ctx->dentry = dget(dentry);
                }
                nfs_set_verifier(dentry,
-                               nfs_save_change_attribute(opendata->dir->d_inode));
+                               nfs_save_change_attribute(d_inode(opendata->dir)));
        }
 
        ret = nfs4_opendata_access(sp->so_cred, opendata, state, fmode, flags);
@@ -2333,7 +2334,7 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
                goto out;
 
        ctx->state = state;
-       if (dentry->d_inode == state->inode) {
+       if (d_inode(dentry) == state->inode) {
                nfs_inode_attach_open_context(ctx);
                if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq))
                        nfs4_schedule_stateid_recovery(server, state);
@@ -2374,10 +2375,10 @@ static int _nfs4_do_open(struct inode *dir,
        status = nfs4_recover_expired_lease(server);
        if (status != 0)
                goto err_put_state_owner;
-       if (dentry->d_inode != NULL)
-               nfs4_return_incompatible_delegation(dentry->d_inode, fmode);
+       if (d_really_is_positive(dentry))
+               nfs4_return_incompatible_delegation(d_inode(dentry), fmode);
        status = -ENOMEM;
-       if (dentry->d_inode)
+       if (d_really_is_positive(dentry))
                claim = NFS4_OPEN_CLAIM_FH;
        opendata = nfs4_opendata_alloc(dentry, sp, fmode, flags, sattr,
                        label, claim, GFP_KERNEL);
@@ -2400,8 +2401,8 @@ static int _nfs4_do_open(struct inode *dir,
                }
                opendata->o_arg.open_bitmap = &nfs4_pnfs_open_bitmap[0];
        }
-       if (dentry->d_inode != NULL)
-               opendata->state = nfs4_get_open_state(dentry->d_inode, sp);
+       if (d_really_is_positive(dentry))
+               opendata->state = nfs4_get_open_state(d_inode(dentry), sp);
 
        status = _nfs4_open_and_get_state(opendata, fmode, flags, ctx);
        if (status != 0)
@@ -3095,16 +3096,13 @@ int nfs4_proc_get_rootfh(struct nfs_server *server, struct nfs_fh *fhandle,
                         struct nfs_fsinfo *info,
                         bool auth_probe)
 {
-       int status;
+       int status = 0;
 
-       switch (auth_probe) {
-       case false:
+       if (!auth_probe)
                status = nfs4_lookup_root(server, fhandle, info);
-               if (status != -NFS4ERR_WRONGSEC)
-                       break;
-       default:
+
+       if (auth_probe || status == NFS4ERR_WRONGSEC)
                status = nfs4_do_find_root_sec(server, fhandle, info);
-       }
 
        if (status == 0)
                status = nfs4_server_capabilities(server, fhandle);
@@ -3254,7 +3252,7 @@ static int
 nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
                  struct iattr *sattr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct rpc_cred *cred = NULL;
        struct nfs4_state *state = NULL;
        struct nfs4_label *label = NULL;
@@ -3871,13 +3869,13 @@ static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
 static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
                u64 cookie, struct page **pages, unsigned int count, int plus)
 {
-       struct inode            *dir = dentry->d_inode;
+       struct inode            *dir = d_inode(dentry);
        struct nfs4_readdir_arg args = {
                .fh = NFS_FH(dir),
                .pages = pages,
                .pgbase = 0,
                .count = count,
-               .bitmask = NFS_SERVER(dentry->d_inode)->attr_bitmask,
+               .bitmask = NFS_SERVER(d_inode(dentry))->attr_bitmask,
                .plus = plus,
        };
        struct nfs4_readdir_res res;
@@ -3914,8 +3912,8 @@ static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
        do {
                err = _nfs4_proc_readdir(dentry, cred, cookie,
                                pages, count, plus);
-               trace_nfs4_readdir(dentry->d_inode, err);
-               err = nfs4_handle_exception(NFS_SERVER(dentry->d_inode), err,
+               trace_nfs4_readdir(d_inode(dentry), err);
+               err = nfs4_handle_exception(NFS_SERVER(d_inode(dentry)), err,
                                &exception);
        } while (exception.retry);
        return err;
@@ -4830,7 +4828,7 @@ nfs4_set_security_label(struct dentry *dentry, const void *buf, size_t buflen)
        struct nfs4_label ilabel, *olabel = NULL;
        struct nfs_fattr fattr;
        struct rpc_cred *cred;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int status;
 
        if (!nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL))
@@ -5670,7 +5668,7 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata)
        data->rpc_status = task->tk_status;
        switch (task->tk_status) {
        case 0:
-               renew_lease(NFS_SERVER(data->ctx->dentry->d_inode),
+               renew_lease(NFS_SERVER(d_inode(data->ctx->dentry)),
                                data->timestamp);
                if (data->arg.new_lock) {
                        data->fl.fl_flags &= ~(FL_SLEEP | FL_ACCESS);
@@ -6112,7 +6110,7 @@ static int nfs4_xattr_set_nfs4_acl(struct dentry *dentry, const char *key,
        if (strcmp(key, "") != 0)
                return -EINVAL;
 
-       return nfs4_proc_set_acl(dentry->d_inode, buf, buflen);
+       return nfs4_proc_set_acl(d_inode(dentry), buf, buflen);
 }
 
 static int nfs4_xattr_get_nfs4_acl(struct dentry *dentry, const char *key,
@@ -6121,7 +6119,7 @@ static int nfs4_xattr_get_nfs4_acl(struct dentry *dentry, const char *key,
        if (strcmp(key, "") != 0)
                return -EINVAL;
 
-       return nfs4_proc_get_acl(dentry->d_inode, buf, buflen);
+       return nfs4_proc_get_acl(d_inode(dentry), buf, buflen);
 }
 
 static size_t nfs4_xattr_list_nfs4_acl(struct dentry *dentry, char *list,
@@ -6130,7 +6128,7 @@ static size_t nfs4_xattr_list_nfs4_acl(struct dentry *dentry, char *list,
 {
        size_t len = sizeof(XATTR_NAME_NFSV4_ACL);
 
-       if (!nfs4_server_supports_acls(NFS_SERVER(dentry->d_inode)))
+       if (!nfs4_server_supports_acls(NFS_SERVER(d_inode(dentry))))
                return 0;
 
        if (list && len <= list_len)
@@ -6158,7 +6156,7 @@ static int nfs4_xattr_get_nfs4_label(struct dentry *dentry, const char *key,
                                   void *buf, size_t buflen, int type)
 {
        if (security_ismaclabel(key))
-               return nfs4_get_security_label(dentry->d_inode, buf, buflen);
+               return nfs4_get_security_label(d_inode(dentry), buf, buflen);
        return -EOPNOTSUPP;
 }
 
@@ -6168,10 +6166,10 @@ static size_t nfs4_xattr_list_nfs4_label(struct dentry *dentry, char *list,
 {
        size_t len = 0;
 
-       if (nfs_server_capable(dentry->d_inode, NFS_CAP_SECURITY_LABEL)) {
-               len = security_inode_listsecurity(dentry->d_inode, NULL, 0);
+       if (nfs_server_capable(d_inode(dentry), NFS_CAP_SECURITY_LABEL)) {
+               len = security_inode_listsecurity(d_inode(dentry), NULL, 0);
                if (list && len <= list_len)
-                       security_inode_listsecurity(dentry->d_inode, list, len);
+                       security_inode_listsecurity(d_inode(dentry), list, len);
        }
        return len;
 }
@@ -7944,6 +7942,8 @@ _nfs4_proc_getdeviceinfo(struct nfs_server *server,
 {
        struct nfs4_getdeviceinfo_args args = {
                .pdev = pdev,
+               .notify_types = NOTIFY_DEVICEID4_CHANGE |
+                       NOTIFY_DEVICEID4_DELETE,
        };
        struct nfs4_getdeviceinfo_res res = {
                .pdev = pdev,
@@ -7958,6 +7958,11 @@ _nfs4_proc_getdeviceinfo(struct nfs_server *server,
 
        dprintk("--> %s\n", __func__);
        status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
+       if (res.notification & ~args.notify_types)
+               dprintk("%s: unsupported notification\n", __func__);
+       if (res.notification != args.notify_types)
+               pdev->nocache = 1;
+
        dprintk("<-- %s status=%d\n", __func__, status);
 
        return status;
index f95e3b58bbc304ae381df2a5f1721d8074789c51..2782cfca22650922e012a4f86a1755e3cca68243 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/nfs_fs.h>
-#include <linux/nfs_idmap.h>
 #include <linux/kthread.h>
 #include <linux/module.h>
 #include <linux/random.h>
@@ -57,6 +56,7 @@
 #include "callback.h"
 #include "delegation.h"
 #include "internal.h"
+#include "nfs4idmap.h"
 #include "nfs4session.h"
 #include "pnfs.h"
 #include "netns.h"
@@ -1902,7 +1902,7 @@ static int nfs4_try_migration(struct nfs_server *server, struct rpc_cred *cred)
                goto out;
        }
 
-       inode = server->super->s_root->d_inode;
+       inode = d_inode(server->super->s_root);
        result = nfs4_proc_get_locations(inode, locations, page, cred);
        if (result) {
                dprintk("<-- %s: failed to retrieve fs_locations: %d\n",
@@ -2021,7 +2021,7 @@ restart:
 
                rcu_read_unlock();
 
-               inode = server->super->s_root->d_inode;
+               inode = d_inode(server->super->s_root);
                status = nfs4_proc_fsid_present(inode, cred);
                if (status != -NFS4ERR_MOVED)
                        goto restart;   /* wasn't this one */
index 75090feeafade9c790bb4bf0d84c8546a46819a0..6fb7cb6b3f4b038398e3c8ef1681cc4d274636a5 100644 (file)
@@ -3,12 +3,12 @@
  */
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/nfs_idmap.h>
 #include <linux/nfs4_mount.h>
 #include <linux/nfs_fs.h>
 #include "delegation.h"
 #include "internal.h"
 #include "nfs4_fs.h"
+#include "nfs4idmap.h"
 #include "dns_resolve.h"
 #include "pnfs.h"
 #include "nfs.h"
@@ -91,10 +91,11 @@ static void nfs4_evict_inode(struct inode *inode)
 {
        truncate_inode_pages_final(&inode->i_data);
        clear_inode(inode);
-       pnfs_return_layout(inode);
-       pnfs_destroy_layout(NFS_I(inode));
        /* If we are holding a delegation, return it! */
        nfs_inode_return_delegation_noreclaim(inode);
+       /* Note that above delegreturn would trigger pnfs return-on-close */
+       pnfs_return_layout(inode);
+       pnfs_destroy_layout(NFS_I(inode));
        /* First call standard NFS clear_inode() code */
        nfs_clear_inode(inode);
 }
index b6ebe7e445f63d34c5bb1d8cc6ef587867cc6813..0fbd3ab1be222e9d3c47a7c96c16e11955724ad0 100644 (file)
@@ -6,10 +6,10 @@
  * Copyright (c) 2006 Trond Myklebust <Trond.Myklebust@netapp.com>
  */
 #include <linux/sysctl.h>
-#include <linux/nfs_idmap.h>
 #include <linux/nfs_fs.h>
 
 #include "nfs4_fs.h"
+#include "nfs4idmap.h"
 #include "callback.h"
 
 static const int nfs_set_port_min = 0;
index 1c32adbe728df548bcc92ee175b4d6061b3b4489..470af1a78becf206c6e2de9aae89b61b35eb8452 100644 (file)
@@ -418,7 +418,7 @@ DECLARE_EVENT_CLASS(nfs4_open_event,
                                __entry->fileid = 0;
                                __entry->fhandle = 0;
                        }
-                       __entry->dir = NFS_FILEID(ctx->dentry->d_parent->d_inode);
+                       __entry->dir = NFS_FILEID(d_inode(ctx->dentry->d_parent));
                        __assign_str(name, ctx->dentry->d_name.name);
                ),
 
@@ -1110,7 +1110,7 @@ TRACE_EVENT(nfs4_layoutget,
                ),
 
                TP_fast_assign(
-                       const struct inode *inode = ctx->dentry->d_inode;
+                       const struct inode *inode = d_inode(ctx->dentry);
                        __entry->dev = inode->i_sb->s_dev;
                        __entry->fileid = NFS_FILEID(inode);
                        __entry->fhandle = nfs_fhandle_hash(NFS_FH(inode));
index 5c399ec41079687791d2fb668d5f6543ce374a2f..0aea97841d3038b56056d0d7fcd0dcddb11f584e 100644 (file)
 #include <linux/nfs.h>
 #include <linux/nfs4.h>
 #include <linux/nfs_fs.h>
-#include <linux/nfs_idmap.h>
 
 #include "nfs4_fs.h"
 #include "internal.h"
+#include "nfs4idmap.h"
 #include "nfs4session.h"
 #include "pnfs.h"
 #include "netns.h"
@@ -1920,7 +1920,7 @@ encode_getdeviceinfo(struct xdr_stream *xdr,
 
        p = reserve_space(xdr, 4 + 4);
        *p++ = cpu_to_be32(1);                  /* bitmap length */
-       *p++ = cpu_to_be32(NOTIFY_DEVICEID4_CHANGE | NOTIFY_DEVICEID4_DELETE);
+       *p++ = cpu_to_be32(args->notify_types);
 }
 
 static void
@@ -5753,8 +5753,9 @@ out_overflow:
 
 #if defined(CONFIG_NFS_V4_1)
 static int decode_getdeviceinfo(struct xdr_stream *xdr,
-                               struct pnfs_device *pdev)
+                               struct nfs4_getdeviceinfo_res *res)
 {
+       struct pnfs_device *pdev = res->pdev;
        __be32 *p;
        uint32_t len, type;
        int status;
@@ -5802,12 +5803,7 @@ static int decode_getdeviceinfo(struct xdr_stream *xdr,
                if (unlikely(!p))
                        goto out_overflow;
 
-               if (be32_to_cpup(p++) &
-                   ~(NOTIFY_DEVICEID4_CHANGE | NOTIFY_DEVICEID4_DELETE)) {
-                       dprintk("%s: unsupported notification\n",
-                               __func__);
-               }
-
+               res->notification = be32_to_cpup(p++);
                for (i = 1; i < len; i++) {
                        if (be32_to_cpup(p++)) {
                                dprintk("%s: unsupported notification\n",
@@ -7061,7 +7057,7 @@ static int nfs4_xdr_dec_getdeviceinfo(struct rpc_rqst *rqstp,
        status = decode_sequence(xdr, &res->seq_res, rqstp);
        if (status != 0)
                goto out;
-       status = decode_getdeviceinfo(xdr, res->pdev);
+       status = decode_getdeviceinfo(xdr, res);
 out:
        return status;
 }
@@ -7365,6 +7361,11 @@ nfs4_stat_to_errno(int stat)
        .p_name   = #proc,                                      \
 }
 
+#define STUB(proc)             \
+[NFSPROC4_CLNT_##proc] = {     \
+       .p_name = #proc,        \
+}
+
 struct rpc_procinfo    nfs4_procedures[] = {
        PROC(READ,              enc_read,               dec_read),
        PROC(WRITE,             enc_write,              dec_write),
@@ -7417,6 +7418,7 @@ struct rpc_procinfo       nfs4_procedures[] = {
        PROC(SECINFO_NO_NAME,   enc_secinfo_no_name,    dec_secinfo_no_name),
        PROC(TEST_STATEID,      enc_test_stateid,       dec_test_stateid),
        PROC(FREE_STATEID,      enc_free_stateid,       dec_free_stateid),
+       STUB(GETDEVICELIST),
        PROC(BIND_CONN_TO_SESSION,
                        enc_bind_conn_to_session, dec_bind_conn_to_session),
        PROC(DESTROY_CLIENTID,  enc_destroy_clientid,   dec_destroy_clientid),
index 4eb0aead69b6c954de19f64099fdd9268f36350d..c74f7af23d77a756b1f785fa78723c00c26a4312 100644 (file)
@@ -7,3 +7,6 @@
 
 #define CREATE_TRACE_POINTS
 #include "nfstrace.h"
+
+EXPORT_TRACEPOINT_SYMBOL_GPL(nfs_fsync_enter);
+EXPORT_TRACEPOINT_SYMBOL_GPL(nfs_fsync_exit);
index 24e1d7403c0be241fa90dd6645f86dddadf0add9..5aaed363556a66e7bd5bb43d4619d037108f5421 100644 (file)
@@ -57,7 +57,7 @@ objio_free_deviceid_node(struct nfs4_deviceid_node *d)
 
        dprintk("%s: free od=%p\n", __func__, de->od.od);
        osduld_put_device(de->od.od);
-       kfree(de);
+       kfree_rcu(d, rcu);
 }
 
 struct objio_segment {
@@ -637,6 +637,8 @@ static struct pnfs_layoutdriver_type objlayout_type = {
        .pg_read_ops             = &objio_pg_read_ops,
        .pg_write_ops            = &objio_pg_write_ops,
 
+       .sync                    = pnfs_generic_sync,
+
        .free_deviceid_node      = objio_free_deviceid_node,
 
        .encode_layoutcommit     = objlayout_encode_layoutcommit,
index d57190a0d533134c2376c6556a8102e88996dd18..282b3936951060a2c8a6216c4c690e166a5fcb8d 100644 (file)
@@ -938,7 +938,7 @@ static bool nfs_can_coalesce_requests(struct nfs_page *prev,
        if (prev) {
                if (!nfs_match_open_context(req->wb_context, prev->wb_context))
                        return false;
-               flctx = req->wb_context->dentry->d_inode->i_flctx;
+               flctx = d_inode(req->wb_context->dentry)->i_flctx;
                if (flctx != NULL &&
                    !(list_empty_careful(&flctx->flc_posix) &&
                      list_empty_careful(&flctx->flc_flock)) &&
index 4f802b02fbb9b0c6fc61912be044f6cef94acd32..230606243be6ad079733e583d173b14d3baeda55 100644 (file)
@@ -1090,6 +1090,7 @@ bool pnfs_roc(struct inode *ino)
        pnfs_get_layout_hdr(lo); /* matched in pnfs_roc_release */
        spin_unlock(&ino->i_lock);
        pnfs_free_lseg_list(&tmp_list);
+       pnfs_layoutcommit_inode(ino, true);
        return true;
 
 out_noroc:
@@ -1104,8 +1105,10 @@ out_noroc:
                }
        }
        spin_unlock(&ino->i_lock);
-       if (layoutreturn)
+       if (layoutreturn) {
+               pnfs_layoutcommit_inode(ino, true);
                pnfs_send_layoutreturn(lo, stateid, IOMODE_ANY, true);
+       }
        return false;
 }
 
@@ -1841,7 +1844,8 @@ void pnfs_ld_write_done(struct nfs_pgio_header *hdr)
 {
        trace_nfs4_pnfs_write(hdr, hdr->pnfs_error);
        if (!hdr->pnfs_error) {
-               pnfs_set_layoutcommit(hdr);
+               pnfs_set_layoutcommit(hdr->inode, hdr->lseg,
+                               hdr->mds_offset + hdr->res.count);
                hdr->mds_ops->rpc_call_done(&hdr->task, hdr);
        } else
                pnfs_ld_handle_write_error(hdr);
@@ -1902,7 +1906,6 @@ static void pnfs_writehdr_free(struct nfs_pgio_header *hdr)
        pnfs_put_lseg(hdr->lseg);
        nfs_pgio_header_free(hdr);
 }
-EXPORT_SYMBOL_GPL(pnfs_writehdr_free);
 
 int
 pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
@@ -2032,7 +2035,6 @@ static void pnfs_readhdr_free(struct nfs_pgio_header *hdr)
        pnfs_put_lseg(hdr->lseg);
        nfs_pgio_header_free(hdr);
 }
-EXPORT_SYMBOL_GPL(pnfs_readhdr_free);
 
 int
 pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
@@ -2099,64 +2101,34 @@ void pnfs_set_lo_fail(struct pnfs_layout_segment *lseg)
 EXPORT_SYMBOL_GPL(pnfs_set_lo_fail);
 
 void
-pnfs_set_layoutcommit(struct nfs_pgio_header *hdr)
+pnfs_set_layoutcommit(struct inode *inode, struct pnfs_layout_segment *lseg,
+               loff_t end_pos)
 {
-       struct inode *inode = hdr->inode;
        struct nfs_inode *nfsi = NFS_I(inode);
-       loff_t end_pos = hdr->mds_offset + hdr->res.count;
        bool mark_as_dirty = false;
 
        spin_lock(&inode->i_lock);
        if (!test_and_set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) {
-               mark_as_dirty = true;
-               dprintk("%s: Set layoutcommit for inode %lu ",
-                       __func__, inode->i_ino);
-       }
-       if (!test_and_set_bit(NFS_LSEG_LAYOUTCOMMIT, &hdr->lseg->pls_flags)) {
-               /* references matched in nfs4_layoutcommit_release */
-               pnfs_get_lseg(hdr->lseg);
-       }
-       if (end_pos > nfsi->layout->plh_lwb)
                nfsi->layout->plh_lwb = end_pos;
-       spin_unlock(&inode->i_lock);
-       dprintk("%s: lseg %p end_pos %llu\n",
-               __func__, hdr->lseg, nfsi->layout->plh_lwb);
-
-       /* if pnfs_layoutcommit_inode() runs between inode locks, the next one
-        * will be a noop because NFS_INO_LAYOUTCOMMIT will not be set */
-       if (mark_as_dirty)
-               mark_inode_dirty_sync(inode);
-}
-EXPORT_SYMBOL_GPL(pnfs_set_layoutcommit);
-
-void pnfs_commit_set_layoutcommit(struct nfs_commit_data *data)
-{
-       struct inode *inode = data->inode;
-       struct nfs_inode *nfsi = NFS_I(inode);
-       bool mark_as_dirty = false;
-
-       spin_lock(&inode->i_lock);
-       if (!test_and_set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) {
                mark_as_dirty = true;
                dprintk("%s: Set layoutcommit for inode %lu ",
                        __func__, inode->i_ino);
-       }
-       if (!test_and_set_bit(NFS_LSEG_LAYOUTCOMMIT, &data->lseg->pls_flags)) {
+       } else if (end_pos > nfsi->layout->plh_lwb)
+               nfsi->layout->plh_lwb = end_pos;
+       if (!test_and_set_bit(NFS_LSEG_LAYOUTCOMMIT, &lseg->pls_flags)) {
                /* references matched in nfs4_layoutcommit_release */
-               pnfs_get_lseg(data->lseg);
+               pnfs_get_lseg(lseg);
        }
-       if (data->lwb > nfsi->layout->plh_lwb)
-               nfsi->layout->plh_lwb = data->lwb;
        spin_unlock(&inode->i_lock);
        dprintk("%s: lseg %p end_pos %llu\n",
-               __func__, data->lseg, nfsi->layout->plh_lwb);
+               __func__, lseg, nfsi->layout->plh_lwb);
 
        /* if pnfs_layoutcommit_inode() runs between inode locks, the next one
         * will be a noop because NFS_INO_LAYOUTCOMMIT will not be set */
        if (mark_as_dirty)
                mark_inode_dirty_sync(inode);
 }
-EXPORT_SYMBOL_GPL(pnfs_commit_set_layoutcommit);
+EXPORT_SYMBOL_GPL(pnfs_set_layoutcommit);
 
 void pnfs_cleanup_layoutcommit(struct nfs4_layoutcommit_data *data)
 {
@@ -2216,7 +2188,6 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync)
        pnfs_list_write_lseg(inode, &data->lseg_list);
 
        end_pos = nfsi->layout->plh_lwb;
-       nfsi->layout->plh_lwb = 0;
 
        nfs4_stateid_copy(&data->args.stateid, &nfsi->layout->plh_stateid);
        spin_unlock(&inode->i_lock);
@@ -2233,11 +2204,11 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync)
                status = ld->prepare_layoutcommit(&data->args);
                if (status) {
                        spin_lock(&inode->i_lock);
-                       if (end_pos < nfsi->layout->plh_lwb)
+                       set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags);
+                       if (end_pos > nfsi->layout->plh_lwb)
                                nfsi->layout->plh_lwb = end_pos;
                        spin_unlock(&inode->i_lock);
                        put_rpccred(data->cred);
-                       set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags);
                        goto clear_layoutcommitting;
                }
        }
@@ -2258,6 +2229,13 @@ clear_layoutcommitting:
 }
 EXPORT_SYMBOL_GPL(pnfs_layoutcommit_inode);
 
+int
+pnfs_generic_sync(struct inode *inode, bool datasync)
+{
+       return pnfs_layoutcommit_inode(inode, true);
+}
+EXPORT_SYMBOL_GPL(pnfs_generic_sync);
+
 struct nfs4_threshold *pnfs_mdsthreshold_alloc(void)
 {
        struct nfs4_threshold *thp;
index 635f0865671cf38b27eea4a49261c9405a4a4731..1e6308f82fc3d5887de850e72226233e4f2138d2 100644 (file)
@@ -155,6 +155,8 @@ struct pnfs_layoutdriver_type {
                               int how,
                               struct nfs_commit_info *cinfo);
 
+       int (*sync)(struct inode *inode, bool datasync);
+
        /*
         * Return PNFS_ATTEMPTED to indicate the layout code has attempted
         * I/O, else return PNFS_NOT_ATTEMPTED to fall back to normal NFS
@@ -203,6 +205,7 @@ struct pnfs_device {
        struct page **pages;
        unsigned int  pgbase;
        unsigned int  pglen;    /* reply buffer length */
+       unsigned char nocache : 1;/* May not be cached */
 };
 
 #define NFS4_PNFS_GETDEVLIST_MAXNUM 16
@@ -263,10 +266,11 @@ bool pnfs_roc(struct inode *ino);
 void pnfs_roc_release(struct inode *ino);
 void pnfs_roc_set_barrier(struct inode *ino, u32 barrier);
 bool pnfs_roc_drain(struct inode *ino, u32 *barrier, struct rpc_task *task);
-void pnfs_set_layoutcommit(struct nfs_pgio_header *);
-void pnfs_commit_set_layoutcommit(struct nfs_commit_data *data);
+void pnfs_set_layoutcommit(struct inode *, struct pnfs_layout_segment *, loff_t);
 void pnfs_cleanup_layoutcommit(struct nfs4_layoutcommit_data *data);
 int pnfs_layoutcommit_inode(struct inode *inode, bool sync);
+int pnfs_generic_sync(struct inode *inode, bool datasync);
+int pnfs_nfs_generic_sync(struct inode *inode, bool datasync);
 int _pnfs_return_layout(struct inode *);
 int pnfs_commit_and_return_layout(struct inode *);
 void pnfs_ld_write_done(struct nfs_pgio_header *);
@@ -291,6 +295,7 @@ void pnfs_error_mark_layout_for_return(struct inode *inode,
 enum {
        NFS_DEVICEID_INVALID = 0,       /* set when MDS clientid recalled */
        NFS_DEVICEID_UNAVAILABLE,       /* device temporarily unavailable */
+       NFS_DEVICEID_NOCACHE,           /* device may not be cached */
 };
 
 /* pnfs_dev.c */
@@ -302,6 +307,7 @@ struct nfs4_deviceid_node {
        unsigned long                   flags;
        unsigned long                   timestamp_unavailable;
        struct nfs4_deviceid            deviceid;
+       struct rcu_head                 rcu;
        atomic_t                        ref;
 };
 
@@ -426,7 +432,7 @@ static inline bool
 pnfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg,
                         struct nfs_commit_info *cinfo, u32 ds_commit_idx)
 {
-       struct inode *inode = req->wb_context->dentry->d_inode;
+       struct inode *inode = d_inode(req->wb_context->dentry);
        struct pnfs_layoutdriver_type *ld = NFS_SERVER(inode)->pnfs_curr_ld;
 
        if (lseg == NULL || ld->mark_request_commit == NULL)
@@ -438,7 +444,7 @@ pnfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg,
 static inline bool
 pnfs_clear_request_commit(struct nfs_page *req, struct nfs_commit_info *cinfo)
 {
-       struct inode *inode = req->wb_context->dentry->d_inode;
+       struct inode *inode = d_inode(req->wb_context->dentry);
        struct pnfs_layoutdriver_type *ld = NFS_SERVER(inode)->pnfs_curr_ld;
 
        if (ld == NULL || ld->clear_request_commit == NULL)
@@ -486,6 +492,14 @@ pnfs_ld_read_whole_page(struct inode *inode)
        return NFS_SERVER(inode)->pnfs_curr_ld->flags & PNFS_READ_WHOLE_PAGE;
 }
 
+static inline int
+pnfs_sync_inode(struct inode *inode, bool datasync)
+{
+       if (!pnfs_enabled_sb(NFS_SERVER(inode)))
+               return 0;
+       return NFS_SERVER(inode)->pnfs_curr_ld->sync(inode, datasync);
+}
+
 static inline bool
 pnfs_layoutcommit_outstanding(struct inode *inode)
 {
@@ -568,6 +582,12 @@ pnfs_ld_read_whole_page(struct inode *inode)
        return false;
 }
 
+static inline int
+pnfs_sync_inode(struct inode *inode, bool datasync)
+{
+       return 0;
+}
+
 static inline bool
 pnfs_roc(struct inode *ino)
 {
index aa2ec00151839f1519a2c7e0ab65509d9f2cfba3..2961fcd7a2df9292bf4f611287c2e48bdfe31ad2 100644 (file)
@@ -149,6 +149,8 @@ nfs4_get_device_info(struct nfs_server *server,
         */
        d = server->pnfs_curr_ld->alloc_deviceid_node(server, pdev,
                        gfp_flags);
+       if (d && pdev->nocache)
+               set_bit(NFS_DEVICEID_NOCACHE, &d->flags);
 
 out_free_pages:
        for (i = 0; i < max_pages; i++)
@@ -175,8 +177,8 @@ __nfs4_find_get_deviceid(struct nfs_server *server,
        rcu_read_lock();
        d = _lookup_deviceid(server->pnfs_curr_ld, server->nfs_client, id,
                        hash);
-       if (d != NULL)
-               atomic_inc(&d->ref);
+       if (d != NULL && !atomic_inc_not_zero(&d->ref))
+               d = NULL;
        rcu_read_unlock();
        return d;
 }
@@ -235,12 +237,11 @@ nfs4_delete_deviceid(const struct pnfs_layoutdriver_type *ld,
                return;
        }
        hlist_del_init_rcu(&d->node);
+       clear_bit(NFS_DEVICEID_NOCACHE, &d->flags);
        spin_unlock(&nfs4_deviceid_lock);
-       synchronize_rcu();
 
        /* balance the initial ref set in pnfs_insert_deviceid */
-       if (atomic_dec_and_test(&d->ref))
-               d->ld->free_deviceid_node(d);
+       nfs4_put_deviceid_node(d);
 }
 EXPORT_SYMBOL_GPL(nfs4_delete_deviceid);
 
@@ -271,6 +272,11 @@ EXPORT_SYMBOL_GPL(nfs4_init_deviceid_node);
 bool
 nfs4_put_deviceid_node(struct nfs4_deviceid_node *d)
 {
+       if (test_bit(NFS_DEVICEID_NOCACHE, &d->flags)) {
+               if (atomic_add_unless(&d->ref, -1, 2))
+                       return false;
+               nfs4_delete_deviceid(d->ld, d->nfs_client, &d->deviceid);
+       }
        if (!atomic_dec_and_test(&d->ref))
                return false;
        d->ld->free_deviceid_node(d);
@@ -314,6 +320,7 @@ _deviceid_purge_client(const struct nfs_client *clp, long hash)
                if (d->nfs_client == clp && atomic_read(&d->ref)) {
                        hlist_del_init_rcu(&d->node);
                        hlist_add_head(&d->tmpnode, &tmp);
+                       clear_bit(NFS_DEVICEID_NOCACHE, &d->flags);
                }
        rcu_read_unlock();
        spin_unlock(&nfs4_deviceid_lock);
@@ -321,12 +328,10 @@ _deviceid_purge_client(const struct nfs_client *clp, long hash)
        if (hlist_empty(&tmp))
                return;
 
-       synchronize_rcu();
        while (!hlist_empty(&tmp)) {
                d = hlist_entry(tmp.first, struct nfs4_deviceid_node, tmpnode);
                hlist_del(&d->tmpnode);
-               if (atomic_dec_and_test(&d->ref))
-                       d->ld->free_deviceid_node(d);
+               nfs4_put_deviceid_node(d);
        }
 }
 
index 54e36b38fb5f89310287635e0838601ad07cf34a..f37e25b6311c83ac890508207be3e7d6cdc7bdda 100644 (file)
@@ -561,7 +561,7 @@ static bool load_v3_ds_connect(void)
        return(get_v3_ds_connect != NULL);
 }
 
-void __exit nfs4_pnfs_v3_ds_connect_unload(void)
+void nfs4_pnfs_v3_ds_connect_unload(void)
 {
        if (get_v3_ds_connect) {
                symbol_put(nfs3_set_ds_client);
@@ -868,3 +868,13 @@ pnfs_layout_mark_request_commit(struct nfs_page *req,
        nfs_request_add_commit_list(req, list, cinfo);
 }
 EXPORT_SYMBOL_GPL(pnfs_layout_mark_request_commit);
+
+int
+pnfs_nfs_generic_sync(struct inode *inode, bool datasync)
+{
+       if (datasync)
+               return 0;
+       return pnfs_layoutcommit_inode(inode, true);
+}
+EXPORT_SYMBOL_GPL(pnfs_nfs_generic_sync);
+
index c63189acd0523cf733ab494dc85c1acf0cdb8f33..b417bbcd970465069afcd820a414b19e4493e7e7 100644 (file)
@@ -118,7 +118,7 @@ static int
 nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
                 struct iattr *sattr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct nfs_sattrargs    arg = { 
                .fh     = NFS_FH(inode),
                .sattr  = sattr
@@ -487,7 +487,7 @@ static int
 nfs_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
                 u64 cookie, struct page **pages, unsigned int count, int plus)
 {
-       struct inode            *dir = dentry->d_inode;
+       struct inode            *dir = d_inode(dentry);
        struct nfs_readdirargs  arg = {
                .fh             = NFS_FH(dir),
                .cookie         = cookie,
index b8f5c63f77b2780b51d410ae4d3928ddf2bd1a76..ae0ff7a11b40339a728ca819283400c7f5e25a42 100644 (file)
@@ -117,7 +117,7 @@ int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
 
 static void nfs_readpage_release(struct nfs_page *req)
 {
-       struct inode *inode = req->wb_context->dentry->d_inode;
+       struct inode *inode = d_inode(req->wb_context->dentry);
 
        dprintk("NFS: read done (%s/%llu %d@%lld)\n", inode->i_sb->s_id,
                (unsigned long long)NFS_FILEID(inode), req->wb_bytes,
@@ -284,7 +284,7 @@ int nfs_readpage(struct file *file, struct page *page)
        dprintk("NFS: nfs_readpage (%p %ld@%lu)\n",
                page, PAGE_CACHE_SIZE, page_file_index(page));
        nfs_inc_stats(inode, NFSIOS_VFSREADPAGE);
-       nfs_inc_stats(inode, NFSIOS_READPAGES);
+       nfs_add_stats(inode, NFSIOS_READPAGES, 1);
 
        /*
         * Try to flush any pending writes to the file..
index 322b2de02988fa6479c2d2831a5e5d70dfdad7c9..f175b833b6ba75b22bced1f9d013ad670caed82d 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/seq_file.h>
 #include <linux/mount.h>
 #include <linux/namei.h>
-#include <linux/nfs_idmap.h>
 #include <linux/vfs.h>
 #include <linux/inet.h>
 #include <linux/in6.h>
@@ -433,7 +432,7 @@ int nfs_statfs(struct dentry *dentry, struct kstatfs *buf)
        struct nfs_server *server = NFS_SB(dentry->d_sb);
        unsigned char blockbits;
        unsigned long blockres;
-       struct nfs_fh *fh = NFS_FH(dentry->d_inode);
+       struct nfs_fh *fh = NFS_FH(d_inode(dentry));
        struct nfs_fsstat res;
        int error = -ENOMEM;
 
@@ -447,7 +446,7 @@ int nfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 
                pd_dentry = dget_parent(dentry);
                if (pd_dentry != NULL) {
-                       nfs_zap_caches(pd_dentry->d_inode);
+                       nfs_zap_caches(d_inode(pd_dentry));
                        dput(pd_dentry);
                }
        }
@@ -2193,7 +2192,7 @@ nfs_compare_remount_data(struct nfs_server *nfss,
            data->version != nfss->nfs_client->rpc_ops->version ||
            data->minorversion != nfss->nfs_client->cl_minorversion ||
            data->retrans != nfss->client->cl_timeout->to_retries ||
-           data->selected_flavor != nfss->client->cl_auth->au_flavor ||
+           !nfs_auth_info_match(&data->auth_info, nfss->client->cl_auth->au_flavor) ||
            data->acregmin != nfss->acregmin / HZ ||
            data->acregmax != nfss->acregmax / HZ ||
            data->acdirmin != nfss->acdirmin / HZ ||
@@ -2241,7 +2240,6 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data)
        data->wsize = nfss->wsize;
        data->retrans = nfss->client->cl_timeout->to_retries;
        data->selected_flavor = nfss->client->cl_auth->au_flavor;
-       data->auth_info = nfss->auth_info;
        data->acregmin = nfss->acregmin / HZ;
        data->acregmax = nfss->acregmax / HZ;
        data->acdirmin = nfss->acdirmin / HZ;
@@ -2526,7 +2524,7 @@ int nfs_clone_sb_security(struct super_block *s, struct dentry *mntroot,
                          struct nfs_mount_info *mount_info)
 {
        /* clone any lsm security options from the parent to the new sb */
-       if (mntroot->d_inode->i_op != NFS_SB(s)->nfs_client->rpc_ops->dir_inode_ops)
+       if (d_inode(mntroot)->i_op != NFS_SB(s)->nfs_client->rpc_ops->dir_inode_ops)
                return -ESTALE;
        return security_sb_clone_mnt_opts(mount_info->cloned->sb, s);
 }
index 05c9e02f4153e340d94035bfdef6cc8db34b5a06..2d56200655fe600ae73d11c382af5815285fab48 100644 (file)
@@ -45,7 +45,7 @@ error:
 
 static void *nfs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct page *page;
        void *err;
 
index de54129336c6d095984fd34c548491a2916e902b..fa538b2ba25183c46aaf62b96c35a647a829479f 100644 (file)
@@ -143,7 +143,7 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n
                nfs_free_dname(data);
                ret = nfs_copy_dname(alias, data);
                spin_lock(&alias->d_lock);
-               if (ret == 0 && alias->d_inode != NULL &&
+               if (ret == 0 && d_really_is_positive(alias) &&
                    !(alias->d_flags & DCACHE_NFSFS_RENAMED)) {
                        devname_garbage = alias->d_fsdata;
                        alias->d_fsdata = data;
@@ -190,7 +190,7 @@ static int nfs_call_unlink(struct dentry *dentry, struct nfs_unlinkdata *data)
        parent = dget_parent(dentry);
        if (parent == NULL)
                goto out_free;
-       dir = parent->d_inode;
+       dir = d_inode(parent);
        /* Non-exclusive lock protects against concurrent lookup() calls */
        spin_lock(&dir->i_lock);
        if (atomic_inc_not_zero(&NFS_I(dir)->silly_count) == 0) {
@@ -210,21 +210,21 @@ out_free:
 
 void nfs_wait_on_sillyrename(struct dentry *dentry)
 {
-       struct nfs_inode *nfsi = NFS_I(dentry->d_inode);
+       struct nfs_inode *nfsi = NFS_I(d_inode(dentry));
 
        wait_event(nfsi->waitqueue, atomic_read(&nfsi->silly_count) <= 1);
 }
 
 void nfs_block_sillyrename(struct dentry *dentry)
 {
-       struct nfs_inode *nfsi = NFS_I(dentry->d_inode);
+       struct nfs_inode *nfsi = NFS_I(d_inode(dentry));
 
        wait_event(nfsi->waitqueue, atomic_cmpxchg(&nfsi->silly_count, 1, 0) == 1);
 }
 
 void nfs_unblock_sillyrename(struct dentry *dentry)
 {
-       struct inode *dir = dentry->d_inode;
+       struct inode *dir = d_inode(dentry);
        struct nfs_inode *nfsi = NFS_I(dir);
        struct nfs_unlinkdata *data;
 
@@ -367,8 +367,8 @@ static void nfs_async_rename_release(void *calldata)
        struct nfs_renamedata   *data = calldata;
        struct super_block *sb = data->old_dir->i_sb;
 
-       if (data->old_dentry->d_inode)
-               nfs_mark_for_revalidate(data->old_dentry->d_inode);
+       if (d_really_is_positive(data->old_dentry))
+               nfs_mark_for_revalidate(d_inode(data->old_dentry));
 
        dput(data->old_dentry);
        dput(data->new_dentry);
@@ -529,10 +529,10 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry)
        if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
                goto out;
 
-       fileid = NFS_FILEID(dentry->d_inode);
+       fileid = NFS_FILEID(d_inode(dentry));
 
        /* Return delegation in anticipation of the rename */
-       NFS_PROTO(dentry->d_inode)->return_delegation(dentry->d_inode);
+       NFS_PROTO(d_inode(dentry))->return_delegation(d_inode(dentry));
 
        sdentry = NULL;
        do {
@@ -554,7 +554,7 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry)
                 */
                if (IS_ERR(sdentry))
                        goto out;
-       } while (sdentry->d_inode != NULL); /* need negative lookup */
+       } while (d_inode(sdentry) != NULL); /* need negative lookup */
 
        /* queue unlink first. Can't do this from rpc_release as it
         * has to allocate memory
index 759931088094940069eecaf4605af0d9f6742581..d12a4be613a5ced58599f8095822f4659b32f9a4 100644 (file)
@@ -580,7 +580,7 @@ static int nfs_do_writepage(struct page *page, struct writeback_control *wbc, st
        int ret;
 
        nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGE);
-       nfs_inc_stats(inode, NFSIOS_WRITEPAGES);
+       nfs_add_stats(inode, NFSIOS_WRITEPAGES, 1);
 
        nfs_pageio_cond_complete(pgio, page_file_index(page));
        ret = nfs_page_async_flush(pgio, page, wbc->sync_mode == WB_SYNC_NONE);
@@ -702,7 +702,7 @@ static void nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
  */
 static void nfs_inode_remove_request(struct nfs_page *req)
 {
-       struct inode *inode = req->wb_context->dentry->d_inode;
+       struct inode *inode = d_inode(req->wb_context->dentry);
        struct nfs_inode *nfsi = NFS_I(inode);
        struct nfs_page *head;
 
@@ -861,7 +861,7 @@ static void
 nfs_clear_request_commit(struct nfs_page *req)
 {
        if (test_bit(PG_CLEAN, &req->wb_flags)) {
-               struct inode *inode = req->wb_context->dentry->d_inode;
+               struct inode *inode = d_inode(req->wb_context->dentry);
                struct nfs_commit_info cinfo;
 
                nfs_init_cinfo_from_inode(&cinfo, inode);
@@ -1591,7 +1591,7 @@ void nfs_init_commit(struct nfs_commit_data *data,
                     struct nfs_commit_info *cinfo)
 {
        struct nfs_page *first = nfs_list_entry(head->next);
-       struct inode *inode = first->wb_context->dentry->d_inode;
+       struct inode *inode = d_inode(first->wb_context->dentry);
 
        /* Set up the RPC argument and reply structs
         * NB: take care not to mess about with data->commit et al. */
@@ -1690,7 +1690,7 @@ static void nfs_commit_release_pages(struct nfs_commit_data *data)
 
                dprintk("NFS:       commit (%s/%llu %d@%lld)",
                        req->wb_context->dentry->d_sb->s_id,
-                       (unsigned long long)NFS_FILEID(req->wb_context->dentry->d_inode),
+                       (unsigned long long)NFS_FILEID(d_inode(req->wb_context->dentry)),
                        req->wb_bytes,
                        (long long)req_offset(req));
                if (status < 0) {
@@ -1840,17 +1840,16 @@ EXPORT_SYMBOL_GPL(nfs_write_inode);
  */
 int nfs_wb_all(struct inode *inode)
 {
-       struct writeback_control wbc = {
-               .sync_mode = WB_SYNC_ALL,
-               .nr_to_write = LONG_MAX,
-               .range_start = 0,
-               .range_end = LLONG_MAX,
-       };
        int ret;
 
        trace_nfs_writeback_inode_enter(inode);
 
-       ret = sync_inode(inode, &wbc);
+       ret = filemap_write_and_wait(inode->i_mapping);
+       if (!ret) {
+               ret = nfs_commit_inode(inode, FLUSH_SYNC);
+               if (!ret)
+                       pnfs_sync_inode(inode, true);
+       }
 
        trace_nfs_writeback_inode_exit(inode, ret);
        return ret;
index fc2d108f5272abe6a0c1a640744a45aaff38015c..a0b77fc1bd3944e9f966705518d4138cd2e4f0e3 100644 (file)
@@ -108,7 +108,7 @@ config NFSD_V4_SECURITY_LABEL
 
 config NFSD_FAULT_INJECTION
        bool "NFS server manual fault injection"
-       depends on NFSD_V4 && DEBUG_KERNEL
+       depends on NFSD_V4 && DEBUG_KERNEL && DEBUG_FS
        help
          This option enables support for manually injecting faults
          into the NFS server.  This is intended to be used for
index c3e3b6e55ae28d01ee4922b98b021dfd45151e02..f79521a597471ed6286fd63c5e483860bfcfbe80 100644 (file)
@@ -599,7 +599,7 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
                                goto out4;
                }
 
-               err = check_export(exp.ex_path.dentry->d_inode, &exp.ex_flags,
+               err = check_export(d_inode(exp.ex_path.dentry), &exp.ex_flags,
                                   exp.ex_uuid);
                if (err)
                        goto out4;
@@ -691,8 +691,7 @@ static int svc_export_match(struct cache_head *a, struct cache_head *b)
        struct svc_export *orig = container_of(a, struct svc_export, h);
        struct svc_export *new = container_of(b, struct svc_export, h);
        return orig->ex_client == new->ex_client &&
-               orig->ex_path.dentry == new->ex_path.dentry &&
-               orig->ex_path.mnt == new->ex_path.mnt;
+               path_equal(&orig->ex_path, &new->ex_path);
 }
 
 static void svc_export_init(struct cache_head *cnew, struct cache_head *citem)
@@ -891,7 +890,7 @@ exp_rootfh(struct net *net, struct auth_domain *clp, char *name,
                printk("nfsd: exp_rootfh path not found %s", name);
                return err;
        }
-       inode = path.dentry->d_inode;
+       inode = d_inode(path.dentry);
 
        dprintk("nfsd: exp_rootfh(%s [%p] %s:%s/%ld)\n",
                 name, path.dentry, clp->name,
@@ -1159,6 +1158,7 @@ static struct flags {
        { NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}},
        { NFSEXP_NOAUTHNLM, {"insecure_locks", ""}},
        { NFSEXP_V4ROOT, {"v4root", ""}},
+       { NFSEXP_PNFS, {"pnfs", ""}},
        { 0, {"", ""}}
 };
 
index ac54ea60b3f690c1803a3abd91b38d1250a06f54..d54701f6dc7873440b2c11d375b96323484ba259 100644 (file)
@@ -42,7 +42,7 @@ static __be32 nfsacld_proc_getacl(struct svc_rqst * rqstp,
        if (nfserr)
                RETURN_STATUS(nfserr);
 
-       inode = fh->fh_dentry->d_inode;
+       inode = d_inode(fh->fh_dentry);
 
        if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
                RETURN_STATUS(nfserr_inval);
@@ -103,7 +103,7 @@ static __be32 nfsacld_proc_setacl(struct svc_rqst * rqstp,
        if (nfserr)
                goto out;
 
-       inode = fh->fh_dentry->d_inode;
+       inode = d_inode(fh->fh_dentry);
        if (!IS_POSIXACL(inode) || !inode->i_op->set_acl) {
                error = -EOPNOTSUPP;
                goto out_errno;
@@ -266,9 +266,9 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p,
         * nfsd_dispatch actually ensures the following cannot happen.
         * However, it seems fragile to depend on that.
         */
-       if (dentry == NULL || dentry->d_inode == NULL)
+       if (dentry == NULL || d_really_is_negative(dentry))
                return 0;
-       inode = dentry->d_inode;
+       inode = d_inode(dentry);
 
        p = nfs2svc_encode_fattr(rqstp, p, &resp->fh, &resp->stat);
        *p++ = htonl(resp->mask);
index 34cbbab6abd76ff4ec08a46aec25616516fda556..882b1a14bc3e85961fbd628009c7618b13263a88 100644 (file)
@@ -39,7 +39,7 @@ static __be32 nfsd3_proc_getacl(struct svc_rqst * rqstp,
        if (nfserr)
                RETURN_STATUS(nfserr);
 
-       inode = fh->fh_dentry->d_inode;
+       inode = d_inode(fh->fh_dentry);
 
        if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
                RETURN_STATUS(nfserr_inval);
@@ -94,7 +94,7 @@ static __be32 nfsd3_proc_setacl(struct svc_rqst * rqstp,
        if (nfserr)
                goto out;
 
-       inode = fh->fh_dentry->d_inode;
+       inode = d_inode(fh->fh_dentry);
        if (!IS_POSIXACL(inode) || !inode->i_op->set_acl) {
                error = -EOPNOTSUPP;
                goto out_errno;
@@ -174,8 +174,8 @@ static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p,
        struct dentry *dentry = resp->fh.fh_dentry;
 
        p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh);
-       if (resp->status == 0 && dentry && dentry->d_inode) {
-               struct inode *inode = dentry->d_inode;
+       if (resp->status == 0 && dentry && d_really_is_positive(dentry)) {
+               struct inode *inode = d_inode(dentry);
                struct kvec *head = rqstp->rq_res.head;
                unsigned int base;
                int n;
index 12f2aab4f614deb86d5a4e9d4edbc4a8da5ee869..7b755b7f785ceb4deff9fd9a5fbafccef15efa3f 100644 (file)
@@ -166,7 +166,7 @@ nfsd3_proc_read(struct svc_rqst *rqstp, struct nfsd3_readargs *argp,
                                  rqstp->rq_vec, argp->vlen,
                                  &resp->count);
        if (nfserr == 0) {
-               struct inode    *inode = resp->fh.fh_dentry->d_inode;
+               struct inode    *inode = d_inode(resp->fh.fh_dentry);
 
                resp->eof = (argp->offset + resp->count) >= inode->i_size;
        }
@@ -551,7 +551,7 @@ nfsd3_proc_fsinfo(struct svc_rqst * rqstp, struct nfsd_fhandle    *argp,
         * different read/write sizes for file systems known to have
         * problems with large blocks */
        if (nfserr == 0) {
-               struct super_block *sb = argp->fh.fh_dentry->d_inode->i_sb;
+               struct super_block *sb = d_inode(argp->fh.fh_dentry)->i_sb;
 
                /* Note that we don't care for remote fs's here */
                if (sb->s_magic == MSDOS_SUPER_MAGIC) {
@@ -587,7 +587,7 @@ nfsd3_proc_pathconf(struct svc_rqst * rqstp, struct nfsd_fhandle      *argp,
        nfserr = fh_verify(rqstp, &argp->fh, 0, NFSD_MAY_NOP);
 
        if (nfserr == 0) {
-               struct super_block *sb = argp->fh.fh_dentry->d_inode->i_sb;
+               struct super_block *sb = d_inode(argp->fh.fh_dentry)->i_sb;
 
                /* Note that we don't care for remote fs's here */
                switch (sb->s_magic) {
index 39c5eb3ad33ad76be9d92302bf6bfadb308dbab4..e4b2b4322553d05e44d17719f33ab3938b57c0d1 100644 (file)
@@ -146,7 +146,7 @@ static __be32 *encode_fsid(__be32 *p, struct svc_fh *fhp)
        default:
        case FSIDSOURCE_DEV:
                p = xdr_encode_hyper(p, (u64)huge_encode_dev
-                                    (fhp->fh_dentry->d_inode->i_sb->s_dev));
+                                    (d_inode(fhp->fh_dentry)->i_sb->s_dev));
                break;
        case FSIDSOURCE_FSID:
                p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid);
@@ -203,14 +203,14 @@ static __be32 *
 encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
 {
        struct dentry *dentry = fhp->fh_dentry;
-       if (dentry && dentry->d_inode) {
+       if (dentry && d_really_is_positive(dentry)) {
                __be32 err;
                struct kstat stat;
 
                err = fh_getattr(fhp, &stat);
                if (!err) {
                        *p++ = xdr_one;         /* attributes follow */
-                       lease_get_mtime(dentry->d_inode, &stat.mtime);
+                       lease_get_mtime(d_inode(dentry), &stat.mtime);
                        return encode_fattr3(rqstp, p, fhp, &stat);
                }
        }
@@ -233,7 +233,7 @@ encode_wcc_data(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
 {
        struct dentry   *dentry = fhp->fh_dentry;
 
-       if (dentry && dentry->d_inode && fhp->fh_post_saved) {
+       if (dentry && d_really_is_positive(dentry) && fhp->fh_post_saved) {
                if (fhp->fh_pre_saved) {
                        *p++ = xdr_one;
                        p = xdr_encode_hyper(p, (u64) fhp->fh_pre_size);
@@ -260,11 +260,11 @@ void fill_post_wcc(struct svc_fh *fhp)
                printk("nfsd: inode locked twice during operation.\n");
 
        err = fh_getattr(fhp, &fhp->fh_post_attr);
-       fhp->fh_post_change = fhp->fh_dentry->d_inode->i_version;
+       fhp->fh_post_change = d_inode(fhp->fh_dentry)->i_version;
        if (err) {
                fhp->fh_post_saved = 0;
                /* Grab the ctime anyway - set_change_info might use it */
-               fhp->fh_post_attr.ctime = fhp->fh_dentry->d_inode->i_ctime;
+               fhp->fh_post_attr.ctime = d_inode(fhp->fh_dentry)->i_ctime;
        } else
                fhp->fh_post_saved = 1;
 }
@@ -628,7 +628,7 @@ nfs3svc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p,
                                        struct nfsd3_attrstat *resp)
 {
        if (resp->status == 0) {
-               lease_get_mtime(resp->fh.fh_dentry->d_inode,
+               lease_get_mtime(d_inode(resp->fh.fh_dentry),
                                &resp->stat.mtime);
                p = encode_fattr3(rqstp, p, &resp->fh, &resp->stat);
        }
@@ -828,7 +828,7 @@ compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
                return rv;
        if (d_mountpoint(dchild))
                goto out;
-       if (!dchild->d_inode)
+       if (d_really_is_negative(dchild))
                goto out;
        rv = fh_compose(fhp, exp, dchild, &cd->fh);
 out:
index 59fd7665178146c6dc188651f8a7eca96d3489aa..67242bf7c6cc3dfd5330f832f62a0043fec68480 100644 (file)
@@ -139,7 +139,7 @@ int
 nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry,
                struct nfs4_acl **acl)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int error = 0;
        struct posix_acl *pacl = NULL, *dpacl = NULL;
        unsigned int flags = 0;
@@ -499,43 +499,13 @@ static inline void add_to_mask(struct posix_acl_state *state, struct posix_ace_s
        state->mask.allow |= astate->allow;
 }
 
-/*
- * Certain bits (SYNCHRONIZE, DELETE, WRITE_OWNER, READ/WRITE_NAMED_ATTRS,
- * READ_ATTRIBUTES, READ_ACL) are currently unenforceable and don't translate
- * to traditional read/write/execute permissions.
- *
- * It's problematic to reject acls that use certain mode bits, because it
- * places the burden on users to learn the rules about which bits one
- * particular server sets, without giving the user a lot of help--we return an
- * error that could mean any number of different things.  To make matters
- * worse, the problematic bits might be introduced by some application that's
- * automatically mapping from some other acl model.
- *
- * So wherever possible we accept anything, possibly erring on the side of
- * denying more permissions than necessary.
- *
- * However we do reject *explicit* DENY's of a few bits representing
- * permissions we could never deny:
- */
-
-static inline int check_deny(u32 mask, int isowner)
-{
-       if (mask & (NFS4_ACE_READ_ATTRIBUTES | NFS4_ACE_READ_ACL))
-               return -EINVAL;
-       if (!isowner)
-               return 0;
-       if (mask & (NFS4_ACE_WRITE_ATTRIBUTES | NFS4_ACE_WRITE_ACL))
-               return -EINVAL;
-       return 0;
-}
-
 static struct posix_acl *
 posix_state_to_acl(struct posix_acl_state *state, unsigned int flags)
 {
        struct posix_acl_entry *pace;
        struct posix_acl *pacl;
        int nace;
-       int i, error = 0;
+       int i;
 
        /*
         * ACLs with no ACEs are treated differently in the inheritable
@@ -560,17 +530,11 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags)
 
        pace = pacl->a_entries;
        pace->e_tag = ACL_USER_OBJ;
-       error = check_deny(state->owner.deny, 1);
-       if (error)
-               goto out_err;
        low_mode_from_nfs4(state->owner.allow, &pace->e_perm, flags);
 
        for (i=0; i < state->users->n; i++) {
                pace++;
                pace->e_tag = ACL_USER;
-               error = check_deny(state->users->aces[i].perms.deny, 0);
-               if (error)
-                       goto out_err;
                low_mode_from_nfs4(state->users->aces[i].perms.allow,
                                        &pace->e_perm, flags);
                pace->e_uid = state->users->aces[i].uid;
@@ -579,18 +543,12 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags)
 
        pace++;
        pace->e_tag = ACL_GROUP_OBJ;
-       error = check_deny(state->group.deny, 0);
-       if (error)
-               goto out_err;
        low_mode_from_nfs4(state->group.allow, &pace->e_perm, flags);
        add_to_mask(state, &state->group);
 
        for (i=0; i < state->groups->n; i++) {
                pace++;
                pace->e_tag = ACL_GROUP;
-               error = check_deny(state->groups->aces[i].perms.deny, 0);
-               if (error)
-                       goto out_err;
                low_mode_from_nfs4(state->groups->aces[i].perms.allow,
                                        &pace->e_perm, flags);
                pace->e_gid = state->groups->aces[i].gid;
@@ -605,15 +563,9 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags)
 
        pace++;
        pace->e_tag = ACL_OTHER;
-       error = check_deny(state->other.deny, 0);
-       if (error)
-               goto out_err;
        low_mode_from_nfs4(state->other.allow, &pace->e_perm, flags);
 
        return pacl;
-out_err:
-       posix_acl_release(pacl);
-       return ERR_PTR(error);
 }
 
 static inline void allow_bits(struct posix_ace_state *astate, u32 mask)
@@ -828,7 +780,7 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
                return error;
 
        dentry = fhp->fh_dentry;
-       inode = dentry->d_inode;
+       inode = d_inode(dentry);
 
        if (!inode->i_op->set_acl || !IS_POSIXACL(inode))
                return nfserr_attrnotsupp;
index 92b9d97aff4f1adfe24ed607d11661196a500ffc..864e2003e8ded5c8e6ff5db13f7fd9331ebefb65 100644 (file)
@@ -52,7 +52,7 @@
 static inline void
 nfsd4_security_inode_setsecctx(struct svc_fh *resfh, struct xdr_netobj *label, u32 *bmval)
 {
-       struct inode *inode = resfh->fh_dentry->d_inode;
+       struct inode *inode = d_inode(resfh->fh_dentry);
        int status;
 
        mutex_lock(&inode->i_mutex);
@@ -110,7 +110,7 @@ check_attr_support(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
         * in current environment or not.
         */
        if (bmval[0] & FATTR4_WORD0_ACL) {
-               if (!IS_POSIXACL(dentry->d_inode))
+               if (!IS_POSIXACL(d_inode(dentry)))
                        return nfserr_attrnotsupp;
        }
 
@@ -209,7 +209,7 @@ do_open_permission(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfs
 
 static __be32 nfsd_check_obj_isreg(struct svc_fh *fh)
 {
-       umode_t mode = fh->fh_dentry->d_inode->i_mode;
+       umode_t mode = d_inode(fh->fh_dentry)->i_mode;
 
        if (S_ISREG(mode))
                return nfs_ok;
@@ -470,7 +470,7 @@ out:
                fh_put(resfh);
                kfree(resfh);
        }
-       nfsd4_cleanup_open_state(cstate, open, status);
+       nfsd4_cleanup_open_state(cstate, open);
        nfsd4_bump_seqid(cstate, status);
        return status;
 }
@@ -881,7 +881,7 @@ nfsd4_secinfo(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                                    &exp, &dentry);
        if (err)
                return err;
-       if (dentry->d_inode == NULL) {
+       if (d_really_is_negative(dentry)) {
                exp_put(exp);
                err = nfserr_noent;
        } else
@@ -1030,6 +1030,8 @@ nfsd4_fallocate(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                dprintk("NFSD: nfsd4_fallocate: couldn't process stateid!\n");
                return status;
        }
+       if (!file)
+               return nfserr_bad_stateid;
 
        status = nfsd4_vfs_fallocate(rqstp, &cstate->current_fh, file,
                                     fallocate->falloc_offset,
@@ -1069,6 +1071,8 @@ nfsd4_seek(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                dprintk("NFSD: nfsd4_seek: couldn't process stateid!\n");
                return status;
        }
+       if (!file)
+               return nfserr_bad_stateid;
 
        switch (seek->seek_whence) {
        case NFS4_CONTENT_DATA:
@@ -1308,7 +1312,7 @@ nfsd4_layoutget(struct svc_rqst *rqstp,
        if (atomic_read(&ls->ls_stid.sc_file->fi_lo_recalls))
                goto out_put_stid;
 
-       nfserr = ops->proc_layoutget(current_fh->fh_dentry->d_inode,
+       nfserr = ops->proc_layoutget(d_inode(current_fh->fh_dentry),
                                     current_fh, lgp);
        if (nfserr)
                goto out_put_stid;
@@ -1342,7 +1346,7 @@ nfsd4_layoutcommit(struct svc_rqst *rqstp,
        ops = nfsd4_layout_verify(current_fh->fh_export, lcp->lc_layout_type);
        if (!ops)
                goto out;
-       inode = current_fh->fh_dentry->d_inode;
+       inode = d_inode(current_fh->fh_dentry);
 
        nfserr = nfserr_inval;
        if (new_size <= seg->offset) {
@@ -1815,7 +1819,7 @@ static inline u32 nfsd4_getattr_rsize(struct svc_rqst *rqstp,
                bmap0 &= ~FATTR4_WORD0_FILEHANDLE;
        }
        if (bmap2 & FATTR4_WORD2_SECURITY_LABEL) {
-               ret += NFSD4_MAX_SEC_LABEL_LEN + 12;
+               ret += NFS4_MAXLABELLEN + 12;
                bmap2 &= ~FATTR4_WORD2_SECURITY_LABEL;
        }
        /*
@@ -2282,13 +2286,13 @@ static struct nfsd4_operation nfsd4_ops[] = {
                .op_func = (nfsd4op_func)nfsd4_allocate,
                .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
                .op_name = "OP_ALLOCATE",
-               .op_rsize_bop = (nfsd4op_rsize)nfsd4_write_rsize,
+               .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
        },
        [OP_DEALLOCATE] = {
                .op_func = (nfsd4op_func)nfsd4_deallocate,
                .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
                .op_name = "OP_DEALLOCATE",
-               .op_rsize_bop = (nfsd4op_rsize)nfsd4_write_rsize,
+               .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
        },
        [OP_SEEK] = {
                .op_func = (nfsd4op_func)nfsd4_seek,
index 1c307f02baa89e79f0a6d2889631d3ef50ed0a48..d88ea7b9a85cbf4557d7689872150d08d33e4e64 100644 (file)
@@ -192,14 +192,14 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
 
        dir = nn->rec_file->f_path.dentry;
        /* lock the parent */
-       mutex_lock(&dir->d_inode->i_mutex);
+       mutex_lock(&d_inode(dir)->i_mutex);
 
        dentry = lookup_one_len(dname, dir, HEXDIR_LEN-1);
        if (IS_ERR(dentry)) {
                status = PTR_ERR(dentry);
                goto out_unlock;
        }
-       if (dentry->d_inode)
+       if (d_really_is_positive(dentry))
                /*
                 * In the 4.1 case, where we're called from
                 * reclaim_complete(), records from the previous reboot
@@ -209,11 +209,11 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
                 * as well be forgiving and just succeed silently.
                 */
                goto out_put;
-       status = vfs_mkdir(dir->d_inode, dentry, S_IRWXU);
+       status = vfs_mkdir(d_inode(dir), dentry, S_IRWXU);
 out_put:
        dput(dentry);
 out_unlock:
-       mutex_unlock(&dir->d_inode->i_mutex);
+       mutex_unlock(&d_inode(dir)->i_mutex);
        if (status == 0) {
                if (nn->in_grace) {
                        crp = nfs4_client_to_reclaim(dname, nn);
@@ -285,7 +285,7 @@ nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn)
        }
 
        status = iterate_dir(nn->rec_file, &ctx.ctx);
-       mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
+       mutex_lock_nested(&d_inode(dir)->i_mutex, I_MUTEX_PARENT);
        while (!list_empty(&ctx.names)) {
                struct name_list *entry;
                entry = list_entry(ctx.names.next, struct name_list, list);
@@ -302,7 +302,7 @@ nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn)
                list_del(&entry->list);
                kfree(entry);
        }
-       mutex_unlock(&dir->d_inode->i_mutex);
+       mutex_unlock(&d_inode(dir)->i_mutex);
        nfs4_reset_creds(original_cred);
        return status;
 }
@@ -316,20 +316,20 @@ nfsd4_unlink_clid_dir(char *name, int namlen, struct nfsd_net *nn)
        dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name);
 
        dir = nn->rec_file->f_path.dentry;
-       mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
+       mutex_lock_nested(&d_inode(dir)->i_mutex, I_MUTEX_PARENT);
        dentry = lookup_one_len(name, dir, namlen);
        if (IS_ERR(dentry)) {
                status = PTR_ERR(dentry);
                goto out_unlock;
        }
        status = -ENOENT;
-       if (!dentry->d_inode)
+       if (d_really_is_negative(dentry))
                goto out;
-       status = vfs_rmdir(dir->d_inode, dentry);
+       status = vfs_rmdir(d_inode(dir), dentry);
 out:
        dput(dentry);
 out_unlock:
-       mutex_unlock(&dir->d_inode->i_mutex);
+       mutex_unlock(&d_inode(dir)->i_mutex);
        return status;
 }
 
@@ -385,7 +385,7 @@ purge_old(struct dentry *parent, struct dentry *child, struct nfsd_net *nn)
        if (nfs4_has_reclaimed_state(child->d_name.name, nn))
                return 0;
 
-       status = vfs_rmdir(parent->d_inode, child);
+       status = vfs_rmdir(d_inode(parent), child);
        if (status)
                printk("failed to remove client recovery directory %pd\n",
                                child);
index 326a545ea7b2bb56277ee32a950e858410f33f1f..38f2d7abe3a707061c3f860ce8042649bf5109eb 100644 (file)
@@ -1139,7 +1139,7 @@ hash_sessionid(struct nfs4_sessionid *sessionid)
        return sid->sequence % SESSION_HASH_SIZE;
 }
 
-#ifdef NFSD_DEBUG
+#ifdef CONFIG_SUNRPC_DEBUG
 static inline void
 dump_sessionid(const char *fn, struct nfs4_sessionid *sessionid)
 {
@@ -4049,7 +4049,6 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
                status = nfserr_bad_stateid;
                if (nfsd4_is_deleg_cur(open))
                        goto out;
-               status = nfserr_jukebox;
        }
 
        /*
@@ -4118,7 +4117,7 @@ out:
 }
 
 void nfsd4_cleanup_open_state(struct nfsd4_compound_state *cstate,
-                             struct nfsd4_open *open, __be32 status)
+                             struct nfsd4_open *open)
 {
        if (open->op_openowner) {
                struct nfs4_stateowner *so = &open->op_openowner->oo_owner;
@@ -4473,7 +4472,7 @@ nfs4_preprocess_stateid_op(struct net *net, struct nfsd4_compound_state *cstate,
        struct nfs4_ol_stateid *stp = NULL;
        struct nfs4_delegation *dp = NULL;
        struct svc_fh *current_fh = &cstate->current_fh;
-       struct inode *ino = current_fh->fh_dentry->d_inode;
+       struct inode *ino = d_inode(current_fh->fh_dentry);
        struct nfsd_net *nn = net_generic(net, nfsd_net_id);
        struct file *file = NULL;
        __be32 status;
@@ -5171,7 +5170,7 @@ lookup_or_create_lock_state(struct nfsd4_compound_state *cstate,
        struct nfs4_file *fi = ost->st_stid.sc_file;
        struct nfs4_openowner *oo = openowner(ost->st_stateowner);
        struct nfs4_client *cl = oo->oo_owner.so_client;
-       struct inode *inode = cstate->current_fh.fh_dentry->d_inode;
+       struct inode *inode = d_inode(cstate->current_fh.fh_dentry);
        struct nfs4_lockowner *lo;
        unsigned int strhashval;
 
index 5fb7e78169a6b27a1a5a4d5e9ec354c9e32f6c43..158badf945df1da9b5f146933b525538cbf1211f 100644 (file)
@@ -424,7 +424,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
                len += 4;
                dummy32 = be32_to_cpup(p++);
                READ_BUF(dummy32);
-               if (dummy32 > NFSD4_MAX_SEC_LABEL_LEN)
+               if (dummy32 > NFS4_MAXLABELLEN)
                        return nfserr_badlabel;
                len += (XDR_QUADLEN(dummy32) << 2);
                READMEM(buf, dummy32);
@@ -2020,7 +2020,7 @@ static __be32 nfsd4_encode_path(struct xdr_stream *xdr,
         * dentries/path components in an array.
         */
        for (;;) {
-               if (cur.dentry == root->dentry && cur.mnt == root->mnt)
+               if (path_equal(&cur, root))
                        break;
                if (cur.dentry == cur.mnt->mnt_root) {
                        if (follow_up(&cur))
@@ -2292,7 +2292,7 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
 #ifdef CONFIG_NFSD_V4_SECURITY_LABEL
        if ((bmval[2] & FATTR4_WORD2_SECURITY_LABEL) ||
                        bmval[0] & FATTR4_WORD0_SUPPORTED_ATTRS) {
-               err = security_inode_getsecctx(dentry->d_inode,
+               err = security_inode_getsecctx(d_inode(dentry),
                                                &context, &contextlen);
                contextsupport = (err == 0);
                if (bmval2 & FATTR4_WORD2_SECURITY_LABEL) {
@@ -2384,7 +2384,7 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
                p = xdr_reserve_space(xdr, 8);
                if (!p)
                        goto out_resource;
-               p = encode_change(p, &stat, dentry->d_inode);
+               p = encode_change(p, &stat, d_inode(dentry));
        }
        if (bmval0 & FATTR4_WORD0_SIZE) {
                p = xdr_reserve_space(xdr, 8);
@@ -2807,7 +2807,7 @@ nfsd4_encode_dirent_fattr(struct xdr_stream *xdr, struct nfsd4_readdir *cd,
        dentry = lookup_one_len(name, cd->rd_fhp->fh_dentry, namlen);
        if (IS_ERR(dentry))
                return nfserrno(PTR_ERR(dentry));
-       if (!dentry->d_inode) {
+       if (d_really_is_negative(dentry)) {
                /*
                 * nfsd_buffered_readdir drops the i_mutex between
                 * readdir and calling this callback, leaving a window
@@ -3324,7 +3324,7 @@ static __be32 nfsd4_encode_splice_read(
        }
 
        eof = (read->rd_offset + maxcount >=
-              read->rd_fhp->fh_dentry->d_inode->i_size);
+              d_inode(read->rd_fhp->fh_dentry)->i_size);
 
        *(p++) = htonl(eof);
        *(p++) = htonl(maxcount);
@@ -3401,7 +3401,7 @@ static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp,
        xdr_truncate_encode(xdr, starting_len + 8 + ((maxcount+3)&~3));
 
        eof = (read->rd_offset + maxcount >=
-              read->rd_fhp->fh_dentry->d_inode->i_size);
+              d_inode(read->rd_fhp->fh_dentry)->i_size);
 
        tmp = htonl(eof);
        write_bytes_to_xdr_buf(xdr->buf, starting_len    , &tmp, 4);
@@ -3422,6 +3422,7 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
        unsigned long maxcount;
        struct xdr_stream *xdr = &resp->xdr;
        struct file *file = read->rd_filp;
+       struct svc_fh *fhp = read->rd_fhp;
        int starting_len = xdr->buf->len;
        struct raparms *ra;
        __be32 *p;
@@ -3445,12 +3446,15 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
        maxcount = min_t(unsigned long, maxcount, (xdr->buf->buflen - xdr->buf->len));
        maxcount = min_t(unsigned long, maxcount, read->rd_length);
 
-       if (!read->rd_filp) {
+       if (read->rd_filp)
+               err = nfsd_permission(resp->rqstp, fhp->fh_export,
+                               fhp->fh_dentry,
+                               NFSD_MAY_READ|NFSD_MAY_OWNER_OVERRIDE);
+       else
                err = nfsd_get_tmp_read_open(resp->rqstp, read->rd_fhp,
                                                &file, &ra);
-               if (err)
-                       goto err_truncate;
-       }
+       if (err)
+               goto err_truncate;
 
        if (file->f_op->splice_read && test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags))
                err = nfsd4_encode_splice_read(resp, read, file, maxcount);
index aa47d75ddb26312c6eebbcf810d4c9ccfcca0b16..9690cb4dd5887b020ffc897ba93888f302db3a56 100644 (file)
@@ -1250,15 +1250,15 @@ static int __init init_nfsd(void)
        int retval;
        printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n");
 
-       retval = register_cld_notifier();
-       if (retval)
-               return retval;
        retval = register_pernet_subsys(&nfsd_net_ops);
        if (retval < 0)
-               goto out_unregister_notifier;
-       retval = nfsd4_init_slabs();
+               return retval;
+       retval = register_cld_notifier();
        if (retval)
                goto out_unregister_pernet;
+       retval = nfsd4_init_slabs();
+       if (retval)
+               goto out_unregister_notifier;
        retval = nfsd4_init_pnfs();
        if (retval)
                goto out_free_slabs;
@@ -1290,10 +1290,10 @@ out_exit_pnfs:
        nfsd4_exit_pnfs();
 out_free_slabs:
        nfsd4_free_slabs();
-out_unregister_pernet:
-       unregister_pernet_subsys(&nfsd_net_ops);
 out_unregister_notifier:
        unregister_cld_notifier();
+out_unregister_pernet:
+       unregister_pernet_subsys(&nfsd_net_ops);
        return retval;
 }
 
@@ -1308,8 +1308,8 @@ static void __exit exit_nfsd(void)
        nfsd4_exit_pnfs();
        nfsd_fault_inject_cleanup();
        unregister_filesystem(&nfsd_fs_type);
-       unregister_pernet_subsys(&nfsd_net_ops);
        unregister_cld_notifier();
+       unregister_pernet_subsys(&nfsd_net_ops);
 }
 
 MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
index 565c4da1a9eb9d0041ceed175918f71517885f65..cf980523898b78cc98debc868e2b5a249531ab18 100644 (file)
@@ -24,7 +24,7 @@
 #include "export.h"
 
 #undef ifdebug
-#ifdef NFSD_DEBUG
+#ifdef CONFIG_SUNRPC_DEBUG
 # define ifdebug(flag)         if (nfsd_debug & NFSDDBG_##flag)
 #else
 # define ifdebug(flag)         if (0)
index e9fa966fc37fe5415f9fba50b61b37d459172303..350041a40fe519ac22fa14901c84a6dfddcec9c1 100644 (file)
@@ -38,7 +38,7 @@ static int nfsd_acceptable(void *expv, struct dentry *dentry)
                /* make sure parents give x permission to user */
                int err;
                parent = dget_parent(tdentry);
-               err = inode_permission(parent->d_inode, MAY_EXEC);
+               err = inode_permission(d_inode(parent), MAY_EXEC);
                if (err < 0) {
                        dput(parent);
                        break;
@@ -340,7 +340,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, int access)
        if (error)
                goto out;
 
-       error = nfsd_mode_check(rqstp, dentry->d_inode->i_mode, type);
+       error = nfsd_mode_check(rqstp, d_inode(dentry)->i_mode, type);
        if (error)
                goto out;
 
@@ -412,8 +412,8 @@ static inline void _fh_update_old(struct dentry *dentry,
                                  struct svc_export *exp,
                                  struct knfsd_fh *fh)
 {
-       fh->ofh_ino = ino_t_to_u32(dentry->d_inode->i_ino);
-       fh->ofh_generation = dentry->d_inode->i_generation;
+       fh->ofh_ino = ino_t_to_u32(d_inode(dentry)->i_ino);
+       fh->ofh_generation = d_inode(dentry)->i_generation;
        if (d_is_dir(dentry) ||
            (exp->ex_flags & NFSEXP_NOSUBTREECHECK))
                fh->ofh_dirino = 0;
@@ -426,7 +426,7 @@ static bool is_root_export(struct svc_export *exp)
 
 static struct super_block *exp_sb(struct svc_export *exp)
 {
-       return exp->ex_path.dentry->d_inode->i_sb;
+       return d_inode(exp->ex_path.dentry)->i_sb;
 }
 
 static bool fsid_type_ok_for_exp(u8 fsid_type, struct svc_export *exp)
@@ -520,12 +520,12 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
         *
         */
 
-       struct inode * inode = dentry->d_inode;
+       struct inode * inode = d_inode(dentry);
        dev_t ex_dev = exp_sb(exp)->s_dev;
 
        dprintk("nfsd: fh_compose(exp %02x:%02x/%ld %pd2, ino=%ld)\n",
                MAJOR(ex_dev), MINOR(ex_dev),
-               (long) exp->ex_path.dentry->d_inode->i_ino,
+               (long) d_inode(exp->ex_path.dentry)->i_ino,
                dentry,
                (inode ? inode->i_ino : 0));
 
@@ -558,7 +558,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
                fhp->fh_handle.ofh_dev =  old_encode_dev(ex_dev);
                fhp->fh_handle.ofh_xdev = fhp->fh_handle.ofh_dev;
                fhp->fh_handle.ofh_xino =
-                       ino_t_to_u32(exp->ex_path.dentry->d_inode->i_ino);
+                       ino_t_to_u32(d_inode(exp->ex_path.dentry)->i_ino);
                fhp->fh_handle.ofh_dirino = ino_t_to_u32(parent_ino(dentry));
                if (inode)
                        _fh_update_old(dentry, exp, &fhp->fh_handle);
@@ -570,7 +570,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
                mk_fsid(fhp->fh_handle.fh_fsid_type,
                        fhp->fh_handle.fh_fsid,
                        ex_dev,
-                       exp->ex_path.dentry->d_inode->i_ino,
+                       d_inode(exp->ex_path.dentry)->i_ino,
                        exp->ex_fsid, exp->ex_uuid);
 
                if (inode)
@@ -597,7 +597,7 @@ fh_update(struct svc_fh *fhp)
                goto out_bad;
 
        dentry = fhp->fh_dentry;
-       if (!dentry->d_inode)
+       if (d_really_is_negative(dentry))
                goto out_negative;
        if (fhp->fh_handle.fh_version != 1) {
                _fh_update_old(dentry, fhp->fh_export, &fhp->fh_handle);
index f2292044217225391aa45f8f83b87ea2942bddd0..1e90dad4926b4aa2e5158d5d0e7acb7c26d73472 100644 (file)
@@ -225,7 +225,7 @@ fill_pre_wcc(struct svc_fh *fhp)
 {
        struct inode    *inode;
 
-       inode = fhp->fh_dentry->d_inode;
+       inode = d_inode(fhp->fh_dentry);
        if (!fhp->fh_pre_saved) {
                fhp->fh_pre_mtime = inode->i_mtime;
                fhp->fh_pre_ctime = inode->i_ctime;
@@ -264,7 +264,7 @@ fh_lock_nested(struct svc_fh *fhp, unsigned int subclass)
                return;
        }
 
-       inode = dentry->d_inode;
+       inode = d_inode(dentry);
        mutex_lock_nested(&inode->i_mutex, subclass);
        fill_pre_wcc(fhp);
        fhp->fh_locked = 1;
@@ -284,7 +284,7 @@ fh_unlock(struct svc_fh *fhp)
 {
        if (fhp->fh_locked) {
                fill_post_wcc(fhp);
-               mutex_unlock(&fhp->fh_dentry->d_inode->i_mutex);
+               mutex_unlock(&d_inode(fhp->fh_dentry)->i_mutex);
                fhp->fh_locked = 0;
        }
 }
index b8680738f5884e7ee94d46c95c89ff68faa9a95f..aecbcd34d3360fb1c6e925ce317ee14f7c48224c 100644 (file)
@@ -223,7 +223,7 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
        }
        fh_init(newfhp, NFS_FHSIZE);
        nfserr = fh_compose(newfhp, dirfhp->fh_export, dchild, dirfhp);
-       if (!nfserr && !dchild->d_inode)
+       if (!nfserr && d_really_is_negative(dchild))
                nfserr = nfserr_noent;
        dput(dchild);
        if (nfserr) {
@@ -241,7 +241,7 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
                }
        }
 
-       inode = newfhp->fh_dentry->d_inode;
+       inode = d_inode(newfhp->fh_dentry);
 
        /* Unfudge the mode bits */
        if (attr->ia_valid & ATTR_MODE) {
index 412d7061f9e5ec764cade00584ac87308b7caf3d..79d964aa8079f354fcadf50ac2a1d3d216668d4a 100644 (file)
@@ -187,7 +187,7 @@ encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
        *p++ = htonl((u32) stat->ino);
        *p++ = htonl((u32) stat->atime.tv_sec);
        *p++ = htonl(stat->atime.tv_nsec ? stat->atime.tv_nsec / 1000 : 0);
-       lease_get_mtime(dentry->d_inode, &time); 
+       lease_get_mtime(d_inode(dentry), &time); 
        *p++ = htonl((u32) time.tv_sec);
        *p++ = htonl(time.tv_nsec ? time.tv_nsec / 1000 : 0); 
        *p++ = htonl((u32) stat->ctime.tv_sec);
index 36852658242943051f1a1cac7d4b6a8c1945f84c..84d770be056ee7b1a4db58e3ca0acb648b91a18d 100644 (file)
@@ -174,7 +174,7 @@ int nfsd_mountpoint(struct dentry *dentry, struct svc_export *exp)
                return 1;
        if (!(exp->ex_flags & NFSEXP_V4ROOT))
                return 0;
-       return dentry->d_inode != NULL;
+       return d_inode(dentry) != NULL;
 }
 
 __be32
@@ -270,7 +270,7 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
         * dentry may be negative, it may need to be updated.
         */
        err = fh_compose(resfh, exp, dentry, fhp);
-       if (!err && !dentry->d_inode)
+       if (!err && d_really_is_negative(dentry))
                err = nfserr_noent;
 out:
        dput(dentry);
@@ -284,7 +284,7 @@ out:
 static int
 commit_metadata(struct svc_fh *fhp)
 {
-       struct inode *inode = fhp->fh_dentry->d_inode;
+       struct inode *inode = d_inode(fhp->fh_dentry);
        const struct export_operations *export_ops = inode->i_sb->s_export_op;
 
        if (!EX_ISSYNC(fhp->fh_export))
@@ -364,7 +364,7 @@ static __be32
 nfsd_get_write_access(struct svc_rqst *rqstp, struct svc_fh *fhp,
                struct iattr *iap)
 {
-       struct inode *inode = fhp->fh_dentry->d_inode;
+       struct inode *inode = d_inode(fhp->fh_dentry);
        int host_err;
 
        if (iap->ia_size < inode->i_size) {
@@ -426,7 +426,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
        }
 
        dentry = fhp->fh_dentry;
-       inode = dentry->d_inode;
+       inode = d_inode(dentry);
 
        /* Ignore any mode updates on symlinks */
        if (S_ISLNK(inode->i_mode))
@@ -495,7 +495,7 @@ out:
  */
 int nfsd4_is_junction(struct dentry *dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
 
        if (inode == NULL)
                return 0;
@@ -521,9 +521,9 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp,
 
        dentry = fhp->fh_dentry;
 
-       mutex_lock(&dentry->d_inode->i_mutex);
+       mutex_lock(&d_inode(dentry)->i_mutex);
        host_error = security_inode_setsecctx(dentry, label->data, label->len);
-       mutex_unlock(&dentry->d_inode->i_mutex);
+       mutex_unlock(&d_inode(dentry)->i_mutex);
        return nfserrno(host_error);
 }
 #else
@@ -706,7 +706,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
 
        path.mnt = fhp->fh_export->ex_path.mnt;
        path.dentry = fhp->fh_dentry;
-       inode = path.dentry->d_inode;
+       inode = d_inode(path.dentry);
 
        /* Disallow write access to files with the append-only bit set
         * or any access when mandatory locking enabled
@@ -1211,7 +1211,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
                goto out;
 
        dentry = fhp->fh_dentry;
-       dirp = dentry->d_inode;
+       dirp = d_inode(dentry);
 
        err = nfserr_notdir;
        if (!dirp->i_op->lookup)
@@ -1250,7 +1250,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
         * Make sure the child dentry is still negative ...
         */
        err = nfserr_exist;
-       if (dchild->d_inode) {
+       if (d_really_is_positive(dchild)) {
                dprintk("nfsd_create: dentry %pd/%pd not negative!\n",
                        dentry, dchild);
                goto out; 
@@ -1353,7 +1353,7 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
                goto out;
 
        dentry = fhp->fh_dentry;
-       dirp = dentry->d_inode;
+       dirp = d_inode(dentry);
 
        /* Get all the sanity checks out of the way before
         * we lock the parent. */
@@ -1376,7 +1376,7 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
                goto out_nfserr;
 
        /* If file doesn't exist, check for permissions to create one */
-       if (!dchild->d_inode) {
+       if (d_really_is_negative(dchild)) {
                err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE);
                if (err)
                        goto out;
@@ -1397,7 +1397,7 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
                v_atime = verifier[1]&0x7fffffff;
        }
        
-       if (dchild->d_inode) {
+       if (d_really_is_positive(dchild)) {
                err = 0;
 
                switch (createmode) {
@@ -1420,17 +1420,17 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
                        }
                        break;
                case NFS3_CREATE_EXCLUSIVE:
-                       if (   dchild->d_inode->i_mtime.tv_sec == v_mtime
-                           && dchild->d_inode->i_atime.tv_sec == v_atime
-                           && dchild->d_inode->i_size  == 0 ) {
+                       if (   d_inode(dchild)->i_mtime.tv_sec == v_mtime
+                           && d_inode(dchild)->i_atime.tv_sec == v_atime
+                           && d_inode(dchild)->i_size  == 0 ) {
                                if (created)
                                        *created = 1;
                                break;
                        }
                case NFS4_CREATE_EXCLUSIVE4_1:
-                       if (   dchild->d_inode->i_mtime.tv_sec == v_mtime
-                           && dchild->d_inode->i_atime.tv_sec == v_atime
-                           && dchild->d_inode->i_size  == 0 ) {
+                       if (   d_inode(dchild)->i_mtime.tv_sec == v_mtime
+                           && d_inode(dchild)->i_atime.tv_sec == v_atime
+                           && d_inode(dchild)->i_size  == 0 ) {
                                if (created)
                                        *created = 1;
                                goto set_attr;
@@ -1513,7 +1513,7 @@ nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp)
 
        path.mnt = fhp->fh_export->ex_path.mnt;
        path.dentry = fhp->fh_dentry;
-       inode = path.dentry->d_inode;
+       inode = d_inode(path.dentry);
 
        err = nfserr_inval;
        if (!inode->i_op->readlink)
@@ -1576,7 +1576,7 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
        if (IS_ERR(dnew))
                goto out_nfserr;
 
-       host_err = vfs_symlink(dentry->d_inode, dnew, path);
+       host_err = vfs_symlink(d_inode(dentry), dnew, path);
        err = nfserrno(host_err);
        if (!err)
                err = nfserrno(commit_metadata(fhp));
@@ -1632,7 +1632,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
 
        fh_lock_nested(ffhp, I_MUTEX_PARENT);
        ddir = ffhp->fh_dentry;
-       dirp = ddir->d_inode;
+       dirp = d_inode(ddir);
 
        dnew = lookup_one_len(name, ddir, len);
        host_err = PTR_ERR(dnew);
@@ -1642,7 +1642,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
        dold = tfhp->fh_dentry;
 
        err = nfserr_noent;
-       if (!dold->d_inode)
+       if (d_really_is_negative(dold))
                goto out_dput;
        host_err = vfs_link(dold, dirp, dnew, NULL);
        if (!host_err) {
@@ -1689,10 +1689,10 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
                goto out;
 
        fdentry = ffhp->fh_dentry;
-       fdir = fdentry->d_inode;
+       fdir = d_inode(fdentry);
 
        tdentry = tfhp->fh_dentry;
-       tdir = tdentry->d_inode;
+       tdir = d_inode(tdentry);
 
        err = nfserr_perm;
        if (!flen || isdotent(fname, flen) || !tlen || isdotent(tname, tlen))
@@ -1717,7 +1717,7 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
                goto out_nfserr;
 
        host_err = -ENOENT;
-       if (!odentry->d_inode)
+       if (d_really_is_negative(odentry))
                goto out_dput_old;
        host_err = -EINVAL;
        if (odentry == trap)
@@ -1790,21 +1790,21 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
 
        fh_lock_nested(fhp, I_MUTEX_PARENT);
        dentry = fhp->fh_dentry;
-       dirp = dentry->d_inode;
+       dirp = d_inode(dentry);
 
        rdentry = lookup_one_len(fname, dentry, flen);
        host_err = PTR_ERR(rdentry);
        if (IS_ERR(rdentry))
                goto out_nfserr;
 
-       if (!rdentry->d_inode) {
+       if (d_really_is_negative(rdentry)) {
                dput(rdentry);
                err = nfserr_noent;
                goto out;
        }
 
        if (!type)
-               type = rdentry->d_inode->i_mode & S_IFMT;
+               type = d_inode(rdentry)->i_mode & S_IFMT;
 
        if (type != S_IFDIR)
                host_err = vfs_unlink(dirp, rdentry, NULL);
@@ -2015,7 +2015,7 @@ __be32
 nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
                                        struct dentry *dentry, int acc)
 {
-       struct inode    *inode = dentry->d_inode;
+       struct inode    *inode = d_inode(dentry);
        int             err;
 
        if ((acc & NFSD_MAY_MASK) == NFSD_MAY_NOP)
index 0bda93e58e1b786a9426bb68fabe4c869090922d..f982ae84f0cd2303df5275086a3a05ce519bbd86 100644 (file)
@@ -40,7 +40,6 @@
 #include "state.h"
 #include "nfsd.h"
 
-#define NFSD4_MAX_SEC_LABEL_LEN        2048
 #define NFSD4_MAX_TAGLEN       128
 #define XDR_LEN(n)                     (((n) + 3) & ~3)
 
@@ -632,7 +631,7 @@ set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp)
 {
        BUG_ON(!fhp->fh_pre_saved);
        cinfo->atomic = fhp->fh_post_saved;
-       cinfo->change_supported = IS_I_VERSION(fhp->fh_dentry->d_inode);
+       cinfo->change_supported = IS_I_VERSION(d_inode(fhp->fh_dentry));
 
        cinfo->before_change = fhp->fh_pre_change;
        cinfo->after_change = fhp->fh_post_change;
@@ -683,7 +682,7 @@ extern __be32 nfsd4_process_open2(struct svc_rqst *rqstp,
                struct svc_fh *current_fh, struct nfsd4_open *open);
 extern void nfsd4_cstate_clear_replay(struct nfsd4_compound_state *cstate);
 extern void nfsd4_cleanup_open_state(struct nfsd4_compound_state *cstate,
-               struct nfsd4_open *open, __be32 status);
+               struct nfsd4_open *open);
 extern __be32 nfsd4_open_confirm(struct svc_rqst *rqstp,
                struct nfsd4_compound_state *, struct nfsd4_open_confirm *oc);
 extern __be32 nfsd4_close(struct svc_rqst *rqstp,
index 059f37137f9ad7b55b6dc0c3f34fa6c0fea6160b..919fd5bb14a842e94b80ae8d839cac1918bb1cc2 100644 (file)
@@ -388,7 +388,7 @@ static int nilfs_btree_root_broken(const struct nilfs_btree_node *node,
        nchildren = nilfs_btree_node_get_nchildren(node);
 
        if (unlikely(level < NILFS_BTREE_LEVEL_NODE_MIN ||
-                    level > NILFS_BTREE_LEVEL_MAX ||
+                    level >= NILFS_BTREE_LEVEL_MAX ||
                     nchildren < 0 ||
                     nchildren > NILFS_BTREE_ROOT_NCHILDREN_MAX)) {
                pr_crit("NILFS: bad btree root (inode number=%lu): level = %d, flags = 0x%x, nchildren = %d\n",
index 197a63e9d10215b54e28179b7976e6c0b56b5384..0ee0bed3649baf1f8974c15e42916294ab55ff6c 100644 (file)
@@ -435,7 +435,7 @@ void nilfs_set_link(struct inode *dir, struct nilfs_dir_entry *de,
  */
 int nilfs_add_link(struct dentry *dentry, struct inode *inode)
 {
-       struct inode *dir = dentry->d_parent->d_inode;
+       struct inode *dir = d_inode(dentry->d_parent);
        const unsigned char *name = dentry->d_name.name;
        int namelen = dentry->d_name.len;
        unsigned chunk_size = nilfs_chunk_size(dir);
index be936df4ba73967837b83a50d4f465e47521924e..258d9fe2521a52f1a6d96d310d90bd0890434634 100644 (file)
@@ -835,7 +835,7 @@ void nilfs_evict_inode(struct inode *inode)
 int nilfs_setattr(struct dentry *dentry, struct iattr *iattr)
 {
        struct nilfs_transaction_info ti;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct super_block *sb = inode->i_sb;
        int err;
 
index 0f84b257932c2351569db8fc87432dfb9bcfebe9..22180836ec2201c0687c1faeb0ccc59315c2d6dd 100644 (file)
@@ -192,7 +192,7 @@ out_fail:
 static int nilfs_link(struct dentry *old_dentry, struct inode *dir,
                      struct dentry *dentry)
 {
-       struct inode *inode = old_dentry->d_inode;
+       struct inode *inode = d_inode(old_dentry);
        struct nilfs_transaction_info ti;
        int err;
 
@@ -283,7 +283,7 @@ static int nilfs_do_unlink(struct inode *dir, struct dentry *dentry)
        if (!de)
                goto out;
 
-       inode = dentry->d_inode;
+       inode = d_inode(dentry);
        err = -EIO;
        if (le64_to_cpu(de->inode) != inode->i_ino)
                goto out;
@@ -318,7 +318,7 @@ static int nilfs_unlink(struct inode *dir, struct dentry *dentry)
 
        if (!err) {
                nilfs_mark_inode_dirty(dir);
-               nilfs_mark_inode_dirty(dentry->d_inode);
+               nilfs_mark_inode_dirty(d_inode(dentry));
                err = nilfs_transaction_commit(dir->i_sb);
        } else
                nilfs_transaction_abort(dir->i_sb);
@@ -328,7 +328,7 @@ static int nilfs_unlink(struct inode *dir, struct dentry *dentry)
 
 static int nilfs_rmdir(struct inode *dir, struct dentry *dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct nilfs_transaction_info ti;
        int err;
 
@@ -358,8 +358,8 @@ static int nilfs_rmdir(struct inode *dir, struct dentry *dentry)
 static int nilfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                        struct inode *new_dir,  struct dentry *new_dentry)
 {
-       struct inode *old_inode = old_dentry->d_inode;
-       struct inode *new_inode = new_dentry->d_inode;
+       struct inode *old_inode = d_inode(old_dentry);
+       struct inode *new_inode = d_inode(new_dentry);
        struct page *dir_page = NULL;
        struct nilfs_dir_entry *dir_de = NULL;
        struct page *old_page;
@@ -453,13 +453,13 @@ static struct dentry *nilfs_get_parent(struct dentry *child)
        struct qstr dotdot = QSTR_INIT("..", 2);
        struct nilfs_root *root;
 
-       ino = nilfs_inode_by_name(child->d_inode, &dotdot);
+       ino = nilfs_inode_by_name(d_inode(child), &dotdot);
        if (!ino)
                return ERR_PTR(-ENOENT);
 
-       root = NILFS_I(child->d_inode)->i_root;
+       root = NILFS_I(d_inode(child))->i_root;
 
-       inode = nilfs_iget(child->d_inode->i_sb, root, ino);
+       inode = nilfs_iget(d_inode(child)->i_sb, root, ino);
        if (IS_ERR(inode))
                return ERR_CAST(inode);
 
index c1725f20a9d1d4149ebb7b369caa9c47d951758e..f47585bfeb0169eee1198d01493e1d54705dabba 100644 (file)
@@ -610,7 +610,7 @@ static int nilfs_unfreeze(struct super_block *sb)
 static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
        struct super_block *sb = dentry->d_sb;
-       struct nilfs_root *root = NILFS_I(dentry->d_inode)->i_root;
+       struct nilfs_root *root = NILFS_I(d_inode(dentry))->i_root;
        struct the_nilfs *nilfs = root->nilfs;
        u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
        unsigned long long blocks;
@@ -681,7 +681,7 @@ static int nilfs_show_options(struct seq_file *seq, struct dentry *dentry)
 {
        struct super_block *sb = dentry->d_sb;
        struct the_nilfs *nilfs = sb->s_fs_info;
-       struct nilfs_root *root = NILFS_I(dentry->d_inode)->i_root;
+       struct nilfs_root *root = NILFS_I(d_inode(dentry))->i_root;
 
        if (!nilfs_test_opt(nilfs, BARRIER))
                seq_puts(seq, ",nobarrier");
@@ -1190,7 +1190,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
 
                sb->s_flags &= ~MS_RDONLY;
 
-               root = NILFS_I(sb->s_root->d_inode)->i_root;
+               root = NILFS_I(d_inode(sb->s_root))->i_root;
                err = nilfs_attach_log_writer(sb, root);
                if (err)
                        goto restore_opts;
index af1b24fa899d0322fc8614960f9bfb13bcdd816e..99521e7c492b087d67bfdf2a6d2a929c23014988 100644 (file)
--- a/fs/nsfs.c
+++ b/fs/nsfs.c
@@ -13,7 +13,7 @@ static const struct file_operations ns_file_operations = {
 
 static char *ns_dname(struct dentry *dentry, char *buffer, int buflen)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        const struct proc_ns_operations *ns_ops = dentry->d_fsdata;
 
        return dynamic_dname(dentry, buffer, buflen, "%s:[%lu]",
@@ -22,7 +22,7 @@ static char *ns_dname(struct dentry *dentry, char *buffer, int buflen)
 
 static void ns_prune_dentry(struct dentry *dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        if (inode) {
                struct ns_common *ns = inode->i_private;
                atomic_long_set(&ns->stashed, 0);
index 1d0c21df0d805cd73248afd42dc05c1108c49700..d284f07eda7754e721bfd2782ba410f04ae145e4 100644 (file)
@@ -2889,7 +2889,7 @@ void ntfs_truncate_vfs(struct inode *vi) {
  */
 int ntfs_setattr(struct dentry *dentry, struct iattr *attr)
 {
-       struct inode *vi = dentry->d_inode;
+       struct inode *vi = d_inode(dentry);
        int err;
        unsigned int ia_valid = attr->ia_valid;
 
index b3973c2fd19007e01bc7260a72b43e769849dd75..0f35b80d17fe019cdae356ecaba8359ac9f9a9a2 100644 (file)
@@ -292,14 +292,14 @@ const struct inode_operations ntfs_dir_inode_ops = {
  * The code is based on the ext3 ->get_parent() implementation found in
  * fs/ext3/namei.c::ext3_get_parent().
  *
- * Note: ntfs_get_parent() is called with @child_dent->d_inode->i_mutex down.
+ * Note: ntfs_get_parent() is called with @d_inode(child_dent)->i_mutex down.
  *
  * Return the dentry of the parent directory on success or the error code on
  * error (IS_ERR() is true).
  */
 static struct dentry *ntfs_get_parent(struct dentry *child_dent)
 {
-       struct inode *vi = child_dent->d_inode;
+       struct inode *vi = d_inode(child_dent);
        ntfs_inode *ni = NTFS_I(vi);
        MFT_RECORD *mrec;
        ntfs_attr_search_ctx *ctx;
index 8e19b9d7aba8f31ba528cd0571706718cb52318f..16eff45727eeaa055852c3c50c2febac5d647006 100644 (file)
@@ -1312,9 +1312,7 @@ static int o2hb_debug_init(void)
        int ret = -ENOMEM;
 
        o2hb_debug_dir = debugfs_create_dir(O2HB_DEBUG_DIR, NULL);
-       if (IS_ERR_OR_NULL(o2hb_debug_dir)) {
-               ret = o2hb_debug_dir ?
-                       PTR_ERR(o2hb_debug_dir) : -ENOMEM;
+       if (!o2hb_debug_dir) {
                mlog_errno(ret);
                goto bail;
        }
@@ -1327,9 +1325,7 @@ static int o2hb_debug_init(void)
                                                 sizeof(o2hb_live_node_bitmap),
                                                 O2NM_MAX_NODES,
                                                 o2hb_live_node_bitmap);
-       if (IS_ERR_OR_NULL(o2hb_debug_livenodes)) {
-               ret = o2hb_debug_livenodes ?
-                       PTR_ERR(o2hb_debug_livenodes) : -ENOMEM;
+       if (!o2hb_debug_livenodes) {
                mlog_errno(ret);
                goto bail;
        }
@@ -1342,9 +1338,7 @@ static int o2hb_debug_init(void)
                                                   sizeof(o2hb_live_region_bitmap),
                                                   O2NM_MAX_REGIONS,
                                                   o2hb_live_region_bitmap);
-       if (IS_ERR_OR_NULL(o2hb_debug_liveregions)) {
-               ret = o2hb_debug_liveregions ?
-                       PTR_ERR(o2hb_debug_liveregions) : -ENOMEM;
+       if (!o2hb_debug_liveregions) {
                mlog_errno(ret);
                goto bail;
        }
@@ -1358,9 +1352,7 @@ static int o2hb_debug_init(void)
                                          sizeof(o2hb_quorum_region_bitmap),
                                          O2NM_MAX_REGIONS,
                                          o2hb_quorum_region_bitmap);
-       if (IS_ERR_OR_NULL(o2hb_debug_quorumregions)) {
-               ret = o2hb_debug_quorumregions ?
-                       PTR_ERR(o2hb_debug_quorumregions) : -ENOMEM;
+       if (!o2hb_debug_quorumregions) {
                mlog_errno(ret);
                goto bail;
        }
@@ -1374,9 +1366,7 @@ static int o2hb_debug_init(void)
                                          sizeof(o2hb_failed_region_bitmap),
                                          O2NM_MAX_REGIONS,
                                          o2hb_failed_region_bitmap);
-       if (IS_ERR_OR_NULL(o2hb_debug_failedregions)) {
-               ret = o2hb_debug_failedregions ?
-                       PTR_ERR(o2hb_debug_failedregions) : -ENOMEM;
+       if (!o2hb_debug_failedregions) {
                mlog_errno(ret);
                goto bail;
        }
@@ -2010,8 +2000,7 @@ static int o2hb_debug_region_init(struct o2hb_region *reg, struct dentry *dir)
 
        reg->hr_debug_dir =
                debugfs_create_dir(config_item_name(&reg->hr_item), dir);
-       if (IS_ERR_OR_NULL(reg->hr_debug_dir)) {
-               ret = reg->hr_debug_dir ? PTR_ERR(reg->hr_debug_dir) : -ENOMEM;
+       if (!reg->hr_debug_dir) {
                mlog_errno(ret);
                goto bail;
        }
@@ -2024,9 +2013,7 @@ static int o2hb_debug_region_init(struct o2hb_region *reg, struct dentry *dir)
                                          O2HB_DB_TYPE_REGION_LIVENODES,
                                          sizeof(reg->hr_live_node_bitmap),
                                          O2NM_MAX_NODES, reg);
-       if (IS_ERR_OR_NULL(reg->hr_debug_livenodes)) {
-               ret = reg->hr_debug_livenodes ?
-                       PTR_ERR(reg->hr_debug_livenodes) : -ENOMEM;
+       if (!reg->hr_debug_livenodes) {
                mlog_errno(ret);
                goto bail;
        }
@@ -2038,9 +2025,7 @@ static int o2hb_debug_region_init(struct o2hb_region *reg, struct dentry *dir)
                                          sizeof(*(reg->hr_db_regnum)),
                                          O2HB_DB_TYPE_REGION_NUMBER,
                                          0, O2NM_MAX_NODES, reg);
-       if (IS_ERR_OR_NULL(reg->hr_debug_regnum)) {
-               ret = reg->hr_debug_regnum ?
-                       PTR_ERR(reg->hr_debug_regnum) : -ENOMEM;
+       if (!reg->hr_debug_regnum) {
                mlog_errno(ret);
                goto bail;
        }
@@ -2052,9 +2037,7 @@ static int o2hb_debug_region_init(struct o2hb_region *reg, struct dentry *dir)
                                          sizeof(*(reg->hr_db_elapsed_time)),
                                          O2HB_DB_TYPE_REGION_ELAPSED_TIME,
                                          0, 0, reg);
-       if (IS_ERR_OR_NULL(reg->hr_debug_elapsed_time)) {
-               ret = reg->hr_debug_elapsed_time ?
-                       PTR_ERR(reg->hr_debug_elapsed_time) : -ENOMEM;
+       if (!reg->hr_debug_elapsed_time) {
                mlog_errno(ret);
                goto bail;
        }
@@ -2066,16 +2049,13 @@ static int o2hb_debug_region_init(struct o2hb_region *reg, struct dentry *dir)
                                          sizeof(*(reg->hr_db_pinned)),
                                          O2HB_DB_TYPE_REGION_PINNED,
                                          0, 0, reg);
-       if (IS_ERR_OR_NULL(reg->hr_debug_pinned)) {
-               ret = reg->hr_debug_pinned ?
-                       PTR_ERR(reg->hr_debug_pinned) : -ENOMEM;
+       if (!reg->hr_debug_pinned) {
                mlog_errno(ret);
                goto bail;
        }
 
-       return 0;
+       ret = 0;
 bail:
-       debugfs_remove_recursive(reg->hr_debug_dir);
        return ret;
 }
 
index 4fda7a5f3088a7144240193508369ba259875a72..290373024d9d6798ce761a2c89aba0892bde4db7 100644 (file)
@@ -42,8 +42,8 @@
 void ocfs2_dentry_attach_gen(struct dentry *dentry)
 {
        unsigned long gen =
-               OCFS2_I(dentry->d_parent->d_inode)->ip_dir_lock_gen;
-       BUG_ON(dentry->d_inode);
+               OCFS2_I(d_inode(dentry->d_parent))->ip_dir_lock_gen;
+       BUG_ON(d_inode(dentry));
        dentry->d_fsdata = (void *)gen;
 }
 
@@ -57,7 +57,7 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry, unsigned int flags)
        if (flags & LOOKUP_RCU)
                return -ECHILD;
 
-       inode = dentry->d_inode;
+       inode = d_inode(dentry);
        osb = OCFS2_SB(dentry->d_sb);
 
        trace_ocfs2_dentry_revalidate(dentry, dentry->d_name.len,
@@ -71,7 +71,7 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry, unsigned int flags)
                unsigned long gen = (unsigned long) dentry->d_fsdata;
                unsigned long pgen;
                spin_lock(&dentry->d_lock);
-               pgen = OCFS2_I(dentry->d_parent->d_inode)->ip_dir_lock_gen;
+               pgen = OCFS2_I(d_inode(dentry->d_parent))->ip_dir_lock_gen;
                spin_unlock(&dentry->d_lock);
                trace_ocfs2_dentry_revalidate_negative(dentry->d_name.len,
                                                       dentry->d_name.name,
@@ -146,7 +146,7 @@ static int ocfs2_match_dentry(struct dentry *dentry,
        if (skip_unhashed && d_unhashed(dentry))
                return 0;
 
-       parent = dentry->d_parent->d_inode;
+       parent = d_inode(dentry->d_parent);
        /* Negative parent dentry? */
        if (!parent)
                return 0;
@@ -243,7 +243,7 @@ int ocfs2_dentry_attach_lock(struct dentry *dentry,
        if (!inode)
                return 0;
 
-       if (!dentry->d_inode && dentry->d_fsdata) {
+       if (d_really_is_negative(dentry) && dentry->d_fsdata) {
                /* Converting a negative dentry to positive
                   Clear dentry->d_fsdata */
                dentry->d_fsdata = dl = NULL;
@@ -446,7 +446,7 @@ void ocfs2_dentry_move(struct dentry *dentry, struct dentry *target,
 {
        int ret;
        struct ocfs2_super *osb = OCFS2_SB(old_dir->i_sb);
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
 
        /*
         * Move within the same directory, so the actual lock info won't
index f0344b75b14d26631993f260bc2e9f8aa9204892..3d8639f3897377dea5649155cfa6cfcb484a9195 100644 (file)
@@ -72,7 +72,7 @@ static inline int ocfs2_add_entry(handle_t *handle,
                                  struct buffer_head *parent_fe_bh,
                                  struct ocfs2_dir_lookup_result *lookup)
 {
-       return __ocfs2_add_entry(handle, dentry->d_parent->d_inode,
+       return __ocfs2_add_entry(handle, d_inode(dentry->d_parent),
                                 dentry->d_name.name, dentry->d_name.len,
                                 inode, blkno, parent_fe_bh, lookup);
 }
index a6944b25fd5b5ddba427ac66c8f50fb582cf1451..fdf4b41d0609a00e591afeed69ea7cc2ab9d5254 100644 (file)
@@ -757,6 +757,19 @@ lookup:
        if (tmpres) {
                spin_unlock(&dlm->spinlock);
                spin_lock(&tmpres->spinlock);
+
+               /*
+                * Right after dlm spinlock was released, dlm_thread could have
+                * purged the lockres. Check if lockres got unhashed. If so
+                * start over.
+                */
+               if (hlist_unhashed(&tmpres->hash_node)) {
+                       spin_unlock(&tmpres->spinlock);
+                       dlm_lockres_put(tmpres);
+                       tmpres = NULL;
+                       goto lookup;
+               }
+
                /* Wait on the thread that is mastering the resource */
                if (tmpres->owner == DLM_LOCK_RES_OWNER_UNKNOWN) {
                        __dlm_wait_on_lockres(tmpres);
index 061ba6a91bf2faa66ef1ea3ad797e47e202deeb7..b5cf27dcb18a78c71c3ef62410c3e4e7e7e641f9 100644 (file)
@@ -208,7 +208,7 @@ static int dlmfs_file_release(struct inode *inode,
 static int dlmfs_file_setattr(struct dentry *dentry, struct iattr *attr)
 {
        int error;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
 
        attr->ia_valid &= ~ATTR_SIZE;
        error = inode_change_ok(inode, attr);
@@ -549,7 +549,7 @@ static int dlmfs_unlink(struct inode *dir,
                        struct dentry *dentry)
 {
        int status;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
 
        mlog(0, "unlink inode %lu\n", inode->i_ino);
 
index 956edf67be20ba6b1711f6aa4c915aad9cead0a7..8b23aa2f52ddafe31be83b730d7219693222a1c5 100644 (file)
@@ -2959,7 +2959,7 @@ static int ocfs2_dlm_init_debug(struct ocfs2_super *osb)
                                                         osb->osb_debug_root,
                                                         osb,
                                                         &ocfs2_dlm_debug_fops);
-       if (IS_ERR_OR_NULL(dlm_debug->d_locking_state)) {
+       if (!dlm_debug->d_locking_state) {
                ret = -EINVAL;
                mlog(ML_ERROR,
                     "Unable to create locking state debugfs file.\n");
index 540dc4bdd042a5035f4a05e7fed0bc06548a1244..827fc9809bc271f09b2c3b7abf4019c31d0e1636 100644 (file)
@@ -147,7 +147,7 @@ static struct dentry *ocfs2_get_parent(struct dentry *child)
        int status;
        u64 blkno;
        struct dentry *parent;
-       struct inode *dir = child->d_inode;
+       struct inode *dir = d_inode(child);
 
        trace_ocfs2_get_parent(child, child->d_name.len, child->d_name.name,
                               (unsigned long long)OCFS2_I(dir)->ip_blkno);
index 913fc250d85a178b569f4d8ddd31b96a539208e0..d8b670cbd909292a6da33e5b16d3c16467727cb3 100644 (file)
@@ -1126,7 +1126,7 @@ out:
 int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
 {
        int status = 0, size_change;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct super_block *sb = inode->i_sb;
        struct ocfs2_super *osb = OCFS2_SB(sb);
        struct buffer_head *bh = NULL;
@@ -1275,8 +1275,8 @@ int ocfs2_getattr(struct vfsmount *mnt,
                  struct dentry *dentry,
                  struct kstat *stat)
 {
-       struct inode *inode = dentry->d_inode;
-       struct super_block *sb = dentry->d_inode->i_sb;
+       struct inode *inode = d_inode(dentry);
+       struct super_block *sb = d_inode(dentry)->i_sb;
        struct ocfs2_super *osb = sb->s_fs_info;
        int err;
 
@@ -2114,7 +2114,7 @@ static int ocfs2_prepare_inode_for_write(struct file *file,
 {
        int ret = 0, meta_level = 0;
        struct dentry *dentry = file->f_path.dentry;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        loff_t end;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        int full_coherency = !(osb->s_mount_opt &
index be71ca0937f742dce3bb4117c0e94fc8e093029c..b254416dc8d92d0fc1c66c0b2787e313de7712b5 100644 (file)
@@ -1209,7 +1209,7 @@ int ocfs2_drop_inode(struct inode *inode)
  */
 int ocfs2_inode_revalidate(struct dentry *dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int status = 0;
 
        trace_ocfs2_inode_revalidate(inode,
index 09f90cbf0e24d39ee0f8b27b2d056273f4bdf879..176fe6afd94eccf584c7ce8faa5556eee776457b 100644 (file)
@@ -689,8 +689,8 @@ static int ocfs2_link(struct dentry *old_dentry,
                      struct dentry *dentry)
 {
        handle_t *handle;
-       struct inode *inode = old_dentry->d_inode;
-       struct inode *old_dir = old_dentry->d_parent->d_inode;
+       struct inode *inode = d_inode(old_dentry);
+       struct inode *old_dir = d_inode(old_dentry->d_parent);
        int err;
        struct buffer_head *fe_bh = NULL;
        struct buffer_head *old_dir_bh = NULL;
@@ -879,7 +879,7 @@ static int ocfs2_unlink(struct inode *dir,
        int status;
        int child_locked = 0;
        bool is_unlinkable = false;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct inode *orphan_dir = NULL;
        struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
        u64 blkno;
@@ -898,7 +898,7 @@ static int ocfs2_unlink(struct inode *dir,
 
        dquot_initialize(dir);
 
-       BUG_ON(dentry->d_parent->d_inode != dir);
+       BUG_ON(d_inode(dentry->d_parent) != dir);
 
        if (inode == osb->root_inode)
                return -EPERM;
@@ -1209,8 +1209,8 @@ static int ocfs2_rename(struct inode *old_dir,
 {
        int status = 0, rename_lock = 0, parents_locked = 0, target_exists = 0;
        int old_child_locked = 0, new_child_locked = 0, update_dot_dot = 0;
-       struct inode *old_inode = old_dentry->d_inode;
-       struct inode *new_inode = new_dentry->d_inode;
+       struct inode *old_inode = d_inode(old_dentry);
+       struct inode *new_inode = d_inode(new_dentry);
        struct inode *orphan_dir = NULL;
        struct ocfs2_dinode *newfe = NULL;
        char orphan_name[OCFS2_ORPHAN_NAMELEN + 1];
@@ -1454,7 +1454,7 @@ static int ocfs2_rename(struct inode *old_dir,
                        should_add_orphan = true;
                }
        } else {
-               BUG_ON(new_dentry->d_parent->d_inode != new_dir);
+               BUG_ON(d_inode(new_dentry->d_parent) != new_dir);
 
                status = ocfs2_check_dir_for_entry(new_dir,
                                                   new_dentry->d_name.name,
index df3a500789c7eb7bfde662e9a391c86b99ef2a11..d8c6af101f3ff79ebb59589cdafab63a3f3c8f95 100644 (file)
@@ -4194,7 +4194,7 @@ static int __ocfs2_reflink(struct dentry *old_dentry,
                           bool preserve)
 {
        int ret;
-       struct inode *inode = old_dentry->d_inode;
+       struct inode *inode = d_inode(old_dentry);
        struct buffer_head *new_bh = NULL;
 
        if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_SYSTEM_FILE) {
@@ -4263,7 +4263,7 @@ static int ocfs2_reflink(struct dentry *old_dentry, struct inode *dir,
                         struct dentry *new_dentry, bool preserve)
 {
        int error;
-       struct inode *inode = old_dentry->d_inode;
+       struct inode *inode = d_inode(old_dentry);
        struct buffer_head *old_bh = NULL;
        struct inode *new_orphan_inode = NULL;
        struct posix_acl *default_acl, *acl;
@@ -4357,7 +4357,7 @@ out:
 /* copied from may_create in VFS. */
 static inline int ocfs2_may_create(struct inode *dir, struct dentry *child)
 {
-       if (child->d_inode)
+       if (d_really_is_positive(child))
                return -EEXIST;
        if (IS_DEADDIR(dir))
                return -ENOENT;
@@ -4375,7 +4375,7 @@ static inline int ocfs2_may_create(struct inode *dir, struct dentry *child)
 static int ocfs2_vfs_reflink(struct dentry *old_dentry, struct inode *dir,
                             struct dentry *new_dentry, bool preserve)
 {
-       struct inode *inode = old_dentry->d_inode;
+       struct inode *inode = d_inode(old_dentry);
        int error;
 
        if (!inode)
@@ -4463,7 +4463,7 @@ int ocfs2_reflink_ioctl(struct inode *inode,
        }
 
        error = ocfs2_vfs_reflink(old_path.dentry,
-                                 new_path.dentry->d_inode,
+                                 d_inode(new_path.dentry),
                                  new_dentry, preserve);
 out_dput:
        done_path_create(&new_path, new_dentry);
index 837ddce4b659fa99816114b07749081872967c8a..403c5660b30644a5c6f564ccaf795af4749e659a 100644 (file)
@@ -1112,7 +1112,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
 
        osb->osb_debug_root = debugfs_create_dir(osb->uuid_str,
                                                 ocfs2_debugfs_root);
-       if (IS_ERR_OR_NULL(osb->osb_debug_root)) {
+       if (!osb->osb_debug_root) {
                status = -EINVAL;
                mlog(ML_ERROR, "Unable to create per-mount debugfs root.\n");
                goto read_super_error;
@@ -1122,7 +1122,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
                                            osb->osb_debug_root,
                                            osb,
                                            &ocfs2_osb_debug_fops);
-       if (IS_ERR_OR_NULL(osb->osb_ctxt)) {
+       if (!osb->osb_ctxt) {
                status = -EINVAL;
                mlog_errno(status);
                goto read_super_error;
@@ -1606,9 +1606,8 @@ static int __init ocfs2_init(void)
        }
 
        ocfs2_debugfs_root = debugfs_create_dir("ocfs2", NULL);
-       if (IS_ERR_OR_NULL(ocfs2_debugfs_root)) {
-               status = ocfs2_debugfs_root ?
-                       PTR_ERR(ocfs2_debugfs_root) : -ENOMEM;
+       if (!ocfs2_debugfs_root) {
+               status = -ENOMEM;
                mlog(ML_ERROR, "Unable to create ocfs2 debugfs root.\n");
                goto out4;
        }
index 4ca7533be479105b51a6952298618f1d73294cf0..d03bfbf3d27d503b3b10bc912f30da9d494c1edb 100644 (file)
@@ -1020,7 +1020,7 @@ ssize_t ocfs2_listxattr(struct dentry *dentry,
        int ret = 0, i_ret = 0, b_ret = 0;
        struct buffer_head *di_bh = NULL;
        struct ocfs2_dinode *di = NULL;
-       struct ocfs2_inode_info *oi = OCFS2_I(dentry->d_inode);
+       struct ocfs2_inode_info *oi = OCFS2_I(d_inode(dentry));
 
        if (!ocfs2_supports_xattr(OCFS2_SB(dentry->d_sb)))
                return -EOPNOTSUPP;
@@ -1028,7 +1028,7 @@ ssize_t ocfs2_listxattr(struct dentry *dentry,
        if (!(oi->ip_dyn_features & OCFS2_HAS_XATTR_FL))
                return ret;
 
-       ret = ocfs2_inode_lock(dentry->d_inode, &di_bh, 0);
+       ret = ocfs2_inode_lock(d_inode(dentry), &di_bh, 0);
        if (ret < 0) {
                mlog_errno(ret);
                return ret;
@@ -1037,7 +1037,7 @@ ssize_t ocfs2_listxattr(struct dentry *dentry,
        di = (struct ocfs2_dinode *)di_bh->b_data;
 
        down_read(&oi->ip_xattr_sem);
-       i_ret = ocfs2_xattr_ibody_list(dentry->d_inode, di, buffer, size);
+       i_ret = ocfs2_xattr_ibody_list(d_inode(dentry), di, buffer, size);
        if (i_ret < 0)
                b_ret = 0;
        else {
@@ -1045,13 +1045,13 @@ ssize_t ocfs2_listxattr(struct dentry *dentry,
                        buffer += i_ret;
                        size -= i_ret;
                }
-               b_ret = ocfs2_xattr_block_list(dentry->d_inode, di,
+               b_ret = ocfs2_xattr_block_list(d_inode(dentry), di,
                                               buffer, size);
                if (b_ret < 0)
                        i_ret = 0;
        }
        up_read(&oi->ip_xattr_sem);
-       ocfs2_inode_unlock(dentry->d_inode, 0);
+       ocfs2_inode_unlock(d_inode(dentry), 0);
 
        brelse(di_bh);
 
@@ -7257,7 +7257,7 @@ static int ocfs2_xattr_security_get(struct dentry *dentry, const char *name,
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return ocfs2_xattr_get(dentry->d_inode, OCFS2_XATTR_INDEX_SECURITY,
+       return ocfs2_xattr_get(d_inode(dentry), OCFS2_XATTR_INDEX_SECURITY,
                               name, buffer, size);
 }
 
@@ -7267,7 +7267,7 @@ static int ocfs2_xattr_security_set(struct dentry *dentry, const char *name,
        if (strcmp(name, "") == 0)
                return -EINVAL;
 
-       return ocfs2_xattr_set(dentry->d_inode, OCFS2_XATTR_INDEX_SECURITY,
+       return ocfs2_xattr_set(d_inode(dentry), OCFS2_XATTR_INDEX_SECURITY,
                               name, value, size, flags);
 }
 
@@ -7347,7 +7347,7 @@ static int ocfs2_xattr_trusted_get(struct dentry *dentry, const char *name,
 {
        if (strcmp(name, "") == 0)
                return -EINVAL;
-       return ocfs2_xattr_get(dentry->d_inode, OCFS2_XATTR_INDEX_TRUSTED,
+       return ocfs2_xattr_get(d_inode(dentry), OCFS2_XATTR_INDEX_TRUSTED,
                               name, buffer, size);
 }
 
@@ -7357,7 +7357,7 @@ static int ocfs2_xattr_trusted_set(struct dentry *dentry, const char *name,
        if (strcmp(name, "") == 0)
                return -EINVAL;
 
-       return ocfs2_xattr_set(dentry->d_inode, OCFS2_XATTR_INDEX_TRUSTED,
+       return ocfs2_xattr_set(d_inode(dentry), OCFS2_XATTR_INDEX_TRUSTED,
                               name, value, size, flags);
 }
 
@@ -7399,7 +7399,7 @@ static int ocfs2_xattr_user_get(struct dentry *dentry, const char *name,
                return -EINVAL;
        if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR)
                return -EOPNOTSUPP;
-       return ocfs2_xattr_get(dentry->d_inode, OCFS2_XATTR_INDEX_USER, name,
+       return ocfs2_xattr_get(d_inode(dentry), OCFS2_XATTR_INDEX_USER, name,
                               buffer, size);
 }
 
@@ -7413,7 +7413,7 @@ static int ocfs2_xattr_user_set(struct dentry *dentry, const char *name,
        if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR)
                return -EOPNOTSUPP;
 
-       return ocfs2_xattr_set(dentry->d_inode, OCFS2_XATTR_INDEX_USER,
+       return ocfs2_xattr_set(d_inode(dentry), OCFS2_XATTR_INDEX_USER,
                               name, value, size, flags);
 }
 
index 1b8e9e8405b230169318a1d60df41c5b0b4f502d..f833bf8d5792928ff9cecacfe83f1efd3300df68 100644 (file)
@@ -110,7 +110,7 @@ int omfs_make_empty(struct inode *inode, struct super_block *sb)
 
 static int omfs_add_link(struct dentry *dentry, struct inode *inode)
 {
-       struct inode *dir = dentry->d_parent->d_inode;
+       struct inode *dir = d_inode(dentry->d_parent);
        const char *name = dentry->d_name.name;
        int namelen = dentry->d_name.len;
        struct omfs_inode *oi;
@@ -155,7 +155,7 @@ out:
 
 static int omfs_delete_entry(struct dentry *dentry)
 {
-       struct inode *dir = dentry->d_parent->d_inode;
+       struct inode *dir = d_inode(dentry->d_parent);
        struct inode *dirty;
        const char *name = dentry->d_name.name;
        int namelen = dentry->d_name.len;
@@ -237,7 +237,7 @@ static int omfs_dir_is_empty(struct inode *inode)
 
 static int omfs_remove(struct inode *dir, struct dentry *dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int ret;
 
 
@@ -373,8 +373,8 @@ static bool omfs_fill_chain(struct inode *dir, struct dir_context *ctx,
 static int omfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                struct inode *new_dir, struct dentry *new_dentry)
 {
-       struct inode *new_inode = new_dentry->d_inode;
-       struct inode *old_inode = old_dentry->d_inode;
+       struct inode *new_inode = d_inode(new_dentry);
+       struct inode *old_inode = d_inode(old_dentry);
        int err;
 
        if (new_inode) {
index f993be7f2156fcd863fcc28261add1326efd0146..d9e26cfbb793113f15b73bde769e49b69932bc9c 100644 (file)
@@ -346,7 +346,7 @@ const struct file_operations omfs_file_operations = {
 
 static int omfs_setattr(struct dentry *dentry, struct iattr *attr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int error;
 
        error = inode_change_ok(inode, attr);
index 6796f04d6032ab7e3009d3666bde640fdec37934..98e5a52dc68c9503136b8ff6a89b44dacd5478bf 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -231,8 +231,7 @@ int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
                return -EINVAL;
 
        /* Return error if mode is not supported */
-       if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE |
-                    FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_ZERO_RANGE))
+       if (mode & ~FALLOC_FL_SUPPORTED_MASK)
                return -EOPNOTSUPP;
 
        /* Punch hole and zero range are mutually exclusive */
@@ -250,6 +249,11 @@ int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
            (mode & ~FALLOC_FL_COLLAPSE_RANGE))
                return -EINVAL;
 
+       /* Insert range should only be used exclusively. */
+       if ((mode & FALLOC_FL_INSERT_RANGE) &&
+           (mode & ~FALLOC_FL_INSERT_RANGE))
+               return -EINVAL;
+
        if (!(file->f_mode & FMODE_WRITE))
                return -EBADF;
 
index 822da5b7cff06610bec61297ad2a3a688faf11b6..8865f796370074dbe7a191ab39c9645e80ed481d 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -627,7 +627,7 @@ static struct vfsmount *pipe_mnt __read_mostly;
 static char *pipefs_dname(struct dentry *dentry, char *buffer, int buflen)
 {
        return dynamic_dname(dentry, buffer, buflen, "pipe:[%lu]",
-                               dentry->d_inode->i_ino);
+                               d_inode(dentry)->i_ino);
 }
 
 static const struct dentry_operations pipefs_dentry_operations = {
index 3a48bb789c9f3e4eb227214f72798b90c52af5dc..84bb65b835701365126833a9e74d9e5d7a8a6c00 100644 (file)
@@ -774,12 +774,12 @@ posix_acl_xattr_get(struct dentry *dentry, const char *name,
        struct posix_acl *acl;
        int error;
 
-       if (!IS_POSIXACL(dentry->d_inode))
+       if (!IS_POSIXACL(d_backing_inode(dentry)))
                return -EOPNOTSUPP;
        if (d_is_symlink(dentry))
                return -EOPNOTSUPP;
 
-       acl = get_acl(dentry->d_inode, type);
+       acl = get_acl(d_backing_inode(dentry), type);
        if (IS_ERR(acl))
                return PTR_ERR(acl);
        if (acl == NULL)
@@ -795,7 +795,7 @@ static int
 posix_acl_xattr_set(struct dentry *dentry, const char *name,
                const void *value, size_t size, int flags, int type)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_backing_inode(dentry);
        struct posix_acl *acl = NULL;
        int ret;
 
@@ -834,7 +834,7 @@ posix_acl_xattr_list(struct dentry *dentry, char *list, size_t list_size,
        const char *xname;
        size_t size;
 
-       if (!IS_POSIXACL(dentry->d_inode))
+       if (!IS_POSIXACL(d_backing_inode(dentry)))
                return -EOPNOTSUPP;
        if (d_is_symlink(dentry))
                return -EOPNOTSUPP;
index 7a3b82f986dd7df1756a20926de1a5f8297092cf..093ca14f570154f5de1cc6db10c7995e1b7cba02 100644 (file)
@@ -169,7 +169,7 @@ static int get_task_root(struct task_struct *task, struct path *root)
 
 static int proc_cwd_link(struct dentry *dentry, struct path *path)
 {
-       struct task_struct *task = get_proc_task(dentry->d_inode);
+       struct task_struct *task = get_proc_task(d_inode(dentry));
        int result = -ENOENT;
 
        if (task) {
@@ -186,7 +186,7 @@ static int proc_cwd_link(struct dentry *dentry, struct path *path)
 
 static int proc_root_link(struct dentry *dentry, struct path *path)
 {
-       struct task_struct *task = get_proc_task(dentry->d_inode);
+       struct task_struct *task = get_proc_task(d_inode(dentry));
        int result = -ENOENT;
 
        if (task) {
@@ -514,7 +514,7 @@ static int proc_fd_access_allowed(struct inode *inode)
 int proc_setattr(struct dentry *dentry, struct iattr *attr)
 {
        int error;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
 
        if (attr->ia_valid & ATTR_MODE)
                return -EPERM;
@@ -1362,7 +1362,7 @@ static int proc_exe_link(struct dentry *dentry, struct path *exe_path)
        struct mm_struct *mm;
        struct file *exe_file;
 
-       task = get_proc_task(dentry->d_inode);
+       task = get_proc_task(d_inode(dentry));
        if (!task)
                return -ENOENT;
        mm = get_task_mm(task);
@@ -1382,7 +1382,7 @@ static int proc_exe_link(struct dentry *dentry, struct path *exe_path)
 
 static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct path path;
        int error = -EACCES;
 
@@ -1427,7 +1427,7 @@ static int do_proc_readlink(struct path *path, char __user *buffer, int buflen)
 static int proc_pid_readlink(struct dentry * dentry, char __user * buffer, int buflen)
 {
        int error = -EACCES;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct path path;
 
        /* Are we allowed to snoop on the tasks file descriptors? */
@@ -1497,7 +1497,7 @@ out_unlock:
 
 int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct task_struct *task;
        const struct cred *cred;
        struct pid_namespace *pid = dentry->d_sb->s_fs_info;
@@ -1554,7 +1554,7 @@ int pid_revalidate(struct dentry *dentry, unsigned int flags)
        if (flags & LOOKUP_RCU)
                return -ECHILD;
 
-       inode = dentry->d_inode;
+       inode = d_inode(dentry);
        task = get_proc_task(inode);
 
        if (task) {
@@ -1588,7 +1588,7 @@ int pid_delete_dentry(const struct dentry *dentry)
         * If so, then don't put the dentry on the lru list,
         * kill it immediately.
         */
-       return proc_inode_is_dead(dentry->d_inode);
+       return proc_inode_is_dead(d_inode(dentry));
 }
 
 const struct dentry_operations pid_dentry_operations =
@@ -1626,12 +1626,12 @@ bool proc_fill_cache(struct file *file, struct dir_context *ctx,
                child = d_alloc(dir, &qname);
                if (!child)
                        goto end_instantiate;
-               if (instantiate(dir->d_inode, child, task, ptr) < 0) {
+               if (instantiate(d_inode(dir), child, task, ptr) < 0) {
                        dput(child);
                        goto end_instantiate;
                }
        }
-       inode = child->d_inode;
+       inode = d_inode(child);
        ino = inode->i_ino;
        type = inode->i_mode >> 12;
        dput(child);
@@ -1674,7 +1674,7 @@ static int map_files_d_revalidate(struct dentry *dentry, unsigned int flags)
                goto out_notask;
        }
 
-       inode = dentry->d_inode;
+       inode = d_inode(dentry);
        task = get_proc_task(inode);
        if (!task)
                goto out_notask;
@@ -1727,7 +1727,7 @@ static int proc_map_files_get_link(struct dentry *dentry, struct path *path)
        int rc;
 
        rc = -ENOENT;
-       task = get_proc_task(dentry->d_inode);
+       task = get_proc_task(d_inode(dentry));
        if (!task)
                goto out;
 
@@ -2863,13 +2863,13 @@ int proc_pid_readdir(struct file *file, struct dir_context *ctx)
                return 0;
 
        if (pos == TGID_OFFSET - 2) {
-               struct inode *inode = ns->proc_self->d_inode;
+               struct inode *inode = d_inode(ns->proc_self);
                if (!dir_emit(ctx, "self", 4, inode->i_ino, DT_LNK))
                        return 0;
                ctx->pos = pos = pos + 1;
        }
        if (pos == TGID_OFFSET - 1) {
-               struct inode *inode = ns->proc_thread_self->d_inode;
+               struct inode *inode = d_inode(ns->proc_thread_self);
                if (!dir_emit(ctx, "thread-self", 11, inode->i_ino, DT_LNK))
                        return 0;
                ctx->pos = pos = pos + 1;
@@ -3188,7 +3188,7 @@ static int proc_task_readdir(struct file *file, struct dir_context *ctx)
 
 static int proc_task_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct task_struct *p = get_proc_task(inode);
        generic_fillattr(inode, stat);
 
index af84ad04df7713a9c590c2de94537b385803059e..6e5fcd00733e0bafa432dcee3ea9a256c3445a4a 100644 (file)
@@ -91,7 +91,7 @@ static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags)
        if (flags & LOOKUP_RCU)
                return -ECHILD;
 
-       inode = dentry->d_inode;
+       inode = d_inode(dentry);
        task = get_proc_task(inode);
        fd = proc_fd(inode);
 
@@ -151,14 +151,14 @@ static int proc_fd_link(struct dentry *dentry, struct path *path)
        struct task_struct *task;
        int ret = -ENOENT;
 
-       task = get_proc_task(dentry->d_inode);
+       task = get_proc_task(d_inode(dentry));
        if (task) {
                files = get_files_struct(task);
                put_task_struct(task);
        }
 
        if (files) {
-               int fd = proc_fd(dentry->d_inode);
+               int fd = proc_fd(d_inode(dentry));
                struct file *fd_file;
 
                spin_lock(&files->file_lock);
index be65b208213518f267d9fe16b5652b5021700cf5..df6327a2b86507b371608a752f65bf12241bf38c 100644 (file)
@@ -101,7 +101,7 @@ static bool pde_subdir_insert(struct proc_dir_entry *dir,
 
 static int proc_notify_change(struct dentry *dentry, struct iattr *iattr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct proc_dir_entry *de = PDE(inode);
        int error;
 
@@ -120,7 +120,7 @@ static int proc_notify_change(struct dentry *dentry, struct iattr *iattr)
 static int proc_getattr(struct vfsmount *mnt, struct dentry *dentry,
                        struct kstat *stat)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct proc_dir_entry *de = PDE(inode);
        if (de && de->nlink)
                set_nlink(inode, de->nlink);
index 7697b6621cfd5b13051318ba15920646942ed528..8272aaba1bb06fd4b65416979155f18b590291a4 100644 (file)
@@ -396,7 +396,7 @@ static const struct file_operations proc_reg_file_ops_no_compat = {
 
 static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-       struct proc_dir_entry *pde = PDE(dentry->d_inode);
+       struct proc_dir_entry *pde = PDE(d_inode(dentry));
        if (unlikely(!use_pde(pde)))
                return ERR_PTR(-EINVAL);
        nd_set_link(nd, pde->data);
index c9eac4563fa8ab497dfbc492d4d63f2c6105df9b..e512642dbbdcb3cfe37f97b586770d695e2a755f 100644 (file)
@@ -32,7 +32,7 @@ static const struct proc_ns_operations *ns_entries[] = {
 
 static void *proc_ns_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns_ops;
        struct task_struct *task;
        struct path ns_path;
@@ -53,7 +53,7 @@ static void *proc_ns_follow_link(struct dentry *dentry, struct nameidata *nd)
 
 static int proc_ns_readlink(struct dentry *dentry, char __user *buffer, int buflen)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns_ops;
        struct task_struct *task;
        char name[50];
index 1bde894bc6248f4c8eba370ae062fa6115e6a492..350984a19c83440e09b6b1dafd87dc150dd078da 100644 (file)
@@ -142,7 +142,7 @@ static struct dentry *proc_tgid_net_lookup(struct inode *dir,
 static int proc_tgid_net_getattr(struct vfsmount *mnt, struct dentry *dentry,
                struct kstat *stat)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct net *net;
 
        net = get_proc_task_net(inode);
index f92d5dd578a4a5289aab9e29dcd37b09ee775c46..fea2561d773bbce01c9858f91ec5fec58f9f7481 100644 (file)
@@ -604,7 +604,7 @@ static bool proc_sys_fill_cache(struct file *file,
                        return false;
                }
        }
-       inode = child->d_inode;
+       inode = d_inode(child);
        ino  = inode->i_ino;
        type = inode->i_mode >> 12;
        dput(child);
@@ -710,7 +710,7 @@ static int proc_sys_permission(struct inode *inode, int mask)
 
 static int proc_sys_setattr(struct dentry *dentry, struct iattr *attr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int error;
 
        if (attr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID))
@@ -727,7 +727,7 @@ static int proc_sys_setattr(struct dentry *dentry, struct iattr *attr)
 
 static int proc_sys_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct ctl_table_header *head = grab_header(inode);
        struct ctl_table *table = PROC_I(inode)->sysctl_entry;
 
@@ -773,12 +773,12 @@ static int proc_sys_revalidate(struct dentry *dentry, unsigned int flags)
 {
        if (flags & LOOKUP_RCU)
                return -ECHILD;
-       return !PROC_I(dentry->d_inode)->sysctl->unregistering;
+       return !PROC_I(d_inode(dentry))->sysctl->unregistering;
 }
 
 static int proc_sys_delete(const struct dentry *dentry)
 {
-       return !!PROC_I(dentry->d_inode)->sysctl->unregistering;
+       return !!PROC_I(d_inode(dentry))->sysctl->unregistering;
 }
 
 static int sysctl_is_seen(struct ctl_table_header *p)
@@ -805,7 +805,7 @@ static int proc_sys_compare(const struct dentry *parent, const struct dentry *de
        /* Although proc doesn't have negative dentries, rcu-walk means
         * that inode here can be NULL */
        /* AV: can it, indeed? */
-       inode = ACCESS_ONCE(dentry->d_inode);
+       inode = d_inode_rcu(dentry);
        if (!inode)
                return 1;
        if (name->len != len)
index e74ac9f1a2c09cdec0621b244b0d9abc8de44699..b7fa4bfe896a2c17f05dd97add756bed889fd2b6 100644 (file)
@@ -195,7 +195,7 @@ void __init proc_root_init(void)
 static int proc_root_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat
 )
 {
-       generic_fillattr(dentry->d_inode, stat);
+       generic_fillattr(d_inode(dentry), stat);
        stat->nlink = proc_root.nlink + nr_processes();
        return 0;
 }
index 4348bb8907c20a6abc211b9fa944eca005d6f47c..6195b4a7c3b17f8c7feb09542e7e435b2cd59356 100644 (file)
@@ -46,7 +46,7 @@ static unsigned self_inum;
 
 int proc_setup_self(struct super_block *s)
 {
-       struct inode *root_inode = s->s_root->d_inode;
+       struct inode *root_inode = d_inode(s->s_root);
        struct pid_namespace *ns = s->s_fs_info;
        struct dentry *self;
        
index 59075b509df31df6777ee7c22928b976e0801418..a8371993b4fb7822b865cd4b2a02bc63d9642fa7 100644 (file)
@@ -47,7 +47,7 @@ static unsigned thread_self_inum;
 
 int proc_setup_thread_self(struct super_block *s)
 {
-       struct inode *root_inode = s->s_root->d_inode;
+       struct inode *root_inode = d_inode(s->s_root);
        struct pid_namespace *ns = s->s_fs_info;
        struct dentry *thread_self;
 
index 56e1ffda4d8936173d70684b0e4f82ee8f8d4688..dc43b5f29305efdd7ee94b72035b3e5b3ba11d17 100644 (file)
@@ -190,7 +190,7 @@ static const struct file_operations pstore_file_operations = {
  */
 static int pstore_unlink(struct inode *dir, struct dentry *dentry)
 {
-       struct pstore_private *p = dentry->d_inode->i_private;
+       struct pstore_private *p = d_inode(dentry)->i_private;
        int err;
 
        err = pstore_check_syslog_permissions(p);
@@ -199,7 +199,7 @@ static int pstore_unlink(struct inode *dir, struct dentry *dentry)
 
        if (p->psi->erase)
                p->psi->erase(p->type, p->id, p->count,
-                             dentry->d_inode->i_ctime, p->psi);
+                             d_inode(dentry)->i_ctime, p->psi);
        else
                return -EPERM;
 
@@ -376,7 +376,7 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id, int count,
                break;
        }
 
-       mutex_lock(&root->d_inode->i_mutex);
+       mutex_lock(&d_inode(root)->i_mutex);
 
        dentry = d_alloc_name(root, name);
        if (!dentry)
@@ -396,12 +396,12 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id, int count,
        list_add(&private->list, &allpstore);
        spin_unlock_irqrestore(&allpstore_lock, flags);
 
-       mutex_unlock(&root->d_inode->i_mutex);
+       mutex_unlock(&d_inode(root)->i_mutex);
 
        return 0;
 
 fail_lockedalloc:
-       mutex_unlock(&root->d_inode->i_mutex);
+       mutex_unlock(&d_inode(root)->i_mutex);
        kfree(private);
 fail_alloc:
        iput(inode);
index 44e73923670d59a0c7663804d8710fb3262c6106..32d2e1a9774ca66005d92786df99a70865efb3fa 100644 (file)
@@ -182,7 +182,7 @@ static const char *qnx6_checkroot(struct super_block *s)
        static char match_root[2][3] = {".\0\0", "..\0"};
        int i, error = 0;
        struct qnx6_dir_entry *dir_entry;
-       struct inode *root = s->s_root->d_inode;
+       struct inode *root = d_inode(s->s_root);
        struct address_space *mapping = root->i_mapping;
        struct page *page = read_mapping_page(mapping, 0, NULL);
        if (IS_ERR(page))
index ecc25cf0ee6e99f96b8d4c7550d8881593c303cf..20d1f74561cf1354b6c5c2d5dabcb8052cf14a73 100644 (file)
@@ -2328,7 +2328,7 @@ int dquot_quota_on(struct super_block *sb, int type, int format_id,
        if (path->dentry->d_sb != sb)
                error = -EXDEV;
        else
-               error = vfs_load_quota_inode(path->dentry->d_inode, type,
+               error = vfs_load_quota_inode(d_inode(path->dentry), type,
                                             format_id, DQUOT_USAGE_ENABLED |
                                             DQUOT_LIMITS_ENABLED);
        return error;
@@ -2392,20 +2392,20 @@ int dquot_quota_on_mount(struct super_block *sb, char *qf_name,
        struct dentry *dentry;
        int error;
 
-       mutex_lock(&sb->s_root->d_inode->i_mutex);
+       mutex_lock(&d_inode(sb->s_root)->i_mutex);
        dentry = lookup_one_len(qf_name, sb->s_root, strlen(qf_name));
-       mutex_unlock(&sb->s_root->d_inode->i_mutex);
+       mutex_unlock(&d_inode(sb->s_root)->i_mutex);
        if (IS_ERR(dentry))
                return PTR_ERR(dentry);
 
-       if (!dentry->d_inode) {
+       if (d_really_is_negative(dentry)) {
                error = -ENOENT;
                goto out;
        }
 
        error = security_quota_on(dentry);
        if (!error)
-               error = vfs_load_quota_inode(dentry->d_inode, type, format_id,
+               error = vfs_load_quota_inode(d_inode(dentry), type, format_id,
                                DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
 
 out:
index 0b38befa69f356b03b34175f9f629feaf4c8d0fa..ba1323a94924962299d27cbe67d76ff4e0056bb9 100644 (file)
@@ -163,7 +163,7 @@ static int ramfs_nommu_resize(struct inode *inode, loff_t newsize, loff_t size)
  */
 static int ramfs_nommu_setattr(struct dentry *dentry, struct iattr *ia)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        unsigned int old_ia_valid = ia->ia_valid;
        int ret = 0;
 
index 0a7dc941aaf4dc7190b4ac3864765f6688b11683..4a024e2ceb9f76fbf9156d0dc84c3e09a4a1ff15 100644 (file)
@@ -53,8 +53,8 @@ static int reiserfs_dir_fsync(struct file *filp, loff_t start, loff_t end,
 static inline bool is_privroot_deh(struct inode *dir, struct reiserfs_de_head *deh)
 {
        struct dentry *privroot = REISERFS_SB(dir->i_sb)->priv_root;
-       return (privroot->d_inode &&
-               deh->deh_objectid == INODE_PKEY(privroot->d_inode)->k_objectid);
+       return (d_really_is_positive(privroot) &&
+               deh->deh_objectid == INODE_PKEY(d_inode(privroot))->k_objectid);
 }
 
 int reiserfs_readdir_inode(struct inode *inode, struct dir_context *ctx)
index 742242b60972671c50926f9a0dd0db48c4e7aeca..f6f2fbad9777d3cc9fd50e9295973ed6f10577a2 100644 (file)
@@ -3308,7 +3308,7 @@ static ssize_t reiserfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
 
 int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        unsigned int ia_valid;
        int error;
 
index cd11358b10c7a1e427394f78ca8334e67f3c9467..b55a074653d7a4ae7722b1df6d31655566527734 100644 (file)
@@ -400,7 +400,7 @@ struct dentry *reiserfs_get_parent(struct dentry *child)
        struct inode *inode = NULL;
        struct reiserfs_dir_entry de;
        INITIALIZE_PATH(path_to_entry);
-       struct inode *dir = child->d_inode;
+       struct inode *dir = d_inode(child);
 
        if (dir->i_nlink == 0) {
                return ERR_PTR(-ENOENT);
@@ -917,7 +917,7 @@ static int reiserfs_rmdir(struct inode *dir, struct dentry *dentry)
                goto end_rmdir;
        }
 
-       inode = dentry->d_inode;
+       inode = d_inode(dentry);
 
        reiserfs_update_inode_transaction(inode);
        reiserfs_update_inode_transaction(dir);
@@ -987,7 +987,7 @@ static int reiserfs_unlink(struct inode *dir, struct dentry *dentry)
 
        dquot_initialize(dir);
 
-       inode = dentry->d_inode;
+       inode = d_inode(dentry);
 
        /*
         * in this transaction we can be doing at max two balancings and
@@ -1174,7 +1174,7 @@ static int reiserfs_link(struct dentry *old_dentry, struct inode *dir,
                         struct dentry *dentry)
 {
        int retval;
-       struct inode *inode = old_dentry->d_inode;
+       struct inode *inode = d_inode(old_dentry);
        struct reiserfs_transaction_handle th;
        /*
         * We need blocks for transaction + update of quotas for
@@ -1311,8 +1311,8 @@ static int reiserfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        dquot_initialize(old_dir);
        dquot_initialize(new_dir);
 
-       old_inode = old_dentry->d_inode;
-       new_dentry_inode = new_dentry->d_inode;
+       old_inode = d_inode(old_dentry);
+       new_dentry_inode = d_inode(new_dentry);
 
        /*
         * make sure that oldname still exists and points to an object we
index 68b5f182984e245c786f05cf29a6e148d2466654..0111ad0466ed42146f652db0be879b7335ab28df 100644 (file)
@@ -1687,7 +1687,7 @@ static __u32 find_hash_out(struct super_block *s)
        __u32 hash = DEFAULT_HASH;
        __u32 deh_hashval, teahash, r5hash, yurahash;
 
-       inode = s->s_root->d_inode;
+       inode = d_inode(s->s_root);
 
        make_cpu_key(&key, inode, ~0, TYPE_DIRENTRY, 3);
        retval = search_by_entry_key(s, &key, &path, &de);
@@ -2347,7 +2347,7 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
                err = -EXDEV;
                goto out;
        }
-       inode = path->dentry->d_inode;
+       inode = d_inode(path->dentry);
        /*
         * We must not pack tails for quota files on reiserfs for quota
         * IO to work
index 4e781e697c90bce3b42f0e0097fe46965bbb5258..e87f9b52bf069af087979782767b6c3471689fd5 100644 (file)
@@ -87,9 +87,9 @@ static int xattr_unlink(struct inode *dir, struct dentry *dentry)
 
        BUG_ON(!mutex_is_locked(&dir->i_mutex));
 
-       mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD);
+       mutex_lock_nested(&d_inode(dentry)->i_mutex, I_MUTEX_CHILD);
        error = dir->i_op->unlink(dir, dentry);
-       mutex_unlock(&dentry->d_inode->i_mutex);
+       mutex_unlock(&d_inode(dentry)->i_mutex);
 
        if (!error)
                d_delete(dentry);
@@ -102,11 +102,11 @@ static int xattr_rmdir(struct inode *dir, struct dentry *dentry)
 
        BUG_ON(!mutex_is_locked(&dir->i_mutex));
 
-       mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD);
+       mutex_lock_nested(&d_inode(dentry)->i_mutex, I_MUTEX_CHILD);
        error = dir->i_op->rmdir(dir, dentry);
        if (!error)
-               dentry->d_inode->i_flags |= S_DEAD;
-       mutex_unlock(&dentry->d_inode->i_mutex);
+               d_inode(dentry)->i_flags |= S_DEAD;
+       mutex_unlock(&d_inode(dentry)->i_mutex);
        if (!error)
                d_delete(dentry);
 
@@ -120,26 +120,26 @@ static struct dentry *open_xa_root(struct super_block *sb, int flags)
        struct dentry *privroot = REISERFS_SB(sb)->priv_root;
        struct dentry *xaroot;
 
-       if (!privroot->d_inode)
+       if (d_really_is_negative(privroot))
                return ERR_PTR(-ENODATA);
 
-       mutex_lock_nested(&privroot->d_inode->i_mutex, I_MUTEX_XATTR);
+       mutex_lock_nested(&d_inode(privroot)->i_mutex, I_MUTEX_XATTR);
 
        xaroot = dget(REISERFS_SB(sb)->xattr_root);
        if (!xaroot)
                xaroot = ERR_PTR(-ENODATA);
-       else if (!xaroot->d_inode) {
+       else if (d_really_is_negative(xaroot)) {
                int err = -ENODATA;
 
                if (xattr_may_create(flags))
-                       err = xattr_mkdir(privroot->d_inode, xaroot, 0700);
+                       err = xattr_mkdir(d_inode(privroot), xaroot, 0700);
                if (err) {
                        dput(xaroot);
                        xaroot = ERR_PTR(err);
                }
        }
 
-       mutex_unlock(&privroot->d_inode->i_mutex);
+       mutex_unlock(&d_inode(privroot)->i_mutex);
        return xaroot;
 }
 
@@ -156,21 +156,21 @@ static struct dentry *open_xa_dir(const struct inode *inode, int flags)
                 le32_to_cpu(INODE_PKEY(inode)->k_objectid),
                 inode->i_generation);
 
-       mutex_lock_nested(&xaroot->d_inode->i_mutex, I_MUTEX_XATTR);
+       mutex_lock_nested(&d_inode(xaroot)->i_mutex, I_MUTEX_XATTR);
 
        xadir = lookup_one_len(namebuf, xaroot, strlen(namebuf));
-       if (!IS_ERR(xadir) && !xadir->d_inode) {
+       if (!IS_ERR(xadir) && d_really_is_negative(xadir)) {
                int err = -ENODATA;
 
                if (xattr_may_create(flags))
-                       err = xattr_mkdir(xaroot->d_inode, xadir, 0700);
+                       err = xattr_mkdir(d_inode(xaroot), xadir, 0700);
                if (err) {
                        dput(xadir);
                        xadir = ERR_PTR(err);
                }
        }
 
-       mutex_unlock(&xaroot->d_inode->i_mutex);
+       mutex_unlock(&d_inode(xaroot)->i_mutex);
        dput(xaroot);
        return xadir;
 }
@@ -195,7 +195,7 @@ fill_with_dentries(struct dir_context *ctx, const char *name, int namelen,
                container_of(ctx, struct reiserfs_dentry_buf, ctx);
        struct dentry *dentry;
 
-       WARN_ON_ONCE(!mutex_is_locked(&dbuf->xadir->d_inode->i_mutex));
+       WARN_ON_ONCE(!mutex_is_locked(&d_inode(dbuf->xadir)->i_mutex));
 
        if (dbuf->count == ARRAY_SIZE(dbuf->dentries))
                return -ENOSPC;
@@ -207,7 +207,7 @@ fill_with_dentries(struct dir_context *ctx, const char *name, int namelen,
        dentry = lookup_one_len(name, dbuf->xadir, namelen);
        if (IS_ERR(dentry)) {
                return PTR_ERR(dentry);
-       } else if (!dentry->d_inode) {
+       } else if (d_really_is_negative(dentry)) {
                /* A directory entry exists, but no file? */
                reiserfs_error(dentry->d_sb, "xattr-20003",
                               "Corrupted directory: xattr %pd listed but "
@@ -249,16 +249,16 @@ static int reiserfs_for_each_xattr(struct inode *inode,
        if (IS_ERR(dir)) {
                err = PTR_ERR(dir);
                goto out;
-       } else if (!dir->d_inode) {
+       } else if (d_really_is_negative(dir)) {
                err = 0;
                goto out_dir;
        }
 
-       mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR);
+       mutex_lock_nested(&d_inode(dir)->i_mutex, I_MUTEX_XATTR);
 
        buf.xadir = dir;
        while (1) {
-               err = reiserfs_readdir_inode(dir->d_inode, &buf.ctx);
+               err = reiserfs_readdir_inode(d_inode(dir), &buf.ctx);
                if (err)
                        break;
                if (!buf.count)
@@ -276,7 +276,7 @@ static int reiserfs_for_each_xattr(struct inode *inode,
                        break;
                buf.count = 0;
        }
-       mutex_unlock(&dir->d_inode->i_mutex);
+       mutex_unlock(&d_inode(dir)->i_mutex);
 
        cleanup_dentry_buf(&buf);
 
@@ -298,13 +298,13 @@ static int reiserfs_for_each_xattr(struct inode *inode,
                if (!err) {
                        int jerror;
 
-                       mutex_lock_nested(&dir->d_parent->d_inode->i_mutex,
+                       mutex_lock_nested(&d_inode(dir->d_parent)->i_mutex,
                                          I_MUTEX_XATTR);
                        err = action(dir, data);
                        reiserfs_write_lock(inode->i_sb);
                        jerror = journal_end(&th);
                        reiserfs_write_unlock(inode->i_sb);
-                       mutex_unlock(&dir->d_parent->d_inode->i_mutex);
+                       mutex_unlock(&d_inode(dir->d_parent)->i_mutex);
                        err = jerror ?: err;
                }
        }
@@ -319,7 +319,7 @@ out:
 
 static int delete_one_xattr(struct dentry *dentry, void *data)
 {
-       struct inode *dir = dentry->d_parent->d_inode;
+       struct inode *dir = d_inode(dentry->d_parent);
 
        /* This is the xattr dir, handle specially. */
        if (d_is_dir(dentry))
@@ -384,27 +384,27 @@ static struct dentry *xattr_lookup(struct inode *inode, const char *name,
        if (IS_ERR(xadir))
                return ERR_CAST(xadir);
 
-       mutex_lock_nested(&xadir->d_inode->i_mutex, I_MUTEX_XATTR);
+       mutex_lock_nested(&d_inode(xadir)->i_mutex, I_MUTEX_XATTR);
        xafile = lookup_one_len(name, xadir, strlen(name));
        if (IS_ERR(xafile)) {
                err = PTR_ERR(xafile);
                goto out;
        }
 
-       if (xafile->d_inode && (flags & XATTR_CREATE))
+       if (d_really_is_positive(xafile) && (flags & XATTR_CREATE))
                err = -EEXIST;
 
-       if (!xafile->d_inode) {
+       if (d_really_is_negative(xafile)) {
                err = -ENODATA;
                if (xattr_may_create(flags))
-                       err = xattr_create(xadir->d_inode, xafile,
+                       err = xattr_create(d_inode(xadir), xafile,
                                              0700|S_IFREG);
        }
 
        if (err)
                dput(xafile);
 out:
-       mutex_unlock(&xadir->d_inode->i_mutex);
+       mutex_unlock(&d_inode(xadir)->i_mutex);
        dput(xadir);
        if (err)
                return ERR_PTR(err);
@@ -469,21 +469,21 @@ static int lookup_and_delete_xattr(struct inode *inode, const char *name)
        if (IS_ERR(xadir))
                return PTR_ERR(xadir);
 
-       mutex_lock_nested(&xadir->d_inode->i_mutex, I_MUTEX_XATTR);
+       mutex_lock_nested(&d_inode(xadir)->i_mutex, I_MUTEX_XATTR);
        dentry = lookup_one_len(name, xadir, strlen(name));
        if (IS_ERR(dentry)) {
                err = PTR_ERR(dentry);
                goto out_dput;
        }
 
-       if (dentry->d_inode) {
-               err = xattr_unlink(xadir->d_inode, dentry);
+       if (d_really_is_positive(dentry)) {
+               err = xattr_unlink(d_inode(xadir), dentry);
                update_ctime(inode);
        }
 
        dput(dentry);
 out_dput:
-       mutex_unlock(&xadir->d_inode->i_mutex);
+       mutex_unlock(&d_inode(xadir)->i_mutex);
        dput(xadir);
        return err;
 }
@@ -533,7 +533,7 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th,
                else
                        chunk = buffer_size - buffer_pos;
 
-               page = reiserfs_get_page(dentry->d_inode, file_pos);
+               page = reiserfs_get_page(d_inode(dentry), file_pos);
                if (IS_ERR(page)) {
                        err = PTR_ERR(page);
                        goto out_unlock;
@@ -573,18 +573,18 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th,
        }
 
        new_size = buffer_size + sizeof(struct reiserfs_xattr_header);
-       if (!err && new_size < i_size_read(dentry->d_inode)) {
+       if (!err && new_size < i_size_read(d_inode(dentry))) {
                struct iattr newattrs = {
                        .ia_ctime = current_fs_time(inode->i_sb),
                        .ia_size = new_size,
                        .ia_valid = ATTR_SIZE | ATTR_CTIME,
                };
 
-               mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_XATTR);
-               inode_dio_wait(dentry->d_inode);
+               mutex_lock_nested(&d_inode(dentry)->i_mutex, I_MUTEX_XATTR);
+               inode_dio_wait(d_inode(dentry));
 
                err = reiserfs_setattr(dentry, &newattrs);
-               mutex_unlock(&dentry->d_inode->i_mutex);
+               mutex_unlock(&d_inode(dentry)->i_mutex);
        } else
                update_ctime(inode);
 out_unlock:
@@ -657,7 +657,7 @@ reiserfs_xattr_get(struct inode *inode, const char *name, void *buffer,
 
        down_read(&REISERFS_I(inode)->i_xattr_sem);
 
-       isize = i_size_read(dentry->d_inode);
+       isize = i_size_read(d_inode(dentry));
 
        /* Just return the size needed */
        if (buffer == NULL) {
@@ -680,7 +680,7 @@ reiserfs_xattr_get(struct inode *inode, const char *name, void *buffer,
                else
                        chunk = isize - file_pos;
 
-               page = reiserfs_get_page(dentry->d_inode, file_pos);
+               page = reiserfs_get_page(d_inode(dentry), file_pos);
                if (IS_ERR(page)) {
                        err = PTR_ERR(page);
                        goto out_unlock;
@@ -775,7 +775,7 @@ reiserfs_getxattr(struct dentry * dentry, const char *name, void *buffer,
 
        handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name);
 
-       if (!handler || get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
+       if (!handler || get_inode_sd_version(d_inode(dentry)) == STAT_DATA_V1)
                return -EOPNOTSUPP;
 
        return handler->get(dentry, name, buffer, size, handler->flags);
@@ -784,7 +784,7 @@ reiserfs_getxattr(struct dentry * dentry, const char *name, void *buffer,
 /*
  * Inode operation setxattr()
  *
- * dentry->d_inode->i_mutex down
+ * d_inode(dentry)->i_mutex down
  */
 int
 reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value,
@@ -794,7 +794,7 @@ reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value,
 
        handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name);
 
-       if (!handler || get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
+       if (!handler || get_inode_sd_version(d_inode(dentry)) == STAT_DATA_V1)
                return -EOPNOTSUPP;
 
        return handler->set(dentry, name, value, size, flags, handler->flags);
@@ -803,7 +803,7 @@ reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value,
 /*
  * Inode operation removexattr()
  *
- * dentry->d_inode->i_mutex down
+ * d_inode(dentry)->i_mutex down
  */
 int reiserfs_removexattr(struct dentry *dentry, const char *name)
 {
@@ -811,7 +811,7 @@ int reiserfs_removexattr(struct dentry *dentry, const char *name)
 
        handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name);
 
-       if (!handler || get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
+       if (!handler || get_inode_sd_version(d_inode(dentry)) == STAT_DATA_V1)
                return -EOPNOTSUPP;
 
        return handler->set(dentry, name, NULL, 0, XATTR_REPLACE, handler->flags);
@@ -875,14 +875,14 @@ ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size)
                .size = buffer ? size : 0,
        };
 
-       if (!dentry->d_inode)
+       if (d_really_is_negative(dentry))
                return -EINVAL;
 
        if (!dentry->d_sb->s_xattr ||
-           get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
+           get_inode_sd_version(d_inode(dentry)) == STAT_DATA_V1)
                return -EOPNOTSUPP;
 
-       dir = open_xa_dir(dentry->d_inode, XATTR_REPLACE);
+       dir = open_xa_dir(d_inode(dentry), XATTR_REPLACE);
        if (IS_ERR(dir)) {
                err = PTR_ERR(dir);
                if (err == -ENODATA)
@@ -890,9 +890,9 @@ ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size)
                goto out;
        }
 
-       mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR);
-       err = reiserfs_readdir_inode(dir->d_inode, &buf.ctx);
-       mutex_unlock(&dir->d_inode->i_mutex);
+       mutex_lock_nested(&d_inode(dir)->i_mutex, I_MUTEX_XATTR);
+       err = reiserfs_readdir_inode(d_inode(dir), &buf.ctx);
+       mutex_unlock(&d_inode(dir)->i_mutex);
 
        if (!err)
                err = buf.pos;
@@ -905,12 +905,12 @@ out:
 static int create_privroot(struct dentry *dentry)
 {
        int err;
-       struct inode *inode = dentry->d_parent->d_inode;
+       struct inode *inode = d_inode(dentry->d_parent);
 
        WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex));
 
        err = xattr_mkdir(inode, dentry, 0700);
-       if (err || !dentry->d_inode) {
+       if (err || d_really_is_negative(dentry)) {
                reiserfs_warning(dentry->d_sb, "jdm-20006",
                                 "xattrs/ACLs enabled and couldn't "
                                 "find/create .reiserfs_priv. "
@@ -918,7 +918,7 @@ static int create_privroot(struct dentry *dentry)
                return -EOPNOTSUPP;
        }
 
-       dentry->d_inode->i_flags |= S_PRIVATE;
+       d_inode(dentry)->i_flags |= S_PRIVATE;
        reiserfs_info(dentry->d_sb, "Created %s - reserved for xattr "
                      "storage.\n", PRIVROOT_NAME);
 
@@ -997,17 +997,17 @@ int reiserfs_lookup_privroot(struct super_block *s)
        int err = 0;
 
        /* If we don't have the privroot located yet - go find it */
-       mutex_lock(&s->s_root->d_inode->i_mutex);
+       mutex_lock(&d_inode(s->s_root)->i_mutex);
        dentry = lookup_one_len(PRIVROOT_NAME, s->s_root,
                                strlen(PRIVROOT_NAME));
        if (!IS_ERR(dentry)) {
                REISERFS_SB(s)->priv_root = dentry;
                d_set_d_op(dentry, &xattr_lookup_poison_ops);
-               if (dentry->d_inode)
-                       dentry->d_inode->i_flags |= S_PRIVATE;
+               if (d_really_is_positive(dentry))
+                       d_inode(dentry)->i_flags |= S_PRIVATE;
        } else
                err = PTR_ERR(dentry);
-       mutex_unlock(&s->s_root->d_inode->i_mutex);
+       mutex_unlock(&d_inode(s->s_root)->i_mutex);
 
        return err;
 }
@@ -1026,15 +1026,15 @@ int reiserfs_xattr_init(struct super_block *s, int mount_flags)
        if (err)
                goto error;
 
-       if (!privroot->d_inode && !(mount_flags & MS_RDONLY)) {
-               mutex_lock(&s->s_root->d_inode->i_mutex);
+       if (d_really_is_negative(privroot) && !(mount_flags & MS_RDONLY)) {
+               mutex_lock(&d_inode(s->s_root)->i_mutex);
                err = create_privroot(REISERFS_SB(s)->priv_root);
-               mutex_unlock(&s->s_root->d_inode->i_mutex);
+               mutex_unlock(&d_inode(s->s_root)->i_mutex);
        }
 
-       if (privroot->d_inode) {
+       if (d_really_is_positive(privroot)) {
                s->s_xattr = reiserfs_xattr_handlers;
-               mutex_lock(&privroot->d_inode->i_mutex);
+               mutex_lock(&d_inode(privroot)->i_mutex);
                if (!REISERFS_SB(s)->xattr_root) {
                        struct dentry *dentry;
 
@@ -1045,7 +1045,7 @@ int reiserfs_xattr_init(struct super_block *s, int mount_flags)
                        else
                                err = PTR_ERR(dentry);
                }
-               mutex_unlock(&privroot->d_inode->i_mutex);
+               mutex_unlock(&d_inode(privroot)->i_mutex);
        }
 
 error:
index f620e9678dd541a3786d031f9774583693f15341..15dde6262c00e3d93b765f79198d93bfe79c3646 100644 (file)
@@ -78,7 +78,7 @@ static inline size_t reiserfs_xattr_jcreate_nblocks(struct inode *inode)
 
        if ((REISERFS_I(inode)->i_flags & i_has_xattr_dir) == 0) {
                nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);
-               if (!REISERFS_SB(inode->i_sb)->xattr_root->d_inode)
+               if (d_really_is_negative(REISERFS_SB(inode->i_sb)->xattr_root))
                        nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);
        }
 
index e7f8939a4cb5786cc1c8df46996c8926afcc066a..9a3b0616f2838848c88dbf90497ebb9af0a68e2a 100644 (file)
@@ -15,10 +15,10 @@ security_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
        if (strlen(name) < sizeof(XATTR_SECURITY_PREFIX))
                return -EINVAL;
 
-       if (IS_PRIVATE(dentry->d_inode))
+       if (IS_PRIVATE(d_inode(dentry)))
                return -EPERM;
 
-       return reiserfs_xattr_get(dentry->d_inode, name, buffer, size);
+       return reiserfs_xattr_get(d_inode(dentry), name, buffer, size);
 }
 
 static int
@@ -28,10 +28,10 @@ security_set(struct dentry *dentry, const char *name, const void *buffer,
        if (strlen(name) < sizeof(XATTR_SECURITY_PREFIX))
                return -EINVAL;
 
-       if (IS_PRIVATE(dentry->d_inode))
+       if (IS_PRIVATE(d_inode(dentry)))
                return -EPERM;
 
-       return reiserfs_xattr_set(dentry->d_inode, name, buffer, size, flags);
+       return reiserfs_xattr_set(d_inode(dentry), name, buffer, size, flags);
 }
 
 static size_t security_list(struct dentry *dentry, char *list, size_t list_len,
@@ -39,7 +39,7 @@ static size_t security_list(struct dentry *dentry, char *list, size_t list_len,
 {
        const size_t len = namelen + 1;
 
-       if (IS_PRIVATE(dentry->d_inode))
+       if (IS_PRIVATE(d_inode(dentry)))
                return 0;
 
        if (list && len <= list_len) {
index 5eeb0c48ba46deb225ec2cc94518746aebceabd3..e4f1343714e0ea8a89598bb776dc8a3f6b42c67d 100644 (file)
@@ -14,10 +14,10 @@ trusted_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
        if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX))
                return -EINVAL;
 
-       if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(dentry->d_inode))
+       if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(d_inode(dentry)))
                return -EPERM;
 
-       return reiserfs_xattr_get(dentry->d_inode, name, buffer, size);
+       return reiserfs_xattr_get(d_inode(dentry), name, buffer, size);
 }
 
 static int
@@ -27,10 +27,10 @@ trusted_set(struct dentry *dentry, const char *name, const void *buffer,
        if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX))
                return -EINVAL;
 
-       if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(dentry->d_inode))
+       if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(d_inode(dentry)))
                return -EPERM;
 
-       return reiserfs_xattr_set(dentry->d_inode, name, buffer, size, flags);
+       return reiserfs_xattr_set(d_inode(dentry), name, buffer, size, flags);
 }
 
 static size_t trusted_list(struct dentry *dentry, char *list, size_t list_size,
@@ -38,7 +38,7 @@ static size_t trusted_list(struct dentry *dentry, char *list, size_t list_size,
 {
        const size_t len = name_len + 1;
 
-       if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(dentry->d_inode))
+       if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(d_inode(dentry)))
                return 0;
 
        if (list && len <= list_size) {
index e50eab0464711f6ebe363ca9f2bd7ff7767aab12..d0b08d3e5689d39aeffbd1d86e13711b50e56f22 100644 (file)
@@ -15,7 +15,7 @@ user_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
                return -EINVAL;
        if (!reiserfs_xattrs_user(dentry->d_sb))
                return -EOPNOTSUPP;
-       return reiserfs_xattr_get(dentry->d_inode, name, buffer, size);
+       return reiserfs_xattr_get(d_inode(dentry), name, buffer, size);
 }
 
 static int
@@ -27,7 +27,7 @@ user_set(struct dentry *dentry, const char *name, const void *buffer,
 
        if (!reiserfs_xattrs_user(dentry->d_sb))
                return -EOPNOTSUPP;
-       return reiserfs_xattr_set(dentry->d_inode, name, buffer, size, flags);
+       return reiserfs_xattr_set(d_inode(dentry), name, buffer, size, flags);
 }
 
 static size_t user_list(struct dentry *dentry, char *list, size_t list_size,
index 5e1101ff276f940eeda02c596dcbdc9acff98d04..8073b6532cf0473f7cb16d75764b3aa93d985a32 100644 (file)
@@ -110,7 +110,7 @@ static struct dentry *squashfs_fh_to_parent(struct super_block *sb,
 
 static struct dentry *squashfs_get_parent(struct dentry *child)
 {
-       struct inode *inode = child->d_inode;
+       struct inode *inode = d_inode(child);
        unsigned int parent_ino = squashfs_i(inode)->parent;
 
        return squashfs_export_iget(inode->i_sb, parent_ino);
index 92fcde7b4d6189c3d88f341d170dbd0fa3441012..e5e0ddf5b1430d335075220824897c2e38d1b289 100644 (file)
@@ -39,7 +39,7 @@ static const struct xattr_handler *squashfs_xattr_handler(int);
 ssize_t squashfs_listxattr(struct dentry *d, char *buffer,
        size_t buffer_size)
 {
-       struct inode *inode = d->d_inode;
+       struct inode *inode = d_inode(d);
        struct super_block *sb = inode->i_sb;
        struct squashfs_sb_info *msblk = sb->s_fs_info;
        u64 start = SQUASHFS_XATTR_BLK(squashfs_i(inode)->xattr)
@@ -229,7 +229,7 @@ static int squashfs_user_get(struct dentry *d, const char *name, void *buffer,
        if (name[0] == '\0')
                return  -EINVAL;
 
-       return squashfs_xattr_get(d->d_inode, SQUASHFS_XATTR_USER, name,
+       return squashfs_xattr_get(d_inode(d), SQUASHFS_XATTR_USER, name,
                buffer, size);
 }
 
@@ -259,7 +259,7 @@ static int squashfs_trusted_get(struct dentry *d, const char *name,
        if (name[0] == '\0')
                return  -EINVAL;
 
-       return squashfs_xattr_get(d->d_inode, SQUASHFS_XATTR_TRUSTED, name,
+       return squashfs_xattr_get(d_inode(d), SQUASHFS_XATTR_TRUSTED, name,
                buffer, size);
 }
 
@@ -286,7 +286,7 @@ static int squashfs_security_get(struct dentry *d, const char *name,
        if (name[0] == '\0')
                return  -EINVAL;
 
-       return squashfs_xattr_get(d->d_inode, SQUASHFS_XATTR_SECURITY, name,
+       return squashfs_xattr_get(d_inode(d), SQUASHFS_XATTR_SECURITY, name,
                buffer, size);
 }
 
index 19636af5e75cc16614f790519c6111599d906830..cccc1aab9a8b75231f056a18b0b9fc3ecaaf1561 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -51,7 +51,7 @@ EXPORT_SYMBOL(generic_fillattr);
  */
 int vfs_getattr_nosec(struct path *path, struct kstat *stat)
 {
-       struct inode *inode = path->dentry->d_inode;
+       struct inode *inode = d_backing_inode(path->dentry);
 
        if (inode->i_op->getattr)
                return inode->i_op->getattr(path->mnt, path->dentry, stat);
@@ -326,7 +326,7 @@ SYSCALL_DEFINE4(readlinkat, int, dfd, const char __user *, pathname,
 retry:
        error = user_path_at_empty(dfd, pathname, lookup_flags, &path, &empty);
        if (!error) {
-               struct inode *inode = path.dentry->d_inode;
+               struct inode *inode = d_backing_inode(path.dentry);
 
                error = empty ? -ENOENT : -EINVAL;
                if (inode->i_op->readlink) {
index d42291d08215abd016d4e3b5aac03fa753ce70b6..8f3555f00c54276aa1f0e1d443b7dd375850bf23 100644 (file)
@@ -132,7 +132,7 @@ struct sysv_dir_entry *sysv_find_entry(struct dentry *dentry, struct page **res_
 {
        const char * name = dentry->d_name.name;
        int namelen = dentry->d_name.len;
-       struct inode * dir = dentry->d_parent->d_inode;
+       struct inode * dir = d_inode(dentry->d_parent);
        unsigned long start, n;
        unsigned long npages = dir_pages(dir);
        struct page *page = NULL;
@@ -176,7 +176,7 @@ found:
 
 int sysv_add_link(struct dentry *dentry, struct inode *inode)
 {
-       struct inode *dir = dentry->d_parent->d_inode;
+       struct inode *dir = d_inode(dentry->d_parent);
        const char * name = dentry->d_name.name;
        int namelen = dentry->d_name.len;
        struct page *page = NULL;
index a48e30410ad1979eaf1068cd59ddfa2dcc89c69a..82ddc09061e2891cec1a877d43dc2c248719114e 100644 (file)
@@ -30,7 +30,7 @@ const struct file_operations sysv_file_operations = {
 
 static int sysv_setattr(struct dentry *dentry, struct iattr *attr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int error;
 
        error = inode_change_ok(inode, attr);
index 66bc316927e8a01f60a387aa19bac4ab81abcd87..2fde40acf024173b1f4fc68131ca97cb921588b0 100644 (file)
@@ -443,7 +443,7 @@ static unsigned sysv_nblocks(struct super_block *s, loff_t size)
 int sysv_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 {
        struct super_block *s = dentry->d_sb;
-       generic_fillattr(dentry->d_inode, stat);
+       generic_fillattr(d_inode(dentry), stat);
        stat->blocks = (s->s_blocksize / 512) * sysv_nblocks(s, stat->size);
        stat->blksize = s->s_blocksize;
        return 0;
index 731b2bbcaab37f7e8d4da84dcc9e9600d3b4e969..11e83ed0b4bf495c39a2d6f0128f8fce3793256f 100644 (file)
@@ -118,7 +118,7 @@ out_fail:
 static int sysv_link(struct dentry * old_dentry, struct inode * dir, 
        struct dentry * dentry)
 {
-       struct inode *inode = old_dentry->d_inode;
+       struct inode *inode = d_inode(old_dentry);
 
        inode->i_ctime = CURRENT_TIME_SEC;
        inode_inc_link_count(inode);
@@ -166,7 +166,7 @@ out_dir:
 
 static int sysv_unlink(struct inode * dir, struct dentry * dentry)
 {
-       struct inode * inode = dentry->d_inode;
+       struct inode * inode = d_inode(dentry);
        struct page * page;
        struct sysv_dir_entry * de;
        int err = -ENOENT;
@@ -187,7 +187,7 @@ out:
 
 static int sysv_rmdir(struct inode * dir, struct dentry * dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int err = -ENOTEMPTY;
 
        if (sysv_empty_dir(inode)) {
@@ -208,8 +208,8 @@ static int sysv_rmdir(struct inode * dir, struct dentry * dentry)
 static int sysv_rename(struct inode * old_dir, struct dentry * old_dentry,
                  struct inode * new_dir, struct dentry * new_dentry)
 {
-       struct inode * old_inode = old_dentry->d_inode;
-       struct inode * new_inode = new_dentry->d_inode;
+       struct inode * old_inode = d_inode(old_dentry);
+       struct inode * new_inode = d_inode(new_dentry);
        struct page * dir_page = NULL;
        struct sysv_dir_entry * dir_de = NULL;
        struct page * old_page;
index 00d2f8a43e4eaefea0e35ba6108ef561d2852b52..d3fa0d703314bc3dafa9b5dd6c9d34a2f2c11f1d 100644 (file)
@@ -10,7 +10,7 @@
 
 static void *sysv_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-       nd_set_link(nd, (char *)SYSV_I(dentry->d_inode)->i_data);
+       nd_set_link(nd, (char *)SYSV_I(d_inode(dentry))->i_data);
        return NULL;
 }
 
index 02d1ee778df032b884ac4d63988d6f7616c59698..27060fc855d42549b2bbe7d3cbe6329858e3fb2c 100644 (file)
@@ -499,7 +499,7 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
                      struct dentry *dentry)
 {
        struct ubifs_info *c = dir->i_sb->s_fs_info;
-       struct inode *inode = old_dentry->d_inode;
+       struct inode *inode = d_inode(old_dentry);
        struct ubifs_inode *ui = ubifs_inode(inode);
        struct ubifs_inode *dir_ui = ubifs_inode(dir);
        int err, sz_change = CALC_DENT_SIZE(dentry->d_name.len);
@@ -554,7 +554,7 @@ out_cancel:
 static int ubifs_unlink(struct inode *dir, struct dentry *dentry)
 {
        struct ubifs_info *c = dir->i_sb->s_fs_info;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct ubifs_inode *dir_ui = ubifs_inode(dir);
        int sz_change = CALC_DENT_SIZE(dentry->d_name.len);
        int err, budgeted = 1;
@@ -646,7 +646,7 @@ static int check_dir_empty(struct ubifs_info *c, struct inode *dir)
 static int ubifs_rmdir(struct inode *dir, struct dentry *dentry)
 {
        struct ubifs_info *c = dir->i_sb->s_fs_info;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int sz_change = CALC_DENT_SIZE(dentry->d_name.len);
        int err, budgeted = 1;
        struct ubifs_inode *dir_ui = ubifs_inode(dir);
@@ -662,7 +662,7 @@ static int ubifs_rmdir(struct inode *dir, struct dentry *dentry)
                inode->i_ino, dir->i_ino);
        ubifs_assert(mutex_is_locked(&dir->i_mutex));
        ubifs_assert(mutex_is_locked(&inode->i_mutex));
-       err = check_dir_empty(c, dentry->d_inode);
+       err = check_dir_empty(c, d_inode(dentry));
        if (err)
                return err;
 
@@ -970,8 +970,8 @@ static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry,
                        struct inode *new_dir, struct dentry *new_dentry)
 {
        struct ubifs_info *c = old_dir->i_sb->s_fs_info;
-       struct inode *old_inode = old_dentry->d_inode;
-       struct inode *new_inode = new_dentry->d_inode;
+       struct inode *old_inode = d_inode(old_dentry);
+       struct inode *new_inode = d_inode(new_dentry);
        struct ubifs_inode *old_inode_ui = ubifs_inode(old_inode);
        int err, release, sync = 0, move = (new_dir != old_dir);
        int is_dir = S_ISDIR(old_inode->i_mode);
@@ -1136,7 +1136,7 @@ int ubifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
                  struct kstat *stat)
 {
        loff_t size;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct ubifs_inode *ui = ubifs_inode(inode);
 
        mutex_lock(&ui->ui_mutex);
index 3ba3fef64e9eaf67d9ca4a03457a68d5f0c95011..35efc103c39c102215cebb0792b6b4f24d49b90d 100644 (file)
@@ -1257,7 +1257,7 @@ static int do_setattr(struct ubifs_info *c, struct inode *inode,
 int ubifs_setattr(struct dentry *dentry, struct iattr *attr)
 {
        int err;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct ubifs_info *c = inode->i_sb->s_fs_info;
 
        dbg_gen("ino %lu, mode %#x, ia_valid %#x",
@@ -1302,7 +1302,7 @@ static void ubifs_invalidatepage(struct page *page, unsigned int offset,
 
 static void *ubifs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-       struct ubifs_inode *ui = ubifs_inode(dentry->d_inode);
+       struct ubifs_inode *ui = ubifs_inode(d_inode(dentry));
 
        nd_set_link(nd, ui->data);
        return NULL;
index 90ae1a8439d94e7b338c154475a2fe3f1d66197a..0b9da5b6e0f966192408b4ddd1ec18bf7ce9555a 100644 (file)
@@ -930,8 +930,8 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
        union ubifs_key key;
        struct ubifs_dent_node *dent, *dent2;
        int err, dlen1, dlen2, ilen, lnum, offs, len;
-       const struct inode *old_inode = old_dentry->d_inode;
-       const struct inode *new_inode = new_dentry->d_inode;
+       const struct inode *old_inode = d_inode(old_dentry);
+       const struct inode *new_inode = d_inode(new_dentry);
        int aligned_dlen1, aligned_dlen2, plen = UBIFS_INO_NODE_SZ;
        int last_reference = !!(new_inode && new_inode->i_nlink == 0);
        int move = (old_dir != new_dir);
index 3659b1934500aadc0a19291d07d3fd50317428a5..96f3448b6eb40c0682ec915a71d5030d5bdf4283 100644 (file)
@@ -364,15 +364,15 @@ int ubifs_setxattr(struct dentry *dentry, const char *name,
                   const void *value, size_t size, int flags)
 {
        dbg_gen("xattr '%s', host ino %lu ('%pd'), size %zd",
-               name, dentry->d_inode->i_ino, dentry, size);
+               name, d_inode(dentry)->i_ino, dentry, size);
 
-       return setxattr(dentry->d_inode, name, value, size, flags);
+       return setxattr(d_inode(dentry), name, value, size, flags);
 }
 
 ssize_t ubifs_getxattr(struct dentry *dentry, const char *name, void *buf,
                       size_t size)
 {
-       struct inode *inode, *host = dentry->d_inode;
+       struct inode *inode, *host = d_inode(dentry);
        struct ubifs_info *c = host->i_sb->s_fs_info;
        struct qstr nm = QSTR_INIT(name, strlen(name));
        struct ubifs_inode *ui;
@@ -432,7 +432,7 @@ out_unlock:
 ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size)
 {
        union ubifs_key key;
-       struct inode *host = dentry->d_inode;
+       struct inode *host = d_inode(dentry);
        struct ubifs_info *c = host->i_sb->s_fs_info;
        struct ubifs_inode *host_ui = ubifs_inode(host);
        struct ubifs_dent_node *xent, *pxent = NULL;
@@ -535,7 +535,7 @@ out_cancel:
 
 int ubifs_removexattr(struct dentry *dentry, const char *name)
 {
-       struct inode *inode, *host = dentry->d_inode;
+       struct inode *inode, *host = d_inode(dentry);
        struct ubifs_info *c = host->i_sb->s_fs_info;
        struct qstr nm = QSTR_INIT(name, strlen(name));
        struct ubifs_dent_node *xent;
index 5dadad9960b9e25cb4698a184005ad1c82073535..7a95b8fed302daa3321915f555ba70cd5fcfd9a4 100644 (file)
@@ -249,7 +249,7 @@ const struct file_operations udf_file_operations = {
 
 static int udf_setattr(struct dentry *dentry, struct iattr *attr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        int error;
 
        error = inode_change_ok(inode, attr);
index 39661977c89cdd657b19a60bf33d58bf79762c94..5c03f0dfb98bcd6f7b396431f5e9ed7f49d23c8d 100644 (file)
@@ -551,7 +551,7 @@ static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi,
 static int udf_add_nondir(struct dentry *dentry, struct inode *inode)
 {
        struct udf_inode_info *iinfo = UDF_I(inode);
-       struct inode *dir = dentry->d_parent->d_inode;
+       struct inode *dir = d_inode(dentry->d_parent);
        struct udf_fileident_bh fibh;
        struct fileIdentDesc cfi, *fi;
        int err;
@@ -767,7 +767,7 @@ static int empty_dir(struct inode *dir)
 static int udf_rmdir(struct inode *dir, struct dentry *dentry)
 {
        int retval;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct udf_fileident_bh fibh;
        struct fileIdentDesc *fi, cfi;
        struct kernel_lb_addr tloc;
@@ -809,7 +809,7 @@ out:
 static int udf_unlink(struct inode *dir, struct dentry *dentry)
 {
        int retval;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct udf_fileident_bh fibh;
        struct fileIdentDesc *fi;
        struct fileIdentDesc cfi;
@@ -999,7 +999,7 @@ out_no_entry:
 static int udf_link(struct dentry *old_dentry, struct inode *dir,
                    struct dentry *dentry)
 {
-       struct inode *inode = old_dentry->d_inode;
+       struct inode *inode = d_inode(old_dentry);
        struct udf_fileident_bh fibh;
        struct fileIdentDesc cfi, *fi;
        int err;
@@ -1038,8 +1038,8 @@ static int udf_link(struct dentry *old_dentry, struct inode *dir,
 static int udf_rename(struct inode *old_dir, struct dentry *old_dentry,
                      struct inode *new_dir, struct dentry *new_dentry)
 {
-       struct inode *old_inode = old_dentry->d_inode;
-       struct inode *new_inode = new_dentry->d_inode;
+       struct inode *old_inode = d_inode(old_dentry);
+       struct inode *new_inode = d_inode(new_dentry);
        struct udf_fileident_bh ofibh, nfibh;
        struct fileIdentDesc *ofi = NULL, *nfi = NULL, *dir_fi = NULL;
        struct fileIdentDesc ocfi, ncfi;
@@ -1179,7 +1179,7 @@ static struct dentry *udf_get_parent(struct dentry *child)
        struct fileIdentDesc cfi;
        struct udf_fileident_bh fibh;
 
-       if (!udf_find_entry(child->d_inode, &dotdot, &fibh, &cfi))
+       if (!udf_find_entry(d_inode(child), &dotdot, &fibh, &cfi))
                return ERR_PTR(-EACCES);
 
        if (fibh.sbh != fibh.ebh)
@@ -1187,7 +1187,7 @@ static struct dentry *udf_get_parent(struct dentry *child)
        brelse(fibh.sbh);
 
        tloc = lelb_to_cpu(cfi.icb.extLocation);
-       inode = udf_iget(child->d_inode->i_sb, &tloc);
+       inode = udf_iget(d_inode(child)->i_sb, &tloc);
        if (IS_ERR(inode))
                return ERR_CAST(inode);
 
index 0ecc2cebed8ffec60bc9ccdb408519253d7fc3a6..1bfe8cabff0f660d107c6bc97446a0cceaf940eb 100644 (file)
@@ -311,7 +311,7 @@ found:
  */
 int ufs_add_link(struct dentry *dentry, struct inode *inode)
 {
-       struct inode *dir = dentry->d_parent->d_inode;
+       struct inode *dir = d_inode(dentry->d_parent);
        const unsigned char *name = dentry->d_name.name;
        int namelen = dentry->d_name.len;
        struct super_block *sb = dir->i_sb;
index fd65deb4b5f095e3103028b83f214ffba73707f7..e491a93a7e9af14c4227ee5072fa4a9d0bc17709 100644 (file)
@@ -165,7 +165,7 @@ out_fail:
 static int ufs_link (struct dentry * old_dentry, struct inode * dir,
        struct dentry *dentry)
 {
-       struct inode *inode = old_dentry->d_inode;
+       struct inode *inode = d_inode(old_dentry);
        int error;
 
        lock_ufs(dir->i_sb);
@@ -222,7 +222,7 @@ out_fail:
 
 static int ufs_unlink(struct inode *dir, struct dentry *dentry)
 {
-       struct inode * inode = dentry->d_inode;
+       struct inode * inode = d_inode(dentry);
        struct ufs_dir_entry *de;
        struct page *page;
        int err = -ENOENT;
@@ -244,7 +244,7 @@ out:
 
 static int ufs_rmdir (struct inode * dir, struct dentry *dentry)
 {
-       struct inode * inode = dentry->d_inode;
+       struct inode * inode = d_inode(dentry);
        int err= -ENOTEMPTY;
 
        lock_ufs(dir->i_sb);
@@ -263,8 +263,8 @@ static int ufs_rmdir (struct inode * dir, struct dentry *dentry)
 static int ufs_rename(struct inode *old_dir, struct dentry *old_dentry,
                      struct inode *new_dir, struct dentry *new_dentry)
 {
-       struct inode *old_inode = old_dentry->d_inode;
-       struct inode *new_inode = new_dentry->d_inode;
+       struct inode *old_inode = d_inode(old_dentry);
+       struct inode *new_inode = d_inode(new_dentry);
        struct page *dir_page = NULL;
        struct ufs_dir_entry * dir_de = NULL;
        struct page *old_page;
index 8092d3759a5e560001ad75bdb9a5238c053a8523..b3bc3e7ae79db3c1542f8e8cf3ac549aa0deed62 100644 (file)
@@ -144,10 +144,10 @@ static struct dentry *ufs_get_parent(struct dentry *child)
        struct qstr dot_dot = QSTR_INIT("..", 2);
        ino_t ino;
 
-       ino = ufs_inode_by_name(child->d_inode, &dot_dot);
+       ino = ufs_inode_by_name(d_inode(child), &dot_dot);
        if (!ino)
                return ERR_PTR(-ENOENT);
-       return d_obtain_alias(ufs_iget(child->d_inode->i_sb, ino));
+       return d_obtain_alias(ufs_iget(d_inode(child)->i_sb, ino));
 }
 
 static const struct export_operations ufs_export_ops = {
index d283628b4778bc4fef3a07d8bf8b267458c1e389..5b537e2fdda385a0da9aa346e93e05e83084e1dd 100644 (file)
@@ -34,7 +34,7 @@
 
 static void *ufs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-       struct ufs_inode_info *p = UFS_I(dentry->d_inode);
+       struct ufs_inode_info *p = UFS_I(d_inode(dentry));
        nd_set_link(nd, (char*)p->i_u1.i_symlink);
        return NULL;
 }
index f04f89fbd4d9914b0a1a16f2cce8c8e0799e020e..21154704c16801ea6525f4152637dc3d16b4bdd8 100644 (file)
@@ -492,7 +492,7 @@ out:
 
 int ufs_setattr(struct dentry *dentry, struct iattr *attr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        unsigned int ia_valid = attr->ia_valid;
        int error;
 
index a6fbf4472017593200ddc07785215ea02d718bf8..516162be1398404a18e32909f8ff25c065364605 100644 (file)
@@ -260,6 +260,7 @@ xfs_alloc_fix_len(
                rlen = rlen - (k - args->mod);
        else
                rlen = rlen - args->prod + (args->mod - k);
+       /* casts to (int) catch length underflows */
        if ((int)rlen < (int)args->minlen)
                return;
        ASSERT(rlen >= args->minlen && rlen <= args->maxlen);
@@ -286,7 +287,8 @@ xfs_alloc_fix_minleft(
        if (diff >= 0)
                return 1;
        args->len += diff;              /* shrink the allocated space */
-       if (args->len >= args->minlen)
+       /* casts to (int) catch length underflows */
+       if ((int)args->len >= (int)args->minlen)
                return 1;
        args->agbno = NULLAGBLOCK;
        return 0;
@@ -315,6 +317,9 @@ xfs_alloc_fixup_trees(
        xfs_agblock_t   nfbno2;         /* second new free startblock */
        xfs_extlen_t    nflen1=0;       /* first new free length */
        xfs_extlen_t    nflen2=0;       /* second new free length */
+       struct xfs_mount *mp;
+
+       mp = cnt_cur->bc_mp;
 
        /*
         * Look up the record in the by-size tree if necessary.
@@ -323,13 +328,13 @@ xfs_alloc_fixup_trees(
 #ifdef DEBUG
                if ((error = xfs_alloc_get_rec(cnt_cur, &nfbno1, &nflen1, &i)))
                        return error;
-               XFS_WANT_CORRUPTED_RETURN(
+               XFS_WANT_CORRUPTED_RETURN(mp,
                        i == 1 && nfbno1 == fbno && nflen1 == flen);
 #endif
        } else {
                if ((error = xfs_alloc_lookup_eq(cnt_cur, fbno, flen, &i)))
                        return error;
-               XFS_WANT_CORRUPTED_RETURN(i == 1);
+               XFS_WANT_CORRUPTED_RETURN(mp, i == 1);
        }
        /*
         * Look up the record in the by-block tree if necessary.
@@ -338,13 +343,13 @@ xfs_alloc_fixup_trees(
 #ifdef DEBUG
                if ((error = xfs_alloc_get_rec(bno_cur, &nfbno1, &nflen1, &i)))
                        return error;
-               XFS_WANT_CORRUPTED_RETURN(
+               XFS_WANT_CORRUPTED_RETURN(mp,
                        i == 1 && nfbno1 == fbno && nflen1 == flen);
 #endif
        } else {
                if ((error = xfs_alloc_lookup_eq(bno_cur, fbno, flen, &i)))
                        return error;
-               XFS_WANT_CORRUPTED_RETURN(i == 1);
+               XFS_WANT_CORRUPTED_RETURN(mp, i == 1);
        }
 
 #ifdef DEBUG
@@ -355,7 +360,7 @@ xfs_alloc_fixup_trees(
                bnoblock = XFS_BUF_TO_BLOCK(bno_cur->bc_bufs[0]);
                cntblock = XFS_BUF_TO_BLOCK(cnt_cur->bc_bufs[0]);
 
-               XFS_WANT_CORRUPTED_RETURN(
+               XFS_WANT_CORRUPTED_RETURN(mp,
                        bnoblock->bb_numrecs == cntblock->bb_numrecs);
        }
 #endif
@@ -386,25 +391,25 @@ xfs_alloc_fixup_trees(
         */
        if ((error = xfs_btree_delete(cnt_cur, &i)))
                return error;
-       XFS_WANT_CORRUPTED_RETURN(i == 1);
+       XFS_WANT_CORRUPTED_RETURN(mp, i == 1);
        /*
         * Add new by-size btree entry(s).
         */
        if (nfbno1 != NULLAGBLOCK) {
                if ((error = xfs_alloc_lookup_eq(cnt_cur, nfbno1, nflen1, &i)))
                        return error;
-               XFS_WANT_CORRUPTED_RETURN(i == 0);
+               XFS_WANT_CORRUPTED_RETURN(mp, i == 0);
                if ((error = xfs_btree_insert(cnt_cur, &i)))
                        return error;
-               XFS_WANT_CORRUPTED_RETURN(i == 1);
+               XFS_WANT_CORRUPTED_RETURN(mp, i == 1);
        }
        if (nfbno2 != NULLAGBLOCK) {
                if ((error = xfs_alloc_lookup_eq(cnt_cur, nfbno2, nflen2, &i)))
                        return error;
-               XFS_WANT_CORRUPTED_RETURN(i == 0);
+               XFS_WANT_CORRUPTED_RETURN(mp, i == 0);
                if ((error = xfs_btree_insert(cnt_cur, &i)))
                        return error;
-               XFS_WANT_CORRUPTED_RETURN(i == 1);
+               XFS_WANT_CORRUPTED_RETURN(mp, i == 1);
        }
        /*
         * Fix up the by-block btree entry(s).
@@ -415,7 +420,7 @@ xfs_alloc_fixup_trees(
                 */
                if ((error = xfs_btree_delete(bno_cur, &i)))
                        return error;
-               XFS_WANT_CORRUPTED_RETURN(i == 1);
+               XFS_WANT_CORRUPTED_RETURN(mp, i == 1);
        } else {
                /*
                 * Update the by-block entry to start later|be shorter.
@@ -429,10 +434,10 @@ xfs_alloc_fixup_trees(
                 */
                if ((error = xfs_alloc_lookup_eq(bno_cur, nfbno2, nflen2, &i)))
                        return error;
-               XFS_WANT_CORRUPTED_RETURN(i == 0);
+               XFS_WANT_CORRUPTED_RETURN(mp, i == 0);
                if ((error = xfs_btree_insert(bno_cur, &i)))
                        return error;
-               XFS_WANT_CORRUPTED_RETURN(i == 1);
+               XFS_WANT_CORRUPTED_RETURN(mp, i == 1);
        }
        return 0;
 }
@@ -682,7 +687,7 @@ xfs_alloc_ag_vextent_exact(
        error = xfs_alloc_get_rec(bno_cur, &fbno, &flen, &i);
        if (error)
                goto error0;
-       XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+       XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0);
        ASSERT(fbno <= args->agbno);
 
        /*
@@ -783,7 +788,7 @@ xfs_alloc_find_best_extent(
                error = xfs_alloc_get_rec(*scur, sbno, slen, &i);
                if (error)
                        goto error0;
-               XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+               XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0);
                xfs_alloc_compute_aligned(args, *sbno, *slen, sbnoa, slena);
 
                /*
@@ -946,7 +951,7 @@ restart:
                                if ((error = xfs_alloc_get_rec(cnt_cur, &ltbno,
                                                &ltlen, &i)))
                                        goto error0;
-                               XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+                               XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0);
                                if (ltlen >= args->minlen)
                                        break;
                                if ((error = xfs_btree_increment(cnt_cur, 0, &i)))
@@ -966,7 +971,7 @@ restart:
                         */
                        if ((error = xfs_alloc_get_rec(cnt_cur, &ltbno, &ltlen, &i)))
                                goto error0;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+                       XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0);
                        xfs_alloc_compute_aligned(args, ltbno, ltlen,
                                                  &ltbnoa, &ltlena);
                        if (ltlena < args->minlen)
@@ -999,7 +1004,7 @@ restart:
                cnt_cur->bc_ptrs[0] = besti;
                if ((error = xfs_alloc_get_rec(cnt_cur, &ltbno, &ltlen, &i)))
                        goto error0;
-               XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+               XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0);
                ASSERT(ltbno + ltlen <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length));
                args->len = blen;
                if (!xfs_alloc_fix_minleft(args)) {
@@ -1088,7 +1093,7 @@ restart:
                if (bno_cur_lt) {
                        if ((error = xfs_alloc_get_rec(bno_cur_lt, &ltbno, &ltlen, &i)))
                                goto error0;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+                       XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0);
                        xfs_alloc_compute_aligned(args, ltbno, ltlen,
                                                  &ltbnoa, &ltlena);
                        if (ltlena >= args->minlen)
@@ -1104,7 +1109,7 @@ restart:
                if (bno_cur_gt) {
                        if ((error = xfs_alloc_get_rec(bno_cur_gt, &gtbno, &gtlen, &i)))
                                goto error0;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+                       XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0);
                        xfs_alloc_compute_aligned(args, gtbno, gtlen,
                                                  &gtbnoa, &gtlena);
                        if (gtlena >= args->minlen)
@@ -1303,7 +1308,7 @@ restart:
                        error = xfs_alloc_get_rec(cnt_cur, &fbno, &flen, &i);
                        if (error)
                                goto error0;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+                       XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0);
 
                        xfs_alloc_compute_aligned(args, fbno, flen,
                                                  &rbno, &rlen);
@@ -1342,7 +1347,7 @@ restart:
         * This can't happen in the second case above.
         */
        rlen = XFS_EXTLEN_MIN(args->maxlen, rlen);
-       XFS_WANT_CORRUPTED_GOTO(rlen == 0 ||
+       XFS_WANT_CORRUPTED_GOTO(args->mp, rlen == 0 ||
                        (rlen <= flen && rbno + rlen <= fbno + flen), error0);
        if (rlen < args->maxlen) {
                xfs_agblock_t   bestfbno;
@@ -1362,13 +1367,13 @@ restart:
                        if ((error = xfs_alloc_get_rec(cnt_cur, &fbno, &flen,
                                        &i)))
                                goto error0;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+                       XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0);
                        if (flen < bestrlen)
                                break;
                        xfs_alloc_compute_aligned(args, fbno, flen,
                                                  &rbno, &rlen);
                        rlen = XFS_EXTLEN_MIN(args->maxlen, rlen);
-                       XFS_WANT_CORRUPTED_GOTO(rlen == 0 ||
+                       XFS_WANT_CORRUPTED_GOTO(args->mp, rlen == 0 ||
                                (rlen <= flen && rbno + rlen <= fbno + flen),
                                error0);
                        if (rlen > bestrlen) {
@@ -1383,7 +1388,7 @@ restart:
                if ((error = xfs_alloc_lookup_eq(cnt_cur, bestfbno, bestflen,
                                &i)))
                        goto error0;
-               XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+               XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0);
                rlen = bestrlen;
                rbno = bestrbno;
                flen = bestflen;
@@ -1408,7 +1413,7 @@ restart:
        if (!xfs_alloc_fix_minleft(args))
                goto out_nominleft;
        rlen = args->len;
-       XFS_WANT_CORRUPTED_GOTO(rlen <= flen, error0);
+       XFS_WANT_CORRUPTED_GOTO(args->mp, rlen <= flen, error0);
        /*
         * Allocate and initialize a cursor for the by-block tree.
         */
@@ -1422,7 +1427,7 @@ restart:
        cnt_cur = bno_cur = NULL;
        args->len = rlen;
        args->agbno = rbno;
-       XFS_WANT_CORRUPTED_GOTO(
+       XFS_WANT_CORRUPTED_GOTO(args->mp,
                args->agbno + args->len <=
                        be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length),
                error0);
@@ -1467,7 +1472,7 @@ xfs_alloc_ag_vextent_small(
        if (i) {
                if ((error = xfs_alloc_get_rec(ccur, &fbno, &flen, &i)))
                        goto error0;
-               XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+               XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0);
        }
        /*
         * Nothing in the btree, try the freelist.  Make sure
@@ -1493,7 +1498,7 @@ xfs_alloc_ag_vextent_small(
                        }
                        args->len = 1;
                        args->agbno = fbno;
-                       XFS_WANT_CORRUPTED_GOTO(
+                       XFS_WANT_CORRUPTED_GOTO(args->mp,
                                args->agbno + args->len <=
                                be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length),
                                error0);
@@ -1579,7 +1584,7 @@ xfs_free_ag_extent(
                 */
                if ((error = xfs_alloc_get_rec(bno_cur, &ltbno, &ltlen, &i)))
                        goto error0;
-               XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+               XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0);
                /*
                 * It's not contiguous, though.
                 */
@@ -1591,7 +1596,8 @@ xfs_free_ag_extent(
                         * space was invalid, it's (partly) already free.
                         * Very bad.
                         */
-                       XFS_WANT_CORRUPTED_GOTO(ltbno + ltlen <= bno, error0);
+                       XFS_WANT_CORRUPTED_GOTO(mp,
+                                               ltbno + ltlen <= bno, error0);
                }
        }
        /*
@@ -1606,7 +1612,7 @@ xfs_free_ag_extent(
                 */
                if ((error = xfs_alloc_get_rec(bno_cur, &gtbno, &gtlen, &i)))
                        goto error0;
-               XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+               XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0);
                /*
                 * It's not contiguous, though.
                 */
@@ -1618,7 +1624,7 @@ xfs_free_ag_extent(
                         * space was invalid, it's (partly) already free.
                         * Very bad.
                         */
-                       XFS_WANT_CORRUPTED_GOTO(gtbno >= bno + len, error0);
+                       XFS_WANT_CORRUPTED_GOTO(mp, gtbno >= bno + len, error0);
                }
        }
        /*
@@ -1635,31 +1641,31 @@ xfs_free_ag_extent(
                 */
                if ((error = xfs_alloc_lookup_eq(cnt_cur, ltbno, ltlen, &i)))
                        goto error0;
-               XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+               XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0);
                if ((error = xfs_btree_delete(cnt_cur, &i)))
                        goto error0;
-               XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+               XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0);
                /*
                 * Delete the old by-size entry on the right.
                 */
                if ((error = xfs_alloc_lookup_eq(cnt_cur, gtbno, gtlen, &i)))
                        goto error0;
-               XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+               XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0);
                if ((error = xfs_btree_delete(cnt_cur, &i)))
                        goto error0;
-               XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+               XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0);
                /*
                 * Delete the old by-block entry for the right block.
                 */
                if ((error = xfs_btree_delete(bno_cur, &i)))
                        goto error0;
-               XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+               XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0);
                /*
                 * Move the by-block cursor back to the left neighbor.
                 */
                if ((error = xfs_btree_decrement(bno_cur, 0, &i)))
                        goto error0;
-               XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+               XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0);
 #ifdef DEBUG
                /*
                 * Check that this is the right record: delete didn't
@@ -1672,7 +1678,7 @@ xfs_free_ag_extent(
                        if ((error = xfs_alloc_get_rec(bno_cur, &xxbno, &xxlen,
                                        &i)))
                                goto error0;
-                       XFS_WANT_CORRUPTED_GOTO(
+                       XFS_WANT_CORRUPTED_GOTO(mp,
                                i == 1 && xxbno == ltbno && xxlen == ltlen,
                                error0);
                }
@@ -1695,17 +1701,17 @@ xfs_free_ag_extent(
                 */
                if ((error = xfs_alloc_lookup_eq(cnt_cur, ltbno, ltlen, &i)))
                        goto error0;
-               XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+               XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0);
                if ((error = xfs_btree_delete(cnt_cur, &i)))
                        goto error0;
-               XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+               XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0);
                /*
                 * Back up the by-block cursor to the left neighbor, and
                 * update its length.
                 */
                if ((error = xfs_btree_decrement(bno_cur, 0, &i)))
                        goto error0;
-               XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+               XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0);
                nbno = ltbno;
                nlen = len + ltlen;
                if ((error = xfs_alloc_update(bno_cur, nbno, nlen)))
@@ -1721,10 +1727,10 @@ xfs_free_ag_extent(
                 */
                if ((error = xfs_alloc_lookup_eq(cnt_cur, gtbno, gtlen, &i)))
                        goto error0;
-               XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+               XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0);
                if ((error = xfs_btree_delete(cnt_cur, &i)))
                        goto error0;
-               XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+               XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0);
                /*
                 * Update the starting block and length of the right
                 * neighbor in the by-block tree.
@@ -1743,7 +1749,7 @@ xfs_free_ag_extent(
                nlen = len;
                if ((error = xfs_btree_insert(bno_cur, &i)))
                        goto error0;
-               XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+               XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0);
        }
        xfs_btree_del_cursor(bno_cur, XFS_BTREE_NOERROR);
        bno_cur = NULL;
@@ -1752,10 +1758,10 @@ xfs_free_ag_extent(
         */
        if ((error = xfs_alloc_lookup_eq(cnt_cur, nbno, nlen, &i)))
                goto error0;
-       XFS_WANT_CORRUPTED_GOTO(i == 0, error0);
+       XFS_WANT_CORRUPTED_GOTO(mp, i == 0, error0);
        if ((error = xfs_btree_insert(cnt_cur, &i)))
                goto error0;
-       XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0);
        xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
        cnt_cur = NULL;
 
index 15105dbc9e28dbd92a80b851e90a79a5f2bb453c..04e79d57bca600b4a21cd0a2a936639d9556e6c8 100644 (file)
@@ -86,8 +86,83 @@ STATIC void xfs_attr3_leaf_moveents(struct xfs_da_args *args,
                        int move_count);
 STATIC int xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index);
 
+/*
+ * attr3 block 'firstused' conversion helpers.
+ *
+ * firstused refers to the offset of the first used byte of the nameval region
+ * of an attr leaf block. The region starts at the tail of the block and expands
+ * backwards towards the middle. As such, firstused is initialized to the block
+ * size for an empty leaf block and is reduced from there.
+ *
+ * The attr3 block size is pegged to the fsb size and the maximum fsb is 64k.
+ * The in-core firstused field is 32-bit and thus supports the maximum fsb size.
+ * The on-disk field is only 16-bit, however, and overflows at 64k. Since this
+ * only occurs at exactly 64k, we use zero as a magic on-disk value to represent
+ * the attr block size. The following helpers manage the conversion between the
+ * in-core and on-disk formats.
+ */
+
+static void
+xfs_attr3_leaf_firstused_from_disk(
+       struct xfs_da_geometry          *geo,
+       struct xfs_attr3_icleaf_hdr     *to,
+       struct xfs_attr_leafblock       *from)
+{
+       struct xfs_attr3_leaf_hdr       *hdr3;
+
+       if (from->hdr.info.magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC)) {
+               hdr3 = (struct xfs_attr3_leaf_hdr *) from;
+               to->firstused = be16_to_cpu(hdr3->firstused);
+       } else {
+               to->firstused = be16_to_cpu(from->hdr.firstused);
+       }
+
+       /*
+        * Convert from the magic fsb size value to actual blocksize. This
+        * should only occur for empty blocks when the block size overflows
+        * 16-bits.
+        */
+       if (to->firstused == XFS_ATTR3_LEAF_NULLOFF) {
+               ASSERT(!to->count && !to->usedbytes);
+               ASSERT(geo->blksize > USHRT_MAX);
+               to->firstused = geo->blksize;
+       }
+}
+
+static void
+xfs_attr3_leaf_firstused_to_disk(
+       struct xfs_da_geometry          *geo,
+       struct xfs_attr_leafblock       *to,
+       struct xfs_attr3_icleaf_hdr     *from)
+{
+       struct xfs_attr3_leaf_hdr       *hdr3;
+       uint32_t                        firstused;
+
+       /* magic value should only be seen on disk */
+       ASSERT(from->firstused != XFS_ATTR3_LEAF_NULLOFF);
+
+       /*
+        * Scale down the 32-bit in-core firstused value to the 16-bit on-disk
+        * value. This only overflows at the max supported value of 64k. Use the
+        * magic on-disk value to represent block size in this case.
+        */
+       firstused = from->firstused;
+       if (firstused > USHRT_MAX) {
+               ASSERT(from->firstused == geo->blksize);
+               firstused = XFS_ATTR3_LEAF_NULLOFF;
+       }
+
+       if (from->magic == XFS_ATTR3_LEAF_MAGIC) {
+               hdr3 = (struct xfs_attr3_leaf_hdr *) to;
+               hdr3->firstused = cpu_to_be16(firstused);
+       } else {
+               to->hdr.firstused = cpu_to_be16(firstused);
+       }
+}
+
 void
 xfs_attr3_leaf_hdr_from_disk(
+       struct xfs_da_geometry          *geo,
        struct xfs_attr3_icleaf_hdr     *to,
        struct xfs_attr_leafblock       *from)
 {
@@ -104,7 +179,7 @@ xfs_attr3_leaf_hdr_from_disk(
                to->magic = be16_to_cpu(hdr3->info.hdr.magic);
                to->count = be16_to_cpu(hdr3->count);
                to->usedbytes = be16_to_cpu(hdr3->usedbytes);
-               to->firstused = be16_to_cpu(hdr3->firstused);
+               xfs_attr3_leaf_firstused_from_disk(geo, to, from);
                to->holes = hdr3->holes;
 
                for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) {
@@ -118,7 +193,7 @@ xfs_attr3_leaf_hdr_from_disk(
        to->magic = be16_to_cpu(from->hdr.info.magic);
        to->count = be16_to_cpu(from->hdr.count);
        to->usedbytes = be16_to_cpu(from->hdr.usedbytes);
-       to->firstused = be16_to_cpu(from->hdr.firstused);
+       xfs_attr3_leaf_firstused_from_disk(geo, to, from);
        to->holes = from->hdr.holes;
 
        for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) {
@@ -129,10 +204,11 @@ xfs_attr3_leaf_hdr_from_disk(
 
 void
 xfs_attr3_leaf_hdr_to_disk(
+       struct xfs_da_geometry          *geo,
        struct xfs_attr_leafblock       *to,
        struct xfs_attr3_icleaf_hdr     *from)
 {
-       int     i;
+       int                             i;
 
        ASSERT(from->magic == XFS_ATTR_LEAF_MAGIC ||
               from->magic == XFS_ATTR3_LEAF_MAGIC);
@@ -145,7 +221,7 @@ xfs_attr3_leaf_hdr_to_disk(
                hdr3->info.hdr.magic = cpu_to_be16(from->magic);
                hdr3->count = cpu_to_be16(from->count);
                hdr3->usedbytes = cpu_to_be16(from->usedbytes);
-               hdr3->firstused = cpu_to_be16(from->firstused);
+               xfs_attr3_leaf_firstused_to_disk(geo, to, from);
                hdr3->holes = from->holes;
                hdr3->pad1 = 0;
 
@@ -160,7 +236,7 @@ xfs_attr3_leaf_hdr_to_disk(
        to->hdr.info.magic = cpu_to_be16(from->magic);
        to->hdr.count = cpu_to_be16(from->count);
        to->hdr.usedbytes = cpu_to_be16(from->usedbytes);
-       to->hdr.firstused = cpu_to_be16(from->firstused);
+       xfs_attr3_leaf_firstused_to_disk(geo, to, from);
        to->hdr.holes = from->holes;
        to->hdr.pad1 = 0;
 
@@ -178,7 +254,7 @@ xfs_attr3_leaf_verify(
        struct xfs_attr_leafblock *leaf = bp->b_addr;
        struct xfs_attr3_icleaf_hdr ichdr;
 
-       xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf);
+       xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr, leaf);
 
        if (xfs_sb_version_hascrc(&mp->m_sb)) {
                struct xfs_da3_node_hdr *hdr3 = bp->b_addr;
@@ -757,9 +833,10 @@ xfs_attr_shortform_allfit(
        struct xfs_attr3_icleaf_hdr leafhdr;
        int                     bytes;
        int                     i;
+       struct xfs_mount        *mp = bp->b_target->bt_mount;
 
        leaf = bp->b_addr;
-       xfs_attr3_leaf_hdr_from_disk(&leafhdr, leaf);
+       xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, leaf);
        entry = xfs_attr3_leaf_entryp(leaf);
 
        bytes = sizeof(struct xfs_attr_sf_hdr);
@@ -812,7 +889,7 @@ xfs_attr3_leaf_to_shortform(
        memcpy(tmpbuffer, bp->b_addr, args->geo->blksize);
 
        leaf = (xfs_attr_leafblock_t *)tmpbuffer;
-       xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf);
+       xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf);
        entry = xfs_attr3_leaf_entryp(leaf);
 
        /* XXX (dgc): buffer is about to be marked stale - why zero it? */
@@ -923,7 +1000,7 @@ xfs_attr3_leaf_to_node(
        btree = dp->d_ops->node_tree_p(node);
 
        leaf = bp2->b_addr;
-       xfs_attr3_leaf_hdr_from_disk(&icleafhdr, leaf);
+       xfs_attr3_leaf_hdr_from_disk(args->geo, &icleafhdr, leaf);
        entries = xfs_attr3_leaf_entryp(leaf);
 
        /* both on-disk, don't endian-flip twice */
@@ -988,7 +1065,7 @@ xfs_attr3_leaf_create(
        }
        ichdr.freemap[0].size = ichdr.firstused - ichdr.freemap[0].base;
 
-       xfs_attr3_leaf_hdr_to_disk(leaf, &ichdr);
+       xfs_attr3_leaf_hdr_to_disk(args->geo, leaf, &ichdr);
        xfs_trans_log_buf(args->trans, bp, 0, args->geo->blksize - 1);
 
        *bpp = bp;
@@ -1073,7 +1150,7 @@ xfs_attr3_leaf_add(
        trace_xfs_attr_leaf_add(args);
 
        leaf = bp->b_addr;
-       xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf);
+       xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf);
        ASSERT(args->index >= 0 && args->index <= ichdr.count);
        entsize = xfs_attr_leaf_newentsize(args, NULL);
 
@@ -1126,7 +1203,7 @@ xfs_attr3_leaf_add(
        tmp = xfs_attr3_leaf_add_work(bp, &ichdr, args, 0);
 
 out_log_hdr:
-       xfs_attr3_leaf_hdr_to_disk(leaf, &ichdr);
+       xfs_attr3_leaf_hdr_to_disk(args->geo, leaf, &ichdr);
        xfs_trans_log_buf(args->trans, bp,
                XFS_DA_LOGRANGE(leaf, &leaf->hdr,
                                xfs_attr3_leaf_hdr_size(leaf)));
@@ -1294,7 +1371,7 @@ xfs_attr3_leaf_compact(
                                                ichdr_dst->freemap[0].base;
 
        /* write the header back to initialise the underlying buffer */
-       xfs_attr3_leaf_hdr_to_disk(leaf_dst, ichdr_dst);
+       xfs_attr3_leaf_hdr_to_disk(args->geo, leaf_dst, ichdr_dst);
 
        /*
         * Copy all entry's in the same (sorted) order,
@@ -1344,9 +1421,10 @@ xfs_attr_leaf_order(
 {
        struct xfs_attr3_icleaf_hdr ichdr1;
        struct xfs_attr3_icleaf_hdr ichdr2;
+       struct xfs_mount *mp = leaf1_bp->b_target->bt_mount;
 
-       xfs_attr3_leaf_hdr_from_disk(&ichdr1, leaf1_bp->b_addr);
-       xfs_attr3_leaf_hdr_from_disk(&ichdr2, leaf2_bp->b_addr);
+       xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr1, leaf1_bp->b_addr);
+       xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr2, leaf2_bp->b_addr);
        return xfs_attr3_leaf_order(leaf1_bp, &ichdr1, leaf2_bp, &ichdr2);
 }
 
@@ -1388,8 +1466,8 @@ xfs_attr3_leaf_rebalance(
        ASSERT(blk2->magic == XFS_ATTR_LEAF_MAGIC);
        leaf1 = blk1->bp->b_addr;
        leaf2 = blk2->bp->b_addr;
-       xfs_attr3_leaf_hdr_from_disk(&ichdr1, leaf1);
-       xfs_attr3_leaf_hdr_from_disk(&ichdr2, leaf2);
+       xfs_attr3_leaf_hdr_from_disk(state->args->geo, &ichdr1, leaf1);
+       xfs_attr3_leaf_hdr_from_disk(state->args->geo, &ichdr2, leaf2);
        ASSERT(ichdr2.count == 0);
        args = state->args;
 
@@ -1490,8 +1568,8 @@ xfs_attr3_leaf_rebalance(
                                        ichdr1.count, count);
        }
 
-       xfs_attr3_leaf_hdr_to_disk(leaf1, &ichdr1);
-       xfs_attr3_leaf_hdr_to_disk(leaf2, &ichdr2);
+       xfs_attr3_leaf_hdr_to_disk(state->args->geo, leaf1, &ichdr1);
+       xfs_attr3_leaf_hdr_to_disk(state->args->geo, leaf2, &ichdr2);
        xfs_trans_log_buf(args->trans, blk1->bp, 0, args->geo->blksize - 1);
        xfs_trans_log_buf(args->trans, blk2->bp, 0, args->geo->blksize - 1);
 
@@ -1684,7 +1762,7 @@ xfs_attr3_leaf_toosmall(
         */
        blk = &state->path.blk[ state->path.active-1 ];
        leaf = blk->bp->b_addr;
-       xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf);
+       xfs_attr3_leaf_hdr_from_disk(state->args->geo, &ichdr, leaf);
        bytes = xfs_attr3_leaf_hdr_size(leaf) +
                ichdr.count * sizeof(xfs_attr_leaf_entry_t) +
                ichdr.usedbytes;
@@ -1740,7 +1818,7 @@ xfs_attr3_leaf_toosmall(
                if (error)
                        return error;
 
-               xfs_attr3_leaf_hdr_from_disk(&ichdr2, bp->b_addr);
+               xfs_attr3_leaf_hdr_from_disk(state->args->geo, &ichdr2, bp->b_addr);
 
                bytes = state->args->geo->blksize -
                        (state->args->geo->blksize >> 2) -
@@ -1805,7 +1883,7 @@ xfs_attr3_leaf_remove(
        trace_xfs_attr_leaf_remove(args);
 
        leaf = bp->b_addr;
-       xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf);
+       xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf);
 
        ASSERT(ichdr.count > 0 && ichdr.count < args->geo->blksize / 8);
        ASSERT(args->index >= 0 && args->index < ichdr.count);
@@ -1918,12 +1996,11 @@ xfs_attr3_leaf_remove(
                                tmp = be16_to_cpu(entry->nameidx);
                }
                ichdr.firstused = tmp;
-               if (!ichdr.firstused)
-                       ichdr.firstused = tmp - XFS_ATTR_LEAF_NAME_ALIGN;
+               ASSERT(ichdr.firstused != 0);
        } else {
                ichdr.holes = 1;        /* mark as needing compaction */
        }
-       xfs_attr3_leaf_hdr_to_disk(leaf, &ichdr);
+       xfs_attr3_leaf_hdr_to_disk(args->geo, leaf, &ichdr);
        xfs_trans_log_buf(args->trans, bp,
                          XFS_DA_LOGRANGE(leaf, &leaf->hdr,
                                          xfs_attr3_leaf_hdr_size(leaf)));
@@ -1957,8 +2034,8 @@ xfs_attr3_leaf_unbalance(
 
        drop_leaf = drop_blk->bp->b_addr;
        save_leaf = save_blk->bp->b_addr;
-       xfs_attr3_leaf_hdr_from_disk(&drophdr, drop_leaf);
-       xfs_attr3_leaf_hdr_from_disk(&savehdr, save_leaf);
+       xfs_attr3_leaf_hdr_from_disk(state->args->geo, &drophdr, drop_leaf);
+       xfs_attr3_leaf_hdr_from_disk(state->args->geo, &savehdr, save_leaf);
        entry = xfs_attr3_leaf_entryp(drop_leaf);
 
        /*
@@ -2012,7 +2089,7 @@ xfs_attr3_leaf_unbalance(
                tmphdr.firstused = state->args->geo->blksize;
 
                /* write the header to the temp buffer to initialise it */
-               xfs_attr3_leaf_hdr_to_disk(tmp_leaf, &tmphdr);
+               xfs_attr3_leaf_hdr_to_disk(state->args->geo, tmp_leaf, &tmphdr);
 
                if (xfs_attr3_leaf_order(save_blk->bp, &savehdr,
                                         drop_blk->bp, &drophdr)) {
@@ -2039,7 +2116,7 @@ xfs_attr3_leaf_unbalance(
                kmem_free(tmp_leaf);
        }
 
-       xfs_attr3_leaf_hdr_to_disk(save_leaf, &savehdr);
+       xfs_attr3_leaf_hdr_to_disk(state->args->geo, save_leaf, &savehdr);
        xfs_trans_log_buf(state->args->trans, save_blk->bp, 0,
                                           state->args->geo->blksize - 1);
 
@@ -2085,7 +2162,7 @@ xfs_attr3_leaf_lookup_int(
        trace_xfs_attr_leaf_lookup(args);
 
        leaf = bp->b_addr;
-       xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf);
+       xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf);
        entries = xfs_attr3_leaf_entryp(leaf);
        ASSERT(ichdr.count < args->geo->blksize / 8);
 
@@ -2190,7 +2267,7 @@ xfs_attr3_leaf_getvalue(
        int                     valuelen;
 
        leaf = bp->b_addr;
-       xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf);
+       xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf);
        ASSERT(ichdr.count < args->geo->blksize / 8);
        ASSERT(args->index < ichdr.count);
 
@@ -2391,8 +2468,9 @@ xfs_attr_leaf_lasthash(
 {
        struct xfs_attr3_icleaf_hdr ichdr;
        struct xfs_attr_leaf_entry *entries;
+       struct xfs_mount *mp = bp->b_target->bt_mount;
 
-       xfs_attr3_leaf_hdr_from_disk(&ichdr, bp->b_addr);
+       xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr, bp->b_addr);
        entries = xfs_attr3_leaf_entryp(bp->b_addr);
        if (count)
                *count = ichdr.count;
@@ -2486,7 +2564,7 @@ xfs_attr3_leaf_clearflag(
        ASSERT(entry->flags & XFS_ATTR_INCOMPLETE);
 
 #ifdef DEBUG
-       xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf);
+       xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf);
        ASSERT(args->index < ichdr.count);
        ASSERT(args->index >= 0);
 
@@ -2550,7 +2628,7 @@ xfs_attr3_leaf_setflag(
 
        leaf = bp->b_addr;
 #ifdef DEBUG
-       xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf);
+       xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf);
        ASSERT(args->index < ichdr.count);
        ASSERT(args->index >= 0);
 #endif
@@ -2629,11 +2707,11 @@ xfs_attr3_leaf_flipflags(
        entry2 = &xfs_attr3_leaf_entryp(leaf2)[args->index2];
 
 #ifdef DEBUG
-       xfs_attr3_leaf_hdr_from_disk(&ichdr1, leaf1);
+       xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr1, leaf1);
        ASSERT(args->index < ichdr1.count);
        ASSERT(args->index >= 0);
 
-       xfs_attr3_leaf_hdr_from_disk(&ichdr2, leaf2);
+       xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr2, leaf2);
        ASSERT(args->index2 < ichdr2.count);
        ASSERT(args->index2 >= 0);
 
index e2929da7c3ba40c1156bfcfe762f2f076389e64f..025c4b820c03a1c642c18d9c53d46e08a0ab2d94 100644 (file)
@@ -100,9 +100,11 @@ int        xfs_attr_leaf_newentsize(struct xfs_da_args *args, int *local);
 int    xfs_attr3_leaf_read(struct xfs_trans *tp, struct xfs_inode *dp,
                        xfs_dablk_t bno, xfs_daddr_t mappedbno,
                        struct xfs_buf **bpp);
-void   xfs_attr3_leaf_hdr_from_disk(struct xfs_attr3_icleaf_hdr *to,
+void   xfs_attr3_leaf_hdr_from_disk(struct xfs_da_geometry *geo,
+                                    struct xfs_attr3_icleaf_hdr *to,
                                     struct xfs_attr_leafblock *from);
-void   xfs_attr3_leaf_hdr_to_disk(struct xfs_attr_leafblock *to,
+void   xfs_attr3_leaf_hdr_to_disk(struct xfs_da_geometry *geo,
+                                  struct xfs_attr_leafblock *to,
                                   struct xfs_attr3_icleaf_hdr *from);
 
 #endif /* __XFS_ATTR_LEAF_H__ */
index 61ec015dca168e4b3d6c067159f252d6f59506b1..aeffeaaac0ec406e543730eb608de1eb3ebc40fb 100644 (file)
@@ -244,30 +244,6 @@ xfs_bmap_forkoff_reset(
        }
 }
 
-/*
- * Debug/sanity checking code
- */
-
-STATIC int
-xfs_bmap_sanity_check(
-       struct xfs_mount        *mp,
-       struct xfs_buf          *bp,
-       int                     level)
-{
-       struct xfs_btree_block  *block = XFS_BUF_TO_BLOCK(bp);
-
-       if (block->bb_magic != cpu_to_be32(XFS_BMAP_CRC_MAGIC) &&
-           block->bb_magic != cpu_to_be32(XFS_BMAP_MAGIC))
-               return 0;
-
-       if (be16_to_cpu(block->bb_level) != level ||
-           be16_to_cpu(block->bb_numrecs) == 0 ||
-           be16_to_cpu(block->bb_numrecs) > mp->m_bmap_dmxr[level != 0])
-               return 0;
-
-       return 1;
-}
-
 #ifdef DEBUG
 STATIC struct xfs_buf *
 xfs_bmap_get_bp(
@@ -410,9 +386,6 @@ xfs_bmap_check_leaf_extents(
                                goto error_norelse;
                }
                block = XFS_BUF_TO_BLOCK(bp);
-               XFS_WANT_CORRUPTED_GOTO(
-                       xfs_bmap_sanity_check(mp, bp, level),
-                       error0);
                if (level == 0)
                        break;
 
@@ -424,7 +397,8 @@ xfs_bmap_check_leaf_extents(
                xfs_check_block(block, mp, 0, 0);
                pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]);
                bno = be64_to_cpu(*pp);
-               XFS_WANT_CORRUPTED_GOTO(XFS_FSB_SANITY_CHECK(mp, bno), error0);
+               XFS_WANT_CORRUPTED_GOTO(mp,
+                                       XFS_FSB_SANITY_CHECK(mp, bno), error0);
                if (bp_release) {
                        bp_release = 0;
                        xfs_trans_brelse(NULL, bp);
@@ -1029,7 +1003,7 @@ xfs_bmap_add_attrfork_btree(
                if ((error = xfs_bmbt_lookup_ge(cur, 0, 0, 0, &stat)))
                        goto error0;
                /* must be at least one entry */
-               XFS_WANT_CORRUPTED_GOTO(stat == 1, error0);
+               XFS_WANT_CORRUPTED_GOTO(mp, stat == 1, error0);
                if ((error = xfs_btree_new_iroot(cur, flags, &stat)))
                        goto error0;
                if (stat == 0) {
@@ -1311,14 +1285,12 @@ xfs_bmap_read_extents(
                if (error)
                        return error;
                block = XFS_BUF_TO_BLOCK(bp);
-               XFS_WANT_CORRUPTED_GOTO(
-                       xfs_bmap_sanity_check(mp, bp, level),
-                       error0);
                if (level == 0)
                        break;
                pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]);
                bno = be64_to_cpu(*pp);
-               XFS_WANT_CORRUPTED_GOTO(XFS_FSB_SANITY_CHECK(mp, bno), error0);
+               XFS_WANT_CORRUPTED_GOTO(mp,
+                       XFS_FSB_SANITY_CHECK(mp, bno), error0);
                xfs_trans_brelse(tp, bp);
        }
        /*
@@ -1345,9 +1317,6 @@ xfs_bmap_read_extents(
                                XFS_ERRLEVEL_LOW, ip->i_mount, block);
                        goto error0;
                }
-               XFS_WANT_CORRUPTED_GOTO(
-                       xfs_bmap_sanity_check(mp, bp, 0),
-                       error0);
                /*
                 * Read-ahead the next leaf block, if any.
                 */
@@ -1755,7 +1724,9 @@ xfs_bmap_add_extent_delay_real(
        xfs_filblks_t           temp=0; /* value for da_new calculations */
        xfs_filblks_t           temp2=0;/* value for da_new calculations */
        int                     tmp_rval;       /* partial logging flags */
+       struct xfs_mount        *mp;
 
+       mp  = bma->tp ? bma->tp->t_mountp : NULL;
        ifp = XFS_IFORK_PTR(bma->ip, XFS_DATA_FORK);
 
        ASSERT(bma->idx >= 0);
@@ -1866,15 +1837,15 @@ xfs_bmap_add_extent_delay_real(
                                        RIGHT.br_blockcount, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                        error = xfs_btree_delete(bma->cur, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                        error = xfs_btree_decrement(bma->cur, 0, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                        error = xfs_bmbt_update(bma->cur, LEFT.br_startoff,
                                        LEFT.br_startblock,
                                        LEFT.br_blockcount +
@@ -1907,7 +1878,7 @@ xfs_bmap_add_extent_delay_real(
                                        &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                        error = xfs_bmbt_update(bma->cur, LEFT.br_startoff,
                                        LEFT.br_startblock,
                                        LEFT.br_blockcount +
@@ -1938,7 +1909,7 @@ xfs_bmap_add_extent_delay_real(
                                        RIGHT.br_blockcount, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                        error = xfs_bmbt_update(bma->cur, PREV.br_startoff,
                                        new->br_startblock,
                                        PREV.br_blockcount +
@@ -1968,12 +1939,12 @@ xfs_bmap_add_extent_delay_real(
                                        &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 0, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
                        bma->cur->bc_rec.b.br_state = XFS_EXT_NORM;
                        error = xfs_btree_insert(bma->cur, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                }
                break;
 
@@ -2001,7 +1972,7 @@ xfs_bmap_add_extent_delay_real(
                                        &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                        error = xfs_bmbt_update(bma->cur, LEFT.br_startoff,
                                        LEFT.br_startblock,
                                        LEFT.br_blockcount +
@@ -2038,12 +2009,12 @@ xfs_bmap_add_extent_delay_real(
                                        &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 0, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
                        bma->cur->bc_rec.b.br_state = XFS_EXT_NORM;
                        error = xfs_btree_insert(bma->cur, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                }
 
                if (xfs_bmap_needs_btree(bma->ip, XFS_DATA_FORK)) {
@@ -2084,7 +2055,7 @@ xfs_bmap_add_extent_delay_real(
                                        RIGHT.br_blockcount, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                        error = xfs_bmbt_update(bma->cur, new->br_startoff,
                                        new->br_startblock,
                                        new->br_blockcount +
@@ -2122,12 +2093,12 @@ xfs_bmap_add_extent_delay_real(
                                        &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 0, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
                        bma->cur->bc_rec.b.br_state = XFS_EXT_NORM;
                        error = xfs_btree_insert(bma->cur, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                }
 
                if (xfs_bmap_needs_btree(bma->ip, XFS_DATA_FORK)) {
@@ -2191,12 +2162,12 @@ xfs_bmap_add_extent_delay_real(
                                        &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 0, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
                        bma->cur->bc_rec.b.br_state = XFS_EXT_NORM;
                        error = xfs_btree_insert(bma->cur, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                }
 
                if (xfs_bmap_needs_btree(bma->ip, XFS_DATA_FORK)) {
@@ -2212,9 +2183,8 @@ xfs_bmap_add_extent_delay_real(
                diff = (int)(temp + temp2 - startblockval(PREV.br_startblock) -
                        (bma->cur ? bma->cur->bc_private.b.allocated : 0));
                if (diff > 0) {
-                       error = xfs_icsb_modify_counters(bma->ip->i_mount,
-                                       XFS_SBS_FDBLOCKS,
-                                       -((int64_t)diff), 0);
+                       error = xfs_mod_fdblocks(bma->ip->i_mount,
+                                                -((int64_t)diff), false);
                        ASSERT(!error);
                        if (error)
                                goto done;
@@ -2265,9 +2235,8 @@ xfs_bmap_add_extent_delay_real(
                        temp += bma->cur->bc_private.b.allocated;
                ASSERT(temp <= da_old);
                if (temp < da_old)
-                       xfs_icsb_modify_counters(bma->ip->i_mount,
-                                       XFS_SBS_FDBLOCKS,
-                                       (int64_t)(da_old - temp), 0);
+                       xfs_mod_fdblocks(bma->ip->i_mount,
+                                       (int64_t)(da_old - temp), false);
        }
 
        /* clear out the allocated field, done with it now in any case. */
@@ -2309,6 +2278,7 @@ xfs_bmap_add_extent_unwritten_real(
                                        /* left is 0, right is 1, prev is 2 */
        int                     rval=0; /* return value (logging flags) */
        int                     state = 0;/* state bits, accessed thru macros */
+       struct xfs_mount        *mp = tp->t_mountp;
 
        *logflagsp = 0;
 
@@ -2421,19 +2391,19 @@ xfs_bmap_add_extent_unwritten_real(
                                        RIGHT.br_startblock,
                                        RIGHT.br_blockcount, &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                        if ((error = xfs_btree_delete(cur, &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                        if ((error = xfs_btree_decrement(cur, 0, &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                        if ((error = xfs_btree_delete(cur, &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                        if ((error = xfs_btree_decrement(cur, 0, &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                        if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
                                LEFT.br_startblock,
                                LEFT.br_blockcount + PREV.br_blockcount +
@@ -2464,13 +2434,13 @@ xfs_bmap_add_extent_unwritten_real(
                                        PREV.br_startblock, PREV.br_blockcount,
                                        &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                        if ((error = xfs_btree_delete(cur, &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                        if ((error = xfs_btree_decrement(cur, 0, &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                        if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,
                                LEFT.br_startblock,
                                LEFT.br_blockcount + PREV.br_blockcount,
@@ -2499,13 +2469,13 @@ xfs_bmap_add_extent_unwritten_real(
                                        RIGHT.br_startblock,
                                        RIGHT.br_blockcount, &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                        if ((error = xfs_btree_delete(cur, &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                        if ((error = xfs_btree_decrement(cur, 0, &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                        if ((error = xfs_bmbt_update(cur, new->br_startoff,
                                new->br_startblock,
                                new->br_blockcount + RIGHT.br_blockcount,
@@ -2532,7 +2502,7 @@ xfs_bmap_add_extent_unwritten_real(
                                        new->br_startblock, new->br_blockcount,
                                        &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                        if ((error = xfs_bmbt_update(cur, new->br_startoff,
                                new->br_startblock, new->br_blockcount,
                                newext)))
@@ -2569,7 +2539,7 @@ xfs_bmap_add_extent_unwritten_real(
                                        PREV.br_startblock, PREV.br_blockcount,
                                        &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                        if ((error = xfs_bmbt_update(cur,
                                PREV.br_startoff + new->br_blockcount,
                                PREV.br_startblock + new->br_blockcount,
@@ -2611,7 +2581,7 @@ xfs_bmap_add_extent_unwritten_real(
                                        PREV.br_startblock, PREV.br_blockcount,
                                        &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                        if ((error = xfs_bmbt_update(cur,
                                PREV.br_startoff + new->br_blockcount,
                                PREV.br_startblock + new->br_blockcount,
@@ -2621,7 +2591,7 @@ xfs_bmap_add_extent_unwritten_real(
                        cur->bc_rec.b = *new;
                        if ((error = xfs_btree_insert(cur, &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                }
                break;
 
@@ -2651,7 +2621,7 @@ xfs_bmap_add_extent_unwritten_real(
                                        PREV.br_startblock,
                                        PREV.br_blockcount, &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                        if ((error = xfs_bmbt_update(cur, PREV.br_startoff,
                                PREV.br_startblock,
                                PREV.br_blockcount - new->br_blockcount,
@@ -2689,7 +2659,7 @@ xfs_bmap_add_extent_unwritten_real(
                                        PREV.br_startblock, PREV.br_blockcount,
                                        &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                        if ((error = xfs_bmbt_update(cur, PREV.br_startoff,
                                PREV.br_startblock,
                                PREV.br_blockcount - new->br_blockcount,
@@ -2699,11 +2669,11 @@ xfs_bmap_add_extent_unwritten_real(
                                        new->br_startblock, new->br_blockcount,
                                        &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 0, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
                        cur->bc_rec.b.br_state = XFS_EXT_NORM;
                        if ((error = xfs_btree_insert(cur, &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                }
                break;
 
@@ -2737,7 +2707,7 @@ xfs_bmap_add_extent_unwritten_real(
                                        PREV.br_startblock, PREV.br_blockcount,
                                        &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                        /* new right extent - oldext */
                        if ((error = xfs_bmbt_update(cur, r[1].br_startoff,
                                r[1].br_startblock, r[1].br_blockcount,
@@ -2749,7 +2719,7 @@ xfs_bmap_add_extent_unwritten_real(
                                new->br_startoff - PREV.br_startoff;
                        if ((error = xfs_btree_insert(cur, &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                        /*
                         * Reset the cursor to the position of the new extent
                         * we are about to insert as we can't trust it after
@@ -2759,12 +2729,12 @@ xfs_bmap_add_extent_unwritten_real(
                                        new->br_startblock, new->br_blockcount,
                                        &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 0, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
                        /* new middle extent - newext */
                        cur->bc_rec.b.br_state = new->br_state;
                        if ((error = xfs_btree_insert(cur, &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                }
                break;
 
@@ -2944,8 +2914,8 @@ xfs_bmap_add_extent_hole_delay(
        }
        if (oldlen != newlen) {
                ASSERT(oldlen > newlen);
-               xfs_icsb_modify_counters(ip->i_mount, XFS_SBS_FDBLOCKS,
-                       (int64_t)(oldlen - newlen), 0);
+               xfs_mod_fdblocks(ip->i_mount, (int64_t)(oldlen - newlen),
+                                false);
                /*
                 * Nothing to do for disk quota accounting here.
                 */
@@ -2968,7 +2938,9 @@ xfs_bmap_add_extent_hole_real(
        xfs_bmbt_irec_t         right;  /* right neighbor extent entry */
        int                     rval=0; /* return value (logging flags) */
        int                     state;  /* state bits, accessed thru macros */
+       struct xfs_mount        *mp;
 
+       mp = bma->tp ? bma->tp->t_mountp : NULL;
        ifp = XFS_IFORK_PTR(bma->ip, whichfork);
 
        ASSERT(bma->idx >= 0);
@@ -3056,15 +3028,15 @@ xfs_bmap_add_extent_hole_real(
                                        &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                        error = xfs_btree_delete(bma->cur, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                        error = xfs_btree_decrement(bma->cur, 0, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                        error = xfs_bmbt_update(bma->cur, left.br_startoff,
                                        left.br_startblock,
                                        left.br_blockcount +
@@ -3097,7 +3069,7 @@ xfs_bmap_add_extent_hole_real(
                                        &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                        error = xfs_bmbt_update(bma->cur, left.br_startoff,
                                        left.br_startblock,
                                        left.br_blockcount +
@@ -3131,7 +3103,7 @@ xfs_bmap_add_extent_hole_real(
                                        right.br_blockcount, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                        error = xfs_bmbt_update(bma->cur, new->br_startoff,
                                        new->br_startblock,
                                        new->br_blockcount +
@@ -3161,12 +3133,12 @@ xfs_bmap_add_extent_hole_real(
                                        new->br_blockcount, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 0, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
                        bma->cur->bc_rec.b.br_state = new->br_state;
                        error = xfs_btree_insert(bma->cur, &i);
                        if (error)
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                }
                break;
        }
@@ -4160,18 +4132,15 @@ xfs_bmapi_reserve_delalloc(
        ASSERT(indlen > 0);
 
        if (rt) {
-               error = xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS,
-                                         -((int64_t)extsz), 0);
+               error = xfs_mod_frextents(mp, -((int64_t)extsz));
        } else {
-               error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
-                                                -((int64_t)alen), 0);
+               error = xfs_mod_fdblocks(mp, -((int64_t)alen), false);
        }
 
        if (error)
                goto out_unreserve_quota;
 
-       error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
-                                        -((int64_t)indlen), 0);
+       error = xfs_mod_fdblocks(mp, -((int64_t)indlen), false);
        if (error)
                goto out_unreserve_blocks;
 
@@ -4198,9 +4167,9 @@ xfs_bmapi_reserve_delalloc(
 
 out_unreserve_blocks:
        if (rt)
-               xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, extsz, 0);
+               xfs_mod_frextents(mp, extsz);
        else
-               xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, alen, 0);
+               xfs_mod_fdblocks(mp, alen, false);
 out_unreserve_quota:
        if (XFS_IS_QUOTA_ON(mp))
                xfs_trans_unreserve_quota_nblks(NULL, ip, (long)alen, 0, rt ?
@@ -4801,7 +4770,7 @@ xfs_bmap_del_extent(
                                        got.br_startblock, got.br_blockcount,
                                        &i)))
                                goto done;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                }
                da_old = da_new = 0;
        } else {
@@ -4835,7 +4804,7 @@ xfs_bmap_del_extent(
                }
                if ((error = xfs_btree_delete(cur, &i)))
                        goto done;
-               XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+               XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                break;
 
        case 2:
@@ -4935,7 +4904,8 @@ xfs_bmap_del_extent(
                                                        got.br_startblock,
                                                        temp, &i)))
                                                goto done;
-                                       XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                                       XFS_WANT_CORRUPTED_GOTO(mp,
+                                                               i == 1, done);
                                        /*
                                         * Update the btree record back
                                         * to the original value.
@@ -4956,7 +4926,7 @@ xfs_bmap_del_extent(
                                        error = -ENOSPC;
                                        goto done;
                                }
-                               XFS_WANT_CORRUPTED_GOTO(i == 1, done);
+                               XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
                        } else
                                flags |= xfs_ilog_fext(whichfork);
                        XFS_IFORK_NEXT_SET(ip, whichfork,
@@ -5012,10 +4982,8 @@ xfs_bmap_del_extent(
         * Nothing to do for disk quota accounting here.
         */
        ASSERT(da_old >= da_new);
-       if (da_old > da_new) {
-               xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
-                       (int64_t)(da_old - da_new), 0);
-       }
+       if (da_old > da_new)
+               xfs_mod_fdblocks(mp, (int64_t)(da_old - da_new), false);
 done:
        *logflagsp = flags;
        return error;
@@ -5284,14 +5252,13 @@ xfs_bunmapi(
 
                                rtexts = XFS_FSB_TO_B(mp, del.br_blockcount);
                                do_div(rtexts, mp->m_sb.sb_rextsize);
-                               xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS,
-                                               (int64_t)rtexts, 0);
+                               xfs_mod_frextents(mp, (int64_t)rtexts);
                                (void)xfs_trans_reserve_quota_nblks(NULL,
                                        ip, -((long)del.br_blockcount), 0,
                                        XFS_QMOPT_RES_RTBLKS);
                        } else {
-                               xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
-                                               (int64_t)del.br_blockcount, 0);
+                               xfs_mod_fdblocks(mp, (int64_t)del.br_blockcount,
+                                                false);
                                (void)xfs_trans_reserve_quota_nblks(NULL,
                                        ip, -((long)del.br_blockcount), 0,
                                        XFS_QMOPT_RES_REGBLKS);
@@ -5453,6 +5420,7 @@ xfs_bmse_merge(
        struct xfs_bmbt_irec            left;
        xfs_filblks_t                   blockcount;
        int                             error, i;
+       struct xfs_mount                *mp = ip->i_mount;
 
        xfs_bmbt_get_all(gotp, &got);
        xfs_bmbt_get_all(leftp, &left);
@@ -5487,19 +5455,19 @@ xfs_bmse_merge(
                                   got.br_blockcount, &i);
        if (error)
                return error;
-       XFS_WANT_CORRUPTED_RETURN(i == 1);
+       XFS_WANT_CORRUPTED_RETURN(mp, i == 1);
 
        error = xfs_btree_delete(cur, &i);
        if (error)
                return error;
-       XFS_WANT_CORRUPTED_RETURN(i == 1);
+       XFS_WANT_CORRUPTED_RETURN(mp, i == 1);
 
        /* lookup and update size of the previous extent */
        error = xfs_bmbt_lookup_eq(cur, left.br_startoff, left.br_startblock,
                                   left.br_blockcount, &i);
        if (error)
                return error;
-       XFS_WANT_CORRUPTED_RETURN(i == 1);
+       XFS_WANT_CORRUPTED_RETURN(mp, i == 1);
 
        left.br_blockcount = blockcount;
 
@@ -5518,50 +5486,92 @@ xfs_bmse_shift_one(
        int                             *current_ext,
        struct xfs_bmbt_rec_host        *gotp,
        struct xfs_btree_cur            *cur,
-       int                             *logflags)
+       int                             *logflags,
+       enum shift_direction            direction)
 {
        struct xfs_ifork                *ifp;
+       struct xfs_mount                *mp;
        xfs_fileoff_t                   startoff;
-       struct xfs_bmbt_rec_host        *leftp;
+       struct xfs_bmbt_rec_host        *adj_irecp;
        struct xfs_bmbt_irec            got;
-       struct xfs_bmbt_irec            left;
+       struct xfs_bmbt_irec            adj_irec;
        int                             error;
        int                             i;
+       int                             total_extents;
 
+       mp = ip->i_mount;
        ifp = XFS_IFORK_PTR(ip, whichfork);
+       total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t);
 
        xfs_bmbt_get_all(gotp, &got);
-       startoff = got.br_startoff - offset_shift_fsb;
 
        /* delalloc extents should be prevented by caller */
-       XFS_WANT_CORRUPTED_RETURN(!isnullstartblock(got.br_startblock));
+       XFS_WANT_CORRUPTED_RETURN(mp, !isnullstartblock(got.br_startblock));
 
-       /*
-        * Check for merge if we've got an extent to the left, otherwise make
-        * sure there's enough room at the start of the file for the shift.
-        */
-       if (*current_ext) {
-               /* grab the left extent and check for a large enough hole */
-               leftp = xfs_iext_get_ext(ifp, *current_ext - 1);
-               xfs_bmbt_get_all(leftp, &left);
+       if (direction == SHIFT_LEFT) {
+               startoff = got.br_startoff - offset_shift_fsb;
+
+               /*
+                * Check for merge if we've got an extent to the left,
+                * otherwise make sure there's enough room at the start
+                * of the file for the shift.
+                */
+               if (!*current_ext) {
+                       if (got.br_startoff < offset_shift_fsb)
+                               return -EINVAL;
+                       goto update_current_ext;
+               }
+               /*
+                * grab the left extent and check for a large
+                * enough hole.
+                */
+               adj_irecp = xfs_iext_get_ext(ifp, *current_ext - 1);
+               xfs_bmbt_get_all(adj_irecp, &adj_irec);
 
-               if (startoff < left.br_startoff + left.br_blockcount)
+               if (startoff <
+                   adj_irec.br_startoff + adj_irec.br_blockcount)
                        return -EINVAL;
 
                /* check whether to merge the extent or shift it down */
-               if (xfs_bmse_can_merge(&left, &got, offset_shift_fsb)) {
+               if (xfs_bmse_can_merge(&adj_irec, &got,
+                                      offset_shift_fsb)) {
                        return xfs_bmse_merge(ip, whichfork, offset_shift_fsb,
-                                             *current_ext, gotp, leftp, cur,
-                                             logflags);
+                                             *current_ext, gotp, adj_irecp,
+                                             cur, logflags);
                }
-       } else if (got.br_startoff < offset_shift_fsb)
-               return -EINVAL;
-
+       } else {
+               startoff = got.br_startoff + offset_shift_fsb;
+               /* nothing to move if this is the last extent */
+               if (*current_ext >= (total_extents - 1))
+                       goto update_current_ext;
+               /*
+                * If this is not the last extent in the file, make sure there
+                * is enough room between current extent and next extent for
+                * accommodating the shift.
+                */
+               adj_irecp = xfs_iext_get_ext(ifp, *current_ext + 1);
+               xfs_bmbt_get_all(adj_irecp, &adj_irec);
+               if (startoff + got.br_blockcount > adj_irec.br_startoff)
+                       return -EINVAL;
+               /*
+                * Unlike a left shift (which involves a hole punch),
+                * a right shift does not modify extent neighbors
+                * in any way. We should never find mergeable extents
+                * in this scenario. Check anyways and warn if we
+                * encounter two extents that could be one.
+                */
+               if (xfs_bmse_can_merge(&got, &adj_irec, offset_shift_fsb))
+                       WARN_ON_ONCE(1);
+       }
        /*
         * Increment the extent index for the next iteration, update the start
         * offset of the in-core extent and update the btree if applicable.
         */
-       (*current_ext)++;
+update_current_ext:
+       if (direction == SHIFT_LEFT)
+               (*current_ext)++;
+       else
+               (*current_ext)--;
        xfs_bmbt_set_startoff(gotp, startoff);
        *logflags |= XFS_ILOG_CORE;
        if (!cur) {
@@ -5573,18 +5583,18 @@ xfs_bmse_shift_one(
                                   got.br_blockcount, &i);
        if (error)
                return error;
-       XFS_WANT_CORRUPTED_RETURN(i == 1);
+       XFS_WANT_CORRUPTED_RETURN(mp, i == 1);
 
        got.br_startoff = startoff;
        return xfs_bmbt_update(cur, got.br_startoff, got.br_startblock,
-                               got.br_blockcount, got.br_state);
+                              got.br_blockcount, got.br_state);
 }
 
 /*
- * Shift extent records to the left to cover a hole.
+ * Shift extent records to the left/right to cover/create a hole.
  *
  * The maximum number of extents to be shifted in a single operation is
- * @num_exts. @start_fsb specifies the file offset to start the shift and the
+ * @num_exts. @stop_fsb specifies the file offset at which to stop shift and the
  * file offset where we've left off is returned in @next_fsb. @offset_shift_fsb
  * is the length by which each extent is shifted. If there is no hole to shift
  * the extents into, this will be considered invalid operation and we abort
@@ -5594,12 +5604,13 @@ int
 xfs_bmap_shift_extents(
        struct xfs_trans        *tp,
        struct xfs_inode        *ip,
-       xfs_fileoff_t           start_fsb,
+       xfs_fileoff_t           *next_fsb,
        xfs_fileoff_t           offset_shift_fsb,
        int                     *done,
-       xfs_fileoff_t           *next_fsb,
+       xfs_fileoff_t           stop_fsb,
        xfs_fsblock_t           *firstblock,
        struct xfs_bmap_free    *flist,
+       enum shift_direction    direction,
        int                     num_exts)
 {
        struct xfs_btree_cur            *cur = NULL;
@@ -5609,10 +5620,11 @@ xfs_bmap_shift_extents(
        struct xfs_ifork                *ifp;
        xfs_extnum_t                    nexts = 0;
        xfs_extnum_t                    current_ext;
+       xfs_extnum_t                    total_extents;
+       xfs_extnum_t                    stop_extent;
        int                             error = 0;
        int                             whichfork = XFS_DATA_FORK;
        int                             logflags = 0;
-       int                             total_extents;
 
        if (unlikely(XFS_TEST_ERROR(
            (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
@@ -5628,6 +5640,8 @@ xfs_bmap_shift_extents(
 
        ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
        ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+       ASSERT(direction == SHIFT_LEFT || direction == SHIFT_RIGHT);
+       ASSERT(*next_fsb != NULLFSBLOCK || direction == SHIFT_RIGHT);
 
        ifp = XFS_IFORK_PTR(ip, whichfork);
        if (!(ifp->if_flags & XFS_IFEXTENTS)) {
@@ -5644,44 +5658,84 @@ xfs_bmap_shift_extents(
                cur->bc_private.b.flags = 0;
        }
 
+       /*
+        * There may be delalloc extents in the data fork before the range we
+        * are collapsing out, so we cannot use the count of real extents here.
+        * Instead we have to calculate it from the incore fork.
+        */
+       total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t);
+       if (total_extents == 0) {
+               *done = 1;
+               goto del_cursor;
+       }
+
+       /*
+        * In case of first right shift, we need to initialize next_fsb
+        */
+       if (*next_fsb == NULLFSBLOCK) {
+               gotp = xfs_iext_get_ext(ifp, total_extents - 1);
+               xfs_bmbt_get_all(gotp, &got);
+               *next_fsb = got.br_startoff;
+               if (stop_fsb > *next_fsb) {
+                       *done = 1;
+                       goto del_cursor;
+               }
+       }
+
+       /* Lookup the extent index at which we have to stop */
+       if (direction == SHIFT_RIGHT) {
+               gotp = xfs_iext_bno_to_ext(ifp, stop_fsb, &stop_extent);
+               /* Make stop_extent exclusive of shift range */
+               stop_extent--;
+       } else
+               stop_extent = total_extents;
+
        /*
         * Look up the extent index for the fsb where we start shifting. We can
         * henceforth iterate with current_ext as extent list changes are locked
         * out via ilock.
         *
         * gotp can be null in 2 cases: 1) if there are no extents or 2)
-        * start_fsb lies in a hole beyond which there are no extents. Either
+        * *next_fsb lies in a hole beyond which there are no extents. Either
         * way, we are done.
         */
-       gotp = xfs_iext_bno_to_ext(ifp, start_fsb, &current_ext);
+       gotp = xfs_iext_bno_to_ext(ifp, *next_fsb, &current_ext);
        if (!gotp) {
                *done = 1;
                goto del_cursor;
        }
 
-       /*
-        * There may be delalloc extents in the data fork before the range we
-        * are collapsing out, so we cannot use the count of real extents here.
-        * Instead we have to calculate it from the incore fork.
-        */
-       total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t);
-       while (nexts++ < num_exts && current_ext < total_extents) {
+       /* some sanity checking before we finally start shifting extents */
+       if ((direction == SHIFT_LEFT && current_ext >= stop_extent) ||
+            (direction == SHIFT_RIGHT && current_ext <= stop_extent)) {
+               error = -EIO;
+               goto del_cursor;
+       }
+
+       while (nexts++ < num_exts) {
                error = xfs_bmse_shift_one(ip, whichfork, offset_shift_fsb,
-                                       &current_ext, gotp, cur, &logflags);
+                                          &current_ext, gotp, cur, &logflags,
+                                          direction);
                if (error)
                        goto del_cursor;
+               /*
+                * If there was an extent merge during the shift, the extent
+                * count can change. Update the total and grade the next record.
+                */
+               if (direction == SHIFT_LEFT) {
+                       total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t);
+                       stop_extent = total_extents;
+               }
 
-               /* update total extent count and grab the next record */
-               total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t);
-               if (current_ext >= total_extents)
+               if (current_ext == stop_extent) {
+                       *done = 1;
+                       *next_fsb = NULLFSBLOCK;
                        break;
+               }
                gotp = xfs_iext_get_ext(ifp, current_ext);
        }
 
-       /* Check if we are done */
-       if (current_ext == total_extents) {
-               *done = 1;
-       } else if (next_fsb) {
+       if (!*done) {
                xfs_bmbt_get_all(gotp, &got);
                *next_fsb = got.br_startoff;
        }
@@ -5696,3 +5750,189 @@ del_cursor:
 
        return error;
 }
+
+/*
+ * Splits an extent into two extents at split_fsb block such that it is
+ * the first block of the current_ext. @current_ext is a target extent
+ * to be split. @split_fsb is a block where the extents is split.
+ * If split_fsb lies in a hole or the first block of extents, just return 0.
+ */
+STATIC int
+xfs_bmap_split_extent_at(
+       struct xfs_trans        *tp,
+       struct xfs_inode        *ip,
+       xfs_fileoff_t           split_fsb,
+       xfs_fsblock_t           *firstfsb,
+       struct xfs_bmap_free    *free_list)
+{
+       int                             whichfork = XFS_DATA_FORK;
+       struct xfs_btree_cur            *cur = NULL;
+       struct xfs_bmbt_rec_host        *gotp;
+       struct xfs_bmbt_irec            got;
+       struct xfs_bmbt_irec            new; /* split extent */
+       struct xfs_mount                *mp = ip->i_mount;
+       struct xfs_ifork                *ifp;
+       xfs_fsblock_t                   gotblkcnt; /* new block count for got */
+       xfs_extnum_t                    current_ext;
+       int                             error = 0;
+       int                             logflags = 0;
+       int                             i = 0;
+
+       if (unlikely(XFS_TEST_ERROR(
+           (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
+            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE),
+            mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) {
+               XFS_ERROR_REPORT("xfs_bmap_split_extent_at",
+                                XFS_ERRLEVEL_LOW, mp);
+               return -EFSCORRUPTED;
+       }
+
+       if (XFS_FORCED_SHUTDOWN(mp))
+               return -EIO;
+
+       ifp = XFS_IFORK_PTR(ip, whichfork);
+       if (!(ifp->if_flags & XFS_IFEXTENTS)) {
+               /* Read in all the extents */
+               error = xfs_iread_extents(tp, ip, whichfork);
+               if (error)
+                       return error;
+       }
+
+       /*
+        * gotp can be null in 2 cases: 1) if there are no extents
+        * or 2) split_fsb lies in a hole beyond which there are
+        * no extents. Either way, we are done.
+        */
+       gotp = xfs_iext_bno_to_ext(ifp, split_fsb, &current_ext);
+       if (!gotp)
+               return 0;
+
+       xfs_bmbt_get_all(gotp, &got);
+
+       /*
+        * Check split_fsb lies in a hole or the start boundary offset
+        * of the extent.
+        */
+       if (got.br_startoff >= split_fsb)
+               return 0;
+
+       gotblkcnt = split_fsb - got.br_startoff;
+       new.br_startoff = split_fsb;
+       new.br_startblock = got.br_startblock + gotblkcnt;
+       new.br_blockcount = got.br_blockcount - gotblkcnt;
+       new.br_state = got.br_state;
+
+       if (ifp->if_flags & XFS_IFBROOT) {
+               cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
+               cur->bc_private.b.firstblock = *firstfsb;
+               cur->bc_private.b.flist = free_list;
+               cur->bc_private.b.flags = 0;
+               error = xfs_bmbt_lookup_eq(cur, got.br_startoff,
+                               got.br_startblock,
+                               got.br_blockcount,
+                               &i);
+               if (error)
+                       goto del_cursor;
+               XFS_WANT_CORRUPTED_GOTO(mp, i == 1, del_cursor);
+       }
+
+       xfs_bmbt_set_blockcount(gotp, gotblkcnt);
+       got.br_blockcount = gotblkcnt;
+
+       logflags = XFS_ILOG_CORE;
+       if (cur) {
+               error = xfs_bmbt_update(cur, got.br_startoff,
+                               got.br_startblock,
+                               got.br_blockcount,
+                               got.br_state);
+               if (error)
+                       goto del_cursor;
+       } else
+               logflags |= XFS_ILOG_DEXT;
+
+       /* Add new extent */
+       current_ext++;
+       xfs_iext_insert(ip, current_ext, 1, &new, 0);
+       XFS_IFORK_NEXT_SET(ip, whichfork,
+                          XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
+
+       if (cur) {
+               error = xfs_bmbt_lookup_eq(cur, new.br_startoff,
+                               new.br_startblock, new.br_blockcount,
+                               &i);
+               if (error)
+                       goto del_cursor;
+               XFS_WANT_CORRUPTED_GOTO(mp, i == 0, del_cursor);
+               cur->bc_rec.b.br_state = new.br_state;
+
+               error = xfs_btree_insert(cur, &i);
+               if (error)
+                       goto del_cursor;
+               XFS_WANT_CORRUPTED_GOTO(mp, i == 1, del_cursor);
+       }
+
+       /*
+        * Convert to a btree if necessary.
+        */
+       if (xfs_bmap_needs_btree(ip, whichfork)) {
+               int tmp_logflags; /* partial log flag return val */
+
+               ASSERT(cur == NULL);
+               error = xfs_bmap_extents_to_btree(tp, ip, firstfsb, free_list,
+                               &cur, 0, &tmp_logflags, whichfork);
+               logflags |= tmp_logflags;
+       }
+
+del_cursor:
+       if (cur) {
+               cur->bc_private.b.allocated = 0;
+               xfs_btree_del_cursor(cur,
+                               error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
+       }
+
+       if (logflags)
+               xfs_trans_log_inode(tp, ip, logflags);
+       return error;
+}
+
+int
+xfs_bmap_split_extent(
+       struct xfs_inode        *ip,
+       xfs_fileoff_t           split_fsb)
+{
+       struct xfs_mount        *mp = ip->i_mount;
+       struct xfs_trans        *tp;
+       struct xfs_bmap_free    free_list;
+       xfs_fsblock_t           firstfsb;
+       int                     committed;
+       int                     error;
+
+       tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
+       error = xfs_trans_reserve(tp, &M_RES(mp)->tr_write,
+                       XFS_DIOSTRAT_SPACE_RES(mp, 0), 0);
+       if (error) {
+               xfs_trans_cancel(tp, 0);
+               return error;
+       }
+
+       xfs_ilock(ip, XFS_ILOCK_EXCL);
+       xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
+
+       xfs_bmap_init(&free_list, &firstfsb);
+
+       error = xfs_bmap_split_extent_at(tp, ip, split_fsb,
+                       &firstfsb, &free_list);
+       if (error)
+               goto out;
+
+       error = xfs_bmap_finish(&tp, &free_list, &committed);
+       if (error)
+               goto out;
+
+       return xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
+
+
+out:
+       xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
+       return error;
+}
index b9d8a499d2c458b43f2e5bbe05de4a4cfcfbeff1..6aaa0c1c7200594de983a02b40d61900ced8e200 100644 (file)
@@ -166,6 +166,11 @@ static inline void xfs_bmap_init(xfs_bmap_free_t *flp, xfs_fsblock_t *fbp)
  */
 #define XFS_BMAP_MAX_SHIFT_EXTENTS     1
 
+enum shift_direction {
+       SHIFT_LEFT = 0,
+       SHIFT_RIGHT,
+};
+
 #ifdef DEBUG
 void   xfs_bmap_trace_exlist(struct xfs_inode *ip, xfs_extnum_t cnt,
                int whichfork, unsigned long caller_ip);
@@ -211,8 +216,10 @@ int        xfs_check_nostate_extents(struct xfs_ifork *ifp, xfs_extnum_t idx,
                xfs_extnum_t num);
 uint   xfs_default_attroffset(struct xfs_inode *ip);
 int    xfs_bmap_shift_extents(struct xfs_trans *tp, struct xfs_inode *ip,
-               xfs_fileoff_t start_fsb, xfs_fileoff_t offset_shift_fsb,
-               int *done, xfs_fileoff_t *next_fsb, xfs_fsblock_t *firstblock,
-               struct xfs_bmap_free *flist, int num_exts);
+               xfs_fileoff_t *next_fsb, xfs_fileoff_t offset_shift_fsb,
+               int *done, xfs_fileoff_t stop_fsb, xfs_fsblock_t *firstblock,
+               struct xfs_bmap_free *flist, enum shift_direction direction,
+               int num_exts);
+int    xfs_bmap_split_extent(struct xfs_inode *ip, xfs_fileoff_t split_offset);
 
 #endif /* __XFS_BMAP_H__ */
index 81cad433df85d6a744c898bb2b43f45588c3fbd5..c72283dd8d44b6327e420355864ea8571068c9f4 100644 (file)
@@ -168,7 +168,7 @@ xfs_btree_check_lptr(
        xfs_fsblock_t           bno,    /* btree block disk address */
        int                     level)  /* btree block level */
 {
-       XFS_WANT_CORRUPTED_RETURN(
+       XFS_WANT_CORRUPTED_RETURN(cur->bc_mp,
                level > 0 &&
                bno != NULLFSBLOCK &&
                XFS_FSB_SANITY_CHECK(cur->bc_mp, bno));
@@ -187,7 +187,7 @@ xfs_btree_check_sptr(
 {
        xfs_agblock_t           agblocks = cur->bc_mp->m_sb.sb_agblocks;
 
-       XFS_WANT_CORRUPTED_RETURN(
+       XFS_WANT_CORRUPTED_RETURN(cur->bc_mp,
                level > 0 &&
                bno != NULLAGBLOCK &&
                bno != 0 &&
@@ -1825,7 +1825,7 @@ xfs_btree_lookup(
                        error = xfs_btree_increment(cur, 0, &i);
                        if (error)
                                goto error0;
-                       XFS_WANT_CORRUPTED_RETURN(i == 1);
+                       XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, i == 1);
                        XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
                        *stat = 1;
                        return 0;
@@ -2285,7 +2285,7 @@ xfs_btree_rshift(
        if (error)
                goto error0;
        i = xfs_btree_lastrec(tcur, level);
-       XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+       XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0);
 
        error = xfs_btree_increment(tcur, level, &i);
        if (error)
@@ -3138,7 +3138,7 @@ xfs_btree_insert(
                        goto error0;
                }
 
-               XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+               XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0);
                level++;
 
                /*
@@ -3582,15 +3582,15 @@ xfs_btree_delrec(
                 * Actually any entry but the first would suffice.
                 */
                i = xfs_btree_lastrec(tcur, level);
-               XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+               XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0);
 
                error = xfs_btree_increment(tcur, level, &i);
                if (error)
                        goto error0;
-               XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+               XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0);
 
                i = xfs_btree_lastrec(tcur, level);
-               XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+               XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0);
 
                /* Grab a pointer to the block. */
                right = xfs_btree_get_block(tcur, level, &rbp);
@@ -3634,12 +3634,12 @@ xfs_btree_delrec(
                rrecs = xfs_btree_get_numrecs(right);
                if (!xfs_btree_ptr_is_null(cur, &lptr)) {
                        i = xfs_btree_firstrec(tcur, level);
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+                       XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0);
 
                        error = xfs_btree_decrement(tcur, level, &i);
                        if (error)
                                goto error0;
-                       XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+                       XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0);
                }
        }
 
@@ -3653,13 +3653,13 @@ xfs_btree_delrec(
                 * previous block.
                 */
                i = xfs_btree_firstrec(tcur, level);
-               XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+               XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0);
 
                error = xfs_btree_decrement(tcur, level, &i);
                if (error)
                        goto error0;
                i = xfs_btree_firstrec(tcur, level);
-               XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+               XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0);
 
                /* Grab a pointer to the block. */
                left = xfs_btree_get_block(tcur, level, &lbp);
index 9cb0115c6bd1745576b962dd65fc9f942bc392c3..2385f8cd08ab9f1cdf19ad3a9a8473a5e4e34eb3 100644 (file)
@@ -538,12 +538,12 @@ xfs_da3_root_split(
        oldroot = blk1->bp->b_addr;
        if (oldroot->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC) ||
            oldroot->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC)) {
-               struct xfs_da3_icnode_hdr nodehdr;
+               struct xfs_da3_icnode_hdr icnodehdr;
 
-               dp->d_ops->node_hdr_from_disk(&nodehdr, oldroot);
+               dp->d_ops->node_hdr_from_disk(&icnodehdr, oldroot);
                btree = dp->d_ops->node_tree_p(oldroot);
-               size = (int)((char *)&btree[nodehdr.count] - (char *)oldroot);
-               level = nodehdr.level;
+               size = (int)((char *)&btree[icnodehdr.count] - (char *)oldroot);
+               level = icnodehdr.level;
 
                /*
                 * we are about to copy oldroot to bp, so set up the type
index 0a49b02863724204450fbce07f9df2806b34af76..74bcbabfa52329bda4d932daeab73ae624bde7f1 100644 (file)
@@ -725,7 +725,13 @@ struct xfs_attr3_icleaf_hdr {
        __uint16_t      magic;
        __uint16_t      count;
        __uint16_t      usedbytes;
-       __uint16_t      firstused;
+       /*
+        * firstused is 32-bit here instead of 16-bit like the on-disk variant
+        * to support maximum fsb size of 64k without overflow issues throughout
+        * the attr code. Instead, the overflow condition is handled on
+        * conversion to/from disk.
+        */
+       __uint32_t      firstused;
        __u8            holes;
        struct {
                __uint16_t      base;
@@ -733,6 +739,12 @@ struct xfs_attr3_icleaf_hdr {
        } freemap[XFS_ATTR_LEAF_MAPSIZE];
 };
 
+/*
+ * Special value to represent fs block size in the leaf header firstused field.
+ * Only used when block size overflows the 2-bytes available on disk.
+ */
+#define XFS_ATTR3_LEAF_NULLOFF 0
+
 /*
  * Flags used in the leaf_entry[i].flags field.
  * NOTE: the INCOMPLETE bit must not collide with the flags bits specified
index 5ff31be9b1cd4537052a853dbf6c77776a83af25..de1ea16f57485ccc03143196eb2aced9147aed5b 100644 (file)
@@ -89,7 +89,7 @@ __xfs_dir3_data_check(
                 * so just ensure that the count falls somewhere inside the
                 * block right now.
                 */
-               XFS_WANT_CORRUPTED_RETURN(be32_to_cpu(btp->count) <
+               XFS_WANT_CORRUPTED_RETURN(mp, be32_to_cpu(btp->count) <
                        ((char *)btp - p) / sizeof(struct xfs_dir2_leaf_entry));
                break;
        case cpu_to_be32(XFS_DIR3_DATA_MAGIC):
@@ -107,21 +107,21 @@ __xfs_dir3_data_check(
        bf = ops->data_bestfree_p(hdr);
        count = lastfree = freeseen = 0;
        if (!bf[0].length) {
-               XFS_WANT_CORRUPTED_RETURN(!bf[0].offset);
+               XFS_WANT_CORRUPTED_RETURN(mp, !bf[0].offset);
                freeseen |= 1 << 0;
        }
        if (!bf[1].length) {
-               XFS_WANT_CORRUPTED_RETURN(!bf[1].offset);
+               XFS_WANT_CORRUPTED_RETURN(mp, !bf[1].offset);
                freeseen |= 1 << 1;
        }
        if (!bf[2].length) {
-               XFS_WANT_CORRUPTED_RETURN(!bf[2].offset);
+               XFS_WANT_CORRUPTED_RETURN(mp, !bf[2].offset);
                freeseen |= 1 << 2;
        }
 
-       XFS_WANT_CORRUPTED_RETURN(be16_to_cpu(bf[0].length) >=
+       XFS_WANT_CORRUPTED_RETURN(mp, be16_to_cpu(bf[0].length) >=
                                                be16_to_cpu(bf[1].length));
-       XFS_WANT_CORRUPTED_RETURN(be16_to_cpu(bf[1].length) >=
+       XFS_WANT_CORRUPTED_RETURN(mp, be16_to_cpu(bf[1].length) >=
                                                be16_to_cpu(bf[2].length));
        /*
         * Loop over the data/unused entries.
@@ -134,18 +134,18 @@ __xfs_dir3_data_check(
                 * doesn't need to be there.
                 */
                if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
-                       XFS_WANT_CORRUPTED_RETURN(lastfree == 0);
-                       XFS_WANT_CORRUPTED_RETURN(
+                       XFS_WANT_CORRUPTED_RETURN(mp, lastfree == 0);
+                       XFS_WANT_CORRUPTED_RETURN(mp,
                                be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)) ==
                                               (char *)dup - (char *)hdr);
                        dfp = xfs_dir2_data_freefind(hdr, bf, dup);
                        if (dfp) {
                                i = (int)(dfp - bf);
-                               XFS_WANT_CORRUPTED_RETURN(
+                               XFS_WANT_CORRUPTED_RETURN(mp,
                                        (freeseen & (1 << i)) == 0);
                                freeseen |= 1 << i;
                        } else {
-                               XFS_WANT_CORRUPTED_RETURN(
+                               XFS_WANT_CORRUPTED_RETURN(mp,
                                        be16_to_cpu(dup->length) <=
                                                be16_to_cpu(bf[2].length));
                        }
@@ -160,13 +160,13 @@ __xfs_dir3_data_check(
                 * The linear search is crude but this is DEBUG code.
                 */
                dep = (xfs_dir2_data_entry_t *)p;
-               XFS_WANT_CORRUPTED_RETURN(dep->namelen != 0);
-               XFS_WANT_CORRUPTED_RETURN(
+               XFS_WANT_CORRUPTED_RETURN(mp, dep->namelen != 0);
+               XFS_WANT_CORRUPTED_RETURN(mp,
                        !xfs_dir_ino_validate(mp, be64_to_cpu(dep->inumber)));
-               XFS_WANT_CORRUPTED_RETURN(
+               XFS_WANT_CORRUPTED_RETURN(mp,
                        be16_to_cpu(*ops->data_entry_tag_p(dep)) ==
                                               (char *)dep - (char *)hdr);
-               XFS_WANT_CORRUPTED_RETURN(
+               XFS_WANT_CORRUPTED_RETURN(mp,
                                ops->data_get_ftype(dep) < XFS_DIR3_FT_MAX);
                count++;
                lastfree = 0;
@@ -183,14 +183,15 @@ __xfs_dir3_data_check(
                                    be32_to_cpu(lep[i].hashval) == hash)
                                        break;
                        }
-                       XFS_WANT_CORRUPTED_RETURN(i < be32_to_cpu(btp->count));
+                       XFS_WANT_CORRUPTED_RETURN(mp,
+                                                 i < be32_to_cpu(btp->count));
                }
                p += ops->data_entsize(dep->namelen);
        }
        /*
         * Need to have seen all the entries and all the bestfree slots.
         */
-       XFS_WANT_CORRUPTED_RETURN(freeseen == 7);
+       XFS_WANT_CORRUPTED_RETURN(mp, freeseen == 7);
        if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
            hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) {
                for (i = stale = 0; i < be32_to_cpu(btp->count); i++) {
@@ -198,13 +199,13 @@ __xfs_dir3_data_check(
                            cpu_to_be32(XFS_DIR2_NULL_DATAPTR))
                                stale++;
                        if (i > 0)
-                               XFS_WANT_CORRUPTED_RETURN(
+                               XFS_WANT_CORRUPTED_RETURN(mp,
                                        be32_to_cpu(lep[i].hashval) >=
                                                be32_to_cpu(lep[i - 1].hashval));
                }
-               XFS_WANT_CORRUPTED_RETURN(count ==
+               XFS_WANT_CORRUPTED_RETURN(mp, count ==
                        be32_to_cpu(btp->count) - be32_to_cpu(btp->stale));
-               XFS_WANT_CORRUPTED_RETURN(stale == be32_to_cpu(btp->stale));
+               XFS_WANT_CORRUPTED_RETURN(mp, stale == be32_to_cpu(btp->stale));
        }
        return 0;
 }
index 8eb7189793836b74084afc154549979e77f6f581..4daaa662337b516f0794ea0d4680a12512ab6262 100644 (file)
@@ -264,68 +264,6 @@ typedef struct xfs_dsb {
        /* must be padded to 64 bit alignment */
 } xfs_dsb_t;
 
-/*
- * Sequence number values for the fields.
- */
-typedef enum {
-       XFS_SBS_MAGICNUM, XFS_SBS_BLOCKSIZE, XFS_SBS_DBLOCKS, XFS_SBS_RBLOCKS,
-       XFS_SBS_REXTENTS, XFS_SBS_UUID, XFS_SBS_LOGSTART, XFS_SBS_ROOTINO,
-       XFS_SBS_RBMINO, XFS_SBS_RSUMINO, XFS_SBS_REXTSIZE, XFS_SBS_AGBLOCKS,
-       XFS_SBS_AGCOUNT, XFS_SBS_RBMBLOCKS, XFS_SBS_LOGBLOCKS,
-       XFS_SBS_VERSIONNUM, XFS_SBS_SECTSIZE, XFS_SBS_INODESIZE,
-       XFS_SBS_INOPBLOCK, XFS_SBS_FNAME, XFS_SBS_BLOCKLOG,
-       XFS_SBS_SECTLOG, XFS_SBS_INODELOG, XFS_SBS_INOPBLOG, XFS_SBS_AGBLKLOG,
-       XFS_SBS_REXTSLOG, XFS_SBS_INPROGRESS, XFS_SBS_IMAX_PCT, XFS_SBS_ICOUNT,
-       XFS_SBS_IFREE, XFS_SBS_FDBLOCKS, XFS_SBS_FREXTENTS, XFS_SBS_UQUOTINO,
-       XFS_SBS_GQUOTINO, XFS_SBS_QFLAGS, XFS_SBS_FLAGS, XFS_SBS_SHARED_VN,
-       XFS_SBS_INOALIGNMT, XFS_SBS_UNIT, XFS_SBS_WIDTH, XFS_SBS_DIRBLKLOG,
-       XFS_SBS_LOGSECTLOG, XFS_SBS_LOGSECTSIZE, XFS_SBS_LOGSUNIT,
-       XFS_SBS_FEATURES2, XFS_SBS_BAD_FEATURES2, XFS_SBS_FEATURES_COMPAT,
-       XFS_SBS_FEATURES_RO_COMPAT, XFS_SBS_FEATURES_INCOMPAT,
-       XFS_SBS_FEATURES_LOG_INCOMPAT, XFS_SBS_CRC, XFS_SBS_PAD,
-       XFS_SBS_PQUOTINO, XFS_SBS_LSN,
-       XFS_SBS_FIELDCOUNT
-} xfs_sb_field_t;
-
-/*
- * Mask values, defined based on the xfs_sb_field_t values.
- * Only define the ones we're using.
- */
-#define        XFS_SB_MVAL(x)          (1LL << XFS_SBS_ ## x)
-#define        XFS_SB_UUID             XFS_SB_MVAL(UUID)
-#define        XFS_SB_FNAME            XFS_SB_MVAL(FNAME)
-#define        XFS_SB_ROOTINO          XFS_SB_MVAL(ROOTINO)
-#define        XFS_SB_RBMINO           XFS_SB_MVAL(RBMINO)
-#define        XFS_SB_RSUMINO          XFS_SB_MVAL(RSUMINO)
-#define        XFS_SB_VERSIONNUM       XFS_SB_MVAL(VERSIONNUM)
-#define XFS_SB_UQUOTINO                XFS_SB_MVAL(UQUOTINO)
-#define XFS_SB_GQUOTINO                XFS_SB_MVAL(GQUOTINO)
-#define XFS_SB_QFLAGS          XFS_SB_MVAL(QFLAGS)
-#define XFS_SB_SHARED_VN       XFS_SB_MVAL(SHARED_VN)
-#define XFS_SB_UNIT            XFS_SB_MVAL(UNIT)
-#define XFS_SB_WIDTH           XFS_SB_MVAL(WIDTH)
-#define XFS_SB_ICOUNT          XFS_SB_MVAL(ICOUNT)
-#define XFS_SB_IFREE           XFS_SB_MVAL(IFREE)
-#define XFS_SB_FDBLOCKS                XFS_SB_MVAL(FDBLOCKS)
-#define XFS_SB_FEATURES2       (XFS_SB_MVAL(FEATURES2) | \
-                                XFS_SB_MVAL(BAD_FEATURES2))
-#define XFS_SB_FEATURES_COMPAT XFS_SB_MVAL(FEATURES_COMPAT)
-#define XFS_SB_FEATURES_RO_COMPAT XFS_SB_MVAL(FEATURES_RO_COMPAT)
-#define XFS_SB_FEATURES_INCOMPAT XFS_SB_MVAL(FEATURES_INCOMPAT)
-#define XFS_SB_FEATURES_LOG_INCOMPAT XFS_SB_MVAL(FEATURES_LOG_INCOMPAT)
-#define XFS_SB_CRC             XFS_SB_MVAL(CRC)
-#define XFS_SB_PQUOTINO                XFS_SB_MVAL(PQUOTINO)
-#define        XFS_SB_NUM_BITS         ((int)XFS_SBS_FIELDCOUNT)
-#define        XFS_SB_ALL_BITS         ((1LL << XFS_SB_NUM_BITS) - 1)
-#define        XFS_SB_MOD_BITS         \
-       (XFS_SB_UUID | XFS_SB_ROOTINO | XFS_SB_RBMINO | XFS_SB_RSUMINO | \
-        XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO | XFS_SB_GQUOTINO | \
-        XFS_SB_QFLAGS | XFS_SB_SHARED_VN | XFS_SB_UNIT | XFS_SB_WIDTH | \
-        XFS_SB_ICOUNT | XFS_SB_IFREE | XFS_SB_FDBLOCKS | XFS_SB_FEATURES2 | \
-        XFS_SB_FEATURES_COMPAT | XFS_SB_FEATURES_RO_COMPAT | \
-        XFS_SB_FEATURES_INCOMPAT | XFS_SB_FEATURES_LOG_INCOMPAT | \
-        XFS_SB_PQUOTINO)
-
 
 /*
  * Misc. Flags - warning - these will be cleared by xfs_repair unless
index 116ef1ddb3e3ce162c24ac1240e5e50984bd5265..07349a183a110fdf57bdf9a7f1d704452de5cdb7 100644 (file)
@@ -376,7 +376,8 @@ xfs_ialloc_ag_alloc(
         */
        newlen = args.mp->m_ialloc_inos;
        if (args.mp->m_maxicount &&
-           args.mp->m_sb.sb_icount + newlen > args.mp->m_maxicount)
+           percpu_counter_read(&args.mp->m_icount) + newlen >
+                                                       args.mp->m_maxicount)
                return -ENOSPC;
        args.minlen = args.maxlen = args.mp->m_ialloc_blks;
        /*
@@ -700,7 +701,7 @@ xfs_ialloc_next_rec(
                error = xfs_inobt_get_rec(cur, rec, &i);
                if (error)
                        return error;
-               XFS_WANT_CORRUPTED_RETURN(i == 1);
+               XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, i == 1);
        }
 
        return 0;
@@ -724,7 +725,7 @@ xfs_ialloc_get_rec(
                error = xfs_inobt_get_rec(cur, rec, &i);
                if (error)
                        return error;
-               XFS_WANT_CORRUPTED_RETURN(i == 1);
+               XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, i == 1);
        }
 
        return 0;
@@ -783,12 +784,12 @@ xfs_dialloc_ag_inobt(
                error = xfs_inobt_lookup(cur, pagino, XFS_LOOKUP_LE, &i);
                if (error)
                        goto error0;
-               XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+               XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0);
 
                error = xfs_inobt_get_rec(cur, &rec, &j);
                if (error)
                        goto error0;
-               XFS_WANT_CORRUPTED_GOTO(j == 1, error0);
+               XFS_WANT_CORRUPTED_GOTO(mp, j == 1, error0);
 
                if (rec.ir_freecount > 0) {
                        /*
@@ -944,19 +945,19 @@ newino:
        error = xfs_inobt_lookup(cur, 0, XFS_LOOKUP_GE, &i);
        if (error)
                goto error0;
-       XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0);
 
        for (;;) {
                error = xfs_inobt_get_rec(cur, &rec, &i);
                if (error)
                        goto error0;
-               XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+               XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0);
                if (rec.ir_freecount > 0)
                        break;
                error = xfs_btree_increment(cur, 0, &i);
                if (error)
                        goto error0;
-               XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+               XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0);
        }
 
 alloc_inode:
@@ -1016,7 +1017,7 @@ xfs_dialloc_ag_finobt_near(
                error = xfs_inobt_get_rec(lcur, rec, &i);
                if (error)
                        return error;
-               XFS_WANT_CORRUPTED_RETURN(i == 1);
+               XFS_WANT_CORRUPTED_RETURN(lcur->bc_mp, i == 1);
 
                /*
                 * See if we've landed in the parent inode record. The finobt
@@ -1039,10 +1040,10 @@ xfs_dialloc_ag_finobt_near(
                error = xfs_inobt_get_rec(rcur, &rrec, &j);
                if (error)
                        goto error_rcur;
-               XFS_WANT_CORRUPTED_GOTO(j == 1, error_rcur);
+               XFS_WANT_CORRUPTED_GOTO(lcur->bc_mp, j == 1, error_rcur);
        }
 
-       XFS_WANT_CORRUPTED_GOTO(i == 1 || j == 1, error_rcur);
+       XFS_WANT_CORRUPTED_GOTO(lcur->bc_mp, i == 1 || j == 1, error_rcur);
        if (i == 1 && j == 1) {
                /*
                 * Both the left and right records are valid. Choose the closer
@@ -1095,7 +1096,7 @@ xfs_dialloc_ag_finobt_newino(
                        error = xfs_inobt_get_rec(cur, rec, &i);
                        if (error)
                                return error;
-                       XFS_WANT_CORRUPTED_RETURN(i == 1);
+                       XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, i == 1);
                        return 0;
                }
        }
@@ -1106,12 +1107,12 @@ xfs_dialloc_ag_finobt_newino(
        error = xfs_inobt_lookup(cur, 0, XFS_LOOKUP_GE, &i);
        if (error)
                return error;
-       XFS_WANT_CORRUPTED_RETURN(i == 1);
+       XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, i == 1);
 
        error = xfs_inobt_get_rec(cur, rec, &i);
        if (error)
                return error;
-       XFS_WANT_CORRUPTED_RETURN(i == 1);
+       XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, i == 1);
 
        return 0;
 }
@@ -1133,19 +1134,19 @@ xfs_dialloc_ag_update_inobt(
        error = xfs_inobt_lookup(cur, frec->ir_startino, XFS_LOOKUP_EQ, &i);
        if (error)
                return error;
-       XFS_WANT_CORRUPTED_RETURN(i == 1);
+       XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, i == 1);
 
        error = xfs_inobt_get_rec(cur, &rec, &i);
        if (error)
                return error;
-       XFS_WANT_CORRUPTED_RETURN(i == 1);
+       XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, i == 1);
        ASSERT((XFS_AGINO_TO_OFFSET(cur->bc_mp, rec.ir_startino) %
                                   XFS_INODES_PER_CHUNK) == 0);
 
        rec.ir_free &= ~XFS_INOBT_MASK(offset);
        rec.ir_freecount--;
 
-       XFS_WANT_CORRUPTED_RETURN((rec.ir_free == frec->ir_free) &&
+       XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, (rec.ir_free == frec->ir_free) &&
                                  (rec.ir_freecount == frec->ir_freecount));
 
        return xfs_inobt_update(cur, &rec);
@@ -1340,7 +1341,8 @@ xfs_dialloc(
         * inode.
         */
        if (mp->m_maxicount &&
-           mp->m_sb.sb_icount + mp->m_ialloc_inos > mp->m_maxicount) {
+           percpu_counter_read(&mp->m_icount) + mp->m_ialloc_inos >
+                                                       mp->m_maxicount) {
                noroom = 1;
                okalloc = 0;
        }
@@ -1475,14 +1477,14 @@ xfs_difree_inobt(
                        __func__, error);
                goto error0;
        }
-       XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0);
        error = xfs_inobt_get_rec(cur, &rec, &i);
        if (error) {
                xfs_warn(mp, "%s: xfs_inobt_get_rec() returned error %d.",
                        __func__, error);
                goto error0;
        }
-       XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
+       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error0);
        /*
         * Get the offset in the inode chunk.
         */
@@ -1592,7 +1594,7 @@ xfs_difree_finobt(
                 * freed an inode in a previously fully allocated chunk. If not,
                 * something is out of sync.
                 */
-               XFS_WANT_CORRUPTED_GOTO(ibtrec->ir_freecount == 1, error);
+               XFS_WANT_CORRUPTED_GOTO(mp, ibtrec->ir_freecount == 1, error);
 
                error = xfs_inobt_insert_rec(cur, ibtrec->ir_freecount,
                                             ibtrec->ir_free, &i);
@@ -1613,12 +1615,12 @@ xfs_difree_finobt(
        error = xfs_inobt_get_rec(cur, &rec, &i);
        if (error)
                goto error;
-       XFS_WANT_CORRUPTED_GOTO(i == 1, error);
+       XFS_WANT_CORRUPTED_GOTO(mp, i == 1, error);
 
        rec.ir_free |= XFS_INOBT_MASK(offset);
        rec.ir_freecount++;
 
-       XFS_WANT_CORRUPTED_GOTO((rec.ir_free == ibtrec->ir_free) &&
+       XFS_WANT_CORRUPTED_GOTO(mp, (rec.ir_free == ibtrec->ir_free) &&
                                (rec.ir_freecount == ibtrec->ir_freecount),
                                error);
 
index b0a5fe95a3e22d0c56f2ba482814da2a68b9a318..dc4bfc5d88fccf221609cf2ac13c80370de07221 100644 (file)
@@ -111,14 +111,6 @@ xfs_mount_validate_sb(
        bool            check_inprogress,
        bool            check_version)
 {
-
-       /*
-        * If the log device and data device have the
-        * same device number, the log is internal.
-        * Consequently, the sb_logstart should be non-zero.  If
-        * we have a zero sb_logstart in this case, we may be trying to mount
-        * a volume filesystem in a non-volume manner.
-        */
        if (sbp->sb_magicnum != XFS_SB_MAGIC) {
                xfs_warn(mp, "bad magic number");
                return -EWRONGFS;
@@ -743,17 +735,15 @@ xfs_initialize_perag_data(
                btree += pag->pagf_btreeblks;
                xfs_perag_put(pag);
        }
-       /*
-        * Overwrite incore superblock counters with just-read data
-        */
+
+       /* Overwrite incore superblock counters with just-read data */
        spin_lock(&mp->m_sb_lock);
        sbp->sb_ifree = ifree;
        sbp->sb_icount = ialloc;
        sbp->sb_fdblocks = bfree + bfreelst + btree;
        spin_unlock(&mp->m_sb_lock);
 
-       /* Fixup the per-cpu counters as well. */
-       xfs_icsb_reinit_counters(mp);
+       xfs_reinit_percpu_counters(mp);
 
        return 0;
 }
@@ -771,6 +761,10 @@ xfs_log_sb(
        struct xfs_mount        *mp = tp->t_mountp;
        struct xfs_buf          *bp = xfs_trans_getsb(tp, mp, 0);
 
+       mp->m_sb.sb_icount = percpu_counter_sum(&mp->m_icount);
+       mp->m_sb.sb_ifree = percpu_counter_sum(&mp->m_ifree);
+       mp->m_sb.sb_fdblocks = percpu_counter_sum(&mp->m_fdblocks);
+
        xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb);
        xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF);
        xfs_trans_log_buf(tp, bp, 0, sizeof(struct xfs_dsb));
index 1d8eef9cf0f509ac91f86f97ae7fe608e44bc849..a56960dd16847bccd3fea619f28aedad0f744f31 100644 (file)
@@ -1232,6 +1232,117 @@ xfs_vm_releasepage(
        return try_to_free_buffers(page);
 }
 
+/*
+ * When we map a DIO buffer, we may need to attach an ioend that describes the
+ * type of write IO we are doing. This passes to the completion function the
+ * operations it needs to perform. If the mapping is for an overwrite wholly
+ * within the EOF then we don't need an ioend and so we don't allocate one.
+ * This avoids the unnecessary overhead of allocating and freeing ioends for
+ * workloads that don't require transactions on IO completion.
+ *
+ * If we get multiple mappings in a single IO, we might be mapping different
+ * types. But because the direct IO can only have a single private pointer, we
+ * need to ensure that:
+ *
+ * a) i) the ioend spans the entire region of unwritten mappings; or
+ *    ii) the ioend spans all the mappings that cross or are beyond EOF; and
+ * b) if it contains unwritten extents, it is *permanently* marked as such
+ *
+ * We could do this by chaining ioends like buffered IO does, but we only
+ * actually get one IO completion callback from the direct IO, and that spans
+ * the entire IO regardless of how many mappings and IOs are needed to complete
+ * the DIO. There is only going to be one reference to the ioend and its life
+ * cycle is constrained by the DIO completion code. hence we don't need
+ * reference counting here.
+ */
+static void
+xfs_map_direct(
+       struct inode            *inode,
+       struct buffer_head      *bh_result,
+       struct xfs_bmbt_irec    *imap,
+       xfs_off_t               offset)
+{
+       struct xfs_ioend        *ioend;
+       xfs_off_t               size = bh_result->b_size;
+       int                     type;
+
+       if (ISUNWRITTEN(imap))
+               type = XFS_IO_UNWRITTEN;
+       else
+               type = XFS_IO_OVERWRITE;
+
+       trace_xfs_gbmap_direct(XFS_I(inode), offset, size, type, imap);
+
+       if (bh_result->b_private) {
+               ioend = bh_result->b_private;
+               ASSERT(ioend->io_size > 0);
+               ASSERT(offset >= ioend->io_offset);
+               if (offset + size > ioend->io_offset + ioend->io_size)
+                       ioend->io_size = offset - ioend->io_offset + size;
+
+               if (type == XFS_IO_UNWRITTEN && type != ioend->io_type)
+                       ioend->io_type = XFS_IO_UNWRITTEN;
+
+               trace_xfs_gbmap_direct_update(XFS_I(inode), ioend->io_offset,
+                                             ioend->io_size, ioend->io_type,
+                                             imap);
+       } else if (type == XFS_IO_UNWRITTEN ||
+                  offset + size > i_size_read(inode)) {
+               ioend = xfs_alloc_ioend(inode, type);
+               ioend->io_offset = offset;
+               ioend->io_size = size;
+
+               bh_result->b_private = ioend;
+               set_buffer_defer_completion(bh_result);
+
+               trace_xfs_gbmap_direct_new(XFS_I(inode), offset, size, type,
+                                          imap);
+       } else {
+               trace_xfs_gbmap_direct_none(XFS_I(inode), offset, size, type,
+                                           imap);
+       }
+}
+
+/*
+ * If this is O_DIRECT or the mpage code calling tell them how large the mapping
+ * is, so that we can avoid repeated get_blocks calls.
+ *
+ * If the mapping spans EOF, then we have to break the mapping up as the mapping
+ * for blocks beyond EOF must be marked new so that sub block regions can be
+ * correctly zeroed. We can't do this for mappings within EOF unless the mapping
+ * was just allocated or is unwritten, otherwise the callers would overwrite
+ * existing data with zeros. Hence we have to split the mapping into a range up
+ * to and including EOF, and a second mapping for beyond EOF.
+ */
+static void
+xfs_map_trim_size(
+       struct inode            *inode,
+       sector_t                iblock,
+       struct buffer_head      *bh_result,
+       struct xfs_bmbt_irec    *imap,
+       xfs_off_t               offset,
+       ssize_t                 size)
+{
+       xfs_off_t               mapping_size;
+
+       mapping_size = imap->br_startoff + imap->br_blockcount - iblock;
+       mapping_size <<= inode->i_blkbits;
+
+       ASSERT(mapping_size > 0);
+       if (mapping_size > size)
+               mapping_size = size;
+       if (offset < i_size_read(inode) &&
+           offset + mapping_size >= i_size_read(inode)) {
+               /* limit mapping to block that spans EOF */
+               mapping_size = roundup_64(i_size_read(inode) - offset,
+                                         1 << inode->i_blkbits);
+       }
+       if (mapping_size > LONG_MAX)
+               mapping_size = LONG_MAX;
+
+       bh_result->b_size = mapping_size;
+}
+
 STATIC int
 __xfs_get_blocks(
        struct inode            *inode,
@@ -1320,31 +1431,37 @@ __xfs_get_blocks(
 
                        xfs_iunlock(ip, lockmode);
                }
-
-               trace_xfs_get_blocks_alloc(ip, offset, size, 0, &imap);
+               trace_xfs_get_blocks_alloc(ip, offset, size,
+                               ISUNWRITTEN(&imap) ? XFS_IO_UNWRITTEN
+                                                  : XFS_IO_DELALLOC, &imap);
        } else if (nimaps) {
-               trace_xfs_get_blocks_found(ip, offset, size, 0, &imap);
+               trace_xfs_get_blocks_found(ip, offset, size,
+                               ISUNWRITTEN(&imap) ? XFS_IO_UNWRITTEN
+                                                  : XFS_IO_OVERWRITE, &imap);
                xfs_iunlock(ip, lockmode);
        } else {
                trace_xfs_get_blocks_notfound(ip, offset, size);
                goto out_unlock;
        }
 
+       /* trim mapping down to size requested */
+       if (direct || size > (1 << inode->i_blkbits))
+               xfs_map_trim_size(inode, iblock, bh_result,
+                                 &imap, offset, size);
+
+       /*
+        * For unwritten extents do not report a disk address in the buffered
+        * read case (treat as if we're reading into a hole).
+        */
        if (imap.br_startblock != HOLESTARTBLOCK &&
-           imap.br_startblock != DELAYSTARTBLOCK) {
-               /*
-                * For unwritten extents do not report a disk address on
-                * the read case (treat as if we're reading into a hole).
-                */
-               if (create || !ISUNWRITTEN(&imap))
-                       xfs_map_buffer(inode, bh_result, &imap, offset);
-               if (create && ISUNWRITTEN(&imap)) {
-                       if (direct) {
-                               bh_result->b_private = inode;
-                               set_buffer_defer_completion(bh_result);
-                       }
+           imap.br_startblock != DELAYSTARTBLOCK &&
+           (create || !ISUNWRITTEN(&imap))) {
+               xfs_map_buffer(inode, bh_result, &imap, offset);
+               if (ISUNWRITTEN(&imap))
                        set_buffer_unwritten(bh_result);
-               }
+               /* direct IO needs special help */
+               if (create && direct)
+                       xfs_map_direct(inode, bh_result, &imap, offset);
        }
 
        /*
@@ -1377,39 +1494,6 @@ __xfs_get_blocks(
                }
        }
 
-       /*
-        * If this is O_DIRECT or the mpage code calling tell them how large
-        * the mapping is, so that we can avoid repeated get_blocks calls.
-        *
-        * If the mapping spans EOF, then we have to break the mapping up as the
-        * mapping for blocks beyond EOF must be marked new so that sub block
-        * regions can be correctly zeroed. We can't do this for mappings within
-        * EOF unless the mapping was just allocated or is unwritten, otherwise
-        * the callers would overwrite existing data with zeros. Hence we have
-        * to split the mapping into a range up to and including EOF, and a
-        * second mapping for beyond EOF.
-        */
-       if (direct || size > (1 << inode->i_blkbits)) {
-               xfs_off_t               mapping_size;
-
-               mapping_size = imap.br_startoff + imap.br_blockcount - iblock;
-               mapping_size <<= inode->i_blkbits;
-
-               ASSERT(mapping_size > 0);
-               if (mapping_size > size)
-                       mapping_size = size;
-               if (offset < i_size_read(inode) &&
-                   offset + mapping_size >= i_size_read(inode)) {
-                       /* limit mapping to block that spans EOF */
-                       mapping_size = roundup_64(i_size_read(inode) - offset,
-                                                 1 << inode->i_blkbits);
-               }
-               if (mapping_size > LONG_MAX)
-                       mapping_size = LONG_MAX;
-
-               bh_result->b_size = mapping_size;
-       }
-
        return 0;
 
 out_unlock:
@@ -1440,9 +1524,11 @@ xfs_get_blocks_direct(
 /*
  * Complete a direct I/O write request.
  *
- * If the private argument is non-NULL __xfs_get_blocks signals us that we
- * need to issue a transaction to convert the range from unwritten to written
- * extents.
+ * The ioend structure is passed from __xfs_get_blocks() to tell us what to do.
+ * If no ioend exists (i.e. @private == NULL) then the write IO is an overwrite
+ * wholly within the EOF and so there is nothing for us to do. Note that in this
+ * case the completion can be called in interrupt context, whereas if we have an
+ * ioend we will always be called in task context (i.e. from a workqueue).
  */
 STATIC void
 xfs_end_io_direct_write(
@@ -1454,43 +1540,71 @@ xfs_end_io_direct_write(
        struct inode            *inode = file_inode(iocb->ki_filp);
        struct xfs_inode        *ip = XFS_I(inode);
        struct xfs_mount        *mp = ip->i_mount;
+       struct xfs_ioend        *ioend = private;
 
-       if (XFS_FORCED_SHUTDOWN(mp))
+       trace_xfs_gbmap_direct_endio(ip, offset, size,
+                                    ioend ? ioend->io_type : 0, NULL);
+
+       if (!ioend) {
+               ASSERT(offset + size <= i_size_read(inode));
                return;
+       }
+
+       if (XFS_FORCED_SHUTDOWN(mp))
+               goto out_end_io;
 
        /*
-        * While the generic direct I/O code updates the inode size, it does
-        * so only after the end_io handler is called, which means our
-        * end_io handler thinks the on-disk size is outside the in-core
-        * size.  To prevent this just update it a little bit earlier here.
+        * dio completion end_io functions are only called on writes if more
+        * than 0 bytes was written.
         */
+       ASSERT(size > 0);
+
+       /*
+        * The ioend only maps whole blocks, while the IO may be sector aligned.
+        * Hence the ioend offset/size may not match the IO offset/size exactly.
+        * Because we don't map overwrites within EOF into the ioend, the offset
+        * may not match, but only if the endio spans EOF.  Either way, write
+        * the IO sizes into the ioend so that completion processing does the
+        * right thing.
+        */
+       ASSERT(offset + size <= ioend->io_offset + ioend->io_size);
+       ioend->io_size = size;
+       ioend->io_offset = offset;
+
+       /*
+        * The ioend tells us whether we are doing unwritten extent conversion
+        * or an append transaction that updates the on-disk file size. These
+        * cases are the only cases where we should *potentially* be needing
+        * to update the VFS inode size.
+        *
+        * We need to update the in-core inode size here so that we don't end up
+        * with the on-disk inode size being outside the in-core inode size. We
+        * have no other method of updating EOF for AIO, so always do it here
+        * if necessary.
+        *
+        * We need to lock the test/set EOF update as we can be racing with
+        * other IO completions here to update the EOF. Failing to serialise
+        * here can result in EOF moving backwards and Bad Things Happen when
+        * that occurs.
+        */
+       spin_lock(&ip->i_flags_lock);
        if (offset + size > i_size_read(inode))
                i_size_write(inode, offset + size);
+       spin_unlock(&ip->i_flags_lock);
 
        /*
-        * For direct I/O we do not know if we need to allocate blocks or not,
-        * so we can't preallocate an append transaction, as that results in
-        * nested reservations and log space deadlocks. Hence allocate the
-        * transaction here. While this is sub-optimal and can block IO
-        * completion for some time, we're stuck with doing it this way until
-        * we can pass the ioend to the direct IO allocation callbacks and
-        * avoid nesting that way.
+        * If we are doing an append IO that needs to update the EOF on disk,
+        * do the transaction reserve now so we can use common end io
+        * processing. Stashing the error (if there is one) in the ioend will
+        * result in the ioend processing passing on the error if it is
+        * possible as we can't return it from here.
         */
-       if (private && size > 0) {
-               xfs_iomap_write_unwritten(ip, offset, size);
-       } else if (offset + size > ip->i_d.di_size) {
-               struct xfs_trans        *tp;
-               int                     error;
-
-               tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS);
-               error = xfs_trans_reserve(tp, &M_RES(mp)->tr_fsyncts, 0, 0);
-               if (error) {
-                       xfs_trans_cancel(tp, 0);
-                       return;
-               }
+       if (ioend->io_type == XFS_IO_OVERWRITE)
+               ioend->io_error = xfs_setfilesize_trans_alloc(ioend);
 
-               xfs_setfilesize(ip, tp, offset, size);
-       }
+out_end_io:
+       xfs_end_io(&ioend->io_work);
+       return;
 }
 
 STATIC ssize_t
index 83af4c14963579b3a8377e43c54e4cd0825ca236..f9c1c64782d39ec36fabf800653772f8c5b24280 100644 (file)
@@ -132,9 +132,10 @@ xfs_attr3_leaf_inactive(
        int                     size;
        int                     tmp;
        int                     i;
+       struct xfs_mount        *mp = bp->b_target->bt_mount;
 
        leaf = bp->b_addr;
-       xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf);
+       xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr, leaf);
 
        /*
         * Count the number of "remote" value extents.
index a43d370d2c5887c689844a66c787785fef608808..65fb37a18e92316616967bc7465c4e36e3fa116f 100644 (file)
@@ -225,6 +225,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
        int error, i;
        struct xfs_buf *bp;
        struct xfs_inode        *dp = context->dp;
+       struct xfs_mount        *mp = dp->i_mount;
 
        trace_xfs_attr_node_list(context);
 
@@ -256,7 +257,8 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
                        case XFS_ATTR_LEAF_MAGIC:
                        case XFS_ATTR3_LEAF_MAGIC:
                                leaf = bp->b_addr;
-                               xfs_attr3_leaf_hdr_from_disk(&leafhdr, leaf);
+                               xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo,
+                                                            &leafhdr, leaf);
                                entries = xfs_attr3_leaf_entryp(leaf);
                                if (cursor->hashval > be32_to_cpu(
                                                entries[leafhdr.count - 1].hashval)) {
@@ -340,7 +342,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
                        xfs_trans_brelse(NULL, bp);
                        return error;
                }
-               xfs_attr3_leaf_hdr_from_disk(&leafhdr, leaf);
+               xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, leaf);
                if (context->seen_enough || leafhdr.forw == 0)
                        break;
                cursor->blkno = leafhdr.forw;
@@ -368,11 +370,12 @@ xfs_attr3_leaf_list_int(
        struct xfs_attr_leaf_entry      *entry;
        int                             retval;
        int                             i;
+       struct xfs_mount                *mp = context->dp->i_mount;
 
        trace_xfs_attr_list_leaf(context);
 
        leaf = bp->b_addr;
-       xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf);
+       xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr, leaf);
        entries = xfs_attr3_leaf_entryp(leaf);
 
        cursor = context->cursor;
index 22a5dcb70b327293c1278a6fd44685e0b2ecc502..a52bbd3abc7df3ac7fa07a12b5dc9ec336d9ab49 100644 (file)
@@ -1376,22 +1376,19 @@ out:
 }
 
 /*
- * xfs_collapse_file_space()
- *     This routine frees disk space and shift extent for the given file.
- *     The first thing we do is to free data blocks in the specified range
- *     by calling xfs_free_file_space(). It would also sync dirty data
- *     and invalidate page cache over the region on which collapse range
- *     is working. And Shift extent records to the left to cover a hole.
- * RETURNS:
- *     0 on success
- *     errno on error
- *
+ * @next_fsb will keep track of the extent currently undergoing shift.
+ * @stop_fsb will keep track of the extent at which we have to stop.
+ * If we are shifting left, we will start with block (offset + len) and
+ * shift each extent till last extent.
+ * If we are shifting right, we will start with last extent inside file space
+ * and continue until we reach the block corresponding to offset.
  */
-int
-xfs_collapse_file_space(
-       struct xfs_inode        *ip,
-       xfs_off_t               offset,
-       xfs_off_t               len)
+static int
+xfs_shift_file_space(
+       struct xfs_inode        *ip,
+       xfs_off_t               offset,
+       xfs_off_t               len,
+       enum shift_direction    direction)
 {
        int                     done = 0;
        struct xfs_mount        *mp = ip->i_mount;
@@ -1400,21 +1397,26 @@ xfs_collapse_file_space(
        struct xfs_bmap_free    free_list;
        xfs_fsblock_t           first_block;
        int                     committed;
-       xfs_fileoff_t           start_fsb;
+       xfs_fileoff_t           stop_fsb;
        xfs_fileoff_t           next_fsb;
        xfs_fileoff_t           shift_fsb;
 
-       ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
+       ASSERT(direction == SHIFT_LEFT || direction == SHIFT_RIGHT);
 
-       trace_xfs_collapse_file_space(ip);
+       if (direction == SHIFT_LEFT) {
+               next_fsb = XFS_B_TO_FSB(mp, offset + len);
+               stop_fsb = XFS_B_TO_FSB(mp, VFS_I(ip)->i_size);
+       } else {
+               /*
+                * If right shift, delegate the work of initialization of
+                * next_fsb to xfs_bmap_shift_extent as it has ilock held.
+                */
+               next_fsb = NULLFSBLOCK;
+               stop_fsb = XFS_B_TO_FSB(mp, offset);
+       }
 
-       next_fsb = XFS_B_TO_FSB(mp, offset + len);
        shift_fsb = XFS_B_TO_FSB(mp, len);
 
-       error = xfs_free_file_space(ip, offset, len);
-       if (error)
-               return error;
-
        /*
         * Trim eofblocks to avoid shifting uninitialized post-eof preallocation
         * into the accessible region of the file.
@@ -1427,20 +1429,28 @@ xfs_collapse_file_space(
 
        /*
         * Writeback and invalidate cache for the remainder of the file as we're
-        * about to shift down every extent from the collapse range to EOF. The
-        * free of the collapse range above might have already done some of
-        * this, but we shouldn't rely on it to do anything outside of the range
-        * that was freed.
+        * about to shift down every extent from offset to EOF.
         */
        error = filemap_write_and_wait_range(VFS_I(ip)->i_mapping,
-                                            offset + len, -1);
+                                            offset, -1);
        if (error)
                return error;
        error = invalidate_inode_pages2_range(VFS_I(ip)->i_mapping,
-                                       (offset + len) >> PAGE_CACHE_SHIFT, -1);
+                                       offset >> PAGE_CACHE_SHIFT, -1);
        if (error)
                return error;
 
+       /*
+        * The extent shiting code works on extent granularity. So, if
+        * stop_fsb is not the starting block of extent, we need to split
+        * the extent at stop_fsb.
+        */
+       if (direction == SHIFT_RIGHT) {
+               error = xfs_bmap_split_extent(ip, stop_fsb);
+               if (error)
+                       return error;
+       }
+
        while (!error && !done) {
                tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
                /*
@@ -1464,7 +1474,7 @@ xfs_collapse_file_space(
                if (error)
                        goto out;
 
-               xfs_trans_ijoin(tp, ip, 0);
+               xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
 
                xfs_bmap_init(&free_list, &first_block);
 
@@ -1472,10 +1482,9 @@ xfs_collapse_file_space(
                 * We are using the write transaction in which max 2 bmbt
                 * updates are allowed
                 */
-               start_fsb = next_fsb;
-               error = xfs_bmap_shift_extents(tp, ip, start_fsb, shift_fsb,
-                               &done, &next_fsb, &first_block, &free_list,
-                               XFS_BMAP_MAX_SHIFT_EXTENTS);
+               error = xfs_bmap_shift_extents(tp, ip, &next_fsb, shift_fsb,
+                               &done, stop_fsb, &first_block, &free_list,
+                               direction, XFS_BMAP_MAX_SHIFT_EXTENTS);
                if (error)
                        goto out;
 
@@ -1484,17 +1493,69 @@ xfs_collapse_file_space(
                        goto out;
 
                error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
-               xfs_iunlock(ip, XFS_ILOCK_EXCL);
        }
 
        return error;
 
 out:
        xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
-       xfs_iunlock(ip, XFS_ILOCK_EXCL);
        return error;
 }
 
+/*
+ * xfs_collapse_file_space()
+ *     This routine frees disk space and shift extent for the given file.
+ *     The first thing we do is to free data blocks in the specified range
+ *     by calling xfs_free_file_space(). It would also sync dirty data
+ *     and invalidate page cache over the region on which collapse range
+ *     is working. And Shift extent records to the left to cover a hole.
+ * RETURNS:
+ *     0 on success
+ *     errno on error
+ *
+ */
+int
+xfs_collapse_file_space(
+       struct xfs_inode        *ip,
+       xfs_off_t               offset,
+       xfs_off_t               len)
+{
+       int error;
+
+       ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
+       trace_xfs_collapse_file_space(ip);
+
+       error = xfs_free_file_space(ip, offset, len);
+       if (error)
+               return error;
+
+       return xfs_shift_file_space(ip, offset, len, SHIFT_LEFT);
+}
+
+/*
+ * xfs_insert_file_space()
+ *     This routine create hole space by shifting extents for the given file.
+ *     The first thing we do is to sync dirty data and invalidate page cache
+ *     over the region on which insert range is working. And split an extent
+ *     to two extents at given offset by calling xfs_bmap_split_extent.
+ *     And shift all extent records which are laying between [offset,
+ *     last allocated extent] to the right to reserve hole range.
+ * RETURNS:
+ *     0 on success
+ *     errno on error
+ */
+int
+xfs_insert_file_space(
+       struct xfs_inode        *ip,
+       loff_t                  offset,
+       loff_t                  len)
+{
+       ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
+       trace_xfs_insert_file_space(ip);
+
+       return xfs_shift_file_space(ip, offset, len, SHIFT_RIGHT);
+}
+
 /*
  * We need to check that the format of the data fork in the temporary inode is
  * valid for the target inode before doing the swap. This is not a problem with
@@ -1599,13 +1660,6 @@ xfs_swap_extent_flush(
        /* Verify O_DIRECT for ftmp */
        if (VFS_I(ip)->i_mapping->nrpages)
                return -EINVAL;
-
-       /*
-        * Don't try to swap extents on mmap()d files because we can't lock
-        * out races against page faults safely.
-        */
-       if (mapping_mapped(VFS_I(ip)->i_mapping))
-               return -EBUSY;
        return 0;
 }
 
@@ -1633,13 +1687,14 @@ xfs_swap_extents(
        }
 
        /*
-        * Lock up the inodes against other IO and truncate to begin with.
-        * Then we can ensure the inodes are flushed and have no page cache
-        * safely. Once we have done this we can take the ilocks and do the rest
-        * of the checks.
+        * Lock the inodes against other IO, page faults and truncate to
+        * begin with.  Then we can ensure the inodes are flushed and have no
+        * page cache safely. Once we have done this we can take the ilocks and
+        * do the rest of the checks.
         */
-       lock_flags = XFS_IOLOCK_EXCL;
+       lock_flags = XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL;
        xfs_lock_two_inodes(ip, tip, XFS_IOLOCK_EXCL);
+       xfs_lock_two_inodes(ip, tip, XFS_MMAPLOCK_EXCL);
 
        /* Verify that both files have the same format */
        if ((ip->i_d.di_mode & S_IFMT) != (tip->i_d.di_mode & S_IFMT)) {
@@ -1666,8 +1721,16 @@ xfs_swap_extents(
                xfs_trans_cancel(tp, 0);
                goto out_unlock;
        }
+
+       /*
+        * Lock and join the inodes to the tansaction so that transaction commit
+        * or cancel will unlock the inodes from this point onwards.
+        */
        xfs_lock_two_inodes(ip, tip, XFS_ILOCK_EXCL);
        lock_flags |= XFS_ILOCK_EXCL;
+       xfs_trans_ijoin(tp, ip, lock_flags);
+       xfs_trans_ijoin(tp, tip, lock_flags);
+
 
        /* Verify all data are being swapped */
        if (sxp->sx_offset != 0 ||
@@ -1720,9 +1783,6 @@ xfs_swap_extents(
                        goto out_trans_cancel;
        }
 
-       xfs_trans_ijoin(tp, ip, lock_flags);
-       xfs_trans_ijoin(tp, tip, lock_flags);
-
        /*
         * Before we've swapped the forks, lets set the owners of the forks
         * appropriately. We have to do this as we are demand paging the btree
@@ -1856,5 +1916,5 @@ out_unlock:
 
 out_trans_cancel:
        xfs_trans_cancel(tp, 0);
-       goto out_unlock;
+       goto out;
 }
index 736429a72a12843d0a7ca6c5626059024566c870..af97d9a1dfb449230139891d53ff89a175fabbfc 100644 (file)
@@ -63,6 +63,8 @@ int   xfs_zero_file_space(struct xfs_inode *ip, xfs_off_t offset,
                            xfs_off_t len);
 int    xfs_collapse_file_space(struct xfs_inode *, xfs_off_t offset,
                                xfs_off_t len);
+int    xfs_insert_file_space(struct xfs_inode *, xfs_off_t offset,
+                               xfs_off_t len);
 
 /* EOF block manipulation functions */
 bool   xfs_can_free_eofblocks(struct xfs_inode *ip, bool force);
index 507d96a57ac7c6eef3853993786d29026f3657b9..092d652bc03df3153b6bcf427ed972ffe480fd86 100644 (file)
@@ -537,9 +537,9 @@ xfs_buf_item_push(
 
        /* has a previous flush failed due to IO errors? */
        if ((bp->b_flags & XBF_WRITE_FAIL) &&
-           ___ratelimit(&xfs_buf_write_fail_rl_state, "XFS:")) {
+           ___ratelimit(&xfs_buf_write_fail_rl_state, "XFS: Failing async write")) {
                xfs_warn(bp->b_target->bt_mount,
-"Detected failing async write on buffer block 0x%llx. Retrying async write.",
+"Failing async write on buffer block 0x%llx. Retrying async write.",
                         (long long)bp->b_bn);
        }
 
index 799e5a2d334d993a6f546f5e7b60895df1cb1a86..e85a9519a5aee71c23b7eeb44f282675d427c4b4 100644 (file)
@@ -84,7 +84,7 @@ xfs_trim_extents(
                error = xfs_alloc_get_rec(cur, &fbno, &flen, &i);
                if (error)
                        goto out_del_cursor;
-               XFS_WANT_CORRUPTED_GOTO(i == 1, out_del_cursor);
+               XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_del_cursor);
                ASSERT(flen <= be32_to_cpu(XFS_BUF_TO_AGF(agbp)->agf_longest));
 
                /*
index 3ee186ac10938855965a5907c93de487e83851bf..338e50bbfd1ec8bc8345fbbd84cdc56b82d5f43a 100644 (file)
@@ -131,7 +131,7 @@ xfs_error_report(
 {
        if (level <= xfs_error_level) {
                xfs_alert_tag(mp, XFS_PTAG_ERROR_REPORT,
-               "Internal error %s at line %d of file %s.  Caller %pF",
+               "Internal error %s at line %d of file %s.  Caller %pS",
                            tag, linenum, filename, ra);
 
                xfs_stack_trace();
index 279a76e52791fcee2bb8d40b4724231dc35d92bb..c0394ed126fcc891df140fb6536b94ebdb520d01 100644 (file)
@@ -40,25 +40,25 @@ extern void xfs_verifier_error(struct xfs_buf *bp);
 /*
  * Macros to set EFSCORRUPTED & return/branch.
  */
-#define        XFS_WANT_CORRUPTED_GOTO(x,l)    \
+#define        XFS_WANT_CORRUPTED_GOTO(mp, x, l)       \
        { \
                int fs_is_ok = (x); \
                ASSERT(fs_is_ok); \
                if (unlikely(!fs_is_ok)) { \
                        XFS_ERROR_REPORT("XFS_WANT_CORRUPTED_GOTO", \
-                                        XFS_ERRLEVEL_LOW, NULL); \
+                                        XFS_ERRLEVEL_LOW, mp); \
                        error = -EFSCORRUPTED; \
                        goto l; \
                } \
        }
 
-#define        XFS_WANT_CORRUPTED_RETURN(x)    \
+#define        XFS_WANT_CORRUPTED_RETURN(mp, x)        \
        { \
                int fs_is_ok = (x); \
                ASSERT(fs_is_ok); \
                if (unlikely(!fs_is_ok)) { \
                        XFS_ERROR_REPORT("XFS_WANT_CORRUPTED_RETURN", \
-                                        XFS_ERRLEVEL_LOW, NULL); \
+                                        XFS_ERRLEVEL_LOW, mp); \
                        return -EFSCORRUPTED; \
                } \
        }
index b97359ba2648f12fca1bfa98e25be6efc719c8e3..652cd3c5b58c1cac1562239c9c644a19dbe588b7 100644 (file)
@@ -215,7 +215,7 @@ xfs_fs_get_parent(
        int                     error;
        struct xfs_inode        *cip;
 
-       error = xfs_lookup(XFS_I(child->d_inode), &xfs_name_dotdot, &cip, NULL);
+       error = xfs_lookup(XFS_I(d_inode(child)), &xfs_name_dotdot, &cip, NULL);
        if (unlikely(error))
                return ERR_PTR(error);
 
index 1f12ad0a8585b3d0f0788cfe5b88b6ab662a1547..8121e75352ee9bddd4726ca685d6d3e855256bdd 100644 (file)
@@ -559,7 +559,7 @@ restart:
        if (error <= 0)
                return error;
 
-       error = xfs_break_layouts(inode, iolock);
+       error = xfs_break_layouts(inode, iolock, true);
        if (error)
                return error;
 
@@ -569,21 +569,42 @@ restart:
         * write.  If zeroing is needed and we are currently holding the
         * iolock shared, we need to update it to exclusive which implies
         * having to redo all checks before.
+        *
+        * We need to serialise against EOF updates that occur in IO
+        * completions here. We want to make sure that nobody is changing the
+        * size while we do this check until we have placed an IO barrier (i.e.
+        * hold the XFS_IOLOCK_EXCL) that prevents new IO from being dispatched.
+        * The spinlock effectively forms a memory barrier once we have the
+        * XFS_IOLOCK_EXCL so we are guaranteed to see the latest EOF value
+        * and hence be able to correctly determine if we need to run zeroing.
         */
+       spin_lock(&ip->i_flags_lock);
        if (iocb->ki_pos > i_size_read(inode)) {
                bool    zero = false;
 
+               spin_unlock(&ip->i_flags_lock);
                if (*iolock == XFS_IOLOCK_SHARED) {
                        xfs_rw_iunlock(ip, *iolock);
                        *iolock = XFS_IOLOCK_EXCL;
                        xfs_rw_ilock(ip, *iolock);
                        iov_iter_reexpand(from, count);
+
+                       /*
+                        * We now have an IO submission barrier in place, but
+                        * AIO can do EOF updates during IO completion and hence
+                        * we now need to wait for all of them to drain. Non-AIO
+                        * DIO will have drained before we are given the
+                        * XFS_IOLOCK_EXCL, and so for most cases this wait is a
+                        * no-op.
+                        */
+                       inode_dio_wait(inode);
                        goto restart;
                }
                error = xfs_zero_eof(ip, iocb->ki_pos, i_size_read(inode), &zero);
                if (error)
                        return error;
-       }
+       } else
+               spin_unlock(&ip->i_flags_lock);
 
        /*
         * Updating the timestamps will grab the ilock again from
@@ -645,6 +666,8 @@ xfs_file_dio_aio_write(
        int                     iolock;
        size_t                  count = iov_iter_count(from);
        loff_t                  pos = iocb->ki_pos;
+       loff_t                  end;
+       struct iov_iter         data;
        struct xfs_buftarg      *target = XFS_IS_REALTIME_INODE(ip) ?
                                        mp->m_rtdev_targp : mp->m_ddev_targp;
 
@@ -685,10 +708,11 @@ xfs_file_dio_aio_write(
                goto out;
        count = iov_iter_count(from);
        pos = iocb->ki_pos;
+       end = pos + count - 1;
 
        if (mapping->nrpages) {
                ret = filemap_write_and_wait_range(VFS_I(ip)->i_mapping,
-                                                   pos, pos + count - 1);
+                                                  pos, end);
                if (ret)
                        goto out;
                /*
@@ -698,7 +722,7 @@ xfs_file_dio_aio_write(
                 */
                ret = invalidate_inode_pages2_range(VFS_I(ip)->i_mapping,
                                        pos >> PAGE_CACHE_SHIFT,
-                                       (pos + count - 1) >> PAGE_CACHE_SHIFT);
+                                       end >> PAGE_CACHE_SHIFT);
                WARN_ON_ONCE(ret);
                ret = 0;
        }
@@ -715,8 +739,22 @@ xfs_file_dio_aio_write(
        }
 
        trace_xfs_file_direct_write(ip, count, iocb->ki_pos, 0);
-       ret = generic_file_direct_write(iocb, from, pos);
 
+       data = *from;
+       ret = mapping->a_ops->direct_IO(iocb, &data, pos);
+
+       /* see generic_file_direct_write() for why this is necessary */
+       if (mapping->nrpages) {
+               invalidate_inode_pages2_range(mapping,
+                                             pos >> PAGE_CACHE_SHIFT,
+                                             end >> PAGE_CACHE_SHIFT);
+       }
+
+       if (ret > 0) {
+               pos += ret;
+               iov_iter_advance(from, ret);
+               iocb->ki_pos = pos;
+       }
 out:
        xfs_rw_iunlock(ip, iolock);
 
@@ -822,6 +860,11 @@ xfs_file_write_iter(
        return ret;
 }
 
+#define        XFS_FALLOC_FL_SUPPORTED                                         \
+               (FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE |           \
+                FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_ZERO_RANGE |      \
+                FALLOC_FL_INSERT_RANGE)
+
 STATIC long
 xfs_file_fallocate(
        struct file             *file,
@@ -835,18 +878,21 @@ xfs_file_fallocate(
        enum xfs_prealloc_flags flags = 0;
        uint                    iolock = XFS_IOLOCK_EXCL;
        loff_t                  new_size = 0;
+       bool                    do_file_insert = 0;
 
        if (!S_ISREG(inode->i_mode))
                return -EINVAL;
-       if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE |
-                    FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_ZERO_RANGE))
+       if (mode & ~XFS_FALLOC_FL_SUPPORTED)
                return -EOPNOTSUPP;
 
        xfs_ilock(ip, iolock);
-       error = xfs_break_layouts(inode, &iolock);
+       error = xfs_break_layouts(inode, &iolock, false);
        if (error)
                goto out_unlock;
 
+       xfs_ilock(ip, XFS_MMAPLOCK_EXCL);
+       iolock |= XFS_MMAPLOCK_EXCL;
+
        if (mode & FALLOC_FL_PUNCH_HOLE) {
                error = xfs_free_file_space(ip, offset, len);
                if (error)
@@ -873,6 +919,27 @@ xfs_file_fallocate(
                error = xfs_collapse_file_space(ip, offset, len);
                if (error)
                        goto out_unlock;
+       } else if (mode & FALLOC_FL_INSERT_RANGE) {
+               unsigned blksize_mask = (1 << inode->i_blkbits) - 1;
+
+               new_size = i_size_read(inode) + len;
+               if (offset & blksize_mask || len & blksize_mask) {
+                       error = -EINVAL;
+                       goto out_unlock;
+               }
+
+               /* check the new inode size does not wrap through zero */
+               if (new_size > inode->i_sb->s_maxbytes) {
+                       error = -EFBIG;
+                       goto out_unlock;
+               }
+
+               /* Offset should be less than i_size */
+               if (offset >= i_size_read(inode)) {
+                       error = -EINVAL;
+                       goto out_unlock;
+               }
+               do_file_insert = 1;
        } else {
                flags |= XFS_PREALLOC_SET;
 
@@ -907,8 +974,19 @@ xfs_file_fallocate(
                iattr.ia_valid = ATTR_SIZE;
                iattr.ia_size = new_size;
                error = xfs_setattr_size(ip, &iattr);
+               if (error)
+                       goto out_unlock;
        }
 
+       /*
+        * Perform hole insertion now that the file size has been
+        * updated so that if we crash during the operation we don't
+        * leave shifted extents past EOF and hence losing access to
+        * the data that is contained within them.
+        */
+       if (do_file_insert)
+               error = xfs_insert_file_space(ip, offset, len);
+
 out_unlock:
        xfs_iunlock(ip, iolock);
        return error;
@@ -996,20 +1074,6 @@ xfs_file_mmap(
        return 0;
 }
 
-/*
- * mmap()d file has taken write protection fault and is being made
- * writable. We can set the page state up correctly for a writable
- * page, which means we can do correct delalloc accounting (ENOSPC
- * checking!) and unwritten extent mapping.
- */
-STATIC int
-xfs_vm_page_mkwrite(
-       struct vm_area_struct   *vma,
-       struct vm_fault         *vmf)
-{
-       return block_page_mkwrite(vma, vmf, xfs_get_blocks);
-}
-
 /*
  * This type is designed to indicate the type of offset we would like
  * to search from page cache for xfs_seek_hole_data().
@@ -1385,6 +1449,55 @@ xfs_file_llseek(
        }
 }
 
+/*
+ * Locking for serialisation of IO during page faults. This results in a lock
+ * ordering of:
+ *
+ * mmap_sem (MM)
+ *   i_mmap_lock (XFS - truncate serialisation)
+ *     page_lock (MM)
+ *       i_lock (XFS - extent map serialisation)
+ */
+STATIC int
+xfs_filemap_fault(
+       struct vm_area_struct   *vma,
+       struct vm_fault         *vmf)
+{
+       struct xfs_inode        *ip = XFS_I(vma->vm_file->f_mapping->host);
+       int                     error;
+
+       trace_xfs_filemap_fault(ip);
+
+       xfs_ilock(ip, XFS_MMAPLOCK_SHARED);
+       error = filemap_fault(vma, vmf);
+       xfs_iunlock(ip, XFS_MMAPLOCK_SHARED);
+
+       return error;
+}
+
+/*
+ * mmap()d file has taken write protection fault and is being made writable. We
+ * can set the page state up correctly for a writable page, which means we can
+ * do correct delalloc accounting (ENOSPC checking!) and unwritten extent
+ * mapping.
+ */
+STATIC int
+xfs_filemap_page_mkwrite(
+       struct vm_area_struct   *vma,
+       struct vm_fault         *vmf)
+{
+       struct xfs_inode        *ip = XFS_I(vma->vm_file->f_mapping->host);
+       int                     error;
+
+       trace_xfs_filemap_page_mkwrite(ip);
+
+       xfs_ilock(ip, XFS_MMAPLOCK_SHARED);
+       error = block_page_mkwrite(vma, vmf, xfs_get_blocks);
+       xfs_iunlock(ip, XFS_MMAPLOCK_SHARED);
+
+       return error;
+}
+
 const struct file_operations xfs_file_operations = {
        .llseek         = xfs_file_llseek,
        .read_iter      = xfs_file_read_iter,
@@ -1415,7 +1528,7 @@ const struct file_operations xfs_dir_file_operations = {
 };
 
 static const struct vm_operations_struct xfs_file_vm_ops = {
-       .fault          = filemap_fault,
+       .fault          = xfs_filemap_fault,
        .map_pages      = filemap_map_pages,
-       .page_mkwrite   = xfs_vm_page_mkwrite,
+       .page_mkwrite   = xfs_filemap_page_mkwrite,
 };
index a2e86e8a0feac8fabf316fb8a790fc805153469a..da82f1cb4b9bde824979bad9cca0b72c748a49d9 100644 (file)
@@ -294,7 +294,7 @@ xfs_filestream_get_parent(
        if (!parent)
                goto out_dput;
 
-       dir = igrab(parent->d_inode);
+       dir = igrab(d_inode(parent));
        dput(parent);
 
 out_dput:
@@ -322,7 +322,7 @@ xfs_filestream_lookup_ag(
 
        pip = xfs_filestream_get_parent(ip);
        if (!pip)
-               goto out;
+               return NULLAGNUMBER;
 
        mru = xfs_mru_cache_lookup(mp->m_filestream, pip->i_ino);
        if (mru) {
index 74efe5b760dcc2907280db8e374afe6f5914d7b3..cb7e8a29dfb6e9e8b2b0f1044cc67a9dca5e1603 100644 (file)
@@ -637,12 +637,13 @@ xfs_fs_counts(
        xfs_mount_t             *mp,
        xfs_fsop_counts_t       *cnt)
 {
-       xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
+       cnt->allocino = percpu_counter_read_positive(&mp->m_icount);
+       cnt->freeino = percpu_counter_read_positive(&mp->m_ifree);
+       cnt->freedata = percpu_counter_read_positive(&mp->m_fdblocks) -
+                                                       XFS_ALLOC_SET_ASIDE(mp);
+
        spin_lock(&mp->m_sb_lock);
-       cnt->freedata = mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
        cnt->freertx = mp->m_sb.sb_frextents;
-       cnt->freeino = mp->m_sb.sb_ifree;
-       cnt->allocino = mp->m_sb.sb_icount;
        spin_unlock(&mp->m_sb_lock);
        return 0;
 }
@@ -692,14 +693,9 @@ xfs_reserve_blocks(
         * what to do. This means that the amount of free space can
         * change while we do this, so we need to retry if we end up
         * trying to reserve more space than is available.
-        *
-        * We also use the xfs_mod_incore_sb() interface so that we
-        * don't have to care about whether per cpu counter are
-        * enabled, disabled or even compiled in....
         */
 retry:
        spin_lock(&mp->m_sb_lock);
-       xfs_icsb_sync_counters_locked(mp, 0);
 
        /*
         * If our previous reservation was larger than the current value,
@@ -716,7 +712,8 @@ retry:
        } else {
                __int64_t       free;
 
-               free =  mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
+               free = percpu_counter_sum(&mp->m_fdblocks) -
+                                                       XFS_ALLOC_SET_ASIDE(mp);
                if (!free)
                        goto out; /* ENOSPC and fdblks_delta = 0 */
 
@@ -755,8 +752,7 @@ out:
                 * the extra reserve blocks from the reserve.....
                 */
                int error;
-               error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
-                                                fdblks_delta, 0);
+               error = xfs_mod_fdblocks(mp, fdblks_delta, 0);
                if (error == -ENOSPC)
                        goto retry;
        }
index 9771b7ef62ed516bf12a7b3db58247ec12b78071..76a9f27832827db72fc58465389a619648a90b56 100644 (file)
@@ -439,11 +439,11 @@ again:
        *ipp = ip;
 
        /*
-        * If we have a real type for an on-disk inode, we can set ops(&unlock)
+        * If we have a real type for an on-disk inode, we can setup the inode
         * now.  If it's a new inode being created, xfs_ialloc will handle it.
         */
        if (xfs_iflags_test(ip, XFS_INEW) && ip->i_d.di_mode != 0)
-               xfs_setup_inode(ip);
+               xfs_setup_existing_inode(ip);
        return 0;
 
 out_error_or_again:
index 6163767aa8562f6d611a1442ed4f299aa85bceea..d6ebc85192b7b3f4fd21e3cbc25ccb5f54501319 100644 (file)
@@ -117,24 +117,34 @@ xfs_ilock_attr_map_shared(
 }
 
 /*
- * The xfs inode contains 2 locks: a multi-reader lock called the
- * i_iolock and a multi-reader lock called the i_lock.  This routine
- * allows either or both of the locks to be obtained.
+ * The xfs inode contains 3 multi-reader locks: the i_iolock the i_mmap_lock and
+ * the i_lock.  This routine allows various combinations of the locks to be
+ * obtained.
  *
- * The 2 locks should always be ordered so that the IO lock is
- * obtained first in order to prevent deadlock.
+ * The 3 locks should always be ordered so that the IO lock is obtained first,
+ * the mmap lock second and the ilock last in order to prevent deadlock.
  *
- * ip -- the inode being locked
- * lock_flags -- this parameter indicates the inode's locks
- *       to be locked.  It can be:
- *             XFS_IOLOCK_SHARED,
- *             XFS_IOLOCK_EXCL,
- *             XFS_ILOCK_SHARED,
- *             XFS_ILOCK_EXCL,
- *             XFS_IOLOCK_SHARED | XFS_ILOCK_SHARED,
- *             XFS_IOLOCK_SHARED | XFS_ILOCK_EXCL,
- *             XFS_IOLOCK_EXCL | XFS_ILOCK_SHARED,
- *             XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL
+ * Basic locking order:
+ *
+ * i_iolock -> i_mmap_lock -> page_lock -> i_ilock
+ *
+ * mmap_sem locking order:
+ *
+ * i_iolock -> page lock -> mmap_sem
+ * mmap_sem -> i_mmap_lock -> page_lock
+ *
+ * The difference in mmap_sem locking order mean that we cannot hold the
+ * i_mmap_lock over syscall based read(2)/write(2) based IO. These IO paths can
+ * fault in pages during copy in/out (for buffered IO) or require the mmap_sem
+ * in get_user_pages() to map the user pages into the kernel address space for
+ * direct IO. Similarly the i_iolock cannot be taken inside a page fault because
+ * page faults already hold the mmap_sem.
+ *
+ * Hence to serialise fully against both syscall and mmap based IO, we need to
+ * take both the i_iolock and the i_mmap_lock. These locks should *only* be both
+ * taken in places where we need to invalidate the page cache in a race
+ * free manner (e.g. truncate, hole punch and other extent manipulation
+ * functions).
  */
 void
 xfs_ilock(
@@ -150,6 +160,8 @@ xfs_ilock(
         */
        ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) !=
               (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL));
+       ASSERT((lock_flags & (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL)) !=
+              (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL));
        ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) !=
               (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
        ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_DEP_MASK)) == 0);
@@ -159,6 +171,11 @@ xfs_ilock(
        else if (lock_flags & XFS_IOLOCK_SHARED)
                mraccess_nested(&ip->i_iolock, XFS_IOLOCK_DEP(lock_flags));
 
+       if (lock_flags & XFS_MMAPLOCK_EXCL)
+               mrupdate_nested(&ip->i_mmaplock, XFS_MMAPLOCK_DEP(lock_flags));
+       else if (lock_flags & XFS_MMAPLOCK_SHARED)
+               mraccess_nested(&ip->i_mmaplock, XFS_MMAPLOCK_DEP(lock_flags));
+
        if (lock_flags & XFS_ILOCK_EXCL)
                mrupdate_nested(&ip->i_lock, XFS_ILOCK_DEP(lock_flags));
        else if (lock_flags & XFS_ILOCK_SHARED)
@@ -191,6 +208,8 @@ xfs_ilock_nowait(
         */
        ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) !=
               (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL));
+       ASSERT((lock_flags & (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL)) !=
+              (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL));
        ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) !=
               (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
        ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_DEP_MASK)) == 0);
@@ -202,21 +221,35 @@ xfs_ilock_nowait(
                if (!mrtryaccess(&ip->i_iolock))
                        goto out;
        }
+
+       if (lock_flags & XFS_MMAPLOCK_EXCL) {
+               if (!mrtryupdate(&ip->i_mmaplock))
+                       goto out_undo_iolock;
+       } else if (lock_flags & XFS_MMAPLOCK_SHARED) {
+               if (!mrtryaccess(&ip->i_mmaplock))
+                       goto out_undo_iolock;
+       }
+
        if (lock_flags & XFS_ILOCK_EXCL) {
                if (!mrtryupdate(&ip->i_lock))
-                       goto out_undo_iolock;
+                       goto out_undo_mmaplock;
        } else if (lock_flags & XFS_ILOCK_SHARED) {
                if (!mrtryaccess(&ip->i_lock))
-                       goto out_undo_iolock;
+                       goto out_undo_mmaplock;
        }
        return 1;
 
- out_undo_iolock:
+out_undo_mmaplock:
+       if (lock_flags & XFS_MMAPLOCK_EXCL)
+               mrunlock_excl(&ip->i_mmaplock);
+       else if (lock_flags & XFS_MMAPLOCK_SHARED)
+               mrunlock_shared(&ip->i_mmaplock);
+out_undo_iolock:
        if (lock_flags & XFS_IOLOCK_EXCL)
                mrunlock_excl(&ip->i_iolock);
        else if (lock_flags & XFS_IOLOCK_SHARED)
                mrunlock_shared(&ip->i_iolock);
- out:
+out:
        return 0;
 }
 
@@ -244,6 +277,8 @@ xfs_iunlock(
         */
        ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) !=
               (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL));
+       ASSERT((lock_flags & (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL)) !=
+              (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL));
        ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) !=
               (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
        ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_DEP_MASK)) == 0);
@@ -254,6 +289,11 @@ xfs_iunlock(
        else if (lock_flags & XFS_IOLOCK_SHARED)
                mrunlock_shared(&ip->i_iolock);
 
+       if (lock_flags & XFS_MMAPLOCK_EXCL)
+               mrunlock_excl(&ip->i_mmaplock);
+       else if (lock_flags & XFS_MMAPLOCK_SHARED)
+               mrunlock_shared(&ip->i_mmaplock);
+
        if (lock_flags & XFS_ILOCK_EXCL)
                mrunlock_excl(&ip->i_lock);
        else if (lock_flags & XFS_ILOCK_SHARED)
@@ -271,11 +311,14 @@ xfs_ilock_demote(
        xfs_inode_t             *ip,
        uint                    lock_flags)
 {
-       ASSERT(lock_flags & (XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL));
-       ASSERT((lock_flags & ~(XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL)) == 0);
+       ASSERT(lock_flags & (XFS_IOLOCK_EXCL|XFS_MMAPLOCK_EXCL|XFS_ILOCK_EXCL));
+       ASSERT((lock_flags &
+               ~(XFS_IOLOCK_EXCL|XFS_MMAPLOCK_EXCL|XFS_ILOCK_EXCL)) == 0);
 
        if (lock_flags & XFS_ILOCK_EXCL)
                mrdemote(&ip->i_lock);
+       if (lock_flags & XFS_MMAPLOCK_EXCL)
+               mrdemote(&ip->i_mmaplock);
        if (lock_flags & XFS_IOLOCK_EXCL)
                mrdemote(&ip->i_iolock);
 
@@ -294,6 +337,12 @@ xfs_isilocked(
                return rwsem_is_locked(&ip->i_lock.mr_lock);
        }
 
+       if (lock_flags & (XFS_MMAPLOCK_EXCL|XFS_MMAPLOCK_SHARED)) {
+               if (!(lock_flags & XFS_MMAPLOCK_SHARED))
+                       return !!ip->i_mmaplock.mr_writer;
+               return rwsem_is_locked(&ip->i_mmaplock.mr_lock);
+       }
+
        if (lock_flags & (XFS_IOLOCK_EXCL|XFS_IOLOCK_SHARED)) {
                if (!(lock_flags & XFS_IOLOCK_SHARED))
                        return !!ip->i_iolock.mr_writer;
@@ -314,14 +363,27 @@ int xfs_lock_delays;
 #endif
 
 /*
- * Bump the subclass so xfs_lock_inodes() acquires each lock with
- * a different value
+ * Bump the subclass so xfs_lock_inodes() acquires each lock with a different
+ * value. This shouldn't be called for page fault locking, but we also need to
+ * ensure we don't overrun the number of lockdep subclasses for the iolock or
+ * mmaplock as that is limited to 12 by the mmap lock lockdep annotations.
  */
 static inline int
 xfs_lock_inumorder(int lock_mode, int subclass)
 {
-       if (lock_mode & (XFS_IOLOCK_SHARED|XFS_IOLOCK_EXCL))
+       if (lock_mode & (XFS_IOLOCK_SHARED|XFS_IOLOCK_EXCL)) {
+               ASSERT(subclass + XFS_LOCK_INUMORDER <
+                       (1 << (XFS_MMAPLOCK_SHIFT - XFS_IOLOCK_SHIFT)));
                lock_mode |= (subclass + XFS_LOCK_INUMORDER) << XFS_IOLOCK_SHIFT;
+       }
+
+       if (lock_mode & (XFS_MMAPLOCK_SHARED|XFS_MMAPLOCK_EXCL)) {
+               ASSERT(subclass + XFS_LOCK_INUMORDER <
+                       (1 << (XFS_ILOCK_SHIFT - XFS_MMAPLOCK_SHIFT)));
+               lock_mode |= (subclass + XFS_LOCK_INUMORDER) <<
+                                                       XFS_MMAPLOCK_SHIFT;
+       }
+
        if (lock_mode & (XFS_ILOCK_SHARED|XFS_ILOCK_EXCL))
                lock_mode |= (subclass + XFS_LOCK_INUMORDER) << XFS_ILOCK_SHIFT;
 
@@ -329,15 +391,14 @@ xfs_lock_inumorder(int lock_mode, int subclass)
 }
 
 /*
- * The following routine will lock n inodes in exclusive mode.
- * We assume the caller calls us with the inodes in i_ino order.
+ * The following routine will lock n inodes in exclusive mode.  We assume the
+ * caller calls us with the inodes in i_ino order.
  *
- * We need to detect deadlock where an inode that we lock
- * is in the AIL and we start waiting for another inode that is locked
- * by a thread in a long running transaction (such as truncate). This can
- * result in deadlock since the long running trans might need to wait
- * for the inode we just locked in order to push the tail and free space
- * in the log.
+ * We need to detect deadlock where an inode that we lock is in the AIL and we
+ * start waiting for another inode that is locked by a thread in a long running
+ * transaction (such as truncate). This can result in deadlock since the long
+ * running trans might need to wait for the inode we just locked in order to
+ * push the tail and free space in the log.
  */
 void
 xfs_lock_inodes(
@@ -348,30 +409,27 @@ xfs_lock_inodes(
        int             attempts = 0, i, j, try_lock;
        xfs_log_item_t  *lp;
 
-       ASSERT(ips && (inodes >= 2)); /* we need at least two */
+       /* currently supports between 2 and 5 inodes */
+       ASSERT(ips && inodes >= 2 && inodes <= 5);
 
        try_lock = 0;
        i = 0;
-
 again:
        for (; i < inodes; i++) {
                ASSERT(ips[i]);
 
-               if (i && (ips[i] == ips[i-1]))  /* Already locked */
+               if (i && (ips[i] == ips[i - 1]))        /* Already locked */
                        continue;
 
                /*
-                * If try_lock is not set yet, make sure all locked inodes
-                * are not in the AIL.
-                * If any are, set try_lock to be used later.
+                * If try_lock is not set yet, make sure all locked inodes are
+                * not in the AIL.  If any are, set try_lock to be used later.
                 */
-
                if (!try_lock) {
                        for (j = (i - 1); j >= 0 && !try_lock; j--) {
                                lp = (xfs_log_item_t *)ips[j]->i_itemp;
-                               if (lp && (lp->li_flags & XFS_LI_IN_AIL)) {
+                               if (lp && (lp->li_flags & XFS_LI_IN_AIL))
                                        try_lock++;
-                               }
                        }
                }
 
@@ -381,51 +439,42 @@ again:
                 * we can't get any, we must release all we have
                 * and try again.
                 */
+               if (!try_lock) {
+                       xfs_ilock(ips[i], xfs_lock_inumorder(lock_mode, i));
+                       continue;
+               }
+
+               /* try_lock means we have an inode locked that is in the AIL. */
+               ASSERT(i != 0);
+               if (xfs_ilock_nowait(ips[i], xfs_lock_inumorder(lock_mode, i)))
+                       continue;
 
-               if (try_lock) {
-                       /* try_lock must be 0 if i is 0. */
+               /*
+                * Unlock all previous guys and try again.  xfs_iunlock will try
+                * to push the tail if the inode is in the AIL.
+                */
+               attempts++;
+               for (j = i - 1; j >= 0; j--) {
                        /*
-                        * try_lock means we have an inode locked
-                        * that is in the AIL.
+                        * Check to see if we've already unlocked this one.  Not
+                        * the first one going back, and the inode ptr is the
+                        * same.
                         */
-                       ASSERT(i != 0);
-                       if (!xfs_ilock_nowait(ips[i], xfs_lock_inumorder(lock_mode, i))) {
-                               attempts++;
-
-                               /*
-                                * Unlock all previous guys and try again.
-                                * xfs_iunlock will try to push the tail
-                                * if the inode is in the AIL.
-                                */
-
-                               for(j = i - 1; j >= 0; j--) {
-
-                                       /*
-                                        * Check to see if we've already
-                                        * unlocked this one.
-                                        * Not the first one going back,
-                                        * and the inode ptr is the same.
-                                        */
-                                       if ((j != (i - 1)) && ips[j] ==
-                                                               ips[j+1])
-                                               continue;
-
-                                       xfs_iunlock(ips[j], lock_mode);
-                               }
+                       if (j != (i - 1) && ips[j] == ips[j + 1])
+                               continue;
+
+                       xfs_iunlock(ips[j], lock_mode);
+               }
 
-                               if ((attempts % 5) == 0) {
-                                       delay(1); /* Don't just spin the CPU */
+               if ((attempts % 5) == 0) {
+                       delay(1); /* Don't just spin the CPU */
 #ifdef DEBUG
-                                       xfs_lock_delays++;
+                       xfs_lock_delays++;
 #endif
-                               }
-                               i = 0;
-                               try_lock = 0;
-                               goto again;
-                       }
-               } else {
-                       xfs_ilock(ips[i], xfs_lock_inumorder(lock_mode, i));
                }
+               i = 0;
+               try_lock = 0;
+               goto again;
        }
 
 #ifdef DEBUG
@@ -440,10 +489,10 @@ again:
 }
 
 /*
- * xfs_lock_two_inodes() can only be used to lock one type of lock
- * at a time - the iolock or the ilock, but not both at once. If
- * we lock both at once, lockdep will report false positives saying
- * we have violated locking orders.
+ * xfs_lock_two_inodes() can only be used to lock one type of lock at a time -
+ * the iolock, the mmaplock or the ilock, but not more than one at a time. If we
+ * lock more than one at a time, lockdep will report false positives saying we
+ * have violated locking orders.
  */
 void
 xfs_lock_two_inodes(
@@ -455,8 +504,12 @@ xfs_lock_two_inodes(
        int                     attempts = 0;
        xfs_log_item_t          *lp;
 
-       if (lock_mode & (XFS_IOLOCK_SHARED|XFS_IOLOCK_EXCL))
-               ASSERT((lock_mode & (XFS_ILOCK_SHARED|XFS_ILOCK_EXCL)) == 0);
+       if (lock_mode & (XFS_IOLOCK_SHARED|XFS_IOLOCK_EXCL)) {
+               ASSERT(!(lock_mode & (XFS_MMAPLOCK_SHARED|XFS_MMAPLOCK_EXCL)));
+               ASSERT(!(lock_mode & (XFS_ILOCK_SHARED|XFS_ILOCK_EXCL)));
+       } else if (lock_mode & (XFS_MMAPLOCK_SHARED|XFS_MMAPLOCK_EXCL))
+               ASSERT(!(lock_mode & (XFS_ILOCK_SHARED|XFS_ILOCK_EXCL)));
+
        ASSERT(ip0->i_ino != ip1->i_ino);
 
        if (ip0->i_ino > ip1->i_ino) {
@@ -818,7 +871,7 @@ xfs_ialloc(
        xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
        xfs_trans_log_inode(tp, ip, flags);
 
-       /* now that we have an i_mode we can setup inode ops and unlock */
+       /* now that we have an i_mode we can setup the inode structure */
        xfs_setup_inode(ip);
 
        *ipp = ip;
@@ -1235,12 +1288,14 @@ xfs_create(
        xfs_trans_cancel(tp, cancel_flags);
  out_release_inode:
        /*
-        * Wait until after the current transaction is aborted to
-        * release the inode.  This prevents recursive transactions
-        * and deadlocks from xfs_inactive.
+        * Wait until after the current transaction is aborted to finish the
+        * setup of the inode and release the inode.  This prevents recursive
+        * transactions and deadlocks from xfs_inactive.
         */
-       if (ip)
+       if (ip) {
+               xfs_finish_inode_setup(ip);
                IRELE(ip);
+       }
 
        xfs_qm_dqrele(udqp);
        xfs_qm_dqrele(gdqp);
@@ -1345,12 +1400,14 @@ xfs_create_tmpfile(
        xfs_trans_cancel(tp, cancel_flags);
  out_release_inode:
        /*
-        * Wait until after the current transaction is aborted to
-        * release the inode.  This prevents recursive transactions
-        * and deadlocks from xfs_inactive.
+        * Wait until after the current transaction is aborted to finish the
+        * setup of the inode and release the inode.  This prevents recursive
+        * transactions and deadlocks from xfs_inactive.
         */
-       if (ip)
+       if (ip) {
+               xfs_finish_inode_setup(ip);
                IRELE(ip);
+       }
 
        xfs_qm_dqrele(udqp);
        xfs_qm_dqrele(gdqp);
@@ -2611,19 +2668,22 @@ xfs_remove(
 /*
  * Enter all inodes for a rename transaction into a sorted array.
  */
+#define __XFS_SORT_INODES      5
 STATIC void
 xfs_sort_for_rename(
-       xfs_inode_t     *dp1,   /* in: old (source) directory inode */
-       xfs_inode_t     *dp2,   /* in: new (target) directory inode */
-       xfs_inode_t     *ip1,   /* in: inode of old entry */
-       xfs_inode_t     *ip2,   /* in: inode of new entry, if it
-                                  already exists, NULL otherwise. */
-       xfs_inode_t     **i_tab,/* out: array of inode returned, sorted */
-       int             *num_inodes)  /* out: number of inodes in array */
+       struct xfs_inode        *dp1,   /* in: old (source) directory inode */
+       struct xfs_inode        *dp2,   /* in: new (target) directory inode */
+       struct xfs_inode        *ip1,   /* in: inode of old entry */
+       struct xfs_inode        *ip2,   /* in: inode of new entry */
+       struct xfs_inode        *wip,   /* in: whiteout inode */
+       struct xfs_inode        **i_tab,/* out: sorted array of inodes */
+       int                     *num_inodes)  /* in/out: inodes in array */
 {
-       xfs_inode_t             *temp;
        int                     i, j;
 
+       ASSERT(*num_inodes == __XFS_SORT_INODES);
+       memset(i_tab, 0, *num_inodes * sizeof(struct xfs_inode *));
+
        /*
         * i_tab contains a list of pointers to inodes.  We initialize
         * the table here & we'll sort it.  We will then use it to
@@ -2631,25 +2691,24 @@ xfs_sort_for_rename(
         *
         * Note that the table may contain duplicates.  e.g., dp1 == dp2.
         */
-       i_tab[0] = dp1;
-       i_tab[1] = dp2;
-       i_tab[2] = ip1;
-       if (ip2) {
-               *num_inodes = 4;
-               i_tab[3] = ip2;
-       } else {
-               *num_inodes = 3;
-               i_tab[3] = NULL;
-       }
+       i = 0;
+       i_tab[i++] = dp1;
+       i_tab[i++] = dp2;
+       i_tab[i++] = ip1;
+       if (ip2)
+               i_tab[i++] = ip2;
+       if (wip)
+               i_tab[i++] = wip;
+       *num_inodes = i;
 
        /*
         * Sort the elements via bubble sort.  (Remember, there are at
-        * most 4 elements to sort, so this is adequate.)
+        * most 5 elements to sort, so this is adequate.)
         */
        for (i = 0; i < *num_inodes; i++) {
                for (j = 1; j < *num_inodes; j++) {
                        if (i_tab[j]->i_ino < i_tab[j-1]->i_ino) {
-                               temp = i_tab[j];
+                               struct xfs_inode *temp = i_tab[j];
                                i_tab[j] = i_tab[j-1];
                                i_tab[j-1] = temp;
                        }
@@ -2657,6 +2716,31 @@ xfs_sort_for_rename(
        }
 }
 
+static int
+xfs_finish_rename(
+       struct xfs_trans        *tp,
+       struct xfs_bmap_free    *free_list)
+{
+       int                     committed = 0;
+       int                     error;
+
+       /*
+        * If this is a synchronous mount, make sure that the rename transaction
+        * goes to disk before returning to the user.
+        */
+       if (tp->t_mountp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC))
+               xfs_trans_set_sync(tp);
+
+       error = xfs_bmap_finish(&tp, free_list, &committed);
+       if (error) {
+               xfs_bmap_cancel(free_list);
+               xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
+               return error;
+       }
+
+       return xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
+}
+
 /*
  * xfs_cross_rename()
  *
@@ -2685,14 +2769,14 @@ xfs_cross_rename(
                                ip2->i_ino,
                                first_block, free_list, spaceres);
        if (error)
-               goto out;
+               goto out_trans_abort;
 
        /* Swap inode number for dirent in second parent */
        error = xfs_dir_replace(tp, dp2, name2,
                                ip1->i_ino,
                                first_block, free_list, spaceres);
        if (error)
-               goto out;
+               goto out_trans_abort;
 
        /*
         * If we're renaming one or more directories across different parents,
@@ -2707,16 +2791,16 @@ xfs_cross_rename(
                                                dp1->i_ino, first_block,
                                                free_list, spaceres);
                        if (error)
-                               goto out;
+                               goto out_trans_abort;
 
                        /* transfer ip2 ".." reference to dp1 */
                        if (!S_ISDIR(ip1->i_d.di_mode)) {
                                error = xfs_droplink(tp, dp2);
                                if (error)
-                                       goto out;
+                                       goto out_trans_abort;
                                error = xfs_bumplink(tp, dp1);
                                if (error)
-                                       goto out;
+                                       goto out_trans_abort;
                        }
 
                        /*
@@ -2734,16 +2818,16 @@ xfs_cross_rename(
                                                dp2->i_ino, first_block,
                                                free_list, spaceres);
                        if (error)
-                               goto out;
+                               goto out_trans_abort;
 
                        /* transfer ip1 ".." reference to dp2 */
                        if (!S_ISDIR(ip2->i_d.di_mode)) {
                                error = xfs_droplink(tp, dp1);
                                if (error)
-                                       goto out;
+                                       goto out_trans_abort;
                                error = xfs_bumplink(tp, dp2);
                                if (error)
-                                       goto out;
+                                       goto out_trans_abort;
                        }
 
                        /*
@@ -2771,66 +2855,108 @@ xfs_cross_rename(
        }
        xfs_trans_ichgtime(tp, dp1, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
        xfs_trans_log_inode(tp, dp1, XFS_ILOG_CORE);
-out:
+       return xfs_finish_rename(tp, free_list);
+
+out_trans_abort:
+       xfs_bmap_cancel(free_list);
+       xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
        return error;
 }
 
+/*
+ * xfs_rename_alloc_whiteout()
+ *
+ * Return a referenced, unlinked, unlocked inode that that can be used as a
+ * whiteout in a rename transaction. We use a tmpfile inode here so that if we
+ * crash between allocating the inode and linking it into the rename transaction
+ * recovery will free the inode and we won't leak it.
+ */
+static int
+xfs_rename_alloc_whiteout(
+       struct xfs_inode        *dp,
+       struct xfs_inode        **wip)
+{
+       struct xfs_inode        *tmpfile;
+       int                     error;
+
+       error = xfs_create_tmpfile(dp, NULL, S_IFCHR | WHITEOUT_MODE, &tmpfile);
+       if (error)
+               return error;
+
+       /* Satisfy xfs_bumplink that this is a real tmpfile */
+       xfs_finish_inode_setup(tmpfile);
+       VFS_I(tmpfile)->i_state |= I_LINKABLE;
+
+       *wip = tmpfile;
+       return 0;
+}
+
 /*
  * xfs_rename
  */
 int
 xfs_rename(
-       xfs_inode_t     *src_dp,
-       struct xfs_name *src_name,
-       xfs_inode_t     *src_ip,
-       xfs_inode_t     *target_dp,
-       struct xfs_name *target_name,
-       xfs_inode_t     *target_ip,
-       unsigned int    flags)
+       struct xfs_inode        *src_dp,
+       struct xfs_name         *src_name,
+       struct xfs_inode        *src_ip,
+       struct xfs_inode        *target_dp,
+       struct xfs_name         *target_name,
+       struct xfs_inode        *target_ip,
+       unsigned int            flags)
 {
-       xfs_trans_t     *tp = NULL;
-       xfs_mount_t     *mp = src_dp->i_mount;
-       int             new_parent;             /* moving to a new dir */
-       int             src_is_directory;       /* src_name is a directory */
-       int             error;
-       xfs_bmap_free_t free_list;
-       xfs_fsblock_t   first_block;
-       int             cancel_flags;
-       int             committed;
-       xfs_inode_t     *inodes[4];
-       int             spaceres;
-       int             num_inodes;
+       struct xfs_mount        *mp = src_dp->i_mount;
+       struct xfs_trans        *tp;
+       struct xfs_bmap_free    free_list;
+       xfs_fsblock_t           first_block;
+       struct xfs_inode        *wip = NULL;            /* whiteout inode */
+       struct xfs_inode        *inodes[__XFS_SORT_INODES];
+       int                     num_inodes = __XFS_SORT_INODES;
+       bool                    new_parent = (src_dp != target_dp);
+       bool                    src_is_directory = S_ISDIR(src_ip->i_d.di_mode);
+       int                     cancel_flags = 0;
+       int                     spaceres;
+       int                     error;
 
        trace_xfs_rename(src_dp, target_dp, src_name, target_name);
 
-       new_parent = (src_dp != target_dp);
-       src_is_directory = S_ISDIR(src_ip->i_d.di_mode);
+       if ((flags & RENAME_EXCHANGE) && !target_ip)
+               return -EINVAL;
 
-       xfs_sort_for_rename(src_dp, target_dp, src_ip, target_ip,
+       /*
+        * If we are doing a whiteout operation, allocate the whiteout inode
+        * we will be placing at the target and ensure the type is set
+        * appropriately.
+        */
+       if (flags & RENAME_WHITEOUT) {
+               ASSERT(!(flags & (RENAME_NOREPLACE | RENAME_EXCHANGE)));
+               error = xfs_rename_alloc_whiteout(target_dp, &wip);
+               if (error)
+                       return error;
+
+               /* setup target dirent info as whiteout */
+               src_name->type = XFS_DIR3_FT_CHRDEV;
+       }
+
+       xfs_sort_for_rename(src_dp, target_dp, src_ip, target_ip, wip,
                                inodes, &num_inodes);
 
-       xfs_bmap_init(&free_list, &first_block);
        tp = xfs_trans_alloc(mp, XFS_TRANS_RENAME);
-       cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
        spaceres = XFS_RENAME_SPACE_RES(mp, target_name->len);
        error = xfs_trans_reserve(tp, &M_RES(mp)->tr_rename, spaceres, 0);
        if (error == -ENOSPC) {
                spaceres = 0;
                error = xfs_trans_reserve(tp, &M_RES(mp)->tr_rename, 0, 0);
        }
-       if (error) {
-               xfs_trans_cancel(tp, 0);
-               goto std_return;
-       }
+       if (error)
+               goto out_trans_cancel;
+       cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
 
        /*
         * Attach the dquots to the inodes
         */
        error = xfs_qm_vop_rename_dqattach(inodes);
-       if (error) {
-               xfs_trans_cancel(tp, cancel_flags);
-               goto std_return;
-       }
+       if (error)
+               goto out_trans_cancel;
 
        /*
         * Lock all the participating inodes. Depending upon whether
@@ -2851,6 +2977,8 @@ xfs_rename(
        xfs_trans_ijoin(tp, src_ip, XFS_ILOCK_EXCL);
        if (target_ip)
                xfs_trans_ijoin(tp, target_ip, XFS_ILOCK_EXCL);
+       if (wip)
+               xfs_trans_ijoin(tp, wip, XFS_ILOCK_EXCL);
 
        /*
         * If we are using project inheritance, we only allow renames
@@ -2860,24 +2988,16 @@ xfs_rename(
        if (unlikely((target_dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
                     (xfs_get_projid(target_dp) != xfs_get_projid(src_ip)))) {
                error = -EXDEV;
-               goto error_return;
+               goto out_trans_cancel;
        }
 
-       /*
-        * Handle RENAME_EXCHANGE flags
-        */
-       if (flags & RENAME_EXCHANGE) {
-               if (target_ip == NULL) {
-                       error = -EINVAL;
-                       goto error_return;
-               }
-               error = xfs_cross_rename(tp, src_dp, src_name, src_ip,
-                                        target_dp, target_name, target_ip,
-                                        &free_list, &first_block, spaceres);
-               if (error)
-                       goto abort_return;
-               goto finish_rename;
-       }
+       xfs_bmap_init(&free_list, &first_block);
+
+       /* RENAME_EXCHANGE is unique from here on. */
+       if (flags & RENAME_EXCHANGE)
+               return xfs_cross_rename(tp, src_dp, src_name, src_ip,
+                                       target_dp, target_name, target_ip,
+                                       &free_list, &first_block, spaceres);
 
        /*
         * Set up the target.
@@ -2890,7 +3010,7 @@ xfs_rename(
                if (!spaceres) {
                        error = xfs_dir_canenter(tp, target_dp, target_name);
                        if (error)
-                               goto error_return;
+                               goto out_trans_cancel;
                }
                /*
                 * If target does not exist and the rename crosses
@@ -2901,9 +3021,9 @@ xfs_rename(
                                                src_ip->i_ino, &first_block,
                                                &free_list, spaceres);
                if (error == -ENOSPC)
-                       goto error_return;
+                       goto out_bmap_cancel;
                if (error)
-                       goto abort_return;
+                       goto out_trans_abort;
 
                xfs_trans_ichgtime(tp, target_dp,
                                        XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
@@ -2911,7 +3031,7 @@ xfs_rename(
                if (new_parent && src_is_directory) {
                        error = xfs_bumplink(tp, target_dp);
                        if (error)
-                               goto abort_return;
+                               goto out_trans_abort;
                }
        } else { /* target_ip != NULL */
                /*
@@ -2926,7 +3046,7 @@ xfs_rename(
                        if (!(xfs_dir_isempty(target_ip)) ||
                            (target_ip->i_d.di_nlink > 2)) {
                                error = -EEXIST;
-                               goto error_return;
+                               goto out_trans_cancel;
                        }
                }
 
@@ -2943,7 +3063,7 @@ xfs_rename(
                                        src_ip->i_ino,
                                        &first_block, &free_list, spaceres);
                if (error)
-                       goto abort_return;
+                       goto out_trans_abort;
 
                xfs_trans_ichgtime(tp, target_dp,
                                        XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
@@ -2954,7 +3074,7 @@ xfs_rename(
                 */
                error = xfs_droplink(tp, target_ip);
                if (error)
-                       goto abort_return;
+                       goto out_trans_abort;
 
                if (src_is_directory) {
                        /*
@@ -2962,7 +3082,7 @@ xfs_rename(
                         */
                        error = xfs_droplink(tp, target_ip);
                        if (error)
-                               goto abort_return;
+                               goto out_trans_abort;
                }
        } /* target_ip != NULL */
 
@@ -2979,7 +3099,7 @@ xfs_rename(
                                        &first_block, &free_list, spaceres);
                ASSERT(error != -EEXIST);
                if (error)
-                       goto abort_return;
+                       goto out_trans_abort;
        }
 
        /*
@@ -3005,49 +3125,67 @@ xfs_rename(
                 */
                error = xfs_droplink(tp, src_dp);
                if (error)
-                       goto abort_return;
+                       goto out_trans_abort;
        }
 
-       error = xfs_dir_removename(tp, src_dp, src_name, src_ip->i_ino,
+       /*
+        * For whiteouts, we only need to update the source dirent with the
+        * inode number of the whiteout inode rather than removing it
+        * altogether.
+        */
+       if (wip) {
+               error = xfs_dir_replace(tp, src_dp, src_name, wip->i_ino,
                                        &first_block, &free_list, spaceres);
+       } else
+               error = xfs_dir_removename(tp, src_dp, src_name, src_ip->i_ino,
+                                          &first_block, &free_list, spaceres);
        if (error)
-               goto abort_return;
-
-       xfs_trans_ichgtime(tp, src_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
-       xfs_trans_log_inode(tp, src_dp, XFS_ILOG_CORE);
-       if (new_parent)
-               xfs_trans_log_inode(tp, target_dp, XFS_ILOG_CORE);
+               goto out_trans_abort;
 
-finish_rename:
        /*
-        * If this is a synchronous mount, make sure that the
-        * rename transaction goes to disk before returning to
-        * the user.
+        * For whiteouts, we need to bump the link count on the whiteout inode.
+        * This means that failures all the way up to this point leave the inode
+        * on the unlinked list and so cleanup is a simple matter of dropping
+        * the remaining reference to it. If we fail here after bumping the link
+        * count, we're shutting down the filesystem so we'll never see the
+        * intermediate state on disk.
         */
-       if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
-               xfs_trans_set_sync(tp);
-       }
+       if (wip) {
+               ASSERT(wip->i_d.di_nlink == 0);
+               error = xfs_bumplink(tp, wip);
+               if (error)
+                       goto out_trans_abort;
+               error = xfs_iunlink_remove(tp, wip);
+               if (error)
+                       goto out_trans_abort;
+               xfs_trans_log_inode(tp, wip, XFS_ILOG_CORE);
 
-       error = xfs_bmap_finish(&tp, &free_list, &committed);
-       if (error) {
-               xfs_bmap_cancel(&free_list);
-               xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES |
-                                XFS_TRANS_ABORT));
-               goto std_return;
+               /*
+                * Now we have a real link, clear the "I'm a tmpfile" state
+                * flag from the inode so it doesn't accidentally get misused in
+                * future.
+                */
+               VFS_I(wip)->i_state &= ~I_LINKABLE;
        }
 
-       /*
-        * trans_commit will unlock src_ip, target_ip & decrement
-        * the vnode references.
-        */
-       return xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
+       xfs_trans_ichgtime(tp, src_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+       xfs_trans_log_inode(tp, src_dp, XFS_ILOG_CORE);
+       if (new_parent)
+               xfs_trans_log_inode(tp, target_dp, XFS_ILOG_CORE);
 
- abort_return:
+       error = xfs_finish_rename(tp, &free_list);
+       if (wip)
+               IRELE(wip);
+       return error;
+
+out_trans_abort:
        cancel_flags |= XFS_TRANS_ABORT;
- error_return:
+out_bmap_cancel:
        xfs_bmap_cancel(&free_list);
+out_trans_cancel:
        xfs_trans_cancel(tp, cancel_flags);
- std_return:
+       if (wip)
+               IRELE(wip);
        return error;
 }
 
index a1cd55f3f351e1361e2a3ea790f88f5f5070e7e3..8f22d20368d8ff4c0232174f8bdc7c1e1bcf28eb 100644 (file)
@@ -56,6 +56,7 @@ typedef struct xfs_inode {
        struct xfs_inode_log_item *i_itemp;     /* logging information */
        mrlock_t                i_lock;         /* inode lock */
        mrlock_t                i_iolock;       /* inode IO lock */
+       mrlock_t                i_mmaplock;     /* inode mmap IO lock */
        atomic_t                i_pincount;     /* inode pin count */
        spinlock_t              i_flags_lock;   /* inode i_flags lock */
        /* Miscellaneous state. */
@@ -263,15 +264,20 @@ static inline int xfs_isiflocked(struct xfs_inode *ip)
 #define        XFS_IOLOCK_SHARED       (1<<1)
 #define        XFS_ILOCK_EXCL          (1<<2)
 #define        XFS_ILOCK_SHARED        (1<<3)
+#define        XFS_MMAPLOCK_EXCL       (1<<4)
+#define        XFS_MMAPLOCK_SHARED     (1<<5)
 
 #define XFS_LOCK_MASK          (XFS_IOLOCK_EXCL | XFS_IOLOCK_SHARED \
-                               | XFS_ILOCK_EXCL | XFS_ILOCK_SHARED)
+                               | XFS_ILOCK_EXCL | XFS_ILOCK_SHARED \
+                               | XFS_MMAPLOCK_EXCL | XFS_MMAPLOCK_SHARED)
 
 #define XFS_LOCK_FLAGS \
        { XFS_IOLOCK_EXCL,      "IOLOCK_EXCL" }, \
        { XFS_IOLOCK_SHARED,    "IOLOCK_SHARED" }, \
        { XFS_ILOCK_EXCL,       "ILOCK_EXCL" }, \
-       { XFS_ILOCK_SHARED,     "ILOCK_SHARED" }
+       { XFS_ILOCK_SHARED,     "ILOCK_SHARED" }, \
+       { XFS_MMAPLOCK_EXCL,    "MMAPLOCK_EXCL" }, \
+       { XFS_MMAPLOCK_SHARED,  "MMAPLOCK_SHARED" }
 
 
 /*
@@ -302,17 +308,26 @@ static inline int xfs_isiflocked(struct xfs_inode *ip)
 #define XFS_IOLOCK_SHIFT       16
 #define        XFS_IOLOCK_PARENT       (XFS_LOCK_PARENT << XFS_IOLOCK_SHIFT)
 
+#define XFS_MMAPLOCK_SHIFT     20
+
 #define XFS_ILOCK_SHIFT                24
 #define        XFS_ILOCK_PARENT        (XFS_LOCK_PARENT << XFS_ILOCK_SHIFT)
 #define        XFS_ILOCK_RTBITMAP      (XFS_LOCK_RTBITMAP << XFS_ILOCK_SHIFT)
 #define        XFS_ILOCK_RTSUM         (XFS_LOCK_RTSUM << XFS_ILOCK_SHIFT)
 
-#define XFS_IOLOCK_DEP_MASK    0x00ff0000
+#define XFS_IOLOCK_DEP_MASK    0x000f0000
+#define XFS_MMAPLOCK_DEP_MASK  0x00f00000
 #define XFS_ILOCK_DEP_MASK     0xff000000
-#define XFS_LOCK_DEP_MASK      (XFS_IOLOCK_DEP_MASK | XFS_ILOCK_DEP_MASK)
+#define XFS_LOCK_DEP_MASK      (XFS_IOLOCK_DEP_MASK | \
+                                XFS_MMAPLOCK_DEP_MASK | \
+                                XFS_ILOCK_DEP_MASK)
 
-#define XFS_IOLOCK_DEP(flags)  (((flags) & XFS_IOLOCK_DEP_MASK) >> XFS_IOLOCK_SHIFT)
-#define XFS_ILOCK_DEP(flags)   (((flags) & XFS_ILOCK_DEP_MASK) >> XFS_ILOCK_SHIFT)
+#define XFS_IOLOCK_DEP(flags)  (((flags) & XFS_IOLOCK_DEP_MASK) \
+                                       >> XFS_IOLOCK_SHIFT)
+#define XFS_MMAPLOCK_DEP(flags)        (((flags) & XFS_MMAPLOCK_DEP_MASK) \
+                                       >> XFS_MMAPLOCK_SHIFT)
+#define XFS_ILOCK_DEP(flags)   (((flags) & XFS_ILOCK_DEP_MASK) \
+                                       >> XFS_ILOCK_SHIFT)
 
 /*
  * For multiple groups support: if S_ISGID bit is set in the parent
@@ -391,6 +406,28 @@ int        xfs_zero_eof(struct xfs_inode *ip, xfs_off_t offset,
 int    xfs_iozero(struct xfs_inode *ip, loff_t pos, size_t count);
 
 
+/* from xfs_iops.c */
+/*
+ * When setting up a newly allocated inode, we need to call
+ * xfs_finish_inode_setup() once the inode is fully instantiated at
+ * the VFS level to prevent the rest of the world seeing the inode
+ * before we've completed instantiation. Otherwise we can do it
+ * the moment the inode lookup is complete.
+ */
+extern void xfs_setup_inode(struct xfs_inode *ip);
+static inline void xfs_finish_inode_setup(struct xfs_inode *ip)
+{
+       xfs_iflags_clear(ip, XFS_INEW);
+       barrier();
+       unlock_new_inode(VFS_I(ip));
+}
+
+static inline void xfs_setup_existing_inode(struct xfs_inode *ip)
+{
+       xfs_setup_inode(ip);
+       xfs_finish_inode_setup(ip);
+}
+
 #define IHOLD(ip) \
 do { \
        ASSERT(atomic_read(&VFS_I(ip)->i_count) > 0) ; \
index ac4feae45eb308c39629f177c0b6620fae77fb69..87f67c6b654cb5c9899c5c566d238f5a9ea1f04a 100644 (file)
@@ -82,7 +82,7 @@ xfs_find_handle(
                error = user_lpath((const char __user *)hreq->path, &path);
                if (error)
                        return error;
-               inode = path.dentry->d_inode;
+               inode = d_inode(path.dentry);
        }
        ip = XFS_I(inode);
 
@@ -210,7 +210,7 @@ xfs_open_by_handle(
        dentry = xfs_handlereq_to_dentry(parfilp, hreq);
        if (IS_ERR(dentry))
                return PTR_ERR(dentry);
-       inode = dentry->d_inode;
+       inode = d_inode(dentry);
 
        /* Restrict xfs_open_by_handle to directories & regular files. */
        if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) {
@@ -303,7 +303,7 @@ xfs_readlink_by_handle(
                goto out_dput;
        }
 
-       error = xfs_readlink(XFS_I(dentry->d_inode), link);
+       error = xfs_readlink(XFS_I(d_inode(dentry)), link);
        if (error)
                goto out_kfree;
        error = readlink_copy(hreq->ohandle, olen, link);
@@ -376,7 +376,7 @@ xfs_fssetdm_by_handle(
                return PTR_ERR(dentry);
        }
 
-       if (IS_IMMUTABLE(dentry->d_inode) || IS_APPEND(dentry->d_inode)) {
+       if (IS_IMMUTABLE(d_inode(dentry)) || IS_APPEND(d_inode(dentry))) {
                error = -EPERM;
                goto out;
        }
@@ -386,7 +386,7 @@ xfs_fssetdm_by_handle(
                goto out;
        }
 
-       error = xfs_set_dmattrs(XFS_I(dentry->d_inode), fsd.fsd_dmevmask,
+       error = xfs_set_dmattrs(XFS_I(d_inode(dentry)), fsd.fsd_dmevmask,
                                 fsd.fsd_dmstate);
 
  out:
@@ -429,7 +429,7 @@ xfs_attrlist_by_handle(
                goto out_dput;
 
        cursor = (attrlist_cursor_kern_t *)&al_hreq.pos;
-       error = xfs_attr_list(XFS_I(dentry->d_inode), kbuf, al_hreq.buflen,
+       error = xfs_attr_list(XFS_I(d_inode(dentry)), kbuf, al_hreq.buflen,
                                        al_hreq.flags, cursor);
        if (error)
                goto out_kfree;
@@ -559,7 +559,7 @@ xfs_attrmulti_by_handle(
                switch (ops[i].am_opcode) {
                case ATTR_OP_GET:
                        ops[i].am_error = xfs_attrmulti_attr_get(
-                                       dentry->d_inode, attr_name,
+                                       d_inode(dentry), attr_name,
                                        ops[i].am_attrvalue, &ops[i].am_length,
                                        ops[i].am_flags);
                        break;
@@ -568,7 +568,7 @@ xfs_attrmulti_by_handle(
                        if (ops[i].am_error)
                                break;
                        ops[i].am_error = xfs_attrmulti_attr_set(
-                                       dentry->d_inode, attr_name,
+                                       d_inode(dentry), attr_name,
                                        ops[i].am_attrvalue, ops[i].am_length,
                                        ops[i].am_flags);
                        mnt_drop_write_file(parfilp);
@@ -578,7 +578,7 @@ xfs_attrmulti_by_handle(
                        if (ops[i].am_error)
                                break;
                        ops[i].am_error = xfs_attrmulti_attr_remove(
-                                       dentry->d_inode, attr_name,
+                                       d_inode(dentry), attr_name,
                                        ops[i].am_flags);
                        mnt_drop_write_file(parfilp);
                        break;
@@ -631,7 +631,7 @@ xfs_ioc_space(
 
        if (filp->f_flags & O_DSYNC)
                flags |= XFS_PREALLOC_SYNC;
-       if (ioflags & XFS_IO_INVIS)     
+       if (ioflags & XFS_IO_INVIS)
                flags |= XFS_PREALLOC_INVISIBLE;
 
        error = mnt_want_write_file(filp);
@@ -639,10 +639,13 @@ xfs_ioc_space(
                return error;
 
        xfs_ilock(ip, iolock);
-       error = xfs_break_layouts(inode, &iolock);
+       error = xfs_break_layouts(inode, &iolock, false);
        if (error)
                goto out_unlock;
 
+       xfs_ilock(ip, XFS_MMAPLOCK_EXCL);
+       iolock |= XFS_MMAPLOCK_EXCL;
+
        switch (bf->l_whence) {
        case 0: /*SEEK_SET*/
                break;
index bfc7c7c8a0c884a2ebcc30194a1ccb30373d0955..b88bdc85dd3db365230d51e31fc97030ed2de38d 100644 (file)
@@ -375,7 +375,7 @@ xfs_compat_attrlist_by_handle(
                goto out_dput;
 
        cursor = (attrlist_cursor_kern_t *)&al_hreq.pos;
-       error = xfs_attr_list(XFS_I(dentry->d_inode), kbuf, al_hreq.buflen,
+       error = xfs_attr_list(XFS_I(d_inode(dentry)), kbuf, al_hreq.buflen,
                                        al_hreq.flags, cursor);
        if (error)
                goto out_kfree;
@@ -445,7 +445,7 @@ xfs_compat_attrmulti_by_handle(
                switch (ops[i].am_opcode) {
                case ATTR_OP_GET:
                        ops[i].am_error = xfs_attrmulti_attr_get(
-                                       dentry->d_inode, attr_name,
+                                       d_inode(dentry), attr_name,
                                        compat_ptr(ops[i].am_attrvalue),
                                        &ops[i].am_length, ops[i].am_flags);
                        break;
@@ -454,7 +454,7 @@ xfs_compat_attrmulti_by_handle(
                        if (ops[i].am_error)
                                break;
                        ops[i].am_error = xfs_attrmulti_attr_set(
-                                       dentry->d_inode, attr_name,
+                                       d_inode(dentry), attr_name,
                                        compat_ptr(ops[i].am_attrvalue),
                                        ops[i].am_length, ops[i].am_flags);
                        mnt_drop_write_file(parfilp);
@@ -464,7 +464,7 @@ xfs_compat_attrmulti_by_handle(
                        if (ops[i].am_error)
                                break;
                        ops[i].am_error = xfs_attrmulti_attr_remove(
-                                       dentry->d_inode, attr_name,
+                                       d_inode(dentry), attr_name,
                                        ops[i].am_flags);
                        mnt_drop_write_file(parfilp);
                        break;
@@ -504,7 +504,7 @@ xfs_compat_fssetdm_by_handle(
        if (IS_ERR(dentry))
                return PTR_ERR(dentry);
 
-       if (IS_IMMUTABLE(dentry->d_inode) || IS_APPEND(dentry->d_inode)) {
+       if (IS_IMMUTABLE(d_inode(dentry)) || IS_APPEND(d_inode(dentry))) {
                error = -EPERM;
                goto out;
        }
@@ -514,7 +514,7 @@ xfs_compat_fssetdm_by_handle(
                goto out;
        }
 
-       error = xfs_set_dmattrs(XFS_I(dentry->d_inode), fsd.fsd_dmevmask,
+       error = xfs_set_dmattrs(XFS_I(d_inode(dentry)), fsd.fsd_dmevmask,
                                 fsd.fsd_dmstate);
 
 out:
index ccb1dd0d509ef8f9d50f1fb0d51e6c4fe6712237..38e633bad8c2a2c919d1b1c9a4b9bda1d24d2ec4 100644 (file)
@@ -460,8 +460,7 @@ xfs_iomap_prealloc_size(
        alloc_blocks = XFS_FILEOFF_MIN(roundup_pow_of_two(MAXEXTLEN),
                                       alloc_blocks);
 
-       xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
-       freesp = mp->m_sb.sb_fdblocks;
+       freesp = percpu_counter_read_positive(&mp->m_fdblocks);
        if (freesp < mp->m_low_space[XFS_LOWSP_5_PCNT]) {
                shift = 2;
                if (freesp < mp->m_low_space[XFS_LOWSP_4_PCNT])
index e53a903314225c030c45f694b4ffdaa509fa1ce8..f4cd7204e23667724c01a4c4b8efe8c1d48b1cb3 100644 (file)
@@ -187,6 +187,8 @@ xfs_generic_create(
        else
                d_instantiate(dentry, inode);
 
+       xfs_finish_inode_setup(ip);
+
  out_free_acl:
        if (default_acl)
                posix_acl_release(default_acl);
@@ -195,6 +197,7 @@ xfs_generic_create(
        return error;
 
  out_cleanup_inode:
+       xfs_finish_inode_setup(ip);
        if (!tmpfile)
                xfs_cleanup_inode(dir, inode, dentry);
        iput(inode);
@@ -301,7 +304,7 @@ xfs_vn_link(
        struct inode    *dir,
        struct dentry   *dentry)
 {
-       struct inode    *inode = old_dentry->d_inode;
+       struct inode    *inode = d_inode(old_dentry);
        struct xfs_name name;
        int             error;
 
@@ -326,7 +329,7 @@ xfs_vn_unlink(
 
        xfs_dentry_to_name(&name, dentry, 0);
 
-       error = xfs_remove(XFS_I(dir), &name, XFS_I(dentry->d_inode));
+       error = xfs_remove(XFS_I(dir), &name, XFS_I(d_inode(dentry)));
        if (error)
                return error;
 
@@ -367,9 +370,11 @@ xfs_vn_symlink(
                goto out_cleanup_inode;
 
        d_instantiate(dentry, inode);
+       xfs_finish_inode_setup(cip);
        return 0;
 
  out_cleanup_inode:
+       xfs_finish_inode_setup(cip);
        xfs_cleanup_inode(dir, inode, dentry);
        iput(inode);
  out:
@@ -384,22 +389,22 @@ xfs_vn_rename(
        struct dentry   *ndentry,
        unsigned int    flags)
 {
-       struct inode    *new_inode = ndentry->d_inode;
+       struct inode    *new_inode = d_inode(ndentry);
        int             omode = 0;
        struct xfs_name oname;
        struct xfs_name nname;
 
-       if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
+       if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
                return -EINVAL;
 
        /* if we are exchanging files, we need to set i_mode of both files */
        if (flags & RENAME_EXCHANGE)
-               omode = ndentry->d_inode->i_mode;
+               omode = d_inode(ndentry)->i_mode;
 
        xfs_dentry_to_name(&oname, odentry, omode);
-       xfs_dentry_to_name(&nname, ndentry, odentry->d_inode->i_mode);
+       xfs_dentry_to_name(&nname, ndentry, d_inode(odentry)->i_mode);
 
-       return xfs_rename(XFS_I(odir), &oname, XFS_I(odentry->d_inode),
+       return xfs_rename(XFS_I(odir), &oname, XFS_I(d_inode(odentry)),
                          XFS_I(ndir), &nname,
                          new_inode ? XFS_I(new_inode) : NULL, flags);
 }
@@ -421,7 +426,7 @@ xfs_vn_follow_link(
        if (!link)
                goto out_err;
 
-       error = xfs_readlink(XFS_I(dentry->d_inode), link);
+       error = xfs_readlink(XFS_I(d_inode(dentry)), link);
        if (unlikely(error))
                goto out_kfree;
 
@@ -441,7 +446,7 @@ xfs_vn_getattr(
        struct dentry           *dentry,
        struct kstat            *stat)
 {
-       struct inode            *inode = dentry->d_inode;
+       struct inode            *inode = d_inode(dentry);
        struct xfs_inode        *ip = XFS_I(inode);
        struct xfs_mount        *mp = ip->i_mount;
 
@@ -766,6 +771,7 @@ xfs_setattr_size(
                return error;
 
        ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
+       ASSERT(xfs_isilocked(ip, XFS_MMAPLOCK_EXCL));
        ASSERT(S_ISREG(ip->i_d.di_mode));
        ASSERT((iattr->ia_valid & (ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET|
                ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0);
@@ -829,55 +835,27 @@ xfs_setattr_size(
        inode_dio_wait(inode);
 
        /*
-        * Do all the page cache truncate work outside the transaction context
-        * as the "lock" order is page lock->log space reservation.  i.e.
-        * locking pages inside the transaction can ABBA deadlock with
-        * writeback. We have to do the VFS inode size update before we truncate
-        * the pagecache, however, to avoid racing with page faults beyond the
-        * new EOF they are not serialised against truncate operations except by
-        * page locks and size updates.
+        * We've already locked out new page faults, so now we can safely remove
+        * pages from the page cache knowing they won't get refaulted until we
+        * drop the XFS_MMAP_EXCL lock after the extent manipulations are
+        * complete. The truncate_setsize() call also cleans partial EOF page
+        * PTEs on extending truncates and hence ensures sub-page block size
+        * filesystems are correctly handled, too.
         *
-        * Hence we are in a situation where a truncate can fail with ENOMEM
-        * from xfs_trans_reserve(), but having already truncated the in-memory
-        * version of the file (i.e. made user visible changes). There's not
-        * much we can do about this, except to hope that the caller sees ENOMEM
-        * and retries the truncate operation.
+        * We have to do all the page cache truncate work outside the
+        * transaction context as the "lock" order is page lock->log space
+        * reservation as defined by extent allocation in the writeback path.
+        * Hence a truncate can fail with ENOMEM from xfs_trans_reserve(), but
+        * having already truncated the in-memory version of the file (i.e. made
+        * user visible changes). There's not much we can do about this, except
+        * to hope that the caller sees ENOMEM and retries the truncate
+        * operation.
         */
        error = block_truncate_page(inode->i_mapping, newsize, xfs_get_blocks);
        if (error)
                return error;
        truncate_setsize(inode, newsize);
 
-       /*
-        * The "we can't serialise against page faults" pain gets worse.
-        *
-        * If the file is mapped then we have to clean the page at the old EOF
-        * when extending the file. Extending the file can expose changes the
-        * underlying page mapping (e.g. from beyond EOF to a hole or
-        * unwritten), and so on the next attempt to write to that page we need
-        * to remap it for write. i.e. we need .page_mkwrite() to be called.
-        * Hence we need to clean the page to clean the pte and so a new write
-        * fault will be triggered appropriately.
-        *
-        * If we do it before we change the inode size, then we can race with a
-        * page fault that maps the page with exactly the same problem. If we do
-        * it after we change the file size, then a new page fault can come in
-        * and allocate space before we've run the rest of the truncate
-        * transaction. That's kinda grotesque, but it's better than have data
-        * over a hole, and so that's the lesser evil that has been chosen here.
-        *
-        * The real solution, however, is to have some mechanism for locking out
-        * page faults while a truncate is in progress.
-        */
-       if (newsize > oldsize && mapping_mapped(VFS_I(ip)->i_mapping)) {
-               error = filemap_write_and_wait_range(
-                               VFS_I(ip)->i_mapping,
-                               round_down(oldsize, PAGE_CACHE_SIZE),
-                               round_up(oldsize, PAGE_CACHE_SIZE) - 1);
-               if (error)
-                       return error;
-       }
-
        tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_SIZE);
        error = xfs_trans_reserve(tp, &M_RES(mp)->tr_itruncate, 0, 0);
        if (error)
@@ -968,16 +946,20 @@ xfs_vn_setattr(
        struct dentry           *dentry,
        struct iattr            *iattr)
 {
-       struct xfs_inode        *ip = XFS_I(dentry->d_inode);
+       struct xfs_inode        *ip = XFS_I(d_inode(dentry));
        int                     error;
 
        if (iattr->ia_valid & ATTR_SIZE) {
                uint            iolock = XFS_IOLOCK_EXCL;
 
                xfs_ilock(ip, iolock);
-               error = xfs_break_layouts(dentry->d_inode, &iolock);
-               if (!error)
+               error = xfs_break_layouts(d_inode(dentry), &iolock, true);
+               if (!error) {
+                       xfs_ilock(ip, XFS_MMAPLOCK_EXCL);
+                       iolock |= XFS_MMAPLOCK_EXCL;
+
                        error = xfs_setattr_size(ip, iattr);
+               }
                xfs_iunlock(ip, iolock);
        } else {
                error = xfs_setattr_nonsize(ip, iattr, 0);
@@ -1228,16 +1210,12 @@ xfs_diflags_to_iflags(
 }
 
 /*
- * Initialize the Linux inode, set up the operation vectors and
- * unlock the inode.
+ * Initialize the Linux inode and set up the operation vectors.
  *
- * When reading existing inodes from disk this is called directly
- * from xfs_iget, when creating a new inode it is called from
- * xfs_ialloc after setting up the inode.
- *
- * We are always called with an uninitialised linux inode here.
- * We need to initialise the necessary fields and take a reference
- * on it.
+ * When reading existing inodes from disk this is called directly from xfs_iget,
+ * when creating a new inode it is called from xfs_ialloc after setting up the
+ * inode. These callers have different criteria for clearing XFS_INEW, so leave
+ * it up to the caller to deal with unlocking the inode appropriately.
  */
 void
 xfs_setup_inode(
@@ -1324,9 +1302,4 @@ xfs_setup_inode(
                inode_has_no_xattr(inode);
                cache_no_acl(inode);
        }
-
-       xfs_iflags_clear(ip, XFS_INEW);
-       barrier();
-
-       unlock_new_inode(inode);
 }
index ea7a98e9cb7048820bfa69c5bc294ccbe4102709..a0f84abb0d09d34e0893e6c61b6e01c287a9946a 100644 (file)
@@ -25,8 +25,6 @@ extern const struct file_operations xfs_dir_file_operations;
 
 extern ssize_t xfs_vn_listxattr(struct dentry *, char *data, size_t size);
 
-extern void xfs_setup_inode(struct xfs_inode *);
-
 /*
  * Internal setattr interfaces.
  */
index 82e314258f739a1ff02d20f6c15c6aae5f593f2b..80429891dc9b59dcf893fc8cc4dad9fe85079c7b 100644 (file)
@@ -229,7 +229,7 @@ xfs_bulkstat_grab_ichunk(
        error = xfs_inobt_get_rec(cur, irec, &stat);
        if (error)
                return error;
-       XFS_WANT_CORRUPTED_RETURN(stat == 1);
+       XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, stat == 1);
 
        /* Check if the record contains the inode in request */
        if (irec->ir_startino + XFS_INODES_PER_CHUNK <= agino) {
index c31d2c2eadc4445606d53cbd0c744b9143345375..7c7842c85a082f92c99b25f6ca818c1bf32a7224 100644 (file)
@@ -116,15 +116,6 @@ typedef __uint64_t __psunsigned_t;
 #undef XFS_NATIVE_HOST
 #endif
 
-/*
- * Feature macros (disable/enable)
- */
-#ifdef CONFIG_SMP
-#define HAVE_PERCPU_SB /* per cpu superblock counters are a 2.6 feature */
-#else
-#undef  HAVE_PERCPU_SB /* per cpu superblock counters are a 2.6 feature */
-#endif
-
 #define irix_sgid_inherit      xfs_params.sgid_inherit.val
 #define irix_symlink_mode      xfs_params.symlink_mode.val
 #define xfs_panic_mask         xfs_params.panic_mask.val
index a5a945fc3bdc700e218c15f3d9511e9d390cba8f..4f5784f85a5b22e4bad0946106dcb1302f817ace 100644 (file)
@@ -4463,10 +4463,10 @@ xlog_do_recover(
        xfs_sb_from_disk(sbp, XFS_BUF_TO_SBP(bp));
        ASSERT(sbp->sb_magicnum == XFS_SB_MAGIC);
        ASSERT(xfs_sb_good_version(sbp));
+       xfs_reinit_percpu_counters(log->l_mp);
+
        xfs_buf_relse(bp);
 
-       /* We've re-read the superblock so re-initialize per-cpu counters */
-       xfs_icsb_reinit_counters(log->l_mp);
 
        xlog_recover_check_summary(log);
 
index 4fa80e63eea2ab86d786af16cb03ec3bf9e49dc1..2ce7ee3b4ec1fdb9e9344a1ec7ea3a2df5a3b29c 100644 (file)
 #include "xfs_sysfs.h"
 
 
-#ifdef HAVE_PERCPU_SB
-STATIC void    xfs_icsb_balance_counter(xfs_mount_t *, xfs_sb_field_t,
-                                               int);
-STATIC void    xfs_icsb_balance_counter_locked(xfs_mount_t *, xfs_sb_field_t,
-                                               int);
-STATIC void    xfs_icsb_disable_counter(xfs_mount_t *, xfs_sb_field_t);
-#else
-
-#define xfs_icsb_balance_counter(mp, a, b)             do { } while (0)
-#define xfs_icsb_balance_counter_locked(mp, a, b)      do { } while (0)
-#endif
-
 static DEFINE_MUTEX(xfs_uuid_table_mutex);
 static int xfs_uuid_table_size;
 static uuid_t *xfs_uuid_table;
@@ -347,8 +335,7 @@ reread:
                goto reread;
        }
 
-       /* Initialize per-cpu counters */
-       xfs_icsb_reinit_counters(mp);
+       xfs_reinit_percpu_counters(mp);
 
        /* no need to be quiet anymore, so reset the buf ops */
        bp->b_ops = &xfs_sb_buf_ops;
@@ -1087,8 +1074,6 @@ xfs_log_sbcount(xfs_mount_t *mp)
        if (!xfs_fs_writable(mp, SB_FREEZE_COMPLETE))
                return 0;
 
-       xfs_icsb_sync_counters(mp, 0);
-
        /*
         * we don't need to do this if we are updating the superblock
         * counters on every modification.
@@ -1099,253 +1084,136 @@ xfs_log_sbcount(xfs_mount_t *mp)
        return xfs_sync_sb(mp, true);
 }
 
-/*
- * xfs_mod_incore_sb_unlocked() is a utility routine commonly used to apply
- * a delta to a specified field in the in-core superblock.  Simply
- * switch on the field indicated and apply the delta to that field.
- * Fields are not allowed to dip below zero, so if the delta would
- * do this do not apply it and return EINVAL.
- *
- * The m_sb_lock must be held when this routine is called.
- */
-STATIC int
-xfs_mod_incore_sb_unlocked(
-       xfs_mount_t     *mp,
-       xfs_sb_field_t  field,
-       int64_t         delta,
-       int             rsvd)
+int
+xfs_mod_icount(
+       struct xfs_mount        *mp,
+       int64_t                 delta)
 {
-       int             scounter;       /* short counter for 32 bit fields */
-       long long       lcounter;       /* long counter for 64 bit fields */
-       long long       res_used, rem;
-
-       /*
-        * With the in-core superblock spin lock held, switch
-        * on the indicated field.  Apply the delta to the
-        * proper field.  If the fields value would dip below
-        * 0, then do not apply the delta and return EINVAL.
-        */
-       switch (field) {
-       case XFS_SBS_ICOUNT:
-               lcounter = (long long)mp->m_sb.sb_icount;
-               lcounter += delta;
-               if (lcounter < 0) {
-                       ASSERT(0);
-                       return -EINVAL;
-               }
-               mp->m_sb.sb_icount = lcounter;
-               return 0;
-       case XFS_SBS_IFREE:
-               lcounter = (long long)mp->m_sb.sb_ifree;
-               lcounter += delta;
-               if (lcounter < 0) {
-                       ASSERT(0);
-                       return -EINVAL;
-               }
-               mp->m_sb.sb_ifree = lcounter;
-               return 0;
-       case XFS_SBS_FDBLOCKS:
-               lcounter = (long long)
-                       mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
-               res_used = (long long)(mp->m_resblks - mp->m_resblks_avail);
-
-               if (delta > 0) {                /* Putting blocks back */
-                       if (res_used > delta) {
-                               mp->m_resblks_avail += delta;
-                       } else {
-                               rem = delta - res_used;
-                               mp->m_resblks_avail = mp->m_resblks;
-                               lcounter += rem;
-                       }
-               } else {                                /* Taking blocks away */
-                       lcounter += delta;
-                       if (lcounter >= 0) {
-                               mp->m_sb.sb_fdblocks = lcounter +
-                                                       XFS_ALLOC_SET_ASIDE(mp);
-                               return 0;
-                       }
-
-                       /*
-                        * We are out of blocks, use any available reserved
-                        * blocks if were allowed to.
-                        */
-                       if (!rsvd)
-                               return -ENOSPC;
-
-                       lcounter = (long long)mp->m_resblks_avail + delta;
-                       if (lcounter >= 0) {
-                               mp->m_resblks_avail = lcounter;
-                               return 0;
-                       }
-                       printk_once(KERN_WARNING
-                               "Filesystem \"%s\": reserve blocks depleted! "
-                               "Consider increasing reserve pool size.",
-                               mp->m_fsname);
-                       return -ENOSPC;
-               }
-
-               mp->m_sb.sb_fdblocks = lcounter + XFS_ALLOC_SET_ASIDE(mp);
-               return 0;
-       case XFS_SBS_FREXTENTS:
-               lcounter = (long long)mp->m_sb.sb_frextents;
-               lcounter += delta;
-               if (lcounter < 0) {
-                       return -ENOSPC;
-               }
-               mp->m_sb.sb_frextents = lcounter;
-               return 0;
-       case XFS_SBS_DBLOCKS:
-               lcounter = (long long)mp->m_sb.sb_dblocks;
-               lcounter += delta;
-               if (lcounter < 0) {
-                       ASSERT(0);
-                       return -EINVAL;
-               }
-               mp->m_sb.sb_dblocks = lcounter;
-               return 0;
-       case XFS_SBS_AGCOUNT:
-               scounter = mp->m_sb.sb_agcount;
-               scounter += delta;
-               if (scounter < 0) {
-                       ASSERT(0);
-                       return -EINVAL;
-               }
-               mp->m_sb.sb_agcount = scounter;
-               return 0;
-       case XFS_SBS_IMAX_PCT:
-               scounter = mp->m_sb.sb_imax_pct;
-               scounter += delta;
-               if (scounter < 0) {
-                       ASSERT(0);
-                       return -EINVAL;
-               }
-               mp->m_sb.sb_imax_pct = scounter;
-               return 0;
-       case XFS_SBS_REXTSIZE:
-               scounter = mp->m_sb.sb_rextsize;
-               scounter += delta;
-               if (scounter < 0) {
-                       ASSERT(0);
-                       return -EINVAL;
-               }
-               mp->m_sb.sb_rextsize = scounter;
-               return 0;
-       case XFS_SBS_RBMBLOCKS:
-               scounter = mp->m_sb.sb_rbmblocks;
-               scounter += delta;
-               if (scounter < 0) {
-                       ASSERT(0);
-                       return -EINVAL;
-               }
-               mp->m_sb.sb_rbmblocks = scounter;
-               return 0;
-       case XFS_SBS_RBLOCKS:
-               lcounter = (long long)mp->m_sb.sb_rblocks;
-               lcounter += delta;
-               if (lcounter < 0) {
-                       ASSERT(0);
-                       return -EINVAL;
-               }
-               mp->m_sb.sb_rblocks = lcounter;
-               return 0;
-       case XFS_SBS_REXTENTS:
-               lcounter = (long long)mp->m_sb.sb_rextents;
-               lcounter += delta;
-               if (lcounter < 0) {
-                       ASSERT(0);
-                       return -EINVAL;
-               }
-               mp->m_sb.sb_rextents = lcounter;
-               return 0;
-       case XFS_SBS_REXTSLOG:
-               scounter = mp->m_sb.sb_rextslog;
-               scounter += delta;
-               if (scounter < 0) {
-                       ASSERT(0);
-                       return -EINVAL;
-               }
-               mp->m_sb.sb_rextslog = scounter;
-               return 0;
-       default:
+       /* deltas are +/-64, hence the large batch size of 128. */
+       __percpu_counter_add(&mp->m_icount, delta, 128);
+       if (percpu_counter_compare(&mp->m_icount, 0) < 0) {
                ASSERT(0);
+               percpu_counter_add(&mp->m_icount, -delta);
                return -EINVAL;
        }
+       return 0;
 }
 
-/*
- * xfs_mod_incore_sb() is used to change a field in the in-core
- * superblock structure by the specified delta.  This modification
- * is protected by the m_sb_lock.  Just use the xfs_mod_incore_sb_unlocked()
- * routine to do the work.
- */
 int
-xfs_mod_incore_sb(
+xfs_mod_ifree(
        struct xfs_mount        *mp,
-       xfs_sb_field_t          field,
-       int64_t                 delta,
-       int                     rsvd)
+       int64_t                 delta)
 {
-       int                     status;
-
-#ifdef HAVE_PERCPU_SB
-       ASSERT(field < XFS_SBS_ICOUNT || field > XFS_SBS_FDBLOCKS);
-#endif
-       spin_lock(&mp->m_sb_lock);
-       status = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd);
-       spin_unlock(&mp->m_sb_lock);
-
-       return status;
+       percpu_counter_add(&mp->m_ifree, delta);
+       if (percpu_counter_compare(&mp->m_ifree, 0) < 0) {
+               ASSERT(0);
+               percpu_counter_add(&mp->m_ifree, -delta);
+               return -EINVAL;
+       }
+       return 0;
 }
 
-/*
- * Change more than one field in the in-core superblock structure at a time.
- *
- * The fields and changes to those fields are specified in the array of
- * xfs_mod_sb structures passed in.  Either all of the specified deltas
- * will be applied or none of them will.  If any modified field dips below 0,
- * then all modifications will be backed out and EINVAL will be returned.
- *
- * Note that this function may not be used for the superblock values that
- * are tracked with the in-memory per-cpu counters - a direct call to
- * xfs_icsb_modify_counters is required for these.
- */
 int
-xfs_mod_incore_sb_batch(
+xfs_mod_fdblocks(
        struct xfs_mount        *mp,
-       xfs_mod_sb_t            *msb,
-       uint                    nmsb,
-       int                     rsvd)
+       int64_t                 delta,
+       bool                    rsvd)
 {
-       xfs_mod_sb_t            *msbp;
-       int                     error = 0;
+       int64_t                 lcounter;
+       long long               res_used;
+       s32                     batch;
+
+       if (delta > 0) {
+               /*
+                * If the reserve pool is depleted, put blocks back into it
+                * first. Most of the time the pool is full.
+                */
+               if (likely(mp->m_resblks == mp->m_resblks_avail)) {
+                       percpu_counter_add(&mp->m_fdblocks, delta);
+                       return 0;
+               }
+
+               spin_lock(&mp->m_sb_lock);
+               res_used = (long long)(mp->m_resblks - mp->m_resblks_avail);
+
+               if (res_used > delta) {
+                       mp->m_resblks_avail += delta;
+               } else {
+                       delta -= res_used;
+                       mp->m_resblks_avail = mp->m_resblks;
+                       percpu_counter_add(&mp->m_fdblocks, delta);
+               }
+               spin_unlock(&mp->m_sb_lock);
+               return 0;
+       }
 
        /*
-        * Loop through the array of mod structures and apply each individually.
-        * If any fail, then back out all those which have already been applied.
-        * Do all of this within the scope of the m_sb_lock so that all of the
-        * changes will be atomic.
+        * Taking blocks away, need to be more accurate the closer we
+        * are to zero.
+        *
+        * batch size is set to a maximum of 1024 blocks - if we are
+        * allocating of freeing extents larger than this then we aren't
+        * going to be hammering the counter lock so a lock per update
+        * is not a problem.
+        *
+        * If the counter has a value of less than 2 * max batch size,
+        * then make everything serialise as we are real close to
+        * ENOSPC.
+        */
+#define __BATCH        1024
+       if (percpu_counter_compare(&mp->m_fdblocks, 2 * __BATCH) < 0)
+               batch = 1;
+       else
+               batch = __BATCH;
+#undef __BATCH
+
+       __percpu_counter_add(&mp->m_fdblocks, delta, batch);
+       if (percpu_counter_compare(&mp->m_fdblocks,
+                                  XFS_ALLOC_SET_ASIDE(mp)) >= 0) {
+               /* we had space! */
+               return 0;
+       }
+
+       /*
+        * lock up the sb for dipping into reserves before releasing the space
+        * that took us to ENOSPC.
         */
        spin_lock(&mp->m_sb_lock);
-       for (msbp = msb; msbp < (msb + nmsb); msbp++) {
-               ASSERT(msbp->msb_field < XFS_SBS_ICOUNT ||
-                      msbp->msb_field > XFS_SBS_FDBLOCKS);
+       percpu_counter_add(&mp->m_fdblocks, -delta);
+       if (!rsvd)
+               goto fdblocks_enospc;
 
-               error = xfs_mod_incore_sb_unlocked(mp, msbp->msb_field,
-                                                  msbp->msb_delta, rsvd);
-               if (error)
-                       goto unwind;
+       lcounter = (long long)mp->m_resblks_avail + delta;
+       if (lcounter >= 0) {
+               mp->m_resblks_avail = lcounter;
+               spin_unlock(&mp->m_sb_lock);
+               return 0;
        }
+       printk_once(KERN_WARNING
+               "Filesystem \"%s\": reserve blocks depleted! "
+               "Consider increasing reserve pool size.",
+               mp->m_fsname);
+fdblocks_enospc:
        spin_unlock(&mp->m_sb_lock);
-       return 0;
+       return -ENOSPC;
+}
 
-unwind:
-       while (--msbp >= msb) {
-               error = xfs_mod_incore_sb_unlocked(mp, msbp->msb_field,
-                                                  -msbp->msb_delta, rsvd);
-               ASSERT(error == 0);
-       }
+int
+xfs_mod_frextents(
+       struct xfs_mount        *mp,
+       int64_t                 delta)
+{
+       int64_t                 lcounter;
+       int                     ret = 0;
+
+       spin_lock(&mp->m_sb_lock);
+       lcounter = mp->m_sb.sb_frextents + delta;
+       if (lcounter < 0)
+               ret = -ENOSPC;
+       else
+               mp->m_sb.sb_frextents = lcounter;
        spin_unlock(&mp->m_sb_lock);
-       return error;
+       return ret;
 }
 
 /*
@@ -1407,573 +1275,3 @@ xfs_dev_is_read_only(
        }
        return 0;
 }
-
-#ifdef HAVE_PERCPU_SB
-/*
- * Per-cpu incore superblock counters
- *
- * Simple concept, difficult implementation
- *
- * Basically, replace the incore superblock counters with a distributed per cpu
- * counter for contended fields (e.g.  free block count).
- *
- * Difficulties arise in that the incore sb is used for ENOSPC checking, and
- * hence needs to be accurately read when we are running low on space. Hence
- * there is a method to enable and disable the per-cpu counters based on how
- * much "stuff" is available in them.
- *
- * Basically, a counter is enabled if there is enough free resource to justify
- * running a per-cpu fast-path. If the per-cpu counter runs out (i.e. a local
- * ENOSPC), then we disable the counters to synchronise all callers and
- * re-distribute the available resources.
- *
- * If, once we redistributed the available resources, we still get a failure,
- * we disable the per-cpu counter and go through the slow path.
- *
- * The slow path is the current xfs_mod_incore_sb() function.  This means that
- * when we disable a per-cpu counter, we need to drain its resources back to
- * the global superblock. We do this after disabling the counter to prevent
- * more threads from queueing up on the counter.
- *
- * Essentially, this means that we still need a lock in the fast path to enable
- * synchronisation between the global counters and the per-cpu counters. This
- * is not a problem because the lock will be local to a CPU almost all the time
- * and have little contention except when we get to ENOSPC conditions.
- *
- * Basically, this lock becomes a barrier that enables us to lock out the fast
- * path while we do things like enabling and disabling counters and
- * synchronising the counters.
- *
- * Locking rules:
- *
- *     1. m_sb_lock before picking up per-cpu locks
- *     2. per-cpu locks always picked up via for_each_online_cpu() order
- *     3. accurate counter sync requires m_sb_lock + per cpu locks
- *     4. modifying per-cpu counters requires holding per-cpu lock
- *     5. modifying global counters requires holding m_sb_lock
- *     6. enabling or disabling a counter requires holding the m_sb_lock 
- *        and _none_ of the per-cpu locks.
- *
- * Disabled counters are only ever re-enabled by a balance operation
- * that results in more free resources per CPU than a given threshold.
- * To ensure counters don't remain disabled, they are rebalanced when
- * the global resource goes above a higher threshold (i.e. some hysteresis
- * is present to prevent thrashing).
- */
-
-#ifdef CONFIG_HOTPLUG_CPU
-/*
- * hot-plug CPU notifier support.
- *
- * We need a notifier per filesystem as we need to be able to identify
- * the filesystem to balance the counters out. This is achieved by
- * having a notifier block embedded in the xfs_mount_t and doing pointer
- * magic to get the mount pointer from the notifier block address.
- */
-STATIC int
-xfs_icsb_cpu_notify(
-       struct notifier_block *nfb,
-       unsigned long action,
-       void *hcpu)
-{
-       xfs_icsb_cnts_t *cntp;
-       xfs_mount_t     *mp;
-
-       mp = (xfs_mount_t *)container_of(nfb, xfs_mount_t, m_icsb_notifier);
-       cntp = (xfs_icsb_cnts_t *)
-                       per_cpu_ptr(mp->m_sb_cnts, (unsigned long)hcpu);
-       switch (action) {
-       case CPU_UP_PREPARE:
-       case CPU_UP_PREPARE_FROZEN:
-               /* Easy Case - initialize the area and locks, and
-                * then rebalance when online does everything else for us. */
-               memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
-               break;
-       case CPU_ONLINE:
-       case CPU_ONLINE_FROZEN:
-               xfs_icsb_lock(mp);
-               xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0);
-               xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0);
-               xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
-               xfs_icsb_unlock(mp);
-               break;
-       case CPU_DEAD:
-       case CPU_DEAD_FROZEN:
-               /* Disable all the counters, then fold the dead cpu's
-                * count into the total on the global superblock and
-                * re-enable the counters. */
-               xfs_icsb_lock(mp);
-               spin_lock(&mp->m_sb_lock);
-               xfs_icsb_disable_counter(mp, XFS_SBS_ICOUNT);
-               xfs_icsb_disable_counter(mp, XFS_SBS_IFREE);
-               xfs_icsb_disable_counter(mp, XFS_SBS_FDBLOCKS);
-
-               mp->m_sb.sb_icount += cntp->icsb_icount;
-               mp->m_sb.sb_ifree += cntp->icsb_ifree;
-               mp->m_sb.sb_fdblocks += cntp->icsb_fdblocks;
-
-               memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
-
-               xfs_icsb_balance_counter_locked(mp, XFS_SBS_ICOUNT, 0);
-               xfs_icsb_balance_counter_locked(mp, XFS_SBS_IFREE, 0);
-               xfs_icsb_balance_counter_locked(mp, XFS_SBS_FDBLOCKS, 0);
-               spin_unlock(&mp->m_sb_lock);
-               xfs_icsb_unlock(mp);
-               break;
-       }
-
-       return NOTIFY_OK;
-}
-#endif /* CONFIG_HOTPLUG_CPU */
-
-int
-xfs_icsb_init_counters(
-       xfs_mount_t     *mp)
-{
-       xfs_icsb_cnts_t *cntp;
-       int             i;
-
-       mp->m_sb_cnts = alloc_percpu(xfs_icsb_cnts_t);
-       if (mp->m_sb_cnts == NULL)
-               return -ENOMEM;
-
-       for_each_online_cpu(i) {
-               cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
-               memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
-       }
-
-       mutex_init(&mp->m_icsb_mutex);
-
-       /*
-        * start with all counters disabled so that the
-        * initial balance kicks us off correctly
-        */
-       mp->m_icsb_counters = -1;
-
-#ifdef CONFIG_HOTPLUG_CPU
-       mp->m_icsb_notifier.notifier_call = xfs_icsb_cpu_notify;
-       mp->m_icsb_notifier.priority = 0;
-       register_hotcpu_notifier(&mp->m_icsb_notifier);
-#endif /* CONFIG_HOTPLUG_CPU */
-
-       return 0;
-}
-
-void
-xfs_icsb_reinit_counters(
-       xfs_mount_t     *mp)
-{
-       xfs_icsb_lock(mp);
-       /*
-        * start with all counters disabled so that the
-        * initial balance kicks us off correctly
-        */
-       mp->m_icsb_counters = -1;
-       xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0);
-       xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0);
-       xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
-       xfs_icsb_unlock(mp);
-}
-
-void
-xfs_icsb_destroy_counters(
-       xfs_mount_t     *mp)
-{
-       if (mp->m_sb_cnts) {
-               unregister_hotcpu_notifier(&mp->m_icsb_notifier);
-               free_percpu(mp->m_sb_cnts);
-       }
-       mutex_destroy(&mp->m_icsb_mutex);
-}
-
-STATIC void
-xfs_icsb_lock_cntr(
-       xfs_icsb_cnts_t *icsbp)
-{
-       while (test_and_set_bit(XFS_ICSB_FLAG_LOCK, &icsbp->icsb_flags)) {
-               ndelay(1000);
-       }
-}
-
-STATIC void
-xfs_icsb_unlock_cntr(
-       xfs_icsb_cnts_t *icsbp)
-{
-       clear_bit(XFS_ICSB_FLAG_LOCK, &icsbp->icsb_flags);
-}
-
-
-STATIC void
-xfs_icsb_lock_all_counters(
-       xfs_mount_t     *mp)
-{
-       xfs_icsb_cnts_t *cntp;
-       int             i;
-
-       for_each_online_cpu(i) {
-               cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
-               xfs_icsb_lock_cntr(cntp);
-       }
-}
-
-STATIC void
-xfs_icsb_unlock_all_counters(
-       xfs_mount_t     *mp)
-{
-       xfs_icsb_cnts_t *cntp;
-       int             i;
-
-       for_each_online_cpu(i) {
-               cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
-               xfs_icsb_unlock_cntr(cntp);
-       }
-}
-
-STATIC void
-xfs_icsb_count(
-       xfs_mount_t     *mp,
-       xfs_icsb_cnts_t *cnt,
-       int             flags)
-{
-       xfs_icsb_cnts_t *cntp;
-       int             i;
-
-       memset(cnt, 0, sizeof(xfs_icsb_cnts_t));
-
-       if (!(flags & XFS_ICSB_LAZY_COUNT))
-               xfs_icsb_lock_all_counters(mp);
-
-       for_each_online_cpu(i) {
-               cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
-               cnt->icsb_icount += cntp->icsb_icount;
-               cnt->icsb_ifree += cntp->icsb_ifree;
-               cnt->icsb_fdblocks += cntp->icsb_fdblocks;
-       }
-
-       if (!(flags & XFS_ICSB_LAZY_COUNT))
-               xfs_icsb_unlock_all_counters(mp);
-}
-
-STATIC int
-xfs_icsb_counter_disabled(
-       xfs_mount_t     *mp,
-       xfs_sb_field_t  field)
-{
-       ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS));
-       return test_bit(field, &mp->m_icsb_counters);
-}
-
-STATIC void
-xfs_icsb_disable_counter(
-       xfs_mount_t     *mp,
-       xfs_sb_field_t  field)
-{
-       xfs_icsb_cnts_t cnt;
-
-       ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS));
-
-       /*
-        * If we are already disabled, then there is nothing to do
-        * here. We check before locking all the counters to avoid
-        * the expensive lock operation when being called in the
-        * slow path and the counter is already disabled. This is
-        * safe because the only time we set or clear this state is under
-        * the m_icsb_mutex.
-        */
-       if (xfs_icsb_counter_disabled(mp, field))
-               return;
-
-       xfs_icsb_lock_all_counters(mp);
-       if (!test_and_set_bit(field, &mp->m_icsb_counters)) {
-               /* drain back to superblock */
-
-               xfs_icsb_count(mp, &cnt, XFS_ICSB_LAZY_COUNT);
-               switch(field) {
-               case XFS_SBS_ICOUNT:
-                       mp->m_sb.sb_icount = cnt.icsb_icount;
-                       break;
-               case XFS_SBS_IFREE:
-                       mp->m_sb.sb_ifree = cnt.icsb_ifree;
-                       break;
-               case XFS_SBS_FDBLOCKS:
-                       mp->m_sb.sb_fdblocks = cnt.icsb_fdblocks;
-                       break;
-               default:
-                       BUG();
-               }
-       }
-
-       xfs_icsb_unlock_all_counters(mp);
-}
-
-STATIC void
-xfs_icsb_enable_counter(
-       xfs_mount_t     *mp,
-       xfs_sb_field_t  field,
-       uint64_t        count,
-       uint64_t        resid)
-{
-       xfs_icsb_cnts_t *cntp;
-       int             i;
-
-       ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS));
-
-       xfs_icsb_lock_all_counters(mp);
-       for_each_online_cpu(i) {
-               cntp = per_cpu_ptr(mp->m_sb_cnts, i);
-               switch (field) {
-               case XFS_SBS_ICOUNT:
-                       cntp->icsb_icount = count + resid;
-                       break;
-               case XFS_SBS_IFREE:
-                       cntp->icsb_ifree = count + resid;
-                       break;
-               case XFS_SBS_FDBLOCKS:
-                       cntp->icsb_fdblocks = count + resid;
-                       break;
-               default:
-                       BUG();
-                       break;
-               }
-               resid = 0;
-       }
-       clear_bit(field, &mp->m_icsb_counters);
-       xfs_icsb_unlock_all_counters(mp);
-}
-
-void
-xfs_icsb_sync_counters_locked(
-       xfs_mount_t     *mp,
-       int             flags)
-{
-       xfs_icsb_cnts_t cnt;
-
-       xfs_icsb_count(mp, &cnt, flags);
-
-       if (!xfs_icsb_counter_disabled(mp, XFS_SBS_ICOUNT))
-               mp->m_sb.sb_icount = cnt.icsb_icount;
-       if (!xfs_icsb_counter_disabled(mp, XFS_SBS_IFREE))
-               mp->m_sb.sb_ifree = cnt.icsb_ifree;
-       if (!xfs_icsb_counter_disabled(mp, XFS_SBS_FDBLOCKS))
-               mp->m_sb.sb_fdblocks = cnt.icsb_fdblocks;
-}
-
-/*
- * Accurate update of per-cpu counters to incore superblock
- */
-void
-xfs_icsb_sync_counters(
-       xfs_mount_t     *mp,
-       int             flags)
-{
-       spin_lock(&mp->m_sb_lock);
-       xfs_icsb_sync_counters_locked(mp, flags);
-       spin_unlock(&mp->m_sb_lock);
-}
-
-/*
- * Balance and enable/disable counters as necessary.
- *
- * Thresholds for re-enabling counters are somewhat magic.  inode counts are
- * chosen to be the same number as single on disk allocation chunk per CPU, and
- * free blocks is something far enough zero that we aren't going thrash when we
- * get near ENOSPC. We also need to supply a minimum we require per cpu to
- * prevent looping endlessly when xfs_alloc_space asks for more than will
- * be distributed to a single CPU but each CPU has enough blocks to be
- * reenabled.
- *
- * Note that we can be called when counters are already disabled.
- * xfs_icsb_disable_counter() optimises the counter locking in this case to
- * prevent locking every per-cpu counter needlessly.
- */
-
-#define XFS_ICSB_INO_CNTR_REENABLE     (uint64_t)64
-#define XFS_ICSB_FDBLK_CNTR_REENABLE(mp) \
-               (uint64_t)(512 + XFS_ALLOC_SET_ASIDE(mp))
-STATIC void
-xfs_icsb_balance_counter_locked(
-       xfs_mount_t     *mp,
-       xfs_sb_field_t  field,
-       int             min_per_cpu)
-{
-       uint64_t        count, resid;
-       int             weight = num_online_cpus();
-       uint64_t        min = (uint64_t)min_per_cpu;
-
-       /* disable counter and sync counter */
-       xfs_icsb_disable_counter(mp, field);
-
-       /* update counters  - first CPU gets residual*/
-       switch (field) {
-       case XFS_SBS_ICOUNT:
-               count = mp->m_sb.sb_icount;
-               resid = do_div(count, weight);
-               if (count < max(min, XFS_ICSB_INO_CNTR_REENABLE))
-                       return;
-               break;
-       case XFS_SBS_IFREE:
-               count = mp->m_sb.sb_ifree;
-               resid = do_div(count, weight);
-               if (count < max(min, XFS_ICSB_INO_CNTR_REENABLE))
-                       return;
-               break;
-       case XFS_SBS_FDBLOCKS:
-               count = mp->m_sb.sb_fdblocks;
-               resid = do_div(count, weight);
-               if (count < max(min, XFS_ICSB_FDBLK_CNTR_REENABLE(mp)))
-                       return;
-               break;
-       default:
-               BUG();
-               count = resid = 0;      /* quiet, gcc */
-               break;
-       }
-
-       xfs_icsb_enable_counter(mp, field, count, resid);
-}
-
-STATIC void
-xfs_icsb_balance_counter(
-       xfs_mount_t     *mp,
-       xfs_sb_field_t  fields,
-       int             min_per_cpu)
-{
-       spin_lock(&mp->m_sb_lock);
-       xfs_icsb_balance_counter_locked(mp, fields, min_per_cpu);
-       spin_unlock(&mp->m_sb_lock);
-}
-
-int
-xfs_icsb_modify_counters(
-       xfs_mount_t     *mp,
-       xfs_sb_field_t  field,
-       int64_t         delta,
-       int             rsvd)
-{
-       xfs_icsb_cnts_t *icsbp;
-       long long       lcounter;       /* long counter for 64 bit fields */
-       int             ret = 0;
-
-       might_sleep();
-again:
-       preempt_disable();
-       icsbp = this_cpu_ptr(mp->m_sb_cnts);
-
-       /*
-        * if the counter is disabled, go to slow path
-        */
-       if (unlikely(xfs_icsb_counter_disabled(mp, field)))
-               goto slow_path;
-       xfs_icsb_lock_cntr(icsbp);
-       if (unlikely(xfs_icsb_counter_disabled(mp, field))) {
-               xfs_icsb_unlock_cntr(icsbp);
-               goto slow_path;
-       }
-
-       switch (field) {
-       case XFS_SBS_ICOUNT:
-               lcounter = icsbp->icsb_icount;
-               lcounter += delta;
-               if (unlikely(lcounter < 0))
-                       goto balance_counter;
-               icsbp->icsb_icount = lcounter;
-               break;
-
-       case XFS_SBS_IFREE:
-               lcounter = icsbp->icsb_ifree;
-               lcounter += delta;
-               if (unlikely(lcounter < 0))
-                       goto balance_counter;
-               icsbp->icsb_ifree = lcounter;
-               break;
-
-       case XFS_SBS_FDBLOCKS:
-               BUG_ON((mp->m_resblks - mp->m_resblks_avail) != 0);
-
-               lcounter = icsbp->icsb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
-               lcounter += delta;
-               if (unlikely(lcounter < 0))
-                       goto balance_counter;
-               icsbp->icsb_fdblocks = lcounter + XFS_ALLOC_SET_ASIDE(mp);
-               break;
-       default:
-               BUG();
-               break;
-       }
-       xfs_icsb_unlock_cntr(icsbp);
-       preempt_enable();
-       return 0;
-
-slow_path:
-       preempt_enable();
-
-       /*
-        * serialise with a mutex so we don't burn lots of cpu on
-        * the superblock lock. We still need to hold the superblock
-        * lock, however, when we modify the global structures.
-        */
-       xfs_icsb_lock(mp);
-
-       /*
-        * Now running atomically.
-        *
-        * If the counter is enabled, someone has beaten us to rebalancing.
-        * Drop the lock and try again in the fast path....
-        */
-       if (!(xfs_icsb_counter_disabled(mp, field))) {
-               xfs_icsb_unlock(mp);
-               goto again;
-       }
-
-       /*
-        * The counter is currently disabled. Because we are
-        * running atomically here, we know a rebalance cannot
-        * be in progress. Hence we can go straight to operating
-        * on the global superblock. We do not call xfs_mod_incore_sb()
-        * here even though we need to get the m_sb_lock. Doing so
-        * will cause us to re-enter this function and deadlock.
-        * Hence we get the m_sb_lock ourselves and then call
-        * xfs_mod_incore_sb_unlocked() as the unlocked path operates
-        * directly on the global counters.
-        */
-       spin_lock(&mp->m_sb_lock);
-       ret = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd);
-       spin_unlock(&mp->m_sb_lock);
-
-       /*
-        * Now that we've modified the global superblock, we
-        * may be able to re-enable the distributed counters
-        * (e.g. lots of space just got freed). After that
-        * we are done.
-        */
-       if (ret != -ENOSPC)
-               xfs_icsb_balance_counter(mp, field, 0);
-       xfs_icsb_unlock(mp);
-       return ret;
-
-balance_counter:
-       xfs_icsb_unlock_cntr(icsbp);
-       preempt_enable();
-
-       /*
-        * We may have multiple threads here if multiple per-cpu
-        * counters run dry at the same time. This will mean we can
-        * do more balances than strictly necessary but it is not
-        * the common slowpath case.
-        */
-       xfs_icsb_lock(mp);
-
-       /*
-        * running atomically.
-        *
-        * This will leave the counter in the correct state for future
-        * accesses. After the rebalance, we simply try again and our retry
-        * will either succeed through the fast path or slow path without
-        * another balance operation being required.
-        */
-       xfs_icsb_balance_counter(mp, field, delta);
-       xfs_icsb_unlock(mp);
-       goto again;
-}
-
-#endif
index 0d8abd6364d97e613d98d4f827814c7eb7beb207..8c995a2ccb6f94d01728812e47e361678ce61c22 100644 (file)
@@ -18,8 +18,6 @@
 #ifndef __XFS_MOUNT_H__
 #define        __XFS_MOUNT_H__
 
-#ifdef __KERNEL__
-
 struct xlog;
 struct xfs_inode;
 struct xfs_mru_cache;
@@ -29,44 +27,6 @@ struct xfs_quotainfo;
 struct xfs_dir_ops;
 struct xfs_da_geometry;
 
-#ifdef HAVE_PERCPU_SB
-
-/*
- * Valid per-cpu incore superblock counters. Note that if you add new counters,
- * you may need to define new counter disabled bit field descriptors as there
- * are more possible fields in the superblock that can fit in a bitfield on a
- * 32 bit platform. The XFS_SBS_* values for the current current counters just
- * fit.
- */
-typedef struct xfs_icsb_cnts {
-       uint64_t        icsb_fdblocks;
-       uint64_t        icsb_ifree;
-       uint64_t        icsb_icount;
-       unsigned long   icsb_flags;
-} xfs_icsb_cnts_t;
-
-#define XFS_ICSB_FLAG_LOCK     (1 << 0)        /* counter lock bit */
-
-#define XFS_ICSB_LAZY_COUNT    (1 << 1)        /* accuracy not needed */
-
-extern int     xfs_icsb_init_counters(struct xfs_mount *);
-extern void    xfs_icsb_reinit_counters(struct xfs_mount *);
-extern void    xfs_icsb_destroy_counters(struct xfs_mount *);
-extern void    xfs_icsb_sync_counters(struct xfs_mount *, int);
-extern void    xfs_icsb_sync_counters_locked(struct xfs_mount *, int);
-extern int     xfs_icsb_modify_counters(struct xfs_mount *, xfs_sb_field_t,
-                                               int64_t, int);
-
-#else
-#define xfs_icsb_init_counters(mp)             (0)
-#define xfs_icsb_destroy_counters(mp)          do { } while (0)
-#define xfs_icsb_reinit_counters(mp)           do { } while (0)
-#define xfs_icsb_sync_counters(mp, flags)      do { } while (0)
-#define xfs_icsb_sync_counters_locked(mp, flags) do { } while (0)
-#define xfs_icsb_modify_counters(mp, field, delta, rsvd) \
-       xfs_mod_incore_sb(mp, field, delta, rsvd)
-#endif
-
 /* dynamic preallocation free space thresholds, 5% down to 1% */
 enum {
        XFS_LOWSP_1_PCNT = 0,
@@ -81,8 +41,13 @@ typedef struct xfs_mount {
        struct super_block      *m_super;
        xfs_tid_t               m_tid;          /* next unused tid for fs */
        struct xfs_ail          *m_ail;         /* fs active log item list */
-       xfs_sb_t                m_sb;           /* copy of fs superblock */
+
+       struct xfs_sb           m_sb;           /* copy of fs superblock */
        spinlock_t              m_sb_lock;      /* sb counter lock */
+       struct percpu_counter   m_icount;       /* allocated inodes counter */
+       struct percpu_counter   m_ifree;        /* free inodes counter */
+       struct percpu_counter   m_fdblocks;     /* free block counter */
+
        struct xfs_buf          *m_sb_bp;       /* buffer for superblock */
        char                    *m_fsname;      /* filesystem name */
        int                     m_fsname_len;   /* strlen of fs name */
@@ -152,12 +117,6 @@ typedef struct xfs_mount {
        const struct xfs_dir_ops *m_nondir_inode_ops; /* !dir inode ops */
        uint                    m_chsize;       /* size of next field */
        atomic_t                m_active_trans; /* number trans frozen */
-#ifdef HAVE_PERCPU_SB
-       xfs_icsb_cnts_t __percpu *m_sb_cnts;    /* per-cpu superblock counters */
-       unsigned long           m_icsb_counters; /* disabled per-cpu counters */
-       struct notifier_block   m_icsb_notifier; /* hotplug cpu notifier */
-       struct mutex            m_icsb_mutex;   /* balancer sync lock */
-#endif
        struct xfs_mru_cache    *m_filestream;  /* per-mount filestream data */
        struct delayed_work     m_reclaim_work; /* background inode reclaim */
        struct delayed_work     m_eofblocks_work; /* background eof blocks
@@ -300,35 +259,6 @@ xfs_daddr_to_agbno(struct xfs_mount *mp, xfs_daddr_t d)
        return (xfs_agblock_t) do_div(ld, mp->m_sb.sb_agblocks);
 }
 
-/*
- * Per-cpu superblock locking functions
- */
-#ifdef HAVE_PERCPU_SB
-static inline void
-xfs_icsb_lock(xfs_mount_t *mp)
-{
-       mutex_lock(&mp->m_icsb_mutex);
-}
-
-static inline void
-xfs_icsb_unlock(xfs_mount_t *mp)
-{
-       mutex_unlock(&mp->m_icsb_mutex);
-}
-#else
-#define xfs_icsb_lock(mp)
-#define xfs_icsb_unlock(mp)
-#endif
-
-/*
- * This structure is for use by the xfs_mod_incore_sb_batch() routine.
- * xfs_growfs can specify a few fields which are more than int limit
- */
-typedef struct xfs_mod_sb {
-       xfs_sb_field_t  msb_field;      /* Field to modify, see below */
-       int64_t         msb_delta;      /* Change to make to specified field */
-} xfs_mod_sb_t;
-
 /*
  * Per-ag incore structure, copies of information in agf and agi, to improve the
  * performance of allocation group selection.
@@ -383,11 +313,14 @@ extern __uint64_t xfs_default_resblks(xfs_mount_t *mp);
 extern int     xfs_mountfs(xfs_mount_t *mp);
 extern int     xfs_initialize_perag(xfs_mount_t *mp, xfs_agnumber_t agcount,
                                     xfs_agnumber_t *maxagi);
-
 extern void    xfs_unmountfs(xfs_mount_t *);
-extern int     xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int64_t, int);
-extern int     xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *,
-                       uint, int);
+
+extern int     xfs_mod_icount(struct xfs_mount *mp, int64_t delta);
+extern int     xfs_mod_ifree(struct xfs_mount *mp, int64_t delta);
+extern int     xfs_mod_fdblocks(struct xfs_mount *mp, int64_t delta,
+                                bool reserved);
+extern int     xfs_mod_frextents(struct xfs_mount *mp, int64_t delta);
+
 extern int     xfs_mount_log_sb(xfs_mount_t *);
 extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int);
 extern int     xfs_readsb(xfs_mount_t *, int);
@@ -399,6 +332,4 @@ extern int  xfs_dev_is_read_only(struct xfs_mount *, char *);
 
 extern void    xfs_set_low_space_thresholds(struct xfs_mount *);
 
-#endif /* __KERNEL__ */
-
 #endif /* __XFS_MOUNT_H__ */
index 30ecca3037e37bc5354fb9e37deb4db6e163fa8a..f8a674d7f092441fb5fb3ba2a35d3da3f9175e1a 100644 (file)
@@ -437,7 +437,7 @@ xfs_mru_cache_insert(
        if (!mru || !mru->lists)
                return -EINVAL;
 
-       if (radix_tree_preload(GFP_KERNEL))
+       if (radix_tree_preload(GFP_NOFS))
                return -ENOMEM;
 
        INIT_LIST_HEAD(&elem->list_node);
index 365dd57ea760ddd5beaa87d78dc6a1f31d7feb94..981a657eca396768dccafb187526de6f5395bfa0 100644 (file)
@@ -31,7 +31,8 @@
 int
 xfs_break_layouts(
        struct inode            *inode,
-       uint                    *iolock)
+       uint                    *iolock,
+       bool                    with_imutex)
 {
        struct xfs_inode        *ip = XFS_I(inode);
        int                     error;
@@ -40,8 +41,12 @@ xfs_break_layouts(
 
        while ((error = break_layout(inode, false) == -EWOULDBLOCK)) {
                xfs_iunlock(ip, *iolock);
+               if (with_imutex && (*iolock & XFS_IOLOCK_EXCL))
+                       mutex_unlock(&inode->i_mutex);
                error = break_layout(inode, true);
                *iolock = XFS_IOLOCK_EXCL;
+               if (with_imutex)
+                       mutex_lock(&inode->i_mutex);
                xfs_ilock(ip, *iolock);
        }
 
index b7fbfce660f68516d261e56f2c0ea2c78291832c..8147ac1088203b285bb8ebd6462c00d0c916abc1 100644 (file)
@@ -8,9 +8,10 @@ int xfs_fs_map_blocks(struct inode *inode, loff_t offset, u64 length,
 int xfs_fs_commit_blocks(struct inode *inode, struct iomap *maps, int nr_maps,
                struct iattr *iattr);
 
-int xfs_break_layouts(struct inode *inode, uint *iolock);
+int xfs_break_layouts(struct inode *inode, uint *iolock, bool with_imutex);
 #else
-static inline int xfs_break_layouts(struct inode *inode, uint *iolock)
+static inline int
+xfs_break_layouts(struct inode *inode, uint *iolock, bool with_imutex)
 {
        return 0;
 }
index fbbb9e62e274b525a03e7cb1373cae35b49ace1b..5538468c7f630d21d16c34551b98f2f4c4c7c5a9 100644 (file)
@@ -719,6 +719,7 @@ xfs_qm_qino_alloc(
        xfs_trans_t     *tp;
        int             error;
        int             committed;
+       bool            need_alloc = true;
 
        *ip = NULL;
        /*
@@ -747,6 +748,7 @@ xfs_qm_qino_alloc(
                                return error;
                        mp->m_sb.sb_gquotino = NULLFSINO;
                        mp->m_sb.sb_pquotino = NULLFSINO;
+                       need_alloc = false;
                }
        }
 
@@ -758,7 +760,7 @@ xfs_qm_qino_alloc(
                return error;
        }
 
-       if (!*ip) {
+       if (need_alloc) {
                error = xfs_dir_ialloc(&tp, NULL, S_IFREG, 1, 0, 0, 1, ip,
                                                                &committed);
                if (error) {
@@ -794,11 +796,14 @@ xfs_qm_qino_alloc(
        spin_unlock(&mp->m_sb_lock);
        xfs_log_sb(tp);
 
-       if ((error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES))) {
+       error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
+       if (error) {
+               ASSERT(XFS_FORCED_SHUTDOWN(mp));
                xfs_alert(mp, "%s failed (error %d)!", __func__, error);
-               return error;
        }
-       return 0;
+       if (need_alloc)
+               xfs_finish_inode_setup(*ip);
+       return error;
 }
 
 
index 8fcc4ccc5c791224e0d9325a5ad0557390a14d71..858e1e62bbaa390d0ea34a5b7766274f04361fd2 100644 (file)
@@ -109,8 +109,6 @@ static struct xfs_kobj xfs_dbg_kobj;        /* global debug sysfs attrs */
 #define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */
 #define MNTOPT_PQUOTANOENF "pqnoenforce"/* project quota limit enforcement */
 #define MNTOPT_QUOTANOENF  "qnoenforce"        /* same as uqnoenforce */
-#define MNTOPT_DELAYLOG    "delaylog"  /* Delayed logging enabled */
-#define MNTOPT_NODELAYLOG  "nodelaylog"        /* Delayed logging disabled */
 #define MNTOPT_DISCARD    "discard"    /* Discard unused blocks */
 #define MNTOPT_NODISCARD   "nodiscard" /* Do not discard unused blocks */
 
@@ -361,28 +359,10 @@ xfs_parseargs(
                } else if (!strcmp(this_char, MNTOPT_GQUOTANOENF)) {
                        mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE);
                        mp->m_qflags &= ~XFS_GQUOTA_ENFD;
-               } else if (!strcmp(this_char, MNTOPT_DELAYLOG)) {
-                       xfs_warn(mp,
-       "delaylog is the default now, option is deprecated.");
-               } else if (!strcmp(this_char, MNTOPT_NODELAYLOG)) {
-                       xfs_warn(mp,
-       "nodelaylog support has been removed, option is deprecated.");
                } else if (!strcmp(this_char, MNTOPT_DISCARD)) {
                        mp->m_flags |= XFS_MOUNT_DISCARD;
                } else if (!strcmp(this_char, MNTOPT_NODISCARD)) {
                        mp->m_flags &= ~XFS_MOUNT_DISCARD;
-               } else if (!strcmp(this_char, "ihashsize")) {
-                       xfs_warn(mp,
-       "ihashsize no longer used, option is deprecated.");
-               } else if (!strcmp(this_char, "osyncisdsync")) {
-                       xfs_warn(mp,
-       "osyncisdsync has no effect, option is deprecated.");
-               } else if (!strcmp(this_char, "osyncisosync")) {
-                       xfs_warn(mp,
-       "osyncisosync has no effect, option is deprecated.");
-               } else if (!strcmp(this_char, "irixsgid")) {
-                       xfs_warn(mp,
-       "irixsgid is now a sysctl(2) variable, option is deprecated.");
                } else {
                        xfs_warn(mp, "unknown mount option [%s].", this_char);
                        return -EINVAL;
@@ -986,6 +966,8 @@ xfs_fs_inode_init_once(
        atomic_set(&ip->i_pincount, 0);
        spin_lock_init(&ip->i_flags_lock);
 
+       mrlock_init(&ip->i_mmaplock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER,
+                    "xfsino", ip->i_ino);
        mrlock_init(&ip->i_lock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER,
                     "xfsino", ip->i_ino);
 }
@@ -1033,23 +1015,6 @@ xfs_free_fsname(
        kfree(mp->m_logname);
 }
 
-STATIC void
-xfs_fs_put_super(
-       struct super_block      *sb)
-{
-       struct xfs_mount        *mp = XFS_M(sb);
-
-       xfs_filestream_unmount(mp);
-       xfs_unmountfs(mp);
-
-       xfs_freesb(mp);
-       xfs_icsb_destroy_counters(mp);
-       xfs_destroy_mount_workqueues(mp);
-       xfs_close_devices(mp);
-       xfs_free_fsname(mp);
-       kfree(mp);
-}
-
 STATIC int
 xfs_fs_sync_fs(
        struct super_block      *sb,
@@ -1083,8 +1048,11 @@ xfs_fs_statfs(
 {
        struct xfs_mount        *mp = XFS_M(dentry->d_sb);
        xfs_sb_t                *sbp = &mp->m_sb;
-       struct xfs_inode        *ip = XFS_I(dentry->d_inode);
+       struct xfs_inode        *ip = XFS_I(d_inode(dentry));
        __uint64_t              fakeinos, id;
+       __uint64_t              icount;
+       __uint64_t              ifree;
+       __uint64_t              fdblocks;
        xfs_extlen_t            lsize;
        __int64_t               ffree;
 
@@ -1095,17 +1063,21 @@ xfs_fs_statfs(
        statp->f_fsid.val[0] = (u32)id;
        statp->f_fsid.val[1] = (u32)(id >> 32);
 
-       xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
+       icount = percpu_counter_sum(&mp->m_icount);
+       ifree = percpu_counter_sum(&mp->m_ifree);
+       fdblocks = percpu_counter_sum(&mp->m_fdblocks);
 
        spin_lock(&mp->m_sb_lock);
        statp->f_bsize = sbp->sb_blocksize;
        lsize = sbp->sb_logstart ? sbp->sb_logblocks : 0;
        statp->f_blocks = sbp->sb_dblocks - lsize;
-       statp->f_bfree = statp->f_bavail =
-                               sbp->sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
+       spin_unlock(&mp->m_sb_lock);
+
+       statp->f_bfree = fdblocks - XFS_ALLOC_SET_ASIDE(mp);
+       statp->f_bavail = statp->f_bfree;
+
        fakeinos = statp->f_bfree << sbp->sb_inopblog;
-       statp->f_files =
-           MIN(sbp->sb_icount + fakeinos, (__uint64_t)XFS_MAXINUMBER);
+       statp->f_files = MIN(icount + fakeinos, (__uint64_t)XFS_MAXINUMBER);
        if (mp->m_maxicount)
                statp->f_files = min_t(typeof(statp->f_files),
                                        statp->f_files,
@@ -1117,10 +1089,9 @@ xfs_fs_statfs(
                                        sbp->sb_icount);
 
        /* make sure statp->f_ffree does not underflow */
-       ffree = statp->f_files - (sbp->sb_icount - sbp->sb_ifree);
+       ffree = statp->f_files - (icount - ifree);
        statp->f_ffree = max_t(__int64_t, ffree, 0);
 
-       spin_unlock(&mp->m_sb_lock);
 
        if ((ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
            ((mp->m_qflags & (XFS_PQUOTA_ACCT|XFS_PQUOTA_ENFD))) ==
@@ -1256,6 +1227,12 @@ xfs_fs_remount(
 
        /* ro -> rw */
        if ((mp->m_flags & XFS_MOUNT_RDONLY) && !(*flags & MS_RDONLY)) {
+               if (mp->m_flags & XFS_MOUNT_NORECOVERY) {
+                       xfs_warn(mp,
+               "ro->rw transition prohibited on norecovery mount");
+                       return -EINVAL;
+               }
+
                mp->m_flags &= ~XFS_MOUNT_RDONLY;
 
                /*
@@ -1401,6 +1378,51 @@ xfs_finish_flags(
        return 0;
 }
 
+static int
+xfs_init_percpu_counters(
+       struct xfs_mount        *mp)
+{
+       int             error;
+
+       error = percpu_counter_init(&mp->m_icount, 0, GFP_KERNEL);
+       if (error)
+               return -ENOMEM;
+
+       error = percpu_counter_init(&mp->m_ifree, 0, GFP_KERNEL);
+       if (error)
+               goto free_icount;
+
+       error = percpu_counter_init(&mp->m_fdblocks, 0, GFP_KERNEL);
+       if (error)
+               goto free_ifree;
+
+       return 0;
+
+free_ifree:
+       percpu_counter_destroy(&mp->m_ifree);
+free_icount:
+       percpu_counter_destroy(&mp->m_icount);
+       return -ENOMEM;
+}
+
+void
+xfs_reinit_percpu_counters(
+       struct xfs_mount        *mp)
+{
+       percpu_counter_set(&mp->m_icount, mp->m_sb.sb_icount);
+       percpu_counter_set(&mp->m_ifree, mp->m_sb.sb_ifree);
+       percpu_counter_set(&mp->m_fdblocks, mp->m_sb.sb_fdblocks);
+}
+
+static void
+xfs_destroy_percpu_counters(
+       struct xfs_mount        *mp)
+{
+       percpu_counter_destroy(&mp->m_icount);
+       percpu_counter_destroy(&mp->m_ifree);
+       percpu_counter_destroy(&mp->m_fdblocks);
+}
+
 STATIC int
 xfs_fs_fill_super(
        struct super_block      *sb,
@@ -1449,7 +1471,7 @@ xfs_fs_fill_super(
        if (error)
                goto out_close_devices;
 
-       error = xfs_icsb_init_counters(mp);
+       error = xfs_init_percpu_counters(mp);
        if (error)
                goto out_destroy_workqueues;
 
@@ -1507,7 +1529,7 @@ xfs_fs_fill_super(
  out_free_sb:
        xfs_freesb(mp);
  out_destroy_counters:
-       xfs_icsb_destroy_counters(mp);
+       xfs_destroy_percpu_counters(mp);
 out_destroy_workqueues:
        xfs_destroy_mount_workqueues(mp);
  out_close_devices:
@@ -1524,6 +1546,24 @@ out_destroy_workqueues:
        goto out_free_sb;
 }
 
+STATIC void
+xfs_fs_put_super(
+       struct super_block      *sb)
+{
+       struct xfs_mount        *mp = XFS_M(sb);
+
+       xfs_notice(mp, "Unmounting Filesystem");
+       xfs_filestream_unmount(mp);
+       xfs_unmountfs(mp);
+
+       xfs_freesb(mp);
+       xfs_destroy_percpu_counters(mp);
+       xfs_destroy_mount_workqueues(mp);
+       xfs_close_devices(mp);
+       xfs_free_fsname(mp);
+       kfree(mp);
+}
+
 STATIC struct dentry *
 xfs_fs_mount(
        struct file_system_type *fs_type,
index 2b830c2f322e36ec4ce58753c4db96c2b6842a58..499058fea303a81fa3d77f15123a83a2bf6f28b8 100644 (file)
@@ -72,6 +72,8 @@ extern const struct export_operations xfs_export_operations;
 extern const struct xattr_handler *xfs_xattr_handlers[];
 extern const struct quotactl_ops xfs_quotactl_operations;
 
+extern void xfs_reinit_percpu_counters(struct xfs_mount *mp);
+
 #define XFS_M(sb)              ((struct xfs_mount *)((sb)->s_fs_info))
 
 #endif /* __XFS_SUPER_H__ */
index 25791df6f638c7a77421840e07b35204a5589f3f..3df411eadb867c83388bdec2995ca41a7a815d7e 100644 (file)
@@ -177,7 +177,7 @@ xfs_symlink(
        int                     pathlen;
        struct xfs_bmap_free    free_list;
        xfs_fsblock_t           first_block;
-       bool                    unlock_dp_on_error = false;
+       bool                    unlock_dp_on_error = false;
        uint                    cancel_flags;
        int                     committed;
        xfs_fileoff_t           first_fsb;
@@ -221,7 +221,7 @@ xfs_symlink(
                        XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT,
                        &udqp, &gdqp, &pdqp);
        if (error)
-               goto std_return;
+               return error;
 
        tp = xfs_trans_alloc(mp, XFS_TRANS_SYMLINK);
        cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
@@ -241,7 +241,7 @@ xfs_symlink(
        }
        if (error) {
                cancel_flags = 0;
-               goto error_return;
+               goto out_trans_cancel;
        }
 
        xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
@@ -252,7 +252,7 @@ xfs_symlink(
         */
        if (dp->i_d.di_flags & XFS_DIFLAG_NOSYMLINKS) {
                error = -EPERM;
-               goto error_return;
+               goto out_trans_cancel;
        }
 
        /*
@@ -261,7 +261,7 @@ xfs_symlink(
        error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp,
                                                pdqp, resblks, 1, 0);
        if (error)
-               goto error_return;
+               goto out_trans_cancel;
 
        /*
         * Check for ability to enter directory entry, if no space reserved.
@@ -269,7 +269,7 @@ xfs_symlink(
        if (!resblks) {
                error = xfs_dir_canenter(tp, dp, link_name);
                if (error)
-                       goto error_return;
+                       goto out_trans_cancel;
        }
        /*
         * Initialize the bmap freelist prior to calling either
@@ -282,15 +282,14 @@ xfs_symlink(
         */
        error = xfs_dir_ialloc(&tp, dp, S_IFLNK | (mode & ~S_IFMT), 1, 0,
                               prid, resblks > 0, &ip, NULL);
-       if (error) {
-               if (error == -ENOSPC)
-                       goto error_return;
-               goto error1;
-       }
+       if (error)
+               goto out_trans_cancel;
 
        /*
-        * An error after we've joined dp to the transaction will result in the
-        * transaction cancel unlocking dp so don't do it explicitly in the
+        * Now we join the directory inode to the transaction.  We do not do it
+        * earlier because xfs_dir_ialloc might commit the previous transaction
+        * (and release all the locks).  An error from here on will result in
+        * the transaction cancel unlocking dp so don't do it explicitly in the
         * error path.
         */
        xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
@@ -330,7 +329,7 @@ xfs_symlink(
                                  XFS_BMAPI_METADATA, &first_block, resblks,
                                  mval, &nmaps, &free_list);
                if (error)
-                       goto error2;
+                       goto out_bmap_cancel;
 
                if (resblks)
                        resblks -= fs_blocks;
@@ -348,7 +347,7 @@ xfs_symlink(
                                               BTOBB(byte_cnt), 0);
                        if (!bp) {
                                error = -ENOMEM;
-                               goto error2;
+                               goto out_bmap_cancel;
                        }
                        bp->b_ops = &xfs_symlink_buf_ops;
 
@@ -378,7 +377,7 @@ xfs_symlink(
        error = xfs_dir_createname(tp, dp, link_name, ip->i_ino,
                                        &first_block, &free_list, resblks);
        if (error)
-               goto error2;
+               goto out_bmap_cancel;
        xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
        xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
 
@@ -392,10 +391,13 @@ xfs_symlink(
        }
 
        error = xfs_bmap_finish(&tp, &free_list, &committed);
-       if (error) {
-               goto error2;
-       }
+       if (error)
+               goto out_bmap_cancel;
+
        error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
+       if (error)
+               goto out_release_inode;
+
        xfs_qm_dqrele(udqp);
        xfs_qm_dqrele(gdqp);
        xfs_qm_dqrele(pdqp);
@@ -403,20 +405,28 @@ xfs_symlink(
        *ipp = ip;
        return 0;
 
- error2:
-       IRELE(ip);
- error1:
+out_bmap_cancel:
        xfs_bmap_cancel(&free_list);
        cancel_flags |= XFS_TRANS_ABORT;
- error_return:
+out_trans_cancel:
        xfs_trans_cancel(tp, cancel_flags);
+out_release_inode:
+       /*
+        * Wait until after the current transaction is aborted to finish the
+        * setup of the inode and release the inode.  This prevents recursive
+        * transactions and deadlocks from xfs_inactive.
+        */
+       if (ip) {
+               xfs_finish_inode_setup(ip);
+               IRELE(ip);
+       }
+
        xfs_qm_dqrele(udqp);
        xfs_qm_dqrele(gdqp);
        xfs_qm_dqrele(pdqp);
 
        if (unlock_dp_on_error)
                xfs_iunlock(dp, XFS_ILOCK_EXCL);
- std_return:
        return error;
 }
 
index 51372e34d9889b7977fa4821af3d5785766f983c..615781bf4ee5096e96c00e7f14f7a28f0cd16f9e 100644 (file)
@@ -115,7 +115,7 @@ DECLARE_EVENT_CLASS(xfs_perag_class,
                __entry->refcount = refcount;
                __entry->caller_ip = caller_ip;
        ),
-       TP_printk("dev %d:%d agno %u refcount %d caller %pf",
+       TP_printk("dev %d:%d agno %u refcount %d caller %ps",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  __entry->agno,
                  __entry->refcount,
@@ -239,7 +239,7 @@ TRACE_EVENT(xfs_iext_insert,
                __entry->caller_ip = caller_ip;
        ),
        TP_printk("dev %d:%d ino 0x%llx state %s idx %ld "
-                 "offset %lld block %lld count %lld flag %d caller %pf",
+                 "offset %lld block %lld count %lld flag %d caller %ps",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  __entry->ino,
                  __print_flags(__entry->bmap_state, "|", XFS_BMAP_EXT_FLAGS),
@@ -283,7 +283,7 @@ DECLARE_EVENT_CLASS(xfs_bmap_class,
                __entry->caller_ip = caller_ip;
        ),
        TP_printk("dev %d:%d ino 0x%llx state %s idx %ld "
-                 "offset %lld block %lld count %lld flag %d caller %pf",
+                 "offset %lld block %lld count %lld flag %d caller %ps",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  __entry->ino,
                  __print_flags(__entry->bmap_state, "|", XFS_BMAP_EXT_FLAGS),
@@ -329,7 +329,7 @@ DECLARE_EVENT_CLASS(xfs_buf_class,
                __entry->caller_ip = caller_ip;
        ),
        TP_printk("dev %d:%d bno 0x%llx nblks 0x%x hold %d pincount %d "
-                 "lock %d flags %s caller %pf",
+                 "lock %d flags %s caller %ps",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  (unsigned long long)__entry->bno,
                  __entry->nblks,
@@ -402,7 +402,7 @@ DECLARE_EVENT_CLASS(xfs_buf_flags_class,
                __entry->caller_ip = caller_ip;
        ),
        TP_printk("dev %d:%d bno 0x%llx len 0x%zx hold %d pincount %d "
-                 "lock %d flags %s caller %pf",
+                 "lock %d flags %s caller %ps",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  (unsigned long long)__entry->bno,
                  __entry->buffer_length,
@@ -447,7 +447,7 @@ TRACE_EVENT(xfs_buf_ioerror,
                __entry->caller_ip = caller_ip;
        ),
        TP_printk("dev %d:%d bno 0x%llx len 0x%zx hold %d pincount %d "
-                 "lock %d error %d flags %s caller %pf",
+                 "lock %d error %d flags %s caller %ps",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  (unsigned long long)__entry->bno,
                  __entry->buffer_length,
@@ -613,7 +613,7 @@ DECLARE_EVENT_CLASS(xfs_lock_class,
                __entry->lock_flags = lock_flags;
                __entry->caller_ip = caller_ip;
        ),
-       TP_printk("dev %d:%d ino 0x%llx flags %s caller %pf",
+       TP_printk("dev %d:%d ino 0x%llx flags %s caller %ps",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  __entry->ino,
                  __print_flags(__entry->lock_flags, "|", XFS_LOCK_FLAGS),
@@ -664,6 +664,7 @@ DEFINE_INODE_EVENT(xfs_alloc_file_space);
 DEFINE_INODE_EVENT(xfs_free_file_space);
 DEFINE_INODE_EVENT(xfs_zero_file_space);
 DEFINE_INODE_EVENT(xfs_collapse_file_space);
+DEFINE_INODE_EVENT(xfs_insert_file_space);
 DEFINE_INODE_EVENT(xfs_readdir);
 #ifdef CONFIG_XFS_POSIX_ACL
 DEFINE_INODE_EVENT(xfs_get_acl);
@@ -685,6 +686,9 @@ DEFINE_INODE_EVENT(xfs_inode_set_eofblocks_tag);
 DEFINE_INODE_EVENT(xfs_inode_clear_eofblocks_tag);
 DEFINE_INODE_EVENT(xfs_inode_free_eofblocks_invalid);
 
+DEFINE_INODE_EVENT(xfs_filemap_fault);
+DEFINE_INODE_EVENT(xfs_filemap_page_mkwrite);
+
 DECLARE_EVENT_CLASS(xfs_iref_class,
        TP_PROTO(struct xfs_inode *ip, unsigned long caller_ip),
        TP_ARGS(ip, caller_ip),
@@ -702,7 +706,7 @@ DECLARE_EVENT_CLASS(xfs_iref_class,
                __entry->pincount = atomic_read(&ip->i_pincount);
                __entry->caller_ip = caller_ip;
        ),
-       TP_printk("dev %d:%d ino 0x%llx count %d pincount %d caller %pf",
+       TP_printk("dev %d:%d ino 0x%llx count %d pincount %d caller %ps",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  __entry->ino,
                  __entry->count,
@@ -1217,6 +1221,11 @@ DEFINE_IOMAP_EVENT(xfs_map_blocks_found);
 DEFINE_IOMAP_EVENT(xfs_map_blocks_alloc);
 DEFINE_IOMAP_EVENT(xfs_get_blocks_found);
 DEFINE_IOMAP_EVENT(xfs_get_blocks_alloc);
+DEFINE_IOMAP_EVENT(xfs_gbmap_direct);
+DEFINE_IOMAP_EVENT(xfs_gbmap_direct_new);
+DEFINE_IOMAP_EVENT(xfs_gbmap_direct_update);
+DEFINE_IOMAP_EVENT(xfs_gbmap_direct_none);
+DEFINE_IOMAP_EVENT(xfs_gbmap_direct_endio);
 
 DECLARE_EVENT_CLASS(xfs_simple_io_class,
        TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count),
@@ -1333,7 +1342,7 @@ TRACE_EVENT(xfs_bunmap,
                __entry->flags = flags;
        ),
        TP_printk("dev %d:%d ino 0x%llx size 0x%llx bno 0x%llx len 0x%llx"
-                 "flags %s caller %pf",
+                 "flags %s caller %ps",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  __entry->ino,
                  __entry->size,
@@ -1466,7 +1475,7 @@ TRACE_EVENT(xfs_agf,
        ),
        TP_printk("dev %d:%d agno %u flags %s length %u roots b %u c %u "
                  "levels b %u c %u flfirst %u fllast %u flcount %u "
-                 "freeblks %u longest %u caller %pf",
+                 "freeblks %u longest %u caller %ps",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  __entry->agno,
                  __print_flags(__entry->flags, "|", XFS_AGF_FLAGS),
index eb90cd59a0ec6298ec2bb98cae11fd2d4af57bc5..220ef2c906b2e2da7fcdfc0278a6256c59943691 100644 (file)
@@ -173,7 +173,7 @@ xfs_trans_reserve(
        uint                    rtextents)
 {
        int             error = 0;
-       int             rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
+       bool            rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
 
        /* Mark this thread as being in a transaction */
        current_set_flags_nested(&tp->t_pflags, PF_FSTRANS);
@@ -184,8 +184,7 @@ xfs_trans_reserve(
         * fail if the count would go below zero.
         */
        if (blocks > 0) {
-               error = xfs_icsb_modify_counters(tp->t_mountp, XFS_SBS_FDBLOCKS,
-                                         -((int64_t)blocks), rsvd);
+               error = xfs_mod_fdblocks(tp->t_mountp, -((int64_t)blocks), rsvd);
                if (error != 0) {
                        current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
                        return -ENOSPC;
@@ -236,8 +235,7 @@ xfs_trans_reserve(
         * fail if the count would go below zero.
         */
        if (rtextents > 0) {
-               error = xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FREXTENTS,
-                                         -((int64_t)rtextents), rsvd);
+               error = xfs_mod_frextents(tp->t_mountp, -((int64_t)rtextents));
                if (error) {
                        error = -ENOSPC;
                        goto undo_log;
@@ -268,8 +266,7 @@ undo_log:
 
 undo_blocks:
        if (blocks > 0) {
-               xfs_icsb_modify_counters(tp->t_mountp, XFS_SBS_FDBLOCKS,
-                                        (int64_t)blocks, rsvd);
+               xfs_mod_fdblocks(tp->t_mountp, -((int64_t)blocks), rsvd);
                tp->t_blk_res = 0;
        }
 
@@ -488,6 +485,54 @@ xfs_trans_apply_sb_deltas(
                                  sizeof(sbp->sb_frextents) - 1);
 }
 
+STATIC int
+xfs_sb_mod8(
+       uint8_t                 *field,
+       int8_t                  delta)
+{
+       int8_t                  counter = *field;
+
+       counter += delta;
+       if (counter < 0) {
+               ASSERT(0);
+               return -EINVAL;
+       }
+       *field = counter;
+       return 0;
+}
+
+STATIC int
+xfs_sb_mod32(
+       uint32_t                *field,
+       int32_t                 delta)
+{
+       int32_t                 counter = *field;
+
+       counter += delta;
+       if (counter < 0) {
+               ASSERT(0);
+               return -EINVAL;
+       }
+       *field = counter;
+       return 0;
+}
+
+STATIC int
+xfs_sb_mod64(
+       uint64_t                *field,
+       int64_t                 delta)
+{
+       int64_t                 counter = *field;
+
+       counter += delta;
+       if (counter < 0) {
+               ASSERT(0);
+               return -EINVAL;
+       }
+       *field = counter;
+       return 0;
+}
+
 /*
  * xfs_trans_unreserve_and_mod_sb() is called to release unused reservations
  * and apply superblock counter changes to the in-core superblock.  The
@@ -495,13 +540,6 @@ xfs_trans_apply_sb_deltas(
  * applied to the in-core superblock.  The idea is that that has already been
  * done.
  *
- * This is done efficiently with a single call to xfs_mod_incore_sb_batch().
- * However, we have to ensure that we only modify each superblock field only
- * once because the application of the delta values may not be atomic. That can
- * lead to ENOSPC races occurring if we have two separate modifcations of the
- * free space counter to put back the entire reservation and then take away
- * what we used.
- *
  * If we are not logging superblock counters, then the inode allocated/free and
  * used block counts are not updated in the on disk superblock. In this case,
  * XFS_TRANS_SB_DIRTY will not be set when the transaction is updated but we
@@ -509,21 +547,15 @@ xfs_trans_apply_sb_deltas(
  */
 void
 xfs_trans_unreserve_and_mod_sb(
-       xfs_trans_t     *tp)
+       struct xfs_trans        *tp)
 {
-       xfs_mod_sb_t    msb[9]; /* If you add cases, add entries */
-       xfs_mod_sb_t    *msbp;
-       xfs_mount_t     *mp = tp->t_mountp;
-       /* REFERENCED */
-       int             error;
-       int             rsvd;
-       int64_t         blkdelta = 0;
-       int64_t         rtxdelta = 0;
-       int64_t         idelta = 0;
-       int64_t         ifreedelta = 0;
-
-       msbp = msb;
-       rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
+       struct xfs_mount        *mp = tp->t_mountp;
+       bool                    rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
+       int64_t                 blkdelta = 0;
+       int64_t                 rtxdelta = 0;
+       int64_t                 idelta = 0;
+       int64_t                 ifreedelta = 0;
+       int                     error;
 
        /* calculate deltas */
        if (tp->t_blk_res > 0)
@@ -547,97 +579,115 @@ xfs_trans_unreserve_and_mod_sb(
 
        /* apply the per-cpu counters */
        if (blkdelta) {
-               error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
-                                                blkdelta, rsvd);
+               error = xfs_mod_fdblocks(mp, blkdelta, rsvd);
                if (error)
                        goto out;
        }
 
        if (idelta) {
-               error = xfs_icsb_modify_counters(mp, XFS_SBS_ICOUNT,
-                                                idelta, rsvd);
+               error = xfs_mod_icount(mp, idelta);
                if (error)
                        goto out_undo_fdblocks;
        }
 
        if (ifreedelta) {
-               error = xfs_icsb_modify_counters(mp, XFS_SBS_IFREE,
-                                                ifreedelta, rsvd);
+               error = xfs_mod_ifree(mp, ifreedelta);
                if (error)
                        goto out_undo_icount;
        }
 
+       if (rtxdelta == 0 && !(tp->t_flags & XFS_TRANS_SB_DIRTY))
+               return;
+
        /* apply remaining deltas */
-       if (rtxdelta != 0) {
-               msbp->msb_field = XFS_SBS_FREXTENTS;
-               msbp->msb_delta = rtxdelta;
-               msbp++;
+       spin_lock(&mp->m_sb_lock);
+       if (rtxdelta) {
+               error = xfs_sb_mod64(&mp->m_sb.sb_frextents, rtxdelta);
+               if (error)
+                       goto out_undo_ifree;
        }
 
-       if (tp->t_flags & XFS_TRANS_SB_DIRTY) {
-               if (tp->t_dblocks_delta != 0) {
-                       msbp->msb_field = XFS_SBS_DBLOCKS;
-                       msbp->msb_delta = tp->t_dblocks_delta;
-                       msbp++;
-               }
-               if (tp->t_agcount_delta != 0) {
-                       msbp->msb_field = XFS_SBS_AGCOUNT;
-                       msbp->msb_delta = tp->t_agcount_delta;
-                       msbp++;
-               }
-               if (tp->t_imaxpct_delta != 0) {
-                       msbp->msb_field = XFS_SBS_IMAX_PCT;
-                       msbp->msb_delta = tp->t_imaxpct_delta;
-                       msbp++;
-               }
-               if (tp->t_rextsize_delta != 0) {
-                       msbp->msb_field = XFS_SBS_REXTSIZE;
-                       msbp->msb_delta = tp->t_rextsize_delta;
-                       msbp++;
-               }
-               if (tp->t_rbmblocks_delta != 0) {
-                       msbp->msb_field = XFS_SBS_RBMBLOCKS;
-                       msbp->msb_delta = tp->t_rbmblocks_delta;
-                       msbp++;
-               }
-               if (tp->t_rblocks_delta != 0) {
-                       msbp->msb_field = XFS_SBS_RBLOCKS;
-                       msbp->msb_delta = tp->t_rblocks_delta;
-                       msbp++;
-               }
-               if (tp->t_rextents_delta != 0) {
-                       msbp->msb_field = XFS_SBS_REXTENTS;
-                       msbp->msb_delta = tp->t_rextents_delta;
-                       msbp++;
-               }
-               if (tp->t_rextslog_delta != 0) {
-                       msbp->msb_field = XFS_SBS_REXTSLOG;
-                       msbp->msb_delta = tp->t_rextslog_delta;
-                       msbp++;
-               }
+       if (tp->t_dblocks_delta != 0) {
+               error = xfs_sb_mod64(&mp->m_sb.sb_dblocks, tp->t_dblocks_delta);
+               if (error)
+                       goto out_undo_frextents;
        }
-
-       /*
-        * If we need to change anything, do it.
-        */
-       if (msbp > msb) {
-               error = xfs_mod_incore_sb_batch(tp->t_mountp, msb,
-                       (uint)(msbp - msb), rsvd);
+       if (tp->t_agcount_delta != 0) {
+               error = xfs_sb_mod32(&mp->m_sb.sb_agcount, tp->t_agcount_delta);
                if (error)
-                       goto out_undo_ifreecount;
+                       goto out_undo_dblocks;
        }
-
+       if (tp->t_imaxpct_delta != 0) {
+               error = xfs_sb_mod8(&mp->m_sb.sb_imax_pct, tp->t_imaxpct_delta);
+               if (error)
+                       goto out_undo_agcount;
+       }
+       if (tp->t_rextsize_delta != 0) {
+               error = xfs_sb_mod32(&mp->m_sb.sb_rextsize,
+                                    tp->t_rextsize_delta);
+               if (error)
+                       goto out_undo_imaxpct;
+       }
+       if (tp->t_rbmblocks_delta != 0) {
+               error = xfs_sb_mod32(&mp->m_sb.sb_rbmblocks,
+                                    tp->t_rbmblocks_delta);
+               if (error)
+                       goto out_undo_rextsize;
+       }
+       if (tp->t_rblocks_delta != 0) {
+               error = xfs_sb_mod64(&mp->m_sb.sb_rblocks, tp->t_rblocks_delta);
+               if (error)
+                       goto out_undo_rbmblocks;
+       }
+       if (tp->t_rextents_delta != 0) {
+               error = xfs_sb_mod64(&mp->m_sb.sb_rextents,
+                                    tp->t_rextents_delta);
+               if (error)
+                       goto out_undo_rblocks;
+       }
+       if (tp->t_rextslog_delta != 0) {
+               error = xfs_sb_mod8(&mp->m_sb.sb_rextslog,
+                                    tp->t_rextslog_delta);
+               if (error)
+                       goto out_undo_rextents;
+       }
+       spin_unlock(&mp->m_sb_lock);
        return;
 
-out_undo_ifreecount:
+out_undo_rextents:
+       if (tp->t_rextents_delta)
+               xfs_sb_mod64(&mp->m_sb.sb_rextents, -tp->t_rextents_delta);
+out_undo_rblocks:
+       if (tp->t_rblocks_delta)
+               xfs_sb_mod64(&mp->m_sb.sb_rblocks, -tp->t_rblocks_delta);
+out_undo_rbmblocks:
+       if (tp->t_rbmblocks_delta)
+               xfs_sb_mod32(&mp->m_sb.sb_rbmblocks, -tp->t_rbmblocks_delta);
+out_undo_rextsize:
+       if (tp->t_rextsize_delta)
+               xfs_sb_mod32(&mp->m_sb.sb_rextsize, -tp->t_rextsize_delta);
+out_undo_imaxpct:
+       if (tp->t_rextsize_delta)
+               xfs_sb_mod8(&mp->m_sb.sb_imax_pct, -tp->t_imaxpct_delta);
+out_undo_agcount:
+       if (tp->t_agcount_delta)
+               xfs_sb_mod32(&mp->m_sb.sb_agcount, -tp->t_agcount_delta);
+out_undo_dblocks:
+       if (tp->t_dblocks_delta)
+               xfs_sb_mod64(&mp->m_sb.sb_dblocks, -tp->t_dblocks_delta);
+out_undo_frextents:
+       if (rtxdelta)
+               xfs_sb_mod64(&mp->m_sb.sb_frextents, -rtxdelta);
+out_undo_ifree:
+       spin_unlock(&mp->m_sb_lock);
        if (ifreedelta)
-               xfs_icsb_modify_counters(mp, XFS_SBS_IFREE, -ifreedelta, rsvd);
+               xfs_mod_ifree(mp, -ifreedelta);
 out_undo_icount:
        if (idelta)
-               xfs_icsb_modify_counters(mp, XFS_SBS_ICOUNT, -idelta, rsvd);
+               xfs_mod_icount(mp, -idelta);
 out_undo_fdblocks:
        if (blkdelta)
-               xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, -blkdelta, rsvd);
+               xfs_mod_fdblocks(mp, -blkdelta, rsvd);
 out:
        ASSERT(error == 0);
        return;
index 69f6e475de97cacba39f85cdd0c2058539260447..c036815183cb69bd82c58a0300c243e7e7ca7f32 100644 (file)
@@ -35,7 +35,7 @@ static int
 xfs_xattr_get(struct dentry *dentry, const char *name,
                void *value, size_t size, int xflags)
 {
-       struct xfs_inode *ip = XFS_I(dentry->d_inode);
+       struct xfs_inode *ip = XFS_I(d_inode(dentry));
        int error, asize = size;
 
        if (strcmp(name, "") == 0)
@@ -57,7 +57,7 @@ static int
 xfs_xattr_set(struct dentry *dentry, const char *name, const void *value,
                size_t size, int flags, int xflags)
 {
-       struct xfs_inode *ip = XFS_I(dentry->d_inode);
+       struct xfs_inode *ip = XFS_I(d_inode(dentry));
 
        if (strcmp(name, "") == 0)
                return -EINVAL;
@@ -197,7 +197,7 @@ xfs_vn_listxattr(struct dentry *dentry, char *data, size_t size)
 {
        struct xfs_attr_list_context context;
        struct attrlist_cursor_kern cursor = { 0 };
-       struct inode            *inode = dentry->d_inode;
+       struct inode            *inode = d_inode(dentry);
        int                     error;
 
        /*
index 444671e9c65db3db323182081651282f40b847f6..dd86c5fc102d4798199f04f05e95998a7bb4d643 100644 (file)
@@ -3,11 +3,15 @@
 
 #include <linux/io.h>
 
+#include <asm/acpi.h>
+
+#ifndef acpi_os_ioremap
 static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys,
                                            acpi_size size)
 {
        return ioremap_cache(phys, size);
 }
+#endif
 
 void __iomem *__init_refok
 acpi_os_map_iomem(acpi_physical_address phys, acpi_size size);
index f5ca0e989bba417b275c781a0de86b247c1d8619..1c3002e1db20c8f91a31f17e8d6d323ed76ea404 100644 (file)
 
 #ifndef ACPI_USE_SYSTEM_INTTYPES
 
-typedef unsigned char u8;
 typedef unsigned char u8;
 typedef unsigned short u16;
 typedef short s16;
index b95dc32a6e6b61aefac9fefce83c6a3da20fa111..4188a4d3b597cac7e8d929d8745217d584d0bb63 100644 (file)
@@ -196,7 +196,7 @@ struct acpi_processor_flags {
 struct acpi_processor {
        acpi_handle handle;
        u32 acpi_id;
-       u32 phys_id;    /* CPU hardware ID such as APIC ID for x86 */
+       phys_cpuid_t phys_id;   /* CPU hardware ID such as APIC ID for x86 */
        u32 id;         /* CPU logical ID allocated by OS */
        u32 pblk;
        int performance_platform_limit;
@@ -310,8 +310,8 @@ static inline int acpi_processor_get_bios_limit(int cpu, unsigned int *limit)
 #endif                         /* CONFIG_CPU_FREQ */
 
 /* in processor_core.c */
-int acpi_get_phys_id(acpi_handle, int type, u32 acpi_id);
-int acpi_map_cpuid(int phys_id, u32 acpi_id);
+phys_cpuid_t acpi_get_phys_id(acpi_handle, int type, u32 acpi_id);
+int acpi_map_cpuid(phys_cpuid_t phys_id, u32 acpi_id);
 int acpi_get_cpuid(acpi_handle, int type, u32 acpi_id);
 
 /* in processor_pdc.c */
index 5c48c58514e551ab66ee158802aec6fe3905ea69..8bd374d3cf21fb0ee32e217f7f7eb6915c992514 100644 (file)
 #define TRACE_SYSCALLS()
 #endif
 
+#ifdef CONFIG_SERIAL_EARLYCON
+#define EARLYCON_TABLE() STRUCT_ALIGN();                       \
+                        VMLINUX_SYMBOL(__earlycon_table) = .;  \
+                        *(__earlycon_table)                    \
+                        *(__earlycon_table_end)
+#else
+#define EARLYCON_TABLE()
+#endif
 
 #define ___OF_TABLE(cfg, name) _OF_TABLE_##cfg(name)
 #define __OF_TABLE(cfg, name)  ___OF_TABLE(cfg, name)
        CPUIDLE_METHOD_OF_TABLES()                                      \
        KERNEL_DTB()                                                    \
        IRQCHIP_OF_MATCH_TABLE()                                        \
+       EARLYCON_TABLE()                                                \
        EARLYCON_OF_TABLES()
 
 #define INIT_TEXT                                                      \
index 961b9c130ea90ff62c4ded40f376c4bae6e094e2..aab088d301999278fa283a7f6d4a6e38ce6546d6 100644 (file)
  */
 #define NR_CLKS_DMC                    21
 
+/*
+ * CMU ISP
+ */
+
+/* Dividers */
+
+#define CLK_DIV_ISP1                   1
+#define CLK_DIV_ISP0                   2
+#define CLK_DIV_MCUISP1                        3
+#define CLK_DIV_MCUISP0                        4
+#define CLK_DIV_MPWM                   5
+
+/* Gates */
+
+#define CLK_UART_ISP                   8
+#define CLK_WDT_ISP                    9
+#define CLK_PWM_ISP                    10
+#define CLK_I2C1_ISP                   11
+#define CLK_I2C0_ISP                   12
+#define CLK_MPWM_ISP                   13
+#define CLK_MCUCTL_ISP                 14
+#define CLK_PPMUISPX                   15
+#define CLK_PPMUISPMX                  16
+#define CLK_QE_LITE1                   17
+#define CLK_QE_LITE0                   18
+#define CLK_QE_FD                      19
+#define CLK_QE_DRC                     20
+#define CLK_QE_ISP                     21
+#define CLK_CSIS1                      22
+#define CLK_SMMU_LITE1                 23
+#define CLK_SMMU_LITE0                 24
+#define CLK_SMMU_FD                    25
+#define CLK_SMMU_DRC                   26
+#define CLK_SMMU_ISP                   27
+#define CLK_GICISP                     28
+#define CLK_CSIS0                      29
+#define CLK_MCUISP                     30
+#define CLK_LITE1                      31
+#define CLK_LITE0                      32
+#define CLK_FD                         33
+#define CLK_DRC                                34
+#define CLK_ISP                                35
+#define CLK_QE_ISPCX                   36
+#define CLK_QE_SCALERP                 37
+#define CLK_QE_SCALERC                 38
+#define CLK_SMMU_SCALERP               39
+#define CLK_SMMU_SCALERC               40
+#define CLK_SCALERP                    41
+#define CLK_SCALERC                    42
+#define CLK_SPI1_ISP                   43
+#define CLK_SPI0_ISP                   44
+#define CLK_SMMU_ISPCX                 45
+#define CLK_ASYNCAXIM                  46
+#define CLK_SCLK_MPWM_ISP              47
+
+/*
+ * Total number of clocks of CMU_ISP.
+ * NOTE: Must be equal to last clock ID increased by one.
+ */
+#define NR_CLKS_ISP                    48
+
 #endif /* _DT_BINDINGS_CLOCK_SAMSUNG_EXYNOS3250_CLOCK_H */
diff --git a/include/dt-bindings/clock/exynos5433.h b/include/dt-bindings/clock/exynos5433.h
new file mode 100644 (file)
index 0000000..5bd80d5
--- /dev/null
@@ -0,0 +1,1403 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Author: Chanwoo Choi <cw00.choi@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.
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_EXYNOS5433_H
+#define _DT_BINDINGS_CLOCK_EXYNOS5433_H
+
+/* CMU_TOP */
+#define CLK_FOUT_ISP_PLL               1
+#define CLK_FOUT_AUD_PLL               2
+
+#define CLK_MOUT_AUD_PLL               10
+#define CLK_MOUT_ISP_PLL               11
+#define CLK_MOUT_AUD_PLL_USER_T                12
+#define CLK_MOUT_MPHY_PLL_USER         13
+#define CLK_MOUT_MFC_PLL_USER          14
+#define CLK_MOUT_BUS_PLL_USER          15
+#define CLK_MOUT_ACLK_HEVC_400         16
+#define CLK_MOUT_ACLK_CAM1_333         17
+#define CLK_MOUT_ACLK_CAM1_552_B       18
+#define CLK_MOUT_ACLK_CAM1_552_A       19
+#define CLK_MOUT_ACLK_ISP_DIS_400      20
+#define CLK_MOUT_ACLK_ISP_400          21
+#define CLK_MOUT_ACLK_BUS0_400         22
+#define CLK_MOUT_ACLK_MSCL_400_B       23
+#define CLK_MOUT_ACLK_MSCL_400_A       24
+#define CLK_MOUT_ACLK_GSCL_333         25
+#define CLK_MOUT_ACLK_G2D_400_B                26
+#define CLK_MOUT_ACLK_G2D_400_A                27
+#define CLK_MOUT_SCLK_JPEG_C           28
+#define CLK_MOUT_SCLK_JPEG_B           29
+#define CLK_MOUT_SCLK_JPEG_A           30
+#define CLK_MOUT_SCLK_MMC2_B           31
+#define CLK_MOUT_SCLK_MMC2_A           32
+#define CLK_MOUT_SCLK_MMC1_B           33
+#define CLK_MOUT_SCLK_MMC1_A           34
+#define CLK_MOUT_SCLK_MMC0_D           35
+#define CLK_MOUT_SCLK_MMC0_C           36
+#define CLK_MOUT_SCLK_MMC0_B           37
+#define CLK_MOUT_SCLK_MMC0_A           38
+#define CLK_MOUT_SCLK_SPI4             39
+#define CLK_MOUT_SCLK_SPI3             40
+#define CLK_MOUT_SCLK_UART2            41
+#define CLK_MOUT_SCLK_UART1            42
+#define CLK_MOUT_SCLK_UART0            43
+#define CLK_MOUT_SCLK_SPI2             44
+#define CLK_MOUT_SCLK_SPI1             45
+#define CLK_MOUT_SCLK_SPI0             46
+#define CLK_MOUT_ACLK_MFC_400_C                47
+#define CLK_MOUT_ACLK_MFC_400_B                48
+#define CLK_MOUT_ACLK_MFC_400_A                49
+#define CLK_MOUT_SCLK_ISP_SENSOR2      50
+#define CLK_MOUT_SCLK_ISP_SENSOR1      51
+#define CLK_MOUT_SCLK_ISP_SENSOR0      52
+#define CLK_MOUT_SCLK_ISP_UART         53
+#define CLK_MOUT_SCLK_ISP_SPI1         54
+#define CLK_MOUT_SCLK_ISP_SPI0         55
+#define CLK_MOUT_SCLK_PCIE_100         56
+#define CLK_MOUT_SCLK_UFSUNIPRO                57
+#define CLK_MOUT_SCLK_USBHOST30                58
+#define CLK_MOUT_SCLK_USBDRD30         59
+#define CLK_MOUT_SCLK_SLIMBUS          60
+#define CLK_MOUT_SCLK_SPDIF            61
+#define CLK_MOUT_SCLK_AUDIO1           62
+#define CLK_MOUT_SCLK_AUDIO0           63
+#define CLK_MOUT_SCLK_HDMI_SPDIF       64
+
+#define CLK_DIV_ACLK_FSYS_200          100
+#define CLK_DIV_ACLK_IMEM_SSSX_266     101
+#define CLK_DIV_ACLK_IMEM_200          102
+#define CLK_DIV_ACLK_IMEM_266          103
+#define CLK_DIV_ACLK_PERIC_66_B                104
+#define CLK_DIV_ACLK_PERIC_66_A                105
+#define CLK_DIV_ACLK_PERIS_66_B                106
+#define CLK_DIV_ACLK_PERIS_66_A                107
+#define CLK_DIV_SCLK_MMC1_B            108
+#define CLK_DIV_SCLK_MMC1_A            109
+#define CLK_DIV_SCLK_MMC0_B            110
+#define CLK_DIV_SCLK_MMC0_A            111
+#define CLK_DIV_SCLK_MMC2_B            112
+#define CLK_DIV_SCLK_MMC2_A            113
+#define CLK_DIV_SCLK_SPI1_B            114
+#define CLK_DIV_SCLK_SPI1_A            115
+#define CLK_DIV_SCLK_SPI0_B            116
+#define CLK_DIV_SCLK_SPI0_A            117
+#define CLK_DIV_SCLK_SPI2_B            118
+#define CLK_DIV_SCLK_SPI2_A            119
+#define CLK_DIV_SCLK_UART2             120
+#define CLK_DIV_SCLK_UART1             121
+#define CLK_DIV_SCLK_UART0             122
+#define CLK_DIV_SCLK_SPI4_B            123
+#define CLK_DIV_SCLK_SPI4_A            124
+#define CLK_DIV_SCLK_SPI3_B            125
+#define CLK_DIV_SCLK_SPI3_A            126
+#define CLK_DIV_SCLK_I2S1              127
+#define CLK_DIV_SCLK_PCM1              128
+#define CLK_DIV_SCLK_AUDIO1            129
+#define CLK_DIV_SCLK_AUDIO0            130
+#define CLK_DIV_ACLK_GSCL_111          131
+#define CLK_DIV_ACLK_GSCL_333          132
+#define CLK_DIV_ACLK_HEVC_400          133
+#define CLK_DIV_ACLK_MFC_400           134
+#define CLK_DIV_ACLK_G2D_266           135
+#define CLK_DIV_ACLK_G2D_400           136
+#define CLK_DIV_ACLK_G3D_400           137
+#define CLK_DIV_ACLK_BUS0_400          138
+#define CLK_DIV_ACLK_BUS1_400          139
+#define CLK_DIV_SCLK_PCIE_100          140
+#define CLK_DIV_SCLK_USBHOST30         141
+#define CLK_DIV_SCLK_UFSUNIPRO         142
+#define CLK_DIV_SCLK_USBDRD30          143
+#define CLK_DIV_SCLK_JPEG              144
+#define CLK_DIV_ACLK_MSCL_400          145
+#define CLK_DIV_ACLK_ISP_DIS_400       146
+#define CLK_DIV_ACLK_ISP_400           147
+#define CLK_DIV_ACLK_CAM0_333          148
+#define CLK_DIV_ACLK_CAM0_400          149
+#define CLK_DIV_ACLK_CAM0_552          150
+#define CLK_DIV_ACLK_CAM1_333          151
+#define CLK_DIV_ACLK_CAM1_400          152
+#define CLK_DIV_ACLK_CAM1_552          153
+#define CLK_DIV_SCLK_ISP_UART          154
+#define CLK_DIV_SCLK_ISP_SPI1_B                155
+#define CLK_DIV_SCLK_ISP_SPI1_A                156
+#define CLK_DIV_SCLK_ISP_SPI0_B                157
+#define CLK_DIV_SCLK_ISP_SPI0_A                158
+#define CLK_DIV_SCLK_ISP_SENSOR2_B     159
+#define CLK_DIV_SCLK_ISP_SENSOR2_A     160
+#define CLK_DIV_SCLK_ISP_SENSOR1_B     161
+#define CLK_DIV_SCLK_ISP_SENSOR1_A     162
+#define CLK_DIV_SCLK_ISP_SENSOR0_B     163
+#define CLK_DIV_SCLK_ISP_SENSOR0_A     164
+
+#define CLK_ACLK_PERIC_66              200
+#define CLK_ACLK_PERIS_66              201
+#define CLK_ACLK_FSYS_200              202
+#define CLK_SCLK_MMC2_FSYS             203
+#define CLK_SCLK_MMC1_FSYS             204
+#define CLK_SCLK_MMC0_FSYS             205
+#define CLK_SCLK_SPI4_PERIC            206
+#define CLK_SCLK_SPI3_PERIC            207
+#define CLK_SCLK_UART2_PERIC           208
+#define CLK_SCLK_UART1_PERIC           209
+#define CLK_SCLK_UART0_PERIC           210
+#define CLK_SCLK_SPI2_PERIC            211
+#define CLK_SCLK_SPI1_PERIC            212
+#define CLK_SCLK_SPI0_PERIC            213
+#define CLK_SCLK_SPDIF_PERIC           214
+#define CLK_SCLK_I2S1_PERIC            215
+#define CLK_SCLK_PCM1_PERIC            216
+#define CLK_SCLK_SLIMBUS               217
+#define CLK_SCLK_AUDIO1                        218
+#define CLK_SCLK_AUDIO0                        219
+#define CLK_ACLK_G2D_266               220
+#define CLK_ACLK_G2D_400               221
+#define CLK_ACLK_G3D_400               222
+#define CLK_ACLK_IMEM_SSX_266          223
+#define CLK_ACLK_BUS0_400              224
+#define CLK_ACLK_BUS1_400              225
+#define CLK_ACLK_IMEM_200              226
+#define CLK_ACLK_IMEM_266              227
+#define CLK_SCLK_PCIE_100_FSYS         228
+#define CLK_SCLK_UFSUNIPRO_FSYS                229
+#define CLK_SCLK_USBHOST30_FSYS                230
+#define CLK_SCLK_USBDRD30_FSYS         231
+#define CLK_ACLK_GSCL_111              232
+#define CLK_ACLK_GSCL_333              233
+#define CLK_SCLK_JPEG_MSCL             234
+#define CLK_ACLK_MSCL_400              235
+#define CLK_ACLK_MFC_400               236
+#define CLK_ACLK_HEVC_400              237
+#define CLK_ACLK_ISP_DIS_400           238
+#define CLK_ACLK_ISP_400               239
+#define CLK_ACLK_CAM0_333              240
+#define CLK_ACLK_CAM0_400              241
+#define CLK_ACLK_CAM0_552              242
+#define CLK_ACLK_CAM1_333              243
+#define CLK_ACLK_CAM1_400              244
+#define CLK_ACLK_CAM1_552              245
+#define CLK_SCLK_ISP_SENSOR2           246
+#define CLK_SCLK_ISP_SENSOR1           247
+#define CLK_SCLK_ISP_SENSOR0           248
+#define CLK_SCLK_ISP_MCTADC_CAM1       249
+#define CLK_SCLK_ISP_UART_CAM1         250
+#define CLK_SCLK_ISP_SPI1_CAM1         251
+#define CLK_SCLK_ISP_SPI0_CAM1         252
+#define CLK_SCLK_HDMI_SPDIF_DISP       253
+
+#define TOP_NR_CLK                     254
+
+/* CMU_CPIF */
+#define CLK_FOUT_MPHY_PLL              1
+
+#define CLK_MOUT_MPHY_PLL              2
+
+#define CLK_DIV_SCLK_MPHY              10
+
+#define CLK_SCLK_MPHY_PLL              11
+#define CLK_SCLK_UFS_MPHY              11
+
+#define CPIF_NR_CLK                    12
+
+/* CMU_MIF */
+#define CLK_FOUT_MEM0_PLL              1
+#define CLK_FOUT_MEM1_PLL              2
+#define CLK_FOUT_BUS_PLL               3
+#define CLK_FOUT_MFC_PLL               4
+#define CLK_DOUT_MFC_PLL               5
+#define CLK_DOUT_BUS_PLL               6
+#define CLK_DOUT_MEM1_PLL              7
+#define CLK_DOUT_MEM0_PLL              8
+
+#define CLK_MOUT_MFC_PLL_DIV2          10
+#define CLK_MOUT_BUS_PLL_DIV2          11
+#define CLK_MOUT_MEM1_PLL_DIV2         12
+#define CLK_MOUT_MEM0_PLL_DIV2         13
+#define CLK_MOUT_MFC_PLL               14
+#define CLK_MOUT_BUS_PLL               15
+#define CLK_MOUT_MEM1_PLL              16
+#define CLK_MOUT_MEM0_PLL              17
+#define CLK_MOUT_CLK2X_PHY_C           18
+#define CLK_MOUT_CLK2X_PHY_B           19
+#define CLK_MOUT_CLK2X_PHY_A           20
+#define CLK_MOUT_CLKM_PHY_C            21
+#define CLK_MOUT_CLKM_PHY_B            22
+#define CLK_MOUT_CLKM_PHY_A            23
+#define CLK_MOUT_ACLK_MIFNM_200                24
+#define CLK_MOUT_ACLK_MIFNM_400                25
+#define CLK_MOUT_ACLK_DISP_333_B       26
+#define CLK_MOUT_ACLK_DISP_333_A       27
+#define CLK_MOUT_SCLK_DECON_VCLK_C     28
+#define CLK_MOUT_SCLK_DECON_VCLK_B     29
+#define CLK_MOUT_SCLK_DECON_VCLK_A     30
+#define CLK_MOUT_SCLK_DECON_ECLK_C     31
+#define CLK_MOUT_SCLK_DECON_ECLK_B     32
+#define CLK_MOUT_SCLK_DECON_ECLK_A     33
+#define CLK_MOUT_SCLK_DECON_TV_ECLK_C  34
+#define CLK_MOUT_SCLK_DECON_TV_ECLK_B  35
+#define CLK_MOUT_SCLK_DECON_TV_ECLK_A  36
+#define CLK_MOUT_SCLK_DSD_C            37
+#define CLK_MOUT_SCLK_DSD_B            38
+#define CLK_MOUT_SCLK_DSD_A            39
+#define CLK_MOUT_SCLK_DSIM0_C          40
+#define CLK_MOUT_SCLK_DSIM0_B          41
+#define CLK_MOUT_SCLK_DSIM0_A          42
+#define CLK_MOUT_SCLK_DECON_TV_VCLK_C  46
+#define CLK_MOUT_SCLK_DECON_TV_VCLK_B  47
+#define CLK_MOUT_SCLK_DECON_TV_VCLK_A  48
+#define CLK_MOUT_SCLK_DSIM1_C          49
+#define CLK_MOUT_SCLK_DSIM1_B          50
+#define CLK_MOUT_SCLK_DSIM1_A          51
+
+#define CLK_DIV_SCLK_HPM_MIF           55
+#define CLK_DIV_ACLK_DREX1             56
+#define CLK_DIV_ACLK_DREX0             57
+#define CLK_DIV_CLK2XPHY               58
+#define CLK_DIV_ACLK_MIF_266           59
+#define CLK_DIV_ACLK_MIFND_133         60
+#define CLK_DIV_ACLK_MIF_133           61
+#define CLK_DIV_ACLK_MIFNM_200         62
+#define CLK_DIV_ACLK_MIF_200           63
+#define CLK_DIV_ACLK_MIF_400           64
+#define CLK_DIV_ACLK_BUS2_400          65
+#define CLK_DIV_ACLK_DISP_333          66
+#define CLK_DIV_ACLK_CPIF_200          67
+#define CLK_DIV_SCLK_DSIM1             68
+#define CLK_DIV_SCLK_DECON_TV_VCLK     69
+#define CLK_DIV_SCLK_DSIM0             70
+#define CLK_DIV_SCLK_DSD               71
+#define CLK_DIV_SCLK_DECON_TV_ECLK     72
+#define CLK_DIV_SCLK_DECON_VCLK                73
+#define CLK_DIV_SCLK_DECON_ECLK                74
+#define CLK_DIV_MIF_PRE                        75
+
+#define CLK_CLK2X_PHY1                 80
+#define CLK_CLK2X_PHY0                 81
+#define CLK_CLKM_PHY1                  82
+#define CLK_CLKM_PHY0                  83
+#define CLK_RCLK_DREX1                 84
+#define CLK_RCLK_DREX0                 85
+#define CLK_ACLK_DREX1_TZ              86
+#define CLK_ACLK_DREX0_TZ              87
+#define CLK_ACLK_DREX1_PEREV           88
+#define CLK_ACLK_DREX0_PEREV           89
+#define CLK_ACLK_DREX1_MEMIF           90
+#define CLK_ACLK_DREX0_MEMIF           91
+#define CLK_ACLK_DREX1_SCH             92
+#define CLK_ACLK_DREX0_SCH             93
+#define CLK_ACLK_DREX1_BUSIF           94
+#define CLK_ACLK_DREX0_BUSIF           95
+#define CLK_ACLK_DREX1_BUSIF_RD                96
+#define CLK_ACLK_DREX0_BUSIF_RD                97
+#define CLK_ACLK_DREX1                 98
+#define CLK_ACLK_DREX0                 99
+#define CLK_ACLK_ASYNCAXIM_ATLAS_CCIX  100
+#define CLK_ACLK_ASYNCAXIS_ATLAS_MIF   101
+#define CLK_ACLK_ASYNCAXIM_ATLAS_MIF   102
+#define CLK_ACLK_ASYNCAXIS_MIF_IMEM    103
+#define CLK_ACLK_ASYNCAXIS_NOC_P_CCI   104
+#define CLK_ACLK_ASYNCAXIM_NOC_P_CCI   105
+#define CLK_ACLK_ASYNCAXIS_CP1         106
+#define CLK_ACLK_ASYNCAXIM_CP1         107
+#define CLK_ACLK_ASYNCAXIS_CP0         108
+#define CLK_ACLK_ASYNCAXIM_CP0         109
+#define CLK_ACLK_ASYNCAXIS_DREX1_3     110
+#define CLK_ACLK_ASYNCAXIM_DREX1_3     111
+#define CLK_ACLK_ASYNCAXIS_DREX1_1     112
+#define CLK_ACLK_ASYNCAXIM_DREX1_1     113
+#define CLK_ACLK_ASYNCAXIS_DREX1_0     114
+#define CLK_ACLK_ASYNCAXIM_DREX1_0     115
+#define CLK_ACLK_ASYNCAXIS_DREX0_3     116
+#define CLK_ACLK_ASYNCAXIM_DREX0_3     117
+#define CLK_ACLK_ASYNCAXIS_DREX0_1     118
+#define CLK_ACLK_ASYNCAXIM_DREX0_1     119
+#define CLK_ACLK_ASYNCAXIS_DREX0_0     120
+#define CLK_ACLK_ASYNCAXIM_DREX0_0     121
+#define CLK_ACLK_AHB2APB_MIF2P         122
+#define CLK_ACLK_AHB2APB_MIF1P         123
+#define CLK_ACLK_AHB2APB_MIF0P         124
+#define CLK_ACLK_IXIU_CCI              125
+#define CLK_ACLK_XIU_MIFSFRX           126
+#define CLK_ACLK_MIFNP_133             127
+#define CLK_ACLK_MIFNM_200             128
+#define CLK_ACLK_MIFND_133             129
+#define CLK_ACLK_MIFND_400             130
+#define CLK_ACLK_CCI                   131
+#define CLK_ACLK_MIFND_266             132
+#define CLK_ACLK_PPMU_DREX1S3          133
+#define CLK_ACLK_PPMU_DREX1S1          134
+#define CLK_ACLK_PPMU_DREX1S0          135
+#define CLK_ACLK_PPMU_DREX0S3          136
+#define CLK_ACLK_PPMU_DREX0S1          137
+#define CLK_ACLK_PPMU_DREX0S0          138
+#define CLK_ACLK_BTS_APOLLO            139
+#define CLK_ACLK_BTS_ATLAS             140
+#define CLK_ACLK_ACE_SEL_APOLL         141
+#define CLK_ACLK_ACE_SEL_ATLAS         142
+#define CLK_ACLK_AXIDS_CCI_MIFSFRX     143
+#define CLK_ACLK_AXIUS_ATLAS_CCI       144
+#define CLK_ACLK_AXISYNCDNS_CCI                145
+#define CLK_ACLK_AXISYNCDN_CCI         146
+#define CLK_ACLK_AXISYNCDN_NOC_D       147
+#define CLK_ACLK_ASYNCACEM_APOLLO_CCI  148
+#define CLK_ACLK_ASYNCACEM_ATLAS_CCI   149
+#define CLK_ACLK_ASYNCAPBS_MIF_CSSYS   150
+#define CLK_ACLK_BUS2_400              151
+#define CLK_ACLK_DISP_333              152
+#define CLK_ACLK_CPIF_200              153
+#define CLK_PCLK_PPMU_DREX1S3          154
+#define CLK_PCLK_PPMU_DREX1S1          155
+#define CLK_PCLK_PPMU_DREX1S0          156
+#define CLK_PCLK_PPMU_DREX0S3          157
+#define CLK_PCLK_PPMU_DREX0S1          158
+#define CLK_PCLK_PPMU_DREX0S0          159
+#define CLK_PCLK_BTS_APOLLO            160
+#define CLK_PCLK_BTS_ATLAS             161
+#define CLK_PCLK_ASYNCAXI_NOC_P_CCI    162
+#define CLK_PCLK_ASYNCAXI_CP1          163
+#define CLK_PCLK_ASYNCAXI_CP0          164
+#define CLK_PCLK_ASYNCAXI_DREX1_3      165
+#define CLK_PCLK_ASYNCAXI_DREX1_1      166
+#define CLK_PCLK_ASYNCAXI_DREX1_0      167
+#define CLK_PCLK_ASYNCAXI_DREX0_3      168
+#define CLK_PCLK_ASYNCAXI_DREX0_1      169
+#define CLK_PCLK_ASYNCAXI_DREX0_0      170
+#define CLK_PCLK_MIFSRVND_133          171
+#define CLK_PCLK_PMU_MIF               172
+#define CLK_PCLK_SYSREG_MIF            173
+#define CLK_PCLK_GPIO_ALIVE            174
+#define CLK_PCLK_ABB                   175
+#define CLK_PCLK_PMU_APBIF             176
+#define CLK_PCLK_DDR_PHY1              177
+#define CLK_PCLK_DREX1                 178
+#define CLK_PCLK_DDR_PHY0              179
+#define CLK_PCLK_DREX0                 180
+#define CLK_PCLK_DREX0_TZ              181
+#define CLK_PCLK_DREX1_TZ              182
+#define CLK_PCLK_MONOTONIC_CNT         183
+#define CLK_PCLK_RTC                   184
+#define CLK_SCLK_DSIM1_DISP            185
+#define CLK_SCLK_DECON_TV_VCLK_DISP    186
+#define CLK_SCLK_FREQ_DET_BUS_PLL      187
+#define CLK_SCLK_FREQ_DET_MFC_PLL      188
+#define CLK_SCLK_FREQ_DET_MEM0_PLL     189
+#define CLK_SCLK_FREQ_DET_MEM1_PLL     190
+#define CLK_SCLK_DSIM0_DISP            191
+#define CLK_SCLK_DSD_DISP              192
+#define CLK_SCLK_DECON_TV_ECLK_DISP    193
+#define CLK_SCLK_DECON_VCLK_DISP       194
+#define CLK_SCLK_DECON_ECLK_DISP       195
+#define CLK_SCLK_HPM_MIF               196
+#define CLK_SCLK_MFC_PLL               197
+#define CLK_SCLK_BUS_PLL               198
+#define CLK_SCLK_BUS_PLL_APOLLO                199
+#define CLK_SCLK_BUS_PLL_ATLAS         200
+
+#define MIF_NR_CLK                     201
+
+/* CMU_PERIC */
+#define CLK_PCLK_SPI2                  1
+#define CLK_PCLK_SPI1                  2
+#define CLK_PCLK_SPI0                  3
+#define CLK_PCLK_UART2                 4
+#define CLK_PCLK_UART1                 5
+#define CLK_PCLK_UART0                 6
+#define CLK_PCLK_HSI2C3                        7
+#define CLK_PCLK_HSI2C2                        8
+#define CLK_PCLK_HSI2C1                        9
+#define CLK_PCLK_HSI2C0                        10
+#define CLK_PCLK_I2C7                  11
+#define CLK_PCLK_I2C6                  12
+#define CLK_PCLK_I2C5                  13
+#define CLK_PCLK_I2C4                  14
+#define CLK_PCLK_I2C3                  15
+#define CLK_PCLK_I2C2                  16
+#define CLK_PCLK_I2C1                  17
+#define CLK_PCLK_I2C0                  18
+#define CLK_PCLK_SPI4                  19
+#define CLK_PCLK_SPI3                  20
+#define CLK_PCLK_HSI2C11               21
+#define CLK_PCLK_HSI2C10               22
+#define CLK_PCLK_HSI2C9                        23
+#define CLK_PCLK_HSI2C8                        24
+#define CLK_PCLK_HSI2C7                        25
+#define CLK_PCLK_HSI2C6                        26
+#define CLK_PCLK_HSI2C5                        27
+#define CLK_PCLK_HSI2C4                        28
+#define CLK_SCLK_SPI4                  29
+#define CLK_SCLK_SPI3                  30
+#define CLK_SCLK_SPI2                  31
+#define CLK_SCLK_SPI1                  32
+#define CLK_SCLK_SPI0                  33
+#define CLK_SCLK_UART2                 34
+#define CLK_SCLK_UART1                 35
+#define CLK_SCLK_UART0                 36
+#define CLK_ACLK_AHB2APB_PERIC2P       37
+#define CLK_ACLK_AHB2APB_PERIC1P       38
+#define CLK_ACLK_AHB2APB_PERIC0P       39
+#define CLK_ACLK_PERICNP_66            40
+#define CLK_PCLK_SCI                   41
+#define CLK_PCLK_GPIO_FINGER           42
+#define CLK_PCLK_GPIO_ESE              43
+#define CLK_PCLK_PWM                   44
+#define CLK_PCLK_SPDIF                 45
+#define CLK_PCLK_PCM1                  46
+#define CLK_PCLK_I2S1                  47
+#define CLK_PCLK_ADCIF                 48
+#define CLK_PCLK_GPIO_TOUCH            49
+#define CLK_PCLK_GPIO_NFC              50
+#define CLK_PCLK_GPIO_PERIC            51
+#define CLK_PCLK_PMU_PERIC             52
+#define CLK_PCLK_SYSREG_PERIC          53
+#define CLK_SCLK_IOCLK_SPI4            54
+#define CLK_SCLK_IOCLK_SPI3            55
+#define CLK_SCLK_SCI                   56
+#define CLK_SCLK_SC_IN                 57
+#define CLK_SCLK_PWM                   58
+#define CLK_SCLK_IOCLK_SPI2            59
+#define CLK_SCLK_IOCLK_SPI1            60
+#define CLK_SCLK_IOCLK_SPI0            61
+#define CLK_SCLK_IOCLK_I2S1_BCLK       62
+#define CLK_SCLK_SPDIF                 63
+#define CLK_SCLK_PCM1                  64
+#define CLK_SCLK_I2S1                  65
+
+#define CLK_DIV_SCLK_SCI               70
+#define CLK_DIV_SCLK_SC_IN             71
+
+#define PERIC_NR_CLK                   72
+
+/* CMU_PERIS */
+#define CLK_PCLK_HPM_APBIF             1
+#define CLK_PCLK_TMU1_APBIF            2
+#define CLK_PCLK_TMU0_APBIF            3
+#define CLK_PCLK_PMU_PERIS             4
+#define CLK_PCLK_SYSREG_PERIS          5
+#define CLK_PCLK_CMU_TOP_APBIF         6
+#define CLK_PCLK_WDT_APOLLO            7
+#define CLK_PCLK_WDT_ATLAS             8
+#define CLK_PCLK_MCT                   9
+#define CLK_PCLK_HDMI_CEC              10
+#define CLK_ACLK_AHB2APB_PERIS1P       11
+#define CLK_ACLK_AHB2APB_PERIS0P       12
+#define CLK_ACLK_PERISNP_66            13
+#define CLK_PCLK_TZPC12                        14
+#define CLK_PCLK_TZPC11                        15
+#define CLK_PCLK_TZPC10                        16
+#define CLK_PCLK_TZPC9                 17
+#define CLK_PCLK_TZPC8                 18
+#define CLK_PCLK_TZPC7                 19
+#define CLK_PCLK_TZPC6                 20
+#define CLK_PCLK_TZPC5                 21
+#define CLK_PCLK_TZPC4                 22
+#define CLK_PCLK_TZPC3                 23
+#define CLK_PCLK_TZPC2                 24
+#define CLK_PCLK_TZPC1                 25
+#define CLK_PCLK_TZPC0                 26
+#define CLK_PCLK_SECKEY_APBIF          27
+#define CLK_PCLK_CHIPID_APBIF          28
+#define CLK_PCLK_TOPRTC                        29
+#define CLK_PCLK_CUSTOM_EFUSE_APBIF    30
+#define CLK_PCLK_ANTIRBK_CNT_APBIF     31
+#define CLK_PCLK_OTP_CON_APBIF         32
+#define CLK_SCLK_ASV_TB                        33
+#define CLK_SCLK_TMU1                  34
+#define CLK_SCLK_TMU0                  35
+#define CLK_SCLK_SECKEY                        36
+#define CLK_SCLK_CHIPID                        37
+#define CLK_SCLK_TOPRTC                        38
+#define CLK_SCLK_CUSTOM_EFUSE          39
+#define CLK_SCLK_ANTIRBK_CNT           40
+#define CLK_SCLK_OTP_CON               41
+
+#define PERIS_NR_CLK                   42
+
+/* CMU_FSYS */
+#define CLK_MOUT_ACLK_FSYS_200_USER    1
+#define CLK_MOUT_SCLK_MMC2_USER                2
+#define CLK_MOUT_SCLK_MMC1_USER                3
+#define CLK_MOUT_SCLK_MMC0_USER                4
+#define CLK_MOUT_SCLK_UFS_MPHY_USER    5
+#define CLK_MOUT_SCLK_PCIE_100_USER    6
+#define CLK_MOUT_SCLK_UFSUNIPRO_USER   7
+#define CLK_MOUT_SCLK_USBHOST30_USER   8
+#define CLK_MOUT_SCLK_USBDRD30_USER    9
+#define CLK_MOUT_PHYCLK_USBHOST30_UHOST30_PIPE_PCLK_USER       10
+#define CLK_MOUT_PHYCLK_USBHOST30_UHOST30_PHYCLOCK_USER                11
+#define CLK_MOUT_PHYCLK_USBHOST20_PHY_HSIC1_USER               12
+#define CLK_MOUT_PHYCLK_USBHOST20_PHY_CLK48MOHCI_USER          13
+#define CLK_MOUT_PHYCLK_USBHOST20_PHY_PHYCLOCK_USER            14
+#define CLK_MOUT_PHYCLK_USBHOST20_PHY_PHY_FREECLK_USER         15
+#define CLK_MOUT_PHYCLK_USBDRD30_UDRD30_PIPE_PCLK_USER         16
+#define CLK_MOUT_PHYCLK_USBDRD30_UDRD30_PHYCLOCK_USER          17
+#define CLK_MOUT_PHYCLK_UFS_RX1_SYMBOL_USER                    18
+#define CLK_MOUT_PHYCLK_UFS_RX0_SYMBOL_USER                    19
+#define CLK_MOUT_PHYCLK_UFS_TX1_SYMBOL_USER                    20
+#define CLK_MOUT_PHYCLK_UFS_TX0_SYMBOL_USER                    21
+#define CLK_MOUT_PHYCLK_LLI_MPHY_TO_UFS_USER                   22
+#define CLK_MOUT_SCLK_MPHY                                     23
+
+#define CLK_PHYCLK_USBDRD30_UDRD30_PHYCLOCK_PHY                        25
+#define CLK_PHYCLK_USBDRD30_UDRD30_PIPE_PCLK_PHY               26
+#define CLK_PHYCLK_USBHOST30_UHOST30_PHYCLOCK_PHY              27
+#define CLK_PHYCLK_USBHOST30_UHOST30_PIPE_PCLK_PHY             28
+#define CLK_PHYCLK_USBHOST20_PHY_FREECLK_PHY                   29
+#define CLK_PHYCLK_USBHOST20_PHY_PHYCLOCK_PHY                  30
+#define CLK_PHYCLK_USBHOST20_PHY_CLK48MOHCI_PHY                        31
+#define CLK_PHYCLK_USBHOST20_PHY_HSIC1_PHY                     32
+#define CLK_PHYCLK_UFS_TX0_SYMBOL_PHY                          33
+#define CLK_PHYCLK_UFS_RX0_SYMBOL_PHY                          34
+#define CLK_PHYCLK_UFS_TX1_SYMBOL_PHY                          35
+#define CLK_PHYCLK_UFS_RX1_SYMBOL_PHY                          36
+#define CLK_PHYCLK_LLI_MPHY_TO_UFS_PHY                         37
+
+#define CLK_ACLK_PCIE                  50
+#define CLK_ACLK_PDMA1                 51
+#define CLK_ACLK_TSI                   52
+#define CLK_ACLK_MMC2                  53
+#define CLK_ACLK_MMC1                  54
+#define CLK_ACLK_MMC0                  55
+#define CLK_ACLK_UFS                   56
+#define CLK_ACLK_USBHOST20             57
+#define CLK_ACLK_USBHOST30             58
+#define CLK_ACLK_USBDRD30              59
+#define CLK_ACLK_PDMA0                 60
+#define CLK_SCLK_MMC2                  61
+#define CLK_SCLK_MMC1                  62
+#define CLK_SCLK_MMC0                  63
+#define CLK_PDMA1                      64
+#define CLK_PDMA0                      65
+#define CLK_ACLK_XIU_FSYSPX            66
+#define CLK_ACLK_AHB_USBLINKH1         67
+#define CLK_ACLK_SMMU_PDMA1            68
+#define CLK_ACLK_BTS_PCIE              69
+#define CLK_ACLK_AXIUS_PDMA1           70
+#define CLK_ACLK_SMMU_PDMA0            71
+#define CLK_ACLK_BTS_UFS               72
+#define CLK_ACLK_BTS_USBHOST30         73
+#define CLK_ACLK_BTS_USBDRD30          74
+#define CLK_ACLK_AXIUS_PDMA0           75
+#define CLK_ACLK_AXIUS_USBHS           76
+#define CLK_ACLK_AXIUS_FSYSSX          77
+#define CLK_ACLK_AHB2APB_FSYSP         78
+#define CLK_ACLK_AHB2AXI_USBHS         79
+#define CLK_ACLK_AHB_USBLINKH0         80
+#define CLK_ACLK_AHB_USBHS             81
+#define CLK_ACLK_AHB_FSYSH             82
+#define CLK_ACLK_XIU_FSYSX             83
+#define CLK_ACLK_XIU_FSYSSX            84
+#define CLK_ACLK_FSYSNP_200            85
+#define CLK_ACLK_FSYSND_200            86
+#define CLK_PCLK_PCIE_CTRL             87
+#define CLK_PCLK_SMMU_PDMA1            88
+#define CLK_PCLK_PCIE_PHY              89
+#define CLK_PCLK_BTS_PCIE              90
+#define CLK_PCLK_SMMU_PDMA0            91
+#define CLK_PCLK_BTS_UFS               92
+#define CLK_PCLK_BTS_USBHOST30         93
+#define CLK_PCLK_BTS_USBDRD30          94
+#define CLK_PCLK_GPIO_FSYS             95
+#define CLK_PCLK_PMU_FSYS              96
+#define CLK_PCLK_SYSREG_FSYS           97
+#define CLK_SCLK_PCIE_100              98
+#define CLK_PHYCLK_USBHOST30_UHOST30_PIPE_PCLK 99
+#define CLK_PHYCLK_USBHOST30_UHOST30_PHYCLOCK  100
+#define CLK_PHYCLK_UFS_RX1_SYMBOL              101
+#define CLK_PHYCLK_UFS_RX0_SYMBOL              102
+#define CLK_PHYCLK_UFS_TX1_SYMBOL              103
+#define CLK_PHYCLK_UFS_TX0_SYMBOL              104
+#define CLK_PHYCLK_USBHOST20_PHY_HSIC1         105
+#define CLK_PHYCLK_USBHOST20_PHY_CLK48MOHCI    106
+#define CLK_PHYCLK_USBHOST20_PHY_PHYCLOCK      107
+#define CLK_PHYCLK_USBHOST20_PHY_FREECLK       108
+#define CLK_PHYCLK_USBDRD30_UDRD30_PIPE_PCLK   109
+#define CLK_PHYCLK_USBDRD30_UDRD30_PHYCLOCK    110
+#define CLK_SCLK_MPHY                  111
+#define CLK_SCLK_UFSUNIPRO             112
+#define CLK_SCLK_USBHOST30             113
+#define CLK_SCLK_USBDRD30              114
+
+#define FSYS_NR_CLK                    115
+
+/* CMU_G2D */
+#define CLK_MUX_ACLK_G2D_266_USER      1
+#define CLK_MUX_ACLK_G2D_400_USER      2
+
+#define CLK_DIV_PCLK_G2D               3
+
+#define CLK_ACLK_SMMU_MDMA1            4
+#define CLK_ACLK_BTS_MDMA1             5
+#define CLK_ACLK_BTS_G2D               6
+#define CLK_ACLK_ALB_G2D               7
+#define CLK_ACLK_AXIUS_G2DX            8
+#define CLK_ACLK_ASYNCAXI_SYSX         9
+#define CLK_ACLK_AHB2APB_G2D1P         10
+#define CLK_ACLK_AHB2APB_G2D0P         11
+#define CLK_ACLK_XIU_G2DX              12
+#define CLK_ACLK_G2DNP_133             13
+#define CLK_ACLK_G2DND_400             14
+#define CLK_ACLK_MDMA1                 15
+#define CLK_ACLK_G2D                   16
+#define CLK_ACLK_SMMU_G2D              17
+#define CLK_PCLK_SMMU_MDMA1            18
+#define CLK_PCLK_BTS_MDMA1             19
+#define CLK_PCLK_BTS_G2D               20
+#define CLK_PCLK_ALB_G2D               21
+#define CLK_PCLK_ASYNCAXI_SYSX         22
+#define CLK_PCLK_PMU_G2D               23
+#define CLK_PCLK_SYSREG_G2D            24
+#define CLK_PCLK_G2D                   25
+#define CLK_PCLK_SMMU_G2D              26
+
+#define G2D_NR_CLK                     27
+
+/* CMU_DISP */
+#define CLK_FOUT_DISP_PLL                              1
+
+#define CLK_MOUT_DISP_PLL                              2
+#define CLK_MOUT_SCLK_DSIM1_USER                       3
+#define CLK_MOUT_SCLK_DSIM0_USER                       4
+#define CLK_MOUT_SCLK_DSD_USER                         5
+#define CLK_MOUT_SCLK_DECON_TV_ECLK_USER               6
+#define CLK_MOUT_SCLK_DECON_VCLK_USER                  7
+#define CLK_MOUT_SCLK_DECON_ECLK_USER                  8
+#define CLK_MOUT_SCLK_DECON_TV_VCLK_USER               9
+#define CLK_MOUT_ACLK_DISP_333_USER                    10
+#define CLK_MOUT_PHYCLK_MIPIDPHY1_BITCLKDIV8_USER      11
+#define CLK_MOUT_PHYCLK_MIPIDPHY1_RXCLKESC0_USER       12
+#define CLK_MOUT_PHYCLK_MIPIDPHY0_BITCLKDIV8_USER      13
+#define CLK_MOUT_PHYCLK_MIPIDPHY0_RXCLKESC0_USER       14
+#define CLK_MOUT_PHYCLK_HDMIPHY_TMDS_CLKO_USER         15
+#define CLK_MOUT_PHYCLK_HDMIPHY_PIXEL_CLKO_USER                16
+#define CLK_MOUT_SCLK_DSIM0                            17
+#define CLK_MOUT_SCLK_DECON_TV_ECLK                    18
+#define CLK_MOUT_SCLK_DECON_VCLK                       19
+#define CLK_MOUT_SCLK_DECON_ECLK                       20
+#define CLK_MOUT_SCLK_DSIM1_B_DISP                     21
+#define CLK_MOUT_SCLK_DSIM1_A_DISP                     22
+#define CLK_MOUT_SCLK_DECON_TV_VCLK_C_DISP             23
+#define CLK_MOUT_SCLK_DECON_TV_VCLK_B_DISP             24
+#define CLK_MOUT_SCLK_DECON_TV_VCLK_A_DISP             25
+
+#define CLK_DIV_SCLK_DSIM1_DISP                                30
+#define CLK_DIV_SCLK_DECON_TV_VCLK_DISP                        31
+#define CLK_DIV_SCLK_DSIM0_DISP                                32
+#define CLK_DIV_SCLK_DECON_TV_ECLK_DISP                        33
+#define CLK_DIV_SCLK_DECON_VCLK_DISP                   34
+#define CLK_DIV_SCLK_DECON_ECLK_DISP                   35
+#define CLK_DIV_PCLK_DISP                              36
+
+#define CLK_ACLK_DECON_TV                              40
+#define CLK_ACLK_DECON                                 41
+#define CLK_ACLK_SMMU_TV1X                             42
+#define CLK_ACLK_SMMU_TV0X                             43
+#define CLK_ACLK_SMMU_DECON1X                          44
+#define CLK_ACLK_SMMU_DECON0X                          45
+#define CLK_ACLK_BTS_DECON_TV_M3                       46
+#define CLK_ACLK_BTS_DECON_TV_M2                       47
+#define CLK_ACLK_BTS_DECON_TV_M1                       48
+#define CLK_ACLK_BTS_DECON_TV_M0                       49
+#define CLK_ACLK_BTS_DECON_NM4                         50
+#define CLK_ACLK_BTS_DECON_NM3                         51
+#define CLK_ACLK_BTS_DECON_NM2                         52
+#define CLK_ACLK_BTS_DECON_NM1                         53
+#define CLK_ACLK_BTS_DECON_NM0                         54
+#define CLK_ACLK_AHB2APB_DISPSFR2P                     55
+#define CLK_ACLK_AHB2APB_DISPSFR1P                     56
+#define CLK_ACLK_AHB2APB_DISPSFR0P                     57
+#define CLK_ACLK_AHB_DISPH                             58
+#define CLK_ACLK_XIU_TV1X                              59
+#define CLK_ACLK_XIU_TV0X                              60
+#define CLK_ACLK_XIU_DECON1X                           61
+#define CLK_ACLK_XIU_DECON0X                           62
+#define CLK_ACLK_XIU_DISP1X                            63
+#define CLK_ACLK_XIU_DISPNP_100                                64
+#define CLK_ACLK_DISP1ND_333                           65
+#define CLK_ACLK_DISP0ND_333                           66
+#define CLK_PCLK_SMMU_TV1X                             67
+#define CLK_PCLK_SMMU_TV0X                             68
+#define CLK_PCLK_SMMU_DECON1X                          69
+#define CLK_PCLK_SMMU_DECON0X                          70
+#define CLK_PCLK_BTS_DECON_TV_M3                       71
+#define CLK_PCLK_BTS_DECON_TV_M2                       72
+#define CLK_PCLK_BTS_DECON_TV_M1                       73
+#define CLK_PCLK_BTS_DECON_TV_M0                       74
+#define CLK_PCLK_BTS_DECONM4                           75
+#define CLK_PCLK_BTS_DECONM3                           76
+#define CLK_PCLK_BTS_DECONM2                           77
+#define CLK_PCLK_BTS_DECONM1                           78
+#define CLK_PCLK_BTS_DECONM0                           79
+#define CLK_PCLK_MIC1                                  80
+#define CLK_PCLK_PMU_DISP                              81
+#define CLK_PCLK_SYSREG_DISP                           82
+#define CLK_PCLK_HDMIPHY                               83
+#define CLK_PCLK_HDMI                                  84
+#define CLK_PCLK_MIC0                                  85
+#define CLK_PCLK_DSIM1                                 86
+#define CLK_PCLK_DSIM0                                 87
+#define CLK_PCLK_DECON_TV                              88
+#define CLK_PHYCLK_MIPIDPHY1_BITCLKDIV8                        89
+#define CLK_PHYCLK_MIPIDPHY1_RXCLKESC0                 90
+#define CLK_SCLK_RGB_TV_VCLK_TO_DSIM1                  91
+#define CLK_SCLK_RGB_TV_VCLK_TO_MIC1                   92
+#define CLK_SCLK_DSIM1                                 93
+#define CLK_SCLK_DECON_TV_VCLK                         94
+#define CLK_PHYCLK_MIPIDPHY0_BITCLKDIV8                        95
+#define CLK_PHYCLK_MIPIDPHY0_RXCLKESC0                 96
+#define CLK_PHYCLK_HDMIPHY_TMDS_CLKO                   97
+#define CLK_PHYCLK_HDMI_PIXEL                          98
+#define CLK_SCLK_RGB_VCLK_TO_SMIES                     99
+#define CLK_SCLK_FREQ_DET_DISP_PLL                     100
+#define CLK_SCLK_RGB_VCLK_TO_DSIM0                     101
+#define CLK_SCLK_RGB_VCLK_TO_MIC0                      102
+#define CLK_SCLK_DSD                                   103
+#define CLK_SCLK_HDMI_SPDIF                            104
+#define CLK_SCLK_DSIM0                                 105
+#define CLK_SCLK_DECON_TV_ECLK                         106
+#define CLK_SCLK_DECON_VCLK                            107
+#define CLK_SCLK_DECON_ECLK                            108
+#define CLK_SCLK_RGB_VCLK                              109
+#define CLK_SCLK_RGB_TV_VCLK                           110
+
+#define DISP_NR_CLK                                    111
+
+/* CMU_AUD */
+#define CLK_MOUT_AUD_PLL_USER                          1
+#define CLK_MOUT_SCLK_AUD_PCM                          2
+#define CLK_MOUT_SCLK_AUD_I2S                          3
+
+#define CLK_DIV_ATCLK_AUD                              4
+#define CLK_DIV_PCLK_DBG_AUD                           5
+#define CLK_DIV_ACLK_AUD                               6
+#define CLK_DIV_AUD_CA5                                        7
+#define CLK_DIV_SCLK_AUD_SLIMBUS                       8
+#define CLK_DIV_SCLK_AUD_UART                          9
+#define CLK_DIV_SCLK_AUD_PCM                           10
+#define CLK_DIV_SCLK_AUD_I2S                           11
+
+#define CLK_ACLK_INTR_CTRL                             12
+#define CLK_ACLK_AXIDS2_LPASSP                         13
+#define CLK_ACLK_AXIDS1_LPASSP                         14
+#define CLK_ACLK_AXI2APB1_LPASSP                       15
+#define CLK_ACLK_AXI2APH_LPASSP                                16
+#define CLK_ACLK_SMMU_LPASSX                           17
+#define CLK_ACLK_AXIDS0_LPASSP                         18
+#define CLK_ACLK_AXI2APB0_LPASSP                       19
+#define CLK_ACLK_XIU_LPASSX                            20
+#define CLK_ACLK_AUDNP_133                             21
+#define CLK_ACLK_AUDND_133                             22
+#define CLK_ACLK_SRAMC                                 23
+#define CLK_ACLK_DMAC                                  24
+#define CLK_PCLK_WDT1                                  25
+#define CLK_PCLK_WDT0                                  26
+#define CLK_PCLK_SFR1                                  27
+#define CLK_PCLK_SMMU_LPASSX                           28
+#define CLK_PCLK_GPIO_AUD                              29
+#define CLK_PCLK_PMU_AUD                               30
+#define CLK_PCLK_SYSREG_AUD                            31
+#define CLK_PCLK_AUD_SLIMBUS                           32
+#define CLK_PCLK_AUD_UART                              33
+#define CLK_PCLK_AUD_PCM                               34
+#define CLK_PCLK_AUD_I2S                               35
+#define CLK_PCLK_TIMER                                 36
+#define CLK_PCLK_SFR0_CTRL                             37
+#define CLK_ATCLK_AUD                                  38
+#define CLK_PCLK_DBG_AUD                               39
+#define CLK_SCLK_AUD_CA5                               40
+#define CLK_SCLK_JTAG_TCK                              41
+#define CLK_SCLK_SLIMBUS_CLKIN                         42
+#define CLK_SCLK_AUD_SLIMBUS                           43
+#define CLK_SCLK_AUD_UART                              44
+#define CLK_SCLK_AUD_PCM                               45
+#define CLK_SCLK_I2S_BCLK                              46
+#define CLK_SCLK_AUD_I2S                               47
+
+#define AUD_NR_CLK                                     48
+
+/* CMU_BUS{0|1|2} */
+#define CLK_DIV_PCLK_BUS_133                           1
+
+#define CLK_ACLK_AHB2APB_BUSP                          2
+#define CLK_ACLK_BUSNP_133                             3
+#define CLK_ACLK_BUSND_400                             4
+#define CLK_PCLK_BUSSRVND_133                          5
+#define CLK_PCLK_PMU_BUS                               6
+#define CLK_PCLK_SYSREG_BUS                            7
+
+#define CLK_MOUT_ACLK_BUS2_400_USER                    8  /* Only CMU_BUS2 */
+#define CLK_ACLK_BUS2BEND_400                          9  /* Only CMU_BUS2 */
+#define CLK_ACLK_BUS2RTND_400                          10 /* Only CMU_BUS2 */
+
+#define BUSx_NR_CLK                                    11
+
+/* CMU_G3D */
+#define CLK_FOUT_G3D_PLL                               1
+
+#define CLK_MOUT_ACLK_G3D_400                          2
+#define CLK_MOUT_G3D_PLL                               3
+
+#define CLK_DIV_SCLK_HPM_G3D                           4
+#define CLK_DIV_PCLK_G3D                               5
+#define CLK_DIV_ACLK_G3D                               6
+#define CLK_ACLK_BTS_G3D1                              7
+#define CLK_ACLK_BTS_G3D0                              8
+#define CLK_ACLK_ASYNCAPBS_G3D                         9
+#define CLK_ACLK_ASYNCAPBM_G3D                         10
+#define CLK_ACLK_AHB2APB_G3DP                          11
+#define CLK_ACLK_G3DNP_150                             12
+#define CLK_ACLK_G3DND_600                             13
+#define CLK_ACLK_G3D                                   14
+#define CLK_PCLK_BTS_G3D1                              15
+#define CLK_PCLK_BTS_G3D0                              16
+#define CLK_PCLK_PMU_G3D                               17
+#define CLK_PCLK_SYSREG_G3D                            18
+#define CLK_SCLK_HPM_G3D                               19
+
+#define G3D_NR_CLK                                     20
+
+/* CMU_GSCL */
+#define CLK_MOUT_ACLK_GSCL_111_USER                    1
+#define CLK_MOUT_ACLK_GSCL_333_USER                    2
+
+#define CLK_ACLK_BTS_GSCL2                             3
+#define CLK_ACLK_BTS_GSCL1                             4
+#define CLK_ACLK_BTS_GSCL0                             5
+#define CLK_ACLK_AHB2APB_GSCLP                         6
+#define CLK_ACLK_XIU_GSCLX                             7
+#define CLK_ACLK_GSCLNP_111                            8
+#define CLK_ACLK_GSCLRTND_333                          9
+#define CLK_ACLK_GSCLBEND_333                          10
+#define CLK_ACLK_GSD                                   11
+#define CLK_ACLK_GSCL2                                 12
+#define CLK_ACLK_GSCL1                                 13
+#define CLK_ACLK_GSCL0                                 14
+#define CLK_ACLK_SMMU_GSCL0                            15
+#define CLK_ACLK_SMMU_GSCL1                            16
+#define CLK_ACLK_SMMU_GSCL2                            17
+#define CLK_PCLK_BTS_GSCL2                             18
+#define CLK_PCLK_BTS_GSCL1                             19
+#define CLK_PCLK_BTS_GSCL0                             20
+#define CLK_PCLK_PMU_GSCL                              21
+#define CLK_PCLK_SYSREG_GSCL                           22
+#define CLK_PCLK_GSCL2                                 23
+#define CLK_PCLK_GSCL1                                 24
+#define CLK_PCLK_GSCL0                                 25
+#define CLK_PCLK_SMMU_GSCL0                            26
+#define CLK_PCLK_SMMU_GSCL1                            27
+#define CLK_PCLK_SMMU_GSCL2                            28
+
+#define GSCL_NR_CLK                                    29
+
+/* CMU_APOLLO */
+#define CLK_FOUT_APOLLO_PLL                            1
+
+#define CLK_MOUT_APOLLO_PLL                            2
+#define CLK_MOUT_BUS_PLL_APOLLO_USER                   3
+#define CLK_MOUT_APOLLO                                        4
+
+#define CLK_DIV_CNTCLK_APOLLO                          5
+#define CLK_DIV_PCLK_DBG_APOLLO                                6
+#define CLK_DIV_ATCLK_APOLLO                           7
+#define CLK_DIV_PCLK_APOLLO                            8
+#define CLK_DIV_ACLK_APOLLO                            9
+#define CLK_DIV_APOLLO2                                        10
+#define CLK_DIV_APOLLO1                                        11
+#define CLK_DIV_SCLK_HPM_APOLLO                                12
+#define CLK_DIV_APOLLO_PLL                             13
+
+#define CLK_ACLK_ATBDS_APOLLO_3                                14
+#define CLK_ACLK_ATBDS_APOLLO_2                                15
+#define CLK_ACLK_ATBDS_APOLLO_1                                16
+#define CLK_ACLK_ATBDS_APOLLO_0                                17
+#define CLK_ACLK_ASATBSLV_APOLLO_3_CSSYS               18
+#define CLK_ACLK_ASATBSLV_APOLLO_2_CSSYS               19
+#define CLK_ACLK_ASATBSLV_APOLLO_1_CSSYS               20
+#define CLK_ACLK_ASATBSLV_APOLLO_0_CSSYS               21
+#define CLK_ACLK_ASYNCACES_APOLLO_CCI                  22
+#define CLK_ACLK_AHB2APB_APOLLOP                       23
+#define CLK_ACLK_APOLLONP_200                          24
+#define CLK_PCLK_ASAPBMST_CSSYS_APOLLO                 25
+#define CLK_PCLK_PMU_APOLLO                            26
+#define CLK_PCLK_SYSREG_APOLLO                         27
+#define CLK_CNTCLK_APOLLO                              28
+#define CLK_SCLK_HPM_APOLLO                            29
+#define CLK_SCLK_APOLLO                                        30
+
+#define APOLLO_NR_CLK                                  31
+
+/* CMU_ATLAS */
+#define CLK_FOUT_ATLAS_PLL                             1
+
+#define CLK_MOUT_ATLAS_PLL                             2
+#define CLK_MOUT_BUS_PLL_ATLAS_USER                    3
+#define CLK_MOUT_ATLAS                                 4
+
+#define CLK_DIV_CNTCLK_ATLAS                           5
+#define CLK_DIV_PCLK_DBG_ATLAS                         6
+#define CLK_DIV_ATCLK_ATLASO                           7
+#define CLK_DIV_PCLK_ATLAS                             8
+#define CLK_DIV_ACLK_ATLAS                             9
+#define CLK_DIV_ATLAS2                                 10
+#define CLK_DIV_ATLAS1                                 11
+#define CLK_DIV_SCLK_HPM_ATLAS                         12
+#define CLK_DIV_ATLAS_PLL                              13
+
+#define CLK_ACLK_ATB_AUD_CSSYS                         14
+#define CLK_ACLK_ATB_APOLLO3_CSSYS                     15
+#define CLK_ACLK_ATB_APOLLO2_CSSYS                     16
+#define CLK_ACLK_ATB_APOLLO1_CSSYS                     17
+#define CLK_ACLK_ATB_APOLLO0_CSSYS                     18
+#define CLK_ACLK_ASYNCAHBS_CSSYS_SSS                   19
+#define CLK_ACLK_ASYNCAXIS_CSSYS_CCIX                  20
+#define CLK_ACLK_ASYNCACES_ATLAS_CCI                   21
+#define CLK_ACLK_AHB2APB_ATLASP                                22
+#define CLK_ACLK_ATLASNP_200                           23
+#define CLK_PCLK_ASYNCAPB_AUD_CSSYS                    24
+#define CLK_PCLK_ASYNCAPB_ISP_CSSYS                    25
+#define CLK_PCLK_ASYNCAPB_APOLLO_CSSYS                 26
+#define CLK_PCLK_PMU_ATLAS                             27
+#define CLK_PCLK_SYSREG_ATLAS                          28
+#define CLK_PCLK_SECJTAG                               29
+#define CLK_CNTCLK_ATLAS                               30
+#define CLK_SCLK_FREQ_DET_ATLAS_PLL                    31
+#define CLK_SCLK_HPM_ATLAS                             32
+#define CLK_TRACECLK                                   33
+#define CLK_CTMCLK                                     34
+#define CLK_HCLK_CSSYS                                 35
+#define CLK_PCLK_DBG_CSSYS                             36
+#define CLK_PCLK_DBG                                   37
+#define CLK_ATCLK                                      38
+#define CLK_SCLK_ATLAS                                 39
+
+#define ATLAS_NR_CLK                                   40
+
+/* CMU_MSCL */
+#define CLK_MOUT_SCLK_JPEG_USER                                1
+#define CLK_MOUT_ACLK_MSCL_400_USER                    2
+#define CLK_MOUT_SCLK_JPEG                             3
+
+#define CLK_DIV_PCLK_MSCL                              4
+
+#define CLK_ACLK_BTS_JPEG                              5
+#define CLK_ACLK_BTS_M2MSCALER1                                6
+#define CLK_ACLK_BTS_M2MSCALER0                                7
+#define CLK_ACLK_AHB2APB_MSCL0P                                8
+#define CLK_ACLK_XIU_MSCLX                             9
+#define CLK_ACLK_MSCLNP_100                            10
+#define CLK_ACLK_MSCLND_400                            11
+#define CLK_ACLK_JPEG                                  12
+#define CLK_ACLK_M2MSCALER1                            13
+#define CLK_ACLK_M2MSCALER0                            14
+#define CLK_ACLK_SMMU_M2MSCALER0                       15
+#define CLK_ACLK_SMMU_M2MSCALER1                       16
+#define CLK_ACLK_SMMU_JPEG                             17
+#define CLK_PCLK_BTS_JPEG                              18
+#define CLK_PCLK_BTS_M2MSCALER1                                19
+#define CLK_PCLK_BTS_M2MSCALER0                                20
+#define CLK_PCLK_PMU_MSCL                              21
+#define CLK_PCLK_SYSREG_MSCL                           22
+#define CLK_PCLK_JPEG                                  23
+#define CLK_PCLK_M2MSCALER1                            24
+#define CLK_PCLK_M2MSCALER0                            25
+#define CLK_PCLK_SMMU_M2MSCALER0                       26
+#define CLK_PCLK_SMMU_M2MSCALER1                       27
+#define CLK_PCLK_SMMU_JPEG                             28
+#define CLK_SCLK_JPEG                                  29
+
+#define MSCL_NR_CLK                                    30
+
+/* CMU_MFC */
+#define CLK_MOUT_ACLK_MFC_400_USER                     1
+
+#define CLK_DIV_PCLK_MFC                               2
+
+#define CLK_ACLK_BTS_MFC_1                             3
+#define CLK_ACLK_BTS_MFC_0                             4
+#define CLK_ACLK_AHB2APB_MFCP                          5
+#define CLK_ACLK_XIU_MFCX                              6
+#define CLK_ACLK_MFCNP_100                             7
+#define CLK_ACLK_MFCND_400                             8
+#define CLK_ACLK_MFC                                   9
+#define CLK_ACLK_SMMU_MFC_1                            10
+#define CLK_ACLK_SMMU_MFC_0                            11
+#define CLK_PCLK_BTS_MFC_1                             12
+#define CLK_PCLK_BTS_MFC_0                             13
+#define CLK_PCLK_PMU_MFC                               14
+#define CLK_PCLK_SYSREG_MFC                            15
+#define CLK_PCLK_MFC                                   16
+#define CLK_PCLK_SMMU_MFC_1                            17
+#define CLK_PCLK_SMMU_MFC_0                            18
+
+#define MFC_NR_CLK                                     19
+
+/* CMU_HEVC */
+#define CLK_MOUT_ACLK_HEVC_400_USER                    1
+
+#define CLK_DIV_PCLK_HEVC                              2
+
+#define CLK_ACLK_BTS_HEVC_1                            3
+#define CLK_ACLK_BTS_HEVC_0                            4
+#define CLK_ACLK_AHB2APB_HEVCP                         5
+#define CLK_ACLK_XIU_HEVCX                             6
+#define CLK_ACLK_HEVCNP_100                            7
+#define CLK_ACLK_HEVCND_400                            8
+#define CLK_ACLK_HEVC                                  9
+#define CLK_ACLK_SMMU_HEVC_1                           10
+#define CLK_ACLK_SMMU_HEVC_0                           11
+#define CLK_PCLK_BTS_HEVC_1                            12
+#define CLK_PCLK_BTS_HEVC_0                            13
+#define CLK_PCLK_PMU_HEVC                              14
+#define CLK_PCLK_SYSREG_HEVC                           15
+#define CLK_PCLK_HEVC                                  16
+#define CLK_PCLK_SMMU_HEVC_1                           17
+#define CLK_PCLK_SMMU_HEVC_0                           18
+
+#define HEVC_NR_CLK                                    19
+
+/* CMU_ISP */
+#define CLK_MOUT_ACLK_ISP_DIS_400_USER                 1
+#define CLK_MOUT_ACLK_ISP_400_USER                     2
+
+#define CLK_DIV_PCLK_ISP_DIS                           3
+#define CLK_DIV_PCLK_ISP                               4
+#define CLK_DIV_ACLK_ISP_D_200                         5
+#define CLK_DIV_ACLK_ISP_C_200                         6
+
+#define CLK_ACLK_ISP_D_GLUE                            7
+#define CLK_ACLK_SCALERP                               8
+#define CLK_ACLK_3DNR                                  9
+#define CLK_ACLK_DIS                                   10
+#define CLK_ACLK_SCALERC                               11
+#define CLK_ACLK_DRC                                   12
+#define CLK_ACLK_ISP                                   13
+#define CLK_ACLK_AXIUS_SCALERP                         14
+#define CLK_ACLK_AXIUS_SCALERC                         15
+#define CLK_ACLK_AXIUS_DRC                             16
+#define CLK_ACLK_ASYNCAHBM_ISP2P                       17
+#define CLK_ACLK_ASYNCAHBM_ISP1P                       18
+#define CLK_ACLK_ASYNCAXIS_DIS1                                19
+#define CLK_ACLK_ASYNCAXIS_DIS0                                20
+#define CLK_ACLK_ASYNCAXIM_DIS1                                21
+#define CLK_ACLK_ASYNCAXIM_DIS0                                22
+#define CLK_ACLK_ASYNCAXIM_ISP2P                       23
+#define CLK_ACLK_ASYNCAXIM_ISP1P                       24
+#define CLK_ACLK_AHB2APB_ISP2P                         25
+#define CLK_ACLK_AHB2APB_ISP1P                         26
+#define CLK_ACLK_AXI2APB_ISP2P                         27
+#define CLK_ACLK_AXI2APB_ISP1P                         28
+#define CLK_ACLK_XIU_ISPEX1                            29
+#define CLK_ACLK_XIU_ISPEX0                            30
+#define CLK_ACLK_ISPND_400                             31
+#define CLK_ACLK_SMMU_SCALERP                          32
+#define CLK_ACLK_SMMU_3DNR                             33
+#define CLK_ACLK_SMMU_DIS1                             34
+#define CLK_ACLK_SMMU_DIS0                             35
+#define CLK_ACLK_SMMU_SCALERC                          36
+#define CLK_ACLK_SMMU_DRC                              37
+#define CLK_ACLK_SMMU_ISP                              38
+#define CLK_ACLK_BTS_SCALERP                           39
+#define CLK_ACLK_BTS_3DR                               40
+#define CLK_ACLK_BTS_DIS1                              41
+#define CLK_ACLK_BTS_DIS0                              42
+#define CLK_ACLK_BTS_SCALERC                           43
+#define CLK_ACLK_BTS_DRC                               44
+#define CLK_ACLK_BTS_ISP                               45
+#define CLK_PCLK_SMMU_SCALERP                          46
+#define CLK_PCLK_SMMU_3DNR                             47
+#define CLK_PCLK_SMMU_DIS1                             48
+#define CLK_PCLK_SMMU_DIS0                             49
+#define CLK_PCLK_SMMU_SCALERC                          50
+#define CLK_PCLK_SMMU_DRC                              51
+#define CLK_PCLK_SMMU_ISP                              52
+#define CLK_PCLK_BTS_SCALERP                           53
+#define CLK_PCLK_BTS_3DNR                              54
+#define CLK_PCLK_BTS_DIS1                              55
+#define CLK_PCLK_BTS_DIS0                              56
+#define CLK_PCLK_BTS_SCALERC                           57
+#define CLK_PCLK_BTS_DRC                               58
+#define CLK_PCLK_BTS_ISP                               59
+#define CLK_PCLK_ASYNCAXI_DIS1                         60
+#define CLK_PCLK_ASYNCAXI_DIS0                         61
+#define CLK_PCLK_PMU_ISP                               62
+#define CLK_PCLK_SYSREG_ISP                            63
+#define CLK_PCLK_CMU_ISP_LOCAL                         64
+#define CLK_PCLK_SCALERP                               65
+#define CLK_PCLK_3DNR                                  66
+#define CLK_PCLK_DIS_CORE                              67
+#define CLK_PCLK_DIS                                   68
+#define CLK_PCLK_SCALERC                               69
+#define CLK_PCLK_DRC                                   70
+#define CLK_PCLK_ISP                                   71
+#define CLK_SCLK_PIXELASYNCS_DIS                       72
+#define CLK_SCLK_PIXELASYNCM_DIS                       73
+#define CLK_SCLK_PIXELASYNCS_SCALERP                   74
+#define CLK_SCLK_PIXELASYNCM_ISPD                      75
+#define CLK_SCLK_PIXELASYNCS_ISPC                      76
+#define CLK_SCLK_PIXELASYNCM_ISPC                      77
+
+#define ISP_NR_CLK                                     78
+
+/* CMU_CAM0 */
+#define CLK_PHYCLK_RXBYTEECLKHS0_S4_PHY                        1
+#define CLK_PHYCLK_RXBYTEECLKHS0_S2A_PHY               2
+
+#define CLK_MOUT_ACLK_CAM0_333_USER                    3
+#define CLK_MOUT_ACLK_CAM0_400_USER                    4
+#define CLK_MOUT_ACLK_CAM0_552_USER                    5
+#define CLK_MOUT_PHYCLK_RXBYTECLKHS0_S4_USER           6
+#define CLK_MOUT_PHYCLK_RXBYTECLKHS0_S2A_USER          7
+#define CLK_MOUT_ACLK_LITE_D_B                         8
+#define CLK_MOUT_ACLK_LITE_D_A                         9
+#define CLK_MOUT_ACLK_LITE_B_B                         10
+#define CLK_MOUT_ACLK_LITE_B_A                         11
+#define CLK_MOUT_ACLK_LITE_A_B                         12
+#define CLK_MOUT_ACLK_LITE_A_A                         13
+#define CLK_MOUT_ACLK_CAM0_400                         14
+#define CLK_MOUT_ACLK_CSIS1_B                          15
+#define CLK_MOUT_ACLK_CSIS1_A                          16
+#define CLK_MOUT_ACLK_CSIS0_B                          17
+#define CLK_MOUT_ACLK_CSIS0_A                          18
+#define CLK_MOUT_ACLK_3AA1_B                           19
+#define CLK_MOUT_ACLK_3AA1_A                           20
+#define CLK_MOUT_ACLK_3AA0_B                           21
+#define CLK_MOUT_ACLK_3AA0_A                           22
+#define CLK_MOUT_SCLK_LITE_FREECNT_C                   23
+#define CLK_MOUT_SCLK_LITE_FREECNT_B                   24
+#define CLK_MOUT_SCLK_LITE_FREECNT_A                   25
+#define CLK_MOUT_SCLK_PIXELASYNC_LITE_C_B              26
+#define CLK_MOUT_SCLK_PIXELASYNC_LITE_C_A              27
+#define CLK_MOUT_SCLK_PIXELASYNC_LITE_C_INIT_B         28
+#define CLK_MOUT_SCLK_PIXELASYNC_LITE_C_INIT_A         29
+
+#define CLK_DIV_PCLK_CAM0_50                           30
+#define CLK_DIV_ACLK_CAM0_200                          31
+#define CLK_DIV_ACLK_CAM0_BUS_400                      32
+#define CLK_DIV_PCLK_LITE_D                            33
+#define CLK_DIV_ACLK_LITE_D                            34
+#define CLK_DIV_PCLK_LITE_B                            35
+#define CLK_DIV_ACLK_LITE_B                            36
+#define CLK_DIV_PCLK_LITE_A                            37
+#define CLK_DIV_ACLK_LITE_A                            38
+#define CLK_DIV_ACLK_CSIS1                             39
+#define CLK_DIV_ACLK_CSIS0                             40
+#define CLK_DIV_PCLK_3AA1                              41
+#define CLK_DIV_ACLK_3AA1                              42
+#define CLK_DIV_PCLK_3AA0                              43
+#define CLK_DIV_ACLK_3AA0                              44
+#define CLK_DIV_SCLK_PIXELASYNC_LITE_C                 45
+#define CLK_DIV_PCLK_PIXELASYNC_LITE_C                 46
+#define CLK_DIV_SCLK_PIXELASYNC_LITE_C_INIT            47
+
+#define CLK_ACLK_CSIS1                                 50
+#define CLK_ACLK_CSIS0                                 51
+#define CLK_ACLK_3AA1                                  52
+#define CLK_ACLK_3AA0                                  53
+#define CLK_ACLK_LITE_D                                        54
+#define CLK_ACLK_LITE_B                                        55
+#define CLK_ACLK_LITE_A                                        56
+#define CLK_ACLK_AHBSYNCDN                             57
+#define CLK_ACLK_AXIUS_LITE_D                          58
+#define CLK_ACLK_AXIUS_LITE_B                          59
+#define CLK_ACLK_AXIUS_LITE_A                          60
+#define CLK_ACLK_ASYNCAPBM_3AA1                                61
+#define CLK_ACLK_ASYNCAPBS_3AA1                                62
+#define CLK_ACLK_ASYNCAPBM_3AA0                                63
+#define CLK_ACLK_ASYNCAPBS_3AA0                                64
+#define CLK_ACLK_ASYNCAPBM_LITE_D                      65
+#define CLK_ACLK_ASYNCAPBS_LITE_D                      66
+#define CLK_ACLK_ASYNCAPBM_LITE_B                      67
+#define CLK_ACLK_ASYNCAPBS_LITE_B                      68
+#define CLK_ACLK_ASYNCAPBM_LITE_A                      69
+#define CLK_ACLK_ASYNCAPBS_LITE_A                      70
+#define CLK_ACLK_ASYNCAXIM_ISP0P                       71
+#define CLK_ACLK_ASYNCAXIM_3AA1                                72
+#define CLK_ACLK_ASYNCAXIS_3AA1                                73
+#define CLK_ACLK_ASYNCAXIM_3AA0                                74
+#define CLK_ACLK_ASYNCAXIS_3AA0                                75
+#define CLK_ACLK_ASYNCAXIM_LITE_D                      76
+#define CLK_ACLK_ASYNCAXIS_LITE_D                      77
+#define CLK_ACLK_ASYNCAXIM_LITE_B                      78
+#define CLK_ACLK_ASYNCAXIS_LITE_B                      79
+#define CLK_ACLK_ASYNCAXIM_LITE_A                      80
+#define CLK_ACLK_ASYNCAXIS_LITE_A                      81
+#define CLK_ACLK_AHB2APB_ISPSFRP                       82
+#define CLK_ACLK_AXI2APB_ISP0P                         83
+#define CLK_ACLK_AXI2AHB_ISP0P                         84
+#define CLK_ACLK_XIU_IS0X                              85
+#define CLK_ACLK_XIU_ISP0EX                            86
+#define CLK_ACLK_CAM0NP_276                            87
+#define CLK_ACLK_CAM0ND_400                            88
+#define CLK_ACLK_SMMU_3AA1                             89
+#define CLK_ACLK_SMMU_3AA0                             90
+#define CLK_ACLK_SMMU_LITE_D                           91
+#define CLK_ACLK_SMMU_LITE_B                           92
+#define CLK_ACLK_SMMU_LITE_A                           93
+#define CLK_ACLK_BTS_3AA1                              94
+#define CLK_ACLK_BTS_3AA0                              95
+#define CLK_ACLK_BTS_LITE_D                            96
+#define CLK_ACLK_BTS_LITE_B                            97
+#define CLK_ACLK_BTS_LITE_A                            98
+#define CLK_PCLK_SMMU_3AA1                             99
+#define CLK_PCLK_SMMU_3AA0                             100
+#define CLK_PCLK_SMMU_LITE_D                           101
+#define CLK_PCLK_SMMU_LITE_B                           102
+#define CLK_PCLK_SMMU_LITE_A                           103
+#define CLK_PCLK_BTS_3AA1                              104
+#define CLK_PCLK_BTS_3AA0                              105
+#define CLK_PCLK_BTS_LITE_D                            106
+#define CLK_PCLK_BTS_LITE_B                            107
+#define CLK_PCLK_BTS_LITE_A                            108
+#define CLK_PCLK_ASYNCAXI_CAM1                         109
+#define CLK_PCLK_ASYNCAXI_3AA1                         110
+#define CLK_PCLK_ASYNCAXI_3AA0                         111
+#define CLK_PCLK_ASYNCAXI_LITE_D                       112
+#define CLK_PCLK_ASYNCAXI_LITE_B                       113
+#define CLK_PCLK_ASYNCAXI_LITE_A                       114
+#define CLK_PCLK_PMU_CAM0                              115
+#define CLK_PCLK_SYSREG_CAM0                           116
+#define CLK_PCLK_CMU_CAM0_LOCAL                                117
+#define CLK_PCLK_CSIS1                                 118
+#define CLK_PCLK_CSIS0                                 119
+#define CLK_PCLK_3AA1                                  120
+#define CLK_PCLK_3AA0                                  121
+#define CLK_PCLK_LITE_D                                        122
+#define CLK_PCLK_LITE_B                                        123
+#define CLK_PCLK_LITE_A                                        124
+#define CLK_PHYCLK_RXBYTECLKHS0_S4                     125
+#define CLK_PHYCLK_RXBYTECLKHS0_S2A                    126
+#define CLK_SCLK_LITE_FREECNT                          127
+#define CLK_SCLK_PIXELASYNCM_3AA1                      128
+#define CLK_SCLK_PIXELASYNCM_3AA0                      129
+#define CLK_SCLK_PIXELASYNCS_3AA0                      130
+#define CLK_SCLK_PIXELASYNCM_LITE_C                    131
+#define CLK_SCLK_PIXELASYNCM_LITE_C_INIT               132
+#define CLK_SCLK_PIXELASYNCS_LITE_C_INIT               133
+
+#define CAM0_NR_CLK                                    134
+
+/* CMU_CAM1 */
+#define CLK_PHYCLK_RXBYTEECLKHS0_S2B                   1
+
+#define CLK_MOUT_SCLK_ISP_UART_USER                    2
+#define CLK_MOUT_SCLK_ISP_SPI1_USER                    3
+#define CLK_MOUT_SCLK_ISP_SPI0_USER                    4
+#define CLK_MOUT_ACLK_CAM1_333_USER                    5
+#define CLK_MOUT_ACLK_CAM1_400_USER                    6
+#define CLK_MOUT_ACLK_CAM1_552_USER                    7
+#define CLK_MOUT_PHYCLK_RXBYTECLKHS0_S2B_USER          8
+#define CLK_MOUT_ACLK_CSIS2_B                          9
+#define CLK_MOUT_ACLK_CSIS2_A                          10
+#define CLK_MOUT_ACLK_FD_B                             11
+#define CLK_MOUT_ACLK_FD_A                             12
+#define CLK_MOUT_ACLK_LITE_C_B                         13
+#define CLK_MOUT_ACLK_LITE_C_A                         14
+
+#define CLK_DIV_SCLK_ISP_WPWM                          15
+#define CLK_DIV_PCLK_CAM1_83                           16
+#define CLK_DIV_PCLK_CAM1_166                          17
+#define CLK_DIV_PCLK_DBG_CAM1                          18
+#define CLK_DIV_ATCLK_CAM1                             19
+#define CLK_DIV_ACLK_CSIS2                             20
+#define CLK_DIV_PCLK_FD                                        21
+#define CLK_DIV_ACLK_FD                                        22
+#define CLK_DIV_PCLK_LITE_C                            23
+#define CLK_DIV_ACLK_LITE_C                            24
+
+#define CLK_ACLK_ISP_GIC                               25
+#define CLK_ACLK_FD                                    26
+#define CLK_ACLK_LITE_C                                        27
+#define CLK_ACLK_CSIS2                                 28
+#define CLK_ACLK_ASYNCAPBM_FD                          29
+#define CLK_ACLK_ASYNCAPBS_FD                          30
+#define CLK_ACLK_ASYNCAPBM_LITE_C                      31
+#define CLK_ACLK_ASYNCAPBS_LITE_C                      32
+#define CLK_ACLK_ASYNCAHBS_SFRISP2H2                   33
+#define CLK_ACLK_ASYNCAHBS_SFRISP2H1                   34
+#define CLK_ACLK_ASYNCAXIM_CA5                         35
+#define CLK_ACLK_ASYNCAXIS_CA5                         36
+#define CLK_ACLK_ASYNCAXIS_ISPX2                       37
+#define CLK_ACLK_ASYNCAXIS_ISPX1                       38
+#define CLK_ACLK_ASYNCAXIS_ISPX0                       39
+#define CLK_ACLK_ASYNCAXIM_ISPEX                       40
+#define CLK_ACLK_ASYNCAXIM_ISP3P                       41
+#define CLK_ACLK_ASYNCAXIS_ISP3P                       42
+#define CLK_ACLK_ASYNCAXIM_FD                          43
+#define CLK_ACLK_ASYNCAXIS_FD                          44
+#define CLK_ACLK_ASYNCAXIM_LITE_C                      45
+#define CLK_ACLK_ASYNCAXIS_LITE_C                      46
+#define CLK_ACLK_AHB2APB_ISP5P                         47
+#define CLK_ACLK_AHB2APB_ISP3P                         48
+#define CLK_ACLK_AXI2APB_ISP3P                         49
+#define CLK_ACLK_AHB_SFRISP2H                          50
+#define CLK_ACLK_AXI_ISP_HX_R                          51
+#define CLK_ACLK_AXI_ISP_CX_R                          52
+#define CLK_ACLK_AXI_ISP_HX                            53
+#define CLK_ACLK_AXI_ISP_CX                            54
+#define CLK_ACLK_XIU_ISPX                              55
+#define CLK_ACLK_XIU_ISPEX                             56
+#define CLK_ACLK_CAM1NP_333                            57
+#define CLK_ACLK_CAM1ND_400                            58
+#define CLK_ACLK_SMMU_ISPCPU                           59
+#define CLK_ACLK_SMMU_FD                               60
+#define CLK_ACLK_SMMU_LITE_C                           61
+#define CLK_ACLK_BTS_ISP3P                             62
+#define CLK_ACLK_BTS_FD                                        63
+#define CLK_ACLK_BTS_LITE_C                            64
+#define CLK_ACLK_AHBDN_SFRISP2H                                65
+#define CLK_ACLK_AHBDN_ISP5P                           66
+#define CLK_ACLK_AXIUS_ISP3P                           67
+#define CLK_ACLK_AXIUS_FD                              68
+#define CLK_ACLK_AXIUS_LITE_C                          69
+#define CLK_PCLK_SMMU_ISPCPU                           70
+#define CLK_PCLK_SMMU_FD                               71
+#define CLK_PCLK_SMMU_LITE_C                           72
+#define CLK_PCLK_BTS_ISP3P                             73
+#define CLK_PCLK_BTS_FD                                        74
+#define CLK_PCLK_BTS_LITE_C                            75
+#define CLK_PCLK_ASYNCAXIM_CA5                         76
+#define CLK_PCLK_ASYNCAXIM_ISPEX                       77
+#define CLK_PCLK_ASYNCAXIM_ISP3P                       78
+#define CLK_PCLK_ASYNCAXIM_FD                          79
+#define CLK_PCLK_ASYNCAXIM_LITE_C                      80
+#define CLK_PCLK_PMU_CAM1                              81
+#define CLK_PCLK_SYSREG_CAM1                           82
+#define CLK_PCLK_CMU_CAM1_LOCAL                                83
+#define CLK_PCLK_ISP_MCTADC                            84
+#define CLK_PCLK_ISP_WDT                               85
+#define CLK_PCLK_ISP_PWM                               86
+#define CLK_PCLK_ISP_UART                              87
+#define CLK_PCLK_ISP_MCUCTL                            88
+#define CLK_PCLK_ISP_SPI1                              89
+#define CLK_PCLK_ISP_SPI0                              90
+#define CLK_PCLK_ISP_I2C2                              91
+#define CLK_PCLK_ISP_I2C1                              92
+#define CLK_PCLK_ISP_I2C0                              93
+#define CLK_PCLK_ISP_MPWM                              94
+#define CLK_PCLK_FD                                    95
+#define CLK_PCLK_LITE_C                                        96
+#define CLK_PCLK_CSIS2                                 97
+#define CLK_SCLK_ISP_I2C2                              98
+#define CLK_SCLK_ISP_I2C1                              99
+#define CLK_SCLK_ISP_I2C0                              100
+#define CLK_SCLK_ISP_PWM                               101
+#define CLK_PHYCLK_RXBYTECLKHS0_S2B                    102
+#define CLK_SCLK_LITE_C_FREECNT                                103
+#define CLK_SCLK_PIXELASYNCM_FD                                104
+#define CLK_SCLK_ISP_MCTADC                            105
+#define CLK_SCLK_ISP_UART                              106
+#define CLK_SCLK_ISP_SPI1                              107
+#define CLK_SCLK_ISP_SPI0                              108
+#define CLK_SCLK_ISP_MPWM                              109
+#define CLK_PCLK_DBG_ISP                               110
+#define CLK_ATCLK_ISP                                  111
+#define CLK_SCLK_ISP_CA5                               112
+
+#define CAM1_NR_CLK                                    113
+
+#endif /* _DT_BINDINGS_CLOCK_EXYNOS5433_H */
index b690cdba163b85b7c81a60cb1ac0cea8253dcc5c..8780868458a09e9b35d7fdee97f732663da0a61c 100644 (file)
 #define IMX6QDL_PLL6_BYPASS                    235
 #define IMX6QDL_PLL7_BYPASS                    236
 #define IMX6QDL_CLK_GPT_3M                     237
-#define IMX6QDL_CLK_END                                238
+#define IMX6QDL_CLK_VIDEO_27M                  238
+#define IMX6QDL_CLK_MIPI_CORE_CFG              239
+#define IMX6QDL_CLK_MIPI_IPG                   240
+#define IMX6QDL_CLK_END                                241
 
 #endif /* __DT_BINDINGS_CLOCK_IMX6QDL_H */
index 04fb29ae30e69801f37713f1284d165396f8525a..ebd63fd05649b544c7bbeb11ef507efd5e26077e 100644 (file)
 #define UBI32_CORE2_CLK_SRC                    278
 #define UBI32_CORE1_CLK                                279
 #define UBI32_CORE2_CLK                                280
+#define EBI2_AON_CLK                           281
 
 #endif
diff --git a/include/dt-bindings/clock/qcom,gcc-msm8916.h b/include/dt-bindings/clock/qcom,gcc-msm8916.h
new file mode 100644 (file)
index 0000000..e430f64
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2015 Linaro Limited
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_CLK_MSM_GCC_8916_H
+#define _DT_BINDINGS_CLK_MSM_GCC_8916_H
+
+#define GPLL0                                  0
+#define GPLL0_VOTE                             1
+#define BIMC_PLL                               2
+#define BIMC_PLL_VOTE                          3
+#define GPLL1                                  4
+#define GPLL1_VOTE                             5
+#define GPLL2                                  6
+#define GPLL2_VOTE                             7
+#define PCNOC_BFDCD_CLK_SRC                    8
+#define SYSTEM_NOC_BFDCD_CLK_SRC               9
+#define CAMSS_AHB_CLK_SRC                      10
+#define APSS_AHB_CLK_SRC                       11
+#define CSI0_CLK_SRC                           12
+#define CSI1_CLK_SRC                           13
+#define GFX3D_CLK_SRC                          14
+#define VFE0_CLK_SRC                           15
+#define BLSP1_QUP1_I2C_APPS_CLK_SRC            16
+#define BLSP1_QUP1_SPI_APPS_CLK_SRC            17
+#define BLSP1_QUP2_I2C_APPS_CLK_SRC            18
+#define BLSP1_QUP2_SPI_APPS_CLK_SRC            19
+#define BLSP1_QUP3_I2C_APPS_CLK_SRC            20
+#define BLSP1_QUP3_SPI_APPS_CLK_SRC            21
+#define BLSP1_QUP4_I2C_APPS_CLK_SRC            22
+#define BLSP1_QUP4_SPI_APPS_CLK_SRC            23
+#define BLSP1_QUP5_I2C_APPS_CLK_SRC            24
+#define BLSP1_QUP5_SPI_APPS_CLK_SRC            25
+#define BLSP1_QUP6_I2C_APPS_CLK_SRC            26
+#define BLSP1_QUP6_SPI_APPS_CLK_SRC            27
+#define BLSP1_UART1_APPS_CLK_SRC               28
+#define BLSP1_UART2_APPS_CLK_SRC               29
+#define CCI_CLK_SRC                            30
+#define CAMSS_GP0_CLK_SRC                      31
+#define CAMSS_GP1_CLK_SRC                      32
+#define JPEG0_CLK_SRC                          33
+#define MCLK0_CLK_SRC                          34
+#define MCLK1_CLK_SRC                          35
+#define CSI0PHYTIMER_CLK_SRC                   36
+#define CSI1PHYTIMER_CLK_SRC                   37
+#define CPP_CLK_SRC                            38
+#define CRYPTO_CLK_SRC                         39
+#define GP1_CLK_SRC                            40
+#define GP2_CLK_SRC                            41
+#define GP3_CLK_SRC                            42
+#define BYTE0_CLK_SRC                          43
+#define ESC0_CLK_SRC                           44
+#define MDP_CLK_SRC                            45
+#define PCLK0_CLK_SRC                          46
+#define VSYNC_CLK_SRC                          47
+#define PDM2_CLK_SRC                           48
+#define SDCC1_APPS_CLK_SRC                     49
+#define SDCC2_APPS_CLK_SRC                     50
+#define APSS_TCU_CLK_SRC                       51
+#define USB_HS_SYSTEM_CLK_SRC                  52
+#define VCODEC0_CLK_SRC                                53
+#define GCC_BLSP1_AHB_CLK                      54
+#define GCC_BLSP1_SLEEP_CLK                    55
+#define GCC_BLSP1_QUP1_I2C_APPS_CLK            56
+#define GCC_BLSP1_QUP1_SPI_APPS_CLK            57
+#define GCC_BLSP1_QUP2_I2C_APPS_CLK            58
+#define GCC_BLSP1_QUP2_SPI_APPS_CLK            59
+#define GCC_BLSP1_QUP3_I2C_APPS_CLK            60
+#define GCC_BLSP1_QUP3_SPI_APPS_CLK            61
+#define GCC_BLSP1_QUP4_I2C_APPS_CLK            62
+#define GCC_BLSP1_QUP4_SPI_APPS_CLK            63
+#define GCC_BLSP1_QUP5_I2C_APPS_CLK            64
+#define GCC_BLSP1_QUP5_SPI_APPS_CLK            65
+#define GCC_BLSP1_QUP6_I2C_APPS_CLK            66
+#define GCC_BLSP1_QUP6_SPI_APPS_CLK            67
+#define GCC_BLSP1_UART1_APPS_CLK               68
+#define GCC_BLSP1_UART2_APPS_CLK               69
+#define GCC_BOOT_ROM_AHB_CLK                   70
+#define GCC_CAMSS_CCI_AHB_CLK                  71
+#define GCC_CAMSS_CCI_CLK                      72
+#define GCC_CAMSS_CSI0_AHB_CLK                 73
+#define GCC_CAMSS_CSI0_CLK                     74
+#define GCC_CAMSS_CSI0PHY_CLK                  75
+#define GCC_CAMSS_CSI0PIX_CLK                  76
+#define GCC_CAMSS_CSI0RDI_CLK                  77
+#define GCC_CAMSS_CSI1_AHB_CLK                 78
+#define GCC_CAMSS_CSI1_CLK                     79
+#define GCC_CAMSS_CSI1PHY_CLK                  80
+#define GCC_CAMSS_CSI1PIX_CLK                  81
+#define GCC_CAMSS_CSI1RDI_CLK                  82
+#define GCC_CAMSS_CSI_VFE0_CLK                 83
+#define GCC_CAMSS_GP0_CLK                      84
+#define GCC_CAMSS_GP1_CLK                      85
+#define GCC_CAMSS_ISPIF_AHB_CLK                        86
+#define GCC_CAMSS_JPEG0_CLK                    87
+#define GCC_CAMSS_JPEG_AHB_CLK                 88
+#define GCC_CAMSS_JPEG_AXI_CLK                 89
+#define GCC_CAMSS_MCLK0_CLK                    90
+#define GCC_CAMSS_MCLK1_CLK                    91
+#define GCC_CAMSS_MICRO_AHB_CLK                        92
+#define GCC_CAMSS_CSI0PHYTIMER_CLK             93
+#define GCC_CAMSS_CSI1PHYTIMER_CLK             94
+#define GCC_CAMSS_AHB_CLK                      95
+#define GCC_CAMSS_TOP_AHB_CLK                  96
+#define GCC_CAMSS_CPP_AHB_CLK                  97
+#define GCC_CAMSS_CPP_CLK                      98
+#define GCC_CAMSS_VFE0_CLK                     99
+#define GCC_CAMSS_VFE_AHB_CLK                  100
+#define GCC_CAMSS_VFE_AXI_CLK                  101
+#define GCC_CRYPTO_AHB_CLK                     102
+#define GCC_CRYPTO_AXI_CLK                     103
+#define GCC_CRYPTO_CLK                         104
+#define GCC_OXILI_GMEM_CLK                     105
+#define GCC_GP1_CLK                            106
+#define GCC_GP2_CLK                            107
+#define GCC_GP3_CLK                            108
+#define GCC_MDSS_AHB_CLK                       109
+#define GCC_MDSS_AXI_CLK                       110
+#define GCC_MDSS_BYTE0_CLK                     111
+#define GCC_MDSS_ESC0_CLK                      112
+#define GCC_MDSS_MDP_CLK                       113
+#define GCC_MDSS_PCLK0_CLK                     114
+#define GCC_MDSS_VSYNC_CLK                     115
+#define GCC_MSS_CFG_AHB_CLK                    116
+#define GCC_OXILI_AHB_CLK                      117
+#define GCC_OXILI_GFX3D_CLK                    118
+#define GCC_PDM2_CLK                           119
+#define GCC_PDM_AHB_CLK                                120
+#define GCC_PRNG_AHB_CLK                       121
+#define GCC_SDCC1_AHB_CLK                      122
+#define GCC_SDCC1_APPS_CLK                     123
+#define GCC_SDCC2_AHB_CLK                      124
+#define GCC_SDCC2_APPS_CLK                     125
+#define GCC_GTCU_AHB_CLK                       126
+#define GCC_JPEG_TBU_CLK                       127
+#define GCC_MDP_TBU_CLK                                128
+#define GCC_SMMU_CFG_CLK                       129
+#define GCC_VENUS_TBU_CLK                      130
+#define GCC_VFE_TBU_CLK                                131
+#define GCC_USB2A_PHY_SLEEP_CLK                        132
+#define GCC_USB_HS_AHB_CLK                     133
+#define GCC_USB_HS_SYSTEM_CLK                  134
+#define GCC_VENUS0_AHB_CLK                     135
+#define GCC_VENUS0_AXI_CLK                     136
+#define GCC_VENUS0_VCODEC0_CLK                 137
+
+#endif
diff --git a/include/dt-bindings/clock/r8a73a4-clock.h b/include/dt-bindings/clock/r8a73a4-clock.h
new file mode 100644 (file)
index 0000000..9a4b4c9
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright 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; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_R8A73A4_H__
+#define __DT_BINDINGS_CLOCK_R8A73A4_H__
+
+/* CPG */
+#define R8A73A4_CLK_MAIN       0
+#define R8A73A4_CLK_PLL0       1
+#define R8A73A4_CLK_PLL1       2
+#define R8A73A4_CLK_PLL2       3
+#define R8A73A4_CLK_PLL2S      4
+#define R8A73A4_CLK_PLL2H      5
+#define R8A73A4_CLK_Z          6
+#define R8A73A4_CLK_Z2         7
+#define R8A73A4_CLK_I          8
+#define R8A73A4_CLK_M3         9
+#define R8A73A4_CLK_B          10
+#define R8A73A4_CLK_M1         11
+#define R8A73A4_CLK_M2         12
+#define R8A73A4_CLK_ZX         13
+#define R8A73A4_CLK_ZS         14
+#define R8A73A4_CLK_HP         15
+
+/* MSTP2 */
+#define R8A73A4_CLK_DMAC       18
+#define R8A73A4_CLK_SCIFB3     17
+#define R8A73A4_CLK_SCIFB2     16
+#define R8A73A4_CLK_SCIFB1     7
+#define R8A73A4_CLK_SCIFB0     6
+#define R8A73A4_CLK_SCIFA0     4
+#define R8A73A4_CLK_SCIFA1     3
+
+/* MSTP3 */
+#define R8A73A4_CLK_CMT1       29
+#define R8A73A4_CLK_IIC1       23
+#define R8A73A4_CLK_IIC0       18
+#define R8A73A4_CLK_IIC7       17
+#define R8A73A4_CLK_IIC6       16
+#define R8A73A4_CLK_MMCIF0     15
+#define R8A73A4_CLK_SDHI0      14
+#define R8A73A4_CLK_SDHI1      13
+#define R8A73A4_CLK_SDHI2      12
+#define R8A73A4_CLK_MMCIF1     5
+#define R8A73A4_CLK_IIC2       0
+
+/* MSTP4 */
+#define R8A73A4_CLK_IIC3       11
+#define R8A73A4_CLK_IIC4       10
+#define R8A73A4_CLK_IIC5       9
+
+/* MSTP5 */
+#define R8A73A4_CLK_THERMAL    22
+#define R8A73A4_CLK_IIC8       15
+
+#endif /* __DT_BINDINGS_CLOCK_R8A73A4_H__ */
diff --git a/include/dt-bindings/clock/r8a7778-clock.h b/include/dt-bindings/clock/r8a7778-clock.h
new file mode 100644 (file)
index 0000000..f6b07c5
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_R8A7778_H__
+#define __DT_BINDINGS_CLOCK_R8A7778_H__
+
+/* CPG */
+#define R8A7778_CLK_PLLA       0
+#define R8A7778_CLK_PLLB       1
+#define R8A7778_CLK_B          2
+#define R8A7778_CLK_OUT                3
+#define R8A7778_CLK_P          4
+#define R8A7778_CLK_S          5
+#define R8A7778_CLK_S1         6
+
+/* MSTP0 */
+#define R8A7778_CLK_I2C0       30
+#define R8A7778_CLK_I2C1       29
+#define R8A7778_CLK_I2C2       28
+#define R8A7778_CLK_I2C3       27
+#define R8A7778_CLK_SCIF0      26
+#define R8A7778_CLK_SCIF1      25
+#define R8A7778_CLK_SCIF2      24
+#define R8A7778_CLK_SCIF3      23
+#define R8A7778_CLK_SCIF4      22
+#define R8A7778_CLK_SCIF5      21
+#define R8A7778_CLK_TMU0       16
+#define R8A7778_CLK_TMU1       15
+#define R8A7778_CLK_TMU2       14
+#define R8A7778_CLK_SSI0       12
+#define R8A7778_CLK_SSI1       11
+#define R8A7778_CLK_SSI2       10
+#define R8A7778_CLK_SSI3       9
+#define R8A7778_CLK_SRU                8
+#define R8A7778_CLK_HSPI       7
+
+/* MSTP1 */
+#define R8A7778_CLK_ETHER      14
+#define R8A7778_CLK_VIN0       10
+#define R8A7778_CLK_VIN1       9
+#define R8A7778_CLK_USB                0
+
+/* MSTP3 */
+#define R8A7778_CLK_MMC                31
+#define R8A7778_CLK_SDHI0      23
+#define R8A7778_CLK_SDHI1      22
+#define R8A7778_CLK_SDHI2      21
+#define R8A7778_CLK_SSI4       11
+#define R8A7778_CLK_SSI5       10
+#define R8A7778_CLK_SSI6       9
+#define R8A7778_CLK_SSI7       8
+#define R8A7778_CLK_SSI8       7
+
+/* MSTP5 */
+#define R8A7778_CLK_SRU_SRC0   31
+#define R8A7778_CLK_SRU_SRC1   30
+#define R8A7778_CLK_SRU_SRC2   29
+#define R8A7778_CLK_SRU_SRC3   28
+#define R8A7778_CLK_SRU_SRC4   27
+#define R8A7778_CLK_SRU_SRC5   26
+#define R8A7778_CLK_SRU_SRC6   25
+#define R8A7778_CLK_SRU_SRC7   24
+#define R8A7778_CLK_SRU_SRC8   23
+
+#endif /* __DT_BINDINGS_CLOCK_R8A7778_H__ */
index 91940271cf8347265849da044ba26a62228e5bd2..3f2c6b198d4ac2890af9b1eb07b19988e6b106e8 100644 (file)
@@ -21,6 +21,8 @@
 #define R8A7790_CLK_SD0                        7
 #define R8A7790_CLK_SD1                        8
 #define R8A7790_CLK_Z                  9
+#define R8A7790_CLK_RCAN               10
+#define R8A7790_CLK_ADSP               11
 
 /* MSTP0 */
 #define R8A7790_CLK_MSIOF0             0
@@ -80,6 +82,7 @@
 /* MSTP5 */
 #define R8A7790_CLK_AUDIO_DMAC1                1
 #define R8A7790_CLK_AUDIO_DMAC0                2
+#define R8A7790_CLK_ADSP_MOD           6
 #define R8A7790_CLK_THERMAL            22
 #define R8A7790_CLK_PWM                        23
 
index f096f3f6c16a4c6a2470feeb2dd686796915a93b..8fc5dc8faeea40517f25ef8811c3a97f75bfad93 100644 (file)
@@ -20,6 +20,8 @@
 #define R8A7791_CLK_SDH                        6
 #define R8A7791_CLK_SD0                        7
 #define R8A7791_CLK_Z                  8
+#define R8A7791_CLK_RCAN               9
+#define R8A7791_CLK_ADSP               10
 
 /* MSTP0 */
 #define R8A7791_CLK_MSIOF0             0
@@ -71,6 +73,7 @@
 /* MSTP5 */
 #define R8A7791_CLK_AUDIO_DMAC1                1
 #define R8A7791_CLK_AUDIO_DMAC0                2
+#define R8A7791_CLK_ADSP_MOD           6
 #define R8A7791_CLK_THERMAL            22
 #define R8A7791_CLK_PWM                        23
 
index 1dd3eb2b7d902afd356f4c96aa293d0972ad8313..53369568c24c5dc6055f34c34e5babc318397d3f 100644 (file)
@@ -76,4 +76,7 @@
 #define SH73A0_CLK_IIC4                10
 #define SH73A0_CLK_KEYSC       3
 
+/* MSTP5 */
+#define SH73A0_CLK_INTCA0      8
+
 #endif
index ae2eb17a16580d2c928ec5767381d667aa628d8c..a2156090563f357ae6076a08639f14cb79469671 100644 (file)
 #define TEGRA124_CLK_PLL_C4 270
 #define TEGRA124_CLK_PLL_DP 271
 #define TEGRA124_CLK_PLL_E_MUX 272
-#define TEGRA124_CLK_PLLD_DSI 273
+#define TEGRA124_CLK_PLL_D_DSI_OUT 273
 /* 274 */
 /* 275 */
 /* 276 */
diff --git a/include/dt-bindings/dma/jz4780-dma.h b/include/dt-bindings/dma/jz4780-dma.h
new file mode 100644 (file)
index 0000000..df017fd
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef __DT_BINDINGS_DMA_JZ4780_DMA_H__
+#define __DT_BINDINGS_DMA_JZ4780_DMA_H__
+
+/*
+ * Request type numbers for the JZ4780 DMA controller (written to the DRTn
+ * register for the channel).
+ */
+#define JZ4780_DMA_I2S1_TX     0x4
+#define JZ4780_DMA_I2S1_RX     0x5
+#define JZ4780_DMA_I2S0_TX     0x6
+#define JZ4780_DMA_I2S0_RX     0x7
+#define JZ4780_DMA_AUTO                0x8
+#define JZ4780_DMA_SADC_RX     0x9
+#define JZ4780_DMA_UART4_TX    0xc
+#define JZ4780_DMA_UART4_RX    0xd
+#define JZ4780_DMA_UART3_TX    0xe
+#define JZ4780_DMA_UART3_RX    0xf
+#define JZ4780_DMA_UART2_TX    0x10
+#define JZ4780_DMA_UART2_RX    0x11
+#define JZ4780_DMA_UART1_TX    0x12
+#define JZ4780_DMA_UART1_RX    0x13
+#define JZ4780_DMA_UART0_TX    0x14
+#define JZ4780_DMA_UART0_RX    0x15
+#define JZ4780_DMA_SSI0_TX     0x16
+#define JZ4780_DMA_SSI0_RX     0x17
+#define JZ4780_DMA_SSI1_TX     0x18
+#define JZ4780_DMA_SSI1_RX     0x19
+#define JZ4780_DMA_MSC0_TX     0x1a
+#define JZ4780_DMA_MSC0_RX     0x1b
+#define JZ4780_DMA_MSC1_TX     0x1c
+#define JZ4780_DMA_MSC1_RX     0x1d
+#define JZ4780_DMA_MSC2_TX     0x1e
+#define JZ4780_DMA_MSC2_RX     0x1f
+#define JZ4780_DMA_PCM0_TX     0x20
+#define JZ4780_DMA_PCM0_RX     0x21
+#define JZ4780_DMA_SMB0_TX     0x24
+#define JZ4780_DMA_SMB0_RX     0x25
+#define JZ4780_DMA_SMB1_TX     0x26
+#define JZ4780_DMA_SMB1_RX     0x27
+#define JZ4780_DMA_SMB2_TX     0x28
+#define JZ4780_DMA_SMB2_RX     0x29
+#define JZ4780_DMA_SMB3_TX     0x2a
+#define JZ4780_DMA_SMB3_RX     0x2b
+#define JZ4780_DMA_SMB4_TX     0x2c
+#define JZ4780_DMA_SMB4_RX     0x2d
+#define JZ4780_DMA_DES_TX      0x2e
+#define JZ4780_DMA_DES_RX      0x2f
+
+#endif /* __DT_BINDINGS_DMA_JZ4780_DMA_H__ */
diff --git a/include/dt-bindings/media/omap3-isp.h b/include/dt-bindings/media/omap3-isp.h
new file mode 100644 (file)
index 0000000..b18c60e
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * include/dt-bindings/media/omap3-isp.h
+ *
+ * Copyright (C) 2015 Sakari Ailus
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef __DT_BINDINGS_OMAP3_ISP_H__
+#define __DT_BINDINGS_OMAP3_ISP_H__
+
+#define OMAP3ISP_PHY_TYPE_COMPLEX_IO   0
+#define OMAP3ISP_PHY_TYPE_CSIPHY       1
+
+#endif /* __DT_BINDINGS_OMAP3_ISP_H__ */
diff --git a/include/dt-bindings/media/xilinx-vip.h b/include/dt-bindings/media/xilinx-vip.h
new file mode 100644 (file)
index 0000000..6298fec
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Xilinx Video IP Core
+ *
+ * Copyright (C) 2013-2015 Ideas on Board
+ * Copyright (C) 2013-2015 Xilinx, Inc.
+ *
+ * Contacts: Hyun Kwon <hyun.kwon@xilinx.com>
+ *           Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __DT_BINDINGS_MEDIA_XILINX_VIP_H__
+#define __DT_BINDINGS_MEDIA_XILINX_VIP_H__
+
+/*
+ * Video format codes as defined in "AXI4-Stream Video IP and System Design
+ * Guide".
+ */
+#define XVIP_VF_YUV_422                        0
+#define XVIP_VF_YUV_444                        1
+#define XVIP_VF_RBG                    2
+#define XVIP_VF_YUV_420                        3
+#define XVIP_VF_YUVA_422               4
+#define XVIP_VF_YUVA_444               5
+#define XVIP_VF_RGBA                   6
+#define XVIP_VF_YUVA_420               7
+#define XVIP_VF_YUVD_422               8
+#define XVIP_VF_YUVD_444               9
+#define XVIP_VF_RGBD                   10
+#define XVIP_VF_YUVD_420               11
+#define XVIP_VF_MONO_SENSOR            12
+#define XVIP_VF_CUSTOM2                        13
+#define XVIP_VF_CUSTOM3                        14
+#define XVIP_VF_CUSTOM4                        15
+
+#endif /* __DT_BINDINGS_MEDIA_XILINX_VIP_H__ */
diff --git a/include/dt-bindings/reset/qcom,gcc-msm8916.h b/include/dt-bindings/reset/qcom,gcc-msm8916.h
new file mode 100644 (file)
index 0000000..3d90410
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2015 Linaro Limited
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_RESET_MSM_GCC_8916_H
+#define _DT_BINDINGS_RESET_MSM_GCC_8916_H
+
+#define GCC_BLSP1_BCR                  0
+#define GCC_BLSP1_QUP1_BCR             1
+#define GCC_BLSP1_UART1_BCR            2
+#define GCC_BLSP1_QUP2_BCR             3
+#define GCC_BLSP1_UART2_BCR            4
+#define GCC_BLSP1_QUP3_BCR             5
+#define GCC_BLSP1_QUP4_BCR             6
+#define GCC_BLSP1_QUP5_BCR             7
+#define GCC_BLSP1_QUP6_BCR             8
+#define GCC_IMEM_BCR                   9
+#define GCC_SMMU_BCR                   10
+#define GCC_APSS_TCU_BCR               11
+#define GCC_SMMU_XPU_BCR               12
+#define GCC_PCNOC_TBU_BCR              13
+#define GCC_PRNG_BCR                   14
+#define GCC_BOOT_ROM_BCR               15
+#define GCC_CRYPTO_BCR                 16
+#define GCC_SEC_CTRL_BCR               17
+#define GCC_AUDIO_CORE_BCR             18
+#define GCC_ULT_AUDIO_BCR              19
+#define GCC_DEHR_BCR                   20
+#define GCC_SYSTEM_NOC_BCR             21
+#define GCC_PCNOC_BCR                  22
+#define GCC_TCSR_BCR                   23
+#define GCC_QDSS_BCR                   24
+#define GCC_DCD_BCR                    25
+#define GCC_MSG_RAM_BCR                        26
+#define GCC_MPM_BCR                    27
+#define GCC_SPMI_BCR                   28
+#define GCC_SPDM_BCR                   29
+#define GCC_MM_SPDM_BCR                        30
+#define GCC_BIMC_BCR                   31
+#define GCC_RBCPR_BCR                  32
+#define GCC_TLMM_BCR                   33
+#define GCC_USB_HS_BCR                 34
+#define GCC_USB2A_PHY_BCR              35
+#define GCC_SDCC1_BCR                  36
+#define GCC_SDCC2_BCR                  37
+#define GCC_PDM_BCR                    38
+#define GCC_SNOC_BUS_TIMEOUT0_BCR      39
+#define GCC_PCNOC_BUS_TIMEOUT0_BCR     40
+#define GCC_PCNOC_BUS_TIMEOUT1_BCR     41
+#define GCC_PCNOC_BUS_TIMEOUT2_BCR     42
+#define GCC_PCNOC_BUS_TIMEOUT3_BCR     43
+#define GCC_PCNOC_BUS_TIMEOUT4_BCR     44
+#define GCC_PCNOC_BUS_TIMEOUT5_BCR     45
+#define GCC_PCNOC_BUS_TIMEOUT6_BCR     46
+#define GCC_PCNOC_BUS_TIMEOUT7_BCR     47
+#define GCC_PCNOC_BUS_TIMEOUT8_BCR     48
+#define GCC_PCNOC_BUS_TIMEOUT9_BCR     49
+#define GCC_MMSS_BCR                   50
+#define GCC_VENUS0_BCR                 51
+#define GCC_MDSS_BCR                   52
+#define GCC_CAMSS_PHY0_BCR             53
+#define GCC_CAMSS_CSI0_BCR             54
+#define GCC_CAMSS_CSI0PHY_BCR          55
+#define GCC_CAMSS_CSI0RDI_BCR          56
+#define GCC_CAMSS_CSI0PIX_BCR          57
+#define GCC_CAMSS_PHY1_BCR             58
+#define GCC_CAMSS_CSI1_BCR             59
+#define GCC_CAMSS_CSI1PHY_BCR          60
+#define GCC_CAMSS_CSI1RDI_BCR          61
+#define GCC_CAMSS_CSI1PIX_BCR          62
+#define GCC_CAMSS_ISPIF_BCR            63
+#define GCC_CAMSS_CCI_BCR              64
+#define GCC_CAMSS_MCLK0_BCR            65
+#define GCC_CAMSS_MCLK1_BCR            66
+#define GCC_CAMSS_GP0_BCR              67
+#define GCC_CAMSS_GP1_BCR              68
+#define GCC_CAMSS_TOP_BCR              69
+#define GCC_CAMSS_MICRO_BCR            70
+#define GCC_CAMSS_JPEG_BCR             71
+#define GCC_CAMSS_VFE_BCR              72
+#define GCC_CAMSS_CSI_VFE0_BCR         73
+#define GCC_OXILI_BCR                  74
+#define GCC_GMEM_BCR                   75
+#define GCC_CAMSS_AHB_BCR              76
+#define GCC_MDP_TBU_BCR                        77
+#define GCC_GFX_TBU_BCR                        78
+#define GCC_GFX_TCU_BCR                        79
+#define GCC_MSS_TBU_AXI_BCR            80
+#define GCC_MSS_TBU_GSS_AXI_BCR                81
+#define GCC_MSS_TBU_Q6_AXI_BCR         82
+#define GCC_GTCU_AHB_BCR               83
+#define GCC_SMMU_CFG_BCR               84
+#define GCC_VFE_TBU_BCR                        85
+#define GCC_VENUS_TBU_BCR              86
+#define GCC_JPEG_TBU_BCR               87
+#define GCC_PRONTO_TBU_BCR             88
+#define GCC_SMMU_CATS_BCR              89
+
+#endif
index dd12127f171c7569fd169915d01dd24e7af97aba..e4da5e35e29cd8ee66f443ddd070276ea268e248 100644 (file)
@@ -79,6 +79,7 @@ enum acpi_irq_model_id {
        ACPI_IRQ_MODEL_IOAPIC,
        ACPI_IRQ_MODEL_IOSAPIC,
        ACPI_IRQ_MODEL_PLATFORM,
+       ACPI_IRQ_MODEL_GIC,
        ACPI_IRQ_MODEL_COUNT
 };
 
@@ -152,9 +153,14 @@ void acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa);
 int acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma);
 void acpi_numa_arch_fixup(void);
 
+#ifndef PHYS_CPUID_INVALID
+typedef u32 phys_cpuid_t;
+#define PHYS_CPUID_INVALID (phys_cpuid_t)(-1)
+#endif
+
 #ifdef CONFIG_ACPI_HOTPLUG_CPU
 /* Arch dependent functions for cpu hotplug support */
-int acpi_map_cpu(acpi_handle handle, int physid, int *pcpu);
+int acpi_map_cpu(acpi_handle handle, phys_cpuid_t physid, int *pcpu);
 int acpi_unmap_cpu(int cpu);
 #endif /* CONFIG_ACPI_HOTPLUG_CPU */
 
diff --git a/include/linux/acpi_irq.h b/include/linux/acpi_irq.h
new file mode 100644 (file)
index 0000000..f10c872
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _LINUX_ACPI_IRQ_H
+#define _LINUX_ACPI_IRQ_H
+
+#include <linux/irq.h>
+
+#ifndef acpi_irq_init
+static inline void acpi_irq_init(void) { }
+#endif
+
+#endif /* _LINUX_ACPI_IRQ_H */
diff --git a/include/linux/amba/xilinx_dma.h b/include/linux/amba/xilinx_dma.h
deleted file mode 100644 (file)
index 34b98f2..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Xilinx DMA Engine drivers support header file
- *
- * Copyright (C) 2010-2014 Xilinx, Inc. All rights reserved.
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the 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 __DMA_XILINX_DMA_H
-#define __DMA_XILINX_DMA_H
-
-#include <linux/dma-mapping.h>
-#include <linux/dmaengine.h>
-
-/**
- * struct xilinx_vdma_config - VDMA Configuration structure
- * @frm_dly: Frame delay
- * @gen_lock: Whether in gen-lock mode
- * @master: Master that it syncs to
- * @frm_cnt_en: Enable frame count enable
- * @park: Whether wants to park
- * @park_frm: Frame to park on
- * @coalesc: Interrupt coalescing threshold
- * @delay: Delay counter
- * @reset: Reset Channel
- * @ext_fsync: External Frame Sync source
- */
-struct xilinx_vdma_config {
-       int frm_dly;
-       int gen_lock;
-       int master;
-       int frm_cnt_en;
-       int park;
-       int park_frm;
-       int coalesc;
-       int delay;
-       int reset;
-       int ext_fsync;
-};
-
-int xilinx_vdma_channel_set_config(struct dma_chan *dchan,
-                                       struct xilinx_vdma_config *cfg);
-
-#endif
index 79d6edf446d513d22702ad093b7382ca8ab57b7d..521ec1f2e6bc08441279c0ca5245d82394885ddf 100644 (file)
 #include <linux/errno.h>
 #include <linux/types.h>
 
+#include <asm/arm-cci.h>
+
 struct device_node;
 
 #ifdef CONFIG_ARM_CCI
 extern bool cci_probed(void);
+#else
+static inline bool cci_probed(void) { return false; }
+#endif
+
+#ifdef CONFIG_ARM_CCI400_PORT_CTRL
 extern int cci_ace_get_port(struct device_node *dn);
 extern int cci_disable_port_by_cpu(u64 mpidr);
 extern int __cci_control_port_by_device(struct device_node *dn, bool enable);
 extern int __cci_control_port_by_index(u32 port, bool enable);
 #else
-static inline bool cci_probed(void) { return false; }
 static inline int cci_ace_get_port(struct device_node *dn)
 {
        return -ENODEV;
@@ -49,6 +55,7 @@ static inline int __cci_control_port_by_index(u32 port, bool enable)
        return -ENODEV;
 }
 #endif
+
 #define cci_disable_port_by_device(dev) \
        __cci_control_port_by_device(dev, false)
 #define cci_enable_port_by_device(dev) \
index 179b38ffd351323c89c91e90f5ef370e04ebddc7..388574ea38ed9d4aa1d644442672ad883feaaef3 100644 (file)
@@ -60,12 +60,15 @@ struct dma_chan_ref {
  * dependency chain
  * @ASYNC_TX_FENCE: specify that the next operation in the dependency
  * chain uses this operation's result as an input
+ * @ASYNC_TX_PQ_XOR_DST: do not overwrite the syndrome but XOR it with the
+ * input data. Required for rmw case.
  */
 enum async_tx_flags {
        ASYNC_TX_XOR_ZERO_DST    = (1 << 0),
        ASYNC_TX_XOR_DROP_DST    = (1 << 1),
        ASYNC_TX_ACK             = (1 << 2),
        ASYNC_TX_FENCE           = (1 << 3),
+       ASYNC_TX_PQ_XOR_DST      = (1 << 4),
 };
 
 /**
index 71e05bbf8cebe3888a9a4ff72abb1d210dadd4c1..4763ad64e832cb07496bbd14a35c4bcf3825a885 100644 (file)
 #define CEPH_FEATURE_MDS_INLINE_DATA     (1ULL<<40)
 #define CEPH_FEATURE_CRUSH_TUNABLES3     (1ULL<<41)
 #define CEPH_FEATURE_OSD_PRIMARY_AFFINITY (1ULL<<41)  /* overlap w/ tunables3 */
+#define CEPH_FEATURE_MSGR_KEEPALIVE2   (1ULL<<42)
+#define CEPH_FEATURE_OSD_POOLRESEND    (1ULL<<43)
+#define CEPH_FEATURE_ERASURE_CODE_PLUGINS_V2 (1ULL<<44)
+#define CEPH_FEATURE_OSD_SET_ALLOC_HINT (1ULL<<45)
+#define CEPH_FEATURE_OSD_FADVISE_FLAGS (1ULL<<46)
+#define CEPH_FEATURE_OSD_REPOP         (1ULL<<46)   /* overlap with fadvise */
+#define CEPH_FEATURE_OSD_OBJECT_DIGEST  (1ULL<<46)  /* overlap with fadvise */
+#define CEPH_FEATURE_OSD_TRANSACTION_MAY_LAYOUT (1ULL<<46) /* overlap w/ fadvise */
+#define CEPH_FEATURE_MDS_QUOTA      (1ULL<<47)
+#define CEPH_FEATURE_CRUSH_V4      (1ULL<<48)  /* straw2 buckets */
+#define CEPH_FEATURE_OSD_MIN_SIZE_RECOVERY (1ULL<<49)
+// duplicated since it was introduced at the same time as MIN_SIZE_RECOVERY
+#define CEPH_FEATURE_OSD_PROXY_FEATURES (1ULL<<49)  /* overlap w/ above */
 
 /*
  * The introduction of CEPH_FEATURE_OSD_SNAPMAPPER caused the feature
@@ -93,7 +106,8 @@ static inline u64 ceph_sanitize_features(u64 features)
         CEPH_FEATURE_EXPORT_PEER |             \
         CEPH_FEATURE_OSDMAP_ENC |              \
         CEPH_FEATURE_CRUSH_TUNABLES3 |         \
-        CEPH_FEATURE_OSD_PRIMARY_AFFINITY)
+        CEPH_FEATURE_OSD_PRIMARY_AFFINITY |    \
+        CEPH_FEATURE_CRUSH_V4)
 
 #define CEPH_FEATURES_REQUIRED_DEFAULT   \
        (CEPH_FEATURE_NOSRCADDR |        \
index 31eb03d0c7662dddd02fb126a24bc4198ffc65d8..d7d072a25c2717734139e98b01dd2724f2c43844 100644 (file)
@@ -323,6 +323,7 @@ enum {
        CEPH_MDS_OP_MKSNAP     = 0x01400,
        CEPH_MDS_OP_RMSNAP     = 0x01401,
        CEPH_MDS_OP_LSSNAP     = 0x00402,
+       CEPH_MDS_OP_RENAMESNAP = 0x01403,
 };
 
 extern const char *ceph_mds_op_name(int op);
index 1df086d7882d9a3c5eeaf132835d01161fcd4b8b..29cf897cc5cd3cafe2ed69a415fb0713d90704b2 100644 (file)
@@ -7,13 +7,7 @@
 #define CEPH_DEFINE_SHOW_FUNC(name)                                    \
 static int name##_open(struct inode *inode, struct file *file)         \
 {                                                                      \
-       struct seq_file *sf;                                            \
-       int ret;                                                        \
-                                                                       \
-       ret = single_open(file, name, NULL);                            \
-       sf = file->private_data;                                        \
-       sf->private = inode->i_private;                                 \
-       return ret;                                                     \
+       return single_open(file, name, inode->i_private);               \
 }                                                                      \
                                                                        \
 static const struct file_operations name##_fops = {                    \
index 16fff9608848db88dd2c9bca903bc57ca971f527..30f92cefaa721d040d5f1e2d92ec16429f8c00e3 100644 (file)
@@ -135,6 +135,7 @@ struct ceph_client {
        struct dentry *debugfs_dir;
        struct dentry *debugfs_monmap;
        struct dentry *debugfs_osdmap;
+       struct dentry *debugfs_options;
 #endif
 };
 
@@ -191,6 +192,7 @@ extern struct ceph_options *ceph_parse_options(char *options,
                              const char *dev_name, const char *dev_name_end,
                              int (*parse_extra_token)(char *c, void *private),
                              void *private);
+int ceph_print_client_options(struct seq_file *m, struct ceph_client *client);
 extern void ceph_destroy_options(struct ceph_options *opt);
 extern int ceph_compare_options(struct ceph_options *new_opt,
                                struct ceph_client *client);
index 561ea896c65701ec009fd4e860ed824a36e080de..e55c08bc3a960d0b5f0664e5c46ac9cd969ec97d 100644 (file)
@@ -175,13 +175,12 @@ static inline int ceph_decode_pgid(void **p, void *end, struct ceph_pg *pgid)
        __u8 version;
 
        if (!ceph_has_room(p, end, 1 + 8 + 4 + 4)) {
-               pr_warning("incomplete pg encoding");
-
+               pr_warn("incomplete pg encoding\n");
                return -EINVAL;
        }
        version = ceph_decode_8(p);
        if (version > 1) {
-               pr_warning("do not understand pg encoding %d > 1",
+               pr_warn("do not understand pg encoding %d > 1\n",
                        (int)version);
                return -EINVAL;
        }
index 5591ea71a8d14054bf923dcad45dc94f71bd029a..df695313f975769b6cfc740760cbc8c33b6a8d5c 100644 (file)
@@ -541,7 +541,7 @@ struct clk_gpio {
 
 extern const struct clk_ops clk_gpio_gate_ops;
 struct clk *clk_register_gpio_gate(struct device *dev, const char *name,
-               const char *parent_name, struct gpio_desc *gpio,
+               const char *parent_name, unsigned gpio, bool active_low,
                unsigned long flags);
 
 void of_gpio_clk_gate_setup(struct device_node *node);
index c8e3b3d1ededbdf5b3a21e98b45eab03cb51b761..7669f7618f397be6e526d2e388f4b068c83f45c4 100644 (file)
 extern void __iomem *at91_pmc_base;
 
 #define at91_pmc_read(field) \
-       __raw_readl(at91_pmc_base + field)
+       readl_relaxed(at91_pmc_base + field)
 
 #define at91_pmc_write(field, value) \
-       __raw_writel(value, at91_pmc_base + field)
+       writel_relaxed(value, at91_pmc_base + field)
 #else
 .extern at91_pmc_base
 #endif
index 9f8a14041dd51b6650ebc98d62747473d53fbddf..63a8159c4e64153da9ab10e742dbac2e4ed232ab 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/types.h>
 
+void r8a7778_clocks_init(u32 mode);
 void r8a7779_clocks_init(u32 mode);
 void rcar_gen2_clocks_init(u32 mode);
 
index 67844003493de5936809dc1acac72cd88b5bc521..79b76e13d90425db1ed1320b1bfe9f11aecfd767 100644 (file)
@@ -215,14 +215,14 @@ struct ti_dt_clk {
                .node_name = name,      \
        }
 
-/* Maximum number of clock memmaps */
-#define CLK_MAX_MEMMAPS                        4
-
 /* Static memmap indices */
 enum {
        TI_CLKM_CM = 0,
+       TI_CLKM_CM2,
        TI_CLKM_PRM,
        TI_CLKM_SCRM,
+       TI_CLKM_CTRL,
+       CLK_MAX_MEMMAPS
 };
 
 typedef void (*ti_of_clk_init_cb_t)(struct clk_hw *, struct device_node *);
index 135509821c3994f4083bd2f0eb8f7c05409c026c..d27d0152271f9e8b487a48a9f2d74f51fe9a58a5 100644 (file)
@@ -253,4 +253,10 @@ extern void clocksource_of_init(void);
 static inline void clocksource_of_init(void) {}
 #endif
 
+#ifdef CONFIG_ACPI
+void acpi_generic_timer_init(void);
+#else
+static inline void acpi_generic_timer_init(void) { }
+#endif
+
 #endif /* _LINUX_CLOCKSOURCE_H */
index cdf13ca7cac32b61e07dcdbc9f9a79c68dd9ee3e..371e560d13cf1d19abe18e982f27d39d8ab6fc0a 100644 (file)
@@ -9,10 +9,24 @@
                   + __GNUC_MINOR__ * 100 \
                   + __GNUC_PATCHLEVEL__)
 
-
 /* Optimization barrier */
+
 /* The "volatile" is due to gcc bugs */
 #define barrier() __asm__ __volatile__("": : :"memory")
+/*
+ * This version is i.e. to prevent dead stores elimination on @ptr
+ * where gcc and llvm may behave differently when otherwise using
+ * normal barrier(): while gcc behavior gets along with a normal
+ * barrier(), llvm needs an explicit input variable to be assumed
+ * clobbered. The issue is as follows: while the inline asm might
+ * access any memory it wants, the compiler could have fit all of
+ * @ptr into memory registers instead, and since @ptr never escaped
+ * from that, it proofed that the inline asm wasn't touching any of
+ * it. This version works well with both compilers, i.e. we're telling
+ * the compiler that the inline asm absolutely may see the contents
+ * of @ptr. See also: https://llvm.org/bugs/show_bug.cgi?id=15495
+ */
+#define barrier_data(ptr) __asm__ __volatile__("": :"r"(ptr) :"memory")
 
 /*
  * This macro obfuscates arithmetic on a variable address so that gcc
index ba147a1727e6d2fc22c7899fcb5830803c629f41..0c9a2f2c2802fc381d025428543161d39aa148d4 100644 (file)
 /* Intel ECC compiler doesn't support gcc specific asm stmts.
  * It uses intrinsics to do the equivalent things.
  */
+#undef barrier_data
 #undef RELOC_HIDE
 #undef OPTIMIZER_HIDE_VAR
 
+#define barrier_data(ptr) barrier()
+
 #define RELOC_HIDE(ptr, off)                                   \
   ({ unsigned long __ptr;                                      \
      __ptr = (unsigned long) (ptr);                            \
index 0e41ca0e59275deb33b7c7220dffd1ff39cbb2f7..867722591be2c7e026e1b97c241e65e27e3b9d1b 100644 (file)
@@ -169,6 +169,10 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect);
 # define barrier() __memory_barrier()
 #endif
 
+#ifndef barrier_data
+# define barrier_data(ptr) barrier()
+#endif
+
 /* Unreachable code */
 #ifndef unreachable
 # define unreachable() do { } while (1)
index 7571a16bd6535245c0fb68cce7e18dd5d21f1fd1..9f50fb413c11cbfab760acf79fe76e10062f4c6f 100644 (file)
@@ -123,7 +123,7 @@ struct console {
        struct tty_driver *(*device)(struct console *, int *);
        void    (*unblank)(void);
        int     (*setup)(struct console *, char *);
-       int     (*early_setup)(void);
+       int     (*match)(struct console *, char *name, int idx, char *options);
        short   flags;
        short   index;
        int     cflag;
@@ -141,7 +141,6 @@ extern int console_set_on_cmdline;
 extern struct console *early_console;
 
 extern int add_preferred_console(char *name, int idx, char *options);
-extern int update_console_cmdline(char *name, int idx, char *name_new, int idx_new, char *options);
 extern void register_console(struct console *);
 extern int unregister_console(struct console *);
 extern struct console *console_drivers;
index 4fad5f8ee01d3457974551ef1f874fc61f0524f9..48a1a7d100f190efae067afa7866b75e10eff9fe 100644 (file)
@@ -96,13 +96,15 @@ struct crush_rule {
  *  uniform         O(1)       poor         poor
  *  list            O(n)       optimal      poor
  *  tree            O(log n)   good         good
- *  straw           O(n)       optimal      optimal
+ *  straw           O(n)       better       better
+ *  straw2          O(n)       optimal      optimal
  */
 enum {
        CRUSH_BUCKET_UNIFORM = 1,
        CRUSH_BUCKET_LIST = 2,
        CRUSH_BUCKET_TREE = 3,
-       CRUSH_BUCKET_STRAW = 4
+       CRUSH_BUCKET_STRAW = 4,
+       CRUSH_BUCKET_STRAW2 = 5,
 };
 extern const char *crush_bucket_alg_name(int alg);
 
@@ -149,6 +151,11 @@ struct crush_bucket_straw {
        __u32 *straws;         /* 16-bit fixed point */
 };
 
+struct crush_bucket_straw2 {
+       struct crush_bucket h;
+       __u32 *item_weights;   /* 16-bit fixed point */
+};
+
 
 
 /*
@@ -189,6 +196,7 @@ extern void crush_destroy_bucket_uniform(struct crush_bucket_uniform *b);
 extern void crush_destroy_bucket_list(struct crush_bucket_list *b);
 extern void crush_destroy_bucket_tree(struct crush_bucket_tree *b);
 extern void crush_destroy_bucket_straw(struct crush_bucket_straw *b);
+extern void crush_destroy_bucket_straw2(struct crush_bucket_straw2 *b);
 extern void crush_destroy_bucket(struct crush_bucket *b);
 extern void crush_destroy_rule(struct crush_rule *r);
 extern void crush_destroy(struct crush_map *map);
index 694e1fe1c4b4fa8996cab8dcf9fbfa74198f1aed..2f0b431b73e0a7a2c8807a694c8c89a4e4b61a29 100644 (file)
@@ -162,6 +162,33 @@ struct dma_buf_attachment {
        void *priv;
 };
 
+/**
+ * struct dma_buf_export_info - holds information needed to export a dma_buf
+ * @exp_name:  name of the exporting module - useful for debugging.
+ * @ops:       Attach allocator-defined dma buf ops to the new buffer
+ * @size:      Size of the buffer
+ * @flags:     mode flags for the file
+ * @resv:      reservation-object, NULL to allocate default one
+ * @priv:      Attach private data of allocator to this buffer
+ *
+ * This structure holds the information required to export the buffer. Used
+ * with dma_buf_export() only.
+ */
+struct dma_buf_export_info {
+       const char *exp_name;
+       const struct dma_buf_ops *ops;
+       size_t size;
+       int flags;
+       struct reservation_object *resv;
+       void *priv;
+};
+
+/**
+ * helper macro for exporters; zeros and fills in most common values
+ */
+#define DEFINE_DMA_BUF_EXPORT_INFO(a)  \
+       struct dma_buf_export_info a = { .exp_name = KBUILD_MODNAME }
+
 /**
  * get_dma_buf - convenience wrapper for get_file.
  * @dmabuf:    [in]    pointer to dma_buf
@@ -181,12 +208,7 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
 void dma_buf_detach(struct dma_buf *dmabuf,
                                struct dma_buf_attachment *dmabuf_attach);
 
-struct dma_buf *dma_buf_export_named(void *priv, const struct dma_buf_ops *ops,
-                              size_t size, int flags, const char *,
-                              struct reservation_object *);
-
-#define dma_buf_export(priv, ops, size, flags, resv)   \
-       dma_buf_export_named(priv, ops, size, flags, KBUILD_MODNAME, resv)
+struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info);
 
 int dma_buf_fd(struct dma_buf *dmabuf, int flags);
 struct dma_buf *dma_buf_get(int fd);
diff --git a/include/linux/dma/hsu.h b/include/linux/dma/hsu.h
new file mode 100644 (file)
index 0000000..234393a
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Driver for the High Speed UART DMA
+ *
+ * Copyright (C) 2015 Intel 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.
+ */
+
+#ifndef _DMA_HSU_H
+#define _DMA_HSU_H
+
+#include <linux/device.h>
+#include <linux/interrupt.h>
+
+#include <linux/platform_data/dma-hsu.h>
+
+struct hsu_dma;
+
+/**
+ * struct hsu_dma_chip - representation of HSU DMA hardware
+ * @dev:                struct device of the DMA controller
+ * @irq:                irq line
+ * @regs:               memory mapped I/O space
+ * @length:             I/O space length
+ * @offset:             offset of the I/O space where registers are located
+ * @hsu:                struct hsu_dma that is filed by ->probe()
+ * @pdata:              platform data for the DMA controller if provided
+ */
+struct hsu_dma_chip {
+       struct device                   *dev;
+       int                             irq;
+       void __iomem                    *regs;
+       unsigned int                    length;
+       unsigned int                    offset;
+       struct hsu_dma                  *hsu;
+       struct hsu_dma_platform_data    *pdata;
+};
+
+/* Export to the internal users */
+irqreturn_t hsu_dma_irq(struct hsu_dma_chip *chip, unsigned short nr);
+
+/* Export to the platform drivers */
+int hsu_dma_probe(struct hsu_dma_chip *chip);
+int hsu_dma_remove(struct hsu_dma_chip *chip);
+
+#endif /* _DMA_HSU_H */
diff --git a/include/linux/dma/xilinx_dma.h b/include/linux/dma/xilinx_dma.h
new file mode 100644 (file)
index 0000000..34b98f2
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Xilinx DMA Engine drivers support header file
+ *
+ * Copyright (C) 2010-2014 Xilinx, Inc. All rights reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 __DMA_XILINX_DMA_H
+#define __DMA_XILINX_DMA_H
+
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+
+/**
+ * struct xilinx_vdma_config - VDMA Configuration structure
+ * @frm_dly: Frame delay
+ * @gen_lock: Whether in gen-lock mode
+ * @master: Master that it syncs to
+ * @frm_cnt_en: Enable frame count enable
+ * @park: Whether wants to park
+ * @park_frm: Frame to park on
+ * @coalesc: Interrupt coalescing threshold
+ * @delay: Delay counter
+ * @reset: Reset Channel
+ * @ext_fsync: External Frame Sync source
+ */
+struct xilinx_vdma_config {
+       int frm_dly;
+       int gen_lock;
+       int master;
+       int frm_cnt_en;
+       int park;
+       int park_frm;
+       int coalesc;
+       int delay;
+       int reset;
+       int ext_fsync;
+};
+
+int xilinx_vdma_channel_set_config(struct dma_chan *dchan,
+                                       struct xilinx_vdma_config *cfg);
+
+#endif
index b6997a0cb5284759ee8ff107e9bb78ae8839f0c0..ad419757241ffc7c5d5346f4b82462f5a83f1897 100644 (file)
  * 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.
- *
  * The full GNU General Public License is included in this distribution in the
  * file called COPYING.
  */
@@ -574,7 +570,6 @@ struct dma_tx_state {
  * @copy_align: alignment shift for memcpy operations
  * @xor_align: alignment shift for xor operations
  * @pq_align: alignment shift for pq operations
- * @fill_align: alignment shift for memset operations
  * @dev_id: unique device ID
  * @dev: struct device reference for dma mapping api
  * @src_addr_widths: bit mask of src addr widths the device supports
@@ -625,7 +620,6 @@ struct dma_device {
        u8 copy_align;
        u8 xor_align;
        u8 pq_align;
-       u8 fill_align;
        #define DMA_HAS_PQ_CONTINUE (1 << 15)
 
        int dev_id;
@@ -826,12 +820,6 @@ static inline bool is_dma_pq_aligned(struct dma_device *dev, size_t off1,
        return dmaengine_check_align(dev->pq_align, off1, off2, len);
 }
 
-static inline bool is_dma_fill_aligned(struct dma_device *dev, size_t off1,
-                                      size_t off2, size_t len)
-{
-       return dmaengine_check_align(dev->fill_align, off1, off2, len);
-}
-
 static inline void
 dma_set_maxpq(struct dma_device *dma, int maxpq, int has_pq_continue)
 {
@@ -1098,7 +1086,6 @@ void dma_async_device_unregister(struct dma_device *device);
 void dma_run_dependencies(struct dma_async_tx_descriptor *tx);
 struct dma_chan *dma_get_slave_channel(struct dma_chan *chan);
 struct dma_chan *dma_get_any_slave_channel(struct dma_device *device);
-struct dma_chan *net_dma_find_channel(void);
 #define dma_request_channel(mask, x, y) __dma_request_channel(&(mask), x, y)
 #define dma_request_slave_channel_compat(mask, x, y, dev, name) \
        __dma_request_slave_channel_compat(&(mask), x, y, dev, name)
@@ -1116,27 +1103,4 @@ static inline struct dma_chan
 
        return __dma_request_channel(mask, fn, fn_param);
 }
-
-/* --- Helper iov-locking functions --- */
-
-struct dma_page_list {
-       char __user *base_address;
-       int nr_pages;
-       struct page **pages;
-};
-
-struct dma_pinned_list {
-       int nr_iovecs;
-       struct dma_page_list page_list[0];
-};
-
-struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len);
-void dma_unpin_iovec_pages(struct dma_pinned_list* pinned_list);
-
-dma_cookie_t dma_memcpy_to_iovec(struct dma_chan *chan, struct iovec *iov,
-       struct dma_pinned_list *pinned_list, unsigned char *kdata, size_t len);
-dma_cookie_t dma_memcpy_pg_to_iovec(struct dma_chan *chan, struct iovec *iov,
-       struct dma_pinned_list *pinned_list, struct page *page,
-       unsigned int offset, size_t len);
-
 #endif /* DMAENGINE_H */
index 31591686ac2dd8ab88cee881d7fc42a896522525..996111000a8c014556ff5997e609aeb28bd5ec1d 100644 (file)
@@ -21,4 +21,10 @@ struct space_resv {
 #define FS_IOC_RESVSP          _IOW('X', 40, struct space_resv)
 #define FS_IOC_RESVSP64                _IOW('X', 42, struct space_resv)
 
+#define        FALLOC_FL_SUPPORTED_MASK        (FALLOC_FL_KEEP_SIZE |          \
+                                        FALLOC_FL_PUNCH_HOLE |         \
+                                        FALLOC_FL_COLLAPSE_RANGE |     \
+                                        FALLOC_FL_ZERO_RANGE |         \
+                                        FALLOC_FL_INSERT_RANGE)
+
 #endif /* _FALLOC_H_ */
index 3089d738232530d1bc873a00bd8eb1a255104483..d4686fe1cac752fb17dd182d8e976ac8053afba1 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _FIXP_ARITH_H
 #define _FIXP_ARITH_H
 
+#include <linux/math64.h>
+
 /*
  * Simplistic fixed-point arithmetics.
  * Hmm, I'm probably duplicating some code :(
 
 #include <linux/types.h>
 
-/* The type representing fixed-point values */
-typedef s16 fixp_t;
+static const s32 sin_table[] = {
+       0x00000000, 0x023be165, 0x04779632, 0x06b2f1d2, 0x08edc7b6, 0x0b27eb5c,
+       0x0d61304d, 0x0f996a26, 0x11d06c96, 0x14060b67, 0x163a1a7d, 0x186c6ddd,
+       0x1a9cd9ac, 0x1ccb3236, 0x1ef74bf2, 0x2120fb82, 0x234815ba, 0x256c6f9e,
+       0x278dde6e, 0x29ac379f, 0x2bc750e8, 0x2ddf003f, 0x2ff31bdd, 0x32037a44,
+       0x340ff241, 0x36185aee, 0x381c8bb5, 0x3a1c5c56, 0x3c17a4e7, 0x3e0e3ddb,
+       0x3fffffff, 0x41ecc483, 0x43d464fa, 0x45b6bb5d, 0x4793a20f, 0x496af3e1,
+       0x4b3c8c11, 0x4d084650, 0x4ecdfec6, 0x508d9210, 0x5246dd48, 0x53f9be04,
+       0x55a6125a, 0x574bb8e5, 0x58ea90c2, 0x5a827999, 0x5c135399, 0x5d9cff82,
+       0x5f1f5ea0, 0x609a52d1, 0x620dbe8a, 0x637984d3, 0x64dd894f, 0x6639b039,
+       0x678dde6d, 0x68d9f963, 0x6a1de735, 0x6b598ea1, 0x6c8cd70a, 0x6db7a879,
+       0x6ed9eba0, 0x6ff389de, 0x71046d3c, 0x720c8074, 0x730baeec, 0x7401e4bf,
+       0x74ef0ebb, 0x75d31a5f, 0x76adf5e5, 0x777f903b, 0x7847d908, 0x7906c0af,
+       0x79bc384c, 0x7a6831b8, 0x7b0a9f8c, 0x7ba3751c, 0x7c32a67c, 0x7cb82884,
+       0x7d33f0c8, 0x7da5f5a3, 0x7e0e2e31, 0x7e6c924f, 0x7ec11aa3, 0x7f0bc095,
+       0x7f4c7e52, 0x7f834ecf, 0x7fb02dc4, 0x7fd317b3, 0x7fec09e1, 0x7ffb025e,
+       0x7fffffff
+};
 
-#define FRAC_N 8
-#define FRAC_MASK ((1<<FRAC_N)-1)
+/**
+ * __fixp_sin32() returns the sin of an angle in degrees
+ *
+ * @degrees: angle, in degrees, from 0 to 360.
+ *
+ * The returned value ranges from -0x7fffffff to +0x7fffffff.
+ */
+static inline s32 __fixp_sin32(int degrees)
+{
+       s32 ret;
+       bool negative = false;
 
-/* Not to be used directly. Use fixp_{cos,sin} */
-static const fixp_t cos_table[46] = {
-       0x0100, 0x00FF, 0x00FF, 0x00FE, 0x00FD, 0x00FC, 0x00FA, 0x00F8,
-       0x00F6, 0x00F3, 0x00F0, 0x00ED, 0x00E9, 0x00E6, 0x00E2, 0x00DD,
-       0x00D9, 0x00D4, 0x00CF, 0x00C9, 0x00C4, 0x00BE, 0x00B8, 0x00B1,
-       0x00AB, 0x00A4, 0x009D, 0x0096, 0x008F, 0x0087, 0x0080, 0x0078,
-       0x0070, 0x0068, 0x005F, 0x0057, 0x004F, 0x0046, 0x003D, 0x0035,
-       0x002C, 0x0023, 0x001A, 0x0011, 0x0008, 0x0000
-};
+       if (degrees > 180) {
+               negative = true;
+               degrees -= 180;
+       }
+       if (degrees > 90)
+               degrees = 180 - degrees;
 
+       ret = sin_table[degrees];
 
-/* a: 123 -> 123.0 */
-static inline fixp_t fixp_new(s16 a)
-{
-       return a<<FRAC_N;
+       return negative ? -ret : ret;
 }
 
-/* a: 0xFFFF -> -1.0
-      0x8000 -> 1.0
-      0x0000 -> 0.0
-*/
-static inline fixp_t fixp_new16(s16 a)
+/**
+ * fixp_sin32() returns the sin of an angle in degrees
+ *
+ * @degrees: angle, in degrees. The angle can be positive or negative
+ *
+ * The returned value ranges from -0x7fffffff to +0x7fffffff.
+ */
+static inline s32 fixp_sin32(int degrees)
 {
-       return ((s32)a)>>(16-FRAC_N);
+       degrees = (degrees % 360 + 360) % 360;
+
+       return __fixp_sin32(degrees);
 }
 
-static inline fixp_t fixp_cos(unsigned int degrees)
+/* cos(x) = sin(x + 90 degrees) */
+#define fixp_cos32(v) fixp_sin32((v) + 90)
+
+/*
+ * 16 bits variants
+ *
+ * The returned value ranges from -0x7fff to 0x7fff
+ */
+
+#define fixp_sin16(v) (fixp_sin32(v) >> 16)
+#define fixp_cos16(v) (fixp_cos32(v) >> 16)
+
+/**
+ * fixp_sin32_rad() - calculates the sin of an angle in radians
+ *
+ * @radians: angle, in radians
+ * @twopi: value to be used for 2*pi
+ *
+ * Provides a variant for the cases where just 360
+ * values is not enough. This function uses linear
+ * interpolation to a wider range of values given by
+ * twopi var.
+ *
+ * Experimental tests gave a maximum difference of
+ * 0.000038 between the value calculated by sin() and
+ * the one produced by this function, when twopi is
+ * equal to 360000. That seems to be enough precision
+ * for practical purposes.
+ *
+ * Please notice that two high numbers for twopi could cause
+ * overflows, so the routine will not allow values of twopi
+ * bigger than 1^18.
+ */
+static inline s32 fixp_sin32_rad(u32 radians, u32 twopi)
 {
-       int quadrant = (degrees / 90) & 3;
-       unsigned int i = degrees % 90;
+       int degrees;
+       s32 v1, v2, dx, dy;
+       s64 tmp;
 
-       if (quadrant == 1 || quadrant == 3)
-               i = 90 - i;
+       /*
+        * Avoid too large values for twopi, as we don't want overflows.
+        */
+       BUG_ON(twopi > 1 << 18);
 
-       i >>= 1;
+       degrees = (radians * 360) / twopi;
+       tmp = radians - (degrees * twopi) / 360;
 
-       return (quadrant == 1 || quadrant == 2)? -cos_table[i] : cos_table[i];
-}
+       degrees = (degrees % 360 + 360) % 360;
+       v1 = __fixp_sin32(degrees);
 
-static inline fixp_t fixp_sin(unsigned int degrees)
-{
-       return -fixp_cos(degrees + 90);
-}
+       v2 = fixp_sin32(degrees + 1);
 
-static inline fixp_t fixp_mult(fixp_t a, fixp_t b)
-{
-       return ((s32)(a*b))>>FRAC_N;
+       dx = twopi / 360;
+       dy = v2 - v1;
+
+       tmp *= dy;
+
+       return v1 +  div_s64(tmp, dx);
 }
 
+/* cos(x) = sin(x + pi/2 radians) */
+
+#define fixp_cos32_rad(rad, twopi)     \
+       fixp_sin32_rad(rad + twopi / 4, twopi)
+
 #endif
index c7496f2638601e89d1bc6048653a75aac149ce53..35ec87e490b1a41ff0bc3ba20b06ac9d958f972a 100644 (file)
@@ -1820,7 +1820,7 @@ struct super_operations {
 #define I_SYNC                 (1 << __I_SYNC)
 #define I_REFERENCED           (1 << 8)
 #define __I_DIO_WAKEUP         9
-#define I_DIO_WAKEUP           (1 << I_DIO_WAKEUP)
+#define I_DIO_WAKEUP           (1 << __I_DIO_WAKEUP)
 #define I_LINKABLE             (1 << 10)
 #define I_DIRTY_TIME           (1 << 11)
 #define __I_DIRTY_TIME_EXPIRED 12
@@ -2644,6 +2644,9 @@ enum {
 
        /* filesystem can handle aio writes beyond i_size */
        DIO_ASYNC_EXTEND = 0x04,
+
+       /* inode/fs/bdev does not need truncate protection */
+       DIO_SKIP_DIO_COUNT = 0x08,
 };
 
 void dio_end_io(struct bio *bio, int error);
@@ -2666,7 +2669,31 @@ static inline ssize_t blockdev_direct_IO(struct kiocb *iocb,
 #endif
 
 void inode_dio_wait(struct inode *inode);
-void inode_dio_done(struct inode *inode);
+
+/*
+ * inode_dio_begin - signal start of a direct I/O requests
+ * @inode: inode the direct I/O happens on
+ *
+ * This is called once we've finished processing a direct I/O request,
+ * and is used to wake up callers waiting for direct I/O to be quiesced.
+ */
+static inline void inode_dio_begin(struct inode *inode)
+{
+       atomic_inc(&inode->i_dio_count);
+}
+
+/*
+ * inode_dio_end - signal finish of a direct I/O requests
+ * @inode: inode the direct I/O happens on
+ *
+ * This is called once we've finished processing a direct I/O request,
+ * and is used to wake up callers waiting for direct I/O to be quiesced.
+ */
+static inline void inode_dio_end(struct inode *inode)
+{
+       if (atomic_dec_and_test(&inode->i_dio_count))
+               wake_up_bit(&inode->i_state, __I_DIO_WAKEUP);
+}
 
 extern void inode_set_flags(struct inode *inode, unsigned int flags,
                            unsigned int mask);
index 5a2ba674795eaf2b2b281eaa17289748cbc84320..902c37aef67e6cf308b0777e157a42dead971c6c 100644 (file)
@@ -646,12 +646,13 @@ struct hv_input_signal_event_buffer {
 };
 
 struct vmbus_channel {
+       /* Unique channel id */
+       int id;
+
        struct list_head listentry;
 
        struct hv_device *device_obj;
 
-       struct work_struct work;
-
        enum vmbus_channel_state state;
 
        struct vmbus_channel_offer_channel offermsg;
@@ -672,7 +673,6 @@ struct vmbus_channel {
        struct hv_ring_buffer_info outbound;    /* send to parent */
        struct hv_ring_buffer_info inbound;     /* receive from parent */
        spinlock_t inbound_lock;
-       struct workqueue_struct *controlwq;
 
        struct vmbus_close_msg close_msg;
 
@@ -758,6 +758,9 @@ struct vmbus_channel {
         * link up channels based on their CPU affinity.
         */
        struct list_head percpu_list;
+
+       int num_sc;
+       int next_oc;
 };
 
 static inline void set_channel_read_state(struct vmbus_channel *c, bool state)
@@ -861,6 +864,14 @@ extern int vmbus_sendpacket(struct vmbus_channel *channel,
                                  enum vmbus_packet_type type,
                                  u32 flags);
 
+extern int vmbus_sendpacket_ctl(struct vmbus_channel *channel,
+                                 void *buffer,
+                                 u32 bufferLen,
+                                 u64 requestid,
+                                 enum vmbus_packet_type type,
+                                 u32 flags,
+                                 bool kick_q);
+
 extern int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
                                            struct hv_page_buffer pagebuffers[],
                                            u32 pagecount,
@@ -868,6 +879,15 @@ extern int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
                                            u32 bufferlen,
                                            u64 requestid);
 
+extern int vmbus_sendpacket_pagebuffer_ctl(struct vmbus_channel *channel,
+                                          struct hv_page_buffer pagebuffers[],
+                                          u32 pagecount,
+                                          void *buffer,
+                                          u32 bufferlen,
+                                          u64 requestid,
+                                          u32 flags,
+                                          bool kick_q);
+
 extern int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
                                        struct hv_multipage_buffer *mpb,
                                        void *buffer,
@@ -1106,6 +1126,16 @@ void vmbus_driver_unregister(struct hv_driver *hv_driver);
                        0x9A, 0xE7, 0x6B, 0x17, 0x49, 0x77, 0xC1, 0x92 \
                }
 
+/*
+ * NetworkDirect. This is the guest RDMA service.
+ * {8c2eaf3d-32a7-4b09-ab99-bd1f1c86b501}
+ */
+#define HV_ND_GUID \
+       .guid = { \
+                       0x3d, 0xaf, 0x2e, 0x8c, 0xa7, 0x32, 0x09, 0x4b, \
+                       0xab, 0x99, 0xbd, 0x1f, 0x1c, 0x86, 0xb5, 0x01 \
+               }
+
 /*
  * Common header for Hyper-V ICs
  */
@@ -1213,6 +1243,7 @@ void hv_kvp_onchannelcallback(void *);
 int hv_vss_init(struct hv_util_service *);
 void hv_vss_deinit(void);
 void hv_vss_onchannelcallback(void *);
+void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid);
 
 extern struct resource hyperv_mmio;
 
index ecaf3a93784527cb6ee93c2b3f20f3fd9c66c520..0af9b03e2b1c8cd4a46d99eebe0bbe589f50b864 100644 (file)
@@ -115,10 +115,19 @@ static inline void dmar_writeq(void __iomem *addr, u64 val)
  * Extended Capability Register
  */
 
-#define ecap_niotlb_iunits(e)  ((((e) >> 24) & 0xff) + 1)
+#define ecap_pss(e)            ((e >> 35) & 0x1f)
+#define ecap_eafs(e)           ((e >> 34) & 0x1)
+#define ecap_nwfs(e)           ((e >> 33) & 0x1)
+#define ecap_srs(e)            ((e >> 31) & 0x1)
+#define ecap_ers(e)            ((e >> 30) & 0x1)
+#define ecap_prs(e)            ((e >> 29) & 0x1)
+#define ecap_pasid(e)          ((e >> 28) & 0x1)
+#define ecap_dis(e)            ((e >> 27) & 0x1)
+#define ecap_nest(e)           ((e >> 26) & 0x1)
+#define ecap_mts(e)            ((e >> 25) & 0x1)
+#define ecap_ecs(e)            ((e >> 24) & 0x1)
 #define ecap_iotlb_offset(e)   ((((e) >> 8) & 0x3ff) * 16)
-#define ecap_max_iotlb_offset(e) \
-       (ecap_iotlb_offset(e) + ecap_niotlb_iunits(e) * 16)
+#define ecap_max_iotlb_offset(e) (ecap_iotlb_offset(e) + 16)
 #define ecap_coherent(e)       ((e) & 0x1)
 #define ecap_qis(e)            ((e) & 0x2)
 #define ecap_pass_through(e)   ((e >> 6) & 0x1)
@@ -180,6 +189,9 @@ static inline void dmar_writeq(void __iomem *addr, u64 val)
 #define DMA_GSTS_IRES (((u32)1) << 25)
 #define DMA_GSTS_CFIS (((u32)1) << 23)
 
+/* DMA_RTADDR_REG */
+#define DMA_RTADDR_RTT (((u64)1) << 11)
+
 /* CCMD_REG */
 #define DMA_CCMD_ICC (((u64)1) << 63)
 #define DMA_CCMD_GLOBAL_INVL (((u64)1) << 61)
index 4cc299c598e0309919fe7e70162efba6a2a355e3..986f2bffea1edc95513361a76fa55df5a3e06c06 100644 (file)
@@ -72,6 +72,8 @@ void __iomem *devm_ioremap(struct device *dev, resource_size_t offset,
                           resource_size_t size);
 void __iomem *devm_ioremap_nocache(struct device *dev, resource_size_t offset,
                                   resource_size_t size);
+void __iomem *devm_ioremap_wc(struct device *dev, resource_size_t offset,
+                                  resource_size_t size);
 void devm_iounmap(struct device *dev, void __iomem *addr);
 int check_signature(const volatile void __iomem *io_addr,
                        const unsigned char *signature, int length);
diff --git a/include/linux/irqchip/arm-gic-acpi.h b/include/linux/irqchip/arm-gic-acpi.h
new file mode 100644 (file)
index 0000000..de3419e
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014, Linaro Ltd.
+ *     Author: Tomasz Nowicki <tomasz.nowicki@linaro.org>
+ *
+ * This program is free software; you can 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 ARM_GIC_ACPI_H_
+#define ARM_GIC_ACPI_H_
+
+#ifdef CONFIG_ACPI
+
+/*
+ * Hard code here, we can not get memory size from MADT (but FDT does),
+ * Actually no need to do that, because this size can be inferred
+ * from GIC spec.
+ */
+#define ACPI_GICV2_DIST_MEM_SIZE       (SZ_4K)
+#define ACPI_GIC_CPU_IF_MEM_SIZE       (SZ_8K)
+
+struct acpi_table_header;
+
+int gic_v2_acpi_init(struct acpi_table_header *table);
+void acpi_gic_init(void);
+#else
+static inline void acpi_gic_init(void) { }
+#endif
+
+#endif /* ARM_GIC_ACPI_H_ */
diff --git a/include/linux/jz4780-nemc.h b/include/linux/jz4780-nemc.h
new file mode 100644 (file)
index 0000000..e7f1cc7
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * JZ4780 NAND/external memory controller (NEMC)
+ *
+ * Copyright (c) 2015 Imagination Technologies
+ * Author: Alex Smith <alex@alex-smith.me.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __LINUX_JZ4780_NEMC_H__
+#define __LINUX_JZ4780_NEMC_H__
+
+#include <linux/types.h>
+
+struct device;
+
+/*
+ * Number of NEMC banks. Note that there are actually 6, but they are numbered
+ * from 1.
+ */
+#define JZ4780_NEMC_NUM_BANKS  7
+
+/**
+ * enum jz4780_nemc_bank_type - device types which can be connected to a bank
+ * @JZ4780_NEMC_BANK_SRAM: SRAM
+ * @JZ4780_NEMC_BANK_NAND: NAND
+ */
+enum jz4780_nemc_bank_type {
+       JZ4780_NEMC_BANK_SRAM,
+       JZ4780_NEMC_BANK_NAND,
+};
+
+extern unsigned int jz4780_nemc_num_banks(struct device *dev);
+
+extern void jz4780_nemc_set_type(struct device *dev, unsigned int bank,
+                                enum jz4780_nemc_bank_type type);
+extern void jz4780_nemc_assert(struct device *dev, unsigned int bank,
+                              bool assert);
+
+#endif /* __LINUX_JZ4780_NEMC_H__ */
index 63ca8dacec59c7165b612200f4c4573fc039cc2a..b33c7797eb5707122e9acc4167f15317d0069c39 100644 (file)
  */
 #define IS_MODULE(option) config_enabled(option##_MODULE)
 
+/*
+ * IS_REACHABLE(CONFIG_FOO) evaluates to 1 if the currently compiled
+ * code can call a function defined in code compiled based on CONFIG_FOO.
+ * This is similar to IS_ENABLED(), but returns false when invoked from
+ * built-in code when CONFIG_FOO is set to 'm'.
+ */
+#define IS_REACHABLE(option) (config_enabled(option) || \
+                (config_enabled(option##_MODULE) && config_enabled(MODULE)))
+
 /*
  * IS_ENABLED(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y' or 'm',
  * 0 otherwise.
index e60a745ac1982cd0ba11c29bad97d3175c681002..e804306ef5e88d7b02b8b7399b4d525c16b69cd3 100644 (file)
 #error KEXEC_CONTROL_MEMORY_LIMIT not defined
 #endif
 
+#ifndef KEXEC_CONTROL_MEMORY_GFP
+#define KEXEC_CONTROL_MEMORY_GFP GFP_KERNEL
+#endif
+
 #ifndef KEXEC_CONTROL_PAGE_SIZE
 #error KEXEC_CONTROL_PAGE_SIZE not defined
 #endif
index 9962c6bb1311f199ce91600d22724fd7599020dd..6db19f35f7c51e9d3206d8d839724bcfb6256a5d 100644 (file)
@@ -61,8 +61,8 @@ struct lguest_data {
        u32 tsc_khz;
 
 /* Fields initialized by the Guest at boot: */
-       /* Instruction range to suppress interrupts even if enabled */
-       unsigned long noirq_start, noirq_end;
+       /* Instruction to suppress interrupts even if enabled */
+       unsigned long noirq_iret;
        /* Address above which page tables are all identical. */
        unsigned long kernel_address;
        /* The vector to try to use for system calls (0x40 or 0x80). */
index f97010576f56181be46683434b27d1095c855409..16a498f48169a186d45ccd74366873e3d6878ffe 100644 (file)
@@ -127,7 +127,7 @@ struct arizona {
        struct regmap_irq_chip_data *aod_irq_chip;
        struct regmap_irq_chip_data *irq_chip;
 
-       bool hpdet_magic;
+       bool hpdet_clamp;
        unsigned int hp_ena;
 
        struct mutex clk_lock;
index 0e166b92f5b4f8b5499d37f35f5d9d7b050b5cc5..324a34683971e9a01513590dd11c97aeb0e7d4a3 100644 (file)
@@ -16,6 +16,7 @@
 #ifndef __LINUX_MFD_CROS_EC_H
 #define __LINUX_MFD_CROS_EC_H
 
+#include <linux/cdev.h>
 #include <linux/notifier.h>
 #include <linux/mfd/cros_ec_commands.h>
 #include <linux/mutex.h>
@@ -38,20 +39,20 @@ enum {
 /*
  * @version: Command version number (often 0)
  * @command: Command to send (EC_CMD_...)
- * @outdata: Outgoing data to EC
  * @outsize: Outgoing length in bytes
- * @indata: Where to put the incoming data from EC
  * @insize: Max number of bytes to accept from EC
  * @result: EC's response to the command (separate from communication failure)
+ * @outdata: Outgoing data to EC
+ * @indata: Where to put the incoming data from EC
  */
 struct cros_ec_command {
        uint32_t version;
        uint32_t command;
-       uint8_t *outdata;
        uint32_t outsize;
-       uint8_t *indata;
        uint32_t insize;
        uint32_t result;
+       uint8_t outdata[EC_PROTO2_MAX_PARAM_SIZE];
+       uint8_t indata[EC_PROTO2_MAX_PARAM_SIZE];
 };
 
 /**
@@ -59,9 +60,17 @@ struct cros_ec_command {
  *
  * @ec_name: name of EC device (e.g. 'chromeos-ec')
  * @phys_name: name of physical comms layer (e.g. 'i2c-4')
- * @dev: Device pointer
+ * @dev: Device pointer for physical comms device
+ * @vdev: Device pointer for virtual comms device
+ * @cdev: Character device structure for virtual comms device
  * @was_wake_device: true if this device was set to wake the system from
  * sleep at the last suspend
+ * @cmd_readmem: direct read of the EC memory-mapped region, if supported
+ *     @offset is within EC_LPC_ADDR_MEMMAP region.
+ *     @bytes: number of bytes to read. zero means "read a string" (including
+ *     the trailing '\0'). At most only EC_MEMMAP_SIZE bytes can be read.
+ *     Caller must ensure that the buffer is large enough for the result when
+ *     reading a string.
  *
  * @priv: Private data
  * @irq: Interrupt to use
@@ -90,8 +99,12 @@ struct cros_ec_device {
        const char *ec_name;
        const char *phys_name;
        struct device *dev;
+       struct device *vdev;
+       struct cdev cdev;
        bool was_wake_device;
        struct class *cros_class;
+       int (*cmd_readmem)(struct cros_ec_device *ec, unsigned int offset,
+                          unsigned int bytes, void *dest);
 
        /* These are used to implement the platform-specific interface */
        void *priv;
diff --git a/include/linux/mfd/syscon/atmel-st.h b/include/linux/mfd/syscon/atmel-st.h
new file mode 100644 (file)
index 0000000..8acf1ec
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * System Timer (ST) - System peripherals registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef _LINUX_MFD_SYSCON_ATMEL_ST_H
+#define _LINUX_MFD_SYSCON_ATMEL_ST_H
+
+#include <linux/bitops.h>
+
+#define AT91_ST_CR     0x00    /* Control Register */
+#define                AT91_ST_WDRST   BIT(0)  /* Watchdog Timer Restart */
+
+#define AT91_ST_PIMR   0x04    /* Period Interval Mode Register */
+#define                AT91_ST_PIV     0xffff  /* Period Interval Value */
+
+#define AT91_ST_WDMR   0x08    /* Watchdog Mode Register */
+#define                AT91_ST_WDV     0xffff  /* Watchdog Counter Value */
+#define                AT91_ST_RSTEN   BIT(16) /* Reset Enable */
+#define                AT91_ST_EXTEN   BIT(17) /* External Signal Assertion Enable */
+
+#define AT91_ST_RTMR   0x0c    /* Real-time Mode Register */
+#define                AT91_ST_RTPRES  0xffff  /* Real-time Prescalar Value */
+
+#define AT91_ST_SR     0x10    /* Status Register */
+#define                AT91_ST_PITS    BIT(0)  /* Period Interval Timer Status */
+#define                AT91_ST_WDOVF   BIT(1)  /* Watchdog Overflow */
+#define                AT91_ST_RTTINC  BIT(2)  /* Real-time Timer Increment */
+#define                AT91_ST_ALMS    BIT(3)  /* Alarm Status */
+
+#define AT91_ST_IER    0x14    /* Interrupt Enable Register */
+#define AT91_ST_IDR    0x18    /* Interrupt Disable Register */
+#define AT91_ST_IMR    0x1c    /* Interrupt Mask Register */
+
+#define AT91_ST_RTAR   0x20    /* Real-time Alarm Register */
+#define                AT91_ST_ALMV    0xfffff /* Alarm Value */
+
+#define AT91_ST_CRTR   0x24    /* Current Real-time Register */
+#define                AT91_ST_CRTV    0xfffff /* Current Real-Time Value */
+
+#endif /* _LINUX_MFD_SYSCON_ATMEL_ST_H */
index c877cad61a132586086c6c51ef327a2877d393d2..d16f4c82c568f13ad6e025d28951cb8978e4c3e2 100644 (file)
 #define IMX6Q_GPR3_LVDS0_MUX_CTL_IPU1_DI1      (0x1 << 6)
 #define IMX6Q_GPR3_LVDS0_MUX_CTL_IPU2_DI0      (0x2 << 6)
 #define IMX6Q_GPR3_LVDS0_MUX_CTL_IPU2_DI1      (0x3 << 6)
+#define IMX6Q_GPR3_MIPI_MUX_CTL_SHIFT          4
 #define IMX6Q_GPR3_MIPI_MUX_CTL_MASK           (0x3 << 4)
 #define IMX6Q_GPR3_MIPI_MUX_CTL_IPU1_DI0       (0x0 << 4)
 #define IMX6Q_GPR3_MIPI_MUX_CTL_IPU1_DI1       (0x1 << 4)
index 605812820e483acd798d5e033e2e4d8844f3cb27..24b86d538e8852eef94cc020a7f92230dcfacedd 100644 (file)
@@ -111,6 +111,8 @@ struct dma_chan;
  * data for the MMC controller
  */
 struct tmio_mmc_data {
+       void                            *chan_priv_tx;
+       void                            *chan_priv_rx;
        unsigned int                    hclk;
        unsigned long                   capabilities;
        unsigned long                   capabilities2;
index ee80dd7d9f60fb6e289f798d37b8725d55a71d02..819077c326901384ec3bdb8d16217a1363ab8e28 100644 (file)
@@ -52,6 +52,7 @@
 #define MISC_DYNAMIC_MINOR     255
 
 struct device;
+struct attribute_group;
 
 struct miscdevice  {
        int minor;
@@ -60,6 +61,7 @@ struct miscdevice  {
        struct list_head list;
        struct device *parent;
        struct device *this_device;
+       const struct attribute_group **groups;
        const char *nodename;
        umode_t mode;
 };
index f9ce34bec45b1d615bb1b191bffd867a23dd559a..83e80ab9450048d121b739bd23b85ccb14a39b36 100644 (file)
@@ -1345,6 +1345,10 @@ int mlx4_wol_write(struct mlx4_dev *dev, u64 config, int port);
 int mlx4_counter_alloc(struct mlx4_dev *dev, u32 *idx);
 void mlx4_counter_free(struct mlx4_dev *dev, u32 idx);
 
+void mlx4_set_admin_guid(struct mlx4_dev *dev, __be64 guid, int entry,
+                        int port);
+__be64 mlx4_get_admin_guid(struct mlx4_dev *dev, int entry, int port);
+void mlx4_set_random_admin_guid(struct mlx4_dev *dev, int entry, int port);
 int mlx4_flow_attach(struct mlx4_dev *dev,
                     struct mlx4_net_trans_rule *rule, u64 *reg_id);
 int mlx4_flow_detach(struct mlx4_dev *dev, u64 reg_id);
index 8b086070c3a585d2558467bc547ac450bbaac699..0755b9fd03a7d936e805efb71cfc1d371ddea0d6 100644 (file)
@@ -499,7 +499,7 @@ static inline int page_count(struct page *page)
 
 static inline bool __compound_tail_refcounted(struct page *page)
 {
-       return PageAnon(page) && !PageSlab(page) && !PageHeadHuge(page);
+       return !PageSlab(page) && !PageHeadHuge(page);
 }
 
 /*
index a6cf4c063e4e50f7d778ccd00ecbb373cc0e4717..19f0175c0afa68a99faf3684dda69fe7967ef5a3 100644 (file)
@@ -512,8 +512,18 @@ static inline int mmc_card_broken_irq_polling(const struct mmc_card *c)
 
 #define mmc_dev_to_card(d)     container_of(d, struct mmc_card, dev)
 
-extern int mmc_register_driver(struct device_driver *);
-extern void mmc_unregister_driver(struct device_driver *);
+/*
+ * MMC device driver (e.g., Flash card, I/O card...)
+ */
+struct mmc_driver {
+       struct device_driver drv;
+       int (*probe)(struct mmc_card *);
+       void (*remove)(struct mmc_card *);
+       void (*shutdown)(struct mmc_card *);
+};
+
+extern int mmc_register_driver(struct mmc_driver *);
+extern void mmc_unregister_driver(struct mmc_driver *);
 
 extern void mmc_fixup_device(struct mmc_card *card,
                             const struct mmc_fixup *table);
index da77e5e2041d64422cba234930634fc281064324..95d6f0314a7ded402fc800ef6f3af6f1fc2f1615 100644 (file)
@@ -7,14 +7,4 @@
 #define SH_MOBILE_SDHI_IRQ_SDCARD      "sdcard"
 #define SH_MOBILE_SDHI_IRQ_SDIO                "sdio"
 
-struct sh_mobile_sdhi_info {
-       int dma_slave_tx;
-       int dma_slave_rx;
-       unsigned long tmio_flags;
-       unsigned long tmio_caps;
-       unsigned long tmio_caps2;
-       u32 tmio_ocr_mask;      /* available MMC voltages */
-       unsigned int cd_gpio;
-};
-
 #endif /* LINUX_MMC_SH_MOBILE_SDHI_H */
index 5f487d77641174626c14c0857d2cad96aea92ffd..29975c73a95347a582a98b4cf09baf0fea47c7b0 100644 (file)
@@ -77,7 +77,7 @@
 /* ensure we never evaluate anything shorted than an unsigned long
  * to zero, and ensure we'll never miss the end of an comparison (bjd) */
 
-#define map_calc_words(map) ((map_bankwidth(map) + (sizeof(unsigned long)-1))/ sizeof(unsigned long))
+#define map_calc_words(map) ((map_bankwidth(map) + (sizeof(unsigned long)-1)) / sizeof(unsigned long))
 
 #ifdef CONFIG_MTD_MAP_BANK_WIDTH_8
 # ifdef map_bankwidth
@@ -181,7 +181,7 @@ static inline int map_bankwidth_supported(int w)
        }
 }
 
-#define MAX_MAP_LONGS ( ((MAX_MAP_BANKWIDTH*8) + BITS_PER_LONG - 1) / BITS_PER_LONG )
+#define MAX_MAP_LONGS (((MAX_MAP_BANKWIDTH * 8) + BITS_PER_LONG - 1) / BITS_PER_LONG)
 
 typedef union {
        unsigned long x[MAX_MAP_LONGS];
@@ -264,20 +264,22 @@ void unregister_mtd_chip_driver(struct mtd_chip_driver *);
 struct mtd_info *do_map_probe(const char *name, struct map_info *map);
 void map_destroy(struct mtd_info *mtd);
 
-#define ENABLE_VPP(map) do { if(map->set_vpp) map->set_vpp(map, 1); } while(0)
-#define DISABLE_VPP(map) do { if(map->set_vpp) map->set_vpp(map, 0); } while(0)
+#define ENABLE_VPP(map) do { if (map->set_vpp) map->set_vpp(map, 1); } while (0)
+#define DISABLE_VPP(map) do { if (map->set_vpp) map->set_vpp(map, 0); } while (0)
 
 #define INVALIDATE_CACHED_RANGE(map, from, size) \
-       do { if(map->inval_cache) map->inval_cache(map, from, size); } while(0)
+       do { if (map->inval_cache) map->inval_cache(map, from, size); } while (0)
 
 
 static inline int map_word_equal(struct map_info *map, map_word val1, map_word val2)
 {
        int i;
-       for (i=0; i<map_words(map); i++) {
+
+       for (i = 0; i < map_words(map); i++) {
                if (val1.x[i] != val2.x[i])
                        return 0;
        }
+
        return 1;
 }
 
@@ -286,9 +288,9 @@ static inline map_word map_word_and(struct map_info *map, map_word val1, map_wor
        map_word r;
        int i;
 
-       for (i=0; i<map_words(map); i++) {
+       for (i = 0; i < map_words(map); i++)
                r.x[i] = val1.x[i] & val2.x[i];
-       }
+
        return r;
 }
 
@@ -297,9 +299,9 @@ static inline map_word map_word_clr(struct map_info *map, map_word val1, map_wor
        map_word r;
        int i;
 
-       for (i=0; i<map_words(map); i++) {
+       for (i = 0; i < map_words(map); i++)
                r.x[i] = val1.x[i] & ~val2.x[i];
-       }
+
        return r;
 }
 
@@ -308,22 +310,33 @@ static inline map_word map_word_or(struct map_info *map, map_word val1, map_word
        map_word r;
        int i;
 
-       for (i=0; i<map_words(map); i++) {
+       for (i = 0; i < map_words(map); i++)
                r.x[i] = val1.x[i] | val2.x[i];
-       }
+
        return r;
 }
 
-#define map_word_andequal(m, a, b, z) map_word_equal(m, z, map_word_and(m, a, b))
+static inline int map_word_andequal(struct map_info *map, map_word val1, map_word val2, map_word val3)
+{
+       int i;
+
+       for (i = 0; i < map_words(map); i++) {
+               if ((val1.x[i] & val2.x[i]) != val3.x[i])
+                       return 0;
+       }
+
+       return 1;
+}
 
 static inline int map_word_bitsset(struct map_info *map, map_word val1, map_word val2)
 {
        int i;
 
-       for (i=0; i<map_words(map); i++) {
+       for (i = 0; i < map_words(map); i++) {
                if (val1.x[i] & val2.x[i])
                        return 1;
        }
+
        return 0;
 }
 
@@ -355,14 +368,16 @@ static inline map_word map_word_load_partial(struct map_info *map, map_word orig
 
        if (map_bankwidth_is_large(map)) {
                char *dest = (char *)&orig;
+
                memcpy(dest+start, buf, len);
        } else {
-               for (i=start; i < start+len; i++) {
+               for (i = start; i < start+len; i++) {
                        int bitpos;
+
 #ifdef __LITTLE_ENDIAN
-                       bitpos = i*8;
+                       bitpos = i * 8;
 #else /* __BIG_ENDIAN */
-                       bitpos = (map_bankwidth(map)-1-i)*8;
+                       bitpos = (map_bankwidth(map) - 1 - i) * 8;
 #endif
                        orig.x[0] &= ~(0xff << bitpos);
                        orig.x[0] |= (unsigned long)buf[i-start] << bitpos;
@@ -384,9 +399,10 @@ static inline map_word map_word_ff(struct map_info *map)
 
        if (map_bankwidth(map) < MAP_FF_LIMIT) {
                int bw = 8 * map_bankwidth(map);
+
                r.x[0] = (1UL << bw) - 1;
        } else {
-               for (i=0; i<map_words(map); i++)
+               for (i = 0; i < map_words(map); i++)
                        r.x[i] = ~0UL;
        }
        return r;
@@ -407,7 +423,7 @@ static inline map_word inline_map_read(struct map_info *map, unsigned long ofs)
                r.x[0] = __raw_readq(map->virt + ofs);
 #endif
        else if (map_bankwidth_is_large(map))
-               memcpy_fromio(r.x, map->virt+ofs, map->bankwidth);
+               memcpy_fromio(r.x, map->virt + ofs, map->bankwidth);
        else
                BUG();
 
index 4720b86ee73dce54e39516f3d3371409d1254d3a..e5409524bb0aeca355b5bd44ce2bddb03ceca5da 100644 (file)
@@ -155,6 +155,8 @@ enum spi_nor_option_flags {
  * @write:             [DRIVER-SPECIFIC] write data to the SPI NOR
  * @erase:             [DRIVER-SPECIFIC] erase a sector of the SPI NOR
  *                     at the offset @offs
+ * @lock:              [FLASH-SPECIFIC] lock a region of the SPI NOR
+ * @unlock:            [FLASH-SPECIFIC] unlock a region of the SPI NOR
  * @priv:              the private data
  */
 struct spi_nor {
@@ -189,6 +191,9 @@ struct spi_nor {
                        size_t len, size_t *retlen, const u_char *write_buf);
        int (*erase)(struct spi_nor *nor, loff_t offs);
 
+       int (*flash_lock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
+       int (*flash_unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
+
        void *priv;
 };
 
index bcbde799ec690157d47b64a3c7e0728865b54bfa..1899c74a712791ba33f7e17f2d139da21da70c42 100644 (file)
@@ -60,6 +60,7 @@ struct phy_device;
 struct wireless_dev;
 /* 802.15.4 specific */
 struct wpan_dev;
+struct mpls_dev;
 
 void netdev_set_default_ethtool_ops(struct net_device *dev,
                                    const struct ethtool_ops *ops);
@@ -976,7 +977,8 @@ typedef u16 (*select_queue_fallback_t)(struct net_device *dev,
  * int (*ndo_bridge_setlink)(struct net_device *dev, struct nlmsghdr *nlh,
  *                          u16 flags)
  * int (*ndo_bridge_getlink)(struct sk_buff *skb, u32 pid, u32 seq,
- *                          struct net_device *dev, u32 filter_mask)
+ *                          struct net_device *dev, u32 filter_mask,
+ *                          int nlflags)
  * int (*ndo_bridge_dellink)(struct net_device *dev, struct nlmsghdr *nlh,
  *                          u16 flags);
  *
@@ -1172,7 +1174,8 @@ struct net_device_ops {
        int                     (*ndo_bridge_getlink)(struct sk_buff *skb,
                                                      u32 pid, u32 seq,
                                                      struct net_device *dev,
-                                                     u32 filter_mask);
+                                                     u32 filter_mask,
+                                                     int nlflags);
        int                     (*ndo_bridge_dellink)(struct net_device *dev,
                                                      struct nlmsghdr *nlh,
                                                      u16 flags);
@@ -1627,6 +1630,9 @@ struct net_device {
        void                    *ax25_ptr;
        struct wireless_dev     *ieee80211_ptr;
        struct wpan_dev         *ieee802154_ptr;
+#if IS_ENABLED(CONFIG_MPLS_ROUTING)
+       struct mpls_dev __rcu   *mpls_ptr;
+#endif
 
 /*
  * Cache lines mostly used on receive path (including eth_type_trans())
@@ -2021,10 +2027,10 @@ struct pcpu_sw_netstats {
 ({                                                             \
        typeof(type) __percpu *pcpu_stats = alloc_percpu(type); \
        if (pcpu_stats) {                                       \
-               int i;                                          \
-               for_each_possible_cpu(i) {                      \
+               int __cpu;                                      \
+               for_each_possible_cpu(__cpu) {                  \
                        typeof(type) *stat;                     \
-                       stat = per_cpu_ptr(pcpu_stats, i);      \
+                       stat = per_cpu_ptr(pcpu_stats, __cpu);  \
                        u64_stats_init(&stat->syncp);           \
                }                                               \
        }                                                       \
index ab8f76dba6680f485943545407daeb117620b489..f2fdb5a520709551462ca8b95cf9793b2f182af6 100644 (file)
@@ -39,12 +39,24 @@ static inline void br_drop_fake_rtable(struct sk_buff *skb)
 
 static inline int nf_bridge_get_physinif(const struct sk_buff *skb)
 {
-       return skb->nf_bridge ? skb->nf_bridge->physindev->ifindex : 0;
+       struct nf_bridge_info *nf_bridge;
+
+       if (skb->nf_bridge == NULL)
+               return 0;
+
+       nf_bridge = skb->nf_bridge;
+       return nf_bridge->physindev ? nf_bridge->physindev->ifindex : 0;
 }
 
 static inline int nf_bridge_get_physoutif(const struct sk_buff *skb)
 {
-       return skb->nf_bridge ? skb->nf_bridge->physoutdev->ifindex : 0;
+       struct nf_bridge_info *nf_bridge;
+
+       if (skb->nf_bridge == NULL)
+               return 0;
+
+       nf_bridge = skb->nf_bridge;
+       return nf_bridge->physoutdev ? nf_bridge->physoutdev->ifindex : 0;
 }
 
 static inline struct net_device *
index ed43cb74b11d75d27c9008c3a49a6a3aa68fb353..32201c269890433817f1fac83026d95fa760b996 100644 (file)
 #include <linux/uidgid.h>
 #include <uapi/linux/nfs4.h>
 
+enum nfs4_acl_whotype {
+       NFS4_ACL_WHO_NAMED = 0,
+       NFS4_ACL_WHO_OWNER,
+       NFS4_ACL_WHO_GROUP,
+       NFS4_ACL_WHO_EVERYONE,
+};
+
 struct nfs4_ace {
        uint32_t        type;
        uint32_t        flag;
index 410abd172febee648d8f63cab2e00592773ddaed..b95f914ce083891325b6b8defa3f9995851cf76b 100644 (file)
@@ -511,6 +511,7 @@ extern int  nfs_updatepage(struct file *, struct page *, unsigned int, unsigned
  * Try to write back everything synchronously (but check the
  * return value!)
  */
+extern int nfs_sync_inode(struct inode *inode);
 extern int nfs_wb_all(struct inode *inode);
 extern int nfs_wb_page(struct inode *inode, struct page* page);
 extern int nfs_wb_page_cancel(struct inode *inode, struct page* page);
diff --git a/include/linux/nfs_idmap.h b/include/linux/nfs_idmap.h
deleted file mode 100644 (file)
index 333844e..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * include/linux/nfs_idmap.h
- *
- *  UID and GID to name mapping for clients.
- *
- *  Copyright (c) 2002 The Regents of the University of Michigan.
- *  All rights reserved.
- *
- *  Marius Aamodt Eriksen <marius@umich.edu>
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions
- *  are met:
- *
- *  1. Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *  2. Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *  3. Neither the name of the University nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef NFS_IDMAP_H
-#define NFS_IDMAP_H
-
-#include <linux/uidgid.h>
-#include <uapi/linux/nfs_idmap.h>
-
-
-/* Forward declaration to make this header independent of others */
-struct nfs_client;
-struct nfs_server;
-struct nfs_fattr;
-struct nfs4_string;
-
-#if IS_ENABLED(CONFIG_NFS_V4)
-int nfs_idmap_init(void);
-void nfs_idmap_quit(void);
-#else
-static inline int nfs_idmap_init(void)
-{
-       return 0;
-}
-
-static inline void nfs_idmap_quit(void)
-{}
-#endif
-
-int nfs_idmap_new(struct nfs_client *);
-void nfs_idmap_delete(struct nfs_client *);
-
-void nfs_fattr_init_names(struct nfs_fattr *fattr,
-               struct nfs4_string *owner_name,
-               struct nfs4_string *group_name);
-void nfs_fattr_free_names(struct nfs_fattr *);
-void nfs_fattr_map_and_free_names(struct nfs_server *, struct nfs_fattr *);
-
-int nfs_map_name_to_uid(const struct nfs_server *, const char *, size_t, kuid_t *);
-int nfs_map_group_to_gid(const struct nfs_server *, const char *, size_t, kgid_t *);
-int nfs_map_uid_to_name(const struct nfs_server *, kuid_t, char *, size_t);
-int nfs_map_gid_to_group(const struct nfs_server *, kgid_t, char *, size_t);
-
-int nfs_map_string_to_numeric(const char *name, size_t namelen, __u32 *res);
-
-extern unsigned int nfs_idmap_cache_timeout;
-#endif /* NFS_IDMAP_H */
index 4cb3eaa89cf708a57038049db0df75144155d920..93ab6071bbe967b56ea44c56111157f8a9135e3f 100644 (file)
@@ -255,11 +255,13 @@ struct nfs4_layoutget {
 struct nfs4_getdeviceinfo_args {
        struct nfs4_sequence_args seq_args;
        struct pnfs_device *pdev;
+       __u32 notify_types;
 };
 
 struct nfs4_getdeviceinfo_res {
        struct nfs4_sequence_res seq_res;
        struct pnfs_device *pdev;
+       __u32 notification;
 };
 
 struct nfs4_layoutcommit_args {
@@ -1271,11 +1273,15 @@ struct nfs42_falloc_args {
        nfs4_stateid                     falloc_stateid;
        u64                              falloc_offset;
        u64                              falloc_length;
+       const u32                       *falloc_bitmask;
 };
 
 struct nfs42_falloc_res {
        struct nfs4_sequence_res        seq_res;
        unsigned int                    status;
+
+       struct nfs_fattr                *falloc_fattr;
+       const struct nfs_server         *falloc_server;
 };
 
 struct nfs42_seek_args {
index ff3fea3194c6a05e291de61df2cae02cec8d5348..9abb763e4b863e81aedcd34b868a597b3aaf3567 100644 (file)
@@ -460,7 +460,7 @@ struct nilfs_btree_node {
 /* level */
 #define NILFS_BTREE_LEVEL_DATA          0
 #define NILFS_BTREE_LEVEL_NODE_MIN      (NILFS_BTREE_LEVEL_DATA + 1)
-#define NILFS_BTREE_LEVEL_MAX           14
+#define NILFS_BTREE_LEVEL_MAX           14     /* Max level (exclusive) */
 
 /**
  * struct nilfs_palloc_group_desc - block group descriptor
index 5f124f685e0752952aafe2758a471c077410452e..ddeaae6d2083b256b21b930f3eed8182510e26a8 100644 (file)
@@ -305,6 +305,7 @@ extern int of_property_read_string_helper(struct device_node *np,
 extern int of_device_is_compatible(const struct device_node *device,
                                   const char *);
 extern bool of_device_is_available(const struct device_node *device);
+extern bool of_device_is_big_endian(const struct device_node *device);
 extern const void *of_get_property(const struct device_node *node,
                                const char *name,
                                int *lenp);
@@ -467,6 +468,11 @@ static inline bool of_device_is_available(const struct device_node *device)
        return false;
 }
 
+static inline bool of_device_is_big_endian(const struct device_node *device)
+{
+       return false;
+}
+
 static inline struct property *of_find_property(const struct device_node *np,
                                                const char *name,
                                                int *lenp)
index 0ff360d5b3b3078b1ca85d29696d02741473edd0..587ee507965d78a1b16112a0e3c0bba7856f1d3e 100644 (file)
@@ -33,6 +33,8 @@ extern void *of_fdt_get_property(const void *blob,
 extern int of_fdt_is_compatible(const void *blob,
                                unsigned long node,
                                const char *compat);
+extern bool of_fdt_is_big_endian(const void *blob,
+                                unsigned long node);
 extern int of_fdt_match(const void *blob, unsigned long node,
                        const char *const *compat);
 extern void of_fdt_unflatten_tree(unsigned long *blob,
index bfec136a6d1e60f89f85d93cab465a6a392f7b66..d884929a77479782f9486ac486d0bad444bfcef8 100644 (file)
@@ -37,8 +37,6 @@ extern int of_irq_parse_one(struct device_node *device, int index,
 extern unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data);
 extern int of_irq_to_resource(struct device_node *dev, int index,
                              struct resource *r);
-extern int of_irq_to_resource_table(struct device_node *dev,
-               struct resource *res, int nr_irqs);
 
 extern void of_irq_init(const struct of_device_id *matches);
 
@@ -46,6 +44,8 @@ extern void of_irq_init(const struct of_device_id *matches);
 extern int of_irq_count(struct device_node *dev);
 extern int of_irq_get(struct device_node *dev, int index);
 extern int of_irq_get_byname(struct device_node *dev, const char *name);
+extern int of_irq_to_resource_table(struct device_node *dev,
+               struct resource *res, int nr_irqs);
 #else
 static inline int of_irq_count(struct device_node *dev)
 {
@@ -59,6 +59,11 @@ static inline int of_irq_get_byname(struct device_node *dev, const char *name)
 {
        return 0;
 }
+static inline int of_irq_to_resource_table(struct device_node *dev,
+                                          struct resource *res, int nr_irqs)
+{
+       return 0;
+}
 #endif
 
 #if defined(CONFIG_OF)
index c2080eebbb479f42f97de28ae0ee45a48a81ddf1..7dee00143afd6c14cee7d3a6060281c0c7a14d36 100644 (file)
@@ -163,7 +163,8 @@ extern unsigned int gpmc_ticks_to_ns(unsigned int ticks);
 
 extern void gpmc_cs_write_reg(int cs, int idx, u32 val);
 extern int gpmc_calc_divider(unsigned int sync_clk);
-extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t);
+extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t,
+                              const struct gpmc_settings *s);
 extern int gpmc_cs_program_settings(int cs, struct gpmc_settings *p);
 extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base);
 extern void gpmc_cs_free(int cs);
index 38cff8f6716dd7f6532a6ecb39b750844b346692..2f7b9a40f627ead2e04d4105ad1eaeab76fdf5bf 100644 (file)
 
 #define PCI_VENDOR_ID_INTEL            0x8086
 #define PCI_DEVICE_ID_INTEL_EESSC      0x0008
-#define PCI_DEVICE_ID_INTEL_SNB_IMC    0x0100
-#define PCI_DEVICE_ID_INTEL_IVB_IMC    0x0154
-#define PCI_DEVICE_ID_INTEL_IVB_E3_IMC 0x0150
-#define PCI_DEVICE_ID_INTEL_HSW_IMC    0x0c00
 #define PCI_DEVICE_ID_INTEL_PXHD_0     0x0320
 #define PCI_DEVICE_ID_INTEL_PXHD_1     0x0321
 #define PCI_DEVICE_ID_INTEL_PXH_0      0x0329
diff --git a/include/linux/platform_data/dma-hsu.h b/include/linux/platform_data/dma-hsu.h
new file mode 100644 (file)
index 0000000..8a1f6a4
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Driver for the High Speed UART DMA
+ *
+ * Copyright (C) 2015 Intel 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.
+ */
+
+#ifndef _PLATFORM_DATA_DMA_HSU_H
+#define _PLATFORM_DATA_DMA_HSU_H
+
+#include <linux/device.h>
+
+struct hsu_dma_slave {
+       struct device   *dma_dev;
+       int             chan_id;
+};
+
+struct hsu_dma_platform_data {
+       unsigned short  nr_channels;
+};
+
+#endif /* _PLATFORM_DATA_DMA_HSU_H */
index eabac4e2fc993b114ae940b1be960f04015ade0f..2d08816720f6d6be449db87ae8238144f85923bf 100644 (file)
@@ -48,6 +48,9 @@ struct sdma_script_start_addrs {
        s32 ssish_2_mcu_addr;
        s32 hdmi_dma_addr;
        /* End of v2 array */
+       s32 zcanfd_2_mcu_addr;
+       s32 zqspi_2_mcu_addr;
+       /* End of v3 array */
 };
 
 /**
diff --git a/include/linux/platform_data/mmc-msm_sdcc.h b/include/linux/platform_data/mmc-msm_sdcc.h
deleted file mode 100644 (file)
index 55aa873..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef __MMC_MSM_SDCC_H
-#define __MMC_MSM_SDCC_H
-
-#include <linux/mmc/host.h>
-#include <linux/mmc/card.h>
-#include <linux/mmc/sdio_func.h>
-
-struct msm_mmc_gpio {
-       unsigned no;
-       const char *name;
-};
-
-struct msm_mmc_gpio_data {
-       struct msm_mmc_gpio *gpio;
-       u8 size;
-};
-
-struct msm_mmc_platform_data {
-       unsigned int ocr_mask;                  /* available voltages */
-       u32 (*translate_vdd)(struct device *, unsigned int);
-       unsigned int (*status)(struct device *);
-       int (*register_status_notify)(void (*callback)(int card_present, void *dev_id), void *dev_id);
-       struct msm_mmc_gpio_data *gpio_data;
-       void (*init_card)(struct mmc_card *card);
-};
-
-#endif
diff --git a/include/linux/platform_data/msm_serial_hs.h b/include/linux/platform_data/msm_serial_hs.h
deleted file mode 100644 (file)
index 98a2046..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2008 Google, Inc.
- * Author: Nick Pelly <npelly@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __ASM_ARCH_MSM_SERIAL_HS_H
-#define __ASM_ARCH_MSM_SERIAL_HS_H
-
-#include <linux/serial_core.h>
-
-/* API to request the uart clock off or on for low power management
- * Clients should call request_clock_off() when no uart data is expected,
- * and must call request_clock_on() before any further uart data can be
- * received. */
-extern void msm_hs_request_clock_off(struct uart_port *uport);
-extern void msm_hs_request_clock_on(struct uart_port *uport);
-
-/**
- * struct msm_serial_hs_platform_data
- * @rx_wakeup_irq: Rx activity irq
- * @rx_to_inject: extra character to be inserted to Rx tty on wakeup
- * @inject_rx: 1 = insert rx_to_inject. 0 = do not insert extra character
- * @exit_lpm_cb: function called before every Tx transaction
- *
- * This is an optional structure required for UART Rx GPIO IRQ based
- * wakeup from low power state. UART wakeup can be triggered by RX activity
- * (using a wakeup GPIO on the UART RX pin). This should only be used if
- * there is not a wakeup GPIO on the UART CTS, and the first RX byte is
- * known (eg., with the Bluetooth Texas Instruments HCILL protocol),
- * since the first RX byte will always be lost. RTS will be asserted even
- * while the UART is clocked off in this mode of operation.
- */
-struct msm_serial_hs_platform_data {
-       int rx_wakeup_irq;
-       unsigned char inject_rx_on_wakeup;
-       char rx_to_inject;
-       void (*exit_lpm_cb)(struct uart_port *);
-};
-
-#endif
index 3cc2e3c40914dd3b29b5f68d7c5efd675c2d229b..a938eba2f18e619c7e67696352904457ac54dead 100644 (file)
 #define ASMARM_ARCH_UART_H
 
 #define IMXUART_HAVE_RTSCTS (1<<0)
-#define IMXUART_IRDA        (1<<1)
 
 struct imxuart_platform_data {
        unsigned int flags;
-       void (*irda_enable)(int enable);
-       unsigned int irda_inv_rx:1;
-       unsigned int irda_inv_tx:1;
-       unsigned short transceiver_delay;
 };
 
 #endif
diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h
new file mode 100644 (file)
index 0000000..d7a974d
--- /dev/null
@@ -0,0 +1,28 @@
+/* Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2015 Linaro 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __QCOM_SCM_H
+#define __QCOM_SCM_H
+
+extern int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus);
+extern int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus);
+
+#define QCOM_SCM_CPU_PWR_DOWN_L2_ON    0x0
+#define QCOM_SCM_CPU_PWR_DOWN_L2_OFF   0x1
+
+extern void qcom_scm_cpu_power_down(u32 flags);
+
+#define QCOM_SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF))
+
+extern u32 qcom_scm_get_version(void);
+
+#endif
index 73069cb6c54a15ea01bacdd9af20170be6ba257a..a7a06d1dcf9cb17ee65d1befe1ef6ac62d882d16 100644 (file)
@@ -72,6 +72,7 @@ extern const char raid6_empty_zero_page[PAGE_SIZE];
 /* Routine choices */
 struct raid6_calls {
        void (*gen_syndrome)(int, size_t, void **);
+       void (*xor_syndrome)(int, int, int, size_t, void **);
        int  (*valid)(void);    /* Returns 1 if this routine set is usable */
        const char *name;       /* Name of this routine set */
        int prefer;             /* Has special performance attribute */
index e23d242d1230ff899f37478bcb3a8b92769129d2..dbcbcc59aa92e77de6c1c6065b403c0fa7d0dd15 100644 (file)
@@ -282,7 +282,8 @@ static inline bool rht_shrink_below_30(const struct rhashtable *ht,
 static inline bool rht_grow_above_100(const struct rhashtable *ht,
                                      const struct bucket_table *tbl)
 {
-       return atomic_read(&ht->nelems) > tbl->size;
+       return atomic_read(&ht->nelems) > tbl->size &&
+               (!ht->p.max_size || tbl->size < ht->p.max_size);
 }
 
 /* The bucket lock is selected based on the hash and protects mutations
index 2da5d1081ad990b57a07715ea0751ae10a80ac54..7b8e260c4a27df00b8eca70d5cd4f52864ba6d87 100644 (file)
@@ -122,5 +122,5 @@ extern int ndo_dflt_fdb_del(struct ndmsg *ndm,
 
 extern int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
                                   struct net_device *dev, u16 mode,
-                                  u32 flags, u32 mask);
+                                  u32 flags, u32 mask, int nlflags);
 #endif /* __LINUX_RTNETLINK_H */
index 8222ae40ecb0167d55f3b59027277d2a9e98d80d..26a2e6122734f8237ac44d47fb6bf4e96cca124b 100644 (file)
@@ -175,14 +175,6 @@ extern void get_iowait_load(unsigned long *nr_waiters, unsigned long *load);
 extern void calc_global_load(unsigned long ticks);
 extern void update_cpu_load_nohz(void);
 
-/* Notifier for when a task gets migrated to a new CPU */
-struct task_migration_notifier {
-       struct task_struct *task;
-       int from_cpu;
-       int to_cpu;
-};
-extern void register_task_migration_notifier(struct notifier_block *n);
-
 extern unsigned long get_parent_ip(unsigned long addr);
 
 extern void dump_cpu_task(int cpu);
index a8efa235b7c127c57a51b832bab4f335bdd571e2..78097e7a330a1984942796a4ecf9a156b93f5427 100644 (file)
@@ -60,6 +60,20 @@ enum {
 };
 
 struct uart_8250_dma;
+struct uart_8250_port;
+
+/**
+ * 8250 core driver operations
+ *
+ * @setup_irq()                Setup irq handling. The universal 8250 driver links this
+ *                     port to the irq chain. Other drivers may @request_irq().
+ * @release_irq()      Undo irq handling. The universal 8250 driver unlinks
+ *                     the port from the irq chain.
+ */
+struct uart_8250_ops {
+       int             (*setup_irq)(struct uart_8250_port *);
+       void            (*release_irq)(struct uart_8250_port *);
+};
 
 /*
  * This should be used by drivers which want to register
@@ -88,6 +102,8 @@ struct uart_8250_port {
        unsigned char           canary;         /* non-zero during system sleep
                                                 *   if no_console_suspend
                                                 */
+       unsigned char           probe;
+#define UART_PROBE_RSA (1 << 0)
 
        /*
         * Some bits in registers are cleared on a read, so they must
@@ -100,6 +116,7 @@ struct uart_8250_port {
        unsigned char           msr_saved_flags;
 
        struct uart_8250_dma    *dma;
+       const struct uart_8250_ops *ops;
 
        /* 8250 specific callbacks */
        int                     (*dl_read)(struct uart_8250_port *);
@@ -118,11 +135,8 @@ void serial8250_resume_port(int line);
 
 extern int early_serial_setup(struct uart_port *port);
 
-extern int serial8250_find_port(struct uart_port *p);
-extern int serial8250_find_port_for_earlycon(void);
 extern unsigned int serial8250_early_in(struct uart_port *port, int offset);
 extern void serial8250_early_out(struct uart_port *port, int offset, int value);
-extern int setup_early_serial8250_console(char *cmdline);
 extern void serial8250_do_set_termios(struct uart_port *port,
                struct ktermios *termios, struct ktermios *old);
 extern int serial8250_do_startup(struct uart_port *port);
index d10965f0d8a4af6526a07046ba040ae9708279a4..025dad9dcde4edaacbb51e52d138c7f28b621458 100644 (file)
@@ -235,7 +235,9 @@ struct uart_port {
        const struct uart_ops   *ops;
        unsigned int            custom_divisor;
        unsigned int            line;                   /* port index */
+       unsigned int            minor;
        resource_size_t         mapbase;                /* for ioremap */
+       resource_size_t         mapsize;
        struct device           *dev;                   /* parent device */
        unsigned char           hub6;                   /* this should be in the 8250 driver */
        unsigned char           suspended;
@@ -336,24 +338,29 @@ struct earlycon_device {
        char options[16];               /* e.g., 115200n8 */
        unsigned int baud;
 };
-int setup_earlycon(char *buf, const char *match,
-                  int (*setup)(struct earlycon_device *, const char *));
 
+struct earlycon_id {
+       char    name[16];
+       int     (*setup)(struct earlycon_device *, const char *options);
+} __aligned(32);
+
+extern int setup_earlycon(char *buf);
 extern int of_setup_earlycon(unsigned long addr,
                             int (*setup)(struct earlycon_device *, const char *));
 
-#define EARLYCON_DECLARE(name, func) \
-static int __init name ## _setup_earlycon(char *buf) \
-{ \
-       return setup_earlycon(buf, __stringify(name), func); \
-} \
-early_param("earlycon", name ## _setup_earlycon);
+#define EARLYCON_DECLARE(_name, func)                                  \
+       static const struct earlycon_id __earlycon_##_name              \
+               __used __section(__earlycon_table)                      \
+                = { .name  = __stringify(_name),                       \
+                    .setup = func  }
 
 #define OF_EARLYCON_DECLARE(name, compat, fn)                          \
        _OF_DECLARE(earlycon, name, compat, fn, void *)
 
 struct uart_port *uart_get_console(struct uart_port *ports, int nr,
                                   struct console *c);
+int uart_parse_earlycon(char *p, unsigned char *iotype, unsigned long *addr,
+                       char **options);
 void uart_parse_options(char *options, int *baud, int *parity, int *bits,
                        int *flow);
 int uart_set_options(struct uart_port *port, struct console *co, int baud,
diff --git a/include/linux/serial_mfd.h b/include/linux/serial_mfd.h
deleted file mode 100644 (file)
index 2b071e0..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-#ifndef _SERIAL_MFD_H_
-#define _SERIAL_MFD_H_
-
-/* HW register offset definition */
-#define UART_FOR       0x08
-#define UART_PS                0x0C
-#define UART_MUL       0x0D
-#define UART_DIV       0x0E
-
-#define HSU_GBL_IEN    0x0
-#define HSU_GBL_IST    0x4
-
-#define HSU_GBL_INT_BIT_PORT0  0x0
-#define HSU_GBL_INT_BIT_PORT1  0x1
-#define HSU_GBL_INT_BIT_PORT2  0x2
-#define HSU_GBL_INT_BIT_IRI    0x3
-#define HSU_GBL_INT_BIT_HDLC   0x4
-#define HSU_GBL_INT_BIT_DMA    0x5
-
-#define HSU_GBL_ISR    0x8
-#define HSU_GBL_DMASR  0x400
-#define HSU_GBL_DMAISR 0x404
-
-#define HSU_PORT_REG_OFFSET    0x80
-#define HSU_PORT0_REG_OFFSET   0x80
-#define HSU_PORT1_REG_OFFSET   0x100
-#define HSU_PORT2_REG_OFFSET   0x180
-#define HSU_PORT_REG_LENGTH    0x80
-
-#define HSU_DMA_CHANS_REG_OFFSET       0x500
-#define HSU_DMA_CHANS_REG_LENGTH       0x40
-
-#define HSU_CH_SR              0x0     /* channel status reg */
-#define HSU_CH_CR              0x4     /* control reg */
-#define HSU_CH_DCR             0x8     /* descriptor control reg */
-#define HSU_CH_BSR             0x10    /* max fifo buffer size reg */
-#define HSU_CH_MOTSR           0x14    /* minimum ocp transfer size */
-#define HSU_CH_D0SAR           0x20    /* desc 0 start addr */
-#define HSU_CH_D0TSR           0x24    /* desc 0 transfer size */
-#define HSU_CH_D1SAR           0x28
-#define HSU_CH_D1TSR           0x2C
-#define HSU_CH_D2SAR           0x30
-#define HSU_CH_D2TSR           0x34
-#define HSU_CH_D3SAR           0x38
-#define HSU_CH_D3TSR           0x3C
-
-#endif
index abdf1f229dc3d04e7197d197595fda0eac060098..dd0ba502ccb3a0ea93e9225e98b7d5b847de6ac8 100644 (file)
@@ -69,6 +69,7 @@ struct shdma_chan {
        int id;                         /* Raw id of this channel */
        int irq;                        /* Channel IRQ */
        int slave_id;                   /* Client ID for slave DMA */
+       int real_slave_id;              /* argument passed to filter function */
        int hw_req;                     /* DMA request line for slave DMA - same
                                         * as MID/RID, used with DT */
        enum shdma_pm_state pm_state;
index 0991259643d6ef44eac3940728a4c3fd1d51d7bb..66e374d62f64347025ed0a0bc7dade0744e16818 100644 (file)
@@ -773,6 +773,7 @@ bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from,
 
 struct sk_buff *__alloc_skb(unsigned int size, gfp_t priority, int flags,
                            int node);
+struct sk_buff *__build_skb(void *data, unsigned int frag_size);
 struct sk_buff *build_skb(void *data, unsigned int frag_size);
 static inline struct sk_buff *alloc_skb(unsigned int size,
                                        gfp_t priority)
@@ -3016,6 +3017,18 @@ static inline bool __skb_checksum_validate_needed(struct sk_buff *skb,
  */
 #define CHECKSUM_BREAK 76
 
+/* Unset checksum-complete
+ *
+ * Unset checksum complete can be done when packet is being modified
+ * (uncompressed for instance) and checksum-complete value is
+ * invalidated.
+ */
+static inline void skb_checksum_complete_unset(struct sk_buff *skb)
+{
+       if (skb->ip_summed == CHECKSUM_COMPLETE)
+               skb->ip_summed = CHECKSUM_NONE;
+}
+
 /* Validate (init) checksum based on checksum complete.
  *
  * Return values:
index aadc6a04e1acb91bb4baa40b545237d4822dfaee..807371357160ae97f6d6120ba83b26bbc48b8e66 100644 (file)
@@ -142,12 +142,18 @@ typedef __be32    rpc_fraghdr;
        (RPC_REPHDRSIZE + (2 + RPC_MAX_AUTH_SIZE/4))
 
 /*
- * RFC1833/RFC3530 rpcbind (v3+) well-known netid's.
+ * Well-known netids. See:
+ *
+ *   http://www.iana.org/assignments/rpc-netids/rpc-netids.xhtml
  */
 #define RPCBIND_NETID_UDP      "udp"
 #define RPCBIND_NETID_TCP      "tcp"
+#define RPCBIND_NETID_RDMA     "rdma"
+#define RPCBIND_NETID_SCTP     "sctp"
 #define RPCBIND_NETID_UDP6     "udp6"
 #define RPCBIND_NETID_TCP6     "tcp6"
+#define RPCBIND_NETID_RDMA6    "rdma6"
+#define RPCBIND_NETID_SCTP6    "sctp6"
 #define RPCBIND_NETID_LOCAL    "local"
 
 /*
index 64a0a0a97b2396492352f99fa1a1a04f225ef06a..c984c85981eae2881ebdac43ffdbfba9b55b70b4 100644 (file)
 #ifndef _LINUX_SUNRPC_XPRTRDMA_H
 #define _LINUX_SUNRPC_XPRTRDMA_H
 
-/*
- * rpcbind (v3+) RDMA netid.
- */
-#define RPCBIND_NETID_RDMA     "rdma"
-
 /*
  * Constants. Max RPC/NFS header is big enough to account for
  * additional marshaling buffers passed down by Linux client.
index 358a337af598564f16b03bfa68a696ff85d4513b..fe5623c9af715fda985da02bcecb1c9451b3789c 100644 (file)
@@ -491,6 +491,7 @@ static inline speed_t tty_get_baud_rate(struct tty_struct *tty)
 
 extern void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old);
 extern int tty_termios_hw_change(struct ktermios *a, struct ktermios *b);
+extern int tty_set_termios(struct tty_struct *tty, struct ktermios *kt);
 
 extern struct tty_ldisc *tty_ldisc_ref(struct tty_struct *);
 extern void tty_ldisc_deref(struct tty_ldisc *);
index a7f2604c5f25928938f2a55051f31f22ba469a49..7f5f78bd15ad448414fa8c06fb61fa25fb152b5f 100644 (file)
@@ -77,6 +77,8 @@
                /* Cannot handle ATA_12 or ATA_16 CDBs */       \
        US_FLAG(NO_REPORT_OPCODES,      0x04000000)             \
                /* Cannot handle MI_REPORT_SUPPORTED_OPERATION_CODES */ \
+       US_FLAG(MAX_SECTORS_240,        0x08000000)             \
+               /* Sets max_sectors to 240 */                   \
 
 #define US_FLAG(name, value)   US_FL_##name = value ,
 enum { US_DO_ALL_FLAGS };
index d5f4fb69dba3907db6719e5b260ae463065e7e5d..f9b2ce58039bd728f0d9274026e44e3ffdf1a076 100644 (file)
@@ -5,7 +5,7 @@
 ({                                                                     \
        typeof(as) __fc_i, __fc_as = (as) - 1;                          \
        typeof(x) __fc_x = (x);                                         \
-       typeof(*a) *__fc_a = (a);                                       \
+       typeof(*a) const *__fc_a = (a);                                 \
        for (__fc_i = 0; __fc_i < __fc_as; __fc_i++) {                  \
                if (__fc_x op DIV_ROUND_CLOSEST(__fc_a[__fc_i] +        \
                                                __fc_a[__fc_i + 1], 2)) \
index 28f0e65b9a1172b8a08e0ca9bdf85412eecb5dd2..8f4d4bfa6d46084d8bea6aa3181f7bd7184fc58c 100644 (file)
@@ -108,8 +108,6 @@ struct virtio_device {
        void *priv;
 };
 
-bool virtio_device_is_legacy_only(struct virtio_device_id id);
-
 static inline struct virtio_device *dev_to_virtio(struct device *_dev)
 {
        return container_of(_dev, struct virtio_device, dev);
index ca3ed78e5ec73b5968ebce4c07e0927373413b93..1e306f727edcfcecc528e81483998f947ea46459 100644 (file)
@@ -298,13 +298,6 @@ static inline __virtio64 cpu_to_virtio64(struct virtio_device *vdev, u64 val)
                }                                                       \
        } while(0)
 
-static inline u8 virtio_cread8(struct virtio_device *vdev, unsigned int offset)
-{
-       u8 ret;
-       vdev->config->get(vdev, offset, &ret, sizeof(ret));
-       return ret;
-}
-
 /* Read @count fields, @bytes each. */
 static inline void __virtio_cread_many(struct virtio_device *vdev,
                                       unsigned int offset,
@@ -326,7 +319,6 @@ static inline void __virtio_cread_many(struct virtio_device *vdev,
        } while (gen != old);
 }
 
-
 static inline void virtio_cread_bytes(struct virtio_device *vdev,
                                      unsigned int offset,
                                      void *buf, size_t len)
@@ -334,6 +326,13 @@ static inline void virtio_cread_bytes(struct virtio_device *vdev,
        __virtio_cread_many(vdev, offset, buf, len, 1);
 }
 
+static inline u8 virtio_cread8(struct virtio_device *vdev, unsigned int offset)
+{
+       u8 ret;
+       vdev->config->get(vdev, offset, &ret, sizeof(ret));
+       return ret;
+}
+
 static inline void virtio_cwrite8(struct virtio_device *vdev,
                                  unsigned int offset, u8 val)
 {
@@ -374,7 +373,6 @@ static inline u64 virtio_cread64(struct virtio_device *vdev,
                                 unsigned int offset)
 {
        u64 ret;
-       vdev->config->get(vdev, offset, &ret, sizeof(ret));
        __virtio_cread_many(vdev, offset, &ret, 1, sizeof(ret));
        return virtio64_to_cpu(vdev, (__force __virtio64)ret);
 }
index 67e06fe18c03b6814e217f05134cdb68a5df13bc..8e50888a6d595af06221ee43dfc2d0e4aa91c18e 100644 (file)
  * actually quite cheap.
  */
 
-#ifdef CONFIG_SMP
 static inline void virtio_mb(bool weak_barriers)
 {
+#ifdef CONFIG_SMP
        if (weak_barriers)
                smp_mb();
        else
+#endif
                mb();
 }
 
 static inline void virtio_rmb(bool weak_barriers)
 {
        if (weak_barriers)
-               smp_rmb();
+               dma_rmb();
        else
                rmb();
 }
@@ -41,26 +42,10 @@ static inline void virtio_rmb(bool weak_barriers)
 static inline void virtio_wmb(bool weak_barriers)
 {
        if (weak_barriers)
-               smp_wmb();
+               dma_wmb();
        else
                wmb();
 }
-#else
-static inline void virtio_mb(bool weak_barriers)
-{
-       mb();
-}
-
-static inline void virtio_rmb(bool weak_barriers)
-{
-       rmb();
-}
-
-static inline void virtio_wmb(bool weak_barriers)
-{
-       wmb();
-}
-#endif
 
 struct virtio_device;
 struct virtqueue;
index a9c723be1acfca6cd6d6bbfa37f453404aadb83d..95704cd4cfab3ccee071c4a7765d433b1de99a14 100644 (file)
 
 #include <linux/err.h>
 
-/* Reference clock values */
-enum {
-       WL12XX_REFCLOCK_19      = 0, /* 19.2 MHz */
-       WL12XX_REFCLOCK_26      = 1, /* 26 MHz */
-       WL12XX_REFCLOCK_38      = 2, /* 38.4 MHz */
-       WL12XX_REFCLOCK_52      = 3, /* 52 MHz */
-       WL12XX_REFCLOCK_38_XTAL = 4, /* 38.4 MHz, XTAL */
-       WL12XX_REFCLOCK_26_XTAL = 5, /* 26 MHz, XTAL */
-};
-
-/* TCXO clock values */
-enum {
-       WL12XX_TCXOCLOCK_19_2   = 0, /* 19.2MHz */
-       WL12XX_TCXOCLOCK_26     = 1, /* 26 MHz */
-       WL12XX_TCXOCLOCK_38_4   = 2, /* 38.4MHz */
-       WL12XX_TCXOCLOCK_52     = 3, /* 52 MHz */
-       WL12XX_TCXOCLOCK_16_368 = 4, /* 16.368 MHz */
-       WL12XX_TCXOCLOCK_32_736 = 5, /* 32.736 MHz */
-       WL12XX_TCXOCLOCK_16_8   = 6, /* 16.8 MHz */
-       WL12XX_TCXOCLOCK_33_6   = 7, /* 33.6 MHz */
-};
-
 struct wl1251_platform_data {
        int power_gpio;
        /* SDIO only: IRQ number if WLAN_IRQ line is used, 0 for SDIO IRQs */
@@ -55,41 +33,14 @@ struct wl1251_platform_data {
        bool use_eeprom;
 };
 
-struct wl12xx_platform_data {
-       int irq;
-       int board_ref_clock;
-       int board_tcxo_clock;
-       unsigned long platform_quirks;
-       bool pwr_in_suspend;
-};
-
-/* Platform does not support level trigger interrupts */
-#define WL12XX_PLATFORM_QUIRK_EDGE_IRQ BIT(0)
-
 #ifdef CONFIG_WILINK_PLATFORM_DATA
 
-int wl12xx_set_platform_data(const struct wl12xx_platform_data *data);
-
-struct wl12xx_platform_data *wl12xx_get_platform_data(void);
-
 int wl1251_set_platform_data(const struct wl1251_platform_data *data);
 
 struct wl1251_platform_data *wl1251_get_platform_data(void);
 
 #else
 
-static inline
-int wl12xx_set_platform_data(const struct wl12xx_platform_data *data)
-{
-       return -ENOSYS;
-}
-
-static inline
-struct wl12xx_platform_data *wl12xx_get_platform_data(void)
-{
-       return ERR_PTR(-ENODATA);
-}
-
 static inline
 int wl1251_set_platform_data(const struct wl1251_platform_data *data)
 {
index aa1c4477722d249a80658ab88f18b6a7713b60e0..9ecf353160c1e034475b0aa1ddeb948a9e2920b2 100644 (file)
@@ -47,16 +47,16 @@ enum adv7604_bus_order {
 };
 
 /* Input Color Space (IO register 0x02, [7:4]) */
-enum adv7604_inp_color_space {
-       ADV7604_INP_COLOR_SPACE_LIM_RGB = 0,
-       ADV7604_INP_COLOR_SPACE_FULL_RGB = 1,
-       ADV7604_INP_COLOR_SPACE_LIM_YCbCr_601 = 2,
-       ADV7604_INP_COLOR_SPACE_LIM_YCbCr_709 = 3,
-       ADV7604_INP_COLOR_SPACE_XVYCC_601 = 4,
-       ADV7604_INP_COLOR_SPACE_XVYCC_709 = 5,
-       ADV7604_INP_COLOR_SPACE_FULL_YCbCr_601 = 6,
-       ADV7604_INP_COLOR_SPACE_FULL_YCbCr_709 = 7,
-       ADV7604_INP_COLOR_SPACE_AUTO = 0xf,
+enum adv76xx_inp_color_space {
+       ADV76XX_INP_COLOR_SPACE_LIM_RGB = 0,
+       ADV76XX_INP_COLOR_SPACE_FULL_RGB = 1,
+       ADV76XX_INP_COLOR_SPACE_LIM_YCbCr_601 = 2,
+       ADV76XX_INP_COLOR_SPACE_LIM_YCbCr_709 = 3,
+       ADV76XX_INP_COLOR_SPACE_XVYCC_601 = 4,
+       ADV76XX_INP_COLOR_SPACE_XVYCC_709 = 5,
+       ADV76XX_INP_COLOR_SPACE_FULL_YCbCr_601 = 6,
+       ADV76XX_INP_COLOR_SPACE_FULL_YCbCr_709 = 7,
+       ADV76XX_INP_COLOR_SPACE_AUTO = 0xf,
 };
 
 /* Select output format (IO register 0x03, [4:2]) */
@@ -66,38 +66,39 @@ enum adv7604_op_format_mode_sel {
        ADV7604_OP_FORMAT_MODE2 = 0x08,
 };
 
-enum adv7604_drive_strength {
-       ADV7604_DR_STR_MEDIUM_LOW = 1,
-       ADV7604_DR_STR_MEDIUM_HIGH = 2,
-       ADV7604_DR_STR_HIGH = 3,
+enum adv76xx_drive_strength {
+       ADV76XX_DR_STR_MEDIUM_LOW = 1,
+       ADV76XX_DR_STR_MEDIUM_HIGH = 2,
+       ADV76XX_DR_STR_HIGH = 3,
 };
 
-enum adv7604_int1_config {
-       ADV7604_INT1_CONFIG_OPEN_DRAIN,
-       ADV7604_INT1_CONFIG_ACTIVE_LOW,
-       ADV7604_INT1_CONFIG_ACTIVE_HIGH,
-       ADV7604_INT1_CONFIG_DISABLED,
+/* INT1 Configuration (IO register 0x40, [1:0]) */
+enum adv76xx_int1_config {
+       ADV76XX_INT1_CONFIG_OPEN_DRAIN,
+       ADV76XX_INT1_CONFIG_ACTIVE_LOW,
+       ADV76XX_INT1_CONFIG_ACTIVE_HIGH,
+       ADV76XX_INT1_CONFIG_DISABLED,
 };
 
-enum adv7604_page {
-       ADV7604_PAGE_IO,
+enum adv76xx_page {
+       ADV76XX_PAGE_IO,
        ADV7604_PAGE_AVLINK,
-       ADV7604_PAGE_CEC,
-       ADV7604_PAGE_INFOFRAME,
+       ADV76XX_PAGE_CEC,
+       ADV76XX_PAGE_INFOFRAME,
        ADV7604_PAGE_ESDP,
        ADV7604_PAGE_DPP,
-       ADV7604_PAGE_AFE,
-       ADV7604_PAGE_REP,
-       ADV7604_PAGE_EDID,
-       ADV7604_PAGE_HDMI,
-       ADV7604_PAGE_TEST,
-       ADV7604_PAGE_CP,
+       ADV76XX_PAGE_AFE,
+       ADV76XX_PAGE_REP,
+       ADV76XX_PAGE_EDID,
+       ADV76XX_PAGE_HDMI,
+       ADV76XX_PAGE_TEST,
+       ADV76XX_PAGE_CP,
        ADV7604_PAGE_VDP,
-       ADV7604_PAGE_MAX,
+       ADV76XX_PAGE_MAX,
 };
 
 /* Platform dependent definition */
-struct adv7604_platform_data {
+struct adv76xx_platform_data {
        /* DIS_PWRDNB: 1 if the PWRDNB pin is unused and unconnected */
        unsigned disable_pwrdnb:1;
 
@@ -116,7 +117,7 @@ struct adv7604_platform_data {
        enum adv7604_op_format_mode_sel op_format_mode_sel;
 
        /* Configuration of the INT1 pin */
-       enum adv7604_int1_config int1_config;
+       enum adv76xx_int1_config int1_config;
 
        /* IO register 0x02 */
        unsigned alt_gamma:1;
@@ -134,9 +135,9 @@ struct adv7604_platform_data {
        unsigned inv_llc_pol:1;
 
        /* IO register 0x14 */
-       enum adv7604_drive_strength dr_str_data;
-       enum adv7604_drive_strength dr_str_clk;
-       enum adv7604_drive_strength dr_str_sync;
+       enum adv76xx_drive_strength dr_str_data;
+       enum adv76xx_drive_strength dr_str_clk;
+       enum adv76xx_drive_strength dr_str_sync;
 
        /* IO register 0x30 */
        unsigned output_bus_lsb_to_msb:1;
@@ -145,11 +146,11 @@ struct adv7604_platform_data {
        unsigned hdmi_free_run_mode;
 
        /* i2c addresses: 0 == use default */
-       u8 i2c_addresses[ADV7604_PAGE_MAX];
+       u8 i2c_addresses[ADV76XX_PAGE_MAX];
 };
 
-enum adv7604_pad {
-       ADV7604_PAD_HDMI_PORT_A = 0,
+enum adv76xx_pad {
+       ADV76XX_PAD_HDMI_PORT_A = 0,
        ADV7604_PAD_HDMI_PORT_B = 1,
        ADV7604_PAD_HDMI_PORT_C = 2,
        ADV7604_PAD_HDMI_PORT_D = 3,
@@ -158,7 +159,7 @@ enum adv7604_pad {
        /* The source pad is either 1 (ADV7611) or 6 (ADV7604) */
        ADV7604_PAD_SOURCE = 6,
        ADV7611_PAD_SOURCE = 1,
-       ADV7604_PAD_MAX = 7,
+       ADV76XX_PAD_MAX = 7,
 };
 
 #define V4L2_CID_ADV_RX_ANALOG_SAMPLING_PHASE  (V4L2_CID_DV_CLASS_BASE + 0x1000)
@@ -166,7 +167,7 @@ enum adv7604_pad {
 #define V4L2_CID_ADV_RX_FREE_RUN_COLOR         (V4L2_CID_DV_CLASS_BASE + 0x1002)
 
 /* notify events */
-#define ADV7604_HOTPLUG                1
-#define ADV7604_FMT_CHANGE     2
+#define ADV76XX_HOTPLUG                1
+#define ADV76XX_FMT_CHANGE     2
 
 #endif
index 288772e6900a631e12169108a4ca4bc2c2a6bf03..28bcd71cdd2608f9ad7f19ab124f61679f88b409 100644 (file)
@@ -102,7 +102,7 @@ struct vpfe_config {
 struct vpfe_device {
        /* V4l2 specific parameters */
        /* Identifies video device for this channel */
-       struct video_device *video_dev;
+       struct video_device video_dev;
        /* sub devices */
        struct v4l2_subdev **sd;
        /* vpfe cfg */
index e00459185d2079161424b069c9e9c6bece2210c5..0c003d8174937ba47afa097d6a54b4fb8adce31d 100644 (file)
@@ -44,6 +44,15 @@ struct media_pad {
        unsigned long flags;            /* Pad flags (MEDIA_PAD_FL_*) */
 };
 
+/**
+ * struct media_entity_operations - Media entity operations
+ * @link_setup:                Notify the entity of link changes. The operation can
+ *                     return an error, in which case link setup will be
+ *                     cancelled. Optional.
+ * @link_validate:     Return whether a link is valid from the entity point of
+ *                     view. The media_entity_pipeline_start() function
+ *                     validates all links by calling this operation. Optional.
+ */
 struct media_entity_operations {
        int (*link_setup)(struct media_entity *entity,
                          const struct media_pad *local,
@@ -87,17 +96,7 @@ struct media_entity {
                struct {
                        u32 major;
                        u32 minor;
-               } v4l;
-               struct {
-                       u32 major;
-                       u32 minor;
-               } fb;
-               struct {
-                       u32 card;
-                       u32 device;
-                       u32 subdevice;
-               } alsa;
-               int dvb;
+               } dev;
 
                /* Sub-device specifications */
                /* Nothing needed yet */
index b1e63f2b72bd8ba8ba849f4352d3817f1c84ed5b..1ba361205af1821dcd5663d73f9eb4e9d6ddfc8d 100644 (file)
@@ -5,12 +5,10 @@ struct v4l2_subdev;
 
 /*
  * struct mt9p031_platform_data - MT9P031 platform data
- * @reset: Chip reset GPIO (set to -1 if not used)
  * @ext_freq: Input clock frequency
  * @target_freq: Pixel clock frequency
  */
 struct mt9p031_platform_data {
-       int reset;
        int ext_freq;
        int target_freq;
 };
index 398279dd1922b4b41959aa7966b0991d19fbb24b..048f8f9117efaaa7ee3564290700fe7bfcbf8628 100644 (file)
@@ -45,7 +45,7 @@ enum {
 };
 
 /**
- * struct isp_parallel_platform_data - Parallel interface platform data
+ * struct isp_parallel_cfg - Parallel interface configuration
  * @data_lane_shift: Data lane shifter
  *             ISP_LANE_SHIFT_0 - CAMEXT[13:0] -> CAM[13:0]
  *             ISP_LANE_SHIFT_2 - CAMEXT[13:2] -> CAM[11:0]
@@ -62,7 +62,7 @@ enum {
  * @data_pol: Data polarity
  *             0 - Normal, 1 - One's complement
  */
-struct isp_parallel_platform_data {
+struct isp_parallel_cfg {
        unsigned int data_lane_shift:2;
        unsigned int clk_pol:1;
        unsigned int hs_pol:1;
@@ -105,7 +105,7 @@ struct isp_csiphy_lanes_cfg {
 };
 
 /**
- * struct isp_ccp2_platform_data - CCP2 interface platform data
+ * struct isp_ccp2_cfg - CCP2 interface configuration
  * @strobe_clk_pol: Strobe/clock polarity
  *             0 - Non Inverted, 1 - Inverted
  * @crc: Enable the cyclic redundancy check
@@ -117,7 +117,7 @@ struct isp_csiphy_lanes_cfg {
  *             ISP_CCP2_PHY_DATA_STROBE - Data/strobe physical layer
  * @vpclk_div: Video port output clock control
  */
-struct isp_ccp2_platform_data {
+struct isp_ccp2_cfg {
        unsigned int strobe_clk_pol:1;
        unsigned int crc:1;
        unsigned int ccp2_mode:1;
@@ -127,39 +127,31 @@ struct isp_ccp2_platform_data {
 };
 
 /**
- * struct isp_csi2_platform_data - CSI2 interface platform data
+ * struct isp_csi2_cfg - CSI2 interface configuration
  * @crc: Enable the cyclic redundancy check
- * @vpclk_div: Video port output clock control
  */
-struct isp_csi2_platform_data {
+struct isp_csi2_cfg {
        unsigned crc:1;
-       unsigned vpclk_div:2;
        struct isp_csiphy_lanes_cfg lanecfg;
 };
 
-struct isp_subdev_i2c_board_info {
-       struct i2c_board_info *board_info;
-       int i2c_adapter_id;
-};
-
-struct isp_v4l2_subdevs_group {
-       struct isp_subdev_i2c_board_info *subdevs;
+struct isp_bus_cfg {
        enum isp_interface_type interface;
        union {
-               struct isp_parallel_platform_data parallel;
-               struct isp_ccp2_platform_data ccp2;
-               struct isp_csi2_platform_data csi2;
+               struct isp_parallel_cfg parallel;
+               struct isp_ccp2_cfg ccp2;
+               struct isp_csi2_cfg csi2;
        } bus; /* gcc < 4.6.0 chokes on anonymous union initializers */
 };
 
-struct isp_platform_xclk {
-       const char *dev_id;
-       const char *con_id;
+struct isp_platform_subdev {
+       struct i2c_board_info *board_info;
+       int i2c_adapter_id;
+       struct isp_bus_cfg *bus;
 };
 
 struct isp_platform_data {
-       struct isp_platform_xclk xclks[2];
-       struct isp_v4l2_subdevs_group *subdevs;
+       struct isp_platform_subdev *subdevs;
        void (*set_constraints)(struct isp_device *isp, bool enable);
 };
 
diff --git a/include/media/ov2659.h b/include/media/ov2659.h
new file mode 100644 (file)
index 0000000..4216adc
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Omnivision OV2659 CMOS Image Sensor driver
+ *
+ * Copyright (C) 2015 Texas Instruments, Inc.
+ *
+ * Benoit Parrot <bparrot@ti.com>
+ * Lad, Prabhakar <prabhakar.csengg@gmail.com>
+ *
+ * This program is free software; you may 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.
+ *
+ * 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 OV2659_H
+#define OV2659_H
+
+/**
+ * struct ov2659_platform_data - ov2659 driver platform data
+ * @link_frequency: target pixel clock frequency
+ */
+struct ov2659_platform_data {
+       s64 link_frequency;
+};
+
+#endif /* OV2659_H */
index 944ecdf3530fc6ef28329465375931e9866f02fe..92766f77a5dee7decc5885228d7d02cf43d99d88 100644 (file)
@@ -178,8 +178,8 @@ struct saa7146_use_ops  {
 };
 
 /* from saa7146_fops.c */
-int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev, char *name, int type);
-int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev);
+int saa7146_register_device(struct video_device *vid, struct saa7146_dev *dev, char *name, int type);
+int saa7146_unregister_device(struct video_device *vid, struct saa7146_dev *dev);
 void saa7146_buffer_finish(struct saa7146_dev *dev, struct saa7146_dmaqueue *q, int state);
 void saa7146_buffer_next(struct saa7146_dev *dev, struct saa7146_dmaqueue *q,int vbi);
 int saa7146_buffer_queue(struct saa7146_dev *dev, struct saa7146_dmaqueue *q, struct saa7146_buf *buf);
index 0b36cc138304706e98e5993fc0014b4af9afda43..3ef6e3d5ed6c6f6eb90fa177f6eccc20ee7a9c83 100644 (file)
 struct module;
 struct device;
 
+struct clk;
 struct v4l2_clk {
        struct list_head list;
        const struct v4l2_clk_ops *ops;
        const char *dev_id;
-       const char *id;
        int enable;
        struct mutex lock; /* Protect the enable count */
        atomic_t use_count;
+       struct clk *clk;
        void *priv;
 };
 
@@ -43,7 +44,7 @@ struct v4l2_clk_ops {
 
 struct v4l2_clk *v4l2_clk_register(const struct v4l2_clk_ops *ops,
                                   const char *dev_name,
-                                  const char *name, void *priv);
+                                  void *priv);
 void v4l2_clk_unregister(struct v4l2_clk *clk);
 struct v4l2_clk *v4l2_clk_get(struct device *dev, const char *id);
 void v4l2_clk_put(struct v4l2_clk *clk);
@@ -55,14 +56,13 @@ int v4l2_clk_set_rate(struct v4l2_clk *clk, unsigned long rate);
 struct module;
 
 struct v4l2_clk *__v4l2_clk_register_fixed(const char *dev_id,
-               const char *id, unsigned long rate, struct module *owner);
+                       unsigned long rate, struct module *owner);
 void v4l2_clk_unregister_fixed(struct v4l2_clk *clk);
 
 static inline struct v4l2_clk *v4l2_clk_register_fixed(const char *dev_id,
-                                                       const char *id,
                                                        unsigned long rate)
 {
-       return __v4l2_clk_register_fixed(dev_id, id, rate, THIS_MODULE);
+       return __v4l2_clk_register_fixed(dev_id, rate, THIS_MODULE);
 }
 
 #define v4l2_clk_name_i2c(name, size, adap, client) snprintf(name, size, \
index 3e4fddfc840c2934098a7fa3f258b2a85e010ab2..acbcd2f5fe7f8167b053ac5d6c7fa747f1cbef9b 100644 (file)
@@ -65,7 +65,6 @@ struct v4l2_file_operations {
        ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
        ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
        unsigned int (*poll) (struct file *, struct poll_table_struct *);
-       long (*ioctl) (struct file *, unsigned int, unsigned long);
        long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
 #ifdef CONFIG_COMPAT
        long (*compat_ioctl32) (struct file *, unsigned int, unsigned long);
index ffb69da3ce9ef85fc0271b89b9fc7a374c608580..9c581578783f4d1655d28135c6d9b242b1e96edd 100644 (file)
@@ -58,8 +58,6 @@ struct v4l2_device {
        struct v4l2_ctrl_handler *ctrl_handler;
        /* Device's priority state */
        struct v4l2_prio_state prio;
-       /* BKL replacement mutex. Temporary solution only. */
-       struct mutex ioctl_lock;
        /* Keep track of the references to this struct. */
        struct kref ref;
        /* Release function that is called when the ref count goes to 0. */
index 8537983b9b226b6c3772f65b0a47b52d37d2c0fb..8fbbd76d78e84fdea1ecc5e41a195b15bceba8fb 100644 (file)
@@ -23,12 +23,6 @@ struct v4l2_ioctl_ops {
        /* VIDIOC_QUERYCAP handler */
        int (*vidioc_querycap)(struct file *file, void *fh, struct v4l2_capability *cap);
 
-       /* Priority handling */
-       int (*vidioc_g_priority)   (struct file *file, void *fh,
-                                   enum v4l2_priority *p);
-       int (*vidioc_s_priority)   (struct file *file, void *fh,
-                                   enum v4l2_priority p);
-
        /* VIDIOC_ENUM_FMT handlers */
        int (*vidioc_enum_fmt_vid_cap)     (struct file *file, void *fh,
                                            struct v4l2_fmtdesc *f);
index 70fa7b7b04879fc100bfce80cc79308260900e96..f831c9c225b60baeb78c3f0964662ea46b8e2857 100644 (file)
@@ -29,12 +29,15 @@ struct device_node;
  * @data_lanes: an array of physical data lane indexes
  * @clock_lane: physical lane index of the clock lane
  * @num_data_lanes: number of data lanes
+ * @lane_polarities: polarity of the lanes. The order is the same of
+ *                the physical lanes.
  */
 struct v4l2_of_bus_mipi_csi2 {
        unsigned int flags;
        unsigned char data_lanes[4];
        unsigned char clock_lane;
        unsigned short num_data_lanes;
+       bool lane_polarities[5];
 };
 
 /**
@@ -66,9 +69,26 @@ struct v4l2_of_endpoint {
        struct list_head head;
 };
 
+/**
+ * struct v4l2_of_link - a link between two endpoints
+ * @local_node: pointer to device_node of this endpoint
+ * @local_port: identifier of the port this endpoint belongs to
+ * @remote_node: pointer to device_node of the remote endpoint
+ * @remote_port: identifier of the port the remote endpoint belongs to
+ */
+struct v4l2_of_link {
+       struct device_node *local_node;
+       unsigned int local_port;
+       struct device_node *remote_node;
+       unsigned int remote_port;
+};
+
 #ifdef CONFIG_OF
 int v4l2_of_parse_endpoint(const struct device_node *node,
                           struct v4l2_of_endpoint *endpoint);
+int v4l2_of_parse_link(const struct device_node *node,
+                      struct v4l2_of_link *link);
+void v4l2_of_put_link(struct v4l2_of_link *link);
 #else /* CONFIG_OF */
 
 static inline int v4l2_of_parse_endpoint(const struct device_node *node,
@@ -77,6 +97,16 @@ static inline int v4l2_of_parse_endpoint(const struct device_node *node,
        return -ENOSYS;
 }
 
+static inline int v4l2_of_parse_link(const struct device_node *node,
+                                    struct v4l2_of_link *link)
+{
+       return -ENOSYS;
+}
+
+static inline void v4l2_of_put_link(struct v4l2_of_link *link)
+{
+}
+
 #endif /* CONFIG_OF */
 
 #endif /* _V4L2_OF_H */
index 5beeb8744fd1c7ed86f3aba628535d09c1a8f1d9..2f0a345a7fed1b897117603dcc598d5de5b94194 100644 (file)
@@ -332,8 +332,6 @@ struct v4l2_subdev_video_ops {
                                struct v4l2_subdev_frame_interval *interval);
        int (*s_frame_interval)(struct v4l2_subdev *sd,
                                struct v4l2_subdev_frame_interval *interval);
-       int (*enum_framesizes)(struct v4l2_subdev *sd, struct v4l2_frmsizeenum *fsize);
-       int (*enum_frameintervals)(struct v4l2_subdev *sd, struct v4l2_frmivalenum *fival);
        int (*s_dv_timings)(struct v4l2_subdev *sd,
                        struct v4l2_dv_timings *timings);
        int (*g_dv_timings)(struct v4l2_subdev *sd,
@@ -482,6 +480,18 @@ struct v4l2_subdev_ir_ops {
                                struct v4l2_subdev_ir_parameters *params);
 };
 
+/*
+ * Used for storing subdev pad information. This structure only needs
+ * to be passed to the pad op if the 'which' field of the main argument
+ * is set to V4L2_SUBDEV_FORMAT_TRY. For V4L2_SUBDEV_FORMAT_ACTIVE it is
+ * safe to pass NULL.
+ */
+struct v4l2_subdev_pad_config {
+       struct v4l2_mbus_framefmt try_fmt;
+       struct v4l2_rect try_crop;
+       struct v4l2_rect try_compose;
+};
+
 /**
  * struct v4l2_subdev_pad_ops - v4l2-subdev pad level operations
  * @get_frame_desc: get the current low level media bus frame parameters.
@@ -489,21 +499,26 @@ struct v4l2_subdev_ir_ops {
  *                  may be adjusted by the subdev driver to device capabilities.
  */
 struct v4l2_subdev_pad_ops {
-       int (*enum_mbus_code)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+       int (*enum_mbus_code)(struct v4l2_subdev *sd,
+                             struct v4l2_subdev_pad_config *cfg,
                              struct v4l2_subdev_mbus_code_enum *code);
        int (*enum_frame_size)(struct v4l2_subdev *sd,
-                              struct v4l2_subdev_fh *fh,
+                              struct v4l2_subdev_pad_config *cfg,
                               struct v4l2_subdev_frame_size_enum *fse);
        int (*enum_frame_interval)(struct v4l2_subdev *sd,
-                                  struct v4l2_subdev_fh *fh,
+                                  struct v4l2_subdev_pad_config *cfg,
                                   struct v4l2_subdev_frame_interval_enum *fie);
-       int (*get_fmt)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+       int (*get_fmt)(struct v4l2_subdev *sd,
+                      struct v4l2_subdev_pad_config *cfg,
                       struct v4l2_subdev_format *format);
-       int (*set_fmt)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+       int (*set_fmt)(struct v4l2_subdev *sd,
+                      struct v4l2_subdev_pad_config *cfg,
                       struct v4l2_subdev_format *format);
-       int (*get_selection)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+       int (*get_selection)(struct v4l2_subdev *sd,
+                            struct v4l2_subdev_pad_config *cfg,
                             struct v4l2_subdev_selection *sel);
-       int (*set_selection)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+       int (*set_selection)(struct v4l2_subdev *sd,
+                            struct v4l2_subdev_pad_config *cfg,
                             struct v4l2_subdev_selection *sel);
        int (*get_edid)(struct v4l2_subdev *sd, struct v4l2_edid *edid);
        int (*set_edid)(struct v4l2_subdev *sd, struct v4l2_edid *edid);
@@ -625,11 +640,7 @@ struct v4l2_subdev {
 struct v4l2_subdev_fh {
        struct v4l2_fh vfh;
 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
-       struct {
-               struct v4l2_mbus_framefmt try_fmt;
-               struct v4l2_rect try_crop;
-               struct v4l2_rect try_compose;
-       } *pad;
+       struct v4l2_subdev_pad_config *pad;
 #endif
 };
 
@@ -639,17 +650,17 @@ struct v4l2_subdev_fh {
 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
 #define __V4L2_SUBDEV_MK_GET_TRY(rtype, fun_name, field_name)          \
        static inline struct rtype *                                    \
-       v4l2_subdev_get_try_##fun_name(struct v4l2_subdev_fh *fh,       \
-                                      unsigned int pad)                \
+       fun_name(struct v4l2_subdev *sd,                                \
+                struct v4l2_subdev_pad_config *cfg,                    \
+                unsigned int pad)                                      \
        {                                                               \
-               BUG_ON(pad >= vdev_to_v4l2_subdev(                      \
-                                       fh->vfh.vdev)->entity.num_pads); \
-               return &fh->pad[pad].field_name;                        \
+               BUG_ON(pad >= sd->entity.num_pads);                     \
+               return &cfg[pad].field_name;                            \
        }
 
-__V4L2_SUBDEV_MK_GET_TRY(v4l2_mbus_framefmt, format, try_fmt)
-__V4L2_SUBDEV_MK_GET_TRY(v4l2_rect, crop, try_crop)
-__V4L2_SUBDEV_MK_GET_TRY(v4l2_rect, compose, try_compose)
+__V4L2_SUBDEV_MK_GET_TRY(v4l2_mbus_framefmt, v4l2_subdev_get_try_format, try_fmt)
+__V4L2_SUBDEV_MK_GET_TRY(v4l2_rect, v4l2_subdev_get_try_crop, try_crop)
+__V4L2_SUBDEV_MK_GET_TRY(v4l2_rect, v4l2_subdev_get_try_compose, try_compose)
 #endif
 
 extern const struct v4l2_file_operations v4l2_subdev_fops;
index bd2cec2d6c3dcd20c11c18b8f013082116a89b5f..a5790fd5d12500aa3abac79a8271b1e0fb9ea2ba 100644 (file)
@@ -133,17 +133,6 @@ enum vb2_io_modes {
        VB2_DMABUF      = (1 << 4),
 };
 
-/**
- * enum vb2_fileio_flags - flags for selecting a mode of the file io emulator,
- * by default the 'streaming' style is used by the file io emulator
- * @VB2_FILEIO_READ_ONCE:      report EOF after reading the first buffer
- * @VB2_FILEIO_WRITE_IMMEDIATELY:      queue buffer after each write() call
- */
-enum vb2_fileio_flags {
-       VB2_FILEIO_READ_ONCE            = (1 << 0),
-       VB2_FILEIO_WRITE_IMMEDIATELY    = (1 << 1),
-};
-
 /**
  * enum vb2_buffer_state - current video buffer state
  * @VB2_BUF_STATE_DEQUEUED:    buffer under userspace control
@@ -346,7 +335,9 @@ struct v4l2_fh;
  *
  * @type:      queue type (see V4L2_BUF_TYPE_* in linux/videodev2.h
  * @io_modes:  supported io methods (see vb2_io_modes enum)
- * @io_flags:  additional io flags (see vb2_fileio_flags enum)
+ * @fileio_read_once:          report EOF after reading the first buffer
+ * @fileio_write_immediately:  queue buffer after each write() call
+ * @allow_zero_bytesused:      allow bytesused == 0 to be passed to the driver
  * @lock:      pointer to a mutex that protects the vb2_queue struct. The
  *             driver can set this to a mutex to let the v4l2 core serialize
  *             the queuing ioctls. If the driver wants to handle locking
@@ -396,7 +387,10 @@ struct v4l2_fh;
 struct vb2_queue {
        enum v4l2_buf_type              type;
        unsigned int                    io_modes;
-       unsigned int                    io_flags;
+       unsigned                        fileio_read_once:1;
+       unsigned                        fileio_write_immediately:1;
+       unsigned                        allow_zero_bytesused:1;
+
        struct mutex                    *lock;
        struct v4l2_fh                  *owner;
 
index fda6feeb6c1f3fc3ae7c4929935901e31982166b..78ed135e9dea6a9971d15e3b786a64de170b310c 100644 (file)
 #include <net/bond_alb.h>
 #include <net/bond_options.h>
 
-#define DRV_VERSION    "3.7.1"
-#define DRV_RELDATE    "April 27, 2011"
-#define DRV_NAME       "bonding"
-#define DRV_DESCRIPTION        "Ethernet Channel Bonding Driver"
-
-#define bond_version DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n"
-
 #define BOND_MAX_ARP_TARGETS   16
 
 #define BOND_DEFAULT_MIIMON    100
index 7b5887cd11723441418daa5ec306d8c8b4d7c1f1..48a8158235874b1625c65651b0bd92eedd999fe5 100644 (file)
@@ -279,12 +279,6 @@ static inline void inet_csk_reqsk_queue_add(struct sock *sk,
 void inet_csk_reqsk_queue_hash_add(struct sock *sk, struct request_sock *req,
                                   unsigned long timeout);
 
-static inline void inet_csk_reqsk_queue_removed(struct sock *sk,
-                                               struct request_sock *req)
-{
-       reqsk_queue_removed(&inet_csk(sk)->icsk_accept_queue, req);
-}
-
 static inline void inet_csk_reqsk_queue_added(struct sock *sk,
                                              const unsigned long timeout)
 {
@@ -306,19 +300,7 @@ static inline int inet_csk_reqsk_queue_is_full(const struct sock *sk)
        return reqsk_queue_is_full(&inet_csk(sk)->icsk_accept_queue);
 }
 
-static inline void inet_csk_reqsk_queue_unlink(struct sock *sk,
-                                              struct request_sock *req)
-{
-       reqsk_queue_unlink(&inet_csk(sk)->icsk_accept_queue, req);
-}
-
-static inline void inet_csk_reqsk_queue_drop(struct sock *sk,
-                                            struct request_sock *req)
-{
-       inet_csk_reqsk_queue_unlink(sk, req);
-       inet_csk_reqsk_queue_removed(sk, req);
-       reqsk_put(req);
-}
+void inet_csk_reqsk_queue_drop(struct sock *sk, struct request_sock *req);
 
 void inet_csk_destroy_sock(struct sock *sk);
 void inet_csk_prepare_forced_close(struct sock *sk);
index fe41f3ceb008d767d594de6a042393ba463b509b..9f4265ce88927b0fe1d7418dbeff5f306855ae15 100644 (file)
@@ -212,24 +212,6 @@ static inline int reqsk_queue_empty(struct request_sock_queue *queue)
        return queue->rskq_accept_head == NULL;
 }
 
-static inline void reqsk_queue_unlink(struct request_sock_queue *queue,
-                                     struct request_sock *req)
-{
-       struct listen_sock *lopt = queue->listen_opt;
-       struct request_sock **prev;
-
-       spin_lock(&queue->syn_wait_lock);
-
-       prev = &lopt->syn_table[req->rsk_hash];
-       while (*prev != req)
-               prev = &(*prev)->dl_next;
-       *prev = req->dl_next;
-
-       spin_unlock(&queue->syn_wait_lock);
-       if (del_timer(&req->rsk_timer))
-               reqsk_put(req);
-}
-
 static inline void reqsk_queue_add(struct request_sock_queue *queue,
                                   struct request_sock *req,
                                   struct sock *parent,
index ce55906b54a0eccc316216ce88f5b012a87c537e..ac54c27a2bfd39a2f5ec950afe57963c57b04a42 100644 (file)
@@ -160,7 +160,7 @@ static inline int rdma_ip2gid(struct sockaddr *addr, union ib_gid *gid)
 }
 
 /* Important - sockaddr should be a union of sockaddr_in and sockaddr_in6 */
-static inline int rdma_gid2ip(struct sockaddr *out, union ib_gid *gid)
+static inline void rdma_gid2ip(struct sockaddr *out, union ib_gid *gid)
 {
        if (ipv6_addr_v4mapped((struct in6_addr *)gid)) {
                struct sockaddr_in *out_in = (struct sockaddr_in *)out;
@@ -173,7 +173,6 @@ static inline int rdma_gid2ip(struct sockaddr *out, union ib_gid *gid)
                out_in->sin6_family = AF_INET6;
                memcpy(&out_in->sin6_addr.s6_addr, gid->raw, 16);
        }
-       return 0;
 }
 
 static inline void iboe_addr_get_sgid(struct rdma_dev_addr *dev_addr,
index 0e3ff30647d518483853cb9c52104991df966221..39ed2d2fbd51452216586b031a3e25d236099169 100644 (file)
@@ -105,7 +105,8 @@ enum ib_cm_data_size {
        IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE = 216,
        IB_CM_SIDR_REP_PRIVATE_DATA_SIZE = 136,
        IB_CM_SIDR_REP_INFO_LENGTH       = 72,
-       IB_CM_COMPARE_SIZE               = 64
+       /* compare done u32 at a time */
+       IB_CM_COMPARE_SIZE               = (64 / sizeof(u32))
 };
 
 struct ib_cm_id;
@@ -337,8 +338,8 @@ void ib_destroy_cm_id(struct ib_cm_id *cm_id);
 #define IB_SDP_SERVICE_ID_MASK cpu_to_be64(0xFFFFFFFFFFFF0000ULL)
 
 struct ib_cm_compare_data {
-       u8  data[IB_CM_COMPARE_SIZE];
-       u8  mask[IB_CM_COMPARE_SIZE];
+       u32  data[IB_CM_COMPARE_SIZE];
+       u32  mask[IB_CM_COMPARE_SIZE];
 };
 
 /**
index 928b2775e99244e7df3dae25f218386b84d1ddf3..fda31673a5628831434991f0a087f8417a9589a2 100644 (file)
@@ -147,6 +147,16 @@ int iwpm_add_mapping_cb(struct sk_buff *, struct netlink_callback *);
  */
 int iwpm_add_and_query_mapping_cb(struct sk_buff *, struct netlink_callback *);
 
+/**
+ * iwpm_remote_info_cb - Process remote connecting peer address info, which
+ *                       the port mapper has received from the connecting peer
+ *
+ * @cb: Contains the received message (payload and netlink header)
+ *
+ * Stores the IPv4/IPv6 address info in a hash table
+ */
+int iwpm_remote_info_cb(struct sk_buff *, struct netlink_callback *);
+
 /**
  * iwpm_mapping_error_cb - Process port mapper notification for error
  *
@@ -174,6 +184,21 @@ int iwpm_mapping_info_cb(struct sk_buff *, struct netlink_callback *);
  */
 int iwpm_ack_mapping_info_cb(struct sk_buff *, struct netlink_callback *);
 
+/**
+ * iwpm_get_remote_info - Get the remote connecting peer address info
+ *
+ * @mapped_loc_addr: Mapped local address of the listening peer
+ * @mapped_rem_addr: Mapped remote address of the connecting peer
+ * @remote_addr: To store the remote address of the connecting peer
+ * @nl_client: The index of the netlink client
+ *
+ * The remote address info is retrieved and provided to the client in
+ * the remote_addr. After that it is removed from the hash table
+ */
+int iwpm_get_remote_info(struct sockaddr_storage *mapped_loc_addr,
+                       struct sockaddr_storage *mapped_rem_addr,
+                       struct sockaddr_storage *remote_addr, u8 nl_client);
+
 /**
  * iwpm_create_mapinfo - Store local and mapped IPv4/IPv6 address
  *                       info in a hash table
index 183eaab7c3803dcd081b5a9c30a3b9963767ffe5..96e3f56519e7d9831e4b4c4ce19f78afd436242f 100644 (file)
@@ -36,5 +36,6 @@
                                             for sequential scan */
 #define BLIST_TRY_VPD_PAGES    0x10000000 /* Attempt to read VPD pages */
 #define BLIST_NO_RSOC          0x20000000 /* don't try to issue RSOC */
+#define BLIST_MAX_1024         0x40000000 /* maximum 1024 sector cdb length */
 
 #endif
index 26f406e0f673437498406acbdf84841a87862763..3a8fca9409a7a0c1fad472155854b26f0a122487 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (ST) 2012 Rajeev Kumar (rajeev-dlh.kumar@st.com)
+ * Copyright (ST) 2012 Rajeev Kumar (rajeevkumar.linux@gmail.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
index 0de95ccb92cf58ed0536cca855d1255b0276b4fb..5bd134651f5eef50d7c0faee3c66457b66b1307f 100644 (file)
@@ -41,7 +41,8 @@
 
 #define EMUPAGESIZE     4096
 #define MAXREQVOICES    8
-#define MAXPAGES        8192
+#define MAXPAGES0       4096   /* 32 bit mode */
+#define MAXPAGES1       8192   /* 31 bit mode */
 #define RESERVED        0
 #define NUM_MIDI        16
 #define NUM_G           64              /* use all channels */
@@ -50,8 +51,7 @@
 
 /* FIXME? - according to the OSS driver the EMU10K1 needs a 29 bit DMA mask */
 #define EMU10K1_DMA_MASK       0x7fffffffUL    /* 31bit */
-#define AUDIGY_DMA_MASK                0x7fffffffUL    /* 31bit FIXME - 32 should work? */
-                                               /* See ALSA bug #1276 - rlrevell */
+#define AUDIGY_DMA_MASK                0xffffffffUL    /* 32bit mode */
 
 #define TMEMSIZE        256*1024
 #define TMEMSIZEREG     4
 
 #define MAPB                   0x0d            /* Cache map B                                          */
 
-#define MAP_PTE_MASK           0xffffe000      /* The 19 MSBs of the PTE indexed by the PTI            */
-#define MAP_PTI_MASK           0x00001fff      /* The 13 bit index to one of the 8192 PTE dwords       */
+#define MAP_PTE_MASK0          0xfffff000      /* The 20 MSBs of the PTE indexed by the PTI            */
+#define MAP_PTI_MASK0          0x00000fff      /* The 12 bit index to one of the 4096 PTE dwords       */
+
+#define MAP_PTE_MASK1          0xffffe000      /* The 19 MSBs of the PTE indexed by the PTI            */
+#define MAP_PTI_MASK1          0x00001fff      /* The 13 bit index to one of the 8192 PTE dwords       */
 
 /* 0x0e, 0x0f: Not used */
 
@@ -1704,6 +1707,7 @@ struct snd_emu10k1 {
        unsigned short model;                   /* subsystem id */
        unsigned int card_type;                 /* EMU10K1_CARD_* */
        unsigned int ecard_ctrl;                /* ecard control bits */
+       unsigned int address_mode;              /* address mode */
        unsigned long dma_mask;                 /* PCI DMA mask */
        unsigned int delay_pcm_irq;             /* in samples */
        int max_cache_pages;                    /* max memory size / PAGE_SIZE */
index 0bc83647d3fa39e05fcd153467eec20aa4c74556..1065095c6973555f2ba8f835b5321df647b5bc21 100644 (file)
@@ -287,7 +287,7 @@ struct device;
        .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\
        .tlv.p = (tlv_array), \
        .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
-       .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
+       .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 1) }
 #define SOC_DAPM_SINGLE_TLV_VIRT(xname, max, tlv_array) \
        SOC_DAPM_SINGLE(xname, SND_SOC_NOPM, 0, max, 0, tlv_array)
 #define SOC_DAPM_ENUM(xname, xenum) \
index fcb312b3f25809e781098e2bd2514ae89f59329f..f6226914acfee0d2486d8e57095dbaead1b4a8cc 100644 (file)
@@ -387,8 +387,20 @@ int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source,
 int snd_soc_register_card(struct snd_soc_card *card);
 int snd_soc_unregister_card(struct snd_soc_card *card);
 int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card);
+#ifdef CONFIG_PM_SLEEP
 int snd_soc_suspend(struct device *dev);
 int snd_soc_resume(struct device *dev);
+#else
+static inline int snd_soc_suspend(struct device *dev)
+{
+       return 0;
+}
+
+static inline int snd_soc_resume(struct device *dev)
+{
+       return 0;
+}
+#endif
 int snd_soc_poweroff(struct device *dev);
 int snd_soc_register_platform(struct device *dev,
                const struct snd_soc_platform_driver *platform_drv);
index 65aca51fe255e487f4a3b36e5708b5159b089c03..e290de4e7e82d3d8779be63e983ec234aef16bfe 100644 (file)
@@ -1,7 +1,7 @@
 /*
 * linux/spear_dma.h
 *
-* Copyright (ST) 2012 Rajeev Kumar (rajeev-dlh.kumar@st.com)
+* Copyright (ST) 2012 Rajeev Kumar (rajeevkumar.linux@gmail.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
index d3583d3ee193aa5deaf1d9e3e0917560747af107..54e7af301888f00550a05b872e4c8a5eaf92e51c 100644 (file)
@@ -20,6 +20,8 @@
 #define ISCSIT_MIN_TAGS                        16
 #define ISCSIT_EXTRA_TAGS              8
 #define ISCSIT_TCP_BACKLOG             256
+#define ISCSI_RX_THREAD_NAME           "iscsi_trx"
+#define ISCSI_TX_THREAD_NAME           "iscsi_ttx"
 
 /* struct iscsi_node_attrib sanity values */
 #define NA_DATAOUT_TIMEOUT             3
@@ -60,6 +62,7 @@
 #define TA_CACHE_CORE_NPS              0
 /* T10 protection information disabled by default */
 #define TA_DEFAULT_T10_PI              0
+#define TA_DEFAULT_FABRIC_PROT_TYPE    0
 
 #define ISCSI_IOV_DATA_BUFFER          5
 
@@ -600,8 +603,11 @@ struct iscsi_conn {
        struct iscsi_tpg_np     *tpg_np;
        /* Pointer to parent session */
        struct iscsi_session    *sess;
-       /* Pointer to thread_set in use for this conn's threads */
-       struct iscsi_thread_set *thread_set;
+       int                     bitmap_id;
+       int                     rx_thread_active;
+       struct task_struct      *rx_thread;
+       int                     tx_thread_active;
+       struct task_struct      *tx_thread;
        /* list_head for session connection list */
        struct list_head        conn_list;
 } ____cacheline_aligned;
@@ -767,6 +773,7 @@ struct iscsi_tpg_attrib {
        u32                     demo_mode_discovery;
        u32                     default_erl;
        u8                      t10_pi;
+       u32                     fabric_prot_type;
        struct iscsi_portal_group *tpg;
 };
 
@@ -871,10 +878,10 @@ struct iscsit_global {
        /* Unique identifier used for the authentication daemon */
        u32                     auth_id;
        u32                     inactive_ts;
-       /* Thread Set bitmap count */
-       int                     ts_bitmap_count;
+#define ISCSIT_BITMAP_BITS     262144
        /* Thread Set bitmap pointer */
        unsigned long           *ts_bitmap;
+       spinlock_t              ts_bitmap_lock;
        /* Used for iSCSI discovery session authentication */
        struct iscsi_node_acl   discovery_acl;
        struct iscsi_portal_group       *discovery_tpg;
index 672150b6aaf52bc24c640d16f1f7c841e0be655d..480e9f82dfea861a70fa5e1df45076770c719f2e 100644 (file)
@@ -165,10 +165,8 @@ enum se_cmd_flags_table {
        SCF_SEND_DELAYED_TAS            = 0x00004000,
        SCF_ALUA_NON_OPTIMIZED          = 0x00008000,
        SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC = 0x00020000,
-       SCF_ACK_KREF                    = 0x00040000,
        SCF_COMPARE_AND_WRITE           = 0x00080000,
        SCF_COMPARE_AND_WRITE_POST      = 0x00100000,
-       SCF_CMD_XCOPY_PASSTHROUGH       = 0x00200000,
 };
 
 /* struct se_dev_entry->lun_flags and struct se_lun->lun_access */
@@ -520,11 +518,11 @@ struct se_cmd {
        struct list_head        se_cmd_list;
        struct completion       cmd_wait_comp;
        struct kref             cmd_kref;
-       struct target_core_fabric_ops *se_tfo;
+       const struct target_core_fabric_ops *se_tfo;
        sense_reason_t          (*execute_cmd)(struct se_cmd *);
        sense_reason_t          (*execute_rw)(struct se_cmd *, struct scatterlist *,
                                              u32, enum dma_data_direction);
-       sense_reason_t (*transport_complete_callback)(struct se_cmd *);
+       sense_reason_t (*transport_complete_callback)(struct se_cmd *, bool);
 
        unsigned char           *t_task_cdb;
        unsigned char           __t_task_cdb[TCM_MAX_COMMAND_SIZE];
@@ -591,6 +589,7 @@ struct se_node_acl {
        bool                    acl_stop:1;
        u32                     queue_depth;
        u32                     acl_index;
+       enum target_prot_type   saved_prot_type;
 #define MAX_ACL_TAG_SIZE 64
        char                    acl_tag[MAX_ACL_TAG_SIZE];
        /* Used for PR SPEC_I_PT=1 and REGISTER_AND_MOVE */
@@ -616,6 +615,7 @@ struct se_session {
        unsigned                sess_tearing_down:1;
        u64                     sess_bin_isid;
        enum target_prot_op     sup_prot_ops;
+       enum target_prot_type   sess_prot_type;
        struct se_node_acl      *se_node_acl;
        struct se_portal_group *se_tpg;
        void                    *fabric_sess_ptr;
@@ -890,7 +890,7 @@ struct se_portal_group {
        /* List of TCM sessions associated wth this TPG */
        struct list_head        tpg_sess_list;
        /* Pointer to $FABRIC_MOD dependent code */
-       struct target_core_fabric_ops *se_tpg_tfo;
+       const struct target_core_fabric_ops *se_tpg_tfo;
        struct se_wwn           *se_tpg_wwn;
        struct config_group     tpg_group;
        struct config_group     *tpg_default_groups[7];
index e0801386e4dcb793bfa0f06b4052ad1c517fa725..25bb04c4209ed5c42e82bc54d5ba3996194c4bb2 100644 (file)
@@ -5,12 +5,6 @@
 #define TARGET_CORE_NAME_MAX_LEN       64
 #define TARGET_FABRIC_NAME_SIZE                32
 
-extern struct target_fabric_configfs *target_fabric_configfs_init(
-                               struct module *, const char *);
-extern void target_fabric_configfs_free(struct target_fabric_configfs *);
-extern int target_fabric_configfs_register(struct target_fabric_configfs *);
-extern void target_fabric_configfs_deregister(struct target_fabric_configfs *);
-
 struct target_fabric_configfs_template {
        struct config_item_type tfc_discovery_cit;
        struct config_item_type tfc_wwn_cit;
index 22a4e98eec807ecaa93a735ad63fd05ef26809a9..17c7f5ac7ea0f5066c6b7f2bae0d66b0021f6358 100644 (file)
@@ -2,6 +2,8 @@
 #define TARGET_CORE_FABRIC_H
 
 struct target_core_fabric_ops {
+       struct module *module;
+       const char *name;
        struct configfs_subsystem *tf_subsys;
        char *(*get_fabric_name)(void);
        u8 (*get_fabric_proto_ident)(struct se_portal_group *);
@@ -27,6 +29,14 @@ struct target_core_fabric_ops {
         * inquiry response
         */
        int (*tpg_check_demo_mode_login_only)(struct se_portal_group *);
+       /*
+        * Optionally used as a configfs tunable to determine when
+        * target-core should signal the PROTECT=1 feature bit for
+        * backends that don't support T10-PI, so that either fabric
+        * HW offload or target-core emulation performs the associated
+        * WRITE_STRIP and READ_INSERT operations.
+        */
+       int (*tpg_check_prot_fabric_only)(struct se_portal_group *);
        struct se_node_acl *(*tpg_alloc_fabric_acl)(
                                        struct se_portal_group *);
        void (*tpg_release_fabric_acl)(struct se_portal_group *,
@@ -82,8 +92,23 @@ struct target_core_fabric_ops {
        struct se_node_acl *(*fabric_make_nodeacl)(struct se_portal_group *,
                                struct config_group *, const char *);
        void (*fabric_drop_nodeacl)(struct se_node_acl *);
+
+       struct configfs_attribute **tfc_discovery_attrs;
+       struct configfs_attribute **tfc_wwn_attrs;
+       struct configfs_attribute **tfc_tpg_base_attrs;
+       struct configfs_attribute **tfc_tpg_np_base_attrs;
+       struct configfs_attribute **tfc_tpg_attrib_attrs;
+       struct configfs_attribute **tfc_tpg_auth_attrs;
+       struct configfs_attribute **tfc_tpg_param_attrs;
+       struct configfs_attribute **tfc_tpg_nacl_base_attrs;
+       struct configfs_attribute **tfc_tpg_nacl_attrib_attrs;
+       struct configfs_attribute **tfc_tpg_nacl_auth_attrs;
+       struct configfs_attribute **tfc_tpg_nacl_param_attrs;
 };
 
+int target_register_template(const struct target_core_fabric_ops *fo);
+void target_unregister_template(const struct target_core_fabric_ops *fo);
+
 struct se_session *transport_init_session(enum target_prot_op);
 int transport_alloc_session_tags(struct se_session *, unsigned int,
                unsigned int);
@@ -95,13 +120,15 @@ void       transport_register_session(struct se_portal_group *,
                struct se_node_acl *, struct se_session *, void *);
 void   target_get_session(struct se_session *);
 void   target_put_session(struct se_session *);
+ssize_t        target_show_dynamic_sessions(struct se_portal_group *, char *);
 void   transport_free_session(struct se_session *);
 void   target_put_nacl(struct se_node_acl *);
 void   transport_deregister_session_configfs(struct se_session *);
 void   transport_deregister_session(struct se_session *);
 
 
-void   transport_init_se_cmd(struct se_cmd *, struct target_core_fabric_ops *,
+void   transport_init_se_cmd(struct se_cmd *,
+               const struct target_core_fabric_ops *,
                struct se_session *, u32, int, int, unsigned char *);
 sense_reason_t transport_lookup_cmd_lun(struct se_cmd *, u32);
 sense_reason_t target_setup_cmd_from_cdb(struct se_cmd *, unsigned char *);
@@ -153,8 +180,8 @@ int core_tpg_set_initiator_node_queue_depth(struct se_portal_group *,
                unsigned char *, u32, int);
 int    core_tpg_set_initiator_node_tag(struct se_portal_group *,
                struct se_node_acl *, const char *);
-int    core_tpg_register(struct target_core_fabric_ops *, struct se_wwn *,
-               struct se_portal_group *, void *, int);
+int    core_tpg_register(const struct target_core_fabric_ops *,
+               struct se_wwn *, struct se_portal_group *, void *, int);
 int    core_tpg_deregister(struct se_portal_group *);
 
 /* SAS helpers */
index b32a14905cfa5d8eab71c0450cc6ef4d0a383c85..7a0649c09e792e27ea073892f368a958c33ce02c 100644 (file)
@@ -90,6 +90,11 @@ static struct target_fabric_tpg_attribute _fabric##_tpg_##_name =    \
        _fabric##_tpg_store_##_name);
 
 
+#define TF_TPG_BASE_ATTR_RO(_fabric, _name)                            \
+static struct target_fabric_tpg_attribute _fabric##_tpg_##_name =      \
+       __CONFIGFS_EATTR_RO(_name,                                      \
+       _fabric##_tpg_show_##_name);
+
 CONFIGFS_EATTR_STRUCT(target_fabric_wwn, target_fabric_configfs);
 #define TF_WWN_ATTR(_fabric, _name, _mode)                             \
 static struct target_fabric_wwn_attribute _fabric##_wwn_##_name =      \
index 572e6503394a4c77bbfadfe1ce33bca134600724..7f79cf459591893c775e3520970a88c6bf572842 100644 (file)
@@ -407,10 +407,10 @@ TRACE_EVENT(btrfs_sync_file,
 
        TP_fast_assign(
                struct dentry *dentry = file->f_path.dentry;
-               struct inode *inode = dentry->d_inode;
+               struct inode *inode = d_inode(dentry);
 
                __entry->ino            = inode->i_ino;
-               __entry->parent         = dentry->d_parent->d_inode->i_ino;
+               __entry->parent         = d_inode(dentry->d_parent)->i_ino;
                __entry->datasync       = datasync;
                __entry->root_objectid  =
                                 BTRFS_I(inode)->root->root_key.objectid;
diff --git a/include/trace/events/clk.h b/include/trace/events/clk.h
new file mode 100644 (file)
index 0000000..7586072
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM clk
+
+#if !defined(_TRACE_CLK_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_CLK_H
+
+#include <linux/tracepoint.h>
+
+struct clk_core;
+
+DECLARE_EVENT_CLASS(clk,
+
+       TP_PROTO(struct clk_core *core),
+
+       TP_ARGS(core),
+
+       TP_STRUCT__entry(
+               __string(        name,           core->name       )
+       ),
+
+       TP_fast_assign(
+               __assign_str(name, core->name);
+       ),
+
+       TP_printk("%s", __get_str(name))
+);
+
+DEFINE_EVENT(clk, clk_enable,
+
+       TP_PROTO(struct clk_core *core),
+
+       TP_ARGS(core)
+);
+
+DEFINE_EVENT(clk, clk_enable_complete,
+
+       TP_PROTO(struct clk_core *core),
+
+       TP_ARGS(core)
+);
+
+DEFINE_EVENT(clk, clk_disable,
+
+       TP_PROTO(struct clk_core *core),
+
+       TP_ARGS(core)
+);
+
+DEFINE_EVENT(clk, clk_disable_complete,
+
+       TP_PROTO(struct clk_core *core),
+
+       TP_ARGS(core)
+);
+
+DEFINE_EVENT(clk, clk_prepare,
+
+       TP_PROTO(struct clk_core *core),
+
+       TP_ARGS(core)
+);
+
+DEFINE_EVENT(clk, clk_prepare_complete,
+
+       TP_PROTO(struct clk_core *core),
+
+       TP_ARGS(core)
+);
+
+DEFINE_EVENT(clk, clk_unprepare,
+
+       TP_PROTO(struct clk_core *core),
+
+       TP_ARGS(core)
+);
+
+DEFINE_EVENT(clk, clk_unprepare_complete,
+
+       TP_PROTO(struct clk_core *core),
+
+       TP_ARGS(core)
+);
+
+DECLARE_EVENT_CLASS(clk_rate,
+
+       TP_PROTO(struct clk_core *core, unsigned long rate),
+
+       TP_ARGS(core, rate),
+
+       TP_STRUCT__entry(
+               __string(        name,           core->name                )
+               __field(unsigned long,           rate                      )
+       ),
+
+       TP_fast_assign(
+               __assign_str(name, core->name);
+               __entry->rate = rate;
+       ),
+
+       TP_printk("%s %lu", __get_str(name), (unsigned long)__entry->rate)
+);
+
+DEFINE_EVENT(clk_rate, clk_set_rate,
+
+       TP_PROTO(struct clk_core *core, unsigned long rate),
+
+       TP_ARGS(core, rate)
+);
+
+DEFINE_EVENT(clk_rate, clk_set_rate_complete,
+
+       TP_PROTO(struct clk_core *core, unsigned long rate),
+
+       TP_ARGS(core, rate)
+);
+
+DECLARE_EVENT_CLASS(clk_parent,
+
+       TP_PROTO(struct clk_core *core, struct clk_core *parent),
+
+       TP_ARGS(core, parent),
+
+       TP_STRUCT__entry(
+               __string(        name,           core->name                )
+               __string(        pname,          parent->name              )
+       ),
+
+       TP_fast_assign(
+               __assign_str(name, core->name);
+               __assign_str(pname, parent->name);
+       ),
+
+       TP_printk("%s %s", __get_str(name), __get_str(pname))
+);
+
+DEFINE_EVENT(clk_parent, clk_set_parent,
+
+       TP_PROTO(struct clk_core *core, struct clk_core *parent),
+
+       TP_ARGS(core, parent)
+);
+
+DEFINE_EVENT(clk_parent, clk_set_parent_complete,
+
+       TP_PROTO(struct clk_core *core, struct clk_core *parent),
+
+       TP_ARGS(core, parent)
+);
+
+DECLARE_EVENT_CLASS(clk_phase,
+
+       TP_PROTO(struct clk_core *core, int phase),
+
+       TP_ARGS(core, phase),
+
+       TP_STRUCT__entry(
+               __string(        name,           core->name                )
+               __field(          int,           phase                     )
+       ),
+
+       TP_fast_assign(
+               __assign_str(name, core->name);
+               __entry->phase = phase;
+       ),
+
+       TP_printk("%s %d", __get_str(name), (int)__entry->phase)
+);
+
+DEFINE_EVENT(clk_phase, clk_set_phase,
+
+       TP_PROTO(struct clk_core *core, int phase),
+
+       TP_ARGS(core, phase)
+);
+
+DEFINE_EVENT(clk_phase, clk_set_phase_complete,
+
+       TP_PROTO(struct clk_core *core, int phase),
+
+       TP_ARGS(core, phase)
+);
+
+#endif /* _TRACE_CLK_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
index 7f20707849bbaa76a75f18c9fd99ea78314af249..fc733d28117a4399a17e27076825240421c70ae3 100644 (file)
@@ -439,10 +439,10 @@ TRACE_EVENT(ext3_sync_file_enter,
        TP_fast_assign(
                struct dentry *dentry = file->f_path.dentry;
 
-               __entry->dev            = dentry->d_inode->i_sb->s_dev;
-               __entry->ino            = dentry->d_inode->i_ino;
+               __entry->dev            = d_inode(dentry)->i_sb->s_dev;
+               __entry->ino            = d_inode(dentry)->i_ino;
                __entry->datasync       = datasync;
-               __entry->parent         = dentry->d_parent->d_inode->i_ino;
+               __entry->parent         = d_inode(dentry->d_parent)->i_ino;
        ),
 
        TP_printk("dev %d,%d ino %lu parent %ld datasync %d ",
@@ -710,9 +710,9 @@ TRACE_EVENT(ext3_unlink_enter,
 
        TP_fast_assign(
                __entry->parent         = parent->i_ino;
-               __entry->ino            = dentry->d_inode->i_ino;
-               __entry->size           = dentry->d_inode->i_size;
-               __entry->dev            = dentry->d_inode->i_sb->s_dev;
+               __entry->ino            = d_inode(dentry)->i_ino;
+               __entry->size           = d_inode(dentry)->i_size;
+               __entry->dev            = d_inode(dentry)->i_sb->s_dev;
        ),
 
        TP_printk("dev %d,%d ino %lu size %lld parent %ld",
@@ -734,8 +734,8 @@ TRACE_EVENT(ext3_unlink_exit,
        ),
 
        TP_fast_assign(
-               __entry->ino            = dentry->d_inode->i_ino;
-               __entry->dev            = dentry->d_inode->i_sb->s_dev;
+               __entry->ino            = d_inode(dentry)->i_ino;
+               __entry->dev            = d_inode(dentry)->i_sb->s_dev;
                __entry->ret            = ret;
        ),
 
index 47fca36ee426abb4cf359ceb47a3741fd9ba1393..08ec3dd276306276aa929cd54f87622e86971085 100644 (file)
@@ -872,10 +872,10 @@ TRACE_EVENT(ext4_sync_file_enter,
        TP_fast_assign(
                struct dentry *dentry = file->f_path.dentry;
 
-               __entry->dev            = dentry->d_inode->i_sb->s_dev;
-               __entry->ino            = dentry->d_inode->i_ino;
+               __entry->dev            = d_inode(dentry)->i_sb->s_dev;
+               __entry->ino            = d_inode(dentry)->i_ino;
                __entry->datasync       = datasync;
-               __entry->parent         = dentry->d_parent->d_inode->i_ino;
+               __entry->parent         = d_inode(dentry->d_parent)->i_ino;
        ),
 
        TP_printk("dev %d,%d ino %lu parent %lu datasync %d ",
@@ -1453,10 +1453,10 @@ TRACE_EVENT(ext4_unlink_enter,
        ),
 
        TP_fast_assign(
-               __entry->dev            = dentry->d_inode->i_sb->s_dev;
-               __entry->ino            = dentry->d_inode->i_ino;
+               __entry->dev            = d_inode(dentry)->i_sb->s_dev;
+               __entry->ino            = d_inode(dentry)->i_ino;
                __entry->parent         = parent->i_ino;
-               __entry->size           = dentry->d_inode->i_size;
+               __entry->size           = d_inode(dentry)->i_size;
        ),
 
        TP_printk("dev %d,%d ino %lu size %lld parent %lu",
@@ -1477,8 +1477,8 @@ TRACE_EVENT(ext4_unlink_exit,
        ),
 
        TP_fast_assign(
-               __entry->dev            = dentry->d_inode->i_sb->s_dev;
-               __entry->ino            = dentry->d_inode->i_ino;
+               __entry->dev            = d_inode(dentry)->i_sb->s_dev;
+               __entry->ino            = d_inode(dentry)->i_ino;
                __entry->ret            = ret;
        ),
 
index 38df23435ebbd399489326e649f828c8654878c0..1a0006a76b00a785c62d4bc01959136a6c7ea0e3 100644 (file)
@@ -431,6 +431,7 @@ header-y += virtio_blk.h
 header-y += virtio_config.h
 header-y += virtio_console.h
 header-y += virtio_ids.h
+header-y += virtio_input.h
 header-y += virtio_net.h
 header-y += virtio_pci.h
 header-y += virtio_ring.h
@@ -447,5 +448,6 @@ header-y += wireless.h
 header-y += x25.h
 header-y += xattr.h
 header-y += xfrm.h
+header-y += xilinx-v4l2-controls.h
 header-y += zorro.h
 header-y += zorro_ids.h
index 9b03033f9cd68281636c6e85c391d7fa9d354c69..d75774317b9b43288ba218b99084fbdda62e1309 100644 (file)
@@ -21,6 +21,8 @@
 #ifndef AM437X_VPFE_USER_H
 #define AM437X_VPFE_USER_H
 
+#include <linux/videodev2.h>
+
 enum vpfe_ccdc_data_size {
        VPFE_CCDC_DATA_16BITS = 0,
        VPFE_CCDC_DATA_15BITS,
index d1197ae3723ce5193b0526ea8dfa0511d39c8407..3e445a760f14b384bd78636f5f90b2bcb4f723cf 100644 (file)
  */
 #define FALLOC_FL_ZERO_RANGE           0x10
 
+/*
+ * FALLOC_FL_INSERT_RANGE is use to insert space within the file size without
+ * overwriting any existing data. The contents of the file beyond offset are
+ * shifted towards right by len bytes to create a hole.  As such, this
+ * operation will increase the size of the file by len bytes.
+ *
+ * Different filesystems may implement different limitations on the granularity
+ * of the operation. Most will limit operations to filesystem block size
+ * boundaries, but this boundary may be larger or smaller depending on
+ * the filesystem and/or the configuration of the filesystem or file.
+ *
+ * Attempting to insert space using this flag at OR beyond the end of
+ * the file is considered an illegal operation - just use ftruncate(2) or
+ * fallocate(2) with mode 0 for such type of operations.
+ */
+#define FALLOC_FL_INSERT_RANGE         0x20
+
 #endif /* _UAPI_FALLOC_H_ */
index f574d7be7631e5795f26a8934391b8b6f1473f8e..4b60056776d1484f4c6c43b6c4a1ef47a2592a61 100644 (file)
@@ -813,6 +813,7 @@ struct kvm_ppc_smmu_info {
 #define KVM_CAP_MIPS_MSA 112
 #define KVM_CAP_S390_INJECT_IRQ 113
 #define KVM_CAP_S390_IRQ_STATE 114
+#define KVM_CAP_PPC_HWRNG 115
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
index 73c78f18a328b08bc7eb6e8bdf2e094518e29d18..190d491d5b13a4cea9fa270c9d2cb7d02e6f29a2 100644 (file)
@@ -45,6 +45,7 @@
 #define MEDIA_BUS_FMT_RGB565_2X8_BE            0x1007
 #define MEDIA_BUS_FMT_RGB565_2X8_LE            0x1008
 #define MEDIA_BUS_FMT_RGB666_1X18              0x1009
+#define MEDIA_BUS_FMT_RBG888_1X24              0x100e
 #define MEDIA_BUS_FMT_RGB666_1X24_CPADHI       0x1015
 #define MEDIA_BUS_FMT_RGB666_1X7X3_SPWG                0x1010
 #define MEDIA_BUS_FMT_BGR888_1X24              0x1013
@@ -55,6 +56,7 @@
 #define MEDIA_BUS_FMT_RGB888_1X7X4_SPWG                0x1011
 #define MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA       0x1012
 #define MEDIA_BUS_FMT_ARGB8888_1X32            0x100d
+#define MEDIA_BUS_FMT_RGB888_1X32_PADHI                0x100f
 
 /* YUV (including grey) - next is      0x2026 */
 #define MEDIA_BUS_FMT_Y8_1X8                   0x2001
 #define MEDIA_BUS_FMT_YUYV10_2X10              0x200b
 #define MEDIA_BUS_FMT_YVYU10_2X10              0x200c
 #define MEDIA_BUS_FMT_Y12_1X12                 0x2013
+#define MEDIA_BUS_FMT_UYVY12_2X12              0x201c
+#define MEDIA_BUS_FMT_VYUY12_2X12              0x201d
+#define MEDIA_BUS_FMT_YUYV12_2X12              0x201e
+#define MEDIA_BUS_FMT_YVYU12_2X12              0x201f
 #define MEDIA_BUS_FMT_UYVY8_1X16               0x200f
 #define MEDIA_BUS_FMT_VYUY8_1X16               0x2010
 #define MEDIA_BUS_FMT_YUYV8_1X16               0x2011
 #define MEDIA_BUS_FMT_VYUY10_1X20              0x201b
 #define MEDIA_BUS_FMT_YUYV10_1X20              0x200d
 #define MEDIA_BUS_FMT_YVYU10_1X20              0x200e
+#define MEDIA_BUS_FMT_VUY8_1X24                        0x2024
 #define MEDIA_BUS_FMT_YUV8_1X24                        0x2025
-#define MEDIA_BUS_FMT_YUV10_1X30               0x2016
-#define MEDIA_BUS_FMT_AYUV8_1X32               0x2017
-#define MEDIA_BUS_FMT_UYVY12_2X12              0x201c
-#define MEDIA_BUS_FMT_VYUY12_2X12              0x201d
-#define MEDIA_BUS_FMT_YUYV12_2X12              0x201e
-#define MEDIA_BUS_FMT_YVYU12_2X12              0x201f
 #define MEDIA_BUS_FMT_UYVY12_1X24              0x2020
 #define MEDIA_BUS_FMT_VYUY12_1X24              0x2021
 #define MEDIA_BUS_FMT_YUYV12_1X24              0x2022
 #define MEDIA_BUS_FMT_YVYU12_1X24              0x2023
+#define MEDIA_BUS_FMT_YUV10_1X30               0x2016
+#define MEDIA_BUS_FMT_AYUV8_1X32               0x2017
 
 /* Bayer - next is     0x3019 */
 #define MEDIA_BUS_FMT_SBGGR8_1X8               0x3001
index d847c760e8f09c49fec028cbe3a7b599cee2e60f..4e816be3de39b404b3c21b9f27cc8e3b1eb00025 100644 (file)
@@ -50,7 +50,14 @@ struct media_device_info {
 #define MEDIA_ENT_T_DEVNODE_V4L                (MEDIA_ENT_T_DEVNODE + 1)
 #define MEDIA_ENT_T_DEVNODE_FB         (MEDIA_ENT_T_DEVNODE + 2)
 #define MEDIA_ENT_T_DEVNODE_ALSA       (MEDIA_ENT_T_DEVNODE + 3)
-#define MEDIA_ENT_T_DEVNODE_DVB                (MEDIA_ENT_T_DEVNODE + 4)
+#define MEDIA_ENT_T_DEVNODE_DVB_FE     (MEDIA_ENT_T_DEVNODE + 4)
+#define MEDIA_ENT_T_DEVNODE_DVB_DEMUX  (MEDIA_ENT_T_DEVNODE + 5)
+#define MEDIA_ENT_T_DEVNODE_DVB_DVR    (MEDIA_ENT_T_DEVNODE + 6)
+#define MEDIA_ENT_T_DEVNODE_DVB_CA     (MEDIA_ENT_T_DEVNODE + 7)
+#define MEDIA_ENT_T_DEVNODE_DVB_NET    (MEDIA_ENT_T_DEVNODE + 8)
+
+/* Legacy symbol. Use it to avoid userspace compilation breakages */
+#define MEDIA_ENT_T_DEVNODE_DVB                MEDIA_ENT_T_DEVNODE_DVB_FE
 
 #define MEDIA_ENT_T_V4L2_SUBDEV                (2 << MEDIA_ENT_TYPE_SHIFT)
 #define MEDIA_ENT_T_V4L2_SUBDEV_SENSOR (MEDIA_ENT_T_V4L2_SUBDEV + 1)
@@ -59,6 +66,8 @@ struct media_device_info {
 /* A converter of analogue video to its digital representation. */
 #define MEDIA_ENT_T_V4L2_SUBDEV_DECODER        (MEDIA_ENT_T_V4L2_SUBDEV + 4)
 
+#define MEDIA_ENT_T_V4L2_SUBDEV_TUNER  (MEDIA_ENT_T_V4L2_SUBDEV + 5)
+
 #define MEDIA_ENT_FL_DEFAULT           (1 << 0)
 
 struct media_entity_desc {
@@ -78,17 +87,48 @@ struct media_entity_desc {
                struct {
                        __u32 major;
                        __u32 minor;
-               } v4l;
-               struct {
-                       __u32 major;
-                       __u32 minor;
-               } fb;
+               } dev;
+
+#if 1
+               /*
+                * TODO: this shouldn't have been added without
+                * actual drivers that use this. When the first real driver
+                * appears that sets this information, special attention
+                * should be given whether this information is 1) enough, and
+                * 2) can deal with udev rules that rename devices. The struct
+                * dev would not be sufficient for this since that does not
+                * contain the subdevice information. In addition, struct dev
+                * can only refer to a single device, and not to multiple (e.g.
+                * pcm and mixer devices).
+                *
+                * So for now mark this as a to do.
+                */
                struct {
                        __u32 card;
                        __u32 device;
                        __u32 subdevice;
                } alsa;
+#endif
+
+#if 1
+               /*
+                * DEPRECATED: previous node specifications. Kept just to
+                * avoid breaking compilation, but media_entity_desc.dev
+                * should be used instead. In particular, alsa and dvb
+                * fields below are wrong: for all devnodes, there should
+                * be just major/minor inside the struct, as this is enough
+                * to represent any devnode, no matter what type.
+                */
+               struct {
+                       __u32 major;
+                       __u32 minor;
+               } v4l;
+               struct {
+                       __u32 major;
+                       __u32 minor;
+               } fb;
                int dvb;
+#endif
 
                /* Sub-device specifications */
                /* Nothing needed yet */
index 35f5f4c6c260df7ed2ee74b845522a485ed5394e..adc0aff83fbbc266cdb3896e774749e48c62995c 100644 (file)
  */
 #define NFS4_MAX_BACK_CHANNEL_OPS 2
 
-enum nfs4_acl_whotype {
-       NFS4_ACL_WHO_NAMED = 0,
-       NFS4_ACL_WHO_OWNER,
-       NFS4_ACL_WHO_GROUP,
-       NFS4_ACL_WHO_EVERYONE,
-};
-
 #endif /* _UAPI_LINUX_NFS4_H */
 
 /*
index 8d4b1c7b24d4a57e3ec46b4d2e6b249fd946017f..038e36c96669ef915bcca3ad42c8b0ef8b4eb065 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/linux/nfs_idmap.h
+ * include/uapi/linux/nfs_idmap.h
  *
  *  UID and GID to name mapping for clients.
  *
index 0bf130a1c58df4b0b363ee408ec57263f44af452..28ec6c9c421acf689088a2fe00cd5f04e7b6cd1d 100644 (file)
 
 #include <linux/sunrpc/debug.h>
 
-/*
- * Enable debugging for nfsd.
- * Requires RPC_DEBUG.
- */
-#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
-# define NFSD_DEBUG            1
-#endif
-
 /*
  * knfsd debug flags
  */
index d3bd6ffec04101138e831076789fc11cee98f2be..0df7bd5d2fb17cf4b9df3b300451cce13075d194 100644 (file)
@@ -21,6 +21,9 @@
 
 /*
  * Export flags.
+ *
+ * Please update the expflags[] array in fs/nfsd/export.c when adding
+ * a new flag.
  */
 #define NFSEXP_READONLY                0x0001
 #define NFSEXP_INSECURE_PORT   0x0002
index 49f4210d4394fb837a567f3f241f9b33be4351fd..2ae6131e69a5ba766f8d3b8b4fecf8d770bf27ac 100644 (file)
 #define MD_DISK_ACTIVE         1 /* disk is running or spare disk */
 #define MD_DISK_SYNC           2 /* disk is in sync with the raid set */
 #define MD_DISK_REMOVED                3 /* disk is in sync with the raid set */
+#define MD_DISK_CLUSTER_ADD     4 /* Initiate a disk add across the cluster
+                                  * For clustered enviroments only.
+                                  */
+#define MD_DISK_CANDIDATE      5 /* disk is added as spare (local) until confirmed
+                                  * For clustered enviroments only.
+                                  */
 
 #define        MD_DISK_WRITEMOSTLY     9 /* disk is "write-mostly" is RAID1 config.
                                   * read requests will only be sent here in
@@ -101,6 +107,7 @@ typedef struct mdp_device_descriptor_s {
 #define MD_SB_CLEAN            0
 #define MD_SB_ERRORS           1
 
+#define        MD_SB_CLUSTERED         5 /* MD is clustered */
 #define        MD_SB_BITMAP_PRESENT    8 /* bitmap may be present nearby */
 
 /*
index 74e7c60c4716e66e7c94f07d98379d6614088a6a..1cb8aa6850b59196662dcc4d3f17d0b4ae0315c1 100644 (file)
@@ -62,6 +62,7 @@
 #define STOP_ARRAY             _IO (MD_MAJOR, 0x32)
 #define STOP_ARRAY_RO          _IO (MD_MAJOR, 0x33)
 #define RESTART_ARRAY_RW       _IO (MD_MAJOR, 0x34)
+#define CLUSTERED_DISK_NACK    _IO (MD_MAJOR, 0x35)
 
 /* 63 partitions with the alternate major number (mdp) */
 #define MdpMinorShift 6
index 00adb01fa5f38f53858ea2bb265f2b040948f4cf..e9b4cb0cd7edae5aaf029288db27fe56a8ff05c5 100644 (file)
 #define UART_FCR_PXAR16        0x80    /* receive FIFO threshold = 16 */
 #define UART_FCR_PXAR32        0xc0    /* receive FIFO threshold = 32 */
 
-/*
- * Intel MID on-chip HSU (High Speed UART) defined bits
- */
-#define UART_FCR_HSU_64_1B     0x00    /* receive FIFO treshold = 1 */
-#define UART_FCR_HSU_64_16B    0x40    /* receive FIFO treshold = 16 */
-#define UART_FCR_HSU_64_32B    0x80    /* receive FIFO treshold = 32 */
-#define UART_FCR_HSU_64_56B    0xc0    /* receive FIFO treshold = 56 */
-
-#define UART_FCR_HSU_16_1B     0x00    /* receive FIFO treshold = 1 */
-#define UART_FCR_HSU_16_4B     0x40    /* receive FIFO treshold = 4 */
-#define UART_FCR_HSU_16_8B     0x80    /* receive FIFO treshold = 8 */
-#define UART_FCR_HSU_16_14B    0xc0    /* receive FIFO treshold = 14 */
-
-#define UART_FCR_HSU_64B_FIFO  0x20    /* chose 64 bytes FIFO */
-#define UART_FCR_HSU_16B_FIFO  0x00    /* chose 16 bytes FIFO */
-
-#define UART_FCR_HALF_EMPT_TXI 0x00    /* trigger TX_EMPT IRQ for half empty */
-#define UART_FCR_FULL_EMPT_TXI 0x08    /* trigger TX_EMPT IRQ for full empty */
-
 /*
  * These register definitions are for the 16C950
  */
index b483d1909d3e6baee31be68e5e905aca4a15572c..b67f99d3c520bdc6ca6e51803eb12b1479709fdf 100644 (file)
@@ -6,7 +6,7 @@
 #include <linux/types.h>
 #include <linux/uio.h>
 
-#define TCMU_VERSION "1.0"
+#define TCMU_VERSION "2.0"
 
 /*
  * Ring Design
  * should process the next packet the same way, and so on.
  */
 
-#define TCMU_MAILBOX_VERSION 1
+#define TCMU_MAILBOX_VERSION 2
 #define ALIGN_SIZE 64 /* Should be enough for most CPUs */
 
+/* See https://gcc.gnu.org/onlinedocs/cpp/Stringification.html */
+#define xstr(s) str(s)
+#define str(s) #s
+
 struct tcmu_mailbox {
        __u16 version;
        __u16 flags;
@@ -64,31 +68,36 @@ enum tcmu_opcode {
  * Only a few opcodes, and length is 8-byte aligned, so use low bits for opcode.
  */
 struct tcmu_cmd_entry_hdr {
-               __u32 len_op;
+       __u32 len_op;
+       __u16 cmd_id;
+       __u8 kflags;
+#define TCMU_UFLAG_UNKNOWN_OP 0x1
+       __u8 uflags;
+
 } __packed;
 
 #define TCMU_OP_MASK 0x7
 
-static inline enum tcmu_opcode tcmu_hdr_get_op(struct tcmu_cmd_entry_hdr *hdr)
+static inline enum tcmu_opcode tcmu_hdr_get_op(__u32 len_op)
 {
-       return hdr->len_op & TCMU_OP_MASK;
+       return len_op & TCMU_OP_MASK;
 }
 
-static inline void tcmu_hdr_set_op(struct tcmu_cmd_entry_hdr *hdr, enum tcmu_opcode op)
+static inline void tcmu_hdr_set_op(__u32 *len_op, enum tcmu_opcode op)
 {
-       hdr->len_op &= ~TCMU_OP_MASK;
-       hdr->len_op |= (op & TCMU_OP_MASK);
+       *len_op &= ~TCMU_OP_MASK;
+       *len_op |= (op & TCMU_OP_MASK);
 }
 
-static inline __u32 tcmu_hdr_get_len(struct tcmu_cmd_entry_hdr *hdr)
+static inline __u32 tcmu_hdr_get_len(__u32 len_op)
 {
-       return hdr->len_op & ~TCMU_OP_MASK;
+       return len_op & ~TCMU_OP_MASK;
 }
 
-static inline void tcmu_hdr_set_len(struct tcmu_cmd_entry_hdr *hdr, __u32 len)
+static inline void tcmu_hdr_set_len(__u32 *len_op, __u32 len)
 {
-       hdr->len_op &= TCMU_OP_MASK;
-       hdr->len_op |= len;
+       *len_op &= TCMU_OP_MASK;
+       *len_op |= len;
 }
 
 /* Currently the same as SCSI_SENSE_BUFFERSIZE */
@@ -97,13 +106,14 @@ static inline void tcmu_hdr_set_len(struct tcmu_cmd_entry_hdr *hdr, __u32 len)
 struct tcmu_cmd_entry {
        struct tcmu_cmd_entry_hdr hdr;
 
-       uint16_t cmd_id;
-       uint16_t __pad1;
-
        union {
                struct {
+                       uint32_t iov_cnt;
+                       uint32_t iov_bidi_cnt;
+                       uint32_t iov_dif_cnt;
                        uint64_t cdb_off;
-                       uint64_t iov_cnt;
+                       uint64_t __pad1;
+                       uint64_t __pad2;
                        struct iovec iov[0];
                } req;
                struct {
index 6c8f159e416eea1b2781b4e00139b4b3afe2ea9a..c039f1d68a0929bfac96031d8eaa489be19edba9 100644 (file)
        .type = V4L2_DV_BT_656_1120, \
        V4L2_INIT_BT_TIMINGS(720, 480, 1, 0, \
                13500000, 19, 62, 57, 4, 3, 15, 4, 3, 16, \
-               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_HALF_LINE) \
+               V4L2_DV_BT_STD_CEA861, \
+               V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_720X480P59_94 { \
        .type = V4L2_DV_BT_656_1120, \
        V4L2_INIT_BT_TIMINGS(720, 480, 0, 0, \
                27000000, 16, 62, 60, 9, 6, 30, 0, 0, 0, \
-               V4L2_DV_BT_STD_CEA861, 0) \
+               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 /* Note: these are the nominal timings, for HDMI links this format is typically
        .type = V4L2_DV_BT_656_1120, \
        V4L2_INIT_BT_TIMINGS(720, 576, 1, 0, \
                13500000, 12, 63, 69, 2, 3, 19, 2, 3, 20, \
-               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_HALF_LINE) \
+               V4L2_DV_BT_STD_CEA861, \
+               V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_720X576P50 { \
        .type = V4L2_DV_BT_656_1120, \
        V4L2_INIT_BT_TIMINGS(720, 576, 0, 0, \
                27000000, 12, 64, 68, 5, 5, 39, 0, 0, 0, \
-               V4L2_DV_BT_STD_CEA861, 0) \
+               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_1280X720P24 { \
@@ -88,7 +90,7 @@
        V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
                V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
                74250000, 2420, 40, 220, 5, 5, 20, 0, 0, 0, \
-               V4L2_DV_BT_STD_CEA861, 0) \
+               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_1280X720P30 { \
@@ -96,7 +98,8 @@
        V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
                V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
                74250000, 1760, 40, 220, 5, 5, 20, 0, 0, 0, \
-               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_CAN_REDUCE_FPS) \
+               V4L2_DV_BT_STD_CEA861, \
+               V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_1280X720P50 { \
        V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
                V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
                74250000, 440, 40, 220, 5, 5, 20, 0, 0, 0, \
-               V4L2_DV_BT_STD_CEA861, 0) \
+               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_1280X720P60 { \
        V4L2_INIT_BT_TIMINGS(1280, 720, 0, \
                V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
                74250000, 110, 40, 220, 5, 5, 20, 0, 0, 0, \
-               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_CAN_REDUCE_FPS) \
+               V4L2_DV_BT_STD_CEA861, \
+               V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_1920X1080P24 { \
        V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
                V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
                74250000, 638, 44, 148, 4, 5, 36, 0, 0, 0, \
-               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_CAN_REDUCE_FPS) \
+               V4L2_DV_BT_STD_CEA861, \
+               V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_1920X1080P25 { \
        V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
                V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
                74250000, 528, 44, 148, 4, 5, 36, 0, 0, 0, \
-               V4L2_DV_BT_STD_CEA861, 0) \
+               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_1920X1080P30 { \
        V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
                V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
                74250000, 88, 44, 148, 4, 5, 36, 0, 0, 0, \
-               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_CAN_REDUCE_FPS) \
+               V4L2_DV_BT_STD_CEA861, \
+               V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_1920X1080I50 { \
        V4L2_INIT_BT_TIMINGS(1920, 1080, 1, \
                V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
                74250000, 528, 44, 148, 2, 5, 15, 2, 5, 16, \
-               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_HALF_LINE) \
+               V4L2_DV_BT_STD_CEA861, \
+               V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_1920X1080P50 { \
        V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
                V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
                148500000, 528, 44, 148, 4, 5, 36, 0, 0, 0, \
-               V4L2_DV_BT_STD_CEA861, 0) \
+               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_1920X1080I60 { \
                V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
                74250000, 88, 44, 148, 2, 5, 15, 2, 5, 16, \
                V4L2_DV_BT_STD_CEA861, \
-               V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_HALF_LINE) \
+               V4L2_DV_FL_CAN_REDUCE_FPS | \
+               V4L2_DV_FL_HALF_LINE | V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_1920X1080P60 { \
                V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
                148500000, 88, 44, 148, 4, 5, 36, 0, 0, 0, \
                V4L2_DV_BT_STD_DMT | V4L2_DV_BT_STD_CEA861, \
-               V4L2_DV_FL_CAN_REDUCE_FPS) \
+               V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_3840X2160P24 { \
        .type = V4L2_DV_BT_656_1120, \
        V4L2_INIT_BT_TIMINGS(3840, 2160, 0, V4L2_DV_HSYNC_POS_POL, \
                297000000, 1276, 88, 296, 8, 10, 72, 0, 0, 0, \
-               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_CAN_REDUCE_FPS) \
+               V4L2_DV_BT_STD_CEA861, \
+               V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_3840X2160P25 { \
        .type = V4L2_DV_BT_656_1120, \
        V4L2_INIT_BT_TIMINGS(3840, 2160, 0, V4L2_DV_HSYNC_POS_POL, \
                297000000, 1056, 88, 296, 8, 10, 72, 0, 0, 0, \
-               V4L2_DV_BT_STD_CEA861, 0) \
+               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_3840X2160P30 { \
        .type = V4L2_DV_BT_656_1120, \
        V4L2_INIT_BT_TIMINGS(3840, 2160, 0, V4L2_DV_HSYNC_POS_POL, \
                297000000, 176, 88, 296, 8, 10, 72, 0, 0, 0, \
-               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_CAN_REDUCE_FPS) \
+               V4L2_DV_BT_STD_CEA861, \
+               V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_3840X2160P50 { \
        .type = V4L2_DV_BT_656_1120, \
        V4L2_INIT_BT_TIMINGS(3840, 2160, 0, V4L2_DV_HSYNC_POS_POL, \
                594000000, 1056, 88, 296, 8, 10, 72, 0, 0, 0, \
-               V4L2_DV_BT_STD_CEA861, 0) \
+               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_3840X2160P60 { \
        .type = V4L2_DV_BT_656_1120, \
        V4L2_INIT_BT_TIMINGS(3840, 2160, 0, V4L2_DV_HSYNC_POS_POL, \
                594000000, 176, 88, 296, 8, 10, 72, 0, 0, 0, \
-               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_CAN_REDUCE_FPS) \
+               V4L2_DV_BT_STD_CEA861, \
+               V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_4096X2160P24 { \
        .type = V4L2_DV_BT_656_1120, \
        V4L2_INIT_BT_TIMINGS(4096, 2160, 0, V4L2_DV_HSYNC_POS_POL, \
                297000000, 1020, 88, 296, 8, 10, 72, 0, 0, 0, \
-               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_CAN_REDUCE_FPS) \
+               V4L2_DV_BT_STD_CEA861, \
+               V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_4096X2160P25 { \
        .type = V4L2_DV_BT_656_1120, \
        V4L2_INIT_BT_TIMINGS(4096, 2160, 0, V4L2_DV_HSYNC_POS_POL, \
                297000000, 968, 88, 128, 8, 10, 72, 0, 0, 0, \
-               V4L2_DV_BT_STD_CEA861, 0) \
+               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_4096X2160P30 { \
        .type = V4L2_DV_BT_656_1120, \
        V4L2_INIT_BT_TIMINGS(4096, 2160, 0, V4L2_DV_HSYNC_POS_POL, \
                297000000, 88, 88, 128, 8, 10, 72, 0, 0, 0, \
-               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_CAN_REDUCE_FPS) \
+               V4L2_DV_BT_STD_CEA861, \
+               V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_4096X2160P50 { \
        .type = V4L2_DV_BT_656_1120, \
        V4L2_INIT_BT_TIMINGS(4096, 2160, 0, V4L2_DV_HSYNC_POS_POL, \
                594000000, 968, 88, 128, 8, 10, 72, 0, 0, 0, \
-               V4L2_DV_BT_STD_CEA861, 0) \
+               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 #define V4L2_DV_BT_CEA_4096X2160P60 { \
        .type = V4L2_DV_BT_656_1120, \
        V4L2_INIT_BT_TIMINGS(4096, 2160, 0, V4L2_DV_HSYNC_POS_POL, \
                594000000, 88, 88, 128, 8, 10, 72, 0, 0, 0, \
-               V4L2_DV_BT_STD_CEA861, V4L2_DV_FL_CAN_REDUCE_FPS) \
+               V4L2_DV_BT_STD_CEA861, \
+               V4L2_DV_FL_CAN_REDUCE_FPS | V4L2_DV_FL_IS_CE_VIDEO) \
 }
 
 
index e0a7e3da498a34577fbb5fd7ac4a7e9a8e95108f..dbce2b554e0268695e382f0a31d2e66394e2da85 100644 (file)
@@ -69,12 +69,14 @@ struct v4l2_subdev_crop {
  * @pad: pad number, as reported by the media API
  * @index: format index during enumeration
  * @code: format code (MEDIA_BUS_FMT_ definitions)
+ * @which: format type (from enum v4l2_subdev_format_whence)
  */
 struct v4l2_subdev_mbus_code_enum {
        __u32 pad;
        __u32 index;
        __u32 code;
-       __u32 reserved[9];
+       __u32 which;
+       __u32 reserved[8];
 };
 
 /**
@@ -82,6 +84,7 @@ struct v4l2_subdev_mbus_code_enum {
  * @pad: pad number, as reported by the media API
  * @index: format index during enumeration
  * @code: format code (MEDIA_BUS_FMT_ definitions)
+ * @which: format type (from enum v4l2_subdev_format_whence)
  */
 struct v4l2_subdev_frame_size_enum {
        __u32 index;
@@ -91,7 +94,8 @@ struct v4l2_subdev_frame_size_enum {
        __u32 max_width;
        __u32 min_height;
        __u32 max_height;
-       __u32 reserved[9];
+       __u32 which;
+       __u32 reserved[8];
 };
 
 /**
@@ -113,6 +117,7 @@ struct v4l2_subdev_frame_interval {
  * @width: frame width in pixels
  * @height: frame height in pixels
  * @interval: frame interval in seconds
+ * @which: format type (from enum v4l2_subdev_format_whence)
  */
 struct v4l2_subdev_frame_interval_enum {
        __u32 index;
@@ -121,7 +126,8 @@ struct v4l2_subdev_frame_interval_enum {
        __u32 width;
        __u32 height;
        struct v4l2_fract interval;
-       __u32 reserved[9];
+       __u32 which;
+       __u32 reserved[8];
 };
 
 /**
index fbdc3602ee2706201e9225097e73571b7f74c4ea..fa376f7666bae59f86fe57e4effd9b8687c0900d 100644 (file)
@@ -268,9 +268,10 @@ enum v4l2_ycbcr_encoding {
 
 enum v4l2_quantization {
        /*
-        * The default for R'G'B' quantization is always full range. For
-        * Y'CbCr the quantization is always limited range, except for
-        * SYCC, XV601, XV709 or JPEG: those are full range.
+        * The default for R'G'B' quantization is always full range, except
+        * for the BT2020 colorspace. For Y'CbCr the quantization is always
+        * limited range, except for COLORSPACE_JPEG, SYCC, XV601 or XV709:
+        * those are full range.
         */
        V4L2_QUANTIZATION_DEFAULT     = 0,
        V4L2_QUANTIZATION_FULL_RANGE  = 1,
@@ -1187,6 +1188,12 @@ struct v4l2_bt_timings {
    exactly the same number of half-lines. Whether half-lines can be detected
    or used depends on the hardware. */
 #define V4L2_DV_FL_HALF_LINE                   (1 << 3)
+/* If set, then this is a Consumer Electronics (CE) video format. Such formats
+ * differ from other formats (commonly called IT formats) in that if RGB
+ * encoding is used then by default the RGB values use limited range (i.e.
+ * use the range 16-235) as opposed to 0-255. All formats defined in CEA-861
+ * except for the 640x480 format are CE formats. */
+#define V4L2_DV_FL_IS_CE_VIDEO                 (1 << 4)
 
 /* A few useful defines to calculate the total blanking and frame sizes */
 #define V4L2_DV_BT_BLANKING_WIDTH(bt) \
@@ -1456,6 +1463,7 @@ struct v4l2_querymenu {
 #define V4L2_CTRL_FLAG_WRITE_ONLY      0x0040
 #define V4L2_CTRL_FLAG_VOLATILE                0x0080
 #define V4L2_CTRL_FLAG_HAS_PAYLOAD     0x0100
+#define V4L2_CTRL_FLAG_EXECUTE_ON_WRITE        0x0200
 
 /*  Query flags, to be ORed with the control ID */
 #define V4L2_CTRL_FLAG_NEXT_CTRL       0x80000000
@@ -1841,8 +1849,8 @@ struct v4l2_mpeg_vbi_fmt_ivtv {
  */
 struct v4l2_plane_pix_format {
        __u32           sizeimage;
-       __u16           bytesperline;
-       __u16           reserved[7];
+       __u32           bytesperline;
+       __u16           reserved[6];
 } __attribute__ ((packed));
 
 /**
index 4b0488f20b2ef5bfa9c3c4e94c4dba112a9d0527..984169a819ee4c8f2163c6a5c12d24fbf273caec 100644 (file)
@@ -25,6 +25,7 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE. */
+#include <linux/types.h>
 #include <linux/virtio_ids.h>
 #include <linux/virtio_config.h>
 
@@ -38,9 +39,9 @@
 
 struct virtio_balloon_config {
        /* Number of pages host wants Guest to give up. */
-       __le32 num_pages;
+       __u32 num_pages;
        /* Number of pages we've actually got in balloon. */
-       __le32 actual;
+       __u32 actual;
 };
 
 #define VIRTIO_BALLOON_S_SWAP_IN  0   /* Amount of memory swapped in */
@@ -51,9 +52,32 @@ struct virtio_balloon_config {
 #define VIRTIO_BALLOON_S_MEMTOT   5   /* Total amount of memory */
 #define VIRTIO_BALLOON_S_NR       6
 
+/*
+ * Memory statistics structure.
+ * Driver fills an array of these structures and passes to device.
+ *
+ * NOTE: fields are laid out in a way that would make compiler add padding
+ * between and after fields, so we have to use compiler-specific attributes to
+ * pack it, to disable this padding. This also often causes compiler to
+ * generate suboptimal code.
+ *
+ * We maintain this statistics structure format for backwards compatibility,
+ * but don't follow this example.
+ *
+ * If implementing a similar structure, do something like the below instead:
+ *     struct virtio_balloon_stat {
+ *         __virtio16 tag;
+ *         __u8 reserved[6];
+ *         __virtio64 val;
+ *     };
+ *
+ * In other words, add explicit reserved fields to align field and
+ * structure boundaries at field size, avoiding compiler padding
+ * without the packed attribute.
+ */
 struct virtio_balloon_stat {
-       __u16 tag;
-       __u64 val;
+       __virtio16 tag;
+       __virtio64 val;
 } __attribute__((packed));
 
 #endif /* _LINUX_VIRTIO_BALLOON_H */
index 284fc3a05f7bb5a80c08e6980133c87b6f0c9397..5f60aa4be50a5756651884a559ba6280006f1d1f 100644 (file)
@@ -39,5 +39,6 @@
 #define VIRTIO_ID_9P           9 /* 9p virtio console */
 #define VIRTIO_ID_RPROC_SERIAL 11 /* virtio remoteproc serial link */
 #define VIRTIO_ID_CAIF        12 /* Virtio caif */
+#define VIRTIO_ID_INPUT        18 /* virtio input */
 
 #endif /* _LINUX_VIRTIO_IDS_H */
diff --git a/include/uapi/linux/virtio_input.h b/include/uapi/linux/virtio_input.h
new file mode 100644 (file)
index 0000000..a7fe5c8
--- /dev/null
@@ -0,0 +1,76 @@
+#ifndef _LINUX_VIRTIO_INPUT_H
+#define _LINUX_VIRTIO_INPUT_H
+/* This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of IBM nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL IBM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE. */
+
+#include <linux/types.h>
+
+enum virtio_input_config_select {
+       VIRTIO_INPUT_CFG_UNSET      = 0x00,
+       VIRTIO_INPUT_CFG_ID_NAME    = 0x01,
+       VIRTIO_INPUT_CFG_ID_SERIAL  = 0x02,
+       VIRTIO_INPUT_CFG_ID_DEVIDS  = 0x03,
+       VIRTIO_INPUT_CFG_PROP_BITS  = 0x10,
+       VIRTIO_INPUT_CFG_EV_BITS    = 0x11,
+       VIRTIO_INPUT_CFG_ABS_INFO   = 0x12,
+};
+
+struct virtio_input_absinfo {
+       __u32 min;
+       __u32 max;
+       __u32 fuzz;
+       __u32 flat;
+       __u32 res;
+};
+
+struct virtio_input_devids {
+       __u16 bustype;
+       __u16 vendor;
+       __u16 product;
+       __u16 version;
+};
+
+struct virtio_input_config {
+       __u8    select;
+       __u8    subsel;
+       __u8    size;
+       __u8    reserved[5];
+       union {
+               char string[128];
+               __u8 bitmap[128];
+               struct virtio_input_absinfo abs;
+               struct virtio_input_devids ids;
+       } u;
+};
+
+struct virtio_input_event {
+       __le16 type;
+       __le16 code;
+       __le32 value;
+};
+
+#endif /* _LINUX_VIRTIO_INPUT_H */
index a3318f31e8e7fd05f317c595e8c4ce3bc3595fac..915980ac68dfa8cc1dc973b8a7e659fc56383c22 100644 (file)
@@ -155,7 +155,7 @@ static inline unsigned vring_size(unsigned int num, unsigned long align)
 }
 
 /* The following is used with USED_EVENT_IDX and AVAIL_EVENT_IDX */
-/* Assuming a given event_idx value from the other size, if
+/* Assuming a given event_idx value from the other side, if
  * we have just incremented index from old to new_idx,
  * should we trigger an event? */
 static inline int vring_need_event(__u16 event_idx, __u16 new_idx, __u16 old)
diff --git a/include/uapi/linux/xilinx-v4l2-controls.h b/include/uapi/linux/xilinx-v4l2-controls.h
new file mode 100644 (file)
index 0000000..fb495b9
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Xilinx Controls Header
+ *
+ * Copyright (C) 2013-2015 Ideas on Board
+ * Copyright (C) 2013-2015 Xilinx, Inc.
+ *
+ * Contacts: Hyun Kwon <hyun.kwon@xilinx.com>
+ *           Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __UAPI_XILINX_V4L2_CONTROLS_H__
+#define __UAPI_XILINX_V4L2_CONTROLS_H__
+
+#include <linux/v4l2-controls.h>
+
+#define V4L2_CID_XILINX_OFFSET 0xc000
+#define V4L2_CID_XILINX_BASE   (V4L2_CID_USER_BASE + V4L2_CID_XILINX_OFFSET)
+
+/*
+ * Private Controls for Xilinx Video IPs
+ */
+
+/*
+ * Xilinx TPG Video IP
+ */
+
+#define V4L2_CID_XILINX_TPG                    (V4L2_CID_USER_BASE + 0xc000)
+
+/* Draw cross hairs */
+#define V4L2_CID_XILINX_TPG_CROSS_HAIRS                (V4L2_CID_XILINX_TPG + 1)
+/* Enable a moving box */
+#define V4L2_CID_XILINX_TPG_MOVING_BOX         (V4L2_CID_XILINX_TPG + 2)
+/* Mask out a color component */
+#define V4L2_CID_XILINX_TPG_COLOR_MASK         (V4L2_CID_XILINX_TPG + 3)
+/* Enable a stuck pixel feature */
+#define V4L2_CID_XILINX_TPG_STUCK_PIXEL                (V4L2_CID_XILINX_TPG + 4)
+/* Enable a noisy output */
+#define V4L2_CID_XILINX_TPG_NOISE              (V4L2_CID_XILINX_TPG + 5)
+/* Enable the motion feature */
+#define V4L2_CID_XILINX_TPG_MOTION             (V4L2_CID_XILINX_TPG + 6)
+/* Configure the motion speed of moving patterns */
+#define V4L2_CID_XILINX_TPG_MOTION_SPEED       (V4L2_CID_XILINX_TPG + 7)
+/* The row of horizontal cross hair location */
+#define V4L2_CID_XILINX_TPG_CROSS_HAIR_ROW     (V4L2_CID_XILINX_TPG + 8)
+/* The colum of vertical cross hair location */
+#define V4L2_CID_XILINX_TPG_CROSS_HAIR_COLUMN  (V4L2_CID_XILINX_TPG + 9)
+/* Set starting point of sine wave for horizontal component */
+#define V4L2_CID_XILINX_TPG_ZPLATE_HOR_START   (V4L2_CID_XILINX_TPG + 10)
+/* Set speed of the horizontal component */
+#define V4L2_CID_XILINX_TPG_ZPLATE_HOR_SPEED   (V4L2_CID_XILINX_TPG + 11)
+/* Set starting point of sine wave for vertical component */
+#define V4L2_CID_XILINX_TPG_ZPLATE_VER_START   (V4L2_CID_XILINX_TPG + 12)
+/* Set speed of the vertical component */
+#define V4L2_CID_XILINX_TPG_ZPLATE_VER_SPEED   (V4L2_CID_XILINX_TPG + 13)
+/* Moving box size */
+#define V4L2_CID_XILINX_TPG_BOX_SIZE           (V4L2_CID_XILINX_TPG + 14)
+/* Moving box color */
+#define V4L2_CID_XILINX_TPG_BOX_COLOR          (V4L2_CID_XILINX_TPG + 15)
+/* Upper limit count of generated stuck pixels */
+#define V4L2_CID_XILINX_TPG_STUCK_PIXEL_THRESH (V4L2_CID_XILINX_TPG + 16)
+/* Noise level */
+#define V4L2_CID_XILINX_TPG_NOISE_GAIN         (V4L2_CID_XILINX_TPG + 17)
+
+#endif /* __UAPI_XILINX_V4L2_CONTROLS_H__ */
index de69170a30ce525378632523417c881985f6143a..6e4bb4270ca2ea1bb9eab5e49ae7049b6061e12b 100644 (file)
@@ -37,6 +37,7 @@ enum {
        RDMA_NL_IWPM_ADD_MAPPING,
        RDMA_NL_IWPM_QUERY_MAPPING,
        RDMA_NL_IWPM_REMOVE_MAPPING,
+       RDMA_NL_IWPM_REMOTE_INFO,
        RDMA_NL_IWPM_HANDLE_ERR,
        RDMA_NL_IWPM_MAPINFO,
        RDMA_NL_IWPM_MAPINFO_NUM,
index 46145a5277fe0277808ad54e45ab7e1a3d7b9985..a45be6bdcf5bb88b2871a764e070ed9737818088 100644 (file)
@@ -864,7 +864,7 @@ struct snd_ctl_elem_id {
        snd_ctl_elem_iface_t iface;     /* interface identifier */
        unsigned int device;            /* device/client number */
        unsigned int subdevice;         /* subdevice (substream) number */
-       unsigned char name[44];         /* ASCII name of item */
+       unsigned char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];              /* ASCII name of item */
        unsigned int index;             /* index of item */
 };
 
index 143ca5ffab7ac2c1e3ca5a653fef760f31879b47..4478f4b4aae2ff06473f2aff0e0100684f11c2bf 100644 (file)
@@ -191,6 +191,7 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
                      struct gnttab_unmap_grant_ref *kunmap_ops,
                      struct page **pages, unsigned int count);
 void gnttab_unmap_refs_async(struct gntab_unmap_queue_data* item);
+int gnttab_unmap_refs_sync(struct gntab_unmap_queue_data *item);
 
 
 /* Perform a batch of grant map/copy operations. Retry every batch slot
index c643e6a94c9a31fd241902b924f00dcfb1e4fb34..0ce4f32017ea91e6af37bc860c5633f473da17b3 100644 (file)
@@ -13,6 +13,7 @@ void xen_arch_post_suspend(int suspend_cancelled);
 
 void xen_timer_resume(void);
 void xen_arch_resume(void);
+void xen_arch_suspend(void);
 
 void xen_resume_notifier_register(struct notifier_block *nb);
 void xen_resume_notifier_unregister(struct notifier_block *nb);
index 7635a1cf99f3da986b0cfa57774c7ad38ef28fe3..3aaea7ffd077c874cb1b420013458020057f45a6 100644 (file)
@@ -466,7 +466,7 @@ out_unlock:
 
 static int mqueue_unlink(struct inode *dir, struct dentry *dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
 
        dir->i_ctime = dir->i_mtime = dir->i_atime = CURRENT_TIME;
        dir->i_size -= DIRENT_SIZE;
@@ -770,7 +770,7 @@ static struct file *do_open(struct path *path, int oflag)
        if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY))
                return ERR_PTR(-EINVAL);
        acc = oflag2acc[oflag & O_ACCMODE];
-       if (inode_permission(path->dentry->d_inode, acc))
+       if (inode_permission(d_inode(path->dentry), acc))
                return ERR_PTR(-EACCES);
        return dentry_open(path, oflag, current_cred());
 }
@@ -802,7 +802,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,
 
        ro = mnt_want_write(mnt);       /* we'll drop it in any case */
        error = 0;
-       mutex_lock(&root->d_inode->i_mutex);
+       mutex_lock(&d_inode(root)->i_mutex);
        path.dentry = lookup_one_len(name->name, root, strlen(name->name));
        if (IS_ERR(path.dentry)) {
                error = PTR_ERR(path.dentry);
@@ -811,7 +811,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,
        path.mnt = mntget(mnt);
 
        if (oflag & O_CREAT) {
-               if (path.dentry->d_inode) {     /* entry already exists */
+               if (d_really_is_positive(path.dentry)) {        /* entry already exists */
                        audit_inode(name, path.dentry, 0);
                        if (oflag & O_EXCL) {
                                error = -EEXIST;
@@ -824,12 +824,12 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,
                                goto out;
                        }
                        audit_inode_parent_hidden(name, root);
-                       filp = do_create(ipc_ns, root->d_inode,
+                       filp = do_create(ipc_ns, d_inode(root),
                                                &path, oflag, mode,
                                                u_attr ? &attr : NULL);
                }
        } else {
-               if (!path.dentry->d_inode) {
+               if (d_really_is_negative(path.dentry)) {
                        error = -ENOENT;
                        goto out;
                }
@@ -848,7 +848,7 @@ out_putfd:
                put_unused_fd(fd);
                fd = error;
        }
-       mutex_unlock(&root->d_inode->i_mutex);
+       mutex_unlock(&d_inode(root)->i_mutex);
        if (!ro)
                mnt_drop_write(mnt);
 out_putname:
@@ -873,7 +873,7 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name)
        err = mnt_want_write(mnt);
        if (err)
                goto out_name;
-       mutex_lock_nested(&mnt->mnt_root->d_inode->i_mutex, I_MUTEX_PARENT);
+       mutex_lock_nested(&d_inode(mnt->mnt_root)->i_mutex, I_MUTEX_PARENT);
        dentry = lookup_one_len(name->name, mnt->mnt_root,
                                strlen(name->name));
        if (IS_ERR(dentry)) {
@@ -881,17 +881,17 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name)
                goto out_unlock;
        }
 
-       inode = dentry->d_inode;
+       inode = d_inode(dentry);
        if (!inode) {
                err = -ENOENT;
        } else {
                ihold(inode);
-               err = vfs_unlink(dentry->d_parent->d_inode, dentry, NULL);
+               err = vfs_unlink(d_inode(dentry->d_parent), dentry, NULL);
        }
        dput(dentry);
 
 out_unlock:
-       mutex_unlock(&mnt->mnt_root->d_inode->i_mutex);
+       mutex_unlock(&d_inode(mnt->mnt_root)->i_mutex);
        if (inode)
                iput(inode);
        mnt_drop_write(mnt);
index d280a74af2ef47d63fbaf3215cb68832b68c7c76..6d767071c3673dce09984933c3a444d78880bd10 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -1132,7 +1132,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr,
        path = shp->shm_file->f_path;
        path_get(&path);
        shp->shm_nattch++;
-       size = i_size_read(path.dentry->d_inode);
+       size = i_size_read(d_inode(path.dentry));
        ipc_unlock_object(&shp->shm_perm);
        rcu_read_unlock();
 
index 0f8f8b0bc1bf660b9c8c4d7a51f2d698e1534a17..60c302cfb4d3cbb976f0b2d69f28a96899b1d4ce 100644 (file)
@@ -197,9 +197,9 @@ x509.genkey:
        @echo >>x509.genkey "x509_extensions = myexts"
        @echo >>x509.genkey
        @echo >>x509.genkey "[ req_distinguished_name ]"
-       @echo >>x509.genkey "O = Magrathea"
-       @echo >>x509.genkey "CN = Glacier signing key"
-       @echo >>x509.genkey "emailAddress = slartibartfast@magrathea.h2g2"
+       @echo >>x509.genkey "#O = Unspecified company"
+       @echo >>x509.genkey "CN = Build time autogenerated kernel key"
+       @echo >>x509.genkey "#emailAddress = unspecified.user@unspecified.company"
        @echo >>x509.genkey
        @echo >>x509.genkey "[ myexts ]"
        @echo >>x509.genkey "basicConstraints=critical,CA:FALSE"
index 72ab759a0b43a6400750cefa71650ed64e7a8222..1c13e4267de6e78c0ceb566c6517b837ce2b947e 100644 (file)
@@ -43,6 +43,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/file.h>
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/atomic.h>
@@ -107,6 +108,7 @@ static u32  audit_rate_limit;
  * When set to zero, this means unlimited. */
 static u32     audit_backlog_limit = 64;
 #define AUDIT_BACKLOG_WAIT_TIME (60 * HZ)
+static u32     audit_backlog_wait_time_master = AUDIT_BACKLOG_WAIT_TIME;
 static u32     audit_backlog_wait_time = AUDIT_BACKLOG_WAIT_TIME;
 static u32     audit_backlog_wait_overflow = 0;
 
@@ -338,13 +340,13 @@ static int audit_set_backlog_limit(u32 limit)
 static int audit_set_backlog_wait_time(u32 timeout)
 {
        return audit_do_config_change("audit_backlog_wait_time",
-                                     &audit_backlog_wait_time, timeout);
+                                     &audit_backlog_wait_time_master, timeout);
 }
 
 static int audit_set_enabled(u32 state)
 {
        int rc;
-       if (state < AUDIT_OFF || state > AUDIT_LOCKED)
+       if (state > AUDIT_LOCKED)
                return -EINVAL;
 
        rc =  audit_do_config_change("audit_enabled", &audit_enabled, state);
@@ -663,7 +665,7 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
        case AUDIT_MAKE_EQUIV:
                /* Only support auditd and auditctl in initial pid namespace
                 * for now. */
-               if ((task_active_pid_ns(current) != &init_pid_ns))
+               if (task_active_pid_ns(current) != &init_pid_ns)
                        return -EPERM;
 
                if (!netlink_capable(skb, CAP_AUDIT_CONTROL))
@@ -834,7 +836,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                s.lost                  = atomic_read(&audit_lost);
                s.backlog               = skb_queue_len(&audit_skb_queue);
                s.feature_bitmap        = AUDIT_FEATURE_BITMAP_ALL;
-               s.backlog_wait_time     = audit_backlog_wait_time;
+               s.backlog_wait_time     = audit_backlog_wait_time_master;
                audit_send_reply(skb, seq, AUDIT_GET, 0, 0, &s, sizeof(s));
                break;
        }
@@ -877,8 +879,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                if (s.mask & AUDIT_STATUS_BACKLOG_WAIT_TIME) {
                        if (sizeof(s) > (size_t)nlh->nlmsg_len)
                                return -EINVAL;
-                       if (s.backlog_wait_time < 0 ||
-                           s.backlog_wait_time > 10*AUDIT_BACKLOG_WAIT_TIME)
+                       if (s.backlog_wait_time > 10*AUDIT_BACKLOG_WAIT_TIME)
                                return -EINVAL;
                        err = audit_set_backlog_wait_time(s.backlog_wait_time);
                        if (err < 0)
@@ -1385,7 +1386,8 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
                return NULL;
        }
 
-       audit_backlog_wait_time = AUDIT_BACKLOG_WAIT_TIME;
+       if (!reserve)
+               audit_backlog_wait_time = audit_backlog_wait_time_master;
 
        ab = audit_buffer_alloc(ctx, gfp_mask, type);
        if (!ab) {
@@ -1759,7 +1761,7 @@ void audit_log_name(struct audit_context *context, struct audit_names *n,
        } else
                audit_log_format(ab, " name=(null)");
 
-       if (n->ino != (unsigned long)-1) {
+       if (n->ino != (unsigned long)-1)
                audit_log_format(ab, " inode=%lu"
                                 " dev=%02x:%02x mode=%#ho"
                                 " ouid=%u ogid=%u rdev=%02x:%02x",
@@ -1771,7 +1773,6 @@ void audit_log_name(struct audit_context *context, struct audit_names *n,
                                 from_kgid(&init_user_ns, n->gid),
                                 MAJOR(n->rdev),
                                 MINOR(n->rdev));
-       }
        if (n->osid != 0) {
                char *ctx = NULL;
                u32 len;
@@ -1838,11 +1839,29 @@ error_path:
 }
 EXPORT_SYMBOL(audit_log_task_context);
 
+void audit_log_d_path_exe(struct audit_buffer *ab,
+                         struct mm_struct *mm)
+{
+       struct file *exe_file;
+
+       if (!mm)
+               goto out_null;
+
+       exe_file = get_mm_exe_file(mm);
+       if (!exe_file)
+               goto out_null;
+
+       audit_log_d_path(ab, " exe=", &exe_file->f_path);
+       fput(exe_file);
+       return;
+out_null:
+       audit_log_format(ab, " exe=(null)");
+}
+
 void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk)
 {
        const struct cred *cred;
        char comm[sizeof(tsk->comm)];
-       struct mm_struct *mm = tsk->mm;
        char *tty;
 
        if (!ab)
@@ -1878,13 +1897,7 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk)
        audit_log_format(ab, " comm=");
        audit_log_untrustedstring(ab, get_task_comm(comm, tsk));
 
-       if (mm) {
-               down_read(&mm->mmap_sem);
-               if (mm->exe_file)
-                       audit_log_d_path(ab, " exe=", &mm->exe_file->f_path);
-               up_read(&mm->mmap_sem);
-       } else
-               audit_log_format(ab, " exe=(null)");
+       audit_log_d_path_exe(ab, tsk->mm);
        audit_log_task_context(ab);
 }
 EXPORT_SYMBOL(audit_log_task_info);
@@ -1915,7 +1928,7 @@ void audit_log_link_denied(const char *operation, struct path *link)
 
        /* Generate AUDIT_PATH record with object. */
        name->type = AUDIT_TYPE_NORMAL;
-       audit_copy_inode(name, link->dentry, link->dentry->d_inode);
+       audit_copy_inode(name, link->dentry, d_backing_inode(link->dentry));
        audit_log_name(current->audit_context, name, link, 0, NULL);
 out:
        kfree(name);
index 1caa0d345d90613f955578dacaa7082d9fac5163..d641f9bb3ed0a3970b0b717d99ccdc82bb4acd6c 100644 (file)
@@ -257,6 +257,9 @@ extern struct list_head audit_filter_list[];
 
 extern struct audit_entry *audit_dupe_rule(struct audit_krule *old);
 
+extern void audit_log_d_path_exe(struct audit_buffer *ab,
+                                struct mm_struct *mm);
+
 /* audit watch functions */
 #ifdef CONFIG_AUDIT_WATCH
 extern void audit_put_watch(struct audit_watch *watch);
index 2e0c97427b339c2f794568b8bb0ac383abf90421..b0f9877273fc39746fa063849f1bac51487d8606 100644 (file)
@@ -37,6 +37,7 @@ struct audit_chunk {
 
 static LIST_HEAD(tree_list);
 static LIST_HEAD(prune_list);
+static struct task_struct *prune_thread;
 
 /*
  * One struct chunk is attached to each inode of interest.
@@ -576,7 +577,7 @@ int audit_remove_tree_rule(struct audit_krule *rule)
 
 static int compare_root(struct vfsmount *mnt, void *arg)
 {
-       return mnt->mnt_root->d_inode == arg;
+       return d_backing_inode(mnt->mnt_root) == arg;
 }
 
 void audit_trim_trees(void)
@@ -648,7 +649,58 @@ void audit_put_tree(struct audit_tree *tree)
 
 static int tag_mount(struct vfsmount *mnt, void *arg)
 {
-       return tag_chunk(mnt->mnt_root->d_inode, arg);
+       return tag_chunk(d_backing_inode(mnt->mnt_root), arg);
+}
+
+/*
+ * That gets run when evict_chunk() ends up needing to kill audit_tree.
+ * Runs from a separate thread.
+ */
+static int prune_tree_thread(void *unused)
+{
+       for (;;) {
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (list_empty(&prune_list))
+                       schedule();
+               __set_current_state(TASK_RUNNING);
+
+               mutex_lock(&audit_cmd_mutex);
+               mutex_lock(&audit_filter_mutex);
+
+               while (!list_empty(&prune_list)) {
+                       struct audit_tree *victim;
+
+                       victim = list_entry(prune_list.next,
+                                       struct audit_tree, list);
+                       list_del_init(&victim->list);
+
+                       mutex_unlock(&audit_filter_mutex);
+
+                       prune_one(victim);
+
+                       mutex_lock(&audit_filter_mutex);
+               }
+
+               mutex_unlock(&audit_filter_mutex);
+               mutex_unlock(&audit_cmd_mutex);
+       }
+       return 0;
+}
+
+static int audit_launch_prune(void)
+{
+       if (prune_thread)
+               return 0;
+       prune_thread = kthread_create(prune_tree_thread, NULL,
+                               "audit_prune_tree");
+       if (IS_ERR(prune_thread)) {
+               pr_err("cannot start thread audit_prune_tree");
+               prune_thread = NULL;
+               return -ENOMEM;
+       } else {
+               wake_up_process(prune_thread);
+               return 0;
+       }
 }
 
 /* called with audit_filter_mutex */
@@ -674,6 +726,12 @@ int audit_add_tree_rule(struct audit_krule *rule)
        /* do not set rule->tree yet */
        mutex_unlock(&audit_filter_mutex);
 
+       if (unlikely(!prune_thread)) {
+               err = audit_launch_prune();
+               if (err)
+                       goto Err;
+       }
+
        err = kern_path(tree->pathname, 0, &path);
        if (err)
                goto Err;
@@ -811,36 +869,10 @@ int audit_tag_tree(char *old, char *new)
        return failed;
 }
 
-/*
- * That gets run when evict_chunk() ends up needing to kill audit_tree.
- * Runs from a separate thread.
- */
-static int prune_tree_thread(void *unused)
-{
-       mutex_lock(&audit_cmd_mutex);
-       mutex_lock(&audit_filter_mutex);
-
-       while (!list_empty(&prune_list)) {
-               struct audit_tree *victim;
-
-               victim = list_entry(prune_list.next, struct audit_tree, list);
-               list_del_init(&victim->list);
-
-               mutex_unlock(&audit_filter_mutex);
-
-               prune_one(victim);
-
-               mutex_lock(&audit_filter_mutex);
-       }
-
-       mutex_unlock(&audit_filter_mutex);
-       mutex_unlock(&audit_cmd_mutex);
-       return 0;
-}
 
 static void audit_schedule_prune(void)
 {
-       kthread_run(prune_tree_thread, NULL, "audit_prune_tree");
+       wake_up_process(prune_thread);
 }
 
 /*
@@ -907,9 +939,9 @@ static void evict_chunk(struct audit_chunk *chunk)
        for (n = 0; n < chunk->count; n++)
                list_del_init(&chunk->owners[n].list);
        spin_unlock(&hash_lock);
+       mutex_unlock(&audit_filter_mutex);
        if (need_prune)
                audit_schedule_prune();
-       mutex_unlock(&audit_filter_mutex);
 }
 
 static int audit_tree_handle_event(struct fsnotify_group *group,
index ad9c1682f616a27b25414bb19002d3247540f6c4..6e30024d9aac19fa7aae230d6f521f36a376ee8c 100644 (file)
@@ -146,7 +146,7 @@ int audit_watch_compare(struct audit_watch *watch, unsigned long ino, dev_t dev)
 /* Initialize a parent watch entry. */
 static struct audit_parent *audit_init_parent(struct path *path)
 {
-       struct inode *inode = path->dentry->d_inode;
+       struct inode *inode = d_backing_inode(path->dentry);
        struct audit_parent *parent;
        int ret;
 
@@ -361,11 +361,11 @@ static int audit_get_nd(struct audit_watch *watch, struct path *parent)
        struct dentry *d = kern_path_locked(watch->path, parent);
        if (IS_ERR(d))
                return PTR_ERR(d);
-       mutex_unlock(&parent->dentry->d_inode->i_mutex);
-       if (d->d_inode) {
+       mutex_unlock(&d_backing_inode(parent->dentry)->i_mutex);
+       if (d_is_positive(d)) {
                /* update watch filter fields */
-               watch->dev = d->d_inode->i_sb->s_dev;
-               watch->ino = d->d_inode->i_ino;
+               watch->dev = d_backing_inode(d)->i_sb->s_dev;
+               watch->ino = d_backing_inode(d)->i_ino;
        }
        dput(d);
        return 0;
@@ -426,7 +426,7 @@ int audit_add_watch(struct audit_krule *krule, struct list_head **list)
                return ret;
 
        /* either find an old parent or attach a new one */
-       parent = audit_find_parent(parent_path.dentry->d_inode);
+       parent = audit_find_parent(d_backing_inode(parent_path.dentry));
        if (!parent) {
                parent = audit_init_parent(&parent_path);
                if (IS_ERR(parent)) {
@@ -482,7 +482,7 @@ static int audit_watch_handle_event(struct fsnotify_group *group,
 
        switch (data_type) {
        case (FSNOTIFY_EVENT_PATH):
-               inode = ((struct path *)data)->dentry->d_inode;
+               inode = d_backing_inode(((struct path *)data)->dentry);
                break;
        case (FSNOTIFY_EVENT_INODE):
                inode = (struct inode *)data;
index dc4ae70a74133eabbd52e40e5271202ac28ca9a4..9fb9d1cb83ce2b19997be912aefdfd2c2a4fae3d 100644 (file)
@@ -1629,7 +1629,7 @@ retry:
        rcu_read_lock();
        seq = read_seqbegin(&rename_lock);
        for(;;) {
-               struct inode *inode = d->d_inode;
+               struct inode *inode = d_backing_inode(d);
                if (inode && unlikely(!hlist_empty(&inode->i_fsnotify_marks))) {
                        struct audit_chunk *chunk;
                        chunk = audit_tree_lookup(inode);
@@ -1754,7 +1754,7 @@ void __audit_inode(struct filename *name, const struct dentry *dentry,
                   unsigned int flags)
 {
        struct audit_context *context = current->audit_context;
-       const struct inode *inode = dentry->d_inode;
+       const struct inode *inode = d_backing_inode(dentry);
        struct audit_names *n;
        bool parent = flags & AUDIT_INODE_PARENT;
 
@@ -1853,7 +1853,7 @@ void __audit_inode_child(const struct inode *parent,
                         const unsigned char type)
 {
        struct audit_context *context = current->audit_context;
-       const struct inode *inode = dentry->d_inode;
+       const struct inode *inode = d_backing_inode(dentry);
        const char *dname = dentry->d_name.name;
        struct audit_names *n, *found_parent = NULL, *found_child = NULL;
 
@@ -2361,7 +2361,6 @@ static void audit_log_task(struct audit_buffer *ab)
        kuid_t auid, uid;
        kgid_t gid;
        unsigned int sessionid;
-       struct mm_struct *mm = current->mm;
        char comm[sizeof(current->comm)];
 
        auid = audit_get_loginuid(current);
@@ -2376,13 +2375,7 @@ static void audit_log_task(struct audit_buffer *ab)
        audit_log_task_context(ab);
        audit_log_format(ab, " pid=%d comm=", task_pid_nr(current));
        audit_log_untrustedstring(ab, get_task_comm(comm, current));
-       if (mm) {
-               down_read(&mm->mmap_sem);
-               if (mm->exe_file)
-                       audit_log_d_path(ab, " exe=", &mm->exe_file->f_path);
-               up_read(&mm->mmap_sem);
-       } else
-               audit_log_format(ab, " exe=(null)");
+       audit_log_d_path_exe(ab, current->mm);
 }
 
 /**
index 4139a0f8b558e4e7db4f79adbd353c97c7fda553..54f0e7fcd0e288b4506fab80091dcc39069ae422 100644 (file)
@@ -357,8 +357,8 @@ select_insn:
        ALU64_MOD_X:
                if (unlikely(SRC == 0))
                        return 0;
-               tmp = DST;
-               DST = do_div(tmp, SRC);
+               div64_u64_rem(DST, SRC, &tmp);
+               DST = tmp;
                CONT;
        ALU_MOD_X:
                if (unlikely(SRC == 0))
@@ -367,8 +367,8 @@ select_insn:
                DST = do_div(tmp, (u32) SRC);
                CONT;
        ALU64_MOD_K:
-               tmp = DST;
-               DST = do_div(tmp, IMM);
+               div64_u64_rem(DST, IMM, &tmp);
+               DST = tmp;
                CONT;
        ALU_MOD_K:
                tmp = (u32) DST;
@@ -377,7 +377,7 @@ select_insn:
        ALU64_DIV_X:
                if (unlikely(SRC == 0))
                        return 0;
-               do_div(DST, SRC);
+               DST = div64_u64(DST, SRC);
                CONT;
        ALU_DIV_X:
                if (unlikely(SRC == 0))
@@ -387,7 +387,7 @@ select_insn:
                DST = (u32) tmp;
                CONT;
        ALU64_DIV_K:
-               do_div(DST, IMM);
+               DST = div64_u64(DST, IMM);
                CONT;
        ALU_DIV_K:
                tmp = (u32) DST;
index 38c25b1f2fd5c7e4922f36cf884519c1bd485a85..7a36fdcca5bfb064a6709021782c98bd2a6de179 100644 (file)
@@ -707,7 +707,7 @@ static struct page *kimage_alloc_normal_control_pages(struct kimage *image,
        do {
                unsigned long pfn, epfn, addr, eaddr;
 
-               pages = kimage_alloc_pages(GFP_KERNEL, order);
+               pages = kimage_alloc_pages(KEXEC_CONTROL_MEMORY_GFP, order);
                if (!pages)
                        break;
                pfn   = page_to_pfn(pages);
index 650b038ae52035962cb4fa37b14776225e4ce701..42a1d2afb2173cd3c7c740098dd72d7a52bdb3f8 100644 (file)
@@ -387,9 +387,9 @@ static bool check_symbol(const struct symsearch *syms,
                pr_warn("Symbol %s is marked as UNUSED, however this module is "
                        "using it.\n", fsa->name);
                pr_warn("This symbol will go away in the future.\n");
-               pr_warn("Please evalute if this is the right api to use and if "
-                       "it really is, submit a report the linux kernel "
-                       "mailinglist together with submitting your code for "
+               pr_warn("Please evaluate if this is the right api to use and "
+                       "if it really is, submit a report to the linux kernel "
+                       "mailing list together with submitting your code for "
                        "inclusion.\n");
        }
 #endif
@@ -2511,7 +2511,8 @@ static int copy_module_from_user(const void __user *umod, unsigned long len,
                return err;
 
        /* Suck in entire file: we'll want most of it. */
-       info->hdr = vmalloc(info->len);
+       info->hdr = __vmalloc(info->len,
+                       GFP_KERNEL | __GFP_HIGHMEM | __GFP_NOWARN, PAGE_KERNEL);
        if (!info->hdr)
                return -ENOMEM;
 
index 728e05b167de984afe2e815f63207952051c3915..a22d6a759b1a9391d5713364097bcfca35f197e7 100644 (file)
@@ -173,9 +173,9 @@ static char *next_arg(char *args, char **param, char **val)
                        if (args[i-1] == '"')
                                args[i-1] = '\0';
                }
-               if (quoted && args[i-1] == '"')
-                       args[i-1] = '\0';
        }
+       if (quoted && args[i-1] == '"')
+               args[i-1] = '\0';
 
        if (args[i]) {
                args[i] = '\0';
index 879edfc5ee52d2985d4fb925ec820ba6b113d6d0..c099b082cd0272dc486e57ded2b9fc8413e40da3 100644 (file)
@@ -2017,24 +2017,6 @@ int add_preferred_console(char *name, int idx, char *options)
        return __add_preferred_console(name, idx, options, NULL);
 }
 
-int update_console_cmdline(char *name, int idx, char *name_new, int idx_new, char *options)
-{
-       struct console_cmdline *c;
-       int i;
-
-       for (i = 0, c = console_cmdline;
-            i < MAX_CMDLINECONSOLES && c->name[0];
-            i++, c++)
-               if (strcmp(c->name, name) == 0 && c->index == idx) {
-                       strlcpy(c->name, name_new, sizeof(c->name));
-                       c->options = options;
-                       c->index = idx_new;
-                       return i;
-               }
-       /* not found */
-       return -1;
-}
-
 bool console_suspend_enabled = true;
 EXPORT_SYMBOL(console_suspend_enabled);
 
@@ -2436,9 +2418,6 @@ void register_console(struct console *newcon)
        if (preferred_console < 0 || bcon || !console_drivers)
                preferred_console = selected_console;
 
-       if (newcon->early_setup)
-               newcon->early_setup();
-
        /*
         *      See if we want to use this console driver. If we
         *      didn't select a console we take the first one
@@ -2464,23 +2443,27 @@ void register_console(struct console *newcon)
        for (i = 0, c = console_cmdline;
             i < MAX_CMDLINECONSOLES && c->name[0];
             i++, c++) {
-               BUILD_BUG_ON(sizeof(c->name) != sizeof(newcon->name));
-               if (strcmp(c->name, newcon->name) != 0)
-                       continue;
-               if (newcon->index >= 0 &&
-                   newcon->index != c->index)
-                       continue;
-               if (newcon->index < 0)
-                       newcon->index = c->index;
+               if (!newcon->match ||
+                   newcon->match(newcon, c->name, c->index, c->options) != 0) {
+                       /* default matching */
+                       BUILD_BUG_ON(sizeof(c->name) != sizeof(newcon->name));
+                       if (strcmp(c->name, newcon->name) != 0)
+                               continue;
+                       if (newcon->index >= 0 &&
+                           newcon->index != c->index)
+                               continue;
+                       if (newcon->index < 0)
+                               newcon->index = c->index;
 
-               if (_braille_register_console(newcon, c))
-                       return;
+                       if (_braille_register_console(newcon, c))
+                               return;
+
+                       if (newcon->setup &&
+                           newcon->setup(newcon, c->options) != 0)
+                               break;
+               }
 
-               if (newcon->setup &&
-                   newcon->setup(newcon, console_cmdline[i].options) != 0)
-                       break;
                newcon->flags |= CON_ENABLED;
-               newcon->index = c->index;
                if (i == selected_console) {
                        newcon->flags |= CON_CONSDEV;
                        preferred_console = selected_console;
index 233165da782f51deb88c6373116d9d28a4fec38b..8cf7304b2867f5a113807afb0bd5dc0a3bd3cfc0 100644 (file)
@@ -162,11 +162,14 @@ static void invoke_rcu_callbacks(struct rcu_state *rsp, struct rcu_data *rdp);
 static int kthread_prio = CONFIG_RCU_KTHREAD_PRIO;
 module_param(kthread_prio, int, 0644);
 
-/* Delay in jiffies for grace-period initialization delays. */
-static int gp_init_delay = IS_ENABLED(CONFIG_RCU_TORTURE_TEST_SLOW_INIT)
-                               ? CONFIG_RCU_TORTURE_TEST_SLOW_INIT_DELAY
-                               : 0;
+/* Delay in jiffies for grace-period initialization delays, debug only. */
+#ifdef CONFIG_RCU_TORTURE_TEST_SLOW_INIT
+static int gp_init_delay = CONFIG_RCU_TORTURE_TEST_SLOW_INIT_DELAY;
 module_param(gp_init_delay, int, 0644);
+#else /* #ifdef CONFIG_RCU_TORTURE_TEST_SLOW_INIT */
+static const int gp_init_delay;
+#endif /* #else #ifdef CONFIG_RCU_TORTURE_TEST_SLOW_INIT */
+#define PER_RCU_NODE_PERIOD 10 /* Number of grace periods between delays. */
 
 /*
  * Track the rcutorture test sequence number and the update version
@@ -1843,9 +1846,8 @@ static int rcu_gp_init(struct rcu_state *rsp)
                raw_spin_unlock_irq(&rnp->lock);
                cond_resched_rcu_qs();
                ACCESS_ONCE(rsp->gp_activity) = jiffies;
-               if (IS_ENABLED(CONFIG_RCU_TORTURE_TEST_SLOW_INIT) &&
-                   gp_init_delay > 0 &&
-                   !(rsp->gpnum % (rcu_num_nodes * 10)))
+               if (gp_init_delay > 0 &&
+                   !(rsp->gpnum % (rcu_num_nodes * PER_RCU_NODE_PERIOD)))
                        schedule_timeout_uninterruptible(gp_init_delay);
        }
 
index 5a56d3c8dc03a799e5f53169c85c7f33f05727eb..e9dbaeb8fd65c7d0af385043cddf2b7d7ef7fa8c 100644 (file)
@@ -407,7 +407,7 @@ static inline void relay_set_buf_dentry(struct rchan_buf *buf,
                                        struct dentry *dentry)
 {
        buf->dentry = dentry;
-       buf->dentry->d_inode->i_size = buf->early_bytes;
+       d_inode(buf->dentry)->i_size = buf->early_bytes;
 }
 
 static struct dentry *relay_create_buf_file(struct rchan *chan,
@@ -733,7 +733,7 @@ size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length)
                buf->padding[old_subbuf] = buf->prev_padding;
                buf->subbufs_produced++;
                if (buf->dentry)
-                       buf->dentry->d_inode->i_size +=
+                       d_inode(buf->dentry)->i_size +=
                                buf->chan->subbuf_size -
                                buf->padding[old_subbuf];
                else
index f9123a82cbb614eb26cab55c0f58540a5a3eb24b..fe22f7510bceab3fad0f008379a91f34db074d37 100644 (file)
@@ -1016,13 +1016,6 @@ void check_preempt_curr(struct rq *rq, struct task_struct *p, int flags)
                rq_clock_skip_update(rq, true);
 }
 
-static ATOMIC_NOTIFIER_HEAD(task_migration_notifier);
-
-void register_task_migration_notifier(struct notifier_block *n)
-{
-       atomic_notifier_chain_register(&task_migration_notifier, n);
-}
-
 #ifdef CONFIG_SMP
 void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
 {
@@ -1053,18 +1046,10 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
        trace_sched_migrate_task(p, new_cpu);
 
        if (task_cpu(p) != new_cpu) {
-               struct task_migration_notifier tmn;
-
                if (p->sched_class->migrate_task_rq)
                        p->sched_class->migrate_task_rq(p, new_cpu);
                p->se.nr_migrations++;
                perf_sw_event_sched(PERF_COUNT_SW_CPU_MIGRATIONS, 1, 0);
-
-               tmn.task = p;
-               tmn.from_cpu = task_cpu(p);
-               tmn.to_cpu = new_cpu;
-
-               atomic_notifier_call_chain(&task_migration_notifier, 0, &tmn);
        }
 
        __set_task_cpu(p, new_cpu);
index deef1caa94c6779ea13e48690ffc2d9de2e7dddc..fefcb1fa5160139a41e9dd1fee74b20ef39105e0 100644 (file)
@@ -81,7 +81,6 @@ static void cpuidle_idle_call(void)
        struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
        struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
        int next_state, entered_state;
-       unsigned int broadcast;
        bool reflect;
 
        /*
@@ -150,17 +149,6 @@ static void cpuidle_idle_call(void)
                goto exit_idle;
        }
 
-       broadcast = drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP;
-
-       /*
-        * Tell the time framework to switch to a broadcast timer
-        * because our local timer will be shutdown. If a local timer
-        * is used from another cpu as a broadcast timer, this call may
-        * fail if it is not available
-        */
-       if (broadcast && tick_broadcast_enter())
-               goto use_default;
-
        /* Take note of the planned idle state. */
        idle_set_state(this_rq(), &drv->states[next_state]);
 
@@ -174,8 +162,8 @@ static void cpuidle_idle_call(void)
        /* The cpu is no longer idle or about to enter idle. */
        idle_set_state(this_rq(), NULL);
 
-       if (broadcast)
-               tick_broadcast_exit();
+       if (entered_state == -EBUSY)
+               goto use_default;
 
        /*
         * Give the governor an opportunity to reflect on the outcome
index 25d942d1da27095e6366d720a0f8de58009cb5f3..11dc22a6983b55da3c2c356cb375fa27dbad0ed8 100644 (file)
@@ -440,7 +440,7 @@ int clockevents_unbind_device(struct clock_event_device *ced, int cpu)
        mutex_unlock(&clockevents_mutex);
        return ret;
 }
-EXPORT_SYMBOL_GPL(clockevents_unbind);
+EXPORT_SYMBOL_GPL(clockevents_unbind_device);
 
 /* Sanity check of state transition callbacks */
 static int clockevents_sanity_check(struct clock_event_device *dev)
index 91eecaaa43e0aeaceea2c513a4decc02cf3e981d..05330494a0dffde9824ab8659358e55a789ba286 100644 (file)
@@ -6079,7 +6079,7 @@ trace_create_cpu_file(const char *name, umode_t mode, struct dentry *parent,
        struct dentry *ret = trace_create_file(name, mode, parent, data, fops);
 
        if (ret) /* See tracing_get_cpu() */
-               ret->d_inode->i_cdev = (void *)(cpu + 1);
+               d_inode(ret)->i_cdev = (void *)(cpu + 1);
        return ret;
 }
 
index 7da1dfeb322e696c3352300982bfc0ad96fdd98f..c4de47fc5cca0799a58a72cdb50321e95fd7b4ff 100644 (file)
@@ -494,8 +494,8 @@ static void remove_event_file_dir(struct ftrace_event_file *file)
        if (dir) {
                spin_lock(&dir->d_lock);        /* probably unneeded */
                list_for_each_entry(child, &dir->d_subdirs, d_child) {
-                       if (child->d_inode)     /* probably unneeded */
-                               child->d_inode->i_private = NULL;
+                       if (d_really_is_positive(child))        /* probably unneeded */
+                               d_inode(child)->i_private = NULL;
                }
                spin_unlock(&dir->d_lock);
 
@@ -565,6 +565,7 @@ static int __ftrace_set_clr_event(struct trace_array *tr, const char *match,
 static int ftrace_set_clr_event(struct trace_array *tr, char *buf, int set)
 {
        char *event = NULL, *sub = NULL, *match;
+       int ret;
 
        /*
         * The buf format can be <subsystem>:<event-name>
@@ -590,7 +591,13 @@ static int ftrace_set_clr_event(struct trace_array *tr, char *buf, int set)
                        event = NULL;
        }
 
-       return __ftrace_set_clr_event(tr, match, sub, event, set);
+       ret = __ftrace_set_clr_event(tr, match, sub, event, set);
+
+       /* Put back the colon to allow this to be called again */
+       if (buf)
+               *(buf - 1) = ':';
+
+       return ret;
 }
 
 /**
@@ -1753,6 +1760,8 @@ static void update_event_printk(struct ftrace_event_call *call,
                                ptr++;
                                /* Check for alpha chars like ULL */
                        } while (isalnum(*ptr));
+                       if (!*ptr)
+                               break;
                        /*
                         * A number must have some kind of delimiter after
                         * it, and we can ignore that too.
@@ -1779,12 +1788,16 @@ static void update_event_printk(struct ftrace_event_call *call,
                        do {
                                ptr++;
                        } while (isalnum(*ptr) || *ptr == '_');
+                       if (!*ptr)
+                               break;
                        /*
                         * If what comes after this variable is a '.' or
                         * '->' then we can continue to ignore that string.
                         */
                        if (*ptr == '.' || (ptr[0] == '-' && ptr[1] == '>')) {
                                ptr += *ptr == '.' ? 1 : 2;
+                               if (!*ptr)
+                                       break;
                                goto skip_more;
                        }
                        /*
index 9cfea4c6d314c6153d4986a55a89503671e2b1a4..a51e79688455edb5afb76f09ff2d70c0eae15ca5 100644 (file)
@@ -1308,15 +1308,19 @@ void graph_trace_open(struct trace_iterator *iter)
 {
        /* pid and depth on the last trace processed */
        struct fgraph_data *data;
+       gfp_t gfpflags;
        int cpu;
 
        iter->private = NULL;
 
-       data = kzalloc(sizeof(*data), GFP_KERNEL);
+       /* We can be called in atomic context via ftrace_dump() */
+       gfpflags = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
+
+       data = kzalloc(sizeof(*data), gfpflags);
        if (!data)
                goto out_err;
 
-       data->cpu_data = alloc_percpu(struct fgraph_cpu_data);
+       data->cpu_data = alloc_percpu_gfp(struct fgraph_cpu_data, gfpflags);
        if (!data->cpu_data)
                goto out_err_free;
 
index d60fe62ec4fa4c99dfc9cf381b9a26d8093f6a16..6dd022c7b5bcbfc68f3f92ce322c9b83cf4add4e 100644 (file)
@@ -443,7 +443,7 @@ static int create_trace_uprobe(int argc, char **argv)
        if (ret)
                goto fail_address_parse;
 
-       inode = igrab(path.dentry->d_inode);
+       inode = igrab(d_inode(path.dentry));
        path_put(&path);
 
        if (!inode || !S_ISREG(inode->i_mode)) {
index 17670573dda82d92a515d4519211e8bbe65b5f63..ba2b0c87e65b196c7c1f016798e0b59ea8dba97c 100644 (file)
@@ -1281,6 +1281,7 @@ config RCU_TORTURE_TEST_SLOW_INIT_DELAY
        int "How much to slow down RCU grace-period initialization"
        range 0 5
        default 3
+       depends on RCU_TORTURE_TEST_SLOW_INIT
        help
          This option specifies the number of jiffies to wait between
          each rcu_node structure initialization.
index 4fecaedc80a27adadb25bfa2d4e4a13dc182ab72..777eda7d1ab4bff70b8aa465e336465239c9f1b9 100644 (file)
@@ -10,8 +10,11 @@ config KASAN
        help
          Enables kernel address sanitizer - runtime memory debugger,
          designed to find out-of-bounds accesses and use-after-free bugs.
-         This is strictly debugging feature. It consumes about 1/8
-         of available memory and brings about ~x3 performance slowdown.
+         This is strictly a debugging feature and it requires a gcc version
+         of 4.9.2 or later. Detection of out of bounds accesses to stack or
+         global variables requires gcc 5.0 or later.
+         This feature consumes about 1/8 of available memory and brings about
+         ~x3 performance slowdown.
          For better error detection enable CONFIG_STACKTRACE,
          and add slub_debug=U to boot cmdline.
 
@@ -40,6 +43,7 @@ config KASAN_INLINE
          memory accesses. This is faster than outline (in some workloads
          it gives about x2 boost over outline instrumentation), but
          make kernel's .text size much bigger.
+         This requires a gcc version of 5.0 or later.
 
 endchoice
 
index 0f1dd2e9d2c1e572386acb280695e76a2f58406e..fbe2aac522e67dc16708040128337eec946cd4ad 100644 (file)
@@ -71,6 +71,34 @@ void __iomem *devm_ioremap_nocache(struct device *dev, resource_size_t offset,
 }
 EXPORT_SYMBOL(devm_ioremap_nocache);
 
+/**
+ * devm_ioremap_wc - Managed ioremap_wc()
+ * @dev: Generic device to remap IO address for
+ * @offset: BUS offset to map
+ * @size: Size of map
+ *
+ * Managed ioremap_wc().  Map is automatically unmapped on driver detach.
+ */
+void __iomem *devm_ioremap_wc(struct device *dev, resource_size_t offset,
+                             resource_size_t size)
+{
+       void __iomem **ptr, *addr;
+
+       ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL);
+       if (!ptr)
+               return NULL;
+
+       addr = ioremap_wc(offset, size);
+       if (addr) {
+               *ptr = addr;
+               devres_add(dev, ptr);
+       } else
+               devres_free(ptr);
+
+       return addr;
+}
+EXPORT_SYMBOL(devm_ioremap_wc);
+
 /**
  * devm_iounmap - Managed iounmap()
  * @dev: Generic device to unmap for
diff --git a/lib/find_last_bit.c b/lib/find_last_bit.c
deleted file mode 100644 (file)
index 3e3be40..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/* find_last_bit.c: fallback find next bit implementation
- *
- * Copyright (C) 2008 IBM Corporation
- * Written by Rusty Russell <rusty@rustcorp.com.au>
- * (Inspired by David Howell's find_next_bit implementation)
- *
- * Rewritten by Yury Norov <yury.norov@gmail.com> to decrease
- * size and improve performance, 2015.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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/bitops.h>
-#include <linux/bitmap.h>
-#include <linux/export.h>
-#include <linux/kernel.h>
-
-#ifndef find_last_bit
-
-unsigned long find_last_bit(const unsigned long *addr, unsigned long size)
-{
-       if (size) {
-               unsigned long val = BITMAP_LAST_WORD_MASK(size);
-               unsigned long idx = (size-1) / BITS_PER_LONG;
-
-               do {
-                       val &= addr[idx];
-                       if (val)
-                               return idx * BITS_PER_LONG + __fls(val);
-
-                       val = ~0ul;
-               } while (idx--);
-       }
-       return size;
-}
-EXPORT_SYMBOL(find_last_bit);
-
-#endif
index a1a517cba7ec3bea6140957d2e549317717dedcf..df30632f0bef9ec1c36a48d83a6eb87cd18ee405 100644 (file)
@@ -15,9 +15,9 @@
 #define        DMA_ERROR_CODE (~(dma_addr_t)0x0)
 #endif
 
-unsigned long iommu_large_alloc = 15;
+static unsigned long iommu_large_alloc = 15;
 
-static DEFINE_PER_CPU(unsigned int, iommu_pool_hash);
+static DEFINE_PER_CPU(unsigned int, iommu_hash_common);
 
 static inline bool need_flush(struct iommu_map_table *iommu)
 {
@@ -44,7 +44,7 @@ static void setup_iommu_pool_hash(void)
                return;
        do_once = true;
        for_each_possible_cpu(i)
-               per_cpu(iommu_pool_hash, i) = hash_32(i, IOMMU_POOL_HASHBITS);
+               per_cpu(iommu_hash_common, i) = hash_32(i, IOMMU_POOL_HASHBITS);
 }
 
 /*
@@ -53,12 +53,12 @@ static void setup_iommu_pool_hash(void)
  * the top 1/4 of the table will be set aside for pool allocations
  * of more than iommu_large_alloc pages.
  */
-extern void iommu_tbl_pool_init(struct iommu_map_table *iommu,
-                               unsigned long num_entries,
-                               u32 table_shift,
-                               void (*lazy_flush)(struct iommu_map_table *),
-                               bool large_pool, u32 npools,
-                               bool skip_span_boundary_check)
+void iommu_tbl_pool_init(struct iommu_map_table *iommu,
+                        unsigned long num_entries,
+                        u32 table_shift,
+                        void (*lazy_flush)(struct iommu_map_table *),
+                        bool large_pool, u32 npools,
+                        bool skip_span_boundary_check)
 {
        unsigned int start, i;
        struct iommu_pool *p = &(iommu->large_pool);
@@ -106,7 +106,7 @@ unsigned long iommu_tbl_range_alloc(struct device *dev,
                                unsigned long mask,
                                unsigned int align_order)
 {
-       unsigned int pool_hash = __this_cpu_read(iommu_pool_hash);
+       unsigned int pool_hash = __this_cpu_read(iommu_hash_common);
        unsigned long n, end, start, limit, boundary_size;
        struct iommu_pool *pool;
        int pass = 0;
index dbef2314901ed39c54b61d9511e0dbce37ddaa83..975c6e0434bde0b4b804654822928899ac9e9e2a 100644 (file)
@@ -131,11 +131,12 @@ static inline const struct raid6_recov_calls *raid6_choose_recov(void)
 static inline const struct raid6_calls *raid6_choose_gen(
        void *(*const dptrs)[(65536/PAGE_SIZE)+2], const int disks)
 {
-       unsigned long perf, bestperf, j0, j1;
+       unsigned long perf, bestgenperf, bestxorperf, j0, j1;
+       int start = (disks>>1)-1, stop = disks-3;       /* work on the second half of the disks */
        const struct raid6_calls *const *algo;
        const struct raid6_calls *best;
 
-       for (bestperf = 0, best = NULL, algo = raid6_algos; *algo; algo++) {
+       for (bestgenperf = 0, bestxorperf = 0, best = NULL, algo = raid6_algos; *algo; algo++) {
                if (!best || (*algo)->prefer >= best->prefer) {
                        if ((*algo)->valid && !(*algo)->valid())
                                continue;
@@ -153,19 +154,45 @@ static inline const struct raid6_calls *raid6_choose_gen(
                        }
                        preempt_enable();
 
-                       if (perf > bestperf) {
-                               bestperf = perf;
+                       if (perf > bestgenperf) {
+                               bestgenperf = perf;
                                best = *algo;
                        }
-                       pr_info("raid6: %-8s %5ld MB/s\n", (*algo)->name,
+                       pr_info("raid6: %-8s gen() %5ld MB/s\n", (*algo)->name,
                               (perf*HZ) >> (20-16+RAID6_TIME_JIFFIES_LG2));
+
+                       if (!(*algo)->xor_syndrome)
+                               continue;
+
+                       perf = 0;
+
+                       preempt_disable();
+                       j0 = jiffies;
+                       while ((j1 = jiffies) == j0)
+                               cpu_relax();
+                       while (time_before(jiffies,
+                                           j1 + (1<<RAID6_TIME_JIFFIES_LG2))) {
+                               (*algo)->xor_syndrome(disks, start, stop,
+                                                     PAGE_SIZE, *dptrs);
+                               perf++;
+                       }
+                       preempt_enable();
+
+                       if (best == *algo)
+                               bestxorperf = perf;
+
+                       pr_info("raid6: %-8s xor() %5ld MB/s\n", (*algo)->name,
+                               (perf*HZ) >> (20-16+RAID6_TIME_JIFFIES_LG2+1));
                }
        }
 
        if (best) {
-               pr_info("raid6: using algorithm %s (%ld MB/s)\n",
+               pr_info("raid6: using algorithm %s gen() %ld MB/s\n",
                       best->name,
-                      (bestperf*HZ) >> (20-16+RAID6_TIME_JIFFIES_LG2));
+                      (bestgenperf*HZ) >> (20-16+RAID6_TIME_JIFFIES_LG2));
+               if (best->xor_syndrome)
+                       pr_info("raid6: .... xor() %ld MB/s, rmw enabled\n",
+                              (bestxorperf*HZ) >> (20-16+RAID6_TIME_JIFFIES_LG2+1));
                raid6_call = *best;
        } else
                pr_err("raid6: Yikes!  No algorithm found!\n");
index 7cc12b532e95b90d85e3968099359a8ba19b2708..bec27fce7501702a7da2a16c621c1b91adb938f5 100644 (file)
@@ -119,6 +119,7 @@ int raid6_have_altivec(void)
 
 const struct raid6_calls raid6_altivec$# = {
        raid6_altivec$#_gen_syndrome,
+       NULL,                   /* XOR not yet implemented */
        raid6_have_altivec,
        "altivecx$#",
        0
index bc3b1dd436eb4d4d807e08569237424032e0adf4..76734004358da609f6062f1095cdae89fb038b7e 100644 (file)
@@ -89,6 +89,7 @@ static void raid6_avx21_gen_syndrome(int disks, size_t bytes, void **ptrs)
 
 const struct raid6_calls raid6_avx2x1 = {
        raid6_avx21_gen_syndrome,
+       NULL,                   /* XOR not yet implemented */
        raid6_have_avx2,
        "avx2x1",
        1                       /* Has cache hints */
@@ -150,6 +151,7 @@ static void raid6_avx22_gen_syndrome(int disks, size_t bytes, void **ptrs)
 
 const struct raid6_calls raid6_avx2x2 = {
        raid6_avx22_gen_syndrome,
+       NULL,                   /* XOR not yet implemented */
        raid6_have_avx2,
        "avx2x2",
        1                       /* Has cache hints */
@@ -242,6 +244,7 @@ static void raid6_avx24_gen_syndrome(int disks, size_t bytes, void **ptrs)
 
 const struct raid6_calls raid6_avx2x4 = {
        raid6_avx24_gen_syndrome,
+       NULL,                   /* XOR not yet implemented */
        raid6_have_avx2,
        "avx2x4",
        1                       /* Has cache hints */
index 5b50f8dfc5d244efa4678e1034da785b296559fd..558aeac9342aa8e4b1a40832a7fd4464cb9c06a9 100644 (file)
@@ -107,9 +107,48 @@ static void raid6_int$#_gen_syndrome(int disks, size_t bytes, void **ptrs)
        }
 }
 
+static void raid6_int$#_xor_syndrome(int disks, int start, int stop,
+                                    size_t bytes, void **ptrs)
+{
+       u8 **dptr = (u8 **)ptrs;
+       u8 *p, *q;
+       int d, z, z0;
+
+       unative_t wd$$, wq$$, wp$$, w1$$, w2$$;
+
+       z0 = stop;              /* P/Q right side optimization */
+       p = dptr[disks-2];      /* XOR parity */
+       q = dptr[disks-1];      /* RS syndrome */
+
+       for ( d = 0 ; d < bytes ; d += NSIZE*$# ) {
+               /* P/Q data pages */
+               wq$$ = wp$$ = *(unative_t *)&dptr[z0][d+$$*NSIZE];
+               for ( z = z0-1 ; z >= start ; z-- ) {
+                       wd$$ = *(unative_t *)&dptr[z][d+$$*NSIZE];
+                       wp$$ ^= wd$$;
+                       w2$$ = MASK(wq$$);
+                       w1$$ = SHLBYTE(wq$$);
+                       w2$$ &= NBYTES(0x1d);
+                       w1$$ ^= w2$$;
+                       wq$$ = w1$$ ^ wd$$;
+               }
+               /* P/Q left side optimization */
+               for ( z = start-1 ; z >= 0 ; z-- ) {
+                       w2$$ = MASK(wq$$);
+                       w1$$ = SHLBYTE(wq$$);
+                       w2$$ &= NBYTES(0x1d);
+                       wq$$ = w1$$ ^ w2$$;
+               }
+               *(unative_t *)&p[d+NSIZE*$$] ^= wp$$;
+               *(unative_t *)&q[d+NSIZE*$$] ^= wq$$;
+       }
+
+}
+
 const struct raid6_calls raid6_intx$# = {
        raid6_int$#_gen_syndrome,
-       NULL,           /* always valid */
+       raid6_int$#_xor_syndrome,
+       NULL,                   /* always valid */
        "int" NSTRING "x$#",
        0
 };
index 590c71c9e2005b407166cde2e37a0c8066c7ef0d..b3b0e1fcd3af8b6d13f72b1501275f472c4f06ec 100644 (file)
@@ -76,6 +76,7 @@ static void raid6_mmx1_gen_syndrome(int disks, size_t bytes, void **ptrs)
 
 const struct raid6_calls raid6_mmxx1 = {
        raid6_mmx1_gen_syndrome,
+       NULL,                   /* XOR not yet implemented */
        raid6_have_mmx,
        "mmxx1",
        0
@@ -134,6 +135,7 @@ static void raid6_mmx2_gen_syndrome(int disks, size_t bytes, void **ptrs)
 
 const struct raid6_calls raid6_mmxx2 = {
        raid6_mmx2_gen_syndrome,
+       NULL,                   /* XOR not yet implemented */
        raid6_have_mmx,
        "mmxx2",
        0
index 36ad4705df1aef883d32e79d8e41b92569741a07..d9ad6ee284f4b0ae33961fe42528de2df69b591b 100644 (file)
@@ -42,6 +42,7 @@
        }                                                               \
        struct raid6_calls const raid6_neonx ## _n = {                  \
                raid6_neon ## _n ## _gen_syndrome,                      \
+               NULL,           /* XOR not yet implemented */           \
                raid6_have_neon,                                        \
                "neonx" #_n,                                            \
                0                                                       \
index f7629713944505e575e2d2746c62ebaef3ca6946..9025b8ca9aa3b5968faa31d2a8d0e27e3abd56bc 100644 (file)
@@ -92,6 +92,7 @@ static void raid6_sse11_gen_syndrome(int disks, size_t bytes, void **ptrs)
 
 const struct raid6_calls raid6_sse1x1 = {
        raid6_sse11_gen_syndrome,
+       NULL,                   /* XOR not yet implemented */
        raid6_have_sse1_or_mmxext,
        "sse1x1",
        1                       /* Has cache hints */
@@ -154,6 +155,7 @@ static void raid6_sse12_gen_syndrome(int disks, size_t bytes, void **ptrs)
 
 const struct raid6_calls raid6_sse1x2 = {
        raid6_sse12_gen_syndrome,
+       NULL,                   /* XOR not yet implemented */
        raid6_have_sse1_or_mmxext,
        "sse1x2",
        1                       /* Has cache hints */
index 85b82c85f28e61699bbf94e19e3f2f7750108d10..1d2276b007ee1c7b502e6266f73f11a9e47e77aa 100644 (file)
@@ -88,8 +88,58 @@ static void raid6_sse21_gen_syndrome(int disks, size_t bytes, void **ptrs)
        kernel_fpu_end();
 }
 
+
+static void raid6_sse21_xor_syndrome(int disks, int start, int stop,
+                                    size_t bytes, void **ptrs)
+ {
+       u8 **dptr = (u8 **)ptrs;
+       u8 *p, *q;
+       int d, z, z0;
+
+       z0 = stop;              /* P/Q right side optimization */
+       p = dptr[disks-2];      /* XOR parity */
+       q = dptr[disks-1];      /* RS syndrome */
+
+       kernel_fpu_begin();
+
+       asm volatile("movdqa %0,%%xmm0" : : "m" (raid6_sse_constants.x1d[0]));
+
+       for ( d = 0 ; d < bytes ; d += 16 ) {
+               asm volatile("movdqa %0,%%xmm4" :: "m" (dptr[z0][d]));
+               asm volatile("movdqa %0,%%xmm2" : : "m" (p[d]));
+               asm volatile("pxor %xmm4,%xmm2");
+               /* P/Q data pages */
+               for ( z = z0-1 ; z >= start ; z-- ) {
+                       asm volatile("pxor %xmm5,%xmm5");
+                       asm volatile("pcmpgtb %xmm4,%xmm5");
+                       asm volatile("paddb %xmm4,%xmm4");
+                       asm volatile("pand %xmm0,%xmm5");
+                       asm volatile("pxor %xmm5,%xmm4");
+                       asm volatile("movdqa %0,%%xmm5" :: "m" (dptr[z][d]));
+                       asm volatile("pxor %xmm5,%xmm2");
+                       asm volatile("pxor %xmm5,%xmm4");
+               }
+               /* P/Q left side optimization */
+               for ( z = start-1 ; z >= 0 ; z-- ) {
+                       asm volatile("pxor %xmm5,%xmm5");
+                       asm volatile("pcmpgtb %xmm4,%xmm5");
+                       asm volatile("paddb %xmm4,%xmm4");
+                       asm volatile("pand %xmm0,%xmm5");
+                       asm volatile("pxor %xmm5,%xmm4");
+               }
+               asm volatile("pxor %0,%%xmm4" : : "m" (q[d]));
+               /* Don't use movntdq for r/w memory area < cache line */
+               asm volatile("movdqa %%xmm4,%0" : "=m" (q[d]));
+               asm volatile("movdqa %%xmm2,%0" : "=m" (p[d]));
+       }
+
+       asm volatile("sfence" : : : "memory");
+       kernel_fpu_end();
+}
+
 const struct raid6_calls raid6_sse2x1 = {
        raid6_sse21_gen_syndrome,
+       raid6_sse21_xor_syndrome,
        raid6_have_sse2,
        "sse2x1",
        1                       /* Has cache hints */
@@ -150,8 +200,76 @@ static void raid6_sse22_gen_syndrome(int disks, size_t bytes, void **ptrs)
        kernel_fpu_end();
 }
 
+ static void raid6_sse22_xor_syndrome(int disks, int start, int stop,
+                                    size_t bytes, void **ptrs)
+ {
+       u8 **dptr = (u8 **)ptrs;
+       u8 *p, *q;
+       int d, z, z0;
+
+       z0 = stop;              /* P/Q right side optimization */
+       p = dptr[disks-2];      /* XOR parity */
+       q = dptr[disks-1];      /* RS syndrome */
+
+       kernel_fpu_begin();
+
+       asm volatile("movdqa %0,%%xmm0" : : "m" (raid6_sse_constants.x1d[0]));
+
+       for ( d = 0 ; d < bytes ; d += 32 ) {
+               asm volatile("movdqa %0,%%xmm4" :: "m" (dptr[z0][d]));
+               asm volatile("movdqa %0,%%xmm6" :: "m" (dptr[z0][d+16]));
+               asm volatile("movdqa %0,%%xmm2" : : "m" (p[d]));
+               asm volatile("movdqa %0,%%xmm3" : : "m" (p[d+16]));
+               asm volatile("pxor %xmm4,%xmm2");
+               asm volatile("pxor %xmm6,%xmm3");
+               /* P/Q data pages */
+               for ( z = z0-1 ; z >= start ; z-- ) {
+                       asm volatile("pxor %xmm5,%xmm5");
+                       asm volatile("pxor %xmm7,%xmm7");
+                       asm volatile("pcmpgtb %xmm4,%xmm5");
+                       asm volatile("pcmpgtb %xmm6,%xmm7");
+                       asm volatile("paddb %xmm4,%xmm4");
+                       asm volatile("paddb %xmm6,%xmm6");
+                       asm volatile("pand %xmm0,%xmm5");
+                       asm volatile("pand %xmm0,%xmm7");
+                       asm volatile("pxor %xmm5,%xmm4");
+                       asm volatile("pxor %xmm7,%xmm6");
+                       asm volatile("movdqa %0,%%xmm5" :: "m" (dptr[z][d]));
+                       asm volatile("movdqa %0,%%xmm7" :: "m" (dptr[z][d+16]));
+                       asm volatile("pxor %xmm5,%xmm2");
+                       asm volatile("pxor %xmm7,%xmm3");
+                       asm volatile("pxor %xmm5,%xmm4");
+                       asm volatile("pxor %xmm7,%xmm6");
+               }
+               /* P/Q left side optimization */
+               for ( z = start-1 ; z >= 0 ; z-- ) {
+                       asm volatile("pxor %xmm5,%xmm5");
+                       asm volatile("pxor %xmm7,%xmm7");
+                       asm volatile("pcmpgtb %xmm4,%xmm5");
+                       asm volatile("pcmpgtb %xmm6,%xmm7");
+                       asm volatile("paddb %xmm4,%xmm4");
+                       asm volatile("paddb %xmm6,%xmm6");
+                       asm volatile("pand %xmm0,%xmm5");
+                       asm volatile("pand %xmm0,%xmm7");
+                       asm volatile("pxor %xmm5,%xmm4");
+                       asm volatile("pxor %xmm7,%xmm6");
+               }
+               asm volatile("pxor %0,%%xmm4" : : "m" (q[d]));
+               asm volatile("pxor %0,%%xmm6" : : "m" (q[d+16]));
+               /* Don't use movntdq for r/w memory area < cache line */
+               asm volatile("movdqa %%xmm4,%0" : "=m" (q[d]));
+               asm volatile("movdqa %%xmm6,%0" : "=m" (q[d+16]));
+               asm volatile("movdqa %%xmm2,%0" : "=m" (p[d]));
+               asm volatile("movdqa %%xmm3,%0" : "=m" (p[d+16]));
+       }
+
+       asm volatile("sfence" : : : "memory");
+       kernel_fpu_end();
+ }
+
 const struct raid6_calls raid6_sse2x2 = {
        raid6_sse22_gen_syndrome,
+       raid6_sse22_xor_syndrome,
        raid6_have_sse2,
        "sse2x2",
        1                       /* Has cache hints */
@@ -248,8 +366,117 @@ static void raid6_sse24_gen_syndrome(int disks, size_t bytes, void **ptrs)
        kernel_fpu_end();
 }
 
+ static void raid6_sse24_xor_syndrome(int disks, int start, int stop,
+                                    size_t bytes, void **ptrs)
+ {
+       u8 **dptr = (u8 **)ptrs;
+       u8 *p, *q;
+       int d, z, z0;
+
+       z0 = stop;              /* P/Q right side optimization */
+       p = dptr[disks-2];      /* XOR parity */
+       q = dptr[disks-1];      /* RS syndrome */
+
+       kernel_fpu_begin();
+
+       asm volatile("movdqa %0,%%xmm0" :: "m" (raid6_sse_constants.x1d[0]));
+
+       for ( d = 0 ; d < bytes ; d += 64 ) {
+               asm volatile("movdqa %0,%%xmm4" :: "m" (dptr[z0][d]));
+               asm volatile("movdqa %0,%%xmm6" :: "m" (dptr[z0][d+16]));
+               asm volatile("movdqa %0,%%xmm12" :: "m" (dptr[z0][d+32]));
+               asm volatile("movdqa %0,%%xmm14" :: "m" (dptr[z0][d+48]));
+               asm volatile("movdqa %0,%%xmm2" : : "m" (p[d]));
+               asm volatile("movdqa %0,%%xmm3" : : "m" (p[d+16]));
+               asm volatile("movdqa %0,%%xmm10" : : "m" (p[d+32]));
+               asm volatile("movdqa %0,%%xmm11" : : "m" (p[d+48]));
+               asm volatile("pxor %xmm4,%xmm2");
+               asm volatile("pxor %xmm6,%xmm3");
+               asm volatile("pxor %xmm12,%xmm10");
+               asm volatile("pxor %xmm14,%xmm11");
+               /* P/Q data pages */
+               for ( z = z0-1 ; z >= start ; z-- ) {
+                       asm volatile("prefetchnta %0" :: "m" (dptr[z][d]));
+                       asm volatile("prefetchnta %0" :: "m" (dptr[z][d+32]));
+                       asm volatile("pxor %xmm5,%xmm5");
+                       asm volatile("pxor %xmm7,%xmm7");
+                       asm volatile("pxor %xmm13,%xmm13");
+                       asm volatile("pxor %xmm15,%xmm15");
+                       asm volatile("pcmpgtb %xmm4,%xmm5");
+                       asm volatile("pcmpgtb %xmm6,%xmm7");
+                       asm volatile("pcmpgtb %xmm12,%xmm13");
+                       asm volatile("pcmpgtb %xmm14,%xmm15");
+                       asm volatile("paddb %xmm4,%xmm4");
+                       asm volatile("paddb %xmm6,%xmm6");
+                       asm volatile("paddb %xmm12,%xmm12");
+                       asm volatile("paddb %xmm14,%xmm14");
+                       asm volatile("pand %xmm0,%xmm5");
+                       asm volatile("pand %xmm0,%xmm7");
+                       asm volatile("pand %xmm0,%xmm13");
+                       asm volatile("pand %xmm0,%xmm15");
+                       asm volatile("pxor %xmm5,%xmm4");
+                       asm volatile("pxor %xmm7,%xmm6");
+                       asm volatile("pxor %xmm13,%xmm12");
+                       asm volatile("pxor %xmm15,%xmm14");
+                       asm volatile("movdqa %0,%%xmm5" :: "m" (dptr[z][d]));
+                       asm volatile("movdqa %0,%%xmm7" :: "m" (dptr[z][d+16]));
+                       asm volatile("movdqa %0,%%xmm13" :: "m" (dptr[z][d+32]));
+                       asm volatile("movdqa %0,%%xmm15" :: "m" (dptr[z][d+48]));
+                       asm volatile("pxor %xmm5,%xmm2");
+                       asm volatile("pxor %xmm7,%xmm3");
+                       asm volatile("pxor %xmm13,%xmm10");
+                       asm volatile("pxor %xmm15,%xmm11");
+                       asm volatile("pxor %xmm5,%xmm4");
+                       asm volatile("pxor %xmm7,%xmm6");
+                       asm volatile("pxor %xmm13,%xmm12");
+                       asm volatile("pxor %xmm15,%xmm14");
+               }
+               asm volatile("prefetchnta %0" :: "m" (q[d]));
+               asm volatile("prefetchnta %0" :: "m" (q[d+32]));
+               /* P/Q left side optimization */
+               for ( z = start-1 ; z >= 0 ; z-- ) {
+                       asm volatile("pxor %xmm5,%xmm5");
+                       asm volatile("pxor %xmm7,%xmm7");
+                       asm volatile("pxor %xmm13,%xmm13");
+                       asm volatile("pxor %xmm15,%xmm15");
+                       asm volatile("pcmpgtb %xmm4,%xmm5");
+                       asm volatile("pcmpgtb %xmm6,%xmm7");
+                       asm volatile("pcmpgtb %xmm12,%xmm13");
+                       asm volatile("pcmpgtb %xmm14,%xmm15");
+                       asm volatile("paddb %xmm4,%xmm4");
+                       asm volatile("paddb %xmm6,%xmm6");
+                       asm volatile("paddb %xmm12,%xmm12");
+                       asm volatile("paddb %xmm14,%xmm14");
+                       asm volatile("pand %xmm0,%xmm5");
+                       asm volatile("pand %xmm0,%xmm7");
+                       asm volatile("pand %xmm0,%xmm13");
+                       asm volatile("pand %xmm0,%xmm15");
+                       asm volatile("pxor %xmm5,%xmm4");
+                       asm volatile("pxor %xmm7,%xmm6");
+                       asm volatile("pxor %xmm13,%xmm12");
+                       asm volatile("pxor %xmm15,%xmm14");
+               }
+               asm volatile("movntdq %%xmm2,%0" : "=m" (p[d]));
+               asm volatile("movntdq %%xmm3,%0" : "=m" (p[d+16]));
+               asm volatile("movntdq %%xmm10,%0" : "=m" (p[d+32]));
+               asm volatile("movntdq %%xmm11,%0" : "=m" (p[d+48]));
+               asm volatile("pxor %0,%%xmm4" : : "m" (q[d]));
+               asm volatile("pxor %0,%%xmm6" : : "m" (q[d+16]));
+               asm volatile("pxor %0,%%xmm12" : : "m" (q[d+32]));
+               asm volatile("pxor %0,%%xmm14" : : "m" (q[d+48]));
+               asm volatile("movntdq %%xmm4,%0" : "=m" (q[d]));
+               asm volatile("movntdq %%xmm6,%0" : "=m" (q[d+16]));
+               asm volatile("movntdq %%xmm12,%0" : "=m" (q[d+32]));
+               asm volatile("movntdq %%xmm14,%0" : "=m" (q[d+48]));
+       }
+       asm volatile("sfence" : : : "memory");
+       kernel_fpu_end();
+ }
+
+
 const struct raid6_calls raid6_sse2x4 = {
        raid6_sse24_gen_syndrome,
+       raid6_sse24_xor_syndrome,
        raid6_have_sse2,
        "sse2x4",
        1                       /* Has cache hints */
index 5a485b7a7d3c3f8004924f638ad9db77b35ebf5c..3bebbabdb51004bb7d66d8eed659f50afca29f5c 100644 (file)
@@ -28,11 +28,11 @@ char *dataptrs[NDISKS];
 char data[NDISKS][PAGE_SIZE];
 char recovi[PAGE_SIZE], recovj[PAGE_SIZE];
 
-static void makedata(void)
+static void makedata(int start, int stop)
 {
        int i, j;
 
-       for (i = 0; i < NDISKS; i++) {
+       for (i = start; i <= stop; i++) {
                for (j = 0; j < PAGE_SIZE; j++)
                        data[i][j] = rand();
 
@@ -91,34 +91,55 @@ int main(int argc, char *argv[])
 {
        const struct raid6_calls *const *algo;
        const struct raid6_recov_calls *const *ra;
-       int i, j;
+       int i, j, p1, p2;
        int err = 0;
 
-       makedata();
+       makedata(0, NDISKS-1);
 
        for (ra = raid6_recov_algos; *ra; ra++) {
                if ((*ra)->valid  && !(*ra)->valid())
                        continue;
+
                raid6_2data_recov = (*ra)->data2;
                raid6_datap_recov = (*ra)->datap;
 
                printf("using recovery %s\n", (*ra)->name);
 
                for (algo = raid6_algos; *algo; algo++) {
-                       if (!(*algo)->valid || (*algo)->valid()) {
-                               raid6_call = **algo;
+                       if ((*algo)->valid && !(*algo)->valid())
+                               continue;
+
+                       raid6_call = **algo;
+
+                       /* Nuke syndromes */
+                       memset(data[NDISKS-2], 0xee, 2*PAGE_SIZE);
+
+                       /* Generate assumed good syndrome */
+                       raid6_call.gen_syndrome(NDISKS, PAGE_SIZE,
+                                               (void **)&dataptrs);
+
+                       for (i = 0; i < NDISKS-1; i++)
+                               for (j = i+1; j < NDISKS; j++)
+                                       err += test_disks(i, j);
+
+                       if (!raid6_call.xor_syndrome)
+                               continue;
+
+                       for (p1 = 0; p1 < NDISKS-2; p1++)
+                               for (p2 = p1; p2 < NDISKS-2; p2++) {
 
-                               /* Nuke syndromes */
-                               memset(data[NDISKS-2], 0xee, 2*PAGE_SIZE);
+                                       /* Simulate rmw run */
+                                       raid6_call.xor_syndrome(NDISKS, p1, p2, PAGE_SIZE,
+                                                               (void **)&dataptrs);
+                                       makedata(p1, p2);
+                                       raid6_call.xor_syndrome(NDISKS, p1, p2, PAGE_SIZE,
+                                                                (void **)&dataptrs);
 
-                               /* Generate assumed good syndrome */
-                               raid6_call.gen_syndrome(NDISKS, PAGE_SIZE,
-                                                       (void **)&dataptrs);
+                                       for (i = 0; i < NDISKS-1; i++)
+                                               for (j = i+1; j < NDISKS; j++)
+                                                       err += test_disks(i, j);
+                               }
 
-                               for (i = 0; i < NDISKS-1; i++)
-                                       for (j = i+1; j < NDISKS; j++)
-                                               err += test_disks(i, j);
-                       }
                }
                printf("\n");
        }
index e7c29459cbcd5a69fc929f1994cdeab02bea6148..2dd291a112645f82450cca76431e5d72e7884c5d 100644 (file)
@@ -80,6 +80,7 @@ void raid6_tilegx$#_gen_syndrome(int disks, size_t bytes, void **ptrs)
 
 const struct raid6_calls raid6_tilegx$# = {
        raid6_tilegx$#_gen_syndrome,
+       NULL,                   /* XOR not yet implemented */
        NULL,
        "tilegx$#",
        0
index 4898442b837fbd715f8d5079a1060e43c4b7a367..b28df4019adedfe182d5c719da62b6bf05c031fe 100644 (file)
@@ -405,13 +405,18 @@ int rhashtable_insert_rehash(struct rhashtable *ht)
 
        if (rht_grow_above_75(ht, tbl))
                size *= 2;
-       /* More than two rehashes (not resizes) detected. */
-       else if (WARN_ON(old_tbl != tbl && old_tbl->size == size))
+       /* Do not schedule more than one rehash */
+       else if (old_tbl != tbl)
                return -EBUSY;
 
        new_tbl = bucket_table_alloc(ht, size, GFP_ATOMIC);
-       if (new_tbl == NULL)
+       if (new_tbl == NULL) {
+               /* Schedule async resize/rehash to try allocation
+                * non-atomic context.
+                */
+               schedule_work(&ht->run_work);
                return -ENOMEM;
+       }
 
        err = rhashtable_rehash_attach(ht, tbl, new_tbl);
        if (err) {
index a5792019193cac08715b9f72304607f8746599de..bb3d4b6993c408321da2268b07b1eeefe57cd854 100644 (file)
@@ -607,7 +607,7 @@ EXPORT_SYMBOL(memset);
 void memzero_explicit(void *s, size_t count)
 {
        memset(s, 0, count);
-       barrier();
+       barrier_data(s);
 }
 EXPORT_SYMBOL(memzero_explicit);
 
index 329caf56df22d84d02495e35f051062b01bdeaba..4ca5fe0042e17c2eac0dd6d16f0065c41a5dfd4e 100644 (file)
@@ -34,13 +34,13 @@ static int hwpoison_inject(void *data, u64 val)
        if (!hwpoison_filter_enable)
                goto inject;
 
-       if (!PageLRU(p) && !PageHuge(p))
-               shake_page(p, 0);
+       if (!PageLRU(hpage) && !PageHuge(p))
+               shake_page(hpage, 0);
        /*
         * This implies unable to support non-LRU pages.
         */
-       if (!PageLRU(p) && !PageHuge(p))
-               return 0;
+       if (!PageLRU(hpage) && !PageHuge(p))
+               goto put_out;
 
        /*
         * do a racy check with elevated page count, to make sure PG_hwpoison
@@ -52,11 +52,14 @@ static int hwpoison_inject(void *data, u64 val)
        err = hwpoison_filter(hpage);
        unlock_page(hpage);
        if (err)
-               return 0;
+               goto put_out;
 
 inject:
        pr_info("Injecting memory failure at pfn %#lx\n", pfn);
        return memory_failure(pfn, 18, MF_COUNT_INCREASED);
+put_out:
+       put_page(hpage);
+       return 0;
 }
 
 static int hwpoison_unpoison(void *data, u64 val)
index d9359b770cd96b37ee945553a4230edbfd720e46..501820c815b335b017ea87cf3dd3f1a0d034bd98 100644 (file)
@@ -1187,10 +1187,10 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
         * The check (unnecessarily) ignores LRU pages being isolated and
         * walked by the page reclaim code, however that's not a big loss.
         */
-       if (!PageHuge(p) && !PageTransTail(p)) {
-               if (!PageLRU(p))
-                       shake_page(p, 0);
-               if (!PageLRU(p)) {
+       if (!PageHuge(p)) {
+               if (!PageLRU(hpage))
+                       shake_page(hpage, 0);
+               if (!PageLRU(hpage)) {
                        /*
                         * shake_page could have turned it free.
                         */
@@ -1777,12 +1777,12 @@ int soft_offline_page(struct page *page, int flags)
        } else if (ret == 0) { /* for free pages */
                if (PageHuge(page)) {
                        set_page_hwpoison_huge_page(hpage);
-                       dequeue_hwpoisoned_huge_page(hpage);
-                       atomic_long_add(1 << compound_order(hpage),
+                       if (!dequeue_hwpoisoned_huge_page(hpage))
+                               atomic_long_add(1 << compound_order(hpage),
                                        &num_poisoned_pages);
                } else {
-                       SetPageHWPoison(page);
-                       atomic_long_inc(&num_poisoned_pages);
+                       if (!TestSetPageHWPoison(page))
+                               atomic_long_inc(&num_poisoned_pages);
                }
        }
        unset_migratetype_isolate(page, MIGRATE_MOVABLE);
index 1ea2400b52450fccdc526d569d1447657379609d..de981370fbc5d596de3d419062c0977829602af7 100644 (file)
@@ -544,7 +544,7 @@ EXPORT_SYMBOL_GPL(shmem_truncate_range);
 
 static int shmem_setattr(struct dentry *dentry, struct iattr *attr)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
        struct shmem_inode_info *info = SHMEM_I(inode);
        int error;
 
@@ -2274,7 +2274,7 @@ static int shmem_create(struct inode *dir, struct dentry *dentry, umode_t mode,
  */
 static int shmem_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
 {
-       struct inode *inode = old_dentry->d_inode;
+       struct inode *inode = d_inode(old_dentry);
        int ret;
 
        /*
@@ -2298,7 +2298,7 @@ out:
 
 static int shmem_unlink(struct inode *dir, struct dentry *dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
 
        if (inode->i_nlink > 1 && !S_ISDIR(inode->i_mode))
                shmem_free_inode(inode->i_sb);
@@ -2315,7 +2315,7 @@ static int shmem_rmdir(struct inode *dir, struct dentry *dentry)
        if (!simple_empty(dentry))
                return -ENOTEMPTY;
 
-       drop_nlink(dentry->d_inode);
+       drop_nlink(d_inode(dentry));
        drop_nlink(dir);
        return shmem_unlink(dir, dentry);
 }
@@ -2336,8 +2336,8 @@ static int shmem_exchange(struct inode *old_dir, struct dentry *old_dentry, stru
        }
        old_dir->i_ctime = old_dir->i_mtime =
        new_dir->i_ctime = new_dir->i_mtime =
-       old_dentry->d_inode->i_ctime =
-       new_dentry->d_inode->i_ctime = CURRENT_TIME;
+       d_inode(old_dentry)->i_ctime =
+       d_inode(new_dentry)->i_ctime = CURRENT_TIME;
 
        return 0;
 }
@@ -2376,7 +2376,7 @@ static int shmem_whiteout(struct inode *old_dir, struct dentry *old_dentry)
  */
 static int shmem_rename2(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry, unsigned int flags)
 {
-       struct inode *inode = old_dentry->d_inode;
+       struct inode *inode = d_inode(old_dentry);
        int they_are_dirs = S_ISDIR(inode->i_mode);
 
        if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
@@ -2396,10 +2396,10 @@ static int shmem_rename2(struct inode *old_dir, struct dentry *old_dentry, struc
                        return error;
        }
 
-       if (new_dentry->d_inode) {
+       if (d_really_is_positive(new_dentry)) {
                (void) shmem_unlink(new_dir, new_dentry);
                if (they_are_dirs) {
-                       drop_nlink(new_dentry->d_inode);
+                       drop_nlink(d_inode(new_dentry));
                        drop_nlink(old_dir);
                }
        } else if (they_are_dirs) {
@@ -2476,14 +2476,14 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
 
 static void *shmem_follow_short_symlink(struct dentry *dentry, struct nameidata *nd)
 {
-       nd_set_link(nd, SHMEM_I(dentry->d_inode)->symlink);
+       nd_set_link(nd, SHMEM_I(d_inode(dentry))->symlink);
        return NULL;
 }
 
 static void *shmem_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        struct page *page = NULL;
-       int error = shmem_getpage(dentry->d_inode, 0, &page, SGP_READ, NULL);
+       int error = shmem_getpage(d_inode(dentry), 0, &page, SGP_READ, NULL);
        nd_set_link(nd, error ? ERR_PTR(error) : kmap(page));
        if (page)
                unlock_page(page);
@@ -2574,7 +2574,7 @@ static int shmem_xattr_validate(const char *name)
 static ssize_t shmem_getxattr(struct dentry *dentry, const char *name,
                              void *buffer, size_t size)
 {
-       struct shmem_inode_info *info = SHMEM_I(dentry->d_inode);
+       struct shmem_inode_info *info = SHMEM_I(d_inode(dentry));
        int err;
 
        /*
@@ -2595,7 +2595,7 @@ static ssize_t shmem_getxattr(struct dentry *dentry, const char *name,
 static int shmem_setxattr(struct dentry *dentry, const char *name,
                          const void *value, size_t size, int flags)
 {
-       struct shmem_inode_info *info = SHMEM_I(dentry->d_inode);
+       struct shmem_inode_info *info = SHMEM_I(d_inode(dentry));
        int err;
 
        /*
@@ -2615,7 +2615,7 @@ static int shmem_setxattr(struct dentry *dentry, const char *name,
 
 static int shmem_removexattr(struct dentry *dentry, const char *name)
 {
-       struct shmem_inode_info *info = SHMEM_I(dentry->d_inode);
+       struct shmem_inode_info *info = SHMEM_I(d_inode(dentry));
        int err;
 
        /*
@@ -2635,7 +2635,7 @@ static int shmem_removexattr(struct dentry *dentry, const char *name)
 
 static ssize_t shmem_listxattr(struct dentry *dentry, char *buffer, size_t size)
 {
-       struct shmem_inode_info *info = SHMEM_I(dentry->d_inode);
+       struct shmem_inode_info *info = SHMEM_I(d_inode(dentry));
        return simple_xattr_list(&info->xattrs, buffer, size);
 }
 #endif /* CONFIG_TMPFS_XATTR */
index 409608960899630b5349bbd310200a95dc2867a2..e29ad70b3000be4f0e7486b172746ea62b4f216f 100644 (file)
@@ -170,7 +170,7 @@ static int nlmsg_populate_mdb_fill(struct sk_buff *skb,
        struct br_port_msg *bpm;
        struct nlattr *nest, *nest2;
 
-       nlh = nlmsg_put(skb, pid, seq, type, sizeof(*bpm), NLM_F_MULTI);
+       nlh = nlmsg_put(skb, pid, seq, type, sizeof(*bpm), 0);
        if (!nlh)
                return -EMSGSIZE;
 
index 0e4ddb81610d90ff51a45835424cef547bba73bf..4b5c236998ff1010831711a17b773e16c7d8ba58 100644 (file)
@@ -394,7 +394,7 @@ errout:
  * Dump information about all ports, in response to GETLINK
  */
 int br_getlink(struct sk_buff *skb, u32 pid, u32 seq,
-              struct net_device *dev, u32 filter_mask)
+              struct net_device *dev, u32 filter_mask, int nlflags)
 {
        struct net_bridge_port *port = br_port_get_rtnl(dev);
 
@@ -402,7 +402,7 @@ int br_getlink(struct sk_buff *skb, u32 pid, u32 seq,
            !(filter_mask & RTEXT_FILTER_BRVLAN_COMPRESSED))
                return 0;
 
-       return br_fill_ifinfo(skb, port, pid, seq, RTM_NEWLINK, NLM_F_MULTI,
+       return br_fill_ifinfo(skb, port, pid, seq, RTM_NEWLINK, nlflags,
                              filter_mask, dev);
 }
 
index 6ca0251cb478bf3147501b325a381a4081dd5149..3362c29400f182c90db6e67a04fcc5018906fa41 100644 (file)
@@ -828,7 +828,7 @@ void br_ifinfo_notify(int event, struct net_bridge_port *port);
 int br_setlink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags);
 int br_dellink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags);
 int br_getlink(struct sk_buff *skb, u32 pid, u32 seq, struct net_device *dev,
-              u32 filter_mask);
+              u32 filter_mask, int nlflags);
 
 #ifdef CONFIG_SYSFS
 /* br_sysfs_if.c */
index ec565508e904113e65329b89dec5952bf5d41075..79e8f71aef5be312ab7aa547293fd047cf42e97c 100644 (file)
@@ -490,6 +490,43 @@ out:
 }
 EXPORT_SYMBOL(ceph_parse_options);
 
+int ceph_print_client_options(struct seq_file *m, struct ceph_client *client)
+{
+       struct ceph_options *opt = client->options;
+       size_t pos = m->count;
+
+       if (opt->name)
+               seq_printf(m, "name=%s,", opt->name);
+       if (opt->key)
+               seq_puts(m, "secret=<hidden>,");
+
+       if (opt->flags & CEPH_OPT_FSID)
+               seq_printf(m, "fsid=%pU,", &opt->fsid);
+       if (opt->flags & CEPH_OPT_NOSHARE)
+               seq_puts(m, "noshare,");
+       if (opt->flags & CEPH_OPT_NOCRC)
+               seq_puts(m, "nocrc,");
+       if (opt->flags & CEPH_OPT_NOMSGAUTH)
+               seq_puts(m, "nocephx_require_signatures,");
+       if ((opt->flags & CEPH_OPT_TCP_NODELAY) == 0)
+               seq_puts(m, "notcp_nodelay,");
+
+       if (opt->mount_timeout != CEPH_MOUNT_TIMEOUT_DEFAULT)
+               seq_printf(m, "mount_timeout=%d,", opt->mount_timeout);
+       if (opt->osd_idle_ttl != CEPH_OSD_IDLE_TTL_DEFAULT)
+               seq_printf(m, "osd_idle_ttl=%d,", opt->osd_idle_ttl);
+       if (opt->osd_keepalive_timeout != CEPH_OSD_KEEPALIVE_DEFAULT)
+               seq_printf(m, "osdkeepalivetimeout=%d,",
+                          opt->osd_keepalive_timeout);
+
+       /* drop redundant comma */
+       if (m->count != pos)
+               m->count--;
+
+       return 0;
+}
+EXPORT_SYMBOL(ceph_print_client_options);
+
 u64 ceph_client_id(struct ceph_client *client)
 {
        return client->monc.auth->global_id;
index 16bc199d9a622e7ecb7957643b26e5c41977ff55..9d84ce4ea0dfa8928cc498b9f0515735666b7857 100644 (file)
@@ -17,6 +17,7 @@ const char *crush_bucket_alg_name(int alg)
        case CRUSH_BUCKET_LIST: return "list";
        case CRUSH_BUCKET_TREE: return "tree";
        case CRUSH_BUCKET_STRAW: return "straw";
+       case CRUSH_BUCKET_STRAW2: return "straw2";
        default: return "unknown";
        }
 }
@@ -40,6 +41,8 @@ int crush_get_bucket_item_weight(const struct crush_bucket *b, int p)
                return ((struct crush_bucket_tree *)b)->node_weights[crush_calc_tree_node(p)];
        case CRUSH_BUCKET_STRAW:
                return ((struct crush_bucket_straw *)b)->item_weights[p];
+       case CRUSH_BUCKET_STRAW2:
+               return ((struct crush_bucket_straw2 *)b)->item_weights[p];
        }
        return 0;
 }
@@ -77,6 +80,14 @@ void crush_destroy_bucket_straw(struct crush_bucket_straw *b)
        kfree(b);
 }
 
+void crush_destroy_bucket_straw2(struct crush_bucket_straw2 *b)
+{
+       kfree(b->item_weights);
+       kfree(b->h.perm);
+       kfree(b->h.items);
+       kfree(b);
+}
+
 void crush_destroy_bucket(struct crush_bucket *b)
 {
        switch (b->alg) {
@@ -92,6 +103,9 @@ void crush_destroy_bucket(struct crush_bucket *b)
        case CRUSH_BUCKET_STRAW:
                crush_destroy_bucket_straw((struct crush_bucket_straw *)b);
                break;
+       case CRUSH_BUCKET_STRAW2:
+               crush_destroy_bucket_straw2((struct crush_bucket_straw2 *)b);
+               break;
        }
 }
 
diff --git a/net/ceph/crush/crush_ln_table.h b/net/ceph/crush/crush_ln_table.h
new file mode 100644 (file)
index 0000000..6192c7f
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2015 Intel Corporation All Rights Reserved
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation.  See file COPYING.
+ *
+ */
+
+#if defined(__linux__)
+#include <linux/types.h>
+#elif defined(__FreeBSD__)
+#include <sys/types.h>
+#endif
+
+#ifndef CEPH_CRUSH_LN_H
+#define CEPH_CRUSH_LN_H
+
+
+// RH_LH_tbl[2*k] = 2^48/(1.0+k/128.0)
+// RH_LH_tbl[2*k+1] = 2^48*log2(1.0+k/128.0)
+
+static int64_t __RH_LH_tbl[128*2+2] = {
+  0x0001000000000000ll, 0x0000000000000000ll, 0x0000fe03f80fe040ll, 0x000002dfca16dde1ll,
+  0x0000fc0fc0fc0fc1ll, 0x000005b9e5a170b4ll, 0x0000fa232cf25214ll, 0x0000088e68ea899all,
+  0x0000f83e0f83e0f9ll, 0x00000b5d69bac77ell, 0x0000f6603d980f67ll, 0x00000e26fd5c8555ll,
+  0x0000f4898d5f85bcll, 0x000010eb389fa29fll, 0x0000f2b9d6480f2cll, 0x000013aa2fdd27f1ll,
+  0x0000f0f0f0f0f0f1ll, 0x00001663f6fac913ll, 0x0000ef2eb71fc435ll, 0x00001918a16e4633ll,
+  0x0000ed7303b5cc0fll, 0x00001bc84240adabll, 0x0000ebbdb2a5c162ll, 0x00001e72ec117fa5ll,
+  0x0000ea0ea0ea0ea1ll, 0x00002118b119b4f3ll, 0x0000e865ac7b7604ll, 0x000023b9a32eaa56ll,
+  0x0000e6c2b4481cd9ll, 0x00002655d3c4f15cll, 0x0000e525982af70dll, 0x000028ed53f307eell,
+  0x0000e38e38e38e39ll, 0x00002b803473f7adll, 0x0000e1fc780e1fc8ll, 0x00002e0e85a9de04ll,
+  0x0000e070381c0e08ll, 0x0000309857a05e07ll, 0x0000dee95c4ca038ll, 0x0000331dba0efce1ll,
+  0x0000dd67c8a60dd7ll, 0x0000359ebc5b69d9ll, 0x0000dbeb61eed19dll, 0x0000381b6d9bb29bll,
+  0x0000da740da740dbll, 0x00003a93dc9864b2ll, 0x0000d901b2036407ll, 0x00003d0817ce9cd4ll,
+  0x0000d79435e50d7all, 0x00003f782d7204d0ll, 0x0000d62b80d62b81ll, 0x000041e42b6ec0c0ll,
+  0x0000d4c77b03531ell, 0x0000444c1f6b4c2dll, 0x0000d3680d3680d4ll, 0x000046b016ca47c1ll,
+  0x0000d20d20d20d21ll, 0x000049101eac381cll, 0x0000d0b69fcbd259ll, 0x00004b6c43f1366all,
+  0x0000cf6474a8819fll, 0x00004dc4933a9337ll, 0x0000ce168a772509ll, 0x0000501918ec6c11ll,
+  0x0000cccccccccccdll, 0x00005269e12f346ell, 0x0000cb8727c065c4ll, 0x000054b6f7f1325all,
+  0x0000ca4587e6b750ll, 0x0000570068e7ef5all, 0x0000c907da4e8712ll, 0x000059463f919deell,
+  0x0000c7ce0c7ce0c8ll, 0x00005b8887367433ll, 0x0000c6980c6980c7ll, 0x00005dc74ae9fbecll,
+  0x0000c565c87b5f9ell, 0x00006002958c5871ll, 0x0000c4372f855d83ll, 0x0000623a71cb82c8ll,
+  0x0000c30c30c30c31ll, 0x0000646eea247c5cll, 0x0000c1e4bbd595f7ll, 0x000066a008e4788cll,
+  0x0000c0c0c0c0c0c1ll, 0x000068cdd829fd81ll, 0x0000bfa02fe80bfbll, 0x00006af861e5fc7dll,
+  0x0000be82fa0be830ll, 0x00006d1fafdce20all, 0x0000bd6910470767ll, 0x00006f43cba79e40ll,
+  0x0000bc52640bc527ll, 0x00007164beb4a56dll, 0x0000bb3ee721a54ell, 0x000073829248e961ll,
+  0x0000ba2e8ba2e8bbll, 0x0000759d4f80cba8ll, 0x0000b92143fa36f6ll, 0x000077b4ff5108d9ll,
+  0x0000b81702e05c0cll, 0x000079c9aa879d53ll, 0x0000b70fbb5a19bfll, 0x00007bdb59cca388ll,
+  0x0000b60b60b60b61ll, 0x00007dea15a32c1bll, 0x0000b509e68a9b95ll, 0x00007ff5e66a0ffell,
+  0x0000b40b40b40b41ll, 0x000081fed45cbccbll, 0x0000b30f63528918ll, 0x00008404e793fb81ll,
+  0x0000b21642c8590cll, 0x000086082806b1d5ll, 0x0000b11fd3b80b12ll, 0x000088089d8a9e47ll,
+  0x0000b02c0b02c0b1ll, 0x00008a064fd50f2all, 0x0000af3addc680b0ll, 0x00008c01467b94bbll,
+  0x0000ae4c415c9883ll, 0x00008df988f4ae80ll, 0x0000ad602b580ad7ll, 0x00008fef1e987409ll,
+  0x0000ac7691840ac8ll, 0x000091e20ea1393ell, 0x0000ab8f69e2835all, 0x000093d2602c2e5fll,
+  0x0000aaaaaaaaaaabll, 0x000095c01a39fbd6ll, 0x0000a9c84a47a080ll, 0x000097ab43af59f9ll,
+  0x0000a8e83f5717c1ll, 0x00009993e355a4e5ll, 0x0000a80a80a80a81ll, 0x00009b79ffdb6c8bll,
+  0x0000a72f0539782all, 0x00009d5d9fd5010bll, 0x0000a655c4392d7cll, 0x00009f3ec9bcfb80ll,
+  0x0000a57eb50295fbll, 0x0000a11d83f4c355ll, 0x0000a4a9cf1d9684ll, 0x0000a2f9d4c51039ll,
+  0x0000a3d70a3d70a4ll, 0x0000a4d3c25e68dcll, 0x0000a3065e3fae7dll, 0x0000a6ab52d99e76ll,
+  0x0000a237c32b16d0ll, 0x0000a8808c384547ll, 0x0000a16b312ea8fdll, 0x0000aa5374652a1cll,
+  0x0000a0a0a0a0a0a1ll, 0x0000ac241134c4e9ll, 0x00009fd809fd80a0ll, 0x0000adf26865a8a1ll,
+  0x00009f1165e72549ll, 0x0000afbe7fa0f04dll, 0x00009e4cad23dd60ll, 0x0000b1885c7aa982ll,
+  0x00009d89d89d89d9ll, 0x0000b35004723c46ll, 0x00009cc8e160c3fcll, 0x0000b5157cf2d078ll,
+  0x00009c09c09c09c1ll, 0x0000b6d8cb53b0call, 0x00009b4c6f9ef03bll, 0x0000b899f4d8ab63ll,
+  0x00009a90e7d95bc7ll, 0x0000ba58feb2703all, 0x000099d722dabde6ll, 0x0000bc15edfeed32ll,
+  0x0000991f1a515886ll, 0x0000bdd0c7c9a817ll, 0x00009868c809868dll, 0x0000bf89910c1678ll,
+  0x000097b425ed097cll, 0x0000c1404eadf383ll, 0x000097012e025c05ll, 0x0000c2f5058593d9ll,
+  0x0000964fda6c0965ll, 0x0000c4a7ba58377cll, 0x000095a02568095bll, 0x0000c65871da59ddll,
+  0x000094f2094f2095ll, 0x0000c80730b00016ll, 0x0000944580944581ll, 0x0000c9b3fb6d0559ll,
+  0x0000939a85c4093all, 0x0000cb5ed69565afll, 0x000092f113840498ll, 0x0000cd07c69d8702ll,
+  0x0000924924924925ll, 0x0000ceaecfea8085ll, 0x000091a2b3c4d5e7ll, 0x0000d053f6d26089ll,
+  0x000090fdbc090fdcll, 0x0000d1f73f9c70c0ll, 0x0000905a38633e07ll, 0x0000d398ae817906ll,
+  0x00008fb823ee08fcll, 0x0000d53847ac00a6ll, 0x00008f1779d9fdc4ll, 0x0000d6d60f388e41ll,
+  0x00008e78356d1409ll, 0x0000d8720935e643ll, 0x00008dda5202376all, 0x0000da0c39a54804ll,
+  0x00008d3dcb08d3ddll, 0x0000dba4a47aa996ll, 0x00008ca29c046515ll, 0x0000dd3b4d9cf24bll,
+  0x00008c08c08c08c1ll, 0x0000ded038e633f3ll, 0x00008b70344a139cll, 0x0000e0636a23e2eell,
+  0x00008ad8f2fba939ll, 0x0000e1f4e5170d02ll, 0x00008a42f870566all, 0x0000e384ad748f0ell,
+  0x000089ae4089ae41ll, 0x0000e512c6e54998ll, 0x0000891ac73ae982ll, 0x0000e69f35065448ll,
+  0x0000888888888889ll, 0x0000e829fb693044ll, 0x000087f78087f781ll, 0x0000e9b31d93f98ell,
+  0x00008767ab5f34e5ll, 0x0000eb3a9f019750ll, 0x000086d905447a35ll, 0x0000ecc08321eb30ll,
+  0x0000864b8a7de6d2ll, 0x0000ee44cd59ffabll, 0x000085bf37612cefll, 0x0000efc781043579ll,
+  0x0000853408534086ll, 0x0000f148a170700all, 0x000084a9f9c8084bll, 0x0000f2c831e44116ll,
+  0x0000842108421085ll, 0x0000f446359b1353ll, 0x0000839930523fbfll, 0x0000f5c2afc65447ll,
+  0x000083126e978d50ll, 0x0000f73da38d9d4all, 0x0000828cbfbeb9a1ll, 0x0000f8b7140edbb1ll,
+  0x0000820820820821ll, 0x0000fa2f045e7832ll, 0x000081848da8faf1ll, 0x0000fba577877d7dll,
+  0x0000810204081021ll, 0x0000fd1a708bbe11ll, 0x0000808080808081ll, 0x0000fe8df263f957ll,
+  0x0000800000000000ll, 0x0000ffff00000000ll,
+  };
+
+
+    // LL_tbl[k] = 2^48*log2(1.0+k/2^15);
+static int64_t __LL_tbl[256] = {
+  0x0000000000000000ull, 0x00000002e2a60a00ull, 0x000000070cb64ec5ull, 0x00000009ef50ce67ull,
+  0x0000000cd1e588fdull, 0x0000000fb4747e9cull, 0x0000001296fdaf5eull, 0x0000001579811b58ull,
+  0x000000185bfec2a1ull, 0x0000001b3e76a552ull, 0x0000001e20e8c380ull, 0x0000002103551d43ull,
+  0x00000023e5bbb2b2ull, 0x00000026c81c83e4ull, 0x00000029aa7790f0ull, 0x0000002c8cccd9edull,
+  0x0000002f6f1c5ef2ull, 0x0000003251662017ull, 0x0000003533aa1d71ull, 0x0000003815e8571aull,
+  0x0000003af820cd26ull, 0x0000003dda537faeull, 0x00000040bc806ec8ull, 0x000000439ea79a8cull,
+  0x0000004680c90310ull, 0x0000004962e4a86cull, 0x0000004c44fa8ab6ull, 0x0000004f270aaa06ull,
+  0x0000005209150672ull, 0x00000054eb19a013ull, 0x00000057cd1876fdull, 0x0000005aaf118b4aull,
+  0x0000005d9104dd0full, 0x0000006072f26c64ull, 0x0000006354da3960ull, 0x0000006636bc441aull,
+  0x0000006918988ca8ull, 0x0000006bfa6f1322ull, 0x0000006edc3fd79full, 0x00000071be0ada35ull,
+  0x000000749fd01afdull, 0x00000077818f9a0cull, 0x0000007a6349577aull, 0x0000007d44fd535eull,
+  0x0000008026ab8dceull, 0x00000083085406e3ull, 0x00000085e9f6beb2ull, 0x00000088cb93b552ull,
+  0x0000008bad2aeadcull, 0x0000008e8ebc5f65ull, 0x0000009170481305ull, 0x0000009451ce05d3ull,
+  0x00000097334e37e5ull, 0x0000009a14c8a953ull, 0x0000009cf63d5a33ull, 0x0000009fd7ac4a9dull,
+  0x000000a2b07f3458ull, 0x000000a59a78ea6aull, 0x000000a87bd699fbull, 0x000000ab5d2e8970ull,
+  0x000000ae3e80b8e3ull, 0x000000b11fcd2869ull, 0x000000b40113d818ull, 0x000000b6e254c80aull,
+  0x000000b9c38ff853ull, 0x000000bca4c5690cull, 0x000000bf85f51a4aull, 0x000000c2671f0c26ull,
+  0x000000c548433eb6ull, 0x000000c82961b211ull, 0x000000cb0a7a664dull, 0x000000cdeb8d5b82ull,
+  0x000000d0cc9a91c8ull, 0x000000d3ada20933ull, 0x000000d68ea3c1ddull, 0x000000d96f9fbbdbull,
+  0x000000dc5095f744ull, 0x000000df31867430ull, 0x000000e2127132b5ull, 0x000000e4f35632eaull,
+  0x000000e7d43574e6ull, 0x000000eab50ef8c1ull, 0x000000ed95e2be90ull, 0x000000f076b0c66cull,
+  0x000000f35779106aull, 0x000000f6383b9ca2ull, 0x000000f918f86b2aull, 0x000000fbf9af7c1aull,
+  0x000000feda60cf88ull, 0x00000101bb0c658cull, 0x000001049bb23e3cull, 0x000001077c5259afull,
+  0x0000010a5cecb7fcull, 0x0000010d3d81593aull, 0x000001101e103d7full, 0x00000112fe9964e4ull,
+  0x00000115df1ccf7eull, 0x00000118bf9a7d64ull, 0x0000011ba0126eadull, 0x0000011e8084a371ull,
+  0x0000012160f11bc6ull, 0x000001244157d7c3ull, 0x0000012721b8d77full, 0x0000012a02141b10ull,
+  0x0000012ce269a28eull, 0x0000012fc2b96e0full, 0x00000132a3037daaull, 0x000001358347d177ull,
+  0x000001386386698cull, 0x0000013b43bf45ffull, 0x0000013e23f266e9ull, 0x00000141041fcc5eull,
+  0x00000143e4477678ull, 0x00000146c469654bull, 0x00000149a48598f0ull, 0x0000014c849c117cull,
+  0x0000014f64accf08ull, 0x0000015244b7d1a9ull, 0x0000015524bd1976ull, 0x0000015804bca687ull,
+  0x0000015ae4b678f2ull, 0x0000015dc4aa90ceull, 0x00000160a498ee31ull, 0x0000016384819134ull,
+  0x00000166646479ecull, 0x000001694441a870ull, 0x0000016c24191cd7ull, 0x0000016df6ca19bdull,
+  0x00000171e3b6d7aaull, 0x00000174c37d1e44ull, 0x00000177a33dab1cull, 0x0000017a82f87e49ull,
+  0x0000017d62ad97e2ull, 0x00000180425cf7feull, 0x00000182b07f3458ull, 0x0000018601aa8c19ull,
+  0x00000188e148c046ull, 0x0000018bc0e13b52ull, 0x0000018ea073fd52ull, 0x000001918001065dull,
+  0x000001945f88568bull, 0x000001973f09edf2ull, 0x0000019a1e85ccaaull, 0x0000019cfdfbf2c8ull,
+  0x0000019fdd6c6063ull, 0x000001a2bcd71593ull, 0x000001a59c3c126eull, 0x000001a87b9b570bull,
+  0x000001ab5af4e380ull, 0x000001ae3a48b7e5ull, 0x000001b11996d450ull, 0x000001b3f8df38d9ull,
+  0x000001b6d821e595ull, 0x000001b9b75eda9bull, 0x000001bc96961803ull, 0x000001bf75c79de3ull,
+  0x000001c254f36c51ull, 0x000001c534198365ull, 0x000001c81339e336ull, 0x000001caf2548bd9ull,
+  0x000001cdd1697d67ull, 0x000001d0b078b7f5ull, 0x000001d38f823b9aull, 0x000001d66e86086dull,
+  0x000001d94d841e86ull, 0x000001dc2c7c7df9ull, 0x000001df0b6f26dfull, 0x000001e1ea5c194eull,
+  0x000001e4c943555dull, 0x000001e7a824db23ull, 0x000001ea8700aab5ull, 0x000001ed65d6c42bull,
+  0x000001f044a7279dull, 0x000001f32371d51full, 0x000001f60236cccaull, 0x000001f8e0f60eb3ull,
+  0x000001fbbfaf9af3ull, 0x000001fe9e63719eull, 0x000002017d1192ccull, 0x000002045bb9fe94ull,
+  0x000002073a5cb50dull, 0x00000209c06e6212ull, 0x0000020cf791026aull, 0x0000020fd622997cull,
+  0x00000212b07f3458ull, 0x000002159334a8d8ull, 0x0000021871b52150ull, 0x0000021b502fe517ull,
+  0x0000021d6a73a78full, 0x000002210d144eeeull, 0x00000223eb7df52cull, 0x00000226c9e1e713ull,
+  0x00000229a84024bbull, 0x0000022c23679b4eull, 0x0000022f64eb83a8ull, 0x000002324338a51bull,
+  0x00000235218012a9ull, 0x00000237ffc1cc69ull, 0x0000023a2c3b0ea4ull, 0x0000023d13ee805bull,
+  0x0000024035e9221full, 0x00000243788faf25ull, 0x0000024656b4e735ull, 0x00000247ed646bfeull,
+  0x0000024c12ee3d98ull, 0x0000024ef1025c1aull, 0x00000251cf10c799ull, 0x0000025492644d65ull,
+  0x000002578b1c85eeull, 0x0000025a6919d8f0ull, 0x0000025d13ee805bull, 0x0000026025036716ull,
+  0x0000026296453882ull, 0x00000265e0d62b53ull, 0x00000268beb701f3ull, 0x0000026b9c92265eull,
+  0x0000026d32f798a9ull, 0x00000271583758ebull, 0x000002743601673bull, 0x0000027713c5c3b0ull,
+  0x00000279f1846e5full, 0x0000027ccf3d6761ull, 0x0000027e6580aecbull, 0x000002828a9e44b3ull,
+  0x0000028568462932ull, 0x00000287bdbf5255ull, 0x0000028b2384de4aull, 0x0000028d13ee805bull,
+  0x0000029035e9221full, 0x0000029296453882ull, 0x0000029699bdfb61ull, 0x0000029902a37aabull,
+  0x0000029c54b864c9ull, 0x0000029deabd1083ull, 0x000002a20f9c0bb5ull, 0x000002a4c7605d61ull,
+  0x000002a7bdbf5255ull, 0x000002a96056dafcull, 0x000002ac3daf14efull, 0x000002af1b019ecaull,
+  0x000002b296453882ull, 0x000002b5d022d80full, 0x000002b8fa471cb3ull, 0x000002ba9012e713ull,
+  0x000002bd6d4901ccull, 0x000002c04a796cf6ull, 0x000002c327a428a6ull, 0x000002c61a5e8f4cull,
+  0x000002c8e1e891f6ull, 0x000002cbbf023fc2ull, 0x000002ce9c163e6eull, 0x000002d179248e13ull,
+  0x000002d4562d2ec6ull, 0x000002d73330209dull, 0x000002da102d63b0ull, 0x000002dced24f814ull,
+};
+
+
+
+
+#endif
index a1ef53c044151be9df2ac4e61e0631226d59f0a8..5b47736d27d94584bf33b2e60af56b5e76fc141c 100644 (file)
@@ -20,7 +20,7 @@
 
 #include <linux/crush/crush.h>
 #include <linux/crush/hash.h>
-#include <linux/crush/mapper.h>
+#include "crush_ln_table.h"
 
 /*
  * Implement the core CRUSH mapping algorithm.
@@ -238,6 +238,102 @@ static int bucket_straw_choose(struct crush_bucket_straw *bucket,
        return bucket->h.items[high];
 }
 
+// compute 2^44*log2(input+1)
+uint64_t crush_ln(unsigned xin)
+{
+    unsigned x=xin, x1;
+    int iexpon, index1, index2;
+    uint64_t RH, LH, LL, xl64, result;
+
+    x++;
+
+    // normalize input
+    iexpon = 15;
+    while(!(x&0x18000)) { x<<=1; iexpon--; }
+
+    index1 = (x>>8)<<1;
+    // RH ~ 2^56/index1
+    RH = __RH_LH_tbl[index1 - 256];
+    // LH ~ 2^48 * log2(index1/256)
+    LH = __RH_LH_tbl[index1 + 1 - 256];
+
+    // RH*x ~ 2^48 * (2^15 + xf), xf<2^8
+    xl64 = (int64_t)x * RH;
+    xl64 >>= 48;
+    x1 = xl64;
+
+    result = iexpon;
+    result <<= (12 + 32);
+
+    index2 = x1 & 0xff;
+    // LL ~ 2^48*log2(1.0+index2/2^15)
+    LL = __LL_tbl[index2];
+
+    LH = LH + LL;
+
+    LH >>= (48-12 - 32);
+    result += LH;
+
+    return result;
+}
+
+
+/*
+ * straw2
+ *
+ * for reference, see:
+ *
+ * http://en.wikipedia.org/wiki/Exponential_distribution#Distribution_of_the_minimum_of_exponential_random_variables
+ *
+ */
+
+static int bucket_straw2_choose(struct crush_bucket_straw2 *bucket,
+                               int x, int r)
+{
+       unsigned i, high = 0;
+       unsigned u;
+       unsigned w;
+       __s64 ln, draw, high_draw = 0;
+
+       for (i = 0; i < bucket->h.size; i++) {
+               w = bucket->item_weights[i];
+               if (w) {
+                       u = crush_hash32_3(bucket->h.hash, x,
+                                          bucket->h.items[i], r);
+                       u &= 0xffff;
+
+                       /*
+                        * for some reason slightly less than 0x10000 produces
+                        * a slightly more accurate distribution... probably a
+                        * rounding effect.
+                        *
+                        * the natural log lookup table maps [0,0xffff]
+                        * (corresponding to real numbers [1/0x10000, 1] to
+                        * [0, 0xffffffffffff] (corresponding to real numbers
+                        * [-11.090355,0]).
+                        */
+                       ln = crush_ln(u) - 0x1000000000000ll;
+
+                       /*
+                        * divide by 16.16 fixed-point weight.  note
+                        * that the ln value is negative, so a larger
+                        * weight means a larger (less negative) value
+                        * for draw.
+                        */
+                       draw = div64_s64(ln, w);
+               } else {
+                       draw = S64_MIN;
+               }
+
+               if (i == 0 || draw > high_draw) {
+                       high = i;
+                       high_draw = draw;
+               }
+       }
+       return bucket->h.items[high];
+}
+
+
 static int crush_bucket_choose(struct crush_bucket *in, int x, int r)
 {
        dprintk(" crush_bucket_choose %d x=%d r=%d\n", in->id, x, r);
@@ -255,12 +351,16 @@ static int crush_bucket_choose(struct crush_bucket *in, int x, int r)
        case CRUSH_BUCKET_STRAW:
                return bucket_straw_choose((struct crush_bucket_straw *)in,
                                           x, r);
+       case CRUSH_BUCKET_STRAW2:
+               return bucket_straw2_choose((struct crush_bucket_straw2 *)in,
+                                           x, r);
        default:
                dprintk("unknown bucket %d alg %d\n", in->id, in->alg);
                return in->items[0];
        }
 }
 
+
 /*
  * true if device is marked "out" (failed, fully offloaded)
  * of the cluster
@@ -290,6 +390,7 @@ static int is_out(const struct crush_map *map,
  * @type: the type of item to choose
  * @out: pointer to output vector
  * @outpos: our position in that vector
+ * @out_size: size of the out vector
  * @tries: number of attempts to make
  * @recurse_tries: number of attempts to have recursive chooseleaf make
  * @local_retries: localized retries
@@ -304,6 +405,7 @@ static int crush_choose_firstn(const struct crush_map *map,
                               const __u32 *weight, int weight_max,
                               int x, int numrep, int type,
                               int *out, int outpos,
+                              int out_size,
                               unsigned int tries,
                               unsigned int recurse_tries,
                               unsigned int local_retries,
@@ -322,6 +424,7 @@ static int crush_choose_firstn(const struct crush_map *map,
        int item = 0;
        int itemtype;
        int collide, reject;
+       int count = out_size;
 
        dprintk("CHOOSE%s bucket %d x %d outpos %d numrep %d tries %d recurse_tries %d local_retries %d local_fallback_retries %d parent_r %d\n",
                recurse_to_leaf ? "_LEAF" : "",
@@ -329,7 +432,7 @@ static int crush_choose_firstn(const struct crush_map *map,
                tries, recurse_tries, local_retries, local_fallback_retries,
                parent_r);
 
-       for (rep = outpos; rep < numrep; rep++) {
+       for (rep = outpos; rep < numrep && count > 0 ; rep++) {
                /* keep trying until we get a non-out, non-colliding item */
                ftotal = 0;
                skip_rep = 0;
@@ -403,7 +506,7 @@ static int crush_choose_firstn(const struct crush_map *map,
                                                         map->buckets[-1-item],
                                                         weight, weight_max,
                                                         x, outpos+1, 0,
-                                                        out2, outpos,
+                                                        out2, outpos, count,
                                                         recurse_tries, 0,
                                                         local_retries,
                                                         local_fallback_retries,
@@ -463,6 +566,7 @@ reject:
                dprintk("CHOOSE got %d\n", item);
                out[outpos] = item;
                outpos++;
+               count--;
        }
 
        dprintk("CHOOSE returns %d\n", outpos);
@@ -654,6 +758,7 @@ int crush_do_rule(const struct crush_map *map,
        __u32 step;
        int i, j;
        int numrep;
+       int out_size;
        /*
         * the original choose_total_tries value was off by one (it
         * counted "retries" and not "tries").  add one.
@@ -761,6 +866,7 @@ int crush_do_rule(const struct crush_map *map,
                                                x, numrep,
                                                curstep->arg2,
                                                o+osize, j,
+                                               result_max-osize,
                                                choose_tries,
                                                recurse_tries,
                                                choose_local_retries,
@@ -770,11 +876,13 @@ int crush_do_rule(const struct crush_map *map,
                                                c+osize,
                                                0);
                                } else {
+                                       out_size = ((numrep < (result_max-osize)) ?
+                                                    numrep : (result_max-osize));
                                        crush_choose_indep(
                                                map,
                                                map->buckets[-1-w[i]],
                                                weight, weight_max,
-                                               x, numrep, numrep,
+                                               x, out_size, numrep,
                                                curstep->arg2,
                                                o+osize, j,
                                                choose_tries,
@@ -783,7 +891,7 @@ int crush_do_rule(const struct crush_map *map,
                                                recurse_to_leaf,
                                                c+osize,
                                                0);
-                                       osize += numrep;
+                                       osize += out_size;
                                }
                        }
 
index 14d9995097cc84ea33f8c6811be18bc3919fcbbd..593dc2eabcc803342187c1e57355f31d76b17f49 100644 (file)
@@ -22,6 +22,7 @@
  *      .../monmap      - current monmap
  *      .../osdc        - active osd requests
  *      .../monc        - mon client state
+ *      .../client_options - libceph-only (i.e. not rbd or cephfs) options
  *      .../dentry_lru  - dump contents of dentry lru
  *      .../caps        - expose cap (reservation) stats
  *      .../bdi         - symlink to ../../bdi/something
@@ -177,10 +178,24 @@ static int osdc_show(struct seq_file *s, void *pp)
        return 0;
 }
 
+static int client_options_show(struct seq_file *s, void *p)
+{
+       struct ceph_client *client = s->private;
+       int ret;
+
+       ret = ceph_print_client_options(s, client);
+       if (ret)
+               return ret;
+
+       seq_putc(s, '\n');
+       return 0;
+}
+
 CEPH_DEFINE_SHOW_FUNC(monmap_show)
 CEPH_DEFINE_SHOW_FUNC(osdmap_show)
 CEPH_DEFINE_SHOW_FUNC(monc_show)
 CEPH_DEFINE_SHOW_FUNC(osdc_show)
+CEPH_DEFINE_SHOW_FUNC(client_options_show)
 
 int ceph_debugfs_init(void)
 {
@@ -242,6 +257,14 @@ int ceph_debugfs_client_init(struct ceph_client *client)
        if (!client->debugfs_osdmap)
                goto out;
 
+       client->debugfs_options = debugfs_create_file("client_options",
+                                       0600,
+                                       client->debugfs_dir,
+                                       client,
+                                       &client_options_show_fops);
+       if (!client->debugfs_options)
+               goto out;
+
        return 0;
 
 out:
@@ -252,6 +275,7 @@ out:
 void ceph_debugfs_client_cleanup(struct ceph_client *client)
 {
        dout("ceph_debugfs_client_cleanup %p\n", client);
+       debugfs_remove(client->debugfs_options);
        debugfs_remove(client->debugfs_osdmap);
        debugfs_remove(client->debugfs_monmap);
        debugfs_remove(client->osdc.debugfs_file);
index a9f4ae45b7fb856295a30a87a6c3701933d2f3f2..967080a9f0436e8575663909572f063ac60440fe 100644 (file)
@@ -505,8 +505,6 @@ static int ceph_tcp_connect(struct ceph_connection *con)
                pr_err("connect %s error %d\n",
                       ceph_pr_addr(&con->peer_addr.in_addr), ret);
                sock_release(sock);
-               con->error_msg = "connect error";
-
                return ret;
        }
 
@@ -2145,12 +2143,10 @@ static int process_connect(struct ceph_connection *con)
                 * to WAIT.  This shouldn't happen if we are the
                 * client.
                 */
-               pr_err("process_connect got WAIT as client\n");
                con->error_msg = "protocol error, got WAIT as client";
                return -1;
 
        default:
-               pr_err("connect protocol error, will retry\n");
                con->error_msg = "protocol error, garbage tag during connect";
                return -1;
        }
@@ -2282,8 +2278,7 @@ static int read_partial_message(struct ceph_connection *con)
 
        crc = crc32c(0, &con->in_hdr, offsetof(struct ceph_msg_header, crc));
        if (cpu_to_le32(crc) != con->in_hdr.crc) {
-               pr_err("read_partial_message bad hdr "
-                      " crc %u != expected %u\n",
+               pr_err("read_partial_message bad hdr crc %u != expected %u\n",
                       crc, con->in_hdr.crc);
                return -EBADMSG;
        }
@@ -2313,7 +2308,7 @@ static int read_partial_message(struct ceph_connection *con)
                pr_err("read_partial_message bad seq %lld expected %lld\n",
                       seq, con->in_seq + 1);
                con->error_msg = "bad message sequence # for incoming message";
-               return -EBADMSG;
+               return -EBADE;
        }
 
        /* allocate message? */
@@ -2660,6 +2655,8 @@ more:
                        switch (ret) {
                        case -EBADMSG:
                                con->error_msg = "bad crc";
+                               /* fall through */
+                       case -EBADE:
                                ret = -EIO;
                                break;
                        case -EIO:
@@ -2838,7 +2835,8 @@ static void con_work(struct work_struct *work)
                if (ret < 0) {
                        if (ret == -EAGAIN)
                                continue;
-                       con->error_msg = "socket error on read";
+                       if (!con->error_msg)
+                               con->error_msg = "socket error on read";
                        fault = true;
                        break;
                }
@@ -2847,7 +2845,8 @@ static void con_work(struct work_struct *work)
                if (ret < 0) {
                        if (ret == -EAGAIN)
                                continue;
-                       con->error_msg = "socket error on write";
+                       if (!con->error_msg)
+                               con->error_msg = "socket error on write";
                        fault = true;
                }
 
@@ -2869,11 +2868,13 @@ static void con_work(struct work_struct *work)
  */
 static void con_fault(struct ceph_connection *con)
 {
-       pr_warn("%s%lld %s %s\n", ENTITY_NAME(con->peer_name),
-               ceph_pr_addr(&con->peer_addr.in_addr), con->error_msg);
        dout("fault %p state %lu to peer %s\n",
             con, con->state, ceph_pr_addr(&con->peer_addr.in_addr));
 
+       pr_warn("%s%lld %s %s\n", ENTITY_NAME(con->peer_name),
+               ceph_pr_addr(&con->peer_addr.in_addr), con->error_msg);
+       con->error_msg = NULL;
+
        WARN_ON(con->state != CON_STATE_CONNECTING &&
               con->state != CON_STATE_NEGOTIATING &&
               con->state != CON_STATE_OPEN);
@@ -3295,8 +3296,8 @@ static int ceph_con_in_msg_alloc(struct ceph_connection *con, int *skip)
                 */
                if (*skip)
                        return 0;
-               con->error_msg = "error allocating memory for incoming message";
 
+               con->error_msg = "error allocating memory for incoming message";
                return -ENOMEM;
        }
        memcpy(&con->in_msg->hdr, &con->in_hdr, sizeof(con->in_hdr));
index b8c3fde5b04f4e7539ba80a0e36ce4654352a71d..15796696d64ede6b6a3118f5077972bed0c64350 100644 (file)
@@ -122,6 +122,22 @@ bad:
        return -EINVAL;
 }
 
+static int crush_decode_straw2_bucket(void **p, void *end,
+                                     struct crush_bucket_straw2 *b)
+{
+       int j;
+       dout("crush_decode_straw2_bucket %p to %p\n", *p, end);
+       b->item_weights = kcalloc(b->h.size, sizeof(u32), GFP_NOFS);
+       if (b->item_weights == NULL)
+               return -ENOMEM;
+       ceph_decode_need(p, end, b->h.size * sizeof(u32), bad);
+       for (j = 0; j < b->h.size; j++)
+               b->item_weights[j] = ceph_decode_32(p);
+       return 0;
+bad:
+       return -EINVAL;
+}
+
 static int skip_name_map(void **p, void *end)
 {
         int len;
@@ -204,6 +220,9 @@ static struct crush_map *crush_decode(void *pbyval, void *end)
                case CRUSH_BUCKET_STRAW:
                        size = sizeof(struct crush_bucket_straw);
                        break;
+               case CRUSH_BUCKET_STRAW2:
+                       size = sizeof(struct crush_bucket_straw2);
+                       break;
                default:
                        err = -EINVAL;
                        goto bad;
@@ -261,6 +280,12 @@ static struct crush_map *crush_decode(void *pbyval, void *end)
                        if (err < 0)
                                goto bad;
                        break;
+               case CRUSH_BUCKET_STRAW2:
+                       err = crush_decode_straw2_bucket(p, end,
+                               (struct crush_bucket_straw2 *)b);
+                       if (err < 0)
+                               goto bad;
+                       break;
                }
        }
 
index 1796cef55ab5af93718047604c554475b4d3275b..c7ba0388f1be8e37e780f27e0b3bd95f45dd0ade 100644 (file)
@@ -3079,7 +3079,7 @@ static struct rps_dev_flow *
 set_rps_cpu(struct net_device *dev, struct sk_buff *skb,
            struct rps_dev_flow *rflow, u16 next_cpu)
 {
-       if (next_cpu != RPS_NO_CPU) {
+       if (next_cpu < nr_cpu_ids) {
 #ifdef CONFIG_RFS_ACCEL
                struct netdev_rx_queue *rxqueue;
                struct rps_dev_flow_table *flow_table;
@@ -3184,7 +3184,7 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb,
                 * If the desired CPU (where last recvmsg was done) is
                 * different from current CPU (one in the rx-queue flow
                 * table entry), switch if one of the following holds:
-                *   - Current CPU is unset (equal to RPS_NO_CPU).
+                *   - Current CPU is unset (>= nr_cpu_ids).
                 *   - Current CPU is offline.
                 *   - The current CPU's queue tail has advanced beyond the
                 *     last packet that was enqueued using this table entry.
@@ -3192,14 +3192,14 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb,
                 *     have been dequeued, thus preserving in order delivery.
                 */
                if (unlikely(tcpu != next_cpu) &&
-                   (tcpu == RPS_NO_CPU || !cpu_online(tcpu) ||
+                   (tcpu >= nr_cpu_ids || !cpu_online(tcpu) ||
                     ((int)(per_cpu(softnet_data, tcpu).input_queue_head -
                      rflow->last_qtail)) >= 0)) {
                        tcpu = next_cpu;
                        rflow = set_rps_cpu(dev, skb, rflow, next_cpu);
                }
 
-               if (tcpu != RPS_NO_CPU && cpu_online(tcpu)) {
+               if (tcpu < nr_cpu_ids && cpu_online(tcpu)) {
                        *rflowp = rflow;
                        cpu = tcpu;
                        goto done;
@@ -3240,14 +3240,14 @@ bool rps_may_expire_flow(struct net_device *dev, u16 rxq_index,
        struct rps_dev_flow_table *flow_table;
        struct rps_dev_flow *rflow;
        bool expire = true;
-       int cpu;
+       unsigned int cpu;
 
        rcu_read_lock();
        flow_table = rcu_dereference(rxqueue->rps_flow_table);
        if (flow_table && flow_id <= flow_table->mask) {
                rflow = &flow_table->flows[flow_id];
                cpu = ACCESS_ONCE(rflow->cpu);
-               if (rflow->filter == filter_id && cpu != RPS_NO_CPU &&
+               if (rflow->filter == filter_id && cpu < nr_cpu_ids &&
                    ((int)(per_cpu(softnet_data, cpu).input_queue_head -
                           rflow->last_qtail) <
                     (int)(10 * flow_table->mask)))
index 358d52a38533b90d8df212de6636ca8e2525730b..666e0928ba404b85cf210749e505a2c205e5ee3f 100644 (file)
@@ -2854,7 +2854,7 @@ static int brport_nla_put_flag(struct sk_buff *skb, u32 flags, u32 mask,
 
 int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
                            struct net_device *dev, u16 mode,
-                           u32 flags, u32 mask)
+                           u32 flags, u32 mask, int nlflags)
 {
        struct nlmsghdr *nlh;
        struct ifinfomsg *ifm;
@@ -2863,7 +2863,7 @@ int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
        u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN;
        struct net_device *br_dev = netdev_master_upper_dev_get(dev);
 
-       nlh = nlmsg_put(skb, pid, seq, RTM_NEWLINK, sizeof(*ifm), NLM_F_MULTI);
+       nlh = nlmsg_put(skb, pid, seq, RTM_NEWLINK, sizeof(*ifm), nlflags);
        if (nlh == NULL)
                return -EMSGSIZE;
 
@@ -2969,7 +2969,8 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)
                if (br_dev && br_dev->netdev_ops->ndo_bridge_getlink) {
                        if (idx >= cb->args[0] &&
                            br_dev->netdev_ops->ndo_bridge_getlink(
-                                   skb, portid, seq, dev, filter_mask) < 0)
+                                   skb, portid, seq, dev, filter_mask,
+                                   NLM_F_MULTI) < 0)
                                break;
                        idx++;
                }
@@ -2977,7 +2978,8 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)
                if (ops->ndo_bridge_getlink) {
                        if (idx >= cb->args[0] &&
                            ops->ndo_bridge_getlink(skb, portid, seq, dev,
-                                                   filter_mask) < 0)
+                                                   filter_mask,
+                                                   NLM_F_MULTI) < 0)
                                break;
                        idx++;
                }
@@ -3018,7 +3020,7 @@ static int rtnl_bridge_notify(struct net_device *dev)
                goto errout;
        }
 
-       err = dev->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev, 0);
+       err = dev->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev, 0, 0);
        if (err < 0)
                goto errout;
 
index d1967dab9cc697a4dad45838e1a94c2b5f9cf147..3cfff2a3d651fb7d7cd2baaa3698c123eb7fc00f 100644 (file)
@@ -280,13 +280,14 @@ nodata:
 EXPORT_SYMBOL(__alloc_skb);
 
 /**
- * build_skb - build a network buffer
+ * __build_skb - build a network buffer
  * @data: data buffer provided by caller
- * @frag_size: size of fragment, or 0 if head was kmalloced
+ * @frag_size: size of data, or 0 if head was kmalloced
  *
  * Allocate a new &sk_buff. Caller provides space holding head and
  * skb_shared_info. @data must have been allocated by kmalloc() only if
- * @frag_size is 0, otherwise data should come from the page allocator.
+ * @frag_size is 0, otherwise data should come from the page allocator
+ *  or vmalloc()
  * The return is the new skb buffer.
  * On a failure the return is %NULL, and @data is not freed.
  * Notes :
@@ -297,7 +298,7 @@ EXPORT_SYMBOL(__alloc_skb);
  *  before giving packet to stack.
  *  RX rings only contains data buffers, not full skbs.
  */
-struct sk_buff *build_skb(void *data, unsigned int frag_size)
+struct sk_buff *__build_skb(void *data, unsigned int frag_size)
 {
        struct skb_shared_info *shinfo;
        struct sk_buff *skb;
@@ -311,7 +312,6 @@ struct sk_buff *build_skb(void *data, unsigned int frag_size)
 
        memset(skb, 0, offsetof(struct sk_buff, tail));
        skb->truesize = SKB_TRUESIZE(size);
-       skb->head_frag = frag_size != 0;
        atomic_set(&skb->users, 1);
        skb->head = data;
        skb->data = data;
@@ -328,6 +328,23 @@ struct sk_buff *build_skb(void *data, unsigned int frag_size)
 
        return skb;
 }
+
+/* build_skb() is wrapper over __build_skb(), that specifically
+ * takes care of skb->head and skb->pfmemalloc
+ * This means that if @frag_size is not zero, then @data must be backed
+ * by a page fragment, not kmalloc() or vmalloc()
+ */
+struct sk_buff *build_skb(void *data, unsigned int frag_size)
+{
+       struct sk_buff *skb = __build_skb(data, frag_size);
+
+       if (skb && frag_size) {
+               skb->head_frag = 1;
+               if (virt_to_head_page(data)->pfmemalloc)
+                       skb->pfmemalloc = 1;
+       }
+       return skb;
+}
 EXPORT_SYMBOL(build_skb);
 
 struct netdev_alloc_cache {
@@ -348,7 +365,8 @@ static struct page *__page_frag_refill(struct netdev_alloc_cache *nc,
        gfp_t gfp = gfp_mask;
 
        if (order) {
-               gfp_mask |= __GFP_COMP | __GFP_NOWARN | __GFP_NORETRY;
+               gfp_mask |= __GFP_COMP | __GFP_NOWARN | __GFP_NORETRY |
+                           __GFP_NOMEMALLOC;
                page = alloc_pages_node(NUMA_NO_NODE, gfp_mask, order);
                nc->frag.size = PAGE_SIZE << (page ? order : 0);
        }
index 2b4f21d34df6819c134b590d8ddeecffe668aaf6..ccf4c5629b3c8672f348a3ca29b0b6bd46cc23e8 100644 (file)
@@ -453,7 +453,8 @@ static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
                                                       iph->saddr, iph->daddr);
        if (req) {
                nsk = dccp_check_req(sk, skb, req);
-               reqsk_put(req);
+               if (!nsk)
+                       reqsk_put(req);
                return nsk;
        }
        nsk = inet_lookup_established(sock_net(sk), &dccp_hashinfo,
index 9d0551092c6cd73f3cfa30c89130bac69d693118..5165571f397aa6d40da19d36287ca8339852ab54 100644 (file)
@@ -301,7 +301,8 @@ static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
                                   &iph->daddr, inet6_iif(skb));
        if (req) {
                nsk = dccp_check_req(sk, skb, req);
-               reqsk_put(req);
+               if (!nsk)
+                       reqsk_put(req);
                return nsk;
        }
        nsk = __inet6_lookup_established(sock_net(sk), &dccp_hashinfo,
index 5f566663e47f3faa8025a998b2d8ae976db58860..30addee2dd037f9686c5585243e503632dcdd21a 100644 (file)
@@ -186,8 +186,7 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
        if (child == NULL)
                goto listen_overflow;
 
-       inet_csk_reqsk_queue_unlink(sk, req);
-       inet_csk_reqsk_queue_removed(sk, req);
+       inet_csk_reqsk_queue_drop(sk, req);
        inet_csk_reqsk_queue_add(sk, req, child);
 out:
        return child;
index 079a224471e7e20641079e9f54f82743c0172165..e6f6cc3a1bcf45ee6fa49d6cfe840f58660e3511 100644 (file)
@@ -633,7 +633,7 @@ static int dsa_of_probe(struct device *dev)
                if (cd->sw_addr > PHY_MAX_ADDR)
                        continue;
 
-               if (!of_property_read_u32(np, "eeprom-length", &eeprom_len))
+               if (!of_property_read_u32(child, "eeprom-length", &eeprom_len))
                        cd->eeprom_len = eeprom_len;
 
                for_each_available_child_of_node(child, port) {
index 5c3dd6267ed3557f2f139f83002fd7b1feaab237..8976ca423a074447f0d857973ab9ea3bc6bbca7c 100644 (file)
@@ -564,6 +564,40 @@ int inet_rtx_syn_ack(struct sock *parent, struct request_sock *req)
 }
 EXPORT_SYMBOL(inet_rtx_syn_ack);
 
+/* return true if req was found in the syn_table[] */
+static bool reqsk_queue_unlink(struct request_sock_queue *queue,
+                              struct request_sock *req)
+{
+       struct listen_sock *lopt = queue->listen_opt;
+       struct request_sock **prev;
+       bool found = false;
+
+       spin_lock(&queue->syn_wait_lock);
+
+       for (prev = &lopt->syn_table[req->rsk_hash]; *prev != NULL;
+            prev = &(*prev)->dl_next) {
+               if (*prev == req) {
+                       *prev = req->dl_next;
+                       found = true;
+                       break;
+               }
+       }
+
+       spin_unlock(&queue->syn_wait_lock);
+       if (del_timer(&req->rsk_timer))
+               reqsk_put(req);
+       return found;
+}
+
+void inet_csk_reqsk_queue_drop(struct sock *sk, struct request_sock *req)
+{
+       if (reqsk_queue_unlink(&inet_csk(sk)->icsk_accept_queue, req)) {
+               reqsk_queue_removed(&inet_csk(sk)->icsk_accept_queue, req);
+               reqsk_put(req);
+       }
+}
+EXPORT_SYMBOL(inet_csk_reqsk_queue_drop);
+
 static void reqsk_timer_handler(unsigned long data)
 {
        struct request_sock *req = (struct request_sock *)data;
index 939992c456f3bb0d1505c6d4e9af8cc5b4da1ecc..3674484946a5abeb14ff4d11dc9b7666458f8128 100644 (file)
@@ -82,6 +82,9 @@ int ip_forward(struct sk_buff *skb)
        if (skb->pkt_type != PACKET_HOST)
                goto drop;
 
+       if (unlikely(skb->sk))
+               goto drop;
+
        if (skb_warn_if_lro(skb))
                goto drop;
 
index a93f260cf24ca0a9d60346dc085eb51afdb43927..05ff44b758dfee1e02996a3726ac63854a96ad16 100644 (file)
@@ -158,6 +158,7 @@ void ping_unhash(struct sock *sk)
        if (sk_hashed(sk)) {
                write_lock_bh(&ping_table.lock);
                hlist_nulls_del(&sk->sk_nulls_node);
+               sk_nulls_node_init(&sk->sk_nulls_node);
                sock_put(sk);
                isk->inet_num = 0;
                isk->inet_sport = 0;
index a78540f28276771e4c8f35024d3ee133c31317ab..bff62fc87b8e266dbee59d43359fea8a77e29d60 100644 (file)
@@ -962,10 +962,7 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
        if (dst_metric_locked(dst, RTAX_MTU))
                return;
 
-       if (dst->dev->mtu < mtu)
-               return;
-
-       if (rt->rt_pmtu && rt->rt_pmtu < mtu)
+       if (ipv4_mtu(dst) < mtu)
                return;
 
        if (mtu < ip_rt_min_pmtu)
index 59c8a027721b2d7dcd8b8631a1ed686b530b4241..8c5cd9efebbcfa877fedb49dda67e3d098ccbbc1 100644 (file)
@@ -520,8 +520,10 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
 
                                /* Race breaker. If space is freed after
                                 * wspace test but before the flags are set,
-                                * IO signal will be lost.
+                                * IO signal will be lost. Memory barrier
+                                * pairs with the input side.
                                 */
+                               smp_mb__after_atomic();
                                if (sk_stream_is_writeable(sk))
                                        mask |= POLLOUT | POLLWRNORM;
                        }
index a7ef679dd3ea434e5b3bda48d391e1a872ed2478..3a4d9b34bed44a2f6b77b2be0e753867bad32292 100644 (file)
@@ -4845,6 +4845,8 @@ static void tcp_check_space(struct sock *sk)
 {
        if (sock_flag(sk, SOCK_QUEUE_SHRUNK)) {
                sock_reset_flag(sk, SOCK_QUEUE_SHRUNK);
+               /* pairs with tcp_poll() */
+               smp_mb__after_atomic();
                if (sk->sk_socket &&
                    test_bit(SOCK_NOSPACE, &sk->sk_socket->flags))
                        tcp_new_space(sk);
index 3571f2be4470749b9a7c8178fa43a6bf2bac33d8..fc1c658ec6c18cb1daa1cc06039a9f19df67bb5e 100644 (file)
@@ -1348,7 +1348,8 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
        req = inet_csk_search_req(sk, th->source, iph->saddr, iph->daddr);
        if (req) {
                nsk = tcp_check_req(sk, skb, req, false);
-               reqsk_put(req);
+               if (!nsk)
+                       reqsk_put(req);
                return nsk;
        }
 
index 63d6311b5365944fae0bdaa0f7abfbc51f55a429..e5d7649136fcb31ca70b097dcbd9873df07e7417 100644 (file)
@@ -755,10 +755,11 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
        if (!child)
                goto listen_overflow;
 
-       inet_csk_reqsk_queue_unlink(sk, req);
-       inet_csk_reqsk_queue_removed(sk, req);
-
+       inet_csk_reqsk_queue_drop(sk, req);
        inet_csk_reqsk_queue_add(sk, req, child);
+       /* Warning: caller must not call reqsk_put(req);
+        * child stole last reference on it.
+        */
        return child;
 
 listen_overflow:
index 8c8d7e06b72fc1e5c4a50ca55136757f0501f8c0..a369e8a70b2c775bfee94d7f329ee892c2cdc895 100644 (file)
@@ -2812,39 +2812,65 @@ begin_fwd:
        }
 }
 
-/* Send a fin.  The caller locks the socket for us.  This cannot be
- * allowed to fail queueing a FIN frame under any circumstances.
+/* We allow to exceed memory limits for FIN packets to expedite
+ * connection tear down and (memory) recovery.
+ * Otherwise tcp_send_fin() could be tempted to either delay FIN
+ * or even be forced to close flow without any FIN.
+ */
+static void sk_forced_wmem_schedule(struct sock *sk, int size)
+{
+       int amt, status;
+
+       if (size <= sk->sk_forward_alloc)
+               return;
+       amt = sk_mem_pages(size);
+       sk->sk_forward_alloc += amt * SK_MEM_QUANTUM;
+       sk_memory_allocated_add(sk, amt, &status);
+}
+
+/* Send a FIN. The caller locks the socket for us.
+ * We should try to send a FIN packet really hard, but eventually give up.
  */
 void tcp_send_fin(struct sock *sk)
 {
+       struct sk_buff *skb, *tskb = tcp_write_queue_tail(sk);
        struct tcp_sock *tp = tcp_sk(sk);
-       struct sk_buff *skb = tcp_write_queue_tail(sk);
-       int mss_now;
 
-       /* Optimization, tack on the FIN if we have a queue of
-        * unsent frames.  But be careful about outgoing SACKS
-        * and IP options.
+       /* Optimization, tack on the FIN if we have one skb in write queue and
+        * this skb was not yet sent, or we are under memory pressure.
+        * Note: in the latter case, FIN packet will be sent after a timeout,
+        * as TCP stack thinks it has already been transmitted.
         */
-       mss_now = tcp_current_mss(sk);
-
-       if (tcp_send_head(sk)) {
-               TCP_SKB_CB(skb)->tcp_flags |= TCPHDR_FIN;
-               TCP_SKB_CB(skb)->end_seq++;
+       if (tskb && (tcp_send_head(sk) || sk_under_memory_pressure(sk))) {
+coalesce:
+               TCP_SKB_CB(tskb)->tcp_flags |= TCPHDR_FIN;
+               TCP_SKB_CB(tskb)->end_seq++;
                tp->write_seq++;
+               if (!tcp_send_head(sk)) {
+                       /* This means tskb was already sent.
+                        * Pretend we included the FIN on previous transmit.
+                        * We need to set tp->snd_nxt to the value it would have
+                        * if FIN had been sent. This is because retransmit path
+                        * does not change tp->snd_nxt.
+                        */
+                       tp->snd_nxt++;
+                       return;
+               }
        } else {
-               /* Socket is locked, keep trying until memory is available. */
-               for (;;) {
-                       skb = sk_stream_alloc_skb(sk, 0, sk->sk_allocation);
-                       if (skb)
-                               break;
-                       yield();
+               skb = alloc_skb_fclone(MAX_TCP_HEADER, sk->sk_allocation);
+               if (unlikely(!skb)) {
+                       if (tskb)
+                               goto coalesce;
+                       return;
                }
+               skb_reserve(skb, MAX_TCP_HEADER);
+               sk_forced_wmem_schedule(sk, skb->truesize);
                /* FIN eats a sequence byte, write_seq advanced by tcp_queue_skb(). */
                tcp_init_nondata_skb(skb, tp->write_seq,
                                     TCPHDR_ACK | TCPHDR_FIN);
                tcp_queue_skb(sk, skb);
        }
-       __tcp_push_pending_frames(sk, mss_now, TCP_NAGLE_OFF);
+       __tcp_push_pending_frames(sk, tcp_current_mss(sk), TCP_NAGLE_OFF);
 }
 
 /* We get here when a process closes a file descriptor (either due to
index b5e6cc1d4a7302f3288ba00ee9c75bb327410960..a38d3ac0f18f6e631e3a17904bf617f7a0dfe28a 100644 (file)
@@ -1246,7 +1246,6 @@ static void ip6gre_tunnel_setup(struct net_device *dev)
 static int ip6gre_tunnel_init(struct net_device *dev)
 {
        struct ip6_tnl *tunnel;
-       int i;
 
        tunnel = netdev_priv(dev);
 
@@ -1260,16 +1259,10 @@ static int ip6gre_tunnel_init(struct net_device *dev)
        if (ipv6_addr_any(&tunnel->parms.raddr))
                dev->header_ops = &ip6gre_header_ops;
 
-       dev->tstats = alloc_percpu(struct pcpu_sw_netstats);
+       dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
        if (!dev->tstats)
                return -ENOMEM;
 
-       for_each_possible_cpu(i) {
-               struct pcpu_sw_netstats *ip6gre_tunnel_stats;
-               ip6gre_tunnel_stats = per_cpu_ptr(dev->tstats, i);
-               u64_stats_init(&ip6gre_tunnel_stats->syncp);
-       }
-
        return 0;
 }
 
index ad51df85aa00dda56b86dca24ed5fe9a3b5c791e..b6575d6655681e8e84993a5db929c7309d47d4d3 100644 (file)
@@ -946,7 +946,8 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk, struct sk_buff *skb)
                                   &ipv6_hdr(skb)->daddr, tcp_v6_iif(skb));
        if (req) {
                nsk = tcp_check_req(sk, skb, req, false);
-               reqsk_put(req);
+               if (!nsk)
+                       reqsk_put(req);
                return nsk;
        }
        nsk = __inet6_lookup_established(sock_net(sk), &tcp_hashinfo,
index db8a2ea6d4de5bb2b4b92785d2e6a05a7613b0f3..954810c76a8650d87ec4bddc62fa5618e48c1341 100644 (file)
@@ -53,6 +53,11 @@ static struct mpls_route *mpls_route_input_rcu(struct net *net, unsigned index)
        return rt;
 }
 
+static inline struct mpls_dev *mpls_dev_get(const struct net_device *dev)
+{
+       return rcu_dereference_rtnl(dev->mpls_ptr);
+}
+
 static bool mpls_output_possible(const struct net_device *dev)
 {
        return dev && (dev->flags & IFF_UP) && netif_carrier_ok(dev);
@@ -136,6 +141,7 @@ static int mpls_forward(struct sk_buff *skb, struct net_device *dev,
        struct mpls_route *rt;
        struct mpls_entry_decoded dec;
        struct net_device *out_dev;
+       struct mpls_dev *mdev;
        unsigned int hh_len;
        unsigned int new_header_size;
        unsigned int mtu;
@@ -143,6 +149,10 @@ static int mpls_forward(struct sk_buff *skb, struct net_device *dev,
 
        /* Careful this entire function runs inside of an rcu critical section */
 
+       mdev = mpls_dev_get(dev);
+       if (!mdev || !mdev->input_enabled)
+               goto drop;
+
        if (skb->pkt_type != PACKET_HOST)
                goto drop;
 
@@ -352,9 +362,9 @@ static int mpls_route_add(struct mpls_route_config *cfg)
        if (!dev)
                goto errout;
 
-       /* For now just support ethernet devices */
+       /* Ensure this is a supported device */
        err = -EINVAL;
-       if ((dev->type != ARPHRD_ETHER) && (dev->type != ARPHRD_LOOPBACK))
+       if (!mpls_dev_get(dev))
                goto errout;
 
        err = -EINVAL;
@@ -428,10 +438,89 @@ errout:
        return err;
 }
 
+#define MPLS_PERDEV_SYSCTL_OFFSET(field)       \
+       (&((struct mpls_dev *)0)->field)
+
+static const struct ctl_table mpls_dev_table[] = {
+       {
+               .procname       = "input",
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec,
+               .data           = MPLS_PERDEV_SYSCTL_OFFSET(input_enabled),
+       },
+       { }
+};
+
+static int mpls_dev_sysctl_register(struct net_device *dev,
+                                   struct mpls_dev *mdev)
+{
+       char path[sizeof("net/mpls/conf/") + IFNAMSIZ];
+       struct ctl_table *table;
+       int i;
+
+       table = kmemdup(&mpls_dev_table, sizeof(mpls_dev_table), GFP_KERNEL);
+       if (!table)
+               goto out;
+
+       /* Table data contains only offsets relative to the base of
+        * the mdev at this point, so make them absolute.
+        */
+       for (i = 0; i < ARRAY_SIZE(mpls_dev_table); i++)
+               table[i].data = (char *)mdev + (uintptr_t)table[i].data;
+
+       snprintf(path, sizeof(path), "net/mpls/conf/%s", dev->name);
+
+       mdev->sysctl = register_net_sysctl(dev_net(dev), path, table);
+       if (!mdev->sysctl)
+               goto free;
+
+       return 0;
+
+free:
+       kfree(table);
+out:
+       return -ENOBUFS;
+}
+
+static void mpls_dev_sysctl_unregister(struct mpls_dev *mdev)
+{
+       struct ctl_table *table;
+
+       table = mdev->sysctl->ctl_table_arg;
+       unregister_net_sysctl_table(mdev->sysctl);
+       kfree(table);
+}
+
+static struct mpls_dev *mpls_add_dev(struct net_device *dev)
+{
+       struct mpls_dev *mdev;
+       int err = -ENOMEM;
+
+       ASSERT_RTNL();
+
+       mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
+       if (!mdev)
+               return ERR_PTR(err);
+
+       err = mpls_dev_sysctl_register(dev, mdev);
+       if (err)
+               goto free;
+
+       rcu_assign_pointer(dev->mpls_ptr, mdev);
+
+       return mdev;
+
+free:
+       kfree(mdev);
+       return ERR_PTR(err);
+}
+
 static void mpls_ifdown(struct net_device *dev)
 {
        struct mpls_route __rcu **platform_label;
        struct net *net = dev_net(dev);
+       struct mpls_dev *mdev;
        unsigned index;
 
        platform_label = rtnl_dereference(net->mpls.platform_label);
@@ -443,14 +532,35 @@ static void mpls_ifdown(struct net_device *dev)
                        continue;
                rt->rt_dev = NULL;
        }
+
+       mdev = mpls_dev_get(dev);
+       if (!mdev)
+               return;
+
+       mpls_dev_sysctl_unregister(mdev);
+
+       RCU_INIT_POINTER(dev->mpls_ptr, NULL);
+
+       kfree(mdev);
 }
 
 static int mpls_dev_notify(struct notifier_block *this, unsigned long event,
                           void *ptr)
 {
        struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+       struct mpls_dev *mdev;
 
        switch(event) {
+       case NETDEV_REGISTER:
+               /* For now just support ethernet devices */
+               if ((dev->type == ARPHRD_ETHER) ||
+                   (dev->type == ARPHRD_LOOPBACK)) {
+                       mdev = mpls_add_dev(dev);
+                       if (IS_ERR(mdev))
+                               return notifier_from_errno(PTR_ERR(mdev));
+               }
+               break;
+
        case NETDEV_UNREGISTER:
                mpls_ifdown(dev);
                break;
@@ -536,6 +646,15 @@ int nla_get_labels(const struct nlattr *nla,
                if ((dec.bos != bos) || dec.ttl || dec.tc)
                        return -EINVAL;
 
+               switch (dec.label) {
+               case LABEL_IMPLICIT_NULL:
+                       /* RFC3032: This is a label that an LSR may
+                        * assign and distribute, but which never
+                        * actually appears in the encapsulation.
+                        */
+                       return -EINVAL;
+               }
+
                label[i] = dec.label;
        }
        *labels = nla_labels;
@@ -912,7 +1031,7 @@ static int mpls_platform_labels(struct ctl_table *table, int write,
        return ret;
 }
 
-static struct ctl_table mpls_table[] = {
+static const struct ctl_table mpls_table[] = {
        {
                .procname       = "platform_labels",
                .data           = NULL,
index fb6de92052c4bc87db6c83ba5288f2f921e13c62..693877d69606a1ecdab02dd78dc74eefdaf26f3f 100644 (file)
@@ -22,6 +22,12 @@ struct mpls_entry_decoded {
        u8 bos;
 };
 
+struct mpls_dev {
+       int                     input_enabled;
+
+       struct ctl_table_header *sysctl;
+};
+
 struct sk_buff;
 
 static inline struct mpls_shim_hdr *mpls_hdr(const struct sk_buff *skb)
index 78af83bc9c8e8dbfcead6e151247a127602ac107..ad9d11fb29fd208cd44d67e786b7977afc9e51e7 100644 (file)
@@ -4340,7 +4340,6 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
        case NFT_CONTINUE:
        case NFT_BREAK:
        case NFT_RETURN:
-               desc->len = sizeof(data->verdict);
                break;
        case NFT_JUMP:
        case NFT_GOTO:
@@ -4355,10 +4354,10 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
 
                chain->use++;
                data->verdict.chain = chain;
-               desc->len = sizeof(data);
                break;
        }
 
+       desc->len = sizeof(data->verdict);
        desc->type = NFT_DATA_VERDICT;
        return 0;
 }
index 57d3e1af56305e90eade03e1fca1b38524091be6..0522fc9bfb0a88db513c480f45dff35a6f233000 100644 (file)
@@ -63,6 +63,8 @@ int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr)
                if (nla_put_u8(skb, NFTA_REJECT_ICMP_CODE, priv->icmp_code))
                        goto nla_put_failure;
                break;
+       default:
+               break;
        }
 
        return 0;
index 62cabee42fbecc93587a0b008b19913a5a8470f9..635dbba93d013244038cbdbb48bbe9549f622304 100644 (file)
@@ -108,6 +108,8 @@ static int nft_reject_inet_dump(struct sk_buff *skb,
                if (nla_put_u8(skb, NFTA_REJECT_ICMP_CODE, priv->icmp_code))
                        goto nla_put_failure;
                break;
+       default:
+               break;
        }
 
        return 0;
index 19909d0786a2e60574ba623d343193ca212ed2be..ec4adbdcb9b4a9926b4d992906f51787c57dc6a2 100644 (file)
@@ -1629,13 +1629,11 @@ static struct sk_buff *netlink_alloc_large_skb(unsigned int size,
        if (data == NULL)
                return NULL;
 
-       skb = build_skb(data, size);
+       skb = __build_skb(data, size);
        if (skb == NULL)
                vfree(data);
-       else {
-               skb->head_frag = 0;
+       else
                skb->destructor = netlink_skb_destructor;
-       }
 
        return skb;
 }
index 8e472518f9f6856dcd5802c16373b6579f7284eb..295d14bd6c678c31b56219371df83d4ebe3b0a2c 100644 (file)
@@ -63,7 +63,6 @@ static int tcf_connmark(struct sk_buff *skb, const struct tc_action *a,
                skb->mark = c->mark;
                /* using overlimits stats to count how many packets marked */
                ca->tcf_qstats.overlimits++;
-               nf_ct_put(c);
                goto out;
        }
 
@@ -82,7 +81,6 @@ static int tcf_connmark(struct sk_buff *skb, const struct tc_action *a,
        nf_ct_put(c);
 
 out:
-       skb->nfct = NULL;
        spin_unlock(&ca->tcf_lock);
        return ca->tcf_action;
 }
index 3e33959f3ce5711863fca7ce1805a4d1cf4ed6e0..884e3299769840c3e05c43f1320ba849a10ad73c 100644 (file)
@@ -312,7 +312,7 @@ static const struct super_operations sockfs_ops = {
 static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen)
 {
        return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]",
-                               dentry->d_inode->i_ino);
+                               d_inode(dentry)->i_ino);
 }
 
 static const struct dentry_operations sockfs_dentry_operations = {
@@ -375,7 +375,7 @@ struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
                  &socket_file_ops);
        if (unlikely(IS_ERR(file))) {
                /* drop dentry, keep inode */
-               ihold(path.dentry->d_inode);
+               ihold(d_inode(path.dentry));
                path_put(&path);
                return file;
        }
@@ -497,7 +497,7 @@ static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
        ssize_t len;
        ssize_t used = 0;
 
-       len = security_inode_listsecurity(dentry->d_inode, buffer, size);
+       len = security_inode_listsecurity(d_inode(dentry), buffer, size);
        if (len < 0)
                return len;
        used += len;
index 2d12b76b5a64f958e4fa8f45ffaeea00a5d857a9..d81186d34558c8c206c65bc5d05f36977734aafd 100644 (file)
@@ -94,7 +94,7 @@ rpc_timeout_upcall_queue(struct work_struct *work)
        }
        dentry = dget(pipe->dentry);
        spin_unlock(&pipe->lock);
-       rpc_purge_list(dentry ? &RPC_I(dentry->d_inode)->waitq : NULL,
+       rpc_purge_list(dentry ? &RPC_I(d_inode(dentry))->waitq : NULL,
                        &free_list, destroy_msg, -ETIMEDOUT);
        dput(dentry);
 }
@@ -152,7 +152,7 @@ rpc_queue_upcall(struct rpc_pipe *pipe, struct rpc_pipe_msg *msg)
        dentry = dget(pipe->dentry);
        spin_unlock(&pipe->lock);
        if (dentry) {
-               wake_up(&RPC_I(dentry->d_inode)->waitq);
+               wake_up(&RPC_I(d_inode(dentry))->waitq);
                dput(dentry);
        }
        return res;
@@ -591,7 +591,7 @@ static int __rpc_mkpipe_dentry(struct inode *dir, struct dentry *dentry,
        err = __rpc_create_common(dir, dentry, S_IFIFO | mode, i_fop, private);
        if (err)
                return err;
-       rpci = RPC_I(dentry->d_inode);
+       rpci = RPC_I(d_inode(dentry));
        rpci->private = private;
        rpci->pipe = pipe;
        fsnotify_create(dir, dentry);
@@ -616,7 +616,7 @@ int rpc_rmdir(struct dentry *dentry)
        int error;
 
        parent = dget_parent(dentry);
-       dir = parent->d_inode;
+       dir = d_inode(parent);
        mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
        error = __rpc_rmdir(dir, dentry);
        mutex_unlock(&dir->i_mutex);
@@ -638,7 +638,7 @@ static int __rpc_unlink(struct inode *dir, struct dentry *dentry)
 
 static int __rpc_rmpipe(struct inode *dir, struct dentry *dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_inode(dentry);
 
        rpc_close_pipes(inode);
        return __rpc_unlink(dir, dentry);
@@ -654,7 +654,7 @@ static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent,
                if (!dentry)
                        return ERR_PTR(-ENOMEM);
        }
-       if (dentry->d_inode == NULL)
+       if (d_really_is_negative(dentry))
                return dentry;
        dput(dentry);
        return ERR_PTR(-EEXIST);
@@ -667,7 +667,7 @@ static void __rpc_depopulate(struct dentry *parent,
                             const struct rpc_filelist *files,
                             int start, int eof)
 {
-       struct inode *dir = parent->d_inode;
+       struct inode *dir = d_inode(parent);
        struct dentry *dentry;
        struct qstr name;
        int i;
@@ -679,9 +679,9 @@ static void __rpc_depopulate(struct dentry *parent,
 
                if (dentry == NULL)
                        continue;
-               if (dentry->d_inode == NULL)
+               if (d_really_is_negative(dentry))
                        goto next;
-               switch (dentry->d_inode->i_mode & S_IFMT) {
+               switch (d_inode(dentry)->i_mode & S_IFMT) {
                        default:
                                BUG();
                        case S_IFREG:
@@ -699,7 +699,7 @@ static void rpc_depopulate(struct dentry *parent,
                           const struct rpc_filelist *files,
                           int start, int eof)
 {
-       struct inode *dir = parent->d_inode;
+       struct inode *dir = d_inode(parent);
 
        mutex_lock_nested(&dir->i_mutex, I_MUTEX_CHILD);
        __rpc_depopulate(parent, files, start, eof);
@@ -711,7 +711,7 @@ static int rpc_populate(struct dentry *parent,
                        int start, int eof,
                        void *private)
 {
-       struct inode *dir = parent->d_inode;
+       struct inode *dir = d_inode(parent);
        struct dentry *dentry;
        int i, err;
 
@@ -754,7 +754,7 @@ static struct dentry *rpc_mkdir_populate(struct dentry *parent,
                int (*populate)(struct dentry *, void *), void *args_populate)
 {
        struct dentry *dentry;
-       struct inode *dir = parent->d_inode;
+       struct inode *dir = d_inode(parent);
        int error;
 
        mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
@@ -787,7 +787,7 @@ static int rpc_rmdir_depopulate(struct dentry *dentry,
        int error;
 
        parent = dget_parent(dentry);
-       dir = parent->d_inode;
+       dir = d_inode(parent);
        mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
        if (depopulate != NULL)
                depopulate(dentry);
@@ -819,7 +819,7 @@ struct dentry *rpc_mkpipe_dentry(struct dentry *parent, const char *name,
                                 void *private, struct rpc_pipe *pipe)
 {
        struct dentry *dentry;
-       struct inode *dir = parent->d_inode;
+       struct inode *dir = d_inode(parent);
        umode_t umode = S_IFIFO | S_IRUSR | S_IWUSR;
        int err;
 
@@ -864,7 +864,7 @@ rpc_unlink(struct dentry *dentry)
        int error = 0;
 
        parent = dget_parent(dentry);
-       dir = parent->d_inode;
+       dir = d_inode(parent);
        mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
        error = __rpc_rmpipe(dir, dentry);
        mutex_unlock(&dir->i_mutex);
@@ -1375,7 +1375,7 @@ rpc_gssd_dummy_depopulate(struct dentry *pipe_dentry)
        struct dentry *clnt_dir = pipe_dentry->d_parent;
        struct dentry *gssd_dir = clnt_dir->d_parent;
 
-       __rpc_rmpipe(clnt_dir->d_inode, pipe_dentry);
+       __rpc_rmpipe(d_inode(clnt_dir), pipe_dentry);
        __rpc_depopulate(clnt_dir, gssd_dummy_info_file, 0, 1);
        __rpc_depopulate(gssd_dir, gssd_dummy_clnt_dir, 0, 1);
        dput(pipe_dentry);
index b91fd9c597b45158cc9ce88a8fb4caa5130faf96..337ca851a350cc412532ff4d3c96d87a8605e785 100644 (file)
@@ -89,8 +89,8 @@ __rpc_add_timer(struct rpc_wait_queue *queue, struct rpc_task *task)
        if (!task->tk_timeout)
                return;
 
-       dprintk("RPC: %5u setting alarm for %lu ms\n",
-                       task->tk_pid, task->tk_timeout * 1000 / HZ);
+       dprintk("RPC: %5u setting alarm for %u ms\n",
+               task->tk_pid, jiffies_to_msecs(task->tk_timeout));
 
        task->u.tk_wait.expires = jiffies + task->tk_timeout;
        if (list_empty(&queue->timer_list.list) || time_before(task->u.tk_wait.expires, queue->timer_list.expires))
index 9949722d99cebf6afa15953d8a9ac6a5c0bc2824..1d4fe24af06a1115bd80538c5346ae2f843f1eb8 100644 (file)
@@ -326,6 +326,15 @@ out_unlock:
        xprt_clear_locked(xprt);
 }
 
+static void xprt_task_clear_bytes_sent(struct rpc_task *task)
+{
+       if (task != NULL) {
+               struct rpc_rqst *req = task->tk_rqstp;
+               if (req != NULL)
+                       req->rq_bytes_sent = 0;
+       }
+}
+
 /**
  * xprt_release_xprt - allow other requests to use a transport
  * @xprt: transport with other tasks potentially waiting
@@ -336,11 +345,7 @@ out_unlock:
 void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task)
 {
        if (xprt->snd_task == task) {
-               if (task != NULL) {
-                       struct rpc_rqst *req = task->tk_rqstp;
-                       if (req != NULL)
-                               req->rq_bytes_sent = 0;
-               }
+               xprt_task_clear_bytes_sent(task);
                xprt_clear_locked(xprt);
                __xprt_lock_write_next(xprt);
        }
@@ -358,11 +363,7 @@ EXPORT_SYMBOL_GPL(xprt_release_xprt);
 void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task)
 {
        if (xprt->snd_task == task) {
-               if (task != NULL) {
-                       struct rpc_rqst *req = task->tk_rqstp;
-                       if (req != NULL)
-                               req->rq_bytes_sent = 0;
-               }
+               xprt_task_clear_bytes_sent(task);
                xprt_clear_locked(xprt);
                __xprt_lock_write_next_cong(xprt);
        }
@@ -700,6 +701,7 @@ bool xprt_lock_connect(struct rpc_xprt *xprt,
                goto out;
        if (xprt->snd_task != task)
                goto out;
+       xprt_task_clear_bytes_sent(task);
        xprt->snd_task = cookie;
        ret = true;
 out:
index da5136fd56943fa91e20946d2a89346c3da556b2..579f72bbcf4ba66eb58b7c9cfde0bde812c996e2 100644 (file)
@@ -1,6 +1,7 @@
 obj-$(CONFIG_SUNRPC_XPRT_RDMA_CLIENT) += xprtrdma.o
 
-xprtrdma-y := transport.o rpc_rdma.o verbs.o
+xprtrdma-y := transport.o rpc_rdma.o verbs.o \
+       fmr_ops.o frwr_ops.o physical_ops.o
 
 obj-$(CONFIG_SUNRPC_XPRT_RDMA_SERVER) += svcrdma.o
 
diff --git a/net/sunrpc/xprtrdma/fmr_ops.c b/net/sunrpc/xprtrdma/fmr_ops.c
new file mode 100644 (file)
index 0000000..302d4eb
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2015 Oracle.  All rights reserved.
+ * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved.
+ */
+
+/* Lightweight memory registration using Fast Memory Regions (FMR).
+ * Referred to sometimes as MTHCAFMR mode.
+ *
+ * FMR uses synchronous memory registration and deregistration.
+ * FMR registration is known to be fast, but FMR deregistration
+ * can take tens of usecs to complete.
+ */
+
+#include "xprt_rdma.h"
+
+#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
+# define RPCDBG_FACILITY       RPCDBG_TRANS
+#endif
+
+/* Maximum scatter/gather per FMR */
+#define RPCRDMA_MAX_FMR_SGES   (64)
+
+static int
+fmr_op_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep,
+           struct rpcrdma_create_data_internal *cdata)
+{
+       return 0;
+}
+
+/* FMR mode conveys up to 64 pages of payload per chunk segment.
+ */
+static size_t
+fmr_op_maxpages(struct rpcrdma_xprt *r_xprt)
+{
+       return min_t(unsigned int, RPCRDMA_MAX_DATA_SEGS,
+                    rpcrdma_max_segments(r_xprt) * RPCRDMA_MAX_FMR_SGES);
+}
+
+static int
+fmr_op_init(struct rpcrdma_xprt *r_xprt)
+{
+       struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
+       int mr_access_flags = IB_ACCESS_REMOTE_WRITE | IB_ACCESS_REMOTE_READ;
+       struct ib_fmr_attr fmr_attr = {
+               .max_pages      = RPCRDMA_MAX_FMR_SGES,
+               .max_maps       = 1,
+               .page_shift     = PAGE_SHIFT
+       };
+       struct ib_pd *pd = r_xprt->rx_ia.ri_pd;
+       struct rpcrdma_mw *r;
+       int i, rc;
+
+       INIT_LIST_HEAD(&buf->rb_mws);
+       INIT_LIST_HEAD(&buf->rb_all);
+
+       i = (buf->rb_max_requests + 1) * RPCRDMA_MAX_SEGS;
+       dprintk("RPC:       %s: initializing %d FMRs\n", __func__, i);
+
+       while (i--) {
+               r = kzalloc(sizeof(*r), GFP_KERNEL);
+               if (!r)
+                       return -ENOMEM;
+
+               r->r.fmr = ib_alloc_fmr(pd, mr_access_flags, &fmr_attr);
+               if (IS_ERR(r->r.fmr))
+                       goto out_fmr_err;
+
+               list_add(&r->mw_list, &buf->rb_mws);
+               list_add(&r->mw_all, &buf->rb_all);
+       }
+       return 0;
+
+out_fmr_err:
+       rc = PTR_ERR(r->r.fmr);
+       dprintk("RPC:       %s: ib_alloc_fmr status %i\n", __func__, rc);
+       kfree(r);
+       return rc;
+}
+
+/* Use the ib_map_phys_fmr() verb to register a memory region
+ * for remote access via RDMA READ or RDMA WRITE.
+ */
+static int
+fmr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg,
+          int nsegs, bool writing)
+{
+       struct rpcrdma_ia *ia = &r_xprt->rx_ia;
+       struct ib_device *device = ia->ri_id->device;
+       enum dma_data_direction direction = rpcrdma_data_dir(writing);
+       struct rpcrdma_mr_seg *seg1 = seg;
+       struct rpcrdma_mw *mw = seg1->rl_mw;
+       u64 physaddrs[RPCRDMA_MAX_DATA_SEGS];
+       int len, pageoff, i, rc;
+
+       pageoff = offset_in_page(seg1->mr_offset);
+       seg1->mr_offset -= pageoff;     /* start of page */
+       seg1->mr_len += pageoff;
+       len = -pageoff;
+       if (nsegs > RPCRDMA_MAX_FMR_SGES)
+               nsegs = RPCRDMA_MAX_FMR_SGES;
+       for (i = 0; i < nsegs;) {
+               rpcrdma_map_one(device, seg, direction);
+               physaddrs[i] = seg->mr_dma;
+               len += seg->mr_len;
+               ++seg;
+               ++i;
+               /* Check for holes */
+               if ((i < nsegs && offset_in_page(seg->mr_offset)) ||
+                   offset_in_page((seg-1)->mr_offset + (seg-1)->mr_len))
+                       break;
+       }
+
+       rc = ib_map_phys_fmr(mw->r.fmr, physaddrs, i, seg1->mr_dma);
+       if (rc)
+               goto out_maperr;
+
+       seg1->mr_rkey = mw->r.fmr->rkey;
+       seg1->mr_base = seg1->mr_dma + pageoff;
+       seg1->mr_nsegs = i;
+       seg1->mr_len = len;
+       return i;
+
+out_maperr:
+       dprintk("RPC:       %s: ib_map_phys_fmr %u@0x%llx+%i (%d) status %i\n",
+               __func__, len, (unsigned long long)seg1->mr_dma,
+               pageoff, i, rc);
+       while (i--)
+               rpcrdma_unmap_one(device, --seg);
+       return rc;
+}
+
+/* Use the ib_unmap_fmr() verb to prevent further remote
+ * access via RDMA READ or RDMA WRITE.
+ */
+static int
+fmr_op_unmap(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg)
+{
+       struct rpcrdma_ia *ia = &r_xprt->rx_ia;
+       struct rpcrdma_mr_seg *seg1 = seg;
+       struct ib_device *device;
+       int rc, nsegs = seg->mr_nsegs;
+       LIST_HEAD(l);
+
+       list_add(&seg1->rl_mw->r.fmr->list, &l);
+       rc = ib_unmap_fmr(&l);
+       read_lock(&ia->ri_qplock);
+       device = ia->ri_id->device;
+       while (seg1->mr_nsegs--)
+               rpcrdma_unmap_one(device, seg++);
+       read_unlock(&ia->ri_qplock);
+       if (rc)
+               goto out_err;
+       return nsegs;
+
+out_err:
+       dprintk("RPC:       %s: ib_unmap_fmr status %i\n", __func__, rc);
+       return nsegs;
+}
+
+/* After a disconnect, unmap all FMRs.
+ *
+ * This is invoked only in the transport connect worker in order
+ * to serialize with rpcrdma_register_fmr_external().
+ */
+static void
+fmr_op_reset(struct rpcrdma_xprt *r_xprt)
+{
+       struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
+       struct rpcrdma_mw *r;
+       LIST_HEAD(list);
+       int rc;
+
+       list_for_each_entry(r, &buf->rb_all, mw_all)
+               list_add(&r->r.fmr->list, &list);
+
+       rc = ib_unmap_fmr(&list);
+       if (rc)
+               dprintk("RPC:       %s: ib_unmap_fmr failed %i\n",
+                       __func__, rc);
+}
+
+static void
+fmr_op_destroy(struct rpcrdma_buffer *buf)
+{
+       struct rpcrdma_mw *r;
+       int rc;
+
+       while (!list_empty(&buf->rb_all)) {
+               r = list_entry(buf->rb_all.next, struct rpcrdma_mw, mw_all);
+               list_del(&r->mw_all);
+               rc = ib_dealloc_fmr(r->r.fmr);
+               if (rc)
+                       dprintk("RPC:       %s: ib_dealloc_fmr failed %i\n",
+                               __func__, rc);
+               kfree(r);
+       }
+}
+
+const struct rpcrdma_memreg_ops rpcrdma_fmr_memreg_ops = {
+       .ro_map                         = fmr_op_map,
+       .ro_unmap                       = fmr_op_unmap,
+       .ro_open                        = fmr_op_open,
+       .ro_maxpages                    = fmr_op_maxpages,
+       .ro_init                        = fmr_op_init,
+       .ro_reset                       = fmr_op_reset,
+       .ro_destroy                     = fmr_op_destroy,
+       .ro_displayname                 = "fmr",
+};
diff --git a/net/sunrpc/xprtrdma/frwr_ops.c b/net/sunrpc/xprtrdma/frwr_ops.c
new file mode 100644 (file)
index 0000000..dff0481
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * Copyright (c) 2015 Oracle.  All rights reserved.
+ * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved.
+ */
+
+/* Lightweight memory registration using Fast Registration Work
+ * Requests (FRWR). Also referred to sometimes as FRMR mode.
+ *
+ * FRWR features ordered asynchronous registration and deregistration
+ * of arbitrarily sized memory regions. This is the fastest and safest
+ * but most complex memory registration mode.
+ */
+
+#include "xprt_rdma.h"
+
+#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
+# define RPCDBG_FACILITY       RPCDBG_TRANS
+#endif
+
+static int
+__frwr_init(struct rpcrdma_mw *r, struct ib_pd *pd, struct ib_device *device,
+           unsigned int depth)
+{
+       struct rpcrdma_frmr *f = &r->r.frmr;
+       int rc;
+
+       f->fr_mr = ib_alloc_fast_reg_mr(pd, depth);
+       if (IS_ERR(f->fr_mr))
+               goto out_mr_err;
+       f->fr_pgl = ib_alloc_fast_reg_page_list(device, depth);
+       if (IS_ERR(f->fr_pgl))
+               goto out_list_err;
+       return 0;
+
+out_mr_err:
+       rc = PTR_ERR(f->fr_mr);
+       dprintk("RPC:       %s: ib_alloc_fast_reg_mr status %i\n",
+               __func__, rc);
+       return rc;
+
+out_list_err:
+       rc = PTR_ERR(f->fr_pgl);
+       dprintk("RPC:       %s: ib_alloc_fast_reg_page_list status %i\n",
+               __func__, rc);
+       ib_dereg_mr(f->fr_mr);
+       return rc;
+}
+
+static void
+__frwr_release(struct rpcrdma_mw *r)
+{
+       int rc;
+
+       rc = ib_dereg_mr(r->r.frmr.fr_mr);
+       if (rc)
+               dprintk("RPC:       %s: ib_dereg_mr status %i\n",
+                       __func__, rc);
+       ib_free_fast_reg_page_list(r->r.frmr.fr_pgl);
+}
+
+static int
+frwr_op_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep,
+            struct rpcrdma_create_data_internal *cdata)
+{
+       struct ib_device_attr *devattr = &ia->ri_devattr;
+       int depth, delta;
+
+       ia->ri_max_frmr_depth =
+                       min_t(unsigned int, RPCRDMA_MAX_DATA_SEGS,
+                             devattr->max_fast_reg_page_list_len);
+       dprintk("RPC:       %s: device's max FR page list len = %u\n",
+               __func__, ia->ri_max_frmr_depth);
+
+       /* Add room for frmr register and invalidate WRs.
+        * 1. FRMR reg WR for head
+        * 2. FRMR invalidate WR for head
+        * 3. N FRMR reg WRs for pagelist
+        * 4. N FRMR invalidate WRs for pagelist
+        * 5. FRMR reg WR for tail
+        * 6. FRMR invalidate WR for tail
+        * 7. The RDMA_SEND WR
+        */
+       depth = 7;
+
+       /* Calculate N if the device max FRMR depth is smaller than
+        * RPCRDMA_MAX_DATA_SEGS.
+        */
+       if (ia->ri_max_frmr_depth < RPCRDMA_MAX_DATA_SEGS) {
+               delta = RPCRDMA_MAX_DATA_SEGS - ia->ri_max_frmr_depth;
+               do {
+                       depth += 2; /* FRMR reg + invalidate */
+                       delta -= ia->ri_max_frmr_depth;
+               } while (delta > 0);
+       }
+
+       ep->rep_attr.cap.max_send_wr *= depth;
+       if (ep->rep_attr.cap.max_send_wr > devattr->max_qp_wr) {
+               cdata->max_requests = devattr->max_qp_wr / depth;
+               if (!cdata->max_requests)
+                       return -EINVAL;
+               ep->rep_attr.cap.max_send_wr = cdata->max_requests *
+                                              depth;
+       }
+
+       return 0;
+}
+
+/* FRWR mode conveys a list of pages per chunk segment. The
+ * maximum length of that list is the FRWR page list depth.
+ */
+static size_t
+frwr_op_maxpages(struct rpcrdma_xprt *r_xprt)
+{
+       struct rpcrdma_ia *ia = &r_xprt->rx_ia;
+
+       return min_t(unsigned int, RPCRDMA_MAX_DATA_SEGS,
+                    rpcrdma_max_segments(r_xprt) * ia->ri_max_frmr_depth);
+}
+
+/* If FAST_REG or LOCAL_INV failed, indicate the frmr needs to be reset. */
+static void
+frwr_sendcompletion(struct ib_wc *wc)
+{
+       struct rpcrdma_mw *r;
+
+       if (likely(wc->status == IB_WC_SUCCESS))
+               return;
+
+       /* WARNING: Only wr_id and status are reliable at this point */
+       r = (struct rpcrdma_mw *)(unsigned long)wc->wr_id;
+       dprintk("RPC:       %s: frmr %p (stale), status %d\n",
+               __func__, r, wc->status);
+       r->r.frmr.fr_state = FRMR_IS_STALE;
+}
+
+static int
+frwr_op_init(struct rpcrdma_xprt *r_xprt)
+{
+       struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
+       struct ib_device *device = r_xprt->rx_ia.ri_id->device;
+       unsigned int depth = r_xprt->rx_ia.ri_max_frmr_depth;
+       struct ib_pd *pd = r_xprt->rx_ia.ri_pd;
+       int i;
+
+       INIT_LIST_HEAD(&buf->rb_mws);
+       INIT_LIST_HEAD(&buf->rb_all);
+
+       i = (buf->rb_max_requests + 1) * RPCRDMA_MAX_SEGS;
+       dprintk("RPC:       %s: initializing %d FRMRs\n", __func__, i);
+
+       while (i--) {
+               struct rpcrdma_mw *r;
+               int rc;
+
+               r = kzalloc(sizeof(*r), GFP_KERNEL);
+               if (!r)
+                       return -ENOMEM;
+
+               rc = __frwr_init(r, pd, device, depth);
+               if (rc) {
+                       kfree(r);
+                       return rc;
+               }
+
+               list_add(&r->mw_list, &buf->rb_mws);
+               list_add(&r->mw_all, &buf->rb_all);
+               r->mw_sendcompletion = frwr_sendcompletion;
+       }
+
+       return 0;
+}
+
+/* Post a FAST_REG Work Request to register a memory region
+ * for remote access via RDMA READ or RDMA WRITE.
+ */
+static int
+frwr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg,
+           int nsegs, bool writing)
+{
+       struct rpcrdma_ia *ia = &r_xprt->rx_ia;
+       struct ib_device *device = ia->ri_id->device;
+       enum dma_data_direction direction = rpcrdma_data_dir(writing);
+       struct rpcrdma_mr_seg *seg1 = seg;
+       struct rpcrdma_mw *mw = seg1->rl_mw;
+       struct rpcrdma_frmr *frmr = &mw->r.frmr;
+       struct ib_mr *mr = frmr->fr_mr;
+       struct ib_send_wr fastreg_wr, *bad_wr;
+       u8 key;
+       int len, pageoff;
+       int i, rc;
+       int seg_len;
+       u64 pa;
+       int page_no;
+
+       pageoff = offset_in_page(seg1->mr_offset);
+       seg1->mr_offset -= pageoff;     /* start of page */
+       seg1->mr_len += pageoff;
+       len = -pageoff;
+       if (nsegs > ia->ri_max_frmr_depth)
+               nsegs = ia->ri_max_frmr_depth;
+       for (page_no = i = 0; i < nsegs;) {
+               rpcrdma_map_one(device, seg, direction);
+               pa = seg->mr_dma;
+               for (seg_len = seg->mr_len; seg_len > 0; seg_len -= PAGE_SIZE) {
+                       frmr->fr_pgl->page_list[page_no++] = pa;
+                       pa += PAGE_SIZE;
+               }
+               len += seg->mr_len;
+               ++seg;
+               ++i;
+               /* Check for holes */
+               if ((i < nsegs && offset_in_page(seg->mr_offset)) ||
+                   offset_in_page((seg-1)->mr_offset + (seg-1)->mr_len))
+                       break;
+       }
+       dprintk("RPC:       %s: Using frmr %p to map %d segments (%d bytes)\n",
+               __func__, mw, i, len);
+
+       frmr->fr_state = FRMR_IS_VALID;
+
+       memset(&fastreg_wr, 0, sizeof(fastreg_wr));
+       fastreg_wr.wr_id = (unsigned long)(void *)mw;
+       fastreg_wr.opcode = IB_WR_FAST_REG_MR;
+       fastreg_wr.wr.fast_reg.iova_start = seg1->mr_dma + pageoff;
+       fastreg_wr.wr.fast_reg.page_list = frmr->fr_pgl;
+       fastreg_wr.wr.fast_reg.page_shift = PAGE_SHIFT;
+       fastreg_wr.wr.fast_reg.page_list_len = page_no;
+       fastreg_wr.wr.fast_reg.length = len;
+       fastreg_wr.wr.fast_reg.access_flags = writing ?
+                               IB_ACCESS_REMOTE_WRITE | IB_ACCESS_LOCAL_WRITE :
+                               IB_ACCESS_REMOTE_READ;
+       key = (u8)(mr->rkey & 0x000000FF);
+       ib_update_fast_reg_key(mr, ++key);
+       fastreg_wr.wr.fast_reg.rkey = mr->rkey;
+
+       DECR_CQCOUNT(&r_xprt->rx_ep);
+       rc = ib_post_send(ia->ri_id->qp, &fastreg_wr, &bad_wr);
+       if (rc)
+               goto out_senderr;
+
+       seg1->mr_rkey = mr->rkey;
+       seg1->mr_base = seg1->mr_dma + pageoff;
+       seg1->mr_nsegs = i;
+       seg1->mr_len = len;
+       return i;
+
+out_senderr:
+       dprintk("RPC:       %s: ib_post_send status %i\n", __func__, rc);
+       ib_update_fast_reg_key(mr, --key);
+       frmr->fr_state = FRMR_IS_INVALID;
+       while (i--)
+               rpcrdma_unmap_one(device, --seg);
+       return rc;
+}
+
+/* Post a LOCAL_INV Work Request to prevent further remote access
+ * via RDMA READ or RDMA WRITE.
+ */
+static int
+frwr_op_unmap(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg)
+{
+       struct rpcrdma_mr_seg *seg1 = seg;
+       struct rpcrdma_ia *ia = &r_xprt->rx_ia;
+       struct ib_send_wr invalidate_wr, *bad_wr;
+       int rc, nsegs = seg->mr_nsegs;
+       struct ib_device *device;
+
+       seg1->rl_mw->r.frmr.fr_state = FRMR_IS_INVALID;
+
+       memset(&invalidate_wr, 0, sizeof(invalidate_wr));
+       invalidate_wr.wr_id = (unsigned long)(void *)seg1->rl_mw;
+       invalidate_wr.opcode = IB_WR_LOCAL_INV;
+       invalidate_wr.ex.invalidate_rkey = seg1->rl_mw->r.frmr.fr_mr->rkey;
+       DECR_CQCOUNT(&r_xprt->rx_ep);
+
+       read_lock(&ia->ri_qplock);
+       device = ia->ri_id->device;
+       while (seg1->mr_nsegs--)
+               rpcrdma_unmap_one(device, seg++);
+       rc = ib_post_send(ia->ri_id->qp, &invalidate_wr, &bad_wr);
+       read_unlock(&ia->ri_qplock);
+       if (rc)
+               goto out_err;
+       return nsegs;
+
+out_err:
+       /* Force rpcrdma_buffer_get() to retry */
+       seg1->rl_mw->r.frmr.fr_state = FRMR_IS_STALE;
+       dprintk("RPC:       %s: ib_post_send status %i\n", __func__, rc);
+       return nsegs;
+}
+
+/* After a disconnect, a flushed FAST_REG_MR can leave an FRMR in
+ * an unusable state. Find FRMRs in this state and dereg / reg
+ * each.  FRMRs that are VALID and attached to an rpcrdma_req are
+ * also torn down.
+ *
+ * This gives all in-use FRMRs a fresh rkey and leaves them INVALID.
+ *
+ * This is invoked only in the transport connect worker in order
+ * to serialize with rpcrdma_register_frmr_external().
+ */
+static void
+frwr_op_reset(struct rpcrdma_xprt *r_xprt)
+{
+       struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
+       struct ib_device *device = r_xprt->rx_ia.ri_id->device;
+       unsigned int depth = r_xprt->rx_ia.ri_max_frmr_depth;
+       struct ib_pd *pd = r_xprt->rx_ia.ri_pd;
+       struct rpcrdma_mw *r;
+       int rc;
+
+       list_for_each_entry(r, &buf->rb_all, mw_all) {
+               if (r->r.frmr.fr_state == FRMR_IS_INVALID)
+                       continue;
+
+               __frwr_release(r);
+               rc = __frwr_init(r, pd, device, depth);
+               if (rc) {
+                       dprintk("RPC:       %s: mw %p left %s\n",
+                               __func__, r,
+                               (r->r.frmr.fr_state == FRMR_IS_STALE ?
+                                       "stale" : "valid"));
+                       continue;
+               }
+
+               r->r.frmr.fr_state = FRMR_IS_INVALID;
+       }
+}
+
+static void
+frwr_op_destroy(struct rpcrdma_buffer *buf)
+{
+       struct rpcrdma_mw *r;
+
+       while (!list_empty(&buf->rb_all)) {
+               r = list_entry(buf->rb_all.next, struct rpcrdma_mw, mw_all);
+               list_del(&r->mw_all);
+               __frwr_release(r);
+               kfree(r);
+       }
+}
+
+const struct rpcrdma_memreg_ops rpcrdma_frwr_memreg_ops = {
+       .ro_map                         = frwr_op_map,
+       .ro_unmap                       = frwr_op_unmap,
+       .ro_open                        = frwr_op_open,
+       .ro_maxpages                    = frwr_op_maxpages,
+       .ro_init                        = frwr_op_init,
+       .ro_reset                       = frwr_op_reset,
+       .ro_destroy                     = frwr_op_destroy,
+       .ro_displayname                 = "frwr",
+};
diff --git a/net/sunrpc/xprtrdma/physical_ops.c b/net/sunrpc/xprtrdma/physical_ops.c
new file mode 100644 (file)
index 0000000..ba518af
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2015 Oracle.  All rights reserved.
+ * Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved.
+ */
+
+/* No-op chunk preparation. All client memory is pre-registered.
+ * Sometimes referred to as ALLPHYSICAL mode.
+ *
+ * Physical registration is simple because all client memory is
+ * pre-registered and never deregistered. This mode is good for
+ * adapter bring up, but is considered not safe: the server is
+ * trusted not to abuse its access to client memory not involved
+ * in RDMA I/O.
+ */
+
+#include "xprt_rdma.h"
+
+#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
+# define RPCDBG_FACILITY       RPCDBG_TRANS
+#endif
+
+static int
+physical_op_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep,
+                struct rpcrdma_create_data_internal *cdata)
+{
+       return 0;
+}
+
+/* PHYSICAL memory registration conveys one page per chunk segment.
+ */
+static size_t
+physical_op_maxpages(struct rpcrdma_xprt *r_xprt)
+{
+       return min_t(unsigned int, RPCRDMA_MAX_DATA_SEGS,
+                    rpcrdma_max_segments(r_xprt));
+}
+
+static int
+physical_op_init(struct rpcrdma_xprt *r_xprt)
+{
+       return 0;
+}
+
+/* The client's physical memory is already exposed for
+ * remote access via RDMA READ or RDMA WRITE.
+ */
+static int
+physical_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg,
+               int nsegs, bool writing)
+{
+       struct rpcrdma_ia *ia = &r_xprt->rx_ia;
+
+       rpcrdma_map_one(ia->ri_id->device, seg,
+                       rpcrdma_data_dir(writing));
+       seg->mr_rkey = ia->ri_bind_mem->rkey;
+       seg->mr_base = seg->mr_dma;
+       seg->mr_nsegs = 1;
+       return 1;
+}
+
+/* Unmap a memory region, but leave it registered.
+ */
+static int
+physical_op_unmap(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg)
+{
+       struct rpcrdma_ia *ia = &r_xprt->rx_ia;
+
+       read_lock(&ia->ri_qplock);
+       rpcrdma_unmap_one(ia->ri_id->device, seg);
+       read_unlock(&ia->ri_qplock);
+
+       return 1;
+}
+
+static void
+physical_op_reset(struct rpcrdma_xprt *r_xprt)
+{
+}
+
+static void
+physical_op_destroy(struct rpcrdma_buffer *buf)
+{
+}
+
+const struct rpcrdma_memreg_ops rpcrdma_physical_memreg_ops = {
+       .ro_map                         = physical_op_map,
+       .ro_unmap                       = physical_op_unmap,
+       .ro_open                        = physical_op_open,
+       .ro_maxpages                    = physical_op_maxpages,
+       .ro_init                        = physical_op_init,
+       .ro_reset                       = physical_op_reset,
+       .ro_destroy                     = physical_op_destroy,
+       .ro_displayname                 = "physical",
+};
index 91ffde82fa0c49eba3e11385aec9e334eb6b699a..2c53ea9e1b83dae01ebdd1aa22d256174dfbae08 100644 (file)
 # define RPCDBG_FACILITY       RPCDBG_TRANS
 #endif
 
+enum rpcrdma_chunktype {
+       rpcrdma_noch = 0,
+       rpcrdma_readch,
+       rpcrdma_areadch,
+       rpcrdma_writech,
+       rpcrdma_replych
+};
+
 #if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
 static const char transfertypes[][12] = {
        "pure inline",  /* no chunks */
@@ -179,6 +187,7 @@ rpcrdma_create_chunks(struct rpc_rqst *rqst, struct xdr_buf *target,
        struct rpcrdma_write_array *warray = NULL;
        struct rpcrdma_write_chunk *cur_wchunk = NULL;
        __be32 *iptr = headerp->rm_body.rm_chunks;
+       int (*map)(struct rpcrdma_xprt *, struct rpcrdma_mr_seg *, int, bool);
 
        if (type == rpcrdma_readch || type == rpcrdma_areadch) {
                /* a read chunk - server will RDMA Read our memory */
@@ -201,9 +210,9 @@ rpcrdma_create_chunks(struct rpc_rqst *rqst, struct xdr_buf *target,
        if (nsegs < 0)
                return nsegs;
 
+       map = r_xprt->rx_ia.ri_ops->ro_map;
        do {
-               n = rpcrdma_register_external(seg, nsegs,
-                                               cur_wchunk != NULL, r_xprt);
+               n = map(r_xprt, seg, nsegs, cur_wchunk != NULL);
                if (n <= 0)
                        goto out;
                if (cur_rchunk) {       /* read */
@@ -275,34 +284,13 @@ rpcrdma_create_chunks(struct rpc_rqst *rqst, struct xdr_buf *target,
        return (unsigned char *)iptr - (unsigned char *)headerp;
 
 out:
-       if (r_xprt->rx_ia.ri_memreg_strategy != RPCRDMA_FRMR) {
-               for (pos = 0; nchunks--;)
-                       pos += rpcrdma_deregister_external(
-                                       &req->rl_segments[pos], r_xprt);
-       }
-       return n;
-}
+       if (r_xprt->rx_ia.ri_memreg_strategy == RPCRDMA_FRMR)
+               return n;
 
-/*
- * Marshal chunks. This routine returns the header length
- * consumed by marshaling.
- *
- * Returns positive RPC/RDMA header size, or negative errno.
- */
-
-ssize_t
-rpcrdma_marshal_chunks(struct rpc_rqst *rqst, ssize_t result)
-{
-       struct rpcrdma_req *req = rpcr_to_rdmar(rqst);
-       struct rpcrdma_msg *headerp = rdmab_to_msg(req->rl_rdmabuf);
-
-       if (req->rl_rtype != rpcrdma_noch)
-               result = rpcrdma_create_chunks(rqst, &rqst->rq_snd_buf,
-                                              headerp, req->rl_rtype);
-       else if (req->rl_wtype != rpcrdma_noch)
-               result = rpcrdma_create_chunks(rqst, &rqst->rq_rcv_buf,
-                                              headerp, req->rl_wtype);
-       return result;
+       for (pos = 0; nchunks--;)
+               pos += r_xprt->rx_ia.ri_ops->ro_unmap(r_xprt,
+                                                     &req->rl_segments[pos]);
+       return n;
 }
 
 /*
@@ -397,6 +385,7 @@ rpcrdma_marshal_req(struct rpc_rqst *rqst)
        char *base;
        size_t rpclen, padlen;
        ssize_t hdrlen;
+       enum rpcrdma_chunktype rtype, wtype;
        struct rpcrdma_msg *headerp;
 
        /*
@@ -433,13 +422,13 @@ rpcrdma_marshal_req(struct rpc_rqst *rqst)
         * into pages; otherwise use reply chunks.
         */
        if (rqst->rq_rcv_buf.buflen <= RPCRDMA_INLINE_READ_THRESHOLD(rqst))
-               req->rl_wtype = rpcrdma_noch;
+               wtype = rpcrdma_noch;
        else if (rqst->rq_rcv_buf.page_len == 0)
-               req->rl_wtype = rpcrdma_replych;
+               wtype = rpcrdma_replych;
        else if (rqst->rq_rcv_buf.flags & XDRBUF_READ)
-               req->rl_wtype = rpcrdma_writech;
+               wtype = rpcrdma_writech;
        else
-               req->rl_wtype = rpcrdma_replych;
+               wtype = rpcrdma_replych;
 
        /*
         * Chunks needed for arguments?
@@ -456,16 +445,16 @@ rpcrdma_marshal_req(struct rpc_rqst *rqst)
         * TBD check NFSv4 setacl
         */
        if (rqst->rq_snd_buf.len <= RPCRDMA_INLINE_WRITE_THRESHOLD(rqst))
-               req->rl_rtype = rpcrdma_noch;
+               rtype = rpcrdma_noch;
        else if (rqst->rq_snd_buf.page_len == 0)
-               req->rl_rtype = rpcrdma_areadch;
+               rtype = rpcrdma_areadch;
        else
-               req->rl_rtype = rpcrdma_readch;
+               rtype = rpcrdma_readch;
 
        /* The following simplification is not true forever */
-       if (req->rl_rtype != rpcrdma_noch && req->rl_wtype == rpcrdma_replych)
-               req->rl_wtype = rpcrdma_noch;
-       if (req->rl_rtype != rpcrdma_noch && req->rl_wtype != rpcrdma_noch) {
+       if (rtype != rpcrdma_noch && wtype == rpcrdma_replych)
+               wtype = rpcrdma_noch;
+       if (rtype != rpcrdma_noch && wtype != rpcrdma_noch) {
                dprintk("RPC:       %s: cannot marshal multiple chunk lists\n",
                        __func__);
                return -EIO;
@@ -479,7 +468,7 @@ rpcrdma_marshal_req(struct rpc_rqst *rqst)
         * When padding is in use and applies to the transfer, insert
         * it and change the message type.
         */
-       if (req->rl_rtype == rpcrdma_noch) {
+       if (rtype == rpcrdma_noch) {
 
                padlen = rpcrdma_inline_pullup(rqst,
                                                RPCRDMA_INLINE_PAD_VALUE(rqst));
@@ -494,7 +483,7 @@ rpcrdma_marshal_req(struct rpc_rqst *rqst)
                        headerp->rm_body.rm_padded.rm_pempty[1] = xdr_zero;
                        headerp->rm_body.rm_padded.rm_pempty[2] = xdr_zero;
                        hdrlen += 2 * sizeof(u32); /* extra words in padhdr */
-                       if (req->rl_wtype != rpcrdma_noch) {
+                       if (wtype != rpcrdma_noch) {
                                dprintk("RPC:       %s: invalid chunk list\n",
                                        __func__);
                                return -EIO;
@@ -515,18 +504,26 @@ rpcrdma_marshal_req(struct rpc_rqst *rqst)
                         * on receive. Therefore, we request a reply chunk
                         * for non-writes wherever feasible and efficient.
                         */
-                       if (req->rl_wtype == rpcrdma_noch)
-                               req->rl_wtype = rpcrdma_replych;
+                       if (wtype == rpcrdma_noch)
+                               wtype = rpcrdma_replych;
                }
        }
 
-       hdrlen = rpcrdma_marshal_chunks(rqst, hdrlen);
+       if (rtype != rpcrdma_noch) {
+               hdrlen = rpcrdma_create_chunks(rqst, &rqst->rq_snd_buf,
+                                              headerp, rtype);
+               wtype = rtype;  /* simplify dprintk */
+
+       } else if (wtype != rpcrdma_noch) {
+               hdrlen = rpcrdma_create_chunks(rqst, &rqst->rq_rcv_buf,
+                                              headerp, wtype);
+       }
        if (hdrlen < 0)
                return hdrlen;
 
        dprintk("RPC:       %s: %s: hdrlen %zd rpclen %zd padlen %zd"
                " headerp 0x%p base 0x%p lkey 0x%x\n",
-               __func__, transfertypes[req->rl_wtype], hdrlen, rpclen, padlen,
+               __func__, transfertypes[wtype], hdrlen, rpclen, padlen,
                headerp, base, rdmab_lkey(req->rl_rdmabuf));
 
        /*
index 2e192baa59f3d83841746a4ea5769d8680a5f039..54f23b1be98617d5c29fb482a221ad6ed1391876 100644 (file)
@@ -156,13 +156,48 @@ static struct ctl_table sunrpc_table[] = {
 
 static struct rpc_xprt_ops xprt_rdma_procs;    /* forward reference */
 
+static void
+xprt_rdma_format_addresses4(struct rpc_xprt *xprt, struct sockaddr *sap)
+{
+       struct sockaddr_in *sin = (struct sockaddr_in *)sap;
+       char buf[20];
+
+       snprintf(buf, sizeof(buf), "%08x", ntohl(sin->sin_addr.s_addr));
+       xprt->address_strings[RPC_DISPLAY_HEX_ADDR] = kstrdup(buf, GFP_KERNEL);
+
+       xprt->address_strings[RPC_DISPLAY_NETID] = RPCBIND_NETID_RDMA;
+}
+
+static void
+xprt_rdma_format_addresses6(struct rpc_xprt *xprt, struct sockaddr *sap)
+{
+       struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
+       char buf[40];
+
+       snprintf(buf, sizeof(buf), "%pi6", &sin6->sin6_addr);
+       xprt->address_strings[RPC_DISPLAY_HEX_ADDR] = kstrdup(buf, GFP_KERNEL);
+
+       xprt->address_strings[RPC_DISPLAY_NETID] = RPCBIND_NETID_RDMA6;
+}
+
 static void
 xprt_rdma_format_addresses(struct rpc_xprt *xprt)
 {
        struct sockaddr *sap = (struct sockaddr *)
                                        &rpcx_to_rdmad(xprt).addr;
-       struct sockaddr_in *sin = (struct sockaddr_in *)sap;
-       char buf[64];
+       char buf[128];
+
+       switch (sap->sa_family) {
+       case AF_INET:
+               xprt_rdma_format_addresses4(xprt, sap);
+               break;
+       case AF_INET6:
+               xprt_rdma_format_addresses6(xprt, sap);
+               break;
+       default:
+               pr_err("rpcrdma: Unrecognized address family\n");
+               return;
+       }
 
        (void)rpc_ntop(sap, buf, sizeof(buf));
        xprt->address_strings[RPC_DISPLAY_ADDR] = kstrdup(buf, GFP_KERNEL);
@@ -170,16 +205,10 @@ xprt_rdma_format_addresses(struct rpc_xprt *xprt)
        snprintf(buf, sizeof(buf), "%u", rpc_get_port(sap));
        xprt->address_strings[RPC_DISPLAY_PORT] = kstrdup(buf, GFP_KERNEL);
 
-       xprt->address_strings[RPC_DISPLAY_PROTO] = "rdma";
-
-       snprintf(buf, sizeof(buf), "%08x", ntohl(sin->sin_addr.s_addr));
-       xprt->address_strings[RPC_DISPLAY_HEX_ADDR] = kstrdup(buf, GFP_KERNEL);
-
        snprintf(buf, sizeof(buf), "%4hx", rpc_get_port(sap));
        xprt->address_strings[RPC_DISPLAY_HEX_PORT] = kstrdup(buf, GFP_KERNEL);
 
-       /* netid */
-       xprt->address_strings[RPC_DISPLAY_NETID] = "rdma";
+       xprt->address_strings[RPC_DISPLAY_PROTO] = "rdma";
 }
 
 static void
@@ -377,7 +406,10 @@ xprt_setup_rdma(struct xprt_create *args)
                          xprt_rdma_connect_worker);
 
        xprt_rdma_format_addresses(xprt);
-       xprt->max_payload = rpcrdma_max_payload(new_xprt);
+       xprt->max_payload = new_xprt->rx_ia.ri_ops->ro_maxpages(new_xprt);
+       if (xprt->max_payload == 0)
+               goto out4;
+       xprt->max_payload <<= PAGE_SHIFT;
        dprintk("RPC:       %s: transport data payload maximum: %zu bytes\n",
                __func__, xprt->max_payload);
 
@@ -552,8 +584,8 @@ xprt_rdma_free(void *buffer)
 
        for (i = 0; req->rl_nchunks;) {
                --req->rl_nchunks;
-               i += rpcrdma_deregister_external(
-                       &req->rl_segments[i], r_xprt);
+               i += r_xprt->rx_ia.ri_ops->ro_unmap(r_xprt,
+                                                   &req->rl_segments[i]);
        }
 
        rpcrdma_buffer_put(req);
@@ -579,10 +611,7 @@ xprt_rdma_send_request(struct rpc_task *task)
        struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt);
        int rc = 0;
 
-       if (req->rl_niovs == 0)
-               rc = rpcrdma_marshal_req(rqst);
-       else if (r_xprt->rx_ia.ri_memreg_strategy != RPCRDMA_ALLPHYSICAL)
-               rc = rpcrdma_marshal_chunks(rqst, 0);
+       rc = rpcrdma_marshal_req(rqst);
        if (rc < 0)
                goto failed_marshal;
 
index e28909fddd30a3c273e4cfcbf5e600d005e916b2..4870d272e0067140dbdc7f16a914ee99dbabe9fc 100644 (file)
@@ -50,6 +50,7 @@
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/prefetch.h>
+#include <linux/sunrpc/addr.h>
 #include <asm/bitops.h>
 
 #include "xprt_rdma.h"
@@ -62,9 +63,6 @@
 # define RPCDBG_FACILITY       RPCDBG_TRANS
 #endif
 
-static void rpcrdma_reset_frmrs(struct rpcrdma_ia *);
-static void rpcrdma_reset_fmrs(struct rpcrdma_ia *);
-
 /*
  * internal functions
  */
@@ -188,7 +186,7 @@ static const char * const wc_status[] = {
        "remote access error",
        "remote operation error",
        "transport retry counter exceeded",
-       "RNR retrycounter exceeded",
+       "RNR retry counter exceeded",
        "local RDD violation error",
        "remove invalid RD request",
        "operation aborted",
@@ -206,21 +204,17 @@ static const char * const wc_status[] = {
 static void
 rpcrdma_sendcq_process_wc(struct ib_wc *wc)
 {
-       if (likely(wc->status == IB_WC_SUCCESS))
-               return;
-
        /* WARNING: Only wr_id and status are reliable at this point */
-       if (wc->wr_id == 0ULL) {
-               if (wc->status != IB_WC_WR_FLUSH_ERR)
+       if (wc->wr_id == RPCRDMA_IGNORE_COMPLETION) {
+               if (wc->status != IB_WC_SUCCESS &&
+                   wc->status != IB_WC_WR_FLUSH_ERR)
                        pr_err("RPC:       %s: SEND: %s\n",
                               __func__, COMPLETION_MSG(wc->status));
        } else {
                struct rpcrdma_mw *r;
 
                r = (struct rpcrdma_mw *)(unsigned long)wc->wr_id;
-               r->r.frmr.fr_state = FRMR_IS_STALE;
-               pr_err("RPC:       %s: frmr %p (stale): %s\n",
-                      __func__, r, COMPLETION_MSG(wc->status));
+               r->mw_sendcompletion(wc);
        }
 }
 
@@ -424,7 +418,7 @@ rpcrdma_conn_upcall(struct rdma_cm_id *id, struct rdma_cm_event *event)
        struct rpcrdma_ia *ia = &xprt->rx_ia;
        struct rpcrdma_ep *ep = &xprt->rx_ep;
 #if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
-       struct sockaddr_in *addr = (struct sockaddr_in *) &ep->rep_remote_addr;
+       struct sockaddr *sap = (struct sockaddr *)&ep->rep_remote_addr;
 #endif
        struct ib_qp_attr *attr = &ia->ri_qp_attr;
        struct ib_qp_init_attr *iattr = &ia->ri_qp_init_attr;
@@ -480,9 +474,8 @@ connected:
                wake_up_all(&ep->rep_connect_wait);
                /*FALLTHROUGH*/
        default:
-               dprintk("RPC:       %s: %pI4:%u (ep 0x%p): %s\n",
-                       __func__, &addr->sin_addr.s_addr,
-                       ntohs(addr->sin_port), ep,
+               dprintk("RPC:       %s: %pIS:%u (ep 0x%p): %s\n",
+                       __func__, sap, rpc_get_port(sap), ep,
                        CONNECTION_MSG(event->event));
                break;
        }
@@ -491,19 +484,16 @@ connected:
        if (connstate == 1) {
                int ird = attr->max_dest_rd_atomic;
                int tird = ep->rep_remote_cma.responder_resources;
-               printk(KERN_INFO "rpcrdma: connection to %pI4:%u "
-                       "on %s, memreg %d slots %d ird %d%s\n",
-                       &addr->sin_addr.s_addr,
-                       ntohs(addr->sin_port),
+
+               pr_info("rpcrdma: connection to %pIS:%u on %s, memreg '%s', %d credits, %d responders%s\n",
+                       sap, rpc_get_port(sap),
                        ia->ri_id->device->name,
-                       ia->ri_memreg_strategy,
+                       ia->ri_ops->ro_displayname,
                        xprt->rx_buf.rb_max_requests,
                        ird, ird < 4 && ird < tird / 2 ? " (low!)" : "");
        } else if (connstate < 0) {
-               printk(KERN_INFO "rpcrdma: connection to %pI4:%u closed (%d)\n",
-                       &addr->sin_addr.s_addr,
-                       ntohs(addr->sin_port),
-                       connstate);
+               pr_info("rpcrdma: connection to %pIS:%u closed (%d)\n",
+                       sap, rpc_get_port(sap), connstate);
        }
 #endif
 
@@ -621,17 +611,13 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg)
 
        if (memreg == RPCRDMA_FRMR) {
                /* Requires both frmr reg and local dma lkey */
-               if ((devattr->device_cap_flags &
+               if (((devattr->device_cap_flags &
                     (IB_DEVICE_MEM_MGT_EXTENSIONS|IB_DEVICE_LOCAL_DMA_LKEY)) !=
-                   (IB_DEVICE_MEM_MGT_EXTENSIONS|IB_DEVICE_LOCAL_DMA_LKEY)) {
+                   (IB_DEVICE_MEM_MGT_EXTENSIONS|IB_DEVICE_LOCAL_DMA_LKEY)) ||
+                     (devattr->max_fast_reg_page_list_len == 0)) {
                        dprintk("RPC:       %s: FRMR registration "
                                "not supported by HCA\n", __func__);
                        memreg = RPCRDMA_MTHCAFMR;
-               } else {
-                       /* Mind the ia limit on FRMR page list depth */
-                       ia->ri_max_frmr_depth = min_t(unsigned int,
-                               RPCRDMA_MAX_DATA_SEGS,
-                               devattr->max_fast_reg_page_list_len);
                }
        }
        if (memreg == RPCRDMA_MTHCAFMR) {
@@ -652,13 +638,16 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg)
         */
        switch (memreg) {
        case RPCRDMA_FRMR:
+               ia->ri_ops = &rpcrdma_frwr_memreg_ops;
                break;
        case RPCRDMA_ALLPHYSICAL:
+               ia->ri_ops = &rpcrdma_physical_memreg_ops;
                mem_priv = IB_ACCESS_LOCAL_WRITE |
                                IB_ACCESS_REMOTE_WRITE |
                                IB_ACCESS_REMOTE_READ;
                goto register_setup;
        case RPCRDMA_MTHCAFMR:
+               ia->ri_ops = &rpcrdma_fmr_memreg_ops;
                if (ia->ri_have_dma_lkey)
                        break;
                mem_priv = IB_ACCESS_LOCAL_WRITE;
@@ -678,8 +667,8 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg)
                rc = -ENOMEM;
                goto out3;
        }
-       dprintk("RPC:       %s: memory registration strategy is %d\n",
-               __func__, memreg);
+       dprintk("RPC:       %s: memory registration strategy is '%s'\n",
+               __func__, ia->ri_ops->ro_displayname);
 
        /* Else will do memory reg/dereg for each chunk */
        ia->ri_memreg_strategy = memreg;
@@ -743,49 +732,11 @@ rpcrdma_ep_create(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia,
 
        ep->rep_attr.event_handler = rpcrdma_qp_async_error_upcall;
        ep->rep_attr.qp_context = ep;
-       /* send_cq and recv_cq initialized below */
        ep->rep_attr.srq = NULL;
        ep->rep_attr.cap.max_send_wr = cdata->max_requests;
-       switch (ia->ri_memreg_strategy) {
-       case RPCRDMA_FRMR: {
-               int depth = 7;
-
-               /* Add room for frmr register and invalidate WRs.
-                * 1. FRMR reg WR for head
-                * 2. FRMR invalidate WR for head
-                * 3. N FRMR reg WRs for pagelist
-                * 4. N FRMR invalidate WRs for pagelist
-                * 5. FRMR reg WR for tail
-                * 6. FRMR invalidate WR for tail
-                * 7. The RDMA_SEND WR
-                */
-
-               /* Calculate N if the device max FRMR depth is smaller than
-                * RPCRDMA_MAX_DATA_SEGS.
-                */
-               if (ia->ri_max_frmr_depth < RPCRDMA_MAX_DATA_SEGS) {
-                       int delta = RPCRDMA_MAX_DATA_SEGS -
-                                   ia->ri_max_frmr_depth;
-
-                       do {
-                               depth += 2; /* FRMR reg + invalidate */
-                               delta -= ia->ri_max_frmr_depth;
-                       } while (delta > 0);
-
-               }
-               ep->rep_attr.cap.max_send_wr *= depth;
-               if (ep->rep_attr.cap.max_send_wr > devattr->max_qp_wr) {
-                       cdata->max_requests = devattr->max_qp_wr / depth;
-                       if (!cdata->max_requests)
-                               return -EINVAL;
-                       ep->rep_attr.cap.max_send_wr = cdata->max_requests *
-                                                      depth;
-               }
-               break;
-       }
-       default:
-               break;
-       }
+       rc = ia->ri_ops->ro_open(ia, ep, cdata);
+       if (rc)
+               return rc;
        ep->rep_attr.cap.max_recv_wr = cdata->max_requests;
        ep->rep_attr.cap.max_send_sge = (cdata->padding ? 4 : 2);
        ep->rep_attr.cap.max_recv_sge = 1;
@@ -944,21 +895,9 @@ retry:
                rpcrdma_ep_disconnect(ep, ia);
                rpcrdma_flush_cqs(ep);
 
-               switch (ia->ri_memreg_strategy) {
-               case RPCRDMA_FRMR:
-                       rpcrdma_reset_frmrs(ia);
-                       break;
-               case RPCRDMA_MTHCAFMR:
-                       rpcrdma_reset_fmrs(ia);
-                       break;
-               case RPCRDMA_ALLPHYSICAL:
-                       break;
-               default:
-                       rc = -EIO;
-                       goto out;
-               }
-
                xprt = container_of(ia, struct rpcrdma_xprt, rx_ia);
+               ia->ri_ops->ro_reset(xprt);
+
                id = rpcrdma_create_id(xprt, ia,
                                (struct sockaddr *)&xprt->rx_data.addr);
                if (IS_ERR(id)) {
@@ -1123,91 +1062,6 @@ out:
        return ERR_PTR(rc);
 }
 
-static int
-rpcrdma_init_fmrs(struct rpcrdma_ia *ia, struct rpcrdma_buffer *buf)
-{
-       int mr_access_flags = IB_ACCESS_REMOTE_WRITE | IB_ACCESS_REMOTE_READ;
-       struct ib_fmr_attr fmr_attr = {
-               .max_pages      = RPCRDMA_MAX_DATA_SEGS,
-               .max_maps       = 1,
-               .page_shift     = PAGE_SHIFT
-       };
-       struct rpcrdma_mw *r;
-       int i, rc;
-
-       i = (buf->rb_max_requests + 1) * RPCRDMA_MAX_SEGS;
-       dprintk("RPC:       %s: initializing %d FMRs\n", __func__, i);
-
-       while (i--) {
-               r = kzalloc(sizeof(*r), GFP_KERNEL);
-               if (r == NULL)
-                       return -ENOMEM;
-
-               r->r.fmr = ib_alloc_fmr(ia->ri_pd, mr_access_flags, &fmr_attr);
-               if (IS_ERR(r->r.fmr)) {
-                       rc = PTR_ERR(r->r.fmr);
-                       dprintk("RPC:       %s: ib_alloc_fmr failed %i\n",
-                               __func__, rc);
-                       goto out_free;
-               }
-
-               list_add(&r->mw_list, &buf->rb_mws);
-               list_add(&r->mw_all, &buf->rb_all);
-       }
-       return 0;
-
-out_free:
-       kfree(r);
-       return rc;
-}
-
-static int
-rpcrdma_init_frmrs(struct rpcrdma_ia *ia, struct rpcrdma_buffer *buf)
-{
-       struct rpcrdma_frmr *f;
-       struct rpcrdma_mw *r;
-       int i, rc;
-
-       i = (buf->rb_max_requests + 1) * RPCRDMA_MAX_SEGS;
-       dprintk("RPC:       %s: initializing %d FRMRs\n", __func__, i);
-
-       while (i--) {
-               r = kzalloc(sizeof(*r), GFP_KERNEL);
-               if (r == NULL)
-                       return -ENOMEM;
-               f = &r->r.frmr;
-
-               f->fr_mr = ib_alloc_fast_reg_mr(ia->ri_pd,
-                                               ia->ri_max_frmr_depth);
-               if (IS_ERR(f->fr_mr)) {
-                       rc = PTR_ERR(f->fr_mr);
-                       dprintk("RPC:       %s: ib_alloc_fast_reg_mr "
-                               "failed %i\n", __func__, rc);
-                       goto out_free;
-               }
-
-               f->fr_pgl = ib_alloc_fast_reg_page_list(ia->ri_id->device,
-                                                       ia->ri_max_frmr_depth);
-               if (IS_ERR(f->fr_pgl)) {
-                       rc = PTR_ERR(f->fr_pgl);
-                       dprintk("RPC:       %s: ib_alloc_fast_reg_page_list "
-                               "failed %i\n", __func__, rc);
-
-                       ib_dereg_mr(f->fr_mr);
-                       goto out_free;
-               }
-
-               list_add(&r->mw_list, &buf->rb_mws);
-               list_add(&r->mw_all, &buf->rb_all);
-       }
-
-       return 0;
-
-out_free:
-       kfree(r);
-       return rc;
-}
-
 int
 rpcrdma_buffer_create(struct rpcrdma_xprt *r_xprt)
 {
@@ -1244,22 +1098,9 @@ rpcrdma_buffer_create(struct rpcrdma_xprt *r_xprt)
        buf->rb_recv_bufs = (struct rpcrdma_rep **) p;
        p = (char *) &buf->rb_recv_bufs[buf->rb_max_requests];
 
-       INIT_LIST_HEAD(&buf->rb_mws);
-       INIT_LIST_HEAD(&buf->rb_all);
-       switch (ia->ri_memreg_strategy) {
-       case RPCRDMA_FRMR:
-               rc = rpcrdma_init_frmrs(ia, buf);
-               if (rc)
-                       goto out;
-               break;
-       case RPCRDMA_MTHCAFMR:
-               rc = rpcrdma_init_fmrs(ia, buf);
-               if (rc)
-                       goto out;
-               break;
-       default:
-               break;
-       }
+       rc = ia->ri_ops->ro_init(r_xprt);
+       if (rc)
+               goto out;
 
        for (i = 0; i < buf->rb_max_requests; i++) {
                struct rpcrdma_req *req;
@@ -1311,47 +1152,6 @@ rpcrdma_destroy_req(struct rpcrdma_ia *ia, struct rpcrdma_req *req)
        kfree(req);
 }
 
-static void
-rpcrdma_destroy_fmrs(struct rpcrdma_buffer *buf)
-{
-       struct rpcrdma_mw *r;
-       int rc;
-
-       while (!list_empty(&buf->rb_all)) {
-               r = list_entry(buf->rb_all.next, struct rpcrdma_mw, mw_all);
-               list_del(&r->mw_all);
-               list_del(&r->mw_list);
-
-               rc = ib_dealloc_fmr(r->r.fmr);
-               if (rc)
-                       dprintk("RPC:       %s: ib_dealloc_fmr failed %i\n",
-                               __func__, rc);
-
-               kfree(r);
-       }
-}
-
-static void
-rpcrdma_destroy_frmrs(struct rpcrdma_buffer *buf)
-{
-       struct rpcrdma_mw *r;
-       int rc;
-
-       while (!list_empty(&buf->rb_all)) {
-               r = list_entry(buf->rb_all.next, struct rpcrdma_mw, mw_all);
-               list_del(&r->mw_all);
-               list_del(&r->mw_list);
-
-               rc = ib_dereg_mr(r->r.frmr.fr_mr);
-               if (rc)
-                       dprintk("RPC:       %s: ib_dereg_mr failed %i\n",
-                               __func__, rc);
-               ib_free_fast_reg_page_list(r->r.frmr.fr_pgl);
-
-               kfree(r);
-       }
-}
-
 void
 rpcrdma_buffer_destroy(struct rpcrdma_buffer *buf)
 {
@@ -1372,104 +1172,11 @@ rpcrdma_buffer_destroy(struct rpcrdma_buffer *buf)
                        rpcrdma_destroy_req(ia, buf->rb_send_bufs[i]);
        }
 
-       switch (ia->ri_memreg_strategy) {
-       case RPCRDMA_FRMR:
-               rpcrdma_destroy_frmrs(buf);
-               break;
-       case RPCRDMA_MTHCAFMR:
-               rpcrdma_destroy_fmrs(buf);
-               break;
-       default:
-               break;
-       }
+       ia->ri_ops->ro_destroy(buf);
 
        kfree(buf->rb_pool);
 }
 
-/* After a disconnect, unmap all FMRs.
- *
- * This is invoked only in the transport connect worker in order
- * to serialize with rpcrdma_register_fmr_external().
- */
-static void
-rpcrdma_reset_fmrs(struct rpcrdma_ia *ia)
-{
-       struct rpcrdma_xprt *r_xprt =
-                               container_of(ia, struct rpcrdma_xprt, rx_ia);
-       struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
-       struct list_head *pos;
-       struct rpcrdma_mw *r;
-       LIST_HEAD(l);
-       int rc;
-
-       list_for_each(pos, &buf->rb_all) {
-               r = list_entry(pos, struct rpcrdma_mw, mw_all);
-
-               INIT_LIST_HEAD(&l);
-               list_add(&r->r.fmr->list, &l);
-               rc = ib_unmap_fmr(&l);
-               if (rc)
-                       dprintk("RPC:       %s: ib_unmap_fmr failed %i\n",
-                               __func__, rc);
-       }
-}
-
-/* After a disconnect, a flushed FAST_REG_MR can leave an FRMR in
- * an unusable state. Find FRMRs in this state and dereg / reg
- * each.  FRMRs that are VALID and attached to an rpcrdma_req are
- * also torn down.
- *
- * This gives all in-use FRMRs a fresh rkey and leaves them INVALID.
- *
- * This is invoked only in the transport connect worker in order
- * to serialize with rpcrdma_register_frmr_external().
- */
-static void
-rpcrdma_reset_frmrs(struct rpcrdma_ia *ia)
-{
-       struct rpcrdma_xprt *r_xprt =
-                               container_of(ia, struct rpcrdma_xprt, rx_ia);
-       struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
-       struct list_head *pos;
-       struct rpcrdma_mw *r;
-       int rc;
-
-       list_for_each(pos, &buf->rb_all) {
-               r = list_entry(pos, struct rpcrdma_mw, mw_all);
-
-               if (r->r.frmr.fr_state == FRMR_IS_INVALID)
-                       continue;
-
-               rc = ib_dereg_mr(r->r.frmr.fr_mr);
-               if (rc)
-                       dprintk("RPC:       %s: ib_dereg_mr failed %i\n",
-                               __func__, rc);
-               ib_free_fast_reg_page_list(r->r.frmr.fr_pgl);
-
-               r->r.frmr.fr_mr = ib_alloc_fast_reg_mr(ia->ri_pd,
-                                       ia->ri_max_frmr_depth);
-               if (IS_ERR(r->r.frmr.fr_mr)) {
-                       rc = PTR_ERR(r->r.frmr.fr_mr);
-                       dprintk("RPC:       %s: ib_alloc_fast_reg_mr"
-                               " failed %i\n", __func__, rc);
-                       continue;
-               }
-               r->r.frmr.fr_pgl = ib_alloc_fast_reg_page_list(
-                                       ia->ri_id->device,
-                                       ia->ri_max_frmr_depth);
-               if (IS_ERR(r->r.frmr.fr_pgl)) {
-                       rc = PTR_ERR(r->r.frmr.fr_pgl);
-                       dprintk("RPC:       %s: "
-                               "ib_alloc_fast_reg_page_list "
-                               "failed %i\n", __func__, rc);
-
-                       ib_dereg_mr(r->r.frmr.fr_mr);
-                       continue;
-               }
-               r->r.frmr.fr_state = FRMR_IS_INVALID;
-       }
-}
-
 /* "*mw" can be NULL when rpcrdma_buffer_get_mrs() fails, leaving
  * some req segments uninitialized.
  */
@@ -1509,7 +1216,7 @@ rpcrdma_buffer_put_sendbuf(struct rpcrdma_req *req, struct rpcrdma_buffer *buf)
        }
 }
 
-/* rpcrdma_unmap_one() was already done by rpcrdma_deregister_frmr_external().
+/* rpcrdma_unmap_one() was already done during deregistration.
  * Redo only the ib_post_send().
  */
 static void
@@ -1729,6 +1436,14 @@ rpcrdma_recv_buffer_put(struct rpcrdma_rep *rep)
  * Wrappers for internal-use kmalloc memory registration, used by buffer code.
  */
 
+void
+rpcrdma_mapping_error(struct rpcrdma_mr_seg *seg)
+{
+       dprintk("RPC:       map_one: offset %p iova %llx len %zu\n",
+               seg->mr_offset,
+               (unsigned long long)seg->mr_dma, seg->mr_dmalen);
+}
+
 static int
 rpcrdma_register_internal(struct rpcrdma_ia *ia, void *va, int len,
                                struct ib_mr **mrp, struct ib_sge *iov)
@@ -1853,287 +1568,6 @@ rpcrdma_free_regbuf(struct rpcrdma_ia *ia, struct rpcrdma_regbuf *rb)
        }
 }
 
-/*
- * Wrappers for chunk registration, shared by read/write chunk code.
- */
-
-static void
-rpcrdma_map_one(struct rpcrdma_ia *ia, struct rpcrdma_mr_seg *seg, int writing)
-{
-       seg->mr_dir = writing ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-       seg->mr_dmalen = seg->mr_len;
-       if (seg->mr_page)
-               seg->mr_dma = ib_dma_map_page(ia->ri_id->device,
-                               seg->mr_page, offset_in_page(seg->mr_offset),
-                               seg->mr_dmalen, seg->mr_dir);
-       else
-               seg->mr_dma = ib_dma_map_single(ia->ri_id->device,
-                               seg->mr_offset,
-                               seg->mr_dmalen, seg->mr_dir);
-       if (ib_dma_mapping_error(ia->ri_id->device, seg->mr_dma)) {
-               dprintk("RPC:       %s: mr_dma %llx mr_offset %p mr_dma_len %zu\n",
-                       __func__,
-                       (unsigned long long)seg->mr_dma,
-                       seg->mr_offset, seg->mr_dmalen);
-       }
-}
-
-static void
-rpcrdma_unmap_one(struct rpcrdma_ia *ia, struct rpcrdma_mr_seg *seg)
-{
-       if (seg->mr_page)
-               ib_dma_unmap_page(ia->ri_id->device,
-                               seg->mr_dma, seg->mr_dmalen, seg->mr_dir);
-       else
-               ib_dma_unmap_single(ia->ri_id->device,
-                               seg->mr_dma, seg->mr_dmalen, seg->mr_dir);
-}
-
-static int
-rpcrdma_register_frmr_external(struct rpcrdma_mr_seg *seg,
-                       int *nsegs, int writing, struct rpcrdma_ia *ia,
-                       struct rpcrdma_xprt *r_xprt)
-{
-       struct rpcrdma_mr_seg *seg1 = seg;
-       struct rpcrdma_mw *mw = seg1->rl_mw;
-       struct rpcrdma_frmr *frmr = &mw->r.frmr;
-       struct ib_mr *mr = frmr->fr_mr;
-       struct ib_send_wr fastreg_wr, *bad_wr;
-       u8 key;
-       int len, pageoff;
-       int i, rc;
-       int seg_len;
-       u64 pa;
-       int page_no;
-
-       pageoff = offset_in_page(seg1->mr_offset);
-       seg1->mr_offset -= pageoff;     /* start of page */
-       seg1->mr_len += pageoff;
-       len = -pageoff;
-       if (*nsegs > ia->ri_max_frmr_depth)
-               *nsegs = ia->ri_max_frmr_depth;
-       for (page_no = i = 0; i < *nsegs;) {
-               rpcrdma_map_one(ia, seg, writing);
-               pa = seg->mr_dma;
-               for (seg_len = seg->mr_len; seg_len > 0; seg_len -= PAGE_SIZE) {
-                       frmr->fr_pgl->page_list[page_no++] = pa;
-                       pa += PAGE_SIZE;
-               }
-               len += seg->mr_len;
-               ++seg;
-               ++i;
-               /* Check for holes */
-               if ((i < *nsegs && offset_in_page(seg->mr_offset)) ||
-                   offset_in_page((seg-1)->mr_offset + (seg-1)->mr_len))
-                       break;
-       }
-       dprintk("RPC:       %s: Using frmr %p to map %d segments\n",
-               __func__, mw, i);
-
-       frmr->fr_state = FRMR_IS_VALID;
-
-       memset(&fastreg_wr, 0, sizeof(fastreg_wr));
-       fastreg_wr.wr_id = (unsigned long)(void *)mw;
-       fastreg_wr.opcode = IB_WR_FAST_REG_MR;
-       fastreg_wr.wr.fast_reg.iova_start = seg1->mr_dma;
-       fastreg_wr.wr.fast_reg.page_list = frmr->fr_pgl;
-       fastreg_wr.wr.fast_reg.page_list_len = page_no;
-       fastreg_wr.wr.fast_reg.page_shift = PAGE_SHIFT;
-       fastreg_wr.wr.fast_reg.length = page_no << PAGE_SHIFT;
-       if (fastreg_wr.wr.fast_reg.length < len) {
-               rc = -EIO;
-               goto out_err;
-       }
-
-       /* Bump the key */
-       key = (u8)(mr->rkey & 0x000000FF);
-       ib_update_fast_reg_key(mr, ++key);
-
-       fastreg_wr.wr.fast_reg.access_flags = (writing ?
-                               IB_ACCESS_REMOTE_WRITE | IB_ACCESS_LOCAL_WRITE :
-                               IB_ACCESS_REMOTE_READ);
-       fastreg_wr.wr.fast_reg.rkey = mr->rkey;
-       DECR_CQCOUNT(&r_xprt->rx_ep);
-
-       rc = ib_post_send(ia->ri_id->qp, &fastreg_wr, &bad_wr);
-       if (rc) {
-               dprintk("RPC:       %s: failed ib_post_send for register,"
-                       " status %i\n", __func__, rc);
-               ib_update_fast_reg_key(mr, --key);
-               goto out_err;
-       } else {
-               seg1->mr_rkey = mr->rkey;
-               seg1->mr_base = seg1->mr_dma + pageoff;
-               seg1->mr_nsegs = i;
-               seg1->mr_len = len;
-       }
-       *nsegs = i;
-       return 0;
-out_err:
-       frmr->fr_state = FRMR_IS_INVALID;
-       while (i--)
-               rpcrdma_unmap_one(ia, --seg);
-       return rc;
-}
-
-static int
-rpcrdma_deregister_frmr_external(struct rpcrdma_mr_seg *seg,
-                       struct rpcrdma_ia *ia, struct rpcrdma_xprt *r_xprt)
-{
-       struct rpcrdma_mr_seg *seg1 = seg;
-       struct ib_send_wr invalidate_wr, *bad_wr;
-       int rc;
-
-       seg1->rl_mw->r.frmr.fr_state = FRMR_IS_INVALID;
-
-       memset(&invalidate_wr, 0, sizeof invalidate_wr);
-       invalidate_wr.wr_id = (unsigned long)(void *)seg1->rl_mw;
-       invalidate_wr.opcode = IB_WR_LOCAL_INV;
-       invalidate_wr.ex.invalidate_rkey = seg1->rl_mw->r.frmr.fr_mr->rkey;
-       DECR_CQCOUNT(&r_xprt->rx_ep);
-
-       read_lock(&ia->ri_qplock);
-       while (seg1->mr_nsegs--)
-               rpcrdma_unmap_one(ia, seg++);
-       rc = ib_post_send(ia->ri_id->qp, &invalidate_wr, &bad_wr);
-       read_unlock(&ia->ri_qplock);
-       if (rc) {
-               /* Force rpcrdma_buffer_get() to retry */
-               seg1->rl_mw->r.frmr.fr_state = FRMR_IS_STALE;
-               dprintk("RPC:       %s: failed ib_post_send for invalidate,"
-                       " status %i\n", __func__, rc);
-       }
-       return rc;
-}
-
-static int
-rpcrdma_register_fmr_external(struct rpcrdma_mr_seg *seg,
-                       int *nsegs, int writing, struct rpcrdma_ia *ia)
-{
-       struct rpcrdma_mr_seg *seg1 = seg;
-       u64 physaddrs[RPCRDMA_MAX_DATA_SEGS];
-       int len, pageoff, i, rc;
-
-       pageoff = offset_in_page(seg1->mr_offset);
-       seg1->mr_offset -= pageoff;     /* start of page */
-       seg1->mr_len += pageoff;
-       len = -pageoff;
-       if (*nsegs > RPCRDMA_MAX_DATA_SEGS)
-               *nsegs = RPCRDMA_MAX_DATA_SEGS;
-       for (i = 0; i < *nsegs;) {
-               rpcrdma_map_one(ia, seg, writing);
-               physaddrs[i] = seg->mr_dma;
-               len += seg->mr_len;
-               ++seg;
-               ++i;
-               /* Check for holes */
-               if ((i < *nsegs && offset_in_page(seg->mr_offset)) ||
-                   offset_in_page((seg-1)->mr_offset + (seg-1)->mr_len))
-                       break;
-       }
-       rc = ib_map_phys_fmr(seg1->rl_mw->r.fmr, physaddrs, i, seg1->mr_dma);
-       if (rc) {
-               dprintk("RPC:       %s: failed ib_map_phys_fmr "
-                       "%u@0x%llx+%i (%d)... status %i\n", __func__,
-                       len, (unsigned long long)seg1->mr_dma,
-                       pageoff, i, rc);
-               while (i--)
-                       rpcrdma_unmap_one(ia, --seg);
-       } else {
-               seg1->mr_rkey = seg1->rl_mw->r.fmr->rkey;
-               seg1->mr_base = seg1->mr_dma + pageoff;
-               seg1->mr_nsegs = i;
-               seg1->mr_len = len;
-       }
-       *nsegs = i;
-       return rc;
-}
-
-static int
-rpcrdma_deregister_fmr_external(struct rpcrdma_mr_seg *seg,
-                       struct rpcrdma_ia *ia)
-{
-       struct rpcrdma_mr_seg *seg1 = seg;
-       LIST_HEAD(l);
-       int rc;
-
-       list_add(&seg1->rl_mw->r.fmr->list, &l);
-       rc = ib_unmap_fmr(&l);
-       read_lock(&ia->ri_qplock);
-       while (seg1->mr_nsegs--)
-               rpcrdma_unmap_one(ia, seg++);
-       read_unlock(&ia->ri_qplock);
-       if (rc)
-               dprintk("RPC:       %s: failed ib_unmap_fmr,"
-                       " status %i\n", __func__, rc);
-       return rc;
-}
-
-int
-rpcrdma_register_external(struct rpcrdma_mr_seg *seg,
-                       int nsegs, int writing, struct rpcrdma_xprt *r_xprt)
-{
-       struct rpcrdma_ia *ia = &r_xprt->rx_ia;
-       int rc = 0;
-
-       switch (ia->ri_memreg_strategy) {
-
-       case RPCRDMA_ALLPHYSICAL:
-               rpcrdma_map_one(ia, seg, writing);
-               seg->mr_rkey = ia->ri_bind_mem->rkey;
-               seg->mr_base = seg->mr_dma;
-               seg->mr_nsegs = 1;
-               nsegs = 1;
-               break;
-
-       /* Registration using frmr registration */
-       case RPCRDMA_FRMR:
-               rc = rpcrdma_register_frmr_external(seg, &nsegs, writing, ia, r_xprt);
-               break;
-
-       /* Registration using fmr memory registration */
-       case RPCRDMA_MTHCAFMR:
-               rc = rpcrdma_register_fmr_external(seg, &nsegs, writing, ia);
-               break;
-
-       default:
-               return -EIO;
-       }
-       if (rc)
-               return rc;
-
-       return nsegs;
-}
-
-int
-rpcrdma_deregister_external(struct rpcrdma_mr_seg *seg,
-               struct rpcrdma_xprt *r_xprt)
-{
-       struct rpcrdma_ia *ia = &r_xprt->rx_ia;
-       int nsegs = seg->mr_nsegs, rc;
-
-       switch (ia->ri_memreg_strategy) {
-
-       case RPCRDMA_ALLPHYSICAL:
-               read_lock(&ia->ri_qplock);
-               rpcrdma_unmap_one(ia, seg);
-               read_unlock(&ia->ri_qplock);
-               break;
-
-       case RPCRDMA_FRMR:
-               rc = rpcrdma_deregister_frmr_external(seg, ia, r_xprt);
-               break;
-
-       case RPCRDMA_MTHCAFMR:
-               rc = rpcrdma_deregister_fmr_external(seg, ia);
-               break;
-
-       default:
-               break;
-       }
-       return nsegs;
-}
-
 /*
  * Prepost any receive buffer, then post send.
  *
@@ -2156,7 +1590,7 @@ rpcrdma_ep_post(struct rpcrdma_ia *ia,
        }
 
        send_wr.next = NULL;
-       send_wr.wr_id = 0ULL;   /* no send cookie */
+       send_wr.wr_id = RPCRDMA_IGNORE_COMPLETION;
        send_wr.sg_list = req->rl_send_iov;
        send_wr.num_sge = req->rl_niovs;
        send_wr.opcode = IB_WR_SEND;
@@ -2215,43 +1649,24 @@ rpcrdma_ep_post_recv(struct rpcrdma_ia *ia,
        return rc;
 }
 
-/* Physical mapping means one Read/Write list entry per-page.
- * All list entries must fit within an inline buffer
- *
- * NB: The server must return a Write list for NFS READ,
- *     which has the same constraint. Factor in the inline
- *     rsize as well.
+/* How many chunk list items fit within our inline buffers?
  */
-static size_t
-rpcrdma_physical_max_payload(struct rpcrdma_xprt *r_xprt)
+unsigned int
+rpcrdma_max_segments(struct rpcrdma_xprt *r_xprt)
 {
        struct rpcrdma_create_data_internal *cdata = &r_xprt->rx_data;
-       unsigned int inline_size, pages;
+       int bytes, segments;
 
-       inline_size = min_t(unsigned int,
-                           cdata->inline_wsize, cdata->inline_rsize);
-       inline_size -= RPCRDMA_HDRLEN_MIN;
-       pages = inline_size / sizeof(struct rpcrdma_segment);
-       return pages << PAGE_SHIFT;
-}
-
-static size_t
-rpcrdma_mr_max_payload(struct rpcrdma_xprt *r_xprt)
-{
-       return RPCRDMA_MAX_DATA_SEGS << PAGE_SHIFT;
-}
-
-size_t
-rpcrdma_max_payload(struct rpcrdma_xprt *r_xprt)
-{
-       size_t result;
-
-       switch (r_xprt->rx_ia.ri_memreg_strategy) {
-       case RPCRDMA_ALLPHYSICAL:
-               result = rpcrdma_physical_max_payload(r_xprt);
-               break;
-       default:
-               result = rpcrdma_mr_max_payload(r_xprt);
+       bytes = min_t(unsigned int, cdata->inline_wsize, cdata->inline_rsize);
+       bytes -= RPCRDMA_HDRLEN_MIN;
+       if (bytes < sizeof(struct rpcrdma_segment) * 2) {
+               pr_warn("RPC:       %s: inline threshold too small\n",
+                       __func__);
+               return 0;
        }
-       return result;
+
+       segments = 1 << (fls(bytes / sizeof(struct rpcrdma_segment)) - 1);
+       dprintk("RPC:       %s: max chunk list size = %d segments\n",
+               __func__, segments);
+       return segments;
 }
index 0a16fb6f088590c142232ad99b2ac3b29304c169..78e0b8beaa363f4ea8a2e2c1073bf5d5c0a92b45 100644 (file)
@@ -60,6 +60,7 @@
  * Interface Adapter -- one per transport instance
  */
 struct rpcrdma_ia {
+       const struct rpcrdma_memreg_ops *ri_ops;
        rwlock_t                ri_qplock;
        struct rdma_cm_id       *ri_id;
        struct ib_pd            *ri_pd;
@@ -105,6 +106,10 @@ struct rpcrdma_ep {
 #define INIT_CQCOUNT(ep) atomic_set(&(ep)->rep_cqcount, (ep)->rep_cqinit)
 #define DECR_CQCOUNT(ep) atomic_sub_return(1, &(ep)->rep_cqcount)
 
+/* Force completion handler to ignore the signal
+ */
+#define RPCRDMA_IGNORE_COMPLETION      (0ULL)
+
 /* Registered buffer -- registered kmalloc'd memory for RDMA SEND/RECV
  *
  * The below structure appears at the front of a large region of kmalloc'd
@@ -143,14 +148,6 @@ rdmab_to_msg(struct rpcrdma_regbuf *rb)
        return (struct rpcrdma_msg *)rb->rg_base;
 }
 
-enum rpcrdma_chunktype {
-       rpcrdma_noch = 0,
-       rpcrdma_readch,
-       rpcrdma_areadch,
-       rpcrdma_writech,
-       rpcrdma_replych
-};
-
 /*
  * struct rpcrdma_rep -- this structure encapsulates state required to recv
  * and complete a reply, asychronously. It needs several pieces of
@@ -213,6 +210,7 @@ struct rpcrdma_mw {
                struct ib_fmr           *fmr;
                struct rpcrdma_frmr     frmr;
        } r;
+       void                    (*mw_sendcompletion)(struct ib_wc *);
        struct list_head        mw_list;
        struct list_head        mw_all;
 };
@@ -258,7 +256,6 @@ struct rpcrdma_req {
        unsigned int    rl_niovs;       /* 0, 2 or 4 */
        unsigned int    rl_nchunks;     /* non-zero if chunks */
        unsigned int    rl_connect_cookie;      /* retry detection */
-       enum rpcrdma_chunktype  rl_rtype, rl_wtype;
        struct rpcrdma_buffer *rl_buffer; /* home base for this structure */
        struct rpcrdma_rep      *rl_reply;/* holder for reply buffer */
        struct ib_sge   rl_send_iov[4]; /* for active requests */
@@ -339,6 +336,29 @@ struct rpcrdma_stats {
        unsigned long           bad_reply_count;
 };
 
+/*
+ * Per-registration mode operations
+ */
+struct rpcrdma_xprt;
+struct rpcrdma_memreg_ops {
+       int             (*ro_map)(struct rpcrdma_xprt *,
+                                 struct rpcrdma_mr_seg *, int, bool);
+       int             (*ro_unmap)(struct rpcrdma_xprt *,
+                                   struct rpcrdma_mr_seg *);
+       int             (*ro_open)(struct rpcrdma_ia *,
+                                  struct rpcrdma_ep *,
+                                  struct rpcrdma_create_data_internal *);
+       size_t          (*ro_maxpages)(struct rpcrdma_xprt *);
+       int             (*ro_init)(struct rpcrdma_xprt *);
+       void            (*ro_reset)(struct rpcrdma_xprt *);
+       void            (*ro_destroy)(struct rpcrdma_buffer *);
+       const char      *ro_displayname;
+};
+
+extern const struct rpcrdma_memreg_ops rpcrdma_fmr_memreg_ops;
+extern const struct rpcrdma_memreg_ops rpcrdma_frwr_memreg_ops;
+extern const struct rpcrdma_memreg_ops rpcrdma_physical_memreg_ops;
+
 /*
  * RPCRDMA transport -- encapsulates the structures above for
  * integration with RPC.
@@ -398,16 +418,56 @@ void rpcrdma_buffer_put(struct rpcrdma_req *);
 void rpcrdma_recv_buffer_get(struct rpcrdma_req *);
 void rpcrdma_recv_buffer_put(struct rpcrdma_rep *);
 
-int rpcrdma_register_external(struct rpcrdma_mr_seg *,
-                               int, int, struct rpcrdma_xprt *);
-int rpcrdma_deregister_external(struct rpcrdma_mr_seg *,
-                               struct rpcrdma_xprt *);
-
 struct rpcrdma_regbuf *rpcrdma_alloc_regbuf(struct rpcrdma_ia *,
                                            size_t, gfp_t);
 void rpcrdma_free_regbuf(struct rpcrdma_ia *,
                         struct rpcrdma_regbuf *);
 
+unsigned int rpcrdma_max_segments(struct rpcrdma_xprt *);
+
+/*
+ * Wrappers for chunk registration, shared by read/write chunk code.
+ */
+
+void rpcrdma_mapping_error(struct rpcrdma_mr_seg *);
+
+static inline enum dma_data_direction
+rpcrdma_data_dir(bool writing)
+{
+       return writing ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+}
+
+static inline void
+rpcrdma_map_one(struct ib_device *device, struct rpcrdma_mr_seg *seg,
+               enum dma_data_direction direction)
+{
+       seg->mr_dir = direction;
+       seg->mr_dmalen = seg->mr_len;
+
+       if (seg->mr_page)
+               seg->mr_dma = ib_dma_map_page(device,
+                               seg->mr_page, offset_in_page(seg->mr_offset),
+                               seg->mr_dmalen, seg->mr_dir);
+       else
+               seg->mr_dma = ib_dma_map_single(device,
+                               seg->mr_offset,
+                               seg->mr_dmalen, seg->mr_dir);
+
+       if (ib_dma_mapping_error(device, seg->mr_dma))
+               rpcrdma_mapping_error(seg);
+}
+
+static inline void
+rpcrdma_unmap_one(struct ib_device *device, struct rpcrdma_mr_seg *seg)
+{
+       if (seg->mr_page)
+               ib_dma_unmap_page(device,
+                                 seg->mr_dma, seg->mr_dmalen, seg->mr_dir);
+       else
+               ib_dma_unmap_single(device,
+                                   seg->mr_dma, seg->mr_dmalen, seg->mr_dir);
+}
+
 /*
  * RPC/RDMA connection management calls - xprtrdma/rpc_rdma.c
  */
@@ -418,9 +478,7 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *);
 /*
  * RPC/RDMA protocol calls - xprtrdma/rpc_rdma.c
  */
-ssize_t rpcrdma_marshal_chunks(struct rpc_rqst *, ssize_t);
 int rpcrdma_marshal_req(struct rpc_rqst *);
-size_t rpcrdma_max_payload(struct rpcrdma_xprt *);
 
 /* Temporary NFS request map cache. Created in svc_rdma.c  */
 extern struct kmem_cache *svc_rdma_map_cachep;
index 3613e72e858e2e259bd91455127e4ec0af5c903b..70e3dacbf84ab7a899298fca1fdcb2e77fd0c2d5 100644 (file)
@@ -591,14 +591,14 @@ void tipc_bearer_stop(struct net *net)
 
 /* Caller should hold rtnl_lock to protect the bearer */
 static int __tipc_nl_add_bearer(struct tipc_nl_msg *msg,
-                               struct tipc_bearer *bearer)
+                               struct tipc_bearer *bearer, int nlflags)
 {
        void *hdr;
        struct nlattr *attrs;
        struct nlattr *prop;
 
        hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,
-                         NLM_F_MULTI, TIPC_NL_BEARER_GET);
+                         nlflags, TIPC_NL_BEARER_GET);
        if (!hdr)
                return -EMSGSIZE;
 
@@ -657,7 +657,7 @@ int tipc_nl_bearer_dump(struct sk_buff *skb, struct netlink_callback *cb)
                if (!bearer)
                        continue;
 
-               err = __tipc_nl_add_bearer(&msg, bearer);
+               err = __tipc_nl_add_bearer(&msg, bearer, NLM_F_MULTI);
                if (err)
                        break;
        }
@@ -705,7 +705,7 @@ int tipc_nl_bearer_get(struct sk_buff *skb, struct genl_info *info)
                goto err_out;
        }
 
-       err = __tipc_nl_add_bearer(&msg, bearer);
+       err = __tipc_nl_add_bearer(&msg, bearer, 0);
        if (err)
                goto err_out;
        rtnl_unlock();
@@ -857,14 +857,14 @@ int tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info)
 }
 
 static int __tipc_nl_add_media(struct tipc_nl_msg *msg,
-                              struct tipc_media *media)
+                              struct tipc_media *media, int nlflags)
 {
        void *hdr;
        struct nlattr *attrs;
        struct nlattr *prop;
 
        hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,
-                         NLM_F_MULTI, TIPC_NL_MEDIA_GET);
+                         nlflags, TIPC_NL_MEDIA_GET);
        if (!hdr)
                return -EMSGSIZE;
 
@@ -916,7 +916,8 @@ int tipc_nl_media_dump(struct sk_buff *skb, struct netlink_callback *cb)
 
        rtnl_lock();
        for (; media_info_array[i] != NULL; i++) {
-               err = __tipc_nl_add_media(&msg, media_info_array[i]);
+               err = __tipc_nl_add_media(&msg, media_info_array[i],
+                                         NLM_F_MULTI);
                if (err)
                        break;
        }
@@ -963,7 +964,7 @@ int tipc_nl_media_get(struct sk_buff *skb, struct genl_info *info)
                goto err_out;
        }
 
-       err = __tipc_nl_add_media(&msg, media);
+       err = __tipc_nl_add_media(&msg, media, 0);
        if (err)
                goto err_out;
        rtnl_unlock();
index a6b30df6ec02ec22f1b4b44930bd1ceb168258f3..43a515dc97b0d4a2c7fca5bc9dc2951175201fff 100644 (file)
@@ -1145,11 +1145,8 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr)
                }
                /* Synchronize with parallel link if applicable */
                if (unlikely((l_ptr->flags & LINK_SYNCHING) && !msg_dup(msg))) {
-                       link_handle_out_of_seq_msg(l_ptr, skb);
-                       if (link_synch(l_ptr))
-                               link_retrieve_defq(l_ptr, &head);
-                       skb = NULL;
-                       goto unlock;
+                       if (!link_synch(l_ptr))
+                               goto unlock;
                }
                l_ptr->next_in_no++;
                if (unlikely(!skb_queue_empty(&l_ptr->deferdq)))
@@ -2013,7 +2010,7 @@ msg_full:
 
 /* Caller should hold appropriate locks to protect the link */
 static int __tipc_nl_add_link(struct net *net, struct tipc_nl_msg *msg,
-                             struct tipc_link *link)
+                             struct tipc_link *link, int nlflags)
 {
        int err;
        void *hdr;
@@ -2022,7 +2019,7 @@ static int __tipc_nl_add_link(struct net *net, struct tipc_nl_msg *msg,
        struct tipc_net *tn = net_generic(net, tipc_net_id);
 
        hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,
-                         NLM_F_MULTI, TIPC_NL_LINK_GET);
+                         nlflags, TIPC_NL_LINK_GET);
        if (!hdr)
                return -EMSGSIZE;
 
@@ -2095,7 +2092,7 @@ static int __tipc_nl_add_node_links(struct net *net, struct tipc_nl_msg *msg,
                if (!node->links[i])
                        continue;
 
-               err = __tipc_nl_add_link(net, msg, node->links[i]);
+               err = __tipc_nl_add_link(net, msg, node->links[i], NLM_F_MULTI);
                if (err)
                        return err;
        }
@@ -2143,7 +2140,6 @@ int tipc_nl_link_dump(struct sk_buff *skb, struct netlink_callback *cb)
                        err = __tipc_nl_add_node_links(net, &msg, node,
                                                       &prev_link);
                        tipc_node_unlock(node);
-                       tipc_node_put(node);
                        if (err)
                                goto out;
 
@@ -2210,7 +2206,7 @@ int tipc_nl_link_get(struct sk_buff *skb, struct genl_info *info)
                goto err_out;
        }
 
-       err = __tipc_nl_add_link(net, &msg, link);
+       err = __tipc_nl_add_link(net, &msg, link, 0);
        if (err)
                goto err_out;
 
index ab6183cdb12113565e3575e746470d5564f2ce22..77ff03ed1e18d13224f086c2315d7123cc931123 100644 (file)
@@ -102,7 +102,7 @@ static void tipc_conn_kref_release(struct kref *kref)
                }
                saddr->scope = -TIPC_NODE_SCOPE;
                kernel_bind(sock, (struct sockaddr *)saddr, sizeof(*saddr));
-               sk_release_kernel(sk);
+               sock_release(sock);
                con->sock = NULL;
        }
 
@@ -321,12 +321,9 @@ static struct socket *tipc_create_listen_sock(struct tipc_conn *con)
        struct socket *sock = NULL;
        int ret;
 
-       ret = sock_create_kern(AF_TIPC, SOCK_SEQPACKET, 0, &sock);
+       ret = __sock_create(s->net, AF_TIPC, SOCK_SEQPACKET, 0, &sock, 1);
        if (ret < 0)
                return NULL;
-
-       sk_change_net(sock->sk, s->net);
-
        ret = kernel_setsockopt(sock, SOL_TIPC, TIPC_IMPORTANCE,
                                (char *)&s->imp, sizeof(s->imp));
        if (ret < 0)
@@ -376,7 +373,7 @@ static struct socket *tipc_create_listen_sock(struct tipc_conn *con)
 
 create_err:
        kernel_sock_shutdown(sock, SHUT_RDWR);
-       sk_release_kernel(sock->sk);
+       sock_release(sock);
        return NULL;
 }
 
index ee90d74d7516e93af0587f5898d81e41f870e267..9074b5cede38b8edd75890b684a706d96b9f71ba 100644 (file)
@@ -1764,13 +1764,14 @@ static int tipc_sk_enqueue(struct sk_buff_head *inputq, struct sock *sk,
 int tipc_sk_rcv(struct net *net, struct sk_buff_head *inputq)
 {
        u32 dnode, dport = 0;
-       int err = -TIPC_ERR_NO_PORT;
+       int err;
        struct sk_buff *skb;
        struct tipc_sock *tsk;
        struct tipc_net *tn;
        struct sock *sk;
 
        while (skb_queue_len(inputq)) {
+               err = -TIPC_ERR_NO_PORT;
                skb = NULL;
                dport = tipc_skb_peek_port(inputq, dport);
                tsk = tipc_sk_lookup(net, dport);
index 433f287ee548391183c63d80b4db3736454a7f28..5266ea7b922b76d1977dea57cc7c227594c49285 100644 (file)
@@ -305,7 +305,7 @@ static struct sock *unix_find_socket_byinode(struct inode *i)
                    &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) {
                struct dentry *dentry = unix_sk(s)->path.dentry;
 
-               if (dentry && dentry->d_inode == i) {
+               if (dentry && d_backing_inode(dentry) == i) {
                        sock_hold(s);
                        goto found;
                }
@@ -778,7 +778,7 @@ static struct sock *unix_find_other(struct net *net,
                err = kern_path(sunname->sun_path, LOOKUP_FOLLOW, &path);
                if (err)
                        goto fail;
-               inode = path.dentry->d_inode;
+               inode = d_backing_inode(path.dentry);
                err = inode_permission(inode, MAY_WRITE);
                if (err)
                        goto put_fail;
@@ -839,7 +839,7 @@ static int unix_mknod(const char *sun_path, umode_t mode, struct path *res)
         */
        err = security_path_mknod(&path, dentry, mode, 0);
        if (!err) {
-               err = vfs_mknod(path.dentry->d_inode, dentry, mode, 0);
+               err = vfs_mknod(d_inode(path.dentry), dentry, mode, 0);
                if (!err) {
                        res->mnt = mntget(path.mnt);
                        res->dentry = dget(dentry);
@@ -905,7 +905,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
                        goto out_up;
                }
                addr->hash = UNIX_HASH_SIZE;
-               hash = path.dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1);
+               hash = d_backing_inode(path.dentry)->i_ino & (UNIX_HASH_SIZE-1);
                spin_lock(&unix_table_lock);
                u->path = path;
                list = &unix_socket_table[hash];
index ef542fbca9fe52dd85f6946e9d65ee8a28f6340e..c512f64d528766f940b30236bf3e3c8fa2047661 100644 (file)
@@ -25,7 +25,7 @@ static int sk_diag_dump_vfs(struct sock *sk, struct sk_buff *nlskb)
 
        if (dentry) {
                struct unix_diag_vfs uv = {
-                       .udiag_vfs_ino = dentry->d_inode->i_ino,
+                       .udiag_vfs_ino = d_backing_inode(dentry)->i_ino,
                        .udiag_vfs_dev = dentry->d_sb->s_dev,
                };
 
index 99f7012b23b9f2101bc8b3a35ed27871a7835b1d..a73a226f2d33f07261f606fa84ef4db8b91ed6fc 100644 (file)
@@ -95,39 +95,36 @@ static DECLARE_WAIT_QUEUE_HEAD(unix_gc_wait);
 
 unsigned int unix_tot_inflight;
 
-
 struct sock *unix_get_socket(struct file *filp)
 {
        struct sock *u_sock = NULL;
        struct inode *inode = file_inode(filp);
 
-       /*
-        *      Socket ?
-        */
+       /* Socket ? */
        if (S_ISSOCK(inode->i_mode) && !(filp->f_mode & FMODE_PATH)) {
                struct socket *sock = SOCKET_I(inode);
                struct sock *s = sock->sk;
 
-               /*
-                *      PF_UNIX ?
-                */
+               /* PF_UNIX ? */
                if (s && sock->ops && sock->ops->family == PF_UNIX)
                        u_sock = s;
        }
        return u_sock;
 }
 
-/*
- *     Keep the number of times in flight count for the file
- *     descriptor if it is for an AF_UNIX socket.
+/* Keep the number of times in flight count for the file
+ * descriptor if it is for an AF_UNIX socket.
  */
 
 void unix_inflight(struct file *fp)
 {
        struct sock *s = unix_get_socket(fp);
+
        if (s) {
                struct unix_sock *u = unix_sk(s);
+
                spin_lock(&unix_gc_lock);
+
                if (atomic_long_inc_return(&u->inflight) == 1) {
                        BUG_ON(!list_empty(&u->link));
                        list_add_tail(&u->link, &gc_inflight_list);
@@ -142,10 +139,13 @@ void unix_inflight(struct file *fp)
 void unix_notinflight(struct file *fp)
 {
        struct sock *s = unix_get_socket(fp);
+
        if (s) {
                struct unix_sock *u = unix_sk(s);
+
                spin_lock(&unix_gc_lock);
                BUG_ON(list_empty(&u->link));
+
                if (atomic_long_dec_and_test(&u->inflight))
                        list_del_init(&u->link);
                unix_tot_inflight--;
@@ -161,32 +161,27 @@ static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *),
 
        spin_lock(&x->sk_receive_queue.lock);
        skb_queue_walk_safe(&x->sk_receive_queue, skb, next) {
-               /*
-                *      Do we have file descriptors ?
-                */
+               /* Do we have file descriptors ? */
                if (UNIXCB(skb).fp) {
                        bool hit = false;
-                       /*
-                        *      Process the descriptors of this socket
-                        */
+                       /* Process the descriptors of this socket */
                        int nfd = UNIXCB(skb).fp->count;
                        struct file **fp = UNIXCB(skb).fp->fp;
+
                        while (nfd--) {
-                               /*
-                                *      Get the socket the fd matches
-                                *      if it indeed does so
-                                */
+                               /* Get the socket the fd matches if it indeed does so */
                                struct sock *sk = unix_get_socket(*fp++);
+
                                if (sk) {
                                        struct unix_sock *u = unix_sk(sk);
 
-                                       /*
-                                        * Ignore non-candidates, they could
+                                       /* Ignore non-candidates, they could
                                         * have been added to the queues after
                                         * starting the garbage collection
                                         */
                                        if (test_bit(UNIX_GC_CANDIDATE, &u->gc_flags)) {
                                                hit = true;
+
                                                func(u);
                                        }
                                }
@@ -203,24 +198,22 @@ static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *),
 static void scan_children(struct sock *x, void (*func)(struct unix_sock *),
                          struct sk_buff_head *hitlist)
 {
-       if (x->sk_state != TCP_LISTEN)
+       if (x->sk_state != TCP_LISTEN) {
                scan_inflight(x, func, hitlist);
-       else {
+       else {
                struct sk_buff *skb;
                struct sk_buff *next;
                struct unix_sock *u;
                LIST_HEAD(embryos);
 
-               /*
-                * For a listening socket collect the queued embryos
+               /* For a listening socket collect the queued embryos
                 * and perform a scan on them as well.
                 */
                spin_lock(&x->sk_receive_queue.lock);
                skb_queue_walk_safe(&x->sk_receive_queue, skb, next) {
                        u = unix_sk(skb->sk);
 
-                       /*
-                        * An embryo cannot be in-flight, so it's safe
+                       /* An embryo cannot be in-flight, so it's safe
                         * to use the list link.
                         */
                        BUG_ON(!list_empty(&u->link));
@@ -249,8 +242,7 @@ static void inc_inflight(struct unix_sock *usk)
 static void inc_inflight_move_tail(struct unix_sock *u)
 {
        atomic_long_inc(&u->inflight);
-       /*
-        * If this still might be part of a cycle, move it to the end
+       /* If this still might be part of a cycle, move it to the end
         * of the list, so that it's checked even if it was already
         * passed over
         */
@@ -263,8 +255,7 @@ static bool gc_in_progress;
 
 void wait_for_unix_gc(void)
 {
-       /*
-        * If number of inflight sockets is insane,
+       /* If number of inflight sockets is insane,
         * force a garbage collect right now.
         */
        if (unix_tot_inflight > UNIX_INFLIGHT_TRIGGER_GC && !gc_in_progress)
@@ -288,8 +279,7 @@ void unix_gc(void)
                goto out;
 
        gc_in_progress = true;
-       /*
-        * First, select candidates for garbage collection.  Only
+       /* First, select candidates for garbage collection.  Only
         * in-flight sockets are considered, and from those only ones
         * which don't have any external reference.
         *
@@ -320,15 +310,13 @@ void unix_gc(void)
                }
        }
 
-       /*
-        * Now remove all internal in-flight reference to children of
+       /* Now remove all internal in-flight reference to children of
         * the candidates.
         */
        list_for_each_entry(u, &gc_candidates, link)
                scan_children(&u->sk, dec_inflight, NULL);
 
-       /*
-        * Restore the references for children of all candidates,
+       /* Restore the references for children of all candidates,
         * which have remaining references.  Do this recursively, so
         * only those remain, which form cyclic references.
         *
@@ -350,8 +338,7 @@ void unix_gc(void)
        }
        list_del(&cursor);
 
-       /*
-        * not_cycle_list contains those sockets which do not make up a
+       /* not_cycle_list contains those sockets which do not make up a
         * cycle.  Restore these to the inflight list.
         */
        while (!list_empty(&not_cycle_list)) {
@@ -360,8 +347,7 @@ void unix_gc(void)
                list_move_tail(&u->link, &gc_inflight_list);
        }
 
-       /*
-        * Now gc_candidates contains only garbage.  Restore original
+       /* Now gc_candidates contains only garbage.  Restore original
         * inflight counters for these as well, and remove the skbuffs
         * which are creating the cycle(s).
         */
index 044eb4f89a91f6ec5aed6616b9a1323e746e82fe..79e86613712f22308b8ad4c3442403e09770f2ed 100644 (file)
@@ -282,7 +282,8 @@ $(obj)/%.dtb.S: $(obj)/%.dtb
        $(call cmd,dt_S_dtb)
 
 quiet_cmd_dtc = DTC     $@
-cmd_dtc = $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \
+cmd_dtc = mkdir -p $(dir ${dtc-tmp}) ; \
+       $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \
        $(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 \
                -i $(dir $<) $(DTC_FLAGS) \
                -d $(depfile).dtc.tmp $(dtc-tmp) ; \
diff --git a/scripts/check_extable.sh b/scripts/check_extable.sh
new file mode 100755 (executable)
index 0000000..0fb6b1c
--- /dev/null
@@ -0,0 +1,146 @@
+#! /bin/bash
+# (c) 2015, Quentin Casasnovas <quentin.casasnovas@oracle.com>
+
+obj=$1
+
+file ${obj} | grep -q ELF || (echo "${obj} is not and ELF file." 1>&2 ; exit 0)
+
+# Bail out early if there isn't an __ex_table section in this object file.
+objdump -hj __ex_table ${obj} 2> /dev/null > /dev/null
+[ $? -ne 0 ] && exit 0
+
+white_list=.text,.fixup
+
+suspicious_relocs=$(objdump -rj __ex_table ${obj}  | tail -n +6 |
+                       grep -v $(eval echo -e{${white_list}}) | awk '{print $3}')
+
+# No suspicious relocs in __ex_table, jobs a good'un
+[ -z "${suspicious_relocs}" ] && exit 0
+
+
+# After this point, something is seriously wrong since we just found out we
+# have some relocations in __ex_table which point to sections which aren't
+# white listed.  If you're adding a new section in the Linux kernel, and
+# you're expecting this section to contain code which can fault (i.e. the
+# __ex_table relocation to your new section is expected), simply add your
+# new section to the white_list variable above.  If not, you're probably
+# doing something wrong and the rest of this code is just trying to print
+# you more information about it.
+
+function find_section_offset_from_symbol()
+{
+    eval $(objdump -t ${obj} | grep ${1} | sed 's/\([0-9a-f]\+\) .\{7\} \([^ \t]\+\).*/section="\2"; section_offset="0x\1" /')
+
+    # addr2line takes addresses in hexadecimal...
+    section_offset=$(printf "0x%016x" $(( ${section_offset} + $2 )) )
+}
+
+function find_symbol_and_offset_from_reloc()
+{
+    # Extract symbol and offset from the objdump output
+    eval $(echo $reloc | sed 's/\([^+]\+\)+\?\(0x[0-9a-f]\+\)\?/symbol="\1"; symbol_offset="\2"/')
+
+    # When the relocation points to the begining of a symbol or section, it
+    # won't print the offset since it is zero.
+    if [ -z "${symbol_offset}" ]; then
+       symbol_offset=0x0
+    fi
+}
+
+function find_alt_replacement_target()
+{
+    # The target of the .altinstr_replacement is the relocation just before
+    # the .altinstr_replacement one.
+    eval $(objdump -rj .altinstructions ${obj} | grep -B1 "${section}+${section_offset}" | head -n1 | awk '{print $3}' |
+          sed 's/\([^+]\+\)+\(0x[0-9a-f]\+\)/alt_target_section="\1"; alt_target_offset="\2"/')
+}
+
+function handle_alt_replacement_reloc()
+{
+    # This will define alt_target_section and alt_target_section_offset
+    find_alt_replacement_target ${section} ${section_offset}
+
+    echo "Error: found a reference to .altinstr_replacement in __ex_table:"
+    addr2line -fip -j ${alt_target_section} -e ${obj} ${alt_target_offset} | awk '{print "\t" $0}'
+
+    error=true
+}
+
+function is_executable_section()
+{
+    objdump -hwj ${section} ${obj} | grep -q CODE
+    return $?
+}
+
+function handle_suspicious_generic_reloc()
+{
+    if is_executable_section ${section}; then
+       # We've got a relocation to a non white listed _executable_
+       # section, print a warning so the developper adds the section to
+       # the white list or fix his code.  We try to pretty-print the file
+       # and line number where that relocation was added.
+       echo "Warning: found a reference to section \"${section}\" in __ex_table:"
+       addr2line -fip -j ${section} -e ${obj} ${section_offset} | awk '{print "\t" $0}'
+    else
+       # Something is definitively wrong here since we've got a relocation
+       # to a non-executable section, there's no way this would ever be
+       # running in the kernel.
+       echo "Error: found a reference to non-executable section \"${section}\" in __ex_table at offset ${section_offset}"
+       error=true
+    fi
+}
+
+function handle_suspicious_reloc()
+{
+    case "${section}" in
+       ".altinstr_replacement")
+           handle_alt_replacement_reloc ${section} ${section_offset}
+           ;;
+       *)
+           handle_suspicious_generic_reloc ${section} ${section_offset}
+           ;;
+    esac
+}
+
+function diagnose()
+{
+
+    for reloc in ${suspicious_relocs}; do
+       # Let's find out where the target of the relocation in __ex_table
+       # is, this will define ${symbol} and ${symbol_offset}
+       find_symbol_and_offset_from_reloc ${reloc}
+
+       # When there's a global symbol at the place of the relocation,
+       # objdump will use it instead of giving us a section+offset, so
+       # let's find out which section is this symbol in and the total
+       # offset withing that section.
+       find_section_offset_from_symbol ${symbol} ${symbol_offset}
+
+       # In this case objdump was presenting us with a reloc to a symbol
+       # rather than a section. Now that we've got the actual section,
+       # we can skip it if it's in the white_list.
+       if [ -z "$( echo $section | grep -v $(eval echo -e{${white_list}}))" ]; then
+           continue;
+       fi
+
+       # Will either print a warning if the relocation happens to be in a
+       # section we do not know but has executable bit set, or error out.
+       handle_suspicious_reloc
+    done
+}
+
+function check_debug_info() {
+    objdump -hj .debug_info ${obj} 2> /dev/null > /dev/null ||
+       echo -e "${obj} does not contain debug information, the addr2line output will be limited.\n" \
+            "Recompile ${obj} with CONFIG_DEBUG_INFO to get a more useful output."
+}
+
+check_debug_info
+
+diagnose
+
+if [ "${error}" ]; then
+    exit 1
+fi
+
+exit 0
old mode 100644 (file)
new mode 100755 (executable)
index e9cc689..74086a5
@@ -1,8 +1,8 @@
 #!/usr/bin/env python
 
-"""Find Kconfig identifiers that are referenced but not defined."""
+"""Find Kconfig symbols that are referenced but not defined."""
 
-# (c) 2014 Valentin Rothberg <valentinrothberg@gmail.com>
+# (c) 2014-2015 Valentin Rothberg <Valentin.Rothberg@lip6.fr>
 # (c) 2014 Stefan Hengelein <stefan.hengelein@fau.de>
 #
 # Licensed under the terms of the GNU GPL License version 2
@@ -10,7 +10,9 @@
 
 import os
 import re
+import sys
 from subprocess import Popen, PIPE, STDOUT
+from optparse import OptionParser
 
 
 # regex expressions
@@ -32,22 +34,149 @@ REGEX_KCONFIG_HELP = re.compile(r"^\s+(help|---help---)\s*$")
 REGEX_FILTER_FEATURES = re.compile(r"[A-Za-z0-9]$")
 
 
+def parse_options():
+    """The user interface of this module."""
+    usage = "%prog [options]\n\n"                                              \
+            "Run this tool to detect Kconfig symbols that are referenced but " \
+            "not defined in\nKconfig.  The output of this tool has the "       \
+            "format \'Undefined symbol\\tFile list\'\n\n"                      \
+            "If no option is specified, %prog will default to check your\n"    \
+            "current tree.  Please note that specifying commits will "         \
+            "\'git reset --hard\'\nyour current tree!  You may save "          \
+            "uncommitted changes to avoid losing data."
+
+    parser = OptionParser(usage=usage)
+
+    parser.add_option('-c', '--commit', dest='commit', action='store',
+                      default="",
+                      help="Check if the specified commit (hash) introduces "
+                           "undefined Kconfig symbols.")
+
+    parser.add_option('-d', '--diff', dest='diff', action='store',
+                      default="",
+                      help="Diff undefined symbols between two commits.  The "
+                           "input format bases on Git log's "
+                           "\'commmit1..commit2\'.")
+
+    parser.add_option('', '--force', dest='force', action='store_true',
+                      default=False,
+                      help="Reset current Git tree even when it's dirty.")
+
+    (opts, _) = parser.parse_args()
+
+    if opts.commit and opts.diff:
+        sys.exit("Please specify only one option at once.")
+
+    if opts.diff and not re.match(r"^[\w\-\.]+\.\.[\w\-\.]+$", opts.diff):
+        sys.exit("Please specify valid input in the following format: "
+                 "\'commmit1..commit2\'")
+
+    if opts.commit or opts.diff:
+        if not opts.force and tree_is_dirty():
+            sys.exit("The current Git tree is dirty (see 'git status').  "
+                     "Running this script may\ndelete important data since it "
+                     "calls 'git reset --hard' for some performance\nreasons. "
+                     " Please run this script in a clean Git tree or pass "
+                     "'--force' if you\nwant to ignore this warning and "
+                     "continue.")
+
+    return opts
+
+
 def main():
     """Main function of this module."""
+    opts = parse_options()
+
+    if opts.commit or opts.diff:
+        head = get_head()
+
+        # get commit range
+        commit_a = None
+        commit_b = None
+        if opts.commit:
+            commit_a = opts.commit + "~"
+            commit_b = opts.commit
+        elif opts.diff:
+            split = opts.diff.split("..")
+            commit_a = split[0]
+            commit_b = split[1]
+            undefined_a = {}
+            undefined_b = {}
+
+        # get undefined items before the commit
+        execute("git reset --hard %s" % commit_a)
+        undefined_a = check_symbols()
+
+        # get undefined items for the commit
+        execute("git reset --hard %s" % commit_b)
+        undefined_b = check_symbols()
+
+        # report cases that are present for the commit but not before
+        for feature in sorted(undefined_b):
+            # feature has not been undefined before
+            if not feature in undefined_a:
+                files = sorted(undefined_b.get(feature))
+                print "%s\t%s" % (feature, ", ".join(files))
+            # check if there are new files that reference the undefined feature
+            else:
+                files = sorted(undefined_b.get(feature) -
+                               undefined_a.get(feature))
+                if files:
+                    print "%s\t%s" % (feature, ", ".join(files))
+
+        # reset to head
+        execute("git reset --hard %s" % head)
+
+    # default to check the entire tree
+    else:
+        undefined = check_symbols()
+        for feature in sorted(undefined):
+            files = sorted(undefined.get(feature))
+            print "%s\t%s" % (feature, ", ".join(files))
+
+
+def execute(cmd):
+    """Execute %cmd and return stdout.  Exit in case of error."""
+    pop = Popen(cmd, stdout=PIPE, stderr=STDOUT, shell=True)
+    (stdout, _) = pop.communicate()  # wait until finished
+    if pop.returncode != 0:
+        sys.exit(stdout)
+    return stdout
+
+
+def tree_is_dirty():
+    """Return true if the current working tree is dirty (i.e., if any file has
+    been added, deleted, modified, renamed or copied but not committed)."""
+    stdout = execute("git status --porcelain")
+    for line in stdout:
+        if re.findall(r"[URMADC]{1}", line[:2]):
+            return True
+    return False
+
+
+def get_head():
+    """Return commit hash of current HEAD."""
+    stdout = execute("git rev-parse HEAD")
+    return stdout.strip('\n')
+
+
+def check_symbols():
+    """Find undefined Kconfig symbols and return a dict with the symbol as key
+    and a list of referencing files as value."""
     source_files = []
     kconfig_files = []
     defined_features = set()
     referenced_features = dict()  # {feature: [files]}
 
     # use 'git ls-files' to get the worklist
-    pop = Popen("git ls-files", stdout=PIPE, stderr=STDOUT, shell=True)
-    (stdout, _) = pop.communicate()  # wait until finished
+    stdout = execute("git ls-files")
     if len(stdout) > 0 and stdout[-1] == "\n":
         stdout = stdout[:-1]
 
     for gitfile in stdout.rsplit("\n"):
-        if ".git" in gitfile or "ChangeLog" in gitfile or \
-                ".log" in gitfile or os.path.isdir(gitfile):
+        if ".git" in gitfile or "ChangeLog" in gitfile or      \
+                ".log" in gitfile or os.path.isdir(gitfile) or \
+                gitfile.startswith("tools/"):
             continue
         if REGEX_FILE_KCONFIG.match(gitfile):
             kconfig_files.append(gitfile)
@@ -61,7 +190,7 @@ def main():
     for kfile in kconfig_files:
         parse_kconfig_file(kfile, defined_features, referenced_features)
 
-    print "Undefined symbol used\tFile list"
+    undefined = {}  # {feature: [files]}
     for feature in sorted(referenced_features):
         # filter some false positives
         if feature == "FOO" or feature == "BAR" or \
@@ -72,8 +201,8 @@ def main():
                 # avoid false positives for kernel modules
                 if feature[:-len("_MODULE")] in defined_features:
                     continue
-            files = referenced_features.get(feature)
-            print "%s\t%s" % (feature, ", ".join(files))
+            undefined[feature] = referenced_features.get(feature)
+    return undefined
 
 
 def parse_source_file(sfile, referenced_features):
index d439856f81760b7e12497e2167d641120ccb4a39..91ee1b2e0f9aa65fbdcb471d8f6695489453029f 100644 (file)
@@ -776,6 +776,7 @@ static const char *sech_name(struct elf_info *elf, Elf_Shdr *sechdr)
  * "foo" will match an exact string equal to "foo"
  * "*foo" will match a string that ends with "foo"
  * "foo*" will match a string that begins with "foo"
+ * "*foo*" will match a string that contains "foo"
  */
 static int match(const char *sym, const char * const pat[])
 {
@@ -784,8 +785,17 @@ static int match(const char *sym, const char * const pat[])
                p = *pat++;
                const char *endp = p + strlen(p) - 1;
 
+               /* "*foo*" */
+               if (*p == '*' && *endp == '*') {
+                       char *here, *bare = strndup(p + 1, strlen(p) - 2);
+
+                       here = strstr(sym, bare);
+                       free(bare);
+                       if (here != NULL)
+                               return 1;
+               }
                /* "*foo" */
-               if (*p == '*') {
+               else if (*p == '*') {
                        if (strrcmp(sym, p + 1) == 0)
                                return 1;
                }
@@ -873,7 +883,10 @@ static void check_section(const char *modname, struct elf_info *elf,
 #define ALL_EXIT_SECTIONS EXIT_SECTIONS, ALL_XXXEXIT_SECTIONS
 
 #define DATA_SECTIONS ".data", ".data.rel"
-#define TEXT_SECTIONS ".text", ".text.unlikely"
+#define TEXT_SECTIONS ".text", ".text.unlikely", ".sched.text", \
+               ".kprobes.text"
+#define OTHER_TEXT_SECTIONS ".ref.text", ".head.text", ".spinlock.text", \
+               ".fixup", ".entry.text", ".exception.text", ".text.*"
 
 #define INIT_SECTIONS      ".init.*"
 #define MEM_INIT_SECTIONS  ".meminit.*"
@@ -881,6 +894,9 @@ static void check_section(const char *modname, struct elf_info *elf,
 #define EXIT_SECTIONS      ".exit.*"
 #define MEM_EXIT_SECTIONS  ".memexit.*"
 
+#define ALL_TEXT_SECTIONS  ALL_INIT_TEXT_SECTIONS, ALL_EXIT_TEXT_SECTIONS, \
+               TEXT_SECTIONS, OTHER_TEXT_SECTIONS
+
 /* init data sections */
 static const char *const init_data_sections[] =
        { ALL_INIT_DATA_SECTIONS, NULL };
@@ -892,6 +908,9 @@ static const char *const init_sections[] = { ALL_INIT_SECTIONS, NULL };
 static const char *const init_exit_sections[] =
        {ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS, NULL };
 
+/* all text sections */
+static const char *const text_sections[] = { ALL_TEXT_SECTIONS, NULL };
+
 /* data section */
 static const char *const data_sections[] = { DATA_SECTIONS, NULL };
 
@@ -910,6 +929,7 @@ static const char *const data_sections[] = { DATA_SECTIONS, NULL };
 static const char *const head_sections[] = { ".head.text*", NULL };
 static const char *const linker_symbols[] =
        { "__init_begin", "_sinittext", "_einittext", NULL };
+static const char *const optim_symbols[] = { "*.constprop.*", NULL };
 
 enum mismatch {
        TEXT_TO_ANY_INIT,
@@ -921,34 +941,65 @@ enum mismatch {
        ANY_INIT_TO_ANY_EXIT,
        ANY_EXIT_TO_ANY_INIT,
        EXPORT_TO_INIT_EXIT,
+       EXTABLE_TO_NON_TEXT,
 };
 
+/**
+ * Describe how to match sections on different criterias:
+ *
+ * @fromsec: Array of sections to be matched.
+ *
+ * @bad_tosec: Relocations applied to a section in @fromsec to a section in
+ * this array is forbidden (black-list).  Can be empty.
+ *
+ * @good_tosec: Relocations applied to a section in @fromsec must be
+ * targetting sections in this array (white-list).  Can be empty.
+ *
+ * @mismatch: Type of mismatch.
+ *
+ * @symbol_white_list: Do not match a relocation to a symbol in this list
+ * even if it is targetting a section in @bad_to_sec.
+ *
+ * @handler: Specific handler to call when a match is found.  If NULL,
+ * default_mismatch_handler() will be called.
+ *
+ */
 struct sectioncheck {
        const char *fromsec[20];
-       const char *tosec[20];
+       const char *bad_tosec[20];
+       const char *good_tosec[20];
        enum mismatch mismatch;
        const char *symbol_white_list[20];
+       void (*handler)(const char *modname, struct elf_info *elf,
+                       const struct sectioncheck* const mismatch,
+                       Elf_Rela *r, Elf_Sym *sym, const char *fromsec);
+
 };
 
+static void extable_mismatch_handler(const char *modname, struct elf_info *elf,
+                                    const struct sectioncheck* const mismatch,
+                                    Elf_Rela *r, Elf_Sym *sym,
+                                    const char *fromsec);
+
 static const struct sectioncheck sectioncheck[] = {
 /* Do not reference init/exit code/data from
  * normal code and data
  */
 {
        .fromsec = { TEXT_SECTIONS, NULL },
-       .tosec   = { ALL_INIT_SECTIONS, NULL },
+       .bad_tosec = { ALL_INIT_SECTIONS, NULL },
        .mismatch = TEXT_TO_ANY_INIT,
        .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
 },
 {
        .fromsec = { DATA_SECTIONS, NULL },
-       .tosec   = { ALL_XXXINIT_SECTIONS, NULL },
+       .bad_tosec = { ALL_XXXINIT_SECTIONS, NULL },
        .mismatch = DATA_TO_ANY_INIT,
        .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
 },
 {
        .fromsec = { DATA_SECTIONS, NULL },
-       .tosec   = { INIT_SECTIONS, NULL },
+       .bad_tosec = { INIT_SECTIONS, NULL },
        .mismatch = DATA_TO_ANY_INIT,
        .symbol_white_list = {
                "*_template", "*_timer", "*_sht", "*_ops",
@@ -957,56 +1008,66 @@ static const struct sectioncheck sectioncheck[] = {
 },
 {
        .fromsec = { TEXT_SECTIONS, NULL },
-       .tosec   = { ALL_EXIT_SECTIONS, NULL },
+       .bad_tosec = { ALL_EXIT_SECTIONS, NULL },
        .mismatch = TEXT_TO_ANY_EXIT,
        .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
 },
 {
        .fromsec = { DATA_SECTIONS, NULL },
-       .tosec   = { ALL_EXIT_SECTIONS, NULL },
+       .bad_tosec = { ALL_EXIT_SECTIONS, NULL },
        .mismatch = DATA_TO_ANY_EXIT,
        .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
 },
 /* Do not reference init code/data from meminit code/data */
 {
        .fromsec = { ALL_XXXINIT_SECTIONS, NULL },
-       .tosec   = { INIT_SECTIONS, NULL },
+       .bad_tosec = { INIT_SECTIONS, NULL },
        .mismatch = XXXINIT_TO_SOME_INIT,
        .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
 },
 /* Do not reference exit code/data from memexit code/data */
 {
        .fromsec = { ALL_XXXEXIT_SECTIONS, NULL },
-       .tosec   = { EXIT_SECTIONS, NULL },
+       .bad_tosec = { EXIT_SECTIONS, NULL },
        .mismatch = XXXEXIT_TO_SOME_EXIT,
        .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
 },
 /* Do not use exit code/data from init code */
 {
        .fromsec = { ALL_INIT_SECTIONS, NULL },
-       .tosec   = { ALL_EXIT_SECTIONS, NULL },
+       .bad_tosec = { ALL_EXIT_SECTIONS, NULL },
        .mismatch = ANY_INIT_TO_ANY_EXIT,
        .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
 },
 /* Do not use init code/data from exit code */
 {
        .fromsec = { ALL_EXIT_SECTIONS, NULL },
-       .tosec   = { ALL_INIT_SECTIONS, NULL },
+       .bad_tosec = { ALL_INIT_SECTIONS, NULL },
        .mismatch = ANY_EXIT_TO_ANY_INIT,
        .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
 },
 {
        .fromsec = { ALL_PCI_INIT_SECTIONS, NULL },
-       .tosec   = { INIT_SECTIONS, NULL },
+       .bad_tosec = { INIT_SECTIONS, NULL },
        .mismatch = ANY_INIT_TO_ANY_EXIT,
        .symbol_white_list = { NULL },
 },
 /* Do not export init/exit functions or data */
 {
        .fromsec = { "__ksymtab*", NULL },
-       .tosec   = { INIT_SECTIONS, EXIT_SECTIONS, NULL },
+       .bad_tosec = { INIT_SECTIONS, EXIT_SECTIONS, NULL },
        .mismatch = EXPORT_TO_INIT_EXIT,
        .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
+},
+{
+       .fromsec = { "__ex_table", NULL },
+       /* If you're adding any new black-listed sections in here, consider
+        * adding a special 'printer' for them in scripts/check_extable.
+        */
+       .bad_tosec = { ".altinstr_replacement", NULL },
+       .good_tosec = {ALL_TEXT_SECTIONS , NULL},
+       .mismatch = EXTABLE_TO_NON_TEXT,
+       .handler = extable_mismatch_handler,
 }
 };
 
@@ -1017,10 +1078,22 @@ static const struct sectioncheck *section_mismatch(
        int elems = sizeof(sectioncheck) / sizeof(struct sectioncheck);
        const struct sectioncheck *check = &sectioncheck[0];
 
+       /*
+        * The target section could be the SHT_NUL section when we're
+        * handling relocations to un-resolved symbols, trying to match it
+        * doesn't make much sense and causes build failures on parisc and
+        * mn10300 architectures.
+        */
+       if (*tosec == '\0')
+               return NULL;
+
        for (i = 0; i < elems; i++) {
-               if (match(fromsec, check->fromsec) &&
-                   match(tosec, check->tosec))
-                       return check;
+               if (match(fromsec, check->fromsec)) {
+                       if (check->bad_tosec[0] && match(tosec, check->bad_tosec))
+                               return check;
+                       if (check->good_tosec[0] && !match(tosec, check->good_tosec))
+                               return check;
+               }
                check++;
        }
        return NULL;
@@ -1067,6 +1140,17 @@ static const struct sectioncheck *section_mismatch(
  *   This pattern is identified by
  *   refsymname = __init_begin, _sinittext, _einittext
  *
+ * Pattern 5:
+ *   GCC may optimize static inlines when fed constant arg(s) resulting
+ *   in functions like cpumask_empty() -- generating an associated symbol
+ *   cpumask_empty.constprop.3 that appears in the audit.  If the const that
+ *   is passed in comes from __init, like say nmi_ipi_mask, we get a
+ *   meaningless section warning.  May need to add isra symbols too...
+ *   This pattern is identified by
+ *   tosec   = init section
+ *   fromsec = text section
+ *   refsymname = *.constprop.*
+ *
  **/
 static int secref_whitelist(const struct sectioncheck *mismatch,
                            const char *fromsec, const char *fromsym,
@@ -1099,6 +1183,12 @@ static int secref_whitelist(const struct sectioncheck *mismatch,
        if (match(tosym, linker_symbols))
                return 0;
 
+       /* Check for pattern 5 */
+       if (match(fromsec, text_sections) &&
+           match(tosec, init_sections) &&
+           match(fromsym, optim_symbols))
+               return 0;
+
        return 1;
 }
 
@@ -1261,6 +1351,15 @@ static void print_section_list(const char * const list[20])
        fprintf(stderr, "\n");
 }
 
+static inline void get_pretty_name(int is_func, const char** name, const char** name_p)
+{
+       switch (is_func) {
+       case 0: *name = "variable"; *name_p = ""; break;
+       case 1: *name = "function"; *name_p = "()"; break;
+       default: *name = "(unknown reference)"; *name_p = ""; break;
+       }
+}
+
 /*
  * Print a warning about a section mismatch.
  * Try to find symbols near it so user can find it.
@@ -1280,21 +1379,13 @@ static void report_sec_mismatch(const char *modname,
        char *prl_from;
        char *prl_to;
 
-       switch (from_is_func) {
-       case 0: from = "variable"; from_p = "";   break;
-       case 1: from = "function"; from_p = "()"; break;
-       default: from = "(unknown reference)"; from_p = ""; break;
-       }
-       switch (to_is_func) {
-       case 0: to = "variable"; to_p = "";   break;
-       case 1: to = "function"; to_p = "()"; break;
-       default: to = "(unknown reference)"; to_p = ""; break;
-       }
-
        sec_mismatch_count++;
        if (!sec_mismatch_verbose)
                return;
 
+       get_pretty_name(from_is_func, &from, &from_p);
+       get_pretty_name(to_is_func, &to, &to_p);
+
        warn("%s(%s+0x%llx): Section mismatch in reference from the %s %s%s "
             "to the %s %s:%s%s\n",
             modname, fromsec, fromaddr, from, fromsym, from_p, to, tosec,
@@ -1408,41 +1499,179 @@ static void report_sec_mismatch(const char *modname,
                tosym, prl_to, prl_to, tosym);
                free(prl_to);
                break;
+       case EXTABLE_TO_NON_TEXT:
+               fatal("There's a special handler for this mismatch type, "
+                     "we should never get here.");
+               break;
        }
        fprintf(stderr, "\n");
 }
 
-static void check_section_mismatch(const char *modname, struct elf_info *elf,
-                                  Elf_Rela *r, Elf_Sym *sym, const char *fromsec)
+static void default_mismatch_handler(const char *modname, struct elf_info *elf,
+                                    const struct sectioncheck* const mismatch,
+                                    Elf_Rela *r, Elf_Sym *sym, const char *fromsec)
 {
        const char *tosec;
-       const struct sectioncheck *mismatch;
+       Elf_Sym *to;
+       Elf_Sym *from;
+       const char *tosym;
+       const char *fromsym;
+
+       from = find_elf_symbol2(elf, r->r_offset, fromsec);
+       fromsym = sym_name(elf, from);
+
+       if (!strncmp(fromsym, "reference___initcall",
+                    sizeof("reference___initcall")-1))
+               return;
 
        tosec = sec_name(elf, get_secindex(elf, sym));
-       mismatch = section_mismatch(fromsec, tosec);
+       to = find_elf_symbol(elf, r->r_addend, sym);
+       tosym = sym_name(elf, to);
+
+       /* check whitelist - we may ignore it */
+       if (secref_whitelist(mismatch,
+                            fromsec, fromsym, tosec, tosym)) {
+               report_sec_mismatch(modname, mismatch,
+                                   fromsec, r->r_offset, fromsym,
+                                   is_function(from), tosec, tosym,
+                                   is_function(to));
+       }
+}
+
+static int is_executable_section(struct elf_info* elf, unsigned int section_index)
+{
+       if (section_index > elf->num_sections)
+               fatal("section_index is outside elf->num_sections!\n");
+
+       return ((elf->sechdrs[section_index].sh_flags & SHF_EXECINSTR) == SHF_EXECINSTR);
+}
+
+/*
+ * We rely on a gross hack in section_rel[a]() calling find_extable_entry_size()
+ * to know the sizeof(struct exception_table_entry) for the target architecture.
+ */
+static unsigned int extable_entry_size = 0;
+static void find_extable_entry_size(const char* const sec, const Elf_Rela* r)
+{
+       /*
+        * If we're currently checking the second relocation within __ex_table,
+        * that relocation offset tells us the offsetof(struct
+        * exception_table_entry, fixup) which is equal to sizeof(struct
+        * exception_table_entry) divided by two.  We use that to our advantage
+        * since there's no portable way to get that size as every architecture
+        * seems to go with different sized types.  Not pretty but better than
+        * hard-coding the size for every architecture..
+        */
+       if (!extable_entry_size)
+               extable_entry_size = r->r_offset * 2;
+}
+
+static inline bool is_extable_fault_address(Elf_Rela *r)
+{
+       /*
+        * extable_entry_size is only discovered after we've handled the
+        * _second_ relocation in __ex_table, so only abort when we're not
+        * handling the first reloc and extable_entry_size is zero.
+        */
+       if (r->r_offset && extable_entry_size == 0)
+               fatal("extable_entry size hasn't been discovered!\n");
+
+       return ((r->r_offset == 0) ||
+               (r->r_offset % extable_entry_size == 0));
+}
+
+#define is_second_extable_reloc(Start, Cur, Sec)                       \
+       (((Cur) == (Start) + 1) && (strcmp("__ex_table", (Sec)) == 0))
+
+static void report_extable_warnings(const char* modname, struct elf_info* elf,
+                                   const struct sectioncheck* const mismatch,
+                                   Elf_Rela* r, Elf_Sym* sym,
+                                   const char* fromsec, const char* tosec)
+{
+       Elf_Sym* fromsym = find_elf_symbol2(elf, r->r_offset, fromsec);
+       const char* fromsym_name = sym_name(elf, fromsym);
+       Elf_Sym* tosym = find_elf_symbol(elf, r->r_addend, sym);
+       const char* tosym_name = sym_name(elf, tosym);
+       const char* from_pretty_name;
+       const char* from_pretty_name_p;
+       const char* to_pretty_name;
+       const char* to_pretty_name_p;
+
+       get_pretty_name(is_function(fromsym),
+                       &from_pretty_name, &from_pretty_name_p);
+       get_pretty_name(is_function(tosym),
+                       &to_pretty_name, &to_pretty_name_p);
+
+       warn("%s(%s+0x%lx): Section mismatch in reference"
+            " from the %s %s%s to the %s %s:%s%s\n",
+            modname, fromsec, (long)r->r_offset, from_pretty_name,
+            fromsym_name, from_pretty_name_p,
+            to_pretty_name, tosec, tosym_name, to_pretty_name_p);
+
+       if (!match(tosec, mismatch->bad_tosec) &&
+           is_executable_section(elf, get_secindex(elf, sym)))
+               fprintf(stderr,
+                       "The relocation at %s+0x%lx references\n"
+                       "section \"%s\" which is not in the list of\n"
+                       "authorized sections.  If you're adding a new section\n"
+                       "and/or if this reference is valid, add \"%s\" to the\n"
+                       "list of authorized sections to jump to on fault.\n"
+                       "This can be achieved by adding \"%s\" to \n"
+                       "OTHER_TEXT_SECTIONS in scripts/mod/modpost.c.\n",
+                       fromsec, (long)r->r_offset, tosec, tosec, tosec);
+}
+
+static void extable_mismatch_handler(const char* modname, struct elf_info *elf,
+                                    const struct sectioncheck* const mismatch,
+                                    Elf_Rela* r, Elf_Sym* sym,
+                                    const char *fromsec)
+{
+       const char* tosec = sec_name(elf, get_secindex(elf, sym));
+
+       sec_mismatch_count++;
+
+       if (sec_mismatch_verbose)
+               report_extable_warnings(modname, elf, mismatch, r, sym,
+                                       fromsec, tosec);
+
+       if (match(tosec, mismatch->bad_tosec))
+               fatal("The relocation at %s+0x%lx references\n"
+                     "section \"%s\" which is black-listed.\n"
+                     "Something is seriously wrong and should be fixed.\n"
+                     "You might get more information about where this is\n"
+                     "coming from by using scripts/check_extable.sh %s\n",
+                     fromsec, (long)r->r_offset, tosec, modname);
+       else if (!is_executable_section(elf, get_secindex(elf, sym))) {
+               if (is_extable_fault_address(r))
+                       fatal("The relocation at %s+0x%lx references\n"
+                             "section \"%s\" which is not executable, IOW\n"
+                             "it is not possible for the kernel to fault\n"
+                             "at that address.  Something is seriously wrong\n"
+                             "and should be fixed.\n",
+                             fromsec, (long)r->r_offset, tosec);
+               else
+                       fatal("The relocation at %s+0x%lx references\n"
+                             "section \"%s\" which is not executable, IOW\n"
+                             "the kernel will fault if it ever tries to\n"
+                             "jump to it.  Something is seriously wrong\n"
+                             "and should be fixed.\n",
+                             fromsec, (long)r->r_offset, tosec);
+       }
+}
+
+static void check_section_mismatch(const char *modname, struct elf_info *elf,
+                                  Elf_Rela *r, Elf_Sym *sym, const char *fromsec)
+{
+       const char *tosec = sec_name(elf, get_secindex(elf, sym));;
+       const struct sectioncheck *mismatch = section_mismatch(fromsec, tosec);
+
        if (mismatch) {
-               Elf_Sym *to;
-               Elf_Sym *from;
-               const char *tosym;
-               const char *fromsym;
-
-               from = find_elf_symbol2(elf, r->r_offset, fromsec);
-               fromsym = sym_name(elf, from);
-               to = find_elf_symbol(elf, r->r_addend, sym);
-               tosym = sym_name(elf, to);
-
-               if (!strncmp(fromsym, "reference___initcall",
-                               sizeof("reference___initcall")-1))
-                       return;
-
-               /* check whitelist - we may ignore it */
-               if (secref_whitelist(mismatch,
-                                       fromsec, fromsym, tosec, tosym)) {
-                       report_sec_mismatch(modname, mismatch,
-                          fromsec, r->r_offset, fromsym,
-                          is_function(from), tosec, tosym,
-                          is_function(to));
-               }
+               if (mismatch->handler)
+                       mismatch->handler(modname, elf,  mismatch,
+                                         r, sym, fromsec);
+               else
+                       default_mismatch_handler(modname, elf, mismatch,
+                                                r, sym, fromsec);
        }
 }
 
@@ -1582,6 +1811,8 @@ static void section_rela(const char *modname, struct elf_info *elf,
                /* Skip special sections */
                if (is_shndx_special(sym->st_shndx))
                        continue;
+               if (is_second_extable_reloc(start, rela, fromsec))
+                       find_extable_entry_size(fromsec, &r);
                check_section_mismatch(modname, elf, &r, sym, fromsec);
        }
 }
@@ -1640,6 +1871,8 @@ static void section_rel(const char *modname, struct elf_info *elf,
                /* Skip special sections */
                if (is_shndx_special(sym->st_shndx))
                        continue;
+               if (is_second_extable_reloc(start, rel, fromsec))
+                       find_extable_entry_size(fromsec, &r);
                check_section_mismatch(modname, elf, &r, sym, fromsec);
        }
 }
index 7db9954f1af2c56c42400746f367f5f4d9906ca8..ad4fa49ad1db23a70dfa16751a9c7f8ec006e854 100644 (file)
@@ -365,7 +365,7 @@ void __aa_fs_profile_rmdir(struct aa_profile *profile)
                if (!profile->dents[i])
                        continue;
 
-               r = profile->dents[i]->d_inode->i_private;
+               r = d_inode(profile->dents[i])->i_private;
                securityfs_remove(profile->dents[i]);
                aa_put_replacedby(r);
                profile->dents[i] = NULL;
index fdaa50cb1876e2ac5a1cae2d54d74794db5f2f65..913f377a038a672f8cdc07c0aaa23721b47321b2 100644 (file)
@@ -259,7 +259,7 @@ unsigned int aa_str_perms(struct aa_dfa *dfa, unsigned int start,
  */
 static inline bool is_deleted(struct dentry *dentry)
 {
-       if (d_unlinked(dentry) && dentry->d_inode->i_nlink == 0)
+       if (d_unlinked(dentry) && d_backing_inode(dentry)->i_nlink == 0)
                return 1;
        return 0;
 }
@@ -351,8 +351,8 @@ int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
        struct path link = { new_dir->mnt, new_dentry };
        struct path target = { new_dir->mnt, old_dentry };
        struct path_cond cond = {
-               old_dentry->d_inode->i_uid,
-               old_dentry->d_inode->i_mode
+               d_backing_inode(old_dentry)->i_uid,
+               d_backing_inode(old_dentry)->i_mode
        };
        char *buffer = NULL, *buffer2 = NULL;
        const char *lname, *tname = NULL, *info = NULL;
index dd56bffd6500e078b4aa7d4b64c8e04c91802541..e5f1561439dbe016bcaaf4c7ffe00516e0550b8d 100644 (file)
@@ -204,8 +204,8 @@ static int common_perm_mnt_dentry(int op, struct vfsmount *mnt,
                                  struct dentry *dentry, u32 mask)
 {
        struct path path = { mnt, dentry };
-       struct path_cond cond = { dentry->d_inode->i_uid,
-                                 dentry->d_inode->i_mode
+       struct path_cond cond = { d_backing_inode(dentry)->i_uid,
+                                 d_backing_inode(dentry)->i_mode
        };
 
        return common_perm(op, &path, mask, &cond);
@@ -223,7 +223,7 @@ static int common_perm_mnt_dentry(int op, struct vfsmount *mnt,
 static int common_perm_rm(int op, struct path *dir,
                          struct dentry *dentry, u32 mask)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_backing_inode(dentry);
        struct path_cond cond = { };
 
        if (!inode || !dir->mnt || !mediated_filesystem(dentry))
@@ -281,8 +281,8 @@ static int apparmor_path_mknod(struct path *dir, struct dentry *dentry,
 
 static int apparmor_path_truncate(struct path *path)
 {
-       struct path_cond cond = { path->dentry->d_inode->i_uid,
-                                 path->dentry->d_inode->i_mode
+       struct path_cond cond = { d_backing_inode(path->dentry)->i_uid,
+                                 d_backing_inode(path->dentry)->i_mode
        };
 
        if (!path->mnt || !mediated_filesystem(path->dentry))
@@ -327,8 +327,8 @@ static int apparmor_path_rename(struct path *old_dir, struct dentry *old_dentry,
        if (!unconfined(profile)) {
                struct path old_path = { old_dir->mnt, old_dentry };
                struct path new_path = { new_dir->mnt, new_dentry };
-               struct path_cond cond = { old_dentry->d_inode->i_uid,
-                                         old_dentry->d_inode->i_mode
+               struct path_cond cond = { d_backing_inode(old_dentry)->i_uid,
+                                         d_backing_inode(old_dentry)->i_mode
                };
 
                error = aa_path_perm(OP_RENAME_SRC, profile, &old_path, 0,
@@ -354,8 +354,8 @@ static int apparmor_path_chmod(struct path *path, umode_t mode)
 
 static int apparmor_path_chown(struct path *path, kuid_t uid, kgid_t gid)
 {
-       struct path_cond cond =  { path->dentry->d_inode->i_uid,
-                                  path->dentry->d_inode->i_mode
+       struct path_cond cond =  { d_backing_inode(path->dentry)->i_uid,
+                                  d_backing_inode(path->dentry)->i_mode
        };
 
        if (!mediated_filesystem(path->dentry))
index f66713bd7450a7e522fd29faa543eb1171885a18..f2875cd9f67775828c01557c513b464705e70653 100644 (file)
@@ -297,7 +297,7 @@ static inline void bprm_clear_caps(struct linux_binprm *bprm)
  */
 int cap_inode_need_killpriv(struct dentry *dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_backing_inode(dentry);
        int error;
 
        if (!inode->i_op->getxattr)
@@ -319,7 +319,7 @@ int cap_inode_need_killpriv(struct dentry *dentry)
  */
 int cap_inode_killpriv(struct dentry *dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_backing_inode(dentry);
 
        if (!inode->i_op->removexattr)
               return 0;
@@ -375,7 +375,7 @@ static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps,
  */
 int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_backing_inode(dentry);
        __u32 magic_etc;
        unsigned tocopy, i;
        int size;
index 131a3c49f766444f167f88d19b712ef80ee47a66..91503b79c5f8f8d373920da4b16854c590774799 100644 (file)
@@ -27,7 +27,7 @@ static int mount_count;
 
 static inline int positive(struct dentry *dentry)
 {
-       return dentry->d_inode && !d_unhashed(dentry);
+       return d_really_is_positive(dentry) && !d_unhashed(dentry);
 }
 
 static int fill_super(struct super_block *sb, void *data, int silent)
@@ -102,14 +102,14 @@ struct dentry *securityfs_create_file(const char *name, umode_t mode,
        if (!parent)
                parent = mount->mnt_root;
 
-       dir = parent->d_inode;
+       dir = d_inode(parent);
 
        mutex_lock(&dir->i_mutex);
        dentry = lookup_one_len(name, parent, strlen(name));
        if (IS_ERR(dentry))
                goto out;
 
-       if (dentry->d_inode) {
+       if (d_really_is_positive(dentry)) {
                error = -EEXIST;
                goto out1;
        }
@@ -197,20 +197,20 @@ void securityfs_remove(struct dentry *dentry)
                return;
 
        parent = dentry->d_parent;
-       if (!parent || !parent->d_inode)
+       if (!parent || d_really_is_negative(parent))
                return;
 
-       mutex_lock(&parent->d_inode->i_mutex);
+       mutex_lock(&d_inode(parent)->i_mutex);
        if (positive(dentry)) {
-               if (dentry->d_inode) {
+               if (d_really_is_positive(dentry)) {
                        if (d_is_dir(dentry))
-                               simple_rmdir(parent->d_inode, dentry);
+                               simple_rmdir(d_inode(parent), dentry);
                        else
-                               simple_unlink(parent->d_inode, dentry);
+                               simple_unlink(d_inode(parent), dentry);
                        dput(dentry);
                }
        }
-       mutex_unlock(&parent->d_inode->i_mutex);
+       mutex_unlock(&d_inode(parent)->i_mutex);
        simple_release_fs(&mount, &mount_count);
 }
 EXPORT_SYMBOL_GPL(securityfs_remove);
index 5e9687f02e1b14e56e56d3a303afbef23ea79dca..159ef3ea41308dbb2ef44e2c491d44083c27d72f 100644 (file)
@@ -131,7 +131,7 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
                                size_t req_xattr_value_len,
                                char type, char *digest)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_backing_inode(dentry);
        struct shash_desc *desc;
        char **xattrname;
        size_t xattr_size = 0;
@@ -199,7 +199,7 @@ int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name,
 int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name,
                        const char *xattr_value, size_t xattr_value_len)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_backing_inode(dentry);
        struct evm_ima_xattr_data xattr_data;
        int rc = 0;
 
index f589c9a05da29f6bf40cfd903858ee1569791c41..10f994307a04ec0473fef1795a4b8b0cca3755e3 100644 (file)
@@ -72,7 +72,7 @@ static void __init evm_init_config(void)
 
 static int evm_find_protected_xattrs(struct dentry *dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_backing_inode(dentry);
        char **xattr;
        int error;
        int count = 0;
@@ -165,8 +165,8 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
                        /* Replace RSA with HMAC if not mounted readonly and
                         * not immutable
                         */
-                       if (!IS_RDONLY(dentry->d_inode) &&
-                           !IS_IMMUTABLE(dentry->d_inode))
+                       if (!IS_RDONLY(d_backing_inode(dentry)) &&
+                           !IS_IMMUTABLE(d_backing_inode(dentry)))
                                evm_update_evmxattr(dentry, xattr_name,
                                                    xattr_value,
                                                    xattr_value_len);
@@ -235,7 +235,7 @@ enum integrity_status evm_verifyxattr(struct dentry *dentry,
                return INTEGRITY_UNKNOWN;
 
        if (!iint) {
-               iint = integrity_iint_find(dentry->d_inode);
+               iint = integrity_iint_find(d_backing_inode(dentry));
                if (!iint)
                        return INTEGRITY_UNKNOWN;
        }
@@ -253,7 +253,7 @@ EXPORT_SYMBOL_GPL(evm_verifyxattr);
  */
 static enum integrity_status evm_verify_current_integrity(struct dentry *dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_backing_inode(dentry);
 
        if (!evm_initialized || !S_ISREG(inode->i_mode) || evm_fixmode)
                return 0;
@@ -293,13 +293,13 @@ static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name,
        if (evm_status == INTEGRITY_NOXATTRS) {
                struct integrity_iint_cache *iint;
 
-               iint = integrity_iint_find(dentry->d_inode);
+               iint = integrity_iint_find(d_backing_inode(dentry));
                if (iint && (iint->flags & IMA_NEW_FILE))
                        return 0;
        }
 out:
        if (evm_status != INTEGRITY_PASS)
-               integrity_audit_msg(AUDIT_INTEGRITY_METADATA, dentry->d_inode,
+               integrity_audit_msg(AUDIT_INTEGRITY_METADATA, d_backing_inode(dentry),
                                    dentry->d_name.name, "appraise_metadata",
                                    integrity_status_msg[evm_status],
                                    -EPERM, 0);
@@ -379,7 +379,7 @@ void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name,
  */
 void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_backing_inode(dentry);
 
        if (!evm_initialized || !evm_protected_xattr(xattr_name))
                return;
@@ -404,7 +404,7 @@ int evm_inode_setattr(struct dentry *dentry, struct iattr *attr)
        if ((evm_status == INTEGRITY_PASS) ||
            (evm_status == INTEGRITY_NOXATTRS))
                return 0;
-       integrity_audit_msg(AUDIT_INTEGRITY_METADATA, dentry->d_inode,
+       integrity_audit_msg(AUDIT_INTEGRITY_METADATA, d_backing_inode(dentry),
                            dentry->d_name.name, "appraise_metadata",
                            integrity_status_msg[evm_status], -EPERM, 0);
        return -EPERM;
index fffcdb0b31f0dfc139ea15079bfb1f89d1b739a1..4df493e4b3c9108e1c37e00397a4c4c56809c4da 100644 (file)
@@ -165,7 +165,7 @@ void ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, int xattr_len,
 int ima_read_xattr(struct dentry *dentry,
                   struct evm_ima_xattr_data **xattr_value)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_backing_inode(dentry);
 
        if (!inode->i_op->getxattr)
                return 0;
@@ -190,7 +190,7 @@ int ima_appraise_measurement(int func, struct integrity_iint_cache *iint,
        static const char op[] = "appraise_data";
        char *cause = "unknown";
        struct dentry *dentry = file->f_path.dentry;
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_backing_inode(dentry);
        enum integrity_status status = INTEGRITY_UNKNOWN;
        int rc = xattr_len, hash_start = 0;
 
@@ -314,7 +314,7 @@ void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file)
  */
 void ima_inode_post_setattr(struct dentry *dentry)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_backing_inode(dentry);
        struct integrity_iint_cache *iint;
        int must_appraise, rc;
 
@@ -380,7 +380,7 @@ int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
        if (result == 1) {
                if (!xattr_value_len || (xvalue->type >= IMA_XATTR_LAST))
                        return -EINVAL;
-               ima_reset_appraise_flags(dentry->d_inode,
+               ima_reset_appraise_flags(d_backing_inode(dentry),
                         (xvalue->type == EVM_IMA_XATTR_DIGSIG) ? 1 : 0);
                result = 0;
        }
@@ -393,7 +393,7 @@ int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name)
 
        result = ima_protect_xattr(dentry, xattr_name, NULL, 0);
        if (result == 1) {
-               ima_reset_appraise_flags(dentry->d_inode, 0);
+               ima_reset_appraise_flags(d_backing_inode(dentry), 0);
                result = 0;
        }
        return result;
index b526ddc3add5817a9370fc054cbfa395b055563f..1d34277dc402b5971122fdb35d0171eb33f612f5 100644 (file)
@@ -237,7 +237,7 @@ static void dump_common_audit_data(struct audit_buffer *ab,
 
                audit_log_d_path(ab, " path=", &a->u.path);
 
-               inode = a->u.path.dentry->d_inode;
+               inode = d_backing_inode(a->u.path.dentry);
                if (inode) {
                        audit_log_format(ab, " dev=");
                        audit_log_untrustedstring(ab, inode->i_sb->s_id);
@@ -251,7 +251,7 @@ static void dump_common_audit_data(struct audit_buffer *ab,
                audit_log_format(ab, " name=");
                audit_log_untrustedstring(ab, a->u.dentry->d_name.name);
 
-               inode = a->u.dentry->d_inode;
+               inode = d_backing_inode(a->u.dentry);
                if (inode) {
                        audit_log_format(ab, " dev=");
                        audit_log_untrustedstring(ab, inode->i_sb->s_id);
index 730ac65a573722238142ad0d978abc26f87287cd..8e9b1f4b9b45dfac98287fe969b869a3a29fb2bc 100644 (file)
@@ -410,7 +410,7 @@ EXPORT_SYMBOL(security_old_inode_init_security);
 int security_path_mknod(struct path *dir, struct dentry *dentry, umode_t mode,
                        unsigned int dev)
 {
-       if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
+       if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
                return 0;
        return security_ops->path_mknod(dir, dentry, mode, dev);
 }
@@ -418,7 +418,7 @@ EXPORT_SYMBOL(security_path_mknod);
 
 int security_path_mkdir(struct path *dir, struct dentry *dentry, umode_t mode)
 {
-       if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
+       if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
                return 0;
        return security_ops->path_mkdir(dir, dentry, mode);
 }
@@ -426,14 +426,14 @@ EXPORT_SYMBOL(security_path_mkdir);
 
 int security_path_rmdir(struct path *dir, struct dentry *dentry)
 {
-       if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
+       if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
                return 0;
        return security_ops->path_rmdir(dir, dentry);
 }
 
 int security_path_unlink(struct path *dir, struct dentry *dentry)
 {
-       if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
+       if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
                return 0;
        return security_ops->path_unlink(dir, dentry);
 }
@@ -442,7 +442,7 @@ EXPORT_SYMBOL(security_path_unlink);
 int security_path_symlink(struct path *dir, struct dentry *dentry,
                          const char *old_name)
 {
-       if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
+       if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
                return 0;
        return security_ops->path_symlink(dir, dentry, old_name);
 }
@@ -450,7 +450,7 @@ int security_path_symlink(struct path *dir, struct dentry *dentry,
 int security_path_link(struct dentry *old_dentry, struct path *new_dir,
                       struct dentry *new_dentry)
 {
-       if (unlikely(IS_PRIVATE(old_dentry->d_inode)))
+       if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry))))
                return 0;
        return security_ops->path_link(old_dentry, new_dir, new_dentry);
 }
@@ -459,8 +459,8 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
                         struct path *new_dir, struct dentry *new_dentry,
                         unsigned int flags)
 {
-       if (unlikely(IS_PRIVATE(old_dentry->d_inode) ||
-                    (new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode))))
+       if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)) ||
+                    (d_is_positive(new_dentry) && IS_PRIVATE(d_backing_inode(new_dentry)))))
                return 0;
 
        if (flags & RENAME_EXCHANGE) {
@@ -477,21 +477,21 @@ EXPORT_SYMBOL(security_path_rename);
 
 int security_path_truncate(struct path *path)
 {
-       if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
+       if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
                return 0;
        return security_ops->path_truncate(path);
 }
 
 int security_path_chmod(struct path *path, umode_t mode)
 {
-       if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
+       if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
                return 0;
        return security_ops->path_chmod(path, mode);
 }
 
 int security_path_chown(struct path *path, kuid_t uid, kgid_t gid)
 {
-       if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
+       if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
                return 0;
        return security_ops->path_chown(path, uid, gid);
 }
@@ -513,14 +513,14 @@ EXPORT_SYMBOL_GPL(security_inode_create);
 int security_inode_link(struct dentry *old_dentry, struct inode *dir,
                         struct dentry *new_dentry)
 {
-       if (unlikely(IS_PRIVATE(old_dentry->d_inode)))
+       if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry))))
                return 0;
        return security_ops->inode_link(old_dentry, dir, new_dentry);
 }
 
 int security_inode_unlink(struct inode *dir, struct dentry *dentry)
 {
-       if (unlikely(IS_PRIVATE(dentry->d_inode)))
+       if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return 0;
        return security_ops->inode_unlink(dir, dentry);
 }
@@ -543,7 +543,7 @@ EXPORT_SYMBOL_GPL(security_inode_mkdir);
 
 int security_inode_rmdir(struct inode *dir, struct dentry *dentry)
 {
-       if (unlikely(IS_PRIVATE(dentry->d_inode)))
+       if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return 0;
        return security_ops->inode_rmdir(dir, dentry);
 }
@@ -559,8 +559,8 @@ int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
                           struct inode *new_dir, struct dentry *new_dentry,
                           unsigned int flags)
 {
-        if (unlikely(IS_PRIVATE(old_dentry->d_inode) ||
-            (new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode))))
+        if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)) ||
+            (d_is_positive(new_dentry) && IS_PRIVATE(d_backing_inode(new_dentry)))))
                return 0;
 
        if (flags & RENAME_EXCHANGE) {
@@ -576,14 +576,14 @@ int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
 
 int security_inode_readlink(struct dentry *dentry)
 {
-       if (unlikely(IS_PRIVATE(dentry->d_inode)))
+       if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return 0;
        return security_ops->inode_readlink(dentry);
 }
 
 int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-       if (unlikely(IS_PRIVATE(dentry->d_inode)))
+       if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return 0;
        return security_ops->inode_follow_link(dentry, nd);
 }
@@ -599,7 +599,7 @@ int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
 {
        int ret;
 
-       if (unlikely(IS_PRIVATE(dentry->d_inode)))
+       if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return 0;
        ret = security_ops->inode_setattr(dentry, attr);
        if (ret)
@@ -610,7 +610,7 @@ EXPORT_SYMBOL_GPL(security_inode_setattr);
 
 int security_inode_getattr(const struct path *path)
 {
-       if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
+       if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
                return 0;
        return security_ops->inode_getattr(path);
 }
@@ -620,7 +620,7 @@ int security_inode_setxattr(struct dentry *dentry, const char *name,
 {
        int ret;
 
-       if (unlikely(IS_PRIVATE(dentry->d_inode)))
+       if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return 0;
        ret = security_ops->inode_setxattr(dentry, name, value, size, flags);
        if (ret)
@@ -634,7 +634,7 @@ int security_inode_setxattr(struct dentry *dentry, const char *name,
 void security_inode_post_setxattr(struct dentry *dentry, const char *name,
                                  const void *value, size_t size, int flags)
 {
-       if (unlikely(IS_PRIVATE(dentry->d_inode)))
+       if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return;
        security_ops->inode_post_setxattr(dentry, name, value, size, flags);
        evm_inode_post_setxattr(dentry, name, value, size);
@@ -642,14 +642,14 @@ void security_inode_post_setxattr(struct dentry *dentry, const char *name,
 
 int security_inode_getxattr(struct dentry *dentry, const char *name)
 {
-       if (unlikely(IS_PRIVATE(dentry->d_inode)))
+       if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return 0;
        return security_ops->inode_getxattr(dentry, name);
 }
 
 int security_inode_listxattr(struct dentry *dentry)
 {
-       if (unlikely(IS_PRIVATE(dentry->d_inode)))
+       if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return 0;
        return security_ops->inode_listxattr(dentry);
 }
@@ -658,7 +658,7 @@ int security_inode_removexattr(struct dentry *dentry, const char *name)
 {
        int ret;
 
-       if (unlikely(IS_PRIVATE(dentry->d_inode)))
+       if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
                return 0;
        ret = security_ops->inode_removexattr(dentry, name);
        if (ret)
index c318b304ee2f5be7001d6e26e30811bbbbd83859..7dade28affba5a0ebc0944be49dbd59dbf5c8761 100644 (file)
@@ -414,7 +414,7 @@ static int sb_finish_set_opts(struct super_block *sb)
 {
        struct superblock_security_struct *sbsec = sb->s_security;
        struct dentry *root = sb->s_root;
-       struct inode *root_inode = root->d_inode;
+       struct inode *root_inode = d_backing_inode(root);
        int rc = 0;
 
        if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
@@ -552,7 +552,7 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
                opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT;
        }
        if (sbsec->flags & ROOTCONTEXT_MNT) {
-               struct inode *root = sbsec->sb->s_root->d_inode;
+               struct inode *root = d_backing_inode(sbsec->sb->s_root);
                struct inode_security_struct *isec = root->i_security;
 
                rc = security_sid_to_context(isec->sid, &context, &len);
@@ -608,7 +608,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
        int rc = 0, i;
        struct superblock_security_struct *sbsec = sb->s_security;
        const char *name = sb->s_type->name;
-       struct inode *inode = sbsec->sb->s_root->d_inode;
+       struct inode *inode = d_backing_inode(sbsec->sb->s_root);
        struct inode_security_struct *root_isec = inode->i_security;
        u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
        u32 defcontext_sid = 0;
@@ -835,8 +835,8 @@ static int selinux_cmp_sb_context(const struct super_block *oldsb,
        if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
                goto mismatch;
        if (oldflags & ROOTCONTEXT_MNT) {
-               struct inode_security_struct *oldroot = oldsb->s_root->d_inode->i_security;
-               struct inode_security_struct *newroot = newsb->s_root->d_inode->i_security;
+               struct inode_security_struct *oldroot = d_backing_inode(oldsb->s_root)->i_security;
+               struct inode_security_struct *newroot = d_backing_inode(newsb->s_root)->i_security;
                if (oldroot->sid != newroot->sid)
                        goto mismatch;
        }
@@ -886,16 +886,16 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
                if (!set_fscontext)
                        newsbsec->sid = sid;
                if (!set_rootcontext) {
-                       struct inode *newinode = newsb->s_root->d_inode;
+                       struct inode *newinode = d_backing_inode(newsb->s_root);
                        struct inode_security_struct *newisec = newinode->i_security;
                        newisec->sid = sid;
                }
                newsbsec->mntpoint_sid = sid;
        }
        if (set_rootcontext) {
-               const struct inode *oldinode = oldsb->s_root->d_inode;
+               const struct inode *oldinode = d_backing_inode(oldsb->s_root);
                const struct inode_security_struct *oldisec = oldinode->i_security;
-               struct inode *newinode = newsb->s_root->d_inode;
+               struct inode *newinode = d_backing_inode(newsb->s_root);
                struct inode_security_struct *newisec = newinode->i_security;
 
                newisec->sid = oldisec->sid;
@@ -1610,7 +1610,7 @@ static inline int dentry_has_perm(const struct cred *cred,
                                  struct dentry *dentry,
                                  u32 av)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_backing_inode(dentry);
        struct common_audit_data ad;
 
        ad.type = LSM_AUDIT_DATA_DENTRY;
@@ -1625,7 +1625,7 @@ static inline int path_has_perm(const struct cred *cred,
                                const struct path *path,
                                u32 av)
 {
-       struct inode *inode = path->dentry->d_inode;
+       struct inode *inode = d_backing_inode(path->dentry);
        struct common_audit_data ad;
 
        ad.type = LSM_AUDIT_DATA_PATH;
@@ -1753,7 +1753,7 @@ static int may_link(struct inode *dir,
        int rc;
 
        dsec = dir->i_security;
-       isec = dentry->d_inode->i_security;
+       isec = d_backing_inode(dentry)->i_security;
 
        ad.type = LSM_AUDIT_DATA_DENTRY;
        ad.u.dentry = dentry;
@@ -1797,7 +1797,7 @@ static inline int may_rename(struct inode *old_dir,
        int rc;
 
        old_dsec = old_dir->i_security;
-       old_isec = old_dentry->d_inode->i_security;
+       old_isec = d_backing_inode(old_dentry)->i_security;
        old_is_dir = d_is_dir(old_dentry);
        new_dsec = new_dir->i_security;
 
@@ -1827,7 +1827,7 @@ static inline int may_rename(struct inode *old_dir,
        if (rc)
                return rc;
        if (d_is_positive(new_dentry)) {
-               new_isec = new_dentry->d_inode->i_security;
+               new_isec = d_backing_inode(new_dentry)->i_security;
                new_is_dir = d_is_dir(new_dentry);
                rc = avc_has_perm(sid, new_isec->sid,
                                  new_isec->sclass,
@@ -1963,7 +1963,7 @@ static int selinux_binder_transfer_file(struct task_struct *from,
 {
        u32 sid = task_sid(to);
        struct file_security_struct *fsec = file->f_security;
-       struct inode *inode = file->f_path.dentry->d_inode;
+       struct inode *inode = d_backing_inode(file->f_path.dentry);
        struct inode_security_struct *isec = inode->i_security;
        struct common_audit_data ad;
        int rc;
@@ -2627,7 +2627,7 @@ static int selinux_sb_remount(struct super_block *sb, void *data)
                        break;
                case ROOTCONTEXT_MNT: {
                        struct inode_security_struct *root_isec;
-                       root_isec = sb->s_root->d_inode->i_security;
+                       root_isec = d_backing_inode(sb->s_root)->i_security;
 
                        if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
                                goto out_bad_option;
@@ -2727,7 +2727,7 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode,
        struct task_security_struct *tsec;
        struct inode_security_struct *dsec;
        struct superblock_security_struct *sbsec;
-       struct inode *dir = dentry->d_parent->d_inode;
+       struct inode *dir = d_backing_inode(dentry->d_parent);
        u32 newsid;
        int rc;
 
@@ -2982,7 +2982,7 @@ static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
 static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
                                  const void *value, size_t size, int flags)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_backing_inode(dentry);
        struct inode_security_struct *isec = inode->i_security;
        struct superblock_security_struct *sbsec;
        struct common_audit_data ad;
@@ -3059,7 +3059,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
                                        const void *value, size_t size,
                                        int flags)
 {
-       struct inode *inode = dentry->d_inode;
+       struct inode *inode = d_backing_inode(dentry);
        struct inode_security_struct *isec = inode->i_security;
        u32 newsid;
        int rc;
index 5fde34326dcf28312ab4c36cb09623ecb811760b..d2787cca1fcb94aea94f73f1535d4a57f2907129 100644 (file)
@@ -1737,7 +1737,7 @@ static struct dentry *sel_make_dir(struct dentry *dir, const char *name,
        inc_nlink(inode);
        d_add(dentry, inode);
        /* bump link count on parent directory, too */
-       inc_nlink(dir->d_inode);
+       inc_nlink(d_inode(dir));
 
        return dentry;
 }
index 69fdc384af301f7724b26f6be7e6264da41bd6c2..b644757886bc5314a7f861624868a8bdc30fdf9b 100644 (file)
@@ -593,7 +593,7 @@ static int smack_sb_copy_data(char *orig, char *smackopts)
 static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data)
 {
        struct dentry *root = sb->s_root;
-       struct inode *inode = root->d_inode;
+       struct inode *inode = d_backing_inode(root);
        struct superblock_smack *sp = sb->s_security;
        struct inode_smack *isp;
        struct smack_known *skp;
@@ -889,15 +889,15 @@ static int smack_inode_link(struct dentry *old_dentry, struct inode *dir,
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
        smk_ad_setfield_u_fs_path_dentry(&ad, old_dentry);
 
-       isp = smk_of_inode(old_dentry->d_inode);
+       isp = smk_of_inode(d_backing_inode(old_dentry));
        rc = smk_curacc(isp, MAY_WRITE, &ad);
-       rc = smk_bu_inode(old_dentry->d_inode, MAY_WRITE, rc);
+       rc = smk_bu_inode(d_backing_inode(old_dentry), MAY_WRITE, rc);
 
        if (rc == 0 && d_is_positive(new_dentry)) {
-               isp = smk_of_inode(new_dentry->d_inode);
+               isp = smk_of_inode(d_backing_inode(new_dentry));
                smk_ad_setfield_u_fs_path_dentry(&ad, new_dentry);
                rc = smk_curacc(isp, MAY_WRITE, &ad);
-               rc = smk_bu_inode(new_dentry->d_inode, MAY_WRITE, rc);
+               rc = smk_bu_inode(d_backing_inode(new_dentry), MAY_WRITE, rc);
        }
 
        return rc;
@@ -913,7 +913,7 @@ static int smack_inode_link(struct dentry *old_dentry, struct inode *dir,
  */
 static int smack_inode_unlink(struct inode *dir, struct dentry *dentry)
 {
-       struct inode *ip = dentry->d_inode;
+       struct inode *ip = d_backing_inode(dentry);
        struct smk_audit_info ad;
        int rc;
 
@@ -956,8 +956,8 @@ static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry)
        /*
         * You need write access to the thing you're removing
         */
-       rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
-       rc = smk_bu_inode(dentry->d_inode, MAY_WRITE, rc);
+       rc = smk_curacc(smk_of_inode(d_backing_inode(dentry)), MAY_WRITE, &ad);
+       rc = smk_bu_inode(d_backing_inode(dentry), MAY_WRITE, rc);
        if (rc == 0) {
                /*
                 * You also need write access to the containing directory
@@ -995,15 +995,15 @@ static int smack_inode_rename(struct inode *old_inode,
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
        smk_ad_setfield_u_fs_path_dentry(&ad, old_dentry);
 
-       isp = smk_of_inode(old_dentry->d_inode);
+       isp = smk_of_inode(d_backing_inode(old_dentry));
        rc = smk_curacc(isp, MAY_READWRITE, &ad);
-       rc = smk_bu_inode(old_dentry->d_inode, MAY_READWRITE, rc);
+       rc = smk_bu_inode(d_backing_inode(old_dentry), MAY_READWRITE, rc);
 
        if (rc == 0 && d_is_positive(new_dentry)) {
-               isp = smk_of_inode(new_dentry->d_inode);
+               isp = smk_of_inode(d_backing_inode(new_dentry));
                smk_ad_setfield_u_fs_path_dentry(&ad, new_dentry);
                rc = smk_curacc(isp, MAY_READWRITE, &ad);
-               rc = smk_bu_inode(new_dentry->d_inode, MAY_READWRITE, rc);
+               rc = smk_bu_inode(d_backing_inode(new_dentry), MAY_READWRITE, rc);
        }
        return rc;
 }
@@ -1060,8 +1060,8 @@ static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr)
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
        smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
 
-       rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
-       rc = smk_bu_inode(dentry->d_inode, MAY_WRITE, rc);
+       rc = smk_curacc(smk_of_inode(d_backing_inode(dentry)), MAY_WRITE, &ad);
+       rc = smk_bu_inode(d_backing_inode(dentry), MAY_WRITE, rc);
        return rc;
 }
 
@@ -1075,7 +1075,7 @@ static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr)
 static int smack_inode_getattr(const struct path *path)
 {
        struct smk_audit_info ad;
-       struct inode *inode = path->dentry->d_inode;
+       struct inode *inode = d_backing_inode(path->dentry);
        int rc;
 
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
@@ -1142,8 +1142,8 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
        smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
 
        if (rc == 0) {
-               rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
-               rc = smk_bu_inode(dentry->d_inode, MAY_WRITE, rc);
+               rc = smk_curacc(smk_of_inode(d_backing_inode(dentry)), MAY_WRITE, &ad);
+               rc = smk_bu_inode(d_backing_inode(dentry), MAY_WRITE, rc);
        }
 
        return rc;
@@ -1164,7 +1164,7 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name,
                                      const void *value, size_t size, int flags)
 {
        struct smack_known *skp;
-       struct inode_smack *isp = dentry->d_inode->i_security;
+       struct inode_smack *isp = d_backing_inode(dentry)->i_security;
 
        if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) {
                isp->smk_flags |= SMK_INODE_TRANSMUTE;
@@ -1209,8 +1209,8 @@ static int smack_inode_getxattr(struct dentry *dentry, const char *name)
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
        smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
 
-       rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad);
-       rc = smk_bu_inode(dentry->d_inode, MAY_READ, rc);
+       rc = smk_curacc(smk_of_inode(d_backing_inode(dentry)), MAY_READ, &ad);
+       rc = smk_bu_inode(d_backing_inode(dentry), MAY_READ, rc);
        return rc;
 }
 
@@ -1246,12 +1246,12 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name)
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
        smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
 
-       rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
-       rc = smk_bu_inode(dentry->d_inode, MAY_WRITE, rc);
+       rc = smk_curacc(smk_of_inode(d_backing_inode(dentry)), MAY_WRITE, &ad);
+       rc = smk_bu_inode(d_backing_inode(dentry), MAY_WRITE, rc);
        if (rc != 0)
                return rc;
 
-       isp = dentry->d_inode->i_security;
+       isp = d_backing_inode(dentry)->i_security;
        /*
         * Don't do anything special for these.
         *      XATTR_NAME_SMACKIPIN
index 06f719ed63c952cf5b27f8cfbe807fce514b6772..d9682985349e6ec182407b94e57a3f4d59af766f 100644 (file)
@@ -2490,7 +2490,7 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
                return rc;
        }
 
-       root_inode = sb->s_root->d_inode;
+       root_inode = d_inode(sb->s_root);
 
        return 0;
 }
index 63681e8be62868cb69e691619d9aa4068babb3f8..6c4528d4b48f8b5cdfaad0b072fc7afe6f17e1ff 100644 (file)
@@ -714,7 +714,7 @@ void tomoyo_get_attributes(struct tomoyo_obj_info *obj)
                        dentry = dget_parent(dentry);
                        break;
                }
-               inode = dentry->d_inode;
+               inode = d_backing_inode(dentry);
                if (inode) {
                        struct tomoyo_mini_stat *stat = &obj->stat[i];
                        stat->uid  = inode->i_uid;
index 1e0d480ff6a6b653cce9c4af266f5a8420a58c52..5077f1968841ab5717b88da5b965efa344961272 100644 (file)
@@ -97,7 +97,7 @@ static char *tomoyo_get_absolute_path(const struct path *path, char * const buff
                /* go to whatever namespace root we are under */
                pos = d_absolute_path(path, buffer, buflen - 1);
                if (!IS_ERR(pos) && *pos == '/' && pos[1]) {
-                       struct inode *inode = path->dentry->d_inode;
+                       struct inode *inode = d_backing_inode(path->dentry);
                        if (inode && S_ISDIR(inode->i_mode)) {
                                buffer[buflen - 2] = '/';
                                buffer[buflen - 1] = '\0';
@@ -125,7 +125,7 @@ static char *tomoyo_get_dentry_path(struct dentry *dentry, char * const buffer,
        if (buflen >= 256) {
                pos = dentry_path_raw(dentry, buffer, buflen - 1);
                if (!IS_ERR(pos) && *pos == '/' && pos[1]) {
-                       struct inode *inode = dentry->d_inode;
+                       struct inode *inode = d_backing_inode(dentry);
                        if (inode && S_ISDIR(inode->i_mode)) {
                                buffer[buflen - 2] = '/';
                                buffer[buflen - 1] = '\0';
@@ -168,7 +168,7 @@ static char *tomoyo_get_local_path(struct dentry *dentry, char * const buffer,
        if (!MAJOR(sb->s_dev))
                goto prepend_filesystem_name;
        {
-               struct inode *inode = sb->s_root->d_inode;
+               struct inode *inode = d_backing_inode(sb->s_root);
                /*
                 * Use filesystem name if filesystem does not support rename()
                 * operation.
@@ -219,7 +219,7 @@ out:
 static char *tomoyo_get_socket_name(const struct path *path, char * const buffer,
                                    const int buflen)
 {
-       struct inode *inode = path->dentry->d_inode;
+       struct inode *inode = d_backing_inode(path->dentry);
        struct socket *sock = inode ? SOCKET_I(inode) : NULL;
        struct sock *sk = sock ? sock->sk : NULL;
        if (sk) {
@@ -277,7 +277,7 @@ char *tomoyo_realpath_from_path(const struct path *path)
                        pos = dentry->d_op->d_dname(dentry, buf, buf_len - 1);
                        goto encode;
                }
-               inode = sb->s_root->d_inode;
+               inode = d_backing_inode(sb->s_root);
                /*
                 * Get local name for filesystems without rename() operation
                 * or dentry without vfsmount.
index c0eea1dfe90ff5448cf1c6c43be2ebddbf4edf8d..f19da4b47c1dfcd89c5da0bb03f14d55811c532c 100644 (file)
@@ -681,13 +681,8 @@ static int seq_timing_event(unsigned char *event_rec)
                        break;
 
                case TMR_ECHO:
-                       if (seq_mode == SEQ_2)
-                               seq_copy_to_input(event_rec, 8);
-                       else
-                       {
-                               parm = (parm << 8 | SEQ_ECHO);
-                               seq_copy_to_input((unsigned char *) &parm, 4);
-                       }
+                       parm = (parm << 8 | SEQ_ECHO);
+                       seq_copy_to_input((unsigned char *) &parm, 4);
                        break;
 
                default:;
@@ -1324,7 +1319,6 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, void __user *a
        int mode = translate_mode(file);
        struct synth_info inf;
        struct seq_event_rec event_rec;
-       unsigned long flags;
        int __user *p = arg;
 
        orig_dev = dev = dev >> 4;
@@ -1479,9 +1473,7 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, void __user *a
                case SNDCTL_SEQ_OUTOFBAND:
                        if (copy_from_user(&event_rec, arg, sizeof(event_rec)))
                                return -EFAULT;
-                       spin_lock_irqsave(&lock,flags);
                        play_event(event_rec.arr);
-                       spin_unlock_irqrestore(&lock,flags);
                        return 0;
 
                case SNDCTL_MIDI_INFO:
index 37d0220a094cb55451cff620c5e455f83d8a894d..db7a2e5e4a14ee6d7d110206aa94d7d71002066a 100644 (file)
@@ -183,8 +183,10 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci,
        }
 #endif
  
-       strcpy(card->driver, emu->card_capabilities->driver);
-       strcpy(card->shortname, emu->card_capabilities->name);
+       strlcpy(card->driver, emu->card_capabilities->driver,
+               sizeof(card->driver));
+       strlcpy(card->shortname, emu->card_capabilities->name,
+               sizeof(card->shortname));
        snprintf(card->longname, sizeof(card->longname),
                 "%s (rev.%d, serial:0x%x) at 0x%lx, irq %i",
                 card->shortname, emu->revision, emu->serial, emu->port, emu->irq);
index 874cd76c7b7fb09b5c6c3cc722173914280b45ce..d2c7ea3a7610861a15730bb3a8b0c8764205fd5a 100644 (file)
@@ -415,7 +415,7 @@ start_voice(struct snd_emux_voice *vp)
        snd_emu10k1_ptr_write(hw, Z2, ch, 0);
 
        /* invalidate maps */
-       temp = (hw->silent_page.addr << 1) | MAP_PTI_MASK;
+       temp = (hw->silent_page.addr << hw->address_mode) | (hw->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0);
        snd_emu10k1_ptr_write(hw, MAPA, ch, temp);
        snd_emu10k1_ptr_write(hw, MAPB, ch, temp);
 #if 0
@@ -436,7 +436,7 @@ start_voice(struct snd_emux_voice *vp)
                snd_emu10k1_ptr_write(hw, CDF, ch, sample);
 
                /* invalidate maps */
-               temp = ((unsigned int)hw->silent_page.addr << 1) | MAP_PTI_MASK;
+               temp = ((unsigned int)hw->silent_page.addr << hw_address_mode) | (hw->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0);
                snd_emu10k1_ptr_write(hw, MAPA, ch, temp);
                snd_emu10k1_ptr_write(hw, MAPB, ch, temp);
                
index 54079f5d5673951ad739c81e2e679d3864f0ea79..a4548147c6215e788bc6cd9ead8357cb72658f8a 100644 (file)
@@ -282,7 +282,7 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
        snd_emu10k1_ptr_write(emu, TCB, 0, 0);  /* taken from original driver */
        snd_emu10k1_ptr_write(emu, TCBS, 0, 4); /* taken from original driver */
 
-       silent_page = (emu->silent_page.addr << 1) | MAP_PTI_MASK;
+       silent_page = (emu->silent_page.addr << emu->address_mode) | (emu->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0);
        for (ch = 0; ch < NUM_G; ch++) {
                snd_emu10k1_ptr_write(emu, MAPA, ch, silent_page);
                snd_emu10k1_ptr_write(emu, MAPB, ch, silent_page);
@@ -348,6 +348,11 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
                outl(reg | A_IOCFG_GPOUT0, emu->port + A_IOCFG);
        }
 
+       if (emu->address_mode == 0) {
+               /* use 16M in 4G */
+               outl(inl(emu->port + HCFG) | HCFG_EXPANDED_MEM, emu->port + HCFG);
+       }
+
        return 0;
 }
 
@@ -1446,7 +1451,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
         *
         */
        {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x20011102,
-        .driver = "Audigy2", .name = "SB Audigy 2 ZS Notebook [SB0530]",
+        .driver = "Audigy2", .name = "Audigy 2 ZS Notebook [SB0530]",
         .id = "Audigy2",
         .emu10k2_chip = 1,
         .ca0108_chip = 1,
@@ -1596,7 +1601,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
         .adc_1361t = 1,  /* 24 bit capture instead of 16bit */
         .ac97_chip = 1} ,
        {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102,
-        .driver = "Audigy2", .name = "SB Audigy 2 Platinum EX [SB0280]",
+        .driver = "Audigy2", .name = "Audigy 2 Platinum EX [SB0280]",
         .id = "Audigy2",
         .emu10k2_chip = 1,
         .ca0102_chip = 1,
@@ -1902,8 +1907,10 @@ int snd_emu10k1_create(struct snd_card *card,
 
        is_audigy = emu->audigy = c->emu10k2_chip;
 
+       /* set addressing mode */
+       emu->address_mode = is_audigy ? 0 : 1;
        /* set the DMA transfer mask */
-       emu->dma_mask = is_audigy ? AUDIGY_DMA_MASK : EMU10K1_DMA_MASK;
+       emu->dma_mask = emu->address_mode ? EMU10K1_DMA_MASK : AUDIGY_DMA_MASK;
        if (pci_set_dma_mask(pci, emu->dma_mask) < 0 ||
            pci_set_consistent_dma_mask(pci, emu->dma_mask) < 0) {
                dev_err(card->dev,
@@ -1928,7 +1935,7 @@ int snd_emu10k1_create(struct snd_card *card,
 
        emu->max_cache_pages = max_cache_bytes >> PAGE_SHIFT;
        if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
-                               32 * 1024, &emu->ptb_pages) < 0) {
+                               (emu->address_mode ? 32 : 16) * 1024, &emu->ptb_pages) < 0) {
                err = -ENOMEM;
                goto error;
        }
@@ -2027,8 +2034,8 @@ int snd_emu10k1_create(struct snd_card *card,
 
        /* Clear silent pages and set up pointers */
        memset(emu->silent_page.area, 0, PAGE_SIZE);
-       silent_page = emu->silent_page.addr << 1;
-       for (idx = 0; idx < MAXPAGES; idx++)
+       silent_page = emu->silent_page.addr << emu->address_mode;
+       for (idx = 0; idx < (emu->address_mode ? MAXPAGES1 : MAXPAGES0); idx++)
                ((u32 *)emu->ptb_pages.area)[idx] = cpu_to_le32(silent_page | idx);
 
        /* set up voice indices */
index 0dc07385af0ebaee5ea66126bf8d758e17f71054..14a305bd8a98577cf50ecad28090996714b2034b 100644 (file)
@@ -380,7 +380,7 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
        snd_emu10k1_ptr_write(emu, Z1, voice, 0);
        snd_emu10k1_ptr_write(emu, Z2, voice, 0);
        /* invalidate maps */
-       silent_page = ((unsigned int)emu->silent_page.addr << 1) | MAP_PTI_MASK;
+       silent_page = ((unsigned int)emu->silent_page.addr << emu->address_mode) | (emu->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0);
        snd_emu10k1_ptr_write(emu, MAPA, voice, silent_page);
        snd_emu10k1_ptr_write(emu, MAPB, voice, silent_page);
        /* modulation envelope */
index c68e6dd2fa6772fc88cae359b1b7947f1c4e9796..4f1f69be18651b7c692f9feb812c239e8f911386 100644 (file)
  * aligned pages in others
  */
 #define __set_ptb_entry(emu,page,addr) \
-       (((u32 *)(emu)->ptb_pages.area)[page] = cpu_to_le32(((addr) << 1) | (page)))
+       (((u32 *)(emu)->ptb_pages.area)[page] = cpu_to_le32(((addr) << (emu->address_mode)) | (page)))
 
 #define UNIT_PAGES             (PAGE_SIZE / EMUPAGESIZE)
-#define MAX_ALIGN_PAGES                (MAXPAGES / UNIT_PAGES)
+#define MAX_ALIGN_PAGES0               (MAXPAGES0 / UNIT_PAGES)
+#define MAX_ALIGN_PAGES1               (MAXPAGES1 / UNIT_PAGES)
 /* get aligned page from offset address */
 #define get_aligned_page(offset)       ((offset) >> PAGE_SHIFT)
 /* get offset address from aligned page */
@@ -124,7 +125,7 @@ static int search_empty_map_area(struct snd_emu10k1 *emu, int npages, struct lis
                }
                page = blk->mapped_page + blk->pages;
        }
-       size = MAX_ALIGN_PAGES - page;
+       size = (emu->address_mode ? MAX_ALIGN_PAGES1 : MAX_ALIGN_PAGES0) - page;
        if (size >= max_size) {
                *nextp = pos;
                return page;
@@ -181,7 +182,7 @@ static int unmap_memblk(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk)
                q = get_emu10k1_memblk(p, mapped_link);
                end_page = q->mapped_page;
        } else
-               end_page = MAX_ALIGN_PAGES;
+               end_page = (emu->address_mode ? MAX_ALIGN_PAGES1 : MAX_ALIGN_PAGES0);
 
        /* remove links */
        list_del(&blk->mapped_link);
@@ -307,7 +308,7 @@ snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *subst
        if (snd_BUG_ON(!emu))
                return NULL;
        if (snd_BUG_ON(runtime->dma_bytes <= 0 ||
-                      runtime->dma_bytes >= MAXPAGES * EMUPAGESIZE))
+                      runtime->dma_bytes >= (emu->address_mode ? MAXPAGES1 : MAXPAGES0) * EMUPAGESIZE))
                return NULL;
        hdr = emu->memhdr;
        if (snd_BUG_ON(!hdr))
index e70a7fb393dd5d441fef9c9316ee417c46d9606b..b49feff0a31982e7c22071c08e8d088e91a97727 100644 (file)
@@ -873,14 +873,15 @@ struct hda_pcm *snd_hda_codec_pcm_new(struct hda_codec *codec,
        struct hda_pcm *pcm;
        va_list args;
 
-       va_start(args, fmt);
        pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
        if (!pcm)
                return NULL;
 
        pcm->codec = codec;
        kref_init(&pcm->kref);
+       va_start(args, fmt);
        pcm->name = kvasprintf(GFP_KERNEL, fmt, args);
+       va_end(args);
        if (!pcm->name) {
                kfree(pcm);
                return NULL;
@@ -2082,6 +2083,16 @@ static struct snd_kcontrol_new vmaster_mute_mode = {
        .put = vmaster_mute_mode_put,
 };
 
+/* meta hook to call each driver's vmaster hook */
+static void vmaster_hook(void *private_data, int enabled)
+{
+       struct hda_vmaster_mute_hook *hook = private_data;
+
+       if (hook->mute_mode != HDA_VMUTE_FOLLOW_MASTER)
+               enabled = hook->mute_mode;
+       hook->hook(hook->codec, enabled);
+}
+
 /**
  * snd_hda_add_vmaster_hook - Add a vmaster hook for mute-LED
  * @codec: the HDA codec
@@ -2100,9 +2111,9 @@ int snd_hda_add_vmaster_hook(struct hda_codec *codec,
 
        if (!hook->hook || !hook->sw_kctl)
                return 0;
-       snd_ctl_add_vmaster_hook(hook->sw_kctl, hook->hook, codec);
        hook->codec = codec;
        hook->mute_mode = HDA_VMUTE_FOLLOW_MASTER;
+       snd_ctl_add_vmaster_hook(hook->sw_kctl, vmaster_hook, hook);
        if (!expose_enum_ctl)
                return 0;
        kctl = snd_ctl_new1(&vmaster_mute_mode, hook);
@@ -2128,14 +2139,7 @@ void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook)
         */
        if (hook->codec->bus->shutdown)
                return;
-       switch (hook->mute_mode) {
-       case HDA_VMUTE_FOLLOW_MASTER:
-               snd_ctl_sync_vmaster_hook(hook->sw_kctl);
-               break;
-       default:
-               hook->hook(hook->codec, hook->mute_mode);
-               break;
-       }
+       snd_ctl_sync_vmaster_hook(hook->sw_kctl);
 }
 EXPORT_SYMBOL_GPL(snd_hda_sync_vmaster_hook);
 
@@ -2529,7 +2533,7 @@ static void set_dig_out(struct hda_codec *codec, hda_nid_t nid,
        if (!d)
                return;
        for (; *d; d++)
-               snd_hdac_regmap_update(&codec->core, nid,
+               snd_hdac_regmap_update(&codec->core, *d,
                                       AC_VERB_SET_DIGI_CONVERT_1, mask, val);
 }
 
index be1b7ded8d8202f43282611f0549d20577f75f98..0efdb094d21cf90e0e90a3fa8745b29276a82fb0 100644 (file)
@@ -404,7 +404,7 @@ struct azx {
        ((chip)->ops->reg_readb((dev)->sd_addr + AZX_REG_##reg))
 
 #define azx_has_pm_runtime(chip) \
-       (!AZX_DCAPS_PM_RUNTIME || ((chip)->driver_caps & AZX_DCAPS_PM_RUNTIME))
+       ((chip)->driver_caps & AZX_DCAPS_PM_RUNTIME)
 
 /* PCM setup */
 static inline struct azx_dev *get_azx_dev(struct snd_pcm_substream *substream)
index 3d2597b7037bbc9c5a74faeeae035f5c5bd70f76..788f969b1a680e50f61940e31fe1a4609ccce402 100644 (file)
@@ -3259,7 +3259,8 @@ static int create_input_ctls(struct hda_codec *codec)
                val = PIN_IN;
                if (cfg->inputs[i].type == AUTO_PIN_MIC)
                        val |= snd_hda_get_default_vref(codec, pin);
-               if (pin != spec->hp_mic_pin)
+               if (pin != spec->hp_mic_pin &&
+                   !snd_hda_codec_get_pin_target(codec, pin))
                        set_pin_target(codec, pin, val, false);
 
                if (mixer) {
index 52a85d87c23c58ae11cd8985d4a50d808ffe3731..3052a2b095f7a7bd2483add40e4fbc893cdbc184 100644 (file)
@@ -55,6 +55,12 @@ void haswell_set_bclk(struct hda_intel *hda)
        int cdclk_freq;
        unsigned int bclk_m, bclk_n;
        struct i915_audio_component *acomp = &hda->audio_component;
+       struct pci_dev *pci = hda->chip.pci;
+
+       /* Only Haswell/Broadwell need set BCLK */
+       if (pci->device != 0x0a0c && pci->device != 0x0c0c
+          && pci->device != 0x0d0c && pci->device != 0x160c)
+               return;
 
        if (!acomp->ops)
                return;
index e1c2105155815ebc16c2fdc8e18e0ac8fe5c75d8..34040d26c94ff04c84e8ee1cb2115eb76b0e755d 100644 (file)
@@ -297,6 +297,9 @@ enum {
         AZX_DCAPS_PM_RUNTIME | AZX_DCAPS_I915_POWERWELL |\
         AZX_DCAPS_SNOOP_TYPE(SCH))
 
+#define AZX_DCAPS_INTEL_BAYTRAIL \
+       (AZX_DCAPS_INTEL_PCH_NOPM | AZX_DCAPS_I915_POWERWELL)
+
 #define AZX_DCAPS_INTEL_BRASWELL \
        (AZX_DCAPS_INTEL_PCH | AZX_DCAPS_I915_POWERWELL)
 
@@ -1992,7 +1995,7 @@ static const struct pci_device_id azx_ids[] = {
          .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM },
        /* BayTrail */
        { PCI_DEVICE(0x8086, 0x0f04),
-         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM },
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_BAYTRAIL },
        /* Braswell */
        { PCI_DEVICE(0x8086, 0x2284),
          .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_BRASWELL },
index ee6230767c641dfc67d7cc86ae2999e0fabf180c..baaf7ed068755f1fca23c1c8d39c6cd0e646ff35 100644 (file)
@@ -582,8 +582,8 @@ static void print_conn_list(struct snd_info_buffer *buffer,
 
        /* Get Cache connections info */
        cache_len = snd_hda_get_conn_list(codec, nid, &list);
-       if (cache_len != conn_len
-                       || memcmp(list, conn, conn_len)) {
+       if (cache_len >= 0 && (cache_len != conn_len ||
+                             memcmp(list, conn, conn_len) != 0)) {
                snd_iprintf(buffer, "  In-driver Connection: %d\n", cache_len);
                if (cache_len > 0) {
                        snd_iprintf(buffer, "    ");
index b18b9c67b262bbd21e72f96070acc89a5789ae86..e2afd53cc14c7356b84d80e3c2aaed30d3c8ab49 100644 (file)
@@ -4176,29 +4176,33 @@ static void alc_fixup_disable_aamix(struct hda_codec *codec,
        }
 }
 
-static unsigned int alc_power_filter_xps13(struct hda_codec *codec,
-                               hda_nid_t nid,
-                               unsigned int power_state)
+static void alc_shutup_dell_xps13(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
+       int hp_pin = spec->gen.autocfg.hp_pins[0];
 
-       /* Avoid pop noises when headphones are plugged in */
-       if (spec->gen.hp_jack_present)
-               if (nid == codec->core.afg || nid == 0x02 || nid == 0x15)
-                       return AC_PWRST_D0;
-       return snd_hda_gen_path_power_filter(codec, nid, power_state);
+       /* Prevent pop noises when headphones are plugged in */
+       snd_hda_codec_write(codec, hp_pin, 0,
+                           AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
+       msleep(20);
 }
 
 static void alc_fixup_dell_xps13(struct hda_codec *codec,
                                const struct hda_fixup *fix, int action)
 {
-       if (action == HDA_FIXUP_ACT_PROBE) {
-               struct alc_spec *spec = codec->spec;
-               struct hda_input_mux *imux = &spec->gen.input_mux;
-               int i;
+       struct alc_spec *spec = codec->spec;
+       struct hda_input_mux *imux = &spec->gen.input_mux;
+       int i;
 
-               spec->shutup = alc_no_shutup;
-               codec->power_filter = alc_power_filter_xps13;
+       switch (action) {
+       case HDA_FIXUP_ACT_PRE_PROBE:
+               /* mic pin 0x19 must be initialized with Vref Hi-Z, otherwise
+                * it causes a click noise at start up
+                */
+               snd_hda_codec_set_pin_target(codec, 0x19, PIN_VREFHIZ);
+               break;
+       case HDA_FIXUP_ACT_PROBE:
+               spec->shutup = alc_shutup_dell_xps13;
 
                /* Make the internal mic the default input source. */
                for (i = 0; i < imux->num_items; i++) {
@@ -4207,6 +4211,7 @@ static void alc_fixup_dell_xps13(struct hda_codec *codec,
                                break;
                        }
                }
+               break;
        }
 }
 
@@ -5231,6 +5236,16 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
        {0x1b, 0x411111f0}, \
        {0x1e, 0x411111f0}
 
+#define ALC256_STANDARD_PINS \
+       {0x12, 0x90a60140}, \
+       {0x14, 0x90170110}, \
+       {0x19, 0x411111f0}, \
+       {0x1a, 0x411111f0}, \
+       {0x1b, 0x411111f0}, \
+       {0x1d, 0x40700001}, \
+       {0x1e, 0x411111f0}, \
+       {0x21, 0x02211020}
+
 #define ALC282_STANDARD_PINS \
        {0x14, 0x90170110}, \
        {0x18, 0x411111f0}, \
@@ -5331,15 +5346,11 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
                {0x1d, 0x40700001},
                {0x21, 0x02211050}),
        SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
-               {0x12, 0x90a60140},
-               {0x13, 0x40000000},
-               {0x14, 0x90170110},
-               {0x19, 0x411111f0},
-               {0x1a, 0x411111f0},
-               {0x1b, 0x411111f0},
-               {0x1d, 0x40700001},
-               {0x1e, 0x411111f0},
-               {0x21, 0x02211020}),
+               ALC256_STANDARD_PINS,
+               {0x13, 0x40000000}),
+       SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+               ALC256_STANDARD_PINS,
+               {0x13, 0x411111f0}),
        SND_HDA_PIN_QUIRK(0x10ec0280, 0x103c, "HP", ALC280_FIXUP_HP_GPIO4,
                {0x12, 0x90a60130},
                {0x13, 0x40000000},
@@ -5667,6 +5678,8 @@ static int patch_alc269(struct hda_codec *codec)
                break;
        case 0x10ec0256:
                spec->codec_variant = ALC269_TYPE_ALC256;
+               spec->gen.mixer_nid = 0; /* ALC256 does not have any loopback mixer path */
+               alc_update_coef_idx(codec, 0x36, 1 << 13, 1 << 5); /* Switch pcbeep path to Line in path*/
                break;
        }
 
@@ -5680,8 +5693,8 @@ static int patch_alc269(struct hda_codec *codec)
        if (err < 0)
                goto error;
 
-       if (!spec->gen.no_analog && spec->gen.beep_nid)
-               set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
+       if (!spec->gen.no_analog && spec->gen.beep_nid && spec->gen.mixer_nid)
+               set_beep_amp(spec, spec->gen.mixer_nid, 0x04, HDA_INPUT);
 
        codec->patch_ops = alc_patch_ops;
        codec->patch_ops.stream_pm = snd_hda_gen_stream_pm;
index 0a4ad5feb82e7817f7036f86c973d02b1dfecb9b..d51703e305238700bce9da8184971ffa516247ca 100644 (file)
@@ -72,6 +72,7 @@ static void hda_fixup_thinkpad_acpi(struct hda_codec *codec,
                if (led_set_func(TPACPI_LED_MUTE, false) >= 0) {
                        old_vmaster_hook = spec->vmaster_mute.hook;
                        spec->vmaster_mute.hook = update_tpacpi_mute_led;
+                       spec->vmaster_mute_enum = 1;
                        removefunc = false;
                }
                if (led_set_func(TPACPI_LED_MICMUTE, false) >= 0) {
index 749069aa6997be301813d1bee1b3e43083967cf0..b120925223aec23c40aba2428387f31aa2a4c227 100644 (file)
@@ -3101,13 +3101,13 @@ static int snd_intel8x0_create(struct snd_card *card,
                chip->bmaddr = pci_iomap(pci, 3, 0);
        else
                chip->bmaddr = pci_iomap(pci, 1, 0);
+
+ port_inited:
        if (!chip->bmaddr) {
                dev_err(card->dev, "Controller space ioremap problem\n");
                snd_intel8x0_free(chip);
                return -EIO;
        }
-
- port_inited:
        chip->bdbars_count = bdbars[device_type];
 
        /* initialize offsets */
index 57da0ceda03fa7eb0f4ce384ae040703a7c99f5c..eff4b4d512b7b8fbd8bfa31c3c0ee3a79474a478 100644 (file)
@@ -840,8 +840,8 @@ int arizona_hp_ev(struct snd_soc_dapm_widget *w,
        priv->arizona->hp_ena &= ~mask;
        priv->arizona->hp_ena |= val;
 
-       /* Force off if HPDET magic is active */
-       if (priv->arizona->hpdet_magic)
+       /* Force off if HPDET clamp is active */
+       if (priv->arizona->hpdet_clamp)
                val = 0;
 
        regmap_update_bits_async(arizona->regmap, ARIZONA_OUTPUT_ENABLES_1,
index 69528ae5410c991125c2e16f3810d51ae7026b88..be4d741c45baa3164c8698782055aa9599d1df45 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/gpio.h>
+#include <linux/acpi.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -2656,6 +2657,15 @@ static const struct i2c_device_id rt5645_i2c_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, rt5645_i2c_id);
 
+#ifdef CONFIG_ACPI
+static struct acpi_device_id rt5645_acpi_match[] = {
+       { "10EC5645", 0 },
+       { "10EC5650", 0 },
+       {},
+};
+MODULE_DEVICE_TABLE(acpi, rt5645_acpi_match);
+#endif
+
 static int rt5645_i2c_probe(struct i2c_client *i2c,
                    const struct i2c_device_id *id)
 {
@@ -2770,7 +2780,7 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
 
                case RT5645_DMIC_DATA_GPIO12:
                        regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1,
-                               RT5645_DMIC_1_DP_MASK, RT5645_DMIC_2_DP_GPIO12);
+                               RT5645_DMIC_2_DP_MASK, RT5645_DMIC_2_DP_GPIO12);
                        regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1,
                                RT5645_GP12_PIN_MASK,
                                RT5645_GP12_PIN_DMIC2_SDA);
@@ -2872,6 +2882,7 @@ static struct i2c_driver rt5645_i2c_driver = {
        .driver = {
                .name = "rt5645",
                .owner = THIS_MODULE,
+               .acpi_match_table = ACPI_PTR(rt5645_acpi_match),
        },
        .probe = rt5645_i2c_probe,
        .remove   = rt5645_i2c_remove,
index af182586712d42f9bbac6d5b03338e3e5219cf23..169aa471ffbd447e2ec3f009d775524eb77aa5ae 100644 (file)
@@ -62,6 +62,9 @@ static const struct reg_default init_list[] = {
        {RT5677_PR_BASE + 0x1e, 0x0000},
        {RT5677_PR_BASE + 0x12, 0x0eaa},
        {RT5677_PR_BASE + 0x14, 0x018a},
+       {RT5677_PR_BASE + 0x15, 0x0490},
+       {RT5677_PR_BASE + 0x38, 0x0f71},
+       {RT5677_PR_BASE + 0x39, 0x0f71},
 };
 #define RT5677_INIT_REG_LEN ARRAY_SIZE(init_list)
 
@@ -914,7 +917,7 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w,
 {
        struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
        struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
-       int idx = rl6231_calc_dmic_clk(rt5677->sysclk);
+       int idx = rl6231_calc_dmic_clk(rt5677->lrck[RT5677_AIF1] << 8);
 
        if (idx < 0)
                dev_err(codec->dev, "Failed to set DMIC clock\n");
index 16f1b71edb554aac82cb74093cbf6a80b84f5d0b..aab0af681e8cb3cd1b2c0ea0b5a22e32c1f08c2b 100644 (file)
@@ -280,8 +280,8 @@ static int tfa9879_i2c_probe(struct i2c_client *i2c,
        int i;
 
        tfa9879 = devm_kzalloc(&i2c->dev, sizeof(*tfa9879), GFP_KERNEL);
-       if (IS_ERR(tfa9879))
-               return PTR_ERR(tfa9879);
+       if (!tfa9879)
+               return -ENOMEM;
 
        i2c_set_clientdata(i2c, tfa9879);
 
index e8bb8eef1d16bee3d9d8ca5e4b7e4d5a7a026267..0d48804218b1bdbc31198fbb6b0ce16bc09a4fc3 100644 (file)
@@ -1357,7 +1357,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
        }
 
        ssi_private->irq = platform_get_irq(pdev, 0);
-       if (!ssi_private->irq) {
+       if (ssi_private->irq < 0) {
                dev_err(&pdev->dev, "no irq for node %s\n", pdev->name);
                return ssi_private->irq;
        }
index cd9aee9871a36a4400646441f1105d949fe5a2af..3853ec2ddbc758d2c558dfcbe093d2cee59af8a1 100644 (file)
@@ -4,7 +4,7 @@ obj-$(CONFIG_SND_SOC_INTEL_SST) += common/
 # Platform Support
 obj-$(CONFIG_SND_SOC_INTEL_HASWELL) += haswell/
 obj-$(CONFIG_SND_SOC_INTEL_BAYTRAIL) += baytrail/
-obj-$(CONFIG_SND_SOC_INTEL_BAYTRAIL) += atom/
+obj-$(CONFIG_SND_SST_MFLD_PLATFORM) += atom/
 
 # Machine support
 obj-$(CONFIG_SND_SOC_INTEL_SST) += boards/
index 1efb33b36303ea8b5c3c725c4f35b65055744689..a839dbfa5218e832c487512ca3d9f77f0b7db629 100644 (file)
@@ -759,7 +759,6 @@ fw_err:
 dsp_new_err:
        sst_ipc_fini(ipc);
 ipc_init_err:
-       kfree(byt);
 
        return err;
 }
index 344a1e9bbce5794311ec95a24143581ebf715907..324eceb07b255b06e71c07cd1267a55364ce403e 100644 (file)
@@ -2201,7 +2201,6 @@ dma_err:
 dsp_new_err:
        sst_ipc_fini(ipc);
 ipc_init_err:
-       kfree(hsw);
        return ret;
 }
 EXPORT_SYMBOL_GPL(sst_hsw_dsp_init);
index 6698d058de29600a464be79490bec641736819c3..dc790abaa3318e4760107c726ac02ea7e2c1a2cb 100644 (file)
@@ -194,7 +194,7 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream,
                int cmd, struct snd_soc_dai *dai)
 {
        struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
-       int ret;
+       int ret = -EINVAL;
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
index 326d3c3804e34bccf1069e61df0bb12d5a8bf042..5bf723689692fc52ffc5edce20f82e8d5cb4fc21 100644 (file)
@@ -461,8 +461,8 @@ static int s3c24xx_iis_dev_probe(struct platform_device *pdev)
                return -ENOENT;
        }
        s3c24xx_i2s.regs = devm_ioremap_resource(&pdev->dev, res);
-       if (s3c24xx_i2s.regs == NULL)
-               return -ENXIO;
+       if (IS_ERR(s3c24xx_i2s.regs))
+               return PTR_ERR(s3c24xx_i2s.regs);
 
        s3c24xx_i2s_pcm_stereo_out.dma_addr = res->start + S3C2410_IISFIFO;
        s3c24xx_i2s_pcm_stereo_in.dma_addr = res->start + S3C2410_IISFIFO;
index 0c2af21b0b82513176ac841ae8e394cd6711eead..142c066eaee2ecb13dcfbee6ac01b076ce52894c 100644 (file)
@@ -250,6 +250,7 @@ struct fsi_clk {
 
 struct fsi_priv {
        void __iomem *base;
+       phys_addr_t phys;
        struct fsi_master *master;
 
        struct fsi_stream playback;
@@ -1371,13 +1372,18 @@ static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct dev
                                shdma_chan_filter, (void *)io->dma_id,
                                dev, is_play ? "tx" : "rx");
        if (io->chan) {
-               struct dma_slave_config cfg;
+               struct dma_slave_config cfg = {};
                int ret;
 
-               cfg.slave_id    = io->dma_id;
-               cfg.dst_addr    = 0; /* use default addr */
-               cfg.src_addr    = 0; /* use default addr */
-               cfg.direction   = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
+               if (is_play) {
+                       cfg.dst_addr            = fsi->phys + REG_DODT;
+                       cfg.dst_addr_width      = DMA_SLAVE_BUSWIDTH_4_BYTES;
+                       cfg.direction           = DMA_MEM_TO_DEV;
+               } else {
+                       cfg.src_addr            = fsi->phys + REG_DIDT;
+                       cfg.src_addr_width      = DMA_SLAVE_BUSWIDTH_4_BYTES;
+                       cfg.direction           = DMA_DEV_TO_MEM;
+               }
 
                ret = dmaengine_slave_config(io->chan, &cfg);
                if (ret < 0) {
@@ -1974,6 +1980,7 @@ static int fsi_probe(struct platform_device *pdev)
        /* FSI A setting */
        fsi             = &master->fsia;
        fsi->base       = master->base;
+       fsi->phys       = res->start;
        fsi->master     = master;
        fsi_port_info_init(fsi, &info.port_a);
        fsi_handler_init(fsi, &info.port_a);
@@ -1986,6 +1993,7 @@ static int fsi_probe(struct platform_device *pdev)
        /* FSI B setting */
        fsi             = &master->fsib;
        fsi->base       = master->base + 0x40;
+       fsi->phys       = res->start + 0x40;
        fsi->master     = master;
        fsi_port_info_init(fsi, &info.port_b);
        fsi_handler_init(fsi, &info.port_b);
index ac3756f6af603e9a21fe79988b00d13477da6fab..144308f15fb336cd1a27e99e57ab9b40b255499b 100644 (file)
@@ -156,6 +156,7 @@ static int rsnd_dmaen_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id,
                                                  (void *)id);
        }
        if (IS_ERR_OR_NULL(dmaen->chan)) {
+               dmaen->chan = NULL;
                dev_err(dev, "can't get dma channel\n");
                goto rsnd_dma_channel_err;
        }
index ab37add269aecd6ae00909776d954735e587f9a2..82e350e9501ccc0d5ebc82962f60c034466448eb 100644 (file)
@@ -118,12 +118,8 @@ snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure)
        if (snd_BUG_ON(!arg || !emu))
                return -ENXIO;
 
-       mutex_lock(&emu->register_mutex);
-
-       if (!snd_emux_inc_count(emu)) {
-               mutex_unlock(&emu->register_mutex);
+       if (!snd_emux_inc_count(emu))
                return -EFAULT;
-       }
 
        memset(&callback, 0, sizeof(callback));
        callback.owner = THIS_MODULE;
@@ -135,7 +131,6 @@ snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure)
        if (p == NULL) {
                snd_printk(KERN_ERR "can't create port\n");
                snd_emux_dec_count(emu);
-               mutex_unlock(&emu->register_mutex);
                return -ENOMEM;
        }
 
@@ -148,8 +143,6 @@ snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure)
        reset_port_mode(p, arg->seq_mode);
 
        snd_emux_reset_port(p);
-
-       mutex_unlock(&emu->register_mutex);
        return 0;
 }
 
@@ -195,13 +188,11 @@ snd_emux_close_seq_oss(struct snd_seq_oss_arg *arg)
        if (snd_BUG_ON(!emu))
                return -ENXIO;
 
-       mutex_lock(&emu->register_mutex);
        snd_emux_sounds_off_all(p);
        snd_soundfont_close_check(emu->sflist, SF_CLIENT_NO(p->chset.port));
        snd_seq_event_port_detach(p->chset.client, p->chset.port);
        snd_emux_dec_count(emu);
 
-       mutex_unlock(&emu->register_mutex);
        return 0;
 }
 
index 7778b8e19782e24a3ca56a5aa5dff9e00bf33e4d..a0209204ae4892a490877c30eaf056c45cd8043a 100644 (file)
@@ -124,12 +124,10 @@ snd_emux_detach_seq(struct snd_emux *emu)
        if (emu->voices)
                snd_emux_terminate_all(emu);
                
-       mutex_lock(&emu->register_mutex);
        if (emu->client >= 0) {
                snd_seq_delete_kernel_client(emu->client);
                emu->client = -1;
        }
-       mutex_unlock(&emu->register_mutex);
 }
 
 
@@ -269,8 +267,8 @@ snd_emux_event_input(struct snd_seq_event *ev, int direct, void *private_data,
 /*
  * increment usage count
  */
-int
-snd_emux_inc_count(struct snd_emux *emu)
+static int
+__snd_emux_inc_count(struct snd_emux *emu)
 {
        emu->used++;
        if (!try_module_get(emu->ops.owner))
@@ -284,12 +282,21 @@ snd_emux_inc_count(struct snd_emux *emu)
        return 1;
 }
 
+int snd_emux_inc_count(struct snd_emux *emu)
+{
+       int ret;
+
+       mutex_lock(&emu->register_mutex);
+       ret = __snd_emux_inc_count(emu);
+       mutex_unlock(&emu->register_mutex);
+       return ret;
+}
 
 /*
  * decrease usage count
  */
-void
-snd_emux_dec_count(struct snd_emux *emu)
+static void
+__snd_emux_dec_count(struct snd_emux *emu)
 {
        module_put(emu->card->module);
        emu->used--;
@@ -298,6 +305,12 @@ snd_emux_dec_count(struct snd_emux *emu)
        module_put(emu->ops.owner);
 }
 
+void snd_emux_dec_count(struct snd_emux *emu)
+{
+       mutex_lock(&emu->register_mutex);
+       __snd_emux_dec_count(emu);
+       mutex_unlock(&emu->register_mutex);
+}
 
 /*
  * Routine that is called upon a first use of a particular port
@@ -317,7 +330,7 @@ snd_emux_use(void *private_data, struct snd_seq_port_subscribe *info)
 
        mutex_lock(&emu->register_mutex);
        snd_emux_init_port(p);
-       snd_emux_inc_count(emu);
+       __snd_emux_inc_count(emu);
        mutex_unlock(&emu->register_mutex);
        return 0;
 }
@@ -340,7 +353,7 @@ snd_emux_unuse(void *private_data, struct snd_seq_port_subscribe *info)
 
        mutex_lock(&emu->register_mutex);
        snd_emux_sounds_off_all(p);
-       snd_emux_dec_count(emu);
+       __snd_emux_dec_count(emu);
        mutex_unlock(&emu->register_mutex);
        return 0;
 }
index 8bcc87cf5667efbebc164e000f07cae23fc2a4c2..789d19ec035daf4aab2e2094d1952be71e25f822 100644 (file)
@@ -79,7 +79,10 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
                format = 1 << UAC_FORMAT_TYPE_I_PCM;
        }
        if (format & (1 << UAC_FORMAT_TYPE_I_PCM)) {
-               if (chip->usb_id == USB_ID(0x0582, 0x0016) /* Edirol SD-90 */ &&
+               if (((chip->usb_id == USB_ID(0x0582, 0x0016)) ||
+                    /* Edirol SD-90 */
+                    (chip->usb_id == USB_ID(0x0582, 0x000c))) &&
+                    /* Roland SC-D70 */
                    sample_width == 24 && sample_bytes == 2)
                        sample_bytes = 3;
                else if (sample_width > sample_bytes * 8) {
index 07f984d5f5162809ee6124f651585df5c3a4496f..2f6d3e9a1bcd0144cf81d77f3ec085af3984d07e 100644 (file)
@@ -816,37 +816,11 @@ YAMAHA_DEVICE(0x7010, "UB99"),
                .data = (const struct snd_usb_audio_quirk[]) {
                        {
                                .ifnum = 0,
-                               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
-                               .data = & (const struct audioformat) {
-                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
-                                       .channels = 2,
-                                       .iface = 0,
-                                       .altsetting = 1,
-                                       .altset_idx = 1,
-                                       .attributes = 0,
-                                       .endpoint = 0x01,
-                                       .ep_attr = 0x01,
-                                       .rates = SNDRV_PCM_RATE_CONTINUOUS,
-                                       .rate_min = 44100,
-                                       .rate_max = 44100,
-                               }
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
                        },
                        {
                                .ifnum = 1,
-                               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
-                               .data = & (const struct audioformat) {
-                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
-                                       .channels = 2,
-                                       .iface = 1,
-                                       .altsetting = 1,
-                                       .altset_idx = 1,
-                                       .attributes = 0,
-                                       .endpoint = 0x81,
-                                       .ep_attr = 0x01,
-                                       .rates = SNDRV_PCM_RATE_CONTINUOUS,
-                                       .rate_min = 44100,
-                                       .rate_max = 44100,
-                               }
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
                        },
                        {
                                .ifnum = 2,
index 99ffe61051a702ab386a45a13c364bc1a77f0f25..a8ab795569266f6e48550e4fb400d27a6f4c817d 100644 (file)
@@ -3,7 +3,7 @@
 CC = $(CROSS_COMPILE)gcc
 PTHREAD_LIBS = -lpthread
 WARNINGS = -Wall -Wextra
-CFLAGS = $(WARNINGS) -g $(PTHREAD_LIBS)
+CFLAGS = $(WARNINGS) -g $(PTHREAD_LIBS) $(shell getconf LFS_CFLAGS)
 
 all: hv_kvp_daemon hv_vss_daemon hv_fcopy_daemon
 %: %.c
index 5e63f70bd956e56f9506ef306e11ff2206c23b52..506dd01488286f8033f3ceaf3915fd06742f33de 100644 (file)
@@ -81,6 +81,7 @@ static int vss_operate(int operation)
        char match[] = "/dev/";
        FILE *mounts;
        struct mntent *ent;
+       char errdir[1024] = {0};
        unsigned int cmd;
        int error = 0, root_seen = 0, save_errno = 0;
 
@@ -115,6 +116,8 @@ static int vss_operate(int operation)
                        goto err;
        }
 
+       endmntent(mounts);
+
        if (root_seen) {
                error |= vss_do_freeze("/", cmd);
                if (error && operation == VSS_OP_FREEZE)
@@ -124,16 +127,19 @@ static int vss_operate(int operation)
        goto out;
 err:
        save_errno = errno;
+       if (ent) {
+               strncpy(errdir, ent->mnt_dir, sizeof(errdir)-1);
+               endmntent(mounts);
+       }
        vss_operate(VSS_OP_THAW);
        /* Call syslog after we thaw all filesystems */
        if (ent)
                syslog(LOG_ERR, "FREEZE of %s failed; error:%d %s",
-                      ent->mnt_dir, save_errno, strerror(save_errno));
+                      errdir, save_errno, strerror(save_errno));
        else
                syslog(LOG_ERR, "FREEZE of / failed; error:%d %s", save_errno,
                       strerror(save_errno));
 out:
-       endmntent(mounts);
        return error;
 }
 
index d8fe29fc19a41de308141fac73ce05dc80388f39..8bd9606584632582f7e893c0a3c01e8f0240678f 100644 (file)
@@ -16,7 +16,7 @@ MAKEFLAGS += --no-print-directory
 LIBFILE = $(OUTPUT)libapi.a
 
 CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
-CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -D_FORTIFY_SOURCE=2 -fPIC
+CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC
 CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
 
 RM = rm -f
index e0917c0f5d9f3babf82fc84ece90472a8a321f4e..29f94f6f0d9e9e2510d38471724e686a9a21167c 100644 (file)
@@ -3865,7 +3865,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
                        } else if (el_size == 4) {
                                trace_seq_printf(s, "%u", *(uint32_t *)num);
                        } else if (el_size == 8) {
-                               trace_seq_printf(s, "%lu", *(uint64_t *)num);
+                               trace_seq_printf(s, "%"PRIu64, *(uint64_t *)num);
                        } else {
                                trace_seq_printf(s, "BAD SIZE:%d 0x%x",
                                                 el_size, *(uint8_t *)num);
index bedff6b5b3cf3a61b38b172a97504cafebfd519f..ad0d9b5342fb6ae4713178daf15fdcce6238a2d9 100644 (file)
@@ -132,6 +132,9 @@ int bench_futex_requeue(int argc, const char **argv,
        if (!fshared)
                futex_flag = FUTEX_PRIVATE_FLAG;
 
+       if (nrequeue > nthreads)
+               nrequeue = nthreads;
+
        printf("Run summary [PID %d]: Requeuing %d threads (from [%s] %p to %p), "
               "%d at a time.\n\n",  getpid(), nthreads,
               fshared ? "shared":"private", &futex1, &futex2, nrequeue);
@@ -161,20 +164,18 @@ int bench_futex_requeue(int argc, const char **argv,
 
                /* Ok, all threads are patiently blocked, start requeueing */
                gettimeofday(&start, NULL);
-               for (nrequeued = 0; nrequeued < nthreads; nrequeued += nrequeue) {
+               while (nrequeued < nthreads) {
                        /*
                         * Do not wakeup any tasks blocked on futex1, allowing
                         * us to really measure futex_wait functionality.
                         */
-                       futex_cmp_requeue(&futex1, 0, &futex2, 0,
-                                         nrequeue, futex_flag);
+                       nrequeued += futex_cmp_requeue(&futex1, 0, &futex2, 0,
+                                                      nrequeue, futex_flag);
                }
+
                gettimeofday(&end, NULL);
                timersub(&end, &start, &runtime);
 
-               if (nrequeued > nthreads)
-                       nrequeued = nthreads;
-
                update_stats(&requeued_stats, nrequeued);
                update_stats(&requeuetime_stats, runtime.tv_usec);
 
@@ -184,7 +185,7 @@ int bench_futex_requeue(int argc, const char **argv,
                }
 
                /* everybody should be blocked on futex2, wake'em up */
-               nrequeued = futex_wake(&futex2, nthreads, futex_flag);
+               nrequeued = futex_wake(&futex2, nrequeued, futex_flag);
                if (nthreads != nrequeued)
                        warnx("couldn't wakeup all tasks (%d/%d)", nrequeued, nthreads);
 
index ebfa163b80b568af4d2708b1ff3b1980ea16e2b6..ba5efa4710b558239ff79c08b025ddc2da06efc5 100644 (file)
@@ -180,7 +180,7 @@ static const struct option options[] = {
        OPT_INTEGER('H', "thp"          , &p0.thp,              "MADV_NOHUGEPAGE < 0 < MADV_HUGEPAGE"),
        OPT_BOOLEAN('c', "show_convergence", &p0.show_convergence, "show convergence details"),
        OPT_BOOLEAN('m', "measure_convergence", &p0.measure_convergence, "measure convergence latency"),
-       OPT_BOOLEAN('q', "quiet"        , &p0.show_quiet,       "bzero the initial allocations"),
+       OPT_BOOLEAN('q', "quiet"        , &p0.show_quiet,       "quiet mode"),
        OPT_BOOLEAN('S', "serialize-startup", &p0.serialize_startup,"serialize thread startup"),
 
        /* Special option string parsing callbacks: */
@@ -828,6 +828,9 @@ static int count_process_nodes(int process_nr)
                td = g->threads + task_nr;
 
                node = numa_node_of_cpu(td->curr_cpu);
+               if (node < 0) /* curr_cpu was likely still -1 */
+                       return 0;
+
                node_present[node] = 1;
        }
 
@@ -882,6 +885,11 @@ static void calc_convergence_compression(int *strong)
        for (p = 0; p < g->p.nr_proc; p++) {
                unsigned int nodes = count_process_nodes(p);
 
+               if (!nodes) {
+                       *strong = 0;
+                       return;
+               }
+
                nodes_min = min(nodes, nodes_min);
                nodes_max = max(nodes, nodes_max);
        }
@@ -1395,7 +1403,7 @@ static void print_res(const char *name, double val,
        if (!name)
                name = "main,";
 
-       if (g->p.show_quiet)
+       if (!g->p.show_quiet)
                printf(" %-30s %15.3f, %-15s %s\n", name, val, txt_unit, txt_short);
        else
                printf(" %14.3f %s\n", val, txt_long);
index 63ea01349b6e2b6c6bf4fb16ce3722c93d625695..1634186d537cdc2eb2ee38b174891361ef13db9f 100644 (file)
@@ -319,7 +319,7 @@ static int page_stat_cmp(struct page_stat *a, struct page_stat *b)
        return 0;
 }
 
-static struct page_stat *search_page_alloc_stat(struct page_stat *stat, bool create)
+static struct page_stat *search_page_alloc_stat(struct page_stat *pstat, bool create)
 {
        struct rb_node **node = &page_alloc_tree.rb_node;
        struct rb_node *parent = NULL;
@@ -331,7 +331,7 @@ static struct page_stat *search_page_alloc_stat(struct page_stat *stat, bool cre
                parent = *node;
                data = rb_entry(*node, struct page_stat, node);
 
-               cmp = page_stat_cmp(data, stat);
+               cmp = page_stat_cmp(data, pstat);
                if (cmp < 0)
                        node = &parent->rb_left;
                else if (cmp > 0)
@@ -345,10 +345,10 @@ static struct page_stat *search_page_alloc_stat(struct page_stat *stat, bool cre
 
        data = zalloc(sizeof(*data));
        if (data != NULL) {
-               data->page = stat->page;
-               data->order = stat->order;
-               data->gfp_flags = stat->gfp_flags;
-               data->migrate_type = stat->migrate_type;
+               data->page = pstat->page;
+               data->order = pstat->order;
+               data->gfp_flags = pstat->gfp_flags;
+               data->migrate_type = pstat->migrate_type;
 
                rb_link_node(&data->node, parent, node);
                rb_insert_color(&data->node, &page_alloc_tree);
@@ -375,7 +375,7 @@ static int perf_evsel__process_page_alloc_event(struct perf_evsel *evsel,
        unsigned int migrate_type = perf_evsel__intval(evsel, sample,
                                                       "migratetype");
        u64 bytes = kmem_page_size << order;
-       struct page_stat *stat;
+       struct page_stat *pstat;
        struct page_stat this = {
                .order = order,
                .gfp_flags = gfp_flags,
@@ -401,21 +401,21 @@ static int perf_evsel__process_page_alloc_event(struct perf_evsel *evsel,
         * This is to find the current page (with correct gfp flags and
         * migrate type) at free event.
         */
-       stat = search_page(page, true);
-       if (stat == NULL)
+       pstat = search_page(page, true);
+       if (pstat == NULL)
                return -ENOMEM;
 
-       stat->order = order;
-       stat->gfp_flags = gfp_flags;
-       stat->migrate_type = migrate_type;
+       pstat->order = order;
+       pstat->gfp_flags = gfp_flags;
+       pstat->migrate_type = migrate_type;
 
        this.page = page;
-       stat = search_page_alloc_stat(&this, true);
-       if (stat == NULL)
+       pstat = search_page_alloc_stat(&this, true);
+       if (pstat == NULL)
                return -ENOMEM;
 
-       stat->nr_alloc++;
-       stat->alloc_bytes += bytes;
+       pstat->nr_alloc++;
+       pstat->alloc_bytes += bytes;
 
        order_stats[order][migrate_type]++;
 
@@ -428,7 +428,7 @@ static int perf_evsel__process_page_free_event(struct perf_evsel *evsel,
        u64 page;
        unsigned int order = perf_evsel__intval(evsel, sample, "order");
        u64 bytes = kmem_page_size << order;
-       struct page_stat *stat;
+       struct page_stat *pstat;
        struct page_stat this = {
                .order = order,
        };
@@ -441,8 +441,8 @@ static int perf_evsel__process_page_free_event(struct perf_evsel *evsel,
        nr_page_frees++;
        total_page_free_bytes += bytes;
 
-       stat = search_page(page, false);
-       if (stat == NULL) {
+       pstat = search_page(page, false);
+       if (pstat == NULL) {
                pr_debug2("missing free at page %"PRIx64" (order: %d)\n",
                          page, order);
 
@@ -453,18 +453,18 @@ static int perf_evsel__process_page_free_event(struct perf_evsel *evsel,
        }
 
        this.page = page;
-       this.gfp_flags = stat->gfp_flags;
-       this.migrate_type = stat->migrate_type;
+       this.gfp_flags = pstat->gfp_flags;
+       this.migrate_type = pstat->migrate_type;
 
-       rb_erase(&stat->node, &page_tree);
-       free(stat);
+       rb_erase(&pstat->node, &page_tree);
+       free(pstat);
 
-       stat = search_page_alloc_stat(&this, false);
-       if (stat == NULL)
+       pstat = search_page_alloc_stat(&this, false);
+       if (pstat == NULL)
                return -ENOENT;
 
-       stat->nr_free++;
-       stat->free_bytes += bytes;
+       pstat->nr_free++;
+       pstat->free_bytes += bytes;
 
        return 0;
 }
@@ -640,9 +640,9 @@ static void print_page_summary(void)
               nr_page_frees, total_page_free_bytes / 1024);
        printf("\n");
 
-       printf("%-30s: %'16lu   [ %'16"PRIu64" KB ]\n", "Total alloc+freed requests",
+       printf("%-30s: %'16"PRIu64"   [ %'16"PRIu64" KB ]\n", "Total alloc+freed requests",
               nr_alloc_freed, (total_alloc_freed_bytes) / 1024);
-       printf("%-30s: %'16lu   [ %'16"PRIu64" KB ]\n", "Total alloc-only requests",
+       printf("%-30s: %'16"PRIu64"   [ %'16"PRIu64" KB ]\n", "Total alloc-only requests",
               nr_page_allocs - nr_alloc_freed,
               (total_page_alloc_bytes - total_alloc_freed_bytes) / 1024);
        printf("%-30s: %'16lu   [ %'16"PRIu64" KB ]\n", "Total free-only requests",
index 476cdf7afcca3fc7b1135d9973d15886cd7b8988..b63aeda719be0c7604da5229e1a3a0ec33253400 100644 (file)
@@ -329,7 +329,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
                fprintf(stdout, "\n\n");
        }
 
-       if (sort_order == default_sort_order &&
+       if (sort_order == NULL &&
            parent_pattern == default_parent_pattern) {
                fprintf(stdout, "#\n# (%s)\n#\n", help);
 
index 1cb3436276d1599ea0f1ffc80d36e655aad690be..6a4d5d41c671d0ce176deb13d318de35acee0161 100644 (file)
@@ -733,7 +733,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
 "Kernel address maps (/proc/{kallsyms,modules}) are restricted.\n\n"
 "Check /proc/sys/kernel/kptr_restrict.\n\n"
 "Kernel%s samples will not be resolved.\n",
-                         !RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION]) ?
+                         al.map && !RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION]) ?
                          " modules" : "");
                if (use_browser <= 0)
                        sleep(5);
index e124741be187ee729a77b088d30f843ee24eefa4..e122970361f21af6d07c321480aefa2cb90bf31d 100644 (file)
@@ -2241,10 +2241,11 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
        if (err < 0)
                goto out_error_mmap;
 
+       if (!target__none(&trace->opts.target))
+               perf_evlist__enable(evlist);
+
        if (forks)
                perf_evlist__start_workload(evlist);
-       else
-               perf_evlist__enable(evlist);
 
        trace->multiple_threads = evlist->threads->map[0] == -1 ||
                                  evlist->threads->nr > 1 ||
@@ -2272,6 +2273,11 @@ next_event:
 
                        if (interrupted)
                                goto out_disable;
+
+                       if (done && !draining) {
+                               perf_evlist__disable(evlist);
+                               draining = true;
+                       }
                }
        }
 
index d8bb616ff57c29b38c05ac134d35e88f646f42cd..d05b77cf35f77051354b9d08acc035cf4575dd5b 100644 (file)
@@ -1084,6 +1084,8 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
         *
         * TODO:Group name support
         */
+       if (!arg)
+               return -EINVAL;
 
        ptr = strpbrk(arg, ";=@+%");
        if (ptr && *ptr == '=') {       /* Event name */
index b5bf9d5efeaf2dc32317573de059c1d73367cc7c..2a76e14db73289d196a0171f4830693b46445e23 100644 (file)
@@ -578,10 +578,12 @@ static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
        /* Search child die for local variables and parameters. */
        if (!die_find_variable_at(sc_die, pf->pvar->var, pf->addr, &vr_die)) {
                /* Search again in global variables */
-               if (!die_find_variable_at(&pf->cu_die, pf->pvar->var, 0, &vr_die))
+               if (!die_find_variable_at(&pf->cu_die, pf->pvar->var,
+                                               0, &vr_die)) {
                        pr_warning("Failed to find '%s' in this function.\n",
                                   pf->pvar->var);
                        ret = -ENOENT;
+               }
        }
        if (ret >= 0)
                ret = convert_variable(&vr_die, pf);
index 9690798e64463bc2ef7178cb35078406d0b5971d..8b278983cfc574bbfa230ad2b818c22d0903bdc6 100644 (file)
 struct pci_dev *pci_acc_init(struct pci_access **pacc, int domain, int bus,
                             int slot, int func, int vendor, int dev)
 {
-       struct pci_filter filter_nb_link = { domain, bus, slot, func,
-                                            vendor, dev };
+       struct pci_filter filter_nb_link;
        struct pci_dev *device;
 
        *pacc = pci_alloc();
        if (*pacc == NULL)
                return NULL;
 
+       pci_filter_init(*pacc, &filter_nb_link);
+       filter_nb_link.domain   = domain;
+       filter_nb_link.bus      = bus;
+       filter_nb_link.slot     = slot;
+       filter_nb_link.func     = func;
+       filter_nb_link.vendor   = vendor;
+       filter_nb_link.device   = dev;
+
        pci_init(*pacc);
        pci_scan_bus(*pacc);
 
index 5a161175bbd4197e907dbeb68f7c5f7003ecdf76..a9099d9f8f39ea8a38a6345b15e2d24ab2e00eb7 100644 (file)
@@ -26,7 +26,7 @@ override define EMIT_TESTS
        $(MAKE) -s -C ebb emit_tests
 endef
 
-DEFAULT_INSTALL := $(INSTALL_RULE)
+DEFAULT_INSTALL_RULE := $(INSTALL_RULE)
 override define INSTALL_RULE
        $(DEFAULT_INSTALL_RULE)
        $(MAKE) -C ebb install
index 1b616fa79e93947987fa0093e8f73d1428205fd2..6bff955e1d55ac6cccb526f5a00355ac4e904973 100644 (file)
@@ -1,4 +1,4 @@
-TEST_PROGS := tm-resched-dscr tm-syscall
+TEST_PROGS := tm-resched-dscr
 
 all: $(TEST_PROGS)
 
index ddf63569df5ae166e466901aa1a60e1b194fe508..9309097f58e8f94810c4a78b860b5e949f7c75c2 100644 (file)
@@ -1,6 +1,6 @@
 .PHONY: all all_32 all_64 check_build32 clean run_tests
 
-TARGETS_C_BOTHBITS := sigreturn single_step_syscall
+TARGETS_C_BOTHBITS := sigreturn single_step_syscall sysret_ss_attrs
 
 BINARIES_32 := $(TARGETS_C_BOTHBITS:%=%_32)
 BINARIES_64 := $(TARGETS_C_BOTHBITS:%=%_64)
@@ -46,3 +46,6 @@ check_build32:
          echo "  yum install glibc-devel.*i686";                       \
          exit 1;                                                       \
        fi
+
+# Some tests have additional dependencies.
+sysret_ss_attrs_64: thunks.S
index 3fc19b3768121ad0e3846297a17470b03d8fa4e7..d25034280dd51cd3132f78816502f05fbc535253 100644 (file)
@@ -4,10 +4,12 @@
 # script here.
 ./sigreturn_32 || exit 1
 ./single_step_syscall_32 || exit 1
+./sysret_ss_attrs_32 || exit 1
 
 if [[ "$uname -p" -eq "x86_64" ]]; then
     ./sigreturn_64 || exit 1
     ./single_step_syscall_64 || exit 1
+    ./sysret_ss_attrs_64 || exit 1
 fi
 
 exit 0
diff --git a/tools/testing/selftests/x86/sysret_ss_attrs.c b/tools/testing/selftests/x86/sysret_ss_attrs.c
new file mode 100644 (file)
index 0000000..ce42d5a
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * sysret_ss_attrs.c - test that syscalls return valid hidden SS attributes
+ * Copyright (c) 2015 Andrew Lutomirski
+ *
+ * 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.
+ *
+ * On AMD CPUs, SYSRET can return with a valid SS descriptor with with
+ * the hidden attributes set to an unusable state.  Make sure the kernel
+ * doesn't let this happen.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <err.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <pthread.h>
+
+static void *threadproc(void *ctx)
+{
+       /*
+        * Do our best to cause sleeps on this CPU to exit the kernel and
+        * re-enter with SS = 0.
+        */
+       while (true)
+               ;
+
+       return NULL;
+}
+
+#ifdef __x86_64__
+extern unsigned long call32_from_64(void *stack, void (*function)(void));
+
+asm (".pushsection .text\n\t"
+     ".code32\n\t"
+     "test_ss:\n\t"
+     "pushl $0\n\t"
+     "popl %eax\n\t"
+     "ret\n\t"
+     ".code64");
+extern void test_ss(void);
+#endif
+
+int main()
+{
+       /*
+        * Start a busy-looping thread on the same CPU we're on.
+        * For simplicity, just stick everything to CPU 0.  This will
+        * fail in some containers, but that's probably okay.
+        */
+       cpu_set_t cpuset;
+       CPU_ZERO(&cpuset);
+       CPU_SET(0, &cpuset);
+       if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0)
+               printf("[WARN]\tsched_setaffinity failed\n");
+
+       pthread_t thread;
+       if (pthread_create(&thread, 0, threadproc, 0) != 0)
+               err(1, "pthread_create");
+
+#ifdef __x86_64__
+       unsigned char *stack32 = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
+                                     MAP_32BIT | MAP_ANONYMOUS | MAP_PRIVATE,
+                                     -1, 0);
+       if (stack32 == MAP_FAILED)
+               err(1, "mmap");
+#endif
+
+       printf("[RUN]\tSyscalls followed by SS validation\n");
+
+       for (int i = 0; i < 1000; i++) {
+               /*
+                * Go to sleep and return using sysret (if we're 64-bit
+                * or we're 32-bit on AMD on a 64-bit kernel).  On AMD CPUs,
+                * SYSRET doesn't fix up the cached SS descriptor, so the
+                * kernel needs some kind of workaround to make sure that we
+                * end the system call with a valid stack segment.  This
+                * can be a confusing failure because the SS *selector*
+                * is the same regardless.
+                */
+               usleep(2);
+
+#ifdef __x86_64__
+               /*
+                * On 32-bit, just doing a syscall through glibc is enough
+                * to cause a crash if our cached SS descriptor is invalid.
+                * On 64-bit, it's not, so try extra hard.
+                */
+               call32_from_64(stack32 + 4088, test_ss);
+#endif
+       }
+
+       printf("[OK]\tWe survived\n");
+
+#ifdef __x86_64__
+       munmap(stack32, 4096);
+#endif
+
+       return 0;
+}
diff --git a/tools/testing/selftests/x86/thunks.S b/tools/testing/selftests/x86/thunks.S
new file mode 100644 (file)
index 0000000..ce8a995
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * thunks.S - assembly helpers for mixed-bitness code
+ * Copyright (c) 2015 Andrew Lutomirski
+ *
+ * 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.
+ *
+ * These are little helpers that make it easier to switch bitness on
+ * the fly.
+ */
+
+       .text
+
+       .global call32_from_64
+       .type call32_from_64, @function
+call32_from_64:
+       // rdi: stack to use
+       // esi: function to call
+
+       // Save registers
+       pushq %rbx
+       pushq %rbp
+       pushq %r12
+       pushq %r13
+       pushq %r14
+       pushq %r15
+       pushfq
+
+       // Switch stacks
+       mov %rsp,(%rdi)
+       mov %rdi,%rsp
+
+       // Switch to compatibility mode
+       pushq $0x23  /* USER32_CS */
+       pushq $1f
+       lretq
+
+1:
+       .code32
+       // Call the function
+       call *%esi
+       // Switch back to long mode
+       jmp $0x33,$1f
+       .code64
+
+1:
+       // Restore the stack
+       mov (%rsp),%rsp
+
+       // Restore registers
+       popfq
+       popq %r15
+       popq %r14
+       popq %r13
+       popq %r12
+       popq %rbp
+       popq %rbx
+
+       ret
+
+.size call32_from_64, .-call32_from_64
index 8d550ff14700c8a628b9c2c6ab55301f6bd0e92b..78fb8201014f74f2172baf8a48acc5173a450f4d 100644 (file)
@@ -1561,6 +1561,9 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
                        goto out;
        }
 
+       if (irq_num >= kvm->arch.vgic.nr_irqs)
+               return -EINVAL;
+
        vcpu_id = vgic_update_irq_pending(kvm, cpuid, irq_num, level);
        if (vcpu_id >= 0) {
                /* kick the specified vcpu */
@@ -2141,7 +2144,7 @@ int kvm_irq_map_gsi(struct kvm *kvm,
                    struct kvm_kernel_irq_routing_entry *entries,
                    int gsi)
 {
-       return gsi;
+       return 0;
 }
 
 int kvm_irq_map_chip_pin(struct kvm *kvm, unsigned irqchip, unsigned pin)
index d3fc9399062a5034b99eaa3d12c855699fdbf608..90977418aeb6edfbf274c2260b48296638fd0762 100644 (file)
@@ -89,6 +89,7 @@ EXPORT_SYMBOL_GPL(kvm_vcpu_cache);
 static __read_mostly struct preempt_ops kvm_preempt_ops;
 
 struct dentry *kvm_debugfs_dir;
+EXPORT_SYMBOL_GPL(kvm_debugfs_dir);
 
 static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl,
                           unsigned long arg);